From 35e2ec234646f04eb0e17e4c3a4cf21faed3655a Mon Sep 17 00:00:00 2001
From: Wen He <wen.he_1@nxp.com>
Date: Wed, 18 Sep 2019 11:05:31 +0800
Subject: [PATCH] drm: bridge: cadence: Add support for periodically poll the
 connector

Normally, DP/HDMI PHY use HPD_IRQ to monitor the connector connection
status, but LS1028A doesn't support HPD_IRQ signals response.

This patch allows periodically poll the connector for connection and
disconnection.

Signed-off-by: Wen He <wen.he_1@nxp.com>
---
 drivers/gpu/drm/bridge/cadence/cdns-dp-core.c | 86 +++++++++++++++++----------
 include/drm/bridge/cdns-mhdp-common.h         |  1 +
 2 files changed, 54 insertions(+), 33 deletions(-)

--- a/drivers/gpu/drm/bridge/cadence/cdns-dp-core.c
+++ b/drivers/gpu/drm/bridge/cadence/cdns-dp-core.c
@@ -276,7 +276,11 @@ static int cdns_dp_bridge_attach(struct
 
 	connector->interlace_allowed = 1;
 
-	connector->polled = DRM_CONNECTOR_POLL_HPD;
+	if (mhdp->is_hpd)
+		connector->polled = DRM_CONNECTOR_POLL_HPD;
+	else
+		connector->polled = DRM_CONNECTOR_POLL_CONNECT |
+		DRM_CONNECTOR_POLL_DISCONNECT;
 
 	drm_connector_helper_add(connector, &cdns_dp_connector_helper_funcs);
 
@@ -439,22 +443,34 @@ static int __cdns_dp_probe(struct platfo
 	INIT_DELAYED_WORK(&mhdp->hotplug_work, hotplug_work_func);
 
 	iores = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-	mhdp->regs_base = devm_ioremap(dev, iores->start, resource_size(iores));
-	if (IS_ERR(mhdp->regs_base))
-		return -ENOMEM;
+	if (iores) {
+		mhdp->regs_base = devm_ioremap(dev, iores->start,
+					       resource_size(iores));
+		if (IS_ERR(mhdp->regs_base))
+			return -ENOMEM;
+	}
 
 	iores = platform_get_resource(pdev, IORESOURCE_MEM, 1);
-	mhdp->regs_sec = devm_ioremap(dev, iores->start, resource_size(iores));
-	if (IS_ERR(mhdp->regs_sec))
-		return -ENOMEM;
+	if (iores) {
+		mhdp->regs_sec = devm_ioremap(dev, iores->start,
+					      resource_size(iores));
+		if (IS_ERR(mhdp->regs_sec))
+			return -ENOMEM;
+	}
+
+	mhdp->is_hpd = true;
 
 	mhdp->irq[IRQ_IN] = platform_get_irq_byname(pdev, "plug_in");
-	if (mhdp->irq[IRQ_IN] < 0)
+	if (mhdp->irq[IRQ_IN] < 0) {
+		mhdp->is_hpd = false;
 		dev_info(dev, "No plug_in irq number\n");
+	}
 
 	mhdp->irq[IRQ_OUT] = platform_get_irq_byname(pdev, "plug_out");
-	if (mhdp->irq[IRQ_OUT] < 0)
+	if (mhdp->irq[IRQ_OUT] < 0) {
+		mhdp->is_hpd = false;
 		dev_info(dev, "No plug_out irq number\n");
+	}
 
 	cdns_dp_parse_dt(mhdp);
 
@@ -474,33 +490,37 @@ static int __cdns_dp_probe(struct platfo
 	cdns_mhdp_plat_call(mhdp, phy_set);
 
 	/* Enable Hotplug Detect IRQ thread */
-	irq_set_status_flags(mhdp->irq[IRQ_IN], IRQ_NOAUTOEN);
-	ret = devm_request_threaded_irq(dev, mhdp->irq[IRQ_IN],
-					NULL, cdns_dp_irq_thread,
-					IRQF_ONESHOT, dev_name(dev),
-					mhdp);
-	if (ret) {
-		dev_err(dev, "can't claim irq %d\n",
-						mhdp->irq[IRQ_IN]);
-		return -EINVAL;
-	}
+	if (mhdp->is_hpd) {
+		irq_set_status_flags(mhdp->irq[IRQ_IN], IRQ_NOAUTOEN);
+		ret = devm_request_threaded_irq(dev, mhdp->irq[IRQ_IN],
+						NULL, cdns_dp_irq_thread,
+						IRQF_ONESHOT, dev_name(dev),
+						mhdp);
 	
-	irq_set_status_flags(mhdp->irq[IRQ_OUT], IRQ_NOAUTOEN);
-	ret = devm_request_threaded_irq(dev, mhdp->irq[IRQ_OUT],
-					NULL, cdns_dp_irq_thread,
-					IRQF_ONESHOT, dev_name(dev),
-					mhdp);
-	if (ret) {
-		dev_err(dev, "can't claim irq %d\n",
-						mhdp->irq[IRQ_OUT]);
-		return -EINVAL;
+		if (ret) {
+			dev_err(dev, "can't claim irq %d\n",
+					mhdp->irq[IRQ_IN]);
+			return -EINVAL;
+		}
+
+		irq_set_status_flags(mhdp->irq[IRQ_OUT], IRQ_NOAUTOEN);
+		ret = devm_request_threaded_irq(dev, mhdp->irq[IRQ_OUT],
+						NULL, cdns_dp_irq_thread,
+						IRQF_ONESHOT, dev_name(dev),
+						mhdp);
+
+		if (ret) {
+			dev_err(dev, "can't claim irq %d\n",
+					mhdp->irq[IRQ_OUT]);
+			return -EINVAL;
+		}
+
+		if (cdns_mhdp_read_hpd(mhdp))
+			enable_irq(mhdp->irq[IRQ_OUT]);
+		else
+			enable_irq(mhdp->irq[IRQ_IN]);
 	}
 
-	if (cdns_mhdp_read_hpd(mhdp))
-		enable_irq(mhdp->irq[IRQ_OUT]);
-	else
-		enable_irq(mhdp->irq[IRQ_IN]);
-
 	mhdp->bridge.base.driver_private = mhdp;
 	mhdp->bridge.base.funcs = &cdns_dp_bridge_funcs;
 #ifdef CONFIG_OF
--- a/include/drm/bridge/cdns-mhdp-common.h
+++ b/include/drm/bridge/cdns-mhdp-common.h
@@ -683,6 +683,7 @@ struct cdns_mhdp_device {
 	bool link_up;
 	bool power_up;
 	bool plugged;
+	bool is_hpd;
 	struct mutex lock;
 
 	int irq[IRQ_NUM];