SM8550: add initial support for AYANEO Pocket S

Add device support for the AYANEO Pocket S (Snapdragon SM8550):

- Import device tree (based on upstream sm8550-ayaneo-ps.dts)
- Adjust firmware paths for Pocket S layout
- Enable CONFIG_DRM_PANEL_AYANEO_WT0600_2K
- Add DRM panel patch (WT0600 2K)
- Register device in config.xml
- Add inputplumber device profile
- Add hardware quirks (GPU, controller, LEDs, configs)
- Add sway quirk to force internal DSI panel as primary output

Hardware status on real device:
- Display: working
- Audio: working
- WiFi: working
- Fans: operational (may require further tuning)
- Controls: functional but default mappings need refinement

The device boots successfully into a usable Wayland session.

Signed-off-by: Fabrice Di Meglio <fdimeglio@gmail.com>
This commit is contained in:
Fabrice Di Meglio
2026-02-28 15:10:27 -08:00
parent 9f75d70686
commit ac793414d0
13 changed files with 2350 additions and 23 deletions

View File

@@ -88,6 +88,7 @@
<file short="pocketdmg" full="AYANEO Pocket DMG">qcs8550-ayaneo-pocketdmg</file>
<file short="pocketevo" full="AYANEO Pocket EVO">qcs8550-ayaneo-pocketevo</file>
<file short="pocketds" full="AYANEO Pocket DS">qcs8550-ayaneo-pocketds</file>
<file short="pockets" full="AYANEO Pocket S">qcs8550-ayaneo-pockets</file>
<file short="rp6" full="Retroid Pocket 6">qcs8550-retroidpocket-rp6</file>
</SM8550>
<SM8650 mkimage_options="grub,dtb,abl" dtb_prefix="qcom">

View File

@@ -11,28 +11,32 @@ name: AYANEO Japanese Layout
# Only use this profile if *any* of the given matches matches. If this list is
# empty, then the source devices will *always* be checked.
# /sys/class/dmi/id/product_name
#matches:
# - udev:
# sys_path: /sys/firmware/devicetree/base
# attributes:
# - name: model
# value: AYANEO Pocket ACE
# - udev:
# sys_path: /sys/firmware/devicetree/base
# attributes:
# - name: model
# value: AYANEO Pocket DMG
# - udev:
# sys_path: /sys/firmware/devicetree/base
# attributes:
# - name: model
# value: AYANEO Pocket EVO
# - udev:
# sys_path: /sys/firmware/devicetree/base
# attributes:
# - name: model
# value: AYANEO Pocket DS
matches: []
matches:
- udev:
sys_path: /sys/firmware/devicetree/base
attributes:
- name: model
value: AYANEO Pocket S 2K
- udev:
sys_path: /sys/firmware/devicetree/base
attributes:
- name: model
value: AYANEO Pocket ACE
- udev:
sys_path: /sys/firmware/devicetree/base
attributes:
- name: model
value: AYANEO Pocket DMG
- udev:
sys_path: /sys/firmware/devicetree/base
attributes:
- name: model
value: AYANEO Pocket EVO
- udev:
sys_path: /sys/firmware/devicetree/base
attributes:
- name: model
value: AYANEO Pocket DS
# Only allow a single source device per composite device of this type.
single_source: false

File diff suppressed because it is too large Load Diff

View File

@@ -4443,6 +4443,7 @@ CONFIG_DRM_PANEL_LVDS=m
# CONFIG_DRM_PANEL_RAYDIUM_RM69380 is not set
# CONFIG_DRM_PANEL_RENESAS_R61307 is not set
# CONFIG_DRM_PANEL_RENESAS_R69328 is not set
CONFIG_DRM_PANEL_AYANEO_WT0600_2K=y
CONFIG_DRM_PANEL_RETROID_POCKET_6=y
# CONFIG_DRM_PANEL_RONBO_RB070D30 is not set
# CONFIG_DRM_PANEL_SAMSUNG_AMS581VF01 is not set

