* [PATCH v2 00/15] drm: starfive: jh7110: Enable display subsystem
[not found] <CGME20260828134813eucas1p1bd003a66706ed251017185fc14f13cc9@eucas1p1.samsung.com>
2026-08-28 13:47 ` Michal Wilczynski
(?)
@ 2026-08-28 13:47 ` Michal Wilczynski
0 siblings, 0 replies; 116+ messages in thread
From: Michal Wilczynski @ 2026-08-28 13:47 UTC (permalink / raw)
To: Vinod Koul, Neil Armstrong, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Andrzej Hajda, Robert Foss, Laurent Pinchart,
Jonas Karlman, Jernej Skrabec, Luca Ceresoli, David Airlie,
Simona Vetter, Maarten Lankhorst, Maxime Ripard,
Thomas Zimmermann, Lee Jones, Andy Yan, Philipp Zabel,
Emil Renner Berthing, Hal Feng, Michael Turquette, Stephen Boyd,
Brian Masney, Heiko Stuebner, Conor Dooley, Paul Walmsley,
Palmer Dabbelt, Albert Ou, Alexandre Ghiti, Dominique Belhachemi
Cc: linux-phy, devicetree, linux-kernel, dri-devel, mfd, linux-clk,
linux-arm-kernel, linux-rockchip, linux-riscv, Icenowy Zheng,
Andy Yan, Marek Szyprowski, Maud Spierings, Graham Markall,
Michal Wilczynski
This series enables the display subsystem on the StarFive JH7110.
The dom_vout block holds the display controller (dc8200), the clock
generator (voutcrg) and the HDMI IP, all inside PD_VOUT. The HDMI IP is
a single register block containing both the controller and the PHY, and
it has a circular clock dependency with voutcrg:
- the HDMI controller needs sys/mclk/bclk from voutcrg
- voutcrg needs the pixel clock for its dc8200 pixel MUXes, and that
clock is generated by the HDMI PHY
The loop only exists if the HDMI block is treated as one device. The
PHY's reference clock is xin24m, not a voutcrg output, so splitting the
node into a parent plus phy and controller children gives deferred probe
a linear order: hdmi-phy, then voutcrg, then hdmi-controller.
The parent maps the register block, owns the regmap its two children
share, and enables the NoC display bus clock and reset that gate the
whole vout region. Each node has its own power-domains property, so
genpd powers PD_VOUT on demand. The RFC's vout-subsystem wrapper is gone
along with the patch that relaxed the voutcrg binding.
Patch 7 adds a .mode_valid platform op to inno-hdmi.
inno_hdmi_bridge_mode_valid() checks the pixel clock against
hdmi->refclk, but that clock only exists where a "ref" clock is
described. The JH7110 gets its pixel clock from the PHY, so refclk is
NULL and the check was skipped: unsupported modes were advertised, the
modeset then "succeeded" because the atomic enable path cannot fail, and
the display stayed blank.
Patches 11-13 drop the PHY duplication from the RFC. The JH7110 has the
same Innosilicon PHY as the RK3328, offset by 0x100 because it sits
behind the controller in the shared register block. Patch 11 factors out
the pre-PLL config format, table lookup, determine_rate, recalc_rate and
the pre-PLL programming; patch 12 moves Rockchip onto it; patch 13 adds
the JH7110 driver. Pixel clock tables, post-PLL and analog config stay
SoC specific.
Patch 12 should be a no-op for Rockchip - same writes, same order, same
values - and RK3228, whose pre-PLL is at different addresses, keeps its
own register code and shares only the lookup. I have no Rockchip
hardware, so it is build tested only (arm and riscv). A Tested-by would
help.
The dc8200 driver, th1520 reset controller and inno-hdmi bridge that the
RFC listed as prerequisites are all upstream now, so there are no
out-of-tree dependencies.
Testing
=======
Tested on a VisionFive 2 v1.3B using modetest.
All 42 modes the sink advertises work, with nothing in dmesg. Pixel
clocks run from 25.175 MHz (640x480@59.94) up to 297 MHz
(4096x2160@30), including 3840x2160 and the full 1920x1080 and 1280x720
rate families.
The four modes the RFC reported as broken work now too: 2560x1440@59.95,
2048x1080@60.00, 2048x1080@24.00 and 720x400@70.08.
Before patch 7, four of the advertised modes failed: 1680x1050@59.95
(146.250 MHz), 1400x1050@59.98 (121.750), 1152x864@59.97 (81.768) and
1280x768@60.35 (80.140). Those pixel clocks are not in the PHY pre-PLL
table, so clk_set_rate() returned -EINVAL and the screen stayed black
while userspace saw a successful modeset. They are rejected in
.mode_valid now; the other refresh rates of those resolutions still work.
Every commit builds for riscv, and the Rockchip PHY also for arm.
Notes
=====
The JH7110 has no central MAINTAINERS entry and maintainership is
fragmented, so patch 15 adds one for the display subsystem and I am
happy to help maintain it. The new PHY library lives under drivers/phy/,
already covered by the generic PHY framework entry.
checkpatch warns "does MAINTAINERS need updating?" on the patches adding
files, because that entry comes in patch 15.
Changes since the RFC:
- Dropped the vout-subsystem wrapper driver and its binding, along with
the patch relaxing the voutcrg binding; genpd handles PD_VOUT per node.
- Renamed the compatible to starfive,jh7110-hdmi-subsystem, dropping
"mfd" as a Linux term (Conor Dooley).
- Absolute $refs in the bindings, unused example labels dropped, and the
examples deduplicated between parent and children (Conor Dooley).
- Added the .mode_valid platform operation (patch 7).
- Split the inno-hdmi rework into a mechanical probe/bind split (patch 4)
and the regmap-from-parent change (patch 5). struct inno_hdmi is no
longer exported; no platform glue dereferences it.
- Replaced the duplicated PHY driver with a shared Innosilicon library
and moved Rockchip onto it (patches 11-13).
- Fixed pre-PLL lock detection, which masked the status read with the
register address instead of the lock bit.
- Fixed a pixel clock refcount underflow: enable returns early on
failure while disable tore down unconditionally.
- voutcrg patch reduced to adding CLK_SET_RATE_PARENT to the two dc8200
pixel MUXes.
- Rebased onto v7.2.
Thanks to Icenowy Zheng for the dc8200 driver and for explaining how the
SoC and the display pipeline fit together.
Thanks also to Dominique Belhachemi, who got rid of the vout-subsystem
wrapper and helped with the testing, and to Graham Markall for testing
the JH7110 display patches independently and writing up the results:
https://big-grey.co.uk/2026/01/26/testing-starfive-jh7110-display-controller-patches/
Link to v1: https://lore.kernel.org/all/20251108-jh7110-clean-send-v1-0-06bf43bb76b1@samsung.com/
---
Michal Wilczynski (15):
dt-bindings: phy: Add starfive,jh7110-inno-hdmi-phy
dt-bindings: display: bridge: Add starfive,jh7110-inno-hdmi-controller
dt-bindings: mfd: Add starfive,jh7110-hdmi-subsystem
drm/bridge: inno-hdmi: Split probe out of bind
drm/bridge: inno-hdmi: Allow the register map to come from a parent
drm/bridge: inno-hdmi: Add .disable platform operation
drm/bridge: inno-hdmi: Add .mode_valid platform operation
soc: starfive: Add jh7110-hdmi-subsystem driver
clk: starfive: jh7110-vout: Allow pixel clock rate propagation
drm/bridge: starfive: Add JH7110 HDMI controller driver
phy: Add common Innosilicon HDMI PHY helpers
phy: rockchip: inno-hdmi: Use the common Innosilicon PHY helpers
phy: starfive: Add jh7110-inno-hdmi-phy driver
riscv: dts: starfive: jh7110: Update DT for display subsystem
MAINTAINERS: Add StarFive JH7110 display subsystem entry
.../starfive,jh7110-inno-hdmi-controller.yaml | 109 ++++
.../mfd/starfive,jh7110-hdmi-subsystem.yaml | 116 +++++
.../phy/starfive,jh7110-inno-hdmi-phy.yaml | 58 +++
MAINTAINERS | 10 +
arch/riscv/boot/dts/starfive/jh7110-common.dtsi | 119 ++++-
arch/riscv/boot/dts/starfive/jh7110.dtsi | 87 +++-
drivers/clk/starfive/clk-starfive-jh7110-vout.c | 4 +-
drivers/gpu/drm/bridge/Kconfig | 11 +
drivers/gpu/drm/bridge/Makefile | 1 +
drivers/gpu/drm/bridge/inno-hdmi.c | 82 ++-
drivers/gpu/drm/bridge/jh7110-inno-hdmi.c | 224 ++++++++
drivers/phy/Kconfig | 8 +
drivers/phy/Makefile | 1 +
drivers/phy/phy-inno-hdmi.c | 297 +++++++++++
drivers/phy/rockchip/Kconfig | 1 +
drivers/phy/rockchip/phy-rockchip-inno-hdmi.c | 127 +----
drivers/phy/starfive/Kconfig | 20 +
drivers/phy/starfive/Makefile | 1 +
drivers/phy/starfive/phy-jh7110-inno-hdmi.c | 567 +++++++++++++++++++++
drivers/soc/Kconfig | 1 +
drivers/soc/Makefile | 1 +
drivers/soc/starfive/Kconfig | 27 +
drivers/soc/starfive/Makefile | 2 +
drivers/soc/starfive/jh7110-hdmi-subsystem.c | 114 +++++
include/drm/bridge/inno_hdmi.h | 10 +-
include/linux/phy/inno-hdmi-phy.h | 85 +++
26 files changed, 1959 insertions(+), 124 deletions(-)
---
base-commit: 8d3ae59288f1e7d58d76558a6ee96d533bc5019f
change-id: 20251031-jh7110-clean-send-7d2242118026
Best regards,
--
Michal Wilczynski <m.wilczynski@samsung.com>
^ permalink raw reply [flat|nested] 116+ messages in thread
* [PATCH v2 00/15] drm: starfive: jh7110: Enable display subsystem
@ 2026-08-28 13:47 ` Michal Wilczynski
0 siblings, 0 replies; 116+ messages in thread
From: Michal Wilczynski @ 2026-08-28 13:47 UTC (permalink / raw)
To: Vinod Koul, Neil Armstrong, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Andrzej Hajda, Robert Foss, Laurent Pinchart,
Jonas Karlman, Jernej Skrabec, Luca Ceresoli, David Airlie,
Simona Vetter, Maarten Lankhorst, Maxime Ripard,
Thomas Zimmermann, Lee Jones, Andy Yan, Philipp Zabel,
Emil Renner Berthing, Hal Feng, Michael Turquette, Stephen Boyd,
Brian Masney, Heiko Stuebner, Conor Dooley, Paul Walmsley,
Palmer Dabbelt, Albert Ou, Alexandre Ghiti, Dominique Belhachemi
Cc: devicetree, mfd, linux-kernel, dri-devel, Andy Yan,
Graham Markall, linux-rockchip, linux-phy, Michal Wilczynski,
linux-riscv, Maud Spierings, linux-clk, linux-arm-kernel,
Marek Szyprowski
This series enables the display subsystem on the StarFive JH7110.
The dom_vout block holds the display controller (dc8200), the clock
generator (voutcrg) and the HDMI IP, all inside PD_VOUT. The HDMI IP is
a single register block containing both the controller and the PHY, and
it has a circular clock dependency with voutcrg:
- the HDMI controller needs sys/mclk/bclk from voutcrg
- voutcrg needs the pixel clock for its dc8200 pixel MUXes, and that
clock is generated by the HDMI PHY
The loop only exists if the HDMI block is treated as one device. The
PHY's reference clock is xin24m, not a voutcrg output, so splitting the
node into a parent plus phy and controller children gives deferred probe
a linear order: hdmi-phy, then voutcrg, then hdmi-controller.
The parent maps the register block, owns the regmap its two children
share, and enables the NoC display bus clock and reset that gate the
whole vout region. Each node has its own power-domains property, so
genpd powers PD_VOUT on demand. The RFC's vout-subsystem wrapper is gone
along with the patch that relaxed the voutcrg binding.
Patch 7 adds a .mode_valid platform op to inno-hdmi.
inno_hdmi_bridge_mode_valid() checks the pixel clock against
hdmi->refclk, but that clock only exists where a "ref" clock is
described. The JH7110 gets its pixel clock from the PHY, so refclk is
NULL and the check was skipped: unsupported modes were advertised, the
modeset then "succeeded" because the atomic enable path cannot fail, and
the display stayed blank.
Patches 11-13 drop the PHY duplication from the RFC. The JH7110 has the
same Innosilicon PHY as the RK3328, offset by 0x100 because it sits
behind the controller in the shared register block. Patch 11 factors out
the pre-PLL config format, table lookup, determine_rate, recalc_rate and
the pre-PLL programming; patch 12 moves Rockchip onto it; patch 13 adds
the JH7110 driver. Pixel clock tables, post-PLL and analog config stay
SoC specific.
Patch 12 should be a no-op for Rockchip - same writes, same order, same
values - and RK3228, whose pre-PLL is at different addresses, keeps its
own register code and shares only the lookup. I have no Rockchip
hardware, so it is build tested only (arm and riscv). A Tested-by would
help.
The dc8200 driver, th1520 reset controller and inno-hdmi bridge that the
RFC listed as prerequisites are all upstream now, so there are no
out-of-tree dependencies.
Testing
=======
Tested on a VisionFive 2 v1.3B using modetest.
All 42 modes the sink advertises work, with nothing in dmesg. Pixel
clocks run from 25.175 MHz (640x480@59.94) up to 297 MHz
(4096x2160@30), including 3840x2160 and the full 1920x1080 and 1280x720
rate families.
The four modes the RFC reported as broken work now too: 2560x1440@59.95,
2048x1080@60.00, 2048x1080@24.00 and 720x400@70.08.
Before patch 7, four of the advertised modes failed: 1680x1050@59.95
(146.250 MHz), 1400x1050@59.98 (121.750), 1152x864@59.97 (81.768) and
1280x768@60.35 (80.140). Those pixel clocks are not in the PHY pre-PLL
table, so clk_set_rate() returned -EINVAL and the screen stayed black
while userspace saw a successful modeset. They are rejected in
.mode_valid now; the other refresh rates of those resolutions still work.
Every commit builds for riscv, and the Rockchip PHY also for arm.
Notes
=====
The JH7110 has no central MAINTAINERS entry and maintainership is
fragmented, so patch 15 adds one for the display subsystem and I am
happy to help maintain it. The new PHY library lives under drivers/phy/,
already covered by the generic PHY framework entry.
checkpatch warns "does MAINTAINERS need updating?" on the patches adding
files, because that entry comes in patch 15.
Changes since the RFC:
- Dropped the vout-subsystem wrapper driver and its binding, along with
the patch relaxing the voutcrg binding; genpd handles PD_VOUT per node.
- Renamed the compatible to starfive,jh7110-hdmi-subsystem, dropping
"mfd" as a Linux term (Conor Dooley).
- Absolute $refs in the bindings, unused example labels dropped, and the
examples deduplicated between parent and children (Conor Dooley).
- Added the .mode_valid platform operation (patch 7).
- Split the inno-hdmi rework into a mechanical probe/bind split (patch 4)
and the regmap-from-parent change (patch 5). struct inno_hdmi is no
longer exported; no platform glue dereferences it.
- Replaced the duplicated PHY driver with a shared Innosilicon library
and moved Rockchip onto it (patches 11-13).
- Fixed pre-PLL lock detection, which masked the status read with the
register address instead of the lock bit.
- Fixed a pixel clock refcount underflow: enable returns early on
failure while disable tore down unconditionally.
- voutcrg patch reduced to adding CLK_SET_RATE_PARENT to the two dc8200
pixel MUXes.
- Rebased onto v7.2.
Thanks to Icenowy Zheng for the dc8200 driver and for explaining how the
SoC and the display pipeline fit together.
Thanks also to Dominique Belhachemi, who got rid of the vout-subsystem
wrapper and helped with the testing, and to Graham Markall for testing
the JH7110 display patches independently and writing up the results:
https://big-grey.co.uk/2026/01/26/testing-starfive-jh7110-display-controller-patches/
Link to v1: https://lore.kernel.org/all/20251108-jh7110-clean-send-v1-0-06bf43bb76b1@samsung.com/
---
Michal Wilczynski (15):
dt-bindings: phy: Add starfive,jh7110-inno-hdmi-phy
dt-bindings: display: bridge: Add starfive,jh7110-inno-hdmi-controller
dt-bindings: mfd: Add starfive,jh7110-hdmi-subsystem
drm/bridge: inno-hdmi: Split probe out of bind
drm/bridge: inno-hdmi: Allow the register map to come from a parent
drm/bridge: inno-hdmi: Add .disable platform operation
drm/bridge: inno-hdmi: Add .mode_valid platform operation
soc: starfive: Add jh7110-hdmi-subsystem driver
clk: starfive: jh7110-vout: Allow pixel clock rate propagation
drm/bridge: starfive: Add JH7110 HDMI controller driver
phy: Add common Innosilicon HDMI PHY helpers
phy: rockchip: inno-hdmi: Use the common Innosilicon PHY helpers
phy: starfive: Add jh7110-inno-hdmi-phy driver
riscv: dts: starfive: jh7110: Update DT for display subsystem
MAINTAINERS: Add StarFive JH7110 display subsystem entry
.../starfive,jh7110-inno-hdmi-controller.yaml | 109 ++++
.../mfd/starfive,jh7110-hdmi-subsystem.yaml | 116 +++++
.../phy/starfive,jh7110-inno-hdmi-phy.yaml | 58 +++
MAINTAINERS | 10 +
arch/riscv/boot/dts/starfive/jh7110-common.dtsi | 119 ++++-
arch/riscv/boot/dts/starfive/jh7110.dtsi | 87 +++-
drivers/clk/starfive/clk-starfive-jh7110-vout.c | 4 +-
drivers/gpu/drm/bridge/Kconfig | 11 +
drivers/gpu/drm/bridge/Makefile | 1 +
drivers/gpu/drm/bridge/inno-hdmi.c | 82 ++-
drivers/gpu/drm/bridge/jh7110-inno-hdmi.c | 224 ++++++++
drivers/phy/Kconfig | 8 +
drivers/phy/Makefile | 1 +
drivers/phy/phy-inno-hdmi.c | 297 +++++++++++
drivers/phy/rockchip/Kconfig | 1 +
drivers/phy/rockchip/phy-rockchip-inno-hdmi.c | 127 +----
drivers/phy/starfive/Kconfig | 20 +
drivers/phy/starfive/Makefile | 1 +
drivers/phy/starfive/phy-jh7110-inno-hdmi.c | 567 +++++++++++++++++++++
drivers/soc/Kconfig | 1 +
drivers/soc/Makefile | 1 +
drivers/soc/starfive/Kconfig | 27 +
drivers/soc/starfive/Makefile | 2 +
drivers/soc/starfive/jh7110-hdmi-subsystem.c | 114 +++++
include/drm/bridge/inno_hdmi.h | 10 +-
include/linux/phy/inno-hdmi-phy.h | 85 +++
26 files changed, 1959 insertions(+), 124 deletions(-)
---
base-commit: 8d3ae59288f1e7d58d76558a6ee96d533bc5019f
change-id: 20251031-jh7110-clean-send-7d2242118026
Best regards,
--
Michal Wilczynski <m.wilczynski@samsung.com>
_______________________________________________
linux-riscv mailing list
linux-riscv@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-riscv
^ permalink raw reply [flat|nested] 116+ messages in thread
* [PATCH v2 00/15] drm: starfive: jh7110: Enable display subsystem
@ 2026-08-28 13:47 ` Michal Wilczynski
0 siblings, 0 replies; 116+ messages in thread
From: Michal Wilczynski @ 2026-08-28 13:47 UTC (permalink / raw)
To: Vinod Koul, Neil Armstrong, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Andrzej Hajda, Robert Foss, Laurent Pinchart,
Jonas Karlman, Jernej Skrabec, Luca Ceresoli, David Airlie,
Simona Vetter, Maarten Lankhorst, Maxime Ripard,
Thomas Zimmermann, Lee Jones, Andy Yan, Philipp Zabel,
Emil Renner Berthing, Hal Feng, Michael Turquette, Stephen Boyd,
Brian Masney, Heiko Stuebner, Conor Dooley, Paul Walmsley,
Palmer Dabbelt, Albert Ou, Alexandre Ghiti, Dominique Belhachemi
Cc: linux-phy, devicetree, linux-kernel, dri-devel, mfd, linux-clk,
linux-arm-kernel, linux-rockchip, linux-riscv, Icenowy Zheng,
Andy Yan, Marek Szyprowski, Maud Spierings, Graham Markall,
Michal Wilczynski
This series enables the display subsystem on the StarFive JH7110.
The dom_vout block holds the display controller (dc8200), the clock
generator (voutcrg) and the HDMI IP, all inside PD_VOUT. The HDMI IP is
a single register block containing both the controller and the PHY, and
it has a circular clock dependency with voutcrg:
- the HDMI controller needs sys/mclk/bclk from voutcrg
- voutcrg needs the pixel clock for its dc8200 pixel MUXes, and that
clock is generated by the HDMI PHY
The loop only exists if the HDMI block is treated as one device. The
PHY's reference clock is xin24m, not a voutcrg output, so splitting the
node into a parent plus phy and controller children gives deferred probe
a linear order: hdmi-phy, then voutcrg, then hdmi-controller.
The parent maps the register block, owns the regmap its two children
share, and enables the NoC display bus clock and reset that gate the
whole vout region. Each node has its own power-domains property, so
genpd powers PD_VOUT on demand. The RFC's vout-subsystem wrapper is gone
along with the patch that relaxed the voutcrg binding.
Patch 7 adds a .mode_valid platform op to inno-hdmi.
inno_hdmi_bridge_mode_valid() checks the pixel clock against
hdmi->refclk, but that clock only exists where a "ref" clock is
described. The JH7110 gets its pixel clock from the PHY, so refclk is
NULL and the check was skipped: unsupported modes were advertised, the
modeset then "succeeded" because the atomic enable path cannot fail, and
the display stayed blank.
Patches 11-13 drop the PHY duplication from the RFC. The JH7110 has the
same Innosilicon PHY as the RK3328, offset by 0x100 because it sits
behind the controller in the shared register block. Patch 11 factors out
the pre-PLL config format, table lookup, determine_rate, recalc_rate and
the pre-PLL programming; patch 12 moves Rockchip onto it; patch 13 adds
the JH7110 driver. Pixel clock tables, post-PLL and analog config stay
SoC specific.
Patch 12 should be a no-op for Rockchip - same writes, same order, same
values - and RK3228, whose pre-PLL is at different addresses, keeps its
own register code and shares only the lookup. I have no Rockchip
hardware, so it is build tested only (arm and riscv). A Tested-by would
help.
The dc8200 driver, th1520 reset controller and inno-hdmi bridge that the
RFC listed as prerequisites are all upstream now, so there are no
out-of-tree dependencies.
Testing
=======
Tested on a VisionFive 2 v1.3B using modetest.
All 42 modes the sink advertises work, with nothing in dmesg. Pixel
clocks run from 25.175 MHz (640x480@59.94) up to 297 MHz
(4096x2160@30), including 3840x2160 and the full 1920x1080 and 1280x720
rate families.
The four modes the RFC reported as broken work now too: 2560x1440@59.95,
2048x1080@60.00, 2048x1080@24.00 and 720x400@70.08.
Before patch 7, four of the advertised modes failed: 1680x1050@59.95
(146.250 MHz), 1400x1050@59.98 (121.750), 1152x864@59.97 (81.768) and
1280x768@60.35 (80.140). Those pixel clocks are not in the PHY pre-PLL
table, so clk_set_rate() returned -EINVAL and the screen stayed black
while userspace saw a successful modeset. They are rejected in
.mode_valid now; the other refresh rates of those resolutions still work.
Every commit builds for riscv, and the Rockchip PHY also for arm.
Notes
=====
The JH7110 has no central MAINTAINERS entry and maintainership is
fragmented, so patch 15 adds one for the display subsystem and I am
happy to help maintain it. The new PHY library lives under drivers/phy/,
already covered by the generic PHY framework entry.
checkpatch warns "does MAINTAINERS need updating?" on the patches adding
files, because that entry comes in patch 15.
Changes since the RFC:
- Dropped the vout-subsystem wrapper driver and its binding, along with
the patch relaxing the voutcrg binding; genpd handles PD_VOUT per node.
- Renamed the compatible to starfive,jh7110-hdmi-subsystem, dropping
"mfd" as a Linux term (Conor Dooley).
- Absolute $refs in the bindings, unused example labels dropped, and the
examples deduplicated between parent and children (Conor Dooley).
- Added the .mode_valid platform operation (patch 7).
- Split the inno-hdmi rework into a mechanical probe/bind split (patch 4)
and the regmap-from-parent change (patch 5). struct inno_hdmi is no
longer exported; no platform glue dereferences it.
- Replaced the duplicated PHY driver with a shared Innosilicon library
and moved Rockchip onto it (patches 11-13).
- Fixed pre-PLL lock detection, which masked the status read with the
register address instead of the lock bit.
- Fixed a pixel clock refcount underflow: enable returns early on
failure while disable tore down unconditionally.
- voutcrg patch reduced to adding CLK_SET_RATE_PARENT to the two dc8200
pixel MUXes.
- Rebased onto v7.2.
Thanks to Icenowy Zheng for the dc8200 driver and for explaining how the
SoC and the display pipeline fit together.
Thanks also to Dominique Belhachemi, who got rid of the vout-subsystem
wrapper and helped with the testing, and to Graham Markall for testing
the JH7110 display patches independently and writing up the results:
https://big-grey.co.uk/2026/01/26/testing-starfive-jh7110-display-controller-patches/
Link to v1: https://lore.kernel.org/all/20251108-jh7110-clean-send-v1-0-06bf43bb76b1@samsung.com/
---
Michal Wilczynski (15):
dt-bindings: phy: Add starfive,jh7110-inno-hdmi-phy
dt-bindings: display: bridge: Add starfive,jh7110-inno-hdmi-controller
dt-bindings: mfd: Add starfive,jh7110-hdmi-subsystem
drm/bridge: inno-hdmi: Split probe out of bind
drm/bridge: inno-hdmi: Allow the register map to come from a parent
drm/bridge: inno-hdmi: Add .disable platform operation
drm/bridge: inno-hdmi: Add .mode_valid platform operation
soc: starfive: Add jh7110-hdmi-subsystem driver
clk: starfive: jh7110-vout: Allow pixel clock rate propagation
drm/bridge: starfive: Add JH7110 HDMI controller driver
phy: Add common Innosilicon HDMI PHY helpers
phy: rockchip: inno-hdmi: Use the common Innosilicon PHY helpers
phy: starfive: Add jh7110-inno-hdmi-phy driver
riscv: dts: starfive: jh7110: Update DT for display subsystem
MAINTAINERS: Add StarFive JH7110 display subsystem entry
.../starfive,jh7110-inno-hdmi-controller.yaml | 109 ++++
.../mfd/starfive,jh7110-hdmi-subsystem.yaml | 116 +++++
.../phy/starfive,jh7110-inno-hdmi-phy.yaml | 58 +++
MAINTAINERS | 10 +
arch/riscv/boot/dts/starfive/jh7110-common.dtsi | 119 ++++-
arch/riscv/boot/dts/starfive/jh7110.dtsi | 87 +++-
drivers/clk/starfive/clk-starfive-jh7110-vout.c | 4 +-
drivers/gpu/drm/bridge/Kconfig | 11 +
drivers/gpu/drm/bridge/Makefile | 1 +
drivers/gpu/drm/bridge/inno-hdmi.c | 82 ++-
drivers/gpu/drm/bridge/jh7110-inno-hdmi.c | 224 ++++++++
drivers/phy/Kconfig | 8 +
drivers/phy/Makefile | 1 +
drivers/phy/phy-inno-hdmi.c | 297 +++++++++++
drivers/phy/rockchip/Kconfig | 1 +
drivers/phy/rockchip/phy-rockchip-inno-hdmi.c | 127 +----
drivers/phy/starfive/Kconfig | 20 +
drivers/phy/starfive/Makefile | 1 +
drivers/phy/starfive/phy-jh7110-inno-hdmi.c | 567 +++++++++++++++++++++
drivers/soc/Kconfig | 1 +
drivers/soc/Makefile | 1 +
drivers/soc/starfive/Kconfig | 27 +
drivers/soc/starfive/Makefile | 2 +
drivers/soc/starfive/jh7110-hdmi-subsystem.c | 114 +++++
include/drm/bridge/inno_hdmi.h | 10 +-
include/linux/phy/inno-hdmi-phy.h | 85 +++
26 files changed, 1959 insertions(+), 124 deletions(-)
---
base-commit: 8d3ae59288f1e7d58d76558a6ee96d533bc5019f
change-id: 20251031-jh7110-clean-send-7d2242118026
Best regards,
--
Michal Wilczynski <m.wilczynski@samsung.com>
_______________________________________________
Linux-rockchip mailing list
Linux-rockchip@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-rockchip
^ permalink raw reply [flat|nested] 116+ messages in thread
* [PATCH v2 00/15] drm: starfive: jh7110: Enable display subsystem
@ 2026-08-28 13:47 ` Michal Wilczynski
0 siblings, 0 replies; 116+ messages in thread
From: Michal Wilczynski @ 2026-08-28 13:47 UTC (permalink / raw)
To: Vinod Koul, Neil Armstrong, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Andrzej Hajda, Robert Foss, Laurent Pinchart,
Jonas Karlman, Jernej Skrabec, Luca Ceresoli, David Airlie,
Simona Vetter, Maarten Lankhorst, Maxime Ripard,
Thomas Zimmermann, Lee Jones, Andy Yan, Philipp Zabel,
Emil Renner Berthing, Hal Feng, Michael Turquette, Stephen Boyd,
Brian Masney, Heiko Stuebner, Conor Dooley, Paul Walmsley,
Palmer Dabbelt, Albert Ou, Alexandre Ghiti, Dominique Belhachemi
Cc: linux-phy, devicetree, linux-kernel, dri-devel, mfd, linux-clk,
linux-arm-kernel, linux-rockchip, linux-riscv, Icenowy Zheng,
Andy Yan, Marek Szyprowski, Maud Spierings, Graham Markall,
Michal Wilczynski
This series enables the display subsystem on the StarFive JH7110.
The dom_vout block holds the display controller (dc8200), the clock
generator (voutcrg) and the HDMI IP, all inside PD_VOUT. The HDMI IP is
a single register block containing both the controller and the PHY, and
it has a circular clock dependency with voutcrg:
- the HDMI controller needs sys/mclk/bclk from voutcrg
- voutcrg needs the pixel clock for its dc8200 pixel MUXes, and that
clock is generated by the HDMI PHY
The loop only exists if the HDMI block is treated as one device. The
PHY's reference clock is xin24m, not a voutcrg output, so splitting the
node into a parent plus phy and controller children gives deferred probe
a linear order: hdmi-phy, then voutcrg, then hdmi-controller.
The parent maps the register block, owns the regmap its two children
share, and enables the NoC display bus clock and reset that gate the
whole vout region. Each node has its own power-domains property, so
genpd powers PD_VOUT on demand. The RFC's vout-subsystem wrapper is gone
along with the patch that relaxed the voutcrg binding.
Patch 7 adds a .mode_valid platform op to inno-hdmi.
inno_hdmi_bridge_mode_valid() checks the pixel clock against
hdmi->refclk, but that clock only exists where a "ref" clock is
described. The JH7110 gets its pixel clock from the PHY, so refclk is
NULL and the check was skipped: unsupported modes were advertised, the
modeset then "succeeded" because the atomic enable path cannot fail, and
the display stayed blank.
Patches 11-13 drop the PHY duplication from the RFC. The JH7110 has the
same Innosilicon PHY as the RK3328, offset by 0x100 because it sits
behind the controller in the shared register block. Patch 11 factors out
the pre-PLL config format, table lookup, determine_rate, recalc_rate and
the pre-PLL programming; patch 12 moves Rockchip onto it; patch 13 adds
the JH7110 driver. Pixel clock tables, post-PLL and analog config stay
SoC specific.
Patch 12 should be a no-op for Rockchip - same writes, same order, same
values - and RK3228, whose pre-PLL is at different addresses, keeps its
own register code and shares only the lookup. I have no Rockchip
hardware, so it is build tested only (arm and riscv). A Tested-by would
help.
The dc8200 driver, th1520 reset controller and inno-hdmi bridge that the
RFC listed as prerequisites are all upstream now, so there are no
out-of-tree dependencies.
Testing
=======
Tested on a VisionFive 2 v1.3B using modetest.
All 42 modes the sink advertises work, with nothing in dmesg. Pixel
clocks run from 25.175 MHz (640x480@59.94) up to 297 MHz
(4096x2160@30), including 3840x2160 and the full 1920x1080 and 1280x720
rate families.
The four modes the RFC reported as broken work now too: 2560x1440@59.95,
2048x1080@60.00, 2048x1080@24.00 and 720x400@70.08.
Before patch 7, four of the advertised modes failed: 1680x1050@59.95
(146.250 MHz), 1400x1050@59.98 (121.750), 1152x864@59.97 (81.768) and
1280x768@60.35 (80.140). Those pixel clocks are not in the PHY pre-PLL
table, so clk_set_rate() returned -EINVAL and the screen stayed black
while userspace saw a successful modeset. They are rejected in
.mode_valid now; the other refresh rates of those resolutions still work.
Every commit builds for riscv, and the Rockchip PHY also for arm.
Notes
=====
The JH7110 has no central MAINTAINERS entry and maintainership is
fragmented, so patch 15 adds one for the display subsystem and I am
happy to help maintain it. The new PHY library lives under drivers/phy/,
already covered by the generic PHY framework entry.
checkpatch warns "does MAINTAINERS need updating?" on the patches adding
files, because that entry comes in patch 15.
Changes since the RFC:
- Dropped the vout-subsystem wrapper driver and its binding, along with
the patch relaxing the voutcrg binding; genpd handles PD_VOUT per node.
- Renamed the compatible to starfive,jh7110-hdmi-subsystem, dropping
"mfd" as a Linux term (Conor Dooley).
- Absolute $refs in the bindings, unused example labels dropped, and the
examples deduplicated between parent and children (Conor Dooley).
- Added the .mode_valid platform operation (patch 7).
- Split the inno-hdmi rework into a mechanical probe/bind split (patch 4)
and the regmap-from-parent change (patch 5). struct inno_hdmi is no
longer exported; no platform glue dereferences it.
- Replaced the duplicated PHY driver with a shared Innosilicon library
and moved Rockchip onto it (patches 11-13).
- Fixed pre-PLL lock detection, which masked the status read with the
register address instead of the lock bit.
- Fixed a pixel clock refcount underflow: enable returns early on
failure while disable tore down unconditionally.
- voutcrg patch reduced to adding CLK_SET_RATE_PARENT to the two dc8200
pixel MUXes.
- Rebased onto v7.2.
Thanks to Icenowy Zheng for the dc8200 driver and for explaining how the
SoC and the display pipeline fit together.
Thanks also to Dominique Belhachemi, who got rid of the vout-subsystem
wrapper and helped with the testing, and to Graham Markall for testing
the JH7110 display patches independently and writing up the results:
https://big-grey.co.uk/2026/01/26/testing-starfive-jh7110-display-controller-patches/
Link to v1: https://lore.kernel.org/all/20251108-jh7110-clean-send-v1-0-06bf43bb76b1@samsung.com/
---
Michal Wilczynski (15):
dt-bindings: phy: Add starfive,jh7110-inno-hdmi-phy
dt-bindings: display: bridge: Add starfive,jh7110-inno-hdmi-controller
dt-bindings: mfd: Add starfive,jh7110-hdmi-subsystem
drm/bridge: inno-hdmi: Split probe out of bind
drm/bridge: inno-hdmi: Allow the register map to come from a parent
drm/bridge: inno-hdmi: Add .disable platform operation
drm/bridge: inno-hdmi: Add .mode_valid platform operation
soc: starfive: Add jh7110-hdmi-subsystem driver
clk: starfive: jh7110-vout: Allow pixel clock rate propagation
drm/bridge: starfive: Add JH7110 HDMI controller driver
phy: Add common Innosilicon HDMI PHY helpers
phy: rockchip: inno-hdmi: Use the common Innosilicon PHY helpers
phy: starfive: Add jh7110-inno-hdmi-phy driver
riscv: dts: starfive: jh7110: Update DT for display subsystem
MAINTAINERS: Add StarFive JH7110 display subsystem entry
.../starfive,jh7110-inno-hdmi-controller.yaml | 109 ++++
.../mfd/starfive,jh7110-hdmi-subsystem.yaml | 116 +++++
.../phy/starfive,jh7110-inno-hdmi-phy.yaml | 58 +++
MAINTAINERS | 10 +
arch/riscv/boot/dts/starfive/jh7110-common.dtsi | 119 ++++-
arch/riscv/boot/dts/starfive/jh7110.dtsi | 87 +++-
drivers/clk/starfive/clk-starfive-jh7110-vout.c | 4 +-
drivers/gpu/drm/bridge/Kconfig | 11 +
drivers/gpu/drm/bridge/Makefile | 1 +
drivers/gpu/drm/bridge/inno-hdmi.c | 82 ++-
drivers/gpu/drm/bridge/jh7110-inno-hdmi.c | 224 ++++++++
drivers/phy/Kconfig | 8 +
drivers/phy/Makefile | 1 +
drivers/phy/phy-inno-hdmi.c | 297 +++++++++++
drivers/phy/rockchip/Kconfig | 1 +
drivers/phy/rockchip/phy-rockchip-inno-hdmi.c | 127 +----
drivers/phy/starfive/Kconfig | 20 +
drivers/phy/starfive/Makefile | 1 +
drivers/phy/starfive/phy-jh7110-inno-hdmi.c | 567 +++++++++++++++++++++
drivers/soc/Kconfig | 1 +
drivers/soc/Makefile | 1 +
drivers/soc/starfive/Kconfig | 27 +
drivers/soc/starfive/Makefile | 2 +
drivers/soc/starfive/jh7110-hdmi-subsystem.c | 114 +++++
include/drm/bridge/inno_hdmi.h | 10 +-
include/linux/phy/inno-hdmi-phy.h | 85 +++
26 files changed, 1959 insertions(+), 124 deletions(-)
---
base-commit: 8d3ae59288f1e7d58d76558a6ee96d533bc5019f
change-id: 20251031-jh7110-clean-send-7d2242118026
Best regards,
--
Michal Wilczynski <m.wilczynski@samsung.com>
--
linux-phy mailing list
linux-phy@lists.infradead.org
https://lists.infradead.org/mailman/listinfo/linux-phy
^ permalink raw reply [flat|nested] 116+ messages in thread
* [PATCH v2 01/15] dt-bindings: phy: Add starfive,jh7110-inno-hdmi-phy
2026-08-28 13:47 ` Michal Wilczynski
(?)
(?)
@ 2026-08-28 13:47 ` Michal Wilczynski
-1 siblings, 0 replies; 116+ messages in thread
From: Michal Wilczynski @ 2026-08-28 13:47 UTC (permalink / raw)
To: Vinod Koul, Neil Armstrong, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Andrzej Hajda, Robert Foss, Laurent Pinchart,
Jonas Karlman, Jernej Skrabec, Luca Ceresoli, David Airlie,
Simona Vetter, Maarten Lankhorst, Maxime Ripard,
Thomas Zimmermann, Lee Jones, Andy Yan, Philipp Zabel,
Emil Renner Berthing, Hal Feng, Michael Turquette, Stephen Boyd,
Brian Masney, Heiko Stuebner, Conor Dooley, Paul Walmsley,
Palmer Dabbelt, Albert Ou, Alexandre Ghiti, Dominique Belhachemi
Cc: linux-phy, devicetree, linux-kernel, dri-devel, mfd, linux-clk,
linux-arm-kernel, linux-rockchip, linux-riscv, Icenowy Zheng,
Andy Yan, Marek Szyprowski, Maud Spierings, Graham Markall,
Michal Wilczynski
Add the dt-binding for the StarFive JH7110 Innosilicon HDMI PHY.
This device is a child of the starfive,jh7110-hdmi-subsystem node. It
functions as both a PHY provider for the controller and as a clock
provider for the variable pixel clock (hdmi_pclk), which it generates
from its refoclk.
Signed-off-by: Michal Wilczynski <m.wilczynski@samsung.com>
---
.../phy/starfive,jh7110-inno-hdmi-phy.yaml | 58 ++++++++++++++++++++++
1 file changed, 58 insertions(+)
diff --git a/Documentation/devicetree/bindings/phy/starfive,jh7110-inno-hdmi-phy.yaml b/Documentation/devicetree/bindings/phy/starfive,jh7110-inno-hdmi-phy.yaml
new file mode 100644
index 0000000000000000000000000000000000000000..b1ab3c555fbf60a971f511af29a03a6b2e4ae097
--- /dev/null
+++ b/Documentation/devicetree/bindings/phy/starfive,jh7110-inno-hdmi-phy.yaml
@@ -0,0 +1,58 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/phy/starfive,jh7110-inno-hdmi-phy.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: StarFive JH7110 Innosilicon INNO HDMI PHY
+
+maintainers:
+ - Michal Wilczynski <m.wilczynski@samsung.com>
+
+description:
+ The PHY portion of the StarFive JH7110 INNO HDMI IP.
+
+properties:
+ compatible:
+ const: starfive,jh7110-inno-hdmi-phy
+
+ clocks:
+ maxItems: 1
+
+ clock-names:
+ const: refoclk
+
+ '#clock-cells':
+ const: 0
+
+ clock-output-names:
+ const: hdmi_pclk
+
+ '#phy-cells':
+ const: 0
+
+required:
+ - compatible
+ - clocks
+ - clock-names
+ - '#clock-cells'
+ - clock-output-names
+ - '#phy-cells'
+
+additionalProperties: false
+
+examples:
+ # Shown as a child of the HDMI subsystem node; see
+ # Documentation/devicetree/bindings/mfd/starfive,jh7110-hdmi-subsystem.yaml
+ # for the full node.
+ - |
+ phy {
+ compatible = "starfive,jh7110-inno-hdmi-phy";
+ #clock-cells = <0>;
+ clock-output-names = "hdmi_pclk";
+ clocks = <&xin24m>;
+ clock-names = "refoclk";
+ #phy-cells = <0>;
+ };
+
+...
--
2.34.1
^ permalink raw reply related [flat|nested] 116+ messages in thread
* [PATCH v2 01/15] dt-bindings: phy: Add starfive,jh7110-inno-hdmi-phy
@ 2026-08-28 13:47 ` Michal Wilczynski
0 siblings, 0 replies; 116+ messages in thread
From: Michal Wilczynski @ 2026-08-28 13:47 UTC (permalink / raw)
To: Vinod Koul, Neil Armstrong, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Andrzej Hajda, Robert Foss, Laurent Pinchart,
Jonas Karlman, Jernej Skrabec, Luca Ceresoli, David Airlie,
Simona Vetter, Maarten Lankhorst, Maxime Ripard,
Thomas Zimmermann, Lee Jones, Andy Yan, Philipp Zabel,
Emil Renner Berthing, Hal Feng, Michael Turquette, Stephen Boyd,
Brian Masney, Heiko Stuebner, Conor Dooley, Paul Walmsley,
Palmer Dabbelt, Albert Ou, Alexandre Ghiti, Dominique Belhachemi
Cc: devicetree, mfd, linux-kernel, dri-devel, Andy Yan,
Graham Markall, linux-rockchip, linux-phy, Michal Wilczynski,
linux-riscv, Maud Spierings, linux-clk, linux-arm-kernel,
Marek Szyprowski
Add the dt-binding for the StarFive JH7110 Innosilicon HDMI PHY.
This device is a child of the starfive,jh7110-hdmi-subsystem node. It
functions as both a PHY provider for the controller and as a clock
provider for the variable pixel clock (hdmi_pclk), which it generates
from its refoclk.
Signed-off-by: Michal Wilczynski <m.wilczynski@samsung.com>
---
.../phy/starfive,jh7110-inno-hdmi-phy.yaml | 58 ++++++++++++++++++++++
1 file changed, 58 insertions(+)
diff --git a/Documentation/devicetree/bindings/phy/starfive,jh7110-inno-hdmi-phy.yaml b/Documentation/devicetree/bindings/phy/starfive,jh7110-inno-hdmi-phy.yaml
new file mode 100644
index 0000000000000000000000000000000000000000..b1ab3c555fbf60a971f511af29a03a6b2e4ae097
--- /dev/null
+++ b/Documentation/devicetree/bindings/phy/starfive,jh7110-inno-hdmi-phy.yaml
@@ -0,0 +1,58 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/phy/starfive,jh7110-inno-hdmi-phy.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: StarFive JH7110 Innosilicon INNO HDMI PHY
+
+maintainers:
+ - Michal Wilczynski <m.wilczynski@samsung.com>
+
+description:
+ The PHY portion of the StarFive JH7110 INNO HDMI IP.
+
+properties:
+ compatible:
+ const: starfive,jh7110-inno-hdmi-phy
+
+ clocks:
+ maxItems: 1
+
+ clock-names:
+ const: refoclk
+
+ '#clock-cells':
+ const: 0
+
+ clock-output-names:
+ const: hdmi_pclk
+
+ '#phy-cells':
+ const: 0
+
+required:
+ - compatible
+ - clocks
+ - clock-names
+ - '#clock-cells'
+ - clock-output-names
+ - '#phy-cells'
+
+additionalProperties: false
+
+examples:
+ # Shown as a child of the HDMI subsystem node; see
+ # Documentation/devicetree/bindings/mfd/starfive,jh7110-hdmi-subsystem.yaml
+ # for the full node.
+ - |
+ phy {
+ compatible = "starfive,jh7110-inno-hdmi-phy";
+ #clock-cells = <0>;
+ clock-output-names = "hdmi_pclk";
+ clocks = <&xin24m>;
+ clock-names = "refoclk";
+ #phy-cells = <0>;
+ };
+
+...
--
2.34.1
_______________________________________________
linux-riscv mailing list
linux-riscv@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-riscv
^ permalink raw reply related [flat|nested] 116+ messages in thread
* [PATCH v2 01/15] dt-bindings: phy: Add starfive,jh7110-inno-hdmi-phy
@ 2026-08-28 13:47 ` Michal Wilczynski
0 siblings, 0 replies; 116+ messages in thread
From: Michal Wilczynski @ 2026-08-28 13:47 UTC (permalink / raw)
To: Vinod Koul, Neil Armstrong, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Andrzej Hajda, Robert Foss, Laurent Pinchart,
Jonas Karlman, Jernej Skrabec, Luca Ceresoli, David Airlie,
Simona Vetter, Maarten Lankhorst, Maxime Ripard,
Thomas Zimmermann, Lee Jones, Andy Yan, Philipp Zabel,
Emil Renner Berthing, Hal Feng, Michael Turquette, Stephen Boyd,
Brian Masney, Heiko Stuebner, Conor Dooley, Paul Walmsley,
Palmer Dabbelt, Albert Ou, Alexandre Ghiti, Dominique Belhachemi
Cc: linux-phy, devicetree, linux-kernel, dri-devel, mfd, linux-clk,
linux-arm-kernel, linux-rockchip, linux-riscv, Icenowy Zheng,
Andy Yan, Marek Szyprowski, Maud Spierings, Graham Markall,
Michal Wilczynski
Add the dt-binding for the StarFive JH7110 Innosilicon HDMI PHY.
This device is a child of the starfive,jh7110-hdmi-subsystem node. It
functions as both a PHY provider for the controller and as a clock
provider for the variable pixel clock (hdmi_pclk), which it generates
from its refoclk.
Signed-off-by: Michal Wilczynski <m.wilczynski@samsung.com>
---
.../phy/starfive,jh7110-inno-hdmi-phy.yaml | 58 ++++++++++++++++++++++
1 file changed, 58 insertions(+)
diff --git a/Documentation/devicetree/bindings/phy/starfive,jh7110-inno-hdmi-phy.yaml b/Documentation/devicetree/bindings/phy/starfive,jh7110-inno-hdmi-phy.yaml
new file mode 100644
index 0000000000000000000000000000000000000000..b1ab3c555fbf60a971f511af29a03a6b2e4ae097
--- /dev/null
+++ b/Documentation/devicetree/bindings/phy/starfive,jh7110-inno-hdmi-phy.yaml
@@ -0,0 +1,58 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/phy/starfive,jh7110-inno-hdmi-phy.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: StarFive JH7110 Innosilicon INNO HDMI PHY
+
+maintainers:
+ - Michal Wilczynski <m.wilczynski@samsung.com>
+
+description:
+ The PHY portion of the StarFive JH7110 INNO HDMI IP.
+
+properties:
+ compatible:
+ const: starfive,jh7110-inno-hdmi-phy
+
+ clocks:
+ maxItems: 1
+
+ clock-names:
+ const: refoclk
+
+ '#clock-cells':
+ const: 0
+
+ clock-output-names:
+ const: hdmi_pclk
+
+ '#phy-cells':
+ const: 0
+
+required:
+ - compatible
+ - clocks
+ - clock-names
+ - '#clock-cells'
+ - clock-output-names
+ - '#phy-cells'
+
+additionalProperties: false
+
+examples:
+ # Shown as a child of the HDMI subsystem node; see
+ # Documentation/devicetree/bindings/mfd/starfive,jh7110-hdmi-subsystem.yaml
+ # for the full node.
+ - |
+ phy {
+ compatible = "starfive,jh7110-inno-hdmi-phy";
+ #clock-cells = <0>;
+ clock-output-names = "hdmi_pclk";
+ clocks = <&xin24m>;
+ clock-names = "refoclk";
+ #phy-cells = <0>;
+ };
+
+...
--
2.34.1
_______________________________________________
Linux-rockchip mailing list
Linux-rockchip@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-rockchip
^ permalink raw reply related [flat|nested] 116+ messages in thread
* [PATCH v2 01/15] dt-bindings: phy: Add starfive,jh7110-inno-hdmi-phy
@ 2026-08-28 13:47 ` Michal Wilczynski
0 siblings, 0 replies; 116+ messages in thread
From: Michal Wilczynski @ 2026-08-28 13:47 UTC (permalink / raw)
To: Vinod Koul, Neil Armstrong, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Andrzej Hajda, Robert Foss, Laurent Pinchart,
Jonas Karlman, Jernej Skrabec, Luca Ceresoli, David Airlie,
Simona Vetter, Maarten Lankhorst, Maxime Ripard,
Thomas Zimmermann, Lee Jones, Andy Yan, Philipp Zabel,
Emil Renner Berthing, Hal Feng, Michael Turquette, Stephen Boyd,
Brian Masney, Heiko Stuebner, Conor Dooley, Paul Walmsley,
Palmer Dabbelt, Albert Ou, Alexandre Ghiti, Dominique Belhachemi
Cc: linux-phy, devicetree, linux-kernel, dri-devel, mfd, linux-clk,
linux-arm-kernel, linux-rockchip, linux-riscv, Icenowy Zheng,
Andy Yan, Marek Szyprowski, Maud Spierings, Graham Markall,
Michal Wilczynski
Add the dt-binding for the StarFive JH7110 Innosilicon HDMI PHY.
This device is a child of the starfive,jh7110-hdmi-subsystem node. It
functions as both a PHY provider for the controller and as a clock
provider for the variable pixel clock (hdmi_pclk), which it generates
from its refoclk.
Signed-off-by: Michal Wilczynski <m.wilczynski@samsung.com>
---
.../phy/starfive,jh7110-inno-hdmi-phy.yaml | 58 ++++++++++++++++++++++
1 file changed, 58 insertions(+)
diff --git a/Documentation/devicetree/bindings/phy/starfive,jh7110-inno-hdmi-phy.yaml b/Documentation/devicetree/bindings/phy/starfive,jh7110-inno-hdmi-phy.yaml
new file mode 100644
index 0000000000000000000000000000000000000000..b1ab3c555fbf60a971f511af29a03a6b2e4ae097
--- /dev/null
+++ b/Documentation/devicetree/bindings/phy/starfive,jh7110-inno-hdmi-phy.yaml
@@ -0,0 +1,58 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/phy/starfive,jh7110-inno-hdmi-phy.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: StarFive JH7110 Innosilicon INNO HDMI PHY
+
+maintainers:
+ - Michal Wilczynski <m.wilczynski@samsung.com>
+
+description:
+ The PHY portion of the StarFive JH7110 INNO HDMI IP.
+
+properties:
+ compatible:
+ const: starfive,jh7110-inno-hdmi-phy
+
+ clocks:
+ maxItems: 1
+
+ clock-names:
+ const: refoclk
+
+ '#clock-cells':
+ const: 0
+
+ clock-output-names:
+ const: hdmi_pclk
+
+ '#phy-cells':
+ const: 0
+
+required:
+ - compatible
+ - clocks
+ - clock-names
+ - '#clock-cells'
+ - clock-output-names
+ - '#phy-cells'
+
+additionalProperties: false
+
+examples:
+ # Shown as a child of the HDMI subsystem node; see
+ # Documentation/devicetree/bindings/mfd/starfive,jh7110-hdmi-subsystem.yaml
+ # for the full node.
+ - |
+ phy {
+ compatible = "starfive,jh7110-inno-hdmi-phy";
+ #clock-cells = <0>;
+ clock-output-names = "hdmi_pclk";
+ clocks = <&xin24m>;
+ clock-names = "refoclk";
+ #phy-cells = <0>;
+ };
+
+...
--
2.34.1
--
linux-phy mailing list
linux-phy@lists.infradead.org
https://lists.infradead.org/mailman/listinfo/linux-phy
^ permalink raw reply related [flat|nested] 116+ messages in thread
* [PATCH v2 02/15] dt-bindings: display: bridge: Add starfive,jh7110-inno-hdmi-controller
2026-08-28 13:47 ` Michal Wilczynski
(?)
(?)
@ 2026-08-28 13:47 ` Michal Wilczynski
-1 siblings, 0 replies; 116+ messages in thread
From: Michal Wilczynski @ 2026-08-28 13:47 UTC (permalink / raw)
To: Vinod Koul, Neil Armstrong, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Andrzej Hajda, Robert Foss, Laurent Pinchart,
Jonas Karlman, Jernej Skrabec, Luca Ceresoli, David Airlie,
Simona Vetter, Maarten Lankhorst, Maxime Ripard,
Thomas Zimmermann, Lee Jones, Andy Yan, Philipp Zabel,
Emil Renner Berthing, Hal Feng, Michael Turquette, Stephen Boyd,
Brian Masney, Heiko Stuebner, Conor Dooley, Paul Walmsley,
Palmer Dabbelt, Albert Ou, Alexandre Ghiti, Dominique Belhachemi
Cc: linux-phy, devicetree, linux-kernel, dri-devel, mfd, linux-clk,
linux-arm-kernel, linux-rockchip, linux-riscv, Icenowy Zheng,
Andy Yan, Marek Szyprowski, Maud Spierings, Graham Markall,
Michal Wilczynski
Add the dt-binding for the StarFive JH7110 Innosilicon HDMI controller
(DRM bridge).
This device is the second child of the starfive,jh7110-hdmi-subsystem node.
It consumes register access clocks (sys, mclk, bclk) from the voutcrg and
both the pixel clock (pclk) and the PHY from its hdmi_phy sibling.
Signed-off-by: Michal Wilczynski <m.wilczynski@samsung.com>
---
.../starfive,jh7110-inno-hdmi-controller.yaml | 109 +++++++++++++++++++++
1 file changed, 109 insertions(+)
diff --git a/Documentation/devicetree/bindings/display/bridge/starfive,jh7110-inno-hdmi-controller.yaml b/Documentation/devicetree/bindings/display/bridge/starfive,jh7110-inno-hdmi-controller.yaml
new file mode 100644
index 0000000000000000000000000000000000000000..0e584e7b756e24e2f99a62daab3117bbf4b472b6
--- /dev/null
+++ b/Documentation/devicetree/bindings/display/bridge/starfive,jh7110-inno-hdmi-controller.yaml
@@ -0,0 +1,109 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/display/bridge/starfive,jh7110-inno-hdmi-controller.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: StarFive JH7110 Innosilicon HDMI Controller
+
+maintainers:
+ - Michal Wilczynski <m.wilczynski@samsung.com>
+
+description:
+ The controller portion of the StarFive JH7110 INNO HDMI IP.
+
+properties:
+ compatible:
+ const: starfive,jh7110-inno-hdmi-controller
+
+ interrupts:
+ maxItems: 1
+
+ clocks:
+ items:
+ - description: System clock for register access
+ - description: Module clock
+ - description: Bus clock
+ - description: Pixel clock from PHY
+
+ clock-names:
+ items:
+ - const: sys
+ - const: mclk
+ - const: bclk
+ - const: pclk
+
+ resets:
+ maxItems: 1
+
+ reset-names:
+ const: hdmi_tx
+
+ phys:
+ maxItems: 1
+
+ phy-names:
+ const: hdmi-phy
+
+ ports:
+ $ref: /schemas/graph.yaml#/properties/ports
+ description:
+ A graph node with one input port and one output port.
+
+required:
+ - compatible
+ - interrupts
+ - clocks
+ - clock-names
+ - resets
+ - reset-names
+ - phys
+ - phy-names
+ - ports
+
+additionalProperties: false
+
+examples:
+ # Shown as a child of the HDMI subsystem node; see
+ # Documentation/devicetree/bindings/mfd/starfive,jh7110-hdmi-subsystem.yaml
+ # for the full node.
+ - |
+ #include <dt-bindings/clock/starfive,jh7110-crg.h>
+ #include <dt-bindings/reset/starfive,jh7110-crg.h>
+
+ controller {
+ compatible = "starfive,jh7110-inno-hdmi-controller";
+ clocks = <&voutcrg JH7110_VOUTCLK_HDMI_TX_SYS>,
+ <&voutcrg JH7110_VOUTCLK_HDMI_TX_MCLK>,
+ <&voutcrg JH7110_VOUTCLK_HDMI_TX_BCLK>,
+ <&hdmi_phy>;
+ clock-names = "sys", "mclk", "bclk", "pclk";
+ interrupts = <99>;
+ phys = <&hdmi_phy>;
+ phy-names = "hdmi-phy";
+ resets = <&voutcrg JH7110_VOUTRST_HDMI_TX_HDMI>;
+ reset-names = "hdmi_tx";
+
+ ports {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ port@0 {
+ reg = <0>;
+
+ endpoint {
+ remote-endpoint = <&dpu_out_dpi0>;
+ };
+ };
+
+ port@1 {
+ reg = <1>;
+
+ endpoint {
+ remote-endpoint = <&hdmi_con_in>;
+ };
+ };
+ };
+ };
+
+...
--
2.34.1
^ permalink raw reply related [flat|nested] 116+ messages in thread
* [PATCH v2 02/15] dt-bindings: display: bridge: Add starfive,jh7110-inno-hdmi-controller
@ 2026-08-28 13:47 ` Michal Wilczynski
0 siblings, 0 replies; 116+ messages in thread
From: Michal Wilczynski @ 2026-08-28 13:47 UTC (permalink / raw)
To: Vinod Koul, Neil Armstrong, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Andrzej Hajda, Robert Foss, Laurent Pinchart,
Jonas Karlman, Jernej Skrabec, Luca Ceresoli, David Airlie,
Simona Vetter, Maarten Lankhorst, Maxime Ripard,
Thomas Zimmermann, Lee Jones, Andy Yan, Philipp Zabel,
Emil Renner Berthing, Hal Feng, Michael Turquette, Stephen Boyd,
Brian Masney, Heiko Stuebner, Conor Dooley, Paul Walmsley,
Palmer Dabbelt, Albert Ou, Alexandre Ghiti, Dominique Belhachemi
Cc: devicetree, mfd, linux-kernel, dri-devel, Andy Yan,
Graham Markall, linux-rockchip, linux-phy, Michal Wilczynski,
linux-riscv, Maud Spierings, linux-clk, linux-arm-kernel,
Marek Szyprowski
Add the dt-binding for the StarFive JH7110 Innosilicon HDMI controller
(DRM bridge).
This device is the second child of the starfive,jh7110-hdmi-subsystem node.
It consumes register access clocks (sys, mclk, bclk) from the voutcrg and
both the pixel clock (pclk) and the PHY from its hdmi_phy sibling.
Signed-off-by: Michal Wilczynski <m.wilczynski@samsung.com>
---
.../starfive,jh7110-inno-hdmi-controller.yaml | 109 +++++++++++++++++++++
1 file changed, 109 insertions(+)
diff --git a/Documentation/devicetree/bindings/display/bridge/starfive,jh7110-inno-hdmi-controller.yaml b/Documentation/devicetree/bindings/display/bridge/starfive,jh7110-inno-hdmi-controller.yaml
new file mode 100644
index 0000000000000000000000000000000000000000..0e584e7b756e24e2f99a62daab3117bbf4b472b6
--- /dev/null
+++ b/Documentation/devicetree/bindings/display/bridge/starfive,jh7110-inno-hdmi-controller.yaml
@@ -0,0 +1,109 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/display/bridge/starfive,jh7110-inno-hdmi-controller.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: StarFive JH7110 Innosilicon HDMI Controller
+
+maintainers:
+ - Michal Wilczynski <m.wilczynski@samsung.com>
+
+description:
+ The controller portion of the StarFive JH7110 INNO HDMI IP.
+
+properties:
+ compatible:
+ const: starfive,jh7110-inno-hdmi-controller
+
+ interrupts:
+ maxItems: 1
+
+ clocks:
+ items:
+ - description: System clock for register access
+ - description: Module clock
+ - description: Bus clock
+ - description: Pixel clock from PHY
+
+ clock-names:
+ items:
+ - const: sys
+ - const: mclk
+ - const: bclk
+ - const: pclk
+
+ resets:
+ maxItems: 1
+
+ reset-names:
+ const: hdmi_tx
+
+ phys:
+ maxItems: 1
+
+ phy-names:
+ const: hdmi-phy
+
+ ports:
+ $ref: /schemas/graph.yaml#/properties/ports
+ description:
+ A graph node with one input port and one output port.
+
+required:
+ - compatible
+ - interrupts
+ - clocks
+ - clock-names
+ - resets
+ - reset-names
+ - phys
+ - phy-names
+ - ports
+
+additionalProperties: false
+
+examples:
+ # Shown as a child of the HDMI subsystem node; see
+ # Documentation/devicetree/bindings/mfd/starfive,jh7110-hdmi-subsystem.yaml
+ # for the full node.
+ - |
+ #include <dt-bindings/clock/starfive,jh7110-crg.h>
+ #include <dt-bindings/reset/starfive,jh7110-crg.h>
+
+ controller {
+ compatible = "starfive,jh7110-inno-hdmi-controller";
+ clocks = <&voutcrg JH7110_VOUTCLK_HDMI_TX_SYS>,
+ <&voutcrg JH7110_VOUTCLK_HDMI_TX_MCLK>,
+ <&voutcrg JH7110_VOUTCLK_HDMI_TX_BCLK>,
+ <&hdmi_phy>;
+ clock-names = "sys", "mclk", "bclk", "pclk";
+ interrupts = <99>;
+ phys = <&hdmi_phy>;
+ phy-names = "hdmi-phy";
+ resets = <&voutcrg JH7110_VOUTRST_HDMI_TX_HDMI>;
+ reset-names = "hdmi_tx";
+
+ ports {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ port@0 {
+ reg = <0>;
+
+ endpoint {
+ remote-endpoint = <&dpu_out_dpi0>;
+ };
+ };
+
+ port@1 {
+ reg = <1>;
+
+ endpoint {
+ remote-endpoint = <&hdmi_con_in>;
+ };
+ };
+ };
+ };
+
+...
--
2.34.1
_______________________________________________
linux-riscv mailing list
linux-riscv@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-riscv
^ permalink raw reply related [flat|nested] 116+ messages in thread
* [PATCH v2 02/15] dt-bindings: display: bridge: Add starfive,jh7110-inno-hdmi-controller
@ 2026-08-28 13:47 ` Michal Wilczynski
0 siblings, 0 replies; 116+ messages in thread
From: Michal Wilczynski @ 2026-08-28 13:47 UTC (permalink / raw)
To: Vinod Koul, Neil Armstrong, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Andrzej Hajda, Robert Foss, Laurent Pinchart,
Jonas Karlman, Jernej Skrabec, Luca Ceresoli, David Airlie,
Simona Vetter, Maarten Lankhorst, Maxime Ripard,
Thomas Zimmermann, Lee Jones, Andy Yan, Philipp Zabel,
Emil Renner Berthing, Hal Feng, Michael Turquette, Stephen Boyd,
Brian Masney, Heiko Stuebner, Conor Dooley, Paul Walmsley,
Palmer Dabbelt, Albert Ou, Alexandre Ghiti, Dominique Belhachemi
Cc: linux-phy, devicetree, linux-kernel, dri-devel, mfd, linux-clk,
linux-arm-kernel, linux-rockchip, linux-riscv, Icenowy Zheng,
Andy Yan, Marek Szyprowski, Maud Spierings, Graham Markall,
Michal Wilczynski
Add the dt-binding for the StarFive JH7110 Innosilicon HDMI controller
(DRM bridge).
This device is the second child of the starfive,jh7110-hdmi-subsystem node.
It consumes register access clocks (sys, mclk, bclk) from the voutcrg and
both the pixel clock (pclk) and the PHY from its hdmi_phy sibling.
Signed-off-by: Michal Wilczynski <m.wilczynski@samsung.com>
---
.../starfive,jh7110-inno-hdmi-controller.yaml | 109 +++++++++++++++++++++
1 file changed, 109 insertions(+)
diff --git a/Documentation/devicetree/bindings/display/bridge/starfive,jh7110-inno-hdmi-controller.yaml b/Documentation/devicetree/bindings/display/bridge/starfive,jh7110-inno-hdmi-controller.yaml
new file mode 100644
index 0000000000000000000000000000000000000000..0e584e7b756e24e2f99a62daab3117bbf4b472b6
--- /dev/null
+++ b/Documentation/devicetree/bindings/display/bridge/starfive,jh7110-inno-hdmi-controller.yaml
@@ -0,0 +1,109 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/display/bridge/starfive,jh7110-inno-hdmi-controller.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: StarFive JH7110 Innosilicon HDMI Controller
+
+maintainers:
+ - Michal Wilczynski <m.wilczynski@samsung.com>
+
+description:
+ The controller portion of the StarFive JH7110 INNO HDMI IP.
+
+properties:
+ compatible:
+ const: starfive,jh7110-inno-hdmi-controller
+
+ interrupts:
+ maxItems: 1
+
+ clocks:
+ items:
+ - description: System clock for register access
+ - description: Module clock
+ - description: Bus clock
+ - description: Pixel clock from PHY
+
+ clock-names:
+ items:
+ - const: sys
+ - const: mclk
+ - const: bclk
+ - const: pclk
+
+ resets:
+ maxItems: 1
+
+ reset-names:
+ const: hdmi_tx
+
+ phys:
+ maxItems: 1
+
+ phy-names:
+ const: hdmi-phy
+
+ ports:
+ $ref: /schemas/graph.yaml#/properties/ports
+ description:
+ A graph node with one input port and one output port.
+
+required:
+ - compatible
+ - interrupts
+ - clocks
+ - clock-names
+ - resets
+ - reset-names
+ - phys
+ - phy-names
+ - ports
+
+additionalProperties: false
+
+examples:
+ # Shown as a child of the HDMI subsystem node; see
+ # Documentation/devicetree/bindings/mfd/starfive,jh7110-hdmi-subsystem.yaml
+ # for the full node.
+ - |
+ #include <dt-bindings/clock/starfive,jh7110-crg.h>
+ #include <dt-bindings/reset/starfive,jh7110-crg.h>
+
+ controller {
+ compatible = "starfive,jh7110-inno-hdmi-controller";
+ clocks = <&voutcrg JH7110_VOUTCLK_HDMI_TX_SYS>,
+ <&voutcrg JH7110_VOUTCLK_HDMI_TX_MCLK>,
+ <&voutcrg JH7110_VOUTCLK_HDMI_TX_BCLK>,
+ <&hdmi_phy>;
+ clock-names = "sys", "mclk", "bclk", "pclk";
+ interrupts = <99>;
+ phys = <&hdmi_phy>;
+ phy-names = "hdmi-phy";
+ resets = <&voutcrg JH7110_VOUTRST_HDMI_TX_HDMI>;
+ reset-names = "hdmi_tx";
+
+ ports {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ port@0 {
+ reg = <0>;
+
+ endpoint {
+ remote-endpoint = <&dpu_out_dpi0>;
+ };
+ };
+
+ port@1 {
+ reg = <1>;
+
+ endpoint {
+ remote-endpoint = <&hdmi_con_in>;
+ };
+ };
+ };
+ };
+
+...
--
2.34.1
_______________________________________________
Linux-rockchip mailing list
Linux-rockchip@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-rockchip
^ permalink raw reply related [flat|nested] 116+ messages in thread
* [PATCH v2 02/15] dt-bindings: display: bridge: Add starfive,jh7110-inno-hdmi-controller
@ 2026-08-28 13:47 ` Michal Wilczynski
0 siblings, 0 replies; 116+ messages in thread
From: Michal Wilczynski @ 2026-08-28 13:47 UTC (permalink / raw)
To: Vinod Koul, Neil Armstrong, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Andrzej Hajda, Robert Foss, Laurent Pinchart,
Jonas Karlman, Jernej Skrabec, Luca Ceresoli, David Airlie,
Simona Vetter, Maarten Lankhorst, Maxime Ripard,
Thomas Zimmermann, Lee Jones, Andy Yan, Philipp Zabel,
Emil Renner Berthing, Hal Feng, Michael Turquette, Stephen Boyd,
Brian Masney, Heiko Stuebner, Conor Dooley, Paul Walmsley,
Palmer Dabbelt, Albert Ou, Alexandre Ghiti, Dominique Belhachemi
Cc: linux-phy, devicetree, linux-kernel, dri-devel, mfd, linux-clk,
linux-arm-kernel, linux-rockchip, linux-riscv, Icenowy Zheng,
Andy Yan, Marek Szyprowski, Maud Spierings, Graham Markall,
Michal Wilczynski
Add the dt-binding for the StarFive JH7110 Innosilicon HDMI controller
(DRM bridge).
This device is the second child of the starfive,jh7110-hdmi-subsystem node.
It consumes register access clocks (sys, mclk, bclk) from the voutcrg and
both the pixel clock (pclk) and the PHY from its hdmi_phy sibling.
Signed-off-by: Michal Wilczynski <m.wilczynski@samsung.com>
---
.../starfive,jh7110-inno-hdmi-controller.yaml | 109 +++++++++++++++++++++
1 file changed, 109 insertions(+)
diff --git a/Documentation/devicetree/bindings/display/bridge/starfive,jh7110-inno-hdmi-controller.yaml b/Documentation/devicetree/bindings/display/bridge/starfive,jh7110-inno-hdmi-controller.yaml
new file mode 100644
index 0000000000000000000000000000000000000000..0e584e7b756e24e2f99a62daab3117bbf4b472b6
--- /dev/null
+++ b/Documentation/devicetree/bindings/display/bridge/starfive,jh7110-inno-hdmi-controller.yaml
@@ -0,0 +1,109 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/display/bridge/starfive,jh7110-inno-hdmi-controller.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: StarFive JH7110 Innosilicon HDMI Controller
+
+maintainers:
+ - Michal Wilczynski <m.wilczynski@samsung.com>
+
+description:
+ The controller portion of the StarFive JH7110 INNO HDMI IP.
+
+properties:
+ compatible:
+ const: starfive,jh7110-inno-hdmi-controller
+
+ interrupts:
+ maxItems: 1
+
+ clocks:
+ items:
+ - description: System clock for register access
+ - description: Module clock
+ - description: Bus clock
+ - description: Pixel clock from PHY
+
+ clock-names:
+ items:
+ - const: sys
+ - const: mclk
+ - const: bclk
+ - const: pclk
+
+ resets:
+ maxItems: 1
+
+ reset-names:
+ const: hdmi_tx
+
+ phys:
+ maxItems: 1
+
+ phy-names:
+ const: hdmi-phy
+
+ ports:
+ $ref: /schemas/graph.yaml#/properties/ports
+ description:
+ A graph node with one input port and one output port.
+
+required:
+ - compatible
+ - interrupts
+ - clocks
+ - clock-names
+ - resets
+ - reset-names
+ - phys
+ - phy-names
+ - ports
+
+additionalProperties: false
+
+examples:
+ # Shown as a child of the HDMI subsystem node; see
+ # Documentation/devicetree/bindings/mfd/starfive,jh7110-hdmi-subsystem.yaml
+ # for the full node.
+ - |
+ #include <dt-bindings/clock/starfive,jh7110-crg.h>
+ #include <dt-bindings/reset/starfive,jh7110-crg.h>
+
+ controller {
+ compatible = "starfive,jh7110-inno-hdmi-controller";
+ clocks = <&voutcrg JH7110_VOUTCLK_HDMI_TX_SYS>,
+ <&voutcrg JH7110_VOUTCLK_HDMI_TX_MCLK>,
+ <&voutcrg JH7110_VOUTCLK_HDMI_TX_BCLK>,
+ <&hdmi_phy>;
+ clock-names = "sys", "mclk", "bclk", "pclk";
+ interrupts = <99>;
+ phys = <&hdmi_phy>;
+ phy-names = "hdmi-phy";
+ resets = <&voutcrg JH7110_VOUTRST_HDMI_TX_HDMI>;
+ reset-names = "hdmi_tx";
+
+ ports {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ port@0 {
+ reg = <0>;
+
+ endpoint {
+ remote-endpoint = <&dpu_out_dpi0>;
+ };
+ };
+
+ port@1 {
+ reg = <1>;
+
+ endpoint {
+ remote-endpoint = <&hdmi_con_in>;
+ };
+ };
+ };
+ };
+
+...
--
2.34.1
--
linux-phy mailing list
linux-phy@lists.infradead.org
https://lists.infradead.org/mailman/listinfo/linux-phy
^ permalink raw reply related [flat|nested] 116+ messages in thread
* [PATCH v2 03/15] dt-bindings: mfd: Add starfive,jh7110-hdmi-subsystem
2026-08-28 13:47 ` Michal Wilczynski
(?)
(?)
@ 2026-08-28 13:47 ` Michal Wilczynski
-1 siblings, 0 replies; 116+ messages in thread
From: Michal Wilczynski @ 2026-08-28 13:47 UTC (permalink / raw)
To: Vinod Koul, Neil Armstrong, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Andrzej Hajda, Robert Foss, Laurent Pinchart,
Jonas Karlman, Jernej Skrabec, Luca Ceresoli, David Airlie,
Simona Vetter, Maarten Lankhorst, Maxime Ripard,
Thomas Zimmermann, Lee Jones, Andy Yan, Philipp Zabel,
Emil Renner Berthing, Hal Feng, Michael Turquette, Stephen Boyd,
Brian Masney, Heiko Stuebner, Conor Dooley, Paul Walmsley,
Palmer Dabbelt, Albert Ou, Alexandre Ghiti, Dominique Belhachemi
Cc: linux-phy, devicetree, linux-kernel, dri-devel, mfd, linux-clk,
linux-arm-kernel, linux-rockchip, linux-riscv, Icenowy Zheng,
Andy Yan, Marek Szyprowski, Maud Spierings, Graham Markall,
Michal Wilczynski
Add the dt-binding for the StarFive JH7110 HDMI subsystem.
The JH7110 HDMI IP is a monolithic block containing both the digital
controller and analog PHY in a single register space. This binding
defines the parent device, which holds the shared register map and
populates its two children: the PHY and the controller. This is
necessary to resolve a circular clock dependency between the HDMI block
and the VOUT clock generator.
Signed-off-by: Michal Wilczynski <m.wilczynski@samsung.com>
---
.../mfd/starfive,jh7110-hdmi-subsystem.yaml | 116 +++++++++++++++++++++
1 file changed, 116 insertions(+)
diff --git a/Documentation/devicetree/bindings/mfd/starfive,jh7110-hdmi-subsystem.yaml b/Documentation/devicetree/bindings/mfd/starfive,jh7110-hdmi-subsystem.yaml
new file mode 100644
index 0000000000000000000000000000000000000000..01f079160ab8c13c6fa4ce3abaac6607021b3792
--- /dev/null
+++ b/Documentation/devicetree/bindings/mfd/starfive,jh7110-hdmi-subsystem.yaml
@@ -0,0 +1,116 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/mfd/starfive,jh7110-hdmi-subsystem.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: StarFive JH7110 HDMI subsystem
+
+maintainers:
+ - Michal Wilczynski <m.wilczynski@samsung.com>
+
+description:
+ The StarFive JH7110 HDMI block is a monolithic IP containing both
+ the digital controller logic and the analog PHY logic in a single
+ register space.
+
+properties:
+ compatible:
+ const: starfive,jh7110-hdmi-subsystem
+
+ reg:
+ maxItems: 1
+
+ clocks:
+ maxItems: 1
+ description:
+ NoC display bus clock, which gates access to the whole vout
+ register region.
+
+ resets:
+ maxItems: 1
+ description:
+ NoC display bus reset, which gates access to the whole vout
+ register region.
+
+ power-domains:
+ maxItems: 1
+
+required:
+ - compatible
+ - reg
+ - clocks
+ - resets
+ - power-domains
+
+patternProperties:
+ "^phy(@[0-9a-f]+)?$":
+ $ref: /schemas/phy/starfive,jh7110-inno-hdmi-phy.yaml#
+ "^controller(@[0-9a-f]+)?$":
+ $ref: /schemas/display/bridge/starfive,jh7110-inno-hdmi-controller.yaml#
+
+additionalProperties: false
+
+examples:
+ - |
+ #include <dt-bindings/clock/starfive,jh7110-crg.h>
+ #include <dt-bindings/power/starfive,jh7110-pmu.h>
+ #include <dt-bindings/reset/starfive,jh7110-crg.h>
+
+ soc {
+ #address-cells = <1>;
+ #size-cells = <1>;
+
+ hdmi@29590000 {
+ compatible = "starfive,jh7110-hdmi-subsystem";
+ reg = <0x29590000 0x4000>;
+ clocks = <&syscrg JH7110_SYSCLK_NOC_BUS_DISP_AXI>;
+ power-domains = <&pwrc JH7110_PD_VOUT>;
+ resets = <&syscrg JH7110_SYSRST_NOC_BUS_DISP_AXI>;
+
+ controller {
+ compatible = "starfive,jh7110-inno-hdmi-controller";
+ clocks = <&voutcrg JH7110_VOUTCLK_HDMI_TX_SYS>,
+ <&voutcrg JH7110_VOUTCLK_HDMI_TX_MCLK>,
+ <&voutcrg JH7110_VOUTCLK_HDMI_TX_BCLK>,
+ <&hdmi_phy>;
+ clock-names = "sys", "mclk", "bclk", "pclk";
+ interrupts = <99>;
+ phys = <&hdmi_phy>;
+ phy-names = "hdmi-phy";
+ resets = <&voutcrg JH7110_VOUTRST_HDMI_TX_HDMI>;
+ reset-names = "hdmi_tx";
+
+ ports {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ port@0 {
+ reg = <0>;
+
+ endpoint {
+ remote-endpoint = <&dpu_out_dpi0>;
+ };
+ };
+
+ port@1 {
+ reg = <1>;
+
+ endpoint {
+ remote-endpoint = <&hdmi_con_in>;
+ };
+ };
+ };
+ };
+
+ hdmi_phy: phy {
+ compatible = "starfive,jh7110-inno-hdmi-phy";
+ #clock-cells = <0>;
+ clock-output-names = "hdmi_pclk";
+ clocks = <&xin24m>;
+ clock-names = "refoclk";
+ #phy-cells = <0>;
+ };
+ };
+ };
+...
--
2.34.1
^ permalink raw reply related [flat|nested] 116+ messages in thread
* [PATCH v2 03/15] dt-bindings: mfd: Add starfive,jh7110-hdmi-subsystem
@ 2026-08-28 13:47 ` Michal Wilczynski
0 siblings, 0 replies; 116+ messages in thread
From: Michal Wilczynski @ 2026-08-28 13:47 UTC (permalink / raw)
To: Vinod Koul, Neil Armstrong, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Andrzej Hajda, Robert Foss, Laurent Pinchart,
Jonas Karlman, Jernej Skrabec, Luca Ceresoli, David Airlie,
Simona Vetter, Maarten Lankhorst, Maxime Ripard,
Thomas Zimmermann, Lee Jones, Andy Yan, Philipp Zabel,
Emil Renner Berthing, Hal Feng, Michael Turquette, Stephen Boyd,
Brian Masney, Heiko Stuebner, Conor Dooley, Paul Walmsley,
Palmer Dabbelt, Albert Ou, Alexandre Ghiti, Dominique Belhachemi
Cc: devicetree, mfd, linux-kernel, dri-devel, Andy Yan,
Graham Markall, linux-rockchip, linux-phy, Michal Wilczynski,
linux-riscv, Maud Spierings, linux-clk, linux-arm-kernel,
Marek Szyprowski
Add the dt-binding for the StarFive JH7110 HDMI subsystem.
The JH7110 HDMI IP is a monolithic block containing both the digital
controller and analog PHY in a single register space. This binding
defines the parent device, which holds the shared register map and
populates its two children: the PHY and the controller. This is
necessary to resolve a circular clock dependency between the HDMI block
and the VOUT clock generator.
Signed-off-by: Michal Wilczynski <m.wilczynski@samsung.com>
---
.../mfd/starfive,jh7110-hdmi-subsystem.yaml | 116 +++++++++++++++++++++
1 file changed, 116 insertions(+)
diff --git a/Documentation/devicetree/bindings/mfd/starfive,jh7110-hdmi-subsystem.yaml b/Documentation/devicetree/bindings/mfd/starfive,jh7110-hdmi-subsystem.yaml
new file mode 100644
index 0000000000000000000000000000000000000000..01f079160ab8c13c6fa4ce3abaac6607021b3792
--- /dev/null
+++ b/Documentation/devicetree/bindings/mfd/starfive,jh7110-hdmi-subsystem.yaml
@@ -0,0 +1,116 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/mfd/starfive,jh7110-hdmi-subsystem.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: StarFive JH7110 HDMI subsystem
+
+maintainers:
+ - Michal Wilczynski <m.wilczynski@samsung.com>
+
+description:
+ The StarFive JH7110 HDMI block is a monolithic IP containing both
+ the digital controller logic and the analog PHY logic in a single
+ register space.
+
+properties:
+ compatible:
+ const: starfive,jh7110-hdmi-subsystem
+
+ reg:
+ maxItems: 1
+
+ clocks:
+ maxItems: 1
+ description:
+ NoC display bus clock, which gates access to the whole vout
+ register region.
+
+ resets:
+ maxItems: 1
+ description:
+ NoC display bus reset, which gates access to the whole vout
+ register region.
+
+ power-domains:
+ maxItems: 1
+
+required:
+ - compatible
+ - reg
+ - clocks
+ - resets
+ - power-domains
+
+patternProperties:
+ "^phy(@[0-9a-f]+)?$":
+ $ref: /schemas/phy/starfive,jh7110-inno-hdmi-phy.yaml#
+ "^controller(@[0-9a-f]+)?$":
+ $ref: /schemas/display/bridge/starfive,jh7110-inno-hdmi-controller.yaml#
+
+additionalProperties: false
+
+examples:
+ - |
+ #include <dt-bindings/clock/starfive,jh7110-crg.h>
+ #include <dt-bindings/power/starfive,jh7110-pmu.h>
+ #include <dt-bindings/reset/starfive,jh7110-crg.h>
+
+ soc {
+ #address-cells = <1>;
+ #size-cells = <1>;
+
+ hdmi@29590000 {
+ compatible = "starfive,jh7110-hdmi-subsystem";
+ reg = <0x29590000 0x4000>;
+ clocks = <&syscrg JH7110_SYSCLK_NOC_BUS_DISP_AXI>;
+ power-domains = <&pwrc JH7110_PD_VOUT>;
+ resets = <&syscrg JH7110_SYSRST_NOC_BUS_DISP_AXI>;
+
+ controller {
+ compatible = "starfive,jh7110-inno-hdmi-controller";
+ clocks = <&voutcrg JH7110_VOUTCLK_HDMI_TX_SYS>,
+ <&voutcrg JH7110_VOUTCLK_HDMI_TX_MCLK>,
+ <&voutcrg JH7110_VOUTCLK_HDMI_TX_BCLK>,
+ <&hdmi_phy>;
+ clock-names = "sys", "mclk", "bclk", "pclk";
+ interrupts = <99>;
+ phys = <&hdmi_phy>;
+ phy-names = "hdmi-phy";
+ resets = <&voutcrg JH7110_VOUTRST_HDMI_TX_HDMI>;
+ reset-names = "hdmi_tx";
+
+ ports {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ port@0 {
+ reg = <0>;
+
+ endpoint {
+ remote-endpoint = <&dpu_out_dpi0>;
+ };
+ };
+
+ port@1 {
+ reg = <1>;
+
+ endpoint {
+ remote-endpoint = <&hdmi_con_in>;
+ };
+ };
+ };
+ };
+
+ hdmi_phy: phy {
+ compatible = "starfive,jh7110-inno-hdmi-phy";
+ #clock-cells = <0>;
+ clock-output-names = "hdmi_pclk";
+ clocks = <&xin24m>;
+ clock-names = "refoclk";
+ #phy-cells = <0>;
+ };
+ };
+ };
+...
--
2.34.1
_______________________________________________
linux-riscv mailing list
linux-riscv@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-riscv
^ permalink raw reply related [flat|nested] 116+ messages in thread
* [PATCH v2 03/15] dt-bindings: mfd: Add starfive,jh7110-hdmi-subsystem
@ 2026-08-28 13:47 ` Michal Wilczynski
0 siblings, 0 replies; 116+ messages in thread
From: Michal Wilczynski @ 2026-08-28 13:47 UTC (permalink / raw)
To: Vinod Koul, Neil Armstrong, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Andrzej Hajda, Robert Foss, Laurent Pinchart,
Jonas Karlman, Jernej Skrabec, Luca Ceresoli, David Airlie,
Simona Vetter, Maarten Lankhorst, Maxime Ripard,
Thomas Zimmermann, Lee Jones, Andy Yan, Philipp Zabel,
Emil Renner Berthing, Hal Feng, Michael Turquette, Stephen Boyd,
Brian Masney, Heiko Stuebner, Conor Dooley, Paul Walmsley,
Palmer Dabbelt, Albert Ou, Alexandre Ghiti, Dominique Belhachemi
Cc: linux-phy, devicetree, linux-kernel, dri-devel, mfd, linux-clk,
linux-arm-kernel, linux-rockchip, linux-riscv, Icenowy Zheng,
Andy Yan, Marek Szyprowski, Maud Spierings, Graham Markall,
Michal Wilczynski
Add the dt-binding for the StarFive JH7110 HDMI subsystem.
The JH7110 HDMI IP is a monolithic block containing both the digital
controller and analog PHY in a single register space. This binding
defines the parent device, which holds the shared register map and
populates its two children: the PHY and the controller. This is
necessary to resolve a circular clock dependency between the HDMI block
and the VOUT clock generator.
Signed-off-by: Michal Wilczynski <m.wilczynski@samsung.com>
---
.../mfd/starfive,jh7110-hdmi-subsystem.yaml | 116 +++++++++++++++++++++
1 file changed, 116 insertions(+)
diff --git a/Documentation/devicetree/bindings/mfd/starfive,jh7110-hdmi-subsystem.yaml b/Documentation/devicetree/bindings/mfd/starfive,jh7110-hdmi-subsystem.yaml
new file mode 100644
index 0000000000000000000000000000000000000000..01f079160ab8c13c6fa4ce3abaac6607021b3792
--- /dev/null
+++ b/Documentation/devicetree/bindings/mfd/starfive,jh7110-hdmi-subsystem.yaml
@@ -0,0 +1,116 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/mfd/starfive,jh7110-hdmi-subsystem.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: StarFive JH7110 HDMI subsystem
+
+maintainers:
+ - Michal Wilczynski <m.wilczynski@samsung.com>
+
+description:
+ The StarFive JH7110 HDMI block is a monolithic IP containing both
+ the digital controller logic and the analog PHY logic in a single
+ register space.
+
+properties:
+ compatible:
+ const: starfive,jh7110-hdmi-subsystem
+
+ reg:
+ maxItems: 1
+
+ clocks:
+ maxItems: 1
+ description:
+ NoC display bus clock, which gates access to the whole vout
+ register region.
+
+ resets:
+ maxItems: 1
+ description:
+ NoC display bus reset, which gates access to the whole vout
+ register region.
+
+ power-domains:
+ maxItems: 1
+
+required:
+ - compatible
+ - reg
+ - clocks
+ - resets
+ - power-domains
+
+patternProperties:
+ "^phy(@[0-9a-f]+)?$":
+ $ref: /schemas/phy/starfive,jh7110-inno-hdmi-phy.yaml#
+ "^controller(@[0-9a-f]+)?$":
+ $ref: /schemas/display/bridge/starfive,jh7110-inno-hdmi-controller.yaml#
+
+additionalProperties: false
+
+examples:
+ - |
+ #include <dt-bindings/clock/starfive,jh7110-crg.h>
+ #include <dt-bindings/power/starfive,jh7110-pmu.h>
+ #include <dt-bindings/reset/starfive,jh7110-crg.h>
+
+ soc {
+ #address-cells = <1>;
+ #size-cells = <1>;
+
+ hdmi@29590000 {
+ compatible = "starfive,jh7110-hdmi-subsystem";
+ reg = <0x29590000 0x4000>;
+ clocks = <&syscrg JH7110_SYSCLK_NOC_BUS_DISP_AXI>;
+ power-domains = <&pwrc JH7110_PD_VOUT>;
+ resets = <&syscrg JH7110_SYSRST_NOC_BUS_DISP_AXI>;
+
+ controller {
+ compatible = "starfive,jh7110-inno-hdmi-controller";
+ clocks = <&voutcrg JH7110_VOUTCLK_HDMI_TX_SYS>,
+ <&voutcrg JH7110_VOUTCLK_HDMI_TX_MCLK>,
+ <&voutcrg JH7110_VOUTCLK_HDMI_TX_BCLK>,
+ <&hdmi_phy>;
+ clock-names = "sys", "mclk", "bclk", "pclk";
+ interrupts = <99>;
+ phys = <&hdmi_phy>;
+ phy-names = "hdmi-phy";
+ resets = <&voutcrg JH7110_VOUTRST_HDMI_TX_HDMI>;
+ reset-names = "hdmi_tx";
+
+ ports {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ port@0 {
+ reg = <0>;
+
+ endpoint {
+ remote-endpoint = <&dpu_out_dpi0>;
+ };
+ };
+
+ port@1 {
+ reg = <1>;
+
+ endpoint {
+ remote-endpoint = <&hdmi_con_in>;
+ };
+ };
+ };
+ };
+
+ hdmi_phy: phy {
+ compatible = "starfive,jh7110-inno-hdmi-phy";
+ #clock-cells = <0>;
+ clock-output-names = "hdmi_pclk";
+ clocks = <&xin24m>;
+ clock-names = "refoclk";
+ #phy-cells = <0>;
+ };
+ };
+ };
+...
--
2.34.1
_______________________________________________
Linux-rockchip mailing list
Linux-rockchip@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-rockchip
^ permalink raw reply related [flat|nested] 116+ messages in thread
* [PATCH v2 03/15] dt-bindings: mfd: Add starfive,jh7110-hdmi-subsystem
@ 2026-08-28 13:47 ` Michal Wilczynski
0 siblings, 0 replies; 116+ messages in thread
From: Michal Wilczynski @ 2026-08-28 13:47 UTC (permalink / raw)
To: Vinod Koul, Neil Armstrong, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Andrzej Hajda, Robert Foss, Laurent Pinchart,
Jonas Karlman, Jernej Skrabec, Luca Ceresoli, David Airlie,
Simona Vetter, Maarten Lankhorst, Maxime Ripard,
Thomas Zimmermann, Lee Jones, Andy Yan, Philipp Zabel,
Emil Renner Berthing, Hal Feng, Michael Turquette, Stephen Boyd,
Brian Masney, Heiko Stuebner, Conor Dooley, Paul Walmsley,
Palmer Dabbelt, Albert Ou, Alexandre Ghiti, Dominique Belhachemi
Cc: linux-phy, devicetree, linux-kernel, dri-devel, mfd, linux-clk,
linux-arm-kernel, linux-rockchip, linux-riscv, Icenowy Zheng,
Andy Yan, Marek Szyprowski, Maud Spierings, Graham Markall,
Michal Wilczynski
Add the dt-binding for the StarFive JH7110 HDMI subsystem.
The JH7110 HDMI IP is a monolithic block containing both the digital
controller and analog PHY in a single register space. This binding
defines the parent device, which holds the shared register map and
populates its two children: the PHY and the controller. This is
necessary to resolve a circular clock dependency between the HDMI block
and the VOUT clock generator.
Signed-off-by: Michal Wilczynski <m.wilczynski@samsung.com>
---
.../mfd/starfive,jh7110-hdmi-subsystem.yaml | 116 +++++++++++++++++++++
1 file changed, 116 insertions(+)
diff --git a/Documentation/devicetree/bindings/mfd/starfive,jh7110-hdmi-subsystem.yaml b/Documentation/devicetree/bindings/mfd/starfive,jh7110-hdmi-subsystem.yaml
new file mode 100644
index 0000000000000000000000000000000000000000..01f079160ab8c13c6fa4ce3abaac6607021b3792
--- /dev/null
+++ b/Documentation/devicetree/bindings/mfd/starfive,jh7110-hdmi-subsystem.yaml
@@ -0,0 +1,116 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/mfd/starfive,jh7110-hdmi-subsystem.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: StarFive JH7110 HDMI subsystem
+
+maintainers:
+ - Michal Wilczynski <m.wilczynski@samsung.com>
+
+description:
+ The StarFive JH7110 HDMI block is a monolithic IP containing both
+ the digital controller logic and the analog PHY logic in a single
+ register space.
+
+properties:
+ compatible:
+ const: starfive,jh7110-hdmi-subsystem
+
+ reg:
+ maxItems: 1
+
+ clocks:
+ maxItems: 1
+ description:
+ NoC display bus clock, which gates access to the whole vout
+ register region.
+
+ resets:
+ maxItems: 1
+ description:
+ NoC display bus reset, which gates access to the whole vout
+ register region.
+
+ power-domains:
+ maxItems: 1
+
+required:
+ - compatible
+ - reg
+ - clocks
+ - resets
+ - power-domains
+
+patternProperties:
+ "^phy(@[0-9a-f]+)?$":
+ $ref: /schemas/phy/starfive,jh7110-inno-hdmi-phy.yaml#
+ "^controller(@[0-9a-f]+)?$":
+ $ref: /schemas/display/bridge/starfive,jh7110-inno-hdmi-controller.yaml#
+
+additionalProperties: false
+
+examples:
+ - |
+ #include <dt-bindings/clock/starfive,jh7110-crg.h>
+ #include <dt-bindings/power/starfive,jh7110-pmu.h>
+ #include <dt-bindings/reset/starfive,jh7110-crg.h>
+
+ soc {
+ #address-cells = <1>;
+ #size-cells = <1>;
+
+ hdmi@29590000 {
+ compatible = "starfive,jh7110-hdmi-subsystem";
+ reg = <0x29590000 0x4000>;
+ clocks = <&syscrg JH7110_SYSCLK_NOC_BUS_DISP_AXI>;
+ power-domains = <&pwrc JH7110_PD_VOUT>;
+ resets = <&syscrg JH7110_SYSRST_NOC_BUS_DISP_AXI>;
+
+ controller {
+ compatible = "starfive,jh7110-inno-hdmi-controller";
+ clocks = <&voutcrg JH7110_VOUTCLK_HDMI_TX_SYS>,
+ <&voutcrg JH7110_VOUTCLK_HDMI_TX_MCLK>,
+ <&voutcrg JH7110_VOUTCLK_HDMI_TX_BCLK>,
+ <&hdmi_phy>;
+ clock-names = "sys", "mclk", "bclk", "pclk";
+ interrupts = <99>;
+ phys = <&hdmi_phy>;
+ phy-names = "hdmi-phy";
+ resets = <&voutcrg JH7110_VOUTRST_HDMI_TX_HDMI>;
+ reset-names = "hdmi_tx";
+
+ ports {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ port@0 {
+ reg = <0>;
+
+ endpoint {
+ remote-endpoint = <&dpu_out_dpi0>;
+ };
+ };
+
+ port@1 {
+ reg = <1>;
+
+ endpoint {
+ remote-endpoint = <&hdmi_con_in>;
+ };
+ };
+ };
+ };
+
+ hdmi_phy: phy {
+ compatible = "starfive,jh7110-inno-hdmi-phy";
+ #clock-cells = <0>;
+ clock-output-names = "hdmi_pclk";
+ clocks = <&xin24m>;
+ clock-names = "refoclk";
+ #phy-cells = <0>;
+ };
+ };
+ };
+...
--
2.34.1
--
linux-phy mailing list
linux-phy@lists.infradead.org
https://lists.infradead.org/mailman/listinfo/linux-phy
^ permalink raw reply related [flat|nested] 116+ messages in thread
* [PATCH v2 04/15] drm/bridge: inno-hdmi: Split probe out of bind
2026-08-28 13:47 ` Michal Wilczynski
(?)
(?)
@ 2026-08-28 13:47 ` Michal Wilczynski
-1 siblings, 0 replies; 116+ messages in thread
From: Michal Wilczynski @ 2026-08-28 13:47 UTC (permalink / raw)
To: Vinod Koul, Neil Armstrong, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Andrzej Hajda, Robert Foss, Laurent Pinchart,
Jonas Karlman, Jernej Skrabec, Luca Ceresoli, David Airlie,
Simona Vetter, Maarten Lankhorst, Maxime Ripard,
Thomas Zimmermann, Lee Jones, Andy Yan, Philipp Zabel,
Emil Renner Berthing, Hal Feng, Michael Turquette, Stephen Boyd,
Brian Masney, Heiko Stuebner, Conor Dooley, Paul Walmsley,
Palmer Dabbelt, Albert Ou, Alexandre Ghiti, Dominique Belhachemi
Cc: linux-phy, devicetree, linux-kernel, dri-devel, mfd, linux-clk,
linux-arm-kernel, linux-rockchip, linux-riscv, Icenowy Zheng,
Andy Yan, Marek Szyprowski, Maud Spierings, Graham Markall,
Michal Wilczynski
inno_hdmi_bind() both sets up the bridge and attaches it to a DRM
encoder. A platform whose HDMI controller is a child of a larger device
needs the first half without the second, since it registers as its own
platform driver and lets the DRM core bind the bridge later.
Move the setup into a new exported inno_hdmi_probe(), with a matching
inno_hdmi_remove(), and reduce inno_hdmi_bind() to a wrapper around it.
No functional change intended.
Signed-off-by: Michal Wilczynski <m.wilczynski@samsung.com>
---
drivers/gpu/drm/bridge/inno-hdmi.c | 40 +++++++++++++++++++++++++++++++++-----
include/drm/bridge/inno_hdmi.h | 4 ++++
2 files changed, 39 insertions(+), 5 deletions(-)
diff --git a/drivers/gpu/drm/bridge/inno-hdmi.c b/drivers/gpu/drm/bridge/inno-hdmi.c
index 9a62bf59a4033ae9150d82a6defdd78d1f1f2fcb..12fd208d5e852cdcbdebef7853cb4143c5fe1c0f 100644
--- a/drivers/gpu/drm/bridge/inno-hdmi.c
+++ b/drivers/gpu/drm/bridge/inno-hdmi.c
@@ -1061,11 +1061,24 @@ static struct i2c_adapter *inno_hdmi_i2c_adapter(struct inno_hdmi *hdmi)
return adap;
}
-struct inno_hdmi *inno_hdmi_bind(struct device *dev,
- struct drm_encoder *encoder,
- const struct inno_hdmi_plat_data *plat_data)
+/**
+ * inno_hdmi_probe - Internal helper to perform common setup
+ * @pdev: platform device
+ * @plat_data: SoC-specific platform data
+ *
+ * This function handles all the common hardware setup: allocating the main
+ * struct, mapping registers, getting clocks, initializing the hardware,
+ * setting up the IRQ, and initializing the DDC adapter and bridge struct.
+ * It returns a pointer to the inno_hdmi struct on success, or an ERR_PTR
+ * on failure.
+ *
+ * This function is used by modern, decoupled MFD/glue drivers. It registers
+ * the bridge but does not attach it.
+ */
+struct inno_hdmi *inno_hdmi_probe(struct platform_device *pdev,
+ const struct inno_hdmi_plat_data *plat_data)
{
- struct platform_device *pdev = to_platform_device(dev);
+ struct device *dev = &pdev->dev;
struct inno_hdmi *hdmi;
int irq;
int ret;
@@ -1128,7 +1141,24 @@ struct inno_hdmi *inno_hdmi_bind(struct device *dev,
if (ret)
return ERR_PTR(ret);
- ret = drm_bridge_attach(encoder, &hdmi->bridge, NULL, DRM_BRIDGE_ATTACH_NO_CONNECTOR);
+ return hdmi;
+}
+EXPORT_SYMBOL_GPL(inno_hdmi_probe);
+
+struct inno_hdmi *inno_hdmi_bind(struct device *dev,
+ struct drm_encoder *encoder,
+ const struct inno_hdmi_plat_data *plat_data)
+{
+ struct platform_device *pdev = to_platform_device(dev);
+ struct inno_hdmi *hdmi;
+ int ret;
+
+ hdmi = inno_hdmi_probe(pdev, plat_data);
+ if (IS_ERR(hdmi))
+ return hdmi;
+
+ ret = drm_bridge_attach(encoder, &hdmi->bridge, NULL,
+ DRM_BRIDGE_ATTACH_NO_CONNECTOR);
if (ret)
return ERR_PTR(ret);
diff --git a/include/drm/bridge/inno_hdmi.h b/include/drm/bridge/inno_hdmi.h
index 5bbcaeea94e2a20fd0dc0ae0c6946eb5604bbaf6..81da9d9bcd79db8fe26c6dff4569371e484df608 100644
--- a/include/drm/bridge/inno_hdmi.h
+++ b/include/drm/bridge/inno_hdmi.h
@@ -12,6 +12,7 @@ struct device;
struct drm_encoder;
struct drm_display_mode;
struct inno_hdmi;
+struct platform_device;
struct inno_hdmi_plat_ops {
void (*enable)(struct device *pdev, struct drm_display_mode *mode);
@@ -32,4 +33,7 @@ struct inno_hdmi_plat_data {
struct inno_hdmi *inno_hdmi_bind(struct device *pdev,
struct drm_encoder *encoder,
const struct inno_hdmi_plat_data *plat_data);
+
+struct inno_hdmi *inno_hdmi_probe(struct platform_device *pdev,
+ const struct inno_hdmi_plat_data *plat_data);
#endif /* __INNO_HDMI__ */
--
2.34.1
^ permalink raw reply related [flat|nested] 116+ messages in thread
* [PATCH v2 04/15] drm/bridge: inno-hdmi: Split probe out of bind
@ 2026-08-28 13:47 ` Michal Wilczynski
0 siblings, 0 replies; 116+ messages in thread
From: Michal Wilczynski @ 2026-08-28 13:47 UTC (permalink / raw)
To: Vinod Koul, Neil Armstrong, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Andrzej Hajda, Robert Foss, Laurent Pinchart,
Jonas Karlman, Jernej Skrabec, Luca Ceresoli, David Airlie,
Simona Vetter, Maarten Lankhorst, Maxime Ripard,
Thomas Zimmermann, Lee Jones, Andy Yan, Philipp Zabel,
Emil Renner Berthing, Hal Feng, Michael Turquette, Stephen Boyd,
Brian Masney, Heiko Stuebner, Conor Dooley, Paul Walmsley,
Palmer Dabbelt, Albert Ou, Alexandre Ghiti, Dominique Belhachemi
Cc: devicetree, mfd, linux-kernel, dri-devel, Andy Yan,
Graham Markall, linux-rockchip, linux-phy, Michal Wilczynski,
linux-riscv, Maud Spierings, linux-clk, linux-arm-kernel,
Marek Szyprowski
inno_hdmi_bind() both sets up the bridge and attaches it to a DRM
encoder. A platform whose HDMI controller is a child of a larger device
needs the first half without the second, since it registers as its own
platform driver and lets the DRM core bind the bridge later.
Move the setup into a new exported inno_hdmi_probe(), with a matching
inno_hdmi_remove(), and reduce inno_hdmi_bind() to a wrapper around it.
No functional change intended.
Signed-off-by: Michal Wilczynski <m.wilczynski@samsung.com>
---
drivers/gpu/drm/bridge/inno-hdmi.c | 40 +++++++++++++++++++++++++++++++++-----
include/drm/bridge/inno_hdmi.h | 4 ++++
2 files changed, 39 insertions(+), 5 deletions(-)
diff --git a/drivers/gpu/drm/bridge/inno-hdmi.c b/drivers/gpu/drm/bridge/inno-hdmi.c
index 9a62bf59a4033ae9150d82a6defdd78d1f1f2fcb..12fd208d5e852cdcbdebef7853cb4143c5fe1c0f 100644
--- a/drivers/gpu/drm/bridge/inno-hdmi.c
+++ b/drivers/gpu/drm/bridge/inno-hdmi.c
@@ -1061,11 +1061,24 @@ static struct i2c_adapter *inno_hdmi_i2c_adapter(struct inno_hdmi *hdmi)
return adap;
}
-struct inno_hdmi *inno_hdmi_bind(struct device *dev,
- struct drm_encoder *encoder,
- const struct inno_hdmi_plat_data *plat_data)
+/**
+ * inno_hdmi_probe - Internal helper to perform common setup
+ * @pdev: platform device
+ * @plat_data: SoC-specific platform data
+ *
+ * This function handles all the common hardware setup: allocating the main
+ * struct, mapping registers, getting clocks, initializing the hardware,
+ * setting up the IRQ, and initializing the DDC adapter and bridge struct.
+ * It returns a pointer to the inno_hdmi struct on success, or an ERR_PTR
+ * on failure.
+ *
+ * This function is used by modern, decoupled MFD/glue drivers. It registers
+ * the bridge but does not attach it.
+ */
+struct inno_hdmi *inno_hdmi_probe(struct platform_device *pdev,
+ const struct inno_hdmi_plat_data *plat_data)
{
- struct platform_device *pdev = to_platform_device(dev);
+ struct device *dev = &pdev->dev;
struct inno_hdmi *hdmi;
int irq;
int ret;
@@ -1128,7 +1141,24 @@ struct inno_hdmi *inno_hdmi_bind(struct device *dev,
if (ret)
return ERR_PTR(ret);
- ret = drm_bridge_attach(encoder, &hdmi->bridge, NULL, DRM_BRIDGE_ATTACH_NO_CONNECTOR);
+ return hdmi;
+}
+EXPORT_SYMBOL_GPL(inno_hdmi_probe);
+
+struct inno_hdmi *inno_hdmi_bind(struct device *dev,
+ struct drm_encoder *encoder,
+ const struct inno_hdmi_plat_data *plat_data)
+{
+ struct platform_device *pdev = to_platform_device(dev);
+ struct inno_hdmi *hdmi;
+ int ret;
+
+ hdmi = inno_hdmi_probe(pdev, plat_data);
+ if (IS_ERR(hdmi))
+ return hdmi;
+
+ ret = drm_bridge_attach(encoder, &hdmi->bridge, NULL,
+ DRM_BRIDGE_ATTACH_NO_CONNECTOR);
if (ret)
return ERR_PTR(ret);
diff --git a/include/drm/bridge/inno_hdmi.h b/include/drm/bridge/inno_hdmi.h
index 5bbcaeea94e2a20fd0dc0ae0c6946eb5604bbaf6..81da9d9bcd79db8fe26c6dff4569371e484df608 100644
--- a/include/drm/bridge/inno_hdmi.h
+++ b/include/drm/bridge/inno_hdmi.h
@@ -12,6 +12,7 @@ struct device;
struct drm_encoder;
struct drm_display_mode;
struct inno_hdmi;
+struct platform_device;
struct inno_hdmi_plat_ops {
void (*enable)(struct device *pdev, struct drm_display_mode *mode);
@@ -32,4 +33,7 @@ struct inno_hdmi_plat_data {
struct inno_hdmi *inno_hdmi_bind(struct device *pdev,
struct drm_encoder *encoder,
const struct inno_hdmi_plat_data *plat_data);
+
+struct inno_hdmi *inno_hdmi_probe(struct platform_device *pdev,
+ const struct inno_hdmi_plat_data *plat_data);
#endif /* __INNO_HDMI__ */
--
2.34.1
_______________________________________________
linux-riscv mailing list
linux-riscv@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-riscv
^ permalink raw reply related [flat|nested] 116+ messages in thread
* [PATCH v2 04/15] drm/bridge: inno-hdmi: Split probe out of bind
@ 2026-08-28 13:47 ` Michal Wilczynski
0 siblings, 0 replies; 116+ messages in thread
From: Michal Wilczynski @ 2026-08-28 13:47 UTC (permalink / raw)
To: Vinod Koul, Neil Armstrong, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Andrzej Hajda, Robert Foss, Laurent Pinchart,
Jonas Karlman, Jernej Skrabec, Luca Ceresoli, David Airlie,
Simona Vetter, Maarten Lankhorst, Maxime Ripard,
Thomas Zimmermann, Lee Jones, Andy Yan, Philipp Zabel,
Emil Renner Berthing, Hal Feng, Michael Turquette, Stephen Boyd,
Brian Masney, Heiko Stuebner, Conor Dooley, Paul Walmsley,
Palmer Dabbelt, Albert Ou, Alexandre Ghiti, Dominique Belhachemi
Cc: linux-phy, devicetree, linux-kernel, dri-devel, mfd, linux-clk,
linux-arm-kernel, linux-rockchip, linux-riscv, Icenowy Zheng,
Andy Yan, Marek Szyprowski, Maud Spierings, Graham Markall,
Michal Wilczynski
inno_hdmi_bind() both sets up the bridge and attaches it to a DRM
encoder. A platform whose HDMI controller is a child of a larger device
needs the first half without the second, since it registers as its own
platform driver and lets the DRM core bind the bridge later.
Move the setup into a new exported inno_hdmi_probe(), with a matching
inno_hdmi_remove(), and reduce inno_hdmi_bind() to a wrapper around it.
No functional change intended.
Signed-off-by: Michal Wilczynski <m.wilczynski@samsung.com>
---
drivers/gpu/drm/bridge/inno-hdmi.c | 40 +++++++++++++++++++++++++++++++++-----
include/drm/bridge/inno_hdmi.h | 4 ++++
2 files changed, 39 insertions(+), 5 deletions(-)
diff --git a/drivers/gpu/drm/bridge/inno-hdmi.c b/drivers/gpu/drm/bridge/inno-hdmi.c
index 9a62bf59a4033ae9150d82a6defdd78d1f1f2fcb..12fd208d5e852cdcbdebef7853cb4143c5fe1c0f 100644
--- a/drivers/gpu/drm/bridge/inno-hdmi.c
+++ b/drivers/gpu/drm/bridge/inno-hdmi.c
@@ -1061,11 +1061,24 @@ static struct i2c_adapter *inno_hdmi_i2c_adapter(struct inno_hdmi *hdmi)
return adap;
}
-struct inno_hdmi *inno_hdmi_bind(struct device *dev,
- struct drm_encoder *encoder,
- const struct inno_hdmi_plat_data *plat_data)
+/**
+ * inno_hdmi_probe - Internal helper to perform common setup
+ * @pdev: platform device
+ * @plat_data: SoC-specific platform data
+ *
+ * This function handles all the common hardware setup: allocating the main
+ * struct, mapping registers, getting clocks, initializing the hardware,
+ * setting up the IRQ, and initializing the DDC adapter and bridge struct.
+ * It returns a pointer to the inno_hdmi struct on success, or an ERR_PTR
+ * on failure.
+ *
+ * This function is used by modern, decoupled MFD/glue drivers. It registers
+ * the bridge but does not attach it.
+ */
+struct inno_hdmi *inno_hdmi_probe(struct platform_device *pdev,
+ const struct inno_hdmi_plat_data *plat_data)
{
- struct platform_device *pdev = to_platform_device(dev);
+ struct device *dev = &pdev->dev;
struct inno_hdmi *hdmi;
int irq;
int ret;
@@ -1128,7 +1141,24 @@ struct inno_hdmi *inno_hdmi_bind(struct device *dev,
if (ret)
return ERR_PTR(ret);
- ret = drm_bridge_attach(encoder, &hdmi->bridge, NULL, DRM_BRIDGE_ATTACH_NO_CONNECTOR);
+ return hdmi;
+}
+EXPORT_SYMBOL_GPL(inno_hdmi_probe);
+
+struct inno_hdmi *inno_hdmi_bind(struct device *dev,
+ struct drm_encoder *encoder,
+ const struct inno_hdmi_plat_data *plat_data)
+{
+ struct platform_device *pdev = to_platform_device(dev);
+ struct inno_hdmi *hdmi;
+ int ret;
+
+ hdmi = inno_hdmi_probe(pdev, plat_data);
+ if (IS_ERR(hdmi))
+ return hdmi;
+
+ ret = drm_bridge_attach(encoder, &hdmi->bridge, NULL,
+ DRM_BRIDGE_ATTACH_NO_CONNECTOR);
if (ret)
return ERR_PTR(ret);
diff --git a/include/drm/bridge/inno_hdmi.h b/include/drm/bridge/inno_hdmi.h
index 5bbcaeea94e2a20fd0dc0ae0c6946eb5604bbaf6..81da9d9bcd79db8fe26c6dff4569371e484df608 100644
--- a/include/drm/bridge/inno_hdmi.h
+++ b/include/drm/bridge/inno_hdmi.h
@@ -12,6 +12,7 @@ struct device;
struct drm_encoder;
struct drm_display_mode;
struct inno_hdmi;
+struct platform_device;
struct inno_hdmi_plat_ops {
void (*enable)(struct device *pdev, struct drm_display_mode *mode);
@@ -32,4 +33,7 @@ struct inno_hdmi_plat_data {
struct inno_hdmi *inno_hdmi_bind(struct device *pdev,
struct drm_encoder *encoder,
const struct inno_hdmi_plat_data *plat_data);
+
+struct inno_hdmi *inno_hdmi_probe(struct platform_device *pdev,
+ const struct inno_hdmi_plat_data *plat_data);
#endif /* __INNO_HDMI__ */
--
2.34.1
_______________________________________________
Linux-rockchip mailing list
Linux-rockchip@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-rockchip
^ permalink raw reply related [flat|nested] 116+ messages in thread
* [PATCH v2 04/15] drm/bridge: inno-hdmi: Split probe out of bind
@ 2026-08-28 13:47 ` Michal Wilczynski
0 siblings, 0 replies; 116+ messages in thread
From: Michal Wilczynski @ 2026-08-28 13:47 UTC (permalink / raw)
To: Vinod Koul, Neil Armstrong, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Andrzej Hajda, Robert Foss, Laurent Pinchart,
Jonas Karlman, Jernej Skrabec, Luca Ceresoli, David Airlie,
Simona Vetter, Maarten Lankhorst, Maxime Ripard,
Thomas Zimmermann, Lee Jones, Andy Yan, Philipp Zabel,
Emil Renner Berthing, Hal Feng, Michael Turquette, Stephen Boyd,
Brian Masney, Heiko Stuebner, Conor Dooley, Paul Walmsley,
Palmer Dabbelt, Albert Ou, Alexandre Ghiti, Dominique Belhachemi
Cc: linux-phy, devicetree, linux-kernel, dri-devel, mfd, linux-clk,
linux-arm-kernel, linux-rockchip, linux-riscv, Icenowy Zheng,
Andy Yan, Marek Szyprowski, Maud Spierings, Graham Markall,
Michal Wilczynski
inno_hdmi_bind() both sets up the bridge and attaches it to a DRM
encoder. A platform whose HDMI controller is a child of a larger device
needs the first half without the second, since it registers as its own
platform driver and lets the DRM core bind the bridge later.
Move the setup into a new exported inno_hdmi_probe(), with a matching
inno_hdmi_remove(), and reduce inno_hdmi_bind() to a wrapper around it.
No functional change intended.
Signed-off-by: Michal Wilczynski <m.wilczynski@samsung.com>
---
drivers/gpu/drm/bridge/inno-hdmi.c | 40 +++++++++++++++++++++++++++++++++-----
include/drm/bridge/inno_hdmi.h | 4 ++++
2 files changed, 39 insertions(+), 5 deletions(-)
diff --git a/drivers/gpu/drm/bridge/inno-hdmi.c b/drivers/gpu/drm/bridge/inno-hdmi.c
index 9a62bf59a4033ae9150d82a6defdd78d1f1f2fcb..12fd208d5e852cdcbdebef7853cb4143c5fe1c0f 100644
--- a/drivers/gpu/drm/bridge/inno-hdmi.c
+++ b/drivers/gpu/drm/bridge/inno-hdmi.c
@@ -1061,11 +1061,24 @@ static struct i2c_adapter *inno_hdmi_i2c_adapter(struct inno_hdmi *hdmi)
return adap;
}
-struct inno_hdmi *inno_hdmi_bind(struct device *dev,
- struct drm_encoder *encoder,
- const struct inno_hdmi_plat_data *plat_data)
+/**
+ * inno_hdmi_probe - Internal helper to perform common setup
+ * @pdev: platform device
+ * @plat_data: SoC-specific platform data
+ *
+ * This function handles all the common hardware setup: allocating the main
+ * struct, mapping registers, getting clocks, initializing the hardware,
+ * setting up the IRQ, and initializing the DDC adapter and bridge struct.
+ * It returns a pointer to the inno_hdmi struct on success, or an ERR_PTR
+ * on failure.
+ *
+ * This function is used by modern, decoupled MFD/glue drivers. It registers
+ * the bridge but does not attach it.
+ */
+struct inno_hdmi *inno_hdmi_probe(struct platform_device *pdev,
+ const struct inno_hdmi_plat_data *plat_data)
{
- struct platform_device *pdev = to_platform_device(dev);
+ struct device *dev = &pdev->dev;
struct inno_hdmi *hdmi;
int irq;
int ret;
@@ -1128,7 +1141,24 @@ struct inno_hdmi *inno_hdmi_bind(struct device *dev,
if (ret)
return ERR_PTR(ret);
- ret = drm_bridge_attach(encoder, &hdmi->bridge, NULL, DRM_BRIDGE_ATTACH_NO_CONNECTOR);
+ return hdmi;
+}
+EXPORT_SYMBOL_GPL(inno_hdmi_probe);
+
+struct inno_hdmi *inno_hdmi_bind(struct device *dev,
+ struct drm_encoder *encoder,
+ const struct inno_hdmi_plat_data *plat_data)
+{
+ struct platform_device *pdev = to_platform_device(dev);
+ struct inno_hdmi *hdmi;
+ int ret;
+
+ hdmi = inno_hdmi_probe(pdev, plat_data);
+ if (IS_ERR(hdmi))
+ return hdmi;
+
+ ret = drm_bridge_attach(encoder, &hdmi->bridge, NULL,
+ DRM_BRIDGE_ATTACH_NO_CONNECTOR);
if (ret)
return ERR_PTR(ret);
diff --git a/include/drm/bridge/inno_hdmi.h b/include/drm/bridge/inno_hdmi.h
index 5bbcaeea94e2a20fd0dc0ae0c6946eb5604bbaf6..81da9d9bcd79db8fe26c6dff4569371e484df608 100644
--- a/include/drm/bridge/inno_hdmi.h
+++ b/include/drm/bridge/inno_hdmi.h
@@ -12,6 +12,7 @@ struct device;
struct drm_encoder;
struct drm_display_mode;
struct inno_hdmi;
+struct platform_device;
struct inno_hdmi_plat_ops {
void (*enable)(struct device *pdev, struct drm_display_mode *mode);
@@ -32,4 +33,7 @@ struct inno_hdmi_plat_data {
struct inno_hdmi *inno_hdmi_bind(struct device *pdev,
struct drm_encoder *encoder,
const struct inno_hdmi_plat_data *plat_data);
+
+struct inno_hdmi *inno_hdmi_probe(struct platform_device *pdev,
+ const struct inno_hdmi_plat_data *plat_data);
#endif /* __INNO_HDMI__ */
--
2.34.1
--
linux-phy mailing list
linux-phy@lists.infradead.org
https://lists.infradead.org/mailman/listinfo/linux-phy
^ permalink raw reply related [flat|nested] 116+ messages in thread
* [PATCH v2 05/15] drm/bridge: inno-hdmi: Allow the register map to come from a parent
2026-08-28 13:47 ` Michal Wilczynski
(?)
(?)
@ 2026-08-28 13:47 ` Michal Wilczynski
-1 siblings, 0 replies; 116+ messages in thread
From: Michal Wilczynski @ 2026-08-28 13:47 UTC (permalink / raw)
To: Vinod Koul, Neil Armstrong, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Andrzej Hajda, Robert Foss, Laurent Pinchart,
Jonas Karlman, Jernej Skrabec, Luca Ceresoli, David Airlie,
Simona Vetter, Maarten Lankhorst, Maxime Ripard,
Thomas Zimmermann, Lee Jones, Andy Yan, Philipp Zabel,
Emil Renner Berthing, Hal Feng, Michael Turquette, Stephen Boyd,
Brian Masney, Heiko Stuebner, Conor Dooley, Paul Walmsley,
Palmer Dabbelt, Albert Ou, Alexandre Ghiti, Dominique Belhachemi
Cc: linux-phy, devicetree, linux-kernel, dri-devel, mfd, linux-clk,
linux-arm-kernel, linux-rockchip, linux-riscv, Icenowy Zheng,
Andy Yan, Marek Szyprowski, Maud Spierings, Graham Markall,
Michal Wilczynski
On some SoCs the HDMI controller does not own its register window. The
StarFive JH7110 documents one 64 KB block, u0_hdmitx, that holds both
the controller and the PHY, so the parent device maps it and owns the
regmap while the two children share it.
Use a regmap supplied by the parent device when there is one, and keep
mapping our own resource when there is not, so platforms that own their
register window are unaffected.
Signed-off-by: Michal Wilczynski <m.wilczynski@samsung.com>
---
drivers/gpu/drm/bridge/inno-hdmi.c | 29 ++++++++++++++++++++++++++---
1 file changed, 26 insertions(+), 3 deletions(-)
diff --git a/drivers/gpu/drm/bridge/inno-hdmi.c b/drivers/gpu/drm/bridge/inno-hdmi.c
index 12fd208d5e852cdcbdebef7853cb4143c5fe1c0f..ebc5093f13ac4f263b903fb727629dfb83d051e1 100644
--- a/drivers/gpu/drm/bridge/inno-hdmi.c
+++ b/drivers/gpu/drm/bridge/inno-hdmi.c
@@ -397,6 +397,7 @@ struct inno_hdmi {
struct clk *pclk;
struct clk *refclk;
void __iomem *regs;
+ struct regmap *regmap;
struct regmap *grf;
struct inno_hdmi_i2c *i2c;
@@ -470,11 +471,23 @@ static int inno_hdmi_find_phy_config(struct inno_hdmi *hdmi,
static inline u8 hdmi_readb(struct inno_hdmi *hdmi, u16 offset)
{
+ u32 val;
+
+ if (hdmi->regmap) {
+ regmap_read(hdmi->regmap, offset * 4, &val);
+ return val;
+ }
+
return readl_relaxed(hdmi->regs + (offset) * 0x04);
}
static inline void hdmi_writeb(struct inno_hdmi *hdmi, u16 offset, u32 val)
{
+ if (hdmi->regmap) {
+ regmap_write(hdmi->regmap, offset * 4, val);
+ return;
+ }
+
writel_relaxed(val, hdmi->regs + (offset) * 0x04);
}
@@ -1095,9 +1108,19 @@ struct inno_hdmi *inno_hdmi_probe(struct platform_device *pdev,
hdmi->dev = dev;
hdmi->plat_data = plat_data;
- hdmi->regs = devm_platform_ioremap_resource(pdev, 0);
- if (IS_ERR(hdmi->regs))
- return ERR_CAST(hdmi->regs);
+ /*
+ * On platforms where the controller shares a register space with
+ * other blocks, the parent owns the regmap. Fall back to mapping
+ * our own resource where it does not.
+ */
+ if (dev->parent)
+ hdmi->regmap = dev_get_regmap(dev->parent, NULL);
+
+ if (!hdmi->regmap) {
+ hdmi->regs = devm_platform_ioremap_resource(pdev, 0);
+ if (IS_ERR(hdmi->regs))
+ return ERR_CAST(hdmi->regs);
+ }
hdmi->pclk = devm_clk_get_enabled(hdmi->dev, "pclk");
if (IS_ERR(hdmi->pclk)) {
--
2.34.1
^ permalink raw reply related [flat|nested] 116+ messages in thread
* [PATCH v2 05/15] drm/bridge: inno-hdmi: Allow the register map to come from a parent
@ 2026-08-28 13:47 ` Michal Wilczynski
0 siblings, 0 replies; 116+ messages in thread
From: Michal Wilczynski @ 2026-08-28 13:47 UTC (permalink / raw)
To: Vinod Koul, Neil Armstrong, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Andrzej Hajda, Robert Foss, Laurent Pinchart,
Jonas Karlman, Jernej Skrabec, Luca Ceresoli, David Airlie,
Simona Vetter, Maarten Lankhorst, Maxime Ripard,
Thomas Zimmermann, Lee Jones, Andy Yan, Philipp Zabel,
Emil Renner Berthing, Hal Feng, Michael Turquette, Stephen Boyd,
Brian Masney, Heiko Stuebner, Conor Dooley, Paul Walmsley,
Palmer Dabbelt, Albert Ou, Alexandre Ghiti, Dominique Belhachemi
Cc: devicetree, mfd, linux-kernel, dri-devel, Andy Yan,
Graham Markall, linux-rockchip, linux-phy, Michal Wilczynski,
linux-riscv, Maud Spierings, linux-clk, linux-arm-kernel,
Marek Szyprowski
On some SoCs the HDMI controller does not own its register window. The
StarFive JH7110 documents one 64 KB block, u0_hdmitx, that holds both
the controller and the PHY, so the parent device maps it and owns the
regmap while the two children share it.
Use a regmap supplied by the parent device when there is one, and keep
mapping our own resource when there is not, so platforms that own their
register window are unaffected.
Signed-off-by: Michal Wilczynski <m.wilczynski@samsung.com>
---
drivers/gpu/drm/bridge/inno-hdmi.c | 29 ++++++++++++++++++++++++++---
1 file changed, 26 insertions(+), 3 deletions(-)
diff --git a/drivers/gpu/drm/bridge/inno-hdmi.c b/drivers/gpu/drm/bridge/inno-hdmi.c
index 12fd208d5e852cdcbdebef7853cb4143c5fe1c0f..ebc5093f13ac4f263b903fb727629dfb83d051e1 100644
--- a/drivers/gpu/drm/bridge/inno-hdmi.c
+++ b/drivers/gpu/drm/bridge/inno-hdmi.c
@@ -397,6 +397,7 @@ struct inno_hdmi {
struct clk *pclk;
struct clk *refclk;
void __iomem *regs;
+ struct regmap *regmap;
struct regmap *grf;
struct inno_hdmi_i2c *i2c;
@@ -470,11 +471,23 @@ static int inno_hdmi_find_phy_config(struct inno_hdmi *hdmi,
static inline u8 hdmi_readb(struct inno_hdmi *hdmi, u16 offset)
{
+ u32 val;
+
+ if (hdmi->regmap) {
+ regmap_read(hdmi->regmap, offset * 4, &val);
+ return val;
+ }
+
return readl_relaxed(hdmi->regs + (offset) * 0x04);
}
static inline void hdmi_writeb(struct inno_hdmi *hdmi, u16 offset, u32 val)
{
+ if (hdmi->regmap) {
+ regmap_write(hdmi->regmap, offset * 4, val);
+ return;
+ }
+
writel_relaxed(val, hdmi->regs + (offset) * 0x04);
}
@@ -1095,9 +1108,19 @@ struct inno_hdmi *inno_hdmi_probe(struct platform_device *pdev,
hdmi->dev = dev;
hdmi->plat_data = plat_data;
- hdmi->regs = devm_platform_ioremap_resource(pdev, 0);
- if (IS_ERR(hdmi->regs))
- return ERR_CAST(hdmi->regs);
+ /*
+ * On platforms where the controller shares a register space with
+ * other blocks, the parent owns the regmap. Fall back to mapping
+ * our own resource where it does not.
+ */
+ if (dev->parent)
+ hdmi->regmap = dev_get_regmap(dev->parent, NULL);
+
+ if (!hdmi->regmap) {
+ hdmi->regs = devm_platform_ioremap_resource(pdev, 0);
+ if (IS_ERR(hdmi->regs))
+ return ERR_CAST(hdmi->regs);
+ }
hdmi->pclk = devm_clk_get_enabled(hdmi->dev, "pclk");
if (IS_ERR(hdmi->pclk)) {
--
2.34.1
_______________________________________________
linux-riscv mailing list
linux-riscv@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-riscv
^ permalink raw reply related [flat|nested] 116+ messages in thread
* [PATCH v2 05/15] drm/bridge: inno-hdmi: Allow the register map to come from a parent
@ 2026-08-28 13:47 ` Michal Wilczynski
0 siblings, 0 replies; 116+ messages in thread
From: Michal Wilczynski @ 2026-08-28 13:47 UTC (permalink / raw)
To: Vinod Koul, Neil Armstrong, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Andrzej Hajda, Robert Foss, Laurent Pinchart,
Jonas Karlman, Jernej Skrabec, Luca Ceresoli, David Airlie,
Simona Vetter, Maarten Lankhorst, Maxime Ripard,
Thomas Zimmermann, Lee Jones, Andy Yan, Philipp Zabel,
Emil Renner Berthing, Hal Feng, Michael Turquette, Stephen Boyd,
Brian Masney, Heiko Stuebner, Conor Dooley, Paul Walmsley,
Palmer Dabbelt, Albert Ou, Alexandre Ghiti, Dominique Belhachemi
Cc: linux-phy, devicetree, linux-kernel, dri-devel, mfd, linux-clk,
linux-arm-kernel, linux-rockchip, linux-riscv, Icenowy Zheng,
Andy Yan, Marek Szyprowski, Maud Spierings, Graham Markall,
Michal Wilczynski
On some SoCs the HDMI controller does not own its register window. The
StarFive JH7110 documents one 64 KB block, u0_hdmitx, that holds both
the controller and the PHY, so the parent device maps it and owns the
regmap while the two children share it.
Use a regmap supplied by the parent device when there is one, and keep
mapping our own resource when there is not, so platforms that own their
register window are unaffected.
Signed-off-by: Michal Wilczynski <m.wilczynski@samsung.com>
---
drivers/gpu/drm/bridge/inno-hdmi.c | 29 ++++++++++++++++++++++++++---
1 file changed, 26 insertions(+), 3 deletions(-)
diff --git a/drivers/gpu/drm/bridge/inno-hdmi.c b/drivers/gpu/drm/bridge/inno-hdmi.c
index 12fd208d5e852cdcbdebef7853cb4143c5fe1c0f..ebc5093f13ac4f263b903fb727629dfb83d051e1 100644
--- a/drivers/gpu/drm/bridge/inno-hdmi.c
+++ b/drivers/gpu/drm/bridge/inno-hdmi.c
@@ -397,6 +397,7 @@ struct inno_hdmi {
struct clk *pclk;
struct clk *refclk;
void __iomem *regs;
+ struct regmap *regmap;
struct regmap *grf;
struct inno_hdmi_i2c *i2c;
@@ -470,11 +471,23 @@ static int inno_hdmi_find_phy_config(struct inno_hdmi *hdmi,
static inline u8 hdmi_readb(struct inno_hdmi *hdmi, u16 offset)
{
+ u32 val;
+
+ if (hdmi->regmap) {
+ regmap_read(hdmi->regmap, offset * 4, &val);
+ return val;
+ }
+
return readl_relaxed(hdmi->regs + (offset) * 0x04);
}
static inline void hdmi_writeb(struct inno_hdmi *hdmi, u16 offset, u32 val)
{
+ if (hdmi->regmap) {
+ regmap_write(hdmi->regmap, offset * 4, val);
+ return;
+ }
+
writel_relaxed(val, hdmi->regs + (offset) * 0x04);
}
@@ -1095,9 +1108,19 @@ struct inno_hdmi *inno_hdmi_probe(struct platform_device *pdev,
hdmi->dev = dev;
hdmi->plat_data = plat_data;
- hdmi->regs = devm_platform_ioremap_resource(pdev, 0);
- if (IS_ERR(hdmi->regs))
- return ERR_CAST(hdmi->regs);
+ /*
+ * On platforms where the controller shares a register space with
+ * other blocks, the parent owns the regmap. Fall back to mapping
+ * our own resource where it does not.
+ */
+ if (dev->parent)
+ hdmi->regmap = dev_get_regmap(dev->parent, NULL);
+
+ if (!hdmi->regmap) {
+ hdmi->regs = devm_platform_ioremap_resource(pdev, 0);
+ if (IS_ERR(hdmi->regs))
+ return ERR_CAST(hdmi->regs);
+ }
hdmi->pclk = devm_clk_get_enabled(hdmi->dev, "pclk");
if (IS_ERR(hdmi->pclk)) {
--
2.34.1
_______________________________________________
Linux-rockchip mailing list
Linux-rockchip@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-rockchip
^ permalink raw reply related [flat|nested] 116+ messages in thread
* [PATCH v2 05/15] drm/bridge: inno-hdmi: Allow the register map to come from a parent
@ 2026-08-28 13:47 ` Michal Wilczynski
0 siblings, 0 replies; 116+ messages in thread
From: Michal Wilczynski @ 2026-08-28 13:47 UTC (permalink / raw)
To: Vinod Koul, Neil Armstrong, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Andrzej Hajda, Robert Foss, Laurent Pinchart,
Jonas Karlman, Jernej Skrabec, Luca Ceresoli, David Airlie,
Simona Vetter, Maarten Lankhorst, Maxime Ripard,
Thomas Zimmermann, Lee Jones, Andy Yan, Philipp Zabel,
Emil Renner Berthing, Hal Feng, Michael Turquette, Stephen Boyd,
Brian Masney, Heiko Stuebner, Conor Dooley, Paul Walmsley,
Palmer Dabbelt, Albert Ou, Alexandre Ghiti, Dominique Belhachemi
Cc: linux-phy, devicetree, linux-kernel, dri-devel, mfd, linux-clk,
linux-arm-kernel, linux-rockchip, linux-riscv, Icenowy Zheng,
Andy Yan, Marek Szyprowski, Maud Spierings, Graham Markall,
Michal Wilczynski
On some SoCs the HDMI controller does not own its register window. The
StarFive JH7110 documents one 64 KB block, u0_hdmitx, that holds both
the controller and the PHY, so the parent device maps it and owns the
regmap while the two children share it.
Use a regmap supplied by the parent device when there is one, and keep
mapping our own resource when there is not, so platforms that own their
register window are unaffected.
Signed-off-by: Michal Wilczynski <m.wilczynski@samsung.com>
---
drivers/gpu/drm/bridge/inno-hdmi.c | 29 ++++++++++++++++++++++++++---
1 file changed, 26 insertions(+), 3 deletions(-)
diff --git a/drivers/gpu/drm/bridge/inno-hdmi.c b/drivers/gpu/drm/bridge/inno-hdmi.c
index 12fd208d5e852cdcbdebef7853cb4143c5fe1c0f..ebc5093f13ac4f263b903fb727629dfb83d051e1 100644
--- a/drivers/gpu/drm/bridge/inno-hdmi.c
+++ b/drivers/gpu/drm/bridge/inno-hdmi.c
@@ -397,6 +397,7 @@ struct inno_hdmi {
struct clk *pclk;
struct clk *refclk;
void __iomem *regs;
+ struct regmap *regmap;
struct regmap *grf;
struct inno_hdmi_i2c *i2c;
@@ -470,11 +471,23 @@ static int inno_hdmi_find_phy_config(struct inno_hdmi *hdmi,
static inline u8 hdmi_readb(struct inno_hdmi *hdmi, u16 offset)
{
+ u32 val;
+
+ if (hdmi->regmap) {
+ regmap_read(hdmi->regmap, offset * 4, &val);
+ return val;
+ }
+
return readl_relaxed(hdmi->regs + (offset) * 0x04);
}
static inline void hdmi_writeb(struct inno_hdmi *hdmi, u16 offset, u32 val)
{
+ if (hdmi->regmap) {
+ regmap_write(hdmi->regmap, offset * 4, val);
+ return;
+ }
+
writel_relaxed(val, hdmi->regs + (offset) * 0x04);
}
@@ -1095,9 +1108,19 @@ struct inno_hdmi *inno_hdmi_probe(struct platform_device *pdev,
hdmi->dev = dev;
hdmi->plat_data = plat_data;
- hdmi->regs = devm_platform_ioremap_resource(pdev, 0);
- if (IS_ERR(hdmi->regs))
- return ERR_CAST(hdmi->regs);
+ /*
+ * On platforms where the controller shares a register space with
+ * other blocks, the parent owns the regmap. Fall back to mapping
+ * our own resource where it does not.
+ */
+ if (dev->parent)
+ hdmi->regmap = dev_get_regmap(dev->parent, NULL);
+
+ if (!hdmi->regmap) {
+ hdmi->regs = devm_platform_ioremap_resource(pdev, 0);
+ if (IS_ERR(hdmi->regs))
+ return ERR_CAST(hdmi->regs);
+ }
hdmi->pclk = devm_clk_get_enabled(hdmi->dev, "pclk");
if (IS_ERR(hdmi->pclk)) {
--
2.34.1
--
linux-phy mailing list
linux-phy@lists.infradead.org
https://lists.infradead.org/mailman/listinfo/linux-phy
^ permalink raw reply related [flat|nested] 116+ messages in thread
* [PATCH v2 06/15] drm/bridge: inno-hdmi: Add .disable platform operation
2026-08-28 13:47 ` Michal Wilczynski
(?)
(?)
@ 2026-08-28 13:47 ` Michal Wilczynski
-1 siblings, 0 replies; 116+ messages in thread
From: Michal Wilczynski @ 2026-08-28 13:47 UTC (permalink / raw)
To: Vinod Koul, Neil Armstrong, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Andrzej Hajda, Robert Foss, Laurent Pinchart,
Jonas Karlman, Jernej Skrabec, Luca Ceresoli, David Airlie,
Simona Vetter, Maarten Lankhorst, Maxime Ripard,
Thomas Zimmermann, Lee Jones, Andy Yan, Philipp Zabel,
Emil Renner Berthing, Hal Feng, Michael Turquette, Stephen Boyd,
Brian Masney, Heiko Stuebner, Conor Dooley, Paul Walmsley,
Palmer Dabbelt, Albert Ou, Alexandre Ghiti, Dominique Belhachemi
Cc: linux-phy, devicetree, linux-kernel, dri-devel, mfd, linux-clk,
linux-arm-kernel, linux-rockchip, linux-riscv, Icenowy Zheng,
Andy Yan, Marek Szyprowski, Maud Spierings, Graham Markall,
Michal Wilczynski
The Innosilicon HDMI driver supports platform-specific behavior through
the `inno_hdmi_plat_ops`. While it provides an `.enable` hook for
platform-specific power up sequences (like enabling PHYs), it lacks a
corresponding hook for power down.
This patch adds a new `.disable` op to the `inno_hdmi_plat_ops` struct
and calls it at the beginning of `inno_hdmi_bridge_atomic_disable()`.
This allows platform specific drivers, such as the StarFive JH7110,
to implement their own power down sequence (e.g., calling
phy_power_off() and clk_disable_unprepare()).
Signed-off-by: Michal Wilczynski <m.wilczynski@samsung.com>
---
drivers/gpu/drm/bridge/inno-hdmi.c | 4 ++++
include/drm/bridge/inno_hdmi.h | 1 +
2 files changed, 5 insertions(+)
diff --git a/drivers/gpu/drm/bridge/inno-hdmi.c b/drivers/gpu/drm/bridge/inno-hdmi.c
index ebc5093f13ac4f263b903fb727629dfb83d051e1..952cc55c10f7dc07de6ebe943aae3e54df2edc8d 100644
--- a/drivers/gpu/drm/bridge/inno-hdmi.c
+++ b/drivers/gpu/drm/bridge/inno-hdmi.c
@@ -884,6 +884,10 @@ static void inno_hdmi_bridge_atomic_disable(struct drm_bridge *bridge,
struct drm_atomic_commit *state)
{
struct inno_hdmi *hdmi = bridge_to_inno_hdmi(bridge);
+ const struct inno_hdmi_plat_ops *plat_ops = hdmi->plat_data->ops;
+
+ if (plat_ops && plat_ops->disable)
+ plat_ops->disable(hdmi->dev);
inno_hdmi_standby(hdmi);
}
diff --git a/include/drm/bridge/inno_hdmi.h b/include/drm/bridge/inno_hdmi.h
index 81da9d9bcd79db8fe26c6dff4569371e484df608..5fca651c56b056d814124aa9c7e91aa7fd7ed1cd 100644
--- a/include/drm/bridge/inno_hdmi.h
+++ b/include/drm/bridge/inno_hdmi.h
@@ -16,6 +16,7 @@ struct platform_device;
struct inno_hdmi_plat_ops {
void (*enable)(struct device *pdev, struct drm_display_mode *mode);
+ void (*disable)(struct device *pdev);
};
struct inno_hdmi_phy_config {
--
2.34.1
^ permalink raw reply related [flat|nested] 116+ messages in thread
* [PATCH v2 06/15] drm/bridge: inno-hdmi: Add .disable platform operation
@ 2026-08-28 13:47 ` Michal Wilczynski
0 siblings, 0 replies; 116+ messages in thread
From: Michal Wilczynski @ 2026-08-28 13:47 UTC (permalink / raw)
To: Vinod Koul, Neil Armstrong, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Andrzej Hajda, Robert Foss, Laurent Pinchart,
Jonas Karlman, Jernej Skrabec, Luca Ceresoli, David Airlie,
Simona Vetter, Maarten Lankhorst, Maxime Ripard,
Thomas Zimmermann, Lee Jones, Andy Yan, Philipp Zabel,
Emil Renner Berthing, Hal Feng, Michael Turquette, Stephen Boyd,
Brian Masney, Heiko Stuebner, Conor Dooley, Paul Walmsley,
Palmer Dabbelt, Albert Ou, Alexandre Ghiti, Dominique Belhachemi
Cc: devicetree, mfd, linux-kernel, dri-devel, Andy Yan,
Graham Markall, linux-rockchip, linux-phy, Michal Wilczynski,
linux-riscv, Maud Spierings, linux-clk, linux-arm-kernel,
Marek Szyprowski
The Innosilicon HDMI driver supports platform-specific behavior through
the `inno_hdmi_plat_ops`. While it provides an `.enable` hook for
platform-specific power up sequences (like enabling PHYs), it lacks a
corresponding hook for power down.
This patch adds a new `.disable` op to the `inno_hdmi_plat_ops` struct
and calls it at the beginning of `inno_hdmi_bridge_atomic_disable()`.
This allows platform specific drivers, such as the StarFive JH7110,
to implement their own power down sequence (e.g., calling
phy_power_off() and clk_disable_unprepare()).
Signed-off-by: Michal Wilczynski <m.wilczynski@samsung.com>
---
drivers/gpu/drm/bridge/inno-hdmi.c | 4 ++++
include/drm/bridge/inno_hdmi.h | 1 +
2 files changed, 5 insertions(+)
diff --git a/drivers/gpu/drm/bridge/inno-hdmi.c b/drivers/gpu/drm/bridge/inno-hdmi.c
index ebc5093f13ac4f263b903fb727629dfb83d051e1..952cc55c10f7dc07de6ebe943aae3e54df2edc8d 100644
--- a/drivers/gpu/drm/bridge/inno-hdmi.c
+++ b/drivers/gpu/drm/bridge/inno-hdmi.c
@@ -884,6 +884,10 @@ static void inno_hdmi_bridge_atomic_disable(struct drm_bridge *bridge,
struct drm_atomic_commit *state)
{
struct inno_hdmi *hdmi = bridge_to_inno_hdmi(bridge);
+ const struct inno_hdmi_plat_ops *plat_ops = hdmi->plat_data->ops;
+
+ if (plat_ops && plat_ops->disable)
+ plat_ops->disable(hdmi->dev);
inno_hdmi_standby(hdmi);
}
diff --git a/include/drm/bridge/inno_hdmi.h b/include/drm/bridge/inno_hdmi.h
index 81da9d9bcd79db8fe26c6dff4569371e484df608..5fca651c56b056d814124aa9c7e91aa7fd7ed1cd 100644
--- a/include/drm/bridge/inno_hdmi.h
+++ b/include/drm/bridge/inno_hdmi.h
@@ -16,6 +16,7 @@ struct platform_device;
struct inno_hdmi_plat_ops {
void (*enable)(struct device *pdev, struct drm_display_mode *mode);
+ void (*disable)(struct device *pdev);
};
struct inno_hdmi_phy_config {
--
2.34.1
_______________________________________________
linux-riscv mailing list
linux-riscv@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-riscv
^ permalink raw reply related [flat|nested] 116+ messages in thread
* [PATCH v2 06/15] drm/bridge: inno-hdmi: Add .disable platform operation
@ 2026-08-28 13:47 ` Michal Wilczynski
0 siblings, 0 replies; 116+ messages in thread
From: Michal Wilczynski @ 2026-08-28 13:47 UTC (permalink / raw)
To: Vinod Koul, Neil Armstrong, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Andrzej Hajda, Robert Foss, Laurent Pinchart,
Jonas Karlman, Jernej Skrabec, Luca Ceresoli, David Airlie,
Simona Vetter, Maarten Lankhorst, Maxime Ripard,
Thomas Zimmermann, Lee Jones, Andy Yan, Philipp Zabel,
Emil Renner Berthing, Hal Feng, Michael Turquette, Stephen Boyd,
Brian Masney, Heiko Stuebner, Conor Dooley, Paul Walmsley,
Palmer Dabbelt, Albert Ou, Alexandre Ghiti, Dominique Belhachemi
Cc: linux-phy, devicetree, linux-kernel, dri-devel, mfd, linux-clk,
linux-arm-kernel, linux-rockchip, linux-riscv, Icenowy Zheng,
Andy Yan, Marek Szyprowski, Maud Spierings, Graham Markall,
Michal Wilczynski
The Innosilicon HDMI driver supports platform-specific behavior through
the `inno_hdmi_plat_ops`. While it provides an `.enable` hook for
platform-specific power up sequences (like enabling PHYs), it lacks a
corresponding hook for power down.
This patch adds a new `.disable` op to the `inno_hdmi_plat_ops` struct
and calls it at the beginning of `inno_hdmi_bridge_atomic_disable()`.
This allows platform specific drivers, such as the StarFive JH7110,
to implement their own power down sequence (e.g., calling
phy_power_off() and clk_disable_unprepare()).
Signed-off-by: Michal Wilczynski <m.wilczynski@samsung.com>
---
drivers/gpu/drm/bridge/inno-hdmi.c | 4 ++++
include/drm/bridge/inno_hdmi.h | 1 +
2 files changed, 5 insertions(+)
diff --git a/drivers/gpu/drm/bridge/inno-hdmi.c b/drivers/gpu/drm/bridge/inno-hdmi.c
index ebc5093f13ac4f263b903fb727629dfb83d051e1..952cc55c10f7dc07de6ebe943aae3e54df2edc8d 100644
--- a/drivers/gpu/drm/bridge/inno-hdmi.c
+++ b/drivers/gpu/drm/bridge/inno-hdmi.c
@@ -884,6 +884,10 @@ static void inno_hdmi_bridge_atomic_disable(struct drm_bridge *bridge,
struct drm_atomic_commit *state)
{
struct inno_hdmi *hdmi = bridge_to_inno_hdmi(bridge);
+ const struct inno_hdmi_plat_ops *plat_ops = hdmi->plat_data->ops;
+
+ if (plat_ops && plat_ops->disable)
+ plat_ops->disable(hdmi->dev);
inno_hdmi_standby(hdmi);
}
diff --git a/include/drm/bridge/inno_hdmi.h b/include/drm/bridge/inno_hdmi.h
index 81da9d9bcd79db8fe26c6dff4569371e484df608..5fca651c56b056d814124aa9c7e91aa7fd7ed1cd 100644
--- a/include/drm/bridge/inno_hdmi.h
+++ b/include/drm/bridge/inno_hdmi.h
@@ -16,6 +16,7 @@ struct platform_device;
struct inno_hdmi_plat_ops {
void (*enable)(struct device *pdev, struct drm_display_mode *mode);
+ void (*disable)(struct device *pdev);
};
struct inno_hdmi_phy_config {
--
2.34.1
--
linux-phy mailing list
linux-phy@lists.infradead.org
https://lists.infradead.org/mailman/listinfo/linux-phy
^ permalink raw reply related [flat|nested] 116+ messages in thread
* [PATCH v2 06/15] drm/bridge: inno-hdmi: Add .disable platform operation
@ 2026-08-28 13:47 ` Michal Wilczynski
0 siblings, 0 replies; 116+ messages in thread
From: Michal Wilczynski @ 2026-08-28 13:47 UTC (permalink / raw)
To: Vinod Koul, Neil Armstrong, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Andrzej Hajda, Robert Foss, Laurent Pinchart,
Jonas Karlman, Jernej Skrabec, Luca Ceresoli, David Airlie,
Simona Vetter, Maarten Lankhorst, Maxime Ripard,
Thomas Zimmermann, Lee Jones, Andy Yan, Philipp Zabel,
Emil Renner Berthing, Hal Feng, Michael Turquette, Stephen Boyd,
Brian Masney, Heiko Stuebner, Conor Dooley, Paul Walmsley,
Palmer Dabbelt, Albert Ou, Alexandre Ghiti, Dominique Belhachemi
Cc: linux-phy, devicetree, linux-kernel, dri-devel, mfd, linux-clk,
linux-arm-kernel, linux-rockchip, linux-riscv, Icenowy Zheng,
Andy Yan, Marek Szyprowski, Maud Spierings, Graham Markall,
Michal Wilczynski
The Innosilicon HDMI driver supports platform-specific behavior through
the `inno_hdmi_plat_ops`. While it provides an `.enable` hook for
platform-specific power up sequences (like enabling PHYs), it lacks a
corresponding hook for power down.
This patch adds a new `.disable` op to the `inno_hdmi_plat_ops` struct
and calls it at the beginning of `inno_hdmi_bridge_atomic_disable()`.
This allows platform specific drivers, such as the StarFive JH7110,
to implement their own power down sequence (e.g., calling
phy_power_off() and clk_disable_unprepare()).
Signed-off-by: Michal Wilczynski <m.wilczynski@samsung.com>
---
drivers/gpu/drm/bridge/inno-hdmi.c | 4 ++++
include/drm/bridge/inno_hdmi.h | 1 +
2 files changed, 5 insertions(+)
diff --git a/drivers/gpu/drm/bridge/inno-hdmi.c b/drivers/gpu/drm/bridge/inno-hdmi.c
index ebc5093f13ac4f263b903fb727629dfb83d051e1..952cc55c10f7dc07de6ebe943aae3e54df2edc8d 100644
--- a/drivers/gpu/drm/bridge/inno-hdmi.c
+++ b/drivers/gpu/drm/bridge/inno-hdmi.c
@@ -884,6 +884,10 @@ static void inno_hdmi_bridge_atomic_disable(struct drm_bridge *bridge,
struct drm_atomic_commit *state)
{
struct inno_hdmi *hdmi = bridge_to_inno_hdmi(bridge);
+ const struct inno_hdmi_plat_ops *plat_ops = hdmi->plat_data->ops;
+
+ if (plat_ops && plat_ops->disable)
+ plat_ops->disable(hdmi->dev);
inno_hdmi_standby(hdmi);
}
diff --git a/include/drm/bridge/inno_hdmi.h b/include/drm/bridge/inno_hdmi.h
index 81da9d9bcd79db8fe26c6dff4569371e484df608..5fca651c56b056d814124aa9c7e91aa7fd7ed1cd 100644
--- a/include/drm/bridge/inno_hdmi.h
+++ b/include/drm/bridge/inno_hdmi.h
@@ -16,6 +16,7 @@ struct platform_device;
struct inno_hdmi_plat_ops {
void (*enable)(struct device *pdev, struct drm_display_mode *mode);
+ void (*disable)(struct device *pdev);
};
struct inno_hdmi_phy_config {
--
2.34.1
_______________________________________________
Linux-rockchip mailing list
Linux-rockchip@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-rockchip
^ permalink raw reply related [flat|nested] 116+ messages in thread
* [PATCH v2 07/15] drm/bridge: inno-hdmi: Add .mode_valid platform operation
2026-08-28 13:47 ` Michal Wilczynski
(?)
(?)
@ 2026-08-28 13:47 ` Michal Wilczynski
-1 siblings, 0 replies; 116+ messages in thread
From: Michal Wilczynski @ 2026-08-28 13:47 UTC (permalink / raw)
To: Vinod Koul, Neil Armstrong, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Andrzej Hajda, Robert Foss, Laurent Pinchart,
Jonas Karlman, Jernej Skrabec, Luca Ceresoli, David Airlie,
Simona Vetter, Maarten Lankhorst, Maxime Ripard,
Thomas Zimmermann, Lee Jones, Andy Yan, Philipp Zabel,
Emil Renner Berthing, Hal Feng, Michael Turquette, Stephen Boyd,
Brian Masney, Heiko Stuebner, Conor Dooley, Paul Walmsley,
Palmer Dabbelt, Albert Ou, Alexandre Ghiti, Dominique Belhachemi
Cc: linux-phy, devicetree, linux-kernel, dri-devel, mfd, linux-clk,
linux-arm-kernel, linux-rockchip, linux-riscv, Icenowy Zheng,
Andy Yan, Marek Szyprowski, Maud Spierings, Graham Markall,
Michal Wilczynski
inno_hdmi_bridge_mode_valid() validates the pixel clock against
hdmi->refclk, but that clock is optional and is only present on
platforms that describe a "ref" clock. Platforms where the pixel clock
is produced by a separate device - such as the StarFive JH7110, whose
PHY is both the clock and the PHY provider - have no "ref" clock, so
the check is skipped entirely and every mode is reported as valid.
A mode the platform cannot generate is then advertised to userspace.
The subsequent modeset appears to succeed, since the atomic enable path
cannot fail, and the display silently stays blank.
Add a .mode_valid platform operation so platforms can reject modes they
are unable to drive. Platforms that do not implement it are unaffected.
Signed-off-by: Michal Wilczynski <m.wilczynski@samsung.com>
---
drivers/gpu/drm/bridge/inno-hdmi.c | 9 +++++++++
include/drm/bridge/inno_hdmi.h | 5 ++++-
2 files changed, 13 insertions(+), 1 deletion(-)
diff --git a/drivers/gpu/drm/bridge/inno-hdmi.c b/drivers/gpu/drm/bridge/inno-hdmi.c
index 952cc55c10f7dc07de6ebe943aae3e54df2edc8d..6da1ef923c99676a2133b4c0e3ba5744195a335c 100644
--- a/drivers/gpu/drm/bridge/inno-hdmi.c
+++ b/drivers/gpu/drm/bridge/inno-hdmi.c
@@ -821,6 +821,7 @@ static enum drm_mode_status inno_hdmi_bridge_mode_valid(struct drm_bridge *bridg
const struct drm_display_mode *mode)
{
struct inno_hdmi *hdmi = bridge_to_inno_hdmi(bridge);
+ const struct inno_hdmi_plat_ops *plat_ops = hdmi->plat_data->ops;
unsigned long mpixelclk, max_tolerance;
long rounded_refclk;
@@ -836,6 +837,14 @@ static enum drm_mode_status inno_hdmi_bridge_mode_valid(struct drm_bridge *bridg
if (inno_hdmi_find_phy_config(hdmi, mpixelclk) < 0)
return MODE_CLOCK_HIGH;
+ if (plat_ops && plat_ops->mode_valid) {
+ enum drm_mode_status status;
+
+ status = plat_ops->mode_valid(hdmi->dev, mode);
+ if (status != MODE_OK)
+ return status;
+ }
+
if (hdmi->refclk) {
rounded_refclk = clk_round_rate(hdmi->refclk, mpixelclk);
if (rounded_refclk < 0)
diff --git a/include/drm/bridge/inno_hdmi.h b/include/drm/bridge/inno_hdmi.h
index 5fca651c56b056d814124aa9c7e91aa7fd7ed1cd..1e9974401c39e3773bb339eaec0b45ff1dd9c975 100644
--- a/include/drm/bridge/inno_hdmi.h
+++ b/include/drm/bridge/inno_hdmi.h
@@ -8,15 +8,18 @@
#include <linux/types.h>
+#include <drm/drm_modes.h>
+
struct device;
struct drm_encoder;
-struct drm_display_mode;
struct inno_hdmi;
struct platform_device;
struct inno_hdmi_plat_ops {
void (*enable)(struct device *pdev, struct drm_display_mode *mode);
void (*disable)(struct device *pdev);
+ enum drm_mode_status (*mode_valid)(struct device *pdev,
+ const struct drm_display_mode *mode);
};
struct inno_hdmi_phy_config {
--
2.34.1
^ permalink raw reply related [flat|nested] 116+ messages in thread
* [PATCH v2 07/15] drm/bridge: inno-hdmi: Add .mode_valid platform operation
@ 2026-08-28 13:47 ` Michal Wilczynski
0 siblings, 0 replies; 116+ messages in thread
From: Michal Wilczynski @ 2026-08-28 13:47 UTC (permalink / raw)
To: Vinod Koul, Neil Armstrong, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Andrzej Hajda, Robert Foss, Laurent Pinchart,
Jonas Karlman, Jernej Skrabec, Luca Ceresoli, David Airlie,
Simona Vetter, Maarten Lankhorst, Maxime Ripard,
Thomas Zimmermann, Lee Jones, Andy Yan, Philipp Zabel,
Emil Renner Berthing, Hal Feng, Michael Turquette, Stephen Boyd,
Brian Masney, Heiko Stuebner, Conor Dooley, Paul Walmsley,
Palmer Dabbelt, Albert Ou, Alexandre Ghiti, Dominique Belhachemi
Cc: linux-phy, devicetree, linux-kernel, dri-devel, mfd, linux-clk,
linux-arm-kernel, linux-rockchip, linux-riscv, Icenowy Zheng,
Andy Yan, Marek Szyprowski, Maud Spierings, Graham Markall,
Michal Wilczynski
inno_hdmi_bridge_mode_valid() validates the pixel clock against
hdmi->refclk, but that clock is optional and is only present on
platforms that describe a "ref" clock. Platforms where the pixel clock
is produced by a separate device - such as the StarFive JH7110, whose
PHY is both the clock and the PHY provider - have no "ref" clock, so
the check is skipped entirely and every mode is reported as valid.
A mode the platform cannot generate is then advertised to userspace.
The subsequent modeset appears to succeed, since the atomic enable path
cannot fail, and the display silently stays blank.
Add a .mode_valid platform operation so platforms can reject modes they
are unable to drive. Platforms that do not implement it are unaffected.
Signed-off-by: Michal Wilczynski <m.wilczynski@samsung.com>
---
drivers/gpu/drm/bridge/inno-hdmi.c | 9 +++++++++
include/drm/bridge/inno_hdmi.h | 5 ++++-
2 files changed, 13 insertions(+), 1 deletion(-)
diff --git a/drivers/gpu/drm/bridge/inno-hdmi.c b/drivers/gpu/drm/bridge/inno-hdmi.c
index 952cc55c10f7dc07de6ebe943aae3e54df2edc8d..6da1ef923c99676a2133b4c0e3ba5744195a335c 100644
--- a/drivers/gpu/drm/bridge/inno-hdmi.c
+++ b/drivers/gpu/drm/bridge/inno-hdmi.c
@@ -821,6 +821,7 @@ static enum drm_mode_status inno_hdmi_bridge_mode_valid(struct drm_bridge *bridg
const struct drm_display_mode *mode)
{
struct inno_hdmi *hdmi = bridge_to_inno_hdmi(bridge);
+ const struct inno_hdmi_plat_ops *plat_ops = hdmi->plat_data->ops;
unsigned long mpixelclk, max_tolerance;
long rounded_refclk;
@@ -836,6 +837,14 @@ static enum drm_mode_status inno_hdmi_bridge_mode_valid(struct drm_bridge *bridg
if (inno_hdmi_find_phy_config(hdmi, mpixelclk) < 0)
return MODE_CLOCK_HIGH;
+ if (plat_ops && plat_ops->mode_valid) {
+ enum drm_mode_status status;
+
+ status = plat_ops->mode_valid(hdmi->dev, mode);
+ if (status != MODE_OK)
+ return status;
+ }
+
if (hdmi->refclk) {
rounded_refclk = clk_round_rate(hdmi->refclk, mpixelclk);
if (rounded_refclk < 0)
diff --git a/include/drm/bridge/inno_hdmi.h b/include/drm/bridge/inno_hdmi.h
index 5fca651c56b056d814124aa9c7e91aa7fd7ed1cd..1e9974401c39e3773bb339eaec0b45ff1dd9c975 100644
--- a/include/drm/bridge/inno_hdmi.h
+++ b/include/drm/bridge/inno_hdmi.h
@@ -8,15 +8,18 @@
#include <linux/types.h>
+#include <drm/drm_modes.h>
+
struct device;
struct drm_encoder;
-struct drm_display_mode;
struct inno_hdmi;
struct platform_device;
struct inno_hdmi_plat_ops {
void (*enable)(struct device *pdev, struct drm_display_mode *mode);
void (*disable)(struct device *pdev);
+ enum drm_mode_status (*mode_valid)(struct device *pdev,
+ const struct drm_display_mode *mode);
};
struct inno_hdmi_phy_config {
--
2.34.1
--
linux-phy mailing list
linux-phy@lists.infradead.org
https://lists.infradead.org/mailman/listinfo/linux-phy
^ permalink raw reply related [flat|nested] 116+ messages in thread
* [PATCH v2 07/15] drm/bridge: inno-hdmi: Add .mode_valid platform operation
@ 2026-08-28 13:47 ` Michal Wilczynski
0 siblings, 0 replies; 116+ messages in thread
From: Michal Wilczynski @ 2026-08-28 13:47 UTC (permalink / raw)
To: Vinod Koul, Neil Armstrong, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Andrzej Hajda, Robert Foss, Laurent Pinchart,
Jonas Karlman, Jernej Skrabec, Luca Ceresoli, David Airlie,
Simona Vetter, Maarten Lankhorst, Maxime Ripard,
Thomas Zimmermann, Lee Jones, Andy Yan, Philipp Zabel,
Emil Renner Berthing, Hal Feng, Michael Turquette, Stephen Boyd,
Brian Masney, Heiko Stuebner, Conor Dooley, Paul Walmsley,
Palmer Dabbelt, Albert Ou, Alexandre Ghiti, Dominique Belhachemi
Cc: devicetree, mfd, linux-kernel, dri-devel, Andy Yan,
Graham Markall, linux-rockchip, linux-phy, Michal Wilczynski,
linux-riscv, Maud Spierings, linux-clk, linux-arm-kernel,
Marek Szyprowski
inno_hdmi_bridge_mode_valid() validates the pixel clock against
hdmi->refclk, but that clock is optional and is only present on
platforms that describe a "ref" clock. Platforms where the pixel clock
is produced by a separate device - such as the StarFive JH7110, whose
PHY is both the clock and the PHY provider - have no "ref" clock, so
the check is skipped entirely and every mode is reported as valid.
A mode the platform cannot generate is then advertised to userspace.
The subsequent modeset appears to succeed, since the atomic enable path
cannot fail, and the display silently stays blank.
Add a .mode_valid platform operation so platforms can reject modes they
are unable to drive. Platforms that do not implement it are unaffected.
Signed-off-by: Michal Wilczynski <m.wilczynski@samsung.com>
---
drivers/gpu/drm/bridge/inno-hdmi.c | 9 +++++++++
include/drm/bridge/inno_hdmi.h | 5 ++++-
2 files changed, 13 insertions(+), 1 deletion(-)
diff --git a/drivers/gpu/drm/bridge/inno-hdmi.c b/drivers/gpu/drm/bridge/inno-hdmi.c
index 952cc55c10f7dc07de6ebe943aae3e54df2edc8d..6da1ef923c99676a2133b4c0e3ba5744195a335c 100644
--- a/drivers/gpu/drm/bridge/inno-hdmi.c
+++ b/drivers/gpu/drm/bridge/inno-hdmi.c
@@ -821,6 +821,7 @@ static enum drm_mode_status inno_hdmi_bridge_mode_valid(struct drm_bridge *bridg
const struct drm_display_mode *mode)
{
struct inno_hdmi *hdmi = bridge_to_inno_hdmi(bridge);
+ const struct inno_hdmi_plat_ops *plat_ops = hdmi->plat_data->ops;
unsigned long mpixelclk, max_tolerance;
long rounded_refclk;
@@ -836,6 +837,14 @@ static enum drm_mode_status inno_hdmi_bridge_mode_valid(struct drm_bridge *bridg
if (inno_hdmi_find_phy_config(hdmi, mpixelclk) < 0)
return MODE_CLOCK_HIGH;
+ if (plat_ops && plat_ops->mode_valid) {
+ enum drm_mode_status status;
+
+ status = plat_ops->mode_valid(hdmi->dev, mode);
+ if (status != MODE_OK)
+ return status;
+ }
+
if (hdmi->refclk) {
rounded_refclk = clk_round_rate(hdmi->refclk, mpixelclk);
if (rounded_refclk < 0)
diff --git a/include/drm/bridge/inno_hdmi.h b/include/drm/bridge/inno_hdmi.h
index 5fca651c56b056d814124aa9c7e91aa7fd7ed1cd..1e9974401c39e3773bb339eaec0b45ff1dd9c975 100644
--- a/include/drm/bridge/inno_hdmi.h
+++ b/include/drm/bridge/inno_hdmi.h
@@ -8,15 +8,18 @@
#include <linux/types.h>
+#include <drm/drm_modes.h>
+
struct device;
struct drm_encoder;
-struct drm_display_mode;
struct inno_hdmi;
struct platform_device;
struct inno_hdmi_plat_ops {
void (*enable)(struct device *pdev, struct drm_display_mode *mode);
void (*disable)(struct device *pdev);
+ enum drm_mode_status (*mode_valid)(struct device *pdev,
+ const struct drm_display_mode *mode);
};
struct inno_hdmi_phy_config {
--
2.34.1
_______________________________________________
linux-riscv mailing list
linux-riscv@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-riscv
^ permalink raw reply related [flat|nested] 116+ messages in thread
* [PATCH v2 07/15] drm/bridge: inno-hdmi: Add .mode_valid platform operation
@ 2026-08-28 13:47 ` Michal Wilczynski
0 siblings, 0 replies; 116+ messages in thread
From: Michal Wilczynski @ 2026-08-28 13:47 UTC (permalink / raw)
To: Vinod Koul, Neil Armstrong, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Andrzej Hajda, Robert Foss, Laurent Pinchart,
Jonas Karlman, Jernej Skrabec, Luca Ceresoli, David Airlie,
Simona Vetter, Maarten Lankhorst, Maxime Ripard,
Thomas Zimmermann, Lee Jones, Andy Yan, Philipp Zabel,
Emil Renner Berthing, Hal Feng, Michael Turquette, Stephen Boyd,
Brian Masney, Heiko Stuebner, Conor Dooley, Paul Walmsley,
Palmer Dabbelt, Albert Ou, Alexandre Ghiti, Dominique Belhachemi
Cc: linux-phy, devicetree, linux-kernel, dri-devel, mfd, linux-clk,
linux-arm-kernel, linux-rockchip, linux-riscv, Icenowy Zheng,
Andy Yan, Marek Szyprowski, Maud Spierings, Graham Markall,
Michal Wilczynski
inno_hdmi_bridge_mode_valid() validates the pixel clock against
hdmi->refclk, but that clock is optional and is only present on
platforms that describe a "ref" clock. Platforms where the pixel clock
is produced by a separate device - such as the StarFive JH7110, whose
PHY is both the clock and the PHY provider - have no "ref" clock, so
the check is skipped entirely and every mode is reported as valid.
A mode the platform cannot generate is then advertised to userspace.
The subsequent modeset appears to succeed, since the atomic enable path
cannot fail, and the display silently stays blank.
Add a .mode_valid platform operation so platforms can reject modes they
are unable to drive. Platforms that do not implement it are unaffected.
Signed-off-by: Michal Wilczynski <m.wilczynski@samsung.com>
---
drivers/gpu/drm/bridge/inno-hdmi.c | 9 +++++++++
include/drm/bridge/inno_hdmi.h | 5 ++++-
2 files changed, 13 insertions(+), 1 deletion(-)
diff --git a/drivers/gpu/drm/bridge/inno-hdmi.c b/drivers/gpu/drm/bridge/inno-hdmi.c
index 952cc55c10f7dc07de6ebe943aae3e54df2edc8d..6da1ef923c99676a2133b4c0e3ba5744195a335c 100644
--- a/drivers/gpu/drm/bridge/inno-hdmi.c
+++ b/drivers/gpu/drm/bridge/inno-hdmi.c
@@ -821,6 +821,7 @@ static enum drm_mode_status inno_hdmi_bridge_mode_valid(struct drm_bridge *bridg
const struct drm_display_mode *mode)
{
struct inno_hdmi *hdmi = bridge_to_inno_hdmi(bridge);
+ const struct inno_hdmi_plat_ops *plat_ops = hdmi->plat_data->ops;
unsigned long mpixelclk, max_tolerance;
long rounded_refclk;
@@ -836,6 +837,14 @@ static enum drm_mode_status inno_hdmi_bridge_mode_valid(struct drm_bridge *bridg
if (inno_hdmi_find_phy_config(hdmi, mpixelclk) < 0)
return MODE_CLOCK_HIGH;
+ if (plat_ops && plat_ops->mode_valid) {
+ enum drm_mode_status status;
+
+ status = plat_ops->mode_valid(hdmi->dev, mode);
+ if (status != MODE_OK)
+ return status;
+ }
+
if (hdmi->refclk) {
rounded_refclk = clk_round_rate(hdmi->refclk, mpixelclk);
if (rounded_refclk < 0)
diff --git a/include/drm/bridge/inno_hdmi.h b/include/drm/bridge/inno_hdmi.h
index 5fca651c56b056d814124aa9c7e91aa7fd7ed1cd..1e9974401c39e3773bb339eaec0b45ff1dd9c975 100644
--- a/include/drm/bridge/inno_hdmi.h
+++ b/include/drm/bridge/inno_hdmi.h
@@ -8,15 +8,18 @@
#include <linux/types.h>
+#include <drm/drm_modes.h>
+
struct device;
struct drm_encoder;
-struct drm_display_mode;
struct inno_hdmi;
struct platform_device;
struct inno_hdmi_plat_ops {
void (*enable)(struct device *pdev, struct drm_display_mode *mode);
void (*disable)(struct device *pdev);
+ enum drm_mode_status (*mode_valid)(struct device *pdev,
+ const struct drm_display_mode *mode);
};
struct inno_hdmi_phy_config {
--
2.34.1
_______________________________________________
Linux-rockchip mailing list
Linux-rockchip@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-rockchip
^ permalink raw reply related [flat|nested] 116+ messages in thread
* [PATCH v2 08/15] soc: starfive: Add jh7110-hdmi-subsystem driver
2026-08-28 13:47 ` Michal Wilczynski
(?)
(?)
@ 2026-08-28 13:47 ` Michal Wilczynski
-1 siblings, 0 replies; 116+ messages in thread
From: Michal Wilczynski @ 2026-08-28 13:47 UTC (permalink / raw)
To: Vinod Koul, Neil Armstrong, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Andrzej Hajda, Robert Foss, Laurent Pinchart,
Jonas Karlman, Jernej Skrabec, Luca Ceresoli, David Airlie,
Simona Vetter, Maarten Lankhorst, Maxime Ripard,
Thomas Zimmermann, Lee Jones, Andy Yan, Philipp Zabel,
Emil Renner Berthing, Hal Feng, Michael Turquette, Stephen Boyd,
Brian Masney, Heiko Stuebner, Conor Dooley, Paul Walmsley,
Palmer Dabbelt, Albert Ou, Alexandre Ghiti, Dominique Belhachemi
Cc: linux-phy, devicetree, linux-kernel, dri-devel, mfd, linux-clk,
linux-arm-kernel, linux-rockchip, linux-riscv, Icenowy Zheng,
Andy Yan, Marek Szyprowski, Maud Spierings, Graham Markall,
Michal Wilczynski
Add the parent driver for the monolithic JH7110 HDMI IP block.
This driver binds to the starfive,jh7110-hdmi-subsystem node. It maps the
shared register block, creates a regmap, and calls
devm_of_platform_populate() to create its hdmi_phy and hdmi_controller
child devices, which retrieve the shared regmap from this parent.
The NoC display-bus clock and reset gate access to the whole vout register
region, and this subsystem's PHY child is the first device there to touch
registers. Enable the bus before populating the children; PD_VOUT is
handled by genpd through the power-domains property.
Co-developed-by: Dominique Belhachemi <db@domibel.de>
Signed-off-by: Dominique Belhachemi <db@domibel.de>
Signed-off-by: Michal Wilczynski <m.wilczynski@samsung.com>
---
drivers/soc/Kconfig | 1 +
drivers/soc/Makefile | 1 +
drivers/soc/starfive/Kconfig | 27 +++++++
drivers/soc/starfive/Makefile | 2 +
drivers/soc/starfive/jh7110-hdmi-subsystem.c | 114 +++++++++++++++++++++++++++
5 files changed, 145 insertions(+)
diff --git a/drivers/soc/Kconfig b/drivers/soc/Kconfig
index a2d65adffb8052c0ac5a6b60bf33fa9c644701bb..b3b01fc38139d98076c14f626a42ae3b7ef7c5d6 100644
--- a/drivers/soc/Kconfig
+++ b/drivers/soc/Kconfig
@@ -24,6 +24,7 @@ source "drivers/soc/renesas/Kconfig"
source "drivers/soc/rockchip/Kconfig"
source "drivers/soc/samsung/Kconfig"
source "drivers/soc/sophgo/Kconfig"
+source "drivers/soc/starfive/Kconfig"
source "drivers/soc/sunxi/Kconfig"
source "drivers/soc/tegra/Kconfig"
source "drivers/soc/ti/Kconfig"
diff --git a/drivers/soc/Makefile b/drivers/soc/Makefile
index c9e689080ceb759384f690c2b65a82b3cb451c74..009f85ff891a15e0455f92c5d5a4059d8b1fcd3f 100644
--- a/drivers/soc/Makefile
+++ b/drivers/soc/Makefile
@@ -30,6 +30,7 @@ obj-y += renesas/
obj-y += rockchip/
obj-$(CONFIG_SOC_SAMSUNG) += samsung/
obj-y += sophgo/
+obj-y += starfive/
obj-y += sunxi/
obj-$(CONFIG_ARCH_TEGRA) += tegra/
obj-y += ti/
diff --git a/drivers/soc/starfive/Kconfig b/drivers/soc/starfive/Kconfig
new file mode 100644
index 0000000000000000000000000000000000000000..7592d87dea37a7c14560b3eb9b23e49e503c2d71
--- /dev/null
+++ b/drivers/soc/starfive/Kconfig
@@ -0,0 +1,27 @@
+# SPDX-License-Identifier: GPL-2.0-only
+#
+# Starfive SoC drivers
+#
+
+if ARCH_STARFIVE || COMPILE_TEST
+menu "Starfive SoC drivers"
+
+config SOC_STARFIVE_JH7110_HDMI_SUBSYSTEM
+ tristate "StarFive JH7110 HDMI subsystem driver"
+ depends on OF
+ help
+ This option enables the parent driver
+ for the monolithic StarFive JH7110 HDMI peripheral.
+
+ The JH7110 HDMI IP block contains both the digital controller
+ (DRM bridge) and the analog PHY (clock/phy provider) logic within
+ a single shared register space.
+
+ This driver acts as a wrapper. Its only job is to map the
+ shared registers and create separate logical child devices
+ for the "PHY" and the "controller". This is required to
+ correctly manage resources and break a circular clock dependency
+ between the PHY and the VOUT clock generator at probe time.
+
+endmenu
+endif
diff --git a/drivers/soc/starfive/Makefile b/drivers/soc/starfive/Makefile
new file mode 100644
index 0000000000000000000000000000000000000000..be89d8119212b7a7038817c2f0e8eac1984ada88
--- /dev/null
+++ b/drivers/soc/starfive/Makefile
@@ -0,0 +1,2 @@
+# SPDX-License-Identifier: GPL-2.0-only
+obj-$(CONFIG_SOC_STARFIVE_JH7110_HDMI_SUBSYSTEM) += jh7110-hdmi-subsystem.o
diff --git a/drivers/soc/starfive/jh7110-hdmi-subsystem.c b/drivers/soc/starfive/jh7110-hdmi-subsystem.c
new file mode 100644
index 0000000000000000000000000000000000000000..d893c1c29f98b072b09d261343d3317dbf4c75fe
--- /dev/null
+++ b/drivers/soc/starfive/jh7110-hdmi-subsystem.c
@@ -0,0 +1,114 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Driver for the StarFive JH7110 HDMI subsystem
+ *
+ * Copyright (c) 2025 Samsung Electronics Co., Ltd.
+ * Author: Michal Wilczynski <m.wilczynski@samsung.com>
+ *
+ * This driver binds to the monolithic HDMI block and creates separate
+ * logical platform devices for the HDMI Controller (bridge) and the
+ * HDMI PHY (clock/phy provider), allowing them to share a single regmap
+ * and breaking the probing circular dependency.
+ */
+
+#include <linux/clk.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/of_platform.h>
+#include <linux/platform_device.h>
+#include <linux/regmap.h>
+#include <linux/reset.h>
+
+static const struct regmap_config starfive_hdmi_regmap_config = {
+ .reg_bits = 32,
+ .val_bits = 8,
+ .max_register = 0x3fff,
+};
+
+static void starfive_hdmi_subsys_clk_disable(void *data)
+{
+ clk_disable_unprepare(data);
+}
+
+static void starfive_hdmi_subsys_rst_assert(void *data)
+{
+ reset_control_assert(data);
+}
+
+static int starfive_hdmi_subsys_probe(struct platform_device *pdev)
+{
+ struct device *dev = &pdev->dev;
+ struct reset_control *bus_rst;
+ void __iomem *regs;
+ struct regmap *regmap;
+ struct clk *bus_clk;
+ int ret;
+
+ /*
+ * The NoC display-bus clock and reset gate access to the whole vout
+ * register region, and this subsystem's PHY child is the first device in
+ * that region to touch registers. Bring the bus up here before
+ * populating the children; PD_VOUT is powered on by genpd through the
+ * power-domains property.
+ */
+ bus_clk = devm_clk_get(dev, NULL);
+ if (IS_ERR(bus_clk))
+ return dev_err_probe(dev, PTR_ERR(bus_clk),
+ "Failed to get NoC bus clock\n");
+
+ ret = clk_prepare_enable(bus_clk);
+ if (ret)
+ return dev_err_probe(dev, ret, "Failed to enable NoC bus clock\n");
+
+ ret = devm_add_action_or_reset(dev, starfive_hdmi_subsys_clk_disable, bus_clk);
+ if (ret)
+ return ret;
+
+ bus_rst = devm_reset_control_get_exclusive(dev, NULL);
+ if (IS_ERR(bus_rst))
+ return dev_err_probe(dev, PTR_ERR(bus_rst),
+ "Failed to get NoC bus reset\n");
+
+ ret = reset_control_deassert(bus_rst);
+ if (ret)
+ return dev_err_probe(dev, ret, "Failed to deassert NoC bus reset\n");
+
+ ret = devm_add_action_or_reset(dev, starfive_hdmi_subsys_rst_assert, bus_rst);
+ if (ret)
+ return ret;
+
+ regs = devm_platform_ioremap_resource(pdev, 0);
+ if (IS_ERR(regs))
+ return PTR_ERR(regs);
+
+ regmap = devm_regmap_init_mmio(dev, regs,
+ &starfive_hdmi_regmap_config);
+ if (IS_ERR(regmap))
+ return dev_err_probe(dev, PTR_ERR(regmap),
+ "Failed to init shared regmap\n");
+
+ ret = devm_of_platform_populate(dev);
+ if (ret)
+ dev_err(dev, "Failed to populate child devices: %d\n", ret);
+
+ return ret;
+}
+
+static const struct of_device_id starfive_hdmi_subsys_of_match[] = {
+ { .compatible = "starfive,jh7110-hdmi-subsystem", },
+ { /* sentinel */ }
+};
+MODULE_DEVICE_TABLE(of, starfive_hdmi_subsys_of_match);
+
+static struct platform_driver starfive_hdmi_subsys_driver = {
+ .probe = starfive_hdmi_subsys_probe,
+ .driver = {
+ .name = "starfive-hdmi-subsystem",
+ .of_match_table = starfive_hdmi_subsys_of_match,
+ },
+};
+module_platform_driver(starfive_hdmi_subsys_driver);
+
+MODULE_AUTHOR("Michal Wilczynski <m.wilczynski@samsung.com>");
+MODULE_DESCRIPTION("StarFive JH7110 HDMI subsystem Driver");
+MODULE_LICENSE("GPL");
--
2.34.1
^ permalink raw reply related [flat|nested] 116+ messages in thread
* [PATCH v2 08/15] soc: starfive: Add jh7110-hdmi-subsystem driver
@ 2026-08-28 13:47 ` Michal Wilczynski
0 siblings, 0 replies; 116+ messages in thread
From: Michal Wilczynski @ 2026-08-28 13:47 UTC (permalink / raw)
To: Vinod Koul, Neil Armstrong, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Andrzej Hajda, Robert Foss, Laurent Pinchart,
Jonas Karlman, Jernej Skrabec, Luca Ceresoli, David Airlie,
Simona Vetter, Maarten Lankhorst, Maxime Ripard,
Thomas Zimmermann, Lee Jones, Andy Yan, Philipp Zabel,
Emil Renner Berthing, Hal Feng, Michael Turquette, Stephen Boyd,
Brian Masney, Heiko Stuebner, Conor Dooley, Paul Walmsley,
Palmer Dabbelt, Albert Ou, Alexandre Ghiti, Dominique Belhachemi
Cc: devicetree, mfd, linux-kernel, dri-devel, Andy Yan,
Graham Markall, linux-rockchip, linux-phy, Michal Wilczynski,
linux-riscv, Maud Spierings, linux-clk, linux-arm-kernel,
Marek Szyprowski
Add the parent driver for the monolithic JH7110 HDMI IP block.
This driver binds to the starfive,jh7110-hdmi-subsystem node. It maps the
shared register block, creates a regmap, and calls
devm_of_platform_populate() to create its hdmi_phy and hdmi_controller
child devices, which retrieve the shared regmap from this parent.
The NoC display-bus clock and reset gate access to the whole vout register
region, and this subsystem's PHY child is the first device there to touch
registers. Enable the bus before populating the children; PD_VOUT is
handled by genpd through the power-domains property.
Co-developed-by: Dominique Belhachemi <db@domibel.de>
Signed-off-by: Dominique Belhachemi <db@domibel.de>
Signed-off-by: Michal Wilczynski <m.wilczynski@samsung.com>
---
drivers/soc/Kconfig | 1 +
drivers/soc/Makefile | 1 +
drivers/soc/starfive/Kconfig | 27 +++++++
drivers/soc/starfive/Makefile | 2 +
drivers/soc/starfive/jh7110-hdmi-subsystem.c | 114 +++++++++++++++++++++++++++
5 files changed, 145 insertions(+)
diff --git a/drivers/soc/Kconfig b/drivers/soc/Kconfig
index a2d65adffb8052c0ac5a6b60bf33fa9c644701bb..b3b01fc38139d98076c14f626a42ae3b7ef7c5d6 100644
--- a/drivers/soc/Kconfig
+++ b/drivers/soc/Kconfig
@@ -24,6 +24,7 @@ source "drivers/soc/renesas/Kconfig"
source "drivers/soc/rockchip/Kconfig"
source "drivers/soc/samsung/Kconfig"
source "drivers/soc/sophgo/Kconfig"
+source "drivers/soc/starfive/Kconfig"
source "drivers/soc/sunxi/Kconfig"
source "drivers/soc/tegra/Kconfig"
source "drivers/soc/ti/Kconfig"
diff --git a/drivers/soc/Makefile b/drivers/soc/Makefile
index c9e689080ceb759384f690c2b65a82b3cb451c74..009f85ff891a15e0455f92c5d5a4059d8b1fcd3f 100644
--- a/drivers/soc/Makefile
+++ b/drivers/soc/Makefile
@@ -30,6 +30,7 @@ obj-y += renesas/
obj-y += rockchip/
obj-$(CONFIG_SOC_SAMSUNG) += samsung/
obj-y += sophgo/
+obj-y += starfive/
obj-y += sunxi/
obj-$(CONFIG_ARCH_TEGRA) += tegra/
obj-y += ti/
diff --git a/drivers/soc/starfive/Kconfig b/drivers/soc/starfive/Kconfig
new file mode 100644
index 0000000000000000000000000000000000000000..7592d87dea37a7c14560b3eb9b23e49e503c2d71
--- /dev/null
+++ b/drivers/soc/starfive/Kconfig
@@ -0,0 +1,27 @@
+# SPDX-License-Identifier: GPL-2.0-only
+#
+# Starfive SoC drivers
+#
+
+if ARCH_STARFIVE || COMPILE_TEST
+menu "Starfive SoC drivers"
+
+config SOC_STARFIVE_JH7110_HDMI_SUBSYSTEM
+ tristate "StarFive JH7110 HDMI subsystem driver"
+ depends on OF
+ help
+ This option enables the parent driver
+ for the monolithic StarFive JH7110 HDMI peripheral.
+
+ The JH7110 HDMI IP block contains both the digital controller
+ (DRM bridge) and the analog PHY (clock/phy provider) logic within
+ a single shared register space.
+
+ This driver acts as a wrapper. Its only job is to map the
+ shared registers and create separate logical child devices
+ for the "PHY" and the "controller". This is required to
+ correctly manage resources and break a circular clock dependency
+ between the PHY and the VOUT clock generator at probe time.
+
+endmenu
+endif
diff --git a/drivers/soc/starfive/Makefile b/drivers/soc/starfive/Makefile
new file mode 100644
index 0000000000000000000000000000000000000000..be89d8119212b7a7038817c2f0e8eac1984ada88
--- /dev/null
+++ b/drivers/soc/starfive/Makefile
@@ -0,0 +1,2 @@
+# SPDX-License-Identifier: GPL-2.0-only
+obj-$(CONFIG_SOC_STARFIVE_JH7110_HDMI_SUBSYSTEM) += jh7110-hdmi-subsystem.o
diff --git a/drivers/soc/starfive/jh7110-hdmi-subsystem.c b/drivers/soc/starfive/jh7110-hdmi-subsystem.c
new file mode 100644
index 0000000000000000000000000000000000000000..d893c1c29f98b072b09d261343d3317dbf4c75fe
--- /dev/null
+++ b/drivers/soc/starfive/jh7110-hdmi-subsystem.c
@@ -0,0 +1,114 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Driver for the StarFive JH7110 HDMI subsystem
+ *
+ * Copyright (c) 2025 Samsung Electronics Co., Ltd.
+ * Author: Michal Wilczynski <m.wilczynski@samsung.com>
+ *
+ * This driver binds to the monolithic HDMI block and creates separate
+ * logical platform devices for the HDMI Controller (bridge) and the
+ * HDMI PHY (clock/phy provider), allowing them to share a single regmap
+ * and breaking the probing circular dependency.
+ */
+
+#include <linux/clk.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/of_platform.h>
+#include <linux/platform_device.h>
+#include <linux/regmap.h>
+#include <linux/reset.h>
+
+static const struct regmap_config starfive_hdmi_regmap_config = {
+ .reg_bits = 32,
+ .val_bits = 8,
+ .max_register = 0x3fff,
+};
+
+static void starfive_hdmi_subsys_clk_disable(void *data)
+{
+ clk_disable_unprepare(data);
+}
+
+static void starfive_hdmi_subsys_rst_assert(void *data)
+{
+ reset_control_assert(data);
+}
+
+static int starfive_hdmi_subsys_probe(struct platform_device *pdev)
+{
+ struct device *dev = &pdev->dev;
+ struct reset_control *bus_rst;
+ void __iomem *regs;
+ struct regmap *regmap;
+ struct clk *bus_clk;
+ int ret;
+
+ /*
+ * The NoC display-bus clock and reset gate access to the whole vout
+ * register region, and this subsystem's PHY child is the first device in
+ * that region to touch registers. Bring the bus up here before
+ * populating the children; PD_VOUT is powered on by genpd through the
+ * power-domains property.
+ */
+ bus_clk = devm_clk_get(dev, NULL);
+ if (IS_ERR(bus_clk))
+ return dev_err_probe(dev, PTR_ERR(bus_clk),
+ "Failed to get NoC bus clock\n");
+
+ ret = clk_prepare_enable(bus_clk);
+ if (ret)
+ return dev_err_probe(dev, ret, "Failed to enable NoC bus clock\n");
+
+ ret = devm_add_action_or_reset(dev, starfive_hdmi_subsys_clk_disable, bus_clk);
+ if (ret)
+ return ret;
+
+ bus_rst = devm_reset_control_get_exclusive(dev, NULL);
+ if (IS_ERR(bus_rst))
+ return dev_err_probe(dev, PTR_ERR(bus_rst),
+ "Failed to get NoC bus reset\n");
+
+ ret = reset_control_deassert(bus_rst);
+ if (ret)
+ return dev_err_probe(dev, ret, "Failed to deassert NoC bus reset\n");
+
+ ret = devm_add_action_or_reset(dev, starfive_hdmi_subsys_rst_assert, bus_rst);
+ if (ret)
+ return ret;
+
+ regs = devm_platform_ioremap_resource(pdev, 0);
+ if (IS_ERR(regs))
+ return PTR_ERR(regs);
+
+ regmap = devm_regmap_init_mmio(dev, regs,
+ &starfive_hdmi_regmap_config);
+ if (IS_ERR(regmap))
+ return dev_err_probe(dev, PTR_ERR(regmap),
+ "Failed to init shared regmap\n");
+
+ ret = devm_of_platform_populate(dev);
+ if (ret)
+ dev_err(dev, "Failed to populate child devices: %d\n", ret);
+
+ return ret;
+}
+
+static const struct of_device_id starfive_hdmi_subsys_of_match[] = {
+ { .compatible = "starfive,jh7110-hdmi-subsystem", },
+ { /* sentinel */ }
+};
+MODULE_DEVICE_TABLE(of, starfive_hdmi_subsys_of_match);
+
+static struct platform_driver starfive_hdmi_subsys_driver = {
+ .probe = starfive_hdmi_subsys_probe,
+ .driver = {
+ .name = "starfive-hdmi-subsystem",
+ .of_match_table = starfive_hdmi_subsys_of_match,
+ },
+};
+module_platform_driver(starfive_hdmi_subsys_driver);
+
+MODULE_AUTHOR("Michal Wilczynski <m.wilczynski@samsung.com>");
+MODULE_DESCRIPTION("StarFive JH7110 HDMI subsystem Driver");
+MODULE_LICENSE("GPL");
--
2.34.1
_______________________________________________
linux-riscv mailing list
linux-riscv@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-riscv
^ permalink raw reply related [flat|nested] 116+ messages in thread
* [PATCH v2 08/15] soc: starfive: Add jh7110-hdmi-subsystem driver
@ 2026-08-28 13:47 ` Michal Wilczynski
0 siblings, 0 replies; 116+ messages in thread
From: Michal Wilczynski @ 2026-08-28 13:47 UTC (permalink / raw)
To: Vinod Koul, Neil Armstrong, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Andrzej Hajda, Robert Foss, Laurent Pinchart,
Jonas Karlman, Jernej Skrabec, Luca Ceresoli, David Airlie,
Simona Vetter, Maarten Lankhorst, Maxime Ripard,
Thomas Zimmermann, Lee Jones, Andy Yan, Philipp Zabel,
Emil Renner Berthing, Hal Feng, Michael Turquette, Stephen Boyd,
Brian Masney, Heiko Stuebner, Conor Dooley, Paul Walmsley,
Palmer Dabbelt, Albert Ou, Alexandre Ghiti, Dominique Belhachemi
Cc: linux-phy, devicetree, linux-kernel, dri-devel, mfd, linux-clk,
linux-arm-kernel, linux-rockchip, linux-riscv, Icenowy Zheng,
Andy Yan, Marek Szyprowski, Maud Spierings, Graham Markall,
Michal Wilczynski
Add the parent driver for the monolithic JH7110 HDMI IP block.
This driver binds to the starfive,jh7110-hdmi-subsystem node. It maps the
shared register block, creates a regmap, and calls
devm_of_platform_populate() to create its hdmi_phy and hdmi_controller
child devices, which retrieve the shared regmap from this parent.
The NoC display-bus clock and reset gate access to the whole vout register
region, and this subsystem's PHY child is the first device there to touch
registers. Enable the bus before populating the children; PD_VOUT is
handled by genpd through the power-domains property.
Co-developed-by: Dominique Belhachemi <db@domibel.de>
Signed-off-by: Dominique Belhachemi <db@domibel.de>
Signed-off-by: Michal Wilczynski <m.wilczynski@samsung.com>
---
drivers/soc/Kconfig | 1 +
drivers/soc/Makefile | 1 +
drivers/soc/starfive/Kconfig | 27 +++++++
drivers/soc/starfive/Makefile | 2 +
drivers/soc/starfive/jh7110-hdmi-subsystem.c | 114 +++++++++++++++++++++++++++
5 files changed, 145 insertions(+)
diff --git a/drivers/soc/Kconfig b/drivers/soc/Kconfig
index a2d65adffb8052c0ac5a6b60bf33fa9c644701bb..b3b01fc38139d98076c14f626a42ae3b7ef7c5d6 100644
--- a/drivers/soc/Kconfig
+++ b/drivers/soc/Kconfig
@@ -24,6 +24,7 @@ source "drivers/soc/renesas/Kconfig"
source "drivers/soc/rockchip/Kconfig"
source "drivers/soc/samsung/Kconfig"
source "drivers/soc/sophgo/Kconfig"
+source "drivers/soc/starfive/Kconfig"
source "drivers/soc/sunxi/Kconfig"
source "drivers/soc/tegra/Kconfig"
source "drivers/soc/ti/Kconfig"
diff --git a/drivers/soc/Makefile b/drivers/soc/Makefile
index c9e689080ceb759384f690c2b65a82b3cb451c74..009f85ff891a15e0455f92c5d5a4059d8b1fcd3f 100644
--- a/drivers/soc/Makefile
+++ b/drivers/soc/Makefile
@@ -30,6 +30,7 @@ obj-y += renesas/
obj-y += rockchip/
obj-$(CONFIG_SOC_SAMSUNG) += samsung/
obj-y += sophgo/
+obj-y += starfive/
obj-y += sunxi/
obj-$(CONFIG_ARCH_TEGRA) += tegra/
obj-y += ti/
diff --git a/drivers/soc/starfive/Kconfig b/drivers/soc/starfive/Kconfig
new file mode 100644
index 0000000000000000000000000000000000000000..7592d87dea37a7c14560b3eb9b23e49e503c2d71
--- /dev/null
+++ b/drivers/soc/starfive/Kconfig
@@ -0,0 +1,27 @@
+# SPDX-License-Identifier: GPL-2.0-only
+#
+# Starfive SoC drivers
+#
+
+if ARCH_STARFIVE || COMPILE_TEST
+menu "Starfive SoC drivers"
+
+config SOC_STARFIVE_JH7110_HDMI_SUBSYSTEM
+ tristate "StarFive JH7110 HDMI subsystem driver"
+ depends on OF
+ help
+ This option enables the parent driver
+ for the monolithic StarFive JH7110 HDMI peripheral.
+
+ The JH7110 HDMI IP block contains both the digital controller
+ (DRM bridge) and the analog PHY (clock/phy provider) logic within
+ a single shared register space.
+
+ This driver acts as a wrapper. Its only job is to map the
+ shared registers and create separate logical child devices
+ for the "PHY" and the "controller". This is required to
+ correctly manage resources and break a circular clock dependency
+ between the PHY and the VOUT clock generator at probe time.
+
+endmenu
+endif
diff --git a/drivers/soc/starfive/Makefile b/drivers/soc/starfive/Makefile
new file mode 100644
index 0000000000000000000000000000000000000000..be89d8119212b7a7038817c2f0e8eac1984ada88
--- /dev/null
+++ b/drivers/soc/starfive/Makefile
@@ -0,0 +1,2 @@
+# SPDX-License-Identifier: GPL-2.0-only
+obj-$(CONFIG_SOC_STARFIVE_JH7110_HDMI_SUBSYSTEM) += jh7110-hdmi-subsystem.o
diff --git a/drivers/soc/starfive/jh7110-hdmi-subsystem.c b/drivers/soc/starfive/jh7110-hdmi-subsystem.c
new file mode 100644
index 0000000000000000000000000000000000000000..d893c1c29f98b072b09d261343d3317dbf4c75fe
--- /dev/null
+++ b/drivers/soc/starfive/jh7110-hdmi-subsystem.c
@@ -0,0 +1,114 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Driver for the StarFive JH7110 HDMI subsystem
+ *
+ * Copyright (c) 2025 Samsung Electronics Co., Ltd.
+ * Author: Michal Wilczynski <m.wilczynski@samsung.com>
+ *
+ * This driver binds to the monolithic HDMI block and creates separate
+ * logical platform devices for the HDMI Controller (bridge) and the
+ * HDMI PHY (clock/phy provider), allowing them to share a single regmap
+ * and breaking the probing circular dependency.
+ */
+
+#include <linux/clk.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/of_platform.h>
+#include <linux/platform_device.h>
+#include <linux/regmap.h>
+#include <linux/reset.h>
+
+static const struct regmap_config starfive_hdmi_regmap_config = {
+ .reg_bits = 32,
+ .val_bits = 8,
+ .max_register = 0x3fff,
+};
+
+static void starfive_hdmi_subsys_clk_disable(void *data)
+{
+ clk_disable_unprepare(data);
+}
+
+static void starfive_hdmi_subsys_rst_assert(void *data)
+{
+ reset_control_assert(data);
+}
+
+static int starfive_hdmi_subsys_probe(struct platform_device *pdev)
+{
+ struct device *dev = &pdev->dev;
+ struct reset_control *bus_rst;
+ void __iomem *regs;
+ struct regmap *regmap;
+ struct clk *bus_clk;
+ int ret;
+
+ /*
+ * The NoC display-bus clock and reset gate access to the whole vout
+ * register region, and this subsystem's PHY child is the first device in
+ * that region to touch registers. Bring the bus up here before
+ * populating the children; PD_VOUT is powered on by genpd through the
+ * power-domains property.
+ */
+ bus_clk = devm_clk_get(dev, NULL);
+ if (IS_ERR(bus_clk))
+ return dev_err_probe(dev, PTR_ERR(bus_clk),
+ "Failed to get NoC bus clock\n");
+
+ ret = clk_prepare_enable(bus_clk);
+ if (ret)
+ return dev_err_probe(dev, ret, "Failed to enable NoC bus clock\n");
+
+ ret = devm_add_action_or_reset(dev, starfive_hdmi_subsys_clk_disable, bus_clk);
+ if (ret)
+ return ret;
+
+ bus_rst = devm_reset_control_get_exclusive(dev, NULL);
+ if (IS_ERR(bus_rst))
+ return dev_err_probe(dev, PTR_ERR(bus_rst),
+ "Failed to get NoC bus reset\n");
+
+ ret = reset_control_deassert(bus_rst);
+ if (ret)
+ return dev_err_probe(dev, ret, "Failed to deassert NoC bus reset\n");
+
+ ret = devm_add_action_or_reset(dev, starfive_hdmi_subsys_rst_assert, bus_rst);
+ if (ret)
+ return ret;
+
+ regs = devm_platform_ioremap_resource(pdev, 0);
+ if (IS_ERR(regs))
+ return PTR_ERR(regs);
+
+ regmap = devm_regmap_init_mmio(dev, regs,
+ &starfive_hdmi_regmap_config);
+ if (IS_ERR(regmap))
+ return dev_err_probe(dev, PTR_ERR(regmap),
+ "Failed to init shared regmap\n");
+
+ ret = devm_of_platform_populate(dev);
+ if (ret)
+ dev_err(dev, "Failed to populate child devices: %d\n", ret);
+
+ return ret;
+}
+
+static const struct of_device_id starfive_hdmi_subsys_of_match[] = {
+ { .compatible = "starfive,jh7110-hdmi-subsystem", },
+ { /* sentinel */ }
+};
+MODULE_DEVICE_TABLE(of, starfive_hdmi_subsys_of_match);
+
+static struct platform_driver starfive_hdmi_subsys_driver = {
+ .probe = starfive_hdmi_subsys_probe,
+ .driver = {
+ .name = "starfive-hdmi-subsystem",
+ .of_match_table = starfive_hdmi_subsys_of_match,
+ },
+};
+module_platform_driver(starfive_hdmi_subsys_driver);
+
+MODULE_AUTHOR("Michal Wilczynski <m.wilczynski@samsung.com>");
+MODULE_DESCRIPTION("StarFive JH7110 HDMI subsystem Driver");
+MODULE_LICENSE("GPL");
--
2.34.1
_______________________________________________
Linux-rockchip mailing list
Linux-rockchip@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-rockchip
^ permalink raw reply related [flat|nested] 116+ messages in thread
* [PATCH v2 08/15] soc: starfive: Add jh7110-hdmi-subsystem driver
@ 2026-08-28 13:47 ` Michal Wilczynski
0 siblings, 0 replies; 116+ messages in thread
From: Michal Wilczynski @ 2026-08-28 13:47 UTC (permalink / raw)
To: Vinod Koul, Neil Armstrong, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Andrzej Hajda, Robert Foss, Laurent Pinchart,
Jonas Karlman, Jernej Skrabec, Luca Ceresoli, David Airlie,
Simona Vetter, Maarten Lankhorst, Maxime Ripard,
Thomas Zimmermann, Lee Jones, Andy Yan, Philipp Zabel,
Emil Renner Berthing, Hal Feng, Michael Turquette, Stephen Boyd,
Brian Masney, Heiko Stuebner, Conor Dooley, Paul Walmsley,
Palmer Dabbelt, Albert Ou, Alexandre Ghiti, Dominique Belhachemi
Cc: linux-phy, devicetree, linux-kernel, dri-devel, mfd, linux-clk,
linux-arm-kernel, linux-rockchip, linux-riscv, Icenowy Zheng,
Andy Yan, Marek Szyprowski, Maud Spierings, Graham Markall,
Michal Wilczynski
Add the parent driver for the monolithic JH7110 HDMI IP block.
This driver binds to the starfive,jh7110-hdmi-subsystem node. It maps the
shared register block, creates a regmap, and calls
devm_of_platform_populate() to create its hdmi_phy and hdmi_controller
child devices, which retrieve the shared regmap from this parent.
The NoC display-bus clock and reset gate access to the whole vout register
region, and this subsystem's PHY child is the first device there to touch
registers. Enable the bus before populating the children; PD_VOUT is
handled by genpd through the power-domains property.
Co-developed-by: Dominique Belhachemi <db@domibel.de>
Signed-off-by: Dominique Belhachemi <db@domibel.de>
Signed-off-by: Michal Wilczynski <m.wilczynski@samsung.com>
---
drivers/soc/Kconfig | 1 +
drivers/soc/Makefile | 1 +
drivers/soc/starfive/Kconfig | 27 +++++++
drivers/soc/starfive/Makefile | 2 +
drivers/soc/starfive/jh7110-hdmi-subsystem.c | 114 +++++++++++++++++++++++++++
5 files changed, 145 insertions(+)
diff --git a/drivers/soc/Kconfig b/drivers/soc/Kconfig
index a2d65adffb8052c0ac5a6b60bf33fa9c644701bb..b3b01fc38139d98076c14f626a42ae3b7ef7c5d6 100644
--- a/drivers/soc/Kconfig
+++ b/drivers/soc/Kconfig
@@ -24,6 +24,7 @@ source "drivers/soc/renesas/Kconfig"
source "drivers/soc/rockchip/Kconfig"
source "drivers/soc/samsung/Kconfig"
source "drivers/soc/sophgo/Kconfig"
+source "drivers/soc/starfive/Kconfig"
source "drivers/soc/sunxi/Kconfig"
source "drivers/soc/tegra/Kconfig"
source "drivers/soc/ti/Kconfig"
diff --git a/drivers/soc/Makefile b/drivers/soc/Makefile
index c9e689080ceb759384f690c2b65a82b3cb451c74..009f85ff891a15e0455f92c5d5a4059d8b1fcd3f 100644
--- a/drivers/soc/Makefile
+++ b/drivers/soc/Makefile
@@ -30,6 +30,7 @@ obj-y += renesas/
obj-y += rockchip/
obj-$(CONFIG_SOC_SAMSUNG) += samsung/
obj-y += sophgo/
+obj-y += starfive/
obj-y += sunxi/
obj-$(CONFIG_ARCH_TEGRA) += tegra/
obj-y += ti/
diff --git a/drivers/soc/starfive/Kconfig b/drivers/soc/starfive/Kconfig
new file mode 100644
index 0000000000000000000000000000000000000000..7592d87dea37a7c14560b3eb9b23e49e503c2d71
--- /dev/null
+++ b/drivers/soc/starfive/Kconfig
@@ -0,0 +1,27 @@
+# SPDX-License-Identifier: GPL-2.0-only
+#
+# Starfive SoC drivers
+#
+
+if ARCH_STARFIVE || COMPILE_TEST
+menu "Starfive SoC drivers"
+
+config SOC_STARFIVE_JH7110_HDMI_SUBSYSTEM
+ tristate "StarFive JH7110 HDMI subsystem driver"
+ depends on OF
+ help
+ This option enables the parent driver
+ for the monolithic StarFive JH7110 HDMI peripheral.
+
+ The JH7110 HDMI IP block contains both the digital controller
+ (DRM bridge) and the analog PHY (clock/phy provider) logic within
+ a single shared register space.
+
+ This driver acts as a wrapper. Its only job is to map the
+ shared registers and create separate logical child devices
+ for the "PHY" and the "controller". This is required to
+ correctly manage resources and break a circular clock dependency
+ between the PHY and the VOUT clock generator at probe time.
+
+endmenu
+endif
diff --git a/drivers/soc/starfive/Makefile b/drivers/soc/starfive/Makefile
new file mode 100644
index 0000000000000000000000000000000000000000..be89d8119212b7a7038817c2f0e8eac1984ada88
--- /dev/null
+++ b/drivers/soc/starfive/Makefile
@@ -0,0 +1,2 @@
+# SPDX-License-Identifier: GPL-2.0-only
+obj-$(CONFIG_SOC_STARFIVE_JH7110_HDMI_SUBSYSTEM) += jh7110-hdmi-subsystem.o
diff --git a/drivers/soc/starfive/jh7110-hdmi-subsystem.c b/drivers/soc/starfive/jh7110-hdmi-subsystem.c
new file mode 100644
index 0000000000000000000000000000000000000000..d893c1c29f98b072b09d261343d3317dbf4c75fe
--- /dev/null
+++ b/drivers/soc/starfive/jh7110-hdmi-subsystem.c
@@ -0,0 +1,114 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Driver for the StarFive JH7110 HDMI subsystem
+ *
+ * Copyright (c) 2025 Samsung Electronics Co., Ltd.
+ * Author: Michal Wilczynski <m.wilczynski@samsung.com>
+ *
+ * This driver binds to the monolithic HDMI block and creates separate
+ * logical platform devices for the HDMI Controller (bridge) and the
+ * HDMI PHY (clock/phy provider), allowing them to share a single regmap
+ * and breaking the probing circular dependency.
+ */
+
+#include <linux/clk.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/of_platform.h>
+#include <linux/platform_device.h>
+#include <linux/regmap.h>
+#include <linux/reset.h>
+
+static const struct regmap_config starfive_hdmi_regmap_config = {
+ .reg_bits = 32,
+ .val_bits = 8,
+ .max_register = 0x3fff,
+};
+
+static void starfive_hdmi_subsys_clk_disable(void *data)
+{
+ clk_disable_unprepare(data);
+}
+
+static void starfive_hdmi_subsys_rst_assert(void *data)
+{
+ reset_control_assert(data);
+}
+
+static int starfive_hdmi_subsys_probe(struct platform_device *pdev)
+{
+ struct device *dev = &pdev->dev;
+ struct reset_control *bus_rst;
+ void __iomem *regs;
+ struct regmap *regmap;
+ struct clk *bus_clk;
+ int ret;
+
+ /*
+ * The NoC display-bus clock and reset gate access to the whole vout
+ * register region, and this subsystem's PHY child is the first device in
+ * that region to touch registers. Bring the bus up here before
+ * populating the children; PD_VOUT is powered on by genpd through the
+ * power-domains property.
+ */
+ bus_clk = devm_clk_get(dev, NULL);
+ if (IS_ERR(bus_clk))
+ return dev_err_probe(dev, PTR_ERR(bus_clk),
+ "Failed to get NoC bus clock\n");
+
+ ret = clk_prepare_enable(bus_clk);
+ if (ret)
+ return dev_err_probe(dev, ret, "Failed to enable NoC bus clock\n");
+
+ ret = devm_add_action_or_reset(dev, starfive_hdmi_subsys_clk_disable, bus_clk);
+ if (ret)
+ return ret;
+
+ bus_rst = devm_reset_control_get_exclusive(dev, NULL);
+ if (IS_ERR(bus_rst))
+ return dev_err_probe(dev, PTR_ERR(bus_rst),
+ "Failed to get NoC bus reset\n");
+
+ ret = reset_control_deassert(bus_rst);
+ if (ret)
+ return dev_err_probe(dev, ret, "Failed to deassert NoC bus reset\n");
+
+ ret = devm_add_action_or_reset(dev, starfive_hdmi_subsys_rst_assert, bus_rst);
+ if (ret)
+ return ret;
+
+ regs = devm_platform_ioremap_resource(pdev, 0);
+ if (IS_ERR(regs))
+ return PTR_ERR(regs);
+
+ regmap = devm_regmap_init_mmio(dev, regs,
+ &starfive_hdmi_regmap_config);
+ if (IS_ERR(regmap))
+ return dev_err_probe(dev, PTR_ERR(regmap),
+ "Failed to init shared regmap\n");
+
+ ret = devm_of_platform_populate(dev);
+ if (ret)
+ dev_err(dev, "Failed to populate child devices: %d\n", ret);
+
+ return ret;
+}
+
+static const struct of_device_id starfive_hdmi_subsys_of_match[] = {
+ { .compatible = "starfive,jh7110-hdmi-subsystem", },
+ { /* sentinel */ }
+};
+MODULE_DEVICE_TABLE(of, starfive_hdmi_subsys_of_match);
+
+static struct platform_driver starfive_hdmi_subsys_driver = {
+ .probe = starfive_hdmi_subsys_probe,
+ .driver = {
+ .name = "starfive-hdmi-subsystem",
+ .of_match_table = starfive_hdmi_subsys_of_match,
+ },
+};
+module_platform_driver(starfive_hdmi_subsys_driver);
+
+MODULE_AUTHOR("Michal Wilczynski <m.wilczynski@samsung.com>");
+MODULE_DESCRIPTION("StarFive JH7110 HDMI subsystem Driver");
+MODULE_LICENSE("GPL");
--
2.34.1
--
linux-phy mailing list
linux-phy@lists.infradead.org
https://lists.infradead.org/mailman/listinfo/linux-phy
^ permalink raw reply related [flat|nested] 116+ messages in thread
* [PATCH v2 09/15] clk: starfive: jh7110-vout: Allow pixel clock rate propagation
2026-08-28 13:47 ` Michal Wilczynski
(?)
(?)
@ 2026-08-28 13:47 ` Michal Wilczynski
-1 siblings, 0 replies; 116+ messages in thread
From: Michal Wilczynski @ 2026-08-28 13:47 UTC (permalink / raw)
To: Vinod Koul, Neil Armstrong, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Andrzej Hajda, Robert Foss, Laurent Pinchart,
Jonas Karlman, Jernej Skrabec, Luca Ceresoli, David Airlie,
Simona Vetter, Maarten Lankhorst, Maxime Ripard,
Thomas Zimmermann, Lee Jones, Andy Yan, Philipp Zabel,
Emil Renner Berthing, Hal Feng, Michael Turquette, Stephen Boyd,
Brian Masney, Heiko Stuebner, Conor Dooley, Paul Walmsley,
Palmer Dabbelt, Albert Ou, Alexandre Ghiti, Dominique Belhachemi
Cc: linux-phy, devicetree, linux-kernel, dri-devel, mfd, linux-clk,
linux-arm-kernel, linux-rockchip, linux-riscv, Icenowy Zheng,
Andy Yan, Marek Szyprowski, Maud Spierings, Graham Markall,
Michal Wilczynski
The dc8200_pix0 and dc8200_pix1 MUXes feed the display controller, and
the rate they carry is ultimately produced by the HDMI PHY, which
registers hdmitx0_pixelclk as a clock provider.
Add CLK_SET_RATE_PARENT to both MUXes so a rate requested on them
reaches that parent, instead of being clamped to whatever rate the
parent already happens to run at.
Co-developed-by: Dominique Belhachemi <db@domibel.de>
Signed-off-by: Dominique Belhachemi <db@domibel.de>
Signed-off-by: Michal Wilczynski <m.wilczynski@samsung.com>
---
drivers/clk/starfive/clk-starfive-jh7110-vout.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/drivers/clk/starfive/clk-starfive-jh7110-vout.c b/drivers/clk/starfive/clk-starfive-jh7110-vout.c
index bad20d5d794a72f071b4d547b7304786a8ba9afa..b608fe358031109a15962a623b1c14d424023c02 100644
--- a/drivers/clk/starfive/clk-starfive-jh7110-vout.c
+++ b/drivers/clk/starfive/clk-starfive-jh7110-vout.c
@@ -40,10 +40,10 @@ static const struct jh71x0_clk_data jh7110_voutclk_data[] = {
JH71X0_GATE(JH7110_VOUTCLK_DC8200_AXI, "dc8200_axi", 0, JH7110_VOUTCLK_VOUT_TOP_AXI),
JH71X0_GATE(JH7110_VOUTCLK_DC8200_CORE, "dc8200_core", 0, JH7110_VOUTCLK_VOUT_TOP_AXI),
JH71X0_GATE(JH7110_VOUTCLK_DC8200_AHB, "dc8200_ahb", 0, JH7110_VOUTCLK_VOUT_TOP_AHB),
- JH71X0_GMUX(JH7110_VOUTCLK_DC8200_PIX0, "dc8200_pix0", 0, 2,
+ JH71X0_GMUX(JH7110_VOUTCLK_DC8200_PIX0, "dc8200_pix0", CLK_SET_RATE_PARENT, 2,
JH7110_VOUTCLK_DC8200_PIX,
JH7110_VOUTCLK_HDMITX0_PIXELCLK),
- JH71X0_GMUX(JH7110_VOUTCLK_DC8200_PIX1, "dc8200_pix1", 0, 2,
+ JH71X0_GMUX(JH7110_VOUTCLK_DC8200_PIX1, "dc8200_pix1", CLK_SET_RATE_PARENT, 2,
JH7110_VOUTCLK_DC8200_PIX,
JH7110_VOUTCLK_HDMITX0_PIXELCLK),
/* LCD */
--
2.34.1
^ permalink raw reply related [flat|nested] 116+ messages in thread
* [PATCH v2 09/15] clk: starfive: jh7110-vout: Allow pixel clock rate propagation
@ 2026-08-28 13:47 ` Michal Wilczynski
0 siblings, 0 replies; 116+ messages in thread
From: Michal Wilczynski @ 2026-08-28 13:47 UTC (permalink / raw)
To: Vinod Koul, Neil Armstrong, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Andrzej Hajda, Robert Foss, Laurent Pinchart,
Jonas Karlman, Jernej Skrabec, Luca Ceresoli, David Airlie,
Simona Vetter, Maarten Lankhorst, Maxime Ripard,
Thomas Zimmermann, Lee Jones, Andy Yan, Philipp Zabel,
Emil Renner Berthing, Hal Feng, Michael Turquette, Stephen Boyd,
Brian Masney, Heiko Stuebner, Conor Dooley, Paul Walmsley,
Palmer Dabbelt, Albert Ou, Alexandre Ghiti, Dominique Belhachemi
Cc: devicetree, mfd, linux-kernel, dri-devel, Andy Yan,
Graham Markall, linux-rockchip, linux-phy, Michal Wilczynski,
linux-riscv, Maud Spierings, linux-clk, linux-arm-kernel,
Marek Szyprowski
The dc8200_pix0 and dc8200_pix1 MUXes feed the display controller, and
the rate they carry is ultimately produced by the HDMI PHY, which
registers hdmitx0_pixelclk as a clock provider.
Add CLK_SET_RATE_PARENT to both MUXes so a rate requested on them
reaches that parent, instead of being clamped to whatever rate the
parent already happens to run at.
Co-developed-by: Dominique Belhachemi <db@domibel.de>
Signed-off-by: Dominique Belhachemi <db@domibel.de>
Signed-off-by: Michal Wilczynski <m.wilczynski@samsung.com>
---
drivers/clk/starfive/clk-starfive-jh7110-vout.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/drivers/clk/starfive/clk-starfive-jh7110-vout.c b/drivers/clk/starfive/clk-starfive-jh7110-vout.c
index bad20d5d794a72f071b4d547b7304786a8ba9afa..b608fe358031109a15962a623b1c14d424023c02 100644
--- a/drivers/clk/starfive/clk-starfive-jh7110-vout.c
+++ b/drivers/clk/starfive/clk-starfive-jh7110-vout.c
@@ -40,10 +40,10 @@ static const struct jh71x0_clk_data jh7110_voutclk_data[] = {
JH71X0_GATE(JH7110_VOUTCLK_DC8200_AXI, "dc8200_axi", 0, JH7110_VOUTCLK_VOUT_TOP_AXI),
JH71X0_GATE(JH7110_VOUTCLK_DC8200_CORE, "dc8200_core", 0, JH7110_VOUTCLK_VOUT_TOP_AXI),
JH71X0_GATE(JH7110_VOUTCLK_DC8200_AHB, "dc8200_ahb", 0, JH7110_VOUTCLK_VOUT_TOP_AHB),
- JH71X0_GMUX(JH7110_VOUTCLK_DC8200_PIX0, "dc8200_pix0", 0, 2,
+ JH71X0_GMUX(JH7110_VOUTCLK_DC8200_PIX0, "dc8200_pix0", CLK_SET_RATE_PARENT, 2,
JH7110_VOUTCLK_DC8200_PIX,
JH7110_VOUTCLK_HDMITX0_PIXELCLK),
- JH71X0_GMUX(JH7110_VOUTCLK_DC8200_PIX1, "dc8200_pix1", 0, 2,
+ JH71X0_GMUX(JH7110_VOUTCLK_DC8200_PIX1, "dc8200_pix1", CLK_SET_RATE_PARENT, 2,
JH7110_VOUTCLK_DC8200_PIX,
JH7110_VOUTCLK_HDMITX0_PIXELCLK),
/* LCD */
--
2.34.1
_______________________________________________
linux-riscv mailing list
linux-riscv@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-riscv
^ permalink raw reply related [flat|nested] 116+ messages in thread
* [PATCH v2 09/15] clk: starfive: jh7110-vout: Allow pixel clock rate propagation
@ 2026-08-28 13:47 ` Michal Wilczynski
0 siblings, 0 replies; 116+ messages in thread
From: Michal Wilczynski @ 2026-08-28 13:47 UTC (permalink / raw)
To: Vinod Koul, Neil Armstrong, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Andrzej Hajda, Robert Foss, Laurent Pinchart,
Jonas Karlman, Jernej Skrabec, Luca Ceresoli, David Airlie,
Simona Vetter, Maarten Lankhorst, Maxime Ripard,
Thomas Zimmermann, Lee Jones, Andy Yan, Philipp Zabel,
Emil Renner Berthing, Hal Feng, Michael Turquette, Stephen Boyd,
Brian Masney, Heiko Stuebner, Conor Dooley, Paul Walmsley,
Palmer Dabbelt, Albert Ou, Alexandre Ghiti, Dominique Belhachemi
Cc: linux-phy, devicetree, linux-kernel, dri-devel, mfd, linux-clk,
linux-arm-kernel, linux-rockchip, linux-riscv, Icenowy Zheng,
Andy Yan, Marek Szyprowski, Maud Spierings, Graham Markall,
Michal Wilczynski
The dc8200_pix0 and dc8200_pix1 MUXes feed the display controller, and
the rate they carry is ultimately produced by the HDMI PHY, which
registers hdmitx0_pixelclk as a clock provider.
Add CLK_SET_RATE_PARENT to both MUXes so a rate requested on them
reaches that parent, instead of being clamped to whatever rate the
parent already happens to run at.
Co-developed-by: Dominique Belhachemi <db@domibel.de>
Signed-off-by: Dominique Belhachemi <db@domibel.de>
Signed-off-by: Michal Wilczynski <m.wilczynski@samsung.com>
---
drivers/clk/starfive/clk-starfive-jh7110-vout.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/drivers/clk/starfive/clk-starfive-jh7110-vout.c b/drivers/clk/starfive/clk-starfive-jh7110-vout.c
index bad20d5d794a72f071b4d547b7304786a8ba9afa..b608fe358031109a15962a623b1c14d424023c02 100644
--- a/drivers/clk/starfive/clk-starfive-jh7110-vout.c
+++ b/drivers/clk/starfive/clk-starfive-jh7110-vout.c
@@ -40,10 +40,10 @@ static const struct jh71x0_clk_data jh7110_voutclk_data[] = {
JH71X0_GATE(JH7110_VOUTCLK_DC8200_AXI, "dc8200_axi", 0, JH7110_VOUTCLK_VOUT_TOP_AXI),
JH71X0_GATE(JH7110_VOUTCLK_DC8200_CORE, "dc8200_core", 0, JH7110_VOUTCLK_VOUT_TOP_AXI),
JH71X0_GATE(JH7110_VOUTCLK_DC8200_AHB, "dc8200_ahb", 0, JH7110_VOUTCLK_VOUT_TOP_AHB),
- JH71X0_GMUX(JH7110_VOUTCLK_DC8200_PIX0, "dc8200_pix0", 0, 2,
+ JH71X0_GMUX(JH7110_VOUTCLK_DC8200_PIX0, "dc8200_pix0", CLK_SET_RATE_PARENT, 2,
JH7110_VOUTCLK_DC8200_PIX,
JH7110_VOUTCLK_HDMITX0_PIXELCLK),
- JH71X0_GMUX(JH7110_VOUTCLK_DC8200_PIX1, "dc8200_pix1", 0, 2,
+ JH71X0_GMUX(JH7110_VOUTCLK_DC8200_PIX1, "dc8200_pix1", CLK_SET_RATE_PARENT, 2,
JH7110_VOUTCLK_DC8200_PIX,
JH7110_VOUTCLK_HDMITX0_PIXELCLK),
/* LCD */
--
2.34.1
_______________________________________________
Linux-rockchip mailing list
Linux-rockchip@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-rockchip
^ permalink raw reply related [flat|nested] 116+ messages in thread
* [PATCH v2 09/15] clk: starfive: jh7110-vout: Allow pixel clock rate propagation
@ 2026-08-28 13:47 ` Michal Wilczynski
0 siblings, 0 replies; 116+ messages in thread
From: Michal Wilczynski @ 2026-08-28 13:47 UTC (permalink / raw)
To: Vinod Koul, Neil Armstrong, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Andrzej Hajda, Robert Foss, Laurent Pinchart,
Jonas Karlman, Jernej Skrabec, Luca Ceresoli, David Airlie,
Simona Vetter, Maarten Lankhorst, Maxime Ripard,
Thomas Zimmermann, Lee Jones, Andy Yan, Philipp Zabel,
Emil Renner Berthing, Hal Feng, Michael Turquette, Stephen Boyd,
Brian Masney, Heiko Stuebner, Conor Dooley, Paul Walmsley,
Palmer Dabbelt, Albert Ou, Alexandre Ghiti, Dominique Belhachemi
Cc: linux-phy, devicetree, linux-kernel, dri-devel, mfd, linux-clk,
linux-arm-kernel, linux-rockchip, linux-riscv, Icenowy Zheng,
Andy Yan, Marek Szyprowski, Maud Spierings, Graham Markall,
Michal Wilczynski
The dc8200_pix0 and dc8200_pix1 MUXes feed the display controller, and
the rate they carry is ultimately produced by the HDMI PHY, which
registers hdmitx0_pixelclk as a clock provider.
Add CLK_SET_RATE_PARENT to both MUXes so a rate requested on them
reaches that parent, instead of being clamped to whatever rate the
parent already happens to run at.
Co-developed-by: Dominique Belhachemi <db@domibel.de>
Signed-off-by: Dominique Belhachemi <db@domibel.de>
Signed-off-by: Michal Wilczynski <m.wilczynski@samsung.com>
---
drivers/clk/starfive/clk-starfive-jh7110-vout.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/drivers/clk/starfive/clk-starfive-jh7110-vout.c b/drivers/clk/starfive/clk-starfive-jh7110-vout.c
index bad20d5d794a72f071b4d547b7304786a8ba9afa..b608fe358031109a15962a623b1c14d424023c02 100644
--- a/drivers/clk/starfive/clk-starfive-jh7110-vout.c
+++ b/drivers/clk/starfive/clk-starfive-jh7110-vout.c
@@ -40,10 +40,10 @@ static const struct jh71x0_clk_data jh7110_voutclk_data[] = {
JH71X0_GATE(JH7110_VOUTCLK_DC8200_AXI, "dc8200_axi", 0, JH7110_VOUTCLK_VOUT_TOP_AXI),
JH71X0_GATE(JH7110_VOUTCLK_DC8200_CORE, "dc8200_core", 0, JH7110_VOUTCLK_VOUT_TOP_AXI),
JH71X0_GATE(JH7110_VOUTCLK_DC8200_AHB, "dc8200_ahb", 0, JH7110_VOUTCLK_VOUT_TOP_AHB),
- JH71X0_GMUX(JH7110_VOUTCLK_DC8200_PIX0, "dc8200_pix0", 0, 2,
+ JH71X0_GMUX(JH7110_VOUTCLK_DC8200_PIX0, "dc8200_pix0", CLK_SET_RATE_PARENT, 2,
JH7110_VOUTCLK_DC8200_PIX,
JH7110_VOUTCLK_HDMITX0_PIXELCLK),
- JH71X0_GMUX(JH7110_VOUTCLK_DC8200_PIX1, "dc8200_pix1", 0, 2,
+ JH71X0_GMUX(JH7110_VOUTCLK_DC8200_PIX1, "dc8200_pix1", CLK_SET_RATE_PARENT, 2,
JH7110_VOUTCLK_DC8200_PIX,
JH7110_VOUTCLK_HDMITX0_PIXELCLK),
/* LCD */
--
2.34.1
--
linux-phy mailing list
linux-phy@lists.infradead.org
https://lists.infradead.org/mailman/listinfo/linux-phy
^ permalink raw reply related [flat|nested] 116+ messages in thread
* [PATCH v2 10/15] drm/bridge: starfive: Add JH7110 HDMI controller driver
2026-08-28 13:47 ` Michal Wilczynski
(?)
(?)
@ 2026-08-28 13:47 ` Michal Wilczynski
-1 siblings, 0 replies; 116+ messages in thread
From: Michal Wilczynski @ 2026-08-28 13:47 UTC (permalink / raw)
To: Vinod Koul, Neil Armstrong, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Andrzej Hajda, Robert Foss, Laurent Pinchart,
Jonas Karlman, Jernej Skrabec, Luca Ceresoli, David Airlie,
Simona Vetter, Maarten Lankhorst, Maxime Ripard,
Thomas Zimmermann, Lee Jones, Andy Yan, Philipp Zabel,
Emil Renner Berthing, Hal Feng, Michael Turquette, Stephen Boyd,
Brian Masney, Heiko Stuebner, Conor Dooley, Paul Walmsley,
Palmer Dabbelt, Albert Ou, Alexandre Ghiti, Dominique Belhachemi
Cc: linux-phy, devicetree, linux-kernel, dri-devel, mfd, linux-clk,
linux-arm-kernel, linux-rockchip, linux-riscv, Icenowy Zheng,
Andy Yan, Marek Szyprowski, Maud Spierings, Graham Markall,
Michal Wilczynski
Add the HDMI controller (bridge) driver for the StarFive JH7110.
This driver binds to the starfive,jh7110-inno-hdmi-controller node.
It gets its shared regmap from its parent and its clocks (sys, mclk,
bclk) from voutcrg. It consumes the pclk (pixel clock) and PHY from its
hdmi_phy sibling.
The driver calls the generic inno_hdmi_probe function and passes the
shared regmap to it, registering as a DRM bridge. The .enable hook is
responsible for setting the PHY's pixel clock rate via clk_set_rate()
and powering on the PHY via phy_power_on().
The PHY can only generate the discrete set of pixel clocks described by
its pre-PLL table, so .mode_valid rejects any mode clk_round_rate()
cannot satisfy. Without it such a mode would be advertised to userspace
and the modeset would appear to succeed while the display stayed blank.
.enable returns early when the rate is unsupported or the PHY fails to
power on, so track whether the pixel clock was actually enabled and let
.disable tear down only what was brought up, otherwise the clock
refcount underflows.
Signed-off-by: Michal Wilczynski <m.wilczynski@samsung.com>
---
drivers/gpu/drm/bridge/Kconfig | 11 ++
drivers/gpu/drm/bridge/Makefile | 1 +
drivers/gpu/drm/bridge/jh7110-inno-hdmi.c | 224 ++++++++++++++++++++++++++++++
3 files changed, 236 insertions(+)
diff --git a/drivers/gpu/drm/bridge/Kconfig b/drivers/gpu/drm/bridge/Kconfig
index 4a57d49b4c6d3ab4b965228835b372d191647197..75b1cf6727d5a32310dcf9fe5734d95e14eea8fe 100644
--- a/drivers/gpu/drm/bridge/Kconfig
+++ b/drivers/gpu/drm/bridge/Kconfig
@@ -359,6 +359,17 @@ config DRM_SOLOMON_SSD2825
Say M here if you want to support this hardware as a module.
The module will be named "ssd2825".
+config DRM_STARFIVE_JH7110_INNO_HDMI
+ tristate "Starfive JH7110 Innosilicon HDMI bridge"
+ depends on OF
+ depends on ARCH_STARFIVE || COMPILE_TEST
+ select DRM_INNO_HDMI
+ help
+ Enable support for the StarFive JH7110 specific implementation
+ of the Innosilicon HDMI controller.
+ This driver acts as a glue layer between the JH7110 HDMI subsystem
+ parent driver and the generic Innosilicon HDMI bridge driver.
+
config DRM_THINE_THC63LVD1024
tristate "Thine THC63LVD1024 LVDS decoder bridge"
depends on OF
diff --git a/drivers/gpu/drm/bridge/Makefile b/drivers/gpu/drm/bridge/Makefile
index 15cc821d85b7ea6f3cdc313f3e521b028de567d7..5d843f4ad7ed50b28cb75286c5e22789d91a0836 100644
--- a/drivers/gpu/drm/bridge/Makefile
+++ b/drivers/gpu/drm/bridge/Makefile
@@ -30,6 +30,7 @@ obj-$(CONFIG_DRM_SIL_SII8620) += sil-sii8620.o
obj-$(CONFIG_DRM_SII902X) += sii902x.o
obj-$(CONFIG_DRM_SII9234) += sii9234.o
obj-$(CONFIG_DRM_SIMPLE_BRIDGE) += simple-bridge.o
+obj-$(CONFIG_DRM_STARFIVE_JH7110_INNO_HDMI) += jh7110-inno-hdmi.o
obj-$(CONFIG_DRM_SOLOMON_SSD2825) += ssd2825.o
obj-$(CONFIG_DRM_THEAD_TH1520_DW_HDMI) += th1520-dw-hdmi.o
obj-$(CONFIG_DRM_THINE_THC63LVD1024) += thc63lvd1024.o
diff --git a/drivers/gpu/drm/bridge/jh7110-inno-hdmi.c b/drivers/gpu/drm/bridge/jh7110-inno-hdmi.c
new file mode 100644
index 0000000000000000000000000000000000000000..be865aa39e33f70614fa7cb58a683b9fcf051599
--- /dev/null
+++ b/drivers/gpu/drm/bridge/jh7110-inno-hdmi.c
@@ -0,0 +1,224 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) StarFive Technology Co., Ltd.
+ * Copyright (c) 2025 Samsung Electronics Co., Ltd.
+ * Author: Michal Wilczynski <m.wilczynski@samsung.com>
+ *
+ * HDMI controller (bridge) driver for the StarFive JH7110 HDMI subsystem.
+ */
+
+#include <linux/clk.h>
+#include <linux/mod_devicetable.h>
+#include <linux/module.h>
+#include <linux/of_device.h>
+#include <linux/platform_device.h>
+#include <linux/phy/phy.h>
+#include <linux/regmap.h>
+#include <linux/reset.h>
+
+#include <drm/bridge/inno_hdmi.h>
+#include <drm/drm_modes.h>
+
+enum stf_hdmi_ctrl_clocks { CLK_SYS = 0, CLK_M, CLK_B, CLK_PCLK, CLK_CTRL_NUM };
+
+struct stf_inno_hdmi_controller {
+ struct device *dev;
+ struct clk_bulk_data clks[CLK_CTRL_NUM];
+ struct reset_control *tx_rst;
+ struct phy *phy;
+ bool enabled;
+};
+
+static enum drm_mode_status
+inno_hdmi_starfive_mode_valid(struct device *dev,
+ const struct drm_display_mode *mode)
+{
+ struct stf_inno_hdmi_controller *ctrl = dev_get_drvdata(dev);
+ unsigned long pixelclk = mode->clock * 1000;
+ long rounded;
+
+ /*
+ * The PHY can only generate the discrete set of pixel clocks described
+ * by its pre-PLL table, and clk_round_rate() fails for anything else.
+ * Reject those modes here: without this the modeset would appear to
+ * succeed while the PHY never produces a signal.
+ */
+ rounded = clk_round_rate(ctrl->clks[CLK_PCLK].clk, pixelclk);
+ if (rounded < 0 || rounded != pixelclk)
+ return MODE_NOCLOCK;
+
+ return MODE_OK;
+}
+
+static void inno_hdmi_starfive_enable(struct device *dev,
+ struct drm_display_mode *mode)
+{
+ struct stf_inno_hdmi_controller *ctrl = dev_get_drvdata(dev);
+ int ret;
+
+ /*
+ * 1. Set the pixel clock rate. This calls the PHY driver's .set_rate op.
+ */
+ ret = clk_set_rate(ctrl->clks[CLK_PCLK].clk, mode->clock * 1000);
+ if (ret) {
+ dev_err(dev, "Failed to set pclk rate %d: %d\n",
+ mode->clock * 1000, ret);
+ return;
+ }
+
+ /*
+ * 2. Enable the pixel clock. This calls the PHY driver's .prepare op.
+ */
+ ret = clk_prepare_enable(ctrl->clks[CLK_PCLK].clk);
+ if (ret) {
+ dev_err(dev, "Failed to enable pclk: %d\n", ret);
+ return;
+ }
+
+ /*
+ * 3. Power on the PHY. This calls the PHY driver's .power_on op,
+ * which configures the Post-PLL and analog blocks.
+ */
+ ret = phy_power_on(ctrl->phy);
+ if (ret) {
+ dev_err(dev, "Failed to power on PHY: %d\n", ret);
+ clk_disable_unprepare(ctrl->clks[CLK_PCLK].clk);
+ return;
+ }
+
+ ctrl->enabled = true;
+}
+
+static void inno_hdmi_starfive_disable(struct device *dev)
+{
+ struct stf_inno_hdmi_controller *ctrl = dev_get_drvdata(dev);
+
+ /*
+ * .enable bails out early if the pixel clock rate is unsupported or
+ * the PHY fails to power on, leaving pclk and the PHY untouched.
+ * Only tear down what was actually brought up, otherwise the clock
+ * refcount underflows.
+ */
+ if (!ctrl->enabled)
+ return;
+
+ phy_power_off(ctrl->phy);
+ clk_disable_unprepare(ctrl->clks[CLK_PCLK].clk);
+ ctrl->enabled = false;
+}
+
+static int starfive_inno_hdmi_controller_probe(struct platform_device *pdev)
+{
+ struct device *dev = &pdev->dev;
+ struct device *parent = dev->parent;
+ struct stf_inno_hdmi_controller *ctrl;
+ const struct inno_hdmi_plat_data *plat_data;
+ struct regmap *regmap;
+ struct inno_hdmi *inno;
+ int ret;
+
+ ctrl = devm_kzalloc(dev, sizeof(*ctrl), GFP_KERNEL);
+ if (!ctrl)
+ return -ENOMEM;
+
+ ctrl->dev = dev;
+ platform_set_drvdata(pdev, ctrl);
+
+ /* Get the shared regmap from the parent */
+ regmap = dev_get_regmap(parent, NULL);
+ if (!regmap) {
+ dev_err(dev, "Failed to get parent regmap\n");
+ return -ENODEV;
+ }
+
+ ctrl->phy = devm_phy_get(dev, "hdmi-phy");
+ if (IS_ERR(ctrl->phy))
+ return dev_err_probe(dev, PTR_ERR(ctrl->phy), "Failed to get PHY\n");
+
+ ctrl->tx_rst = devm_reset_control_get_exclusive(dev, "hdmi_tx");
+ if (IS_ERR(ctrl->tx_rst))
+ return dev_err_probe(dev, PTR_ERR(ctrl->tx_rst), "failed to get tx reset\n");
+
+ /* Populate the clock names this controller *consumes* */
+ ctrl->clks[CLK_SYS].id = "sys";
+ ctrl->clks[CLK_M].id = "mclk";
+ ctrl->clks[CLK_B].id = "bclk";
+ ctrl->clks[CLK_PCLK].id = "pclk"; /* Pixel clock *from* PHY */
+
+ ret = devm_clk_bulk_get(dev, CLK_CTRL_NUM, ctrl->clks);
+ if (ret)
+ return dev_err_probe(dev, ret, "Unable to get controller clocks\n");
+
+ /* pclk is enabled on demand during modeset */
+ ret = clk_bulk_prepare_enable(CLK_CTRL_NUM - 1, ctrl->clks);
+ if (ret)
+ return ret;
+
+ ret = reset_control_deassert(ctrl->tx_rst);
+ if (ret) {
+ clk_bulk_disable_unprepare(CLK_CTRL_NUM - 1, ctrl->clks);
+ return ret;
+ }
+
+ plat_data = of_device_get_match_data(dev);
+
+ /* Hand off to the generic library to create the bridge. */
+ inno = inno_hdmi_probe(pdev, plat_data);
+ if (IS_ERR(inno)) {
+ reset_control_assert(ctrl->tx_rst);
+ clk_bulk_disable_unprepare(CLK_CTRL_NUM - 1, ctrl->clks);
+ return PTR_ERR(inno);
+ }
+
+ return 0;
+}
+
+static void starfive_inno_hdmi_controller_remove(struct platform_device *pdev)
+{
+ struct stf_inno_hdmi_controller *ctrl = platform_get_drvdata(pdev);
+
+ reset_control_assert(ctrl->tx_rst);
+ clk_bulk_disable_unprepare(CLK_CTRL_NUM - 1, ctrl->clks);
+}
+
+/*
+ * This table is now only used for the generic .mode_valid check.
+ * The real validation happens in the PHY driver's .round_rate.
+ */
+static struct inno_hdmi_phy_config stf_hdmi_phy_configs[] = {
+ { 297000000, 0x00, 0x00 },
+ { ~0UL, 0x00, 0x00 }, /* Sentinel */
+};
+
+static const struct inno_hdmi_plat_ops stf_inno_hdmi_plat_ops = {
+ .enable = inno_hdmi_starfive_enable,
+ .disable = inno_hdmi_starfive_disable,
+ .mode_valid = inno_hdmi_starfive_mode_valid,
+};
+
+static const struct inno_hdmi_plat_data stf_inno_hdmi_plat_data = {
+ .ops = &stf_inno_hdmi_plat_ops,
+ .phy_configs = stf_hdmi_phy_configs,
+ .default_phy_config = &stf_hdmi_phy_configs[0],
+};
+
+static const struct of_device_id starfive_hdmi_controller_dt_ids[] = {
+ { .compatible = "starfive,jh7110-inno-hdmi-controller",
+ .data = &stf_inno_hdmi_plat_data },
+ {}
+};
+MODULE_DEVICE_TABLE(of, starfive_hdmi_controller_dt_ids);
+
+struct platform_driver starfive_inno_hdmi_controller_driver = {
+ .probe = starfive_inno_hdmi_controller_probe,
+ .remove = starfive_inno_hdmi_controller_remove,
+ .driver = {
+ .name = "starfive-inno-hdmi-controller",
+ .of_match_table = starfive_hdmi_controller_dt_ids,
+ },
+};
+module_platform_driver(starfive_inno_hdmi_controller_driver);
+
+MODULE_AUTHOR("Michal Wilczynski <m.wilczynski@samsung.com>");
+MODULE_DESCRIPTION("StarFive INNO HDMI Controller Driver");
+MODULE_LICENSE("GPL");
--
2.34.1
^ permalink raw reply related [flat|nested] 116+ messages in thread
* [PATCH v2 10/15] drm/bridge: starfive: Add JH7110 HDMI controller driver
@ 2026-08-28 13:47 ` Michal Wilczynski
0 siblings, 0 replies; 116+ messages in thread
From: Michal Wilczynski @ 2026-08-28 13:47 UTC (permalink / raw)
To: Vinod Koul, Neil Armstrong, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Andrzej Hajda, Robert Foss, Laurent Pinchart,
Jonas Karlman, Jernej Skrabec, Luca Ceresoli, David Airlie,
Simona Vetter, Maarten Lankhorst, Maxime Ripard,
Thomas Zimmermann, Lee Jones, Andy Yan, Philipp Zabel,
Emil Renner Berthing, Hal Feng, Michael Turquette, Stephen Boyd,
Brian Masney, Heiko Stuebner, Conor Dooley, Paul Walmsley,
Palmer Dabbelt, Albert Ou, Alexandre Ghiti, Dominique Belhachemi
Cc: devicetree, mfd, linux-kernel, dri-devel, Andy Yan,
Graham Markall, linux-rockchip, linux-phy, Michal Wilczynski,
linux-riscv, Maud Spierings, linux-clk, linux-arm-kernel,
Marek Szyprowski
Add the HDMI controller (bridge) driver for the StarFive JH7110.
This driver binds to the starfive,jh7110-inno-hdmi-controller node.
It gets its shared regmap from its parent and its clocks (sys, mclk,
bclk) from voutcrg. It consumes the pclk (pixel clock) and PHY from its
hdmi_phy sibling.
The driver calls the generic inno_hdmi_probe function and passes the
shared regmap to it, registering as a DRM bridge. The .enable hook is
responsible for setting the PHY's pixel clock rate via clk_set_rate()
and powering on the PHY via phy_power_on().
The PHY can only generate the discrete set of pixel clocks described by
its pre-PLL table, so .mode_valid rejects any mode clk_round_rate()
cannot satisfy. Without it such a mode would be advertised to userspace
and the modeset would appear to succeed while the display stayed blank.
.enable returns early when the rate is unsupported or the PHY fails to
power on, so track whether the pixel clock was actually enabled and let
.disable tear down only what was brought up, otherwise the clock
refcount underflows.
Signed-off-by: Michal Wilczynski <m.wilczynski@samsung.com>
---
drivers/gpu/drm/bridge/Kconfig | 11 ++
drivers/gpu/drm/bridge/Makefile | 1 +
drivers/gpu/drm/bridge/jh7110-inno-hdmi.c | 224 ++++++++++++++++++++++++++++++
3 files changed, 236 insertions(+)
diff --git a/drivers/gpu/drm/bridge/Kconfig b/drivers/gpu/drm/bridge/Kconfig
index 4a57d49b4c6d3ab4b965228835b372d191647197..75b1cf6727d5a32310dcf9fe5734d95e14eea8fe 100644
--- a/drivers/gpu/drm/bridge/Kconfig
+++ b/drivers/gpu/drm/bridge/Kconfig
@@ -359,6 +359,17 @@ config DRM_SOLOMON_SSD2825
Say M here if you want to support this hardware as a module.
The module will be named "ssd2825".
+config DRM_STARFIVE_JH7110_INNO_HDMI
+ tristate "Starfive JH7110 Innosilicon HDMI bridge"
+ depends on OF
+ depends on ARCH_STARFIVE || COMPILE_TEST
+ select DRM_INNO_HDMI
+ help
+ Enable support for the StarFive JH7110 specific implementation
+ of the Innosilicon HDMI controller.
+ This driver acts as a glue layer between the JH7110 HDMI subsystem
+ parent driver and the generic Innosilicon HDMI bridge driver.
+
config DRM_THINE_THC63LVD1024
tristate "Thine THC63LVD1024 LVDS decoder bridge"
depends on OF
diff --git a/drivers/gpu/drm/bridge/Makefile b/drivers/gpu/drm/bridge/Makefile
index 15cc821d85b7ea6f3cdc313f3e521b028de567d7..5d843f4ad7ed50b28cb75286c5e22789d91a0836 100644
--- a/drivers/gpu/drm/bridge/Makefile
+++ b/drivers/gpu/drm/bridge/Makefile
@@ -30,6 +30,7 @@ obj-$(CONFIG_DRM_SIL_SII8620) += sil-sii8620.o
obj-$(CONFIG_DRM_SII902X) += sii902x.o
obj-$(CONFIG_DRM_SII9234) += sii9234.o
obj-$(CONFIG_DRM_SIMPLE_BRIDGE) += simple-bridge.o
+obj-$(CONFIG_DRM_STARFIVE_JH7110_INNO_HDMI) += jh7110-inno-hdmi.o
obj-$(CONFIG_DRM_SOLOMON_SSD2825) += ssd2825.o
obj-$(CONFIG_DRM_THEAD_TH1520_DW_HDMI) += th1520-dw-hdmi.o
obj-$(CONFIG_DRM_THINE_THC63LVD1024) += thc63lvd1024.o
diff --git a/drivers/gpu/drm/bridge/jh7110-inno-hdmi.c b/drivers/gpu/drm/bridge/jh7110-inno-hdmi.c
new file mode 100644
index 0000000000000000000000000000000000000000..be865aa39e33f70614fa7cb58a683b9fcf051599
--- /dev/null
+++ b/drivers/gpu/drm/bridge/jh7110-inno-hdmi.c
@@ -0,0 +1,224 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) StarFive Technology Co., Ltd.
+ * Copyright (c) 2025 Samsung Electronics Co., Ltd.
+ * Author: Michal Wilczynski <m.wilczynski@samsung.com>
+ *
+ * HDMI controller (bridge) driver for the StarFive JH7110 HDMI subsystem.
+ */
+
+#include <linux/clk.h>
+#include <linux/mod_devicetable.h>
+#include <linux/module.h>
+#include <linux/of_device.h>
+#include <linux/platform_device.h>
+#include <linux/phy/phy.h>
+#include <linux/regmap.h>
+#include <linux/reset.h>
+
+#include <drm/bridge/inno_hdmi.h>
+#include <drm/drm_modes.h>
+
+enum stf_hdmi_ctrl_clocks { CLK_SYS = 0, CLK_M, CLK_B, CLK_PCLK, CLK_CTRL_NUM };
+
+struct stf_inno_hdmi_controller {
+ struct device *dev;
+ struct clk_bulk_data clks[CLK_CTRL_NUM];
+ struct reset_control *tx_rst;
+ struct phy *phy;
+ bool enabled;
+};
+
+static enum drm_mode_status
+inno_hdmi_starfive_mode_valid(struct device *dev,
+ const struct drm_display_mode *mode)
+{
+ struct stf_inno_hdmi_controller *ctrl = dev_get_drvdata(dev);
+ unsigned long pixelclk = mode->clock * 1000;
+ long rounded;
+
+ /*
+ * The PHY can only generate the discrete set of pixel clocks described
+ * by its pre-PLL table, and clk_round_rate() fails for anything else.
+ * Reject those modes here: without this the modeset would appear to
+ * succeed while the PHY never produces a signal.
+ */
+ rounded = clk_round_rate(ctrl->clks[CLK_PCLK].clk, pixelclk);
+ if (rounded < 0 || rounded != pixelclk)
+ return MODE_NOCLOCK;
+
+ return MODE_OK;
+}
+
+static void inno_hdmi_starfive_enable(struct device *dev,
+ struct drm_display_mode *mode)
+{
+ struct stf_inno_hdmi_controller *ctrl = dev_get_drvdata(dev);
+ int ret;
+
+ /*
+ * 1. Set the pixel clock rate. This calls the PHY driver's .set_rate op.
+ */
+ ret = clk_set_rate(ctrl->clks[CLK_PCLK].clk, mode->clock * 1000);
+ if (ret) {
+ dev_err(dev, "Failed to set pclk rate %d: %d\n",
+ mode->clock * 1000, ret);
+ return;
+ }
+
+ /*
+ * 2. Enable the pixel clock. This calls the PHY driver's .prepare op.
+ */
+ ret = clk_prepare_enable(ctrl->clks[CLK_PCLK].clk);
+ if (ret) {
+ dev_err(dev, "Failed to enable pclk: %d\n", ret);
+ return;
+ }
+
+ /*
+ * 3. Power on the PHY. This calls the PHY driver's .power_on op,
+ * which configures the Post-PLL and analog blocks.
+ */
+ ret = phy_power_on(ctrl->phy);
+ if (ret) {
+ dev_err(dev, "Failed to power on PHY: %d\n", ret);
+ clk_disable_unprepare(ctrl->clks[CLK_PCLK].clk);
+ return;
+ }
+
+ ctrl->enabled = true;
+}
+
+static void inno_hdmi_starfive_disable(struct device *dev)
+{
+ struct stf_inno_hdmi_controller *ctrl = dev_get_drvdata(dev);
+
+ /*
+ * .enable bails out early if the pixel clock rate is unsupported or
+ * the PHY fails to power on, leaving pclk and the PHY untouched.
+ * Only tear down what was actually brought up, otherwise the clock
+ * refcount underflows.
+ */
+ if (!ctrl->enabled)
+ return;
+
+ phy_power_off(ctrl->phy);
+ clk_disable_unprepare(ctrl->clks[CLK_PCLK].clk);
+ ctrl->enabled = false;
+}
+
+static int starfive_inno_hdmi_controller_probe(struct platform_device *pdev)
+{
+ struct device *dev = &pdev->dev;
+ struct device *parent = dev->parent;
+ struct stf_inno_hdmi_controller *ctrl;
+ const struct inno_hdmi_plat_data *plat_data;
+ struct regmap *regmap;
+ struct inno_hdmi *inno;
+ int ret;
+
+ ctrl = devm_kzalloc(dev, sizeof(*ctrl), GFP_KERNEL);
+ if (!ctrl)
+ return -ENOMEM;
+
+ ctrl->dev = dev;
+ platform_set_drvdata(pdev, ctrl);
+
+ /* Get the shared regmap from the parent */
+ regmap = dev_get_regmap(parent, NULL);
+ if (!regmap) {
+ dev_err(dev, "Failed to get parent regmap\n");
+ return -ENODEV;
+ }
+
+ ctrl->phy = devm_phy_get(dev, "hdmi-phy");
+ if (IS_ERR(ctrl->phy))
+ return dev_err_probe(dev, PTR_ERR(ctrl->phy), "Failed to get PHY\n");
+
+ ctrl->tx_rst = devm_reset_control_get_exclusive(dev, "hdmi_tx");
+ if (IS_ERR(ctrl->tx_rst))
+ return dev_err_probe(dev, PTR_ERR(ctrl->tx_rst), "failed to get tx reset\n");
+
+ /* Populate the clock names this controller *consumes* */
+ ctrl->clks[CLK_SYS].id = "sys";
+ ctrl->clks[CLK_M].id = "mclk";
+ ctrl->clks[CLK_B].id = "bclk";
+ ctrl->clks[CLK_PCLK].id = "pclk"; /* Pixel clock *from* PHY */
+
+ ret = devm_clk_bulk_get(dev, CLK_CTRL_NUM, ctrl->clks);
+ if (ret)
+ return dev_err_probe(dev, ret, "Unable to get controller clocks\n");
+
+ /* pclk is enabled on demand during modeset */
+ ret = clk_bulk_prepare_enable(CLK_CTRL_NUM - 1, ctrl->clks);
+ if (ret)
+ return ret;
+
+ ret = reset_control_deassert(ctrl->tx_rst);
+ if (ret) {
+ clk_bulk_disable_unprepare(CLK_CTRL_NUM - 1, ctrl->clks);
+ return ret;
+ }
+
+ plat_data = of_device_get_match_data(dev);
+
+ /* Hand off to the generic library to create the bridge. */
+ inno = inno_hdmi_probe(pdev, plat_data);
+ if (IS_ERR(inno)) {
+ reset_control_assert(ctrl->tx_rst);
+ clk_bulk_disable_unprepare(CLK_CTRL_NUM - 1, ctrl->clks);
+ return PTR_ERR(inno);
+ }
+
+ return 0;
+}
+
+static void starfive_inno_hdmi_controller_remove(struct platform_device *pdev)
+{
+ struct stf_inno_hdmi_controller *ctrl = platform_get_drvdata(pdev);
+
+ reset_control_assert(ctrl->tx_rst);
+ clk_bulk_disable_unprepare(CLK_CTRL_NUM - 1, ctrl->clks);
+}
+
+/*
+ * This table is now only used for the generic .mode_valid check.
+ * The real validation happens in the PHY driver's .round_rate.
+ */
+static struct inno_hdmi_phy_config stf_hdmi_phy_configs[] = {
+ { 297000000, 0x00, 0x00 },
+ { ~0UL, 0x00, 0x00 }, /* Sentinel */
+};
+
+static const struct inno_hdmi_plat_ops stf_inno_hdmi_plat_ops = {
+ .enable = inno_hdmi_starfive_enable,
+ .disable = inno_hdmi_starfive_disable,
+ .mode_valid = inno_hdmi_starfive_mode_valid,
+};
+
+static const struct inno_hdmi_plat_data stf_inno_hdmi_plat_data = {
+ .ops = &stf_inno_hdmi_plat_ops,
+ .phy_configs = stf_hdmi_phy_configs,
+ .default_phy_config = &stf_hdmi_phy_configs[0],
+};
+
+static const struct of_device_id starfive_hdmi_controller_dt_ids[] = {
+ { .compatible = "starfive,jh7110-inno-hdmi-controller",
+ .data = &stf_inno_hdmi_plat_data },
+ {}
+};
+MODULE_DEVICE_TABLE(of, starfive_hdmi_controller_dt_ids);
+
+struct platform_driver starfive_inno_hdmi_controller_driver = {
+ .probe = starfive_inno_hdmi_controller_probe,
+ .remove = starfive_inno_hdmi_controller_remove,
+ .driver = {
+ .name = "starfive-inno-hdmi-controller",
+ .of_match_table = starfive_hdmi_controller_dt_ids,
+ },
+};
+module_platform_driver(starfive_inno_hdmi_controller_driver);
+
+MODULE_AUTHOR("Michal Wilczynski <m.wilczynski@samsung.com>");
+MODULE_DESCRIPTION("StarFive INNO HDMI Controller Driver");
+MODULE_LICENSE("GPL");
--
2.34.1
_______________________________________________
linux-riscv mailing list
linux-riscv@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-riscv
^ permalink raw reply related [flat|nested] 116+ messages in thread
* [PATCH v2 10/15] drm/bridge: starfive: Add JH7110 HDMI controller driver
@ 2026-08-28 13:47 ` Michal Wilczynski
0 siblings, 0 replies; 116+ messages in thread
From: Michal Wilczynski @ 2026-08-28 13:47 UTC (permalink / raw)
To: Vinod Koul, Neil Armstrong, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Andrzej Hajda, Robert Foss, Laurent Pinchart,
Jonas Karlman, Jernej Skrabec, Luca Ceresoli, David Airlie,
Simona Vetter, Maarten Lankhorst, Maxime Ripard,
Thomas Zimmermann, Lee Jones, Andy Yan, Philipp Zabel,
Emil Renner Berthing, Hal Feng, Michael Turquette, Stephen Boyd,
Brian Masney, Heiko Stuebner, Conor Dooley, Paul Walmsley,
Palmer Dabbelt, Albert Ou, Alexandre Ghiti, Dominique Belhachemi
Cc: linux-phy, devicetree, linux-kernel, dri-devel, mfd, linux-clk,
linux-arm-kernel, linux-rockchip, linux-riscv, Icenowy Zheng,
Andy Yan, Marek Szyprowski, Maud Spierings, Graham Markall,
Michal Wilczynski
Add the HDMI controller (bridge) driver for the StarFive JH7110.
This driver binds to the starfive,jh7110-inno-hdmi-controller node.
It gets its shared regmap from its parent and its clocks (sys, mclk,
bclk) from voutcrg. It consumes the pclk (pixel clock) and PHY from its
hdmi_phy sibling.
The driver calls the generic inno_hdmi_probe function and passes the
shared regmap to it, registering as a DRM bridge. The .enable hook is
responsible for setting the PHY's pixel clock rate via clk_set_rate()
and powering on the PHY via phy_power_on().
The PHY can only generate the discrete set of pixel clocks described by
its pre-PLL table, so .mode_valid rejects any mode clk_round_rate()
cannot satisfy. Without it such a mode would be advertised to userspace
and the modeset would appear to succeed while the display stayed blank.
.enable returns early when the rate is unsupported or the PHY fails to
power on, so track whether the pixel clock was actually enabled and let
.disable tear down only what was brought up, otherwise the clock
refcount underflows.
Signed-off-by: Michal Wilczynski <m.wilczynski@samsung.com>
---
drivers/gpu/drm/bridge/Kconfig | 11 ++
drivers/gpu/drm/bridge/Makefile | 1 +
drivers/gpu/drm/bridge/jh7110-inno-hdmi.c | 224 ++++++++++++++++++++++++++++++
3 files changed, 236 insertions(+)
diff --git a/drivers/gpu/drm/bridge/Kconfig b/drivers/gpu/drm/bridge/Kconfig
index 4a57d49b4c6d3ab4b965228835b372d191647197..75b1cf6727d5a32310dcf9fe5734d95e14eea8fe 100644
--- a/drivers/gpu/drm/bridge/Kconfig
+++ b/drivers/gpu/drm/bridge/Kconfig
@@ -359,6 +359,17 @@ config DRM_SOLOMON_SSD2825
Say M here if you want to support this hardware as a module.
The module will be named "ssd2825".
+config DRM_STARFIVE_JH7110_INNO_HDMI
+ tristate "Starfive JH7110 Innosilicon HDMI bridge"
+ depends on OF
+ depends on ARCH_STARFIVE || COMPILE_TEST
+ select DRM_INNO_HDMI
+ help
+ Enable support for the StarFive JH7110 specific implementation
+ of the Innosilicon HDMI controller.
+ This driver acts as a glue layer between the JH7110 HDMI subsystem
+ parent driver and the generic Innosilicon HDMI bridge driver.
+
config DRM_THINE_THC63LVD1024
tristate "Thine THC63LVD1024 LVDS decoder bridge"
depends on OF
diff --git a/drivers/gpu/drm/bridge/Makefile b/drivers/gpu/drm/bridge/Makefile
index 15cc821d85b7ea6f3cdc313f3e521b028de567d7..5d843f4ad7ed50b28cb75286c5e22789d91a0836 100644
--- a/drivers/gpu/drm/bridge/Makefile
+++ b/drivers/gpu/drm/bridge/Makefile
@@ -30,6 +30,7 @@ obj-$(CONFIG_DRM_SIL_SII8620) += sil-sii8620.o
obj-$(CONFIG_DRM_SII902X) += sii902x.o
obj-$(CONFIG_DRM_SII9234) += sii9234.o
obj-$(CONFIG_DRM_SIMPLE_BRIDGE) += simple-bridge.o
+obj-$(CONFIG_DRM_STARFIVE_JH7110_INNO_HDMI) += jh7110-inno-hdmi.o
obj-$(CONFIG_DRM_SOLOMON_SSD2825) += ssd2825.o
obj-$(CONFIG_DRM_THEAD_TH1520_DW_HDMI) += th1520-dw-hdmi.o
obj-$(CONFIG_DRM_THINE_THC63LVD1024) += thc63lvd1024.o
diff --git a/drivers/gpu/drm/bridge/jh7110-inno-hdmi.c b/drivers/gpu/drm/bridge/jh7110-inno-hdmi.c
new file mode 100644
index 0000000000000000000000000000000000000000..be865aa39e33f70614fa7cb58a683b9fcf051599
--- /dev/null
+++ b/drivers/gpu/drm/bridge/jh7110-inno-hdmi.c
@@ -0,0 +1,224 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) StarFive Technology Co., Ltd.
+ * Copyright (c) 2025 Samsung Electronics Co., Ltd.
+ * Author: Michal Wilczynski <m.wilczynski@samsung.com>
+ *
+ * HDMI controller (bridge) driver for the StarFive JH7110 HDMI subsystem.
+ */
+
+#include <linux/clk.h>
+#include <linux/mod_devicetable.h>
+#include <linux/module.h>
+#include <linux/of_device.h>
+#include <linux/platform_device.h>
+#include <linux/phy/phy.h>
+#include <linux/regmap.h>
+#include <linux/reset.h>
+
+#include <drm/bridge/inno_hdmi.h>
+#include <drm/drm_modes.h>
+
+enum stf_hdmi_ctrl_clocks { CLK_SYS = 0, CLK_M, CLK_B, CLK_PCLK, CLK_CTRL_NUM };
+
+struct stf_inno_hdmi_controller {
+ struct device *dev;
+ struct clk_bulk_data clks[CLK_CTRL_NUM];
+ struct reset_control *tx_rst;
+ struct phy *phy;
+ bool enabled;
+};
+
+static enum drm_mode_status
+inno_hdmi_starfive_mode_valid(struct device *dev,
+ const struct drm_display_mode *mode)
+{
+ struct stf_inno_hdmi_controller *ctrl = dev_get_drvdata(dev);
+ unsigned long pixelclk = mode->clock * 1000;
+ long rounded;
+
+ /*
+ * The PHY can only generate the discrete set of pixel clocks described
+ * by its pre-PLL table, and clk_round_rate() fails for anything else.
+ * Reject those modes here: without this the modeset would appear to
+ * succeed while the PHY never produces a signal.
+ */
+ rounded = clk_round_rate(ctrl->clks[CLK_PCLK].clk, pixelclk);
+ if (rounded < 0 || rounded != pixelclk)
+ return MODE_NOCLOCK;
+
+ return MODE_OK;
+}
+
+static void inno_hdmi_starfive_enable(struct device *dev,
+ struct drm_display_mode *mode)
+{
+ struct stf_inno_hdmi_controller *ctrl = dev_get_drvdata(dev);
+ int ret;
+
+ /*
+ * 1. Set the pixel clock rate. This calls the PHY driver's .set_rate op.
+ */
+ ret = clk_set_rate(ctrl->clks[CLK_PCLK].clk, mode->clock * 1000);
+ if (ret) {
+ dev_err(dev, "Failed to set pclk rate %d: %d\n",
+ mode->clock * 1000, ret);
+ return;
+ }
+
+ /*
+ * 2. Enable the pixel clock. This calls the PHY driver's .prepare op.
+ */
+ ret = clk_prepare_enable(ctrl->clks[CLK_PCLK].clk);
+ if (ret) {
+ dev_err(dev, "Failed to enable pclk: %d\n", ret);
+ return;
+ }
+
+ /*
+ * 3. Power on the PHY. This calls the PHY driver's .power_on op,
+ * which configures the Post-PLL and analog blocks.
+ */
+ ret = phy_power_on(ctrl->phy);
+ if (ret) {
+ dev_err(dev, "Failed to power on PHY: %d\n", ret);
+ clk_disable_unprepare(ctrl->clks[CLK_PCLK].clk);
+ return;
+ }
+
+ ctrl->enabled = true;
+}
+
+static void inno_hdmi_starfive_disable(struct device *dev)
+{
+ struct stf_inno_hdmi_controller *ctrl = dev_get_drvdata(dev);
+
+ /*
+ * .enable bails out early if the pixel clock rate is unsupported or
+ * the PHY fails to power on, leaving pclk and the PHY untouched.
+ * Only tear down what was actually brought up, otherwise the clock
+ * refcount underflows.
+ */
+ if (!ctrl->enabled)
+ return;
+
+ phy_power_off(ctrl->phy);
+ clk_disable_unprepare(ctrl->clks[CLK_PCLK].clk);
+ ctrl->enabled = false;
+}
+
+static int starfive_inno_hdmi_controller_probe(struct platform_device *pdev)
+{
+ struct device *dev = &pdev->dev;
+ struct device *parent = dev->parent;
+ struct stf_inno_hdmi_controller *ctrl;
+ const struct inno_hdmi_plat_data *plat_data;
+ struct regmap *regmap;
+ struct inno_hdmi *inno;
+ int ret;
+
+ ctrl = devm_kzalloc(dev, sizeof(*ctrl), GFP_KERNEL);
+ if (!ctrl)
+ return -ENOMEM;
+
+ ctrl->dev = dev;
+ platform_set_drvdata(pdev, ctrl);
+
+ /* Get the shared regmap from the parent */
+ regmap = dev_get_regmap(parent, NULL);
+ if (!regmap) {
+ dev_err(dev, "Failed to get parent regmap\n");
+ return -ENODEV;
+ }
+
+ ctrl->phy = devm_phy_get(dev, "hdmi-phy");
+ if (IS_ERR(ctrl->phy))
+ return dev_err_probe(dev, PTR_ERR(ctrl->phy), "Failed to get PHY\n");
+
+ ctrl->tx_rst = devm_reset_control_get_exclusive(dev, "hdmi_tx");
+ if (IS_ERR(ctrl->tx_rst))
+ return dev_err_probe(dev, PTR_ERR(ctrl->tx_rst), "failed to get tx reset\n");
+
+ /* Populate the clock names this controller *consumes* */
+ ctrl->clks[CLK_SYS].id = "sys";
+ ctrl->clks[CLK_M].id = "mclk";
+ ctrl->clks[CLK_B].id = "bclk";
+ ctrl->clks[CLK_PCLK].id = "pclk"; /* Pixel clock *from* PHY */
+
+ ret = devm_clk_bulk_get(dev, CLK_CTRL_NUM, ctrl->clks);
+ if (ret)
+ return dev_err_probe(dev, ret, "Unable to get controller clocks\n");
+
+ /* pclk is enabled on demand during modeset */
+ ret = clk_bulk_prepare_enable(CLK_CTRL_NUM - 1, ctrl->clks);
+ if (ret)
+ return ret;
+
+ ret = reset_control_deassert(ctrl->tx_rst);
+ if (ret) {
+ clk_bulk_disable_unprepare(CLK_CTRL_NUM - 1, ctrl->clks);
+ return ret;
+ }
+
+ plat_data = of_device_get_match_data(dev);
+
+ /* Hand off to the generic library to create the bridge. */
+ inno = inno_hdmi_probe(pdev, plat_data);
+ if (IS_ERR(inno)) {
+ reset_control_assert(ctrl->tx_rst);
+ clk_bulk_disable_unprepare(CLK_CTRL_NUM - 1, ctrl->clks);
+ return PTR_ERR(inno);
+ }
+
+ return 0;
+}
+
+static void starfive_inno_hdmi_controller_remove(struct platform_device *pdev)
+{
+ struct stf_inno_hdmi_controller *ctrl = platform_get_drvdata(pdev);
+
+ reset_control_assert(ctrl->tx_rst);
+ clk_bulk_disable_unprepare(CLK_CTRL_NUM - 1, ctrl->clks);
+}
+
+/*
+ * This table is now only used for the generic .mode_valid check.
+ * The real validation happens in the PHY driver's .round_rate.
+ */
+static struct inno_hdmi_phy_config stf_hdmi_phy_configs[] = {
+ { 297000000, 0x00, 0x00 },
+ { ~0UL, 0x00, 0x00 }, /* Sentinel */
+};
+
+static const struct inno_hdmi_plat_ops stf_inno_hdmi_plat_ops = {
+ .enable = inno_hdmi_starfive_enable,
+ .disable = inno_hdmi_starfive_disable,
+ .mode_valid = inno_hdmi_starfive_mode_valid,
+};
+
+static const struct inno_hdmi_plat_data stf_inno_hdmi_plat_data = {
+ .ops = &stf_inno_hdmi_plat_ops,
+ .phy_configs = stf_hdmi_phy_configs,
+ .default_phy_config = &stf_hdmi_phy_configs[0],
+};
+
+static const struct of_device_id starfive_hdmi_controller_dt_ids[] = {
+ { .compatible = "starfive,jh7110-inno-hdmi-controller",
+ .data = &stf_inno_hdmi_plat_data },
+ {}
+};
+MODULE_DEVICE_TABLE(of, starfive_hdmi_controller_dt_ids);
+
+struct platform_driver starfive_inno_hdmi_controller_driver = {
+ .probe = starfive_inno_hdmi_controller_probe,
+ .remove = starfive_inno_hdmi_controller_remove,
+ .driver = {
+ .name = "starfive-inno-hdmi-controller",
+ .of_match_table = starfive_hdmi_controller_dt_ids,
+ },
+};
+module_platform_driver(starfive_inno_hdmi_controller_driver);
+
+MODULE_AUTHOR("Michal Wilczynski <m.wilczynski@samsung.com>");
+MODULE_DESCRIPTION("StarFive INNO HDMI Controller Driver");
+MODULE_LICENSE("GPL");
--
2.34.1
_______________________________________________
Linux-rockchip mailing list
Linux-rockchip@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-rockchip
^ permalink raw reply related [flat|nested] 116+ messages in thread
* [PATCH v2 10/15] drm/bridge: starfive: Add JH7110 HDMI controller driver
@ 2026-08-28 13:47 ` Michal Wilczynski
0 siblings, 0 replies; 116+ messages in thread
From: Michal Wilczynski @ 2026-08-28 13:47 UTC (permalink / raw)
To: Vinod Koul, Neil Armstrong, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Andrzej Hajda, Robert Foss, Laurent Pinchart,
Jonas Karlman, Jernej Skrabec, Luca Ceresoli, David Airlie,
Simona Vetter, Maarten Lankhorst, Maxime Ripard,
Thomas Zimmermann, Lee Jones, Andy Yan, Philipp Zabel,
Emil Renner Berthing, Hal Feng, Michael Turquette, Stephen Boyd,
Brian Masney, Heiko Stuebner, Conor Dooley, Paul Walmsley,
Palmer Dabbelt, Albert Ou, Alexandre Ghiti, Dominique Belhachemi
Cc: linux-phy, devicetree, linux-kernel, dri-devel, mfd, linux-clk,
linux-arm-kernel, linux-rockchip, linux-riscv, Icenowy Zheng,
Andy Yan, Marek Szyprowski, Maud Spierings, Graham Markall,
Michal Wilczynski
Add the HDMI controller (bridge) driver for the StarFive JH7110.
This driver binds to the starfive,jh7110-inno-hdmi-controller node.
It gets its shared regmap from its parent and its clocks (sys, mclk,
bclk) from voutcrg. It consumes the pclk (pixel clock) and PHY from its
hdmi_phy sibling.
The driver calls the generic inno_hdmi_probe function and passes the
shared regmap to it, registering as a DRM bridge. The .enable hook is
responsible for setting the PHY's pixel clock rate via clk_set_rate()
and powering on the PHY via phy_power_on().
The PHY can only generate the discrete set of pixel clocks described by
its pre-PLL table, so .mode_valid rejects any mode clk_round_rate()
cannot satisfy. Without it such a mode would be advertised to userspace
and the modeset would appear to succeed while the display stayed blank.
.enable returns early when the rate is unsupported or the PHY fails to
power on, so track whether the pixel clock was actually enabled and let
.disable tear down only what was brought up, otherwise the clock
refcount underflows.
Signed-off-by: Michal Wilczynski <m.wilczynski@samsung.com>
---
drivers/gpu/drm/bridge/Kconfig | 11 ++
drivers/gpu/drm/bridge/Makefile | 1 +
drivers/gpu/drm/bridge/jh7110-inno-hdmi.c | 224 ++++++++++++++++++++++++++++++
3 files changed, 236 insertions(+)
diff --git a/drivers/gpu/drm/bridge/Kconfig b/drivers/gpu/drm/bridge/Kconfig
index 4a57d49b4c6d3ab4b965228835b372d191647197..75b1cf6727d5a32310dcf9fe5734d95e14eea8fe 100644
--- a/drivers/gpu/drm/bridge/Kconfig
+++ b/drivers/gpu/drm/bridge/Kconfig
@@ -359,6 +359,17 @@ config DRM_SOLOMON_SSD2825
Say M here if you want to support this hardware as a module.
The module will be named "ssd2825".
+config DRM_STARFIVE_JH7110_INNO_HDMI
+ tristate "Starfive JH7110 Innosilicon HDMI bridge"
+ depends on OF
+ depends on ARCH_STARFIVE || COMPILE_TEST
+ select DRM_INNO_HDMI
+ help
+ Enable support for the StarFive JH7110 specific implementation
+ of the Innosilicon HDMI controller.
+ This driver acts as a glue layer between the JH7110 HDMI subsystem
+ parent driver and the generic Innosilicon HDMI bridge driver.
+
config DRM_THINE_THC63LVD1024
tristate "Thine THC63LVD1024 LVDS decoder bridge"
depends on OF
diff --git a/drivers/gpu/drm/bridge/Makefile b/drivers/gpu/drm/bridge/Makefile
index 15cc821d85b7ea6f3cdc313f3e521b028de567d7..5d843f4ad7ed50b28cb75286c5e22789d91a0836 100644
--- a/drivers/gpu/drm/bridge/Makefile
+++ b/drivers/gpu/drm/bridge/Makefile
@@ -30,6 +30,7 @@ obj-$(CONFIG_DRM_SIL_SII8620) += sil-sii8620.o
obj-$(CONFIG_DRM_SII902X) += sii902x.o
obj-$(CONFIG_DRM_SII9234) += sii9234.o
obj-$(CONFIG_DRM_SIMPLE_BRIDGE) += simple-bridge.o
+obj-$(CONFIG_DRM_STARFIVE_JH7110_INNO_HDMI) += jh7110-inno-hdmi.o
obj-$(CONFIG_DRM_SOLOMON_SSD2825) += ssd2825.o
obj-$(CONFIG_DRM_THEAD_TH1520_DW_HDMI) += th1520-dw-hdmi.o
obj-$(CONFIG_DRM_THINE_THC63LVD1024) += thc63lvd1024.o
diff --git a/drivers/gpu/drm/bridge/jh7110-inno-hdmi.c b/drivers/gpu/drm/bridge/jh7110-inno-hdmi.c
new file mode 100644
index 0000000000000000000000000000000000000000..be865aa39e33f70614fa7cb58a683b9fcf051599
--- /dev/null
+++ b/drivers/gpu/drm/bridge/jh7110-inno-hdmi.c
@@ -0,0 +1,224 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) StarFive Technology Co., Ltd.
+ * Copyright (c) 2025 Samsung Electronics Co., Ltd.
+ * Author: Michal Wilczynski <m.wilczynski@samsung.com>
+ *
+ * HDMI controller (bridge) driver for the StarFive JH7110 HDMI subsystem.
+ */
+
+#include <linux/clk.h>
+#include <linux/mod_devicetable.h>
+#include <linux/module.h>
+#include <linux/of_device.h>
+#include <linux/platform_device.h>
+#include <linux/phy/phy.h>
+#include <linux/regmap.h>
+#include <linux/reset.h>
+
+#include <drm/bridge/inno_hdmi.h>
+#include <drm/drm_modes.h>
+
+enum stf_hdmi_ctrl_clocks { CLK_SYS = 0, CLK_M, CLK_B, CLK_PCLK, CLK_CTRL_NUM };
+
+struct stf_inno_hdmi_controller {
+ struct device *dev;
+ struct clk_bulk_data clks[CLK_CTRL_NUM];
+ struct reset_control *tx_rst;
+ struct phy *phy;
+ bool enabled;
+};
+
+static enum drm_mode_status
+inno_hdmi_starfive_mode_valid(struct device *dev,
+ const struct drm_display_mode *mode)
+{
+ struct stf_inno_hdmi_controller *ctrl = dev_get_drvdata(dev);
+ unsigned long pixelclk = mode->clock * 1000;
+ long rounded;
+
+ /*
+ * The PHY can only generate the discrete set of pixel clocks described
+ * by its pre-PLL table, and clk_round_rate() fails for anything else.
+ * Reject those modes here: without this the modeset would appear to
+ * succeed while the PHY never produces a signal.
+ */
+ rounded = clk_round_rate(ctrl->clks[CLK_PCLK].clk, pixelclk);
+ if (rounded < 0 || rounded != pixelclk)
+ return MODE_NOCLOCK;
+
+ return MODE_OK;
+}
+
+static void inno_hdmi_starfive_enable(struct device *dev,
+ struct drm_display_mode *mode)
+{
+ struct stf_inno_hdmi_controller *ctrl = dev_get_drvdata(dev);
+ int ret;
+
+ /*
+ * 1. Set the pixel clock rate. This calls the PHY driver's .set_rate op.
+ */
+ ret = clk_set_rate(ctrl->clks[CLK_PCLK].clk, mode->clock * 1000);
+ if (ret) {
+ dev_err(dev, "Failed to set pclk rate %d: %d\n",
+ mode->clock * 1000, ret);
+ return;
+ }
+
+ /*
+ * 2. Enable the pixel clock. This calls the PHY driver's .prepare op.
+ */
+ ret = clk_prepare_enable(ctrl->clks[CLK_PCLK].clk);
+ if (ret) {
+ dev_err(dev, "Failed to enable pclk: %d\n", ret);
+ return;
+ }
+
+ /*
+ * 3. Power on the PHY. This calls the PHY driver's .power_on op,
+ * which configures the Post-PLL and analog blocks.
+ */
+ ret = phy_power_on(ctrl->phy);
+ if (ret) {
+ dev_err(dev, "Failed to power on PHY: %d\n", ret);
+ clk_disable_unprepare(ctrl->clks[CLK_PCLK].clk);
+ return;
+ }
+
+ ctrl->enabled = true;
+}
+
+static void inno_hdmi_starfive_disable(struct device *dev)
+{
+ struct stf_inno_hdmi_controller *ctrl = dev_get_drvdata(dev);
+
+ /*
+ * .enable bails out early if the pixel clock rate is unsupported or
+ * the PHY fails to power on, leaving pclk and the PHY untouched.
+ * Only tear down what was actually brought up, otherwise the clock
+ * refcount underflows.
+ */
+ if (!ctrl->enabled)
+ return;
+
+ phy_power_off(ctrl->phy);
+ clk_disable_unprepare(ctrl->clks[CLK_PCLK].clk);
+ ctrl->enabled = false;
+}
+
+static int starfive_inno_hdmi_controller_probe(struct platform_device *pdev)
+{
+ struct device *dev = &pdev->dev;
+ struct device *parent = dev->parent;
+ struct stf_inno_hdmi_controller *ctrl;
+ const struct inno_hdmi_plat_data *plat_data;
+ struct regmap *regmap;
+ struct inno_hdmi *inno;
+ int ret;
+
+ ctrl = devm_kzalloc(dev, sizeof(*ctrl), GFP_KERNEL);
+ if (!ctrl)
+ return -ENOMEM;
+
+ ctrl->dev = dev;
+ platform_set_drvdata(pdev, ctrl);
+
+ /* Get the shared regmap from the parent */
+ regmap = dev_get_regmap(parent, NULL);
+ if (!regmap) {
+ dev_err(dev, "Failed to get parent regmap\n");
+ return -ENODEV;
+ }
+
+ ctrl->phy = devm_phy_get(dev, "hdmi-phy");
+ if (IS_ERR(ctrl->phy))
+ return dev_err_probe(dev, PTR_ERR(ctrl->phy), "Failed to get PHY\n");
+
+ ctrl->tx_rst = devm_reset_control_get_exclusive(dev, "hdmi_tx");
+ if (IS_ERR(ctrl->tx_rst))
+ return dev_err_probe(dev, PTR_ERR(ctrl->tx_rst), "failed to get tx reset\n");
+
+ /* Populate the clock names this controller *consumes* */
+ ctrl->clks[CLK_SYS].id = "sys";
+ ctrl->clks[CLK_M].id = "mclk";
+ ctrl->clks[CLK_B].id = "bclk";
+ ctrl->clks[CLK_PCLK].id = "pclk"; /* Pixel clock *from* PHY */
+
+ ret = devm_clk_bulk_get(dev, CLK_CTRL_NUM, ctrl->clks);
+ if (ret)
+ return dev_err_probe(dev, ret, "Unable to get controller clocks\n");
+
+ /* pclk is enabled on demand during modeset */
+ ret = clk_bulk_prepare_enable(CLK_CTRL_NUM - 1, ctrl->clks);
+ if (ret)
+ return ret;
+
+ ret = reset_control_deassert(ctrl->tx_rst);
+ if (ret) {
+ clk_bulk_disable_unprepare(CLK_CTRL_NUM - 1, ctrl->clks);
+ return ret;
+ }
+
+ plat_data = of_device_get_match_data(dev);
+
+ /* Hand off to the generic library to create the bridge. */
+ inno = inno_hdmi_probe(pdev, plat_data);
+ if (IS_ERR(inno)) {
+ reset_control_assert(ctrl->tx_rst);
+ clk_bulk_disable_unprepare(CLK_CTRL_NUM - 1, ctrl->clks);
+ return PTR_ERR(inno);
+ }
+
+ return 0;
+}
+
+static void starfive_inno_hdmi_controller_remove(struct platform_device *pdev)
+{
+ struct stf_inno_hdmi_controller *ctrl = platform_get_drvdata(pdev);
+
+ reset_control_assert(ctrl->tx_rst);
+ clk_bulk_disable_unprepare(CLK_CTRL_NUM - 1, ctrl->clks);
+}
+
+/*
+ * This table is now only used for the generic .mode_valid check.
+ * The real validation happens in the PHY driver's .round_rate.
+ */
+static struct inno_hdmi_phy_config stf_hdmi_phy_configs[] = {
+ { 297000000, 0x00, 0x00 },
+ { ~0UL, 0x00, 0x00 }, /* Sentinel */
+};
+
+static const struct inno_hdmi_plat_ops stf_inno_hdmi_plat_ops = {
+ .enable = inno_hdmi_starfive_enable,
+ .disable = inno_hdmi_starfive_disable,
+ .mode_valid = inno_hdmi_starfive_mode_valid,
+};
+
+static const struct inno_hdmi_plat_data stf_inno_hdmi_plat_data = {
+ .ops = &stf_inno_hdmi_plat_ops,
+ .phy_configs = stf_hdmi_phy_configs,
+ .default_phy_config = &stf_hdmi_phy_configs[0],
+};
+
+static const struct of_device_id starfive_hdmi_controller_dt_ids[] = {
+ { .compatible = "starfive,jh7110-inno-hdmi-controller",
+ .data = &stf_inno_hdmi_plat_data },
+ {}
+};
+MODULE_DEVICE_TABLE(of, starfive_hdmi_controller_dt_ids);
+
+struct platform_driver starfive_inno_hdmi_controller_driver = {
+ .probe = starfive_inno_hdmi_controller_probe,
+ .remove = starfive_inno_hdmi_controller_remove,
+ .driver = {
+ .name = "starfive-inno-hdmi-controller",
+ .of_match_table = starfive_hdmi_controller_dt_ids,
+ },
+};
+module_platform_driver(starfive_inno_hdmi_controller_driver);
+
+MODULE_AUTHOR("Michal Wilczynski <m.wilczynski@samsung.com>");
+MODULE_DESCRIPTION("StarFive INNO HDMI Controller Driver");
+MODULE_LICENSE("GPL");
--
2.34.1
--
linux-phy mailing list
linux-phy@lists.infradead.org
https://lists.infradead.org/mailman/listinfo/linux-phy
^ permalink raw reply related [flat|nested] 116+ messages in thread
* [PATCH v2 11/15] phy: Add common Innosilicon HDMI PHY helpers
2026-08-28 13:47 ` Michal Wilczynski
(?)
(?)
@ 2026-08-28 13:47 ` Michal Wilczynski
-1 siblings, 0 replies; 116+ messages in thread
From: Michal Wilczynski @ 2026-08-28 13:47 UTC (permalink / raw)
To: Vinod Koul, Neil Armstrong, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Andrzej Hajda, Robert Foss, Laurent Pinchart,
Jonas Karlman, Jernej Skrabec, Luca Ceresoli, David Airlie,
Simona Vetter, Maarten Lankhorst, Maxime Ripard,
Thomas Zimmermann, Lee Jones, Andy Yan, Philipp Zabel,
Emil Renner Berthing, Hal Feng, Michael Turquette, Stephen Boyd,
Brian Masney, Heiko Stuebner, Conor Dooley, Paul Walmsley,
Palmer Dabbelt, Albert Ou, Alexandre Ghiti, Dominique Belhachemi
Cc: linux-phy, devicetree, linux-kernel, dri-devel, mfd, linux-clk,
linux-arm-kernel, linux-rockchip, linux-riscv, Icenowy Zheng,
Andy Yan, Marek Szyprowski, Maud Spierings, Graham Markall,
Michal Wilczynski
The Innosilicon HDMI PHY IP is used by several SoCs. They differ in
where the PHY register block sits in the register space and in which
pixel clocks they support, but the pre-PLL programming sequence and the
layout of its registers are the same.
Add a small library holding that shared part: the pre-PLL configuration
table format, a lookup, clk_ops determine_rate and recalc_rate helpers,
and the pre-PLL register programming. Callers pass a regmap, a register
offset for the PHY block, and their own pixel clock table.
No driver uses it yet; the users are converted separately.
Signed-off-by: Michal Wilczynski <m.wilczynski@samsung.com>
---
drivers/phy/Kconfig | 8 +
drivers/phy/Makefile | 1 +
drivers/phy/phy-inno-hdmi.c | 297 ++++++++++++++++++++++++++++++++++++++
include/linux/phy/inno-hdmi-phy.h | 85 +++++++++++
4 files changed, 391 insertions(+)
diff --git a/drivers/phy/Kconfig b/drivers/phy/Kconfig
index 19f3b7d12b7d492d16000fa52483dc5002590d7a..0e973b3b02a30704d339db9f15d4695bcbec1c75 100644
--- a/drivers/phy/Kconfig
+++ b/drivers/phy/Kconfig
@@ -168,6 +168,14 @@ config PHY_XGENE
help
This option enables support for APM X-Gene SoC multi-purpose PHY.
+config PHY_INNO_HDMI
+ tristate
+ depends on GENERIC_PHY
+ select REGMAP
+ help
+ Common helpers for the Innosilicon HDMI PHY, shared by the SoC
+ drivers that instantiate it. Selected by those drivers.
+
source "drivers/phy/allwinner/Kconfig"
source "drivers/phy/amlogic/Kconfig"
source "drivers/phy/apple/Kconfig"
diff --git a/drivers/phy/Makefile b/drivers/phy/Makefile
index d7aa516bcc49e7662c9c9db421833fe591dfbc05..e93c473dfc6d837ed6ba540f0b0204a0d68d25bf 100644
--- a/drivers/phy/Makefile
+++ b/drivers/phy/Makefile
@@ -7,6 +7,7 @@ obj-$(CONFIG_PHY_COMMON_PROPS) += phy-common-props.o
obj-$(CONFIG_PHY_COMMON_PROPS_TEST) += phy-common-props-test.o
obj-$(CONFIG_GENERIC_PHY) += phy-core.o
obj-$(CONFIG_GENERIC_PHY_MIPI_DPHY) += phy-core-mipi-dphy.o
+obj-$(CONFIG_PHY_INNO_HDMI) += phy-inno-hdmi.o
obj-$(CONFIG_PHY_AIROHA_PCIE) += phy-airoha-pcie.o
obj-$(CONFIG_PHY_CAN_TRANSCEIVER) += phy-can-transceiver.o
obj-$(CONFIG_PHY_ECONET_PCIE) += phy-econet-pcie.o
diff --git a/drivers/phy/phy-inno-hdmi.c b/drivers/phy/phy-inno-hdmi.c
new file mode 100644
index 0000000000000000000000000000000000000000..deb2b73a86f5d6be96dedc818c39777904eb37ee
--- /dev/null
+++ b/drivers/phy/phy-inno-hdmi.c
@@ -0,0 +1,297 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Common helpers for the Innosilicon HDMI PHY.
+ *
+ * Copyright (c) 2017 Rockchip Electronics Co. Ltd.
+ * Copyright (c) 2025 Samsung Electronics Co., Ltd.
+ *
+ * Author: Zheng Yang <zhengyang@rock-chips.com>
+ * Author: Michal Wilczynski <m.wilczynski@samsung.com>
+ *
+ * Derived from drivers/phy/rockchip/phy-rockchip-inno-hdmi.c.
+ *
+ * The same PHY IP is used by several SoCs, which differ in where the PHY
+ * register block sits and in the pixel clock table they support, but share
+ * the pre-PLL programming sequence.
+ */
+
+#include <linux/bitfield.h>
+#include <linux/bits.h>
+#include <linux/clk-provider.h>
+#include <linux/errno.h>
+#include <linux/export.h>
+#include <linux/iopoll.h>
+#include <linux/math64.h>
+#include <linux/module.h>
+#include <linux/regmap.h>
+
+#include <linux/phy/inno-hdmi-phy.h>
+
+#define INNO_PRE_PLL_CONTROL 0xa0
+#define INNO_PRE_PLL_POWER_DOWN BIT(0)
+#define INNO_PCLK_VCO_DIV_5_MASK BIT(1)
+#define INNO_PCLK_VCO_DIV_5(x) FIELD_PREP(BIT(1), x)
+
+#define INNO_PRE_PLL_DIV_1 0xa1
+#define INNO_PRE_PLL_PRE_DIV_MASK GENMASK(5, 0)
+#define INNO_PRE_PLL_PRE_DIV(x) FIELD_PREP(GENMASK(5, 0), x)
+
+#define INNO_PRE_PLL_DIV_2 0xa2
+#define INNO_SPREAD_SPECTRUM_MOD_DISABLE BIT(6)
+#define INNO_PRE_PLL_FRAC_DIV_DISABLE FIELD_PREP(GENMASK(5, 4), 3)
+#define INNO_PRE_PLL_FB_DIV_11_8_MASK GENMASK(3, 0)
+#define INNO_PRE_PLL_FB_DIV_11_8(x) FIELD_PREP(GENMASK(3, 0), (x) >> 8)
+
+#define INNO_PRE_PLL_DIV_3 0xa3
+#define INNO_PRE_PLL_FB_DIV_7_0(x) FIELD_PREP(GENMASK(7, 0), x)
+
+#define INNO_PRE_PLL_TMDSCLK_DIV 0xa4
+#define INNO_PRE_PLL_TMDSCLK_DIV_C(x) FIELD_PREP(GENMASK(1, 0), x)
+#define INNO_PRE_PLL_TMDSCLK_DIV_B(x) FIELD_PREP(GENMASK(3, 2), x)
+#define INNO_PRE_PLL_TMDSCLK_DIV_A(x) FIELD_PREP(GENMASK(5, 4), x)
+
+#define INNO_PCLK_DIV_AB 0xa5
+#define INNO_PCLK_DIV_B_MASK GENMASK(6, 5)
+#define INNO_PCLK_DIV_B(x) FIELD_PREP(GENMASK(6, 5), x)
+#define INNO_PCLK_DIV_A_MASK GENMASK(4, 0)
+#define INNO_PCLK_DIV_A(x) FIELD_PREP(GENMASK(4, 0), x)
+
+#define INNO_PCLK_DIV_CD 0xa6
+#define INNO_PCLK_DIV_C(x) FIELD_PREP(GENMASK(6, 5), x)
+#define INNO_PCLK_DIV_D_MASK GENMASK(4, 0)
+#define INNO_PCLK_DIV_D(x) FIELD_PREP(GENMASK(4, 0), x)
+
+#define INNO_PRE_PLL_LOCK_STATUS 0xa9
+#define INNO_PRE_PLL_LOCK BIT(0)
+
+#define INNO_PRE_PLL_FRAC_DIV_23_16 0xd1
+#define INNO_PRE_PLL_FRAC_DIV_15_8 0xd2
+#define INNO_PRE_PLL_FRAC_DIV_7_0 0xd3
+#define INNO_PRE_PLL_FRAC_DIV(x) FIELD_PREP(GENMASK(7, 0), x)
+
+#define INNO_FRAC_DIV_WIDTH 24
+
+static unsigned int inno_reg(const struct inno_hdmi_phy_pre_pll *pll,
+ unsigned int reg)
+{
+ return (pll->offset + reg) * 4;
+}
+
+static void inno_write(const struct inno_hdmi_phy_pre_pll *pll,
+ unsigned int reg, u8 val)
+{
+ regmap_write(pll->regmap, inno_reg(pll, reg), val);
+}
+
+static u8 inno_read(const struct inno_hdmi_phy_pre_pll *pll, unsigned int reg)
+{
+ unsigned int val;
+
+ regmap_read(pll->regmap, inno_reg(pll, reg), &val);
+
+ return val;
+}
+
+static void inno_update_bits(const struct inno_hdmi_phy_pre_pll *pll,
+ unsigned int reg, u8 mask, u8 val)
+{
+ regmap_update_bits(pll->regmap, inno_reg(pll, reg), mask, val);
+}
+
+/**
+ * inno_hdmi_phy_pre_pll_lookup - find the settings for a pixel clock
+ * @pll: pre-PLL instance
+ * @pixclock: requested pixel clock, in Hz
+ * @tmdsclock: requested TMDS clock, in Hz
+ *
+ * Return: the matching table entry, or an ERR_PTR if the PHY cannot generate
+ * the requested combination.
+ */
+const struct inno_hdmi_phy_pre_pll_config *
+inno_hdmi_phy_pre_pll_lookup(const struct inno_hdmi_phy_pre_pll *pll,
+ unsigned long pixclock, unsigned long tmdsclock)
+{
+ const struct inno_hdmi_phy_pre_pll_config *cfg;
+
+ for (cfg = pll->table; cfg->pixclock != 0; cfg++)
+ if (cfg->pixclock == pixclock && cfg->tmdsclock == tmdsclock)
+ return cfg;
+
+ return ERR_PTR(-EINVAL);
+}
+EXPORT_SYMBOL_GPL(inno_hdmi_phy_pre_pll_lookup);
+
+/**
+ * inno_hdmi_phy_pre_pll_determine_rate - clk_ops.determine_rate helper
+ * @pll: pre-PLL instance
+ * @req: rate request, updated with the rate the PHY would produce
+ *
+ * The PHY can only generate the pixel clocks described by its table, so a
+ * request that does not appear there is rejected rather than rounded.
+ *
+ * Return: 0 on success, -EINVAL if the rate is not supported.
+ */
+int inno_hdmi_phy_pre_pll_determine_rate(const struct inno_hdmi_phy_pre_pll *pll,
+ struct clk_rate_request *req)
+{
+ const struct inno_hdmi_phy_pre_pll_config *cfg;
+ unsigned long rate = rounddown(req->rate, 1000);
+
+ for (cfg = pll->table; cfg->pixclock != 0; cfg++) {
+ if (cfg->pixclock == rate) {
+ req->rate = cfg->pixclock;
+ return 0;
+ }
+ }
+
+ return -EINVAL;
+}
+EXPORT_SYMBOL_GPL(inno_hdmi_phy_pre_pll_determine_rate);
+
+/**
+ * inno_hdmi_phy_pre_pll_recalc_rate - clk_ops.recalc_rate helper
+ * @pll: pre-PLL instance
+ * @parent_rate: rate of the reference clock, in Hz
+ *
+ * Return: the pixel clock the pre-PLL is currently programmed for, in Hz.
+ */
+unsigned long
+inno_hdmi_phy_pre_pll_recalc_rate(const struct inno_hdmi_phy_pre_pll *pll,
+ unsigned long parent_rate)
+{
+ u8 nd, no_a, no_b, no_d;
+ unsigned long frac;
+ u64 vco;
+ u16 nf;
+
+ nd = inno_read(pll, INNO_PRE_PLL_DIV_1) & INNO_PRE_PLL_PRE_DIV_MASK;
+ nf = (inno_read(pll, INNO_PRE_PLL_DIV_2) &
+ INNO_PRE_PLL_FB_DIV_11_8_MASK) << 8;
+ nf |= inno_read(pll, INNO_PRE_PLL_DIV_3);
+ vco = parent_rate * nf;
+
+ if (!(inno_read(pll, INNO_PRE_PLL_DIV_2) &
+ INNO_PRE_PLL_FRAC_DIV_DISABLE)) {
+ frac = inno_read(pll, INNO_PRE_PLL_FRAC_DIV_7_0) |
+ (inno_read(pll, INNO_PRE_PLL_FRAC_DIV_15_8) << 8) |
+ (inno_read(pll, INNO_PRE_PLL_FRAC_DIV_23_16) << 16);
+ vco += DIV_ROUND_CLOSEST(parent_rate * frac,
+ BIT(INNO_FRAC_DIV_WIDTH));
+ }
+
+ if (inno_read(pll, INNO_PRE_PLL_CONTROL) & INNO_PCLK_VCO_DIV_5_MASK) {
+ do_div(vco, nd * 5);
+ } else {
+ no_a = inno_read(pll, INNO_PCLK_DIV_AB) & INNO_PCLK_DIV_A_MASK;
+ no_b = FIELD_GET(INNO_PCLK_DIV_B_MASK,
+ inno_read(pll, INNO_PCLK_DIV_AB)) + 2;
+ no_d = inno_read(pll, INNO_PCLK_DIV_CD) & INNO_PCLK_DIV_D_MASK;
+
+ do_div(vco, nd * (no_a == 1 ? no_b : no_a) * no_d * 2);
+ }
+
+ return DIV_ROUND_CLOSEST((unsigned long)vco, 1000) * 1000;
+}
+EXPORT_SYMBOL_GPL(inno_hdmi_phy_pre_pll_recalc_rate);
+
+/**
+ * inno_hdmi_phy_pre_pll_configure - program the pre-PLL dividers
+ * @pll: pre-PLL instance
+ * @cfg: settings to program
+ *
+ * The caller is responsible for powering the pre-PLL down beforehand and back
+ * up afterwards, and for waiting for it to lock.
+ */
+void inno_hdmi_phy_pre_pll_configure(const struct inno_hdmi_phy_pre_pll *pll,
+ const struct inno_hdmi_phy_pre_pll_config *cfg)
+{
+ u8 val;
+
+ inno_update_bits(pll, INNO_PRE_PLL_CONTROL, INNO_PCLK_VCO_DIV_5_MASK,
+ INNO_PCLK_VCO_DIV_5(cfg->vco_div_5_en));
+ inno_write(pll, INNO_PRE_PLL_DIV_1, INNO_PRE_PLL_PRE_DIV(cfg->prediv));
+
+ val = INNO_SPREAD_SPECTRUM_MOD_DISABLE;
+ if (!cfg->fracdiv)
+ val |= INNO_PRE_PLL_FRAC_DIV_DISABLE;
+
+ inno_write(pll, INNO_PRE_PLL_DIV_2,
+ INNO_PRE_PLL_FB_DIV_11_8(cfg->fbdiv) | val);
+ inno_write(pll, INNO_PRE_PLL_DIV_3,
+ INNO_PRE_PLL_FB_DIV_7_0(cfg->fbdiv));
+
+ inno_write(pll, INNO_PCLK_DIV_AB,
+ INNO_PCLK_DIV_A(cfg->pclk_div_a) |
+ INNO_PCLK_DIV_B(cfg->pclk_div_b));
+ inno_write(pll, INNO_PCLK_DIV_CD,
+ INNO_PCLK_DIV_C(cfg->pclk_div_c) |
+ INNO_PCLK_DIV_D(cfg->pclk_div_d));
+
+ inno_write(pll, INNO_PRE_PLL_TMDSCLK_DIV,
+ INNO_PRE_PLL_TMDSCLK_DIV_A(cfg->tmds_div_a) |
+ INNO_PRE_PLL_TMDSCLK_DIV_B(cfg->tmds_div_b) |
+ INNO_PRE_PLL_TMDSCLK_DIV_C(cfg->tmds_div_c));
+
+ inno_write(pll, INNO_PRE_PLL_FRAC_DIV_7_0,
+ INNO_PRE_PLL_FRAC_DIV(cfg->fracdiv));
+ inno_write(pll, INNO_PRE_PLL_FRAC_DIV_15_8,
+ INNO_PRE_PLL_FRAC_DIV(cfg->fracdiv >> 8));
+ inno_write(pll, INNO_PRE_PLL_FRAC_DIV_23_16,
+ INNO_PRE_PLL_FRAC_DIV(cfg->fracdiv >> 16));
+}
+EXPORT_SYMBOL_GPL(inno_hdmi_phy_pre_pll_configure);
+
+/**
+ * inno_hdmi_phy_pre_pll_power_down - power the pre-PLL down or up
+ * @pll: pre-PLL instance
+ * @power_down: true to power down, false to power up
+ */
+void inno_hdmi_phy_pre_pll_power_down(const struct inno_hdmi_phy_pre_pll *pll,
+ bool power_down)
+{
+ inno_update_bits(pll, INNO_PRE_PLL_CONTROL, INNO_PRE_PLL_POWER_DOWN,
+ power_down ? INNO_PRE_PLL_POWER_DOWN : 0);
+}
+EXPORT_SYMBOL_GPL(inno_hdmi_phy_pre_pll_power_down);
+
+/**
+ * inno_hdmi_phy_pre_pll_is_powered - report whether the pre-PLL is powered up
+ * @pll: pre-PLL instance
+ */
+bool inno_hdmi_phy_pre_pll_is_powered(const struct inno_hdmi_phy_pre_pll *pll)
+{
+ return !(inno_read(pll, INNO_PRE_PLL_CONTROL) & INNO_PRE_PLL_POWER_DOWN);
+}
+EXPORT_SYMBOL_GPL(inno_hdmi_phy_pre_pll_is_powered);
+
+/**
+ * inno_hdmi_phy_pre_pll_is_locked - report whether the pre-PLL has locked
+ * @pll: pre-PLL instance
+ */
+bool inno_hdmi_phy_pre_pll_is_locked(const struct inno_hdmi_phy_pre_pll *pll)
+{
+ return inno_read(pll, INNO_PRE_PLL_LOCK_STATUS) & INNO_PRE_PLL_LOCK;
+}
+EXPORT_SYMBOL_GPL(inno_hdmi_phy_pre_pll_is_locked);
+
+/**
+ * inno_hdmi_phy_pre_pll_wait_locked - wait for the pre-PLL to lock
+ * @pll: pre-PLL instance
+ * @timeout_us: how long to wait, in microseconds
+ *
+ * Return: 0 once locked, -ETIMEDOUT otherwise.
+ */
+int inno_hdmi_phy_pre_pll_wait_locked(const struct inno_hdmi_phy_pre_pll *pll,
+ unsigned int timeout_us)
+{
+ unsigned int val;
+
+ return regmap_read_poll_timeout(pll->regmap,
+ inno_reg(pll, INNO_PRE_PLL_LOCK_STATUS),
+ val, val & INNO_PRE_PLL_LOCK,
+ 1000, timeout_us);
+}
+EXPORT_SYMBOL_GPL(inno_hdmi_phy_pre_pll_wait_locked);
+
+MODULE_DESCRIPTION("Innosilicon HDMI PHY common helpers");
+MODULE_LICENSE("GPL");
diff --git a/include/linux/phy/inno-hdmi-phy.h b/include/linux/phy/inno-hdmi-phy.h
new file mode 100644
index 0000000000000000000000000000000000000000..e13911e1a18437cf9cefa43dac494caeb2935782
--- /dev/null
+++ b/include/linux/phy/inno-hdmi-phy.h
@@ -0,0 +1,85 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+/*
+ * Common helpers for the Innosilicon HDMI PHY.
+ *
+ * Copyright (c) 2017 Rockchip Electronics Co. Ltd.
+ * Copyright (c) 2025 Samsung Electronics Co., Ltd.
+ *
+ * Author: Zheng Yang <zhengyang@rock-chips.com>
+ * Author: Michal Wilczynski <m.wilczynski@samsung.com>
+ *
+ * Derived from drivers/phy/rockchip/phy-rockchip-inno-hdmi.c.
+ */
+
+#ifndef __PHY_INNO_HDMI_H__
+#define __PHY_INNO_HDMI_H__
+
+#include <linux/types.h>
+
+struct clk_rate_request;
+struct regmap;
+
+/**
+ * struct inno_hdmi_phy_pre_pll_config - pre-PLL settings for one pixel clock
+ * @pixclock: pixel clock this entry describes, in Hz
+ * @tmdsclock: TMDS clock this entry describes, in Hz
+ * @prediv: pre-PLL reference divider
+ * @fbdiv: pre-PLL feedback divider
+ * @tmds_div_a: TMDS clock divider A
+ * @tmds_div_b: TMDS clock divider B
+ * @tmds_div_c: TMDS clock divider C
+ * @pclk_div_a: pixel clock divider A
+ * @pclk_div_b: pixel clock divider B
+ * @pclk_div_c: pixel clock divider C
+ * @pclk_div_d: pixel clock divider D
+ * @vco_div_5_en: divide the VCO output by five
+ * @fracdiv: pre-PLL fractional divider, zero to use integer mode
+ */
+struct inno_hdmi_phy_pre_pll_config {
+ unsigned long pixclock;
+ unsigned long tmdsclock;
+ u8 prediv;
+ u16 fbdiv;
+ u8 tmds_div_a;
+ u8 tmds_div_b;
+ u8 tmds_div_c;
+ u8 pclk_div_a;
+ u8 pclk_div_b;
+ u8 pclk_div_c;
+ u8 pclk_div_d;
+ u8 vco_div_5_en;
+ u32 fracdiv;
+};
+
+/**
+ * struct inno_hdmi_phy_pre_pll - a pre-PLL instance
+ * @regmap: register map covering the PHY registers
+ * @offset: offset of the PHY register block, in units of the register index.
+ * Zero where the PHY block starts the register space, 0x100 on the
+ * StarFive JH7110 where it is preceded by the HDMI controller.
+ * @table: pixel clock table, terminated by an entry with a zero pixclock
+ */
+struct inno_hdmi_phy_pre_pll {
+ struct regmap *regmap;
+ unsigned int offset;
+ const struct inno_hdmi_phy_pre_pll_config *table;
+};
+
+const struct inno_hdmi_phy_pre_pll_config *
+inno_hdmi_phy_pre_pll_lookup(const struct inno_hdmi_phy_pre_pll *pll,
+ unsigned long pixclock, unsigned long tmdsclock);
+int inno_hdmi_phy_pre_pll_determine_rate(const struct inno_hdmi_phy_pre_pll *pll,
+ struct clk_rate_request *req);
+unsigned long
+inno_hdmi_phy_pre_pll_recalc_rate(const struct inno_hdmi_phy_pre_pll *pll,
+ unsigned long parent_rate);
+void inno_hdmi_phy_pre_pll_configure(const struct inno_hdmi_phy_pre_pll *pll,
+ const struct inno_hdmi_phy_pre_pll_config *cfg);
+void inno_hdmi_phy_pre_pll_power_down(const struct inno_hdmi_phy_pre_pll *pll,
+ bool power_down);
+bool inno_hdmi_phy_pre_pll_is_powered(const struct inno_hdmi_phy_pre_pll *pll);
+bool inno_hdmi_phy_pre_pll_is_locked(const struct inno_hdmi_phy_pre_pll *pll);
+int inno_hdmi_phy_pre_pll_wait_locked(const struct inno_hdmi_phy_pre_pll *pll,
+ unsigned int timeout_us);
+
+#endif /* __PHY_INNO_HDMI_H__ */
--
2.34.1
^ permalink raw reply related [flat|nested] 116+ messages in thread
* [PATCH v2 11/15] phy: Add common Innosilicon HDMI PHY helpers
@ 2026-08-28 13:47 ` Michal Wilczynski
0 siblings, 0 replies; 116+ messages in thread
From: Michal Wilczynski @ 2026-08-28 13:47 UTC (permalink / raw)
To: Vinod Koul, Neil Armstrong, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Andrzej Hajda, Robert Foss, Laurent Pinchart,
Jonas Karlman, Jernej Skrabec, Luca Ceresoli, David Airlie,
Simona Vetter, Maarten Lankhorst, Maxime Ripard,
Thomas Zimmermann, Lee Jones, Andy Yan, Philipp Zabel,
Emil Renner Berthing, Hal Feng, Michael Turquette, Stephen Boyd,
Brian Masney, Heiko Stuebner, Conor Dooley, Paul Walmsley,
Palmer Dabbelt, Albert Ou, Alexandre Ghiti, Dominique Belhachemi
Cc: linux-phy, devicetree, linux-kernel, dri-devel, mfd, linux-clk,
linux-arm-kernel, linux-rockchip, linux-riscv, Icenowy Zheng,
Andy Yan, Marek Szyprowski, Maud Spierings, Graham Markall,
Michal Wilczynski
The Innosilicon HDMI PHY IP is used by several SoCs. They differ in
where the PHY register block sits in the register space and in which
pixel clocks they support, but the pre-PLL programming sequence and the
layout of its registers are the same.
Add a small library holding that shared part: the pre-PLL configuration
table format, a lookup, clk_ops determine_rate and recalc_rate helpers,
and the pre-PLL register programming. Callers pass a regmap, a register
offset for the PHY block, and their own pixel clock table.
No driver uses it yet; the users are converted separately.
Signed-off-by: Michal Wilczynski <m.wilczynski@samsung.com>
---
drivers/phy/Kconfig | 8 +
drivers/phy/Makefile | 1 +
drivers/phy/phy-inno-hdmi.c | 297 ++++++++++++++++++++++++++++++++++++++
include/linux/phy/inno-hdmi-phy.h | 85 +++++++++++
4 files changed, 391 insertions(+)
diff --git a/drivers/phy/Kconfig b/drivers/phy/Kconfig
index 19f3b7d12b7d492d16000fa52483dc5002590d7a..0e973b3b02a30704d339db9f15d4695bcbec1c75 100644
--- a/drivers/phy/Kconfig
+++ b/drivers/phy/Kconfig
@@ -168,6 +168,14 @@ config PHY_XGENE
help
This option enables support for APM X-Gene SoC multi-purpose PHY.
+config PHY_INNO_HDMI
+ tristate
+ depends on GENERIC_PHY
+ select REGMAP
+ help
+ Common helpers for the Innosilicon HDMI PHY, shared by the SoC
+ drivers that instantiate it. Selected by those drivers.
+
source "drivers/phy/allwinner/Kconfig"
source "drivers/phy/amlogic/Kconfig"
source "drivers/phy/apple/Kconfig"
diff --git a/drivers/phy/Makefile b/drivers/phy/Makefile
index d7aa516bcc49e7662c9c9db421833fe591dfbc05..e93c473dfc6d837ed6ba540f0b0204a0d68d25bf 100644
--- a/drivers/phy/Makefile
+++ b/drivers/phy/Makefile
@@ -7,6 +7,7 @@ obj-$(CONFIG_PHY_COMMON_PROPS) += phy-common-props.o
obj-$(CONFIG_PHY_COMMON_PROPS_TEST) += phy-common-props-test.o
obj-$(CONFIG_GENERIC_PHY) += phy-core.o
obj-$(CONFIG_GENERIC_PHY_MIPI_DPHY) += phy-core-mipi-dphy.o
+obj-$(CONFIG_PHY_INNO_HDMI) += phy-inno-hdmi.o
obj-$(CONFIG_PHY_AIROHA_PCIE) += phy-airoha-pcie.o
obj-$(CONFIG_PHY_CAN_TRANSCEIVER) += phy-can-transceiver.o
obj-$(CONFIG_PHY_ECONET_PCIE) += phy-econet-pcie.o
diff --git a/drivers/phy/phy-inno-hdmi.c b/drivers/phy/phy-inno-hdmi.c
new file mode 100644
index 0000000000000000000000000000000000000000..deb2b73a86f5d6be96dedc818c39777904eb37ee
--- /dev/null
+++ b/drivers/phy/phy-inno-hdmi.c
@@ -0,0 +1,297 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Common helpers for the Innosilicon HDMI PHY.
+ *
+ * Copyright (c) 2017 Rockchip Electronics Co. Ltd.
+ * Copyright (c) 2025 Samsung Electronics Co., Ltd.
+ *
+ * Author: Zheng Yang <zhengyang@rock-chips.com>
+ * Author: Michal Wilczynski <m.wilczynski@samsung.com>
+ *
+ * Derived from drivers/phy/rockchip/phy-rockchip-inno-hdmi.c.
+ *
+ * The same PHY IP is used by several SoCs, which differ in where the PHY
+ * register block sits and in the pixel clock table they support, but share
+ * the pre-PLL programming sequence.
+ */
+
+#include <linux/bitfield.h>
+#include <linux/bits.h>
+#include <linux/clk-provider.h>
+#include <linux/errno.h>
+#include <linux/export.h>
+#include <linux/iopoll.h>
+#include <linux/math64.h>
+#include <linux/module.h>
+#include <linux/regmap.h>
+
+#include <linux/phy/inno-hdmi-phy.h>
+
+#define INNO_PRE_PLL_CONTROL 0xa0
+#define INNO_PRE_PLL_POWER_DOWN BIT(0)
+#define INNO_PCLK_VCO_DIV_5_MASK BIT(1)
+#define INNO_PCLK_VCO_DIV_5(x) FIELD_PREP(BIT(1), x)
+
+#define INNO_PRE_PLL_DIV_1 0xa1
+#define INNO_PRE_PLL_PRE_DIV_MASK GENMASK(5, 0)
+#define INNO_PRE_PLL_PRE_DIV(x) FIELD_PREP(GENMASK(5, 0), x)
+
+#define INNO_PRE_PLL_DIV_2 0xa2
+#define INNO_SPREAD_SPECTRUM_MOD_DISABLE BIT(6)
+#define INNO_PRE_PLL_FRAC_DIV_DISABLE FIELD_PREP(GENMASK(5, 4), 3)
+#define INNO_PRE_PLL_FB_DIV_11_8_MASK GENMASK(3, 0)
+#define INNO_PRE_PLL_FB_DIV_11_8(x) FIELD_PREP(GENMASK(3, 0), (x) >> 8)
+
+#define INNO_PRE_PLL_DIV_3 0xa3
+#define INNO_PRE_PLL_FB_DIV_7_0(x) FIELD_PREP(GENMASK(7, 0), x)
+
+#define INNO_PRE_PLL_TMDSCLK_DIV 0xa4
+#define INNO_PRE_PLL_TMDSCLK_DIV_C(x) FIELD_PREP(GENMASK(1, 0), x)
+#define INNO_PRE_PLL_TMDSCLK_DIV_B(x) FIELD_PREP(GENMASK(3, 2), x)
+#define INNO_PRE_PLL_TMDSCLK_DIV_A(x) FIELD_PREP(GENMASK(5, 4), x)
+
+#define INNO_PCLK_DIV_AB 0xa5
+#define INNO_PCLK_DIV_B_MASK GENMASK(6, 5)
+#define INNO_PCLK_DIV_B(x) FIELD_PREP(GENMASK(6, 5), x)
+#define INNO_PCLK_DIV_A_MASK GENMASK(4, 0)
+#define INNO_PCLK_DIV_A(x) FIELD_PREP(GENMASK(4, 0), x)
+
+#define INNO_PCLK_DIV_CD 0xa6
+#define INNO_PCLK_DIV_C(x) FIELD_PREP(GENMASK(6, 5), x)
+#define INNO_PCLK_DIV_D_MASK GENMASK(4, 0)
+#define INNO_PCLK_DIV_D(x) FIELD_PREP(GENMASK(4, 0), x)
+
+#define INNO_PRE_PLL_LOCK_STATUS 0xa9
+#define INNO_PRE_PLL_LOCK BIT(0)
+
+#define INNO_PRE_PLL_FRAC_DIV_23_16 0xd1
+#define INNO_PRE_PLL_FRAC_DIV_15_8 0xd2
+#define INNO_PRE_PLL_FRAC_DIV_7_0 0xd3
+#define INNO_PRE_PLL_FRAC_DIV(x) FIELD_PREP(GENMASK(7, 0), x)
+
+#define INNO_FRAC_DIV_WIDTH 24
+
+static unsigned int inno_reg(const struct inno_hdmi_phy_pre_pll *pll,
+ unsigned int reg)
+{
+ return (pll->offset + reg) * 4;
+}
+
+static void inno_write(const struct inno_hdmi_phy_pre_pll *pll,
+ unsigned int reg, u8 val)
+{
+ regmap_write(pll->regmap, inno_reg(pll, reg), val);
+}
+
+static u8 inno_read(const struct inno_hdmi_phy_pre_pll *pll, unsigned int reg)
+{
+ unsigned int val;
+
+ regmap_read(pll->regmap, inno_reg(pll, reg), &val);
+
+ return val;
+}
+
+static void inno_update_bits(const struct inno_hdmi_phy_pre_pll *pll,
+ unsigned int reg, u8 mask, u8 val)
+{
+ regmap_update_bits(pll->regmap, inno_reg(pll, reg), mask, val);
+}
+
+/**
+ * inno_hdmi_phy_pre_pll_lookup - find the settings for a pixel clock
+ * @pll: pre-PLL instance
+ * @pixclock: requested pixel clock, in Hz
+ * @tmdsclock: requested TMDS clock, in Hz
+ *
+ * Return: the matching table entry, or an ERR_PTR if the PHY cannot generate
+ * the requested combination.
+ */
+const struct inno_hdmi_phy_pre_pll_config *
+inno_hdmi_phy_pre_pll_lookup(const struct inno_hdmi_phy_pre_pll *pll,
+ unsigned long pixclock, unsigned long tmdsclock)
+{
+ const struct inno_hdmi_phy_pre_pll_config *cfg;
+
+ for (cfg = pll->table; cfg->pixclock != 0; cfg++)
+ if (cfg->pixclock == pixclock && cfg->tmdsclock == tmdsclock)
+ return cfg;
+
+ return ERR_PTR(-EINVAL);
+}
+EXPORT_SYMBOL_GPL(inno_hdmi_phy_pre_pll_lookup);
+
+/**
+ * inno_hdmi_phy_pre_pll_determine_rate - clk_ops.determine_rate helper
+ * @pll: pre-PLL instance
+ * @req: rate request, updated with the rate the PHY would produce
+ *
+ * The PHY can only generate the pixel clocks described by its table, so a
+ * request that does not appear there is rejected rather than rounded.
+ *
+ * Return: 0 on success, -EINVAL if the rate is not supported.
+ */
+int inno_hdmi_phy_pre_pll_determine_rate(const struct inno_hdmi_phy_pre_pll *pll,
+ struct clk_rate_request *req)
+{
+ const struct inno_hdmi_phy_pre_pll_config *cfg;
+ unsigned long rate = rounddown(req->rate, 1000);
+
+ for (cfg = pll->table; cfg->pixclock != 0; cfg++) {
+ if (cfg->pixclock == rate) {
+ req->rate = cfg->pixclock;
+ return 0;
+ }
+ }
+
+ return -EINVAL;
+}
+EXPORT_SYMBOL_GPL(inno_hdmi_phy_pre_pll_determine_rate);
+
+/**
+ * inno_hdmi_phy_pre_pll_recalc_rate - clk_ops.recalc_rate helper
+ * @pll: pre-PLL instance
+ * @parent_rate: rate of the reference clock, in Hz
+ *
+ * Return: the pixel clock the pre-PLL is currently programmed for, in Hz.
+ */
+unsigned long
+inno_hdmi_phy_pre_pll_recalc_rate(const struct inno_hdmi_phy_pre_pll *pll,
+ unsigned long parent_rate)
+{
+ u8 nd, no_a, no_b, no_d;
+ unsigned long frac;
+ u64 vco;
+ u16 nf;
+
+ nd = inno_read(pll, INNO_PRE_PLL_DIV_1) & INNO_PRE_PLL_PRE_DIV_MASK;
+ nf = (inno_read(pll, INNO_PRE_PLL_DIV_2) &
+ INNO_PRE_PLL_FB_DIV_11_8_MASK) << 8;
+ nf |= inno_read(pll, INNO_PRE_PLL_DIV_3);
+ vco = parent_rate * nf;
+
+ if (!(inno_read(pll, INNO_PRE_PLL_DIV_2) &
+ INNO_PRE_PLL_FRAC_DIV_DISABLE)) {
+ frac = inno_read(pll, INNO_PRE_PLL_FRAC_DIV_7_0) |
+ (inno_read(pll, INNO_PRE_PLL_FRAC_DIV_15_8) << 8) |
+ (inno_read(pll, INNO_PRE_PLL_FRAC_DIV_23_16) << 16);
+ vco += DIV_ROUND_CLOSEST(parent_rate * frac,
+ BIT(INNO_FRAC_DIV_WIDTH));
+ }
+
+ if (inno_read(pll, INNO_PRE_PLL_CONTROL) & INNO_PCLK_VCO_DIV_5_MASK) {
+ do_div(vco, nd * 5);
+ } else {
+ no_a = inno_read(pll, INNO_PCLK_DIV_AB) & INNO_PCLK_DIV_A_MASK;
+ no_b = FIELD_GET(INNO_PCLK_DIV_B_MASK,
+ inno_read(pll, INNO_PCLK_DIV_AB)) + 2;
+ no_d = inno_read(pll, INNO_PCLK_DIV_CD) & INNO_PCLK_DIV_D_MASK;
+
+ do_div(vco, nd * (no_a == 1 ? no_b : no_a) * no_d * 2);
+ }
+
+ return DIV_ROUND_CLOSEST((unsigned long)vco, 1000) * 1000;
+}
+EXPORT_SYMBOL_GPL(inno_hdmi_phy_pre_pll_recalc_rate);
+
+/**
+ * inno_hdmi_phy_pre_pll_configure - program the pre-PLL dividers
+ * @pll: pre-PLL instance
+ * @cfg: settings to program
+ *
+ * The caller is responsible for powering the pre-PLL down beforehand and back
+ * up afterwards, and for waiting for it to lock.
+ */
+void inno_hdmi_phy_pre_pll_configure(const struct inno_hdmi_phy_pre_pll *pll,
+ const struct inno_hdmi_phy_pre_pll_config *cfg)
+{
+ u8 val;
+
+ inno_update_bits(pll, INNO_PRE_PLL_CONTROL, INNO_PCLK_VCO_DIV_5_MASK,
+ INNO_PCLK_VCO_DIV_5(cfg->vco_div_5_en));
+ inno_write(pll, INNO_PRE_PLL_DIV_1, INNO_PRE_PLL_PRE_DIV(cfg->prediv));
+
+ val = INNO_SPREAD_SPECTRUM_MOD_DISABLE;
+ if (!cfg->fracdiv)
+ val |= INNO_PRE_PLL_FRAC_DIV_DISABLE;
+
+ inno_write(pll, INNO_PRE_PLL_DIV_2,
+ INNO_PRE_PLL_FB_DIV_11_8(cfg->fbdiv) | val);
+ inno_write(pll, INNO_PRE_PLL_DIV_3,
+ INNO_PRE_PLL_FB_DIV_7_0(cfg->fbdiv));
+
+ inno_write(pll, INNO_PCLK_DIV_AB,
+ INNO_PCLK_DIV_A(cfg->pclk_div_a) |
+ INNO_PCLK_DIV_B(cfg->pclk_div_b));
+ inno_write(pll, INNO_PCLK_DIV_CD,
+ INNO_PCLK_DIV_C(cfg->pclk_div_c) |
+ INNO_PCLK_DIV_D(cfg->pclk_div_d));
+
+ inno_write(pll, INNO_PRE_PLL_TMDSCLK_DIV,
+ INNO_PRE_PLL_TMDSCLK_DIV_A(cfg->tmds_div_a) |
+ INNO_PRE_PLL_TMDSCLK_DIV_B(cfg->tmds_div_b) |
+ INNO_PRE_PLL_TMDSCLK_DIV_C(cfg->tmds_div_c));
+
+ inno_write(pll, INNO_PRE_PLL_FRAC_DIV_7_0,
+ INNO_PRE_PLL_FRAC_DIV(cfg->fracdiv));
+ inno_write(pll, INNO_PRE_PLL_FRAC_DIV_15_8,
+ INNO_PRE_PLL_FRAC_DIV(cfg->fracdiv >> 8));
+ inno_write(pll, INNO_PRE_PLL_FRAC_DIV_23_16,
+ INNO_PRE_PLL_FRAC_DIV(cfg->fracdiv >> 16));
+}
+EXPORT_SYMBOL_GPL(inno_hdmi_phy_pre_pll_configure);
+
+/**
+ * inno_hdmi_phy_pre_pll_power_down - power the pre-PLL down or up
+ * @pll: pre-PLL instance
+ * @power_down: true to power down, false to power up
+ */
+void inno_hdmi_phy_pre_pll_power_down(const struct inno_hdmi_phy_pre_pll *pll,
+ bool power_down)
+{
+ inno_update_bits(pll, INNO_PRE_PLL_CONTROL, INNO_PRE_PLL_POWER_DOWN,
+ power_down ? INNO_PRE_PLL_POWER_DOWN : 0);
+}
+EXPORT_SYMBOL_GPL(inno_hdmi_phy_pre_pll_power_down);
+
+/**
+ * inno_hdmi_phy_pre_pll_is_powered - report whether the pre-PLL is powered up
+ * @pll: pre-PLL instance
+ */
+bool inno_hdmi_phy_pre_pll_is_powered(const struct inno_hdmi_phy_pre_pll *pll)
+{
+ return !(inno_read(pll, INNO_PRE_PLL_CONTROL) & INNO_PRE_PLL_POWER_DOWN);
+}
+EXPORT_SYMBOL_GPL(inno_hdmi_phy_pre_pll_is_powered);
+
+/**
+ * inno_hdmi_phy_pre_pll_is_locked - report whether the pre-PLL has locked
+ * @pll: pre-PLL instance
+ */
+bool inno_hdmi_phy_pre_pll_is_locked(const struct inno_hdmi_phy_pre_pll *pll)
+{
+ return inno_read(pll, INNO_PRE_PLL_LOCK_STATUS) & INNO_PRE_PLL_LOCK;
+}
+EXPORT_SYMBOL_GPL(inno_hdmi_phy_pre_pll_is_locked);
+
+/**
+ * inno_hdmi_phy_pre_pll_wait_locked - wait for the pre-PLL to lock
+ * @pll: pre-PLL instance
+ * @timeout_us: how long to wait, in microseconds
+ *
+ * Return: 0 once locked, -ETIMEDOUT otherwise.
+ */
+int inno_hdmi_phy_pre_pll_wait_locked(const struct inno_hdmi_phy_pre_pll *pll,
+ unsigned int timeout_us)
+{
+ unsigned int val;
+
+ return regmap_read_poll_timeout(pll->regmap,
+ inno_reg(pll, INNO_PRE_PLL_LOCK_STATUS),
+ val, val & INNO_PRE_PLL_LOCK,
+ 1000, timeout_us);
+}
+EXPORT_SYMBOL_GPL(inno_hdmi_phy_pre_pll_wait_locked);
+
+MODULE_DESCRIPTION("Innosilicon HDMI PHY common helpers");
+MODULE_LICENSE("GPL");
diff --git a/include/linux/phy/inno-hdmi-phy.h b/include/linux/phy/inno-hdmi-phy.h
new file mode 100644
index 0000000000000000000000000000000000000000..e13911e1a18437cf9cefa43dac494caeb2935782
--- /dev/null
+++ b/include/linux/phy/inno-hdmi-phy.h
@@ -0,0 +1,85 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+/*
+ * Common helpers for the Innosilicon HDMI PHY.
+ *
+ * Copyright (c) 2017 Rockchip Electronics Co. Ltd.
+ * Copyright (c) 2025 Samsung Electronics Co., Ltd.
+ *
+ * Author: Zheng Yang <zhengyang@rock-chips.com>
+ * Author: Michal Wilczynski <m.wilczynski@samsung.com>
+ *
+ * Derived from drivers/phy/rockchip/phy-rockchip-inno-hdmi.c.
+ */
+
+#ifndef __PHY_INNO_HDMI_H__
+#define __PHY_INNO_HDMI_H__
+
+#include <linux/types.h>
+
+struct clk_rate_request;
+struct regmap;
+
+/**
+ * struct inno_hdmi_phy_pre_pll_config - pre-PLL settings for one pixel clock
+ * @pixclock: pixel clock this entry describes, in Hz
+ * @tmdsclock: TMDS clock this entry describes, in Hz
+ * @prediv: pre-PLL reference divider
+ * @fbdiv: pre-PLL feedback divider
+ * @tmds_div_a: TMDS clock divider A
+ * @tmds_div_b: TMDS clock divider B
+ * @tmds_div_c: TMDS clock divider C
+ * @pclk_div_a: pixel clock divider A
+ * @pclk_div_b: pixel clock divider B
+ * @pclk_div_c: pixel clock divider C
+ * @pclk_div_d: pixel clock divider D
+ * @vco_div_5_en: divide the VCO output by five
+ * @fracdiv: pre-PLL fractional divider, zero to use integer mode
+ */
+struct inno_hdmi_phy_pre_pll_config {
+ unsigned long pixclock;
+ unsigned long tmdsclock;
+ u8 prediv;
+ u16 fbdiv;
+ u8 tmds_div_a;
+ u8 tmds_div_b;
+ u8 tmds_div_c;
+ u8 pclk_div_a;
+ u8 pclk_div_b;
+ u8 pclk_div_c;
+ u8 pclk_div_d;
+ u8 vco_div_5_en;
+ u32 fracdiv;
+};
+
+/**
+ * struct inno_hdmi_phy_pre_pll - a pre-PLL instance
+ * @regmap: register map covering the PHY registers
+ * @offset: offset of the PHY register block, in units of the register index.
+ * Zero where the PHY block starts the register space, 0x100 on the
+ * StarFive JH7110 where it is preceded by the HDMI controller.
+ * @table: pixel clock table, terminated by an entry with a zero pixclock
+ */
+struct inno_hdmi_phy_pre_pll {
+ struct regmap *regmap;
+ unsigned int offset;
+ const struct inno_hdmi_phy_pre_pll_config *table;
+};
+
+const struct inno_hdmi_phy_pre_pll_config *
+inno_hdmi_phy_pre_pll_lookup(const struct inno_hdmi_phy_pre_pll *pll,
+ unsigned long pixclock, unsigned long tmdsclock);
+int inno_hdmi_phy_pre_pll_determine_rate(const struct inno_hdmi_phy_pre_pll *pll,
+ struct clk_rate_request *req);
+unsigned long
+inno_hdmi_phy_pre_pll_recalc_rate(const struct inno_hdmi_phy_pre_pll *pll,
+ unsigned long parent_rate);
+void inno_hdmi_phy_pre_pll_configure(const struct inno_hdmi_phy_pre_pll *pll,
+ const struct inno_hdmi_phy_pre_pll_config *cfg);
+void inno_hdmi_phy_pre_pll_power_down(const struct inno_hdmi_phy_pre_pll *pll,
+ bool power_down);
+bool inno_hdmi_phy_pre_pll_is_powered(const struct inno_hdmi_phy_pre_pll *pll);
+bool inno_hdmi_phy_pre_pll_is_locked(const struct inno_hdmi_phy_pre_pll *pll);
+int inno_hdmi_phy_pre_pll_wait_locked(const struct inno_hdmi_phy_pre_pll *pll,
+ unsigned int timeout_us);
+
+#endif /* __PHY_INNO_HDMI_H__ */
--
2.34.1
--
linux-phy mailing list
linux-phy@lists.infradead.org
https://lists.infradead.org/mailman/listinfo/linux-phy
^ permalink raw reply related [flat|nested] 116+ messages in thread
* [PATCH v2 11/15] phy: Add common Innosilicon HDMI PHY helpers
@ 2026-08-28 13:47 ` Michal Wilczynski
0 siblings, 0 replies; 116+ messages in thread
From: Michal Wilczynski @ 2026-08-28 13:47 UTC (permalink / raw)
To: Vinod Koul, Neil Armstrong, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Andrzej Hajda, Robert Foss, Laurent Pinchart,
Jonas Karlman, Jernej Skrabec, Luca Ceresoli, David Airlie,
Simona Vetter, Maarten Lankhorst, Maxime Ripard,
Thomas Zimmermann, Lee Jones, Andy Yan, Philipp Zabel,
Emil Renner Berthing, Hal Feng, Michael Turquette, Stephen Boyd,
Brian Masney, Heiko Stuebner, Conor Dooley, Paul Walmsley,
Palmer Dabbelt, Albert Ou, Alexandre Ghiti, Dominique Belhachemi
Cc: linux-phy, devicetree, linux-kernel, dri-devel, mfd, linux-clk,
linux-arm-kernel, linux-rockchip, linux-riscv, Icenowy Zheng,
Andy Yan, Marek Szyprowski, Maud Spierings, Graham Markall,
Michal Wilczynski
The Innosilicon HDMI PHY IP is used by several SoCs. They differ in
where the PHY register block sits in the register space and in which
pixel clocks they support, but the pre-PLL programming sequence and the
layout of its registers are the same.
Add a small library holding that shared part: the pre-PLL configuration
table format, a lookup, clk_ops determine_rate and recalc_rate helpers,
and the pre-PLL register programming. Callers pass a regmap, a register
offset for the PHY block, and their own pixel clock table.
No driver uses it yet; the users are converted separately.
Signed-off-by: Michal Wilczynski <m.wilczynski@samsung.com>
---
drivers/phy/Kconfig | 8 +
drivers/phy/Makefile | 1 +
drivers/phy/phy-inno-hdmi.c | 297 ++++++++++++++++++++++++++++++++++++++
include/linux/phy/inno-hdmi-phy.h | 85 +++++++++++
4 files changed, 391 insertions(+)
diff --git a/drivers/phy/Kconfig b/drivers/phy/Kconfig
index 19f3b7d12b7d492d16000fa52483dc5002590d7a..0e973b3b02a30704d339db9f15d4695bcbec1c75 100644
--- a/drivers/phy/Kconfig
+++ b/drivers/phy/Kconfig
@@ -168,6 +168,14 @@ config PHY_XGENE
help
This option enables support for APM X-Gene SoC multi-purpose PHY.
+config PHY_INNO_HDMI
+ tristate
+ depends on GENERIC_PHY
+ select REGMAP
+ help
+ Common helpers for the Innosilicon HDMI PHY, shared by the SoC
+ drivers that instantiate it. Selected by those drivers.
+
source "drivers/phy/allwinner/Kconfig"
source "drivers/phy/amlogic/Kconfig"
source "drivers/phy/apple/Kconfig"
diff --git a/drivers/phy/Makefile b/drivers/phy/Makefile
index d7aa516bcc49e7662c9c9db421833fe591dfbc05..e93c473dfc6d837ed6ba540f0b0204a0d68d25bf 100644
--- a/drivers/phy/Makefile
+++ b/drivers/phy/Makefile
@@ -7,6 +7,7 @@ obj-$(CONFIG_PHY_COMMON_PROPS) += phy-common-props.o
obj-$(CONFIG_PHY_COMMON_PROPS_TEST) += phy-common-props-test.o
obj-$(CONFIG_GENERIC_PHY) += phy-core.o
obj-$(CONFIG_GENERIC_PHY_MIPI_DPHY) += phy-core-mipi-dphy.o
+obj-$(CONFIG_PHY_INNO_HDMI) += phy-inno-hdmi.o
obj-$(CONFIG_PHY_AIROHA_PCIE) += phy-airoha-pcie.o
obj-$(CONFIG_PHY_CAN_TRANSCEIVER) += phy-can-transceiver.o
obj-$(CONFIG_PHY_ECONET_PCIE) += phy-econet-pcie.o
diff --git a/drivers/phy/phy-inno-hdmi.c b/drivers/phy/phy-inno-hdmi.c
new file mode 100644
index 0000000000000000000000000000000000000000..deb2b73a86f5d6be96dedc818c39777904eb37ee
--- /dev/null
+++ b/drivers/phy/phy-inno-hdmi.c
@@ -0,0 +1,297 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Common helpers for the Innosilicon HDMI PHY.
+ *
+ * Copyright (c) 2017 Rockchip Electronics Co. Ltd.
+ * Copyright (c) 2025 Samsung Electronics Co., Ltd.
+ *
+ * Author: Zheng Yang <zhengyang@rock-chips.com>
+ * Author: Michal Wilczynski <m.wilczynski@samsung.com>
+ *
+ * Derived from drivers/phy/rockchip/phy-rockchip-inno-hdmi.c.
+ *
+ * The same PHY IP is used by several SoCs, which differ in where the PHY
+ * register block sits and in the pixel clock table they support, but share
+ * the pre-PLL programming sequence.
+ */
+
+#include <linux/bitfield.h>
+#include <linux/bits.h>
+#include <linux/clk-provider.h>
+#include <linux/errno.h>
+#include <linux/export.h>
+#include <linux/iopoll.h>
+#include <linux/math64.h>
+#include <linux/module.h>
+#include <linux/regmap.h>
+
+#include <linux/phy/inno-hdmi-phy.h>
+
+#define INNO_PRE_PLL_CONTROL 0xa0
+#define INNO_PRE_PLL_POWER_DOWN BIT(0)
+#define INNO_PCLK_VCO_DIV_5_MASK BIT(1)
+#define INNO_PCLK_VCO_DIV_5(x) FIELD_PREP(BIT(1), x)
+
+#define INNO_PRE_PLL_DIV_1 0xa1
+#define INNO_PRE_PLL_PRE_DIV_MASK GENMASK(5, 0)
+#define INNO_PRE_PLL_PRE_DIV(x) FIELD_PREP(GENMASK(5, 0), x)
+
+#define INNO_PRE_PLL_DIV_2 0xa2
+#define INNO_SPREAD_SPECTRUM_MOD_DISABLE BIT(6)
+#define INNO_PRE_PLL_FRAC_DIV_DISABLE FIELD_PREP(GENMASK(5, 4), 3)
+#define INNO_PRE_PLL_FB_DIV_11_8_MASK GENMASK(3, 0)
+#define INNO_PRE_PLL_FB_DIV_11_8(x) FIELD_PREP(GENMASK(3, 0), (x) >> 8)
+
+#define INNO_PRE_PLL_DIV_3 0xa3
+#define INNO_PRE_PLL_FB_DIV_7_0(x) FIELD_PREP(GENMASK(7, 0), x)
+
+#define INNO_PRE_PLL_TMDSCLK_DIV 0xa4
+#define INNO_PRE_PLL_TMDSCLK_DIV_C(x) FIELD_PREP(GENMASK(1, 0), x)
+#define INNO_PRE_PLL_TMDSCLK_DIV_B(x) FIELD_PREP(GENMASK(3, 2), x)
+#define INNO_PRE_PLL_TMDSCLK_DIV_A(x) FIELD_PREP(GENMASK(5, 4), x)
+
+#define INNO_PCLK_DIV_AB 0xa5
+#define INNO_PCLK_DIV_B_MASK GENMASK(6, 5)
+#define INNO_PCLK_DIV_B(x) FIELD_PREP(GENMASK(6, 5), x)
+#define INNO_PCLK_DIV_A_MASK GENMASK(4, 0)
+#define INNO_PCLK_DIV_A(x) FIELD_PREP(GENMASK(4, 0), x)
+
+#define INNO_PCLK_DIV_CD 0xa6
+#define INNO_PCLK_DIV_C(x) FIELD_PREP(GENMASK(6, 5), x)
+#define INNO_PCLK_DIV_D_MASK GENMASK(4, 0)
+#define INNO_PCLK_DIV_D(x) FIELD_PREP(GENMASK(4, 0), x)
+
+#define INNO_PRE_PLL_LOCK_STATUS 0xa9
+#define INNO_PRE_PLL_LOCK BIT(0)
+
+#define INNO_PRE_PLL_FRAC_DIV_23_16 0xd1
+#define INNO_PRE_PLL_FRAC_DIV_15_8 0xd2
+#define INNO_PRE_PLL_FRAC_DIV_7_0 0xd3
+#define INNO_PRE_PLL_FRAC_DIV(x) FIELD_PREP(GENMASK(7, 0), x)
+
+#define INNO_FRAC_DIV_WIDTH 24
+
+static unsigned int inno_reg(const struct inno_hdmi_phy_pre_pll *pll,
+ unsigned int reg)
+{
+ return (pll->offset + reg) * 4;
+}
+
+static void inno_write(const struct inno_hdmi_phy_pre_pll *pll,
+ unsigned int reg, u8 val)
+{
+ regmap_write(pll->regmap, inno_reg(pll, reg), val);
+}
+
+static u8 inno_read(const struct inno_hdmi_phy_pre_pll *pll, unsigned int reg)
+{
+ unsigned int val;
+
+ regmap_read(pll->regmap, inno_reg(pll, reg), &val);
+
+ return val;
+}
+
+static void inno_update_bits(const struct inno_hdmi_phy_pre_pll *pll,
+ unsigned int reg, u8 mask, u8 val)
+{
+ regmap_update_bits(pll->regmap, inno_reg(pll, reg), mask, val);
+}
+
+/**
+ * inno_hdmi_phy_pre_pll_lookup - find the settings for a pixel clock
+ * @pll: pre-PLL instance
+ * @pixclock: requested pixel clock, in Hz
+ * @tmdsclock: requested TMDS clock, in Hz
+ *
+ * Return: the matching table entry, or an ERR_PTR if the PHY cannot generate
+ * the requested combination.
+ */
+const struct inno_hdmi_phy_pre_pll_config *
+inno_hdmi_phy_pre_pll_lookup(const struct inno_hdmi_phy_pre_pll *pll,
+ unsigned long pixclock, unsigned long tmdsclock)
+{
+ const struct inno_hdmi_phy_pre_pll_config *cfg;
+
+ for (cfg = pll->table; cfg->pixclock != 0; cfg++)
+ if (cfg->pixclock == pixclock && cfg->tmdsclock == tmdsclock)
+ return cfg;
+
+ return ERR_PTR(-EINVAL);
+}
+EXPORT_SYMBOL_GPL(inno_hdmi_phy_pre_pll_lookup);
+
+/**
+ * inno_hdmi_phy_pre_pll_determine_rate - clk_ops.determine_rate helper
+ * @pll: pre-PLL instance
+ * @req: rate request, updated with the rate the PHY would produce
+ *
+ * The PHY can only generate the pixel clocks described by its table, so a
+ * request that does not appear there is rejected rather than rounded.
+ *
+ * Return: 0 on success, -EINVAL if the rate is not supported.
+ */
+int inno_hdmi_phy_pre_pll_determine_rate(const struct inno_hdmi_phy_pre_pll *pll,
+ struct clk_rate_request *req)
+{
+ const struct inno_hdmi_phy_pre_pll_config *cfg;
+ unsigned long rate = rounddown(req->rate, 1000);
+
+ for (cfg = pll->table; cfg->pixclock != 0; cfg++) {
+ if (cfg->pixclock == rate) {
+ req->rate = cfg->pixclock;
+ return 0;
+ }
+ }
+
+ return -EINVAL;
+}
+EXPORT_SYMBOL_GPL(inno_hdmi_phy_pre_pll_determine_rate);
+
+/**
+ * inno_hdmi_phy_pre_pll_recalc_rate - clk_ops.recalc_rate helper
+ * @pll: pre-PLL instance
+ * @parent_rate: rate of the reference clock, in Hz
+ *
+ * Return: the pixel clock the pre-PLL is currently programmed for, in Hz.
+ */
+unsigned long
+inno_hdmi_phy_pre_pll_recalc_rate(const struct inno_hdmi_phy_pre_pll *pll,
+ unsigned long parent_rate)
+{
+ u8 nd, no_a, no_b, no_d;
+ unsigned long frac;
+ u64 vco;
+ u16 nf;
+
+ nd = inno_read(pll, INNO_PRE_PLL_DIV_1) & INNO_PRE_PLL_PRE_DIV_MASK;
+ nf = (inno_read(pll, INNO_PRE_PLL_DIV_2) &
+ INNO_PRE_PLL_FB_DIV_11_8_MASK) << 8;
+ nf |= inno_read(pll, INNO_PRE_PLL_DIV_3);
+ vco = parent_rate * nf;
+
+ if (!(inno_read(pll, INNO_PRE_PLL_DIV_2) &
+ INNO_PRE_PLL_FRAC_DIV_DISABLE)) {
+ frac = inno_read(pll, INNO_PRE_PLL_FRAC_DIV_7_0) |
+ (inno_read(pll, INNO_PRE_PLL_FRAC_DIV_15_8) << 8) |
+ (inno_read(pll, INNO_PRE_PLL_FRAC_DIV_23_16) << 16);
+ vco += DIV_ROUND_CLOSEST(parent_rate * frac,
+ BIT(INNO_FRAC_DIV_WIDTH));
+ }
+
+ if (inno_read(pll, INNO_PRE_PLL_CONTROL) & INNO_PCLK_VCO_DIV_5_MASK) {
+ do_div(vco, nd * 5);
+ } else {
+ no_a = inno_read(pll, INNO_PCLK_DIV_AB) & INNO_PCLK_DIV_A_MASK;
+ no_b = FIELD_GET(INNO_PCLK_DIV_B_MASK,
+ inno_read(pll, INNO_PCLK_DIV_AB)) + 2;
+ no_d = inno_read(pll, INNO_PCLK_DIV_CD) & INNO_PCLK_DIV_D_MASK;
+
+ do_div(vco, nd * (no_a == 1 ? no_b : no_a) * no_d * 2);
+ }
+
+ return DIV_ROUND_CLOSEST((unsigned long)vco, 1000) * 1000;
+}
+EXPORT_SYMBOL_GPL(inno_hdmi_phy_pre_pll_recalc_rate);
+
+/**
+ * inno_hdmi_phy_pre_pll_configure - program the pre-PLL dividers
+ * @pll: pre-PLL instance
+ * @cfg: settings to program
+ *
+ * The caller is responsible for powering the pre-PLL down beforehand and back
+ * up afterwards, and for waiting for it to lock.
+ */
+void inno_hdmi_phy_pre_pll_configure(const struct inno_hdmi_phy_pre_pll *pll,
+ const struct inno_hdmi_phy_pre_pll_config *cfg)
+{
+ u8 val;
+
+ inno_update_bits(pll, INNO_PRE_PLL_CONTROL, INNO_PCLK_VCO_DIV_5_MASK,
+ INNO_PCLK_VCO_DIV_5(cfg->vco_div_5_en));
+ inno_write(pll, INNO_PRE_PLL_DIV_1, INNO_PRE_PLL_PRE_DIV(cfg->prediv));
+
+ val = INNO_SPREAD_SPECTRUM_MOD_DISABLE;
+ if (!cfg->fracdiv)
+ val |= INNO_PRE_PLL_FRAC_DIV_DISABLE;
+
+ inno_write(pll, INNO_PRE_PLL_DIV_2,
+ INNO_PRE_PLL_FB_DIV_11_8(cfg->fbdiv) | val);
+ inno_write(pll, INNO_PRE_PLL_DIV_3,
+ INNO_PRE_PLL_FB_DIV_7_0(cfg->fbdiv));
+
+ inno_write(pll, INNO_PCLK_DIV_AB,
+ INNO_PCLK_DIV_A(cfg->pclk_div_a) |
+ INNO_PCLK_DIV_B(cfg->pclk_div_b));
+ inno_write(pll, INNO_PCLK_DIV_CD,
+ INNO_PCLK_DIV_C(cfg->pclk_div_c) |
+ INNO_PCLK_DIV_D(cfg->pclk_div_d));
+
+ inno_write(pll, INNO_PRE_PLL_TMDSCLK_DIV,
+ INNO_PRE_PLL_TMDSCLK_DIV_A(cfg->tmds_div_a) |
+ INNO_PRE_PLL_TMDSCLK_DIV_B(cfg->tmds_div_b) |
+ INNO_PRE_PLL_TMDSCLK_DIV_C(cfg->tmds_div_c));
+
+ inno_write(pll, INNO_PRE_PLL_FRAC_DIV_7_0,
+ INNO_PRE_PLL_FRAC_DIV(cfg->fracdiv));
+ inno_write(pll, INNO_PRE_PLL_FRAC_DIV_15_8,
+ INNO_PRE_PLL_FRAC_DIV(cfg->fracdiv >> 8));
+ inno_write(pll, INNO_PRE_PLL_FRAC_DIV_23_16,
+ INNO_PRE_PLL_FRAC_DIV(cfg->fracdiv >> 16));
+}
+EXPORT_SYMBOL_GPL(inno_hdmi_phy_pre_pll_configure);
+
+/**
+ * inno_hdmi_phy_pre_pll_power_down - power the pre-PLL down or up
+ * @pll: pre-PLL instance
+ * @power_down: true to power down, false to power up
+ */
+void inno_hdmi_phy_pre_pll_power_down(const struct inno_hdmi_phy_pre_pll *pll,
+ bool power_down)
+{
+ inno_update_bits(pll, INNO_PRE_PLL_CONTROL, INNO_PRE_PLL_POWER_DOWN,
+ power_down ? INNO_PRE_PLL_POWER_DOWN : 0);
+}
+EXPORT_SYMBOL_GPL(inno_hdmi_phy_pre_pll_power_down);
+
+/**
+ * inno_hdmi_phy_pre_pll_is_powered - report whether the pre-PLL is powered up
+ * @pll: pre-PLL instance
+ */
+bool inno_hdmi_phy_pre_pll_is_powered(const struct inno_hdmi_phy_pre_pll *pll)
+{
+ return !(inno_read(pll, INNO_PRE_PLL_CONTROL) & INNO_PRE_PLL_POWER_DOWN);
+}
+EXPORT_SYMBOL_GPL(inno_hdmi_phy_pre_pll_is_powered);
+
+/**
+ * inno_hdmi_phy_pre_pll_is_locked - report whether the pre-PLL has locked
+ * @pll: pre-PLL instance
+ */
+bool inno_hdmi_phy_pre_pll_is_locked(const struct inno_hdmi_phy_pre_pll *pll)
+{
+ return inno_read(pll, INNO_PRE_PLL_LOCK_STATUS) & INNO_PRE_PLL_LOCK;
+}
+EXPORT_SYMBOL_GPL(inno_hdmi_phy_pre_pll_is_locked);
+
+/**
+ * inno_hdmi_phy_pre_pll_wait_locked - wait for the pre-PLL to lock
+ * @pll: pre-PLL instance
+ * @timeout_us: how long to wait, in microseconds
+ *
+ * Return: 0 once locked, -ETIMEDOUT otherwise.
+ */
+int inno_hdmi_phy_pre_pll_wait_locked(const struct inno_hdmi_phy_pre_pll *pll,
+ unsigned int timeout_us)
+{
+ unsigned int val;
+
+ return regmap_read_poll_timeout(pll->regmap,
+ inno_reg(pll, INNO_PRE_PLL_LOCK_STATUS),
+ val, val & INNO_PRE_PLL_LOCK,
+ 1000, timeout_us);
+}
+EXPORT_SYMBOL_GPL(inno_hdmi_phy_pre_pll_wait_locked);
+
+MODULE_DESCRIPTION("Innosilicon HDMI PHY common helpers");
+MODULE_LICENSE("GPL");
diff --git a/include/linux/phy/inno-hdmi-phy.h b/include/linux/phy/inno-hdmi-phy.h
new file mode 100644
index 0000000000000000000000000000000000000000..e13911e1a18437cf9cefa43dac494caeb2935782
--- /dev/null
+++ b/include/linux/phy/inno-hdmi-phy.h
@@ -0,0 +1,85 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+/*
+ * Common helpers for the Innosilicon HDMI PHY.
+ *
+ * Copyright (c) 2017 Rockchip Electronics Co. Ltd.
+ * Copyright (c) 2025 Samsung Electronics Co., Ltd.
+ *
+ * Author: Zheng Yang <zhengyang@rock-chips.com>
+ * Author: Michal Wilczynski <m.wilczynski@samsung.com>
+ *
+ * Derived from drivers/phy/rockchip/phy-rockchip-inno-hdmi.c.
+ */
+
+#ifndef __PHY_INNO_HDMI_H__
+#define __PHY_INNO_HDMI_H__
+
+#include <linux/types.h>
+
+struct clk_rate_request;
+struct regmap;
+
+/**
+ * struct inno_hdmi_phy_pre_pll_config - pre-PLL settings for one pixel clock
+ * @pixclock: pixel clock this entry describes, in Hz
+ * @tmdsclock: TMDS clock this entry describes, in Hz
+ * @prediv: pre-PLL reference divider
+ * @fbdiv: pre-PLL feedback divider
+ * @tmds_div_a: TMDS clock divider A
+ * @tmds_div_b: TMDS clock divider B
+ * @tmds_div_c: TMDS clock divider C
+ * @pclk_div_a: pixel clock divider A
+ * @pclk_div_b: pixel clock divider B
+ * @pclk_div_c: pixel clock divider C
+ * @pclk_div_d: pixel clock divider D
+ * @vco_div_5_en: divide the VCO output by five
+ * @fracdiv: pre-PLL fractional divider, zero to use integer mode
+ */
+struct inno_hdmi_phy_pre_pll_config {
+ unsigned long pixclock;
+ unsigned long tmdsclock;
+ u8 prediv;
+ u16 fbdiv;
+ u8 tmds_div_a;
+ u8 tmds_div_b;
+ u8 tmds_div_c;
+ u8 pclk_div_a;
+ u8 pclk_div_b;
+ u8 pclk_div_c;
+ u8 pclk_div_d;
+ u8 vco_div_5_en;
+ u32 fracdiv;
+};
+
+/**
+ * struct inno_hdmi_phy_pre_pll - a pre-PLL instance
+ * @regmap: register map covering the PHY registers
+ * @offset: offset of the PHY register block, in units of the register index.
+ * Zero where the PHY block starts the register space, 0x100 on the
+ * StarFive JH7110 where it is preceded by the HDMI controller.
+ * @table: pixel clock table, terminated by an entry with a zero pixclock
+ */
+struct inno_hdmi_phy_pre_pll {
+ struct regmap *regmap;
+ unsigned int offset;
+ const struct inno_hdmi_phy_pre_pll_config *table;
+};
+
+const struct inno_hdmi_phy_pre_pll_config *
+inno_hdmi_phy_pre_pll_lookup(const struct inno_hdmi_phy_pre_pll *pll,
+ unsigned long pixclock, unsigned long tmdsclock);
+int inno_hdmi_phy_pre_pll_determine_rate(const struct inno_hdmi_phy_pre_pll *pll,
+ struct clk_rate_request *req);
+unsigned long
+inno_hdmi_phy_pre_pll_recalc_rate(const struct inno_hdmi_phy_pre_pll *pll,
+ unsigned long parent_rate);
+void inno_hdmi_phy_pre_pll_configure(const struct inno_hdmi_phy_pre_pll *pll,
+ const struct inno_hdmi_phy_pre_pll_config *cfg);
+void inno_hdmi_phy_pre_pll_power_down(const struct inno_hdmi_phy_pre_pll *pll,
+ bool power_down);
+bool inno_hdmi_phy_pre_pll_is_powered(const struct inno_hdmi_phy_pre_pll *pll);
+bool inno_hdmi_phy_pre_pll_is_locked(const struct inno_hdmi_phy_pre_pll *pll);
+int inno_hdmi_phy_pre_pll_wait_locked(const struct inno_hdmi_phy_pre_pll *pll,
+ unsigned int timeout_us);
+
+#endif /* __PHY_INNO_HDMI_H__ */
--
2.34.1
_______________________________________________
Linux-rockchip mailing list
Linux-rockchip@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-rockchip
^ permalink raw reply related [flat|nested] 116+ messages in thread
* [PATCH v2 11/15] phy: Add common Innosilicon HDMI PHY helpers
@ 2026-08-28 13:47 ` Michal Wilczynski
0 siblings, 0 replies; 116+ messages in thread
From: Michal Wilczynski @ 2026-08-28 13:47 UTC (permalink / raw)
To: Vinod Koul, Neil Armstrong, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Andrzej Hajda, Robert Foss, Laurent Pinchart,
Jonas Karlman, Jernej Skrabec, Luca Ceresoli, David Airlie,
Simona Vetter, Maarten Lankhorst, Maxime Ripard,
Thomas Zimmermann, Lee Jones, Andy Yan, Philipp Zabel,
Emil Renner Berthing, Hal Feng, Michael Turquette, Stephen Boyd,
Brian Masney, Heiko Stuebner, Conor Dooley, Paul Walmsley,
Palmer Dabbelt, Albert Ou, Alexandre Ghiti, Dominique Belhachemi
Cc: devicetree, mfd, linux-kernel, dri-devel, Andy Yan,
Graham Markall, linux-rockchip, linux-phy, Michal Wilczynski,
linux-riscv, Maud Spierings, linux-clk, linux-arm-kernel,
Marek Szyprowski
The Innosilicon HDMI PHY IP is used by several SoCs. They differ in
where the PHY register block sits in the register space and in which
pixel clocks they support, but the pre-PLL programming sequence and the
layout of its registers are the same.
Add a small library holding that shared part: the pre-PLL configuration
table format, a lookup, clk_ops determine_rate and recalc_rate helpers,
and the pre-PLL register programming. Callers pass a regmap, a register
offset for the PHY block, and their own pixel clock table.
No driver uses it yet; the users are converted separately.
Signed-off-by: Michal Wilczynski <m.wilczynski@samsung.com>
---
drivers/phy/Kconfig | 8 +
drivers/phy/Makefile | 1 +
drivers/phy/phy-inno-hdmi.c | 297 ++++++++++++++++++++++++++++++++++++++
include/linux/phy/inno-hdmi-phy.h | 85 +++++++++++
4 files changed, 391 insertions(+)
diff --git a/drivers/phy/Kconfig b/drivers/phy/Kconfig
index 19f3b7d12b7d492d16000fa52483dc5002590d7a..0e973b3b02a30704d339db9f15d4695bcbec1c75 100644
--- a/drivers/phy/Kconfig
+++ b/drivers/phy/Kconfig
@@ -168,6 +168,14 @@ config PHY_XGENE
help
This option enables support for APM X-Gene SoC multi-purpose PHY.
+config PHY_INNO_HDMI
+ tristate
+ depends on GENERIC_PHY
+ select REGMAP
+ help
+ Common helpers for the Innosilicon HDMI PHY, shared by the SoC
+ drivers that instantiate it. Selected by those drivers.
+
source "drivers/phy/allwinner/Kconfig"
source "drivers/phy/amlogic/Kconfig"
source "drivers/phy/apple/Kconfig"
diff --git a/drivers/phy/Makefile b/drivers/phy/Makefile
index d7aa516bcc49e7662c9c9db421833fe591dfbc05..e93c473dfc6d837ed6ba540f0b0204a0d68d25bf 100644
--- a/drivers/phy/Makefile
+++ b/drivers/phy/Makefile
@@ -7,6 +7,7 @@ obj-$(CONFIG_PHY_COMMON_PROPS) += phy-common-props.o
obj-$(CONFIG_PHY_COMMON_PROPS_TEST) += phy-common-props-test.o
obj-$(CONFIG_GENERIC_PHY) += phy-core.o
obj-$(CONFIG_GENERIC_PHY_MIPI_DPHY) += phy-core-mipi-dphy.o
+obj-$(CONFIG_PHY_INNO_HDMI) += phy-inno-hdmi.o
obj-$(CONFIG_PHY_AIROHA_PCIE) += phy-airoha-pcie.o
obj-$(CONFIG_PHY_CAN_TRANSCEIVER) += phy-can-transceiver.o
obj-$(CONFIG_PHY_ECONET_PCIE) += phy-econet-pcie.o
diff --git a/drivers/phy/phy-inno-hdmi.c b/drivers/phy/phy-inno-hdmi.c
new file mode 100644
index 0000000000000000000000000000000000000000..deb2b73a86f5d6be96dedc818c39777904eb37ee
--- /dev/null
+++ b/drivers/phy/phy-inno-hdmi.c
@@ -0,0 +1,297 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Common helpers for the Innosilicon HDMI PHY.
+ *
+ * Copyright (c) 2017 Rockchip Electronics Co. Ltd.
+ * Copyright (c) 2025 Samsung Electronics Co., Ltd.
+ *
+ * Author: Zheng Yang <zhengyang@rock-chips.com>
+ * Author: Michal Wilczynski <m.wilczynski@samsung.com>
+ *
+ * Derived from drivers/phy/rockchip/phy-rockchip-inno-hdmi.c.
+ *
+ * The same PHY IP is used by several SoCs, which differ in where the PHY
+ * register block sits and in the pixel clock table they support, but share
+ * the pre-PLL programming sequence.
+ */
+
+#include <linux/bitfield.h>
+#include <linux/bits.h>
+#include <linux/clk-provider.h>
+#include <linux/errno.h>
+#include <linux/export.h>
+#include <linux/iopoll.h>
+#include <linux/math64.h>
+#include <linux/module.h>
+#include <linux/regmap.h>
+
+#include <linux/phy/inno-hdmi-phy.h>
+
+#define INNO_PRE_PLL_CONTROL 0xa0
+#define INNO_PRE_PLL_POWER_DOWN BIT(0)
+#define INNO_PCLK_VCO_DIV_5_MASK BIT(1)
+#define INNO_PCLK_VCO_DIV_5(x) FIELD_PREP(BIT(1), x)
+
+#define INNO_PRE_PLL_DIV_1 0xa1
+#define INNO_PRE_PLL_PRE_DIV_MASK GENMASK(5, 0)
+#define INNO_PRE_PLL_PRE_DIV(x) FIELD_PREP(GENMASK(5, 0), x)
+
+#define INNO_PRE_PLL_DIV_2 0xa2
+#define INNO_SPREAD_SPECTRUM_MOD_DISABLE BIT(6)
+#define INNO_PRE_PLL_FRAC_DIV_DISABLE FIELD_PREP(GENMASK(5, 4), 3)
+#define INNO_PRE_PLL_FB_DIV_11_8_MASK GENMASK(3, 0)
+#define INNO_PRE_PLL_FB_DIV_11_8(x) FIELD_PREP(GENMASK(3, 0), (x) >> 8)
+
+#define INNO_PRE_PLL_DIV_3 0xa3
+#define INNO_PRE_PLL_FB_DIV_7_0(x) FIELD_PREP(GENMASK(7, 0), x)
+
+#define INNO_PRE_PLL_TMDSCLK_DIV 0xa4
+#define INNO_PRE_PLL_TMDSCLK_DIV_C(x) FIELD_PREP(GENMASK(1, 0), x)
+#define INNO_PRE_PLL_TMDSCLK_DIV_B(x) FIELD_PREP(GENMASK(3, 2), x)
+#define INNO_PRE_PLL_TMDSCLK_DIV_A(x) FIELD_PREP(GENMASK(5, 4), x)
+
+#define INNO_PCLK_DIV_AB 0xa5
+#define INNO_PCLK_DIV_B_MASK GENMASK(6, 5)
+#define INNO_PCLK_DIV_B(x) FIELD_PREP(GENMASK(6, 5), x)
+#define INNO_PCLK_DIV_A_MASK GENMASK(4, 0)
+#define INNO_PCLK_DIV_A(x) FIELD_PREP(GENMASK(4, 0), x)
+
+#define INNO_PCLK_DIV_CD 0xa6
+#define INNO_PCLK_DIV_C(x) FIELD_PREP(GENMASK(6, 5), x)
+#define INNO_PCLK_DIV_D_MASK GENMASK(4, 0)
+#define INNO_PCLK_DIV_D(x) FIELD_PREP(GENMASK(4, 0), x)
+
+#define INNO_PRE_PLL_LOCK_STATUS 0xa9
+#define INNO_PRE_PLL_LOCK BIT(0)
+
+#define INNO_PRE_PLL_FRAC_DIV_23_16 0xd1
+#define INNO_PRE_PLL_FRAC_DIV_15_8 0xd2
+#define INNO_PRE_PLL_FRAC_DIV_7_0 0xd3
+#define INNO_PRE_PLL_FRAC_DIV(x) FIELD_PREP(GENMASK(7, 0), x)
+
+#define INNO_FRAC_DIV_WIDTH 24
+
+static unsigned int inno_reg(const struct inno_hdmi_phy_pre_pll *pll,
+ unsigned int reg)
+{
+ return (pll->offset + reg) * 4;
+}
+
+static void inno_write(const struct inno_hdmi_phy_pre_pll *pll,
+ unsigned int reg, u8 val)
+{
+ regmap_write(pll->regmap, inno_reg(pll, reg), val);
+}
+
+static u8 inno_read(const struct inno_hdmi_phy_pre_pll *pll, unsigned int reg)
+{
+ unsigned int val;
+
+ regmap_read(pll->regmap, inno_reg(pll, reg), &val);
+
+ return val;
+}
+
+static void inno_update_bits(const struct inno_hdmi_phy_pre_pll *pll,
+ unsigned int reg, u8 mask, u8 val)
+{
+ regmap_update_bits(pll->regmap, inno_reg(pll, reg), mask, val);
+}
+
+/**
+ * inno_hdmi_phy_pre_pll_lookup - find the settings for a pixel clock
+ * @pll: pre-PLL instance
+ * @pixclock: requested pixel clock, in Hz
+ * @tmdsclock: requested TMDS clock, in Hz
+ *
+ * Return: the matching table entry, or an ERR_PTR if the PHY cannot generate
+ * the requested combination.
+ */
+const struct inno_hdmi_phy_pre_pll_config *
+inno_hdmi_phy_pre_pll_lookup(const struct inno_hdmi_phy_pre_pll *pll,
+ unsigned long pixclock, unsigned long tmdsclock)
+{
+ const struct inno_hdmi_phy_pre_pll_config *cfg;
+
+ for (cfg = pll->table; cfg->pixclock != 0; cfg++)
+ if (cfg->pixclock == pixclock && cfg->tmdsclock == tmdsclock)
+ return cfg;
+
+ return ERR_PTR(-EINVAL);
+}
+EXPORT_SYMBOL_GPL(inno_hdmi_phy_pre_pll_lookup);
+
+/**
+ * inno_hdmi_phy_pre_pll_determine_rate - clk_ops.determine_rate helper
+ * @pll: pre-PLL instance
+ * @req: rate request, updated with the rate the PHY would produce
+ *
+ * The PHY can only generate the pixel clocks described by its table, so a
+ * request that does not appear there is rejected rather than rounded.
+ *
+ * Return: 0 on success, -EINVAL if the rate is not supported.
+ */
+int inno_hdmi_phy_pre_pll_determine_rate(const struct inno_hdmi_phy_pre_pll *pll,
+ struct clk_rate_request *req)
+{
+ const struct inno_hdmi_phy_pre_pll_config *cfg;
+ unsigned long rate = rounddown(req->rate, 1000);
+
+ for (cfg = pll->table; cfg->pixclock != 0; cfg++) {
+ if (cfg->pixclock == rate) {
+ req->rate = cfg->pixclock;
+ return 0;
+ }
+ }
+
+ return -EINVAL;
+}
+EXPORT_SYMBOL_GPL(inno_hdmi_phy_pre_pll_determine_rate);
+
+/**
+ * inno_hdmi_phy_pre_pll_recalc_rate - clk_ops.recalc_rate helper
+ * @pll: pre-PLL instance
+ * @parent_rate: rate of the reference clock, in Hz
+ *
+ * Return: the pixel clock the pre-PLL is currently programmed for, in Hz.
+ */
+unsigned long
+inno_hdmi_phy_pre_pll_recalc_rate(const struct inno_hdmi_phy_pre_pll *pll,
+ unsigned long parent_rate)
+{
+ u8 nd, no_a, no_b, no_d;
+ unsigned long frac;
+ u64 vco;
+ u16 nf;
+
+ nd = inno_read(pll, INNO_PRE_PLL_DIV_1) & INNO_PRE_PLL_PRE_DIV_MASK;
+ nf = (inno_read(pll, INNO_PRE_PLL_DIV_2) &
+ INNO_PRE_PLL_FB_DIV_11_8_MASK) << 8;
+ nf |= inno_read(pll, INNO_PRE_PLL_DIV_3);
+ vco = parent_rate * nf;
+
+ if (!(inno_read(pll, INNO_PRE_PLL_DIV_2) &
+ INNO_PRE_PLL_FRAC_DIV_DISABLE)) {
+ frac = inno_read(pll, INNO_PRE_PLL_FRAC_DIV_7_0) |
+ (inno_read(pll, INNO_PRE_PLL_FRAC_DIV_15_8) << 8) |
+ (inno_read(pll, INNO_PRE_PLL_FRAC_DIV_23_16) << 16);
+ vco += DIV_ROUND_CLOSEST(parent_rate * frac,
+ BIT(INNO_FRAC_DIV_WIDTH));
+ }
+
+ if (inno_read(pll, INNO_PRE_PLL_CONTROL) & INNO_PCLK_VCO_DIV_5_MASK) {
+ do_div(vco, nd * 5);
+ } else {
+ no_a = inno_read(pll, INNO_PCLK_DIV_AB) & INNO_PCLK_DIV_A_MASK;
+ no_b = FIELD_GET(INNO_PCLK_DIV_B_MASK,
+ inno_read(pll, INNO_PCLK_DIV_AB)) + 2;
+ no_d = inno_read(pll, INNO_PCLK_DIV_CD) & INNO_PCLK_DIV_D_MASK;
+
+ do_div(vco, nd * (no_a == 1 ? no_b : no_a) * no_d * 2);
+ }
+
+ return DIV_ROUND_CLOSEST((unsigned long)vco, 1000) * 1000;
+}
+EXPORT_SYMBOL_GPL(inno_hdmi_phy_pre_pll_recalc_rate);
+
+/**
+ * inno_hdmi_phy_pre_pll_configure - program the pre-PLL dividers
+ * @pll: pre-PLL instance
+ * @cfg: settings to program
+ *
+ * The caller is responsible for powering the pre-PLL down beforehand and back
+ * up afterwards, and for waiting for it to lock.
+ */
+void inno_hdmi_phy_pre_pll_configure(const struct inno_hdmi_phy_pre_pll *pll,
+ const struct inno_hdmi_phy_pre_pll_config *cfg)
+{
+ u8 val;
+
+ inno_update_bits(pll, INNO_PRE_PLL_CONTROL, INNO_PCLK_VCO_DIV_5_MASK,
+ INNO_PCLK_VCO_DIV_5(cfg->vco_div_5_en));
+ inno_write(pll, INNO_PRE_PLL_DIV_1, INNO_PRE_PLL_PRE_DIV(cfg->prediv));
+
+ val = INNO_SPREAD_SPECTRUM_MOD_DISABLE;
+ if (!cfg->fracdiv)
+ val |= INNO_PRE_PLL_FRAC_DIV_DISABLE;
+
+ inno_write(pll, INNO_PRE_PLL_DIV_2,
+ INNO_PRE_PLL_FB_DIV_11_8(cfg->fbdiv) | val);
+ inno_write(pll, INNO_PRE_PLL_DIV_3,
+ INNO_PRE_PLL_FB_DIV_7_0(cfg->fbdiv));
+
+ inno_write(pll, INNO_PCLK_DIV_AB,
+ INNO_PCLK_DIV_A(cfg->pclk_div_a) |
+ INNO_PCLK_DIV_B(cfg->pclk_div_b));
+ inno_write(pll, INNO_PCLK_DIV_CD,
+ INNO_PCLK_DIV_C(cfg->pclk_div_c) |
+ INNO_PCLK_DIV_D(cfg->pclk_div_d));
+
+ inno_write(pll, INNO_PRE_PLL_TMDSCLK_DIV,
+ INNO_PRE_PLL_TMDSCLK_DIV_A(cfg->tmds_div_a) |
+ INNO_PRE_PLL_TMDSCLK_DIV_B(cfg->tmds_div_b) |
+ INNO_PRE_PLL_TMDSCLK_DIV_C(cfg->tmds_div_c));
+
+ inno_write(pll, INNO_PRE_PLL_FRAC_DIV_7_0,
+ INNO_PRE_PLL_FRAC_DIV(cfg->fracdiv));
+ inno_write(pll, INNO_PRE_PLL_FRAC_DIV_15_8,
+ INNO_PRE_PLL_FRAC_DIV(cfg->fracdiv >> 8));
+ inno_write(pll, INNO_PRE_PLL_FRAC_DIV_23_16,
+ INNO_PRE_PLL_FRAC_DIV(cfg->fracdiv >> 16));
+}
+EXPORT_SYMBOL_GPL(inno_hdmi_phy_pre_pll_configure);
+
+/**
+ * inno_hdmi_phy_pre_pll_power_down - power the pre-PLL down or up
+ * @pll: pre-PLL instance
+ * @power_down: true to power down, false to power up
+ */
+void inno_hdmi_phy_pre_pll_power_down(const struct inno_hdmi_phy_pre_pll *pll,
+ bool power_down)
+{
+ inno_update_bits(pll, INNO_PRE_PLL_CONTROL, INNO_PRE_PLL_POWER_DOWN,
+ power_down ? INNO_PRE_PLL_POWER_DOWN : 0);
+}
+EXPORT_SYMBOL_GPL(inno_hdmi_phy_pre_pll_power_down);
+
+/**
+ * inno_hdmi_phy_pre_pll_is_powered - report whether the pre-PLL is powered up
+ * @pll: pre-PLL instance
+ */
+bool inno_hdmi_phy_pre_pll_is_powered(const struct inno_hdmi_phy_pre_pll *pll)
+{
+ return !(inno_read(pll, INNO_PRE_PLL_CONTROL) & INNO_PRE_PLL_POWER_DOWN);
+}
+EXPORT_SYMBOL_GPL(inno_hdmi_phy_pre_pll_is_powered);
+
+/**
+ * inno_hdmi_phy_pre_pll_is_locked - report whether the pre-PLL has locked
+ * @pll: pre-PLL instance
+ */
+bool inno_hdmi_phy_pre_pll_is_locked(const struct inno_hdmi_phy_pre_pll *pll)
+{
+ return inno_read(pll, INNO_PRE_PLL_LOCK_STATUS) & INNO_PRE_PLL_LOCK;
+}
+EXPORT_SYMBOL_GPL(inno_hdmi_phy_pre_pll_is_locked);
+
+/**
+ * inno_hdmi_phy_pre_pll_wait_locked - wait for the pre-PLL to lock
+ * @pll: pre-PLL instance
+ * @timeout_us: how long to wait, in microseconds
+ *
+ * Return: 0 once locked, -ETIMEDOUT otherwise.
+ */
+int inno_hdmi_phy_pre_pll_wait_locked(const struct inno_hdmi_phy_pre_pll *pll,
+ unsigned int timeout_us)
+{
+ unsigned int val;
+
+ return regmap_read_poll_timeout(pll->regmap,
+ inno_reg(pll, INNO_PRE_PLL_LOCK_STATUS),
+ val, val & INNO_PRE_PLL_LOCK,
+ 1000, timeout_us);
+}
+EXPORT_SYMBOL_GPL(inno_hdmi_phy_pre_pll_wait_locked);
+
+MODULE_DESCRIPTION("Innosilicon HDMI PHY common helpers");
+MODULE_LICENSE("GPL");
diff --git a/include/linux/phy/inno-hdmi-phy.h b/include/linux/phy/inno-hdmi-phy.h
new file mode 100644
index 0000000000000000000000000000000000000000..e13911e1a18437cf9cefa43dac494caeb2935782
--- /dev/null
+++ b/include/linux/phy/inno-hdmi-phy.h
@@ -0,0 +1,85 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+/*
+ * Common helpers for the Innosilicon HDMI PHY.
+ *
+ * Copyright (c) 2017 Rockchip Electronics Co. Ltd.
+ * Copyright (c) 2025 Samsung Electronics Co., Ltd.
+ *
+ * Author: Zheng Yang <zhengyang@rock-chips.com>
+ * Author: Michal Wilczynski <m.wilczynski@samsung.com>
+ *
+ * Derived from drivers/phy/rockchip/phy-rockchip-inno-hdmi.c.
+ */
+
+#ifndef __PHY_INNO_HDMI_H__
+#define __PHY_INNO_HDMI_H__
+
+#include <linux/types.h>
+
+struct clk_rate_request;
+struct regmap;
+
+/**
+ * struct inno_hdmi_phy_pre_pll_config - pre-PLL settings for one pixel clock
+ * @pixclock: pixel clock this entry describes, in Hz
+ * @tmdsclock: TMDS clock this entry describes, in Hz
+ * @prediv: pre-PLL reference divider
+ * @fbdiv: pre-PLL feedback divider
+ * @tmds_div_a: TMDS clock divider A
+ * @tmds_div_b: TMDS clock divider B
+ * @tmds_div_c: TMDS clock divider C
+ * @pclk_div_a: pixel clock divider A
+ * @pclk_div_b: pixel clock divider B
+ * @pclk_div_c: pixel clock divider C
+ * @pclk_div_d: pixel clock divider D
+ * @vco_div_5_en: divide the VCO output by five
+ * @fracdiv: pre-PLL fractional divider, zero to use integer mode
+ */
+struct inno_hdmi_phy_pre_pll_config {
+ unsigned long pixclock;
+ unsigned long tmdsclock;
+ u8 prediv;
+ u16 fbdiv;
+ u8 tmds_div_a;
+ u8 tmds_div_b;
+ u8 tmds_div_c;
+ u8 pclk_div_a;
+ u8 pclk_div_b;
+ u8 pclk_div_c;
+ u8 pclk_div_d;
+ u8 vco_div_5_en;
+ u32 fracdiv;
+};
+
+/**
+ * struct inno_hdmi_phy_pre_pll - a pre-PLL instance
+ * @regmap: register map covering the PHY registers
+ * @offset: offset of the PHY register block, in units of the register index.
+ * Zero where the PHY block starts the register space, 0x100 on the
+ * StarFive JH7110 where it is preceded by the HDMI controller.
+ * @table: pixel clock table, terminated by an entry with a zero pixclock
+ */
+struct inno_hdmi_phy_pre_pll {
+ struct regmap *regmap;
+ unsigned int offset;
+ const struct inno_hdmi_phy_pre_pll_config *table;
+};
+
+const struct inno_hdmi_phy_pre_pll_config *
+inno_hdmi_phy_pre_pll_lookup(const struct inno_hdmi_phy_pre_pll *pll,
+ unsigned long pixclock, unsigned long tmdsclock);
+int inno_hdmi_phy_pre_pll_determine_rate(const struct inno_hdmi_phy_pre_pll *pll,
+ struct clk_rate_request *req);
+unsigned long
+inno_hdmi_phy_pre_pll_recalc_rate(const struct inno_hdmi_phy_pre_pll *pll,
+ unsigned long parent_rate);
+void inno_hdmi_phy_pre_pll_configure(const struct inno_hdmi_phy_pre_pll *pll,
+ const struct inno_hdmi_phy_pre_pll_config *cfg);
+void inno_hdmi_phy_pre_pll_power_down(const struct inno_hdmi_phy_pre_pll *pll,
+ bool power_down);
+bool inno_hdmi_phy_pre_pll_is_powered(const struct inno_hdmi_phy_pre_pll *pll);
+bool inno_hdmi_phy_pre_pll_is_locked(const struct inno_hdmi_phy_pre_pll *pll);
+int inno_hdmi_phy_pre_pll_wait_locked(const struct inno_hdmi_phy_pre_pll *pll,
+ unsigned int timeout_us);
+
+#endif /* __PHY_INNO_HDMI_H__ */
--
2.34.1
_______________________________________________
linux-riscv mailing list
linux-riscv@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-riscv
^ permalink raw reply related [flat|nested] 116+ messages in thread
* [PATCH v2 12/15] phy: rockchip: inno-hdmi: Use the common Innosilicon PHY helpers
2026-08-28 13:47 ` Michal Wilczynski
(?)
(?)
@ 2026-08-28 13:47 ` Michal Wilczynski
-1 siblings, 0 replies; 116+ messages in thread
From: Michal Wilczynski @ 2026-08-28 13:47 UTC (permalink / raw)
To: Vinod Koul, Neil Armstrong, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Andrzej Hajda, Robert Foss, Laurent Pinchart,
Jonas Karlman, Jernej Skrabec, Luca Ceresoli, David Airlie,
Simona Vetter, Maarten Lankhorst, Maxime Ripard,
Thomas Zimmermann, Lee Jones, Andy Yan, Philipp Zabel,
Emil Renner Berthing, Hal Feng, Michael Turquette, Stephen Boyd,
Brian Masney, Heiko Stuebner, Conor Dooley, Paul Walmsley,
Palmer Dabbelt, Albert Ou, Alexandre Ghiti, Dominique Belhachemi
Cc: linux-phy, devicetree, linux-kernel, dri-devel, mfd, linux-clk,
linux-arm-kernel, linux-rockchip, linux-riscv, Icenowy Zheng,
Andy Yan, Marek Szyprowski, Maud Spierings, Graham Markall,
Michal Wilczynski
The RK3328 pre-PLL programming, its table lookup and its recalc_rate and
determine_rate implementations are the generic Innosilicon ones, so drop
the local copies and use the shared helpers instead.
The RK3228 pre-PLL sits at different register addresses, so it keeps its
own register level code and only shares the table lookup.
The register writes, their order and the values written are unchanged.
No functional change intended.
Signed-off-by: Michal Wilczynski <m.wilczynski@samsung.com>
---
drivers/phy/rockchip/Kconfig | 1 +
drivers/phy/rockchip/phy-rockchip-inno-hdmi.c | 127 +++++---------------------
2 files changed, 25 insertions(+), 103 deletions(-)
diff --git a/drivers/phy/rockchip/Kconfig b/drivers/phy/rockchip/Kconfig
index 14698571b607590dc0e7a29f3b39eb9a5d4e3d25..9732c5be87717dc3ddbea1c60080952336a07af9 100644
--- a/drivers/phy/rockchip/Kconfig
+++ b/drivers/phy/rockchip/Kconfig
@@ -34,6 +34,7 @@ config PHY_ROCKCHIP_INNO_HDMI
depends on COMMON_CLK
depends on HAS_IOMEM
select GENERIC_PHY
+ select PHY_INNO_HDMI
help
Enable this to support the Rockchip Innosilicon HDMI PHY.
diff --git a/drivers/phy/rockchip/phy-rockchip-inno-hdmi.c b/drivers/phy/rockchip/phy-rockchip-inno-hdmi.c
index 1483907413faa5ce1dc8614db05e6e929410404d..fae766607b0ea120b3adb36001387062f39a5c00 100644
--- a/drivers/phy/rockchip/phy-rockchip-inno-hdmi.c
+++ b/drivers/phy/rockchip/phy-rockchip-inno-hdmi.c
@@ -17,6 +17,7 @@
#include <linux/of.h>
#include <linux/platform_device.h>
#include <linux/regmap.h>
+#include <linux/phy/inno-hdmi-phy.h>
#include <linux/phy/phy.h>
#include <linux/slab.h>
@@ -240,6 +241,8 @@ struct inno_hdmi_phy {
const struct inno_hdmi_phy_drv_data *plat_data;
int chip_version;
+ struct inno_hdmi_phy_pre_pll pre_pll;
+
/* clk provider */
struct clk_hw hw;
struct clk *phyclk;
@@ -247,21 +250,6 @@ struct inno_hdmi_phy {
unsigned long tmdsclock;
};
-struct pre_pll_config {
- unsigned long pixclock;
- unsigned long tmdsclock;
- u8 prediv;
- u16 fbdiv;
- u8 tmds_div_a;
- u8 tmds_div_b;
- u8 tmds_div_c;
- u8 pclk_div_a;
- u8 pclk_div_b;
- u8 pclk_div_c;
- u8 pclk_div_d;
- u8 vco_div_5_en;
- u32 fracdiv;
-};
struct post_pll_config {
unsigned long tmdsclock;
@@ -290,7 +278,7 @@ struct inno_hdmi_phy_drv_data {
const struct phy_config *phy_cfg_table;
};
-static const struct pre_pll_config pre_pll_cfg_table[] = {
+static const struct inno_hdmi_phy_pre_pll_config pre_pll_cfg_table[] = {
{ 25175000, 25175000, 3, 125, 3, 1, 1, 1, 3, 3, 4, 0, 0xe00000},
{ 25175000, 31468750, 1, 41, 0, 3, 3, 1, 3, 3, 4, 0, 0xf5554f},
{ 27000000, 27000000, 1, 36, 0, 3, 3, 1, 2, 3, 4, 0, 0x0},
@@ -673,20 +661,12 @@ static const struct phy_ops inno_hdmi_phy_ops = {
};
static const
-struct pre_pll_config *inno_hdmi_phy_get_pre_pll_cfg(struct inno_hdmi_phy *inno,
- unsigned long rate)
+struct inno_hdmi_phy_pre_pll_config *inno_hdmi_phy_get_pre_pll_cfg(struct inno_hdmi_phy *inno,
+ unsigned long rate)
{
- const struct pre_pll_config *cfg = pre_pll_cfg_table;
unsigned long tmdsclock = inno_hdmi_phy_get_tmdsclk(inno, rate);
- for (; cfg->pixclock != 0; cfg++)
- if (cfg->pixclock == rate && cfg->tmdsclock == tmdsclock)
- break;
-
- if (cfg->pixclock == 0)
- return ERR_PTR(-EINVAL);
-
- return cfg;
+ return inno_hdmi_phy_pre_pll_lookup(&inno->pre_pll, rate, tmdsclock);
}
static int inno_hdmi_phy_rk3228_clk_is_prepared(struct clk_hw *hw)
@@ -752,7 +732,7 @@ unsigned long inno_hdmi_phy_rk3228_clk_recalc_rate(struct clk_hw *hw,
static int inno_hdmi_phy_rk3228_clk_determine_rate(struct clk_hw *hw,
struct clk_rate_request *req)
{
- const struct pre_pll_config *cfg = pre_pll_cfg_table;
+ const struct inno_hdmi_phy_pre_pll_config *cfg = pre_pll_cfg_table;
req->rate = (req->rate / 1000) * 1000;
@@ -773,7 +753,7 @@ static int inno_hdmi_phy_rk3228_clk_set_rate(struct clk_hw *hw,
unsigned long parent_rate)
{
struct inno_hdmi_phy *inno = to_inno_hdmi_phy(hw);
- const struct pre_pll_config *cfg;
+ const struct inno_hdmi_phy_pre_pll_config *cfg;
unsigned long tmdsclock = inno_hdmi_phy_get_tmdsclk(inno, rate);
u32 v;
int ret;
@@ -870,39 +850,11 @@ unsigned long inno_hdmi_phy_rk3328_clk_recalc_rate(struct clk_hw *hw,
unsigned long parent_rate)
{
struct inno_hdmi_phy *inno = to_inno_hdmi_phy(hw);
- unsigned long frac;
- u8 nd, no_a, no_b, no_d;
- u64 vco;
- u16 nf;
-
- nd = inno_read(inno, 0xa1) & RK3328_PRE_PLL_PRE_DIV_MASK;
- nf = ((inno_read(inno, 0xa2) & RK3328_PRE_PLL_FB_DIV_11_8_MASK) << 8);
- nf |= inno_read(inno, 0xa3);
- vco = parent_rate * nf;
-
- if (!(inno_read(inno, 0xa2) & RK3328_PRE_PLL_FRAC_DIV_DISABLE)) {
- frac = inno_read(inno, 0xd3) |
- (inno_read(inno, 0xd2) << 8) |
- (inno_read(inno, 0xd1) << 16);
- vco += DIV_ROUND_CLOSEST(parent_rate * frac, (1 << 24));
- }
- if (inno_read(inno, 0xa0) & RK3328_PCLK_VCO_DIV_5_MASK) {
- do_div(vco, nd * 5);
- } else {
- no_a = inno_read(inno, 0xa5) & RK3328_PRE_PLL_PCLK_DIV_A_MASK;
- no_b = inno_read(inno, 0xa5) & RK3328_PRE_PLL_PCLK_DIV_B_MASK;
- no_b >>= RK3328_PRE_PLL_PCLK_DIV_B_SHIFT;
- no_b += 2;
- no_d = inno_read(inno, 0xa6) & RK3328_PRE_PLL_PCLK_DIV_D_MASK;
-
- do_div(vco, (nd * (no_a == 1 ? no_b : no_a) * no_d * 2));
- }
+ inno->pixclock = inno_hdmi_phy_pre_pll_recalc_rate(&inno->pre_pll,
+ parent_rate);
- inno->pixclock = DIV_ROUND_CLOSEST((unsigned long)vco, 1000) * 1000;
-
- dev_dbg(inno->dev, "%s rate %lu vco %llu\n",
- __func__, inno->pixclock, vco);
+ dev_dbg(inno->dev, "%s rate %lu\n", __func__, inno->pixclock);
return inno->pixclock;
}
@@ -910,20 +862,9 @@ unsigned long inno_hdmi_phy_rk3328_clk_recalc_rate(struct clk_hw *hw,
static int inno_hdmi_phy_rk3328_clk_determine_rate(struct clk_hw *hw,
struct clk_rate_request *req)
{
- const struct pre_pll_config *cfg = pre_pll_cfg_table;
-
- req->rate = (req->rate / 1000) * 1000;
-
- for (; cfg->pixclock != 0; cfg++)
- if (cfg->pixclock == req->rate)
- break;
-
- if (cfg->pixclock == 0)
- return -EINVAL;
-
- req->rate = cfg->pixclock;
+ struct inno_hdmi_phy *inno = to_inno_hdmi_phy(hw);
- return 0;
+ return inno_hdmi_phy_pre_pll_determine_rate(&inno->pre_pll, req);
}
static int inno_hdmi_phy_rk3328_clk_set_rate(struct clk_hw *hw,
@@ -931,9 +872,8 @@ static int inno_hdmi_phy_rk3328_clk_set_rate(struct clk_hw *hw,
unsigned long parent_rate)
{
struct inno_hdmi_phy *inno = to_inno_hdmi_phy(hw);
- const struct pre_pll_config *cfg;
+ const struct inno_hdmi_phy_pre_pll_config *cfg;
unsigned long tmdsclock = inno_hdmi_phy_get_tmdsclk(inno, rate);
- u32 val;
int ret;
dev_dbg(inno->dev, "%s rate %lu tmdsclk %lu\n",
@@ -946,35 +886,11 @@ static int inno_hdmi_phy_rk3328_clk_set_rate(struct clk_hw *hw,
if (IS_ERR(cfg))
return PTR_ERR(cfg);
- inno_update_bits(inno, 0xa0, RK3328_PRE_PLL_POWER_DOWN,
- RK3328_PRE_PLL_POWER_DOWN);
-
- /* Configure pre-pll */
- inno_update_bits(inno, 0xa0, RK3328_PCLK_VCO_DIV_5_MASK,
- RK3328_PCLK_VCO_DIV_5(cfg->vco_div_5_en));
- inno_write(inno, 0xa1, RK3328_PRE_PLL_PRE_DIV(cfg->prediv));
-
- val = RK3328_SPREAD_SPECTRUM_MOD_DISABLE;
- if (!cfg->fracdiv)
- val |= RK3328_PRE_PLL_FRAC_DIV_DISABLE;
- inno_write(inno, 0xa2, RK3328_PRE_PLL_FB_DIV_11_8(cfg->fbdiv) | val);
- inno_write(inno, 0xa3, RK3328_PRE_PLL_FB_DIV_7_0(cfg->fbdiv));
- inno_write(inno, 0xa5, RK3328_PRE_PLL_PCLK_DIV_A(cfg->pclk_div_a) |
- RK3328_PRE_PLL_PCLK_DIV_B(cfg->pclk_div_b));
- inno_write(inno, 0xa6, RK3328_PRE_PLL_PCLK_DIV_C(cfg->pclk_div_c) |
- RK3328_PRE_PLL_PCLK_DIV_D(cfg->pclk_div_d));
- inno_write(inno, 0xa4, RK3328_PRE_PLL_TMDSCLK_DIV_C(cfg->tmds_div_c) |
- RK3328_PRE_PLL_TMDSCLK_DIV_A(cfg->tmds_div_a) |
- RK3328_PRE_PLL_TMDSCLK_DIV_B(cfg->tmds_div_b));
- inno_write(inno, 0xd3, RK3328_PRE_PLL_FRAC_DIV_7_0(cfg->fracdiv));
- inno_write(inno, 0xd2, RK3328_PRE_PLL_FRAC_DIV_15_8(cfg->fracdiv));
- inno_write(inno, 0xd1, RK3328_PRE_PLL_FRAC_DIV_23_16(cfg->fracdiv));
+ inno_hdmi_phy_pre_pll_power_down(&inno->pre_pll, true);
+ inno_hdmi_phy_pre_pll_configure(&inno->pre_pll, cfg);
+ inno_hdmi_phy_pre_pll_power_down(&inno->pre_pll, false);
- inno_update_bits(inno, 0xa0, RK3328_PRE_PLL_POWER_DOWN, 0);
-
- /* Wait for Pre-PLL lock */
- ret = inno_poll(inno, 0xa9, val, val & RK3328_PRE_PLL_LOCK_STATUS,
- 1000, 10000);
+ ret = inno_hdmi_phy_pre_pll_wait_locked(&inno->pre_pll, 10000);
if (ret) {
dev_err(inno->dev, "Pre-PLL locking failed\n");
return ret;
@@ -1373,6 +1289,11 @@ static int inno_hdmi_phy_probe(struct platform_device *pdev)
if (IS_ERR(inno->regmap))
return PTR_ERR(inno->regmap);
+ /* The PHY block starts the register space on these SoCs. */
+ inno->pre_pll.regmap = inno->regmap;
+ inno->pre_pll.offset = 0;
+ inno->pre_pll.table = pre_pll_cfg_table;
+
/* only the newer rk3328 hdmiphy has an interrupt */
inno->irq = platform_get_irq(pdev, 0);
if (inno->irq > 0) {
--
2.34.1
^ permalink raw reply related [flat|nested] 116+ messages in thread
* [PATCH v2 12/15] phy: rockchip: inno-hdmi: Use the common Innosilicon PHY helpers
@ 2026-08-28 13:47 ` Michal Wilczynski
0 siblings, 0 replies; 116+ messages in thread
From: Michal Wilczynski @ 2026-08-28 13:47 UTC (permalink / raw)
To: Vinod Koul, Neil Armstrong, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Andrzej Hajda, Robert Foss, Laurent Pinchart,
Jonas Karlman, Jernej Skrabec, Luca Ceresoli, David Airlie,
Simona Vetter, Maarten Lankhorst, Maxime Ripard,
Thomas Zimmermann, Lee Jones, Andy Yan, Philipp Zabel,
Emil Renner Berthing, Hal Feng, Michael Turquette, Stephen Boyd,
Brian Masney, Heiko Stuebner, Conor Dooley, Paul Walmsley,
Palmer Dabbelt, Albert Ou, Alexandre Ghiti, Dominique Belhachemi
Cc: linux-phy, devicetree, linux-kernel, dri-devel, mfd, linux-clk,
linux-arm-kernel, linux-rockchip, linux-riscv, Icenowy Zheng,
Andy Yan, Marek Szyprowski, Maud Spierings, Graham Markall,
Michal Wilczynski
The RK3328 pre-PLL programming, its table lookup and its recalc_rate and
determine_rate implementations are the generic Innosilicon ones, so drop
the local copies and use the shared helpers instead.
The RK3228 pre-PLL sits at different register addresses, so it keeps its
own register level code and only shares the table lookup.
The register writes, their order and the values written are unchanged.
No functional change intended.
Signed-off-by: Michal Wilczynski <m.wilczynski@samsung.com>
---
drivers/phy/rockchip/Kconfig | 1 +
drivers/phy/rockchip/phy-rockchip-inno-hdmi.c | 127 +++++---------------------
2 files changed, 25 insertions(+), 103 deletions(-)
diff --git a/drivers/phy/rockchip/Kconfig b/drivers/phy/rockchip/Kconfig
index 14698571b607590dc0e7a29f3b39eb9a5d4e3d25..9732c5be87717dc3ddbea1c60080952336a07af9 100644
--- a/drivers/phy/rockchip/Kconfig
+++ b/drivers/phy/rockchip/Kconfig
@@ -34,6 +34,7 @@ config PHY_ROCKCHIP_INNO_HDMI
depends on COMMON_CLK
depends on HAS_IOMEM
select GENERIC_PHY
+ select PHY_INNO_HDMI
help
Enable this to support the Rockchip Innosilicon HDMI PHY.
diff --git a/drivers/phy/rockchip/phy-rockchip-inno-hdmi.c b/drivers/phy/rockchip/phy-rockchip-inno-hdmi.c
index 1483907413faa5ce1dc8614db05e6e929410404d..fae766607b0ea120b3adb36001387062f39a5c00 100644
--- a/drivers/phy/rockchip/phy-rockchip-inno-hdmi.c
+++ b/drivers/phy/rockchip/phy-rockchip-inno-hdmi.c
@@ -17,6 +17,7 @@
#include <linux/of.h>
#include <linux/platform_device.h>
#include <linux/regmap.h>
+#include <linux/phy/inno-hdmi-phy.h>
#include <linux/phy/phy.h>
#include <linux/slab.h>
@@ -240,6 +241,8 @@ struct inno_hdmi_phy {
const struct inno_hdmi_phy_drv_data *plat_data;
int chip_version;
+ struct inno_hdmi_phy_pre_pll pre_pll;
+
/* clk provider */
struct clk_hw hw;
struct clk *phyclk;
@@ -247,21 +250,6 @@ struct inno_hdmi_phy {
unsigned long tmdsclock;
};
-struct pre_pll_config {
- unsigned long pixclock;
- unsigned long tmdsclock;
- u8 prediv;
- u16 fbdiv;
- u8 tmds_div_a;
- u8 tmds_div_b;
- u8 tmds_div_c;
- u8 pclk_div_a;
- u8 pclk_div_b;
- u8 pclk_div_c;
- u8 pclk_div_d;
- u8 vco_div_5_en;
- u32 fracdiv;
-};
struct post_pll_config {
unsigned long tmdsclock;
@@ -290,7 +278,7 @@ struct inno_hdmi_phy_drv_data {
const struct phy_config *phy_cfg_table;
};
-static const struct pre_pll_config pre_pll_cfg_table[] = {
+static const struct inno_hdmi_phy_pre_pll_config pre_pll_cfg_table[] = {
{ 25175000, 25175000, 3, 125, 3, 1, 1, 1, 3, 3, 4, 0, 0xe00000},
{ 25175000, 31468750, 1, 41, 0, 3, 3, 1, 3, 3, 4, 0, 0xf5554f},
{ 27000000, 27000000, 1, 36, 0, 3, 3, 1, 2, 3, 4, 0, 0x0},
@@ -673,20 +661,12 @@ static const struct phy_ops inno_hdmi_phy_ops = {
};
static const
-struct pre_pll_config *inno_hdmi_phy_get_pre_pll_cfg(struct inno_hdmi_phy *inno,
- unsigned long rate)
+struct inno_hdmi_phy_pre_pll_config *inno_hdmi_phy_get_pre_pll_cfg(struct inno_hdmi_phy *inno,
+ unsigned long rate)
{
- const struct pre_pll_config *cfg = pre_pll_cfg_table;
unsigned long tmdsclock = inno_hdmi_phy_get_tmdsclk(inno, rate);
- for (; cfg->pixclock != 0; cfg++)
- if (cfg->pixclock == rate && cfg->tmdsclock == tmdsclock)
- break;
-
- if (cfg->pixclock == 0)
- return ERR_PTR(-EINVAL);
-
- return cfg;
+ return inno_hdmi_phy_pre_pll_lookup(&inno->pre_pll, rate, tmdsclock);
}
static int inno_hdmi_phy_rk3228_clk_is_prepared(struct clk_hw *hw)
@@ -752,7 +732,7 @@ unsigned long inno_hdmi_phy_rk3228_clk_recalc_rate(struct clk_hw *hw,
static int inno_hdmi_phy_rk3228_clk_determine_rate(struct clk_hw *hw,
struct clk_rate_request *req)
{
- const struct pre_pll_config *cfg = pre_pll_cfg_table;
+ const struct inno_hdmi_phy_pre_pll_config *cfg = pre_pll_cfg_table;
req->rate = (req->rate / 1000) * 1000;
@@ -773,7 +753,7 @@ static int inno_hdmi_phy_rk3228_clk_set_rate(struct clk_hw *hw,
unsigned long parent_rate)
{
struct inno_hdmi_phy *inno = to_inno_hdmi_phy(hw);
- const struct pre_pll_config *cfg;
+ const struct inno_hdmi_phy_pre_pll_config *cfg;
unsigned long tmdsclock = inno_hdmi_phy_get_tmdsclk(inno, rate);
u32 v;
int ret;
@@ -870,39 +850,11 @@ unsigned long inno_hdmi_phy_rk3328_clk_recalc_rate(struct clk_hw *hw,
unsigned long parent_rate)
{
struct inno_hdmi_phy *inno = to_inno_hdmi_phy(hw);
- unsigned long frac;
- u8 nd, no_a, no_b, no_d;
- u64 vco;
- u16 nf;
-
- nd = inno_read(inno, 0xa1) & RK3328_PRE_PLL_PRE_DIV_MASK;
- nf = ((inno_read(inno, 0xa2) & RK3328_PRE_PLL_FB_DIV_11_8_MASK) << 8);
- nf |= inno_read(inno, 0xa3);
- vco = parent_rate * nf;
-
- if (!(inno_read(inno, 0xa2) & RK3328_PRE_PLL_FRAC_DIV_DISABLE)) {
- frac = inno_read(inno, 0xd3) |
- (inno_read(inno, 0xd2) << 8) |
- (inno_read(inno, 0xd1) << 16);
- vco += DIV_ROUND_CLOSEST(parent_rate * frac, (1 << 24));
- }
- if (inno_read(inno, 0xa0) & RK3328_PCLK_VCO_DIV_5_MASK) {
- do_div(vco, nd * 5);
- } else {
- no_a = inno_read(inno, 0xa5) & RK3328_PRE_PLL_PCLK_DIV_A_MASK;
- no_b = inno_read(inno, 0xa5) & RK3328_PRE_PLL_PCLK_DIV_B_MASK;
- no_b >>= RK3328_PRE_PLL_PCLK_DIV_B_SHIFT;
- no_b += 2;
- no_d = inno_read(inno, 0xa6) & RK3328_PRE_PLL_PCLK_DIV_D_MASK;
-
- do_div(vco, (nd * (no_a == 1 ? no_b : no_a) * no_d * 2));
- }
+ inno->pixclock = inno_hdmi_phy_pre_pll_recalc_rate(&inno->pre_pll,
+ parent_rate);
- inno->pixclock = DIV_ROUND_CLOSEST((unsigned long)vco, 1000) * 1000;
-
- dev_dbg(inno->dev, "%s rate %lu vco %llu\n",
- __func__, inno->pixclock, vco);
+ dev_dbg(inno->dev, "%s rate %lu\n", __func__, inno->pixclock);
return inno->pixclock;
}
@@ -910,20 +862,9 @@ unsigned long inno_hdmi_phy_rk3328_clk_recalc_rate(struct clk_hw *hw,
static int inno_hdmi_phy_rk3328_clk_determine_rate(struct clk_hw *hw,
struct clk_rate_request *req)
{
- const struct pre_pll_config *cfg = pre_pll_cfg_table;
-
- req->rate = (req->rate / 1000) * 1000;
-
- for (; cfg->pixclock != 0; cfg++)
- if (cfg->pixclock == req->rate)
- break;
-
- if (cfg->pixclock == 0)
- return -EINVAL;
-
- req->rate = cfg->pixclock;
+ struct inno_hdmi_phy *inno = to_inno_hdmi_phy(hw);
- return 0;
+ return inno_hdmi_phy_pre_pll_determine_rate(&inno->pre_pll, req);
}
static int inno_hdmi_phy_rk3328_clk_set_rate(struct clk_hw *hw,
@@ -931,9 +872,8 @@ static int inno_hdmi_phy_rk3328_clk_set_rate(struct clk_hw *hw,
unsigned long parent_rate)
{
struct inno_hdmi_phy *inno = to_inno_hdmi_phy(hw);
- const struct pre_pll_config *cfg;
+ const struct inno_hdmi_phy_pre_pll_config *cfg;
unsigned long tmdsclock = inno_hdmi_phy_get_tmdsclk(inno, rate);
- u32 val;
int ret;
dev_dbg(inno->dev, "%s rate %lu tmdsclk %lu\n",
@@ -946,35 +886,11 @@ static int inno_hdmi_phy_rk3328_clk_set_rate(struct clk_hw *hw,
if (IS_ERR(cfg))
return PTR_ERR(cfg);
- inno_update_bits(inno, 0xa0, RK3328_PRE_PLL_POWER_DOWN,
- RK3328_PRE_PLL_POWER_DOWN);
-
- /* Configure pre-pll */
- inno_update_bits(inno, 0xa0, RK3328_PCLK_VCO_DIV_5_MASK,
- RK3328_PCLK_VCO_DIV_5(cfg->vco_div_5_en));
- inno_write(inno, 0xa1, RK3328_PRE_PLL_PRE_DIV(cfg->prediv));
-
- val = RK3328_SPREAD_SPECTRUM_MOD_DISABLE;
- if (!cfg->fracdiv)
- val |= RK3328_PRE_PLL_FRAC_DIV_DISABLE;
- inno_write(inno, 0xa2, RK3328_PRE_PLL_FB_DIV_11_8(cfg->fbdiv) | val);
- inno_write(inno, 0xa3, RK3328_PRE_PLL_FB_DIV_7_0(cfg->fbdiv));
- inno_write(inno, 0xa5, RK3328_PRE_PLL_PCLK_DIV_A(cfg->pclk_div_a) |
- RK3328_PRE_PLL_PCLK_DIV_B(cfg->pclk_div_b));
- inno_write(inno, 0xa6, RK3328_PRE_PLL_PCLK_DIV_C(cfg->pclk_div_c) |
- RK3328_PRE_PLL_PCLK_DIV_D(cfg->pclk_div_d));
- inno_write(inno, 0xa4, RK3328_PRE_PLL_TMDSCLK_DIV_C(cfg->tmds_div_c) |
- RK3328_PRE_PLL_TMDSCLK_DIV_A(cfg->tmds_div_a) |
- RK3328_PRE_PLL_TMDSCLK_DIV_B(cfg->tmds_div_b));
- inno_write(inno, 0xd3, RK3328_PRE_PLL_FRAC_DIV_7_0(cfg->fracdiv));
- inno_write(inno, 0xd2, RK3328_PRE_PLL_FRAC_DIV_15_8(cfg->fracdiv));
- inno_write(inno, 0xd1, RK3328_PRE_PLL_FRAC_DIV_23_16(cfg->fracdiv));
+ inno_hdmi_phy_pre_pll_power_down(&inno->pre_pll, true);
+ inno_hdmi_phy_pre_pll_configure(&inno->pre_pll, cfg);
+ inno_hdmi_phy_pre_pll_power_down(&inno->pre_pll, false);
- inno_update_bits(inno, 0xa0, RK3328_PRE_PLL_POWER_DOWN, 0);
-
- /* Wait for Pre-PLL lock */
- ret = inno_poll(inno, 0xa9, val, val & RK3328_PRE_PLL_LOCK_STATUS,
- 1000, 10000);
+ ret = inno_hdmi_phy_pre_pll_wait_locked(&inno->pre_pll, 10000);
if (ret) {
dev_err(inno->dev, "Pre-PLL locking failed\n");
return ret;
@@ -1373,6 +1289,11 @@ static int inno_hdmi_phy_probe(struct platform_device *pdev)
if (IS_ERR(inno->regmap))
return PTR_ERR(inno->regmap);
+ /* The PHY block starts the register space on these SoCs. */
+ inno->pre_pll.regmap = inno->regmap;
+ inno->pre_pll.offset = 0;
+ inno->pre_pll.table = pre_pll_cfg_table;
+
/* only the newer rk3328 hdmiphy has an interrupt */
inno->irq = platform_get_irq(pdev, 0);
if (inno->irq > 0) {
--
2.34.1
_______________________________________________
Linux-rockchip mailing list
Linux-rockchip@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-rockchip
^ permalink raw reply related [flat|nested] 116+ messages in thread
* [PATCH v2 12/15] phy: rockchip: inno-hdmi: Use the common Innosilicon PHY helpers
@ 2026-08-28 13:47 ` Michal Wilczynski
0 siblings, 0 replies; 116+ messages in thread
From: Michal Wilczynski @ 2026-08-28 13:47 UTC (permalink / raw)
To: Vinod Koul, Neil Armstrong, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Andrzej Hajda, Robert Foss, Laurent Pinchart,
Jonas Karlman, Jernej Skrabec, Luca Ceresoli, David Airlie,
Simona Vetter, Maarten Lankhorst, Maxime Ripard,
Thomas Zimmermann, Lee Jones, Andy Yan, Philipp Zabel,
Emil Renner Berthing, Hal Feng, Michael Turquette, Stephen Boyd,
Brian Masney, Heiko Stuebner, Conor Dooley, Paul Walmsley,
Palmer Dabbelt, Albert Ou, Alexandre Ghiti, Dominique Belhachemi
Cc: linux-phy, devicetree, linux-kernel, dri-devel, mfd, linux-clk,
linux-arm-kernel, linux-rockchip, linux-riscv, Icenowy Zheng,
Andy Yan, Marek Szyprowski, Maud Spierings, Graham Markall,
Michal Wilczynski
The RK3328 pre-PLL programming, its table lookup and its recalc_rate and
determine_rate implementations are the generic Innosilicon ones, so drop
the local copies and use the shared helpers instead.
The RK3228 pre-PLL sits at different register addresses, so it keeps its
own register level code and only shares the table lookup.
The register writes, their order and the values written are unchanged.
No functional change intended.
Signed-off-by: Michal Wilczynski <m.wilczynski@samsung.com>
---
drivers/phy/rockchip/Kconfig | 1 +
drivers/phy/rockchip/phy-rockchip-inno-hdmi.c | 127 +++++---------------------
2 files changed, 25 insertions(+), 103 deletions(-)
diff --git a/drivers/phy/rockchip/Kconfig b/drivers/phy/rockchip/Kconfig
index 14698571b607590dc0e7a29f3b39eb9a5d4e3d25..9732c5be87717dc3ddbea1c60080952336a07af9 100644
--- a/drivers/phy/rockchip/Kconfig
+++ b/drivers/phy/rockchip/Kconfig
@@ -34,6 +34,7 @@ config PHY_ROCKCHIP_INNO_HDMI
depends on COMMON_CLK
depends on HAS_IOMEM
select GENERIC_PHY
+ select PHY_INNO_HDMI
help
Enable this to support the Rockchip Innosilicon HDMI PHY.
diff --git a/drivers/phy/rockchip/phy-rockchip-inno-hdmi.c b/drivers/phy/rockchip/phy-rockchip-inno-hdmi.c
index 1483907413faa5ce1dc8614db05e6e929410404d..fae766607b0ea120b3adb36001387062f39a5c00 100644
--- a/drivers/phy/rockchip/phy-rockchip-inno-hdmi.c
+++ b/drivers/phy/rockchip/phy-rockchip-inno-hdmi.c
@@ -17,6 +17,7 @@
#include <linux/of.h>
#include <linux/platform_device.h>
#include <linux/regmap.h>
+#include <linux/phy/inno-hdmi-phy.h>
#include <linux/phy/phy.h>
#include <linux/slab.h>
@@ -240,6 +241,8 @@ struct inno_hdmi_phy {
const struct inno_hdmi_phy_drv_data *plat_data;
int chip_version;
+ struct inno_hdmi_phy_pre_pll pre_pll;
+
/* clk provider */
struct clk_hw hw;
struct clk *phyclk;
@@ -247,21 +250,6 @@ struct inno_hdmi_phy {
unsigned long tmdsclock;
};
-struct pre_pll_config {
- unsigned long pixclock;
- unsigned long tmdsclock;
- u8 prediv;
- u16 fbdiv;
- u8 tmds_div_a;
- u8 tmds_div_b;
- u8 tmds_div_c;
- u8 pclk_div_a;
- u8 pclk_div_b;
- u8 pclk_div_c;
- u8 pclk_div_d;
- u8 vco_div_5_en;
- u32 fracdiv;
-};
struct post_pll_config {
unsigned long tmdsclock;
@@ -290,7 +278,7 @@ struct inno_hdmi_phy_drv_data {
const struct phy_config *phy_cfg_table;
};
-static const struct pre_pll_config pre_pll_cfg_table[] = {
+static const struct inno_hdmi_phy_pre_pll_config pre_pll_cfg_table[] = {
{ 25175000, 25175000, 3, 125, 3, 1, 1, 1, 3, 3, 4, 0, 0xe00000},
{ 25175000, 31468750, 1, 41, 0, 3, 3, 1, 3, 3, 4, 0, 0xf5554f},
{ 27000000, 27000000, 1, 36, 0, 3, 3, 1, 2, 3, 4, 0, 0x0},
@@ -673,20 +661,12 @@ static const struct phy_ops inno_hdmi_phy_ops = {
};
static const
-struct pre_pll_config *inno_hdmi_phy_get_pre_pll_cfg(struct inno_hdmi_phy *inno,
- unsigned long rate)
+struct inno_hdmi_phy_pre_pll_config *inno_hdmi_phy_get_pre_pll_cfg(struct inno_hdmi_phy *inno,
+ unsigned long rate)
{
- const struct pre_pll_config *cfg = pre_pll_cfg_table;
unsigned long tmdsclock = inno_hdmi_phy_get_tmdsclk(inno, rate);
- for (; cfg->pixclock != 0; cfg++)
- if (cfg->pixclock == rate && cfg->tmdsclock == tmdsclock)
- break;
-
- if (cfg->pixclock == 0)
- return ERR_PTR(-EINVAL);
-
- return cfg;
+ return inno_hdmi_phy_pre_pll_lookup(&inno->pre_pll, rate, tmdsclock);
}
static int inno_hdmi_phy_rk3228_clk_is_prepared(struct clk_hw *hw)
@@ -752,7 +732,7 @@ unsigned long inno_hdmi_phy_rk3228_clk_recalc_rate(struct clk_hw *hw,
static int inno_hdmi_phy_rk3228_clk_determine_rate(struct clk_hw *hw,
struct clk_rate_request *req)
{
- const struct pre_pll_config *cfg = pre_pll_cfg_table;
+ const struct inno_hdmi_phy_pre_pll_config *cfg = pre_pll_cfg_table;
req->rate = (req->rate / 1000) * 1000;
@@ -773,7 +753,7 @@ static int inno_hdmi_phy_rk3228_clk_set_rate(struct clk_hw *hw,
unsigned long parent_rate)
{
struct inno_hdmi_phy *inno = to_inno_hdmi_phy(hw);
- const struct pre_pll_config *cfg;
+ const struct inno_hdmi_phy_pre_pll_config *cfg;
unsigned long tmdsclock = inno_hdmi_phy_get_tmdsclk(inno, rate);
u32 v;
int ret;
@@ -870,39 +850,11 @@ unsigned long inno_hdmi_phy_rk3328_clk_recalc_rate(struct clk_hw *hw,
unsigned long parent_rate)
{
struct inno_hdmi_phy *inno = to_inno_hdmi_phy(hw);
- unsigned long frac;
- u8 nd, no_a, no_b, no_d;
- u64 vco;
- u16 nf;
-
- nd = inno_read(inno, 0xa1) & RK3328_PRE_PLL_PRE_DIV_MASK;
- nf = ((inno_read(inno, 0xa2) & RK3328_PRE_PLL_FB_DIV_11_8_MASK) << 8);
- nf |= inno_read(inno, 0xa3);
- vco = parent_rate * nf;
-
- if (!(inno_read(inno, 0xa2) & RK3328_PRE_PLL_FRAC_DIV_DISABLE)) {
- frac = inno_read(inno, 0xd3) |
- (inno_read(inno, 0xd2) << 8) |
- (inno_read(inno, 0xd1) << 16);
- vco += DIV_ROUND_CLOSEST(parent_rate * frac, (1 << 24));
- }
- if (inno_read(inno, 0xa0) & RK3328_PCLK_VCO_DIV_5_MASK) {
- do_div(vco, nd * 5);
- } else {
- no_a = inno_read(inno, 0xa5) & RK3328_PRE_PLL_PCLK_DIV_A_MASK;
- no_b = inno_read(inno, 0xa5) & RK3328_PRE_PLL_PCLK_DIV_B_MASK;
- no_b >>= RK3328_PRE_PLL_PCLK_DIV_B_SHIFT;
- no_b += 2;
- no_d = inno_read(inno, 0xa6) & RK3328_PRE_PLL_PCLK_DIV_D_MASK;
-
- do_div(vco, (nd * (no_a == 1 ? no_b : no_a) * no_d * 2));
- }
+ inno->pixclock = inno_hdmi_phy_pre_pll_recalc_rate(&inno->pre_pll,
+ parent_rate);
- inno->pixclock = DIV_ROUND_CLOSEST((unsigned long)vco, 1000) * 1000;
-
- dev_dbg(inno->dev, "%s rate %lu vco %llu\n",
- __func__, inno->pixclock, vco);
+ dev_dbg(inno->dev, "%s rate %lu\n", __func__, inno->pixclock);
return inno->pixclock;
}
@@ -910,20 +862,9 @@ unsigned long inno_hdmi_phy_rk3328_clk_recalc_rate(struct clk_hw *hw,
static int inno_hdmi_phy_rk3328_clk_determine_rate(struct clk_hw *hw,
struct clk_rate_request *req)
{
- const struct pre_pll_config *cfg = pre_pll_cfg_table;
-
- req->rate = (req->rate / 1000) * 1000;
-
- for (; cfg->pixclock != 0; cfg++)
- if (cfg->pixclock == req->rate)
- break;
-
- if (cfg->pixclock == 0)
- return -EINVAL;
-
- req->rate = cfg->pixclock;
+ struct inno_hdmi_phy *inno = to_inno_hdmi_phy(hw);
- return 0;
+ return inno_hdmi_phy_pre_pll_determine_rate(&inno->pre_pll, req);
}
static int inno_hdmi_phy_rk3328_clk_set_rate(struct clk_hw *hw,
@@ -931,9 +872,8 @@ static int inno_hdmi_phy_rk3328_clk_set_rate(struct clk_hw *hw,
unsigned long parent_rate)
{
struct inno_hdmi_phy *inno = to_inno_hdmi_phy(hw);
- const struct pre_pll_config *cfg;
+ const struct inno_hdmi_phy_pre_pll_config *cfg;
unsigned long tmdsclock = inno_hdmi_phy_get_tmdsclk(inno, rate);
- u32 val;
int ret;
dev_dbg(inno->dev, "%s rate %lu tmdsclk %lu\n",
@@ -946,35 +886,11 @@ static int inno_hdmi_phy_rk3328_clk_set_rate(struct clk_hw *hw,
if (IS_ERR(cfg))
return PTR_ERR(cfg);
- inno_update_bits(inno, 0xa0, RK3328_PRE_PLL_POWER_DOWN,
- RK3328_PRE_PLL_POWER_DOWN);
-
- /* Configure pre-pll */
- inno_update_bits(inno, 0xa0, RK3328_PCLK_VCO_DIV_5_MASK,
- RK3328_PCLK_VCO_DIV_5(cfg->vco_div_5_en));
- inno_write(inno, 0xa1, RK3328_PRE_PLL_PRE_DIV(cfg->prediv));
-
- val = RK3328_SPREAD_SPECTRUM_MOD_DISABLE;
- if (!cfg->fracdiv)
- val |= RK3328_PRE_PLL_FRAC_DIV_DISABLE;
- inno_write(inno, 0xa2, RK3328_PRE_PLL_FB_DIV_11_8(cfg->fbdiv) | val);
- inno_write(inno, 0xa3, RK3328_PRE_PLL_FB_DIV_7_0(cfg->fbdiv));
- inno_write(inno, 0xa5, RK3328_PRE_PLL_PCLK_DIV_A(cfg->pclk_div_a) |
- RK3328_PRE_PLL_PCLK_DIV_B(cfg->pclk_div_b));
- inno_write(inno, 0xa6, RK3328_PRE_PLL_PCLK_DIV_C(cfg->pclk_div_c) |
- RK3328_PRE_PLL_PCLK_DIV_D(cfg->pclk_div_d));
- inno_write(inno, 0xa4, RK3328_PRE_PLL_TMDSCLK_DIV_C(cfg->tmds_div_c) |
- RK3328_PRE_PLL_TMDSCLK_DIV_A(cfg->tmds_div_a) |
- RK3328_PRE_PLL_TMDSCLK_DIV_B(cfg->tmds_div_b));
- inno_write(inno, 0xd3, RK3328_PRE_PLL_FRAC_DIV_7_0(cfg->fracdiv));
- inno_write(inno, 0xd2, RK3328_PRE_PLL_FRAC_DIV_15_8(cfg->fracdiv));
- inno_write(inno, 0xd1, RK3328_PRE_PLL_FRAC_DIV_23_16(cfg->fracdiv));
+ inno_hdmi_phy_pre_pll_power_down(&inno->pre_pll, true);
+ inno_hdmi_phy_pre_pll_configure(&inno->pre_pll, cfg);
+ inno_hdmi_phy_pre_pll_power_down(&inno->pre_pll, false);
- inno_update_bits(inno, 0xa0, RK3328_PRE_PLL_POWER_DOWN, 0);
-
- /* Wait for Pre-PLL lock */
- ret = inno_poll(inno, 0xa9, val, val & RK3328_PRE_PLL_LOCK_STATUS,
- 1000, 10000);
+ ret = inno_hdmi_phy_pre_pll_wait_locked(&inno->pre_pll, 10000);
if (ret) {
dev_err(inno->dev, "Pre-PLL locking failed\n");
return ret;
@@ -1373,6 +1289,11 @@ static int inno_hdmi_phy_probe(struct platform_device *pdev)
if (IS_ERR(inno->regmap))
return PTR_ERR(inno->regmap);
+ /* The PHY block starts the register space on these SoCs. */
+ inno->pre_pll.regmap = inno->regmap;
+ inno->pre_pll.offset = 0;
+ inno->pre_pll.table = pre_pll_cfg_table;
+
/* only the newer rk3328 hdmiphy has an interrupt */
inno->irq = platform_get_irq(pdev, 0);
if (inno->irq > 0) {
--
2.34.1
--
linux-phy mailing list
linux-phy@lists.infradead.org
https://lists.infradead.org/mailman/listinfo/linux-phy
^ permalink raw reply related [flat|nested] 116+ messages in thread
* [PATCH v2 12/15] phy: rockchip: inno-hdmi: Use the common Innosilicon PHY helpers
@ 2026-08-28 13:47 ` Michal Wilczynski
0 siblings, 0 replies; 116+ messages in thread
From: Michal Wilczynski @ 2026-08-28 13:47 UTC (permalink / raw)
To: Vinod Koul, Neil Armstrong, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Andrzej Hajda, Robert Foss, Laurent Pinchart,
Jonas Karlman, Jernej Skrabec, Luca Ceresoli, David Airlie,
Simona Vetter, Maarten Lankhorst, Maxime Ripard,
Thomas Zimmermann, Lee Jones, Andy Yan, Philipp Zabel,
Emil Renner Berthing, Hal Feng, Michael Turquette, Stephen Boyd,
Brian Masney, Heiko Stuebner, Conor Dooley, Paul Walmsley,
Palmer Dabbelt, Albert Ou, Alexandre Ghiti, Dominique Belhachemi
Cc: devicetree, mfd, linux-kernel, dri-devel, Andy Yan,
Graham Markall, linux-rockchip, linux-phy, Michal Wilczynski,
linux-riscv, Maud Spierings, linux-clk, linux-arm-kernel,
Marek Szyprowski
The RK3328 pre-PLL programming, its table lookup and its recalc_rate and
determine_rate implementations are the generic Innosilicon ones, so drop
the local copies and use the shared helpers instead.
The RK3228 pre-PLL sits at different register addresses, so it keeps its
own register level code and only shares the table lookup.
The register writes, their order and the values written are unchanged.
No functional change intended.
Signed-off-by: Michal Wilczynski <m.wilczynski@samsung.com>
---
drivers/phy/rockchip/Kconfig | 1 +
drivers/phy/rockchip/phy-rockchip-inno-hdmi.c | 127 +++++---------------------
2 files changed, 25 insertions(+), 103 deletions(-)
diff --git a/drivers/phy/rockchip/Kconfig b/drivers/phy/rockchip/Kconfig
index 14698571b607590dc0e7a29f3b39eb9a5d4e3d25..9732c5be87717dc3ddbea1c60080952336a07af9 100644
--- a/drivers/phy/rockchip/Kconfig
+++ b/drivers/phy/rockchip/Kconfig
@@ -34,6 +34,7 @@ config PHY_ROCKCHIP_INNO_HDMI
depends on COMMON_CLK
depends on HAS_IOMEM
select GENERIC_PHY
+ select PHY_INNO_HDMI
help
Enable this to support the Rockchip Innosilicon HDMI PHY.
diff --git a/drivers/phy/rockchip/phy-rockchip-inno-hdmi.c b/drivers/phy/rockchip/phy-rockchip-inno-hdmi.c
index 1483907413faa5ce1dc8614db05e6e929410404d..fae766607b0ea120b3adb36001387062f39a5c00 100644
--- a/drivers/phy/rockchip/phy-rockchip-inno-hdmi.c
+++ b/drivers/phy/rockchip/phy-rockchip-inno-hdmi.c
@@ -17,6 +17,7 @@
#include <linux/of.h>
#include <linux/platform_device.h>
#include <linux/regmap.h>
+#include <linux/phy/inno-hdmi-phy.h>
#include <linux/phy/phy.h>
#include <linux/slab.h>
@@ -240,6 +241,8 @@ struct inno_hdmi_phy {
const struct inno_hdmi_phy_drv_data *plat_data;
int chip_version;
+ struct inno_hdmi_phy_pre_pll pre_pll;
+
/* clk provider */
struct clk_hw hw;
struct clk *phyclk;
@@ -247,21 +250,6 @@ struct inno_hdmi_phy {
unsigned long tmdsclock;
};
-struct pre_pll_config {
- unsigned long pixclock;
- unsigned long tmdsclock;
- u8 prediv;
- u16 fbdiv;
- u8 tmds_div_a;
- u8 tmds_div_b;
- u8 tmds_div_c;
- u8 pclk_div_a;
- u8 pclk_div_b;
- u8 pclk_div_c;
- u8 pclk_div_d;
- u8 vco_div_5_en;
- u32 fracdiv;
-};
struct post_pll_config {
unsigned long tmdsclock;
@@ -290,7 +278,7 @@ struct inno_hdmi_phy_drv_data {
const struct phy_config *phy_cfg_table;
};
-static const struct pre_pll_config pre_pll_cfg_table[] = {
+static const struct inno_hdmi_phy_pre_pll_config pre_pll_cfg_table[] = {
{ 25175000, 25175000, 3, 125, 3, 1, 1, 1, 3, 3, 4, 0, 0xe00000},
{ 25175000, 31468750, 1, 41, 0, 3, 3, 1, 3, 3, 4, 0, 0xf5554f},
{ 27000000, 27000000, 1, 36, 0, 3, 3, 1, 2, 3, 4, 0, 0x0},
@@ -673,20 +661,12 @@ static const struct phy_ops inno_hdmi_phy_ops = {
};
static const
-struct pre_pll_config *inno_hdmi_phy_get_pre_pll_cfg(struct inno_hdmi_phy *inno,
- unsigned long rate)
+struct inno_hdmi_phy_pre_pll_config *inno_hdmi_phy_get_pre_pll_cfg(struct inno_hdmi_phy *inno,
+ unsigned long rate)
{
- const struct pre_pll_config *cfg = pre_pll_cfg_table;
unsigned long tmdsclock = inno_hdmi_phy_get_tmdsclk(inno, rate);
- for (; cfg->pixclock != 0; cfg++)
- if (cfg->pixclock == rate && cfg->tmdsclock == tmdsclock)
- break;
-
- if (cfg->pixclock == 0)
- return ERR_PTR(-EINVAL);
-
- return cfg;
+ return inno_hdmi_phy_pre_pll_lookup(&inno->pre_pll, rate, tmdsclock);
}
static int inno_hdmi_phy_rk3228_clk_is_prepared(struct clk_hw *hw)
@@ -752,7 +732,7 @@ unsigned long inno_hdmi_phy_rk3228_clk_recalc_rate(struct clk_hw *hw,
static int inno_hdmi_phy_rk3228_clk_determine_rate(struct clk_hw *hw,
struct clk_rate_request *req)
{
- const struct pre_pll_config *cfg = pre_pll_cfg_table;
+ const struct inno_hdmi_phy_pre_pll_config *cfg = pre_pll_cfg_table;
req->rate = (req->rate / 1000) * 1000;
@@ -773,7 +753,7 @@ static int inno_hdmi_phy_rk3228_clk_set_rate(struct clk_hw *hw,
unsigned long parent_rate)
{
struct inno_hdmi_phy *inno = to_inno_hdmi_phy(hw);
- const struct pre_pll_config *cfg;
+ const struct inno_hdmi_phy_pre_pll_config *cfg;
unsigned long tmdsclock = inno_hdmi_phy_get_tmdsclk(inno, rate);
u32 v;
int ret;
@@ -870,39 +850,11 @@ unsigned long inno_hdmi_phy_rk3328_clk_recalc_rate(struct clk_hw *hw,
unsigned long parent_rate)
{
struct inno_hdmi_phy *inno = to_inno_hdmi_phy(hw);
- unsigned long frac;
- u8 nd, no_a, no_b, no_d;
- u64 vco;
- u16 nf;
-
- nd = inno_read(inno, 0xa1) & RK3328_PRE_PLL_PRE_DIV_MASK;
- nf = ((inno_read(inno, 0xa2) & RK3328_PRE_PLL_FB_DIV_11_8_MASK) << 8);
- nf |= inno_read(inno, 0xa3);
- vco = parent_rate * nf;
-
- if (!(inno_read(inno, 0xa2) & RK3328_PRE_PLL_FRAC_DIV_DISABLE)) {
- frac = inno_read(inno, 0xd3) |
- (inno_read(inno, 0xd2) << 8) |
- (inno_read(inno, 0xd1) << 16);
- vco += DIV_ROUND_CLOSEST(parent_rate * frac, (1 << 24));
- }
- if (inno_read(inno, 0xa0) & RK3328_PCLK_VCO_DIV_5_MASK) {
- do_div(vco, nd * 5);
- } else {
- no_a = inno_read(inno, 0xa5) & RK3328_PRE_PLL_PCLK_DIV_A_MASK;
- no_b = inno_read(inno, 0xa5) & RK3328_PRE_PLL_PCLK_DIV_B_MASK;
- no_b >>= RK3328_PRE_PLL_PCLK_DIV_B_SHIFT;
- no_b += 2;
- no_d = inno_read(inno, 0xa6) & RK3328_PRE_PLL_PCLK_DIV_D_MASK;
-
- do_div(vco, (nd * (no_a == 1 ? no_b : no_a) * no_d * 2));
- }
+ inno->pixclock = inno_hdmi_phy_pre_pll_recalc_rate(&inno->pre_pll,
+ parent_rate);
- inno->pixclock = DIV_ROUND_CLOSEST((unsigned long)vco, 1000) * 1000;
-
- dev_dbg(inno->dev, "%s rate %lu vco %llu\n",
- __func__, inno->pixclock, vco);
+ dev_dbg(inno->dev, "%s rate %lu\n", __func__, inno->pixclock);
return inno->pixclock;
}
@@ -910,20 +862,9 @@ unsigned long inno_hdmi_phy_rk3328_clk_recalc_rate(struct clk_hw *hw,
static int inno_hdmi_phy_rk3328_clk_determine_rate(struct clk_hw *hw,
struct clk_rate_request *req)
{
- const struct pre_pll_config *cfg = pre_pll_cfg_table;
-
- req->rate = (req->rate / 1000) * 1000;
-
- for (; cfg->pixclock != 0; cfg++)
- if (cfg->pixclock == req->rate)
- break;
-
- if (cfg->pixclock == 0)
- return -EINVAL;
-
- req->rate = cfg->pixclock;
+ struct inno_hdmi_phy *inno = to_inno_hdmi_phy(hw);
- return 0;
+ return inno_hdmi_phy_pre_pll_determine_rate(&inno->pre_pll, req);
}
static int inno_hdmi_phy_rk3328_clk_set_rate(struct clk_hw *hw,
@@ -931,9 +872,8 @@ static int inno_hdmi_phy_rk3328_clk_set_rate(struct clk_hw *hw,
unsigned long parent_rate)
{
struct inno_hdmi_phy *inno = to_inno_hdmi_phy(hw);
- const struct pre_pll_config *cfg;
+ const struct inno_hdmi_phy_pre_pll_config *cfg;
unsigned long tmdsclock = inno_hdmi_phy_get_tmdsclk(inno, rate);
- u32 val;
int ret;
dev_dbg(inno->dev, "%s rate %lu tmdsclk %lu\n",
@@ -946,35 +886,11 @@ static int inno_hdmi_phy_rk3328_clk_set_rate(struct clk_hw *hw,
if (IS_ERR(cfg))
return PTR_ERR(cfg);
- inno_update_bits(inno, 0xa0, RK3328_PRE_PLL_POWER_DOWN,
- RK3328_PRE_PLL_POWER_DOWN);
-
- /* Configure pre-pll */
- inno_update_bits(inno, 0xa0, RK3328_PCLK_VCO_DIV_5_MASK,
- RK3328_PCLK_VCO_DIV_5(cfg->vco_div_5_en));
- inno_write(inno, 0xa1, RK3328_PRE_PLL_PRE_DIV(cfg->prediv));
-
- val = RK3328_SPREAD_SPECTRUM_MOD_DISABLE;
- if (!cfg->fracdiv)
- val |= RK3328_PRE_PLL_FRAC_DIV_DISABLE;
- inno_write(inno, 0xa2, RK3328_PRE_PLL_FB_DIV_11_8(cfg->fbdiv) | val);
- inno_write(inno, 0xa3, RK3328_PRE_PLL_FB_DIV_7_0(cfg->fbdiv));
- inno_write(inno, 0xa5, RK3328_PRE_PLL_PCLK_DIV_A(cfg->pclk_div_a) |
- RK3328_PRE_PLL_PCLK_DIV_B(cfg->pclk_div_b));
- inno_write(inno, 0xa6, RK3328_PRE_PLL_PCLK_DIV_C(cfg->pclk_div_c) |
- RK3328_PRE_PLL_PCLK_DIV_D(cfg->pclk_div_d));
- inno_write(inno, 0xa4, RK3328_PRE_PLL_TMDSCLK_DIV_C(cfg->tmds_div_c) |
- RK3328_PRE_PLL_TMDSCLK_DIV_A(cfg->tmds_div_a) |
- RK3328_PRE_PLL_TMDSCLK_DIV_B(cfg->tmds_div_b));
- inno_write(inno, 0xd3, RK3328_PRE_PLL_FRAC_DIV_7_0(cfg->fracdiv));
- inno_write(inno, 0xd2, RK3328_PRE_PLL_FRAC_DIV_15_8(cfg->fracdiv));
- inno_write(inno, 0xd1, RK3328_PRE_PLL_FRAC_DIV_23_16(cfg->fracdiv));
+ inno_hdmi_phy_pre_pll_power_down(&inno->pre_pll, true);
+ inno_hdmi_phy_pre_pll_configure(&inno->pre_pll, cfg);
+ inno_hdmi_phy_pre_pll_power_down(&inno->pre_pll, false);
- inno_update_bits(inno, 0xa0, RK3328_PRE_PLL_POWER_DOWN, 0);
-
- /* Wait for Pre-PLL lock */
- ret = inno_poll(inno, 0xa9, val, val & RK3328_PRE_PLL_LOCK_STATUS,
- 1000, 10000);
+ ret = inno_hdmi_phy_pre_pll_wait_locked(&inno->pre_pll, 10000);
if (ret) {
dev_err(inno->dev, "Pre-PLL locking failed\n");
return ret;
@@ -1373,6 +1289,11 @@ static int inno_hdmi_phy_probe(struct platform_device *pdev)
if (IS_ERR(inno->regmap))
return PTR_ERR(inno->regmap);
+ /* The PHY block starts the register space on these SoCs. */
+ inno->pre_pll.regmap = inno->regmap;
+ inno->pre_pll.offset = 0;
+ inno->pre_pll.table = pre_pll_cfg_table;
+
/* only the newer rk3328 hdmiphy has an interrupt */
inno->irq = platform_get_irq(pdev, 0);
if (inno->irq > 0) {
--
2.34.1
_______________________________________________
linux-riscv mailing list
linux-riscv@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-riscv
^ permalink raw reply related [flat|nested] 116+ messages in thread
* [PATCH v2 13/15] phy: starfive: Add jh7110-inno-hdmi-phy driver
2026-08-28 13:47 ` Michal Wilczynski
(?)
(?)
@ 2026-08-28 13:47 ` Michal Wilczynski
-1 siblings, 0 replies; 116+ messages in thread
From: Michal Wilczynski @ 2026-08-28 13:47 UTC (permalink / raw)
To: Vinod Koul, Neil Armstrong, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Andrzej Hajda, Robert Foss, Laurent Pinchart,
Jonas Karlman, Jernej Skrabec, Luca Ceresoli, David Airlie,
Simona Vetter, Maarten Lankhorst, Maxime Ripard,
Thomas Zimmermann, Lee Jones, Andy Yan, Philipp Zabel,
Emil Renner Berthing, Hal Feng, Michael Turquette, Stephen Boyd,
Brian Masney, Heiko Stuebner, Conor Dooley, Paul Walmsley,
Palmer Dabbelt, Albert Ou, Alexandre Ghiti, Dominique Belhachemi
Cc: linux-phy, devicetree, linux-kernel, dri-devel, mfd, linux-clk,
linux-arm-kernel, linux-rockchip, linux-riscv, Icenowy Zheng,
Andy Yan, Marek Szyprowski, Maud Spierings, Graham Markall,
Michal Wilczynski
Add the HDMI PHY driver for the StarFive JH7110.
This driver binds to the starfive,jh7110-inno-hdmi-phy node and
gets its regmap from the parent. It has no dependencies on voutcrg, only
on its refoclk (xin24m), which breaks the probe-time circular
dependency.
This driver provides two main functions:
- Clock Provider: It registers clk_ops to provide the variable pixel
clock (hdmi_pclk). The .set_rate operation configures the Pre-PLL
registers (0x1a0+) based on the requested rate.
- PHY Provider: It registers phy_ops for the controller. The .power_on
op configures and enables the Post-PLL and other analog blocks (BIAS,
LDO, Serializer, etc.).
The JH7110 instantiates the same Innosilicon IP as the Rockchip RK3328,
with the PHY register block shifted by 0x100 because it sits behind the
HDMI controller in the shared register space. The pre-PLL programming
therefore comes from the common Innosilicon helpers; this driver adds
the JH7110 pixel clock table, the post-PLL and the analog configuration.
Co-developed-by: Dominique Belhachemi <db@domibel.de>
Signed-off-by: Dominique Belhachemi <db@domibel.de>
Signed-off-by: Michal Wilczynski <m.wilczynski@samsung.com>
---
drivers/phy/starfive/Kconfig | 20 +
drivers/phy/starfive/Makefile | 1 +
drivers/phy/starfive/phy-jh7110-inno-hdmi.c | 567 ++++++++++++++++++++++++++++
3 files changed, 588 insertions(+)
diff --git a/drivers/phy/starfive/Kconfig b/drivers/phy/starfive/Kconfig
index d0cdd7cb4a13de22ff643c89a79d99cce57284d7..1da417ffbf224c13224e42a3ce322e3d0c272824 100644
--- a/drivers/phy/starfive/Kconfig
+++ b/drivers/phy/starfive/Kconfig
@@ -25,6 +25,26 @@ config PHY_STARFIVE_JH7110_DPHY_TX
system. If M is selected, the module will be called
phy-jh7110-dphy-tx.ko.
+config PHY_STARFIVE_JH7110_INNO_HDMI
+ tristate "Starfive JH7110 INNO HDMI PHY"
+ select PHY_INNO_HDMI
+ depends on COMMON_CLK
+ select GENERIC_PHY
+ help
+ This option enables the driver for the analog HDMI PHY (Physical
+ Layer) on the StarFive JH7110 SoC.
+
+ This driver binds to a child node of the 'starfive,jh7110-hdmi-subsystem'
+ parent driver and gets its register map from that parent.
+
+ It is responsible for two main functions:
+ 1. PHY Provider: It provides standard PHY operations (.power_on,
+ .power_off) for the HDMI controller (bridge) driver. This
+ involves configuring the Post-PLL and analog TMDS blocks.
+ 2. Clock Provider: It registers as a clock provider to supply the
+ variable pixel clock (hdmi_pclk) to the HDMI controller and
+ the VOUT subsystem, which it generates using the Pre-PLL.
+
config PHY_STARFIVE_JH7110_PCIE
tristate "Starfive JH7110 PCIE 2.0/USB 3.0 PHY support"
depends on HAS_IOMEM
diff --git a/drivers/phy/starfive/Makefile b/drivers/phy/starfive/Makefile
index eedc4a6fec156320c99ac0a0da609083b6a6a695..e7b13f00880b500f933f21b6037384d5c6884e3e 100644
--- a/drivers/phy/starfive/Makefile
+++ b/drivers/phy/starfive/Makefile
@@ -1,5 +1,6 @@
# SPDX-License-Identifier: GPL-2.0
obj-$(CONFIG_PHY_STARFIVE_JH7110_DPHY_RX) += phy-jh7110-dphy-rx.o
obj-$(CONFIG_PHY_STARFIVE_JH7110_DPHY_TX) += phy-jh7110-dphy-tx.o
+obj-$(CONFIG_PHY_STARFIVE_JH7110_INNO_HDMI) += phy-jh7110-inno-hdmi.o
obj-$(CONFIG_PHY_STARFIVE_JH7110_PCIE) += phy-jh7110-pcie.o
obj-$(CONFIG_PHY_STARFIVE_JH7110_USB) += phy-jh7110-usb.o
diff --git a/drivers/phy/starfive/phy-jh7110-inno-hdmi.c b/drivers/phy/starfive/phy-jh7110-inno-hdmi.c
new file mode 100644
index 0000000000000000000000000000000000000000..f4c4d76a38754d5edd4d80895481560c9650f3e7
--- /dev/null
+++ b/drivers/phy/starfive/phy-jh7110-inno-hdmi.c
@@ -0,0 +1,567 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (c) 2017 Rockchip Electronics Co. Ltd.
+ * Copyright (c) 2025 Samsung Electronics Co., Ltd.
+ *
+ * Author: Zheng Yang <zhengyang@rock-chips.com>
+ * Author: Michal Wilczynski <m.wilczynski@samsung.com>
+ *
+ * The register layout and programming sequence derive from
+ * drivers/phy/rockchip/phy-rockchip-inno-hdmi.c; the JH7110 places the
+ * same Innosilicon PHY block at a 0x100 register offset.
+ *
+ * This driver handles the PHY portion of the StarFive Innosilicon HDMI IP,
+ * which is part of a monolithic HDMI block. It provides the variable pixel
+ * clock (from the Pre-PLL) and the PHY operations (for the Post-PLL/analog).
+ */
+
+#include <linux/bitfield.h>
+#include <linux/bits.h>
+#include <linux/clk.h>
+#include <linux/clk-provider.h>
+#include <linux/delay.h>
+#include <linux/io.h>
+#include <linux/iopoll.h>
+#include <linux/math64.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
+#include <linux/regmap.h>
+#include <linux/phy/inno-hdmi-phy.h>
+#include <linux/phy/phy.h>
+#include <linux/slab.h>
+
+/*
+ * StarFive (JH7110) Innosilicon HDMI PHY Register Definitions
+ */
+
+/* REG: 0x1aa */
+#define STF_INNO_POST_PLL_DIV_1 0x1aa
+#define STF_INNO_POST_PLL_POST_DIV_ENABLE GENMASK(3, 2)
+#define STF_INNO_POST_PLL_REFCLK_SEL_TMDS BIT(1)
+#define STF_INNO_POST_PLL_POWER_DOWN BIT(0)
+
+/* REG: 0x1ab */
+#define STF_INNO_POST_PLL_DIV_2 0x1ab
+#define STF_INNO_POST_PLL_PRE_DIV(x) FIELD_PREP(GENMASK(5, 0), x)
+#define STF_INNO_POST_PLL_FB_DIV_8(x) FIELD_PREP(BIT(7), (x) >> 8)
+
+/* REG: 0x1ac */
+#define STF_INNO_POST_PLL_DIV_3 0x1ac
+#define STF_INNO_POST_PLL_FB_DIV_7_0(x) FIELD_PREP(GENMASK(7, 0), x)
+
+/* REG: 0x1ad */
+#define STF_INNO_POST_PLL_DIV_4 0x1ad
+#define STF_INNO_POST_PLL_POST_DIV_MASK GENMASK(1, 0)
+
+/* REG: 0x1af */
+#define STF_INNO_POST_PLL_LOCK_STATUS 0x1af
+#define STF_INNO_POST_PLL_LOCK BIT(0)
+
+/* REG: 0x1b0 */
+#define STF_INNO_BIAS_CONTROL 0x1b0
+#define STF_INNO_BIAS_ENABLE BIT(2)
+
+/* REG: 0x1b2 */
+#define STF_INNO_TMDS_CONTROL 0x1b2
+#define STF_INNO_TMDS_CLK_DRIVER_EN BIT(3)
+#define STF_INNO_TMDS_D2_DRIVER_EN BIT(2)
+#define STF_INNO_TMDS_D1_DRIVER_EN BIT(1)
+#define STF_INNO_TMDS_D0_DRIVER_EN BIT(0)
+#define STF_INNO_TMDS_DRIVER_ENABLE (STF_INNO_TMDS_CLK_DRIVER_EN | \
+ STF_INNO_TMDS_D2_DRIVER_EN | \
+ STF_INNO_TMDS_D1_DRIVER_EN | \
+ STF_INNO_TMDS_D0_DRIVER_EN)
+
+/* REG: 0x1b4 */
+#define STF_INNO_LDO_CONTROL 0x1b4
+#define STF_INNO_LDO_ENABLE (BIT(2) | BIT(1) | BIT(0))
+
+/* REG: 0x1be */
+#define STF_INNO_SERIALIER_CONTROL 0x1be
+#define STF_INNO_SERIALIER_ENABLE (BIT(6) | BIT(5) | BIT(4) | BIT(0))
+
+/* REG: 0x1cc */
+#define STF_INNO_RX_CONTROL 0x1cc
+#define STF_INNO_RX_ENABLE (BIT(3) | BIT(2) | BIT(1) | BIT(0))
+
+/*
+ * These tables are copied from the monolithic driver.
+ * They match the Rockchip PHY driver tables.
+ */
+
+struct post_pll_config {
+ unsigned long tmdsclock;
+ u8 prediv;
+ u16 fbdiv;
+ u8 postdiv;
+ u8 post_div_en;
+};
+
+static const struct inno_hdmi_phy_pre_pll_config pre_pll_cfg_table[] = {
+ { 25175000, 25175000, 1, 100, 2, 3, 3, 12, 3, 3, 4, 0, 0xF55555 },
+ { 25200000, 25200000, 1, 100, 2, 3, 3, 12, 3, 3, 4, 0, 0 },
+ { 27000000, 27000000, 1, 90, 3, 2, 2, 10, 3, 3, 4, 0, 0 },
+ { 27027000, 27027000, 1, 90, 3, 2, 2, 10, 3, 3, 4, 0, 0x170A3D },
+ { 28320000, 28320000, 1, 28, 2, 1, 1, 3, 0, 3, 4, 0, 0x51EB85 },
+ { 30240000, 30240000, 1, 30, 2, 1, 1, 3, 0, 3, 4, 0, 0x3D70A3 },
+ { 31500000, 31500000, 1, 31, 2, 1, 1, 3, 0, 3, 4, 0, 0x7FFFFF },
+ { 33750000, 33750000, 1, 33, 2, 1, 1, 3, 0, 3, 4, 0, 0xCFFFFF },
+ { 36000000, 36000000, 1, 36, 2, 1, 1, 3, 0, 3, 4, 0, 0 },
+ { 40000000, 40000000, 1, 80, 2, 2, 2, 12, 2, 2, 2, 0, 0 },
+ { 46970000, 46970000, 1, 46, 2, 1, 1, 3, 0, 3, 4, 0, 0xF851EB },
+ { 49500000, 49500000, 1, 49, 2, 1, 1, 3, 0, 3, 4, 0, 0x7FFFFF },
+ { 49000000, 49000000, 1, 49, 2, 1, 1, 3, 0, 3, 4, 0, 0 },
+ { 50000000, 50000000, 1, 50, 2, 1, 1, 3, 0, 3, 4, 0, 0 },
+ { 54000000, 54000000, 1, 54, 2, 1, 1, 3, 0, 3, 4, 0, 0 },
+ { 54054000, 54054000, 1, 54, 2, 1, 1, 3, 0, 3, 4, 0, 0x0DD2F1 },
+ { 57284000, 57284000, 1, 57, 2, 1, 1, 3, 0, 3, 4, 0, 0x48B439 },
+ { 58230000, 58230000, 1, 58, 2, 1, 1, 3, 0, 3, 4, 0, 0x3AE147 },
+ { 59341000, 59341000, 1, 59, 2, 1, 1, 3, 0, 3, 4, 0, 0x574BC6 },
+ { 59400000, 59400000, 1, 99, 3, 1, 1, 1, 3, 3, 4, 0, 0 },
+ { 65000000, 65000000, 1, 130, 2, 2, 2, 12, 0, 2, 2, 0, 0 },
+ { 68250000, 68250000, 1, 68, 2, 1, 1, 3, 0, 3, 4, 0, 0x3FFFFF },
+ { 71000000, 71000000, 1, 71, 2, 1, 1, 3, 0, 3, 4, 0, 0 },
+ { 74176000, 74176000, 1, 98, 1, 2, 2, 1, 2, 3, 4, 0, 0xE6AE6B },
+ { 74250000, 74250000, 1, 99, 1, 2, 2, 1, 2, 3, 4, 0, 0 },
+ { 75000000, 75000000, 1, 75, 2, 1, 1, 3, 0, 3, 4, 0, 0 },
+ { 78750000, 78750000, 1, 78, 2, 1, 1, 3, 0, 3, 4, 0, 0xCFFFFF },
+ { 79500000, 79500000, 1, 79, 2, 1, 1, 3, 0, 3, 4, 0, 0x7FFFFF },
+ { 83500000, 83500000, 2, 167, 2, 1, 1, 1, 0, 0, 6, 0, 0 },
+ { 83500000, 104375000, 1, 104, 2, 1, 1, 1, 1, 0, 5, 0, 0x600000 },
+ { 85500000, 85500000, 1, 85, 2, 1, 1, 3, 0, 3, 4, 0, 0x7FFFFF },
+ { 85750000, 85750000, 1, 85, 2, 1, 1, 3, 0, 3, 4, 0, 0xCFFFFF },
+ { 85800000, 85800000, 1, 85, 2, 1, 1, 3, 0, 3, 4, 0, 0xCCCCCC },
+ { 88750000, 88750000, 1, 88, 2, 1, 1, 3, 0, 3, 4, 0, 0xCFFFFF },
+ { 89910000, 89910000, 1, 89, 2, 1, 1, 3, 0, 3, 4, 0, 0xE8F5C1 },
+ { 90000000, 90000000, 1, 90, 2, 1, 1, 3, 0, 3, 4, 0, 0 },
+ { 101000000, 101000000, 1, 101, 2, 1, 1, 3, 0, 3, 4, 0, 0 },
+ { 102250000, 102250000, 1, 102, 2, 1, 1, 3, 0, 3, 4, 0, 0x3FFFFF },
+ { 106500000, 106500000, 1, 106, 2, 1, 1, 3, 0, 3, 4, 0, 0x7FFFFF },
+ { 108000000, 108000000, 1, 90, 3, 0, 0, 5, 0, 2, 2, 0, 0 },
+ { 119000000, 119000000, 1, 119, 2, 1, 1, 3, 0, 3, 4, 0, 0 },
+ { 131481000, 131481000, 1, 131, 2, 1, 1, 3, 0, 3, 4, 0, 0x7B22D1 },
+ { 135000000, 135000000, 1, 135, 2, 1, 1, 3, 0, 3, 4, 0, 0 },
+ { 136750000, 136750000, 1, 136, 2, 1, 1, 3, 0, 3, 4, 0, 0xCFFFFF },
+ { 147180000, 147180000, 1, 147, 2, 1, 1, 3, 0, 3, 4, 0, 0x2E147A },
+ { 148352000, 148352000, 1, 98, 1, 1, 1, 1, 2, 2, 2, 0, 0xE6AE6B },
+ { 148500000, 148500000, 1, 99, 1, 1, 1, 1, 2, 2, 2, 0, 0 },
+ { 154000000, 154000000, 1, 154, 2, 1, 1, 3, 0, 3, 4, 0, 0 },
+ { 156000000, 156000000, 1, 156, 2, 1, 1, 3, 0, 3, 4, 0, 0 },
+ { 157000000, 157000000, 1, 157, 2, 1, 1, 3, 0, 3, 4, 0, 0 },
+ { 162000000, 162000000, 1, 162, 2, 1, 1, 3, 0, 3, 4, 0, 0 },
+ { 174250000, 174250000, 1, 145, 3, 0, 0, 5, 0, 2, 2, 0, 0x355555 },
+ { 174500000, 174500000, 1, 174, 2, 1, 1, 3, 0, 3, 4, 0, 0x7FFFFF },
+ { 174570000, 174570000, 1, 174, 2, 1, 1, 3, 0, 3, 4, 0, 0x91EB84 },
+ { 175500000, 175500000, 1, 175, 2, 1, 1, 3, 0, 3, 4, 0, 0x7FFFFF },
+ { 185590000, 185590000, 1, 185, 2, 1, 1, 3, 0, 3, 4, 0, 0x970A3C },
+ { 187000000, 187000000, 1, 187, 2, 1, 1, 3, 0, 3, 4, 0, 0 },
+ { 241500000, 241500000, 1, 161, 1, 1, 1, 4, 0, 2, 2, 0, 0 },
+ { 241700000, 241700000, 1, 241, 2, 1, 1, 3, 0, 3, 4, 0, 0xB33332 },
+ { 262750000, 262750000, 1, 262, 2, 1, 1, 3, 0, 3, 4, 0, 0xCFFFFF },
+ { 296500000, 296500000, 1, 296, 2, 1, 1, 3, 0, 3, 4, 0, 0x7FFFFF },
+ { 296703000, 296703000, 1, 98, 0, 1, 1, 1, 0, 2, 2, 0, 0xE6AE6B },
+ { 297000000, 297000000, 1, 99, 0, 1, 1, 1, 0, 2, 2, 0, 0 },
+ { 594000000, 594000000, 1, 99, 0, 2, 0, 1, 0, 1, 1, 0, 0 },
+ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
+};
+
+static const struct post_pll_config post_pll_cfg_table[] = {
+ { 25200000, 1, 80, 13, 3 },
+ { 27000000, 1, 40, 11, 3 },
+ { 27027000, 1, 40, 11, 3 },
+ { 33750000, 1, 40, 11, 3 },
+ { 49000000, 1, 20, 1, 3 },
+ { 65000000, 1, 20, 1, 3 },
+ { 74250000, 1, 20, 1, 3 },
+ { 88750000, 1, 20, 1, 3 },
+ { 108000000, 1, 20, 1, 3 },
+ { 148500000, 1, 20, 1, 3 },
+ { 162000000, 1, 20, 1, 3 },
+ { 174250000, 1, 20, 1, 3 },
+ { 187000000, 1, 20, 1, 3 },
+ { 241700000, 1, 20, 1, 3 },
+ { 297000000, 4, 20, 0, 0 },
+ { 594000000, 4, 20, 0, 0 }, /* postpll_postdiv_en = 0 */
+ { /* sentinel */ }
+};
+
+struct starfive_hdmi_phy {
+ struct device *dev;
+ struct regmap *regmap;
+ struct phy *phy;
+ struct clk *refoclk;
+
+ struct inno_hdmi_phy_pre_pll pre_pll;
+
+ struct clk_hw hw;
+ struct clk *phyclk;
+ unsigned long pixclock;
+ unsigned long tmdsclock;
+};
+
+static inline void inno_write(struct starfive_hdmi_phy *inno, u32 reg, u8 val)
+{
+ regmap_write(inno->regmap, reg * 4, val);
+}
+
+static inline u8 inno_read(struct starfive_hdmi_phy *inno, u32 reg)
+{
+ u32 val;
+
+ regmap_read(inno->regmap, reg * 4, &val);
+ return val;
+}
+
+static inline void inno_update_bits(struct starfive_hdmi_phy *inno, u16 reg,
+ u8 mask, u8 val)
+{
+ regmap_update_bits(inno->regmap, reg * 4, mask, val);
+}
+
+#define inno_poll(inno, reg, val, cond, sleep_us, timeout_us) \
+ regmap_read_poll_timeout((inno)->regmap, (reg) * 4, val, cond, \
+ sleep_us, timeout_us)
+
+static inline struct starfive_hdmi_phy *to_starfive_hdmi_phy(struct clk_hw *hw)
+{
+ return container_of(hw, struct starfive_hdmi_phy, hw);
+}
+
+static int starfive_hdmi_phy_clk_prepare(struct clk_hw *hw)
+{
+ struct starfive_hdmi_phy *inno = to_starfive_hdmi_phy(hw);
+ int ret;
+
+ inno_hdmi_phy_pre_pll_power_down(&inno->pre_pll, false);
+
+ if (inno_hdmi_phy_pre_pll_is_locked(&inno->pre_pll))
+ return 0;
+
+ ret = inno_hdmi_phy_pre_pll_wait_locked(&inno->pre_pll, 100000);
+ if (ret) {
+ dev_err(inno->dev, "Timeout waiting for pre-PLL lock\n");
+ inno_hdmi_phy_pre_pll_power_down(&inno->pre_pll, true);
+ return ret;
+ }
+
+ return 0;
+}
+
+static void starfive_hdmi_phy_clk_unprepare(struct clk_hw *hw)
+{
+ struct starfive_hdmi_phy *inno = to_starfive_hdmi_phy(hw);
+
+ inno_hdmi_phy_pre_pll_power_down(&inno->pre_pll, true);
+ inno->pixclock = 0; /* Invalidate cached rate */
+}
+
+static int starfive_hdmi_phy_clk_is_prepared(struct clk_hw *hw)
+{
+ struct starfive_hdmi_phy *inno = to_starfive_hdmi_phy(hw);
+
+ if (!inno_hdmi_phy_pre_pll_is_powered(&inno->pre_pll))
+ return 0;
+
+ return inno_hdmi_phy_pre_pll_is_locked(&inno->pre_pll);
+}
+
+static unsigned long starfive_hdmi_phy_clk_recalc_rate(struct clk_hw *hw,
+ unsigned long parent_rate)
+{
+ struct starfive_hdmi_phy *inno = to_starfive_hdmi_phy(hw);
+
+ if (!starfive_hdmi_phy_clk_is_prepared(hw))
+ return inno->pixclock;
+
+ inno->pixclock = inno_hdmi_phy_pre_pll_recalc_rate(&inno->pre_pll,
+ parent_rate);
+
+ return inno->pixclock;
+}
+
+static int starfive_hdmi_phy_clk_determine_rate(struct clk_hw *hw,
+ struct clk_rate_request *req)
+{
+ struct starfive_hdmi_phy *inno = to_starfive_hdmi_phy(hw);
+
+ return inno_hdmi_phy_pre_pll_determine_rate(&inno->pre_pll, req);
+}
+
+static int starfive_hdmi_phy_clk_set_rate(struct clk_hw *hw, unsigned long rate,
+ unsigned long parent_rate)
+{
+ struct starfive_hdmi_phy *inno = to_starfive_hdmi_phy(hw);
+ const struct inno_hdmi_phy_pre_pll_config *cfg;
+
+ /*
+ * The JH7110 only drives 8bpc, so the TMDS clock always matches the
+ * pixel clock.
+ */
+ cfg = inno_hdmi_phy_pre_pll_lookup(&inno->pre_pll, rate, rate);
+ if (IS_ERR(cfg))
+ return PTR_ERR(cfg);
+
+ dev_dbg(inno->dev, "%s rate %lu tmdsclk %lu\n",
+ __func__, rate, cfg->tmdsclock);
+
+ if (inno->pixclock == rate && inno->tmdsclock == cfg->tmdsclock)
+ return 0;
+
+ inno_update_bits(inno, STF_INNO_BIAS_CONTROL,
+ STF_INNO_BIAS_ENABLE, STF_INNO_BIAS_ENABLE);
+ inno_write(inno, STF_INNO_RX_CONTROL, STF_INNO_RX_ENABLE);
+
+ inno_hdmi_phy_pre_pll_power_down(&inno->pre_pll, true);
+ inno_hdmi_phy_pre_pll_configure(&inno->pre_pll, cfg);
+ inno_hdmi_phy_pre_pll_power_down(&inno->pre_pll, false);
+
+ inno->pixclock = rate;
+ inno->tmdsclock = cfg->tmdsclock;
+
+ return 0;
+}
+
+static const struct clk_ops starfive_hdmi_phy_clk_ops = {
+ .prepare = starfive_hdmi_phy_clk_prepare,
+ .unprepare = starfive_hdmi_phy_clk_unprepare,
+ .is_prepared = starfive_hdmi_phy_clk_is_prepared,
+ .recalc_rate = starfive_hdmi_phy_clk_recalc_rate,
+ .determine_rate = starfive_hdmi_phy_clk_determine_rate,
+ .set_rate = starfive_hdmi_phy_clk_set_rate,
+};
+
+static int starfive_hdmi_phy_power_on(struct phy *phy)
+{
+ struct starfive_hdmi_phy *inno = phy_get_drvdata(phy);
+ const struct post_pll_config *cfg = post_pll_cfg_table;
+ const struct inno_hdmi_phy_pre_pll_config *pre_cfg;
+ unsigned long tmdsclock;
+ u8 reg_1ad_value;
+ u8 reg_1aa_value;
+
+ u32 v;
+ int ret;
+
+ tmdsclock = clk_get_rate(inno->phyclk);
+ pre_cfg = inno_hdmi_phy_pre_pll_lookup(&inno->pre_pll, tmdsclock,
+ tmdsclock);
+ if (IS_ERR(pre_cfg)) {
+ dev_err(inno->dev, "no pre-PLL config for current pixel clock\n");
+ return PTR_ERR(pre_cfg);
+ }
+ tmdsclock = pre_cfg->tmdsclock;
+ inno->tmdsclock = tmdsclock;
+
+ inno_update_bits(inno, STF_INNO_BIAS_CONTROL,
+ STF_INNO_BIAS_ENABLE, STF_INNO_BIAS_ENABLE);
+ inno_write(inno, STF_INNO_RX_CONTROL, STF_INNO_RX_ENABLE);
+
+ /* Find Post-PLL config */
+ for (; cfg->tmdsclock != 0; cfg++)
+ if (tmdsclock <= cfg->tmdsclock)
+ break;
+
+ if (cfg->tmdsclock == 0) {
+ dev_err(inno->dev, "Failed to find Post-PLL config\n");
+ return -EINVAL;
+ }
+ dev_dbg(inno->dev, "Inno HDMI PHY Power On: pixclk %lu, tmdsclk %lu\n",
+ inno->pixclock, tmdsclock);
+
+ reg_1ad_value = cfg->post_div_en ? cfg->postdiv : 0x00;
+ reg_1aa_value = cfg->post_div_en ? 0x0e : 0x02;
+
+ /*
+ * Pre-PLL is already prepared and running at inno->pixclock
+ * via the clk_set_rate and prepare calls from the controller/bridge.
+ * Now, configure and enable the Post-PLL and TMDS outputs.
+ */
+
+ inno_write(inno, STF_INNO_POST_PLL_DIV_2,
+ STF_INNO_POST_PLL_PRE_DIV(cfg->prediv));
+ inno_write(inno, STF_INNO_POST_PLL_DIV_3, cfg->fbdiv & 0xff);
+ inno_write(inno, STF_INNO_POST_PLL_DIV_4, reg_1ad_value);
+
+ /* Power up Post-PLL */
+ inno_write(inno, STF_INNO_POST_PLL_DIV_1, reg_1aa_value);
+
+ /* Wait for post PLL lock */
+ ret = inno_poll(inno, STF_INNO_POST_PLL_LOCK_STATUS, v,
+ v & STF_INNO_POST_PLL_LOCK, 1000, 100000);
+ if (ret) {
+ dev_err(inno->dev, "Post-PLL locking failed\n");
+ return ret;
+ }
+
+ inno_write(inno, STF_INNO_LDO_CONTROL, STF_INNO_LDO_ENABLE);
+ inno_write(inno, STF_INNO_SERIALIER_CONTROL,
+ STF_INNO_SERIALIER_ENABLE);
+ inno_write(inno, STF_INNO_TMDS_CONTROL, 0x8f);
+
+ return 0;
+}
+
+static int starfive_hdmi_phy_power_off(struct phy *phy)
+{
+ struct starfive_hdmi_phy *inno = phy_get_drvdata(phy);
+
+ dev_dbg(inno->dev, "Inno HDMI PHY Power Off\n");
+
+ inno_write(inno, STF_INNO_TMDS_CONTROL, 0x00);
+ inno_write(inno, STF_INNO_SERIALIER_CONTROL, 0x00);
+ inno_write(inno, STF_INNO_LDO_CONTROL, 0x00);
+ inno_update_bits(inno, STF_INNO_BIAS_CONTROL,
+ STF_INNO_BIAS_ENABLE, 0x00);
+ inno_write(inno, STF_INNO_RX_CONTROL, 0x00);
+
+ /* Power down Post-PLL */
+ inno_update_bits(inno, STF_INNO_POST_PLL_DIV_1,
+ STF_INNO_POST_PLL_POWER_DOWN,
+ STF_INNO_POST_PLL_POWER_DOWN);
+
+ inno->tmdsclock = 0;
+ inno->pixclock = 0;
+
+ return 0;
+}
+
+static const struct phy_ops starfive_hdmi_phy_ops = {
+ .owner = THIS_MODULE,
+ .power_on = starfive_hdmi_phy_power_on,
+ .power_off = starfive_hdmi_phy_power_off,
+};
+
+static int starfive_hdmi_phy_probe(struct platform_device *pdev)
+{
+ struct device *dev = &pdev->dev;
+ struct device *parent = dev->parent;
+ struct starfive_hdmi_phy *inno;
+ struct phy_provider *phy_provider;
+ struct regmap *regmap;
+ struct clk_init_data init = {};
+ const char *refoclk_name;
+ int ret;
+
+ inno = devm_kzalloc(dev, sizeof(*inno), GFP_KERNEL);
+ if (!inno)
+ return -ENOMEM;
+
+ inno->dev = dev;
+
+ /* Get the regmap from the parent device */
+ regmap = dev_get_regmap(parent, NULL);
+ if (!regmap) {
+ dev_err(dev, "Failed to get parent regmap\n");
+ return -ENODEV;
+ }
+ inno->regmap = regmap;
+
+ /*
+ * The PHY block sits behind the HDMI controller in the shared register
+ * space, so the common pre-PLL helpers need a 0x100 register offset.
+ */
+ inno->pre_pll.regmap = regmap;
+ inno->pre_pll.offset = 0x100;
+ inno->pre_pll.table = pre_pll_cfg_table;
+
+ /* Get the input reference clock */
+ inno->refoclk = devm_clk_get(inno->dev, "refoclk");
+ if (IS_ERR(inno->refoclk)) {
+ ret = PTR_ERR(inno->refoclk);
+ dev_err(inno->dev, "failed to get oscillator-ref clock: %d\n",
+ ret);
+ return ret;
+ }
+
+ /* We must prepare/enable refoclk here so .set_rate/.recalc_rate work */
+ ret = clk_prepare_enable(inno->refoclk);
+ if (ret) {
+ dev_err(dev, "Failed to enable refoclk: %d\n", ret);
+ return ret;
+ }
+
+ platform_set_drvdata(pdev, inno);
+
+ /* Initialize and register the clock provider */
+ refoclk_name = __clk_get_name(inno->refoclk);
+ init.parent_names = &refoclk_name;
+ init.num_parents = 1;
+ init.flags = 0;
+ init.name = "hdmi_pclk";
+ init.ops = &starfive_hdmi_phy_clk_ops;
+
+ of_property_read_string(dev->of_node, "clock-output-names", &init.name);
+
+ inno->hw.init = &init;
+ inno->phyclk = devm_clk_register(dev, &inno->hw);
+ if (IS_ERR(inno->phyclk)) {
+ ret = PTR_ERR(inno->phyclk);
+ dev_err(dev, "Failed to register clock provider: %d\n", ret);
+ goto err_disable_refoclk;
+ }
+
+ ret = of_clk_add_provider(dev->of_node, of_clk_src_simple_get, inno->phyclk);
+ if (ret) {
+ dev_err(dev, "Failed to add clock provider: %d\n", ret);
+ goto err_disable_refoclk;
+ }
+
+ ret = clk_set_rate(inno->phyclk, 297000000);
+ if (ret) {
+ dev_err(dev, "Failed to set default rate: %d\n", ret);
+ goto err_disable_refoclk;
+ }
+
+ /* Create and register the PHY provider */
+ inno->phy = devm_phy_create(inno->dev, NULL, &starfive_hdmi_phy_ops);
+ if (IS_ERR(inno->phy)) {
+ ret = PTR_ERR(inno->phy);
+ dev_err(inno->dev, "failed to create HDMI PHY: %d\n", ret);
+ goto err_del_clk_provider;
+ }
+
+ phy_set_drvdata(inno->phy, inno);
+
+ phy_provider = devm_of_phy_provider_register(inno->dev,
+ of_phy_simple_xlate);
+ ret = PTR_ERR_OR_ZERO(phy_provider);
+ if (ret)
+ goto err_del_clk_provider;
+
+ return 0;
+
+err_del_clk_provider:
+ of_clk_del_provider(dev->of_node);
+err_disable_refoclk:
+ clk_disable_unprepare(inno->refoclk);
+ return ret;
+}
+
+static void starfive_hdmi_phy_remove(struct platform_device *pdev)
+{
+ struct starfive_hdmi_phy *inno = platform_get_drvdata(pdev);
+
+ of_clk_del_provider(pdev->dev.of_node);
+ clk_disable_unprepare(inno->refoclk);
+}
+
+static const struct of_device_id starfive_hdmi_phy_of_match[] = {
+ { .compatible = "starfive,jh7110-inno-hdmi-phy", },
+ { /* sentinel */ }
+};
+MODULE_DEVICE_TABLE(of, starfive_hdmi_phy_of_match);
+
+static struct platform_driver starfive_hdmi_phy_driver = {
+ .probe = starfive_hdmi_phy_probe,
+ .remove = starfive_hdmi_phy_remove,
+ .driver = {
+ .name = "starfive-inno-hdmi-phy",
+ .of_match_table = starfive_hdmi_phy_of_match,
+ },
+};
+module_platform_driver(starfive_hdmi_phy_driver);
+
+MODULE_AUTHOR("Michal Wilczynski <m.wilczynski@samsung.com>");
+MODULE_DESCRIPTION("StarFive JH7110 Innosilicon HDMI PHY Driver");
+MODULE_LICENSE("GPL");
--
2.34.1
^ permalink raw reply related [flat|nested] 116+ messages in thread
* [PATCH v2 13/15] phy: starfive: Add jh7110-inno-hdmi-phy driver
@ 2026-08-28 13:47 ` Michal Wilczynski
0 siblings, 0 replies; 116+ messages in thread
From: Michal Wilczynski @ 2026-08-28 13:47 UTC (permalink / raw)
To: Vinod Koul, Neil Armstrong, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Andrzej Hajda, Robert Foss, Laurent Pinchart,
Jonas Karlman, Jernej Skrabec, Luca Ceresoli, David Airlie,
Simona Vetter, Maarten Lankhorst, Maxime Ripard,
Thomas Zimmermann, Lee Jones, Andy Yan, Philipp Zabel,
Emil Renner Berthing, Hal Feng, Michael Turquette, Stephen Boyd,
Brian Masney, Heiko Stuebner, Conor Dooley, Paul Walmsley,
Palmer Dabbelt, Albert Ou, Alexandre Ghiti, Dominique Belhachemi
Cc: linux-phy, devicetree, linux-kernel, dri-devel, mfd, linux-clk,
linux-arm-kernel, linux-rockchip, linux-riscv, Icenowy Zheng,
Andy Yan, Marek Szyprowski, Maud Spierings, Graham Markall,
Michal Wilczynski
Add the HDMI PHY driver for the StarFive JH7110.
This driver binds to the starfive,jh7110-inno-hdmi-phy node and
gets its regmap from the parent. It has no dependencies on voutcrg, only
on its refoclk (xin24m), which breaks the probe-time circular
dependency.
This driver provides two main functions:
- Clock Provider: It registers clk_ops to provide the variable pixel
clock (hdmi_pclk). The .set_rate operation configures the Pre-PLL
registers (0x1a0+) based on the requested rate.
- PHY Provider: It registers phy_ops for the controller. The .power_on
op configures and enables the Post-PLL and other analog blocks (BIAS,
LDO, Serializer, etc.).
The JH7110 instantiates the same Innosilicon IP as the Rockchip RK3328,
with the PHY register block shifted by 0x100 because it sits behind the
HDMI controller in the shared register space. The pre-PLL programming
therefore comes from the common Innosilicon helpers; this driver adds
the JH7110 pixel clock table, the post-PLL and the analog configuration.
Co-developed-by: Dominique Belhachemi <db@domibel.de>
Signed-off-by: Dominique Belhachemi <db@domibel.de>
Signed-off-by: Michal Wilczynski <m.wilczynski@samsung.com>
---
drivers/phy/starfive/Kconfig | 20 +
drivers/phy/starfive/Makefile | 1 +
drivers/phy/starfive/phy-jh7110-inno-hdmi.c | 567 ++++++++++++++++++++++++++++
3 files changed, 588 insertions(+)
diff --git a/drivers/phy/starfive/Kconfig b/drivers/phy/starfive/Kconfig
index d0cdd7cb4a13de22ff643c89a79d99cce57284d7..1da417ffbf224c13224e42a3ce322e3d0c272824 100644
--- a/drivers/phy/starfive/Kconfig
+++ b/drivers/phy/starfive/Kconfig
@@ -25,6 +25,26 @@ config PHY_STARFIVE_JH7110_DPHY_TX
system. If M is selected, the module will be called
phy-jh7110-dphy-tx.ko.
+config PHY_STARFIVE_JH7110_INNO_HDMI
+ tristate "Starfive JH7110 INNO HDMI PHY"
+ select PHY_INNO_HDMI
+ depends on COMMON_CLK
+ select GENERIC_PHY
+ help
+ This option enables the driver for the analog HDMI PHY (Physical
+ Layer) on the StarFive JH7110 SoC.
+
+ This driver binds to a child node of the 'starfive,jh7110-hdmi-subsystem'
+ parent driver and gets its register map from that parent.
+
+ It is responsible for two main functions:
+ 1. PHY Provider: It provides standard PHY operations (.power_on,
+ .power_off) for the HDMI controller (bridge) driver. This
+ involves configuring the Post-PLL and analog TMDS blocks.
+ 2. Clock Provider: It registers as a clock provider to supply the
+ variable pixel clock (hdmi_pclk) to the HDMI controller and
+ the VOUT subsystem, which it generates using the Pre-PLL.
+
config PHY_STARFIVE_JH7110_PCIE
tristate "Starfive JH7110 PCIE 2.0/USB 3.0 PHY support"
depends on HAS_IOMEM
diff --git a/drivers/phy/starfive/Makefile b/drivers/phy/starfive/Makefile
index eedc4a6fec156320c99ac0a0da609083b6a6a695..e7b13f00880b500f933f21b6037384d5c6884e3e 100644
--- a/drivers/phy/starfive/Makefile
+++ b/drivers/phy/starfive/Makefile
@@ -1,5 +1,6 @@
# SPDX-License-Identifier: GPL-2.0
obj-$(CONFIG_PHY_STARFIVE_JH7110_DPHY_RX) += phy-jh7110-dphy-rx.o
obj-$(CONFIG_PHY_STARFIVE_JH7110_DPHY_TX) += phy-jh7110-dphy-tx.o
+obj-$(CONFIG_PHY_STARFIVE_JH7110_INNO_HDMI) += phy-jh7110-inno-hdmi.o
obj-$(CONFIG_PHY_STARFIVE_JH7110_PCIE) += phy-jh7110-pcie.o
obj-$(CONFIG_PHY_STARFIVE_JH7110_USB) += phy-jh7110-usb.o
diff --git a/drivers/phy/starfive/phy-jh7110-inno-hdmi.c b/drivers/phy/starfive/phy-jh7110-inno-hdmi.c
new file mode 100644
index 0000000000000000000000000000000000000000..f4c4d76a38754d5edd4d80895481560c9650f3e7
--- /dev/null
+++ b/drivers/phy/starfive/phy-jh7110-inno-hdmi.c
@@ -0,0 +1,567 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (c) 2017 Rockchip Electronics Co. Ltd.
+ * Copyright (c) 2025 Samsung Electronics Co., Ltd.
+ *
+ * Author: Zheng Yang <zhengyang@rock-chips.com>
+ * Author: Michal Wilczynski <m.wilczynski@samsung.com>
+ *
+ * The register layout and programming sequence derive from
+ * drivers/phy/rockchip/phy-rockchip-inno-hdmi.c; the JH7110 places the
+ * same Innosilicon PHY block at a 0x100 register offset.
+ *
+ * This driver handles the PHY portion of the StarFive Innosilicon HDMI IP,
+ * which is part of a monolithic HDMI block. It provides the variable pixel
+ * clock (from the Pre-PLL) and the PHY operations (for the Post-PLL/analog).
+ */
+
+#include <linux/bitfield.h>
+#include <linux/bits.h>
+#include <linux/clk.h>
+#include <linux/clk-provider.h>
+#include <linux/delay.h>
+#include <linux/io.h>
+#include <linux/iopoll.h>
+#include <linux/math64.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
+#include <linux/regmap.h>
+#include <linux/phy/inno-hdmi-phy.h>
+#include <linux/phy/phy.h>
+#include <linux/slab.h>
+
+/*
+ * StarFive (JH7110) Innosilicon HDMI PHY Register Definitions
+ */
+
+/* REG: 0x1aa */
+#define STF_INNO_POST_PLL_DIV_1 0x1aa
+#define STF_INNO_POST_PLL_POST_DIV_ENABLE GENMASK(3, 2)
+#define STF_INNO_POST_PLL_REFCLK_SEL_TMDS BIT(1)
+#define STF_INNO_POST_PLL_POWER_DOWN BIT(0)
+
+/* REG: 0x1ab */
+#define STF_INNO_POST_PLL_DIV_2 0x1ab
+#define STF_INNO_POST_PLL_PRE_DIV(x) FIELD_PREP(GENMASK(5, 0), x)
+#define STF_INNO_POST_PLL_FB_DIV_8(x) FIELD_PREP(BIT(7), (x) >> 8)
+
+/* REG: 0x1ac */
+#define STF_INNO_POST_PLL_DIV_3 0x1ac
+#define STF_INNO_POST_PLL_FB_DIV_7_0(x) FIELD_PREP(GENMASK(7, 0), x)
+
+/* REG: 0x1ad */
+#define STF_INNO_POST_PLL_DIV_4 0x1ad
+#define STF_INNO_POST_PLL_POST_DIV_MASK GENMASK(1, 0)
+
+/* REG: 0x1af */
+#define STF_INNO_POST_PLL_LOCK_STATUS 0x1af
+#define STF_INNO_POST_PLL_LOCK BIT(0)
+
+/* REG: 0x1b0 */
+#define STF_INNO_BIAS_CONTROL 0x1b0
+#define STF_INNO_BIAS_ENABLE BIT(2)
+
+/* REG: 0x1b2 */
+#define STF_INNO_TMDS_CONTROL 0x1b2
+#define STF_INNO_TMDS_CLK_DRIVER_EN BIT(3)
+#define STF_INNO_TMDS_D2_DRIVER_EN BIT(2)
+#define STF_INNO_TMDS_D1_DRIVER_EN BIT(1)
+#define STF_INNO_TMDS_D0_DRIVER_EN BIT(0)
+#define STF_INNO_TMDS_DRIVER_ENABLE (STF_INNO_TMDS_CLK_DRIVER_EN | \
+ STF_INNO_TMDS_D2_DRIVER_EN | \
+ STF_INNO_TMDS_D1_DRIVER_EN | \
+ STF_INNO_TMDS_D0_DRIVER_EN)
+
+/* REG: 0x1b4 */
+#define STF_INNO_LDO_CONTROL 0x1b4
+#define STF_INNO_LDO_ENABLE (BIT(2) | BIT(1) | BIT(0))
+
+/* REG: 0x1be */
+#define STF_INNO_SERIALIER_CONTROL 0x1be
+#define STF_INNO_SERIALIER_ENABLE (BIT(6) | BIT(5) | BIT(4) | BIT(0))
+
+/* REG: 0x1cc */
+#define STF_INNO_RX_CONTROL 0x1cc
+#define STF_INNO_RX_ENABLE (BIT(3) | BIT(2) | BIT(1) | BIT(0))
+
+/*
+ * These tables are copied from the monolithic driver.
+ * They match the Rockchip PHY driver tables.
+ */
+
+struct post_pll_config {
+ unsigned long tmdsclock;
+ u8 prediv;
+ u16 fbdiv;
+ u8 postdiv;
+ u8 post_div_en;
+};
+
+static const struct inno_hdmi_phy_pre_pll_config pre_pll_cfg_table[] = {
+ { 25175000, 25175000, 1, 100, 2, 3, 3, 12, 3, 3, 4, 0, 0xF55555 },
+ { 25200000, 25200000, 1, 100, 2, 3, 3, 12, 3, 3, 4, 0, 0 },
+ { 27000000, 27000000, 1, 90, 3, 2, 2, 10, 3, 3, 4, 0, 0 },
+ { 27027000, 27027000, 1, 90, 3, 2, 2, 10, 3, 3, 4, 0, 0x170A3D },
+ { 28320000, 28320000, 1, 28, 2, 1, 1, 3, 0, 3, 4, 0, 0x51EB85 },
+ { 30240000, 30240000, 1, 30, 2, 1, 1, 3, 0, 3, 4, 0, 0x3D70A3 },
+ { 31500000, 31500000, 1, 31, 2, 1, 1, 3, 0, 3, 4, 0, 0x7FFFFF },
+ { 33750000, 33750000, 1, 33, 2, 1, 1, 3, 0, 3, 4, 0, 0xCFFFFF },
+ { 36000000, 36000000, 1, 36, 2, 1, 1, 3, 0, 3, 4, 0, 0 },
+ { 40000000, 40000000, 1, 80, 2, 2, 2, 12, 2, 2, 2, 0, 0 },
+ { 46970000, 46970000, 1, 46, 2, 1, 1, 3, 0, 3, 4, 0, 0xF851EB },
+ { 49500000, 49500000, 1, 49, 2, 1, 1, 3, 0, 3, 4, 0, 0x7FFFFF },
+ { 49000000, 49000000, 1, 49, 2, 1, 1, 3, 0, 3, 4, 0, 0 },
+ { 50000000, 50000000, 1, 50, 2, 1, 1, 3, 0, 3, 4, 0, 0 },
+ { 54000000, 54000000, 1, 54, 2, 1, 1, 3, 0, 3, 4, 0, 0 },
+ { 54054000, 54054000, 1, 54, 2, 1, 1, 3, 0, 3, 4, 0, 0x0DD2F1 },
+ { 57284000, 57284000, 1, 57, 2, 1, 1, 3, 0, 3, 4, 0, 0x48B439 },
+ { 58230000, 58230000, 1, 58, 2, 1, 1, 3, 0, 3, 4, 0, 0x3AE147 },
+ { 59341000, 59341000, 1, 59, 2, 1, 1, 3, 0, 3, 4, 0, 0x574BC6 },
+ { 59400000, 59400000, 1, 99, 3, 1, 1, 1, 3, 3, 4, 0, 0 },
+ { 65000000, 65000000, 1, 130, 2, 2, 2, 12, 0, 2, 2, 0, 0 },
+ { 68250000, 68250000, 1, 68, 2, 1, 1, 3, 0, 3, 4, 0, 0x3FFFFF },
+ { 71000000, 71000000, 1, 71, 2, 1, 1, 3, 0, 3, 4, 0, 0 },
+ { 74176000, 74176000, 1, 98, 1, 2, 2, 1, 2, 3, 4, 0, 0xE6AE6B },
+ { 74250000, 74250000, 1, 99, 1, 2, 2, 1, 2, 3, 4, 0, 0 },
+ { 75000000, 75000000, 1, 75, 2, 1, 1, 3, 0, 3, 4, 0, 0 },
+ { 78750000, 78750000, 1, 78, 2, 1, 1, 3, 0, 3, 4, 0, 0xCFFFFF },
+ { 79500000, 79500000, 1, 79, 2, 1, 1, 3, 0, 3, 4, 0, 0x7FFFFF },
+ { 83500000, 83500000, 2, 167, 2, 1, 1, 1, 0, 0, 6, 0, 0 },
+ { 83500000, 104375000, 1, 104, 2, 1, 1, 1, 1, 0, 5, 0, 0x600000 },
+ { 85500000, 85500000, 1, 85, 2, 1, 1, 3, 0, 3, 4, 0, 0x7FFFFF },
+ { 85750000, 85750000, 1, 85, 2, 1, 1, 3, 0, 3, 4, 0, 0xCFFFFF },
+ { 85800000, 85800000, 1, 85, 2, 1, 1, 3, 0, 3, 4, 0, 0xCCCCCC },
+ { 88750000, 88750000, 1, 88, 2, 1, 1, 3, 0, 3, 4, 0, 0xCFFFFF },
+ { 89910000, 89910000, 1, 89, 2, 1, 1, 3, 0, 3, 4, 0, 0xE8F5C1 },
+ { 90000000, 90000000, 1, 90, 2, 1, 1, 3, 0, 3, 4, 0, 0 },
+ { 101000000, 101000000, 1, 101, 2, 1, 1, 3, 0, 3, 4, 0, 0 },
+ { 102250000, 102250000, 1, 102, 2, 1, 1, 3, 0, 3, 4, 0, 0x3FFFFF },
+ { 106500000, 106500000, 1, 106, 2, 1, 1, 3, 0, 3, 4, 0, 0x7FFFFF },
+ { 108000000, 108000000, 1, 90, 3, 0, 0, 5, 0, 2, 2, 0, 0 },
+ { 119000000, 119000000, 1, 119, 2, 1, 1, 3, 0, 3, 4, 0, 0 },
+ { 131481000, 131481000, 1, 131, 2, 1, 1, 3, 0, 3, 4, 0, 0x7B22D1 },
+ { 135000000, 135000000, 1, 135, 2, 1, 1, 3, 0, 3, 4, 0, 0 },
+ { 136750000, 136750000, 1, 136, 2, 1, 1, 3, 0, 3, 4, 0, 0xCFFFFF },
+ { 147180000, 147180000, 1, 147, 2, 1, 1, 3, 0, 3, 4, 0, 0x2E147A },
+ { 148352000, 148352000, 1, 98, 1, 1, 1, 1, 2, 2, 2, 0, 0xE6AE6B },
+ { 148500000, 148500000, 1, 99, 1, 1, 1, 1, 2, 2, 2, 0, 0 },
+ { 154000000, 154000000, 1, 154, 2, 1, 1, 3, 0, 3, 4, 0, 0 },
+ { 156000000, 156000000, 1, 156, 2, 1, 1, 3, 0, 3, 4, 0, 0 },
+ { 157000000, 157000000, 1, 157, 2, 1, 1, 3, 0, 3, 4, 0, 0 },
+ { 162000000, 162000000, 1, 162, 2, 1, 1, 3, 0, 3, 4, 0, 0 },
+ { 174250000, 174250000, 1, 145, 3, 0, 0, 5, 0, 2, 2, 0, 0x355555 },
+ { 174500000, 174500000, 1, 174, 2, 1, 1, 3, 0, 3, 4, 0, 0x7FFFFF },
+ { 174570000, 174570000, 1, 174, 2, 1, 1, 3, 0, 3, 4, 0, 0x91EB84 },
+ { 175500000, 175500000, 1, 175, 2, 1, 1, 3, 0, 3, 4, 0, 0x7FFFFF },
+ { 185590000, 185590000, 1, 185, 2, 1, 1, 3, 0, 3, 4, 0, 0x970A3C },
+ { 187000000, 187000000, 1, 187, 2, 1, 1, 3, 0, 3, 4, 0, 0 },
+ { 241500000, 241500000, 1, 161, 1, 1, 1, 4, 0, 2, 2, 0, 0 },
+ { 241700000, 241700000, 1, 241, 2, 1, 1, 3, 0, 3, 4, 0, 0xB33332 },
+ { 262750000, 262750000, 1, 262, 2, 1, 1, 3, 0, 3, 4, 0, 0xCFFFFF },
+ { 296500000, 296500000, 1, 296, 2, 1, 1, 3, 0, 3, 4, 0, 0x7FFFFF },
+ { 296703000, 296703000, 1, 98, 0, 1, 1, 1, 0, 2, 2, 0, 0xE6AE6B },
+ { 297000000, 297000000, 1, 99, 0, 1, 1, 1, 0, 2, 2, 0, 0 },
+ { 594000000, 594000000, 1, 99, 0, 2, 0, 1, 0, 1, 1, 0, 0 },
+ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
+};
+
+static const struct post_pll_config post_pll_cfg_table[] = {
+ { 25200000, 1, 80, 13, 3 },
+ { 27000000, 1, 40, 11, 3 },
+ { 27027000, 1, 40, 11, 3 },
+ { 33750000, 1, 40, 11, 3 },
+ { 49000000, 1, 20, 1, 3 },
+ { 65000000, 1, 20, 1, 3 },
+ { 74250000, 1, 20, 1, 3 },
+ { 88750000, 1, 20, 1, 3 },
+ { 108000000, 1, 20, 1, 3 },
+ { 148500000, 1, 20, 1, 3 },
+ { 162000000, 1, 20, 1, 3 },
+ { 174250000, 1, 20, 1, 3 },
+ { 187000000, 1, 20, 1, 3 },
+ { 241700000, 1, 20, 1, 3 },
+ { 297000000, 4, 20, 0, 0 },
+ { 594000000, 4, 20, 0, 0 }, /* postpll_postdiv_en = 0 */
+ { /* sentinel */ }
+};
+
+struct starfive_hdmi_phy {
+ struct device *dev;
+ struct regmap *regmap;
+ struct phy *phy;
+ struct clk *refoclk;
+
+ struct inno_hdmi_phy_pre_pll pre_pll;
+
+ struct clk_hw hw;
+ struct clk *phyclk;
+ unsigned long pixclock;
+ unsigned long tmdsclock;
+};
+
+static inline void inno_write(struct starfive_hdmi_phy *inno, u32 reg, u8 val)
+{
+ regmap_write(inno->regmap, reg * 4, val);
+}
+
+static inline u8 inno_read(struct starfive_hdmi_phy *inno, u32 reg)
+{
+ u32 val;
+
+ regmap_read(inno->regmap, reg * 4, &val);
+ return val;
+}
+
+static inline void inno_update_bits(struct starfive_hdmi_phy *inno, u16 reg,
+ u8 mask, u8 val)
+{
+ regmap_update_bits(inno->regmap, reg * 4, mask, val);
+}
+
+#define inno_poll(inno, reg, val, cond, sleep_us, timeout_us) \
+ regmap_read_poll_timeout((inno)->regmap, (reg) * 4, val, cond, \
+ sleep_us, timeout_us)
+
+static inline struct starfive_hdmi_phy *to_starfive_hdmi_phy(struct clk_hw *hw)
+{
+ return container_of(hw, struct starfive_hdmi_phy, hw);
+}
+
+static int starfive_hdmi_phy_clk_prepare(struct clk_hw *hw)
+{
+ struct starfive_hdmi_phy *inno = to_starfive_hdmi_phy(hw);
+ int ret;
+
+ inno_hdmi_phy_pre_pll_power_down(&inno->pre_pll, false);
+
+ if (inno_hdmi_phy_pre_pll_is_locked(&inno->pre_pll))
+ return 0;
+
+ ret = inno_hdmi_phy_pre_pll_wait_locked(&inno->pre_pll, 100000);
+ if (ret) {
+ dev_err(inno->dev, "Timeout waiting for pre-PLL lock\n");
+ inno_hdmi_phy_pre_pll_power_down(&inno->pre_pll, true);
+ return ret;
+ }
+
+ return 0;
+}
+
+static void starfive_hdmi_phy_clk_unprepare(struct clk_hw *hw)
+{
+ struct starfive_hdmi_phy *inno = to_starfive_hdmi_phy(hw);
+
+ inno_hdmi_phy_pre_pll_power_down(&inno->pre_pll, true);
+ inno->pixclock = 0; /* Invalidate cached rate */
+}
+
+static int starfive_hdmi_phy_clk_is_prepared(struct clk_hw *hw)
+{
+ struct starfive_hdmi_phy *inno = to_starfive_hdmi_phy(hw);
+
+ if (!inno_hdmi_phy_pre_pll_is_powered(&inno->pre_pll))
+ return 0;
+
+ return inno_hdmi_phy_pre_pll_is_locked(&inno->pre_pll);
+}
+
+static unsigned long starfive_hdmi_phy_clk_recalc_rate(struct clk_hw *hw,
+ unsigned long parent_rate)
+{
+ struct starfive_hdmi_phy *inno = to_starfive_hdmi_phy(hw);
+
+ if (!starfive_hdmi_phy_clk_is_prepared(hw))
+ return inno->pixclock;
+
+ inno->pixclock = inno_hdmi_phy_pre_pll_recalc_rate(&inno->pre_pll,
+ parent_rate);
+
+ return inno->pixclock;
+}
+
+static int starfive_hdmi_phy_clk_determine_rate(struct clk_hw *hw,
+ struct clk_rate_request *req)
+{
+ struct starfive_hdmi_phy *inno = to_starfive_hdmi_phy(hw);
+
+ return inno_hdmi_phy_pre_pll_determine_rate(&inno->pre_pll, req);
+}
+
+static int starfive_hdmi_phy_clk_set_rate(struct clk_hw *hw, unsigned long rate,
+ unsigned long parent_rate)
+{
+ struct starfive_hdmi_phy *inno = to_starfive_hdmi_phy(hw);
+ const struct inno_hdmi_phy_pre_pll_config *cfg;
+
+ /*
+ * The JH7110 only drives 8bpc, so the TMDS clock always matches the
+ * pixel clock.
+ */
+ cfg = inno_hdmi_phy_pre_pll_lookup(&inno->pre_pll, rate, rate);
+ if (IS_ERR(cfg))
+ return PTR_ERR(cfg);
+
+ dev_dbg(inno->dev, "%s rate %lu tmdsclk %lu\n",
+ __func__, rate, cfg->tmdsclock);
+
+ if (inno->pixclock == rate && inno->tmdsclock == cfg->tmdsclock)
+ return 0;
+
+ inno_update_bits(inno, STF_INNO_BIAS_CONTROL,
+ STF_INNO_BIAS_ENABLE, STF_INNO_BIAS_ENABLE);
+ inno_write(inno, STF_INNO_RX_CONTROL, STF_INNO_RX_ENABLE);
+
+ inno_hdmi_phy_pre_pll_power_down(&inno->pre_pll, true);
+ inno_hdmi_phy_pre_pll_configure(&inno->pre_pll, cfg);
+ inno_hdmi_phy_pre_pll_power_down(&inno->pre_pll, false);
+
+ inno->pixclock = rate;
+ inno->tmdsclock = cfg->tmdsclock;
+
+ return 0;
+}
+
+static const struct clk_ops starfive_hdmi_phy_clk_ops = {
+ .prepare = starfive_hdmi_phy_clk_prepare,
+ .unprepare = starfive_hdmi_phy_clk_unprepare,
+ .is_prepared = starfive_hdmi_phy_clk_is_prepared,
+ .recalc_rate = starfive_hdmi_phy_clk_recalc_rate,
+ .determine_rate = starfive_hdmi_phy_clk_determine_rate,
+ .set_rate = starfive_hdmi_phy_clk_set_rate,
+};
+
+static int starfive_hdmi_phy_power_on(struct phy *phy)
+{
+ struct starfive_hdmi_phy *inno = phy_get_drvdata(phy);
+ const struct post_pll_config *cfg = post_pll_cfg_table;
+ const struct inno_hdmi_phy_pre_pll_config *pre_cfg;
+ unsigned long tmdsclock;
+ u8 reg_1ad_value;
+ u8 reg_1aa_value;
+
+ u32 v;
+ int ret;
+
+ tmdsclock = clk_get_rate(inno->phyclk);
+ pre_cfg = inno_hdmi_phy_pre_pll_lookup(&inno->pre_pll, tmdsclock,
+ tmdsclock);
+ if (IS_ERR(pre_cfg)) {
+ dev_err(inno->dev, "no pre-PLL config for current pixel clock\n");
+ return PTR_ERR(pre_cfg);
+ }
+ tmdsclock = pre_cfg->tmdsclock;
+ inno->tmdsclock = tmdsclock;
+
+ inno_update_bits(inno, STF_INNO_BIAS_CONTROL,
+ STF_INNO_BIAS_ENABLE, STF_INNO_BIAS_ENABLE);
+ inno_write(inno, STF_INNO_RX_CONTROL, STF_INNO_RX_ENABLE);
+
+ /* Find Post-PLL config */
+ for (; cfg->tmdsclock != 0; cfg++)
+ if (tmdsclock <= cfg->tmdsclock)
+ break;
+
+ if (cfg->tmdsclock == 0) {
+ dev_err(inno->dev, "Failed to find Post-PLL config\n");
+ return -EINVAL;
+ }
+ dev_dbg(inno->dev, "Inno HDMI PHY Power On: pixclk %lu, tmdsclk %lu\n",
+ inno->pixclock, tmdsclock);
+
+ reg_1ad_value = cfg->post_div_en ? cfg->postdiv : 0x00;
+ reg_1aa_value = cfg->post_div_en ? 0x0e : 0x02;
+
+ /*
+ * Pre-PLL is already prepared and running at inno->pixclock
+ * via the clk_set_rate and prepare calls from the controller/bridge.
+ * Now, configure and enable the Post-PLL and TMDS outputs.
+ */
+
+ inno_write(inno, STF_INNO_POST_PLL_DIV_2,
+ STF_INNO_POST_PLL_PRE_DIV(cfg->prediv));
+ inno_write(inno, STF_INNO_POST_PLL_DIV_3, cfg->fbdiv & 0xff);
+ inno_write(inno, STF_INNO_POST_PLL_DIV_4, reg_1ad_value);
+
+ /* Power up Post-PLL */
+ inno_write(inno, STF_INNO_POST_PLL_DIV_1, reg_1aa_value);
+
+ /* Wait for post PLL lock */
+ ret = inno_poll(inno, STF_INNO_POST_PLL_LOCK_STATUS, v,
+ v & STF_INNO_POST_PLL_LOCK, 1000, 100000);
+ if (ret) {
+ dev_err(inno->dev, "Post-PLL locking failed\n");
+ return ret;
+ }
+
+ inno_write(inno, STF_INNO_LDO_CONTROL, STF_INNO_LDO_ENABLE);
+ inno_write(inno, STF_INNO_SERIALIER_CONTROL,
+ STF_INNO_SERIALIER_ENABLE);
+ inno_write(inno, STF_INNO_TMDS_CONTROL, 0x8f);
+
+ return 0;
+}
+
+static int starfive_hdmi_phy_power_off(struct phy *phy)
+{
+ struct starfive_hdmi_phy *inno = phy_get_drvdata(phy);
+
+ dev_dbg(inno->dev, "Inno HDMI PHY Power Off\n");
+
+ inno_write(inno, STF_INNO_TMDS_CONTROL, 0x00);
+ inno_write(inno, STF_INNO_SERIALIER_CONTROL, 0x00);
+ inno_write(inno, STF_INNO_LDO_CONTROL, 0x00);
+ inno_update_bits(inno, STF_INNO_BIAS_CONTROL,
+ STF_INNO_BIAS_ENABLE, 0x00);
+ inno_write(inno, STF_INNO_RX_CONTROL, 0x00);
+
+ /* Power down Post-PLL */
+ inno_update_bits(inno, STF_INNO_POST_PLL_DIV_1,
+ STF_INNO_POST_PLL_POWER_DOWN,
+ STF_INNO_POST_PLL_POWER_DOWN);
+
+ inno->tmdsclock = 0;
+ inno->pixclock = 0;
+
+ return 0;
+}
+
+static const struct phy_ops starfive_hdmi_phy_ops = {
+ .owner = THIS_MODULE,
+ .power_on = starfive_hdmi_phy_power_on,
+ .power_off = starfive_hdmi_phy_power_off,
+};
+
+static int starfive_hdmi_phy_probe(struct platform_device *pdev)
+{
+ struct device *dev = &pdev->dev;
+ struct device *parent = dev->parent;
+ struct starfive_hdmi_phy *inno;
+ struct phy_provider *phy_provider;
+ struct regmap *regmap;
+ struct clk_init_data init = {};
+ const char *refoclk_name;
+ int ret;
+
+ inno = devm_kzalloc(dev, sizeof(*inno), GFP_KERNEL);
+ if (!inno)
+ return -ENOMEM;
+
+ inno->dev = dev;
+
+ /* Get the regmap from the parent device */
+ regmap = dev_get_regmap(parent, NULL);
+ if (!regmap) {
+ dev_err(dev, "Failed to get parent regmap\n");
+ return -ENODEV;
+ }
+ inno->regmap = regmap;
+
+ /*
+ * The PHY block sits behind the HDMI controller in the shared register
+ * space, so the common pre-PLL helpers need a 0x100 register offset.
+ */
+ inno->pre_pll.regmap = regmap;
+ inno->pre_pll.offset = 0x100;
+ inno->pre_pll.table = pre_pll_cfg_table;
+
+ /* Get the input reference clock */
+ inno->refoclk = devm_clk_get(inno->dev, "refoclk");
+ if (IS_ERR(inno->refoclk)) {
+ ret = PTR_ERR(inno->refoclk);
+ dev_err(inno->dev, "failed to get oscillator-ref clock: %d\n",
+ ret);
+ return ret;
+ }
+
+ /* We must prepare/enable refoclk here so .set_rate/.recalc_rate work */
+ ret = clk_prepare_enable(inno->refoclk);
+ if (ret) {
+ dev_err(dev, "Failed to enable refoclk: %d\n", ret);
+ return ret;
+ }
+
+ platform_set_drvdata(pdev, inno);
+
+ /* Initialize and register the clock provider */
+ refoclk_name = __clk_get_name(inno->refoclk);
+ init.parent_names = &refoclk_name;
+ init.num_parents = 1;
+ init.flags = 0;
+ init.name = "hdmi_pclk";
+ init.ops = &starfive_hdmi_phy_clk_ops;
+
+ of_property_read_string(dev->of_node, "clock-output-names", &init.name);
+
+ inno->hw.init = &init;
+ inno->phyclk = devm_clk_register(dev, &inno->hw);
+ if (IS_ERR(inno->phyclk)) {
+ ret = PTR_ERR(inno->phyclk);
+ dev_err(dev, "Failed to register clock provider: %d\n", ret);
+ goto err_disable_refoclk;
+ }
+
+ ret = of_clk_add_provider(dev->of_node, of_clk_src_simple_get, inno->phyclk);
+ if (ret) {
+ dev_err(dev, "Failed to add clock provider: %d\n", ret);
+ goto err_disable_refoclk;
+ }
+
+ ret = clk_set_rate(inno->phyclk, 297000000);
+ if (ret) {
+ dev_err(dev, "Failed to set default rate: %d\n", ret);
+ goto err_disable_refoclk;
+ }
+
+ /* Create and register the PHY provider */
+ inno->phy = devm_phy_create(inno->dev, NULL, &starfive_hdmi_phy_ops);
+ if (IS_ERR(inno->phy)) {
+ ret = PTR_ERR(inno->phy);
+ dev_err(inno->dev, "failed to create HDMI PHY: %d\n", ret);
+ goto err_del_clk_provider;
+ }
+
+ phy_set_drvdata(inno->phy, inno);
+
+ phy_provider = devm_of_phy_provider_register(inno->dev,
+ of_phy_simple_xlate);
+ ret = PTR_ERR_OR_ZERO(phy_provider);
+ if (ret)
+ goto err_del_clk_provider;
+
+ return 0;
+
+err_del_clk_provider:
+ of_clk_del_provider(dev->of_node);
+err_disable_refoclk:
+ clk_disable_unprepare(inno->refoclk);
+ return ret;
+}
+
+static void starfive_hdmi_phy_remove(struct platform_device *pdev)
+{
+ struct starfive_hdmi_phy *inno = platform_get_drvdata(pdev);
+
+ of_clk_del_provider(pdev->dev.of_node);
+ clk_disable_unprepare(inno->refoclk);
+}
+
+static const struct of_device_id starfive_hdmi_phy_of_match[] = {
+ { .compatible = "starfive,jh7110-inno-hdmi-phy", },
+ { /* sentinel */ }
+};
+MODULE_DEVICE_TABLE(of, starfive_hdmi_phy_of_match);
+
+static struct platform_driver starfive_hdmi_phy_driver = {
+ .probe = starfive_hdmi_phy_probe,
+ .remove = starfive_hdmi_phy_remove,
+ .driver = {
+ .name = "starfive-inno-hdmi-phy",
+ .of_match_table = starfive_hdmi_phy_of_match,
+ },
+};
+module_platform_driver(starfive_hdmi_phy_driver);
+
+MODULE_AUTHOR("Michal Wilczynski <m.wilczynski@samsung.com>");
+MODULE_DESCRIPTION("StarFive JH7110 Innosilicon HDMI PHY Driver");
+MODULE_LICENSE("GPL");
--
2.34.1
_______________________________________________
Linux-rockchip mailing list
Linux-rockchip@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-rockchip
^ permalink raw reply related [flat|nested] 116+ messages in thread
* [PATCH v2 13/15] phy: starfive: Add jh7110-inno-hdmi-phy driver
@ 2026-08-28 13:47 ` Michal Wilczynski
0 siblings, 0 replies; 116+ messages in thread
From: Michal Wilczynski @ 2026-08-28 13:47 UTC (permalink / raw)
To: Vinod Koul, Neil Armstrong, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Andrzej Hajda, Robert Foss, Laurent Pinchart,
Jonas Karlman, Jernej Skrabec, Luca Ceresoli, David Airlie,
Simona Vetter, Maarten Lankhorst, Maxime Ripard,
Thomas Zimmermann, Lee Jones, Andy Yan, Philipp Zabel,
Emil Renner Berthing, Hal Feng, Michael Turquette, Stephen Boyd,
Brian Masney, Heiko Stuebner, Conor Dooley, Paul Walmsley,
Palmer Dabbelt, Albert Ou, Alexandre Ghiti, Dominique Belhachemi
Cc: linux-phy, devicetree, linux-kernel, dri-devel, mfd, linux-clk,
linux-arm-kernel, linux-rockchip, linux-riscv, Icenowy Zheng,
Andy Yan, Marek Szyprowski, Maud Spierings, Graham Markall,
Michal Wilczynski
Add the HDMI PHY driver for the StarFive JH7110.
This driver binds to the starfive,jh7110-inno-hdmi-phy node and
gets its regmap from the parent. It has no dependencies on voutcrg, only
on its refoclk (xin24m), which breaks the probe-time circular
dependency.
This driver provides two main functions:
- Clock Provider: It registers clk_ops to provide the variable pixel
clock (hdmi_pclk). The .set_rate operation configures the Pre-PLL
registers (0x1a0+) based on the requested rate.
- PHY Provider: It registers phy_ops for the controller. The .power_on
op configures and enables the Post-PLL and other analog blocks (BIAS,
LDO, Serializer, etc.).
The JH7110 instantiates the same Innosilicon IP as the Rockchip RK3328,
with the PHY register block shifted by 0x100 because it sits behind the
HDMI controller in the shared register space. The pre-PLL programming
therefore comes from the common Innosilicon helpers; this driver adds
the JH7110 pixel clock table, the post-PLL and the analog configuration.
Co-developed-by: Dominique Belhachemi <db@domibel.de>
Signed-off-by: Dominique Belhachemi <db@domibel.de>
Signed-off-by: Michal Wilczynski <m.wilczynski@samsung.com>
---
drivers/phy/starfive/Kconfig | 20 +
drivers/phy/starfive/Makefile | 1 +
drivers/phy/starfive/phy-jh7110-inno-hdmi.c | 567 ++++++++++++++++++++++++++++
3 files changed, 588 insertions(+)
diff --git a/drivers/phy/starfive/Kconfig b/drivers/phy/starfive/Kconfig
index d0cdd7cb4a13de22ff643c89a79d99cce57284d7..1da417ffbf224c13224e42a3ce322e3d0c272824 100644
--- a/drivers/phy/starfive/Kconfig
+++ b/drivers/phy/starfive/Kconfig
@@ -25,6 +25,26 @@ config PHY_STARFIVE_JH7110_DPHY_TX
system. If M is selected, the module will be called
phy-jh7110-dphy-tx.ko.
+config PHY_STARFIVE_JH7110_INNO_HDMI
+ tristate "Starfive JH7110 INNO HDMI PHY"
+ select PHY_INNO_HDMI
+ depends on COMMON_CLK
+ select GENERIC_PHY
+ help
+ This option enables the driver for the analog HDMI PHY (Physical
+ Layer) on the StarFive JH7110 SoC.
+
+ This driver binds to a child node of the 'starfive,jh7110-hdmi-subsystem'
+ parent driver and gets its register map from that parent.
+
+ It is responsible for two main functions:
+ 1. PHY Provider: It provides standard PHY operations (.power_on,
+ .power_off) for the HDMI controller (bridge) driver. This
+ involves configuring the Post-PLL and analog TMDS blocks.
+ 2. Clock Provider: It registers as a clock provider to supply the
+ variable pixel clock (hdmi_pclk) to the HDMI controller and
+ the VOUT subsystem, which it generates using the Pre-PLL.
+
config PHY_STARFIVE_JH7110_PCIE
tristate "Starfive JH7110 PCIE 2.0/USB 3.0 PHY support"
depends on HAS_IOMEM
diff --git a/drivers/phy/starfive/Makefile b/drivers/phy/starfive/Makefile
index eedc4a6fec156320c99ac0a0da609083b6a6a695..e7b13f00880b500f933f21b6037384d5c6884e3e 100644
--- a/drivers/phy/starfive/Makefile
+++ b/drivers/phy/starfive/Makefile
@@ -1,5 +1,6 @@
# SPDX-License-Identifier: GPL-2.0
obj-$(CONFIG_PHY_STARFIVE_JH7110_DPHY_RX) += phy-jh7110-dphy-rx.o
obj-$(CONFIG_PHY_STARFIVE_JH7110_DPHY_TX) += phy-jh7110-dphy-tx.o
+obj-$(CONFIG_PHY_STARFIVE_JH7110_INNO_HDMI) += phy-jh7110-inno-hdmi.o
obj-$(CONFIG_PHY_STARFIVE_JH7110_PCIE) += phy-jh7110-pcie.o
obj-$(CONFIG_PHY_STARFIVE_JH7110_USB) += phy-jh7110-usb.o
diff --git a/drivers/phy/starfive/phy-jh7110-inno-hdmi.c b/drivers/phy/starfive/phy-jh7110-inno-hdmi.c
new file mode 100644
index 0000000000000000000000000000000000000000..f4c4d76a38754d5edd4d80895481560c9650f3e7
--- /dev/null
+++ b/drivers/phy/starfive/phy-jh7110-inno-hdmi.c
@@ -0,0 +1,567 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (c) 2017 Rockchip Electronics Co. Ltd.
+ * Copyright (c) 2025 Samsung Electronics Co., Ltd.
+ *
+ * Author: Zheng Yang <zhengyang@rock-chips.com>
+ * Author: Michal Wilczynski <m.wilczynski@samsung.com>
+ *
+ * The register layout and programming sequence derive from
+ * drivers/phy/rockchip/phy-rockchip-inno-hdmi.c; the JH7110 places the
+ * same Innosilicon PHY block at a 0x100 register offset.
+ *
+ * This driver handles the PHY portion of the StarFive Innosilicon HDMI IP,
+ * which is part of a monolithic HDMI block. It provides the variable pixel
+ * clock (from the Pre-PLL) and the PHY operations (for the Post-PLL/analog).
+ */
+
+#include <linux/bitfield.h>
+#include <linux/bits.h>
+#include <linux/clk.h>
+#include <linux/clk-provider.h>
+#include <linux/delay.h>
+#include <linux/io.h>
+#include <linux/iopoll.h>
+#include <linux/math64.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
+#include <linux/regmap.h>
+#include <linux/phy/inno-hdmi-phy.h>
+#include <linux/phy/phy.h>
+#include <linux/slab.h>
+
+/*
+ * StarFive (JH7110) Innosilicon HDMI PHY Register Definitions
+ */
+
+/* REG: 0x1aa */
+#define STF_INNO_POST_PLL_DIV_1 0x1aa
+#define STF_INNO_POST_PLL_POST_DIV_ENABLE GENMASK(3, 2)
+#define STF_INNO_POST_PLL_REFCLK_SEL_TMDS BIT(1)
+#define STF_INNO_POST_PLL_POWER_DOWN BIT(0)
+
+/* REG: 0x1ab */
+#define STF_INNO_POST_PLL_DIV_2 0x1ab
+#define STF_INNO_POST_PLL_PRE_DIV(x) FIELD_PREP(GENMASK(5, 0), x)
+#define STF_INNO_POST_PLL_FB_DIV_8(x) FIELD_PREP(BIT(7), (x) >> 8)
+
+/* REG: 0x1ac */
+#define STF_INNO_POST_PLL_DIV_3 0x1ac
+#define STF_INNO_POST_PLL_FB_DIV_7_0(x) FIELD_PREP(GENMASK(7, 0), x)
+
+/* REG: 0x1ad */
+#define STF_INNO_POST_PLL_DIV_4 0x1ad
+#define STF_INNO_POST_PLL_POST_DIV_MASK GENMASK(1, 0)
+
+/* REG: 0x1af */
+#define STF_INNO_POST_PLL_LOCK_STATUS 0x1af
+#define STF_INNO_POST_PLL_LOCK BIT(0)
+
+/* REG: 0x1b0 */
+#define STF_INNO_BIAS_CONTROL 0x1b0
+#define STF_INNO_BIAS_ENABLE BIT(2)
+
+/* REG: 0x1b2 */
+#define STF_INNO_TMDS_CONTROL 0x1b2
+#define STF_INNO_TMDS_CLK_DRIVER_EN BIT(3)
+#define STF_INNO_TMDS_D2_DRIVER_EN BIT(2)
+#define STF_INNO_TMDS_D1_DRIVER_EN BIT(1)
+#define STF_INNO_TMDS_D0_DRIVER_EN BIT(0)
+#define STF_INNO_TMDS_DRIVER_ENABLE (STF_INNO_TMDS_CLK_DRIVER_EN | \
+ STF_INNO_TMDS_D2_DRIVER_EN | \
+ STF_INNO_TMDS_D1_DRIVER_EN | \
+ STF_INNO_TMDS_D0_DRIVER_EN)
+
+/* REG: 0x1b4 */
+#define STF_INNO_LDO_CONTROL 0x1b4
+#define STF_INNO_LDO_ENABLE (BIT(2) | BIT(1) | BIT(0))
+
+/* REG: 0x1be */
+#define STF_INNO_SERIALIER_CONTROL 0x1be
+#define STF_INNO_SERIALIER_ENABLE (BIT(6) | BIT(5) | BIT(4) | BIT(0))
+
+/* REG: 0x1cc */
+#define STF_INNO_RX_CONTROL 0x1cc
+#define STF_INNO_RX_ENABLE (BIT(3) | BIT(2) | BIT(1) | BIT(0))
+
+/*
+ * These tables are copied from the monolithic driver.
+ * They match the Rockchip PHY driver tables.
+ */
+
+struct post_pll_config {
+ unsigned long tmdsclock;
+ u8 prediv;
+ u16 fbdiv;
+ u8 postdiv;
+ u8 post_div_en;
+};
+
+static const struct inno_hdmi_phy_pre_pll_config pre_pll_cfg_table[] = {
+ { 25175000, 25175000, 1, 100, 2, 3, 3, 12, 3, 3, 4, 0, 0xF55555 },
+ { 25200000, 25200000, 1, 100, 2, 3, 3, 12, 3, 3, 4, 0, 0 },
+ { 27000000, 27000000, 1, 90, 3, 2, 2, 10, 3, 3, 4, 0, 0 },
+ { 27027000, 27027000, 1, 90, 3, 2, 2, 10, 3, 3, 4, 0, 0x170A3D },
+ { 28320000, 28320000, 1, 28, 2, 1, 1, 3, 0, 3, 4, 0, 0x51EB85 },
+ { 30240000, 30240000, 1, 30, 2, 1, 1, 3, 0, 3, 4, 0, 0x3D70A3 },
+ { 31500000, 31500000, 1, 31, 2, 1, 1, 3, 0, 3, 4, 0, 0x7FFFFF },
+ { 33750000, 33750000, 1, 33, 2, 1, 1, 3, 0, 3, 4, 0, 0xCFFFFF },
+ { 36000000, 36000000, 1, 36, 2, 1, 1, 3, 0, 3, 4, 0, 0 },
+ { 40000000, 40000000, 1, 80, 2, 2, 2, 12, 2, 2, 2, 0, 0 },
+ { 46970000, 46970000, 1, 46, 2, 1, 1, 3, 0, 3, 4, 0, 0xF851EB },
+ { 49500000, 49500000, 1, 49, 2, 1, 1, 3, 0, 3, 4, 0, 0x7FFFFF },
+ { 49000000, 49000000, 1, 49, 2, 1, 1, 3, 0, 3, 4, 0, 0 },
+ { 50000000, 50000000, 1, 50, 2, 1, 1, 3, 0, 3, 4, 0, 0 },
+ { 54000000, 54000000, 1, 54, 2, 1, 1, 3, 0, 3, 4, 0, 0 },
+ { 54054000, 54054000, 1, 54, 2, 1, 1, 3, 0, 3, 4, 0, 0x0DD2F1 },
+ { 57284000, 57284000, 1, 57, 2, 1, 1, 3, 0, 3, 4, 0, 0x48B439 },
+ { 58230000, 58230000, 1, 58, 2, 1, 1, 3, 0, 3, 4, 0, 0x3AE147 },
+ { 59341000, 59341000, 1, 59, 2, 1, 1, 3, 0, 3, 4, 0, 0x574BC6 },
+ { 59400000, 59400000, 1, 99, 3, 1, 1, 1, 3, 3, 4, 0, 0 },
+ { 65000000, 65000000, 1, 130, 2, 2, 2, 12, 0, 2, 2, 0, 0 },
+ { 68250000, 68250000, 1, 68, 2, 1, 1, 3, 0, 3, 4, 0, 0x3FFFFF },
+ { 71000000, 71000000, 1, 71, 2, 1, 1, 3, 0, 3, 4, 0, 0 },
+ { 74176000, 74176000, 1, 98, 1, 2, 2, 1, 2, 3, 4, 0, 0xE6AE6B },
+ { 74250000, 74250000, 1, 99, 1, 2, 2, 1, 2, 3, 4, 0, 0 },
+ { 75000000, 75000000, 1, 75, 2, 1, 1, 3, 0, 3, 4, 0, 0 },
+ { 78750000, 78750000, 1, 78, 2, 1, 1, 3, 0, 3, 4, 0, 0xCFFFFF },
+ { 79500000, 79500000, 1, 79, 2, 1, 1, 3, 0, 3, 4, 0, 0x7FFFFF },
+ { 83500000, 83500000, 2, 167, 2, 1, 1, 1, 0, 0, 6, 0, 0 },
+ { 83500000, 104375000, 1, 104, 2, 1, 1, 1, 1, 0, 5, 0, 0x600000 },
+ { 85500000, 85500000, 1, 85, 2, 1, 1, 3, 0, 3, 4, 0, 0x7FFFFF },
+ { 85750000, 85750000, 1, 85, 2, 1, 1, 3, 0, 3, 4, 0, 0xCFFFFF },
+ { 85800000, 85800000, 1, 85, 2, 1, 1, 3, 0, 3, 4, 0, 0xCCCCCC },
+ { 88750000, 88750000, 1, 88, 2, 1, 1, 3, 0, 3, 4, 0, 0xCFFFFF },
+ { 89910000, 89910000, 1, 89, 2, 1, 1, 3, 0, 3, 4, 0, 0xE8F5C1 },
+ { 90000000, 90000000, 1, 90, 2, 1, 1, 3, 0, 3, 4, 0, 0 },
+ { 101000000, 101000000, 1, 101, 2, 1, 1, 3, 0, 3, 4, 0, 0 },
+ { 102250000, 102250000, 1, 102, 2, 1, 1, 3, 0, 3, 4, 0, 0x3FFFFF },
+ { 106500000, 106500000, 1, 106, 2, 1, 1, 3, 0, 3, 4, 0, 0x7FFFFF },
+ { 108000000, 108000000, 1, 90, 3, 0, 0, 5, 0, 2, 2, 0, 0 },
+ { 119000000, 119000000, 1, 119, 2, 1, 1, 3, 0, 3, 4, 0, 0 },
+ { 131481000, 131481000, 1, 131, 2, 1, 1, 3, 0, 3, 4, 0, 0x7B22D1 },
+ { 135000000, 135000000, 1, 135, 2, 1, 1, 3, 0, 3, 4, 0, 0 },
+ { 136750000, 136750000, 1, 136, 2, 1, 1, 3, 0, 3, 4, 0, 0xCFFFFF },
+ { 147180000, 147180000, 1, 147, 2, 1, 1, 3, 0, 3, 4, 0, 0x2E147A },
+ { 148352000, 148352000, 1, 98, 1, 1, 1, 1, 2, 2, 2, 0, 0xE6AE6B },
+ { 148500000, 148500000, 1, 99, 1, 1, 1, 1, 2, 2, 2, 0, 0 },
+ { 154000000, 154000000, 1, 154, 2, 1, 1, 3, 0, 3, 4, 0, 0 },
+ { 156000000, 156000000, 1, 156, 2, 1, 1, 3, 0, 3, 4, 0, 0 },
+ { 157000000, 157000000, 1, 157, 2, 1, 1, 3, 0, 3, 4, 0, 0 },
+ { 162000000, 162000000, 1, 162, 2, 1, 1, 3, 0, 3, 4, 0, 0 },
+ { 174250000, 174250000, 1, 145, 3, 0, 0, 5, 0, 2, 2, 0, 0x355555 },
+ { 174500000, 174500000, 1, 174, 2, 1, 1, 3, 0, 3, 4, 0, 0x7FFFFF },
+ { 174570000, 174570000, 1, 174, 2, 1, 1, 3, 0, 3, 4, 0, 0x91EB84 },
+ { 175500000, 175500000, 1, 175, 2, 1, 1, 3, 0, 3, 4, 0, 0x7FFFFF },
+ { 185590000, 185590000, 1, 185, 2, 1, 1, 3, 0, 3, 4, 0, 0x970A3C },
+ { 187000000, 187000000, 1, 187, 2, 1, 1, 3, 0, 3, 4, 0, 0 },
+ { 241500000, 241500000, 1, 161, 1, 1, 1, 4, 0, 2, 2, 0, 0 },
+ { 241700000, 241700000, 1, 241, 2, 1, 1, 3, 0, 3, 4, 0, 0xB33332 },
+ { 262750000, 262750000, 1, 262, 2, 1, 1, 3, 0, 3, 4, 0, 0xCFFFFF },
+ { 296500000, 296500000, 1, 296, 2, 1, 1, 3, 0, 3, 4, 0, 0x7FFFFF },
+ { 296703000, 296703000, 1, 98, 0, 1, 1, 1, 0, 2, 2, 0, 0xE6AE6B },
+ { 297000000, 297000000, 1, 99, 0, 1, 1, 1, 0, 2, 2, 0, 0 },
+ { 594000000, 594000000, 1, 99, 0, 2, 0, 1, 0, 1, 1, 0, 0 },
+ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
+};
+
+static const struct post_pll_config post_pll_cfg_table[] = {
+ { 25200000, 1, 80, 13, 3 },
+ { 27000000, 1, 40, 11, 3 },
+ { 27027000, 1, 40, 11, 3 },
+ { 33750000, 1, 40, 11, 3 },
+ { 49000000, 1, 20, 1, 3 },
+ { 65000000, 1, 20, 1, 3 },
+ { 74250000, 1, 20, 1, 3 },
+ { 88750000, 1, 20, 1, 3 },
+ { 108000000, 1, 20, 1, 3 },
+ { 148500000, 1, 20, 1, 3 },
+ { 162000000, 1, 20, 1, 3 },
+ { 174250000, 1, 20, 1, 3 },
+ { 187000000, 1, 20, 1, 3 },
+ { 241700000, 1, 20, 1, 3 },
+ { 297000000, 4, 20, 0, 0 },
+ { 594000000, 4, 20, 0, 0 }, /* postpll_postdiv_en = 0 */
+ { /* sentinel */ }
+};
+
+struct starfive_hdmi_phy {
+ struct device *dev;
+ struct regmap *regmap;
+ struct phy *phy;
+ struct clk *refoclk;
+
+ struct inno_hdmi_phy_pre_pll pre_pll;
+
+ struct clk_hw hw;
+ struct clk *phyclk;
+ unsigned long pixclock;
+ unsigned long tmdsclock;
+};
+
+static inline void inno_write(struct starfive_hdmi_phy *inno, u32 reg, u8 val)
+{
+ regmap_write(inno->regmap, reg * 4, val);
+}
+
+static inline u8 inno_read(struct starfive_hdmi_phy *inno, u32 reg)
+{
+ u32 val;
+
+ regmap_read(inno->regmap, reg * 4, &val);
+ return val;
+}
+
+static inline void inno_update_bits(struct starfive_hdmi_phy *inno, u16 reg,
+ u8 mask, u8 val)
+{
+ regmap_update_bits(inno->regmap, reg * 4, mask, val);
+}
+
+#define inno_poll(inno, reg, val, cond, sleep_us, timeout_us) \
+ regmap_read_poll_timeout((inno)->regmap, (reg) * 4, val, cond, \
+ sleep_us, timeout_us)
+
+static inline struct starfive_hdmi_phy *to_starfive_hdmi_phy(struct clk_hw *hw)
+{
+ return container_of(hw, struct starfive_hdmi_phy, hw);
+}
+
+static int starfive_hdmi_phy_clk_prepare(struct clk_hw *hw)
+{
+ struct starfive_hdmi_phy *inno = to_starfive_hdmi_phy(hw);
+ int ret;
+
+ inno_hdmi_phy_pre_pll_power_down(&inno->pre_pll, false);
+
+ if (inno_hdmi_phy_pre_pll_is_locked(&inno->pre_pll))
+ return 0;
+
+ ret = inno_hdmi_phy_pre_pll_wait_locked(&inno->pre_pll, 100000);
+ if (ret) {
+ dev_err(inno->dev, "Timeout waiting for pre-PLL lock\n");
+ inno_hdmi_phy_pre_pll_power_down(&inno->pre_pll, true);
+ return ret;
+ }
+
+ return 0;
+}
+
+static void starfive_hdmi_phy_clk_unprepare(struct clk_hw *hw)
+{
+ struct starfive_hdmi_phy *inno = to_starfive_hdmi_phy(hw);
+
+ inno_hdmi_phy_pre_pll_power_down(&inno->pre_pll, true);
+ inno->pixclock = 0; /* Invalidate cached rate */
+}
+
+static int starfive_hdmi_phy_clk_is_prepared(struct clk_hw *hw)
+{
+ struct starfive_hdmi_phy *inno = to_starfive_hdmi_phy(hw);
+
+ if (!inno_hdmi_phy_pre_pll_is_powered(&inno->pre_pll))
+ return 0;
+
+ return inno_hdmi_phy_pre_pll_is_locked(&inno->pre_pll);
+}
+
+static unsigned long starfive_hdmi_phy_clk_recalc_rate(struct clk_hw *hw,
+ unsigned long parent_rate)
+{
+ struct starfive_hdmi_phy *inno = to_starfive_hdmi_phy(hw);
+
+ if (!starfive_hdmi_phy_clk_is_prepared(hw))
+ return inno->pixclock;
+
+ inno->pixclock = inno_hdmi_phy_pre_pll_recalc_rate(&inno->pre_pll,
+ parent_rate);
+
+ return inno->pixclock;
+}
+
+static int starfive_hdmi_phy_clk_determine_rate(struct clk_hw *hw,
+ struct clk_rate_request *req)
+{
+ struct starfive_hdmi_phy *inno = to_starfive_hdmi_phy(hw);
+
+ return inno_hdmi_phy_pre_pll_determine_rate(&inno->pre_pll, req);
+}
+
+static int starfive_hdmi_phy_clk_set_rate(struct clk_hw *hw, unsigned long rate,
+ unsigned long parent_rate)
+{
+ struct starfive_hdmi_phy *inno = to_starfive_hdmi_phy(hw);
+ const struct inno_hdmi_phy_pre_pll_config *cfg;
+
+ /*
+ * The JH7110 only drives 8bpc, so the TMDS clock always matches the
+ * pixel clock.
+ */
+ cfg = inno_hdmi_phy_pre_pll_lookup(&inno->pre_pll, rate, rate);
+ if (IS_ERR(cfg))
+ return PTR_ERR(cfg);
+
+ dev_dbg(inno->dev, "%s rate %lu tmdsclk %lu\n",
+ __func__, rate, cfg->tmdsclock);
+
+ if (inno->pixclock == rate && inno->tmdsclock == cfg->tmdsclock)
+ return 0;
+
+ inno_update_bits(inno, STF_INNO_BIAS_CONTROL,
+ STF_INNO_BIAS_ENABLE, STF_INNO_BIAS_ENABLE);
+ inno_write(inno, STF_INNO_RX_CONTROL, STF_INNO_RX_ENABLE);
+
+ inno_hdmi_phy_pre_pll_power_down(&inno->pre_pll, true);
+ inno_hdmi_phy_pre_pll_configure(&inno->pre_pll, cfg);
+ inno_hdmi_phy_pre_pll_power_down(&inno->pre_pll, false);
+
+ inno->pixclock = rate;
+ inno->tmdsclock = cfg->tmdsclock;
+
+ return 0;
+}
+
+static const struct clk_ops starfive_hdmi_phy_clk_ops = {
+ .prepare = starfive_hdmi_phy_clk_prepare,
+ .unprepare = starfive_hdmi_phy_clk_unprepare,
+ .is_prepared = starfive_hdmi_phy_clk_is_prepared,
+ .recalc_rate = starfive_hdmi_phy_clk_recalc_rate,
+ .determine_rate = starfive_hdmi_phy_clk_determine_rate,
+ .set_rate = starfive_hdmi_phy_clk_set_rate,
+};
+
+static int starfive_hdmi_phy_power_on(struct phy *phy)
+{
+ struct starfive_hdmi_phy *inno = phy_get_drvdata(phy);
+ const struct post_pll_config *cfg = post_pll_cfg_table;
+ const struct inno_hdmi_phy_pre_pll_config *pre_cfg;
+ unsigned long tmdsclock;
+ u8 reg_1ad_value;
+ u8 reg_1aa_value;
+
+ u32 v;
+ int ret;
+
+ tmdsclock = clk_get_rate(inno->phyclk);
+ pre_cfg = inno_hdmi_phy_pre_pll_lookup(&inno->pre_pll, tmdsclock,
+ tmdsclock);
+ if (IS_ERR(pre_cfg)) {
+ dev_err(inno->dev, "no pre-PLL config for current pixel clock\n");
+ return PTR_ERR(pre_cfg);
+ }
+ tmdsclock = pre_cfg->tmdsclock;
+ inno->tmdsclock = tmdsclock;
+
+ inno_update_bits(inno, STF_INNO_BIAS_CONTROL,
+ STF_INNO_BIAS_ENABLE, STF_INNO_BIAS_ENABLE);
+ inno_write(inno, STF_INNO_RX_CONTROL, STF_INNO_RX_ENABLE);
+
+ /* Find Post-PLL config */
+ for (; cfg->tmdsclock != 0; cfg++)
+ if (tmdsclock <= cfg->tmdsclock)
+ break;
+
+ if (cfg->tmdsclock == 0) {
+ dev_err(inno->dev, "Failed to find Post-PLL config\n");
+ return -EINVAL;
+ }
+ dev_dbg(inno->dev, "Inno HDMI PHY Power On: pixclk %lu, tmdsclk %lu\n",
+ inno->pixclock, tmdsclock);
+
+ reg_1ad_value = cfg->post_div_en ? cfg->postdiv : 0x00;
+ reg_1aa_value = cfg->post_div_en ? 0x0e : 0x02;
+
+ /*
+ * Pre-PLL is already prepared and running at inno->pixclock
+ * via the clk_set_rate and prepare calls from the controller/bridge.
+ * Now, configure and enable the Post-PLL and TMDS outputs.
+ */
+
+ inno_write(inno, STF_INNO_POST_PLL_DIV_2,
+ STF_INNO_POST_PLL_PRE_DIV(cfg->prediv));
+ inno_write(inno, STF_INNO_POST_PLL_DIV_3, cfg->fbdiv & 0xff);
+ inno_write(inno, STF_INNO_POST_PLL_DIV_4, reg_1ad_value);
+
+ /* Power up Post-PLL */
+ inno_write(inno, STF_INNO_POST_PLL_DIV_1, reg_1aa_value);
+
+ /* Wait for post PLL lock */
+ ret = inno_poll(inno, STF_INNO_POST_PLL_LOCK_STATUS, v,
+ v & STF_INNO_POST_PLL_LOCK, 1000, 100000);
+ if (ret) {
+ dev_err(inno->dev, "Post-PLL locking failed\n");
+ return ret;
+ }
+
+ inno_write(inno, STF_INNO_LDO_CONTROL, STF_INNO_LDO_ENABLE);
+ inno_write(inno, STF_INNO_SERIALIER_CONTROL,
+ STF_INNO_SERIALIER_ENABLE);
+ inno_write(inno, STF_INNO_TMDS_CONTROL, 0x8f);
+
+ return 0;
+}
+
+static int starfive_hdmi_phy_power_off(struct phy *phy)
+{
+ struct starfive_hdmi_phy *inno = phy_get_drvdata(phy);
+
+ dev_dbg(inno->dev, "Inno HDMI PHY Power Off\n");
+
+ inno_write(inno, STF_INNO_TMDS_CONTROL, 0x00);
+ inno_write(inno, STF_INNO_SERIALIER_CONTROL, 0x00);
+ inno_write(inno, STF_INNO_LDO_CONTROL, 0x00);
+ inno_update_bits(inno, STF_INNO_BIAS_CONTROL,
+ STF_INNO_BIAS_ENABLE, 0x00);
+ inno_write(inno, STF_INNO_RX_CONTROL, 0x00);
+
+ /* Power down Post-PLL */
+ inno_update_bits(inno, STF_INNO_POST_PLL_DIV_1,
+ STF_INNO_POST_PLL_POWER_DOWN,
+ STF_INNO_POST_PLL_POWER_DOWN);
+
+ inno->tmdsclock = 0;
+ inno->pixclock = 0;
+
+ return 0;
+}
+
+static const struct phy_ops starfive_hdmi_phy_ops = {
+ .owner = THIS_MODULE,
+ .power_on = starfive_hdmi_phy_power_on,
+ .power_off = starfive_hdmi_phy_power_off,
+};
+
+static int starfive_hdmi_phy_probe(struct platform_device *pdev)
+{
+ struct device *dev = &pdev->dev;
+ struct device *parent = dev->parent;
+ struct starfive_hdmi_phy *inno;
+ struct phy_provider *phy_provider;
+ struct regmap *regmap;
+ struct clk_init_data init = {};
+ const char *refoclk_name;
+ int ret;
+
+ inno = devm_kzalloc(dev, sizeof(*inno), GFP_KERNEL);
+ if (!inno)
+ return -ENOMEM;
+
+ inno->dev = dev;
+
+ /* Get the regmap from the parent device */
+ regmap = dev_get_regmap(parent, NULL);
+ if (!regmap) {
+ dev_err(dev, "Failed to get parent regmap\n");
+ return -ENODEV;
+ }
+ inno->regmap = regmap;
+
+ /*
+ * The PHY block sits behind the HDMI controller in the shared register
+ * space, so the common pre-PLL helpers need a 0x100 register offset.
+ */
+ inno->pre_pll.regmap = regmap;
+ inno->pre_pll.offset = 0x100;
+ inno->pre_pll.table = pre_pll_cfg_table;
+
+ /* Get the input reference clock */
+ inno->refoclk = devm_clk_get(inno->dev, "refoclk");
+ if (IS_ERR(inno->refoclk)) {
+ ret = PTR_ERR(inno->refoclk);
+ dev_err(inno->dev, "failed to get oscillator-ref clock: %d\n",
+ ret);
+ return ret;
+ }
+
+ /* We must prepare/enable refoclk here so .set_rate/.recalc_rate work */
+ ret = clk_prepare_enable(inno->refoclk);
+ if (ret) {
+ dev_err(dev, "Failed to enable refoclk: %d\n", ret);
+ return ret;
+ }
+
+ platform_set_drvdata(pdev, inno);
+
+ /* Initialize and register the clock provider */
+ refoclk_name = __clk_get_name(inno->refoclk);
+ init.parent_names = &refoclk_name;
+ init.num_parents = 1;
+ init.flags = 0;
+ init.name = "hdmi_pclk";
+ init.ops = &starfive_hdmi_phy_clk_ops;
+
+ of_property_read_string(dev->of_node, "clock-output-names", &init.name);
+
+ inno->hw.init = &init;
+ inno->phyclk = devm_clk_register(dev, &inno->hw);
+ if (IS_ERR(inno->phyclk)) {
+ ret = PTR_ERR(inno->phyclk);
+ dev_err(dev, "Failed to register clock provider: %d\n", ret);
+ goto err_disable_refoclk;
+ }
+
+ ret = of_clk_add_provider(dev->of_node, of_clk_src_simple_get, inno->phyclk);
+ if (ret) {
+ dev_err(dev, "Failed to add clock provider: %d\n", ret);
+ goto err_disable_refoclk;
+ }
+
+ ret = clk_set_rate(inno->phyclk, 297000000);
+ if (ret) {
+ dev_err(dev, "Failed to set default rate: %d\n", ret);
+ goto err_disable_refoclk;
+ }
+
+ /* Create and register the PHY provider */
+ inno->phy = devm_phy_create(inno->dev, NULL, &starfive_hdmi_phy_ops);
+ if (IS_ERR(inno->phy)) {
+ ret = PTR_ERR(inno->phy);
+ dev_err(inno->dev, "failed to create HDMI PHY: %d\n", ret);
+ goto err_del_clk_provider;
+ }
+
+ phy_set_drvdata(inno->phy, inno);
+
+ phy_provider = devm_of_phy_provider_register(inno->dev,
+ of_phy_simple_xlate);
+ ret = PTR_ERR_OR_ZERO(phy_provider);
+ if (ret)
+ goto err_del_clk_provider;
+
+ return 0;
+
+err_del_clk_provider:
+ of_clk_del_provider(dev->of_node);
+err_disable_refoclk:
+ clk_disable_unprepare(inno->refoclk);
+ return ret;
+}
+
+static void starfive_hdmi_phy_remove(struct platform_device *pdev)
+{
+ struct starfive_hdmi_phy *inno = platform_get_drvdata(pdev);
+
+ of_clk_del_provider(pdev->dev.of_node);
+ clk_disable_unprepare(inno->refoclk);
+}
+
+static const struct of_device_id starfive_hdmi_phy_of_match[] = {
+ { .compatible = "starfive,jh7110-inno-hdmi-phy", },
+ { /* sentinel */ }
+};
+MODULE_DEVICE_TABLE(of, starfive_hdmi_phy_of_match);
+
+static struct platform_driver starfive_hdmi_phy_driver = {
+ .probe = starfive_hdmi_phy_probe,
+ .remove = starfive_hdmi_phy_remove,
+ .driver = {
+ .name = "starfive-inno-hdmi-phy",
+ .of_match_table = starfive_hdmi_phy_of_match,
+ },
+};
+module_platform_driver(starfive_hdmi_phy_driver);
+
+MODULE_AUTHOR("Michal Wilczynski <m.wilczynski@samsung.com>");
+MODULE_DESCRIPTION("StarFive JH7110 Innosilicon HDMI PHY Driver");
+MODULE_LICENSE("GPL");
--
2.34.1
--
linux-phy mailing list
linux-phy@lists.infradead.org
https://lists.infradead.org/mailman/listinfo/linux-phy
^ permalink raw reply related [flat|nested] 116+ messages in thread
* [PATCH v2 13/15] phy: starfive: Add jh7110-inno-hdmi-phy driver
@ 2026-08-28 13:47 ` Michal Wilczynski
0 siblings, 0 replies; 116+ messages in thread
From: Michal Wilczynski @ 2026-08-28 13:47 UTC (permalink / raw)
To: Vinod Koul, Neil Armstrong, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Andrzej Hajda, Robert Foss, Laurent Pinchart,
Jonas Karlman, Jernej Skrabec, Luca Ceresoli, David Airlie,
Simona Vetter, Maarten Lankhorst, Maxime Ripard,
Thomas Zimmermann, Lee Jones, Andy Yan, Philipp Zabel,
Emil Renner Berthing, Hal Feng, Michael Turquette, Stephen Boyd,
Brian Masney, Heiko Stuebner, Conor Dooley, Paul Walmsley,
Palmer Dabbelt, Albert Ou, Alexandre Ghiti, Dominique Belhachemi
Cc: devicetree, mfd, linux-kernel, dri-devel, Andy Yan,
Graham Markall, linux-rockchip, linux-phy, Michal Wilczynski,
linux-riscv, Maud Spierings, linux-clk, linux-arm-kernel,
Marek Szyprowski
Add the HDMI PHY driver for the StarFive JH7110.
This driver binds to the starfive,jh7110-inno-hdmi-phy node and
gets its regmap from the parent. It has no dependencies on voutcrg, only
on its refoclk (xin24m), which breaks the probe-time circular
dependency.
This driver provides two main functions:
- Clock Provider: It registers clk_ops to provide the variable pixel
clock (hdmi_pclk). The .set_rate operation configures the Pre-PLL
registers (0x1a0+) based on the requested rate.
- PHY Provider: It registers phy_ops for the controller. The .power_on
op configures and enables the Post-PLL and other analog blocks (BIAS,
LDO, Serializer, etc.).
The JH7110 instantiates the same Innosilicon IP as the Rockchip RK3328,
with the PHY register block shifted by 0x100 because it sits behind the
HDMI controller in the shared register space. The pre-PLL programming
therefore comes from the common Innosilicon helpers; this driver adds
the JH7110 pixel clock table, the post-PLL and the analog configuration.
Co-developed-by: Dominique Belhachemi <db@domibel.de>
Signed-off-by: Dominique Belhachemi <db@domibel.de>
Signed-off-by: Michal Wilczynski <m.wilczynski@samsung.com>
---
drivers/phy/starfive/Kconfig | 20 +
drivers/phy/starfive/Makefile | 1 +
drivers/phy/starfive/phy-jh7110-inno-hdmi.c | 567 ++++++++++++++++++++++++++++
3 files changed, 588 insertions(+)
diff --git a/drivers/phy/starfive/Kconfig b/drivers/phy/starfive/Kconfig
index d0cdd7cb4a13de22ff643c89a79d99cce57284d7..1da417ffbf224c13224e42a3ce322e3d0c272824 100644
--- a/drivers/phy/starfive/Kconfig
+++ b/drivers/phy/starfive/Kconfig
@@ -25,6 +25,26 @@ config PHY_STARFIVE_JH7110_DPHY_TX
system. If M is selected, the module will be called
phy-jh7110-dphy-tx.ko.
+config PHY_STARFIVE_JH7110_INNO_HDMI
+ tristate "Starfive JH7110 INNO HDMI PHY"
+ select PHY_INNO_HDMI
+ depends on COMMON_CLK
+ select GENERIC_PHY
+ help
+ This option enables the driver for the analog HDMI PHY (Physical
+ Layer) on the StarFive JH7110 SoC.
+
+ This driver binds to a child node of the 'starfive,jh7110-hdmi-subsystem'
+ parent driver and gets its register map from that parent.
+
+ It is responsible for two main functions:
+ 1. PHY Provider: It provides standard PHY operations (.power_on,
+ .power_off) for the HDMI controller (bridge) driver. This
+ involves configuring the Post-PLL and analog TMDS blocks.
+ 2. Clock Provider: It registers as a clock provider to supply the
+ variable pixel clock (hdmi_pclk) to the HDMI controller and
+ the VOUT subsystem, which it generates using the Pre-PLL.
+
config PHY_STARFIVE_JH7110_PCIE
tristate "Starfive JH7110 PCIE 2.0/USB 3.0 PHY support"
depends on HAS_IOMEM
diff --git a/drivers/phy/starfive/Makefile b/drivers/phy/starfive/Makefile
index eedc4a6fec156320c99ac0a0da609083b6a6a695..e7b13f00880b500f933f21b6037384d5c6884e3e 100644
--- a/drivers/phy/starfive/Makefile
+++ b/drivers/phy/starfive/Makefile
@@ -1,5 +1,6 @@
# SPDX-License-Identifier: GPL-2.0
obj-$(CONFIG_PHY_STARFIVE_JH7110_DPHY_RX) += phy-jh7110-dphy-rx.o
obj-$(CONFIG_PHY_STARFIVE_JH7110_DPHY_TX) += phy-jh7110-dphy-tx.o
+obj-$(CONFIG_PHY_STARFIVE_JH7110_INNO_HDMI) += phy-jh7110-inno-hdmi.o
obj-$(CONFIG_PHY_STARFIVE_JH7110_PCIE) += phy-jh7110-pcie.o
obj-$(CONFIG_PHY_STARFIVE_JH7110_USB) += phy-jh7110-usb.o
diff --git a/drivers/phy/starfive/phy-jh7110-inno-hdmi.c b/drivers/phy/starfive/phy-jh7110-inno-hdmi.c
new file mode 100644
index 0000000000000000000000000000000000000000..f4c4d76a38754d5edd4d80895481560c9650f3e7
--- /dev/null
+++ b/drivers/phy/starfive/phy-jh7110-inno-hdmi.c
@@ -0,0 +1,567 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (c) 2017 Rockchip Electronics Co. Ltd.
+ * Copyright (c) 2025 Samsung Electronics Co., Ltd.
+ *
+ * Author: Zheng Yang <zhengyang@rock-chips.com>
+ * Author: Michal Wilczynski <m.wilczynski@samsung.com>
+ *
+ * The register layout and programming sequence derive from
+ * drivers/phy/rockchip/phy-rockchip-inno-hdmi.c; the JH7110 places the
+ * same Innosilicon PHY block at a 0x100 register offset.
+ *
+ * This driver handles the PHY portion of the StarFive Innosilicon HDMI IP,
+ * which is part of a monolithic HDMI block. It provides the variable pixel
+ * clock (from the Pre-PLL) and the PHY operations (for the Post-PLL/analog).
+ */
+
+#include <linux/bitfield.h>
+#include <linux/bits.h>
+#include <linux/clk.h>
+#include <linux/clk-provider.h>
+#include <linux/delay.h>
+#include <linux/io.h>
+#include <linux/iopoll.h>
+#include <linux/math64.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
+#include <linux/regmap.h>
+#include <linux/phy/inno-hdmi-phy.h>
+#include <linux/phy/phy.h>
+#include <linux/slab.h>
+
+/*
+ * StarFive (JH7110) Innosilicon HDMI PHY Register Definitions
+ */
+
+/* REG: 0x1aa */
+#define STF_INNO_POST_PLL_DIV_1 0x1aa
+#define STF_INNO_POST_PLL_POST_DIV_ENABLE GENMASK(3, 2)
+#define STF_INNO_POST_PLL_REFCLK_SEL_TMDS BIT(1)
+#define STF_INNO_POST_PLL_POWER_DOWN BIT(0)
+
+/* REG: 0x1ab */
+#define STF_INNO_POST_PLL_DIV_2 0x1ab
+#define STF_INNO_POST_PLL_PRE_DIV(x) FIELD_PREP(GENMASK(5, 0), x)
+#define STF_INNO_POST_PLL_FB_DIV_8(x) FIELD_PREP(BIT(7), (x) >> 8)
+
+/* REG: 0x1ac */
+#define STF_INNO_POST_PLL_DIV_3 0x1ac
+#define STF_INNO_POST_PLL_FB_DIV_7_0(x) FIELD_PREP(GENMASK(7, 0), x)
+
+/* REG: 0x1ad */
+#define STF_INNO_POST_PLL_DIV_4 0x1ad
+#define STF_INNO_POST_PLL_POST_DIV_MASK GENMASK(1, 0)
+
+/* REG: 0x1af */
+#define STF_INNO_POST_PLL_LOCK_STATUS 0x1af
+#define STF_INNO_POST_PLL_LOCK BIT(0)
+
+/* REG: 0x1b0 */
+#define STF_INNO_BIAS_CONTROL 0x1b0
+#define STF_INNO_BIAS_ENABLE BIT(2)
+
+/* REG: 0x1b2 */
+#define STF_INNO_TMDS_CONTROL 0x1b2
+#define STF_INNO_TMDS_CLK_DRIVER_EN BIT(3)
+#define STF_INNO_TMDS_D2_DRIVER_EN BIT(2)
+#define STF_INNO_TMDS_D1_DRIVER_EN BIT(1)
+#define STF_INNO_TMDS_D0_DRIVER_EN BIT(0)
+#define STF_INNO_TMDS_DRIVER_ENABLE (STF_INNO_TMDS_CLK_DRIVER_EN | \
+ STF_INNO_TMDS_D2_DRIVER_EN | \
+ STF_INNO_TMDS_D1_DRIVER_EN | \
+ STF_INNO_TMDS_D0_DRIVER_EN)
+
+/* REG: 0x1b4 */
+#define STF_INNO_LDO_CONTROL 0x1b4
+#define STF_INNO_LDO_ENABLE (BIT(2) | BIT(1) | BIT(0))
+
+/* REG: 0x1be */
+#define STF_INNO_SERIALIER_CONTROL 0x1be
+#define STF_INNO_SERIALIER_ENABLE (BIT(6) | BIT(5) | BIT(4) | BIT(0))
+
+/* REG: 0x1cc */
+#define STF_INNO_RX_CONTROL 0x1cc
+#define STF_INNO_RX_ENABLE (BIT(3) | BIT(2) | BIT(1) | BIT(0))
+
+/*
+ * These tables are copied from the monolithic driver.
+ * They match the Rockchip PHY driver tables.
+ */
+
+struct post_pll_config {
+ unsigned long tmdsclock;
+ u8 prediv;
+ u16 fbdiv;
+ u8 postdiv;
+ u8 post_div_en;
+};
+
+static const struct inno_hdmi_phy_pre_pll_config pre_pll_cfg_table[] = {
+ { 25175000, 25175000, 1, 100, 2, 3, 3, 12, 3, 3, 4, 0, 0xF55555 },
+ { 25200000, 25200000, 1, 100, 2, 3, 3, 12, 3, 3, 4, 0, 0 },
+ { 27000000, 27000000, 1, 90, 3, 2, 2, 10, 3, 3, 4, 0, 0 },
+ { 27027000, 27027000, 1, 90, 3, 2, 2, 10, 3, 3, 4, 0, 0x170A3D },
+ { 28320000, 28320000, 1, 28, 2, 1, 1, 3, 0, 3, 4, 0, 0x51EB85 },
+ { 30240000, 30240000, 1, 30, 2, 1, 1, 3, 0, 3, 4, 0, 0x3D70A3 },
+ { 31500000, 31500000, 1, 31, 2, 1, 1, 3, 0, 3, 4, 0, 0x7FFFFF },
+ { 33750000, 33750000, 1, 33, 2, 1, 1, 3, 0, 3, 4, 0, 0xCFFFFF },
+ { 36000000, 36000000, 1, 36, 2, 1, 1, 3, 0, 3, 4, 0, 0 },
+ { 40000000, 40000000, 1, 80, 2, 2, 2, 12, 2, 2, 2, 0, 0 },
+ { 46970000, 46970000, 1, 46, 2, 1, 1, 3, 0, 3, 4, 0, 0xF851EB },
+ { 49500000, 49500000, 1, 49, 2, 1, 1, 3, 0, 3, 4, 0, 0x7FFFFF },
+ { 49000000, 49000000, 1, 49, 2, 1, 1, 3, 0, 3, 4, 0, 0 },
+ { 50000000, 50000000, 1, 50, 2, 1, 1, 3, 0, 3, 4, 0, 0 },
+ { 54000000, 54000000, 1, 54, 2, 1, 1, 3, 0, 3, 4, 0, 0 },
+ { 54054000, 54054000, 1, 54, 2, 1, 1, 3, 0, 3, 4, 0, 0x0DD2F1 },
+ { 57284000, 57284000, 1, 57, 2, 1, 1, 3, 0, 3, 4, 0, 0x48B439 },
+ { 58230000, 58230000, 1, 58, 2, 1, 1, 3, 0, 3, 4, 0, 0x3AE147 },
+ { 59341000, 59341000, 1, 59, 2, 1, 1, 3, 0, 3, 4, 0, 0x574BC6 },
+ { 59400000, 59400000, 1, 99, 3, 1, 1, 1, 3, 3, 4, 0, 0 },
+ { 65000000, 65000000, 1, 130, 2, 2, 2, 12, 0, 2, 2, 0, 0 },
+ { 68250000, 68250000, 1, 68, 2, 1, 1, 3, 0, 3, 4, 0, 0x3FFFFF },
+ { 71000000, 71000000, 1, 71, 2, 1, 1, 3, 0, 3, 4, 0, 0 },
+ { 74176000, 74176000, 1, 98, 1, 2, 2, 1, 2, 3, 4, 0, 0xE6AE6B },
+ { 74250000, 74250000, 1, 99, 1, 2, 2, 1, 2, 3, 4, 0, 0 },
+ { 75000000, 75000000, 1, 75, 2, 1, 1, 3, 0, 3, 4, 0, 0 },
+ { 78750000, 78750000, 1, 78, 2, 1, 1, 3, 0, 3, 4, 0, 0xCFFFFF },
+ { 79500000, 79500000, 1, 79, 2, 1, 1, 3, 0, 3, 4, 0, 0x7FFFFF },
+ { 83500000, 83500000, 2, 167, 2, 1, 1, 1, 0, 0, 6, 0, 0 },
+ { 83500000, 104375000, 1, 104, 2, 1, 1, 1, 1, 0, 5, 0, 0x600000 },
+ { 85500000, 85500000, 1, 85, 2, 1, 1, 3, 0, 3, 4, 0, 0x7FFFFF },
+ { 85750000, 85750000, 1, 85, 2, 1, 1, 3, 0, 3, 4, 0, 0xCFFFFF },
+ { 85800000, 85800000, 1, 85, 2, 1, 1, 3, 0, 3, 4, 0, 0xCCCCCC },
+ { 88750000, 88750000, 1, 88, 2, 1, 1, 3, 0, 3, 4, 0, 0xCFFFFF },
+ { 89910000, 89910000, 1, 89, 2, 1, 1, 3, 0, 3, 4, 0, 0xE8F5C1 },
+ { 90000000, 90000000, 1, 90, 2, 1, 1, 3, 0, 3, 4, 0, 0 },
+ { 101000000, 101000000, 1, 101, 2, 1, 1, 3, 0, 3, 4, 0, 0 },
+ { 102250000, 102250000, 1, 102, 2, 1, 1, 3, 0, 3, 4, 0, 0x3FFFFF },
+ { 106500000, 106500000, 1, 106, 2, 1, 1, 3, 0, 3, 4, 0, 0x7FFFFF },
+ { 108000000, 108000000, 1, 90, 3, 0, 0, 5, 0, 2, 2, 0, 0 },
+ { 119000000, 119000000, 1, 119, 2, 1, 1, 3, 0, 3, 4, 0, 0 },
+ { 131481000, 131481000, 1, 131, 2, 1, 1, 3, 0, 3, 4, 0, 0x7B22D1 },
+ { 135000000, 135000000, 1, 135, 2, 1, 1, 3, 0, 3, 4, 0, 0 },
+ { 136750000, 136750000, 1, 136, 2, 1, 1, 3, 0, 3, 4, 0, 0xCFFFFF },
+ { 147180000, 147180000, 1, 147, 2, 1, 1, 3, 0, 3, 4, 0, 0x2E147A },
+ { 148352000, 148352000, 1, 98, 1, 1, 1, 1, 2, 2, 2, 0, 0xE6AE6B },
+ { 148500000, 148500000, 1, 99, 1, 1, 1, 1, 2, 2, 2, 0, 0 },
+ { 154000000, 154000000, 1, 154, 2, 1, 1, 3, 0, 3, 4, 0, 0 },
+ { 156000000, 156000000, 1, 156, 2, 1, 1, 3, 0, 3, 4, 0, 0 },
+ { 157000000, 157000000, 1, 157, 2, 1, 1, 3, 0, 3, 4, 0, 0 },
+ { 162000000, 162000000, 1, 162, 2, 1, 1, 3, 0, 3, 4, 0, 0 },
+ { 174250000, 174250000, 1, 145, 3, 0, 0, 5, 0, 2, 2, 0, 0x355555 },
+ { 174500000, 174500000, 1, 174, 2, 1, 1, 3, 0, 3, 4, 0, 0x7FFFFF },
+ { 174570000, 174570000, 1, 174, 2, 1, 1, 3, 0, 3, 4, 0, 0x91EB84 },
+ { 175500000, 175500000, 1, 175, 2, 1, 1, 3, 0, 3, 4, 0, 0x7FFFFF },
+ { 185590000, 185590000, 1, 185, 2, 1, 1, 3, 0, 3, 4, 0, 0x970A3C },
+ { 187000000, 187000000, 1, 187, 2, 1, 1, 3, 0, 3, 4, 0, 0 },
+ { 241500000, 241500000, 1, 161, 1, 1, 1, 4, 0, 2, 2, 0, 0 },
+ { 241700000, 241700000, 1, 241, 2, 1, 1, 3, 0, 3, 4, 0, 0xB33332 },
+ { 262750000, 262750000, 1, 262, 2, 1, 1, 3, 0, 3, 4, 0, 0xCFFFFF },
+ { 296500000, 296500000, 1, 296, 2, 1, 1, 3, 0, 3, 4, 0, 0x7FFFFF },
+ { 296703000, 296703000, 1, 98, 0, 1, 1, 1, 0, 2, 2, 0, 0xE6AE6B },
+ { 297000000, 297000000, 1, 99, 0, 1, 1, 1, 0, 2, 2, 0, 0 },
+ { 594000000, 594000000, 1, 99, 0, 2, 0, 1, 0, 1, 1, 0, 0 },
+ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
+};
+
+static const struct post_pll_config post_pll_cfg_table[] = {
+ { 25200000, 1, 80, 13, 3 },
+ { 27000000, 1, 40, 11, 3 },
+ { 27027000, 1, 40, 11, 3 },
+ { 33750000, 1, 40, 11, 3 },
+ { 49000000, 1, 20, 1, 3 },
+ { 65000000, 1, 20, 1, 3 },
+ { 74250000, 1, 20, 1, 3 },
+ { 88750000, 1, 20, 1, 3 },
+ { 108000000, 1, 20, 1, 3 },
+ { 148500000, 1, 20, 1, 3 },
+ { 162000000, 1, 20, 1, 3 },
+ { 174250000, 1, 20, 1, 3 },
+ { 187000000, 1, 20, 1, 3 },
+ { 241700000, 1, 20, 1, 3 },
+ { 297000000, 4, 20, 0, 0 },
+ { 594000000, 4, 20, 0, 0 }, /* postpll_postdiv_en = 0 */
+ { /* sentinel */ }
+};
+
+struct starfive_hdmi_phy {
+ struct device *dev;
+ struct regmap *regmap;
+ struct phy *phy;
+ struct clk *refoclk;
+
+ struct inno_hdmi_phy_pre_pll pre_pll;
+
+ struct clk_hw hw;
+ struct clk *phyclk;
+ unsigned long pixclock;
+ unsigned long tmdsclock;
+};
+
+static inline void inno_write(struct starfive_hdmi_phy *inno, u32 reg, u8 val)
+{
+ regmap_write(inno->regmap, reg * 4, val);
+}
+
+static inline u8 inno_read(struct starfive_hdmi_phy *inno, u32 reg)
+{
+ u32 val;
+
+ regmap_read(inno->regmap, reg * 4, &val);
+ return val;
+}
+
+static inline void inno_update_bits(struct starfive_hdmi_phy *inno, u16 reg,
+ u8 mask, u8 val)
+{
+ regmap_update_bits(inno->regmap, reg * 4, mask, val);
+}
+
+#define inno_poll(inno, reg, val, cond, sleep_us, timeout_us) \
+ regmap_read_poll_timeout((inno)->regmap, (reg) * 4, val, cond, \
+ sleep_us, timeout_us)
+
+static inline struct starfive_hdmi_phy *to_starfive_hdmi_phy(struct clk_hw *hw)
+{
+ return container_of(hw, struct starfive_hdmi_phy, hw);
+}
+
+static int starfive_hdmi_phy_clk_prepare(struct clk_hw *hw)
+{
+ struct starfive_hdmi_phy *inno = to_starfive_hdmi_phy(hw);
+ int ret;
+
+ inno_hdmi_phy_pre_pll_power_down(&inno->pre_pll, false);
+
+ if (inno_hdmi_phy_pre_pll_is_locked(&inno->pre_pll))
+ return 0;
+
+ ret = inno_hdmi_phy_pre_pll_wait_locked(&inno->pre_pll, 100000);
+ if (ret) {
+ dev_err(inno->dev, "Timeout waiting for pre-PLL lock\n");
+ inno_hdmi_phy_pre_pll_power_down(&inno->pre_pll, true);
+ return ret;
+ }
+
+ return 0;
+}
+
+static void starfive_hdmi_phy_clk_unprepare(struct clk_hw *hw)
+{
+ struct starfive_hdmi_phy *inno = to_starfive_hdmi_phy(hw);
+
+ inno_hdmi_phy_pre_pll_power_down(&inno->pre_pll, true);
+ inno->pixclock = 0; /* Invalidate cached rate */
+}
+
+static int starfive_hdmi_phy_clk_is_prepared(struct clk_hw *hw)
+{
+ struct starfive_hdmi_phy *inno = to_starfive_hdmi_phy(hw);
+
+ if (!inno_hdmi_phy_pre_pll_is_powered(&inno->pre_pll))
+ return 0;
+
+ return inno_hdmi_phy_pre_pll_is_locked(&inno->pre_pll);
+}
+
+static unsigned long starfive_hdmi_phy_clk_recalc_rate(struct clk_hw *hw,
+ unsigned long parent_rate)
+{
+ struct starfive_hdmi_phy *inno = to_starfive_hdmi_phy(hw);
+
+ if (!starfive_hdmi_phy_clk_is_prepared(hw))
+ return inno->pixclock;
+
+ inno->pixclock = inno_hdmi_phy_pre_pll_recalc_rate(&inno->pre_pll,
+ parent_rate);
+
+ return inno->pixclock;
+}
+
+static int starfive_hdmi_phy_clk_determine_rate(struct clk_hw *hw,
+ struct clk_rate_request *req)
+{
+ struct starfive_hdmi_phy *inno = to_starfive_hdmi_phy(hw);
+
+ return inno_hdmi_phy_pre_pll_determine_rate(&inno->pre_pll, req);
+}
+
+static int starfive_hdmi_phy_clk_set_rate(struct clk_hw *hw, unsigned long rate,
+ unsigned long parent_rate)
+{
+ struct starfive_hdmi_phy *inno = to_starfive_hdmi_phy(hw);
+ const struct inno_hdmi_phy_pre_pll_config *cfg;
+
+ /*
+ * The JH7110 only drives 8bpc, so the TMDS clock always matches the
+ * pixel clock.
+ */
+ cfg = inno_hdmi_phy_pre_pll_lookup(&inno->pre_pll, rate, rate);
+ if (IS_ERR(cfg))
+ return PTR_ERR(cfg);
+
+ dev_dbg(inno->dev, "%s rate %lu tmdsclk %lu\n",
+ __func__, rate, cfg->tmdsclock);
+
+ if (inno->pixclock == rate && inno->tmdsclock == cfg->tmdsclock)
+ return 0;
+
+ inno_update_bits(inno, STF_INNO_BIAS_CONTROL,
+ STF_INNO_BIAS_ENABLE, STF_INNO_BIAS_ENABLE);
+ inno_write(inno, STF_INNO_RX_CONTROL, STF_INNO_RX_ENABLE);
+
+ inno_hdmi_phy_pre_pll_power_down(&inno->pre_pll, true);
+ inno_hdmi_phy_pre_pll_configure(&inno->pre_pll, cfg);
+ inno_hdmi_phy_pre_pll_power_down(&inno->pre_pll, false);
+
+ inno->pixclock = rate;
+ inno->tmdsclock = cfg->tmdsclock;
+
+ return 0;
+}
+
+static const struct clk_ops starfive_hdmi_phy_clk_ops = {
+ .prepare = starfive_hdmi_phy_clk_prepare,
+ .unprepare = starfive_hdmi_phy_clk_unprepare,
+ .is_prepared = starfive_hdmi_phy_clk_is_prepared,
+ .recalc_rate = starfive_hdmi_phy_clk_recalc_rate,
+ .determine_rate = starfive_hdmi_phy_clk_determine_rate,
+ .set_rate = starfive_hdmi_phy_clk_set_rate,
+};
+
+static int starfive_hdmi_phy_power_on(struct phy *phy)
+{
+ struct starfive_hdmi_phy *inno = phy_get_drvdata(phy);
+ const struct post_pll_config *cfg = post_pll_cfg_table;
+ const struct inno_hdmi_phy_pre_pll_config *pre_cfg;
+ unsigned long tmdsclock;
+ u8 reg_1ad_value;
+ u8 reg_1aa_value;
+
+ u32 v;
+ int ret;
+
+ tmdsclock = clk_get_rate(inno->phyclk);
+ pre_cfg = inno_hdmi_phy_pre_pll_lookup(&inno->pre_pll, tmdsclock,
+ tmdsclock);
+ if (IS_ERR(pre_cfg)) {
+ dev_err(inno->dev, "no pre-PLL config for current pixel clock\n");
+ return PTR_ERR(pre_cfg);
+ }
+ tmdsclock = pre_cfg->tmdsclock;
+ inno->tmdsclock = tmdsclock;
+
+ inno_update_bits(inno, STF_INNO_BIAS_CONTROL,
+ STF_INNO_BIAS_ENABLE, STF_INNO_BIAS_ENABLE);
+ inno_write(inno, STF_INNO_RX_CONTROL, STF_INNO_RX_ENABLE);
+
+ /* Find Post-PLL config */
+ for (; cfg->tmdsclock != 0; cfg++)
+ if (tmdsclock <= cfg->tmdsclock)
+ break;
+
+ if (cfg->tmdsclock == 0) {
+ dev_err(inno->dev, "Failed to find Post-PLL config\n");
+ return -EINVAL;
+ }
+ dev_dbg(inno->dev, "Inno HDMI PHY Power On: pixclk %lu, tmdsclk %lu\n",
+ inno->pixclock, tmdsclock);
+
+ reg_1ad_value = cfg->post_div_en ? cfg->postdiv : 0x00;
+ reg_1aa_value = cfg->post_div_en ? 0x0e : 0x02;
+
+ /*
+ * Pre-PLL is already prepared and running at inno->pixclock
+ * via the clk_set_rate and prepare calls from the controller/bridge.
+ * Now, configure and enable the Post-PLL and TMDS outputs.
+ */
+
+ inno_write(inno, STF_INNO_POST_PLL_DIV_2,
+ STF_INNO_POST_PLL_PRE_DIV(cfg->prediv));
+ inno_write(inno, STF_INNO_POST_PLL_DIV_3, cfg->fbdiv & 0xff);
+ inno_write(inno, STF_INNO_POST_PLL_DIV_4, reg_1ad_value);
+
+ /* Power up Post-PLL */
+ inno_write(inno, STF_INNO_POST_PLL_DIV_1, reg_1aa_value);
+
+ /* Wait for post PLL lock */
+ ret = inno_poll(inno, STF_INNO_POST_PLL_LOCK_STATUS, v,
+ v & STF_INNO_POST_PLL_LOCK, 1000, 100000);
+ if (ret) {
+ dev_err(inno->dev, "Post-PLL locking failed\n");
+ return ret;
+ }
+
+ inno_write(inno, STF_INNO_LDO_CONTROL, STF_INNO_LDO_ENABLE);
+ inno_write(inno, STF_INNO_SERIALIER_CONTROL,
+ STF_INNO_SERIALIER_ENABLE);
+ inno_write(inno, STF_INNO_TMDS_CONTROL, 0x8f);
+
+ return 0;
+}
+
+static int starfive_hdmi_phy_power_off(struct phy *phy)
+{
+ struct starfive_hdmi_phy *inno = phy_get_drvdata(phy);
+
+ dev_dbg(inno->dev, "Inno HDMI PHY Power Off\n");
+
+ inno_write(inno, STF_INNO_TMDS_CONTROL, 0x00);
+ inno_write(inno, STF_INNO_SERIALIER_CONTROL, 0x00);
+ inno_write(inno, STF_INNO_LDO_CONTROL, 0x00);
+ inno_update_bits(inno, STF_INNO_BIAS_CONTROL,
+ STF_INNO_BIAS_ENABLE, 0x00);
+ inno_write(inno, STF_INNO_RX_CONTROL, 0x00);
+
+ /* Power down Post-PLL */
+ inno_update_bits(inno, STF_INNO_POST_PLL_DIV_1,
+ STF_INNO_POST_PLL_POWER_DOWN,
+ STF_INNO_POST_PLL_POWER_DOWN);
+
+ inno->tmdsclock = 0;
+ inno->pixclock = 0;
+
+ return 0;
+}
+
+static const struct phy_ops starfive_hdmi_phy_ops = {
+ .owner = THIS_MODULE,
+ .power_on = starfive_hdmi_phy_power_on,
+ .power_off = starfive_hdmi_phy_power_off,
+};
+
+static int starfive_hdmi_phy_probe(struct platform_device *pdev)
+{
+ struct device *dev = &pdev->dev;
+ struct device *parent = dev->parent;
+ struct starfive_hdmi_phy *inno;
+ struct phy_provider *phy_provider;
+ struct regmap *regmap;
+ struct clk_init_data init = {};
+ const char *refoclk_name;
+ int ret;
+
+ inno = devm_kzalloc(dev, sizeof(*inno), GFP_KERNEL);
+ if (!inno)
+ return -ENOMEM;
+
+ inno->dev = dev;
+
+ /* Get the regmap from the parent device */
+ regmap = dev_get_regmap(parent, NULL);
+ if (!regmap) {
+ dev_err(dev, "Failed to get parent regmap\n");
+ return -ENODEV;
+ }
+ inno->regmap = regmap;
+
+ /*
+ * The PHY block sits behind the HDMI controller in the shared register
+ * space, so the common pre-PLL helpers need a 0x100 register offset.
+ */
+ inno->pre_pll.regmap = regmap;
+ inno->pre_pll.offset = 0x100;
+ inno->pre_pll.table = pre_pll_cfg_table;
+
+ /* Get the input reference clock */
+ inno->refoclk = devm_clk_get(inno->dev, "refoclk");
+ if (IS_ERR(inno->refoclk)) {
+ ret = PTR_ERR(inno->refoclk);
+ dev_err(inno->dev, "failed to get oscillator-ref clock: %d\n",
+ ret);
+ return ret;
+ }
+
+ /* We must prepare/enable refoclk here so .set_rate/.recalc_rate work */
+ ret = clk_prepare_enable(inno->refoclk);
+ if (ret) {
+ dev_err(dev, "Failed to enable refoclk: %d\n", ret);
+ return ret;
+ }
+
+ platform_set_drvdata(pdev, inno);
+
+ /* Initialize and register the clock provider */
+ refoclk_name = __clk_get_name(inno->refoclk);
+ init.parent_names = &refoclk_name;
+ init.num_parents = 1;
+ init.flags = 0;
+ init.name = "hdmi_pclk";
+ init.ops = &starfive_hdmi_phy_clk_ops;
+
+ of_property_read_string(dev->of_node, "clock-output-names", &init.name);
+
+ inno->hw.init = &init;
+ inno->phyclk = devm_clk_register(dev, &inno->hw);
+ if (IS_ERR(inno->phyclk)) {
+ ret = PTR_ERR(inno->phyclk);
+ dev_err(dev, "Failed to register clock provider: %d\n", ret);
+ goto err_disable_refoclk;
+ }
+
+ ret = of_clk_add_provider(dev->of_node, of_clk_src_simple_get, inno->phyclk);
+ if (ret) {
+ dev_err(dev, "Failed to add clock provider: %d\n", ret);
+ goto err_disable_refoclk;
+ }
+
+ ret = clk_set_rate(inno->phyclk, 297000000);
+ if (ret) {
+ dev_err(dev, "Failed to set default rate: %d\n", ret);
+ goto err_disable_refoclk;
+ }
+
+ /* Create and register the PHY provider */
+ inno->phy = devm_phy_create(inno->dev, NULL, &starfive_hdmi_phy_ops);
+ if (IS_ERR(inno->phy)) {
+ ret = PTR_ERR(inno->phy);
+ dev_err(inno->dev, "failed to create HDMI PHY: %d\n", ret);
+ goto err_del_clk_provider;
+ }
+
+ phy_set_drvdata(inno->phy, inno);
+
+ phy_provider = devm_of_phy_provider_register(inno->dev,
+ of_phy_simple_xlate);
+ ret = PTR_ERR_OR_ZERO(phy_provider);
+ if (ret)
+ goto err_del_clk_provider;
+
+ return 0;
+
+err_del_clk_provider:
+ of_clk_del_provider(dev->of_node);
+err_disable_refoclk:
+ clk_disable_unprepare(inno->refoclk);
+ return ret;
+}
+
+static void starfive_hdmi_phy_remove(struct platform_device *pdev)
+{
+ struct starfive_hdmi_phy *inno = platform_get_drvdata(pdev);
+
+ of_clk_del_provider(pdev->dev.of_node);
+ clk_disable_unprepare(inno->refoclk);
+}
+
+static const struct of_device_id starfive_hdmi_phy_of_match[] = {
+ { .compatible = "starfive,jh7110-inno-hdmi-phy", },
+ { /* sentinel */ }
+};
+MODULE_DEVICE_TABLE(of, starfive_hdmi_phy_of_match);
+
+static struct platform_driver starfive_hdmi_phy_driver = {
+ .probe = starfive_hdmi_phy_probe,
+ .remove = starfive_hdmi_phy_remove,
+ .driver = {
+ .name = "starfive-inno-hdmi-phy",
+ .of_match_table = starfive_hdmi_phy_of_match,
+ },
+};
+module_platform_driver(starfive_hdmi_phy_driver);
+
+MODULE_AUTHOR("Michal Wilczynski <m.wilczynski@samsung.com>");
+MODULE_DESCRIPTION("StarFive JH7110 Innosilicon HDMI PHY Driver");
+MODULE_LICENSE("GPL");
--
2.34.1
_______________________________________________
linux-riscv mailing list
linux-riscv@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-riscv
^ permalink raw reply related [flat|nested] 116+ messages in thread
* [PATCH v2 14/15] riscv: dts: starfive: jh7110: Update DT for display subsystem
2026-08-28 13:47 ` Michal Wilczynski
(?)
(?)
@ 2026-08-28 13:47 ` Michal Wilczynski
-1 siblings, 0 replies; 116+ messages in thread
From: Michal Wilczynski @ 2026-08-28 13:47 UTC (permalink / raw)
To: Vinod Koul, Neil Armstrong, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Andrzej Hajda, Robert Foss, Laurent Pinchart,
Jonas Karlman, Jernej Skrabec, Luca Ceresoli, David Airlie,
Simona Vetter, Maarten Lankhorst, Maxime Ripard,
Thomas Zimmermann, Lee Jones, Andy Yan, Philipp Zabel,
Emil Renner Berthing, Hal Feng, Michael Turquette, Stephen Boyd,
Brian Masney, Heiko Stuebner, Conor Dooley, Paul Walmsley,
Palmer Dabbelt, Albert Ou, Alexandre Ghiti, Dominique Belhachemi
Cc: linux-phy, devicetree, linux-kernel, dri-devel, mfd, linux-clk,
linux-arm-kernel, linux-rockchip, linux-riscv, Icenowy Zheng,
Andy Yan, Marek Szyprowski, Maud Spierings, Graham Markall,
Michal Wilczynski
Activate the display subsystem by adding the dc8200, hdmi and voutcrg
nodes as direct soc children. Each references the PD_VOUT power domain
through power-domains, so genpd powers the domain on demand, and the
HDMI-PHY -> voutcrg -> HDMI-controller probe order is resolved by
deferred probe.
The monolithic hdmi node is modelled as a container with hdmi_phy
and hdmi_controller children. This lets the PHY (clock provider,
depending only on xin24m) and the controller (clock consumer) probe
independently, breaking the circular clock dependency with voutcrg.
voutcrg consumes the pixel clock from the &hdmi_phy node instead of the
old fixed-clock, and dc8200 gets its pixel clocks from voutcrg's MUXes
and is marked dma-noncoherent for framebuffer DMA. The old, incorrect
hdmitx0-pixel-clock fixed-clock node is removed.
Co-developed-by: Dominique Belhachemi <db@domibel.de>
Signed-off-by: Dominique Belhachemi <db@domibel.de>
Signed-off-by: Michal Wilczynski <m.wilczynski@samsung.com>
---
arch/riscv/boot/dts/starfive/jh7110-common.dtsi | 119 +++++++++++++++++++++++-
arch/riscv/boot/dts/starfive/jh7110.dtsi | 87 +++++++++++++++--
2 files changed, 196 insertions(+), 10 deletions(-)
diff --git a/arch/riscv/boot/dts/starfive/jh7110-common.dtsi b/arch/riscv/boot/dts/starfive/jh7110-common.dtsi
index a7a1c09a2c9075711f3a214a49618911fdc7b421..7aadc35f4a6aa724c86a868ef65c5c829e666ee2 100644
--- a/arch/riscv/boot/dts/starfive/jh7110-common.dtsi
+++ b/arch/riscv/boot/dts/starfive/jh7110-common.dtsi
@@ -33,6 +33,25 @@ memory@40000000 {
bootph-pre-ram;
};
+ reserved-memory {
+ #address-cells = <2>;
+ #size-cells = <2>;
+ ranges;
+
+ /* vout applies for space from this CMA
+ * Without this CMA reservation,
+ * vout may not work properly.
+ */
+ linux,cma {
+ compatible = "shared-dma-pool";
+ reusable;
+ size = <0x0 0x20000000>;
+ alignment = <0x0 0x1000>;
+ alloc-ranges = <0x0 0x70000000 0x0 0x20000000>;
+ linux,cma-default;
+ };
+ };
+
gpio-restart {
compatible = "gpio-restart";
gpios = <&sysgpio 35 GPIO_ACTIVE_HIGH>;
@@ -73,12 +92,47 @@ codec {
};
};
};
+
+ hdmi-connector {
+ compatible = "hdmi-connector";
+ type = "a";
+
+ port {
+ hdmi_con_in: endpoint {
+ remote-endpoint = <&hdmi_out_con>;
+ };
+ };
+ };
};
&cpus {
timebase-frequency = <4000000>;
};
+&dc8200 {
+ status = "okay";
+
+ ports {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ dpu_port0: port@0 {
+ reg = <0>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ dpu_out_dpi0: endpoint@0 {
+ reg = <0>;
+ remote-endpoint = <&hdmi_in>;
+ };
+ };
+
+ dpu_port1: port@1 {
+ reg = <1>;
+ };
+ };
+};
+
&dvp_clk {
clock-frequency = <74250000>;
};
@@ -99,8 +153,31 @@ &gmac1_rmii_refin {
clock-frequency = <50000000>;
};
-&hdmitx0_pixelclk {
- clock-frequency = <297000000>;
+&hdmi_controller {
+ status = "okay";
+ pinctrl-names = "default";
+ pinctrl-0 = <&hdmi_pins>;
+
+ ports {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ port@0 {
+ reg = <0>;
+
+ hdmi_in: endpoint {
+ remote-endpoint = <&dpu_out_dpi0>;
+ };
+ };
+
+ hdmi_out_port: port@1 {
+ reg = <1>;
+ hdmi_out_con: endpoint {
+ remote-endpoint = <&hdmi_con_in>;
+ };
+
+ };
+ };
};
&i2srx_bclk_ext {
@@ -351,6 +428,40 @@ &syscrg {
};
&sysgpio {
+ hdmi_pins: hdmi-0 {
+ hdmi-cec-pins {
+ pinmux = <GPIOMUX(14, GPOUT_SYS_HDMI_CEC_SDA,
+ GPOEN_SYS_HDMI_CEC_SDA,
+ GPI_SYS_HDMI_CEC_SDA)>;
+ input-enable;
+ bias-pull-up;
+ };
+
+ hdmi-hpd-pins {
+ pinmux = <GPIOMUX(15, GPOUT_HIGH,
+ GPOEN_ENABLE,
+ GPI_SYS_HDMI_HPD)>;
+ input-enable;
+ bias-disable; /* external pull-up */
+ };
+
+ hdmi-scl-pins {
+ pinmux = <GPIOMUX(0, GPOUT_SYS_HDMI_DDC_SCL,
+ GPOEN_SYS_HDMI_DDC_SCL,
+ GPI_SYS_HDMI_DDC_SCL)>;
+ input-enable;
+ bias-pull-up;
+ };
+
+ hdmi-sda-pins {
+ pinmux = <GPIOMUX(1, GPOUT_SYS_HDMI_DDC_SDA,
+ GPOEN_SYS_HDMI_DDC_SDA,
+ GPI_SYS_HDMI_DDC_SDA)>;
+ input-enable;
+ bias-pull-up;
+ };
+ };
+
i2c0_pins: i2c0-0 {
i2c-pins {
pinmux = <GPIOMUX(57, GPOUT_LOW,
@@ -629,3 +740,7 @@ &U74_3 {
&U74_4 {
cpu-supply = <&vdd_cpu>;
};
+
+&voutcrg {
+ status = "okay";
+};
diff --git a/arch/riscv/boot/dts/starfive/jh7110.dtsi b/arch/riscv/boot/dts/starfive/jh7110.dtsi
index 9c3e4598747eb5541effe697044484715569a285..024e33b0e97cb13928d69d1d8090ed14d22bb022 100644
--- a/arch/riscv/boot/dts/starfive/jh7110.dtsi
+++ b/arch/riscv/boot/dts/starfive/jh7110.dtsi
@@ -290,12 +290,6 @@ gmac1_rmii_refin: gmac1-rmii-refin-clock {
#clock-cells = <0>;
};
- hdmitx0_pixelclk: hdmitx0-pixel-clock {
- compatible = "fixed-clock";
- clock-output-names = "hdmitx0_pixelclk";
- #clock-cells = <0>;
- };
-
i2srx_bclk_ext: i2srx-bclk-ext-clock {
compatible = "fixed-clock";
clock-output-names = "i2srx_bclk_ext";
@@ -352,6 +346,13 @@ tdm_ext: tdm-ext-clock {
#clock-cells = <0>;
};
+ xin24m: xin24m {
+ compatible = "fixed-clock";
+ #clock-cells = <0>;
+ clock-frequency = <24000000>;
+ clock-output-names = "xin24m";
+ };
+
soc {
compatible = "simple-bus";
interrupt-parent = <&plic>;
@@ -1199,22 +1200,92 @@ csi_phy: phy@19820000 {
#phy-cells = <0>;
};
+ dc8200: display@29400000 {
+ compatible = "verisilicon,dc";
+ reg = <0x0 0x29400000 0x0 0x2800>;
+ interrupts = <95>;
+ dma-noncoherent;
+
+ power-domains = <&pwrc JH7110_PD_VOUT>;
+
+ clocks = <&voutcrg JH7110_VOUTCLK_DC8200_CORE>,
+ <&voutcrg JH7110_VOUTCLK_DC8200_AXI>,
+ <&voutcrg JH7110_VOUTCLK_DC8200_AHB>,
+ <&voutcrg JH7110_VOUTCLK_DC8200_PIX0>,
+ <&voutcrg JH7110_VOUTCLK_DC8200_PIX1>;
+ clock-names = "core", "axi", "ahb", "pix0", "pix1";
+
+ resets = <&voutcrg JH7110_VOUTRST_DC8200_CORE>,
+ <&voutcrg JH7110_VOUTRST_DC8200_AXI>,
+ <&voutcrg JH7110_VOUTRST_DC8200_AHB>;
+ reset-names = "core", "axi", "ahb";
+ };
+
+ hdmi_subsystem: hdmi@29590000 {
+ compatible = "starfive,jh7110-hdmi-subsystem";
+ reg = <0x0 0x29590000 0x0 0x4000>;
+
+ /*
+ * This MFD's PHY child is the first device in the vout
+ * region to touch registers, so it owns the NoC display
+ * bus clock + reset that gate access to the region.
+ * PD_VOUT is powered on by genpd via power-domains.
+ */
+ power-domains = <&pwrc JH7110_PD_VOUT>;
+ clocks = <&syscrg JH7110_SYSCLK_NOC_BUS_DISP_AXI>;
+ resets = <&syscrg JH7110_SYSRST_NOC_BUS_DISP_AXI>;
+
+ hdmi_phy: phy {
+ compatible = "starfive,jh7110-inno-hdmi-phy";
+
+ clocks = <&xin24m>;
+ clock-names = "refoclk";
+
+ /* Output clock: The variable pixel clock */
+ #clock-cells = <0>;
+ clock-output-names = "hdmi_pclk";
+
+ /* PHY provider for the controller */
+ #phy-cells = <0>;
+ };
+
+ hdmi_controller: controller {
+ compatible = "starfive,jh7110-inno-hdmi-controller";
+ interrupts = <99>;
+
+ clocks = <&voutcrg JH7110_VOUTCLK_HDMI_TX_SYS>,
+ <&voutcrg JH7110_VOUTCLK_HDMI_TX_MCLK>,
+ <&voutcrg JH7110_VOUTCLK_HDMI_TX_BCLK>,
+ <&hdmi_phy>;
+ clock-names = "sys", "mclk", "bclk", "pclk";
+
+ resets = <&voutcrg JH7110_VOUTRST_HDMI_TX_HDMI>;
+ reset-names = "hdmi_tx";
+
+ phys = <&hdmi_phy>;
+ phy-names = "hdmi-phy";
+ };
+ };
+
voutcrg: clock-controller@295c0000 {
compatible = "starfive,jh7110-voutcrg";
reg = <0x0 0x295c0000 0x0 0x10000>;
+
+ power-domains = <&pwrc JH7110_PD_VOUT>;
+
clocks = <&syscrg JH7110_SYSCLK_VOUT_SRC>,
<&syscrg JH7110_SYSCLK_VOUT_TOP_AHB>,
<&syscrg JH7110_SYSCLK_VOUT_TOP_AXI>,
<&syscrg JH7110_SYSCLK_VOUT_TOP_HDMITX0_MCLK>,
<&syscrg JH7110_SYSCLK_I2STX0_BCLK>,
- <&hdmitx0_pixelclk>;
+ <&hdmi_phy>;
clock-names = "vout_src", "vout_top_ahb",
"vout_top_axi", "vout_top_hdmitx0_mclk",
"i2stx0_bclk", "hdmitx0_pixelclk";
+
resets = <&syscrg JH7110_SYSRST_VOUT_TOP_SRC>;
#clock-cells = <1>;
#reset-cells = <1>;
- power-domains = <&pwrc JH7110_PD_VOUT>;
};
pcie0: pcie@940000000 {
--
2.34.1
^ permalink raw reply related [flat|nested] 116+ messages in thread
* [PATCH v2 14/15] riscv: dts: starfive: jh7110: Update DT for display subsystem
@ 2026-08-28 13:47 ` Michal Wilczynski
0 siblings, 0 replies; 116+ messages in thread
From: Michal Wilczynski @ 2026-08-28 13:47 UTC (permalink / raw)
To: Vinod Koul, Neil Armstrong, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Andrzej Hajda, Robert Foss, Laurent Pinchart,
Jonas Karlman, Jernej Skrabec, Luca Ceresoli, David Airlie,
Simona Vetter, Maarten Lankhorst, Maxime Ripard,
Thomas Zimmermann, Lee Jones, Andy Yan, Philipp Zabel,
Emil Renner Berthing, Hal Feng, Michael Turquette, Stephen Boyd,
Brian Masney, Heiko Stuebner, Conor Dooley, Paul Walmsley,
Palmer Dabbelt, Albert Ou, Alexandre Ghiti, Dominique Belhachemi
Cc: linux-phy, devicetree, linux-kernel, dri-devel, mfd, linux-clk,
linux-arm-kernel, linux-rockchip, linux-riscv, Icenowy Zheng,
Andy Yan, Marek Szyprowski, Maud Spierings, Graham Markall,
Michal Wilczynski
Activate the display subsystem by adding the dc8200, hdmi and voutcrg
nodes as direct soc children. Each references the PD_VOUT power domain
through power-domains, so genpd powers the domain on demand, and the
HDMI-PHY -> voutcrg -> HDMI-controller probe order is resolved by
deferred probe.
The monolithic hdmi node is modelled as a container with hdmi_phy
and hdmi_controller children. This lets the PHY (clock provider,
depending only on xin24m) and the controller (clock consumer) probe
independently, breaking the circular clock dependency with voutcrg.
voutcrg consumes the pixel clock from the &hdmi_phy node instead of the
old fixed-clock, and dc8200 gets its pixel clocks from voutcrg's MUXes
and is marked dma-noncoherent for framebuffer DMA. The old, incorrect
hdmitx0-pixel-clock fixed-clock node is removed.
Co-developed-by: Dominique Belhachemi <db@domibel.de>
Signed-off-by: Dominique Belhachemi <db@domibel.de>
Signed-off-by: Michal Wilczynski <m.wilczynski@samsung.com>
---
arch/riscv/boot/dts/starfive/jh7110-common.dtsi | 119 +++++++++++++++++++++++-
arch/riscv/boot/dts/starfive/jh7110.dtsi | 87 +++++++++++++++--
2 files changed, 196 insertions(+), 10 deletions(-)
diff --git a/arch/riscv/boot/dts/starfive/jh7110-common.dtsi b/arch/riscv/boot/dts/starfive/jh7110-common.dtsi
index a7a1c09a2c9075711f3a214a49618911fdc7b421..7aadc35f4a6aa724c86a868ef65c5c829e666ee2 100644
--- a/arch/riscv/boot/dts/starfive/jh7110-common.dtsi
+++ b/arch/riscv/boot/dts/starfive/jh7110-common.dtsi
@@ -33,6 +33,25 @@ memory@40000000 {
bootph-pre-ram;
};
+ reserved-memory {
+ #address-cells = <2>;
+ #size-cells = <2>;
+ ranges;
+
+ /* vout applies for space from this CMA
+ * Without this CMA reservation,
+ * vout may not work properly.
+ */
+ linux,cma {
+ compatible = "shared-dma-pool";
+ reusable;
+ size = <0x0 0x20000000>;
+ alignment = <0x0 0x1000>;
+ alloc-ranges = <0x0 0x70000000 0x0 0x20000000>;
+ linux,cma-default;
+ };
+ };
+
gpio-restart {
compatible = "gpio-restart";
gpios = <&sysgpio 35 GPIO_ACTIVE_HIGH>;
@@ -73,12 +92,47 @@ codec {
};
};
};
+
+ hdmi-connector {
+ compatible = "hdmi-connector";
+ type = "a";
+
+ port {
+ hdmi_con_in: endpoint {
+ remote-endpoint = <&hdmi_out_con>;
+ };
+ };
+ };
};
&cpus {
timebase-frequency = <4000000>;
};
+&dc8200 {
+ status = "okay";
+
+ ports {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ dpu_port0: port@0 {
+ reg = <0>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ dpu_out_dpi0: endpoint@0 {
+ reg = <0>;
+ remote-endpoint = <&hdmi_in>;
+ };
+ };
+
+ dpu_port1: port@1 {
+ reg = <1>;
+ };
+ };
+};
+
&dvp_clk {
clock-frequency = <74250000>;
};
@@ -99,8 +153,31 @@ &gmac1_rmii_refin {
clock-frequency = <50000000>;
};
-&hdmitx0_pixelclk {
- clock-frequency = <297000000>;
+&hdmi_controller {
+ status = "okay";
+ pinctrl-names = "default";
+ pinctrl-0 = <&hdmi_pins>;
+
+ ports {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ port@0 {
+ reg = <0>;
+
+ hdmi_in: endpoint {
+ remote-endpoint = <&dpu_out_dpi0>;
+ };
+ };
+
+ hdmi_out_port: port@1 {
+ reg = <1>;
+ hdmi_out_con: endpoint {
+ remote-endpoint = <&hdmi_con_in>;
+ };
+
+ };
+ };
};
&i2srx_bclk_ext {
@@ -351,6 +428,40 @@ &syscrg {
};
&sysgpio {
+ hdmi_pins: hdmi-0 {
+ hdmi-cec-pins {
+ pinmux = <GPIOMUX(14, GPOUT_SYS_HDMI_CEC_SDA,
+ GPOEN_SYS_HDMI_CEC_SDA,
+ GPI_SYS_HDMI_CEC_SDA)>;
+ input-enable;
+ bias-pull-up;
+ };
+
+ hdmi-hpd-pins {
+ pinmux = <GPIOMUX(15, GPOUT_HIGH,
+ GPOEN_ENABLE,
+ GPI_SYS_HDMI_HPD)>;
+ input-enable;
+ bias-disable; /* external pull-up */
+ };
+
+ hdmi-scl-pins {
+ pinmux = <GPIOMUX(0, GPOUT_SYS_HDMI_DDC_SCL,
+ GPOEN_SYS_HDMI_DDC_SCL,
+ GPI_SYS_HDMI_DDC_SCL)>;
+ input-enable;
+ bias-pull-up;
+ };
+
+ hdmi-sda-pins {
+ pinmux = <GPIOMUX(1, GPOUT_SYS_HDMI_DDC_SDA,
+ GPOEN_SYS_HDMI_DDC_SDA,
+ GPI_SYS_HDMI_DDC_SDA)>;
+ input-enable;
+ bias-pull-up;
+ };
+ };
+
i2c0_pins: i2c0-0 {
i2c-pins {
pinmux = <GPIOMUX(57, GPOUT_LOW,
@@ -629,3 +740,7 @@ &U74_3 {
&U74_4 {
cpu-supply = <&vdd_cpu>;
};
+
+&voutcrg {
+ status = "okay";
+};
diff --git a/arch/riscv/boot/dts/starfive/jh7110.dtsi b/arch/riscv/boot/dts/starfive/jh7110.dtsi
index 9c3e4598747eb5541effe697044484715569a285..024e33b0e97cb13928d69d1d8090ed14d22bb022 100644
--- a/arch/riscv/boot/dts/starfive/jh7110.dtsi
+++ b/arch/riscv/boot/dts/starfive/jh7110.dtsi
@@ -290,12 +290,6 @@ gmac1_rmii_refin: gmac1-rmii-refin-clock {
#clock-cells = <0>;
};
- hdmitx0_pixelclk: hdmitx0-pixel-clock {
- compatible = "fixed-clock";
- clock-output-names = "hdmitx0_pixelclk";
- #clock-cells = <0>;
- };
-
i2srx_bclk_ext: i2srx-bclk-ext-clock {
compatible = "fixed-clock";
clock-output-names = "i2srx_bclk_ext";
@@ -352,6 +346,13 @@ tdm_ext: tdm-ext-clock {
#clock-cells = <0>;
};
+ xin24m: xin24m {
+ compatible = "fixed-clock";
+ #clock-cells = <0>;
+ clock-frequency = <24000000>;
+ clock-output-names = "xin24m";
+ };
+
soc {
compatible = "simple-bus";
interrupt-parent = <&plic>;
@@ -1199,22 +1200,92 @@ csi_phy: phy@19820000 {
#phy-cells = <0>;
};
+ dc8200: display@29400000 {
+ compatible = "verisilicon,dc";
+ reg = <0x0 0x29400000 0x0 0x2800>;
+ interrupts = <95>;
+ dma-noncoherent;
+
+ power-domains = <&pwrc JH7110_PD_VOUT>;
+
+ clocks = <&voutcrg JH7110_VOUTCLK_DC8200_CORE>,
+ <&voutcrg JH7110_VOUTCLK_DC8200_AXI>,
+ <&voutcrg JH7110_VOUTCLK_DC8200_AHB>,
+ <&voutcrg JH7110_VOUTCLK_DC8200_PIX0>,
+ <&voutcrg JH7110_VOUTCLK_DC8200_PIX1>;
+ clock-names = "core", "axi", "ahb", "pix0", "pix1";
+
+ resets = <&voutcrg JH7110_VOUTRST_DC8200_CORE>,
+ <&voutcrg JH7110_VOUTRST_DC8200_AXI>,
+ <&voutcrg JH7110_VOUTRST_DC8200_AHB>;
+ reset-names = "core", "axi", "ahb";
+ };
+
+ hdmi_subsystem: hdmi@29590000 {
+ compatible = "starfive,jh7110-hdmi-subsystem";
+ reg = <0x0 0x29590000 0x0 0x4000>;
+
+ /*
+ * This MFD's PHY child is the first device in the vout
+ * region to touch registers, so it owns the NoC display
+ * bus clock + reset that gate access to the region.
+ * PD_VOUT is powered on by genpd via power-domains.
+ */
+ power-domains = <&pwrc JH7110_PD_VOUT>;
+ clocks = <&syscrg JH7110_SYSCLK_NOC_BUS_DISP_AXI>;
+ resets = <&syscrg JH7110_SYSRST_NOC_BUS_DISP_AXI>;
+
+ hdmi_phy: phy {
+ compatible = "starfive,jh7110-inno-hdmi-phy";
+
+ clocks = <&xin24m>;
+ clock-names = "refoclk";
+
+ /* Output clock: The variable pixel clock */
+ #clock-cells = <0>;
+ clock-output-names = "hdmi_pclk";
+
+ /* PHY provider for the controller */
+ #phy-cells = <0>;
+ };
+
+ hdmi_controller: controller {
+ compatible = "starfive,jh7110-inno-hdmi-controller";
+ interrupts = <99>;
+
+ clocks = <&voutcrg JH7110_VOUTCLK_HDMI_TX_SYS>,
+ <&voutcrg JH7110_VOUTCLK_HDMI_TX_MCLK>,
+ <&voutcrg JH7110_VOUTCLK_HDMI_TX_BCLK>,
+ <&hdmi_phy>;
+ clock-names = "sys", "mclk", "bclk", "pclk";
+
+ resets = <&voutcrg JH7110_VOUTRST_HDMI_TX_HDMI>;
+ reset-names = "hdmi_tx";
+
+ phys = <&hdmi_phy>;
+ phy-names = "hdmi-phy";
+ };
+ };
+
voutcrg: clock-controller@295c0000 {
compatible = "starfive,jh7110-voutcrg";
reg = <0x0 0x295c0000 0x0 0x10000>;
+
+ power-domains = <&pwrc JH7110_PD_VOUT>;
+
clocks = <&syscrg JH7110_SYSCLK_VOUT_SRC>,
<&syscrg JH7110_SYSCLK_VOUT_TOP_AHB>,
<&syscrg JH7110_SYSCLK_VOUT_TOP_AXI>,
<&syscrg JH7110_SYSCLK_VOUT_TOP_HDMITX0_MCLK>,
<&syscrg JH7110_SYSCLK_I2STX0_BCLK>,
- <&hdmitx0_pixelclk>;
+ <&hdmi_phy>;
clock-names = "vout_src", "vout_top_ahb",
"vout_top_axi", "vout_top_hdmitx0_mclk",
"i2stx0_bclk", "hdmitx0_pixelclk";
+
resets = <&syscrg JH7110_SYSRST_VOUT_TOP_SRC>;
#clock-cells = <1>;
#reset-cells = <1>;
- power-domains = <&pwrc JH7110_PD_VOUT>;
};
pcie0: pcie@940000000 {
--
2.34.1
--
linux-phy mailing list
linux-phy@lists.infradead.org
https://lists.infradead.org/mailman/listinfo/linux-phy
^ permalink raw reply related [flat|nested] 116+ messages in thread
* [PATCH v2 14/15] riscv: dts: starfive: jh7110: Update DT for display subsystem
@ 2026-08-28 13:47 ` Michal Wilczynski
0 siblings, 0 replies; 116+ messages in thread
From: Michal Wilczynski @ 2026-08-28 13:47 UTC (permalink / raw)
To: Vinod Koul, Neil Armstrong, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Andrzej Hajda, Robert Foss, Laurent Pinchart,
Jonas Karlman, Jernej Skrabec, Luca Ceresoli, David Airlie,
Simona Vetter, Maarten Lankhorst, Maxime Ripard,
Thomas Zimmermann, Lee Jones, Andy Yan, Philipp Zabel,
Emil Renner Berthing, Hal Feng, Michael Turquette, Stephen Boyd,
Brian Masney, Heiko Stuebner, Conor Dooley, Paul Walmsley,
Palmer Dabbelt, Albert Ou, Alexandre Ghiti, Dominique Belhachemi
Cc: devicetree, mfd, linux-kernel, dri-devel, Andy Yan,
Graham Markall, linux-rockchip, linux-phy, Michal Wilczynski,
linux-riscv, Maud Spierings, linux-clk, linux-arm-kernel,
Marek Szyprowski
Activate the display subsystem by adding the dc8200, hdmi and voutcrg
nodes as direct soc children. Each references the PD_VOUT power domain
through power-domains, so genpd powers the domain on demand, and the
HDMI-PHY -> voutcrg -> HDMI-controller probe order is resolved by
deferred probe.
The monolithic hdmi node is modelled as a container with hdmi_phy
and hdmi_controller children. This lets the PHY (clock provider,
depending only on xin24m) and the controller (clock consumer) probe
independently, breaking the circular clock dependency with voutcrg.
voutcrg consumes the pixel clock from the &hdmi_phy node instead of the
old fixed-clock, and dc8200 gets its pixel clocks from voutcrg's MUXes
and is marked dma-noncoherent for framebuffer DMA. The old, incorrect
hdmitx0-pixel-clock fixed-clock node is removed.
Co-developed-by: Dominique Belhachemi <db@domibel.de>
Signed-off-by: Dominique Belhachemi <db@domibel.de>
Signed-off-by: Michal Wilczynski <m.wilczynski@samsung.com>
---
arch/riscv/boot/dts/starfive/jh7110-common.dtsi | 119 +++++++++++++++++++++++-
arch/riscv/boot/dts/starfive/jh7110.dtsi | 87 +++++++++++++++--
2 files changed, 196 insertions(+), 10 deletions(-)
diff --git a/arch/riscv/boot/dts/starfive/jh7110-common.dtsi b/arch/riscv/boot/dts/starfive/jh7110-common.dtsi
index a7a1c09a2c9075711f3a214a49618911fdc7b421..7aadc35f4a6aa724c86a868ef65c5c829e666ee2 100644
--- a/arch/riscv/boot/dts/starfive/jh7110-common.dtsi
+++ b/arch/riscv/boot/dts/starfive/jh7110-common.dtsi
@@ -33,6 +33,25 @@ memory@40000000 {
bootph-pre-ram;
};
+ reserved-memory {
+ #address-cells = <2>;
+ #size-cells = <2>;
+ ranges;
+
+ /* vout applies for space from this CMA
+ * Without this CMA reservation,
+ * vout may not work properly.
+ */
+ linux,cma {
+ compatible = "shared-dma-pool";
+ reusable;
+ size = <0x0 0x20000000>;
+ alignment = <0x0 0x1000>;
+ alloc-ranges = <0x0 0x70000000 0x0 0x20000000>;
+ linux,cma-default;
+ };
+ };
+
gpio-restart {
compatible = "gpio-restart";
gpios = <&sysgpio 35 GPIO_ACTIVE_HIGH>;
@@ -73,12 +92,47 @@ codec {
};
};
};
+
+ hdmi-connector {
+ compatible = "hdmi-connector";
+ type = "a";
+
+ port {
+ hdmi_con_in: endpoint {
+ remote-endpoint = <&hdmi_out_con>;
+ };
+ };
+ };
};
&cpus {
timebase-frequency = <4000000>;
};
+&dc8200 {
+ status = "okay";
+
+ ports {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ dpu_port0: port@0 {
+ reg = <0>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ dpu_out_dpi0: endpoint@0 {
+ reg = <0>;
+ remote-endpoint = <&hdmi_in>;
+ };
+ };
+
+ dpu_port1: port@1 {
+ reg = <1>;
+ };
+ };
+};
+
&dvp_clk {
clock-frequency = <74250000>;
};
@@ -99,8 +153,31 @@ &gmac1_rmii_refin {
clock-frequency = <50000000>;
};
-&hdmitx0_pixelclk {
- clock-frequency = <297000000>;
+&hdmi_controller {
+ status = "okay";
+ pinctrl-names = "default";
+ pinctrl-0 = <&hdmi_pins>;
+
+ ports {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ port@0 {
+ reg = <0>;
+
+ hdmi_in: endpoint {
+ remote-endpoint = <&dpu_out_dpi0>;
+ };
+ };
+
+ hdmi_out_port: port@1 {
+ reg = <1>;
+ hdmi_out_con: endpoint {
+ remote-endpoint = <&hdmi_con_in>;
+ };
+
+ };
+ };
};
&i2srx_bclk_ext {
@@ -351,6 +428,40 @@ &syscrg {
};
&sysgpio {
+ hdmi_pins: hdmi-0 {
+ hdmi-cec-pins {
+ pinmux = <GPIOMUX(14, GPOUT_SYS_HDMI_CEC_SDA,
+ GPOEN_SYS_HDMI_CEC_SDA,
+ GPI_SYS_HDMI_CEC_SDA)>;
+ input-enable;
+ bias-pull-up;
+ };
+
+ hdmi-hpd-pins {
+ pinmux = <GPIOMUX(15, GPOUT_HIGH,
+ GPOEN_ENABLE,
+ GPI_SYS_HDMI_HPD)>;
+ input-enable;
+ bias-disable; /* external pull-up */
+ };
+
+ hdmi-scl-pins {
+ pinmux = <GPIOMUX(0, GPOUT_SYS_HDMI_DDC_SCL,
+ GPOEN_SYS_HDMI_DDC_SCL,
+ GPI_SYS_HDMI_DDC_SCL)>;
+ input-enable;
+ bias-pull-up;
+ };
+
+ hdmi-sda-pins {
+ pinmux = <GPIOMUX(1, GPOUT_SYS_HDMI_DDC_SDA,
+ GPOEN_SYS_HDMI_DDC_SDA,
+ GPI_SYS_HDMI_DDC_SDA)>;
+ input-enable;
+ bias-pull-up;
+ };
+ };
+
i2c0_pins: i2c0-0 {
i2c-pins {
pinmux = <GPIOMUX(57, GPOUT_LOW,
@@ -629,3 +740,7 @@ &U74_3 {
&U74_4 {
cpu-supply = <&vdd_cpu>;
};
+
+&voutcrg {
+ status = "okay";
+};
diff --git a/arch/riscv/boot/dts/starfive/jh7110.dtsi b/arch/riscv/boot/dts/starfive/jh7110.dtsi
index 9c3e4598747eb5541effe697044484715569a285..024e33b0e97cb13928d69d1d8090ed14d22bb022 100644
--- a/arch/riscv/boot/dts/starfive/jh7110.dtsi
+++ b/arch/riscv/boot/dts/starfive/jh7110.dtsi
@@ -290,12 +290,6 @@ gmac1_rmii_refin: gmac1-rmii-refin-clock {
#clock-cells = <0>;
};
- hdmitx0_pixelclk: hdmitx0-pixel-clock {
- compatible = "fixed-clock";
- clock-output-names = "hdmitx0_pixelclk";
- #clock-cells = <0>;
- };
-
i2srx_bclk_ext: i2srx-bclk-ext-clock {
compatible = "fixed-clock";
clock-output-names = "i2srx_bclk_ext";
@@ -352,6 +346,13 @@ tdm_ext: tdm-ext-clock {
#clock-cells = <0>;
};
+ xin24m: xin24m {
+ compatible = "fixed-clock";
+ #clock-cells = <0>;
+ clock-frequency = <24000000>;
+ clock-output-names = "xin24m";
+ };
+
soc {
compatible = "simple-bus";
interrupt-parent = <&plic>;
@@ -1199,22 +1200,92 @@ csi_phy: phy@19820000 {
#phy-cells = <0>;
};
+ dc8200: display@29400000 {
+ compatible = "verisilicon,dc";
+ reg = <0x0 0x29400000 0x0 0x2800>;
+ interrupts = <95>;
+ dma-noncoherent;
+
+ power-domains = <&pwrc JH7110_PD_VOUT>;
+
+ clocks = <&voutcrg JH7110_VOUTCLK_DC8200_CORE>,
+ <&voutcrg JH7110_VOUTCLK_DC8200_AXI>,
+ <&voutcrg JH7110_VOUTCLK_DC8200_AHB>,
+ <&voutcrg JH7110_VOUTCLK_DC8200_PIX0>,
+ <&voutcrg JH7110_VOUTCLK_DC8200_PIX1>;
+ clock-names = "core", "axi", "ahb", "pix0", "pix1";
+
+ resets = <&voutcrg JH7110_VOUTRST_DC8200_CORE>,
+ <&voutcrg JH7110_VOUTRST_DC8200_AXI>,
+ <&voutcrg JH7110_VOUTRST_DC8200_AHB>;
+ reset-names = "core", "axi", "ahb";
+ };
+
+ hdmi_subsystem: hdmi@29590000 {
+ compatible = "starfive,jh7110-hdmi-subsystem";
+ reg = <0x0 0x29590000 0x0 0x4000>;
+
+ /*
+ * This MFD's PHY child is the first device in the vout
+ * region to touch registers, so it owns the NoC display
+ * bus clock + reset that gate access to the region.
+ * PD_VOUT is powered on by genpd via power-domains.
+ */
+ power-domains = <&pwrc JH7110_PD_VOUT>;
+ clocks = <&syscrg JH7110_SYSCLK_NOC_BUS_DISP_AXI>;
+ resets = <&syscrg JH7110_SYSRST_NOC_BUS_DISP_AXI>;
+
+ hdmi_phy: phy {
+ compatible = "starfive,jh7110-inno-hdmi-phy";
+
+ clocks = <&xin24m>;
+ clock-names = "refoclk";
+
+ /* Output clock: The variable pixel clock */
+ #clock-cells = <0>;
+ clock-output-names = "hdmi_pclk";
+
+ /* PHY provider for the controller */
+ #phy-cells = <0>;
+ };
+
+ hdmi_controller: controller {
+ compatible = "starfive,jh7110-inno-hdmi-controller";
+ interrupts = <99>;
+
+ clocks = <&voutcrg JH7110_VOUTCLK_HDMI_TX_SYS>,
+ <&voutcrg JH7110_VOUTCLK_HDMI_TX_MCLK>,
+ <&voutcrg JH7110_VOUTCLK_HDMI_TX_BCLK>,
+ <&hdmi_phy>;
+ clock-names = "sys", "mclk", "bclk", "pclk";
+
+ resets = <&voutcrg JH7110_VOUTRST_HDMI_TX_HDMI>;
+ reset-names = "hdmi_tx";
+
+ phys = <&hdmi_phy>;
+ phy-names = "hdmi-phy";
+ };
+ };
+
voutcrg: clock-controller@295c0000 {
compatible = "starfive,jh7110-voutcrg";
reg = <0x0 0x295c0000 0x0 0x10000>;
+
+ power-domains = <&pwrc JH7110_PD_VOUT>;
+
clocks = <&syscrg JH7110_SYSCLK_VOUT_SRC>,
<&syscrg JH7110_SYSCLK_VOUT_TOP_AHB>,
<&syscrg JH7110_SYSCLK_VOUT_TOP_AXI>,
<&syscrg JH7110_SYSCLK_VOUT_TOP_HDMITX0_MCLK>,
<&syscrg JH7110_SYSCLK_I2STX0_BCLK>,
- <&hdmitx0_pixelclk>;
+ <&hdmi_phy>;
clock-names = "vout_src", "vout_top_ahb",
"vout_top_axi", "vout_top_hdmitx0_mclk",
"i2stx0_bclk", "hdmitx0_pixelclk";
+
resets = <&syscrg JH7110_SYSRST_VOUT_TOP_SRC>;
#clock-cells = <1>;
#reset-cells = <1>;
- power-domains = <&pwrc JH7110_PD_VOUT>;
};
pcie0: pcie@940000000 {
--
2.34.1
_______________________________________________
linux-riscv mailing list
linux-riscv@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-riscv
^ permalink raw reply related [flat|nested] 116+ messages in thread
* [PATCH v2 14/15] riscv: dts: starfive: jh7110: Update DT for display subsystem
@ 2026-08-28 13:47 ` Michal Wilczynski
0 siblings, 0 replies; 116+ messages in thread
From: Michal Wilczynski @ 2026-08-28 13:47 UTC (permalink / raw)
To: Vinod Koul, Neil Armstrong, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Andrzej Hajda, Robert Foss, Laurent Pinchart,
Jonas Karlman, Jernej Skrabec, Luca Ceresoli, David Airlie,
Simona Vetter, Maarten Lankhorst, Maxime Ripard,
Thomas Zimmermann, Lee Jones, Andy Yan, Philipp Zabel,
Emil Renner Berthing, Hal Feng, Michael Turquette, Stephen Boyd,
Brian Masney, Heiko Stuebner, Conor Dooley, Paul Walmsley,
Palmer Dabbelt, Albert Ou, Alexandre Ghiti, Dominique Belhachemi
Cc: linux-phy, devicetree, linux-kernel, dri-devel, mfd, linux-clk,
linux-arm-kernel, linux-rockchip, linux-riscv, Icenowy Zheng,
Andy Yan, Marek Szyprowski, Maud Spierings, Graham Markall,
Michal Wilczynski
Activate the display subsystem by adding the dc8200, hdmi and voutcrg
nodes as direct soc children. Each references the PD_VOUT power domain
through power-domains, so genpd powers the domain on demand, and the
HDMI-PHY -> voutcrg -> HDMI-controller probe order is resolved by
deferred probe.
The monolithic hdmi node is modelled as a container with hdmi_phy
and hdmi_controller children. This lets the PHY (clock provider,
depending only on xin24m) and the controller (clock consumer) probe
independently, breaking the circular clock dependency with voutcrg.
voutcrg consumes the pixel clock from the &hdmi_phy node instead of the
old fixed-clock, and dc8200 gets its pixel clocks from voutcrg's MUXes
and is marked dma-noncoherent for framebuffer DMA. The old, incorrect
hdmitx0-pixel-clock fixed-clock node is removed.
Co-developed-by: Dominique Belhachemi <db@domibel.de>
Signed-off-by: Dominique Belhachemi <db@domibel.de>
Signed-off-by: Michal Wilczynski <m.wilczynski@samsung.com>
---
arch/riscv/boot/dts/starfive/jh7110-common.dtsi | 119 +++++++++++++++++++++++-
arch/riscv/boot/dts/starfive/jh7110.dtsi | 87 +++++++++++++++--
2 files changed, 196 insertions(+), 10 deletions(-)
diff --git a/arch/riscv/boot/dts/starfive/jh7110-common.dtsi b/arch/riscv/boot/dts/starfive/jh7110-common.dtsi
index a7a1c09a2c9075711f3a214a49618911fdc7b421..7aadc35f4a6aa724c86a868ef65c5c829e666ee2 100644
--- a/arch/riscv/boot/dts/starfive/jh7110-common.dtsi
+++ b/arch/riscv/boot/dts/starfive/jh7110-common.dtsi
@@ -33,6 +33,25 @@ memory@40000000 {
bootph-pre-ram;
};
+ reserved-memory {
+ #address-cells = <2>;
+ #size-cells = <2>;
+ ranges;
+
+ /* vout applies for space from this CMA
+ * Without this CMA reservation,
+ * vout may not work properly.
+ */
+ linux,cma {
+ compatible = "shared-dma-pool";
+ reusable;
+ size = <0x0 0x20000000>;
+ alignment = <0x0 0x1000>;
+ alloc-ranges = <0x0 0x70000000 0x0 0x20000000>;
+ linux,cma-default;
+ };
+ };
+
gpio-restart {
compatible = "gpio-restart";
gpios = <&sysgpio 35 GPIO_ACTIVE_HIGH>;
@@ -73,12 +92,47 @@ codec {
};
};
};
+
+ hdmi-connector {
+ compatible = "hdmi-connector";
+ type = "a";
+
+ port {
+ hdmi_con_in: endpoint {
+ remote-endpoint = <&hdmi_out_con>;
+ };
+ };
+ };
};
&cpus {
timebase-frequency = <4000000>;
};
+&dc8200 {
+ status = "okay";
+
+ ports {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ dpu_port0: port@0 {
+ reg = <0>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ dpu_out_dpi0: endpoint@0 {
+ reg = <0>;
+ remote-endpoint = <&hdmi_in>;
+ };
+ };
+
+ dpu_port1: port@1 {
+ reg = <1>;
+ };
+ };
+};
+
&dvp_clk {
clock-frequency = <74250000>;
};
@@ -99,8 +153,31 @@ &gmac1_rmii_refin {
clock-frequency = <50000000>;
};
-&hdmitx0_pixelclk {
- clock-frequency = <297000000>;
+&hdmi_controller {
+ status = "okay";
+ pinctrl-names = "default";
+ pinctrl-0 = <&hdmi_pins>;
+
+ ports {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ port@0 {
+ reg = <0>;
+
+ hdmi_in: endpoint {
+ remote-endpoint = <&dpu_out_dpi0>;
+ };
+ };
+
+ hdmi_out_port: port@1 {
+ reg = <1>;
+ hdmi_out_con: endpoint {
+ remote-endpoint = <&hdmi_con_in>;
+ };
+
+ };
+ };
};
&i2srx_bclk_ext {
@@ -351,6 +428,40 @@ &syscrg {
};
&sysgpio {
+ hdmi_pins: hdmi-0 {
+ hdmi-cec-pins {
+ pinmux = <GPIOMUX(14, GPOUT_SYS_HDMI_CEC_SDA,
+ GPOEN_SYS_HDMI_CEC_SDA,
+ GPI_SYS_HDMI_CEC_SDA)>;
+ input-enable;
+ bias-pull-up;
+ };
+
+ hdmi-hpd-pins {
+ pinmux = <GPIOMUX(15, GPOUT_HIGH,
+ GPOEN_ENABLE,
+ GPI_SYS_HDMI_HPD)>;
+ input-enable;
+ bias-disable; /* external pull-up */
+ };
+
+ hdmi-scl-pins {
+ pinmux = <GPIOMUX(0, GPOUT_SYS_HDMI_DDC_SCL,
+ GPOEN_SYS_HDMI_DDC_SCL,
+ GPI_SYS_HDMI_DDC_SCL)>;
+ input-enable;
+ bias-pull-up;
+ };
+
+ hdmi-sda-pins {
+ pinmux = <GPIOMUX(1, GPOUT_SYS_HDMI_DDC_SDA,
+ GPOEN_SYS_HDMI_DDC_SDA,
+ GPI_SYS_HDMI_DDC_SDA)>;
+ input-enable;
+ bias-pull-up;
+ };
+ };
+
i2c0_pins: i2c0-0 {
i2c-pins {
pinmux = <GPIOMUX(57, GPOUT_LOW,
@@ -629,3 +740,7 @@ &U74_3 {
&U74_4 {
cpu-supply = <&vdd_cpu>;
};
+
+&voutcrg {
+ status = "okay";
+};
diff --git a/arch/riscv/boot/dts/starfive/jh7110.dtsi b/arch/riscv/boot/dts/starfive/jh7110.dtsi
index 9c3e4598747eb5541effe697044484715569a285..024e33b0e97cb13928d69d1d8090ed14d22bb022 100644
--- a/arch/riscv/boot/dts/starfive/jh7110.dtsi
+++ b/arch/riscv/boot/dts/starfive/jh7110.dtsi
@@ -290,12 +290,6 @@ gmac1_rmii_refin: gmac1-rmii-refin-clock {
#clock-cells = <0>;
};
- hdmitx0_pixelclk: hdmitx0-pixel-clock {
- compatible = "fixed-clock";
- clock-output-names = "hdmitx0_pixelclk";
- #clock-cells = <0>;
- };
-
i2srx_bclk_ext: i2srx-bclk-ext-clock {
compatible = "fixed-clock";
clock-output-names = "i2srx_bclk_ext";
@@ -352,6 +346,13 @@ tdm_ext: tdm-ext-clock {
#clock-cells = <0>;
};
+ xin24m: xin24m {
+ compatible = "fixed-clock";
+ #clock-cells = <0>;
+ clock-frequency = <24000000>;
+ clock-output-names = "xin24m";
+ };
+
soc {
compatible = "simple-bus";
interrupt-parent = <&plic>;
@@ -1199,22 +1200,92 @@ csi_phy: phy@19820000 {
#phy-cells = <0>;
};
+ dc8200: display@29400000 {
+ compatible = "verisilicon,dc";
+ reg = <0x0 0x29400000 0x0 0x2800>;
+ interrupts = <95>;
+ dma-noncoherent;
+
+ power-domains = <&pwrc JH7110_PD_VOUT>;
+
+ clocks = <&voutcrg JH7110_VOUTCLK_DC8200_CORE>,
+ <&voutcrg JH7110_VOUTCLK_DC8200_AXI>,
+ <&voutcrg JH7110_VOUTCLK_DC8200_AHB>,
+ <&voutcrg JH7110_VOUTCLK_DC8200_PIX0>,
+ <&voutcrg JH7110_VOUTCLK_DC8200_PIX1>;
+ clock-names = "core", "axi", "ahb", "pix0", "pix1";
+
+ resets = <&voutcrg JH7110_VOUTRST_DC8200_CORE>,
+ <&voutcrg JH7110_VOUTRST_DC8200_AXI>,
+ <&voutcrg JH7110_VOUTRST_DC8200_AHB>;
+ reset-names = "core", "axi", "ahb";
+ };
+
+ hdmi_subsystem: hdmi@29590000 {
+ compatible = "starfive,jh7110-hdmi-subsystem";
+ reg = <0x0 0x29590000 0x0 0x4000>;
+
+ /*
+ * This MFD's PHY child is the first device in the vout
+ * region to touch registers, so it owns the NoC display
+ * bus clock + reset that gate access to the region.
+ * PD_VOUT is powered on by genpd via power-domains.
+ */
+ power-domains = <&pwrc JH7110_PD_VOUT>;
+ clocks = <&syscrg JH7110_SYSCLK_NOC_BUS_DISP_AXI>;
+ resets = <&syscrg JH7110_SYSRST_NOC_BUS_DISP_AXI>;
+
+ hdmi_phy: phy {
+ compatible = "starfive,jh7110-inno-hdmi-phy";
+
+ clocks = <&xin24m>;
+ clock-names = "refoclk";
+
+ /* Output clock: The variable pixel clock */
+ #clock-cells = <0>;
+ clock-output-names = "hdmi_pclk";
+
+ /* PHY provider for the controller */
+ #phy-cells = <0>;
+ };
+
+ hdmi_controller: controller {
+ compatible = "starfive,jh7110-inno-hdmi-controller";
+ interrupts = <99>;
+
+ clocks = <&voutcrg JH7110_VOUTCLK_HDMI_TX_SYS>,
+ <&voutcrg JH7110_VOUTCLK_HDMI_TX_MCLK>,
+ <&voutcrg JH7110_VOUTCLK_HDMI_TX_BCLK>,
+ <&hdmi_phy>;
+ clock-names = "sys", "mclk", "bclk", "pclk";
+
+ resets = <&voutcrg JH7110_VOUTRST_HDMI_TX_HDMI>;
+ reset-names = "hdmi_tx";
+
+ phys = <&hdmi_phy>;
+ phy-names = "hdmi-phy";
+ };
+ };
+
voutcrg: clock-controller@295c0000 {
compatible = "starfive,jh7110-voutcrg";
reg = <0x0 0x295c0000 0x0 0x10000>;
+
+ power-domains = <&pwrc JH7110_PD_VOUT>;
+
clocks = <&syscrg JH7110_SYSCLK_VOUT_SRC>,
<&syscrg JH7110_SYSCLK_VOUT_TOP_AHB>,
<&syscrg JH7110_SYSCLK_VOUT_TOP_AXI>,
<&syscrg JH7110_SYSCLK_VOUT_TOP_HDMITX0_MCLK>,
<&syscrg JH7110_SYSCLK_I2STX0_BCLK>,
- <&hdmitx0_pixelclk>;
+ <&hdmi_phy>;
clock-names = "vout_src", "vout_top_ahb",
"vout_top_axi", "vout_top_hdmitx0_mclk",
"i2stx0_bclk", "hdmitx0_pixelclk";
+
resets = <&syscrg JH7110_SYSRST_VOUT_TOP_SRC>;
#clock-cells = <1>;
#reset-cells = <1>;
- power-domains = <&pwrc JH7110_PD_VOUT>;
};
pcie0: pcie@940000000 {
--
2.34.1
_______________________________________________
Linux-rockchip mailing list
Linux-rockchip@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-rockchip
^ permalink raw reply related [flat|nested] 116+ messages in thread
* [PATCH v2 15/15] MAINTAINERS: Add StarFive JH7110 display subsystem entry
2026-08-28 13:47 ` Michal Wilczynski
(?)
(?)
@ 2026-08-28 13:47 ` Michal Wilczynski
-1 siblings, 0 replies; 116+ messages in thread
From: Michal Wilczynski @ 2026-08-28 13:47 UTC (permalink / raw)
To: Vinod Koul, Neil Armstrong, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Andrzej Hajda, Robert Foss, Laurent Pinchart,
Jonas Karlman, Jernej Skrabec, Luca Ceresoli, David Airlie,
Simona Vetter, Maarten Lankhorst, Maxime Ripard,
Thomas Zimmermann, Lee Jones, Andy Yan, Philipp Zabel,
Emil Renner Berthing, Hal Feng, Michael Turquette, Stephen Boyd,
Brian Masney, Heiko Stuebner, Conor Dooley, Paul Walmsley,
Palmer Dabbelt, Albert Ou, Alexandre Ghiti, Dominique Belhachemi
Cc: linux-phy, devicetree, linux-kernel, dri-devel, mfd, linux-clk,
linux-arm-kernel, linux-rockchip, linux-riscv, Icenowy Zheng,
Andy Yan, Marek Szyprowski, Maud Spierings, Graham Markall,
Michal Wilczynski
The JH7110 display subsystem spans a PHY driver, a DRM bridge driver,
a parent device and their bindings, and has no existing maintainer entry.
Add an entry covering them so patches reach someone who can review them.
Signed-off-by: Michal Wilczynski <m.wilczynski@samsung.com>
---
MAINTAINERS | 10 ++++++++++
1 file changed, 10 insertions(+)
diff --git a/MAINTAINERS b/MAINTAINERS
index 8014b9f8253edf15231df215d1b14063a54a55ec..84ac5cfe61cdf775167cf9033862724c37946a5f 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -25778,6 +25778,16 @@ S: Maintained
F: Documentation/devicetree/bindings/net/starfive,jh7110-dwmac.yaml
F: drivers/net/ethernet/stmicro/stmmac/dwmac-starfive.c
+STARFIVE JH7110 DISPLAY SUBSYSTEM
+M: Michal Wilczynski <m.wilczynski@samsung.com>
+S: Maintained
+F: Documentation/devicetree/bindings/display/bridge/starfive,jh7110-inno-hdmi-controller.yaml
+F: Documentation/devicetree/bindings/mfd/starfive,jh7110-hdmi-subsystem.yaml
+F: Documentation/devicetree/bindings/phy/starfive,jh7110-inno-hdmi-phy.yaml
+F: drivers/gpu/drm/bridge/jh7110-inno-hdmi.c
+F: drivers/phy/starfive/phy-jh7110-inno-hdmi.c
+F: drivers/soc/starfive/jh7110-hdmi-subsystem.c
+
STARFIVE JH7110 DPHY RX DRIVER
M: Jack Zhu <jack.zhu@starfivetech.com>
M: Changhuang Liang <changhuang.liang@starfivetech.com>
--
2.34.1
^ permalink raw reply related [flat|nested] 116+ messages in thread
* [PATCH v2 15/15] MAINTAINERS: Add StarFive JH7110 display subsystem entry
@ 2026-08-28 13:47 ` Michal Wilczynski
0 siblings, 0 replies; 116+ messages in thread
From: Michal Wilczynski @ 2026-08-28 13:47 UTC (permalink / raw)
To: Vinod Koul, Neil Armstrong, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Andrzej Hajda, Robert Foss, Laurent Pinchart,
Jonas Karlman, Jernej Skrabec, Luca Ceresoli, David Airlie,
Simona Vetter, Maarten Lankhorst, Maxime Ripard,
Thomas Zimmermann, Lee Jones, Andy Yan, Philipp Zabel,
Emil Renner Berthing, Hal Feng, Michael Turquette, Stephen Boyd,
Brian Masney, Heiko Stuebner, Conor Dooley, Paul Walmsley,
Palmer Dabbelt, Albert Ou, Alexandre Ghiti, Dominique Belhachemi
Cc: devicetree, mfd, linux-kernel, dri-devel, Andy Yan,
Graham Markall, linux-rockchip, linux-phy, Michal Wilczynski,
linux-riscv, Maud Spierings, linux-clk, linux-arm-kernel,
Marek Szyprowski
The JH7110 display subsystem spans a PHY driver, a DRM bridge driver,
a parent device and their bindings, and has no existing maintainer entry.
Add an entry covering them so patches reach someone who can review them.
Signed-off-by: Michal Wilczynski <m.wilczynski@samsung.com>
---
MAINTAINERS | 10 ++++++++++
1 file changed, 10 insertions(+)
diff --git a/MAINTAINERS b/MAINTAINERS
index 8014b9f8253edf15231df215d1b14063a54a55ec..84ac5cfe61cdf775167cf9033862724c37946a5f 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -25778,6 +25778,16 @@ S: Maintained
F: Documentation/devicetree/bindings/net/starfive,jh7110-dwmac.yaml
F: drivers/net/ethernet/stmicro/stmmac/dwmac-starfive.c
+STARFIVE JH7110 DISPLAY SUBSYSTEM
+M: Michal Wilczynski <m.wilczynski@samsung.com>
+S: Maintained
+F: Documentation/devicetree/bindings/display/bridge/starfive,jh7110-inno-hdmi-controller.yaml
+F: Documentation/devicetree/bindings/mfd/starfive,jh7110-hdmi-subsystem.yaml
+F: Documentation/devicetree/bindings/phy/starfive,jh7110-inno-hdmi-phy.yaml
+F: drivers/gpu/drm/bridge/jh7110-inno-hdmi.c
+F: drivers/phy/starfive/phy-jh7110-inno-hdmi.c
+F: drivers/soc/starfive/jh7110-hdmi-subsystem.c
+
STARFIVE JH7110 DPHY RX DRIVER
M: Jack Zhu <jack.zhu@starfivetech.com>
M: Changhuang Liang <changhuang.liang@starfivetech.com>
--
2.34.1
_______________________________________________
linux-riscv mailing list
linux-riscv@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-riscv
^ permalink raw reply related [flat|nested] 116+ messages in thread
* [PATCH v2 15/15] MAINTAINERS: Add StarFive JH7110 display subsystem entry
@ 2026-08-28 13:47 ` Michal Wilczynski
0 siblings, 0 replies; 116+ messages in thread
From: Michal Wilczynski @ 2026-08-28 13:47 UTC (permalink / raw)
To: Vinod Koul, Neil Armstrong, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Andrzej Hajda, Robert Foss, Laurent Pinchart,
Jonas Karlman, Jernej Skrabec, Luca Ceresoli, David Airlie,
Simona Vetter, Maarten Lankhorst, Maxime Ripard,
Thomas Zimmermann, Lee Jones, Andy Yan, Philipp Zabel,
Emil Renner Berthing, Hal Feng, Michael Turquette, Stephen Boyd,
Brian Masney, Heiko Stuebner, Conor Dooley, Paul Walmsley,
Palmer Dabbelt, Albert Ou, Alexandre Ghiti, Dominique Belhachemi
Cc: linux-phy, devicetree, linux-kernel, dri-devel, mfd, linux-clk,
linux-arm-kernel, linux-rockchip, linux-riscv, Icenowy Zheng,
Andy Yan, Marek Szyprowski, Maud Spierings, Graham Markall,
Michal Wilczynski
The JH7110 display subsystem spans a PHY driver, a DRM bridge driver,
a parent device and their bindings, and has no existing maintainer entry.
Add an entry covering them so patches reach someone who can review them.
Signed-off-by: Michal Wilczynski <m.wilczynski@samsung.com>
---
MAINTAINERS | 10 ++++++++++
1 file changed, 10 insertions(+)
diff --git a/MAINTAINERS b/MAINTAINERS
index 8014b9f8253edf15231df215d1b14063a54a55ec..84ac5cfe61cdf775167cf9033862724c37946a5f 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -25778,6 +25778,16 @@ S: Maintained
F: Documentation/devicetree/bindings/net/starfive,jh7110-dwmac.yaml
F: drivers/net/ethernet/stmicro/stmmac/dwmac-starfive.c
+STARFIVE JH7110 DISPLAY SUBSYSTEM
+M: Michal Wilczynski <m.wilczynski@samsung.com>
+S: Maintained
+F: Documentation/devicetree/bindings/display/bridge/starfive,jh7110-inno-hdmi-controller.yaml
+F: Documentation/devicetree/bindings/mfd/starfive,jh7110-hdmi-subsystem.yaml
+F: Documentation/devicetree/bindings/phy/starfive,jh7110-inno-hdmi-phy.yaml
+F: drivers/gpu/drm/bridge/jh7110-inno-hdmi.c
+F: drivers/phy/starfive/phy-jh7110-inno-hdmi.c
+F: drivers/soc/starfive/jh7110-hdmi-subsystem.c
+
STARFIVE JH7110 DPHY RX DRIVER
M: Jack Zhu <jack.zhu@starfivetech.com>
M: Changhuang Liang <changhuang.liang@starfivetech.com>
--
2.34.1
_______________________________________________
Linux-rockchip mailing list
Linux-rockchip@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-rockchip
^ permalink raw reply related [flat|nested] 116+ messages in thread
* [PATCH v2 15/15] MAINTAINERS: Add StarFive JH7110 display subsystem entry
@ 2026-08-28 13:47 ` Michal Wilczynski
0 siblings, 0 replies; 116+ messages in thread
From: Michal Wilczynski @ 2026-08-28 13:47 UTC (permalink / raw)
To: Vinod Koul, Neil Armstrong, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Andrzej Hajda, Robert Foss, Laurent Pinchart,
Jonas Karlman, Jernej Skrabec, Luca Ceresoli, David Airlie,
Simona Vetter, Maarten Lankhorst, Maxime Ripard,
Thomas Zimmermann, Lee Jones, Andy Yan, Philipp Zabel,
Emil Renner Berthing, Hal Feng, Michael Turquette, Stephen Boyd,
Brian Masney, Heiko Stuebner, Conor Dooley, Paul Walmsley,
Palmer Dabbelt, Albert Ou, Alexandre Ghiti, Dominique Belhachemi
Cc: linux-phy, devicetree, linux-kernel, dri-devel, mfd, linux-clk,
linux-arm-kernel, linux-rockchip, linux-riscv, Icenowy Zheng,
Andy Yan, Marek Szyprowski, Maud Spierings, Graham Markall,
Michal Wilczynski
The JH7110 display subsystem spans a PHY driver, a DRM bridge driver,
a parent device and their bindings, and has no existing maintainer entry.
Add an entry covering them so patches reach someone who can review them.
Signed-off-by: Michal Wilczynski <m.wilczynski@samsung.com>
---
MAINTAINERS | 10 ++++++++++
1 file changed, 10 insertions(+)
diff --git a/MAINTAINERS b/MAINTAINERS
index 8014b9f8253edf15231df215d1b14063a54a55ec..84ac5cfe61cdf775167cf9033862724c37946a5f 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -25778,6 +25778,16 @@ S: Maintained
F: Documentation/devicetree/bindings/net/starfive,jh7110-dwmac.yaml
F: drivers/net/ethernet/stmicro/stmmac/dwmac-starfive.c
+STARFIVE JH7110 DISPLAY SUBSYSTEM
+M: Michal Wilczynski <m.wilczynski@samsung.com>
+S: Maintained
+F: Documentation/devicetree/bindings/display/bridge/starfive,jh7110-inno-hdmi-controller.yaml
+F: Documentation/devicetree/bindings/mfd/starfive,jh7110-hdmi-subsystem.yaml
+F: Documentation/devicetree/bindings/phy/starfive,jh7110-inno-hdmi-phy.yaml
+F: drivers/gpu/drm/bridge/jh7110-inno-hdmi.c
+F: drivers/phy/starfive/phy-jh7110-inno-hdmi.c
+F: drivers/soc/starfive/jh7110-hdmi-subsystem.c
+
STARFIVE JH7110 DPHY RX DRIVER
M: Jack Zhu <jack.zhu@starfivetech.com>
M: Changhuang Liang <changhuang.liang@starfivetech.com>
--
2.34.1
--
linux-phy mailing list
linux-phy@lists.infradead.org
https://lists.infradead.org/mailman/listinfo/linux-phy
^ permalink raw reply related [flat|nested] 116+ messages in thread
* Re: [PATCH v2 07/15] drm/bridge: inno-hdmi: Add .mode_valid platform operation
2026-08-28 13:47 ` Michal Wilczynski
@ 2026-08-28 13:52 ` sashiko-bot
-1 siblings, 0 replies; 116+ messages in thread
From: sashiko-bot @ 2026-08-28 13:52 UTC (permalink / raw)
To: Michal Wilczynski
Cc: robh, conor+dt, lee, mfd, devicetree, dri-devel, linux-clk,
olteanv, vkoul, linux-phy, neil.armstrong
> inno_hdmi_bridge_mode_valid() validates the pixel clock against
> hdmi->refclk, but that clock is optional and is only present on
> platforms that describe a "ref" clock. Platforms where the pixel clock
> is produced by a separate device - such as the StarFive JH7110, whose
> PHY is both the clock and the PHY provider - have no "ref" clock, so
> the check is skipped entirely and every mode is reported as valid.
>
> A mode the platform cannot generate is then advertised to userspace.
> The subsequent modeset appears to succeed, since the atomic enable path
> cannot fail, and the display silently stays blank.
>
> Add a .mode_valid platform operation so platforms can reject modes they
> are unable to drive. Platforms that do not implement it are unaffected.
>
> Signed-off-by: Michal Wilczynski <m.wilczynski@samsung.com>
Sashiko has reviewed this patch and found no issues. It looks great!
--
Sashiko AI review · https://sashiko.dev/#/patchset/20260828-jh7110-clean-send-v2-0-331680c8b9d1@samsung.com?part=7
^ permalink raw reply [flat|nested] 116+ messages in thread
* Re: [PATCH v2 07/15] drm/bridge: inno-hdmi: Add .mode_valid platform operation
@ 2026-08-28 13:52 ` sashiko-bot
0 siblings, 0 replies; 116+ messages in thread
From: sashiko-bot @ 2026-08-28 13:52 UTC (permalink / raw)
To: Michal Wilczynski
Cc: robh, conor+dt, lee, mfd, devicetree, dri-devel, linux-clk,
olteanv, vkoul, linux-phy, neil.armstrong
> inno_hdmi_bridge_mode_valid() validates the pixel clock against
> hdmi->refclk, but that clock is optional and is only present on
> platforms that describe a "ref" clock. Platforms where the pixel clock
> is produced by a separate device - such as the StarFive JH7110, whose
> PHY is both the clock and the PHY provider - have no "ref" clock, so
> the check is skipped entirely and every mode is reported as valid.
>
> A mode the platform cannot generate is then advertised to userspace.
> The subsequent modeset appears to succeed, since the atomic enable path
> cannot fail, and the display silently stays blank.
>
> Add a .mode_valid platform operation so platforms can reject modes they
> are unable to drive. Platforms that do not implement it are unaffected.
>
> Signed-off-by: Michal Wilczynski <m.wilczynski@samsung.com>
Sashiko has reviewed this patch and found no issues. It looks great!
--
Sashiko AI review · https://sashiko.dev/#/patchset/20260828-jh7110-clean-send-v2-0-331680c8b9d1@samsung.com?part=7
--
linux-phy mailing list
linux-phy@lists.infradead.org
https://lists.infradead.org/mailman/listinfo/linux-phy
^ permalink raw reply [flat|nested] 116+ messages in thread
* Re: [PATCH v2 03/15] dt-bindings: mfd: Add starfive,jh7110-hdmi-subsystem
2026-08-28 13:47 ` Michal Wilczynski
@ 2026-08-28 13:54 ` sashiko-bot
-1 siblings, 0 replies; 116+ messages in thread
From: sashiko-bot @ 2026-08-28 13:54 UTC (permalink / raw)
To: Michal Wilczynski
Cc: dri-devel, olteanv, robh, conor+dt, linux-phy, vkoul,
neil.armstrong, devicetree, mfd, lee, linux-clk
Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:
- [Low] The compatible string 'starfive,jh7110-hdmi-subsystem' embeds software architecture details into the hardware description.
--
commit f244c8f1868df1c7d5507202956114ed3dbd675e
Author: Michal Wilczynski <m.wilczynski@samsung.com>
dt-bindings: mfd: Add starfive,jh7110-hdmi-subsystem
This commit adds a device tree binding for the StarFive JH7110 HDMI subsystem.
The binding describes a parent device acting as an MFD to hold shared
registers for PHY and controller children, addressing a circular clock
dependency.
> diff --git a/Documentation/devicetree/bindings/mfd/starfive,jh7110-hdmi-subsystem.yaml b/Documentation/devicetree/bindings/mfd/starfive,jh7110-hdmi-subsystem.yaml
> new file mode 100644
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/mfd/starfive,jh7110-hdmi-subsystem.yaml
[ ... ]
> +description:
> + The StarFive JH7110 HDMI block is a monolithic IP containing both
> + the digital controller logic and the analog PHY logic in a single
> + register space.
> +
> +properties:
> + compatible:
> + const: starfive,jh7110-hdmi-subsystem
[Severity: Low]
Is the use of "subsystem" in this compatible string intentional?
Device tree bindings typically describe the physical hardware block rather
than the software architecture. Since the commit message and description
indicate the HDMI IP is a monolithic physical block, encoding a Linux-specific
driver concept like a subsystem or an MFD parent into the compatible string
appears to embed software details into the hardware description.
Could this compatible string be updated to reflect the actual hardware block's
designation without the "subsystem" suffix?
--
Sashiko AI review · https://sashiko.dev/#/patchset/20260828-jh7110-clean-send-v2-0-331680c8b9d1@samsung.com?part=3
^ permalink raw reply [flat|nested] 116+ messages in thread
* Re: [PATCH v2 03/15] dt-bindings: mfd: Add starfive,jh7110-hdmi-subsystem
@ 2026-08-28 13:54 ` sashiko-bot
0 siblings, 0 replies; 116+ messages in thread
From: sashiko-bot @ 2026-08-28 13:54 UTC (permalink / raw)
To: Michal Wilczynski
Cc: dri-devel, olteanv, robh, conor+dt, linux-phy, vkoul,
neil.armstrong, devicetree, mfd, lee, linux-clk
Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:
- [Low] The compatible string 'starfive,jh7110-hdmi-subsystem' embeds software architecture details into the hardware description.
--
commit f244c8f1868df1c7d5507202956114ed3dbd675e
Author: Michal Wilczynski <m.wilczynski@samsung.com>
dt-bindings: mfd: Add starfive,jh7110-hdmi-subsystem
This commit adds a device tree binding for the StarFive JH7110 HDMI subsystem.
The binding describes a parent device acting as an MFD to hold shared
registers for PHY and controller children, addressing a circular clock
dependency.
> diff --git a/Documentation/devicetree/bindings/mfd/starfive,jh7110-hdmi-subsystem.yaml b/Documentation/devicetree/bindings/mfd/starfive,jh7110-hdmi-subsystem.yaml
> new file mode 100644
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/mfd/starfive,jh7110-hdmi-subsystem.yaml
[ ... ]
> +description:
> + The StarFive JH7110 HDMI block is a monolithic IP containing both
> + the digital controller logic and the analog PHY logic in a single
> + register space.
> +
> +properties:
> + compatible:
> + const: starfive,jh7110-hdmi-subsystem
[Severity: Low]
Is the use of "subsystem" in this compatible string intentional?
Device tree bindings typically describe the physical hardware block rather
than the software architecture. Since the commit message and description
indicate the HDMI IP is a monolithic physical block, encoding a Linux-specific
driver concept like a subsystem or an MFD parent into the compatible string
appears to embed software details into the hardware description.
Could this compatible string be updated to reflect the actual hardware block's
designation without the "subsystem" suffix?
--
Sashiko AI review · https://sashiko.dev/#/patchset/20260828-jh7110-clean-send-v2-0-331680c8b9d1@samsung.com?part=3
--
linux-phy mailing list
linux-phy@lists.infradead.org
https://lists.infradead.org/mailman/listinfo/linux-phy
^ permalink raw reply [flat|nested] 116+ messages in thread
* Re: [PATCH v2 01/15] dt-bindings: phy: Add starfive,jh7110-inno-hdmi-phy
2026-08-28 13:47 ` Michal Wilczynski
@ 2026-08-28 13:54 ` sashiko-bot
-1 siblings, 0 replies; 116+ messages in thread
From: sashiko-bot @ 2026-08-28 13:54 UTC (permalink / raw)
To: Michal Wilczynski
Cc: devicetree, lee, vkoul, conor+dt, linux-clk, linux-phy, mfd,
neil.armstrong, robh, dri-devel, olteanv
> Add the dt-binding for the StarFive JH7110 Innosilicon HDMI PHY.
>
> This device is a child of the starfive,jh7110-hdmi-subsystem node. It
> functions as both a PHY provider for the controller and as a clock
> provider for the variable pixel clock (hdmi_pclk), which it generates
> from its refoclk.
>
> Signed-off-by: Michal Wilczynski <m.wilczynski@samsung.com>
Sashiko has reviewed this patch and found no issues. It looks great!
--
Sashiko AI review · https://sashiko.dev/#/patchset/20260828-jh7110-clean-send-v2-0-331680c8b9d1@samsung.com?part=1
^ permalink raw reply [flat|nested] 116+ messages in thread
* Re: [PATCH v2 01/15] dt-bindings: phy: Add starfive,jh7110-inno-hdmi-phy
@ 2026-08-28 13:54 ` sashiko-bot
0 siblings, 0 replies; 116+ messages in thread
From: sashiko-bot @ 2026-08-28 13:54 UTC (permalink / raw)
To: Michal Wilczynski
Cc: devicetree, lee, vkoul, conor+dt, linux-clk, linux-phy, mfd,
neil.armstrong, robh, dri-devel, olteanv
> Add the dt-binding for the StarFive JH7110 Innosilicon HDMI PHY.
>
> This device is a child of the starfive,jh7110-hdmi-subsystem node. It
> functions as both a PHY provider for the controller and as a clock
> provider for the variable pixel clock (hdmi_pclk), which it generates
> from its refoclk.
>
> Signed-off-by: Michal Wilczynski <m.wilczynski@samsung.com>
Sashiko has reviewed this patch and found no issues. It looks great!
--
Sashiko AI review · https://sashiko.dev/#/patchset/20260828-jh7110-clean-send-v2-0-331680c8b9d1@samsung.com?part=1
--
linux-phy mailing list
linux-phy@lists.infradead.org
https://lists.infradead.org/mailman/listinfo/linux-phy
^ permalink raw reply [flat|nested] 116+ messages in thread
* Re: [PATCH v2 02/15] dt-bindings: display: bridge: Add starfive,jh7110-inno-hdmi-controller
2026-08-28 13:47 ` Michal Wilczynski
@ 2026-08-28 13:54 ` sashiko-bot
-1 siblings, 0 replies; 116+ messages in thread
From: sashiko-bot @ 2026-08-28 13:54 UTC (permalink / raw)
To: Michal Wilczynski
Cc: olteanv, neil.armstrong, linux-phy, dri-devel, lee, conor+dt,
robh, linux-clk, vkoul, devicetree, mfd
Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:
- [Medium] The `ports` property describes one input and one output port but fails to enforce this constraint in the YAML structure.
--
commit 419cb2b368875cbe282124810522d401e4b0c458
Author: Michal Wilczynski <m.wilczynski@samsung.com>
dt-bindings: display: bridge: Add starfive,jh7110-inno-hdmi-controller
This commit adds the device tree binding schema for the StarFive JH7110
Innosilicon HDMI controller.
> diff --git a/Documentation/devicetree/bindings/display/bridge/starfive,jh7110-inno-hdmi-controller.yaml b/Documentation/devicetree/bindings/display/bridge/starfive,jh7110-inno-hdmi-controller.yaml
> new file mode 100644
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/display/bridge/starfive,jh7110-inno-hdmi-controller.yaml
[ ... ]
> + phy-names:
> + const: hdmi-phy
> +
> + ports:
> + $ref: /schemas/graph.yaml#/properties/ports
> + description:
> + A graph node with one input port and one output port.
[Severity: Medium]
Does this missing structure allow invalid device trees to pass validation?
The description states there is one input port and one output port, but the
YAML lacks the internal property constraints (such as port@0 and port@1) and
the associated required list.
Without these explicit definitions, device trees missing the expected nodes
or adding extraneous invalid ports will silently pass dt_binding_check despite
violating the hardware topology constraints described.
Could explicit definitions and constraints for port@0 and port@1 be added
here to properly enforce the port counts?
[ ... ]
--
Sashiko AI review · https://sashiko.dev/#/patchset/20260828-jh7110-clean-send-v2-0-331680c8b9d1@samsung.com?part=2
^ permalink raw reply [flat|nested] 116+ messages in thread
* Re: [PATCH v2 02/15] dt-bindings: display: bridge: Add starfive,jh7110-inno-hdmi-controller
@ 2026-08-28 13:54 ` sashiko-bot
0 siblings, 0 replies; 116+ messages in thread
From: sashiko-bot @ 2026-08-28 13:54 UTC (permalink / raw)
To: Michal Wilczynski
Cc: olteanv, neil.armstrong, linux-phy, dri-devel, lee, conor+dt,
robh, linux-clk, vkoul, devicetree, mfd
Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:
- [Medium] The `ports` property describes one input and one output port but fails to enforce this constraint in the YAML structure.
--
commit 419cb2b368875cbe282124810522d401e4b0c458
Author: Michal Wilczynski <m.wilczynski@samsung.com>
dt-bindings: display: bridge: Add starfive,jh7110-inno-hdmi-controller
This commit adds the device tree binding schema for the StarFive JH7110
Innosilicon HDMI controller.
> diff --git a/Documentation/devicetree/bindings/display/bridge/starfive,jh7110-inno-hdmi-controller.yaml b/Documentation/devicetree/bindings/display/bridge/starfive,jh7110-inno-hdmi-controller.yaml
> new file mode 100644
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/display/bridge/starfive,jh7110-inno-hdmi-controller.yaml
[ ... ]
> + phy-names:
> + const: hdmi-phy
> +
> + ports:
> + $ref: /schemas/graph.yaml#/properties/ports
> + description:
> + A graph node with one input port and one output port.
[Severity: Medium]
Does this missing structure allow invalid device trees to pass validation?
The description states there is one input port and one output port, but the
YAML lacks the internal property constraints (such as port@0 and port@1) and
the associated required list.
Without these explicit definitions, device trees missing the expected nodes
or adding extraneous invalid ports will silently pass dt_binding_check despite
violating the hardware topology constraints described.
Could explicit definitions and constraints for port@0 and port@1 be added
here to properly enforce the port counts?
[ ... ]
--
Sashiko AI review · https://sashiko.dev/#/patchset/20260828-jh7110-clean-send-v2-0-331680c8b9d1@samsung.com?part=2
--
linux-phy mailing list
linux-phy@lists.infradead.org
https://lists.infradead.org/mailman/listinfo/linux-phy
^ permalink raw reply [flat|nested] 116+ messages in thread
* Re: [PATCH v2 05/15] drm/bridge: inno-hdmi: Allow the register map to come from a parent
2026-08-28 13:47 ` Michal Wilczynski
@ 2026-08-28 13:54 ` sashiko-bot
-1 siblings, 0 replies; 116+ messages in thread
From: sashiko-bot @ 2026-08-28 13:54 UTC (permalink / raw)
To: Michal Wilczynski
Cc: mfd, conor+dt, vkoul, devicetree, linux-clk, lee, dri-devel,
neil.armstrong, linux-phy, olteanv, robh
Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:
- [Medium] Uninitialized variable 'val' is returned if regmap_read() fails
--
commit a6bf796635499ff8cec94a1fb87f0e5e4fc66897
Author: Michal Wilczynski <m.wilczynski@samsung.com>
drm/bridge: inno-hdmi: Allow the register map to come from a parent
This commit updates the inno-hdmi driver to use a regmap supplied by the
parent device if available, falling back to mapping its own resource
otherwise. This allows sharing the register space on SoCs where the HDMI
controller does not exclusively own the register window.
> diff --git a/drivers/gpu/drm/bridge/inno-hdmi.c b/drivers/gpu/drm/bridge/inno-hdmi.c
> index 12fd208d5e852..ebc5093f13ac4 100644
> --- a/drivers/gpu/drm/bridge/inno-hdmi.c
> +++ b/drivers/gpu/drm/bridge/inno-hdmi.c
[ ... ]
> @@ -470,11 +471,23 @@ static int inno_hdmi_find_phy_config(struct inno_hdmi *hdmi,
>
> static inline u8 hdmi_readb(struct inno_hdmi *hdmi, u16 offset)
> {
> + u32 val;
> +
> + if (hdmi->regmap) {
> + regmap_read(hdmi->regmap, offset * 4, &val);
> + return val;
[Severity: Medium]
Does this return uninitialized stack memory if regmap_read() fails?
If regmap_read() fails (e.g., due to an out-of-bounds offset, disabled
clock, or other regmap configuration issues), it returns a negative error
code and does not populate val. The function appears to ignore the return
value and blindly returns the uninitialized stack variable. Callers that
use this value for hardware logic might behave erratically if random stack
data is interpreted as register contents.
> + }
> +
> return readl_relaxed(hdmi->regs + (offset) * 0x04);
> }
--
Sashiko AI review · https://sashiko.dev/#/patchset/20260828-jh7110-clean-send-v2-0-331680c8b9d1@samsung.com?part=5
^ permalink raw reply [flat|nested] 116+ messages in thread
* Re: [PATCH v2 05/15] drm/bridge: inno-hdmi: Allow the register map to come from a parent
@ 2026-08-28 13:54 ` sashiko-bot
0 siblings, 0 replies; 116+ messages in thread
From: sashiko-bot @ 2026-08-28 13:54 UTC (permalink / raw)
To: Michal Wilczynski
Cc: mfd, conor+dt, vkoul, devicetree, linux-clk, lee, dri-devel,
neil.armstrong, linux-phy, olteanv, robh
Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:
- [Medium] Uninitialized variable 'val' is returned if regmap_read() fails
--
commit a6bf796635499ff8cec94a1fb87f0e5e4fc66897
Author: Michal Wilczynski <m.wilczynski@samsung.com>
drm/bridge: inno-hdmi: Allow the register map to come from a parent
This commit updates the inno-hdmi driver to use a regmap supplied by the
parent device if available, falling back to mapping its own resource
otherwise. This allows sharing the register space on SoCs where the HDMI
controller does not exclusively own the register window.
> diff --git a/drivers/gpu/drm/bridge/inno-hdmi.c b/drivers/gpu/drm/bridge/inno-hdmi.c
> index 12fd208d5e852..ebc5093f13ac4 100644
> --- a/drivers/gpu/drm/bridge/inno-hdmi.c
> +++ b/drivers/gpu/drm/bridge/inno-hdmi.c
[ ... ]
> @@ -470,11 +471,23 @@ static int inno_hdmi_find_phy_config(struct inno_hdmi *hdmi,
>
> static inline u8 hdmi_readb(struct inno_hdmi *hdmi, u16 offset)
> {
> + u32 val;
> +
> + if (hdmi->regmap) {
> + regmap_read(hdmi->regmap, offset * 4, &val);
> + return val;
[Severity: Medium]
Does this return uninitialized stack memory if regmap_read() fails?
If regmap_read() fails (e.g., due to an out-of-bounds offset, disabled
clock, or other regmap configuration issues), it returns a negative error
code and does not populate val. The function appears to ignore the return
value and blindly returns the uninitialized stack variable. Callers that
use this value for hardware logic might behave erratically if random stack
data is interpreted as register contents.
> + }
> +
> return readl_relaxed(hdmi->regs + (offset) * 0x04);
> }
--
Sashiko AI review · https://sashiko.dev/#/patchset/20260828-jh7110-clean-send-v2-0-331680c8b9d1@samsung.com?part=5
--
linux-phy mailing list
linux-phy@lists.infradead.org
https://lists.infradead.org/mailman/listinfo/linux-phy
^ permalink raw reply [flat|nested] 116+ messages in thread
* Re: [PATCH v2 06/15] drm/bridge: inno-hdmi: Add .disable platform operation
2026-08-28 13:47 ` Michal Wilczynski
@ 2026-08-28 13:57 ` sashiko-bot
-1 siblings, 0 replies; 116+ messages in thread
From: sashiko-bot @ 2026-08-28 13:57 UTC (permalink / raw)
To: Michal Wilczynski
Cc: linux-phy, linux-clk, conor+dt, dri-devel, neil.armstrong,
devicetree, vkoul, robh, olteanv, mfd, lee
Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:
- [High] Atomic Context Violation: Invoking sleeping functions from atomic context
--
commit 2003c6678c3684f19742ce18515a5d05db18fc6c
Author: Michal Wilczynski <m.wilczynski@samsung.com>
drm/bridge: inno-hdmi: Add .disable platform operation
This commit adds a new .disable platform operation to the inno_hdmi_plat_ops
struct. It invokes this hook at the beginning of
inno_hdmi_bridge_atomic_disable() to allow platform-specific drivers to
implement their own power down sequences.
> diff --git a/drivers/gpu/drm/bridge/inno-hdmi.c b/drivers/gpu/drm/bridge/inno-hdmi.c
> index ebc5093f13ac4..952cc55c10f7d 100644
> --- a/drivers/gpu/drm/bridge/inno-hdmi.c
> +++ b/drivers/gpu/drm/bridge/inno-hdmi.c
> @@ -884,6 +884,10 @@ static void inno_hdmi_bridge_atomic_disable(struct drm_bridge *bridge,
> struct drm_atomic_commit *state)
> {
> struct inno_hdmi *hdmi = bridge_to_inno_hdmi(bridge);
> + const struct inno_hdmi_plat_ops *plat_ops = hdmi->plat_data->ops;
> +
> + if (plat_ops && plat_ops->disable)
> + plat_ops->disable(hdmi->dev);
[Severity: High]
The commit message mentions this hook allows platform drivers to implement
power down sequences by calling clk_disable_unprepare(). Since
inno_hdmi_bridge_atomic_disable() is called from the atomic commit pipeline
(drm_atomic_helper_commit_tail()), where sleeping is strictly forbidden,
can this lead to an atomic context violation?
Because clk_disable_unprepare() acquires a mutex internally, it is a
sleeping function. Calling it from this path could cause system instability,
kernel warnings, or deadlocks during a display modeset, DPMS state change,
or system suspend.
>
> inno_hdmi_standby(hdmi);
> }
--
Sashiko AI review · https://sashiko.dev/#/patchset/20260828-jh7110-clean-send-v2-0-331680c8b9d1@samsung.com?part=6
^ permalink raw reply [flat|nested] 116+ messages in thread
* Re: [PATCH v2 06/15] drm/bridge: inno-hdmi: Add .disable platform operation
@ 2026-08-28 13:57 ` sashiko-bot
0 siblings, 0 replies; 116+ messages in thread
From: sashiko-bot @ 2026-08-28 13:57 UTC (permalink / raw)
To: Michal Wilczynski
Cc: linux-phy, linux-clk, conor+dt, dri-devel, neil.armstrong,
devicetree, vkoul, robh, olteanv, mfd, lee
Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:
- [High] Atomic Context Violation: Invoking sleeping functions from atomic context
--
commit 2003c6678c3684f19742ce18515a5d05db18fc6c
Author: Michal Wilczynski <m.wilczynski@samsung.com>
drm/bridge: inno-hdmi: Add .disable platform operation
This commit adds a new .disable platform operation to the inno_hdmi_plat_ops
struct. It invokes this hook at the beginning of
inno_hdmi_bridge_atomic_disable() to allow platform-specific drivers to
implement their own power down sequences.
> diff --git a/drivers/gpu/drm/bridge/inno-hdmi.c b/drivers/gpu/drm/bridge/inno-hdmi.c
> index ebc5093f13ac4..952cc55c10f7d 100644
> --- a/drivers/gpu/drm/bridge/inno-hdmi.c
> +++ b/drivers/gpu/drm/bridge/inno-hdmi.c
> @@ -884,6 +884,10 @@ static void inno_hdmi_bridge_atomic_disable(struct drm_bridge *bridge,
> struct drm_atomic_commit *state)
> {
> struct inno_hdmi *hdmi = bridge_to_inno_hdmi(bridge);
> + const struct inno_hdmi_plat_ops *plat_ops = hdmi->plat_data->ops;
> +
> + if (plat_ops && plat_ops->disable)
> + plat_ops->disable(hdmi->dev);
[Severity: High]
The commit message mentions this hook allows platform drivers to implement
power down sequences by calling clk_disable_unprepare(). Since
inno_hdmi_bridge_atomic_disable() is called from the atomic commit pipeline
(drm_atomic_helper_commit_tail()), where sleeping is strictly forbidden,
can this lead to an atomic context violation?
Because clk_disable_unprepare() acquires a mutex internally, it is a
sleeping function. Calling it from this path could cause system instability,
kernel warnings, or deadlocks during a display modeset, DPMS state change,
or system suspend.
>
> inno_hdmi_standby(hdmi);
> }
--
Sashiko AI review · https://sashiko.dev/#/patchset/20260828-jh7110-clean-send-v2-0-331680c8b9d1@samsung.com?part=6
--
linux-phy mailing list
linux-phy@lists.infradead.org
https://lists.infradead.org/mailman/listinfo/linux-phy
^ permalink raw reply [flat|nested] 116+ messages in thread
* Re: [PATCH v2 10/15] drm/bridge: starfive: Add JH7110 HDMI controller driver
2026-08-28 13:47 ` Michal Wilczynski
@ 2026-08-28 13:59 ` sashiko-bot
-1 siblings, 0 replies; 116+ messages in thread
From: sashiko-bot @ 2026-08-28 13:59 UTC (permalink / raw)
To: Michal Wilczynski
Cc: olteanv, conor+dt, linux-phy, mfd, devicetree, lee, dri-devel,
neil.armstrong, robh, linux-clk, vkoul
Thank you for your contribution! Sashiko AI review found 3 potential issue(s) to consider:
- [High] Naming collision for 'pclk' causes the generic driver to permanently enable the pixel clock and breaks I2C/EDID reads.
- [High] Manual teardown of clocks and reset in remove() and probe error paths violates devres ordering, risking a kernel panic.
- [Medium] PHY power state and pixel clock reference counts are leaked if the driver is unbound while active.
--
commit c6a610527cc7d181c41335780cfb8a12665b7239
Author: Michal Wilczynski <m.wilczynski@samsung.com>
drm/bridge: starfive: Add JH7110 HDMI controller driver
This commit adds the HDMI controller bridge driver for the StarFive JH7110,
acting as a glue layer between the JH7110 HDMI subsystem and the generic
Innosilicon HDMI bridge driver. It handles shared regmaps, manages clock
hierarchies from voutcrg, and configures the PHY's pixel clock rate dynamically.
> diff --git a/drivers/gpu/drm/bridge/jh7110-inno-hdmi.c b/drivers/gpu/drm/bridge/jh7110-inno-hdmi.c
> new file mode 100644
> index 0000000000000..be865aa39e33f
> --- /dev/null
> +++ b/drivers/gpu/drm/bridge/jh7110-inno-hdmi.c
[ ... ]
> +static int starfive_inno_hdmi_controller_probe(struct platform_device *pdev)
> +{
> + struct device *dev = &pdev->dev;
> + struct device *parent = dev->parent;
> + struct stf_inno_hdmi_controller *ctrl;
> + const struct inno_hdmi_plat_data *plat_data;
> + struct regmap *regmap;
> + struct inno_hdmi *inno;
> + int ret;
> +
> + ctrl = devm_kzalloc(dev, sizeof(*ctrl), GFP_KERNEL);
> + if (!ctrl)
> + return -ENOMEM;
> +
> + ctrl->dev = dev;
> + platform_set_drvdata(pdev, ctrl);
> +
> + /* Get the shared regmap from the parent */
> + regmap = dev_get_regmap(parent, NULL);
> + if (!regmap) {
> + dev_err(dev, "Failed to get parent regmap\n");
> + return -ENODEV;
> + }
> +
> + ctrl->phy = devm_phy_get(dev, "hdmi-phy");
> + if (IS_ERR(ctrl->phy))
> + return dev_err_probe(dev, PTR_ERR(ctrl->phy), "Failed to get PHY\n");
> +
> + ctrl->tx_rst = devm_reset_control_get_exclusive(dev, "hdmi_tx");
> + if (IS_ERR(ctrl->tx_rst))
> + return dev_err_probe(dev, PTR_ERR(ctrl->tx_rst), "failed to get tx reset\n");
> +
> + /* Populate the clock names this controller *consumes* */
> + ctrl->clks[CLK_SYS].id = "sys";
> + ctrl->clks[CLK_M].id = "mclk";
> + ctrl->clks[CLK_B].id = "bclk";
> + ctrl->clks[CLK_PCLK].id = "pclk"; /* Pixel clock *from* PHY */
[Severity: High]
Does this naming collision for 'pclk' cause the generic driver to permanently
enable the pixel clock and break I2C/EDID reads?
The wrapper driver maps the 'pclk' string ID to the dynamically-managed pixel
clock from the PHY. However, the generic driver inno_hdmi_probe() in
drivers/gpu/drm/bridge/inno-hdmi.c expects 'pclk' to be the APB/peripheral
clock and grabs it unconditionally:
inno-hdmi.c:inno_hdmi_probe() {
...
hdmi->pclk = devm_clk_get_enabled(hdmi->dev, "pclk");
...
}
Because both query the same device tree node, the generic driver grabs the
pixel clock and permanently enables it at probe time.
Furthermore, inno_hdmi_init_hw() uses clk_get_rate(hdmi->pclk) at probe time
to calculate the DDC I2C clock divider. Since the pixel clock rate isn't set
until the .enable callback is invoked during modesetting, it will return 0 or
a default rate. This results in a 0 Hz DDC bus frequency, causing I2C timeouts
and breaking EDID reading.
> +
> + ret = devm_clk_bulk_get(dev, CLK_CTRL_NUM, ctrl->clks);
> + if (ret)
> + return dev_err_probe(dev, ret, "Unable to get controller clocks\n");
> +
> + /* pclk is enabled on demand during modeset */
> + ret = clk_bulk_prepare_enable(CLK_CTRL_NUM - 1, ctrl->clks);
> + if (ret)
> + return ret;
> +
> + ret = reset_control_deassert(ctrl->tx_rst);
> + if (ret) {
> + clk_bulk_disable_unprepare(CLK_CTRL_NUM - 1, ctrl->clks);
> + return ret;
> + }
> +
> + plat_data = of_device_get_match_data(dev);
> +
> + /* Hand off to the generic library to create the bridge. */
> + inno = inno_hdmi_probe(pdev, plat_data);
> + if (IS_ERR(inno)) {
> + reset_control_assert(ctrl->tx_rst);
> + clk_bulk_disable_unprepare(CLK_CTRL_NUM - 1, ctrl->clks);
[Severity: High]
Can this manual teardown of clocks and reset violate devres ordering and risk
a kernel panic?
The driver manually enables bus clocks and deasserts reset in probe before
calling inno_hdmi_probe(). The generic inno_hdmi_probe() registers a shared
interrupt handler (inno_hdmi_hardirq) via devm_request_threaded_irq().
In the probe error path here, and in starfive_inno_hdmi_controller_remove()
below, the driver manually disables the clocks and asserts the reset. Because
the IRQ is managed by devres, it is not freed until after the probe error
path finishes or the remove function returns.
If a shared interrupt fires in the window between the manual clock disable
and devres tearing down the IRQ, inno_hdmi_hardirq() will attempt to read
the HDMI_STATUS register. Accessing registers with the APB clock disabled
causes a bus hang.
The driver should use devm_add_action_or_reset() to manage the clocks and
reset safely.
> + return PTR_ERR(inno);
> + }
> +
> + return 0;
> +}
> +
> +static void starfive_inno_hdmi_controller_remove(struct platform_device *pdev)
> +{
> + struct stf_inno_hdmi_controller *ctrl = platform_get_drvdata(pdev);
> +
> + reset_control_assert(ctrl->tx_rst);
> + clk_bulk_disable_unprepare(CLK_CTRL_NUM - 1, ctrl->clks);
> +}
[Severity: Medium]
Will this remove function leak the PHY power state and pixel clock reference
counts if the driver is unbound while active?
During modesetting, inno_hdmi_starfive_enable() dynamically prepares and
enables the pclk and calls phy_power_on(), recording this in ctrl->enabled.
If the driver is unbound while the display pipeline is active, this remove
function executes but does not check ctrl->enabled.
It omits the required phy_power_off() and clk_disable_unprepare() calls.
While devres unwinds and drops the clock and PHY pointers, it does not
reverse the dynamic power state or decrement the prepare/enable counts,
leaving the hardware permanently on.
--
Sashiko AI review · https://sashiko.dev/#/patchset/20260828-jh7110-clean-send-v2-0-331680c8b9d1@samsung.com?part=10
^ permalink raw reply [flat|nested] 116+ messages in thread
* Re: [PATCH v2 10/15] drm/bridge: starfive: Add JH7110 HDMI controller driver
@ 2026-08-28 13:59 ` sashiko-bot
0 siblings, 0 replies; 116+ messages in thread
From: sashiko-bot @ 2026-08-28 13:59 UTC (permalink / raw)
To: Michal Wilczynski
Cc: olteanv, conor+dt, linux-phy, mfd, devicetree, lee, dri-devel,
neil.armstrong, robh, linux-clk, vkoul
Thank you for your contribution! Sashiko AI review found 3 potential issue(s) to consider:
- [High] Naming collision for 'pclk' causes the generic driver to permanently enable the pixel clock and breaks I2C/EDID reads.
- [High] Manual teardown of clocks and reset in remove() and probe error paths violates devres ordering, risking a kernel panic.
- [Medium] PHY power state and pixel clock reference counts are leaked if the driver is unbound while active.
--
commit c6a610527cc7d181c41335780cfb8a12665b7239
Author: Michal Wilczynski <m.wilczynski@samsung.com>
drm/bridge: starfive: Add JH7110 HDMI controller driver
This commit adds the HDMI controller bridge driver for the StarFive JH7110,
acting as a glue layer between the JH7110 HDMI subsystem and the generic
Innosilicon HDMI bridge driver. It handles shared regmaps, manages clock
hierarchies from voutcrg, and configures the PHY's pixel clock rate dynamically.
> diff --git a/drivers/gpu/drm/bridge/jh7110-inno-hdmi.c b/drivers/gpu/drm/bridge/jh7110-inno-hdmi.c
> new file mode 100644
> index 0000000000000..be865aa39e33f
> --- /dev/null
> +++ b/drivers/gpu/drm/bridge/jh7110-inno-hdmi.c
[ ... ]
> +static int starfive_inno_hdmi_controller_probe(struct platform_device *pdev)
> +{
> + struct device *dev = &pdev->dev;
> + struct device *parent = dev->parent;
> + struct stf_inno_hdmi_controller *ctrl;
> + const struct inno_hdmi_plat_data *plat_data;
> + struct regmap *regmap;
> + struct inno_hdmi *inno;
> + int ret;
> +
> + ctrl = devm_kzalloc(dev, sizeof(*ctrl), GFP_KERNEL);
> + if (!ctrl)
> + return -ENOMEM;
> +
> + ctrl->dev = dev;
> + platform_set_drvdata(pdev, ctrl);
> +
> + /* Get the shared regmap from the parent */
> + regmap = dev_get_regmap(parent, NULL);
> + if (!regmap) {
> + dev_err(dev, "Failed to get parent regmap\n");
> + return -ENODEV;
> + }
> +
> + ctrl->phy = devm_phy_get(dev, "hdmi-phy");
> + if (IS_ERR(ctrl->phy))
> + return dev_err_probe(dev, PTR_ERR(ctrl->phy), "Failed to get PHY\n");
> +
> + ctrl->tx_rst = devm_reset_control_get_exclusive(dev, "hdmi_tx");
> + if (IS_ERR(ctrl->tx_rst))
> + return dev_err_probe(dev, PTR_ERR(ctrl->tx_rst), "failed to get tx reset\n");
> +
> + /* Populate the clock names this controller *consumes* */
> + ctrl->clks[CLK_SYS].id = "sys";
> + ctrl->clks[CLK_M].id = "mclk";
> + ctrl->clks[CLK_B].id = "bclk";
> + ctrl->clks[CLK_PCLK].id = "pclk"; /* Pixel clock *from* PHY */
[Severity: High]
Does this naming collision for 'pclk' cause the generic driver to permanently
enable the pixel clock and break I2C/EDID reads?
The wrapper driver maps the 'pclk' string ID to the dynamically-managed pixel
clock from the PHY. However, the generic driver inno_hdmi_probe() in
drivers/gpu/drm/bridge/inno-hdmi.c expects 'pclk' to be the APB/peripheral
clock and grabs it unconditionally:
inno-hdmi.c:inno_hdmi_probe() {
...
hdmi->pclk = devm_clk_get_enabled(hdmi->dev, "pclk");
...
}
Because both query the same device tree node, the generic driver grabs the
pixel clock and permanently enables it at probe time.
Furthermore, inno_hdmi_init_hw() uses clk_get_rate(hdmi->pclk) at probe time
to calculate the DDC I2C clock divider. Since the pixel clock rate isn't set
until the .enable callback is invoked during modesetting, it will return 0 or
a default rate. This results in a 0 Hz DDC bus frequency, causing I2C timeouts
and breaking EDID reading.
> +
> + ret = devm_clk_bulk_get(dev, CLK_CTRL_NUM, ctrl->clks);
> + if (ret)
> + return dev_err_probe(dev, ret, "Unable to get controller clocks\n");
> +
> + /* pclk is enabled on demand during modeset */
> + ret = clk_bulk_prepare_enable(CLK_CTRL_NUM - 1, ctrl->clks);
> + if (ret)
> + return ret;
> +
> + ret = reset_control_deassert(ctrl->tx_rst);
> + if (ret) {
> + clk_bulk_disable_unprepare(CLK_CTRL_NUM - 1, ctrl->clks);
> + return ret;
> + }
> +
> + plat_data = of_device_get_match_data(dev);
> +
> + /* Hand off to the generic library to create the bridge. */
> + inno = inno_hdmi_probe(pdev, plat_data);
> + if (IS_ERR(inno)) {
> + reset_control_assert(ctrl->tx_rst);
> + clk_bulk_disable_unprepare(CLK_CTRL_NUM - 1, ctrl->clks);
[Severity: High]
Can this manual teardown of clocks and reset violate devres ordering and risk
a kernel panic?
The driver manually enables bus clocks and deasserts reset in probe before
calling inno_hdmi_probe(). The generic inno_hdmi_probe() registers a shared
interrupt handler (inno_hdmi_hardirq) via devm_request_threaded_irq().
In the probe error path here, and in starfive_inno_hdmi_controller_remove()
below, the driver manually disables the clocks and asserts the reset. Because
the IRQ is managed by devres, it is not freed until after the probe error
path finishes or the remove function returns.
If a shared interrupt fires in the window between the manual clock disable
and devres tearing down the IRQ, inno_hdmi_hardirq() will attempt to read
the HDMI_STATUS register. Accessing registers with the APB clock disabled
causes a bus hang.
The driver should use devm_add_action_or_reset() to manage the clocks and
reset safely.
> + return PTR_ERR(inno);
> + }
> +
> + return 0;
> +}
> +
> +static void starfive_inno_hdmi_controller_remove(struct platform_device *pdev)
> +{
> + struct stf_inno_hdmi_controller *ctrl = platform_get_drvdata(pdev);
> +
> + reset_control_assert(ctrl->tx_rst);
> + clk_bulk_disable_unprepare(CLK_CTRL_NUM - 1, ctrl->clks);
> +}
[Severity: Medium]
Will this remove function leak the PHY power state and pixel clock reference
counts if the driver is unbound while active?
During modesetting, inno_hdmi_starfive_enable() dynamically prepares and
enables the pclk and calls phy_power_on(), recording this in ctrl->enabled.
If the driver is unbound while the display pipeline is active, this remove
function executes but does not check ctrl->enabled.
It omits the required phy_power_off() and clk_disable_unprepare() calls.
While devres unwinds and drops the clock and PHY pointers, it does not
reverse the dynamic power state or decrement the prepare/enable counts,
leaving the hardware permanently on.
--
Sashiko AI review · https://sashiko.dev/#/patchset/20260828-jh7110-clean-send-v2-0-331680c8b9d1@samsung.com?part=10
--
linux-phy mailing list
linux-phy@lists.infradead.org
https://lists.infradead.org/mailman/listinfo/linux-phy
^ permalink raw reply [flat|nested] 116+ messages in thread
* Re: [PATCH v2 08/15] soc: starfive: Add jh7110-hdmi-subsystem driver
2026-08-28 13:47 ` Michal Wilczynski
@ 2026-08-28 13:59 ` sashiko-bot
-1 siblings, 0 replies; 116+ messages in thread
From: sashiko-bot @ 2026-08-28 13:59 UTC (permalink / raw)
To: Michal Wilczynski
Cc: vkoul, dri-devel, mfd, neil.armstrong, robh, conor+dt, linux-clk,
lee, olteanv, devicetree, linux-phy
Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:
- [Low] Missing `select REGMAP_MMIO` in Kconfig, leading to potential build/link errors.
--
commit 391d2ca299019c57f8ca3f0d4ee7e80cac19c1eb
Author: Michal Wilczynski <m.wilczynski@samsung.com>
Subject: soc: starfive: Add jh7110-hdmi-subsystem driver
This commit adds a parent driver for the monolithic StarFive JH7110 HDMI IP
block. It maps the shared register space and creates separate logical child
devices for the HDMI PHY and controller to break a circular probing
dependency.
> diff --git a/drivers/soc/starfive/Kconfig b/drivers/soc/starfive/Kconfig
> new file mode 100644
> index 0000000000000..7592d87dea37a
> --- /dev/null
> +++ b/drivers/soc/starfive/Kconfig
> @@ -0,0 +1,27 @@
> +# SPDX-License-Identifier: GPL-2.0-only
> +#
> +# Starfive SoC drivers
> +#
> +
> +if ARCH_STARFIVE || COMPILE_TEST
> +menu "Starfive SoC drivers"
> +
> +config SOC_STARFIVE_JH7110_HDMI_SUBSYSTEM
> + tristate "StarFive JH7110 HDMI subsystem driver"
> + depends on OF
[Severity: Low]
Does this Kconfig entry need to select REGMAP_MMIO?
If the kernel is configured with SOC_STARFIVE_JH7110_HDMI_SUBSYSTEM=y (for
example, during a random COMPILE_TEST build) but without any other driver
that enables REGMAP_MMIO, the build will likely fail with a linker error.
[ ... ]
> diff --git a/drivers/soc/starfive/jh7110-hdmi-subsystem.c b/drivers/soc/starfive/jh7110-hdmi-subsystem.c
> new file mode 100644
> index 0000000000000..d893c1c29f98b
> --- /dev/null
> +++ b/drivers/soc/starfive/jh7110-hdmi-subsystem.c
[ ... ]
> + regs = devm_platform_ioremap_resource(pdev, 0);
> + if (IS_ERR(regs))
> + return PTR_ERR(regs);
> +
> + regmap = devm_regmap_init_mmio(dev, regs,
> + &starfive_hdmi_regmap_config);
[Severity: Low]
Could the missing REGMAP_MMIO Kconfig selection cause an undefined
reference to __devm_regmap_init_mmio_clk() here during link time?
--
Sashiko AI review · https://sashiko.dev/#/patchset/20260828-jh7110-clean-send-v2-0-331680c8b9d1@samsung.com?part=8
^ permalink raw reply [flat|nested] 116+ messages in thread
* Re: [PATCH v2 08/15] soc: starfive: Add jh7110-hdmi-subsystem driver
@ 2026-08-28 13:59 ` sashiko-bot
0 siblings, 0 replies; 116+ messages in thread
From: sashiko-bot @ 2026-08-28 13:59 UTC (permalink / raw)
To: Michal Wilczynski
Cc: vkoul, dri-devel, mfd, neil.armstrong, robh, conor+dt, linux-clk,
lee, olteanv, devicetree, linux-phy
Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:
- [Low] Missing `select REGMAP_MMIO` in Kconfig, leading to potential build/link errors.
--
commit 391d2ca299019c57f8ca3f0d4ee7e80cac19c1eb
Author: Michal Wilczynski <m.wilczynski@samsung.com>
Subject: soc: starfive: Add jh7110-hdmi-subsystem driver
This commit adds a parent driver for the monolithic StarFive JH7110 HDMI IP
block. It maps the shared register space and creates separate logical child
devices for the HDMI PHY and controller to break a circular probing
dependency.
> diff --git a/drivers/soc/starfive/Kconfig b/drivers/soc/starfive/Kconfig
> new file mode 100644
> index 0000000000000..7592d87dea37a
> --- /dev/null
> +++ b/drivers/soc/starfive/Kconfig
> @@ -0,0 +1,27 @@
> +# SPDX-License-Identifier: GPL-2.0-only
> +#
> +# Starfive SoC drivers
> +#
> +
> +if ARCH_STARFIVE || COMPILE_TEST
> +menu "Starfive SoC drivers"
> +
> +config SOC_STARFIVE_JH7110_HDMI_SUBSYSTEM
> + tristate "StarFive JH7110 HDMI subsystem driver"
> + depends on OF
[Severity: Low]
Does this Kconfig entry need to select REGMAP_MMIO?
If the kernel is configured with SOC_STARFIVE_JH7110_HDMI_SUBSYSTEM=y (for
example, during a random COMPILE_TEST build) but without any other driver
that enables REGMAP_MMIO, the build will likely fail with a linker error.
[ ... ]
> diff --git a/drivers/soc/starfive/jh7110-hdmi-subsystem.c b/drivers/soc/starfive/jh7110-hdmi-subsystem.c
> new file mode 100644
> index 0000000000000..d893c1c29f98b
> --- /dev/null
> +++ b/drivers/soc/starfive/jh7110-hdmi-subsystem.c
[ ... ]
> + regs = devm_platform_ioremap_resource(pdev, 0);
> + if (IS_ERR(regs))
> + return PTR_ERR(regs);
> +
> + regmap = devm_regmap_init_mmio(dev, regs,
> + &starfive_hdmi_regmap_config);
[Severity: Low]
Could the missing REGMAP_MMIO Kconfig selection cause an undefined
reference to __devm_regmap_init_mmio_clk() here during link time?
--
Sashiko AI review · https://sashiko.dev/#/patchset/20260828-jh7110-clean-send-v2-0-331680c8b9d1@samsung.com?part=8
--
linux-phy mailing list
linux-phy@lists.infradead.org
https://lists.infradead.org/mailman/listinfo/linux-phy
^ permalink raw reply [flat|nested] 116+ messages in thread
* Re: [PATCH v2 11/15] phy: Add common Innosilicon HDMI PHY helpers
2026-08-28 13:47 ` Michal Wilczynski
@ 2026-08-28 14:00 ` sashiko-bot
-1 siblings, 0 replies; 116+ messages in thread
From: sashiko-bot @ 2026-08-28 14:00 UTC (permalink / raw)
To: Michal Wilczynski
Cc: mfd, lee, vkoul, neil.armstrong, devicetree, conor+dt, olteanv,
robh, dri-devel, linux-clk, linux-phy
Thank you for your contribution! Sashiko AI review found 2 potential issue(s) to consider:
Pre-existing issues:
- [High] Possible use of uninitialized stack memory in `inno_read()` if `regmap_read()` fails.
- [High] Kernel panic from division by zero in clock rate recalculation if PHY registers are uninitialized.
--
commit 5b3daa1c79370030c365a1cbd710f38d30ab2630
Author: Michal Wilczynski <m.wilczynski@samsung.com>
phy: Add common Innosilicon HDMI PHY helpers
The Innosilicon HDMI PHY IP is used by several SoCs. They differ in
where the PHY register block sits in the register space and in which
pixel clocks they support, but the pre-PLL programming sequence and the
layout of its registers are the same.
Add a small library holding that shared part: the pre-PLL configuration
table format, a lookup, clk_ops determine_rate and recalc_rate helpers,
and the pre-PLL register programming. Callers pass a regmap, a register
offset for the PHY block, and their own pixel clock table.
> diff --git a/drivers/phy/phy-inno-hdmi.c b/drivers/phy/phy-inno-hdmi.c
> new file mode 100644
> index 0000000000000..deb2b73a86f5d
> --- /dev/null
> +++ b/drivers/phy/phy-inno-hdmi.c
[ ... ]
> +static u8 inno_read(const struct inno_hdmi_phy_pre_pll *pll, unsigned int reg)
> +{
> + unsigned int val;
> +
> + regmap_read(pll->regmap, inno_reg(pll, reg), &val);
> +
> + return val;
> +}
[Severity: High]
This isn't a bug introduced by this patch, as it was inherited from
drivers/phy/rockchip/phy-rockchip-inno-hdmi.c, but is it possible for
regmap_read() to fail here?
If regmap_read() returns an error code, it leaves the stack variable val
uninitialized, which is then returned to the caller.
Could we check the return value of regmap_read() to avoid leaking
uninitialized memory?
[ ... ]
> +unsigned long
> +inno_hdmi_phy_pre_pll_recalc_rate(const struct inno_hdmi_phy_pre_pll *pll,
> + unsigned long parent_rate)
> +{
> + u8 nd, no_a, no_b, no_d;
> + unsigned long frac;
> + u64 vco;
> + u16 nf;
> +
> + nd = inno_read(pll, INNO_PRE_PLL_DIV_1) & INNO_PRE_PLL_PRE_DIV_MASK;
[ ... ]
> + if (inno_read(pll, INNO_PRE_PLL_CONTROL) & INNO_PCLK_VCO_DIV_5_MASK) {
> + do_div(vco, nd * 5);
[Severity: High]
This is also a pre-existing issue from the original driver, but if the PHY
registers are uninitialized (containing default 0s) or if inno_read() fails
and returns an uninitialized 0, the nd variable will be 0.
Doesn't passing a 0 divisor to do_div() cause a divide-by-zero exception
leading to a kernel panic?
> + } else {
> + no_a = inno_read(pll, INNO_PCLK_DIV_AB) & INNO_PCLK_DIV_A_MASK;
> + no_b = FIELD_GET(INNO_PCLK_DIV_B_MASK,
> + inno_read(pll, INNO_PCLK_DIV_AB)) + 2;
> + no_d = inno_read(pll, INNO_PCLK_DIV_CD) & INNO_PCLK_DIV_D_MASK;
> +
> + do_div(vco, nd * (no_a == 1 ? no_b : no_a) * no_d * 2);
[Severity: High]
Similarly, if nd, no_a, or no_d evaluate to 0 due to register read failures
or uninitialized hardware, can this do_div() call also trigger a division by
zero panic during boot when the common clock framework calls recalc_rate()?
> + }
> +
> + return DIV_ROUND_CLOSEST((unsigned long)vco, 1000) * 1000;
> +}
--
Sashiko AI review · https://sashiko.dev/#/patchset/20260828-jh7110-clean-send-v2-0-331680c8b9d1@samsung.com?part=11
--
linux-phy mailing list
linux-phy@lists.infradead.org
https://lists.infradead.org/mailman/listinfo/linux-phy
^ permalink raw reply [flat|nested] 116+ messages in thread
* Re: [PATCH v2 11/15] phy: Add common Innosilicon HDMI PHY helpers
@ 2026-08-28 14:00 ` sashiko-bot
0 siblings, 0 replies; 116+ messages in thread
From: sashiko-bot @ 2026-08-28 14:00 UTC (permalink / raw)
To: Michal Wilczynski
Cc: mfd, lee, vkoul, neil.armstrong, devicetree, conor+dt, olteanv,
robh, dri-devel, linux-clk, linux-phy
Thank you for your contribution! Sashiko AI review found 2 potential issue(s) to consider:
Pre-existing issues:
- [High] Possible use of uninitialized stack memory in `inno_read()` if `regmap_read()` fails.
- [High] Kernel panic from division by zero in clock rate recalculation if PHY registers are uninitialized.
--
commit 5b3daa1c79370030c365a1cbd710f38d30ab2630
Author: Michal Wilczynski <m.wilczynski@samsung.com>
phy: Add common Innosilicon HDMI PHY helpers
The Innosilicon HDMI PHY IP is used by several SoCs. They differ in
where the PHY register block sits in the register space and in which
pixel clocks they support, but the pre-PLL programming sequence and the
layout of its registers are the same.
Add a small library holding that shared part: the pre-PLL configuration
table format, a lookup, clk_ops determine_rate and recalc_rate helpers,
and the pre-PLL register programming. Callers pass a regmap, a register
offset for the PHY block, and their own pixel clock table.
> diff --git a/drivers/phy/phy-inno-hdmi.c b/drivers/phy/phy-inno-hdmi.c
> new file mode 100644
> index 0000000000000..deb2b73a86f5d
> --- /dev/null
> +++ b/drivers/phy/phy-inno-hdmi.c
[ ... ]
> +static u8 inno_read(const struct inno_hdmi_phy_pre_pll *pll, unsigned int reg)
> +{
> + unsigned int val;
> +
> + regmap_read(pll->regmap, inno_reg(pll, reg), &val);
> +
> + return val;
> +}
[Severity: High]
This isn't a bug introduced by this patch, as it was inherited from
drivers/phy/rockchip/phy-rockchip-inno-hdmi.c, but is it possible for
regmap_read() to fail here?
If regmap_read() returns an error code, it leaves the stack variable val
uninitialized, which is then returned to the caller.
Could we check the return value of regmap_read() to avoid leaking
uninitialized memory?
[ ... ]
> +unsigned long
> +inno_hdmi_phy_pre_pll_recalc_rate(const struct inno_hdmi_phy_pre_pll *pll,
> + unsigned long parent_rate)
> +{
> + u8 nd, no_a, no_b, no_d;
> + unsigned long frac;
> + u64 vco;
> + u16 nf;
> +
> + nd = inno_read(pll, INNO_PRE_PLL_DIV_1) & INNO_PRE_PLL_PRE_DIV_MASK;
[ ... ]
> + if (inno_read(pll, INNO_PRE_PLL_CONTROL) & INNO_PCLK_VCO_DIV_5_MASK) {
> + do_div(vco, nd * 5);
[Severity: High]
This is also a pre-existing issue from the original driver, but if the PHY
registers are uninitialized (containing default 0s) or if inno_read() fails
and returns an uninitialized 0, the nd variable will be 0.
Doesn't passing a 0 divisor to do_div() cause a divide-by-zero exception
leading to a kernel panic?
> + } else {
> + no_a = inno_read(pll, INNO_PCLK_DIV_AB) & INNO_PCLK_DIV_A_MASK;
> + no_b = FIELD_GET(INNO_PCLK_DIV_B_MASK,
> + inno_read(pll, INNO_PCLK_DIV_AB)) + 2;
> + no_d = inno_read(pll, INNO_PCLK_DIV_CD) & INNO_PCLK_DIV_D_MASK;
> +
> + do_div(vco, nd * (no_a == 1 ? no_b : no_a) * no_d * 2);
[Severity: High]
Similarly, if nd, no_a, or no_d evaluate to 0 due to register read failures
or uninitialized hardware, can this do_div() call also trigger a division by
zero panic during boot when the common clock framework calls recalc_rate()?
> + }
> +
> + return DIV_ROUND_CLOSEST((unsigned long)vco, 1000) * 1000;
> +}
--
Sashiko AI review · https://sashiko.dev/#/patchset/20260828-jh7110-clean-send-v2-0-331680c8b9d1@samsung.com?part=11
^ permalink raw reply [flat|nested] 116+ messages in thread
* Re: [PATCH v2 04/15] drm/bridge: inno-hdmi: Split probe out of bind
2026-08-28 13:47 ` Michal Wilczynski
@ 2026-08-28 14:01 ` sashiko-bot
-1 siblings, 0 replies; 116+ messages in thread
From: sashiko-bot @ 2026-08-28 14:01 UTC (permalink / raw)
To: Michal Wilczynski
Cc: conor+dt, vkoul, olteanv, devicetree, robh, linux-phy, mfd, lee,
dri-devel, neil.armstrong, linux-clk
Thank you for your contribution! Sashiko AI review found 5 potential issue(s) to consider:
New issues:
- [High] Missing `inno_hdmi_remove` implementation leads to hardware interrupt storms and violates API contract.
Pre-existing issues:
- [Critical] HPD IRQ is requested and enabled before bridge attach, leading to NULL pointer dereference in the interrupt handler.
- [High] Resource leak of devm_-managed allocations during component bind retries.
- [High] TOCTOU race exposing the I2C adapter to userspace before internal initialization completes.
- [High] Use-after-free in the interrupt handler during device teardown due to incorrect devres registration order.
--
commit 355630a3f7bbfe2d55d6902048b35afc6cb4d58d
Author: Michal Wilczynski <m.wilczynski@samsung.com>
drm/bridge: inno-hdmi: Split probe out of bind
inno_hdmi_bind() both sets up the bridge and attaches it to a DRM
encoder. A platform whose HDMI controller is a child of a larger device
needs the first half without the second, since it registers as its own
platform driver and lets the DRM core bind the bridge later.
Move the setup into a new exported inno_hdmi_probe(), with a matching
inno_hdmi_remove(), and reduce inno_hdmi_bind() to a wrapper around it.
No functional change intended.
> Move the setup into a new exported inno_hdmi_probe(), with a matching
> inno_hdmi_remove(), and reduce inno_hdmi_bind() to a wrapper around it.
[Severity: High]
The commit message mentions adding a matching inno_hdmi_remove() function,
but it does not appear to be implemented in this patch.
Without an exported remove function to safely tear down the hardware and
unmask interrupts, could this lead to hardware interrupt storms if the
platform module is removed or the driver is unbound?
> diff --git a/drivers/gpu/drm/bridge/inno-hdmi.c b/drivers/gpu/drm/bridge/inno-hdmi.c
> index 9a62bf59a4033..12fd208d5e852 100644
> --- a/drivers/gpu/drm/bridge/inno-hdmi.c
> +++ b/drivers/gpu/drm/bridge/inno-hdmi.c
[ ... ]
> +struct inno_hdmi *inno_hdmi_probe(struct platform_device *pdev,
> + const struct inno_hdmi_plat_data *plat_data)
> {
> - struct platform_device *pdev = to_platform_device(dev);
> + struct device *dev = &pdev->dev;
[Severity: High]
This isn't a bug introduced by this patch, but there appears to be a
time-of-check to time-of-use (TOCTOU) race condition during I2C adapter
registration within this setup path.
In inno_hdmi_i2c_adapter(), devm_i2c_add_adapter() publishes the adapter
to userspace before assigning hdmi->i2c = i2c. If a userspace tool
initiates an I2C transaction concurrently during this small window,
inno_hdmi_i2c_xfer() will attempt to lock i2c->lock using the still-NULL
hdmi->i2c pointer.
Can this lead to a NULL pointer dereference?
[Severity: Critical]
This is a pre-existing issue, but requesting the IRQ before the bridge
is attached seems to cause a crash on decoupled platforms.
During the hardware setup in this path, devm_request_threaded_irq()
requests the hotplug interrupt. If a monitor is already connected, the
interrupt can fire immediately. The handler, inno_hdmi_irq(), unconditionally
calls drm_helper_hpd_irq_event(hdmi->bridge.dev). However, hdmi->bridge.dev
remains NULL until drm_bridge_attach() is called later.
Since this patch explicitly supports decoupled drivers that register
the bridge without immediately attaching it, does this guarantee a boot-time
NULL pointer dereference if a display is connected?
[Severity: High]
This is a pre-existing issue, but there appears to be a devres registration
order issue that leads to a use-after-free.
The IRQ is requested via devm_request_threaded_irq() before the I2C
adapter memory is allocated with devm_kzalloc(). During device teardown,
devres cleans up resources in reverse order, meaning the I2C memory is freed
while the IRQ remains active.
If a hardware interrupt fires during this teardown window,
inno_hdmi_hardirq() will check the dangling pointer and call
inno_hdmi_i2c_irq(), which accesses the already freed memory.
Should the IRQ be requested after all resources it depends on are allocated?
[ ... ]
> +struct inno_hdmi *inno_hdmi_bind(struct device *dev,
> + struct drm_encoder *encoder,
> + const struct inno_hdmi_plat_data *plat_data)
> +{
> + struct platform_device *pdev = to_platform_device(dev);
> + struct inno_hdmi *hdmi;
> + int ret;
> +
> + hdmi = inno_hdmi_probe(pdev, plat_data);
> + if (IS_ERR(hdmi))
> + return hdmi;
> +
> + ret = drm_bridge_attach(encoder, &hdmi->bridge, NULL,
> + DRM_BRIDGE_ATTACH_NO_CONNECTOR);
> + if (ret)
> + return ERR_PTR(ret);
[Severity: High]
This isn't a bug introduced by this patch, but if drm_bridge_attach() fails
(for example, due to probe deferral of another bridge), this returns an
error directly without explicitly destroying the devm_ resources allocated
during inno_hdmi_probe().
Since devm_ allocations are tied to the component device's lifetime rather
than the component bind cycle, won't this leak memory and accumulate
duplicate IRQ registrations on each component bind retry?
--
Sashiko AI review · https://sashiko.dev/#/patchset/20260828-jh7110-clean-send-v2-0-331680c8b9d1@samsung.com?part=4
^ permalink raw reply [flat|nested] 116+ messages in thread
* Re: [PATCH v2 04/15] drm/bridge: inno-hdmi: Split probe out of bind
@ 2026-08-28 14:01 ` sashiko-bot
0 siblings, 0 replies; 116+ messages in thread
From: sashiko-bot @ 2026-08-28 14:01 UTC (permalink / raw)
To: Michal Wilczynski
Cc: conor+dt, vkoul, olteanv, devicetree, robh, linux-phy, mfd, lee,
dri-devel, neil.armstrong, linux-clk
Thank you for your contribution! Sashiko AI review found 5 potential issue(s) to consider:
New issues:
- [High] Missing `inno_hdmi_remove` implementation leads to hardware interrupt storms and violates API contract.
Pre-existing issues:
- [Critical] HPD IRQ is requested and enabled before bridge attach, leading to NULL pointer dereference in the interrupt handler.
- [High] Resource leak of devm_-managed allocations during component bind retries.
- [High] TOCTOU race exposing the I2C adapter to userspace before internal initialization completes.
- [High] Use-after-free in the interrupt handler during device teardown due to incorrect devres registration order.
--
commit 355630a3f7bbfe2d55d6902048b35afc6cb4d58d
Author: Michal Wilczynski <m.wilczynski@samsung.com>
drm/bridge: inno-hdmi: Split probe out of bind
inno_hdmi_bind() both sets up the bridge and attaches it to a DRM
encoder. A platform whose HDMI controller is a child of a larger device
needs the first half without the second, since it registers as its own
platform driver and lets the DRM core bind the bridge later.
Move the setup into a new exported inno_hdmi_probe(), with a matching
inno_hdmi_remove(), and reduce inno_hdmi_bind() to a wrapper around it.
No functional change intended.
> Move the setup into a new exported inno_hdmi_probe(), with a matching
> inno_hdmi_remove(), and reduce inno_hdmi_bind() to a wrapper around it.
[Severity: High]
The commit message mentions adding a matching inno_hdmi_remove() function,
but it does not appear to be implemented in this patch.
Without an exported remove function to safely tear down the hardware and
unmask interrupts, could this lead to hardware interrupt storms if the
platform module is removed or the driver is unbound?
> diff --git a/drivers/gpu/drm/bridge/inno-hdmi.c b/drivers/gpu/drm/bridge/inno-hdmi.c
> index 9a62bf59a4033..12fd208d5e852 100644
> --- a/drivers/gpu/drm/bridge/inno-hdmi.c
> +++ b/drivers/gpu/drm/bridge/inno-hdmi.c
[ ... ]
> +struct inno_hdmi *inno_hdmi_probe(struct platform_device *pdev,
> + const struct inno_hdmi_plat_data *plat_data)
> {
> - struct platform_device *pdev = to_platform_device(dev);
> + struct device *dev = &pdev->dev;
[Severity: High]
This isn't a bug introduced by this patch, but there appears to be a
time-of-check to time-of-use (TOCTOU) race condition during I2C adapter
registration within this setup path.
In inno_hdmi_i2c_adapter(), devm_i2c_add_adapter() publishes the adapter
to userspace before assigning hdmi->i2c = i2c. If a userspace tool
initiates an I2C transaction concurrently during this small window,
inno_hdmi_i2c_xfer() will attempt to lock i2c->lock using the still-NULL
hdmi->i2c pointer.
Can this lead to a NULL pointer dereference?
[Severity: Critical]
This is a pre-existing issue, but requesting the IRQ before the bridge
is attached seems to cause a crash on decoupled platforms.
During the hardware setup in this path, devm_request_threaded_irq()
requests the hotplug interrupt. If a monitor is already connected, the
interrupt can fire immediately. The handler, inno_hdmi_irq(), unconditionally
calls drm_helper_hpd_irq_event(hdmi->bridge.dev). However, hdmi->bridge.dev
remains NULL until drm_bridge_attach() is called later.
Since this patch explicitly supports decoupled drivers that register
the bridge without immediately attaching it, does this guarantee a boot-time
NULL pointer dereference if a display is connected?
[Severity: High]
This is a pre-existing issue, but there appears to be a devres registration
order issue that leads to a use-after-free.
The IRQ is requested via devm_request_threaded_irq() before the I2C
adapter memory is allocated with devm_kzalloc(). During device teardown,
devres cleans up resources in reverse order, meaning the I2C memory is freed
while the IRQ remains active.
If a hardware interrupt fires during this teardown window,
inno_hdmi_hardirq() will check the dangling pointer and call
inno_hdmi_i2c_irq(), which accesses the already freed memory.
Should the IRQ be requested after all resources it depends on are allocated?
[ ... ]
> +struct inno_hdmi *inno_hdmi_bind(struct device *dev,
> + struct drm_encoder *encoder,
> + const struct inno_hdmi_plat_data *plat_data)
> +{
> + struct platform_device *pdev = to_platform_device(dev);
> + struct inno_hdmi *hdmi;
> + int ret;
> +
> + hdmi = inno_hdmi_probe(pdev, plat_data);
> + if (IS_ERR(hdmi))
> + return hdmi;
> +
> + ret = drm_bridge_attach(encoder, &hdmi->bridge, NULL,
> + DRM_BRIDGE_ATTACH_NO_CONNECTOR);
> + if (ret)
> + return ERR_PTR(ret);
[Severity: High]
This isn't a bug introduced by this patch, but if drm_bridge_attach() fails
(for example, due to probe deferral of another bridge), this returns an
error directly without explicitly destroying the devm_ resources allocated
during inno_hdmi_probe().
Since devm_ allocations are tied to the component device's lifetime rather
than the component bind cycle, won't this leak memory and accumulate
duplicate IRQ registrations on each component bind retry?
--
Sashiko AI review · https://sashiko.dev/#/patchset/20260828-jh7110-clean-send-v2-0-331680c8b9d1@samsung.com?part=4
--
linux-phy mailing list
linux-phy@lists.infradead.org
https://lists.infradead.org/mailman/listinfo/linux-phy
^ permalink raw reply [flat|nested] 116+ messages in thread
* Re: [PATCH v2 09/15] clk: starfive: jh7110-vout: Allow pixel clock rate propagation
2026-08-28 13:47 ` Michal Wilczynski
@ 2026-08-28 14:01 ` sashiko-bot
-1 siblings, 0 replies; 116+ messages in thread
From: sashiko-bot @ 2026-08-28 14:01 UTC (permalink / raw)
To: Michal Wilczynski
Cc: lee, linux-clk, linux-phy, neil.armstrong, dri-devel, conor+dt,
mfd, devicetree, vkoul, olteanv, robh
Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:
- [High] Adding CLK_SET_RATE_PARENT without CLK_SET_RATE_NO_REPARENT on hardware signal-routing muxes allows clk_set_rate() to dynamically hijack the active clock parent.
--
commit 09b0c9046fefb467ad795def912713bba900bd11
Author: Michal Wilczynski <m.wilczynski@samsung.com>
clk: starfive: jh7110-vout: Allow pixel clock rate propagation
This commit adds CLK_SET_RATE_PARENT to the dc8200_pix0 and dc8200_pix1
MUXes, allowing display controller rate requests to propagate to the
parent clock.
> diff --git a/drivers/clk/starfive/clk-starfive-jh7110-vout.c b/drivers/clk/starfive/clk-starfive-jh7110-vout.c
> index bad20d5d794a7..b608fe3580311 100644
> --- a/drivers/clk/starfive/clk-starfive-jh7110-vout.c
> +++ b/drivers/clk/starfive/clk-starfive-jh7110-vout.c
> @@ -40,10 +40,10 @@ static const struct jh71x0_clk_data jh7110_voutclk_data[] = {
> JH71X0_GATE(JH7110_VOUTCLK_DC8200_AXI, "dc8200_axi", 0, JH7110_VOUTCLK_VOUT_TOP_AXI),
> JH71X0_GATE(JH7110_VOUTCLK_DC8200_CORE, "dc8200_core", 0, JH7110_VOUTCLK_VOUT_TOP_AXI),
> JH71X0_GATE(JH7110_VOUTCLK_DC8200_AHB, "dc8200_ahb", 0, JH7110_VOUTCLK_VOUT_TOP_AHB),
> - JH71X0_GMUX(JH7110_VOUTCLK_DC8200_PIX0, "dc8200_pix0", 0, 2,
> + JH71X0_GMUX(JH7110_VOUTCLK_DC8200_PIX0, "dc8200_pix0", CLK_SET_RATE_PARENT, 2,
> JH7110_VOUTCLK_DC8200_PIX,
> JH7110_VOUTCLK_HDMITX0_PIXELCLK),
> - JH71X0_GMUX(JH7110_VOUTCLK_DC8200_PIX1, "dc8200_pix1", 0, 2,
> + JH71X0_GMUX(JH7110_VOUTCLK_DC8200_PIX1, "dc8200_pix1", CLK_SET_RATE_PARENT, 2,
> JH7110_VOUTCLK_DC8200_PIX,
> JH7110_VOUTCLK_HDMITX0_PIXELCLK),
[Severity: High]
Does adding CLK_SET_RATE_PARENT without CLK_SET_RATE_NO_REPARENT on these
hardware signal-routing muxes allow CCF to unexpectedly reparent the active
clock parent?
When the display driver calls clk_set_rate() on the dc8200_pix0 or
dc8200_pix1 clock, __clk_mux_determine_rate() will evaluate all parents
because CLK_SET_RATE_NO_REPARENT is not set.
Because the HDMI PHY PLL is highly adjustable, it will likely offer a
mathematically closer rate than the generic DC8200_PIX divider. CCF will
then select the HDMI PHY as the best parent and dynamically reparent the
clock by calling clk_core_reparent().
Could this silently override the display driver's physical routing
configuration and sever the physical routing, breaking the display output?
--
Sashiko AI review · https://sashiko.dev/#/patchset/20260828-jh7110-clean-send-v2-0-331680c8b9d1@samsung.com?part=9
^ permalink raw reply [flat|nested] 116+ messages in thread
* Re: [PATCH v2 09/15] clk: starfive: jh7110-vout: Allow pixel clock rate propagation
@ 2026-08-28 14:01 ` sashiko-bot
0 siblings, 0 replies; 116+ messages in thread
From: sashiko-bot @ 2026-08-28 14:01 UTC (permalink / raw)
To: Michal Wilczynski
Cc: lee, linux-clk, linux-phy, neil.armstrong, dri-devel, conor+dt,
mfd, devicetree, vkoul, olteanv, robh
Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:
- [High] Adding CLK_SET_RATE_PARENT without CLK_SET_RATE_NO_REPARENT on hardware signal-routing muxes allows clk_set_rate() to dynamically hijack the active clock parent.
--
commit 09b0c9046fefb467ad795def912713bba900bd11
Author: Michal Wilczynski <m.wilczynski@samsung.com>
clk: starfive: jh7110-vout: Allow pixel clock rate propagation
This commit adds CLK_SET_RATE_PARENT to the dc8200_pix0 and dc8200_pix1
MUXes, allowing display controller rate requests to propagate to the
parent clock.
> diff --git a/drivers/clk/starfive/clk-starfive-jh7110-vout.c b/drivers/clk/starfive/clk-starfive-jh7110-vout.c
> index bad20d5d794a7..b608fe3580311 100644
> --- a/drivers/clk/starfive/clk-starfive-jh7110-vout.c
> +++ b/drivers/clk/starfive/clk-starfive-jh7110-vout.c
> @@ -40,10 +40,10 @@ static const struct jh71x0_clk_data jh7110_voutclk_data[] = {
> JH71X0_GATE(JH7110_VOUTCLK_DC8200_AXI, "dc8200_axi", 0, JH7110_VOUTCLK_VOUT_TOP_AXI),
> JH71X0_GATE(JH7110_VOUTCLK_DC8200_CORE, "dc8200_core", 0, JH7110_VOUTCLK_VOUT_TOP_AXI),
> JH71X0_GATE(JH7110_VOUTCLK_DC8200_AHB, "dc8200_ahb", 0, JH7110_VOUTCLK_VOUT_TOP_AHB),
> - JH71X0_GMUX(JH7110_VOUTCLK_DC8200_PIX0, "dc8200_pix0", 0, 2,
> + JH71X0_GMUX(JH7110_VOUTCLK_DC8200_PIX0, "dc8200_pix0", CLK_SET_RATE_PARENT, 2,
> JH7110_VOUTCLK_DC8200_PIX,
> JH7110_VOUTCLK_HDMITX0_PIXELCLK),
> - JH71X0_GMUX(JH7110_VOUTCLK_DC8200_PIX1, "dc8200_pix1", 0, 2,
> + JH71X0_GMUX(JH7110_VOUTCLK_DC8200_PIX1, "dc8200_pix1", CLK_SET_RATE_PARENT, 2,
> JH7110_VOUTCLK_DC8200_PIX,
> JH7110_VOUTCLK_HDMITX0_PIXELCLK),
[Severity: High]
Does adding CLK_SET_RATE_PARENT without CLK_SET_RATE_NO_REPARENT on these
hardware signal-routing muxes allow CCF to unexpectedly reparent the active
clock parent?
When the display driver calls clk_set_rate() on the dc8200_pix0 or
dc8200_pix1 clock, __clk_mux_determine_rate() will evaluate all parents
because CLK_SET_RATE_NO_REPARENT is not set.
Because the HDMI PHY PLL is highly adjustable, it will likely offer a
mathematically closer rate than the generic DC8200_PIX divider. CCF will
then select the HDMI PHY as the best parent and dynamically reparent the
clock by calling clk_core_reparent().
Could this silently override the display driver's physical routing
configuration and sever the physical routing, breaking the display output?
--
Sashiko AI review · https://sashiko.dev/#/patchset/20260828-jh7110-clean-send-v2-0-331680c8b9d1@samsung.com?part=9
--
linux-phy mailing list
linux-phy@lists.infradead.org
https://lists.infradead.org/mailman/listinfo/linux-phy
^ permalink raw reply [flat|nested] 116+ messages in thread
* Re: [PATCH v2 15/15] MAINTAINERS: Add StarFive JH7110 display subsystem entry
2026-08-28 13:47 ` Michal Wilczynski
(?)
(?)
@ 2026-08-28 14:01 ` Icenowy Zheng
-1 siblings, 0 replies; 116+ messages in thread
From: Icenowy Zheng @ 2026-08-28 14:01 UTC (permalink / raw)
To: Michal Wilczynski, Vinod Koul, Neil Armstrong, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, Andrzej Hajda, Robert Foss,
Laurent Pinchart, Jonas Karlman, Jernej Skrabec, Luca Ceresoli,
David Airlie, Simona Vetter, Maarten Lankhorst, Maxime Ripard,
Thomas Zimmermann, Lee Jones, Andy Yan, Philipp Zabel,
Emil Renner Berthing, Hal Feng, Michael Turquette, Stephen Boyd,
Brian Masney, Heiko Stuebner, Conor Dooley, Paul Walmsley,
Palmer Dabbelt, Albert Ou, Alexandre Ghiti, Dominique Belhachemi
Cc: linux-phy, devicetree, linux-kernel, dri-devel, mfd, linux-clk,
linux-arm-kernel, linux-rockchip, linux-riscv, Andy Yan,
Marek Szyprowski, Maud Spierings, Graham Markall
在 2026-08-28五的 15:47 +0200,Michal Wilczynski写道:
> The JH7110 display subsystem spans a PHY driver, a DRM bridge driver,
> a parent device and their bindings, and has no existing maintainer
> entry.
>
> Add an entry covering them so patches reach someone who can review
> them.
>
> Signed-off-by: Michal Wilczynski <m.wilczynski@samsung.com>
> ---
> MAINTAINERS | 10 ++++++++++
> 1 file changed, 10 insertions(+)
>
> diff --git a/MAINTAINERS b/MAINTAINERS
> index
> 8014b9f8253edf15231df215d1b14063a54a55ec..84ac5cfe61cdf775167cf903386
> 2724c37946a5f 100644
> --- a/MAINTAINERS
> +++ b/MAINTAINERS
> @@ -25778,6 +25778,16 @@ S: Maintained
> F: Documentation/devicetree/bindings/net/starfive,jh7110-
> dwmac.yaml
> F: drivers/net/ethernet/stmicro/stmmac/dwmac-starfive.c
>
> +STARFIVE JH7110 DISPLAY SUBSYSTEM
> +M: Michal Wilczynski <m.wilczynski@samsung.com>
Feel free to add
```
R: Icenowy Zheng <zhengxingda@iscas.ac.cn>
```
if you want. I am interested in this.
Thanks,
Icenowy
> +S: Maintained
> +F: Documentation/devicetree/bindings/display/bridge/starfive,jh
> 7110-inno-hdmi-controller.yaml
> +F: Documentation/devicetree/bindings/mfd/starfive,jh7110-hdmi-
> subsystem.yaml
> +F: Documentation/devicetree/bindings/phy/starfive,jh7110-inno-
> hdmi-phy.yaml
> +F: drivers/gpu/drm/bridge/jh7110-inno-hdmi.c
> +F: drivers/phy/starfive/phy-jh7110-inno-hdmi.c
> +F: drivers/soc/starfive/jh7110-hdmi-subsystem.c
> +
> STARFIVE JH7110 DPHY RX DRIVER
> M: Jack Zhu <jack.zhu@starfivetech.com>
> M: Changhuang Liang <changhuang.liang@starfivetech.com>
^ permalink raw reply [flat|nested] 116+ messages in thread
* Re: [PATCH v2 15/15] MAINTAINERS: Add StarFive JH7110 display subsystem entry
@ 2026-08-28 14:01 ` Icenowy Zheng
0 siblings, 0 replies; 116+ messages in thread
From: Icenowy Zheng @ 2026-08-28 14:01 UTC (permalink / raw)
To: Michal Wilczynski, Vinod Koul, Neil Armstrong, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, Andrzej Hajda, Robert Foss,
Laurent Pinchart, Jonas Karlman, Jernej Skrabec, Luca Ceresoli,
David Airlie, Simona Vetter, Maarten Lankhorst, Maxime Ripard,
Thomas Zimmermann, Lee Jones, Andy Yan, Philipp Zabel,
Emil Renner Berthing, Hal Feng, Michael Turquette, Stephen Boyd,
Brian Masney, Heiko Stuebner, Conor Dooley, Paul Walmsley,
Palmer Dabbelt, Albert Ou, Alexandre Ghiti, Dominique Belhachemi
Cc: linux-phy, devicetree, linux-kernel, dri-devel, mfd, linux-clk,
linux-arm-kernel, linux-rockchip, linux-riscv, Andy Yan,
Marek Szyprowski, Maud Spierings, Graham Markall
在 2026-08-28五的 15:47 +0200,Michal Wilczynski写道:
> The JH7110 display subsystem spans a PHY driver, a DRM bridge driver,
> a parent device and their bindings, and has no existing maintainer
> entry.
>
> Add an entry covering them so patches reach someone who can review
> them.
>
> Signed-off-by: Michal Wilczynski <m.wilczynski@samsung.com>
> ---
> MAINTAINERS | 10 ++++++++++
> 1 file changed, 10 insertions(+)
>
> diff --git a/MAINTAINERS b/MAINTAINERS
> index
> 8014b9f8253edf15231df215d1b14063a54a55ec..84ac5cfe61cdf775167cf903386
> 2724c37946a5f 100644
> --- a/MAINTAINERS
> +++ b/MAINTAINERS
> @@ -25778,6 +25778,16 @@ S: Maintained
> F: Documentation/devicetree/bindings/net/starfive,jh7110-
> dwmac.yaml
> F: drivers/net/ethernet/stmicro/stmmac/dwmac-starfive.c
>
> +STARFIVE JH7110 DISPLAY SUBSYSTEM
> +M: Michal Wilczynski <m.wilczynski@samsung.com>
Feel free to add
```
R: Icenowy Zheng <zhengxingda@iscas.ac.cn>
```
if you want. I am interested in this.
Thanks,
Icenowy
> +S: Maintained
> +F: Documentation/devicetree/bindings/display/bridge/starfive,jh
> 7110-inno-hdmi-controller.yaml
> +F: Documentation/devicetree/bindings/mfd/starfive,jh7110-hdmi-
> subsystem.yaml
> +F: Documentation/devicetree/bindings/phy/starfive,jh7110-inno-
> hdmi-phy.yaml
> +F: drivers/gpu/drm/bridge/jh7110-inno-hdmi.c
> +F: drivers/phy/starfive/phy-jh7110-inno-hdmi.c
> +F: drivers/soc/starfive/jh7110-hdmi-subsystem.c
> +
> STARFIVE JH7110 DPHY RX DRIVER
> M: Jack Zhu <jack.zhu@starfivetech.com>
> M: Changhuang Liang <changhuang.liang@starfivetech.com>
_______________________________________________
Linux-rockchip mailing list
Linux-rockchip@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-rockchip
^ permalink raw reply [flat|nested] 116+ messages in thread
* Re: [PATCH v2 15/15] MAINTAINERS: Add StarFive JH7110 display subsystem entry
@ 2026-08-28 14:01 ` Icenowy Zheng
0 siblings, 0 replies; 116+ messages in thread
From: Icenowy Zheng @ 2026-08-28 14:01 UTC (permalink / raw)
To: Michal Wilczynski, Vinod Koul, Neil Armstrong, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, Andrzej Hajda, Robert Foss,
Laurent Pinchart, Jonas Karlman, Jernej Skrabec, Luca Ceresoli,
David Airlie, Simona Vetter, Maarten Lankhorst, Maxime Ripard,
Thomas Zimmermann, Lee Jones, Andy Yan, Philipp Zabel,
Emil Renner Berthing, Hal Feng, Michael Turquette, Stephen Boyd,
Brian Masney, Heiko Stuebner, Conor Dooley, Paul Walmsley,
Palmer Dabbelt, Albert Ou, Alexandre Ghiti, Dominique Belhachemi
Cc: linux-phy, devicetree, linux-kernel, dri-devel, mfd, linux-clk,
linux-arm-kernel, linux-rockchip, linux-riscv, Andy Yan,
Marek Szyprowski, Maud Spierings, Graham Markall
在 2026-08-28五的 15:47 +0200,Michal Wilczynski写道:
> The JH7110 display subsystem spans a PHY driver, a DRM bridge driver,
> a parent device and their bindings, and has no existing maintainer
> entry.
>
> Add an entry covering them so patches reach someone who can review
> them.
>
> Signed-off-by: Michal Wilczynski <m.wilczynski@samsung.com>
> ---
> MAINTAINERS | 10 ++++++++++
> 1 file changed, 10 insertions(+)
>
> diff --git a/MAINTAINERS b/MAINTAINERS
> index
> 8014b9f8253edf15231df215d1b14063a54a55ec..84ac5cfe61cdf775167cf903386
> 2724c37946a5f 100644
> --- a/MAINTAINERS
> +++ b/MAINTAINERS
> @@ -25778,6 +25778,16 @@ S: Maintained
> F: Documentation/devicetree/bindings/net/starfive,jh7110-
> dwmac.yaml
> F: drivers/net/ethernet/stmicro/stmmac/dwmac-starfive.c
>
> +STARFIVE JH7110 DISPLAY SUBSYSTEM
> +M: Michal Wilczynski <m.wilczynski@samsung.com>
Feel free to add
```
R: Icenowy Zheng <zhengxingda@iscas.ac.cn>
```
if you want. I am interested in this.
Thanks,
Icenowy
> +S: Maintained
> +F: Documentation/devicetree/bindings/display/bridge/starfive,jh
> 7110-inno-hdmi-controller.yaml
> +F: Documentation/devicetree/bindings/mfd/starfive,jh7110-hdmi-
> subsystem.yaml
> +F: Documentation/devicetree/bindings/phy/starfive,jh7110-inno-
> hdmi-phy.yaml
> +F: drivers/gpu/drm/bridge/jh7110-inno-hdmi.c
> +F: drivers/phy/starfive/phy-jh7110-inno-hdmi.c
> +F: drivers/soc/starfive/jh7110-hdmi-subsystem.c
> +
> STARFIVE JH7110 DPHY RX DRIVER
> M: Jack Zhu <jack.zhu@starfivetech.com>
> M: Changhuang Liang <changhuang.liang@starfivetech.com>
--
linux-phy mailing list
linux-phy@lists.infradead.org
https://lists.infradead.org/mailman/listinfo/linux-phy
^ permalink raw reply [flat|nested] 116+ messages in thread
* Re: [PATCH v2 15/15] MAINTAINERS: Add StarFive JH7110 display subsystem entry
@ 2026-08-28 14:01 ` Icenowy Zheng
0 siblings, 0 replies; 116+ messages in thread
From: Icenowy Zheng @ 2026-08-28 14:01 UTC (permalink / raw)
To: Michal Wilczynski, Vinod Koul, Neil Armstrong, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, Andrzej Hajda, Robert Foss,
Laurent Pinchart, Jonas Karlman, Jernej Skrabec, Luca Ceresoli,
David Airlie, Simona Vetter, Maarten Lankhorst, Maxime Ripard,
Thomas Zimmermann, Lee Jones, Andy Yan, Philipp Zabel,
Emil Renner Berthing, Hal Feng, Michael Turquette, Stephen Boyd,
Brian Masney, Heiko Stuebner, Conor Dooley, Paul Walmsley,
Palmer Dabbelt, Albert Ou, Alexandre Ghiti, Dominique Belhachemi
Cc: linux-phy, devicetree, linux-kernel, dri-devel, mfd, linux-clk,
linux-arm-kernel, linux-rockchip, linux-riscv, Andy Yan,
Marek Szyprowski, Maud Spierings, Graham Markall
在 2026-08-28五的 15:47 +0200,Michal Wilczynski写道:
> The JH7110 display subsystem spans a PHY driver, a DRM bridge driver,
> a parent device and their bindings, and has no existing maintainer
> entry.
>
> Add an entry covering them so patches reach someone who can review
> them.
>
> Signed-off-by: Michal Wilczynski <m.wilczynski@samsung.com>
> ---
> MAINTAINERS | 10 ++++++++++
> 1 file changed, 10 insertions(+)
>
> diff --git a/MAINTAINERS b/MAINTAINERS
> index
> 8014b9f8253edf15231df215d1b14063a54a55ec..84ac5cfe61cdf775167cf903386
> 2724c37946a5f 100644
> --- a/MAINTAINERS
> +++ b/MAINTAINERS
> @@ -25778,6 +25778,16 @@ S: Maintained
> F: Documentation/devicetree/bindings/net/starfive,jh7110-
> dwmac.yaml
> F: drivers/net/ethernet/stmicro/stmmac/dwmac-starfive.c
>
> +STARFIVE JH7110 DISPLAY SUBSYSTEM
> +M: Michal Wilczynski <m.wilczynski@samsung.com>
Feel free to add
```
R: Icenowy Zheng <zhengxingda@iscas.ac.cn>
```
if you want. I am interested in this.
Thanks,
Icenowy
> +S: Maintained
> +F: Documentation/devicetree/bindings/display/bridge/starfive,jh
> 7110-inno-hdmi-controller.yaml
> +F: Documentation/devicetree/bindings/mfd/starfive,jh7110-hdmi-
> subsystem.yaml
> +F: Documentation/devicetree/bindings/phy/starfive,jh7110-inno-
> hdmi-phy.yaml
> +F: drivers/gpu/drm/bridge/jh7110-inno-hdmi.c
> +F: drivers/phy/starfive/phy-jh7110-inno-hdmi.c
> +F: drivers/soc/starfive/jh7110-hdmi-subsystem.c
> +
> STARFIVE JH7110 DPHY RX DRIVER
> M: Jack Zhu <jack.zhu@starfivetech.com>
> M: Changhuang Liang <changhuang.liang@starfivetech.com>
_______________________________________________
linux-riscv mailing list
linux-riscv@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-riscv
^ permalink raw reply [flat|nested] 116+ messages in thread
* Re: [PATCH v2 02/15] dt-bindings: display: bridge: Add starfive,jh7110-inno-hdmi-controller
2026-08-28 13:47 ` Michal Wilczynski
(?)
(?)
@ 2026-08-28 14:04 ` Icenowy Zheng
-1 siblings, 0 replies; 116+ messages in thread
From: Icenowy Zheng @ 2026-08-28 14:04 UTC (permalink / raw)
To: Michal Wilczynski, Vinod Koul, Neil Armstrong, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, Andrzej Hajda, Robert Foss,
Laurent Pinchart, Jonas Karlman, Jernej Skrabec, Luca Ceresoli,
David Airlie, Simona Vetter, Maarten Lankhorst, Maxime Ripard,
Thomas Zimmermann, Lee Jones, Andy Yan, Philipp Zabel,
Emil Renner Berthing, Hal Feng, Michael Turquette, Stephen Boyd,
Brian Masney, Heiko Stuebner, Conor Dooley, Paul Walmsley,
Palmer Dabbelt, Albert Ou, Alexandre Ghiti, Dominique Belhachemi
Cc: linux-phy, devicetree, linux-kernel, dri-devel, mfd, linux-clk,
linux-arm-kernel, linux-rockchip, linux-riscv, Andy Yan,
Marek Szyprowski, Maud Spierings, Graham Markall
在 2026-08-28五的 15:47 +0200,Michal Wilczynski写道:
> Add the dt-binding for the StarFive JH7110 Innosilicon HDMI
> controller
> (DRM bridge).
>
> This device is the second child of the starfive,jh7110-hdmi-subsystem
> node.
> It consumes register access clocks (sys, mclk, bclk) from the voutcrg
> and
> both the pixel clock (pclk) and the PHY from its hdmi_phy sibling.
>
> Signed-off-by: Michal Wilczynski <m.wilczynski@samsung.com>
> ---
> .../starfive,jh7110-inno-hdmi-controller.yaml | 109
> +++++++++++++++++++++
> 1 file changed, 109 insertions(+)
>
> diff --git
> a/Documentation/devicetree/bindings/display/bridge/starfive,jh7110-
> inno-hdmi-controller.yaml
> b/Documentation/devicetree/bindings/display/bridge/starfive,jh7110-
> inno-hdmi-controller.yaml
> new file mode 100644
> index
> 0000000000000000000000000000000000000000..0e584e7b756e24e2f99a62daab3
> 117bbf4b472b6
> --- /dev/null
> +++
> b/Documentation/devicetree/bindings/display/bridge/starfive,jh7110-
> inno-hdmi-controller.yaml
> @@ -0,0 +1,109 @@
> +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
> +%YAML 1.2
> +---
> +$id:
> http://devicetree.org/schemas/display/bridge/starfive,jh7110-inno-hdmi-controller.yaml#
> +$schema: http://devicetree.org/meta-schemas/core.yaml#
> +
> +title: StarFive JH7110 Innosilicon HDMI Controller
> +
> +maintainers:
> + - Michal Wilczynski <m.wilczynski@samsung.com>
> +
> +description:
> + The controller portion of the StarFive JH7110 INNO HDMI IP.
> +
> +properties:
> + compatible:
> + const: starfive,jh7110-inno-hdmi-controller
> +
> + interrupts:
> + maxItems: 1
> +
> + clocks:
> + items:
> + - description: System clock for register access
> + - description: Module clock
> + - description: Bus clock
> + - description: Pixel clock from PHY
> +
> + clock-names:
> + items:
> + - const: sys
> + - const: mclk
> + - const: bclk
> + - const: pclk
> +
> + resets:
> + maxItems: 1
> +
> + reset-names:
> + const: hdmi_tx
> +
> + phys:
> + maxItems: 1
> +
> + phy-names:
> + const: hdmi-phy
> +
> + ports:
> + $ref: /schemas/graph.yaml#/properties/ports
> + description:
> + A graph node with one input port and one output port.
Maybe this device should handle the display mux in the dom_vout_syscon
part. This syscon is documented in the JH7110 TRM, and the address is
at 0x295b0000.
According to the manual, bit 30:25 of register 0x4 and bit 4 of
register 0x8 (which is marked as u2_display_panel_mux_panel_sel, but
in the block diagram of display subsystem, it could be seen that the
mux controlling the input of HDMI_Ctrl is u2_display_panel_mux) is
related to the HDMI display, with the setup of 8-bit DPI0 connected to
HDMI controller as the default value (u0_hdmi_data_mapping_dpi_dp_sel
= 0 (DPI), u0_hdmi_data_mapping_dpi_bit_depth = 0 (8-bit),
u2_display_panel_mux_panel_sel = 0 (Panel 0)), and this is currently
your example setup.
At least leave a syscon property pointing to the syscon would be then
useful, and maybe it's better to setup the syscon values based on which
DC8200 output interface is in use.
Thanks,
Icenowy
> +
> +required:
> + - compatible
> + - interrupts
> + - clocks
> + - clock-names
> + - resets
> + - reset-names
> + - phys
> + - phy-names
> + - ports
> +
> +additionalProperties: false
> +
> +examples:
> + # Shown as a child of the HDMI subsystem node; see
> + # Documentation/devicetree/bindings/mfd/starfive,jh7110-hdmi-
> subsystem.yaml
> + # for the full node.
> + - |
> + #include <dt-bindings/clock/starfive,jh7110-crg.h>
> + #include <dt-bindings/reset/starfive,jh7110-crg.h>
> +
> + controller {
> + compatible = "starfive,jh7110-inno-hdmi-controller";
> + clocks = <&voutcrg JH7110_VOUTCLK_HDMI_TX_SYS>,
> + <&voutcrg JH7110_VOUTCLK_HDMI_TX_MCLK>,
> + <&voutcrg JH7110_VOUTCLK_HDMI_TX_BCLK>,
> + <&hdmi_phy>;
> + clock-names = "sys", "mclk", "bclk", "pclk";
> + interrupts = <99>;
> + phys = <&hdmi_phy>;
> + phy-names = "hdmi-phy";
> + resets = <&voutcrg JH7110_VOUTRST_HDMI_TX_HDMI>;
> + reset-names = "hdmi_tx";
> +
> + ports {
> + #address-cells = <1>;
> + #size-cells = <0>;
> +
> + port@0 {
> + reg = <0>;
> +
> + endpoint {
> + remote-endpoint = <&dpu_out_dpi0>;
> + };
> + };
> +
> + port@1 {
> + reg = <1>;
> +
> + endpoint {
> + remote-endpoint = <&hdmi_con_in>;
> + };
> + };
> + };
> + };
> +
> +...
^ permalink raw reply [flat|nested] 116+ messages in thread
* Re: [PATCH v2 02/15] dt-bindings: display: bridge: Add starfive,jh7110-inno-hdmi-controller
@ 2026-08-28 14:04 ` Icenowy Zheng
0 siblings, 0 replies; 116+ messages in thread
From: Icenowy Zheng @ 2026-08-28 14:04 UTC (permalink / raw)
To: Michal Wilczynski, Vinod Koul, Neil Armstrong, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, Andrzej Hajda, Robert Foss,
Laurent Pinchart, Jonas Karlman, Jernej Skrabec, Luca Ceresoli,
David Airlie, Simona Vetter, Maarten Lankhorst, Maxime Ripard,
Thomas Zimmermann, Lee Jones, Andy Yan, Philipp Zabel,
Emil Renner Berthing, Hal Feng, Michael Turquette, Stephen Boyd,
Brian Masney, Heiko Stuebner, Conor Dooley, Paul Walmsley,
Palmer Dabbelt, Albert Ou, Alexandre Ghiti, Dominique Belhachemi
Cc: linux-phy, devicetree, linux-kernel, dri-devel, mfd, linux-clk,
linux-arm-kernel, linux-rockchip, linux-riscv, Andy Yan,
Marek Szyprowski, Maud Spierings, Graham Markall
在 2026-08-28五的 15:47 +0200,Michal Wilczynski写道:
> Add the dt-binding for the StarFive JH7110 Innosilicon HDMI
> controller
> (DRM bridge).
>
> This device is the second child of the starfive,jh7110-hdmi-subsystem
> node.
> It consumes register access clocks (sys, mclk, bclk) from the voutcrg
> and
> both the pixel clock (pclk) and the PHY from its hdmi_phy sibling.
>
> Signed-off-by: Michal Wilczynski <m.wilczynski@samsung.com>
> ---
> .../starfive,jh7110-inno-hdmi-controller.yaml | 109
> +++++++++++++++++++++
> 1 file changed, 109 insertions(+)
>
> diff --git
> a/Documentation/devicetree/bindings/display/bridge/starfive,jh7110-
> inno-hdmi-controller.yaml
> b/Documentation/devicetree/bindings/display/bridge/starfive,jh7110-
> inno-hdmi-controller.yaml
> new file mode 100644
> index
> 0000000000000000000000000000000000000000..0e584e7b756e24e2f99a62daab3
> 117bbf4b472b6
> --- /dev/null
> +++
> b/Documentation/devicetree/bindings/display/bridge/starfive,jh7110-
> inno-hdmi-controller.yaml
> @@ -0,0 +1,109 @@
> +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
> +%YAML 1.2
> +---
> +$id:
> http://devicetree.org/schemas/display/bridge/starfive,jh7110-inno-hdmi-controller.yaml#
> +$schema: http://devicetree.org/meta-schemas/core.yaml#
> +
> +title: StarFive JH7110 Innosilicon HDMI Controller
> +
> +maintainers:
> + - Michal Wilczynski <m.wilczynski@samsung.com>
> +
> +description:
> + The controller portion of the StarFive JH7110 INNO HDMI IP.
> +
> +properties:
> + compatible:
> + const: starfive,jh7110-inno-hdmi-controller
> +
> + interrupts:
> + maxItems: 1
> +
> + clocks:
> + items:
> + - description: System clock for register access
> + - description: Module clock
> + - description: Bus clock
> + - description: Pixel clock from PHY
> +
> + clock-names:
> + items:
> + - const: sys
> + - const: mclk
> + - const: bclk
> + - const: pclk
> +
> + resets:
> + maxItems: 1
> +
> + reset-names:
> + const: hdmi_tx
> +
> + phys:
> + maxItems: 1
> +
> + phy-names:
> + const: hdmi-phy
> +
> + ports:
> + $ref: /schemas/graph.yaml#/properties/ports
> + description:
> + A graph node with one input port and one output port.
Maybe this device should handle the display mux in the dom_vout_syscon
part. This syscon is documented in the JH7110 TRM, and the address is
at 0x295b0000.
According to the manual, bit 30:25 of register 0x4 and bit 4 of
register 0x8 (which is marked as u2_display_panel_mux_panel_sel, but
in the block diagram of display subsystem, it could be seen that the
mux controlling the input of HDMI_Ctrl is u2_display_panel_mux) is
related to the HDMI display, with the setup of 8-bit DPI0 connected to
HDMI controller as the default value (u0_hdmi_data_mapping_dpi_dp_sel
= 0 (DPI), u0_hdmi_data_mapping_dpi_bit_depth = 0 (8-bit),
u2_display_panel_mux_panel_sel = 0 (Panel 0)), and this is currently
your example setup.
At least leave a syscon property pointing to the syscon would be then
useful, and maybe it's better to setup the syscon values based on which
DC8200 output interface is in use.
Thanks,
Icenowy
> +
> +required:
> + - compatible
> + - interrupts
> + - clocks
> + - clock-names
> + - resets
> + - reset-names
> + - phys
> + - phy-names
> + - ports
> +
> +additionalProperties: false
> +
> +examples:
> + # Shown as a child of the HDMI subsystem node; see
> + # Documentation/devicetree/bindings/mfd/starfive,jh7110-hdmi-
> subsystem.yaml
> + # for the full node.
> + - |
> + #include <dt-bindings/clock/starfive,jh7110-crg.h>
> + #include <dt-bindings/reset/starfive,jh7110-crg.h>
> +
> + controller {
> + compatible = "starfive,jh7110-inno-hdmi-controller";
> + clocks = <&voutcrg JH7110_VOUTCLK_HDMI_TX_SYS>,
> + <&voutcrg JH7110_VOUTCLK_HDMI_TX_MCLK>,
> + <&voutcrg JH7110_VOUTCLK_HDMI_TX_BCLK>,
> + <&hdmi_phy>;
> + clock-names = "sys", "mclk", "bclk", "pclk";
> + interrupts = <99>;
> + phys = <&hdmi_phy>;
> + phy-names = "hdmi-phy";
> + resets = <&voutcrg JH7110_VOUTRST_HDMI_TX_HDMI>;
> + reset-names = "hdmi_tx";
> +
> + ports {
> + #address-cells = <1>;
> + #size-cells = <0>;
> +
> + port@0 {
> + reg = <0>;
> +
> + endpoint {
> + remote-endpoint = <&dpu_out_dpi0>;
> + };
> + };
> +
> + port@1 {
> + reg = <1>;
> +
> + endpoint {
> + remote-endpoint = <&hdmi_con_in>;
> + };
> + };
> + };
> + };
> +
> +...
_______________________________________________
Linux-rockchip mailing list
Linux-rockchip@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-rockchip
^ permalink raw reply [flat|nested] 116+ messages in thread
* Re: [PATCH v2 02/15] dt-bindings: display: bridge: Add starfive,jh7110-inno-hdmi-controller
@ 2026-08-28 14:04 ` Icenowy Zheng
0 siblings, 0 replies; 116+ messages in thread
From: Icenowy Zheng @ 2026-08-28 14:04 UTC (permalink / raw)
To: Michal Wilczynski, Vinod Koul, Neil Armstrong, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, Andrzej Hajda, Robert Foss,
Laurent Pinchart, Jonas Karlman, Jernej Skrabec, Luca Ceresoli,
David Airlie, Simona Vetter, Maarten Lankhorst, Maxime Ripard,
Thomas Zimmermann, Lee Jones, Andy Yan, Philipp Zabel,
Emil Renner Berthing, Hal Feng, Michael Turquette, Stephen Boyd,
Brian Masney, Heiko Stuebner, Conor Dooley, Paul Walmsley,
Palmer Dabbelt, Albert Ou, Alexandre Ghiti, Dominique Belhachemi
Cc: linux-phy, devicetree, linux-kernel, dri-devel, mfd, linux-clk,
linux-arm-kernel, linux-rockchip, linux-riscv, Andy Yan,
Marek Szyprowski, Maud Spierings, Graham Markall
在 2026-08-28五的 15:47 +0200,Michal Wilczynski写道:
> Add the dt-binding for the StarFive JH7110 Innosilicon HDMI
> controller
> (DRM bridge).
>
> This device is the second child of the starfive,jh7110-hdmi-subsystem
> node.
> It consumes register access clocks (sys, mclk, bclk) from the voutcrg
> and
> both the pixel clock (pclk) and the PHY from its hdmi_phy sibling.
>
> Signed-off-by: Michal Wilczynski <m.wilczynski@samsung.com>
> ---
> .../starfive,jh7110-inno-hdmi-controller.yaml | 109
> +++++++++++++++++++++
> 1 file changed, 109 insertions(+)
>
> diff --git
> a/Documentation/devicetree/bindings/display/bridge/starfive,jh7110-
> inno-hdmi-controller.yaml
> b/Documentation/devicetree/bindings/display/bridge/starfive,jh7110-
> inno-hdmi-controller.yaml
> new file mode 100644
> index
> 0000000000000000000000000000000000000000..0e584e7b756e24e2f99a62daab3
> 117bbf4b472b6
> --- /dev/null
> +++
> b/Documentation/devicetree/bindings/display/bridge/starfive,jh7110-
> inno-hdmi-controller.yaml
> @@ -0,0 +1,109 @@
> +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
> +%YAML 1.2
> +---
> +$id:
> http://devicetree.org/schemas/display/bridge/starfive,jh7110-inno-hdmi-controller.yaml#
> +$schema: http://devicetree.org/meta-schemas/core.yaml#
> +
> +title: StarFive JH7110 Innosilicon HDMI Controller
> +
> +maintainers:
> + - Michal Wilczynski <m.wilczynski@samsung.com>
> +
> +description:
> + The controller portion of the StarFive JH7110 INNO HDMI IP.
> +
> +properties:
> + compatible:
> + const: starfive,jh7110-inno-hdmi-controller
> +
> + interrupts:
> + maxItems: 1
> +
> + clocks:
> + items:
> + - description: System clock for register access
> + - description: Module clock
> + - description: Bus clock
> + - description: Pixel clock from PHY
> +
> + clock-names:
> + items:
> + - const: sys
> + - const: mclk
> + - const: bclk
> + - const: pclk
> +
> + resets:
> + maxItems: 1
> +
> + reset-names:
> + const: hdmi_tx
> +
> + phys:
> + maxItems: 1
> +
> + phy-names:
> + const: hdmi-phy
> +
> + ports:
> + $ref: /schemas/graph.yaml#/properties/ports
> + description:
> + A graph node with one input port and one output port.
Maybe this device should handle the display mux in the dom_vout_syscon
part. This syscon is documented in the JH7110 TRM, and the address is
at 0x295b0000.
According to the manual, bit 30:25 of register 0x4 and bit 4 of
register 0x8 (which is marked as u2_display_panel_mux_panel_sel, but
in the block diagram of display subsystem, it could be seen that the
mux controlling the input of HDMI_Ctrl is u2_display_panel_mux) is
related to the HDMI display, with the setup of 8-bit DPI0 connected to
HDMI controller as the default value (u0_hdmi_data_mapping_dpi_dp_sel
= 0 (DPI), u0_hdmi_data_mapping_dpi_bit_depth = 0 (8-bit),
u2_display_panel_mux_panel_sel = 0 (Panel 0)), and this is currently
your example setup.
At least leave a syscon property pointing to the syscon would be then
useful, and maybe it's better to setup the syscon values based on which
DC8200 output interface is in use.
Thanks,
Icenowy
> +
> +required:
> + - compatible
> + - interrupts
> + - clocks
> + - clock-names
> + - resets
> + - reset-names
> + - phys
> + - phy-names
> + - ports
> +
> +additionalProperties: false
> +
> +examples:
> + # Shown as a child of the HDMI subsystem node; see
> + # Documentation/devicetree/bindings/mfd/starfive,jh7110-hdmi-
> subsystem.yaml
> + # for the full node.
> + - |
> + #include <dt-bindings/clock/starfive,jh7110-crg.h>
> + #include <dt-bindings/reset/starfive,jh7110-crg.h>
> +
> + controller {
> + compatible = "starfive,jh7110-inno-hdmi-controller";
> + clocks = <&voutcrg JH7110_VOUTCLK_HDMI_TX_SYS>,
> + <&voutcrg JH7110_VOUTCLK_HDMI_TX_MCLK>,
> + <&voutcrg JH7110_VOUTCLK_HDMI_TX_BCLK>,
> + <&hdmi_phy>;
> + clock-names = "sys", "mclk", "bclk", "pclk";
> + interrupts = <99>;
> + phys = <&hdmi_phy>;
> + phy-names = "hdmi-phy";
> + resets = <&voutcrg JH7110_VOUTRST_HDMI_TX_HDMI>;
> + reset-names = "hdmi_tx";
> +
> + ports {
> + #address-cells = <1>;
> + #size-cells = <0>;
> +
> + port@0 {
> + reg = <0>;
> +
> + endpoint {
> + remote-endpoint = <&dpu_out_dpi0>;
> + };
> + };
> +
> + port@1 {
> + reg = <1>;
> +
> + endpoint {
> + remote-endpoint = <&hdmi_con_in>;
> + };
> + };
> + };
> + };
> +
> +...
--
linux-phy mailing list
linux-phy@lists.infradead.org
https://lists.infradead.org/mailman/listinfo/linux-phy
^ permalink raw reply [flat|nested] 116+ messages in thread
* Re: [PATCH v2 02/15] dt-bindings: display: bridge: Add starfive,jh7110-inno-hdmi-controller
@ 2026-08-28 14:04 ` Icenowy Zheng
0 siblings, 0 replies; 116+ messages in thread
From: Icenowy Zheng @ 2026-08-28 14:04 UTC (permalink / raw)
To: Michal Wilczynski, Vinod Koul, Neil Armstrong, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, Andrzej Hajda, Robert Foss,
Laurent Pinchart, Jonas Karlman, Jernej Skrabec, Luca Ceresoli,
David Airlie, Simona Vetter, Maarten Lankhorst, Maxime Ripard,
Thomas Zimmermann, Lee Jones, Andy Yan, Philipp Zabel,
Emil Renner Berthing, Hal Feng, Michael Turquette, Stephen Boyd,
Brian Masney, Heiko Stuebner, Conor Dooley, Paul Walmsley,
Palmer Dabbelt, Albert Ou, Alexandre Ghiti, Dominique Belhachemi
Cc: linux-phy, devicetree, linux-kernel, dri-devel, mfd, linux-clk,
linux-arm-kernel, linux-rockchip, linux-riscv, Andy Yan,
Marek Szyprowski, Maud Spierings, Graham Markall
在 2026-08-28五的 15:47 +0200,Michal Wilczynski写道:
> Add the dt-binding for the StarFive JH7110 Innosilicon HDMI
> controller
> (DRM bridge).
>
> This device is the second child of the starfive,jh7110-hdmi-subsystem
> node.
> It consumes register access clocks (sys, mclk, bclk) from the voutcrg
> and
> both the pixel clock (pclk) and the PHY from its hdmi_phy sibling.
>
> Signed-off-by: Michal Wilczynski <m.wilczynski@samsung.com>
> ---
> .../starfive,jh7110-inno-hdmi-controller.yaml | 109
> +++++++++++++++++++++
> 1 file changed, 109 insertions(+)
>
> diff --git
> a/Documentation/devicetree/bindings/display/bridge/starfive,jh7110-
> inno-hdmi-controller.yaml
> b/Documentation/devicetree/bindings/display/bridge/starfive,jh7110-
> inno-hdmi-controller.yaml
> new file mode 100644
> index
> 0000000000000000000000000000000000000000..0e584e7b756e24e2f99a62daab3
> 117bbf4b472b6
> --- /dev/null
> +++
> b/Documentation/devicetree/bindings/display/bridge/starfive,jh7110-
> inno-hdmi-controller.yaml
> @@ -0,0 +1,109 @@
> +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
> +%YAML 1.2
> +---
> +$id:
> http://devicetree.org/schemas/display/bridge/starfive,jh7110-inno-hdmi-controller.yaml#
> +$schema: http://devicetree.org/meta-schemas/core.yaml#
> +
> +title: StarFive JH7110 Innosilicon HDMI Controller
> +
> +maintainers:
> + - Michal Wilczynski <m.wilczynski@samsung.com>
> +
> +description:
> + The controller portion of the StarFive JH7110 INNO HDMI IP.
> +
> +properties:
> + compatible:
> + const: starfive,jh7110-inno-hdmi-controller
> +
> + interrupts:
> + maxItems: 1
> +
> + clocks:
> + items:
> + - description: System clock for register access
> + - description: Module clock
> + - description: Bus clock
> + - description: Pixel clock from PHY
> +
> + clock-names:
> + items:
> + - const: sys
> + - const: mclk
> + - const: bclk
> + - const: pclk
> +
> + resets:
> + maxItems: 1
> +
> + reset-names:
> + const: hdmi_tx
> +
> + phys:
> + maxItems: 1
> +
> + phy-names:
> + const: hdmi-phy
> +
> + ports:
> + $ref: /schemas/graph.yaml#/properties/ports
> + description:
> + A graph node with one input port and one output port.
Maybe this device should handle the display mux in the dom_vout_syscon
part. This syscon is documented in the JH7110 TRM, and the address is
at 0x295b0000.
According to the manual, bit 30:25 of register 0x4 and bit 4 of
register 0x8 (which is marked as u2_display_panel_mux_panel_sel, but
in the block diagram of display subsystem, it could be seen that the
mux controlling the input of HDMI_Ctrl is u2_display_panel_mux) is
related to the HDMI display, with the setup of 8-bit DPI0 connected to
HDMI controller as the default value (u0_hdmi_data_mapping_dpi_dp_sel
= 0 (DPI), u0_hdmi_data_mapping_dpi_bit_depth = 0 (8-bit),
u2_display_panel_mux_panel_sel = 0 (Panel 0)), and this is currently
your example setup.
At least leave a syscon property pointing to the syscon would be then
useful, and maybe it's better to setup the syscon values based on which
DC8200 output interface is in use.
Thanks,
Icenowy
> +
> +required:
> + - compatible
> + - interrupts
> + - clocks
> + - clock-names
> + - resets
> + - reset-names
> + - phys
> + - phy-names
> + - ports
> +
> +additionalProperties: false
> +
> +examples:
> + # Shown as a child of the HDMI subsystem node; see
> + # Documentation/devicetree/bindings/mfd/starfive,jh7110-hdmi-
> subsystem.yaml
> + # for the full node.
> + - |
> + #include <dt-bindings/clock/starfive,jh7110-crg.h>
> + #include <dt-bindings/reset/starfive,jh7110-crg.h>
> +
> + controller {
> + compatible = "starfive,jh7110-inno-hdmi-controller";
> + clocks = <&voutcrg JH7110_VOUTCLK_HDMI_TX_SYS>,
> + <&voutcrg JH7110_VOUTCLK_HDMI_TX_MCLK>,
> + <&voutcrg JH7110_VOUTCLK_HDMI_TX_BCLK>,
> + <&hdmi_phy>;
> + clock-names = "sys", "mclk", "bclk", "pclk";
> + interrupts = <99>;
> + phys = <&hdmi_phy>;
> + phy-names = "hdmi-phy";
> + resets = <&voutcrg JH7110_VOUTRST_HDMI_TX_HDMI>;
> + reset-names = "hdmi_tx";
> +
> + ports {
> + #address-cells = <1>;
> + #size-cells = <0>;
> +
> + port@0 {
> + reg = <0>;
> +
> + endpoint {
> + remote-endpoint = <&dpu_out_dpi0>;
> + };
> + };
> +
> + port@1 {
> + reg = <1>;
> +
> + endpoint {
> + remote-endpoint = <&hdmi_con_in>;
> + };
> + };
> + };
> + };
> +
> +...
_______________________________________________
linux-riscv mailing list
linux-riscv@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-riscv
^ permalink raw reply [flat|nested] 116+ messages in thread
* Re: [PATCH v2 13/15] phy: starfive: Add jh7110-inno-hdmi-phy driver
2026-08-28 13:47 ` Michal Wilczynski
@ 2026-08-28 14:04 ` sashiko-bot
-1 siblings, 0 replies; 116+ messages in thread
From: sashiko-bot @ 2026-08-28 14:04 UTC (permalink / raw)
To: Michal Wilczynski
Cc: mfd, linux-phy, neil.armstrong, linux-clk, conor+dt, dri-devel,
devicetree, lee, olteanv, vkoul, robh
Thank you for your contribution! Sashiko AI review found 3 potential issue(s) to consider:
- [High] Missing cleanup on the clk_set_rate error path in probe leaves a dangling clock provider.
- [High] Clock operations incorrectly modify analog PHY state without synchronization, risking state corruption and power leaks.
- [Medium] Hardware PHY resources are left powered on if starfive_hdmi_phy_power_on() fails.
--
commit 7c46f9e86f09391b8c542e940da1457e36661874
Author: Michal Wilczynski <m.wilczynski@samsung.com>
phy: starfive: Add jh7110-inno-hdmi-phy driver
This commit adds the HDMI PHY driver for the StarFive JH7110. It provides
the variable pixel clock from the Pre-PLL and the PHY operations for the
Post-PLL and analog blocks.
> diff --git a/drivers/phy/starfive/phy-jh7110-inno-hdmi.c b/drivers/phy/starfive/phy-jh7110-inno-hdmi.c
> new file mode 100644
> --- /dev/null
> +++ b/drivers/phy/starfive/phy-jh7110-inno-hdmi.c
[ ... ]
> +static int starfive_hdmi_phy_clk_set_rate(struct clk_hw *hw, unsigned long rate,
> + unsigned long parent_rate)
> +{
[ ... ]
> + if (inno->pixclock == rate && inno->tmdsclock == cfg->tmdsclock)
> + return 0;
> +
> + inno_update_bits(inno, STF_INNO_BIAS_CONTROL,
> + STF_INNO_BIAS_ENABLE, STF_INNO_BIAS_ENABLE);
> + inno_write(inno, STF_INNO_RX_CONTROL, STF_INNO_RX_ENABLE);
[Severity: High]
Does this incorrectly modify analog PHY state during clock operations?
Since clk_set_rate() is unconditionally called during starfive_hdmi_phy_probe(),
these analog blocks are powered on immediately at boot, which could cause a
permanent power leak until the power_off callback happens to be called.
Furthermore, do these state modifications race with the PHY callbacks? The
common clock framework callbacks execute under the CCF prepare_lock, while PHY
callbacks execute under the phy->mutex lock. A concurrent clk_set_rate() and
starfive_hdmi_phy_power_on() could race on hardware registers and shared driver
state like inno->pixclock.
[ ... ]
> +static int starfive_hdmi_phy_power_on(struct phy *phy)
> +{
[ ... ]
> + inno_write(inno, STF_INNO_POST_PLL_DIV_1, reg_1aa_value);
> +
> + /* Wait for post PLL lock */
> + ret = inno_poll(inno, STF_INNO_POST_PLL_LOCK_STATUS, v,
> + v & STF_INNO_POST_PLL_LOCK, 1000, 100000);
> + if (ret) {
> + dev_err(inno->dev, "Post-PLL locking failed\n");
> + return ret;
> + }
[Severity: Medium]
Are the hardware PHY resources left powered on if the Post-PLL lock times out?
If inno_poll() fails, the function returns immediately. The PHY core framework
does not automatically call the power_off callback if the power_on callback
fails, because the power_count remains 0.
Does this error path need to explicitly undo the register writes that enabled
the BIAS, RX, and Post-PLL blocks earlier in this function?
[ ... ]
> +static int starfive_hdmi_phy_probe(struct platform_device *pdev)
> +{
[ ... ]
> + ret = clk_set_rate(inno->phyclk, 297000000);
> + if (ret) {
> + dev_err(dev, "Failed to set default rate: %d\n", ret);
> + goto err_disable_refoclk;
> + }
[ ... ]
> +err_del_clk_provider:
> + of_clk_del_provider(dev->of_node);
> +err_disable_refoclk:
> + clk_disable_unprepare(inno->refoclk);
> + return ret;
> +}
[Severity: High]
Does this error path leave a dangling clock provider in the global list?
If clk_set_rate() fails, the code jumps to err_disable_refoclk, bypassing
the required of_clk_del_provider() cleanup. The devres framework will then
unregister and free inno->phyclk, but the device node will remain in the
system-wide of_clk_providers list pointing to freed memory. Any subsequent
clock lookup could trigger a use-after-free crash.
--
Sashiko AI review · https://sashiko.dev/#/patchset/20260828-jh7110-clean-send-v2-0-331680c8b9d1@samsung.com?part=13
^ permalink raw reply [flat|nested] 116+ messages in thread
* Re: [PATCH v2 13/15] phy: starfive: Add jh7110-inno-hdmi-phy driver
@ 2026-08-28 14:04 ` sashiko-bot
0 siblings, 0 replies; 116+ messages in thread
From: sashiko-bot @ 2026-08-28 14:04 UTC (permalink / raw)
To: Michal Wilczynski
Cc: mfd, linux-phy, neil.armstrong, linux-clk, conor+dt, dri-devel,
devicetree, lee, olteanv, vkoul, robh
Thank you for your contribution! Sashiko AI review found 3 potential issue(s) to consider:
- [High] Missing cleanup on the clk_set_rate error path in probe leaves a dangling clock provider.
- [High] Clock operations incorrectly modify analog PHY state without synchronization, risking state corruption and power leaks.
- [Medium] Hardware PHY resources are left powered on if starfive_hdmi_phy_power_on() fails.
--
commit 7c46f9e86f09391b8c542e940da1457e36661874
Author: Michal Wilczynski <m.wilczynski@samsung.com>
phy: starfive: Add jh7110-inno-hdmi-phy driver
This commit adds the HDMI PHY driver for the StarFive JH7110. It provides
the variable pixel clock from the Pre-PLL and the PHY operations for the
Post-PLL and analog blocks.
> diff --git a/drivers/phy/starfive/phy-jh7110-inno-hdmi.c b/drivers/phy/starfive/phy-jh7110-inno-hdmi.c
> new file mode 100644
> --- /dev/null
> +++ b/drivers/phy/starfive/phy-jh7110-inno-hdmi.c
[ ... ]
> +static int starfive_hdmi_phy_clk_set_rate(struct clk_hw *hw, unsigned long rate,
> + unsigned long parent_rate)
> +{
[ ... ]
> + if (inno->pixclock == rate && inno->tmdsclock == cfg->tmdsclock)
> + return 0;
> +
> + inno_update_bits(inno, STF_INNO_BIAS_CONTROL,
> + STF_INNO_BIAS_ENABLE, STF_INNO_BIAS_ENABLE);
> + inno_write(inno, STF_INNO_RX_CONTROL, STF_INNO_RX_ENABLE);
[Severity: High]
Does this incorrectly modify analog PHY state during clock operations?
Since clk_set_rate() is unconditionally called during starfive_hdmi_phy_probe(),
these analog blocks are powered on immediately at boot, which could cause a
permanent power leak until the power_off callback happens to be called.
Furthermore, do these state modifications race with the PHY callbacks? The
common clock framework callbacks execute under the CCF prepare_lock, while PHY
callbacks execute under the phy->mutex lock. A concurrent clk_set_rate() and
starfive_hdmi_phy_power_on() could race on hardware registers and shared driver
state like inno->pixclock.
[ ... ]
> +static int starfive_hdmi_phy_power_on(struct phy *phy)
> +{
[ ... ]
> + inno_write(inno, STF_INNO_POST_PLL_DIV_1, reg_1aa_value);
> +
> + /* Wait for post PLL lock */
> + ret = inno_poll(inno, STF_INNO_POST_PLL_LOCK_STATUS, v,
> + v & STF_INNO_POST_PLL_LOCK, 1000, 100000);
> + if (ret) {
> + dev_err(inno->dev, "Post-PLL locking failed\n");
> + return ret;
> + }
[Severity: Medium]
Are the hardware PHY resources left powered on if the Post-PLL lock times out?
If inno_poll() fails, the function returns immediately. The PHY core framework
does not automatically call the power_off callback if the power_on callback
fails, because the power_count remains 0.
Does this error path need to explicitly undo the register writes that enabled
the BIAS, RX, and Post-PLL blocks earlier in this function?
[ ... ]
> +static int starfive_hdmi_phy_probe(struct platform_device *pdev)
> +{
[ ... ]
> + ret = clk_set_rate(inno->phyclk, 297000000);
> + if (ret) {
> + dev_err(dev, "Failed to set default rate: %d\n", ret);
> + goto err_disable_refoclk;
> + }
[ ... ]
> +err_del_clk_provider:
> + of_clk_del_provider(dev->of_node);
> +err_disable_refoclk:
> + clk_disable_unprepare(inno->refoclk);
> + return ret;
> +}
[Severity: High]
Does this error path leave a dangling clock provider in the global list?
If clk_set_rate() fails, the code jumps to err_disable_refoclk, bypassing
the required of_clk_del_provider() cleanup. The devres framework will then
unregister and free inno->phyclk, but the device node will remain in the
system-wide of_clk_providers list pointing to freed memory. Any subsequent
clock lookup could trigger a use-after-free crash.
--
Sashiko AI review · https://sashiko.dev/#/patchset/20260828-jh7110-clean-send-v2-0-331680c8b9d1@samsung.com?part=13
--
linux-phy mailing list
linux-phy@lists.infradead.org
https://lists.infradead.org/mailman/listinfo/linux-phy
^ permalink raw reply [flat|nested] 116+ messages in thread
* Re: [PATCH v2 14/15] riscv: dts: starfive: jh7110: Update DT for display subsystem
2026-08-28 13:47 ` Michal Wilczynski
@ 2026-08-28 14:06 ` sashiko-bot
-1 siblings, 0 replies; 116+ messages in thread
From: sashiko-bot @ 2026-08-28 14:06 UTC (permalink / raw)
To: Michal Wilczynski
Cc: devicetree, conor+dt, linux-phy, robh, lee, olteanv, dri-devel,
vkoul, linux-clk, neil.armstrong, mfd
Thank you for your contribution! Sashiko AI review found 4 potential issue(s) to consider:
- [High] Hardcoded exact physical address range for CMA reservation restricts memory allocation and breaks smaller RAM variants.
- [High] The commit claims genpd powers the PD_VOUT domain on demand, but this is functionally impossible due to missing PM runtime integration in the HDMI subsystem driver.
- [Low] Duplicate 24MHz fixed-clock node introduced for `hdmi_phy`.
- [Low] The `dc8200` node provides only `"verisilicon,dc"` in its `compatible` string, which violates the `verisilicon,dc.yaml` binding schema.
--
commit d117ce22b6b03137e7ca5305371a65afdcd406c9
Author: Michal Wilczynski <m.wilczynski@samsung.com>
riscv: dts: starfive: jh7110: Update DT for display subsystem
This commit activates the display subsystem by adding the dc8200, hdmi, and
voutcrg nodes as direct soc children. It models the monolithic hdmi node as
a container with hdmi_phy and hdmi_controller children. It also configures
clock, DMA properties, and CMA reservations.
> diff --git a/arch/riscv/boot/dts/starfive/jh7110-common.dtsi b/arch/riscv/boot/dts/starfive/jh7110-common.dtsi
> index a7a1c09a2c907..7aadc35f4a6aa 100644
> --- a/arch/riscv/boot/dts/starfive/jh7110-common.dtsi
> +++ b/arch/riscv/boot/dts/starfive/jh7110-common.dtsi
> @@ -33,6 +33,25 @@ memory@40000000 {
> bootph-pre-ram;
> };
>
> + reserved-memory {
> + #address-cells = <2>;
> + #size-cells = <2>;
> + ranges;
> +
> + /* vout applies for space from this CMA
> + * Without this CMA reservation,
> + * vout may not work properly.
> + */
> + linux,cma {
> + compatible = "shared-dma-pool";
> + reusable;
> + size = <0x0 0x20000000>;
> + alignment = <0x0 0x1000>;
> + alloc-ranges = <0x0 0x70000000 0x0 0x20000000>;
> + linux,cma-default;
[Severity: High]
Could this alloc-ranges configuration break boot on systems with less
memory or conflicting bootloader placements?
The property alloc-ranges = <0x0 0x70000000 0x0 0x20000000> combined with
size = <0x0 0x20000000> forces the 512MB CMA pool exactly at physical address
0x70000000.
On a board with only 1GB of RAM (ranging from 0x40000000 to 0x80000000),
the top 256MB of this requested region falls completely outside of physical
memory, which would guarantee an allocation failure.
Additionally, if a bootloader dynamically places the DTB or initrd anywhere
within this narrow 512MB slice, CMA reservation will conflict and silently
fail.
> + };
> + };
> +
[ ... ]
> diff --git a/arch/riscv/boot/dts/starfive/jh7110.dtsi b/arch/riscv/boot/dts/starfive/jh7110.dtsi
> index 9c3e4598747eb..024e33b0e97cb 100644
> --- a/arch/riscv/boot/dts/starfive/jh7110.dtsi
> +++ b/arch/riscv/boot/dts/starfive/jh7110.dtsi
[ ... ]
> @@ -352,6 +346,13 @@ tdm_ext: tdm-ext-clock {
> #clock-cells = <0>;
> };
>
> + xin24m: xin24m {
> + compatible = "fixed-clock";
> + #clock-cells = <0>;
> + clock-frequency = <24000000>;
> + clock-output-names = "xin24m";
> + };
> +
[Severity: Low]
Does this introduce a redundant clock definition?
The jh7110.dtsi and jh7110-common.dtsi files already define an osc clock
node representing the 24MHz physical oscillator on the board. Introducing a
new xin24m fixed-clock node with the exact same 24MHz frequency seems
redundant and creates a hardware modeling flaw in the Device Tree.
Should the hdmi_phy node reference the existing <&osc> clock instead?
> soc {
> compatible = "simple-bus";
> interrupt-parent = <&plic>;
> @@ -1199,22 +1200,92 @@ csi_phy: phy@19820000 {
> #phy-cells = <0>;
> };
>
> + dc8200: display@29400000 {
> + compatible = "verisilicon,dc";
[Severity: Low]
Is this missing the SoC-specific compatible string required by the binding
schema?
The verisilicon,dc.yaml schema requires the compatible property to be an
array of two items: an SoC-specific string (e.g., thead,th1520-dc8200 or
starfive,jh7110-dc8200) followed by verisilicon,dc.
Specifying only compatible = "verisilicon,dc" violates the standard rule for
IP block instances and will cause dtbs_check validation to fail.
> + reg = <0x0 0x29400000 0x0 0x2800>;
[ ... ]
> + hdmi_subsystem: hdmi@29590000 {
> + compatible = "starfive,jh7110-hdmi-subsystem";
> + reg = <0x0 0x29590000 0x0 0x4000>;
> +
> + /*
> + * This MFD's PHY child is the first device in the vout
> + * region to touch registers, so it owns the NoC display
> + * bus clock + reset that gate access to the region.
> + * PD_VOUT is powered on by genpd via power-domains.
> + */
> + power-domains = <&pwrc JH7110_PD_VOUT>;
[Severity: High]
Is the claim that genpd powers this domain on demand functionally possible
without PM runtime integration in the HDMI subsystem driver?
The commit message states "genpd powers the domain on demand", and the
hdmi_subsystem node relies on this for PD_VOUT. However, the driver in
drivers/soc/starfive/jh7110-hdmi-subsystem.c does not appear to call
pm_runtime_enable().
Because the container has PM runtime disabled, any pm_runtime_get_sync()
calls from its children will return -EACCES and fail to propagate to genpd.
The hardware appears to only work because the voutcrg clock controller
driver unconditionally calls pm_runtime_resume_and_get() in its probe
function without releasing it. This forcefully pins the PD_VOUT domain ON
indefinitely, which circumvents the on-demand power management expectation.
--
Sashiko AI review · https://sashiko.dev/#/patchset/20260828-jh7110-clean-send-v2-0-331680c8b9d1@samsung.com?part=14
^ permalink raw reply [flat|nested] 116+ messages in thread
* Re: [PATCH v2 14/15] riscv: dts: starfive: jh7110: Update DT for display subsystem
@ 2026-08-28 14:06 ` sashiko-bot
0 siblings, 0 replies; 116+ messages in thread
From: sashiko-bot @ 2026-08-28 14:06 UTC (permalink / raw)
To: Michal Wilczynski
Cc: devicetree, conor+dt, linux-phy, robh, lee, olteanv, dri-devel,
vkoul, linux-clk, neil.armstrong, mfd
Thank you for your contribution! Sashiko AI review found 4 potential issue(s) to consider:
- [High] Hardcoded exact physical address range for CMA reservation restricts memory allocation and breaks smaller RAM variants.
- [High] The commit claims genpd powers the PD_VOUT domain on demand, but this is functionally impossible due to missing PM runtime integration in the HDMI subsystem driver.
- [Low] Duplicate 24MHz fixed-clock node introduced for `hdmi_phy`.
- [Low] The `dc8200` node provides only `"verisilicon,dc"` in its `compatible` string, which violates the `verisilicon,dc.yaml` binding schema.
--
commit d117ce22b6b03137e7ca5305371a65afdcd406c9
Author: Michal Wilczynski <m.wilczynski@samsung.com>
riscv: dts: starfive: jh7110: Update DT for display subsystem
This commit activates the display subsystem by adding the dc8200, hdmi, and
voutcrg nodes as direct soc children. It models the monolithic hdmi node as
a container with hdmi_phy and hdmi_controller children. It also configures
clock, DMA properties, and CMA reservations.
> diff --git a/arch/riscv/boot/dts/starfive/jh7110-common.dtsi b/arch/riscv/boot/dts/starfive/jh7110-common.dtsi
> index a7a1c09a2c907..7aadc35f4a6aa 100644
> --- a/arch/riscv/boot/dts/starfive/jh7110-common.dtsi
> +++ b/arch/riscv/boot/dts/starfive/jh7110-common.dtsi
> @@ -33,6 +33,25 @@ memory@40000000 {
> bootph-pre-ram;
> };
>
> + reserved-memory {
> + #address-cells = <2>;
> + #size-cells = <2>;
> + ranges;
> +
> + /* vout applies for space from this CMA
> + * Without this CMA reservation,
> + * vout may not work properly.
> + */
> + linux,cma {
> + compatible = "shared-dma-pool";
> + reusable;
> + size = <0x0 0x20000000>;
> + alignment = <0x0 0x1000>;
> + alloc-ranges = <0x0 0x70000000 0x0 0x20000000>;
> + linux,cma-default;
[Severity: High]
Could this alloc-ranges configuration break boot on systems with less
memory or conflicting bootloader placements?
The property alloc-ranges = <0x0 0x70000000 0x0 0x20000000> combined with
size = <0x0 0x20000000> forces the 512MB CMA pool exactly at physical address
0x70000000.
On a board with only 1GB of RAM (ranging from 0x40000000 to 0x80000000),
the top 256MB of this requested region falls completely outside of physical
memory, which would guarantee an allocation failure.
Additionally, if a bootloader dynamically places the DTB or initrd anywhere
within this narrow 512MB slice, CMA reservation will conflict and silently
fail.
> + };
> + };
> +
[ ... ]
> diff --git a/arch/riscv/boot/dts/starfive/jh7110.dtsi b/arch/riscv/boot/dts/starfive/jh7110.dtsi
> index 9c3e4598747eb..024e33b0e97cb 100644
> --- a/arch/riscv/boot/dts/starfive/jh7110.dtsi
> +++ b/arch/riscv/boot/dts/starfive/jh7110.dtsi
[ ... ]
> @@ -352,6 +346,13 @@ tdm_ext: tdm-ext-clock {
> #clock-cells = <0>;
> };
>
> + xin24m: xin24m {
> + compatible = "fixed-clock";
> + #clock-cells = <0>;
> + clock-frequency = <24000000>;
> + clock-output-names = "xin24m";
> + };
> +
[Severity: Low]
Does this introduce a redundant clock definition?
The jh7110.dtsi and jh7110-common.dtsi files already define an osc clock
node representing the 24MHz physical oscillator on the board. Introducing a
new xin24m fixed-clock node with the exact same 24MHz frequency seems
redundant and creates a hardware modeling flaw in the Device Tree.
Should the hdmi_phy node reference the existing <&osc> clock instead?
> soc {
> compatible = "simple-bus";
> interrupt-parent = <&plic>;
> @@ -1199,22 +1200,92 @@ csi_phy: phy@19820000 {
> #phy-cells = <0>;
> };
>
> + dc8200: display@29400000 {
> + compatible = "verisilicon,dc";
[Severity: Low]
Is this missing the SoC-specific compatible string required by the binding
schema?
The verisilicon,dc.yaml schema requires the compatible property to be an
array of two items: an SoC-specific string (e.g., thead,th1520-dc8200 or
starfive,jh7110-dc8200) followed by verisilicon,dc.
Specifying only compatible = "verisilicon,dc" violates the standard rule for
IP block instances and will cause dtbs_check validation to fail.
> + reg = <0x0 0x29400000 0x0 0x2800>;
[ ... ]
> + hdmi_subsystem: hdmi@29590000 {
> + compatible = "starfive,jh7110-hdmi-subsystem";
> + reg = <0x0 0x29590000 0x0 0x4000>;
> +
> + /*
> + * This MFD's PHY child is the first device in the vout
> + * region to touch registers, so it owns the NoC display
> + * bus clock + reset that gate access to the region.
> + * PD_VOUT is powered on by genpd via power-domains.
> + */
> + power-domains = <&pwrc JH7110_PD_VOUT>;
[Severity: High]
Is the claim that genpd powers this domain on demand functionally possible
without PM runtime integration in the HDMI subsystem driver?
The commit message states "genpd powers the domain on demand", and the
hdmi_subsystem node relies on this for PD_VOUT. However, the driver in
drivers/soc/starfive/jh7110-hdmi-subsystem.c does not appear to call
pm_runtime_enable().
Because the container has PM runtime disabled, any pm_runtime_get_sync()
calls from its children will return -EACCES and fail to propagate to genpd.
The hardware appears to only work because the voutcrg clock controller
driver unconditionally calls pm_runtime_resume_and_get() in its probe
function without releasing it. This forcefully pins the PD_VOUT domain ON
indefinitely, which circumvents the on-demand power management expectation.
--
Sashiko AI review · https://sashiko.dev/#/patchset/20260828-jh7110-clean-send-v2-0-331680c8b9d1@samsung.com?part=14
--
linux-phy mailing list
linux-phy@lists.infradead.org
https://lists.infradead.org/mailman/listinfo/linux-phy
^ permalink raw reply [flat|nested] 116+ messages in thread
* Re: [PATCH v2 14/15] riscv: dts: starfive: jh7110: Update DT for display subsystem
2026-08-28 13:47 ` Michal Wilczynski
(?)
(?)
@ 2026-08-28 14:06 ` Icenowy Zheng
-1 siblings, 0 replies; 116+ messages in thread
From: Icenowy Zheng @ 2026-08-28 14:06 UTC (permalink / raw)
To: Michal Wilczynski, Vinod Koul, Neil Armstrong, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, Andrzej Hajda, Robert Foss,
Laurent Pinchart, Jonas Karlman, Jernej Skrabec, Luca Ceresoli,
David Airlie, Simona Vetter, Maarten Lankhorst, Maxime Ripard,
Thomas Zimmermann, Lee Jones, Andy Yan, Philipp Zabel,
Emil Renner Berthing, Hal Feng, Michael Turquette, Stephen Boyd,
Brian Masney, Heiko Stuebner, Conor Dooley, Paul Walmsley,
Palmer Dabbelt, Albert Ou, Alexandre Ghiti, Dominique Belhachemi
Cc: linux-phy, devicetree, linux-kernel, dri-devel, mfd, linux-clk,
linux-arm-kernel, linux-rockchip, linux-riscv, Andy Yan,
Marek Szyprowski, Maud Spierings, Graham Markall
在 2026-08-28五的 15:47 +0200,Michal Wilczynski写道:
> Activate the display subsystem by adding the dc8200, hdmi and voutcrg
> nodes as direct soc children. Each references the PD_VOUT power
> domain
> through power-domains, so genpd powers the domain on demand, and the
> HDMI-PHY -> voutcrg -> HDMI-controller probe order is resolved by
> deferred probe.
>
> The monolithic hdmi node is modelled as a container with hdmi_phy
> and hdmi_controller children. This lets the PHY (clock provider,
> depending only on xin24m) and the controller (clock consumer) probe
> independently, breaking the circular clock dependency with voutcrg.
>
> voutcrg consumes the pixel clock from the &hdmi_phy node instead of
> the
> old fixed-clock, and dc8200 gets its pixel clocks from voutcrg's
> MUXes
> and is marked dma-noncoherent for framebuffer DMA. The old, incorrect
> hdmitx0-pixel-clock fixed-clock node is removed.
>
> Co-developed-by: Dominique Belhachemi <db@domibel.de>
> Signed-off-by: Dominique Belhachemi <db@domibel.de>
> Signed-off-by: Michal Wilczynski <m.wilczynski@samsung.com>
> ---
> arch/riscv/boot/dts/starfive/jh7110-common.dtsi | 119
> +++++++++++++++++++++++-
> arch/riscv/boot/dts/starfive/jh7110.dtsi | 87
> +++++++++++++++--
> 2 files changed, 196 insertions(+), 10 deletions(-)
>
> diff --git a/arch/riscv/boot/dts/starfive/jh7110-common.dtsi
> b/arch/riscv/boot/dts/starfive/jh7110-common.dtsi
> index
> a7a1c09a2c9075711f3a214a49618911fdc7b421..7aadc35f4a6aa724c86a868ef65
> c5c829e666ee2 100644
> --- a/arch/riscv/boot/dts/starfive/jh7110-common.dtsi
> +++ b/arch/riscv/boot/dts/starfive/jh7110-common.dtsi
> @@ -33,6 +33,25 @@ memory@40000000 {
> bootph-pre-ram;
> };
>
> + reserved-memory {
> + #address-cells = <2>;
> + #size-cells = <2>;
> + ranges;
> +
> + /* vout applies for space from this CMA
> + * Without this CMA reservation,
> + * vout may not work properly.
> + */
> + linux,cma {
> + compatible = "shared-dma-pool";
> + reusable;
> + size = <0x0 0x20000000>;
> + alignment = <0x0 0x1000>;
> + alloc-ranges = <0x0 0x70000000 0x0
> 0x20000000>;
> + linux,cma-default;
> + };
> + };
> +
> gpio-restart {
> compatible = "gpio-restart";
> gpios = <&sysgpio 35 GPIO_ACTIVE_HIGH>;
> @@ -73,12 +92,47 @@ codec {
> };
> };
> };
> +
> + hdmi-connector {
> + compatible = "hdmi-connector";
> + type = "a";
> +
> + port {
> + hdmi_con_in: endpoint {
> + remote-endpoint = <&hdmi_out_con>;
> + };
> + };
> + };
> };
>
> &cpus {
> timebase-frequency = <4000000>;
> };
>
> +&dc8200 {
> + status = "okay";
> +
> + ports {
> + #address-cells = <1>;
> + #size-cells = <0>;
> +
> + dpu_port0: port@0 {
> + reg = <0>;
> + #address-cells = <1>;
> + #size-cells = <0>;
> +
> + dpu_out_dpi0: endpoint@0 {
> + reg = <0>;
> + remote-endpoint = <&hdmi_in>;
> + };
> + };
> +
> + dpu_port1: port@1 {
> + reg = <1>;
> + };
> + };
> +};
> +
> &dvp_clk {
> clock-frequency = <74250000>;
> };
> @@ -99,8 +153,31 @@ &gmac1_rmii_refin {
> clock-frequency = <50000000>;
> };
>
> -&hdmitx0_pixelclk {
> - clock-frequency = <297000000>;
> +&hdmi_controller {
> + status = "okay";
> + pinctrl-names = "default";
> + pinctrl-0 = <&hdmi_pins>;
> +
> + ports {
> + #address-cells = <1>;
> + #size-cells = <0>;
> +
> + port@0 {
> + reg = <0>;
> +
> + hdmi_in: endpoint {
> + remote-endpoint = <&dpu_out_dpi0>;
> + };
> + };
> +
> + hdmi_out_port: port@1 {
> + reg = <1>;
> + hdmi_out_con: endpoint {
> + remote-endpoint = <&hdmi_con_in>;
> + };
> +
> + };
> + };
> };
>
> &i2srx_bclk_ext {
> @@ -351,6 +428,40 @@ &syscrg {
> };
>
> &sysgpio {
> + hdmi_pins: hdmi-0 {
> + hdmi-cec-pins {
> + pinmux = <GPIOMUX(14,
> GPOUT_SYS_HDMI_CEC_SDA,
> +
> GPOEN_SYS_HDMI_CEC_SDA,
> +
> GPI_SYS_HDMI_CEC_SDA)>;
> + input-enable;
> + bias-pull-up;
> + };
> +
> + hdmi-hpd-pins {
> + pinmux = <GPIOMUX(15, GPOUT_HIGH,
> + GPOEN_ENABLE,
> + GPI_SYS_HDMI_HPD)>;
> + input-enable;
> + bias-disable; /* external pull-up */
> + };
> +
> + hdmi-scl-pins {
> + pinmux = <GPIOMUX(0, GPOUT_SYS_HDMI_DDC_SCL,
> + GPOEN_SYS_HDMI_DDC_SCL,
> + GPI_SYS_HDMI_DDC_SCL)>;
> + input-enable;
> + bias-pull-up;
> + };
> +
> + hdmi-sda-pins {
> + pinmux = <GPIOMUX(1, GPOUT_SYS_HDMI_DDC_SDA,
> + GPOEN_SYS_HDMI_DDC_SDA,
> + GPI_SYS_HDMI_DDC_SDA)>;
> + input-enable;
> + bias-pull-up;
> + };
> + };
> +
> i2c0_pins: i2c0-0 {
> i2c-pins {
> pinmux = <GPIOMUX(57, GPOUT_LOW,
> @@ -629,3 +740,7 @@ &U74_3 {
> &U74_4 {
> cpu-supply = <&vdd_cpu>;
> };
> +
> +&voutcrg {
> + status = "okay";
> +};
> diff --git a/arch/riscv/boot/dts/starfive/jh7110.dtsi
> b/arch/riscv/boot/dts/starfive/jh7110.dtsi
> index
> 9c3e4598747eb5541effe697044484715569a285..024e33b0e97cb13928d69d1d809
> 0ed14d22bb022 100644
> --- a/arch/riscv/boot/dts/starfive/jh7110.dtsi
> +++ b/arch/riscv/boot/dts/starfive/jh7110.dtsi
> @@ -290,12 +290,6 @@ gmac1_rmii_refin: gmac1-rmii-refin-clock {
> #clock-cells = <0>;
> };
>
> - hdmitx0_pixelclk: hdmitx0-pixel-clock {
> - compatible = "fixed-clock";
> - clock-output-names = "hdmitx0_pixelclk";
> - #clock-cells = <0>;
> - };
> -
> i2srx_bclk_ext: i2srx-bclk-ext-clock {
> compatible = "fixed-clock";
> clock-output-names = "i2srx_bclk_ext";
> @@ -352,6 +346,13 @@ tdm_ext: tdm-ext-clock {
> #clock-cells = <0>;
> };
>
> + xin24m: xin24m {
> + compatible = "fixed-clock";
> + #clock-cells = <0>;
> + clock-frequency = <24000000>;
> + clock-output-names = "xin24m";
> + };
> +
> soc {
> compatible = "simple-bus";
> interrupt-parent = <&plic>;
> @@ -1199,22 +1200,92 @@ csi_phy: phy@19820000 {
> #phy-cells = <0>;
> };
>
> + dc8200: display@29400000 {
> + compatible = "verisilicon,dc";
> + reg = <0x0 0x29400000 0x0 0x2800>;
> + interrupts = <95>;
> + dma-noncoherent;
> +
> + power-domains = <&pwrc JH7110_PD_VOUT>;
> +
> + clocks = <&voutcrg
> JH7110_VOUTCLK_DC8200_CORE>,
> + <&voutcrg
> JH7110_VOUTCLK_DC8200_AXI>,
> + <&voutcrg
> JH7110_VOUTCLK_DC8200_AHB>,
> + <&voutcrg
> JH7110_VOUTCLK_DC8200_PIX0>,
> + <&voutcrg
> JH7110_VOUTCLK_DC8200_PIX1>;
> + clock-names = "core", "axi", "ahb", "pix0",
> "pix1";
> +
> + resets = <&voutcrg
> JH7110_VOUTRST_DC8200_CORE>,
> + <&voutcrg
> JH7110_VOUTRST_DC8200_AXI>,
> + <&voutcrg
> JH7110_VOUTRST_DC8200_AHB>;
> + reset-names = "core", "axi", "ahb";
> + };
> +
> + hdmi_subsystem: hdmi@29590000 {
> + compatible = "starfive,jh7110-hdmi-
> subsystem";
> + reg = <0x0 0x29590000 0x0 0x4000>;
> +
> + /*
> + * This MFD's PHY child is the first device
> in the vout
> + * region to touch registers, so it owns the
> NoC display
> + * bus clock + reset that gate access to the
> region.
> + * PD_VOUT is powered on by genpd via power-
> domains.
> + */
> + power-domains = <&pwrc JH7110_PD_VOUT>;
> + clocks = <&syscrg
> JH7110_SYSCLK_NOC_BUS_DISP_AXI>;
> + resets = <&syscrg
> JH7110_SYSRST_NOC_BUS_DISP_AXI>;
I think the NOC clocks/resets should be also needed by the DC8200
either?
Although patching the DC8200 driver to add support for these
clocks/resets looks a little dirty...
Maybe it's still good to have a vout subsys instead of a hdmi subsys...
Thanks,
Icenowy
> +
> + hdmi_phy: phy {
> + compatible = "starfive,jh7110-inno-
> hdmi-phy";
> +
> + clocks = <&xin24m>;
> + clock-names = "refoclk";
> +
> + /* Output clock: The variable pixel
> clock */
> + #clock-cells = <0>;
> + clock-output-names = "hdmi_pclk";
> +
> + /* PHY provider for the controller
> */
> + #phy-cells = <0>;
> + };
> +
> + hdmi_controller: controller {
> + compatible = "starfive,jh7110-inno-
> hdmi-controller";
> + interrupts = <99>;
> +
> + clocks = <&voutcrg
> JH7110_VOUTCLK_HDMI_TX_SYS>,
> + <&voutcrg
> JH7110_VOUTCLK_HDMI_TX_MCLK>,
> + <&voutcrg
> JH7110_VOUTCLK_HDMI_TX_BCLK>,
> + <&hdmi_phy>;
> + clock-names = "sys", "mclk", "bclk",
> "pclk";
> +
> + resets = <&voutcrg
> JH7110_VOUTRST_HDMI_TX_HDMI>;
> + reset-names = "hdmi_tx";
> +
> + phys = <&hdmi_phy>;
> + phy-names = "hdmi-phy";
> + };
> + };
> +
> voutcrg: clock-controller@295c0000 {
> compatible = "starfive,jh7110-voutcrg";
> reg = <0x0 0x295c0000 0x0 0x10000>;
> +
> + power-domains = <&pwrc JH7110_PD_VOUT>;
> +
> clocks = <&syscrg JH7110_SYSCLK_VOUT_SRC>,
> <&syscrg
> JH7110_SYSCLK_VOUT_TOP_AHB>,
> <&syscrg
> JH7110_SYSCLK_VOUT_TOP_AXI>,
> <&syscrg
> JH7110_SYSCLK_VOUT_TOP_HDMITX0_MCLK>,
> <&syscrg
> JH7110_SYSCLK_I2STX0_BCLK>,
> - <&hdmitx0_pixelclk>;
> + <&hdmi_phy>;
> clock-names = "vout_src", "vout_top_ahb",
> "vout_top_axi",
> "vout_top_hdmitx0_mclk",
> "i2stx0_bclk",
> "hdmitx0_pixelclk";
> +
> resets = <&syscrg
> JH7110_SYSRST_VOUT_TOP_SRC>;
> #clock-cells = <1>;
> #reset-cells = <1>;
> - power-domains = <&pwrc JH7110_PD_VOUT>;
> };
>
> pcie0: pcie@940000000 {
^ permalink raw reply [flat|nested] 116+ messages in thread
* Re: [PATCH v2 14/15] riscv: dts: starfive: jh7110: Update DT for display subsystem
@ 2026-08-28 14:06 ` Icenowy Zheng
0 siblings, 0 replies; 116+ messages in thread
From: Icenowy Zheng @ 2026-08-28 14:06 UTC (permalink / raw)
To: Michal Wilczynski, Vinod Koul, Neil Armstrong, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, Andrzej Hajda, Robert Foss,
Laurent Pinchart, Jonas Karlman, Jernej Skrabec, Luca Ceresoli,
David Airlie, Simona Vetter, Maarten Lankhorst, Maxime Ripard,
Thomas Zimmermann, Lee Jones, Andy Yan, Philipp Zabel,
Emil Renner Berthing, Hal Feng, Michael Turquette, Stephen Boyd,
Brian Masney, Heiko Stuebner, Conor Dooley, Paul Walmsley,
Palmer Dabbelt, Albert Ou, Alexandre Ghiti, Dominique Belhachemi
Cc: linux-phy, devicetree, linux-kernel, dri-devel, mfd, linux-clk,
linux-arm-kernel, linux-rockchip, linux-riscv, Andy Yan,
Marek Szyprowski, Maud Spierings, Graham Markall
在 2026-08-28五的 15:47 +0200,Michal Wilczynski写道:
> Activate the display subsystem by adding the dc8200, hdmi and voutcrg
> nodes as direct soc children. Each references the PD_VOUT power
> domain
> through power-domains, so genpd powers the domain on demand, and the
> HDMI-PHY -> voutcrg -> HDMI-controller probe order is resolved by
> deferred probe.
>
> The monolithic hdmi node is modelled as a container with hdmi_phy
> and hdmi_controller children. This lets the PHY (clock provider,
> depending only on xin24m) and the controller (clock consumer) probe
> independently, breaking the circular clock dependency with voutcrg.
>
> voutcrg consumes the pixel clock from the &hdmi_phy node instead of
> the
> old fixed-clock, and dc8200 gets its pixel clocks from voutcrg's
> MUXes
> and is marked dma-noncoherent for framebuffer DMA. The old, incorrect
> hdmitx0-pixel-clock fixed-clock node is removed.
>
> Co-developed-by: Dominique Belhachemi <db@domibel.de>
> Signed-off-by: Dominique Belhachemi <db@domibel.de>
> Signed-off-by: Michal Wilczynski <m.wilczynski@samsung.com>
> ---
> arch/riscv/boot/dts/starfive/jh7110-common.dtsi | 119
> +++++++++++++++++++++++-
> arch/riscv/boot/dts/starfive/jh7110.dtsi | 87
> +++++++++++++++--
> 2 files changed, 196 insertions(+), 10 deletions(-)
>
> diff --git a/arch/riscv/boot/dts/starfive/jh7110-common.dtsi
> b/arch/riscv/boot/dts/starfive/jh7110-common.dtsi
> index
> a7a1c09a2c9075711f3a214a49618911fdc7b421..7aadc35f4a6aa724c86a868ef65
> c5c829e666ee2 100644
> --- a/arch/riscv/boot/dts/starfive/jh7110-common.dtsi
> +++ b/arch/riscv/boot/dts/starfive/jh7110-common.dtsi
> @@ -33,6 +33,25 @@ memory@40000000 {
> bootph-pre-ram;
> };
>
> + reserved-memory {
> + #address-cells = <2>;
> + #size-cells = <2>;
> + ranges;
> +
> + /* vout applies for space from this CMA
> + * Without this CMA reservation,
> + * vout may not work properly.
> + */
> + linux,cma {
> + compatible = "shared-dma-pool";
> + reusable;
> + size = <0x0 0x20000000>;
> + alignment = <0x0 0x1000>;
> + alloc-ranges = <0x0 0x70000000 0x0
> 0x20000000>;
> + linux,cma-default;
> + };
> + };
> +
> gpio-restart {
> compatible = "gpio-restart";
> gpios = <&sysgpio 35 GPIO_ACTIVE_HIGH>;
> @@ -73,12 +92,47 @@ codec {
> };
> };
> };
> +
> + hdmi-connector {
> + compatible = "hdmi-connector";
> + type = "a";
> +
> + port {
> + hdmi_con_in: endpoint {
> + remote-endpoint = <&hdmi_out_con>;
> + };
> + };
> + };
> };
>
> &cpus {
> timebase-frequency = <4000000>;
> };
>
> +&dc8200 {
> + status = "okay";
> +
> + ports {
> + #address-cells = <1>;
> + #size-cells = <0>;
> +
> + dpu_port0: port@0 {
> + reg = <0>;
> + #address-cells = <1>;
> + #size-cells = <0>;
> +
> + dpu_out_dpi0: endpoint@0 {
> + reg = <0>;
> + remote-endpoint = <&hdmi_in>;
> + };
> + };
> +
> + dpu_port1: port@1 {
> + reg = <1>;
> + };
> + };
> +};
> +
> &dvp_clk {
> clock-frequency = <74250000>;
> };
> @@ -99,8 +153,31 @@ &gmac1_rmii_refin {
> clock-frequency = <50000000>;
> };
>
> -&hdmitx0_pixelclk {
> - clock-frequency = <297000000>;
> +&hdmi_controller {
> + status = "okay";
> + pinctrl-names = "default";
> + pinctrl-0 = <&hdmi_pins>;
> +
> + ports {
> + #address-cells = <1>;
> + #size-cells = <0>;
> +
> + port@0 {
> + reg = <0>;
> +
> + hdmi_in: endpoint {
> + remote-endpoint = <&dpu_out_dpi0>;
> + };
> + };
> +
> + hdmi_out_port: port@1 {
> + reg = <1>;
> + hdmi_out_con: endpoint {
> + remote-endpoint = <&hdmi_con_in>;
> + };
> +
> + };
> + };
> };
>
> &i2srx_bclk_ext {
> @@ -351,6 +428,40 @@ &syscrg {
> };
>
> &sysgpio {
> + hdmi_pins: hdmi-0 {
> + hdmi-cec-pins {
> + pinmux = <GPIOMUX(14,
> GPOUT_SYS_HDMI_CEC_SDA,
> +
> GPOEN_SYS_HDMI_CEC_SDA,
> +
> GPI_SYS_HDMI_CEC_SDA)>;
> + input-enable;
> + bias-pull-up;
> + };
> +
> + hdmi-hpd-pins {
> + pinmux = <GPIOMUX(15, GPOUT_HIGH,
> + GPOEN_ENABLE,
> + GPI_SYS_HDMI_HPD)>;
> + input-enable;
> + bias-disable; /* external pull-up */
> + };
> +
> + hdmi-scl-pins {
> + pinmux = <GPIOMUX(0, GPOUT_SYS_HDMI_DDC_SCL,
> + GPOEN_SYS_HDMI_DDC_SCL,
> + GPI_SYS_HDMI_DDC_SCL)>;
> + input-enable;
> + bias-pull-up;
> + };
> +
> + hdmi-sda-pins {
> + pinmux = <GPIOMUX(1, GPOUT_SYS_HDMI_DDC_SDA,
> + GPOEN_SYS_HDMI_DDC_SDA,
> + GPI_SYS_HDMI_DDC_SDA)>;
> + input-enable;
> + bias-pull-up;
> + };
> + };
> +
> i2c0_pins: i2c0-0 {
> i2c-pins {
> pinmux = <GPIOMUX(57, GPOUT_LOW,
> @@ -629,3 +740,7 @@ &U74_3 {
> &U74_4 {
> cpu-supply = <&vdd_cpu>;
> };
> +
> +&voutcrg {
> + status = "okay";
> +};
> diff --git a/arch/riscv/boot/dts/starfive/jh7110.dtsi
> b/arch/riscv/boot/dts/starfive/jh7110.dtsi
> index
> 9c3e4598747eb5541effe697044484715569a285..024e33b0e97cb13928d69d1d809
> 0ed14d22bb022 100644
> --- a/arch/riscv/boot/dts/starfive/jh7110.dtsi
> +++ b/arch/riscv/boot/dts/starfive/jh7110.dtsi
> @@ -290,12 +290,6 @@ gmac1_rmii_refin: gmac1-rmii-refin-clock {
> #clock-cells = <0>;
> };
>
> - hdmitx0_pixelclk: hdmitx0-pixel-clock {
> - compatible = "fixed-clock";
> - clock-output-names = "hdmitx0_pixelclk";
> - #clock-cells = <0>;
> - };
> -
> i2srx_bclk_ext: i2srx-bclk-ext-clock {
> compatible = "fixed-clock";
> clock-output-names = "i2srx_bclk_ext";
> @@ -352,6 +346,13 @@ tdm_ext: tdm-ext-clock {
> #clock-cells = <0>;
> };
>
> + xin24m: xin24m {
> + compatible = "fixed-clock";
> + #clock-cells = <0>;
> + clock-frequency = <24000000>;
> + clock-output-names = "xin24m";
> + };
> +
> soc {
> compatible = "simple-bus";
> interrupt-parent = <&plic>;
> @@ -1199,22 +1200,92 @@ csi_phy: phy@19820000 {
> #phy-cells = <0>;
> };
>
> + dc8200: display@29400000 {
> + compatible = "verisilicon,dc";
> + reg = <0x0 0x29400000 0x0 0x2800>;
> + interrupts = <95>;
> + dma-noncoherent;
> +
> + power-domains = <&pwrc JH7110_PD_VOUT>;
> +
> + clocks = <&voutcrg
> JH7110_VOUTCLK_DC8200_CORE>,
> + <&voutcrg
> JH7110_VOUTCLK_DC8200_AXI>,
> + <&voutcrg
> JH7110_VOUTCLK_DC8200_AHB>,
> + <&voutcrg
> JH7110_VOUTCLK_DC8200_PIX0>,
> + <&voutcrg
> JH7110_VOUTCLK_DC8200_PIX1>;
> + clock-names = "core", "axi", "ahb", "pix0",
> "pix1";
> +
> + resets = <&voutcrg
> JH7110_VOUTRST_DC8200_CORE>,
> + <&voutcrg
> JH7110_VOUTRST_DC8200_AXI>,
> + <&voutcrg
> JH7110_VOUTRST_DC8200_AHB>;
> + reset-names = "core", "axi", "ahb";
> + };
> +
> + hdmi_subsystem: hdmi@29590000 {
> + compatible = "starfive,jh7110-hdmi-
> subsystem";
> + reg = <0x0 0x29590000 0x0 0x4000>;
> +
> + /*
> + * This MFD's PHY child is the first device
> in the vout
> + * region to touch registers, so it owns the
> NoC display
> + * bus clock + reset that gate access to the
> region.
> + * PD_VOUT is powered on by genpd via power-
> domains.
> + */
> + power-domains = <&pwrc JH7110_PD_VOUT>;
> + clocks = <&syscrg
> JH7110_SYSCLK_NOC_BUS_DISP_AXI>;
> + resets = <&syscrg
> JH7110_SYSRST_NOC_BUS_DISP_AXI>;
I think the NOC clocks/resets should be also needed by the DC8200
either?
Although patching the DC8200 driver to add support for these
clocks/resets looks a little dirty...
Maybe it's still good to have a vout subsys instead of a hdmi subsys...
Thanks,
Icenowy
> +
> + hdmi_phy: phy {
> + compatible = "starfive,jh7110-inno-
> hdmi-phy";
> +
> + clocks = <&xin24m>;
> + clock-names = "refoclk";
> +
> + /* Output clock: The variable pixel
> clock */
> + #clock-cells = <0>;
> + clock-output-names = "hdmi_pclk";
> +
> + /* PHY provider for the controller
> */
> + #phy-cells = <0>;
> + };
> +
> + hdmi_controller: controller {
> + compatible = "starfive,jh7110-inno-
> hdmi-controller";
> + interrupts = <99>;
> +
> + clocks = <&voutcrg
> JH7110_VOUTCLK_HDMI_TX_SYS>,
> + <&voutcrg
> JH7110_VOUTCLK_HDMI_TX_MCLK>,
> + <&voutcrg
> JH7110_VOUTCLK_HDMI_TX_BCLK>,
> + <&hdmi_phy>;
> + clock-names = "sys", "mclk", "bclk",
> "pclk";
> +
> + resets = <&voutcrg
> JH7110_VOUTRST_HDMI_TX_HDMI>;
> + reset-names = "hdmi_tx";
> +
> + phys = <&hdmi_phy>;
> + phy-names = "hdmi-phy";
> + };
> + };
> +
> voutcrg: clock-controller@295c0000 {
> compatible = "starfive,jh7110-voutcrg";
> reg = <0x0 0x295c0000 0x0 0x10000>;
> +
> + power-domains = <&pwrc JH7110_PD_VOUT>;
> +
> clocks = <&syscrg JH7110_SYSCLK_VOUT_SRC>,
> <&syscrg
> JH7110_SYSCLK_VOUT_TOP_AHB>,
> <&syscrg
> JH7110_SYSCLK_VOUT_TOP_AXI>,
> <&syscrg
> JH7110_SYSCLK_VOUT_TOP_HDMITX0_MCLK>,
> <&syscrg
> JH7110_SYSCLK_I2STX0_BCLK>,
> - <&hdmitx0_pixelclk>;
> + <&hdmi_phy>;
> clock-names = "vout_src", "vout_top_ahb",
> "vout_top_axi",
> "vout_top_hdmitx0_mclk",
> "i2stx0_bclk",
> "hdmitx0_pixelclk";
> +
> resets = <&syscrg
> JH7110_SYSRST_VOUT_TOP_SRC>;
> #clock-cells = <1>;
> #reset-cells = <1>;
> - power-domains = <&pwrc JH7110_PD_VOUT>;
> };
>
> pcie0: pcie@940000000 {
_______________________________________________
linux-riscv mailing list
linux-riscv@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-riscv
^ permalink raw reply [flat|nested] 116+ messages in thread
* Re: [PATCH v2 14/15] riscv: dts: starfive: jh7110: Update DT for display subsystem
@ 2026-08-28 14:06 ` Icenowy Zheng
0 siblings, 0 replies; 116+ messages in thread
From: Icenowy Zheng @ 2026-08-28 14:06 UTC (permalink / raw)
To: Michal Wilczynski, Vinod Koul, Neil Armstrong, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, Andrzej Hajda, Robert Foss,
Laurent Pinchart, Jonas Karlman, Jernej Skrabec, Luca Ceresoli,
David Airlie, Simona Vetter, Maarten Lankhorst, Maxime Ripard,
Thomas Zimmermann, Lee Jones, Andy Yan, Philipp Zabel,
Emil Renner Berthing, Hal Feng, Michael Turquette, Stephen Boyd,
Brian Masney, Heiko Stuebner, Conor Dooley, Paul Walmsley,
Palmer Dabbelt, Albert Ou, Alexandre Ghiti, Dominique Belhachemi
Cc: linux-phy, devicetree, linux-kernel, dri-devel, mfd, linux-clk,
linux-arm-kernel, linux-rockchip, linux-riscv, Andy Yan,
Marek Szyprowski, Maud Spierings, Graham Markall
在 2026-08-28五的 15:47 +0200,Michal Wilczynski写道:
> Activate the display subsystem by adding the dc8200, hdmi and voutcrg
> nodes as direct soc children. Each references the PD_VOUT power
> domain
> through power-domains, so genpd powers the domain on demand, and the
> HDMI-PHY -> voutcrg -> HDMI-controller probe order is resolved by
> deferred probe.
>
> The monolithic hdmi node is modelled as a container with hdmi_phy
> and hdmi_controller children. This lets the PHY (clock provider,
> depending only on xin24m) and the controller (clock consumer) probe
> independently, breaking the circular clock dependency with voutcrg.
>
> voutcrg consumes the pixel clock from the &hdmi_phy node instead of
> the
> old fixed-clock, and dc8200 gets its pixel clocks from voutcrg's
> MUXes
> and is marked dma-noncoherent for framebuffer DMA. The old, incorrect
> hdmitx0-pixel-clock fixed-clock node is removed.
>
> Co-developed-by: Dominique Belhachemi <db@domibel.de>
> Signed-off-by: Dominique Belhachemi <db@domibel.de>
> Signed-off-by: Michal Wilczynski <m.wilczynski@samsung.com>
> ---
> arch/riscv/boot/dts/starfive/jh7110-common.dtsi | 119
> +++++++++++++++++++++++-
> arch/riscv/boot/dts/starfive/jh7110.dtsi | 87
> +++++++++++++++--
> 2 files changed, 196 insertions(+), 10 deletions(-)
>
> diff --git a/arch/riscv/boot/dts/starfive/jh7110-common.dtsi
> b/arch/riscv/boot/dts/starfive/jh7110-common.dtsi
> index
> a7a1c09a2c9075711f3a214a49618911fdc7b421..7aadc35f4a6aa724c86a868ef65
> c5c829e666ee2 100644
> --- a/arch/riscv/boot/dts/starfive/jh7110-common.dtsi
> +++ b/arch/riscv/boot/dts/starfive/jh7110-common.dtsi
> @@ -33,6 +33,25 @@ memory@40000000 {
> bootph-pre-ram;
> };
>
> + reserved-memory {
> + #address-cells = <2>;
> + #size-cells = <2>;
> + ranges;
> +
> + /* vout applies for space from this CMA
> + * Without this CMA reservation,
> + * vout may not work properly.
> + */
> + linux,cma {
> + compatible = "shared-dma-pool";
> + reusable;
> + size = <0x0 0x20000000>;
> + alignment = <0x0 0x1000>;
> + alloc-ranges = <0x0 0x70000000 0x0
> 0x20000000>;
> + linux,cma-default;
> + };
> + };
> +
> gpio-restart {
> compatible = "gpio-restart";
> gpios = <&sysgpio 35 GPIO_ACTIVE_HIGH>;
> @@ -73,12 +92,47 @@ codec {
> };
> };
> };
> +
> + hdmi-connector {
> + compatible = "hdmi-connector";
> + type = "a";
> +
> + port {
> + hdmi_con_in: endpoint {
> + remote-endpoint = <&hdmi_out_con>;
> + };
> + };
> + };
> };
>
> &cpus {
> timebase-frequency = <4000000>;
> };
>
> +&dc8200 {
> + status = "okay";
> +
> + ports {
> + #address-cells = <1>;
> + #size-cells = <0>;
> +
> + dpu_port0: port@0 {
> + reg = <0>;
> + #address-cells = <1>;
> + #size-cells = <0>;
> +
> + dpu_out_dpi0: endpoint@0 {
> + reg = <0>;
> + remote-endpoint = <&hdmi_in>;
> + };
> + };
> +
> + dpu_port1: port@1 {
> + reg = <1>;
> + };
> + };
> +};
> +
> &dvp_clk {
> clock-frequency = <74250000>;
> };
> @@ -99,8 +153,31 @@ &gmac1_rmii_refin {
> clock-frequency = <50000000>;
> };
>
> -&hdmitx0_pixelclk {
> - clock-frequency = <297000000>;
> +&hdmi_controller {
> + status = "okay";
> + pinctrl-names = "default";
> + pinctrl-0 = <&hdmi_pins>;
> +
> + ports {
> + #address-cells = <1>;
> + #size-cells = <0>;
> +
> + port@0 {
> + reg = <0>;
> +
> + hdmi_in: endpoint {
> + remote-endpoint = <&dpu_out_dpi0>;
> + };
> + };
> +
> + hdmi_out_port: port@1 {
> + reg = <1>;
> + hdmi_out_con: endpoint {
> + remote-endpoint = <&hdmi_con_in>;
> + };
> +
> + };
> + };
> };
>
> &i2srx_bclk_ext {
> @@ -351,6 +428,40 @@ &syscrg {
> };
>
> &sysgpio {
> + hdmi_pins: hdmi-0 {
> + hdmi-cec-pins {
> + pinmux = <GPIOMUX(14,
> GPOUT_SYS_HDMI_CEC_SDA,
> +
> GPOEN_SYS_HDMI_CEC_SDA,
> +
> GPI_SYS_HDMI_CEC_SDA)>;
> + input-enable;
> + bias-pull-up;
> + };
> +
> + hdmi-hpd-pins {
> + pinmux = <GPIOMUX(15, GPOUT_HIGH,
> + GPOEN_ENABLE,
> + GPI_SYS_HDMI_HPD)>;
> + input-enable;
> + bias-disable; /* external pull-up */
> + };
> +
> + hdmi-scl-pins {
> + pinmux = <GPIOMUX(0, GPOUT_SYS_HDMI_DDC_SCL,
> + GPOEN_SYS_HDMI_DDC_SCL,
> + GPI_SYS_HDMI_DDC_SCL)>;
> + input-enable;
> + bias-pull-up;
> + };
> +
> + hdmi-sda-pins {
> + pinmux = <GPIOMUX(1, GPOUT_SYS_HDMI_DDC_SDA,
> + GPOEN_SYS_HDMI_DDC_SDA,
> + GPI_SYS_HDMI_DDC_SDA)>;
> + input-enable;
> + bias-pull-up;
> + };
> + };
> +
> i2c0_pins: i2c0-0 {
> i2c-pins {
> pinmux = <GPIOMUX(57, GPOUT_LOW,
> @@ -629,3 +740,7 @@ &U74_3 {
> &U74_4 {
> cpu-supply = <&vdd_cpu>;
> };
> +
> +&voutcrg {
> + status = "okay";
> +};
> diff --git a/arch/riscv/boot/dts/starfive/jh7110.dtsi
> b/arch/riscv/boot/dts/starfive/jh7110.dtsi
> index
> 9c3e4598747eb5541effe697044484715569a285..024e33b0e97cb13928d69d1d809
> 0ed14d22bb022 100644
> --- a/arch/riscv/boot/dts/starfive/jh7110.dtsi
> +++ b/arch/riscv/boot/dts/starfive/jh7110.dtsi
> @@ -290,12 +290,6 @@ gmac1_rmii_refin: gmac1-rmii-refin-clock {
> #clock-cells = <0>;
> };
>
> - hdmitx0_pixelclk: hdmitx0-pixel-clock {
> - compatible = "fixed-clock";
> - clock-output-names = "hdmitx0_pixelclk";
> - #clock-cells = <0>;
> - };
> -
> i2srx_bclk_ext: i2srx-bclk-ext-clock {
> compatible = "fixed-clock";
> clock-output-names = "i2srx_bclk_ext";
> @@ -352,6 +346,13 @@ tdm_ext: tdm-ext-clock {
> #clock-cells = <0>;
> };
>
> + xin24m: xin24m {
> + compatible = "fixed-clock";
> + #clock-cells = <0>;
> + clock-frequency = <24000000>;
> + clock-output-names = "xin24m";
> + };
> +
> soc {
> compatible = "simple-bus";
> interrupt-parent = <&plic>;
> @@ -1199,22 +1200,92 @@ csi_phy: phy@19820000 {
> #phy-cells = <0>;
> };
>
> + dc8200: display@29400000 {
> + compatible = "verisilicon,dc";
> + reg = <0x0 0x29400000 0x0 0x2800>;
> + interrupts = <95>;
> + dma-noncoherent;
> +
> + power-domains = <&pwrc JH7110_PD_VOUT>;
> +
> + clocks = <&voutcrg
> JH7110_VOUTCLK_DC8200_CORE>,
> + <&voutcrg
> JH7110_VOUTCLK_DC8200_AXI>,
> + <&voutcrg
> JH7110_VOUTCLK_DC8200_AHB>,
> + <&voutcrg
> JH7110_VOUTCLK_DC8200_PIX0>,
> + <&voutcrg
> JH7110_VOUTCLK_DC8200_PIX1>;
> + clock-names = "core", "axi", "ahb", "pix0",
> "pix1";
> +
> + resets = <&voutcrg
> JH7110_VOUTRST_DC8200_CORE>,
> + <&voutcrg
> JH7110_VOUTRST_DC8200_AXI>,
> + <&voutcrg
> JH7110_VOUTRST_DC8200_AHB>;
> + reset-names = "core", "axi", "ahb";
> + };
> +
> + hdmi_subsystem: hdmi@29590000 {
> + compatible = "starfive,jh7110-hdmi-
> subsystem";
> + reg = <0x0 0x29590000 0x0 0x4000>;
> +
> + /*
> + * This MFD's PHY child is the first device
> in the vout
> + * region to touch registers, so it owns the
> NoC display
> + * bus clock + reset that gate access to the
> region.
> + * PD_VOUT is powered on by genpd via power-
> domains.
> + */
> + power-domains = <&pwrc JH7110_PD_VOUT>;
> + clocks = <&syscrg
> JH7110_SYSCLK_NOC_BUS_DISP_AXI>;
> + resets = <&syscrg
> JH7110_SYSRST_NOC_BUS_DISP_AXI>;
I think the NOC clocks/resets should be also needed by the DC8200
either?
Although patching the DC8200 driver to add support for these
clocks/resets looks a little dirty...
Maybe it's still good to have a vout subsys instead of a hdmi subsys...
Thanks,
Icenowy
> +
> + hdmi_phy: phy {
> + compatible = "starfive,jh7110-inno-
> hdmi-phy";
> +
> + clocks = <&xin24m>;
> + clock-names = "refoclk";
> +
> + /* Output clock: The variable pixel
> clock */
> + #clock-cells = <0>;
> + clock-output-names = "hdmi_pclk";
> +
> + /* PHY provider for the controller
> */
> + #phy-cells = <0>;
> + };
> +
> + hdmi_controller: controller {
> + compatible = "starfive,jh7110-inno-
> hdmi-controller";
> + interrupts = <99>;
> +
> + clocks = <&voutcrg
> JH7110_VOUTCLK_HDMI_TX_SYS>,
> + <&voutcrg
> JH7110_VOUTCLK_HDMI_TX_MCLK>,
> + <&voutcrg
> JH7110_VOUTCLK_HDMI_TX_BCLK>,
> + <&hdmi_phy>;
> + clock-names = "sys", "mclk", "bclk",
> "pclk";
> +
> + resets = <&voutcrg
> JH7110_VOUTRST_HDMI_TX_HDMI>;
> + reset-names = "hdmi_tx";
> +
> + phys = <&hdmi_phy>;
> + phy-names = "hdmi-phy";
> + };
> + };
> +
> voutcrg: clock-controller@295c0000 {
> compatible = "starfive,jh7110-voutcrg";
> reg = <0x0 0x295c0000 0x0 0x10000>;
> +
> + power-domains = <&pwrc JH7110_PD_VOUT>;
> +
> clocks = <&syscrg JH7110_SYSCLK_VOUT_SRC>,
> <&syscrg
> JH7110_SYSCLK_VOUT_TOP_AHB>,
> <&syscrg
> JH7110_SYSCLK_VOUT_TOP_AXI>,
> <&syscrg
> JH7110_SYSCLK_VOUT_TOP_HDMITX0_MCLK>,
> <&syscrg
> JH7110_SYSCLK_I2STX0_BCLK>,
> - <&hdmitx0_pixelclk>;
> + <&hdmi_phy>;
> clock-names = "vout_src", "vout_top_ahb",
> "vout_top_axi",
> "vout_top_hdmitx0_mclk",
> "i2stx0_bclk",
> "hdmitx0_pixelclk";
> +
> resets = <&syscrg
> JH7110_SYSRST_VOUT_TOP_SRC>;
> #clock-cells = <1>;
> #reset-cells = <1>;
> - power-domains = <&pwrc JH7110_PD_VOUT>;
> };
>
> pcie0: pcie@940000000 {
_______________________________________________
Linux-rockchip mailing list
Linux-rockchip@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-rockchip
^ permalink raw reply [flat|nested] 116+ messages in thread
* Re: [PATCH v2 14/15] riscv: dts: starfive: jh7110: Update DT for display subsystem
@ 2026-08-28 14:06 ` Icenowy Zheng
0 siblings, 0 replies; 116+ messages in thread
From: Icenowy Zheng @ 2026-08-28 14:06 UTC (permalink / raw)
To: Michal Wilczynski, Vinod Koul, Neil Armstrong, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, Andrzej Hajda, Robert Foss,
Laurent Pinchart, Jonas Karlman, Jernej Skrabec, Luca Ceresoli,
David Airlie, Simona Vetter, Maarten Lankhorst, Maxime Ripard,
Thomas Zimmermann, Lee Jones, Andy Yan, Philipp Zabel,
Emil Renner Berthing, Hal Feng, Michael Turquette, Stephen Boyd,
Brian Masney, Heiko Stuebner, Conor Dooley, Paul Walmsley,
Palmer Dabbelt, Albert Ou, Alexandre Ghiti, Dominique Belhachemi
Cc: linux-phy, devicetree, linux-kernel, dri-devel, mfd, linux-clk,
linux-arm-kernel, linux-rockchip, linux-riscv, Andy Yan,
Marek Szyprowski, Maud Spierings, Graham Markall
在 2026-08-28五的 15:47 +0200,Michal Wilczynski写道:
> Activate the display subsystem by adding the dc8200, hdmi and voutcrg
> nodes as direct soc children. Each references the PD_VOUT power
> domain
> through power-domains, so genpd powers the domain on demand, and the
> HDMI-PHY -> voutcrg -> HDMI-controller probe order is resolved by
> deferred probe.
>
> The monolithic hdmi node is modelled as a container with hdmi_phy
> and hdmi_controller children. This lets the PHY (clock provider,
> depending only on xin24m) and the controller (clock consumer) probe
> independently, breaking the circular clock dependency with voutcrg.
>
> voutcrg consumes the pixel clock from the &hdmi_phy node instead of
> the
> old fixed-clock, and dc8200 gets its pixel clocks from voutcrg's
> MUXes
> and is marked dma-noncoherent for framebuffer DMA. The old, incorrect
> hdmitx0-pixel-clock fixed-clock node is removed.
>
> Co-developed-by: Dominique Belhachemi <db@domibel.de>
> Signed-off-by: Dominique Belhachemi <db@domibel.de>
> Signed-off-by: Michal Wilczynski <m.wilczynski@samsung.com>
> ---
> arch/riscv/boot/dts/starfive/jh7110-common.dtsi | 119
> +++++++++++++++++++++++-
> arch/riscv/boot/dts/starfive/jh7110.dtsi | 87
> +++++++++++++++--
> 2 files changed, 196 insertions(+), 10 deletions(-)
>
> diff --git a/arch/riscv/boot/dts/starfive/jh7110-common.dtsi
> b/arch/riscv/boot/dts/starfive/jh7110-common.dtsi
> index
> a7a1c09a2c9075711f3a214a49618911fdc7b421..7aadc35f4a6aa724c86a868ef65
> c5c829e666ee2 100644
> --- a/arch/riscv/boot/dts/starfive/jh7110-common.dtsi
> +++ b/arch/riscv/boot/dts/starfive/jh7110-common.dtsi
> @@ -33,6 +33,25 @@ memory@40000000 {
> bootph-pre-ram;
> };
>
> + reserved-memory {
> + #address-cells = <2>;
> + #size-cells = <2>;
> + ranges;
> +
> + /* vout applies for space from this CMA
> + * Without this CMA reservation,
> + * vout may not work properly.
> + */
> + linux,cma {
> + compatible = "shared-dma-pool";
> + reusable;
> + size = <0x0 0x20000000>;
> + alignment = <0x0 0x1000>;
> + alloc-ranges = <0x0 0x70000000 0x0
> 0x20000000>;
> + linux,cma-default;
> + };
> + };
> +
> gpio-restart {
> compatible = "gpio-restart";
> gpios = <&sysgpio 35 GPIO_ACTIVE_HIGH>;
> @@ -73,12 +92,47 @@ codec {
> };
> };
> };
> +
> + hdmi-connector {
> + compatible = "hdmi-connector";
> + type = "a";
> +
> + port {
> + hdmi_con_in: endpoint {
> + remote-endpoint = <&hdmi_out_con>;
> + };
> + };
> + };
> };
>
> &cpus {
> timebase-frequency = <4000000>;
> };
>
> +&dc8200 {
> + status = "okay";
> +
> + ports {
> + #address-cells = <1>;
> + #size-cells = <0>;
> +
> + dpu_port0: port@0 {
> + reg = <0>;
> + #address-cells = <1>;
> + #size-cells = <0>;
> +
> + dpu_out_dpi0: endpoint@0 {
> + reg = <0>;
> + remote-endpoint = <&hdmi_in>;
> + };
> + };
> +
> + dpu_port1: port@1 {
> + reg = <1>;
> + };
> + };
> +};
> +
> &dvp_clk {
> clock-frequency = <74250000>;
> };
> @@ -99,8 +153,31 @@ &gmac1_rmii_refin {
> clock-frequency = <50000000>;
> };
>
> -&hdmitx0_pixelclk {
> - clock-frequency = <297000000>;
> +&hdmi_controller {
> + status = "okay";
> + pinctrl-names = "default";
> + pinctrl-0 = <&hdmi_pins>;
> +
> + ports {
> + #address-cells = <1>;
> + #size-cells = <0>;
> +
> + port@0 {
> + reg = <0>;
> +
> + hdmi_in: endpoint {
> + remote-endpoint = <&dpu_out_dpi0>;
> + };
> + };
> +
> + hdmi_out_port: port@1 {
> + reg = <1>;
> + hdmi_out_con: endpoint {
> + remote-endpoint = <&hdmi_con_in>;
> + };
> +
> + };
> + };
> };
>
> &i2srx_bclk_ext {
> @@ -351,6 +428,40 @@ &syscrg {
> };
>
> &sysgpio {
> + hdmi_pins: hdmi-0 {
> + hdmi-cec-pins {
> + pinmux = <GPIOMUX(14,
> GPOUT_SYS_HDMI_CEC_SDA,
> +
> GPOEN_SYS_HDMI_CEC_SDA,
> +
> GPI_SYS_HDMI_CEC_SDA)>;
> + input-enable;
> + bias-pull-up;
> + };
> +
> + hdmi-hpd-pins {
> + pinmux = <GPIOMUX(15, GPOUT_HIGH,
> + GPOEN_ENABLE,
> + GPI_SYS_HDMI_HPD)>;
> + input-enable;
> + bias-disable; /* external pull-up */
> + };
> +
> + hdmi-scl-pins {
> + pinmux = <GPIOMUX(0, GPOUT_SYS_HDMI_DDC_SCL,
> + GPOEN_SYS_HDMI_DDC_SCL,
> + GPI_SYS_HDMI_DDC_SCL)>;
> + input-enable;
> + bias-pull-up;
> + };
> +
> + hdmi-sda-pins {
> + pinmux = <GPIOMUX(1, GPOUT_SYS_HDMI_DDC_SDA,
> + GPOEN_SYS_HDMI_DDC_SDA,
> + GPI_SYS_HDMI_DDC_SDA)>;
> + input-enable;
> + bias-pull-up;
> + };
> + };
> +
> i2c0_pins: i2c0-0 {
> i2c-pins {
> pinmux = <GPIOMUX(57, GPOUT_LOW,
> @@ -629,3 +740,7 @@ &U74_3 {
> &U74_4 {
> cpu-supply = <&vdd_cpu>;
> };
> +
> +&voutcrg {
> + status = "okay";
> +};
> diff --git a/arch/riscv/boot/dts/starfive/jh7110.dtsi
> b/arch/riscv/boot/dts/starfive/jh7110.dtsi
> index
> 9c3e4598747eb5541effe697044484715569a285..024e33b0e97cb13928d69d1d809
> 0ed14d22bb022 100644
> --- a/arch/riscv/boot/dts/starfive/jh7110.dtsi
> +++ b/arch/riscv/boot/dts/starfive/jh7110.dtsi
> @@ -290,12 +290,6 @@ gmac1_rmii_refin: gmac1-rmii-refin-clock {
> #clock-cells = <0>;
> };
>
> - hdmitx0_pixelclk: hdmitx0-pixel-clock {
> - compatible = "fixed-clock";
> - clock-output-names = "hdmitx0_pixelclk";
> - #clock-cells = <0>;
> - };
> -
> i2srx_bclk_ext: i2srx-bclk-ext-clock {
> compatible = "fixed-clock";
> clock-output-names = "i2srx_bclk_ext";
> @@ -352,6 +346,13 @@ tdm_ext: tdm-ext-clock {
> #clock-cells = <0>;
> };
>
> + xin24m: xin24m {
> + compatible = "fixed-clock";
> + #clock-cells = <0>;
> + clock-frequency = <24000000>;
> + clock-output-names = "xin24m";
> + };
> +
> soc {
> compatible = "simple-bus";
> interrupt-parent = <&plic>;
> @@ -1199,22 +1200,92 @@ csi_phy: phy@19820000 {
> #phy-cells = <0>;
> };
>
> + dc8200: display@29400000 {
> + compatible = "verisilicon,dc";
> + reg = <0x0 0x29400000 0x0 0x2800>;
> + interrupts = <95>;
> + dma-noncoherent;
> +
> + power-domains = <&pwrc JH7110_PD_VOUT>;
> +
> + clocks = <&voutcrg
> JH7110_VOUTCLK_DC8200_CORE>,
> + <&voutcrg
> JH7110_VOUTCLK_DC8200_AXI>,
> + <&voutcrg
> JH7110_VOUTCLK_DC8200_AHB>,
> + <&voutcrg
> JH7110_VOUTCLK_DC8200_PIX0>,
> + <&voutcrg
> JH7110_VOUTCLK_DC8200_PIX1>;
> + clock-names = "core", "axi", "ahb", "pix0",
> "pix1";
> +
> + resets = <&voutcrg
> JH7110_VOUTRST_DC8200_CORE>,
> + <&voutcrg
> JH7110_VOUTRST_DC8200_AXI>,
> + <&voutcrg
> JH7110_VOUTRST_DC8200_AHB>;
> + reset-names = "core", "axi", "ahb";
> + };
> +
> + hdmi_subsystem: hdmi@29590000 {
> + compatible = "starfive,jh7110-hdmi-
> subsystem";
> + reg = <0x0 0x29590000 0x0 0x4000>;
> +
> + /*
> + * This MFD's PHY child is the first device
> in the vout
> + * region to touch registers, so it owns the
> NoC display
> + * bus clock + reset that gate access to the
> region.
> + * PD_VOUT is powered on by genpd via power-
> domains.
> + */
> + power-domains = <&pwrc JH7110_PD_VOUT>;
> + clocks = <&syscrg
> JH7110_SYSCLK_NOC_BUS_DISP_AXI>;
> + resets = <&syscrg
> JH7110_SYSRST_NOC_BUS_DISP_AXI>;
I think the NOC clocks/resets should be also needed by the DC8200
either?
Although patching the DC8200 driver to add support for these
clocks/resets looks a little dirty...
Maybe it's still good to have a vout subsys instead of a hdmi subsys...
Thanks,
Icenowy
> +
> + hdmi_phy: phy {
> + compatible = "starfive,jh7110-inno-
> hdmi-phy";
> +
> + clocks = <&xin24m>;
> + clock-names = "refoclk";
> +
> + /* Output clock: The variable pixel
> clock */
> + #clock-cells = <0>;
> + clock-output-names = "hdmi_pclk";
> +
> + /* PHY provider for the controller
> */
> + #phy-cells = <0>;
> + };
> +
> + hdmi_controller: controller {
> + compatible = "starfive,jh7110-inno-
> hdmi-controller";
> + interrupts = <99>;
> +
> + clocks = <&voutcrg
> JH7110_VOUTCLK_HDMI_TX_SYS>,
> + <&voutcrg
> JH7110_VOUTCLK_HDMI_TX_MCLK>,
> + <&voutcrg
> JH7110_VOUTCLK_HDMI_TX_BCLK>,
> + <&hdmi_phy>;
> + clock-names = "sys", "mclk", "bclk",
> "pclk";
> +
> + resets = <&voutcrg
> JH7110_VOUTRST_HDMI_TX_HDMI>;
> + reset-names = "hdmi_tx";
> +
> + phys = <&hdmi_phy>;
> + phy-names = "hdmi-phy";
> + };
> + };
> +
> voutcrg: clock-controller@295c0000 {
> compatible = "starfive,jh7110-voutcrg";
> reg = <0x0 0x295c0000 0x0 0x10000>;
> +
> + power-domains = <&pwrc JH7110_PD_VOUT>;
> +
> clocks = <&syscrg JH7110_SYSCLK_VOUT_SRC>,
> <&syscrg
> JH7110_SYSCLK_VOUT_TOP_AHB>,
> <&syscrg
> JH7110_SYSCLK_VOUT_TOP_AXI>,
> <&syscrg
> JH7110_SYSCLK_VOUT_TOP_HDMITX0_MCLK>,
> <&syscrg
> JH7110_SYSCLK_I2STX0_BCLK>,
> - <&hdmitx0_pixelclk>;
> + <&hdmi_phy>;
> clock-names = "vout_src", "vout_top_ahb",
> "vout_top_axi",
> "vout_top_hdmitx0_mclk",
> "i2stx0_bclk",
> "hdmitx0_pixelclk";
> +
> resets = <&syscrg
> JH7110_SYSRST_VOUT_TOP_SRC>;
> #clock-cells = <1>;
> #reset-cells = <1>;
> - power-domains = <&pwrc JH7110_PD_VOUT>;
> };
>
> pcie0: pcie@940000000 {
--
linux-phy mailing list
linux-phy@lists.infradead.org
https://lists.infradead.org/mailman/listinfo/linux-phy
^ permalink raw reply [flat|nested] 116+ messages in thread
* Re: [PATCH v2 12/15] phy: rockchip: inno-hdmi: Use the common Innosilicon PHY helpers
2026-08-28 13:47 ` Michal Wilczynski
@ 2026-08-28 14:12 ` sashiko-bot
-1 siblings, 0 replies; 116+ messages in thread
From: sashiko-bot @ 2026-08-28 14:12 UTC (permalink / raw)
To: Michal Wilczynski
Cc: lee, conor+dt, olteanv, vkoul, mfd, linux-clk, robh, devicetree,
dri-devel, neil.armstrong, linux-phy
Thank you for your contribution! Sashiko AI review found 2 potential issue(s) to consider:
Pre-existing issues:
- [High] Kernel panic or division-by-zero exception due to division by zero in clock rate recalculation if hardware registers are uninitialized or zeroed.
- [High] Multiplication of unsigned long values silently overflows on 32-bit architectures before assignment to a 64-bit variable in VCO rate calculation.
--
commit 65afb8fac5b8b08e9749e00354df9fbca4121dd2
Author: Michal Wilczynski <m.wilczynski@samsung.com>
phy: rockchip: inno-hdmi: Use the common Innosilicon PHY helpers
This commit replaces the local RK3328 pre-PLL implementations for calculating
and setting rates with the generic shared Innosilicon helpers. It keeps the
RK3228 register-level code separate due to different register addresses but
shares the table lookup.
> diff --git a/drivers/phy/rockchip/phy-rockchip-inno-hdmi.c b/drivers/phy/rockchip/phy-rockchip-inno-hdmi.c
> index 1483907413faa..fae766607b0ea 100644
> --- a/drivers/phy/rockchip/phy-rockchip-inno-hdmi.c
> +++ b/drivers/phy/rockchip/phy-rockchip-inno-hdmi.c
[ ... ]
> @@ -870,39 +850,11 @@ unsigned long inno_hdmi_phy_rk3328_clk_recalc_rate(struct clk_hw *hw,
> unsigned long parent_rate)
> {
> struct inno_hdmi_phy *inno = to_inno_hdmi_phy(hw);
[ ... ]
> + inno->pixclock = inno_hdmi_phy_pre_pll_recalc_rate(&inno->pre_pll,
> + parent_rate);
[Severity: High]
This is a pre-existing issue, but since we are switching to the shared helper
inno_hdmi_phy_pre_pll_recalc_rate(), can this code cause a division by zero?
If the bootloader has not initialized the PHY, the hardware registers may
contain their default 0 values. When the clock framework calls recalc_rate
during registration at boot, would the following logic in the helper result in
a division by zero:
drivers/phy/phy-inno-hdmi.c:inno_hdmi_phy_pre_pll_recalc_rate() {
...
nd = inno_read(pll, INNO_PRE_PLL_DIV_1) & INNO_PRE_PLL_PRE_DIV_MASK;
...
if (inno_read(pll, INNO_PRE_PLL_CONTROL) & INNO_PCLK_VCO_DIV_5_MASK) {
do_div(vco, nd * 5);
} else {
no_a = inno_read(pll, INNO_PCLK_DIV_AB) & INNO_PCLK_DIV_A_MASK;
no_b = FIELD_GET(INNO_PCLK_DIV_B_MASK,
inno_read(pll, INNO_PCLK_DIV_AB)) + 2;
no_d = inno_read(pll, INNO_PCLK_DIV_CD) & INNO_PCLK_DIV_D_MASK;
do_div(vco, nd * (no_a == 1 ? no_b : no_a) * no_d * 2);
}
...
}
If nd, no_a, or no_d evaluate to 0, the denominator becomes 0, which could
lead to a kernel panic or exception on some architectures.
[Severity: High]
This isn't a bug introduced by this patch, but does the rate recalculation
silently overflow on 32-bit architectures?
Inside the same helper, the VCO rate is calculated as:
drivers/phy/phy-inno-hdmi.c:inno_hdmi_phy_pre_pll_recalc_rate() {
...
vco = parent_rate * nf;
if (!(inno_read(pll, INNO_PRE_PLL_DIV_2) &
INNO_PRE_PLL_FRAC_DIV_DISABLE)) {
frac = inno_read(pll, INNO_PRE_PLL_FRAC_DIV_7_0) |
(inno_read(pll, INNO_PRE_PLL_FRAC_DIV_15_8) << 8) |
(inno_read(pll, INNO_PRE_PLL_FRAC_DIV_23_16) << 16);
vco += DIV_ROUND_CLOSEST(parent_rate * frac,
BIT(INNO_FRAC_DIV_WIDTH));
}
...
}
The parent_rate is typically 24,000,000, while nf can be up to 757 and
frac up to ~14.6 million. Since parent_rate is an unsigned long and nf is a
u16, the multiplication is performed as 32-bit unsigned math on 32-bit
platforms (like RK3228 which uses ARM32).
Would parent_rate * nf and parent_rate * frac wrap around ULONG_MAX before
being assigned to the 64-bit vco variable or before the division in
DIV_ROUND_CLOSEST?
>
> - inno->pixclock = DIV_ROUND_CLOSEST((unsigned long)vco, 1000) * 1000;
> -
> - dev_dbg(inno->dev, "%s rate %lu vco %llu\n",
> - __func__, inno->pixclock, vco);
> + dev_dbg(inno->dev, "%s rate %lu\n", __func__, inno->pixclock);
>
> return inno->pixclock;
> }
--
Sashiko AI review · https://sashiko.dev/#/patchset/20260828-jh7110-clean-send-v2-0-331680c8b9d1@samsung.com?part=12
^ permalink raw reply [flat|nested] 116+ messages in thread
* Re: [PATCH v2 12/15] phy: rockchip: inno-hdmi: Use the common Innosilicon PHY helpers
@ 2026-08-28 14:12 ` sashiko-bot
0 siblings, 0 replies; 116+ messages in thread
From: sashiko-bot @ 2026-08-28 14:12 UTC (permalink / raw)
To: Michal Wilczynski
Cc: lee, conor+dt, olteanv, vkoul, mfd, linux-clk, robh, devicetree,
dri-devel, neil.armstrong, linux-phy
Thank you for your contribution! Sashiko AI review found 2 potential issue(s) to consider:
Pre-existing issues:
- [High] Kernel panic or division-by-zero exception due to division by zero in clock rate recalculation if hardware registers are uninitialized or zeroed.
- [High] Multiplication of unsigned long values silently overflows on 32-bit architectures before assignment to a 64-bit variable in VCO rate calculation.
--
commit 65afb8fac5b8b08e9749e00354df9fbca4121dd2
Author: Michal Wilczynski <m.wilczynski@samsung.com>
phy: rockchip: inno-hdmi: Use the common Innosilicon PHY helpers
This commit replaces the local RK3328 pre-PLL implementations for calculating
and setting rates with the generic shared Innosilicon helpers. It keeps the
RK3228 register-level code separate due to different register addresses but
shares the table lookup.
> diff --git a/drivers/phy/rockchip/phy-rockchip-inno-hdmi.c b/drivers/phy/rockchip/phy-rockchip-inno-hdmi.c
> index 1483907413faa..fae766607b0ea 100644
> --- a/drivers/phy/rockchip/phy-rockchip-inno-hdmi.c
> +++ b/drivers/phy/rockchip/phy-rockchip-inno-hdmi.c
[ ... ]
> @@ -870,39 +850,11 @@ unsigned long inno_hdmi_phy_rk3328_clk_recalc_rate(struct clk_hw *hw,
> unsigned long parent_rate)
> {
> struct inno_hdmi_phy *inno = to_inno_hdmi_phy(hw);
[ ... ]
> + inno->pixclock = inno_hdmi_phy_pre_pll_recalc_rate(&inno->pre_pll,
> + parent_rate);
[Severity: High]
This is a pre-existing issue, but since we are switching to the shared helper
inno_hdmi_phy_pre_pll_recalc_rate(), can this code cause a division by zero?
If the bootloader has not initialized the PHY, the hardware registers may
contain their default 0 values. When the clock framework calls recalc_rate
during registration at boot, would the following logic in the helper result in
a division by zero:
drivers/phy/phy-inno-hdmi.c:inno_hdmi_phy_pre_pll_recalc_rate() {
...
nd = inno_read(pll, INNO_PRE_PLL_DIV_1) & INNO_PRE_PLL_PRE_DIV_MASK;
...
if (inno_read(pll, INNO_PRE_PLL_CONTROL) & INNO_PCLK_VCO_DIV_5_MASK) {
do_div(vco, nd * 5);
} else {
no_a = inno_read(pll, INNO_PCLK_DIV_AB) & INNO_PCLK_DIV_A_MASK;
no_b = FIELD_GET(INNO_PCLK_DIV_B_MASK,
inno_read(pll, INNO_PCLK_DIV_AB)) + 2;
no_d = inno_read(pll, INNO_PCLK_DIV_CD) & INNO_PCLK_DIV_D_MASK;
do_div(vco, nd * (no_a == 1 ? no_b : no_a) * no_d * 2);
}
...
}
If nd, no_a, or no_d evaluate to 0, the denominator becomes 0, which could
lead to a kernel panic or exception on some architectures.
[Severity: High]
This isn't a bug introduced by this patch, but does the rate recalculation
silently overflow on 32-bit architectures?
Inside the same helper, the VCO rate is calculated as:
drivers/phy/phy-inno-hdmi.c:inno_hdmi_phy_pre_pll_recalc_rate() {
...
vco = parent_rate * nf;
if (!(inno_read(pll, INNO_PRE_PLL_DIV_2) &
INNO_PRE_PLL_FRAC_DIV_DISABLE)) {
frac = inno_read(pll, INNO_PRE_PLL_FRAC_DIV_7_0) |
(inno_read(pll, INNO_PRE_PLL_FRAC_DIV_15_8) << 8) |
(inno_read(pll, INNO_PRE_PLL_FRAC_DIV_23_16) << 16);
vco += DIV_ROUND_CLOSEST(parent_rate * frac,
BIT(INNO_FRAC_DIV_WIDTH));
}
...
}
The parent_rate is typically 24,000,000, while nf can be up to 757 and
frac up to ~14.6 million. Since parent_rate is an unsigned long and nf is a
u16, the multiplication is performed as 32-bit unsigned math on 32-bit
platforms (like RK3228 which uses ARM32).
Would parent_rate * nf and parent_rate * frac wrap around ULONG_MAX before
being assigned to the 64-bit vco variable or before the division in
DIV_ROUND_CLOSEST?
>
> - inno->pixclock = DIV_ROUND_CLOSEST((unsigned long)vco, 1000) * 1000;
> -
> - dev_dbg(inno->dev, "%s rate %lu vco %llu\n",
> - __func__, inno->pixclock, vco);
> + dev_dbg(inno->dev, "%s rate %lu\n", __func__, inno->pixclock);
>
> return inno->pixclock;
> }
--
Sashiko AI review · https://sashiko.dev/#/patchset/20260828-jh7110-clean-send-v2-0-331680c8b9d1@samsung.com?part=12
--
linux-phy mailing list
linux-phy@lists.infradead.org
https://lists.infradead.org/mailman/listinfo/linux-phy
^ permalink raw reply [flat|nested] 116+ messages in thread
* Re: [PATCH v2 01/15] dt-bindings: phy: Add starfive,jh7110-inno-hdmi-phy
2026-08-28 13:47 ` Michal Wilczynski
(?)
(?)
@ 2026-08-28 16:43 ` Conor Dooley
-1 siblings, 0 replies; 116+ messages in thread
From: Conor Dooley @ 2026-08-28 16:43 UTC (permalink / raw)
To: Michal Wilczynski
Cc: Vinod Koul, Neil Armstrong, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Andrzej Hajda, Robert Foss, Laurent Pinchart,
Jonas Karlman, Jernej Skrabec, Luca Ceresoli, David Airlie,
Simona Vetter, Maarten Lankhorst, Maxime Ripard,
Thomas Zimmermann, Lee Jones, Andy Yan, Philipp Zabel,
Emil Renner Berthing, Hal Feng, Michael Turquette, Stephen Boyd,
Brian Masney, Heiko Stuebner, Paul Walmsley, Palmer Dabbelt,
Albert Ou, Alexandre Ghiti, Dominique Belhachemi, linux-phy,
devicetree, linux-kernel, dri-devel, mfd, linux-clk,
linux-arm-kernel, linux-rockchip, linux-riscv, Icenowy Zheng,
Andy Yan, Marek Szyprowski, Maud Spierings, Graham Markall
[-- Attachment #1: Type: text/plain, Size: 332 bytes --]
On Fri, Aug 28, 2026 at 03:47:25PM +0200, Michal Wilczynski wrote:
> + clock-names:
> + const: refoclk
> + clock-output-names:
> + const: hdmi_pclk
Can you drop the obvious "clk" suffixes from these please? Although,
with one input and one output clock, what's the point of the -names
proeprties anyway?
Cheers,
Conor.
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 228 bytes --]
^ permalink raw reply [flat|nested] 116+ messages in thread
* Re: [PATCH v2 01/15] dt-bindings: phy: Add starfive,jh7110-inno-hdmi-phy
@ 2026-08-28 16:43 ` Conor Dooley
0 siblings, 0 replies; 116+ messages in thread
From: Conor Dooley @ 2026-08-28 16:43 UTC (permalink / raw)
To: Michal Wilczynski
Cc: Vinod Koul, Neil Armstrong, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Andrzej Hajda, Robert Foss, Laurent Pinchart,
Jonas Karlman, Jernej Skrabec, Luca Ceresoli, David Airlie,
Simona Vetter, Maarten Lankhorst, Maxime Ripard,
Thomas Zimmermann, Lee Jones, Andy Yan, Philipp Zabel,
Emil Renner Berthing, Hal Feng, Michael Turquette, Stephen Boyd,
Brian Masney, Heiko Stuebner, Paul Walmsley, Palmer Dabbelt,
Albert Ou, Alexandre Ghiti, Dominique Belhachemi, linux-phy,
devicetree, linux-kernel, dri-devel, mfd, linux-clk,
linux-arm-kernel, linux-rockchip, linux-riscv, Icenowy Zheng,
Andy Yan, Marek Szyprowski, Maud Spierings, Graham Markall
[-- Attachment #1.1: Type: text/plain, Size: 332 bytes --]
On Fri, Aug 28, 2026 at 03:47:25PM +0200, Michal Wilczynski wrote:
> + clock-names:
> + const: refoclk
> + clock-output-names:
> + const: hdmi_pclk
Can you drop the obvious "clk" suffixes from these please? Although,
with one input and one output clock, what's the point of the -names
proeprties anyway?
Cheers,
Conor.
[-- Attachment #1.2: signature.asc --]
[-- Type: application/pgp-signature, Size: 228 bytes --]
[-- Attachment #2: Type: text/plain, Size: 170 bytes --]
_______________________________________________
Linux-rockchip mailing list
Linux-rockchip@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-rockchip
^ permalink raw reply [flat|nested] 116+ messages in thread
* Re: [PATCH v2 01/15] dt-bindings: phy: Add starfive,jh7110-inno-hdmi-phy
@ 2026-08-28 16:43 ` Conor Dooley
0 siblings, 0 replies; 116+ messages in thread
From: Conor Dooley @ 2026-08-28 16:43 UTC (permalink / raw)
To: Michal Wilczynski
Cc: Vinod Koul, Neil Armstrong, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Andrzej Hajda, Robert Foss, Laurent Pinchart,
Jonas Karlman, Jernej Skrabec, Luca Ceresoli, David Airlie,
Simona Vetter, Maarten Lankhorst, Maxime Ripard,
Thomas Zimmermann, Lee Jones, Andy Yan, Philipp Zabel,
Emil Renner Berthing, Hal Feng, Michael Turquette, Stephen Boyd,
Brian Masney, Heiko Stuebner, Paul Walmsley, Palmer Dabbelt,
Albert Ou, Alexandre Ghiti, Dominique Belhachemi, linux-phy,
devicetree, linux-kernel, dri-devel, mfd, linux-clk,
linux-arm-kernel, linux-rockchip, linux-riscv, Icenowy Zheng,
Andy Yan, Marek Szyprowski, Maud Spierings, Graham Markall
[-- Attachment #1.1: Type: text/plain, Size: 332 bytes --]
On Fri, Aug 28, 2026 at 03:47:25PM +0200, Michal Wilczynski wrote:
> + clock-names:
> + const: refoclk
> + clock-output-names:
> + const: hdmi_pclk
Can you drop the obvious "clk" suffixes from these please? Although,
with one input and one output clock, what's the point of the -names
proeprties anyway?
Cheers,
Conor.
[-- Attachment #1.2: signature.asc --]
[-- Type: application/pgp-signature, Size: 228 bytes --]
[-- Attachment #2: Type: text/plain, Size: 112 bytes --]
--
linux-phy mailing list
linux-phy@lists.infradead.org
https://lists.infradead.org/mailman/listinfo/linux-phy
^ permalink raw reply [flat|nested] 116+ messages in thread
* Re: [PATCH v2 01/15] dt-bindings: phy: Add starfive,jh7110-inno-hdmi-phy
@ 2026-08-28 16:43 ` Conor Dooley
0 siblings, 0 replies; 116+ messages in thread
From: Conor Dooley @ 2026-08-28 16:43 UTC (permalink / raw)
To: Michal Wilczynski
Cc: Emil Renner Berthing, Michael Turquette, dri-devel,
Laurent Pinchart, Andrzej Hajda, linux-phy, linux-riscv,
David Airlie, linux-clk, Heiko Stuebner, Simona Vetter,
Rob Herring, Dominique Belhachemi, Robert Foss, Alexandre Ghiti,
Lee Jones, Andy Yan, Jernej Skrabec, Hal Feng, Graham Markall,
linux-rockchip, Marek Szyprowski, Luca Ceresoli, devicetree,
Conor Dooley, Albert Ou, Philipp Zabel, Jonas Karlman,
Brian Masney, Maarten Lankhorst, Maxime Ripard, mfd,
Paul Walmsley, linux-arm-kernel, Neil Armstrong, Stephen Boyd,
linux-kernel, Maud Spierings, Vinod Koul, Palmer Dabbelt,
Thomas Zimmermann, Andy Yan, Krzysztof Kozlowski
[-- Attachment #1.1: Type: text/plain, Size: 332 bytes --]
On Fri, Aug 28, 2026 at 03:47:25PM +0200, Michal Wilczynski wrote:
> + clock-names:
> + const: refoclk
> + clock-output-names:
> + const: hdmi_pclk
Can you drop the obvious "clk" suffixes from these please? Although,
with one input and one output clock, what's the point of the -names
proeprties anyway?
Cheers,
Conor.
[-- Attachment #1.2: signature.asc --]
[-- Type: application/pgp-signature, Size: 228 bytes --]
[-- Attachment #2: Type: text/plain, Size: 161 bytes --]
_______________________________________________
linux-riscv mailing list
linux-riscv@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-riscv
^ permalink raw reply [flat|nested] 116+ messages in thread
* Re: [PATCH v2 02/15] dt-bindings: display: bridge: Add starfive,jh7110-inno-hdmi-controller
2026-08-28 13:47 ` Michal Wilczynski
(?)
(?)
@ 2026-08-28 16:47 ` Conor Dooley
-1 siblings, 0 replies; 116+ messages in thread
From: Conor Dooley @ 2026-08-28 16:47 UTC (permalink / raw)
To: Michal Wilczynski
Cc: Vinod Koul, Neil Armstrong, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Andrzej Hajda, Robert Foss, Laurent Pinchart,
Jonas Karlman, Jernej Skrabec, Luca Ceresoli, David Airlie,
Simona Vetter, Maarten Lankhorst, Maxime Ripard,
Thomas Zimmermann, Lee Jones, Andy Yan, Philipp Zabel,
Emil Renner Berthing, Hal Feng, Michael Turquette, Stephen Boyd,
Brian Masney, Heiko Stuebner, Paul Walmsley, Palmer Dabbelt,
Albert Ou, Alexandre Ghiti, Dominique Belhachemi, linux-phy,
devicetree, linux-kernel, dri-devel, mfd, linux-clk,
linux-arm-kernel, linux-rockchip, linux-riscv, Icenowy Zheng,
Andy Yan, Marek Szyprowski, Maud Spierings, Graham Markall
[-- Attachment #1: Type: text/plain, Size: 4484 bytes --]
On Fri, Aug 28, 2026 at 03:47:26PM +0200, Michal Wilczynski wrote:
> Add the dt-binding for the StarFive JH7110 Innosilicon HDMI controller
> (DRM bridge).
>
> This device is the second child of the starfive,jh7110-hdmi-subsystem node.
> It consumes register access clocks (sys, mclk, bclk) from the voutcrg and
> both the pixel clock (pclk) and the PHY from its hdmi_phy sibling.
>
> Signed-off-by: Michal Wilczynski <m.wilczynski@samsung.com>
> ---
> .../starfive,jh7110-inno-hdmi-controller.yaml | 109 +++++++++++++++++++++
> 1 file changed, 109 insertions(+)
>
> diff --git a/Documentation/devicetree/bindings/display/bridge/starfive,jh7110-inno-hdmi-controller.yaml b/Documentation/devicetree/bindings/display/bridge/starfive,jh7110-inno-hdmi-controller.yaml
> new file mode 100644
> index 0000000000000000000000000000000000000000..0e584e7b756e24e2f99a62daab3117bbf4b472b6
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/display/bridge/starfive,jh7110-inno-hdmi-controller.yaml
> @@ -0,0 +1,109 @@
> +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
> +%YAML 1.2
> +---
> +$id: http://devicetree.org/schemas/display/bridge/starfive,jh7110-inno-hdmi-controller.yaml#
> +$schema: http://devicetree.org/meta-schemas/core.yaml#
> +
> +title: StarFive JH7110 Innosilicon HDMI Controller
> +
> +maintainers:
> + - Michal Wilczynski <m.wilczynski@samsung.com>
> +
> +description:
> + The controller portion of the StarFive JH7110 INNO HDMI IP.
> +
> +properties:
> + compatible:
> + const: starfive,jh7110-inno-hdmi-controller
> +
> + interrupts:
> + maxItems: 1
> +
> + clocks:
> + items:
> + - description: System clock for register access
> + - description: Module clock
> + - description: Bus clock
> + - description: Pixel clock from PHY
> +
> + clock-names:
> + items:
> + - const: sys
> + - const: mclk
> + - const: bclk
> + - const: pclk
"module" "bus" "pixel" would be more informative than spending most of
your characters regurgitating what these are by definition?
> +
> + resets:
> + maxItems: 1
> +
> + reset-names:
> + const: hdmi_tx
> +
> + phys:
> + maxItems: 1
> +
> + phy-names:
> + const: hdmi-phy
With the trend of ?pointless? -names properties, I'm surprised you don't
have interrupt-names? I'd ditch 'em all where there's only a single
clock. The _ rather than - in the reset name triggers my OCD.
pw-bot: changes-requested
> +
> + ports:
> + $ref: /schemas/graph.yaml#/properties/ports
> + description:
> + A graph node with one input port and one output port.
> +
> +required:
> + - compatible
> + - interrupts
> + - clocks
> + - clock-names
> + - resets
> + - reset-names
> + - phys
> + - phy-names
> + - ports
> +
> +additionalProperties: false
> +
> +examples:
> + # Shown as a child of the HDMI subsystem node; see
> + # Documentation/devicetree/bindings/mfd/starfive,jh7110-hdmi-subsystem.yaml
> + # for the full node.
> + - |
> + #include <dt-bindings/clock/starfive,jh7110-crg.h>
> + #include <dt-bindings/reset/starfive,jh7110-crg.h>
> +
> + controller {
"controller" seems over generic for a node, but I guess if the parent is
"hdmi-subsystem" or something it makes sense in that context.
Cheers,
Conor.
> + compatible = "starfive,jh7110-inno-hdmi-controller";
> + clocks = <&voutcrg JH7110_VOUTCLK_HDMI_TX_SYS>,
> + <&voutcrg JH7110_VOUTCLK_HDMI_TX_MCLK>,
> + <&voutcrg JH7110_VOUTCLK_HDMI_TX_BCLK>,
> + <&hdmi_phy>;
> + clock-names = "sys", "mclk", "bclk", "pclk";
> + interrupts = <99>;
> + phys = <&hdmi_phy>;
> + phy-names = "hdmi-phy";
> + resets = <&voutcrg JH7110_VOUTRST_HDMI_TX_HDMI>;
> + reset-names = "hdmi_tx";
> +
> + ports {
> + #address-cells = <1>;
> + #size-cells = <0>;
> +
> + port@0 {
> + reg = <0>;
> +
> + endpoint {
> + remote-endpoint = <&dpu_out_dpi0>;
> + };
> + };
> +
> + port@1 {
> + reg = <1>;
> +
> + endpoint {
> + remote-endpoint = <&hdmi_con_in>;
> + };
> + };
> + };
> + };
> +
> +...
>
> --
> 2.34.1
>
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 228 bytes --]
^ permalink raw reply [flat|nested] 116+ messages in thread
* Re: [PATCH v2 02/15] dt-bindings: display: bridge: Add starfive,jh7110-inno-hdmi-controller
@ 2026-08-28 16:47 ` Conor Dooley
0 siblings, 0 replies; 116+ messages in thread
From: Conor Dooley @ 2026-08-28 16:47 UTC (permalink / raw)
To: Michal Wilczynski
Cc: Emil Renner Berthing, Michael Turquette, dri-devel,
Laurent Pinchart, Andrzej Hajda, linux-phy, linux-riscv,
David Airlie, linux-clk, Heiko Stuebner, Simona Vetter,
Rob Herring, Dominique Belhachemi, Robert Foss, Alexandre Ghiti,
Lee Jones, Andy Yan, Jernej Skrabec, Hal Feng, Graham Markall,
linux-rockchip, Marek Szyprowski, Luca Ceresoli, devicetree,
Conor Dooley, Albert Ou, Philipp Zabel, Jonas Karlman,
Brian Masney, Maarten Lankhorst, Maxime Ripard, mfd,
Paul Walmsley, linux-arm-kernel, Neil Armstrong, Stephen Boyd,
linux-kernel, Maud Spierings, Vinod Koul, Palmer Dabbelt,
Thomas Zimmermann, Andy Yan, Krzysztof Kozlowski
[-- Attachment #1.1: Type: text/plain, Size: 4484 bytes --]
On Fri, Aug 28, 2026 at 03:47:26PM +0200, Michal Wilczynski wrote:
> Add the dt-binding for the StarFive JH7110 Innosilicon HDMI controller
> (DRM bridge).
>
> This device is the second child of the starfive,jh7110-hdmi-subsystem node.
> It consumes register access clocks (sys, mclk, bclk) from the voutcrg and
> both the pixel clock (pclk) and the PHY from its hdmi_phy sibling.
>
> Signed-off-by: Michal Wilczynski <m.wilczynski@samsung.com>
> ---
> .../starfive,jh7110-inno-hdmi-controller.yaml | 109 +++++++++++++++++++++
> 1 file changed, 109 insertions(+)
>
> diff --git a/Documentation/devicetree/bindings/display/bridge/starfive,jh7110-inno-hdmi-controller.yaml b/Documentation/devicetree/bindings/display/bridge/starfive,jh7110-inno-hdmi-controller.yaml
> new file mode 100644
> index 0000000000000000000000000000000000000000..0e584e7b756e24e2f99a62daab3117bbf4b472b6
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/display/bridge/starfive,jh7110-inno-hdmi-controller.yaml
> @@ -0,0 +1,109 @@
> +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
> +%YAML 1.2
> +---
> +$id: http://devicetree.org/schemas/display/bridge/starfive,jh7110-inno-hdmi-controller.yaml#
> +$schema: http://devicetree.org/meta-schemas/core.yaml#
> +
> +title: StarFive JH7110 Innosilicon HDMI Controller
> +
> +maintainers:
> + - Michal Wilczynski <m.wilczynski@samsung.com>
> +
> +description:
> + The controller portion of the StarFive JH7110 INNO HDMI IP.
> +
> +properties:
> + compatible:
> + const: starfive,jh7110-inno-hdmi-controller
> +
> + interrupts:
> + maxItems: 1
> +
> + clocks:
> + items:
> + - description: System clock for register access
> + - description: Module clock
> + - description: Bus clock
> + - description: Pixel clock from PHY
> +
> + clock-names:
> + items:
> + - const: sys
> + - const: mclk
> + - const: bclk
> + - const: pclk
"module" "bus" "pixel" would be more informative than spending most of
your characters regurgitating what these are by definition?
> +
> + resets:
> + maxItems: 1
> +
> + reset-names:
> + const: hdmi_tx
> +
> + phys:
> + maxItems: 1
> +
> + phy-names:
> + const: hdmi-phy
With the trend of ?pointless? -names properties, I'm surprised you don't
have interrupt-names? I'd ditch 'em all where there's only a single
clock. The _ rather than - in the reset name triggers my OCD.
pw-bot: changes-requested
> +
> + ports:
> + $ref: /schemas/graph.yaml#/properties/ports
> + description:
> + A graph node with one input port and one output port.
> +
> +required:
> + - compatible
> + - interrupts
> + - clocks
> + - clock-names
> + - resets
> + - reset-names
> + - phys
> + - phy-names
> + - ports
> +
> +additionalProperties: false
> +
> +examples:
> + # Shown as a child of the HDMI subsystem node; see
> + # Documentation/devicetree/bindings/mfd/starfive,jh7110-hdmi-subsystem.yaml
> + # for the full node.
> + - |
> + #include <dt-bindings/clock/starfive,jh7110-crg.h>
> + #include <dt-bindings/reset/starfive,jh7110-crg.h>
> +
> + controller {
"controller" seems over generic for a node, but I guess if the parent is
"hdmi-subsystem" or something it makes sense in that context.
Cheers,
Conor.
> + compatible = "starfive,jh7110-inno-hdmi-controller";
> + clocks = <&voutcrg JH7110_VOUTCLK_HDMI_TX_SYS>,
> + <&voutcrg JH7110_VOUTCLK_HDMI_TX_MCLK>,
> + <&voutcrg JH7110_VOUTCLK_HDMI_TX_BCLK>,
> + <&hdmi_phy>;
> + clock-names = "sys", "mclk", "bclk", "pclk";
> + interrupts = <99>;
> + phys = <&hdmi_phy>;
> + phy-names = "hdmi-phy";
> + resets = <&voutcrg JH7110_VOUTRST_HDMI_TX_HDMI>;
> + reset-names = "hdmi_tx";
> +
> + ports {
> + #address-cells = <1>;
> + #size-cells = <0>;
> +
> + port@0 {
> + reg = <0>;
> +
> + endpoint {
> + remote-endpoint = <&dpu_out_dpi0>;
> + };
> + };
> +
> + port@1 {
> + reg = <1>;
> +
> + endpoint {
> + remote-endpoint = <&hdmi_con_in>;
> + };
> + };
> + };
> + };
> +
> +...
>
> --
> 2.34.1
>
[-- Attachment #1.2: signature.asc --]
[-- Type: application/pgp-signature, Size: 228 bytes --]
[-- Attachment #2: Type: text/plain, Size: 161 bytes --]
_______________________________________________
linux-riscv mailing list
linux-riscv@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-riscv
^ permalink raw reply [flat|nested] 116+ messages in thread
* Re: [PATCH v2 02/15] dt-bindings: display: bridge: Add starfive,jh7110-inno-hdmi-controller
@ 2026-08-28 16:47 ` Conor Dooley
0 siblings, 0 replies; 116+ messages in thread
From: Conor Dooley @ 2026-08-28 16:47 UTC (permalink / raw)
To: Michal Wilczynski
Cc: Vinod Koul, Neil Armstrong, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Andrzej Hajda, Robert Foss, Laurent Pinchart,
Jonas Karlman, Jernej Skrabec, Luca Ceresoli, David Airlie,
Simona Vetter, Maarten Lankhorst, Maxime Ripard,
Thomas Zimmermann, Lee Jones, Andy Yan, Philipp Zabel,
Emil Renner Berthing, Hal Feng, Michael Turquette, Stephen Boyd,
Brian Masney, Heiko Stuebner, Paul Walmsley, Palmer Dabbelt,
Albert Ou, Alexandre Ghiti, Dominique Belhachemi, linux-phy,
devicetree, linux-kernel, dri-devel, mfd, linux-clk,
linux-arm-kernel, linux-rockchip, linux-riscv, Icenowy Zheng,
Andy Yan, Marek Szyprowski, Maud Spierings, Graham Markall
[-- Attachment #1.1: Type: text/plain, Size: 4484 bytes --]
On Fri, Aug 28, 2026 at 03:47:26PM +0200, Michal Wilczynski wrote:
> Add the dt-binding for the StarFive JH7110 Innosilicon HDMI controller
> (DRM bridge).
>
> This device is the second child of the starfive,jh7110-hdmi-subsystem node.
> It consumes register access clocks (sys, mclk, bclk) from the voutcrg and
> both the pixel clock (pclk) and the PHY from its hdmi_phy sibling.
>
> Signed-off-by: Michal Wilczynski <m.wilczynski@samsung.com>
> ---
> .../starfive,jh7110-inno-hdmi-controller.yaml | 109 +++++++++++++++++++++
> 1 file changed, 109 insertions(+)
>
> diff --git a/Documentation/devicetree/bindings/display/bridge/starfive,jh7110-inno-hdmi-controller.yaml b/Documentation/devicetree/bindings/display/bridge/starfive,jh7110-inno-hdmi-controller.yaml
> new file mode 100644
> index 0000000000000000000000000000000000000000..0e584e7b756e24e2f99a62daab3117bbf4b472b6
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/display/bridge/starfive,jh7110-inno-hdmi-controller.yaml
> @@ -0,0 +1,109 @@
> +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
> +%YAML 1.2
> +---
> +$id: http://devicetree.org/schemas/display/bridge/starfive,jh7110-inno-hdmi-controller.yaml#
> +$schema: http://devicetree.org/meta-schemas/core.yaml#
> +
> +title: StarFive JH7110 Innosilicon HDMI Controller
> +
> +maintainers:
> + - Michal Wilczynski <m.wilczynski@samsung.com>
> +
> +description:
> + The controller portion of the StarFive JH7110 INNO HDMI IP.
> +
> +properties:
> + compatible:
> + const: starfive,jh7110-inno-hdmi-controller
> +
> + interrupts:
> + maxItems: 1
> +
> + clocks:
> + items:
> + - description: System clock for register access
> + - description: Module clock
> + - description: Bus clock
> + - description: Pixel clock from PHY
> +
> + clock-names:
> + items:
> + - const: sys
> + - const: mclk
> + - const: bclk
> + - const: pclk
"module" "bus" "pixel" would be more informative than spending most of
your characters regurgitating what these are by definition?
> +
> + resets:
> + maxItems: 1
> +
> + reset-names:
> + const: hdmi_tx
> +
> + phys:
> + maxItems: 1
> +
> + phy-names:
> + const: hdmi-phy
With the trend of ?pointless? -names properties, I'm surprised you don't
have interrupt-names? I'd ditch 'em all where there's only a single
clock. The _ rather than - in the reset name triggers my OCD.
pw-bot: changes-requested
> +
> + ports:
> + $ref: /schemas/graph.yaml#/properties/ports
> + description:
> + A graph node with one input port and one output port.
> +
> +required:
> + - compatible
> + - interrupts
> + - clocks
> + - clock-names
> + - resets
> + - reset-names
> + - phys
> + - phy-names
> + - ports
> +
> +additionalProperties: false
> +
> +examples:
> + # Shown as a child of the HDMI subsystem node; see
> + # Documentation/devicetree/bindings/mfd/starfive,jh7110-hdmi-subsystem.yaml
> + # for the full node.
> + - |
> + #include <dt-bindings/clock/starfive,jh7110-crg.h>
> + #include <dt-bindings/reset/starfive,jh7110-crg.h>
> +
> + controller {
"controller" seems over generic for a node, but I guess if the parent is
"hdmi-subsystem" or something it makes sense in that context.
Cheers,
Conor.
> + compatible = "starfive,jh7110-inno-hdmi-controller";
> + clocks = <&voutcrg JH7110_VOUTCLK_HDMI_TX_SYS>,
> + <&voutcrg JH7110_VOUTCLK_HDMI_TX_MCLK>,
> + <&voutcrg JH7110_VOUTCLK_HDMI_TX_BCLK>,
> + <&hdmi_phy>;
> + clock-names = "sys", "mclk", "bclk", "pclk";
> + interrupts = <99>;
> + phys = <&hdmi_phy>;
> + phy-names = "hdmi-phy";
> + resets = <&voutcrg JH7110_VOUTRST_HDMI_TX_HDMI>;
> + reset-names = "hdmi_tx";
> +
> + ports {
> + #address-cells = <1>;
> + #size-cells = <0>;
> +
> + port@0 {
> + reg = <0>;
> +
> + endpoint {
> + remote-endpoint = <&dpu_out_dpi0>;
> + };
> + };
> +
> + port@1 {
> + reg = <1>;
> +
> + endpoint {
> + remote-endpoint = <&hdmi_con_in>;
> + };
> + };
> + };
> + };
> +
> +...
>
> --
> 2.34.1
>
[-- Attachment #1.2: signature.asc --]
[-- Type: application/pgp-signature, Size: 228 bytes --]
[-- Attachment #2: Type: text/plain, Size: 170 bytes --]
_______________________________________________
Linux-rockchip mailing list
Linux-rockchip@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-rockchip
^ permalink raw reply [flat|nested] 116+ messages in thread
* Re: [PATCH v2 02/15] dt-bindings: display: bridge: Add starfive,jh7110-inno-hdmi-controller
@ 2026-08-28 16:47 ` Conor Dooley
0 siblings, 0 replies; 116+ messages in thread
From: Conor Dooley @ 2026-08-28 16:47 UTC (permalink / raw)
To: Michal Wilczynski
Cc: Vinod Koul, Neil Armstrong, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Andrzej Hajda, Robert Foss, Laurent Pinchart,
Jonas Karlman, Jernej Skrabec, Luca Ceresoli, David Airlie,
Simona Vetter, Maarten Lankhorst, Maxime Ripard,
Thomas Zimmermann, Lee Jones, Andy Yan, Philipp Zabel,
Emil Renner Berthing, Hal Feng, Michael Turquette, Stephen Boyd,
Brian Masney, Heiko Stuebner, Paul Walmsley, Palmer Dabbelt,
Albert Ou, Alexandre Ghiti, Dominique Belhachemi, linux-phy,
devicetree, linux-kernel, dri-devel, mfd, linux-clk,
linux-arm-kernel, linux-rockchip, linux-riscv, Icenowy Zheng,
Andy Yan, Marek Szyprowski, Maud Spierings, Graham Markall
[-- Attachment #1.1: Type: text/plain, Size: 4484 bytes --]
On Fri, Aug 28, 2026 at 03:47:26PM +0200, Michal Wilczynski wrote:
> Add the dt-binding for the StarFive JH7110 Innosilicon HDMI controller
> (DRM bridge).
>
> This device is the second child of the starfive,jh7110-hdmi-subsystem node.
> It consumes register access clocks (sys, mclk, bclk) from the voutcrg and
> both the pixel clock (pclk) and the PHY from its hdmi_phy sibling.
>
> Signed-off-by: Michal Wilczynski <m.wilczynski@samsung.com>
> ---
> .../starfive,jh7110-inno-hdmi-controller.yaml | 109 +++++++++++++++++++++
> 1 file changed, 109 insertions(+)
>
> diff --git a/Documentation/devicetree/bindings/display/bridge/starfive,jh7110-inno-hdmi-controller.yaml b/Documentation/devicetree/bindings/display/bridge/starfive,jh7110-inno-hdmi-controller.yaml
> new file mode 100644
> index 0000000000000000000000000000000000000000..0e584e7b756e24e2f99a62daab3117bbf4b472b6
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/display/bridge/starfive,jh7110-inno-hdmi-controller.yaml
> @@ -0,0 +1,109 @@
> +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
> +%YAML 1.2
> +---
> +$id: http://devicetree.org/schemas/display/bridge/starfive,jh7110-inno-hdmi-controller.yaml#
> +$schema: http://devicetree.org/meta-schemas/core.yaml#
> +
> +title: StarFive JH7110 Innosilicon HDMI Controller
> +
> +maintainers:
> + - Michal Wilczynski <m.wilczynski@samsung.com>
> +
> +description:
> + The controller portion of the StarFive JH7110 INNO HDMI IP.
> +
> +properties:
> + compatible:
> + const: starfive,jh7110-inno-hdmi-controller
> +
> + interrupts:
> + maxItems: 1
> +
> + clocks:
> + items:
> + - description: System clock for register access
> + - description: Module clock
> + - description: Bus clock
> + - description: Pixel clock from PHY
> +
> + clock-names:
> + items:
> + - const: sys
> + - const: mclk
> + - const: bclk
> + - const: pclk
"module" "bus" "pixel" would be more informative than spending most of
your characters regurgitating what these are by definition?
> +
> + resets:
> + maxItems: 1
> +
> + reset-names:
> + const: hdmi_tx
> +
> + phys:
> + maxItems: 1
> +
> + phy-names:
> + const: hdmi-phy
With the trend of ?pointless? -names properties, I'm surprised you don't
have interrupt-names? I'd ditch 'em all where there's only a single
clock. The _ rather than - in the reset name triggers my OCD.
pw-bot: changes-requested
> +
> + ports:
> + $ref: /schemas/graph.yaml#/properties/ports
> + description:
> + A graph node with one input port and one output port.
> +
> +required:
> + - compatible
> + - interrupts
> + - clocks
> + - clock-names
> + - resets
> + - reset-names
> + - phys
> + - phy-names
> + - ports
> +
> +additionalProperties: false
> +
> +examples:
> + # Shown as a child of the HDMI subsystem node; see
> + # Documentation/devicetree/bindings/mfd/starfive,jh7110-hdmi-subsystem.yaml
> + # for the full node.
> + - |
> + #include <dt-bindings/clock/starfive,jh7110-crg.h>
> + #include <dt-bindings/reset/starfive,jh7110-crg.h>
> +
> + controller {
"controller" seems over generic for a node, but I guess if the parent is
"hdmi-subsystem" or something it makes sense in that context.
Cheers,
Conor.
> + compatible = "starfive,jh7110-inno-hdmi-controller";
> + clocks = <&voutcrg JH7110_VOUTCLK_HDMI_TX_SYS>,
> + <&voutcrg JH7110_VOUTCLK_HDMI_TX_MCLK>,
> + <&voutcrg JH7110_VOUTCLK_HDMI_TX_BCLK>,
> + <&hdmi_phy>;
> + clock-names = "sys", "mclk", "bclk", "pclk";
> + interrupts = <99>;
> + phys = <&hdmi_phy>;
> + phy-names = "hdmi-phy";
> + resets = <&voutcrg JH7110_VOUTRST_HDMI_TX_HDMI>;
> + reset-names = "hdmi_tx";
> +
> + ports {
> + #address-cells = <1>;
> + #size-cells = <0>;
> +
> + port@0 {
> + reg = <0>;
> +
> + endpoint {
> + remote-endpoint = <&dpu_out_dpi0>;
> + };
> + };
> +
> + port@1 {
> + reg = <1>;
> +
> + endpoint {
> + remote-endpoint = <&hdmi_con_in>;
> + };
> + };
> + };
> + };
> +
> +...
>
> --
> 2.34.1
>
[-- Attachment #1.2: signature.asc --]
[-- Type: application/pgp-signature, Size: 228 bytes --]
[-- Attachment #2: Type: text/plain, Size: 112 bytes --]
--
linux-phy mailing list
linux-phy@lists.infradead.org
https://lists.infradead.org/mailman/listinfo/linux-phy
^ permalink raw reply [flat|nested] 116+ messages in thread
* Re: [PATCH v2 03/15] dt-bindings: mfd: Add starfive,jh7110-hdmi-subsystem
2026-08-28 13:47 ` Michal Wilczynski
(?)
(?)
@ 2026-08-28 16:50 ` Conor Dooley
-1 siblings, 0 replies; 116+ messages in thread
From: Conor Dooley @ 2026-08-28 16:50 UTC (permalink / raw)
To: Michal Wilczynski
Cc: Vinod Koul, Neil Armstrong, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Andrzej Hajda, Robert Foss, Laurent Pinchart,
Jonas Karlman, Jernej Skrabec, Luca Ceresoli, David Airlie,
Simona Vetter, Maarten Lankhorst, Maxime Ripard,
Thomas Zimmermann, Lee Jones, Andy Yan, Philipp Zabel,
Emil Renner Berthing, Hal Feng, Michael Turquette, Stephen Boyd,
Brian Masney, Heiko Stuebner, Paul Walmsley, Palmer Dabbelt,
Albert Ou, Alexandre Ghiti, Dominique Belhachemi, linux-phy,
devicetree, linux-kernel, dri-devel, mfd, linux-clk,
linux-arm-kernel, linux-rockchip, linux-riscv, Icenowy Zheng,
Andy Yan, Marek Szyprowski, Maud Spierings, Graham Markall
[-- Attachment #1: Type: text/plain, Size: 5061 bytes --]
On Fri, Aug 28, 2026 at 03:47:27PM +0200, Michal Wilczynski wrote:
> Add the dt-binding for the StarFive JH7110 HDMI subsystem.
>
> The JH7110 HDMI IP is a monolithic block containing both the digital
> controller and analog PHY in a single register space. This binding
> defines the parent device, which holds the shared register map and
> populates its two children: the PHY and the controller. This is
> necessary to resolve a circular clock dependency between the HDMI block
> and the VOUT clock generator.
>
> Signed-off-by: Michal Wilczynski <m.wilczynski@samsung.com>
> ---
> .../mfd/starfive,jh7110-hdmi-subsystem.yaml | 116 +++++++++++++++++++++
> 1 file changed, 116 insertions(+)
>
> diff --git a/Documentation/devicetree/bindings/mfd/starfive,jh7110-hdmi-subsystem.yaml b/Documentation/devicetree/bindings/mfd/starfive,jh7110-hdmi-subsystem.yaml
> new file mode 100644
> index 0000000000000000000000000000000000000000..01f079160ab8c13c6fa4ce3abaac6607021b3792
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/mfd/starfive,jh7110-hdmi-subsystem.yaml
> @@ -0,0 +1,116 @@
> +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
> +%YAML 1.2
> +---
> +$id: http://devicetree.org/schemas/mfd/starfive,jh7110-hdmi-subsystem.yaml#
> +$schema: http://devicetree.org/meta-schemas/core.yaml#
> +
> +title: StarFive JH7110 HDMI subsystem
> +
> +maintainers:
> + - Michal Wilczynski <m.wilczynski@samsung.com>
> +
> +description:
> + The StarFive JH7110 HDMI block is a monolithic IP containing both
> + the digital controller logic and the analog PHY logic in a single
> + register space.
> +
> +properties:
> + compatible:
> + const: starfive,jh7110-hdmi-subsystem
> +
> + reg:
> + maxItems: 1
> +
> + clocks:
> + maxItems: 1
> + description:
> + NoC display bus clock, which gates access to the whole vout
> + register region.
> +
> + resets:
> + maxItems: 1
> + description:
> + NoC display bus reset, which gates access to the whole vout
> + register region.
> +
> + power-domains:
> + maxItems: 1
> +
> +required:
> + - compatible
> + - reg
> + - clocks
> + - resets
> + - power-domains
Here you're willing not to have -names properties?
> +
> +patternProperties:
> + "^phy(@[0-9a-f]+)?$":
These are not pattern properties at all, given they have no variance
because there's no unit addresses involved!
pw-bot: changes-requested
Cheers,
Conor.
> + $ref: /schemas/phy/starfive,jh7110-inno-hdmi-phy.yaml#
> + "^controller(@[0-9a-f]+)?$":
> + $ref: /schemas/display/bridge/starfive,jh7110-inno-hdmi-controller.yaml#
> +
> +additionalProperties: false
> +
> +examples:
> + - |
> + #include <dt-bindings/clock/starfive,jh7110-crg.h>
> + #include <dt-bindings/power/starfive,jh7110-pmu.h>
> + #include <dt-bindings/reset/starfive,jh7110-crg.h>
> +
> + soc {
> + #address-cells = <1>;
> + #size-cells = <1>;
> +
> + hdmi@29590000 {
> + compatible = "starfive,jh7110-hdmi-subsystem";
> + reg = <0x29590000 0x4000>;
> + clocks = <&syscrg JH7110_SYSCLK_NOC_BUS_DISP_AXI>;
> + power-domains = <&pwrc JH7110_PD_VOUT>;
> + resets = <&syscrg JH7110_SYSRST_NOC_BUS_DISP_AXI>;
> +
> + controller {
> + compatible = "starfive,jh7110-inno-hdmi-controller";
> + clocks = <&voutcrg JH7110_VOUTCLK_HDMI_TX_SYS>,
> + <&voutcrg JH7110_VOUTCLK_HDMI_TX_MCLK>,
> + <&voutcrg JH7110_VOUTCLK_HDMI_TX_BCLK>,
> + <&hdmi_phy>;
> + clock-names = "sys", "mclk", "bclk", "pclk";
> + interrupts = <99>;
> + phys = <&hdmi_phy>;
> + phy-names = "hdmi-phy";
> + resets = <&voutcrg JH7110_VOUTRST_HDMI_TX_HDMI>;
> + reset-names = "hdmi_tx";
> +
> + ports {
> + #address-cells = <1>;
> + #size-cells = <0>;
> +
> + port@0 {
> + reg = <0>;
> +
> + endpoint {
> + remote-endpoint = <&dpu_out_dpi0>;
> + };
> + };
> +
> + port@1 {
> + reg = <1>;
> +
> + endpoint {
> + remote-endpoint = <&hdmi_con_in>;
> + };
> + };
> + };
> + };
> +
> + hdmi_phy: phy {
> + compatible = "starfive,jh7110-inno-hdmi-phy";
> + #clock-cells = <0>;
> + clock-output-names = "hdmi_pclk";
> + clocks = <&xin24m>;
> + clock-names = "refoclk";
> + #phy-cells = <0>;
> + };
> + };
> + };
> +...
>
> --
> 2.34.1
>
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 228 bytes --]
^ permalink raw reply [flat|nested] 116+ messages in thread
* Re: [PATCH v2 03/15] dt-bindings: mfd: Add starfive,jh7110-hdmi-subsystem
@ 2026-08-28 16:50 ` Conor Dooley
0 siblings, 0 replies; 116+ messages in thread
From: Conor Dooley @ 2026-08-28 16:50 UTC (permalink / raw)
To: Michal Wilczynski
Cc: Vinod Koul, Neil Armstrong, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Andrzej Hajda, Robert Foss, Laurent Pinchart,
Jonas Karlman, Jernej Skrabec, Luca Ceresoli, David Airlie,
Simona Vetter, Maarten Lankhorst, Maxime Ripard,
Thomas Zimmermann, Lee Jones, Andy Yan, Philipp Zabel,
Emil Renner Berthing, Hal Feng, Michael Turquette, Stephen Boyd,
Brian Masney, Heiko Stuebner, Paul Walmsley, Palmer Dabbelt,
Albert Ou, Alexandre Ghiti, Dominique Belhachemi, linux-phy,
devicetree, linux-kernel, dri-devel, mfd, linux-clk,
linux-arm-kernel, linux-rockchip, linux-riscv, Icenowy Zheng,
Andy Yan, Marek Szyprowski, Maud Spierings, Graham Markall
[-- Attachment #1.1: Type: text/plain, Size: 5061 bytes --]
On Fri, Aug 28, 2026 at 03:47:27PM +0200, Michal Wilczynski wrote:
> Add the dt-binding for the StarFive JH7110 HDMI subsystem.
>
> The JH7110 HDMI IP is a monolithic block containing both the digital
> controller and analog PHY in a single register space. This binding
> defines the parent device, which holds the shared register map and
> populates its two children: the PHY and the controller. This is
> necessary to resolve a circular clock dependency between the HDMI block
> and the VOUT clock generator.
>
> Signed-off-by: Michal Wilczynski <m.wilczynski@samsung.com>
> ---
> .../mfd/starfive,jh7110-hdmi-subsystem.yaml | 116 +++++++++++++++++++++
> 1 file changed, 116 insertions(+)
>
> diff --git a/Documentation/devicetree/bindings/mfd/starfive,jh7110-hdmi-subsystem.yaml b/Documentation/devicetree/bindings/mfd/starfive,jh7110-hdmi-subsystem.yaml
> new file mode 100644
> index 0000000000000000000000000000000000000000..01f079160ab8c13c6fa4ce3abaac6607021b3792
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/mfd/starfive,jh7110-hdmi-subsystem.yaml
> @@ -0,0 +1,116 @@
> +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
> +%YAML 1.2
> +---
> +$id: http://devicetree.org/schemas/mfd/starfive,jh7110-hdmi-subsystem.yaml#
> +$schema: http://devicetree.org/meta-schemas/core.yaml#
> +
> +title: StarFive JH7110 HDMI subsystem
> +
> +maintainers:
> + - Michal Wilczynski <m.wilczynski@samsung.com>
> +
> +description:
> + The StarFive JH7110 HDMI block is a monolithic IP containing both
> + the digital controller logic and the analog PHY logic in a single
> + register space.
> +
> +properties:
> + compatible:
> + const: starfive,jh7110-hdmi-subsystem
> +
> + reg:
> + maxItems: 1
> +
> + clocks:
> + maxItems: 1
> + description:
> + NoC display bus clock, which gates access to the whole vout
> + register region.
> +
> + resets:
> + maxItems: 1
> + description:
> + NoC display bus reset, which gates access to the whole vout
> + register region.
> +
> + power-domains:
> + maxItems: 1
> +
> +required:
> + - compatible
> + - reg
> + - clocks
> + - resets
> + - power-domains
Here you're willing not to have -names properties?
> +
> +patternProperties:
> + "^phy(@[0-9a-f]+)?$":
These are not pattern properties at all, given they have no variance
because there's no unit addresses involved!
pw-bot: changes-requested
Cheers,
Conor.
> + $ref: /schemas/phy/starfive,jh7110-inno-hdmi-phy.yaml#
> + "^controller(@[0-9a-f]+)?$":
> + $ref: /schemas/display/bridge/starfive,jh7110-inno-hdmi-controller.yaml#
> +
> +additionalProperties: false
> +
> +examples:
> + - |
> + #include <dt-bindings/clock/starfive,jh7110-crg.h>
> + #include <dt-bindings/power/starfive,jh7110-pmu.h>
> + #include <dt-bindings/reset/starfive,jh7110-crg.h>
> +
> + soc {
> + #address-cells = <1>;
> + #size-cells = <1>;
> +
> + hdmi@29590000 {
> + compatible = "starfive,jh7110-hdmi-subsystem";
> + reg = <0x29590000 0x4000>;
> + clocks = <&syscrg JH7110_SYSCLK_NOC_BUS_DISP_AXI>;
> + power-domains = <&pwrc JH7110_PD_VOUT>;
> + resets = <&syscrg JH7110_SYSRST_NOC_BUS_DISP_AXI>;
> +
> + controller {
> + compatible = "starfive,jh7110-inno-hdmi-controller";
> + clocks = <&voutcrg JH7110_VOUTCLK_HDMI_TX_SYS>,
> + <&voutcrg JH7110_VOUTCLK_HDMI_TX_MCLK>,
> + <&voutcrg JH7110_VOUTCLK_HDMI_TX_BCLK>,
> + <&hdmi_phy>;
> + clock-names = "sys", "mclk", "bclk", "pclk";
> + interrupts = <99>;
> + phys = <&hdmi_phy>;
> + phy-names = "hdmi-phy";
> + resets = <&voutcrg JH7110_VOUTRST_HDMI_TX_HDMI>;
> + reset-names = "hdmi_tx";
> +
> + ports {
> + #address-cells = <1>;
> + #size-cells = <0>;
> +
> + port@0 {
> + reg = <0>;
> +
> + endpoint {
> + remote-endpoint = <&dpu_out_dpi0>;
> + };
> + };
> +
> + port@1 {
> + reg = <1>;
> +
> + endpoint {
> + remote-endpoint = <&hdmi_con_in>;
> + };
> + };
> + };
> + };
> +
> + hdmi_phy: phy {
> + compatible = "starfive,jh7110-inno-hdmi-phy";
> + #clock-cells = <0>;
> + clock-output-names = "hdmi_pclk";
> + clocks = <&xin24m>;
> + clock-names = "refoclk";
> + #phy-cells = <0>;
> + };
> + };
> + };
> +...
>
> --
> 2.34.1
>
[-- Attachment #1.2: signature.asc --]
[-- Type: application/pgp-signature, Size: 228 bytes --]
[-- Attachment #2: Type: text/plain, Size: 112 bytes --]
--
linux-phy mailing list
linux-phy@lists.infradead.org
https://lists.infradead.org/mailman/listinfo/linux-phy
^ permalink raw reply [flat|nested] 116+ messages in thread
* Re: [PATCH v2 03/15] dt-bindings: mfd: Add starfive,jh7110-hdmi-subsystem
@ 2026-08-28 16:50 ` Conor Dooley
0 siblings, 0 replies; 116+ messages in thread
From: Conor Dooley @ 2026-08-28 16:50 UTC (permalink / raw)
To: Michal Wilczynski
Cc: Emil Renner Berthing, Michael Turquette, dri-devel,
Laurent Pinchart, Andrzej Hajda, linux-phy, linux-riscv,
David Airlie, linux-clk, Heiko Stuebner, Simona Vetter,
Rob Herring, Dominique Belhachemi, Robert Foss, Alexandre Ghiti,
Lee Jones, Andy Yan, Jernej Skrabec, Hal Feng, Graham Markall,
linux-rockchip, Marek Szyprowski, Luca Ceresoli, devicetree,
Conor Dooley, Albert Ou, Philipp Zabel, Jonas Karlman,
Brian Masney, Maarten Lankhorst, Maxime Ripard, mfd,
Paul Walmsley, linux-arm-kernel, Neil Armstrong, Stephen Boyd,
linux-kernel, Maud Spierings, Vinod Koul, Palmer Dabbelt,
Thomas Zimmermann, Andy Yan, Krzysztof Kozlowski
[-- Attachment #1.1: Type: text/plain, Size: 5061 bytes --]
On Fri, Aug 28, 2026 at 03:47:27PM +0200, Michal Wilczynski wrote:
> Add the dt-binding for the StarFive JH7110 HDMI subsystem.
>
> The JH7110 HDMI IP is a monolithic block containing both the digital
> controller and analog PHY in a single register space. This binding
> defines the parent device, which holds the shared register map and
> populates its two children: the PHY and the controller. This is
> necessary to resolve a circular clock dependency between the HDMI block
> and the VOUT clock generator.
>
> Signed-off-by: Michal Wilczynski <m.wilczynski@samsung.com>
> ---
> .../mfd/starfive,jh7110-hdmi-subsystem.yaml | 116 +++++++++++++++++++++
> 1 file changed, 116 insertions(+)
>
> diff --git a/Documentation/devicetree/bindings/mfd/starfive,jh7110-hdmi-subsystem.yaml b/Documentation/devicetree/bindings/mfd/starfive,jh7110-hdmi-subsystem.yaml
> new file mode 100644
> index 0000000000000000000000000000000000000000..01f079160ab8c13c6fa4ce3abaac6607021b3792
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/mfd/starfive,jh7110-hdmi-subsystem.yaml
> @@ -0,0 +1,116 @@
> +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
> +%YAML 1.2
> +---
> +$id: http://devicetree.org/schemas/mfd/starfive,jh7110-hdmi-subsystem.yaml#
> +$schema: http://devicetree.org/meta-schemas/core.yaml#
> +
> +title: StarFive JH7110 HDMI subsystem
> +
> +maintainers:
> + - Michal Wilczynski <m.wilczynski@samsung.com>
> +
> +description:
> + The StarFive JH7110 HDMI block is a monolithic IP containing both
> + the digital controller logic and the analog PHY logic in a single
> + register space.
> +
> +properties:
> + compatible:
> + const: starfive,jh7110-hdmi-subsystem
> +
> + reg:
> + maxItems: 1
> +
> + clocks:
> + maxItems: 1
> + description:
> + NoC display bus clock, which gates access to the whole vout
> + register region.
> +
> + resets:
> + maxItems: 1
> + description:
> + NoC display bus reset, which gates access to the whole vout
> + register region.
> +
> + power-domains:
> + maxItems: 1
> +
> +required:
> + - compatible
> + - reg
> + - clocks
> + - resets
> + - power-domains
Here you're willing not to have -names properties?
> +
> +patternProperties:
> + "^phy(@[0-9a-f]+)?$":
These are not pattern properties at all, given they have no variance
because there's no unit addresses involved!
pw-bot: changes-requested
Cheers,
Conor.
> + $ref: /schemas/phy/starfive,jh7110-inno-hdmi-phy.yaml#
> + "^controller(@[0-9a-f]+)?$":
> + $ref: /schemas/display/bridge/starfive,jh7110-inno-hdmi-controller.yaml#
> +
> +additionalProperties: false
> +
> +examples:
> + - |
> + #include <dt-bindings/clock/starfive,jh7110-crg.h>
> + #include <dt-bindings/power/starfive,jh7110-pmu.h>
> + #include <dt-bindings/reset/starfive,jh7110-crg.h>
> +
> + soc {
> + #address-cells = <1>;
> + #size-cells = <1>;
> +
> + hdmi@29590000 {
> + compatible = "starfive,jh7110-hdmi-subsystem";
> + reg = <0x29590000 0x4000>;
> + clocks = <&syscrg JH7110_SYSCLK_NOC_BUS_DISP_AXI>;
> + power-domains = <&pwrc JH7110_PD_VOUT>;
> + resets = <&syscrg JH7110_SYSRST_NOC_BUS_DISP_AXI>;
> +
> + controller {
> + compatible = "starfive,jh7110-inno-hdmi-controller";
> + clocks = <&voutcrg JH7110_VOUTCLK_HDMI_TX_SYS>,
> + <&voutcrg JH7110_VOUTCLK_HDMI_TX_MCLK>,
> + <&voutcrg JH7110_VOUTCLK_HDMI_TX_BCLK>,
> + <&hdmi_phy>;
> + clock-names = "sys", "mclk", "bclk", "pclk";
> + interrupts = <99>;
> + phys = <&hdmi_phy>;
> + phy-names = "hdmi-phy";
> + resets = <&voutcrg JH7110_VOUTRST_HDMI_TX_HDMI>;
> + reset-names = "hdmi_tx";
> +
> + ports {
> + #address-cells = <1>;
> + #size-cells = <0>;
> +
> + port@0 {
> + reg = <0>;
> +
> + endpoint {
> + remote-endpoint = <&dpu_out_dpi0>;
> + };
> + };
> +
> + port@1 {
> + reg = <1>;
> +
> + endpoint {
> + remote-endpoint = <&hdmi_con_in>;
> + };
> + };
> + };
> + };
> +
> + hdmi_phy: phy {
> + compatible = "starfive,jh7110-inno-hdmi-phy";
> + #clock-cells = <0>;
> + clock-output-names = "hdmi_pclk";
> + clocks = <&xin24m>;
> + clock-names = "refoclk";
> + #phy-cells = <0>;
> + };
> + };
> + };
> +...
>
> --
> 2.34.1
>
[-- Attachment #1.2: signature.asc --]
[-- Type: application/pgp-signature, Size: 228 bytes --]
[-- Attachment #2: Type: text/plain, Size: 161 bytes --]
_______________________________________________
linux-riscv mailing list
linux-riscv@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-riscv
^ permalink raw reply [flat|nested] 116+ messages in thread
* Re: [PATCH v2 03/15] dt-bindings: mfd: Add starfive,jh7110-hdmi-subsystem
@ 2026-08-28 16:50 ` Conor Dooley
0 siblings, 0 replies; 116+ messages in thread
From: Conor Dooley @ 2026-08-28 16:50 UTC (permalink / raw)
To: Michal Wilczynski
Cc: Vinod Koul, Neil Armstrong, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Andrzej Hajda, Robert Foss, Laurent Pinchart,
Jonas Karlman, Jernej Skrabec, Luca Ceresoli, David Airlie,
Simona Vetter, Maarten Lankhorst, Maxime Ripard,
Thomas Zimmermann, Lee Jones, Andy Yan, Philipp Zabel,
Emil Renner Berthing, Hal Feng, Michael Turquette, Stephen Boyd,
Brian Masney, Heiko Stuebner, Paul Walmsley, Palmer Dabbelt,
Albert Ou, Alexandre Ghiti, Dominique Belhachemi, linux-phy,
devicetree, linux-kernel, dri-devel, mfd, linux-clk,
linux-arm-kernel, linux-rockchip, linux-riscv, Icenowy Zheng,
Andy Yan, Marek Szyprowski, Maud Spierings, Graham Markall
[-- Attachment #1.1: Type: text/plain, Size: 5061 bytes --]
On Fri, Aug 28, 2026 at 03:47:27PM +0200, Michal Wilczynski wrote:
> Add the dt-binding for the StarFive JH7110 HDMI subsystem.
>
> The JH7110 HDMI IP is a monolithic block containing both the digital
> controller and analog PHY in a single register space. This binding
> defines the parent device, which holds the shared register map and
> populates its two children: the PHY and the controller. This is
> necessary to resolve a circular clock dependency between the HDMI block
> and the VOUT clock generator.
>
> Signed-off-by: Michal Wilczynski <m.wilczynski@samsung.com>
> ---
> .../mfd/starfive,jh7110-hdmi-subsystem.yaml | 116 +++++++++++++++++++++
> 1 file changed, 116 insertions(+)
>
> diff --git a/Documentation/devicetree/bindings/mfd/starfive,jh7110-hdmi-subsystem.yaml b/Documentation/devicetree/bindings/mfd/starfive,jh7110-hdmi-subsystem.yaml
> new file mode 100644
> index 0000000000000000000000000000000000000000..01f079160ab8c13c6fa4ce3abaac6607021b3792
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/mfd/starfive,jh7110-hdmi-subsystem.yaml
> @@ -0,0 +1,116 @@
> +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
> +%YAML 1.2
> +---
> +$id: http://devicetree.org/schemas/mfd/starfive,jh7110-hdmi-subsystem.yaml#
> +$schema: http://devicetree.org/meta-schemas/core.yaml#
> +
> +title: StarFive JH7110 HDMI subsystem
> +
> +maintainers:
> + - Michal Wilczynski <m.wilczynski@samsung.com>
> +
> +description:
> + The StarFive JH7110 HDMI block is a monolithic IP containing both
> + the digital controller logic and the analog PHY logic in a single
> + register space.
> +
> +properties:
> + compatible:
> + const: starfive,jh7110-hdmi-subsystem
> +
> + reg:
> + maxItems: 1
> +
> + clocks:
> + maxItems: 1
> + description:
> + NoC display bus clock, which gates access to the whole vout
> + register region.
> +
> + resets:
> + maxItems: 1
> + description:
> + NoC display bus reset, which gates access to the whole vout
> + register region.
> +
> + power-domains:
> + maxItems: 1
> +
> +required:
> + - compatible
> + - reg
> + - clocks
> + - resets
> + - power-domains
Here you're willing not to have -names properties?
> +
> +patternProperties:
> + "^phy(@[0-9a-f]+)?$":
These are not pattern properties at all, given they have no variance
because there's no unit addresses involved!
pw-bot: changes-requested
Cheers,
Conor.
> + $ref: /schemas/phy/starfive,jh7110-inno-hdmi-phy.yaml#
> + "^controller(@[0-9a-f]+)?$":
> + $ref: /schemas/display/bridge/starfive,jh7110-inno-hdmi-controller.yaml#
> +
> +additionalProperties: false
> +
> +examples:
> + - |
> + #include <dt-bindings/clock/starfive,jh7110-crg.h>
> + #include <dt-bindings/power/starfive,jh7110-pmu.h>
> + #include <dt-bindings/reset/starfive,jh7110-crg.h>
> +
> + soc {
> + #address-cells = <1>;
> + #size-cells = <1>;
> +
> + hdmi@29590000 {
> + compatible = "starfive,jh7110-hdmi-subsystem";
> + reg = <0x29590000 0x4000>;
> + clocks = <&syscrg JH7110_SYSCLK_NOC_BUS_DISP_AXI>;
> + power-domains = <&pwrc JH7110_PD_VOUT>;
> + resets = <&syscrg JH7110_SYSRST_NOC_BUS_DISP_AXI>;
> +
> + controller {
> + compatible = "starfive,jh7110-inno-hdmi-controller";
> + clocks = <&voutcrg JH7110_VOUTCLK_HDMI_TX_SYS>,
> + <&voutcrg JH7110_VOUTCLK_HDMI_TX_MCLK>,
> + <&voutcrg JH7110_VOUTCLK_HDMI_TX_BCLK>,
> + <&hdmi_phy>;
> + clock-names = "sys", "mclk", "bclk", "pclk";
> + interrupts = <99>;
> + phys = <&hdmi_phy>;
> + phy-names = "hdmi-phy";
> + resets = <&voutcrg JH7110_VOUTRST_HDMI_TX_HDMI>;
> + reset-names = "hdmi_tx";
> +
> + ports {
> + #address-cells = <1>;
> + #size-cells = <0>;
> +
> + port@0 {
> + reg = <0>;
> +
> + endpoint {
> + remote-endpoint = <&dpu_out_dpi0>;
> + };
> + };
> +
> + port@1 {
> + reg = <1>;
> +
> + endpoint {
> + remote-endpoint = <&hdmi_con_in>;
> + };
> + };
> + };
> + };
> +
> + hdmi_phy: phy {
> + compatible = "starfive,jh7110-inno-hdmi-phy";
> + #clock-cells = <0>;
> + clock-output-names = "hdmi_pclk";
> + clocks = <&xin24m>;
> + clock-names = "refoclk";
> + #phy-cells = <0>;
> + };
> + };
> + };
> +...
>
> --
> 2.34.1
>
[-- Attachment #1.2: signature.asc --]
[-- Type: application/pgp-signature, Size: 228 bytes --]
[-- Attachment #2: Type: text/plain, Size: 170 bytes --]
_______________________________________________
Linux-rockchip mailing list
Linux-rockchip@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-rockchip
^ permalink raw reply [flat|nested] 116+ messages in thread
end of thread, other threads:[~2026-08-28 16:50 UTC | newest]
Thread overview: 116+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
[not found] <CGME20260828134813eucas1p1bd003a66706ed251017185fc14f13cc9@eucas1p1.samsung.com>
2026-08-28 13:47 ` [PATCH v2 00/15] drm: starfive: jh7110: Enable display subsystem Michal Wilczynski
2026-08-28 13:47 ` Michal Wilczynski
2026-08-28 13:47 ` Michal Wilczynski
2026-08-28 13:47 ` Michal Wilczynski
2026-08-28 13:47 ` [PATCH v2 01/15] dt-bindings: phy: Add starfive,jh7110-inno-hdmi-phy Michal Wilczynski
2026-08-28 13:47 ` Michal Wilczynski
2026-08-28 13:47 ` Michal Wilczynski
2026-08-28 13:47 ` Michal Wilczynski
2026-08-28 13:54 ` sashiko-bot
2026-08-28 13:54 ` sashiko-bot
2026-08-28 16:43 ` Conor Dooley
2026-08-28 16:43 ` Conor Dooley
2026-08-28 16:43 ` Conor Dooley
2026-08-28 16:43 ` Conor Dooley
2026-08-28 13:47 ` [PATCH v2 02/15] dt-bindings: display: bridge: Add starfive,jh7110-inno-hdmi-controller Michal Wilczynski
2026-08-28 13:47 ` Michal Wilczynski
2026-08-28 13:47 ` Michal Wilczynski
2026-08-28 13:47 ` Michal Wilczynski
2026-08-28 13:54 ` sashiko-bot
2026-08-28 13:54 ` sashiko-bot
2026-08-28 14:04 ` Icenowy Zheng
2026-08-28 14:04 ` Icenowy Zheng
2026-08-28 14:04 ` Icenowy Zheng
2026-08-28 14:04 ` Icenowy Zheng
2026-08-28 16:47 ` Conor Dooley
2026-08-28 16:47 ` Conor Dooley
2026-08-28 16:47 ` Conor Dooley
2026-08-28 16:47 ` Conor Dooley
2026-08-28 13:47 ` [PATCH v2 03/15] dt-bindings: mfd: Add starfive,jh7110-hdmi-subsystem Michal Wilczynski
2026-08-28 13:47 ` Michal Wilczynski
2026-08-28 13:47 ` Michal Wilczynski
2026-08-28 13:47 ` Michal Wilczynski
2026-08-28 13:54 ` sashiko-bot
2026-08-28 13:54 ` sashiko-bot
2026-08-28 16:50 ` Conor Dooley
2026-08-28 16:50 ` Conor Dooley
2026-08-28 16:50 ` Conor Dooley
2026-08-28 16:50 ` Conor Dooley
2026-08-28 13:47 ` [PATCH v2 04/15] drm/bridge: inno-hdmi: Split probe out of bind Michal Wilczynski
2026-08-28 13:47 ` Michal Wilczynski
2026-08-28 13:47 ` Michal Wilczynski
2026-08-28 13:47 ` Michal Wilczynski
2026-08-28 14:01 ` sashiko-bot
2026-08-28 14:01 ` sashiko-bot
2026-08-28 13:47 ` [PATCH v2 05/15] drm/bridge: inno-hdmi: Allow the register map to come from a parent Michal Wilczynski
2026-08-28 13:47 ` Michal Wilczynski
2026-08-28 13:47 ` Michal Wilczynski
2026-08-28 13:47 ` Michal Wilczynski
2026-08-28 13:54 ` sashiko-bot
2026-08-28 13:54 ` sashiko-bot
2026-08-28 13:47 ` [PATCH v2 06/15] drm/bridge: inno-hdmi: Add .disable platform operation Michal Wilczynski
2026-08-28 13:47 ` Michal Wilczynski
2026-08-28 13:47 ` Michal Wilczynski
2026-08-28 13:47 ` Michal Wilczynski
2026-08-28 13:57 ` sashiko-bot
2026-08-28 13:57 ` sashiko-bot
2026-08-28 13:47 ` [PATCH v2 07/15] drm/bridge: inno-hdmi: Add .mode_valid " Michal Wilczynski
2026-08-28 13:47 ` Michal Wilczynski
2026-08-28 13:47 ` Michal Wilczynski
2026-08-28 13:47 ` Michal Wilczynski
2026-08-28 13:52 ` sashiko-bot
2026-08-28 13:52 ` sashiko-bot
2026-08-28 13:47 ` [PATCH v2 08/15] soc: starfive: Add jh7110-hdmi-subsystem driver Michal Wilczynski
2026-08-28 13:47 ` Michal Wilczynski
2026-08-28 13:47 ` Michal Wilczynski
2026-08-28 13:47 ` Michal Wilczynski
2026-08-28 13:59 ` sashiko-bot
2026-08-28 13:59 ` sashiko-bot
2026-08-28 13:47 ` [PATCH v2 09/15] clk: starfive: jh7110-vout: Allow pixel clock rate propagation Michal Wilczynski
2026-08-28 13:47 ` Michal Wilczynski
2026-08-28 13:47 ` Michal Wilczynski
2026-08-28 13:47 ` Michal Wilczynski
2026-08-28 14:01 ` sashiko-bot
2026-08-28 14:01 ` sashiko-bot
2026-08-28 13:47 ` [PATCH v2 10/15] drm/bridge: starfive: Add JH7110 HDMI controller driver Michal Wilczynski
2026-08-28 13:47 ` Michal Wilczynski
2026-08-28 13:47 ` Michal Wilczynski
2026-08-28 13:47 ` Michal Wilczynski
2026-08-28 13:59 ` sashiko-bot
2026-08-28 13:59 ` sashiko-bot
2026-08-28 13:47 ` [PATCH v2 11/15] phy: Add common Innosilicon HDMI PHY helpers Michal Wilczynski
2026-08-28 13:47 ` Michal Wilczynski
2026-08-28 13:47 ` Michal Wilczynski
2026-08-28 13:47 ` Michal Wilczynski
2026-08-28 14:00 ` sashiko-bot
2026-08-28 14:00 ` sashiko-bot
2026-08-28 13:47 ` [PATCH v2 12/15] phy: rockchip: inno-hdmi: Use the common Innosilicon " Michal Wilczynski
2026-08-28 13:47 ` Michal Wilczynski
2026-08-28 13:47 ` Michal Wilczynski
2026-08-28 13:47 ` Michal Wilczynski
2026-08-28 14:12 ` sashiko-bot
2026-08-28 14:12 ` sashiko-bot
2026-08-28 13:47 ` [PATCH v2 13/15] phy: starfive: Add jh7110-inno-hdmi-phy driver Michal Wilczynski
2026-08-28 13:47 ` Michal Wilczynski
2026-08-28 13:47 ` Michal Wilczynski
2026-08-28 13:47 ` Michal Wilczynski
2026-08-28 14:04 ` sashiko-bot
2026-08-28 14:04 ` sashiko-bot
2026-08-28 13:47 ` [PATCH v2 14/15] riscv: dts: starfive: jh7110: Update DT for display subsystem Michal Wilczynski
2026-08-28 13:47 ` Michal Wilczynski
2026-08-28 13:47 ` Michal Wilczynski
2026-08-28 13:47 ` Michal Wilczynski
2026-08-28 14:06 ` sashiko-bot
2026-08-28 14:06 ` sashiko-bot
2026-08-28 14:06 ` Icenowy Zheng
2026-08-28 14:06 ` Icenowy Zheng
2026-08-28 14:06 ` Icenowy Zheng
2026-08-28 14:06 ` Icenowy Zheng
2026-08-28 13:47 ` [PATCH v2 15/15] MAINTAINERS: Add StarFive JH7110 display subsystem entry Michal Wilczynski
2026-08-28 13:47 ` Michal Wilczynski
2026-08-28 13:47 ` Michal Wilczynski
2026-08-28 13:47 ` Michal Wilczynski
2026-08-28 14:01 ` Icenowy Zheng
2026-08-28 14:01 ` Icenowy Zheng
2026-08-28 14:01 ` Icenowy Zheng
2026-08-28 14:01 ` Icenowy Zheng
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.