Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
30 commits
Select commit Hold shift + click to select a range
32f190f
lib: Add getFlakeInput helper
samueldr-at-cyberus Feb 20, 2026
7d43270
lib: Add lockedNixpkgsVersion
samueldr-at-cyberus Feb 20, 2026
ab5481c
checks/pre-commit: Drop redundant and incorrect styleCheckRequired
samueldr-at-cyberus Feb 20, 2026
dc5d6eb
flake: Only run pre-commit checks against the locked Nixpkgs
samueldr-at-cyberus Feb 20, 2026
094bb37
nvidia/jetson-orin-nano-super: Expose nvidia-oot as a kernelPackage
samueldr-at-cyberus Feb 12, 2026
ce7f86d
jetson-orin-nano-super/nvidia-oot: rel-36_eng_2026-01-04 -> r36.5
samueldr-at-cyberus Feb 12, 2026
9beaa36
jetson-orin-nano-super/nvidia-oot: Minor cleanups
samueldr-at-cyberus Feb 12, 2026
eeb05cf
jetson-orin-nano-super/nvidia-oot: Build nv-kernel-display-driver
samueldr-at-cyberus Feb 13, 2026
55a6f68
jetson-orin-nano-super/nvidia-oot: Backport fbdev ttm patch to nv-ker…
samueldr-at-cyberus Feb 13, 2026
981a40c
jetson-orin-nano-super/nvidia-l4t-kernel: Init at r36.5
samueldr-at-cyberus Feb 13, 2026
064508f
jetson-orin-nano-super/nvidia-l4t{,-firmware}: Init at r36.5
samueldr-at-cyberus Feb 13, 2026
069566b
jetson-orin-nano-super/nvidia-l4t: Add uaccess for video nodes
samueldr-at-cyberus Feb 25, 2026
6f004b7
nvidia/jetson-orin-nano-super: Rework as list of `mkIf`s
samueldr-at-cyberus Feb 13, 2026
ccfb3ed
nvidia/jetson-orin-nano-super: Add enableHardwareAcceleration
samueldr-at-cyberus Feb 13, 2026
a51e2e3
nvidia/jetson-orin-nano-super: Select appropriate default kernel
samueldr-at-cyberus Feb 13, 2026
89aa100
nvidia/jetson-orin-nano-super: Add configuration for tegra and nvidia…
samueldr-at-cyberus Feb 13, 2026
699d7c3
nvidia/jetson-orin-nano-super: Add addDebugUserGroup quirk
samueldr-at-cyberus Feb 13, 2026
8d01293
nvidia/jetson-orin-nano-super: Add necessary links for EGL support
samueldr-at-cyberus Feb 13, 2026
a233698
nvidia/jetson-orin-nano-super: Ensure `hardware.graphics` is enabled
samueldr-at-cyberus Feb 20, 2026
05823c0
nvidia/jetson-orin-nano-super: Ensure kernelPackagesExtensions is ava…
samueldr-at-cyberus Feb 16, 2026
c937ec1
nvidia/jetson-orin-nano-super: Add unbindPlatformFramebuffer quirk
samueldr-at-cyberus Feb 13, 2026
8dd9443
nvidia/jetson-orin-nano-super: Warn on disabling unbindPlatformFrameb…
samueldr-at-cyberus Feb 20, 2026
d19a45b
nvidia/jetson-orin-nano-super: Load the nvidia_drm module on unbind
samueldr-at-cyberus Feb 13, 2026
35a1ec5
nvidia/jetson-orin-nano-super: Prevent auto-loading of NVIDIA drm mod…
samueldr-at-cyberus Feb 20, 2026
8860dd7
nvidia/jetson-orin-nano-super: Implement modules loading in a less cl…
samueldr-at-cyberus Feb 20, 2026
bea5754
nvidia/jetson-orin-nano-super: Fix evaluation with 24.05
samueldr-at-cyberus Feb 20, 2026
2f4613d
nvidia/jetson-orin-nano-super: Build vendor kernel with simpledrm
samueldr-at-cyberus Feb 20, 2026
37514b2
nvidia/jetson-orin-nano-super: Add debugging option for module loading
samueldr-at-cyberus Feb 24, 2026
2ef0b29
nvidia/jetson-orin-nano-super: Prevent tegra-audio-graph from loading
samueldr-at-cyberus Feb 24, 2026
1e011a5
nvidia/jetson-orin-nano-super: Be even less clever about loading the …
samueldr-at-cyberus Feb 25, 2026
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
39 changes: 16 additions & 23 deletions checks/pre-commit.nix
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@
perSystem =
{
config,
lib,
pkgs,
...
}:
Expand All @@ -14,30 +13,24 @@
shellHook = config.pre-commit.installationScript;
};

