summary refs log tree commit diff
path: root/module.nix
diff options
context:
space:
mode:
authorMel <mel@rnrd.eu>2026-07-13 20:00:00 +0200
committerMel <mel@rnrd.eu>2026-07-13 20:00:00 +0200
commitdd8f085fc0232b77f3db885b0670a3e8d3094d36 (patch)
tree940d89b684dbaa5175d816ad3d1bdafc8a397e1c /module.nix
parent398608948fa730883d234a636cb33f73f2da51cf (diff)
downloadmhs35-drm-dd8f085fc0232b77f3db885b0670a3e8d3094d36.tar.zst
mhs35-drm-dd8f085fc0232b77f3db885b0670a3e8d3094d36.zip
Wrap into NixOS and Nix flake HEAD main
Signed-off-by: Mel <mel@rnrd.eu>
Diffstat (limited to 'module.nix')
-rw-r--r--module.nix117
1 files changed, 117 insertions, 0 deletions
diff --git a/module.nix b/module.nix
new file mode 100644
index 0000000..2cb054c
--- /dev/null
+++ b/module.nix
@@ -0,0 +1,117 @@
+# nixos module to fully configure mhs35 support both in kernel and userland.
+{
+  config,
+  lib,
+  ...
+}:
+
+let
+  inherit (lib)
+    mkEnableOption
+    mkIf
+    mkOption
+    optional
+    types
+    ;
+
+  cfg = config.hardware.mhs35;
+
+  mhs35-module = config.boot.kernelPackages.callPackage ./package.nix { };
+
+  # just replace the text to avoid messing with merging device trees,
+  # it's just simpler this way... :)
+  panelDts = builtins.replaceStrings
+    [ "rotation = <180>" "spi-max-frequency = <8000000>" ]
+    [
+      "rotation = <${toString cfg.rotation}>"
+      "spi-max-frequency = <${toString cfg.spiFrequencyHz}>"
+    ]
+    (builtins.readFile ./dts/mhs35-overlay.dts);
+
+  # touch matrices for panel. (libinput)
+  # TODO(mel): 90 & 270 are missing, but are of course supported.
+  # let's write the matrix out for them, too!
+  defaultMatrices = {
+    "0" = "0 1 0 -1 0 1";
+    "180" = "0 -1 1 1 0 0";
+  };
+in
+{
+  options.hardware.mhs35 = {
+    enable = mkEnableOption "goodtft MHS-3.5 SPI display support";
+
+    rotation = mkOption {
+      type = types.enum [ 0 90 180 270 ];
+      default = 180;
+      description = ''
+        The panel rotation.
+      '';
+      # orientations (for pi4, when looking at screen upright):
+      # * 0 - landscape, usb/rj-45 ports on the left
+      # * 90 - portrait, ports on top
+      # * 180 - landscape, ports on the right
+      # * 270 - portrait, ports on bottom
+    };
+
+    spiFrequencyHz = mkOption {
+      type = types.ints.positive;
+      default = 8000000;
+      description = ''
+        Panel SPI frequency.
+        8 MHz is the very very conservative default, the panel
+        claims to support upto 125MHz.
+      '';
+    };
+
+    touch = {
+      enable = mkEnableOption "MHS-3.5 ADS7846 touch support" // {
+        default = true;
+      };
+
+      calibrationMatrix = mkOption {
+        type = types.nullOr types.str;
+        default = defaultMatrices.${toString cfg.rotation} or null;
+        description = ''
+          Touch calibration matrix for touchscreen (libinput).
+          Set as LIBINPUT_CALIBRATION_MATRIX in udev.
+        '';
+      };
+    };
+  };
+
+  config = mkIf cfg.enable {
+    assertions = [
+      {
+        assertion = !cfg.touch.enable || cfg.touch.calibrationMatrix != null;
+        message = ''
+          hardware.mhs35: no known touch calibration matrix for
+          rotation ${toString cfg.rotation}!
+          set `hardware.mhs35.touch.calibrationMatrix` explicitly.
+          (and consider contributing the matrix! :3)
+        '';
+      }
+    ];
+
+    boot.extraModulePackages = [ mhs35-module ];
+
+    # do not let the default in-tree ili9486 win control over our device!
+    # (it also lists compatibility with "waveshare,rpi-lcd-35")
+    boot.blacklistedKernelModules = [ "ili9486" ];
+
+    hardware.deviceTree.overlays = [
+      {
+        name = "mhs35-overlay";
+        dtsText = panelDts;
+      }
+    ] ++ optional cfg.touch.enable {
+      name = "mhs35-touch-overlay";
+      dtsFile = ./dts/mhs35-touch-overlay.dts;
+    };
+
+    services.libinput.enable = mkIf cfg.touch.enable true;
+
+    services.udev.extraRules = mkIf cfg.touch.enable ''
+      ATTRS{name}=="ADS7846 Touchscreen", ENV{LIBINPUT_CALIBRATION_MATRIX}="${cfg.touch.calibrationMatrix}"
+    '';
+  };
+}