Compare commits

...

11 Commits

Author SHA1 Message Date
2f081d3e19 fix: panel-cwu50 timing fix from Rex's kernel - native 720x1280 mode
Swap H/V display mode to native panel resolution (720x1280) instead of
rotated (1280x720). The DRM/KMS pipeline handles rotation via connector
orientation property. Setting wrong horizontal resolution caused DSI
controller to send extra pixels per line, resulting in horizontal
repetition.

Add DCS-based panel detection in init_sequence2 as supplemental check.

Based on ak-rex/ClockworkPi-linux rpi-6.12.y branch panel-cwu50.c.

Replaces old 0008 patches (DSI_INIT0, BURST removal) that didn't fix
the issue.
2026-06-13 20:19:19 -04:00
5aca97e057 Merge pull request 'feat: add uConsole CM5 host with Reticulum mesh network support' (#61) from feat/uconsole-cm5-v3 into master
Reviewed-on: #61
2026-06-06 13:19:19 +00:00
a51e095717 feat: enable aarch64 cross-build on lazyworkhorse (QEMU binfmt + extra-platforms) 2026-06-06 09:16:23 -04:00
9ebbb1c0c6 fix: bump nixos-raspberrypi to v1.20260517.0 (matches nixos-uconsole tested version) 2026-06-05 23:38:21 -04:00
7f11da1878 fix: let nixos-raspberrypi manage kernel version (patches incompatible with linuxPackages_latest) 2026-06-05 23:33:10 -04:00
29cc20bb04 fix: add wants=network-online.target to rnsd and kismet services to silence eval warnings 2026-06-05 22:58:09 -04:00
1617ac9149 fix: migrate from deprecated kernelboot to kernel bootloader for nixos-raspberrypi 2026-06-05 22:57:26 -04:00
24f15c98cd fix: add format=setuptools to all reticulum overlay python packages 2026-06-05 22:46:54 -04:00
bdd6d03739 fix: use mkForce for PermitRootLogin to override upstream module default 2026-06-05 22:45:59 -04:00
a0a6663793 fix: use mkForce for PasswordAuthentication to override upstream module default 2026-06-05 22:45:30 -04:00
b66ffadb79 fix: add missing 'keys' to uConsole module args 2026-06-05 22:43:53 -04:00
5 changed files with 178 additions and 75 deletions

View File

@@ -12,18 +12,21 @@
url = "git+https://git.lix.systems/lix-project/lix?ref=main"; url = "git+https://git.lix.systems/lix-project/lix?ref=main";
inputs.nixpkgs.follows = "nixpkgs"; inputs.nixpkgs.follows = "nixpkgs";
}; };
nixpkgs-uconsole.url = "github:NixOS/nixpkgs/nixos-25.11";
nixos-uconsole = { nixos-uconsole = {
url = "github:nixos-uconsole/nixos-uconsole"; url = "github:nixos-uconsole/nixos-uconsole/v1.1.0";
inputs.nixpkgs.follows = "nixpkgs"; inputs.nixpkgs.follows = "nixpkgs-uconsole";
inputs.nixos-raspberrypi.follows = "nixos-raspberrypi";
}; };
nixos-raspberrypi = { nixos-raspberrypi = {
url = "github:nvmd/nixos-raspberrypi/v1.20260317.0"; url = "github:gortium/nixos-raspberrypi/cm5-cross-v1";
inputs.nixpkgs.follows = "nixpkgs"; inputs.nixpkgs.follows = "nixpkgs-uconsole";
}; };
self.submodules = true;
}; };
outputs = { self, nixpkgs, agenix, lix, nixos-uconsole, nixos-raspberrypi, ... }@inputs: outputs = { self, nixpkgs, agenix, lix
, nixpkgs-uconsole, nixos-uconsole, nixos-raspberrypi
, ... }@inputs:
let let
system = "x86_64-linux"; system = "x86_64-linux";
keys = import ./lib/keys.nix; keys = import ./lib/keys.nix;
@@ -34,20 +37,16 @@
"/etc/ssh/ssh_host_ed25519_key" "/etc/ssh/ssh_host_ed25519_key"
"/root/.age/bootstrap.key" ]; "/root/.age/bootstrap.key" ];
}; };
overlays = [ agenix.overlays.default (import ./overlays/reticulum.nix) ]; overlays = [ agenix.overlays.default ];
pkgs = import nixpkgs { pkgs = import nixpkgs {
inherit system overlays; inherit system overlays;
config.allowUnfree = true; config.allowUnfree = true;
config.permittedInsecurePackages = [ config.permittedInsecurePackages = [ "openclaw-2026.3.12" ];
"openclaw-2026.3.12"
];
}; };
devShell = import ./shells/nix_dev.nix { devShell = import ./shells/nix_dev.nix {
inherit pkgs system agenix; inherit pkgs system agenix;
}; };
in in {
{
nixosConfigurations = { nixosConfigurations = {
lazyworkhorse = nixpkgs.lib.nixosSystem { lazyworkhorse = nixpkgs.lib.nixosSystem {
specialArgs = { inherit system self keys paths inputs; }; specialArgs = { inherit system self keys paths inputs; };
@@ -56,9 +55,7 @@
nixpkgs.overlays = overlays; nixpkgs.overlays = overlays;
nixpkgs.config.allowUnfree = true; nixpkgs.config.allowUnfree = true;
nixpkgs.config.rocmSupport = true; nixpkgs.config.rocmSupport = true;
nixpkgs.config.permittedInsecurePackages = [ nixpkgs.config.permittedInsecurePackages = [ "openclaw-2026.3.12" ];
"openclaw-2026.3.12"
];
nix.package = lix.packages.${system}.default; nix.package = lix.packages.${system}.default;
} }
agenix.nixosModules.default agenix.nixosModules.default
@@ -89,22 +86,71 @@
]; ];
}; };
uConsole = nixos-raspberrypi.lib.nixosSystem { uconsole-cm5 = nixpkgs-uconsole.lib.nixosSystem {
specialArgs = { inherit self keys paths inputs nixos-raspberrypi; }; system = "aarch64-linux";
specialArgs = {
inherit self keys paths inputs;
nixos-raspberrypi = nixos-raspberrypi;
isCM4 = false;
};
modules = [ modules = [
{ {
nixpkgs.overlays = overlays; nixpkgs.buildPlatform = "x86_64-linux";
nixpkgs.config.allowUnfree = true;
nixpkgs.hostPlatform = "aarch64-linux"; nixpkgs.hostPlatform = "aarch64-linux";
nix.package = lix.packages."aarch64-linux".default; nixpkgs.config.allowUnfree = true;
boot.loader.raspberry-pi.bootloader = "kernel";
} }
nixos-raspberrypi.nixosModules.nixpkgs-rpi
# Fix display timings from Rex's kernel: native 720x1280 instead of
# rotated 1280x720, plus DCS-based panel detection.
({ lib, ... }: {
boot.kernelPatches = [{
name = "panel-cwu50-rex-timing-fix";
patch = ./patches/0008-panel-cwu50-rex-timing-fix.patch;
}];
})
nixos-raspberrypi.nixosModules.raspberry-pi-5.base nixos-raspberrypi.nixosModules.raspberry-pi-5.base
nixos-raspberrypi.lib.inject-overlays
nixos-raspberrypi.lib.inject-overlays-global
nixos-uconsole.nixosModules.uconsole-cm5 nixos-uconsole.nixosModules.uconsole-cm5
./hosts/uConsole/configuration.nix ({ config, lib, pkgs, inputs, ... }: let
./hosts/uConsole/hardware-configuration.nix lix-cross = import inputs.nixpkgs-uconsole {
localSystem = { system = "x86_64-linux"; };
crossSystem = { system = "aarch64-linux"; };
overlays = [ inputs.lix.overlays.default ];
};
in { nix.package = lix-cross.lix; })
agenix.nixosModules.default
./hosts/uconsole-cm5/configuration.nix
./hosts/uconsole-cm5/hardware-configuration.nix
]; ];
}; };
}; };
devShells.${system}.default = devShell; devShells.${system}.default = devShell;
packages.${system} = {
uconsole-cm5-image = (nixos-raspberrypi.lib.nixosSystem {
system = "aarch64-linux";
specialArgs = {
inherit self keys inputs;
nixos-raspberrypi = nixos-raspberrypi;
isCM4 = false;
};
modules = [
{
nixpkgs.buildPlatform = system;
nixpkgs.hostPlatform = "aarch64-linux";
}
nixos-raspberrypi.nixosModules.nixpkgs-rpi
nixos-raspberrypi.nixosModules.raspberry-pi-5.base
nixos-raspberrypi.lib.inject-overlays-global
nixos-raspberrypi.nixosModules.sd-image
nixos-uconsole.nixosModules.uconsole-cm5
agenix.nixosModules.default
./hosts/uconsole-cm5/configuration.nix
];
}).config.system.build.sdImage;
};
}; };
} }

