Intro
This article is a collection of caveats necessary to get Arch Linux up and running on old Intel MacBooks with AMD GPUs.
In my case, it's old MacBookPro11,5
Steps here are based on various articles and hours of painful debugging.
Article skips full Arch setup process, focusing only on MacBook-specific steps.
This article assumes that you’re using:
- PipeWire as audio server.
- Wayland with Hyprland as a compositor.
Sources
Information in this article is based on following sources:
- https://wiki.t2linux.org/guides/hybrid-graphics/
- https://github.com/Dunedan/mbp-2016-linux
- https://wiki.archlinux.org/title/MacBookPro11,x
- https://github.com/pandeiro/arch-on-air
Table Of Contents
Bootloader
Apple introduces certain limitations for non-macOS systems, such as inability to use Intel GPU.
The most convenient way to bypass them is using rEFInd bootloader.
rEFInd handles MacOS version spoofing, SIP and other stuff out of the box.
rEFInd Installation
Install rEFInd by following instructions from ArchWiki.
⚠️ Important |
---|
Don’t forget to add Linux boot configuration into rEFInd config file /boot/EFI/refind/refind.conf
|
Set Apple OS
Apple blocks access to integrated Intel GPU for any non-macOS operating system.
rEFInd provides a way to workaround this with spoof_osx_version
config parameter.
Open /boot/EFI/refind/refind.conf
and add a following parameter:
spoof_osx_version 12.7
Extra Boot Arguments
Add following options to your Arch Linux menu entry in rEFInd config:
data=writeback libata.force=1:noncq acpi_mask_gpe=0x06 acpi_osi=Darwin i915.modeset=1 amdgpu.modeset=0 amdgpu.runpm=1
Setting rEFInd as default bootloader
Unlike Grub or systemd-boot, rEFInd places itself into a non-standard directory inside EFI partition.
Use efibootmgr
to add rEFInd as boot entry:
efibootmgr -c -L 'rEFInd Boot Manager' -l '\EFI\refind\refind_x64.efi'
⚠️ Important |
---|
Remove old macOS boot entries using efibootmgr to avoid having long boot delays. |
Network
Network Manager
NetworkManager won’t let you to connect to a WiFI without a proper dbus session and keychain provider.
The simplest and most reliable way is to use iwd
instead:
pacman -S iwd
systemctl disable --now NetworkManager
systemctl enable --now systemd-resolved
systemctl enable --now systemd-networkd
systemctl enable --now iwd
💡 Tip |
---|
Check this ArchWiki page for instructions how to connect to a WiFi network. |
Broadcom
You might encounter issues related to missing Broadcom firmware.
In that case, installing broadcom-wl
might help:
paru broadcom-wl-dmks
Then, create /etc/modprobe.d/broadcom-wl-dkms.conf
:
blacklist brcm80211
GPU Power Management
Unfortunately AMD Cape-Verde gGPUs don’t support dynamic power management. This means, dGPU has to be shut down manually in order to save battery.
Udev Rules
Create /etc/udev/rules.d/30-amdgpu-pm.rules
ACTION=="add", SUBSYSTEM=="drm", DRIVERS=="amdgpu", ATTR{device/power/control}="auto"
ACTION=="add", SUBSYSTEM=="drm", DRIVERS=="amdgpu", ATTR{device/power_dpm_force_performance_level}="low"
Kernel Modules
Go to /etc/modprobe.d
and create a couple of files.
amdgpu.conf
options amdgpu modeset=0
options amdgpu enable_psr=1
options amdgpu si_support=1
options amdgpu cik_support=1
options amdgpu runpm=1
radeon.conf
options radeon si_support=0
options radeon cik_support=0
options radeon runpm=1
Then run sudo mkinitcpio -P
to apply changes.
Use Integrated GPU On Boot Using gpu-switch
Install gpu-switch
tool from AUR using Paru.
Then, use a following command to set iGPU as a primary GPU to drive display:
sudo gpu-switch -i
ℹ️ Note |
---|
Operation takes affect only after reboot. |
Disable AMDGPU HDMI Audio
WirePlumber is using /dev/snd/controlC2
which is AMD GPU's HDMI Audio.
This prevents AMDGPU to put a device into D3 cold state.
Make ~/.config/wireplumber/wireplumber.conf.d/50-disable-dgpu-hdmi.conf
:
# disable the HDA function on the Radeon R9 M370X (PCI 01:00.1)
monitor.alsa.rules = [
{
matches = [
{ "device.name" = "alsa_card.pci-0000_01_00.1" }
]
actions = { update-props = { device.disabled = true } }
}
]
After:
- restart wireplumber:
systemctl --user restart wireplumber
- check if
DIS-Audio
isDynOff
:sudo cat /sys/kernel/debug/vgaswitcheroo/switch
Turn Off Discrete AMD GPU
Both GPUs are controlled using Apple's GMUX. It is responsible for turning on and off discrete AMD GPU.
The vga-switcheroo kernel module is responsible for controlling a mux.
# set to integrated
sudo sh -c 'echo IDG > /sys/kernel/debug/vgaswitcheroo/switch'
# turn off dGPU
sudo sh -c 'echo OFF > /sys/kernel/debug/vgaswitcheroo/switch'
# print mux state.
# ensure that "DIS" is "OFF" and "DIS-Audio" is "DynOff"
sudo cat /sys/kernel/debug/vgaswitcheroo/switch
Output of /sys/kernel/vgaswitcheroo/switch
should look like this:
0:IGD:+:Pwr:0000:00:02.0
1:DIS: :Off:0000:01:00.0
2:DIS-Audio: :DynOff:0000:01:00.1
Disable dGPU On Boot
Create oneshot systemd unit file /etc/systemd/system/dgpu-poweroff.service
:
[Unit]
Description=Disable discrete GPU (vgaswitcheroo OFF)
Requires=sys-kernel-debug.mount
After=sys-kernel-debug.mount
[Service]
Type=oneshot
ExecStart=/bin/sh -c 'echo OFF > /sys/kernel/debug/vgaswitcheroo/switch'
[Install]
WantedBy=multi-user.target suspend.target # run at boot *and* after resume
Then, start the service:
sudo systemctl daemon-reload
sudo systemctl enable --now dgpu-poweroff.service
Use iGPU for Hyprland
Find GPU PCI of integrated GPU:
$ lspci | grep VGA
00:02.0 VGA compatible controller: Intel Corporation Crystal Well Integrated Graphics Controller (rev 08)
01:00.0 VGA compatible controller: Advanced Micro Devices, Inc. [AMD/ATI] Venus XT [Radeon HD 8870M / R9 M270X/M370X] (rev 83)
Check what DRI card maps to PCI ID:
$ ls -l /dev/dri/by-path
total 0
lrwxrwxrwx 1 root root 8 Apr 23 03:14 pci-0000:00:02.0-card -> ../card1
lrwxrwxrwx 1 root root 13 Apr 23 03:14 pci-0000:00:02.0-render -> ../renderD128
lrwxrwxrwx 1 root root 8 Apr 23 03:14 pci-0000:01:00.0-card -> ../card0
lrwxrwxrwx 1 root root 13 Apr 23 03:14 pci-0000:01:00.0-render -> ../renderD129
In my case, card1
is Intel and card0
is AMD.
To make Intel GPU a preferred GPU for Hyprland, add following into a ~/.config/hypr/hyprland.conf
:
# Prefer iGPU
env = AQ_DRM_DEVICES,/dev/dri/card1
Power Efficiency
Even with disabled AMD GPU, MacBook still consumes about 15–20 watts (which is a lot).
Although there are a lot of things that can be tweaked, the most basic thing to address is setting a correct CPU power profile.
Battery Monitoring
I recommend using battop tool to monitor power consumption during power optimization.
iGPU Tweaks
PSR (panel self-refresh) and FBC (frame-buffer compression) save ~0.3-0.5 W when the screen shows static content.
Create /etc/modprobe.d/i915.conf
:
options i915 enable_psr=1
options i915 enable_fbc=1
options i915 enable_dc=1
Pefrormance Power Profile
Automatic Power Profiles
The auto-cpufreq
daemon allows automatic CPU power profile configuration based on battery capacity and charging status.
Pros:
- Automatic power profile management based on charging state.
Cons:
- By default it will put CPU into a power save mode when not connected to a charger. This will cause a drastic performance decrease.
- Written in Python and consumes 20MB of RAM which is quite a lot for a simple CPU frequency daemon.
Install auto-cpufreq
daemon to automatically control CPU frequency:
paru auto-cpufreq
sudo systemctl enable --now auto-cpufreq
⚠️ Important |
---|
Don't install auto-cpufreq-git as it's broken. |
Switch Power Profiles Manually
power-profiles-deamon
package provides DBus service and a tool to switch CPU profiles.
sudo pacman -S power-profiles-daemon
sudo systemctl enable --now power-profiles-daemon.service
Later, you can change power profile to power saver, performance or balanced:
powerprofilesctl set power-saver
powerprofilesctl set balanced
Top comments (0)