From 9f84df429b983b7058a35dd412f73bfabc8d2ba3 Mon Sep 17 00:00:00 2001 From: spycat88 Date: Sat, 16 Aug 2025 15:17:33 +0100 Subject: [PATCH] SM8550: add initial support for AYANEO Pocket DMG --- .../devices/SM8550/bootloader/LinuxLoader.cfg | 1 + .../ROCKNIX/devices/SM8550/bootloader/grub | 15 +- .../usr/lib/udev/hwdb.d/10-ayaneo.hwdb | 8 + .../devices/SM8550/linux/linux.aarch64.conf | 1 + projects/ROCKNIX/devices/SM8550/options | 2 +- .../devices/SM8550/packages/u-boot/package.mk | 2 + ...12-Add-AYANEO-Pocket-DMG-Device-Tree.patch | 665 +++++++++++++++++ ...pu-panel-add-Pocket-DMG-panel-driver.patch | 701 ++++++++++++++++++ ...64--dts--qcom--Add-AYANEO-Pocket-DMG.patch | 59 ++ 9 files changed, 1451 insertions(+), 3 deletions(-) create mode 100644 projects/ROCKNIX/devices/SM8550/filesystem/usr/lib/udev/hwdb.d/10-ayaneo.hwdb create mode 100644 projects/ROCKNIX/devices/SM8550/packages/u-boot/patches/0012-Add-AYANEO-Pocket-DMG-Device-Tree.patch create mode 100644 projects/ROCKNIX/devices/SM8550/patches/linux/0052-gpu-panel-add-Pocket-DMG-panel-driver.patch create mode 100644 projects/ROCKNIX/devices/SM8550/patches/linux/0212_arm64--dts--qcom--Add-AYANEO-Pocket-DMG.patch diff --git a/projects/ROCKNIX/devices/SM8550/bootloader/LinuxLoader.cfg b/projects/ROCKNIX/devices/SM8550/bootloader/LinuxLoader.cfg index a8963fd288..f5e8238411 100644 --- a/projects/ROCKNIX/devices/SM8550/bootloader/LinuxLoader.cfg +++ b/projects/ROCKNIX/devices/SM8550/bootloader/LinuxLoader.cfg @@ -12,5 +12,6 @@ Image = "/boot/u-boot-nodtb.bin" initrd = "/boot/u-boot-nodtb.bin" devicetree = "/boot/u-boot-odin2.dtb" #devicetree = "/boot/u-boot-pocket-ace.dtb" +#devicetree = "/boot/u-boot-pocket-dmg.dtb" #devicetree = "/boot/u-boot-pocket-evo.dtb" cmdline = "nodtbo" diff --git a/projects/ROCKNIX/devices/SM8550/bootloader/grub b/projects/ROCKNIX/devices/SM8550/bootloader/grub index 68fd5fb1ba..e86d0b66f2 100755 --- a/projects/ROCKNIX/devices/SM8550/bootloader/grub +++ b/projects/ROCKNIX/devices/SM8550/bootloader/grub @@ -63,12 +63,18 @@ menuentry 'AYANEO Pocket ACE' \$menuentry_id_option 'pocketace' { linux /KERNEL boot=LABEL=${DISTRO_BOOTLABEL} disk=LABEL=${DISTRO_DISKLABEL} grub_portable ${EXTRA_CMDLINE} devicetree /${DEVICE_DTB[3]}.dtb } -menuentry 'AYANEO Pocket EVO' \$menuentry_id_option 'pocketevo' { +menuentry 'AYANEO Pocket DMG' \$menuentry_id_option 'pocketdmg' { savedefault search --set -f /KERNEL linux /KERNEL boot=LABEL=${DISTRO_BOOTLABEL} disk=LABEL=${DISTRO_DISKLABEL} grub_portable ${EXTRA_CMDLINE} devicetree /${DEVICE_DTB[4]}.dtb } +menuentry 'AYANEO Pocket EVO' \$menuentry_id_option 'pocketevo' { + savedefault + search --set -f /KERNEL + linux /KERNEL boot=LABEL=${DISTRO_BOOTLABEL} disk=LABEL=${DISTRO_DISKLABEL} grub_portable ${EXTRA_CMDLINE} + devicetree /${DEVICE_DTB[5]}.dtb +} menuentry 'AYN Odin2 RECOVERY' \$menuentry_id_option 'odin2-recovery' { search --set -f /KERNEL @@ -90,10 +96,15 @@ menuentry 'AYANEO Pocket ACE RECOVERY' \$menuentry_id_option 'pocketace-recovery linux /KERNEL boot=LABEL=${DISTRO_BOOTLABEL} disk=LABEL=${DISTRO_DISKLABEL} grub_portable ${EXTRA_CMDLINE} recovery devicetree /${DEVICE_DTB[3]}.dtb } -menuentry 'AYANEO Pocket EVO RECOVERY' \$menuentry_id_option 'pocketevo-recovery' { +menuentry 'AYANEO Pocket DMG RECOVERY' \$menuentry_id_option 'pocketdmg-recovery' { search --set -f /KERNEL linux /KERNEL boot=LABEL=${DISTRO_BOOTLABEL} disk=LABEL=${DISTRO_DISKLABEL} grub_portable ${EXTRA_CMDLINE} recovery devicetree /${DEVICE_DTB[4]}.dtb } +menuentry 'AYANEO Pocket EVO RECOVERY' \$menuentry_id_option 'pocketevo-recovery' { + search --set -f /KERNEL + linux /KERNEL boot=LABEL=${DISTRO_BOOTLABEL} disk=LABEL=${DISTRO_DISKLABEL} grub_portable ${EXTRA_CMDLINE} recovery + devicetree /${DEVICE_DTB[5]}.dtb +} EOF diff --git a/projects/ROCKNIX/devices/SM8550/filesystem/usr/lib/udev/hwdb.d/10-ayaneo.hwdb b/projects/ROCKNIX/devices/SM8550/filesystem/usr/lib/udev/hwdb.d/10-ayaneo.hwdb new file mode 100644 index 0000000000..3adef1dad6 --- /dev/null +++ b/projects/ROCKNIX/devices/SM8550/filesystem/usr/lib/udev/hwdb.d/10-ayaneo.hwdb @@ -0,0 +1,8 @@ +evdev:name:AYANEO Controller* + KEYBOARD_KEY_90001=btn_east # was btn_south + KEYBOARD_KEY_90002=btn_south # was btn_east + +evdev:name:AYANEO DEVICE* + KEYBOARD_KEY_70068=volumeup + KEYBOARD_KEY_70069=volumedown + KEYBOARD_KEY_70073=mode diff --git a/projects/ROCKNIX/devices/SM8550/linux/linux.aarch64.conf b/projects/ROCKNIX/devices/SM8550/linux/linux.aarch64.conf index e6f169cb6f..e567aad828 100644 --- a/projects/ROCKNIX/devices/SM8550/linux/linux.aarch64.conf +++ b/projects/ROCKNIX/devices/SM8550/linux/linux.aarch64.conf @@ -4247,6 +4247,7 @@ CONFIG_DRM_PANEL=y # # CONFIG_DRM_PANEL_ABT_Y030XX067A is not set CONFIG_DRM_PANEL_AR06_4INCH=y +CONFIG_DRM_PANEL_AR02_3INCH=y # CONFIG_DRM_PANEL_ARM_VERSATILE is not set # CONFIG_DRM_PANEL_ASUS_Z00T_TM5P5_NT35596 is not set # CONFIG_DRM_PANEL_AUO_A030JTN01 is not set diff --git a/projects/ROCKNIX/devices/SM8550/options b/projects/ROCKNIX/devices/SM8550/options index b7e2c49244..991c49f86d 100644 --- a/projects/ROCKNIX/devices/SM8550/options +++ b/projects/ROCKNIX/devices/SM8550/options @@ -25,7 +25,7 @@ esac PARTITION_TABLE="gpt" - DEVICE_DTB=("qcs8550-ayn-odin2portal" "qcs8550-ayn-odin2" "qcs8550-ayn-odin2mini" "qcs8550-ayaneo-pocketace" "qcs8550-ayaneo-pocketevo") + DEVICE_DTB=("qcs8550-ayn-odin2portal" "qcs8550-ayn-odin2" "qcs8550-ayn-odin2mini" "qcs8550-ayaneo-pocketace" "qcs8550-ayaneo-pocketdmg" "qcs8550-ayaneo-pocketevo") HW_CPU="Snapdragon 8 Gen2" # Kernel target diff --git a/projects/ROCKNIX/devices/SM8550/packages/u-boot/package.mk b/projects/ROCKNIX/devices/SM8550/packages/u-boot/package.mk index 8b0b532f07..ae4038766f 100644 --- a/projects/ROCKNIX/devices/SM8550/packages/u-boot/package.mk +++ b/projects/ROCKNIX/devices/SM8550/packages/u-boot/package.mk @@ -26,6 +26,7 @@ make_target() { DEBUG=${PKG_DEBUG} CROSS_COMPILE="${TARGET_KERNEL_PREFIX}" LDFLAGS="" ARCH=arm _python_sysroot="${TOOLCHAIN}" _python_prefix=/ _python_exec_prefix=/ make DEVICE_TREE=qcom/qcs8550-ayn-odin2-common HOSTCC="${HOST_CC}" HOSTCFLAGS="-I${TOOLCHAIN}/include" HOSTLDFLAGS="${HOST_LDFLAGS}" CONFIG_MKIMAGE_DTC_PATH="scripts/dtc/dtc" DEBUG=${PKG_DEBUG} CROSS_COMPILE="${TARGET_KERNEL_PREFIX}" LDFLAGS="" ARCH=arm _python_sysroot="${TOOLCHAIN}" _python_prefix=/ _python_exec_prefix=/ make DEVICE_TREE=qcom/qcs8550-ayaneo-pocket-ace HOSTCC="${HOST_CC}" HOSTCFLAGS="-I${TOOLCHAIN}/include" HOSTLDFLAGS="${HOST_LDFLAGS}" CONFIG_MKIMAGE_DTC_PATH="scripts/dtc/dtc" + DEBUG=${PKG_DEBUG} CROSS_COMPILE="${TARGET_KERNEL_PREFIX}" LDFLAGS="" ARCH=arm _python_sysroot="${TOOLCHAIN}" _python_prefix=/ _python_exec_prefix=/ make DEVICE_TREE=qcom/qcs8550-ayaneo-pocket-dmg HOSTCC="${HOST_CC}" HOSTCFLAGS="-I${TOOLCHAIN}/include" HOSTLDFLAGS="${HOST_LDFLAGS}" CONFIG_MKIMAGE_DTC_PATH="scripts/dtc/dtc" DEBUG=${PKG_DEBUG} CROSS_COMPILE="${TARGET_KERNEL_PREFIX}" LDFLAGS="" ARCH=arm _python_sysroot="${TOOLCHAIN}" _python_prefix=/ _python_exec_prefix=/ make DEVICE_TREE=qcom/qcs8550-ayaneo-pocket-evo HOSTCC="${HOST_CC}" HOSTCFLAGS="-I${TOOLCHAIN}/include" HOSTLDFLAGS="${HOST_LDFLAGS}" CONFIG_MKIMAGE_DTC_PATH="scripts/dtc/dtc" } @@ -38,5 +39,6 @@ makeinstall_target() { cp -av u-boot-nodtb.bin ${INSTALL}/usr/share/bootloader/boot cp -av dts/upstream/src/arm64/qcom/qcs8550-ayn-odin2-common.dtb ${INSTALL}/usr/share/bootloader/boot/u-boot-odin2.dtb cp -av dts/upstream/src/arm64/qcom/qcs8550-ayaneo-pocket-ace.dtb ${INSTALL}/usr/share/bootloader/boot/u-boot-pocket-ace.dtb + cp -av dts/upstream/src/arm64/qcom/qcs8550-ayaneo-pocket-dmg.dtb ${INSTALL}/usr/share/bootloader/boot/u-boot-pocket-dmg.dtb cp -av dts/upstream/src/arm64/qcom/qcs8550-ayaneo-pocket-evo.dtb ${INSTALL}/usr/share/bootloader/boot/u-boot-pocket-evo.dtb } diff --git a/projects/ROCKNIX/devices/SM8550/packages/u-boot/patches/0012-Add-AYANEO-Pocket-DMG-Device-Tree.patch b/projects/ROCKNIX/devices/SM8550/packages/u-boot/patches/0012-Add-AYANEO-Pocket-DMG-Device-Tree.patch new file mode 100644 index 0000000000..3e586fd28e --- /dev/null +++ b/projects/ROCKNIX/devices/SM8550/packages/u-boot/patches/0012-Add-AYANEO-Pocket-DMG-Device-Tree.patch @@ -0,0 +1,665 @@ +diff --git a/dts/upstream/src/arm64/qcom/qcs8550-ayaneo-pocket-dmg.dts b/dts/upstream/src/arm64/qcom/qcs8550-ayaneo-pocket-dmg.dts +new file mode 100644 +index 0000000000..177dc8b93d +--- /dev/null ++++ b/dts/upstream/src/arm64/qcom/qcs8550-ayaneo-pocket-dmg.dts +@@ -0,0 +1,656 @@ ++// SPDX-License-Identifier: BSD-3-Clause ++/* ++ * Copyright (c) 2025, Teguh Sobirin. ++ */ ++/dts-v1/; ++ ++#include ++#include ++#include "qcs8550.dtsi" ++#include "pm8550.dtsi" ++#include "pm8550b.dtsi" ++#define PMK8550VE_SID 5 ++#include "pm8550ve.dtsi" ++#include "pm8550vs.dtsi" ++#include "pmk8550.dtsi" ++ ++/delete-node/ &aop_image_mem; ++/delete-node/ &aop_config_mem; ++/delete-node/ &camera_mem; ++/delete-node/ &ipa_fw_mem; ++/delete-node/ &ipa_gsi_mem; ++/delete-node/ &mpss_dsm_mem; ++/delete-node/ &mpss_mem; ++/delete-node/ &q6_mpss_dtb_mem; ++ ++/delete-node/ &cci0; ++/delete-node/ &cci1; ++/delete-node/ &cci2; ++/delete-node/ &camcc; ++/delete-node/ &remoteproc_mpss; ++ ++/ { ++ model = "AYANEO Pocket DMG"; ++ compatible = "ayaneo,pocketdmg", "qcom,qcs8550", "qcom,sm8550"; ++ ++ chassis-type = "handset"; ++ ++ aliases { ++ serial0 = &uart7; ++ }; ++ ++ chosen { ++ stdout-path = "serial0:115200n8"; ++ ++ #address-cells = <2>; ++ #size-cells = <2>; ++ ranges; ++ ++ framebuffer: framebuffer@b8000000 { ++ compatible = "simple-framebuffer"; ++ reg = <0x0 0xb8000000 0x0 0x2b00000>; ++ width = <1080>; ++ height = <1240>; ++ stride = <(1080 * 4)>; ++ format = "a8r8g8b8"; ++ rot = <1>; ++ }; ++ }; ++ ++ gpio-keys { ++ compatible = "gpio-keys"; ++ ++ pinctrl-0 = <&volume_up_n>; ++ pinctrl-names = "default"; ++ ++ key-volume-up { ++ label = "Volume Up"; ++ debounce-interval = <15>; ++ gpios = <&pm8550_gpios 6 GPIO_ACTIVE_LOW>; ++ linux,code = ; ++ linux,can-disable; ++ wakeup-source; ++ }; ++ }; ++ ++ pmic-glink { ++ compatible = "qcom,sm8550-pmic-glink", "qcom,pmic-glink"; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ orientation-gpios = <&tlmm 11 GPIO_ACTIVE_HIGH>; ++ ++ connector@0 { ++ compatible = "usb-c-connector"; ++ reg = <0>; ++ power-role = "dual"; ++ data-role = "dual"; ++ ++ ports { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ port@0 { ++ reg = <0>; ++ ++ pmic_glink_hs_in: endpoint { ++ remote-endpoint = <&usb_1_dwc3_hs>; ++ }; ++ }; ++ ++ port@1 { ++ reg = <1>; ++ ++ pmic_glink_ss_in: endpoint { ++ remote-endpoint = <&redriver_ss_out>; ++ }; ++ }; ++ }; ++ }; ++ }; ++ ++ vph_pwr: regulator-vph-pwr { ++ compatible = "regulator-fixed"; ++ regulator-name = "vph_pwr"; ++ regulator-min-microvolt = <3700000>; ++ regulator-max-microvolt = <3700000>; ++ ++ regulator-always-on; ++ regulator-boot-on; ++ }; ++ ++ reserved-memory { ++ splash_region@b8000000 { ++ reg = <0x0 0xb8000000 0x0 0x2b00000>; ++ no-map; ++ }; ++ }; ++}; ++ ++&apps_rsc { ++ regulators-0 { ++ compatible = "qcom,pm8550-rpmh-regulators"; ++ qcom,pmic-id = "b"; ++ ++ vdd-bob1-supply = <&vph_pwr>; ++ vdd-bob2-supply = <&vph_pwr>; ++ vdd-l1-l4-l10-supply = <&vreg_s6g_1p86>; ++ vdd-l2-l13-l14-supply = <&vreg_bob1>; ++ vdd-l3-supply = <&vreg_s4g_1p25>; ++ vdd-l5-l16-supply = <&vreg_bob1>; ++ vdd-l6-l7-supply = <&vreg_bob1>; ++ vdd-l8-l9-supply = <&vreg_bob1>; ++ vdd-l11-supply = <&vreg_s4g_1p25>; ++ vdd-l12-supply = <&vreg_s6g_1p86>; ++ vdd-l15-supply = <&vreg_s6g_1p86>; ++ vdd-l17-supply = <&vreg_bob2>; ++ ++ vreg_bob1: bob1 { ++ regulator-name = "vreg_bob1"; ++ regulator-min-microvolt = <3296000>; ++ regulator-max-microvolt = <3960000>; ++ regulator-initial-mode = ; ++ }; ++ ++ vreg_bob2: bob2 { ++ regulator-name = "vreg_bob2"; ++ regulator-min-microvolt = <2720000>; ++ regulator-max-microvolt = <3960000>; ++ regulator-initial-mode = ; ++ }; ++ ++ vreg_l1b_1p8: ldo1 { ++ regulator-name = "vreg_l1b_1p8"; ++ regulator-min-microvolt = <1800000>; ++ regulator-max-microvolt = <1800000>; ++ regulator-initial-mode = ; ++ }; ++ ++ vreg_l2b_3p0: ldo2 { ++ regulator-name = "vreg_l2b_3p0"; ++ regulator-min-microvolt = <3008000>; ++ regulator-max-microvolt = <3008000>; ++ regulator-initial-mode = ; ++ }; ++ ++ vreg_l5b_3p1: ldo5 { ++ regulator-name = "vreg_l5b_3p1"; ++ regulator-min-microvolt = <3104000>; ++ regulator-max-microvolt = <3104000>; ++ regulator-initial-mode = ; ++ }; ++ ++ vreg_l6b_1p8: ldo6 { ++ regulator-name = "vreg_l6b_1p8"; ++ regulator-min-microvolt = <1800000>; ++ regulator-max-microvolt = <3008000>; ++ regulator-initial-mode = ; ++ }; ++ ++ vreg_l7b_1p8: ldo7 { ++ regulator-name = "vreg_l7b_1p8"; ++ regulator-min-microvolt = <1800000>; ++ regulator-max-microvolt = <3008000>; ++ regulator-initial-mode = ; ++ }; ++ ++ vreg_l8b_1p8: ldo8 { ++ regulator-name = "vreg_l8b_1p8"; ++ regulator-min-microvolt = <1800000>; ++ regulator-max-microvolt = <3008000>; ++ regulator-initial-mode = ; ++ }; ++ ++ vreg_l9b_2p9: ldo9 { ++ regulator-name = "vreg_l9b_2p9"; ++ regulator-min-microvolt = <2960000>; ++ regulator-max-microvolt = <3008000>; ++ regulator-initial-mode = ; ++ }; ++ ++ vreg_l11b_1p2: ldo11 { ++ regulator-name = "vreg_l11b_1p2"; ++ regulator-min-microvolt = <1200000>; ++ regulator-max-microvolt = <1504000>; ++ regulator-initial-mode = ; ++ }; ++ ++ vreg_l12b_1p8: ldo12 { ++ regulator-name = "vreg_l12b_1p8"; ++ regulator-min-microvolt = <1800000>; ++ regulator-max-microvolt = <1800000>; ++ regulator-initial-mode = ; ++ }; ++ ++ vreg_l13b_3p0: ldo13 { ++ regulator-name = "vreg_l13b_3p0"; ++ regulator-min-microvolt = <3000000>; ++ regulator-max-microvolt = <3000000>; ++ regulator-initial-mode = ; ++ }; ++ ++ vreg_l14b_3p2: ldo14 { ++ regulator-name = "vreg_l14b_3p2"; ++ regulator-min-microvolt = <3200000>; ++ regulator-max-microvolt = <3200000>; ++ regulator-initial-mode = ; ++ }; ++ ++ vreg_l15b_1p8: ldo15 { ++ regulator-name = "vreg_l15b_1p8"; ++ regulator-min-microvolt = <1800000>; ++ regulator-max-microvolt = <1800000>; ++ regulator-initial-mode = ; ++ }; ++ ++ vreg_l16b_2p8: ldo16 { ++ regulator-name = "vreg_l16b_2p8"; ++ regulator-min-microvolt = <2800000>; ++ regulator-max-microvolt = <2800000>; ++ regulator-initial-mode = ; ++ }; ++ ++ vreg_l17b_2p5: ldo17 { ++ regulator-name = "vreg_l17b_2p5"; ++ regulator-min-microvolt = <2504000>; ++ regulator-max-microvolt = <2504000>; ++ regulator-initial-mode = ; ++ }; ++ }; ++ ++ regulators-1 { ++ compatible = "qcom,pm8550vs-rpmh-regulators"; ++ qcom,pmic-id = "c"; ++ ++ vdd-l1-supply = <&vreg_s4g_1p25>; ++ vdd-l2-supply = <&vreg_s4e_0p95>; ++ vdd-l3-supply = <&vreg_s4e_0p95>; ++ ++ vreg_l3c_0p9: ldo3 { ++ regulator-name = "vreg_l3c_0p9"; ++ regulator-min-microvolt = <880000>; ++ regulator-max-microvolt = <912000>; ++ regulator-initial-mode = ; ++ }; ++ }; ++ ++ regulators-2 { ++ compatible = "qcom,pm8550vs-rpmh-regulators"; ++ qcom,pmic-id = "d"; ++ ++ vdd-l1-supply = <&vreg_s4e_0p95>; ++ vdd-l2-supply = <&vreg_s4e_0p95>; ++ vdd-l3-supply = <&vreg_s4e_0p95>; ++ ++ vreg_l1d_0p88: ldo1 { ++ regulator-name = "vreg_l1d_0p88"; ++ regulator-min-microvolt = <880000>; ++ regulator-max-microvolt = <920000>; ++ regulator-initial-mode = ; ++ }; ++ }; ++ ++ regulators-3 { ++ compatible = "qcom,pm8550vs-rpmh-regulators"; ++ qcom,pmic-id = "e"; ++ ++ vdd-l1-supply = <&vreg_s4e_0p95>; ++ vdd-l2-supply = <&vreg_s4e_0p95>; ++ vdd-l3-supply = <&vreg_s4g_1p25>; ++ vdd-s4-supply = <&vph_pwr>; ++ vdd-s5-supply = <&vph_pwr>; ++ ++ vreg_s4e_0p95: smps4 { ++ regulator-name = "vreg_s4e_0p95"; ++ regulator-min-microvolt = <904000>; ++ regulator-max-microvolt = <984000>; ++ regulator-initial-mode = ; ++ }; ++ ++ vreg_s5e_1p08: smps5 { ++ regulator-name = "vreg_s5e_1p08"; ++ regulator-min-microvolt = <1010000>; ++ regulator-max-microvolt = <1120000>; ++ regulator-initial-mode = ; ++ }; ++ ++ vreg_l1e_0p88: ldo1 { ++ regulator-name = "vreg_l1e_0p88"; ++ regulator-min-microvolt = <880000>; ++ regulator-max-microvolt = <912000>; ++ regulator-initial-mode = ; ++ }; ++ ++ vreg_l2e_0p9: ldo2 { ++ regulator-name = "vreg_l2e_0p9"; ++ regulator-min-microvolt = <870000>; ++ regulator-max-microvolt = <970000>; ++ regulator-initial-mode = ; ++ }; ++ ++ vreg_l3e_1p2: ldo3 { ++ regulator-name = "vreg_l3e_1p2"; ++ regulator-min-microvolt = <1200000>; ++ regulator-max-microvolt = <1200000>; ++ regulator-initial-mode = ; ++ }; ++ }; ++ ++ regulators-4 { ++ compatible = "qcom,pm8550ve-rpmh-regulators"; ++ qcom,pmic-id = "f"; ++ ++ vdd-l1-supply = <&vreg_s4e_0p95>; ++ vdd-l2-supply = <&vreg_s4e_0p95>; ++ vdd-l3-supply = <&vreg_s4e_0p95>; ++ vdd-s4-supply = <&vph_pwr>; ++ ++ vreg_s4f_0p5: smps4 { ++ regulator-name = "vreg_s4f_0p5"; ++ regulator-min-microvolt = <300000>; ++ regulator-max-microvolt = <700000>; ++ regulator-initial-mode = ; ++ }; ++ ++ vreg_l1f_0p9: ldo1 { ++ regulator-name = "vreg_l1f_0p9"; ++ regulator-min-microvolt = <880000>; ++ regulator-max-microvolt = <912000>; ++ regulator-initial-mode = ; ++ }; ++ ++ vreg_l2f_0p88: ldo2 { ++ regulator-name = "vreg_l2f_0p88"; ++ regulator-min-microvolt = <880000>; ++ regulator-max-microvolt = <912000>; ++ regulator-initial-mode = ; ++ }; ++ ++ vreg_l3f_0p88: ldo3 { ++ regulator-name = "vreg_l3f_0p88"; ++ regulator-min-microvolt = <880000>; ++ regulator-max-microvolt = <912000>; ++ regulator-initial-mode = ; ++ }; ++ }; ++ ++ regulators-5 { ++ compatible = "qcom,pm8550vs-rpmh-regulators"; ++ qcom,pmic-id = "g"; ++ vdd-l1-supply = <&vreg_s4g_1p25>; ++ vdd-l2-supply = <&vreg_s4g_1p25>; ++ vdd-l3-supply = <&vreg_s4g_1p25>; ++ vdd-s1-supply = <&vph_pwr>; ++ vdd-s2-supply = <&vph_pwr>; ++ vdd-s3-supply = <&vph_pwr>; ++ vdd-s4-supply = <&vph_pwr>; ++ vdd-s5-supply = <&vph_pwr>; ++ vdd-s6-supply = <&vph_pwr>; ++ ++ vreg_s1g_1p25: smps1 { ++ regulator-name = "vreg_s1g_1p25"; ++ regulator-min-microvolt = <1200000>; ++ regulator-max-microvolt = <1300000>; ++ regulator-initial-mode = ; ++ }; ++ ++ vreg_s2g_0p85: smps2 { ++ regulator-name = "vreg_s2g_0p85"; ++ regulator-min-microvolt = <500000>; ++ regulator-max-microvolt = <1036000>; ++ regulator-initial-mode = ; ++ }; ++ ++ vreg_s3g_0p8: smps3 { ++ regulator-name = "vreg_s3g_0p8"; ++ regulator-min-microvolt = <300000>; ++ regulator-max-microvolt = <1004000>; ++ regulator-initial-mode = ; ++ }; ++ ++ vreg_s4g_1p25: smps4 { ++ regulator-name = "vreg_s4g_1p25"; ++ regulator-min-microvolt = <1256000>; ++ regulator-max-microvolt = <1408000>; ++ regulator-initial-mode = ; ++ }; ++ ++ vreg_s5g_0p85: smps5 { ++ regulator-name = "vreg_s5g_0p85"; ++ regulator-min-microvolt = <500000>; ++ regulator-max-microvolt = <1004000>; ++ regulator-initial-mode = ; ++ }; ++ ++ vreg_s6g_1p86: smps6 { ++ regulator-name = "vreg_s6g_1p86"; ++ regulator-min-microvolt = <1800000>; ++ regulator-max-microvolt = <2000000>; ++ regulator-initial-mode = ; ++ }; ++ ++ vreg_l1g_1p2: ldo1 { ++ regulator-name = "vreg_l1g_1p2"; ++ regulator-min-microvolt = <1128000>; ++ regulator-max-microvolt = <1272000>; ++ regulator-initial-mode = ; ++ }; ++ ++ vreg_l2g_1p2: ldo2 { ++ regulator-name = "vreg_l2g_1p2"; ++ regulator-min-microvolt = <1100000>; ++ regulator-max-microvolt = <1200000>; ++ regulator-initial-mode = ; ++ }; ++ ++ vreg_l3g_1p2: ldo3 { ++ regulator-name = "vreg_l3g_1p2"; ++ regulator-min-microvolt = <1200000>; ++ regulator-max-microvolt = <1200000>; ++ regulator-initial-mode = ; ++ }; ++ }; ++}; ++ ++&i2c_master_hub_0 { ++ status = "okay"; ++}; ++ ++&i2c_hub_2 { ++ status = "okay"; ++ ++ typec-retimer@1c { ++ compatible = "onnn,nb7vpq904m"; ++ reg = <0x1c>; ++ vcc-supply = <&vreg_l15b_1p8>; ++ ++ retimer-switch; ++ orientation-switch; ++ ++ ports { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ port@0 { ++ reg = <0>; ++ ++ redriver_ss_out: endpoint { ++ remote-endpoint = <&pmic_glink_ss_in>; ++ }; ++ }; ++ ++ port@1 { ++ reg = <1>; ++ ++ redriver_ss_in: endpoint { ++ data-lanes = <3 2 1 0>; ++ remote-endpoint = <&usb_dp_qmpphy_out>; ++ }; ++ }; ++ }; ++ }; ++}; ++ ++&gpi_dma1 { ++ status = "okay"; ++}; ++ ++&gpi_dma2 { ++ status = "okay"; ++}; ++ ++&pcie0 { ++ perst-gpios = <&tlmm 94 GPIO_ACTIVE_LOW>; ++ wake-gpios = <&tlmm 96 GPIO_ACTIVE_HIGH>; ++ max-link-speed = <2>; ++ ++ pinctrl-0 = <&pcie0_default_state>; ++ pinctrl-names = "default"; ++ ++ status = "okay"; ++}; ++ ++&pcie0_phy { ++ vdda-phy-supply = <&vreg_l1e_0p88>; ++ vdda-pll-supply = <&vreg_l3e_1p2>; ++ ++ status = "okay"; ++}; ++ ++&pm8550_gpios { ++ sdc2_card_det_n: sdc2-card-det-n-state { ++ pins = "gpio12"; ++ function = "normal"; ++ input-enable; ++ output-disable; ++ bias-pull-up; ++ power-source = <1>; /* 1.8 V */ ++ }; ++ ++ volume_up_n: volume-up-n-state { ++ pins = "gpio6"; ++ function = "normal"; ++ power-source = <1>; ++ bias-pull-up; ++ input-enable; ++ }; ++}; ++ ++&pm8550b_eusb2_repeater { ++ vdd18-supply = <&vreg_l15b_1p8>; ++ vdd3-supply = <&vreg_l5b_3p1>; ++}; ++ ++&pon_pwrkey { ++ status = "okay"; ++}; ++ ++&pon_resin { ++ linux,code = ; ++ ++ status = "okay"; ++}; ++ ++&qupv3_id_0 { ++ status = "okay"; ++}; ++ ++&qupv3_id_1 { ++ status = "okay"; ++}; ++ ++&sdhc_2 { ++ cd-gpios = <&pm8550_gpios 12 GPIO_ACTIVE_LOW>; ++ ++ pinctrl-0 = <&sdc2_default>, <&sdc2_card_det_n>; ++ pinctrl-1 = <&sdc2_sleep>, <&sdc2_card_det_n>; ++ pinctrl-names = "default", "sleep"; ++ ++ vmmc-supply = <&vreg_l9b_2p9>; ++ vqmmc-supply = <&vreg_l8b_1p8>; ++ ++ bus-width = <4>; ++ no-sdio; ++ no-mmc; ++ ++ status = "okay"; ++}; ++ ++&sleep_clk { ++ clock-frequency = <32764>; ++}; ++ ++&tlmm { ++ gpio-reserved-ranges = <32 8>; ++ ++ usb0_sbu_default: usb0-sbu-state { ++ oe-n-pins { ++ pins = "gpio140"; ++ function = "gpio"; ++ bias-disable; ++ drive-strength = <16>; ++ output-high; ++ }; ++ ++ sel-pins { ++ pins = "gpio141"; ++ function = "gpio"; ++ bias-disable; ++ drive-strength = <16>; ++ }; ++ }; ++}; ++ ++&uart7 { ++ status = "okay"; ++}; ++ ++&ufs_mem_hc { ++ reset-gpios = <&tlmm 210 GPIO_ACTIVE_LOW>; ++ ++ vcc-supply = <&vreg_l17b_2p5>; ++ vcc-max-microamp = <1300000>; ++ vccq-supply = <&vreg_l1g_1p2>; ++ vccq-max-microamp = <1200000>; ++ vdd-hba-supply = <&vreg_l3g_1p2>; ++ ++ status = "okay"; ++}; ++ ++&ufs_mem_phy { ++ vdda-phy-supply = <&vreg_l1d_0p88>; ++ vdda-pll-supply = <&vreg_l3e_1p2>; ++ ++ status = "okay"; ++}; ++ ++&usb_1 { ++ status = "okay"; ++}; ++ ++&usb_1_dwc3_hs { ++ remote-endpoint = <&pmic_glink_hs_in>; ++}; ++ ++&usb_1_hsphy { ++ phys = <&pm8550b_eusb2_repeater>; ++ ++ vdd-supply = <&vreg_l1e_0p88>; ++ vdda12-supply = <&vreg_l3e_1p2>; ++ ++ status = "okay"; ++}; ++ ++&usb_dp_qmpphy { ++ vdda-phy-supply = <&vreg_l3e_1p2>; ++ vdda-pll-supply = <&vreg_l3f_0p88>; ++ ++ status = "okay"; ++}; ++ ++&usb_dp_qmpphy_out { ++ remote-endpoint = <&redriver_ss_in>; ++}; ++ ++&xo_board { ++ clock-frequency = <76800000>; ++}; +-- +2.43.0 + diff --git a/projects/ROCKNIX/devices/SM8550/patches/linux/0052-gpu-panel-add-Pocket-DMG-panel-driver.patch b/projects/ROCKNIX/devices/SM8550/patches/linux/0052-gpu-panel-add-Pocket-DMG-panel-driver.patch new file mode 100644 index 0000000000..46162289e1 --- /dev/null +++ b/projects/ROCKNIX/devices/SM8550/patches/linux/0052-gpu-panel-add-Pocket-DMG-panel-driver.patch @@ -0,0 +1,701 @@ +From 1f6b8b9a7112f1c1c50a6e0cc744c92e16da80ea Mon Sep 17 00:00:00 2001 +From: Philippe Simons +Date: Sun, 3 Aug 2025 14:24:50 +0200 +Subject: [PATCH] gpu: panel: add Pocket DMG panel driver + +--- + drivers/gpu/drm/panel/Kconfig | 10 + + drivers/gpu/drm/panel/Makefile | 1 + + drivers/gpu/drm/panel/panel-ar02-3inch.c | 647 +++++++++++++++++++++++ + 3 files changed, 658 insertions(+) + create mode 100644 drivers/gpu/drm/panel/panel-ar02-3inch.c + +diff --git a/drivers/gpu/drm/panel/Kconfig b/drivers/gpu/drm/panel/Kconfig +index 2b0c4bab517c..86f3c0178805 100644 +--- a/drivers/gpu/drm/panel/Kconfig ++++ b/drivers/gpu/drm/panel/Kconfig +@@ -27,6 +27,16 @@ config DRM_PANEL_AR06_4INCH + Say Y here if you want to enable support for Ayaneo Pocket ACE + 1080x1620 60hz Panel. + ++config DRM_PANEL_AR02_3INCH ++ tristate "Ayaneo Pocket DMG 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 Ayaneo Pocket DMG ++ 1080x1240 60hz Panel. ++ + config DRM_PANEL_ARM_VERSATILE + tristate "ARM Versatile panel driver" + depends on OF +diff --git a/drivers/gpu/drm/panel/Makefile b/drivers/gpu/drm/panel/Makefile +index e2e83723083e..630f5f22e40f 100644 +--- a/drivers/gpu/drm/panel/Makefile ++++ b/drivers/gpu/drm/panel/Makefile +@@ -1,6 +1,7 @@ + # SPDX-License-Identifier: GPL-2.0 + obj-$(CONFIG_DRM_PANEL_ABT_Y030XX067A) += panel-abt-y030xx067a.o + obj-$(CONFIG_DRM_PANEL_AR06_4INCH) += panel-ar06-4inch.o ++obj-$(CONFIG_DRM_PANEL_AR02_3INCH) += panel-ar02-3inch.o + obj-$(CONFIG_DRM_PANEL_ARM_VERSATILE) += panel-arm-versatile.o + obj-$(CONFIG_DRM_PANEL_ASUS_Z00T_TM5P5_NT35596) += panel-asus-z00t-tm5p5-n35596.o + obj-$(CONFIG_DRM_PANEL_AUO_A030JTN01) += panel-auo-a030jtn01.o +diff --git a/drivers/gpu/drm/panel/panel-ar02-3inch.c b/drivers/gpu/drm/panel/panel-ar02-3inch.c +new file mode 100644 +index 000000000000..67151480f1aa +--- /dev/null ++++ b/drivers/gpu/drm/panel/panel-ar02-3inch.c +@@ -0,0 +1,647 @@ ++// SPDX-License-Identifier: GPL-2.0-only ++// Copyright (c) 2025 FIXME ++// Generated with linux-mdss-dsi-panel-driver-generator from vendor device tree: ++// Copyright (c) 2013, The Linux Foundation. All rights reserved. (FIXME) ++ ++#include ++#include ++#include ++#include ++#include ++ ++#include ++#include ++#include ++#include ++ ++struct ar02_3inch { ++ struct drm_panel panel; ++ struct mipi_dsi_device *dsi; ++ struct gpio_desc *reset_gpio; ++ struct regulator_bulk_data *supplies; ++ enum drm_panel_orientation orientation; ++}; ++ ++static const struct regulator_bulk_data panel_supplies[] = { ++ { .supply = "avdd" }, ++ { .supply = "vci" }, ++ { .supply = "vddio" }, ++}; ++ ++static inline struct ar02_3inch *to_ar02_3inch(struct drm_panel *panel) ++{ ++ return container_of(panel, struct ar02_3inch, panel); ++} ++ ++static void ar02_3inch_reset(struct ar02_3inch *ctx) ++{ ++ gpiod_set_value_cansleep(ctx->reset_gpio, 0); ++ usleep_range(10000, 11000); ++ gpiod_set_value_cansleep(ctx->reset_gpio, 1); ++ usleep_range(10000, 11000); ++ gpiod_set_value_cansleep(ctx->reset_gpio, 0); ++ msleep(55); ++} ++ ++static int ar02_3inch_on(struct ar02_3inch *ctx) ++{ ++ struct mipi_dsi_multi_context dsi_ctx = { .dsi = ctx->dsi }; ++ ++ ctx->dsi->mode_flags |= MIPI_DSI_MODE_LPM; ++ ++ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x35, 0x00); ++ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x53, 0x20); ++ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x51, 0x03, 0xff); ++ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0x6f, 0x02); ++ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xf0, 0xaa, 0x10); ++ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xb0, ++ 0x01, 0x36, 0x87, 0x00, 0x87); ++ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xb1, ++ 0x01, 0x2d, 0x00, 0x0e, 0x00, 0x0e, 0x01); ++ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xb2, ++ 0x01, 0x2d, 0x00, 0x0e, 0x00, 0x0e, 0x01); ++ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xb6, 0x40); ++ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xb7, 0x84); ++ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xbd, 0x01); ++ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xc1, 0x00, 0x05, 0x00, 0x05); ++ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xc3, 0x11, 0x55); ++ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xc5, 0x10); ++ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xcf, 0x0b, 0x0e, 0x0b, 0x1f); ++ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xd0, ++ 0x80, 0x13, 0x50, 0x14, 0x14, 0x00, 0x29, ++ 0x2d, 0x19, 0x00, 0x00, 0x00, 0x2d, 0x19, ++ 0x33, 0x00, 0x00); ++ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xc0, 0x00); ++ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xf0, 0xaa, 0x12); ++ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xb1, 0x33); ++ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xb5, 0xa7, 0xa7); ++ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xb6, 0xd7, 0xd7); ++ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xb7, 0x30, 0x30); ++ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xb8, 0x20, 0x20); ++ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xb9, 0x38, 0x37, 0x37); ++ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xba, 0x38, 0x1b); ++ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xd2, ++ 0x0f, 0x00, 0x00, 0x02, 0x04, 0x02, 0x04, ++ 0x06, 0x00, 0x00, 0x02, 0x02, 0x00); ++ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xc4, 0x00); ++ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xc7, 0x00, 0x54, 0xa5, 0x02); ++ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xcf, 0x03, 0x28, 0x00, 0x11); ++ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xf0, 0xaa, 0x11); ++ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xc2, ++ 0x10, 0x00, 0x60, 0x02, 0x11, 0x12, 0x13, ++ 0x14, 0x15, 0x16); ++ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xc3, ++ 0x00, 0x00, 0x00, 0x08, 0x00, 0xaa, 0x01, ++ 0xff, 0x02, 0xff, 0x03, 0xff); ++ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xc4, ++ 0x00, 0x0a, 0x00, 0x0a, 0x00, 0x0a, 0x00, ++ 0x0a, 0x00, 0x0a, 0x00, 0x0a, 0x00, 0x0a, ++ 0x00, 0x0a, 0x00, 0x0a, 0x80, 0x28, 0x80, ++ 0x28); ++ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xf0, 0xaa, 0x13); ++ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xbf, 0x05); ++ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xb0, ++ 0x00, 0x00, 0x01, 0x09, 0x01, 0x41, 0x01, ++ 0x5f, 0x01, 0x74, 0x01, 0x93, 0x01, 0xa9, ++ 0x01, 0xbb); ++ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xb1, ++ 0x01, 0xca, 0x01, 0xda, 0x01, 0xea, 0x01, ++ 0xf9, 0x02, 0x08, 0x02, 0x22, 0x02, 0x3b, ++ 0x02, 0x51); ++ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xb2, ++ 0x02, 0x65, 0x02, 0x7a, 0x02, 0x9e, 0x02, ++ 0xc0, 0x02, 0xdd, 0x03, 0x1a, 0x03, 0x4e, ++ 0x03, 0x85); ++ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xb3, 0x03, 0xbd); ++ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xb4, ++ 0x00, 0x00, 0x00, 0xf9, 0x01, 0x30, 0x01, ++ 0x4e, 0x01, 0x63, 0x01, 0x81, 0x01, 0x97, ++ 0x01, 0xa9); ++ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xb5, ++ 0x01, 0xb8, 0x01, 0xc8, 0x01, 0xd7, 0x01, ++ 0xe6, 0x01, 0xf4, 0x02, 0x0e, 0x02, 0x26, ++ 0x02, 0x3c); ++ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xb6, ++ 0x02, 0x50, 0x02, 0x63, 0x02, 0x87, 0x02, ++ 0xa8, 0x02, 0xc7, 0x02, 0xff, 0x03, 0x36, ++ 0x03, 0x69); ++ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xb7, 0x03, 0x9b); ++ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xb8, ++ 0x00, 0x00, 0x01, 0x51, 0x01, 0x84, 0x01, ++ 0x9e, 0x01, 0xb0, 0x01, 0xc9, 0x01, 0xdc, ++ 0x01, 0xea); ++ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xb9, ++ 0x01, 0xf6, 0x02, 0x01, 0x02, 0x0e, 0x02, ++ 0x1b, 0x02, 0x2a, 0x02, 0x44, 0x02, 0x5e, ++ 0x02, 0x76); ++ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xba, ++ 0x02, 0x8b, 0x02, 0xa0, 0x02, 0xc6, 0x02, ++ 0xe9, 0x03, 0x07, 0x03, 0x44, 0x03, 0x7e, ++ 0x03, 0xb5); ++ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xbb, 0x03, 0xec); ++ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xbf, 0x04); ++ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xb0, ++ 0x00, 0x00, 0x01, 0x02, 0x01, 0x37, 0x01, ++ 0x53, 0x01, 0x67, 0x01, 0x83, 0x01, 0x98, ++ 0x01, 0xa9); ++ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xb1, ++ 0x01, 0xb7, 0x01, 0xc7, 0x01, 0xd4, 0x01, ++ 0xe1, 0x01, 0xef, 0x02, 0x0a, 0x02, 0x21, ++ 0x02, 0x38); ++ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xb2, ++ 0x02, 0x4b, 0x02, 0x5e, 0x02, 0x80, 0x02, ++ 0xa0, 0x02, 0xbb, 0x02, 0xf2, 0x03, 0x23, ++ 0x03, 0x52); ++ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xb3, 0x03, 0x82); ++ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xb4, ++ 0x00, 0x00, 0x00, 0xe9, 0x01, 0x1f, 0x01, ++ 0x3c, 0x01, 0x51, 0x01, 0x6f, 0x01, 0x85, ++ 0x01, 0x97); ++ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xb5, ++ 0x01, 0xa6, 0x01, 0xb5, 0x01, 0xc3, 0x01, ++ 0xd1, 0x01, 0xde, 0x01, 0xf8, 0x02, 0x0e, ++ 0x02, 0x24); ++ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xb6, ++ 0x02, 0x37, 0x02, 0x4a, 0x02, 0x6b, 0x02, ++ 0x8c, 0x02, 0xa6, 0x02, 0xdb, 0x03, 0x0b, ++ 0x03, 0x39); ++ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xb7, 0x03, 0x67); ++ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xb8, ++ 0x00, 0x00, 0x01, 0x38, 0x01, 0x6d, 0x01, ++ 0x88, 0x01, 0x9b, 0x01, 0xb7, 0x01, 0xca, ++ 0x01, 0xda); ++ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xb9, ++ 0x01, 0xe7, 0x01, 0xf4, 0x01, 0xfe, 0x02, ++ 0x09, 0x02, 0x13, 0x02, 0x2d, 0x02, 0x44, ++ 0x02, 0x5c); ++ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xba, ++ 0x02, 0x70, 0x02, 0x85, 0x02, 0xa8, 0x02, ++ 0xc9, 0x02, 0xe4, 0x03, 0x1d, 0x03, 0x52, ++ 0x03, 0x83); ++ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xbb, 0x03, 0xb2); ++ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xbf, 0x03); ++ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xb0, ++ 0x00, 0x00, 0x00, 0xd3, 0x01, 0x0c, 0x01, ++ 0x2c, 0x01, 0x43, 0x01, 0x64, 0x01, 0x7d, ++ 0x01, 0x92); ++ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xb1, ++ 0x01, 0xa3, 0x01, 0xb2, 0x01, 0xc0, 0x01, ++ 0xce, 0x01, 0xda, 0x01, 0xf2, 0x02, 0x09, ++ 0x02, 0x1d); ++ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xb2, ++ 0x02, 0x30, 0x02, 0x42, 0x02, 0x62, 0x02, ++ 0x80, 0x02, 0x9b, 0x02, 0xcb, 0x02, 0xf9, ++ 0x03, 0x23); ++ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xb3, 0x03, 0x4d); ++ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xb4, ++ 0x00, 0x00, 0x00, 0xc4, 0x00, 0xfc, 0x01, ++ 0x1c, 0x01, 0x32, 0x01, 0x54, 0x01, 0x6d, ++ 0x01, 0x81); ++ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xb5, ++ 0x01, 0x92, 0x01, 0xa1, 0x01, 0xae, 0x01, ++ 0xbc, 0x01, 0xc9, 0x01, 0xe0, 0x01, 0xf6, ++ 0x02, 0x0a); ++ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xb6, ++ 0x02, 0x1d, 0x02, 0x2f, 0x02, 0x4e, 0x02, ++ 0x6b, 0x02, 0x85, 0x02, 0xb6, 0x02, 0xe2, ++ 0x03, 0x0b); ++ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xb7, 0x03, 0x33); ++ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xb8, ++ 0x00, 0x00, 0x01, 0x08, 0x01, 0x43, 0x01, ++ 0x62, 0x01, 0x79, 0x01, 0x9a, 0x01, 0xb2, ++ 0x01, 0xc5); ++ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xb9, ++ 0x01, 0xd5, 0x01, 0xe3, 0x01, 0xef, 0x01, ++ 0xf9, 0x02, 0x02, 0x02, 0x16, 0x02, 0x2c, ++ 0x02, 0x40); ++ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xba, ++ 0x02, 0x54, 0x02, 0x67, 0x02, 0x89, 0x02, ++ 0xa8, 0x02, 0xc4, 0x02, 0xf5, 0x03, 0x27, ++ 0x03, 0x52); ++ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xbb, 0x03, 0x7b); ++ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xbf, 0x02); ++ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xb0, ++ 0x00, 0x00, 0x00, 0x9d, 0x00, 0xd3, 0x00, ++ 0xf2, 0x01, 0x09, 0x01, 0x2b, 0x01, 0x45, ++ 0x01, 0x5a); ++ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xb1, ++ 0x01, 0x6d, 0x01, 0x7d, 0x01, 0x8b, 0x01, ++ 0x98, 0x01, 0xa4, 0x01, 0xb8, 0x01, 0xcb, ++ 0x01, 0xdc); ++ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xb2, ++ 0x01, 0xed, 0x01, 0xfc, 0x02, 0x19, 0x02, ++ 0x32, 0x02, 0x48, 0x02, 0x71, 0x02, 0x96, ++ 0x02, 0xb6); ++ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xb3, 0x02, 0xd5); ++ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xb4, ++ 0x00, 0x00, 0x00, 0x9c, 0x00, 0xcf, 0x00, ++ 0xec, 0x01, 0x01, 0x01, 0x21, 0x01, 0x39, ++ 0x01, 0x4c); ++ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xb5, ++ 0x01, 0x5d, 0x01, 0x6c, 0x01, 0x79, 0x01, ++ 0x85, 0x01, 0x90, 0x01, 0xa4, 0x01, 0xb7, ++ 0x01, 0xc9); ++ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xb6, ++ 0x01, 0xda, 0x01, 0xe8, 0x02, 0x04, 0x02, ++ 0x1d, 0x02, 0x33, 0x02, 0x5b, 0x02, 0x80, ++ 0x02, 0xa0); ++ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xb7, 0x02, 0xbe); ++ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xb8, ++ 0x00, 0x00, 0x00, 0xd0, 0x01, 0x09, 0x01, ++ 0x28, 0x01, 0x3f, 0x01, 0x60, 0x01, 0x79, ++ 0x01, 0x8e); ++ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xb9, ++ 0x01, 0x9f, 0x01, 0xae, 0x01, 0xbb, 0x01, ++ 0xc7, 0x01, 0xd2, 0x01, 0xe4, 0x01, 0xf2, ++ 0x02, 0x00); ++ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xba, ++ 0x02, 0x0e, 0x02, 0x1d, 0x02, 0x3b, 0x02, ++ 0x55, 0x02, 0x6d, 0x02, 0x98, 0x02, 0xbe, ++ 0x02, 0xe0); ++ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xbb, 0x02, 0xff); ++ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xbf, 0x01); ++ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xb0, ++ 0x00, 0x00, 0x00, 0x6e, 0x00, 0x96, 0x00, ++ 0xad, 0x00, 0xbe, 0x00, 0xd9, 0x00, 0xec, ++ 0x00, 0xfd); ++ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xb1, ++ 0x01, 0x0b, 0x01, 0x17, 0x01, 0x22, 0x01, ++ 0x2d, 0x01, 0x36, 0x01, 0x47, 0x01, 0x56, ++ 0x01, 0x63); ++ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xb2, ++ 0x01, 0x6f, 0x01, 0x7b, 0x01, 0x8f, 0x01, ++ 0xa1, 0x01, 0xb1, 0x01, 0xce, 0x01, 0xe9, ++ 0x01, 0xff); ++ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xb3, 0x02, 0x14); ++ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xb4, ++ 0x00, 0x00, 0x00, 0x62, 0x00, 0x87, 0x00, ++ 0x9e, 0x00, 0xae, 0x00, 0xc7, 0x00, 0xdb, ++ 0x00, 0xeb); ++ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xb5, ++ 0x00, 0xf8, 0x01, 0x04, 0x01, 0x0f, 0x01, ++ 0x19, 0x01, 0x23, 0x01, 0x33, 0x01, 0x42, ++ 0x01, 0x4f); ++ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xb6, ++ 0x01, 0x5b, 0x01, 0x67, 0x01, 0x7b, 0x01, ++ 0x8d, 0x01, 0x9e, 0x01, 0xbb, 0x01, 0xd5, ++ 0x01, 0xec); ++ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xb7, 0x02, 0x00); ++ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xb8, ++ 0x00, 0x00, 0x00, 0x8b, 0x00, 0xb9, 0x00, ++ 0xd2, 0x00, 0xe5, 0x01, 0x01, 0x01, 0x16, ++ 0x01, 0x27); ++ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xb9, ++ 0x01, 0x36, 0x01, 0x43, 0x01, 0x4f, 0x01, ++ 0x59, 0x01, 0x63, 0x01, 0x74, 0x01, 0x83, ++ 0x01, 0x91); ++ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xba, ++ 0x01, 0x9d, 0x01, 0xa9, 0x01, 0xbd, 0x01, ++ 0xcf, 0x01, 0xde, 0x01, 0xf5, 0x02, 0x0a, ++ 0x02, 0x21); ++ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xbb, 0x02, 0x36); ++ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xbf, 0x00); ++ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xb0, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00); ++ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xb1, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00); ++ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xb2, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00); ++ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xb3, 0x00, 0x00); ++ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xb4, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00); ++ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xb5, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00); ++ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xb6, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00); ++ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xb7, 0x00, 0x00); ++ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xb8, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00); ++ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xb9, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00); ++ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xba, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00); ++ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xbb, 0x00, 0x00); ++ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xd2, 0x14, 0x92, 0x24); ++ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xc3, ++ 0x00, 0x23, 0x61, 0x45, 0x21, 0x43, 0x65); ++ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xd4, 0x00, 0xff); ++ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xd5, ++ 0x00, 0x0c, 0x00, 0x1c, 0x00); ++ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xd6, 0x02); ++ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xf0, 0xaa, 0x14); ++ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xb2, 0x03, 0x33); ++ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xb4, 0x04, 0x11, 0x11, 0x07); ++ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xb5, ++ 0x00, 0x6d, 0x6d, 0x06, 0x01); ++ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xb9, 0x00, 0x00, 0x08, 0x32); ++ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xbc, ++ 0x10, 0x00, 0x00, 0x06, 0x11, 0x30, 0x88); ++ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xbe, ++ 0x10, 0x10, 0x00, 0x08, 0x22, 0x30, 0x86); ++ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xf0, 0xaa, 0x15); ++ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xb1, 0x33, 0x41); ++ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xb2, 0x63); ++ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xb3, 0x84, 0x23, 0x30); ++ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xb4, 0x83, 0x04); ++ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xb5, 0x83, 0x04); ++ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xb6, 0x83, 0x00, 0x04); ++ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xb7, 0x83, 0x00, 0x04); ++ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xbc, 0x72); ++ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xbd, 0x48); ++ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xbe, ++ 0x11, 0x00, 0x00, 0x22, 0x00, 0x11, 0x00, ++ 0x00, 0x00, 0x00, 0x01); ++ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xbf, 0x02); ++ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xc0, 0x02); ++ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xc1, 0x02); ++ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xc3, 0x01); ++ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xf0, 0xaa, 0x16); ++ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xb0, 0x25, 0x21, 0x20, 0x0b); ++ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xb1, 0x0a, 0x04, 0x13, 0x12); ++ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xb2, 0x25, 0x25, 0x25, 0x25); ++ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xb3, 0x25, 0x25, 0x25, 0x25); ++ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xb4, 0x25, 0x25, 0x25, 0x25); ++ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xb5, 0x25, 0x25, 0x25, 0x25); ++ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xb6, 0x25, 0x25, 0x25, 0x25); ++ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xb7, 0x25, 0x25, 0x25, 0x25); ++ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xb8, 0x12, 0x13, 0x00, 0x0a); ++ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xb9, 0x0b, 0x20, 0x21, 0x25); ++ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xf0, 0xaa, 0x17); ++ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xb0, ++ 0x02, 0x30, 0x00, 0x09, 0x00, 0x00, 0x00, ++ 0x00, 0x0f, 0xdc, 0xc0, 0x0d, 0x00); ++ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xb1, ++ 0x0c, 0xe0, 0xff, 0x1f, 0xfc, 0x00, 0x20, ++ 0x20, 0x00, 0x20, 0x20, 0x00, 0x20, 0x20, ++ 0x00, 0x20); ++ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xb2, ++ 0x00, 0x00, 0x04, 0x00, 0x80, 0xc0, 0x80, ++ 0x00, 0x14, 0x14, 0x00, 0x14, 0x14, 0x00, ++ 0x14, 0x14); ++ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xb3, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x40, 0x00, 0xc0, 0x40, 0x0d, 0x40, ++ 0xa0, 0xc0); ++ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xb4, ++ 0x67, 0x67, 0x67, 0x67, 0x67, 0x67, 0x3f); ++ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xb5, ++ 0x23, 0x61, 0x45, 0x12, 0x53, 0x64); ++ mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xe5, 0x11); ++ mipi_dsi_dcs_exit_sleep_mode_multi(&dsi_ctx); ++ mipi_dsi_msleep(&dsi_ctx, 200); ++ mipi_dsi_dcs_set_display_on_multi(&dsi_ctx); ++ mipi_dsi_msleep(&dsi_ctx, 120); ++ ++ return dsi_ctx.accum_err; ++} ++ ++static int ar02_3inch_off(struct ar02_3inch *ctx) ++{ ++ struct mipi_dsi_multi_context dsi_ctx = { .dsi = ctx->dsi }; ++ ++ ctx->dsi->mode_flags &= ~MIPI_DSI_MODE_LPM; ++ ++ mipi_dsi_dcs_enter_sleep_mode_multi(&dsi_ctx); ++ mipi_dsi_msleep(&dsi_ctx, 120); ++ mipi_dsi_dcs_set_display_off_multi(&dsi_ctx); ++ mipi_dsi_usleep_range(&dsi_ctx, 10000, 11000); ++ ++ return dsi_ctx.accum_err; ++} ++ ++static int ar02_3inch_prepare(struct drm_panel *panel) ++{ ++ struct ar02_3inch *ctx = to_ar02_3inch(panel); ++ struct device *dev = &ctx->dsi->dev; ++ int ret; ++ ++ ret = regulator_bulk_enable(ARRAY_SIZE(panel_supplies), ctx->supplies); ++ if (ret < 0) { ++ dev_err(panel->dev, "failed to enable regulators: %d\n", ret); ++ return ret; ++ } ++ msleep(20); ++ ++ ar02_3inch_reset(ctx); ++ ++ ret = ar02_3inch_on(ctx); ++ if (ret < 0) { ++ dev_err(dev, "Failed to initialize panel: %d\n", ret); ++ regulator_bulk_disable(ARRAY_SIZE(panel_supplies), ctx->supplies); ++ return ret; ++ } ++ ++ return 0; ++} ++ ++static int ar02_3inch_unprepare(struct drm_panel *panel) ++{ ++ struct ar02_3inch *ctx = to_ar02_3inch(panel); ++ struct device *dev = &ctx->dsi->dev; ++ int ret; ++ ++ ret = ar02_3inch_off(ctx); ++ if (ret < 0) ++ dev_err(dev, "Failed to un-initialize panel: %d\n", ret); ++ ++ regulator_bulk_disable(ARRAY_SIZE(panel_supplies), ctx->supplies); ++ gpiod_set_value_cansleep(ctx->reset_gpio, 1); ++ ++ return 0; ++} ++ ++static const struct drm_display_mode ar02_3inch_mode = { ++ .clock = (1080 + 28 + 4 + 36) * (1240 + 18 + 4 + 8) * 60 / 1000, ++ .hdisplay = 1080, ++ .hsync_start = 1080 + 28, ++ .hsync_end = 1080 + 28 + 4, ++ .htotal = 1080 + 28 + 4 + 36, ++ .vdisplay = 1240, ++ .vsync_start = 1240 + 18, ++ .vsync_end = 1240 + 18 + 4, ++ .vtotal = 1240 + 18 + 4 + 8, ++ .width_mm = 0, ++ .height_mm = 0, ++ .type = DRM_MODE_TYPE_DRIVER | DRM_MODE_TYPE_PREFERRED, ++}; ++ ++static int ar02_3inch_get_modes(struct drm_panel *panel, ++ struct drm_connector *connector) ++{ ++ return drm_connector_helper_get_modes_fixed(connector, &ar02_3inch_mode); ++} ++ ++static enum drm_panel_orientation ar02_3inch_get_orientation(struct drm_panel *panel) ++{ ++ struct ar02_3inch *ctx = to_ar02_3inch(panel); ++ ++ return ctx->orientation; ++} ++ ++static const struct drm_panel_funcs ar02_3inch_panel_funcs = { ++ .prepare = ar02_3inch_prepare, ++ .unprepare = ar02_3inch_unprepare, ++ .get_modes = ar02_3inch_get_modes, ++ .get_orientation = ar02_3inch_get_orientation, ++}; ++ ++static int ar02_3inch_bl_update_status(struct backlight_device *bl) ++{ ++ struct mipi_dsi_device *dsi = bl_get_data(bl); ++ u16 brightness = backlight_get_brightness(bl); ++ int ret; ++ ++ dsi->mode_flags &= ~MIPI_DSI_MODE_LPM; ++ ++ ret = mipi_dsi_dcs_set_display_brightness_large(dsi, brightness); ++ if (ret < 0) ++ return ret; ++ ++ dsi->mode_flags |= MIPI_DSI_MODE_LPM; ++ ++ return 0; ++} ++ ++// TODO: Check if /sys/class/backlight/.../actual_brightness actually returns ++// correct values. If not, remove this function. ++static int ar02_3inch_bl_get_brightness(struct backlight_device *bl) ++{ ++ struct mipi_dsi_device *dsi = bl_get_data(bl); ++ u16 brightness; ++ int ret; ++ ++ dsi->mode_flags &= ~MIPI_DSI_MODE_LPM; ++ ++ ret = mipi_dsi_dcs_get_display_brightness_large(dsi, &brightness); ++ if (ret < 0) ++ return ret; ++ ++ dsi->mode_flags |= MIPI_DSI_MODE_LPM; ++ ++ return brightness; ++} ++ ++static const struct backlight_ops ar02_3inch_bl_ops = { ++ .update_status = ar02_3inch_bl_update_status, ++ .get_brightness = ar02_3inch_bl_get_brightness, ++}; ++ ++static struct backlight_device * ++ar02_3inch_create_backlight(struct mipi_dsi_device *dsi) ++{ ++ struct device *dev = &dsi->dev; ++ const struct backlight_properties props = { ++ .type = BACKLIGHT_RAW, ++ .brightness = 1023, ++ .max_brightness = 1023, ++ }; ++ ++ return devm_backlight_device_register(dev, dev_name(dev), dev, dsi, ++ &ar02_3inch_bl_ops, &props); ++} ++ ++static int ar02_3inch_probe(struct mipi_dsi_device *dsi) ++{ ++ struct device *dev = &dsi->dev; ++ struct ar02_3inch *ctx; ++ int ret; ++ ++ ctx = devm_kzalloc(dev, sizeof(*ctx), GFP_KERNEL); ++ if (!ctx) ++ return -ENOMEM; ++ ++ ret = devm_regulator_bulk_get_const(dev, ARRAY_SIZE(panel_supplies), ++ panel_supplies, &ctx->supplies); ++ if (ret < 0){ ++ return dev_err_probe(dev, ret, "Failed to get regulators\n"); ++ } ++ ++ 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-gpios\n"); ++ ++ ctx->dsi = dsi; ++ mipi_dsi_set_drvdata(dsi, ctx); ++ ++ dsi->lanes = 4; ++ dsi->format = MIPI_DSI_FMT_RGB888; ++ dsi->mode_flags = MIPI_DSI_MODE_VIDEO | MIPI_DSI_MODE_VIDEO_BURST | ++ MIPI_DSI_CLOCK_NON_CONTINUOUS; ++ ++ /* Orientation */ ++ ret = of_drm_get_panel_orientation(dev->of_node, &ctx->orientation); ++ if (ret < 0) { ++ dev_err(dev, "failed to get orientation %d\n", ret); ++ return ret; ++ } ++ ++ drm_panel_init(&ctx->panel, dev, &ar02_3inch_panel_funcs, ++ DRM_MODE_CONNECTOR_DSI); ++ ctx->panel.prepare_prev_first = true; ++ ++ ctx->panel.backlight = ar02_3inch_create_backlight(dsi); ++ if (IS_ERR(ctx->panel.backlight)) ++ return dev_err_probe(dev, PTR_ERR(ctx->panel.backlight), ++ "Failed to create backlight\n"); ++ ++ drm_panel_add(&ctx->panel); ++ ++ ret = mipi_dsi_attach(dsi); ++ if (ret < 0) { ++ drm_panel_remove(&ctx->panel); ++ return dev_err_probe(dev, ret, "Failed to attach to DSI host\n"); ++ } ++ ++ return 0; ++} ++ ++static void ar02_3inch_remove(struct mipi_dsi_device *dsi) ++{ ++ struct ar02_3inch *ctx = mipi_dsi_get_drvdata(dsi); ++ int ret; ++ ++ ret = mipi_dsi_detach(dsi); ++ if (ret < 0) ++ dev_err(&dsi->dev, "Failed to detach from DSI host: %d\n", ret); ++ ++ drm_panel_remove(&ctx->panel); ++} ++ ++static const struct of_device_id ar02_3inch_of_match[] = { ++ { .compatible = "ayaneo,pocket-dmg" }, ++ { /* sentinel */ } ++}; ++MODULE_DEVICE_TABLE(of, ar02_3inch_of_match); ++ ++static struct mipi_dsi_driver ar02_3inch_driver = { ++ .probe = ar02_3inch_probe, ++ .remove = ar02_3inch_remove, ++ .driver = { ++ .name = "panel-ar02-3inch", ++ .of_match_table = ar02_3inch_of_match, ++ }, ++}; ++module_mipi_dsi_driver(ar02_3inch_driver); ++ ++MODULE_AUTHOR("linux-mdss-dsi-panel-driver-generator "); // FIXME ++MODULE_DESCRIPTION("DRM driver for ar02 395inch video mode dsi panel"); ++MODULE_LICENSE("GPL"); +-- +2.50.1 + diff --git a/projects/ROCKNIX/devices/SM8550/patches/linux/0212_arm64--dts--qcom--Add-AYANEO-Pocket-DMG.patch b/projects/ROCKNIX/devices/SM8550/patches/linux/0212_arm64--dts--qcom--Add-AYANEO-Pocket-DMG.patch new file mode 100644 index 0000000000..909a547b20 --- /dev/null +++ b/projects/ROCKNIX/devices/SM8550/patches/linux/0212_arm64--dts--qcom--Add-AYANEO-Pocket-DMG.patch @@ -0,0 +1,59 @@ +diff -rupbN linux.orig/arch/arm64/boot/dts/qcom/qcs8550-ayaneo-pocketdmg.dts linux/arch/arm64/boot/dts/qcom/qcs8550-ayaneo-pocketdmg.dts +--- linux.orig/arch/arm64/boot/dts/qcom/qcs8550-ayaneo-pocketdmg.dts 1970-01-01 00:00:00.000000000 +0000 ++++ linux/arch/arm64/boot/dts/qcom/qcs8550-ayaneo-pocketdmg.dts 2025-02-26 13:52:56.398992835 +0000 +@@ -0,0 +1,55 @@ ++// SPDX-License-Identifier: BSD-3-Clause ++/* ++ * Copyright (c) 2025, Teguh Sobirin. ++ * Copyright (c) 2025, ROCKNIX (https://github.com/ROCKNIX) ++ */ ++ ++/dts-v1/; ++ ++#include "qcs8550-ayaneo-pocket-common.dtsi" ++ ++/ { ++ model = "AYANEO Pocket DMG"; ++ qcom,board-id = <0x1000b 0x01>; ++ qcom,msm-id = <0x258 0x20000>, <0x259 0x20000>; ++ compatible = "ayaneo,pocketdmg", "qcom,qcs8550", "qcom,sm8550"; ++}; ++ ++&tlmm { ++ panel_pwr_active: panel-pwr-active-state { ++ pins = "gpio152", "gpio153"; ++ function = "gpio"; ++ drive-strength = <8>; ++ bias-disable; ++ output-high; ++ }; ++}; ++ ++&i2c0 { ++ clock-frequency = <400000>; ++ status = "okay"; ++ ++ /* Screen power */ ++ sgm3804: regulator@3e { ++ compatible = "sgmicro,sgm3804"; ++ reg = <0x3e>; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&panel_pwr_active>; ++ regulator-name = "panel-avdd"; ++ regulator-min-microvolt = <5000000>; ++ regulator-max-microvolt = <5000000>; ++ reset-gpios = <&tlmm 152 GPIO_ACTIVE_HIGH>, <&tlmm 153 GPIO_ACTIVE_HIGH>; ++ }; ++}; ++ ++&display_panel { ++ compatible = "ayaneo,pocket-dmg"; ++ ++ avdd-supply = <&sgm3804>; ++ vci-supply = <&vreg_l13b_3p0>; ++ vddio-supply = <&vreg_l12b_1p8>; ++ ++ reset-gpios = <&tlmm 133 GPIO_ACTIVE_LOW>; ++ ++ rotation = <270>; ++};