View File

@@ -11,6 +11,10 @@
# Flakesss # Flakesss
nix.settings.experimental-features = [ "nix-command" "flakes" "flake-self-attrs" ]; nix.settings.experimental-features = [ "nix-command" "flakes" "flake-self-attrs" ];
nix.settings.trusted-users = [ "root" "gortium" ]; nix.settings.trusted-users = [ "root" "gortium" ];
nix.settings.extra-platforms = [ "aarch64-linux" ];
# QEMU binfmt for cross-building aarch64 NixOS targets
boot.binfmt.emulatedSystems = [ "aarch64-linux" ];
# Garbage collection # Garbage collection
nix.gc = { nix.gc = {

View File

@@ -1,4 +1,4 @@
{ config, lib, pkgs, paths, self, ... }: { config, lib, pkgs, paths, self, keys, ... }:
{ {
# Basic Host Info # Basic Host Info
@@ -9,15 +9,17 @@
# System State # System State
system.stateVersion = "25.05"; system.stateVersion = "25.05";
# Boot & Hardware (uconsole-cm5 module handles boot.loader) # Boot & Hardware (migrated to kernel bootloader per nixos-raspberrypi deprecation notice)
boot.kernelPackages = pkgs.linuxPackages_latest; boot.loader.raspberry-pi.bootloader = "kernel";
# kernel managed by nixos-raspberrypi module — don't override, patches are version-specific
# boot.kernelPackages = pkgs.linuxPackages_latest;
# Networking # Networking
networking.networkmanager.enable = true; networking.networkmanager.enable = true;
services.openssh = { services.openssh = {
enable = true; enable = true;
settings.PermitRootLogin = "prohibit-password"; settings.PermitRootLogin = lib.mkForce "prohibit-password";
settings.PasswordAuthentication = false; settings.PasswordAuthentication = lib.mkForce false;
}; };
# User # User
@@ -106,6 +108,7 @@
# ============================================================ # ============================================================
systemd.services.rnsd = { systemd.services.rnsd = {
description = "Reticulum Network Stack Daemon"; description = "Reticulum Network Stack Daemon";
wants = [ "network-online.target" ];
after = [ "network-online.target" ]; after = [ "network-online.target" ];
wantedBy = [ "multi-user.target" ]; wantedBy = [ "multi-user.target" ];
serviceConfig = { serviceConfig = {
@@ -123,6 +126,7 @@
# ============================================================ # ============================================================
systemd.services.kismet = { systemd.services.kismet = {
description = "Kismet Wi-Fi Monitor & IDS"; description = "Kismet Wi-Fi Monitor & IDS";
wants = [ "network-online.target" ];
after = [ "network-online.target" ]; after = [ "network-online.target" ];
wantedBy = [ "multi-user.target" ]; wantedBy = [ "multi-user.target" ];
serviceConfig = { serviceConfig = {

View File

@@ -5,6 +5,7 @@ in {
reticulumStack = python3.pkgs.buildPythonApplication rec { reticulumStack = python3.pkgs.buildPythonApplication rec {
pname = "reticulum"; pname = "reticulum";
version = "1.2.9"; version = "1.2.9";
format = "setuptools";
src = pyPkgs.fetchPypi { src = pyPkgs.fetchPypi {
pname = "rns"; pname = "rns";
inherit version; inherit version;
@@ -24,6 +25,7 @@ in {
lxmf = python3.pkgs.buildPythonApplication rec { lxmf = python3.pkgs.buildPythonApplication rec {
pname = "lxmf"; pname = "lxmf";
version = "0.9.8"; version = "0.9.8";
format = "setuptools";
src = pyPkgs.fetchPypi { src = pyPkgs.fetchPypi {
inherit pname version; inherit pname version;
sha256 = "30f39f3a975a049c12ee2cfceb3261d24cb5adec881c6821f7354464b3f3650c"; sha256 = "30f39f3a975a049c12ee2cfceb3261d24cb5adec881c6821f7354464b3f3650c";
@@ -42,6 +44,7 @@ in {
nomadnet = python3.pkgs.buildPythonApplication rec { nomadnet = python3.pkgs.buildPythonApplication rec {
pname = "nomadnet"; pname = "nomadnet";
version = "1.1.1"; version = "1.1.1";
format = "setuptools";
src = pyPkgs.fetchPypi { src = pyPkgs.fetchPypi {
inherit pname version; inherit pname version;
sha256 = "fa13b64a10e75b705a58024815ab72451700aa726af96d415ba99dec28dfc40a"; sha256 = "fa13b64a10e75b705a58024815ab72451700aa726af96d415ba99dec28dfc40a";
@@ -60,6 +63,7 @@ in {
rnsh = python3.pkgs.buildPythonApplication rec { rnsh = python3.pkgs.buildPythonApplication rec {
pname = "rnsh"; pname = "rnsh";
version = "0.1.7"; version = "0.1.7";
format = "setuptools";
src = pyPkgs.fetchPypi { src = pyPkgs.fetchPypi {
inherit pname version; inherit pname version;
sha256 = "9cb72f25abb1c6d300f8014b264184ff78f592fe88e36094938012990b797c93"; sha256 = "9cb72f25abb1c6d300f8014b264184ff78f592fe88e36094938012990b797c93";

View File

@@ -0,0 +1,45 @@
--- a/drivers/gpu/drm/panel/panel-cwu50.c
+++ b/drivers/gpu/drm/panel/panel-cwu50.c
@@ -27,12 +27,12 @@ static const struct drm_display_mode default_mode = {
.clock = 61020,
- .hdisplay = 1280,
- .hsync_start = 1280 + 8,
- .hsync_end = 1280 + 8 + 2,
- .htotal = 1280 + 8 + 2 + 16,
- .vdisplay = 720,
- .vsync_start = 720 + 30,
- .vsync_end = 720 + 30 + 15,
- .vtotal = 720 + 30 + 15 + 15,
+ .hdisplay = 720,
+ .hsync_start = 720 + 30,
+ .hsync_end = 720 + 30 + 15,
+ .htotal = 720 + 30 + 15 + 15,
+ .vdisplay = 1280,
+ .vsync_start = 1280 + 8,
+ .vsync_end = 1280 + 8 + 2,
+ .vtotal = 1280 + 8 + 2 + 16,
};
static inline struct cwu50 *panel_to_cwu50(struct drm_panel *panel)
@@ -586,7 +586,8 @@ static int cwu50_init_sequence2(struct cwu50 *ctx)
{
struct mipi_dsi_device *dsi = to_mipi_dsi_device(ctx->dev);
- int err;
+ int err;
+ u8 buf[4];
dcs_write_seq(0xE0,0x00);
@@ -633,6 +634,12 @@ static int cwu50_init_sequence2(struct cwu50 *ctx)
dcs_write_seq(0x11);// SLPOUT
msleep (200);
+ dcs_write_seq(0xE0,0x00);
+ mipi_dsi_dcs_read(dsi, 0x04, buf, 3);
+
+ if(buf[0] == 0x39) ctx->is_new_panel = 1;
+
+ dcs_write_seq(0xE0,0x00);
dcs_write_seq(0x29);// DSiPON
msleep (100);