Il MacBook Pro Retina 15 pollici Mid 2015 ha due GPU: una Intel Iris Pro e una AMD Radeon R9 M370X. Con Omarchy, però, questa configurazione può trasformare sospensione e riavvio in una lotteria fatta di schermi neri, ventole sempre accese e blocchi completi.

Sul mio MacBookPro11,5 ho risolto affidando schermo e desktop alla GPU Intel, facendo inizializzare la AMD dal driver radeon e spegnendola soltanto al momento giusto. Il risultato è un sistema che si avvia regolarmente, entra davvero in sospensione profonda e si risveglia con lo schermo funzionante.

Con amdgpu il Mac si avviava, ma entrando nello stato S3 produceva errori, schermo nero e, in alcuni tentativi, un blocco completo. La soluzione è stata usare Intel per tutto il rendering e lasciare al driver radeon il solo compito di registrare correttamente la GPU AMD prima di spegnerla.

Per arrivarci ho lavorato insieme a diversi modelli. I tentativi eseguiti con GPT-5.6 Sol e Claude Opus 5 non hanno risolto il problema. La configurazione definitiva, compresa la corretta gestione dei tempi di inizializzazione della GPU durante l'avvio e della sospensione profonda, è stata raggiunta con GPT-6 Astra collegato al Mac tramite SSH.

La procedura è stata verificata con firmware Apple 489.0.0.0.0, Omarchy 4.0.2, kernel 7.1.9-arch1-2 e Hyprland 0.56.2. Prima di applicarla ad altri modelli bisogna controllare gli indirizzi PCI e avere una chiavetta Linux o uno snapshot avviabile.

Capire lo stato delle GPU

Per prima cosa ho verificato modello e dispositivi:

cat /sys/devices/virtual/dmi/id/product_name
lspci -nnk | grep -A3 -E 'VGA|Display|Audio'
sudo cat /sys/kernel/debug/vgaswitcheroo/switch

Sul mio Mac gli indirizzi sono:

Intel: 0000:00:02.0
AMD:   0000:01:00.0

Non bisogna affidarsi a card0 e card1, perché il numero può cambiare tra un avvio e l'altro. vga_switcheroo mostra invece il ruolo e lo stato reale delle GPU. IGD è Intel, DIS è AMD, il simbolo + indica la GPU che controlla lo schermo e Pwr o Off ne indicano l'alimentazione.

Prima delle modifiche ho salvato la configurazione:

mkdir -p "$HOME/macbook-gpu-backup"
sudo cp -a /boot/limine.conf "$HOME/macbook-gpu-backup/"
sudo cp -a /etc/mkinitcpio.conf "$HOME/macbook-gpu-backup/"
sudo cp -a /etc/limine-entry-tool.d "$HOME/macbook-gpu-backup/"
sudo efibootmgr -v > "$HOME/macbook-gpu-backup/efibootmgr.txt"

Affidare Hyprland alla GPU Intel

Ho creato /etc/udev/rules.d/70-macbook-intel-gpu.rules:

SUBSYSTEM=="drm", KERNEL=="card[0-9]", KERNELS=="0000:00:02.0", SYMLINK+="dri/intel-igpu"

Poi ho ricaricato le regole:

sudo udevadm control --reload
sudo udevadm trigger --subsystem-match=drm
sudo udevadm settle
readlink -f /dev/dri/intel-igpu

Nel file ~/.config/uwsm/env-hyprland ho inserito:

export AQ_DRM_DEVICES=/dev/dri/intel-igpu
export DRI_PRIME=pci-0000_00_02_0

Hyprland, Xwayland e le applicazioni principali devono usare Intel prima di spegnere AMD.

Selezionare Intel nel firmware

Per scegliere Intel al successivo avvio ho usato gpu-switch, che include MacBookPro11,5 tra i modelli testati:

git clone https://github.com/0xbb/gpu-switch.git
cd gpu-switch
sudo ./gpu-switch -i

Sul mio firmware la variabile Apple gpu-power-prefs viene scritta, ma non può essere riletta e può scomparire dopo un avvio o una sospensione. Per questo la configurazione finale la ricrea quando manca.

La documentazione di gpu-switch avverte che alcuni MacBook Pro 11,3 e 11,5 possono richiedere apple_set_os, disponibile anche in rEFInd. Sul mio Mac l'avvio finale con Limine funziona senza rEFInd, ma non bisogna eseguire questa fase senza un sistema di recupero. Se Intel produce uno schermo nero, si torna alla GPU discreta con sudo ./gpu-switch -d.

Usare radeon per la GPU AMD

La R9 M370X è una GPU Southern Islands e può essere gestita da amdgpu o radeon. Nel mio caso amdgpu falliva durante sospensione e risveglio con errori -22, -110 e blocchi AtomBIOS.

Ho creato /etc/limine-entry-tool.d/macbook-radeon.conf:

KERNEL_CMDLINE[default]+=" radeon.si_support=1 amdgpu.si_support=0"

Poi ho rigenerato immagine e configurazione di Limine:

