[PATCH RFC 06/13] drm: bridge: inno_hdmi: Refactor to support regmap and probe
Michal Wilczynski
m.wilczynski at samsung.com
Fri Nov 7 17:04:40 PST 2025
Refactor the Innosilicon HDMI bridge driver into a library
to support being called by MFD (Multi-Function Device) drivers.
This is necessary for platforms like the StarFive JH7110, where
the HDMI controller and PHY are part of a monolithic MFD block.
This patch makes the following changes:
- The core probing logic is moved into a new exported function,
inno_hdmi_probe().
- A corresponding exported inno_hdmi_remove() is added.
- The existing inno_hdmi_bind() function is updated to use the
new inno_hdmi_probe() helper.
- The driver now supports retrieving a shared regmap from a parent
device, falling back to ioremap if one is not found.
- The struct inno_hdmi definition is moved to a public header
(include/drm/bridge/inno_hdmi.h) to be accessible by other
drivers.
Signed-off-by: Michal Wilczynski <m.wilczynski at samsung.com>
---
drivers/gpu/drm/bridge/inno-hdmi.c | 99 +++++++++++++++++++++++++++-----------
include/drm/bridge/inno_hdmi.h | 25 +++++++++-
2 files changed, 96 insertions(+), 28 deletions(-)
diff --git a/drivers/gpu/drm/bridge/inno-hdmi.c b/drivers/gpu/drm/bridge/inno-hdmi.c
index e46ee4d85044f18407aaa624b4e3dd1a6c5af5cb..9a2370ed2f208caf3dafb4a4d8884516d489263c 100644
--- a/drivers/gpu/drm/bridge/inno-hdmi.c
+++ b/drivers/gpu/drm/bridge/inno-hdmi.c
@@ -395,12 +395,6 @@ enum inno_hdmi_dev_type {
RK3128_HDMI,
};
-struct inno_hdmi_phy_config {
- unsigned long pixelclock;
- u8 pre_emphasis;
- u8 voltage_level_control;
-};
-
struct inno_hdmi_variant {
enum inno_hdmi_dev_type dev_type;
struct inno_hdmi_phy_config *phy_configs;
@@ -417,19 +411,6 @@ struct inno_hdmi_i2c {
struct completion cmp;
};
-struct inno_hdmi {
- struct device *dev;
- struct drm_bridge bridge;
- struct clk *pclk;
- struct clk *refclk;
- void __iomem *regs;
- struct regmap *grf;
-
- struct inno_hdmi_i2c *i2c;
- struct i2c_adapter *ddc;
- const struct inno_hdmi_plat_data *plat_data;
-};
-
enum {
CSC_RGB_0_255_TO_ITU601_16_235_8BIT,
CSC_RGB_0_255_TO_ITU709_16_235_8BIT,
@@ -496,11 +477,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);
}
@@ -1082,11 +1075,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;
@@ -1103,9 +1109,21 @@ struct inno_hdmi *inno_hdmi_bind(struct device *dev,
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);
+ /*
+ * MFD Support: Check if parent provides a regmap.
+ * If so, use it. Otherwise, fall back to ioremap.
+ */
+ if (dev->parent)
+ hdmi->regmap = dev_get_regmap(dev->parent, NULL);
+
+ if (hdmi->regmap) {
+ dev_info(dev, "Using MFD regmap for registers\n");
+ } else {
+ dev_info(dev, "Falling back to ioremap for registers\n");
+ 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)) {
@@ -1149,7 +1167,34 @@ 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);
+
+/**
+ * inno_hdmi_remove - Remove a bridge created by inno_hdmi_probe
+ * @hdmi: The inno_hdmi instance to remove
+ */
+void inno_hdmi_remove(struct inno_hdmi *hdmi)
+{
+ drm_bridge_remove(&hdmi->bridge);
+}
+EXPORT_SYMBOL_GPL(inno_hdmi_remove);
+
+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 8b39655212e247d9ca7b1f220f970df1fb6afe13..019680622324197e046a1c606ec25aabe95537b4 100644
--- a/include/drm/bridge/inno_hdmi.h
+++ b/include/drm/bridge/inno_hdmi.h
@@ -6,10 +6,13 @@
#ifndef __INNO_HDMI__
#define __INNO_HDMI__
+#include <drm/drm_bridge.h>
+
struct device;
struct drm_encoder;
struct drm_display_mode;
-struct inno_hdmi;
+struct i2c_adapter;
+struct inno_hdmi_i2c;
struct inno_hdmi_plat_ops {
void (*enable)(struct device *pdev, struct drm_display_mode *mode);
@@ -27,7 +30,27 @@ struct inno_hdmi_plat_data {
struct inno_hdmi_phy_config *default_phy_config;
};
+struct inno_hdmi {
+ struct device *dev;
+ struct drm_bridge bridge;
+ struct clk *pclk;
+ struct clk *refclk;
+ void __iomem *regs;
+ struct regmap *regmap;
+ struct regmap *grf;
+
+ struct i2c_adapter *ddc;
+ struct inno_hdmi_i2c *i2c;
+ const struct inno_hdmi_plat_data *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);
+
+void inno_hdmi_remove(struct inno_hdmi *hdmi);
+
#endif /* __INNO_HDMI__ */
--
2.34.1
More information about the linux-riscv
mailing list