View File

@@ -0,0 +1,391 @@
From 16568c4bf8f724594b5ae0c7e32f64f095a85d8e Mon Sep 17 00:00:00 2001
From: Philippe Simons <simons.philippe@gmail.com>
Date: Tue, 2 Sep 2025 15:20:37 +0200
Subject: [PATCH] gpu: drm: panel: add wt0630 panel
thanks KancyJoe <kancy2333@outlook.com>
---
drivers/gpu/drm/panel/Kconfig | 12 +
drivers/gpu/drm/panel/Makefile | 1 +
drivers/gpu/drm/panel/panel-wt0600-2k.c | 336 ++++++++++++++++++++++++
3 files changed, 349 insertions(+)
create mode 100644 drivers/gpu/drm/panel/panel-wt0600-2k.c
diff --git a/drivers/gpu/drm/panel/Kconfig b/drivers/gpu/drm/panel/Kconfig
index 09b9f7ff9340..1bfb393afc57 100644
--- a/drivers/gpu/drm/panel/Kconfig
+++ b/drivers/gpu/drm/panel/Kconfig
@@ -1123,6 +1123,18 @@ config DRM_PANEL_WIDECHIPS_WS2401
480x800 display controller used in panels such as Samsung LMS380KF01.
This display is used in the Samsung Galaxy Ace 2 GT-I8160 (Codina).
+config DRM_PANEL_AYANEO_WT0600_2K
+ tristate "Ayaneo WT0600/WT0630 2K dual-DSI video mode panels"
+ depends on OF
+ depends on DRM_MIPI_DSI
+ depends on BACKLIGHT_CLASS_DEVICE
+ help
+ Say Y here if you want to enable support for Ayaneo WT0600 and WT0630
+ 1440x2560 60Hz dual-DSI video mode display panels. These panels are
+ used in Ayaneo handheld gaming devices.
+
+ To compile this driver as a module, choose M here.
+
config DRM_PANEL_XINPENG_XPP055C272
tristate "Xinpeng XPP055C272 panel driver"
depends on OF
diff --git a/drivers/gpu/drm/panel/Makefile b/drivers/gpu/drm/panel/Makefile
index 957555b49996..45dddcc85b65 100644
--- a/drivers/gpu/drm/panel/Makefile
+++ b/drivers/gpu/drm/panel/Makefile
@@ -113,4 +113,5 @@ obj-$(CONFIG_DRM_PANEL_VISIONOX_RM692E5) += panel-visionox-rm692e5.o
obj-$(CONFIG_DRM_PANEL_VISIONOX_VTDR6130) += panel-visionox-vtdr6130.o
obj-$(CONFIG_DRM_PANEL_VISIONOX_R66451) += panel-visionox-r66451.o
obj-$(CONFIG_DRM_PANEL_WIDECHIPS_WS2401) += panel-widechips-ws2401.o
+obj-$(CONFIG_DRM_PANEL_AYANEO_WT0600_2K) += panel-wt0600-2k.o
obj-$(CONFIG_DRM_PANEL_XINPENG_XPP055C272) += panel-xinpeng-xpp055c272.o
diff --git a/drivers/gpu/drm/panel/panel-wt0600-2k.c b/drivers/gpu/drm/panel/panel-wt0600-2k.c
new file mode 100644
index 000000000000..08d9e32f31c0
--- /dev/null
+++ b/drivers/gpu/drm/panel/panel-wt0600-2k.c
@@ -0,0 +1,336 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * DRM driver for wt0600/wt0630 2K dual-DSI video mode panels
+ *
+ * Copyright (c) 2025, Kancy Joe <kancy2333@outlook.com>
+ */
+
+#include <linux/backlight.h>
+#include <linux/delay.h>
+#include <linux/gpio/consumer.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/of_graph.h>
+#include <linux/regulator/consumer.h>
+
+#include <video/mipi_display.h>
+
+#include <drm/drm_connector.h>
+#include <drm/drm_mipi_dsi.h>
+#include <drm/drm_modes.h>
+#include <drm/drm_panel.h>
+#include <drm/drm_probe_helper.h>
+
+struct wt0600_panel {
+ struct drm_panel panel;
+ struct mipi_dsi_device *dsi[2];
+ const struct panel_desc *desc;
+
+ struct gpio_desc *reset_gpio;
+ struct regulator_bulk_data *supplies;
+ enum drm_panel_orientation orientation;
+};
+
+static const struct regulator_bulk_data wt0600_supplies[] = {
+ { .supply = "vddio" },
+ { .supply = "vci" },
+ { .supply = "vdd" },
+ { .supply = "avdd" },
+};
+
+struct panel_desc {
+ const struct drm_display_mode *mode;
+ unsigned int lanes;
+ unsigned long mode_flags;
+ enum mipi_dsi_pixel_format format;
+ uint16_t height_mm;
+ uint16_t width_mm;
+ const struct mipi_dsi_device_info dsi_info;
+};
+
+static const struct drm_display_mode wt0600_mode = {
+ /* Dual dsi */
+ .clock = 2 * (720 + 100 + 8 + 40) * (2560 + 15 + 2 + 8) * 60 / 1000,
+ .hdisplay = 2 * 720,
+ .hsync_start = 2 * (720 + 100),
+ .hsync_end = 2 * (720 + 100 + 8),
+ .htotal = 2 * (720 + 100 + 8 + 40),
+ .vdisplay = 2560,
+ .vsync_start = 2560 + 15,
+ .vsync_end = 2560 + 15 + 2,
+ .vtotal = 2560 + 15 + 2 + 8,
+ .type = DRM_MODE_TYPE_DRIVER | DRM_MODE_TYPE_PREFERRED,
+};
+
+static struct panel_desc wt0600_desc = {
+ .lanes = 4,
+ .width_mm = 74,
+ .height_mm = 131,
+ .mode = &wt0600_mode,
+ .mode_flags = MIPI_DSI_MODE_VIDEO | MIPI_DSI_MODE_VIDEO_BURST |
+ MIPI_DSI_CLOCK_NON_CONTINUOUS | MIPI_DSI_MODE_LPM,
+ .format = MIPI_DSI_FMT_RGB888,
+ .dsi_info = {
+ .type = "wt0600-2k",
+ .channel = 0,
+ .node = NULL,
+ },
+};
+
+static struct panel_desc wt0630_desc = {
+ .lanes = 4,
+ .width_mm = 78,
+ .height_mm = 140,
+ .mode = &wt0600_mode, /* wt0600 only has different screen size */
+ .mode_flags = MIPI_DSI_MODE_VIDEO | MIPI_DSI_MODE_VIDEO_BURST |
+ MIPI_DSI_CLOCK_NON_CONTINUOUS | MIPI_DSI_MODE_LPM,
+ .format = MIPI_DSI_FMT_RGB888,
+ .dsi_info = {
+ .type = "wt0630-2k",
+ .channel = 0,
+ .node = NULL,
+ },
+};
+
+static inline struct wt0600_panel *to_wt0600_panel(struct drm_panel *panel)
+{
+ return container_of(panel, struct wt0600_panel, panel);
+}
+
+static void wt0600_reset(struct wt0600_panel *ctx)
+{
+ gpiod_set_value_cansleep(ctx->reset_gpio, 1);
+ usleep_range(10000, 11000);
+ gpiod_set_value_cansleep(ctx->reset_gpio, 0);
+ usleep_range(10000, 11000);
+ gpiod_set_value_cansleep(ctx->reset_gpio, 0);
+ msleep(55);
+}
+
+static int wt0600_on(struct wt0600_panel *ctx)
+{
+ struct mipi_dsi_multi_context dsi_ctx = { .dsi = ctx->dsi[0] };
+ struct mipi_dsi_multi_context dsi_ctx1 = { .dsi = ctx->dsi[1] };
+
+ mipi_dsi_dcs_set_display_on_multi(&dsi_ctx);
+ mipi_dsi_dcs_set_display_on_multi(&dsi_ctx1);
+ mipi_dsi_msleep(&dsi_ctx, 150);
+
+ mipi_dsi_dcs_exit_sleep_mode_multi(&dsi_ctx);
+ mipi_dsi_dcs_exit_sleep_mode_multi(&dsi_ctx1);
+ mipi_dsi_msleep(&dsi_ctx, 50);
+
+ return dsi_ctx.accum_err;
+}
+
+static int wt0600_disable(struct drm_panel *panel)
+{
+ struct wt0600_panel *ctx = to_wt0600_panel(panel);
+ struct mipi_dsi_multi_context dsi_ctx = { .dsi = ctx->dsi[0] };
+ struct mipi_dsi_multi_context dsi_ctx1 = { .dsi = ctx->dsi[1] };
+
+ mipi_dsi_dcs_set_display_off_multi(&dsi_ctx);
+ mipi_dsi_dcs_set_display_off_multi(&dsi_ctx1);
+ mipi_dsi_msleep(&dsi_ctx, 50);
+
+ mipi_dsi_dcs_enter_sleep_mode_multi(&dsi_ctx);
+ mipi_dsi_dcs_enter_sleep_mode_multi(&dsi_ctx1);
+ mipi_dsi_msleep(&dsi_ctx, 120);
+
+ return dsi_ctx.accum_err;
+}
+
+static int wt0600_prepare(struct drm_panel *panel)
+{
+ struct wt0600_panel *ctx = to_wt0600_panel(panel);
+ int ret;
+
+ ret = regulator_bulk_enable(ARRAY_SIZE(wt0600_supplies), ctx->supplies);
+ if (ret < 0)
+ return ret;
+
+ wt0600_reset(ctx);
+
+ ret = wt0600_on(ctx);
+ if (ret < 0) {
+ dev_err(panel->dev, "Failed to initialize panel: %d\n", ret);
+ gpiod_set_value_cansleep(ctx->reset_gpio, 1);
+ regulator_bulk_disable(ARRAY_SIZE(wt0600_supplies),
+ ctx->supplies);
+ return ret;
+ }
+
+ return 0;
+}
+
+static int wt0600_unprepare(struct drm_panel *panel)
+{
+ struct wt0600_panel *ctx = to_wt0600_panel(panel);
+
+ gpiod_set_value_cansleep(ctx->reset_gpio, 1);
+
+ regulator_bulk_disable(ARRAY_SIZE(wt0600_supplies), ctx->supplies);
+
+ return 0;
+}
+
+static int wt0600_get_modes(struct drm_panel *panel,
+ struct drm_connector *connector)
+{
+ struct drm_display_mode *mode;
+ struct wt0600_panel *ctx = to_wt0600_panel(panel);
+
+ mode = drm_mode_duplicate(connector->dev, ctx->desc->mode);
+ if (!mode)
+ return -ENOMEM;
+
+ /* Update panel size */
+ mode->width_mm = ctx->desc->width_mm;
+ mode->height_mm = ctx->desc->height_mm;
+
+ drm_mode_set_name(mode);
+ connector->display_info.width_mm = mode->width_mm;
+ connector->display_info.height_mm = mode->height_mm;
+ drm_mode_probed_add(connector, mode);
+
+ return 1;
+}
+
+static enum drm_panel_orientation
+wt0600_get_orientation(struct drm_panel *panel)
+{
+ struct wt0600_panel *ctx = to_wt0600_panel(panel);
+
+ return ctx->orientation;
+}
+
+static const struct drm_panel_funcs wt0600_panel_funcs = {
+ .disable = wt0600_disable,
+ .prepare = wt0600_prepare,
+ .unprepare = wt0600_unprepare,
+ .get_modes = wt0600_get_modes,
+ .get_orientation = wt0600_get_orientation,
+};
+
+static int wt0600_probe(struct mipi_dsi_device *dsi)
+{
+ struct device *dev = &dsi->dev;
+ struct wt0600_panel *ctx;
+ struct device_node *dsi1_node;
+ struct mipi_dsi_host *dsi1_host;
+ int ret, i;
+
+ ctx = devm_kzalloc(dev, sizeof(*ctx), GFP_KERNEL);
+ if (!ctx)
+ return -ENOMEM;
+
+ ctx->desc = of_device_get_match_data(dev);
+ if (!ctx->desc)
+ return dev_err_probe(dev, -ENODEV,
+ "Failed to get panel description\n");
+
+ ret = devm_regulator_bulk_get_const(&dsi->dev,
+ ARRAY_SIZE(wt0600_supplies),
+ wt0600_supplies, &ctx->supplies);
+ if (ret < 0)
+ return ret;
+
+ ctx->reset_gpio = devm_gpiod_get(dev, "reset", GPIOD_OUT_HIGH);
+ if (IS_ERR(ctx->reset_gpio))
+ return dev_err_probe(dev, PTR_ERR(ctx->reset_gpio),
+ "Failed to get reset gpio\n");
+
+ /* Get second DSI host */
+ dsi1_node = of_graph_get_remote_node(dsi->dev.of_node, 1, -1);
+ if (!dsi1_node)
+ return dev_err_probe(
+ dev, -ENODEV,
+ "Failed to get remote node for second DSI\n");
+
+ dsi1_host = of_find_mipi_dsi_host_by_node(dsi1_node);
+ of_node_put(dsi1_node);
+ if (!dsi1_host)
+ return dev_err_probe(dev, -EPROBE_DEFER,
+ "Failed to find second DSI host\n");
+
+ /* Register the second DSI device */
+ ctx->dsi[1] = devm_mipi_dsi_device_register_full(dev, dsi1_host,
+ &ctx->desc->dsi_info);
+ if (IS_ERR(ctx->dsi[1]))
+ return dev_err_probe(dev, PTR_ERR(ctx->dsi[1]),
+ "Failed to register second DSI device\n");
+
+ /* Get panel orientation */
+ ret = of_drm_get_panel_orientation(dev->of_node, &ctx->orientation);
+ if (ret < 0 && ret != -ENODEV)
+ return dev_err_probe(dev, ret,
+ "Failed to get panel orientation\n");
+
+ ctx->dsi[0] = dsi;
+ mipi_dsi_set_drvdata(dsi, ctx);
+
+ drm_panel_init(&ctx->panel, dev, &wt0600_panel_funcs,
+ DRM_MODE_CONNECTOR_DSI);
+ ctx->panel.prepare_prev_first = true;
+
+ ret = drm_panel_of_backlight(&ctx->panel);
+ if (ret)
+ return dev_err_probe(dev, ret, "Failed to get backlight\n");
+
+ drm_panel_add(&ctx->panel);
+
+ /* Configure and attach both DSI devices */
+ for (i = 0; i < ARRAY_SIZE(ctx->dsi); i++) {
+ ctx->dsi[i]->lanes = ctx->desc->lanes;
+ ctx->dsi[i]->format = ctx->desc->format;
+ ctx->dsi[i]->mode_flags = ctx->desc->mode_flags;
+
+ ret = mipi_dsi_attach(ctx->dsi[i]);
+ if (ret < 0) {
+ drm_panel_remove(&ctx->panel);
+ return dev_err_probe(dev, ret,
+ "Failed to attach DSI device %d\n",
+ i);
+ }
+ }
+
+ return 0;
+}
+
+static void wt0600_remove(struct mipi_dsi_device *dsi)
+{
+ struct wt0600_panel *ctx = mipi_dsi_get_drvdata(dsi);
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(ctx->dsi); i++)
+ mipi_dsi_detach(ctx->dsi[i]);
+
+ drm_panel_remove(&ctx->panel);
+}
+
+static const struct of_device_id wt0600_of_match[] = {
+ {
+ .compatible = "ayaneo,wt0600-2k",
+ .data = &wt0600_desc,
+ },
+ {
+ .compatible = "ayaneo,wt0630-2k",
+ .data = &wt0630_desc,
+ },
+ {}
+};
+MODULE_DEVICE_TABLE(of, wt0600_of_match);
+
+static struct mipi_dsi_driver wt0600_driver = {
+ .probe = wt0600_probe,
+ .remove = wt0600_remove,
+ .driver = {
+ .name = "panel-wt0600-2k",
+ .of_match_table = wt0600_of_match,
+ },
+};
+module_mipi_dsi_driver(wt0600_driver);
+
+MODULE_AUTHOR("Kancy Joe <kancy2333@outlook.com>");
+MODULE_DESCRIPTION("DRM driver for wt0600/wt0630 2k video mode dsi panel");
+MODULE_LICENSE("GPL");
--
2.51.0

