Skip to content

Commit fbfc3ea

Browse files
crackerjacquescrackerjacquesjackheinlein
authored
board: add Anbernic RG DS (RK3568 dual 4" 640x480 handheld) as CSC (#9934)
* board: add Anbernic RG DS (RK3568 dual 4" handheld) as CSC RK3568 clamshell handheld, dual 4" 640x480 MIPI-DSI. Supported by mainline drivers on edge (7.0) and bleedingedge (7.1): jadard panels, adc-joystick, goodix touch, rk817 audio, rtw88 wifi, usb. The kernel options for these are set in the shared rockchip64 edge/bleedingedge configs (not the board file). Carries the out-of-tree aw87391 speaker-amp driver (plus its DTS wiring on 7.0; 7.1 already has the amp nodes in the mainline DTS) and a goodix dual-gt911 cfg-from-disk fix. Builds mainline U-Boot v2026.01 (vendor 2017.09 does not boot this board). Needs rk3568 DDR v1.23 / BL31 v1.45 from armbian/rkbin (separate PR). Signed-off-by: crackerjacques <jack@supremeoverlordjabs.co> * anbernic-rg-ds: drop redundant board name from header comment BOARD_NAME already carries 'Anbernic RG DS'; keep only the hardware description on the first-line interactive comment (review: @EvilOlaf). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> --------- Signed-off-by: crackerjacques <jack@supremeoverlordjabs.co> Co-authored-by: crackerjacques <jack@supremeoverlordjabs.co> Co-authored-by: jackheinlein <crackerjaxx@yandex.com>
1 parent 872d188 commit fbfc3ea

16 files changed

Lines changed: 1080 additions & 0 deletions

File tree

config/boards/anbernic-rg-ds.csc

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
# RK3568 quad-core dual 4" 640x480 MIPI-DSI eMMC/MicroSD WiFi/BT 2xUSB-C
2+
BOARD_NAME="Anbernic RG DS"
3+
BOARD_VENDOR="Anbernic"
4+
BOARDFAMILY="rk35xx"
5+
BOOT_SOC="rk3568"
6+
BOARD_MAINTAINER="crackerjacques"
7+
INTRODUCED="2025"
8+
KERNEL_TARGET="edge,bleedingedge"
9+
KERNEL_TEST_TARGET="edge"
10+
11+
PACKAGE_LIST_BOARD+=" python3-evdev python3-libevdev xinput"
12+
13+
# Load the USB serial gadget at boot so the ttyGS0 console (OTG port) exists.
14+
# The shared kernel ships USB_G_SERIAL as a module, so the board loads it here.
15+
MODULES="g_serial"
16+
17+
BOOT_FDT_FILE="rockchip/rk3568-anbernic-rg-ds.dtb"
18+
BOOT_SCENARIO="spl-blobs"
19+
SERIALCON="ttyS2" # RG DS serial console: ttyS2 @ 1500000
20+
BOOTFS_TYPE="fat"
21+
IMAGE_PARTITION_TABLE="gpt"
22+
23+
# rk3568 DDR v1.23 / BL31 v1.45 (matches the ROCKNIX-proven bootloader on this
24+
# board). Fetched from armbian/rkbin at build time; no binaries committed here.
25+
BL31_BLOB="rk35/rk3568_bl31_v1.45.elf"
26+
DDR_BLOB="rk35/rk3568_ddr_1056MHz_v1.23.bin"
27+
28+
# Mainline U-Boot (quartz64-a-rk3566 defconfig + rk3568 DDR v1.23 / BL31 v1.45)
29+
function post_family_config__anbernic_rg_ds_mainline_uboot() {
30+
display_alert "$BOARD" "mainline U-Boot v2026.01 (quartz64-a-rk3566 + rk3568 DDR v1.23)" "info"
31+
declare -g BOOTCONFIG="quartz64-a-rk3566_defconfig"
32+
declare -g BOOTSOURCE="https://github.com/u-boot/u-boot.git"
33+
declare -g BOOTBRANCH="tag:v2026.01"
34+
declare -g BOOTDIR="u-boot-${BOARD}"
35+
declare -g BOOTPATCHDIR="v2026.01"
36+
declare -g UBOOT_TARGET_MAP="BL31=${RKBIN_DIR}/${BL31_BLOB} ROCKCHIP_TPL=${RKBIN_DIR}/${DDR_BLOB};;u-boot-rockchip.bin"
37+
unset uboot_custom_postprocess write_uboot_platform write_uboot_platform_mtd
38+
function write_uboot_platform() {
39+
dd "if=$1/u-boot-rockchip.bin" "of=$2" bs=32k seek=1 conv=notrunc status=none
40+
}
41+
}
42+
43+
# Board helper payloads (dual-screen layout, gamepad-to-keyboard remap, the
44+
# desktop toggle/launcher, polkit rule and controls README) ship as real files
45+
# under config/optional/boards/anbernic-rg-ds/_packages/bsp-cli/ and are baked
46+
# into the board bsp package. Here we only wire up what needs activation:
47+
# - ttyGS0 getty: USB-C gadget serial console (no accessible physical UART)
48+
# - rgds-pad2key.service: gamepad D-pad/buttons -> keyboard (evdev/uinput)
49+
# The X11 dual-screen helper needs no enabling - it is an xdg autostart entry
50+
# that self-guards to X11 sessions (see usr/bin/rgds-screen).
51+
function post_family_tweaks__anbernic_rg_ds_enable_helpers() {
52+
display_alert "$BOARD" "enabling ttyGS0 console + gamepad-to-keyboard" "info"
53+
54+
# USB-gadget serial console login on the OTG port
55+
mkdir -p "${SDCARD}/etc/systemd/system/getty.target.wants"
56+
ln -sf /lib/systemd/system/serial-getty@.service \
57+
"${SDCARD}/etc/systemd/system/getty.target.wants/serial-getty@ttyGS0.service"
58+
59+
# Gamepad-to-keyboard remap (unit file shipped via bsp-cli)
60+
mkdir -p "${SDCARD}/etc/systemd/system/multi-user.target.wants"
61+
ln -sf /etc/systemd/system/rgds-pad2key.service \
62+
"${SDCARD}/etc/systemd/system/multi-user.target.wants/rgds-pad2key.service"
63+
}

config/kernel/linux-rockchip64-bleedingedge.config

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1146,6 +1146,7 @@ CONFIG_KEYBOARD_PINEPHONE=m
11461146
CONFIG_KEYBOARD_IQS62X=m
11471147
CONFIG_KEYBOARD_CYPRESS_SF=m
11481148
CONFIG_INPUT_JOYSTICK=y
1149+
CONFIG_JOYSTICK_ADC=m
11491150
CONFIG_JOYSTICK_IFORCE=m
11501151
CONFIG_JOYSTICK_IFORCE_USB=m
11511152
CONFIG_JOYSTICK_XPAD=m
@@ -2015,6 +2016,7 @@ CONFIG_DRM_PANEL_ILITEK_ILI9341=m
20152016
CONFIG_DRM_PANEL_ILITEK_ILI9881C=m
20162017
CONFIG_DRM_PANEL_INNOLUX_EJ030NA=m
20172018
CONFIG_DRM_PANEL_INNOLUX_P079ZCA=m
2019+
CONFIG_DRM_PANEL_JADARD_JD9365DA_H3=m
20182020
CONFIG_DRM_PANEL_JDI_LT070ME05000=m
20192021
CONFIG_DRM_PANEL_JDI_R63452=m
20202022
CONFIG_DRM_PANEL_KHADAS_TS050=m
@@ -2177,6 +2179,7 @@ CONFIG_SND_SOC_AK4642=m
21772179
CONFIG_SND_SOC_AK5386=m
21782180
CONFIG_SND_SOC_AK5558=m
21792181
CONFIG_SND_SOC_ALC5623=m
2182+
CONFIG_SND_SOC_AW87391=m
21802183
CONFIG_SND_SOC_BD28623=m
21812184
CONFIG_SND_SOC_CS35L36=m
21822185
CONFIG_SND_SOC_CS35L41_SPI=m
@@ -3024,6 +3027,7 @@ CONFIG_SENSORS_HMC5843_SPI=m
30243027
CONFIG_SENSORS_RM3100_I2C=m
30253028
CONFIG_SENSORS_RM3100_SPI=m
30263029
CONFIG_YAMAHA_YAS530=m
3030+
CONFIG_IIO_MUX=m
30273031
CONFIG_HID_SENSOR_INCLINOMETER_3D=m
30283032
CONFIG_HID_SENSOR_DEVICE_ROTATION=m
30293033
CONFIG_IIO_HRTIMER_TRIGGER=m

config/kernel/linux-rockchip64-edge.config

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1170,6 +1170,7 @@ CONFIG_KEYBOARD_PINEPHONE=m
11701170
CONFIG_KEYBOARD_IQS62X=m
11711171
CONFIG_KEYBOARD_CYPRESS_SF=m
11721172
CONFIG_INPUT_JOYSTICK=y
1173+
CONFIG_JOYSTICK_ADC=m
11731174
CONFIG_JOYSTICK_IFORCE=m
11741175
CONFIG_JOYSTICK_IFORCE_USB=m
11751176
CONFIG_JOYSTICK_XPAD=m
@@ -2039,6 +2040,7 @@ CONFIG_DRM_PANEL_ILITEK_ILI9341=m
20392040
CONFIG_DRM_PANEL_ILITEK_ILI9881C=m
20402041
CONFIG_DRM_PANEL_INNOLUX_EJ030NA=m
20412042
CONFIG_DRM_PANEL_INNOLUX_P079ZCA=m
2043+
CONFIG_DRM_PANEL_JADARD_JD9365DA_H3=m
20422044
CONFIG_DRM_PANEL_JDI_LT070ME05000=m
20432045
CONFIG_DRM_PANEL_JDI_R63452=m
20442046
CONFIG_DRM_PANEL_KHADAS_TS050=m
@@ -2201,6 +2203,7 @@ CONFIG_SND_SOC_AK4642=m
22012203
CONFIG_SND_SOC_AK5386=m
22022204
CONFIG_SND_SOC_AK5558=m
22032205
CONFIG_SND_SOC_ALC5623=m
2206+
CONFIG_SND_SOC_AW87391=m
22042207
CONFIG_SND_SOC_BD28623=m
22052208
CONFIG_SND_SOC_CS35L36=m
22062209
CONFIG_SND_SOC_CS35L41_SPI=m
@@ -3048,6 +3051,7 @@ CONFIG_SENSORS_HMC5843_SPI=m
30483051
CONFIG_SENSORS_RM3100_I2C=m
30493052
CONFIG_SENSORS_RM3100_SPI=m
30503053
CONFIG_YAMAHA_YAS530=m
3054+
CONFIG_IIO_MUX=m
30513055
CONFIG_HID_SENSOR_INCLINOMETER_3D=m
30523056
CONFIG_HID_SENSOR_DEVICE_ROTATION=m
30533057
CONFIG_IIO_HRTIMER_TRIGGER=m
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
polkit.addRule(function(action, subject) {
2+
if (action.id == "org.freedesktop.systemd1.manage-units" &&
3+
action.lookup("unit") == "rgds-pad2key.service" &&
4+
subject.local && subject.active) {
5+
return polkit.Result.YES;
6+
}
7+
});
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
Anbernic RG DS - controls
2+
=========================
3+
4+
Gamepad -> keyboard (pad2key) for desktop navigation:
5+
D-pad arrow keys
6+
Select Space
7+
Start Super / Meta
8+
A (South) Enter
9+
B (East) Esc
10+
Y (West) Home
11+
X (North) Ctrl+F4 (close window)
12+
HOME (Mode) Alt+Tab (switch window)
13+
14+
Analog sticks are NOT remapped - they always work as a gamepad.
15+
16+
Playing games?
17+
The injected keys (Esc, Ctrl+F4, Alt+Tab...) interfere with games.
18+
Turn the remap OFF before gaming, ON again for the desktop:
19+
20+
OFF : systemctl stop rgds-pad2key
21+
ON : systemctl start rgds-pad2key
22+
23+
Or use "Toggle Pad-as-Keyboard" in the application menu (no password).
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
[Unit]
2+
Description=RG DS gamepad-to-keyboard remap
3+
[Service]
4+
ExecStart=/usr/bin/rgds-pad2key
5+
Restart=always
6+
RestartSec=2
7+
[Install]
8+
WantedBy=multi-user.target
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
[Desktop Entry]
2+
Type=Application
3+
Name=Anbernic RG DS dual-screen layout
4+
Comment=Stack the two DSI panels and map each touchscreen (X11 only)
5+
Exec=/usr/bin/rgds-screen
6+
NoDisplay=true
7+
X-GNOME-Autostart-enabled=true
Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
#!/usr/bin/env python3
2+
# RG DS: gamepad/HOME buttons -> keyboard (evdev/uinput, X11/Wayland-safe).
3+
# Reads every input device that emits a mapped BTN_* code (gpio gamepad keys AND
4+
# the separate adc HOME key) and injects keyboard keys. Analog sticks untouched.
5+
import time, select, evdev
6+
from evdev import ecodes as e, UInput
7+
MAP = {
8+
e.BTN_DPAD_UP: e.KEY_UP, e.BTN_DPAD_DOWN: e.KEY_DOWN,
9+
e.BTN_DPAD_LEFT: e.KEY_LEFT, e.BTN_DPAD_RIGHT: e.KEY_RIGHT,
10+
e.BTN_SELECT: e.KEY_SPACE,
11+
e.BTN_START: e.KEY_LEFTMETA,
12+
e.BTN_SOUTH: e.KEY_ENTER,
13+
e.BTN_EAST: e.KEY_ESC,
14+
e.BTN_WEST: e.KEY_HOME,
15+
}
16+
# Chords: on a single press, tap the whole combo (modifiers down first, up last).
17+
COMBO = {
18+
e.BTN_MODE: (e.KEY_LEFTALT, e.KEY_TAB), # HOME -> Alt+Tab
19+
e.BTN_NORTH: (e.KEY_LEFTCTRL, e.KEY_F4), # X -> Ctrl+F4
20+
}
21+
ALL = set(MAP) | set(COMBO)
22+
def sources():
23+
out = {}
24+
for p in evdev.list_devices():
25+
try: d = evdev.InputDevice(p)
26+
except Exception: continue
27+
if d.name == "rgds-pad2key": continue
28+
if any(k in d.capabilities().get(e.EV_KEY, []) for k in ALL):
29+
out[d.fd] = d
30+
return out
31+
devs = {}
32+
while not devs:
33+
devs = sources()
34+
if not devs: time.sleep(2)
35+
_keys = set(MAP.values())
36+
for _seq in COMBO.values(): _keys.update(_seq)
37+
ui = UInput({e.EV_KEY: sorted(_keys)}, name="rgds-pad2key")
38+
while True:
39+
if not devs: # all inputs vanished: re-scan, don't spin
40+
devs = sources()
41+
if not devs:
42+
time.sleep(2)
43+
continue
44+
r, _, _ = select.select(devs, [], [])
45+
for fd in r:
46+
try: events = list(devs[fd].read())
47+
except OSError: # device removed: drop its stale fd
48+
try: devs[fd].close()
49+
except Exception: pass
50+
del devs[fd]
51+
continue
52+
for ev in events:
53+
if ev.type != e.EV_KEY: continue
54+
if ev.code in COMBO:
55+
if ev.value == 1: # press: tap the chord once
56+
seq = COMBO[ev.code]
57+
for k in seq: ui.write(e.EV_KEY, k, 1)
58+
for k in reversed(seq): ui.write(e.EV_KEY, k, 0)
59+
ui.syn()
60+
elif ev.code in MAP:
61+
ui.write(e.EV_KEY, MAP[ev.code], ev.value); ui.syn()
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
#!/bin/bash
2+
if systemctl is-active --quiet rgds-pad2key; then
3+
systemctl stop rgds-pad2key && m="Pad-as-keyboard OFF — raw gamepad (for games)"
4+
else
5+
systemctl start rgds-pad2key && m="Pad-as-keyboard ON — D-pad = keyboard"
6+
fi
7+
command -v notify-send >/dev/null 2>&1 && notify-send -t 1500 -i input-gaming "RG DS" "$m"
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
#!/bin/bash
2+
# Anbernic RG DS: DS-style dual-screen layout for X11.
3+
# Stacks DSI-2 (top, primary) over DSI-1 (bottom) and maps each gt911
4+
# touchscreen (i2c controllers fe5c0000 / fe5e0000) to its own panel.
5+
# X11 only: bail out under Wayland / no DISPLAY so xrandr/xinput never error.
6+
[ "${XDG_SESSION_TYPE:-}" = "x11" ] && [ -n "${DISPLAY:-}" ] || exit 0
7+
sleep 2
8+
xrandr --output DSI-1 --pos 0x480
9+
xrandr --output DSI-2 --primary --pos 0x0
10+
DISP_A=DSI-2; DISP_B=DSI-1
11+
ev_for(){ readlink -f /dev/input/by-path/platform-$1.i2c*-event 2>/dev/null; }
12+
id_for(){ local w="$1" id n; for id in $(xinput list --id-only); do
13+
n=$(xinput list-props "$id" 2>/dev/null | grep -oP 'Device Node[^"]*"\K[^"]+')
14+
[ "$n" = "$w" ] && { echo "$id"; return; }; done; }
15+
A=$(id_for "$(ev_for fe5c0000)"); B=$(id_for "$(ev_for fe5e0000)")
16+
[ -n "$A" ] && xinput map-to-output "$A" "$DISP_A"
17+
[ -n "$B" ] && xinput map-to-output "$B" "$DISP_B"

0 commit comments

Comments
 (0)