From b9b5fb8b0cfe018440ba1a577fdf41b08ae73f5f Mon Sep 17 00:00:00 2001 From: Alex Ling Date: Fri, 23 Jan 2026 10:24:10 +0800 Subject: [PATCH] sm8550: Add patches for 6.18 Signed-off-by: Alex Ling --- config/kernel/linux-sm8550-edge.config | 56 +- ...001-arm64-dts-qcom-sm8550-add-UART15.patch | 53 + ...input-Add-driver-for-RSInput-Gamepad.patch | 472 ++ ...nel-driver-for-Chipone-ICNA3512-base.patch | 565 ++ ...4-leds-Add-driver-for-HEROIC-HTR3212.patch | 353 + ...sc8280xp-Add-support-for-Primary-I2S.patch | 98 + ...qcom-Document-level-shifter-flag-for.patch | 39 + ...m-Limit-HS-mode-frequency-to-37.5MHz.patch | 62 + ...ggle-the-FIFO-write-clock-after-unga.patch | 100 + ...-sm8550-Keep-UFS-PHY-GDSCs-ALWAYS_ON.patch | 53 + ...-Add-WIP-panel-driver-for-AYN-Odin-2.patch | 307 + ...4-dts-qcom-Added-pmk8550-pwm-support.patch | 33 + ...c-Added-qcom-downstream-sdhci-driver.patch | 6208 +++++++++++++++++ ...-power-Fix-name-for-sc8280xp-battery.patch | 35 + .../0014-HACK-fix-usb-boot-hang.patch | 37 + ...se-soc-serial-for-wifi-and-bluetooth.patch | 301 + ...K-Revert-back-to-6.12-aw88166-driver.patch | 540 ++ ...017-pwm-Add-SI-EN-SN3112-PWM-support.patch | 407 ++ ...-qcom-Added-Ayn-Odin2-device-support.patch | 2143 ++++++ 19 files changed, 11821 insertions(+), 41 deletions(-) create mode 100644 patch/kernel/archive/sm8550-6.18/0001-arm64-dts-qcom-sm8550-add-UART15.patch create mode 100644 patch/kernel/archive/sm8550-6.18/0002-input-Add-driver-for-RSInput-Gamepad.patch create mode 100644 patch/kernel/archive/sm8550-6.18/0003-drm-panel-Add-panel-driver-for-Chipone-ICNA3512-base.patch create mode 100644 patch/kernel/archive/sm8550-6.18/0004-leds-Add-driver-for-HEROIC-HTR3212.patch create mode 100644 patch/kernel/archive/sm8550-6.18/0005-ASoC-qcom-sc8280xp-Add-support-for-Primary-I2S.patch create mode 100644 patch/kernel/archive/sm8550-6.18/0006-dt-bindings-mmc-qcom-Document-level-shifter-flag-for.patch create mode 100644 patch/kernel/archive/sm8550-6.18/0007-mmc-sdhci-msm-Limit-HS-mode-frequency-to-37.5MHz.patch create mode 100644 patch/kernel/archive/sm8550-6.18/0008-mmc-sdhci-msm-Toggle-the-FIFO-write-clock-after-unga.patch create mode 100644 patch/kernel/archive/sm8550-6.18/0009-clk-qcom-gcc-sm8550-Keep-UFS-PHY-GDSCs-ALWAYS_ON.patch create mode 100644 patch/kernel/archive/sm8550-6.18/0010-drm-panel-Add-WIP-panel-driver-for-AYN-Odin-2.patch create mode 100644 patch/kernel/archive/sm8550-6.18/0011-arm64-dts-qcom-Added-pmk8550-pwm-support.patch create mode 100644 patch/kernel/archive/sm8550-6.18/0012-drivers-mmc-Added-qcom-downstream-sdhci-driver.patch create mode 100644 patch/kernel/archive/sm8550-6.18/0013-drivers-power-Fix-name-for-sc8280xp-battery.patch create mode 100644 patch/kernel/archive/sm8550-6.18/0014-HACK-fix-usb-boot-hang.patch create mode 100644 patch/kernel/archive/sm8550-6.18/0015-drivers-use-soc-serial-for-wifi-and-bluetooth.patch create mode 100644 patch/kernel/archive/sm8550-6.18/0016-HACK-Revert-back-to-6.12-aw88166-driver.patch create mode 100644 patch/kernel/archive/sm8550-6.18/0017-pwm-Add-SI-EN-SN3112-PWM-support.patch create mode 100644 patch/kernel/archive/sm8550-6.18/0018-dts-arm64-qcom-Added-Ayn-Odin2-device-support.patch diff --git a/config/kernel/linux-sm8550-edge.config b/config/kernel/linux-sm8550-edge.config index 128ba5bf64..e80a2e941e 100644 --- a/config/kernel/linux-sm8550-edge.config +++ b/config/kernel/linux-sm8550-edge.config @@ -1,4 +1,4 @@ -# Armbian defconfig generated with 6.12 +# Armbian defconfig generated with 6.18 # CONFIG_LOCALVERSION_AUTO is not set CONFIG_DEFAULT_HOSTNAME="@DEVICENAME@" CONFIG_SYSVIPC=y @@ -42,8 +42,6 @@ CONFIG_ARCH_QCOM=y # CONFIG_NVIDIA_CARMEL_CNP_ERRATUM is not set # CONFIG_ROCKCHIP_ERRATUM_3588001 is not set CONFIG_ARM64_VA_BITS_48=y -CONFIG_SCHED_MC=y -CONFIG_SCHED_SMT=y CONFIG_NUMA=y CONFIG_PARAVIRT=y CONFIG_COMPAT=y @@ -74,7 +72,6 @@ CONFIG_ACPI_APEI_MEMORY_FAILURE=y CONFIG_ACPI_APEI_EINJ=y CONFIG_VIRTUALIZATION=y CONFIG_KVM=y -CONFIG_JUMP_LABEL=y CONFIG_MODULES=y CONFIG_MODULE_UNLOAD=y CONFIG_BLK_DEV_INTEGRITY=y @@ -83,7 +80,6 @@ CONFIG_PARTITION_ADVANCED=y # CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set CONFIG_BINFMT_MISC=y CONFIG_ZSWAP=y -CONFIG_ZSWAP_ZPOOL_DEFAULT_ZBUD=y # CONFIG_COMPAT_BRK is not set CONFIG_MEMORY_HOTPLUG=y CONFIG_MEMORY_HOTREMOVE=y @@ -145,18 +141,22 @@ CONFIG_NETFILTER_XT_TARGET_AUDIT=m CONFIG_NETFILTER_XT_TARGET_CHECKSUM=m CONFIG_NETFILTER_XT_TARGET_CLASSIFY=m CONFIG_NETFILTER_XT_TARGET_CONNMARK=m +CONFIG_NETFILTER_XT_TARGET_CT=m CONFIG_NETFILTER_XT_TARGET_DSCP=m +CONFIG_NETFILTER_XT_TARGET_HL=m CONFIG_NETFILTER_XT_TARGET_HMARK=m CONFIG_NETFILTER_XT_TARGET_IDLETIMER=m CONFIG_NETFILTER_XT_TARGET_LED=m CONFIG_NETFILTER_XT_TARGET_LOG=m CONFIG_NETFILTER_XT_TARGET_MARK=m +CONFIG_NETFILTER_XT_NAT=m +CONFIG_NETFILTER_XT_TARGET_NETMAP=m CONFIG_NETFILTER_XT_TARGET_NFLOG=m CONFIG_NETFILTER_XT_TARGET_NFQUEUE=m -CONFIG_NETFILTER_XT_TARGET_NOTRACK=m +CONFIG_NETFILTER_XT_TARGET_REDIRECT=m +CONFIG_NETFILTER_XT_TARGET_MASQUERADE=m CONFIG_NETFILTER_XT_TARGET_TEE=m CONFIG_NETFILTER_XT_TARGET_TPROXY=m -CONFIG_NETFILTER_XT_TARGET_TRACE=m CONFIG_NETFILTER_XT_TARGET_TCPMSS=m CONFIG_NETFILTER_XT_TARGET_TCPOPTSTRIP=m CONFIG_NETFILTER_XT_MATCH_ADDRTYPE=m @@ -221,15 +221,7 @@ CONFIG_NFT_DUP_IPV4=m CONFIG_NFT_FIB_IPV4=m CONFIG_NF_TABLES_ARP=y CONFIG_IP_NF_IPTABLES=m -CONFIG_IP_NF_FILTER=m CONFIG_IP_NF_TARGET_REJECT=m -CONFIG_IP_NF_NAT=m -CONFIG_IP_NF_TARGET_MASQUERADE=m -CONFIG_IP_NF_TARGET_NETMAP=m -CONFIG_IP_NF_TARGET_REDIRECT=m -CONFIG_IP_NF_MANGLE=m -CONFIG_IP_NF_RAW=m -CONFIG_IP_NF_SECURITY=m CONFIG_NFT_DUP_IPV6=m CONFIG_NFT_FIB_IPV6=m CONFIG_IP6_NF_IPTABLES=m @@ -243,15 +235,8 @@ CONFIG_IP6_NF_MATCH_MH=m CONFIG_IP6_NF_MATCH_RPFILTER=m CONFIG_IP6_NF_MATCH_RT=m CONFIG_IP6_NF_MATCH_SRH=m -CONFIG_IP6_NF_TARGET_HL=m -CONFIG_IP6_NF_FILTER=m CONFIG_IP6_NF_TARGET_REJECT=m CONFIG_IP6_NF_TARGET_SYNPROXY=m -CONFIG_IP6_NF_MANGLE=m -CONFIG_IP6_NF_RAW=m -CONFIG_IP6_NF_SECURITY=m -CONFIG_IP6_NF_NAT=m -CONFIG_IP6_NF_TARGET_MASQUERADE=m CONFIG_IP6_NF_TARGET_NPT=m CONFIG_NF_TABLES_BRIDGE=m CONFIG_NFT_BRIDGE_META=m @@ -289,7 +274,9 @@ CONFIG_BT_HCIUART=m CONFIG_BT_HCIUART_LL=y CONFIG_BT_HCIUART_QCA=y CONFIG_CFG80211=m +CONFIG_CFG80211_WEXT=y CONFIG_MAC80211=m +CONFIG_MAC80211_MESH=y CONFIG_MAC80211_LEDS=y CONFIG_RFKILL=m CONFIG_RFKILL_INPUT=y @@ -364,15 +351,14 @@ CONFIG_QCOM_COINCELL=m CONFIG_QCOM_FASTRPC=y CONFIG_SRAM=y CONFIG_PCI_ENDPOINT_TEST=m +CONFIG_NTSYNC=m CONFIG_EEPROM_AT24=m CONFIG_EEPROM_AT25=m -CONFIG_EEPROM_93CX6=y CONFIG_UACCE=m CONFIG_SCSI=y # CONFIG_SCSI_PROC_FS is not set CONFIG_BLK_DEV_SD=y CONFIG_MD=y -# CONFIG_MD_BITMAP_FILE is not set CONFIG_NETDEVICES=y CONFIG_DUMMY=m CONFIG_WIREGUARD=m @@ -608,9 +594,7 @@ CONFIG_VIDEO_QCOM_VENUS=m CONFIG_DRM=y CONFIG_DRM_LOAD_EDID_FIRMWARE=y CONFIG_DRM_DISPLAY_DP_AUX_CHARDEV=y -CONFIG_DRM_I2C_CH7006=m -CONFIG_DRM_I2C_SIL164=m -CONFIG_DRM_I2C_NXP_TDA998X=m +CONFIG_DRM_SIMPLEDRM=y CONFIG_DRM_MSM=y CONFIG_DRM_PANEL_CHIPONE_ICNA3512=y CONFIG_DRM_PANEL_LVDS=m @@ -618,8 +602,8 @@ CONFIG_DRM_PANEL_EDP=y CONFIG_DRM_PANEL_SIMPLE=m CONFIG_DRM_PANEL_SYNAPTICS_TD4328=y CONFIG_DRM_DISPLAY_CONNECTOR=y +CONFIG_DRM_I2C_NXP_TDA998X=m CONFIG_DRM_SIMPLE_BRIDGE=m -CONFIG_DRM_SIMPLEDRM=y CONFIG_FB=y CONFIG_FB_EFI=y CONFIG_FB_MODE_HELPERS=y @@ -681,10 +665,10 @@ CONFIG_HID_PLAYSTATION=y CONFIG_PLAYSTATION_FF=y CONFIG_HID_SONY=y CONFIG_SONY_FF=y -CONFIG_USB_HIDDEV=y CONFIG_I2C_HID_ACPI=m CONFIG_I2C_HID_OF=m CONFIG_I2C_HID_OF_ELAN=m +CONFIG_USB_HIDDEV=y CONFIG_USB_ULPI_BUS=y CONFIG_USB_CONN_GPIO=y CONFIG_USB_OTG=y @@ -852,12 +836,13 @@ CONFIG_IIO_TRIGGERED_BUFFER=m CONFIG_QCOM_SPMI_VADC=y CONFIG_QCOM_SPMI_ADC5=y CONFIG_PWM=y -CONFIG_PWM_SN3112=y +CONFIG_PWM_SN3112=m CONFIG_QCOM_PDC=y CONFIG_QCOM_MPM=y CONFIG_RESET_GPIO=m CONFIG_RESET_QCOM_AOSS=y CONFIG_RESET_QCOM_PDC=y +CONFIG_PHY_SNPS_EUSB2=y CONFIG_PHY_CAN_TRANSCEIVER=m CONFIG_PHY_CADENCE_TORRENT=m CONFIG_PHY_CADENCE_DPHY_RX=m @@ -868,7 +853,6 @@ CONFIG_PHY_QCOM_PCIE2=m CONFIG_PHY_QCOM_QMP=y CONFIG_PHY_QCOM_QMP_PCIE_8996=m CONFIG_PHY_QCOM_QUSB2=m -CONFIG_PHY_QCOM_SNPS_EUSB2=y CONFIG_PHY_QCOM_EUSB2_REPEATER=y CONFIG_PHY_QCOM_M31_USB=m CONFIG_PHY_QCOM_USB_HS=m @@ -898,7 +882,6 @@ CONFIG_TEE=y CONFIG_OPTEE=y CONFIG_MUX_GPIO=m CONFIG_MUX_MMIO=m -CONFIG_SLIM_QCOM_CTRL=m CONFIG_SLIM_QCOM_NGD_CTRL=m CONFIG_INTERCONNECT_QCOM=y CONFIG_INTERCONNECT_QCOM_OSM_L3=y @@ -952,7 +935,6 @@ CONFIG_SECURITY=y CONFIG_SECURITY_APPARMOR=y CONFIG_LSM="landlock,lockdown,yama,loadpin,safesetid,bpf" CONFIG_CRYPTO_USER=y -CONFIG_CRYPTO_TEST=m CONFIG_CRYPTO_ECDH=y CONFIG_CRYPTO_DES=m CONFIG_CRYPTO_ARC4=m @@ -963,14 +945,10 @@ CONFIG_CRYPTO_MICHAEL_MIC=y CONFIG_CRYPTO_ANSI_CPRNG=y CONFIG_CRYPTO_USER_API_RNG=m CONFIG_CRYPTO_GHASH_ARM64_CE=y -CONFIG_CRYPTO_SHA1_ARM64_CE=y -CONFIG_CRYPTO_SHA2_ARM64_CE=y -CONFIG_CRYPTO_SHA512_ARM64_CE=m CONFIG_CRYPTO_SHA3_ARM64=m CONFIG_CRYPTO_SM3_ARM64_CE=m CONFIG_CRYPTO_AES_ARM64_BS=m CONFIG_CRYPTO_AES_ARM64_CE_CCM=y -CONFIG_CRYPTO_CRCT10DIF_ARM64_CE=y CONFIG_CRYPTO_DEV_QCE=y CONFIG_CRYPTO_DEV_QCOM_RNG=y CONFIG_CRYPTO_DEV_CCREE=m @@ -981,7 +959,6 @@ CONFIG_CRYPTO_DEV_HISI_TRNG=m CONFIG_CRYPTO_DEV_AMLOGIC_GXL=m CONFIG_PACKING=y CONFIG_INDIRECT_PIO=y -CONFIG_CRC_CCITT=m CONFIG_DMA_RESTRICTED_POOL=y CONFIG_DMA_CMA=y CONFIG_CMA_SIZE_MBYTES=32 @@ -991,11 +968,8 @@ CONFIG_CONSOLE_LOGLEVEL_DEFAULT=4 CONFIG_CONSOLE_LOGLEVEL_QUIET=1 CONFIG_BOOT_PRINTK_DELAY=y CONFIG_DYNAMIC_DEBUG=y -CONFIG_DEBUG_INFO_DWARF5=y -CONFIG_DEBUG_INFO_REDUCED=y CONFIG_MAGIC_SYSRQ=y CONFIG_DEBUG_FS=y CONFIG_DEBUG_MEMORY_INIT=y -# CONFIG_SCHED_DEBUG is not set # CONFIG_FTRACE is not set CONFIG_MEMTEST=y diff --git a/patch/kernel/archive/sm8550-6.18/0001-arm64-dts-qcom-sm8550-add-UART15.patch b/patch/kernel/archive/sm8550-6.18/0001-arm64-dts-qcom-sm8550-add-UART15.patch new file mode 100644 index 0000000000..d215dc33a2 --- /dev/null +++ b/patch/kernel/archive/sm8550-6.18/0001-arm64-dts-qcom-sm8550-add-UART15.patch @@ -0,0 +1,53 @@ +From df25170e42b1b5a20e5e2d1489bcffe5d6aee336 Mon Sep 17 00:00:00 2001 +From: Teguh Sobirin +Date: Wed, 12 Feb 2025 17:53:48 +0800 +Subject: [PATCH 01/18] arm64: dts: qcom: sm8550: add UART15 + +Signed-off-by: Teguh Sobirin +--- + arch/arm64/boot/dts/qcom/sm8550.dtsi | 22 ++++++++++++++++++++++ + 1 file changed, 22 insertions(+) + +diff --git a/arch/arm64/boot/dts/qcom/sm8550.dtsi b/arch/arm64/boot/dts/qcom/sm8550.dtsi +index 7724dba75..ac0698c01 100644 +--- a/arch/arm64/boot/dts/qcom/sm8550.dtsi ++++ b/arch/arm64/boot/dts/qcom/sm8550.dtsi +@@ -1251,6 +1251,20 @@ &config_noc SLAVE_QUP_2 QCOM_ICC_TAG_ACTIVE_ONLY>, + #size-cells = <0>; + status = "disabled"; + }; ++ ++ uart15: serial@89c000 { ++ compatible = "qcom,geni-uart"; ++ reg = <0 0x89c000 0 0x4000>; ++ clock-names = "se"; ++ clocks = <&gcc GCC_QUPV3_WRAP2_S7_CLK>; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&qup_uart15_default>; ++ interrupts = ; ++ interconnects = <&clk_virt MASTER_QUP_CORE_2 0 &clk_virt SLAVE_QUP_CORE_2 0>, ++ <&gem_noc MASTER_APPSS_PROC 0 &config_noc SLAVE_QUP_2 0>; ++ interconnect-names = "qup-core", "qup-config"; ++ status = "disabled"; ++ }; + }; + + i2c_master_hub_0: geniqup@9c0000 { +@@ -4917,6 +4931,14 @@ qup_uart14_cts_rts: qup-uart14-cts-rts-state { + bias-pull-down; + }; + ++ qup_uart15_default: qup-uart15-default-state { ++ /* TX, RX */ ++ pins = "gpio74", "gpio75"; ++ function = "qup2_se7"; ++ drive-strength = <2>; ++ bias-pull-up; ++ }; ++ + sdc2_sleep: sdc2-sleep-state { + clk-pins { + pins = "sdc2_clk"; +-- +2.43.0 + diff --git a/patch/kernel/archive/sm8550-6.18/0002-input-Add-driver-for-RSInput-Gamepad.patch b/patch/kernel/archive/sm8550-6.18/0002-input-Add-driver-for-RSInput-Gamepad.patch new file mode 100644 index 0000000000..5812814f1c --- /dev/null +++ b/patch/kernel/archive/sm8550-6.18/0002-input-Add-driver-for-RSInput-Gamepad.patch @@ -0,0 +1,472 @@ +From 223437dc502f36021f3131bf8ba3a0b2a3dcee0c Mon Sep 17 00:00:00 2001 +From: Teguh Sobirin +Date: Thu, 20 Feb 2025 14:50:30 +0800 +Subject: [PATCH 02/18] input: Add driver for RSInput Gamepad + +Signed-off-by: Teguh Sobirin +--- + drivers/input/joystick/Kconfig | 4 + + drivers/input/joystick/Makefile | 1 + + drivers/input/joystick/rsinput.c | 423 +++++++++++++++++++++++++++++++ + 3 files changed, 428 insertions(+) + create mode 100644 drivers/input/joystick/rsinput.c + +diff --git a/drivers/input/joystick/Kconfig b/drivers/input/joystick/Kconfig +index 7755e5b45..0da3c0f44 100644 +--- a/drivers/input/joystick/Kconfig ++++ b/drivers/input/joystick/Kconfig +@@ -383,6 +383,10 @@ config JOYSTICK_QWIIC + To compile this driver as a module, choose M here: the + module will be called qwiic-joystick. + ++config JOYSTICK_RSINPUT ++ tristate "UART Based gamepad driver that found in AYN and Retroid Pocket products" ++ depends on SERIAL_DEV_BUS ++ + config JOYSTICK_FSIA6B + tristate "FlySky FS-iA6B RC Receiver" + select SERIO +diff --git a/drivers/input/joystick/Makefile b/drivers/input/joystick/Makefile +index 9976f596a..3de503e29 100644 +--- a/drivers/input/joystick/Makefile ++++ b/drivers/input/joystick/Makefile +@@ -28,6 +28,7 @@ obj-$(CONFIG_JOYSTICK_N64) += n64joy.o + obj-$(CONFIG_JOYSTICK_PSXPAD_SPI) += psxpad-spi.o + obj-$(CONFIG_JOYSTICK_PXRC) += pxrc.o + obj-$(CONFIG_JOYSTICK_QWIIC) += qwiic-joystick.o ++obj-$(CONFIG_JOYSTICK_RSINPUT) += rsinput.o + obj-$(CONFIG_JOYSTICK_SEESAW) += adafruit-seesaw.o + obj-$(CONFIG_JOYSTICK_SENSEHAT) += sensehat-joystick.o + obj-$(CONFIG_JOYSTICK_SIDEWINDER) += sidewinder.o +diff --git a/drivers/input/joystick/rsinput.c b/drivers/input/joystick/rsinput.c +new file mode 100644 +index 000000000..8fc0c6ac3 +--- /dev/null ++++ b/drivers/input/joystick/rsinput.c +@@ -0,0 +1,423 @@ ++// SPDX-License-Identifier: GPL-2.0-only ++/* ++ * RSInput Gamepad Driver ++ * ++ * Copyright (C) 2024 Teguh Sobirin ++ * ++ */ ++#define DEBUG ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#define FRAME_HEAD_1 0xA5 ++#define FRAME_HEAD_2 0xD3 ++#define FRAME_HEAD_3 0x5A ++#define FRAME_HEAD_4 0x3D ++ ++#define CMD_COMMOD 0x01 ++#define CMD_STATUS 0x02 ++ ++#define DATA_COMMOD_VERSION 0x02 ++#define DATA_COMMOD_SET_PAR 0x05 ++ ++#define FRAME_POS_SEQ 4 ++#define FRAME_POS_CMD 5 ++#define FRAME_POS_LEN_L 6 ++#define FRAME_POS_LEN_H 7 ++#define FRAME_POS_DATA_1 8 ++#define FRAME_POS_DATA_2 9 ++#define FRAME_POS_DATA_3 10 ++#define FRAME_POS_DATA_4 11 ++#define FRAME_POS_DATA_5 12 ++#define FRAME_POS_DATA_6 13 ++#define FRAME_POS_DATA_7 14 ++#define FRAME_POS_DATA_8 15 ++#define FRAME_POS_DATA_9 16 ++#define FRAME_POS_DATA_10 17 ++#define FRAME_POS_DATA_11 18 ++#define FRAME_POS_DATA_12 19 ++#define FRAME_POS_DATA_13 20 ++#define FRAME_POS_DATA_14 21 ++ ++#define MCU_PKT_SIZE_MIN 9 ++ ++#define MCU_VERSION_MAX_LEN 64 ++ ++struct rsinput_driver { ++ struct serdev_device *serdev; ++ struct input_dev *input; ++ struct gpio_desc *boot_gpio; ++ struct gpio_desc *enable_gpio; ++ struct gpio_desc *reset_gpio; ++ uint8_t rx_buf[256]; ++ uint8_t sequence_number; ++}; ++ ++static const unsigned int keymap[] = { ++ BTN_DPAD_UP, BTN_DPAD_DOWN, BTN_DPAD_LEFT, BTN_DPAD_RIGHT, ++ BTN_NORTH, BTN_WEST, BTN_EAST, BTN_SOUTH, ++ BTN_TL, BTN_TR, BTN_SELECT, BTN_START, ++ BTN_THUMBL, BTN_THUMBR, BTN_MODE, BTN_BACK ++}; ++ ++static uint8_t compute_checksum(const uint8_t *data, size_t len) { ++ uint8_t checksum = 0; ++ ++ for (size_t i = FRAME_POS_SEQ; i < len - 1; i++) { ++ checksum ^= data[i]; ++ } ++ ++ return checksum; ++} ++ ++static int rsinput_send_command(struct rsinput_driver *drv, uint8_t cmd, const uint8_t *data, size_t len) { ++ uint8_t frame[256]; ++ uint8_t checksum = 0; ++ size_t frame_len = 0; ++ ++ frame[frame_len++] = FRAME_HEAD_1; ++ frame[frame_len++] = FRAME_HEAD_2; ++ frame[frame_len++] = FRAME_HEAD_3; ++ frame[frame_len++] = FRAME_HEAD_4; ++ ++ frame[frame_len++] = drv->sequence_number; ++ drv->sequence_number++; ++ ++ frame[frame_len++] = cmd; ++ ++ frame[frame_len++] = len & 0xFF; ++ frame[frame_len++] = (len >> 8) & 0xFF; ++ ++ if (data && len) { ++ memcpy(&frame[frame_len], data, len); ++ frame_len += len; ++ } ++ ++ checksum = compute_checksum(frame, frame_len + 1); ++ frame[frame_len++] = checksum; ++ ++ return serdev_device_write_buf(drv->serdev, frame, frame_len); ++} ++ ++static int rsinput_init_commands(struct rsinput_driver *drv) { ++ int error; ++ ++ msleep(100); ++ uint8_t version_request[] = {DATA_COMMOD_VERSION}; ++ error = rsinput_send_command(drv, CMD_COMMOD, version_request, sizeof(version_request)); ++ if (error < 0) { ++ dev_err(&drv->serdev->dev, "Failed to request MCU version: %d\n", error); ++ return error; ++ } ++ ++ msleep(100); ++ uint8_t mcu_params[] = { ++ DATA_COMMOD_SET_PAR, ++ 0x01, ++ 0x00, 0x00, 0x00, 0x28, ++ 0x00, 0x00, 0x00, 0x07 ++ }; ++ error = rsinput_send_command(drv, CMD_COMMOD, mcu_params, sizeof(mcu_params)); ++ if (error < 0) { ++ dev_err(&drv->serdev->dev, "Failed to set MCU parameters: %d\n", error); ++ return error; ++ } ++ ++ return 0; ++} ++ ++static void handle_cmd_commod(struct rsinput_driver *drv, const uint8_t *data, size_t payload_length) { ++ switch (data[FRAME_POS_DATA_1]) { ++ case DATA_COMMOD_VERSION: ++ if (payload_length >= 1) { ++ char mcu_version[MCU_VERSION_MAX_LEN] = {0}; ++ size_t version_length = payload_length; ++ if (version_length > MCU_VERSION_MAX_LEN - 1) { ++ version_length = MCU_VERSION_MAX_LEN - 1; ++ } ++ memcpy(mcu_version, &data[FRAME_POS_DATA_1], version_length); ++ mcu_version[version_length] = '\0'; ++ dev_info(&drv->serdev->dev, "MCU Version: %s\n", mcu_version); ++ } else { ++ dev_err(&drv->serdev->dev, "Invalid MCU version response length\n"); ++ } ++ break; ++ case DATA_COMMOD_SET_PAR: ++ dev_info(&drv->serdev->dev, "MCU parameters set successfully\n"); ++ break; ++ default: ++ dev_warn(&drv->serdev->dev, "Unhandled CMD_COMMOD sub-command: 0x%02x\n", data[FRAME_POS_DATA_1]); ++ break; ++ } ++} ++ ++static void handle_cmd_status(struct rsinput_driver *drv, const uint8_t *data, size_t payload_length) { ++ if (payload_length >= 6) { ++ static unsigned long prev_states; ++ unsigned long keys = data[FRAME_POS_DATA_1] | (data[FRAME_POS_DATA_2] << 8); ++ unsigned long current_states = keys, changes; ++ int i; ++ ++ bitmap_xor(&changes, ¤t_states, &prev_states, ARRAY_SIZE(keymap)); ++ ++ for_each_set_bit(i, &changes, ARRAY_SIZE(keymap)) { ++ input_report_key(drv->input, keymap[i], (current_states & BIT(i))); ++ } ++ ++ input_report_abs(drv->input, ABS_HAT2X, ++ 0x650 - (data[FRAME_POS_DATA_3] | (data[FRAME_POS_DATA_4] << 8))); ++ input_report_abs(drv->input, ABS_HAT2Y, ++ 0x650 - (data[FRAME_POS_DATA_5] | (data[FRAME_POS_DATA_6] << 8))); ++ input_report_abs(drv->input, ABS_X, ++ -(int16_t)(data[FRAME_POS_DATA_7] | (data[FRAME_POS_DATA_8] << 8))); ++ input_report_abs(drv->input, ABS_Y, ++ -(int16_t)(data[FRAME_POS_DATA_9] | (data[FRAME_POS_DATA_10] << 8))); ++ input_report_abs(drv->input, ABS_RX, ++ -(int16_t)(data[FRAME_POS_DATA_11] | (data[FRAME_POS_DATA_12] << 8))); ++ input_report_abs(drv->input, ABS_RY, ++ -(int16_t)(data[FRAME_POS_DATA_13] | (data[FRAME_POS_DATA_14] << 8))); ++ ++ input_sync(drv->input); ++ prev_states = keys; ++ ++ } else { ++ dev_warn(&drv->serdev->dev, "Invalid CMD_STATUS response length\n"); ++ } ++} ++ ++static void rsinput_process_data(struct rsinput_driver *drv, const uint8_t *data, size_t len) { ++ while (len >= MCU_PKT_SIZE_MIN) { ++ uint16_t payload_length = data[FRAME_POS_LEN_L] | (data[FRAME_POS_LEN_H] << 8); ++ size_t frame_length = MCU_PKT_SIZE_MIN + payload_length; ++ ++ if (len < frame_length) { ++ return; ++ } ++ ++ uint8_t received_checksum = data[frame_length - 1]; ++ uint8_t computed_checksum = compute_checksum(data, frame_length); ++ if (computed_checksum != received_checksum) { ++ data += frame_length; ++ len -= frame_length; ++ continue; ++ } ++ ++ switch (data[FRAME_POS_CMD]) { ++ case CMD_COMMOD: ++ handle_cmd_commod(drv, data, payload_length); ++ break; ++ case CMD_STATUS: ++ handle_cmd_status(drv, data, payload_length); ++ break; ++ default: ++ dev_warn(&drv->serdev->dev, "Unhandled command: 0x%02X\n", data[FRAME_POS_CMD]); ++ break; ++ } ++ ++ data += frame_length; ++ len -= frame_length; ++ } ++ ++ if (len > 0) { ++ dev_warn(&drv->serdev->dev, "Trailing bytes after processing: %zu\n", len); ++ } ++} ++ ++static size_t rsinput_rx(struct serdev_device *serdev, const u8 *data, size_t count) { ++ struct rsinput_driver *drv = serdev_device_get_drvdata(serdev); ++ uint8_t received_checksum, computed_checksum; ++ ++ if (!drv || !data || count == 0) { ++ dev_warn_ratelimited(&serdev->dev, "Invalid RX data\n"); ++ goto error; ++ } ++ ++ if (count > sizeof(drv->rx_buf)) { ++ dev_warn_ratelimited(&serdev->dev, "RX buffer overflow\n"); ++ goto error; ++ } ++ ++ memcpy(drv->rx_buf, data, count); ++ ++ if (count < MCU_PKT_SIZE_MIN) { ++ dev_warn_ratelimited(&serdev->dev, "Frame too short for checksum validation\n"); ++ goto error; ++ } ++ ++ received_checksum = drv->rx_buf[count - 1]; ++ ++ computed_checksum = compute_checksum(drv->rx_buf, count); ++ ++ if (computed_checksum != received_checksum) { ++ rsinput_init_commands(drv); ++ goto error; ++ } ++ ++ rsinput_process_data(drv, drv->rx_buf, count); ++ ++error: ++ return count; ++} ++ ++static const struct serdev_device_ops rsinput_rx_ops = { ++ .receive_buf = rsinput_rx, ++}; ++ ++static int rsinput_probe(struct serdev_device *serdev) { ++ struct rsinput_driver *drv; ++ u32 gamepad_bus = 0; ++ u32 gamepad_vid = 0; ++ u32 gamepad_pid = 0; ++ u32 gamepad_rev = 0; ++ int error; ++ ++ drv = devm_kzalloc(&serdev->dev, sizeof(*drv), GFP_KERNEL); ++ if (!drv) ++ return -ENOMEM; ++ ++ drv->boot_gpio = ++ devm_gpiod_get_optional(&serdev->dev, "boot", GPIOD_OUT_HIGH); ++ if (IS_ERR(drv->boot_gpio)) { ++ error = PTR_ERR(drv->boot_gpio); ++ dev_warn(&serdev->dev, "Unable to get boot gpio: %d\n", error); ++ } ++ ++ drv->enable_gpio = ++ devm_gpiod_get_optional(&serdev->dev, "enable", GPIOD_OUT_HIGH); ++ if (IS_ERR(drv->enable_gpio)) { ++ error = PTR_ERR(drv->enable_gpio); ++ dev_warn(&serdev->dev, "Unable to get enable gpio: %d\n", error); ++ } ++ ++ drv->reset_gpio = ++ devm_gpiod_get_optional(&serdev->dev, "reset", GPIOD_OUT_HIGH); ++ if (IS_ERR(drv->reset_gpio)) { ++ error = PTR_ERR(drv->reset_gpio); ++ dev_warn(&serdev->dev, "Unable to get reset gpio: %d\n", error); ++ } ++ ++ if (drv->boot_gpio) ++ gpiod_set_value_cansleep(drv->boot_gpio, 0); ++ ++ if (drv->reset_gpio) ++ gpiod_set_value_cansleep(drv->reset_gpio, 0); ++ ++ msleep(100); ++ ++ if (drv->enable_gpio) ++ gpiod_set_value_cansleep(drv->enable_gpio, 1); ++ ++ if (drv->reset_gpio) ++ gpiod_set_value_cansleep(drv->reset_gpio, 1); ++ ++ msleep(100); ++ ++ serdev_device_set_client_ops(serdev, &rsinput_rx_ops); ++ error = serdev_device_open(serdev); ++ if (error) ++ return dev_err_probe(&serdev->dev, error, "Unable to open UART device\n"); ++ ++ drv->serdev = serdev; ++ drv->sequence_number = 0; ++ ++ serdev_device_set_drvdata(serdev, drv); ++ ++ error = serdev_device_set_baudrate(serdev, 115200); ++ if (error < 0) ++ goto err_close; ++ ++ serdev_device_set_flow_control(serdev, false); ++ ++ drv->input = devm_input_allocate_device(&serdev->dev); ++ if (!drv->input) { ++ error = -ENOMEM; ++ goto err_close; ++ } ++ ++ drv->input->phys = "rsinput-gamepad/input0"; ++ ++ error = device_property_read_string(&serdev->dev, "gamepad-name", &drv->input->name); ++ if (error) { ++ drv->input->name = "RSInput Gamepad"; ++ } ++ ++ device_property_read_u32(&serdev->dev, "gamepad-bus", &gamepad_bus); ++ device_property_read_u32(&serdev->dev, "gamepad-vid", &gamepad_vid); ++ device_property_read_u32(&serdev->dev, "gamepad-pid", &gamepad_pid); ++ device_property_read_u32(&serdev->dev, "gamepad-rev", &gamepad_rev); ++ ++ drv->input->id.bustype = (u16)gamepad_bus; ++ drv->input->id.vendor = (u16)gamepad_vid; ++ drv->input->id.product = (u16)gamepad_pid; ++ drv->input->id.version = (u16)gamepad_rev; ++ ++ __set_bit(EV_KEY, drv->input->evbit); ++ for (int i = 0; i < ARRAY_SIZE(keymap); i++) ++ input_set_capability(drv->input, EV_KEY, keymap[i]); ++ ++ __set_bit(EV_ABS, drv->input->evbit); ++ for (int i = ABS_X; i <= ABS_RZ; i++) ++ input_set_abs_params(drv->input, i, -0x580, 0x580, ++ 0, 0); ++ ++ input_set_abs_params(drv->input, ABS_HAT2X, 0, 1830, 0, 30); ++ input_set_abs_params(drv->input, ABS_HAT2Y, 0, 1830, 0, 30); ++ ++ error = input_register_device(drv->input); ++ if (error) { ++ goto err_close; ++ } ++ ++ error = rsinput_init_commands(drv); ++ if (error < 0) { ++ goto err_close; ++ } ++ ++ return 0; ++ ++err_close: ++ serdev_device_close(serdev); ++ return error; ++} ++ ++static void rsinput_remove(struct serdev_device *serdev) { ++ struct rsinput_driver *drv = serdev_device_get_drvdata(serdev); ++ ++ serdev_device_close(serdev); ++ input_unregister_device(drv->input); ++ if (drv->enable_gpio) ++ gpiod_set_value_cansleep(drv->enable_gpio, 0); ++ ++ if (drv->reset_gpio) ++ gpiod_set_value_cansleep(drv->reset_gpio, 0); ++} ++ ++static const struct of_device_id rsinput_of_match[] = { ++ { .compatible = "gamepad,rsinput" }, ++ { /* sentinel */ } ++}; ++MODULE_DEVICE_TABLE(of, rsinput_of_match); ++ ++static struct serdev_device_driver rsinput_driver = { ++ .probe = rsinput_probe, ++ .remove = rsinput_remove, ++ .driver = { ++ .name = "rsinput", ++ .of_match_table = rsinput_of_match, ++ }, ++}; ++ ++module_serdev_device_driver(rsinput_driver); ++ ++MODULE_LICENSE("GPL"); ++MODULE_DESCRIPTION("RSInput Gamepad Driver"); ++MODULE_AUTHOR("Teguh Sobirin "); +-- +2.43.0 + diff --git a/patch/kernel/archive/sm8550-6.18/0003-drm-panel-Add-panel-driver-for-Chipone-ICNA3512-base.patch b/patch/kernel/archive/sm8550-6.18/0003-drm-panel-Add-panel-driver-for-Chipone-ICNA3512-base.patch new file mode 100644 index 0000000000..48d3070a17 --- /dev/null +++ b/patch/kernel/archive/sm8550-6.18/0003-drm-panel-Add-panel-driver-for-Chipone-ICNA3512-base.patch @@ -0,0 +1,565 @@ +From e795cc2b164408cc92c11f96be268a689c7b4c1a Mon Sep 17 00:00:00 2001 +From: Teguh Sobirin +Date: Thu, 13 Feb 2025 18:25:19 +0800 +Subject: [PATCH 03/18] drm/panel: Add panel driver for Chipone ICNA3512 based + panels + +Signed-off-by: Teguh Sobirin +--- + drivers/gpu/drm/panel/Kconfig | 11 + + drivers/gpu/drm/panel/Makefile | 1 + + .../gpu/drm/panel/panel-chipone-icna3512.c | 473 ++++++++++++++++++ + include/drm/drm_mipi_dsi.h | 22 + + 4 files changed, 507 insertions(+) + create mode 100644 drivers/gpu/drm/panel/panel-chipone-icna3512.c + +diff --git a/drivers/gpu/drm/panel/Kconfig b/drivers/gpu/drm/panel/Kconfig +index 407c5f6a2..d8cf15b0b 100644 +--- a/drivers/gpu/drm/panel/Kconfig ++++ b/drivers/gpu/drm/panel/Kconfig +@@ -105,6 +105,17 @@ config DRM_PANEL_BOE_TV101WUM_LL2 + Say Y here if you want to support for BOE TV101WUM-LL2 + WUXGA PANEL DSI Video Mode panel + ++config DRM_PANEL_CHIPONE_ICNA3512 ++ tristate "Chipone ICNA3512 panel driver" ++ depends on OF ++ depends on DRM_MIPI_DSI ++ depends on BACKLIGHT_CLASS_DEVICE ++ select DRM_DISPLAY_HELPER ++ help ++ Say Y here if you want to enable support for the panels built ++ around the Chipone ICNA3512 display controller, such as some ++ Tianma panels used in AYN Odin2 Portal. ++ + config DRM_PANEL_EBBG_FT8719 + tristate "EBBG FT8719 panel driver" + depends on OF +diff --git a/drivers/gpu/drm/panel/Makefile b/drivers/gpu/drm/panel/Makefile +index 3615a761b..171843de9 100644 +--- a/drivers/gpu/drm/panel/Makefile ++++ b/drivers/gpu/drm/panel/Makefile +@@ -9,6 +9,7 @@ obj-$(CONFIG_DRM_PANEL_BOE_TD4320) += panel-boe-td4320.o + obj-$(CONFIG_DRM_PANEL_BOE_TH101MB31UIG002_28A) += panel-boe-th101mb31ig002-28a.o + obj-$(CONFIG_DRM_PANEL_BOE_TV101WUM_LL2) += panel-boe-tv101wum-ll2.o + obj-$(CONFIG_DRM_PANEL_BOE_TV101WUM_NL6) += panel-boe-tv101wum-nl6.o ++obj-$(CONFIG_DRM_PANEL_CHIPONE_ICNA3512) += panel-chipone-icna3512.o + obj-$(CONFIG_DRM_PANEL_DSI_CM) += panel-dsi-cm.o + obj-$(CONFIG_DRM_PANEL_LVDS) += panel-lvds.o + obj-$(CONFIG_DRM_PANEL_SIMPLE) += panel-simple.o +diff --git a/drivers/gpu/drm/panel/panel-chipone-icna3512.c b/drivers/gpu/drm/panel/panel-chipone-icna3512.c +new file mode 100644 +index 000000000..cbda976df +--- /dev/null ++++ b/drivers/gpu/drm/panel/panel-chipone-icna3512.c +@@ -0,0 +1,473 @@ ++// SPDX-License-Identifier: GPL-2.0-only ++/* ++ * Chipone ICNA3512 Driver IC panels driver ++ * ++ * Copyright (c) 2025 Teguh Sobirin ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include