| #!/usr/bin/env bash | | | # ============================================================================== | | | # Omarchy / Hyprland Setup & Fix for ASUS ROG Zephyrus G14 | | | # Hardware: AMD Ryzen AI 9 HX 370 (Radeon 890M iGPU) + NVIDIA GeForce RTX dGPU | |
| # Display: 14" 2.8K/3K 120Hz OLED Panel (eDP-1) | |
| # ============================================================================== | |
| # This script resolves: | | | # 1. Aquamarine atomic DRM commit freeze ([AQ] atomic drm request: failed to commit) | | | # by setting AQ_NO_ATOMIC=1 across UWSM, PAM, and shell environments. | | | # 2. Invisible/frozen cursor on legacy DRM by forcing software cursor fallback. | | | # 3. Colon-safe, persistent GPU device routing via udev symlinks (/dev/dri/amd-igpu). | | | # 4. Omarchy Lua configuration errors in monitors.lua (proper 1.5x HiDPI scaling). | | | # 5. Early KMS module in mkinitcpio and Limine boot DRM modesetting. | | | # | | | # Usage: | |
| # curl -sL <your-new-gist-raw-url> | bash | |
| # ============================================================================== | |
| set -eo pipefail | |
| RED='\033[0;31m' | |
| GREEN='\033[0;32m' | |
| YELLOW='\033[1;33m' | |
| BLUE='\033[0;34m' | |
| BOLD='\033[1m' | |
| NC='\033[0m' | |
| info() { echo -e "${BLUE}[INFO]${NC} $*"; } | |
| success() { echo -e "${GREEN}[SUCCESS]${NC} $*"; } | |
| warn() { echo -e "${YELLOW}[WARN]${NC} $*"; } | |
| error() { echo -e "${RED}[ERROR]${NC} $*"; } | |
| echo -e "${BOLD}${BLUE}======================================================${NC}" | |
| echo -e "${BOLD}${BLUE} Omarchy / Hyprland G14 Hybrid Graphics Fix ${NC}" | |
| echo -e "${BOLD}${BLUE}======================================================${NC}" | |
| # ------------------------------------------------------------------------------ | |
| # 1. GPU Detection & Persistent Udev Symlinks | | | # ------------------------------------------------------------------------------ | | | info "Detecting AMD iGPU and NVIDIA dGPU PCI addresses..." | |
| AMD_PCI=$(lspci -D -d 1002::03xx 2>/dev/null | awk '{print $1}' | head -n 1 || true) | |
| NVIDIA_PCI=$(lspci -D -d 10de::03xx 2>/dev/null | awk '{print $1}' | head -n 1 || true) | |
| # Fallback detection via VGA/3D controller strings if class filter missed | |
| if [[ -z "$AMD_PCI" ]]; then | |
| AMD_PCI=$(lspci -D 2>/dev/null | grep -i -E "VGA|3D|Display" | grep -i -E "AMD|ATI" | awk '{print $1}' | head -n 1 || true) | |
| fi | |
| if [[ -z "$NVIDIA_PCI" ]]; then | |
| NVIDIA_PCI=$(lspci -D 2>/dev/null | grep -i -E "VGA|3D|Display" | grep -i "NVIDIA" | awk '{print $1}' | head -n 1 || true) | |
| fi | |
| info "Detected AMD iGPU at PCI: ${AMD_PCI:-'Not found'}" | |
| info "Detected NVIDIA dGPU at PCI: ${NVIDIA_PCI:-'Not found'}" | |
| UDEV_RULE_FILE="/etc/udev/rules.d/99-hyprland-drm.rules" | | | if command -v sudo &>/dev/null && [[ -n "$AMD_PCI" ]]; then | | | info "Configuring persistent udev rules in ${UDEV_RULE_FILE}..." | | | sudo bash -c "cat << 'UDEV' > ${UDEV_RULE_FILE} | | | # Persistent symlinks for Hyprland/Aquamarine (avoids colon-delimiter PCI path bug) | | | KERNEL=="card*", SUBSYSTEM=="drm", SUBSYSTEMS=="pci", KERNELS=="${AMD_PCI}", SYMLINK+="dri/amd-igpu" | | | UDEV" | |
| if [[ -n "$NVIDIA_PCI" ]]; then | |
| sudo bash -c "cat << UDEV >> ${UDEV_RULE_FILE} | |
| KERNEL==\"card*\", SUBSYSTEM==\"drm\", SUBSYSTEMS==\"pci\", KERNELS==\"${NVIDIA_PCI}\", SYMLINK+=\"dri/nvidia-dgpu\" | |
| UDEV" | | | fi | |
| sudo udevadm control --reload-rules 2>/dev/null || true | |
| sudo udevadm trigger --subsystem-match=drm 2>/dev/null || true | |
| # Create immediate symlinks right now | |
| AMD_CARD=$(readlink -f "/dev/dri/by-path/pci-${AMD_PCI}-card" 2>/dev/null || true) | |
| if [[ -n "${AMD_CARD}" && -e "${AMD_CARD}" ]]; then | |
| sudo ln -sfn "${AMD_CARD}" /dev/dri/amd-igpu | |
| fi | |
| if [[ -n "$NVIDIA_PCI" ]]; then | |
| NVIDIA_CARD=$(readlink -f "/dev/dri/by-path/pci-${NVIDIA_PCI}-card" 2>/dev/null || true) | |
| if [[ -n "${NVIDIA_CARD}" && -e "${NVIDIA_CARD}" ]]; then | |
| sudo ln -sfn "${NVIDIA_CARD}" /dev/dri/nvidia-dgpu | |
| fi | | | fi | | | success "Udev rules and /dev/dri symlinks configured." | | | fi | | | # Set target primary display device | |
| if [[ -e /dev/dri/amd-igpu ]]; then | |
| AQ_DEVICES="/dev/dri/amd-igpu" | |
| else | | | AQ_DEVICES="/dev/dri/card0" | | | fi | |
| info "Using primary display device: ${AQ_DEVICES}" | |
| # ------------------------------------------------------------------------------ | |
| # 2. Configure UWSM & Session Environment Variables | | | # ------------------------------------------------------------------------------ | | | info "Configuring environment variables for Aquamarine and software cursor..." | | | set_env_var() { | | | local file="$1" | | | local key="$2" | | | local val="$3" | | | mkdir -p "$(dirname "$file")" | | | touch "$file" | |
| sed -i "/^export ${key}=/d" "$file" | |
| sed -i "/^${key}=/d" "$file" | |
| echo "export ${key}=\"${val}\"" >> "$file" | |
| } | | | # UWSM Hyprland environment (~/.config/uwsm/env-hyprland) | | | set_env_var "${HOME}/.config/uwsm/env-hyprland" "AQ_NO_ATOMIC" "1" | | | set_env_var "${HOME}/.config/uwsm/env-hyprland" "WLR_NO_HARDWARE_CURSORS" "1" | | | set_env_var "${HOME}/.config/uwsm/env-hyprland" "AQ_DRM_DEVICES" "${AQ_DEVICES}" | | | # UWSM General environment (~/.config/uwsm/env) | | | set_env_var "${HOME}/.config/uwsm/env" "AQ_NO_ATOMIC" "1" | | | set_env_var "${HOME}/.config/uwsm/env" "WLR_NO_HARDWARE_CURSORS" "1" | | | # Shell Profile (~/.bash_profile) | | | set_env_var "${HOME}/.bash_profile" "AQ_NO_ATOMIC" "1" | | | set_env_var "${HOME}/.bash_profile" "WLR_NO_HARDWARE_CURSORS" "1" | | | # System-wide environment (/etc/environment for display managers like greetd/sddm) | | | if command -v sudo &>/dev/null; then | | | sudo bash -c 'touch /etc/environment | | | sed -i "/^AQ_NO_ATOMIC=/d" /etc/environment | | | sed -i "/^WLR_NO_HARDWARE_CURSORS=/d" /etc/environment | |
| echo "AQ_NO_ATOMIC=1" >> /etc/environment | |
| echo "WLR_NO_HARDWARE_CURSORS=1" >> /etc/environment' | |
| fi | | | success "Environment variables written to UWSM, bash_profile, and /etc/environment." | | | # ------------------------------------------------------------------------------ | | | # 3. Configure Omarchy Hyprland Lua Files | | | # ------------------------------------------------------------------------------ | | | info "Configuring Omarchy Hyprland Lua settings..." | |
| HYPR_DIR="${HOME}/.config/hypr" | |
| mkdir -p "${HYPR_DIR}" | |
| # Write valid Lua syntax to monitors.lua (OLED 2880x1800@120Hz at 1.5x scale) | |
| cat << 'EOF' > "${HYPR_DIR}/monitors.lua" | |
| -- Omarchy Monitor Configuration | |
| local omarchy_monitor_scale = 1.5 | | | local omarchy_gdk_scale = 1.5 | |
| hl.env("GDK_SCALE", tostring(omarchy_gdk_scale)) | |
| hl.monitor({ | |
| output = "eDP-1", | |
| mode = "2880x1800@120", | | | position = "0x0", | | | scale = omarchy_monitor_scale | | | }) | | | EOF | | | success "Configured ${HYPR_DIR}/monitors.lua" | | | # Clean up any legacy or invalid calls in hyprland.lua | |
| if [[ -f "${HYPR_DIR}/hyprland.lua" ]]; then | |
| sed -i '/hl.cursor/,/})/d' "${HYPR_DIR}/hyprland.lua" | |
| sed -i '/no_hardware_cursors/d' "${HYPR_DIR}/hyprland.lua" | |
| sed -i '/AQ_DRM_DEVICES/d' "${HYPR_DIR}/hyprland.lua" | |
| sed -i '/by-path/d' "${HYPR_DIR}/hyprland.lua" | |
| success "Cleaned up ${HYPR_DIR}/hyprland.lua" | | | fi | | | # ------------------------------------------------------------------------------ | | | # 4. Early KMS Initramfs & Boot Options | |
| # ------------------------------------------------------------------------------ | |
| if command -v sudo &>/dev/null; then | |
| # mkinitcpio early KMS | | | MKINITCPIO="/etc/mkinitcpio.conf" | | | if [[ -f "${MKINITCPIO}" ]]; then | | | info "Configuring early KMS modules in ${MKINITCPIO}..." | |
| if ! grep -q "amdgpu" "${MKINITCPIO}" || ! grep -q "nvidia_drm" "${MKINITCPIO}"; then | |
| sudo cp "${MKINITCPIO}" "${MKINITCPIO}.bak.$(date +%s)" | |
| sudo sed -i 's/^MODULES=(.*/MODULES=(amdgpu nvidia nvidia_modeset nvidia_uvm nvidia_drm)/' "${MKINITCPIO}" | |
| info "Regenerating initramfs images (mkinitcpio -P)..." | | | sudo mkinitcpio -P || warn "mkinitcpio encountered a non-fatal warning; continuing." | | | success "Initramfs early KMS updated." | | | else | | | success "Early KMS modules already present in ${MKINITCPIO}." | | | fi | | | fi | | | # Limine boot kernel parameters | | | LIMINE_CONF="/etc/default/limine" | |
| if [[ -f "${LIMINE_CONF}" ]]; then | |
| if ! grep -q "nvidia_drm.modeset=1" "${LIMINE_CONF}"; then | |
| info "Adding nvidia_drm modeset parameters to ${LIMINE_CONF}..." | | | sudo sed -i 's/APPEND="/APPEND="nvidia_drm.modeset=1 nvidia_drm.fbdev=1 /' "${LIMINE_CONF}" || true | | | success "Limine configuration updated." | | | fi | | | fi | | | fi | | | # ------------------------------------------------------------------------------ | | | # 5. Summary & Completion | |
| # ------------------------------------------------------------------------------ | |
| echo -e "${BOLD}${GREEN}======================================================${NC}" | |
| echo -e "${BOLD}${GREEN} Setup Completed Successfully! ${NC}" | |
| echo -e "${BOLD}${GREEN}======================================================${NC}" | |
| echo -e "Applied settings:" | |
| echo -e " • ${BOLD}AQ_NO_ATOMIC=1${NC} (Bypasses AMD Strix Point DRM atomic commit bug)" | |
| echo -e " • ${BOLD}WLR_NO_HARDWARE_CURSORS=1${NC} (Prevents cursor freezes on legacy DRM)" | |
| echo -e " • ${BOLD}AQ_DRM_DEVICES=${AQ_DEVICES}${NC}" | |
| echo -e " • ${BOLD}monitors.lua${NC} configured for 2880x1800@120Hz with 1.5x HiDPI scale" | |
| echo -e "" | | | echo -e "To apply all kernel and module changes, restart your laptop:" | | | echo -e " ${YELLOW}sudo reboot${NC}" |