[PATCH v2 07/15] drm/bridge: inno-hdmi: Add .mode_valid platform operation
From: Michal Wilczynski
Date: Fri Aug 28 2026 - 09:52:06 EST
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@xxxxxxxxxxx>
---
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