From f7f5ec54b815df2c9a92f0fd6edea4f5d0700937 Mon Sep 17 00:00:00 2001
From: Sandor Yu <Sandor.yu@nxp.com>
Date: Mon, 16 Nov 2020 10:56:44 +0800
Subject: [PATCH 17/49] MLK-24081-03: drm: bridge: cdns-cec: support hdmi rx
 cec

Create struct cdns_mhdp_cec and cec specific bus_read/write function.
CEC driver could be reuse by hdmi rx.

Signed-off-by: Sandor Yu <Sandor.yu@nxp.com>
Reviewed-by: Robby Cai <robby.cai@nxp.com>
---
 drivers/gpu/drm/bridge/cadence/Kconfig        |  1 -
 .../gpu/drm/bridge/cadence/cdns-hdmi-core.c   | 18 ++++-
 .../gpu/drm/bridge/cadence/cdns-mhdp-cec.c    | 66 +++++++++++++------
 .../gpu/drm/bridge/cadence/cdns-mhdp-common.c |  6 --
 include/drm/bridge/cdns-mhdp.h                | 19 +++---
 5 files changed, 72 insertions(+), 38 deletions(-)

diff --git a/drivers/gpu/drm/bridge/cadence/Kconfig b/drivers/gpu/drm/bridge/cadence/Kconfig
index bb1865b15aca..c271ab24a99a 100644
--- a/drivers/gpu/drm/bridge/cadence/Kconfig
+++ b/drivers/gpu/drm/bridge/cadence/Kconfig
@@ -45,6 +45,5 @@ config DRM_CDNS_AUDIO
 
 config DRM_CDNS_HDMI_CEC
 	tristate "Cadence MHDP HDMI CEC driver"
-	depends on DRM_CDNS_HDMI
 	select CEC_CORE
 	select CEC_NOTIFIER
diff --git a/drivers/gpu/drm/bridge/cadence/cdns-hdmi-core.c b/drivers/gpu/drm/bridge/cadence/cdns-hdmi-core.c
index e796c2c0e895..84c175997740 100644
--- a/drivers/gpu/drm/bridge/cadence/cdns-hdmi-core.c
+++ b/drivers/gpu/drm/bridge/cadence/cdns-hdmi-core.c
@@ -569,6 +569,19 @@ static void cdns_hdmi_parse_dt(struct cdns_mhdp_device *mhdp)
 	dev_info(mhdp->dev, "lane-mapping 0x%02x\n", mhdp->lane_mapping);
 }
 