pre-commit =
let
styleCheckRequired = lib.versionAtLeast lib.version "25.11";
in
{
check.enable = lib.warnIfNot (
styleCheckRequired
) "Style Check disabled, because we do not use the latest nixpkgs version" styleCheckRequired;
settings = {
package = pkgs.pre-commit;
excludes = [
];
hooks = {
shfmt = {
enable = true;
raw.entry = " --indent 2";
};
nixfmt.enable = true;
deadnix.enable = true;
shellcheck.enable = true;
trim-trailing-whitespace.enable = true;
check-executables-have-shebangs.enable = true;
pre-commit = {
check.enable = true;
settings = {
package = pkgs.pre-commit;
excludes = [
];
hooks = {
shfmt = {
enable = true;
raw.entry = " --indent 2";
};
nixfmt.enable = true;
deadnix.enable = true;
shellcheck.enable = true;
trim-trailing-whitespace.enable = true;
check-executables-have-shebangs.enable = true;
};
};
};
};
}
7 changes: 6 additions & 1 deletion flake.nix
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,12 @@
./packages/flakeModule.nix
]
++
inputs.nixpkgs.lib.optionals (inputs.nixpkgs.lib.versionAtLeast inputs.nixpkgs.lib.version "25.11")
# Only run the `pre-commit` checks when ran using the locked Nixpkgs.
# This ensures our CI isn't running those checks when we override the Nixpkgs input.
inputs.nixpkgs.lib.optionals
(inputs.nixpkgs.lib.versionAtLeast inputs.nixpkgs.lib.version
(import ./lib { lib = { }; }).lockedNixpkgsVersion
)
[
inputs.preCommitHooksNix.flakeModule
./checks/pre-commit.nix
Expand Down
19 changes: 19 additions & 0 deletions lib/default.nix
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,25 @@ let
) dir
)
);

/**
Returns the Flake lock information for the given input name on this Flake.
*/
getFlakeInput =
name:
let
data = builtins.fromJSON (builtins.readFile ../flake.lock);
nodeName = data.nodes.root.inputs.${name};
in
data.nodes.${nodeName};

/**
The default locked Nixpkgs version number. For example, 26.05.
This can be used to check for overridden inputs.
*/
lockedNixpkgsVersion = builtins.head (
builtins.match ".*/nixos-([0-9]+\\.[0-9]+).*" (self.getFlakeInput "nixpkgs").locked.url
);
};
in
self
278 changes: 259 additions & 19 deletions modules/hardware/devices/nvidia/jetson-orin-nano-super/default.nix
Original file line number Diff line number Diff line change
@@ -1,4 +1,10 @@
{ config, lib, ... }:
{
config,
lib,
options,
pkgs,
...
}:

let
cfg = config.ctrl-os.hardware.devices.nvidia-jetson-orin-nano-super;
Expand All @@ -9,25 +15,259 @@ in
enableOotModules = lib.mkEnableOption "the NVIDIA Out-Of-Tree kernel modules" // {
default = true;
};
enableStage1KernelModules =
lib.mkEnableOption "use of storage and necessary kernel modules in stage-1"
// {
default = true;
};
# Reminder device enablement modules should not set the unfree software option.
# The module *must* fail with the unfree software error.
# The user must make the informed decision about enabling unfree software.
enableHardwareAcceleration = lib.mkEnableOption "the NVIDIA proprietary graphical and ML drivers";
quirks = {
# Enabled by default since it's cheap.
addDebugUserGroup =
lib.mkEnableOption "adding the `debug` user group, which is used in vendor udev configuration"
// {
default = true;
};
debugModuleLoading =
lib.mkEnableOption "send debug information to the kernel log when loading the kernel module."
// {
internal = true;
};
};
};
};

