diff --git a/nixos/modules/hardware/facter/camera/default.nix b/nixos/modules/hardware/facter/camera/default.nix new file mode 100644 index 000000000000..2944c241fac5 --- /dev/null +++ b/nixos/modules/hardware/facter/camera/default.nix @@ -0,0 +1,3 @@ +{ + imports = [ ./ipu6.nix ]; +} diff --git a/nixos/modules/hardware/facter/camera/ipu6-devices.json b/nixos/modules/hardware/facter/camera/ipu6-devices.json new file mode 100644 index 000000000000..b3b770f15324 --- /dev/null +++ b/nixos/modules/hardware/facter/camera/ipu6-devices.json @@ -0,0 +1,3 @@ +{ + "8086:9A19:17AA:508B/0004-0080-0001": true +} diff --git a/nixos/modules/hardware/facter/camera/ipu6.nix b/nixos/modules/hardware/facter/camera/ipu6.nix new file mode 100644 index 000000000000..5319d8bf3d49 --- /dev/null +++ b/nixos/modules/hardware/facter/camera/ipu6.nix @@ -0,0 +1,115 @@ +{ config, lib, ... }: +let + inherit (config.hardware.facter) report detected; + facterLib = import ../lib.nix lib; + + isCpuGeneration = + _family: models: + facterLib.hasIntelCpu report + && lib.any ( + actual: (actual.family or 0) == 6 && builtins.elem (actual.model or 0) models + ) report.hardware.cpu; + + # Family model combinations have been looked up at https://en.wikichip.org/wiki/intel/cpuid + isTigerLake = isCpuGeneration 6 [ + 140 # Combination tested on actual hardware + 141 + ]; + + isAdlerLake = isCpuGeneration 6 [ + 151 + 154 + ]; + + isRaptorLake = isCpuGeneration 6 [ + 183 + 186 + 190 + 191 + ]; + + isMeteorLake = isCpuGeneration 6 [ + 170 + 171 + 172 + ]; + + devices = builtins.fromJSON (builtins.readFile ./ipu6-devices.json); + isCameraSupported = + let + default = { + value = 0; + }; + in + lib.any ( + { + base_class ? default, + sub_class ? default, + vendor ? default, + sub_vendor ? default, + device ? default, + sub_device ? default, + revision ? default, + bus_type ? { + name = ""; + }, + ... + }: + let + baseClassHex = facterLib.toZeroPaddedHex base_class.value; + subClassHex = facterLib.toZeroPaddedHex sub_class.value; + vendorHex = facterLib.toZeroPaddedHex vendor.value; + subVendorHex = facterLib.toZeroPaddedHex sub_vendor.value; + deviceHex = facterLib.toZeroPaddedHex device.value; + subDeviceHex = facterLib.toZeroPaddedHex sub_device.value; + revisionHex = facterLib.toZeroPaddedHex revision.value; + in + bus_type.name == "PCI" + && devices + ? "${vendorHex}:${deviceHex}:${subVendorHex}:${subDeviceHex}/${baseClassHex}-${subClassHex}-${revisionHex}" + ); +in +{ + options.hardware.facter.detected.camera.ipu6.enable = + let + cameraSupported = + isCameraSupported (report.hardware.unknown or [ ]) + || isCameraSupported (report.hardware.pci or [ ]); + + cpuSupported = lib.any (generation: generation) [ + isTigerLake + isAdlerLake + isRaptorLake + isMeteorLake + ]; + in + lib.mkEnableOption "webcams using ipu6 from Intel" + // { + default = cameraSupported && cpuSupported; + defaultText = "hardware dependent"; + }; + + config.hardware.ipu6 = lib.mkIf detected.camera.ipu6.enable { + enable = true; + platform = + if isTigerLake then + "ipu6" + else if isAdlerLake || isRaptorLake then + "ipu6ep" + else if isMeteorLake then + "ipu6epmtl" + else + throw "Unexpected CPU generation for ipu6 detected."; + }; + + config.warnings = + let + isKernel6_16OrLater = lib.versionAtLeast config.boot.kernelPackages.kernel.version "6.16"; + inherit (detected.camera) ipu6; + in + lib.optional (isKernel6_16OrLater && ipu6.enable) '' + A regression bug can occur when combining ipu6 with kernel version 6.16 or later. + This will most likely prevent your system from properly suspending or shutting down. + For more information see: https://github.com/intel/ipu6-drivers/issues/381 + ''; +} diff --git a/nixos/modules/hardware/facter/default.nix b/nixos/modules/hardware/facter/default.nix index aa8a1ca4175e..12499b5ad31f 100644 --- a/nixos/modules/hardware/facter/default.nix +++ b/nixos/modules/hardware/facter/default.nix @@ -6,6 +6,7 @@ { imports = [ ./bluetooth.nix + ./camera ./disk.nix ./fingerprint ./firmware.nix diff --git a/nixos/modules/hardware/facter/lib.nix b/nixos/modules/hardware/facter/lib.nix index 099254cbce8d..db9f70b71b76 100644 --- a/nixos/modules/hardware/facter/lib.nix +++ b/nixos/modules/hardware/facter/lib.nix @@ -28,7 +28,7 @@ let ) cpus; # Extract all driver_modules from a list of hardware entries - collectDrivers = list: lib.catAttrs "driver_modules" list; + collectDrivers = list: lib.foldl' (lst: value: lst ++ value.driver_modules or [ ]) [ ] list; # Convert number to zero-padded 4-digit hex string (for USB device IDs) toZeroPaddedHex = diff --git a/nixos/tests/facter/facter.json b/nixos/tests/facter/facter.json index 37d6ba87c14d..5a6cf464dfec 100644 --- a/nixos/tests/facter/facter.json +++ b/nixos/tests/facter/facter.json @@ -14,6 +14,18 @@ "model": 33 } ], + "graphics_card": [ + { + "driver_modules": [ + "i915" + ] + } + ], + "monitor": [ + { + "model": "Test Monitor" + } + ], "system": { "form_factor": "desktop" }