| 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]; |