[PATCH v2 07/15] drm/bridge: inno-hdmi: Add .mode_valid platform operation
Michal Wilczynski <[email protected]>
| Newsgroups | org.infradead.lists.linux-riscv,dev.linux.lists.mfd,org.freedesktop.lists.dri-devel,org.infradead.lists.linux-arm-kernel,org.infradead.lists.linux-phy,org.infradead.lists.linux-rockchip,org.kernel.vger.linux-clk,org.kernel.vger.linux-devicetree,org.kernel.vger.linux-kernel |
|---|---|
| Message-ID | <[email protected]> |
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 <[email protected]> --- 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 [email protected] http://lists.infradead.org/mailman/listinfo/linux-riscv