Experimental · one hardware configuration proven

Native 5K.
One real monitor.

The tested dual-stream LG 27MD5KA sends two 2560×2880 DisplayPort streams. This Aquamarine prototype joins them into one 5120×2880@60 Hyprland output—with the distro library left untouched.

Omarchy first Hyprland 0.56.2 Aquamarine 0.14 · ABI 13 LG 27MD5KA + AMD proven

Read this before trying it

Native 5K at login worked on one tested machine. This is not a finished driver.

Proven: one native 5120×2880@60 output at login, scale 2, from two synchronized 2560×2880 tiles on one LG + Radeon 780M system.

Not supported by the recommended cut: grouped display sleep/DPMS and Night Light/CTM. Hotplug, VT switching, suspend/resume, docks, multi-GPU, and multi-monitor use are also unproven. A later research build attempted DPMS incorrectly and produced a retry storm; it is not recommended.

This guide uses the last hardware-proven startup-only cut, isolates it from /usr/lib, and preserves the stock login session. The candidate Hyprland config is a bare verification desktop: it imports no Omarchy graphical shell, modules, autostart, user hooks, lock/idle code, Night Light, or output-management bindings. SDDM still runs the account’s Bash login profile before the wrapper can clean its environment, so custom login-profile side effects require agent review. If you need normal desktop features, do not use the prototype yet.

The problem in plain English

The panel is one screen.
Linux receives two halves.

Native 5K exceeded a single DisplayPort 1.2 stream when this display shipped. The monitor carries two streams over one cable and marks them as a 2×1 DRM TILE group.

Stock Aquamarine

Two outputs—or a 3840×2160 fallback that the panel scales.

Experimental Aquamarine

Left crop to CRTC A, right crop to CRTC B, committed together.

01

Discover the TILE group.

Aquamarine reads the kernel’s TILE connector properties and checks that the two members describe one complete panel.

02

Publish one logical output.

Hyprland sees one 5120×2880 monitor. At scale 2, the workspace is a crisp 2560×1440 logical desktop.

03

Scan one frame across both halves.

The prototype shares one full-width framebuffer and programs complementary 2560×2880 crops in one grouped atomic transaction.

Step zero · read-only

First prove you have the same problem.

The preflight script makes no changes and uses no sudo. It inventories packages, ABI, GPU, connected outputs, EDID topology, and kernel DRM TILE properties. Its report is evidence for an experienced reviewer—not automatic approval.

An expert must confirm

  • Two connected DisplayPort connectors on one DRM device.
  • One complete 2×1 TILE group with matching panel identity.
  • Both members offer 2560×2880@60.
  • Atomic, local scanout on the primary GPU.
×

Stop here

  • One connector, no TILE property, or tiles on different GPUs.
  • A true 5120×2880 connector already exists.
  • NVIDIA, leases, legacy KMS, blit, dock, or cross-device path.
  • No live, tested SSH recovery path from another device.

Current guided build gate

OSOmarchy 4.0.1-1

Hyprland0.56.2-1

Aquamarine0.14.0-2 · SONAME 13

UWSM0.26.7-1

Linux7.1.9.arch1-2

EDID toolsv4l-utils 1.32.0-2

Architecturex86_64

LoginSDDM 0.21.0-7 · bare direct candidate

The guided script is deliberately narrower than the idea. It accepts exactly the proven LG UltraFine 27MD5KA identity, two DisplayPort streams, the Radeon 780M-class amdgpu path, no other connected monitor, and the pinned package matrix above. This is the current build-compatibility gate, not the original hardware-proof matrix: the physical candidate-login proof used Omarchy 4.0.0-1 and Linux 7.1.8-arch1-3. Another TILE display may use the same architecture, but it needs an expert port—not this copy-and-paste path.

SHA-256 · 3e4ee6af…287be8f

Download and run the read-only report.

Read the script on this page first. If the checksum differs, stop.

preflight=$(mktemp)
curl --fail --location \
  https://aquamarine.youens.com/native5k-preflight.sh \
  --output "$preflight"
printf '%s  %s\n' \
  3e4ee6af9c8298576fd474022c2165c7548695f4c55b6d60b8a384e2d287be8f \
  "$preflight" | sha256sum --check -
/usr/bin/env -u BASH_ENV -u ENV \
  /usr/bin/bash --noprofile --norc "$preflight"
Read native5k-preflight.sh Read-only Bash · 18.7 KB Not loaded
Download
Open this section to load and verify the script.

Recommended route

Let your agent do the machine-specific work.

The source is pinned, but activation depends on your ABI, DRM topology, display manager, and recovery setup. This prompt makes the agent prove each gate and wait before touching the system.

Prompt SHA-256 · 6a6399c867c5c453d02251cfad62d43abd5954f5d1311dbb4855cd0084b92b03

