Compare commits

...

5 Commits

Author SHA1 Message Date
mia26MAjFm
935dc3e322 build-kernel: run --distro fedora after --distro all so .rpm ships (#23)
* build-kernel: release .rpm alongside .deb + .pkg.tar.zst

Now that ps5-linux-image's --distro all also produces an .rpm (paired
image PR), pick it up in the artifact upload, checksum list and
release files: block. Also add rpm as an explicit format choice so
someone can dispatch an rpm-only kernel build.

The sha256sum pipeline gets a 2>/dev/null so it doesn't complain
when an older ps5-linux-image checkout is used that only writes
deb + pkg.tar.zst.

* test: run on ubuntu-latest, point at paired ps5-linux-image branch, skip release on fork

* build-kernel: run --distro fedora after --distro all so .rpm ships

---------

Co-authored-by: Your Name <you@example.com>
2026-07-04 18:27:59 +02:00
mia26MAjFm
9ee33721e4 build-kernel: release .rpm alongside .deb + .pkg.tar.zst (#22)
Now that ps5-linux-image's --distro all also produces an .rpm (paired
image PR), pick it up in the artifact upload, checksum list and
release files: block. Also add rpm as an explicit format choice so
someone can dispatch an rpm-only kernel build.

The sha256sum pipeline gets a 2>/dev/null so it doesn't complain
when an older ps5-linux-image checkout is used that only writes
deb + pkg.tar.zst.

