From 7bd094a3846f7fa1e62c0e9c888168f2ddda4709 Mon Sep 17 00:00:00 2001 From: Algea Cao Date: Fri, 3 Dec 2021 14:11:24 +0800 Subject: [PATCH] drm/rockchip: dw_hdmi_qp: Fix rk3588 hdmitx suspend crash Signed-off-by: Algea Cao Change-Id: I5f7771dbcbcfb13fb556b84ba147711fbde689e5 --- drivers/gpu/drm/bridge/synopsys/dw-hdmi-qp.c | 25 ++++---------------- drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c | 12 ++++++++-- 2 files changed, 15 insertions(+), 22 deletions(-) diff --git a/drivers/gpu/drm/bridge/synopsys/dw-hdmi-qp.c b/drivers/gpu/drm/bridge/synopsys/dw-hdmi-qp.c index 811e4d96eff7..182f7170af1f 100644 --- a/drivers/gpu/drm/bridge/synopsys/dw-hdmi-qp.c +++ b/drivers/gpu/drm/bridge/synopsys/dw-hdmi-qp.c @@ -247,9 +247,6 @@ struct dw_hdmi_qp { bool sink_has_audio; bool hpd_state; - struct delayed_work work; - struct workqueue_struct *workqueue; - struct mutex mutex; /* for state below and previous_mode */ struct drm_connector *curr_conn;/* current connector (only valid when !disabled) */ enum drm_connector_force force; /* mutex-protected force state */ @@ -2322,8 +2319,6 @@ void dw_hdmi_qp_suspend(struct device *dev, struct dw_hdmi_qp *hdmi) if (hdmi->earc_irq) disable_irq(hdmi->earc_irq); - cancel_delayed_work(&hdmi->work); - flush_workqueue(hdmi->workqueue); pinctrl_pm_select_sleep_state(dev); } EXPORT_SYMBOL_GPL(dw_hdmi_qp_suspend); @@ -2335,6 +2330,10 @@ void dw_hdmi_qp_resume(struct device *dev, struct dw_hdmi_qp *hdmi) return; } + hdmi_writel(hdmi, 0, MAINUNIT_0_INT_MASK_N); + hdmi_writel(hdmi, 0, MAINUNIT_1_INT_MASK_N); + hdmi_writel(hdmi, 428571429, TIMER_BASE_CONFIG0); + pinctrl_pm_select_default_state(dev); mutex_lock(&hdmi->mutex); if (hdmi->i2c) @@ -2347,21 +2346,7 @@ void dw_hdmi_qp_resume(struct device *dev, struct dw_hdmi_qp *hdmi) if (hdmi->earc_irq) enable_irq(hdmi->earc_irq); - /* - * HDMI status maybe incorrect in the following condition: - * HDMI plug in -> system sleep -> HDMI plug out -> system wake up. - * At this time, cat /sys/class/drm/card 0-HDMI-A-1/status is connected. - * There is no hpd interrupt, because HDMI is powerdown during suspend. - * So we need check the current HDMI status in this case. - */ - if (hdmi->connector.status == connector_status_connected) { - if (hdmi->phy.ops->read_hpd(hdmi, hdmi->phy.data) == - connector_status_disconnected) { - hdmi->hpd_state = false; - mod_delayed_work(hdmi->workqueue, &hdmi->work, - msecs_to_jiffies(20)); - } - } + mutex_unlock(&hdmi->mutex); } EXPORT_SYMBOL_GPL(dw_hdmi_qp_resume); diff --git a/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c b/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c index aad0ace9f115..346c90ae06ff 100644 --- a/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c +++ b/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c @@ -3184,7 +3184,10 @@ static int dw_hdmi_rockchip_suspend(struct device *dev) { struct rockchip_hdmi *hdmi = dev_get_drvdata(dev); - dw_hdmi_suspend(hdmi->hdmi); + if (hdmi->is_hdmi_qp) + dw_hdmi_qp_suspend(dev, hdmi->hdmi_qp); + else + dw_hdmi_suspend(hdmi->hdmi); pm_runtime_put_sync(dev); return 0; @@ -3194,7 +3197,12 @@ static int dw_hdmi_rockchip_resume(struct device *dev) { struct rockchip_hdmi *hdmi = dev_get_drvdata(dev); - dw_hdmi_resume(hdmi->hdmi); + if (hdmi->is_hdmi_qp) { + dw_hdmi_qp_resume(dev, hdmi->hdmi_qp); + drm_helper_hpd_irq_event(hdmi->encoder.dev); + } else { + dw_hdmi_resume(hdmi->hdmi); + } pm_runtime_get_sync(dev); return 0;