Loading the exact agent prompt…

Omarchy guided path

Build first. Activate separately.

This route is deliberately split in two. The stage script builds and tests in your home directory without sudo. Only after review do you add a separate login-session entry. It is for the exact Omarchy/SDDM matrix and an already-equipped Arch development system; missing build tools or libraries cause a refusal, not an automatic install.

STEP 01

Run the preflight and save its report.

Continue only when the result is needs-expert-topology-review and a human or agent independently confirms one complete matching 2×1 TILE group on one DRM device, equal 2560×2880@60 modes, local atomic scanout, and the exact package matrix. already-native-5k-stop means another build is already providing 5K; identify its live mapped library instead of stacking this prototype. autologin-agent-required-stop means SDDM cannot safely expose a one-time manual chooser.

STEP 02

Stage the proven source cut—no sudo.

The script verifies its 21-commit mbox, reproduces the expected Git tree, builds, runs CTest with inherited library overrides removed, and installs only under your user data directory. Stock Omarchy includes base-devel, but CMake and Ninja are not guaranteed.

pacman -Q base-devel cmake ninja v4l-utils

# Only if a reviewed prerequisite is missing:
sudo pacman -S --needed base-devel cmake ninja v4l-utils

The package-install line changes the system and is separate from the no-sudo stage script. If you are using an agent, it should show you what is missing and wait for approval.

stage_script=$(mktemp)
curl --fail --location \
  https://aquamarine.youens.com/native5k-stage.sh \
  --output "$stage_script"
printf '%s  %s\n' \
  b1b3d8d7b8fd9684d65874fb41ea36b9f879871e6563f5793af8ecb83de19a06 \
  "$stage_script" | sha256sum --check -
/usr/bin/env -u BASH_ENV -u ENV \
  /usr/bin/bash --noprofile --norc "$stage_script"

Expected source: base f3d1804 → head 01cad21 → tree 08f6997bc876ea459d1fae4876cd25eac474e835.

STEP 03

Review the staged result and recovery plan.

Check the printed library and isolated-config hashes, SONAME, test result, complete dynamic-loader report, topology-derived aggregate connector, both EDID hashes, and the three recovery-first bindings. Review ~/.bash_profile and the noninteractive path through ~/.bashrc, because SDDM runs them before the candidate wrapper; use the agent route if they have side effects. Before installing or logging out, connect from a second device, run sudo -v, and leave that SSH session open. A TTY is secondary because VT switching under the candidate is unproven.

STEP 04

Add a separate session, leaving stock Omarchy intact.

Proceed manually only if preflight prints sddm_manual_selection_safe=yes; otherwise stop and use the agent-reviewed route—do not edit SDDM yourself. This activation reruns the verified read-only preflight before sudo, then installs two new, explicitly named files under /usr/local. It refuses pre-existing targets, does not replace the stock session, does not edit /usr/lib, and never points autologin at the candidate.

