Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 30 additions & 0 deletions bin/omarchy-hw-msi
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
#!/bin/bash

# omarchy:summary=Detect whether the computer is an MSI laptop.

# Read DMI IDs via OMARCHY_DMI_ID_PATH for test stubs, falling back to /sys.
dmi_path="${OMARCHY_DMI_ID_PATH:-/sys/class/dmi/id}"

# MSI laptops report "Micro-Star International Co., Ltd." as sys_vendor. Some
# MSI desktop boards also report this, so we additionally check for laptop
# product families in either product_family or product_name.
sys_vendor=$(cat "$dmi_path/sys_vendor" 2>/dev/null)
[[ $sys_vendor == "Micro-Star International Co., Ltd." ]] || exit 1

# Combine both fields for a single match — laptops have the model line in
# product_family (e.g. "Titan GT77HX 13VI") and optionally the short model
# in product_name (e.g. "MSI Titan GT77HX 13VI"). Desktop boards usually
# only have the board name in product_name (e.g. "MEG X670E ACE").
combined="$(cat "$dmi_path/product_family" 2>/dev/null) $(cat "$dmi_path/product_name" 2>/dev/null)"

# All known MSI laptop families as of 2026. Katana, Cyborg, Pulse, Bravo,
# Alpha cover budget/mid-tier; Prestige covers content-creation ultraportables.
for family in "Titan" "Stealth" "Raider" "Vector" "Crosshair" "Summit" \
"Creator" "Modern" "Katana" "Cyborg" "Pulse" "Bravo" \
"Alpha" "Prestige"; do
if grep -qi "$family" <<<"$combined"; then
exit 0
fi
done

exit 1
12 changes: 12 additions & 0 deletions bin/omarchy-hw-msi-titan
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
#!/bin/bash

# omarchy:summary=Detect whether the computer is an MSI Titan GT77HX
# omarchy:hidden=true

dmi_path="${OMARCHY_DMI_ID_PATH:-/sys/class/dmi/id}"

sys_vendor=$(cat "$dmi_path/sys_vendor" 2>/dev/null)
[[ $sys_vendor == "Micro-Star International Co., Ltd." ]] || exit 1

combined="$(cat "$dmi_path/product_family" 2>/dev/null) $(cat "$dmi_path/product_name" 2>/dev/null)"
grep -qi "Titan GT77HX" <<<"$combined"
143 changes: 143 additions & 0 deletions bin/omarchy-msi-cooler-boost-watch
Original file line number Diff line number Diff line change
@@ -0,0 +1,143 @@
#!/bin/bash

# omarchy:summary=Turn MSI Cooler Boost on when CPU/GPU hit the high-temp threshold
# omarchy:args=[--once|--decide <state> <cpu> <gpu>]
# omarchy:hidden=true
# omarchy:requires-sudo=true

# Cooler Boost is a binary EC flag. Silent/auto fan modes do not enable it at a
# temperature, so Titan GT77HX units stay on the quiet curve until this watcher
# flips the flag. Default: on at 85C after 30s sustained, off at 70C (hysteresis).
# Matches #11583 Extreme 100% at 85C and Silent staying low until 70C.

set -euo pipefail

ON_AT=${MSI_COOLER_BOOST_ON_AT:-85}
OFF_AT=${MSI_COOLER_BOOST_OFF_AT:-70}
SUSTAIN=${MSI_COOLER_BOOST_SUSTAIN:-30}
INTERVAL=${MSI_COOLER_BOOST_INTERVAL:-5}
EC_PATH=${OMARCHY_MSI_EC_PATH:-/sys/devices/platform/msi-ec}

desired_cooler_boost() {
local state=$1 cpu=$2 gpu=$3 on_at=$4 off_at=$5
local hot=$cpu

[[ $cpu =~ ^[0-9]+$ ]] || cpu=0
[[ $gpu =~ ^[0-9]+$ ]] || gpu=0
hot=$cpu
if (( gpu > hot )); then
hot=$gpu
fi

if [[ $state != on ]] && (( hot >= on_at )); then
printf '%s\n' on
elif [[ $state == on ]] && (( hot <= off_at )); then
printf '%s\n' off
elif [[ $state == on ]]; then
printf '%s\n' on
else
printf '%s\n' off
fi
}

read_temp() {
local file=$1
local value=0

if [[ -r $file ]]; then
value=$(< "$file")
fi
if [[ ! $value =~ ^[0-9]+$ ]]; then
value=0
fi
printf '%s\n' "$value"
}

read_state() {
local file=$1
local value=off

if [[ -r $file ]]; then
value=$(tr -d '[:space:]' < "$file")
fi
if [[ $value != on ]]; then
value=off
fi
printf '%s\n' "$value"
}

