diff --git a/config/boards/xiaomi-elish.conf b/config/boards/xiaomi-elish.conf index fc5d6e886..5de7fbe73 100644 --- a/config/boards/xiaomi-elish.conf +++ b/config/boards/xiaomi-elish.conf @@ -14,8 +14,8 @@ declare -g BOARD_FIRMWARE_INSTALL="-full" function post_family_config_branch_sm8250__pmos_kernel() { display_alert "Setting up kernel for" "${BOARD}" "info" - declare -g KERNEL_MAJOR_MINOR="6.6" # Major and minor versions of this kernel. - declare -g KERNELBRANCH='branch:linux-6.6.y' + declare -g KERNEL_MAJOR_MINOR="6.7" # Major and minor versions of this kernel. + declare -g KERNELBRANCH='tag:v6.7-rc2' } function xiaomi-elish_is_userspace_supported() { @@ -37,6 +37,7 @@ function post_family_tweaks_bsp__xiaomi-elish_firmware() { mkdir -p $destination/usr/local/bin/ mkdir -p $destination/usr/lib/systemd/system/ install -Dm655 $SRC/packages/bsp/xiaomi-elish/setup-usbgadget-network.sh $destination/usr/local/bin/ + install -Dm655 $SRC/packages/bsp/xiaomi-elish/remove-usbgadget-network.sh $destination/usr/local/bin/ install -Dm644 $SRC/packages/bsp/xiaomi-elish/usbgadget-rndis.service $destination/usr/lib/systemd/system/ # Kernel postinst script to update abl boot partition diff --git a/config/kernel/linux-arm64-sm8250.config b/config/kernel/linux-arm64-sm8250.config index 8d237e36a..dea5d40f1 100644 --- a/config/kernel/linux-arm64-sm8250.config +++ b/config/kernel/linux-arm64-sm8250.config @@ -1,6 +1,6 @@ # # Automatically generated file; DO NOT EDIT. -# Linux/arm64 6.6.0 Kernel Configuration +# Linux/arm64 6.7.0-rc2 Kernel Configuration # CONFIG_CC_VERSION_TEXT="aarch64-linux-gnu-gcc (Ubuntu 11.4.0-1ubuntu1~22.04) 11.4.0" CONFIG_CC_IS_GCC=y @@ -314,6 +314,7 @@ CONFIG_BUILTIN_RETURN_ADDRESS_STRIPS_PAC=y # CONFIG_ARCH_NXP is not set # CONFIG_ARCH_MA35 is not set # CONFIG_ARCH_NPCM is not set +# CONFIG_ARCH_PENSANDO is not set CONFIG_ARCH_QCOM=y # CONFIG_ARCH_REALTEK is not set # CONFIG_ARCH_RENESAS is not set @@ -424,6 +425,7 @@ CONFIG_ARCH_SUPPORTS_KEXEC_SIG=y CONFIG_ARCH_SUPPORTS_KEXEC_IMAGE_VERIFY_SIG=y CONFIG_ARCH_DEFAULT_KEXEC_IMAGE_VERIFY_SIG=y CONFIG_ARCH_SUPPORTS_CRASH_DUMP=y +CONFIG_ARCH_HAS_GENERIC_CRASHKERNEL_RESERVATION=y CONFIG_TRANS_TABLE=y # CONFIG_XEN is not set CONFIG_ARCH_FORCE_MAX_ORDER=10 @@ -953,6 +955,7 @@ CONFIG_MIGRATION=y CONFIG_ARCH_ENABLE_HUGEPAGE_MIGRATION=y CONFIG_ARCH_ENABLE_THP_MIGRATION=y CONFIG_CONTIG_ALLOC=y +CONFIG_PCP_BATCH_SCALE_MAX=5 CONFIG_PHYS_ADDR_T_64BIT=y CONFIG_KSM=y CONFIG_DEFAULT_MMAP_MIN_ADDR=4096 @@ -1642,6 +1645,7 @@ CONFIG_VGA_ARB=y CONFIG_VGA_ARB_MAX_GPUS=16 CONFIG_HOTPLUG_PCI=y CONFIG_HOTPLUG_PCI_ACPI=y +# CONFIG_HOTPLUG_PCI_ACPI_AMPERE_ALTRA is not set # CONFIG_HOTPLUG_PCI_ACPI_IBM is not set # CONFIG_HOTPLUG_PCI_CPCI is not set # CONFIG_HOTPLUG_PCI_SHPC is not set @@ -1766,7 +1770,6 @@ CONFIG_GENERIC_ARCH_NUMA=y # # Bus devices # -# CONFIG_BRCMSTB_GISB_ARB is not set # CONFIG_MOXTET is not set CONFIG_QCOM_EBI2=y # CONFIG_QCOM_SSC_BLOCK_BUS is not set @@ -1802,6 +1805,7 @@ CONFIG_ARM_SCMI_TRANSPORT_SMC=y # CONFIG_ARM_SCMI_TRANSPORT_SMC_ATOMIC_ENABLE is not set # CONFIG_ARM_SCMI_TRANSPORT_VIRTIO is not set CONFIG_ARM_SCMI_POWER_DOMAIN=y +CONFIG_ARM_SCMI_PERF_DOMAIN=y # CONFIG_ARM_SCMI_POWER_CONTROL is not set # end of ARM System Control and Management Interface Protocol @@ -1812,8 +1816,6 @@ CONFIG_DMIID=y # CONFIG_DMI_SYSFS is not set # CONFIG_ISCSI_IBFT is not set # CONFIG_FW_CFG_SYSFS is not set -CONFIG_QCOM_SCM=y -# CONFIG_QCOM_SCM_DOWNLOAD_MODE_DEFAULT is not set CONFIG_SYSFB=y CONFIG_SYSFB_SIMPLEFB=y # CONFIG_ARM_FFA_TRANSPORT is not set @@ -1845,6 +1847,15 @@ CONFIG_UEFI_CPER=y CONFIG_UEFI_CPER_ARM=y CONFIG_ARM_PSCI_FW=y # CONFIG_ARM_PSCI_CHECKER is not set + +# +# Qualcomm firmware drivers +# +CONFIG_QCOM_SCM=y +# CONFIG_QCOM_SCM_DOWNLOAD_MODE_DEFAULT is not set +# CONFIG_QCOM_QSEECOM is not set +# end of Qualcomm firmware drivers + CONFIG_HAVE_ARM_SMCCC=y CONFIG_HAVE_ARM_SMCCC_DISCOVERY=y CONFIG_ARM_SMCCC_SOC_ID=y @@ -1867,7 +1878,6 @@ CONFIG_MTD=y # # Partition parsers # -# CONFIG_MTD_AR7_PARTS is not set # CONFIG_MTD_CMDLINE_PARTS is not set CONFIG_MTD_OF_PARTS=y # CONFIG_MTD_AFS_PARTS is not set @@ -2093,7 +2103,6 @@ CONFIG_PCI_ENDPOINT_TEST=m # CONFIG_EEPROM_AT24=m CONFIG_EEPROM_AT25=m -# CONFIG_EEPROM_LEGACY is not set # CONFIG_EEPROM_MAX6875 is not set # CONFIG_EEPROM_93CX6 is not set # CONFIG_EEPROM_93XX46 is not set @@ -2396,6 +2405,7 @@ CONFIG_TAP=m CONFIG_VETH=m # CONFIG_VIRTIO_NET is not set # CONFIG_NLMON is not set +# CONFIG_NETKIT is not set # CONFIG_NET_VRF is not set # CONFIG_MHI_NET is not set # CONFIG_ARCNET is not set @@ -2816,7 +2826,6 @@ CONFIG_INPUT_PWM_VIBRA=m # CONFIG_INPUT_DRV260X_HAPTICS is not set # CONFIG_INPUT_DRV2665_HAPTICS is not set # CONFIG_INPUT_DRV2667_HAPTICS is not set -CONFIG_XIAOMI_KEYBOARD=y # CONFIG_RMI4_CORE is not set # @@ -3292,7 +3301,6 @@ CONFIG_GPIO_MAX77620=y # CONFIG_W1 is not set CONFIG_POWER_RESET=y -# CONFIG_POWER_RESET_BRCMSTB is not set # CONFIG_POWER_RESET_GPIO is not set # CONFIG_POWER_RESET_GPIO_RESTART is not set CONFIG_POWER_RESET_MSM=y @@ -3338,6 +3346,8 @@ CONFIG_BATTERY_BQ27XXX_I2C=y # CONFIG_CHARGER_DETECTOR_MAX14656 is not set # CONFIG_CHARGER_MAX77976 is not set # CONFIG_CHARGER_QCOM_SMBB is not set +# CONFIG_BATTERY_PM8916_BMS_VM is not set +# CONFIG_CHARGER_PM8916_LBC is not set # CONFIG_CHARGER_BQ2415X is not set # CONFIG_CHARGER_BQ24190 is not set # CONFIG_CHARGER_BQ24257 is not set @@ -3357,6 +3367,7 @@ CONFIG_BATTERY_BQ27XXX_I2C=y # CONFIG_CHARGER_BD99954 is not set # CONFIG_BATTERY_UG3105 is not set # CONFIG_CHARGER_QCOM_SMB2 is not set +# CONFIG_FUEL_GAUGE_MM8013 is not set CONFIG_HWMON=y # CONFIG_HWMON_DEBUG_CHIP is not set @@ -3408,12 +3419,14 @@ CONFIG_SENSORS_ARM_SCPI=y # CONFIG_SENSORS_IIO_HWMON is not set # CONFIG_SENSORS_IT87 is not set # CONFIG_SENSORS_JC42 is not set +# CONFIG_SENSORS_POWERZ is not set # CONFIG_SENSORS_POWR1220 is not set # CONFIG_SENSORS_LINEAGE is not set # CONFIG_SENSORS_LTC2945 is not set # CONFIG_SENSORS_LTC2947_I2C is not set # CONFIG_SENSORS_LTC2947_SPI is not set # CONFIG_SENSORS_LTC2990 is not set +# CONFIG_SENSORS_LTC2991 is not set # CONFIG_SENSORS_LTC2992 is not set # CONFIG_SENSORS_LTC4151 is not set # CONFIG_SENSORS_LTC4215 is not set @@ -3776,6 +3789,7 @@ CONFIG_REGULATOR_HI6421V530=y # CONFIG_REGULATOR_LTC3589 is not set # CONFIG_REGULATOR_LTC3676 is not set # CONFIG_REGULATOR_MAX1586 is not set +# CONFIG_REGULATOR_MAX77503 is not set CONFIG_REGULATOR_MAX77620=y # CONFIG_REGULATOR_MAX77857 is not set # CONFIG_REGULATOR_MAX8649 is not set @@ -3951,6 +3965,10 @@ CONFIG_V4L_MEM2MEM_DRIVERS=y # Microchip Technology, Inc. media platform drivers # +# +# Nuvoton media platform drivers +# + # # NVidia media platform drivers # @@ -4127,10 +4145,12 @@ CONFIG_DRM_PANEL=y # CONFIG_DRM_PANEL_ILITEK_IL9322 is not set # CONFIG_DRM_PANEL_ILITEK_ILI9341 is not set # CONFIG_DRM_PANEL_ILITEK_ILI9881C is not set +# CONFIG_DRM_PANEL_ILITEK_ILI9882T is not set # CONFIG_DRM_PANEL_INNOLUX_EJ030NA is not set # CONFIG_DRM_PANEL_INNOLUX_P079ZCA is not set # CONFIG_DRM_PANEL_JADARD_JD9365DA_H3 is not set # CONFIG_DRM_PANEL_JDI_LT070ME05000 is not set +# CONFIG_DRM_PANEL_JDI_LPM102A188A is not set # CONFIG_DRM_PANEL_JDI_R63452 is not set # CONFIG_DRM_PANEL_KHADAS_TS050 is not set # CONFIG_DRM_PANEL_KINGDISPLAY_KD097D04 is not set @@ -4158,6 +4178,7 @@ CONFIG_DRM_PANEL_NOVATEK_NT36523=y # CONFIG_DRM_PANEL_RASPBERRYPI_TOUCHSCREEN is not set # CONFIG_DRM_PANEL_RAYDIUM_RM67191 is not set # CONFIG_DRM_PANEL_RAYDIUM_RM68200 is not set +# CONFIG_DRM_PANEL_RAYDIUM_RM692E5 is not set # CONFIG_DRM_PANEL_RONBO_RB070D30 is not set # CONFIG_DRM_PANEL_SAMSUNG_ATNA33XC20 is not set # CONFIG_DRM_PANEL_SAMSUNG_DB7430 is not set @@ -4323,6 +4344,7 @@ CONFIG_FB_SYS_IMAGEBLIT=y # CONFIG_FB_FOREIGN_ENDIAN is not set CONFIG_FB_SYS_FOPS=y CONFIG_FB_DEFERRED_IO=y +CONFIG_FB_IOMEM_FOPS=y CONFIG_FB_IOMEM_HELPERS=y CONFIG_FB_SYSMEM_HELPERS=y CONFIG_FB_SYSMEM_HELPERS_DEFERRED=y @@ -4531,6 +4553,8 @@ CONFIG_SND_SOC_WM_ADSP=m # CONFIG_SND_SOC_AW8738 is not set # CONFIG_SND_SOC_AW88395 is not set # CONFIG_SND_SOC_AW88261 is not set +# CONFIG_SND_SOC_AW87390 is not set +# CONFIG_SND_SOC_AW88399 is not set # CONFIG_SND_SOC_BD28623 is not set # CONFIG_SND_SOC_BT_SCO is not set # CONFIG_SND_SOC_CHV3_CODEC is not set @@ -4629,6 +4653,7 @@ CONFIG_SND_SOC_HDMI_CODEC=y # CONFIG_SND_SOC_RT715_SDW is not set # CONFIG_SND_SOC_RT715_SDCA_SDW is not set # CONFIG_SND_SOC_RT9120 is not set +# CONFIG_SND_SOC_RTQ9128 is not set # CONFIG_SND_SOC_SGTL5000 is not set # CONFIG_SND_SOC_SIMPLE_AMPLIFIER is not set # CONFIG_SND_SOC_SIMPLE_MUX is not set @@ -4877,6 +4902,7 @@ CONFIG_USB_CONN_GPIO=m CONFIG_USB_ARCH_HAS_HCD=y CONFIG_USB=y CONFIG_USB_PCI=y +# CONFIG_USB_PCI_AMD is not set # CONFIG_USB_ANNOUNCE_NEW_DEVICES is not set # @@ -5004,6 +5030,7 @@ CONFIG_USB_CHIPIDEA_UDC=y CONFIG_USB_CHIPIDEA_HOST=y CONFIG_USB_CHIPIDEA_PCI=y CONFIG_USB_CHIPIDEA_MSM=y +CONFIG_USB_CHIPIDEA_NPCM=y CONFIG_USB_CHIPIDEA_IMX=y CONFIG_USB_CHIPIDEA_GENERIC=y CONFIG_USB_CHIPIDEA_TEGRA=y @@ -5087,6 +5114,7 @@ CONFIG_USB_SERIAL_OPTION=m # CONFIG_USB_APPLEDISPLAY is not set # CONFIG_USB_QCOM_EUD is not set # CONFIG_APPLE_MFI_FASTCHARGE is not set +# CONFIG_USB_LJCA is not set # CONFIG_USB_SISUSBVGA is not set # CONFIG_USB_LD is not set # CONFIG_USB_TRANCEVIBRATOR is not set @@ -5220,6 +5248,7 @@ CONFIG_TYPEC_HD3SS3220=m # CONFIG_TYPEC_MUX_GPIO_SBU is not set # CONFIG_TYPEC_MUX_PI3USB30532 is not set # CONFIG_TYPEC_MUX_NB7VPQ904M is not set +# CONFIG_TYPEC_MUX_PTN36502 is not set # end of USB Type-C Multiplexer/DeMultiplexer Switch support # @@ -5313,6 +5342,7 @@ CONFIG_LEDS_TRIGGER_HEARTBEAT=y # CONFIG_LEDS_TRIGGER_BACKLIGHT is not set CONFIG_LEDS_TRIGGER_CPU=y # CONFIG_LEDS_TRIGGER_ACTIVITY is not set +# CONFIG_LEDS_TRIGGER_GPIO is not set CONFIG_LEDS_TRIGGER_DEFAULT_ON=y # @@ -5532,7 +5562,6 @@ CONFIG_VIRTIO=y # CONFIG_COMEDI is not set CONFIG_STAGING=y # CONFIG_PRISM2_USB is not set -# CONFIG_RTL8192U is not set # CONFIG_RTLLIB is not set # CONFIG_R8712U is not set # CONFIG_RTS5208 is not set @@ -5574,12 +5603,6 @@ CONFIG_STAGING=y # # CONFIG_AD5933 is not set # end of Network Analyzer, Impedance Converters - -# -# Resolver to digital converters -# -# CONFIG_AD2S1210 is not set -# end of Resolver to digital converters # end of IIO staging drivers # CONFIG_FB_SM750 is not set @@ -5701,7 +5724,9 @@ CONFIG_QCOM_CLK_RPMH=y # CONFIG_SM_CAMCC_6350 is not set # CONFIG_SM_CAMCC_8250 is not set # CONFIG_SM_CAMCC_8450 is not set +# CONFIG_SM_CAMCC_8550 is not set CONFIG_SM_DISPCC_8250=y +# CONFIG_SM_GCC_4450 is not set # CONFIG_SM_GCC_6115 is not set # CONFIG_SM_GCC_6125 is not set # CONFIG_SM_GCC_6350 is not set @@ -5842,7 +5867,6 @@ CONFIG_SOUNDWIRE_QCOM=y # # Broadcom SoC drivers # -# CONFIG_SOC_BRCMSTB is not set # end of Broadcom SoC drivers # @@ -5876,7 +5900,6 @@ CONFIG_FSL_RCPM=y # CONFIG_QCOM_AOSS_QMP=y CONFIG_QCOM_COMMAND_DB=y -CONFIG_QCOM_CPR=y CONFIG_QCOM_GENI_SE=y # CONFIG_QCOM_GSBI is not set CONFIG_QCOM_LLCC=y @@ -5890,8 +5913,6 @@ CONFIG_QCOM_QMI_HELPERS=y CONFIG_QCOM_RMTFS_MEM=m # CONFIG_QCOM_RPM_MASTER_STATS is not set CONFIG_QCOM_RPMH=y -CONFIG_QCOM_RPMHPD=y -CONFIG_QCOM_RPMPD=y CONFIG_QCOM_SMEM=y CONFIG_QCOM_SMD_RPM=y CONFIG_QCOM_SMEM_STATE=y @@ -5913,6 +5934,34 @@ CONFIG_QCOM_APR=y # end of Xilinx SoC drivers # end of SOC (System On Chip) specific Drivers +# +# PM Domains +# + +# +# Amlogic PM Domains +# +# end of Amlogic PM Domains + +# +# Broadcom PM Domains +# +# end of Broadcom PM Domains + +# +# i.MX PM Domains +# +# end of i.MX PM Domains + +# +# Qualcomm PM Domains +# +CONFIG_QCOM_CPR=y +CONFIG_QCOM_RPMHPD=y +CONFIG_QCOM_RPMPD=y +# end of Qualcomm PM Domains +# end of PM Domains + CONFIG_PM_DEVFREQ=y # @@ -6039,6 +6088,7 @@ CONFIG_IIO_CONSUMERS_PER_TRIGGER=2 # CONFIG_HI8435 is not set # CONFIG_HX711 is not set # CONFIG_INA2XX_ADC is not set +# CONFIG_LTC2309 is not set # CONFIG_LTC2471 is not set # CONFIG_LTC2485 is not set # CONFIG_LTC2496 is not set @@ -6053,6 +6103,7 @@ CONFIG_IIO_CONSUMERS_PER_TRIGGER=2 CONFIG_MAX9611=m # CONFIG_MCP320X is not set # CONFIG_MCP3422 is not set +# CONFIG_MCP3564 is not set # CONFIG_MCP3911 is not set # CONFIG_NAU7802 is not set CONFIG_QCOM_VADC_COMMON=m @@ -6425,6 +6476,7 @@ CONFIG_IIO_ST_MAGN_SPI_3AXIS=m # Pressure sensors # # CONFIG_ABP060MG is not set +# CONFIG_ROHM_BM1390 is not set # CONFIG_BMP280 is not set # CONFIG_DLHL60D is not set # CONFIG_DPS310 is not set @@ -6472,6 +6524,7 @@ CONFIG_MPL3115=m # # CONFIG_AD2S90 is not set # CONFIG_AD2S1200 is not set +# CONFIG_AD2S1210 is not set # end of Resolver to digital converters # @@ -6699,6 +6752,7 @@ CONFIG_INTERCONNECT_QCOM_RPMH=y # CONFIG_INTERCONNECT_QCOM_SDM845 is not set # CONFIG_INTERCONNECT_QCOM_SDX55 is not set # CONFIG_INTERCONNECT_QCOM_SDX65 is not set +# CONFIG_INTERCONNECT_QCOM_SDX75 is not set # CONFIG_INTERCONNECT_QCOM_SM6350 is not set # CONFIG_INTERCONNECT_QCOM_SM8150 is not set CONFIG_INTERCONNECT_QCOM_SM8250=y @@ -6739,7 +6793,6 @@ CONFIG_FS_MBCACHE=y # CONFIG_OCFS2_FS is not set CONFIG_BTRFS_FS=y # CONFIG_BTRFS_FS_POSIX_ACL is not set -# CONFIG_BTRFS_FS_CHECK_INTEGRITY is not set # CONFIG_BTRFS_FS_RUN_SANITY_TESTS is not set # CONFIG_BTRFS_DEBUG is not set # CONFIG_BTRFS_ASSERT is not set @@ -6755,6 +6808,7 @@ CONFIG_F2FS_FS_POSIX_ACL=y # CONFIG_F2FS_FS_COMPRESSION is not set CONFIG_F2FS_IOSTAT=y # CONFIG_F2FS_UNFAIR_RWSEM is not set +# CONFIG_BCACHEFS_FS is not set CONFIG_FS_POSIX_ACL=y CONFIG_EXPORTFS=y # CONFIG_EXPORTFS_BLOCK_OPS is not set @@ -7115,7 +7169,7 @@ CONFIG_CRYPTO_CBC=m # CONFIG_CRYPTO_CFB is not set CONFIG_CRYPTO_CTR=m # CONFIG_CRYPTO_CTS is not set -CONFIG_CRYPTO_ECB=m +CONFIG_CRYPTO_ECB=y # CONFIG_CRYPTO_HCTR2 is not set # CONFIG_CRYPTO_KEYWRAP is not set # CONFIG_CRYPTO_LRW is not set @@ -7192,7 +7246,9 @@ CONFIG_CRYPTO_DRBG_HMAC=y # CONFIG_CRYPTO_DRBG_CTR is not set CONFIG_CRYPTO_DRBG=y CONFIG_CRYPTO_JITTERENTROPY=y -# CONFIG_CRYPTO_JITTERENTROPY_TESTINTERFACE is not set +CONFIG_CRYPTO_JITTERENTROPY_MEMORY_BLOCKS=64 +CONFIG_CRYPTO_JITTERENTROPY_MEMORY_BLOCKSIZE=32 +CONFIG_CRYPTO_JITTERENTROPY_OSR=1 CONFIG_CRYPTO_KDF800108_CTR=y # end of Random number generation @@ -7254,7 +7310,7 @@ CONFIG_CRYPTO_HW=y # CONFIG_CRYPTO_DEV_QAT_C62XVF is not set # CONFIG_CRYPTO_DEV_CAVIUM_ZIP is not set # CONFIG_CRYPTO_DEV_QCE is not set -CONFIG_CRYPTO_DEV_QCOM_RNG=y +CONFIG_CRYPTO_DEV_QCOM_RNG=m # CONFIG_CRYPTO_DEV_VIRTIO is not set # CONFIG_CRYPTO_DEV_SAFEXCEL is not set CONFIG_CRYPTO_DEV_CCREE=m @@ -7363,7 +7419,6 @@ CONFIG_ZSTD_DECOMPRESS=y CONFIG_XZ_DEC=y CONFIG_XZ_DEC_X86=y CONFIG_XZ_DEC_POWERPC=y -CONFIG_XZ_DEC_IA64=y CONFIG_XZ_DEC_ARM=y CONFIG_XZ_DEC_ARMTHUMB=y CONFIG_XZ_DEC_SPARC=y @@ -7442,10 +7497,12 @@ CONFIG_SG_POOL=y CONFIG_ARCH_STACKWALK=y CONFIG_STACKDEPOT=y CONFIG_SBITMAP=y +# CONFIG_LWQ_TEST is not set # end of Library routines CONFIG_GENERIC_IOREMAP=y CONFIG_GENERIC_LIB_DEVMEM_IS_ALLOWED=y +CONFIG_FIRMWARE_TABLE=y # # Kernel hacking diff --git a/patch/kernel/archive/sm8250-6.7/0001-drm-msm-dpu1-improve-support-for-active-CTLs.patch b/patch/kernel/archive/sm8250-6.7/0001-drm-msm-dpu1-improve-support-for-active-CTLs.patch new file mode 100644 index 000000000..5467dbe92 --- /dev/null +++ b/patch/kernel/archive/sm8250-6.7/0001-drm-msm-dpu1-improve-support-for-active-CTLs.patch @@ -0,0 +1,83 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Dmitry Baryshkov +Date: Sun, 14 Mar 2021 04:52:34 +0300 +Subject: drm/msm/dpu1: improve support for active CTLs + +- Support setting master interface if several INTFs are to be handled by + a single CTL + +- Support setting handling several MERGE_3D instances using a single + CTL. + +Signed-off-by: Dmitry Baryshkov +--- + drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.c | 15 ++++++++++ + drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.h | 2 ++ + 2 files changed, 17 insertions(+) + +diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.c +index 86182c734..4ecffbcdb 100644 +--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.c ++++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.c +@@ -510,6 +510,7 @@ static void dpu_hw_ctl_intf_cfg_v1(struct dpu_hw_ctl *ctx, + u32 intf_active = 0; + u32 wb_active = 0; + u32 mode_sel = 0; ++ u32 merge_3d_active = 0; + + /* CTL_TOP[31:28] carries group_id to collate CTL paths + * per VM. Explicitly disable it until VM support is +@@ -530,16 +531,30 @@ static void dpu_hw_ctl_intf_cfg_v1(struct dpu_hw_ctl *ctx, + if (cfg->wb) + wb_active |= BIT(cfg->wb - WB_0); + ++ merge_3d_active = DPU_REG_READ(c, CTL_MERGE_3D_ACTIVE); ++ if (cfg->merge_3d) ++ merge_3d_active |= BIT(cfg->merge_3d - MERGE_3D_0); ++ + DPU_REG_WRITE(c, CTL_TOP, mode_sel); + DPU_REG_WRITE(c, CTL_INTF_ACTIVE, intf_active); + DPU_REG_WRITE(c, CTL_WB_ACTIVE, wb_active); + ++ if (cfg->intf_master) ++ DPU_REG_WRITE(c, CTL_INTF_MASTER, BIT(cfg->intf_master - INTF_0)); ++ + if (cfg->merge_3d) + DPU_REG_WRITE(c, CTL_MERGE_3D_ACTIVE, + BIT(cfg->merge_3d - MERGE_3D_0)); + + if (cfg->dsc) + DPU_REG_WRITE(c, CTL_DSC_ACTIVE, cfg->dsc); ++ if (cfg->merge_3d) ++ DPU_REG_WRITE(c, CTL_MERGE_3D_ACTIVE, merge_3d_active); ++ ++ if (cfg->intf_master) ++ DPU_DEBUG_DRIVER("ACTIVE: %x %x %lx\n", intf_active, merge_3d_active, BIT(cfg->intf_master - INTF_0)); ++ else ++ DPU_DEBUG_DRIVER("ACTIVE: %x %x\n", intf_active, merge_3d_active); + } + + static void dpu_hw_ctl_intf_cfg(struct dpu_hw_ctl *ctx, +diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.h +index 1c242298f..36dd4e91a 100644 +--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.h ++++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.h +@@ -36,6 +36,7 @@ struct dpu_hw_stage_cfg { + /** + * struct dpu_hw_intf_cfg :Describes how the DPU writes data to output interface + * @intf : Interface id ++ * @intf_master: Master interface id in the dual pipe topology + * @mode_3d: 3d mux configuration + * @merge_3d: 3d merge block used + * @intf_mode_sel: Interface mode, cmd / vid +@@ -44,6 +45,7 @@ struct dpu_hw_stage_cfg { + */ + struct dpu_hw_intf_cfg { + enum dpu_intf intf; ++ enum dpu_intf intf_master; + enum dpu_wb wb; + enum dpu_3d_blend_mode mode_3d; + enum dpu_merge_3d merge_3d; +-- +Armbian + diff --git a/patch/kernel/archive/sm8250-6.7/0002-drm-msm-dpu1-use-one-active-CTL-if-it-is-available.patch b/patch/kernel/archive/sm8250-6.7/0002-drm-msm-dpu1-use-one-active-CTL-if-it-is-available.patch new file mode 100644 index 000000000..205dbc4be --- /dev/null +++ b/patch/kernel/archive/sm8250-6.7/0002-drm-msm-dpu1-use-one-active-CTL-if-it-is-available.patch @@ -0,0 +1,136 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Dmitry Baryshkov +Date: Sun, 14 Mar 2021 04:58:32 +0300 +Subject: drm/msm/dpu1: use one active CTL if it is available + +Unlike previous generation, with newer ("active") CTLs it is possible to +use just one CTL to handle both interfaces. And one has to use single +CTL to support master/slave DSI config. So use one active CTL if it is +available. + +Signed-off-by: Dmitry Baryshkov +--- + drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_5_0_sm8150.h | 1 + + drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_6_0_sm8250.h | 1 + + drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c | 8 ++++-- + drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.h | 1 + + drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c | 14 +++++++--- + drivers/gpu/drm/msm/disp/dpu1/dpu_rm.h | 1 + + 6 files changed, 20 insertions(+), 6 deletions(-) + +diff --git a/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_5_0_sm8150.h b/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_5_0_sm8150.h +index 9392ad2b4..35b3856f9 100644 +--- a/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_5_0_sm8150.h ++++ b/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_5_0_sm8150.h +@@ -15,6 +15,7 @@ static const struct dpu_caps sm8150_dpu_caps = { + .has_dim_layer = true, + .has_idle_pc = true, + .has_3d_merge = true, ++ .has_active_ctls = true, + .max_linewidth = 4096, + .pixel_ram_size = DEFAULT_PIXEL_RAM_SIZE, + .max_hdeci_exp = MAX_HORZ_DECIMATION, +diff --git a/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_6_0_sm8250.h b/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_6_0_sm8250.h +index 94278a3e3..be95a27c4 100644 +--- a/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_6_0_sm8250.h ++++ b/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_6_0_sm8250.h +@@ -15,6 +15,7 @@ static const struct dpu_caps sm8250_dpu_caps = { + .has_dim_layer = true, + .has_idle_pc = true, + .has_3d_merge = true, ++ .has_active_ctls = true, + .max_linewidth = 4096, + .pixel_ram_size = DEFAULT_PIXEL_RAM_SIZE, + }; +diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c +index 1cf7ff6ca..98f46cc98 100644 +--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c ++++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c +@@ -1117,14 +1117,18 @@ static void dpu_encoder_virt_atomic_mode_set(struct drm_encoder *drm_enc, + return; + } + +- if (!hw_ctl[i]) { ++ /* Use first (and only) CTL if active CTLs are supported */ ++ if (dpu_kms->catalog->caps->has_active_ctls) ++ phys->hw_ctl = to_dpu_hw_ctl(hw_ctl[0]); ++ else ++ phys->hw_ctl = to_dpu_hw_ctl(hw_ctl[i]); ++ if (!phys->hw_ctl) { + DPU_ERROR_ENC(dpu_enc, + "no ctl block assigned at idx: %d\n", i); + return; + } + + phys->hw_pp = dpu_enc->hw_pp[i]; +- phys->hw_ctl = to_dpu_hw_ctl(hw_ctl[i]); + + phys->cached_mode = crtc_state->adjusted_mode; + if (phys->ops.atomic_mode_set) +diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.h +index df024e10d..4e9533c7e 100644 +--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.h ++++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.h +@@ -359,6 +359,7 @@ struct dpu_caps { + bool has_dim_layer; + bool has_idle_pc; + bool has_3d_merge; ++ bool has_active_ctls; + /* SSPP limits */ + u32 max_linewidth; + u32 pixel_ram_size; +diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c +index 8759466e2..ba55b4381 100644 +--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c ++++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c +@@ -196,6 +196,7 @@ int dpu_rm_init(struct dpu_rm *rm, + } + rm->ctl_blks[ctl->id - CTL_0] = &hw->base; + } ++ rm->has_active_ctls = cat->caps->has_active_ctls; + + for (i = 0; i < cat->dspp_count; i++) { + struct dpu_hw_dspp *hw; +@@ -418,10 +419,15 @@ static int _dpu_rm_reserve_ctls( + int i = 0, j, num_ctls; + bool needs_split_display; + +- /* each hw_intf needs its own hw_ctrl to program its control path */ +- num_ctls = top->num_intf; ++ if (rm->has_active_ctls) { ++ num_ctls = 1; ++ needs_split_display = false; ++ } else { ++ /* each hw_intf needs its own hw_ctrl to program its control path */ ++ num_ctls = top->num_intf; + +- needs_split_display = _dpu_rm_needs_split_display(top); ++ needs_split_display = _dpu_rm_needs_split_display(top); ++ } + + for (j = 0; j < ARRAY_SIZE(rm->ctl_blks); j++) { + const struct dpu_hw_ctl *ctl; +@@ -439,7 +445,7 @@ static int _dpu_rm_reserve_ctls( + + DPU_DEBUG("ctl %d caps 0x%lX\n", j + CTL_0, features); + +- if (needs_split_display != has_split_display) ++ if (!rm->has_active_ctls && needs_split_display != has_split_display) + continue; + + ctl_idx[i] = j; +diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.h +index 2b551566c..6e4777f57 100644 +--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.h ++++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.h +@@ -33,6 +33,7 @@ struct dpu_rm { + struct dpu_hw_blk *merge_3d_blks[MERGE_3D_MAX - MERGE_3D_0]; + struct dpu_hw_blk *dsc_blks[DSC_MAX - DSC_0]; + struct dpu_hw_sspp *hw_sspp[SSPP_MAX - SSPP_NONE]; ++ bool has_active_ctls; + }; + + /** +-- +Armbian + diff --git a/patch/kernel/archive/sm8250-6.7/0003-drm-msm-dpu1-dpu_encoder_phys_-proper-suppor-for-act.patch b/patch/kernel/archive/sm8250-6.7/0003-drm-msm-dpu1-dpu_encoder_phys_-proper-suppor-for-act.patch new file mode 100644 index 000000000..738dbe337 --- /dev/null +++ b/patch/kernel/archive/sm8250-6.7/0003-drm-msm-dpu1-dpu_encoder_phys_-proper-suppor-for-act.patch @@ -0,0 +1,53 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Dmitry Baryshkov +Date: Sun, 14 Mar 2021 05:03:35 +0300 +Subject: drm/msm/dpu1: dpu_encoder_phys_*: proper suppor for active CTLs + +Adapt dpu_encoder_phys_* to properly support active CTLs and their +features. + +Signed-off-by: Dmitry Baryshkov +--- + drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_cmd.c | 2 ++ + drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_vid.c | 5 ++++- + 2 files changed, 6 insertions(+), 1 deletion(-) + +diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_cmd.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_cmd.c +index be185fe69..4eb2cc1e2 100644 +--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_cmd.c ++++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_cmd.c +@@ -57,6 +57,8 @@ static void _dpu_encoder_phys_cmd_update_intf_cfg( + return; + + intf_cfg.intf = phys_enc->hw_intf->idx; ++ if (phys_enc->split_role == ENC_ROLE_MASTER) ++ intf_cfg.intf_master = phys_enc->hw_intf->idx; + intf_cfg.intf_mode_sel = DPU_CTL_MODE_SEL_CMD; + intf_cfg.stream_sel = cmd_enc->stream_sel; + intf_cfg.mode_3d = dpu_encoder_helper_get_3d_blend_mode(phys_enc); +diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_vid.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_vid.c +index a01fda711..1293b0ea3 100644 +--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_vid.c ++++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_vid.c +@@ -271,6 +271,8 @@ static void dpu_encoder_phys_vid_setup_timing_engine( + DPU_DEBUG_VIDENC(phys_enc, "fmt_fourcc 0x%X\n", fmt_fourcc); + + intf_cfg.intf = phys_enc->hw_intf->idx; ++ if (phys_enc->split_role == ENC_ROLE_MASTER) ++ intf_cfg.intf_master = phys_enc->hw_intf->idx; + intf_cfg.intf_mode_sel = DPU_CTL_MODE_SEL_VID; + intf_cfg.stream_sel = 0; /* Don't care value for video mode */ + intf_cfg.mode_3d = dpu_encoder_helper_get_3d_blend_mode(phys_enc); +@@ -344,7 +346,8 @@ static void dpu_encoder_phys_vid_underrun_irq(void *arg) + static bool dpu_encoder_phys_vid_needs_single_flush( + struct dpu_encoder_phys *phys_enc) + { +- return phys_enc->split_role != ENC_ROLE_SOLO; ++ return !(phys_enc->hw_ctl->caps->features & BIT(DPU_CTL_ACTIVE_CFG)) && ++ phys_enc->split_role != ENC_ROLE_SOLO; + } + + static void dpu_encoder_phys_vid_atomic_mode_set( +-- +Armbian + diff --git a/patch/kernel/archive/sm8250-6.7/0004-dt-bindings-mfd-qcom-qca639x-add-binding-for-QCA639x.patch b/patch/kernel/archive/sm8250-6.7/0004-dt-bindings-mfd-qcom-qca639x-add-binding-for-QCA639x.patch new file mode 100644 index 000000000..4905e498f --- /dev/null +++ b/patch/kernel/archive/sm8250-6.7/0004-dt-bindings-mfd-qcom-qca639x-add-binding-for-QCA639x.patch @@ -0,0 +1,108 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Dmitry Baryshkov +Date: Sun, 20 Dec 2020 18:47:57 +0300 +Subject: dt-bindings: mfd: qcom,qca639x: add binding for QCA639x defvice + +Qualcomm QCA639x is a family of WiFi + Bluetooth SoCs, with BT part +being controlled through the UART and WiFi being present on PCIe bus. +Both blocks share common power sources. Add binding to describe power +sequencing required to power up this device. + +Signed-off-by: Dmitry Baryshkov +--- + Documentation/devicetree/bindings/mfd/qcom,qca639x.yaml | 84 ++++++++++ + 1 file changed, 84 insertions(+) + +diff --git a/Documentation/devicetree/bindings/mfd/qcom,qca639x.yaml b/Documentation/devicetree/bindings/mfd/qcom,qca639x.yaml +new file mode 100644 +index 000000000..d43c75da1 +--- /dev/null ++++ b/Documentation/devicetree/bindings/mfd/qcom,qca639x.yaml +@@ -0,0 +1,84 @@ ++# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause) ++%YAML 1.2 ++--- ++$id: "http://devicetree.org/schemas/mfd/qcom,qca639x.yaml#" ++$schema: "http://devicetree.org/meta-schemas/core.yaml#" ++ ++title: Qualcomm QCA639x WiFi + Bluetoot SoC bindings ++ ++maintainers: ++ - Andy Gross ++ - Bjorn Andersson ++ ++description: | ++ This binding describes thes Qualcomm QCA6390 or QCA6391 power supplies and ++ enablement pins. ++ ++properties: ++ compatible: ++ const: qcom,qca639x ++ ++ '#power-domain-cells': ++ const: 0 ++ ++ pinctrl-0: true ++ pinctrl-1: true ++ ++ pinctrl-names: ++ items: ++ - const: default ++ - const: active ++ ++ vddaon-supply: ++ description: ++ 0.95V always-on LDO power input ++ ++ vddpmu-supply: ++ description: ++ 0.95V LDO power input to PMU ++ ++ vddrfa1-supply: ++ description: ++ 0.95V LDO power input to RFA ++ ++ vddrfa2-supply: ++ description: ++ 1.25V LDO power input to RFA ++ ++ vddrfa3-supply: ++ description: ++ 2V LDO power input to RFA ++ ++ vddpcie1-supply: ++ description: ++ 1.25V LDO power input to PCIe part ++ ++ vddpcie2-supply: ++ description: ++ 2V LDO power input to PCIe part ++ ++ vddio-supply: ++ description: ++ 1.8V VIO input ++ ++additionalProperties: false ++ ++examples: ++ - | ++ qca639x: qca639x { ++ compatible = "qcom,qca639x"; ++ #power-domain-cells = <0>; ++ ++ vddaon-supply = <&vreg_s6a_0p95>; ++ vddpmu-supply = <&vreg_s2f_0p95>; ++ vddrfa1-supply = <&vreg_s2f_0p95>; ++ vddrfa2-supply = <&vreg_s8c_1p3>; ++ vddrfa3-supply = <&vreg_s5a_1p9>; ++ vddpcie1-supply = <&vreg_s8c_1p3>; ++ vddpcie2-supply = <&vreg_s5a_1p9>; ++ vddio-supply = <&vreg_s4a_1p8>; ++ pinctrl-names = "default", "active"; ++ pinctrl-0 = <&wlan_default_state &bt_default_state>; ++ pinctrl-1 = <&wlan_active_state &bt_active_state>; ++ }; ++... +-- +Armbian + diff --git a/patch/kernel/archive/sm8250-6.7/0005-mfd-qca639x-add-support-for-QCA639x-powerup-sequence.patch b/patch/kernel/archive/sm8250-6.7/0005-mfd-qca639x-add-support-for-QCA639x-powerup-sequence.patch new file mode 100644 index 000000000..b636bf859 --- /dev/null +++ b/patch/kernel/archive/sm8250-6.7/0005-mfd-qca639x-add-support-for-QCA639x-powerup-sequence.patch @@ -0,0 +1,223 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Dmitry Baryshkov +Date: Fri, 18 Dec 2020 16:24:56 +0300 +Subject: mfd: qca639x: add support for QCA639x powerup sequence + +Qualcomm QCA639x is a family of WiFi + Bluetooth SoCs, with BT part +being controlled through the UART and WiFi being present on PCIe +bus. Both blocks share common power sources. So add mfd device driver +handling power sequencing of QCA6390/1. + +Signed-off-by: Dmitry Baryshkov +--- + drivers/mfd/Kconfig | 12 + + drivers/mfd/Makefile | 1 + + drivers/mfd/qcom-qca639x.c | 162 ++++++++++ + 3 files changed, 175 insertions(+) + +diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig +index 90ce58fd6..2dd393ff2 100644 +--- a/drivers/mfd/Kconfig ++++ b/drivers/mfd/Kconfig +@@ -1123,6 +1123,18 @@ config MFD_PM8XXX + Say M here if you want to include support for PM8xxx chips as a + module. This will build a module called "pm8xxx-core". + ++config MFD_QCOM_QCA639X ++ tristate "Qualcomm QCA639x WiFi/Bluetooth module support" ++ depends on REGULATOR && PM_GENERIC_DOMAINS ++ help ++ If you say yes to this option, support will be included for Qualcomm ++ QCA639x family of WiFi and Bluetooth SoCs. Note, this driver supports ++ only power control for this SoC, you still have to enable individual ++ Bluetooth and WiFi drivers. ++ ++ Say M here if you want to include support for QCA639x chips as a ++ module. This will build a module called "qcom-qca639x". ++ + config MFD_QCOM_RPM + tristate "Qualcomm Resource Power Manager (RPM)" + depends on ARCH_QCOM && OF +diff --git a/drivers/mfd/Makefile b/drivers/mfd/Makefile +index c66f07edc..3e1b32dd0 100644 +--- a/drivers/mfd/Makefile ++++ b/drivers/mfd/Makefile +@@ -204,6 +204,7 @@ obj-$(CONFIG_MFD_SI476X_CORE) += si476x-core.o + obj-$(CONFIG_MFD_CS5535) += cs5535-mfd.o + obj-$(CONFIG_MFD_OMAP_USB_HOST) += omap-usb-host.o omap-usb-tll.o + obj-$(CONFIG_MFD_PM8XXX) += qcom-pm8xxx.o ssbi.o ++obj-$(CONFIG_MFD_QCOM_QCA639X) += qcom-qca639x.o + obj-$(CONFIG_MFD_QCOM_RPM) += qcom_rpm.o + obj-$(CONFIG_MFD_SPMI_PMIC) += qcom-spmi-pmic.o + obj-$(CONFIG_TPS65911_COMPARATOR) += tps65911-comparator.o +diff --git a/drivers/mfd/qcom-qca639x.c b/drivers/mfd/qcom-qca639x.c +new file mode 100644 +index 000000000..b31e4b65b +--- /dev/null ++++ b/drivers/mfd/qcom-qca639x.c +@@ -0,0 +1,162 @@ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#define MAX_NUM_REGULATORS 8 ++ ++static struct vreg { ++ const char *name; ++ unsigned int load_uA; ++} vregs [MAX_NUM_REGULATORS] = { ++ /* 2.0 V */ ++ { "vddpcie2", 15000 }, ++ { "vddrfa3", 400000 }, ++ ++ /* 0.95 V */ ++ { "vddaon", 100000 }, ++ { "vddpmu", 1250000 }, ++ { "vddrfa1", 200000 }, ++ ++ /* 1.35 V */ ++ { "vddrfa2", 400000 }, ++ { "vddpcie1", 35000 }, ++ ++ /* 1.8 V */ ++ { "vddio", 20000 }, ++}; ++ ++struct qca639x_data { ++ struct regulator_bulk_data regulators[MAX_NUM_REGULATORS]; ++ size_t num_vregs; ++ struct device *dev; ++ struct pinctrl_state *active_state; ++ struct generic_pm_domain pd; ++}; ++ ++#define domain_to_data(domain) container_of(domain, struct qca639x_data, pd) ++ ++static int qca639x_power_on(struct generic_pm_domain *domain) ++{ ++ struct qca639x_data *data = domain_to_data(domain); ++ int ret; ++ ++ dev_warn(&domain->dev, "DUMMY POWER ON\n"); ++ ++ ret = regulator_bulk_enable(data->num_vregs, data->regulators); ++ if (ret) { ++ dev_err(data->dev, "Failed to enable regulators"); ++ return ret; ++ } ++ ++ /* Wait for 1ms before toggling enable pins. */ ++ msleep(1); ++ ++ ret = pinctrl_select_state(data->dev->pins->p, data->active_state); ++ if (ret) { ++ dev_err(data->dev, "Failed to select active state"); ++ return ret; ++ } ++ ++ /* Wait for all power levels to stabilize */ ++ msleep(6); ++ ++ return 0; ++} ++ ++static int qca639x_power_off(struct generic_pm_domain *domain) ++{ ++ struct qca639x_data *data = domain_to_data(domain); ++ ++ dev_warn(&domain->dev, "DUMMY POWER OFF\n"); ++ ++ pinctrl_select_default_state(data->dev); ++ regulator_bulk_disable(data->num_vregs, data->regulators); ++ ++ return 0; ++} ++ ++static int qca639x_probe(struct platform_device *pdev) ++{ ++ struct qca639x_data *data; ++ struct device *dev = &pdev->dev; ++ int i, ret; ++ ++ if (!dev->pins || IS_ERR_OR_NULL(dev->pins->default_state)) ++ return -EINVAL; ++ ++ data = devm_kzalloc(dev, sizeof(*data), GFP_KERNEL); ++ if (!data) ++ return -ENOMEM; ++ ++ data->dev = dev; ++ data->num_vregs = ARRAY_SIZE(vregs); ++ ++ data->active_state = pinctrl_lookup_state(dev->pins->p, "active"); ++ if (IS_ERR(data->active_state)) { ++ ret = PTR_ERR(data->active_state); ++ dev_err(dev, "Failed to get active_state: %d\n", ret); ++ return ret; ++ } ++ ++ for (i = 0; i < data->num_vregs; i++) ++ data->regulators[i].supply = vregs[i].name; ++ ret = devm_regulator_bulk_get(dev, data->num_vregs, data->regulators); ++ if (ret < 0) ++ return ret; ++ ++ for (i = 0; i < data->num_vregs; i++) { ++ ret = regulator_set_load(data->regulators[i].consumer, vregs[i].load_uA); ++ if (ret) ++ return ret; ++ } ++ ++ data->pd.name = dev_name(dev); ++ data->pd.power_on = qca639x_power_on; ++ data->pd.power_off = qca639x_power_off; ++ ++ ret = pm_genpd_init(&data->pd, NULL, true); ++ if (ret < 0) ++ return ret; ++ ++ ret = of_genpd_add_provider_simple(dev->of_node, &data->pd); ++ if (ret < 0) { ++ pm_genpd_remove(&data->pd); ++ return ret; ++ } ++ ++ platform_set_drvdata(pdev, data); ++ ++ return 0; ++} ++ ++static int qca639x_remove(struct platform_device *pdev) ++{ ++ struct qca639x_data *data = platform_get_drvdata(pdev); ++ ++ pm_genpd_remove(&data->pd); ++ ++ return 0; ++} ++ ++static const struct of_device_id qca639x_of_match[] = { ++ { .compatible = "qcom,qca639x" }, ++}; ++ ++static struct platform_driver qca639x_driver = { ++ .probe = qca639x_probe, ++ .remove = qca639x_remove, ++ .driver = { ++ .name = "qca639x", ++ .of_match_table = qca639x_of_match, ++ }, ++}; ++ ++module_platform_driver(qca639x_driver); ++MODULE_LICENSE("GPL v2"); +-- +Armbian + diff --git a/patch/kernel/archive/sm8250-6.7/0006-mfd-qcom-qca639x-switch-to-platform-config-data.patch b/patch/kernel/archive/sm8250-6.7/0006-mfd-qcom-qca639x-switch-to-platform-config-data.patch new file mode 100644 index 000000000..7e68d8b8c --- /dev/null +++ b/patch/kernel/archive/sm8250-6.7/0006-mfd-qcom-qca639x-switch-to-platform-config-data.patch @@ -0,0 +1,188 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Dmitry Baryshkov +Date: Sat, 26 Feb 2022 21:13:18 +0300 +Subject: mfd: qcom-qca639x: switch to platform config data + +Change qcom-qca639x to use platform config data, in preparation to +supporting other devices. + +Signed-off-by: Dmitry Baryshkov +--- + drivers/mfd/qcom-qca639x.c | 74 ++++++---- + 1 file changed, 46 insertions(+), 28 deletions(-) + +diff --git a/drivers/mfd/qcom-qca639x.c b/drivers/mfd/qcom-qca639x.c +index b31e4b65b..22792561d 100644 +--- a/drivers/mfd/qcom-qca639x.c ++++ b/drivers/mfd/qcom-qca639x.c +@@ -1,4 +1,5 @@ + #include ++#include + #include + #include + #include +@@ -6,15 +7,21 @@ + #include + #include + #include ++#include + #include + #include + +-#define MAX_NUM_REGULATORS 8 +- +-static struct vreg { ++struct vreg { + const char *name; + unsigned int load_uA; +-} vregs [MAX_NUM_REGULATORS] = { ++}; ++ ++struct qca_cfg_data { ++ const struct vreg *vregs; ++ size_t num_vregs; ++}; ++ ++static const struct vreg qca6390_vregs[] = { + /* 2.0 V */ + { "vddpcie2", 15000 }, + { "vddrfa3", 400000 }, +@@ -32,19 +39,24 @@ static struct vreg { + { "vddio", 20000 }, + }; + +-struct qca639x_data { +- struct regulator_bulk_data regulators[MAX_NUM_REGULATORS]; ++static const struct qca_cfg_data qca6390_cfg_data = { ++ .vregs = qca6390_vregs, ++ .num_vregs = ARRAY_SIZE(qca6390_vregs), ++}; ++ ++struct qca_data { + size_t num_vregs; + struct device *dev; + struct pinctrl_state *active_state; + struct generic_pm_domain pd; ++ struct regulator_bulk_data regulators[]; + }; + +-#define domain_to_data(domain) container_of(domain, struct qca639x_data, pd) ++#define domain_to_data(domain) container_of(domain, struct qca_data, pd) + +-static int qca639x_power_on(struct generic_pm_domain *domain) ++static int qca_power_on(struct generic_pm_domain *domain) + { +- struct qca639x_data *data = domain_to_data(domain); ++ struct qca_data *data = domain_to_data(domain); + int ret; + + dev_warn(&domain->dev, "DUMMY POWER ON\n"); +@@ -70,9 +82,9 @@ static int qca639x_power_on(struct generic_pm_domain *domain) + return 0; + } + +-static int qca639x_power_off(struct generic_pm_domain *domain) ++static int qca_power_off(struct generic_pm_domain *domain) + { +- struct qca639x_data *data = domain_to_data(domain); ++ struct qca_data *data = domain_to_data(domain); + + dev_warn(&domain->dev, "DUMMY POWER OFF\n"); + +@@ -82,21 +94,26 @@ static int qca639x_power_off(struct generic_pm_domain *domain) + return 0; + } + +-static int qca639x_probe(struct platform_device *pdev) ++static int qca_probe(struct platform_device *pdev) + { +- struct qca639x_data *data; ++ const struct qca_cfg_data *cfg; ++ struct qca_data *data; + struct device *dev = &pdev->dev; + int i, ret; + ++ cfg = device_get_match_data(&pdev->dev); ++ if (!cfg) ++ return -EINVAL; ++ + if (!dev->pins || IS_ERR_OR_NULL(dev->pins->default_state)) + return -EINVAL; + +- data = devm_kzalloc(dev, sizeof(*data), GFP_KERNEL); ++ data = devm_kzalloc(dev, struct_size(data, regulators, cfg->num_vregs), GFP_KERNEL); + if (!data) + return -ENOMEM; + + data->dev = dev; +- data->num_vregs = ARRAY_SIZE(vregs); ++ data->num_vregs = cfg->num_vregs; + + data->active_state = pinctrl_lookup_state(dev->pins->p, "active"); + if (IS_ERR(data->active_state)) { +@@ -106,20 +123,20 @@ static int qca639x_probe(struct platform_device *pdev) + } + + for (i = 0; i < data->num_vregs; i++) +- data->regulators[i].supply = vregs[i].name; ++ data->regulators[i].supply = cfg->vregs[i].name; + ret = devm_regulator_bulk_get(dev, data->num_vregs, data->regulators); + if (ret < 0) + return ret; + + for (i = 0; i < data->num_vregs; i++) { +- ret = regulator_set_load(data->regulators[i].consumer, vregs[i].load_uA); ++ ret = regulator_set_load(data->regulators[i].consumer, cfg->vregs[i].load_uA); + if (ret) + return ret; + } + + data->pd.name = dev_name(dev); +- data->pd.power_on = qca639x_power_on; +- data->pd.power_off = qca639x_power_off; ++ data->pd.power_on = qca_power_on; ++ data->pd.power_off = qca_power_off; + + ret = pm_genpd_init(&data->pd, NULL, true); + if (ret < 0) +@@ -136,27 +153,28 @@ static int qca639x_probe(struct platform_device *pdev) + return 0; + } + +-static int qca639x_remove(struct platform_device *pdev) ++static int qca_remove(struct platform_device *pdev) + { +- struct qca639x_data *data = platform_get_drvdata(pdev); ++ struct qca_data *data = platform_get_drvdata(pdev); + + pm_genpd_remove(&data->pd); + + return 0; + } + +-static const struct of_device_id qca639x_of_match[] = { +- { .compatible = "qcom,qca639x" }, ++static const struct of_device_id qca_of_match[] = { ++ { .compatible = "qcom,qca6390", .data = &qca6390_cfg_data }, ++ { }, + }; + +-static struct platform_driver qca639x_driver = { +- .probe = qca639x_probe, +- .remove = qca639x_remove, ++static struct platform_driver qca_driver = { ++ .probe = qca_probe, ++ .remove = qca_remove, + .driver = { + .name = "qca639x", +- .of_match_table = qca639x_of_match, ++ .of_match_table = qca_of_match, + }, + }; + +-module_platform_driver(qca639x_driver); ++module_platform_driver(qca_driver); + MODULE_LICENSE("GPL v2"); +-- +Armbian + diff --git a/patch/kernel/archive/sm8250-6.7/0007-mfd-qcom-qca639x-change-qca639x-to-use-gpios-rather-.patch b/patch/kernel/archive/sm8250-6.7/0007-mfd-qcom-qca639x-change-qca639x-to-use-gpios-rather-.patch new file mode 100644 index 000000000..ed3c7d8c6 --- /dev/null +++ b/patch/kernel/archive/sm8250-6.7/0007-mfd-qcom-qca639x-change-qca639x-to-use-gpios-rather-.patch @@ -0,0 +1,88 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Dmitry Baryshkov +Date: Sat, 26 Feb 2022 21:17:22 +0300 +Subject: mfd: qcom-qca639x: change qca639x to use gpios rather than pinctrl + +Use gpio interface instead of pinctrl interface to toggle enable pins. + +Signed-off-by: Dmitry Baryshkov +--- + drivers/mfd/qcom-qca639x.c | 33 ++++++---- + 1 file changed, 19 insertions(+), 14 deletions(-) + +diff --git a/drivers/mfd/qcom-qca639x.c b/drivers/mfd/qcom-qca639x.c +index 22792561d..4de860e9b 100644 +--- a/drivers/mfd/qcom-qca639x.c ++++ b/drivers/mfd/qcom-qca639x.c +@@ -47,8 +47,9 @@ static const struct qca_cfg_data qca6390_cfg_data = { + struct qca_data { + size_t num_vregs; + struct device *dev; +- struct pinctrl_state *active_state; + struct generic_pm_domain pd; ++ struct gpio_desc *wlan_en_gpio; ++ struct gpio_desc *bt_en_gpio; + struct regulator_bulk_data regulators[]; + }; + +@@ -70,11 +71,10 @@ static int qca_power_on(struct generic_pm_domain *domain) + /* Wait for 1ms before toggling enable pins. */ + msleep(1); + +- ret = pinctrl_select_state(data->dev->pins->p, data->active_state); +- if (ret) { +- dev_err(data->dev, "Failed to select active state"); +- return ret; +- } ++ if (data->wlan_en_gpio) ++ gpiod_set_value(data->wlan_en_gpio, 1); ++ if (data->bt_en_gpio) ++ gpiod_set_value(data->bt_en_gpio, 1); + + /* Wait for all power levels to stabilize */ + msleep(6); +@@ -88,7 +88,11 @@ static int qca_power_off(struct generic_pm_domain *domain) + + dev_warn(&domain->dev, "DUMMY POWER OFF\n"); + +- pinctrl_select_default_state(data->dev); ++ if (data->wlan_en_gpio) ++ gpiod_set_value(data->wlan_en_gpio, 0); ++ if (data->bt_en_gpio) ++ gpiod_set_value(data->bt_en_gpio, 0); ++ + regulator_bulk_disable(data->num_vregs, data->regulators); + + return 0; +@@ -115,13 +119,6 @@ static int qca_probe(struct platform_device *pdev) + data->dev = dev; + data->num_vregs = cfg->num_vregs; + +- data->active_state = pinctrl_lookup_state(dev->pins->p, "active"); +- if (IS_ERR(data->active_state)) { +- ret = PTR_ERR(data->active_state); +- dev_err(dev, "Failed to get active_state: %d\n", ret); +- return ret; +- } +- + for (i = 0; i < data->num_vregs; i++) + data->regulators[i].supply = cfg->vregs[i].name; + ret = devm_regulator_bulk_get(dev, data->num_vregs, data->regulators); +@@ -134,6 +131,14 @@ static int qca_probe(struct platform_device *pdev) + return ret; + } + ++ data->wlan_en_gpio = devm_gpiod_get_optional(&pdev->dev, "wlan-en", GPIOD_OUT_LOW); ++ if (IS_ERR(data->wlan_en_gpio)) ++ return PTR_ERR(data->wlan_en_gpio); ++ ++ data->bt_en_gpio = devm_gpiod_get_optional(&pdev->dev, "bt-en", GPIOD_OUT_LOW); ++ if (IS_ERR(data->bt_en_gpio)) ++ return PTR_ERR(data->bt_en_gpio); ++ + data->pd.name = dev_name(dev); + data->pd.power_on = qca_power_on; + data->pd.power_off = qca_power_off; +-- +Armbian + diff --git a/patch/kernel/archive/sm8250-6.7/0008-Bluetooth-hci_qca-reopen-serial-port-after-toggling-.patch b/patch/kernel/archive/sm8250-6.7/0008-Bluetooth-hci_qca-reopen-serial-port-after-toggling-.patch new file mode 100644 index 000000000..ca1531a35 --- /dev/null +++ b/patch/kernel/archive/sm8250-6.7/0008-Bluetooth-hci_qca-reopen-serial-port-after-toggling-.patch @@ -0,0 +1,29 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Dmitry Baryshkov +Date: Sat, 26 Feb 2022 23:07:54 +0300 +Subject: Bluetooth: hci_qca: reopen serial port after toggling power + +Reopen the serial port after toggling the power. This saves us from +getting command timeouts on first command submitted. + +Signed-off-by: Dmitry Baryshkov +--- + drivers/bluetooth/hci_qca.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/drivers/bluetooth/hci_qca.c b/drivers/bluetooth/hci_qca.c +index 067e248e3..2d77e6272 100644 +--- a/drivers/bluetooth/hci_qca.c ++++ b/drivers/bluetooth/hci_qca.c +@@ -1797,6 +1797,8 @@ static int qca_power_on(struct hci_dev *hdev) + gpiod_set_value_cansleep(qcadev->bt_en, 1); + /* Controller needs time to bootup. */ + msleep(150); ++ serdev_device_close(hu->serdev); ++ ret = serdev_device_open(hu->serdev); + } + } + +-- +Armbian + diff --git a/patch/kernel/archive/sm8250-6.7/0009-drm-Add-drm-notifier-support.patch b/patch/kernel/archive/sm8250-6.7/0009-drm-Add-drm-notifier-support.patch new file mode 100644 index 000000000..cdc2d4ff0 --- /dev/null +++ b/patch/kernel/archive/sm8250-6.7/0009-drm-Add-drm-notifier-support.patch @@ -0,0 +1,135 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Jianhua Lu +Date: Thu, 4 Aug 2022 13:26:53 +0800 +Subject: drm: Add drm notifier support + +--- + drivers/gpu/drm/Makefile | 3 +- + drivers/gpu/drm/drm_notifier.c | 57 ++++++++++ + include/drm/drm_notifier.h | 37 ++++++ + 3 files changed, 96 insertions(+), 1 deletion(-) + +diff --git a/drivers/gpu/drm/Makefile b/drivers/gpu/drm/Makefile +index 8e1bde059..3095874a2 100644 +--- a/drivers/gpu/drm/Makefile ++++ b/drivers/gpu/drm/Makefile +@@ -45,7 +45,8 @@ drm-y := \ + drm_vblank.o \ + drm_vblank_work.o \ + drm_vma_manager.o \ +- drm_writeback.o ++ drm_writeback.o \ ++ drm_notifier.o + drm-$(CONFIG_DRM_LEGACY) += \ + drm_agpsupport.o \ + drm_bufs.o \ +diff --git a/drivers/gpu/drm/drm_notifier.c b/drivers/gpu/drm/drm_notifier.c +new file mode 100644 +index 000000000..792069640 +--- /dev/null ++++ b/drivers/gpu/drm/drm_notifier.c +@@ -0,0 +1,57 @@ ++/* ++ * Copyright (c) 2019, The Linux Foundation. All rights reserved. ++ * Copyright (C) 2021 XiaoMi, Inc. ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License version 2 and ++ * only version 2 as published by the Free Software Foundation. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ */ ++ ++#include ++ ++static BLOCKING_NOTIFIER_HEAD(mi_drm_notifier_list); ++ ++/** ++ * mi_drm_register_client - register a client notifier ++ * @nb: notifier block to callback on events ++ * ++ * This function registers a notifier callback function ++ * to msm_drm_notifier_list, which would be called when ++ * received unblank/power down event. ++ */ ++int mi_drm_register_client(struct notifier_block *nb) ++{ ++ return blocking_notifier_chain_register(&mi_drm_notifier_list, nb); ++} ++EXPORT_SYMBOL(mi_drm_register_client); ++ ++/** ++ * mi_drm_unregister_client - unregister a client notifier ++ * @nb: notifier block to callback on events ++ * ++ * This function unregisters the callback function from ++ * msm_drm_notifier_list. ++ */ ++int mi_drm_unregister_client(struct notifier_block *nb) ++{ ++ return blocking_notifier_chain_unregister(&mi_drm_notifier_list, nb); ++} ++EXPORT_SYMBOL(mi_drm_unregister_client); ++ ++/** ++ * mi_drm_notifier_call_chain - notify clients of drm_events ++ * @val: event MSM_DRM_EARLY_EVENT_BLANK or MSM_DRM_EVENT_BLANK ++ * @v: notifier data, inculde display id and display blank ++ * event(unblank or power down). ++ */ ++int mi_drm_notifier_call_chain(unsigned long val, void *v) ++{ ++ return blocking_notifier_call_chain(&mi_drm_notifier_list, val, v); ++} ++EXPORT_SYMBOL(mi_drm_notifier_call_chain); +\ No newline at end of file +diff --git a/include/drm/drm_notifier.h b/include/drm/drm_notifier.h +new file mode 100644 +index 000000000..fd0e97655 +--- /dev/null ++++ b/include/drm/drm_notifier.h +@@ -0,0 +1,37 @@ ++/* ++ * Copyright (c) 2019, The Linux Foundation. All rights reserved. ++ * Copyright (C) 2021 XiaoMi, Inc. ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License version 2 and ++ * only version 2 as published by the Free Software Foundation. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ */ ++ ++#ifndef _DRM_NOTIFIER_H_ ++#define _DRM_NOTIFIER_H_ ++ ++#include ++ ++/* A hardware display blank change occurred */ ++#define MI_DRM_EVENT_BLANK 0x01 ++/* A hardware display blank early change occurred */ ++#define MI_DRM_EARLY_EVENT_BLANK 0x02 ++ ++enum drm_notifier_data { ++ /* panel: power on */ ++ MI_DRM_BLANK_UNBLANK, ++ /* panel: power down */ ++ MI_DRM_BLANK_POWERDOWN, ++}; ++ ++int mi_drm_register_client(struct notifier_block *nb); ++int mi_drm_unregister_client(struct notifier_block *nb); ++int mi_drm_notifier_call_chain(unsigned long val, void *v); ++ ++#endif /* _DRM_NOTIFIER_H */ +-- +Armbian + diff --git a/patch/kernel/archive/sm8250-6.7/0010-drm-dsi-emit-panel-turn-on-off-signal-to-touchscreen.patch b/patch/kernel/archive/sm8250-6.7/0010-drm-dsi-emit-panel-turn-on-off-signal-to-touchscreen.patch new file mode 100644 index 000000000..0179ba67a --- /dev/null +++ b/patch/kernel/archive/sm8250-6.7/0010-drm-dsi-emit-panel-turn-on-off-signal-to-touchscreen.patch @@ -0,0 +1,59 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Jianhua Lu +Date: Mon, 17 Oct 2022 08:02:58 +0800 +Subject: drm: dsi: emit panel turn on/off signal to touchscreen + +--- + drivers/gpu/drm/msm/dsi/dsi_manager.c | 9 +++++++++ + 1 file changed, 9 insertions(+) + +diff --git a/drivers/gpu/drm/msm/dsi/dsi_manager.c b/drivers/gpu/drm/msm/dsi/dsi_manager.c +index 896f369fd..50d788138 100644 +--- a/drivers/gpu/drm/msm/dsi/dsi_manager.c ++++ b/drivers/gpu/drm/msm/dsi/dsi_manager.c +@@ -7,6 +7,7 @@ + + #include "msm_kms.h" + #include "dsi.h" ++#include "drm/drm_notifier.h" + + #define DSI_CLOCK_MASTER DSI_0 + #define DSI_CLOCK_SLAVE DSI_1 +@@ -303,6 +304,7 @@ static void dsi_mgr_bridge_pre_enable(struct drm_bridge *bridge) + struct mipi_dsi_host *host = msm_dsi->host; + bool is_bonded_dsi = IS_BONDED_DSI(); + int ret; ++ enum drm_notifier_data notifier_data; + + DBG("id=%d", id); + if (!msm_dsi_device_connected(msm_dsi)) +@@ -318,6 +320,9 @@ static void dsi_mgr_bridge_pre_enable(struct drm_bridge *bridge) + return; + } + ++ notifier_data = MI_DRM_BLANK_UNBLANK; ++ mi_drm_notifier_call_chain(MI_DRM_EVENT_BLANK, ¬ifier_data); ++ + ret = msm_dsi_host_enable(host); + if (ret) { + pr_err("%s: enable host %d failed, %d\n", __func__, id, ret); +@@ -361,12 +366,16 @@ static void dsi_mgr_bridge_post_disable(struct drm_bridge *bridge) + struct mipi_dsi_host *host = msm_dsi->host; + bool is_bonded_dsi = IS_BONDED_DSI(); + int ret; ++ enum drm_notifier_data notifier_data; + + DBG("id=%d", id); + + if (!msm_dsi_device_connected(msm_dsi)) + return; + ++ notifier_data = MI_DRM_BLANK_POWERDOWN; ++ mi_drm_notifier_call_chain(MI_DRM_EARLY_EVENT_BLANK, ¬ifier_data); ++ + /* + * Do nothing with the host if it is slave-DSI in case of bonded DSI. + * It is safe to call dsi_mgr_phy_disable() here because a single PHY +-- +Armbian + diff --git a/patch/kernel/archive/sm8250-6.7/0011-Input-Add-nt36523-touchscreen-driver.patch b/patch/kernel/archive/sm8250-6.7/0011-Input-Add-nt36523-touchscreen-driver.patch new file mode 100644 index 000000000..4d3ac7bad --- /dev/null +++ b/patch/kernel/archive/sm8250-6.7/0011-Input-Add-nt36523-touchscreen-driver.patch @@ -0,0 +1,3491 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Jianhua Lu +Date: Thu, 4 Aug 2022 13:26:26 +0800 +Subject: Input: Add nt36523 touchscreen driver + +--- + drivers/input/touchscreen/Kconfig | 2 + + drivers/input/touchscreen/Makefile | 1 + + drivers/input/touchscreen/nt36523/Kconfig | 11 + + drivers/input/touchscreen/nt36523/Makefile | 8 + + drivers/input/touchscreen/nt36523/nt36xxx.c | 1908 ++++++++++ + drivers/input/touchscreen/nt36523/nt36xxx.h | 240 ++ + drivers/input/touchscreen/nt36523/nt36xxx_fw_update.c | 857 +++++ + drivers/input/touchscreen/nt36523/nt36xxx_mem_map.h | 390 ++ + 8 files changed, 3417 insertions(+) + +diff --git a/drivers/input/touchscreen/Kconfig b/drivers/input/touchscreen/Kconfig +index e3e232454..1f8b33c2b 100644 +--- a/drivers/input/touchscreen/Kconfig ++++ b/drivers/input/touchscreen/Kconfig +@@ -12,6 +12,8 @@ menuconfig INPUT_TOUCHSCREEN + + if INPUT_TOUCHSCREEN + ++source "drivers/input/touchscreen/nt36523/Kconfig" ++ + config TOUCHSCREEN_88PM860X + tristate "Marvell 88PM860x touchscreen" + depends on MFD_88PM860X +diff --git a/drivers/input/touchscreen/Makefile b/drivers/input/touchscreen/Makefile +index 62bd24f3a..7d52592f4 100644 +--- a/drivers/input/touchscreen/Makefile ++++ b/drivers/input/touchscreen/Makefile +@@ -118,3 +118,4 @@ obj-$(CONFIG_TOUCHSCREEN_IQS5XX) += iqs5xx.o + obj-$(CONFIG_TOUCHSCREEN_IQS7211) += iqs7211.o + obj-$(CONFIG_TOUCHSCREEN_ZINITIX) += zinitix.o + obj-$(CONFIG_TOUCHSCREEN_HIMAX_HX83112B) += himax_hx83112b.o ++obj-$(CONFIG_TOUCHSCREEN_NT36523_SPI) += nt36523/ +diff --git a/drivers/input/touchscreen/nt36523/Kconfig b/drivers/input/touchscreen/nt36523/Kconfig +new file mode 100644 +index 000000000..5f4ef5abf +--- /dev/null ++++ b/drivers/input/touchscreen/nt36523/Kconfig +@@ -0,0 +1,11 @@ ++# ++# Novatek NT36523 touchscreen driver configuration ++# ++config TOUCHSCREEN_NT36523_SPI ++ tristate "Novatek NT36523 no flash SPI driver" ++ default n ++ help ++ Say Y here if you have a Novatek NT36523 no flash touchscreen connected ++ to your system by SPI bus. ++ ++ If unsure, say N. +diff --git a/drivers/input/touchscreen/nt36523/Makefile b/drivers/input/touchscreen/nt36523/Makefile +new file mode 100644 +index 000000000..d16afc8f1 +--- /dev/null ++++ b/drivers/input/touchscreen/nt36523/Makefile +@@ -0,0 +1,8 @@ ++# ++# Makefile for the Novatek NT36523 touchscreen driver. ++# ++ ++# Each configuration option enables a list of files. ++obj-$(CONFIG_TOUCHSCREEN_NT36523_SPI) += nt36523_ts.o ++nt36523_ts-y := nt36xxx.o \ ++ nt36xxx_fw_update.o +diff --git a/drivers/input/touchscreen/nt36523/nt36xxx.c b/drivers/input/touchscreen/nt36523/nt36xxx.c +new file mode 100644 +index 000000000..45500ad5c +--- /dev/null ++++ b/drivers/input/touchscreen/nt36523/nt36xxx.c +@@ -0,0 +1,1908 @@ ++/* ++ * Copyright (C) 2010 - 2018 Novatek, Inc. ++ * Copyright (C) 2021 XiaoMi, Inc. ++ * ++ * $Revision: 73033 $ ++ * $Date: 2020-11-26 10:09:14 +0800 (週四, 26 十一月 2020) $ ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation; either version 2 of the License, or ++ * (at your option) any later version. ++ * ++ * This program is distributed in the hope that it will be useful, but WITHOUT ++ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or ++ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for ++ * more details. ++ * ++ */ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#ifdef CONFIG_DRM ++#include ++#endif ++ ++#include "nt36xxx.h" ++ ++#if NVT_TOUCH_ESD_PROTECT ++#include ++#endif /* #if NVT_TOUCH_ESD_PROTECT */ ++ ++#if NVT_TOUCH_ESD_PROTECT ++static struct delayed_work nvt_esd_check_work; ++static struct workqueue_struct *nvt_esd_check_wq; ++static unsigned long irq_timer = 0; ++uint8_t esd_check = false; ++uint8_t esd_retry = 0; ++#endif /* #if NVT_TOUCH_ESD_PROTECT */ ++ ++struct nvt_ts_data *ts; ++ ++#if BOOT_UPDATE_FIRMWARE ++static struct workqueue_struct *nvt_fwu_wq; ++extern void Boot_Update_Firmware(struct work_struct *work); ++#endif ++ ++#ifdef CONFIG_DRM ++static int nvt_drm_notifier_callback(struct notifier_block *self, unsigned long event, void *data); ++#endif ++ ++static int32_t nvt_ts_suspend(struct device *dev); ++static int32_t nvt_ts_resume(struct device *dev); ++ ++uint32_t ENG_RST_ADDR = 0x7FFF80; ++uint32_t SWRST_N8_ADDR = 0; //read from dtsi ++uint32_t SPI_RD_FAST_ADDR = 0; //read from dtsi ++ ++#if TOUCH_KEY_NUM > 0 ++const uint16_t touch_key_array[TOUCH_KEY_NUM] = { ++ KEY_BACK, ++ KEY_HOME, ++ KEY_MENU ++}; ++#endif ++ ++static uint8_t bTouchIsAwake = 0; ++ ++/******************************************************* ++Description: ++ Novatek touchscreen irq enable/disable function. ++ ++return: ++ n.a. ++*******************************************************/ ++static void nvt_irq_enable(bool enable) ++{ ++ if (enable) { ++ if (!ts->irq_enabled) { ++ enable_irq(ts->client->irq); ++ ts->irq_enabled = true; ++ } ++ } else { ++ if (ts->irq_enabled) { ++ disable_irq(ts->client->irq); ++ ts->irq_enabled = false; ++ } ++ } ++} ++ ++static inline int32_t spi_read_write(struct spi_device *client, uint8_t *buf, size_t len , NVT_SPI_RW rw) ++{ ++ struct spi_message m; ++ struct spi_transfer t = { ++ .len = len, ++ }; ++ ++ memset(ts->xbuf, 0, len + DUMMY_BYTES); ++ memcpy(ts->xbuf, buf, len); ++ ++ switch (rw) { ++ case NVTREAD: ++ t.tx_buf = ts->xbuf; ++ t.rx_buf = ts->rbuf; ++ t.len = (len + DUMMY_BYTES); ++ break; ++ ++ case NVTWRITE: ++ t.tx_buf = ts->xbuf; ++ break; ++ } ++ ++ spi_message_init(&m); ++ spi_message_add_tail(&t, &m); ++ return spi_sync(client, &m); ++} ++ ++/******************************************************* ++Description: ++ Novatek touchscreen spi read function. ++ ++return: ++ Executive outcomes. 2---succeed. -5---I/O error ++*******************************************************/ ++int32_t CTP_SPI_READ(struct spi_device *client, uint8_t *buf, uint16_t len) ++{ ++ int32_t ret = -1; ++ int32_t retries = 0; ++ ++ mutex_lock(&ts->xbuf_lock); ++ ++ buf[0] = SPI_READ_MASK(buf[0]); ++ ++ while (retries < 5) { ++ ret = spi_read_write(client, buf, len, NVTREAD); ++ if (ret == 0) break; ++ retries++; ++ } ++ ++ if (unlikely(retries == 5)) { ++ NVT_ERR("read error, ret=%d\n", ret); ++ ret = -EIO; ++ } else { ++ memcpy((buf+1), (ts->rbuf+2), (len-1)); ++ } ++ ++ mutex_unlock(&ts->xbuf_lock); ++ ++ return ret; ++} ++ ++/******************************************************* ++Description: ++ Novatek touchscreen spi write function. ++ ++return: ++ Executive outcomes. 1---succeed. -5---I/O error ++*******************************************************/ ++int32_t CTP_SPI_WRITE(struct spi_device *client, uint8_t *buf, uint16_t len) ++{ ++ int32_t ret = -1; ++ int32_t retries = 0; ++ ++ mutex_lock(&ts->xbuf_lock); ++ ++ buf[0] = SPI_WRITE_MASK(buf[0]); ++ ++ while (retries < 5) { ++ ret = spi_read_write(client, buf, len, NVTWRITE); ++ if (ret == 0) break; ++ retries++; ++ } ++ ++ if (unlikely(retries == 5)) { ++ NVT_ERR("error, ret=%d\n", ret); ++ ret = -EIO; ++ } ++ ++ mutex_unlock(&ts->xbuf_lock); ++ ++ return ret; ++} ++ ++/******************************************************* ++Description: ++ Novatek touchscreen set index/page/addr address. ++ ++return: ++ Executive outcomes. 0---succeed. -5---access fail. ++*******************************************************/ ++int32_t nvt_set_page(uint32_t addr) ++{ ++ uint8_t buf[4] = {0}; ++ ++ buf[0] = 0xFF; //set index/page/addr command ++ buf[1] = (addr >> 15) & 0xFF; ++ buf[2] = (addr >> 7) & 0xFF; ++ ++ return CTP_SPI_WRITE(ts->client, buf, 3); ++} ++ ++/******************************************************* ++Description: ++ Novatek touchscreen write data to specify address. ++ ++return: ++ Executive outcomes. 0---succeed. -5---access fail. ++*******************************************************/ ++int32_t nvt_write_addr(uint32_t addr, uint8_t data) ++{ ++ int32_t ret = 0; ++ uint8_t buf[4] = {0}; ++ ++ //---set xdata index--- ++ buf[0] = 0xFF; //set index/page/addr command ++ buf[1] = (addr >> 15) & 0xFF; ++ buf[2] = (addr >> 7) & 0xFF; ++ ret = CTP_SPI_WRITE(ts->client, buf, 3); ++ if (ret) { ++ NVT_ERR("set page 0x%06X failed, ret = %d\n", addr, ret); ++ return ret; ++ } ++ ++ //---write data to index--- ++ buf[0] = addr & (0x7F); ++ buf[1] = data; ++ ret = CTP_SPI_WRITE(ts->client, buf, 2); ++ if (ret) { ++ NVT_ERR("write data to 0x%06X failed, ret = %d\n", addr, ret); ++ return ret; ++ } ++ ++ return ret; ++} ++ ++/******************************************************* ++Description: ++ Novatek touchscreen enable hw bld crc function. ++ ++return: ++ N/A. ++*******************************************************/ ++void nvt_bld_crc_enable(void) ++{ ++ uint8_t buf[4] = {0}; ++ ++ //---set xdata index to BLD_CRC_EN_ADDR--- ++ nvt_set_page(ts->mmap->BLD_CRC_EN_ADDR); ++ ++ //---read data from index--- ++ buf[0] = ts->mmap->BLD_CRC_EN_ADDR & (0x7F); ++ buf[1] = 0xFF; ++ CTP_SPI_READ(ts->client, buf, 2); ++ ++ //---write data to index--- ++ buf[0] = ts->mmap->BLD_CRC_EN_ADDR & (0x7F); ++ buf[1] = buf[1] | (0x01 << 7); ++ CTP_SPI_WRITE(ts->client, buf, 2); ++} ++ ++/******************************************************* ++Description: ++ Novatek touchscreen clear status & enable fw crc function. ++ ++return: ++ N/A. ++*******************************************************/ ++void nvt_fw_crc_enable(void) ++{ ++ uint8_t buf[4] = {0}; ++ ++ //---set xdata index to EVENT BUF ADDR--- ++ nvt_set_page(ts->mmap->EVENT_BUF_ADDR); ++ ++ //---clear fw reset status--- ++ buf[0] = EVENT_MAP_RESET_COMPLETE & (0x7F); ++ buf[1] = 0x00; ++ CTP_SPI_WRITE(ts->client, buf, 2); ++ ++ //---enable fw crc--- ++ buf[0] = EVENT_MAP_HOST_CMD & (0x7F); ++ buf[1] = 0xAE; //enable fw crc command ++ CTP_SPI_WRITE(ts->client, buf, 2); ++} ++ ++/******************************************************* ++Description: ++ Novatek touchscreen set boot ready function. ++ ++return: ++ N/A. ++*******************************************************/ ++void nvt_boot_ready(void) ++{ ++ //---write BOOT_RDY status cmds--- ++ nvt_write_addr(ts->mmap->BOOT_RDY_ADDR, 1); ++ ++ mdelay(5); ++ ++ if (!ts->hw_crc) { ++ //---write BOOT_RDY status cmds--- ++ nvt_write_addr(ts->mmap->BOOT_RDY_ADDR, 0); ++ ++ //---write POR_CD cmds--- ++ nvt_write_addr(ts->mmap->POR_CD_ADDR, 0xA0); ++ } ++} ++ ++/******************************************************* ++Description: ++ Novatek touchscreen enable auto copy mode function. ++ ++return: ++ N/A. ++*******************************************************/ ++void nvt_tx_auto_copy_mode(void) ++{ ++ //---write TX_AUTO_COPY_EN cmds--- ++ nvt_write_addr(ts->mmap->TX_AUTO_COPY_EN, 0x69); ++ ++ NVT_ERR("tx auto copy mode enable\n"); ++} ++ ++/******************************************************* ++Description: ++ Novatek touchscreen check spi dma tx info function. ++ ++return: ++ N/A. ++*******************************************************/ ++int32_t nvt_check_spi_dma_tx_info(void) ++{ ++ uint8_t buf[8] = {0}; ++ int32_t i = 0; ++ const int32_t retry = 200; ++ ++ for (i = 0; i < retry; i++) { ++ //---set xdata index to EVENT BUF ADDR--- ++ nvt_set_page(ts->mmap->SPI_DMA_TX_INFO); ++ ++ //---read fw status--- ++ buf[0] = ts->mmap->SPI_DMA_TX_INFO & 0x7F; ++ buf[1] = 0xFF; ++ CTP_SPI_READ(ts->client, buf, 2); ++ ++ if (buf[1] == 0x00) ++ break; ++ ++ usleep_range(1000, 1000); ++ } ++ ++ if (i >= retry) { ++ NVT_ERR("failed, i=%d, buf[1]=0x%02X\n", i, buf[1]); ++ return -1; ++ } else { ++ return 0; ++ } ++} ++ ++/******************************************************* ++Description: ++ Novatek touchscreen eng reset cmd ++ function. ++ ++return: ++ n.a. ++*******************************************************/ ++void nvt_eng_reset(void) ++{ ++ //---eng reset cmds to ENG_RST_ADDR--- ++ nvt_write_addr(ENG_RST_ADDR, 0x5A); ++ ++ mdelay(1); //wait tMCU_Idle2TP_REX_Hi after TP_RST ++} ++ ++/******************************************************* ++Description: ++ Novatek touchscreen reset MCU ++ function. ++ ++return: ++ n.a. ++*******************************************************/ ++void nvt_sw_reset(void) ++{ ++ //---software reset cmds to SWRST_N8_ADDR--- ++ nvt_write_addr(SWRST_N8_ADDR, 0x55); ++ ++ msleep(10); ++} ++ ++/******************************************************* ++Description: ++ Novatek touchscreen reset MCU then into idle mode ++ function. ++ ++return: ++ n.a. ++*******************************************************/ ++void nvt_sw_reset_idle(void) ++{ ++ //---MCU idle cmds to SWRST_N8_ADDR--- ++ nvt_write_addr(SWRST_N8_ADDR, 0xAA); ++ ++ msleep(15); ++} ++ ++/******************************************************* ++Description: ++ Novatek touchscreen reset MCU (boot) function. ++ ++return: ++ n.a. ++*******************************************************/ ++void nvt_bootloader_reset(void) ++{ ++ //---reset cmds to SWRST_N8_ADDR--- ++ nvt_write_addr(SWRST_N8_ADDR, 0x69); ++ ++ mdelay(5); //wait tBRST2FR after Bootload RST ++ ++ if (SPI_RD_FAST_ADDR) { ++ /* disable SPI_RD_FAST */ ++ nvt_write_addr(SPI_RD_FAST_ADDR, 0x00); ++ } ++} ++ ++/******************************************************* ++Description: ++ Novatek touchscreen clear FW status function. ++ ++return: ++ Executive outcomes. 0---succeed. -1---fail. ++*******************************************************/ ++int32_t nvt_clear_fw_status(void) ++{ ++ uint8_t buf[8] = {0}; ++ int32_t i = 0; ++ const int32_t retry = 20; ++ ++ for (i = 0; i < retry; i++) { ++ //---set xdata index to EVENT BUF ADDR--- ++ nvt_set_page(ts->mmap->EVENT_BUF_ADDR | EVENT_MAP_HANDSHAKING_or_SUB_CMD_BYTE); ++ ++ //---clear fw status--- ++ buf[0] = EVENT_MAP_HANDSHAKING_or_SUB_CMD_BYTE; ++ buf[1] = 0x00; ++ CTP_SPI_WRITE(ts->client, buf, 2); ++ ++ //---read fw status--- ++ buf[0] = EVENT_MAP_HANDSHAKING_or_SUB_CMD_BYTE; ++ buf[1] = 0xFF; ++ CTP_SPI_READ(ts->client, buf, 2); ++ ++ if (buf[1] == 0x00) ++ break; ++ ++ usleep_range(10000, 10000); ++ } ++ ++ if (i >= retry) { ++ NVT_ERR("failed, i=%d, buf[1]=0x%02X\n", i, buf[1]); ++ return -1; ++ } else { ++ return 0; ++ } ++} ++ ++/******************************************************* ++Description: ++ Novatek touchscreen check FW status function. ++ ++return: ++ Executive outcomes. 0---succeed. -1---failed. ++*******************************************************/ ++int32_t nvt_check_fw_status(void) ++{ ++ uint8_t buf[8] = {0}; ++ int32_t i = 0; ++ const int32_t retry = 50; ++ ++ for (i = 0; i < retry; i++) { ++ //---set xdata index to EVENT BUF ADDR--- ++ nvt_set_page(ts->mmap->EVENT_BUF_ADDR | EVENT_MAP_HANDSHAKING_or_SUB_CMD_BYTE); ++ ++ //---read fw status--- ++ buf[0] = EVENT_MAP_HANDSHAKING_or_SUB_CMD_BYTE; ++ buf[1] = 0x00; ++ CTP_SPI_READ(ts->client, buf, 2); ++ ++ if ((buf[1] & 0xF0) == 0xA0) ++ break; ++ ++ usleep_range(10000, 10000); ++ } ++ ++ if (i >= retry) { ++ NVT_ERR("failed, i=%d, buf[1]=0x%02X\n", i, buf[1]); ++ return -1; ++ } else { ++ return 0; ++ } ++} ++ ++/******************************************************* ++Description: ++ Novatek touchscreen check FW reset state function. ++ ++return: ++ Executive outcomes. 0---succeed. -1---failed. ++*******************************************************/ ++int32_t nvt_check_fw_reset_state(RST_COMPLETE_STATE check_reset_state) ++{ ++ uint8_t buf[8] = {0}; ++ int32_t ret = 0; ++ int32_t retry = 0; ++ int32_t retry_max = (check_reset_state == RESET_STATE_INIT) ? 10 : 50; ++ ++ //---set xdata index to EVENT BUF ADDR--- ++ nvt_set_page(ts->mmap->EVENT_BUF_ADDR | EVENT_MAP_RESET_COMPLETE); ++ ++ while (1) { ++ //---read reset state--- ++ buf[0] = EVENT_MAP_RESET_COMPLETE; ++ buf[1] = 0x00; ++ CTP_SPI_READ(ts->client, buf, 6); ++ ++ if ((buf[1] >= check_reset_state) && (buf[1] <= RESET_STATE_MAX)) { ++ ret = 0; ++ break; ++ } ++ ++ retry++; ++ if(unlikely(retry > retry_max)) { ++ NVT_ERR("error, retry=%d, buf[1]=0x%02X, 0x%02X, 0x%02X, 0x%02X, 0x%02X\n", ++ retry, buf[1], buf[2], buf[3], buf[4], buf[5]); ++ ret = -1; ++ break; ++ } ++ ++ usleep_range(10000, 10000); ++ } ++ ++ return ret; ++} ++ ++/******************************************************* ++Description: ++ Novatek touchscreen get novatek project id information ++ function. ++ ++return: ++ Executive outcomes. 0---success. -1---fail. ++*******************************************************/ ++int32_t nvt_read_pid(void) ++{ ++ uint8_t buf[4] = {0}; ++ int32_t ret = 0; ++ ++ //---set xdata index to EVENT BUF ADDR--- ++ nvt_set_page(ts->mmap->EVENT_BUF_ADDR | EVENT_MAP_PROJECTID); ++ ++ //---read project id--- ++ buf[0] = EVENT_MAP_PROJECTID; ++ buf[1] = 0x00; ++ buf[2] = 0x00; ++ CTP_SPI_READ(ts->client, buf, 3); ++ ++ ts->nvt_pid = (buf[2] << 8) + buf[1]; ++ ++ //---set xdata index to EVENT BUF ADDR--- ++ nvt_set_page(ts->mmap->EVENT_BUF_ADDR); ++ ++ NVT_LOG("PID=%04X\n", ts->nvt_pid); ++ ++ return ret; ++} ++ ++/******************************************************* ++Description: ++ Novatek touchscreen get firmware related information ++ function. ++ ++return: ++ Executive outcomes. 0---success. -1---fail. ++*******************************************************/ ++int32_t nvt_get_fw_info(void) ++{ ++ uint8_t buf[64] = {0}; ++ uint32_t retry_count = 0; ++ int32_t ret = 0; ++ ++info_retry: ++ //---set xdata index to EVENT BUF ADDR--- ++ nvt_set_page(ts->mmap->EVENT_BUF_ADDR | EVENT_MAP_FWINFO); ++ ++ //---read fw info--- ++ buf[0] = EVENT_MAP_FWINFO; ++ CTP_SPI_READ(ts->client, buf, 39); ++ ts->fw_ver = buf[1]; ++ ts->x_num = buf[3]; ++ ts->y_num = buf[4]; ++ ts->abs_x_max = (uint16_t)((buf[5] << 8) | buf[6]); ++ ts->abs_y_max = (uint16_t)((buf[7] << 8) | buf[8]); ++ ts->max_button_num = buf[11]; ++ ts->cascade = buf[34] & 0x01; ++ if (ts->pen_support) { ++ ts->x_gang_num = buf[37]; ++ ts->y_gang_num = buf[38]; ++ } ++ ++ //---clear x_num, y_num if fw info is broken--- ++ if ((buf[1] + buf[2]) != 0xFF) { ++ NVT_ERR("FW info is broken! fw_ver=0x%02X, ~fw_ver=0x%02X\n", buf[1], buf[2]); ++ ts->fw_ver = 0; ++ ts->x_num = 18; ++ ts->y_num = 32; ++ ts->abs_x_max = TOUCH_DEFAULT_MAX_WIDTH; ++ ts->abs_y_max = TOUCH_DEFAULT_MAX_HEIGHT; ++ ts->max_button_num = TOUCH_KEY_NUM; ++ ++ if(retry_count < 3) { ++ retry_count++; ++ NVT_ERR("retry_count=%d\n", retry_count); ++ goto info_retry; ++ } else { ++ NVT_ERR("Set default fw_ver=%d, x_num=%d, y_num=%d, " ++ "abs_x_max=%d, abs_y_max=%d, max_button_num=%d!\n", ++ ts->fw_ver, ts->x_num, ts->y_num, ++ ts->abs_x_max, ts->abs_y_max, ts->max_button_num); ++ ret = -1; ++ } ++ } else { ++ ret = 0; ++ } ++ ++ NVT_LOG("fw_ver = 0x%02X, fw_type = 0x%02X, x_num=%d, y_num=%d\n", ts->fw_ver, buf[14], ts->x_num, ts->y_num); ++ ++ //---Get Novatek PID--- ++ nvt_read_pid(); ++ ++ return ret; ++} ++ ++static void release_pen_event(void) { ++ if (ts && ts->pen_input_dev) { ++ input_report_abs(ts->pen_input_dev, ABS_X, 0); ++ input_report_abs(ts->pen_input_dev, ABS_Y, 0); ++ input_report_abs(ts->pen_input_dev, ABS_PRESSURE, 0); ++ input_report_abs(ts->pen_input_dev, ABS_TILT_X, 0); ++ input_report_abs(ts->pen_input_dev, ABS_TILT_Y, 0); ++ input_report_abs(ts->pen_input_dev, ABS_DISTANCE, 0); ++ input_report_key(ts->pen_input_dev, BTN_TOUCH, 0); ++ input_report_key(ts->pen_input_dev, BTN_TOOL_PEN, 0); ++ input_report_key(ts->pen_input_dev, BTN_STYLUS, 0); ++ input_report_key(ts->pen_input_dev, BTN_STYLUS2, 0); ++ input_sync(ts->pen_input_dev); ++ } ++} ++ ++/******************************************************* ++Description: ++ Novatek touchscreen parse device tree function. ++ ++return: ++ n.a. ++*******************************************************/ ++#ifdef CONFIG_OF ++static int32_t nvt_parse_dt(struct device *dev) ++{ ++ struct device_node *np = dev->of_node; ++ int32_t ret = 0; ++ ++#if NVT_TOUCH_SUPPORT_HW_RST ++ ts->reset_gpio = of_get_named_gpio_flags(np, "novatek,reset-gpio", 0, &ts->reset_flags); ++ NVT_LOG("novatek,reset-gpio=%d\n", ts->reset_gpio); ++#endif ++ ts->irq_gpio = of_get_named_gpio(np, "novatek,irq-gpio", 0); ++ NVT_LOG("novatek,irq-gpio=%d\n", ts->irq_gpio); ++ ++ ts->pen_support = of_property_read_bool(np, "novatek,pen-support"); ++ NVT_LOG("novatek,pen-support=%d\n", ts->pen_support); ++ ++ ts->wgp_stylus = of_property_read_bool(np, "novatek,wgp-stylus"); ++ NVT_LOG("novatek,wgp-stylus=%d\n", ts->wgp_stylus); ++ ++ ret = of_property_read_u32(np, "novatek,swrst-n8-addr", &SWRST_N8_ADDR); ++ if (ret) { ++ NVT_ERR("error reading novatek,swrst-n8-addr. ret=%d\n", ret); ++ return ret; ++ } else { ++ NVT_LOG("SWRST_N8_ADDR=0x%06X\n", SWRST_N8_ADDR); ++ } ++ ++ ret = of_property_read_u32(np, "novatek,spi-rd-fast-addr", &SPI_RD_FAST_ADDR); ++ if (ret) { ++ NVT_LOG("not support novatek,spi-rd-fast-addr\n"); ++ SPI_RD_FAST_ADDR = 0; ++ ret = 0; ++ } else { ++ NVT_LOG("SPI_RD_FAST_ADDR=0x%06X\n", SPI_RD_FAST_ADDR); ++ } ++ ++ ret = of_property_read_string(np, "firmware-name", &ts->fw_name); ++ if (ret) { ++ NVT_LOG("Unable to get touchscreen firmware name\n"); ++ ts->fw_name = DEFAULT_BOOT_UPDATE_FIRMWARE_NAME; ++ } ++ ++ ret = of_property_read_u32(np, "spi-max-frequency", &ts->spi_max_freq); ++ if (ret) { ++ NVT_LOG("Unable to get spi freq\n"); ++ return ret; ++ } else { ++ NVT_LOG("spi-max-frequency: %u\n", ts->spi_max_freq); ++ } ++ ++ return ret; ++} ++#else ++static int32_t nvt_parse_dt(struct device *dev) ++{ ++#if NVT_TOUCH_SUPPORT_HW_RST ++ ts->reset_gpio = NVTTOUCH_RST_PIN; ++#endif ++ ts->irq_gpio = NVTTOUCH_INT_PIN; ++ return 0; ++} ++#endif ++ ++/******************************************************* ++Description: ++ Novatek touchscreen config and request gpio ++ ++return: ++ Executive outcomes. 0---succeed. not 0---failed. ++*******************************************************/ ++static int nvt_gpio_config(struct nvt_ts_data *ts) ++{ ++ int32_t ret = 0; ++ ++#if NVT_TOUCH_SUPPORT_HW_RST ++ /* request RST-pin (Output/High) */ ++ if (gpio_is_valid(ts->reset_gpio)) { ++ ret = gpio_request_one(ts->reset_gpio, GPIOF_OUT_INIT_LOW, "NVT-tp-rst"); ++ if (ret) { ++ NVT_ERR("Failed to request NVT-tp-rst GPIO\n"); ++ goto err_request_reset_gpio; ++ } ++ } ++#endif ++ ++ /* request INT-pin (Input) */ ++ if (gpio_is_valid(ts->irq_gpio)) { ++ ret = gpio_request_one(ts->irq_gpio, GPIOF_IN, "NVT-int"); ++ if (ret) { ++ NVT_ERR("Failed to request NVT-int GPIO\n"); ++ goto err_request_irq_gpio; ++ } ++ } ++ ++ return ret; ++ ++err_request_irq_gpio: ++#if NVT_TOUCH_SUPPORT_HW_RST ++ gpio_free(ts->reset_gpio); ++err_request_reset_gpio: ++#endif ++ return ret; ++} ++ ++/******************************************************* ++Description: ++ Novatek touchscreen deconfig gpio ++ ++return: ++ n.a. ++*******************************************************/ ++static void nvt_gpio_deconfig(struct nvt_ts_data *ts) ++{ ++ if (gpio_is_valid(ts->irq_gpio)) ++ gpio_free(ts->irq_gpio); ++#if NVT_TOUCH_SUPPORT_HW_RST ++ if (gpio_is_valid(ts->reset_gpio)) ++ gpio_free(ts->reset_gpio); ++#endif ++} ++ ++static uint8_t nvt_fw_recovery(uint8_t *point_data) ++{ ++ uint8_t i = 0; ++ uint8_t detected = true; ++ ++ /* check pattern */ ++ for (i=1 ; i<7 ; i++) { ++ if (point_data[i] != 0x77) { ++ detected = false; ++ break; ++ } ++ } ++ ++ return detected; ++} ++ ++void nvt_set_dbgfw_status(bool enable) ++{ ++ ts->fw_debug = enable; ++} ++ ++bool nvt_get_dbgfw_status(void) ++{ ++ return ts->fw_debug; ++} ++ ++#if NVT_TOUCH_ESD_PROTECT ++void nvt_esd_check_enable(uint8_t enable) ++{ ++ /* update interrupt timer */ ++ irq_timer = jiffies; ++ /* clear esd_retry counter, if protect function is enabled */ ++ esd_retry = enable ? 0 : esd_retry; ++ /* enable/disable esd check flag */ ++ esd_check = enable; ++} ++ ++static void nvt_esd_check_func(struct work_struct *work) ++{ ++ unsigned int timer = jiffies_to_msecs(jiffies - irq_timer); ++ ++ //NVT_LOG("esd_check = %d (retry %d)\n", esd_check, esd_retry); //DEBUG ++ ++ if ((timer > NVT_TOUCH_ESD_CHECK_PERIOD) && esd_check) { ++ mutex_lock(&ts->lock); ++ NVT_ERR("do ESD recovery, timer = %d, retry = %d\n", timer, esd_retry); ++ /* do esd recovery, reload fw */ ++ nvt_update_firmware(ts->fw_name); ++ mutex_unlock(&ts->lock); ++ /* update interrupt timer */ ++ irq_timer = jiffies; ++ /* update esd_retry counter */ ++ esd_retry++; ++ } ++ ++ queue_delayed_work(nvt_esd_check_wq, &nvt_esd_check_work, ++ msecs_to_jiffies(NVT_TOUCH_ESD_CHECK_PERIOD)); ++} ++#endif /* #if NVT_TOUCH_ESD_PROTECT */ ++ ++#if NVT_TOUCH_WDT_RECOVERY ++static uint8_t recovery_cnt = 0; ++static uint8_t nvt_wdt_fw_recovery(uint8_t *point_data) ++{ ++ uint32_t recovery_cnt_max = 10; ++ uint8_t recovery_enable = false; ++ uint8_t i = 0; ++ ++ recovery_cnt++; ++ ++ /* check pattern */ ++ for (i=1 ; i<7 ; i++) { ++ if ((point_data[i] != 0xFD) && (point_data[i] != 0xFE)) { ++ recovery_cnt = 0; ++ break; ++ } ++ } ++ ++ if (recovery_cnt > recovery_cnt_max){ ++ recovery_enable = true; ++ recovery_cnt = 0; ++ } ++ ++ return recovery_enable; ++} ++#endif /* #if NVT_TOUCH_WDT_RECOVERY */ ++ ++#define PEN_DATA_LEN 14 ++#define FW_HISTORY_SIZE 128 ++static uint32_t nvt_dump_fw_history(void) ++{ ++ int32_t ret = 0; ++ uint8_t buf[FW_HISTORY_SIZE + 1 + DUMMY_BYTES] = {0}; ++ int32_t i = 0; ++ char *tmp_dump = NULL; ++ int32_t line_cnt = 0; ++ ++ if (ts->mmap->FW_HISTORY_ADDR == 0) { ++ NVT_ERR("FW_HISTORY_ADDR not available!\n"); ++ ret = -1; ++ goto exit_nvt_dump_fw_history; ++ } ++ nvt_set_page(ts->mmap->FW_HISTORY_ADDR); ++ buf[0] = ts->mmap->FW_HISTORY_ADDR & 0xFF; ++ CTP_SPI_READ(ts->client, buf, FW_HISTORY_SIZE + 1); ++ if (ret) { ++ NVT_ERR("CTP_SPI_READ failed.(%d)\n", ret); ++ ret = -1; ++ goto exit_nvt_dump_fw_history; ++ } ++ ++ tmp_dump = (char *)kzalloc(FW_HISTORY_SIZE * 4, GFP_KERNEL); ++ for (i = 0; i < FW_HISTORY_SIZE; i++) { ++ sprintf(tmp_dump + i * 3 + line_cnt, "%02X ", buf[1 + i]); ++ if ((i + 1) % 16 == 0) { ++ sprintf(tmp_dump + i * 3 + line_cnt + 3, "%c", '\n'); ++ line_cnt++; ++ } ++ } ++ NVT_LOG("%s", tmp_dump); ++ ++exit_nvt_dump_fw_history: ++ if (tmp_dump) { ++ kfree(tmp_dump); ++ tmp_dump = NULL; ++ } ++ nvt_set_page(ts->mmap->EVENT_BUF_ADDR); ++ ++ return ret; ++} ++ ++#define POINT_DATA_LEN 65 ++/******************************************************* ++Description: ++ Novatek touchscreen work function. ++ ++return: ++ n.a. ++*******************************************************/ ++static irqreturn_t nvt_ts_work_func(int irq, void *data) ++{ ++ int32_t ret = -1; ++ uint8_t point_data[POINT_DATA_LEN + PEN_DATA_LEN + 1 + DUMMY_BYTES] = {0}; ++ uint32_t position = 0; ++ uint32_t input_x = 0; ++ uint32_t input_y = 0; ++ uint32_t input_w = 0; ++ uint32_t input_p = 0; ++ uint8_t input_id = 0; ++#if MT_PROTOCOL_B ++ uint8_t press_id[TOUCH_MAX_FINGER_NUM] = {0}; ++#endif /* MT_PROTOCOL_B */ ++ int32_t i = 0; ++ int32_t finger_cnt = 0; ++ uint8_t pen_format_id = 0; ++ uint32_t pen_x = 0; ++ uint32_t pen_y = 0; ++ uint32_t pen_pressure = 0; ++ uint32_t pen_distance = 0; ++ int8_t pen_tilt_x = 0; ++ int8_t pen_tilt_y = 0; ++ uint32_t pen_btn1 = 0; ++ uint32_t pen_btn2 = 0; ++ uint32_t pen_battery = 0; ++ ++ mutex_lock(&ts->lock); ++ ++ if (ts->dev_pm_suspend) { ++ ret = wait_for_completion_timeout(&ts->dev_pm_suspend_completion, msecs_to_jiffies(500)); ++ if (!ret) { ++ NVT_ERR("system(spi) can't finished resuming procedure, skip it\n"); ++ goto XFER_ERROR; ++ } ++ } ++ ++ if (ts->pen_support) ++ ret = CTP_SPI_READ(ts->client, point_data, POINT_DATA_LEN + PEN_DATA_LEN + 1); ++ else ++ ret = CTP_SPI_READ(ts->client, point_data, POINT_DATA_LEN + 1); ++ if (ret < 0) { ++ NVT_ERR("CTP_SPI_READ failed.(%d)\n", ret); ++ goto XFER_ERROR; ++ } ++ ++ /*--- dump SPI buf --- ++ for (i = 0; i < 10; i++) { ++ NVT_LOG("%02X %02X %02X %02X %02X %02X \n", ++ point_data[1+i*6], point_data[2+i*6], point_data[3+i*6], point_data[4+i*6], point_data[5+i*6], point_data[6+i*6]); ++ } ++ */ ++ ++#if NVT_TOUCH_WDT_RECOVERY ++ /* ESD protect by WDT */ ++ if (nvt_wdt_fw_recovery(point_data)) { ++ NVT_ERR("Recover for fw reset, %02X\n", point_data[1]); ++ if (point_data[1] == 0xFD) { ++ NVT_ERR("Dump FW history:\n"); ++ nvt_dump_fw_history(); ++ } ++ nvt_update_firmware(ts->fw_name); ++ goto XFER_ERROR; ++ } ++#endif /* #if NVT_TOUCH_WDT_RECOVERY */ ++ ++ /* ESD protect by FW handshake */ ++ if (nvt_fw_recovery(point_data)) { ++#if NVT_TOUCH_ESD_PROTECT ++ nvt_esd_check_enable(true); ++#endif /* #if NVT_TOUCH_ESD_PROTECT */ ++ goto XFER_ERROR; ++ } ++ ++ finger_cnt = 0; ++ ++ for (i = 0; i < ts->max_touch_num; i++) { ++ position = 1 + 6 * i; ++ input_id = (uint8_t)(point_data[position + 0] >> 3); ++ if ((input_id == 0) || (input_id > ts->max_touch_num)) ++ continue; ++ ++ if (((point_data[position] & 0x07) == 0x01) || ((point_data[position] & 0x07) == 0x02)) { //finger down (enter & moving) ++#if NVT_TOUCH_ESD_PROTECT ++ /* update interrupt timer */ ++ irq_timer = jiffies; ++#endif /* #if NVT_TOUCH_ESD_PROTECT */ ++ input_x = (uint32_t)(point_data[position + 1] << 4) + (uint32_t) (point_data[position + 3] >> 4); ++ input_y = (uint32_t)(point_data[position + 2] << 4) + (uint32_t) (point_data[position + 3] & 0x0F); ++ if ((input_x < 0) || (input_y < 0)) ++ continue; ++ if ((input_x > ts->abs_x_max) || (input_y > ts->abs_y_max)) ++ continue; ++ input_w = (uint32_t)(point_data[position + 4]); ++ if (input_w == 0) ++ input_w = 1; ++ if (i < 2) { ++ input_p = (uint32_t)(point_data[position + 5]) + (uint32_t)(point_data[i + 63] << 8); ++ if (input_p > TOUCH_FORCE_NUM) ++ input_p = TOUCH_FORCE_NUM; ++ } else { ++ input_p = (uint32_t)(point_data[position + 5]); ++ } ++ if (input_p == 0) ++ input_p = 1; ++ ++#if MT_PROTOCOL_B ++ press_id[input_id - 1] = 1; ++ input_mt_slot(ts->input_dev, input_id - 1); ++ input_mt_report_slot_state(ts->input_dev, MT_TOOL_FINGER, true); ++#else /* MT_PROTOCOL_B */ ++ input_report_abs(ts->input_dev, ABS_MT_TRACKING_ID, input_id - 1); ++ input_report_key(ts->input_dev, BTN_TOUCH, 1); ++#endif /* MT_PROTOCOL_B */ ++ ++ input_report_abs(ts->input_dev, ABS_MT_POSITION_X, input_x); ++ input_report_abs(ts->input_dev, ABS_MT_POSITION_Y, input_y); ++ input_report_abs(ts->input_dev, ABS_MT_TOUCH_MAJOR, input_w); ++ input_report_abs(ts->input_dev, ABS_MT_PRESSURE, input_p); ++ ++#if MT_PROTOCOL_B ++#else /* MT_PROTOCOL_B */ ++ input_mt_sync(ts->input_dev); ++#endif /* MT_PROTOCOL_B */ ++ ++ finger_cnt++; ++ } ++ } ++ ++#if MT_PROTOCOL_B ++ for (i = 0; i < ts->max_touch_num; i++) { ++ if (press_id[i] != 1) { ++ input_mt_slot(ts->input_dev, i); ++ input_report_abs(ts->input_dev, ABS_MT_TOUCH_MAJOR, 0); ++ input_report_abs(ts->input_dev, ABS_MT_PRESSURE, 0); ++ input_mt_report_slot_state(ts->input_dev, MT_TOOL_FINGER, false); ++ } ++ } ++ input_report_key(ts->input_dev, BTN_TOUCH, (finger_cnt > 0)); ++#else /* MT_PROTOCOL_B */ ++ if (finger_cnt == 0) { ++ input_report_key(ts->input_dev, BTN_TOUCH, 0); ++ input_mt_sync(ts->input_dev); ++ } ++#endif /* MT_PROTOCOL_B */ ++ ++#if TOUCH_KEY_NUM > 0 ++ if (point_data[61] == 0xF8) { ++#if NVT_TOUCH_ESD_PROTECT ++ /* update interrupt timer */ ++ irq_timer = jiffies; ++#endif /* #if NVT_TOUCH_ESD_PROTECT */ ++ for (i = 0; i < ts->max_button_num; i++) { ++ input_report_key(ts->input_dev, touch_key_array[i], ((point_data[62] >> i) & 0x01)); ++ } ++ } else { ++ for (i = 0; i < ts->max_button_num; i++) { ++ input_report_key(ts->input_dev, touch_key_array[i], 0); ++ } ++ } ++#endif ++ ++ input_sync(ts->input_dev); ++ ++ if (ts->pen_support && ts->pen_input_dev_enable && !(ts->pen_is_charge)) { ++/* ++ //--- dump pen buf --- ++ printk("%02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X\n", ++ point_data[66], point_data[67], point_data[68], point_data[69], point_data[70], ++ point_data[71], point_data[72], point_data[73], point_data[74], point_data[75], ++ point_data[76], point_data[77], point_data[78], point_data[79]); ++*/ ++ // parse and handle pen report ++ pen_format_id = point_data[66]; ++ if (pen_format_id != 0xFF) { ++ if (pen_format_id == 0x01) { ++ // report pen data ++ pen_x = (uint32_t)(point_data[67] << 8) + (uint32_t)(point_data[68]); ++ pen_y = (uint32_t)(point_data[69] << 8) + (uint32_t)(point_data[70]); ++ if (pen_x >= ts->abs_x_max * 2 - 1) { ++ pen_x -= 1; ++ } ++ if (pen_y >= ts->abs_y_max * 2 - 1) { ++ pen_y -= 1; ++ } ++ pen_pressure = (uint32_t)(point_data[71] << 8) + (uint32_t)(point_data[72]); ++ pen_tilt_x = (int32_t)point_data[73]; ++ pen_tilt_y = (int32_t)point_data[74]; ++ pen_distance = (uint32_t)(point_data[75] << 8) + (uint32_t)(point_data[76]); ++ pen_btn1 = (uint32_t)(point_data[77] & 0x01); ++ pen_btn2 = (uint32_t)((point_data[77] >> 1) & 0x01); ++ pen_battery = (uint32_t)point_data[78]; ++// printk("x=%d,y=%d,p=%d,tx=%d,ty=%d,d=%d,b1=%d,b2=%d,bat=%d\n", pen_x, pen_y, pen_pressure, ++// pen_tilt_x, pen_tilt_y, pen_distance, pen_btn1, pen_btn2, pen_battery); ++ ++ input_report_abs(ts->pen_input_dev, ABS_X, pen_x); ++ input_report_abs(ts->pen_input_dev, ABS_Y, pen_y); ++ input_report_abs(ts->pen_input_dev, ABS_PRESSURE, pen_pressure); ++ input_report_key(ts->pen_input_dev, BTN_TOUCH, !!pen_pressure); ++ input_report_abs(ts->pen_input_dev, ABS_TILT_X, pen_tilt_x); ++ input_report_abs(ts->pen_input_dev, ABS_TILT_Y, pen_tilt_y); ++ input_report_abs(ts->pen_input_dev, ABS_DISTANCE, pen_distance); ++ input_report_key(ts->pen_input_dev, BTN_TOOL_PEN, !!pen_distance || !!pen_pressure); ++ input_report_key(ts->pen_input_dev, BTN_STYLUS, pen_btn1); ++ input_report_key(ts->pen_input_dev, BTN_STYLUS2, pen_btn2); ++ input_sync(ts->pen_input_dev); ++ // TBD: pen battery event report ++ // NVT_LOG("pen_battery=%d\n", pen_battery); ++ } else if (pen_format_id == 0xF0) { ++ // report Pen ID ++ } else { ++ NVT_ERR("Unknown pen format id!\n"); ++ goto XFER_ERROR; ++ } ++ } else { // pen_format_id = 0xFF, i.e. no pen present ++ release_pen_event(); ++ } ++ } /* if (ts->pen_support) */ ++ ++XFER_ERROR: ++ ++ mutex_unlock(&ts->lock); ++ return IRQ_HANDLED; ++} ++ ++ ++/******************************************************* ++Description: ++ Novatek touchscreen check chip version trim function. ++ ++return: ++ Executive outcomes. 0---NVT IC. -1---not NVT IC. ++*******************************************************/ ++static int8_t nvt_ts_check_chip_ver_trim(uint32_t chip_ver_trim_addr) ++{ ++ ++ ts->mmap = &NT36523_memory_map; ++ ts->carrier_system = NT36523_hw_info.carrier_system; ++ ts->hw_crc = NT36523_hw_info.hw_crc; ++ return 0; ++} ++ ++static void nvt_suspend_work(struct work_struct *work) ++{ ++ struct nvt_ts_data *ts_core = container_of(work, struct nvt_ts_data, suspend_work); ++ nvt_ts_suspend(&ts_core->client->dev); ++} ++ ++static void nvt_resume_work(struct work_struct *work) ++{ ++ struct nvt_ts_data *ts_core = container_of(work, struct nvt_ts_data, resume_work); ++ nvt_ts_resume(&ts_core->client->dev); ++} ++ ++/******************************************************* ++Description: ++ Novatek touchscreen driver probe function. ++ ++return: ++ Executive outcomes. 0---succeed. negative---failed ++*******************************************************/ ++static int32_t nvt_ts_probe(struct spi_device *client) ++{ ++ int32_t ret = 0; ++#if (TOUCH_KEY_NUM > 0) ++ int32_t retry = 0; ++#endif ++ ++ NVT_LOG("probe start\n"); ++ ++ ts = kzalloc(sizeof(struct nvt_ts_data), GFP_KERNEL); ++ if (ts == NULL) { ++ NVT_ERR("failed to allocated memory for nvt ts data\n"); ++ return -ENOMEM; ++ } ++ ++ ts->xbuf = (uint8_t *)kzalloc((NVT_TRANSFER_LEN+1+DUMMY_BYTES), GFP_KERNEL); ++ if(ts->xbuf == NULL) { ++ NVT_ERR("kzalloc for xbuf failed!\n"); ++ ret = -ENOMEM; ++ goto err_malloc_xbuf; ++ } ++ ++ ts->rbuf = (uint8_t *)kzalloc(NVT_READ_LEN, GFP_KERNEL); ++ if(ts->rbuf == NULL) { ++ NVT_ERR("kzalloc for rbuf failed!\n"); ++ ret = -ENOMEM; ++ goto err_malloc_rbuf; ++ } ++ ++ ts->client = client; ++ spi_set_drvdata(client, ts); ++ ++ //---prepare for spi parameter--- ++ if (ts->client->master->flags & SPI_MASTER_HALF_DUPLEX) { ++ NVT_ERR("Full duplex not supported by master\n"); ++ ret = -EIO; ++ goto err_ckeck_full_duplex; ++ } ++ ts->client->bits_per_word = 8; ++ ts->client->mode = SPI_MODE_0; ++ ++ ret = spi_setup(ts->client); ++ if (ret < 0) { ++ NVT_ERR("Failed to perform SPI setup\n"); ++ goto err_spi_setup; ++ } ++ ++#ifdef CONFIG_MTK_SPI ++ /* old usage of MTK spi API */ ++ memcpy(&ts->spi_ctrl, &spi_ctrdata, sizeof(struct mt_chip_conf)); ++ ts->client->controller_data = (void *)&ts->spi_ctrl; ++#endif ++ ++#ifdef CONFIG_SPI_MT65XX ++ /* new usage of MTK spi API */ ++ memcpy(&ts->spi_ctrl, &spi_ctrdata, sizeof(struct mtk_chip_config)); ++ ts->client->controller_data = (void *)&ts->spi_ctrl; ++#endif ++ ++ NVT_LOG("mode=%d, max_speed_hz=%d\n", ts->client->mode, ts->client->max_speed_hz); ++ ++ //---parse dts--- ++ ret = nvt_parse_dt(&client->dev); ++ if (ret) { ++ NVT_ERR("parse dt error\n"); ++ goto err_spi_setup; ++ } ++ ++ //---request and config GPIOs--- ++ ret = nvt_gpio_config(ts); ++ if (ret) { ++ NVT_ERR("gpio config error!\n"); ++ goto err_gpio_config_failed; ++ } ++ ++ mutex_init(&ts->lock); ++ mutex_init(&ts->xbuf_lock); ++ ++ //---eng reset before TP_RESX high ++ nvt_eng_reset(); ++ ++#if NVT_TOUCH_SUPPORT_HW_RST ++ gpio_set_value(ts->reset_gpio, 1); ++#endif ++ ++ // need 10ms delay after POR(power on reset) ++ msleep(10); ++ ++ //---check chip version trim--- ++ ret = nvt_ts_check_chip_ver_trim(CHIP_VER_TRIM_ADDR); ++ if (ret) { ++ NVT_LOG("try to check from old chip ver trim address\n"); ++ ret = nvt_ts_check_chip_ver_trim(CHIP_VER_TRIM_OLD_ADDR); ++ if (ret) { ++ NVT_ERR("chip is not identified\n"); ++ ret = -EINVAL; ++ goto err_chipvertrim_failed; ++ } ++ } ++ ++ ts->abs_x_max = TOUCH_DEFAULT_MAX_WIDTH; ++ ts->abs_y_max = TOUCH_DEFAULT_MAX_HEIGHT; ++ ++ //---allocate input device--- ++ ts->input_dev = input_allocate_device(); ++ if (ts->input_dev == NULL) { ++ NVT_ERR("allocate input device failed\n"); ++ ret = -ENOMEM; ++ goto err_input_dev_alloc_failed; ++ } ++ ++ ts->max_touch_num = TOUCH_MAX_FINGER_NUM; ++ ++#if TOUCH_KEY_NUM > 0 ++ ts->max_button_num = TOUCH_KEY_NUM; ++#endif ++ ++ ts->int_trigger_type = INT_TRIGGER_TYPE; ++ ++ //---set input device info.--- ++ ts->input_dev->evbit[0] = BIT_MASK(EV_SYN) | BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS); ++ ts->input_dev->keybit[BIT_WORD(BTN_TOUCH)] = BIT_MASK(BTN_TOUCH); ++ ts->input_dev->propbit[0] = BIT(INPUT_PROP_DIRECT); ++ ++ ts->db_wakeup = 0; ++ ts->fw_ver = 0; ++ ts->x_num = 32; ++ ts->y_num = 50; ++ ts->x_gang_num = 4; ++ ts->y_gang_num = 6; ++ ts->abs_x_max = TOUCH_DEFAULT_MAX_WIDTH; ++ ts->abs_y_max = TOUCH_DEFAULT_MAX_HEIGHT; ++ ts->max_button_num = TOUCH_KEY_NUM; ++ NVT_LOG("Set default fw_ver=%d, x_num=%d, y_num=%d, " ++ "abs_x_max=%d, abs_y_max=%d, max_button_num=%d!\n", ++ ts->fw_ver, ts->x_num, ts->y_num, ++ ts->abs_x_max, ts->abs_y_max, ts->max_button_num); ++ ++#if MT_PROTOCOL_B ++ input_mt_init_slots(ts->input_dev, ts->max_touch_num, 0); ++#endif ++ ++ input_set_abs_params(ts->input_dev, ABS_MT_PRESSURE, 0, TOUCH_FORCE_NUM, 0, 0); //pressure = TOUCH_FORCE_NUM ++ ++#if TOUCH_MAX_FINGER_NUM > 1 ++ input_set_abs_params(ts->input_dev, ABS_MT_TOUCH_MAJOR, 0, 255, 0, 0); //area = 255 ++ ++ input_set_abs_params(ts->input_dev, ABS_MT_POSITION_X, 0, ts->abs_x_max - 1, 0, 0); ++ input_set_abs_params(ts->input_dev, ABS_MT_POSITION_Y, 0, ts->abs_y_max - 1, 0, 0); ++#if MT_PROTOCOL_B ++ // no need to set ABS_MT_TRACKING_ID, input_mt_init_slots() already set it ++#else ++ input_set_abs_params(ts->input_dev, ABS_MT_TRACKING_ID, 0, ts->max_touch_num, 0, 0); ++#endif //MT_PROTOCOL_B ++#endif //TOUCH_MAX_FINGER_NUM > 1 ++ ++#if TOUCH_KEY_NUM > 0 ++ for (retry = 0; retry < ts->max_button_num; retry++) { ++ input_set_capability(ts->input_dev, EV_KEY, touch_key_array[retry]); ++ } ++#endif ++ ++ sprintf(ts->phys, "input/ts"); ++ ts->input_dev->name = NVT_TS_NAME; ++ ts->input_dev->phys = ts->phys; ++ ts->input_dev->id.bustype = BUS_SPI; ++ ++ //---register input device--- ++ ret = input_register_device(ts->input_dev); ++ if (ret) { ++ NVT_ERR("register input device (%s) failed. ret=%d\n", ts->input_dev->name, ret); ++ goto err_input_register_device_failed; ++ } ++ ++ if (ts->pen_support) { ++ //---allocate pen input device--- ++ ts->pen_input_dev = input_allocate_device(); ++ if (ts->pen_input_dev == NULL) { ++ NVT_ERR("allocate pen input device failed\n"); ++ ret = -ENOMEM; ++ goto err_pen_input_dev_alloc_failed; ++ } ++ ++ //---set pen input device info.--- ++ ts->pen_input_dev->evbit[0] = BIT_MASK(EV_SYN) | BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS); ++ ts->pen_input_dev->keybit[BIT_WORD(BTN_TOUCH)] = BIT_MASK(BTN_TOUCH); ++ ts->pen_input_dev->keybit[BIT_WORD(BTN_TOOL_PEN)] |= BIT_MASK(BTN_TOOL_PEN); ++ //ts->pen_input_dev->keybit[BIT_WORD(BTN_TOOL_RUBBER)] |= BIT_MASK(BTN_TOOL_RUBBER); ++ ts->pen_input_dev->keybit[BIT_WORD(BTN_STYLUS)] |= BIT_MASK(BTN_STYLUS); ++ ts->pen_input_dev->keybit[BIT_WORD(BTN_STYLUS2)] |= BIT_MASK(BTN_STYLUS2); ++ ts->pen_input_dev->propbit[0] = BIT(INPUT_PROP_DIRECT); ++ ++ if (ts->wgp_stylus) { ++ input_set_abs_params(ts->pen_input_dev, ABS_X, 0, ts->abs_x_max * 2 - 1, 0, 0); ++ input_set_abs_params(ts->pen_input_dev, ABS_Y, 0, ts->abs_y_max * 2 - 1, 0, 0); ++ } else { ++ input_set_abs_params(ts->pen_input_dev, ABS_X, 0, ts->abs_x_max - 1, 0, 0); ++ input_set_abs_params(ts->pen_input_dev, ABS_Y, 0, ts->abs_y_max - 1, 0, 0); ++ } ++ ++ input_set_abs_params(ts->pen_input_dev, ABS_PRESSURE, 0, PEN_PRESSURE_MAX, 0, 0); ++ input_set_abs_params(ts->pen_input_dev, ABS_DISTANCE, 0, PEN_DISTANCE_MAX, 0, 0); ++ input_set_abs_params(ts->pen_input_dev, ABS_TILT_X, PEN_TILT_MIN, PEN_TILT_MAX, 0, 0); ++ input_set_abs_params(ts->pen_input_dev, ABS_TILT_Y, PEN_TILT_MIN, PEN_TILT_MAX, 0, 0); ++ ++ sprintf(ts->pen_phys, "input/pen"); ++ ts->pen_input_dev->name = NVT_PEN_NAME; ++ ts->pen_input_dev->phys = ts->pen_phys; ++ ts->pen_input_dev->id.bustype = BUS_SPI; ++ ++ //---register pen input device--- ++ ret = input_register_device(ts->pen_input_dev); ++ if (ret) { ++ NVT_ERR("register pen input device (%s) failed. ret=%d\n", ts->pen_input_dev->name, ret); ++ goto err_pen_input_register_device_failed; ++ } ++ } /* if (ts->pen_support) */ ++ ++ //---set int-pin & request irq--- ++ client->irq = gpio_to_irq(ts->irq_gpio); ++ if (client->irq) { ++ NVT_LOG("int_trigger_type=%d\n", ts->int_trigger_type); ++ ts->irq_enabled = true; ++ ret = request_threaded_irq(client->irq, NULL, nvt_ts_work_func, ++ ts->int_trigger_type | IRQF_ONESHOT, NVT_SPI_NAME, ts); ++ if (ret != 0) { ++ NVT_ERR("request irq failed. ret=%d\n", ret); ++ goto err_int_request_failed; ++ } else { ++ nvt_irq_enable(false); ++ NVT_LOG("request irq %d succeed\n", client->irq); ++ } ++ } ++ ++ ts->pen_is_charge = false; ++ ++ ts->lkdown_readed =false; ++ pm_stay_awake(&client->dev); ++ ++ ts->ic_state = NVT_IC_INIT; ++ ts->dev_pm_suspend = false; ++ ts->gesture_command_delayed = -1; ++ init_completion(&ts->dev_pm_suspend_completion); ++ ts->fw_debug = false; ++ ++#ifdef CONFIG_FACTORY_BUILD ++ ts->pen_input_dev_enable = 1; ++#else ++ ts->pen_input_dev_enable = 0; ++#endif ++ ++#if BOOT_UPDATE_FIRMWARE ++ nvt_fwu_wq = alloc_workqueue("nvt_fwu_wq", WQ_UNBOUND | WQ_MEM_RECLAIM, 1); ++ if (!nvt_fwu_wq) { ++ NVT_ERR("nvt_fwu_wq create workqueue failed\n"); ++ ret = -ENOMEM; ++ goto err_create_nvt_fwu_wq_failed; ++ } ++ INIT_DELAYED_WORK(&ts->nvt_fwu_work, Boot_Update_Firmware); ++ // please make sure boot update start after display reset(RESX) sequence ++ queue_delayed_work(nvt_fwu_wq, &ts->nvt_fwu_work, msecs_to_jiffies(14000)); ++#endif ++ ++ NVT_LOG("NVT_TOUCH_ESD_PROTECT is %d\n", NVT_TOUCH_ESD_PROTECT); ++#if NVT_TOUCH_ESD_PROTECT ++ INIT_DELAYED_WORK(&nvt_esd_check_work, nvt_esd_check_func); ++ nvt_esd_check_wq = alloc_workqueue("nvt_esd_check_wq", WQ_MEM_RECLAIM, 1); ++ if (!nvt_esd_check_wq) { ++ NVT_ERR("nvt_esd_check_wq create workqueue failed\n"); ++ ret = -ENOMEM; ++ goto err_create_nvt_esd_check_wq_failed; ++ } ++ queue_delayed_work(nvt_esd_check_wq, &nvt_esd_check_work, ++ msecs_to_jiffies(NVT_TOUCH_ESD_CHECK_PERIOD)); ++#endif /* #if NVT_TOUCH_ESD_PROTECT */ ++ ++ ts->event_wq = alloc_workqueue("nvt-event-queue", ++ WQ_UNBOUND | WQ_HIGHPRI | WQ_CPU_INTENSIVE, 1); ++ if (!ts->event_wq) { ++ NVT_ERR("Can not create work thread for suspend/resume!!"); ++ ret = -ENOMEM; ++ goto err_alloc_work_thread_failed; ++ } ++ INIT_WORK(&ts->resume_work, nvt_resume_work); ++ INIT_WORK(&ts->suspend_work, nvt_suspend_work); ++ ++#ifdef CONFIG_DRM ++ ts->drm_notif.notifier_call = nvt_drm_notifier_callback; ++ ret = mi_drm_register_client(&ts->drm_notif); ++ if(ret) { ++ NVT_ERR("register drm_notifier failed. ret=%d\n", ret); ++ goto err_register_drm_notif_failed; ++ } ++#endif ++ ++ bTouchIsAwake = 1; ++ NVT_LOG("end\n"); ++ ++ nvt_irq_enable(true); ++ ++ return 0; ++ ++#ifdef CONFIG_DRM ++ if (mi_drm_unregister_client(&ts->drm_notif)) ++ NVT_ERR("Error occurred while unregistering drm_notifier.\n"); ++err_register_drm_notif_failed: ++#endif ++ ++err_alloc_work_thread_failed: ++ ++#if NVT_TOUCH_ESD_PROTECT ++ if (nvt_esd_check_wq) { ++ cancel_delayed_work_sync(&nvt_esd_check_work); ++ destroy_workqueue(nvt_esd_check_wq); ++ nvt_esd_check_wq = NULL; ++ } ++err_create_nvt_esd_check_wq_failed: ++#endif ++#if BOOT_UPDATE_FIRMWARE ++ if (nvt_fwu_wq) { ++ cancel_delayed_work_sync(&ts->nvt_fwu_work); ++ destroy_workqueue(nvt_fwu_wq); ++ nvt_fwu_wq = NULL; ++ } ++err_create_nvt_fwu_wq_failed: ++ ++#endif ++ free_irq(client->irq, ts); ++err_int_request_failed: ++ if (ts->pen_support) { ++ input_unregister_device(ts->pen_input_dev); ++ ts->pen_input_dev = NULL; ++ } ++err_pen_input_register_device_failed: ++ if (ts->pen_support) { ++ if (ts->pen_input_dev) { ++ input_free_device(ts->pen_input_dev); ++ ts->pen_input_dev = NULL; ++ } ++ } ++err_pen_input_dev_alloc_failed: ++ input_unregister_device(ts->input_dev); ++ ts->input_dev = NULL; ++err_input_register_device_failed: ++ if (ts->input_dev) { ++ input_free_device(ts->input_dev); ++ ts->input_dev = NULL; ++ } ++err_input_dev_alloc_failed: ++err_chipvertrim_failed: ++ mutex_destroy(&ts->xbuf_lock); ++ mutex_destroy(&ts->lock); ++ nvt_gpio_deconfig(ts); ++err_gpio_config_failed: ++err_spi_setup: ++err_ckeck_full_duplex: ++ spi_set_drvdata(client, NULL); ++ if (ts->rbuf) { ++ kfree(ts->rbuf); ++ ts->rbuf = NULL; ++ } ++err_malloc_rbuf: ++ if (ts->xbuf) { ++ kfree(ts->xbuf); ++ ts->xbuf = NULL; ++ } ++err_malloc_xbuf: ++ if (ts) { ++ kfree(ts); ++ ts = NULL; ++ } ++ return ret; ++} ++ ++/******************************************************* ++Description: ++ Novatek touchscreen driver release function. ++ ++return: ++ Executive outcomes. 0---succeed. ++*******************************************************/ ++static void nvt_ts_remove(struct spi_device *client) ++{ ++ NVT_LOG("Removing driver...\n"); ++ ++#ifdef CONFIG_DRM ++ if (mi_drm_unregister_client(&ts->drm_notif)) ++ NVT_ERR("Error occurred while unregistering drm_notifier.\n"); ++#endif ++ ++#if NVT_TOUCH_ESD_PROTECT ++ if (nvt_esd_check_wq) { ++ cancel_delayed_work_sync(&nvt_esd_check_work); ++ nvt_esd_check_enable(false); ++ destroy_workqueue(nvt_esd_check_wq); ++ nvt_esd_check_wq = NULL; ++ } ++#endif ++ ++#if BOOT_UPDATE_FIRMWARE ++ if (nvt_fwu_wq) { ++ cancel_delayed_work_sync(&ts->nvt_fwu_work); ++ destroy_workqueue(nvt_fwu_wq); ++ nvt_fwu_wq = NULL; ++ } ++#endif ++ ++ nvt_irq_enable(false); ++ free_irq(client->irq, ts); ++ ++ mutex_destroy(&ts->xbuf_lock); ++ mutex_destroy(&ts->lock); ++ ++ nvt_gpio_deconfig(ts); ++ ++ if (ts->pen_support) { ++ if (ts->pen_input_dev) { ++ input_unregister_device(ts->pen_input_dev); ++ ts->pen_input_dev = NULL; ++ } ++ } ++ ++ if (ts->input_dev) { ++ input_unregister_device(ts->input_dev); ++ ts->input_dev = NULL; ++ } ++ ++ spi_set_drvdata(client, NULL); ++ ++ if (ts) { ++ kfree(ts); ++ ts = NULL; ++ } ++} ++ ++static void nvt_ts_shutdown(struct spi_device *client) ++{ ++ NVT_LOG("Shutdown driver...\n"); ++ ++ nvt_irq_enable(false); ++ ++#ifdef CONFIG_DRM ++ if (mi_drm_unregister_client(&ts->drm_notif)) ++ NVT_ERR("Error occurred while unregistering drm_notifier.\n"); ++#endif ++ ++ destroy_workqueue(ts->event_wq); ++ ++#if NVT_TOUCH_ESD_PROTECT ++ if (nvt_esd_check_wq) { ++ cancel_delayed_work_sync(&nvt_esd_check_work); ++ nvt_esd_check_enable(false); ++ destroy_workqueue(nvt_esd_check_wq); ++ nvt_esd_check_wq = NULL; ++ } ++#endif /* #if NVT_TOUCH_ESD_PROTECT */ ++ ++#if BOOT_UPDATE_FIRMWARE ++ if (nvt_fwu_wq) { ++ cancel_delayed_work_sync(&ts->nvt_fwu_work); ++ destroy_workqueue(nvt_fwu_wq); ++ nvt_fwu_wq = NULL; ++ } ++#endif ++} ++ ++/******************************************************* ++Description: ++ Novatek touchscreen driver suspend function. ++ ++return: ++ Executive outcomes. 0---succeed. ++*******************************************************/ ++static int32_t nvt_ts_suspend(struct device *dev) ++{ ++ uint8_t buf[4] = {0}; ++#if MT_PROTOCOL_B ++ uint32_t i = 0; ++#endif ++ ++ if (!bTouchIsAwake) { ++ NVT_LOG("Touch is already suspend\n"); ++ return 0; ++ } ++ ++ pm_stay_awake(dev); ++ ts->ic_state = NVT_IC_SUSPEND_IN; ++ ++ if (!ts->db_wakeup) { ++ if (!ts->irq_enabled) ++ NVT_LOG("IRQ already disabled\n"); ++ else ++ nvt_irq_enable(false); ++ } ++ ++#if NVT_TOUCH_ESD_PROTECT ++ NVT_LOG("cancel delayed work sync\n"); ++ cancel_delayed_work_sync(&nvt_esd_check_work); ++ nvt_esd_check_enable(false); ++#endif /* #if NVT_TOUCH_ESD_PROTECT */ ++ ++ mutex_lock(&ts->lock); ++ ++ NVT_LOG("suspend start\n"); ++ ++ bTouchIsAwake = 0; ++ ++ if (ts->pen_input_dev_enable) { ++ NVT_LOG("if enable pen,will close it"); ++ } ++ ++ if (ts->db_wakeup) { ++ /*---write command to enter "wakeup gesture mode"---*/ ++ /*DoubleClick wakeup CMD was sent by display to meet timing*/ ++ /* ++ buf[0] = EVENT_MAP_HOST_CMD; ++ buf[1] = 0x13; ++ CTP_SPI_WRITE(ts->client, buf, 2); ++ */ ++ enable_irq_wake(ts->client->irq); ++ ++ NVT_LOG("Enabled touch wakeup gesture\n"); ++ } else { ++ /*---write command to enter "deep sleep mode"---*/ ++ buf[0] = EVENT_MAP_HOST_CMD; ++ buf[1] = 0x11; ++ CTP_SPI_WRITE(ts->client, buf, 2); ++ } ++ ++ mutex_unlock(&ts->lock); ++ ++ /* release all touches */ ++#if MT_PROTOCOL_B ++ for (i = 0; i < ts->max_touch_num; i++) { ++ input_mt_slot(ts->input_dev, i); ++ input_report_abs(ts->input_dev, ABS_MT_TOUCH_MAJOR, 0); ++ input_report_abs(ts->input_dev, ABS_MT_PRESSURE, 0); ++ input_mt_report_slot_state(ts->input_dev, MT_TOOL_FINGER, 0); ++ } ++#endif ++ input_report_key(ts->input_dev, BTN_TOUCH, 0); ++#if !MT_PROTOCOL_B ++ input_mt_sync(ts->input_dev); ++#endif ++ input_sync(ts->input_dev); ++ ++ msleep(50); ++ /* release pen event */ ++ release_pen_event(); ++ if (likely(ts->ic_state == NVT_IC_SUSPEND_IN)) ++ ts->ic_state = NVT_IC_SUSPEND_OUT; ++ else ++ NVT_ERR("IC state may error,caused by suspend/resume flow, please CHECK!!"); ++ pm_relax(dev); ++ NVT_LOG("end\n"); ++ ++ return 0; ++} ++ ++/******************************************************* ++Description: ++ Novatek touchscreen driver resume function. ++ ++return: ++ Executive outcomes. 0---succeed. ++*******************************************************/ ++static int32_t nvt_ts_resume(struct device *dev) ++{ ++ int ret = 0; ++ if (bTouchIsAwake) { ++ NVT_LOG("Touch is already resume\n"); ++ return 0; ++ } ++ ++ if (ts->dev_pm_suspend) ++ pm_stay_awake(dev); ++ ++ mutex_lock(&ts->lock); ++ ++ NVT_LOG("resume start\n"); ++ ts->ic_state = NVT_IC_RESUME_IN; ++ ++ // please make sure display reset(RESX) sequence and mipi dsi cmds sent before this ++#if NVT_TOUCH_SUPPORT_HW_RST ++ gpio_set_value(ts->reset_gpio, 1); ++#endif ++ ret = nvt_update_firmware(ts->fw_name); ++ if (ret) ++ NVT_ERR("download firmware failed\n"); ++ ++ nvt_check_fw_reset_state(RESET_STATE_REK); ++ ++ if (!ts->db_wakeup && !ts->irq_enabled) { ++ nvt_irq_enable(true); ++ } ++ ++#if NVT_TOUCH_ESD_PROTECT ++ nvt_esd_check_enable(false); ++ queue_delayed_work(nvt_esd_check_wq, &nvt_esd_check_work, ++ msecs_to_jiffies(NVT_TOUCH_ESD_CHECK_PERIOD)); ++#endif /* #if NVT_TOUCH_ESD_PROTECT */ ++ ++ bTouchIsAwake = 1; ++ ++ mutex_unlock(&ts->lock); ++ ++ if (likely(ts->ic_state == NVT_IC_RESUME_IN)) { ++ ts->ic_state = NVT_IC_RESUME_OUT; ++ } else { ++ NVT_ERR("IC state may error,caused by suspend/resume flow, please CHECK!!"); ++ } ++ if (ts->gesture_command_delayed >= 0){ ++ ts->db_wakeup = ts->gesture_command_delayed; ++ ts->gesture_command_delayed = -1; ++ NVT_LOG("execute delayed command, set double click wakeup %d\n", ts->db_wakeup); ++ } ++ ++ if (ts->dev_pm_suspend) ++ pm_relax(dev); ++ NVT_LOG("end\n"); ++ ++ return 0; ++} ++ ++ ++#ifdef CONFIG_DRM ++static int nvt_drm_notifier_callback(struct notifier_block *self, unsigned long event, void *data) ++{ ++ int blank = *(enum drm_notifier_data *)data; ++ struct nvt_ts_data *ts_data = ++ container_of(self, struct nvt_ts_data, drm_notif); ++ ++ if (data && ts_data) { ++ if (event == MI_DRM_EARLY_EVENT_BLANK) { ++ if (blank == MI_DRM_BLANK_POWERDOWN) { ++ NVT_LOG("event=%lu, *blank=%d\n", event, blank); ++ flush_workqueue(ts_data->event_wq); ++ queue_work(ts_data->event_wq, &ts_data->suspend_work); ++ } ++ } else if (event == MI_DRM_EVENT_BLANK) { ++ if (blank == MI_DRM_BLANK_UNBLANK) { ++ NVT_LOG("event=%lu, *blank=%d\n", event, blank); ++ flush_workqueue(ts_data->event_wq); ++ queue_work(ts_data->event_wq, &ts_data->resume_work); ++ } ++ } ++ } ++ ++ return 0; ++} ++#endif ++ ++static int nvt_pm_suspend(struct device *dev) ++{ ++ if (device_may_wakeup(dev) && ts->db_wakeup) { ++ NVT_LOG("enable touch irq wake\n"); ++ enable_irq_wake(ts->client->irq); ++ } ++ ts->dev_pm_suspend = true; ++ reinit_completion(&ts->dev_pm_suspend_completion); ++ ++ return 0; ++} ++ ++static int nvt_pm_resume(struct device *dev) ++{ ++ if (device_may_wakeup(dev) && ts->db_wakeup) { ++ NVT_LOG("disable touch irq wake\n"); ++ disable_irq_wake(ts->client->irq); ++ } ++ ts->dev_pm_suspend = false; ++ complete(&ts->dev_pm_suspend_completion); ++ ++ return 0; ++} ++ ++static const struct dev_pm_ops nvt_dev_pm_ops = { ++ .suspend = nvt_pm_suspend, ++ .resume = nvt_pm_resume, ++}; ++ ++static const struct spi_device_id nvt_ts_id[] = { ++ { NVT_SPI_NAME, 0 }, ++ { } ++}; ++ ++#ifdef CONFIG_OF ++static struct of_device_id nvt_match_table[] = { ++ { .compatible = "novatek,NVT-ts-spi",}, ++ { }, ++}; ++#endif ++ ++static struct spi_driver nvt_spi_driver = { ++ .probe = nvt_ts_probe, ++ .remove = nvt_ts_remove, ++ .shutdown = nvt_ts_shutdown, ++ .id_table = nvt_ts_id, ++ .driver = { ++ .name = NVT_SPI_NAME, ++ .owner = THIS_MODULE, ++#ifdef CONFIG_PM ++ .pm = &nvt_dev_pm_ops, ++#endif ++#ifdef CONFIG_OF ++ .of_match_table = nvt_match_table, ++#endif ++ }, ++}; ++ ++module_spi_driver(nvt_spi_driver); ++ ++MODULE_DESCRIPTION("Novatek Touchscreen Driver"); ++MODULE_LICENSE("GPL"); +diff --git a/drivers/input/touchscreen/nt36523/nt36xxx.h b/drivers/input/touchscreen/nt36523/nt36xxx.h +new file mode 100644 +index 000000000..2ec9ccb3b +--- /dev/null ++++ b/drivers/input/touchscreen/nt36523/nt36xxx.h +@@ -0,0 +1,240 @@ ++/* ++ * Copyright (C) 2010 - 2018 Novatek, Inc. ++ * Copyright (C) 2021 XiaoMi, Inc. ++ * ++ * $Revision: 69262 $ ++ * $Date: 2020-09-23 15:07:14 +0800 (週三, 23 九月 2020) $ ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation; either version 2 of the License, or ++ * (at your option) any later version. ++ * ++ * This program is distributed in the hope that it will be useful, but WITHOUT ++ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or ++ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for ++ * more details. ++ * ++ */ ++#ifndef _LINUX_NVT_TOUCH_H ++#define _LINUX_NVT_TOUCH_H ++ ++#include ++#include ++#include ++#include ++#include ++ ++#include "nt36xxx_mem_map.h" ++ ++#define NVT_DEBUG 1 ++ ++//---GPIO number--- ++#define NVTTOUCH_RST_PIN 980 ++#define NVTTOUCH_INT_PIN 943 ++ ++#define PINCTRL_STATE_ACTIVE "pmx_ts_active" ++#define PINCTRL_STATE_SUSPEND "pmx_ts_suspend" ++ ++//---INT trigger mode--- ++//#define IRQ_TYPE_EDGE_RISING 1 ++//#define IRQ_TYPE_EDGE_FALLING 2 ++#define INT_TRIGGER_TYPE IRQ_TYPE_EDGE_RISING ++ ++ ++//---SPI driver info.--- ++#define NVT_SPI_NAME "NVT-ts" ++ ++#if NVT_DEBUG ++#define NVT_LOG(fmt, args...) pr_err("[%s] %s %d: " fmt, NVT_SPI_NAME, __func__, __LINE__, ##args) ++#else ++#define NVT_LOG(fmt, args...) pr_info("[%s] %s %d: " fmt, NVT_SPI_NAME, __func__, __LINE__, ##args) ++#endif ++#define NVT_ERR(fmt, args...) pr_err("[%s] %s %d: " fmt, NVT_SPI_NAME, __func__, __LINE__, ##args) ++ ++//---Input device info.--- ++#define NVT_TS_NAME "NVTCapacitiveTouchScreen" ++#define NVT_PEN_NAME "NVTCapacitivePen" ++ ++//---Touch info.--- ++#define TOUCH_DEFAULT_MAX_WIDTH 1600 ++#define TOUCH_DEFAULT_MAX_HEIGHT 2560 ++#define TOUCH_MAX_FINGER_NUM 10 ++#define TOUCH_KEY_NUM 0 ++#if TOUCH_KEY_NUM > 0 ++extern const uint16_t touch_key_array[TOUCH_KEY_NUM]; ++#endif ++#define TOUCH_FORCE_NUM 1000 ++//---for Pen--- ++#define PEN_PRESSURE_MAX (4095) ++#define PEN_DISTANCE_MAX (1) ++#define PEN_TILT_MIN (-60) ++#define PEN_TILT_MAX (60) ++ ++/* Enable only when module have tp reset pin and connected to host */ ++#define NVT_TOUCH_SUPPORT_HW_RST 0 ++ ++//---Customerized func.--- ++#define NVT_TOUCH_MP 0 ++#define NVT_TOUCH_MP_SETTING_CRITERIA_FROM_CSV 0 ++#define MT_PROTOCOL_B 1 ++#define FUNCPAGE_PALM 4 ++#define PACKET_PALM_ON 3 ++#define PACKET_PALM_OFF 4 ++ ++#define BOOT_UPDATE_FIRMWARE 1 ++#define DEFAULT_BOOT_UPDATE_FIRMWARE_NAME "novatek/nt36523.bin" ++#define DEFAULT_MP_UPDATE_FIRMWARE_NAME "novatek_ts_mp.bin" ++ ++//---ESD Protect.--- ++#define NVT_TOUCH_ESD_PROTECT 1 ++#define NVT_TOUCH_ESD_CHECK_PERIOD 1500 /* ms */ ++#define NVT_TOUCH_WDT_RECOVERY 1 ++ ++enum nvt_ic_state { ++ NVT_IC_SUSPEND_IN, ++ NVT_IC_SUSPEND_OUT, ++ NVT_IC_RESUME_IN, ++ NVT_IC_RESUME_OUT, ++ NVT_IC_INIT, ++}; ++ ++struct nvt_config_info { ++ u8 tp_vendor; ++ u8 tp_color; ++ u8 display_maker; ++ u8 glass_vendor; ++ const char *nvt_fw_name; ++ const char *nvt_mp_name; ++ const char *nvt_limit_name; ++}; ++ ++struct nvt_ts_data { ++ struct spi_device *client; ++ struct input_dev *input_dev; ++ struct delayed_work nvt_fwu_work; ++ struct work_struct switch_mode_work; ++ struct work_struct pen_charge_state_change_work; ++ bool pen_is_charge; ++ struct notifier_block pen_charge_state_notifier; ++ uint16_t addr; ++ int8_t phys[32]; ++#if defined(CONFIG_FB) ++#ifdef CONFIG_DRM ++ struct notifier_block drm_notif; ++#else ++ struct notifier_block fb_notif; ++#endif ++#endif ++ uint32_t config_array_size; ++ struct nvt_config_info *config_array; ++ const char *fw_name; ++ bool lkdown_readed; ++ uint8_t fw_ver; ++ uint8_t x_num; ++ uint8_t y_num; ++ int ic_state; ++ uint16_t abs_x_max; ++ uint16_t abs_y_max; ++ uint8_t max_touch_num; ++ uint8_t max_button_num; ++ uint32_t int_trigger_type; ++ int32_t irq_gpio; ++ uint32_t irq_flags; ++ int32_t reset_gpio; ++ uint32_t reset_flags; ++ struct mutex lock; ++ const struct nvt_ts_mem_map *mmap; ++ uint8_t carrier_system; ++ uint8_t hw_crc; ++ uint16_t nvt_pid; ++ uint8_t *rbuf; ++ uint8_t *xbuf; ++ struct mutex xbuf_lock; ++ bool irq_enabled; ++ uint8_t cascade; ++ bool pen_support; ++ bool wgp_stylus; ++ uint8_t x_gang_num; ++ uint8_t y_gang_num; ++ struct input_dev *pen_input_dev; ++ bool pen_input_dev_enable; ++ int8_t pen_phys[32]; ++ struct workqueue_struct *event_wq; ++ struct work_struct suspend_work; ++ struct work_struct resume_work; ++ int result_type; ++ int panel_index; ++ uint32_t spi_max_freq; ++ int db_wakeup; ++ uint8_t debug_flag; ++ bool fw_debug; ++ bool dev_pm_suspend; ++ struct completion dev_pm_suspend_completion; ++ bool palm_sensor_switch; ++ int gesture_command_delayed; ++ struct pinctrl *ts_pinctrl; ++ struct pinctrl_state *pinctrl_state_active; ++ struct pinctrl_state *pinctrl_state_suspend; ++}; ++ ++typedef enum { ++ RESET_STATE_INIT = 0xA0,// IC reset ++ RESET_STATE_REK, // ReK baseline ++ RESET_STATE_REK_FINISH, // baseline is ready ++ RESET_STATE_NORMAL_RUN, // normal run ++ RESET_STATE_MAX = 0xAF ++} RST_COMPLETE_STATE; ++ ++typedef enum { ++ EVENT_MAP_HOST_CMD = 0x50, ++ EVENT_MAP_HANDSHAKING_or_SUB_CMD_BYTE = 0x51, ++ EVENT_MAP_RESET_COMPLETE = 0x60, ++ EVENT_MAP_FWINFO = 0x78, ++ EVENT_MAP_PROJECTID = 0x9A, ++} SPI_EVENT_MAP; ++ ++//---SPI READ/WRITE--- ++#define SPI_WRITE_MASK(a) (a | 0x80) ++#define SPI_READ_MASK(a) (a & 0x7F) ++ ++#define DUMMY_BYTES (1) ++#define NVT_TRANSFER_LEN (63*1024) ++#define NVT_READ_LEN (2*1024) ++ ++typedef enum { ++ NVTWRITE = 0, ++ NVTREAD = 1 ++} NVT_SPI_RW; ++ ++//---extern structures--- ++extern struct nvt_ts_data *ts; ++ ++//---extern functions--- ++int32_t CTP_SPI_READ(struct spi_device *client, uint8_t *buf, uint16_t len); ++int32_t CTP_SPI_WRITE(struct spi_device *client, uint8_t *buf, uint16_t len); ++void nvt_bootloader_reset(void); ++void nvt_eng_reset(void); ++void nvt_sw_reset(void); ++void nvt_sw_reset_idle(void); ++void nvt_boot_ready(void); ++void nvt_bld_crc_enable(void); ++void nvt_fw_crc_enable(void); ++void nvt_tx_auto_copy_mode(void); ++void nvt_set_dbgfw_status(bool enable); ++void nvt_match_fw(void); ++int32_t nvt_update_firmware(const char *firmware_name); ++int32_t nvt_check_fw_reset_state(RST_COMPLETE_STATE check_reset_state); ++int32_t nvt_get_fw_info(void); ++int32_t nvt_clear_fw_status(void); ++int32_t nvt_check_fw_status(void); ++int32_t nvt_check_spi_dma_tx_info(void); ++int32_t nvt_set_page(uint32_t addr); ++int32_t nvt_write_addr(uint32_t addr, uint8_t data); ++bool nvt_get_dbgfw_status(void); ++int32_t nvt_set_pocket_palm_switch(uint8_t pocket_palm_switch); ++#if NVT_TOUCH_ESD_PROTECT ++extern void nvt_esd_check_enable(uint8_t enable); ++#endif /* #if NVT_TOUCH_ESD_PROTECT */ ++ ++#endif /* _LINUX_NVT_TOUCH_H */ +diff --git a/drivers/input/touchscreen/nt36523/nt36xxx_fw_update.c b/drivers/input/touchscreen/nt36523/nt36xxx_fw_update.c +new file mode 100644 +index 000000000..4f383dac2 +--- /dev/null ++++ b/drivers/input/touchscreen/nt36523/nt36xxx_fw_update.c +@@ -0,0 +1,857 @@ ++/* ++ * Copyright (C) 2010 - 2018 Novatek, Inc. ++ * Copyright (C) 2021 XiaoMi, Inc. ++ * ++ * $Revision: 68983 $ ++ * $Date: 2020-09-17 09:43:23 +0800 (週四, 17 九月 2020) $ ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation; either version 2 of the License, or ++ * (at your option) any later version. ++ * ++ * This program is distributed in the hope that it will be useful, but WITHOUT ++ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or ++ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for ++ * more details. ++ * ++ */ ++ ++#include ++#include ++ ++#include "nt36xxx.h" ++ ++#if BOOT_UPDATE_FIRMWARE ++ ++#define SIZE_4KB 4096 ++#define FLASH_SECTOR_SIZE SIZE_4KB ++#define FW_BIN_VER_OFFSET (fw_need_write_size - SIZE_4KB) ++#define FW_BIN_VER_BAR_OFFSET (FW_BIN_VER_OFFSET + 1) ++#define NVT_FLASH_END_FLAG_LEN 3 ++#define NVT_FLASH_END_FLAG_ADDR (fw_need_write_size - NVT_FLASH_END_FLAG_LEN) ++ ++static ktime_t start, end; ++const struct firmware *fw_entry = NULL; ++static size_t fw_need_write_size = 0; ++static uint8_t *fwbuf = NULL; ++ ++struct nvt_ts_bin_map { ++ char name[12]; ++ uint32_t BIN_addr; ++ uint32_t SRAM_addr; ++ uint32_t size; ++ uint32_t crc; ++}; ++ ++static struct nvt_ts_bin_map *bin_map; ++ ++/******************************************************* ++Description: ++ Novatek touchscreen init variable and allocate buffer ++for download firmware function. ++ ++return: ++ n.a. ++*******************************************************/ ++static int32_t nvt_download_init(void) ++{ ++ /* allocate buffer for transfer firmware */ ++ //NVT_LOG("NVT_TRANSFER_LEN = 0x%06X\n", NVT_TRANSFER_LEN); ++ ++ if (fwbuf == NULL) { ++ fwbuf = (uint8_t *)kzalloc((NVT_TRANSFER_LEN + 1 + DUMMY_BYTES), GFP_KERNEL); ++ if(fwbuf == NULL) { ++ NVT_ERR("kzalloc for fwbuf failed!\n"); ++ return -ENOMEM; ++ } ++ } ++ ++ return 0; ++} ++ ++/******************************************************* ++Description: ++ Novatek touchscreen checksum function. Calculate bin ++file checksum for comparison. ++ ++return: ++ n.a. ++*******************************************************/ ++static uint32_t CheckSum(const u8 *data, size_t len) ++{ ++ uint32_t i = 0; ++ uint32_t checksum = 0; ++ ++ for (i = 0 ; i < len+1 ; i++) ++ checksum += data[i]; ++ ++ checksum += len; ++ checksum = ~checksum +1; ++ ++ return checksum; ++} ++ ++static uint32_t byte_to_word(const uint8_t *data) ++{ ++ return data[0] + (data[1] << 8) + (data[2] << 16) + (data[3] << 24); ++} ++ ++/******************************************************* ++Description: ++ Novatek touchscreen parsing bin header function. ++ ++return: ++ n.a. ++*******************************************************/ ++static uint32_t partition = 0; ++static uint8_t ilm_dlm_num = 2; ++static uint8_t cascade_2nd_header_info = 0; ++static int32_t nvt_bin_header_parser(const u8 *fwdata, size_t fwsize) ++{ ++ uint32_t list = 0; ++ uint32_t pos = 0x00; ++ uint32_t end = 0x00; ++ uint8_t info_sec_num = 0; ++ uint8_t ovly_sec_num = 0; ++ uint8_t ovly_info = 0; ++ uint8_t find_bin_header = 0; ++ ++ /* Find the header size */ ++ end = fwdata[0] + (fwdata[1] << 8) + (fwdata[2] << 16) + (fwdata[3] << 24); ++ ++ /* check cascade next header */ ++ cascade_2nd_header_info = (fwdata[0x20] & 0x02) >> 1; ++ NVT_LOG("cascade_2nd_header_info = %d\n", cascade_2nd_header_info); ++ ++ if (cascade_2nd_header_info) { ++ pos = 0x30; // info section start at 0x30 offset ++ while (pos < (end / 2)) { ++ info_sec_num ++; ++ pos += 0x10; /* each header info is 16 bytes */ ++ } ++ ++ info_sec_num = info_sec_num + 1; //next header section ++ } else { ++ pos = 0x30; // info section start at 0x30 offset ++ while (pos < end) { ++ info_sec_num ++; ++ pos += 0x10; /* each header info is 16 bytes */ ++ } ++ } ++ ++ /* ++ * Find the DLM OVLY section ++ * [0:3] Overlay Section Number ++ * [4] Overlay Info ++ */ ++ ovly_info = (fwdata[0x28] & 0x10) >> 4; ++ ovly_sec_num = (ovly_info) ? (fwdata[0x28] & 0x0F) : 0; ++ ++ /* ++ * calculate all partition number ++ * ilm_dlm_num (ILM & DLM) + ovly_sec_num + info_sec_num ++ */ ++ partition = ilm_dlm_num + ovly_sec_num + info_sec_num; ++ NVT_LOG("ovly_info = %d, ilm_dlm_num = %d, ovly_sec_num = %d, info_sec_num = %d, partition = %d\n", ++ ovly_info, ilm_dlm_num, ovly_sec_num, info_sec_num, partition); ++ ++ /* allocated memory for header info */ ++ bin_map = (struct nvt_ts_bin_map *)kzalloc((partition+1) * sizeof(struct nvt_ts_bin_map), GFP_KERNEL); ++ if(bin_map == NULL) { ++ NVT_ERR("kzalloc for bin_map failed!\n"); ++ return -ENOMEM; ++ } ++ ++ for (list = 0; list < partition; list++) { ++ /* ++ * [1] parsing ILM & DLM header info ++ * BIN_addr : SRAM_addr : size (12-bytes) ++ * crc located at 0x18 & 0x1C ++ */ ++ if (list < ilm_dlm_num) { ++ bin_map[list].BIN_addr = byte_to_word(&fwdata[0 + list*12]); ++ bin_map[list].SRAM_addr = byte_to_word(&fwdata[4 + list*12]); ++ bin_map[list].size = byte_to_word(&fwdata[8 + list*12]); ++ if (ts->hw_crc) ++ bin_map[list].crc = byte_to_word(&fwdata[0x18 + list*4]); ++ else { //ts->hw_crc ++ if ((bin_map[list].BIN_addr + bin_map[list].size) < fwsize) ++ bin_map[list].crc = CheckSum(&fwdata[bin_map[list].BIN_addr], bin_map[list].size); ++ else { ++ NVT_ERR("access range (0x%08X to 0x%08X) is larger than bin size!\n", ++ bin_map[list].BIN_addr, bin_map[list].BIN_addr + bin_map[list].size); ++ return -EINVAL; ++ } ++ } //ts->hw_crc ++ if (list == 0) ++ sprintf(bin_map[list].name, "ILM"); ++ else if (list == 1) ++ sprintf(bin_map[list].name, "DLM"); ++ } ++ ++ /* ++ * [2] parsing others header info ++ * SRAM_addr : size : BIN_addr : crc (16-bytes) ++ */ ++ if ((list >= ilm_dlm_num) && (list < (ilm_dlm_num + info_sec_num))) { ++ if (find_bin_header == 0) { ++ /* others partition located at 0x30 offset */ ++ pos = 0x30 + (0x10 * (list - ilm_dlm_num)); ++ } else if (find_bin_header && cascade_2nd_header_info) { ++ /* cascade 2nd header info */ ++ pos = end - 0x10; ++ } ++ ++ bin_map[list].SRAM_addr = byte_to_word(&fwdata[pos]); ++ bin_map[list].size = byte_to_word(&fwdata[pos+4]); ++ bin_map[list].BIN_addr = byte_to_word(&fwdata[pos+8]); ++ if (ts->hw_crc) ++ bin_map[list].crc = byte_to_word(&fwdata[pos+12]); ++ else { //ts->hw_crc ++ if ((bin_map[list].BIN_addr + bin_map[list].size) < fwsize) ++ bin_map[list].crc = CheckSum(&fwdata[bin_map[list].BIN_addr], bin_map[list].size); ++ else { ++ NVT_ERR("access range (0x%08X to 0x%08X) is larger than bin size!\n", ++ bin_map[list].BIN_addr, bin_map[list].BIN_addr + bin_map[list].size); ++ return -EINVAL; ++ } ++ } //ts->hw_crc ++ /* detect header end to protect parser function */ ++ if ((bin_map[list].BIN_addr < end) && (bin_map[list].size != 0)) { ++ sprintf(bin_map[list].name, "Header"); ++ find_bin_header = 1; ++ } else { ++ sprintf(bin_map[list].name, "Info-%d", (list - ilm_dlm_num)); ++ } ++ } ++ ++ /* ++ * [3] parsing overlay section header info ++ * SRAM_addr : size : BIN_addr : crc (16-bytes) ++ */ ++ if (list >= (ilm_dlm_num + info_sec_num)) { ++ /* overlay info located at DLM (list = 1) start addr */ ++ pos = bin_map[1].BIN_addr + (0x10 * (list- ilm_dlm_num - info_sec_num)); ++ ++ bin_map[list].SRAM_addr = byte_to_word(&fwdata[pos]); ++ bin_map[list].size = byte_to_word(&fwdata[pos+4]); ++ bin_map[list].BIN_addr = byte_to_word(&fwdata[pos+8]); ++ if (ts->hw_crc) ++ bin_map[list].crc = byte_to_word(&fwdata[pos+12]); ++ else { //ts->hw_crc ++ if ((bin_map[list].BIN_addr + bin_map[list].size) < fwsize) ++ bin_map[list].crc = CheckSum(&fwdata[bin_map[list].BIN_addr], bin_map[list].size); ++ else { ++ NVT_ERR("access range (0x%08X to 0x%08X) is larger than bin size!\n", ++ bin_map[list].BIN_addr, bin_map[list].BIN_addr + bin_map[list].size); ++ return -EINVAL; ++ } ++ } //ts->hw_crc ++ sprintf(bin_map[list].name, "Overlay-%d", (list- ilm_dlm_num - info_sec_num)); ++ } ++ ++ /* BIN size error detect */ ++ if ((bin_map[list].BIN_addr + bin_map[list].size) > fwsize) { ++ NVT_ERR("access range (0x%08X to 0x%08X) is larger than bin size!\n", ++ bin_map[list].BIN_addr, bin_map[list].BIN_addr + bin_map[list].size); ++ return -EINVAL; ++ } ++ ++// NVT_LOG("[%d][%s] SRAM (0x%08X), SIZE (0x%08X), BIN (0x%08X), CRC (0x%08X)\n", ++// list, bin_map[list].name, ++// bin_map[list].SRAM_addr, bin_map[list].size, bin_map[list].BIN_addr, bin_map[list].crc); ++ } ++ ++ return 0; ++} ++ ++/******************************************************* ++Description: ++ Novatek touchscreen release update firmware function. ++ ++return: ++ n.a. ++*******************************************************/ ++static void update_firmware_release(void) ++{ ++ if (fw_entry) { ++ release_firmware(fw_entry); ++ } ++ ++ fw_entry = NULL; ++} ++ ++/******************************************************* ++Description: ++ Novatek touchscreen request update firmware function. ++ ++return: ++ Executive outcomes. 0---succeed. -1,-22---failed. ++*******************************************************/ ++static int32_t update_firmware_request(const char *filename) ++{ ++ uint8_t retry = 0; ++ int32_t ret = 0; ++ ++ if (NULL == filename) { ++ return -ENOENT; ++ } ++ ++ while (1) { ++ NVT_LOG("filename is %s\n", filename); ++ ++ ret = request_firmware(&fw_entry, filename, &ts->client->dev); ++ if (ret) { ++ NVT_ERR("firmware load failed, ret=%d\n", ret); ++ goto request_fail; ++ } ++ ++ fw_need_write_size = fw_entry->size; ++ ++ // check if FW version add FW version bar equals 0xFF ++ if (*(fw_entry->data + FW_BIN_VER_OFFSET) + *(fw_entry->data + FW_BIN_VER_BAR_OFFSET) != 0xFF) { ++ NVT_ERR("bin file FW_VER + FW_VER_BAR should be 0xFF!\n"); ++ NVT_ERR("FW_VER=0x%02X, FW_VER_BAR=0x%02X\n", *(fw_entry->data+FW_BIN_VER_OFFSET), *(fw_entry->data+FW_BIN_VER_BAR_OFFSET)); ++ ret = -ENOEXEC; ++ goto invalid; ++ } ++ ++ /* BIN Header Parser */ ++ ret = nvt_bin_header_parser(fw_entry->data, fw_entry->size); ++ if (ret) { ++ NVT_ERR("bin header parser failed\n"); ++ goto invalid; ++ } else { ++ break; ++ } ++ ++invalid: ++ update_firmware_release(); ++ if (!IS_ERR_OR_NULL(bin_map)) { ++ kfree(bin_map); ++ bin_map = NULL; ++ } ++ ++request_fail: ++ retry++; ++ if(unlikely(retry > 2)) { ++ NVT_ERR("error, retry=%d\n", retry); ++ break; ++ } ++ } ++ ++ return ret; ++} ++ ++/******************************************************* ++Description: ++ Novatek touchscreen write data to sram function. ++ ++- fwdata : The buffer is written ++- SRAM_addr: The sram destination address ++- size : Number of data bytes in @fwdata being written ++- BIN_addr : The transferred data offset of @fwdata ++ ++return: ++ Executive outcomes. 0---succeed. else---fail. ++*******************************************************/ ++static int32_t nvt_write_sram(const u8 *fwdata, ++ uint32_t SRAM_addr, uint32_t size, uint32_t BIN_addr) ++{ ++ int32_t ret = 0; ++ uint32_t i = 0; ++ uint16_t len = 0; ++ int32_t count = 0; ++ ++ if (size % NVT_TRANSFER_LEN) ++ count = (size / NVT_TRANSFER_LEN) + 1; ++ else ++ count = (size / NVT_TRANSFER_LEN); ++ ++ for (i = 0 ; i < count ; i++) { ++ len = (size < NVT_TRANSFER_LEN) ? size : NVT_TRANSFER_LEN; ++ ++ //---set xdata index to start address of SRAM--- ++ ret = nvt_set_page(SRAM_addr); ++ if (ret) { ++ NVT_ERR("set page failed, ret = %d\n", ret); ++ return ret; ++ } ++ ++ //---write data into SRAM--- ++ fwbuf[0] = SRAM_addr & 0x7F; //offset ++ memcpy(fwbuf+1, &fwdata[BIN_addr], len); //payload ++ ret = CTP_SPI_WRITE(ts->client, fwbuf, len+1); ++ if (ret) { ++ NVT_ERR("write to sram failed, ret = %d\n", ret); ++ return ret; ++ } ++ ++ SRAM_addr += NVT_TRANSFER_LEN; ++ BIN_addr += NVT_TRANSFER_LEN; ++ size -= NVT_TRANSFER_LEN; ++ } ++ ++ return ret; ++} ++ ++/******************************************************* ++Description: ++ Novatek touchscreen nvt_write_firmware function to write ++firmware into each partition. ++ ++return: ++ n.a. ++*******************************************************/ ++static int32_t nvt_write_firmware(const u8 *fwdata, size_t fwsize) ++{ ++ uint32_t list = 0; ++ char *name; ++ uint32_t BIN_addr, SRAM_addr, size; ++ int32_t ret = 0; ++ ++ memset(fwbuf, 0, (NVT_TRANSFER_LEN+1)); ++ ++ for (list = 0; list < partition; list++) { ++ /* initialize variable */ ++ SRAM_addr = bin_map[list].SRAM_addr; ++ size = bin_map[list].size; ++ BIN_addr = bin_map[list].BIN_addr; ++ name = bin_map[list].name; ++ ++// NVT_LOG("[%d][%s] SRAM (0x%08X), SIZE (0x%08X), BIN (0x%08X)\n", ++// list, name, SRAM_addr, size, BIN_addr); ++ ++ /* Check data size */ ++ if ((BIN_addr + size) > fwsize) { ++ NVT_ERR("access range (0x%08X to 0x%08X) is larger than bin size!\n", ++ BIN_addr, BIN_addr + size); ++ ret = -EINVAL; ++ goto out; ++ } ++ ++ /* ignore reserved partition (Reserved Partition size is zero) */ ++ if (!size) ++ continue; ++ else ++ size = size +1; ++ ++ /* write data to SRAM */ ++ ret = nvt_write_sram(fwdata, SRAM_addr, size, BIN_addr); ++ if (ret) { ++ NVT_ERR("sram program failed, ret = %d\n", ret); ++ goto out; ++ } ++ } ++ ++out: ++ return ret; ++} ++ ++/******************************************************* ++Description: ++ Novatek touchscreen check checksum function. ++This function will compare file checksum and fw checksum. ++ ++return: ++ n.a. ++*******************************************************/ ++static int32_t nvt_check_fw_checksum(void) ++{ ++ uint32_t fw_checksum = 0; ++ uint32_t len = partition*4; ++ uint32_t list = 0; ++ int32_t ret = 0; ++ ++ memset(fwbuf, 0, (len+1)); ++ ++ //---set xdata index to checksum--- ++ nvt_set_page(ts->mmap->R_ILM_CHECKSUM_ADDR); ++ ++ /* read checksum */ ++ fwbuf[0] = (ts->mmap->R_ILM_CHECKSUM_ADDR) & 0x7F; ++ ret = CTP_SPI_READ(ts->client, fwbuf, len+1); ++ if (ret) { ++ NVT_ERR("Read fw checksum failed\n"); ++ return ret; ++ } ++ ++ /* ++ * Compare each checksum from fw ++ * ILM + DLM + Overlay + Info ++ * ilm_dlm_num (ILM & DLM) + ovly_sec_num + info_sec_num ++ */ ++ for (list = 0; list < partition; list++) { ++ fw_checksum = byte_to_word(&fwbuf[1+list*4]); ++ ++ /* ignore reserved partition (Reserved Partition size is zero) */ ++ if(!bin_map[list].size) ++ continue; ++ ++ if (bin_map[list].crc != fw_checksum) { ++ NVT_ERR("[%d] BIN_checksum=0x%08X, FW_checksum=0x%08X\n", ++ list, bin_map[list].crc, fw_checksum); ++ ret = -EIO; ++ } ++ } ++ ++ return ret; ++} ++ ++/******************************************************* ++Description: ++ Novatek touchscreen set bootload crc reg bank function. ++This function will set hw crc reg before enable crc function. ++ ++return: ++ n.a. ++*******************************************************/ ++static void nvt_set_bld_crc_bank(uint32_t DES_ADDR, uint32_t SRAM_ADDR, ++ uint32_t LENGTH_ADDR, uint32_t size, ++ uint32_t G_CHECKSUM_ADDR, uint32_t crc) ++{ ++ /* write destination address */ ++ nvt_set_page(DES_ADDR); ++ fwbuf[0] = DES_ADDR & 0x7F; ++ fwbuf[1] = (SRAM_ADDR) & 0xFF; ++ fwbuf[2] = (SRAM_ADDR >> 8) & 0xFF; ++ fwbuf[3] = (SRAM_ADDR >> 16) & 0xFF; ++ CTP_SPI_WRITE(ts->client, fwbuf, 4); ++ ++ /* write length */ ++ //nvt_set_page(LENGTH_ADDR); ++ fwbuf[0] = LENGTH_ADDR & 0x7F; ++ fwbuf[1] = (size) & 0xFF; ++ fwbuf[2] = (size >> 8) & 0xFF; ++ fwbuf[3] = (size >> 16) & 0x01; ++ if (ts->hw_crc == 1) { ++ CTP_SPI_WRITE(ts->client, fwbuf, 3); ++ } else if (ts->hw_crc > 1) { ++ CTP_SPI_WRITE(ts->client, fwbuf, 4); ++ } ++ ++ /* write golden dlm checksum */ ++ //nvt_set_page(G_CHECKSUM_ADDR); ++ fwbuf[0] = G_CHECKSUM_ADDR & 0x7F; ++ fwbuf[1] = (crc) & 0xFF; ++ fwbuf[2] = (crc >> 8) & 0xFF; ++ fwbuf[3] = (crc >> 16) & 0xFF; ++ fwbuf[4] = (crc >> 24) & 0xFF; ++ CTP_SPI_WRITE(ts->client, fwbuf, 5); ++ ++ return; ++} ++ ++/******************************************************* ++Description: ++ Novatek touchscreen set BLD hw crc function. ++This function will set ILM and DLM crc information to register. ++ ++return: ++ n.a. ++*******************************************************/ ++static void nvt_set_bld_hw_crc(void) ++{ ++ /* [0] ILM */ ++ /* write register bank */ ++ nvt_set_bld_crc_bank(ts->mmap->ILM_DES_ADDR, bin_map[0].SRAM_addr, ++ ts->mmap->ILM_LENGTH_ADDR, bin_map[0].size, ++ ts->mmap->G_ILM_CHECKSUM_ADDR, bin_map[0].crc); ++ ++ /* [1] DLM */ ++ /* write register bank */ ++ nvt_set_bld_crc_bank(ts->mmap->DLM_DES_ADDR, bin_map[1].SRAM_addr, ++ ts->mmap->DLM_LENGTH_ADDR, bin_map[1].size, ++ ts->mmap->G_DLM_CHECKSUM_ADDR, bin_map[1].crc); ++} ++ ++/******************************************************* ++Description: ++ Novatek touchscreen read BLD hw crc info function. ++This function will check crc results from register. ++ ++return: ++ n.a. ++*******************************************************/ ++static void nvt_read_bld_hw_crc(void) ++{ ++ uint8_t buf[8] = {0}; ++ uint32_t g_crc = 0, r_crc = 0; ++ ++ /* CRC Flag */ ++ nvt_set_page(ts->mmap->BLD_ILM_DLM_CRC_ADDR); ++ buf[0] = ts->mmap->BLD_ILM_DLM_CRC_ADDR & 0x7F; ++ buf[1] = 0x00; ++ CTP_SPI_READ(ts->client, buf, 2); ++ NVT_ERR("crc_done = %d, ilm_crc_flag = %d, dlm_crc_flag = %d\n", ++ (buf[1] >> 2) & 0x01, (buf[1] >> 0) & 0x01, (buf[1] >> 1) & 0x01); ++ ++ /* ILM CRC */ ++ nvt_set_page(ts->mmap->G_ILM_CHECKSUM_ADDR); ++ buf[0] = ts->mmap->G_ILM_CHECKSUM_ADDR & 0x7F; ++ buf[1] = 0x00; ++ buf[2] = 0x00; ++ buf[3] = 0x00; ++ buf[4] = 0x00; ++ CTP_SPI_READ(ts->client, buf, 5); ++ g_crc = buf[1] | (buf[2] << 8) | (buf[3] << 16) | (buf[4] << 24); ++ ++ nvt_set_page(ts->mmap->R_ILM_CHECKSUM_ADDR); ++ buf[0] = ts->mmap->R_ILM_CHECKSUM_ADDR & 0x7F; ++ buf[1] = 0x00; ++ buf[2] = 0x00; ++ buf[3] = 0x00; ++ buf[4] = 0x00; ++ CTP_SPI_READ(ts->client, buf, 5); ++ r_crc = buf[1] | (buf[2] << 8) | (buf[3] << 16) | (buf[4] << 24); ++ ++ NVT_ERR("ilm: bin crc = 0x%08X, golden = 0x%08X, result = 0x%08X\n", ++ bin_map[0].crc, g_crc, r_crc); ++ ++ /* DLM CRC */ ++ nvt_set_page(ts->mmap->G_DLM_CHECKSUM_ADDR); ++ buf[0] = ts->mmap->G_DLM_CHECKSUM_ADDR & 0x7F; ++ buf[1] = 0x00; ++ buf[2] = 0x00; ++ buf[3] = 0x00; ++ buf[4] = 0x00; ++ CTP_SPI_READ(ts->client, buf, 5); ++ g_crc = buf[1] | (buf[2] << 8) | (buf[3] << 16) | (buf[4] << 24); ++ ++ nvt_set_page(ts->mmap->R_DLM_CHECKSUM_ADDR); ++ buf[0] = ts->mmap->R_DLM_CHECKSUM_ADDR & 0x7F; ++ buf[1] = 0x00; ++ buf[2] = 0x00; ++ buf[3] = 0x00; ++ buf[4] = 0x00; ++ CTP_SPI_READ(ts->client, buf, 5); ++ r_crc = buf[1] | (buf[2] << 8) | (buf[3] << 16) | (buf[4] << 24); ++ ++ NVT_ERR("dlm: bin crc = 0x%08X, golden = 0x%08X, result = 0x%08X\n", ++ bin_map[1].crc, g_crc, r_crc); ++ ++ return; ++} ++ ++/******************************************************* ++Description: ++ Novatek touchscreen Download_Firmware with HW CRC ++function. It's complete download firmware flow. ++ ++return: ++ Executive outcomes. 0---succeed. else---fail. ++*******************************************************/ ++static int32_t nvt_download_firmware_hw_crc(void) ++{ ++ uint8_t retry = 0; ++ int32_t ret = 0; ++ ++ start = ktime_get(); ++ ++ while (1) { ++ /* bootloader reset to reset MCU */ ++ nvt_bootloader_reset(); ++ ++ /* set ilm & dlm reg bank */ ++ nvt_set_bld_hw_crc(); ++ ++ /* Start to write firmware process */ ++ if (cascade_2nd_header_info) { ++ /* for cascade */ ++ nvt_tx_auto_copy_mode(); ++ ++ ret = nvt_write_firmware(fw_entry->data, fw_entry->size); ++ if (ret) { ++ NVT_ERR("Write_Firmware failed. (%d)\n", ret); ++ goto fail; ++ } ++ ++ ret = nvt_check_spi_dma_tx_info(); ++ if (ret) { ++ NVT_ERR("spi dma tx info failed. (%d)\n", ret); ++ goto fail; ++ } ++ } else { ++ ret = nvt_write_firmware(fw_entry->data, fw_entry->size); ++ if (ret) { ++ NVT_ERR("Write_Firmware failed. (%d)\n", ret); ++ goto fail; ++ } ++ } ++ ++ /* enable hw bld crc function */ ++ nvt_bld_crc_enable(); ++ ++ /* clear fw reset status & enable fw crc check */ ++ nvt_fw_crc_enable(); ++ ++ /* Set Boot Ready Bit */ ++ nvt_boot_ready(); ++ ++ ret = nvt_check_fw_reset_state(RESET_STATE_INIT); ++ if (ret) { ++ NVT_ERR("nvt_check_fw_reset_state failed. (%d)\n", ret); ++ goto fail; ++ } else { ++ break; ++ } ++ ++fail: ++ retry++; ++ if(unlikely(retry > 2)) { ++ NVT_ERR("error, retry=%d\n", retry); ++ nvt_read_bld_hw_crc(); ++ break; ++ } ++ } ++ ++ end = ktime_get(); ++ ++ return ret; ++} ++ ++/******************************************************* ++Description: ++ Novatek touchscreen Download_Firmware function. It's ++complete download firmware flow. ++ ++return: ++ n.a. ++*******************************************************/ ++static int32_t nvt_download_firmware(void) ++{ ++ uint8_t retry = 0; ++ int32_t ret = 0; ++ ++ start = ktime_get(); ++ ++ while (1) { ++ /* ++ * Send eng reset cmd before download FW ++ * Keep TP_RESX low when send eng reset cmd ++ */ ++#if NVT_TOUCH_SUPPORT_HW_RST ++ gpio_set_value(ts->reset_gpio, 0); ++ mdelay(1); //wait 1ms ++#endif ++ nvt_eng_reset(); ++#if NVT_TOUCH_SUPPORT_HW_RST ++ gpio_set_value(ts->reset_gpio, 1); ++ mdelay(10); //wait tRT2BRST after TP_RST ++#endif ++ nvt_bootloader_reset(); ++ ++ /* clear fw reset status */ ++ nvt_write_addr(ts->mmap->EVENT_BUF_ADDR | EVENT_MAP_RESET_COMPLETE, 0x00); ++ ++ /* Start to write firmware process */ ++ ret = nvt_write_firmware(fw_entry->data, fw_entry->size); ++ if (ret) { ++ NVT_ERR("Write_Firmware failed. (%d)\n", ret); ++ goto fail; ++ } ++ ++ /* Set Boot Ready Bit */ ++ nvt_boot_ready(); ++ ++ ret = nvt_check_fw_reset_state(RESET_STATE_INIT); ++ if (ret) { ++ NVT_ERR("nvt_check_fw_reset_state failed. (%d)\n", ret); ++ goto fail; ++ } ++ ++ /* check fw checksum result */ ++ ret = nvt_check_fw_checksum(); ++ if (ret) { ++ NVT_ERR("firmware checksum not match, retry=%d\n", retry); ++ goto fail; ++ } else { ++ break; ++ } ++ ++fail: ++ retry++; ++ if(unlikely(retry > 2)) { ++ NVT_ERR("error, retry=%d\n", retry); ++ break; ++ } ++ } ++ ++ end = ktime_get(); ++ ++ return ret; ++} ++ ++/******************************************************* ++Description: ++ Novatek touchscreen update firmware main function. ++ ++return: ++ n.a. ++*******************************************************/ ++int32_t nvt_update_firmware(const char *firmware_name) ++{ ++ int32_t ret = 0; ++ ++ // request bin file in "/etc/firmware" ++ ret = update_firmware_request(firmware_name); ++ if (ret) { ++ NVT_ERR("update_firmware_request failed. (%d)\n", ret); ++ goto request_firmware_fail; ++ } ++ ++ /* initial buffer and variable */ ++ ret = nvt_download_init(); ++ if (ret) { ++ NVT_ERR("Download Init failed. (%d)\n", ret); ++ goto download_fail; ++ } ++ ++ /* download firmware process */ ++ if (ts->hw_crc) ++ ret = nvt_download_firmware_hw_crc(); ++ else ++ ret = nvt_download_firmware(); ++ if (ret) { ++ NVT_ERR("Download Firmware failed. (%d)\n", ret); ++ goto download_fail; ++ } ++ ++ NVT_LOG("Update firmware success! <%ld us>\n", ++ (long) ktime_us_delta(end, start)); ++ ++ /* Get FW Info */ ++ ret = nvt_get_fw_info(); ++ if (ret) { ++ NVT_ERR("nvt_get_fw_info failed. (%d)\n", ret); ++ } ++ ++download_fail: ++ if (!IS_ERR_OR_NULL(bin_map)) { ++ kfree(bin_map); ++ bin_map = NULL; ++ } ++ ++ update_firmware_release(); ++request_firmware_fail: ++ ++ return ret; ++} ++ ++/******************************************************* ++Description: ++ Novatek touchscreen update firmware when booting ++ function. ++ ++return: ++ n.a. ++*******************************************************/ ++void Boot_Update_Firmware(struct work_struct *work) ++{ ++ mutex_lock(&ts->lock); ++ nvt_update_firmware(ts->fw_name); ++ nvt_get_fw_info(); ++ mutex_unlock(&ts->lock); ++} ++#endif /* BOOT_UPDATE_FIRMWARE */ +diff --git a/drivers/input/touchscreen/nt36523/nt36xxx_mem_map.h b/drivers/input/touchscreen/nt36523/nt36xxx_mem_map.h +new file mode 100644 +index 000000000..3f4195d63 +--- /dev/null ++++ b/drivers/input/touchscreen/nt36523/nt36xxx_mem_map.h +@@ -0,0 +1,390 @@ ++/* ++ * Copyright (C) 2010 - 2018 Novatek, Inc. ++ * Copyright (C) 2021 XiaoMi, Inc. ++ * ++ * $Revision: 57674 $ ++ * $Date: 2020-03-02 11:16:20 +0800 (週一, 02 三月 2020) $ ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation; either version 2 of the License, or ++ * (at your option) any later version. ++ * ++ * This program is distributed in the hope that it will be useful, but WITHOUT ++ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or ++ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for ++ * more details. ++ * ++ */ ++ ++#define CHIP_VER_TRIM_ADDR 0x3F004 ++#define CHIP_VER_TRIM_OLD_ADDR 0x1F64E ++ ++struct nvt_ts_mem_map { ++ uint32_t EVENT_BUF_ADDR; ++ uint32_t RAW_PIPE0_ADDR; ++ uint32_t RAW_PIPE1_ADDR; ++ uint32_t BASELINE_ADDR; ++ uint32_t BASELINE_BTN_ADDR; ++ uint32_t DIFF_PIPE0_ADDR; ++ uint32_t DIFF_PIPE1_ADDR; ++ uint32_t RAW_BTN_PIPE0_ADDR; ++ uint32_t RAW_BTN_PIPE1_ADDR; ++ uint32_t DIFF_BTN_PIPE0_ADDR; ++ uint32_t DIFF_BTN_PIPE1_ADDR; ++ uint32_t PEN_2D_BL_TIP_X_ADDR; ++ uint32_t PEN_2D_BL_TIP_Y_ADDR; ++ uint32_t PEN_2D_BL_RING_X_ADDR; ++ uint32_t PEN_2D_BL_RING_Y_ADDR; ++ uint32_t PEN_2D_DIFF_TIP_X_ADDR; ++ uint32_t PEN_2D_DIFF_TIP_Y_ADDR; ++ uint32_t PEN_2D_DIFF_RING_X_ADDR; ++ uint32_t PEN_2D_DIFF_RING_Y_ADDR; ++ uint32_t PEN_2D_RAW_TIP_X_ADDR; ++ uint32_t PEN_2D_RAW_TIP_Y_ADDR; ++ uint32_t PEN_2D_RAW_RING_X_ADDR; ++ uint32_t PEN_2D_RAW_RING_Y_ADDR; ++ uint32_t PEN_1D_DIFF_TIP_X_ADDR; ++ uint32_t PEN_1D_DIFF_TIP_Y_ADDR; ++ uint32_t PEN_1D_DIFF_RING_X_ADDR; ++ uint32_t PEN_1D_DIFF_RING_Y_ADDR; ++ uint32_t READ_FLASH_CHECKSUM_ADDR; ++ uint32_t RW_FLASH_DATA_ADDR; ++ /* Phase 2 Host Download */ ++ uint32_t BOOT_RDY_ADDR; ++ uint32_t POR_CD_ADDR; ++ uint32_t TX_AUTO_COPY_EN; ++ uint32_t SPI_DMA_TX_INFO; ++ /* BLD CRC */ ++ uint32_t BLD_LENGTH_ADDR; ++ uint32_t ILM_LENGTH_ADDR; ++ uint32_t DLM_LENGTH_ADDR; ++ uint32_t BLD_DES_ADDR; ++ uint32_t ILM_DES_ADDR; ++ uint32_t DLM_DES_ADDR; ++ uint32_t G_ILM_CHECKSUM_ADDR; ++ uint32_t G_DLM_CHECKSUM_ADDR; ++ uint32_t R_ILM_CHECKSUM_ADDR; ++ uint32_t R_DLM_CHECKSUM_ADDR; ++ uint32_t BLD_CRC_EN_ADDR; ++ uint32_t DMA_CRC_EN_ADDR; ++ uint32_t BLD_ILM_DLM_CRC_ADDR; ++ uint32_t DMA_CRC_FLAG_ADDR; ++ uint32_t FW_HISTORY_ADDR; ++}; ++ ++struct nvt_ts_hw_info { ++ uint8_t carrier_system; ++ uint8_t hw_crc; ++}; ++ ++static const struct nvt_ts_mem_map NT36523_memory_map = { ++ .EVENT_BUF_ADDR = 0x2FE00, ++ .RAW_PIPE0_ADDR = 0x30FA0, ++ .RAW_PIPE1_ADDR = 0x30FA0, ++ .BASELINE_ADDR = 0x36510, ++ .BASELINE_BTN_ADDR = 0, ++ .DIFF_PIPE0_ADDR = 0x373E8, ++ .DIFF_PIPE1_ADDR = 0x38068, ++ .RAW_BTN_PIPE0_ADDR = 0, ++ .RAW_BTN_PIPE1_ADDR = 0, ++ .DIFF_BTN_PIPE0_ADDR = 0, ++ .DIFF_BTN_PIPE1_ADDR = 0, ++ .PEN_2D_BL_TIP_X_ADDR = 0x2988A, ++ .PEN_2D_BL_TIP_Y_ADDR = 0x29A1A, ++ .PEN_2D_BL_RING_X_ADDR = 0x29BAA, ++ .PEN_2D_BL_RING_Y_ADDR = 0x29D3A, ++ .PEN_2D_DIFF_TIP_X_ADDR = 0x29ECA, ++ .PEN_2D_DIFF_TIP_Y_ADDR = 0x2A05A, ++ .PEN_2D_DIFF_RING_X_ADDR = 0x2A1EA, ++ .PEN_2D_DIFF_RING_Y_ADDR = 0x2A37A, ++ .PEN_2D_RAW_TIP_X_ADDR = 0x2A50A, ++ .PEN_2D_RAW_TIP_Y_ADDR = 0x2A69A, ++ .PEN_2D_RAW_RING_X_ADDR = 0x2A82A, ++ .PEN_2D_RAW_RING_Y_ADDR = 0x2A9BA, ++ .PEN_1D_DIFF_TIP_X_ADDR = 0x2AB4A, ++ .PEN_1D_DIFF_TIP_Y_ADDR = 0x2ABAE, ++ .PEN_1D_DIFF_RING_X_ADDR = 0x2AC12, ++ .PEN_1D_DIFF_RING_Y_ADDR = 0x2AC76, ++ .READ_FLASH_CHECKSUM_ADDR = 0x24000, ++ .RW_FLASH_DATA_ADDR = 0x24002, ++ /* Phase 2 Host Download */ ++ .BOOT_RDY_ADDR = 0x3F10D, ++ .TX_AUTO_COPY_EN = 0x3F7E8, ++ .SPI_DMA_TX_INFO = 0x3F7F1, ++ /* BLD CRC */ ++ .BLD_LENGTH_ADDR = 0x3F138, //0x3F138 ~ 0x3F13A (3 bytes) ++ .ILM_LENGTH_ADDR = 0x3F118, //0x3F118 ~ 0x3F11A (3 bytes) ++ .DLM_LENGTH_ADDR = 0x3F130, //0x3F130 ~ 0x3F132 (3 bytes) ++ .BLD_DES_ADDR = 0x3F114, //0x3F114 ~ 0x3F116 (3 bytes) ++ .ILM_DES_ADDR = 0x3F128, //0x3F128 ~ 0x3F12A (3 bytes) ++ .DLM_DES_ADDR = 0x3F12C, //0x3F12C ~ 0x3F12E (3 bytes) ++ .G_ILM_CHECKSUM_ADDR = 0x3F100, //0x3F100 ~ 0x3F103 (4 bytes) ++ .G_DLM_CHECKSUM_ADDR = 0x3F104, //0x3F104 ~ 0x3F107 (4 bytes) ++ .R_ILM_CHECKSUM_ADDR = 0x3F120, //0x3F120 ~ 0x3F123 (4 bytes) ++ .R_DLM_CHECKSUM_ADDR = 0x3F124, //0x3F124 ~ 0x3F127 (4 bytes) ++ .BLD_CRC_EN_ADDR = 0x3F30E, ++ .DMA_CRC_EN_ADDR = 0x3F136, ++ .BLD_ILM_DLM_CRC_ADDR = 0x3F133, ++ .DMA_CRC_FLAG_ADDR = 0x3F134, ++ .FW_HISTORY_ADDR = 0x38D54, ++}; ++ ++static const struct nvt_ts_mem_map NT36526_memory_map = { ++ .EVENT_BUF_ADDR = 0x22D00, ++ .RAW_PIPE0_ADDR = 0x24000, ++ .RAW_PIPE1_ADDR = 0x24000, ++ .BASELINE_ADDR = 0x21758, ++ .BASELINE_BTN_ADDR = 0, ++ .DIFF_PIPE0_ADDR = 0x20AB0, ++ .DIFF_PIPE1_ADDR = 0x24AB0, ++ .RAW_BTN_PIPE0_ADDR = 0, ++ .RAW_BTN_PIPE1_ADDR = 0, ++ .DIFF_BTN_PIPE0_ADDR = 0, ++ .DIFF_BTN_PIPE1_ADDR = 0, ++ .READ_FLASH_CHECKSUM_ADDR = 0x24000, ++ .RW_FLASH_DATA_ADDR = 0x24002, ++ /* Phase 2 Host Download */ ++ .BOOT_RDY_ADDR = 0x3F10D, ++ /* BLD CRC */ ++ .BLD_LENGTH_ADDR = 0x3F138, //0x3F138 ~ 0x3F13A (3 bytes) ++ .ILM_LENGTH_ADDR = 0x3F118, //0x3F118 ~ 0x3F11A (3 bytes) ++ .DLM_LENGTH_ADDR = 0x3F130, //0x3F130 ~ 0x3F132 (3 bytes) ++ .BLD_DES_ADDR = 0x3F114, //0x3F114 ~ 0x3F116 (3 bytes) ++ .ILM_DES_ADDR = 0x3F128, //0x3F128 ~ 0x3F12A (3 bytes) ++ .DLM_DES_ADDR = 0x3F12C, //0x3F12C ~ 0x3F12E (3 bytes) ++ .G_ILM_CHECKSUM_ADDR = 0x3F100, //0x3F100 ~ 0x3F103 (4 bytes) ++ .G_DLM_CHECKSUM_ADDR = 0x3F104, //0x3F104 ~ 0x3F107 (4 bytes) ++ .R_ILM_CHECKSUM_ADDR = 0x3F120, //0x3F120 ~ 0x3F123 (4 bytes) ++ .R_DLM_CHECKSUM_ADDR = 0x3F124, //0x3F124 ~ 0x3F127 (4 bytes) ++ .BLD_CRC_EN_ADDR = 0x3F30E, ++ .DMA_CRC_EN_ADDR = 0x3F136, ++ .BLD_ILM_DLM_CRC_ADDR = 0x3F133, ++ .DMA_CRC_FLAG_ADDR = 0x3F134, ++}; ++ ++ ++static const struct nvt_ts_mem_map NT36675_memory_map = { ++ .EVENT_BUF_ADDR = 0x22D00, ++ .RAW_PIPE0_ADDR = 0x24000, ++ .RAW_PIPE1_ADDR = 0x24000, ++ .BASELINE_ADDR = 0x21B90, ++ .BASELINE_BTN_ADDR = 0, ++ .DIFF_PIPE0_ADDR = 0x20C60, ++ .DIFF_PIPE1_ADDR = 0x24C60, ++ .RAW_BTN_PIPE0_ADDR = 0, ++ .RAW_BTN_PIPE1_ADDR = 0, ++ .DIFF_BTN_PIPE0_ADDR = 0, ++ .DIFF_BTN_PIPE1_ADDR = 0, ++ .READ_FLASH_CHECKSUM_ADDR = 0x24000, ++ .RW_FLASH_DATA_ADDR = 0x24002, ++ /* Phase 2 Host Download */ ++ .BOOT_RDY_ADDR = 0x3F10D, ++ /* BLD CRC */ ++ .BLD_LENGTH_ADDR = 0x3F138, //0x3F138 ~ 0x3F13A (3 bytes) ++ .ILM_LENGTH_ADDR = 0x3F118, //0x3F118 ~ 0x3F11A (3 bytes) ++ .DLM_LENGTH_ADDR = 0x3F130, //0x3F130 ~ 0x3F132 (3 bytes) ++ .BLD_DES_ADDR = 0x3F114, //0x3F114 ~ 0x3F116 (3 bytes) ++ .ILM_DES_ADDR = 0x3F128, //0x3F128 ~ 0x3F12A (3 bytes) ++ .DLM_DES_ADDR = 0x3F12C, //0x3F12C ~ 0x3F12E (3 bytes) ++ .G_ILM_CHECKSUM_ADDR = 0x3F100, //0x3F100 ~ 0x3F103 (4 bytes) ++ .G_DLM_CHECKSUM_ADDR = 0x3F104, //0x3F104 ~ 0x3F107 (4 bytes) ++ .R_ILM_CHECKSUM_ADDR = 0x3F120, //0x3F120 ~ 0x3F123 (4 bytes) ++ .R_DLM_CHECKSUM_ADDR = 0x3F124, //0x3F124 ~ 0x3F127 (4 bytes) ++ .BLD_CRC_EN_ADDR = 0x3F30E, ++ .DMA_CRC_EN_ADDR = 0x3F136, ++ .BLD_ILM_DLM_CRC_ADDR = 0x3F133, ++ .DMA_CRC_FLAG_ADDR = 0x3F134, ++}; ++ ++ ++static const struct nvt_ts_mem_map NT36672A_memory_map = { ++ .EVENT_BUF_ADDR = 0x21C00, ++ .RAW_PIPE0_ADDR = 0x20000, ++ .RAW_PIPE1_ADDR = 0x23000, ++ .BASELINE_ADDR = 0x20BFC, ++ .BASELINE_BTN_ADDR = 0x23BFC, ++ .DIFF_PIPE0_ADDR = 0x206DC, ++ .DIFF_PIPE1_ADDR = 0x236DC, ++ .RAW_BTN_PIPE0_ADDR = 0x20510, ++ .RAW_BTN_PIPE1_ADDR = 0x23510, ++ .DIFF_BTN_PIPE0_ADDR = 0x20BF0, ++ .DIFF_BTN_PIPE1_ADDR = 0x23BF0, ++ .READ_FLASH_CHECKSUM_ADDR = 0x24000, ++ .RW_FLASH_DATA_ADDR = 0x24002, ++ /* Phase 2 Host Download */ ++ .BOOT_RDY_ADDR = 0x3F10D, ++ /* BLD CRC */ ++ .BLD_LENGTH_ADDR = 0x3F10E, //0x3F10E ~ 0x3F10F (2 bytes) ++ .ILM_LENGTH_ADDR = 0x3F118, //0x3F118 ~ 0x3F119 (2 bytes) ++ .DLM_LENGTH_ADDR = 0x3F130, //0x3F130 ~ 0x3F131 (2 bytes) ++ .BLD_DES_ADDR = 0x3F114, //0x3F114 ~ 0x3F116 (3 bytes) ++ .ILM_DES_ADDR = 0x3F128, //0x3F128 ~ 0x3F12A (3 bytes) ++ .DLM_DES_ADDR = 0x3F12C, //0x3F12C ~ 0x3F12E (3 bytes) ++ .G_ILM_CHECKSUM_ADDR = 0x3F100, //0x3F100 ~ 0x3F103 (4 bytes) ++ .G_DLM_CHECKSUM_ADDR = 0x3F104, //0x3F104 ~ 0x3F107 (4 bytes) ++ .R_ILM_CHECKSUM_ADDR = 0x3F120, //0x3F120 ~ 0x3F123 (4 bytes) ++ .R_DLM_CHECKSUM_ADDR = 0x3F124, //0x3F124 ~ 0x3F127 (4 bytes) ++ .BLD_CRC_EN_ADDR = 0x3F30E, ++ .DMA_CRC_EN_ADDR = 0x3F132, ++ .BLD_ILM_DLM_CRC_ADDR = 0x3F133, ++ .DMA_CRC_FLAG_ADDR = 0x3F134, ++}; ++ ++static const struct nvt_ts_mem_map NT36772_memory_map = { ++ .EVENT_BUF_ADDR = 0x11E00, ++ .RAW_PIPE0_ADDR = 0x10000, ++ .RAW_PIPE1_ADDR = 0x12000, ++ .BASELINE_ADDR = 0x10E70, ++ .BASELINE_BTN_ADDR = 0x12E70, ++ .DIFF_PIPE0_ADDR = 0x10830, ++ .DIFF_PIPE1_ADDR = 0x12830, ++ .RAW_BTN_PIPE0_ADDR = 0x10E60, ++ .RAW_BTN_PIPE1_ADDR = 0x12E60, ++ .DIFF_BTN_PIPE0_ADDR = 0x10E68, ++ .DIFF_BTN_PIPE1_ADDR = 0x12E68, ++ .READ_FLASH_CHECKSUM_ADDR = 0x14000, ++ .RW_FLASH_DATA_ADDR = 0x14002, ++ /* Phase 2 Host Download */ ++ .BOOT_RDY_ADDR = 0x1F141, ++ .POR_CD_ADDR = 0x1F61C, ++ /* BLD CRC */ ++ .R_ILM_CHECKSUM_ADDR = 0x1BF00, ++}; ++ ++static const struct nvt_ts_mem_map NT36525_memory_map = { ++ .EVENT_BUF_ADDR = 0x11A00, ++ .RAW_PIPE0_ADDR = 0x10000, ++ .RAW_PIPE1_ADDR = 0x12000, ++ .BASELINE_ADDR = 0x10B08, ++ .BASELINE_BTN_ADDR = 0x12B08, ++ .DIFF_PIPE0_ADDR = 0x1064C, ++ .DIFF_PIPE1_ADDR = 0x1264C, ++ .RAW_BTN_PIPE0_ADDR = 0x10634, ++ .RAW_BTN_PIPE1_ADDR = 0x12634, ++ .DIFF_BTN_PIPE0_ADDR = 0x10AFC, ++ .DIFF_BTN_PIPE1_ADDR = 0x12AFC, ++ .READ_FLASH_CHECKSUM_ADDR = 0x14000, ++ .RW_FLASH_DATA_ADDR = 0x14002, ++ /* Phase 2 Host Download */ ++ .BOOT_RDY_ADDR = 0x1F141, ++ .POR_CD_ADDR = 0x1F61C, ++ /* BLD CRC */ ++ .R_ILM_CHECKSUM_ADDR = 0x1BF00, ++}; ++ ++static const struct nvt_ts_mem_map NT36676F_memory_map = { ++ .EVENT_BUF_ADDR = 0x11A00, ++ .RAW_PIPE0_ADDR = 0x10000, ++ .RAW_PIPE1_ADDR = 0x12000, ++ .BASELINE_ADDR = 0x10B08, ++ .BASELINE_BTN_ADDR = 0x12B08, ++ .DIFF_PIPE0_ADDR = 0x1064C, ++ .DIFF_PIPE1_ADDR = 0x1264C, ++ .RAW_BTN_PIPE0_ADDR = 0x10634, ++ .RAW_BTN_PIPE1_ADDR = 0x12634, ++ .DIFF_BTN_PIPE0_ADDR = 0x10AFC, ++ .DIFF_BTN_PIPE1_ADDR = 0x12AFC, ++ .READ_FLASH_CHECKSUM_ADDR = 0x14000, ++ .RW_FLASH_DATA_ADDR = 0x14002, ++}; ++ ++static struct nvt_ts_hw_info NT36523_hw_info = { ++ .carrier_system = 2, ++ .hw_crc = 2, ++}; ++ ++static struct nvt_ts_hw_info NT36526_hw_info = { ++ .carrier_system = 2, ++ .hw_crc = 2, ++}; ++ ++static struct nvt_ts_hw_info NT36675_hw_info = { ++ .carrier_system = 2, ++ .hw_crc = 2, ++}; ++ ++static struct nvt_ts_hw_info NT36672A_hw_info = { ++ .carrier_system = 0, ++ .hw_crc = 1, ++}; ++ ++static struct nvt_ts_hw_info NT36772_hw_info = { ++ .carrier_system = 0, ++ .hw_crc = 0, ++}; ++ ++static struct nvt_ts_hw_info NT36525_hw_info = { ++ .carrier_system = 0, ++ .hw_crc = 0, ++}; ++ ++static struct nvt_ts_hw_info NT36676F_hw_info = { ++ .carrier_system = 0, ++ .hw_crc = 0, ++}; ++ ++#define NVT_ID_BYTE_MAX 6 ++struct nvt_ts_trim_id_table { ++ uint8_t id[NVT_ID_BYTE_MAX]; ++ uint8_t mask[NVT_ID_BYTE_MAX]; ++ const struct nvt_ts_mem_map *mmap; ++ const struct nvt_ts_hw_info *hwinfo; ++}; ++ ++static const struct nvt_ts_trim_id_table trim_id_table[] = { ++ {.id = {0x20, 0xFF, 0xFF, 0x23, 0x65, 0x03}, .mask = {1, 0, 0, 1, 1, 1}, ++ .mmap = &NT36523_memory_map, .hwinfo = &NT36523_hw_info}, ++ {.id = {0x0C, 0xFF, 0xFF, 0x23, 0x65, 0x03}, .mask = {1, 0, 0, 1, 1, 1}, ++ .mmap = &NT36523_memory_map, .hwinfo = &NT36523_hw_info}, ++ {.id = {0x0B, 0xFF, 0xFF, 0x23, 0x65, 0x03}, .mask = {1, 0, 0, 1, 1, 1}, ++ .mmap = &NT36523_memory_map, .hwinfo = &NT36523_hw_info}, ++ {.id = {0x0A, 0xFF, 0xFF, 0x23, 0x65, 0x03}, .mask = {1, 0, 0, 1, 1, 1}, ++ .mmap = &NT36523_memory_map, .hwinfo = &NT36523_hw_info}, ++ {.id = {0xFF, 0xFF, 0xFF, 0x23, 0x65, 0x03}, .mask = {0, 0, 0, 1, 1, 1}, ++ .mmap = &NT36523_memory_map, .hwinfo = &NT36523_hw_info}, ++ {.id = {0x0C, 0xFF, 0xFF, 0x72, 0x66, 0x03}, .mask = {1, 0, 0, 1, 1, 1}, ++ .mmap = &NT36675_memory_map, .hwinfo = &NT36675_hw_info}, ++ {.id = {0xFF, 0xFF, 0xFF, 0x26, 0x65, 0x03}, .mask = {0, 0, 0, 1, 1, 1}, ++ .mmap = &NT36526_memory_map, .hwinfo = &NT36526_hw_info}, ++ {.id = {0xFF, 0xFF, 0xFF, 0x75, 0x66, 0x03}, .mask = {0, 0, 0, 1, 1, 1}, ++ .mmap = &NT36675_memory_map, .hwinfo = &NT36675_hw_info}, ++ {.id = {0x0B, 0xFF, 0xFF, 0x72, 0x66, 0x03}, .mask = {1, 0, 0, 1, 1, 1}, ++ .mmap = &NT36672A_memory_map, .hwinfo = &NT36672A_hw_info}, ++ {.id = {0x0B, 0xFF, 0xFF, 0x82, 0x66, 0x03}, .mask = {1, 0, 0, 1, 1, 1}, ++ .mmap = &NT36672A_memory_map, .hwinfo = &NT36672A_hw_info}, ++ {.id = {0x0B, 0xFF, 0xFF, 0x25, 0x65, 0x03}, .mask = {1, 0, 0, 1, 1, 1}, ++ .mmap = &NT36672A_memory_map, .hwinfo = &NT36672A_hw_info}, ++ {.id = {0x0A, 0xFF, 0xFF, 0x72, 0x65, 0x03}, .mask = {1, 0, 0, 1, 1, 1}, ++ .mmap = &NT36672A_memory_map, .hwinfo = &NT36672A_hw_info}, ++ {.id = {0x0A, 0xFF, 0xFF, 0x72, 0x66, 0x03}, .mask = {1, 0, 0, 1, 1, 1}, ++ .mmap = &NT36672A_memory_map, .hwinfo = &NT36672A_hw_info}, ++ {.id = {0x0A, 0xFF, 0xFF, 0x82, 0x66, 0x03}, .mask = {1, 0, 0, 1, 1, 1}, ++ .mmap = &NT36672A_memory_map, .hwinfo = &NT36672A_hw_info}, ++ {.id = {0x0A, 0xFF, 0xFF, 0x70, 0x66, 0x03}, .mask = {1, 0, 0, 1, 1, 1}, ++ .mmap = &NT36672A_memory_map, .hwinfo = &NT36672A_hw_info}, ++ {.id = {0x0B, 0xFF, 0xFF, 0x70, 0x66, 0x03}, .mask = {1, 0, 0, 1, 1, 1}, ++ .mmap = &NT36672A_memory_map, .hwinfo = &NT36672A_hw_info}, ++ {.id = {0x0A, 0xFF, 0xFF, 0x72, 0x67, 0x03}, .mask = {1, 0, 0, 1, 1, 1}, ++ .mmap = &NT36672A_memory_map, .hwinfo = &NT36672A_hw_info}, ++ {.id = {0x55, 0x00, 0xFF, 0x00, 0x00, 0x00}, .mask = {1, 1, 0, 1, 1, 1}, ++ .mmap = &NT36772_memory_map, .hwinfo = &NT36772_hw_info}, ++ {.id = {0x55, 0x72, 0xFF, 0x00, 0x00, 0x00}, .mask = {1, 1, 0, 1, 1, 1}, ++ .mmap = &NT36772_memory_map, .hwinfo = &NT36772_hw_info}, ++ {.id = {0xAA, 0x00, 0xFF, 0x00, 0x00, 0x00}, .mask = {1, 1, 0, 1, 1, 1}, ++ .mmap = &NT36772_memory_map, .hwinfo = &NT36772_hw_info}, ++ {.id = {0xAA, 0x72, 0xFF, 0x00, 0x00, 0x00}, .mask = {1, 1, 0, 1, 1, 1}, ++ .mmap = &NT36772_memory_map, .hwinfo = &NT36772_hw_info}, ++ {.id = {0xFF, 0xFF, 0xFF, 0x72, 0x67, 0x03}, .mask = {0, 0, 0, 1, 1, 1}, ++ .mmap = &NT36772_memory_map, .hwinfo = &NT36772_hw_info}, ++ {.id = {0xFF, 0xFF, 0xFF, 0x70, 0x66, 0x03}, .mask = {0, 0, 0, 1, 1, 1}, ++ .mmap = &NT36772_memory_map, .hwinfo = &NT36772_hw_info}, ++ {.id = {0xFF, 0xFF, 0xFF, 0x70, 0x67, 0x03}, .mask = {0, 0, 0, 1, 1, 1}, ++ .mmap = &NT36772_memory_map, .hwinfo = &NT36772_hw_info}, ++ {.id = {0xFF, 0xFF, 0xFF, 0x72, 0x66, 0x03}, .mask = {0, 0, 0, 1, 1, 1}, ++ .mmap = &NT36772_memory_map, .hwinfo = &NT36772_hw_info}, ++ {.id = {0xFF, 0xFF, 0xFF, 0x25, 0x65, 0x03}, .mask = {0, 0, 0, 1, 1, 1}, ++ .mmap = &NT36525_memory_map, .hwinfo = &NT36525_hw_info}, ++ {.id = {0xFF, 0xFF, 0xFF, 0x76, 0x66, 0x03}, .mask = {0, 0, 0, 1, 1, 1}, ++ .mmap = &NT36676F_memory_map, .hwinfo = &NT36676F_hw_info} ++}; +-- +Armbian + diff --git a/patch/kernel/archive/sm8250-6.7/0012-arm64-dts-qcom-sm8250-xiaomi-elish-enable-wifi-and-b.patch b/patch/kernel/archive/sm8250-6.7/0012-arm64-dts-qcom-sm8250-xiaomi-elish-enable-wifi-and-b.patch new file mode 100644 index 000000000..410052ca7 --- /dev/null +++ b/patch/kernel/archive/sm8250-6.7/0012-arm64-dts-qcom-sm8250-xiaomi-elish-enable-wifi-and-b.patch @@ -0,0 +1,106 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Jianhua Lu +Date: Mon, 6 Mar 2023 23:13:06 +0800 +Subject: arm64: dts: qcom: sm8250-xiaomi-elish: enable wifi and bluetooth + +Signed-off-by: Jianhua Lu +--- + arch/arm64/boot/dts/qcom/sm8250-xiaomi-elish-common.dtsi | 61 ++++++++++ + 1 file changed, 61 insertions(+) + +diff --git a/arch/arm64/boot/dts/qcom/sm8250-xiaomi-elish-common.dtsi b/arch/arm64/boot/dts/qcom/sm8250-xiaomi-elish-common.dtsi +index 85e5cf3dc..d7ec6bdd1 100644 +--- a/arch/arm64/boot/dts/qcom/sm8250-xiaomi-elish-common.dtsi ++++ b/arch/arm64/boot/dts/qcom/sm8250-xiaomi-elish-common.dtsi +@@ -29,6 +29,10 @@ / { + qcom,msm-id = ; /* SM8250 v2.1 */ + qcom,board-id = <0x10008 0>; + ++ aliases { ++ hsuart0 = &uart6; ++ }; ++ + chosen { + #address-cells = <2>; + #size-cells = <2>; +@@ -113,6 +117,25 @@ vreg_s6c_0p88: smpc6-regulator { + vin-supply = <&vph_pwr>; + }; + ++ qca639x: qca639x { ++ compatible = "qcom,qca6390"; ++ #power-domain-cells = <0>; ++ ++ vddaon-supply = <&vreg_s6a_0p95>; ++ vddpmu-supply = <&vreg_s6a_0p95>; ++ vddrfa1-supply = <&vreg_s6a_0p95>; ++ vddrfa2-supply = <&vreg_s8c_1p35>; ++ vddrfa3-supply = <&vreg_s5a_1p9>; ++ vddpcie1-supply = <&vreg_s8c_1p35>; ++ vddpcie2-supply = <&vreg_s5a_1p9>; ++ vddio-supply = <&vreg_s4a_1p8>; ++ ++ pinctrl-names = "default"; ++ pinctrl-0 = <&wlan_en_state>; ++ ++ wlan-en-gpios = <&tlmm 20 GPIO_ACTIVE_HIGH>; ++ }; ++ + reserved-memory { + xbl_aop_mem: xbl-aop@80700000 { + reg = <0x0 0x80600000 0x0 0x260000>; +@@ -615,6 +638,9 @@ &pcie0_phy { + vdda-phy-supply = <&vreg_l5a_0p88>; + vdda-pll-supply = <&vreg_l9a_1p2>; + status = "okay"; ++ ++ /* Power on QCA639x chip, otherwise PCIe bus timeouts */ ++ power-domains = <&qca639x>; + }; + + &pm8150_gpios { +@@ -655,6 +681,41 @@ &slpi { + + &tlmm { + gpio-reserved-ranges = <40 4>; ++ ++ bt_en_state: bt-default-state { ++ bt-en-pins { ++ pins = "gpio21"; ++ function = "gpio"; ++ ++ drive-strength = <16>; ++ output-low; ++ bias-pull-up; ++ }; ++ }; ++ ++ wlan_en_state: wlan-default-state { ++ wlan-en-pins { ++ pins = "gpio20"; ++ function = "gpio"; ++ ++ drive-strength = <16>; ++ output-low; ++ bias-pull-up; ++ }; ++ }; ++}; ++ ++&uart6 { ++ status = "okay"; ++ ++ bluetooth { ++ compatible = "qcom,qca6390-bt"; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&bt_en_state>; ++ ++ power-domains = <&qca639x>; ++ enable-gpios = <&tlmm 21 GPIO_ACTIVE_HIGH>; ++ }; + }; + + &usb_1 { +-- +Armbian + diff --git a/patch/kernel/archive/sm8250-6.7/0013-arm64-dts-qcom-sm8250-xiaomi-elish-enable-touchscree.patch b/patch/kernel/archive/sm8250-6.7/0013-arm64-dts-qcom-sm8250-xiaomi-elish-enable-touchscree.patch new file mode 100644 index 000000000..115a1055b --- /dev/null +++ b/patch/kernel/archive/sm8250-6.7/0013-arm64-dts-qcom-sm8250-xiaomi-elish-enable-touchscree.patch @@ -0,0 +1,91 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Jianhua Lu +Date: Mon, 6 Mar 2023 23:23:13 +0800 +Subject: arm64: dts: qcom: sm8250-xiaomi-elish: enable touchscreen + +Signed-off-by: Jianhua Lu +--- + arch/arm64/boot/dts/qcom/sm8250-xiaomi-elish-boe.dts | 5 ++ + arch/arm64/boot/dts/qcom/sm8250-xiaomi-elish-common.dtsi | 32 ++++++++++ + arch/arm64/boot/dts/qcom/sm8250-xiaomi-elish-csot.dts | 5 ++ + 3 files changed, 42 insertions(+) + +diff --git a/arch/arm64/boot/dts/qcom/sm8250-xiaomi-elish-boe.dts b/arch/arm64/boot/dts/qcom/sm8250-xiaomi-elish-boe.dts +index de6101dde..b8d9e9406 100644 +--- a/arch/arm64/boot/dts/qcom/sm8250-xiaomi-elish-boe.dts ++++ b/arch/arm64/boot/dts/qcom/sm8250-xiaomi-elish-boe.dts +@@ -16,3 +16,8 @@ &display_panel { + compatible = "xiaomi,elish-boe-nt36523", "novatek,nt36523"; + status = "okay"; + }; ++ ++&touchscreen { ++ firmware-name = "novatek/nt36523-boe.bin"; ++ status = "okay"; ++}; +diff --git a/arch/arm64/boot/dts/qcom/sm8250-xiaomi-elish-common.dtsi b/arch/arm64/boot/dts/qcom/sm8250-xiaomi-elish-common.dtsi +index d7ec6bdd1..b0fe139f8 100644 +--- a/arch/arm64/boot/dts/qcom/sm8250-xiaomi-elish-common.dtsi ++++ b/arch/arm64/boot/dts/qcom/sm8250-xiaomi-elish-common.dtsi +@@ -662,6 +662,16 @@ &pon_resin { + status = "okay"; + }; + ++&qup_spi4_cs_gpio { ++ drive-strength = <6>; ++ bias-disable; ++}; ++ ++&qup_spi4_data_clk { ++ drive-strength = <6>; ++ bias-disable; ++}; ++ + &qupv3_id_0 { + status = "okay"; + }; +@@ -679,6 +689,28 @@ &slpi { + status = "okay"; + }; + ++&spi4 { ++ status = "okay"; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&qup_spi4_data_clk &qup_spi4_cs_gpio>; ++ cs-gpios = <&tlmm 11 GPIO_ACTIVE_LOW>; ++ touchscreen: touchscreen@0 { ++ compatible = "novatek,NVT-ts-spi"; ++ reg = <0>; //Same as CS ID ++ status = "disabled"; ++ ++ spi-max-frequency = <19200000>; //4800000,9600000,15000000,19200000 ++ novatek,irq-gpio = <&tlmm 39 0x2001>; ++ ++ novatek,pen-support; ++ novatek,wgp-stylus; ++ ++ /* 523 */ ++ novatek,swrst-n8-addr = <0x03F0FE>; ++ novatek,spi-rd-fast-addr = <0x03F310>; ++ }; ++}; ++ + &tlmm { + gpio-reserved-ranges = <40 4>; + +diff --git a/arch/arm64/boot/dts/qcom/sm8250-xiaomi-elish-csot.dts b/arch/arm64/boot/dts/qcom/sm8250-xiaomi-elish-csot.dts +index 4cffe9c70..5953f652e 100644 +--- a/arch/arm64/boot/dts/qcom/sm8250-xiaomi-elish-csot.dts ++++ b/arch/arm64/boot/dts/qcom/sm8250-xiaomi-elish-csot.dts +@@ -16,3 +16,8 @@ &display_panel { + compatible = "xiaomi,elish-csot-nt36523", "novatek,nt36523"; + status = "okay"; + }; ++ ++&touchscreen { ++ firmware-name = "novatek/nt36523-csot.bin"; ++ status = "okay"; ++}; +-- +Armbian + diff --git a/patch/kernel/archive/sm8250-6.7/0014-arm64-dts-qcom-sm8250-xiaomi-elish-Disable-slpi.patch b/patch/kernel/archive/sm8250-6.7/0014-arm64-dts-qcom-sm8250-xiaomi-elish-Disable-slpi.patch new file mode 100644 index 000000000..450056c71 --- /dev/null +++ b/patch/kernel/archive/sm8250-6.7/0014-arm64-dts-qcom-sm8250-xiaomi-elish-Disable-slpi.patch @@ -0,0 +1,25 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Jianhua Lu +Date: Wed, 29 Mar 2023 01:57:43 +0800 +Subject: arm64: dts: qcom: sm8250-xiaomi-elish: Disable slpi + +--- + arch/arm64/boot/dts/qcom/sm8250-xiaomi-elish-common.dtsi | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/arch/arm64/boot/dts/qcom/sm8250-xiaomi-elish-common.dtsi b/arch/arm64/boot/dts/qcom/sm8250-xiaomi-elish-common.dtsi +index b0fe139f8..2da3820dd 100644 +--- a/arch/arm64/boot/dts/qcom/sm8250-xiaomi-elish-common.dtsi ++++ b/arch/arm64/boot/dts/qcom/sm8250-xiaomi-elish-common.dtsi +@@ -686,7 +686,7 @@ &qupv3_id_2 { + + &slpi { + firmware-name = "qcom/sm8250/xiaomi/elish/slpi.mbn"; +- status = "okay"; ++ status = "disabled"; + }; + + &spi4 { +-- +Armbian + diff --git a/patch/kernel/archive/sm8250-6.7/0015-sound-soc-qcom-sm8250-Add-tdm-support.patch b/patch/kernel/archive/sm8250-6.7/0015-sound-soc-qcom-sm8250-Add-tdm-support.patch new file mode 100644 index 000000000..dcb2d7d2b --- /dev/null +++ b/patch/kernel/archive/sm8250-6.7/0015-sound-soc-qcom-sm8250-Add-tdm-support.patch @@ -0,0 +1,147 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Jianhua Lu +Date: Fri, 17 Feb 2023 21:31:38 +0800 +Subject: sound: soc: qcom: sm8250: Add tdm support + +--- + sound/soc/qcom/sdw.c | 65 ++++++++++ + sound/soc/qcom/sm8250.c | 17 +++ + 2 files changed, 82 insertions(+) + +diff --git a/sound/soc/qcom/sdw.c b/sound/soc/qcom/sdw.c +index dd275123d..f9370432c 100644 +--- a/sound/soc/qcom/sdw.c ++++ b/sound/soc/qcom/sdw.c +@@ -5,8 +5,11 @@ + #include + #include + #include ++#include + #include "sdw.h" + ++static unsigned int tdm_slot_offset[8] = {0, 4, 8, 12, 16, 20, 24, 28}; ++ + int qcom_snd_sdw_prepare(struct snd_pcm_substream *substream, + struct sdw_stream_runtime *sruntime, + bool *stream_prepared) +@@ -58,6 +61,64 @@ int qcom_snd_sdw_prepare(struct snd_pcm_substream *substream, + } + EXPORT_SYMBOL_GPL(qcom_snd_sdw_prepare); + ++static int qcom_tdm_snd_hw_params(struct snd_pcm_substream *substream, ++ struct snd_pcm_hw_params *params) ++{ ++ struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream); ++ struct snd_soc_dai *cpu_dai = snd_soc_rtd_to_cpu(rtd, 0); ++ ++ int ret = 0; ++ int channels, slot_width; ++ ++ switch (params_format(params)) { ++ case SNDRV_PCM_FORMAT_S16_LE: ++ slot_width = 32; ++ break; ++ default: ++ dev_err(rtd->dev, "%s: invalid param format 0x%x\n", ++ __func__, params_format(params)); ++ return -EINVAL; ++ } ++ ++ channels = params_channels(params); ++ if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { ++ ret = snd_soc_dai_set_tdm_slot(cpu_dai, 0, 0x03, ++ 8, slot_width); ++ if (ret < 0) { ++ dev_err(rtd->dev, "%s: failed to set tdm slot, err:%d\n", ++ __func__, ret); ++ goto end; ++ } ++ ++ ret = snd_soc_dai_set_channel_map(cpu_dai, 0, NULL, ++ channels, tdm_slot_offset); ++ if (ret < 0) { ++ dev_err(rtd->dev, "%s: failed to set channel map, err:%d\n", ++ __func__, ret); ++ goto end; ++ } ++ } else { ++ ret = snd_soc_dai_set_tdm_slot(cpu_dai, 0xf, 0, ++ 8, slot_width); ++ if (ret < 0) { ++ dev_err(rtd->dev, "%s: failed to set tdm slot, err:%d\n", ++ __func__, ret); ++ goto end; ++ } ++ ++ ret = snd_soc_dai_set_channel_map(cpu_dai, channels, ++ tdm_slot_offset, 0, NULL); ++ if (ret < 0) { ++ dev_err(rtd->dev, "%s: failed to set channel map, err:%d\n", ++ __func__, ret); ++ goto end; ++ } ++ } ++ ++end: ++ return ret; ++} ++ + int qcom_snd_sdw_hw_params(struct snd_pcm_substream *substream, + struct snd_pcm_hw_params *params, + struct sdw_stream_runtime **psruntime) +@@ -82,6 +143,10 @@ int qcom_snd_sdw_hw_params(struct snd_pcm_substream *substream, + *psruntime = sruntime; + } + break; ++ case TERTIARY_TDM_RX_0: ++ case TERTIARY_TDM_TX_0: ++ qcom_tdm_snd_hw_params(substream, params); ++ break; + } + + return 0; +diff --git a/sound/soc/qcom/sm8250.c b/sound/soc/qcom/sm8250.c +index 9cc869fd7..200794057 100644 +--- a/sound/soc/qcom/sm8250.c ++++ b/sound/soc/qcom/sm8250.c +@@ -16,6 +16,7 @@ + + #define DRIVER_NAME "sm8250" + #define MI2S_BCLK_RATE 1536000 ++#define TDM_BCLK_RATE 12288000 + + struct sm8250_snd_data { + bool stream_prepared[AFE_PORT_MAX]; +@@ -53,6 +54,7 @@ static int sm8250_snd_startup(struct snd_pcm_substream *substream) + struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_dai *cpu_dai = snd_soc_rtd_to_cpu(rtd, 0); + struct snd_soc_dai *codec_dai = snd_soc_rtd_to_codec(rtd, 0); ++ int ret,j; + + switch (cpu_dai->id) { + case TERTIARY_MI2S_RX: +@@ -63,6 +65,21 @@ static int sm8250_snd_startup(struct snd_pcm_substream *substream) + snd_soc_dai_set_fmt(cpu_dai, fmt); + snd_soc_dai_set_fmt(codec_dai, codec_dai_fmt); + break; ++ case TERTIARY_TDM_RX_0: ++ codec_dai_fmt |= SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_DSP_A; ++ snd_soc_dai_set_sysclk(cpu_dai, ++ Q6AFE_LPASS_CLK_ID_TER_TDM_IBIT, ++ TDM_BCLK_RATE, SNDRV_PCM_STREAM_PLAYBACK); ++ ++ for_each_rtd_codec_dais(rtd, j, codec_dai) { ++ ret = snd_soc_dai_set_fmt(codec_dai, codec_dai_fmt); ++ snd_soc_dai_set_sysclk(codec_dai, 0, TDM_BCLK_RATE, SNDRV_PCM_STREAM_PLAYBACK); ++ if (ret < 0) { ++ dev_err(rtd->dev, "TDM fmt err:%d\n", ret); ++ return ret; ++ } ++ } ++ break; + default: + break; + } +-- +Armbian + diff --git a/patch/kernel/archive/sm8250-6.7/0016-arm64-dts-qcom-sm8250-xiaomi-elish-Add-sound-support.patch b/patch/kernel/archive/sm8250-6.7/0016-arm64-dts-qcom-sm8250-xiaomi-elish-Add-sound-support.patch new file mode 100644 index 000000000..6aa144ef7 --- /dev/null +++ b/patch/kernel/archive/sm8250-6.7/0016-arm64-dts-qcom-sm8250-xiaomi-elish-Add-sound-support.patch @@ -0,0 +1,281 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Jianhua Lu +Date: Sat, 18 Mar 2023 22:26:22 +0800 +Subject: arm64: dts: qcom: sm8250-xiaomi-elish: Add sound support + +--- + arch/arm64/boot/dts/qcom/sm8250-xiaomi-elish-common.dtsi | 232 ++++++++++ + 1 file changed, 232 insertions(+) + +diff --git a/arch/arm64/boot/dts/qcom/sm8250-xiaomi-elish-common.dtsi b/arch/arm64/boot/dts/qcom/sm8250-xiaomi-elish-common.dtsi +index 2da3820dd..45775428c 100644 +--- a/arch/arm64/boot/dts/qcom/sm8250-xiaomi-elish-common.dtsi ++++ b/arch/arm64/boot/dts/qcom/sm8250-xiaomi-elish-common.dtsi +@@ -6,6 +6,8 @@ + #include + #include + #include ++#include ++#include + #include "sm8250.dtsi" + #include "pm8150.dtsi" + #include "pm8150b.dtsi" +@@ -529,6 +531,152 @@ fuel-gauge@55 { + }; + }; + ++&i2c1 { ++ clock-frequency = <400000>; ++ status = "okay"; ++ ++ cs35l41_brh: speaker-amp@40 { ++ compatible = "cirrus,cs35l41"; ++ reg = <0x40>; ++ interrupt-parent = <&tlmm>; ++ interrupts = <7 IRQ_TYPE_LEVEL_LOW>; ++ reset-gpios = <&tlmm 6 GPIO_ACTIVE_HIGH>; ++ cirrus,boost-type = <0>; ++ cirrus,boost-peak-milliamp = <4000>; ++ cirrus,boost-ind-nanohenry = <1000>; ++ cirrus,boost-cap-microfarad = <15>; ++ cirrus,asp-sdout-hiz = <3>; ++ cirrus,gpio2-src-select = <4>; ++ cirrus,gpio2-output-enable; ++ sound-name-prefix = "BRH"; ++ #sound-dai-cells = <1>; ++ }; ++ ++ cs35l41_blh: speaker-amp@41 { ++ compatible = "cirrus,cs35l41"; ++ reg = <0x41>; ++ interrupt-parent = <&tlmm>; ++ interrupts = <67 IRQ_TYPE_LEVEL_LOW>; ++ reset-gpios = <&tlmm 62 GPIO_ACTIVE_HIGH>; ++ cirrus,boost-type = <0>; ++ cirrus,boost-peak-milliamp = <4000>; ++ cirrus,boost-ind-nanohenry = <1000>; ++ cirrus,boost-cap-microfarad = <15>; ++ cirrus,asp-sdout-hiz = <3>; ++ cirrus,gpio2-src-select = <4>; ++ cirrus,gpio2-output-enable; ++ sound-name-prefix = "BLH"; ++ #sound-dai-cells = <1>; ++ }; ++ ++ cs35l41_brl: speaker-amp@42 { ++ compatible = "cirrus,cs35l41"; ++ reg = <0x42>; ++ interrupt-parent = <&tlmm>; ++ interrupts = <100 IRQ_TYPE_LEVEL_LOW>; ++ reset-gpios = <&tlmm 69 GPIO_ACTIVE_HIGH>; ++ cirrus,boost-type = <0>; ++ cirrus,boost-peak-milliamp = <4000>; ++ cirrus,boost-ind-nanohenry = <1000>; ++ cirrus,boost-cap-microfarad = <15>; ++ cirrus,asp-sdout-hiz = <3>; ++ cirrus,gpio2-src-select = <4>; ++ cirrus,gpio2-output-enable; ++ sound-name-prefix = "BRL"; ++ #sound-dai-cells = <1>; ++ }; ++ ++ cs35l41_bll: speaker-amp@43 { ++ compatible = "cirrus,cs35l41"; ++ reg = <0x43>; ++ interrupt-parent = <&tlmm>; ++ interrupts = <126 IRQ_TYPE_LEVEL_LOW>; ++ reset-gpios = <&tlmm 49 GPIO_ACTIVE_HIGH>; ++ cirrus,boost-type = <0>; ++ cirrus,boost-peak-milliamp = <4000>; ++ cirrus,boost-ind-nanohenry = <1000>; ++ cirrus,boost-cap-microfarad = <15>; ++ cirrus,asp-sdout-hiz = <3>; ++ cirrus,gpio2-src-select = <4>; ++ cirrus,gpio2-output-enable; ++ sound-name-prefix = "BLL"; ++ #sound-dai-cells = <1>; ++ }; ++}; ++ ++&i2c3 { ++ clock-frequency = <400000>; ++ status = "okay"; ++ ++ cs35l41_trh: speaker-amp@40 { ++ compatible = "cirrus,cs35l41"; ++ reg = <0x40>; ++ interrupt-parent = <&tlmm>; ++ interrupts = <27 IRQ_TYPE_LEVEL_LOW>; ++ reset-gpios = <&tlmm 50 GPIO_ACTIVE_HIGH>; ++ cirrus,boost-type = <0>; ++ cirrus,boost-peak-milliamp = <4000>; ++ cirrus,boost-ind-nanohenry = <1000>; ++ cirrus,boost-cap-microfarad = <15>; ++ cirrus,asp-sdout-hiz = <3>; ++ cirrus,gpio2-src-select = <4>; ++ cirrus,gpio2-output-enable; ++ sound-name-prefix = "TRH"; ++ #sound-dai-cells = <1>; ++ }; ++ ++ cs35l41_tlh: speaker-amp@41 { ++ compatible = "cirrus,cs35l41"; ++ reg = <0x41>; ++ interrupt-parent = <&tlmm>; ++ interrupts = <92 IRQ_TYPE_LEVEL_LOW>; ++ reset-gpios = <&tlmm 78 GPIO_ACTIVE_HIGH>; ++ cirrus,boost-type = <0>; ++ cirrus,boost-peak-milliamp = <4000>; ++ cirrus,boost-ind-nanohenry = <1000>; ++ cirrus,boost-cap-microfarad = <15>; ++ cirrus,asp-sdout-hiz = <3>; ++ cirrus,gpio2-src-select = <4>; ++ cirrus,gpio2-output-enable; ++ sound-name-prefix = "TLH"; ++ #sound-dai-cells = <1>; ++ }; ++ ++ cs35l41_tll: speaker-amp@42 { ++ compatible = "cirrus,cs35l41"; ++ reg = <0x42>; ++ interrupt-parent = <&tlmm>; ++ interrupts = <112 IRQ_TYPE_LEVEL_LOW>; ++ reset-gpios = <&tlmm 30 GPIO_ACTIVE_HIGH>; ++ cirrus,boost-type = <0>; ++ cirrus,boost-peak-milliamp = <4000>; ++ cirrus,boost-ind-nanohenry = <1000>; ++ cirrus,boost-cap-microfarad = <15>; ++ cirrus,asp-sdout-hiz = <3>; ++ cirrus,gpio2-src-select = <4>; ++ cirrus,gpio2-output-enable; ++ sound-name-prefix = "TLL"; ++ #sound-dai-cells = <1>; ++ }; ++ ++ cs35l41_trl: speaker-amp@43 { ++ compatible = "cirrus,cs35l41"; ++ reg = <0x43>; ++ interrupt-parent = <&tlmm>; ++ interrupts = <129 IRQ_TYPE_LEVEL_LOW>; ++ reset-gpios = <&tlmm 144 GPIO_ACTIVE_HIGH>; ++ cirrus,boost-type = <0>; ++ cirrus,boost-peak-milliamp = <4000>; ++ cirrus,boost-ind-nanohenry = <1000>; ++ cirrus,boost-cap-microfarad = <15>; ++ cirrus,asp-sdout-hiz = <3>; ++ cirrus,gpio2-src-select = <4>; ++ cirrus,gpio2-output-enable; ++ sound-name-prefix = "TRL"; ++ #sound-dai-cells = <1>; ++ }; ++}; ++ + &i2c11 { + clock-frequency = <400000>; + status = "okay"; +@@ -684,11 +832,63 @@ &qupv3_id_2 { + status = "okay"; + }; + ++&q6afedai { ++ dai@56 { ++ reg = ; ++ qcom,tdm-sync-mode = <0>; ++ qcom,tdm-sync-src = <1>; ++ qcom,tdm-data-out = <0>; ++ qcom,tdm-invert-sync = <1>; ++ qcom,tdm-data-delay = <1>; ++ qcom,tdm-data-align = <0>; ++ }; ++}; ++ ++&q6asmdai { ++ dai@0 { ++ reg = <0>; ++ }; ++}; ++ + &slpi { + firmware-name = "qcom/sm8250/xiaomi/elish/slpi.mbn"; + status = "disabled"; + }; + ++&sound { ++ compatible = "qcom,sm8250-sndcard"; ++ model = "Xiaomi Mi Pad 5 Pro"; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&tert_tdm_active>; ++ ++ mm1-dai-link { ++ link-name = "MultiMedia1"; ++ ++ cpu { ++ sound-dai = <&q6asmdai MSM_FRONTEND_DAI_MULTIMEDIA1>; ++ }; ++ }; ++ ++ speaker-dai-link { ++ link-name = "Tertiary TDM Playback"; ++ ++ cpu { ++ sound-dai = <&q6afedai TERTIARY_TDM_RX_0>; ++ }; ++ ++ platform { ++ sound-dai = <&q6routing>; ++ }; ++ ++ codec { ++ sound-dai = <&cs35l41_tlh 0>, <&cs35l41_tll 0>, ++ <&cs35l41_trh 0>, <&cs35l41_trl 0>, ++ <&cs35l41_blh 0>, <&cs35l41_bll 0>, ++ <&cs35l41_brh 0>, <&cs35l41_brl 0>; ++ }; ++ }; ++}; ++ + &spi4 { + status = "okay"; + pinctrl-names = "default"; +@@ -735,6 +935,38 @@ wlan-en-pins { + bias-pull-up; + }; + }; ++ ++ tert_tdm_active: tert-tdm-active-state { ++ sck-pins { ++ pins = "gpio133"; ++ function = "mi2s2_sck"; ++ drive-strength = <8>; ++ bias-disable; ++ output-high; ++ }; ++ ++ din-pins { ++ pins = "gpio134"; ++ function = "mi2s2_data0"; ++ drive-strength = <8>; ++ bias-disable; ++ }; ++ ++ ws-pins { ++ pins = "gpio135"; ++ function = "mi2s2_ws"; ++ drive-strength = <8>; ++ bias-disable; ++ output-high; ++ }; ++ ++ dout-pins { ++ pins = "gpio137"; ++ function = "mi2s2_data1"; ++ drive-strength = <8>; ++ bias-disable; ++ }; ++ }; + }; + + &uart6 { +-- +Armbian + diff --git a/patch/kernel/archive/sm8250-6.7/0017-Asoc-wm_adsp-Add-prefix-support.patch b/patch/kernel/archive/sm8250-6.7/0017-Asoc-wm_adsp-Add-prefix-support.patch new file mode 100644 index 000000000..7d27f9496 --- /dev/null +++ b/patch/kernel/archive/sm8250-6.7/0017-Asoc-wm_adsp-Add-prefix-support.patch @@ -0,0 +1,44 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Jianhua Lu +Date: Wed, 29 Mar 2023 19:38:33 +0800 +Subject: Asoc: wm_adsp: Add prefix support + +--- + sound/soc/codecs/wm_adsp.c | 14 ++++++++++ + 1 file changed, 14 insertions(+) + +diff --git a/sound/soc/codecs/wm_adsp.c b/sound/soc/codecs/wm_adsp.c +index 236b12b69..06770554e 100644 +--- a/sound/soc/codecs/wm_adsp.c ++++ b/sound/soc/codecs/wm_adsp.c +@@ -750,6 +750,10 @@ static int wm_adsp_request_firmware_file(struct wm_adsp *dsp, + *filename = kasprintf(GFP_KERNEL, "%s%s-%s-%s-%s.%s", dir, dsp->part, + dsp->fwf_name, wm_adsp_fw[dsp->fw].file, system_name, + filetype); ++ else if (asoc_component_prefix) ++ *filename = kasprintf(GFP_KERNEL, "%s%s-%s-%s-%s.%s", dir, dsp->part, ++ dsp->fwf_name, wm_adsp_fw[dsp->fw].file, asoc_component_prefix, ++ filetype); + else + *filename = kasprintf(GFP_KERNEL, "%s%s-%s-%s.%s", dir, dsp->part, dsp->fwf_name, + wm_adsp_fw[dsp->fw].file, filetype); +@@ -821,6 +825,16 @@ static int wm_adsp_request_firmware_files(struct wm_adsp *dsp, + NULL, "bin"); + return 0; + } ++ } else if (asoc_component_prefix) { ++ if (!wm_adsp_request_firmware_file(dsp, wmfw_firmware, wmfw_filename, ++ cirrus_dir, NULL, ++ NULL, "wmfw")) { ++ adsp_dbg(dsp, "Found '%s'\n", *wmfw_filename); ++ wm_adsp_request_firmware_file(dsp, coeff_firmware, coeff_filename, ++ cirrus_dir, NULL, ++ asoc_component_prefix, "bin"); ++ return 0; ++ } + } + + if (!wm_adsp_request_firmware_file(dsp, wmfw_firmware, wmfw_filename, +-- +Armbian + diff --git a/patch/kernel/archive/sm8250-6.7/0018-arm64-dts-qcom-sm8250-xiaomi-elish-Add-xiaomi-keyboa.patch b/patch/kernel/archive/sm8250-6.7/0018-arm64-dts-qcom-sm8250-xiaomi-elish-Add-xiaomi-keyboa.patch new file mode 100644 index 000000000..3cdfca9d1 --- /dev/null +++ b/patch/kernel/archive/sm8250-6.7/0018-arm64-dts-qcom-sm8250-xiaomi-elish-Add-xiaomi-keyboa.patch @@ -0,0 +1,100 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Xin Xu +Date: Tue, 22 Aug 2023 00:04:45 +0800 +Subject: arm64: dts: qcom: sm8250-xiaomi-elish: Add xiaomi-keyboard support + +--- + arch/arm64/boot/dts/qcom/sm8250-xiaomi-elish-common.dtsi | 56 ++++++++++ + 1 file changed, 56 insertions(+) + +diff --git a/arch/arm64/boot/dts/qcom/sm8250-xiaomi-elish-common.dtsi b/arch/arm64/boot/dts/qcom/sm8250-xiaomi-elish-common.dtsi +index 45775428c..a8a684b2d 100644 +--- a/arch/arm64/boot/dts/qcom/sm8250-xiaomi-elish-common.dtsi ++++ b/arch/arm64/boot/dts/qcom/sm8250-xiaomi-elish-common.dtsi +@@ -178,6 +178,14 @@ ramoops@b0000000 { + no-map; + }; + }; ++ ++ extcon_usb: extcon-usb { ++ compatible = "linux,extcon-usb-gpio"; ++ id-gpio = <&tlmm 91 GPIO_ACTIVE_HIGH>; ++ vbus-gpio = <&pm8150_gpios 10 GPIO_ACTIVE_HIGH>; ++ pinctrl-0 = <&keyboard_active &usb_2_vbus_det_n>; ++ pinctrl-names = "default"; ++ }; + }; + + &adsp { +@@ -792,6 +800,14 @@ &pcie0_phy { + }; + + &pm8150_gpios { ++ usb_2_vbus_det_n: usb-2-vbus-det-state { ++ pins = "gpio10"; ++ function = "normal"; ++ power-source = <1>; ++ input-enable; ++ bias-pull-down; ++ }; ++ + vol_up_n: vol-up-n-state { + pins = "gpio6"; + function = "normal"; +@@ -967,6 +983,23 @@ dout-pins { + bias-disable; + }; + }; ++ ++ keyboard_active: keyboard-active-state { ++ active-pins { ++ pins = "gpio155"; ++ function = "gpio"; ++ drive-strength = <8>; ++ bias-pull-up; ++ }; ++ ++ vdd-pins { ++ pins = "gpio127"; ++ function = "gpio"; ++ drive-strength = <8>; ++ bias-disable; ++ output-high; ++ }; ++ }; + }; + + &uart6 { +@@ -1003,6 +1036,29 @@ &usb_1_hsphy { + status = "okay"; + }; + ++&usb_2 { ++ status = "okay"; ++}; ++ ++&usb_2_dwc3 { ++ dr_mode = "host"; ++ maximum-speed = "super-speed"; ++ extcon = <&extcon_usb>; ++}; ++ ++&usb_2_hsphy { ++ vdda-pll-supply = <&vreg_l5a_0p88>; ++ vdda18-supply = <&vreg_l12a_1p8>; ++ vdda33-supply = <&vreg_l2a_3p1>; ++ status = "okay"; ++}; ++ ++&usb_2_qmpphy { ++ vdda-phy-supply = <&vreg_l9a_1p2>; ++ vdda-pll-supply = <&vreg_l18a_0p9>; ++ status = "okay"; ++}; ++ + &ufs_mem_hc { + vcc-supply = <&vreg_l17a_3p0>; + vcc-max-microamp = <800000>; +-- +Armbian + diff --git a/patch/kernel/archive/sm8250-6.7/0019-drm-panel-nt36523-Fix-for-kernel-6.5.patch b/patch/kernel/archive/sm8250-6.7/0019-drm-panel-nt36523-Fix-for-kernel-6.5.patch new file mode 100644 index 000000000..3493b7571 --- /dev/null +++ b/patch/kernel/archive/sm8250-6.7/0019-drm-panel-nt36523-Fix-for-kernel-6.5.patch @@ -0,0 +1,24 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: amazingfate +Date: Mon, 16 Oct 2023 13:28:48 +0800 +Subject: drm/panel: nt36523: Fix for kernel 6.5 + +--- + drivers/gpu/drm/panel/panel-novatek-nt36523.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/drivers/gpu/drm/panel/panel-novatek-nt36523.c b/drivers/gpu/drm/panel/panel-novatek-nt36523.c +index 9b9a7eb1b..aa006edb2 100644 +--- a/drivers/gpu/drm/panel/panel-novatek-nt36523.c ++++ b/drivers/gpu/drm/panel/panel-novatek-nt36523.c +@@ -1262,6 +1262,7 @@ static int nt36523_probe(struct mipi_dsi_device *dsi) + + pinfo->dsi[0] = dsi; + mipi_dsi_set_drvdata(dsi, pinfo); ++ pinfo->panel.prepare_prev_first = true; + drm_panel_init(&pinfo->panel, dev, &nt36523_panel_funcs, DRM_MODE_CONNECTOR_DSI); + + ret = of_drm_get_panel_orientation(dev->of_node, &pinfo->orientation); +-- +Armbian + diff --git a/patch/kernel/archive/sm8250-6.7/0020-drivers-spmi-spmi-pmic-arb.c-remove-warnings.patch b/patch/kernel/archive/sm8250-6.7/0020-drivers-spmi-spmi-pmic-arb.c-remove-warnings.patch new file mode 100644 index 000000000..d7ece00f7 --- /dev/null +++ b/patch/kernel/archive/sm8250-6.7/0020-drivers-spmi-spmi-pmic-arb.c-remove-warnings.patch @@ -0,0 +1,24 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: amazingfate +Date: Mon, 16 Oct 2023 13:32:19 +0800 +Subject: drivers/spmi/spmi-pmic-arb.c: remove warnings + +--- + drivers/spmi/spmi-pmic-arb.c | 1 - + 1 file changed, 1 deletion(-) + +diff --git a/drivers/spmi/spmi-pmic-arb.c b/drivers/spmi/spmi-pmic-arb.c +index dcb675d98..2688ac2a7 100644 +--- a/drivers/spmi/spmi-pmic-arb.c ++++ b/drivers/spmi/spmi-pmic-arb.c +@@ -289,7 +289,6 @@ static int pmic_arb_wait_for_done(struct spmi_controller *ctrl, + if (status & PMIC_ARB_STATUS_FAILURE) { + dev_err(&ctrl->dev, "%s: %#x %#x: transaction failed (%#x)\n", + __func__, sid, addr, status); +- WARN_ON(1); + return -EIO; + } + +-- +Armbian + diff --git a/patch/kernel/archive/sm8250-6.7/0021-tty-serial-qcom-geni-fix-zero-dma-rx-len-in.patch b/patch/kernel/archive/sm8250-6.7/0021-tty-serial-qcom-geni-fix-zero-dma-rx-len-in.patch new file mode 100644 index 000000000..32f7d602f --- /dev/null +++ b/patch/kernel/archive/sm8250-6.7/0021-tty-serial-qcom-geni-fix-zero-dma-rx-len-in.patch @@ -0,0 +1,25 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: amazingfate +Date: Mon, 16 Oct 2023 13:32:58 +0800 +Subject: tty: serial: qcom-geni: fix zero dma-rx-len-in + +--- + drivers/tty/serial/qcom_geni_serial.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/tty/serial/qcom_geni_serial.c b/drivers/tty/serial/qcom_geni_serial.c +index 7e78f97e8..6ea1a4f8b 100644 +--- a/drivers/tty/serial/qcom_geni_serial.c ++++ b/drivers/tty/serial/qcom_geni_serial.c +@@ -820,7 +820,7 @@ static void qcom_geni_serial_handle_rx_dma(struct uart_port *uport, bool drop) + rx_in = readl(uport->membase + SE_DMA_RX_LEN_IN); + if (!rx_in) { + dev_warn(uport->dev, "serial engine reports 0 RX bytes in!\n"); +- return; ++ //return; + } + + if (!drop) +-- +Armbian + diff --git a/patch/kernel/archive/sm8250-6.7/0022-Asoc-wm_adsp-Use-xiaomi-elish-firmware-name.patch b/patch/kernel/archive/sm8250-6.7/0022-Asoc-wm_adsp-Use-xiaomi-elish-firmware-name.patch new file mode 100644 index 000000000..8cdc94f79 --- /dev/null +++ b/patch/kernel/archive/sm8250-6.7/0022-Asoc-wm_adsp-Use-xiaomi-elish-firmware-name.patch @@ -0,0 +1,25 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: amazingfate +Date: Tue, 24 Oct 2023 01:01:46 +0800 +Subject: Asoc: wm_adsp: Use xiaomi-elish firmware name + +--- + sound/soc/codecs/wm_adsp.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/sound/soc/codecs/wm_adsp.c b/sound/soc/codecs/wm_adsp.c +index 06770554e..ad52dd67c 100644 +--- a/sound/soc/codecs/wm_adsp.c ++++ b/sound/soc/codecs/wm_adsp.c +@@ -827,7 +827,7 @@ static int wm_adsp_request_firmware_files(struct wm_adsp *dsp, + } + } else if (asoc_component_prefix) { + if (!wm_adsp_request_firmware_file(dsp, wmfw_firmware, wmfw_filename, +- cirrus_dir, NULL, ++ cirrus_dir, "xiaomi-elish", + NULL, "wmfw")) { + adsp_dbg(dsp, "Found '%s'\n", *wmfw_filename); + wm_adsp_request_firmware_file(dsp, coeff_firmware, coeff_filename, +-- +Armbian + diff --git a/patch/kernel/archive/sm8250-6.7/0023-input-nt36523-short-the-firmware-download-delay-from.patch b/patch/kernel/archive/sm8250-6.7/0023-input-nt36523-short-the-firmware-download-delay-from.patch new file mode 100644 index 000000000..4fee775c6 --- /dev/null +++ b/patch/kernel/archive/sm8250-6.7/0023-input-nt36523-short-the-firmware-download-delay-from.patch @@ -0,0 +1,25 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: amazingfate +Date: Thu, 26 Oct 2023 13:13:34 +0800 +Subject: input: nt36523: short the firmware download delay from 14s to 4s + +--- + drivers/input/touchscreen/nt36523/nt36xxx.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/input/touchscreen/nt36523/nt36xxx.c b/drivers/input/touchscreen/nt36523/nt36xxx.c +index 45500ad5c..27f93e531 100644 +--- a/drivers/input/touchscreen/nt36523/nt36xxx.c ++++ b/drivers/input/touchscreen/nt36523/nt36xxx.c +@@ -1452,7 +1452,7 @@ static int32_t nvt_ts_probe(struct spi_device *client) + } + INIT_DELAYED_WORK(&ts->nvt_fwu_work, Boot_Update_Firmware); + // please make sure boot update start after display reset(RESX) sequence +- queue_delayed_work(nvt_fwu_wq, &ts->nvt_fwu_work, msecs_to_jiffies(14000)); ++ queue_delayed_work(nvt_fwu_wq, &ts->nvt_fwu_work, msecs_to_jiffies(4000)); + #endif + + NVT_LOG("NVT_TOUCH_ESD_PROTECT is %d\n", NVT_TOUCH_ESD_PROTECT); +-- +Armbian + diff --git a/patch/kernel/archive/sm8250-6.7/0024-Enable-non-coherent-dst-bufs-for-Venus-V4L2-driver.patch b/patch/kernel/archive/sm8250-6.7/0024-Enable-non-coherent-dst-bufs-for-Venus-V4L2-driver.patch new file mode 100644 index 000000000..77dbaa03b --- /dev/null +++ b/patch/kernel/archive/sm8250-6.7/0024-Enable-non-coherent-dst-bufs-for-Venus-V4L2-driver.patch @@ -0,0 +1,24 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: amazingfate +Date: Fri, 3 Nov 2023 11:20:40 +0800 +Subject: Enable non-coherent dst bufs for Venus V4L2 driver + +--- + drivers/media/platform/qcom/venus/vdec.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/drivers/media/platform/qcom/venus/vdec.c b/drivers/media/platform/qcom/venus/vdec.c +index dbf305cec..14b5d2ebb 100644 +--- a/drivers/media/platform/qcom/venus/vdec.c ++++ b/drivers/media/platform/qcom/venus/vdec.c +@@ -1659,6 +1659,7 @@ static int m2m_queue_init(void *priv, struct vb2_queue *src_vq, + dst_vq->min_buffers_needed = 0; + dst_vq->dev = inst->core->dev; + dst_vq->lock = &inst->ctx_q_lock; ++ dst_vq->allow_cache_hints = 1; + return vb2_queue_init(dst_vq); + } + +-- +Armbian + diff --git a/patch/kernel/archive/sm8250-6.7/0025-bluetooth-fix-some-blutooth-LE-devices-not-pairing.patch b/patch/kernel/archive/sm8250-6.7/0025-bluetooth-fix-some-blutooth-LE-devices-not-pairing.patch new file mode 100644 index 000000000..1748c770a --- /dev/null +++ b/patch/kernel/archive/sm8250-6.7/0025-bluetooth-fix-some-blutooth-LE-devices-not-pairing.patch @@ -0,0 +1,30 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: amazingfate +Date: Sun, 5 Nov 2023 12:23:48 +0800 +Subject: bluetooth: fix some blutooth LE devices not pairing + +--- + net/bluetooth/smp.c | 7 +++++-- + 1 file changed, 5 insertions(+), 2 deletions(-) + +diff --git a/net/bluetooth/smp.c b/net/bluetooth/smp.c +index 5f2f97de2..03b2e9e49 100644 +--- a/net/bluetooth/smp.c ++++ b/net/bluetooth/smp.c +@@ -2969,8 +2969,11 @@ static int smp_sig_channel(struct l2cap_chan *chan, struct sk_buff *skb) + if (code > SMP_CMD_MAX) + goto drop; + +- if (smp && !test_and_clear_bit(code, &smp->allow_cmd)) +- goto drop; ++ if (smp && !test_and_clear_bit(code, &smp->allow_cmd)) { ++ bt_dev_warn(hcon->hdev, "test_and_clear_bit failed with command code 0x%2.2x", code); ++ if ((code != SMP_CMD_ENCRYPT_INFO) && (code != SMP_CMD_INITIATOR_IDENT)) ++ goto drop; ++ } + + /* If we don't have a context the only allowed commands are + * pairing request and security request. +-- +Armbian + diff --git a/patch/kernel/archive/sm8250-6.7/0026-arm64-dts-qcom-sm8250-xiaomi-elish-Fix-typos.patch b/patch/kernel/archive/sm8250-6.7/0026-arm64-dts-qcom-sm8250-xiaomi-elish-Fix-typos.patch new file mode 100644 index 000000000..e7fa013bb --- /dev/null +++ b/patch/kernel/archive/sm8250-6.7/0026-arm64-dts-qcom-sm8250-xiaomi-elish-Fix-typos.patch @@ -0,0 +1,40 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Jianhua Lu +Date: Sun, 26 Nov 2023 10:28:48 +0800 +Subject: arm64: dts: qcom: sm8250-xiaomi-elish: Fix typos + +There are two typos in this dtsi, so fix it. + classis -> chassis. + 80700000 -> 80600000 + +Reviewed-by: Konrad Dybcio +Signed-off-by: Jianhua Lu +--- + arch/arm64/boot/dts/qcom/sm8250-xiaomi-elish-common.dtsi | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/arch/arm64/boot/dts/qcom/sm8250-xiaomi-elish-common.dtsi b/arch/arm64/boot/dts/qcom/sm8250-xiaomi-elish-common.dtsi +index a8a684b2d..6fcbf387c 100644 +--- a/arch/arm64/boot/dts/qcom/sm8250-xiaomi-elish-common.dtsi ++++ b/arch/arm64/boot/dts/qcom/sm8250-xiaomi-elish-common.dtsi +@@ -25,7 +25,7 @@ + /delete-node/ &xbl_aop_mem; + + / { +- classis-type = "tablet"; ++ chassis-type = "tablet"; + + /* required for bootloader to select correct board */ + qcom,msm-id = ; /* SM8250 v2.1 */ +@@ -139,7 +139,7 @@ qca639x: qca639x { + }; + + reserved-memory { +- xbl_aop_mem: xbl-aop@80700000 { ++ xbl_aop_mem: xbl-aop@80600000 { + reg = <0x0 0x80600000 0x0 0x260000>; + no-map; + }; +-- +Armbian + diff --git a/patch/kernel/archive/sm8250-6.7/0027-arm64-dts-qcom-sm8250-xiaomi-elish-Add-pm8150b-type-.patch b/patch/kernel/archive/sm8250-6.7/0027-arm64-dts-qcom-sm8250-xiaomi-elish-Add-pm8150b-type-.patch new file mode 100644 index 000000000..7ae037e3f --- /dev/null +++ b/patch/kernel/archive/sm8250-6.7/0027-arm64-dts-qcom-sm8250-xiaomi-elish-Add-pm8150b-type-.patch @@ -0,0 +1,97 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Jianhua Lu +Date: Sun, 26 Nov 2023 10:28:49 +0800 +Subject: arm64: dts: qcom: sm8250-xiaomi-elish: Add pm8150b type-c node and + enable usb otg + +Add type-c node to feature otg function and set usb-role-switch property +for usb_1_dwc3 to enable usb otg. + +Reviewed-by: Konrad Dybcio +Signed-off-by: Jianhua Lu +--- + arch/arm64/boot/dts/qcom/sm8250-xiaomi-elish-common.dtsi | 43 +++++++++- + 1 file changed, 42 insertions(+), 1 deletion(-) + +diff --git a/arch/arm64/boot/dts/qcom/sm8250-xiaomi-elish-common.dtsi b/arch/arm64/boot/dts/qcom/sm8250-xiaomi-elish-common.dtsi +index 6fcbf387c..276d5a53d 100644 +--- a/arch/arm64/boot/dts/qcom/sm8250-xiaomi-elish-common.dtsi ++++ b/arch/arm64/boot/dts/qcom/sm8250-xiaomi-elish-common.dtsi +@@ -8,6 +8,7 @@ + #include + #include + #include ++#include + #include "sm8250.dtsi" + #include "pm8150.dtsi" + #include "pm8150b.dtsi" +@@ -817,6 +818,41 @@ vol_up_n: vol-up-n-state { + }; + }; + ++&pm8150b_typec { ++ vdd-pdphy-supply = <&vreg_l2a_3p1>; ++ status = "okay"; ++ ++ connector { ++ compatible = "usb-c-connector"; ++ ++ power-role = "source"; ++ data-role = "dual"; ++ self-powered; ++ ++ source-pdos = ; ++ ++ ports { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ port@0 { ++ reg = <0>; ++ ++ pm8150b_role_switch_in: endpoint { ++ remote-endpoint = <&usb_1_role_switch_out>; ++ }; ++ }; ++ }; ++ }; ++}; ++ ++&pm8150b_vbus { ++ status = "okay"; ++}; ++ + &pon_pwrkey { + status = "okay"; + }; +@@ -1022,11 +1058,12 @@ &usb_1 { + }; + + &usb_1_dwc3 { +- dr_mode = "peripheral"; ++ dr_mode = "otg"; + maximum-speed = "high-speed"; + /* Remove USB3 phy */ + phys = <&usb_1_hsphy>; + phy-names = "usb2-phy"; ++ usb-role-switch; + }; + + &usb_1_hsphy { +@@ -1059,6 +1096,10 @@ &usb_2_qmpphy { + status = "okay"; + }; + ++&usb_1_role_switch_out { ++ remote-endpoint = <&pm8150b_role_switch_in>; ++}; ++ + &ufs_mem_hc { + vcc-supply = <&vreg_l17a_3p0>; + vcc-max-microamp = <800000>; +-- +Armbian + diff --git a/patch/kernel/archive/sm8250-6.7/0028-drm-msm-dsi-change-sync-mode-to-sync-on-DSI0-rather-.patch b/patch/kernel/archive/sm8250-6.7/0028-drm-msm-dsi-change-sync-mode-to-sync-on-DSI0-rather-.patch new file mode 100644 index 000000000..865ee4e15 --- /dev/null +++ b/patch/kernel/archive/sm8250-6.7/0028-drm-msm-dsi-change-sync-mode-to-sync-on-DSI0-rather-.patch @@ -0,0 +1,78 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Dmitry Baryshkov +Date: Sun, 4 Jun 2023 21:44:33 +0300 +Subject: drm/msm/dsi: change sync mode to sync on DSI0 rather than DSI1 + +Change MSM DSI's sync-dual-dsi mode to resync on DSI0 rather than DSI1. + +Signed-off-by: Dmitry Baryshkov +--- + drivers/gpu/drm/msm/dsi/dsi_manager.c | 24 +++++----- + 1 file changed, 12 insertions(+), 12 deletions(-) + +diff --git a/drivers/gpu/drm/msm/dsi/dsi_manager.c b/drivers/gpu/drm/msm/dsi/dsi_manager.c +index 50d788138..500b201c5 100644 +--- a/drivers/gpu/drm/msm/dsi/dsi_manager.c ++++ b/drivers/gpu/drm/msm/dsi/dsi_manager.c +@@ -564,7 +564,7 @@ int msm_dsi_manager_ext_bridge_init(u8 id) + int msm_dsi_manager_cmd_xfer(int id, const struct mipi_dsi_msg *msg) + { + struct msm_dsi *msm_dsi = dsi_mgr_get_dsi(id); +- struct msm_dsi *msm_dsi0 = dsi_mgr_get_dsi(DSI_0); ++ struct msm_dsi *msm_dsi1 = dsi_mgr_get_dsi(DSI_1); + struct mipi_dsi_host *host = msm_dsi->host; + bool is_read = (msg->rx_buf && msg->rx_len); + bool need_sync = (IS_SYNC_NEEDED() && !is_read); +@@ -575,14 +575,14 @@ int msm_dsi_manager_cmd_xfer(int id, const struct mipi_dsi_msg *msg) + + /* In bonded master case, panel requires the same commands sent to + * both DSI links. Host issues the command trigger to both links +- * when DSI_1 calls the cmd transfer function, no matter it happens +- * before or after DSI_0 cmd transfer. ++ * when DSI_0 calls the cmd transfer function, no matter it happens ++ * before or after DSI_1 cmd transfer. + */ +- if (need_sync && (id == DSI_0)) ++ if (need_sync && (id == DSI_1)) + return is_read ? msg->rx_len : msg->tx_len; + +- if (need_sync && msm_dsi0) { +- ret = msm_dsi_host_xfer_prepare(msm_dsi0->host, msg); ++ if (need_sync && msm_dsi1) { ++ ret = msm_dsi_host_xfer_prepare(msm_dsi1->host, msg); + if (ret) { + pr_err("%s: failed to prepare non-trigger host, %d\n", + __func__, ret); +@@ -601,8 +601,8 @@ int msm_dsi_manager_cmd_xfer(int id, const struct mipi_dsi_msg *msg) + msm_dsi_host_xfer_restore(host, msg); + + restore_host0: +- if (need_sync && msm_dsi0) +- msm_dsi_host_xfer_restore(msm_dsi0->host, msg); ++ if (need_sync && msm_dsi1) ++ msm_dsi_host_xfer_restore(msm_dsi1->host, msg); + + return ret; + } +@@ -610,14 +610,14 @@ int msm_dsi_manager_cmd_xfer(int id, const struct mipi_dsi_msg *msg) + bool msm_dsi_manager_cmd_xfer_trigger(int id, u32 dma_base, u32 len) + { + struct msm_dsi *msm_dsi = dsi_mgr_get_dsi(id); +- struct msm_dsi *msm_dsi0 = dsi_mgr_get_dsi(DSI_0); ++ struct msm_dsi *msm_dsi1 = dsi_mgr_get_dsi(DSI_1); + struct mipi_dsi_host *host = msm_dsi->host; + +- if (IS_SYNC_NEEDED() && (id == DSI_0)) ++ if (IS_SYNC_NEEDED() && (id == DSI_1)) + return false; + +- if (IS_SYNC_NEEDED() && msm_dsi0) +- msm_dsi_host_cmd_xfer_commit(msm_dsi0->host, dma_base, len); ++ if (IS_SYNC_NEEDED() && msm_dsi1) ++ msm_dsi_host_cmd_xfer_commit(msm_dsi1->host, dma_base, len); + + msm_dsi_host_cmd_xfer_commit(host, dma_base, len); + +-- +Armbian + diff --git a/patch/kernel/archive/sm8250-6.7/0029-arm64-dts-qcom-sm8250-xiaomi-elish-Hook-up-type-c-fo.patch b/patch/kernel/archive/sm8250-6.7/0029-arm64-dts-qcom-sm8250-xiaomi-elish-Hook-up-type-c-fo.patch new file mode 100644 index 000000000..4cc44238e --- /dev/null +++ b/patch/kernel/archive/sm8250-6.7/0029-arm64-dts-qcom-sm8250-xiaomi-elish-Hook-up-type-c-fo.patch @@ -0,0 +1,80 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Jianhua Lu +Date: Fri, 1 Sep 2023 23:29:17 +0800 +Subject: arm64: dts: qcom: sm8250-xiaomi-elish: Hook up type-c for usb_1 + +--- + arch/arm64/boot/dts/qcom/sm8250-xiaomi-elish-common.dtsi | 14 ++++++-- + arch/arm64/boot/dts/qcom/sm8250.dtsi | 17 ++++++++-- + 2 files changed, 27 insertions(+), 4 deletions(-) + +diff --git a/arch/arm64/boot/dts/qcom/sm8250-xiaomi-elish-common.dtsi b/arch/arm64/boot/dts/qcom/sm8250-xiaomi-elish-common.dtsi +index 276d5a53d..ae6a2a060 100644 +--- a/arch/arm64/boot/dts/qcom/sm8250-xiaomi-elish-common.dtsi ++++ b/arch/arm64/boot/dts/qcom/sm8250-xiaomi-elish-common.dtsi +@@ -822,6 +822,12 @@ &pm8150b_typec { + vdd-pdphy-supply = <&vreg_l2a_3p1>; + status = "okay"; + ++ port { ++ pm8150b_role_switch_in: endpoint { ++ remote-endpoint = <&usb_1_role_switch_out>; ++ }; ++ }; ++ + connector { + compatible = "usb-c-connector"; + +@@ -841,8 +847,8 @@ ports { + port@0 { + reg = <0>; + +- pm8150b_role_switch_in: endpoint { +- remote-endpoint = <&usb_1_role_switch_out>; ++ pm8150b_typec_hsphy_in: endpoint { ++ remote-endpoint = <&usb_1_dwc3_hs>; + }; + }; + }; +@@ -1066,6 +1072,10 @@ &usb_1_dwc3 { + usb-role-switch; + }; + ++&usb_1_dwc3_hs { ++ remote-endpoint = <&pm8150b_typec_hsphy_in>; ++}; ++ + &usb_1_hsphy { + vdda-pll-supply = <&vreg_l5a_0p88>; + vdda18-supply = <&vreg_l12a_1p8>; +diff --git a/arch/arm64/boot/dts/qcom/sm8250.dtsi b/arch/arm64/boot/dts/qcom/sm8250.dtsi +index be970472f..d9ac8bc62 100644 +--- a/arch/arm64/boot/dts/qcom/sm8250.dtsi ++++ b/arch/arm64/boot/dts/qcom/sm8250.dtsi +@@ -4158,8 +4158,21 @@ usb_1_dwc3: usb@a600000 { + phys = <&usb_1_hsphy>, <&usb_1_qmpphy QMP_USB43DP_USB3_PHY>; + phy-names = "usb2-phy", "usb3-phy"; + +- port { +- usb_1_role_switch_out: endpoint {}; ++ ports { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ port@0 { ++ reg = <0>; ++ ++ usb_1_role_switch_out: endpoint {}; ++ }; ++ ++ port@1 { ++ reg = <1>; ++ ++ usb_1_dwc3_hs: endpoint {}; ++ }; + }; + }; + }; +-- +Armbian + diff --git a/patch/kernel/archive/sm8250-6.7/0030-arm64-dts-qcom-sm8250-xiaomi-elish-Hook-up-usb-keybo.patch b/patch/kernel/archive/sm8250-6.7/0030-arm64-dts-qcom-sm8250-xiaomi-elish-Hook-up-usb-keybo.patch new file mode 100644 index 000000000..114748eae --- /dev/null +++ b/patch/kernel/archive/sm8250-6.7/0030-arm64-dts-qcom-sm8250-xiaomi-elish-Hook-up-usb-keybo.patch @@ -0,0 +1,111 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Jianhua Lu +Date: Sat, 2 Sep 2023 14:54:26 +0800 +Subject: arm64: dts: qcom: sm8250-xiaomi-elish: Hook up usb keyboard + +--- + arch/arm64/boot/dts/qcom/sm8250-xiaomi-elish-common.dtsi | 31 +++++----- + arch/arm64/boot/dts/qcom/sm8250.dtsi | 17 +++++ + 2 files changed, 31 insertions(+), 17 deletions(-) + +diff --git a/arch/arm64/boot/dts/qcom/sm8250-xiaomi-elish-common.dtsi b/arch/arm64/boot/dts/qcom/sm8250-xiaomi-elish-common.dtsi +index ae6a2a060..31031e919 100644 +--- a/arch/arm64/boot/dts/qcom/sm8250-xiaomi-elish-common.dtsi ++++ b/arch/arm64/boot/dts/qcom/sm8250-xiaomi-elish-common.dtsi +@@ -179,14 +179,6 @@ ramoops@b0000000 { + no-map; + }; + }; +- +- extcon_usb: extcon-usb { +- compatible = "linux,extcon-usb-gpio"; +- id-gpio = <&tlmm 91 GPIO_ACTIVE_HIGH>; +- vbus-gpio = <&pm8150_gpios 10 GPIO_ACTIVE_HIGH>; +- pinctrl-0 = <&keyboard_active &usb_2_vbus_det_n>; +- pinctrl-names = "default"; +- }; + }; + + &adsp { +@@ -801,14 +793,6 @@ &pcie0_phy { + }; + + &pm8150_gpios { +- usb_2_vbus_det_n: usb-2-vbus-det-state { +- pins = "gpio10"; +- function = "normal"; +- power-source = <1>; +- input-enable; +- bias-pull-down; +- }; +- + vol_up_n: vol-up-n-state { + pins = "gpio6"; + function = "normal"; +@@ -851,6 +835,13 @@ pm8150b_typec_hsphy_in: endpoint { + remote-endpoint = <&usb_1_dwc3_hs>; + }; + }; ++ ++ port@1 { ++ reg = <1>; ++ pm8150b_typec_ssphy_in: endpoint { ++ remote-endpoint = <&usb_2_dwc3_ss>; ++ }; ++ }; + }; + }; + }; +@@ -1090,7 +1081,10 @@ &usb_2 { + &usb_2_dwc3 { + dr_mode = "host"; + maximum-speed = "super-speed"; +- extcon = <&extcon_usb>; ++}; ++ ++&usb_2_dwc3_ss { ++ remote-endpoint = <&pm8150b_typec_ssphy_in>; + }; + + &usb_2_hsphy { +@@ -1104,6 +1098,9 @@ &usb_2_qmpphy { + vdda-phy-supply = <&vreg_l9a_1p2>; + vdda-pll-supply = <&vreg_l18a_0p9>; + status = "okay"; ++ ++ pinctrl-0 = <&keyboard_active>; ++ pinctrl-names = "default"; + }; + + &usb_1_role_switch_out { +diff --git a/arch/arm64/boot/dts/qcom/sm8250.dtsi b/arch/arm64/boot/dts/qcom/sm8250.dtsi +index d9ac8bc62..7c27e5c1a 100644 +--- a/arch/arm64/boot/dts/qcom/sm8250.dtsi ++++ b/arch/arm64/boot/dts/qcom/sm8250.dtsi +@@ -4238,6 +4238,23 @@ usb_2_dwc3: usb@a800000 { + snps,dis_enblslpm_quirk; + phys = <&usb_2_hsphy>, <&usb_2_ssphy>; + phy-names = "usb2-phy", "usb3-phy"; ++ ++ ports { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ port@0 { ++ reg = <0>; ++ ++ usb_2_dwc3_hs: endpoint {}; ++ }; ++ ++ port@1 { ++ reg = <1>; ++ ++ usb_2_dwc3_ss: endpoint {}; ++ }; ++ }; + }; + }; + +-- +Armbian + diff --git a/patch/kernel/arm64-sm8250 b/patch/kernel/arm64-sm8250 index 8908a5574..a31825316 120000 --- a/patch/kernel/arm64-sm8250 +++ b/patch/kernel/arm64-sm8250 @@ -1 +1 @@ -archive/sm8250-6.6 \ No newline at end of file +archive/sm8250-6.7 \ No newline at end of file