+#ifdef CONFIG_DRM_CDNS_HDMI_CEC
+static void cdns_mhdp_cec_init(struct cdns_mhdp_device *mhdp)
+{
+	struct cdns_mhdp_cec *cec = &mhdp->hdmi.cec;
+
+	cec->dev = mhdp->dev;
+	cec->iolock = &mhdp->iolock;
+	cec->regs_base = mhdp->regs_base;
+	cec->regs_sec = mhdp->regs_sec;
+	cec->bus_type = mhdp->bus_type;
+}
+#endif
+
 static int __cdns_hdmi_probe(struct platform_device *pdev,
 		  struct cdns_mhdp_device *mhdp)
 {
@@ -669,7 +682,8 @@ static int __cdns_hdmi_probe(struct platform_device *pdev,
 
 	/* register cec driver */
 #ifdef CONFIG_DRM_CDNS_HDMI_CEC
-	cdns_mhdp_register_cec_driver(dev);
+	cdns_mhdp_cec_init(mhdp);
+	cdns_mhdp_register_cec_driver(&mhdp->hdmi.cec);
 #endif
 
 	return 0;
@@ -679,7 +693,7 @@ static void __cdns_hdmi_remove(struct cdns_mhdp_device *mhdp)
 {
 	/* unregister cec driver */
 #ifdef CONFIG_DRM_CDNS_HDMI_CEC
-	cdns_mhdp_unregister_cec_driver(mhdp->dev);
+	cdns_mhdp_unregister_cec_driver(&mhdp->hdmi.cec);
 #endif
 	cdns_mhdp_unregister_audio_driver(mhdp->dev);
 }
diff --git a/drivers/gpu/drm/bridge/cadence/cdns-mhdp-cec.c b/drivers/gpu/drm/bridge/cadence/cdns-mhdp-cec.c
index 029ad761606a..25cf9e91e64f 100644
--- a/drivers/gpu/drm/bridge/cadence/cdns-mhdp-cec.c
+++ b/drivers/gpu/drm/bridge/cadence/cdns-mhdp-cec.c
@@ -1,5 +1,5 @@
 /*
- * Copyright 2019 NXP
+ * Copyright 2019-2020 NXP
  *
  * This program is free software; you can redistribute it and/or
  * modify it under the terms of the GNU General Public License
@@ -74,16 +74,49 @@ enum {
 
 static u32 mhdp_cec_read(struct cdns_mhdp_cec *cec, u32 offset)
 {
-	struct cdns_mhdp_device *mhdp =
-			container_of(cec, struct cdns_mhdp_device, hdmi.cec);
-	return cdns_mhdp_bus_read(mhdp, offset);
+	u32 val;
+
+	mutex_lock(cec->iolock);
+
+	if (cec->bus_type == BUS_TYPE_LOW4K_HDMI_RX) {
+		/* Remap address to low 4K HDMI RX */
+		writel(offset >> 12, cec->regs_sec + 4);
+		val = readl((offset & 0xfff) + cec->regs_base);
+	} else if (cec->bus_type == BUS_TYPE_LOW4K_APB) {
+		/* Remap address to low 4K memory */
+		writel(offset >> 12, cec->regs_sec + 8);
+		val = readl((offset & 0xfff) + cec->regs_base);
+	} else
+		val = readl(cec->regs_base + offset);
+
+	mutex_unlock(cec->iolock);
+
+	return val;
 }
 
 static void mhdp_cec_write(struct cdns_mhdp_cec *cec, u32 offset, u32 val)
 {
-	struct cdns_mhdp_device *mhdp =
-			container_of(cec, struct cdns_mhdp_device, hdmi.cec);
-	cdns_mhdp_bus_write(val, mhdp, offset);
+	mutex_lock(cec->iolock);
+
+	if (cec->bus_type == BUS_TYPE_LOW4K_HDMI_RX) {
+		/* Remap address to low 4K SAPB bus */
+		writel(offset >> 12, cec->regs_sec + 4);
+		writel(val, (offset & 0xfff) + cec->regs_base);
+	} else if (cec->bus_type == BUS_TYPE_LOW4K_APB) {
+		/* Remap address to low 4K memory */
+		writel(offset >> 12, cec->regs_sec + 8);
+		writel(val, (offset & 0xfff) + cec->regs_base);
+	} else if (cec->bus_type == BUS_TYPE_NORMAL_SAPB)
+		writel(val, cec->regs_sec + offset);
+	else
+		writel(val, cec->regs_base + offset);
+
+	mutex_unlock(cec->iolock);
+}
+
+static u32 mhdp_get_fw_clk(struct cdns_mhdp_cec *cec)
+{
+	return mhdp_cec_read(cec, SW_CLK_H);
 }
 
 static void mhdp_cec_clear_rx_buffer(struct cdns_mhdp_cec *cec)
