From f7f5ec54b815df2c9a92f0fd6edea4f5d0700937 Mon Sep 17 00:00:00 2001 From: Sandor Yu 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 Reviewed-by: Robby Cai --- 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