diff --git a/flake.nix b/flake.nix index a9fc3a0..492ed9f 100644 --- a/flake.nix +++ b/flake.nix @@ -203,6 +203,9 @@ hermes = { url = "github:NousResearch/hermes-agent"; }; + mt7927 = { + url = "github:cmspam/mt7927-nixos"; + }; }; outputs = inputs: diff --git a/modules/hosts/14900k/_private/mediatek-mt7927.nix b/modules/hosts/14900k/_private/mediatek-mt7927.nix new file mode 100644 index 0000000..89e2d64 --- /dev/null +++ b/modules/hosts/14900k/_private/mediatek-mt7927.nix @@ -0,0 +1,107 @@ +{ pkgs, inputs, ... }: +# All MediaTek MT7927 / MT6639 (Filogic 380) WiFi 7 + Bluetooth support for this +# host in one place: the upstream flake module, the hardware enablement, and the +# workarounds needed to actually make it function on nixos-unstable. +# +# Workaround background: on current nixos-unstable, `boot.extraModulePackages` +# modules placed in `extra/` are NOT indexed by `depmod` (modules.dep / +# modules.alias contain zero `extra/` entries). As a result `modprobe`/udev +# resolve mt7925e / btusb to the stock in-tree drivers, which do not support the +# MediaTek MT7927 (14c3:7927). We therefore force the patched out-of-tree modules +# to load by explicit path, blacklist the in-tree collisions so udev cannot bind +# them first, and fix the BT firmware path the driver expects. +let + # The upstream mt7927 flake installs the BT firmware under + # `mediatek/mt6639/`, but the patched btmtk driver requests it from + # `mediatek/mt7927/`. Provide it at the expected path. + mt7927BtFirmwareFix = pkgs.runCommand "mt7927-bt-firmware-fix" { } '' + src="${inputs.mt7927.packages.${pkgs.system}.firmware}/lib/firmware/mediatek/mt6639/BT_RAM_CODE_MT6639_2_1_hdr.bin" + install -Dm644 "$src" \ + "$out/lib/firmware/mediatek/mt7927/BT_RAM_CODE_MT6639_2_1_hdr.bin" + ''; +in +{ + imports = [ + inputs.mt7927.nixosModules.default + ]; + + hardware.mediatek-mt7927 = { + enable = true; + enableWifi = true; + enableBluetooth = true; + disableAspm = true; # Highly recommended to fix upload speeds + }; + + hardware.firmware = [ mt7927BtFirmwareFix ]; + + boot.blacklistedKernelModules = [ + # Whole mt76 stack (patched extra/ copy replaces it entirely). + "mt76" + "mt76_connac_lib" + "mt792x_lib" + "mt7921_common" + "mt7921e" + "mt7925_common" + "mt7925e" + # Patched bluetooth. + "btusb" + "btmtk" + ]; + + systemd.services.mt7927-force = { + description = "Force-load patched MediaTek MT7927 (Filogic 380) kernel modules"; + wantedBy = [ "multi-user.target" ]; + before = [ "network.target" "NetworkManager.service" ]; + path = [ pkgs.kmod ]; + serviceConfig = { + Type = "oneshot"; + RemainAfterExit = true; + }; + script = '' + KVER="$(uname -r)" + EXTRA="/run/booted-system/kernel-modules/lib/modules/$KVER/extra" + + # Load in-tree core dependencies (these ARE indexed, so modprobe works). + modprobe mac80211 cfg80211 rfkill led-class bluetooth || true + + # Defensive: drop any in-tree mt76 modules that may have been pulled in + # (e.g. via boot.kernelModules) so the patched copies can bind instead. + rmmod mt7925e mt7921e mt7925_common mt7921_common mt792x_lib mt76_connac_lib mt76 2>/dev/null || true + + insmod_x() { + local mod="$1" + local name + name="''${mod##*/}"; name="''${name%.ko}" + if lsmod | grep -q "^$name "; then + echo "mt7927-force: $name already loaded, skipping" + else + echo "mt7927-force: insmod $mod" + insmod "$mod" || echo "mt7927-force: FAILED to insmod $mod" + fi + } + + # Patched mt76 stack (full replacement, dependency order). + insmod_x "$EXTRA/mt76/mt76.ko" + insmod_x "$EXTRA/mt76/mt76-connac-lib.ko" + insmod_x "$EXTRA/mt76/mt792x-lib.ko" + insmod_x "$EXTRA/mt76/mt7921/mt7921-common.ko" + insmod_x "$EXTRA/mt76/mt7925/mt7925-common.ko" + insmod_x "$EXTRA/mt76/mt7921/mt7921e.ko" + insmod_x "$EXTRA/mt76/mt7925/mt7925e.ko" + + # Patched bluetooth. The patched btmtk/btusb need symbols from the + # in-tree bluetooth core (bluetooth.ko) and the btrtl/btintel/btbcm + # helpers, so load those first (they are indexed and modprobe-able). + for m in bluetooth btrtl btintel btbcm rfkill ecdh_generic ecc crc16; do + if modprobe "$m" 2>/dev/null; then + echo "mt7927-force: modprobe $m ok" + else + echo "mt7927-force: modprobe $m FAILED (continuing)" + fi + done + + insmod_x "$EXTRA/bluetooth/btmtk.ko" + insmod_x "$EXTRA/bluetooth/btusb.ko" + ''; + }; +} diff --git a/modules/hosts/14900k/configuration.nix b/modules/hosts/14900k/configuration.nix index fdac7cd..5d7631c 100644 --- a/modules/hosts/14900k/configuration.nix +++ b/modules/hosts/14900k/configuration.nix @@ -23,6 +23,7 @@ ./_private/streaming-display.nix ./_private/ai.nix ./_private/media-disk.nix + ./_private/mediatek-mt7927.nix ./_private/jellyfin-nfs-export.nix ./_private/moonfin-flatpak.nix ]; @@ -44,7 +45,6 @@ libvdpau-va-gl ]; }; - environment.sessionVariables = { LIBVA_DRIVER_NAME = "iHD"; # Force VA-API to use the Intel iGPU render node (otherwise libva may pick NVIDIA and iHD fails).