From 35e2ec234646f04eb0e17e4c3a4cf21faed3655a Mon Sep 17 00:00:00 2001 From: Wen He 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 --- 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];