@@ -94,12 +127,10 @@ static void mhdp_cec_clear_rx_buffer(struct cdns_mhdp_cec *cec)
 
 static void mhdp_cec_set_divider(struct cdns_mhdp_cec *cec)
 {
-	struct cdns_mhdp_device *mhdp =
-			container_of(cec, struct cdns_mhdp_device, hdmi.cec);
 	u32 clk_div;
 
 	/* Set clock divider */
-	clk_div = cdns_mhdp_get_fw_clk(mhdp) * 10;
+	clk_div = mhdp_get_fw_clk(cec) * 10;
 
 	mhdp_cec_write(cec, CLK_DIV_MSB,
 			  (clk_div >> 8) & 0xFF);
@@ -291,10 +322,8 @@ static const struct cec_adap_ops cdns_mhdp_cec_adap_ops = {
 	.adap_transmit = mhdp_cec_adap_transmit,
 };
 
-int cdns_mhdp_register_cec_driver(struct device *dev)
+int cdns_mhdp_register_cec_driver(struct cdns_mhdp_cec *cec)
 {
-	struct cdns_mhdp_device *mhdp = dev_get_drvdata(dev);
-	struct cdns_mhdp_cec *cec = &mhdp->hdmi.cec;
 	int ret;
 
 	cec->adap = cec_allocate_adapter(&cdns_mhdp_cec_adap_ops, cec,
@@ -305,29 +334,24 @@ int cdns_mhdp_register_cec_driver(struct device *dev)
 	ret = PTR_ERR_OR_ZERO(cec->adap);
 	if (ret)
 		return ret;
-	ret = cec_register_adapter(cec->adap, dev);
+	ret = cec_register_adapter(cec->adap, cec->dev);
 	if (ret) {
 		cec_delete_adapter(cec->adap);
 		return ret;
 	}
 
-	cec->dev = dev;
-
 	cec->cec_worker = kthread_create(mhdp_cec_poll_worker, cec, "cdns-mhdp-cec");
 	if (IS_ERR(cec->cec_worker))
 		dev_err(cec->dev, "failed  create hdp cec thread\n");
 
 	wake_up_process(cec->cec_worker);
 
-	dev_dbg(dev, "CEC successfuly probed\n");
+	dev_dbg(cec->dev, "CEC successfuly probed\n");
 	return 0;
 }
 
-int cdns_mhdp_unregister_cec_driver(struct device *dev)
+int cdns_mhdp_unregister_cec_driver(struct cdns_mhdp_cec *cec)
 {
-	struct cdns_mhdp_device *mhdp = dev_get_drvdata(dev);
-	struct cdns_mhdp_cec *cec = &mhdp->hdmi.cec;
-
 	if (cec->cec_worker) {
 		kthread_stop(cec->cec_worker);
 		cec->cec_worker = NULL;
diff --git a/drivers/gpu/drm/bridge/cadence/cdns-mhdp-common.c b/drivers/gpu/drm/bridge/cadence/cdns-mhdp-common.c
index 2043016f176b..ff37cc4e57e6 100644
--- a/drivers/gpu/drm/bridge/cadence/cdns-mhdp-common.c
+++ b/drivers/gpu/drm/bridge/cadence/cdns-mhdp-common.c
@@ -99,12 +99,6 @@ void cdns_mhdp_bus_write(u32 val, struct cdns_mhdp_device *mhdp, u32 offset)
 }
 EXPORT_SYMBOL(cdns_mhdp_bus_write);
 
-u32 cdns_mhdp_get_fw_clk(struct cdns_mhdp_device *mhdp)
-{
-	return cdns_mhdp_bus_read(mhdp, SW_CLK_H);
-}
-EXPORT_SYMBOL(cdns_mhdp_get_fw_clk);
-
 void cdns_mhdp_set_fw_clk(struct cdns_mhdp_device *mhdp, unsigned long clk)
 {
 	cdns_mhdp_bus_write(clk / 1000000, mhdp, SW_CLK_H);
diff --git a/include/drm/bridge/cdns-mhdp.h b/include/drm/bridge/cdns-mhdp.h
index 6bfd82a3d9a2..338fa55b8bdf 100644
--- a/include/drm/bridge/cdns-mhdp.h
+++ b/include/drm/bridge/cdns-mhdp.h
@@ -509,6 +509,7 @@ enum {
 	BUS_TYPE_NORMAL_SAPB = 1,
 	BUS_TYPE_LOW4K_APB = 2,
 	BUS_TYPE_LOW4K_SAPB = 3,
+	BUS_TYPE_LOW4K_HDMI_RX = 4,
 };
 
 enum voltage_swing_level {
@@ -623,12 +624,15 @@ struct cdns_mhdp_connector {
 };
 
 struct cdns_mhdp_cec {
-       struct cec_adapter *adap;
-       struct device *dev;
-       struct mutex lock;
+	struct cec_adapter *adap;
+	struct device *dev;
+	struct mutex *iolock;
+	void __iomem		*regs_base;
+	void __iomem		*regs_sec;
+	int bus_type;
 
-       struct cec_msg msg;
-       struct task_struct *cec_worker;
+	struct cec_msg msg;
+	struct task_struct *cec_worker;
 };
 
 struct cdns_plat_data {
@@ -724,7 +728,6 @@ u32 cdns_mhdp_bus_read(struct cdns_mhdp_device *mhdp, u32 offset);
 void cdns_mhdp_bus_write(u32 val, struct cdns_mhdp_device *mhdp, u32 offset);
 void cdns_mhdp_clock_reset(struct cdns_mhdp_device *mhdp);
 void cdns_mhdp_set_fw_clk(struct cdns_mhdp_device *mhdp, unsigned long clk);
-u32 cdns_mhdp_get_fw_clk(struct cdns_mhdp_device *mhdp);
 int cdns_mhdp_load_firmware(struct cdns_mhdp_device *mhdp, const u32 *i_mem,
 			    u32 i_size, const u32 *d_mem, u32 d_size);
 int cdns_mhdp_set_firmware_active(struct cdns_mhdp_device *mhdp, bool enable);
@@ -805,8 +808,8 @@ int cdns_hdmi_set_plugged_cb(struct cdns_mhdp_device *mhdp, hdmi_codec_plugged_c
 
 /* CEC */
 #ifdef CONFIG_DRM_CDNS_HDMI_CEC
-int cdns_mhdp_register_cec_driver(struct device *dev);
-int cdns_mhdp_unregister_cec_driver(struct device *dev);
+int cdns_mhdp_register_cec_driver(struct cdns_mhdp_cec *cec);
+int cdns_mhdp_unregister_cec_driver(struct cdns_mhdp_cec *cec);
 #endif
 
 #endif /* CDNS_MHDP_H_ */
-- 
2.29.2