View File

@@ -0,0 +1,11 @@
diff --git a/arch/arm64/boot/dts/qcom/Makefile b/arch/arm64/boot/dts/qcom/Makefile
--- a/arch/arm64/boot/dts/qcom/Makefile
+++ b/arch/arm64/boot/dts/qcom/Makefile
@@ -139,6 +139,7 @@ dtb-$(CONFIG_ARCH_QCOM) += qcs8550-ayn-odin2.dtb
dtb-$(CONFIG_ARCH_QCOM) += qcs8550-ayn-odin2mini.dtb
dtb-$(CONFIG_ARCH_QCOM) += qcs8550-ayn-odin2portal.dtb
dtb-$(CONFIG_ARCH_QCOM) += qcs8550-ayn-thor.dtb
+dtb-$(CONFIG_ARCH_QCOM) += qcs8550-ayaneo-pockets.dtb
dtb-$(CONFIG_ARCH_QCOM) += qcs9100-ride.dtb
dtb-$(CONFIG_ARCH_QCOM) += qcs9100-ride-r3.dtb
dtb-$(CONFIG_ARCH_QCOM) += qdu1000-idp.dtb

View File

@@ -0,0 +1,7 @@
#!/bin/sh
# SPDX-License-Identifier: Apache-2.0
# Copyright (C) 2024-present ROCKNIX (https://github.com/ROCKNIX)
cat <<EOF >/storage/.config/profile.d/400-device_config
DEVICE_GPU_OVERCLOCK="true"
EOF