Co-authored-by: Your Name <you@example.com>
2026-07-04 08:56:04 +02:00
Andy Nguyen
a57d783d89 config: update to 7.1.2 2026-06-30 11:26:04 +02:00
Andy Nguyen
07f9d7f847 readme: remove todo for xhci 2026-06-30 09:18:59 +02:00
rmux
6cfe53c6d3 feat: add PS5 LED driver (#21)
usage:
  # list presets
  ls /sys/class/leds/

  # set a preset
  echo 255 > /sys/class/leds/ps5:<preset>:indicator/brightness

  # turn off
  echo 0 > /sys/class/leds/ps5:off:indicator/brightness
2026-06-28 15:59:14 +02:00
4 changed files with 541 additions and 15 deletions

View File

@@ -1,6 +1,6 @@
#
# Automatically generated file; DO NOT EDIT.
# Linux/x86 7.1.1 Kernel Configuration
# Linux/x86 7.1.2 Kernel Configuration
#
CONFIG_CC_VERSION_TEXT="gcc (Ubuntu 15.2.0-16ubuntu1) 15.2.0"
CONFIG_CC_IS_GCC=y

View File

@@ -8,7 +8,7 @@ on:
description: 'Package format'
default: 'all'
type: choice
options: [deb, arch, all]
options: [deb, arch, rpm, all]
patches_ref:
description: 'Patches branch/tag/SHA (empty = default)'
default: ''
@@ -43,6 +43,15 @@ jobs:
bash image/build_image.sh --kernel-only \
--distro "$FORMAT" \
--patches-ref "$PATCHES_REF"
# build_image.sh's --distro all skips the rpm packager. Run the rpm
# branch explicitly so the release ships .rpm alongside .deb/.pkg.tar.zst.
# ccache holds the kernel objects — this second call only re-runs
# the rpm packaging step.
if [ "$FORMAT" = "all" ]; then
bash image/build_image.sh --kernel-only \
--distro fedora \
--patches-ref "$PATCHES_REF"
fi
- name: Read kernel and patches version
id: version
@@ -61,6 +70,7 @@ jobs:
path: |
image/linux-bin/*.deb
image/linux-bin/*.pkg.tar.zst
image/linux-bin/*.rpm
retention-days: 7
- name: Compute checksums
@@ -68,7 +78,7 @@ jobs:
run: |
{
echo 'sums<<SHAEOF'
sha256sum image/linux-bin/*.deb image/linux-bin/*.pkg.tar.zst | sed 's|image/linux-bin/||'
sha256sum image/linux-bin/*.deb image/linux-bin/*.pkg.tar.zst image/linux-bin/*.rpm 2>/dev/null | sed 's|image/linux-bin/||'
echo 'SHAEOF'
} >> "$GITHUB_OUTPUT"
@@ -90,4 +100,5 @@ jobs:
files: |
image/linux-bin/*.deb
image/linux-bin/*.pkg.tar.zst
image/linux-bin/*.rpm
make_latest: true

View File

@@ -24,7 +24,6 @@ sudo make install
## TODO
- amdgpu smu driver to show correct gpu frequency and temperature
- xhci driver adjustment for 0x104d:0x9108 to enable bluetooth
- hdmi converter improvments: hdr, rgb range, 120hz
## Bugs

View File

@@ -1091,7 +1091,7 @@ index 000000000000..39cc76f39e06
+
+#endif
diff --git a/drivers/bluetooth/btusb.c b/drivers/bluetooth/btusb.c
index 830fefb342c6..f13155f049c4 100644
index 830fefb342c6..380bc421583d 100644
--- a/drivers/bluetooth/btusb.c
+++ b/drivers/bluetooth/btusb.c
@@ -67,6 +67,10 @@ static struct usb_driver btusb_driver;
@@ -1112,10 +1112,10 @@ index 830fefb342c6..f13155f049c4 100644
+ /* PS5 IW620 Bluetooth device */
+ { USB_DEVICE(0x1286, 0x2059),
+ .driver_info = BTUSB_MARVELL |
+ BTUSB_IFNUM_0 |
+ BTUSB_BROKEN_LE_DEFAULT_PHY |
+ BTUSB_BROKEN_READ_LOCAL_NAME |
+ BTUSB_NO_AUTOSUSPEND },
+ BTUSB_IFNUM_0 |
+ BTUSB_BROKEN_LE_DEFAULT_PHY |
+ BTUSB_BROKEN_READ_LOCAL_NAME |
+ BTUSB_NO_AUTOSUSPEND },
+
{ } /* Terminating entry */
};
@@ -1125,10 +1125,10 @@ index 830fefb342c6..f13155f049c4 100644
{ USB_DEVICE(0x1286, 0x2046), .driver_info = BTUSB_MARVELL },
{ USB_DEVICE(0x1286, 0x204e), .driver_info = BTUSB_MARVELL },
+ { USB_DEVICE(0x1286, 0x2059), .driver_info = BTUSB_MARVELL |
+ BTUSB_IFNUM_0 |
+ BTUSB_BROKEN_LE_DEFAULT_PHY |
+ BTUSB_BROKEN_READ_LOCAL_NAME |
+ BTUSB_NO_AUTOSUSPEND },
+ BTUSB_IFNUM_0 |
+ BTUSB_BROKEN_LE_DEFAULT_PHY |
+ BTUSB_BROKEN_READ_LOCAL_NAME |
+ BTUSB_NO_AUTOSUSPEND },
/* Intel Bluetooth devices */
{ USB_DEVICE(0x8087, 0x0025), .driver_info = BTUSB_INTEL_COMBINED },
@@ -3409,11 +3409,12 @@ index b63cd0c310bc..495b2714838b 100644
diff --git a/drivers/ps5/Makefile b/drivers/ps5/Makefile
new file mode 100644
index 000000000000..36a3f5261a26
index 000000000000..ccb2740e3375
--- /dev/null
+++ b/drivers/ps5/Makefile
@@ -0,0 +1 @@
@@ -0,0 +1,2 @@
+obj-y += spcie.o tpcie.o hdmi.o mp1.o buzzer.o svm.o vmenter.o
+obj-y += led/
diff --git a/drivers/ps5/autoservo_param.h b/drivers/ps5/autoservo_param.h
new file mode 100644
index 000000000000..d2c25e461bf7
@@ -6862,6 +6863,521 @@ index 000000000000..8f094490d677
+ }
+}
+EXPORT_SYMBOL(hdmi_notification_handler);
diff --git a/drivers/ps5/led.h b/drivers/ps5/led.h
new file mode 100644
index 000000000000..a1a205147478
--- /dev/null
+++ b/drivers/ps5/led.h
@@ -0,0 +1,10 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+#ifndef _PS5_LED_H
+#define _PS5_LED_H
+
+#include <linux/types.h>
+
+int ps5_led_set_raw(u8 blue, u8 white, u8 orange);
+int ps5_led_set_preset(const char *name);
+
+#endif
diff --git a/drivers/ps5/led/Makefile b/drivers/ps5/led/Makefile
new file mode 100644
index 000000000000..38cfacb315b2
--- /dev/null
+++ b/drivers/ps5/led/Makefile
@@ -0,0 +1 @@
+obj-y += core.o presets.o
diff --git a/drivers/ps5/led/core.c b/drivers/ps5/led/core.c
new file mode 100644
index 000000000000..796cc0edc859
--- /dev/null
+++ b/drivers/ps5/led/core.c
@@ -0,0 +1,158 @@
+// SPDX-License-Identifier: GPL-2.0-only
+
+#include <linux/module.h>
+#include <linux/leds.h>
+#include <linux/mutex.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+#include <linux/ps5.h>
+#include "../led.h"
+#include "presets.h"
+
+static const u8 ps5_led_off_payload[] = {
+ 0x03, 0x00, 0x00, 0x00,
+ 0x10, 0x01, 0x02, 0x00, 0x05, 0x04, 0x00,
+ 0x11, 0x01, 0x02, 0x00, 0x05, 0x04, 0x00,
+ 0x12, 0x01, 0x02, 0x00, 0x05, 0x04, 0x00,
+};
+
+struct ps5_led_node {
+ struct led_classdev cdev;
+ const u8 *payload;
+ size_t size;
+};
+
+static DEFINE_MUTEX(ps5_led_lock);
+static const u8 *ps5_led_current;
+
+static int ps5_led_brightness_set(struct led_classdev *cdev,
+ enum led_brightness value)
+{
+ struct ps5_led_node *node =
+ container_of(cdev, struct ps5_led_node, cdev);
+ const u8 *data = (value == LED_OFF) ? ps5_led_off_payload : node->payload;
+ size_t size = (value == LED_OFF) ? sizeof(ps5_led_off_payload) : node->size;
+ int ret;
+
+ if (!spcie_is_initialized())
+ return -ENODEV;
+
+ mutex_lock(&ps5_led_lock);
+
+ if (ps5_led_current == data) {
+ mutex_unlock(&ps5_led_lock);
+ return 0;
+ }
+
+ if (value != LED_OFF)
+ icc_indicator_set_led(ps5_led_off_payload,
+ sizeof(ps5_led_off_payload));
+
+ ret = icc_indicator_set_led(data, size);
+ if (!ret)
+ ps5_led_current = data;
+
+ mutex_unlock(&ps5_led_lock);
+ return ret;
+}
+
+int ps5_led_set_raw(u8 blue, u8 white, u8 orange)
+{
+ u8 buf[25];
+
+ if (!spcie_is_initialized())
+ return -ENODEV;
+
+ if (!blue && !white && !orange)
+ return icc_indicator_set_led(ps5_led_off_payload,
+ sizeof(ps5_led_off_payload));
+
+ buf[0] = 0x03; buf[1] = 0x00; buf[2] = 0x00; buf[3] = 0x00;
+ buf[4] = 0x10; buf[5] = 0x01; buf[6] = 0x02; buf[7] = blue;
+ buf[8] = 0x05; buf[9] = 0x03; buf[10] = 0x00;
+ buf[11] = 0x11; buf[12] = 0x01; buf[13] = 0x02; buf[14] = white;
+ buf[15] = 0x05; buf[16] = 0x03; buf[17] = 0x00;
+ buf[18] = 0x12; buf[19] = 0x01; buf[20] = 0x02; buf[21] = orange;
+ buf[22] = 0x05; buf[23] = 0x03; buf[24] = 0x00;
+
+ return icc_indicator_set_led(buf, sizeof(buf));
+}
+EXPORT_SYMBOL(ps5_led_set_raw);
+
+static int ps5_led_probe(struct platform_device *pdev)
+{
+ size_t i;
+ int ret;
+
+ for (i = 0; i < ps5_num_presets; i++) {
+ struct ps5_led_node *node;
+ char *name;
+
+ node = devm_kzalloc(&pdev->dev, sizeof(*node), GFP_KERNEL);
+ if (!node)
+ return -ENOMEM;
+
+ name = devm_kasprintf(&pdev->dev, GFP_KERNEL,
+ "ps5:%s:indicator",
+ ps5_presets[i].name);
+ if (!name)
+ return -ENOMEM;
+
+ node->payload = ps5_presets[i].data;
+ node->size = ps5_presets[i].size;
+ node->cdev.name = name;
+ node->cdev.max_brightness = 255;
+ node->cdev.brightness_set_blocking = ps5_led_brightness_set;
+ node->cdev.flags = LED_CORE_SUSPENDRESUME;
+
+ ret = devm_led_classdev_register(&pdev->dev, &node->cdev);
+ if (ret)
+ return ret;
+ }
+
+ return 0;
+}
+
+static struct platform_driver ps5_led_driver = {
+ .probe = ps5_led_probe,
+ .driver = {
+ .name = "ps5-led",
+ },
+};
+
+static struct platform_device *ps5_led_pdev;
+
+static int __init ps5_led_init(void)
+{
+ int ret;
+
+ ret = platform_driver_register(&ps5_led_driver);
+ if (ret)
+ return ret;
+
+ ps5_led_pdev = platform_device_register_simple("ps5-led", -1,
+ NULL, 0);
+ if (IS_ERR(ps5_led_pdev)) {
+ ret = PTR_ERR(ps5_led_pdev);
+ platform_driver_unregister(&ps5_led_driver);
+ ps5_led_pdev = NULL;
+ return ret;
+ }
+
+ return 0;
+}
+
+static void __exit ps5_led_exit(void)
+{
+ if (ps5_led_pdev)
+ platform_device_unregister(ps5_led_pdev);
+ platform_driver_unregister(&ps5_led_driver);
+}
+
+module_init(ps5_led_init);
+module_exit(ps5_led_exit);
+
+MODULE_AUTHOR("Armandas Kvietkus <armandas.kvietkus@proton.me>");
+MODULE_DESCRIPTION("PlayStation 5 indicator LED driver");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:ps5-led");
diff --git a/drivers/ps5/led/presets.c b/drivers/ps5/led/presets.c
new file mode 100644
index 000000000000..218da5ecb31e
--- /dev/null
+++ b/drivers/ps5/led/presets.c
@@ -0,0 +1,300 @@
+// SPDX-License-Identifier: GPL-2.0-only
+
+#include <linux/module.h>
+#include <linux/string.h>
+#include <linux/ps5.h>
+#include "../led.h"
+#include "presets.h"
+
+
+static const u8 payload_off[] = {
+ 0x03, 0x00, 0x00, 0x00,
+ 0x10, 0x01, 0x02, 0x00, 0x05, 0x04, 0x00,
+ 0x11, 0x01, 0x02, 0x00, 0x05, 0x04, 0x00,
+ 0x12, 0x01, 0x02, 0x00, 0x05, 0x04, 0x00,
+};
+
+static const u8 payload_white_dim[] = {
+ 0x01, 0x00, 0x00, 0x00,
+ 0x11, 0x01, 0x02, 0x20, 0x05, 0x03, 0x00,
+};
+
+static const u8 payload_white_medium[] = {
+ 0x01, 0x00, 0x00, 0x00,
+ 0x11, 0x01, 0x02, 0x5f, 0x05, 0x03, 0x00,
+};
+
+static const u8 payload_white_bright[] = {
+ 0x01, 0x00, 0x00, 0x00,
+ 0x11, 0x01, 0x02, 0xff, 0x05, 0x03, 0x00,
+};
+
+static const u8 payload_blue_rich[] = {
+ 0x01, 0x00, 0x00, 0x00,
+ 0x10, 0x01, 0x02, 0xff, 0x05, 0x03, 0x00,
+};
+
+static const u8 payload_orange_dim[] = {
+ 0x01, 0x00, 0x00, 0x00,
+ 0x12, 0x01, 0x02, 0xff, 0x05, 0x03, 0x00,
+};
+
+static const u8 payload_soft_blue_purple_1[] = {
+ 0x03, 0x00, 0x00, 0x00,
+ 0x10, 0x01, 0x02, 0xff, 0x05, 0x03, 0x00,
+ 0x11, 0x01, 0x02, 0x40, 0x05, 0x03, 0x00,
+ 0x12, 0x01, 0x02, 0x20, 0x05, 0x03, 0x00,
+};
+
+static const u8 payload_soft_blue_purple_2[] = {
+ 0x03, 0x00, 0x00, 0x00,
+ 0x10, 0x01, 0x02, 0xff, 0x05, 0x03, 0x00,
+ 0x11, 0x01, 0x02, 0xc0, 0x05, 0x03, 0x00,
+ 0x12, 0x01, 0x02, 0x00, 0x05, 0x03, 0x00,
+};
+
+static const u8 payload_salmon_pink[] = {
+ 0x02, 0x00, 0x00, 0x00,
+ 0x11, 0x01, 0x02, 0x30, 0x05, 0x03, 0x00,
+ 0x12, 0x01, 0x02, 0xff, 0x05, 0x03, 0x00,
+};
+
+static const u8 payload_pink_purple[] = {
+ 0x03, 0x00, 0x00, 0x00,
+ 0x10, 0x01, 0x02, 0x20, 0x05, 0x03, 0x00,
+ 0x11, 0x01, 0x02, 0x18, 0x05, 0x03, 0x00,
+ 0x12, 0x01, 0x02, 0xff, 0x05, 0x03, 0x00,
+};
+
+static const u8 payload_warm_pink_dim[] = {
+ 0x02, 0x00, 0x00, 0x00,
+ 0x10, 0x01, 0x02, 0x10, 0x05, 0x03, 0x00,
+ 0x12, 0x01, 0x02, 0xff, 0x05, 0x03, 0x00,
+};
+
+static const u8 payload_blue_hint_purple[] = {
+ 0x02, 0x00, 0x00, 0x00,
+ 0x10, 0x01, 0x02, 0x80, 0x05, 0x03, 0x00,
+ 0x12, 0x01, 0x02, 0xff, 0x05, 0x03, 0x00,
+};
+
+static const u8 payload_purple[] = {
+ 0x02, 0x00, 0x00, 0x00,
+ 0x10, 0x01, 0x02, 0x40, 0x05, 0x03, 0x00,
+ 0x12, 0x01, 0x02, 0xff, 0x05, 0x03, 0x00,
+};
+
+static const u8 payload_soft_purple[] = {
+ 0x02, 0x00, 0x00, 0x00,
+ 0x10, 0x01, 0x02, 0x50, 0x05, 0x03, 0x00,
+ 0x12, 0x01, 0x02, 0xff, 0x05, 0x03, 0x00,
+};
+
+static const u8 payload_pink_violet_dim[] = {
+ 0x02, 0x00, 0x00, 0x00,
+ 0x10, 0x01, 0x02, 0x20, 0x05, 0x03, 0x00,
+ 0x12, 0x01, 0x02, 0xff, 0x05, 0x03, 0x00,
+};
+
+static const u8 payload_purple_white[] = {
+ 0x03, 0x00, 0x00, 0x00,
+ 0x10, 0x01, 0x02, 0x40, 0x05, 0x03, 0x00,
+ 0x11, 0x01, 0x02, 0x20, 0x05, 0x03, 0x00,
+ 0x12, 0x01, 0x02, 0xff, 0x05, 0x03, 0x00,
+};
+
+static const u8 payload_soft_orange_dim[] = {
+ 0x02, 0x00, 0x00, 0x00,
+ 0x11, 0x01, 0x02, 0x20, 0x05, 0x03, 0x00,
+ 0x12, 0x01, 0x02, 0xff, 0x05, 0x03, 0x00,
+};
+
+static const u8 payload_purplish_blue_white[] = {
+ 0x02, 0x00, 0x00, 0x00,
+ 0x10, 0x01, 0x02, 0xff, 0x05, 0x03, 0x00,
+ 0x11, 0x01, 0x02, 0x80, 0x05, 0x03, 0x00,
+};
+
+static const u8 payload_dim_cool_white[] = {
+ 0x02, 0x00, 0x00, 0x00,
+ 0x10, 0x01, 0x02, 0x40, 0x05, 0x03, 0x00,
+ 0x11, 0x01, 0x02, 0x40, 0x05, 0x03, 0x00,
+};
+
+static const u8 payload_all_dim_purplish[] = {
+ 0x03, 0x00, 0x00, 0x00,
+ 0x10, 0x01, 0x02, 0x20, 0x05, 0x03, 0x00,
+ 0x11, 0x01, 0x02, 0x20, 0x05, 0x03, 0x00,
+ 0x12, 0x01, 0x02, 0x20, 0x05, 0x03, 0x00,
+};
+
+
+#define BREATHE_SLOW \
+ 0x00, 0x00, 0x00, 0x56, 0x00, 0x02, 0x02, 0x02, 0x04, 0x01, \
+ 0x02, 0x0e, 0x02, 0x03, 0x06, 0x02, 0x25, 0x04, 0x03, 0x05, \
+ 0x02, 0x6c, 0x05, 0x03, 0x0d, 0x02, 0xb9, 0x03, 0x02, 0x18, \
+ 0x02, 0xe7, 0x05, 0x04, 0x08, 0x02, 0xff, 0x03, 0x05, 0x08
+
+#define BREATHE_FAST \
+ 0x00, 0x00, 0x00, 0x20, 0x00, 0x02, 0x02, 0x02, 0x04, 0x01, \
+ 0x02, 0x0e, 0x02, 0x03, 0x06, 0x02, 0x25, 0x04, 0x03, 0x05, \
+ 0x02, 0x6c, 0x05, 0x03, 0x0d, 0x02, 0xb9, 0x03, 0x02, 0x18, \
+ 0x02, 0xe7, 0x05, 0x04, 0x08, 0x02, 0xff, 0x03, 0x05, 0x08
+
+static const u8 payload_blue_breathe[] = {
+ 0x03, 0x00, 0x00, 0x00,
+ 0x10, 0x08, BREATHE_SLOW,
+ 0x11, 0x01, 0x02, 0x00, 0x05, 0x03, 0x00,
+ 0x12, 0x01, 0x02, 0x00, 0x06, 0x02, 0x15,
+};
+
+static const u8 payload_white_breathe[] = {
+ 0x03, 0x00, 0x00, 0x00,
+ 0x11, 0x08, BREATHE_SLOW,
+ 0x10, 0x01, 0x02, 0x00, 0x05, 0x03, 0x00,
+ 0x12, 0x01, 0x02, 0x00, 0x06, 0x02, 0x15,
+};
+
+static const u8 payload_orange_breathe[] = {
+ 0x03, 0x00, 0x00, 0x00,
+ 0x12, 0x08, BREATHE_SLOW,
+ 0x10, 0x01, 0x02, 0x00, 0x05, 0x03, 0x00,
+ 0x11, 0x01, 0x02, 0x00, 0x06, 0x02, 0x15,
+};
+
+static const u8 payload_pink_breathe[] = {
+ 0x03, 0x00, 0x00, 0x00,
+ 0x12, 0x08, BREATHE_SLOW,
+ 0x10, 0x01, 0x02, 0x20, 0x05, 0x03, 0x00,
+ 0x11, 0x01, 0x02, 0x18, 0x06, 0x02, 0x15,
+};
+
+static const u8 payload_pink_breathe_fast[] = {
+ 0x03, 0x00, 0x00, 0x00,
+ 0x12, 0x08, BREATHE_FAST,
+ 0x10, 0x01, 0x02, 0x20, 0x05, 0x03, 0x00,
+ 0x11, 0x01, 0x02, 0x18, 0x06, 0x02, 0x15,
+};
+
+static const u8 payload_salmon_pink_breathe[] = {
+ 0x03, 0x00, 0x00, 0x00,
+ 0x12, 0x08, BREATHE_SLOW,
+ 0x10, 0x01, 0x02, 0x00, 0x05, 0x03, 0x00,
+ 0x11, 0x01, 0x02, 0x30, 0x06, 0x02, 0x15,
+};
+
+static const u8 payload_blue_to_richblue[] = {
+ 0x03, 0x00, 0x00, 0x00,
+ 0x10, 0x08, BREATHE_SLOW,
+ 0x11, 0x01, 0x02, 0x00, 0x05, 0x03, 0x00,
+ 0x12, 0x01, 0x02, 0xff, 0x06, 0x02, 0x15,
+};
+
+static const u8 payload_sunrise[] = {
+ 0x03, 0x00, 0x00, 0x00,
+ 0x11, 0x08, BREATHE_SLOW,
+ 0x10, 0x01, 0x02, 0x00, 0x05, 0x03, 0x00,
+ 0x12, 0x01, 0x02, 0x40, 0x06, 0x02, 0x15,
+};
+
+static const u8 payload_blue_white_anim[] = {
+ 0x02, 0x01, 0x00, 0x00,
+ 0x10, 0x03, 0x02, 0x2d, 0x01, 0x01, 0xd1, 0x02, 0x12, 0x03,
+ 0x05, 0x08, 0x02, 0x00, 0x02, 0x05, 0x08,
+ 0x11, 0x05, 0x02, 0x21, 0x01, 0x04, 0x20, 0x02, 0x58, 0x02,
+ 0x03, 0x1b, 0x02, 0xab, 0x05, 0x04, 0x10, 0x02, 0xe2, 0x05,
+ 0x05, 0x0b, 0x02, 0xff, 0x01, 0x02, 0x1d,
+};
+
+
+static const u8 payload_zoneb_white_pulse[] = {
+ 0x01, 0x01, 0x00, 0x00,
+ 0x01, 0x08, 0x02, 0xd3, 0x02, 0x02, 0x16, 0x02, 0x5b, 0x05,
+ 0x02, 0x18, 0x02, 0x18, 0x04, 0x02, 0x0f, 0x02, 0x11, 0x01,
+ 0x01, 0x06, 0x02, 0x0d, 0x01, 0x02, 0x03, 0x02, 0x12, 0x02,
+ 0x02, 0x02, 0x02, 0x42, 0x03, 0x01, 0x10, 0x02, 0xff, 0x0b,
+ 0x02, 0x11,
+};
+
+static const u8 payload_zoneb_orange_pulse[] = {
+ 0x01, 0x01, 0x00, 0x00,
+ 0x02, 0x08, 0x02, 0x18, 0x08, 0x03, 0x0d, 0x02, 0x11, 0x02,
+ 0x01, 0x03, 0x02, 0x0d, 0x01, 0x02, 0x03, 0x02, 0x12, 0x01,
+ 0x02, 0x04, 0x02, 0x41, 0x03, 0x01, 0x0e, 0x02, 0xff, 0x0e,
+ 0x02, 0x0d, 0x02, 0xd5, 0x04, 0x04, 0x09, 0x02, 0x80, 0x03,
+ 0x01, 0x1c,
+};
+
+static const u8 payload_zoneb_both_pulse[] = {
+ 0x02, 0x01, 0x00, 0x00,
+ 0x01, 0x08, 0x02, 0xd3, 0x02, 0x02, 0x16, 0x02, 0x5b, 0x05,
+ 0x02, 0x18, 0x02, 0x18, 0x04, 0x02, 0x0f, 0x02, 0x11, 0x01,
+ 0x01, 0x06, 0x02, 0x0d, 0x01, 0x02, 0x03, 0x02, 0x12, 0x02,
+ 0x02, 0x02, 0x02, 0x42, 0x03, 0x01, 0x10, 0x02, 0xff, 0x0b,
+ 0x02, 0x11,
+ 0x02, 0x08, 0x02, 0x18, 0x08, 0x03, 0x0d, 0x02, 0x11, 0x02,
+ 0x01, 0x03, 0x02, 0x0d, 0x01, 0x02, 0x03, 0x02, 0x12, 0x01,
+ 0x02, 0x04, 0x02, 0x41, 0x03, 0x01, 0x0e, 0x02, 0xff, 0x0e,
+ 0x02, 0x0d, 0x02, 0xd5, 0x04, 0x04, 0x09, 0x02, 0x80, 0x03,
+ 0x01, 0x1c,
+};
+
+
+#define PRESET(n) { .name = #n, .data = payload_##n, .size = sizeof(payload_##n) }
+
+const struct ps5_led_preset ps5_presets[] = {
+ PRESET(off),
+ PRESET(white_dim),
+ PRESET(white_medium),
+ PRESET(white_bright),
+ PRESET(blue_rich),
+ PRESET(orange_dim),
+ PRESET(soft_blue_purple_1),
+ PRESET(soft_blue_purple_2),
+ PRESET(salmon_pink),
+ PRESET(pink_purple),
+ PRESET(warm_pink_dim),
+ PRESET(blue_hint_purple),
+ PRESET(purple),
+ PRESET(soft_purple),
+ PRESET(pink_violet_dim),
+ PRESET(purple_white),
+ PRESET(soft_orange_dim),
+ PRESET(purplish_blue_white),
+ PRESET(dim_cool_white),
+ PRESET(all_dim_purplish),
+ PRESET(blue_breathe),
+ PRESET(white_breathe),
+ PRESET(orange_breathe),
+ PRESET(pink_breathe),
+ PRESET(pink_breathe_fast),
+ PRESET(salmon_pink_breathe),
+ PRESET(blue_to_richblue),
+ PRESET(sunrise),
+ PRESET(blue_white_anim),
+ PRESET(zoneb_white_pulse),
+ PRESET(zoneb_orange_pulse),
+ PRESET(zoneb_both_pulse),
+};
+
+const size_t ps5_num_presets = ARRAY_SIZE(ps5_presets);
+
+int ps5_led_set_preset(const char *name)
+{
+ size_t i;
+
+ if (!spcie_is_initialized())
+ return -ENODEV;
+
+ for (i = 0; i < ps5_num_presets; i++) {
+ if (!strcmp(ps5_presets[i].name, name)) {
+ if (i != 0)
+ icc_indicator_set_led(payload_off,
+ sizeof(payload_off));
+ return icc_indicator_set_led(ps5_presets[i].data,
+ ps5_presets[i].size);
+ }
+ }
+ return -EINVAL;
+}
+EXPORT_SYMBOL(ps5_led_set_preset);
diff --git a/drivers/ps5/led/presets.h b/drivers/ps5/led/presets.h
new file mode 100644
index 000000000000..a234788e9990
--- /dev/null
+++ b/drivers/ps5/led/presets.h
@@ -0,0 +1,16 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+#ifndef _PS5_LED_PRESETS_H
+#define _PS5_LED_PRESETS_H
+
+#include <linux/types.h>
+
+struct ps5_led_preset {
+ const char *name;
+ const u8 *data;
+ size_t size;
+};
+
+extern const struct ps5_led_preset ps5_presets[];
+extern const size_t ps5_num_presets;
+
+#endif
diff --git a/drivers/ps5/mp1.c b/drivers/ps5/mp1.c
new file mode 100644
index 000000000000..4af890c842a7