# 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}" ''; }; }