aboutsummaryrefslogtreecommitdiffstats
path: root/target/linux/layerscape/patches-5.4/805-display-0008-drm-bridge-cadence-Add-CEC-driver-for-cdns-mhdp-hdmi.patch
diff options
context:
space:
mode:
Diffstat (limited to 'target/linux/layerscape/patches-5.4/805-display-0008-drm-bridge-cadence-Add-CEC-driver-for-cdns-mhdp-hdmi.patch')
-rw-r--r--target/linux/layerscape/patches-5.4/805-display-0008-drm-bridge-cadence-Add-CEC-driver-for-cdns-mhdp-hdmi.patch474
1 files changed, 0 insertions, 474 deletions
diff --git a/target/linux/layerscape/patches-5.4/805-display-0008-drm-bridge-cadence-Add-CEC-driver-for-cdns-mhdp-hdmi.patch b/target/linux/layerscape/patches-5.4/805-display-0008-drm-bridge-cadence-Add-CEC-driver-for-cdns-mhdp-hdmi.patch
deleted file mode 100644
index 742928e71a..0000000000
--- a/target/linux/layerscape/patches-5.4/805-display-0008-drm-bridge-cadence-Add-CEC-driver-for-cdns-mhdp-hdmi.patch
+++ /dev/null
@@ -1,474 +0,0 @@
-From ed9e7a6b3346b186a7bd22d9b62072e55ff7b9c5 Mon Sep 17 00:00:00 2001
-From: Sandor Yu <Sandor.yu@nxp.com>
-Date: Mon, 2 Sep 2019 14:57:05 +0800
-Subject: [PATCH] drm: bridge: cadence: Add CEC driver for cdns mhdp hdmi
-
-Add cec driver for cdns mhdp hdmi.
-
-Signed-off-by: Sandor Yu <Sandor.yu@nxp.com>
----
- drivers/gpu/drm/bridge/cadence/Kconfig | 3 +
- drivers/gpu/drm/bridge/cadence/Makefile | 1 +
- drivers/gpu/drm/bridge/cadence/cdns-dp-core.c | 0
- drivers/gpu/drm/bridge/cadence/cdns-hdmi-core.c | 9 +
- drivers/gpu/drm/bridge/cadence/cdns-mhdp-cec.c | 347 ++++++++++++++++++++++
- drivers/gpu/drm/bridge/cadence/cdns-mhdp-common.c | 0
- drivers/gpu/drm/bridge/cadence/cdns-mhdp-hdmi.c | 0
- include/drm/bridge/cdns-mhdp-common.h | 24 +-
- 8 files changed, 382 insertions(+), 2 deletions(-)
- mode change 100755 => 100644 drivers/gpu/drm/bridge/cadence/cdns-dp-core.c
- mode change 100755 => 100644 drivers/gpu/drm/bridge/cadence/cdns-hdmi-core.c
- create mode 100644 drivers/gpu/drm/bridge/cadence/cdns-mhdp-cec.c
- mode change 100755 => 100644 drivers/gpu/drm/bridge/cadence/cdns-mhdp-common.c
- mode change 100755 => 100644 drivers/gpu/drm/bridge/cadence/cdns-mhdp-hdmi.c
-
---- a/drivers/gpu/drm/bridge/cadence/Kconfig
-+++ b/drivers/gpu/drm/bridge/cadence/Kconfig
-@@ -14,3 +14,6 @@ config DRM_CDNS_DP
-
- config DRM_CDNS_AUDIO
- tristate "Cadence MHDP Audio driver"
-+
-+config DRM_CDNS_HDMI_CEC
-+ tristate "Cadence MHDP HDMI CEC driver"
---- a/drivers/gpu/drm/bridge/cadence/Makefile
-+++ b/drivers/gpu/drm/bridge/cadence/Makefile
-@@ -2,3 +2,4 @@ obj-$(CONFIG_DRM_CDNS_MHDP) += cdns-mhdp
- obj-$(CONFIG_DRM_CDNS_HDMI) += cdns-hdmi-core.o
- obj-$(CONFIG_DRM_CDNS_DP) += cdns-dp-core.o
- obj-$(CONFIG_DRM_CDNS_AUDIO) += cdns-mhdp-audio.o
-+obj-$(CONFIG_DRM_CDNS_HDMI_CEC) += cdns-mhdp-cec.o
---- a/drivers/gpu/drm/bridge/cadence/cdns-hdmi-core.c
-+++ b/drivers/gpu/drm/bridge/cadence/cdns-hdmi-core.c
-@@ -515,6 +515,11 @@ __cdns_hdmi_probe(struct platform_device
- /* register audio driver */
- cdns_mhdp_register_audio_driver(dev);
-
-+ /* register cec driver */
-+#ifdef CONFIG_DRM_CDNS_HDMI_CEC
-+ cdns_mhdp_register_cec_driver(dev);
-+#endif
-+
- return hdmi;
-
- err_out:
-@@ -524,6 +529,10 @@ err_out:
-
- 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);
-+#endif
- cdns_mhdp_unregister_audio_driver(mhdp->dev);
- }
-
---- /dev/null
-+++ b/drivers/gpu/drm/bridge/cadence/cdns-mhdp-cec.c
-@@ -0,0 +1,347 @@
-+/*
-+ * Copyright 2019 NXP
-+ *
-+ * This program is free software; you can redistribute it and/or
-+ * modify it under the terms of the GNU General Public License
-+ * as published by the Free Software Foundation; either version 2
-+ * of the License, or (at your option) any later version.
-+ *
-+ * This program is distributed in the hope that it will be useful,
-+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-+ * GNU General Public License for more details.
-+ */
-+#include <linux/module.h>
-+#include <linux/workqueue.h>
-+#include <linux/kthread.h>
-+#include <linux/freezer.h>
-+#include <drm/bridge/cdns-mhdp-common.h>
-+
-+#define CEC_NAME "cdns-mhdp-cec"
-+
-+#define REG_ADDR_OFF 4
-+#define MAX_LA_IDX 4
-+#define MAX_LA_VAL 15
-+
-+/* regsiter define */
-+#define TX_MSG_HEADER 0x33800
-+#define TX_MSG_LENGTH 0x33840
-+#define TX_MSG_CMD 0x33844
-+#define RX_MSG_CMD 0x33850
-+#define RX_CLEAR_BUF 0x33854
-+#define LOGICAL_ADDRESS_LA0 0x33858
-+
-+#define CLK_DIV_MSB 0x3386c
-+#define CLK_DIV_LSB 0x33870
-+#define RX_MSG_DATA1 0x33900
-+#define RX_MSG_LENGTH 0x33940
-+#define RX_MSG_STATUS 0x33944
-+#define NUM_OF_MSG_RX_BUF 0x33948
-+#define TX_MSG_STATUS 0x3394c
-+#define DB_L_TIMER 0x33980
-+
-+/**
-+ * CEC Transceiver operation.
-+ */
-+enum {
-+ CEC_TX_STOP,
-+ CEC_TX_TRANSMIT,
-+ CEC_TX_ABORT,
-+ CEC_TX_ABORT_AND_TRANSMIT
-+};
-+
-+/**
-+ * CEC Transceiver status.
-+ */
-+enum {
-+ CEC_STS_IDLE,
-+ CEC_STS_BUSY,
-+ CEC_STS_SUCCESS,
-+ CEC_STS_ERROR
-+};
-+
-+/**
-+ * CEC Receiver operation.
-+ */
-+enum {
-+ CEC_RX_STOP,
-+ CEC_RX_READ,
-+ CEC_RX_DISABLE,
-+ CEC_RX_ABORT_AND_CLR_FIFO
-+};
-+/**
-+ * Maximum number of Messages in the RX Buffers.
-+ */
-+#define CEC_MAX_RX_MSGS 2
-+
-+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);
-+}
-+
-+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);
-+}
-+
-+static void mhdp_cec_clear_rx_buffer(struct cdns_mhdp_cec *cec)
-+{
-+ mhdp_cec_write(cec, RX_CLEAR_BUF, 1);
-+ mhdp_cec_write(cec, RX_CLEAR_BUF, 0);
-+}
-+
-+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;
-+
-+ mhdp_cec_write(cec, CLK_DIV_MSB,
-+ (clk_div >> 8) & 0xFF);
-+ mhdp_cec_write(cec, CLK_DIV_LSB, clk_div & 0xFF);
-+}
-+
-+static u32 mhdp_cec_read_message(struct cdns_mhdp_cec *cec)
-+{
-+ struct cec_msg *msg = &cec->msg;
-+ int len;
-+ int i;
-+
-+ mhdp_cec_write(cec, RX_MSG_CMD, CEC_RX_READ);
-+
-+ len = mhdp_cec_read(cec, RX_MSG_LENGTH);
-+ msg->len = len + 1;
-+ dev_dbg(cec->dev, "RX MSG len =%d\n", len);
-+
-+ /* Read RX MSG bytes */
-+ for (i = 0; i < msg->len; ++i) {
-+ msg->msg[i] = (u8) mhdp_cec_read(cec, RX_MSG_DATA1 + (i * REG_ADDR_OFF));
-+ dev_dbg(cec->dev, "RX MSG[%d]=0x%x\n", i, msg->msg[i]);
-+ }
-+
-+ mhdp_cec_write(cec, RX_MSG_CMD, CEC_RX_STOP);
-+
-+ return true;
-+}
-+
-+static u32 mhdp_cec_write_message(struct cdns_mhdp_cec *cec, struct cec_msg *msg)
-+{
-+ u8 i;
-+
-+ mhdp_cec_write(cec, TX_MSG_CMD, CEC_TX_STOP);
-+
-+ if (msg->len > CEC_MAX_MSG_SIZE) {
-+ dev_err(cec->dev, "Invalid MSG size!\n");
-+ return -EINVAL;
-+ }
-+
-+ for (i = 0; i < msg->len; ++i)
-+ printk("msg[%d]=0x%x\n",i, msg->msg[i]);
-+
-+ /* Write Message to register */
-+ for (i = 0; i < msg->len; ++i) {
-+ mhdp_cec_write(cec, TX_MSG_HEADER + (i * REG_ADDR_OFF),
-+ msg->msg[i]);
-+ }
-+ /* Write Message Length (payload + opcode) */
-+ mhdp_cec_write(cec, TX_MSG_LENGTH, msg->len - 1);
-+
-+ mhdp_cec_write(cec, TX_MSG_CMD, CEC_TX_TRANSMIT);
-+
-+ return true;
-+}
-+
-+//static void cec_abort_tx_transfer(struct cdns_mhdp_cec *cec)
-+//{
-+// cec_write(cec, TX_MSG_CMD, CEC_TX_ABORT);
-+// cec_write(cec, TX_MSG_CMD, CEC_TX_STOP);
-+//}
-+
-+static int mhdp_cec_set_logical_addr(struct cdns_mhdp_cec *cec, u32 la)
-+{
-+ u8 i;
-+ u8 la_reg;
-+
-+ if (la >= MAX_LA_VAL) {
-+ dev_err(cec->dev, "Error logical Addr\n");
-+ return -EINVAL;
-+ }
-+
-+ for (i = 0; i < MAX_LA_IDX; ++i) {
-+ la_reg =
-+ mhdp_cec_read(cec, LOGICAL_ADDRESS_LA0 + (i * REG_ADDR_OFF));
-+
-+ if (la_reg & 0x10)
-+ continue;
-+
-+ if ((la_reg & 0xF) == la) {
-+ dev_warn(cec->dev, "Warning. LA already in use.\n");
-+ return true;
-+ }
-+
-+ la = (la & 0xF) | (1 << 4);
-+
-+ mhdp_cec_write(cec, LOGICAL_ADDRESS_LA0 + (i * REG_ADDR_OFF), la);
-+ return true;
-+ }
-+
-+ dev_warn(cec->dev, "All LA in use\n");
-+
-+ return false;
-+}
-+
-+static int mhdp_cec_poll_worker(void *_cec)
-+{
-+ struct cdns_mhdp_cec *cec = (struct cdns_mhdp_cec *)_cec;
-+ int num_rx_msgs, i;
-+ int sts;
-+
-+ set_freezable();
-+
-+ for (;;) {
-+ if (kthread_freezable_should_stop(NULL))
-+ break;
-+
-+ /* Check TX State */
-+ sts = mhdp_cec_read(cec, TX_MSG_STATUS);
-+ switch (sts) {
-+ case CEC_STS_SUCCESS:
-+ cec_transmit_done(cec->adap, CEC_TX_STATUS_OK, 0, 0, 0,
-+ 0);
-+ mhdp_cec_write(cec, TX_MSG_CMD, CEC_TX_STOP);
-+ break;
-+ case CEC_STS_ERROR:
-+ mhdp_cec_write(cec, TX_MSG_CMD, CEC_TX_STOP);
-+ cec_transmit_done(cec->adap,
-+ CEC_TX_STATUS_MAX_RETRIES |
-+ CEC_TX_STATUS_NACK, 0, 1, 0, 0);
-+ break;
-+ case CEC_STS_BUSY:
-+ default:
-+ break;
-+ }
-+
-+ /* Check RX State */
-+ sts = mhdp_cec_read(cec, RX_MSG_STATUS);
-+ num_rx_msgs = mhdp_cec_read(cec, NUM_OF_MSG_RX_BUF);
-+ switch (sts) {
-+ case CEC_STS_SUCCESS:
-+ if (num_rx_msgs == 0xf)
-+ num_rx_msgs = CEC_MAX_RX_MSGS;
-+
-+ if (num_rx_msgs > CEC_MAX_RX_MSGS) {
-+ dev_err(cec->dev, "Error rx msg num %d\n",
-+ num_rx_msgs);
-+ mhdp_cec_clear_rx_buffer(cec);
-+ break;
-+ }
-+
-+ /* Rx FIFO Depth 2 RX MSG */
-+ for (i = 0; i < num_rx_msgs; i++) {
-+ mhdp_cec_read_message(cec);
-+ cec->msg.rx_status = CEC_RX_STATUS_OK;
-+ cec_received_msg(cec->adap, &cec->msg);
-+ }
-+ break;
-+ default:
-+ break;
-+ }
-+
-+ if (!kthread_should_stop())
-+ schedule_timeout_idle(20);
-+ }
-+
-+ return 0;
-+}
-+
-+static int mhdp_cec_adap_enable(struct cec_adapter *adap, bool enable)
-+{
-+ struct cdns_mhdp_cec *cec = adap->priv;
-+
-+ if (enable) {
-+ mhdp_cec_write(cec, DB_L_TIMER, 0x10);
-+ mhdp_cec_set_divider(cec);
-+ } else
-+ mhdp_cec_set_divider(cec);
-+
-+ return 0;
-+}
-+
-+static int mhdp_cec_adap_log_addr(struct cec_adapter *adap, u8 addr)
-+{
-+ struct cdns_mhdp_cec *cec = adap->priv;
-+
-+ return mhdp_cec_set_logical_addr(cec, addr);
-+}
-+
-+static int mhdp_cec_adap_transmit(struct cec_adapter *adap, u8 attempts,
-+ u32 signal_free_time, struct cec_msg *msg)
-+{
-+ struct cdns_mhdp_cec *cec = adap->priv;
-+
-+ mhdp_cec_write_message(cec, msg);
-+
-+ return 0;
-+}
-+
-+static const struct cec_adap_ops cdns_mhdp_cec_adap_ops = {
-+ .adap_enable = mhdp_cec_adap_enable,
-+ .adap_log_addr = mhdp_cec_adap_log_addr,
-+ .adap_transmit = mhdp_cec_adap_transmit,
-+};
-+
-+int cdns_mhdp_register_cec_driver(struct device *dev)
-+{
-+ 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,
-+ CEC_NAME,
-+ CEC_CAP_PHYS_ADDR | CEC_CAP_LOG_ADDRS |
-+ CEC_CAP_TRANSMIT | CEC_CAP_PASSTHROUGH
-+ | CEC_CAP_RC, 1);
-+ ret = PTR_ERR_OR_ZERO(cec->adap);
-+ if (ret)
-+ return ret;
-+ ret = cec_register_adapter(cec->adap, 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");
-+ return 0;
-+}
-+
-+int cdns_mhdp_unregister_cec_driver(struct device *dev)
-+{
-+ 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;
-+ }
-+ cec_unregister_adapter(cec->adap);
-+ return 0;
-+}
-+
-+MODULE_AUTHOR("Sandor.Yu@NXP.com");
-+MODULE_LICENSE("GPL");
-+MODULE_DESCRIPTION("NXP CDNS MHDP CEC driver");
---- a/include/drm/bridge/cdns-mhdp-common.h
-+++ b/include/drm/bridge/cdns-mhdp-common.h
-@@ -21,7 +21,7 @@
- #include <drm/drm_connector.h>
- #include <drm/drm_dp_helper.h>
- #include <drm/drm_dp_mst_helper.h>
--
-+#include <media/cec.h>
- #include <linux/bitops.h>
-
- #define ADDR_IMEM 0x10000
-@@ -605,6 +605,17 @@ struct cdns_mhdp_connector {
- struct cdns_mhdp_bridge *bridge;
- };
-
-+#ifdef CONFIG_DRM_CDNS_HDMI_CEC
-+struct cdns_mhdp_cec {
-+ struct cec_adapter *adap;
-+ struct device *dev;
-+ struct mutex lock;
-+
-+ struct cec_msg msg;
-+ struct task_struct *cec_worker;
-+};
-+#endif
-+
- struct cdns_mhdp_device {
- void __iomem *regs;
-
-@@ -633,7 +644,7 @@ struct cdns_mhdp_device {
- bool plugged;
-
- union {
-- struct cdn_dp_data {
-+ struct _dp_data {
- struct drm_dp_link link;
- struct drm_dp_aux aux;
- struct cdns_mhdp_host host;
-@@ -645,6 +656,9 @@ struct cdns_mhdp_device {
- u32 num_lanes;
- } dp;
- struct _hdmi_data {
-+#ifdef CONFIG_DRM_CDNS_HDMI_CEC
-+ struct cdns_mhdp_cec cec;
-+#endif
- u32 char_rate;
- u32 hdmi_type;
- } hdmi;
-@@ -713,4 +727,10 @@ int cdns_hdmi_disable_gcp(struct cdns_mh
- int cdns_hdmi_enable_gcp(struct cdns_mhdp_device *mhdp);
-
- bool cdns_mhdp_check_alive(struct cdns_mhdp_device *mhdp);
-+/* 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);
-+#endif
-+
- #endif /* CDNS_MHDP_COMMON_H_ */