View File

@@ -0,0 +1,16 @@
#!/bin/sh
# SPDX-License-Identifier: GPL-2.0-or-later
# Copyright (C) 2025 ROCKNIX
# Serial device
SERIAL_DEVICE="/dev/ttyHS0"
# Open serial device
stty -F $SERIAL_DEVICE 115200 -clocal -opost -isig -icanon -echo
# Send frame to switch gamepad to fake xbox 360 controller
printf "\xe7\x55\x05\x01\x00\x00\x00\x00\x00\x5b\xed" >$SERIAL_DEVICE
sleep 0.1
printf "\x35\x35\x30\x35\x30\x31\x30\x30\x30\x30\x30\x30\x30\x30\x30\x30" >$SERIAL_DEVICE
sleep 0.1

View File

@@ -0,0 +1,7 @@
#!/bin/sh
# SPDX-License-Identifier: GPL-2.0
# Copyright (C) 2024-present ROCKNIX (https://github.com/ROCKNIX)
#Disable retroarch microphone and set default audio driver to pulse
sed -i '/^microphone_enable =/c\microphone_enable = "false"' /storage/.config/retroarch/retroarch.cfg
sed -i '/^audio_driver =/c\audio_driver = "pulse"' /storage/.config/retroarch/retroarch.cfg

