refactor: change to litterate config
Configuration is now held by the `.org` files. All `.nix` files are tangled from the org-mode files.
This commit is contained in:
+45
-59
@@ -1,64 +1,50 @@
|
||||
{
|
||||
flake.modules.nixos.amdgpu = {
|
||||
pkgs,
|
||||
lib,
|
||||
config,
|
||||
...
|
||||
}:
|
||||
with lib; let
|
||||
cfg = config.mySystem.hardware.amdgpu;
|
||||
in {
|
||||
options.mySystem.hardware.amdgpu.enable = mkEnableOption "Enables an AMD GPU configuration";
|
||||
config = mkIf cfg.enable {
|
||||
hardware = {
|
||||
graphics = {
|
||||
enable = true;
|
||||
enable32Bit = true;
|
||||
extraPackages = with pkgs; [
|
||||
mesa # Mesa drivers for AMD GPUs
|
||||
rocmPackages.clr # common language runtime for ROCm
|
||||
rocmPackages.clr.icd # ROCm ICD for OpenCL
|
||||
rocmPackages.rocblas # ROCm BLAS library
|
||||
rocmPackages.hipblas #
|
||||
rocmPackages.rpp # High-performance computer vision library
|
||||
nvtopPackages.amd # GPU utilization monitoring
|
||||
];
|
||||
};
|
||||
amdgpu = {
|
||||
initrd.enable = true;
|
||||
opencl.enable = true;
|
||||
};
|
||||
};
|
||||
environment.systemPackages = with pkgs; [
|
||||
clinfo
|
||||
amdgpu_top
|
||||
nvtopPackages.amd
|
||||
];
|
||||
systemd = {
|
||||
packages = with pkgs; [lact];
|
||||
services.lactd.wantedBy = ["multi-user.target"];
|
||||
tmpfiles.rules = let
|
||||
rocmEnv = pkgs.symlinkJoin {
|
||||
name = "rocm-combined";
|
||||
paths = with pkgs.rocmPackages; [
|
||||
clr
|
||||
clr.icd
|
||||
rocblas
|
||||
hipblas
|
||||
rpp
|
||||
];
|
||||
};
|
||||
in [
|
||||
"L+ /opt/rocm - - - - ${rocmEnv}"
|
||||
flake.modules.nixos.amdgpu = {pkgs, ...}: {
|
||||
hardware.graphics = {
|
||||
enable = true;
|
||||
enable32Bit = true;
|
||||
};
|
||||
hardware.amdgpu = {
|
||||
initrd.enable = true;
|
||||
opencl.enable = true;
|
||||
};
|
||||
hardware.graphics.extraPackages = with pkgs; [
|
||||
mesa
|
||||
rocmPackages.clr
|
||||
rocmPackages.clr.icd
|
||||
rocmPackages.rocblas
|
||||
rocmPackages.hipblas
|
||||
rocmPackages.rpp
|
||||
nvtopPackages.amd
|
||||
];
|
||||
environment.systemPackages = with pkgs; [
|
||||
clinfo
|
||||
amdgpu_top
|
||||
nvtopPackages.amd
|
||||
];
|
||||
systemd = {
|
||||
packages = with pkgs; [lact];
|
||||
services.lactd.wantedBy = ["multi-user.target"];
|
||||
tmpfiles.rules = let
|
||||
rocmEnv = pkgs.symlinkJoin {
|
||||
name = "rocm-combined";
|
||||
paths = with pkgs.rocmPackages; [
|
||||
clr
|
||||
clr.icd
|
||||
rocblas
|
||||
hipblas
|
||||
rpp
|
||||
];
|
||||
};
|
||||
environment.variables = {
|
||||
ROCM_PATH = "/opt/rocm"; # Set ROCm path
|
||||
HIP_VISIBLE_DEVICES = "1"; # Use only the eGPU (ID 1)
|
||||
ROCM_VISIBLE_DEVICES = "1"; # Optional: ROCm equivalent for visibility
|
||||
# LD_LIBRARY_PATH = "/opt/rocm/lib"; # Add ROCm libraries
|
||||
HSA_OVERRIDE_GFX_VERSION = "10.3.0"; # Set GFX version override
|
||||
};
|
||||
};
|
||||
in [
|
||||
"L+ /opt/rocm - - - - ${rocmEnv}"
|
||||
];
|
||||
};
|
||||
environment.variables = {
|
||||
ROCM_PATH = "/opt/rocm";
|
||||
HIP_VISIBLE_DEVICES = "1";
|
||||
ROCM_VISIBLE_DEVICES = "1";
|
||||
HSA_OVERRIDE_GFX_VERSION = "10.3.0";
|
||||
};
|
||||
};
|
||||
}
|
||||
|
||||
@@ -0,0 +1,147 @@
|
||||
#+title: AMD GPU support
|
||||
#+setupfile: ../headers
|
||||
#+property: header-args:emacs-lisp :lexical t :exports none :tangle no
|
||||
|
||||
* AMD GPU support
|
||||
Only one of my machines has an AMD GPU, but it does require some
|
||||
tweaking. First, here’s the skeleton of the =nixos.amdgpu= module.
|
||||
#+begin_src nix :tangle yes
|
||||
{
|
||||
flake.modules.nixos.amdgpu = {pkgs, ...}: {
|
||||
<<enable-graphics>>
|
||||
<<enable-hardware>>
|
||||
<<hardware-extra-packages>>
|
||||
<<system-packages>>
|
||||
<<lact>>
|
||||
<<environment-variables>>
|
||||
};
|
||||
}
|
||||
#+end_src
|
||||
|
||||
** Enable the Hardware
|
||||
The first thing is to enable graphics in NixOS. We’ll enable 32-bit
|
||||
support while we’re at it.
|
||||
#+name: enable-graphics
|
||||
#+begin_src nix
|
||||
hardware.graphics = {
|
||||
enable = true;
|
||||
enable32Bit = true;
|
||||
};
|
||||
#+end_src
|
||||
|
||||
We can now enable the hardware proper, including initrd and OpenCL
|
||||
support for the GPU. =initrd.enable= already makes NixOS load =amdgpu= as
|
||||
early as stage 1 on its own, which is why the kernel module (see
|
||||
[[file:../boot/kernel.org][Kernel Configuration]]) doesn’t need to pick between =amdgpu= and =i915=
|
||||
itself: it can simply default to =i915= and let this module handle its
|
||||
own early loading.
|
||||
#+name: enable-hardware
|
||||
#+begin_src nix
|
||||
hardware.amdgpu = {
|
||||
initrd.enable = true;
|
||||
opencl.enable = true;
|
||||
};
|
||||
#+end_src
|
||||
|
||||
Some software expect some packages to be installed by default, such as
|
||||
rocblas or Hipblas. Here are these packages.
|
||||
#+name: amd-packages
|
||||
| Package Name | Description |
|
||||
|----------------------+--------------------------------------------------------------------|
|
||||
| =mesa= | Mesa drivers for AMD GPUs |
|
||||
| =rocmPackages.clr= | Common Language Runtime for ROCm |
|
||||
| =rocmPackages.clr.icd= | ROCm ICD for OpenCL |
|
||||
| =rocmPackages.rocblas= | ROCm BLAS library |
|
||||
| =rocmPackages.hipblas= | HIP BLAS marshalling library (CUDA-compatible interface to rocBLAS) |
|
||||
| =rocmPackages.rpp= | High-performance computer vision library |
|
||||
| =nvtopPackages.amd= | Just for me, GPU utilisation monitoring |
|
||||
|
||||
#+name: extra-hardware-packages
|
||||
#+begin_src emacs-lisp :var packages=amd-packages :cache yes
|
||||
(mapconcat (lambda (package) (s-chop-prefix "=" (s-chop-suffix "=" package)))
|
||||
(mapcar #'car packages)
|
||||
"\n")
|
||||
#+end_src
|
||||
|
||||
#+RESULTS[28ba71596b4f184338e46c76c0ba1aa41899bba0]: extra-hardware-packages
|
||||
: mesa
|
||||
: rocmPackages.clr
|
||||
: rocmPackages.clr.icd
|
||||
: rocmPackages.rocblas
|
||||
: rocmPackages.hipblas
|
||||
: rocmPackages.rpp
|
||||
: nvtopPackages.amd
|
||||
|
||||
#+name: hardware-extra-packages
|
||||
#+begin_src nix
|
||||
hardware.graphics.extraPackages = with pkgs; [
|
||||
<<extra-hardware-packages()>>
|
||||
];
|
||||
#+end_src
|
||||
|
||||
** Diagnostics and Monitoring
|
||||
Beyond what’s needed by the driver stack itself, I also want a couple
|
||||
of tools available on the command line to check on the GPU: =clinfo= to
|
||||
inspect the available OpenCL platforms and devices, =amdgpu_top= for a
|
||||
=btop=-like view of the AMD GPU’s activity, and =nvtop= (packaged for AMD
|
||||
under =nvtopPackages.amd=) for a more familiar process-oriented monitor.
|
||||
#+name: system-packages
|
||||
#+begin_src nix
|
||||
environment.systemPackages = with pkgs; [
|
||||
clinfo
|
||||
amdgpu_top
|
||||
nvtopPackages.amd
|
||||
];
|
||||
#+end_src
|
||||
|
||||
** LACT, the GPU Control Daemon
|
||||
[[https://github.com/ilya-zlobintsev/LACT][LACT]] (Linux AMDGPU Control Application) lets me tweak fan curves,
|
||||
power limits and clocks on the card, through a daemon (=lactd=) and a
|
||||
GUI that talks to it. The package ships both a systemd service
|
||||
definition and a udev rule, so all that’s left for me to do is install
|
||||
the package and make sure the daemon is started.
|
||||
|
||||
I’m also consolidating the ROCm libraries under =/opt/rocm= via a
|
||||
=tmpfiles= rule. Some tools out there still expect to find ROCm
|
||||
installed at that standard filesystem location rather than resolved
|
||||
through the Nix store, so I build a combined derivation of the ROCm
|
||||
packages I need and symlink it into place.
|
||||
#+name: lact
|
||||
#+begin_src nix
|
||||
systemd = {
|
||||
packages = with pkgs; [lact];
|
||||
services.lactd.wantedBy = ["multi-user.target"];
|
||||
tmpfiles.rules = let
|
||||
rocmEnv = pkgs.symlinkJoin {
|
||||
name = "rocm-combined";
|
||||
paths = with pkgs.rocmPackages; [
|
||||
clr
|
||||
clr.icd
|
||||
rocblas
|
||||
hipblas
|
||||
rpp
|
||||
];
|
||||
};
|
||||
in [
|
||||
"L+ /opt/rocm - - - - ${rocmEnv}"
|
||||
];
|
||||
};
|
||||
#+end_src
|
||||
|
||||
** Environment Variables
|
||||
Finally, a handful of environment variables to point tools at that
|
||||
=/opt/rocm= prefix and to steer ROCm/HIP towards the right GPU. This
|
||||
machine exposes the AMD card as device ID =1= (the other device being an
|
||||
iGPU), so I pin both =HIP_VISIBLE_DEVICES= and =ROCM_VISIBLE_DEVICES= to
|
||||
it. The card also isn’t officially supported by ROCm, hence the
|
||||
=HSA_OVERRIDE_GFX_VERSION= override, which tells ROCm to treat it as the
|
||||
closest supported architecture instead of refusing to run.
|
||||
#+name: environment-variables
|
||||
#+begin_src nix
|
||||
environment.variables = {
|
||||
ROCM_PATH = "/opt/rocm";
|
||||
HIP_VISIBLE_DEVICES = "1";
|
||||
ROCM_VISIBLE_DEVICES = "1";
|
||||
HSA_OVERRIDE_GFX_VERSION = "10.3.0";
|
||||
};
|
||||
#+end_src
|
||||
@@ -1,16 +1,6 @@
|
||||
{
|
||||
flake.modules.nixos.bluetooth = {
|
||||
lib,
|
||||
config,
|
||||
...
|
||||
}:
|
||||
with lib; let
|
||||
cfg = config.mySystem.hardware.bluetooth;
|
||||
in {
|
||||
options.mySystem.hardware.bluetooth.enable = mkEnableOption "Enable bluetooth";
|
||||
config = mkIf cfg.enable {
|
||||
hardware.bluetooth.enable = cfg.enable;
|
||||
services.blueman.enable = cfg.enable;
|
||||
};
|
||||
};
|
||||
hardware.bluetooth.enable = true;
|
||||
services.blueman.enable = true;
|
||||
};
|
||||
}
|
||||
|
||||
@@ -0,0 +1,24 @@
|
||||
#+title: Bluetooth
|
||||
#+setupfile: ../headers
|
||||
|
||||
* Bluetooth
|
||||
Not all of my machines have Bluetooth hardware worth turning on, so
|
||||
this is a plain toggle rather than something applied unconditionally.
|
||||
Here’s the skeleton of the =nixos.bluetooth= module.
|
||||
#+begin_src nix :tangle yes
|
||||
{
|
||||
flake.modules.nixos.bluetooth = {
|
||||
<<config>>
|
||||
};
|
||||
}
|
||||
#+end_src
|
||||
|
||||
** Enabling Bluetooth
|
||||
Turning the option on enables Bluetooth support at the kernel level
|
||||
and installs =blueman=, a tray applet I use to pair and manage devices
|
||||
without digging through a terminal.
|
||||
#+name: config
|
||||
#+begin_src nix
|
||||
hardware.bluetooth.enable = true;
|
||||
services.blueman.enable = true;
|
||||
#+end_src
|
||||
@@ -1,15 +1,5 @@
|
||||
{
|
||||
flake.modules.nixos.fingerprint = {
|
||||
lib,
|
||||
config,
|
||||
...
|
||||
}:
|
||||
with lib; let
|
||||
cfg = config.mySystem.hardware.fingerprint;
|
||||
in {
|
||||
options.mySystem.hardware.fingerprint.enable = mkEnableOption "Enable fingerprint reader";
|
||||
config = mkIf cfg.enable {
|
||||
hardware.facter.detected.fingerprint.enable = cfg.enable;
|
||||
};
|
||||
};
|
||||
hardware.facter.detected.fingerprint.enable = true;
|
||||
};
|
||||
}
|
||||
|
||||
@@ -0,0 +1,22 @@
|
||||
#+title: Fingerprint Reader
|
||||
#+setupfile: ../headers
|
||||
|
||||
* Fingerprint Reader
|
||||
My ThinkPad x220 has a fingerprint reader, so this is a plain toggle
|
||||
rather than something applied unconditionally. Here’s the skeleton of
|
||||
the =nixos.fingerprint= module.
|
||||
#+begin_src nix :tangle yes
|
||||
{
|
||||
flake.modules.nixos.fingerprint = {
|
||||
<<config>>
|
||||
};
|
||||
}
|
||||
#+end_src
|
||||
|
||||
** Enabling the Reader
|
||||
Rather than picking a driver myself, I let [[https://github.com/numtide/nixos-facter-modules][nixos-facter]] detect the
|
||||
reader and wire up the matching driver automatically.
|
||||
#+name: config
|
||||
#+begin_src nix
|
||||
hardware.facter.detected.fingerprint.enable = true;
|
||||
#+end_src
|
||||
@@ -0,0 +1,21 @@
|
||||
#+title: Firmware
|
||||
#+setupfile: ../headers
|
||||
|
||||
* Firmware
|
||||
A small module to pull in the full firmware blob set, for machines
|
||||
where I’d rather not chase down which specific firmware package a
|
||||
piece of hardware needs. Here’s the =nixos.firmware= module.
|
||||
#+begin_src nix :tangle yes
|
||||
{
|
||||
flake.modules.nixos.firmware = {lib, ...}: {
|
||||
<<enable-all-firmware>>
|
||||
};
|
||||
}
|
||||
#+end_src
|
||||
|
||||
=mkDefault= keeps this overridable, in case a host needs to turn it back
|
||||
off or pin a narrower set of firmware packages itself.
|
||||
#+name: enable-all-firmware
|
||||
#+begin_src nix
|
||||
hardware.enableAllFirmware = lib.mkDefault true;
|
||||
#+end_src
|
||||
@@ -1,17 +1,9 @@
|
||||
{
|
||||
flake.modules.nixos.corne = {
|
||||
lib,
|
||||
config,
|
||||
...
|
||||
}:
|
||||
with lib; let
|
||||
cfg = config.mySystem.hardware.input.corne;
|
||||
in {
|
||||
options.mySystem.hardware.input.corne.allowHidAccess = mkEnableOption "Enable HID access to the corne keyboard";
|
||||
config.services.udev = mkIf cfg.allowHidAccess {
|
||||
extraRules = ''
|
||||
KERNEL=="hidraw*", SUBSYSTEM=="hidraw", ATTRS{serial}=="*vial:f64c2b3c*", MODE="0660", GROUP="users", TAG+="uaccess", TAG+="udev-acl"
|
||||
'';
|
||||
};
|
||||
services.udev = {
|
||||
extraRules = ''
|
||||
KERNEL=="hidraw*", SUBSYSTEM=="hidraw", ATTRS{serial}=="*vial:f64c2b3c*", MODE="0660", GROUP="users", TAG+="uaccess", TAG+="udev-acl"
|
||||
'';
|
||||
};
|
||||
};
|
||||
}
|
||||
|
||||
@@ -0,0 +1,32 @@
|
||||
#+title: Corne Keyboard
|
||||
#+setupfile: ../../headers
|
||||
|
||||
* Corne Keyboard
|
||||
I use a Corne (=crkbd=), a small split ergonomic keyboard, flashed with
|
||||
[[https://get.vial.today/][Vial]], a QMK-based firmware that lets me remap keys live from a GUI
|
||||
instead of having to reflash the keyboard every time I want to tweak
|
||||
my layout. Here’s the skeleton of the =nixos.corne= module.
|
||||
#+begin_src nix :tangle yes
|
||||
{
|
||||
flake.modules.nixos.corne = {
|
||||
<<udev-rule>>
|
||||
};
|
||||
}
|
||||
#+end_src
|
||||
|
||||
** Granting HID Access
|
||||
By default, the =hidraw= device nodes created for the keyboard are only
|
||||
accessible to root, which means Vial can’t talk to it without running
|
||||
as root too. Instead, I add a =udev= rule matching my keyboard’s Vial
|
||||
identifier (the part after =vial:= is the keyboard’s unique unlock ID,
|
||||
burned into its firmware) and grant the =users= group read/write access
|
||||
to it, tagging it for =uaccess= / =udev-acl= so it’s also picked up by the
|
||||
logged-in session’s ACLs.
|
||||
#+name: udev-rule
|
||||
#+begin_src nix
|
||||
services.udev = {
|
||||
extraRules = ''
|
||||
KERNEL=="hidraw*", SUBSYSTEM=="hidraw", ATTRS{serial}=="*vial:f64c2b3c*", MODE="0660", GROUP="users", TAG+="uaccess", TAG+="udev-acl"
|
||||
'';
|
||||
};
|
||||
#+end_src
|
||||
@@ -0,0 +1,7 @@
|
||||
{
|
||||
flake.modules.nixos.disable-ibm-trackpoint = {
|
||||
services.udev.extraRules = ''
|
||||
ATTRS{name}=="*TPPS/2 IBM TrackPoint", ENV{ID_INPUT}="", ENV{ID_INPUT_MOUSE}="", ENV{ID_INPUT_POINTINGSTICK}=""
|
||||
'';
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
#+title: Disable the IBM TrackPoint
|
||||
#+setupfile: ../../headers
|
||||
|
||||
* Disable the IBM TrackPoint
|
||||
My ThinkPads come with IBM’s TrackPoint, the little red nub sitting
|
||||
between the =G=, =H= and =B= keys. I don’t want it active, though, it has a
|
||||
drift and I cannot fix it unless I change my keyboard. Thus, this
|
||||
module exposes a way to turn it off. Here’s the skeleton of the
|
||||
=nixos.disable-ibm-trackpoint= module.
|
||||
#+begin_src nix :tangle yes
|
||||
{
|
||||
flake.modules.nixos.disable-ibm-trackpoint = {
|
||||
<<udev-rule>>
|
||||
};
|
||||
}
|
||||
#+end_src
|
||||
|
||||
** Disabling the TrackPoint
|
||||
The TrackPoint shows up to the input stack as a regular pointer
|
||||
device, so to disable it I can’t simply blacklist a driver — libinput
|
||||
and friends would still pick it up through =evdev=. Instead, I match it
|
||||
by its device name and clear the =ID_INPUT=, =ID_INPUT_MOUSE= and
|
||||
=ID_INPUT_POINTINGSTICK= udev properties on it, which tells the input
|
||||
stack to simply ignore the device as a pointing device.
|
||||
#+name: udev-rule
|
||||
#+begin_src nix
|
||||
services.udev.extraRules = ''
|
||||
ATTRS{name}=="*TPPS/2 IBM TrackPoint", ENV{ID_INPUT}="", ENV{ID_INPUT_MOUSE}="", ENV{ID_INPUT_POINTINGSTICK}=""
|
||||
'';
|
||||
#+end_src
|
||||
@@ -1,17 +0,0 @@
|
||||
{
|
||||
flake.modules.nixos.ibm-trackpoint = {
|
||||
lib,
|
||||
config,
|
||||
...
|
||||
}:
|
||||
with lib; let
|
||||
cfg = config.mySystem.hardware.input.ibmTrackpoint;
|
||||
in {
|
||||
options.mySystem.hardware.input.ibmTrackpoint.disable = mkEnableOption "Disable IBM’s trackpoint on ThinkPad";
|
||||
config.services.udev = mkIf cfg.disable {
|
||||
extraRules = ''
|
||||
ATTRS{name}=="*TPPS/2 IBM TrackPoint", ENV{ID_INPUT}="", ENV{ID_INPUT_MOUSE}="", ENV{ID_INPUT_POINTINGSTICK}=""
|
||||
'';
|
||||
};
|
||||
};
|
||||
}
|
||||
@@ -1,19 +1,9 @@
|
||||
{
|
||||
flake.modules.nixos.opentablet = {
|
||||
lib,
|
||||
config,
|
||||
...
|
||||
}:
|
||||
with lib; let
|
||||
cfg = config.mySystem.hardware.input.opentablet;
|
||||
in {
|
||||
options.mySystem.hardware.input.opentablet.enable = mkEnableOption "Enables OpenTablet drivers";
|
||||
config = mkIf cfg.enable {
|
||||
hardware.opentabletdriver = {
|
||||
inherit (cfg) enable;
|
||||
daemon.enable = true;
|
||||
};
|
||||
boot.kernelModules = ["wacom"];
|
||||
};
|
||||
hardware.opentabletdriver = {
|
||||
enable = true;
|
||||
daemon.enable = true;
|
||||
};
|
||||
boot.kernelModules = ["wacom"];
|
||||
};
|
||||
}
|
||||
|
||||
@@ -0,0 +1,30 @@
|
||||
#+title: OpenTabletDriver
|
||||
#+setupfile: ../../headers
|
||||
|
||||
* OpenTabletDriver
|
||||
Some of my machines are hooked up to a graphics tablet, a Wacom
|
||||
Bamboo, driven by [[https://opentabletdriver.net/][OpenTabletDriver]]. I remember buying it for 15€, what
|
||||
a deal that was! Anyway, since most of my hosts don’t have a tablet
|
||||
attached, this is exposed as a regular toggle rather than enabled
|
||||
unconditionally. Here’s the skeleton of the =nixos.opentablet= module.
|
||||
#+begin_src nix :tangle yes
|
||||
{
|
||||
flake.modules.nixos.opentablet = {
|
||||
<<config>>
|
||||
};
|
||||
}
|
||||
#+end_src
|
||||
|
||||
** Enabling the Driver
|
||||
Enabling OpenTabletDriver proper is just a matter of turning on the
|
||||
module and its daemon. I also need to explicitly load the =wacom=
|
||||
kernel module, since my tablet (like most of them) identifies itself
|
||||
as a Wacom device at the hardware level regardless of brand.
|
||||
#+name: config
|
||||
#+begin_src nix
|
||||
hardware.opentabletdriver = {
|
||||
enable = true;
|
||||
daemon.enable = true;
|
||||
};
|
||||
boot.kernelModules = ["wacom"];
|
||||
#+end_src
|
||||
@@ -0,0 +1,22 @@
|
||||
#+title: Trackball
|
||||
#+setupfile: ../../headers
|
||||
|
||||
* Trackball
|
||||
I use a trackball on some of my machines, and I middle-click by
|
||||
pressing the left and right buttons together rather than through a
|
||||
dedicated button. That’s the only downside of the two trackballs I
|
||||
own; otherwise, I can’t recommend one enough. Here’s the
|
||||
=nixos.trackball= module enabling this behaviour.
|
||||
#+begin_src nix :tangle yes
|
||||
{
|
||||
flake.modules.nixos.trackball = {
|
||||
<<middle-emulation>>
|
||||
};
|
||||
}
|
||||
#+end_src
|
||||
|
||||
Enabling middle-click emulation is simple:
|
||||
#+name: middle-emulation
|
||||
#+begin_src nix
|
||||
services.libinput.mouse.middleEmulation = true;
|
||||
#+end_src
|
||||
@@ -1,14 +1,10 @@
|
||||
{
|
||||
flake.modules.nixos.pinetab2 = {lib, ...}:
|
||||
with lib; {
|
||||
options.mySystem.hardware.pinetab2.enable = mkEnableOption "Activate support for the PineTab2";
|
||||
config = {
|
||||
boot.kernelParams = ["console=tty0" "console=ttyS2,1500000n8" "rootwait" "root=LABEL=NIXOS_SD" "rw"];
|
||||
hardware.sensor.iio.enable = true;
|
||||
services.avahi = {
|
||||
enable = true;
|
||||
openFirewall = true;
|
||||
};
|
||||
};
|
||||
flake.modules.nixos.pinetab2 = {
|
||||
boot.kernelParams = ["console=tty0" "console=ttyS2,1500000n8" "rootwait" "root=LABEL=NIXOS_SD" "rw"];
|
||||
hardware.sensor.iio.enable = true;
|
||||
services.avahi = {
|
||||
enable = true;
|
||||
openFirewall = true;
|
||||
};
|
||||
};
|
||||
}
|
||||
|
||||
@@ -0,0 +1,48 @@
|
||||
#+title: PineTab2
|
||||
#+setupfile: ../headers
|
||||
|
||||
* PineTab2
|
||||
A few tweaks are specific to my PineTab2 tablet: getting a serial
|
||||
console working at boot, exposing its sensors, and making it easy to
|
||||
find on whatever network it’s connected to. Here’s the skeleton of the
|
||||
=nixos.pinetab2= module.
|
||||
#+begin_src nix :tangle yes
|
||||
{
|
||||
flake.modules.nixos.pinetab2 = {
|
||||
<<kernel-params>>
|
||||
<<sensors>>
|
||||
<<avahi>>
|
||||
};
|
||||
}
|
||||
#+end_src
|
||||
|
||||
** Serial Console
|
||||
These kernel parameters get me a working serial console on the
|
||||
tablet’s UART at boot, and point the kernel at the SD card’s root
|
||||
filesystem by label rather than by a device path that can shift
|
||||
around.
|
||||
#+name: kernel-params
|
||||
#+begin_src nix
|
||||
boot.kernelParams = ["console=tty0" "console=ttyS2,1500000n8" "rootwait" "root=LABEL=NIXOS_SD" "rw"];
|
||||
#+end_src
|
||||
|
||||
** Sensors
|
||||
Turning on the IIO (Industrial I/O) subsystem exposes the tablet’s
|
||||
accelerometer and ambient light sensor, which is what lets things like
|
||||
auto-rotate work.
|
||||
#+name: sensors
|
||||
#+begin_src nix
|
||||
hardware.sensor.iio.enable = true;
|
||||
#+end_src
|
||||
|
||||
** Finding It on the Network
|
||||
The tablet moves between networks a lot, so Avahi lets me reach it by
|
||||
its =.local= hostname over mDNS instead of having to look up whatever IP
|
||||
it was handed.
|
||||
#+name: avahi
|
||||
#+begin_src nix
|
||||
services.avahi = {
|
||||
enable = true;
|
||||
openFirewall = true;
|
||||
};
|
||||
#+end_src
|
||||
@@ -9,7 +9,6 @@
|
||||
cfg = config.mySystem.hardware.sound;
|
||||
in {
|
||||
options.mySystem.hardware.sound = {
|
||||
enable = mkEnableOption "Whether to enable sounds with Pipewire";
|
||||
noisetorch = mkEnableOption "Whether to activate noisetorch support";
|
||||
scarlett.enable = mkEnableOption "Activate support for Scarlett sound card";
|
||||
alsa = mkOption {
|
||||
@@ -35,7 +34,7 @@
|
||||
config = {
|
||||
environment.systemPackages = mkIf cfg.scarlett.enable [pkgs.alsa-scarlett-gui];
|
||||
services = {
|
||||
pipewire = mkIf cfg.enable {
|
||||
pipewire = {
|
||||
enable = true;
|
||||
alsa = mkIf cfg.alsa {
|
||||
enable = mkDefault true;
|
||||
@@ -45,9 +44,7 @@
|
||||
};
|
||||
pulseaudio.enable = false;
|
||||
};
|
||||
programs.noisetorch = mkIf cfg.enable {
|
||||
enable = cfg.noisetorch;
|
||||
};
|
||||
programs.noisetorch.enable = cfg.noisetorch;
|
||||
};
|
||||
};
|
||||
}
|
||||
|
||||
@@ -0,0 +1,118 @@
|
||||
#+title: Sound
|
||||
#+setupfile: ../headers
|
||||
|
||||
* Sound
|
||||
I use Pipewire for audio on my desktop machines, with a couple of
|
||||
compatibility layers and bits of hardware-specific support switched on
|
||||
as needed. Here’s the skeleton of the =nixos.sound= module.
|
||||
#+begin_src nix :tangle yes
|
||||
{
|
||||
flake.modules.nixos.sound = {
|
||||
lib,
|
||||
config,
|
||||
pkgs,
|
||||
...
|
||||
}:
|
||||
with lib; let
|
||||
cfg = config.mySystem.hardware.sound;
|
||||
in {
|
||||
options.mySystem.hardware.sound = {
|
||||
<<opt-noisetorch>>
|
||||
<<opt-scarlett>>
|
||||
<<opt-alsa>>
|
||||
<<opt-jack>>
|
||||
<<opt-package>>
|
||||
};
|
||||
|
||||
config = {
|
||||
<<scarlett-package>>
|
||||
<<pipewire-config>>
|
||||
<<noisetorch-config>>
|
||||
};
|
||||
};
|
||||
}
|
||||
#+end_src
|
||||
|
||||
** Noise Suppression
|
||||
=noisetorch= toggles [[https://github.com/noisetorch/NoiseTorch][NoiseTorch]], a real-time microphone noise
|
||||
suppression tool I use for calls, so I have an option for that.
|
||||
#+name: opt-noisetorch
|
||||
#+begin_src nix
|
||||
noisetorch = mkEnableOption "Whether to activate noisetorch support";
|
||||
#+end_src
|
||||
|
||||
Passing it to NixOS is quite simple.
|
||||
#+name: noisetorch-config
|
||||
#+begin_src nix
|
||||
programs.noisetorch.enable = cfg.noisetorch;
|
||||
#+end_src
|
||||
|
||||
** Scarlett Sound Card
|
||||
=scarlett.enable= is for the machine =marpa= with a Focusrite Scarlett 2i2
|
||||
audio interface plugged in; it only pulls in that card’s control GUI.
|
||||
#+name: opt-scarlett
|
||||
#+begin_src nix
|
||||
scarlett.enable = mkEnableOption "Activate support for Scarlett sound card";
|
||||
#+end_src
|
||||
|
||||
It is installed quite easily in enabled.
|
||||
#+name: scarlett-package
|
||||
#+begin_src nix
|
||||
environment.systemPackages = mkIf cfg.scarlett.enable [pkgs.alsa-scarlett-gui];
|
||||
#+end_src
|
||||
|
||||
** Enabling Pipewire
|
||||
Enabling Pipewire also means explicitly turning PulseAudio off, since
|
||||
the two can’t run as the system’s sound server at the same time.
|
||||
#+name: pipewire-config
|
||||
#+begin_src nix
|
||||
services = {
|
||||
pipewire = {
|
||||
enable = true;
|
||||
alsa = mkIf cfg.alsa {
|
||||
enable = mkDefault true;
|
||||
support32Bit = mkDefault true;
|
||||
};
|
||||
jack.enable = mkDefault cfg.jack;
|
||||
};
|
||||
pulseaudio.enable = false;
|
||||
};
|
||||
#+end_src
|
||||
|
||||
** ALSA Compatibility
|
||||
=alsa= enables Pipewire’s ALSA compatibility layer, on by default since
|
||||
most of my audio software still expects ALSA.
|
||||
#+name: opt-alsa
|
||||
#+begin_src nix
|
||||
alsa = mkOption {
|
||||
type = types.bool;
|
||||
example = true;
|
||||
default = true;
|
||||
description = "Whether to enable ALSA support with Pipewire";
|
||||
};
|
||||
#+end_src
|
||||
|
||||
** JACK Compatibility
|
||||
=jack= enables Pipewire’s JACK compatibility layer, off by default since
|
||||
only my production machine needs it.
|
||||
#+name: opt-jack
|
||||
#+begin_src nix
|
||||
jack = mkOption {
|
||||
type = types.bool;
|
||||
example = true;
|
||||
default = false;
|
||||
description = "Whether to enable JACK support with Pipewire";
|
||||
};
|
||||
#+end_src
|
||||
|
||||
** Base Package
|
||||
=package= picks which PulseAudio package to build things on top of.
|
||||
#+name: opt-package
|
||||
#+begin_src nix
|
||||
package = mkOption {
|
||||
type = types.package;
|
||||
example = pkgs.pulseaudio;
|
||||
default = pkgs.pulseaudioFull;
|
||||
description = "Which base package to use for PulseAudio";
|
||||
};
|
||||
#+end_src
|
||||
Reference in New Issue
Block a user