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 <[email protected]>
---
 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

Reply via email to