View File

@@ -0,0 +1,22 @@
#!/bin/sh
# SPDX-License-Identifier: GPL-2.0-or-later
# Copyright (C) 2024-present ROCKNIX (https://github.com/ROCKNIX)
# Minimal OS variable loading for performance
. /etc/profile.d/001-functions
# Get GPU overclock state
GPU_OC_STATE=$(get_setting "enable.gpu-overclock")
if [ ! -n "${GPU_OC_STATE}" ]; then
GPU_OC_STATE="disable"
set_setting "enable.gpu-overclock" "0"
elif [ "${GPU_OC_STATE}" = 1 ]; then
GPU_OC_STATE="enable"
else
GPU_OC_STATE="disable"
set_setting "enable.gpu-overclock" "0"
fi
# Set GPU OC state
/usr/lib/autostart/quirks/platforms/SM8550/bin/gpu_overclock ${GPU_OC_STATE}

View File

@@ -0,0 +1,108 @@
#!/bin/sh
# SPDX-License-Identifier: GPL-2.0-or-later
# Copyright (C) 2024 ROCKNIX (https://github.com/ROCKNIX)
# Simple script to watch the battery capacity and
# turn the power LED orange when it reaches 30%, red at 20%, and blinking red at 10%
# Minimal OS variable loading for performance
. /etc/profile.d/001-functions
LED_PATH="/sys/class/leds"
function led_brightness() {
echo ${2} >${LED_PATH}/${1}/brightness
}
function led_rgb() {
echo ${2} ${3} ${4} >${LED_PATH}/${1}/multi_intensity
}
function bat_led_off() {
led_brightness power-led 0
led_rgb power-led 0 0 0
}
function bat_led_green() {
led_brightness power-led 255
led_rgb power-led 0 255 0
}
function bat_led_red() {
led_brightness power-led 255
led_rgb power-led 255 0 0
}
function bat_led_orange() {
led_brightness power-led 255
led_rgb power-led 255 20 0
}
function bat_led_yellow() {
led_brightness power-led 255
led_rgb power-led 255 125 0
}
PREV_BATCAP="null"
while true
do
BAT_LED_STATE=$(get_setting led.color)
if [ ! ${BAT_LED_STATE} == "battery" ]; then
break
fi
CAP=$(cat /sys/class/power_supply/battery/capacity)
STAT=$(cat /sys/class/power_supply/battery/status)
if [ ${STAT} == "Discharging" ]; then
if (( ${CAP} <= 10 ))
then
for ctr in $(seq 1 1 5)
do
bat_led_red
sleep .5
bat_led_off
sleep .5
done
continue
elif (( ${CAP} <= 20 ))
then
BATCAP="D_RED"
if [ ! ${BATCAP} = ${PREV_BATCAP} ]; then
bat_led_red
fi
elif (( ${CAP} <= 30 ))
then
BATCAP="D_ORANGE"
if [ ! ${BATCAP} = ${PREV_BATCAP} ]; then
bat_led_orange
fi
elif (( ${CAP} <= 40 ))
then
BATCAP="D_YELLOW"
if [ ! ${BATCAP} = ${PREV_BATCAP} ]; then
bat_led_yellow
fi
else
BATCAP="D_GREEN"
if [ ! ${BATCAP} = ${PREV_BATCAP} ]; then
bat_led_green
fi
fi
elif (( ${CAP} <= 94 ))
then
BATCAP="C_ORANGE"
if [ ! ${BATCAP} = ${PREV_BATCAP} ]; then
bat_led_orange
fi
elif (( ${CAP} >= 95 ))
then
BATCAP="C_GREEN"
if [ ! ${BATCAP} = ${PREV_BATCAP} ]; then
bat_led_green
fi
fi
PREV_BATCAP=${BATCAP}
sleep 15
done

