[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-Id: <20251108-jh7110-clean-send-v1-6-06bf43bb76b1@samsung.com>
Date: Sat, 08 Nov 2025 02:04:40 +0100
From: Michal Wilczynski <m.wilczynski@...sung.com>
To: Michal Wilczynski <m.wilczynski@...sung.com>, Conor Dooley
<conor@...nel.org>, Rob Herring <robh@...nel.org>, Krzysztof Kozlowski
<krzk+dt@...nel.org>, Emil Renner Berthing <kernel@...il.dk>, Hal Feng
<hal.feng@...rfivetech.com>, Michael Turquette <mturquette@...libre.com>,
Stephen Boyd <sboyd@...nel.org>, Conor Dooley <conor+dt@...nel.org>, Xingyu
Wu <xingyu.wu@...rfivetech.com>, Vinod Koul <vkoul@...nel.org>, Kishon
Vijay Abraham I <kishon@...nel.org>, Andrzej Hajda
<andrzej.hajda@...el.com>, Neil Armstrong <neil.armstrong@...aro.org>,
Robert Foss <rfoss@...nel.org>, Laurent Pinchart
<Laurent.pinchart@...asonboard.com>, Jonas Karlman <jonas@...boo.se>,
Jernej Skrabec <jernej.skrabec@...il.com>, David Airlie
<airlied@...il.com>, Simona Vetter <simona@...ll.ch>, Maarten Lankhorst
<maarten.lankhorst@...ux.intel.com>, Maxime Ripard <mripard@...nel.org>,
Thomas Zimmermann <tzimmermann@...e.de>, Lee Jones <lee@...nel.org>,
Philipp Zabel <p.zabel@...gutronix.de>, Paul Walmsley
<paul.walmsley@...ive.com>, Palmer Dabbelt <palmer@...belt.com>, Albert Ou
<aou@...s.berkeley.edu>, Alexandre Ghiti <alex@...ti.fr>, Marek Szyprowski
<m.szyprowski@...sung.com>, Icenowy Zheng <uwu@...nowy.me>, Maud Spierings
<maudspierings@...ontroll.com>, Andy Yan <andyshrk@....com>, Heiko Stuebner
<heiko@...ech.de>
Cc: devicetree@...r.kernel.org, linux-kernel@...r.kernel.org,
linux-clk@...r.kernel.org, linux-phy@...ts.infradead.org,
dri-devel@...ts.freedesktop.org, linux-riscv@...ts.infradead.org
Subject: [PATCH RFC 06/13] drm: bridge: inno_hdmi: Refactor to support
regmap and probe
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@...sung.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
Powered by blists - more mailing lists