Skip to content

Commit d33be4e

Browse files
committed
apple-drm: quiesce inactive 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 inactive 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 d33be4e

1 file changed

Lines changed: 41 additions & 8 deletions

File tree

drivers/gpu/drm/apple/apple_drv.c

Lines changed: 41 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,10 @@
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"
4245
#include "plane.h"
4346

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

116117
if (crtc_state->active)
@@ -439,8 +440,9 @@ static int apple_drm_init_dcp(struct device *dev)
439440
* (successfully). Ignoring it should not do any harm now.
440441
* Needs to reevaluated when adding dcpext support.
441442
*/
442-
if (ret)
443+
if (ret) {
443444
dev_warn(dev, "DCP[%d] not ready: %d\n", i, ret);
445+
}
444446
}
445447
/* HACK: Wait for dcp* to settle before a modeset */
446448
msleep(100);
@@ -627,19 +629,50 @@ MODULE_DEVICE_TABLE(of, of_match);
627629
static int apple_platform_suspend(struct device *dev)
628630
{
629631
struct apple_drm_private *apple = dev_get_drvdata(dev);
632+
struct drm_crtc *crtc;
633+
int ret;
630634

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

634651
return 0;
635652
}
636653

637654
static int apple_platform_resume(struct device *dev)
638655
{
639656
struct apple_drm_private *apple = dev_get_drvdata(dev);
657+
struct drm_crtc *crtc;
640658

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

644677
return 0;
645678
}
@@ -690,6 +723,6 @@ static void __exit appledrm_unregister(void)
690723
module_init(appledrm_register);
691724
module_exit(appledrm_unregister);
692725

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

0 commit comments

Comments
 (0)