diff options
Diffstat (limited to 'nixos/modules/hardware')
25 files changed, 840 insertions, 129 deletions
diff --git a/nixos/modules/hardware/acpilight.nix b/nixos/modules/hardware/acpilight.nix index 34e8a222096..2de448a265c 100644 --- a/nixos/modules/hardware/acpilight.nix +++ b/nixos/modules/hardware/acpilight.nix @@ -19,6 +19,7 @@ in }; config = mkIf cfg.enable { + environment.systemPackages = with pkgs; [ acpilight ]; services.udev.packages = with pkgs; [ acpilight ]; }; } diff --git a/nixos/modules/hardware/all-firmware.nix b/nixos/modules/hardware/all-firmware.nix index b07edb0f6ac..3e88a4c20ad 100644 --- a/nixos/modules/hardware/all-firmware.nix +++ b/nixos/modules/hardware/all-firmware.nix @@ -48,7 +48,8 @@ in { rtl8192su-firmware rt5677-firmware rtl8723bs-firmware - rtlwifi_new-firmware + rtl8761b-firmware + rtw88-firmware zd1211fw alsa-firmware sof-firmware diff --git a/nixos/modules/hardware/corectrl.nix b/nixos/modules/hardware/corectrl.nix new file mode 100644 index 00000000000..3185f6486c7 --- /dev/null +++ b/nixos/modules/hardware/corectrl.nix @@ -0,0 +1,62 @@ +{ config, pkgs, lib, ... }: + +with lib; + +let + cfg = config.programs.corectrl; +in +{ + options.programs.corectrl = { + enable = mkEnableOption '' + A tool to overclock amd graphics cards and processors. + Add your user to the corectrl group to run corectrl without needing to enter your password + ''; + + gpuOverclock = { + enable = mkEnableOption '' + true + ''; + ppfeaturemask = mkOption { + type = types.str; + default = "0xfffd7fff"; + example = "0xffffffff"; + description = '' + Sets the `amdgpu.ppfeaturemask` kernel option. + In particular, it is used here to set the overdrive bit. + Default is `0xfffd7fff` as it is less likely to cause flicker issues. + Setting it to `0xffffffff` enables all features. + ''; + }; + }; + }; + + config = mkIf cfg.enable (lib.mkMerge [ + { + environment.systemPackages = [ pkgs.corectrl ]; + + services.dbus.packages = [ pkgs.corectrl ]; + + users.groups.corectrl = { }; + + security.polkit.extraConfig = '' + polkit.addRule(function(action, subject) { + if ((action.id == "org.corectrl.helper.init" || + action.id == "org.corectrl.helperkiller.init") && + subject.local == true && + subject.active == true && + subject.isInGroup("corectrl")) { + return polkit.Result.YES; + } + }); + ''; + } + + (lib.mkIf cfg.gpuOverclock.enable { + # https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/drivers/gpu/drm/amd/include/amd_shared.h#n169 + # The overdrive bit + boot.kernelParams = [ "amdgpu.ppfeaturemask=${cfg.gpuOverclock.ppfeaturemask}" ]; + }) + ]); + + meta.maintainers = with lib.maintainers; [ artturin ]; +} diff --git a/nixos/modules/hardware/device-tree.nix b/nixos/modules/hardware/device-tree.nix index b3f1dda98c8..4aa1d6369d1 100644 --- a/nixos/modules/hardware/device-tree.nix +++ b/nixos/modules/hardware/device-tree.nix @@ -4,11 +4,118 @@ with lib; let cfg = config.hardware.deviceTree; -in { + + overlayType = types.submodule { + options = { + name = mkOption { + type = types.str; + description = '' + Name of this overlay + ''; + }; + + dtsFile = mkOption { + type = types.nullOr types.path; + description = '' + Path to .dts overlay file, overlay is applied to + each .dtb file matching "compatible" of the overlay. + ''; + default = null; + example = literalExample "./dts/overlays.dts"; + }; + + dtsText = mkOption { + type = types.nullOr types.str; + default = null; + description = '' + Literal DTS contents, overlay is applied to + each .dtb file matching "compatible" of the overlay. + ''; + example = literalExample '' + /dts-v1/; + /plugin/; + / { + compatible = "raspberrypi"; + fragment@0 { + target-path = "/soc"; + __overlay__ { + pps { + compatible = "pps-gpio"; + status = "okay"; + }; + }; + }; + }; + ''; + }; + + dtboFile = mkOption { + type = types.nullOr types.path; + default = null; + description = '' + Path to .dtbo compiled overlay file. + ''; + }; + }; + }; + + # this requires kernel package + dtbsWithSymbols = pkgs.stdenv.mkDerivation { + name = "dtbs-with-symbols"; + inherit (cfg.kernelPackage) src nativeBuildInputs depsBuildBuild; + patches = map (patch: patch.patch) cfg.kernelPackage.kernelPatches; + buildPhase = '' + patchShebangs scripts/* + substituteInPlace scripts/Makefile.lib \ + --replace 'DTC_FLAGS += $(DTC_FLAGS_$(basetarget))' 'DTC_FLAGS += $(DTC_FLAGS_$(basetarget)) -@' + make ${pkgs.stdenv.hostPlatform.linux-kernel.baseConfig} ARCH="${pkgs.stdenv.hostPlatform.linuxArch}" + make dtbs ARCH="${pkgs.stdenv.hostPlatform.linuxArch}" + ''; + installPhase = '' + make dtbs_install INSTALL_DTBS_PATH=$out/dtbs ARCH="${pkgs.stdenv.hostPlatform.linuxArch}" + ''; + }; + + filterDTBs = src: if isNull cfg.filter + then "${src}/dtbs" + else + pkgs.runCommand "dtbs-filtered" {} '' + mkdir -p $out + cd ${src}/dtbs + find . -type f -name '${cfg.filter}' -print0 \ + | xargs -0 cp -v --no-preserve=mode --target-directory $out --parents + ''; + + # Compile single Device Tree overlay source + # file (.dts) into its compiled variant (.dtbo) + compileDTS = name: f: pkgs.callPackage({ dtc }: pkgs.stdenv.mkDerivation { + name = "${name}-dtbo"; + + nativeBuildInputs = [ dtc ]; + + buildCommand = '' + dtc -I dts ${f} -O dtb -@ -o $out + ''; + }) {}; + + # Fill in `dtboFile` for each overlay if not set already. + # Existence of one of these is guarded by assertion below + withDTBOs = xs: flip map xs (o: o // { dtboFile = + if isNull o.dtboFile then + if !isNull o.dtsFile then compileDTS o.name o.dtsFile + else compileDTS o.name (pkgs.writeText "dts" o.dtsText) + else o.dtboFile; } ); + +in +{ + imports = [ + (mkRemovedOptionModule [ "hardware" "deviceTree" "base" ] "Use hardware.deviceTree.kernelPackage instead") + ]; + options = { hardware.deviceTree = { enable = mkOption { - default = pkgs.stdenv.hostPlatform.platform.kernelDTB or false; + default = pkgs.stdenv.hostPlatform.linux-kernel.DTB or false; type = types.bool; description = '' Build device tree files. These are used to describe the @@ -16,13 +123,13 @@ in { ''; }; - base = mkOption { - default = "${config.boot.kernelPackages.kernel}/dtbs"; - defaultText = "\${config.boot.kernelPackages.kernel}/dtbs"; - example = literalExample "pkgs.device-tree_rpi"; + kernelPackage = mkOption { + default = config.boot.kernelPackages.kernel; + defaultText = "config.boot.kernelPackages.kernel"; + example = literalExample "pkgs.linux_latest"; type = types.path; description = '' - The path containing the base device-tree (.dtb) to boot. Contains + Kernel package containing the base device-tree (.dtb) to boot. Uses device trees bundled with the Linux kernel by default. ''; }; @@ -38,14 +145,32 @@ in { ''; }; + filter = mkOption { + type = types.nullOr types.str; + default = null; + example = "*rpi*.dtb"; + description = '' + Only include .dtb files matching glob expression. + ''; + }; + overlays = mkOption { default = []; - example = literalExample - "[\"\${pkgs.device-tree_rpi.overlays}/w1-gpio.dtbo\"]"; - type = types.listOf types.path; + example = literalExample '' + [ + { name = "pps"; dtsFile = ./dts/pps.dts; } + { name = "spi"; + dtsText = "..."; + } + { name = "precompiled"; dtboFile = ./dtbos/example.dtbo; } + ] + ''; + type = types.listOf (types.coercedTo types.path (path: { + name = baseNameOf path; + dtboFile = path; + }) overlayType); description = '' - A path containing device tree overlays (.dtbo) to be applied to all - base device-trees. + List of overlays to apply to base device-tree (.dtb) files. ''; }; @@ -54,14 +179,27 @@ in { type = types.nullOr types.path; internal = true; description = '' - A path containing the result of applying `overlays` to `base`. + A path containing the result of applying `overlays` to `kernelPackage`. ''; }; }; }; config = mkIf (cfg.enable) { + + assertions = let + invalidOverlay = o: isNull o.dtsFile && isNull o.dtsText && isNull o.dtboFile; + in lib.singleton { + assertion = lib.all (o: !invalidOverlay o) cfg.overlays; + message = '' + deviceTree overlay needs one of dtsFile, dtsText or dtboFile set. + Offending overlay(s): + ${toString (map (o: o.name) (builtins.filter invalidOverlay cfg.overlays))} + ''; + }; + hardware.deviceTree.package = if (cfg.overlays != []) - then pkgs.deviceTree.applyOverlays cfg.base cfg.overlays else cfg.base; + then pkgs.deviceTree.applyOverlays (filterDTBs dtbsWithSymbols) (withDTBOs cfg.overlays) + else (filterDTBs cfg.kernelPackage); }; } diff --git a/nixos/modules/hardware/i2c.nix b/nixos/modules/hardware/i2c.nix new file mode 100644 index 00000000000..ff14b4b1c89 --- /dev/null +++ b/nixos/modules/hardware/i2c.nix @@ -0,0 +1,43 @@ +{ config, lib, ... }: + +with lib; + +let + cfg = config.hardware.i2c; +in + +{ + options.hardware.i2c = { + enable = mkEnableOption '' + i2c devices support. By default access is granted to users in the "i2c" + group (will be created if non-existent) and any user with a seat, meaning + logged on the computer locally. + ''; + + group = mkOption { + type = types.str; + default = "i2c"; + description = '' + Grant access to i2c devices (/dev/i2c-*) to users in this group. + ''; + }; + }; + + config = mkIf cfg.enable { + + boot.kernelModules = [ "i2c-dev" ]; + + users.groups = mkIf (cfg.group == "i2c") { + i2c = { }; + }; + + services.udev.extraRules = '' + # allow group ${cfg.group} and users with a seat use of i2c devices + ACTION=="add", KERNEL=="i2c-[0-9]*", TAG+="uaccess", GROUP="${cfg.group}", MODE="660" + ''; + + }; + + meta.maintainers = [ maintainers.rnhmjoj ]; + +} diff --git a/nixos/modules/hardware/keyboard/teck.nix b/nixos/modules/hardware/keyboard/teck.nix new file mode 100644 index 00000000000..091ddb81962 --- /dev/null +++ b/nixos/modules/hardware/keyboard/teck.nix @@ -0,0 +1,16 @@ +{ config, lib, pkgs, ... }: + +with lib; +let + cfg = config.hardware.keyboard.teck; +in +{ + options.hardware.keyboard.teck = { + enable = mkEnableOption "non-root access to the firmware of TECK keyboards"; + }; + + config = mkIf cfg.enable { + services.udev.packages = [ pkgs.teck-udev-rules ]; + }; +} + diff --git a/nixos/modules/hardware/keyboard/zsa.nix b/nixos/modules/hardware/keyboard/zsa.nix new file mode 100644 index 00000000000..5cb09e5af49 --- /dev/null +++ b/nixos/modules/hardware/keyboard/zsa.nix @@ -0,0 +1,27 @@ +{ config, lib, pkgs, ... }: + +let + inherit (lib) mkOption mkIf types; + cfg = config.hardware.keyboard.zsa; +in +{ + # TODO: make group configurable like in https://github.com/NixOS/nixpkgs/blob/0b2b4b8c4e729535a61db56468809c5c2d3d175c/pkgs/tools/security/nitrokey-app/udev-rules.nix ? + options.hardware.keyboard.zsa = { + enable = mkOption { + type = types.bool; + default = false; + description = '' + Enables udev rules for keyboards from ZSA like the ErgoDox EZ, Planck EZ and Moonlander Mark I. + You need it when you want to flash a new configuration on the keyboard + or use their live training in the browser. + Access to the keyboard is granted to users in the "plugdev" group. + You may want to install the wally-cli package. + ''; + }; + }; + + config = mkIf cfg.enable { + services.udev.packages = [ pkgs.zsa-udev-rules ]; + users.groups.plugdev = {}; + }; +} diff --git a/nixos/modules/hardware/ksm.nix b/nixos/modules/hardware/ksm.nix index 0938dbdc110..829c3532c45 100644 --- a/nixos/modules/hardware/ksm.nix +++ b/nixos/modules/hardware/ksm.nix @@ -26,13 +26,13 @@ in { systemd.services.enable-ksm = { description = "Enable Kernel Same-Page Merging"; wantedBy = [ "multi-user.target" ]; - after = [ "systemd-udev-settle.service" ]; - script = '' - if [ -e /sys/kernel/mm/ksm ]; then + script = + '' echo 1 > /sys/kernel/mm/ksm/run - ${optionalString (cfg.sleep != null) ''echo ${toString cfg.sleep} > /sys/kernel/mm/ksm/sleep_millisecs''} - fi - ''; + '' + optionalString (cfg.sleep != null) + '' + echo ${toString cfg.sleep} > /sys/kernel/mm/ksm/sleep_millisecs + ''; }; }; } diff --git a/nixos/modules/hardware/network/ath-user-regd.nix b/nixos/modules/hardware/network/ath-user-regd.nix new file mode 100644 index 00000000000..b5ade5ed501 --- /dev/null +++ b/nixos/modules/hardware/network/ath-user-regd.nix @@ -0,0 +1,31 @@ +{ config, lib, pkgs, ... }: + +with lib; +let + kernelVersion = config.boot.kernelPackages.kernel.version; + linuxKernelMinVersion = "5.8"; + kernelPatch = pkgs.kernelPatches.ath_regd_optional // { + extraConfig = '' + ATH_USER_REGD y + ''; + }; +in +{ + options.networking.wireless.athUserRegulatoryDomain = mkOption { + default = false; + type = types.bool; + description = '' + If enabled, sets the ATH_USER_REGD kernel config switch to true to + disable the enforcement of EEPROM regulatory restrictions for ath + drivers. Requires at least Linux ${linuxKernelMinVersion}. + ''; + }; + + config = mkIf config.networking.wireless.athUserRegulatoryDomain { + assertions = singleton { + assertion = lessThan 0 (builtins.compareVersions kernelVersion linuxKernelMinVersion); + message = "ATH_USER_REGD patch for kernels older than ${linuxKernelMinVersion} not ported yet!"; + }; + boot.kernelPatches = [ kernelPatch ]; + }; +} diff --git a/nixos/modules/hardware/nitrokey.nix b/nixos/modules/hardware/nitrokey.nix index 02e4c3f46f8..baa07203118 100644 --- a/nixos/modules/hardware/nitrokey.nix +++ b/nixos/modules/hardware/nitrokey.nix @@ -19,23 +19,9 @@ in nitrokey-app package, depending on your device and needs. ''; }; - - group = mkOption { - type = types.str; - default = "nitrokey"; - example = "wheel"; - description = '' - Grant access to Nitrokey devices to users in this group. - ''; - }; }; config = mkIf cfg.enable { - services.udev.packages = [ - (pkgs.nitrokey-udev-rules.override (attrs: - { inherit (cfg) group; } - )) - ]; - users.groups.${cfg.group} = {}; + services.udev.packages = [ pkgs.nitrokey-udev-rules ]; }; } diff --git a/nixos/modules/hardware/opengl.nix b/nixos/modules/hardware/opengl.nix index 061528f4b1b..a50b5d32c35 100644 --- a/nixos/modules/hardware/opengl.nix +++ b/nixos/modules/hardware/opengl.nix @@ -63,8 +63,7 @@ in description = '' On 64-bit systems, whether to support Direct Rendering for 32-bit applications (such as Wine). This is currently only - supported for the <literal>nvidia</literal> and - <literal>ati_unfree</literal> drivers, as well as + supported for the <literal>nvidia</literal> as well as <literal>Mesa</literal>. ''; }; diff --git a/nixos/modules/hardware/opentabletdriver.nix b/nixos/modules/hardware/opentabletdriver.nix new file mode 100644 index 00000000000..295e23e6164 --- /dev/null +++ b/nixos/modules/hardware/opentabletdriver.nix @@ -0,0 +1,69 @@ +{ config, lib, pkgs, ... }: + +with lib; +let + cfg = config.hardware.opentabletdriver; +in +{ + meta.maintainers = with lib.maintainers; [ thiagokokada ]; + + options = { + hardware.opentabletdriver = { + enable = mkOption { + default = false; + type = types.bool; + description = '' + Enable OpenTabletDriver udev rules, user service and blacklist kernel + modules known to conflict with OpenTabletDriver. + ''; + }; + + blacklistedKernelModules = mkOption { + type = types.listOf types.str; + default = [ "hid-uclogic" "wacom" ]; + description = '' + Blacklist of kernel modules known to conflict with OpenTabletDriver. + ''; + }; + + package = mkOption { + type = types.package; + default = pkgs.opentabletdriver; + defaultText = "pkgs.opentabletdriver"; + description = '' + OpenTabletDriver derivation to use. + ''; + }; + + daemon = { + enable = mkOption { + default = true; + type = types.bool; + description = '' + Whether to start OpenTabletDriver daemon as a systemd user service. + ''; + }; + }; + }; + }; + + config = mkIf cfg.enable { + environment.systemPackages = [ cfg.package ]; + + services.udev.packages = [ cfg.package ]; + + boot.blacklistedKernelModules = cfg.blacklistedKernelModules; + + systemd.user.services.opentabletdriver = with pkgs; mkIf cfg.daemon.enable { + description = "Open source, cross-platform, user-mode tablet driver"; + wantedBy = [ "graphical-session.target" ]; + partOf = [ "graphical-session.target" ]; + + serviceConfig = { + Type = "simple"; + ExecStart = "${cfg.package}/bin/otd-daemon -c ${cfg.package}/lib/OpenTabletDriver/Configurations"; + Restart = "on-failure"; + }; + }; + }; +} diff --git a/nixos/modules/hardware/printers.nix b/nixos/modules/hardware/printers.nix index 752de41f26d..c587076dcd1 100644 --- a/nixos/modules/hardware/printers.nix +++ b/nixos/modules/hardware/printers.nix @@ -15,7 +15,7 @@ let ${ppdOptionsString p.ppdOptions} ''; ensureDefaultPrinter = name: '' - ${pkgs.cups}/bin/lpoptions -d '${name}' + ${pkgs.cups}/bin/lpadmin -d '${name}' ''; # "graph but not # or /" can't be implemented as regex alone due to missing lookahead support diff --git a/nixos/modules/hardware/rtl-sdr.nix b/nixos/modules/hardware/rtl-sdr.nix new file mode 100644 index 00000000000..9605c7967f6 --- /dev/null +++ b/nixos/modules/hardware/rtl-sdr.nix @@ -0,0 +1,19 @@ +{ config, lib, pkgs, ... }: + +let + cfg = config.hardware.rtl-sdr; + +in { + options.hardware.rtl-sdr = { + enable = lib.mkEnableOption '' + Enables rtl-sdr udev rules, ensures 'plugdev' group exists, and blacklists DVB kernel modules. + This is a prerequisite to using devices supported by rtl-sdr without being root, since rtl-sdr USB descriptors will be owned by plugdev through udev. + ''; + }; + + config = lib.mkIf cfg.enable { + boot.blacklistedKernelModules = [ "dvb_usb_rtl28xxu" "e4000" "rtl2832" ]; + services.udev.packages = [ pkgs.rtl-sdr ]; + users.groups.plugdev = {}; + }; +} diff --git a/nixos/modules/hardware/sata.nix b/nixos/modules/hardware/sata.nix new file mode 100644 index 00000000000..541897527a8 --- /dev/null +++ b/nixos/modules/hardware/sata.nix @@ -0,0 +1,100 @@ +{ config, lib, pkgs, ... }: +let + inherit (lib) mkEnableOption mkIf mkOption types; + + cfg = config.hardware.sata.timeout; + + buildRule = d: + lib.concatStringsSep ", " [ + ''ACTION=="add"'' + ''SUBSYSTEM=="block"'' + ''ENV{ID_${lib.toUpper d.idBy}}=="${d.name}"'' + ''TAG+="systemd"'' + ''ENV{SYSTEMD_WANTS}="${unitName d}"'' + ]; + + devicePath = device: + "/dev/disk/by-${device.idBy}/${device.name}"; + + unitName = device: + "sata-timeout-${lib.strings.sanitizeDerivationName device.name}"; + + startScript = + pkgs.writeShellScript "sata-timeout.sh" '' + set -eEuo pipefail + + device="$1" + + ${pkgs.smartmontools}/bin/smartctl \ + -l scterc,${toString cfg.deciSeconds},${toString cfg.deciSeconds} \ + --quietmode errorsonly \ + "$device" + ''; + +in +{ + meta.maintainers = with lib.maintainers; [ peterhoeg ]; + + options.hardware.sata.timeout = { + enable = mkEnableOption "SATA drive timeouts"; + + deciSeconds = mkOption { + example = "70"; + type = types.int; + description = '' + Set SCT Error Recovery Control timeout in deciseconds for use in RAID configurations. + + Values are as follows: + 0 = disable SCT ERT + 70 = default in consumer drives (7 seconds) + + Maximum is disk dependant but probably 60 seconds. + ''; + }; + + drives = mkOption { + description = "List of drives for which to configure the timeout."; + type = types.listOf + (types.submodule { + options = { + name = mkOption { + description = "Drive name without the full path."; + type = types.str; + }; + + idBy = mkOption { + description = "The method to identify the drive."; + type = types.enum [ "path" "wwn" ]; + default = "path"; + }; + }; + }); + }; + }; + + config = mkIf cfg.enable { + services.udev.extraRules = lib.concatMapStringsSep "\n" buildRule cfg.drives; + + systemd.services = lib.listToAttrs (map + (e: + lib.nameValuePair (unitName e) { + description = "SATA timeout for ${e.name}"; + wantedBy = [ "sata-timeout.target" ]; + serviceConfig = { + Type = "oneshot"; + ExecStart = "${startScript} '${devicePath e}'"; + PrivateTmp = true; + PrivateNetwork = true; + ProtectHome = "tmpfs"; + ProtectSystem = "strict"; + }; + } + ) + cfg.drives); + + systemd.targets.sata-timeout = { + description = "SATA timeout"; + wantedBy = [ "multi-user.target" ]; + }; + }; +} diff --git a/nixos/modules/hardware/sensor/hddtemp.nix b/nixos/modules/hardware/sensor/hddtemp.nix new file mode 100644 index 00000000000..df3f75e229a --- /dev/null +++ b/nixos/modules/hardware/sensor/hddtemp.nix @@ -0,0 +1,81 @@ +{ config, lib, pkgs, ... }: +let + inherit (lib) mkIf mkOption types; + + cfg = config.hardware.sensor.hddtemp; + + wrapper = pkgs.writeShellScript "hddtemp-wrapper" '' + set -eEuo pipefail + + file=/var/lib/hddtemp/hddtemp.db + + drives=(${toString (map (e: ''$(realpath ${lib.escapeShellArg e}) '') cfg.drives)}) + + cp ${pkgs.hddtemp}/share/hddtemp/hddtemp.db $file + ${lib.concatMapStringsSep "\n" (e: "echo ${lib.escapeShellArg e} >> $file") cfg.dbEntries} + + exec ${pkgs.hddtemp}/bin/hddtemp ${lib.escapeShellArgs cfg.extraArgs} \ + --daemon \ + --unit=${cfg.unit} \ + --file=$file \ + ''${drives[@]} + ''; + +in +{ + meta.maintainers = with lib.maintainers; [ peterhoeg ]; + + ###### interface + + options = { + hardware.sensor.hddtemp = { + enable = mkOption { + description = '' + Enable this option to support HDD/SSD temperature sensors. + ''; + type = types.bool; + default = false; + }; + + drives = mkOption { + description = "List of drives to monitor. If you pass /dev/disk/by-path/* entries the symlinks will be resolved as hddtemp doesn't like names with colons."; + type = types.listOf types.str; + }; + + unit = mkOption { + description = "Celcius or Fahrenheit"; + type = types.enum [ "C" "F" ]; + default = "C"; + }; + + dbEntries = mkOption { + description = "Additional DB entries"; + type = types.listOf types.str; + default = [ ]; + }; + + extraArgs = mkOption { + description = "Additional arguments passed to the daemon."; + type = types.listOf types.str; + default = [ ]; + }; + }; + }; + + ###### implementation + + config = mkIf cfg.enable { + systemd.services.hddtemp = { + description = "HDD/SSD temperature"; + wantedBy = [ "multi-user.target" ]; + serviceConfig = { + Type = "forking"; + ExecStart = wrapper; + StateDirectory = "hddtemp"; + PrivateTmp = true; + ProtectHome = "tmpfs"; + ProtectSystem = "strict"; + }; + }; + }; +} diff --git a/nixos/modules/hardware/sensor/iio.nix b/nixos/modules/hardware/sensor/iio.nix index 4c359c3b172..8b3ba87a7d9 100644 --- a/nixos/modules/hardware/sensor/iio.nix +++ b/nixos/modules/hardware/sensor/iio.nix @@ -9,7 +9,7 @@ with lib; hardware.sensor.iio = { enable = mkOption { description = '' - Enable this option to support IIO sensors. + Enable this option to support IIO sensors with iio-sensor-proxy. IIO sensors are used for orientation and ambient light sensors on some mobile devices. diff --git a/nixos/modules/hardware/system-76.nix b/nixos/modules/hardware/system-76.nix new file mode 100644 index 00000000000..d4896541dba --- /dev/null +++ b/nixos/modules/hardware/system-76.nix @@ -0,0 +1,85 @@ +{ config, lib, pkgs, ... }: + +let + inherit (lib) mkOption mkEnableOption types mkIf mkMerge optional versionOlder; + cfg = config.hardware.system76; + + kpkgs = config.boot.kernelPackages; + modules = [ "system76" "system76-io" ] ++ (optional (versionOlder kpkgs.kernel.version "5.5") "system76-acpi"); + modulePackages = map (m: kpkgs.${m}) modules; + moduleConfig = mkIf cfg.kernel-modules.enable { + boot.extraModulePackages = modulePackages; + + boot.kernelModules = modules; + + services.udev.packages = modulePackages; + }; + + firmware-pkg = pkgs.system76-firmware; + firmwareConfig = mkIf cfg.firmware-daemon.enable { + # Make system76-firmware-cli usable by root from the command line. + environment.systemPackages = [ firmware-pkg ]; + + services.dbus.packages = [ firmware-pkg ]; + + systemd.services.system76-firmware-daemon = { + description = "The System76 Firmware Daemon"; + + serviceConfig = { + ExecStart = "${firmware-pkg}/bin/system76-firmware-daemon"; + + Restart = "on-failure"; + }; + + wantedBy = [ "multi-user.target" ]; + }; + }; + + power-pkg = config.boot.kernelPackages.system76-power; + powerConfig = mkIf cfg.power-daemon.enable { + # Make system76-power usable by root from the command line. + environment.systemPackages = [ power-pkg ]; + + services.dbus.packages = [ power-pkg ]; + + systemd.services.system76-power = { + description = "System76 Power Daemon"; + serviceConfig = { + ExecStart = "${power-pkg}/bin/system76-power daemon"; + Restart = "on-failure"; + Type = "dbus"; + BusName = "com.system76.PowerDaemon"; + }; + wantedBy = [ "multi-user.target" ]; + }; + }; +in { + options = { + hardware.system76 = { + enableAll = mkEnableOption "all recommended configuration for system76 systems"; + + firmware-daemon.enable = mkOption { + default = cfg.enableAll; + example = true; + description = "Whether to enable the system76 firmware daemon"; + type = types.bool; + }; + + kernel-modules.enable = mkOption { + default = cfg.enableAll; + example = true; + description = "Whether to make the system76 out-of-tree kernel modules available"; + type = types.bool; + }; + + power-daemon.enable = mkOption { + default = cfg.enableAll; + example = true; + description = "Whether to enable the system76 power daemon"; + type = types.bool; + }; + }; + }; + + config = mkMerge [ moduleConfig firmwareConfig powerConfig ]; +} diff --git a/nixos/modules/hardware/ubertooth.nix b/nixos/modules/hardware/ubertooth.nix new file mode 100644 index 00000000000..637fddfb37d --- /dev/null +++ b/nixos/modules/hardware/ubertooth.nix @@ -0,0 +1,29 @@ +{ config, lib, pkgs, ... }: + +with lib; + +let + cfg = config.hardware.ubertooth; + + ubertoothPkg = pkgs.ubertooth.override { + udevGroup = cfg.group; + }; +in { + options.hardware.ubertooth = { + enable = mkEnableOption "Enable the Ubertooth software and its udev rules."; + + group = mkOption { + type = types.str; + default = "ubertooth"; + example = "wheel"; + description = "Group for Ubertooth's udev rules."; + }; + }; + + config = mkIf cfg.enable { + environment.systemPackages = [ ubertoothPkg ]; + + services.udev.packages = [ ubertoothPkg ]; + users.groups.${cfg.group} = {}; + }; +} diff --git a/nixos/modules/hardware/video/amdgpu.nix b/nixos/modules/hardware/video/amdgpu.nix deleted file mode 100644 index 42fc8fa362d..00000000000 --- a/nixos/modules/hardware/video/amdgpu.nix +++ /dev/null @@ -1,9 +0,0 @@ -{ config, lib, ... }: - -with lib; -{ - config = mkIf (elem "amdgpu" config.services.xserver.videoDrivers) { - boot.blacklistedKernelModules = [ "radeon" ]; - }; -} - diff --git a/nixos/modules/hardware/video/ati.nix b/nixos/modules/hardware/video/ati.nix deleted file mode 100644 index 06d3ea324d8..00000000000 --- a/nixos/modules/hardware/video/ati.nix +++ /dev/null @@ -1,40 +0,0 @@ -# This module provides the proprietary ATI X11 / OpenGL drivers. - -{ config, lib, pkgs, ... }: - -with lib; - -let - - drivers = config.services.xserver.videoDrivers; - - enabled = elem "ati_unfree" drivers; - - ati_x11 = config.boot.kernelPackages.ati_drivers_x11; - -in - -{ - - config = mkIf enabled { - - nixpkgs.config.xorg.abiCompat = "1.17"; - - services.xserver.drivers = singleton - { name = "fglrx"; modules = [ ati_x11 ]; display = true; }; - - hardware.opengl.package = ati_x11; - hardware.opengl.package32 = pkgs.pkgsi686Linux.linuxPackages.ati_drivers_x11.override { libsOnly = true; kernel = null; }; - hardware.opengl.setLdLibraryPath = true; - - environment.systemPackages = [ ati_x11 ]; - - boot.extraModulePackages = [ ati_x11 ]; - - boot.blacklistedKernelModules = [ "radeon" ]; - - environment.etc.ati.source = "${ati_x11}/etc/ati"; - - }; - -} diff --git a/nixos/modules/hardware/video/bumblebee.nix b/nixos/modules/hardware/video/bumblebee.nix index 2278c7b4061..b6af4f80445 100644 --- a/nixos/modules/hardware/video/bumblebee.nix +++ b/nixos/modules/hardware/video/bumblebee.nix @@ -40,7 +40,7 @@ in default = "wheel"; example = "video"; type = types.str; - description = ''Group for bumblebee socket''; + description = "Group for bumblebee socket"; }; connectDisplay = mkOption { diff --git a/nixos/modules/hardware/video/nvidia.nix b/nixos/modules/hardware/video/nvidia.nix index 6328971492c..2be9da8f42a 100644 --- a/nixos/modules/hardware/video/nvidia.nix +++ b/nixos/modules/hardware/video/nvidia.nix @@ -5,34 +5,17 @@ with lib; let - - drivers = config.services.xserver.videoDrivers; - - # FIXME: should introduce an option like - # ‘hardware.video.nvidia.package’ for overriding the default NVIDIA - # driver. - nvidiaForKernel = kernelPackages: - if elem "nvidia" drivers then - kernelPackages.nvidia_x11 - else if elem "nvidiaBeta" drivers then - kernelPackages.nvidia_x11_beta - else if elem "nvidiaLegacy304" drivers then - kernelPackages.nvidia_x11_legacy304 - else if elem "nvidiaLegacy340" drivers then - kernelPackages.nvidia_x11_legacy340 - else if elem "nvidiaLegacy390" drivers then - kernelPackages.nvidia_x11_legacy390 - else null; - - nvidia_x11 = nvidiaForKernel config.boot.kernelPackages; - nvidia_libs32 = - if versionOlder nvidia_x11.version "391" then - ((nvidiaForKernel pkgs.pkgsi686Linux.linuxPackages).override { libsOnly = true; kernel = null; }).out - else - (nvidiaForKernel config.boot.kernelPackages).lib32; + nvidia_x11 = let + drivers = config.services.xserver.videoDrivers; + isDeprecated = str: (hasPrefix "nvidia" str) && (str != "nvidia"); + hasDeprecated = drivers: any isDeprecated drivers; + in if (hasDeprecated drivers) then + throw '' + Selecting an nvidia driver has been modified for NixOS 19.03. The version is now set using `hardware.nvidia.package`. + '' + else if (elem "nvidia" drivers) then cfg.package else null; enabled = nvidia_x11 != null; - cfg = config.hardware.nvidia; pCfg = cfg.prime; @@ -61,6 +44,15 @@ in ''; }; + hardware.nvidia.powerManagement.finegrained = mkOption { + type = types.bool; + default = false; + description = '' + Experimental power management of PRIME offload. For more information, see + the NVIDIA docs, chapter 22. PCI-Express runtime power management. + ''; + }; + hardware.nvidia.modesetting.enable = mkOption { type = types.bool; default = false; @@ -94,6 +86,16 @@ in ''; }; + hardware.nvidia.prime.amdgpuBusId = mkOption { + type = types.str; + default = ""; + example = "PCI:4:0:0"; + description = '' + Bus ID of the AMD APU. You can find it using lspci; for example if lspci + shows the AMD APU at "04:00.0", set this option to "PCI:4:0:0". + ''; + }; + hardware.nvidia.prime.sync.enable = mkOption { type = types.bool; default = false; @@ -149,9 +151,22 @@ in GPUs stay awake even during headless mode. ''; }; + + hardware.nvidia.package = lib.mkOption { + type = lib.types.package; + default = config.boot.kernelPackages.nvidiaPackages.stable; + defaultText = "config.boot.kernelPackages.nvidiaPackages.stable"; + description = '' + The NVIDIA X11 derivation to use. + ''; + example = "config.boot.kernelPackages.nvidiaPackages.legacy_340"; + }; }; - config = mkIf enabled { + config = let + igpuDriver = if pCfg.intelBusId != "" then "modesetting" else "amdgpu"; + igpuBusId = if pCfg.intelBusId != "" then pCfg.intelBusId else pCfg.amdgpuBusId; + in mkIf enabled { assertions = [ { assertion = with config.services.xserver.displayManager; gdm.nvidiaWayland -> cfg.modesetting.enable; @@ -159,7 +174,13 @@ in } { - assertion = primeEnabled -> pCfg.nvidiaBusId != "" && pCfg.intelBusId != ""; + assertion = primeEnabled -> pCfg.intelBusId == "" || pCfg.amdgpuBusId == ""; + message = '' + You cannot configure both an Intel iGPU and an AMD APU. Pick the one corresponding to your processor. + ''; + } + { + assertion = primeEnabled -> pCfg.nvidiaBusId != "" && (pCfg.intelBusId != "" || pCfg.amdgpuBusId != ""); message = '' When NVIDIA PRIME is enabled, the GPU bus IDs must configured. ''; @@ -172,6 +193,14 @@ in assertion = !(syncCfg.enable && offloadCfg.enable); message = "Only one NVIDIA PRIME solution may be used at a time."; } + { + assertion = !(syncCfg.enable && cfg.powerManagement.finegrained); + message = "Sync precludes powering down the NVIDIA GPU."; + } + { + assertion = cfg.powerManagement.enable -> offloadCfg.enable; + message = "Fine-grained power management requires offload to be enabled."; + } ]; # If Optimus/PRIME is enabled, we: @@ -181,18 +210,22 @@ in # "nvidia" driver, in order to allow the X server to start without any outputs. # - Add a separate Device section for the Intel GPU, using the "modesetting" # driver and with the configured BusID. + # - OR add a separate Device section for the AMD APU, using the "amdgpu" + # driver and with the configures BusID. # - Reference that Device section from the ServerLayout section as an inactive # device. # - Configure the display manager to run specific `xrandr` commands which will - # configure/enable displays connected to the Intel GPU. + # configure/enable displays connected to the Intel iGPU / AMD APU. services.xserver.useGlamor = mkDefault offloadCfg.enable; - services.xserver.drivers = optional primeEnabled { - name = "modesetting"; + services.xserver.drivers = let + in optional primeEnabled { + name = igpuDriver; display = offloadCfg.enable; + modules = optional (igpuDriver == "amdgpu") [ pkgs.xorg.xf86videoamdgpu ]; deviceSection = '' - BusID "${pCfg.intelBusId}" + BusID "${igpuBusId}" ${optionalString syncCfg.enable ''Option "AccelMethod" "none"''} ''; } ++ singleton { @@ -203,6 +236,7 @@ in '' BusID "${pCfg.nvidiaBusId}" ${optionalString syncCfg.allowExternalGpu "Option \"AllowExternalGpus\""} + ${optionalString cfg.powerManagement.finegrained "Option \"NVreg_DynamicPowerManagement=0x02\""} ''; screenSection = '' @@ -212,14 +246,14 @@ in }; services.xserver.serverLayoutSection = optionalString syncCfg.enable '' - Inactive "Device-modesetting[0]" + Inactive "Device-${igpuDriver}[0]" '' + optionalString offloadCfg.enable '' Option "AllowNVIDIAGPUScreens" ''; services.xserver.displayManager.setupCommands = optionalString syncCfg.enable '' # Added by nvidia configuration module for Optimus/PRIME. - ${pkgs.xorg.xrandr}/bin/xrandr --setprovideroutputsource modesetting NVIDIA-0 + ${pkgs.xorg.xrandr}/bin/xrandr --setprovideroutputsource ${igpuDriver} NVIDIA-0 ${pkgs.xorg.xrandr}/bin/xrandr --auto ''; @@ -228,12 +262,12 @@ in }; hardware.opengl.package = mkIf (!offloadCfg.enable) nvidia_x11.out; - hardware.opengl.package32 = mkIf (!offloadCfg.enable) nvidia_libs32; + hardware.opengl.package32 = mkIf (!offloadCfg.enable) nvidia_x11.lib32; hardware.opengl.extraPackages = optional offloadCfg.enable nvidia_x11.out; - hardware.opengl.extraPackages32 = optional offloadCfg.enable nvidia_libs32; + hardware.opengl.extraPackages32 = optional offloadCfg.enable nvidia_x11.lib32; environment.systemPackages = [ nvidia_x11.bin nvidia_x11.settings ] - ++ filter (p: p != null) [ nvidia_x11.persistenced ]; + ++ optionals nvidiaPersistencedEnabled [ nvidia_x11.persistenced ]; systemd.packages = optional cfg.powerManagement.enable nvidia_x11.out; @@ -290,16 +324,37 @@ in boot.kernelParams = optional (offloadCfg.enable || cfg.modesetting.enable) "nvidia-drm.modeset=1" ++ optional cfg.powerManagement.enable "nvidia.NVreg_PreserveVideoMemoryAllocations=1"; - # Create /dev/nvidia-uvm when the nvidia-uvm module is loaded. services.udev.extraRules = '' + # Create /dev/nvidia-uvm when the nvidia-uvm module is loaded. KERNEL=="nvidia", RUN+="${pkgs.runtimeShell} -c 'mknod -m 666 /dev/nvidiactl c $$(grep nvidia-frontend /proc/devices | cut -d \ -f 1) 255'" KERNEL=="nvidia_modeset", RUN+="${pkgs.runtimeShell} -c 'mknod -m 666 /dev/nvidia-modeset c $$(grep nvidia-frontend /proc/devices | cut -d \ -f 1) 254'" KERNEL=="card*", SUBSYSTEM=="drm", DRIVERS=="nvidia", RUN+="${pkgs.runtimeShell} -c 'mknod -m 666 /dev/nvidia%n c $$(grep nvidia-frontend /proc/devices | cut -d \ -f 1) %n'" KERNEL=="nvidia_uvm", RUN+="${pkgs.runtimeShell} -c 'mknod -m 666 /dev/nvidia-uvm c $$(grep nvidia-uvm /proc/devices | cut -d \ -f 1) 0'" KERNEL=="nvidia_uvm", RUN+="${pkgs.runtimeShell} -c 'mknod -m 666 /dev/nvidia-uvm-tools c $$(grep nvidia-uvm /proc/devices | cut -d \ -f 1) 0'" + '' + optionalString cfg.powerManagement.finegrained '' + # Remove NVIDIA USB xHCI Host Controller devices, if present + ACTION=="add", SUBSYSTEM=="pci", ATTR{vendor}=="0x10de", ATTR{class}=="0x0c0330", ATTR{remove}="1" + + # Remove NVIDIA USB Type-C UCSI devices, if present + ACTION=="add", SUBSYSTEM=="pci", ATTR{vendor}=="0x10de", ATTR{class}=="0x0c8000", ATTR{remove}="1" + + # Remove NVIDIA Audio devices, if present + ACTION=="add", SUBSYSTEM=="pci", ATTR{vendor}=="0x10de", ATTR{class}=="0x040300", ATTR{remove}="1" + + # Enable runtime PM for NVIDIA VGA/3D controller devices on driver bind + ACTION=="bind", SUBSYSTEM=="pci", ATTR{vendor}=="0x10de", ATTR{class}=="0x030000", TEST=="power/control", ATTR{power/control}="auto" + ACTION=="bind", SUBSYSTEM=="pci", ATTR{vendor}=="0x10de", ATTR{class}=="0x030200", TEST=="power/control", ATTR{power/control}="auto" + + # Disable runtime PM for NVIDIA VGA/3D controller devices on driver unbind + ACTION=="unbind", SUBSYSTEM=="pci", ATTR{vendor}=="0x10de", ATTR{class}=="0x030000", TEST=="power/control", ATTR{power/control}="on" + ACTION=="unbind", SUBSYSTEM=="pci", ATTR{vendor}=="0x10de", ATTR{class}=="0x030200", TEST=="power/control", ATTR{power/control}="on" ''; + boot.extraModprobeConfig = mkIf cfg.powerManagement.finegrained '' + options nvidia "NVreg_DynamicPowerManagement=0x02" + ''; + boot.blacklistedKernelModules = [ "nouveau" "nvidiafb" ]; services.acpid.enable = true; diff --git a/nixos/modules/hardware/video/switcheroo-control.nix b/nixos/modules/hardware/video/switcheroo-control.nix new file mode 100644 index 00000000000..199adb2ad8f --- /dev/null +++ b/nixos/modules/hardware/video/switcheroo-control.nix @@ -0,0 +1,18 @@ +{ config, pkgs, lib, ... }: + +with lib; +let + pkg = [ pkgs.switcheroo-control ]; + cfg = config.services.switcherooControl; +in { + options.services.switcherooControl = { + enable = mkEnableOption "switcheroo-control, a D-Bus service to check the availability of dual-GPU"; + }; + + config = mkIf cfg.enable { + services.dbus.packages = pkg; + environment.systemPackages = pkg; + systemd.packages = pkg; + systemd.targets.multi-user.wants = [ "switcheroo-control.service" ]; + }; +} diff --git a/nixos/modules/hardware/xpadneo.nix b/nixos/modules/hardware/xpadneo.nix index d504697e61f..dbc4ba21256 100644 --- a/nixos/modules/hardware/xpadneo.nix +++ b/nixos/modules/hardware/xpadneo.nix @@ -24,6 +24,6 @@ in }; meta = { - maintainers = with maintainers; [ metadark ]; + maintainers = with maintainers; [ kira-bruneau ]; }; } |