Lakka-LibreELEC/projects/NXP/devices/iMX8/patches/linux/0017-MLK-24081-03-drm-bridge-cdns-cec-support-hdmi-rx-cec.patch

272 lines
8.9 KiB
Diff

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