Skip to content

Commit 0b2b907

Browse files
committed
apple-drm: quiesce disconnected DCPs on suspend, fix resume crash
drm_mode_config_helper_suspend returns -EINVAL when a secondary DCP (external display) is disconnected, which blocks the entire PM suspend path. Even if suspend returns 0 anyway, the DCP RTKit firmware keeps running and generates mailbox IRQs that immediately wake from s2idle. When the drm suspend helper fails, iterate CRTCs and call apple_rtkit_quiesce on disconnected DCPs so they stop generating IRQs. On resume, re-boot them with apple_rtkit_boot and fire a hotplug event. Also fix the resume path: drm_mode_config_helper_resume crashes on NULL suspend_state when suspend failed, so check for that and fall back to a hotplug event instead. Tested on M1 MacBook Air (J313) with USB-C display, fairydust 6.18.10.
1 parent ce3b823 commit 0b2b907

1 file changed

Lines changed: 42 additions & 8 deletions

File tree

drivers/gpu/drm/apple/apple_drv.c

Lines changed: 42 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
// SPDX-License-Identifier: GPL-2.0-only OR MIT
2-
/* Copyright 2021 Alyssa Rosenzweig */
2+
/* Copyright 2021 Alyssa Rosenzweig <alyssa@rosenzweig.io> */
33
/* Based on meson driver which is
44
* Copyright (C) 2016 BayLibre, SAS
55
* Author: Neil Armstrong <narmstrong@baylibre.com>
@@ -38,7 +38,11 @@
3838
#include <drm/drm_vblank.h>
3939
#include <drm/drm_fixed.h>
4040

41+
#include <linux/soc/apple/rtkit.h>
42+
4143
#include "dcp.h"
44+
#include "dcp-internal.h"
45+
#include "connector.h"
4246
#include "plane.h"
4347

4448
#define DRIVER_NAME "apple"
@@ -109,8 +113,6 @@ static void apple_crtc_atomic_enable(struct drm_crtc *crtc,
109113
if (crtc_state->active_changed && crtc_state->active) {
110114
struct apple_crtc *apple_crtc = to_apple_crtc(crtc);
111115
dcp_poweron(apple_crtc->dcp);
112-
/* Force the CTM to be set on first swap */
113-
crtc_state->color_mgmt_changed = true;
114116
}
115117

116118
if (crtc_state->active)
@@ -439,8 +441,9 @@ static int apple_drm_init_dcp(struct device *dev)
439441
* (successfully). Ignoring it should not do any harm now.
440442
* Needs to reevaluated when adding dcpext support.
441443
*/
442-
if (ret)
444+
if (ret) {
443445
dev_warn(dev, "DCP[%d] not ready: %d\n", i, ret);
446+
}
444447
}
445448
/* HACK: Wait for dcp* to settle before a modeset */
446449
msleep(100);
@@ -627,19 +630,50 @@ MODULE_DEVICE_TABLE(of, of_match);
627630
static int apple_platform_suspend(struct device *dev)
628631
{
629632
struct apple_drm_private *apple = dev_get_drvdata(dev);
633+
struct drm_crtc *crtc;
634+
int ret;
630635

631-
if (apple)
632-
return drm_mode_config_helper_suspend(&apple->drm);
636+
if (apple) {
637+
ret = drm_mode_config_helper_suspend(&apple->drm);
638+
if (ret) {
639+
dev_warn(dev, "drm suspend helper failed: %d, quiescing inactive DCPs\n", ret);
640+
drm_for_each_crtc(crtc, &apple->drm) {
641+
struct apple_crtc *acrtc = to_apple_crtc(crtc);
642+
struct apple_dcp *dcp = platform_get_drvdata(acrtc->dcp);
643+
644+
if (dcp && dcp->connector && !dcp->connector->connected && dcp->rtk) {
645+
dev_info(dev, "quiescing disconnected DCP %d\n", dcp->index);
646+
apple_rtkit_quiesce(dcp->rtk);
647+
}
648+
}
649+
}
650+
}
633651

634652
return 0;
635653
}
636654

637655
static int apple_platform_resume(struct device *dev)
638656
{
639657
struct apple_drm_private *apple = dev_get_drvdata(dev);
658+
struct drm_crtc *crtc;
640659

641-
if (apple)
660+
if (!apple)
661+
return 0;
662+
663+
if (apple->drm.mode_config.suspend_state) {
642664
drm_mode_config_helper_resume(&apple->drm);
665+
} else {
666+
drm_for_each_crtc(crtc, &apple->drm) {
667+
struct apple_crtc *acrtc = to_apple_crtc(crtc);
668+
struct apple_dcp *dcp = platform_get_drvdata(acrtc->dcp);
669+
670+
if (dcp && dcp->connector && !dcp->connector->connected && dcp->rtk) {
671+
dev_info(dev, "re-booting DCP %d after quiesce\n", dcp->index);
672+
apple_rtkit_boot(dcp->rtk);
673+
}
674+
}
675+
drm_kms_helper_hotplug_event(&apple->drm);
676+
}
643677

644678
return 0;
645679
}
@@ -690,6 +724,6 @@ static void __exit appledrm_unregister(void)
690724
module_init(appledrm_register);
691725
module_exit(appledrm_unregister);
692726

693-
MODULE_AUTHOR("Asahi Linux contributors");
727+
MODULE_AUTHOR("Alyssa Rosenzweig <alyssa@rosenzweig.io>");
694728
MODULE_DESCRIPTION(DRIVER_DESC);
695729
MODULE_LICENSE("Dual MIT/GPL");

0 commit comments

Comments
 (0)