if [[ ${1:-} == --decide ]]; then
desired_cooler_boost "${2:-off}" "${3:-0}" "${4:-0}" "$ON_AT" "$OFF_AT"
exit 0
fi

if ! omarchy-hw-msi-titan; then
echo "omarchy-msi-cooler-boost-watch: not an MSI Titan GT77HX; exiting"
exit 0
fi

boost=$EC_PATH/cooler_boost
cpu_temp=$EC_PATH/cpu/realtime_temperature
gpu_temp=$EC_PATH/gpu/realtime_temperature

if [[ ! -e $boost ]]; then
echo "omarchy-msi-cooler-boost-watch: $boost missing (msi-ec not loaded)" >&2
exit 1
fi

apply_once() {
local state cpu gpu want hot sustained_file count

state=$(read_state "$boost")
cpu=$(read_temp "$cpu_temp")
gpu=$(read_temp "$gpu_temp")
sustained_file="${OMARCHY_MSI_SUSTAIN_FILE:-/run/omarchy-msi-cooler-boost.sustain}"

hot=$cpu
[[ $cpu =~ ^[0-9]+$ ]] || cpu=0
[[ $gpu =~ ^[0-9]+$ ]] || gpu=0
if (( gpu > hot )); then
hot=$gpu
fi

if [[ $state == off ]] && (( hot >= ON_AT )); then
# Track consecutive high-temp readings; flip only after SUSTAIN seconds
if [[ -s "$sustained_file" ]]; then
count=$(< "$sustained_file")
else
count=0
fi
count=$(( count + 1 ))
printf '%s\n' "$count" > "$sustained_file"

if (( count * INTERVAL > SUSTAIN )); then
want=on
else
want=off
fi
else
# Reset sustain tracking when temp drops or boost is already on
rm -f "$sustained_file"
want=$(desired_cooler_boost "$state" "$cpu" "$gpu" "$ON_AT" "$OFF_AT")
fi

if [[ $want != "$state" ]]; then
if printf '%s\n' "$want" > "$boost"; then
echo "cooler_boost $state -> $want (cpu=${cpu}C gpu=${gpu}C)"
else
echo "omarchy-msi-cooler-boost-watch: cannot write $boost" >&2
return 1
fi
fi
}

if [[ ${1:-} == --once ]]; then
apply_once
exit $?
fi

echo "omarchy-msi-cooler-boost-watch: on>=${ON_AT}C off<=${OFF_AT}C sustain=${SUSTAIN}s interval=${INTERVAL}s"
while true; do
apply_once || true
sleep "$INTERVAL"
done
18 changes: 18 additions & 0 deletions default/systemd/system/omarchy-msi-cooler-boost-watch.service
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
[Unit]
Description=Enable MSI Cooler Boost when CPU/GPU hit 85C (sustained 30s)
Documentation=https://github.com/omacom/omarchy/issues/11583
After=multi-user.target
ConditionPathExists=/sys/devices/platform/msi-ec/cooler_boost

[Service]
Type=simple
ExecStart=/usr/bin/omarchy-msi-cooler-boost-watch
Restart=on-failure
RestartSec=10
Environment=MSI_COOLER_BOOST_ON_AT=85
Environment=MSI_COOLER_BOOST_OFF_AT=70
Environment=MSI_COOLER_BOOST_SUSTAIN=30
Environment=MSI_COOLER_BOOST_INTERVAL=5

[Install]
WantedBy=multi-user.target
1 change: 1 addition & 0 deletions install/hardware/all.sh
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
run_logged "$OMARCHY_INSTALL/hardware/asus-rog.sh"
run_logged "$OMARCHY_INSTALL/hardware/framework16.sh"
run_logged "$OMARCHY_INSTALL/hardware/msi.sh"
run_logged "$OMARCHY_INSTALL/hardware/dell-xps-touchpad-haptics.sh"
run_logged "$OMARCHY_INSTALL/hardware/surface.sh"

Expand Down
118 changes: 118 additions & 0 deletions install/hardware/msi.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,118 @@
#!/bin/bash
set -euo pipefail

# Install and configure MSI-specific drivers for Titan/Stealth/Raider/etc laptops.
# Requires omarchy-hw-msi detection to gate execution.

