From 9c57de06f78d899f3572d47daf3cc88516721894 Mon Sep 17 00:00:00 2001 From: Federico Krum Date: Fri, 13 Feb 2026 15:38:06 +0100 Subject: [PATCH] [H700] Improve display rotation handling and aspect ratio for HDMI outputs This commit improves the experience of using vertical (portrait) monitors via HDMI on Allwinner H700 based devices (RG40XX, RG35XX, etc.) and adds support for independent rotation settings between internal and external displays. Key Improvements: 1. Aspect Ratio Correction: Automatically reports an inverted resolution (e.g., 720x1280 instead of 1280x720) when rotation is set to 90 or 270 degrees. This ensures that EmulationStation and the UI render with correct proportions without image stretching. 2. Context-Aware Rotation: Implements persistence for rotation settings per output. The script automatically synchronizes the system's rotation setting based on whether HDMI is connected or if the internal panel is being used. 3. Software Rotation Fallback: Forces software rotation (via EmulationStation's --screenrotate) in vertical modes. This bypasses hardware rotation limitations on the H700 chip that often cause artifacts or incorrect scaling on digital outputs. 4. Backward Compatibility: Maintains existing logic for other boards (like RG28XX) and ensures zero impact on performance or behavior for standard horizontal orientations. Technical Details: - Modified 'currentResolution' to conditionally swap dimensions based on the effective rotation value. - Added 'sync_rotation_per_output' to manage 'display.rotate.hdmi' and 'display.rotate.internal' configuration keys. - Fully compatible with the existing Knulli system settings UI. --- .../fsoverlay/usr/bin/batocera-resolution | 72 +++++++++++++++++-- 1 file changed, 67 insertions(+), 5 deletions(-) diff --git a/board/batocera/allwinner/h700/fsoverlay/usr/bin/batocera-resolution b/board/batocera/allwinner/h700/fsoverlay/usr/bin/batocera-resolution index f602a181a74..73e49bc76b4 100755 --- a/board/batocera/allwinner/h700/fsoverlay/usr/bin/batocera-resolution +++ b/board/batocera/allwinner/h700/fsoverlay/usr/bin/batocera-resolution @@ -1,15 +1,58 @@ #!/bin/sh +# Batocera Resolution Script - Knulli RC1 (Revised) +# Purpose: Add context-aware rotation per output and aspect ratio correction for vertical modes. +# This script handles hardware limitations of the Allwinner H700 (RG40XX, RG35XX) +# to allow perfect vertical display on HDMI outputs from the System Settings menu. + DISPLAY="/sys/kernel/debug/dispdbg" HDMI_STATE="/sys/devices/platform/soc/6000000.hdmi/extcon/hdmi/state" +LAST_STATE_FILE="/var/run/last_hdmi_state" BOARD=$(cat /boot/boot/batocera.board) +# Configuration keys for contextual rotation storage +KEY_GLOBAL="display.rotate" +KEY_HDMI="display.rotate.hdmi" +KEY_INT="display.rotate.internal" + f_usage() { echo "$0 listOutputs" >&2 echo "$0 currentResolution" >&2 echo "$0 setOutput" >&2 } +# Sync UI button with active output (Contextual Rotation Persistence) +sync_rotation_per_output() { + STATE=$(cat "$HDMI_STATE") + [ -f "$LAST_STATE_FILE" ] && LAST_STATE=$(cat "$LAST_STATE_FILE") || LAST_STATE="none" + + UI_ROT=$(batocera-settings-get $KEY_GLOBAL) + [ -z "$UI_ROT" ] && UI_ROT=0 + + # Check if HDMI was just plugged/unplugged + if [ "$STATE" != "$LAST_STATE" ]; then + if [ "$STATE" = "HDMI=1" ]; then + SAVED_HDMI=$(batocera-settings-get $KEY_HDMI) + [ -n "$SAVED_HDMI" ] && [ "$SAVED_HDMI" != "$UI_ROT" ] && batocera-settings-set $KEY_GLOBAL "$SAVED_HDMI" + else + SAVED_INT=$(batocera-settings-get $KEY_INT) + [ -n "$SAVED_INT" ] && [ "$SAVED_INT" != "$UI_ROT" ] && batocera-settings-set $KEY_GLOBAL "$SAVED_INT" + fi + echo "$STATE" > "$LAST_STATE_FILE" + else + # Update specific config key if user changed the setting manually in the UI + [ "$STATE" = "HDMI=1" ] && batocera-settings-set $KEY_HDMI "$UI_ROT" || batocera-settings-set $KEY_INT "$UI_ROT" + fi +} + +# Retrieve the rotation value effective for the current display context +get_effective_rotation() { + STATE=$(cat "$HDMI_STATE") + [ "$STATE" = "HDMI=1" ] && ROT=$(batocera-settings-get $KEY_HDMI) || ROT=$(batocera-settings-get $KEY_INT) + [ -z "$ROT" ] && ROT=$(batocera-settings-get $KEY_GLOBAL) + echo "${ROT:-0}" +} + if [ $# -eq 0 ]; then f_usage exit 1 @@ -67,7 +110,6 @@ set_output() { } ACTION=$1 - case "${ACTION}" in "listOutputs") echo "hdmi-1080p" @@ -77,6 +119,7 @@ case "${ACTION}" in "listModes") ;; "setOutput") + sync_rotation_per_output STATE=$(cat "$HDMI_STATE") if [ "$STATE" = "HDMI=1" ]; then set_output hdmi @@ -85,10 +128,27 @@ case "${ACTION}" in fi ;; "currentResolution") - if [ "$BOARD" = "rg28xx" ]; then - fbset | grep "geometry" | awk '{print $3"x"$2}' + ROT=$(get_effective_rotation) + STATE=$(cat "$HDMI_STATE") + + # Aspect Ratio (AR) Correction for Portrait modes (90/270 degrees). + # We only apply this to rotation 1 and 3 because rotation 2 (180 degrees) + # remains horizontal and doesn't require swapping dimensions to maintain correct AR. + if [ "$ROT" = "1" ] || [ "$ROT" = "3" ]; then + if [ "$STATE" = "HDMI=1" ]; then + # Standard 16:9 HDMI output mapped to Portrait + echo "720x1280" + else + # Internal panels (RG28XX is natively portrait) + [ "$BOARD" = "rg28xx" ] && echo "640x480" || echo "480x640" + fi else - fbset | grep "geometry" | awk '{print $2"x"$3}' + # Default behavior for non-vertical modes + if [ "$BOARD" = "rg28xx" ]; then + fbset | grep "geometry" | awk '{print $3"x"$2}' + else + fbset | grep "geometry" | awk '{print $2"x"$3}' + fi fi ;; "currentOutput") @@ -101,6 +161,9 @@ case "${ACTION}" in exit 1 ;; "supportSystemRotation") + # Returning 1 forces EmulationStation to handle rotation via software (--screenrotate). + # This is necessary because H700 hardware rotation (rotset) doesn't play well + # with HDMI HDMI pixel buffers, causing image stretching. exit 1 ;; *) @@ -109,5 +172,4 @@ case "${ACTION}" in exit 1 ;; esac - exit 0