Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

drm/bridge: dw-hdmi-qp: Fix spurious IRQ on resume

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

authored by

Sebastian Reichel and committed by
Heiko Stuebner
14adddc6 d5bdf88d

+21 -1
+9
drivers/gpu/drm/bridge/synopsys/dw-hdmi-qp.c
··· 163 163 164 164 unsigned long ref_clk_rate; 165 165 struct regmap *regm; 166 + int main_irq; 166 167 167 168 unsigned long tmds_char_rate; 168 169 }; ··· 1272 1271 1273 1272 dw_hdmi_qp_init_hw(hdmi); 1274 1273 1274 + hdmi->main_irq = plat_data->main_irq; 1275 1275 ret = devm_request_threaded_irq(dev, plat_data->main_irq, 1276 1276 dw_hdmi_qp_main_hardirq, NULL, 1277 1277 IRQF_SHARED, dev_name(dev), hdmi); ··· 1333 1331 } 1334 1332 EXPORT_SYMBOL_GPL(dw_hdmi_qp_bind); 1335 1333 1334 + void dw_hdmi_qp_suspend(struct device *dev, struct dw_hdmi_qp *hdmi) 1335 + { 1336 + disable_irq(hdmi->main_irq); 1337 + } 1338 + EXPORT_SYMBOL_GPL(dw_hdmi_qp_suspend); 1339 + 1336 1340 void dw_hdmi_qp_resume(struct device *dev, struct dw_hdmi_qp *hdmi) 1337 1341 { 1338 1342 dw_hdmi_qp_init_hw(hdmi); 1343 + enable_irq(hdmi->main_irq); 1339 1344 } 1340 1345 EXPORT_SYMBOL_GPL(dw_hdmi_qp_resume); 1341 1346
+11 -1
drivers/gpu/drm/rockchip/dw_hdmi_qp-rockchip.c
··· 640 640 component_del(&pdev->dev, &dw_hdmi_qp_rockchip_ops); 641 641 } 642 642 643 + static int __maybe_unused dw_hdmi_qp_rockchip_suspend(struct device *dev) 644 + { 645 + struct rockchip_hdmi_qp *hdmi = dev_get_drvdata(dev); 646 + 647 + dw_hdmi_qp_suspend(dev, hdmi->hdmi); 648 + 649 + return 0; 650 + } 651 + 643 652 static int __maybe_unused dw_hdmi_qp_rockchip_resume(struct device *dev) 644 653 { 645 654 struct rockchip_hdmi_qp *hdmi = dev_get_drvdata(dev); ··· 664 655 } 665 656 666 657 static const struct dev_pm_ops dw_hdmi_qp_rockchip_pm = { 667 - SET_SYSTEM_SLEEP_PM_OPS(NULL, dw_hdmi_qp_rockchip_resume) 658 + SET_SYSTEM_SLEEP_PM_OPS(dw_hdmi_qp_rockchip_suspend, 659 + dw_hdmi_qp_rockchip_resume) 668 660 }; 669 661 670 662 struct platform_driver dw_hdmi_qp_rockchip_pltfm_driver = {
+1
include/drm/bridge/dw_hdmi_qp.h
··· 34 34 struct dw_hdmi_qp *dw_hdmi_qp_bind(struct platform_device *pdev, 35 35 struct drm_encoder *encoder, 36 36 const struct dw_hdmi_qp_plat_data *plat_data); 37 + void dw_hdmi_qp_suspend(struct device *dev, struct dw_hdmi_qp *hdmi); 37 38 void dw_hdmi_qp_resume(struct device *dev, struct dw_hdmi_qp *hdmi); 38 39 #endif /* __DW_HDMI_QP__ */