]> git.ipfire.org Git - thirdparty/kernel/stable.git/commitdiff
drm/bridge: dw-hdmi-qp: Fix spurious IRQ on resume
authorSebastian Reichel <sebastian.reichel@collabora.com>
Tue, 14 Oct 2025 16:00:57 +0000 (18:00 +0200)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Fri, 23 Jan 2026 10:21:14 +0000 (11:21 +0100)
[ Upstream commit 14adddc65340f2034751c95616861c0e888e2bb1 ]

After resume from suspend to RAM, the following splash is generated if
the HDMI driver is probed (independent of a connected cable):

[ 1194.484052] irq 80: nobody cared (try booting with the "irqpoll" option)
[ 1194.484074] CPU: 0 UID: 0 PID: 627 Comm: rtcwake Not tainted 6.17.0-rc7-g96f1a11414b3 #1 PREEMPT
[ 1194.484082] Hardware name: Rockchip RK3576 EVB V10 Board (DT)
[ 1194.484085] Call trace:
[ 1194.484087]  ... (stripped)
[ 1194.484283] handlers:
[ 1194.484285] [<00000000bc363dcb>] dw_hdmi_qp_main_hardirq [dw_hdmi_qp]
[ 1194.484302] Disabling IRQ #80

Apparently the HDMI IP is losing part of its state while the system
is suspended and generates spurious interrupts during resume. The
bug has not yet been noticed, as system suspend does not yet work
properly on upstream kernel with either the Rockchip RK3588 or RK3576
platform.

Fixes: 128a9bf8ace2 ("drm/rockchip: Add basic RK3588 HDMI output support")
Signed-off-by: Sebastian Reichel <sebastian.reichel@collabora.com>
Reviewed-by: Cristian Ciocaltea <cristian.ciocaltea@collabora.com>
Signed-off-by: Heiko Stuebner <heiko@sntech.de>
Link: https://patch.msgid.link/20251014-rockchip-hdmi-suspend-fix-v1-1-983fcbf44839@collabora.com
Signed-off-by: Sasha Levin <sashal@kernel.org>
drivers/gpu/drm/bridge/synopsys/dw-hdmi-qp.c
drivers/gpu/drm/rockchip/dw_hdmi_qp-rockchip.c
include/drm/bridge/dw_hdmi_qp.h

index 39332c57f2c54296f39e27612544f4fbf923863f..c85eb340e5a3521d5e02c6022ff7e37da6a0556a 100644 (file)
@@ -143,6 +143,7 @@ struct dw_hdmi_qp {
        } phy;
 
        struct regmap *regm;
+       int main_irq;
 
        unsigned long tmds_char_rate;
 };
@@ -1068,6 +1069,7 @@ struct dw_hdmi_qp *dw_hdmi_qp_bind(struct platform_device *pdev,
 
        dw_hdmi_qp_init_hw(hdmi);
 
+       hdmi->main_irq = plat_data->main_irq;
        ret = devm_request_threaded_irq(dev, plat_data->main_irq,
                                        dw_hdmi_qp_main_hardirq, NULL,
                                        IRQF_SHARED, dev_name(dev), hdmi);
@@ -1106,9 +1108,16 @@ struct dw_hdmi_qp *dw_hdmi_qp_bind(struct platform_device *pdev,
 }
 EXPORT_SYMBOL_GPL(dw_hdmi_qp_bind);
 
+void dw_hdmi_qp_suspend(struct device *dev, struct dw_hdmi_qp *hdmi)
+{
+       disable_irq(hdmi->main_irq);
+}
+EXPORT_SYMBOL_GPL(dw_hdmi_qp_suspend);
+
 void dw_hdmi_qp_resume(struct device *dev, struct dw_hdmi_qp *hdmi)
 {
        dw_hdmi_qp_init_hw(hdmi);
+       enable_irq(hdmi->main_irq);
 }
 EXPORT_SYMBOL_GPL(dw_hdmi_qp_resume);
 
index ed6e8f036f4b3d76425725c130394cedf039acd0..9ac45e7bc987a6e155b8345e65f45b30b5b23799 100644 (file)
@@ -597,6 +597,15 @@ static void dw_hdmi_qp_rockchip_remove(struct platform_device *pdev)
        component_del(&pdev->dev, &dw_hdmi_qp_rockchip_ops);
 }
 
+static int __maybe_unused dw_hdmi_qp_rockchip_suspend(struct device *dev)
+{
+       struct rockchip_hdmi_qp *hdmi = dev_get_drvdata(dev);
+
+       dw_hdmi_qp_suspend(dev, hdmi->hdmi);
+
+       return 0;
+}
+
 static int __maybe_unused dw_hdmi_qp_rockchip_resume(struct device *dev)
 {
        struct rockchip_hdmi_qp *hdmi = dev_get_drvdata(dev);
@@ -612,7 +621,8 @@ static int __maybe_unused dw_hdmi_qp_rockchip_resume(struct device *dev)
 }
 
 static const struct dev_pm_ops dw_hdmi_qp_rockchip_pm = {
-       SET_SYSTEM_SLEEP_PM_OPS(NULL, dw_hdmi_qp_rockchip_resume)
+       SET_SYSTEM_SLEEP_PM_OPS(dw_hdmi_qp_rockchip_suspend,
+                               dw_hdmi_qp_rockchip_resume)
 };
 
 struct platform_driver dw_hdmi_qp_rockchip_pltfm_driver = {
index e9be6d507ad9cdc55f5c7d6d3ef37eba41f1ce74..8955450663e530b127373e431ae0271ef4fecd52 100644 (file)
@@ -28,5 +28,6 @@ struct dw_hdmi_qp_plat_data {
 struct dw_hdmi_qp *dw_hdmi_qp_bind(struct platform_device *pdev,
                                   struct drm_encoder *encoder,
                                   const struct dw_hdmi_qp_plat_data *plat_data);
+void dw_hdmi_qp_suspend(struct device *dev, struct dw_hdmi_qp *hdmi);
 void dw_hdmi_qp_resume(struct device *dev, struct dw_hdmi_qp *hdmi);
 #endif /* __DW_HDMI_QP__ */