sudo /usr/bin/limine-mkinitcpio

Dopo il riavvio, il driver della AMD deve essere radeon:

cat /proc/cmdline
readlink -f /sys/bus/pci/devices/0000:01:00.0/driver

Spegnere AMD al momento giusto

Scrivere subito OFF durante l'avvio può bloccare il kernel se Radeon non ha ancora terminato la registrazione. È accaduto nel mio primo test. Ho quindi creato /usr/local/libexec/macbook-amd-off.py, che aspetta entrambe le GPU e controlla che Intel sia attiva:

#!/usr/bin/env python3
from pathlib import Path
import time

for attempt in range(150):
    devices = {
        str((card / "device").resolve())
        for card in Path("/sys/class/drm").glob("card[0-9]*")
        if (card / "device").exists() and "-" not in card.name
    }
    intel = any(path.endswith("/0000:00:02.0") for path in devices)
    amd = any(path.endswith("/0000:01:00.0") for path in devices)
    if intel and amd:
        time.sleep(2)
        break
    time.sleep(0.2)
else:
    raise SystemExit("Entrambe le GPU DRM non sono registrate")

switch = Path("/sys/kernel/debug/vgaswitcheroo/switch")
for attempt in range(100):
    if switch.exists():
        state = switch.read_text()
        if any(":IGD:+:" in line for line in state.splitlines()):
            switch.write_text("OFF\n")
            state = switch.read_text()
            print(state, end="")
            if any(":DIS: :Off:" in line for line in state.splitlines()):
                preference = Path(
                    "/sys/firmware/efi/efivars/"
                    "gpu-power-prefs-fa4ce28d-b62f-4c99-9cc3-6815686e30f9"
                )
                if not preference.exists():
                    preference.write_bytes(bytes([7, 0, 0, 0, 1, 0, 0, 0]))
                raise SystemExit(0)
            raise SystemExit("AMD non risulta spenta")
    time.sleep(0.2)

raise SystemExit("Intel non è la GPU attiva")

Ho reso eseguibile lo script con sudo chmod 755 /usr/local/libexec/macbook-amd-off.py.

Il servizio /etc/systemd/system/macbook-amd-off.service contiene:

[Unit]
Description=Power off unused AMD GPU when MacBook display is on Intel
After=systemd-udev-trigger.service
Before=display-manager.service
ConditionPathExists=/sys/module/apple_gmux

[Service]
Type=oneshot
ExecStart=/usr/bin/python3 /usr/local/libexec/macbook-amd-off.py
RemainAfterExit=yes
TimeoutStartSec=60

[Install]
WantedBy=graphical.target

L'ho attivato con:

sudo systemctl daemon-reload
sudo systemctl enable macbook-amd-off.service

Dopo il riavvio il risultato corretto è:

0:IGD:+:Pwr:0000:00:02.0
1:DIS: :Off:0000:01:00.0
2:DIS-Audio: :DynOff:0000:01:00.1

Sospensione profonda e risveglio

Ho creato /etc/systemd/sleep.conf.d/90-macbook-intel.conf:

[Sleep]
SuspendState=
SuspendState=mem
MemorySleepMode=
MemorySleepMode=deep

Le assegnazioni vuote azzerano eventuali valori accumulati da altri file; mem e deep selezionano poi la sospensione S3.

Al risveglio il firmware può eliminare la preferenza Intel. Il file /usr/lib/systemd/system-sleep/macbook-intel-resume riesegue quindi lo script soltanto dopo la sospensione:

#!/bin/sh
if [ "$1" = post ]; then
    /usr/bin/python3 /usr/local/libexec/macbook-amd-off.py
fi
sudo chmod 755 /usr/lib/systemd/system-sleep/macbook-intel-resume

Non bisogna accendere AMD prima della sospensione. Durante un tentativo con amdgpu questa operazione ha prodotto un blocco completo del Mac.

Verifica finale

Ho provato prima un risveglio programmato:

sudo rtcwake -m no -s 40
sudo systemctl suspend

Poi ho ripetuto il test chiudendo normalmente il coperchio. I log hanno confermato la sospensione profonda:

PM: suspend entry (deep)
ACPI: PM: Preparing to enter system sleep state S3
ACPI: PM: Low-level resume complete
ACPI: PM: Waking up from system sleep state S3
PM: suspend exit

Durante la prova le ventole si sono fermate. Alla riapertura lo schermo Retina interno è tornato, la sessione si è sbloccata normalmente e AMD risultava ancora Off.

Questa configurazione rende indisponibili le uscite video collegate fisicamente alla GPU AMD. Non ho verificato l'ibernazione. Dopo ogni aggiornamento importante del kernel controllerò:

cat /proc/cmdline
readlink -f /sys/bus/pci/devices/0000:01:00.0/driver
sudo cat /sys/kernel/debug/vgaswitcheroo/switch

Una volta rispettato quest'ordine, il MacBook ha finalmente iniziato a comportarsi come volevo: Intel per il desktop, AMD realmente spenta e sospensione profonda funzionante.


Fonti essenziali