View File

@@ -0,0 +1,113 @@
#!/bin/sh
# SPDX-License-Identifier: GPL-2.0
# Copyright (C) 2024 ROCKNIX (https://github.com/ROCKNIX)
# Minimal OS variable loading for performance
. /etc/profile.d/001-functions
LED_PATH="/sys/class/leds"
function led_brightness() {
echo ${2} >${LED_PATH}/${1}/brightness
}
function led_rgb() {
echo ${2} ${3} ${4} >${LED_PATH}/${1}/multi_intensity
}
function led_off() {
led_brightness power-led 0
led_rgb power-led 0 0 0
}
function led_red() {
led_brightness power-led 255
led_rgb power-led 255 0 0
}
function led_green() {
led_brightness power-led 255
led_rgb power-led 0 255 0
}
function led_blue() {
led_brightness power-led 255
led_rgb power-led 0 0 255
}
function led_white() {
led_brightness power-led 255
led_rgb power-led 255 255 255
}
function led_orange() {
led_brightness power-led 255
led_rgb power-led 255 20 0
}
function led_yellow() {
led_brightness power-led 255
led_rgb power-led 255 125 0
}
function led_purple() {
led_brightness power-led 255
led_rgb power-led 255 0 255
}
case ${1} in
red)
led_red
set_setting led.color ${1}
;;
green)
led_green
set_setting led.color ${1}
;;
blue)
led_blue
set_setting led.color ${1}
;;
white)
led_white
set_setting led.color ${1}
;;
orange)
led_orange
set_setting led.color ${1}
;;
yellow)
led_yellow
set_setting led.color ${1}
;;
purple)
led_purple
set_setting led.color ${1}
;;
off)
led_off
set_setting led.color ${1}
;;
battery)
led_off
set_setting led.color ${1}
systemctl restart batteryledstatus.service
;;
poweroff)
led_off
;;
list)
cat <<EOF
off
battery
red
green
blue
white
orange
yellow
purple
EOF
;;
esac

