forked from libretro/Lakka-LibreELEC
272 lines
8.9 KiB
Diff
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
|
|
|