if omarchy-hw-msi; then
# Killer E-series Ethernet (RTL8125B) — blacklist r8169 for stability.
# Use sysfs reads instead of lspci (see PR #11259) to avoid waking
# suspended GPUs on hybrid laptops.
pci_devices_path="${OMARCHY_PCI_DEVICES_PATH:-/sys/bus/pci/devices}"
rtl8125b_found=false
for device in "$pci_devices_path"/*; do
[[ $(< "$device/vendor" 2>/dev/null) == "0x10ec" ]] || continue
device_id=$(< "$device/device" 2>/dev/null)
if [[ $device_id == "0x8125" ]]; then
rtl8125b_found=true
break
fi
done

if $rtl8125b_found; then
if ! omarchy-pkg-present r8125-dkms 2>/dev/null; then
omarchy-pkg-add r8125-dkms || echo "WARNING: Failed to install r8125-dkms" >&2
fi

# Blacklist r8169 so r8125 loads exclusively. Only do this if r8125
# is actually loaded — otherwise we risk leaving the system with no
# network driver until the next reboot.
if lsmod | grep -q r8125; then
sudo install -Dm644 /dev/stdin /etc/modprobe.d/r8169.conf <<'EOF'
blacklist r8169
EOF
sudo install -Dm644 /dev/stdin /etc/modules-load.d/r8125.conf <<'EOF'
r8125
EOF
limine-mkinitcpio 2>/dev/null || sudo mkinitcpio -P
else
echo "WARNING: r8125 module not loaded — skipping blacklist to avoid network loss" >&2
fi
fi

# MSI Embedded Controller — required for fan modes, shift modes,
# battery thresholds, and other laptop-specific features.
if ! lsmod | grep -q msi_ec; then
if ! omarchy-pkg-present msi-ec-dkms-git 2>/dev/null; then
omarchy-pkg-add msi-ec-dkms-git || echo "WARNING: Failed to install msi-ec-dkms-git" >&2
fi
fi

# Set battery charge thresholds for battery health.
# Start charging at 60%, stop at 80% to preserve battery lifespan.
# Only set if the system is currently on battery (not AC power).
if [[ -f /sys/class/power_supply/BAT1/charge_control_start_threshold ]]; then
current_status=$(cat /sys/class/power_supply/BAT1/status 2>/dev/null)
if [[ $current_status == "Discharging" ]]; then
echo 60 | sudo tee /sys/class/power_supply/BAT1/charge_control_start_threshold >/dev/null
echo 80 | sudo tee /sys/class/power_supply/BAT1/charge_control_end_threshold >/dev/null
fi
fi

# CoolerControl for fan curves + thermal management. Disable thermald
# (generic DPTF) to avoid conflicts — coolercontrold talks to the EC
# directly and knows the MSI fan table.
if ! omarchy-pkg-present coolercontrol 2>/dev/null; then
omarchy-pkg-add coolercontrol || echo "WARNING: Failed to install coolercontrol" >&2
fi

if systemctl is-enabled thermald.service &>/dev/null; then
sudo systemctl disable --now thermald.service || echo "WARNING: Failed to disable thermald" >&2
fi

if ! systemctl is-active coolercontrold.service &>/dev/null; then
sudo systemctl enable --now coolercontrold.service || echo "WARNING: Failed to enable coolercontrold" >&2
fi

# CoolerControl cannot PWM these EC fans (RPM-only). Cooler Boost is the
# binary "fast fans" flag and is not turned on by silent/auto curves. On the
# Titan GT77HX, enable a watcher that flips it at 85C once sustained for 30s
# (off again at 70C).
if omarchy-hw-msi-titan; then
sudo install -Dm644 "$OMARCHY_PATH/default/systemd/system/omarchy-msi-cooler-boost-watch.service" \
/etc/systemd/system/omarchy-msi-cooler-boost-watch.service
sudo systemctl daemon-reload
sudo systemctl enable --now omarchy-msi-cooler-boost-watch.service || \
echo "WARNING: Failed to enable omarchy-msi-cooler-boost-watch" >&2
fi

# NVIDIA-settings for GPU monitoring and tuning on MSI dGPU laptops
if omarchy-hw-nvidia; then
if ! omarchy-pkg-present nvidia-settings 2>/dev/null; then
omarchy-pkg-add nvidia-settings || echo "WARNING: Failed to install nvidia-settings" >&2
fi

# X11 config for DPMS and backlight control via nvidia-settings
sudo install -Dm644 /dev/stdin /etc/X11/xorg.conf.d/10-nvidia-dpms.conf <<'EOF'
Section "Device"
Identifier "NVIDIA Card"
Driver "nvidia"
Option "RegistryDwords" "EnableBrightnessControl=1"
EndSection

Section "Screen"
Identifier "Screen0"
Device "NVIDIA Card"
Option "AllowNVIDIAGPUScreens" "on"
EndSection
EOF
fi

# Early-load msi_ec module via mkinitcpio if it's currently loaded
if lsmod | grep -q msi_ec; then
sudo install -Dm644 /dev/stdin /etc/mkinitcpio.conf.d/msi.conf <<'EOF'
MODULES+=(msi_ec)
EOF
limine-mkinitcpio 2>/dev/null || sudo mkinitcpio -P
fi
fi
Loading