config = lib.mkIf cfg.enable {
nixpkgs.hostPlatform = "aarch64-linux";

boot.initrd.availableKernelModules = [
# Enable PCIe support at boot time
"phy_tegra194_p2u"
"pcie_tegra194"
# Enable USB support for USB Boot
"xhci-tegra"
"phy-tegra-xusb"
];

boot.extraModulePackages = lib.mkMerge [
(lib.mkIf cfg.enableOotModules [
(config.boot.kernelPackages.callPackage ./nvidia-oot { })
])
];
};
config = lib.mkIf cfg.enable (
lib.mkMerge [
{
assertions = [
{
assertion = pkgs.linuxKernel.override.__functionArgs ? kernelPackagesExtensions;
message = "The `kernelPackagesExtensions` feature was not detected on the `linuxKernel` attribute. Your Nixpkgs version may be too old.";
}
];
}
{
nixpkgs.hostPlatform = "aarch64-linux";

# We can add the proprietary packages to the overlay even without enabling the
# *configuration* for proprietary packages. This leaves it up to the end-user
# to use those proprietary packages.
nixpkgs.overlays = [
(final: super: {
kernelPackagesExtensions = (super.kernelPackagesExtensions or [ ]) ++ [
(kFinal: _kSuper: {
nvidia-oot = kFinal.callPackage ./nvidia-oot { };
})
];
nvidia-jetson-orin-nano-super = {
nvidia-l4t = final.callPackage ./nvidia-l4t { };
nvidia-l4t-firmware = final.callPackage ./nvidia-l4t-firmware {
inherit (final.nvidia-jetson-orin-nano-super)
nvidia-l4t
;
};
nvidia-l4t-kernelPackages = final.linuxPackagesFor final.nvidia-jetson-orin-nano-super.nvidia-l4t-kernel;
nvidia-l4t-kernel = final.callPackage ./nvidia-l4t-kernel {
kernelPatches = [
final.linuxKernel.kernelPatches.bridge_stp_helper
final.linuxKernel.kernelPatches.request_key_helper
];
};
};
})
];
}

(lib.mkIf cfg.enableStage1KernelModules {
boot.initrd.availableKernelModules = [
# Enable PCIe support at boot time
"phy_tegra194_p2u"
"pcie_tegra194"
# Enable USB support for USB Boot
"xhci-tegra"
"phy-tegra-xusb"
];
})

{
boot.kernelPackages = lib.mkDefault pkgs.linuxPackages_6_12;
}

(lib.mkIf cfg.enableOotModules {
boot.extraModulePackages = [
config.boot.kernelPackages.nvidia-oot
];
})

(lib.mkIf cfg.quirks.addDebugUserGroup {
users.groups = {
# Works around these warnings in system logs:
# /etc/udev/rules.d/99-tegra-devices.rules:00 Unknown group 'debug', ignoring.
debug = { };
};
})

(lib.mkIf (cfg.enableHardwareAcceleration) {
# This service handles the weakly defined dependencies for the NVIDIA
# driver stack.
# - simpledrm must not hold the device
# - tegra-drm must be loaded before nvidia-drm
# - nvidia-drm is loaded last
# For better support of wayland compositors, this uses a trick to
# force the nvidia-drm driver to pick the `card0` name (from the
# assigned minor device number).
# This workaround will not work when “SOC Display Hand-Off” is
# disabled, or if running on a kernel with simpledrm disabled.
systemd.services.nvidia-load-modules = {
wantedBy = [ "graphical.target" ];
before = [
"graphical.target"
"display-manager.service"
];
after = [
"multi-user.target"
"systemd-modules-load.service"
];
path = with pkgs; [
kmod
coreutils
];
script = ''
(
set -eu -o pipefail
printf 'Loading nvidia-drm kernel module...\n\n'
(
# This path allows manually unbinding the simpledrm driver from the framebuffer.
# The vendor driver does not know how to do that.
unbind_path='/sys/bus/platform/devices/chosen:framebuffer/driver/unbind'

simpledrm_card="/dev/dri/by-path/platform-chosen:framebuffer-card"
tegra_card="dev/dri/by-path/platform-13e00000.host1x-card"
nvidia_card="dev/dri/by-path/platform-13800000.display-card"

printf "Checking nvidia-drm can take card0...\n"
if ! test -e "$unbind_path"; then
printf "WARNING: The nvidia-drm driver will be on '/dev/dri/card1'.\n"
printf "This may break some wayland compositors or other DRM software.\n"
fi

printf "Checking if the module can be loaded...\n"
if ! modprobe --first-time --dry-run nvidia-drm; then
printf "Skipping loading nvidia-drm kernel module.\n" >&2
# This is not a failure for this unit.
# The module might be loaded.
exit 0
fi

${lib.optionalString cfg.quirks.debugModuleLoading "set -x"}

# Load the tegra-drm driver.
# If simpledrm is loaded, this will effectively use /dev/dri/card1.
modprobe tegra-drm

i=30
# Wait a bit until the card shows up.
until test -e "$tegra_card"; do
sleep 0.1
((i--)) || break
done

# The vendor driver stack is fussy, wait a bit more.
sleep 1

# Make the simpledrm driver drop the card0 identifier, if relevant.
if test -e "$unbind_path"; then
printf 'chosen:framebuffer' > "$unbind_path"
i=30
# Wait until (effectively) card0 is free.
while test -e ; do
sleep 0.1
((i--)) || break
done
fi

# The vendor driver stack is fussy, wait just a bit more again.
sleep 1

# Then load the driver actual driver.
modprobe nvidia-drm
)

printf '... done loading nvidia-drm kernel module.\n'
) ${lib.optionalString cfg.quirks.debugModuleLoading ">/dev/kmsg 2>&1"}
'';
serviceConfig = {
# > systemd will consider [oneshot units] to be in the state "starting"
# > until the program has terminated, so ordered dependencies will
# > wait for the program to finish before starting themselves
Type = "oneshot";
# Never restart this unit.
Restart = "no";
};
};

services.udev.packages = [
pkgs.nvidia-jetson-orin-nano-super.nvidia-l4t
];
hardware = {
firmware = lib.mkAfter [
pkgs.nvidia-jetson-orin-nano-super.nvidia-l4t-firmware
];
# Backward compatibility to evaluate against 24.05
"${if options.hardware ? graphics then "graphics" else "opengl"}" = {
enable = true;
extraPackages = [
pkgs.nvidia-jetson-orin-nano-super.nvidia-l4t
];
};
};
environment.etc = {
"egl/egl_external_platform.d".source = "/run/opengl-driver/share/egl/egl_external_platform.d/";
"glvnd/egl_vendor.d".source = "/run/opengl-driver/share/glvnd/egl_vendor.d";
};
boot.blacklistedKernelModules = [
# The tegra_drm and nvidia_drm modules need to be loaded in order.
# Prevent the usual modules loading mechanisms from trying and failing.
# See 70-nvidia-unbind-simpledrm.rules for how this gets loaded.
"tegra_drm"
"nvidia_drm"
# Vendor prevents this module from being loaded by default.
# The reason why is not explained.
"snd_soc_tegra_audio_graph_card"
];
boot.extraModprobeConfig = lib.mkMerge [
# Without `modeset`, the X11 driver will fail to work.
# This is the vendor-suggested configuration.
"options nvidia_drm modeset=1 fbdev=1"
];
services.xserver = {
# Use the `nvidia` driver for `tegra` kernel driver matches.
config = ''
Section "OutputClass"
Identifier "nvidia"
MatchDriver "tegra"
Driver "nvidia"
EndSection
'';
# NOTE: videoDrivers cannot be used.
# Enabling `"nvidia"` within it uses the non-l4t NVIDIA driver.
# Instead we force the driver list to ensure only this one is used.
drivers = lib.mkForce (
lib.singleton {
name = "nvidia";
modules = [ pkgs.nvidia-jetson-orin-nano-super.nvidia-l4t ];
display = true;
deviceSection = ''
Option "AllowEmptyInitialConfiguration" "true"
'';
}
);
};
})
]
);
}
Loading
Loading