View File

@@ -138,6 +138,19 @@ if [ "${QUIRK_DEVICE}" = "AYN Thor" ]; then
echo "exec_always swaymsg '[app_id=\"emulationstation\"]' seat seat1 attach \"4660:22136:InputPlumber_Keyboard\"" >> $SWAY_HOME/config
fi
# AYANEO Pocket S: force primary output to the internal DSI panel.
# Some panel stacks expose extra connectors and sway can pick the wrong one.
if [ "${QUIRK_DEVICE}" = "AYANEO Pocket S" ] || [ "${QUIRK_DEVICE}" = "AYANEO Pocket S 2K" ]; then
if [ -n "${dsi}" ]; then
con="${dsi}"
echo "output ${con} transform ${angle}" >> $SWAY_HOME/config
echo "output ${con} bg #000000 solid_color" >> $SWAY_HOME/config
echo "output ${con} allow_tearing yes" >> $SWAY_HOME/config
echo "output ${con} max_render_time off" >> $SWAY_HOME/config
echo "WLR_CON=${con}" >> ${env_file}
fi
fi
# Anbernic RG DS touchscreen setup
if [ "${QUIRK_DEVICE}" = "Anbernic RG DS" ]; then
echo 'for_window [title=".*(Secondary|\[w2\]|Sub|Bottom|Screen 2|GamePad).*"] output '"${second_con}"' power on' >> $SWAY_HOME/config
@@ -146,4 +159,4 @@ if [ "${QUIRK_DEVICE}" = "Anbernic RG DS" ]; then
echo "exec_always swaymsg '[app_id=\"emulationstation\"]' focus output ${con}, output ${second_con} power off" >> $SWAY_HOME/config
echo "exec_always swaymsg '[app_id=\"emulationstation\"]' seat seat1 attach \"1046:911:Goodix_Capacitive_TouchScreen\"" >> $SWAY_HOME/config
echo "exec_always swaymsg '[app_id=\"emulationstation\"]' seat seat1 fallback yes" >> $SWAY_HOME/config
fi
fi