(
set -e
export PATH=/usr/bin
stage_root="$HOME/.local/share/aquamarine-native5k/01cad21"
wrapper_target=/usr/local/bin/aquamarine-native5k-session
desktop_target=/usr/local/share/wayland-sessions/aquamarine-native5k.desktop
preflight_script=$(mktemp)
preflight_report=$(mktemp)
cleanup_preflight() {
  rm -f -- "$preflight_script" "$preflight_report"
}
trap cleanup_preflight EXIT

curl --fail --location \
  https://aquamarine.youens.com/native5k-preflight.sh \
  --output "$preflight_script"
printf '%s  %s\n' \
  3e4ee6af9c8298576fd474022c2165c7548695f4c55b6d60b8a384e2d287be8f \
  "$preflight_script" | sha256sum --check -
/usr/bin/env -u BASH_ENV -u ENV \
  /usr/bin/bash --noprofile --norc "$preflight_script" \
  >"$preflight_report"

grep -qx 'result=needs-expert-topology-review' "$preflight_report" || {
  cat "$preflight_report"
  printf 'Preflight no longer permits guided activation. Stop.\n' >&2
  exit 1
}
grep -qx 'sddm_manual_selection_safe=yes' "$preflight_report" || {
  cat "$preflight_report"
  printf 'SDDM needs an agent-reviewed selection plan. Stop.\n' >&2
  exit 1
}
cleanup_preflight
trap - EXIT

for target in "$wrapper_target" "$desktop_target"; do
  if [[ -e "$target" || -L "$target" ]]; then
    printf 'Refusing existing target: %s\n' "$target" >&2
    exit 1
  fi
done
for directory in /usr/local/bin /usr/local/share/wayland-sessions; do
  [[ -d "$directory" && ! -L "$directory" ]] || {
    printf 'Required real directory is missing: %s\n' "$directory" >&2
    exit 1
  }
  directory_owner=$(stat -c '%U:%G' "$directory")
  directory_mode=$(stat -c '%a' "$directory")
  [[ $directory_owner == root:root && $directory_mode =~ ^[0-7]{3,4}$ ]] || {
    printf 'Unsafe installation directory ownership or mode: %s\n' "$directory" >&2
    exit 1
  }
  (( (8#$directory_mode & 0022) == 0 )) || {
    printf 'Installation directory is group/world writable: %s\n' "$directory" >&2
    exit 1
  }
done
[[ -f "$stage_root/aquamarine-native5k-session" &&
   ! -L "$stage_root/aquamarine-native5k-session" &&
   -O "$stage_root/aquamarine-native5k-session" &&
   -f "$stage_root/aquamarine-native5k.desktop" &&
   ! -L "$stage_root/aquamarine-native5k.desktop" &&
   -O "$stage_root/aquamarine-native5k.desktop" ]] || {
  printf 'The user-local stage is incomplete. Stop.\n' >&2
  exit 1
}

wrapper_tmp=
desktop_tmp=
cleanup_install() {
  status=$?
  trap - EXIT HUP INT TERM
  if (( status != 0 )); then
    if [[ -n $desktop_tmp ]] && sudo test "$desktop_target" -ef "$desktop_tmp"; then
      sudo rm -f -- "$desktop_target" || true
    fi
    if [[ -n $wrapper_tmp ]] && sudo test "$wrapper_target" -ef "$wrapper_tmp"; then
      sudo rm -f -- "$wrapper_target" || true
    fi
  fi
  [[ -z $wrapper_tmp ]] || sudo rm -f -- "$wrapper_tmp" || true
  [[ -z $desktop_tmp ]] || sudo rm -f -- "$desktop_tmp" || true
  exit "$status"
}
trap cleanup_install EXIT
trap 'exit 129' HUP
trap 'exit 130' INT
trap 'exit 143' TERM

wrapper_tmp=$(sudo mktemp \
  /usr/local/bin/.aquamarine-native5k-session.installing.XXXXXXXX)
desktop_tmp=$(sudo mktemp \
  /usr/local/share/wayland-sessions/.aquamarine-native5k.installing.XXXXXXXX)

sudo install -m755 /dev/stdin "$wrapper_tmp" \
  <"$stage_root/aquamarine-native5k-session"

sudo install -m644 /dev/stdin "$desktop_tmp" \
  <"$stage_root/aquamarine-native5k.desktop"

cmp --silent "$stage_root/aquamarine-native5k-session" "$wrapper_tmp"
cmp --silent "$stage_root/aquamarine-native5k.desktop" "$desktop_tmp"

sudo ln -T -- "$wrapper_tmp" "$wrapper_target"
sudo ln -T -- "$desktop_tmp" "$desktop_target"

cmp --silent "$stage_root/aquamarine-native5k-session" "$wrapper_target"
cmp --silent "$stage_root/aquamarine-native5k.desktop" "$desktop_target"
[[ $(stat -c '%U:%G:%a' "$wrapper_target") == root:root:755 ]]
[[ $(stat -c '%U:%G:%a' "$desktop_target") == root:root:644 ]]
)

Log out normally—do not reboot or restart SDDM—and choose Omarchy (experimental native 5K). Expect a deliberately bare Hyprland logo desktop: Super+Return opens a clean Alacritty/Bash recovery terminal, Super+Q closes a window, and Super+Shift+Escape returns to SDDM. A one-shot stock autologin with an explicit stock session and Relogin=false is safe after its first login; an empty Session is not, because SDDM can reuse the last selected session. The candidate must never become the autologin target.

Screen sleep is deliberately unavailable in the candidate.

The candidate starts /usr/bin/Hyprland directly—without UWSM, the restart watchdog, imported Omarchy modules, Hyprland autostart, or graphical-session services—and disables input-triggered DPMS wake. SDDM’s account login profile is a separate pre-wrapper boundary; review it before activation. The candidate has no lock or idle blanking, so the panel remains on until you exit. This avoids the known broken path; it does not fix DPMS. A manual absolute-path command can still bypass policy: do not run /usr/bin/hyprctl DPMS, monitor keyword, reload, or CTM actions. Return to stock Omarchy if you need normal desktop features.

No universal “latest” command exists.

The prototype is based on an older Aquamarine tree and uses C++ ABI-sensitive libraries. The stage script intentionally refuses newer package versions instead of downgrading or forcing the patch. A current Aquamarine port is real engineering work, not a version-number substitution.

Read native5k-stage.sh before running it Build and user-stage helper · 32.7 KB · no sudo Not loaded
Download
Open this section to load and verify the script.

First candidate login

Success is specific and measurable.

Do not judge by appearance alone. Verify that Hyprland loaded the isolated library and published one real 5K output.

Check the compositor.

Expected: no config errors and exactly one enabled 5120×2880 output near 60 Hz at scale 2.

/usr/bin/hyprctl configerrors
/usr/bin/hyprctl -j monitors all |
  /usr/bin/jq '.[] | {
    name, width, height,
    refreshRate, scale, disabled
  }'

Check the mapped library.

Expected: the path under your user data directory—not /usr/lib and not a mystery global override.

hypr_pid=$(/usr/bin/pgrep -u "$UID" -n -x Hyprland)
/usr/bin/awk '/libaquamarine\.so/ {print $6}' \
  "/proc/$hypr_pid/maps" |
  /usr/bin/sort -u

printf 'startup_only=%s\n' "$NATIVE5K_STARTUP_ONLY"
/usr/bin/hyprctl -j binds |
  /usr/bin/jq -r '.[].description'

Expected isolation: startup_only=1 and exactly the three documented binding descriptions. No omarchy-shell, hypridle, or hyprsunset process should exist. An agent should also discover both active DRM members and prove that their primary planes share one nonzero framebuffer with left/right 2560×2880 source crops. If any check fails, press Super+Shift+Escape and return to stock.

Exact source

The full native-5K patch is here.

The canonical artifact contains the 21 commits through the last hardware-proven startup cut. It is large because it preserves the development slices and tests; it is not an upstream-ready series.

Source identity

Base f3d1804205e8158c15595cdda1b566f93349ffae
Historical head 01cad213c76ab1cc4adfe80ad9b7093f9e4c721b
Result tree 08f6997bc876ea459d1fae4876cd25eac474e835

Artifact identity

21 mail patches · 1,818,248 bytes
SHA-256
e4d1493cdb65dc90f7cdb4b03120fa23ca549ddc57ff8b14c67e255652eeed5c

Physical proof

LG 27MD5KA + Radeon 780M on Omarchy 4.0.0-1 and Linux 7.1.8-arch1-3: one 5120×2880@60 output, one shared framebuffer split into complementary tile crops, 30-second paired page-flip soak, and stock rollback.

Why this cut

The exact machine now loads acd258c, three commits later, on Omarchy 4.0.1-1 and Linux 7.1.9. That is evidence that the inherited startup core still runs on the newer matrix, but it is not a fresh 01cad21 candidate login or proof of that exact cut on the newer matrix. Its build, tests, loader selection, and config are verified here; the page does not turn that inference into hardware proof.

Read all 21 native-5K source patches Full mbox · 1.82 MB · lazy-loaded Not loaded
Download mbox
Open this section to load and verify the complete source series.
Research provenance: what is running on the example machine?

The current example-machine session—not the recommended 01cad21 cut and not the small upstream patch—loads acd258c (tree 563609b2…), which contains the broken experimental DPMS implementation. During final August 30 inspection, its log contained 19,199 accumulated outer disable failures with submit=-22; -22 is Linux EINVAL, meaning the kernel rejected the atomic request. The total rose from 14,599 during this review as the lock/blank path retriggered. It does not mean 19,199 separate user actions—or that ioctls fire continuously at every instant—and each outer failure can follow four rejected ioctls. Three of the four retry shapes put the connector’s legacy DPMS property into an atomic request, which the Linux KMS contract forbids. The sole no-DPMS shape still tears down connector routes and planes instead of only toggling the CRTCs’ active state; AMD rejects that request too.

The intended backend repair is one grouped atomic commit that toggles only both tile CRTCs’ ACTIVE properties—0 for sleep and 1 for wake—while preserving mode, routes, planes, framebuffer, and CTM. That repair is not yet implemented or hardware-proven. The current panel only appears off because a separate LG USB helper blanks its backlight.

The exact-current source mbox is preserved for engineering comparison, not installation: download acd258c research mbox · SHA-256 7b2c067269e579b601982cc8556bdac77af4875692537247fd3f8d1574088630.

For developers · separate work

The small upstream patch is not the 5K patch.

The five-file c8dd371 patch makes Aquamarine more conservative before hiding DRM TILE connectors. That is useful upstream groundwork, but it neither joins two streams nor enables native 5K.

Upstream-sized

TILE suppression validation

Requires a complete, consistent group and one exact aggregate-mode owner before suppressing peer connectors.

SHA-256 · dc58953120adde209b93d8747bf66e9c21ba80b2b9da5087063bd86606dab89c

Native aggregation

Must be redesigned for current Aquamarine.

The 21-commit prototype is behavioral and hardware evidence. Current upstream has a newer asynchronous commit architecture, so the native solution should be re-derived—not rebased wholesale.

Start with the report, not the installer.

If the topology and ABI match, the experimental source can produce real native 5K. If they do not, stopping is the correct result.