kernel: Adding changes for taoyao
FROMGIT: Kernel: Xiaomi kernel changes for Xiaomi 12 Lite Android S The Patch based on QualComm release TAG:LA.UM.9.14.r1-18300.05-LAHAINA.QSSI12.0-1 The kernel config file used is taoyao_QGKI.config Signed-off-by: jiahao <jiahao@xiaomi.com> Change-Id: Ie81ca042c1c9187468339728f8d1066060fb8702
This commit is contained in:
@@ -348,6 +348,15 @@ Contact: "Daeho Jeong" <daehojeong@google.com>
|
||||
Description: Give a way to change iostat_period time. 3secs by default.
|
||||
The new iostat trace gives stats gap given the period.
|
||||
|
||||
What: /sys/fs/f2fs/<disk>/ckpt_thread_ioprio
|
||||
Date: January 2021
|
||||
Contact: "Daeho Jeong" <daehojeong@google.com>
|
||||
Description: Give a way to change checkpoint merge daemon's io priority.
|
||||
Its default value is "be,3", which means "BE" I/O class and
|
||||
I/O priority "3". We can select the class between "rt" and "be",
|
||||
and set the I/O priority within valid range of it. "," delimiter
|
||||
is necessary in between I/O class and priority number.
|
||||
|
||||
What: /sys/fs/f2fs/<disk>/ovp_segments
|
||||
Date: March 2021
|
||||
Contact: "Jaegeuk Kim" <jaegeuk@kernel.org>
|
||||
|
||||
@@ -106,6 +106,12 @@ background_gc=%s Turn on/off cleaning operations, namely garbage
|
||||
on synchronous garbage collection running in background.
|
||||
Default value for this option is on. So garbage
|
||||
collection is on by default.
|
||||
gc_merge When background_gc is on, this option can be enabled to
|
||||
let background GC thread to handle foreground GC requests,
|
||||
it can eliminate the sluggish issue caused by slow foreground
|
||||
GC operation when GC is triggered from a process with limited
|
||||
I/O and CPU resources.
|
||||
nogc_merge Disable GC merge feature.
|
||||
disable_roll_forward Disable the roll-forward recovery routine
|
||||
norecovery Disable the roll-forward recovery routine, mounted read-
|
||||
only (i.e., -o ro,disable_roll_forward)
|
||||
@@ -239,6 +245,17 @@ checkpoint=%s[:%u[%]] Set to "disable" to turn off checkpointing. Set to "en
|
||||
hide up to all remaining free space. The actual space that
|
||||
would be unusable can be viewed at /sys/fs/f2fs/<disk>/unusable
|
||||
This space is reclaimed once checkpoint=enable.
|
||||
checkpoint_merge When checkpoint is enabled, this can be used to create a kernel
|
||||
daemon and make it to merge concurrent checkpoint requests as
|
||||
much as possible to eliminate redundant checkpoint issues. Plus,
|
||||
we can eliminate the sluggish issue caused by slow checkpoint
|
||||
operation when the checkpoint is done in a process context in
|
||||
a cgroup having low i/o budget and cpu shares. To make this
|
||||
do better, we set the default i/o priority of the kernel daemon
|
||||
to "3", to give one higher priority than other kernel threads.
|
||||
This is the same way to give a I/O priority to the jbd2
|
||||
journaling thread of ext4 filesystem.
|
||||
nocheckpoint_merge Disable checkpoint merge feature.
|
||||
compress_algorithm=%s Control compress algorithm, currently f2fs supports "lzo",
|
||||
"lz4" and "zstd" algorithm.
|
||||
compress_log_size=%u Support configuring compress cluster size, the size will
|
||||
|
||||
@@ -44,6 +44,8 @@
|
||||
wakeup_source_remove
|
||||
wakeup_source_add
|
||||
wakeup_source_create
|
||||
mipi_dsi_dcs_read
|
||||
mipi_dsi_dcs_write
|
||||
|
||||
# required by exfat.ko
|
||||
block_write_full_page
|
||||
@@ -106,5 +108,27 @@
|
||||
utf8s_to_utf16s
|
||||
write_inode_now
|
||||
|
||||
# required by goodix_core.ko
|
||||
filp_close
|
||||
filp_open
|
||||
strncat
|
||||
single_open_size
|
||||
input_mt_sync_frame
|
||||
|
||||
# required by sr100.ko
|
||||
spi_bus_type
|
||||
# required by incrementalfs.ko
|
||||
revert_creds
|
||||
|
||||
# required by aw8697-haptic.ko
|
||||
i2c_smbus_read_byte_data
|
||||
i2c_smbus_write_byte_data
|
||||
|
||||
# required by aw882xx_dlkm.ko
|
||||
class_remove_file_ns
|
||||
class_create_file_ns
|
||||
class_remove_file
|
||||
class_create_file
|
||||
|
||||
# required by synaptics_tcm_testing.ko
|
||||
__kernel_write
|
||||
|
||||
261
arch/arm64/configs/vendor/taoyao_GKI.config
vendored
Normal file
261
arch/arm64/configs/vendor/taoyao_GKI.config
vendored
Normal file
@@ -0,0 +1,261 @@
|
||||
CONFIG_ARCH_QCOM=y
|
||||
CONFIG_ARCH_LAHAINA=y
|
||||
CONFIG_ARCH_SHIMA=y
|
||||
CONFIG_TRIM_UNUSED_KSYMS=y
|
||||
CONFIG_UNUSED_KSYMS_WHITELIST="android/abi_gki_aarch64_qcom android/abi_gki_aarch64_xiaomi android/abi_gki_aarch64_qcom_internal"
|
||||
CONFIG_UNUSED_KSYMS_WHITELIST_ONLY=y
|
||||
CONFIG_QCOM_RPMH=m
|
||||
CONFIG_QCOM_RPMHPD=m
|
||||
CONFIG_QCOM_COMMAND_DB=m
|
||||
CONFIG_REGULATOR_STUB=m
|
||||
CONFIG_REGULATOR_PROXY_CONSUMER=m
|
||||
CONFIG_PINCTRL_MSM=m
|
||||
CONFIG_PINCTRL_LAHAINA=m
|
||||
CONFIG_PINCTRL_SHIMA=m
|
||||
CONFIG_SND_USB_AUDIO_QMI=m
|
||||
CONFIG_EXTCON=m
|
||||
CONFIG_SPMI_MSM_PMIC_ARB=m
|
||||
CONFIG_SPMI_MSM_PMIC_ARB_DEBUG=m
|
||||
CONFIG_SPMI_QTI_GLINK_DEBUG=m
|
||||
CONFIG_MFD_I2C_PMIC=m
|
||||
CONFIG_PINCTRL_QCOM_SPMI_PMIC=m
|
||||
CONFIG_NVMEM_SPMI_SDAM=m
|
||||
CONFIG_RTC_DRV_PM8XXX=m
|
||||
CONFIG_QCOM_SPMI_ADC5=m
|
||||
CONFIG_QCOM_SPMI_TEMP_ALARM=m
|
||||
CONFIG_INPUT_QPNP_POWER_ON=m
|
||||
#CONFIG_INPUT_QCOM_HV_HAPTICS is not set
|
||||
#CONFIG_INPUT_AW8624_HAPTIC=m
|
||||
CONFIG_INPUT_AW862XX_HAPTIC=m
|
||||
CONFIG_NOP_USB_XCEIV=m
|
||||
CONFIG_USB_QCOM_EMU_PHY=m
|
||||
CONFIG_USB_XHCI_HCD=m
|
||||
CONFIG_USB_DWC3=m
|
||||
CONFIG_USB_DWC3_QCOM=m
|
||||
CONFIG_USB_DWC3_MSM=m
|
||||
CONFIG_USB_EHSET_TEST_FIXTURE=m
|
||||
CONFIG_USB_LINK_LAYER_TEST=m
|
||||
CONFIG_USB_CONFIGFS_F_DIAG=m
|
||||
CONFIG_USB_CONFIGFS_F_CCID=m
|
||||
CONFIG_USB_CONFIGFS_F_CDEV=m
|
||||
CONFIG_USB_CONFIGFS_F_GSI=m
|
||||
CONFIG_USB_CONFIGFS_F_QDSS=m
|
||||
CONFIG_USB_CONFIGFS_F_UAC2=m
|
||||
CONFIG_TYPEC_UCSI=m
|
||||
CONFIG_UCSI_QTI_GLINK=m
|
||||
CONFIG_INTERCONNECT_QCOM=m
|
||||
CONFIG_INTERCONNECT_QCOM_LAHAINA=m
|
||||
CONFIG_PHY_QCOM_UFS=m
|
||||
CONFIG_PHY_QCOM_UFS_QRBTC_SDM845=m
|
||||
CONFIG_PHY_QCOM_UFS_V4=m
|
||||
CONFIG_SCSI_UFS_QCOM=m
|
||||
CONFIG_CHR_DEV_SG=m
|
||||
CONFIG_MSM_CORE_HANG_DETECT=m
|
||||
CONFIG_QCOM_LLCC=m
|
||||
CONFIG_QCOM_LAHAINA_LLCC=m
|
||||
CONFIG_QCOM_SHIMA_LLCC=m
|
||||
CONFIG_QCOM_IPCC=m
|
||||
CONFIG_QCOM_WDT_CORE=m
|
||||
CONFIG_QCOM_FORCE_WDOG_BITE_ON_PANIC=y
|
||||
CONFIG_QCOM_MEMORY_DUMP_V2=m
|
||||
CONFIG_QCOM_SCM=m
|
||||
CONFIG_QTEE_SHM_BRIDGE=y
|
||||
# CONFIG_QCOM_SCM_DOWNLOAD_MODE_DEFAULT is not set
|
||||
CONFIG_BUILD_ARM64_UNCOMPRESSED_KERNEL=y
|
||||
CONFIG_HWSPINLOCK_QCOM=m
|
||||
CONFIG_QCOM_GLINK_PKT=m
|
||||
CONFIG_QCOM_SMEM=m
|
||||
CONFIG_QCOM_SMP2P=m
|
||||
CONFIG_QCOM_SMSM=m
|
||||
CONFIG_MSM_QMP=m
|
||||
CONFIG_QCOM_SMP2P_SLEEPSTATE=m
|
||||
CONFIG_RPMSG_QCOM_GLINK_SMEM=m
|
||||
CONFIG_QCOM_GLINK=m
|
||||
CONFIG_MSM_GLINK_SSR=m
|
||||
CONFIG_QTI_PMIC_GLINK=m
|
||||
CONFIG_QTI_BATTERY_CHARGER_ODIN=m
|
||||
CONFIG_QTI_BATTERY_GLINK_DEBUG=m
|
||||
CONFIG_QTI_ALTMODE_GLINK=m
|
||||
CONFIG_QTI_PMIC_PON_LOG=m
|
||||
CONFIG_QRTR_MHI=m
|
||||
CONFIG_QSEE_IPC_IRQ_BRIDGE=m
|
||||
CONFIG_SENSORS_SSC=m
|
||||
CONFIG_POWER_RESET_MSM=m
|
||||
CONFIG_POWER_RESET_QCOM_DOWNLOAD_MODE=m
|
||||
CONFIG_POWER_RESET_QCOM_DOWNLOAD_MODE_DEFAULT=y
|
||||
CONFIG_POWER_RESET_QCOM_REBOOT_REASON=m
|
||||
CONFIG_QCOM_FORCE_WDOG_BITE_ON_PANIC=y
|
||||
CONFIG_MSM_SUBSYSTEM_RESTART=m
|
||||
CONFIG_SETUP_SSR_NOTIF_TIMEOUTS=y
|
||||
CONFIG_SSR_SYSMON_NOTIF_TIMEOUT=20000
|
||||
CONFIG_SSR_SUBSYS_NOTIF_TIMEOUT=20000
|
||||
CONFIG_PANIC_ON_SSR_NOTIF_TIMEOUT=y
|
||||
CONFIG_MSM_PIL_SSR_GENERIC=m
|
||||
CONFIG_MSM_SERVICE_LOCATOR=m
|
||||
CONFIG_MSM_SERVICE_NOTIFIER=m
|
||||
CONFIG_QSEE_IPC_IRQ=m
|
||||
CONFIG_RPMSG_QCOM_GLINK_SPSS=m
|
||||
CONFIG_REGULATOR_RPMH=m
|
||||
CONFIG_REGULATOR_QTI_FIXED_VOLTAGE=m
|
||||
CONFIG_REGULATOR_QCOM_PM8008=m
|
||||
CONFIG_REGULATOR_QPNP_AMOLED=m
|
||||
CONFIG_HWMON=m
|
||||
CONFIG_SENSORS_QTI_AMOLED_ECM=m
|
||||
CONFIG_MSM_GCC_LAHAINA=m
|
||||
CONFIG_REGULATOR_REFGEN=m
|
||||
CONFIG_MSM_VIDEOCC_LAHAINA=m
|
||||
CONFIG_MSM_DISPCC_LAHAINA=m
|
||||
CONFIG_COMMON_CLK_QCOM=m
|
||||
CONFIG_MSM_GPUCC_LAHAINA=m
|
||||
CONFIG_MSM_GLOBAL_SYNX=m
|
||||
CONFIG_MSM_CVP=m
|
||||
CONFIG_QCOM_EUD=m
|
||||
CONFIG_QRTR=m
|
||||
CONFIG_QRTR_SMD=m
|
||||
CONFIG_USB_MSM_SSPHY_QMP=m
|
||||
CONFIG_MSM_HSUSB_PHY=m
|
||||
CONFIG_MSM_CAMCC_LAHAINA=m
|
||||
CONFIG_MSM_BT_POWER=m
|
||||
CONFIG_ARM_SMMU=m
|
||||
CONFIG_ARM_SMMU_POWER_ALWAYS_ON=y
|
||||
CONFIG_QTI_IOMMU_SUPPORT=m
|
||||
CONFIG_MSM_CLK_AOP_QMP=m
|
||||
CONFIG_MSM_SPSS_UTILS=m
|
||||
CONFIG_IPA3=m
|
||||
CONFIG_IPA_WDI_UNIFIED_API=y
|
||||
CONFIG_CNSS2=m
|
||||
CONFIG_CNSS2_QMI=y
|
||||
CONFIG_ICNSS2=m
|
||||
CONFIG_ICNSS2_QMI=y
|
||||
CONFIG_CNSS_ASYNC=y
|
||||
CONFIG_DRM_LONTIUM_LT9611UXC=y
|
||||
CONFIG_BUS_AUTO_SUSPEND=y
|
||||
CONFIG_CNSS_UTILS=m
|
||||
CONFIG_CNSS_GENL=m
|
||||
CONFIG_WCNSS_MEM_PRE_ALLOC=m
|
||||
CONFIG_QCOM_SECURE_BUFFER=m
|
||||
CONFIG_MSM_QBT_HANDLER=m
|
||||
CONFIG_ION_MSM_HEAPS=m
|
||||
CONFIG_QCOM_CLK_RPMH=m
|
||||
CONFIG_QCOM_LAZY_MAPPING=m
|
||||
CONFIG_MFD_SPMI_PMIC=m
|
||||
CONFIG_PWM_QTI_LPG=m
|
||||
CONFIG_INTERCONNECT_QCOM_EPSS_L3=m
|
||||
CONFIG_LEDS_QTI_FLASH=m
|
||||
CONFIG_LEDS_QTI_TRI_LED=m
|
||||
CONFIG_MSM_SPCOM=m
|
||||
CONFIG_MSM_ADSPRPC=m
|
||||
CONFIG_MSM_RDBG=m
|
||||
CONFIG_MSM_CDSP_LOADER=m
|
||||
CONFIG_UIO_MSM_SHAREDMEM=m
|
||||
CONFIG_QCOM_SOCINFO=m
|
||||
CONFIG_QCOM_PROXY_OF_CONSUMER=m
|
||||
CONFIG_BTFM_SLIM=m
|
||||
CONFIG_VIRT_DRIVERS=y
|
||||
CONFIG_HAVEN_DRIVERS=y
|
||||
CONFIG_HH_CTRL=m
|
||||
CONFIG_HH_MSGQ=m
|
||||
CONFIG_HH_RM_DRV=m
|
||||
CONFIG_HH_MEM_NOTIFIER=m
|
||||
CONFIG_HH_DBL=m
|
||||
CONFIG_HVC_HAVEN=m
|
||||
# CONFIG_HVC_HAVEN_CONSOLE is not set
|
||||
# CONFIG_SND_SOC_WCD9335 is not set
|
||||
# CONFIG_SLIM_QCOM_CTRL is not set
|
||||
# CONFIG_SLIM_QCOM_NGD_CTRL is not set
|
||||
# CONFIG_SLIMBUS_MSM_CTRL is not set
|
||||
# CONFIG_SLIMBUS_MSM_NGD is not set
|
||||
CONFIG_MSM_GENI_SE=m
|
||||
CONFIG_SERIAL_MSM_GENI=m
|
||||
CONFIG_SERIAL_MSM_GENI_HALF_SAMPLING=y
|
||||
CONFIG_I2C_MSM_GENI=m
|
||||
CONFIG_SPI_MSM_GENI=m
|
||||
# CONFIG_SERIAL_MSM is not set
|
||||
CONFIG_MSM_GPI_DMA=m
|
||||
CONFIG_MSM_GPI_DMA_DEBUG=y
|
||||
CONFIG_QSEECOM=m
|
||||
CONFIG_QCOM_SMCINVOKE=m
|
||||
CONFIG_HDCP_QSEECOM=m
|
||||
CONFIG_CRYPTO_DEV_QCOM_MSM_QCE=m
|
||||
CONFIG_CRYPTO_DEV_QCEDEV=m
|
||||
CONFIG_HW_RANDOM_MSM_LEGACY=m
|
||||
CONFIG_MHI_BUS=m
|
||||
CONFIG_MHI_UCI=m
|
||||
CONFIG_PCI_MSM=m
|
||||
CONFIG_EXTCON_USB_GPIO=m
|
||||
CONFIG_PM_WAKELOCKS=y
|
||||
CONFIG_MMC_SDHCI_MSM=m
|
||||
CONFIG_QCOM_KGSL=m
|
||||
CONFIG_QCOM_QFPROM=m
|
||||
CONFIG_DEVFREQ_GOV_QCOM_GPUBW_MON=m
|
||||
CONFIG_DEVFREQ_GOV_QCOM_ADRENO_TZ=m
|
||||
CONFIG_INTERCONNECT_TEST=m
|
||||
CONFIG_SCSI_UFS_CRYPTO_QTI=m
|
||||
CONFIG_QTI_CRYPTO_COMMON=m
|
||||
CONFIG_QTI_HW_KEY_MANAGER=m
|
||||
CONFIG_MMC_CQHCI_CRYPTO=m
|
||||
CONFIG_MMC_CQHCI_CRYPTO_QTI=m
|
||||
CONFIG_VIDEOBUF2_VMALLOC=m
|
||||
CONFIG_SLIMBUS_MSM_NGD=m
|
||||
CONFIG_QRTR_HAVEN=m
|
||||
CONFIG_QCOM_CDSP_RM=m
|
||||
CONFIG_QCOM_SYSMON_SUBSYSTEM_STATS=m
|
||||
CONFIG_QCOM_PDC=m
|
||||
CONFIG_HEADER_TEST=y
|
||||
CONFIG_HEADERS_INSTALL=y
|
||||
CONFIG_KERNEL_HEADER_TEST=y
|
||||
CONFIG_SPS=m
|
||||
CONFIG_SPS_SUPPORT_NDP_BAM=y
|
||||
# CONFIG_SPS_SUPPORT_BAMDMA is not set
|
||||
CONFIG_USB_BAM=m
|
||||
CONFIG_UTS_NS=y
|
||||
CONFIG_HH_IRQ_LEND=m
|
||||
CONFIG_SM_GCC_SHIMA=m
|
||||
CONFIG_NFC_QTI_I2C=m
|
||||
CONFIG_NETFILTER_XT_TARGET_DSCP=y
|
||||
CONFIG_USB_REDRIVER_NB7VPQ904M=m
|
||||
# CONFIG_UAPI_HEADER_TEST is not set
|
||||
CONFIG_SM_VIDEOCC_SHIMA=m
|
||||
CONFIG_SM_CAMCC_SHIMA=m
|
||||
CONFIG_SM_GPUCC_SHIMA=m
|
||||
CONFIG_INTERCONNECT_QCOM_SHIMA=m
|
||||
CONFIG_ARM_QCOM_CPUFREQ_HW=m
|
||||
CONFIG_SM_DISPCC_SHIMA=m
|
||||
CONFIG_NETFILTER_XT_MATCH_DSCP=y
|
||||
CONFIG_NETFILTER_XT_MATCH_MULTIPORT=y
|
||||
CONFIG_INCREMENTAL_FS=m
|
||||
CONFIG_QCOM_MICRODUMP=m
|
||||
CONFIG_HH_VIRT_WATCHDOG=m
|
||||
CONFIG_QCOM_SOC_WATCHDOG=m
|
||||
CONFIG_QPNP_PBS=m
|
||||
CONFIG_ARCH_YUPIK=y
|
||||
CONFIG_PINCTRL_YUPIK=m
|
||||
CONFIG_QCOM_QFPROM_SYS=m
|
||||
CONFIG_RELAY=y
|
||||
CONFIG_MSM_PERFORMANCE=m
|
||||
CONFIG_SM_GCC_YUPIK=m
|
||||
CONFIG_SM_GPUCC_YUPIK=m
|
||||
CONFIG_INTERCONNECT_QCOM_YUPIK=m
|
||||
CONFIG_SM_VIDEOCC_YUPIK=m
|
||||
CONFIG_SM_CAMCC_YUPIK=m
|
||||
CONFIG_QCOM_YUPIK_LLCC=m
|
||||
CONFIG_SM_DISPCC_YUPIK=m
|
||||
CONFIG_REGULATOR_QPNP_LCDB=m
|
||||
#CONFIG_LEDS_QPNP_VIBRATOR_LDO is not set
|
||||
CONFIG_LIRC=y
|
||||
CONFIG_RC_CORE=y
|
||||
CONFIG_RC_DECODERS=y
|
||||
CONFIG_RC_DEVICES=y
|
||||
CONFIG_IR_SPI=m
|
||||
CONFIG_GPIO_TESTING_MODE=y
|
||||
CONFIG_PINCTRL_SM7325=y
|
||||
CONFIG_MI_HARDWARE_ID=m
|
||||
CONFIG_TOUCHSCREEN_XIAOMI_TOUCHFEATURE=m
|
||||
CONFIG_BQ2597X=y
|
||||
CONFIG_USB_K9=y
|
||||
CONFIG_INPUT_FINGERPRINT=y
|
||||
CONFIG_FINGERPRINT_GOODIX_FOD=m
|
||||
CONFIG_TOUCHSCREEN_GOODIX_BRL_9916=m
|
||||
CONFIG_TOUCHSCREEN_FOCALTECH_3680=m
|
||||
# CONFIG_HAPTIC_NV_L is not set
|
||||
|
||||
344
arch/arm64/configs/vendor/taoyao_QGKI.config
vendored
Normal file
344
arch/arm64/configs/vendor/taoyao_QGKI.config
vendored
Normal file
@@ -0,0 +1,344 @@
|
||||
CONFIG_LOCALVERSION="-qgki"
|
||||
CONFIG_CNSS2=m
|
||||
CONFIG_ICNSS2=m
|
||||
# CONFIG_TRIM_UNUSED_KSYMS is not set
|
||||
CONFIG_CMA_DEBUGFS=y
|
||||
CONFIG_QCOM_IOMMU_IO_PGTABLE_QUIRKS=y
|
||||
CONFIG_QCOM_IOMMU_TLBI_QUIRKS=y
|
||||
CONFIG_QCOM_IOMMU_TLBI_QUIRKS=y
|
||||
CONFIG_QCOM_LAZY_MAPPING=y
|
||||
CONFIG_QCOM_SECURE_BUFFER=y
|
||||
CONFIG_DMABUF_DESTRUCTOR_SUPPORT=y
|
||||
# CONFIG_ZONE_DMA32 is not set
|
||||
CONFIG_EDAC_KRYO_ARM64=y
|
||||
CONFIG_EDAC_KRYO_ARM64_PANIC_ON_UE=y
|
||||
CONFIG_SPARSEMEM_VMEMMAP=y
|
||||
CONFIG_STM_PROTO_BASIC=y
|
||||
CONFIG_ION_MSM_HEAPS=y
|
||||
CONFIG_IOMMU_IO_PGTABLE_FAST=y
|
||||
CONFIG_IOMMU_DYNAMIC_DOMAINS=y
|
||||
# CONFIG_ARM_SMMU_SKIP_MAP_POWER_ON=y
|
||||
# CONFIG_IOMMU_IO_PGTABLE_FAST_SELFTEST is not set
|
||||
# CONFIG_IOMMU_IO_PGTABLE_FAST_PROVE_TLB is not set
|
||||
# CONFIG_SOFTLOCKUP_DETECTOR is not set
|
||||
# CONFIG_DETECT_HUNG_TASK is not set
|
||||
CONFIG_RCU_EXPERT=y
|
||||
CONFIG_RCU_FAST_NO_HZ=y
|
||||
CONFIG_RCU_NOCB_CPU=y
|
||||
CONFIG_QCOM_LLCC_PERFMON=m
|
||||
CONFIG_SCHED_WALT=y
|
||||
CONFIG_PERF_HUMANTASK=y
|
||||
CONFIG_TASK_DELAY_ACCT=y
|
||||
CONFIG_QCOM_HYP_CORE_CTL=y
|
||||
CONFIG_QGKI=y
|
||||
CONFIG_I2C_CHARDEV=y
|
||||
CONFIG_SPI_SPIDEV=y
|
||||
CONFIG_REGULATOR_QTI_DEBUG=y
|
||||
CONFIG_REGMAP_QTI_DEBUG=y
|
||||
CONFIG_IPC_LOGGING=y
|
||||
CONFIG_IPC_LOG_MINIDUMP_BUFFERS=16
|
||||
CONFIG_REGMAP_ALLOW_WRITE_DEBUGFS=y
|
||||
CONFIG_DYNAMIC_DEBUG=y
|
||||
CONFIG_VM_EVENT_COUNTERS=y
|
||||
CONFIG_QCOM_SHOW_RESUME_IRQ=y
|
||||
CONFIG_QCOM_SOC_SLEEP_STATS=y
|
||||
CONFIG_QCOM_RUN_QUEUE_STATS=y
|
||||
CONFIG_QTI_RPM_STATS_LOG=y
|
||||
CONFIG_QTI_DDR_STATS_LOG=y
|
||||
CONFIG_ARM_QCOM_LPM_CPUIDLE=y
|
||||
# CONFIG_ARM_CPUIDLE is not set
|
||||
# CONFIG_ARM_PSCI_CPUIDLE is not set
|
||||
CONFIG_MSM_GLOBAL_SYNX=y
|
||||
CONFIG_MSM_CVP=y
|
||||
CONFIG_ION_POOL_AUTO_REFILL=y
|
||||
CONFIG_QCOM_MINIDUMP=y
|
||||
CONFIG_QCOM_MEM_BUF=y
|
||||
CONFIG_VM_EVENT_COUNT_CLEAN_PAGE_RECLAIM=y
|
||||
CONFIG_BALANCE_ANON_FILE_RECLAIM=y
|
||||
CONFIG_DMA_COHERENT_HINT_CACHED=y
|
||||
CONFIG_PRIORITIZE_OOM_TASKS=y
|
||||
CONFIG_DMA_CONFIGURE_ALIGNMENT=y
|
||||
CONFIG_LIMIT_MOVABLE_ZONE_ALLOC=y
|
||||
# CONFIG_ZONE_DEVICE is not set
|
||||
# CONFIG_BUG_ON_HW_MEM_ONLINE_FAIL is not set
|
||||
CONFIG_MSM_BT_POWER=m
|
||||
CONFIG_I2C_RTC6226_QCA=m
|
||||
CONFIG_MI_UFS_FFU=y
|
||||
CONFIG_SCSI_UFSHCD_QTI=y
|
||||
# CONFIG_UFS_DBG is not set
|
||||
CONFIG_SCSI_UFS_BSG=y
|
||||
CONFIG_MSM_EXT_DISPLAY=y
|
||||
CONFIG_SCSI_UFSHCD=y
|
||||
CONFIG_DRM_LONTIUM_LT9611UXC=y
|
||||
# CONFIG_RADIO_SI470X is not set
|
||||
# CONFIG_RADIO_SI4713 is not set
|
||||
# CONFIG_USB_MR800 is not set
|
||||
# CONFIG_USB_DSBR is not set
|
||||
# CONFIG_RADIO_MAXIRADIO is not set
|
||||
# CONFIG_RADIO_SHARK is not set
|
||||
# CONFIG_RADIO_SHARK2 is not set
|
||||
# CONFIG_USB_KEENE is not set
|
||||
# CONFIG_USB_RAREMONO is not set
|
||||
# CONFIG_USB_MA901 is not set
|
||||
# CONFIG_RADIO_TEA5764 is not set
|
||||
# CONFIG_RADIO_SAA7706H is not set
|
||||
# CONFIG_RADIO_TEF6862 is not set
|
||||
# CONFIG_RADIO_WL1273 is not set
|
||||
CONFIG_QCOM_BIMC_BWMON=y
|
||||
CONFIG_ARM_MEMLAT_MON=y
|
||||
CONFIG_DEVFREQ_GOV_QCOM_BW_HWMON=y
|
||||
CONFIG_DEVFREQ_GOV_MEMLAT=y
|
||||
CONFIG_DEVFREQ_SIMPLE_DEV=y
|
||||
CONFIG_EDAC_QCOM=y
|
||||
CONFIG_EDAC_QGKI=y
|
||||
CONFIG_EDAC_QCOM_LLCC_PANIC_ON_UE=y
|
||||
CONFIG_MSM_BOOT_STATS=y
|
||||
CONFIG_QCOM_DEVFREQ_ICC=y
|
||||
CONFIG_ARM_QCOM_DEVFREQ_QOSLAT=y
|
||||
CONFIG_QCOM_LLCC_PMU=y
|
||||
CONFIG_QCOM_GUESTVM=y
|
||||
CONFIG_QTI_TZ_LOG=y
|
||||
CONFIG_MSM_REMOTEQDSS=y
|
||||
CONFIG_QCOM_DCC_V2=y
|
||||
CONFIG_CLD_LL_CORE=y
|
||||
CONFIG_CORESIGHT_QGKI=y
|
||||
CONFIG_CORESIGHT_LINK_AND_SINK_TMC=y
|
||||
CONFIG_CORESIGHT_CTI=y
|
||||
CONFIG_CORESIGHT_CTI_SAVE_DISABLE=y
|
||||
CONFIG_CORESIGHT_TPDA=y
|
||||
CONFIG_CORESIGHT_TPDM=y
|
||||
CONFIG_CORESIGHT_HWEVENT=y
|
||||
CONFIG_CORESIGHT_DUMMY=y
|
||||
CONFIG_CORESIGHT_REMOTE_ETM=y
|
||||
CONFIG_CORESIGHT_TGU=y
|
||||
CONFIG_AUDIO_QGKI=y
|
||||
CONFIG_QCOM_FSA4480_I2C=y
|
||||
# CONFIG_CORESIGHT_CATU is not set
|
||||
# CONFIG_CORESIGHT_TPDM_DEFAULT_ENABLE is not set
|
||||
CONFIG_BTFM_SLIM=m
|
||||
# CONFIG_SND_SOC_WCD9335 is not set
|
||||
# CONFIG_SLIM_QCOM_CTRL is not set
|
||||
# CONFIG_SLIM_QCOM_NGD_CTRL is not set
|
||||
# CONFIG_SLIMBUS_MSM_CTRL is not set
|
||||
# CONFIG_SLIMBUS_MSM_NGD is not set
|
||||
CONFIG_QTI_THERMAL=y
|
||||
CONFIG_THERMAL_WRITABLE_TRIPS=y
|
||||
CONFIG_QTI_QMI_SENSOR=y
|
||||
CONFIG_QTI_BCL_PMIC5=y
|
||||
CONFIG_QTI_BCL_SOC_DRIVER=y
|
||||
CONFIG_MSM_PERFORMANCE=y
|
||||
CONFIG_QTI_SCMI_PLH_PROTOCOL=y
|
||||
CONFIG_QTI_PLH=y
|
||||
CONFIG_QTI_PLH_SCMI_CLIENT=y
|
||||
CONFIG_MSM_PERFORMANCE_QGKI=y
|
||||
CONFIG_QTI_QMI_COOLING_DEVICE=y
|
||||
CONFIG_QTI_ADC_TM=y
|
||||
CONFIG_QTI_CPU_ISOLATE_COOLING_DEVICE=y
|
||||
CONFIG_QTI_CPU_HOTPLUG_COOLING_DEVICE=y
|
||||
CONFIG_QTI_THERMAL_LIMITS_DCVS=y
|
||||
CONFIG_QTI_CPU_VOLTAGE_COOLING_DEVICE=y
|
||||
CONFIG_QTI_POLICY_ENGINE_SENSOR=y
|
||||
CONFIG_QTI_SDPM_CLOCK_MONITOR=y
|
||||
CONFIG_THERMAL_EMERGENCY_POWEROFF_DELAY_MS=10000
|
||||
CONFIG_QTI_DDR_COOLING_DEVICE=y
|
||||
CONFIG_SPS=y
|
||||
# CONFIG_SPS_SUPPORT_BAMDMA is not set
|
||||
CONFIG_SPS_SUPPORT_NDP_BAM=y
|
||||
CONFIG_CPU_FREQ_DEFAULT_GOV_PERFORMANCE=y
|
||||
CONFIG_CRYPTO_DEV_QCRYPTO=y
|
||||
CONFIG_THERMAL_TSENS=y
|
||||
CONFIG_CPU_FREQ_GOV_SCHEDUTIL=y
|
||||
CONFIG_HAVE_USERSPACE_LOW_MEMORY_KILLER=y
|
||||
CONFIG_I2C_MSM_GENI=y
|
||||
CONFIG_MSM_GENI_SE=y
|
||||
CONFIG_SERIAL_MSM_GENI=y
|
||||
CONFIG_SERIAL_MSM_GENI_HALF_SAMPLING=y
|
||||
CONFIG_FASTBOOT_CMD_CTRL_UART=y
|
||||
CONFIG_HH_DISABLE_UART=y
|
||||
CONFIG_QTI_BATTERY_CHARGER_ODIN=m
|
||||
CONFIG_SPI_MSM_GENI=y
|
||||
CONFIG_MSM_DEBUGCC_LAHAINA=y
|
||||
# CONFIG_SERIAL_DEV_BUS is not set
|
||||
CONFIG_MSM_GPI_DMA=y
|
||||
CONFIG_SERIAL_MSM_GENI_CONSOLE=y
|
||||
CONFIG_MSM_GPI_DMA_DEBUG=y
|
||||
# CONFIG_I3C is not set
|
||||
# CONFIG_I3C_MASTER_MSM_GENI is not set
|
||||
# CONFIG_NFC_QTI_I3C is not set
|
||||
# CONFIG_CDNS_I3C_MASTER is not set
|
||||
# CONFIG_DW_I3C_MASTER is not set
|
||||
CONFIG_SLIMBUS=m
|
||||
CONFIG_SLIMBUS_MSM_NGD=m
|
||||
CONFIG_SLIMBUS_MSM_NGD=y
|
||||
CONFIG_QCOM_KGSL=y
|
||||
CONFIG_QCOM_QFPROM=y
|
||||
CONFIG_ARM_QCOM_CPUFREQ_HW=y
|
||||
CONFIG_NETFILTER_XT_TARGET_TEE=y
|
||||
CONFIG_NETFILTER_XT_TARGET_NOTRACK=y
|
||||
CONFIG_NETFILTER_XT_MATCH_ESP=y
|
||||
CONFIG_NETFILTER_XT_MATCH_CONNBYTES=y
|
||||
CONFIG_NETFILTER_XT_MATCH_MULTIPORT=y
|
||||
CONFIG_NET_SCH_PRIO=y
|
||||
CONFIG_NET_CLS_FW=y
|
||||
CONFIG_MMC_SDHCI_MSM=y
|
||||
CONFIG_DUMMY=y
|
||||
CONFIG_IOSCHED_BFQ=y
|
||||
CONFIG_BFQ_GROUP_IOSCHED=y
|
||||
CONFIG_HID_QVR=y
|
||||
CONFIG_NEURON_SERVICE=y
|
||||
CONFIG_NEURON_CH_HAVEN=y
|
||||
CONFIG_NEURON_APP_BLOCK_SERVER=y
|
||||
CONFIG_ADSPRPC_QGKI=y
|
||||
CONFIG_MSM_RDBG=m
|
||||
CONFIG_COMMON_CLK_QCOM_DEBUG=y
|
||||
CONFIG_QMP_DEBUGFS_CLIENT=y
|
||||
CONFIG_SDC_QTI=y
|
||||
CONFIG_BRIDGE_NF_EBTABLES=y
|
||||
CONFIG_BRIDGE_EBT_BROUTE=y
|
||||
CONFIG_BRIDGE=y
|
||||
CONFIG_PCI_QTI=y
|
||||
CONFIG_CFG80211_INTERNAL_REGDB=y
|
||||
CONFIG_IRQ_TIME_ACCOUNTING=y
|
||||
CONFIG_NET_IPIP=y
|
||||
CONFIG_NET_IPGRE=y
|
||||
CONFIG_IPV6_GRE=y
|
||||
CONFIG_VETH=y
|
||||
CONFIG_HID_BATTERY_STRENGTH=y
|
||||
CONFIG_MMC_CQHCI=y
|
||||
CONFIG_STATIC_USERMODEHELPER=y
|
||||
CONFIG_UTS_NS=y
|
||||
CONFIG_CFG80211_CRDA_SUPPORT=y
|
||||
CONFIG_RTC_SYSTOHC=y
|
||||
# CONFIG_NET_IPGRE_BROADCAST is not set
|
||||
CONFIG_BLK_DEV_LOOP_MIN_COUNT=16
|
||||
CONFIG_BLK_WBT=y
|
||||
CONFIG_BLK_WBT_SQ=y
|
||||
CONFIG_HID_PRODIKEYS=y
|
||||
CONFIG_HID_UCLOGIC=y
|
||||
CONFIG_HID_LOGITECH=y
|
||||
CONFIG_HID_LOGITECH_DJ=y
|
||||
CONFIG_HID_PICOLCD=y
|
||||
CONFIG_HID_ROCCAT=y
|
||||
CONFIG_HID_WACOM=y
|
||||
CONFIG_HID_WIIMOTE=y
|
||||
CONFIG_USB_DUMMY_HCD=y
|
||||
CONFIG_USB_CONFIGFS_ACM=y
|
||||
CONFIG_USB_F_DTP=m
|
||||
# CONFIG_USB_CONFIGFS_RNDIS is not set
|
||||
CONFIG_USB_CONFIGFS_F_HID=y
|
||||
CONFIG_EXT4_FS_POSIX_ACL=y
|
||||
CONFIG_EROFS_FS=y
|
||||
# CONFIG_SERIAL_MSM_GENI_EARLY_CONSOLE is not set
|
||||
CONFIG_SM_DEBUGCC_SHIMA=y
|
||||
CONFIG_QTI_SYS_PM_VX=y
|
||||
CONFIG_IOMMU_TLBSYNC_DEBUG=y
|
||||
CONFIG_STACK_HASH_ORDER_SHIFT=12
|
||||
CONFIG_PAGE_OWNER=y
|
||||
CONFIG_BQ2597X=y
|
||||
# CONFIG_DEBUG_DMA_BUF_REF is not set
|
||||
# CONFIG_PAGE_OWNER_ENABLE_DEFAULT is not set
|
||||
# CONFIG_PAGE_EXTENSION_PAGE_FREE is not set
|
||||
CONFIG_PERF_KERNEL_SHARE=y
|
||||
# CONFIG_PERF_USER_SHARE is not set
|
||||
CONFIG_MEDIA_RADIO_SUPPORT=y
|
||||
# CONFIG_RADIO_SI470X is not set
|
||||
# CONFIG_RADIO_SI4713 is not set
|
||||
# CONFIG_USB_MR800 is not set
|
||||
# CONFIG_USB_DSBR is not set
|
||||
# CONFIG_RADIO_MAXIRADIO is not set
|
||||
# CONFIG_RADIO_SHARK is not set
|
||||
# CONFIG_RADIO_SHARK2 is not set
|
||||
# CONFIG_USB_KEENE is not set
|
||||
# CONFIG_USB_RAREMONO is not set
|
||||
# CONFIG_USB_MA901 is not set
|
||||
# CONFIG_RADIO_TEA5764 is not set
|
||||
# CONFIG_RADIO_SAA7706H is not set
|
||||
# CONFIG_RADIO_TEF6862 is not set
|
||||
# CONFIG_RADIO_WL1273 is not set
|
||||
CONFIG_INTERCONNECT_TEST=y
|
||||
# CONFIG_BT_HCIUART is not set
|
||||
CONFIG_QCOM_QFPROM_SYSFS=y
|
||||
# CONFIG_NVMEM_SYSFS is not set
|
||||
CONFIG_ARM_QCOM_CPUFREQ_HW_DEBUG=y
|
||||
CONFIG_PSTORE=y
|
||||
CONFIG_PSTORE_RAM=y
|
||||
CONFIG_PSTORE_CONSOLE=y
|
||||
CONFIG_PSTORE_PMSG=y
|
||||
CONFIG_USB_LAN78XX=y
|
||||
CONFIG_USB_K9=y
|
||||
CONFIG_SYN_COOKIES=y
|
||||
CONFIG_QTI_SCMI_MEMLAT_PROTOCOL=y
|
||||
CONFIG_QCOM_RIMPS=y
|
||||
CONFIG_QTI_HW_MEMLAT=y
|
||||
CONFIG_QTI_HW_MEMLAT_SCMI_CLIENT=y
|
||||
CONFIG_QTI_HW_MEMLAT_LOG=y
|
||||
CONFIG_SRAM=y
|
||||
CONFIG_CRYPTO_SHA1_ARM64_CE=y
|
||||
ONFIG_MAX31760_FAN_CONTROLLER=y
|
||||
CONFIG_I2C_GPIO=y
|
||||
CONFIG_HID_AKSYS_QRD=m
|
||||
CONFIG_AKSYS_QRD_FF=y
|
||||
CONFIG_PCIEAER=y
|
||||
CONFIG_PCIEASPM_POWER_SUPERSAVE=y
|
||||
CONFIG_PRINT_SUSPEND_EPOCH_QGKI=y
|
||||
CONFIG_SM_DEBUGCC_YUPIK=y
|
||||
CONFIG_CMDLINE="ramoops_memreserve=4M"
|
||||
CONFIG_CMDLINE_EXTEND=y
|
||||
CONFIG_LIRC=y
|
||||
CONFIG_RC_CORE=y
|
||||
CONFIG_RC_DECODERS=y
|
||||
CONFIG_RC_DEVICES=y
|
||||
CONFIG_IR_SPI=m
|
||||
CONFIG_INPUT_JOYSTICK=y
|
||||
CONFIG_JOYSTICK_XPAD=y
|
||||
CONFIG_JOYSTICK_XPAD_FF=y
|
||||
CONFIG_JOYSTICK_XPAD_LEDS=y
|
||||
CONFIG_MI_HARDWARE_ID=m
|
||||
CONFIG_TOUCHSCREEN_XIAOMI_TOUCHFEATURE=m
|
||||
CONFIG_BQ_FUEL_GAUGE=y
|
||||
CONFIG_BQ_FG_1S=y
|
||||
CONFIG_TOUCHSCREEN_QGKI_GOODIX=y
|
||||
CONFIG_QCOM_RTB_QGKI=y
|
||||
CONFIG_QCOM_RTB=y
|
||||
CONFIG_QCOM_RTB_SEPARATE_CPUS=y
|
||||
CONFIG_QGKI_SYSTEM=y
|
||||
CONFIG_DEBUG_POLICY_STATUS=y
|
||||
CONFIG_STATIC_USERMODEHELPER_PATH="/system/bin/micd"
|
||||
CONFIG_LOG_BUF_SHIFT=21
|
||||
CONFIG_MTD=y
|
||||
CONFIG_MTD_BLOCK=y
|
||||
CONFIG_MTD_BLOCK2MTD=y
|
||||
CONFIG_MTD_OOPS=y
|
||||
# CONFIG_MI_RECLAIM is not set
|
||||
CONFIG_GPIO_TESTING_MODE=y
|
||||
CONFIG_PINCTRL_SM7325=y
|
||||
CONFIG_RTMM=y
|
||||
CONFIG_PROCESS_RECLAIM=y
|
||||
#CONFIG_TOUCHSCREEN_FOCALTECH_3658U=m
|
||||
CONFIG_F2FS_CP_OPT=y
|
||||
CONFIG_NFC_QTI_I2C=m
|
||||
CONFIG_LEDS_QTI_FLASH=m
|
||||
# CONFIG_MIUS_PROXIMITY is not set
|
||||
CONFIG_TOUCHSCREEN_SYNAPTICS_TCM_S3908P_L9=m
|
||||
CONFIG_TOUCHSCREEN_SYNAPTICS_TCM_SPI=m
|
||||
CONFIG_TOUCHSCREEN_SYNAPTICS_TCM_CORE=m
|
||||
CONFIG_TOUCHSCREEN_SYNAPTICS_TCM_REFLASH=m
|
||||
CONFIG_TOUCHSCREEN_SYNAPTICS_TCM_DEVICE=m
|
||||
CONFIG_TOUCHSCREEN_SYNAPTICS_TCM_TESTING=m
|
||||
CONFIG_TOUCHSCREEN_SYNAPTICS_TCM_DIAGNOSTIC=m
|
||||
CONFIG_INPUT_FINGERPRINT=y
|
||||
CONFIG_FINGERPRINT_GOODIX_FOD=m
|
||||
CONFIG_MI_THERMAL_INTERFACE=m
|
||||
CONFIG_TLB_CONF_HANDLER=y
|
||||
CONFIG_TOUCHSCREEN_GOODIX_BRL_9916=m
|
||||
CONFIG_PASSTHROUGH_SYSTEM=y
|
||||
CONFIG_TOUCHSCREEN_FOCALTECH_3680=m
|
||||
CONFIG_ZRAM=y
|
||||
CONFIG_MIUI_ZRAM_MEMORY_TRACKING=y
|
||||
CONFIG_ZRAM_WRITEBACK=y
|
||||
# CONFIG_SLUB_DEBUG is not set
|
||||
# CONFIG_PANIC_ON_OOPS is not set
|
||||
CONFIG_CRYPTO_CHACHA20POLY1305=y
|
||||
CONFIG_CRYPTO_XCBC=y
|
||||
CONFIG_PERF_CRITICAL_RT_TASK=y
|
||||
CONFIG_SF_BINDER=y
|
||||
@@ -853,13 +853,14 @@ static DEFINE_RAW_SPINLOCK(stop_lock);
|
||||
|
||||
static DEFINE_PER_CPU(struct pt_regs, regs_before_stop);
|
||||
|
||||
int in_long_press = 0;
|
||||
static void local_cpu_stop(void)
|
||||
{
|
||||
unsigned int cpu = smp_processor_id();
|
||||
struct pt_regs *regs = get_irq_regs();
|
||||
|
||||
if (system_state == SYSTEM_BOOTING ||
|
||||
system_state == SYSTEM_RUNNING) {
|
||||
if ((system_state == SYSTEM_BOOTING ||
|
||||
system_state == SYSTEM_RUNNING) && (!in_long_press)) {
|
||||
per_cpu(regs_before_stop, cpu) = *regs;
|
||||
raw_spin_lock(&stop_lock);
|
||||
pr_crit("CPU%u: stopping\n", cpu);
|
||||
|
||||
@@ -918,11 +918,34 @@ bool blk_rq_merge_ok(struct request *rq, struct bio *bio)
|
||||
|
||||
enum elv_merge blk_try_merge(struct request *rq, struct bio *bio)
|
||||
{
|
||||
enum elv_merge where;
|
||||
|
||||
#ifdef CONFIG_PERF_HUMANTASK
|
||||
if (bio->human_task) {
|
||||
if (blk_discard_mergable(rq))
|
||||
where = ELEVATOR_DISCARD_MERGE;
|
||||
else if (blk_rq_pos(rq) - bio_sectors(bio) == bio->bi_iter.bi_sector)
|
||||
where = ELEVATOR_FRONT_MERGE;
|
||||
else if (blk_rq_pos(rq) + blk_rq_sectors(rq) == bio->bi_iter.bi_sector)
|
||||
where = ELEVATOR_BACK_MERGE;
|
||||
else
|
||||
where = ELEVATOR_NO_MERGE;
|
||||
if (where && where != ELEVATOR_DISCARD_MERGE) {
|
||||
rq->ioprio = 0 ;
|
||||
bio->bi_ioprio = 0;
|
||||
}
|
||||
return where;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (blk_discard_mergable(rq))
|
||||
return ELEVATOR_DISCARD_MERGE;
|
||||
where = ELEVATOR_DISCARD_MERGE;
|
||||
else if (blk_rq_pos(rq) + blk_rq_sectors(rq) == bio->bi_iter.bi_sector)
|
||||
return ELEVATOR_BACK_MERGE;
|
||||
where = ELEVATOR_BACK_MERGE;
|
||||
else if (blk_rq_pos(rq) - bio_sectors(bio) == bio->bi_iter.bi_sector)
|
||||
return ELEVATOR_FRONT_MERGE;
|
||||
return ELEVATOR_NO_MERGE;
|
||||
where = ELEVATOR_FRONT_MERGE;
|
||||
|
||||
where = ELEVATOR_NO_MERGE;
|
||||
|
||||
return where;
|
||||
}
|
||||
|
||||
@@ -230,4 +230,6 @@ source "drivers/interconnect/Kconfig"
|
||||
|
||||
source "drivers/counter/Kconfig"
|
||||
|
||||
source "drivers/uwb-sr100/Kconfig"
|
||||
|
||||
endmenu
|
||||
|
||||
@@ -186,3 +186,5 @@ obj-$(CONFIG_SIOX) += siox/
|
||||
obj-$(CONFIG_GNSS) += gnss/
|
||||
obj-$(CONFIG_INTERCONNECT) += interconnect/
|
||||
obj-$(CONFIG_COUNTER) += counter/
|
||||
obj-$(CONFIG_NXP_SR100) += uwb-sr100/
|
||||
obj-y += fragmention/
|
||||
|
||||
@@ -700,12 +700,24 @@ static void binder_do_set_priority(struct binder_thread *thread,
|
||||
if (verify && is_rt_policy(policy) && !has_cap_nice) {
|
||||
long max_rtprio = task_rlimit(task, RLIMIT_RTPRIO);
|
||||
|
||||
#ifdef CONFIG_PERF_CRITICAL_RT_TASK
|
||||
unsigned int critical_rt_task = task->group_leader->critical_rt_task;
|
||||
if (!critical_rt_task) {
|
||||
if (max_rtprio == 0) {
|
||||
policy = SCHED_NORMAL;
|
||||
priority = MIN_NICE;
|
||||
} else if (priority > max_rtprio) {
|
||||
priority = max_rtprio;
|
||||
}
|
||||
}
|
||||
#else
|
||||
if (max_rtprio == 0) {
|
||||
policy = SCHED_NORMAL;
|
||||
priority = MIN_NICE;
|
||||
} else if (priority > max_rtprio) {
|
||||
priority = max_rtprio;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
if (verify && is_fair_policy(policy) && !has_cap_nice) {
|
||||
@@ -2891,6 +2903,9 @@ static int binder_proc_transaction(struct binder_transaction *t,
|
||||
bool oneway = !!(t->flags & TF_ONE_WAY);
|
||||
bool pending_async = false;
|
||||
struct binder_transaction *t_outdated = NULL;
|
||||
#ifdef CONFIG_PERF_HUMANTASK
|
||||
int task_pri = 0;
|
||||
#endif
|
||||
|
||||
BUG_ON(!node);
|
||||
binder_node_lock(node);
|
||||
@@ -2921,6 +2936,17 @@ static int binder_proc_transaction(struct binder_transaction *t,
|
||||
thread = binder_select_thread_ilocked(proc);
|
||||
|
||||
if (thread) {
|
||||
#ifdef CONFIG_PERF_HUMANTASK
|
||||
if (t->from && t->from->task) {
|
||||
task_pri = t->from->task->human_task;
|
||||
}
|
||||
if (!oneway && task_pri && task_pri <=4 ) {
|
||||
if (thread->task && !t->from->task->inherit_task) {
|
||||
thread->task->human_task++;
|
||||
thread->task->inherit_task = 1;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
binder_transaction_priority(thread, t, node);
|
||||
binder_enqueue_thread_work_ilocked(thread, &t->work);
|
||||
} else if (!pending_async) {
|
||||
@@ -3694,6 +3720,12 @@ static void binder_transaction(struct binder_proc *proc,
|
||||
trace_android_vh_binder_restore_priority(in_reply_to, current);
|
||||
binder_restore_priority(thread, &in_reply_to->saved_priority);
|
||||
binder_free_transaction(in_reply_to);
|
||||
#ifdef CONFIG_PERF_HUMANTASK
|
||||
if (thread->task && thread->task->inherit_task) {
|
||||
thread->task->inherit_task = 0 ;
|
||||
thread->task->human_task = 0;
|
||||
}
|
||||
#endif
|
||||
} else if (!(t->flags & TF_ONE_WAY)) {
|
||||
BUG_ON(t->buffer->async_transaction != 0);
|
||||
binder_inner_proc_lock(proc);
|
||||
@@ -4639,6 +4671,9 @@ static int binder_thread_read(struct binder_proc *proc,
|
||||
int ret = 0;
|
||||
int wait_for_proc_work;
|
||||
|
||||
#ifdef CONFIG_SF_BINDER
|
||||
unsigned int flag = current->group_leader->sf_binder_task;
|
||||
#endif
|
||||
if (*consumed == 0) {
|
||||
if (put_user(BR_NOOP, (uint32_t __user *)ptr))
|
||||
return -EFAULT;
|
||||
@@ -4664,6 +4699,12 @@ retry:
|
||||
binder_stop_on_user_error < 2);
|
||||
}
|
||||
trace_android_vh_binder_restore_priority(NULL, current);
|
||||
#ifdef CONFIG_SF_BINDER
|
||||
if (flag) {
|
||||
proc->default_priority.sched_policy = current->policy;
|
||||
proc->default_priority.prio = current->normal_prio;
|
||||
}
|
||||
#endif
|
||||
binder_restore_priority(thread, &proc->default_priority);
|
||||
}
|
||||
|
||||
@@ -5983,6 +6024,17 @@ static int binder_open(struct inode *nodp, struct file *filp)
|
||||
proc->default_priority.prio = NICE_TO_PRIO(0);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_PERF_CRITICAL_RT_TASK
|
||||
if ((strncmp(proc->tsk->comm, "com.miui.home", strlen("com.miui.home")) == 0) ||
|
||||
(strncmp(proc->tsk->comm, "ndroid.systemui", strlen("ndroid.systemui")) == 0)) {
|
||||
proc->tsk->critical_rt_task = 1;
|
||||
}
|
||||
#endif
|
||||
#ifdef CONFIG_SF_BINDER
|
||||
if (strncmp(proc->tsk->comm,"surfaceflinger",strlen("surfaceflinger")) == 0) {
|
||||
proc->tsk->sf_binder_task = 1;
|
||||
}
|
||||
#endif
|
||||
/* binderfs stashes devices in i_private */
|
||||
if (is_binderfs_device(nodp)) {
|
||||
binder_dev = nodp->i_private;
|
||||
|
||||
@@ -648,4 +648,9 @@ config RANDOM_TRUST_BOOTLOADER
|
||||
believe its RNG facilities may be faulty. This may also be configured
|
||||
at boot time with "random.trust_bootloader=on/off".
|
||||
|
||||
config XLOGCHAR
|
||||
tristate "xlogchar driver"
|
||||
help
|
||||
Implements a high performance log driver
|
||||
|
||||
endmenu
|
||||
|
||||
@@ -68,3 +68,4 @@ obj-$(CONFIG_ADI) += adi.o
|
||||
obj-$(CONFIG_MSM_RDBG) += rdbg.o
|
||||
obj-$(CONFIG_MSM_FASTCVPD) += fastcvpd.o
|
||||
obj-$(CONFIG_VIRTIO_EAVB) += virtio_eavb/
|
||||
obj-$(CONFIG_XLOGCHAR) += xlogchar.o
|
||||
|
||||
265
drivers/char/xlogchar.c
Normal file
265
drivers/char/xlogchar.c
Normal file
@@ -0,0 +1,265 @@
|
||||
/* Copyright (C) 2018 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 <linux/slab.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/cdev.h>
|
||||
#include <linux/fs.h>
|
||||
#include <linux/device.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/uaccess.h>
|
||||
#include <linux/sched.h>
|
||||
#include <linux/ratelimit.h>
|
||||
#include <asm/current.h>
|
||||
#include <asm/div64.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/atomic.h>
|
||||
#include <linux/poll.h>
|
||||
#include "xlogchar.h"
|
||||
#include <linux/string.h>
|
||||
|
||||
static struct xlogchar_dev *xlogdriver;
|
||||
|
||||
static int xlogchar_open(struct inode *inode, struct file *file)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int xlogchar_close(struct inode *inode, struct file *file)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static ssize_t xlogchar_read(struct file *file, char __user *buf,
|
||||
size_t count, loff_t *ppos)
|
||||
{
|
||||
u64 temp = count;
|
||||
int err;
|
||||
size_t copy_bytes;
|
||||
if (do_div(temp, XLOGPKG_SIZE) || (count > XLOGBUF_SIZE)) {
|
||||
pr_err("xlog: invalide count %zu\n", count);
|
||||
return -EBADMSG;
|
||||
}
|
||||
if (!buf) {
|
||||
pr_err("xlog: bad address from user side\n");
|
||||
return -EFAULT;
|
||||
}
|
||||
mutex_lock(&xlogdriver->xlog_mutex);
|
||||
while ((XLOGBUF_SIZE - xlogdriver->free_size) < count) {
|
||||
mutex_unlock(&xlogdriver->xlog_mutex);
|
||||
pr_info("%s goint to sleep\n", __func__);
|
||||
err = wait_event_interruptible(xlogdriver->wait_q, (XLOGBUF_SIZE - xlogdriver->free_size) >= count);
|
||||
if (err == -ERESTARTSYS) {
|
||||
return -ERESTARTSYS;
|
||||
}
|
||||
pr_info("%s wakeup \n", __func__);
|
||||
mutex_lock(&xlogdriver->xlog_mutex);
|
||||
}
|
||||
if (XLOGBUF_SIZE < xlogdriver->readindex + count) {
|
||||
copy_bytes = XLOGBUF_SIZE - xlogdriver->readindex;
|
||||
err = copy_to_user(buf, (void *)(xlogdriver->buf + xlogdriver->readindex), copy_bytes);
|
||||
err = copy_to_user(buf + copy_bytes, (void *)(xlogdriver->buf), count - copy_bytes);
|
||||
xlogdriver->readindex = count - copy_bytes;
|
||||
} else {
|
||||
err = copy_to_user(buf, (void *)(xlogdriver->buf + xlogdriver->readindex), count);
|
||||
xlogdriver->readindex += count;
|
||||
}
|
||||
xlogdriver->free_size += count;
|
||||
mutex_unlock(&xlogdriver->xlog_mutex);
|
||||
return count;
|
||||
}
|
||||
|
||||
|
||||
static ssize_t xlogchar_write(struct file *file, const char __user *buf,
|
||||
size_t count, loff_t *ppos)
|
||||
{
|
||||
int err = 0;
|
||||
size_t copy_bytes;
|
||||
u64 temp = count;
|
||||
pr_info("%s: count is %zu\n", __func__, count);
|
||||
if (do_div(temp, XLOGPKG_SIZE) || (count > XLOGBUF_SIZE)) {
|
||||
pr_err("xlog: invalide count %zu\n", count);
|
||||
return -EBADMSG;
|
||||
}
|
||||
mutex_lock(&xlogdriver->xlog_mutex);
|
||||
if (xlogdriver->free_size < count) {
|
||||
pr_err("xlog: no more space to write free: %zu, count %zu\n", xlogdriver->free_size, count);
|
||||
mutex_unlock(&xlogdriver->xlog_mutex);
|
||||
return -EIO;
|
||||
}
|
||||
if (XLOGBUF_SIZE < xlogdriver->writeindex + count) {
|
||||
copy_bytes = XLOGBUF_SIZE - xlogdriver->writeindex;
|
||||
err = copy_from_user(xlogdriver->buf + xlogdriver->writeindex, buf, copy_bytes);
|
||||
err = copy_from_user(xlogdriver->buf, buf + copy_bytes, count - copy_bytes);
|
||||
xlogdriver->writeindex = count - copy_bytes;
|
||||
} else {
|
||||
err = copy_from_user(xlogdriver->buf + xlogdriver->writeindex, buf, count);
|
||||
xlogdriver->writeindex += count;
|
||||
}
|
||||
xlogdriver->free_size -= count;
|
||||
mutex_unlock(&xlogdriver->xlog_mutex);
|
||||
pr_info("%s wakeup reader \n", __func__);
|
||||
wake_up_interruptible(&xlogdriver->wait_q);
|
||||
return count;
|
||||
}
|
||||
|
||||
ssize_t xlogchar_kwrite(const char *buf, size_t count)
|
||||
{
|
||||
size_t copy_bytes;
|
||||
u64 temp = count;
|
||||
pr_err("%s start\n", __func__);
|
||||
pr_info("%s: count is %zu\n", __func__, count);
|
||||
if (do_div(temp, XLOGPKG_SIZE) || (count > XLOGBUF_SIZE)) {
|
||||
pr_err("xlog: invalide count %zu\n", count);
|
||||
return -EBADMSG;
|
||||
}
|
||||
mutex_lock(&xlogdriver->xlog_mutex);
|
||||
if (xlogdriver->free_size < count) {
|
||||
pr_err("xlog: no more space to write free: %zu, count %zu\n", xlogdriver->free_size, count);
|
||||
mutex_unlock(&xlogdriver->xlog_mutex);
|
||||
return -EIO;
|
||||
}
|
||||
if (XLOGBUF_SIZE < xlogdriver->writeindex + count) {
|
||||
copy_bytes = XLOGBUF_SIZE - xlogdriver->writeindex;
|
||||
memcpy(xlogdriver->buf + xlogdriver->writeindex, buf, copy_bytes);
|
||||
memcpy(xlogdriver->buf, buf + copy_bytes, count - copy_bytes);
|
||||
xlogdriver->writeindex = count - copy_bytes;
|
||||
} else {
|
||||
memcpy(xlogdriver->buf + xlogdriver->writeindex, buf, count);
|
||||
xlogdriver->writeindex += count;
|
||||
}
|
||||
xlogdriver->free_size -= count;
|
||||
mutex_unlock(&xlogdriver->xlog_mutex);
|
||||
pr_info("%s wakeup reader \n", __func__);
|
||||
wake_up_interruptible(&xlogdriver->wait_q);
|
||||
return count;
|
||||
}
|
||||
|
||||
EXPORT_SYMBOL(xlogchar_kwrite);
|
||||
|
||||
static unsigned int xlogchar_poll(struct file *file, poll_table *wait)
|
||||
{
|
||||
int masks = 0;
|
||||
|
||||
return masks;
|
||||
}
|
||||
|
||||
|
||||
static const struct file_operations xlogcharfops = {
|
||||
.owner = THIS_MODULE,
|
||||
.read = xlogchar_read,
|
||||
.write = xlogchar_write,
|
||||
.poll = xlogchar_poll,
|
||||
.open = xlogchar_open,
|
||||
.release = xlogchar_close
|
||||
};
|
||||
|
||||
static int xlogchar_setup_cdev(dev_t devno)
|
||||
{
|
||||
|
||||
int err;
|
||||
|
||||
cdev_init(xlogdriver->cdev, &xlogcharfops);
|
||||
|
||||
xlogdriver->cdev->owner = THIS_MODULE;
|
||||
xlogdriver->cdev->ops = &xlogcharfops;
|
||||
|
||||
err = cdev_add(xlogdriver->cdev, devno, 1);
|
||||
|
||||
if (err) {
|
||||
pr_info("xlog cdev registration failed !\n");
|
||||
return err;
|
||||
}
|
||||
|
||||
xlogdriver->xlogchar_class = class_create(THIS_MODULE, "xlog");
|
||||
|
||||
if (IS_ERR(xlogdriver->xlogchar_class)) {
|
||||
pr_err("Error creating xlogchar class.\n");
|
||||
return PTR_ERR(xlogdriver->xlogchar_class);
|
||||
}
|
||||
|
||||
xlogdriver->xlog_dev = device_create(xlogdriver->xlogchar_class,
|
||||
NULL, devno, (void *)xlogdriver, "xlog");
|
||||
|
||||
if (!xlogdriver->xlog_dev)
|
||||
return -EIO;
|
||||
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
||||
static int __init xlogchar_init(void)
|
||||
{
|
||||
dev_t dev;
|
||||
int ret;
|
||||
|
||||
pr_info("xlogchar_init\n");
|
||||
ret = 0;
|
||||
xlogdriver = kzalloc(sizeof(struct xlogchar_dev) + 5, GFP_KERNEL);
|
||||
if (!xlogdriver)
|
||||
return -ENOMEM;
|
||||
|
||||
xlogdriver->buf = kzalloc(XLOGBUF_SIZE, GFP_KERNEL);
|
||||
if (!xlogdriver->buf)
|
||||
return -ENOMEM;
|
||||
|
||||
mutex_init(&xlogdriver->xlog_mutex);
|
||||
init_waitqueue_head(&xlogdriver->wait_q);
|
||||
|
||||
xlogdriver->num = 1;
|
||||
xlogdriver->name = ((void *)xlogdriver) + sizeof(struct xlogchar_dev);
|
||||
xlogdriver->free_size = XLOGBUF_SIZE;
|
||||
strlcpy(xlogdriver->name, "xlog", 4);
|
||||
/* Get major number from kernel and initialize */
|
||||
ret = alloc_chrdev_region(&dev, xlogdriver->minor_start,
|
||||
xlogdriver->num, xlogdriver->name);
|
||||
if (!ret) {
|
||||
xlogdriver->major = MAJOR(dev);
|
||||
xlogdriver->minor_start = MINOR(dev);
|
||||
} else {
|
||||
pr_err("xlog: Major number not allocated\n");
|
||||
return ret;
|
||||
}
|
||||
xlogdriver->cdev = cdev_alloc();
|
||||
ret = xlogchar_setup_cdev(dev);
|
||||
if (ret)
|
||||
pr_err("xlogchar_setup_cdev failed\n");
|
||||
|
||||
pr_info("xlogchar_init done\n");
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void xlogchar_exit(void)
|
||||
{
|
||||
if (xlogdriver) {
|
||||
kfree(xlogdriver->buf);
|
||||
if (xlogdriver->cdev) {
|
||||
/* TODO - Check if device exists before deleting */
|
||||
device_destroy(xlogdriver->xlogchar_class,
|
||||
MKDEV(xlogdriver->major,
|
||||
xlogdriver->minor_start));
|
||||
cdev_del(xlogdriver->cdev);
|
||||
}
|
||||
if (!IS_ERR(xlogdriver->xlogchar_class))
|
||||
class_destroy(xlogdriver->xlogchar_class);
|
||||
kfree(xlogdriver);
|
||||
}
|
||||
pr_info("done xlogchar exit\n");
|
||||
}
|
||||
|
||||
core_initcall(xlogchar_init);
|
||||
module_exit(xlogchar_exit);
|
||||
|
||||
MODULE_DESCRIPTION("Xlog Char Driver");
|
||||
MODULE_LICENSE("GPL v2");
|
||||
40
drivers/char/xlogchar.h
Normal file
40
drivers/char/xlogchar.h
Normal file
@@ -0,0 +1,40 @@
|
||||
/* Copyright (C) 2018 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 XLOGCHAR_H
|
||||
#define XLOGCHAR_H
|
||||
|
||||
/* xlog alloc 1M bytes buffer used for audio event,
|
||||
* and use the ping pong buffer for write and read
|
||||
*/
|
||||
|
||||
#define XLOGBUF_SIZE (1024*1024)
|
||||
#define XLOGPKG_SIZE 512
|
||||
#define XLOGPKG_NUM (XLOGBUF_SIZE/XLOGPKG_SIZE)
|
||||
struct xlogchar_dev {
|
||||
/* State for the char driver */
|
||||
unsigned int major;
|
||||
unsigned int minor_start;
|
||||
int num;
|
||||
struct cdev *cdev;
|
||||
char *name;
|
||||
size_t readindex;
|
||||
size_t writeindex;
|
||||
size_t free_size;
|
||||
struct class *xlogchar_class;
|
||||
struct device *xlog_dev;
|
||||
struct mutex xlog_mutex;
|
||||
wait_queue_head_t wait_q;
|
||||
char *buf;
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -107,6 +107,8 @@ struct clk {
|
||||
struct hlist_node clks_node;
|
||||
};
|
||||
|
||||
extern int in_panic;
|
||||
|
||||
/*** runtime pm ***/
|
||||
static int clk_pm_runtime_get(struct clk_core *core)
|
||||
{
|
||||
|
||||
4
drivers/fragmention/Makefile
Normal file
4
drivers/fragmention/Makefile
Normal file
@@ -0,0 +1,4 @@
|
||||
fragmentize-y := fragmentize_main.o
|
||||
obj-m += fragmentize.o
|
||||
|
||||
BOARD_VENDOR_KERNEL_MODULES += $(KERNEL_MODULES_OUT)/fragmentize.ko
|
||||
198
drivers/fragmention/fragmentize_main.c
Normal file
198
drivers/fragmention/fragmentize_main.c
Normal file
@@ -0,0 +1,198 @@
|
||||
/* Copyright (c) 2011-2012, The Linux Foundation. All Rights Reserved.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Memory fragmentize simulate test
|
||||
*
|
||||
*/
|
||||
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/mm.h>
|
||||
#include <linux/pagemap.h>
|
||||
#include <linux/list.h>
|
||||
#include <linux/gfp.h>
|
||||
#include <linux/memory.h>
|
||||
#include <linux/kobject.h>
|
||||
#include <linux/version.h>
|
||||
|
||||
|
||||
#include <asm/page.h>
|
||||
#include <asm/pgalloc.h>
|
||||
#include <asm/pgtable.h>
|
||||
#include <linux/dma-mapping.h>
|
||||
#include <linux/dma-contiguous.h>
|
||||
|
||||
#define DEFAULT_BLOCK_ORDER 2
|
||||
#define DEFAULT_ALLOC_TIMES 16384
|
||||
#define DEFAULT_ACCUPY_SIZE 0
|
||||
|
||||
/* Module params */
|
||||
static unsigned long alloc_times = DEFAULT_ALLOC_TIMES;
|
||||
static unsigned long real_alloc_times = DEFAULT_ALLOC_TIMES;
|
||||
static unsigned long block_order = DEFAULT_BLOCK_ORDER;
|
||||
static unsigned long accupy = 0;
|
||||
static unsigned long real_accupy = 0;
|
||||
|
||||
|
||||
static unsigned long * pfn_occupy;
|
||||
|
||||
static int filled = 0;
|
||||
|
||||
static struct kobject *fragmentize_kobj;
|
||||
|
||||
static ssize_t alloc_times_total_show(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
if (0 == block_order)
|
||||
return sprintf(buf, "%u\n", filled);
|
||||
else
|
||||
return sprintf(buf, "%u\n", filled / ((1 << block_order) / 2));
|
||||
}
|
||||
|
||||
static ssize_t alloc_size_total_show(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
|
||||
return sprintf(buf, "%u MBytes\n", (filled << PAGE_SHIFT) / SZ_1M);
|
||||
}
|
||||
|
||||
static DEVICE_ATTR(alloc_times_total, S_IRUGO, alloc_times_total_show, NULL);
|
||||
|
||||
static DEVICE_ATTR(alloc_size_total, S_IRUGO, alloc_size_total_show, NULL);
|
||||
|
||||
|
||||
static struct attribute *fragmentize_attrs[] = {
|
||||
&dev_attr_alloc_size_total.attr,
|
||||
&dev_attr_alloc_times_total.attr,
|
||||
NULL,
|
||||
};
|
||||
|
||||
struct attribute_group fragmentize_attr_group = {
|
||||
.attrs = fragmentize_attrs,
|
||||
};
|
||||
|
||||
static int __init fragmentize_init(void)
|
||||
{
|
||||
struct page *contigpages = NULL;
|
||||
unsigned long contigpfn = 0;
|
||||
unsigned long page_records;
|
||||
int i , j, m;
|
||||
int block_idx = 0;
|
||||
int ret = 0;
|
||||
|
||||
fragmentize_kobj = kobject_create_and_add("fragmentize", kernel_kobj);
|
||||
if (!fragmentize_kobj)
|
||||
return -ENOMEM;
|
||||
|
||||
ret = sysfs_create_group(fragmentize_kobj,
|
||||
&fragmentize_attr_group);
|
||||
if (ret < 0) {
|
||||
kobject_put(fragmentize_kobj);
|
||||
pr_warning("Error creating sysfs group");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (block_order >= MAX_ORDER)
|
||||
block_order = MAX_ORDER - 1;
|
||||
|
||||
// if block_order=zero mean only accupy not to fragmention
|
||||
if (0 == block_order) {
|
||||
if (DEFAULT_ACCUPY_SIZE != accupy)
|
||||
alloc_times = (accupy * SZ_1M) >> PAGE_SHIFT;
|
||||
page_records = alloc_times;
|
||||
} else {
|
||||
if (DEFAULT_ACCUPY_SIZE != accupy)
|
||||
alloc_times = ((accupy * SZ_1M) >> PAGE_SHIFT) / ((1 << block_order) / 2);
|
||||
page_records = ((1 << block_order) / 2) * alloc_times;
|
||||
}
|
||||
accupy = (page_records << PAGE_SHIFT) / SZ_1M;
|
||||
|
||||
pfn_occupy = (unsigned long *)vmalloc(page_records * sizeof(unsigned long));
|
||||
|
||||
if(NULL == pfn_occupy) {
|
||||
printk("fail to vmalloc pfn_free or pfn_occupy \n");
|
||||
goto skip_alloc;
|
||||
}
|
||||
|
||||
for(i = 0; i < alloc_times; i++) {
|
||||
contigpages = alloc_pages(GFP_KERNEL | __GFP_MOVABLE, block_order);
|
||||
if(contigpages != NULL) {
|
||||
contigpfn = page_to_pfn(contigpages);
|
||||
for (m = 0; m < (1 << block_order); m++) {
|
||||
#if LINUX_VERSION_CODE >= KERNEL_VERSION(4,9,0)
|
||||
atomic_set(&((pfn_to_page(contigpfn + m))->_refcount), 1);
|
||||
#else
|
||||
atomic_set(&((pfn_to_page(contigpfn + m))->_count), 1);
|
||||
#endif
|
||||
}
|
||||
if (0 == block_order) {
|
||||
block_idx = i;
|
||||
pfn_occupy[block_idx] = contigpfn;
|
||||
} else {
|
||||
block_idx = i * (1 << block_order) / 2;
|
||||
for(j = 0; j < (1 << block_order) / 2; j++) {
|
||||
__free_pages(pfn_to_page(contigpfn + 2 *j), 0);
|
||||
pfn_occupy[block_idx + j] = contigpfn + 2*j + 1;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
//printk("tried %d times\n", i);
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
real_alloc_times = i;
|
||||
|
||||
if (0 == block_order)
|
||||
filled = block_idx + (1 << block_order);
|
||||
else
|
||||
filled = block_idx + (1 << block_order) / 2;
|
||||
|
||||
real_accupy = (filled << PAGE_SHIFT) / SZ_1M;
|
||||
skip_alloc:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void __exit fragmentize_exit(void)
|
||||
{
|
||||
int k = 0;
|
||||
|
||||
sysfs_remove_group(fragmentize_kobj,
|
||||
&fragmentize_attr_group);
|
||||
kobject_put(fragmentize_kobj);
|
||||
|
||||
if (NULL != pfn_occupy) {
|
||||
for(; k < filled; k++) {
|
||||
//atomic_set(&((pfn_to_page(pfn_free[k]))->_count), 0);
|
||||
__free_pages(pfn_to_page(pfn_occupy[k]), 0);
|
||||
}
|
||||
vfree(pfn_occupy);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
module_init(fragmentize_init);
|
||||
module_exit(fragmentize_exit);
|
||||
|
||||
module_param(alloc_times, ulong, S_IRUSR);
|
||||
module_param(real_alloc_times, ulong, S_IRUSR);
|
||||
module_param(block_order, ulong, S_IRUSR);
|
||||
module_param(accupy, ulong, S_IRUSR);
|
||||
module_param(real_accupy, ulong, S_IRUSR);
|
||||
MODULE_PARM_DESC(block_order, "block_order should be less than MAX_ORDER");
|
||||
MODULE_PARM_DESC(accupy, "The two accupy and alloc_times are used together, accupy is valid");
|
||||
|
||||
MODULE_LICENSE("GPL v2");
|
||||
MODULE_DESCRIPTION("fragmention");
|
||||
|
||||
@@ -2811,8 +2811,9 @@ static int a6xx_gmu_power_off(struct adreno_device *adreno_dev)
|
||||
|
||||
clk_bulk_disable_unprepare(gmu->num_clks, gmu->clks);
|
||||
|
||||
/* Poll to make sure that the CX is off */
|
||||
a6xx_cx_regulator_disable_wait(gmu->cx_gdsc, device, 5000);
|
||||
/* Pool to make sure that the CX is off */
|
||||
a6xx_cx_regulator_disable_wait(gmu->cx_gdsc, device,
|
||||
IS_ENABLED(CONFIG_ARM_SMMU_POWER_ALWAYS_ON) ? 0 : 5000);
|
||||
|
||||
a6xx_rdpm_cx_freq_update(gmu, 0);
|
||||
|
||||
|
||||
@@ -21,6 +21,9 @@
|
||||
#include <linux/pm_runtime.h>
|
||||
#include <linux/security.h>
|
||||
#include <linux/sort.h>
|
||||
#if IS_ENABLED(CONFIG_MIMISC_MC)
|
||||
#include <linux/memcontrol.h>
|
||||
#endif
|
||||
#include <soc/qcom/boot_stats.h>
|
||||
|
||||
#include "kgsl_compat.h"
|
||||
@@ -1043,6 +1046,11 @@ static void process_release_memory(struct kgsl_process_private *private)
|
||||
if (!entry->pending_free) {
|
||||
entry->pending_free = 1;
|
||||
spin_unlock(&private->mem_lock);
|
||||
#if IS_ENABLED(CONFIG_MIMISC_MC)
|
||||
if (likely(entry->memdesc.page_count))
|
||||
memcg_misc_uncharge(&(entry->memdesc.memgroup),
|
||||
entry->memdesc.page_count, MEMCG_GPU_TYPE);
|
||||
#endif
|
||||
kgsl_mem_entry_put(entry);
|
||||
} else {
|
||||
spin_unlock(&private->mem_lock);
|
||||
@@ -2222,6 +2230,12 @@ long gpumem_free_entry(struct kgsl_mem_entry *entry)
|
||||
if (!kgsl_mem_entry_set_pend(entry))
|
||||
return -EBUSY;
|
||||
|
||||
#if IS_ENABLED(CONFIG_MIMISC_MC)
|
||||
if (likely(entry->memdesc.page_count))
|
||||
memcg_misc_uncharge(&(entry->memdesc.memgroup),
|
||||
entry->memdesc.page_count, MEMCG_GPU_TYPE);
|
||||
#endif
|
||||
|
||||
trace_kgsl_mem_free(entry);
|
||||
kgsl_memfree_add(pid_nr(entry->priv->pid),
|
||||
entry->memdesc.pagetable ?
|
||||
@@ -2241,6 +2255,12 @@ static void gpumem_free_func(struct kgsl_device *device,
|
||||
struct kgsl_mem_entry *entry = priv;
|
||||
unsigned int timestamp;
|
||||
|
||||
#if IS_ENABLED(CONFIG_MIMISC_MC)
|
||||
if (likely(entry->memdesc.page_count))
|
||||
memcg_misc_uncharge(&(entry->memdesc.memgroup),
|
||||
entry->memdesc.page_count, MEMCG_GPU_TYPE);
|
||||
#endif
|
||||
|
||||
kgsl_readtimestamp(device, context, KGSL_TIMESTAMP_RETIRED, ×tamp);
|
||||
|
||||
/* Free the memory for all event types */
|
||||
@@ -2345,6 +2365,12 @@ static bool gpuobj_free_fence_func(void *priv)
|
||||
{
|
||||
struct kgsl_mem_entry *entry = priv;
|
||||
|
||||
#if IS_ENABLED(CONFIG_MIMISC_MC)
|
||||
if (likely(entry->memdesc.page_count))
|
||||
memcg_misc_uncharge(&(entry->memdesc.memgroup),
|
||||
entry->memdesc.page_count, MEMCG_GPU_TYPE);
|
||||
#endif
|
||||
|
||||
trace_kgsl_mem_free(entry);
|
||||
kgsl_memfree_add(pid_nr(entry->priv->pid),
|
||||
entry->memdesc.pagetable ?
|
||||
@@ -3635,6 +3661,13 @@ struct kgsl_mem_entry *gpumem_alloc_entry(
|
||||
trace_kgsl_mem_alloc(entry);
|
||||
|
||||
kgsl_mem_entry_commit_process(entry);
|
||||
|
||||
#if IS_ENABLED(CONFIG_MIMISC_MC)
|
||||
if (likely(entry->memdesc.page_count))
|
||||
memcg_misc_charge(&(entry->memdesc.memgroup), 0,
|
||||
entry->memdesc.page_count, MEMCG_GPU_TYPE);
|
||||
#endif
|
||||
|
||||
return entry;
|
||||
err:
|
||||
kfree(entry);
|
||||
|
||||
@@ -217,6 +217,9 @@ struct kgsl_memdesc {
|
||||
unsigned long attrs;
|
||||
struct page **pages;
|
||||
unsigned int page_count;
|
||||
#if IS_ENABLED(CONFIG_MIMISC_MC)
|
||||
struct page memgroup;
|
||||
#endif
|
||||
/*
|
||||
* @lock: Spinlock to protect the gpuaddr from being accessed by
|
||||
* multiple entities trying to map the same SVM region at once
|
||||
|
||||
@@ -478,6 +478,9 @@ static vm_fault_t kgsl_paged_vmfault(struct kgsl_memdesc *memdesc,
|
||||
|
||||
pgoff = offset >> PAGE_SHIFT;
|
||||
|
||||
if( !memdesc->pages)
|
||||
return VM_FAULT_NOPAGE;
|
||||
|
||||
return vmf_insert_page(vma, vmf->address, memdesc->pages[pgoff]);
|
||||
}
|
||||
|
||||
|
||||
@@ -695,7 +695,7 @@ static int i3c_geni_runtime_get_mutex_lock(struct geni_i3c_dev *gi3c)
|
||||
static void i3c_geni_runtime_put_mutex_unlock(struct geni_i3c_dev *gi3c)
|
||||
{
|
||||
pm_runtime_mark_last_busy(gi3c->se.dev);
|
||||
pm_runtime_put_autosuspend(gi3c->se.dev);
|
||||
pm_runtime_put_sync_suspend(gi3c->se.dev);
|
||||
mutex_unlock(&gi3c->lock);
|
||||
}
|
||||
|
||||
|
||||
@@ -123,4 +123,11 @@ config VL53L0X_I2C
|
||||
To compile this driver as a module, choose M here: the
|
||||
module will be called vl53l0x-i2c.
|
||||
|
||||
config MIUS_PROXIMITY
|
||||
tristate "xiaomi ultrasound proximity sensor"
|
||||
select IIO_BUFFER
|
||||
select IIO_TRIGGERED_BUFFER
|
||||
select IIO_BUFFER_CB
|
||||
select IIO_KFIFO_BUF
|
||||
select IIO_TRIGGER
|
||||
endmenu
|
||||
|
||||
@@ -201,6 +201,10 @@ source "drivers/input/misc/Kconfig"
|
||||
|
||||
source "drivers/input/rmi4/Kconfig"
|
||||
|
||||
source "drivers/input/fingerprint/Kconfig"
|
||||
|
||||
source "drivers/input/stmvl53l5/Kconfig"
|
||||
|
||||
endif
|
||||
|
||||
menu "Hardware I/O ports"
|
||||
|
||||
@@ -24,8 +24,33 @@ obj-$(CONFIG_INPUT_MOUSE) += mouse/
|
||||
obj-$(CONFIG_INPUT_JOYSTICK) += joystick/
|
||||
obj-$(CONFIG_INPUT_TABLET) += tablet/
|
||||
obj-$(CONFIG_INPUT_TOUCHSCREEN) += touchscreen/
|
||||
obj-$(CONFIG_INPUT_FINGERPRINT) += fingerprint/
|
||||
obj-$(CONFIG_INPUT_MISC) += misc/
|
||||
|
||||
obj-$(CONFIG_INPUT_APMPOWER) += apm-power.o
|
||||
|
||||
obj-$(CONFIG_RMI4_CORE) += rmi4/
|
||||
obj-$(CONFIG_STMVL53L5) += stmvl53l5/
|
||||
|
||||
ifeq ($(TARGET_PRODUCT), renoir)
|
||||
KBUILD_CPPFLAGS += -DQCOM_HAPTIC_BOB
|
||||
KBUILD_CPPFLAGS += -DQCOM_HAPTIC_F0_PROTECT
|
||||
endif
|
||||
|
||||
ifeq ($(TARGET_PRODUCT), cetus)
|
||||
KBUILD_CPPFLAGS += -DQCOM_HAPTIC_F0_PROTECT
|
||||
endif
|
||||
|
||||
ifeq ($(TARGET_PRODUCT), argo)
|
||||
KBUILD_CPPFLAGS += -DQCOM_HAPTIC_F0_PROTECT
|
||||
endif
|
||||
|
||||
ifeq ($(TARGET_PRODUCT), haydn)
|
||||
KBUILD_CPPFLAGS += -DQCOM_HAPTIC_F0_PROTECT
|
||||
KBUILD_CPPFLAGS += -DCONFIG_TARGET_PRODUCT_HAYDN
|
||||
endif
|
||||
|
||||
ifeq ($(TARGET_PRODUCT), vili)
|
||||
KBUILD_CPPFLAGS += -DQCOM_HAPTIC_F0_PROTECT
|
||||
KBUILD_CPPFLAGS += -DCONFIG_TARGET_PRODUCT_VILI
|
||||
endif
|
||||
|
||||
28
drivers/input/fingerprint/Kconfig
Normal file
28
drivers/input/fingerprint/Kconfig
Normal file
@@ -0,0 +1,28 @@
|
||||
#
|
||||
# Fingerprint driver configuration
|
||||
#
|
||||
config FINGERPRINT_FP_VREG_CONTROL
|
||||
bool "fingerprint fp_vdd_reg regulator control"
|
||||
default n
|
||||
---help---
|
||||
Say Y here to enable fp_vdd_vreg regulator by device driver
|
||||
|
||||
config FINGERPRINT_SET_VREG_CONTROL
|
||||
bool "Goodix FOD Fingerprint K9B sensor"
|
||||
default n
|
||||
help
|
||||
Goodix FOD Fingerprint K9B sensor
|
||||
|
||||
menuconfig INPUT_FINGERPRINT
|
||||
bool "Fingerprints"
|
||||
help
|
||||
Say Y here, and a list of supported fingerprints will be displayed.
|
||||
This option doesn't affect the kernel.
|
||||
|
||||
If unsure, say Y.
|
||||
|
||||
if INPUT_FINGERPRINT
|
||||
|
||||
source "drivers/input/fingerprint/goodix_fod/Kconfig"
|
||||
|
||||
endif
|
||||
6
drivers/input/fingerprint/Makefile
Normal file
6
drivers/input/fingerprint/Makefile
Normal file
@@ -0,0 +1,6 @@
|
||||
#
|
||||
# Makefile for the fingerprint drivers.
|
||||
#
|
||||
|
||||
# Each configuration option enables a list of files.
|
||||
obj-$(CONFIG_FINGERPRINT_GOODIX_FOD) += goodix_fod/
|
||||
10
drivers/input/fingerprint/goodix_fod/Kconfig
Normal file
10
drivers/input/fingerprint/goodix_fod/Kconfig
Normal file
@@ -0,0 +1,10 @@
|
||||
config FINGERPRINT_GOODIX_FOD
|
||||
tristate "Finger print card goodix"
|
||||
depends on INPUT_FINGERPRINT
|
||||
help
|
||||
Say Y here to enable support for retrieving self-test reports.
|
||||
|
||||
If unsure, say N.
|
||||
|
||||
To compile this driver as a module, choose M here.
|
||||
|
||||
20
drivers/input/fingerprint/goodix_fod/Makefile
Normal file
20
drivers/input/fingerprint/goodix_fod/Makefile
Normal file
@@ -0,0 +1,20 @@
|
||||
ifneq ($(KERNELRELEASE),)
|
||||
goodix_fod-objs := gf_spi.o platform.o netlink.o
|
||||
obj-$(CONFIG_FINGERPRINT_GOODIX_FOD) += goodix_fod.o
|
||||
else
|
||||
KDIR = $(OUT)/obj/KERNEL_OBJ
|
||||
CROSS_COMPILE = $(ANDROID_TOOLCHAIN)/aarch64-linux-android-
|
||||
CLANG = $(ANDROID_BUILD_TOP)/prebuilts/clang/host/linux-x86/clang-r370808
|
||||
REAL_CC = $(CLANG)/bin/clang
|
||||
AR = $(CLANG)/bin/llvm-ar
|
||||
LLVM_NM = $(CLANG)/bin/llvm-nm
|
||||
LD = $(CLANG)/bin/ld.lld
|
||||
|
||||
.PHONY: clean
|
||||
|
||||
default:
|
||||
$(MAKE) ARCH=arm64 CROSS_COMPILE=$(CROSS_COMPILE) REAL_CC=$(REAL_CC) CLANG_TRIPLE=aarch64-linux-gnu- AR=$(AR) LLVM_NM=$(LLVM_NM) LD=$(LD) -C $(KDIR) M=$(PWD) modules
|
||||
clean:
|
||||
@rm -rf *.o* *.order *.symvers *.mod* .*.o.cmd .*.mod.o.cmd .*.ko.cmd .tmp_versions *.ko
|
||||
|
||||
endif
|
||||
1155
drivers/input/fingerprint/goodix_fod/gf_spi.c
Normal file
1155
drivers/input/fingerprint/goodix_fod/gf_spi.c
Normal file
File diff suppressed because it is too large
Load Diff
162
drivers/input/fingerprint/goodix_fod/gf_spi.h
Normal file
162
drivers/input/fingerprint/goodix_fod/gf_spi.h
Normal file
@@ -0,0 +1,162 @@
|
||||
/*
|
||||
* driver definition for sensor driver
|
||||
*
|
||||
* Coypright (c) 2017 Goodix
|
||||
*/
|
||||
#ifndef __GF_SPI_H
|
||||
#define __GF_SPI_H
|
||||
|
||||
#include <linux/types.h>
|
||||
#include <linux/notifier.h>
|
||||
/**********************************************************/
|
||||
enum FP_MODE {
|
||||
GF_IMAGE_MODE = 0,
|
||||
GF_KEY_MODE,
|
||||
GF_SLEEP_MODE,
|
||||
GF_FF_MODE,
|
||||
GF_DEBUG_MODE = 0x56
|
||||
};
|
||||
|
||||
#define SUPPORT_NAV_EVENT
|
||||
|
||||
#if defined(SUPPORT_NAV_EVENT)
|
||||
#define GF_NAV_INPUT_UP KEY_UP
|
||||
#define GF_NAV_INPUT_DOWN KEY_DOWN
|
||||
#define GF_NAV_INPUT_LEFT KEY_LEFT
|
||||
#define GF_NAV_INPUT_RIGHT KEY_RIGHT
|
||||
#define GF_NAV_INPUT_CLICK KEY_VOLUMEDOWN
|
||||
#define GF_NAV_INPUT_DOUBLE_CLICK KEY_VOLUMEUP
|
||||
#define GF_NAV_INPUT_LONG_PRESS KEY_SEARCH
|
||||
#define GF_NAV_INPUT_HEAVY KEY_CHAT
|
||||
#endif
|
||||
|
||||
#define GF_KEY_INPUT_HOME KEY_HOME
|
||||
#define GF_KEY_INPUT_MENU KEY_MENU
|
||||
#define GF_KEY_INPUT_BACK KEY_BACK
|
||||
#define GF_KEY_INPUT_POWER KEY_POWER
|
||||
#define GF_KEY_INPUT_CAMERA KEY_CAMERA
|
||||
|
||||
#if defined(SUPPORT_NAV_EVENT)
|
||||
typedef enum gf_nav_event {
|
||||
GF_NAV_NONE = 0,
|
||||
GF_NAV_FINGER_UP,
|
||||
GF_NAV_FINGER_DOWN,
|
||||
GF_NAV_UP,
|
||||
GF_NAV_DOWN,
|
||||
GF_NAV_LEFT,
|
||||
GF_NAV_RIGHT,
|
||||
GF_NAV_CLICK,
|
||||
GF_NAV_HEAVY,
|
||||
GF_NAV_LONG_PRESS,
|
||||
GF_NAV_DOUBLE_CLICK,
|
||||
} gf_nav_event_t;
|
||||
#endif
|
||||
|
||||
typedef enum gf_key_event {
|
||||
GF_KEY_NONE = 0,
|
||||
GF_KEY_HOME,
|
||||
GF_KEY_POWER,
|
||||
GF_KEY_MENU,
|
||||
GF_KEY_BACK,
|
||||
GF_KEY_CAMERA,
|
||||
} gf_key_event_t;
|
||||
|
||||
struct gf_key {
|
||||
enum gf_key_event key;
|
||||
uint32_t value; /* key down = 1, key up = 0 */
|
||||
};
|
||||
|
||||
struct gf_key_map {
|
||||
unsigned int type;
|
||||
unsigned int code;
|
||||
};
|
||||
|
||||
struct gf_ioc_chip_info {
|
||||
unsigned char vendor_id;
|
||||
unsigned char mode;
|
||||
unsigned char operation;
|
||||
unsigned char reserved[5];
|
||||
};
|
||||
|
||||
#define GF_IOC_MAGIC 'g' /*define magic number */
|
||||
#define GF_IOC_INIT _IOR(GF_IOC_MAGIC, 0, uint8_t)
|
||||
#define GF_IOC_EXIT _IO(GF_IOC_MAGIC, 1)
|
||||
#define GF_IOC_RESET _IO(GF_IOC_MAGIC, 2)
|
||||
#define GF_IOC_ENABLE_IRQ _IO(GF_IOC_MAGIC, 3)
|
||||
#define GF_IOC_DISABLE_IRQ _IO(GF_IOC_MAGIC, 4)
|
||||
#define GF_IOC_ENABLE_SPI_CLK _IOW(GF_IOC_MAGIC, 5, uint32_t)
|
||||
#define GF_IOC_DISABLE_SPI_CLK _IO(GF_IOC_MAGIC, 6)
|
||||
#define GF_IOC_ENABLE_POWER _IO(GF_IOC_MAGIC, 7)
|
||||
#define GF_IOC_DISABLE_POWER _IO(GF_IOC_MAGIC, 8)
|
||||
#define GF_IOC_INPUT_KEY_EVENT _IOW(GF_IOC_MAGIC, 9, struct gf_key)
|
||||
#define GF_IOC_ENTER_SLEEP_MODE _IO(GF_IOC_MAGIC, 10)
|
||||
#define GF_IOC_GET_FW_INFO _IOR(GF_IOC_MAGIC, 11, uint8_t)
|
||||
#define GF_IOC_REMOVE _IO(GF_IOC_MAGIC, 12)
|
||||
#define GF_IOC_CHIP_INFO _IOW(GF_IOC_MAGIC, 13, struct gf_ioc_chip_info)
|
||||
|
||||
#if defined(SUPPORT_NAV_EVENT)
|
||||
#define GF_IOC_NAV_EVENT _IOW(GF_IOC_MAGIC, 14, gf_nav_event_t)
|
||||
#define GF_IOC_MAXNR 15 /* THIS MACRO IS NOT USED NOW... */
|
||||
#else
|
||||
#define GF_IOC_MAXNR 14 /* THIS MACRO IS NOT USED NOW... */
|
||||
#endif
|
||||
|
||||
/*#define AP_CONTROL_CLK 1*/
|
||||
#define USE_PLATFORM_BUS 1
|
||||
/*#define USE_SPI_BUS 1*/
|
||||
/*#define GF_FASYNC 1*/
|
||||
/*If support fasync mechanism. */
|
||||
/*#define GF_PW_CTL 1*/
|
||||
#undef GF_PW_CTL
|
||||
#define GF_NETLINK_ENABLE 1
|
||||
#define GF_NET_EVENT_IRQ 1
|
||||
#define GF_NET_EVENT_FB_BLACK 2
|
||||
#define GF_NET_EVENT_FB_UNBLACK 3
|
||||
#define NETLINK_TEST 25
|
||||
|
||||
struct gf_dev {
|
||||
dev_t devt;
|
||||
struct list_head device_entry;
|
||||
#if defined(USE_SPI_BUS)
|
||||
struct spi_device *spi;
|
||||
#elif defined(USE_PLATFORM_BUS)
|
||||
struct platform_device *spi;
|
||||
#endif
|
||||
struct clk *core_clk;
|
||||
struct clk *iface_clk;
|
||||
|
||||
struct input_dev *input;
|
||||
/* buffer is NULL unless this device is open (users > 0) */
|
||||
unsigned users;
|
||||
signed irq_gpio;
|
||||
signed reset_gpio;
|
||||
signed pwr_gpio;
|
||||
int irq;
|
||||
int irq_enabled;
|
||||
int clk_enabled;
|
||||
#ifdef GF_FASYNC
|
||||
struct fasync_struct *async;
|
||||
#endif
|
||||
struct notifier_block notifier;
|
||||
char device_available;
|
||||
char fb_black;
|
||||
char wait_finger_down;
|
||||
struct work_struct work;
|
||||
#ifdef CONFIG_FINGERPRINT_FP_VREG_CONTROL
|
||||
struct regulator *vreg;
|
||||
#endif
|
||||
};
|
||||
|
||||
int gf_parse_dts(struct gf_dev *gf_dev);
|
||||
void gf_cleanup(struct gf_dev *gf_dev);
|
||||
|
||||
int gf_power_on(struct gf_dev *gf_dev);
|
||||
int gf_power_off(struct gf_dev *gf_dev);
|
||||
|
||||
int gf_hw_reset(struct gf_dev *gf_dev, unsigned int delay_ms);
|
||||
int gf_irq_num(struct gf_dev *gf_dev);
|
||||
|
||||
void sendnlmsg(char *message);
|
||||
int netlink_init(void);
|
||||
void netlink_exit(void);
|
||||
#endif /*__GF_SPI_H*/
|
||||
96
drivers/input/fingerprint/goodix_fod/netlink.c
Normal file
96
drivers/input/fingerprint/goodix_fod/netlink.c
Normal file
@@ -0,0 +1,96 @@
|
||||
/*
|
||||
* netlink interface
|
||||
*
|
||||
* Copyright (c) 2017 Goodix
|
||||
*/
|
||||
#include <linux/init.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/timer.h>
|
||||
#include <linux/time.h>
|
||||
#include <linux/types.h>
|
||||
#include <net/sock.h>
|
||||
#include <net/netlink.h>
|
||||
|
||||
#define NETLINK_TEST 25
|
||||
#define MAX_MSGSIZE 32
|
||||
int stringlength(char *s);
|
||||
void sendnlmsg(char *message);
|
||||
static int pid = -1;
|
||||
struct sock *nl_sk;
|
||||
|
||||
void sendnlmsg(char *message)
|
||||
{
|
||||
struct sk_buff *skb_1;
|
||||
struct nlmsghdr *nlh;
|
||||
int len = NLMSG_SPACE(MAX_MSGSIZE);
|
||||
int slen = 0;
|
||||
int ret = 0;
|
||||
|
||||
if (!message || !nl_sk || !pid) {
|
||||
return;
|
||||
}
|
||||
|
||||
skb_1 = alloc_skb(len, GFP_KERNEL);
|
||||
|
||||
if (!skb_1) {
|
||||
pr_err("alloc_skb error\n");
|
||||
return;
|
||||
}
|
||||
|
||||
slen = strlen(message);
|
||||
nlh = nlmsg_put(skb_1, 0, 0, 0, MAX_MSGSIZE, 0);
|
||||
NETLINK_CB(skb_1).portid = 0;
|
||||
NETLINK_CB(skb_1).dst_group = 0;
|
||||
message[slen] = '\0';
|
||||
memcpy(NLMSG_DATA(nlh), message, slen + 1);
|
||||
ret = netlink_unicast(nl_sk, skb_1, pid, MSG_DONTWAIT);
|
||||
|
||||
if (!ret) {
|
||||
/*kfree_skb(skb_1); */
|
||||
pr_err("send msg from kernel to usespace failed ret 0x%x\n",
|
||||
ret);
|
||||
}
|
||||
}
|
||||
|
||||
void nl_data_ready(struct sk_buff *__skb)
|
||||
{
|
||||
struct sk_buff *skb;
|
||||
struct nlmsghdr *nlh;
|
||||
char str[100];
|
||||
skb = skb_get(__skb);
|
||||
|
||||
if (skb->len >= NLMSG_SPACE(0)) {
|
||||
nlh = nlmsg_hdr(skb);
|
||||
memcpy(str, NLMSG_DATA(nlh), sizeof(str));
|
||||
pid = nlh->nlmsg_pid;
|
||||
kfree_skb(skb);
|
||||
}
|
||||
}
|
||||
|
||||
int netlink_init(void)
|
||||
{
|
||||
struct netlink_kernel_cfg netlink_cfg;
|
||||
memset(&netlink_cfg, 0, sizeof(struct netlink_kernel_cfg));
|
||||
netlink_cfg.groups = 0;
|
||||
netlink_cfg.flags = 0;
|
||||
netlink_cfg.input = nl_data_ready;
|
||||
netlink_cfg.cb_mutex = NULL;
|
||||
nl_sk = netlink_kernel_create(&init_net, NETLINK_TEST, &netlink_cfg);
|
||||
|
||||
if (!nl_sk) {
|
||||
pr_err("create netlink socket error\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void netlink_exit(void)
|
||||
{
|
||||
if (nl_sk != NULL) {
|
||||
netlink_kernel_release(nl_sk);
|
||||
nl_sk = NULL;
|
||||
}
|
||||
|
||||
pr_info("self module exited\n");
|
||||
}
|
||||
139
drivers/input/fingerprint/goodix_fod/platform.c
Normal file
139
drivers/input/fingerprint/goodix_fod/platform.c
Normal file
@@ -0,0 +1,139 @@
|
||||
/*
|
||||
* platform indepent driver interface
|
||||
*
|
||||
* Coypritht (c) 2017 Goodix
|
||||
*/
|
||||
#define DEBUG
|
||||
#define pr_fmt(fmt) "gf_platform: " fmt
|
||||
|
||||
#include <linux/delay.h>
|
||||
#include <linux/workqueue.h>
|
||||
#include <linux/of_gpio.h>
|
||||
#include <linux/gpio.h>
|
||||
#include <linux/regulator/consumer.h>
|
||||
#include <linux/timer.h>
|
||||
#include <linux/err.h>
|
||||
|
||||
#include "gf_spi.h"
|
||||
|
||||
#if defined(USE_SPI_BUS)
|
||||
#include <linux/spi/spi.h>
|
||||
#include <linux/spi/spidev.h>
|
||||
#elif defined(USE_PLATFORM_BUS)
|
||||
#include <linux/platform_device.h>
|
||||
#endif
|
||||
|
||||
int gf_parse_dts(struct gf_dev *gf_dev)
|
||||
{
|
||||
#ifdef GF_PW_CTL
|
||||
/*get pwr resource */
|
||||
gf_dev->pwr_gpio =
|
||||
of_get_named_gpio(gf_dev->spi->dev.of_node, "fp-gpio-pwr", 0);
|
||||
|
||||
if (!gpio_is_valid(gf_dev->pwr_gpio)) {
|
||||
pr_info("PWR GPIO is invalid.\n");
|
||||
return -EPERM;
|
||||
}
|
||||
#endif
|
||||
/*get reset resource */
|
||||
gf_dev->reset_gpio =
|
||||
of_get_named_gpio(gf_dev->spi->dev.of_node, "goodix,gpio-reset", 0);
|
||||
|
||||
if (!gpio_is_valid(gf_dev->reset_gpio)) {
|
||||
pr_info("RESET GPIO is invalid.\n");
|
||||
return -EPERM;
|
||||
}
|
||||
pr_info("gf::gpio-reset:%d\n", gf_dev->reset_gpio);
|
||||
|
||||
/*get irq resourece */
|
||||
gf_dev->irq_gpio =
|
||||
of_get_named_gpio(gf_dev->spi->dev.of_node, "goodix,gpio-irq", 0);
|
||||
pr_info("gf::irq_gpio:%d\n", gf_dev->irq_gpio);
|
||||
|
||||
if (!gpio_is_valid(gf_dev->irq_gpio)) {
|
||||
pr_info("IRQ GPIO is invalid.\n");
|
||||
return -EPERM;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void gf_cleanup(struct gf_dev *gf_dev)
|
||||
{
|
||||
pr_info("[info] %s\n", __func__);
|
||||
|
||||
if (gpio_is_valid(gf_dev->irq_gpio)) {
|
||||
gpio_free(gf_dev->irq_gpio);
|
||||
pr_info("remove irq_gpio success\n");
|
||||
}
|
||||
|
||||
if (gpio_is_valid(gf_dev->reset_gpio)) {
|
||||
gpio_free(gf_dev->reset_gpio);
|
||||
pr_info("remove reset_gpio success\n");
|
||||
}
|
||||
#ifdef GF_PW_CTL
|
||||
|
||||
if (gpio_is_valid(gf_dev->pwr_gpio)) {
|
||||
gpio_free(gf_dev->pwr_gpio);
|
||||
pr_info("remove pwr_gpio success\n");
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
int gf_power_on(struct gf_dev *gf_dev)
|
||||
{
|
||||
int rc = 0;
|
||||
#ifdef GF_PW_CTL
|
||||
|
||||
if (gpio_is_valid(gf_dev->pwr_gpio)) {
|
||||
rc = gpio_direction_output(gf_dev->pwr_gpio, 1);
|
||||
pr_info("---- power on result: %d----\n", rc);
|
||||
} else {
|
||||
pr_info("%s: gpio_is_invalid\n", __func__);
|
||||
}
|
||||
|
||||
#endif
|
||||
msleep(10);
|
||||
return rc;
|
||||
}
|
||||
|
||||
int gf_power_off(struct gf_dev *gf_dev)
|
||||
{
|
||||
int rc = 0;
|
||||
#ifdef GF_PW_CTL
|
||||
|
||||
if (gpio_is_valid(gf_dev->pwr_gpio)) {
|
||||
rc = gpio_direction_output(gf_dev->pwr_gpio, 0);
|
||||
pr_info("---- power off result: %d----\n", rc);
|
||||
} else {
|
||||
pr_info("%s: gpio_is_invalid\n", __func__);
|
||||
}
|
||||
|
||||
#endif
|
||||
return rc;
|
||||
}
|
||||
|
||||
int gf_hw_reset(struct gf_dev *gf_dev, unsigned int delay_ms)
|
||||
{
|
||||
if (gf_dev == NULL) {
|
||||
pr_info("Input buff is NULL.\n");
|
||||
return -EPERM;
|
||||
}
|
||||
|
||||
gpio_direction_output(gf_dev->reset_gpio, 0);
|
||||
mdelay(3);
|
||||
gpio_set_value(gf_dev->reset_gpio, 1);
|
||||
mdelay(delay_ms);
|
||||
pr_info("%s\n", __func__);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int gf_irq_num(struct gf_dev *gf_dev)
|
||||
{
|
||||
if (gf_dev == NULL) {
|
||||
pr_info("Input buff is NULL.\n");
|
||||
return -EPERM;
|
||||
} else {
|
||||
return gpio_to_irq(gf_dev->irq_gpio);
|
||||
}
|
||||
}
|
||||
@@ -914,4 +914,7 @@ config INPUT_STPMIC1_ONKEY
|
||||
To compile this driver as a module, choose M here: the
|
||||
module will be called stpmic1_onkey.
|
||||
|
||||
source "drivers/input/misc/aw8697_haptic/Kconfig"
|
||||
source "drivers/input/misc/aw8624_haptic/Kconfig"
|
||||
source "drivers/input/misc/aw8622x_haptic/Kconfig"
|
||||
endif
|
||||
|
||||
@@ -87,4 +87,7 @@ obj-$(CONFIG_INPUT_WM831X_ON) += wm831x-on.o
|
||||
obj-$(CONFIG_INPUT_XEN_KBDDEV_FRONTEND) += xen-kbdfront.o
|
||||
obj-$(CONFIG_INPUT_YEALINK) += yealink.o
|
||||
obj-$(CONFIG_INPUT_IDEAPAD_SLIDEBAR) += ideapad_slidebar.o
|
||||
obj-$(CONFIG_INPUT_AW8697_HAPTIC) += aw8697_haptic/
|
||||
obj-$(CONFIG_INPUT_AW8624_HAPTIC) += aw8624_haptic/
|
||||
obj-$(CONFIG_INPUT_AW862XX_HAPTIC) += aw8622x_haptic/
|
||||
|
||||
|
||||
12
drivers/input/misc/aw8622x_haptic/Kconfig
Normal file
12
drivers/input/misc/aw8622x_haptic/Kconfig
Normal file
@@ -0,0 +1,12 @@
|
||||
config INPUT_AW862XX_HAPTIC
|
||||
tristate "Awinic AW862XX haptic driver"
|
||||
depends on I2C
|
||||
help
|
||||
Say Y here if you have Awinic AW862XX haptic controller
|
||||
chip in your system.
|
||||
If unsure, say N.
|
||||
To compile this driver as a module, choose M here: the
|
||||
module will be called aw862xx haptic driver.
|
||||
|
||||
|
||||
|
||||
2
drivers/input/misc/aw8622x_haptic/Makefile
Normal file
2
drivers/input/misc/aw8622x_haptic/Makefile
Normal file
@@ -0,0 +1,2 @@
|
||||
obj-$(CONFIG_INPUT_AW862XX_HAPTIC) += haptic.o
|
||||
haptic-objs := aw_haptic.o aw8622x.o aw8624.o
|
||||
4276
drivers/input/misc/aw8622x_haptic/aw8622x.c
Normal file
4276
drivers/input/misc/aw8622x_haptic/aw8622x.c
Normal file
File diff suppressed because it is too large
Load Diff
366
drivers/input/misc/aw8622x_haptic/aw8622x.h
Normal file
366
drivers/input/misc/aw8622x_haptic/aw8622x.h
Normal file
@@ -0,0 +1,366 @@
|
||||
/*********************************************************
|
||||
*
|
||||
|
||||
* aw8622x.h
|
||||
*
|
||||
********************************************************/
|
||||
#ifndef _AW8622X_H_
|
||||
#define _AW8622X_H_
|
||||
|
||||
|
||||
#include <linux/regmap.h>
|
||||
#include <linux/timer.h>
|
||||
#include <linux/workqueue.h>
|
||||
#include <linux/hrtimer.h>
|
||||
#include <linux/mutex.h>
|
||||
#include <linux/cdev.h>
|
||||
#include <linux/version.h>
|
||||
#include <linux/pm_wakeup.h>
|
||||
#include <linux/pm_wakeirq.h>
|
||||
#include <sound/control.h>
|
||||
#include <sound/soc.h>
|
||||
#include "haptic.h"
|
||||
#include <linux/timekeeping.h>
|
||||
/*********************************************************
|
||||
*
|
||||
* Marco
|
||||
*
|
||||
********************************************************/
|
||||
#if LINUX_VERSION_CODE <= KERNEL_VERSION(4, 4, 1)
|
||||
#define TIMED_OUTPUT
|
||||
#endif
|
||||
|
||||
#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 19, 1)
|
||||
#define AW_KERNEL_VER_OVER_4_19
|
||||
#endif
|
||||
|
||||
#ifdef TIMED_OUTPUT
|
||||
#include <../../../drivers/staging/android/timed_output.h>
|
||||
typedef struct timed_output_dev cdev_t;
|
||||
#else
|
||||
typedef struct led_classdev cdev_t;
|
||||
#endif
|
||||
|
||||
#define AW8622X_I2C_RETRIES (5)
|
||||
#define AW8622X_RTP_NAME_MAX (64)
|
||||
#define AW8622X_SEQUENCER_SIZE (8)
|
||||
#define AW8622X_SEQUENCER_LOOP_SIZE (4)
|
||||
#define AW8622X_OSC_CALI_MAX_LENGTH (11000000)
|
||||
#define AW8622X_PM_QOS_VALUE_VB (400)
|
||||
#define AW8622X_VBAT_REFER (4200)
|
||||
#define AW8622X_VBAT_MIN (3000)
|
||||
#define AW8622X_VBAT_MAX (5500)
|
||||
#define AW8622X_TRIG_NUM (3)
|
||||
#define AW8622X_I2C_RETRY_DELAY (2)
|
||||
|
||||
|
||||
// static int wf_s_repeat[4] = { 1, 2, 4, 8 };
|
||||
|
||||
enum aw8622x_flags {
|
||||
AW8622X_FLAG_NONR = 0,
|
||||
AW8622X_FLAG_SKIP_INTERRUPTS = 1,
|
||||
};
|
||||
|
||||
enum aw8622x_haptic_work_mode {
|
||||
AW8622X_HAPTIC_STANDBY_MODE = 0,
|
||||
AW8622X_HAPTIC_RAM_MODE = 1,
|
||||
AW8622X_HAPTIC_RTP_MODE = 2,
|
||||
AW8622X_HAPTIC_TRIG_MODE = 3,
|
||||
AW8622X_HAPTIC_CONT_MODE = 4,
|
||||
AW8622X_HAPTIC_RAM_LOOP_MODE = 5,
|
||||
};
|
||||
|
||||
enum aw8622x_haptic_activate_mode {
|
||||
AW8622X_HAPTIC_ACTIVATE_RAM_MODE = 0,
|
||||
AW8622X_HAPTIC_ACTIVATE_CONT_MODE = 1,
|
||||
AW8622X_HAPTIC_ACTIVATE_RTP_MODE = 2,
|
||||
AW8622X_HAPTIC_ACTIVATE_RAM_LOOP_MODE = 3,
|
||||
};
|
||||
|
||||
enum aw8622x_haptic_cont_vbat_comp_mode {
|
||||
AW8622X_HAPTIC_CONT_VBAT_SW_ADJUST_MODE = 0,
|
||||
AW8622X_HAPTIC_CONT_VBAT_HW_ADJUST_MODE = 1,
|
||||
};
|
||||
|
||||
enum aw8622x_haptic_ram_vbat_compensate_mode {
|
||||
AW8622X_HAPTIC_RAM_VBAT_COMP_DISABLE = 0,
|
||||
AW8622X_HAPTIC_RAM_VBAT_COMP_ENABLE = 1,
|
||||
};
|
||||
|
||||
enum aw8622x_haptic_f0_flag {
|
||||
AW8622X_HAPTIC_LRA_F0 = 0,
|
||||
AW8622X_HAPTIC_CALI_F0 = 1,
|
||||
};
|
||||
|
||||
enum aw8622x_sram_size_flag {
|
||||
AW8622X_HAPTIC_SRAM_1K = 0,
|
||||
AW8622X_HAPTIC_SRAM_2K = 1,
|
||||
AW8622X_HAPTIC_SRAM_3K = 2,
|
||||
};
|
||||
|
||||
enum aw8622x_haptic_pwm_mode {
|
||||
AW8622X_PWM_48K = 0,
|
||||
AW8622X_PWM_24K = 1,
|
||||
AW8622X_PWM_12K = 2,
|
||||
};
|
||||
|
||||
enum aw8622x_haptic_play {
|
||||
AW8622X_HAPTIC_PLAY_NULL = 0,
|
||||
AW8622X_HAPTIC_PLAY_ENABLE = 1,
|
||||
AW8622X_HAPTIC_PLAY_STOP = 2,
|
||||
AW8622X_HAPTIC_PLAY_GAIN = 8,
|
||||
};
|
||||
|
||||
enum aw8622x_haptic_cmd {
|
||||
AW8622X_HAPTIC_CMD_NULL = 0,
|
||||
AW8622X_HAPTIC_CMD_ENABLE = 1,
|
||||
AW8622X_HAPTIC_CMD_HAPTIC = 0x0f,
|
||||
AW8622X_HAPTIC_CMD_TP = 0x10,
|
||||
AW8622X_HAPTIC_CMD_SYS = 0xf0,
|
||||
AW8622X_HAPTIC_CMD_STOP = 255,
|
||||
};
|
||||
|
||||
enum aw8622x_haptic_cali_lra {
|
||||
AW8622X_WRITE_ZERO = 0,
|
||||
AW8622X_F0_CALI = 1,
|
||||
AW8622X_OSC_CALI = 2,
|
||||
};
|
||||
|
||||
enum aw8622x_haptic_rtp_mode {
|
||||
AW8622X_RTP_SHORT = 4,
|
||||
AW8622X_RTP_LONG = 5,
|
||||
AW8622X_RTP_SEGMENT = 6,
|
||||
};
|
||||
|
||||
enum aw8622x_ef_id {
|
||||
AW86223_EF_ID = 0x01,
|
||||
AW86224_5_EF_ID = 0x00,
|
||||
};
|
||||
|
||||
|
||||
|
||||
/*********************************************************
|
||||
*
|
||||
* Struct Define
|
||||
*
|
||||
********************************************************/
|
||||
|
||||
|
||||
/* trig_config
|
||||
* trig default high level
|
||||
* ___________ ___________
|
||||
* | |
|
||||
* | |
|
||||
* |___________|
|
||||
* first edge
|
||||
* second edge
|
||||
*
|
||||
* trig default low level
|
||||
* ___________
|
||||
* | |
|
||||
* | |
|
||||
* __________| |__________
|
||||
* first edge
|
||||
* second edge
|
||||
******************** vib_trig_config *********************
|
||||
* level polar pos_en pos_seq neg_en neg_seq brk bst
|
||||
trig1* 1 0 1 1 1 2 0 0
|
||||
trig2* 1 0 0 1 0 2 0 0
|
||||
trig3* 1 0 0 1 0 2 0 0
|
||||
*/
|
||||
|
||||
|
||||
struct aw8622x_dts_info {
|
||||
unsigned int mode;
|
||||
unsigned int f0_ref;
|
||||
unsigned int f0_cali_percent;
|
||||
unsigned int cont_drv1_lvl_dt;
|
||||
unsigned int cont_drv2_lvl_dt;
|
||||
unsigned int cont_drv1_time_dt;
|
||||
unsigned int cont_drv2_time_dt;
|
||||
unsigned int cont_wait_num_dt;
|
||||
unsigned int cont_brk_time_dt;
|
||||
unsigned int cont_track_margin;
|
||||
unsigned int cont_tset;
|
||||
unsigned int cont_drv_width;
|
||||
unsigned int cont_bemf_set;
|
||||
unsigned int cont_brk_gain;
|
||||
unsigned int d2s_gain;
|
||||
unsigned int prctmode[3];
|
||||
unsigned int sine_array[4];
|
||||
unsigned int trig_config[24];
|
||||
unsigned int effect_id_boundary;
|
||||
unsigned int effect_max;
|
||||
unsigned int rtp_time[194];
|
||||
bool is_enabled_powerup_f0_cali;
|
||||
bool is_enabled_auto_bst;
|
||||
};
|
||||
|
||||
struct aw8622x_trig {
|
||||
unsigned char trig_level;
|
||||
unsigned char trig_polar;
|
||||
unsigned char pos_enable;
|
||||
unsigned char pos_sequence;
|
||||
unsigned char neg_enable;
|
||||
unsigned char neg_sequence;
|
||||
unsigned char trig_brk;
|
||||
};
|
||||
|
||||
struct aw8622x {
|
||||
struct regmap *regmap;
|
||||
struct i2c_client *i2c;
|
||||
|
||||
/*struct snd_soc_codec *codec; */
|
||||
struct device *dev;
|
||||
struct input_dev *input;
|
||||
struct mutex lock;
|
||||
struct mutex rtp_lock;
|
||||
struct hrtimer timer;
|
||||
struct work_struct long_vibrate_work;
|
||||
struct work_struct rtp_work;
|
||||
struct work_struct set_gain_work;
|
||||
struct delayed_work ram_work;
|
||||
struct delayed_work stop_work;
|
||||
struct aw8622x_trig trig[AW8622X_TRIG_NUM];
|
||||
struct aw8622x_dts_info dts_info;
|
||||
struct fileops fileops;
|
||||
struct ram ram;
|
||||
struct timespec64 start, end;
|
||||
struct aw8622x_container *rtp_container;
|
||||
|
||||
cdev_t vib_dev;
|
||||
|
||||
bool haptic_ready;
|
||||
|
||||
unsigned char seq[AW8622X_SEQUENCER_SIZE];
|
||||
unsigned char loop[AW8622X_SEQUENCER_SIZE];
|
||||
unsigned char rtp_init;
|
||||
unsigned char ram_init;
|
||||
unsigned char rtp_routine_on;
|
||||
unsigned char max_pos_beme;
|
||||
unsigned char max_neg_beme;
|
||||
unsigned char f0_cali_flag;
|
||||
unsigned char ram_vbat_compensate;
|
||||
unsigned char hwen_flag;
|
||||
unsigned char flags;
|
||||
unsigned char chipid;
|
||||
unsigned char play_mode;
|
||||
unsigned char activate_mode;
|
||||
unsigned char ram_state;
|
||||
|
||||
unsigned char wk_lock_flag;
|
||||
|
||||
bool isUsedIntn;
|
||||
|
||||
int name;
|
||||
int reset_gpio;
|
||||
int irq_gpio;
|
||||
int state;
|
||||
int duration;
|
||||
int amplitude;
|
||||
int index;
|
||||
int vmax;
|
||||
int gain;
|
||||
int sysclk;
|
||||
int rate;
|
||||
int width;
|
||||
int pstream;
|
||||
int cstream;
|
||||
|
||||
unsigned int gun_type;
|
||||
unsigned int bullet_nr;
|
||||
unsigned int rtp_cnt;
|
||||
unsigned int rtp_file_num;
|
||||
unsigned int f0;
|
||||
unsigned int cont_f0;
|
||||
unsigned int cont_drv1_lvl;
|
||||
unsigned int cont_drv2_lvl;
|
||||
unsigned int cont_brk_time;
|
||||
unsigned int cont_wait_num;
|
||||
unsigned int cont_drv1_time;
|
||||
unsigned int cont_drv2_time;
|
||||
unsigned int theory_time;
|
||||
unsigned int vbat;
|
||||
unsigned int lra;
|
||||
unsigned int ram_update_flag;
|
||||
unsigned int rtp_update_flag;
|
||||
unsigned int osc_cali_data;
|
||||
unsigned int f0_cali_data;
|
||||
unsigned int timeval_flags;
|
||||
unsigned int osc_cali_flag;
|
||||
unsigned int sys_frequency;
|
||||
unsigned int rtp_len;
|
||||
unsigned long int microsecond;
|
||||
|
||||
u16 new_gain;
|
||||
unsigned char level;
|
||||
struct haptic_audio haptic_audio;
|
||||
unsigned int osc_cali_run;
|
||||
unsigned char ram_vbat_comp;
|
||||
atomic_t is_in_rtp_loop;
|
||||
atomic_t exit_in_rtp_loop;
|
||||
wait_queue_head_t wait_q;
|
||||
wait_queue_head_t stop_wait_q;
|
||||
struct workqueue_struct *work_queue;
|
||||
struct work_struct vibrator_work;
|
||||
/* ram monitor */
|
||||
#ifdef AW_RAM_STATE_OUTPUT
|
||||
struct delayed_work ram_monitor_work;
|
||||
#endif
|
||||
#ifdef INPUT_DEV
|
||||
struct platform_device *pdev;
|
||||
struct input_dev *input_dev;
|
||||
struct pwm_device *pwm_dev;
|
||||
struct qti_hap_config config;
|
||||
struct qti_hap_play_info play;
|
||||
struct qti_hap_effect *predefined;
|
||||
struct qti_hap_effect constant;
|
||||
struct regulator *vdd_supply;
|
||||
struct hrtimer stop_timer;
|
||||
struct hrtimer hap_disable_timer;
|
||||
spinlock_t bus_lock;
|
||||
ktime_t last_sc_time;
|
||||
int play_irq;
|
||||
int sc_irq;
|
||||
int effects_count;
|
||||
int sc_det_count;
|
||||
u16 reg_base;
|
||||
bool perm_disable;
|
||||
bool play_irq_en;
|
||||
bool vdd_enabled;
|
||||
int effect_type;
|
||||
int effect_id;
|
||||
int test_val;
|
||||
#endif
|
||||
};
|
||||
|
||||
struct aw8622x_container {
|
||||
int len;
|
||||
unsigned char data[];
|
||||
};
|
||||
/*********************************************************
|
||||
*
|
||||
* extern
|
||||
*
|
||||
********************************************************/
|
||||
extern char aw8622x_check_qualify(struct aw8622x *aw8622x);
|
||||
|
||||
extern int aw8622x_parse_dt(struct device *dev, struct aw8622x *aw8622x,
|
||||
struct device_node *np);
|
||||
extern void aw8622x_interrupt_setup(struct aw8622x *aw8622x);
|
||||
extern int aw8622x_vibrator_init(struct aw8622x *aw8622x);
|
||||
extern int aw8622x_haptic_init(struct aw8622x *aw8622x);
|
||||
extern int aw8622x_ram_work_init(struct aw8622x *aw8622x);
|
||||
extern irqreturn_t aw8622x_irq(int irq, void *data);
|
||||
extern struct attribute_group aw8622x_vibrator_attribute_group;
|
||||
extern void aw8622x_haptics_set_gain(struct input_dev *dev, u16 gain);
|
||||
extern int aw8622x_haptics_erase(struct input_dev *dev, int effect_id);
|
||||
extern int aw8622x_haptics_playback(struct input_dev *dev, int effect_id,
|
||||
int val);
|
||||
extern int aw8622x_haptics_upload_effect (struct input_dev *dev,
|
||||
struct ff_effect *effect,
|
||||
struct ff_effect *old);
|
||||
extern void aw8622x_haptics_set_gain_work_routine(struct work_struct *work);
|
||||
|
||||
|
||||
#endif
|
||||
856
drivers/input/misc/aw8622x_haptic/aw8622x_reg.h
Normal file
856
drivers/input/misc/aw8622x_haptic/aw8622x_reg.h
Normal file
@@ -0,0 +1,856 @@
|
||||
/*********************************************************
|
||||
*
|
||||
* aw8622x_reg.h
|
||||
*
|
||||
********************************************************/
|
||||
#ifndef _AW8622X_REG_H_
|
||||
#define _AW8622X_REG_H_
|
||||
|
||||
/********************************************
|
||||
* Register List
|
||||
*******************************************/
|
||||
#define AW8622X_REG_ID (0x00)
|
||||
#define AW8622X_REG_SYSST (0x01)
|
||||
#define AW8622X_REG_SYSINT (0x02)
|
||||
#define AW8622X_REG_SYSINTM (0x03)
|
||||
#define AW8622X_REG_SYSST2 (0x04)
|
||||
#define AW8622X_REG_SYSER (0x05)
|
||||
#define AW8622X_REG_PLAYCFG2 (0x07)
|
||||
#define AW8622X_REG_PLAYCFG3 (0x08)
|
||||
#define AW8622X_REG_PLAYCFG4 (0x09)
|
||||
#define AW8622X_REG_WAVCFG1 (0x0A)
|
||||
#define AW8622X_REG_WAVCFG2 (0x0B)
|
||||
#define AW8622X_REG_WAVCFG3 (0x0C)
|
||||
#define AW8622X_REG_WAVCFG4 (0x0D)
|
||||
#define AW8622X_REG_WAVCFG5 (0x0E)
|
||||
#define AW8622X_REG_WAVCFG6 (0x0F)
|
||||
#define AW8622X_REG_WAVCFG7 (0x10)
|
||||
#define AW8622X_REG_WAVCFG8 (0x11)
|
||||
#define AW8622X_REG_WAVCFG9 (0x12)
|
||||
#define AW8622X_REG_WAVCFG10 (0x13)
|
||||
#define AW8622X_REG_WAVCFG11 (0x14)
|
||||
#define AW8622X_REG_WAVCFG12 (0x15)
|
||||
#define AW8622X_REG_WAVCFG13 (0x16)
|
||||
#define AW8622X_REG_WAVCFG14 (0x17)
|
||||
#define AW8622X_REG_CONTCFG1 (0x18)
|
||||
#define AW8622X_REG_CONTCFG2 (0x19)
|
||||
#define AW8622X_REG_CONTCFG3 (0x1A)
|
||||
#define AW8622X_REG_CONTCFG4 (0x1B)
|
||||
#define AW8622X_REG_CONTCFG5 (0x1C)
|
||||
#define AW8622X_REG_CONTCFG6 (0x1D)
|
||||
#define AW8622X_REG_CONTCFG7 (0x1E)
|
||||
#define AW8622X_REG_CONTCFG8 (0x1F)
|
||||
#define AW8622X_REG_CONTCFG9 (0x20)
|
||||
#define AW8622X_REG_CONTCFG10 (0x21)
|
||||
#define AW8622X_REG_CONTCFG11 (0x22)
|
||||
#define AW8622X_REG_CONTCFG12 (0x23)
|
||||
#define AW8622X_REG_CONTCFG13 (0x24)
|
||||
#define AW8622X_REG_CONTRD14 (0x25)
|
||||
#define AW8622X_REG_CONTRD15 (0x26)
|
||||
#define AW8622X_REG_CONTRD16 (0x27)
|
||||
#define AW8622X_REG_CONTRD17 (0x28)
|
||||
#define AW8622X_REG_CONTRD18 (0x29)
|
||||
#define AW8622X_REG_CONTRD19 (0x2A)
|
||||
#define AW8622X_REG_CONTRD20 (0x2B)
|
||||
#define AW8622X_REG_CONTRD21 (0x2C)
|
||||
#define AW8622X_REG_RTPCFG1 (0x2D)
|
||||
#define AW8622X_REG_RTPCFG2 (0x2E)
|
||||
#define AW8622X_REG_RTPCFG3 (0x2F)
|
||||
#define AW8622X_REG_RTPCFG4 (0x30)
|
||||
#define AW8622X_REG_RTPCFG5 (0x31)
|
||||
#define AW8622X_REG_RTPDATA (0x32)
|
||||
#define AW8622X_REG_TRGCFG1 (0x33)
|
||||
#define AW8622X_REG_TRGCFG2 (0x34)
|
||||
#define AW8622X_REG_TRGCFG3 (0x35)
|
||||
#define AW8622X_REG_TRGCFG4 (0x36)
|
||||
#define AW8622X_REG_TRGCFG5 (0x37)
|
||||
#define AW8622X_REG_TRGCFG6 (0x38)
|
||||
#define AW8622X_REG_TRGCFG7 (0x39)
|
||||
#define AW8622X_REG_TRGCFG8 (0x3A)
|
||||
#define AW8622X_REG_GLBCFG1 (0x3B)
|
||||
#define AW8622X_REG_GLBCFG2 (0x3C)
|
||||
#define AW8622X_REG_GLBCFG3 (0x3D)
|
||||
#define AW8622X_REG_GLBCFG4 (0x3E)
|
||||
#define AW8622X_REG_GLBRD5 (0x3F)
|
||||
#define AW8622X_REG_RAMADDRH (0x40)
|
||||
#define AW8622X_REG_RAMADDRL (0x41)
|
||||
#define AW8622X_REG_RAMDATA (0x42)
|
||||
#define AW8622X_REG_SYSCTRL1 (0x43)
|
||||
#define AW8622X_REG_SYSCTRL2 (0x44)
|
||||
#define AW8622X_REG_SYSCTRL3 (0x45)
|
||||
#define AW8622X_REG_SYSCTRL4 (0x46)
|
||||
#define AW8622X_REG_SYSCTRL5 (0x47)
|
||||
#define AW8622X_REG_SYSCTRL6 (0x48)
|
||||
#define AW8622X_REG_SYSCTRL7 (0x49)
|
||||
#define AW8622X_REG_PWMCFG1 (0x4C)
|
||||
#define AW8622X_REG_PWMCFG2 (0x4D)
|
||||
#define AW8622X_REG_PWMCFG3 (0x4E)
|
||||
#define AW8622X_REG_PWMCFG4 (0x4F)
|
||||
#define AW8622X_REG_TMCFG (0x50)
|
||||
#define AW8622X_REG_DETCFG1 (0x51)
|
||||
#define AW8622X_REG_DETCFG2 (0x52)
|
||||
#define AW8622X_REG_DET_RL (0x53)
|
||||
#define AW8622X_REG_DET_OS (0x54)
|
||||
#define AW8622X_REG_DET_VBAT (0x55)
|
||||
#define AW8622X_REG_DET_TEST (0x56)
|
||||
#define AW8622X_REG_DET_LO (0x57)
|
||||
#define AW8622X_REG_TRIMCFG1 (0x58)
|
||||
#define AW8622X_REG_TRIMCFG3 (0x5A)
|
||||
#define AW8622X_REG_TRIMCFG4 (0x5B)
|
||||
#define AW8622X_REG_EFCFG1 (0x5C)
|
||||
#define AW8622X_REG_EFCFG2 (0x5D)
|
||||
#define AW8622X_REG_EFCFG3 (0x5E)
|
||||
#define AW8622X_REG_EFCFG4 (0x5F)
|
||||
#define AW8622X_REG_EFCFG5 (0x60)
|
||||
#define AW8622X_REG_EFCFG6 (0x61)
|
||||
#define AW8622X_REG_EFRD9 (0x64)
|
||||
#define AW8622X_REG_EFRD10 (0x65)
|
||||
#define AW8622X_REG_ANACFG1 (0x6A)
|
||||
#define AW8622X_REG_ANACFG2 (0x6B)
|
||||
#define AW8622X_REG_ANACFG3 (0x6C)
|
||||
#define AW8622X_REG_ANACFG4 (0x73)
|
||||
#define AW8622X_REG_ANACFG5 (0x74)
|
||||
#define AW8622X_REG_ANACFG6 (0x75)
|
||||
#define AW8622X_REG_ANACFG7 (0x76)
|
||||
#define AW8622X_REG_ANACFG8 (0x77)
|
||||
#define AW8622X_REG_SPACE (0x78)
|
||||
#define AW8622X_REG_MBIST (0x79)
|
||||
|
||||
/********************************************
|
||||
* Register Access
|
||||
*******************************************/
|
||||
#define REG_NONE_ACCESS (0)
|
||||
#define REG_RD_ACCESS (1 << 0)
|
||||
#define REG_WR_ACCESS (1 << 1)
|
||||
#define AW8622X_REG_MAX 0xff
|
||||
const unsigned char aw8622x_reg_access[AW8622X_REG_MAX] = {
|
||||
[AW8622X_REG_ID] = REG_RD_ACCESS,
|
||||
[AW8622X_REG_SYSST] = REG_RD_ACCESS,
|
||||
[AW8622X_REG_SYSINT] = REG_RD_ACCESS,
|
||||
[AW8622X_REG_SYSINTM] = REG_RD_ACCESS | REG_WR_ACCESS,
|
||||
[AW8622X_REG_SYSST2] = REG_RD_ACCESS,
|
||||
[AW8622X_REG_SYSER] = REG_RD_ACCESS,
|
||||
[AW8622X_REG_PLAYCFG2] = REG_RD_ACCESS | REG_WR_ACCESS,
|
||||
[AW8622X_REG_PLAYCFG3] = REG_RD_ACCESS | REG_WR_ACCESS,
|
||||
[AW8622X_REG_PLAYCFG4] = REG_RD_ACCESS | REG_WR_ACCESS,
|
||||
[AW8622X_REG_WAVCFG1] = REG_RD_ACCESS | REG_WR_ACCESS,
|
||||
[AW8622X_REG_WAVCFG2] = REG_RD_ACCESS | REG_WR_ACCESS,
|
||||
[AW8622X_REG_WAVCFG3] = REG_RD_ACCESS | REG_WR_ACCESS,
|
||||
[AW8622X_REG_WAVCFG4] = REG_RD_ACCESS | REG_WR_ACCESS,
|
||||
[AW8622X_REG_WAVCFG5] = REG_RD_ACCESS | REG_WR_ACCESS,
|
||||
[AW8622X_REG_WAVCFG6] = REG_RD_ACCESS | REG_WR_ACCESS,
|
||||
[AW8622X_REG_WAVCFG7] = REG_RD_ACCESS | REG_WR_ACCESS,
|
||||
[AW8622X_REG_WAVCFG8] = REG_RD_ACCESS | REG_WR_ACCESS,
|
||||
[AW8622X_REG_WAVCFG9] = REG_RD_ACCESS | REG_WR_ACCESS,
|
||||
[AW8622X_REG_WAVCFG10] = REG_RD_ACCESS | REG_WR_ACCESS,
|
||||
[AW8622X_REG_WAVCFG11] = REG_RD_ACCESS | REG_WR_ACCESS,
|
||||
[AW8622X_REG_WAVCFG12] = REG_RD_ACCESS | REG_WR_ACCESS,
|
||||
[AW8622X_REG_WAVCFG13] = REG_RD_ACCESS | REG_WR_ACCESS,
|
||||
[AW8622X_REG_WAVCFG14] = REG_RD_ACCESS | REG_WR_ACCESS,
|
||||
[AW8622X_REG_CONTCFG1] = REG_RD_ACCESS | REG_WR_ACCESS,
|
||||
[AW8622X_REG_CONTCFG2] = REG_RD_ACCESS | REG_WR_ACCESS,
|
||||
[AW8622X_REG_CONTCFG3] = REG_RD_ACCESS | REG_WR_ACCESS,
|
||||
[AW8622X_REG_CONTCFG4] = REG_RD_ACCESS | REG_WR_ACCESS,
|
||||
[AW8622X_REG_CONTCFG5] = REG_RD_ACCESS | REG_WR_ACCESS,
|
||||
[AW8622X_REG_CONTCFG6] = REG_RD_ACCESS | REG_WR_ACCESS,
|
||||
[AW8622X_REG_CONTCFG7] = REG_RD_ACCESS | REG_WR_ACCESS,
|
||||
[AW8622X_REG_CONTCFG8] = REG_RD_ACCESS | REG_WR_ACCESS,
|
||||
[AW8622X_REG_CONTCFG9] = REG_RD_ACCESS | REG_WR_ACCESS,
|
||||
[AW8622X_REG_CONTCFG10] = REG_RD_ACCESS | REG_WR_ACCESS,
|
||||
[AW8622X_REG_CONTCFG11] = REG_RD_ACCESS | REG_WR_ACCESS,
|
||||
[AW8622X_REG_CONTCFG12] = REG_RD_ACCESS | REG_WR_ACCESS,
|
||||
[AW8622X_REG_CONTCFG13] = REG_RD_ACCESS | REG_WR_ACCESS,
|
||||
[AW8622X_REG_CONTRD14] = REG_RD_ACCESS,
|
||||
[AW8622X_REG_CONTRD15] = REG_RD_ACCESS,
|
||||
[AW8622X_REG_CONTRD16] = REG_RD_ACCESS,
|
||||
[AW8622X_REG_CONTRD17] = REG_RD_ACCESS,
|
||||
[AW8622X_REG_CONTRD18] = REG_RD_ACCESS,
|
||||
[AW8622X_REG_CONTRD19] = REG_RD_ACCESS,
|
||||
[AW8622X_REG_CONTRD20] = REG_RD_ACCESS,
|
||||
[AW8622X_REG_CONTRD21] = REG_RD_ACCESS,
|
||||
[AW8622X_REG_RTPCFG1] = REG_RD_ACCESS | REG_WR_ACCESS,
|
||||
[AW8622X_REG_RTPCFG2] = REG_RD_ACCESS | REG_WR_ACCESS,
|
||||
[AW8622X_REG_RTPCFG3] = REG_RD_ACCESS | REG_WR_ACCESS,
|
||||
[AW8622X_REG_RTPCFG4] = REG_RD_ACCESS | REG_WR_ACCESS,
|
||||
[AW8622X_REG_RTPCFG5] = REG_RD_ACCESS | REG_WR_ACCESS,
|
||||
[AW8622X_REG_RTPDATA] = REG_RD_ACCESS | REG_WR_ACCESS,
|
||||
[AW8622X_REG_TRGCFG1] = REG_RD_ACCESS | REG_WR_ACCESS,
|
||||
[AW8622X_REG_TRGCFG2] = REG_RD_ACCESS | REG_WR_ACCESS,
|
||||
[AW8622X_REG_TRGCFG3] = REG_RD_ACCESS | REG_WR_ACCESS,
|
||||
[AW8622X_REG_TRGCFG4] = REG_RD_ACCESS | REG_WR_ACCESS,
|
||||
[AW8622X_REG_TRGCFG5] = REG_RD_ACCESS | REG_WR_ACCESS,
|
||||
[AW8622X_REG_TRGCFG6] = REG_RD_ACCESS | REG_WR_ACCESS,
|
||||
[AW8622X_REG_TRGCFG7] = REG_RD_ACCESS | REG_WR_ACCESS,
|
||||
[AW8622X_REG_TRGCFG8] = REG_RD_ACCESS | REG_WR_ACCESS,
|
||||
[AW8622X_REG_GLBCFG1] = REG_RD_ACCESS | REG_WR_ACCESS,
|
||||
[AW8622X_REG_GLBCFG2] = REG_RD_ACCESS | REG_WR_ACCESS,
|
||||
[AW8622X_REG_GLBCFG3] = REG_RD_ACCESS | REG_WR_ACCESS,
|
||||
[AW8622X_REG_GLBCFG4] = REG_RD_ACCESS | REG_WR_ACCESS,
|
||||
[AW8622X_REG_GLBRD5] = REG_RD_ACCESS,
|
||||
[AW8622X_REG_RAMADDRH] = REG_RD_ACCESS | REG_WR_ACCESS,
|
||||
[AW8622X_REG_RAMADDRL] = REG_RD_ACCESS | REG_WR_ACCESS,
|
||||
[AW8622X_REG_RAMDATA] = REG_RD_ACCESS | REG_WR_ACCESS,
|
||||
[AW8622X_REG_SYSCTRL1] = REG_RD_ACCESS | REG_WR_ACCESS,
|
||||
[AW8622X_REG_SYSCTRL2] = REG_RD_ACCESS | REG_WR_ACCESS,
|
||||
[AW8622X_REG_SYSCTRL3] = REG_RD_ACCESS | REG_WR_ACCESS,
|
||||
[AW8622X_REG_SYSCTRL4] = REG_RD_ACCESS | REG_WR_ACCESS,
|
||||
[AW8622X_REG_SYSCTRL5] = REG_RD_ACCESS | REG_WR_ACCESS,
|
||||
[AW8622X_REG_SYSCTRL6] = REG_RD_ACCESS | REG_WR_ACCESS,
|
||||
[AW8622X_REG_SYSCTRL7] = REG_RD_ACCESS | REG_WR_ACCESS,
|
||||
[AW8622X_REG_PWMCFG1] = REG_RD_ACCESS | REG_WR_ACCESS,
|
||||
[AW8622X_REG_PWMCFG2] = REG_RD_ACCESS | REG_WR_ACCESS,
|
||||
[AW8622X_REG_PWMCFG3] = REG_RD_ACCESS | REG_WR_ACCESS,
|
||||
[AW8622X_REG_PWMCFG4] = REG_RD_ACCESS | REG_WR_ACCESS,
|
||||
[AW8622X_REG_DETCFG1] = REG_RD_ACCESS | REG_WR_ACCESS,
|
||||
[AW8622X_REG_DETCFG2] = REG_RD_ACCESS | REG_WR_ACCESS,
|
||||
[AW8622X_REG_DET_RL] = REG_RD_ACCESS,
|
||||
[AW8622X_REG_DET_OS] = REG_RD_ACCESS,
|
||||
[AW8622X_REG_DET_VBAT] = REG_RD_ACCESS,
|
||||
[AW8622X_REG_DET_TEST] = REG_RD_ACCESS,
|
||||
[AW8622X_REG_DET_LO] = REG_RD_ACCESS,
|
||||
[AW8622X_REG_TRIMCFG1] = REG_RD_ACCESS | REG_WR_ACCESS,
|
||||
[AW8622X_REG_TRIMCFG3] = REG_RD_ACCESS | REG_WR_ACCESS,
|
||||
[AW8622X_REG_TRIMCFG4] = REG_RD_ACCESS | REG_WR_ACCESS,
|
||||
};
|
||||
|
||||
/******************************************************
|
||||
* Register Detail
|
||||
*****************************************************/
|
||||
/* SYSST: reg 0x01 RO */
|
||||
#define AW8622X_BIT_SYSST_UVLS (1<<5)
|
||||
#define AW8622X_BIT_SYSST_FF_AES (1<<4)
|
||||
#define AW8622X_BIT_SYSST_FF_AFS (1<<3)
|
||||
#define AW8622X_BIT_SYSST_OCDS (1<<2)
|
||||
#define AW8622X_BIT_SYSST_OTS (1<<1)
|
||||
#define AW8622X_BIT_SYSST_DONES (1<<0)
|
||||
|
||||
/* SYSINT: reg 0x02 RC */
|
||||
#define AW8622X_BIT_SYSINT_UVLI (1<<5)
|
||||
#define AW8622X_BIT_SYSINT_FF_AEI (1<<4)
|
||||
#define AW8622X_BIT_SYSINT_FF_AFI (1<<3)
|
||||
#define AW8622X_BIT_SYSINT_OCDI (1<<2)
|
||||
#define AW8622X_BIT_SYSINT_OTI (1<<1)
|
||||
#define AW8622X_BIT_SYSINT_DONEI (1<<0)
|
||||
|
||||
/* SYSINTM: reg 0x03 RW */
|
||||
#define AW8622X_BIT_SYSINTM_UVLM_MASK (~(1<<5))
|
||||
#define AW8622X_BIT_SYSINTM_UVLM_OFF (1<<5)
|
||||
#define AW8622X_BIT_SYSINTM_UVLM_ON (0<<5)
|
||||
#define AW8622X_BIT_SYSINTM_FF_AEM_MASK (~(1<<4))
|
||||
#define AW8622X_BIT_SYSINTM_FF_AEM_OFF (1<<4)
|
||||
#define AW8622X_BIT_SYSINTM_FF_AEM_ON (0<<4)
|
||||
#define AW8622X_BIT_SYSINTM_FF_AFM_MASK (~(1<<3))
|
||||
#define AW8622X_BIT_SYSINTM_FF_AFM_OFF (1<<3)
|
||||
#define AW8622X_BIT_SYSINTM_FF_AFM_ON (0<<3)
|
||||
#define AW8622X_BIT_SYSINTM_OCDM_MASK (~(1<<2))
|
||||
#define AW8622X_BIT_SYSINTM_OCDM_OFF (1<<2)
|
||||
#define AW8622X_BIT_SYSINTM_OCDM_ON (0<<2)
|
||||
#define AW8622X_BIT_SYSINTM_OTM_MASK (~(1<<1))
|
||||
#define AW8622X_BIT_SYSINTM_OTM_OFF (1<<1)
|
||||
#define AW8622X_BIT_SYSINTM_OTM_ON (0<<1)
|
||||
#define AW8622X_BIT_SYSINTM_DONEM_MASK (~(1<<0))
|
||||
#define AW8622X_BIT_SYSINTM_DONEM_OFF (1<<0)
|
||||
#define AW8622X_BIT_SYSINTM_DONEM_ON (0<<0)
|
||||
|
||||
/* SYSST2: reg 0x04 RO */
|
||||
#define AW8622X_BIT_SYSST2_RAM_ADDR_ER (1<<7)
|
||||
#define AW8622X_BIT_SYSST2_TRG_ADDR_ER (1<<6)
|
||||
#define AW8622X_BIT_SYSST2_VBG_OK (1<<3)
|
||||
#define AW8622X_BIT_SYSST2_LDO_OK (1<<2)
|
||||
#define AW8622X_BIT_SYSST2_FF_FULL (1<<1)
|
||||
#define AW8622X_BIT_SYSST2_FF_EMPTY (1<<0)
|
||||
|
||||
/* SYSER: reg 0x05 RC */
|
||||
#define AW8622X_BIT_SYSER_I2S_ERR (1<<7)
|
||||
#define AW8622X_BIT_SYSER_TRIG1_EVENT (1<<6)
|
||||
#define AW8622X_BIT_SYSER_TRIG2_EVENT (1<<5)
|
||||
#define AW8622X_BIT_SYSER_TRIG3_EVENT (1<<4)
|
||||
#define AW8622X_BIT_SYSER_OV (1<<3)
|
||||
#define AW8622X_BIT_SYSER_ADDR_ER (1<<2)
|
||||
#define AW8622X_BIT_SYSER_FF_ER (1<<1)
|
||||
#define AW8622X_BIT_SYSER_PLL_REF_ER (1<<0)
|
||||
|
||||
|
||||
/* PLAYCFG2: reg 0x07 RW */
|
||||
/* GAIN */
|
||||
|
||||
/* PLAYCFG3: reg 0x08 RW */
|
||||
#define AW8622X_BIT_PLAYCFG3_STOP_MODE_MASK (~(1<<5))
|
||||
#define AW8622X_BIT_PLAYCFG3_STOP_MODE_NOW (1<<5)
|
||||
#define AW8622X_BIT_PLAYCFG3_STOP_MODE_LATER (0<<5)
|
||||
#define AW8622X_BIT_PLAYCFG3_BRK_EN_MASK (~(1<<2))
|
||||
#define AW8622X_BIT_PLAYCFG3_BRK_ENABLE (1<<2)
|
||||
#define AW8622X_BIT_PLAYCFG3_BRK_DISABLE (0<<2)
|
||||
#define AW8622X_BIT_PLAYCFG3_PLAY_MODE_MASK (~(3<<0))
|
||||
#define AW8622X_BIT_PLAYCFG3_PLAY_MODE_STOP (3<<0)
|
||||
#define AW8622X_BIT_PLAYCFG3_PLAY_MODE_CONT (2<<0)
|
||||
#define AW8622X_BIT_PLAYCFG3_PLAY_MODE_RTP (1<<0)
|
||||
#define AW8622X_BIT_PLAYCFG3_PLAY_MODE_RAM (0<<0)
|
||||
|
||||
/* PLAYCFG4: reg 0x09 RW */
|
||||
#define AW8622X_BIT_PLAYCFG4_STOP_MASK (~(1<<1))
|
||||
#define AW8622X_BIT_PLAYCFG4_STOP_ON (1<<1)
|
||||
#define AW8622X_BIT_PLAYCFG4_STOP_OFF (0<<1)
|
||||
#define AW8622X_BIT_PLAYCFG4_GO_MASK (~(1<<0))
|
||||
#define AW8622X_BIT_PLAYCFG4_GO_ON (1<<0)
|
||||
#define AW8622X_BIT_PLAYCFG4_GO_OFF (0<<0)
|
||||
|
||||
/* WAVCFG1-8: reg 0x0A - reg 0x11 RW */
|
||||
#define AW8622X_BIT_WAVCFG_SEQWAIT_MASK (~(1<<7))
|
||||
#define AW8622X_BIT_WAVCFG_SEQWAIT_TIME (1<<7)
|
||||
#define AW8622X_BIT_WAVCFG_SEQWAIT_NUMBER (0<<7)
|
||||
|
||||
/* WAVCFG9-12: reg 0x12 - reg 0x15 RW */
|
||||
#define AW8622X_BIT_WAVLOOP_SEQ_ODD_MASK (~(0x0F<<4))
|
||||
#define AW8622X_BIT_WAVLOOP_SEQ_ODD_INIFINITELY (0x0F<<4)
|
||||
#define AW8622X_BIT_WAVLOOP_SEQ_EVEN_MASK (~(0x0F<<0))
|
||||
#define AW8622X_BIT_WAVLOOP_SEQ_EVEN_INIFINITELY (0x0F<<0)
|
||||
#define AW8622X_BIT_WAVLOOP_INIFINITELY (0x0F<<0)
|
||||
|
||||
/* WAVCFG9: reg 0x12 RW */
|
||||
#define AW8622X_BIT_WAVCFG9_SEQ1LOOP_MASK (~(0x0F<<4))
|
||||
#define AW8622X_BIT_WAVCFG9_SEQ1LOOP_INIFINITELY (0x0F<<4)
|
||||
#define AW8622X_BIT_WAVCFG9_SEQ2LOOP_MASK (~(0x0F<<0))
|
||||
#define AW8622X_BIT_WAVCFG9_SEQ2LOOP_INIFINITELY (0x0F<<0)
|
||||
|
||||
/* WAVCFG10: reg 0x13 RW */
|
||||
#define AW8622X_BIT_WAVCFG10_SEQ3LOOP_MASK (~(0x0F<<4))
|
||||
#define AW8622X_BIT_WAVCFG10_SEQ3LOOP_INIFINITELY (0x0F<<4)
|
||||
#define AW8622X_BIT_WAVCFG10_SEQ4LOOP_MASK (~(0x0F<<0))
|
||||
#define AW8622X_BIT_WAVCFG10_SEQ4LOOP_INIFINITELY (0x0F<<0)
|
||||
|
||||
/* WAVCFG11: reg 0x14 RW */
|
||||
#define AW8622X_BIT_WAVCFG11_SEQ5LOOP_MASK (~(0x0F<<4))
|
||||
#define AW8622X_BIT_WAVCFG11_SEQ5LOOP_INIFINITELY (0x0F<<4)
|
||||
#define AW8622X_BIT_WAVCFG11_SEQ6LOOP_MASK (~(0x0F<<0))
|
||||
#define AW8622X_BIT_WAVCFG11_SEQ6LOOP_INIFINITELY (0x0F<<0)
|
||||
|
||||
/* WAVCFG12: reg 0x15 RW */
|
||||
#define AW8622X_BIT_WAVCFG12_SEQ7LOOP_MASK (~(0x0F<<4))
|
||||
#define AW8622X_BIT_WAVCFG12_SEQ7LOOP_INIFINITELY (0x0F<<4)
|
||||
#define AW8622X_BIT_WAVCFG12_SEQ8LOOP_MASK (~(0x0F<<0))
|
||||
#define AW8622X_BIT_WAVCFG12_SEQ8LOOP_INIFINITELY (0x0F<<0)
|
||||
|
||||
/* WAVCFG13: reg 0x16 RW */
|
||||
#define AW8622X_BIT_WAVCFG13_WAITSLOT_MASK (~(3<<5))
|
||||
#define AW8622X_BIT_WAVCFG13_WAITSLOT_DIV_1 (0<<5)
|
||||
#define AW8622X_BIT_WAVCFG13_WAITSLOT_DIV_8 (1<<5)
|
||||
#define AW8622X_BIT_WAVCFG13_WAITSLOT_DIV_64 (2<<5)
|
||||
#define AW8622X_BIT_WAVCFG13_WAITSLOT_DIV_512 (3<<5)
|
||||
#define AW8622X_BIT_WAVCFG13_AUTO_MD_MASK (~(1<<4))
|
||||
#define AW8622X_BIT_WAVCFG13_AUTO_MD_CONT_MODE (1<<4)
|
||||
#define AW8622X_BIT_WAVCFG13_AUTO_MD_SIN_WAV (0<<4)
|
||||
#define AW8622X_BIT_WAVCFG13_MAINLOOP_MASK (~(0x0F<<0))
|
||||
#define AW8622X_BIT_WAVCFG13_MAINLOOP_INIFINITELY (0x0F<<0)
|
||||
|
||||
/* WAVCFG14: reg 0x17 RW */
|
||||
/* AUTO_WAV */
|
||||
|
||||
/***************** CONT *****************/
|
||||
/* CONTCFG1: reg 0x18 RW */
|
||||
#define AW8622X_BIT_CONTCFG1_EDGE_FRE_MASK (~(0x0F<<4))
|
||||
#define AW8622X_BIT_CONTCFG1_EN_F0_DET_MASK (~(1<<3))
|
||||
#define AW8622X_BIT_CONTCFG1_F0_DET_ENABLE (1<<3)
|
||||
#define AW8622X_BIT_CONTCFG1_F0_DET_DISABLE (0<<3)
|
||||
#define AW8622X_BIT_CONTCFG1_SIN_MODE_MASK (~(1<<0))
|
||||
#define AW8622X_BIT_CONTCFG1_SIN_MODE_COS (1<<0)
|
||||
#define AW8622X_BIT_CONTCFG1_SIN_MODE_SINE (0<<0)
|
||||
|
||||
/* CONTCFG2: reg 0x19 RW */
|
||||
/* F_PRE */
|
||||
|
||||
/* CONTCFG3: reg 0x1A RW */
|
||||
/* DRV_WIDTH */
|
||||
|
||||
/* CONTCFG4: reg 0x1B RW */
|
||||
/* WAIT_NUM */
|
||||
|
||||
/* CONTCFG5: reg 0x1C RW */
|
||||
#define AW8622X_BIT_CONTCFG5_BRK_GAIN_MASK (~(0x0F<<0))
|
||||
|
||||
/* CONTCFG6: reg 0x1D RW */
|
||||
#define AW8622X_BIT_CONTCFG6_TRACK_EN_MASK (~(1<<7))
|
||||
#define AW8622X_BIT_CONTCFG6_TRACK_ENABLE (1<<7)
|
||||
#define AW8622X_BIT_CONTCFG6_TRACK_DISABLE (0<<7)
|
||||
#define AW8622X_BIT_CONTCFG6_DRV1_LVL_MASK (~(0x7F<<0))
|
||||
|
||||
/* CONTCFG7: reg 0x1E RW */
|
||||
#define AW8622X_BIT_CONTCFG7_DRV2_LVL_MASK (~(0x7F<<0))
|
||||
|
||||
/* CONTCFG8: reg 0x1F RW */
|
||||
/* DRV1_TIME */
|
||||
|
||||
/* CONTCFG9: reg 0x20 RW */
|
||||
/* DRV2_TIME */
|
||||
|
||||
/* CONTCFG10: reg 0x21 RW */
|
||||
/* BRK_TIME */
|
||||
|
||||
/* CONTCFG11: reg 0x22 RW */
|
||||
/* TRACK_MARGIN */
|
||||
|
||||
/* CONTCFG12: reg 0x23 RW */
|
||||
/* MBRK_TH */
|
||||
|
||||
/* CONTCFG13: reg 0x24 RW */
|
||||
#define AW8622X_BIT_CONTCFG13_TSET_MASK (~(0x0F<<4))
|
||||
#define AW8622X_BIT_CONTCFG13_BEME_SET_MASK (~(0x0F<<0))
|
||||
|
||||
/* CONTRD14: reg 0x25 RO */
|
||||
/* F_LRA_F0_H */
|
||||
|
||||
/* CONTRD15: reg 0x26 RO */
|
||||
/* F_LRA_F0_L */
|
||||
|
||||
/* CONTRD16: reg 0x27 RO */
|
||||
/* CONT_F0_H */
|
||||
|
||||
/* CONTRD17: reg 0x28 RO */
|
||||
/* CONT_F0_L */
|
||||
|
||||
/* CONTRD18: reg 0x29 RO */
|
||||
/* ACCELERATION */
|
||||
|
||||
/* CONTRD19: reg 0x2A RO */
|
||||
/* BEMF_PEAK1 */
|
||||
|
||||
/* CONTRD20: reg 0x2B RO */
|
||||
/* BEMF_PEAK2 */
|
||||
|
||||
/* CONTRD21: reg 0x2C RO */
|
||||
/* BEMF_PEAK3 */
|
||||
|
||||
/***************** RTP *****************/
|
||||
/* RTPCFG1: reg 0x2D RW */
|
||||
#define AW8622X_BIT_RTPCFG1_ADDRH_MASK (~(0x0F<<0))
|
||||
|
||||
#define AW8622X_BIT_RTPCFG1_SRAM_SIZE_2K_MASK (~(1<<5))
|
||||
#define AW8622X_BIT_RTPCFG1_SRAM_SIZE_2K_EN (1<<5)
|
||||
#define AW8622X_BIT_RTPCFG1_SRAM_SIZE_2K_DIS (0<<5)
|
||||
|
||||
#define AW8622X_BIT_RTPCFG1_SRAM_SIZE_1K_MASK (~(1<<4))
|
||||
#define AW8622X_BIT_RTPCFG1_SRAM_SIZE_1K_EN (1<<4)
|
||||
#define AW8622X_BIT_RTPCFG1_SRAM_SIZE_1K_DIS (0<<4)
|
||||
/* BASE_ADDR_H */
|
||||
|
||||
/* RTPCFG2: reg 0x2E RW */
|
||||
/* BASE_ADDR_L */
|
||||
|
||||
/* RTPCFG3: reg 0x2F RW */
|
||||
#define AW8622X_BIT_RTPCFG3_FIFO_AEH_MASK (~(0x0F<<4))
|
||||
#define AW8622X_BIT_RTPCFG3_FIFO_AFH_MASK (~(0x0F<<0))
|
||||
|
||||
/* RTPCFG4: reg 0x30 RW */
|
||||
/* FIFO_AEL */
|
||||
|
||||
/* RTPCFG5: reg 0x31 RW */
|
||||
/* FIFO_AFL */
|
||||
|
||||
/* RTPDATA: reg 0x32 RW */
|
||||
/* FIFO_AFL */
|
||||
|
||||
/***************** TRIGGER *****************/
|
||||
#define AW8622X_BIT_TRG_ENABLE_MASK (~(1<<7))
|
||||
#define AW8622X_BIT_TRG_ENABLE (1<<7)
|
||||
#define AW8622X_BIT_TRG_DISABLE (0<<7)
|
||||
#define AW8622X_BIT_TRG_SEQ_MASK (~(0x7F<<0))
|
||||
|
||||
/* TRGCFG1: reg 0x33 RW */
|
||||
#define AW8622X_BIT_TRGCFG1_TRG1_POS_MASK (~(1<<7))
|
||||
#define AW8622X_BIT_TRGCFG1_TRG1_POS_ENABLE (1<<7)
|
||||
#define AW8622X_BIT_TRGCFG1_TRG1_POS_DISABLE (0<<7)
|
||||
#define AW8622X_BIT_TRGCFG1_TRG1SEQ_P_MASK (~(0x7F<<0))
|
||||
|
||||
/* TRGCFG2: reg 0x34 RW */
|
||||
#define AW8622X_BIT_TRGCFG2_TRG2_POS_MASK (~(1<<7))
|
||||
#define AW8622X_BIT_TRGCFG2_TRG2_POS_ENABLE (1<<7)
|
||||
#define AW8622X_BIT_TRGCFG2_TRG2_POS_DISABLE (0<<7)
|
||||
#define AW8622X_BIT_TRGCFG2_TRG2SEQ_P_MASK (~(0x7F<<0))
|
||||
|
||||
/* TRGCFG3: reg 0x35 RW */
|
||||
#define AW8622X_BIT_TRGCFG3_TRG3_POS_MASK (~(1<<7))
|
||||
#define AW8622X_BIT_TRGCFG3_TRG3_POS_ENABLE (1<<7)
|
||||
#define AW8622X_BIT_TRGCFG3_TRG3_POS_DISABLE (0<<7)
|
||||
#define AW8622X_BIT_TRGCFG3_TRG3SEQ_P_MASK (~(0x7F<<0))
|
||||
|
||||
/* TRGCFG4: reg 0x36 RW */
|
||||
#define AW8622X_BIT_TRGCFG4_TRG1_NEG_MASK (~(1<<7))
|
||||
#define AW8622X_BIT_TRGCFG4_TRG1_NEG_ENABLE (1<<7)
|
||||
#define AW8622X_BIT_TRGCFG4_TRG1_NEG_DISABLE (0<<7)
|
||||
#define AW8622X_BIT_TRGCFG4_TRG1SEQ_N_MASK (~(0x7F<<0))
|
||||
|
||||
/* TRGCFG5: reg 0x37 RW */
|
||||
#define AW8622X_BIT_TRGCFG5_TRG2_NEG_MASK (~(1<<7))
|
||||
#define AW8622X_BIT_TRGCFG5_TRG2_NEG_ENABLE (1<<7)
|
||||
#define AW8622X_BIT_TRGCFG5_TRG2_NEG_DISABLE (0<<7)
|
||||
#define AW8622X_BIT_TRGCFG5_TRG2SEQ_N_MASK (~(0x7F<<0))
|
||||
|
||||
/* TRGCFG6: reg 0x38 RW */
|
||||
#define AW8622X_BIT_TRGCFG6_TRG3_NEG_MASK (~(1<<7))
|
||||
#define AW8622X_BIT_TRGCFG6_TRG3_NEG_ENABLE (1<<7)
|
||||
#define AW8622X_BIT_TRGCFG6_TRG3_NEG_DISABLE (0<<7)
|
||||
#define AW8622X_BIT_TRGCFG6_TRG3SEQ_N_MASK (~(0x7F<<0))
|
||||
|
||||
/* TRGCFG7: reg 0x39 RW */
|
||||
#define AW8622X_BIT_TRGCFG7_TRG1_POR_LEV_BRK_MASK (~(7<<5))
|
||||
#define AW8622X_BIT_TRGCFG7_TRG2_POR_LEV_BRK_MASK (~(7<<1))
|
||||
#define AW8622X_BIT_TRGCFG7_TRG1_POLAR_MASK (~(1<<7))
|
||||
#define AW8622X_BIT_TRGCFG7_TRG1_POLAR_NEG (1<<7)
|
||||
#define AW8622X_BIT_TRGCFG7_TRG1_POLAR_POS (0<<7)
|
||||
#define AW8622X_BIT_TRGCFG7_TRG1_MODE_MASK (~(1<<6))
|
||||
#define AW8622X_BIT_TRGCFG7_TRG1_MODE_LEVEL (1<<6)
|
||||
#define AW8622X_BIT_TRGCFG7_TRG1_MODE_EDGE (0<<6)
|
||||
#define AW8622X_BIT_TRGCFG7_TRG1_AUTO_BRK_MASK (~(1<<5))
|
||||
#define AW8622X_BIT_TRGCFG7_TRG1_AUTO_BRK_ENABLE (1<<5)
|
||||
#define AW8622X_BIT_TRGCFG7_TRG1_AUTO_BRK_DISABLE (0<<5)
|
||||
#define AW8622X_BIT_TRGCFG7_TRG2_POLAR_MASK (~(1<<3))
|
||||
#define AW8622X_BIT_TRGCFG7_TRG2_POLAR_NEG (1<<3)
|
||||
#define AW8622X_BIT_TRGCFG7_TRG2_POLAR_POS (0<<3)
|
||||
#define AW8622X_BIT_TRGCFG7_TRG2_MODE_MASK (~(1<<2))
|
||||
#define AW8622X_BIT_TRGCFG7_TRG2_MODE_LEVEL (1<<2)
|
||||
#define AW8622X_BIT_TRGCFG7_TRG2_MODE_EDGE (0<<2)
|
||||
#define AW8622X_BIT_TRGCFG7_TRG2_AUTO_BRK_MASK (~(1<<1))
|
||||
#define AW8622X_BIT_TRGCFG7_TRG2_AUTO_BRK_ENABLE (1<<1)
|
||||
#define AW8622X_BIT_TRGCFG7_TRG2_AUTO_BRK_DISABLE (0<<1)
|
||||
|
||||
/* TRGCFG8: reg 0x3A RW */
|
||||
#define AW8622X_BIT_TRGCFG8_TRG3_POR_LEV_BRK_MASK (~(7<<5))
|
||||
#define AW8622X_BIT_TRGCFG8_TRG3_POLAR_MASK (~(1<<7))
|
||||
#define AW8622X_BIT_TRGCFG8_TRG3_POLAR_NEG (1<<7)
|
||||
#define AW8622X_BIT_TRGCFG8_TRG3_POLAR_POS (0<<7)
|
||||
#define AW8622X_BIT_TRGCFG8_TRG3_MODE_MASK (~(1<<6))
|
||||
#define AW8622X_BIT_TRGCFG8_TRG3_MODE_LEVEL (1<<6)
|
||||
#define AW8622X_BIT_TRGCFG8_TRG3_MODE_EDGE (0<<6)
|
||||
#define AW8622X_BIT_TRGCFG8_TRG3_AUTO_BRK_MASK (~(1<<5))
|
||||
#define AW8622X_BIT_TRGCFG8_TRG3_AUTO_BRK_ENABLE (1<<5)
|
||||
#define AW8622X_BIT_TRGCFG8_TRG3_AUTO_BRK_DISABLE (0<<5)
|
||||
#define AW8622X_BIT_TRGCFG8_TRG_TRIG1_MODE_MASK (~(3<<3))
|
||||
#define AW8622X_BIT_TRGCFG8_PWM_LRA (0<<3)
|
||||
#define AW8622X_BIT_TRGCFG8_PWM_ERA (1<<3)
|
||||
#define AW8622X_BIT_TRGCFG8_TRIG1 (2<<3)
|
||||
#define AW8622X_BIT_TRGCFG8_DISABLE (3<<3)
|
||||
#define AW8622X_BIT_TRGCFG8_TRG1_STOP_MASK (~(1<<2))
|
||||
#define AW8622X_BIT_TRGCFG8_TRG1_STOP (1<<2)
|
||||
#define AW8622X_BIT_TRGCFG8_TRG2_STOP_MASK (~(1<<1))
|
||||
#define AW8622X_BIT_TRGCFG8_TRG2_STOP (1<<1)
|
||||
#define AW8622X_BIT_TRGCFG8_TRG3_STOP_MASK (~(1<<0))
|
||||
#define AW8622X_BIT_TRGCFG8_TRG3_STOP (1<<0)
|
||||
|
||||
/* GLBCFG1: reg 0x3B RW */
|
||||
/* WAKE_DLY */
|
||||
|
||||
/* GLBCFG2: reg 0x3C RW */
|
||||
/* START_DLY */
|
||||
|
||||
/* GLBCFG3: reg 0x3D RW */
|
||||
/* END_DLY */
|
||||
|
||||
/* GLBCFG4: reg 0x3E RW */
|
||||
#define AW8622X_BIT_GLBCFG4_GO_PRIO_MASK (~(3<<6))
|
||||
#define AW8622X_BIT_GLBCFG4_TRG3_PRIO_MASK (~(3<<4))
|
||||
#define AW8622X_BIT_GLBCFG4_TRG2_PRIO_MASK (~(3<<2))
|
||||
#define AW8622X_BIT_GLBCFG4_TRG1_PRIO_MASK (~(3<<0))
|
||||
|
||||
/* GLBRD5: reg 0x3F R0 */
|
||||
/* GLB_STATE */
|
||||
#define AW8622X_BIT_GLBRD5_STATE_MASK (~(15<<0))
|
||||
#define AW8622X_BIT_GLBRD5_STATE_STANDBY (0<<0)
|
||||
#define AW8622X_BIT_GLBRD5_STATE_WAKEUP (1<<0)
|
||||
#define AW8622X_BIT_GLBRD5_STATE_STARTUP (2<<0)
|
||||
#define AW8622X_BIT_GLBRD5_STATE_WAIT (3<<0)
|
||||
#define AW8622X_BIT_GLBRD5_STATE_CONT_GO (6<<0)
|
||||
#define AW8622X_BIT_GLBRD5_STATE_RAM_GO (7<<0)
|
||||
#define AW8622X_BIT_GLBRD5_STATE_RTP_GO (8<<0)
|
||||
#define AW8622X_BIT_GLBRD5_STATE_TRIG_GO (9<<0)
|
||||
#define AW8622X_BIT_GLBRD5_STATE_I2S_GO (10<<0)
|
||||
#define AW8622X_BIT_GLBRD5_STATE_BRAKE (11<<0)
|
||||
#define AW8622X_BIT_GLBRD5_STATE_END (12<<0)
|
||||
/* RAMADDRH: reg 0x40 RWS */
|
||||
#define AW8622X_BIT_RAMADDRH_MASK (~(63<<0))
|
||||
|
||||
/* RAMADDRL: reg 0x41 RWS */
|
||||
/* RAMADDRL */
|
||||
|
||||
/* RAMDATA: reg 0x42 RWS */
|
||||
/* RAMDATA */
|
||||
|
||||
/***************** SYSCTRL *****************/
|
||||
/* SYSCTRL1: reg 0x43 RW */
|
||||
#define AW8622X_BIT_SYSCTRL1_VBAT_MODE_MASK (~(1<<7))
|
||||
#define AW8622X_BIT_SYSCTRL1_VBAT_MODE_HW (1<<7)
|
||||
#define AW8622X_BIT_SYSCTRL1_VBAT_MODE_SW (0<<7)
|
||||
#define AW8622X_BIT_SYSCTRL1_PERP_MASK (~(1<<6))
|
||||
#define AW8622X_BIT_SYSCTRL1_PERP_ON (1<<6)
|
||||
#define AW8622X_BIT_SYSCTRL1_PERP_OFF (0<<6)
|
||||
#define AW8622X_BIT_SYSCTRL1_CLK_SEL_MASK (~(3<<4))
|
||||
#define AW8622X_BIT_SYSCTRL1_CLK_SEL_OSC (1<<4)
|
||||
#define AW8622X_BIT_SYSCTRL1_CLK_SEL_AUTO (0<<4)
|
||||
#define AW8622X_BIT_SYSCTRL1_RAMINIT_MASK (~(1<<3))
|
||||
#define AW8622X_BIT_SYSCTRL1_RAMINIT_ON (1<<3)
|
||||
#define AW8622X_BIT_SYSCTRL1_RAMINIT_OFF (0<<3)
|
||||
#define AW8622X_BIT_SYSCTRL1_EN_FIR_MASK (~(1<<2))
|
||||
#define AW8622X_BIT_SYSCTRL1_FIR_ENABLE (0<<2)
|
||||
#define AW8622X_BIT_SYSCTRL1_WAKE_MODE_MASK (~(1<<1))
|
||||
#define AW8622X_BIT_SYSCTRL1_WAKE_MODE_WAKEUP (1<<1)
|
||||
#define AW8622X_BIT_SYSCTRL1_WAKE_MODE_BST (0<<1)
|
||||
#define AW8622X_BIT_SYSCTRL1_RTP_CLK_MASK (~(1<<0))
|
||||
#define AW8622X_BIT_SYSCTRL1_RTP_PLL (1<<0)
|
||||
#define AW8622X_BIT_SYSCTRL1_RTP_OSC (0<<0)
|
||||
|
||||
/* SYSCTRL2: reg 0x44 RW */
|
||||
#define AW8622X_BIT_SYSCTRL2_WAKE_MASK (~(1<<7))
|
||||
#define AW8622X_BIT_SYSCTRL2_WAKE_ON (1<<7)
|
||||
#define AW8622X_BIT_SYSCTRL2_WAKE_OFF (0<<7)
|
||||
#define AW8622X_BIT_SYSCTRL2_STANDBY_MASK (~(1<<6))
|
||||
#define AW8622X_BIT_SYSCTRL2_STANDBY_ON (1<<6)
|
||||
#define AW8622X_BIT_SYSCTRL2_STANDBY_OFF (0<<6)
|
||||
#define AW8622X_BIT_SYSCTRL2_RTP_DLY_MASK (~(3<<4))
|
||||
#define AW8622X_BIT_SYSCTRL2_INTN_PIN_MASK (~(1<<3))
|
||||
#define AW8622X_BIT_SYSCTRL2_INTN (1<<3)
|
||||
#define AW8622X_BIT_SYSCTRL2_TRIG1 (0<<3)
|
||||
#define AW8622X_BIT_SYSCTRL2_WCK_PIN_MASK (~(1<<2))
|
||||
#define AW8622X_BIT_SYSCTRL2_ENABLE_TRIG2 (1<<2)
|
||||
#define AW8622X_BIT_SYSCTRL2_DISENABLE_TRIG2 (0<<2)
|
||||
#define AW8622X_BIT_SYSCTRL2_WAVDAT_MODE_MASK (~(3<<0))
|
||||
#define AW8622X_BIT_SYSCTRL2_RATE_12K (2<<0)
|
||||
#define AW8622X_BIT_SYSCTRL2_RATE_24K (0<<0)
|
||||
#define AW8622X_BIT_SYSCTRL2_RATE_48K (1<<0)
|
||||
|
||||
/* SYSCTRL3: reg 0x45 RW */
|
||||
/* SIN_H */
|
||||
|
||||
/* SYSCTRL4: reg 0x46 RW */
|
||||
/* SIN_L */
|
||||
|
||||
/* SYSCTRL5: reg 0x47 RW */
|
||||
/* COS_H */
|
||||
|
||||
/* SYSCTRL6: reg 0x48 RW */
|
||||
/* COS_L */
|
||||
|
||||
/* SYSCTRL7: reg 0x49 RW */
|
||||
#define AW8622X_BIT_SYSCTRL7_GAIN_BYPASS_MASK (~(1<<6))
|
||||
#define AW8622X_BIT_SYSCTRL7_GAIN_CHANGEABLE (1<<6)
|
||||
#define AW8622X_BIT_SYSCTRL7_GAIN_FIXED (0<<6)
|
||||
|
||||
#define AW8622X_BIT_SYSCTRL7_INT_EDGE_MODE_MASK (~(1<<5))
|
||||
#define AW8622X_BIT_SYSCTRL7_INT_EDGE_MODE_POS (0<<5)
|
||||
#define AW8622X_BIT_SYSCTRL7_INT_EDGE_MODE_BOTH (1<<5)
|
||||
#define AW8622X_BIT_SYSCTRL7_INT_MODE_MASK (~(1<<4))
|
||||
#define AW8622X_BIT_SYSCTRL7_INT_MODE_EDGE (1<<4)
|
||||
#define AW8622X_BIT_SYSCTRL7_INT_MODE_LEVEL (0<<4)
|
||||
|
||||
#define AW8622X_BIT_SYSCTRL7_INTP_MASK (~(1<<3))
|
||||
#define AW8622X_BIT_SYSCTRL7_INTP_HIGH (1<<3)
|
||||
#define AW8622X_BIT_SYSCTRL7_INTP_LOW (0<<3)
|
||||
#define AW8622X_BIT_SYSCTRL7_D2S_GAIN_MASK (~(7<<0))
|
||||
#define AW8622X_BIT_SYSCTRL7_D2S_GAIN_1 (0<<0)
|
||||
#define AW8622X_BIT_SYSCTRL7_D2S_GAIN_2 (1<<0)
|
||||
#define AW8622X_BIT_SYSCTRL7_D2S_GAIN_4 (2<<0)
|
||||
#define AW8622X_BIT_SYSCTRL7_D2S_GAIN_5 (3<<0)
|
||||
#define AW8622X_BIT_SYSCTRL7_D2S_GAIN_8 (4<<0)
|
||||
#define AW8622X_BIT_SYSCTRL7_D2S_GAIN_10 (5<<0)
|
||||
#define AW8622X_BIT_SYSCTRL7_D2S_GAIN_20 (6<<0)
|
||||
#define AW8622X_BIT_SYSCTRL7_D2S_GAIN_40 (7<<0)
|
||||
|
||||
/***************** I2S *****************/
|
||||
/* I2SCFG1: reg 0x4A RW */
|
||||
#define AW8622X_BIT_I2SCFG1_I2SMD_MASK (~(3<<6))
|
||||
#define AW8622X_BIT_I2SCFG1_I2SFS_MASK (~(3<<4))
|
||||
#define AW8622X_BIT_I2SCFG1_I2SFS_16BIT (0<<4)
|
||||
#define AW8622X_BIT_I2SCFG1_I2SFS_20BIT (1<<4)
|
||||
#define AW8622X_BIT_I2SCFG1_I2SFS_24BIT (2<<4)
|
||||
#define AW8622X_BIT_I2SCFG1_I2SFS_32BIT (3<<4)
|
||||
#define AW8622X_BIT_I2SCFG1_I2SBCK_MASK (~(3<<2))
|
||||
#define AW8622X_BIT_I2SCFG1_I2SBCK_32FS (0<<2)
|
||||
#define AW8622X_BIT_I2SCFG1_I2SBCK_48FS (1<<2)
|
||||
#define AW8622X_BIT_I2SCFG1_I2SBCK_64FS (2<<2)
|
||||
#define AW8622X_BIT_I2SCFG1_RX_THRS_MASK (~(3<<0))
|
||||
|
||||
/* I2SCFG2: reg 0x4B RW */
|
||||
#define AW8622X_BIT_I2SCFG2_WSINV_MASK (~(1<<4))
|
||||
#define AW8622X_BIT_I2SCFG2_WSINV_SWITCH (1<<4)
|
||||
#define AW8622X_BIT_I2SCFG2_WSINV_NO_SWITCH (0<<4)
|
||||
#define AW8622X_BIT_I2SCFG2_BCKINV_MASK (~(1<<3))
|
||||
#define AW8622X_BIT_I2SCFG2_BCKINV_INVERT (1<<3)
|
||||
#define AW8622X_BIT_I2SCFG2_BCKINV_NOTINVT (0<<3)
|
||||
#define AW8622X_BIT_I2SCFG2_CHSEL_MASK (~(1<<2))
|
||||
#define AW8622X_BIT_I2SCFG2_CHSEL_LEFT (1<<2)
|
||||
#define AW8622X_BIT_I2SCFG2_CHSEL_RIGHT (0<<2)
|
||||
#define AW8622X_BIT_I2SCFG2_I2S_INT_MASK (~(1<<1))
|
||||
#define AW8622X_BIT_I2SCFG2_I2S_INT_ON (1<<1)
|
||||
#define AW8622X_BIT_I2SCFG2_I2S_INT_OFF (0<<1)
|
||||
#define AW8622X_BIT_I2SCFG2_I2S_EN_MASK (~(1<<0))
|
||||
#define AW8622X_BIT_I2SCFG2_I2S_ENABLE (1<<0)
|
||||
#define AW8622X_BIT_I2SCFG2_I2S_DISABLE (0<<0)
|
||||
|
||||
/* PWMCFG1: reg 0x4C RW */
|
||||
#define AW8622X_BIT_PWMCFG1_PRC_EN_MASK (~(1<<7))
|
||||
#define AW8622X_BIT_PWMCFG1_PRC_ENABLE (1<<7)
|
||||
#define AW8622X_BIT_PWMCFG1_PRC_DISABLE (0<<7)
|
||||
#define AW8622X_BIT_PWMCFG1_PRCTIME_MASK (~(0x7F<<0))
|
||||
|
||||
/* PWMCFG2: reg 0x4D RW */
|
||||
#define AW8622X_BIT_PWMCFG2_REF_SEL_MASK (~(1<<5))
|
||||
#define AW8622X_BIT_PWMCFG2_REF_SEL_TRIANGLE (1<<5)
|
||||
#define AW8622X_BIT_PWMCFG2_REF_SEL_SAWTOOTH (0<<5)
|
||||
#define AW8622X_BIT_PWMCFG2_PD_HWM_MASK (~(1<<4))
|
||||
#define AW8622X_BIT_PWMCFG2_PD_HWM_ON (1<<4)
|
||||
#define AW8622X_BIT_PWMCFG2_PWMOE_MASK (~(1<<3))
|
||||
#define AW8622X_BIT_PWMCFG2_PWMOE_ON (1<<3)
|
||||
#define AW8622X_BIT_PWMCFG2_PWMFRC_MASK (~(7<<0))
|
||||
|
||||
/* PWMCFG3: reg 0x4E RW */
|
||||
#define AW8622X_BIT_PWMCFG3_PR_EN_MASK (~(1<<7))
|
||||
#define AW8622X_BIT_PWMCFG3_PR_ENABLE (1<<7)
|
||||
#define AW8622X_BIT_PWMCFG3_PR_DISABLE (0<<7)
|
||||
#define AW8622X_BIT_PWMCFG3_PRLVL_MASK (~(0x7F<<0))
|
||||
|
||||
/* PWMCFG4: reg 0x4F RW */
|
||||
/* PRTIME */
|
||||
|
||||
/* TMCFG: reg 0x50 RW */
|
||||
/* TM */
|
||||
|
||||
/* DETCFG1: reg 0x51 RW */
|
||||
#define AW8622X_BIT_DETCFG1_FTS_GO_MASK (~(1<<7))
|
||||
#define AW8622X_BIT_DETCFG1_FTS_GO_ENABLE (1<<7)
|
||||
#define AW8622X_BIT_DETCFG1_TEST_GO_MASK (~(1<<6))
|
||||
#define AW8622X_BIT_DETCFG1_TEST_GO_ENABLE (1<<6)
|
||||
#define AW8622X_BIT_DETCFG1_ADO_SLOT_MODE_MASK (~(1<<5))
|
||||
#define AW8622X_BIT_DETCFG1_ADO_SLOT_ADC_32 (1<<5)
|
||||
#define AW8622X_BIT_DETCFG1_ADO_SLOT_ADC_256 (0<<5)
|
||||
#define AW8622X_BIT_DETCFG1_RL_OS_MASK (~(1<<4))
|
||||
#define AW8622X_BIT_DETCFG1_RL (1<<4)
|
||||
#define AW8622X_BIT_DETCFG1_OS (0<<4)
|
||||
#define AW8622X_BIT_DETCFG1_PRCT_MODE_MASK (~(1<<3))
|
||||
#define AW8622X_BIT_DETCFG1_PRCT_MODE_INVALID (1<<3)
|
||||
#define AW8622X_BIT_DETCFG1_PRCT_MODE_VALID (0<<3)
|
||||
#define AW8622X_BIT_DETCFG1_CLK_ADC_MASK (~(7<<0))
|
||||
#define AW8622X_BIT_DETCFG1_CLK_ADC_12M (0<<0)
|
||||
#define AW8622X_BIT_DETCFG1_CLK_ADC_6M (1<<0)
|
||||
#define AW8622X_BIT_DETCFG1_CLK_ADC_3M (2<<0)
|
||||
#define AW8622X_BIT_DETCFG1_CLK_ADC_1M5 (3<<0)
|
||||
#define AW8622X_BIT_DETCFG1_CLK_ADC_M75 (4<<0)
|
||||
#define AW8622X_BIT_DETCFG1_CLK_ADC_M37 (5<<0)
|
||||
#define AW8622X_BIT_DETCFG1_CLK_ADC_M18 (6<<0)
|
||||
#define AW8622X_BIT_DETCFG1_CLK_ADC_M09 (7<<0)
|
||||
|
||||
/* DETCFG2: reg 0x52 RW */
|
||||
#define AW8622X_BIT_DETCFG2_VBAT_GO_MASK (~(1<<1))
|
||||
#define AW8622X_BIT_DETCFG2_VABT_GO_ON (1<<1)
|
||||
#define AW8622X_BIT_DETCFG2_DIAG_GO_MASK (~(1<<0))
|
||||
#define AW8622X_BIT_DETCFG2_DIAG_GO_ON (1<<0)
|
||||
|
||||
/* DET_RL: reg 0x53 RW */
|
||||
/* RL */
|
||||
|
||||
/* DET_OS: reg 0x54 RW */
|
||||
/* OS */
|
||||
|
||||
/* DET_VBAT: reg 0x55 RW */
|
||||
/* VBAT */
|
||||
|
||||
/* DET_TEST: reg 0x56 RW */
|
||||
/* TEST */
|
||||
|
||||
/* DET_LO: reg 0x57 RW */
|
||||
#define AW8622X_BIT_DET_LO_TEST_MASK (~(3<<6))
|
||||
#define AW8622X_BIT_DET_LO_VBAT_MASK (~(3<<4))
|
||||
#define AW8622X_BIT_DET_LO_OS_MASK (~(3<<2))
|
||||
#define AW8622X_BIT_DET_LO_RL_MASK (~(3<<0))
|
||||
|
||||
/* TRIMCFG1: reg:0x58 RW */
|
||||
#define AW8622X_BIT_TRIMCFG1_RL_TRIM_SRC_MASK (~(1<<6))
|
||||
#define AW8622X_BIT_TRIMCFG1_RL_TRIM_SRC_REG (1<<6)
|
||||
#define AW8622X_BIT_TRIMCFG1_RL_TRIM_SRC_EFUSE (0<<6)
|
||||
#define AW8622X_BIT_TRIMCFG1_TRIM_RL_MASK (~(63<<0))
|
||||
|
||||
/* TRIMCFG3: reg:0x5A RW */
|
||||
#define AW8622X_BIT_TRIMCFG3_OSC_TRIM_SRC_MASK (~(1<<7))
|
||||
#define AW8622X_BIT_TRIMCFG3_OSC_TRIM_SRC_REG (1<<7)
|
||||
#define AW8622X_BIT_TRIMCFG3_OSC_TRIM_SRC_EFUSE (0<<7)
|
||||
#define AW8622X_BIT_TRIMCFG3_TRIM_LRA_MASK (~(63<<0))
|
||||
|
||||
/* TRIMCFG4: reg:0x5B RW */
|
||||
/* TRIM_OSC */
|
||||
|
||||
/* PLLCFG1: reg:0x68 RW */
|
||||
#define AW8622X_BIT_PLLCFG1_PLL_TEST_EN_MASK (~(1<<6))
|
||||
#define AW8622X_BIT_PLLCFG1_PLL_TEST_ENABLE (1<<6)
|
||||
#define AW8622X_BIT_PLLCFG1_PLL_TEST_DIV_MASK (~(3<<4))
|
||||
#define AW8622X_BIT_PLLCFG1_PLL_TEST_DIV_1 (0<<4)
|
||||
#define AW8622X_BIT_PLLCFG1_PLL_TEST_DIV_2 (1<<4)
|
||||
#define AW8622X_BIT_PLLCFG1_PLL_TEST_DIV_4 (2<<4)
|
||||
#define AW8622X_BIT_PLLCFG1_PLL_TEST_DIV_8 (3<<4)
|
||||
#define AW8622X_BIT_PLLCFG1_PLL_BIAS_CP1_IEN_MASK (~(1<<3))
|
||||
#define AW8622X_BIT_PLLCFG1_PLL_BIAS_CP1_IENABLE (1<<3)
|
||||
#define AW8622X_BIT_PLLCFG1_PLL_VTI_CP1_IEN_MASK (~(1<<2))
|
||||
#define AW8622X_BIT_PLLCFG1_PLL_VTI_CP1_IENABLE (1<<2)
|
||||
#define AW8622X_BIT_PLLCFG1_PLL_DELAY_SEL_MASK (~(1<<1))
|
||||
#define AW8622X_BIT_PLLCFG1_PLL_R1_SEL_MASK (~(1<<0))
|
||||
|
||||
/* PLLCFG2: reg:0x69 RW */
|
||||
#define AW8622X_BIT_PLLCFG2_PLL_CP1_SEL_MASK (~(0x0F<<4))
|
||||
#define AW8622X_BIT_PLLCFG2_PLL_CP1_40UA (4<<4)
|
||||
#define AW8622X_BIT_PLLCFG2_PLL_CP1_50UA (5<<4)
|
||||
#define AW8622X_BIT_PLLCFG2_PLL_CP1_80UA (8<<4)
|
||||
#define AW8622X_BIT_PLLCFG2_PLL_CP1_100UA (10<<4)
|
||||
#define AW8622X_BIT_PLLCFG2_PLL_CP2_SEL_MASK (~(0x0F<<0))
|
||||
#define AW8622X_BIT_PLLCFG2_PLL_CP2_40NA (1<<0)
|
||||
#define AW8622X_BIT_PLLCFG2_PLL_CP2_600NA (8<<0)
|
||||
#define AW8622X_BIT_PLLCFG2_PLL_CP2_800NA (10<<0)
|
||||
#define AW8622X_BIT_PLLCFG2_PLL_CP2_1200NA (12<<0)
|
||||
|
||||
/* HDRVCFG1: reg:0x6A RW */
|
||||
#define AW8622X_BIT_HDRVCFG1_EN_HD_LOW_MASK (~(1<<7))
|
||||
#define AW8622X_BIT_HDRVCFG1_EN_HD_HZ (0<<7)
|
||||
#define AW8622X_BIT_HDRVCFG1_EN_HD_PD (1<<7)
|
||||
|
||||
/* IOCFG1: reg:0x6B RW */
|
||||
#define AW8622X_BIT_IOCFG1_HSEN_MASK (~(1<<6))
|
||||
#define AW8622X_BIT_IOCFG1_HS_ENABLE (1<<6)
|
||||
#define AW8622X_BIT_IOCFG1_HS_DISABLE (0<<6)
|
||||
#define AW8622X_BIT_IOCFG1_IO_FAST_MASK (~(3<<4))
|
||||
#define AW8622X_BIT_IOCFG1_ALL_IO_FAST_ENABLE (3<<4)
|
||||
#define AW8622X_BIT_IOCFG1_IIS_IO_FAST_ENABLE (2<<4)
|
||||
#define AW8622X_BIT_IOCFG1_IIC_IO_FAST_ENABLE (1<<4)
|
||||
#define AW8622X_BIT_IOCFG1_IO_FAST_DISABLE (0<<4)
|
||||
|
||||
/* OCCFG1: reg:0x74 RW */
|
||||
#define AW8622X_BIT_OCCFG1_HS_IOC_MASK (~(3<<6))
|
||||
#define AW8622X_BIT_OCCFG1_HS_IOC_3A15 (0<<6)
|
||||
#define AW8622X_BIT_OCCFG1_HS_IOC_3A65 (1<<6)
|
||||
#define AW8622X_BIT_OCCFG1_HS_IOC_4A15 (2<<6)
|
||||
#define AW8622X_BIT_OCCFG1_HS_IOC_4A65 (3<<6)
|
||||
#define AW8622X_BIT_OCCFG1_LS_IOC_MASK (~(3<<4))
|
||||
#define AW8622X_BIT_OCCFG1_LS_IOC_3A15 (0<<4)
|
||||
#define AW8622X_BIT_OCCFG1_LS_IOC_3A65 (1<<4)
|
||||
#define AW8622X_BIT_OCCFG1_LS_IOC_4A15 (2<<4)
|
||||
#define AW8622X_BIT_OCCFG1_LS_IOC_4A65 (3<<4)
|
||||
#define AW8622X_BIT_OCCFG1_OCDT_MASK (~(3<<2))
|
||||
|
||||
#define AW8622X_BIT_OCCLK_MODE_MASK (~(3<<0))
|
||||
|
||||
/* ADCCFG1: reg:0x75 RW */
|
||||
#define AW8622X_BIT_ADCCFG1_EN_OS_DET_MASK (~(1<<7))
|
||||
#define AW8622X_BIT_ADCCFG1_EN_RL_DET_MASK (~(1<<6))
|
||||
#define AW8622X_BIT_ADCCFG1_D2S_SEL_HDRV_MASK (~(1<<5))
|
||||
#define AW8622X_BIT_ADCCFG1_AD_SEL_HDP_MASK (~(1<<4))
|
||||
#define AW8622X_BIT_ADCCFG1_AD_SEL_HDN_MASK (~(1<<3))
|
||||
#define AW8622X_BIT_ADCCFG1_AD_SEL_VBAT_MASK (~(1<<2))
|
||||
#define AW8622X_BIT_ADCCFG1_AD_SEL_TEST_MASK (~(1<<1))
|
||||
#define AW8622X_BIT_ADCCFG1_AD_SEL_D2S_MASK (~(1<<0))
|
||||
|
||||
/* D2SCFG1: reg:0x76 RW */
|
||||
#define AW8622X_BIT_D2SCFG1_CLK_TRIM_MODE_MASK (~(7<<0))
|
||||
#define AW8622X_BIT_D2SCFG1_CLK_TRIM_MODE_48K (0<<0)
|
||||
#define AW8622X_BIT_D2SCFG1_CLK_TRIM_MODE_24K (1<<0)
|
||||
#define AW8622X_BIT_D2SCFG1_CLK_TRIM_MODE_12K (2<<0)
|
||||
#define AW8622X_BIT_D2SCFG1_CLK_TRIM_MODE_6K (3<<0)
|
||||
#define AW8622X_BIT_D2SCFG1_CLK_TRIM_MODE_12M (4<<0)
|
||||
|
||||
/* ANACFG8: reg:0x77 RW */
|
||||
#define AW8622X_BIT_ANACFG8_TRTF_CTRL_HDRV_MASK (~(1<<6))
|
||||
#define AW8622X_BIT_ANACFG8_TRTF_CTRL_HDRV (3<<6)
|
||||
#endif
|
||||
4331
drivers/input/misc/aw8622x_haptic/aw8624.c
Normal file
4331
drivers/input/misc/aw8622x_haptic/aw8624.c
Normal file
File diff suppressed because it is too large
Load Diff
389
drivers/input/misc/aw8622x_haptic/aw8624.h
Normal file
389
drivers/input/misc/aw8622x_haptic/aw8624.h
Normal file
@@ -0,0 +1,389 @@
|
||||
#ifndef _AW8624_H_
|
||||
#define _AW8624_H_
|
||||
|
||||
/*********************************************************
|
||||
*
|
||||
* kernel version
|
||||
*
|
||||
********************************************************/
|
||||
#define TEST_CONT_TO_RAM
|
||||
/*********************************************************
|
||||
*
|
||||
* aw8624.h
|
||||
*
|
||||
********************************************************/
|
||||
#include <linux/regmap.h>
|
||||
#include <linux/timer.h>
|
||||
#include <linux/workqueue.h>
|
||||
#include <linux/hrtimer.h>
|
||||
#include <linux/mutex.h>
|
||||
#include <linux/cdev.h>
|
||||
#include <linux/leds.h>
|
||||
#include <linux/atomic.h>
|
||||
#include <linux/timekeeping.h>
|
||||
#include "haptic.h"
|
||||
|
||||
/*********************************************************
|
||||
*
|
||||
* marco
|
||||
*
|
||||
********************************************************/
|
||||
#define MAX_I2C_BUFFER_SIZE 65536
|
||||
|
||||
#define AW8624_SEQUENCER_SIZE 8
|
||||
#define AW8624_SEQUENCER_LOOP_SIZE 4
|
||||
|
||||
#define AW8624_RTP_I2C_SINGLE_MAX_NUM 512
|
||||
|
||||
#define HAPTIC_MAX_TIMEOUT 10000
|
||||
|
||||
#define AW8624_VBAT_REFER 4400
|
||||
#define AW8624_VBAT_MIN 3500
|
||||
#define AW8624_VBAT_MAX 4500
|
||||
|
||||
|
||||
#define AW8624_CONT_PLAYBACK_MODE AW8624_BIT_CONT_CTRL_CLOSE_PLAYBACK
|
||||
|
||||
/*
|
||||
* trig default high level
|
||||
* ___________ _________________
|
||||
* | |
|
||||
* | |
|
||||
* |___________|
|
||||
* first edge
|
||||
* second edge
|
||||
*
|
||||
*
|
||||
* trig default low level
|
||||
* ___________
|
||||
* | |
|
||||
* | |
|
||||
* __________| |_________________
|
||||
* first edge
|
||||
* second edge
|
||||
*/
|
||||
/* trig config */
|
||||
/*dts config
|
||||
* default_level -> 1: high level; 0: low level
|
||||
* dual_edge -> 1: dual edge; 0: first edge
|
||||
*vib_trig_config = <
|
||||
* 1 1 1 1 2
|
||||
* enable default_level dual_edge first_seq second_seq
|
||||
* 1 1 2 1 2
|
||||
* enable default_level dual_edge first_seq second_seq
|
||||
* 1 1 3 1 2
|
||||
* enable default_level dual_edge first_seq second_seq
|
||||
*/
|
||||
#define AW8624_TRIG_NUM 3
|
||||
|
||||
|
||||
enum aw8624_flags {
|
||||
AW8624_FLAG_NONR = 0,
|
||||
AW8624_FLAG_SKIP_INTERRUPTS = 1,
|
||||
};
|
||||
|
||||
enum aw8624_chipids {
|
||||
AW8624_ID = 1,
|
||||
};
|
||||
|
||||
enum aw8624_haptic_read_write {
|
||||
AW8624_HAPTIC_CMD_READ_REG = 0,
|
||||
AW8624_HAPTIC_CMD_WRITE_REG = 1,
|
||||
};
|
||||
|
||||
enum aw8624_haptic_work_mode {
|
||||
AW8624_HAPTIC_STANDBY_MODE = 0,
|
||||
AW8624_HAPTIC_RAM_MODE = 1,
|
||||
AW8624_HAPTIC_RTP_MODE = 2,
|
||||
AW8624_HAPTIC_TRIG_MODE = 3,
|
||||
AW8624_HAPTIC_CONT_MODE = 4,
|
||||
AW8624_HAPTIC_RAM_LOOP_MODE = 5,
|
||||
};
|
||||
|
||||
enum aw8624_haptic_activate_mode {
|
||||
AW8624_HAPTIC_ACTIVATE_RAM_MODE = 0,
|
||||
AW8624_HAPTIC_ACTIVATE_CONT_MODE = 1,
|
||||
AW8624_HAPTIC_ACTIVATE_RTP_MODE = 2,
|
||||
AW8624_HAPTIC_ACTIVATE_RAM_LOOP_MODE = 3,
|
||||
};
|
||||
|
||||
enum aw8624_haptic_cont_vbat_comp_mode {
|
||||
AW8624_HAPTIC_CONT_VBAT_SW_COMP_MODE = 0,
|
||||
AW8624_HAPTIC_CONT_VBAT_HW_COMP_MODE = 1,
|
||||
};
|
||||
|
||||
enum aw8624_haptic_ram_vbat_comp_mode {
|
||||
AW8624_HAPTIC_RAM_VBAT_COMP_DISABLE = 0,
|
||||
AW8624_HAPTIC_RAM_VBAT_COMP_ENABLE = 1,
|
||||
};
|
||||
|
||||
enum aw8624_haptic_f0_flag {
|
||||
AW8624_HAPTIC_LRA_F0 = 0,
|
||||
AW8624_HAPTIC_CALI_F0 = 1,
|
||||
};
|
||||
|
||||
enum aw8624_haptic_pwm_mode {
|
||||
AW8624_PWM_48K = 0,
|
||||
AW8624_PWM_24K = 1,
|
||||
AW8624_PWM_12K = 2,
|
||||
};
|
||||
|
||||
enum aw8624_haptic_play {
|
||||
AW8624_HAPTIC_PLAY_NULL = 0,
|
||||
AW8624_HAPTIC_PLAY_ENABLE = 1,
|
||||
AW8624_HAPTIC_PLAY_STOP = 2,
|
||||
AW8624_HAPTIC_PLAY_GAIN = 8,
|
||||
};
|
||||
|
||||
enum aw8624_haptic_cmd {
|
||||
AW8624_HAPTIC_CMD_NULL = 0,
|
||||
AW8624_HAPTIC_CMD_ENABLE = 1,
|
||||
AW8624_HAPTIC_CMD_STOP = 255,
|
||||
};
|
||||
|
||||
enum aw8624_haptic_strength {
|
||||
AW8624_LIGHT_MAGNITUDE = 0x3fff,
|
||||
AW8624_MEDIUM_MAGNITUDE = 0x5fff,
|
||||
AW8624_STRONG_MAGNITUDE = 0x7fff,
|
||||
};
|
||||
|
||||
enum aw8624_haptic_cali_lra {
|
||||
NORMAL_CALI = 0,
|
||||
F0_CALI = 1,
|
||||
OSC_CALI = 2,
|
||||
};
|
||||
|
||||
/*********************************************************
|
||||
*
|
||||
* struct
|
||||
*
|
||||
********************************************************/
|
||||
/*struct ram {
|
||||
unsigned int len;
|
||||
unsigned int check_sum;
|
||||
unsigned int base_addr;
|
||||
unsigned char version;
|
||||
unsigned char ram_shift;
|
||||
unsigned char baseaddr_shift;
|
||||
};
|
||||
|
||||
struct haptic_ctr {
|
||||
unsigned char cmd;
|
||||
unsigned char play;
|
||||
unsigned char wavseq;
|
||||
unsigned char loop;
|
||||
unsigned char gain;
|
||||
};
|
||||
|
||||
struct haptic_audio {
|
||||
struct mutex lock;
|
||||
struct hrtimer timer;
|
||||
struct work_struct work;
|
||||
int delay_val;
|
||||
int timer_val;
|
||||
unsigned char cnt;
|
||||
struct haptic_ctr data[256];
|
||||
struct haptic_ctr ctr;
|
||||
unsigned char ori_gain;
|
||||
};*/
|
||||
struct aw8624_dts_info {
|
||||
unsigned int mode;
|
||||
unsigned int f0_pre;
|
||||
unsigned int f0_cali_percen;
|
||||
unsigned int cont_drv_lvl;
|
||||
unsigned int cont_drv_lvl_ov;
|
||||
unsigned int cont_td;
|
||||
unsigned int cont_zc_thr;
|
||||
unsigned int cont_num_brk;
|
||||
unsigned int f0_coeff;
|
||||
unsigned int f0_trace_parameter[4];
|
||||
unsigned int bemf_config[4];
|
||||
unsigned int sw_brake;
|
||||
unsigned int tset;
|
||||
unsigned int r_spare;
|
||||
unsigned int parameter1;
|
||||
unsigned int gain_flag;
|
||||
unsigned int effect_id_boundary;
|
||||
unsigned int effect_max;
|
||||
unsigned int rtp_time[194];
|
||||
unsigned int trig_config[3][5];
|
||||
};
|
||||
|
||||
struct aw8624_tirg {
|
||||
unsigned char enable;
|
||||
unsigned char default_level;
|
||||
unsigned char dual_edge;
|
||||
unsigned char frist_seq;
|
||||
unsigned char second_seq;
|
||||
|
||||
};
|
||||
|
||||
struct aw8624 {
|
||||
struct i2c_client *i2c;
|
||||
struct mutex lock;
|
||||
|
||||
struct work_struct vibrator_work;
|
||||
struct work_struct rtp_work;
|
||||
struct work_struct set_gain_work;
|
||||
struct delayed_work ram_work;
|
||||
struct delayed_work stop_work;
|
||||
|
||||
struct fileops fileops;
|
||||
struct ram ram;
|
||||
|
||||
struct timespec64 start, end;
|
||||
unsigned int timeval_flags;
|
||||
unsigned int osc_cali_flag;
|
||||
unsigned long int microsecond;
|
||||
unsigned int sys_frequency;
|
||||
unsigned int rtp_len;
|
||||
unsigned int lra_calib_data;
|
||||
unsigned int f0_calib_data;
|
||||
|
||||
int reset_gpio;
|
||||
int irq_gpio;
|
||||
|
||||
unsigned char hwen_flag;
|
||||
unsigned char flags;
|
||||
unsigned char chipid;
|
||||
unsigned char chipid_flag;
|
||||
|
||||
unsigned char play_mode;
|
||||
|
||||
unsigned char activate_mode;
|
||||
|
||||
unsigned char auto_boost;
|
||||
unsigned char wk_lock_flag;
|
||||
unsigned char irq_sts_flag;
|
||||
|
||||
int state;
|
||||
int duration;
|
||||
int amplitude;
|
||||
int index;
|
||||
int vmax;
|
||||
int gain;
|
||||
u16 new_gain;
|
||||
int f0_value;
|
||||
unsigned char level;
|
||||
|
||||
unsigned char seq[AW8624_SEQUENCER_SIZE];
|
||||
unsigned char loop[AW8624_SEQUENCER_SIZE];
|
||||
|
||||
unsigned int rtp_cnt;
|
||||
unsigned int rtp_file_num;
|
||||
|
||||
unsigned char rtp_init;
|
||||
unsigned char ram_init;
|
||||
|
||||
unsigned int f0;
|
||||
unsigned int cont_f0;
|
||||
unsigned char max_pos_beme;
|
||||
unsigned char max_neg_beme;
|
||||
unsigned char f0_cali_flag;
|
||||
unsigned int osc_cali_run;
|
||||
|
||||
unsigned char ram_vbat_comp;
|
||||
unsigned int vbat;
|
||||
unsigned int lra;
|
||||
|
||||
struct aw8624_tirg trig[AW8624_TRIG_NUM];
|
||||
|
||||
struct haptic_audio haptic_audio;
|
||||
struct aw8624_dts_info info;
|
||||
atomic_t is_in_rtp_loop;
|
||||
atomic_t exit_in_rtp_loop;
|
||||
wait_queue_head_t wait_q;//wait queue for exit irq mode
|
||||
wait_queue_head_t stop_wait_q; //wait queue for stop rtp mode
|
||||
struct workqueue_struct *work_queue;
|
||||
|
||||
#ifdef INPUT_DEV
|
||||
struct platform_device *pdev;
|
||||
struct device *dev;
|
||||
struct regmap *regmap;
|
||||
struct input_dev *input_dev;
|
||||
struct pwm_device *pwm_dev;
|
||||
struct qti_hap_config config;
|
||||
struct qti_hap_play_info play;
|
||||
struct qti_hap_effect *predefined;
|
||||
struct qti_hap_effect constant;
|
||||
struct regulator *vdd_supply;
|
||||
struct hrtimer stop_timer;
|
||||
struct hrtimer hap_disable_timer;
|
||||
struct hrtimer timer; /*test used ,del */
|
||||
struct mutex rtp_lock;
|
||||
spinlock_t bus_lock;
|
||||
ktime_t last_sc_time;
|
||||
int play_irq;
|
||||
int sc_irq;
|
||||
int effects_count;
|
||||
int sc_det_count;
|
||||
u16 reg_base;
|
||||
bool perm_disable;
|
||||
bool play_irq_en;
|
||||
bool vdd_enabled;
|
||||
int effect_type;
|
||||
int effect_id;
|
||||
int test_val;
|
||||
#endif
|
||||
};
|
||||
|
||||
struct aw8624_container {
|
||||
int len;
|
||||
unsigned char data[];
|
||||
};
|
||||
|
||||
/*********************************************************
|
||||
*
|
||||
* ioctl
|
||||
*
|
||||
********************************************************/
|
||||
struct aw8624_seq_loop {
|
||||
unsigned char loop[AW8624_SEQUENCER_SIZE];
|
||||
};
|
||||
|
||||
struct aw8624_que_seq {
|
||||
unsigned char index[AW8624_SEQUENCER_SIZE];
|
||||
};
|
||||
|
||||
#define AW8624_HAPTIC_IOCTL_MAGIC 'h'
|
||||
|
||||
#define AW8624_HAPTIC_SET_QUE_SEQ _IOWR(AW8624_HAPTIC_IOCTL_MAGIC,\
|
||||
1,\
|
||||
struct aw8624_que_seq*)
|
||||
#define AW8624_HAPTIC_SET_SEQ_LOOP _IOWR(AW8624_HAPTIC_IOCTL_MAGIC,\
|
||||
2,\
|
||||
struct aw8624_seq_loop*)
|
||||
#define AW8624_HAPTIC_PLAY_QUE_SEQ _IOWR(AW8624_HAPTIC_IOCTL_MAGIC,\
|
||||
3,\
|
||||
unsigned int)
|
||||
#define AW8624_HAPTIC_SET_GAIN _IOWR(AW8624_HAPTIC_IOCTL_MAGIC,\
|
||||
6,\
|
||||
unsigned int)
|
||||
#define AW8624_HAPTIC_PLAY_REPEAT_SEQ _IOWR(AW8624_HAPTIC_IOCTL_MAGIC,\
|
||||
7,\
|
||||
unsigned int)
|
||||
|
||||
/*********************************************************
|
||||
*
|
||||
* extern
|
||||
*
|
||||
********************************************************/
|
||||
extern int aw8624_haptics_upload_effect(struct input_dev *dev,
|
||||
struct ff_effect *effect,
|
||||
struct ff_effect *old);
|
||||
extern int aw8624_haptics_playback(struct input_dev *dev, int effect_id,
|
||||
int val);
|
||||
extern int aw8624_haptics_erase(struct input_dev *dev, int effect_id);
|
||||
extern void aw8624_haptics_set_gain_work_routine(struct work_struct *work);
|
||||
extern void aw8624_interrupt_setup(struct aw8624 *aw8624);
|
||||
extern int aw8624_parse_dt(struct device *dev, struct aw8624 *aw8624,
|
||||
struct device_node *np);
|
||||
extern int aw8624_vibrator_init(struct aw8624 *aw8624);
|
||||
extern int aw8624_haptic_init(struct aw8624 *aw8624);
|
||||
extern int aw8624_ram_init(struct aw8624 *aw8624);
|
||||
extern void aw8624_haptics_set_gain(struct input_dev *dev, u16 gain);
|
||||
extern irqreturn_t aw8624_irq(int irq, void *data);
|
||||
extern struct attribute_group aw8624_vibrator_attribute_group;
|
||||
|
||||
#endif
|
||||
|
||||
118
drivers/input/misc/aw8622x_haptic/aw8624_config.h
Normal file
118
drivers/input/misc/aw8622x_haptic/aw8624_config.h
Normal file
@@ -0,0 +1,118 @@
|
||||
#ifndef __AW8624_CONFIG_H__
|
||||
#define __AW8624_CONFIG_H__
|
||||
|
||||
#define AW8624_BSTCFG_PEAKCUR_LIMIT 0x07
|
||||
#define AW8624_DEFAULT_PEAKCUR AW8624_BIT_BSTCFG_PEAKCUR_3P5A
|
||||
|
||||
#define AW8624_CONT_PLAYBACK_MODE AW8624_BIT_CONT_CTRL_CLOSE_PLAYBACK
|
||||
|
||||
/*#define CONFIG_DEBUG_FS*/
|
||||
|
||||
/*#ifdef INPUT_DEV*/
|
||||
#if 1
|
||||
/* haptics module register definitions */
|
||||
#define REG_HAP_STATUS1 0x0A
|
||||
#define HAP_SC_DET_BIT BIT(3)
|
||||
#define HAP_BUSY_BIT BIT(1)
|
||||
|
||||
#define REG_HAP_EN_CTL1 0x46
|
||||
#define HAP_EN_BIT BIT(7)
|
||||
|
||||
#define REG_HAP_EN_CTL2 0x48
|
||||
#define HAP_AUTO_STANDBY_EN_BIT BIT(1)
|
||||
#define HAP_BRAKE_EN_BIT BIT(0)
|
||||
|
||||
#define REG_HAP_EN_CTL3 0x4A
|
||||
#define HAP_HBRIDGE_EN_BIT BIT(7)
|
||||
#define HAP_PWM_SIGNAL_EN_BIT BIT(6)
|
||||
#define HAP_ILIM_EN_BIT BIT(5)
|
||||
#define HAP_ILIM_CC_EN_BIT BIT(4)
|
||||
#define HAP_AUTO_RES_RBIAS_EN_BIT BIT(3)
|
||||
#define HAP_DAC_EN_BIT BIT(2)
|
||||
#define HAP_ZX_HYST_EN_BIT BIT(1)
|
||||
#define HAP_PWM_CTL_EN_BIT BIT(0)
|
||||
|
||||
#define REG_HAP_AUTO_RES_CTRL 0x4B
|
||||
#define HAP_AUTO_RES_EN_BIT BIT(7)
|
||||
#define HAP_SEL_AUTO_RES_PERIOD BIT(6)
|
||||
#define HAP_AUTO_RES_CNT_ERR_DELTA_MASK GENMASK(5, 4)
|
||||
#define HAP_AUTO_RES_CNT_ERR_DELTA_SHIFT 4
|
||||
#define HAP_AUTO_RES_ERR_RECOVERY_BIT BIT(3)
|
||||
#define HAP_AUTO_RES_EN_DLY_MASK GENMASK(2, 0)
|
||||
#define AUTO_RES_CNT_ERR_DELTA(x) (x << HAP_AUTO_RES_CNT_ERR_DELTA_SHIFT)
|
||||
#define AUTO_RES_EN_DLY(x) x
|
||||
|
||||
#define REG_HAP_CFG1 0x4C
|
||||
#define REG_HAP_CFG2 0x4D
|
||||
#define HAP_LRA_RES_TYPE_BIT BIT(0)
|
||||
|
||||
#define REG_HAP_SEL 0x4E
|
||||
#define HAP_WF_SOURCE_MASK GENMASK(5, 4)
|
||||
#define HAP_WF_SOURCE_SHIFT 4
|
||||
#define HAP_WF_TRIGGER_BIT BIT(0)
|
||||
#define HAP_WF_SOURCE_VMAX (0 << HAP_WF_SOURCE_SHIFT)
|
||||
#define HAP_WF_SOURCE_BUFFER (1 << HAP_WF_SOURCE_SHIFT)
|
||||
#define HAP_WF_SOURCE_AUDIO (2 << HAP_WF_SOURCE_SHIFT)
|
||||
#define HAP_WF_SOURCE_PWM (3 << HAP_WF_SOURCE_SHIFT)
|
||||
|
||||
#define REG_HAP_AUTO_RES_CFG 0x4F
|
||||
#define HAP_AUTO_RES_MODE_BIT BIT(7)
|
||||
#define HAP_AUTO_RES_MODE_SHIFT 7
|
||||
#define HAP_AUTO_RES_CAL_DURATON_MASK GENMASK(6, 5)
|
||||
#define HAP_CAL_EOP_EN_BIT BIT(3)
|
||||
#define HAP_CAL_PERIOD_MASK GENMASK(2, 0)
|
||||
#define HAP_CAL_OPT3_EVERY_8_PERIOD 2
|
||||
|
||||
#define REG_HAP_SLEW_CFG 0x50
|
||||
#define REG_HAP_VMAX_CFG 0x51
|
||||
#define HAP_VMAX_SIGN_BIT BIT(7)
|
||||
#define HAP_VMAX_OVD_BIT BIT(6)
|
||||
#define HAP_VMAX_MV_MASK GENMASK(5, 1)
|
||||
#define HAP_VMAX_MV_SHIFT 1
|
||||
#define HAP_VMAX_MV_LSB 116
|
||||
|
||||
#define REG_HAP_ILIM_CFG 0x52
|
||||
#define HAP_ILIM_SEL_1000MA BIT(1)
|
||||
#define HAP_ILIM_DEFAULT_SEL HAP_ILIM_SEL_1000MA
|
||||
#define REG_HAP_SC_DEB_CFG 0x53
|
||||
#define REG_HAP_RATE_CFG1 0x54
|
||||
#define REG_HAP_RATE_CFG2 0x55
|
||||
#define REG_HAP_INTERNAL_PWM 0x56
|
||||
#define REG_HAP_EXTERNAL_PWM 0x57
|
||||
#define REG_HAP_PWM 0x58
|
||||
|
||||
#define REG_HAP_SC_CLR 0x59
|
||||
#define HAP_SC_CLR_BIT BIT(0)
|
||||
|
||||
#define REG_HAP_ZX_CFG 0x5A
|
||||
#define HAP_ZX_DET_DEB_MASK GENMASK(2, 0)
|
||||
#define ZX_DET_DEB_10US 0
|
||||
#define ZX_DET_DEB_20US 1
|
||||
#define ZX_DET_DEB_40US 2
|
||||
#define ZX_DET_DEB_80US 3
|
||||
|
||||
#define REG_HAP_BRAKE 0x5C
|
||||
#define HAP_BRAKE_PATTERN_MASK 0x3
|
||||
#define HAP_BRAKE_PATTERN_SHIFT 2
|
||||
|
||||
#define REG_HAP_WF_REPEAT 0x5E
|
||||
#define HAP_WF_REPEAT_MASK GENMASK(6, 4)
|
||||
#define HAP_WF_REPEAT_SHIFT 4
|
||||
#define HAP_WF_S_REPEAT_MASK GENMASK(1, 0)
|
||||
|
||||
#define REG_HAP_WF_S1 0x60
|
||||
#define HAP_WF_SIGN_BIT BIT(7)
|
||||
#define HAP_WF_OVD_BIT BIT(6)
|
||||
#define HAP_WF_AMP_BIT GENMASK(5, 1)
|
||||
#define HAP_WF_AMP_SHIFT 1
|
||||
|
||||
#define REG_HAP_PLAY 0x70
|
||||
#define HAP_PLAY_BIT BIT(7)
|
||||
|
||||
#define REG_HAP_SEC_ACCESS 0xD0
|
||||
|
||||
static int wf_repeat[8] = { 1, 2, 4, 8, 16, 32, 64, 128 };
|
||||
static int wf_s_repeat[4] = { 1, 2, 4, 8 };
|
||||
#endif
|
||||
#endif
|
||||
|
||||
460
drivers/input/misc/aw8622x_haptic/aw8624_params.h
Normal file
460
drivers/input/misc/aw8622x_haptic/aw8624_params.h
Normal file
@@ -0,0 +1,460 @@
|
||||
#ifndef __AW8624_PARAMS_H__
|
||||
#define __AW8624_PARAMS_H__
|
||||
|
||||
//#include <stdint.h>
|
||||
|
||||
uint8_t aw8624_ram_data[5416] = {
|
||||
0xE5, 0x8D, 0x08, 0x00, 0x85, 0x08, 0x2D, 0x0A, 0xE7, 0x0A, 0xE8, 0x0D,
|
||||
0x31, 0x0D, 0x32, 0x0F, 0x7B, 0x0F, 0x7C, 0x11, 0xC5, 0x11, 0xC6, 0x13,
|
||||
0x58, 0x13, 0x59, 0x15, 0xA2, 0x15, 0xA3, 0x17, 0xA8, 0x17, 0xA9, 0x18,
|
||||
0xD1, 0x18, 0xD2, 0x1A, 0x64, 0x1A, 0x65, 0x1C, 0xAE, 0x1C, 0xAF, 0x1D,
|
||||
0x23, 0x00, 0x06, 0x0C, 0x12, 0x18, 0x1E, 0x23, 0x29, 0x2F, 0x34, 0x3A,
|
||||
0x3F, 0x44, 0x48, 0x4D, 0x51, 0x55, 0x59, 0x5D, 0x60, 0x63, 0x65, 0x68,
|
||||
0x6A, 0x6C, 0x6D, 0x6E, 0x6F, 0x6F, 0x6F, 0x6F, 0x6F, 0x6E, 0x6D, 0x6B,
|
||||
0x69, 0x67, 0x65, 0x62, 0x5F, 0x5B, 0x58, 0x54, 0x50, 0x4B, 0x47, 0x42,
|
||||
0x3D, 0x38, 0x33, 0x2D, 0x27, 0x22, 0x1C, 0x16, 0x10, 0x0A, 0x04, 0xFF,
|
||||
0xF9, 0xF2, 0xEC, 0xE6, 0xE1, 0xDB, 0xD5, 0xD0, 0xCA, 0xC5, 0xC0, 0xBB,
|
||||
0xB6, 0xB2, 0xAE, 0xAA, 0xA6, 0xA2, 0x9F, 0x9C, 0x9A, 0x98, 0x96, 0x94,
|
||||
0x93, 0x92, 0x91, 0x91, 0x91, 0x91, 0x92, 0x92, 0x94, 0x95, 0x97, 0x9A,
|
||||
0x9C, 0x9F, 0xA2, 0xA6, 0xA9, 0xAD, 0xB1, 0xB6, 0xBB, 0xBF, 0xC4, 0xCA,
|
||||
0xCF, 0xD5, 0xDA, 0xE0, 0xE6, 0xEC, 0xF2, 0xF8, 0x00, 0x06, 0x0C, 0x12,
|
||||
0x18, 0x1E, 0x23, 0x29, 0x2F, 0x34, 0x3A, 0x3F, 0x44, 0x48, 0x4D, 0x51,
|
||||
0x55, 0x59, 0x5D, 0x60, 0x63, 0x65, 0x68, 0x6A, 0x6C, 0x6D, 0x6E, 0x6F,
|
||||
0x6F, 0x6F, 0x6F, 0x6F, 0x6E, 0x6D, 0x6B, 0x69, 0x67, 0x65, 0x62, 0x5F,
|
||||
0x5B, 0x58, 0x54, 0x50, 0x4B, 0x47, 0x42, 0x3D, 0x38, 0x33, 0x2D, 0x27,
|
||||
0x22, 0x1C, 0x16, 0x10, 0x0A, 0xC4, 0xBD, 0xB7, 0xB2, 0xAE, 0xAA, 0xA6,
|
||||
0xA3, 0xA1, 0x9F, 0x9D, 0x9B, 0x9A, 0x98, 0x97, 0x97, 0x96, 0x95, 0x95,
|
||||
0x94, 0x94, 0x94, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93,
|
||||
0x94, 0x94, 0x94, 0x95, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9A, 0x9B, 0x9D,
|
||||
0x9F, 0xA1, 0xA4, 0xA7, 0xAB, 0xAF, 0xB3, 0xB9, 0xBF, 0xC7, 0xCF, 0xD9,
|
||||
0xE4, 0xF1, 0x3C, 0x43, 0x49, 0x4E, 0x52, 0x56, 0x5A, 0x5D, 0x5F, 0x61,
|
||||
0x63, 0x65, 0x66, 0x68, 0x69, 0x69, 0x6A, 0x6B, 0x6B, 0x6C, 0x6C, 0x6C,
|
||||
0x6D, 0x6D, 0x6D, 0x6D, 0x6D, 0x6D, 0x6D, 0x6D, 0x6D, 0x6C, 0x6C, 0x6B,
|
||||
0x6B, 0x6A, 0x6A, 0x69, 0x68, 0x67, 0x65, 0x64, 0x62, 0x60, 0x5D, 0x5B,
|
||||
0x57, 0x54, 0x4F, 0x4A, 0x44, 0x3D, 0x36, 0x2C, 0x22, 0x16, 0x08, 0xF8,
|
||||
0xEA, 0xDE, 0xD4, 0xCA, 0xC3, 0xBC, 0xB6, 0xB1, 0xAD, 0xA9, 0xA5, 0xA3,
|
||||
0xA0, 0x9E, 0x9C, 0x9B, 0x99, 0x98, 0x97, 0x97, 0x96, 0x95, 0x95, 0x94,
|
||||
0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x95, 0x95, 0x96,
|
||||
0x96, 0x97, 0x98, 0x99, 0x9A, 0x9C, 0x9D, 0x9F, 0xA1, 0xA4, 0xA7, 0xAB,
|
||||
0xAF, 0xB3, 0xB9, 0xBF, 0xC7, 0xCF, 0xD9, 0xE4, 0xF1, 0x00, 0x0A, 0x14,
|
||||
0x1E, 0x28, 0x31, 0x3A, 0x43, 0x4A, 0x52, 0x58, 0x5E, 0x63, 0x68, 0x6B,
|
||||
0x6D, 0x6F, 0x6F, 0x6F, 0x6E, 0x6C, 0x69, 0x65, 0x60, 0x5A, 0x54, 0x4D,
|
||||
0x45, 0x3C, 0x34, 0x2A, 0x21, 0x17, 0x0D, 0x02, 0xF9, 0xEF, 0xE5, 0xDB,
|
||||
0xD2, 0xC9, 0xC0, 0xB8, 0xB0, 0xA9, 0xA3, 0x9E, 0x9A, 0x96, 0x93, 0x91,
|
||||
0x91, 0x91, 0x92, 0x94, 0x96, 0x9A, 0x9F, 0xA4, 0xAA, 0xB1, 0xB9, 0xC1,
|
||||
0xCA, 0xD3, 0xDC, 0xE6, 0xF0, 0x3C, 0x43, 0x49, 0x4E, 0x52, 0x56, 0x5A,
|
||||
0x5D, 0x5F, 0x61, 0x63, 0x65, 0x66, 0x68, 0x69, 0x69, 0x6A, 0x6B, 0x6B,
|
||||
0x6C, 0x6C, 0x6C, 0x6D, 0x6D, 0x6D, 0x6D, 0x6D, 0x6D, 0x6D, 0x6D, 0x6D,
|
||||
0x6C, 0x6C, 0x6B, 0x6B, 0x6A, 0x6A, 0x69, 0x68, 0x67, 0x65, 0x64, 0x62,
|
||||
0x60, 0x5D, 0x5B, 0x57, 0x54, 0x4F, 0x4A, 0x44, 0x3D, 0x36, 0x2C, 0x22,
|
||||
0x16, 0x08, 0xF8, 0xEA, 0xDE, 0xD4, 0xCA, 0xC3, 0xBC, 0xB6, 0xB1, 0xAD,
|
||||
0xA9, 0xA5, 0xA3, 0xA0, 0x9E, 0x9C, 0x9B, 0x99, 0x98, 0x97, 0x97, 0x96,
|
||||
0x95, 0x95, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94,
|
||||
0x95, 0x95, 0x96, 0x97, 0x97, 0x98, 0x99, 0x9B, 0x9C, 0x9E, 0xA0, 0xA3,
|
||||
0xA5, 0xA9, 0xAD, 0xB1, 0xB6, 0xBC, 0xC3, 0xCA, 0xD4, 0xDE, 0xEA, 0xF8,
|
||||
0x08, 0x16, 0x22, 0x2C, 0x36, 0x3D, 0x44, 0x4A, 0x4F, 0x53, 0x57, 0x5A,
|
||||
0x5D, 0x60, 0x62, 0x64, 0x65, 0x66, 0x68, 0x69, 0x69, 0x6A, 0x6B, 0x6B,
|
||||
0x6B, 0x6C, 0x6C, 0x6C, 0x6C, 0x6C, 0x6C, 0x6C, 0x6B, 0x6B, 0x6B, 0x6A,
|
||||
0x69, 0x69, 0x68, 0x66, 0x65, 0x64, 0x62, 0x60, 0x5D, 0x5A, 0x57, 0x53,
|
||||
0x4F, 0x4A, 0x44, 0x3D, 0x36, 0x2C, 0x22, 0x16, 0x08, 0xF8, 0xEA, 0xDE,
|
||||
0xD4, 0xCA, 0xC3, 0xBC, 0xB6, 0xB1, 0xAD, 0xA9, 0xA5, 0xA3, 0xA0, 0x9E,
|
||||
0x9C, 0x9B, 0x99, 0x98, 0x97, 0x97, 0x96, 0x95, 0x95, 0x94, 0x94, 0x94,
|
||||
0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x95, 0x95, 0x96, 0x96, 0x97,
|
||||
0x98, 0x99, 0x9A, 0x9C, 0x9D, 0x9F, 0xA1, 0xA4, 0xA7, 0xAB, 0xAF, 0xB3,
|
||||
0xB9, 0xBF, 0xC7, 0xCF, 0xD9, 0xE4, 0xF1, 0x00, 0x02, 0x05, 0x08, 0x0A,
|
||||
0x0D, 0x10, 0x12, 0x15, 0x17, 0x19, 0x1C, 0x1E, 0x20, 0x22, 0x24, 0x26,
|
||||
0x27, 0x29, 0x2A, 0x2C, 0x2D, 0x2E, 0x2F, 0x30, 0x30, 0x31, 0x31, 0x31,
|
||||
0x31, 0x31, 0x31, 0x31, 0x30, 0x30, 0x2F, 0x2E, 0x2D, 0x2B, 0x2A, 0x29,
|
||||
0x27, 0x25, 0x23, 0x21, 0x1F, 0x1D, 0x1B, 0x19, 0x16, 0x14, 0x11, 0x0F,
|
||||
0x0C, 0x09, 0x07, 0x04, 0x00, 0x06, 0x0C, 0x12, 0x18, 0x1E, 0x23, 0x29,
|
||||
0x2F, 0x34, 0x3A, 0x3F, 0x44, 0x48, 0x4D, 0x51, 0x55, 0x59, 0x5D, 0x60,
|
||||
0x63, 0x65, 0x68, 0x6A, 0x6C, 0x6D, 0x6E, 0x6F, 0x6F, 0x6F, 0x6F, 0x6F,
|
||||
0x6E, 0x6D, 0x6B, 0x69, 0x67, 0x65, 0x62, 0x5F, 0x5B, 0x58, 0x54, 0x50,
|
||||
0x4B, 0x47, 0x42, 0x3D, 0x38, 0x33, 0x2D, 0x27, 0x22, 0x1C, 0x16, 0x10,
|
||||
0x0A, 0x04, 0xFF, 0xF9, 0xF2, 0xEC, 0xE6, 0xE1, 0xDB, 0xD5, 0xD0, 0xCA,
|
||||
0xC5, 0xC0, 0xBB, 0xB6, 0xB2, 0xAE, 0xAA, 0xA6, 0xA2, 0x9F, 0x9C, 0x9A,
|
||||
0x98, 0x96, 0x94, 0x93, 0x92, 0x91, 0x91, 0x91, 0x91, 0x92, 0x92, 0x94,
|
||||
0x95, 0x97, 0x9A, 0x9C, 0x9F, 0xA2, 0xA6, 0xA9, 0xAD, 0xB1, 0xB6, 0xBB,
|
||||
0xBF, 0xC4, 0xCA, 0xCF, 0xD5, 0xDA, 0xE0, 0xE6, 0xEC, 0xF2, 0xF8, 0xFE,
|
||||
0x03, 0x09, 0x0F, 0x15, 0x1B, 0x21, 0x27, 0x2D, 0x32, 0x37, 0x3D, 0x42,
|
||||
0x47, 0x4B, 0x50, 0x54, 0x58, 0x5B, 0x5F, 0x62, 0x64, 0x67, 0x69, 0x6B,
|
||||
0x6D, 0x6E, 0x6F, 0x6F, 0x6F, 0x6F, 0x6F, 0x6E, 0x6D, 0x6C, 0x6A, 0x68,
|
||||
0x66, 0x63, 0x60, 0x5D, 0x59, 0x55, 0x51, 0x4D, 0x49, 0x44, 0x3F, 0x3A,
|
||||
0x35, 0x2F, 0x2A, 0x24, 0x1E, 0x18, 0x12, 0x0C, 0x06, 0x00, 0xFB, 0xF5,
|
||||
0xEF, 0xE9, 0xE3, 0xDD, 0xD7, 0xD2, 0xCC, 0xC7, 0xC2, 0xBD, 0xB8, 0xB3,
|
||||
0xAF, 0xAB, 0xA7, 0xA4, 0xA0, 0x9D, 0x9B, 0x98, 0x96, 0x95, 0x93, 0x92,
|
||||
0x91, 0x91, 0x91, 0x91, 0x91, 0x92, 0x93, 0x95, 0x97, 0x99, 0x9B, 0x9E,
|
||||
0xA1, 0xA4, 0xA8, 0xAC, 0xB0, 0xB4, 0xB9, 0xBE, 0xC3, 0xC8, 0xCD, 0xD3,
|
||||
0xD8, 0xDE, 0xE4, 0xEA, 0xF0, 0xF6, 0xFC, 0x01, 0x07, 0x0D, 0x13, 0x19,
|
||||
0x1F, 0x25, 0x2A, 0x30, 0x35, 0x3B, 0x40, 0x45, 0x49, 0x4E, 0x52, 0x56,
|
||||
0x5A, 0x5D, 0x60, 0x63, 0x66, 0x68, 0x6A, 0x6C, 0x6D, 0x6E, 0x6F, 0x6F,
|
||||
0x6F, 0x6F, 0x6F, 0x6E, 0x6C, 0x6B, 0x69, 0x67, 0x64, 0x61, 0x5E, 0x5B,
|
||||
0x57, 0x53, 0x4F, 0x4A, 0x46, 0x41, 0x3C, 0x37, 0x31, 0x2C, 0x26, 0x20,
|
||||
0x1A, 0x14, 0x0E, 0x08, 0x00, 0xF6, 0xEC, 0xE2, 0xD8, 0xCF, 0xC6, 0xBD,
|
||||
0xB6, 0xAE, 0xA8, 0xA2, 0x9D, 0x98, 0x95, 0x93, 0x91, 0x91, 0x91, 0x92,
|
||||
0x94, 0x97, 0x9B, 0xA0, 0xA6, 0xAC, 0xB3, 0xBB, 0xC4, 0xCC, 0xD6, 0xDF,
|
||||
0xE9, 0xF3, 0xFE, 0x07, 0x11, 0x1B, 0x25, 0x2E, 0x37, 0x40, 0x48, 0x50,
|
||||
0x57, 0x5D, 0x62, 0x66, 0x6A, 0x6D, 0x6F, 0x6F, 0x6F, 0x6E, 0x6C, 0x6A,
|
||||
0x66, 0x61, 0x5C, 0x56, 0x4F, 0x47, 0x3F, 0x36, 0x2D, 0x24, 0x1A, 0x10,
|
||||
0xC4, 0xBD, 0xB7, 0xB2, 0xAE, 0xAA, 0xA6, 0xA3, 0xA1, 0x9F, 0x9D, 0x9B,
|
||||
0x9A, 0x98, 0x97, 0x97, 0x96, 0x95, 0x95, 0x94, 0x94, 0x94, 0x93, 0x93,
|
||||
0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x94, 0x94, 0x95, 0x95, 0x96,
|
||||
0x96, 0x97, 0x98, 0x99, 0x9B, 0x9C, 0x9E, 0xA0, 0xA3, 0xA5, 0xA9, 0xAC,
|
||||
0xB1, 0xB6, 0xBC, 0xC3, 0xCA, 0xD4, 0xDE, 0xEA, 0xF8, 0x08, 0x16, 0x22,
|
||||
0x2C, 0x36, 0x3D, 0x44, 0x4A, 0x4F, 0x53, 0x57, 0x5B, 0x5D, 0x60, 0x62,
|
||||
0x64, 0x65, 0x67, 0x68, 0x69, 0x69, 0x6A, 0x6B, 0x6B, 0x6C, 0x6C, 0x6C,
|
||||
0x6C, 0x6C, 0x6C, 0x6C, 0x6C, 0x6C, 0x6C, 0x6B, 0x6B, 0x6A, 0x69, 0x69,
|
||||
0x68, 0x67, 0x65, 0x64, 0x62, 0x60, 0x5D, 0x5B, 0x57, 0x53, 0x4F, 0x4A,
|
||||
0x44, 0x3D, 0x36, 0x2C, 0x22, 0x16, 0x08, 0xF8, 0xEA, 0xDE, 0xD4, 0xCA,
|
||||
0xC3, 0xBC, 0xB6, 0xB1, 0xAD, 0xA9, 0xA5, 0xA3, 0xA0, 0x9E, 0x9C, 0x9B,
|
||||
0x99, 0x98, 0x97, 0x97, 0x96, 0x95, 0x95, 0x94, 0x94, 0x94, 0x94, 0x94,
|
||||
0x94, 0x94, 0x94, 0x94, 0x94, 0x95, 0x95, 0x96, 0x96, 0x97, 0x98, 0x99,
|
||||
0x9B, 0x9C, 0x9E, 0xA0, 0xA2, 0xA5, 0xA8, 0xAC, 0xB0, 0xB5, 0xBB, 0xC1,
|
||||
0xC9, 0xD2, 0xDC, 0xE8, 0xF5, 0x00, 0x02, 0x05, 0x08, 0x0A, 0x0D, 0x10,
|
||||
0x12, 0x15, 0x17, 0x19, 0x1C, 0x1E, 0x20, 0x22, 0x24, 0x26, 0x27, 0x29,
|
||||
0x2A, 0x2C, 0x2D, 0x2E, 0x2F, 0x30, 0x30, 0x31, 0x31, 0x31, 0x31, 0x31,
|
||||
0x31, 0x31, 0x30, 0x30, 0x2F, 0x2E, 0x2D, 0x2B, 0x2A, 0x29, 0x27, 0x25,
|
||||
0x23, 0x21, 0x1F, 0x1D, 0x1B, 0x19, 0x16, 0x14, 0x11, 0x0F, 0x0C, 0x09,
|
||||
0x07, 0x04, 0x00, 0x06, 0x0C, 0x12, 0x18, 0x1E, 0x23, 0x29, 0x2F, 0x34,
|
||||
0x3A, 0x3F, 0x44, 0x48, 0x4D, 0x51, 0x55, 0x59, 0x5D, 0x60, 0x63, 0x65,
|
||||
0x68, 0x6A, 0x6C, 0x6D, 0x6E, 0x6F, 0x6F, 0x6F, 0x6F, 0x6F, 0x6E, 0x6D,
|
||||
0x6B, 0x69, 0x67, 0x65, 0x62, 0x5F, 0x5B, 0x58, 0x54, 0x50, 0x4B, 0x47,
|
||||
0x42, 0x3D, 0x38, 0x33, 0x2D, 0x27, 0x22, 0x1C, 0x16, 0x10, 0x0A, 0x04,
|
||||
0xFF, 0xF9, 0xF2, 0xEC, 0xE6, 0xE1, 0xDB, 0xD5, 0xD0, 0xCA, 0xC5, 0xC0,
|
||||
0xBB, 0xB6, 0xB2, 0xAE, 0xAA, 0xA6, 0xA2, 0x9F, 0x9C, 0x9A, 0x98, 0x96,
|
||||
0x94, 0x93, 0x92, 0x91, 0x91, 0x91, 0x91, 0x92, 0x92, 0x94, 0x95, 0x97,
|
||||
0x9A, 0x9C, 0x9F, 0xA2, 0xA6, 0xA9, 0xAD, 0xB1, 0xB6, 0xBB, 0xBF, 0xC4,
|
||||
0xCA, 0xCF, 0xD5, 0xDA, 0xE0, 0xE6, 0xEC, 0xF2, 0xF8, 0xFE, 0x03, 0x09,
|
||||
0x0F, 0x15, 0x1B, 0x21, 0x27, 0x2D, 0x32, 0x37, 0x3D, 0x42, 0x47, 0x4B,
|
||||
0x50, 0x54, 0x58, 0x5B, 0x5F, 0x62, 0x64, 0x67, 0x69, 0x6B, 0x6D, 0x6E,
|
||||
0x6F, 0x6F, 0x6F, 0x6F, 0x6F, 0x6E, 0x6D, 0x6C, 0x6A, 0x68, 0x66, 0x63,
|
||||
0x60, 0x5D, 0x59, 0x55, 0x51, 0x4D, 0x49, 0x44, 0x3F, 0x3A, 0x35, 0x2F,
|
||||
0x2A, 0x24, 0x1E, 0x18, 0x12, 0x0C, 0x06, 0x00, 0xFB, 0xF5, 0xEF, 0xE9,
|
||||
0xE3, 0xDD, 0xD7, 0xD2, 0xCC, 0xC7, 0xC2, 0xBD, 0xB8, 0xB3, 0xAF, 0xAB,
|
||||
0xA7, 0xA4, 0xA0, 0x9D, 0x9B, 0x98, 0x96, 0x95, 0x93, 0x92, 0x91, 0x91,
|
||||
0x91, 0x91, 0x91, 0x92, 0x93, 0x95, 0x97, 0x99, 0x9B, 0x9E, 0xA1, 0xA4,
|
||||
0xA8, 0xAC, 0xB0, 0xB4, 0xB9, 0xBE, 0xC3, 0xC8, 0xCD, 0xD3, 0xD8, 0xDE,
|
||||
0xE4, 0xEA, 0xF0, 0xF6, 0xFC, 0x01, 0x07, 0x0D, 0x13, 0x19, 0x1F, 0x25,
|
||||
0x2A, 0x30, 0x35, 0x3B, 0x40, 0x45, 0x49, 0x4E, 0x52, 0x56, 0x5A, 0x5D,
|
||||
0x60, 0x63, 0x66, 0x68, 0x6A, 0x6C, 0x6D, 0x6E, 0x6F, 0x6F, 0x6F, 0x6F,
|
||||
0x6F, 0x6E, 0x6C, 0x6B, 0x69, 0x67, 0x64, 0x61, 0x5E, 0x5B, 0x57, 0x53,
|
||||
0x4F, 0x4A, 0x46, 0x41, 0x3C, 0x37, 0x31, 0x2C, 0x26, 0x20, 0x1A, 0x14,
|
||||
0x0E, 0x08, 0x00, 0xF6, 0xEC, 0xE2, 0xD8, 0xCF, 0xC6, 0xBD, 0xB6, 0xAE,
|
||||
0xA8, 0xA2, 0x9D, 0x98, 0x95, 0x93, 0x91, 0x91, 0x91, 0x92, 0x94, 0x97,
|
||||
0x9B, 0xA0, 0xA6, 0xAC, 0xB3, 0xBB, 0xC4, 0xCC, 0xD6, 0xDF, 0xE9, 0xF3,
|
||||
0xFE, 0x07, 0x11, 0x1B, 0x25, 0x2E, 0x37, 0x40, 0x48, 0x50, 0x57, 0x5D,
|
||||
0x62, 0x66, 0x6A, 0x6D, 0x6F, 0x6F, 0x6F, 0x6E, 0x6C, 0x6A, 0x66, 0x61,
|
||||
0x5C, 0x56, 0x4F, 0x47, 0x3F, 0x36, 0x2D, 0x24, 0x1A, 0x10, 0xC4, 0xBD,
|
||||
0xB7, 0xB2, 0xAE, 0xAA, 0xA6, 0xA3, 0xA1, 0x9F, 0x9D, 0x9B, 0x9A, 0x98,
|
||||
0x97, 0x97, 0x96, 0x95, 0x95, 0x94, 0x94, 0x94, 0x93, 0x93, 0x93, 0x93,
|
||||
0x93, 0x93, 0x93, 0x93, 0x93, 0x94, 0x94, 0x95, 0x95, 0x96, 0x96, 0x97,
|
||||
0x98, 0x99, 0x9B, 0x9C, 0x9E, 0xA0, 0xA3, 0xA5, 0xA9, 0xAC, 0xB1, 0xB6,
|
||||
0xBC, 0xC3, 0xCA, 0xD4, 0xDE, 0xEA, 0xF8, 0x08, 0x16, 0x22, 0x2C, 0x36,
|
||||
0x3D, 0x44, 0x4A, 0x4F, 0x53, 0x57, 0x5B, 0x5D, 0x60, 0x62, 0x64, 0x65,
|
||||
0x67, 0x68, 0x69, 0x69, 0x6A, 0x6B, 0x6B, 0x6C, 0x6C, 0x6C, 0x6C, 0x6C,
|
||||
0x6C, 0x6C, 0x6C, 0x6C, 0x6C, 0x6B, 0x6B, 0x6A, 0x69, 0x69, 0x68, 0x67,
|
||||
0x65, 0x64, 0x62, 0x60, 0x5D, 0x5B, 0x57, 0x53, 0x4F, 0x4A, 0x44, 0x3D,
|
||||
0x36, 0x2C, 0x22, 0x16, 0x08, 0xF8, 0xEA, 0xDE, 0xD4, 0xCA, 0xC3, 0xBC,
|
||||
0xB6, 0xB1, 0xAD, 0xA9, 0xA5, 0xA3, 0xA0, 0x9E, 0x9C, 0x9B, 0x99, 0x98,
|
||||
0x97, 0x97, 0x96, 0x95, 0x95, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94,
|
||||
0x94, 0x94, 0x94, 0x95, 0x95, 0x96, 0x96, 0x97, 0x98, 0x99, 0x9B, 0x9C,
|
||||
0x9E, 0xA0, 0xA2, 0xA5, 0xA8, 0xAC, 0xB0, 0xB5, 0xBB, 0xC1, 0xC9, 0xD2,
|
||||
0xDC, 0xE8, 0xF5, 0x00, 0x02, 0x05, 0x08, 0x0A, 0x0D, 0x10, 0x12, 0x15,
|
||||
0x17, 0x19, 0x1C, 0x1E, 0x20, 0x22, 0x24, 0x26, 0x27, 0x29, 0x2A, 0x2C,
|
||||
0x2D, 0x2E, 0x2F, 0x30, 0x30, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31,
|
||||
0x30, 0x30, 0x2F, 0x2E, 0x2D, 0x2B, 0x2A, 0x29, 0x27, 0x25, 0x23, 0x21,
|
||||
0x1F, 0x1D, 0x1B, 0x19, 0x16, 0x14, 0x11, 0x0F, 0x0C, 0x09, 0x07, 0x04,
|
||||
0x00, 0x06, 0x0C, 0x12, 0x18, 0x1E, 0x23, 0x29, 0x2F, 0x34, 0x3A, 0x3F,
|
||||
0x44, 0x48, 0x4D, 0x51, 0x55, 0x59, 0x5D, 0x60, 0x63, 0x65, 0x68, 0x6A,
|
||||
0x6C, 0x6D, 0x6E, 0x6F, 0x6F, 0x6F, 0x6F, 0x6F, 0x6E, 0x6D, 0x6B, 0x69,
|
||||
0x67, 0x65, 0x62, 0x5F, 0x5B, 0x58, 0x54, 0x50, 0x4B, 0x47, 0x42, 0x3D,
|
||||
0x38, 0x33, 0x2D, 0x27, 0x22, 0x1C, 0x16, 0x10, 0x0A, 0x04, 0xFF, 0xF9,
|
||||
0xF2, 0xEC, 0xE6, 0xE1, 0xDB, 0xD5, 0xD0, 0xCA, 0xC5, 0xC0, 0xBB, 0xB6,
|
||||
0xB2, 0xAE, 0xAA, 0xA6, 0xA2, 0x9F, 0x9C, 0x9A, 0x98, 0x96, 0x94, 0x93,
|
||||
0x92, 0x91, 0x91, 0x91, 0x91, 0x92, 0x92, 0x94, 0x95, 0x97, 0x9A, 0x9C,
|
||||
0x9F, 0xA2, 0xA6, 0xA9, 0xAD, 0xB1, 0xB6, 0xBB, 0xBF, 0xC4, 0xCA, 0xCF,
|
||||
0xD5, 0xDA, 0xE0, 0xE6, 0xEC, 0xF2, 0xF8, 0xFE, 0x03, 0x09, 0x0F, 0x15,
|
||||
0x1B, 0x21, 0x27, 0x2D, 0x32, 0x37, 0x3D, 0x42, 0x47, 0x4B, 0x50, 0x54,
|
||||
0x58, 0x5B, 0x5F, 0x62, 0x64, 0x67, 0x69, 0x6B, 0x6D, 0x6E, 0x6F, 0x6F,
|
||||
0x6F, 0x6F, 0x6F, 0x6E, 0x6D, 0x6C, 0x6A, 0x68, 0x66, 0x63, 0x60, 0x5D,
|
||||
0x59, 0x55, 0x51, 0x4D, 0x49, 0x44, 0x3F, 0x3A, 0x35, 0x2F, 0x2A, 0x24,
|
||||
0x1E, 0x18, 0x12, 0x0C, 0x06, 0x00, 0xFB, 0xF5, 0xEF, 0xE9, 0xE3, 0xDD,
|
||||
0xD7, 0xD2, 0xCC, 0xC7, 0xC2, 0xBD, 0xB8, 0xB3, 0xAF, 0xAB, 0xA7, 0xA4,
|
||||
0xA0, 0x9D, 0x9B, 0x98, 0x96, 0x95, 0x93, 0x92, 0x91, 0x91, 0x91, 0x91,
|
||||
0x91, 0x92, 0x93, 0x95, 0x97, 0x99, 0x9B, 0x9E, 0xA1, 0xA4, 0xA8, 0xAC,
|
||||
0xB0, 0xB4, 0xB9, 0xBE, 0xC3, 0xC8, 0xCD, 0xD3, 0xD8, 0xDE, 0xE4, 0xEA,
|
||||
0xF0, 0xF6, 0xFC, 0x01, 0x07, 0x0D, 0x13, 0x19, 0x1F, 0x25, 0x2A, 0x30,
|
||||
0x35, 0x3B, 0x40, 0x45, 0x49, 0x4E, 0x52, 0x56, 0x5A, 0x5D, 0x60, 0x63,
|
||||
0x66, 0x68, 0x6A, 0x6C, 0x6D, 0x6E, 0x6F, 0x6F, 0x6F, 0x6F, 0x6F, 0x6E,
|
||||
0x6C, 0x6B, 0x69, 0x67, 0x64, 0x61, 0x5E, 0x5B, 0x57, 0x53, 0x4F, 0x4A,
|
||||
0x46, 0x41, 0x3C, 0x37, 0x31, 0x2C, 0x26, 0x20, 0x1A, 0x14, 0x0E, 0x08,
|
||||
0x00, 0xF6, 0xEC, 0xE2, 0xD8, 0xCF, 0xC6, 0xBD, 0xB6, 0xAE, 0xA8, 0xA2,
|
||||
0x9D, 0x98, 0x95, 0x93, 0x91, 0x91, 0x91, 0x92, 0x94, 0x97, 0x9B, 0xA0,
|
||||
0xA6, 0xAC, 0xB3, 0xBB, 0xC4, 0xCC, 0xD6, 0xDF, 0xE9, 0xF3, 0xFE, 0x07,
|
||||
0x11, 0x1B, 0x25, 0x2E, 0x37, 0x40, 0x48, 0x50, 0x57, 0x5D, 0x62, 0x66,
|
||||
0x6A, 0x6D, 0x6F, 0x6F, 0x6F, 0x6E, 0x6C, 0x6A, 0x66, 0x61, 0x5C, 0x56,
|
||||
0x4F, 0x47, 0x3F, 0x36, 0x2D, 0x24, 0x1A, 0x10, 0xC4, 0xBD, 0xB7, 0xB2,
|
||||
0xAE, 0xAA, 0xA6, 0xA3, 0xA1, 0x9F, 0x9D, 0x9B, 0x9A, 0x98, 0x97, 0x97,
|
||||
0x96, 0x95, 0x95, 0x94, 0x94, 0x94, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93,
|
||||
0x93, 0x93, 0x93, 0x94, 0x94, 0x95, 0x95, 0x96, 0x96, 0x97, 0x98, 0x99,
|
||||
0x9B, 0x9C, 0x9E, 0xA0, 0xA3, 0xA5, 0xA9, 0xAC, 0xB1, 0xB6, 0xBC, 0xC3,
|
||||
0xCA, 0xD4, 0xDE, 0xEA, 0xF8, 0x08, 0x16, 0x22, 0x2C, 0x36, 0x3D, 0x44,
|
||||
0x4A, 0x4F, 0x53, 0x57, 0x5B, 0x5D, 0x60, 0x62, 0x64, 0x65, 0x67, 0x68,
|
||||
0x69, 0x69, 0x6A, 0x6B, 0x6B, 0x6C, 0x6C, 0x6C, 0x6C, 0x6C, 0x6C, 0x6C,
|
||||
0x6C, 0x6C, 0x6C, 0x6B, 0x6B, 0x6A, 0x69, 0x69, 0x68, 0x67, 0x65, 0x64,
|
||||
0x62, 0x60, 0x5D, 0x5B, 0x57, 0x53, 0x4F, 0x4A, 0x44, 0x3D, 0x36, 0x2C,
|
||||
0x22, 0x16, 0x08, 0xF8, 0xEA, 0xDE, 0xD4, 0xCA, 0xC3, 0xBC, 0xB6, 0xB1,
|
||||
0xAD, 0xA9, 0xA5, 0xA3, 0xA0, 0x9E, 0x9C, 0x9B, 0x99, 0x98, 0x97, 0x97,
|
||||
0x96, 0x95, 0x95, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94,
|
||||
0x94, 0x95, 0x95, 0x96, 0x96, 0x97, 0x98, 0x99, 0x9B, 0x9C, 0x9E, 0xA0,
|
||||
0xA2, 0xA5, 0xA8, 0xAC, 0xB0, 0xB5, 0xBB, 0xC1, 0xC9, 0xD2, 0xDC, 0xE8,
|
||||
0xF5, 0x00, 0x02, 0x05, 0x08, 0x0A, 0x0D, 0x10, 0x12, 0x15, 0x17, 0x19,
|
||||
0x1C, 0x1E, 0x20, 0x22, 0x24, 0x26, 0x27, 0x29, 0x2A, 0x2C, 0x2D, 0x2E,
|
||||
0x2F, 0x30, 0x30, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x30, 0x30,
|
||||
0x2F, 0x2E, 0x2D, 0x2B, 0x2A, 0x29, 0x27, 0x25, 0x23, 0x21, 0x1F, 0x1D,
|
||||
0x1B, 0x19, 0x16, 0x14, 0x11, 0x0F, 0x0C, 0x09, 0x07, 0x04, 0x3C, 0x43,
|
||||
0x49, 0x4E, 0x52, 0x56, 0x5A, 0x5D, 0x5F, 0x61, 0x63, 0x65, 0x66, 0x68,
|
||||
0x69, 0x69, 0x6A, 0x6B, 0x6B, 0x6C, 0x6C, 0x6C, 0x6D, 0x6D, 0x6D, 0x6D,
|
||||
0x6D, 0x6D, 0x6D, 0x6D, 0x6D, 0x6C, 0x6C, 0x6B, 0x6B, 0x6A, 0x6A, 0x69,
|
||||
0x68, 0x67, 0x65, 0x64, 0x62, 0x60, 0x5D, 0x5B, 0x57, 0x54, 0x4F, 0x4A,
|
||||
0x44, 0x3D, 0x36, 0x2C, 0x22, 0x16, 0x08, 0xF8, 0xEA, 0xDE, 0xD4, 0xCA,
|
||||
0xC3, 0xBC, 0xB6, 0xB1, 0xAD, 0xA9, 0xA5, 0xA3, 0xA0, 0x9E, 0x9C, 0x9B,
|
||||
0x99, 0x98, 0x97, 0x97, 0x96, 0x95, 0x95, 0x94, 0x94, 0x94, 0x94, 0x94,
|
||||
0x94, 0x94, 0x94, 0x94, 0x94, 0x95, 0x95, 0x96, 0x97, 0x97, 0x98, 0x99,
|
||||
0x9B, 0x9C, 0x9E, 0xA0, 0xA3, 0xA5, 0xA9, 0xAD, 0xB1, 0xB6, 0xBC, 0xC3,
|
||||
0xCA, 0xD4, 0xDE, 0xEA, 0xF8, 0x08, 0x16, 0x22, 0x2C, 0x36, 0x3D, 0x44,
|
||||
0x4A, 0x4F, 0x53, 0x57, 0x5B, 0x5D, 0x60, 0x62, 0x64, 0x65, 0x67, 0x68,
|
||||
0x69, 0x69, 0x6A, 0x6B, 0x6B, 0x6C, 0x6C, 0x6C, 0x6C, 0x6C, 0x6C, 0x6C,
|
||||
0x6C, 0x6C, 0x6C, 0x6B, 0x6B, 0x6A, 0x6A, 0x69, 0x68, 0x67, 0x65, 0x64,
|
||||
0x62, 0x60, 0x5E, 0x5B, 0x58, 0x54, 0x50, 0x4B, 0x45, 0x3F, 0x37, 0x2E,
|
||||
0x24, 0x18, 0x0B, 0x00, 0x06, 0x0C, 0x12, 0x18, 0x1E, 0x23, 0x29, 0x2F,
|
||||
0x34, 0x3A, 0x3F, 0x44, 0x48, 0x4D, 0x51, 0x55, 0x59, 0x5D, 0x60, 0x63,
|
||||
0x65, 0x68, 0x6A, 0x6C, 0x6D, 0x6E, 0x6F, 0x6F, 0x6F, 0x6F, 0x6F, 0x6E,
|
||||
0x6D, 0x6B, 0x69, 0x67, 0x65, 0x62, 0x5F, 0x5B, 0x58, 0x54, 0x50, 0x4B,
|
||||
0x47, 0x42, 0x3D, 0x38, 0x33, 0x2D, 0x27, 0x22, 0x1C, 0x16, 0x10, 0x0A,
|
||||
0x04, 0xFF, 0xF9, 0xF2, 0xEC, 0xE6, 0xE1, 0xDB, 0xD5, 0xD0, 0xCA, 0xC5,
|
||||
0xC0, 0xBB, 0xB6, 0xB2, 0xAE, 0xAA, 0xA6, 0xA2, 0x9F, 0x9C, 0x9A, 0x98,
|
||||
0x96, 0x94, 0x93, 0x92, 0x91, 0x91, 0x91, 0x91, 0x92, 0x92, 0x94, 0x95,
|
||||
0x97, 0x9A, 0x9C, 0x9F, 0xA2, 0xA6, 0xA9, 0xAD, 0xB1, 0xB6, 0xBB, 0xBF,
|
||||
0xC4, 0xCA, 0xCF, 0xD5, 0xDA, 0xE0, 0xE6, 0xEC, 0xF2, 0xF8, 0x00, 0x03,
|
||||
0x07, 0x0B, 0x0F, 0x12, 0x16, 0x1A, 0x1D, 0x20, 0x24, 0x27, 0x2A, 0x2D,
|
||||
0x30, 0x33, 0x35, 0x37, 0x3A, 0x3C, 0x3E, 0x3F, 0x41, 0x42, 0x43, 0x44,
|
||||
0x45, 0x45, 0x45, 0x45, 0x45, 0x45, 0x44, 0x44, 0x43, 0x42, 0x40, 0x3F,
|
||||
0x3D, 0x3B, 0x39, 0x37, 0x34, 0x32, 0x2F, 0x2C, 0x29, 0x26, 0x23, 0x1F,
|
||||
0x1C, 0x18, 0x15, 0x11, 0x0D, 0x0A, 0x06, 0x02, 0xFF, 0xFC, 0xF8, 0xF4,
|
||||
0xF0, 0xED, 0xE9, 0xE5, 0xE2, 0xDF, 0xDB, 0xD8, 0xD5, 0xD2, 0xCF, 0xCD,
|
||||
0xCA, 0xC8, 0xC6, 0xC4, 0xC2, 0xC0, 0xBF, 0xBE, 0xBD, 0xBC, 0xBB, 0xBB,
|
||||
0xBB, 0xBB, 0xBB, 0xBB, 0xBC, 0xBD, 0xBE, 0xBF, 0xC0, 0xC2, 0xC4, 0xC6,
|
||||
0xC8, 0xCA, 0xCC, 0xCF, 0xD2, 0xD5, 0xD8, 0xDB, 0xDE, 0xE2, 0xE5, 0xE9,
|
||||
0xEC, 0xF0, 0xF4, 0xF7, 0xFB, 0x00, 0x06, 0x0C, 0x12, 0x18, 0x1E, 0x23,
|
||||
0x29, 0x2F, 0x34, 0x3A, 0x3F, 0x44, 0x48, 0x4D, 0x51, 0x55, 0x59, 0x5D,
|
||||
0x60, 0x63, 0x65, 0x68, 0x6A, 0x6C, 0x6D, 0x6E, 0x6F, 0x6F, 0x6F, 0x6F,
|
||||
0x6F, 0x6E, 0x6D, 0x6B, 0x69, 0x67, 0x65, 0x62, 0x5F, 0x5B, 0x58, 0x54,
|
||||
0x50, 0x4B, 0x47, 0x42, 0x3D, 0x38, 0x33, 0x2D, 0x27, 0x22, 0x1C, 0x16,
|
||||
0x10, 0x0A, 0x04, 0xFF, 0xF9, 0xF2, 0xEC, 0xE6, 0xE1, 0xDB, 0xD5, 0xD0,
|
||||
0xCA, 0xC5, 0xC0, 0xBB, 0xB6, 0xB2, 0xAE, 0xAA, 0xA6, 0xA2, 0x9F, 0x9C,
|
||||
0x9A, 0x98, 0x96, 0x94, 0x93, 0x92, 0x91, 0x91, 0x91, 0x91, 0x92, 0x92,
|
||||
0x94, 0x95, 0x97, 0x9A, 0x9C, 0x9F, 0xA2, 0xA6, 0xA9, 0xAD, 0xB1, 0xB6,
|
||||
0xBB, 0xBF, 0xC4, 0xCA, 0xCF, 0xD5, 0xDA, 0xE0, 0xE6, 0xEC, 0xF2, 0xF8,
|
||||
0xFE, 0x03, 0x09, 0x0F, 0x15, 0x1B, 0x21, 0x27, 0x2D, 0x32, 0x37, 0x3D,
|
||||
0x42, 0x47, 0x4B, 0x50, 0x54, 0x58, 0x5B, 0x5F, 0x62, 0x64, 0x67, 0x69,
|
||||
0x6B, 0x6D, 0x6E, 0x6F, 0x6F, 0x6F, 0x6F, 0x6F, 0x6E, 0x6D, 0x6C, 0x6A,
|
||||
0x68, 0x66, 0x63, 0x60, 0x5D, 0x59, 0x55, 0x51, 0x4D, 0x49, 0x44, 0x3F,
|
||||
0x3A, 0x35, 0x2F, 0x2A, 0x24, 0x1E, 0x18, 0x12, 0x0C, 0x06, 0x00, 0xFB,
|
||||
0xF5, 0xEF, 0xE9, 0xE3, 0xDD, 0xD7, 0xD2, 0xCC, 0xC7, 0xC2, 0xBD, 0xB8,
|
||||
0xB3, 0xAF, 0xAB, 0xA7, 0xA4, 0xA0, 0x9D, 0x9B, 0x98, 0x96, 0x95, 0x93,
|
||||
0x92, 0x91, 0x91, 0x91, 0x91, 0x91, 0x92, 0x93, 0x95, 0x97, 0x99, 0x9B,
|
||||
0x9E, 0xA1, 0xA4, 0xA8, 0xAC, 0xB0, 0xB4, 0xB9, 0xBE, 0xC3, 0xC8, 0xCD,
|
||||
0xD3, 0xD8, 0xDE, 0xE4, 0xEA, 0xF0, 0xF6, 0xFC, 0x01, 0x07, 0x0D, 0x13,
|
||||
0x19, 0x1F, 0x25, 0x2A, 0x30, 0x35, 0x3B, 0x40, 0x45, 0x49, 0x4E, 0x52,
|
||||
0x56, 0x5A, 0x5D, 0x60, 0x63, 0x66, 0x68, 0x6A, 0x6C, 0x6D, 0x6E, 0x6F,
|
||||
0x6F, 0x6F, 0x6F, 0x6F, 0x6E, 0x6C, 0x6B, 0x69, 0x67, 0x64, 0x61, 0x5E,
|
||||
0x5B, 0x57, 0x53, 0x4F, 0x4A, 0x46, 0x41, 0x3C, 0x37, 0x31, 0x2C, 0x26,
|
||||
0x20, 0x1A, 0x14, 0x0E, 0x08, 0x00, 0xF6, 0xEC, 0xE2, 0xD8, 0xCF, 0xC6,
|
||||
0xBD, 0xB6, 0xAE, 0xA8, 0xA2, 0x9D, 0x98, 0x95, 0x93, 0x91, 0x91, 0x91,
|
||||
0x92, 0x94, 0x97, 0x9B, 0xA0, 0xA6, 0xAC, 0xB3, 0xBB, 0xC4, 0xCC, 0xD6,
|
||||
0xDF, 0xE9, 0xF3, 0xFE, 0x07, 0x11, 0x1B, 0x25, 0x2E, 0x37, 0x40, 0x48,
|
||||
0x50, 0x57, 0x5D, 0x62, 0x66, 0x6A, 0x6D, 0x6F, 0x6F, 0x6F, 0x6E, 0x6C,
|
||||
0x6A, 0x66, 0x61, 0x5C, 0x56, 0x4F, 0x47, 0x3F, 0x36, 0x2D, 0x24, 0x1A,
|
||||
0x10, 0xC4, 0xBD, 0xB7, 0xB2, 0xAE, 0xAA, 0xA6, 0xA3, 0xA1, 0x9F, 0x9D,
|
||||
0x9B, 0x9A, 0x98, 0x97, 0x97, 0x96, 0x95, 0x95, 0x94, 0x94, 0x94, 0x93,
|
||||
0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x94, 0x94, 0x95, 0x95,
|
||||
0x96, 0x96, 0x97, 0x98, 0x99, 0x9B, 0x9C, 0x9E, 0xA0, 0xA3, 0xA5, 0xA9,
|
||||
0xAC, 0xB1, 0xB6, 0xBC, 0xC3, 0xCA, 0xD4, 0xDE, 0xEA, 0xF8, 0x08, 0x16,
|
||||
0x22, 0x2C, 0x36, 0x3D, 0x44, 0x4A, 0x4F, 0x53, 0x57, 0x5B, 0x5D, 0x60,
|
||||
0x62, 0x64, 0x65, 0x67, 0x68, 0x69, 0x69, 0x6A, 0x6B, 0x6B, 0x6C, 0x6C,
|
||||
0x6C, 0x6C, 0x6C, 0x6C, 0x6C, 0x6C, 0x6C, 0x6C, 0x6B, 0x6B, 0x6A, 0x69,
|
||||
0x69, 0x68, 0x67, 0x65, 0x64, 0x62, 0x60, 0x5D, 0x5B, 0x57, 0x53, 0x4F,
|
||||
0x4A, 0x44, 0x3D, 0x36, 0x2C, 0x22, 0x16, 0x08, 0xF8, 0xEA, 0xDE, 0xD4,
|
||||
0xCA, 0xC3, 0xBC, 0xB6, 0xB1, 0xAD, 0xA9, 0xA5, 0xA3, 0xA0, 0x9E, 0x9C,
|
||||
0x9B, 0x99, 0x98, 0x97, 0x97, 0x96, 0x95, 0x95, 0x94, 0x94, 0x94, 0x94,
|
||||
0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x95, 0x95, 0x96, 0x96, 0x97, 0x98,
|
||||
0x99, 0x9B, 0x9C, 0x9E, 0xA0, 0xA2, 0xA5, 0xA8, 0xAC, 0xB0, 0xB5, 0xBB,
|
||||
0xC1, 0xC9, 0xD2, 0xDC, 0xE8, 0xF5, 0x00, 0x02, 0x05, 0x08, 0x0A, 0x0D,
|
||||
0x10, 0x12, 0x15, 0x17, 0x19, 0x1C, 0x1E, 0x20, 0x22, 0x24, 0x26, 0x27,
|
||||
0x29, 0x2A, 0x2C, 0x2D, 0x2E, 0x2F, 0x30, 0x30, 0x31, 0x31, 0x31, 0x31,
|
||||
0x31, 0x31, 0x31, 0x30, 0x30, 0x2F, 0x2E, 0x2D, 0x2B, 0x2A, 0x29, 0x27,
|
||||
0x25, 0x23, 0x21, 0x1F, 0x1D, 0x1B, 0x19, 0x16, 0x14, 0x11, 0x0F, 0x0C,
|
||||
0x09, 0x07, 0x04, 0x00, 0x06, 0x0C, 0x12, 0x18, 0x1E, 0x23, 0x29, 0x2F,
|
||||
0x34, 0x3A, 0x3F, 0x44, 0x48, 0x4D, 0x51, 0x55, 0x59, 0x5D, 0x60, 0x63,
|
||||
0x65, 0x68, 0x6A, 0x6C, 0x6D, 0x6E, 0x6F, 0x6F, 0x6F, 0x6F, 0x6F, 0x6E,
|
||||
0x6D, 0x6B, 0x69, 0x67, 0x65, 0x62, 0x5F, 0x5B, 0x58, 0x54, 0x50, 0x4B,
|
||||
0x47, 0x42, 0x3D, 0x38, 0x33, 0x2D, 0x27, 0x22, 0x1C, 0x16, 0x10, 0x0A,
|
||||
0x04, 0xFF, 0xF9, 0xF2, 0xEC, 0xE6, 0xE1, 0xDB, 0xD5, 0xD0, 0xCA, 0xC5,
|
||||
0xC0, 0xBB, 0xB6, 0xB2, 0xAE, 0xAA, 0xA6, 0xA2, 0x9F, 0x9C, 0x9A, 0x98,
|
||||
0x96, 0x94, 0x93, 0x92, 0x91, 0x91, 0x91, 0x91, 0x92, 0x92, 0x94, 0x95,
|
||||
0x97, 0x9A, 0x9C, 0x9F, 0xA2, 0xA6, 0xA9, 0xAD, 0xB1, 0xB6, 0xBB, 0xBF,
|
||||
0xC4, 0xCA, 0xCF, 0xD5, 0xDA, 0xE0, 0xE6, 0xEC, 0xF2, 0xF8, 0xFE, 0x03,
|
||||
0x09, 0x0F, 0x15, 0x1B, 0x21, 0x27, 0x2D, 0x32, 0x37, 0x3D, 0x42, 0x47,
|
||||
0x4B, 0x50, 0x54, 0x58, 0x5B, 0x5F, 0x62, 0x64, 0x67, 0x69, 0x6B, 0x6D,
|
||||
0x6E, 0x6F, 0x6F, 0x6F, 0x6F, 0x6F, 0x6E, 0x6D, 0x6C, 0x6A, 0x68, 0x66,
|
||||
0x63, 0x60, 0x5D, 0x59, 0x55, 0x51, 0x4D, 0x49, 0x44, 0x3F, 0x3A, 0x35,
|
||||
0x2F, 0x2A, 0x24, 0x1E, 0x18, 0x12, 0x0C, 0x06, 0x00, 0xFB, 0xF5, 0xEF,
|
||||
0xE9, 0xE3, 0xDD, 0xD7, 0xD2, 0xCC, 0xC7, 0xC2, 0xBD, 0xB8, 0xB3, 0xAF,
|
||||
0xAB, 0xA7, 0xA4, 0xA0, 0x9D, 0x9B, 0x98, 0x96, 0x95, 0x93, 0x92, 0x91,
|
||||
0x91, 0x91, 0x91, 0x91, 0x92, 0x93, 0x95, 0x97, 0x99, 0x9B, 0x9E, 0xA1,
|
||||
0xA4, 0xA8, 0xAC, 0xB0, 0xB4, 0xB9, 0xBE, 0xC3, 0xC8, 0xCD, 0xD3, 0xD8,
|
||||
0xDE, 0xE4, 0xEA, 0xF0, 0xF6, 0x00, 0xFA, 0xF4, 0xEE, 0xE8, 0xE2, 0xDD,
|
||||
0xD7, 0xD1, 0xCC, 0xC6, 0xC1, 0xBC, 0xB8, 0xB3, 0xAF, 0xAB, 0xA7, 0xA3,
|
||||
0xA0, 0x9D, 0x9B, 0x98, 0x96, 0x94, 0x93, 0x92, 0x91, 0x91, 0x91, 0x91,
|
||||
0x91, 0x92, 0x93, 0x95, 0x97, 0x99, 0x9B, 0x9E, 0xA1, 0xA5, 0xA8, 0xAC,
|
||||
0xB0, 0xB5, 0xB9, 0xBE, 0xC3, 0xC8, 0xCD, 0xD3, 0xD9, 0xDE, 0xE4, 0xEA,
|
||||
0xF0, 0xF6, 0xFC, 0x01, 0x07, 0x0E, 0x14, 0x1A, 0x1F, 0x25, 0x2B, 0x30,
|
||||
0x36, 0x3B, 0x40, 0x45, 0x4A, 0x4E, 0x52, 0x56, 0x5A, 0x5E, 0x61, 0x64,
|
||||
0x66, 0x68, 0x6A, 0x6C, 0x6D, 0x6E, 0x6F, 0x6F, 0x6F, 0x6F, 0x6E, 0x6E,
|
||||
0x6C, 0x6B, 0x69, 0x66, 0x64, 0x61, 0x5E, 0x5A, 0x57, 0x53, 0x4F, 0x4A,
|
||||
0x45, 0x41, 0x3C, 0x36, 0x31, 0x2B, 0x26, 0x20, 0x1A, 0x14, 0x0E, 0x08,
|
||||
0x02, 0xFD, 0xF7, 0xF1, 0xEB, 0xE5, 0xDF, 0xD9, 0xD3, 0xCE, 0xC9, 0xC3,
|
||||
0xBE, 0xB9, 0xB5, 0xB0, 0xAC, 0xA8, 0xA5, 0xA1, 0x9E, 0x9C, 0x99, 0x97,
|
||||
0x95, 0x93, 0x92, 0x91, 0x91, 0x91, 0x91, 0x91, 0x92, 0x93, 0x94, 0x96,
|
||||
0x98, 0x9A, 0x9D, 0xA0, 0xA3, 0xA7, 0xAB, 0xAF, 0xB3, 0xB7, 0xBC, 0xC1,
|
||||
0xC6, 0xCB, 0xD1, 0xD6, 0xDC, 0xE2, 0xE8, 0xEE, 0xF4, 0xFA, 0x00, 0x01,
|
||||
0x03, 0x04, 0x06, 0x08, 0x09, 0x0B, 0x0C, 0x0E, 0x0F, 0x10, 0x12, 0x13,
|
||||
0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1A, 0x1B, 0x1B, 0x1C, 0x1C, 0x1D,
|
||||
0x1D, 0x1D, 0x1D, 0x1D, 0x1D, 0x1D, 0x1D, 0x1D, 0x1C, 0x1C, 0x1B, 0x1B,
|
||||
0x1A, 0x19, 0x18, 0x17, 0x16, 0x15, 0x14, 0x13, 0x11, 0x10, 0x0F, 0x0D,
|
||||
0x0C, 0x0A, 0x09, 0x07, 0x05, 0x04, 0x02, 0x01, 0x00, 0xFE, 0xFD, 0xFB,
|
||||
0xFA, 0xF8, 0xF6, 0xF5, 0xF3, 0xF2, 0xF1, 0xEF, 0xEE, 0xED, 0xEB, 0xEA,
|
||||
0xE9, 0xE8, 0xE7, 0xE6, 0xE6, 0xE5, 0xE4, 0xE4, 0xE3, 0xE3, 0xE3, 0xE3,
|
||||
0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE4, 0xE4, 0xE5, 0xE6, 0xE6, 0xE7,
|
||||
0xE8, 0xE9, 0xEA, 0xEB, 0xED, 0xEE, 0xEF, 0xF0, 0xF2, 0xF3, 0xF5, 0xF6,
|
||||
0xF8, 0xF9, 0xFB, 0xFD, 0xFE, 0x3C, 0x43, 0x49, 0x4E, 0x52, 0x56, 0x5A,
|
||||
0x5D, 0x5F, 0x61, 0x63, 0x65, 0x66, 0x68, 0x69, 0x69, 0x6A, 0x6B, 0x6B,
|
||||
0x6C, 0x6C, 0x6C, 0x6D, 0x6D, 0x6D, 0x6D, 0x6D, 0x6D, 0x6D, 0x6D, 0x6D,
|
||||
0x6C, 0x6C, 0x6C, 0x6B, 0x6B, 0x6A, 0x69, 0x68, 0x67, 0x66, 0x65, 0x63,
|
||||
0x61, 0x5F, 0x5C, 0x59, 0x55, 0x51, 0x4D, 0x47, 0x41, 0x39, 0x31, 0x27,
|
||||
0x1C, 0x0F, 0x00, 0xFA, 0xF4, 0xEE, 0xE8, 0xE2, 0xDD, 0xD7, 0xD1, 0xCC,
|
||||
0xC6, 0xC1, 0xBC, 0xB8, 0xB3, 0xAF, 0xAB, 0xA7, 0xA3, 0xA0, 0x9D, 0x9B,
|
||||
0x98, 0x96, 0x94, 0x93, 0x92, 0x91, 0x91, 0x91, 0x91, 0x91, 0x92, 0x93,
|
||||
0x95, 0x97, 0x99, 0x9B, 0x9E, 0xA1, 0xA5, 0xA8, 0xAC, 0xB0, 0xB5, 0xB9,
|
||||
0xBE, 0xC3, 0xC8, 0xCD, 0xD3, 0xD9, 0xDE, 0xE4, 0xEA, 0xF0, 0xF6, 0x00,
|
||||
0x0A, 0x14, 0x1E, 0x28, 0x31, 0x3A, 0x43, 0x4A, 0x52, 0x58, 0x5E, 0x63,
|
||||
0x68, 0x6B, 0x6D, 0x6F, 0x6F, 0x6F, 0x6E, 0x6C, 0x69, 0x65, 0x60, 0x5A,
|
||||
0x54, 0x4D, 0x45, 0x3C, 0x34, 0x2A, 0x21, 0x17, 0x0D, 0x02, 0xF9, 0xEF,
|
||||
0xE5, 0xDB, 0xD2, 0xC9, 0xC0, 0xB8, 0xB0, 0xA9, 0xA3, 0x9E, 0x9A, 0x96,
|
||||
0x93, 0x91, 0x91, 0x91, 0x92, 0x94, 0x96, 0x9A, 0x9F, 0xA4, 0xAA, 0xB1,
|
||||
0xB9, 0xC1, 0xCA, 0xD3, 0xDC, 0xE6, 0xF0, 0x00, 0x06, 0x0C, 0x12, 0x18,
|
||||
0x1E, 0x23, 0x29, 0x2F, 0x34, 0x3A, 0x3F, 0x44, 0x48, 0x4D, 0x51, 0x55,
|
||||
0x59, 0x5D, 0x60, 0x63, 0x65, 0x68, 0x6A, 0x6C, 0x6D, 0x6E, 0x6F, 0x6F,
|
||||
0x6F, 0x6F, 0x6F, 0x6E, 0x6D, 0x6B, 0x69, 0x67, 0x65, 0x62, 0x5F, 0x5B,
|
||||
0x58, 0x54, 0x50, 0x4B, 0x47, 0x42, 0x3D, 0x38, 0x33, 0x2D, 0x27, 0x22,
|
||||
0x1C, 0x16, 0x10, 0x0A, 0x04, 0xFF, 0xF9, 0xF2, 0xEC, 0xE6, 0xE1, 0xDB,
|
||||
0xD5, 0xD0, 0xCA, 0xC5, 0xC0, 0xBB, 0xB6, 0xB2, 0xAE, 0xAA, 0xA6, 0xA2,
|
||||
0x9F, 0x9C, 0x9A, 0x98, 0x96, 0x94, 0x93, 0x92, 0x91, 0x91, 0x91, 0x91,
|
||||
0x92, 0x92, 0x94, 0x95, 0x97, 0x9A, 0x9C, 0x9F, 0xA2, 0xA6, 0xA9, 0xAD,
|
||||
0xB1, 0xB6, 0xBB, 0xBF, 0xC4, 0xCA, 0xCF, 0xD5, 0xDA, 0xE0, 0xE6, 0xEC,
|
||||
0xF2, 0xF8, 0x3C, 0x43, 0x49, 0x4E, 0x52, 0x56, 0x5A, 0x5D, 0x5F, 0x61,
|
||||
0x63, 0x65, 0x66, 0x68, 0x69, 0x69, 0x6A, 0x6B, 0x6B, 0x6C, 0x6C, 0x6C,
|
||||
0x6D, 0x6D, 0x6D, 0x6D, 0x6D, 0x6D, 0x6D, 0x6D, 0x6D, 0x6C, 0x6C, 0x6B,
|
||||
0x6B, 0x6A, 0x6A, 0x69, 0x68, 0x67, 0x65, 0x64, 0x62, 0x60, 0x5D, 0x5B,
|
||||
0x57, 0x54, 0x4F, 0x4A, 0x44, 0x3D, 0x36, 0x2C, 0x22, 0x16, 0x08, 0xF8,
|
||||
0xEA, 0xDE, 0xD4, 0xCA, 0xC3, 0xBC, 0xB6, 0xB1, 0xAD, 0xA9, 0xA5, 0xA3,
|
||||
0xA0, 0x9E, 0x9C, 0x9B, 0x99, 0x98, 0x97, 0x97, 0x96, 0x95, 0x95, 0x94,
|
||||
0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x95, 0x95, 0x96,
|
||||
0x97, 0x97, 0x98, 0x99, 0x9B, 0x9C, 0x9E, 0xA0, 0xA3, 0xA5, 0xA9, 0xAD,
|
||||
0xB1, 0xB6, 0xBC, 0xC3, 0xCA, 0xD4, 0xDE, 0xEA, 0xF8, 0x08, 0x16, 0x22,
|
||||
0x2C, 0x36, 0x3D, 0x44, 0x4A, 0x4F, 0x53, 0x57, 0x5B, 0x5D, 0x60, 0x62,
|
||||
0x64, 0x65, 0x67, 0x68, 0x69, 0x69, 0x6A, 0x6B, 0x6B, 0x6C, 0x6C, 0x6C,
|
||||
0x6C, 0x6C, 0x6C, 0x6C, 0x6C, 0x6C, 0x6C, 0x6B, 0x6B, 0x6A, 0x6A, 0x69,
|
||||
0x68, 0x67, 0x65, 0x64, 0x62, 0x60, 0x5E, 0x5B, 0x58, 0x54, 0x50, 0x4B,
|
||||
0x45, 0x3F, 0x37, 0x2E, 0x24, 0x18, 0x0B, 0x00, 0x06, 0x0C, 0x12, 0x18,
|
||||
0x1E, 0x23, 0x29, 0x2F, 0x34, 0x3A, 0x3F, 0x44, 0x48, 0x4D, 0x51, 0x55,
|
||||
0x59, 0x5D, 0x60, 0x63, 0x65, 0x68, 0x6A, 0x6C, 0x6D, 0x6E, 0x6F, 0x6F,
|
||||
0x6F, 0x6F, 0x6F, 0x6E, 0x6D, 0x6B, 0x69, 0x67, 0x65, 0x62, 0x5F, 0x5B,
|
||||
0x58, 0x54, 0x50, 0x4B, 0x47, 0x42, 0x3D, 0x38, 0x33, 0x2D, 0x27, 0x22,
|
||||
0x1C, 0x16, 0x10, 0x0A, 0x04, 0xFF, 0xF9, 0xF2, 0xEC, 0xE6, 0xE1, 0xDB,
|
||||
0xD5, 0xD0, 0xCA, 0xC5, 0xC0, 0xBB, 0xB6, 0xB2, 0xAE, 0xAA, 0xA6, 0xA2,
|
||||
0x9F, 0x9C, 0x9A, 0x98, 0x96, 0x94, 0x93, 0x92, 0x91, 0x91, 0x91, 0x91,
|
||||
0x92, 0x92, 0x94, 0x95, 0x97, 0x9A, 0x9C, 0x9F, 0xA2, 0xA6, 0xA9, 0xAD,
|
||||
0xB1, 0xB6, 0xBB, 0xBF, 0xC4, 0xCA, 0xCF, 0xD5, 0xDA, 0xE0, 0xE6, 0xEC,
|
||||
0xF2, 0xF8, 0x00, 0x03, 0x07, 0x0B, 0x0F, 0x12, 0x16, 0x1A, 0x1D, 0x20,
|
||||
0x24, 0x27, 0x2A, 0x2D, 0x30, 0x33, 0x35, 0x37, 0x3A, 0x3C, 0x3E, 0x3F,
|
||||
0x41, 0x42, 0x43, 0x44, 0x45, 0x45, 0x45, 0x45, 0x45, 0x45, 0x44, 0x44,
|
||||
0x43, 0x42, 0x40, 0x3F, 0x3D, 0x3B, 0x39, 0x37, 0x34, 0x32, 0x2F, 0x2C,
|
||||
0x29, 0x26, 0x23, 0x1F, 0x1C, 0x18, 0x15, 0x11, 0x0D, 0x0A, 0x06, 0x02,
|
||||
0xFF, 0xFC, 0xF8, 0xF4, 0xF0, 0xED, 0xE9, 0xE5, 0xE2, 0xDF, 0xDB, 0xD8,
|
||||
0xD5, 0xD2, 0xCF, 0xCD, 0xCA, 0xC8, 0xC6, 0xC4, 0xC2, 0xC0, 0xBF, 0xBE,
|
||||
0xBD, 0xBC, 0xBB, 0xBB, 0xBB, 0xBB, 0xBB, 0xBB, 0xBC, 0xBD, 0xBE, 0xBF,
|
||||
0xC0, 0xC2, 0xC4, 0xC6, 0xC8, 0xCA, 0xCC, 0xCF, 0xD2, 0xD5, 0xD8, 0xDB,
|
||||
0xDE, 0xE2, 0xE5, 0xE9, 0xEC, 0xF0, 0xF4, 0xF7, 0xFB, 0x00, 0x06, 0x0C,
|
||||
0x12, 0x18, 0x1E, 0x23, 0x29, 0x2F, 0x34, 0x3A, 0x3F, 0x44, 0x48, 0x4D,
|
||||
0x51, 0x55, 0x59, 0x5D, 0x60, 0x63, 0x65, 0x68, 0x6A, 0x6C, 0x6D, 0x6E,
|
||||
0x6F, 0x6F, 0x6F, 0x6F, 0x6F, 0x6E, 0x6D, 0x6B, 0x69, 0x67, 0x65, 0x62,
|
||||
0x5F, 0x5B, 0x58, 0x54, 0x50, 0x4B, 0x47, 0x42, 0x3D, 0x38, 0x33, 0x2D,
|
||||
0x27, 0x22, 0x1C, 0x16, 0x10, 0x0A, 0x04, 0xFF, 0xF9, 0xF2, 0xEC, 0xE6,
|
||||
0xE1, 0xDB, 0xD5, 0xD0, 0xCA, 0xC5, 0xC0, 0xBB, 0xB6, 0xB2, 0xAE, 0xAA,
|
||||
0xA6, 0xA2, 0x9F, 0x9C, 0x9A, 0x98, 0x96, 0x94, 0x93, 0x92, 0x91, 0x91,
|
||||
0x91, 0x91, 0x92, 0x92, 0x94, 0x95, 0x97, 0x9A, 0x9C, 0x9F, 0xA2, 0xA6,
|
||||
0xA9, 0xAD, 0xB1, 0xB6, 0xBB, 0xBF, 0xC4, 0xCA, 0xCF, 0xD5, 0xDA, 0xE0,
|
||||
0xE6, 0xEC, 0xF2, 0xF8, 0xFE, 0x03, 0x09, 0x0F, 0x15, 0x1B, 0x21, 0x27,
|
||||
0x2D, 0x32, 0x37, 0x3D, 0x42, 0x47, 0x4B, 0x50, 0x54, 0x58, 0x5B, 0x5F,
|
||||
0x62, 0x64, 0x67, 0x69, 0x6B, 0x6D, 0x6E, 0x6F, 0x6F, 0x6F, 0x6F, 0x6F,
|
||||
0x6E, 0x6D, 0x6C, 0x6A, 0x68, 0x66, 0x63, 0x60, 0x5D, 0x59, 0x55, 0x51,
|
||||
0x4D, 0x49, 0x44, 0x3F, 0x3A, 0x35, 0x2F, 0x2A, 0x24, 0x1E, 0x18, 0x12,
|
||||
0x0C, 0x06, 0x00, 0xFB, 0xF5, 0xEF, 0xE9, 0xE3, 0xDD, 0xD7, 0xD2, 0xCC,
|
||||
0xC7, 0xC2, 0xBD, 0xB8, 0xB3, 0xAF, 0xAB, 0xA7, 0xA4, 0xA0, 0x9D, 0x9B,
|
||||
0x98, 0x96, 0x95, 0x93, 0x92, 0x91, 0x91, 0x91, 0x91, 0x91, 0x92, 0x93,
|
||||
0x95, 0x97, 0x99, 0x9B, 0x9E, 0xA1, 0xA4, 0xA8, 0xAC, 0xB0, 0xB4, 0xB9,
|
||||
0xBE, 0xC3, 0xC8, 0xCD, 0xD3, 0xD8, 0xDE, 0xE4, 0xEA, 0xF0, 0xF6, 0xFC,
|
||||
0x01, 0x07, 0x0D, 0x13, 0x19, 0x1F, 0x25, 0x2A, 0x30, 0x35, 0x3B, 0x40,
|
||||
0x45, 0x49, 0x4E, 0x52, 0x56, 0x5A, 0x5D, 0x60, 0x63, 0x66, 0x68, 0x6A,
|
||||
0x6C, 0x6D, 0x6E, 0x6F, 0x6F, 0x6F, 0x6F, 0x6F, 0x6E, 0x6C, 0x6B, 0x69,
|
||||
0x67, 0x64, 0x61, 0x5E, 0x5B, 0x57, 0x53, 0x4F, 0x4A, 0x46, 0x41, 0x3C,
|
||||
0x37, 0x31, 0x2C, 0x26, 0x20, 0x1A, 0x14, 0x0E, 0x08, 0x00, 0xF6, 0xEC,
|
||||
0xE2, 0xD8, 0xCF, 0xC6, 0xBD, 0xB6, 0xAE, 0xA8, 0xA2, 0x9D, 0x98, 0x95,
|
||||
0x93, 0x91, 0x91, 0x91, 0x92, 0x94, 0x97, 0x9B, 0xA0, 0xA6, 0xAC, 0xB3,
|
||||
0xBB, 0xC4, 0xCC, 0xD6, 0xDF, 0xE9, 0xF3, 0xFE, 0x07, 0x11, 0x1B, 0x25,
|
||||
0x2E, 0x37, 0x40, 0x48, 0x50, 0x57, 0x5D, 0x62, 0x66, 0x6A, 0x6D, 0x6F,
|
||||
0x6F, 0x6F, 0x6E, 0x6C, 0x6A, 0x66, 0x61, 0x5C, 0x56, 0x4F, 0x47, 0x3F,
|
||||
0x36, 0x2D, 0x24, 0x1A, 0x10, 0xC4, 0xBD, 0xB7, 0xB2, 0xAE, 0xAA, 0xA6,
|
||||
0xA3, 0xA1, 0x9F, 0x9D, 0x9B, 0x9A, 0x98, 0x97, 0x97, 0x96, 0x95, 0x95,
|
||||
0x94, 0x94, 0x94, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93,
|
||||
0x94, 0x94, 0x95, 0x95, 0x96, 0x96, 0x97, 0x98, 0x99, 0x9B, 0x9C, 0x9E,
|
||||
0xA0, 0xA3, 0xA5, 0xA9, 0xAC, 0xB1, 0xB6, 0xBC, 0xC3, 0xCA, 0xD4, 0xDE,
|
||||
0xEA, 0xF8, 0x08, 0x16, 0x22, 0x2C, 0x36, 0x3D, 0x44, 0x4A, 0x4F, 0x53,
|
||||
0x57, 0x5B, 0x5D, 0x60, 0x62, 0x64, 0x65, 0x67, 0x68, 0x69, 0x69, 0x6A,
|
||||
0x6B, 0x6B, 0x6C, 0x6C, 0x6C, 0x6C, 0x6C, 0x6C, 0x6C, 0x6C, 0x6C, 0x6C,
|
||||
0x6B, 0x6B, 0x6A, 0x69, 0x69, 0x68, 0x67, 0x65, 0x64, 0x62, 0x60, 0x5D,
|
||||
0x5B, 0x57, 0x53, 0x4F, 0x4A, 0x44, 0x3D, 0x36, 0x2C, 0x22, 0x16, 0x08,
|
||||
0xF8, 0xEA, 0xDE, 0xD4, 0xCA, 0xC3, 0xBC, 0xB6, 0xB1, 0xAD, 0xA9, 0xA5,
|
||||
0xA3, 0xA0, 0x9E, 0x9C, 0x9B, 0x99, 0x98, 0x97, 0x97, 0x96, 0x95, 0x95,
|
||||
0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x95, 0x95,
|
||||
0x96, 0x96, 0x97, 0x98, 0x99, 0x9B, 0x9C, 0x9E, 0xA0, 0xA2, 0xA5, 0xA8,
|
||||
0xAC, 0xB0, 0xB5, 0xBB, 0xC1, 0xC9, 0xD2, 0xDC, 0xE8, 0xF5, 0x00, 0x02,
|
||||
0x05, 0x08, 0x0A, 0x0D, 0x10, 0x12, 0x15, 0x17, 0x19, 0x1C, 0x1E, 0x20,
|
||||
0x22, 0x24, 0x26, 0x27, 0x29, 0x2A, 0x2C, 0x2D, 0x2E, 0x2F, 0x30, 0x30,
|
||||
0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x30, 0x30, 0x2F, 0x2E, 0x2D,
|
||||
0x2B, 0x2A, 0x29, 0x27, 0x25, 0x23, 0x21, 0x1F, 0x1D, 0x1B, 0x19, 0x16,
|
||||
0x14, 0x11, 0x0F, 0x0C, 0x09, 0x07, 0x04, 0x00, 0x03, 0x07, 0x0B, 0x0F,
|
||||
0x13, 0x16, 0x1A, 0x1D, 0x21, 0x24, 0x28, 0x2B, 0x2E, 0x31, 0x33, 0x36,
|
||||
0x38, 0x3B, 0x3D, 0x3F, 0x41, 0x42, 0x43, 0x45, 0x46, 0x46, 0x47, 0x47,
|
||||
0x47, 0x47, 0x47, 0x47, 0x46, 0x45, 0x44, 0x43, 0x41, 0x40, 0x3E, 0x3C,
|
||||
0x3A, 0x37, 0x35, 0x32, 0x2F, 0x2C, 0x29, 0x26, 0x23, 0x1F, 0x1C, 0x18,
|
||||
0x15, 0x11, 0x0D, 0x09, 0x05, 0x02, 0xFF, 0xFB, 0xF7, 0xF3, 0xEF, 0xEC,
|
||||
0xE8, 0xE4, 0xE1, 0xDD, 0xDA, 0xD7, 0xD4, 0xD1, 0xCE, 0xCB, 0xC9, 0xC6,
|
||||
0xC4, 0xC2, 0xC0, 0xBF, 0xBD, 0xBC, 0xBB, 0xBA, 0xB9, 0xB9, 0xB9, 0xB9,
|
||||
0xB9, 0xB9, 0xBA, 0xBA, 0xBB, 0xBC, 0xBE, 0xBF, 0xC1, 0xC3, 0xC5, 0xC7,
|
||||
0xCA, 0xCC, 0xCF, 0xD2, 0xD5, 0xD8, 0xDB, 0xDF, 0xE2, 0xE6, 0xE9, 0xED,
|
||||
0xF1, 0xF5, 0xF9, 0xFC
|
||||
};
|
||||
#endif
|
||||
540
drivers/input/misc/aw8622x_haptic/aw8624_reg.h
Normal file
540
drivers/input/misc/aw8622x_haptic/aw8624_reg.h
Normal file
@@ -0,0 +1,540 @@
|
||||
#ifndef _AW8624_REG_H_
|
||||
#define _AW8624_REG_H_
|
||||
|
||||
/********************************************
|
||||
* Register List
|
||||
*******************************************/
|
||||
#define AW8624_REG_ID 0x00
|
||||
#define AW8624_REG_SYSST 0x01
|
||||
#define AW8624_REG_SYSINT 0x02
|
||||
#define AW8624_REG_SYSINTM 0x03
|
||||
#define AW8624_REG_SYSCTRL 0x04
|
||||
#define AW8624_REG_GO 0x05
|
||||
#define AW8624_REG_RTP_DATA 0x06
|
||||
#define AW8624_REG_WAVSEQ1 0x07
|
||||
#define AW8624_REG_WAVSEQ2 0x08
|
||||
#define AW8624_REG_WAVSEQ3 0x09
|
||||
#define AW8624_REG_WAVSEQ4 0x0a
|
||||
#define AW8624_REG_WAVSEQ5 0x0b
|
||||
#define AW8624_REG_WAVSEQ6 0x0c
|
||||
#define AW8624_REG_WAVSEQ7 0x0d
|
||||
#define AW8624_REG_WAVSEQ8 0x0e
|
||||
#define AW8624_REG_WAVLOOP1 0x0f
|
||||
#define AW8624_REG_WAVLOOP2 0x10
|
||||
#define AW8624_REG_WAVLOOP3 0x11
|
||||
#define AW8624_REG_WAVLOOP4 0x12
|
||||
#define AW8624_REG_MAIN_LOOP 0x13
|
||||
#define AW8624_REG_TRG1_SEQP 0x14
|
||||
#define AW8624_REG_TRG1_SEQN 0x17
|
||||
#define AW8624_REG_PLAY_PRIO 0x1a
|
||||
#define AW8624_REG_TRG_CFG1 0x1b
|
||||
#define AW8624_REG_TRG_CFG2 0x1c
|
||||
#define AW8624_REG_DBGCTRL 0x20
|
||||
#define AW8624_REG_BASE_ADDRH 0x21
|
||||
#define AW8624_REG_BASE_ADDRL 0x22
|
||||
#define AW8624_REG_FIFO_AEH 0x23
|
||||
#define AW8624_REG_FIFO_AEL 0x24
|
||||
#define AW8624_REG_FIFO_AFH 0x25
|
||||
#define AW8624_REG_FIFO_AFL 0x26
|
||||
#define AW8624_REG_WAKE_DLY 0x27
|
||||
#define AW8624_REG_START_DLY 0x28
|
||||
#define AW8624_REG_END_DLY_H 0x29
|
||||
#define AW8624_REG_END_DLY_L 0x2a
|
||||
#define AW8624_REG_DATCTRL 0x2b
|
||||
#define AW8624_REG_PWMDEL 0x2c
|
||||
#define AW8624_REG_PWMPRC 0x2d
|
||||
#define AW8624_REG_PWMDBG 0x2e
|
||||
#define AW8624_REG_LDOCTRL 0x2f
|
||||
#define AW8624_REG_DBGSTAT 0x30
|
||||
#define AW8624_REG_WAVECTRL 0x31
|
||||
#define AW8624_REG_BRAKE0_CTRL 0x32
|
||||
#define AW8624_REG_BRAKE1_CTRL 0x33
|
||||
#define AW8624_REG_BRAKE2_CTRL 0x34
|
||||
#define AW8624_REG_BRAKE_NUM 0x35
|
||||
#define AW8624_REG_ANADBG1 0x36
|
||||
#define AW8624_REG_ANADBG2 0x37
|
||||
#define AW8624_REG_ANACTRL 0x38
|
||||
#define AW8624_REG_SW_BRAKE 0x39
|
||||
#define AW8624_REG_GLBDBG 0x3a
|
||||
#define AW8624_REG_DATDBG 0x3b
|
||||
#define AW8624_REG_WDCTRL 0x3c
|
||||
#define AW8624_REG_HDRVDBG 0x3d
|
||||
#define AW8624_REG_PRLVL 0x3e
|
||||
#define AW8624_REG_PRTIME 0x3f
|
||||
#define AW8624_REG_RAMADDRH 0x40
|
||||
#define AW8624_REG_RAMADDRL 0x41
|
||||
#define AW8624_REG_RAMDATA 0x42
|
||||
#define AW8624_REG_TM 0x43
|
||||
#define AW8624_REG_BRA_MAX_NUM 0x44
|
||||
#define AW8624_REG_BEMF_ERM_FAC 0x45
|
||||
#define AW8624_REG_BEMF_BRA_FAC 0x46
|
||||
#define AW8624_REG_GLB_STATE 0x47
|
||||
#define AW8624_REG_CONT_CTRL 0x48
|
||||
#define AW8624_REG_F_PRE_H 0x49
|
||||
#define AW8624_REG_F_PRE_L 0x4a
|
||||
#define AW8624_REG_TD_H 0x4b
|
||||
#define AW8624_REG_TD_L 0x4c
|
||||
#define AW8624_REG_TSET 0x4d
|
||||
#define AW8624_REG_THRS_BRA_RAP 0x4e
|
||||
#define AW8624_REG_THRS_BRA_END 0x4f
|
||||
#define AW8624_REG_EF_CTRL 0x50
|
||||
#define AW8624_REG_EF_WDATAH 0x53
|
||||
#define AW8624_REG_EF_WDATAL 0x54
|
||||
#define AW8624_REG_EF_RDATAH 0x55
|
||||
#define AW8624_REG_EF_RDATAL 0x56
|
||||
#define AW8624_REG_DLY 0x57
|
||||
#define AW8624_REG_EF_WR_WIDTH 0x58
|
||||
#define AW8624_REG_EF_RD_WIDTH 0x59
|
||||
#define AW8624_REG_TRIM_LRA 0x5b
|
||||
#define AW8624_REG_TRIM_OSC 0x5c
|
||||
#define AW8624_REG_R_SPARE 0x5d
|
||||
#define AW8624_REG_D2SCFG 0x5e
|
||||
#define AW8624_REG_DETCTRL 0x5f
|
||||
#define AW8624_REG_RLDET 0x60
|
||||
#define AW8624_REG_OSDET 0x61
|
||||
#define AW8624_REG_VBATDET 0x62
|
||||
#define AW8624_REG_TESTDET 0x63
|
||||
#define AW8624_REG_DETLO 0x64
|
||||
#define AW8624_REG_BEMFDBG 0x65
|
||||
#define AW8624_REG_ADCTEST 0x66
|
||||
#define AW8624_REG_BEMFTEST 0x67
|
||||
#define AW8624_REG_F_LRA_F0_H 0x68
|
||||
#define AW8624_REG_F_LRA_F0_L 0x69
|
||||
#define AW8624_REG_F_LRA_CONT_H 0x6a
|
||||
#define AW8624_REG_F_LRA_CONT_L 0x6b
|
||||
#define AW8624_REG_WAIT_VOL_MP 0x6e
|
||||
#define AW8624_REG_WAIT_VOL_MN 0x6f
|
||||
#define AW8624_REG_BEMF_VOL_H 0x70
|
||||
#define AW8624_REG_BEMF_VOL_L 0x71
|
||||
#define AW8624_REG_ZC_THRSH_H 0x72
|
||||
#define AW8624_REG_ZC_THRSH_L 0x73
|
||||
#define AW8624_REG_BEMF_VTHH_H 0x74
|
||||
#define AW8624_REG_BEMF_VTHH_L 0x75
|
||||
#define AW8624_REG_BEMF_VTHL_H 0x76
|
||||
#define AW8624_REG_BEMF_VTHL_L 0x77
|
||||
#define AW8624_REG_BEMF_NUM 0x78
|
||||
#define AW8624_REG_DRV_TIME 0x79
|
||||
#define AW8624_REG_TIME_NZC 0x7a
|
||||
#define AW8624_REG_DRV_LVL 0x7b
|
||||
#define AW8624_REG_DRV_LVL_OV 0x7c
|
||||
#define AW8624_REG_NUM_F0_1 0x7d
|
||||
#define AW8624_REG_NUM_F0_2 0x7e
|
||||
#define AW8624_REG_NUM_F0_3 0x7f
|
||||
|
||||
|
||||
|
||||
/********************************************
|
||||
* Register Access
|
||||
*******************************************/
|
||||
#define REG_NONE_ACCESS 0
|
||||
#define REG_RD_ACCESS (1 << 0)
|
||||
#define REG_WR_ACCESS (1 << 1)
|
||||
#define AW8624_REG_MAX 0xff
|
||||
|
||||
|
||||
const unsigned char aw8624_reg_access[AW8624_REG_MAX] = {
|
||||
[AW8624_REG_ID] = REG_RD_ACCESS,
|
||||
[AW8624_REG_SYSST] = REG_RD_ACCESS,
|
||||
[AW8624_REG_SYSINT] = REG_RD_ACCESS,
|
||||
[AW8624_REG_SYSINTM] = REG_RD_ACCESS|REG_WR_ACCESS,
|
||||
[AW8624_REG_SYSCTRL] = REG_RD_ACCESS|REG_WR_ACCESS,
|
||||
[AW8624_REG_GO] = REG_RD_ACCESS|REG_WR_ACCESS,
|
||||
[AW8624_REG_RTP_DATA] = REG_RD_ACCESS|REG_WR_ACCESS,
|
||||
[AW8624_REG_WAVSEQ1] = REG_RD_ACCESS|REG_WR_ACCESS,
|
||||
[AW8624_REG_WAVSEQ2] = REG_RD_ACCESS|REG_WR_ACCESS,
|
||||
[AW8624_REG_WAVSEQ3] = REG_RD_ACCESS|REG_WR_ACCESS,
|
||||
[AW8624_REG_WAVSEQ4] = REG_RD_ACCESS|REG_WR_ACCESS,
|
||||
[AW8624_REG_WAVSEQ5] = REG_RD_ACCESS|REG_WR_ACCESS,
|
||||
[AW8624_REG_WAVSEQ6] = REG_RD_ACCESS|REG_WR_ACCESS,
|
||||
[AW8624_REG_WAVSEQ7] = REG_RD_ACCESS|REG_WR_ACCESS,
|
||||
[AW8624_REG_WAVSEQ8] = REG_RD_ACCESS|REG_WR_ACCESS,
|
||||
[AW8624_REG_WAVLOOP1] = REG_RD_ACCESS|REG_WR_ACCESS,
|
||||
[AW8624_REG_WAVLOOP2] = REG_RD_ACCESS|REG_WR_ACCESS,
|
||||
[AW8624_REG_WAVLOOP3] = REG_RD_ACCESS|REG_WR_ACCESS,
|
||||
[AW8624_REG_WAVLOOP4] = REG_RD_ACCESS|REG_WR_ACCESS,
|
||||
[AW8624_REG_MAIN_LOOP] = REG_RD_ACCESS|REG_WR_ACCESS,
|
||||
[AW8624_REG_TRG1_SEQP] = REG_RD_ACCESS|REG_WR_ACCESS,
|
||||
[AW8624_REG_TRG1_SEQN] = REG_RD_ACCESS|REG_WR_ACCESS,
|
||||
[AW8624_REG_PLAY_PRIO] = REG_RD_ACCESS|REG_WR_ACCESS,
|
||||
[AW8624_REG_TRG_CFG1] = REG_RD_ACCESS|REG_WR_ACCESS,
|
||||
[AW8624_REG_TRG_CFG2] = REG_RD_ACCESS|REG_WR_ACCESS,
|
||||
[AW8624_REG_DBGCTRL] = REG_RD_ACCESS|REG_WR_ACCESS,
|
||||
[AW8624_REG_BASE_ADDRH] = REG_RD_ACCESS|REG_WR_ACCESS,
|
||||
[AW8624_REG_BASE_ADDRL] = REG_RD_ACCESS|REG_WR_ACCESS,
|
||||
[AW8624_REG_FIFO_AEH] = REG_RD_ACCESS|REG_WR_ACCESS,
|
||||
[AW8624_REG_FIFO_AEL] = REG_RD_ACCESS|REG_WR_ACCESS,
|
||||
[AW8624_REG_FIFO_AFH] = REG_RD_ACCESS|REG_WR_ACCESS,
|
||||
[AW8624_REG_FIFO_AFL] = REG_RD_ACCESS|REG_WR_ACCESS,
|
||||
[AW8624_REG_WAKE_DLY] = REG_RD_ACCESS|REG_WR_ACCESS,
|
||||
[AW8624_REG_START_DLY] = REG_RD_ACCESS|REG_WR_ACCESS,
|
||||
[AW8624_REG_END_DLY_H] = REG_RD_ACCESS|REG_WR_ACCESS,
|
||||
[AW8624_REG_END_DLY_L] = REG_RD_ACCESS|REG_WR_ACCESS,
|
||||
[AW8624_REG_DATCTRL] = REG_RD_ACCESS|REG_WR_ACCESS,
|
||||
[AW8624_REG_PWMDEL] = REG_RD_ACCESS|REG_WR_ACCESS,
|
||||
[AW8624_REG_PWMPRC] = REG_RD_ACCESS|REG_WR_ACCESS,
|
||||
[AW8624_REG_PWMDBG] = REG_RD_ACCESS|REG_WR_ACCESS,
|
||||
[AW8624_REG_LDOCTRL] = REG_RD_ACCESS|REG_WR_ACCESS,
|
||||
[AW8624_REG_DBGSTAT] = REG_RD_ACCESS,
|
||||
[AW8624_REG_WAVECTRL] = REG_RD_ACCESS|REG_WR_ACCESS,
|
||||
[AW8624_REG_BRAKE0_CTRL] = REG_RD_ACCESS|REG_WR_ACCESS,
|
||||
[AW8624_REG_BRAKE1_CTRL] = REG_RD_ACCESS|REG_WR_ACCESS,
|
||||
[AW8624_REG_BRAKE2_CTRL] = REG_RD_ACCESS|REG_WR_ACCESS,
|
||||
[AW8624_REG_BRAKE_NUM] = REG_RD_ACCESS|REG_WR_ACCESS,
|
||||
[AW8624_REG_ANADBG1] = REG_RD_ACCESS|REG_WR_ACCESS,
|
||||
[AW8624_REG_ANADBG2] = REG_RD_ACCESS|REG_WR_ACCESS,
|
||||
[AW8624_REG_ANACTRL] = REG_RD_ACCESS|REG_WR_ACCESS,
|
||||
[AW8624_REG_SW_BRAKE] = REG_RD_ACCESS|REG_WR_ACCESS,
|
||||
[AW8624_REG_GLBDBG] = REG_RD_ACCESS|REG_WR_ACCESS,
|
||||
[AW8624_REG_DATDBG] = REG_RD_ACCESS|REG_WR_ACCESS,
|
||||
[AW8624_REG_WDCTRL] = REG_RD_ACCESS|REG_WR_ACCESS,
|
||||
[AW8624_REG_HDRVDBG] = REG_RD_ACCESS|REG_WR_ACCESS,
|
||||
[AW8624_REG_PRLVL] = REG_RD_ACCESS|REG_WR_ACCESS,
|
||||
[AW8624_REG_PRTIME] = REG_RD_ACCESS|REG_WR_ACCESS,
|
||||
[AW8624_REG_RAMADDRH] = REG_RD_ACCESS|REG_WR_ACCESS,
|
||||
[AW8624_REG_RAMADDRL] = REG_RD_ACCESS|REG_WR_ACCESS,
|
||||
[AW8624_REG_RAMDATA] = REG_RD_ACCESS|REG_WR_ACCESS,
|
||||
[AW8624_REG_TM] = REG_RD_ACCESS|REG_WR_ACCESS,
|
||||
[AW8624_REG_BRA_MAX_NUM] = REG_RD_ACCESS|REG_WR_ACCESS,
|
||||
[AW8624_REG_BEMF_ERM_FAC] = REG_RD_ACCESS|REG_WR_ACCESS,
|
||||
[AW8624_REG_BEMF_BRA_FAC] = REG_RD_ACCESS|REG_WR_ACCESS,
|
||||
[AW8624_REG_GLB_STATE] = REG_RD_ACCESS|REG_WR_ACCESS,
|
||||
[AW8624_REG_CONT_CTRL] = REG_RD_ACCESS|REG_WR_ACCESS,
|
||||
[AW8624_REG_F_PRE_H] = REG_RD_ACCESS|REG_WR_ACCESS,
|
||||
[AW8624_REG_F_PRE_L] = REG_RD_ACCESS|REG_WR_ACCESS,
|
||||
[AW8624_REG_TD_H] = REG_RD_ACCESS|REG_WR_ACCESS,
|
||||
[AW8624_REG_TD_L] = REG_RD_ACCESS|REG_WR_ACCESS,
|
||||
[AW8624_REG_TSET] = REG_RD_ACCESS|REG_WR_ACCESS,
|
||||
[AW8624_REG_THRS_BRA_RAP] = REG_RD_ACCESS|REG_WR_ACCESS,
|
||||
[AW8624_REG_THRS_BRA_END] = REG_RD_ACCESS|REG_WR_ACCESS,
|
||||
[AW8624_REG_EF_CTRL] = REG_RD_ACCESS|REG_WR_ACCESS,
|
||||
[AW8624_REG_EF_WDATAH] = REG_RD_ACCESS|REG_WR_ACCESS,
|
||||
[AW8624_REG_EF_WDATAL] = REG_RD_ACCESS|REG_WR_ACCESS,
|
||||
[AW8624_REG_EF_RDATAH] = REG_RD_ACCESS|REG_WR_ACCESS,
|
||||
[AW8624_REG_EF_RDATAL] = REG_RD_ACCESS|REG_WR_ACCESS,
|
||||
[AW8624_REG_DLY] = REG_RD_ACCESS|REG_WR_ACCESS,
|
||||
[AW8624_REG_EF_WR_WIDTH] = REG_RD_ACCESS|REG_WR_ACCESS,
|
||||
[AW8624_REG_EF_RD_WIDTH] = REG_RD_ACCESS|REG_WR_ACCESS,
|
||||
[AW8624_REG_TRIM_LRA] = REG_RD_ACCESS|REG_WR_ACCESS,
|
||||
[AW8624_REG_TRIM_OSC] = REG_RD_ACCESS|REG_WR_ACCESS,
|
||||
[AW8624_REG_R_SPARE] = REG_RD_ACCESS|REG_WR_ACCESS,
|
||||
[AW8624_REG_D2SCFG] = REG_RD_ACCESS|REG_WR_ACCESS,
|
||||
[AW8624_REG_DETCTRL] = REG_RD_ACCESS|REG_WR_ACCESS,
|
||||
[AW8624_REG_RLDET] = REG_RD_ACCESS,
|
||||
[AW8624_REG_OSDET] = REG_RD_ACCESS,
|
||||
[AW8624_REG_VBATDET] = REG_RD_ACCESS,
|
||||
[AW8624_REG_TESTDET] = REG_RD_ACCESS|REG_WR_ACCESS,
|
||||
[AW8624_REG_DETLO] = REG_RD_ACCESS|REG_WR_ACCESS,
|
||||
[AW8624_REG_BEMFDBG] = REG_RD_ACCESS|REG_WR_ACCESS,
|
||||
[AW8624_REG_ADCTEST] = REG_RD_ACCESS|REG_WR_ACCESS,
|
||||
[AW8624_REG_BEMFTEST] = REG_RD_ACCESS|REG_WR_ACCESS,
|
||||
[AW8624_REG_F_LRA_F0_H] = REG_RD_ACCESS,
|
||||
[AW8624_REG_F_LRA_F0_L] = REG_RD_ACCESS,
|
||||
[AW8624_REG_F_LRA_CONT_H] = REG_RD_ACCESS,
|
||||
[AW8624_REG_F_LRA_CONT_L] = REG_RD_ACCESS,
|
||||
[AW8624_REG_WAIT_VOL_MP] = REG_RD_ACCESS,
|
||||
[AW8624_REG_WAIT_VOL_MN] = REG_RD_ACCESS,
|
||||
[AW8624_REG_BEMF_VOL_H] = REG_RD_ACCESS,
|
||||
[AW8624_REG_BEMF_VOL_L] = REG_RD_ACCESS,
|
||||
[AW8624_REG_ZC_THRSH_H] = REG_RD_ACCESS|REG_WR_ACCESS,
|
||||
[AW8624_REG_ZC_THRSH_L] = REG_RD_ACCESS|REG_WR_ACCESS,
|
||||
[AW8624_REG_BEMF_VTHH_H] = REG_RD_ACCESS|REG_WR_ACCESS,
|
||||
[AW8624_REG_BEMF_VTHH_L] = REG_RD_ACCESS|REG_WR_ACCESS,
|
||||
[AW8624_REG_BEMF_VTHL_H] = REG_RD_ACCESS|REG_WR_ACCESS,
|
||||
[AW8624_REG_BEMF_VTHL_L] = REG_RD_ACCESS|REG_WR_ACCESS,
|
||||
[AW8624_REG_BEMF_NUM] = REG_RD_ACCESS|REG_WR_ACCESS,
|
||||
[AW8624_REG_DRV_TIME] = REG_RD_ACCESS|REG_WR_ACCESS,
|
||||
[AW8624_REG_TIME_NZC] = REG_RD_ACCESS|REG_WR_ACCESS,
|
||||
[AW8624_REG_DRV_LVL] = REG_RD_ACCESS|REG_WR_ACCESS,
|
||||
[AW8624_REG_DRV_LVL_OV] = REG_RD_ACCESS|REG_WR_ACCESS,
|
||||
[AW8624_REG_NUM_F0_1] = REG_RD_ACCESS|REG_WR_ACCESS,
|
||||
[AW8624_REG_NUM_F0_2] = REG_RD_ACCESS|REG_WR_ACCESS,
|
||||
[AW8624_REG_NUM_F0_3] = REG_RD_ACCESS|REG_WR_ACCESS,
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
/******************************************************
|
||||
* Register Detail
|
||||
*****************************************************/
|
||||
/* SYSST 0x01 */
|
||||
#define AW8624_BIT_SYSST_OVS (1<<6)
|
||||
#define AW8624_BIT_SYSST_UVLS (1<<5)
|
||||
#define AW8624_BIT_SYSST_FF_AES (1<<4)
|
||||
#define AW8624_BIT_SYSST_FF_AFS (1<<3)
|
||||
#define AW8624_BIT_SYSST_OCDS (1<<2)
|
||||
#define AW8624_BIT_SYSST_OTS (1<<1)
|
||||
#define AW8624_BIT_SYSST_DONES (1<<0)
|
||||
|
||||
/* SYSINT 0x02 */
|
||||
#define AW8624_BIT_SYSINT_OVI (1<<6)
|
||||
#define AW8624_BIT_SYSINT_UVLI (1<<5)
|
||||
#define AW8624_BIT_SYSINT_FF_AEI (1<<4)
|
||||
#define AW8624_BIT_SYSINT_FF_AFI (1<<3)
|
||||
#define AW8624_BIT_SYSINT_OCDI (1<<2)
|
||||
#define AW8624_BIT_SYSINT_OTI (1<<1)
|
||||
#define AW8624_BIT_SYSINT_DONEI (1<<0)
|
||||
|
||||
/* SYSINTM 0x03 */
|
||||
#define AW8624_BIT_SYSINTM_OV_MASK (~(1<<6))
|
||||
#define AW8624_BIT_SYSINTM_OV_OFF (1<<6)
|
||||
#define AW8624_BIT_SYSINTM_OV_EN (0<<6)
|
||||
#define AW8624_BIT_SYSINTM_UVLO_MASK (~(1<<5))
|
||||
#define AW8624_BIT_SYSINTM_UVLO_OFF (1<<5)
|
||||
#define AW8624_BIT_SYSINTM_UVLO_EN (0<<5)
|
||||
#define AW8624_BIT_SYSINTM_FF_AE_MASK (~(1<<4))
|
||||
#define AW8624_BIT_SYSINTM_FF_AE_OFF (1<<4)
|
||||
#define AW8624_BIT_SYSINTM_FF_AE_EN (0<<4)
|
||||
#define AW8624_BIT_SYSINTM_FF_AF_MASK (~(1<<3))
|
||||
#define AW8624_BIT_SYSINTM_FF_AF_OFF (1<<3)
|
||||
#define AW8624_BIT_SYSINTM_FF_AF_EN (0<<3)
|
||||
#define AW8624_BIT_SYSINTM_OCD_MASK (~(1<<2))
|
||||
#define AW8624_BIT_SYSINTM_OCD_OFF (1<<2)
|
||||
#define AW8624_BIT_SYSINTM_OCD_EN (0<<2)
|
||||
#define AW8624_BIT_SYSINTM_OT_MASK (~(1<<1))
|
||||
#define AW8624_BIT_SYSINTM_OT_OFF (1<<1)
|
||||
#define AW8624_BIT_SYSINTM_OT_EN (0<<1)
|
||||
#define AW8624_BIT_SYSINTM_DONE_MASK (~(1<<0))
|
||||
#define AW8624_BIT_SYSINTM_DONE_OFF (1<<0)
|
||||
#define AW8624_BIT_SYSINTM_DONE_EN (0<<0)
|
||||
|
||||
/* SYSCTRL 0x04 */
|
||||
#define AW8624_BIT_SYSCTRL_WAVDAT_MODE_MASK (~(3<<6))
|
||||
#define AW8624_BIT_SYSCTRL_WAVDAT_MODE_4X (3<<6)
|
||||
#define AW8624_BIT_SYSCTRL_WAVDAT_MODE_2X (0<<6)
|
||||
#define AW8624_BIT_SYSCTRL_WAVDAT_MODE_1X (1<<6)
|
||||
#define AW8624_BIT_SYSCTRL_RAMINIT_MASK (~(1<<5))
|
||||
#define AW8624_BIT_SYSCTRL_RAMINIT_EN (1<<5)
|
||||
#define AW8624_BIT_SYSCTRL_RAMINIT_OFF (0<<5)
|
||||
#define AW8624_BIT_SYSCTRL_PLAY_MODE_MASK (~(3<<2))
|
||||
#define AW8624_BIT_SYSCTRL_PLAY_MODE_CONT (2<<2)
|
||||
#define AW8624_BIT_SYSCTRL_PLAY_MODE_RTP (1<<2)
|
||||
#define AW8624_BIT_SYSCTRL_PLAY_MODE_RAM (0<<2)
|
||||
#define AW8624_BIT_SYSCTRL_WORK_MODE_MASK (~(1<<0))
|
||||
#define AW8624_BIT_SYSCTRL_STANDBY (1<<0)
|
||||
#define AW8624_BIT_SYSCTRL_ACTIVE (0<<0)
|
||||
|
||||
/* GO 0x05 */
|
||||
#define AW8624_BIT_GO_MASK (~(1<<0))
|
||||
#define AW8624_BIT_GO_ENABLE (1<<0)
|
||||
#define AW8624_BIT_GO_DISABLE (0<<0)
|
||||
|
||||
/* WAVSEQ1 0x07 */
|
||||
#define AW8624_BIT_WAVSEQ1_WAIT (1<<7)
|
||||
#define AW8624_BIT_WAVSEQ1_WAV_FRM_SEQ1_MASK (~(127<<0))
|
||||
|
||||
/* WAVSEQ2 0x08 */
|
||||
#define AW8624_BIT_WAVSEQ2_WAIT (1<<7)
|
||||
#define AW8624_BIT_WAVSEQ2_WAV_FRM_SEQ2_MASK (~(127<<0))
|
||||
|
||||
/* WAVSEQ3 0x09 */
|
||||
#define AW8624_BIT_WAVSEQ3_WAIT (1<<7)
|
||||
#define AW8624_BIT_WAVSEQ3_WAV_FRM_SEQ3_MASK (~(127<<0))
|
||||
|
||||
/* WAVSEQ4 0x0A */
|
||||
#define AW8624_BIT_WAVSEQ4_WAIT (1<<7)
|
||||
#define AW8624_BIT_WAVSEQ4_WAV_FRM_SEQ4_MASK (~(127<<0))
|
||||
|
||||
/* WAVSEQ5 0X0B */
|
||||
#define AW8624_BIT_WAVSEQ5_WAIT (1<<7)
|
||||
#define AW8624_BIT_WAVSEQ5_WAV_FRM_SEQ5_MASK (~(127<<0))
|
||||
|
||||
/* WAVSEQ6 0X0C */
|
||||
#define AW8624_BIT_WAVSEQ6_WAIT (1<<7)
|
||||
#define AW8624_BIT_WAVSEQ6_WAV_FRM_SEQ6_MASK (~(127<<0))
|
||||
|
||||
/* WAVSEQ7 */
|
||||
#define AW8624_BIT_WAVSEQ7_WAIT (1<<7)
|
||||
#define AW8624_BIT_WAVSEQ7_WAV_FRM_SEQ7_MASK (~(127<<0))
|
||||
|
||||
/* WAVSEQ8 */
|
||||
#define AW8624_BIT_WAVSEQ8_WAIT (1<<7)
|
||||
#define AW8624_BIT_WAVSEQ8_WAV_FRM_SEQ8_MASK (~(127<<0))
|
||||
|
||||
/* WAVLOOP */
|
||||
#define AW8624_BIT_WAVLOOP_SEQN_MASK (~(15<<4))
|
||||
#define AW8624_BIT_WAVLOOP_SEQNP1_MASK (~(15<<0))
|
||||
#define AW8624_BIT_WAVLOOP_INIFINITELY (15<<0)
|
||||
|
||||
/* WAVLOOP1 */
|
||||
#define AW8624_BIT_WAVLOOP1_SEQ1_MASK (~(15<<4))
|
||||
#define AW8624_BIT_WAVLOOP1_SEQ2_MASK (~(15<<0))
|
||||
|
||||
/* WAVLOOP2 */
|
||||
#define AW8624_BIT_WAVLOOP2_SEQ3_MASK (~(15<<4))
|
||||
#define AW8624_BIT_WAVLOOP2_SEQ4_MASK (~(15<<0))
|
||||
|
||||
/* WAVLOOP3 */
|
||||
#define AW8624_BIT_WAVLOOP3_SEQ5_MASK (~(15<<4))
|
||||
#define AW8624_BIT_WAVLOOP3_SEQ6_MASK (~(15<<0))
|
||||
|
||||
/* WAVLOOP4 */
|
||||
#define AW8624_BIT_WAVLOOP4_SEQ7_MASK (~(15<<4))
|
||||
#define AW8624_BIT_WAVLOOP4_SEQ8_MASK (~(15<<0))
|
||||
|
||||
|
||||
/* PLAYPRIO */
|
||||
#define AW8624_BIT_PLAYPRIO_GO_MASK (~(3<<6))
|
||||
#define AW8624_BIT_PLAYPRIO_TRIG3_MASK (~(3<<4))
|
||||
#define AW8624_BIT_PLAYPRIO_TRIG2_MASK (~(3<<2))
|
||||
#define AW8624_BIT_PLAYPRIO_TRIG1_MASK (~(3<<0))
|
||||
|
||||
/* TRGCFG1 */
|
||||
#define AW8624_BIT_TRGCFG1_TRG3_POLAR_MASK (~(1<<5))
|
||||
#define AW8624_BIT_TRGCFG1_TRG3_POLAR_NEG (1<<5)
|
||||
#define AW8624_BIT_TRGCFG1_TRG3_POLAR_POS (0<<5)
|
||||
#define AW8624_BIT_TRGCFG1_TRG3_EDGE_MASK (~(1<<4))
|
||||
#define AW8624_BIT_TRGCFG1_TRG3_EDGE_POS (1<<4)
|
||||
#define AW8624_BIT_TRGCFG1_TRG3_EDGE_POS_NEG (0<<4)
|
||||
#define AW8624_BIT_TRGCFG1_TRG2_POLAR_MASK (~(1<<3))
|
||||
#define AW8624_BIT_TRGCFG1_TRG2_POLAR_NEG (1<<3)
|
||||
#define AW8624_BIT_TRGCFG1_TRG2_POLAR_POS (0<<3)
|
||||
#define AW8624_BIT_TRGCFG1_TRG2_EDGE_MASK (~(1<<2))
|
||||
#define AW8624_BIT_TRGCFG1_TRG2_EDGE_POS (1<<2)
|
||||
#define AW8624_BIT_TRGCFG1_TRG2_EDGE_POS_NEG (0<<2)
|
||||
#define AW8624_BIT_TRGCFG1_TRG1_POLAR_MASK (~(1<<1))
|
||||
#define AW8624_BIT_TRGCFG1_TRG1_POLAR_NEG (1<<1)
|
||||
#define AW8624_BIT_TRGCFG1_TRG1_POLAR_POS (0<<1)
|
||||
#define AW8624_BIT_TRGCFG1_TRG1_EDGE_MASK (~(1<<0))
|
||||
#define AW8624_BIT_TRGCFG1_TRG1_EDGE_POS (1<<0)
|
||||
#define AW8624_BIT_TRGCFG1_TRG1_EDGE_POS_NEG (0<<0)
|
||||
|
||||
/* TRGCFG2 */
|
||||
#define AW8624_BIT_TRGCFG2_TRG3_ENABLE_MASK (~(1<<2))
|
||||
#define AW8624_BIT_TRGCFG2_TRG3_ENABLE (1<<2)
|
||||
#define AW8624_BIT_TRGCFG2_TRG3_DISABLE (0<<2)
|
||||
#define AW8624_BIT_TRGCFG2_TRG2_ENABLE_MASK (~(1<<1))
|
||||
#define AW8624_BIT_TRGCFG2_TRG2_ENABLE (1<<1)
|
||||
#define AW8624_BIT_TRGCFG2_TRG2_DISABLE (0<<1)
|
||||
#define AW8624_BIT_TRGCFG2_TRG1_ENABLE_MASK (~(1<<0))
|
||||
#define AW8624_BIT_TRGCFG2_TRG1_ENABLE (1<<0)
|
||||
#define AW8624_BIT_TRGCFG2_TRG1_DISABLE (0<<0)
|
||||
|
||||
/*DBGCTRL 0X20 */
|
||||
#define AW8624_BIT_DBGCTRL_INTN_TRG_SEL_MASK (~(1<<5))
|
||||
#define AW8624_BIT_DBGCTRL_INTN_SEL_ENABLE (1<<5)
|
||||
#define AW8624_BIT_DBGCTRL_TRG_SEL_ENABLE (0<<5)
|
||||
#define AW8624_BIT_DBGCTRL_INTMODE_MASK (~(3<<2))
|
||||
#define AW8624_BIT_DBGCTRL_INTN_LEVEL_MODE (0<<2)
|
||||
#define AW8624_BIT_DBGCTRL_INTN_EDGE_MODE (1<<2)
|
||||
#define AW8624_BIT_DBGCTRL_INTN_POSEDGE_MODE (2<<2)
|
||||
#define AW8624_BIT_DBGCTRL_INTN_BOTH_EDGE_MODE (3<<2)
|
||||
|
||||
|
||||
/* DATCTRL */
|
||||
#define AW8624_BIT_DATCTRL_FC_MASK (~(1<<6))
|
||||
#define AW8624_BIT_DATCTRL_FC_1000HZ (3<<6)
|
||||
#define AW8624_BIT_DATCTRL_FC_800HZ (3<<6)
|
||||
#define AW8624_BIT_DATCTRL_FC_600HZ (1<<6)
|
||||
#define AW8624_BIT_DATCTRL_FC_400HZ (0<<6)
|
||||
#define AW8624_BIT_DATCTRL_LPF_ENABLE_MASK (~(1<<5))
|
||||
#define AW8624_BIT_DATCTRL_LPF_ENABLE (1<<5)
|
||||
#define AW8624_BIT_DATCTRL_LPF_DISABLE (0<<5)
|
||||
|
||||
/*PWMPRC 0X2D */
|
||||
#define AW8624_BIT_PWMPRC_PRC_EN_MASK (~(1<<7))
|
||||
#define AW8624_BIT_PWMPRC_PRC_ENABLE (1<<7)
|
||||
#define AW8624_BIT_PWMPRC_PRC_DISABLE (0<<7)
|
||||
#define AW8624_BIT_PWMPRC_PRCTIME_MASK (~(0x7f<<0))
|
||||
|
||||
/* REG:0X2E PWMDBG */
|
||||
#define AW8624_BIT_PWMDBG_PWM_MODE_MASK (~(3<<5))
|
||||
#define AW8624_BIT_PWMDBG_PWM_12K (3<<5)
|
||||
#define AW8624_BIT_PWMDBG_PWM_24K (2<<5)
|
||||
#define AW8624_BIT_PWMDBG_PWM_48K (0<<5)
|
||||
|
||||
/* WAVECTRL */
|
||||
#define AW8624_BIT_WAVECTRL_NUM_OV_DRIVER_MASK (~(0xF<<4))
|
||||
#define AW8624_BIT_WAVECTRL_NUM_OV_DRIVER (0<<4)
|
||||
|
||||
/* CONT_CTRL */
|
||||
#define AW8624_BIT_CONT_CTRL_ZC_DETEC_MASK (~(1<<7))
|
||||
#define AW8624_BIT_CONT_CTRL_ZC_DETEC_ENABLE (1<<7)
|
||||
#define AW8624_BIT_CONT_CTRL_ZC_DETEC_DISABLE (0<<7)
|
||||
#define AW8624_BIT_CONT_CTRL_WAIT_PERIOD_MASK (~(3<<5))
|
||||
#define AW8624_BIT_CONT_CTRL_WAIT_8PERIOD (3<<5)
|
||||
#define AW8624_BIT_CONT_CTRL_WAIT_4PERIOD (2<<5)
|
||||
#define AW8624_BIT_CONT_CTRL_WAIT_2PERIOD (1<<5)
|
||||
#define AW8624_BIT_CONT_CTRL_WAIT_1PERIOD (0<<5)
|
||||
#define AW8624_BIT_CONT_CTRL_MODE_MASK (~(1<<4))
|
||||
#define AW8624_BIT_CONT_CTRL_BY_DRV_TIME (1<<4)
|
||||
#define AW8624_BIT_CONT_CTRL_BY_GO_SIGNAL (0<<4)
|
||||
#define AW8624_BIT_CONT_CTRL_EN_CLOSE_MASK (~(1<<3))
|
||||
#define AW8624_BIT_CONT_CTRL_CLOSE_PLAYBACK (1<<3)
|
||||
#define AW8624_BIT_CONT_CTRL_OPEN_PLAYBACK (0<<3)
|
||||
#define AW8624_BIT_CONT_CTRL_F0_DETECT_MASK (~(1<<2))
|
||||
#define AW8624_BIT_CONT_CTRL_F0_DETECT_ENABLE (1<<2)
|
||||
#define AW8624_BIT_CONT_CTRL_F0_DETECT_DISABLE (0<<2)
|
||||
#define AW8624_BIT_CONT_CTRL_O2C_MASK (~(1<<1))
|
||||
#define AW8624_BIT_CONT_CTRL_O2C_ENABLE (1<<1)
|
||||
#define AW8624_BIT_CONT_CTRL_O2C_DISABLE (0<<1)
|
||||
#define AW8624_BIT_CONT_CTRL_AUTO_BRK_MASK (~(1<<0))
|
||||
#define AW8624_BIT_CONT_CTRL_AUTO_BRK_ENABLE (1<<0)
|
||||
#define AW8624_BIT_CONT_CTRL_AUTO_BRK_DISABLE (0<<0)
|
||||
|
||||
#define AW8624_BIT_D2SCFG_CLK_ADC_MASK (~(7<<4))
|
||||
#define AW8624_BIT_D2SCFG_CLK_ASC_1P5MHZ (3<<4)
|
||||
|
||||
/* DETCTRL */
|
||||
#define AW8624_BIT_DETCTRL_RL_OS_MASK (~(1<<6))
|
||||
#define AW8624_BIT_DETCTRL_RL_DETECT (1<<6)
|
||||
#define AW8624_BIT_DETCTRL_OS_DETECT (0<<6)
|
||||
#define AW8624_BIT_DETCTRL_PROTECT_MASK (~(1<<5))
|
||||
#define AW8624_BIT_DETCTRL_PROTECT_NO_ACTION (1<<5)
|
||||
#define AW8624_BIT_DETCTRL_PROTECT_SHUTDOWN (0<<5)
|
||||
#define AW8624_BIT_DETCTRL_VBAT_GO_MASK (~(1<<1))
|
||||
#define AW8624_BIT_DETCTRL_VABT_GO_ENABLE (1<<1)
|
||||
#define AW8624_BIT_DETCTRL_VBAT_GO_DISBALE (0<<1)
|
||||
#define AW8624_BIT_DETCTRL_DIAG_GO_MASK (~(1<<0))
|
||||
#define AW8624_BIT_DETCTRL_DIAG_GO_ENABLE (1<<0)
|
||||
#define AW8624_BIT_DETCTRL_DIAG_GO_DISABLE (0<<0)
|
||||
|
||||
|
||||
/* VBAT MODE */
|
||||
#define AW8624_BIT_DETCTRL_VBAT_MODE_MASK (~(1<<6))
|
||||
#define AW8624_BIT_DETCTRL_VBAT_HW_COMP (1<<6)
|
||||
#define AW8624_BIT_DETCTRL_VBAT_SW_COMP (0<<6)
|
||||
|
||||
|
||||
/* ANACTRL */
|
||||
#define AW8624_BIT_ANACTRL_LRA_SRC_MASK (~(1<<5))
|
||||
#define AW8624_BIT_ANACTRL_LRA_SRC_REG (1<<5)
|
||||
#define AW8624_BIT_ANACTRL_LRA_SRC_EFUSE (0<<5)
|
||||
#define AW8624_BIT_ANACTRL_EN_IO_PD1_MASK (~(1<<0))
|
||||
#define AW8624_BIT_ANACTRL_EN_IO_PD1_HIGH (1<<0)
|
||||
#define AW8624_BIT_ANACTRL_EN_IO_PD1_LOW (0<<0)
|
||||
|
||||
/* SW_BRAKE */
|
||||
#define AW8624_BIT_EN_BRAKE_CONT_MASK (~(1<<3))
|
||||
#define AW8624_BIT_EN_BRAKE_CONT_ENABLE (1<<3)
|
||||
#define AW8624_BIT_EN_BRAKE_CONT_DISABLE (0<<3)
|
||||
#define AW8624_BIT_EN_BRAKE_RAM_MASK (~(1<<2))
|
||||
#define AW8624_BIT_EN_BRAKE_RAM_ENABLE (1<<2)
|
||||
#define AW8624_BIT_EN_BRAKE_RAM_DISABLE (0<<2)
|
||||
#define AW8624_BIT_EN_BRAKE_RTP_MASK (~(1<<1))
|
||||
#define AW8624_BIT_EN_BRAKE_RTP_ENABLE (1<<1)
|
||||
#define AW8624_BIT_EN_BRAKE_RTP_DISABLE (0<<1)
|
||||
#define AW8624_BIT_EN_BRAKE_TRIG_MASK (~(1<<0))
|
||||
#define AW8624_BIT_EN_BRAKE_TRIG_ENABLE (1<<0)
|
||||
#define AW8624_BIT_EN_BRAKE_TRIG_DISABLE (0<<0)
|
||||
|
||||
/* PRLVL */
|
||||
#define AW8624_BIT_PRLVL_PR_EN_MASK (~(1<<7))
|
||||
#define AW8624_BIT_PRLVL_PR_ENABLE (1<<7)
|
||||
#define AW8624_BIT_PRLVL_PR_DISABLE (0<<7)
|
||||
#define AW8624_BIT_PRLVL_PRLVL_MASK (~(0x7f<<0))
|
||||
|
||||
/* PRTIME */
|
||||
#define AW8624_BIT_PRTIME_PRTIME_MASK (~(0xff<<0))
|
||||
|
||||
#define AW8624_BIT_BEMF_NUM_BRK_MASK (~(0xf<<0))
|
||||
|
||||
/* TD_H 0x4b TD_brake */
|
||||
#define AW8624_BIT_TDH_TD_BRAKE_MASK (~(0xF<<4))
|
||||
#define AW8624_BIT_R_SPARE_MASK (~(1<<7))
|
||||
#define AW8624_BIT_R_SPARE_ENABLE (1<<7)
|
||||
/* PWMDBG */
|
||||
#define AW8624_BIT_D2SCFG_DS_GAIN_MASK (~(7<<0))
|
||||
#define AW8624_BIT_D2SCFG_DS_GAIN_40 (7<<0)
|
||||
#endif
|
||||
|
||||
748
drivers/input/misc/aw8622x_haptic/aw_haptic.c
Normal file
748
drivers/input/misc/aw8622x_haptic/aw_haptic.c
Normal file
@@ -0,0 +1,748 @@
|
||||
#include <linux/module.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/i2c.h>
|
||||
#include <linux/of_gpio.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/device.h>
|
||||
#include <linux/firmware.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/version.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/debugfs.h>
|
||||
#include <linux/miscdevice.h>
|
||||
#include <linux/uaccess.h>
|
||||
#include <linux/syscalls.h>
|
||||
#include <linux/power_supply.h>
|
||||
#include <linux/pm_qos.h>
|
||||
#include <linux/pm_wakeup.h>
|
||||
#include <linux/pm_wakeirq.h>
|
||||
#include <linux/jiffies.h>
|
||||
#include <linux/vmalloc.h>
|
||||
#include "haptic.h"
|
||||
#include "aw8624.h"
|
||||
#include "aw8622x.h"
|
||||
|
||||
/******************************************************
|
||||
*
|
||||
* Marco
|
||||
*
|
||||
******************************************************/
|
||||
#define AWINIC_DRIVER_VERSION ("v0.1.0.1")
|
||||
#define AWINIC_I2C_NAME ("awinic_haptic")
|
||||
#define AWINIC_HAPTIC_NAME ("awinic_haptic")
|
||||
#define AW_READ_CHIPID_RETRIES (5)
|
||||
#define AW_I2C_RETRIES (2)
|
||||
#define AW8624_CHIP_ID (0x24)
|
||||
#define AW8622X_CHIP_ID (0x00)
|
||||
#define AW_REG_ID (0x00)
|
||||
#define AW8622X_REG_EFRD9 (0x64)
|
||||
|
||||
#ifdef ENABLE_PIN_CONTROL
|
||||
const char * const pctl_names[] = {
|
||||
"awinic_reset_reset",
|
||||
"awinic_reset_active",
|
||||
"awinic_interrupt_active",
|
||||
};
|
||||
#endif
|
||||
|
||||
static int awinic_i2c_read(struct awinic *awinic,
|
||||
unsigned char reg_addr, unsigned char *reg_data)
|
||||
{
|
||||
int ret = -1;
|
||||
unsigned char cnt = 0;
|
||||
|
||||
while (cnt < AW_I2C_RETRIES) {
|
||||
ret = i2c_smbus_read_byte_data(awinic->i2c, reg_addr);
|
||||
if (ret < 0) {
|
||||
aw_dev_err(awinic->dev, "%s: i2c_read cnt=%d error=%d\n",
|
||||
__func__, cnt, ret);
|
||||
} else {
|
||||
*reg_data = ret;
|
||||
break;
|
||||
}
|
||||
cnt++;
|
||||
usleep_range(2000, 3000);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int awinic_i2c_write(struct awinic *awinic,
|
||||
unsigned char reg_addr, unsigned char reg_data)
|
||||
{
|
||||
int ret = -1;
|
||||
unsigned char cnt = 0;
|
||||
|
||||
while (cnt < AW_I2C_RETRIES) {
|
||||
ret =
|
||||
i2c_smbus_write_byte_data(awinic->i2c, reg_addr, reg_data);
|
||||
if (ret < 0) {
|
||||
aw_dev_err(awinic->dev, "%s: i2c_write cnt=%d error=%d\n",
|
||||
__func__, cnt, ret);
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
cnt++;
|
||||
usleep_range(2000, 3000);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
#ifdef ENABLE_PIN_CONTROL
|
||||
static int select_pin_ctl(struct awinic *awinic, const char *name)
|
||||
{
|
||||
size_t i;
|
||||
int rc;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(awinic->pinctrl_state); i++) {
|
||||
const char *n = pctl_names[i];
|
||||
|
||||
if (!strncmp(n, name, strlen(n))) {
|
||||
rc = pinctrl_select_state(awinic->awinic_pinctrl,
|
||||
awinic->pinctrl_state[i]);
|
||||
if (rc)
|
||||
aw_dev_err(awinic->dev,
|
||||
"%s: cannot select '%s'\n", __func__, name);
|
||||
else
|
||||
aw_dev_err(awinic->dev,
|
||||
"%s: Selected '%s'\n", __func__, name);
|
||||
goto exit;
|
||||
}
|
||||
}
|
||||
|
||||
rc = -EINVAL;
|
||||
pr_info("%s: '%s' not found\n", __func__, name);
|
||||
|
||||
exit:
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int awinic_set_interrupt(struct awinic *awinic)
|
||||
{
|
||||
int rc = select_pin_ctl(awinic, "awinic_interrupt_active");
|
||||
return rc;
|
||||
}
|
||||
#endif
|
||||
|
||||
static int awinic_hw_reset(struct awinic *awinic)
|
||||
{
|
||||
#ifdef ENABLE_PIN_CONTROL
|
||||
int rc = 0;
|
||||
#endif
|
||||
aw_dev_info(awinic->dev, "%s enter\n", __func__);
|
||||
#ifdef ENABLE_PIN_CONTROL
|
||||
rc = select_pin_ctl(awinic, "awinic_reset_active");
|
||||
msleep(5);
|
||||
rc = select_pin_ctl(awinic, "awinic_reset_reset");
|
||||
msleep(5);
|
||||
rc = select_pin_ctl(awinic, "awinic_reset_active");
|
||||
#endif
|
||||
if (awinic && gpio_is_valid(awinic->reset_gpio)) {
|
||||
gpio_set_value_cansleep(awinic->reset_gpio, 0);
|
||||
usleep_range(1000, 2000);
|
||||
gpio_set_value_cansleep(awinic->reset_gpio, 1);
|
||||
usleep_range(3500, 4000);
|
||||
} else {
|
||||
aw_dev_err(awinic->dev, "%s: failed\n", __func__);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int awinic_haptic_softreset(struct awinic *awinic)
|
||||
{
|
||||
aw_dev_info(awinic->dev, "%s enter\n", __func__);
|
||||
awinic_i2c_write(awinic, AW_REG_ID, 0xAA);
|
||||
usleep_range(2000, 2500);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int awinic_read_chipid(struct awinic *awinic,
|
||||
unsigned char *reg, unsigned char type)
|
||||
{
|
||||
int ret = -1;
|
||||
unsigned char cnt = 0;
|
||||
|
||||
aw_dev_info(awinic->dev, "%s: awinic i2c addr = 0x%02x", __func__, awinic->i2c->addr);
|
||||
while (cnt < AW_I2C_RETRIES) {
|
||||
ret = i2c_smbus_read_byte_data(awinic->i2c, AW_REG_ID);
|
||||
if (ret < 0) {
|
||||
if (type == AW_FIRST_TRY) {
|
||||
aw_dev_info(awinic->dev,
|
||||
"%s: reading chip id\n", __func__);
|
||||
} else if (type == AW_LAST_TRY) {
|
||||
aw_dev_err(awinic->dev,
|
||||
"%s: i2c_read cnt=%d error=%d\n",
|
||||
__func__, cnt, ret);
|
||||
} else {
|
||||
aw_dev_err(awinic->dev,
|
||||
"%s: type is error\n", __func__);
|
||||
}
|
||||
} else {
|
||||
*reg = ret;
|
||||
break;
|
||||
}
|
||||
cnt++;
|
||||
usleep_range(2000, 3000);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int awinic_parse_chipid(struct awinic *awinic)
|
||||
{
|
||||
int ret = -1;
|
||||
unsigned char cnt = 0;
|
||||
unsigned char reg = 0;
|
||||
unsigned char ef_id = 0xff;
|
||||
|
||||
|
||||
while (cnt < AW_READ_CHIPID_RETRIES) {
|
||||
/* hardware reset */
|
||||
awinic_hw_reset(awinic);
|
||||
|
||||
ret = awinic_read_chipid(awinic, ®, AW_FIRST_TRY);
|
||||
if (ret < 0) {
|
||||
awinic->i2c->addr = (u16)awinic->aw8622x_i2c_addr;
|
||||
aw_dev_info(awinic->dev,
|
||||
"%s: try to replace i2c addr [(0x%02X)] to read chip id again\n",
|
||||
__func__, awinic->i2c->addr);
|
||||
ret = awinic_read_chipid(awinic, ®, AW_LAST_TRY);
|
||||
if (ret < 0)
|
||||
break;
|
||||
}
|
||||
|
||||
switch (reg) {
|
||||
case AW8624_CHIP_ID:
|
||||
aw_dev_info(awinic->dev,
|
||||
"%s aw8624 detected\n", __func__);
|
||||
awinic->name = AW8624;
|
||||
awinic_haptic_softreset(awinic);
|
||||
return 0;
|
||||
case AW8622X_CHIP_ID:
|
||||
/* Distinguish products by AW8622X_REG_EFRD9. */
|
||||
awinic_i2c_read(awinic, AW8622X_REG_EFRD9, &ef_id);
|
||||
if ((ef_id & 0x41) == AW86224_5_EF_ID) {
|
||||
awinic->name = AW86224_5;
|
||||
aw_dev_info(awinic->dev,
|
||||
"%s aw86224_5 detected\n", __func__);
|
||||
awinic_haptic_softreset(awinic);
|
||||
return 0;
|
||||
} else if ((ef_id & 0x41) == AW86223_EF_ID) {
|
||||
awinic->name = AW86223;
|
||||
aw_dev_info(awinic->dev,
|
||||
"%s aw86223 detected\n", __func__);
|
||||
awinic_haptic_softreset(awinic);
|
||||
return 0;
|
||||
} else {
|
||||
aw_dev_info(awinic->dev,
|
||||
"%s unsupported ef_id = (0x%02X)\n",
|
||||
__func__, ef_id);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
aw_dev_info(awinic->dev,
|
||||
"%s unsupported device revision (0x%x)\n",
|
||||
__func__, reg);
|
||||
break;
|
||||
}
|
||||
cnt++;
|
||||
|
||||
usleep_range(2000, 3000);
|
||||
}
|
||||
|
||||
return -EINVAL;
|
||||
}
|
||||
static int awinic_parse_dt(struct device *dev, struct awinic *awinic,
|
||||
struct device_node *np) {
|
||||
unsigned int val = 0;
|
||||
|
||||
awinic->reset_gpio = of_get_named_gpio(np, "reset-gpio", 0);
|
||||
if (awinic->reset_gpio >= 0) {
|
||||
aw_dev_err(awinic->dev,
|
||||
"%s: reset gpio provided ok\n", __func__);
|
||||
} else {
|
||||
awinic->reset_gpio = -1;
|
||||
aw_dev_err(awinic->dev,
|
||||
"%s: no reset gpio provided, will not HW reset device\n",
|
||||
__func__);
|
||||
return -1;
|
||||
}
|
||||
|
||||
awinic->irq_gpio = of_get_named_gpio(np, "irq-gpio", 0);
|
||||
if (awinic->irq_gpio < 0) {
|
||||
dev_err(dev, "%s: no irq gpio provided.\n", __func__);
|
||||
awinic->IsUsedIRQ = false;
|
||||
} else {
|
||||
aw_dev_err(awinic->dev,
|
||||
"%s: irq gpio provided ok.\n", __func__);
|
||||
awinic->IsUsedIRQ = true;
|
||||
}
|
||||
|
||||
val = of_property_read_u32(np,
|
||||
"aw8622x_i2c_addr", &awinic->aw8622x_i2c_addr);
|
||||
if (val)
|
||||
aw_dev_err(awinic->dev,
|
||||
"%s:configure aw8622x_i2c_addr error\n", __func__);
|
||||
else
|
||||
aw_dev_info(awinic->dev,
|
||||
"%s: configure aw8622x_i2c_addr ok\n", __func__);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
awinic_i2c_probe(struct i2c_client *i2c, const struct i2c_device_id *id)
|
||||
{
|
||||
struct awinic *awinic;
|
||||
struct input_dev *input_dev;
|
||||
struct device_node *np = i2c->dev.of_node;
|
||||
struct ff_device *ff;
|
||||
int rc = 0;
|
||||
int effect_count_max;
|
||||
int ret = -1;
|
||||
int irq_flags = 0;
|
||||
#ifdef ENABLE_PIN_CONTROL
|
||||
int i;
|
||||
#endif
|
||||
|
||||
aw_dev_err(&i2c->dev, "%s enter\n", __func__);
|
||||
if (!i2c_check_functionality(i2c->adapter, I2C_FUNC_I2C)) {
|
||||
aw_dev_err(&i2c->dev, "check_functionality failed\n");
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
awinic = devm_kzalloc(&i2c->dev, sizeof(struct awinic), GFP_KERNEL);
|
||||
if (awinic == NULL)
|
||||
return -ENOMEM;
|
||||
|
||||
input_dev = devm_input_allocate_device(&i2c->dev);
|
||||
if (!input_dev)
|
||||
return -ENOMEM;
|
||||
|
||||
awinic->dev = &i2c->dev;
|
||||
awinic->i2c = i2c;
|
||||
|
||||
i2c_set_clientdata(i2c, awinic);
|
||||
/* awinic rst & int */
|
||||
if (np) {
|
||||
ret = awinic_parse_dt(&i2c->dev, awinic, np);
|
||||
if (ret) {
|
||||
aw_dev_err(&i2c->dev,
|
||||
"%s: failed to parse device tree node\n",
|
||||
__func__);
|
||||
goto err_parse_dt;
|
||||
}
|
||||
}
|
||||
awinic->enable_pin_control = 0;
|
||||
#ifdef ENABLE_PIN_CONTROL
|
||||
awinic->awinic_pinctrl = devm_pinctrl_get(&i2c->dev);
|
||||
if (IS_ERR(awinic->awinic_pinctrl )) {
|
||||
if (PTR_ERR(awinic->awinic_pinctrl ) == -EPROBE_DEFER) {
|
||||
aw_dev_err(&i2c->dev, "pinctrl not ready\n");
|
||||
return -EPROBE_DEFER;
|
||||
}
|
||||
aw_dev_err(&i2c->dev, "Target does not use pinctrl\n");
|
||||
awinic->awinic_pinctrl = NULL;
|
||||
rc = -EINVAL;
|
||||
return rc;
|
||||
}
|
||||
for (i = 0; i < ARRAY_SIZE(awinic->pinctrl_state); i++) {
|
||||
const char *n = pctl_names[i];
|
||||
struct pinctrl_state *state = pinctrl_lookup_state(awinic->awinic_pinctrl, n);
|
||||
if (!IS_ERR(state)) {
|
||||
pr_info("%s: found pin control %s\n", __func__, n);
|
||||
awinic->pinctrl_state[i] = state;
|
||||
awinic->enable_pin_control = 1;
|
||||
awinic_set_interrupt(awinic);
|
||||
continue;
|
||||
}
|
||||
aw_dev_err(&i2c->dev, "cannot find '%s'\n", n);
|
||||
}
|
||||
#endif
|
||||
if (!awinic->enable_pin_control) {
|
||||
if (gpio_is_valid(awinic->reset_gpio)) {
|
||||
ret = devm_gpio_request_one(&i2c->dev, awinic->reset_gpio,
|
||||
GPIOF_OUT_INIT_LOW, "awinic_rst");
|
||||
if (ret) {
|
||||
aw_dev_err(&i2c->dev,
|
||||
"%s: rst request failed\n", __func__);
|
||||
goto err_reset_gpio_request;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (gpio_is_valid(awinic->irq_gpio)) {
|
||||
ret = devm_gpio_request_one(&i2c->dev, awinic->irq_gpio,
|
||||
GPIOF_DIR_IN, "awinic_int");
|
||||
if (ret) {
|
||||
aw_dev_err(&i2c->dev,
|
||||
"%s: int request failed\n", __func__);
|
||||
goto err_irq_gpio_request;
|
||||
}
|
||||
}
|
||||
/* parse chip id */
|
||||
ret = awinic_parse_chipid(awinic);
|
||||
if (ret < 0) {
|
||||
aw_dev_err(&i2c->dev, "%s: awinic parse chipid failed\n",
|
||||
__func__);
|
||||
goto err_id;
|
||||
}
|
||||
/* aw8624 */
|
||||
if (awinic->name == AW8624) {
|
||||
awinic->aw8624 = devm_kzalloc(&i2c->dev,
|
||||
sizeof(struct aw8624), GFP_KERNEL);
|
||||
if (awinic->aw8624 == NULL) {
|
||||
if (gpio_is_valid(awinic->irq_gpio))
|
||||
devm_gpio_free(&i2c->dev, awinic->irq_gpio);
|
||||
if (gpio_is_valid(awinic->reset_gpio))
|
||||
devm_gpio_free(&i2c->dev, awinic->reset_gpio);
|
||||
devm_kfree(&i2c->dev, awinic);
|
||||
awinic = NULL;
|
||||
return -ENOMEM;
|
||||
}
|
||||
awinic->aw8624->dev = awinic->dev;
|
||||
awinic->aw8624->i2c = awinic->i2c;
|
||||
awinic->aw8624->reset_gpio = awinic->reset_gpio;
|
||||
awinic->aw8624->irq_gpio = awinic->irq_gpio;
|
||||
|
||||
device_init_wakeup(awinic->aw8624->dev, true);
|
||||
|
||||
/* aw8624 rst & int */
|
||||
if (np) {
|
||||
ret = aw8624_parse_dt(&i2c->dev, awinic->aw8624, np);
|
||||
if (ret) {
|
||||
aw_dev_err(&i2c->dev,
|
||||
"%s: failed to parse device tree node\n",
|
||||
__func__);
|
||||
goto err_aw8624_parse_dt;
|
||||
}
|
||||
}
|
||||
|
||||
/* aw8624 irq */
|
||||
if (gpio_is_valid(awinic->aw8624->irq_gpio) &&
|
||||
!(awinic->aw8624->flags & AW8624_FLAG_SKIP_INTERRUPTS)) {
|
||||
/* register irq handler */
|
||||
aw8624_interrupt_setup(awinic->aw8624);
|
||||
irq_flags = IRQF_TRIGGER_FALLING | IRQF_ONESHOT;
|
||||
ret = devm_request_threaded_irq(&i2c->dev,
|
||||
gpio_to_irq(awinic->aw8624->irq_gpio),
|
||||
NULL, aw8624_irq, irq_flags,
|
||||
"aw8624", awinic->aw8624);
|
||||
awinic->aw8624->irq_sts_flag = 1;
|
||||
aw_dev_info(&i2c->dev, "%s: aw8624_irq success.\n", __func__);
|
||||
if (ret != 0) {
|
||||
dev_err(&i2c->dev, "%s: failed to request IRQ %d: %d\n",
|
||||
__func__, gpio_to_irq(awinic->aw8624->irq_gpio), ret);
|
||||
goto err_aw8624_irq;
|
||||
}
|
||||
} else {
|
||||
aw_dev_info(&i2c->dev, "%s skipping IRQ registration\n", __func__);
|
||||
/* disable feature support if gpio was invalid */
|
||||
awinic->aw8624->flags |= AW8624_FLAG_SKIP_INTERRUPTS;
|
||||
aw_dev_info(&i2c->dev, "%s: aw8624_irq failed.\n", __func__);
|
||||
}
|
||||
|
||||
aw8624_vibrator_init(awinic->aw8624);
|
||||
aw8624_haptic_init(awinic->aw8624);
|
||||
aw8624_ram_init(awinic->aw8624);
|
||||
|
||||
/* aw8624 input config */
|
||||
input_dev->name = "aw8624_haptic";
|
||||
input_set_drvdata(input_dev, awinic->aw8624);
|
||||
awinic->aw8624->input_dev = input_dev;
|
||||
input_set_capability(input_dev, EV_FF, FF_CONSTANT);
|
||||
input_set_capability(input_dev, EV_FF, FF_GAIN);
|
||||
if (awinic->aw8624->effects_count != 0) {
|
||||
input_set_capability(input_dev, EV_FF, FF_PERIODIC);
|
||||
input_set_capability(input_dev, EV_FF, FF_CUSTOM);
|
||||
}
|
||||
if (awinic->aw8624->effects_count + 1 > FF_EFFECT_COUNT_MAX)
|
||||
effect_count_max = awinic->aw8624->effects_count + 1;
|
||||
else
|
||||
effect_count_max = FF_EFFECT_COUNT_MAX;
|
||||
rc = input_ff_create(input_dev, effect_count_max);
|
||||
if (rc < 0) {
|
||||
dev_err(awinic->aw8624->dev, "create FF input device failed, rc=%d\n",
|
||||
rc);
|
||||
return rc;
|
||||
}
|
||||
awinic->aw8624->work_queue = create_singlethread_workqueue("aw8624_vibrator_work_queue");
|
||||
if (!awinic->aw8624->work_queue) {
|
||||
dev_err(&i2c->dev,
|
||||
"%s: Error creating aw8624_vibrator_work_queue\n",
|
||||
__func__);
|
||||
goto err_aw8624_sysfs;
|
||||
}
|
||||
INIT_WORK(&awinic->aw8624->set_gain_work, aw8624_haptics_set_gain_work_routine);
|
||||
ff = input_dev->ff;
|
||||
ff->upload = aw8624_haptics_upload_effect;
|
||||
ff->playback = aw8624_haptics_playback;
|
||||
ff->erase = aw8624_haptics_erase;
|
||||
ff->set_gain = aw8624_haptics_set_gain;
|
||||
rc = input_register_device(input_dev);
|
||||
if (rc < 0) {
|
||||
dev_err(awinic->aw8624->dev, "register input device failed, rc=%d\n",
|
||||
rc);
|
||||
goto aw8624_destroy_ff;
|
||||
}
|
||||
|
||||
|
||||
} else if (awinic->name == AW86223 || awinic->name == AW86224_5) {
|
||||
awinic->aw8622x = devm_kzalloc(&i2c->dev, sizeof(struct aw8622x),
|
||||
GFP_KERNEL);
|
||||
if (awinic->aw8622x == NULL) {
|
||||
if (gpio_is_valid(awinic->irq_gpio))
|
||||
devm_gpio_free(&i2c->dev, awinic->irq_gpio);
|
||||
if (gpio_is_valid(awinic->reset_gpio))
|
||||
devm_gpio_free(&i2c->dev, awinic->reset_gpio);
|
||||
devm_kfree(&i2c->dev, awinic);
|
||||
awinic = NULL;
|
||||
return -ENOMEM;
|
||||
}
|
||||
awinic->aw8622x->dev = awinic->dev;
|
||||
awinic->aw8622x->i2c = awinic->i2c;
|
||||
awinic->aw8622x->reset_gpio = awinic->reset_gpio;
|
||||
awinic->aw8622x->irq_gpio = awinic->irq_gpio;
|
||||
awinic->aw8622x->isUsedIntn = awinic->IsUsedIRQ;
|
||||
|
||||
awinic->aw8622x->level = 0x80;
|
||||
|
||||
/* chip qualify */
|
||||
if (!aw8622x_check_qualify(awinic->aw8622x)) {
|
||||
aw_dev_err(&i2c->dev,
|
||||
"%s:unqualified chip!\n", __func__);
|
||||
goto err_aw8622x_check_qualify;
|
||||
}
|
||||
if (np) {
|
||||
ret = aw8622x_parse_dt(&i2c->dev, awinic->aw8622x, np);
|
||||
if (ret) {
|
||||
aw_dev_err(&i2c->dev,
|
||||
"%s: failed to parse device tree node\n",
|
||||
__func__);
|
||||
goto err_aw8622x_parse_dt;
|
||||
}
|
||||
}
|
||||
|
||||
/* aw8622x irq */
|
||||
if (gpio_is_valid(awinic->aw8622x->irq_gpio) &&
|
||||
!(awinic->aw8622x->flags & AW8622X_FLAG_SKIP_INTERRUPTS)) {
|
||||
/* register irq handler */
|
||||
aw8622x_interrupt_setup(awinic->aw8622x);
|
||||
irq_flags = IRQF_TRIGGER_FALLING | IRQF_ONESHOT;
|
||||
ret = devm_request_threaded_irq(&i2c->dev,
|
||||
gpio_to_irq(awinic->aw8622x->irq_gpio),
|
||||
NULL, aw8622x_irq, irq_flags,
|
||||
"aw8622x", awinic->aw8622x);
|
||||
if (ret != 0) {
|
||||
aw_dev_err(&i2c->dev,
|
||||
"%s: failed to request IRQ %d: %d\n",
|
||||
__func__,
|
||||
gpio_to_irq(awinic->aw8622x->irq_gpio),
|
||||
ret);
|
||||
goto err_aw8622x_irq;
|
||||
}
|
||||
} else {
|
||||
aw_dev_err(&i2c->dev,
|
||||
"%s skipping IRQ registration\n", __func__);
|
||||
/* disable feature support if gpio was invalid */
|
||||
awinic->aw8622x->flags |= AW8622X_FLAG_SKIP_INTERRUPTS;
|
||||
}
|
||||
|
||||
aw8622x_vibrator_init(awinic->aw8622x);
|
||||
aw8622x_haptic_init(awinic->aw8622x);
|
||||
aw8622x_ram_work_init(awinic->aw8622x);
|
||||
|
||||
/* aw8622x input config */
|
||||
input_dev->name = "awinic_haptic";
|
||||
input_set_drvdata(input_dev, awinic->aw8622x);
|
||||
awinic->aw8622x->input_dev = input_dev;
|
||||
input_set_capability(input_dev, EV_FF, FF_CONSTANT);
|
||||
input_set_capability(input_dev, EV_FF, FF_GAIN);
|
||||
if (awinic->aw8622x->effects_count != 0) {
|
||||
input_set_capability(input_dev, EV_FF, FF_PERIODIC);
|
||||
input_set_capability(input_dev, EV_FF, FF_CUSTOM);
|
||||
}
|
||||
|
||||
if (awinic->aw8622x->effects_count + 1 > FF_EFFECT_COUNT_MAX)
|
||||
effect_count_max = awinic->aw8622x->effects_count + 1;
|
||||
else
|
||||
effect_count_max = FF_EFFECT_COUNT_MAX;
|
||||
rc = input_ff_create(input_dev, effect_count_max);
|
||||
if (rc < 0) {
|
||||
dev_err(awinic->aw8622x->dev, "create FF input device failed, rc=%d\n",
|
||||
rc);
|
||||
return rc;
|
||||
}
|
||||
awinic->aw8622x->work_queue = create_singlethread_workqueue("aw8622x_vibrator_work_queue");
|
||||
if (!awinic->aw8622x->work_queue) {
|
||||
dev_err(&i2c->dev,
|
||||
"%s: Error creating aw8622x_vibrator_work_queue\n",
|
||||
__func__);
|
||||
goto err_aw8622x_sysfs;
|
||||
}
|
||||
INIT_WORK(&awinic->aw8622x->set_gain_work,
|
||||
aw8622x_haptics_set_gain_work_routine);
|
||||
ff = input_dev->ff;
|
||||
ff->upload = aw8622x_haptics_upload_effect;
|
||||
ff->playback = aw8622x_haptics_playback;
|
||||
ff->erase = aw8622x_haptics_erase;
|
||||
ff->set_gain = aw8622x_haptics_set_gain;
|
||||
rc = input_register_device(input_dev);
|
||||
if (rc < 0) {
|
||||
aw_dev_err(awinic->aw8622x->dev, "register input device failed, rc=%d\n",
|
||||
rc);
|
||||
goto aw8622x_destroy_ff;
|
||||
}
|
||||
} else{
|
||||
goto err_parse_dt;
|
||||
}
|
||||
|
||||
dev_set_drvdata(&i2c->dev, awinic);
|
||||
aw_dev_err(&i2c->dev, "%s probe completed successfully!\n", __func__);
|
||||
return 0;
|
||||
|
||||
|
||||
err_aw8622x_sysfs:
|
||||
if (awinic->name == AW86223 || awinic->name == AW86224_5)
|
||||
devm_free_irq(&i2c->dev, gpio_to_irq(awinic->aw8622x->irq_gpio),
|
||||
awinic->aw8622x);
|
||||
aw8622x_destroy_ff:
|
||||
if (awinic->name == AW86223 || awinic->name == AW86224_5)
|
||||
input_ff_destroy(awinic->aw8622x->input_dev);
|
||||
err_aw8622x_irq:
|
||||
err_aw8622x_parse_dt:
|
||||
err_aw8622x_check_qualify:
|
||||
if (awinic->name == AW86223 || awinic->name == AW86224_5) {
|
||||
devm_kfree(&i2c->dev, awinic->aw8622x);
|
||||
awinic->aw8622x = NULL;
|
||||
}
|
||||
|
||||
err_aw8624_sysfs:
|
||||
if (awinic->name == AW8624)
|
||||
devm_free_irq(&i2c->dev, gpio_to_irq(awinic->aw8624->irq_gpio),
|
||||
awinic->aw8624);
|
||||
aw8624_destroy_ff:
|
||||
if (awinic->name == AW8624)
|
||||
input_ff_destroy(awinic->aw8624->input_dev);
|
||||
err_aw8624_irq:
|
||||
err_aw8624_parse_dt:
|
||||
if (awinic->name == AW8624) {
|
||||
device_init_wakeup(awinic->aw8624->dev, false);
|
||||
devm_kfree(&i2c->dev, awinic->aw8624);
|
||||
awinic->aw8624 = NULL;
|
||||
}
|
||||
|
||||
err_id:
|
||||
if (gpio_is_valid(awinic->irq_gpio))
|
||||
devm_gpio_free(&i2c->dev, awinic->irq_gpio);
|
||||
err_irq_gpio_request:
|
||||
if (gpio_is_valid(awinic->reset_gpio))
|
||||
devm_gpio_free(&i2c->dev, awinic->reset_gpio);
|
||||
err_reset_gpio_request:
|
||||
err_parse_dt:
|
||||
devm_kfree(&i2c->dev, awinic);
|
||||
awinic = NULL;
|
||||
return ret;
|
||||
|
||||
}
|
||||
|
||||
static int awinic_i2c_remove(struct i2c_client *i2c)
|
||||
{
|
||||
struct awinic *awinic = i2c_get_clientdata(i2c);
|
||||
|
||||
aw_dev_info(&i2c->dev, "%s enter \n", __func__);
|
||||
|
||||
if (awinic->name == AW8624) {
|
||||
aw_dev_err(&i2c->dev, "%s remove aw8624\n", __func__);
|
||||
sysfs_remove_group(&i2c->dev.kobj, &aw8624_vibrator_attribute_group);
|
||||
|
||||
devm_free_irq(&i2c->dev, gpio_to_irq(awinic->aw8624->irq_gpio),
|
||||
awinic->aw8624);
|
||||
if (gpio_is_valid(awinic->aw8624->irq_gpio))
|
||||
devm_gpio_free(&i2c->dev, awinic->aw8624->irq_gpio);
|
||||
if (gpio_is_valid(awinic->aw8624->reset_gpio))
|
||||
devm_gpio_free(&i2c->dev, awinic->aw8624->reset_gpio);
|
||||
if (awinic->aw8624 != NULL) {
|
||||
flush_workqueue(awinic->aw8624->work_queue);
|
||||
destroy_workqueue(awinic->aw8624->work_queue);
|
||||
}
|
||||
device_init_wakeup(awinic->aw8624->dev, false);
|
||||
devm_kfree(&i2c->dev, awinic->aw8624);
|
||||
awinic->aw8624 = NULL;
|
||||
} else if (awinic->name == AW86223 || awinic->name == AW86224_5) {
|
||||
aw_dev_err(&i2c->dev, "%s remove aw8622x\n", __func__);
|
||||
cancel_delayed_work_sync(&awinic->aw8622x->ram_work);
|
||||
cancel_work_sync(&awinic->aw8622x->haptic_audio.work);
|
||||
hrtimer_cancel(&awinic->aw8622x->haptic_audio.timer);
|
||||
if (awinic->aw8622x->isUsedIntn)
|
||||
cancel_work_sync(&awinic->aw8622x->rtp_work);
|
||||
cancel_work_sync(&awinic->aw8622x->long_vibrate_work);
|
||||
|
||||
hrtimer_cancel(&awinic->aw8622x->timer);
|
||||
mutex_destroy(&awinic->aw8622x->lock);
|
||||
mutex_destroy(&awinic->aw8622x->rtp_lock);
|
||||
mutex_destroy(&awinic->aw8622x->haptic_audio.lock);
|
||||
sysfs_remove_group(&awinic->aw8622x->i2c->dev.kobj,
|
||||
&aw8622x_vibrator_attribute_group);
|
||||
devm_free_irq(&i2c->dev, gpio_to_irq(awinic->aw8622x->irq_gpio),
|
||||
awinic->aw8622x);
|
||||
#ifdef TIMED_OUTPUT
|
||||
timed_output_dev_unregister(&awinic->aw8622x->vib_dev);
|
||||
#endif
|
||||
devm_kfree(&i2c->dev, awinic->aw8622x);
|
||||
awinic->aw8622x = NULL;
|
||||
} else {
|
||||
aw_dev_err(&i2c->dev, "%s no chip\n", __func__);
|
||||
return -ERANGE;
|
||||
}
|
||||
|
||||
aw_dev_info(&i2c->dev, "%s exit\n", __func__);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct i2c_device_id awinic_i2c_id[] = {
|
||||
{ AWINIC_I2C_NAME, 0 },
|
||||
{ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(i2c, awinic_i2c_id);
|
||||
|
||||
static const struct of_device_id awinic_dt_match[] = {
|
||||
{ .compatible = "awinic,awinic_haptic" },
|
||||
{ },
|
||||
};
|
||||
|
||||
static struct i2c_driver awinic_i2c_driver = {
|
||||
.driver = {
|
||||
.name = AWINIC_I2C_NAME,
|
||||
.owner = THIS_MODULE,
|
||||
.of_match_table = of_match_ptr(awinic_dt_match),
|
||||
},
|
||||
.probe = awinic_i2c_probe,
|
||||
.remove = awinic_i2c_remove,
|
||||
.id_table = awinic_i2c_id,
|
||||
};
|
||||
|
||||
static int __init awinic_i2c_init(void)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
pr_info("awinic driver version %s\n", AWINIC_DRIVER_VERSION);
|
||||
|
||||
ret = i2c_add_driver(&awinic_i2c_driver);
|
||||
if (ret) {
|
||||
pr_err("fail to add awinic device into i2c\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
late_initcall(awinic_i2c_init);
|
||||
|
||||
static void __exit awinic_i2c_exit(void)
|
||||
{
|
||||
i2c_del_driver(&awinic_i2c_driver);
|
||||
}
|
||||
module_exit(awinic_i2c_exit);
|
||||
|
||||
MODULE_DESCRIPTION("awinic Haptic Driver");
|
||||
MODULE_LICENSE("GPL v2");
|
||||
202
drivers/input/misc/aw8622x_haptic/haptic.h
Normal file
202
drivers/input/misc/aw8622x_haptic/haptic.h
Normal file
@@ -0,0 +1,202 @@
|
||||
#ifndef _AW_HAPTIC_H_
|
||||
#define _AW_HAPTIC_H_
|
||||
#include <linux/regmap.h>
|
||||
#include <linux/timer.h>
|
||||
#include <linux/workqueue.h>
|
||||
#include <linux/hrtimer.h>
|
||||
#include <linux/mutex.h>
|
||||
#include <linux/cdev.h>
|
||||
#include <linux/device.h>
|
||||
#include <linux/syscalls.h>
|
||||
#include <linux/input.h>
|
||||
|
||||
/********************************************
|
||||
* print information control
|
||||
*******************************************/
|
||||
#define aw_dev_err(dev, format, ...) \
|
||||
pr_err("[%s]" format, dev_name(dev), ##__VA_ARGS__)
|
||||
|
||||
#define aw_dev_info(dev, format, ...) \
|
||||
pr_info("[%s]" format, dev_name(dev), ##__VA_ARGS__)
|
||||
|
||||
#define aw_dev_dbg(dev, format, ...) \
|
||||
pr_debug("[%s]" format, dev_name(dev), ##__VA_ARGS__)
|
||||
|
||||
/*********************************************************
|
||||
*
|
||||
* normal macro
|
||||
*
|
||||
********************************************************/
|
||||
#define AWINIC_DEV_NAME ("awinic_vibrator")
|
||||
#define FF_EFFECT_COUNT_MAX 32
|
||||
#define HAP_BRAKE_PATTERN_MAX 4
|
||||
#define HAP_WAVEFORM_BUFFER_MAX 8
|
||||
#define HAP_PLAY_RATE_US_DEFAULT 5715
|
||||
#define HAP_PLAY_RATE_US_MAX 20475
|
||||
#define FF_EFFECT_COUNT_MAX 32
|
||||
|
||||
|
||||
/*********************************************************
|
||||
*
|
||||
* macro control
|
||||
*
|
||||
********************************************************/
|
||||
|
||||
#define ENABLE_PIN_CONTROL
|
||||
#define INPUT_DEV
|
||||
#define AW_CHECK_RAM_DATA
|
||||
#define AW_READ_BIN_FLEXBALLY
|
||||
#define AW_OSC_COARSE_CALI
|
||||
|
||||
/*********************************************************
|
||||
*
|
||||
* enum
|
||||
*
|
||||
********************************************************/
|
||||
|
||||
enum awinic_chip_name {
|
||||
AW86223 = 0,
|
||||
AW86224_5 = 1,
|
||||
AW8624 = 2,
|
||||
};
|
||||
|
||||
enum haptics_custom_effect_param {
|
||||
CUSTOM_DATA_EFFECT_IDX,
|
||||
CUSTOM_DATA_TIMEOUT_SEC_IDX,
|
||||
CUSTOM_DATA_TIMEOUT_MSEC_IDX,
|
||||
CUSTOM_DATA_LEN,
|
||||
};
|
||||
|
||||
enum haptic_nv_read_chip_type {
|
||||
AW_FIRST_TRY = 0,
|
||||
AW_LAST_TRY = 1,
|
||||
};
|
||||
|
||||
#ifdef INPUT_DEV
|
||||
enum actutor_type {
|
||||
ACT_LRA,
|
||||
ACT_ERM,
|
||||
};
|
||||
|
||||
enum lra_res_sig_shape {
|
||||
RES_SIG_SINE,
|
||||
RES_SIG_SQUARE,
|
||||
};
|
||||
|
||||
enum lra_auto_res_mode {
|
||||
AUTO_RES_MODE_ZXD,
|
||||
AUTO_RES_MODE_QWD,
|
||||
};
|
||||
|
||||
enum wf_src {
|
||||
INT_WF_VMAX,
|
||||
INT_WF_BUFFER,
|
||||
EXT_WF_AUDIO,
|
||||
EXT_WF_PWM,
|
||||
};
|
||||
#endif
|
||||
|
||||
/*********************************************************
|
||||
*
|
||||
* struct
|
||||
*
|
||||
********************************************************/
|
||||
|
||||
#ifdef INPUT_DEV
|
||||
struct qti_hap_effect {
|
||||
int id;
|
||||
u8 *pattern;
|
||||
int pattern_length;
|
||||
u16 play_rate_us;
|
||||
u16 vmax_mv;
|
||||
u8 wf_repeat_n;
|
||||
u8 wf_s_repeat_n;
|
||||
u8 brake[HAP_BRAKE_PATTERN_MAX];
|
||||
int brake_pattern_length;
|
||||
bool brake_en;
|
||||
bool lra_auto_res_disable;
|
||||
};
|
||||
|
||||
struct qti_hap_play_info {
|
||||
struct qti_hap_effect *effect;
|
||||
u16 vmax_mv;
|
||||
int length_us;
|
||||
int playing_pos;
|
||||
bool playing_pattern;
|
||||
};
|
||||
|
||||
struct qti_hap_config {
|
||||
enum actutor_type act_type;
|
||||
enum lra_res_sig_shape lra_shape;
|
||||
enum lra_auto_res_mode lra_auto_res_mode;
|
||||
enum wf_src ext_src;
|
||||
u16 vmax_mv;
|
||||
u16 play_rate_us;
|
||||
bool lra_allow_variable_play_rate;
|
||||
bool use_ext_wf_src;
|
||||
};
|
||||
#endif
|
||||
|
||||
struct fileops {
|
||||
unsigned char cmd;
|
||||
unsigned char reg;
|
||||
unsigned char ram_addrh;
|
||||
unsigned char ram_addrl;
|
||||
};
|
||||
|
||||
/*awinic*/
|
||||
struct awinic {
|
||||
struct i2c_client *i2c;
|
||||
struct device *dev;
|
||||
unsigned char name;
|
||||
bool IsUsedIRQ;
|
||||
|
||||
unsigned int aw8622x_i2c_addr;
|
||||
int reset_gpio;
|
||||
int irq_gpio;
|
||||
int reset_gpio_ret;
|
||||
int irq_gpio_ret;
|
||||
int enable_pin_control;
|
||||
|
||||
struct aw8624 *aw8624;
|
||||
struct aw8622x *aw8622x;
|
||||
#ifdef ENABLE_PIN_CONTROL
|
||||
struct pinctrl *awinic_pinctrl;
|
||||
struct pinctrl_state *pinctrl_state[3];
|
||||
#endif
|
||||
};
|
||||
|
||||
|
||||
struct ram {
|
||||
unsigned int len;
|
||||
unsigned int check_sum;
|
||||
unsigned int base_addr;
|
||||
unsigned char version;
|
||||
unsigned char ram_shift;
|
||||
unsigned char baseaddr_shift;
|
||||
};
|
||||
|
||||
struct haptic_ctr {
|
||||
unsigned char cnt;
|
||||
unsigned char cmd;
|
||||
unsigned char play;
|
||||
unsigned char wavseq;
|
||||
unsigned char loop;
|
||||
unsigned char gain;
|
||||
struct list_head list;
|
||||
};
|
||||
|
||||
struct haptic_audio {
|
||||
struct mutex lock;
|
||||
struct hrtimer timer;
|
||||
struct work_struct work;
|
||||
int delay_val;
|
||||
int timer_val;
|
||||
unsigned char cnt;
|
||||
struct haptic_ctr data[256];
|
||||
struct haptic_ctr ctr;
|
||||
struct list_head ctr_list;
|
||||
unsigned char ori_gain;
|
||||
};
|
||||
|
||||
#endif
|
||||
13
drivers/input/misc/aw8624_haptic/Kconfig
Normal file
13
drivers/input/misc/aw8624_haptic/Kconfig
Normal file
@@ -0,0 +1,13 @@
|
||||
config INPUT_AW8624_HAPTIC
|
||||
tristate "Awinic AW8624 haptic driver"
|
||||
depends on I2C
|
||||
help
|
||||
Say Y here if you have Awinic AW8624 haptic controller
|
||||
chip in your system.
|
||||
|
||||
If unsure, say N.
|
||||
|
||||
To compile this driver as a module, choose M here.
|
||||
|
||||
|
||||
|
||||
2
drivers/input/misc/aw8624_haptic/Makefile
Normal file
2
drivers/input/misc/aw8624_haptic/Makefile
Normal file
@@ -0,0 +1,2 @@
|
||||
obj-$(CONFIG_INPUT_AW8624_HAPTIC) += aw8624.o
|
||||
|
||||
4630
drivers/input/misc/aw8624_haptic/aw8624.c
Normal file
4630
drivers/input/misc/aw8624_haptic/aw8624.c
Normal file
File diff suppressed because it is too large
Load Diff
458
drivers/input/misc/aw8624_haptic/aw8624.h
Normal file
458
drivers/input/misc/aw8624_haptic/aw8624.h
Normal file
@@ -0,0 +1,458 @@
|
||||
#ifndef _AW8624_H_
|
||||
#define _AW8624_H_
|
||||
|
||||
/*********************************************************
|
||||
*
|
||||
* kernel version
|
||||
*
|
||||
********************************************************/
|
||||
#define INPUT_DEV
|
||||
//#define TEST_RTP
|
||||
#define TEST_CONT_TO_RAM
|
||||
/*********************************************************
|
||||
*
|
||||
* aw8624.h
|
||||
*
|
||||
********************************************************/
|
||||
#include <linux/regmap.h>
|
||||
#include <linux/timer.h>
|
||||
#include <linux/workqueue.h>
|
||||
#include <linux/hrtimer.h>
|
||||
#include <linux/mutex.h>
|
||||
#include <linux/cdev.h>
|
||||
#include <linux/leds.h>
|
||||
#include <linux/atomic.h>
|
||||
#include <linux/timekeeping.h>
|
||||
|
||||
|
||||
/*********************************************************
|
||||
*
|
||||
* marco
|
||||
*
|
||||
********************************************************/
|
||||
#define MAX_I2C_BUFFER_SIZE 65536
|
||||
|
||||
#define AW8624_SEQUENCER_SIZE 8
|
||||
#define AW8624_SEQUENCER_LOOP_SIZE 4
|
||||
|
||||
#define AW8624_RTP_I2C_SINGLE_MAX_NUM 512
|
||||
|
||||
#define HAPTIC_MAX_TIMEOUT 10000
|
||||
|
||||
#define AW8624_VBAT_REFER 4400
|
||||
#define AW8624_VBAT_MIN 3500
|
||||
#define AW8624_VBAT_MAX 4500
|
||||
#define ENABLE_PIN_CONTROL
|
||||
|
||||
#define HAP_BRAKE_PATTERN_MAX 4
|
||||
#define HAP_WAVEFORM_BUFFER_MAX 8
|
||||
#define HAP_PLAY_RATE_US_DEFAULT 5715
|
||||
#define HAP_PLAY_RATE_US_MAX 20475
|
||||
#define FF_EFFECT_COUNT_MAX 32
|
||||
|
||||
#define AW8624_CONT_PLAYBACK_MODE AW8624_BIT_CONT_CTRL_CLOSE_PLAYBACK
|
||||
static int wf_repeat[8] = { 1, 2, 4, 8, 16, 32, 64, 128 };
|
||||
static int wf_s_repeat[4] = { 1, 2, 4, 8 };
|
||||
|
||||
|
||||
/*
|
||||
* trig default high level
|
||||
* ___________ _________________
|
||||
* | |
|
||||
* | |
|
||||
* |___________|
|
||||
* first edge
|
||||
* second edge
|
||||
*
|
||||
*
|
||||
* trig default low level
|
||||
* ___________
|
||||
* | |
|
||||
* | |
|
||||
* __________| |_________________
|
||||
* first edge
|
||||
* second edge
|
||||
*/
|
||||
/* trig config */
|
||||
/*dts config
|
||||
* default_level -> 1: high level; 0: low level
|
||||
* dual_edge -> 1: dual edge; 0: first edge
|
||||
*vib_trig_config = <
|
||||
* 1 1 1 1 2
|
||||
* enable default_level dual_edge first_seq second_seq
|
||||
* 1 1 2 1 2
|
||||
* enable default_level dual_edge first_seq second_seq
|
||||
* 1 1 3 1 2
|
||||
* enable default_level dual_edge first_seq second_seq
|
||||
*/
|
||||
#define AW8624_TRIG_NUM 3
|
||||
|
||||
|
||||
enum aw8624_flags {
|
||||
AW8624_FLAG_NONR = 0,
|
||||
AW8624_FLAG_SKIP_INTERRUPTS = 1,
|
||||
};
|
||||
|
||||
enum aw8624_chipids {
|
||||
AW8624_ID = 1,
|
||||
};
|
||||
|
||||
enum aw8624_haptic_read_write {
|
||||
AW8624_HAPTIC_CMD_READ_REG = 0,
|
||||
AW8624_HAPTIC_CMD_WRITE_REG = 1,
|
||||
};
|
||||
|
||||
enum aw8624_haptic_work_mode {
|
||||
AW8624_HAPTIC_STANDBY_MODE = 0,
|
||||
AW8624_HAPTIC_RAM_MODE = 1,
|
||||
AW8624_HAPTIC_RTP_MODE = 2,
|
||||
AW8624_HAPTIC_TRIG_MODE = 3,
|
||||
AW8624_HAPTIC_CONT_MODE = 4,
|
||||
AW8624_HAPTIC_RAM_LOOP_MODE = 5,
|
||||
};
|
||||
|
||||
enum aw8624_haptic_activate_mode {
|
||||
AW8624_HAPTIC_ACTIVATE_RAM_MODE = 0,
|
||||
AW8624_HAPTIC_ACTIVATE_CONT_MODE = 1,
|
||||
AW8624_HAPTIC_ACTIVATE_RTP_MODE = 2,
|
||||
AW8624_HAPTIC_ACTIVATE_RAM_LOOP_MODE = 3,
|
||||
};
|
||||
|
||||
enum aw8624_haptic_cont_vbat_comp_mode {
|
||||
AW8624_HAPTIC_CONT_VBAT_SW_COMP_MODE = 0,
|
||||
AW8624_HAPTIC_CONT_VBAT_HW_COMP_MODE = 1,
|
||||
};
|
||||
|
||||
enum aw8624_haptic_ram_vbat_comp_mode {
|
||||
AW8624_HAPTIC_RAM_VBAT_COMP_DISABLE = 0,
|
||||
AW8624_HAPTIC_RAM_VBAT_COMP_ENABLE = 1,
|
||||
};
|
||||
|
||||
enum aw8624_haptic_f0_flag {
|
||||
AW8624_HAPTIC_LRA_F0 = 0,
|
||||
AW8624_HAPTIC_CALI_F0 = 1,
|
||||
};
|
||||
|
||||
enum aw8624_haptic_pwm_mode {
|
||||
AW8624_PWM_48K = 0,
|
||||
AW8624_PWM_24K = 1,
|
||||
AW8624_PWM_12K = 2,
|
||||
};
|
||||
|
||||
enum aw8624_haptic_play {
|
||||
AW8624_HAPTIC_PLAY_NULL = 0,
|
||||
AW8624_HAPTIC_PLAY_ENABLE = 1,
|
||||
AW8624_HAPTIC_PLAY_STOP = 2,
|
||||
AW8624_HAPTIC_PLAY_GAIN = 8,
|
||||
};
|
||||
|
||||
enum aw8624_haptic_cmd {
|
||||
AW8624_HAPTIC_CMD_NULL = 0,
|
||||
AW8624_HAPTIC_CMD_ENABLE = 1,
|
||||
AW8624_HAPTIC_CMD_STOP = 255,
|
||||
};
|
||||
|
||||
enum haptics_custom_effect_param {
|
||||
CUSTOM_DATA_EFFECT_IDX,
|
||||
CUSTOM_DATA_TIMEOUT_SEC_IDX,
|
||||
CUSTOM_DATA_TIMEOUT_MSEC_IDX,
|
||||
CUSTOM_DATA_LEN,
|
||||
};
|
||||
enum aw8624_haptic_strength {
|
||||
AW8624_LIGHT_MAGNITUDE = 0x3fff,
|
||||
AW8624_MEDIUM_MAGNITUDE = 0x5fff,
|
||||
AW8624_STRONG_MAGNITUDE = 0x7fff,
|
||||
};
|
||||
/*********************************************************
|
||||
*
|
||||
* struct
|
||||
*
|
||||
********************************************************/
|
||||
struct fileops {
|
||||
unsigned char cmd;
|
||||
unsigned char reg;
|
||||
unsigned char ram_addrh;
|
||||
unsigned char ram_addrl;
|
||||
};
|
||||
|
||||
struct ram {
|
||||
unsigned int len;
|
||||
unsigned int check_sum;
|
||||
unsigned int base_addr;
|
||||
unsigned char version;
|
||||
unsigned char ram_shift;
|
||||
unsigned char baseaddr_shift;
|
||||
};
|
||||
|
||||
struct haptic_ctr {
|
||||
unsigned char cmd;
|
||||
unsigned char play;
|
||||
unsigned char wavseq;
|
||||
unsigned char loop;
|
||||
unsigned char gain;
|
||||
};
|
||||
|
||||
struct haptic_audio {
|
||||
struct mutex lock;
|
||||
struct hrtimer timer;
|
||||
struct work_struct work;
|
||||
int delay_val;
|
||||
int timer_val;
|
||||
unsigned char cnt;
|
||||
struct haptic_ctr data[256];
|
||||
struct haptic_ctr ctr;
|
||||
unsigned char ori_gain;
|
||||
};
|
||||
|
||||
struct trig {
|
||||
unsigned char enable;
|
||||
unsigned char default_level;
|
||||
unsigned char dual_edge;
|
||||
unsigned char frist_seq;
|
||||
unsigned char second_seq;
|
||||
};
|
||||
|
||||
struct aw8624_dts_info {
|
||||
unsigned int mode;
|
||||
unsigned int f0_pre;
|
||||
unsigned int f0_cali_percen;
|
||||
unsigned int cont_drv_lvl;
|
||||
unsigned int cont_drv_lvl_ov;
|
||||
unsigned int cont_td;
|
||||
unsigned int cont_zc_thr;
|
||||
unsigned int cont_num_brk;
|
||||
unsigned int f0_coeff;
|
||||
unsigned int f0_trace_parameter[4];
|
||||
unsigned int bemf_config[4];
|
||||
unsigned int sw_brake;
|
||||
unsigned int tset;
|
||||
unsigned int r_spare;
|
||||
unsigned int parameter1;
|
||||
unsigned int gain_flag;
|
||||
unsigned int effect_id_boundary;
|
||||
unsigned int effect_max;
|
||||
unsigned int rtp_time[175];
|
||||
unsigned int trig_config[3][5];
|
||||
};
|
||||
|
||||
#ifdef INPUT_DEV
|
||||
enum actutor_type {
|
||||
ACT_LRA,
|
||||
ACT_ERM,
|
||||
};
|
||||
|
||||
enum lra_res_sig_shape {
|
||||
RES_SIG_SINE,
|
||||
RES_SIG_SQUARE,
|
||||
};
|
||||
|
||||
enum lra_auto_res_mode {
|
||||
AUTO_RES_MODE_ZXD,
|
||||
AUTO_RES_MODE_QWD,
|
||||
};
|
||||
|
||||
enum wf_src {
|
||||
INT_WF_VMAX,
|
||||
INT_WF_BUFFER,
|
||||
EXT_WF_AUDIO,
|
||||
EXT_WF_PWM,
|
||||
};
|
||||
|
||||
enum own_cali {
|
||||
NORMAL_CALI,
|
||||
F0_CALI,
|
||||
OSC_CALI,
|
||||
};
|
||||
struct qti_hap_effect {
|
||||
int id;
|
||||
u8 *pattern;
|
||||
int pattern_length;
|
||||
u16 play_rate_us;
|
||||
u16 vmax_mv;
|
||||
u8 wf_repeat_n;
|
||||
u8 wf_s_repeat_n;
|
||||
u8 brake[HAP_BRAKE_PATTERN_MAX];
|
||||
int brake_pattern_length;
|
||||
bool brake_en;
|
||||
bool lra_auto_res_disable;
|
||||
};
|
||||
|
||||
struct qti_hap_play_info {
|
||||
struct qti_hap_effect *effect;
|
||||
u16 vmax_mv;
|
||||
int length_us;
|
||||
int playing_pos;
|
||||
bool playing_pattern;
|
||||
};
|
||||
|
||||
struct qti_hap_config {
|
||||
enum actutor_type act_type;
|
||||
enum lra_res_sig_shape lra_shape;
|
||||
enum lra_auto_res_mode lra_auto_res_mode;
|
||||
enum wf_src ext_src;
|
||||
u16 vmax_mv;
|
||||
u16 play_rate_us;
|
||||
bool lra_allow_variable_play_rate;
|
||||
bool use_ext_wf_src;
|
||||
};
|
||||
#endif
|
||||
|
||||
#ifdef ENABLE_PIN_CONTROL
|
||||
const char * const pctl_names[] = {
|
||||
"aw8624_reset_reset",
|
||||
"aw8624_reset_active",
|
||||
"aw8624_interrupt_active",
|
||||
};
|
||||
#endif
|
||||
struct aw8624 {
|
||||
struct i2c_client *i2c;
|
||||
struct mutex lock;
|
||||
#ifdef ENABLE_PIN_CONTROL
|
||||
struct pinctrl *aw8624_pinctrl;
|
||||
struct pinctrl_state *pinctrl_state[ARRAY_SIZE(pctl_names)];
|
||||
#endif
|
||||
int enable_pin_control;
|
||||
struct work_struct vibrator_work;
|
||||
struct work_struct rtp_work;
|
||||
struct work_struct set_gain_work;
|
||||
struct delayed_work ram_work;
|
||||
struct delayed_work stop_work;
|
||||
|
||||
struct fileops fileops;
|
||||
struct ram ram;
|
||||
|
||||
struct timespec64 start, end;
|
||||
unsigned int timeval_flags;
|
||||
unsigned int osc_cali_flag;
|
||||
unsigned long int microsecond;
|
||||
unsigned int sys_frequency;
|
||||
unsigned int rtp_len;
|
||||
unsigned int lra_calib_data;
|
||||
unsigned int f0_calib_data;
|
||||
|
||||
int reset_gpio;
|
||||
int irq_gpio;
|
||||
|
||||
unsigned char hwen_flag;
|
||||
unsigned char flags;
|
||||
unsigned char chipid;
|
||||
unsigned char chipid_flag;
|
||||
|
||||
unsigned char play_mode;
|
||||
|
||||
unsigned char activate_mode;
|
||||
|
||||
unsigned char auto_boost;
|
||||
unsigned char wk_lock_flag;
|
||||
unsigned char irq_sts_flag;
|
||||
|
||||
int state;
|
||||
int duration;
|
||||
int amplitude;
|
||||
int index;
|
||||
int vmax;
|
||||
int gain;
|
||||
u16 new_gain;
|
||||
int f0_value;
|
||||
unsigned char level;
|
||||
|
||||
unsigned char seq[AW8624_SEQUENCER_SIZE];
|
||||
unsigned char loop[AW8624_SEQUENCER_SIZE];
|
||||
|
||||
unsigned int rtp_cnt;
|
||||
unsigned int rtp_file_num;
|
||||
|
||||
unsigned char rtp_init;
|
||||
unsigned char ram_init;
|
||||
unsigned char ram_retry_cnt;//Daniel 20211009 modify
|
||||
|
||||
unsigned int f0;
|
||||
unsigned int cont_f0;
|
||||
unsigned char max_pos_beme;
|
||||
unsigned char max_neg_beme;
|
||||
unsigned char f0_cali_flag;
|
||||
unsigned int osc_cali_run;
|
||||
|
||||
unsigned char ram_vbat_comp;
|
||||
unsigned int vbat;
|
||||
unsigned int lra;
|
||||
|
||||
struct trig trig[AW8624_TRIG_NUM];
|
||||
|
||||
struct haptic_audio haptic_audio;
|
||||
struct aw8624_dts_info info;
|
||||
atomic_t is_in_rtp_loop;
|
||||
atomic_t exit_in_rtp_loop;
|
||||
wait_queue_head_t wait_q;//wait queue for exit irq mode
|
||||
wait_queue_head_t stop_wait_q; //wait queue for stop rtp mode
|
||||
struct workqueue_struct *work_queue;
|
||||
|
||||
#ifdef INPUT_DEV
|
||||
struct platform_device *pdev;
|
||||
struct device *dev;
|
||||
struct regmap *regmap;
|
||||
struct input_dev *input_dev;
|
||||
struct pwm_device *pwm_dev;
|
||||
struct qti_hap_config config;
|
||||
struct qti_hap_play_info play;
|
||||
struct qti_hap_effect *predefined;
|
||||
struct qti_hap_effect constant;
|
||||
struct regulator *vdd_supply;
|
||||
struct hrtimer stop_timer;
|
||||
struct hrtimer hap_disable_timer;
|
||||
struct hrtimer timer; /*test used ,del */
|
||||
struct mutex rtp_lock;
|
||||
spinlock_t bus_lock;
|
||||
ktime_t last_sc_time;
|
||||
int play_irq;
|
||||
int sc_irq;
|
||||
int effects_count;
|
||||
int sc_det_count;
|
||||
u16 reg_base;
|
||||
bool perm_disable;
|
||||
bool play_irq_en;
|
||||
bool vdd_enabled;
|
||||
int effect_type;
|
||||
int effect_id;
|
||||
int test_val;
|
||||
#endif
|
||||
};
|
||||
|
||||
struct aw8624_container {
|
||||
int len;
|
||||
unsigned char data[];
|
||||
};
|
||||
|
||||
/*********************************************************
|
||||
*
|
||||
* ioctl
|
||||
*
|
||||
********************************************************/
|
||||
struct aw8624_seq_loop {
|
||||
unsigned char loop[AW8624_SEQUENCER_SIZE];
|
||||
};
|
||||
|
||||
struct aw8624_que_seq {
|
||||
unsigned char index[AW8624_SEQUENCER_SIZE];
|
||||
};
|
||||
|
||||
#define AW8624_HAPTIC_IOCTL_MAGIC 'h'
|
||||
|
||||
#define AW8624_HAPTIC_SET_QUE_SEQ _IOWR(AW8624_HAPTIC_IOCTL_MAGIC,\
|
||||
1,\
|
||||
struct aw8624_que_seq*)
|
||||
#define AW8624_HAPTIC_SET_SEQ_LOOP _IOWR(AW8624_HAPTIC_IOCTL_MAGIC,\
|
||||
2,\
|
||||
struct aw8624_seq_loop*)
|
||||
#define AW8624_HAPTIC_PLAY_QUE_SEQ _IOWR(AW8624_HAPTIC_IOCTL_MAGIC,\
|
||||
3,\
|
||||
unsigned int)
|
||||
#define AW8624_HAPTIC_SET_GAIN _IOWR(AW8624_HAPTIC_IOCTL_MAGIC,\
|
||||
6,\
|
||||
unsigned int)
|
||||
#define AW8624_HAPTIC_PLAY_REPEAT_SEQ _IOWR(AW8624_HAPTIC_IOCTL_MAGIC,\
|
||||
7,\
|
||||
unsigned int)
|
||||
|
||||
#endif
|
||||
|
||||
118
drivers/input/misc/aw8624_haptic/aw8624_config.h
Normal file
118
drivers/input/misc/aw8624_haptic/aw8624_config.h
Normal file
@@ -0,0 +1,118 @@
|
||||
#ifndef __AW8624_CONFIG_H__
|
||||
#define __AW8624_CONFIG_H__
|
||||
|
||||
#define AW8624_BSTCFG_PEAKCUR_LIMIT 0x07
|
||||
#define AW8624_DEFAULT_PEAKCUR AW8624_BIT_BSTCFG_PEAKCUR_3P5A
|
||||
|
||||
#define AW8624_CONT_PLAYBACK_MODE AW8624_BIT_CONT_CTRL_CLOSE_PLAYBACK
|
||||
|
||||
/*#define CONFIG_DEBUG_FS*/
|
||||
|
||||
/*#ifdef INPUT_DEV*/
|
||||
#if 1
|
||||
/* haptics module register definitions */
|
||||
#define REG_HAP_STATUS1 0x0A
|
||||
#define HAP_SC_DET_BIT BIT(3)
|
||||
#define HAP_BUSY_BIT BIT(1)
|
||||
|
||||
#define REG_HAP_EN_CTL1 0x46
|
||||
#define HAP_EN_BIT BIT(7)
|
||||
|
||||
#define REG_HAP_EN_CTL2 0x48
|
||||
#define HAP_AUTO_STANDBY_EN_BIT BIT(1)
|
||||
#define HAP_BRAKE_EN_BIT BIT(0)
|
||||
|
||||
#define REG_HAP_EN_CTL3 0x4A
|
||||
#define HAP_HBRIDGE_EN_BIT BIT(7)
|
||||
#define HAP_PWM_SIGNAL_EN_BIT BIT(6)
|
||||
#define HAP_ILIM_EN_BIT BIT(5)
|
||||
#define HAP_ILIM_CC_EN_BIT BIT(4)
|
||||
#define HAP_AUTO_RES_RBIAS_EN_BIT BIT(3)
|
||||
#define HAP_DAC_EN_BIT BIT(2)
|
||||
#define HAP_ZX_HYST_EN_BIT BIT(1)
|
||||
#define HAP_PWM_CTL_EN_BIT BIT(0)
|
||||
|
||||
#define REG_HAP_AUTO_RES_CTRL 0x4B
|
||||
#define HAP_AUTO_RES_EN_BIT BIT(7)
|
||||
#define HAP_SEL_AUTO_RES_PERIOD BIT(6)
|
||||
#define HAP_AUTO_RES_CNT_ERR_DELTA_MASK GENMASK(5, 4)
|
||||
#define HAP_AUTO_RES_CNT_ERR_DELTA_SHIFT 4
|
||||
#define HAP_AUTO_RES_ERR_RECOVERY_BIT BIT(3)
|
||||
#define HAP_AUTO_RES_EN_DLY_MASK GENMASK(2, 0)
|
||||
#define AUTO_RES_CNT_ERR_DELTA(x) (x << HAP_AUTO_RES_CNT_ERR_DELTA_SHIFT)
|
||||
#define AUTO_RES_EN_DLY(x) x
|
||||
|
||||
#define REG_HAP_CFG1 0x4C
|
||||
#define REG_HAP_CFG2 0x4D
|
||||
#define HAP_LRA_RES_TYPE_BIT BIT(0)
|
||||
|
||||
#define REG_HAP_SEL 0x4E
|
||||
#define HAP_WF_SOURCE_MASK GENMASK(5, 4)
|
||||
#define HAP_WF_SOURCE_SHIFT 4
|
||||
#define HAP_WF_TRIGGER_BIT BIT(0)
|
||||
#define HAP_WF_SOURCE_VMAX (0 << HAP_WF_SOURCE_SHIFT)
|
||||
#define HAP_WF_SOURCE_BUFFER (1 << HAP_WF_SOURCE_SHIFT)
|
||||
#define HAP_WF_SOURCE_AUDIO (2 << HAP_WF_SOURCE_SHIFT)
|
||||
#define HAP_WF_SOURCE_PWM (3 << HAP_WF_SOURCE_SHIFT)
|
||||
|
||||
#define REG_HAP_AUTO_RES_CFG 0x4F
|
||||
#define HAP_AUTO_RES_MODE_BIT BIT(7)
|
||||
#define HAP_AUTO_RES_MODE_SHIFT 7
|
||||
#define HAP_AUTO_RES_CAL_DURATON_MASK GENMASK(6, 5)
|
||||
#define HAP_CAL_EOP_EN_BIT BIT(3)
|
||||
#define HAP_CAL_PERIOD_MASK GENMASK(2, 0)
|
||||
#define HAP_CAL_OPT3_EVERY_8_PERIOD 2
|
||||
|
||||
#define REG_HAP_SLEW_CFG 0x50
|
||||
#define REG_HAP_VMAX_CFG 0x51
|
||||
#define HAP_VMAX_SIGN_BIT BIT(7)
|
||||
#define HAP_VMAX_OVD_BIT BIT(6)
|
||||
#define HAP_VMAX_MV_MASK GENMASK(5, 1)
|
||||
#define HAP_VMAX_MV_SHIFT 1
|
||||
#define HAP_VMAX_MV_LSB 116
|
||||
|
||||
#define REG_HAP_ILIM_CFG 0x52
|
||||
#define HAP_ILIM_SEL_1000MA BIT(1)
|
||||
#define HAP_ILIM_DEFAULT_SEL HAP_ILIM_SEL_1000MA
|
||||
#define REG_HAP_SC_DEB_CFG 0x53
|
||||
#define REG_HAP_RATE_CFG1 0x54
|
||||
#define REG_HAP_RATE_CFG2 0x55
|
||||
#define REG_HAP_INTERNAL_PWM 0x56
|
||||
#define REG_HAP_EXTERNAL_PWM 0x57
|
||||
#define REG_HAP_PWM 0x58
|
||||
|
||||
#define REG_HAP_SC_CLR 0x59
|
||||
#define HAP_SC_CLR_BIT BIT(0)
|
||||
|
||||
#define REG_HAP_ZX_CFG 0x5A
|
||||
#define HAP_ZX_DET_DEB_MASK GENMASK(2, 0)
|
||||
#define ZX_DET_DEB_10US 0
|
||||
#define ZX_DET_DEB_20US 1
|
||||
#define ZX_DET_DEB_40US 2
|
||||
#define ZX_DET_DEB_80US 3
|
||||
|
||||
#define REG_HAP_BRAKE 0x5C
|
||||
#define HAP_BRAKE_PATTERN_MASK 0x3
|
||||
#define HAP_BRAKE_PATTERN_SHIFT 2
|
||||
|
||||
#define REG_HAP_WF_REPEAT 0x5E
|
||||
#define HAP_WF_REPEAT_MASK GENMASK(6, 4)
|
||||
#define HAP_WF_REPEAT_SHIFT 4
|
||||
#define HAP_WF_S_REPEAT_MASK GENMASK(1, 0)
|
||||
|
||||
#define REG_HAP_WF_S1 0x60
|
||||
#define HAP_WF_SIGN_BIT BIT(7)
|
||||
#define HAP_WF_OVD_BIT BIT(6)
|
||||
#define HAP_WF_AMP_BIT GENMASK(5, 1)
|
||||
#define HAP_WF_AMP_SHIFT 1
|
||||
|
||||
#define REG_HAP_PLAY 0x70
|
||||
#define HAP_PLAY_BIT BIT(7)
|
||||
|
||||
#define REG_HAP_SEC_ACCESS 0xD0
|
||||
|
||||
static int wf_repeat[8] = { 1, 2, 4, 8, 16, 32, 64, 128 };
|
||||
static int wf_s_repeat[4] = { 1, 2, 4, 8 };
|
||||
#endif
|
||||
#endif
|
||||
|
||||
540
drivers/input/misc/aw8624_haptic/aw8624_reg.h
Normal file
540
drivers/input/misc/aw8624_haptic/aw8624_reg.h
Normal file
@@ -0,0 +1,540 @@
|
||||
#ifndef _AW8624_REG_H_
|
||||
#define _AW8624_REG_H_
|
||||
|
||||
/********************************************
|
||||
* Register List
|
||||
*******************************************/
|
||||
#define AW8624_REG_ID 0x00
|
||||
#define AW8624_REG_SYSST 0x01
|
||||
#define AW8624_REG_SYSINT 0x02
|
||||
#define AW8624_REG_SYSINTM 0x03
|
||||
#define AW8624_REG_SYSCTRL 0x04
|
||||
#define AW8624_REG_GO 0x05
|
||||
#define AW8624_REG_RTP_DATA 0x06
|
||||
#define AW8624_REG_WAVSEQ1 0x07
|
||||
#define AW8624_REG_WAVSEQ2 0x08
|
||||
#define AW8624_REG_WAVSEQ3 0x09
|
||||
#define AW8624_REG_WAVSEQ4 0x0a
|
||||
#define AW8624_REG_WAVSEQ5 0x0b
|
||||
#define AW8624_REG_WAVSEQ6 0x0c
|
||||
#define AW8624_REG_WAVSEQ7 0x0d
|
||||
#define AW8624_REG_WAVSEQ8 0x0e
|
||||
#define AW8624_REG_WAVLOOP1 0x0f
|
||||
#define AW8624_REG_WAVLOOP2 0x10
|
||||
#define AW8624_REG_WAVLOOP3 0x11
|
||||
#define AW8624_REG_WAVLOOP4 0x12
|
||||
#define AW8624_REG_MAIN_LOOP 0x13
|
||||
#define AW8624_REG_TRG1_SEQP 0x14
|
||||
#define AW8624_REG_TRG1_SEQN 0x17
|
||||
#define AW8624_REG_PLAY_PRIO 0x1a
|
||||
#define AW8624_REG_TRG_CFG1 0x1b
|
||||
#define AW8624_REG_TRG_CFG2 0x1c
|
||||
#define AW8624_REG_DBGCTRL 0x20
|
||||
#define AW8624_REG_BASE_ADDRH 0x21
|
||||
#define AW8624_REG_BASE_ADDRL 0x22
|
||||
#define AW8624_REG_FIFO_AEH 0x23
|
||||
#define AW8624_REG_FIFO_AEL 0x24
|
||||
#define AW8624_REG_FIFO_AFH 0x25
|
||||
#define AW8624_REG_FIFO_AFL 0x26
|
||||
#define AW8624_REG_WAKE_DLY 0x27
|
||||
#define AW8624_REG_START_DLY 0x28
|
||||
#define AW8624_REG_END_DLY_H 0x29
|
||||
#define AW8624_REG_END_DLY_L 0x2a
|
||||
#define AW8624_REG_DATCTRL 0x2b
|
||||
#define AW8624_REG_PWMDEL 0x2c
|
||||
#define AW8624_REG_PWMPRC 0x2d
|
||||
#define AW8624_REG_PWMDBG 0x2e
|
||||
#define AW8624_REG_LDOCTRL 0x2f
|
||||
#define AW8624_REG_DBGSTAT 0x30
|
||||
#define AW8624_REG_WAVECTRL 0x31
|
||||
#define AW8624_REG_BRAKE0_CTRL 0x32
|
||||
#define AW8624_REG_BRAKE1_CTRL 0x33
|
||||
#define AW8624_REG_BRAKE2_CTRL 0x34
|
||||
#define AW8624_REG_BRAKE_NUM 0x35
|
||||
#define AW8624_REG_ANADBG1 0x36
|
||||
#define AW8624_REG_ANADBG2 0x37
|
||||
#define AW8624_REG_ANACTRL 0x38
|
||||
#define AW8624_REG_SW_BRAKE 0x39
|
||||
#define AW8624_REG_GLBDBG 0x3a
|
||||
#define AW8624_REG_DATDBG 0x3b
|
||||
#define AW8624_REG_WDCTRL 0x3c
|
||||
#define AW8624_REG_HDRVDBG 0x3d
|
||||
#define AW8624_REG_PRLVL 0x3e
|
||||
#define AW8624_REG_PRTIME 0x3f
|
||||
#define AW8624_REG_RAMADDRH 0x40
|
||||
#define AW8624_REG_RAMADDRL 0x41
|
||||
#define AW8624_REG_RAMDATA 0x42
|
||||
#define AW8624_REG_TM 0x43
|
||||
#define AW8624_REG_BRA_MAX_NUM 0x44
|
||||
#define AW8624_REG_BEMF_ERM_FAC 0x45
|
||||
#define AW8624_REG_BEMF_BRA_FAC 0x46
|
||||
#define AW8624_REG_GLB_STATE 0x47
|
||||
#define AW8624_REG_CONT_CTRL 0x48
|
||||
#define AW8624_REG_F_PRE_H 0x49
|
||||
#define AW8624_REG_F_PRE_L 0x4a
|
||||
#define AW8624_REG_TD_H 0x4b
|
||||
#define AW8624_REG_TD_L 0x4c
|
||||
#define AW8624_REG_TSET 0x4d
|
||||
#define AW8624_REG_THRS_BRA_RAP 0x4e
|
||||
#define AW8624_REG_THRS_BRA_END 0x4f
|
||||
#define AW8624_REG_EF_CTRL 0x50
|
||||
#define AW8624_REG_EF_WDATAH 0x53
|
||||
#define AW8624_REG_EF_WDATAL 0x54
|
||||
#define AW8624_REG_EF_RDATAH 0x55
|
||||
#define AW8624_REG_EF_RDATAL 0x56
|
||||
#define AW8624_REG_DLY 0x57
|
||||
#define AW8624_REG_EF_WR_WIDTH 0x58
|
||||
#define AW8624_REG_EF_RD_WIDTH 0x59
|
||||
#define AW8624_REG_TRIM_LRA 0x5b
|
||||
#define AW8624_REG_TRIM_OSC 0x5c
|
||||
#define AW8624_REG_R_SPARE 0x5d
|
||||
#define AW8624_REG_D2SCFG 0x5e
|
||||
#define AW8624_REG_DETCTRL 0x5f
|
||||
#define AW8624_REG_RLDET 0x60
|
||||
#define AW8624_REG_OSDET 0x61
|
||||
#define AW8624_REG_VBATDET 0x62
|
||||
#define AW8624_REG_TESTDET 0x63
|
||||
#define AW8624_REG_DETLO 0x64
|
||||
#define AW8624_REG_BEMFDBG 0x65
|
||||
#define AW8624_REG_ADCTEST 0x66
|
||||
#define AW8624_REG_BEMFTEST 0x67
|
||||
#define AW8624_REG_F_LRA_F0_H 0x68
|
||||
#define AW8624_REG_F_LRA_F0_L 0x69
|
||||
#define AW8624_REG_F_LRA_CONT_H 0x6a
|
||||
#define AW8624_REG_F_LRA_CONT_L 0x6b
|
||||
#define AW8624_REG_WAIT_VOL_MP 0x6e
|
||||
#define AW8624_REG_WAIT_VOL_MN 0x6f
|
||||
#define AW8624_REG_BEMF_VOL_H 0x70
|
||||
#define AW8624_REG_BEMF_VOL_L 0x71
|
||||
#define AW8624_REG_ZC_THRSH_H 0x72
|
||||
#define AW8624_REG_ZC_THRSH_L 0x73
|
||||
#define AW8624_REG_BEMF_VTHH_H 0x74
|
||||
#define AW8624_REG_BEMF_VTHH_L 0x75
|
||||
#define AW8624_REG_BEMF_VTHL_H 0x76
|
||||
#define AW8624_REG_BEMF_VTHL_L 0x77
|
||||
#define AW8624_REG_BEMF_NUM 0x78
|
||||
#define AW8624_REG_DRV_TIME 0x79
|
||||
#define AW8624_REG_TIME_NZC 0x7a
|
||||
#define AW8624_REG_DRV_LVL 0x7b
|
||||
#define AW8624_REG_DRV_LVL_OV 0x7c
|
||||
#define AW8624_REG_NUM_F0_1 0x7d
|
||||
#define AW8624_REG_NUM_F0_2 0x7e
|
||||
#define AW8624_REG_NUM_F0_3 0x7f
|
||||
|
||||
|
||||
|
||||
/********************************************
|
||||
* Register Access
|
||||
*******************************************/
|
||||
#define REG_NONE_ACCESS 0
|
||||
#define REG_RD_ACCESS (1 << 0)
|
||||
#define REG_WR_ACCESS (1 << 1)
|
||||
#define AW8624_REG_MAX 0xff
|
||||
|
||||
|
||||
const unsigned char aw8624_reg_access[AW8624_REG_MAX] = {
|
||||
[AW8624_REG_ID] = REG_RD_ACCESS,
|
||||
[AW8624_REG_SYSST] = REG_RD_ACCESS,
|
||||
[AW8624_REG_SYSINT] = REG_RD_ACCESS,
|
||||
[AW8624_REG_SYSINTM] = REG_RD_ACCESS|REG_WR_ACCESS,
|
||||
[AW8624_REG_SYSCTRL] = REG_RD_ACCESS|REG_WR_ACCESS,
|
||||
[AW8624_REG_GO] = REG_RD_ACCESS|REG_WR_ACCESS,
|
||||
[AW8624_REG_RTP_DATA] = REG_RD_ACCESS|REG_WR_ACCESS,
|
||||
[AW8624_REG_WAVSEQ1] = REG_RD_ACCESS|REG_WR_ACCESS,
|
||||
[AW8624_REG_WAVSEQ2] = REG_RD_ACCESS|REG_WR_ACCESS,
|
||||
[AW8624_REG_WAVSEQ3] = REG_RD_ACCESS|REG_WR_ACCESS,
|
||||
[AW8624_REG_WAVSEQ4] = REG_RD_ACCESS|REG_WR_ACCESS,
|
||||
[AW8624_REG_WAVSEQ5] = REG_RD_ACCESS|REG_WR_ACCESS,
|
||||
[AW8624_REG_WAVSEQ6] = REG_RD_ACCESS|REG_WR_ACCESS,
|
||||
[AW8624_REG_WAVSEQ7] = REG_RD_ACCESS|REG_WR_ACCESS,
|
||||
[AW8624_REG_WAVSEQ8] = REG_RD_ACCESS|REG_WR_ACCESS,
|
||||
[AW8624_REG_WAVLOOP1] = REG_RD_ACCESS|REG_WR_ACCESS,
|
||||
[AW8624_REG_WAVLOOP2] = REG_RD_ACCESS|REG_WR_ACCESS,
|
||||
[AW8624_REG_WAVLOOP3] = REG_RD_ACCESS|REG_WR_ACCESS,
|
||||
[AW8624_REG_WAVLOOP4] = REG_RD_ACCESS|REG_WR_ACCESS,
|
||||
[AW8624_REG_MAIN_LOOP] = REG_RD_ACCESS|REG_WR_ACCESS,
|
||||
[AW8624_REG_TRG1_SEQP] = REG_RD_ACCESS|REG_WR_ACCESS,
|
||||
[AW8624_REG_TRG1_SEQN] = REG_RD_ACCESS|REG_WR_ACCESS,
|
||||
[AW8624_REG_PLAY_PRIO] = REG_RD_ACCESS|REG_WR_ACCESS,
|
||||
[AW8624_REG_TRG_CFG1] = REG_RD_ACCESS|REG_WR_ACCESS,
|
||||
[AW8624_REG_TRG_CFG2] = REG_RD_ACCESS|REG_WR_ACCESS,
|
||||
[AW8624_REG_DBGCTRL] = REG_RD_ACCESS|REG_WR_ACCESS,
|
||||
[AW8624_REG_BASE_ADDRH] = REG_RD_ACCESS|REG_WR_ACCESS,
|
||||
[AW8624_REG_BASE_ADDRL] = REG_RD_ACCESS|REG_WR_ACCESS,
|
||||
[AW8624_REG_FIFO_AEH] = REG_RD_ACCESS|REG_WR_ACCESS,
|
||||
[AW8624_REG_FIFO_AEL] = REG_RD_ACCESS|REG_WR_ACCESS,
|
||||
[AW8624_REG_FIFO_AFH] = REG_RD_ACCESS|REG_WR_ACCESS,
|
||||
[AW8624_REG_FIFO_AFL] = REG_RD_ACCESS|REG_WR_ACCESS,
|
||||
[AW8624_REG_WAKE_DLY] = REG_RD_ACCESS|REG_WR_ACCESS,
|
||||
[AW8624_REG_START_DLY] = REG_RD_ACCESS|REG_WR_ACCESS,
|
||||
[AW8624_REG_END_DLY_H] = REG_RD_ACCESS|REG_WR_ACCESS,
|
||||
[AW8624_REG_END_DLY_L] = REG_RD_ACCESS|REG_WR_ACCESS,
|
||||
[AW8624_REG_DATCTRL] = REG_RD_ACCESS|REG_WR_ACCESS,
|
||||
[AW8624_REG_PWMDEL] = REG_RD_ACCESS|REG_WR_ACCESS,
|
||||
[AW8624_REG_PWMPRC] = REG_RD_ACCESS|REG_WR_ACCESS,
|
||||
[AW8624_REG_PWMDBG] = REG_RD_ACCESS|REG_WR_ACCESS,
|
||||
[AW8624_REG_LDOCTRL] = REG_RD_ACCESS|REG_WR_ACCESS,
|
||||
[AW8624_REG_DBGSTAT] = REG_RD_ACCESS,
|
||||
[AW8624_REG_WAVECTRL] = REG_RD_ACCESS|REG_WR_ACCESS,
|
||||
[AW8624_REG_BRAKE0_CTRL] = REG_RD_ACCESS|REG_WR_ACCESS,
|
||||
[AW8624_REG_BRAKE1_CTRL] = REG_RD_ACCESS|REG_WR_ACCESS,
|
||||
[AW8624_REG_BRAKE2_CTRL] = REG_RD_ACCESS|REG_WR_ACCESS,
|
||||
[AW8624_REG_BRAKE_NUM] = REG_RD_ACCESS|REG_WR_ACCESS,
|
||||
[AW8624_REG_ANADBG1] = REG_RD_ACCESS|REG_WR_ACCESS,
|
||||
[AW8624_REG_ANADBG2] = REG_RD_ACCESS|REG_WR_ACCESS,
|
||||
[AW8624_REG_ANACTRL] = REG_RD_ACCESS|REG_WR_ACCESS,
|
||||
[AW8624_REG_SW_BRAKE] = REG_RD_ACCESS|REG_WR_ACCESS,
|
||||
[AW8624_REG_GLBDBG] = REG_RD_ACCESS|REG_WR_ACCESS,
|
||||
[AW8624_REG_DATDBG] = REG_RD_ACCESS|REG_WR_ACCESS,
|
||||
[AW8624_REG_WDCTRL] = REG_RD_ACCESS|REG_WR_ACCESS,
|
||||
[AW8624_REG_HDRVDBG] = REG_RD_ACCESS|REG_WR_ACCESS,
|
||||
[AW8624_REG_PRLVL] = REG_RD_ACCESS|REG_WR_ACCESS,
|
||||
[AW8624_REG_PRTIME] = REG_RD_ACCESS|REG_WR_ACCESS,
|
||||
[AW8624_REG_RAMADDRH] = REG_RD_ACCESS|REG_WR_ACCESS,
|
||||
[AW8624_REG_RAMADDRL] = REG_RD_ACCESS|REG_WR_ACCESS,
|
||||
[AW8624_REG_RAMDATA] = REG_RD_ACCESS|REG_WR_ACCESS,
|
||||
[AW8624_REG_TM] = REG_RD_ACCESS|REG_WR_ACCESS,
|
||||
[AW8624_REG_BRA_MAX_NUM] = REG_RD_ACCESS|REG_WR_ACCESS,
|
||||
[AW8624_REG_BEMF_ERM_FAC] = REG_RD_ACCESS|REG_WR_ACCESS,
|
||||
[AW8624_REG_BEMF_BRA_FAC] = REG_RD_ACCESS|REG_WR_ACCESS,
|
||||
[AW8624_REG_GLB_STATE] = REG_RD_ACCESS|REG_WR_ACCESS,
|
||||
[AW8624_REG_CONT_CTRL] = REG_RD_ACCESS|REG_WR_ACCESS,
|
||||
[AW8624_REG_F_PRE_H] = REG_RD_ACCESS|REG_WR_ACCESS,
|
||||
[AW8624_REG_F_PRE_L] = REG_RD_ACCESS|REG_WR_ACCESS,
|
||||
[AW8624_REG_TD_H] = REG_RD_ACCESS|REG_WR_ACCESS,
|
||||
[AW8624_REG_TD_L] = REG_RD_ACCESS|REG_WR_ACCESS,
|
||||
[AW8624_REG_TSET] = REG_RD_ACCESS|REG_WR_ACCESS,
|
||||
[AW8624_REG_THRS_BRA_RAP] = REG_RD_ACCESS|REG_WR_ACCESS,
|
||||
[AW8624_REG_THRS_BRA_END] = REG_RD_ACCESS|REG_WR_ACCESS,
|
||||
[AW8624_REG_EF_CTRL] = REG_RD_ACCESS|REG_WR_ACCESS,
|
||||
[AW8624_REG_EF_WDATAH] = REG_RD_ACCESS|REG_WR_ACCESS,
|
||||
[AW8624_REG_EF_WDATAL] = REG_RD_ACCESS|REG_WR_ACCESS,
|
||||
[AW8624_REG_EF_RDATAH] = REG_RD_ACCESS|REG_WR_ACCESS,
|
||||
[AW8624_REG_EF_RDATAL] = REG_RD_ACCESS|REG_WR_ACCESS,
|
||||
[AW8624_REG_DLY] = REG_RD_ACCESS|REG_WR_ACCESS,
|
||||
[AW8624_REG_EF_WR_WIDTH] = REG_RD_ACCESS|REG_WR_ACCESS,
|
||||
[AW8624_REG_EF_RD_WIDTH] = REG_RD_ACCESS|REG_WR_ACCESS,
|
||||
[AW8624_REG_TRIM_LRA] = REG_RD_ACCESS|REG_WR_ACCESS,
|
||||
[AW8624_REG_TRIM_OSC] = REG_RD_ACCESS|REG_WR_ACCESS,
|
||||
[AW8624_REG_R_SPARE] = REG_RD_ACCESS|REG_WR_ACCESS,
|
||||
[AW8624_REG_D2SCFG] = REG_RD_ACCESS|REG_WR_ACCESS,
|
||||
[AW8624_REG_DETCTRL] = REG_RD_ACCESS|REG_WR_ACCESS,
|
||||
[AW8624_REG_RLDET] = REG_RD_ACCESS,
|
||||
[AW8624_REG_OSDET] = REG_RD_ACCESS,
|
||||
[AW8624_REG_VBATDET] = REG_RD_ACCESS,
|
||||
[AW8624_REG_TESTDET] = REG_RD_ACCESS|REG_WR_ACCESS,
|
||||
[AW8624_REG_DETLO] = REG_RD_ACCESS|REG_WR_ACCESS,
|
||||
[AW8624_REG_BEMFDBG] = REG_RD_ACCESS|REG_WR_ACCESS,
|
||||
[AW8624_REG_ADCTEST] = REG_RD_ACCESS|REG_WR_ACCESS,
|
||||
[AW8624_REG_BEMFTEST] = REG_RD_ACCESS|REG_WR_ACCESS,
|
||||
[AW8624_REG_F_LRA_F0_H] = REG_RD_ACCESS,
|
||||
[AW8624_REG_F_LRA_F0_L] = REG_RD_ACCESS,
|
||||
[AW8624_REG_F_LRA_CONT_H] = REG_RD_ACCESS,
|
||||
[AW8624_REG_F_LRA_CONT_L] = REG_RD_ACCESS,
|
||||
[AW8624_REG_WAIT_VOL_MP] = REG_RD_ACCESS,
|
||||
[AW8624_REG_WAIT_VOL_MN] = REG_RD_ACCESS,
|
||||
[AW8624_REG_BEMF_VOL_H] = REG_RD_ACCESS,
|
||||
[AW8624_REG_BEMF_VOL_L] = REG_RD_ACCESS,
|
||||
[AW8624_REG_ZC_THRSH_H] = REG_RD_ACCESS|REG_WR_ACCESS,
|
||||
[AW8624_REG_ZC_THRSH_L] = REG_RD_ACCESS|REG_WR_ACCESS,
|
||||
[AW8624_REG_BEMF_VTHH_H] = REG_RD_ACCESS|REG_WR_ACCESS,
|
||||
[AW8624_REG_BEMF_VTHH_L] = REG_RD_ACCESS|REG_WR_ACCESS,
|
||||
[AW8624_REG_BEMF_VTHL_H] = REG_RD_ACCESS|REG_WR_ACCESS,
|
||||
[AW8624_REG_BEMF_VTHL_L] = REG_RD_ACCESS|REG_WR_ACCESS,
|
||||
[AW8624_REG_BEMF_NUM] = REG_RD_ACCESS|REG_WR_ACCESS,
|
||||
[AW8624_REG_DRV_TIME] = REG_RD_ACCESS|REG_WR_ACCESS,
|
||||
[AW8624_REG_TIME_NZC] = REG_RD_ACCESS|REG_WR_ACCESS,
|
||||
[AW8624_REG_DRV_LVL] = REG_RD_ACCESS|REG_WR_ACCESS,
|
||||
[AW8624_REG_DRV_LVL_OV] = REG_RD_ACCESS|REG_WR_ACCESS,
|
||||
[AW8624_REG_NUM_F0_1] = REG_RD_ACCESS|REG_WR_ACCESS,
|
||||
[AW8624_REG_NUM_F0_2] = REG_RD_ACCESS|REG_WR_ACCESS,
|
||||
[AW8624_REG_NUM_F0_3] = REG_RD_ACCESS|REG_WR_ACCESS,
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
/******************************************************
|
||||
* Register Detail
|
||||
*****************************************************/
|
||||
/* SYSST 0x01 */
|
||||
#define AW8624_BIT_SYSST_OVS (1<<6)
|
||||
#define AW8624_BIT_SYSST_UVLS (1<<5)
|
||||
#define AW8624_BIT_SYSST_FF_AES (1<<4)
|
||||
#define AW8624_BIT_SYSST_FF_AFS (1<<3)
|
||||
#define AW8624_BIT_SYSST_OCDS (1<<2)
|
||||
#define AW8624_BIT_SYSST_OTS (1<<1)
|
||||
#define AW8624_BIT_SYSST_DONES (1<<0)
|
||||
|
||||
/* SYSINT 0x02 */
|
||||
#define AW8624_BIT_SYSINT_OVI (1<<6)
|
||||
#define AW8624_BIT_SYSINT_UVLI (1<<5)
|
||||
#define AW8624_BIT_SYSINT_FF_AEI (1<<4)
|
||||
#define AW8624_BIT_SYSINT_FF_AFI (1<<3)
|
||||
#define AW8624_BIT_SYSINT_OCDI (1<<2)
|
||||
#define AW8624_BIT_SYSINT_OTI (1<<1)
|
||||
#define AW8624_BIT_SYSINT_DONEI (1<<0)
|
||||
|
||||
/* SYSINTM 0x03 */
|
||||
#define AW8624_BIT_SYSINTM_OV_MASK (~(1<<6))
|
||||
#define AW8624_BIT_SYSINTM_OV_OFF (1<<6)
|
||||
#define AW8624_BIT_SYSINTM_OV_EN (0<<6)
|
||||
#define AW8624_BIT_SYSINTM_UVLO_MASK (~(1<<5))
|
||||
#define AW8624_BIT_SYSINTM_UVLO_OFF (1<<5)
|
||||
#define AW8624_BIT_SYSINTM_UVLO_EN (0<<5)
|
||||
#define AW8624_BIT_SYSINTM_FF_AE_MASK (~(1<<4))
|
||||
#define AW8624_BIT_SYSINTM_FF_AE_OFF (1<<4)
|
||||
#define AW8624_BIT_SYSINTM_FF_AE_EN (0<<4)
|
||||
#define AW8624_BIT_SYSINTM_FF_AF_MASK (~(1<<3))
|
||||
#define AW8624_BIT_SYSINTM_FF_AF_OFF (1<<3)
|
||||
#define AW8624_BIT_SYSINTM_FF_AF_EN (0<<3)
|
||||
#define AW8624_BIT_SYSINTM_OCD_MASK (~(1<<2))
|
||||
#define AW8624_BIT_SYSINTM_OCD_OFF (1<<2)
|
||||
#define AW8624_BIT_SYSINTM_OCD_EN (0<<2)
|
||||
#define AW8624_BIT_SYSINTM_OT_MASK (~(1<<1))
|
||||
#define AW8624_BIT_SYSINTM_OT_OFF (1<<1)
|
||||
#define AW8624_BIT_SYSINTM_OT_EN (0<<1)
|
||||
#define AW8624_BIT_SYSINTM_DONE_MASK (~(1<<0))
|
||||
#define AW8624_BIT_SYSINTM_DONE_OFF (1<<0)
|
||||
#define AW8624_BIT_SYSINTM_DONE_EN (0<<0)
|
||||
|
||||
/* SYSCTRL 0x04 */
|
||||
#define AW8624_BIT_SYSCTRL_WAVDAT_MODE_MASK (~(3<<6))
|
||||
#define AW8624_BIT_SYSCTRL_WAVDAT_MODE_4X (3<<6)
|
||||
#define AW8624_BIT_SYSCTRL_WAVDAT_MODE_2X (0<<6)
|
||||
#define AW8624_BIT_SYSCTRL_WAVDAT_MODE_1X (1<<6)
|
||||
#define AW8624_BIT_SYSCTRL_RAMINIT_MASK (~(1<<5))
|
||||
#define AW8624_BIT_SYSCTRL_RAMINIT_EN (1<<5)
|
||||
#define AW8624_BIT_SYSCTRL_RAMINIT_OFF (0<<5)
|
||||
#define AW8624_BIT_SYSCTRL_PLAY_MODE_MASK (~(3<<2))
|
||||
#define AW8624_BIT_SYSCTRL_PLAY_MODE_CONT (2<<2)
|
||||
#define AW8624_BIT_SYSCTRL_PLAY_MODE_RTP (1<<2)
|
||||
#define AW8624_BIT_SYSCTRL_PLAY_MODE_RAM (0<<2)
|
||||
#define AW8624_BIT_SYSCTRL_WORK_MODE_MASK (~(1<<0))
|
||||
#define AW8624_BIT_SYSCTRL_STANDBY (1<<0)
|
||||
#define AW8624_BIT_SYSCTRL_ACTIVE (0<<0)
|
||||
|
||||
/* GO 0x05 */
|
||||
#define AW8624_BIT_GO_MASK (~(1<<0))
|
||||
#define AW8624_BIT_GO_ENABLE (1<<0)
|
||||
#define AW8624_BIT_GO_DISABLE (0<<0)
|
||||
|
||||
/* WAVSEQ1 0x07 */
|
||||
#define AW8624_BIT_WAVSEQ1_WAIT (1<<7)
|
||||
#define AW8624_BIT_WAVSEQ1_WAV_FRM_SEQ1_MASK (~(127<<0))
|
||||
|
||||
/* WAVSEQ2 0x08 */
|
||||
#define AW8624_BIT_WAVSEQ2_WAIT (1<<7)
|
||||
#define AW8624_BIT_WAVSEQ2_WAV_FRM_SEQ2_MASK (~(127<<0))
|
||||
|
||||
/* WAVSEQ3 0x09 */
|
||||
#define AW8624_BIT_WAVSEQ3_WAIT (1<<7)
|
||||
#define AW8624_BIT_WAVSEQ3_WAV_FRM_SEQ3_MASK (~(127<<0))
|
||||
|
||||
/* WAVSEQ4 0x0A */
|
||||
#define AW8624_BIT_WAVSEQ4_WAIT (1<<7)
|
||||
#define AW8624_BIT_WAVSEQ4_WAV_FRM_SEQ4_MASK (~(127<<0))
|
||||
|
||||
/* WAVSEQ5 0X0B */
|
||||
#define AW8624_BIT_WAVSEQ5_WAIT (1<<7)
|
||||
#define AW8624_BIT_WAVSEQ5_WAV_FRM_SEQ5_MASK (~(127<<0))
|
||||
|
||||
/* WAVSEQ6 0X0C */
|
||||
#define AW8624_BIT_WAVSEQ6_WAIT (1<<7)
|
||||
#define AW8624_BIT_WAVSEQ6_WAV_FRM_SEQ6_MASK (~(127<<0))
|
||||
|
||||
/* WAVSEQ7 */
|
||||
#define AW8624_BIT_WAVSEQ7_WAIT (1<<7)
|
||||
#define AW8624_BIT_WAVSEQ7_WAV_FRM_SEQ7_MASK (~(127<<0))
|
||||
|
||||
/* WAVSEQ8 */
|
||||
#define AW8624_BIT_WAVSEQ8_WAIT (1<<7)
|
||||
#define AW8624_BIT_WAVSEQ8_WAV_FRM_SEQ8_MASK (~(127<<0))
|
||||
|
||||
/* WAVLOOP */
|
||||
#define AW8624_BIT_WAVLOOP_SEQN_MASK (~(15<<4))
|
||||
#define AW8624_BIT_WAVLOOP_SEQNP1_MASK (~(15<<0))
|
||||
#define AW8624_BIT_WAVLOOP_INIFINITELY (15<<0)
|
||||
|
||||
/* WAVLOOP1 */
|
||||
#define AW8624_BIT_WAVLOOP1_SEQ1_MASK (~(15<<4))
|
||||
#define AW8624_BIT_WAVLOOP1_SEQ2_MASK (~(15<<0))
|
||||
|
||||
/* WAVLOOP2 */
|
||||
#define AW8624_BIT_WAVLOOP2_SEQ3_MASK (~(15<<4))
|
||||
#define AW8624_BIT_WAVLOOP2_SEQ4_MASK (~(15<<0))
|
||||
|
||||
/* WAVLOOP3 */
|
||||
#define AW8624_BIT_WAVLOOP3_SEQ5_MASK (~(15<<4))
|
||||
#define AW8624_BIT_WAVLOOP3_SEQ6_MASK (~(15<<0))
|
||||
|
||||
/* WAVLOOP4 */
|
||||
#define AW8624_BIT_WAVLOOP4_SEQ7_MASK (~(15<<4))
|
||||
#define AW8624_BIT_WAVLOOP4_SEQ8_MASK (~(15<<0))
|
||||
|
||||
|
||||
/* PLAYPRIO */
|
||||
#define AW8624_BIT_PLAYPRIO_GO_MASK (~(3<<6))
|
||||
#define AW8624_BIT_PLAYPRIO_TRIG3_MASK (~(3<<4))
|
||||
#define AW8624_BIT_PLAYPRIO_TRIG2_MASK (~(3<<2))
|
||||
#define AW8624_BIT_PLAYPRIO_TRIG1_MASK (~(3<<0))
|
||||
|
||||
/* TRGCFG1 */
|
||||
#define AW8624_BIT_TRGCFG1_TRG3_POLAR_MASK (~(1<<5))
|
||||
#define AW8624_BIT_TRGCFG1_TRG3_POLAR_NEG (1<<5)
|
||||
#define AW8624_BIT_TRGCFG1_TRG3_POLAR_POS (0<<5)
|
||||
#define AW8624_BIT_TRGCFG1_TRG3_EDGE_MASK (~(1<<4))
|
||||
#define AW8624_BIT_TRGCFG1_TRG3_EDGE_POS (1<<4)
|
||||
#define AW8624_BIT_TRGCFG1_TRG3_EDGE_POS_NEG (0<<4)
|
||||
#define AW8624_BIT_TRGCFG1_TRG2_POLAR_MASK (~(1<<3))
|
||||
#define AW8624_BIT_TRGCFG1_TRG2_POLAR_NEG (1<<3)
|
||||
#define AW8624_BIT_TRGCFG1_TRG2_POLAR_POS (0<<3)
|
||||
#define AW8624_BIT_TRGCFG1_TRG2_EDGE_MASK (~(1<<2))
|
||||
#define AW8624_BIT_TRGCFG1_TRG2_EDGE_POS (1<<2)
|
||||
#define AW8624_BIT_TRGCFG1_TRG2_EDGE_POS_NEG (0<<2)
|
||||
#define AW8624_BIT_TRGCFG1_TRG1_POLAR_MASK (~(1<<1))
|
||||
#define AW8624_BIT_TRGCFG1_TRG1_POLAR_NEG (1<<1)
|
||||
#define AW8624_BIT_TRGCFG1_TRG1_POLAR_POS (0<<1)
|
||||
#define AW8624_BIT_TRGCFG1_TRG1_EDGE_MASK (~(1<<0))
|
||||
#define AW8624_BIT_TRGCFG1_TRG1_EDGE_POS (1<<0)
|
||||
#define AW8624_BIT_TRGCFG1_TRG1_EDGE_POS_NEG (0<<0)
|
||||
|
||||
/* TRGCFG2 */
|
||||
#define AW8624_BIT_TRGCFG2_TRG3_ENABLE_MASK (~(1<<2))
|
||||
#define AW8624_BIT_TRGCFG2_TRG3_ENABLE (1<<2)
|
||||
#define AW8624_BIT_TRGCFG2_TRG3_DISABLE (0<<2)
|
||||
#define AW8624_BIT_TRGCFG2_TRG2_ENABLE_MASK (~(1<<1))
|
||||
#define AW8624_BIT_TRGCFG2_TRG2_ENABLE (1<<1)
|
||||
#define AW8624_BIT_TRGCFG2_TRG2_DISABLE (0<<1)
|
||||
#define AW8624_BIT_TRGCFG2_TRG1_ENABLE_MASK (~(1<<0))
|
||||
#define AW8624_BIT_TRGCFG2_TRG1_ENABLE (1<<0)
|
||||
#define AW8624_BIT_TRGCFG2_TRG1_DISABLE (0<<0)
|
||||
|
||||
/*DBGCTRL 0X20 */
|
||||
#define AW8624_BIT_DBGCTRL_INTN_TRG_SEL_MASK (~(1<<5))
|
||||
#define AW8624_BIT_DBGCTRL_INTN_SEL_ENABLE (1<<5)
|
||||
#define AW8624_BIT_DBGCTRL_TRG_SEL_ENABLE (0<<5)
|
||||
#define AW8624_BIT_DBGCTRL_INTMODE_MASK (~(3<<2))
|
||||
#define AW8624_BIT_DBGCTRL_INTN_LEVEL_MODE (0<<2)
|
||||
#define AW8624_BIT_DBGCTRL_INTN_EDGE_MODE (1<<2)
|
||||
#define AW8624_BIT_DBGCTRL_INTN_POSEDGE_MODE (2<<2)
|
||||
#define AW8624_BIT_DBGCTRL_INTN_BOTH_EDGE_MODE (3<<2)
|
||||
|
||||
|
||||
/* DATCTRL */
|
||||
#define AW8624_BIT_DATCTRL_FC_MASK (~(1<<6))
|
||||
#define AW8624_BIT_DATCTRL_FC_1000HZ (3<<6)
|
||||
#define AW8624_BIT_DATCTRL_FC_800HZ (3<<6)
|
||||
#define AW8624_BIT_DATCTRL_FC_600HZ (1<<6)
|
||||
#define AW8624_BIT_DATCTRL_FC_400HZ (0<<6)
|
||||
#define AW8624_BIT_DATCTRL_LPF_ENABLE_MASK (~(1<<5))
|
||||
#define AW8624_BIT_DATCTRL_LPF_ENABLE (1<<5)
|
||||
#define AW8624_BIT_DATCTRL_LPF_DISABLE (0<<5)
|
||||
|
||||
/*PWMPRC 0X2D */
|
||||
#define AW8624_BIT_PWMPRC_PRC_EN_MASK (~(1<<7))
|
||||
#define AW8624_BIT_PWMPRC_PRC_ENABLE (1<<7)
|
||||
#define AW8624_BIT_PWMPRC_PRC_DISABLE (0<<7)
|
||||
#define AW8624_BIT_PWMPRC_PRCTIME_MASK (~(0x7f<<0))
|
||||
|
||||
/* REG:0X2E PWMDBG */
|
||||
#define AW8624_BIT_PWMDBG_PWM_MODE_MASK (~(3<<5))
|
||||
#define AW8624_BIT_PWMDBG_PWM_12K (3<<5)
|
||||
#define AW8624_BIT_PWMDBG_PWM_24K (2<<5)
|
||||
#define AW8624_BIT_PWMDBG_PWM_48K (0<<5)
|
||||
|
||||
/* WAVECTRL */
|
||||
#define AW8624_BIT_WAVECTRL_NUM_OV_DRIVER_MASK (~(0xF<<4))
|
||||
#define AW8624_BIT_WAVECTRL_NUM_OV_DRIVER (0<<4)
|
||||
|
||||
/* CONT_CTRL */
|
||||
#define AW8624_BIT_CONT_CTRL_ZC_DETEC_MASK (~(1<<7))
|
||||
#define AW8624_BIT_CONT_CTRL_ZC_DETEC_ENABLE (1<<7)
|
||||
#define AW8624_BIT_CONT_CTRL_ZC_DETEC_DISABLE (0<<7)
|
||||
#define AW8624_BIT_CONT_CTRL_WAIT_PERIOD_MASK (~(3<<5))
|
||||
#define AW8624_BIT_CONT_CTRL_WAIT_8PERIOD (3<<5)
|
||||
#define AW8624_BIT_CONT_CTRL_WAIT_4PERIOD (2<<5)
|
||||
#define AW8624_BIT_CONT_CTRL_WAIT_2PERIOD (1<<5)
|
||||
#define AW8624_BIT_CONT_CTRL_WAIT_1PERIOD (0<<5)
|
||||
#define AW8624_BIT_CONT_CTRL_MODE_MASK (~(1<<4))
|
||||
#define AW8624_BIT_CONT_CTRL_BY_DRV_TIME (1<<4)
|
||||
#define AW8624_BIT_CONT_CTRL_BY_GO_SIGNAL (0<<4)
|
||||
#define AW8624_BIT_CONT_CTRL_EN_CLOSE_MASK (~(1<<3))
|
||||
#define AW8624_BIT_CONT_CTRL_CLOSE_PLAYBACK (1<<3)
|
||||
#define AW8624_BIT_CONT_CTRL_OPEN_PLAYBACK (0<<3)
|
||||
#define AW8624_BIT_CONT_CTRL_F0_DETECT_MASK (~(1<<2))
|
||||
#define AW8624_BIT_CONT_CTRL_F0_DETECT_ENABLE (1<<2)
|
||||
#define AW8624_BIT_CONT_CTRL_F0_DETECT_DISABLE (0<<2)
|
||||
#define AW8624_BIT_CONT_CTRL_O2C_MASK (~(1<<1))
|
||||
#define AW8624_BIT_CONT_CTRL_O2C_ENABLE (1<<1)
|
||||
#define AW8624_BIT_CONT_CTRL_O2C_DISABLE (0<<1)
|
||||
#define AW8624_BIT_CONT_CTRL_AUTO_BRK_MASK (~(1<<0))
|
||||
#define AW8624_BIT_CONT_CTRL_AUTO_BRK_ENABLE (1<<0)
|
||||
#define AW8624_BIT_CONT_CTRL_AUTO_BRK_DISABLE (0<<0)
|
||||
|
||||
#define AW8624_BIT_D2SCFG_CLK_ADC_MASK (~(7<<4))
|
||||
#define AW8624_BIT_D2SCFG_CLK_ASC_1P5MHZ (3<<4)
|
||||
|
||||
/* DETCTRL */
|
||||
#define AW8624_BIT_DETCTRL_RL_OS_MASK (~(1<<6))
|
||||
#define AW8624_BIT_DETCTRL_RL_DETECT (1<<6)
|
||||
#define AW8624_BIT_DETCTRL_OS_DETECT (0<<6)
|
||||
#define AW8624_BIT_DETCTRL_PROTECT_MASK (~(1<<5))
|
||||
#define AW8624_BIT_DETCTRL_PROTECT_NO_ACTION (1<<5)
|
||||
#define AW8624_BIT_DETCTRL_PROTECT_SHUTDOWN (0<<5)
|
||||
#define AW8624_BIT_DETCTRL_VBAT_GO_MASK (~(1<<1))
|
||||
#define AW8624_BIT_DETCTRL_VABT_GO_ENABLE (1<<1)
|
||||
#define AW8624_BIT_DETCTRL_VBAT_GO_DISBALE (0<<1)
|
||||
#define AW8624_BIT_DETCTRL_DIAG_GO_MASK (~(1<<0))
|
||||
#define AW8624_BIT_DETCTRL_DIAG_GO_ENABLE (1<<0)
|
||||
#define AW8624_BIT_DETCTRL_DIAG_GO_DISABLE (0<<0)
|
||||
|
||||
|
||||
/* VBAT MODE */
|
||||
#define AW8624_BIT_DETCTRL_VBAT_MODE_MASK (~(1<<6))
|
||||
#define AW8624_BIT_DETCTRL_VBAT_HW_COMP (1<<6)
|
||||
#define AW8624_BIT_DETCTRL_VBAT_SW_COMP (0<<6)
|
||||
|
||||
|
||||
/* ANACTRL */
|
||||
#define AW8624_BIT_ANACTRL_LRA_SRC_MASK (~(1<<5))
|
||||
#define AW8624_BIT_ANACTRL_LRA_SRC_REG (1<<5)
|
||||
#define AW8624_BIT_ANACTRL_LRA_SRC_EFUSE (0<<5)
|
||||
#define AW8624_BIT_ANACTRL_EN_IO_PD1_MASK (~(1<<0))
|
||||
#define AW8624_BIT_ANACTRL_EN_IO_PD1_HIGH (1<<0)
|
||||
#define AW8624_BIT_ANACTRL_EN_IO_PD1_LOW (0<<0)
|
||||
|
||||
/* SW_BRAKE */
|
||||
#define AW8624_BIT_EN_BRAKE_CONT_MASK (~(1<<3))
|
||||
#define AW8624_BIT_EN_BRAKE_CONT_ENABLE (1<<3)
|
||||
#define AW8624_BIT_EN_BRAKE_CONT_DISABLE (0<<3)
|
||||
#define AW8624_BIT_EN_BRAKE_RAM_MASK (~(1<<2))
|
||||
#define AW8624_BIT_EN_BRAKE_RAM_ENABLE (1<<2)
|
||||
#define AW8624_BIT_EN_BRAKE_RAM_DISABLE (0<<2)
|
||||
#define AW8624_BIT_EN_BRAKE_RTP_MASK (~(1<<1))
|
||||
#define AW8624_BIT_EN_BRAKE_RTP_ENABLE (1<<1)
|
||||
#define AW8624_BIT_EN_BRAKE_RTP_DISABLE (0<<1)
|
||||
#define AW8624_BIT_EN_BRAKE_TRIG_MASK (~(1<<0))
|
||||
#define AW8624_BIT_EN_BRAKE_TRIG_ENABLE (1<<0)
|
||||
#define AW8624_BIT_EN_BRAKE_TRIG_DISABLE (0<<0)
|
||||
|
||||
/* PRLVL */
|
||||
#define AW8624_BIT_PRLVL_PR_EN_MASK (~(1<<7))
|
||||
#define AW8624_BIT_PRLVL_PR_ENABLE (1<<7)
|
||||
#define AW8624_BIT_PRLVL_PR_DISABLE (0<<7)
|
||||
#define AW8624_BIT_PRLVL_PRLVL_MASK (~(0x7f<<0))
|
||||
|
||||
/* PRTIME */
|
||||
#define AW8624_BIT_PRTIME_PRTIME_MASK (~(0xff<<0))
|
||||
|
||||
#define AW8624_BIT_BEMF_NUM_BRK_MASK (~(0xf<<0))
|
||||
|
||||
/* TD_H 0x4b TD_brake */
|
||||
#define AW8624_BIT_TDH_TD_BRAKE_MASK (~(0xF<<4))
|
||||
#define AW8624_BIT_R_SPARE_MASK (~(1<<7))
|
||||
#define AW8624_BIT_R_SPARE_ENABLE (1<<7)
|
||||
/* PWMDBG */
|
||||
#define AW8624_BIT_D2SCFG_DS_GAIN_MASK (~(7<<0))
|
||||
#define AW8624_BIT_D2SCFG_DS_GAIN_40 (7<<0)
|
||||
#endif
|
||||
|
||||
14
drivers/input/misc/aw8697_haptic/Kconfig
Normal file
14
drivers/input/misc/aw8697_haptic/Kconfig
Normal file
@@ -0,0 +1,14 @@
|
||||
#
|
||||
# Awinic aw8697 driver
|
||||
#
|
||||
|
||||
config INPUT_AW8697_HAPTIC
|
||||
tristate "Awinic AW8697 HAPTIC"
|
||||
depends on I2C
|
||||
help
|
||||
Say Y here if you have Awinic AW8697 haptic controller
|
||||
chip in your system.
|
||||
|
||||
If unsure, say N.
|
||||
|
||||
To compile this driver as a module, choose M here.
|
||||
8
drivers/input/misc/aw8697_haptic/Makefile
Normal file
8
drivers/input/misc/aw8697_haptic/Makefile
Normal file
@@ -0,0 +1,8 @@
|
||||
ifeq ($(TARGET_PRODUCT),lmi)
|
||||
CDEFINES += -DUSE_CONT_F0_CALI
|
||||
KBUILD_CPPFLAGS += $(CDEFINES)
|
||||
endif
|
||||
|
||||
aw8697-haptic-objs = ringbuffer.o aw8697.o
|
||||
|
||||
obj-$(CONFIG_INPUT_AW8697_HAPTIC) += aw8697-haptic.o
|
||||
4876
drivers/input/misc/aw8697_haptic/aw8697.c
Normal file
4876
drivers/input/misc/aw8697_haptic/aw8697.c
Normal file
File diff suppressed because it is too large
Load Diff
466
drivers/input/misc/aw8697_haptic/aw8697.h
Normal file
466
drivers/input/misc/aw8697_haptic/aw8697.h
Normal file
@@ -0,0 +1,466 @@
|
||||
#ifndef _AW8697_H_
|
||||
#define _AW8697_H_
|
||||
|
||||
/*********************************************************
|
||||
*
|
||||
* kernel version
|
||||
*
|
||||
********************************************************/
|
||||
#define INPUT_DEV
|
||||
//#define TEST_RTP
|
||||
#define TEST_CONT_TO_RAM
|
||||
/*********************************************************
|
||||
*
|
||||
* aw8697.h
|
||||
*
|
||||
********************************************************/
|
||||
#include <linux/regmap.h>
|
||||
#include <linux/timer.h>
|
||||
#include <linux/workqueue.h>
|
||||
#include <linux/hrtimer.h>
|
||||
#include <linux/mutex.h>
|
||||
#include <linux/cdev.h>
|
||||
#include <linux/leds.h>
|
||||
#include <linux/atomic.h>
|
||||
|
||||
|
||||
/*********************************************************
|
||||
*
|
||||
* marco
|
||||
*
|
||||
********************************************************/
|
||||
#define AW8697_CHIPID 0x97
|
||||
|
||||
#define MAX_I2C_BUFFER_SIZE 65536
|
||||
|
||||
#define AW8697_SEQUENCER_SIZE 8
|
||||
#define AW8697_SEQUENCER_LOOP_SIZE 4
|
||||
|
||||
#define AW8697_RTP_I2C_SINGLE_MAX_NUM 512
|
||||
|
||||
#define HAPTIC_MAX_TIMEOUT 10000
|
||||
|
||||
#define AW8697_VBAT_REFER 4200
|
||||
#define AW8697_VBAT_MIN 3000
|
||||
#define AW8697_VBAT_MAX 4500
|
||||
#define ENABLE_PIN_CONTROL
|
||||
|
||||
#ifdef INPUT_DEV
|
||||
/* common definitions */
|
||||
#define HAP_BRAKE_PATTERN_MAX 4
|
||||
#define HAP_WAVEFORM_BUFFER_MAX 8 /*used */
|
||||
#define HAP_VMAX_MV_DEFAULT 1800
|
||||
#define HAP_VMAX_MV_MAX 3596
|
||||
#define HAP_PLAY_RATE_US_DEFAULT 5715 /*used */
|
||||
#define HAP_PLAY_RATE_US_MAX 20475
|
||||
#define HAP_PLAY_RATE_US_LSB 5
|
||||
#define VMAX_MIN_PLAY_TIME_US 20000
|
||||
#define HAP_SC_DET_MAX_COUNT 5
|
||||
#define HAP_SC_DET_TIME_US 1000000
|
||||
#define FF_EFFECT_COUNT_MAX 32
|
||||
#define HAP_DISABLE_DELAY_USEC 1000
|
||||
#endif
|
||||
/*
|
||||
* trig default high level
|
||||
* ___________ _________________
|
||||
* | |
|
||||
* | |
|
||||
* |___________|
|
||||
* first edge
|
||||
* second edge
|
||||
*
|
||||
*
|
||||
* trig default low level
|
||||
* ___________
|
||||
* | |
|
||||
* | |
|
||||
* __________| |_________________
|
||||
* first edge
|
||||
* second edge
|
||||
*/
|
||||
/* trig config */
|
||||
/*dts config
|
||||
* default_level -> 1: high level; 0: low level
|
||||
* dual_edge -> 1: dual edge; 0: first edge
|
||||
*vib_trig_config = <
|
||||
* 1 1 1 1 2
|
||||
* enable default_level dual_edge first_seq second_seq
|
||||
* 1 1 2 1 2
|
||||
* enable default_level dual_edge first_seq second_seq
|
||||
* 1 1 3 1 2
|
||||
* enable default_level dual_edge first_seq second_seq
|
||||
*/
|
||||
#define AW8697_TRIG_NUM 3
|
||||
|
||||
|
||||
enum aw8697_flags {
|
||||
AW8697_FLAG_NONR = 0,
|
||||
AW8697_FLAG_SKIP_INTERRUPTS = 1,
|
||||
};
|
||||
|
||||
enum aw8697_haptic_read_write {
|
||||
AW8697_HAPTIC_CMD_READ_REG = 0,
|
||||
AW8697_HAPTIC_CMD_WRITE_REG = 1,
|
||||
};
|
||||
|
||||
enum aw8697_haptic_work_mode {
|
||||
AW8697_HAPTIC_STANDBY_MODE = 0,
|
||||
AW8697_HAPTIC_RAM_MODE = 1,
|
||||
AW8697_HAPTIC_RTP_MODE = 2,
|
||||
AW8697_HAPTIC_TRIG_MODE = 3,
|
||||
AW8697_HAPTIC_CONT_MODE = 4,
|
||||
AW8697_HAPTIC_RAM_LOOP_MODE = 5,
|
||||
};
|
||||
|
||||
enum aw8697_haptic_bst_mode {
|
||||
AW8697_HAPTIC_BYPASS_MODE = 0,
|
||||
AW8697_HAPTIC_BOOST_MODE = 1,
|
||||
};
|
||||
|
||||
enum aw8697_haptic_activate_mode {
|
||||
AW8697_HAPTIC_ACTIVATE_RAM_MODE = 0,
|
||||
AW8697_HAPTIC_ACTIVATE_CONT_MODE = 1,
|
||||
AW8697_HAPTIC_ACTIVATE_RTP_MODE = 2,
|
||||
AW8697_HAPTIC_ACTIVATE_RAM_LOOP_MODE = 3,
|
||||
};
|
||||
|
||||
enum aw8697_haptic_cont_vbat_comp_mode {
|
||||
AW8697_HAPTIC_CONT_VBAT_SW_COMP_MODE = 0,
|
||||
AW8697_HAPTIC_CONT_VBAT_HW_COMP_MODE = 1,
|
||||
};
|
||||
|
||||
enum aw8697_haptic_ram_vbat_comp_mode {
|
||||
AW8697_HAPTIC_RAM_VBAT_COMP_DISABLE = 0,
|
||||
AW8697_HAPTIC_RAM_VBAT_COMP_ENABLE = 1,
|
||||
};
|
||||
|
||||
enum aw8697_haptic_f0_flag {
|
||||
AW8697_HAPTIC_LRA_F0 = 0,
|
||||
AW8697_HAPTIC_CALI_F0 = 1,
|
||||
};
|
||||
|
||||
enum aw8697_haptic_pwm_mode {
|
||||
AW8697_PWM_48K = 0,
|
||||
AW8697_PWM_24K = 1,
|
||||
AW8697_PWM_12K = 2,
|
||||
};
|
||||
|
||||
enum aw8697_haptic_play {
|
||||
AW8697_HAPTIC_PLAY_NULL = 0,
|
||||
AW8697_HAPTIC_PLAY_ENABLE = 1,
|
||||
AW8697_HAPTIC_PLAY_STOP = 2,
|
||||
AW8697_HAPTIC_PLAY_GAIN = 8,
|
||||
};
|
||||
|
||||
enum aw8697_haptic_cmd {
|
||||
AW8697_HAPTIC_CMD_NULL = 0,
|
||||
AW8697_HAPTIC_CMD_ENABLE = 1,
|
||||
AW8697_HAPTIC_CMD_STOP = 255,
|
||||
};
|
||||
|
||||
enum haptics_custom_effect_param {
|
||||
CUSTOM_DATA_EFFECT_IDX,
|
||||
CUSTOM_DATA_TIMEOUT_SEC_IDX,
|
||||
CUSTOM_DATA_TIMEOUT_MSEC_IDX,
|
||||
CUSTOM_DATA_LEN,
|
||||
};
|
||||
enum aw8697_haptic_strength {
|
||||
AW8697_LIGHT_MAGNITUDE = 0x3fff,
|
||||
AW8697_MEDIUM_MAGNITUDE = 0x5fff,
|
||||
AW8697_STRONG_MAGNITUDE = 0x7fff,
|
||||
};
|
||||
/*********************************************************
|
||||
*
|
||||
* struct
|
||||
*
|
||||
********************************************************/
|
||||
struct fileops {
|
||||
unsigned char cmd;
|
||||
unsigned char reg;
|
||||
unsigned char ram_addrh;
|
||||
unsigned char ram_addrl;
|
||||
};
|
||||
|
||||
struct ram {
|
||||
unsigned int len;
|
||||
unsigned int check_sum;
|
||||
unsigned int base_addr;
|
||||
unsigned char version;
|
||||
unsigned char ram_shift;
|
||||
unsigned char baseaddr_shift;
|
||||
};
|
||||
|
||||
struct haptic_ctr {
|
||||
unsigned char cmd;
|
||||
unsigned char play;
|
||||
unsigned char wavseq;
|
||||
unsigned char loop;
|
||||
unsigned char gain;
|
||||
};
|
||||
|
||||
struct haptic_audio {
|
||||
struct mutex lock;
|
||||
struct hrtimer timer;
|
||||
struct work_struct work;
|
||||
int delay_val;
|
||||
int timer_val;
|
||||
unsigned char cnt;
|
||||
struct haptic_ctr data[256];
|
||||
struct haptic_ctr ctr;
|
||||
unsigned char ori_gain;
|
||||
};
|
||||
|
||||
struct trig {
|
||||
unsigned char enable;
|
||||
unsigned char default_level;
|
||||
unsigned char dual_edge;
|
||||
unsigned char frist_seq;
|
||||
unsigned char second_seq;
|
||||
};
|
||||
|
||||
struct aw8697_dts_info {
|
||||
unsigned int mode;
|
||||
unsigned int f0_pre;
|
||||
unsigned int f0_cali_percen;
|
||||
unsigned int cont_drv_lvl;
|
||||
unsigned int cont_drv_lvl_ov;
|
||||
unsigned int cont_td;
|
||||
unsigned int cont_zc_thr;
|
||||
unsigned int cont_num_brk;
|
||||
unsigned int f0_coeff;
|
||||
unsigned int f0_trace_parameter[4];
|
||||
unsigned int bemf_config[4];
|
||||
unsigned int sw_brake;
|
||||
unsigned int tset;
|
||||
unsigned int r_spare;
|
||||
unsigned int bstdbg[6];
|
||||
unsigned int parameter1;
|
||||
unsigned int effect_id_boundary;
|
||||
unsigned int effect_max;
|
||||
unsigned int rtp_time[175];
|
||||
unsigned int trig_config[3][5];
|
||||
unsigned int bst_vol_default;
|
||||
unsigned int bst_vol_ram;
|
||||
unsigned int bst_vol_rtp;
|
||||
};
|
||||
|
||||
#ifdef INPUT_DEV
|
||||
enum actutor_type {
|
||||
ACT_LRA,
|
||||
ACT_ERM,
|
||||
};
|
||||
|
||||
enum lra_res_sig_shape {
|
||||
RES_SIG_SINE,
|
||||
RES_SIG_SQUARE,
|
||||
};
|
||||
|
||||
enum lra_auto_res_mode {
|
||||
AUTO_RES_MODE_ZXD,
|
||||
AUTO_RES_MODE_QWD,
|
||||
};
|
||||
|
||||
enum wf_src {
|
||||
INT_WF_VMAX,
|
||||
INT_WF_BUFFER,
|
||||
EXT_WF_AUDIO,
|
||||
EXT_WF_PWM,
|
||||
};
|
||||
|
||||
struct qti_hap_effect {
|
||||
int id;
|
||||
u8 *pattern;
|
||||
int pattern_length;
|
||||
u16 play_rate_us;
|
||||
u16 vmax_mv;
|
||||
u8 wf_repeat_n;
|
||||
u8 wf_s_repeat_n;
|
||||
u8 brake[HAP_BRAKE_PATTERN_MAX];
|
||||
int brake_pattern_length;
|
||||
bool brake_en;
|
||||
bool lra_auto_res_disable;
|
||||
};
|
||||
|
||||
struct qti_hap_play_info {
|
||||
struct qti_hap_effect *effect;
|
||||
u16 vmax_mv;
|
||||
int length_us;
|
||||
int playing_pos;
|
||||
bool playing_pattern;
|
||||
};
|
||||
|
||||
struct qti_hap_config {
|
||||
enum actutor_type act_type;
|
||||
enum lra_res_sig_shape lra_shape;
|
||||
enum lra_auto_res_mode lra_auto_res_mode;
|
||||
enum wf_src ext_src;
|
||||
u16 vmax_mv;
|
||||
u16 play_rate_us;
|
||||
bool lra_allow_variable_play_rate;
|
||||
bool use_ext_wf_src;
|
||||
};
|
||||
#endif
|
||||
|
||||
#ifdef ENABLE_PIN_CONTROL
|
||||
const char * const pctl_names[] = {
|
||||
"aw8697_reset_reset",
|
||||
"aw8697_reset_active",
|
||||
"aw8697_interrupt_active",
|
||||
};
|
||||
#endif
|
||||
struct aw8697 {
|
||||
struct i2c_client *i2c;
|
||||
struct mutex lock;
|
||||
#ifdef ENABLE_PIN_CONTROL
|
||||
struct pinctrl *aw8697_pinctrl;
|
||||
struct pinctrl_state *pinctrl_state[ARRAY_SIZE(pctl_names)];
|
||||
#endif
|
||||
int enable_pin_control;
|
||||
struct work_struct vibrator_work;
|
||||
struct work_struct rtp_work;
|
||||
struct work_struct set_gain_work;
|
||||
struct delayed_work ram_work;
|
||||
|
||||
struct fileops fileops;
|
||||
struct ram ram;
|
||||
|
||||
struct timespec64 start, end;
|
||||
unsigned int timeval_flags;
|
||||
unsigned int osc_cali_flag;
|
||||
unsigned long int microsecond;
|
||||
unsigned int sys_frequency;
|
||||
unsigned int rtp_len;
|
||||
unsigned int lra_calib_data;
|
||||
unsigned int f0_calib_data;
|
||||
|
||||
int reset_gpio;
|
||||
int irq_gpio;
|
||||
|
||||
unsigned char hwen_flag;
|
||||
unsigned char flags;
|
||||
unsigned char chipid;
|
||||
|
||||
unsigned char play_mode;
|
||||
|
||||
unsigned char activate_mode;
|
||||
|
||||
unsigned char auto_boost;
|
||||
unsigned char wk_lock_flag;
|
||||
|
||||
int state;
|
||||
int duration;
|
||||
int amplitude;
|
||||
int index;
|
||||
int vmax;
|
||||
int gain;
|
||||
u16 new_gain;
|
||||
unsigned char level;
|
||||
|
||||
unsigned char seq[AW8697_SEQUENCER_SIZE];
|
||||
unsigned char loop[AW8697_SEQUENCER_SIZE];
|
||||
|
||||
unsigned int rtp_cnt;
|
||||
unsigned int rtp_file_num;
|
||||
|
||||
unsigned char rtp_init;
|
||||
unsigned char ram_init;
|
||||
|
||||
unsigned int f0;
|
||||
unsigned int cont_f0;
|
||||
unsigned char max_pos_beme;
|
||||
unsigned char max_neg_beme;
|
||||
unsigned char f0_cali_flag;
|
||||
bool f0_cali_status;
|
||||
unsigned int osc_cali_run;
|
||||
|
||||
unsigned char ram_vbat_comp;
|
||||
unsigned int vbat;
|
||||
unsigned int lra;
|
||||
|
||||
struct trig trig[AW8697_TRIG_NUM];
|
||||
|
||||
struct haptic_audio haptic_audio;
|
||||
struct aw8697_dts_info info;
|
||||
atomic_t is_in_rtp_loop;
|
||||
atomic_t exit_in_rtp_loop;
|
||||
atomic_t is_in_write_loop;
|
||||
wait_queue_head_t wait_q;//wait queue for exit irq mode
|
||||
wait_queue_head_t stop_wait_q; //wait queue for stop rtp mode
|
||||
struct workqueue_struct *work_queue;
|
||||
|
||||
#ifdef INPUT_DEV
|
||||
struct platform_device *pdev;
|
||||
struct device *dev;
|
||||
struct regmap *regmap;
|
||||
struct input_dev *input_dev;
|
||||
struct pwm_device *pwm_dev;
|
||||
struct qti_hap_config config;
|
||||
struct qti_hap_play_info play;
|
||||
struct qti_hap_effect *predefined;
|
||||
struct qti_hap_effect constant;
|
||||
struct regulator *vdd_supply;
|
||||
struct hrtimer stop_timer;
|
||||
struct hrtimer hap_disable_timer;
|
||||
struct hrtimer timer; /*test used ,del */
|
||||
struct dentry *hap_debugfs;
|
||||
struct mutex rtp_lock;
|
||||
spinlock_t bus_lock;
|
||||
ktime_t last_sc_time;
|
||||
int play_irq;
|
||||
int sc_irq;
|
||||
int effects_count;
|
||||
int sc_det_count;
|
||||
u16 reg_base;
|
||||
bool perm_disable;
|
||||
bool play_irq_en;
|
||||
bool vdd_enabled;
|
||||
int effect_type;
|
||||
int effect_id;
|
||||
int test_val;
|
||||
int is_custom_wave;
|
||||
#endif
|
||||
};
|
||||
|
||||
struct aw8697_container {
|
||||
int len;
|
||||
unsigned char data[];
|
||||
};
|
||||
|
||||
/*********************************************************
|
||||
*
|
||||
* ioctl
|
||||
*
|
||||
********************************************************/
|
||||
struct aw8697_seq_loop {
|
||||
unsigned char loop[AW8697_SEQUENCER_SIZE];
|
||||
};
|
||||
|
||||
struct aw8697_que_seq {
|
||||
unsigned char index[AW8697_SEQUENCER_SIZE];
|
||||
};
|
||||
|
||||
#define AW8697_HAPTIC_IOCTL_MAGIC 'h'
|
||||
|
||||
#define AW8697_HAPTIC_SET_QUE_SEQ _IOWR(AW8697_HAPTIC_IOCTL_MAGIC,\
|
||||
1,\
|
||||
struct aw8697_que_seq*)
|
||||
#define AW8697_HAPTIC_SET_SEQ_LOOP _IOWR(AW8697_HAPTIC_IOCTL_MAGIC,\
|
||||
2,\
|
||||
struct aw8697_seq_loop*)
|
||||
#define AW8697_HAPTIC_PLAY_QUE_SEQ _IOWR(AW8697_HAPTIC_IOCTL_MAGIC,\
|
||||
3,\
|
||||
unsigned int)
|
||||
#define AW8697_HAPTIC_SET_BST_VOL _IOWR(AW8697_HAPTIC_IOCTL_MAGIC,\
|
||||
4,\
|
||||
unsigned int)
|
||||
#define AW8697_HAPTIC_SET_BST_PEAK_CUR _IOWR(AW8697_HAPTIC_IOCTL_MAGIC,\
|
||||
5,\
|
||||
unsigned int)
|
||||
#define AW8697_HAPTIC_SET_GAIN _IOWR(AW8697_HAPTIC_IOCTL_MAGIC,\
|
||||
6,\
|
||||
unsigned int)
|
||||
#define AW8697_HAPTIC_PLAY_REPEAT_SEQ _IOWR(AW8697_HAPTIC_IOCTL_MAGIC,\
|
||||
7,\
|
||||
unsigned int)
|
||||
|
||||
#endif
|
||||
117
drivers/input/misc/aw8697_haptic/aw8697_config.h
Normal file
117
drivers/input/misc/aw8697_haptic/aw8697_config.h
Normal file
@@ -0,0 +1,117 @@
|
||||
#ifndef __AW8697_CONFIG_H__
|
||||
#define __AW8697_CONFIG_H__
|
||||
|
||||
#define AW8697_BSTCFG_PEAKCUR_LIMIT 0x07
|
||||
#define AW8697_DEFAULT_PEAKCUR AW8697_BIT_BSTCFG_PEAKCUR_3P5A
|
||||
|
||||
#define AW8697_CONT_PLAYBACK_MODE AW8697_BIT_CONT_CTRL_CLOSE_PLAYBACK
|
||||
|
||||
/*#define CONFIG_DEBUG_FS*/
|
||||
|
||||
/*#ifdef INPUT_DEV*/
|
||||
#if 1
|
||||
/* haptics module register definitions */
|
||||
#define REG_HAP_STATUS1 0x0A
|
||||
#define HAP_SC_DET_BIT BIT(3)
|
||||
#define HAP_BUSY_BIT BIT(1)
|
||||
|
||||
#define REG_HAP_EN_CTL1 0x46
|
||||
#define HAP_EN_BIT BIT(7)
|
||||
|
||||
#define REG_HAP_EN_CTL2 0x48
|
||||
#define HAP_AUTO_STANDBY_EN_BIT BIT(1)
|
||||
#define HAP_BRAKE_EN_BIT BIT(0)
|
||||
|
||||
#define REG_HAP_EN_CTL3 0x4A
|
||||
#define HAP_HBRIDGE_EN_BIT BIT(7)
|
||||
#define HAP_PWM_SIGNAL_EN_BIT BIT(6)
|
||||
#define HAP_ILIM_EN_BIT BIT(5)
|
||||
#define HAP_ILIM_CC_EN_BIT BIT(4)
|
||||
#define HAP_AUTO_RES_RBIAS_EN_BIT BIT(3)
|
||||
#define HAP_DAC_EN_BIT BIT(2)
|
||||
#define HAP_ZX_HYST_EN_BIT BIT(1)
|
||||
#define HAP_PWM_CTL_EN_BIT BIT(0)
|
||||
|
||||
#define REG_HAP_AUTO_RES_CTRL 0x4B
|
||||
#define HAP_AUTO_RES_EN_BIT BIT(7)
|
||||
#define HAP_SEL_AUTO_RES_PERIOD BIT(6)
|
||||
#define HAP_AUTO_RES_CNT_ERR_DELTA_MASK GENMASK(5, 4)
|
||||
#define HAP_AUTO_RES_CNT_ERR_DELTA_SHIFT 4
|
||||
#define HAP_AUTO_RES_ERR_RECOVERY_BIT BIT(3)
|
||||
#define HAP_AUTO_RES_EN_DLY_MASK GENMASK(2, 0)
|
||||
#define AUTO_RES_CNT_ERR_DELTA(x) (x << HAP_AUTO_RES_CNT_ERR_DELTA_SHIFT)
|
||||
#define AUTO_RES_EN_DLY(x) x
|
||||
|
||||
#define REG_HAP_CFG1 0x4C
|
||||
#define REG_HAP_CFG2 0x4D
|
||||
#define HAP_LRA_RES_TYPE_BIT BIT(0)
|
||||
|
||||
#define REG_HAP_SEL 0x4E
|
||||
#define HAP_WF_SOURCE_MASK GENMASK(5, 4)
|
||||
#define HAP_WF_SOURCE_SHIFT 4
|
||||
#define HAP_WF_TRIGGER_BIT BIT(0)
|
||||
#define HAP_WF_SOURCE_VMAX (0 << HAP_WF_SOURCE_SHIFT)
|
||||
#define HAP_WF_SOURCE_BUFFER (1 << HAP_WF_SOURCE_SHIFT)
|
||||
#define HAP_WF_SOURCE_AUDIO (2 << HAP_WF_SOURCE_SHIFT)
|
||||
#define HAP_WF_SOURCE_PWM (3 << HAP_WF_SOURCE_SHIFT)
|
||||
|
||||
#define REG_HAP_AUTO_RES_CFG 0x4F
|
||||
#define HAP_AUTO_RES_MODE_BIT BIT(7)
|
||||
#define HAP_AUTO_RES_MODE_SHIFT 7
|
||||
#define HAP_AUTO_RES_CAL_DURATON_MASK GENMASK(6, 5)
|
||||
#define HAP_CAL_EOP_EN_BIT BIT(3)
|
||||
#define HAP_CAL_PERIOD_MASK GENMASK(2, 0)
|
||||
#define HAP_CAL_OPT3_EVERY_8_PERIOD 2
|
||||
|
||||
#define REG_HAP_SLEW_CFG 0x50
|
||||
#define REG_HAP_VMAX_CFG 0x51
|
||||
#define HAP_VMAX_SIGN_BIT BIT(7)
|
||||
#define HAP_VMAX_OVD_BIT BIT(6)
|
||||
#define HAP_VMAX_MV_MASK GENMASK(5, 1)
|
||||
#define HAP_VMAX_MV_SHIFT 1
|
||||
#define HAP_VMAX_MV_LSB 116
|
||||
|
||||
#define REG_HAP_ILIM_CFG 0x52
|
||||
#define HAP_ILIM_SEL_1000MA BIT(1)
|
||||
#define HAP_ILIM_DEFAULT_SEL HAP_ILIM_SEL_1000MA
|
||||
#define REG_HAP_SC_DEB_CFG 0x53
|
||||
#define REG_HAP_RATE_CFG1 0x54
|
||||
#define REG_HAP_RATE_CFG2 0x55
|
||||
#define REG_HAP_INTERNAL_PWM 0x56
|
||||
#define REG_HAP_EXTERNAL_PWM 0x57
|
||||
#define REG_HAP_PWM 0x58
|
||||
|
||||
#define REG_HAP_SC_CLR 0x59
|
||||
#define HAP_SC_CLR_BIT BIT(0)
|
||||
|
||||
#define REG_HAP_ZX_CFG 0x5A
|
||||
#define HAP_ZX_DET_DEB_MASK GENMASK(2, 0)
|
||||
#define ZX_DET_DEB_10US 0
|
||||
#define ZX_DET_DEB_20US 1
|
||||
#define ZX_DET_DEB_40US 2
|
||||
#define ZX_DET_DEB_80US 3
|
||||
|
||||
#define REG_HAP_BRAKE 0x5C
|
||||
#define HAP_BRAKE_PATTERN_MASK 0x3
|
||||
#define HAP_BRAKE_PATTERN_SHIFT 2
|
||||
|
||||
#define REG_HAP_WF_REPEAT 0x5E
|
||||
#define HAP_WF_REPEAT_MASK GENMASK(6, 4)
|
||||
#define HAP_WF_REPEAT_SHIFT 4
|
||||
#define HAP_WF_S_REPEAT_MASK GENMASK(1, 0)
|
||||
|
||||
#define REG_HAP_WF_S1 0x60
|
||||
#define HAP_WF_SIGN_BIT BIT(7)
|
||||
#define HAP_WF_OVD_BIT BIT(6)
|
||||
#define HAP_WF_AMP_BIT GENMASK(5, 1)
|
||||
#define HAP_WF_AMP_SHIFT 1
|
||||
|
||||
#define REG_HAP_PLAY 0x70
|
||||
#define HAP_PLAY_BIT BIT(7)
|
||||
|
||||
#define REG_HAP_SEC_ACCESS 0xD0
|
||||
|
||||
static int wf_repeat[8] = { 1, 2, 4, 8, 16, 32, 64, 128 };
|
||||
static int wf_s_repeat[4] = { 1, 2, 4, 8 };
|
||||
#endif
|
||||
#endif
|
||||
539
drivers/input/misc/aw8697_haptic/aw8697_reg.h
Normal file
539
drivers/input/misc/aw8697_haptic/aw8697_reg.h
Normal file
@@ -0,0 +1,539 @@
|
||||
#ifndef _AW8697_REG_H_
|
||||
#define _AW8697_REG_H_
|
||||
|
||||
/********************************************
|
||||
* Register List
|
||||
*******************************************/
|
||||
#define AW8697_REG_ID 0x00
|
||||
#define AW8697_REG_SYSST 0x01
|
||||
#define AW8697_REG_SYSINT 0x02
|
||||
#define AW8697_REG_SYSINTM 0x03
|
||||
#define AW8697_REG_SYSCTRL 0x04
|
||||
#define AW8697_REG_GO 0x05
|
||||
#define AW8697_REG_RTP_DATA 0x06
|
||||
#define AW8697_REG_WAVSEQ1 0x07
|
||||
#define AW8697_REG_WAVSEQ2 0x08
|
||||
#define AW8697_REG_WAVSEQ3 0x09
|
||||
#define AW8697_REG_WAVSEQ4 0x0a
|
||||
#define AW8697_REG_WAVSEQ5 0x0b
|
||||
#define AW8697_REG_WAVSEQ6 0x0c
|
||||
#define AW8697_REG_WAVSEQ7 0x0d
|
||||
#define AW8697_REG_WAVSEQ8 0x0e
|
||||
#define AW8697_REG_WAVLOOP1 0x0f
|
||||
#define AW8697_REG_WAVLOOP2 0x10
|
||||
#define AW8697_REG_WAVLOOP3 0x11
|
||||
#define AW8697_REG_WAVLOOP4 0x12
|
||||
#define AW8697_REG_MAIN_LOOP 0x13
|
||||
#define AW8697_REG_TRG1_WAV_P 0x14
|
||||
#define AW8697_REG_TRG2_WAV_P 0x15
|
||||
#define AW8697_REG_TRG3_WAV_P 0x16
|
||||
#define AW8697_REG_TRG1_WAV_N 0x17
|
||||
#define AW8697_REG_TRG2_WAV_N 0x18
|
||||
#define AW8697_REG_TRG3_WAV_N 0x19
|
||||
#define AW8697_REG_TRG_PRIO 0x1a
|
||||
#define AW8697_REG_TRG_CFG1 0x1b
|
||||
#define AW8697_REG_TRG_CFG2 0x1c
|
||||
#define AW8697_REG_DBGCTRL 0x20
|
||||
#define AW8697_REG_BASE_ADDRH 0x21
|
||||
#define AW8697_REG_BASE_ADDRL 0x22
|
||||
#define AW8697_REG_FIFO_AEH 0x23
|
||||
#define AW8697_REG_FIFO_AEL 0x24
|
||||
#define AW8697_REG_FIFO_AFH 0x25
|
||||
#define AW8697_REG_FIFO_AFL 0x26
|
||||
#define AW8697_REG_WAKE_DLY 0x27
|
||||
#define AW8697_REG_START_DLY 0x28
|
||||
#define AW8697_REG_END_DLY_H 0x29
|
||||
#define AW8697_REG_END_DLY_L 0x2a
|
||||
#define AW8697_REG_DATCTRL 0x2b
|
||||
#define AW8697_REG_PWMDEL 0x2c
|
||||
#define AW8697_REG_PWMPRC 0x2d
|
||||
#define AW8697_REG_PWMDBG 0x2e
|
||||
#define AW8697_REG_LDOCTRL 0x2f
|
||||
#define AW8697_REG_DBGSTAT 0x30
|
||||
#define AW8697_REG_BSTDBG1 0x31
|
||||
#define AW8697_REG_BSTDBG2 0x32
|
||||
#define AW8697_REG_BSTDBG3 0x33
|
||||
#define AW8697_REG_BSTCFG 0x34
|
||||
#define AW8697_REG_ANADBG 0x35
|
||||
#define AW8697_REG_ANACTRL 0x36
|
||||
#define AW8697_REG_CPDBG 0x37
|
||||
#define AW8697_REG_GLBDBG 0x38
|
||||
#define AW8697_REG_DATDBG 0x39
|
||||
#define AW8697_REG_BSTDBG4 0x3a
|
||||
#define AW8697_REG_BSTDBG5 0x3b
|
||||
#define AW8697_REG_BSTDBG6 0x3c
|
||||
#define AW8697_REG_HDRVDBG 0x3d
|
||||
#define AW8697_REG_PRLVL 0x3e
|
||||
#define AW8697_REG_PRTIME 0x3f
|
||||
#define AW8697_REG_RAMADDRH 0x40
|
||||
#define AW8697_REG_RAMADDRL 0x41
|
||||
#define AW8697_REG_RAMDATA 0x42
|
||||
#define AW8697_REG_GLB_STATE 0x46
|
||||
#define AW8697_REG_BST_AUTO 0x47
|
||||
#define AW8697_REG_CONT_CTRL 0x48
|
||||
#define AW8697_REG_F_PRE_H 0x49
|
||||
#define AW8697_REG_F_PRE_L 0x4a
|
||||
#define AW8697_REG_TD_H 0x4b
|
||||
#define AW8697_REG_TD_L 0x4c
|
||||
#define AW8697_REG_TSET 0x4d
|
||||
#define AW8697_REG_TRIM_LRA 0x5b
|
||||
#define AW8697_REG_R_SPARE 0x5d
|
||||
#define AW8697_REG_D2SCFG 0x5e
|
||||
#define AW8697_REG_DETCTRL 0x5f
|
||||
#define AW8697_REG_RLDET 0x60
|
||||
#define AW8697_REG_OSDET 0x61
|
||||
#define AW8697_REG_VBATDET 0x62
|
||||
#define AW8697_REG_TESTDET 0x63
|
||||
#define AW8697_REG_DETLO 0x64
|
||||
#define AW8697_REG_BEMFDBG 0x65
|
||||
#define AW8697_REG_ADCTEST 0x66
|
||||
#define AW8697_REG_BEMFTEST 0x67
|
||||
#define AW8697_REG_F_LRA_F0_H 0x68
|
||||
#define AW8697_REG_F_LRA_F0_L 0x69
|
||||
#define AW8697_REG_F_LRA_CONT_H 0x6a
|
||||
#define AW8697_REG_F_LRA_CONT_L 0x6b
|
||||
#define AW8697_REG_WAIT_VOL_MP 0x6d
|
||||
#define AW8697_REG_WAIT_VOL_MN 0x6f
|
||||
#define AW8697_REG_BEMF_VOL_H 0x70
|
||||
#define AW8697_REG_BEMF_VOL_L 0x71
|
||||
#define AW8697_REG_ZC_THRSH_H 0x72
|
||||
#define AW8697_REG_ZC_THRSH_L 0x73
|
||||
#define AW8697_REG_BEMF_VTHH_H 0x74
|
||||
#define AW8697_REG_BEMF_VTHH_L 0x75
|
||||
#define AW8697_REG_BEMF_VTHL_H 0x76
|
||||
#define AW8697_REG_BEMF_VTHL_L 0x77
|
||||
#define AW8697_REG_BEMF_NUM 0x78
|
||||
#define AW8697_REG_DRV_TIME 0x79
|
||||
#define AW8697_REG_TIME_NZC 0x7a
|
||||
#define AW8697_REG_DRV_LVL 0x7b
|
||||
#define AW8697_REG_DRV_LVL_OV 0x7c
|
||||
#define AW8697_REG_NUM_F0_1 0x7d
|
||||
#define AW8697_REG_NUM_F0_2 0x7e
|
||||
#define AW8697_REG_NUM_F0_3 0x7f
|
||||
|
||||
/********************************************
|
||||
* Register Access
|
||||
*******************************************/
|
||||
#define REG_NONE_ACCESS 0
|
||||
#define REG_RD_ACCESS (1 << 0)
|
||||
#define REG_WR_ACCESS (1 << 1)
|
||||
#define AW8697_REG_MAX 0xff
|
||||
|
||||
const unsigned char aw8697_reg_access[AW8697_REG_MAX] = {
|
||||
[AW8697_REG_ID] = REG_RD_ACCESS,
|
||||
[AW8697_REG_SYSST] = REG_RD_ACCESS,
|
||||
[AW8697_REG_SYSINT] = REG_RD_ACCESS,
|
||||
[AW8697_REG_SYSINTM] = REG_RD_ACCESS | REG_WR_ACCESS,
|
||||
[AW8697_REG_SYSCTRL] = REG_RD_ACCESS | REG_WR_ACCESS,
|
||||
[AW8697_REG_GO] = REG_RD_ACCESS | REG_WR_ACCESS,
|
||||
[AW8697_REG_RTP_DATA] = REG_RD_ACCESS | REG_WR_ACCESS,
|
||||
[AW8697_REG_WAVSEQ1] = REG_RD_ACCESS | REG_WR_ACCESS,
|
||||
[AW8697_REG_WAVSEQ2] = REG_RD_ACCESS | REG_WR_ACCESS,
|
||||
[AW8697_REG_WAVSEQ3] = REG_RD_ACCESS | REG_WR_ACCESS,
|
||||
[AW8697_REG_WAVSEQ4] = REG_RD_ACCESS | REG_WR_ACCESS,
|
||||
[AW8697_REG_WAVSEQ5] = REG_RD_ACCESS | REG_WR_ACCESS,
|
||||
[AW8697_REG_WAVSEQ6] = REG_RD_ACCESS | REG_WR_ACCESS,
|
||||
[AW8697_REG_WAVSEQ7] = REG_RD_ACCESS | REG_WR_ACCESS,
|
||||
[AW8697_REG_WAVSEQ8] = REG_RD_ACCESS | REG_WR_ACCESS,
|
||||
[AW8697_REG_WAVLOOP1] = REG_RD_ACCESS | REG_WR_ACCESS,
|
||||
[AW8697_REG_WAVLOOP2] = REG_RD_ACCESS | REG_WR_ACCESS,
|
||||
[AW8697_REG_WAVLOOP3] = REG_RD_ACCESS | REG_WR_ACCESS,
|
||||
[AW8697_REG_WAVLOOP4] = REG_RD_ACCESS | REG_WR_ACCESS,
|
||||
[AW8697_REG_MAIN_LOOP] = REG_RD_ACCESS | REG_WR_ACCESS,
|
||||
[AW8697_REG_TRG1_WAV_P] = REG_RD_ACCESS | REG_WR_ACCESS,
|
||||
[AW8697_REG_TRG2_WAV_P] = REG_RD_ACCESS | REG_WR_ACCESS,
|
||||
[AW8697_REG_TRG3_WAV_P] = REG_RD_ACCESS | REG_WR_ACCESS,
|
||||
[AW8697_REG_TRG1_WAV_N] = REG_RD_ACCESS | REG_WR_ACCESS,
|
||||
[AW8697_REG_TRG2_WAV_N] = REG_RD_ACCESS | REG_WR_ACCESS,
|
||||
[AW8697_REG_TRG3_WAV_N] = REG_RD_ACCESS | REG_WR_ACCESS,
|
||||
[AW8697_REG_TRG_PRIO] = REG_RD_ACCESS | REG_WR_ACCESS,
|
||||
[AW8697_REG_TRG_CFG1] = REG_RD_ACCESS | REG_WR_ACCESS,
|
||||
[AW8697_REG_TRG_CFG2] = REG_RD_ACCESS | REG_WR_ACCESS,
|
||||
[AW8697_REG_DBGCTRL] = REG_RD_ACCESS | REG_WR_ACCESS,
|
||||
[AW8697_REG_BASE_ADDRH] = REG_RD_ACCESS | REG_WR_ACCESS,
|
||||
[AW8697_REG_BASE_ADDRL] = REG_RD_ACCESS | REG_WR_ACCESS,
|
||||
[AW8697_REG_FIFO_AEH] = REG_RD_ACCESS | REG_WR_ACCESS,
|
||||
[AW8697_REG_FIFO_AEL] = REG_RD_ACCESS | REG_WR_ACCESS,
|
||||
[AW8697_REG_FIFO_AFH] = REG_RD_ACCESS | REG_WR_ACCESS,
|
||||
[AW8697_REG_FIFO_AFL] = REG_RD_ACCESS | REG_WR_ACCESS,
|
||||
[AW8697_REG_WAKE_DLY] = REG_RD_ACCESS | REG_WR_ACCESS,
|
||||
[AW8697_REG_START_DLY] = REG_RD_ACCESS | REG_WR_ACCESS,
|
||||
[AW8697_REG_END_DLY_H] = REG_RD_ACCESS | REG_WR_ACCESS,
|
||||
[AW8697_REG_END_DLY_L] = REG_RD_ACCESS | REG_WR_ACCESS,
|
||||
[AW8697_REG_DATCTRL] = REG_RD_ACCESS | REG_WR_ACCESS,
|
||||
[AW8697_REG_PWMDEL] = REG_RD_ACCESS | REG_WR_ACCESS,
|
||||
[AW8697_REG_PWMPRC] = REG_RD_ACCESS | REG_WR_ACCESS,
|
||||
[AW8697_REG_PWMDBG] = REG_RD_ACCESS | REG_WR_ACCESS,
|
||||
[AW8697_REG_LDOCTRL] = REG_RD_ACCESS | REG_WR_ACCESS,
|
||||
[AW8697_REG_DBGSTAT] = REG_RD_ACCESS,
|
||||
[AW8697_REG_BSTDBG1] = REG_RD_ACCESS | REG_WR_ACCESS,
|
||||
[AW8697_REG_BSTDBG2] = REG_RD_ACCESS | REG_WR_ACCESS,
|
||||
[AW8697_REG_BSTDBG3] = REG_RD_ACCESS | REG_WR_ACCESS,
|
||||
[AW8697_REG_BSTCFG] = REG_RD_ACCESS | REG_WR_ACCESS,
|
||||
[AW8697_REG_ANADBG] = REG_RD_ACCESS | REG_WR_ACCESS,
|
||||
[AW8697_REG_ANACTRL] = REG_RD_ACCESS | REG_WR_ACCESS,
|
||||
[AW8697_REG_CPDBG] = REG_RD_ACCESS | REG_WR_ACCESS,
|
||||
[AW8697_REG_GLBDBG] = REG_RD_ACCESS | REG_WR_ACCESS,
|
||||
[AW8697_REG_DATDBG] = REG_RD_ACCESS | REG_WR_ACCESS,
|
||||
[AW8697_REG_BSTDBG4] = REG_RD_ACCESS | REG_WR_ACCESS,
|
||||
[AW8697_REG_BSTDBG5] = REG_RD_ACCESS | REG_WR_ACCESS,
|
||||
[AW8697_REG_BSTDBG6] = REG_RD_ACCESS | REG_WR_ACCESS,
|
||||
[AW8697_REG_HDRVDBG] = REG_RD_ACCESS | REG_WR_ACCESS,
|
||||
[AW8697_REG_PRLVL] = REG_RD_ACCESS | REG_WR_ACCESS,
|
||||
[AW8697_REG_PRTIME] = REG_RD_ACCESS | REG_WR_ACCESS,
|
||||
[AW8697_REG_RAMADDRH] = REG_RD_ACCESS | REG_WR_ACCESS,
|
||||
[AW8697_REG_RAMADDRL] = REG_RD_ACCESS | REG_WR_ACCESS,
|
||||
[AW8697_REG_RAMDATA] = REG_RD_ACCESS | REG_WR_ACCESS,
|
||||
[AW8697_REG_GLB_STATE] = REG_RD_ACCESS | REG_WR_ACCESS,
|
||||
[AW8697_REG_BST_AUTO] = REG_RD_ACCESS | REG_WR_ACCESS,
|
||||
[AW8697_REG_CONT_CTRL] = REG_RD_ACCESS | REG_WR_ACCESS,
|
||||
[AW8697_REG_F_PRE_H] = REG_RD_ACCESS | REG_WR_ACCESS,
|
||||
[AW8697_REG_F_PRE_L] = REG_RD_ACCESS | REG_WR_ACCESS,
|
||||
[AW8697_REG_TD_H] = REG_RD_ACCESS | REG_WR_ACCESS,
|
||||
[AW8697_REG_TD_L] = REG_RD_ACCESS | REG_WR_ACCESS,
|
||||
[AW8697_REG_TSET] = REG_RD_ACCESS | REG_WR_ACCESS,
|
||||
[AW8697_REG_TRIM_LRA] = REG_RD_ACCESS | REG_WR_ACCESS,
|
||||
[AW8697_REG_R_SPARE] = REG_RD_ACCESS | REG_WR_ACCESS,
|
||||
[AW8697_REG_D2SCFG] = REG_RD_ACCESS | REG_WR_ACCESS,
|
||||
[AW8697_REG_DETCTRL] = REG_RD_ACCESS | REG_WR_ACCESS,
|
||||
[AW8697_REG_RLDET] = REG_RD_ACCESS | REG_WR_ACCESS,
|
||||
[AW8697_REG_OSDET] = REG_RD_ACCESS | REG_WR_ACCESS,
|
||||
[AW8697_REG_VBATDET] = REG_RD_ACCESS | REG_WR_ACCESS,
|
||||
[AW8697_REG_TESTDET] = REG_RD_ACCESS | REG_WR_ACCESS,
|
||||
[AW8697_REG_DETLO] = REG_RD_ACCESS | REG_WR_ACCESS,
|
||||
[AW8697_REG_BEMFDBG] = REG_RD_ACCESS | REG_WR_ACCESS,
|
||||
[AW8697_REG_ADCTEST] = REG_RD_ACCESS | REG_WR_ACCESS,
|
||||
[AW8697_REG_BEMFTEST] = REG_RD_ACCESS | REG_WR_ACCESS,
|
||||
[AW8697_REG_F_LRA_F0_H] = REG_RD_ACCESS | REG_WR_ACCESS,
|
||||
[AW8697_REG_F_LRA_F0_L] = REG_RD_ACCESS | REG_WR_ACCESS,
|
||||
[AW8697_REG_F_LRA_CONT_H] = REG_RD_ACCESS | REG_WR_ACCESS,
|
||||
[AW8697_REG_F_LRA_CONT_L] = REG_RD_ACCESS | REG_WR_ACCESS,
|
||||
[AW8697_REG_WAIT_VOL_MP] = REG_RD_ACCESS | REG_WR_ACCESS,
|
||||
[AW8697_REG_WAIT_VOL_MN] = REG_RD_ACCESS | REG_WR_ACCESS,
|
||||
[AW8697_REG_BEMF_VOL_H] = REG_RD_ACCESS | REG_WR_ACCESS,
|
||||
[AW8697_REG_BEMF_VOL_L] = REG_RD_ACCESS | REG_WR_ACCESS,
|
||||
[AW8697_REG_ZC_THRSH_H] = REG_RD_ACCESS | REG_WR_ACCESS,
|
||||
[AW8697_REG_ZC_THRSH_L] = REG_RD_ACCESS | REG_WR_ACCESS,
|
||||
[AW8697_REG_BEMF_VTHH_H] = REG_RD_ACCESS | REG_WR_ACCESS,
|
||||
[AW8697_REG_BEMF_VTHH_L] = REG_RD_ACCESS | REG_WR_ACCESS,
|
||||
[AW8697_REG_BEMF_VTHL_H] = REG_RD_ACCESS | REG_WR_ACCESS,
|
||||
[AW8697_REG_BEMF_VTHL_L] = REG_RD_ACCESS | REG_WR_ACCESS,
|
||||
[AW8697_REG_BEMF_NUM] = REG_RD_ACCESS | REG_WR_ACCESS,
|
||||
[AW8697_REG_DRV_TIME] = REG_RD_ACCESS | REG_WR_ACCESS,
|
||||
[AW8697_REG_TIME_NZC] = REG_RD_ACCESS | REG_WR_ACCESS,
|
||||
[AW8697_REG_DRV_LVL] = REG_RD_ACCESS | REG_WR_ACCESS,
|
||||
[AW8697_REG_DRV_LVL_OV] = REG_RD_ACCESS | REG_WR_ACCESS,
|
||||
[AW8697_REG_NUM_F0_1] = REG_RD_ACCESS | REG_WR_ACCESS,
|
||||
[AW8697_REG_NUM_F0_2] = REG_RD_ACCESS | REG_WR_ACCESS,
|
||||
[AW8697_REG_NUM_F0_3] = REG_RD_ACCESS | REG_WR_ACCESS,
|
||||
};
|
||||
|
||||
/******************************************************
|
||||
* Register Detail
|
||||
*****************************************************/
|
||||
/* SYSST: reg0x01 */
|
||||
#define AW8697_BIT_SYSST_BSTERRS (1<<7)
|
||||
#define AW8697_BIT_SYSST_OVS (1<<6)
|
||||
#define AW8697_BIT_SYSST_UVLS (1<<5)
|
||||
#define AW8697_BIT_SYSST_FF_AES (1<<4)
|
||||
#define AW8697_BIT_SYSST_FF_AFS (1<<3)
|
||||
#define AW8697_BIT_SYSST_OCDS (1<<2)
|
||||
#define AW8697_BIT_SYSST_OTS (1<<1)
|
||||
#define AW8697_BIT_SYSST_DONES (1<<0)
|
||||
|
||||
/* SYSINT: reg0x02 */
|
||||
#define AW8697_BIT_SYSINT_BSTERRI (1<<7)
|
||||
#define AW8697_BIT_SYSINT_OVI (1<<6)
|
||||
#define AW8697_BIT_SYSINT_UVLI (1<<5)
|
||||
#define AW8697_BIT_SYSINT_FF_AEI (1<<4)
|
||||
#define AW8697_BIT_SYSINT_FF_AFI (1<<3)
|
||||
#define AW8697_BIT_SYSINT_OCDI (1<<2)
|
||||
#define AW8697_BIT_SYSINT_OTI (1<<1)
|
||||
#define AW8697_BIT_SYSINT_DONEI (1<<0)
|
||||
|
||||
/* SYSINTM: reg0x03 */
|
||||
#define AW8697_BIT_SYSINTM_BSTERR_MASK (~(1<<7))
|
||||
#define AW8697_BIT_SYSINTM_BSTERR_OFF (1<<7)
|
||||
#define AW8697_BIT_SYSINTM_BSTERR_EN (0<<7)
|
||||
#define AW8697_BIT_SYSINTM_OV_MASK (~(1<<6))
|
||||
#define AW8697_BIT_SYSINTM_OV_OFF (1<<6)
|
||||
#define AW8697_BIT_SYSINTM_OV_EN (0<<6)
|
||||
#define AW8697_BIT_SYSINTM_UVLO_MASK (~(1<<5))
|
||||
#define AW8697_BIT_SYSINTM_UVLO_OFF (1<<5)
|
||||
#define AW8697_BIT_SYSINTM_UVLO_EN (0<<5)
|
||||
#define AW8697_BIT_SYSINTM_FF_AE_MASK (~(1<<4))
|
||||
#define AW8697_BIT_SYSINTM_FF_AE_OFF (1<<4)
|
||||
#define AW8697_BIT_SYSINTM_FF_AE_EN (0<<4)
|
||||
#define AW8697_BIT_SYSINTM_FF_AF_MASK (~(1<<3))
|
||||
#define AW8697_BIT_SYSINTM_FF_AF_OFF (1<<3)
|
||||
#define AW8697_BIT_SYSINTM_FF_AF_EN (0<<3)
|
||||
#define AW8697_BIT_SYSINTM_OCD_MASK (~(1<<2))
|
||||
#define AW8697_BIT_SYSINTM_OCD_OFF (1<<2)
|
||||
#define AW8697_BIT_SYSINTM_OCD_EN (0<<2)
|
||||
#define AW8697_BIT_SYSINTM_OT_MASK (~(1<<1))
|
||||
#define AW8697_BIT_SYSINTM_OT_OFF (1<<1)
|
||||
#define AW8697_BIT_SYSINTM_OT_EN (0<<1)
|
||||
#define AW8697_BIT_SYSINTM_DONE_MASK (~(1<<0))
|
||||
#define AW8697_BIT_SYSINTM_DONE_OFF (1<<0)
|
||||
#define AW8697_BIT_SYSINTM_DONE_EN (0<<0)
|
||||
|
||||
/* SYSCTRL: reg0x04 */
|
||||
#define AW8697_BIT_SYSCTRL_WAVDAT_MODE_MASK (~(3<<6))
|
||||
#define AW8697_BIT_SYSCTRL_WAVDAT_MODE_4X (3<<6)
|
||||
#define AW8697_BIT_SYSCTRL_WAVDAT_MODE_2X (0<<6)
|
||||
#define AW8697_BIT_SYSCTRL_WAVDAT_MODE_1X (1<<6)
|
||||
#define AW8697_BIT_SYSCTRL_RAMINIT_MASK (~(1<<5))
|
||||
#define AW8697_BIT_SYSCTRL_RAMINIT_EN (1<<5)
|
||||
#define AW8697_BIT_SYSCTRL_RAMINIT_OFF (0<<5)
|
||||
#define AW8697_BIT_SYSCTRL_PLAY_MODE_MASK (~(3<<2))
|
||||
#define AW8697_BIT_SYSCTRL_PLAY_MODE_CONT (2<<2)
|
||||
#define AW8697_BIT_SYSCTRL_PLAY_MODE_RTP (1<<2)
|
||||
#define AW8697_BIT_SYSCTRL_PLAY_MODE_RAM (0<<2)
|
||||
#define AW8697_BIT_SYSCTRL_BST_MODE_MASK (~(1<<1))
|
||||
#define AW8697_BIT_SYSCTRL_BST_MODE_BOOST (1<<1)
|
||||
#define AW8697_BIT_SYSCTRL_BST_MODE_BYPASS (0<<1)
|
||||
#define AW8697_BIT_SYSCTRL_WORK_MODE_MASK (~(1<<0))
|
||||
#define AW8697_BIT_SYSCTRL_STANDBY (1<<0)
|
||||
#define AW8697_BIT_SYSCTRL_ACTIVE (0<<0)
|
||||
|
||||
/* GO: reg0x05 */
|
||||
#define AW8697_BIT_GO_MASK (~(1<<0))
|
||||
#define AW8697_BIT_GO_ENABLE (1<<0)
|
||||
#define AW8697_BIT_GO_DISABLE (0<<0)
|
||||
|
||||
/* WAVSEQ1: reg0x07 */
|
||||
#define AW8697_BIT_WAVSEQ1_WAIT (1<<7)
|
||||
#define AW8697_BIT_WAVSEQ1_WAV_FRM_SEQ1_MASK (~(127<<0))
|
||||
|
||||
/* WAVSEQ2: reg0x08 */
|
||||
#define AW8697_BIT_WAVSEQ2_WAIT (1<<7)
|
||||
#define AW8697_BIT_WAVSEQ2_WAV_FRM_SEQ2_MASK (~(127<<0))
|
||||
|
||||
/* WAVSEQ3: reg0x09 */
|
||||
#define AW8697_BIT_WAVSEQ3_WAIT (1<<7)
|
||||
#define AW8697_BIT_WAVSEQ3_WAV_FRM_SEQ3_MASK (~(127<<0))
|
||||
|
||||
/* WAVSEQ4: reg0x0a */
|
||||
#define AW8697_BIT_WAVSEQ4_WAIT (1<<7)
|
||||
#define AW8697_BIT_WAVSEQ4_WAV_FRM_SEQ4_MASK (~(127<<0))
|
||||
|
||||
/* WAVSEQ5: reg0x0b */
|
||||
#define AW8697_BIT_WAVSEQ5_WAIT (1<<7)
|
||||
#define AW8697_BIT_WAVSEQ5_WAV_FRM_SEQ5_MASK (~(127<<0))
|
||||
|
||||
/* WAVSEQ6: reg0x0c */
|
||||
#define AW8697_BIT_WAVSEQ6_WAIT (1<<7)
|
||||
#define AW8697_BIT_WAVSEQ6_WAV_FRM_SEQ6_MASK (~(127<<0))
|
||||
|
||||
/* WAVSEQ7: reg0x0d */
|
||||
#define AW8697_BIT_WAVSEQ7_WAIT (1<<7)
|
||||
#define AW8697_BIT_WAVSEQ7_WAV_FRM_SEQ7_MASK (~(127<<0))
|
||||
|
||||
/* WAVSEQ8: reg0x0e */
|
||||
#define AW8697_BIT_WAVSEQ8_WAIT (1<<7)
|
||||
#define AW8697_BIT_WAVSEQ8_WAV_FRM_SEQ8_MASK (~(127<<0))
|
||||
|
||||
/* WAVLOOP: */
|
||||
#define AW8697_BIT_WAVLOOP_SEQN_MASK (~(15<<4))
|
||||
#define AW8697_BIT_WAVLOOP_SEQNP1_MASK (~(15<<0))
|
||||
#define AW8697_BIT_WAVLOOP_INIFINITELY (15<<0)
|
||||
|
||||
/* WAVLOOP1: reg0x0f */
|
||||
#define AW8697_BIT_WAVLOOP1_SEQ1_MASK (~(15<<4))
|
||||
#define AW8697_BIT_WAVLOOP1_SEQ2_MASK (~(15<<0))
|
||||
|
||||
/* WAVLOOP2: reg0x10 */
|
||||
#define AW8697_BIT_WAVLOOP2_SEQ3_MASK (~(15<<4))
|
||||
#define AW8697_BIT_WAVLOOP2_SEQ4_MASK (~(15<<0))
|
||||
|
||||
/* WAVLOOP3: reg0x11 */
|
||||
#define AW8697_BIT_WAVLOOP3_SEQ5_MASK (~(15<<4))
|
||||
#define AW8697_BIT_WAVLOOP3_SEQ6_MASK (~(15<<0))
|
||||
|
||||
/* WAVLOOP4: reg0x12 */
|
||||
#define AW8697_BIT_WAVLOOP4_SEQ7_MASK (~(15<<4))
|
||||
#define AW8697_BIT_WAVLOOP4_SEQ8_MASK (~(15<<0))
|
||||
|
||||
/* PLAYPRIO: reg0x1a */
|
||||
#define AW8697_BIT_PLAYPRIO_GO_MASK (~(3<<6))
|
||||
#define AW8697_BIT_PLAYPRIO_TRIG3_MASK (~(3<<4))
|
||||
#define AW8697_BIT_PLAYPRIO_TRIG2_MASK (~(3<<2))
|
||||
#define AW8697_BIT_PLAYPRIO_TRIG1_MASK (~(3<<0))
|
||||
|
||||
/* TRGCFG1: reg0x1b */
|
||||
#define AW8697_BIT_TRGCFG1_TRG3_POLAR_MASK (~(1<<5))
|
||||
#define AW8697_BIT_TRGCFG1_TRG3_POLAR_NEG (1<<5)
|
||||
#define AW8697_BIT_TRGCFG1_TRG3_POLAR_POS (0<<5)
|
||||
#define AW8697_BIT_TRGCFG1_TRG3_EDGE_MASK (~(1<<4))
|
||||
#define AW8697_BIT_TRGCFG1_TRG3_EDGE_POS (1<<4)
|
||||
#define AW8697_BIT_TRGCFG1_TRG3_EDGE_POS_NEG (0<<4)
|
||||
#define AW8697_BIT_TRGCFG1_TRG2_POLAR_MASK (~(1<<3))
|
||||
#define AW8697_BIT_TRGCFG1_TRG2_POLAR_NEG (1<<3)
|
||||
#define AW8697_BIT_TRGCFG1_TRG2_POLAR_POS (0<<3)
|
||||
#define AW8697_BIT_TRGCFG1_TRG2_EDGE_MASK (~(1<<2))
|
||||
#define AW8697_BIT_TRGCFG1_TRG2_EDGE_POS (1<<2)
|
||||
#define AW8697_BIT_TRGCFG1_TRG2_EDGE_POS_NEG (0<<2)
|
||||
#define AW8697_BIT_TRGCFG1_TRG1_POLAR_MASK (~(1<<1))
|
||||
#define AW8697_BIT_TRGCFG1_TRG1_POLAR_NEG (1<<1)
|
||||
#define AW8697_BIT_TRGCFG1_TRG1_POLAR_POS (0<<1)
|
||||
#define AW8697_BIT_TRGCFG1_TRG1_EDGE_MASK (~(1<<0))
|
||||
#define AW8697_BIT_TRGCFG1_TRG1_EDGE_POS (1<<0)
|
||||
#define AW8697_BIT_TRGCFG1_TRG1_EDGE_POS_NEG (0<<0)
|
||||
|
||||
/* TRGCFG2: reg0x1c */
|
||||
#define AW8697_BIT_TRGCFG2_TRG3_ENABLE_MASK (~(1<<2))
|
||||
#define AW8697_BIT_TRGCFG2_TRG3_ENABLE (1<<2)
|
||||
#define AW8697_BIT_TRGCFG2_TRG3_DISABLE (0<<2)
|
||||
#define AW8697_BIT_TRGCFG2_TRG2_ENABLE_MASK (~(1<<1))
|
||||
#define AW8697_BIT_TRGCFG2_TRG2_ENABLE (1<<1)
|
||||
#define AW8697_BIT_TRGCFG2_TRG2_DISABLE (0<<1)
|
||||
#define AW8697_BIT_TRGCFG2_TRG1_ENABLE_MASK (~(1<<0))
|
||||
#define AW8697_BIT_TRGCFG2_TRG1_ENABLE (1<<0)
|
||||
#define AW8697_BIT_TRGCFG2_TRG1_DISABLE (0<<0)
|
||||
|
||||
/* DBGCTRL: reg0x20 */
|
||||
#define AW8697_BIT_DBGCTRL_INT_EDGE_MODE_MASK (~(1<<3))
|
||||
#define AW8697_BIT_DBGCTRL_INT_EDGE_MODE_POS (1<<3)
|
||||
#define AW8697_BIT_DBGCTRL_INT_EDGE_MODE_BOTH (0<<3)
|
||||
#define AW8697_BIT_DBGCTRL_INT_MODE_MASK (~(1<<2))
|
||||
#define AW8697_BIT_DBGCTRL_INT_MODE_EDGE (1<<2)
|
||||
#define AW8697_BIT_DBGCTRL_INT_MODE_LEVEL (0<<2)
|
||||
|
||||
/* DATCTRL: reg0x2b */
|
||||
#define AW8697_BIT_DATCTRL_FC_MASK (~(1<<6))
|
||||
#define AW8697_BIT_DATCTRL_FC_1000HZ (3<<6)
|
||||
#define AW8697_BIT_DATCTRL_FC_800HZ (3<<6)
|
||||
#define AW8697_BIT_DATCTRL_FC_600HZ (1<<6)
|
||||
#define AW8697_BIT_DATCTRL_FC_400HZ (0<<6)
|
||||
#define AW8697_BIT_DATCTRL_LPF_ENABLE_MASK (~(1<<5))
|
||||
#define AW8697_BIT_DATCTRL_LPF_ENABLE (1<<5)
|
||||
#define AW8697_BIT_DATCTRL_LPF_DISABLE (0<<5)
|
||||
#define AW8697_BIT_DATCTRL_WAKEMODE_ENABLE_MASK (~(1<<0))
|
||||
#define AW8697_BIT_DATCTRL_WAKEMODE_ENABLE (1<<0)
|
||||
#define AW8697_BIT_DATCTRL_WAKEMODE_DISABLE (0<<0)
|
||||
|
||||
/* PWMPRC: reg0x2d */
|
||||
#define AW8697_BIT_PWMPRC_PRC_MASK (~(1<<7))
|
||||
#define AW8697_BIT_PWMPRC_PRC_ENABLE (1<<7)
|
||||
#define AW8697_BIT_PWMPRC_PRC_DISABLE (0<<7)
|
||||
#define AW8697_BIT_PWMPRC_PRCTIME_MASK (~(0x7f<<0))
|
||||
|
||||
/* PWMDBG: reg0x2e */
|
||||
#define AW8697_BIT_PWMDBG_PWM_MODE_MASK (~(3<<5))
|
||||
#define AW8697_BIT_PWMDBG_PWM_12K (3<<5)
|
||||
#define AW8697_BIT_PWMDBG_PWM_24K (2<<5)
|
||||
#define AW8697_BIT_PWMDBG_PWM_48K (0<<5)
|
||||
|
||||
/* DBGST: reg0x30 */
|
||||
#define AW8697_BIT_DBGSTAT_FF_EMPTY (1<<0)
|
||||
/* BSTCFG: reg0x34 */
|
||||
#define AW8697_BIT_BSTCFG_PEAKCUR_MASK (~(7<<0))
|
||||
#define AW8697_BIT_BSTCFG_PEAKCUR_4A (7<<0)
|
||||
#define AW8697_BIT_BSTCFG_PEAKCUR_3P75A (6<<0)
|
||||
#define AW8697_BIT_BSTCFG_PEAKCUR_3P5A (5<<0)
|
||||
#define AW8697_BIT_BSTCFG_PEAKCUR_3P25A (4<<0)
|
||||
#define AW8697_BIT_BSTCFG_PEAKCUR_3A (3<<0)
|
||||
#define AW8697_BIT_BSTCFG_PEAKCUR_2P5A (2<<0)
|
||||
#define AW8697_BIT_BSTCFG_PEAKCUR_2A (1<<0)
|
||||
#define AW8697_BIT_BSTCFG_PEAKCUR_1P5A (0<<0)
|
||||
|
||||
/* ANADBG: reg0x35 */
|
||||
#define AW8697_BIT_ANADBG_IOC_MASK (~(3<<2))
|
||||
#define AW8697_BIT_ANADBG_IOC_4P65A (3<<2)
|
||||
#define AW8697_BIT_ANADBG_IOC_4P15A (2<<2)
|
||||
#define AW8697_BIT_ANADBG_IOC_3P65A (1<<2)
|
||||
#define AW8697_BIT_ANADBG_IOC_3P15A (0<<2)
|
||||
|
||||
/* ANACTRL: reg0x36 */
|
||||
#define AW8697_BIT_ANACTRL_LRA_SRC_MASK (~(1<<5))
|
||||
#define AW8697_BIT_ANACTRL_LRA_SRC_REG (1<<5)
|
||||
#define AW8697_BIT_ANACTRL_LRA_SRC_EFUSE (0<<5)
|
||||
#define AW8697_BIT_ANACTRL_HD_PD_MASK (~(1<<3))
|
||||
#define AW8697_BIT_ANACTRL_HD_PD_EN (1<<3)
|
||||
#define AW8697_BIT_ANACTRL_HD_HZ_EN (0<<3)
|
||||
|
||||
/* BSTDBG4: reg0x3a */
|
||||
#define AW8697_BIT_BSTDBG4_BSTVOL_MASK (~(31<<1))
|
||||
|
||||
/* PRLVL: reg0x3e */
|
||||
#define AW8697_BIT_PRLVL_PR_MASK (~(1<<7))
|
||||
#define AW8697_BIT_PRLVL_PR_ENABLE (1<<7)
|
||||
#define AW8697_BIT_PRLVL_PR_DISABLE (0<<7)
|
||||
#define AW8697_BIT_PRLVL_PRLVL_MASK (~(0x7f<<0))
|
||||
|
||||
/*PRTIME: reg0x3f */
|
||||
#define AW8697_BIT_PRTIME_PRTIME_MASK (~(0xff<<0))
|
||||
|
||||
/* BST_AUTO: reg0x47 */
|
||||
#define AW8697_BIT_BST_AUTO_BST_AUTOSW_MASK (~(1<<2))
|
||||
#define AW8697_BIT_BST_AUTO_BST_AUTOMATIC_BOOST (1<<2)
|
||||
#define AW8697_BIT_BST_AUTO_BST_MANUAL_BOOST (0<<2)
|
||||
#define AW8697_BIT_BST_AUTO_BST_RTP_MASK (~(1<<1))
|
||||
#define AW8697_BIT_BST_AUTO_BST_RTP_ENABLE (1<<1)
|
||||
#define AW8697_BIT_BST_AUTO_BST_RTP_DISABLE (0<<1)
|
||||
#define AW8697_BIT_BST_AUTO_BST_RAM_MASK (~(1<<0))
|
||||
#define AW8697_BIT_BST_AUTO_BST_RAM_ENABLE (1<<0)
|
||||
#define AW8697_BIT_BST_AUTO_BST_RAM_DISABLE (0<<0)
|
||||
|
||||
/* CONT_CTRL: reg0x48 */
|
||||
#define AW8697_BIT_CONT_CTRL_ZC_DETEC_MASK (~(1<<7))
|
||||
#define AW8697_BIT_CONT_CTRL_ZC_DETEC_ENABLE (1<<7)
|
||||
#define AW8697_BIT_CONT_CTRL_ZC_DETEC_DISABLE (0<<7)
|
||||
#define AW8697_BIT_CONT_CTRL_WAIT_PERIOD_MASK (~(3<<5))
|
||||
#define AW8697_BIT_CONT_CTRL_WAIT_8PERIOD (3<<5)
|
||||
#define AW8697_BIT_CONT_CTRL_WAIT_4PERIOD (2<<5)
|
||||
#define AW8697_BIT_CONT_CTRL_WAIT_2PERIOD (1<<5)
|
||||
#define AW8697_BIT_CONT_CTRL_WAIT_1PERIOD (0<<5)
|
||||
#define AW8697_BIT_CONT_CTRL_MODE_MASK (~(1<<4))
|
||||
#define AW8697_BIT_CONT_CTRL_BY_DRV_TIME (1<<4)
|
||||
#define AW8697_BIT_CONT_CTRL_BY_GO_SIGNAL (0<<4)
|
||||
#define AW8697_BIT_CONT_CTRL_EN_CLOSE_MASK (~(1<<3))
|
||||
#define AW8697_BIT_CONT_CTRL_CLOSE_PLAYBACK (1<<3)
|
||||
#define AW8697_BIT_CONT_CTRL_OPEN_PLAYBACK (0<<3)
|
||||
#define AW8697_BIT_CONT_CTRL_F0_DETECT_MASK (~(1<<2))
|
||||
#define AW8697_BIT_CONT_CTRL_F0_DETECT_ENABLE (1<<2)
|
||||
#define AW8697_BIT_CONT_CTRL_F0_DETECT_DISABLE (0<<2)
|
||||
#define AW8697_BIT_CONT_CTRL_O2C_MASK (~(1<<1))
|
||||
#define AW8697_BIT_CONT_CTRL_O2C_ENABLE (1<<1)
|
||||
#define AW8697_BIT_CONT_CTRL_O2C_DISABLE (0<<1)
|
||||
#define AW8697_BIT_CONT_CTRL_AUTO_BRK_MASK (~(1<<0))
|
||||
#define AW8697_BIT_CONT_CTRL_AUTO_BRK_ENABLE (1<<0)
|
||||
#define AW8697_BIT_CONT_CTRL_AUTO_BRK_DISABLE (0<<0)
|
||||
|
||||
/* D2SCFG: reg0x5e */
|
||||
#define AW8697_BIT_D2SCFG_CLK_ADC_MASK (~(7<<5))
|
||||
#define AW8697_BIT_D2SCFG_CLK_ASC_0P09375MHZ (7<<5)
|
||||
#define AW8697_BIT_D2SCFG_CLK_ASC_0P1875MHZ (6<<5)
|
||||
#define AW8697_BIT_D2SCFG_CLK_ASC_0P375MHZ (5<<5)
|
||||
#define AW8697_BIT_D2SCFG_CLK_ASC_0P75MHZ (4<<5)
|
||||
#define AW8697_BIT_D2SCFG_CLK_ASC_1P5MHZ (3<<5)
|
||||
#define AW8697_BIT_D2SCFG_CLK_ASC_3MHZ (2<<5)
|
||||
#define AW8697_BIT_D2SCFG_CLK_ASC_6MHZ (1<<5)
|
||||
#define AW8697_BIT_D2SCFG_CLK_ASC_12MHZ (0<<5)
|
||||
|
||||
/* DETCTRL: reg0x5f */
|
||||
#define AW8697_BIT_DETCTRL_RL_OS_MASK (~(1<<6))
|
||||
#define AW8697_BIT_DETCTRL_RL_DETECT (1<<6)
|
||||
#define AW8697_BIT_DETCTRL_OS_DETECT (0<<6)
|
||||
#define AW8697_BIT_DETCTRL_PROTECT_MASK (~(1<<5))
|
||||
#define AW8697_BIT_DETCTRL_PROTECT_NO_ACTION (1<<5)
|
||||
#define AW8697_BIT_DETCTRL_PROTECT_SHUTDOWN (0<<5)
|
||||
#define AW8697_BIT_DETCTRL_ADO_SLOT_MODE_MASK (~(1<<4))
|
||||
#define AW8697_BIT_DETCTRL_ADO_SLOT_MODE_ENABLE (1<<4)
|
||||
#define AW8697_BIT_DETCTRL_ADO_SLOT_MODE_DISABLE (0<<4)
|
||||
#define AW8697_BIT_DETCTRL_VBAT_GO_MASK (~(1<<1))
|
||||
#define AW8697_BIT_DETCTRL_VABT_GO_ENABLE (1<<1)
|
||||
#define AW8697_BIT_DETCTRL_VBAT_GO_DISBALE (0<<1)
|
||||
#define AW8697_BIT_DETCTRL_DIAG_GO_MASK (~(1<<0))
|
||||
#define AW8697_BIT_DETCTRL_DIAG_GO_ENABLE (1<<0)
|
||||
#define AW8697_BIT_DETCTRL_DIAG_GO_DISABLE (0<<0)
|
||||
|
||||
/* ADCTEST: reg0x66 */
|
||||
#define AW8697_BIT_ADCTEST_VBAT_MODE_MASK (~(1<<6))
|
||||
#define AW8697_BIT_ADCTEST_VBAT_HW_COMP (1<<6)
|
||||
#define AW8697_BIT_ADCTEST_VBAT_SW_COMP (0<<6)
|
||||
|
||||
/* BEMF_NUM: reg0x78 */
|
||||
#define AW8697_BIT_BEMF_NUM_BRK_MASK (~(15<<0))
|
||||
|
||||
#endif
|
||||
215
drivers/input/misc/aw8697_haptic/ringbuffer.c
Normal file
215
drivers/input/misc/aw8697_haptic/ringbuffer.c
Normal file
@@ -0,0 +1,215 @@
|
||||
/*
|
||||
* reader shoule NEVER block !!!, if no data is avaliable, just return zero
|
||||
* writer will block if there is no space, and wakend up by reader or force exit
|
||||
* there is 1 writer and 1 reader for each buffer, so no lock is used
|
||||
* writer shoule read rd_index to check if free size is enought, and then fill this buffer update wr_index
|
||||
* reader shoule read wr_index to check if avaliable size is enought, and then read the buffer and update rd_index
|
||||
* empty: wr_index==rd_index
|
||||
* full: (wr_index +1) % BUFFER_SIZE == rd_index
|
||||
* total avaliable size is BUFFER_SIZE -1
|
||||
*/
|
||||
#define DEBUG
|
||||
#include <linux/errno.h>
|
||||
#include "ringbuffer.h"
|
||||
|
||||
#define MIN(x, y) ((x) < (y) ? (x) : (y))
|
||||
|
||||
#define BUFFER_SIZE (1024 * 8 + 1)
|
||||
|
||||
struct rb {
|
||||
char *gbuffer;
|
||||
atomic_t wr_index;
|
||||
atomic_t rd_index;
|
||||
atomic_t eof;
|
||||
volatile int32_t aval_size; // avalibale to write size.
|
||||
atomic_t buf_condition, exit;
|
||||
wait_queue_head_t wait_q;
|
||||
};
|
||||
|
||||
struct rb *grb;
|
||||
|
||||
int32_t get_free_size(int32_t tail, int32_t head)
|
||||
{
|
||||
if (head == tail)
|
||||
return BUFFER_SIZE - 1;
|
||||
else if (head < tail)
|
||||
return (head + BUFFER_SIZE - 1 - tail);
|
||||
else
|
||||
return(head - tail - 1);
|
||||
}
|
||||
|
||||
int write_rb(const char *data, int32_t size)
|
||||
{
|
||||
int32_t tail = atomic_read(&grb->wr_index);
|
||||
int32_t head = atomic_read(&grb->rd_index);
|
||||
int32_t part;
|
||||
int32_t ret;
|
||||
grb->aval_size = get_free_size(tail, head);
|
||||
|
||||
pr_debug("write write index %d, read index %d, free size %d", tail, head, grb->aval_size);
|
||||
|
||||
while ((grb->aval_size < size) && (!atomic_read(&grb->exit))) {
|
||||
pr_debug("no space avaliable");
|
||||
pr_info("%s goint to waiting irq exit\n", __func__);
|
||||
ret = wait_event_interruptible(grb->wait_q, atomic_read(&grb->buf_condition) == 1);
|
||||
if (ret == -ERESTARTSYS) {
|
||||
pr_err("%s wake up by signal return erro\n", __func__);
|
||||
return ret;
|
||||
}
|
||||
|
||||
atomic_set(&grb->buf_condition, 0);
|
||||
tail = atomic_read(&grb->wr_index);
|
||||
head = atomic_read(&grb->rd_index);
|
||||
grb->aval_size = get_free_size(tail, head);
|
||||
}
|
||||
if (atomic_read(&grb->exit) == 1) {
|
||||
pr_debug("exit write_rb");
|
||||
return -EPERM;
|
||||
}
|
||||
|
||||
part = BUFFER_SIZE - tail;
|
||||
if (part < size) {
|
||||
memcpy(grb->gbuffer + tail, data, part);
|
||||
memcpy(grb->gbuffer, data + part, size - part);
|
||||
tail = size - part;
|
||||
} else {
|
||||
memcpy(grb->gbuffer + tail, data, size);
|
||||
tail += size;
|
||||
if (tail >= BUFFER_SIZE)
|
||||
tail = tail % BUFFER_SIZE;
|
||||
}
|
||||
atomic_set(&grb->wr_index, tail);
|
||||
grb->aval_size = get_free_size(tail, head);
|
||||
pr_debug("after write %d, write index %d, read index %d, aval_size %d", size, tail, head, grb->aval_size);
|
||||
return size;
|
||||
}
|
||||
|
||||
int read_rb(char *data, int32_t size)
|
||||
{
|
||||
int32_t tail;
|
||||
int32_t head;
|
||||
int32_t filled_size;
|
||||
void *buf;
|
||||
int32_t read_bytes, part;
|
||||
buf = data;
|
||||
|
||||
pr_debug("read_rb data:%p, size %d", data, (int)size);
|
||||
|
||||
tail = atomic_read(&grb->wr_index);
|
||||
head = atomic_read(&grb->rd_index);
|
||||
grb->aval_size = get_free_size(tail, head);
|
||||
filled_size = BUFFER_SIZE - 1 - grb->aval_size; // aready write size.
|
||||
|
||||
pr_debug("write index %d, read index %d, filled size %d", tail, head, filled_size);
|
||||
read_bytes = MIN (size, filled_size);
|
||||
if (size > filled_size)
|
||||
pr_debug("buffer underrun , req size %d, filled size %d", size, filled_size);
|
||||
part = BUFFER_SIZE - head;
|
||||
if (part < read_bytes) {
|
||||
memcpy(buf, grb->gbuffer + head, part);
|
||||
memcpy((char *)buf + part, grb->gbuffer, read_bytes - part);
|
||||
head = read_bytes - part;
|
||||
} else {
|
||||
memcpy(buf, grb->gbuffer + head, read_bytes);
|
||||
head += read_bytes;
|
||||
if (head >= BUFFER_SIZE)
|
||||
head = head % BUFFER_SIZE;
|
||||
}
|
||||
atomic_set(&grb->rd_index, head);
|
||||
grb->aval_size = get_free_size(tail, head);
|
||||
|
||||
//add wakeup here
|
||||
atomic_set(&grb->buf_condition, 1);
|
||||
wake_up_interruptible(&grb->wait_q);
|
||||
pr_debug("read_rb: after read %d write index %d, read index %d, aval_size %d", read_bytes, tail, head, grb->aval_size);
|
||||
|
||||
return atomic_read(&grb->eof) ? read_bytes : size;
|
||||
}
|
||||
|
||||
int get_rb_free_size(void)
|
||||
{
|
||||
int32_t tail = atomic_read(&grb->wr_index);
|
||||
int32_t head = atomic_read(&grb->rd_index);
|
||||
grb->aval_size = get_free_size(tail, head);
|
||||
return grb->aval_size;
|
||||
}
|
||||
|
||||
int get_rb_avalible_size(void)
|
||||
{
|
||||
return BUFFER_SIZE - 1 - get_rb_free_size();
|
||||
}
|
||||
|
||||
int get_rb_max_size(void)
|
||||
{
|
||||
return BUFFER_SIZE - 1;
|
||||
}
|
||||
|
||||
void rb_force_exit(void)
|
||||
{
|
||||
pr_debug("rb force exit");
|
||||
atomic_set(&grb->exit, 1);
|
||||
atomic_set(&grb->buf_condition, 1);
|
||||
wake_up_interruptible(&grb->wait_q);
|
||||
}
|
||||
|
||||
void rb_end(void)
|
||||
{
|
||||
atomic_set(&grb->eof, 1);
|
||||
}
|
||||
|
||||
int rb_shoule_exit(void)
|
||||
{
|
||||
return atomic_read(&grb->eof) || atomic_read(&grb->exit);
|
||||
}
|
||||
|
||||
int create_rb(void)
|
||||
{
|
||||
int32_t tail;
|
||||
int32_t head;
|
||||
grb = kzalloc(sizeof(struct rb), GFP_KERNEL);
|
||||
if (grb == NULL) {
|
||||
goto err;;
|
||||
}
|
||||
grb->gbuffer = kzalloc(BUFFER_SIZE, GFP_KERNEL);
|
||||
if (grb->gbuffer == NULL) {
|
||||
goto err;
|
||||
}
|
||||
|
||||
rb_init();
|
||||
|
||||
init_waitqueue_head(&grb->wait_q);
|
||||
tail = atomic_read(&grb->wr_index);
|
||||
head = atomic_read(&grb->rd_index);
|
||||
grb->aval_size = get_free_size(tail, head);
|
||||
|
||||
return 0;
|
||||
err:
|
||||
if (grb)
|
||||
kfree(grb);
|
||||
if (grb->gbuffer)
|
||||
kfree(grb->gbuffer);
|
||||
return -EPERM;
|
||||
}
|
||||
|
||||
void rb_init(void)
|
||||
{
|
||||
pr_debug("rb init");
|
||||
atomic_set(&grb->wr_index, 0);
|
||||
atomic_set(&grb->rd_index, 0);
|
||||
atomic_set(&grb->buf_condition, 0);
|
||||
atomic_set(&grb->exit, 0);
|
||||
atomic_set(&grb->eof, 0);
|
||||
}
|
||||
|
||||
int release_rb(void)
|
||||
{
|
||||
if (grb != NULL) {
|
||||
if (grb->gbuffer) {
|
||||
kfree(grb->gbuffer);
|
||||
grb->gbuffer = NULL;
|
||||
}
|
||||
kfree(grb);
|
||||
grb = NULL;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
35
drivers/input/misc/aw8697_haptic/ringbuffer.h
Normal file
35
drivers/input/misc/aw8697_haptic/ringbuffer.h
Normal file
@@ -0,0 +1,35 @@
|
||||
/*
|
||||
* reader shoule NEVER block !!!, if no data is avaliable, just return zero
|
||||
* writer will block if there is no space, and wakend up by reader or force exit
|
||||
* there is 1 writer and 1 reader for each buffer, so no lock is used
|
||||
* writer shoule read rd_index to check if free size is enought, and then fill this buffer update wr_index
|
||||
* reader shoule read wr_index to check if avaliable size is enought, and then read the buffer and update rd_index
|
||||
* empty: wr_index==rd_index
|
||||
* full: (wr_index +1) % BUFFER_SIZE == rd_index
|
||||
* total avaliable size is BUFFER_SIZE -1
|
||||
*/
|
||||
|
||||
#ifndef _RINGBUFFER_H_
|
||||
#define _RINGBUFFER_H_
|
||||
|
||||
#include <linux/timer.h>
|
||||
#include <linux/workqueue.h>
|
||||
#include <linux/mutex.h>
|
||||
#include <linux/atomic.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/sched.h>
|
||||
|
||||
|
||||
int write_rb(const char *data, int32_t size);
|
||||
int read_rb(char *data, int32_t size) ;
|
||||
int get_rb_free_size(void);
|
||||
int get_rb_max_size(void);
|
||||
void rb_force_exit(void);
|
||||
void rb_end(void);
|
||||
int rb_shoule_exit(void);
|
||||
int create_rb(void) ;
|
||||
void rb_init(void);
|
||||
int release_rb(void);
|
||||
int get_rb_avalible_size(void);
|
||||
#endif
|
||||
@@ -137,6 +137,7 @@
|
||||
#define HAP_CFG_AUTORES_CFG_REG 0x63
|
||||
#define AUTORES_EN_BIT BIT(7)
|
||||
#define AUTORES_EN_DLY_MASK GENMASK(5, 2)
|
||||
#define AUTORES_EN_DLY_6_CYCLE 0xc
|
||||
#define AUTORES_EN_DLY(cycles) ((cycles) * 2)
|
||||
#define AUTORES_EN_DLY_6_CYCLES AUTORES_EN_DLY(6)
|
||||
#define AUTORES_EN_DLY_SHIFT 2
|
||||
@@ -672,22 +673,22 @@ static void __dump_effects(struct haptics_chip *chip)
|
||||
if (!effect)
|
||||
return;
|
||||
|
||||
dev_dbg(chip->dev, "effect %d\n", effect->id);
|
||||
dev_dbg(chip->dev, "vmax_mv = %d\n", effect->vmax_mv);
|
||||
dev_info(chip->dev, "effect %d\n", effect->id);
|
||||
dev_info(chip->dev, "vmax_mv = %d\n", effect->vmax_mv);
|
||||
if (effect->pattern) {
|
||||
for (j = 0; j < SAMPLES_PER_PATTERN; j++) {
|
||||
sample = &effect->pattern->samples[j];
|
||||
dev_dbg(chip->dev, "pattern = %d, period = %s, f_lra_x2 = %d\n",
|
||||
dev_info(chip->dev, "pattern = %d, period = %s, f_lra_x2 = %d\n",
|
||||
sample->amplitude,
|
||||
period_str[sample->period],
|
||||
sample->f_lra_x2);
|
||||
}
|
||||
|
||||
dev_dbg(chip->dev, "pattern play_rate_us = %d\n",
|
||||
dev_info(chip->dev, "pattern play_rate_us = %d\n",
|
||||
effect->pattern->play_rate_us);
|
||||
dev_dbg(chip->dev, "pattern play_length_us = %d\n",
|
||||
dev_info(chip->dev, "pattern play_length_us = %d\n",
|
||||
effect->pattern->play_length_us);
|
||||
dev_dbg(chip->dev, "pattern preload = %d\n",
|
||||
dev_info(chip->dev, "pattern preload = %d\n",
|
||||
effect->pattern->preload);
|
||||
}
|
||||
|
||||
@@ -704,11 +705,11 @@ static void __dump_effects(struct haptics_chip *chip)
|
||||
pos += scnprintf(str + pos, size - pos, "%d ",
|
||||
(s8)effect->fifo->samples[j]);
|
||||
|
||||
dev_dbg(chip->dev, "%s\n", str);
|
||||
dev_info(chip->dev, "%s\n", str);
|
||||
kfree(str);
|
||||
dev_dbg(chip->dev, "FIFO data play rate: %s\n",
|
||||
dev_info(chip->dev, "FIFO data play rate: %s\n",
|
||||
period_str[effect->fifo->period_per_s]);
|
||||
dev_dbg(chip->dev, "FIFO data play length: %dus\n",
|
||||
dev_info(chip->dev, "FIFO data play length: %dus\n",
|
||||
effect->fifo->play_length_us);
|
||||
}
|
||||
|
||||
@@ -725,16 +726,16 @@ static void __dump_effects(struct haptics_chip *chip)
|
||||
pos += scnprintf(str + pos, size - pos, "%#x ",
|
||||
effect->brake->samples[j]);
|
||||
|
||||
dev_dbg(chip->dev, "%s\n", str);
|
||||
dev_info(chip->dev, "%s\n", str);
|
||||
kfree(str);
|
||||
dev_dbg(chip->dev, "brake mode: %s\n",
|
||||
dev_info(chip->dev, "brake mode: %s\n",
|
||||
brake_str[effect->brake->mode]);
|
||||
dev_dbg(chip->dev, "brake play length: %dus\n",
|
||||
dev_info(chip->dev, "brake play length: %dus\n",
|
||||
effect->brake->play_length_us);
|
||||
}
|
||||
|
||||
dev_dbg(chip->dev, "pattern src: %s\n", src_str[effect->src]);
|
||||
dev_dbg(chip->dev, "auto resonance %s\n",
|
||||
dev_info(chip->dev, "pattern src: %s\n", src_str[effect->src]);
|
||||
dev_info(chip->dev, "auto resonance %s\n",
|
||||
effect->auto_res_disable ?
|
||||
"disabled" : "enabled");
|
||||
}
|
||||
@@ -1008,6 +1009,12 @@ static int haptics_get_closeloop_lra_period_v2(
|
||||
bool auto_res_done;
|
||||
u64 tmp;
|
||||
int rc;
|
||||
#ifdef QCOM_HAPTIC_F0_PROTECT
|
||||
//protect low rate of xbl f0 abnormal for k9 only
|
||||
int f0_mix, f0_max, f0_default, f0_cnt;
|
||||
int rc1, rc2, rc3, rc4;
|
||||
struct device_node *node = chip->dev->of_node;
|
||||
#endif
|
||||
|
||||
/* read RC_CLK_CAL enabling mode */
|
||||
rc = haptics_read(chip, chip->cfg_addr_base,
|
||||
@@ -1019,7 +1026,7 @@ static int haptics_get_closeloop_lra_period_v2(
|
||||
/* read auto resonance calibration result */
|
||||
if (in_boot && (chip->pmic_type == PM8350B)) {
|
||||
if (chip->hap_cfg_nvmem == NULL) {
|
||||
dev_dbg(chip->dev, "nvmem device for hap_cfg is not defined\n");
|
||||
dev_info(chip->dev, "nvmem device for hap_cfg is not defined\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
@@ -1062,13 +1069,13 @@ static int haptics_get_closeloop_lra_period_v2(
|
||||
tlra_cl_err_sts =
|
||||
((val[0] & TLRA_CL_ERR_MSB_MASK) << 8) | val[1];
|
||||
|
||||
dev_dbg(chip->dev, "rc_clk_cal = %u, auto_res_done = %d\n",
|
||||
dev_info(chip->dev, "rc_clk_cal = %u, auto_res_done = %d\n",
|
||||
rc_clk_cal, auto_res_done);
|
||||
|
||||
if (rc_clk_cal == CAL_RC_CLK_DISABLED_VAL && !auto_res_done) {
|
||||
/* TLRA_CL_ERR(us) = TLRA_CL_ERR_STS * 1.667 us */
|
||||
tmp = tlra_cl_err_sts * TLRA_AUTO_RES_ERR_NO_CAL_STEP_PSEC;
|
||||
dev_dbg(chip->dev, "tlra_cl_err_sts = %#x\n", tlra_cl_err_sts);
|
||||
dev_info(chip->dev, "tlra_cl_err_sts = %#x\n", tlra_cl_err_sts);
|
||||
config->cl_t_lra_us = div_u64(tmp, 1000000);
|
||||
} else if (rc_clk_cal == CAL_RC_CLK_DISABLED_VAL && auto_res_done) {
|
||||
/*
|
||||
@@ -1076,7 +1083,7 @@ static int haptics_get_closeloop_lra_period_v2(
|
||||
* TLRA_AUTO_RES(us) = CAL_TLRA_CL_STS_NO_CAL * 3.333 us
|
||||
*/
|
||||
tmp = cal_tlra_cl_sts * TLRA_AUTO_RES_NO_CAL_STEP_PSEC;
|
||||
dev_dbg(chip->dev, "cal_tlra_cl_sts = %#x\n", cal_tlra_cl_sts);
|
||||
dev_info(chip->dev, "cal_tlra_cl_sts = %#x\n", cal_tlra_cl_sts);
|
||||
config->cl_t_lra_us = div_u64(tmp, 1000000);
|
||||
} else if (rc_clk_cal == CAL_RC_CLK_AUTO_VAL && !auto_res_done) {
|
||||
/*
|
||||
@@ -1092,7 +1099,7 @@ static int haptics_get_closeloop_lra_period_v2(
|
||||
return rc;
|
||||
|
||||
tlra_ol = (val[0] & TLRA_OL_MSB_MASK) << 8 | val[1];
|
||||
dev_dbg(chip->dev, "tlra_ol = %#x, tlra_cl_err_sts = %#x, cal_tlra_cl_sts = %#x\n",
|
||||
dev_info(chip->dev, "tlra_ol = %#x, tlra_cl_err_sts = %#x, cal_tlra_cl_sts = %#x\n",
|
||||
tlra_ol, tlra_cl_err_sts, cal_tlra_cl_sts);
|
||||
|
||||
tmp = tlra_cl_err_sts * tlra_ol;
|
||||
@@ -1140,7 +1147,7 @@ static int haptics_get_closeloop_lra_period_v2(
|
||||
last_good_tlra_cl_sts =
|
||||
((val[0] & LAST_GOOD_TLRA_CL_MSB_MASK) << 8) | val[1];
|
||||
|
||||
dev_dbg(chip->dev, "last_good_tlra_cl_sts = %#x, cal_tlra_cl_sts = %#x\n",
|
||||
dev_info(chip->dev, "last_good_tlra_cl_sts = %#x, cal_tlra_cl_sts = %#x\n",
|
||||
last_good_tlra_cl_sts, cal_tlra_cl_sts);
|
||||
|
||||
tmp = last_good_tlra_cl_sts * last_good_tlra_cl_sts;
|
||||
@@ -1162,6 +1169,39 @@ static int haptics_get_closeloop_lra_period_v2(
|
||||
tmp = div_u64(tmp, last_good_tlra_cl_sts);
|
||||
tmp = div_u64(tmp, 293);
|
||||
config->rc_clk_cal_count = div_u64(tmp, config->t_lra_us);
|
||||
#ifdef QCOM_HAPTIC_F0_PROTECT
|
||||
//protect low rate of xbl f0 abnormal for k9 only
|
||||
if(in_boot){
|
||||
u32 xbl_f0 = USEC_PER_SEC / config->cl_t_lra_us;
|
||||
dev_err(chip->dev, "xbl f0 =%d \n", xbl_f0);
|
||||
rc1 = of_property_read_u32(node, "qcom,lra-f0-min", &f0_mix);
|
||||
if (rc1 < 0) {
|
||||
dev_err(chip->dev, "lra-f0-min failed, rc=%d\n", rc);
|
||||
}
|
||||
rc2 = of_property_read_u32(node, "qcom,lra-f0-max", &f0_max);
|
||||
if (rc2 < 0) {
|
||||
dev_err(chip->dev, "lra-f0-max failed, rc=%d\n", rc);
|
||||
}
|
||||
rc3 = of_property_read_u32(node, "qcom,lra-f0-default", &f0_default);
|
||||
if (rc3 < 0) {
|
||||
dev_err(chip->dev, "lra-f0-default failed, rc=%d\n", rc);
|
||||
}
|
||||
rc4 = of_property_read_u32(node, "qcom,lra-f0-cal-count", &f0_cnt);
|
||||
if (rc4 < 0) {
|
||||
dev_err(chip->dev, "lra-f0-cal-count failed, rc=%d\n", rc);
|
||||
}
|
||||
if (rc1 >= 0 && rc2 >= 0 && rc3 >= 0 && rc4 >= 0) {
|
||||
if (xbl_f0 > f0_max || xbl_f0 < f0_mix) {
|
||||
dev_err(chip->dev, "xbl f0 abnormal: %d ~ 0x%x use default: %d ~ 0x%x f0:%d - %d after boot\n",
|
||||
xbl_f0, config->rc_clk_cal_count, f0_default, f0_cnt, f0_mix, f0_max);
|
||||
config->cl_t_lra_us = USEC_PER_SEC /f0_default;
|
||||
config->rc_clk_cal_count = f0_cnt;
|
||||
}
|
||||
} else {
|
||||
dev_err(chip->dev, "lra-f0: default min max count must set together in dtsi\n");
|
||||
}
|
||||
}
|
||||
#endif
|
||||
} else {
|
||||
dev_err(chip->dev, "Can't get close-loop LRA period in rc_clk_cal mode %u\n",
|
||||
rc_clk_cal);
|
||||
@@ -1187,7 +1227,7 @@ static int haptics_get_closeloop_lra_period(struct haptics_chip *chip,
|
||||
return rc;
|
||||
}
|
||||
|
||||
dev_dbg(chip->dev, "OL_TLRA %u us, CL_TLRA %u us, RC_CLK_CAL_COUNT %#x\n",
|
||||
dev_info(chip->dev, "OL_TLRA %u us, CL_TLRA %u us, RC_CLK_CAL_COUNT %#x\n",
|
||||
chip->config.t_lra_us, chip->config.cl_t_lra_us,
|
||||
chip->config.rc_clk_cal_count);
|
||||
return 0;
|
||||
@@ -1215,7 +1255,7 @@ static int haptics_set_vmax_mv(struct haptics_chip *chip, u32 vmax_mv)
|
||||
if (rc < 0)
|
||||
dev_err(chip->dev, "config VMAX failed, rc=%d\n", rc);
|
||||
else
|
||||
dev_dbg(chip->dev, "Set Vmax to %u mV\n", vmax_mv);
|
||||
dev_info(chip->dev, "Set Vmax to %u mV\n", vmax_mv);
|
||||
|
||||
return rc;
|
||||
}
|
||||
@@ -1297,7 +1337,7 @@ static int haptics_boost_vreg_enable(struct haptics_chip *chip, bool en)
|
||||
return 0;
|
||||
|
||||
if (chip->hap_cfg_nvmem == NULL) {
|
||||
dev_dbg(chip->dev, "nvmem device for hap_cfg is not defined\n");
|
||||
dev_info(chip->dev, "nvmem device for hap_cfg is not defined\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -1355,7 +1395,7 @@ static bool is_boost_vreg_enabled_in_open_loop(struct haptics_chip *chip)
|
||||
rc = haptics_read(chip, chip->hbst_addr_base,
|
||||
HAP_BOOST_VREG_EN_REG, &val, 1);
|
||||
if (!rc && (val & VREG_EN_BIT)) {
|
||||
dev_dbg(chip->dev, "HBoost is enabled in open loop condition\n");
|
||||
dev_info(chip->dev, "HBoost is enabled in open loop condition\n");
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -1463,7 +1503,7 @@ static int haptics_enable_hpwr_vreg(struct haptics_chip *chip, bool en)
|
||||
}
|
||||
}
|
||||
|
||||
dev_dbg(chip->dev, "%s hpwr vreg\n", en ? "enabled" : "disabled");
|
||||
dev_info(chip->dev, "%s hpwr vreg\n", en ? "enabled" : "disabled");
|
||||
chip->hpwr_vreg_enabled = en;
|
||||
return 0;
|
||||
}
|
||||
@@ -1476,12 +1516,13 @@ static int haptics_open_loop_drive_config(struct haptics_chip *chip, bool en)
|
||||
if ((is_boost_vreg_enabled_in_open_loop(chip) ||
|
||||
chip->hboost_enabled || is_haptics_external_powered(chip)) && en) {
|
||||
/* Force VREG_RDY */
|
||||
#if !defined(QCOM_HAPTIC_BOB)
|
||||
rc = haptics_masked_write(chip, chip->cfg_addr_base,
|
||||
HAP_CFG_VSET_CFG_REG, FORCE_VREG_RDY_BIT,
|
||||
FORCE_VREG_RDY_BIT);
|
||||
if (rc < 0)
|
||||
return rc;
|
||||
|
||||
#endif
|
||||
/* Toggle RC_CLK_CAL_EN if it's in auto mode */
|
||||
rc = haptics_read(chip, chip->cfg_addr_base,
|
||||
HAP_CFG_CAL_EN_REG, &val, 1);
|
||||
@@ -1505,12 +1546,14 @@ static int haptics_open_loop_drive_config(struct haptics_chip *chip, bool en)
|
||||
if (rc < 0)
|
||||
return rc;
|
||||
|
||||
dev_dbg(chip->dev, "Toggle CAL_EN in open-loop-VREG playing\n");
|
||||
dev_info(chip->dev, "Toggle CAL_EN in open-loop-VREG playing\n");
|
||||
}
|
||||
} else if (!is_haptics_external_powered(chip)) {
|
||||
#if !defined(QCOM_HAPTIC_BOB)
|
||||
rc = haptics_masked_write(chip, chip->cfg_addr_base,
|
||||
HAP_CFG_VSET_CFG_REG,
|
||||
FORCE_VREG_RDY_BIT, 0);
|
||||
#endif
|
||||
}
|
||||
|
||||
return rc;
|
||||
@@ -1537,8 +1580,6 @@ static int haptics_enable_play(struct haptics_chip *chip, bool en)
|
||||
return rc;
|
||||
|
||||
val = play->pattern_src;
|
||||
if (play->brake && !play->brake->disabled)
|
||||
val |= BRAKE_EN_BIT;
|
||||
|
||||
if (en)
|
||||
val |= PLAY_EN_BIT;
|
||||
@@ -1798,7 +1839,7 @@ static int haptics_set_manual_rc_clk_cal(struct haptics_chip *chip)
|
||||
u8 val[2];
|
||||
|
||||
if (cal_count == 0) {
|
||||
dev_dbg(chip->dev, "Ignore setting RC_CLK_CAL_COUNT\n");
|
||||
dev_info(chip->dev, "Ignore setting RC_CLK_CAL_COUNT\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -2131,7 +2172,7 @@ static int haptics_load_predefined_effect(struct haptics_chip *chip,
|
||||
|
||||
if (play->pattern_src == PATTERN1 || play->pattern_src == PATTERN2) {
|
||||
if (play->effect->pattern->preload) {
|
||||
dev_dbg(chip->dev, "Ignore preloaded effect: %d\n",
|
||||
dev_info(chip->dev, "Ignore preloaded effect: %d\n",
|
||||
play->effect->id);
|
||||
return 0;
|
||||
}
|
||||
@@ -2167,7 +2208,13 @@ static int haptics_init_custom_effect(struct haptics_chip *chip)
|
||||
chip->custom_effect->pattern = NULL;
|
||||
chip->custom_effect->brake = NULL;
|
||||
chip->custom_effect->id = UINT_MAX;
|
||||
#ifdef QCOM_HAPTIC_BOB
|
||||
chip->custom_effect->vmax_mv = chip->config.vmax_mv;
|
||||
#elif defined(CONFIG_TARGET_PRODUCT_HAYDN)
|
||||
chip->custom_effect->vmax_mv = 8500;
|
||||
#else
|
||||
chip->custom_effect->vmax_mv = 9000;
|
||||
#endif
|
||||
chip->custom_effect->t_lra_us = chip->config.t_lra_us;
|
||||
chip->custom_effect->src = FIFO;
|
||||
chip->custom_effect->auto_res_disable = true;
|
||||
@@ -2238,7 +2285,7 @@ static int haptics_load_custom_effect(struct haptics_chip *chip,
|
||||
if (copy_from_user(&custom_data, data, sizeof(custom_data)))
|
||||
return -EFAULT;
|
||||
|
||||
dev_dbg(chip->dev, "custom data length %d with play-rate %d Hz\n",
|
||||
dev_info(chip->dev, "custom data length %d with play-rate %d Hz\n",
|
||||
custom_data.length, custom_data.play_rate_hz);
|
||||
rc = haptics_convert_sample_period(chip, custom_data.play_rate_hz);
|
||||
if (rc < 0) {
|
||||
@@ -2270,7 +2317,7 @@ static int haptics_load_custom_effect(struct haptics_chip *chip,
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
dev_dbg(chip->dev, "Copy custom FIFO samples successfully\n");
|
||||
dev_info(chip->dev, "Copy custom FIFO samples successfully\n");
|
||||
fifo->num_s = custom_data.length;
|
||||
fifo->play_length_us = get_fifo_play_length_us(fifo,
|
||||
chip->custom_effect->t_lra_us);
|
||||
@@ -2283,7 +2330,11 @@ static int haptics_load_custom_effect(struct haptics_chip *chip,
|
||||
|
||||
play->effect = chip->custom_effect;
|
||||
play->brake = NULL;
|
||||
play->vmax_mv = (magnitude * chip->custom_effect->vmax_mv) / 0x7fff;
|
||||
/*
|
||||
* make vibration intensity could changed larger, 0x4000
|
||||
* is computed by 0x7fff - 0x3fff
|
||||
*/
|
||||
play->vmax_mv = (magnitude - 0x3fff) * chip->custom_effect->vmax_mv / 0x4000;
|
||||
rc = haptics_set_vmax_mv(chip, play->vmax_mv);
|
||||
if (rc < 0)
|
||||
goto cleanup;
|
||||
@@ -2353,7 +2404,7 @@ static int haptics_load_periodic_effect(struct haptics_chip *chip,
|
||||
}
|
||||
|
||||
mutex_lock(&chip->play.lock);
|
||||
dev_dbg(chip->dev, "upload effect %d, vmax_mv=%d\n",
|
||||
dev_info(chip->dev, "upload effect %d, vmax_mv=%d\n",
|
||||
chip->effects[i].id, play->vmax_mv);
|
||||
|
||||
if (chip->play.in_calibration) {
|
||||
@@ -2402,7 +2453,7 @@ static u8 get_direct_play_max_amplitude(struct haptics_chip *chip)
|
||||
amplitude = DIRECT_PLAY_MAX_AMPLITUDE;
|
||||
}
|
||||
|
||||
dev_dbg(chip->dev, "max amplitude for direct play: %#x\n", amplitude);
|
||||
dev_info(chip->dev, "max amplitude for direct play: %#x\n", amplitude);
|
||||
return (u8)amplitude;
|
||||
}
|
||||
|
||||
@@ -2462,7 +2513,7 @@ static int haptics_upload_effect(struct input_dev *dev,
|
||||
tmp = get_direct_play_max_amplitude(chip);
|
||||
tmp *= level;
|
||||
amplitude = tmp / 0x7fff;
|
||||
dev_dbg(chip->dev, "upload constant effect, length = %dus, amplitude = %#x\n",
|
||||
dev_info(chip->dev, "upload constant effect, length = %dus, amplitude = %#x\n",
|
||||
length_us, amplitude);
|
||||
haptics_load_constant_effect(chip, amplitude);
|
||||
if (rc < 0) {
|
||||
@@ -2539,7 +2590,7 @@ static int haptics_playback(struct input_dev *dev, int effect_id, int val)
|
||||
struct haptics_play_info *play = &chip->play;
|
||||
int rc;
|
||||
|
||||
dev_dbg(chip->dev, "playback val = %d\n", val);
|
||||
dev_info(chip->dev, "playback val = %d\n", val);
|
||||
if (!!val) {
|
||||
rc = haptics_enable_play(chip, true);
|
||||
if (rc < 0)
|
||||
@@ -2547,7 +2598,7 @@ static int haptics_playback(struct input_dev *dev, int effect_id, int val)
|
||||
} else {
|
||||
if (play->pattern_src == FIFO &&
|
||||
atomic_read(&play->fifo_status.is_busy)) {
|
||||
dev_dbg(chip->dev, "FIFO playing is not done yet, defer stopping in erase\n");
|
||||
dev_info(chip->dev, "FIFO playing is not done yet, defer stopping in erase\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -2567,7 +2618,7 @@ static int haptics_erase(struct input_dev *dev, int effect_id)
|
||||
if ((play->pattern_src == FIFO) &&
|
||||
atomic_read(&play->fifo_status.is_busy)) {
|
||||
if (atomic_read(&play->fifo_status.written_done) == 0) {
|
||||
dev_dbg(chip->dev, "cancelling FIFO playing\n");
|
||||
dev_info(chip->dev, "cancelling FIFO playing\n");
|
||||
atomic_set(&play->fifo_status.cancelled, 1);
|
||||
}
|
||||
|
||||
@@ -2581,6 +2632,8 @@ static int haptics_erase(struct input_dev *dev, int effect_id)
|
||||
}
|
||||
mutex_unlock(&play->lock);
|
||||
|
||||
mutex_unlock(&play->lock);
|
||||
|
||||
rc = haptics_enable_hpwr_vreg(chip, false);
|
||||
if (rc < 0)
|
||||
dev_err(chip->dev, "disable hpwr_vreg failed, rc=%d\n");
|
||||
@@ -2601,7 +2654,7 @@ static void haptics_set_gain(struct input_dev *dev, u16 gain)
|
||||
if (gain > 0x7fff)
|
||||
gain = 0x7fff;
|
||||
|
||||
dev_dbg(chip->dev, "Set gain: %#x\n", gain);
|
||||
dev_info(chip->dev, "Set gain: %#x\n", gain);
|
||||
|
||||
/* scale amplitude when playing in DIRECT_PLAY mode */
|
||||
if (chip->play.pattern_src == DIRECT_PLAY) {
|
||||
@@ -2609,7 +2662,7 @@ static void haptics_set_gain(struct input_dev *dev, u16 gain)
|
||||
amplitude *= gain;
|
||||
amplitude /= 0x7fff;
|
||||
|
||||
dev_dbg(chip->dev, "Set amplitude: %#x\n", amplitude);
|
||||
dev_info(chip->dev, "Set amplitude: %#x\n", amplitude);
|
||||
haptics_set_direct_play(chip, (u8)amplitude);
|
||||
return;
|
||||
}
|
||||
@@ -2873,10 +2926,10 @@ static irqreturn_t fifo_empty_irq_handler(int irq, void *data)
|
||||
if (rc < 0)
|
||||
goto unlock;
|
||||
|
||||
dev_dbg(chip->dev, "FIFO playing is done\n");
|
||||
dev_info(chip->dev, "FIFO playing is done\n");
|
||||
} else {
|
||||
if (atomic_read(&status->cancelled) == 1) {
|
||||
dev_dbg(chip->dev, "FIFO programming got cancelled\n");
|
||||
dev_info(chip->dev, "FIFO programming got cancelled\n");
|
||||
goto unlock;
|
||||
}
|
||||
|
||||
@@ -2915,7 +2968,7 @@ static irqreturn_t fifo_empty_irq_handler(int irq, void *data)
|
||||
|
||||
status->samples_written += num;
|
||||
if (status->samples_written == fifo->num_s) {
|
||||
dev_dbg(chip->dev, "FIFO programming is done\n");
|
||||
dev_info(chip->dev, "FIFO programming is done\n");
|
||||
atomic_set(&chip->play.fifo_status.written_done, 1);
|
||||
haptics_set_fifo_empty_threshold(chip, 0);
|
||||
}
|
||||
@@ -3633,7 +3686,7 @@ static int haptics_parse_per_effect_dt(struct haptics_chip *chip,
|
||||
effect->vmax_mv = config->vmax_mv;
|
||||
rc = of_property_read_u32(node, "qcom,wf-vmax-mv", &tmp);
|
||||
if (rc < 0)
|
||||
dev_dbg(chip->dev, "Read qcom,wf-vmax-mv failed, rc=%d\n",
|
||||
dev_info(chip->dev, "Read qcom,wf-vmax-mv failed, rc=%d\n",
|
||||
rc);
|
||||
else
|
||||
effect->vmax_mv = tmp;
|
||||
@@ -3740,7 +3793,7 @@ static int haptics_parse_per_effect_dt(struct haptics_chip *chip,
|
||||
rc = of_property_read_u32(node, "qcom,wf-pattern-period-us",
|
||||
&tmp);
|
||||
if (rc < 0)
|
||||
dev_dbg(chip->dev, "Read qcom,wf-pattern-period-us failed, rc=%d\n",
|
||||
dev_info(chip->dev, "Read qcom,wf-pattern-period-us failed, rc=%d\n",
|
||||
rc);
|
||||
else
|
||||
effect->pattern->play_rate_us = tmp;
|
||||
@@ -3760,7 +3813,7 @@ static int haptics_parse_per_effect_dt(struct haptics_chip *chip,
|
||||
}
|
||||
|
||||
if (effect->fifo)
|
||||
dev_dbg(chip->dev, "Ignore FIFO data if pattern is specified!\n");
|
||||
dev_info(chip->dev, "Ignore FIFO data if pattern is specified!\n");
|
||||
|
||||
} else if (effect->fifo) {
|
||||
effect->fifo->period_per_s = T_LRA;
|
||||
@@ -3963,7 +4016,7 @@ static int haptics_get_revision(struct haptics_chip *chip)
|
||||
return rc;
|
||||
|
||||
chip->hbst_revision = (val[1] << 8) | val[0];
|
||||
dev_dbg(chip->dev, "haptics revision: HAP_CFG %#x, HAP_PTN %#x, HAP_HBST %#x\n",
|
||||
dev_info(chip->dev, "haptics revision: HAP_CFG %#x, HAP_PTN %#x, HAP_HBST %#x\n",
|
||||
chip->cfg_revision, chip->ptn_revision, chip->hbst_revision);
|
||||
}
|
||||
|
||||
@@ -4094,6 +4147,12 @@ static int haptics_parse_dt(struct haptics_chip *chip)
|
||||
goto free_pbs;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_TARGET_PRODUCT_HAYDN
|
||||
config->vmax_mv = 1200;
|
||||
#endif
|
||||
#ifdef CONFIG_TARGET_PRODUCT_VILI
|
||||
config->vmax_mv = 1300;
|
||||
#endif
|
||||
config->fifo_empty_thresh = get_fifo_empty_threshold(chip);
|
||||
of_property_read_u32(node, "qcom,fifo-empty-threshold",
|
||||
&config->fifo_empty_thresh);
|
||||
@@ -4321,7 +4380,7 @@ static u32 get_lra_impedance_capable_max(struct haptics_chip *chip)
|
||||
if (is_haptics_external_powered(chip))
|
||||
mohms = (chip->hpwr_voltage_mv * 1000) / MIN_ISC_MA;
|
||||
|
||||
dev_dbg(chip->dev, "LRA impedance capable max: %u mohms\n", mohms);
|
||||
dev_info(chip->dev, "LRA impedance capable max: %u mohms\n", mohms);
|
||||
return mohms;
|
||||
}
|
||||
|
||||
@@ -4339,7 +4398,7 @@ static int haptics_detect_lra_impedance(struct haptics_chip *chip)
|
||||
u32 amplitude, lra_min_mohms, lra_max_mohms, capability_mohms;
|
||||
|
||||
if (chip->cfg_revision == HAP_CFG_V1) {
|
||||
dev_dbg(chip->dev, "HAP_CFG V1.0 doesn't support impedance detection\n");
|
||||
dev_info(chip->dev, "HAP_CFG V1.0 doesn't support impedance detection\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -4381,7 +4440,7 @@ static int haptics_detect_lra_impedance(struct haptics_chip *chip)
|
||||
if (rc < 0)
|
||||
goto restore;
|
||||
|
||||
dev_dbg(chip->dev, "sweeping milli_pct %u, amplitude %#x\n",
|
||||
dev_info(chip->dev, "sweeping milli_pct %u, amplitude %#x\n",
|
||||
duty_milli_pct, amplitude);
|
||||
/* Enable play */
|
||||
chip->play.pattern_src = DIRECT_PLAY;
|
||||
@@ -4419,7 +4478,7 @@ static int haptics_detect_lra_impedance(struct haptics_chip *chip)
|
||||
else if (lra_max_mohms >= capability_mohms)
|
||||
dev_warn(chip->dev, "Open circuit detected!\n");
|
||||
else
|
||||
dev_dbg(chip->dev, "LRA impedance is between %u - %u mohms\n",
|
||||
dev_info(chip->dev, "LRA impedance is between %u - %u mohms\n",
|
||||
lra_min_mohms, lra_max_mohms);
|
||||
|
||||
chip->config.lra_min_mohms = lra_min_mohms;
|
||||
@@ -4824,7 +4883,7 @@ static int haptics_suspend(struct device *dev)
|
||||
if ((play->pattern_src == FIFO) &&
|
||||
atomic_read(&play->fifo_status.is_busy)) {
|
||||
if (atomic_read(&play->fifo_status.written_done) == 0) {
|
||||
dev_dbg(chip->dev, "cancelling FIFO playing\n");
|
||||
dev_info(chip->dev, "cancelling FIFO playing\n");
|
||||
atomic_set(&play->fifo_status.cancelled, 1);
|
||||
}
|
||||
|
||||
|
||||
@@ -22,10 +22,13 @@
|
||||
#include <linux/regmap.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/spmi.h>
|
||||
#include <linux/nmi.h>
|
||||
#include <linux/sched/debug.h>
|
||||
#include <linux/input/qpnp-power-on.h>
|
||||
#include <linux/regulator/driver.h>
|
||||
#include <linux/regulator/machine.h>
|
||||
#include <linux/regulator/of_regulator.h>
|
||||
#include <uapi/linux/sched/types.h>
|
||||
|
||||
#define PMIC_VER_8941 0x01
|
||||
#define PMIC_VERSION_REG 0x0105
|
||||
@@ -130,6 +133,8 @@ enum qpnp_pon_version {
|
||||
#define QPNP_PON_KPDPWR_RESIN_BARK_N_SET BIT(5)
|
||||
#define QPNP_PON_GEN3_RESIN_N_SET BIT(6)
|
||||
#define QPNP_PON_GEN3_KPDPWR_N_SET BIT(7)
|
||||
#define QPNP_PON_KPDPWR_RESIN_N_SET (QPNP_PON_GEN3_RESIN_N_SET | \
|
||||
QPNP_PON_GEN3_KPDPWR_N_SET)
|
||||
|
||||
#define QPNP_PON_WD_EN BIT(7)
|
||||
#define QPNP_PON_RESET_EN BIT(7)
|
||||
@@ -167,6 +172,8 @@ enum qpnp_pon_version {
|
||||
|
||||
#define QPNP_POFF_REASON_UVLO 13
|
||||
|
||||
#define QPNP_PON_KPDPWR_RESIN_RESET_TIME 400
|
||||
|
||||
enum pon_type {
|
||||
PON_KPDPWR = PON_POWER_ON_TYPE_KPDPWR,
|
||||
PON_RESIN = PON_POWER_ON_TYPE_RESIN,
|
||||
@@ -216,7 +223,14 @@ struct qpnp_pon {
|
||||
struct list_head list;
|
||||
struct mutex restore_lock;
|
||||
struct delayed_work bark_work;
|
||||
|
||||
#ifdef CONFIG_QGKI_SYSTEM
|
||||
struct delayed_work collect_d_work;
|
||||
bool collect_d_in_progress;
|
||||
#endif
|
||||
|
||||
struct dentry *debugfs;
|
||||
struct task_struct *longpress_task;
|
||||
u16 base;
|
||||
u16 pbs_base;
|
||||
u8 subtype;
|
||||
@@ -244,6 +258,7 @@ struct qpnp_pon {
|
||||
bool kpdpwr_dbc_enable;
|
||||
bool resin_pon_reset;
|
||||
ktime_t kpdpwr_last_release_time;
|
||||
ktime_t time_kpdpwr_bark;
|
||||
bool legacy_hard_reset_offset;
|
||||
bool log_kpd_event;
|
||||
};
|
||||
@@ -253,6 +268,12 @@ static struct qpnp_pon *modem_reset_dev;
|
||||
static DEFINE_SPINLOCK(spon_list_slock);
|
||||
static LIST_HEAD(spon_dev_list);
|
||||
|
||||
#ifdef CONFIG_QGKI_SYSTEM
|
||||
extern int in_long_press;
|
||||
static u32 comb_reset_time;
|
||||
static bool comb_reset_enable;
|
||||
#endif
|
||||
|
||||
static u32 s1_delay[PON_S1_COUNT_MAX + 1] = {
|
||||
0, 32, 56, 80, 138, 184, 272, 408, 608, 904, 1352, 2048, 3072, 4480,
|
||||
6720, 10256
|
||||
@@ -1030,6 +1051,21 @@ static int qpnp_pon_input_dispatch(struct qpnp_pon *pon, u32 pon_type)
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_QGKI_SYSTEM
|
||||
if (comb_reset_enable == true) {
|
||||
if (((pon_rt_sts & QPNP_PON_KPDPWR_RESIN_N_SET) == QPNP_PON_KPDPWR_RESIN_N_SET) && (pon->collect_d_in_progress == false) &&
|
||||
(cfg->key_code == KEY_POWER || cfg->key_code == KEY_VOLUMEDOWN)) {
|
||||
pon->collect_d_in_progress = true;
|
||||
schedule_delayed_work(&pon->collect_d_work,
|
||||
msecs_to_jiffies(comb_reset_time - QPNP_PON_KPDPWR_RESIN_RESET_TIME));
|
||||
} else if ((pon->collect_d_in_progress == true) && ((pon_rt_sts & QPNP_PON_KPDPWR_RESIN_N_SET) != QPNP_PON_KPDPWR_RESIN_N_SET) &&
|
||||
(cfg->key_code == KEY_POWER || cfg->key_code == KEY_VOLUMEDOWN)) {
|
||||
cancel_delayed_work(&pon->collect_d_work);
|
||||
pon->collect_d_in_progress = false;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
pr_debug("PMIC input: code=%d, status=0x%02X\n", cfg->key_code,
|
||||
pon_rt_sts);
|
||||
key_status = pon_rt_sts & pon_rt_bit;
|
||||
@@ -1060,6 +1096,88 @@ static int qpnp_pon_input_dispatch(struct qpnp_pon *pon, u32 pon_type)
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
#ifdef CONFIG_QGKI_SYSTEM
|
||||
void show_state_filter_single(unsigned long state_filter)
|
||||
{
|
||||
struct task_struct *g, *p;
|
||||
|
||||
#if BITS_PER_LONG == 32
|
||||
printk(KERN_INFO
|
||||
" task PC stack pid father\n");
|
||||
#else
|
||||
printk(KERN_INFO
|
||||
" task PC stack pid father\n");
|
||||
#endif
|
||||
rcu_read_lock();
|
||||
for_each_process_thread(g, p) {
|
||||
/*
|
||||
* reset the NMI-timeout, listing all files on a slow
|
||||
* console might take a lot of time:
|
||||
* Also, reset softlockup watchdogs on all CPUs, because
|
||||
* another CPU might be blocked waiting for us to process
|
||||
* an IPI.
|
||||
*/
|
||||
touch_nmi_watchdog();
|
||||
touch_all_softlockup_watchdogs();
|
||||
if (p->state == state_filter)
|
||||
sched_show_task(p);
|
||||
}
|
||||
rcu_read_unlock();
|
||||
}
|
||||
|
||||
static void collect_d_work_func(struct work_struct *work)
|
||||
{
|
||||
int rc;
|
||||
int tmp_console = console_loglevel;
|
||||
uint pon_rt_sts = 0;
|
||||
struct qpnp_pon *pon =
|
||||
container_of(work, struct qpnp_pon, collect_d_work.work);
|
||||
|
||||
/* check the RT status to get the current status of the line */
|
||||
rc = regmap_read(pon->regmap, QPNP_PON_RT_STS(pon), &pon_rt_sts);
|
||||
if (rc) {
|
||||
dev_err(pon->dev, "Unable to read PON RT status\n");
|
||||
goto err_return;
|
||||
}
|
||||
if ((pon_rt_sts & QPNP_PON_KPDPWR_RESIN_N_SET) == QPNP_PON_KPDPWR_RESIN_N_SET) {
|
||||
console_verbose();
|
||||
pr_info("------ collect D&R-state processes info before long comb key ------\n");
|
||||
show_state_filter_single(TASK_UNINTERRUPTIBLE);
|
||||
show_state_filter_single(TASK_RUNNING);
|
||||
pr_info("------ end collecting D&R-state processes info ------\n");
|
||||
console_loglevel = tmp_console;
|
||||
}
|
||||
err_return:
|
||||
pon->collect_d_in_progress = false;
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
extern int mi_display_pm_suspend(void);
|
||||
static int longpress_kthread(void *_pon)
|
||||
{
|
||||
#ifdef CONFIG_MTD_BLOCK2MTD
|
||||
struct qpnp_pon *pon = _pon;
|
||||
ktime_t time_to_S2, time_S2;
|
||||
|
||||
dev_err(pon->dev, "Long press :Start to run longpress_kthread ");
|
||||
//mi_display_pm_suspend();
|
||||
|
||||
long_press();
|
||||
|
||||
time_S2 = pon->pon_cfg->s2_timer;
|
||||
time_to_S2 = time_S2 - ktime_ms_delta(ktime_get(), pon->time_kpdpwr_bark);
|
||||
|
||||
if (time_to_S2 > 0)
|
||||
mdelay(time_to_S2);
|
||||
|
||||
machine_restart("lp_kthread");
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static irqreturn_t qpnp_kpdpwr_irq(int irq, void *_pon)
|
||||
{
|
||||
int rc;
|
||||
@@ -1074,6 +1192,16 @@ static irqreturn_t qpnp_kpdpwr_irq(int irq, void *_pon)
|
||||
|
||||
static irqreturn_t qpnp_kpdpwr_bark_irq(int irq, void *_pon)
|
||||
{
|
||||
struct qpnp_pon *pon = _pon;
|
||||
dev_err(pon->dev, "Enter in kpdpwr irq !");
|
||||
|
||||
#ifdef CONFIG_QGKI_SYSTEM
|
||||
in_long_press = 1;
|
||||
#endif
|
||||
|
||||
wake_up_process(pon->longpress_task);
|
||||
pon->time_kpdpwr_bark = ktime_get();
|
||||
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
@@ -1475,12 +1603,16 @@ static int qpnp_pon_config_kpdpwr_init(struct qpnp_pon *pon,
|
||||
|
||||
cfg->use_bark = of_property_read_bool(node, "qcom,use-bark");
|
||||
if (cfg->use_bark) {
|
||||
struct sched_param param = {.sched_priority = MAX_RT_PRIO-1};
|
||||
|
||||
cfg->bark_irq = platform_get_irq_byname(pdev, "kpdpwr-bark");
|
||||
pon->longpress_task = kthread_create(longpress_kthread, pon, "longpress");
|
||||
if (cfg->bark_irq < 0) {
|
||||
dev_err(pon->dev, "Unable to get kpdpwr-bark irq, rc=%d\n",
|
||||
cfg->bark_irq);
|
||||
return cfg->bark_irq;
|
||||
}
|
||||
sched_setscheduler(pon->longpress_task, SCHED_FIFO, ¶m);
|
||||
}
|
||||
|
||||
if (pon->pon_ver == QPNP_PON_GEN1_V1) {
|
||||
@@ -1741,6 +1873,12 @@ static int qpnp_pon_config_init(struct qpnp_pon *pon,
|
||||
if (rc)
|
||||
return rc;
|
||||
|
||||
#ifdef CONFIG_QGKI_SYSTEM
|
||||
if (cfg->pon_type == PON_KPDPWR_RESIN) {
|
||||
comb_reset_time = cfg->s1_timer + cfg->s2_timer;
|
||||
comb_reset_enable = true;
|
||||
}
|
||||
#endif
|
||||
/*
|
||||
* Get the standard key parameters. This might not be
|
||||
* specified if there is no key mapping on the reset line.
|
||||
@@ -2360,6 +2498,66 @@ static int qpnp_pon_parse_dt_power_off_config(struct qpnp_pon *pon)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int debug_pon_on_off_reg(struct qpnp_pon *pon)
|
||||
{
|
||||
int rc = 0;
|
||||
uint pon_sts = 0;
|
||||
int i = 0;
|
||||
char str_buf[256] = "";
|
||||
char reg[16] = "";
|
||||
|
||||
for (i = QPNP_PON_REASON1(pon); i <= QPNP_S3_RESET_REASON(pon) + 1; i++) {
|
||||
rc = regmap_read(pon->regmap, i, &pon_sts);
|
||||
if (rc) {
|
||||
dev_err(pon->dev,
|
||||
"Unable to read PON_RESASON1 reg rc: %d\n",
|
||||
rc);
|
||||
return rc;
|
||||
}
|
||||
snprintf(reg, sizeof(reg), "0x%x:0x%x ", i, pon_sts);
|
||||
strlcat(str_buf, reg, sizeof(str_buf));
|
||||
}
|
||||
|
||||
if (to_spmi_device(pon->dev->parent)->usid)
|
||||
goto print_log;
|
||||
|
||||
rc = regmap_read(pon->regmap, QPNP_PON_KPDPWR_S2_CNTL(pon), &pon_sts);
|
||||
if (rc) {
|
||||
dev_err(pon->dev,
|
||||
"Unable to read PON_RESASON1 reg rc: %d\n",
|
||||
rc);
|
||||
return rc;
|
||||
}
|
||||
snprintf(reg, sizeof(reg), "0x%x:0x%x ", QPNP_PON_KPDPWR_S2_CNTL(pon), pon_sts);
|
||||
strlcat(str_buf, reg, sizeof(str_buf));
|
||||
|
||||
rc = regmap_read(pon->regmap, QPNP_PON_KPDPWR_RESIN_S2_CNTL(pon), &pon_sts);
|
||||
if (rc) {
|
||||
dev_err(pon->dev,
|
||||
"Unable to read PON_RESASON1 reg rc: %d\n",
|
||||
rc);
|
||||
return rc;
|
||||
}
|
||||
snprintf(reg, sizeof(reg), "0x%x:0x%x ", QPNP_PON_KPDPWR_RESIN_S2_CNTL(pon), pon_sts);
|
||||
strlcat(str_buf, reg, sizeof(str_buf));
|
||||
|
||||
rc = regmap_read(pon->regmap, QPNP_PON_PS_HOLD_RST_CTL(pon), &pon_sts);
|
||||
if (rc) {
|
||||
dev_err(pon->dev,
|
||||
"Unable to read PON_RESASON1 reg rc: %d\n",
|
||||
rc);
|
||||
return rc;
|
||||
}
|
||||
snprintf(reg, sizeof(reg), "0x%x:0x%x ", QPNP_PON_PS_HOLD_RST_CTL(pon), pon_sts);
|
||||
strlcat(str_buf, reg, sizeof(str_buf));
|
||||
|
||||
print_log:
|
||||
strlcat(str_buf, "\n", sizeof(str_buf));
|
||||
printk(str_buf);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int qpnp_pon_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct device *dev = &pdev->dev;
|
||||
@@ -2441,6 +2639,10 @@ static int qpnp_pon_probe(struct platform_device *pdev)
|
||||
dev_set_drvdata(dev, pon);
|
||||
|
||||
INIT_DELAYED_WORK(&pon->bark_work, bark_work_func);
|
||||
#ifdef CONFIG_QGKI_SYSTEM
|
||||
pon->collect_d_in_progress = false;
|
||||
INIT_DELAYED_WORK(&pon->collect_d_work, collect_d_work_func);
|
||||
#endif
|
||||
|
||||
rc = qpnp_pon_parse_dt_power_off_config(pon);
|
||||
if (rc)
|
||||
@@ -2456,9 +2658,16 @@ static int qpnp_pon_probe(struct platform_device *pdev)
|
||||
return rc;
|
||||
}
|
||||
|
||||
rc = qpnp_pon_get_dbc(pon, &pon->dbc_time_us);
|
||||
if (rc)
|
||||
return rc;
|
||||
pon->kpdpwr_dbc_enable = of_property_read_bool(dev->of_node,
|
||||
"qcom,kpdpwr-sw-debounce");
|
||||
|
||||
if (pon->kpdpwr_dbc_enable) {
|
||||
pr_info("use kpdpwr-sw-debounce\n");
|
||||
} else {
|
||||
rc = qpnp_pon_get_dbc(pon, &pon->dbc_time_us);
|
||||
if (rc)
|
||||
return rc;
|
||||
}
|
||||
|
||||
pon->kpdpwr_dbc_enable = of_property_read_bool(dev->of_node,
|
||||
"qcom,kpdpwr-sw-debounce");
|
||||
@@ -2502,6 +2711,7 @@ static int qpnp_pon_probe(struct platform_device *pdev)
|
||||
if (modem_reset)
|
||||
modem_reset_dev = pon;
|
||||
|
||||
debug_pon_on_off_reg(pon);
|
||||
qpnp_pon_debugfs_init(pon);
|
||||
|
||||
return 0;
|
||||
@@ -2516,6 +2726,10 @@ static int qpnp_pon_remove(struct platform_device *pdev)
|
||||
|
||||
cancel_delayed_work_sync(&pon->bark_work);
|
||||
|
||||
#ifdef CONFIG_QGKI_SYSTEM
|
||||
cancel_delayed_work_sync(&pon->collect_d_work);
|
||||
#endif
|
||||
|
||||
qpnp_pon_debugfs_remove(pon);
|
||||
if (pon->is_spon) {
|
||||
spin_lock_irqsave(&spon_list_slock, flags);
|
||||
|
||||
10
drivers/input/stmvl53l5/Kconfig
Normal file
10
drivers/input/stmvl53l5/Kconfig
Normal file
@@ -0,0 +1,10 @@
|
||||
#
|
||||
# ST SPI stmvl53l5 devices
|
||||
#
|
||||
menu "stmvl53l5"
|
||||
config STMVL53L5
|
||||
tristate "ST stmvl53l5 driver"
|
||||
help
|
||||
This enables the ST stmvl53l5 driver
|
||||
endmenu
|
||||
|
||||
2
drivers/input/stmvl53l5/Makefile
Normal file
2
drivers/input/stmvl53l5/Makefile
Normal file
@@ -0,0 +1,2 @@
|
||||
obj-$(CONFIG_STMVL53L5) += stmvl53l5.o
|
||||
stmvl53l5-objs := stmvl53l5_spi.o stmvl53l5_i2c.o stmvl53l5_load_fw.o stmvl53l5_module.o
|
||||
144
drivers/input/stmvl53l5/stmvl53l5_i2c.c
Normal file
144
drivers/input/stmvl53l5/stmvl53l5_i2c.c
Normal file
@@ -0,0 +1,144 @@
|
||||
/**************************************************************************
|
||||
* Copyright (c) 2016, STMicroelectronics - All Rights Reserved
|
||||
|
||||
License terms: BSD 3-clause "New" or "Revised" License.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright notice, this
|
||||
list of conditions and the following disclaimer.
|
||||
|
||||
2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
|
||||
3. Neither the name of the copyright holder nor the names of its contributors
|
||||
may be used to endorse or promote products derived from this software
|
||||
without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
||||
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
****************************************************************************/
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/uaccess.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/i2c.h>
|
||||
#include <linux/i2c-dev.h>
|
||||
#include <linux/mutex.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/irq.h>
|
||||
#include <linux/gpio.h>
|
||||
#include <linux/input.h>
|
||||
#include <linux/miscdevice.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/fs.h>
|
||||
#include <linux/time.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/version.h>
|
||||
|
||||
#include "stmvl53l5_i2c.h"
|
||||
|
||||
int32_t stmvl53l5_read_multi(struct i2c_client *client,
|
||||
uint8_t * i2c_buffer,
|
||||
uint16_t reg_index,
|
||||
uint8_t *pdata,
|
||||
uint32_t count)
|
||||
{
|
||||
int32_t status = 0;
|
||||
uint32_t position = 0;
|
||||
uint32_t data_size = 0;
|
||||
struct i2c_msg message;
|
||||
|
||||
message.addr = 0x29;
|
||||
|
||||
do {
|
||||
data_size = (count - position) > VL53L5_COMMS_CHUNK_SIZE ? VL53L5_COMMS_CHUNK_SIZE : (count - position);
|
||||
|
||||
i2c_buffer[0] = (reg_index + position) >> 8;
|
||||
i2c_buffer[1] = (reg_index + position) & 0xFF;
|
||||
|
||||
message.flags = 0;
|
||||
message.buf = i2c_buffer;
|
||||
message.len = 2;
|
||||
|
||||
status = i2c_transfer(client->adapter, &message, 1);
|
||||
if (status != 1)
|
||||
return -EIO;
|
||||
|
||||
message.flags = 1;
|
||||
message.buf = pdata + position;
|
||||
message.len = data_size;
|
||||
|
||||
status = i2c_transfer(client->adapter, &message, 1);
|
||||
if (status != 1)
|
||||
return -EIO;
|
||||
|
||||
position += data_size;
|
||||
|
||||
} while (position < count);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int32_t stmvl53l5_write_multi(struct i2c_client *client,
|
||||
uint8_t *i2c_buffer,
|
||||
uint16_t reg_index,
|
||||
uint8_t *pdata,
|
||||
uint32_t count)
|
||||
{
|
||||
int32_t status = 0;
|
||||
uint32_t position = 0;
|
||||
int32_t data_size = 0;
|
||||
struct i2c_msg message;
|
||||
|
||||
message.addr = 0x29;
|
||||
|
||||
do {
|
||||
data_size = (count - position) > (VL53L5_COMMS_CHUNK_SIZE-2) ? (VL53L5_COMMS_CHUNK_SIZE-2) : (count - position);
|
||||
|
||||
memcpy(&i2c_buffer[2], &pdata[position], data_size);
|
||||
|
||||
i2c_buffer[0] = (reg_index + position) >> 8;
|
||||
i2c_buffer[1] = (reg_index + position) & 0xFF;
|
||||
|
||||
message.flags = 0;
|
||||
message.len = data_size + 2;
|
||||
message.buf = i2c_buffer;
|
||||
|
||||
status = i2c_transfer(client->adapter, &message, 1);
|
||||
if (status != 1)
|
||||
return -EIO;
|
||||
|
||||
position += data_size;
|
||||
|
||||
} while (position < count);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int32_t stmvl53l5_write_byte(
|
||||
struct i2c_client *client, uint8_t * i2c_buffer, uint16_t address, uint8_t value)
|
||||
{
|
||||
return stmvl53l5_write_multi(client, i2c_buffer, address, &value, 1);
|
||||
}
|
||||
|
||||
int32_t stmvl53l5_read_byte(
|
||||
struct i2c_client *client, uint8_t * i2c_buffer, uint16_t address, uint8_t *p_value)
|
||||
{
|
||||
return stmvl53l5_read_multi(client, i2c_buffer, address, p_value, 1);
|
||||
}
|
||||
63
drivers/input/stmvl53l5/stmvl53l5_i2c.h
Normal file
63
drivers/input/stmvl53l5/stmvl53l5_i2c.h
Normal file
@@ -0,0 +1,63 @@
|
||||
/**************************************************************************
|
||||
* Copyright (c) 2016, STMicroelectronics - All Rights Reserved
|
||||
|
||||
License terms: BSD 3-clause "New" or "Revised" License.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright notice, this
|
||||
list of conditions and the following disclaimer.
|
||||
|
||||
2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
|
||||
3. Neither the name of the copyright holder nor the names of its contributors
|
||||
may be used to endorse or promote products derived from this software
|
||||
without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
||||
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef STMVL53L5_I2C_H
|
||||
#define STMVL53L5_I2C_H
|
||||
|
||||
#define VL53L5_COMMS_CHUNK_SIZE 1024
|
||||
|
||||
int32_t stmvl53l5_write_byte(
|
||||
struct i2c_client *client,
|
||||
uint8_t *i2c_buffer,
|
||||
uint16_t address,
|
||||
uint8_t value);
|
||||
|
||||
int32_t stmvl53l5_read_byte(
|
||||
struct i2c_client *client,
|
||||
uint8_t *i2c_buffer,
|
||||
uint16_t address,
|
||||
uint8_t *p_value);
|
||||
|
||||
int32_t stmvl53l5_read_multi(
|
||||
struct i2c_client *client,
|
||||
uint8_t *i2c_buffer,
|
||||
uint16_t reg_index,
|
||||
uint8_t *pdata,
|
||||
uint32_t count);
|
||||
|
||||
int32_t stmvl53l5_write_multi(
|
||||
struct i2c_client *client,
|
||||
uint8_t *i2c_buffer,
|
||||
uint16_t reg_index,
|
||||
uint8_t *pdata,
|
||||
uint32_t count);
|
||||
|
||||
#endif
|
||||
635
drivers/input/stmvl53l5/stmvl53l5_load_fw.c
Normal file
635
drivers/input/stmvl53l5/stmvl53l5_load_fw.c
Normal file
@@ -0,0 +1,635 @@
|
||||
/**************************************************************************
|
||||
* Copyright (c) 2016, STMicroelectronics - All Rights Reserved
|
||||
|
||||
License terms: BSD 3-clause "New" or "Revised" License.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright notice, this
|
||||
list of conditions and the following disclaimer.
|
||||
|
||||
2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
|
||||
3. Neither the name of the copyright holder nor the names of its contributors
|
||||
may be used to endorse or promote products derived from this software
|
||||
without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
||||
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
****************************************************************************/
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/uaccess.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/i2c.h>
|
||||
#include <linux/i2c-dev.h>
|
||||
#include <linux/spi/spi.h>
|
||||
|
||||
#include <linux/mutex.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/irq.h>
|
||||
#include <linux/gpio.h>
|
||||
#include <linux/input.h>
|
||||
#include <linux/miscdevice.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/fs.h>
|
||||
#include <linux/time.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/version.h>
|
||||
#include <linux/regulator/consumer.h>
|
||||
|
||||
#include "stmvl53l5_i2c.h"
|
||||
#include "stmvl53l5_spi.h"
|
||||
#include "vl53l5_fw_data.h"
|
||||
#include "stmvl53l5_load_fw.h"
|
||||
|
||||
#define VL53L5_COMMS_BUFFER_SIZE_BYTES 5052
|
||||
#define PAGE_SELECT 0x7FFF
|
||||
#define XSHUT_CTRL 0x0009
|
||||
|
||||
const uint8_t _fw_buffer[] = EWOKMZ_STXP70_TCPM_RAM_FULL;
|
||||
|
||||
uint8_t * host_dev_p_fw_buff;
|
||||
uint32_t host_dev_fw_buff_count;
|
||||
uint8_t * host_dev_p_comms_buff;
|
||||
uint32_t host_dev_comms_buff_max_count;
|
||||
|
||||
uint8_t _comms_buffer[VL53L5_COMMS_BUFFER_SIZE_BYTES] = {0};
|
||||
|
||||
#define VL53L5_ASSIGN_FW_BUFF(fw_buff_ptr, count) \
|
||||
do {\
|
||||
host_dev_p_fw_buff = (uint8_t *)(fw_buff_ptr);\
|
||||
host_dev_fw_buff_count = (count);\
|
||||
} while (0)
|
||||
|
||||
#define VL53L5_ASSIGN_COMMS_BUFF(comms_buff_ptr, max_count) \
|
||||
do {\
|
||||
host_dev_p_comms_buff = (comms_buff_ptr);\
|
||||
host_dev_comms_buff_max_count = (max_count);\
|
||||
} while (0)
|
||||
|
||||
#define MASK_XSHUT_REGISTER(reg_val, value)\
|
||||
do {\
|
||||
reg_val &= 0xf8;\
|
||||
reg_val |= (value ? 0x04 : 0x02);\
|
||||
} while (0)
|
||||
|
||||
|
||||
struct dci_ui__dev_info_t dev;
|
||||
|
||||
int32_t wait_mcu_boot(struct i2c_client *client, struct spi_data_t *spi_data, uint8_t i2c_not_spi, uint8_t *raw_data_buffer, uint8_t state)
|
||||
{
|
||||
int32_t status = 0; //STATUS_OK;
|
||||
// uint32_t start_time_ms = 0;
|
||||
// uint32_t current_time_ms = 0;
|
||||
|
||||
// status = vl53l5_get_tick_count(p_dev, &start_time_ms);
|
||||
// if (status < STATUS_OK)
|
||||
// goto exit;
|
||||
|
||||
VL53L5_GO2_STATUS_0(&dev).bytes = 0;
|
||||
|
||||
do {
|
||||
|
||||
if (i2c_not_spi)
|
||||
status = stmvl53l5_read_multi(client, raw_data_buffer, GO2_STATUS_0, &VL53L5_GO2_STATUS_0(&dev).bytes, 1);
|
||||
else
|
||||
status = stmvl53l5_spi_read(spi_data, GO2_STATUS_0, &VL53L5_GO2_STATUS_0(&dev).bytes, 1);
|
||||
if (status != 0) //< STATUS_OK)
|
||||
goto exit;
|
||||
|
||||
if (HW_TRAP(&dev)) {
|
||||
if (i2c_not_spi)
|
||||
status = stmvl53l5_read_multi(client, raw_data_buffer, GO2_STATUS_1, &VL53L5_GO2_STATUS_1(&dev).bytes, 1);
|
||||
else
|
||||
status = stmvl53l5_spi_read(spi_data, GO2_STATUS_1, &VL53L5_GO2_STATUS_1(&dev).bytes, 1);
|
||||
if (status != 0) //< STATUS_OK)
|
||||
goto exit;
|
||||
|
||||
// if (VL53L5_GO2_STATUS_1(&dev).bytes)
|
||||
// status = VL53L5_ERROR_MCU_ERROR_POWER_STATE;
|
||||
// else
|
||||
// status =
|
||||
// VL53L5_ERROR_FALSE_MCU_ERROR_POWER_STATE;
|
||||
status = -1;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
if (MCU_ERROR(&dev)) {
|
||||
status = -1; //VL53L5_ERROR_MCU_ERROR_POWER_STATE;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
if (((state == 1) && MCU_BOOT_COMPLETE(&dev)) ||
|
||||
((state == 0) && MCU_BOOT_NOT_COMPLETE(&dev)))
|
||||
break;
|
||||
|
||||
// status = vl53l5_get_tick_count(p_dev, ¤t_time_ms);
|
||||
// if (status < STATUS_OK)
|
||||
// goto exit;
|
||||
|
||||
// CHECK_FOR_TIMEOUT(
|
||||
// status, p_dev, start_time_ms, current_time_ms,
|
||||
// VL53L5_BOOT_COMPLETION_POLLING_TIMEOUT_MS);
|
||||
// if (status < STATUS_OK) {
|
||||
// status = VL53L5_ERROR_BOOT_COMPLETE_TIMEOUT;
|
||||
// goto exit;
|
||||
// }
|
||||
msleep(10);
|
||||
|
||||
} while (1);
|
||||
|
||||
exit:
|
||||
if (status != 0)
|
||||
printk("stmvl53l5: wait_mcu_boot failed !\n");
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
|
||||
|
||||
int32_t _check_rom_firmware_boot_cut_1_2(struct i2c_client *client, uint8_t * raw_data_buffer)
|
||||
{
|
||||
int status = 0;
|
||||
|
||||
status = wait_mcu_boot(client, NULL, 1, raw_data_buffer, 1);
|
||||
if (status != 0)
|
||||
return -1;
|
||||
|
||||
status = stmvl53l5_write_byte(client, raw_data_buffer, 0x000E, 0x01);
|
||||
return status;
|
||||
}
|
||||
|
||||
int32_t check_rom_firmware_boot(struct i2c_client *client, uint8_t * raw_data_buffer)
|
||||
{
|
||||
int32_t status = 0;
|
||||
uint8_t page = 0;
|
||||
uint8_t device_id = 0;
|
||||
uint8_t revision_id = 0;
|
||||
|
||||
//LOG_FUNCTION_START("");
|
||||
//printf("entering check rom fw boot ....\n");
|
||||
|
||||
status = stmvl53l5_write_multi(client, raw_data_buffer, PAGE_SELECT, &page, 1);
|
||||
if (status != 0)
|
||||
goto exit;
|
||||
|
||||
status = stmvl53l5_read_multi(client, raw_data_buffer, 0x00, &device_id, 1);
|
||||
if (status != 0)
|
||||
goto exit;
|
||||
printk ("stmvl53l5: device id = 0x%x\n", device_id);
|
||||
|
||||
status = stmvl53l5_read_multi(client, raw_data_buffer, 0x01, &revision_id, 1);
|
||||
if (status != 0)
|
||||
goto exit;
|
||||
printk ("stmvl53l5: revision id = 0x%x\n", revision_id);
|
||||
|
||||
if ((device_id == 0xF0) && (revision_id == 0x02)) {
|
||||
status = _check_rom_firmware_boot_cut_1_2(client, raw_data_buffer);
|
||||
if (status != 0)
|
||||
goto exit;
|
||||
} else {
|
||||
status = -1;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
exit:
|
||||
if (status != 0)
|
||||
printk("stmvl53l5: check_rom_firmware_boot failed : %d\n", status);
|
||||
return status;
|
||||
}
|
||||
|
||||
|
||||
static int32_t _enable_host_access_to_go1_async(struct i2c_client *client, uint8_t * raw_data_buffer)
|
||||
{
|
||||
int32_t status = 0;
|
||||
// uint32_t start_time_ms = 0;
|
||||
// uint32_t current_time_ms = 0;
|
||||
uint8_t m_status = 0;
|
||||
uint8_t revision_id = 0;
|
||||
|
||||
status = stmvl53l5_write_byte(client, raw_data_buffer, 0x7FFF, 0x00);
|
||||
if (status != 0)
|
||||
goto exit;
|
||||
|
||||
status = stmvl53l5_read_byte(client, raw_data_buffer, 0x0001, &revision_id);
|
||||
if (status != 0)
|
||||
goto exit;
|
||||
|
||||
status = stmvl53l5_write_byte(client, raw_data_buffer, 0x7FFF, 0x02);
|
||||
if (status != 0)
|
||||
goto exit;
|
||||
|
||||
if (revision_id != 2) {
|
||||
status = -1;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
status = stmvl53l5_write_byte(client, raw_data_buffer, 0x03, 0x0D);
|
||||
if (status != 0)
|
||||
goto exit;
|
||||
|
||||
status = stmvl53l5_write_byte(client, raw_data_buffer, 0x7FFF, 0x01);
|
||||
if (status != 0)
|
||||
goto exit;
|
||||
|
||||
m_status = 0;
|
||||
// status = vl53l5_get_tick_count(p_dev, &start_time_ms);
|
||||
if (status != 0)
|
||||
goto exit;
|
||||
|
||||
while ((m_status & 0x10) == 0) {
|
||||
status = stmvl53l5_read_byte(client, raw_data_buffer, 0x21, &m_status);
|
||||
if (status != 0)
|
||||
goto exit;
|
||||
|
||||
// status = vl53l5_get_tick_count(p_dev, ¤t_time_ms);
|
||||
// if (status != 0)
|
||||
// goto exit;
|
||||
|
||||
// CHECK_FOR_TIMEOUT(
|
||||
// status, p_dev, start_time_ms, current_time_ms,
|
||||
// VL53L5_BOOT_COMPLETION_POLLING_TIMEOUT_MS);
|
||||
// if (status != 0) {
|
||||
// trace_print(
|
||||
// VL53L5_TRACE_LEVEL_ERRORS,
|
||||
// "ERROR: timeout waiting for mcu idle m_status %02x\n",
|
||||
// m_status);
|
||||
// status = VL53L5_ERROR_MCU_IDLE_TIMEOUT;
|
||||
// goto exit;
|
||||
//}
|
||||
msleep(10);
|
||||
}
|
||||
|
||||
status = stmvl53l5_write_byte(client, raw_data_buffer, 0x7FFF, 0x00);
|
||||
if (status != 0)
|
||||
goto exit;
|
||||
|
||||
status = stmvl53l5_write_byte(client, raw_data_buffer, 0x0C, 0x01);
|
||||
if (status != 0)
|
||||
goto exit;
|
||||
|
||||
exit:
|
||||
if (status != 0)
|
||||
printk("stmvl53l5: _enable_host_access_to_go1_async failed: %d\n", status);
|
||||
return status;
|
||||
}
|
||||
|
||||
static int32_t _set_to_power_on_status(struct i2c_client *client, uint8_t * raw_data_buffer)
|
||||
{
|
||||
int32_t status = 0;
|
||||
|
||||
status = stmvl53l5_write_byte(client, raw_data_buffer, 0x7FFF, 0x00);
|
||||
if (status != 0)
|
||||
goto exit;
|
||||
|
||||
status = stmvl53l5_write_byte(client, raw_data_buffer, 0x101, 0x00);
|
||||
if (status != 0)
|
||||
goto exit;
|
||||
|
||||
status = stmvl53l5_write_byte(client, raw_data_buffer, 0x102, 0x00);
|
||||
if (status != 0)
|
||||
goto exit;
|
||||
|
||||
status = stmvl53l5_write_byte(client, raw_data_buffer, 0x4002, 0x01);
|
||||
if (status != 0)
|
||||
goto exit;
|
||||
|
||||
status = stmvl53l5_write_byte(client, raw_data_buffer, 0x4002, 0x00);
|
||||
if (status != 0)
|
||||
goto exit;
|
||||
|
||||
status = stmvl53l5_write_byte(client, raw_data_buffer, 0x103, 0x01);
|
||||
if (status != 0)
|
||||
goto exit;
|
||||
|
||||
status = stmvl53l5_write_byte(client, raw_data_buffer, 0x400F, 0x00);
|
||||
if (status != 0)
|
||||
goto exit;
|
||||
|
||||
status = stmvl53l5_write_byte(client, raw_data_buffer, 0x21A, 0x43);
|
||||
if (status != 0)
|
||||
goto exit;
|
||||
|
||||
status = stmvl53l5_write_byte(client, raw_data_buffer, 0x21A, 0x03);
|
||||
if (status != 0)
|
||||
goto exit;
|
||||
|
||||
status = stmvl53l5_write_byte(client, raw_data_buffer, 0x21A, 0x01);
|
||||
if (status != 0)
|
||||
goto exit;
|
||||
|
||||
status = stmvl53l5_write_byte(client, raw_data_buffer, 0x21A, 0x00);
|
||||
if (status != 0)
|
||||
goto exit;
|
||||
|
||||
status = stmvl53l5_write_byte(client, raw_data_buffer, 0x219, 0x00);
|
||||
if (status != 0)
|
||||
goto exit;
|
||||
|
||||
status = stmvl53l5_write_byte(client, raw_data_buffer, 0x21B, 0x00);
|
||||
if (status != 0)
|
||||
goto exit;
|
||||
|
||||
exit:
|
||||
if (status != 0)
|
||||
printk("stmvl53l5: _set_to_power_on_status failed : %d\n", status);
|
||||
return status;
|
||||
}
|
||||
|
||||
|
||||
int32_t _wake_up_mcu(struct i2c_client *client, uint8_t * raw_data_buffer)
|
||||
{
|
||||
int32_t status = 0;
|
||||
|
||||
status = stmvl53l5_write_byte(client, raw_data_buffer, 0x7FFF, 0x00);
|
||||
if (status != 0)
|
||||
goto exit;
|
||||
|
||||
status = stmvl53l5_write_byte(client, raw_data_buffer, 0x0C, 0x00);
|
||||
if (status != 0)
|
||||
goto exit;
|
||||
|
||||
status = stmvl53l5_write_byte(client, raw_data_buffer, 0x7FFF, 0x01);
|
||||
if (status != 0)
|
||||
goto exit;
|
||||
|
||||
status = stmvl53l5_write_byte(client, raw_data_buffer, 0x20, 0x07);
|
||||
if (status != 0)
|
||||
goto exit;
|
||||
|
||||
status = stmvl53l5_write_byte(client, raw_data_buffer, 0x20, 0x06);
|
||||
if (status != 0)
|
||||
goto exit;
|
||||
|
||||
exit:
|
||||
if (status != 0)
|
||||
printk("stmvl53l5: _wake_up_mcu failed : %d\n", status);
|
||||
return status;
|
||||
}
|
||||
|
||||
int32_t _wait_for_boot_complete_before_fw_load(struct i2c_client *client, uint8_t * raw_data_buffer)
|
||||
{
|
||||
int32_t status = 0;
|
||||
|
||||
status = _enable_host_access_to_go1_async(client, raw_data_buffer);
|
||||
if (status != 0)
|
||||
goto exit;
|
||||
|
||||
status = _set_to_power_on_status(client, raw_data_buffer);
|
||||
if (status != 0)
|
||||
goto exit;
|
||||
|
||||
status = _wake_up_mcu(client, raw_data_buffer);
|
||||
if (status != 0)
|
||||
goto exit;
|
||||
|
||||
exit:
|
||||
if (status != 0)
|
||||
printk("stmvl53l5: _wait_for_boot_complete_before_fw_load failed : %d\n", status);
|
||||
return status;
|
||||
}
|
||||
|
||||
int32_t _reset_mcu_and_wait_boot(struct i2c_client *client, uint8_t * raw_data_buffer)
|
||||
{
|
||||
int32_t status = 0;
|
||||
uint8_t u_start[] = {0, 0, 0x42, 0};
|
||||
|
||||
status = stmvl53l5_write_byte(client, raw_data_buffer, 0x7FFF, 0x00);
|
||||
if (status != 0)
|
||||
goto exit;
|
||||
|
||||
status = stmvl53l5_write_multi(client, raw_data_buffer, 0x114, u_start, 4);
|
||||
if (status != 0)
|
||||
goto exit;
|
||||
|
||||
status = stmvl53l5_write_byte(client, raw_data_buffer, 0x0B, 0x00);
|
||||
if (status != 0)
|
||||
goto exit;
|
||||
|
||||
status = stmvl53l5_write_byte(client, raw_data_buffer, 0x0C, 0x00);
|
||||
if (status != 0)
|
||||
goto exit;
|
||||
|
||||
status = stmvl53l5_write_byte(client, raw_data_buffer, 0x0B, 0x01);
|
||||
if (status != 0)
|
||||
goto exit;
|
||||
|
||||
status = wait_mcu_boot(client, NULL, 1, raw_data_buffer, 1);
|
||||
if (status != 0)
|
||||
goto exit;
|
||||
|
||||
exit:
|
||||
if (status != 0)
|
||||
printk("stmvl53l5: _reset_mcu_and_wait_boot failed : %d\n", status);
|
||||
return status;
|
||||
}
|
||||
|
||||
|
||||
int32_t _wait_for_boot_complete_after_fw_load(struct i2c_client *client, uint8_t * raw_data_buffer)
|
||||
{
|
||||
int32_t status = 0;
|
||||
|
||||
status = _enable_host_access_to_go1_async(client, raw_data_buffer);
|
||||
if (status != 0)
|
||||
goto exit;
|
||||
|
||||
status = _reset_mcu_and_wait_boot(client, raw_data_buffer);
|
||||
if (status != 0)
|
||||
goto exit;
|
||||
|
||||
exit:
|
||||
if (status != 0)
|
||||
printk("stmvl53l5: _wait_for_boot_complete_after_fw_load failed : %d\n", status);
|
||||
return status;
|
||||
}
|
||||
|
||||
|
||||
int32_t _write_page(
|
||||
struct i2c_client *client, uint8_t * raw_data_buffer, uint32_t page_offset,
|
||||
uint32_t page_size, uint32_t max_chunk_size, uint32_t *p_write_count)
|
||||
{
|
||||
int32_t status;
|
||||
uint32_t write_size = 0;
|
||||
uint32_t remainder_size = 0;
|
||||
uint8_t *p_write_buff = NULL;
|
||||
|
||||
if ((page_offset + max_chunk_size) < page_size)
|
||||
write_size = max_chunk_size;
|
||||
else
|
||||
write_size = page_size - page_offset;
|
||||
|
||||
if (*p_write_count > host_dev_fw_buff_count) {
|
||||
|
||||
p_write_buff = host_dev_p_comms_buff;
|
||||
memset(p_write_buff, 0, write_size);
|
||||
} else {
|
||||
if ((host_dev_fw_buff_count - *p_write_count)
|
||||
< write_size) {
|
||||
|
||||
p_write_buff = host_dev_p_comms_buff;
|
||||
remainder_size =
|
||||
host_dev_fw_buff_count - *p_write_count;
|
||||
memcpy(p_write_buff,
|
||||
host_dev_p_fw_buff + *p_write_count,
|
||||
remainder_size);
|
||||
memset(p_write_buff + remainder_size,
|
||||
0,
|
||||
write_size - remainder_size);
|
||||
} else {
|
||||
|
||||
p_write_buff =
|
||||
host_dev_p_fw_buff + *p_write_count;
|
||||
}
|
||||
}
|
||||
|
||||
status = stmvl53l5_write_multi(client, raw_data_buffer, page_offset, p_write_buff,
|
||||
write_size);
|
||||
if (status != 0) {
|
||||
status = -1;
|
||||
goto exit;
|
||||
}
|
||||
(*p_write_count) += write_size;
|
||||
|
||||
exit:
|
||||
if (status != 0)
|
||||
printk("stmvl53l5: _write_page failed : %d\n", status);
|
||||
return status;
|
||||
}
|
||||
|
||||
|
||||
int32_t _download_fw_to_ram(struct i2c_client *client, uint8_t * raw_data_buffer)
|
||||
{
|
||||
int32_t status = 0;
|
||||
|
||||
uint16_t tdcm_offset = 0;
|
||||
uint8_t tdcm_page = 9;
|
||||
uint32_t tdcm_page_size = 0;
|
||||
uint32_t write_count = 0;
|
||||
|
||||
for (tdcm_page = 9; tdcm_page < 12; tdcm_page++) {
|
||||
status = stmvl53l5_write_byte(client, raw_data_buffer, 0x7FFF, tdcm_page);
|
||||
if (status != 0)
|
||||
goto exit;
|
||||
|
||||
if (tdcm_page == 9)
|
||||
tdcm_page_size = 0x8000;
|
||||
if (tdcm_page == 10)
|
||||
tdcm_page_size = 0x8000;
|
||||
if (tdcm_page == 11)
|
||||
tdcm_page_size = 0x5000;
|
||||
|
||||
for (tdcm_offset = 0; tdcm_offset < tdcm_page_size;
|
||||
tdcm_offset += VL53L5_COMMS_BUFFER_SIZE_BYTES) {
|
||||
status = _write_page(
|
||||
client, raw_data_buffer, tdcm_offset, tdcm_page_size,
|
||||
VL53L5_COMMS_BUFFER_SIZE_BYTES, &write_count);
|
||||
if (status != 0)
|
||||
goto exit;
|
||||
}
|
||||
}
|
||||
|
||||
exit:
|
||||
if (status != 0)
|
||||
printk("stmvl53l5: _download_fw_to_ram failed : %d\n", status);
|
||||
return status;
|
||||
}
|
||||
|
||||
|
||||
int32_t load_firmware(struct i2c_client *client, uint8_t * raw_data_buffer)
|
||||
{
|
||||
int32_t status = 0;
|
||||
|
||||
status = _wait_for_boot_complete_before_fw_load(client, raw_data_buffer);
|
||||
if (status != 0)
|
||||
goto exit;
|
||||
|
||||
status = _download_fw_to_ram(client, raw_data_buffer);
|
||||
if (status != 0)
|
||||
goto exit;
|
||||
|
||||
status = _wait_for_boot_complete_after_fw_load(client, raw_data_buffer);
|
||||
if (status != 0)
|
||||
goto exit;
|
||||
|
||||
status = stmvl53l5_write_byte(client, raw_data_buffer, 0x7FFF, 0x02);
|
||||
if (status != 0)
|
||||
goto exit;
|
||||
|
||||
exit:
|
||||
printk("stmvl53l5: load_firmware : GO2s0=0x%x GO2s1=0x%x status=%d\n", VL53L5_GO2_STATUS_0(&dev).bytes, VL53L5_GO2_STATUS_1(&dev).bytes, status);
|
||||
return status;
|
||||
}
|
||||
|
||||
|
||||
int32_t stmvl53l5_load_fw_stm(struct i2c_client *client, uint8_t * raw_data_buffer)
|
||||
{
|
||||
|
||||
int status = 0;
|
||||
|
||||
VL53L5_ASSIGN_FW_BUFF(_fw_buffer, sizeof(_fw_buffer));
|
||||
VL53L5_ASSIGN_COMMS_BUFF(_comms_buffer, sizeof(_comms_buffer));
|
||||
status = check_rom_firmware_boot(client, raw_data_buffer);
|
||||
status |= load_firmware(client, raw_data_buffer);
|
||||
printk("stmvl53l5: load_fw : %d\n", status);
|
||||
|
||||
return status;
|
||||
|
||||
}
|
||||
|
||||
int32_t stmvl53l5_move_device_to_low_power(struct i2c_client *client, struct spi_data_t *spi_data, uint8_t i2c_not_spi, uint8_t * raw_data_buffer)
|
||||
{
|
||||
|
||||
int status = 0;
|
||||
uint8_t page = 0;
|
||||
uint8_t reg_val = 0;
|
||||
|
||||
// put the device in low power idle with comms enabled
|
||||
if (i2c_not_spi)
|
||||
status = stmvl53l5_write_multi(client, raw_data_buffer, PAGE_SELECT, &page, 1);
|
||||
else
|
||||
status = stmvl53l5_spi_write(spi_data, PAGE_SELECT, &page, 1);
|
||||
if (status != 0)
|
||||
return -1;
|
||||
|
||||
reg_val = 0;
|
||||
if (i2c_not_spi)
|
||||
status = stmvl53l5_read_multi(client, raw_data_buffer, XSHUT_CTRL, ®_val, 1);
|
||||
else
|
||||
status = stmvl53l5_spi_write(spi_data, XSHUT_CTRL, ®_val, 1);
|
||||
|
||||
if (status != 0)
|
||||
return -1;
|
||||
|
||||
MASK_XSHUT_REGISTER(reg_val, 0);
|
||||
|
||||
if (i2c_not_spi)
|
||||
status = stmvl53l5_write_multi(client, raw_data_buffer, XSHUT_CTRL, ®_val, 1);
|
||||
else
|
||||
status = stmvl53l5_spi_write(spi_data, XSHUT_CTRL, ®_val, 1);
|
||||
|
||||
status = wait_mcu_boot(client, spi_data, i2c_not_spi, raw_data_buffer, 0);
|
||||
if (status != 0)
|
||||
return -1;
|
||||
|
||||
printk("stmvl53l5: device set in low power (idle with comms) : %d\n", status);
|
||||
|
||||
return status;
|
||||
|
||||
}
|
||||
|
||||
108
drivers/input/stmvl53l5/stmvl53l5_load_fw.h
Normal file
108
drivers/input/stmvl53l5/stmvl53l5_load_fw.h
Normal file
@@ -0,0 +1,108 @@
|
||||
/**************************************************************************
|
||||
* Copyright (c) 2016, STMicroelectronics - All Rights Reserved
|
||||
|
||||
License terms: BSD 3-clause "New" or "Revised" License.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright notice, this
|
||||
list of conditions and the following disclaimer.
|
||||
|
||||
2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
|
||||
3. Neither the name of the copyright holder nor the names of its contributors
|
||||
may be used to endorse or promote products derived from this software
|
||||
without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
||||
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef STMVL53L5_LOAD_FW_H
|
||||
#define STMVL53L5_LOAD_FW_H
|
||||
|
||||
union dci_union__go2_status_0_go1_u {
|
||||
uint8_t bytes;
|
||||
struct {
|
||||
|
||||
uint8_t mcu__boot_complete_go1 : 1;
|
||||
|
||||
uint8_t mcu__analog_checks_ok_go1 : 1;
|
||||
|
||||
uint8_t mcu__threshold_triggered_g01 : 1;
|
||||
uint8_t mcu__error_flag_go1 : 1;
|
||||
uint8_t mcu__ui_range_data_present_go1 : 1;
|
||||
uint8_t mcu__ui_new_range_data_avail_go1 : 1;
|
||||
uint8_t mcu__ui_update_blocked_go1 : 1;
|
||||
|
||||
uint8_t mcu__hw_trap_flag_go1 : 1;
|
||||
};
|
||||
};
|
||||
|
||||
union dci_union__go2_status_1_go1_u {
|
||||
uint8_t bytes;
|
||||
struct {
|
||||
|
||||
uint8_t mcu__avdd_reg_ok_go1 : 1;
|
||||
|
||||
uint8_t mcu__pll_lock_ok_go1 : 1;
|
||||
|
||||
uint8_t mcu__ls_watchdog_pass_go1 : 1;
|
||||
|
||||
uint8_t mcu__warning_flag_go1 : 1;
|
||||
|
||||
uint8_t mcu__cp_collapse_flag_go1 : 1;
|
||||
uint8_t mcu__spare2 : 1;
|
||||
uint8_t mcu__spare3 : 1;
|
||||
uint8_t mcu__spare4 : 1;
|
||||
};
|
||||
};
|
||||
|
||||
struct dci_ui__dev_info_t {
|
||||
|
||||
union dci_union__go2_status_0_go1_u dev_info__go2_status_0;
|
||||
|
||||
union dci_union__go2_status_1_go1_u dev_info__go2_status_1;
|
||||
|
||||
uint8_t dev_info__device_status;
|
||||
|
||||
uint8_t dev_info__ui_stream_count;
|
||||
};
|
||||
|
||||
#define GO2_STATUS_0 0x6
|
||||
#define GO2_STATUS_1 0x7
|
||||
|
||||
#define VL53L5_GO2_STATUS_0(p_dev) \
|
||||
((p_dev)->dev_info__go2_status_0)
|
||||
|
||||
#define VL53L5_GO2_STATUS_1(p_dev) \
|
||||
((p_dev)->dev_info__go2_status_1)
|
||||
|
||||
#define HW_TRAP(p_dev)\
|
||||
(VL53L5_GO2_STATUS_0(p_dev).mcu__hw_trap_flag_go1 == 1)
|
||||
|
||||
#define MCU_ERROR(p_dev)\
|
||||
(VL53L5_GO2_STATUS_0(p_dev).mcu__error_flag_go1 == 1)
|
||||
|
||||
#define MCU_BOOT_COMPLETE(p_dev)\
|
||||
(VL53L5_GO2_STATUS_0(p_dev).mcu__boot_complete_go1 == 1)
|
||||
|
||||
#define MCU_BOOT_NOT_COMPLETE(p_dev)\
|
||||
(VL53L5_GO2_STATUS_0(p_dev).mcu__boot_complete_go1 == 0)
|
||||
|
||||
|
||||
int32_t stmvl53l5_load_fw_stm(struct i2c_client *client, uint8_t * i2c_buffer);
|
||||
int32_t stmvl53l5_move_device_to_low_power(struct i2c_client *client, struct spi_data_t *spi_data, uint8_t i2c_not_spi, uint8_t * raw_data_buffer);
|
||||
|
||||
#endif
|
||||
602
drivers/input/stmvl53l5/stmvl53l5_module.c
Normal file
602
drivers/input/stmvl53l5/stmvl53l5_module.c
Normal file
@@ -0,0 +1,602 @@
|
||||
/**************************************************************************
|
||||
* Copyright (c) 2016, STMicroelectronics - All Rights Reserved
|
||||
|
||||
License terms: BSD 3-clause "New" or "Revised" License.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright notice, this
|
||||
list of conditions and the following disclaimer.
|
||||
|
||||
2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
|
||||
3. Neither the name of the copyright holder nor the names of its contributors
|
||||
may be used to endorse or promote products derived from this software
|
||||
without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
||||
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
****************************************************************************/
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/uaccess.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/i2c.h>
|
||||
#include <linux/i2c-dev.h>
|
||||
#include <linux/spi/spi.h>
|
||||
#include <linux/miscdevice.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/fs.h>
|
||||
#include <linux/time.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/version.h>
|
||||
#include <linux/gpio.h>
|
||||
#include <linux/regulator/consumer.h>
|
||||
|
||||
#include "stmvl53l5_i2c.h"
|
||||
#include "stmvl53l5_spi.h"
|
||||
#include "stmvl53l5_load_fw.h"
|
||||
|
||||
#define STMVL53L5_DRV_NAME "stmvl53l5"
|
||||
#define STMVL53L5_SLAVE_ADDR 0x29
|
||||
|
||||
#define ST_TOF_IOCTL_TRANSFER _IOWR('a',0x1, void*)
|
||||
|
||||
struct stmvl53l5_comms_struct {
|
||||
__u16 len;
|
||||
__u16 reg_index;
|
||||
__u8 *buf;
|
||||
__u8 write_not_read;
|
||||
};
|
||||
|
||||
static struct miscdevice st_tof_miscdev;
|
||||
static uint8_t * raw_data_buffer = NULL;
|
||||
|
||||
static uint8_t i2c_not_spi = 1;
|
||||
|
||||
static uint8_t i2c_driver_added = 0;
|
||||
static uint8_t spi_driver_registered = 0;
|
||||
static uint8_t misc_registered = 0;
|
||||
|
||||
static struct spi_data_t spi_data;
|
||||
|
||||
// ------- i2c ---------------------------
|
||||
static const struct i2c_device_id stmvl53l5_i2c_id[] = {
|
||||
{STMVL53L5_DRV_NAME, 0},
|
||||
{},
|
||||
};
|
||||
|
||||
// ------- spi ---------------------------
|
||||
static const struct spi_device_id stmvl53l5_spi_id[] = {
|
||||
{STMVL53L5_DRV_NAME, 0 },
|
||||
{ },
|
||||
};
|
||||
|
||||
MODULE_DEVICE_TABLE(i2c, stmvl53l5_i2c_id);
|
||||
|
||||
static const struct of_device_id st_tof_of_match[] = {
|
||||
{
|
||||
/* An older compatible */
|
||||
.compatible = "st,stmvl53l5",
|
||||
.data = STMVL53L5_DRV_NAME,
|
||||
},
|
||||
{},
|
||||
};
|
||||
|
||||
MODULE_DEVICE_TABLE(of, st_tof_of_match); // add to the kernel device tree table
|
||||
|
||||
static struct i2c_client *stmvl53l5_i2c_client = NULL;
|
||||
|
||||
static struct regulator *p_3v0_vreg = NULL;
|
||||
static struct regulator *p_1v8_vreg = NULL;
|
||||
|
||||
static int enable_regulator_1V8(struct device *dev, struct regulator **pp_vreg)
|
||||
{
|
||||
int ret_source = 0;
|
||||
int ret_enable = 0;
|
||||
*pp_vreg = regulator_get(dev, "_1P8_power");
|
||||
if (IS_ERR(*pp_vreg)) {
|
||||
pr_err("stmvl53l5 : Error at %s(%d)\n", __func__, __LINE__);
|
||||
ret_source = PTR_ERR(*pp_vreg);
|
||||
goto put_regulator;
|
||||
} else {
|
||||
pr_info("stmvl53l5 : 1P8 successful found\n");
|
||||
}
|
||||
ret_source = regulator_set_voltage(*pp_vreg, 1800000, 1800000);
|
||||
|
||||
if (ret_source) {
|
||||
pr_err("stmvl53l5 : Error at %s(%d)\n", __func__, __LINE__);
|
||||
goto put_regulator;
|
||||
}
|
||||
ret_source = regulator_set_load(*pp_vreg, 85000);
|
||||
if (ret_source) {
|
||||
pr_err("stmvl53l5 : Error at %s(%d)\n", __func__, __LINE__);
|
||||
goto put_regulator;
|
||||
}
|
||||
ret_enable = regulator_enable(*pp_vreg);
|
||||
if (ret_enable) {
|
||||
pr_err("stmvl53l5 : Error at %s(%d)\n", __func__, __LINE__);
|
||||
goto disable_regulator;
|
||||
}
|
||||
|
||||
disable_regulator:
|
||||
if(ret_enable) {
|
||||
regulator_disable(*pp_vreg);
|
||||
regulator_set_load(*pp_vreg, 0);
|
||||
regulator_set_voltage(*pp_vreg, 0, 1800000);
|
||||
}
|
||||
put_regulator:
|
||||
if (ret_enable || ret_source) {
|
||||
regulator_put(*pp_vreg);
|
||||
*pp_vreg = NULL;
|
||||
}
|
||||
return ret_enable || ret_source;
|
||||
}
|
||||
|
||||
static int enable_regulator_3V0(struct device *dev, struct regulator **pp_vreg)
|
||||
{
|
||||
int ret_source = 0;
|
||||
int ret_enable = 0;
|
||||
*pp_vreg = regulator_get(dev, "_3P0_power");
|
||||
if (IS_ERR(*pp_vreg)) {
|
||||
pr_err("stmvl53l5 : Error at %s(%d)\n", __func__, __LINE__);
|
||||
ret_source = PTR_ERR(*pp_vreg);
|
||||
goto put_regulator;
|
||||
} else {
|
||||
pr_info("stmvl53l5 : 3P0 successful found\n");
|
||||
}
|
||||
ret_source = regulator_set_voltage(*pp_vreg, 3008000, 3008000);
|
||||
|
||||
if (ret_source) {
|
||||
pr_err("stmvl53l5 : Error at %s(%d)\n", __func__, __LINE__);
|
||||
goto put_regulator;
|
||||
}
|
||||
ret_source = regulator_set_load(*pp_vreg, 85000);
|
||||
if (ret_source) {
|
||||
pr_err("stmvl53l5 : Error at %s(%d)\n", __func__, __LINE__);
|
||||
goto put_regulator;
|
||||
}
|
||||
ret_enable = regulator_enable(*pp_vreg);
|
||||
if (ret_enable) {
|
||||
pr_err("stmvl53l5 : Error at %s(%d)\n", __func__, __LINE__);
|
||||
goto disable_regulator;
|
||||
}
|
||||
|
||||
disable_regulator:
|
||||
if(ret_enable) {
|
||||
regulator_disable(*pp_vreg);
|
||||
regulator_set_load(*pp_vreg, 0);
|
||||
regulator_set_voltage(*pp_vreg, 0, 3008000);
|
||||
}
|
||||
put_regulator:
|
||||
if (ret_enable || ret_source) {
|
||||
regulator_put(*pp_vreg);
|
||||
*pp_vreg = NULL;
|
||||
}
|
||||
return ret_enable || ret_source;
|
||||
}
|
||||
|
||||
static int enable_power(struct spi_device *spi)
|
||||
{
|
||||
int ret = -1;
|
||||
ret = enable_regulator_3V0(&spi->dev,&p_3v0_vreg);
|
||||
ret |= enable_regulator_1V8(&spi->dev,&p_1v8_vreg);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void disable_power(void)
|
||||
{
|
||||
regulator_disable(p_1v8_vreg);
|
||||
regulator_set_load(p_1v8_vreg, 0);
|
||||
regulator_set_voltage(p_1v8_vreg, 0, 1800000);
|
||||
regulator_put(p_1v8_vreg);
|
||||
p_1v8_vreg = NULL;
|
||||
|
||||
regulator_disable(p_3v0_vreg);
|
||||
regulator_set_load(p_3v0_vreg, 0);
|
||||
regulator_set_voltage(p_3v0_vreg, 0, 3008000);
|
||||
regulator_put(p_3v0_vreg);
|
||||
p_3v0_vreg = NULL;
|
||||
}
|
||||
|
||||
static int stmvl53l5_open(struct inode *inode, struct file *file)
|
||||
{
|
||||
printk("stmvl53l5 : %s(%d)\n", __func__, __LINE__);
|
||||
if (unlikely(spi_data.nusers >= SHRT_MAX)) {
|
||||
dev_err(&spi_data.device->dev, "device busy\n");
|
||||
return -EBUSY;
|
||||
}
|
||||
mutex_lock(&spi_data.mutex);
|
||||
/*if (spi_data.nusers == 0) {
|
||||
regulator_enable(p_3v0_vreg);
|
||||
regulator_enable(p_1v8_vreg);
|
||||
}*/
|
||||
spi_data.nusers++;
|
||||
printk("stmvl53l5_open : spi_data.nusers = %u\n", spi_data.nusers);
|
||||
mutex_unlock(&spi_data.mutex);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int stmvl53l5_release(struct inode *inode, struct file *file)
|
||||
{
|
||||
printk("stmvl53l5 : %s(%d)\n", __func__, __LINE__);
|
||||
mutex_lock(&spi_data.mutex);
|
||||
printk("stmvl53l5_release : spi_data.nusers = %u\n", spi_data.nusers);
|
||||
spi_data.nusers--;
|
||||
/*if (spi_data.nusers == 0) {
|
||||
regulator_disable(p_1v8_vreg);
|
||||
regulator_disable(p_3v0_vreg);
|
||||
}*/
|
||||
mutex_unlock(&spi_data.mutex);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static long stmvl53l5_ioctl(struct file *file,
|
||||
unsigned int cmd, unsigned long arg)
|
||||
{
|
||||
struct i2c_msg st_i2c_message;
|
||||
struct stmvl53l5_comms_struct comms_struct;
|
||||
int32_t ret = 0;
|
||||
uint16_t index, transfer_size, chunk_size;
|
||||
u8 __user *data_ptr = NULL;
|
||||
|
||||
pr_debug("stmvl53l5_ioctl : cmd = %u\n", cmd);
|
||||
switch (cmd) {
|
||||
case ST_TOF_IOCTL_TRANSFER:
|
||||
|
||||
ret = copy_from_user(&comms_struct, (void __user *)arg, sizeof(comms_struct));
|
||||
if (ret) {
|
||||
pr_err("Error at %s(%d)\n", __func__, __LINE__);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
//printk("Transfer. write_not_read = %d, reg_index = 0x%x size = %d\n", comms_struct.write_not_read, comms_struct.reg_index, comms_struct.len);
|
||||
|
||||
if (i2c_not_spi) {
|
||||
// address and buis the same whatever the transfers to be done !
|
||||
st_i2c_message.addr = 0x29;
|
||||
// st_i2c_message.buf is the same whatever the transfers to be done
|
||||
st_i2c_message.buf = raw_data_buffer;
|
||||
}
|
||||
|
||||
if (!comms_struct.write_not_read) {
|
||||
data_ptr = (u8 __user *)(comms_struct.buf);
|
||||
}
|
||||
|
||||
// in case of i2c write, it is a single transfer with read index set in the 2 first bytes
|
||||
// the other case use fully the raw data buffer for raw data transfers
|
||||
if ((i2c_not_spi) && (comms_struct.write_not_read))
|
||||
chunk_size = VL53L5_COMMS_CHUNK_SIZE - 2;
|
||||
else
|
||||
chunk_size = VL53L5_COMMS_CHUNK_SIZE;
|
||||
|
||||
// index is the number of bytes already transfered
|
||||
index = 0;
|
||||
|
||||
do {
|
||||
// take the max number of bytes that can be transfered
|
||||
transfer_size = (comms_struct.len - index) > chunk_size ? chunk_size : (comms_struct.len - index);
|
||||
|
||||
// ----- WRITE
|
||||
if (comms_struct.write_not_read) {
|
||||
// ---- i2c
|
||||
if (i2c_not_spi) {
|
||||
// put red index at the beginning of the buffer
|
||||
raw_data_buffer[0] = (uint8_t)(((comms_struct.reg_index + index) & 0xFF00) >> 8);
|
||||
raw_data_buffer[1] = (uint8_t)((comms_struct.reg_index + index) & 0x00FF);
|
||||
|
||||
ret = copy_from_user(&raw_data_buffer[2], comms_struct.buf + index, transfer_size);
|
||||
if (ret) {
|
||||
pr_err("Error at %s(%d)\n", __func__, __LINE__);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
st_i2c_message.len = transfer_size + 2;
|
||||
st_i2c_message.flags = 0;
|
||||
ret = i2c_transfer(stmvl53l5_i2c_client->adapter, &st_i2c_message, 1);
|
||||
if (ret != 1) {
|
||||
pr_err("Error %d at %s(%d)\n",ret, __func__, __LINE__);
|
||||
return -EIO;
|
||||
}
|
||||
}
|
||||
// ---- spi
|
||||
else {
|
||||
ret = copy_from_user(raw_data_buffer, comms_struct.buf + index, transfer_size);
|
||||
if (ret) {
|
||||
pr_err("stmvl53l5: Error at %s(%d)\n", __func__, __LINE__);
|
||||
return -EINVAL;
|
||||
}
|
||||
ret = stmvl53l5_spi_write(&spi_data, comms_struct.reg_index + index, raw_data_buffer, transfer_size);
|
||||
if (ret) {
|
||||
pr_err("Error %d at %s(%d)\n",ret, __func__, __LINE__);
|
||||
return -EIO;
|
||||
}
|
||||
}
|
||||
}
|
||||
// ----- READ
|
||||
else {
|
||||
// ---- i2c
|
||||
if (i2c_not_spi) {
|
||||
// write reg_index
|
||||
st_i2c_message.len = 2;
|
||||
st_i2c_message.flags = 0;
|
||||
raw_data_buffer[0] = (uint8_t)(((comms_struct.reg_index + index) & 0xFF00) >> 8);
|
||||
raw_data_buffer[1] = (uint8_t)((comms_struct.reg_index + index) & 0x00FF);
|
||||
|
||||
ret = i2c_transfer(stmvl53l5_i2c_client->adapter, &st_i2c_message, 1);
|
||||
if (ret != 1) {
|
||||
pr_err("Error at %s(%d)\n", __func__, __LINE__);
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
st_i2c_message.len = transfer_size;
|
||||
st_i2c_message.flags = 1;
|
||||
|
||||
ret = i2c_transfer(stmvl53l5_i2c_client->adapter, &st_i2c_message, 1);
|
||||
if (ret != 1) {
|
||||
pr_err("Error at %s(%d)\n", __func__, __LINE__);
|
||||
return -EIO;
|
||||
}
|
||||
}
|
||||
// ---- spi
|
||||
else {
|
||||
ret = stmvl53l5_spi_read(&spi_data, comms_struct.reg_index + index, raw_data_buffer, transfer_size);
|
||||
if (ret) {
|
||||
pr_err("stmvl53l5: Error at %s(%d)\n", __func__, __LINE__);
|
||||
return -EIO;
|
||||
}
|
||||
}
|
||||
|
||||
// copy to user buffer the read transfer
|
||||
ret = copy_to_user(data_ptr + index, raw_data_buffer, transfer_size);
|
||||
|
||||
if (ret) {
|
||||
pr_err("Error at %s(%d)\n", __func__, __LINE__);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
} // ----- READ
|
||||
|
||||
index += transfer_size;
|
||||
|
||||
} while (index < comms_struct.len);
|
||||
break;
|
||||
|
||||
default:
|
||||
return -EINVAL;
|
||||
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct file_operations stmvl53l5_ranging_fops = {
|
||||
.owner = THIS_MODULE,
|
||||
.unlocked_ioctl = stmvl53l5_ioctl,
|
||||
.open = stmvl53l5_open,
|
||||
.release = stmvl53l5_release,
|
||||
};
|
||||
|
||||
static int stmvl53l5_i2c_probe(struct i2c_client *client,
|
||||
const struct i2c_device_id *id)
|
||||
{
|
||||
int ret;
|
||||
uint8_t page = 0, revision_id = 0, device_id = 0;
|
||||
stmvl53l5_i2c_client = client;
|
||||
|
||||
i2c_not_spi = 1;
|
||||
|
||||
printk("stmvl53l5: probing i2c\n");
|
||||
|
||||
raw_data_buffer = kzalloc(VL53L5_COMMS_CHUNK_SIZE, GFP_DMA | GFP_KERNEL);
|
||||
if (raw_data_buffer == NULL)
|
||||
return -ENOMEM;
|
||||
|
||||
ret = stmvl53l5_write_multi(client, raw_data_buffer, 0x7FFF, &page, 1);
|
||||
ret |= stmvl53l5_read_multi(client, raw_data_buffer, 0x00, &device_id, 1);
|
||||
ret |= stmvl53l5_read_multi(client, raw_data_buffer, 0x01, &revision_id, 1);
|
||||
|
||||
if ((device_id != 0xF0) || (revision_id != 0x02)) {
|
||||
pr_err("stmvl53l5: Error. Could not read device and revision id registers\n");
|
||||
return ret;
|
||||
}
|
||||
printk("stmvl53l5: device_id : 0x%x. revision_id : 0x%x\n", device_id, revision_id);
|
||||
|
||||
st_tof_miscdev.minor = MISC_DYNAMIC_MINOR;
|
||||
st_tof_miscdev.name = "stmvl53l5";
|
||||
st_tof_miscdev.fops = &stmvl53l5_ranging_fops;
|
||||
st_tof_miscdev.mode = 0444;
|
||||
|
||||
ret = misc_register(&st_tof_miscdev);
|
||||
if (ret) {
|
||||
pr_err("stmvl53l5 : Failed to create misc device, err = %d\n", ret);
|
||||
return -1;
|
||||
}
|
||||
|
||||
misc_registered = 1;
|
||||
|
||||
ret = stmvl53l5_load_fw_stm(client, raw_data_buffer);
|
||||
if (ret) {
|
||||
pr_err("stmvl53l5 : Failed in loading the FW into the device, err = %d\n", ret);
|
||||
}
|
||||
|
||||
ret = stmvl53l5_move_device_to_low_power(client, NULL, 1, raw_data_buffer);
|
||||
if (ret) {
|
||||
pr_err("stmvl53l5 : could not move the device to low power = %d\n", ret);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int stmvl53l5_i2c_remove(struct i2c_client *client)
|
||||
{
|
||||
|
||||
if (raw_data_buffer)
|
||||
kfree(raw_data_buffer);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct i2c_driver stmvl53l5_i2c_driver = {
|
||||
.driver = {
|
||||
.name = STMVL53L5_DRV_NAME,
|
||||
.owner = THIS_MODULE,
|
||||
.of_match_table = of_match_ptr(st_tof_of_match), // for platform register to pick up the dts info
|
||||
},
|
||||
.probe = stmvl53l5_i2c_probe,
|
||||
.remove = stmvl53l5_i2c_remove,
|
||||
.id_table = stmvl53l5_i2c_id,
|
||||
};
|
||||
|
||||
static int stmvl53l5_spi_probe(struct spi_device *spi)
|
||||
{
|
||||
int ret = -1;
|
||||
uint8_t page = 0, revision_id = 0, device_id = 0;
|
||||
|
||||
if(enable_power(spi)) {
|
||||
pr_err("stmvl53l5: Error. Could not enable power, return -1\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
i2c_not_spi = 0;
|
||||
mutex_init(&spi_data.mutex);
|
||||
|
||||
spi_data.device = spi;
|
||||
spi_data.device->mode |= SPI_CPHA;
|
||||
spi_data.device->mode |= SPI_CPOL;
|
||||
|
||||
ret = stmvl53l5_spi_write(&spi_data, 0x7FFF, &page, 1);
|
||||
ret |= stmvl53l5_spi_read(&spi_data, 0x00, &device_id, 1);
|
||||
ret |= stmvl53l5_spi_read(&spi_data, 0x01, &revision_id, 1);
|
||||
|
||||
if ((device_id != 0xF0) || (revision_id != 0x02)) {
|
||||
pr_err("stmvl53l5: Error. Could not read device and revision id registers\n");
|
||||
ret = -1;
|
||||
goto quitpower;
|
||||
}
|
||||
printk("stmvl53l5: device_id : 0x%x. revision_id : 0x%x\n", device_id, revision_id);
|
||||
|
||||
raw_data_buffer = kzalloc(VL53L5_COMMS_CHUNK_SIZE, GFP_DMA | GFP_KERNEL);
|
||||
if (raw_data_buffer == NULL) {
|
||||
ret = -ENOMEM;
|
||||
goto quitpower;
|
||||
}
|
||||
st_tof_miscdev.minor = MISC_DYNAMIC_MINOR;
|
||||
st_tof_miscdev.name = "stmvl53l5";
|
||||
st_tof_miscdev.fops = &stmvl53l5_ranging_fops;
|
||||
st_tof_miscdev.mode = 0444;
|
||||
|
||||
ret = misc_register(&st_tof_miscdev);
|
||||
if (ret) {
|
||||
pr_err("stmvl53l5 : Failed to create misc device, err = %d\n", ret);
|
||||
ret = -2;
|
||||
goto quitmisc;
|
||||
}
|
||||
|
||||
misc_registered = 1;
|
||||
|
||||
/*regulator_disable(p_1v8_vreg);
|
||||
regulator_disable(p_3v0_vreg);*/
|
||||
quitmisc:
|
||||
if (ret == -2)
|
||||
misc_deregister(&st_tof_miscdev);
|
||||
|
||||
quitpower:
|
||||
if(ret == -1 || ret == -2 || ret == -ENOMEM)
|
||||
disable_power();
|
||||
|
||||
return ret;
|
||||
|
||||
}
|
||||
|
||||
static int stmvl53l5_spi_remove(struct spi_device *device)
|
||||
{
|
||||
|
||||
if (raw_data_buffer)
|
||||
kfree(raw_data_buffer);
|
||||
disable_power();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct spi_driver stmvl53l5_spi_driver = {
|
||||
.driver = {
|
||||
.name = STMVL53L5_DRV_NAME,
|
||||
.owner = THIS_MODULE,
|
||||
},
|
||||
.probe = stmvl53l5_spi_probe,
|
||||
.remove = stmvl53l5_spi_remove,
|
||||
.id_table = stmvl53l5_spi_id,
|
||||
};
|
||||
|
||||
static int __init st_tof_module_init(void)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
printk("stmvl53l5: module init\n");
|
||||
|
||||
/* register as a i2c client device */
|
||||
/* ret = i2c_add_driver(&stmvl53l5_i2c_driver);
|
||||
|
||||
if (ret) {
|
||||
i2c_del_driver(&stmvl53l5_i2c_driver);
|
||||
printk("stmvl53l5: could not add i2c driver\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
i2c_driver_added = 1;
|
||||
*/
|
||||
ret = spi_register_driver(&stmvl53l5_spi_driver);
|
||||
if (ret) {
|
||||
printk("stmvl53l5: could not register spi driver : %d", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
spi_driver_registered = 1;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void __exit st_tof_module_exit(void)
|
||||
{
|
||||
|
||||
printk("stmvl53l5 : module exit\n");
|
||||
|
||||
if (misc_registered) {
|
||||
misc_deregister(&st_tof_miscdev);
|
||||
misc_registered = 0;
|
||||
}
|
||||
|
||||
if (spi_driver_registered) {
|
||||
spi_unregister_driver(&stmvl53l5_spi_driver);
|
||||
spi_driver_registered = 0;
|
||||
}
|
||||
|
||||
if (i2c_driver_added) {
|
||||
i2c_del_driver(&stmvl53l5_i2c_driver);
|
||||
i2c_driver_added = 0;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
module_init(st_tof_module_init);
|
||||
module_exit(st_tof_module_exit);
|
||||
MODULE_LICENSE("GPL");
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
88
drivers/input/stmvl53l5/stmvl53l5_spi.c
Normal file
88
drivers/input/stmvl53l5/stmvl53l5_spi.c
Normal file
@@ -0,0 +1,88 @@
|
||||
/*
|
||||
* This file is part of VL53L5 Kernel Driver
|
||||
*
|
||||
* Copyright (C) 2020, STMicroelectronics - All Rights Reserved
|
||||
*
|
||||
* License terms: STMicroelectronics Proprietary in accordance with licensing
|
||||
* terms at www.st.com/sla0081
|
||||
*
|
||||
* STMicroelectronics confidential
|
||||
* Reproduction and Communication of this document is strictly prohibited unless
|
||||
* specifically authorized in writing by STMicroelectronics.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <linux/spi/spi.h>
|
||||
#include <stddef.h>
|
||||
|
||||
#include "stmvl53l5_spi.h"
|
||||
|
||||
|
||||
#define SPI_READWRITE_BIT 0x8000
|
||||
|
||||
#define SPI_WRITE_MASK(x) (x | SPI_READWRITE_BIT)
|
||||
#define SPI_READ_MASK(x) (x & ~SPI_READWRITE_BIT)
|
||||
|
||||
int stmvl53l5_spi_write(struct spi_data_t *spi_data, int index, uint8_t *data, uint16_t len)
|
||||
{
|
||||
int status = 0;
|
||||
uint8_t index_bytes[2] = {0};
|
||||
struct spi_message m;
|
||||
struct spi_transfer t[2];
|
||||
|
||||
spi_message_init(&m);
|
||||
memset(&t, 0, sizeof(t));
|
||||
|
||||
index_bytes[0] = ((SPI_WRITE_MASK(index) & 0xff00) >> 8);
|
||||
index_bytes[1] = (SPI_WRITE_MASK(index) & 0xff);
|
||||
|
||||
t[0].tx_buf = index_bytes;
|
||||
t[0].len = 2;
|
||||
|
||||
t[1].tx_buf = data;
|
||||
t[1].len = (unsigned int)len;
|
||||
|
||||
spi_message_add_tail(&t[0], &m);
|
||||
spi_message_add_tail(&t[1], &m);
|
||||
|
||||
status = spi_sync(spi_data->device, &m);
|
||||
if (status != 0) {
|
||||
printk("stmvl53l5 : spi_sync failed. %d", status);
|
||||
goto out;
|
||||
}
|
||||
|
||||
out:
|
||||
return status;
|
||||
}
|
||||
|
||||
int stmvl53l5_spi_read(struct spi_data_t *spi_data, int index, uint8_t *data, uint16_t len)
|
||||
{
|
||||
int status = 0;
|
||||
uint8_t index_bytes[2] = {0};
|
||||
struct spi_message m;
|
||||
struct spi_transfer t[2];
|
||||
|
||||
spi_message_init(&m);
|
||||
memset(&t, 0, sizeof(t));
|
||||
|
||||
index_bytes[0] = ((SPI_READ_MASK(index) >> 8) & 0xff);
|
||||
index_bytes[1] = (SPI_READ_MASK(index) & 0xff);
|
||||
|
||||
t[0].tx_buf = index_bytes;
|
||||
t[0].len = 2;
|
||||
|
||||
t[1].rx_buf = data;
|
||||
t[1].len = (unsigned int)len;
|
||||
|
||||
spi_message_add_tail(&t[0], &m);
|
||||
spi_message_add_tail(&t[1], &m);
|
||||
|
||||
status = spi_sync(spi_data->device, &m);
|
||||
if (status != 0) {
|
||||
printk("stmvl53l5 : spi_sync failed. %d", status);
|
||||
goto out;
|
||||
}
|
||||
|
||||
out:
|
||||
return status;
|
||||
}
|
||||
44
drivers/input/stmvl53l5/stmvl53l5_spi.h
Normal file
44
drivers/input/stmvl53l5/stmvl53l5_spi.h
Normal file
@@ -0,0 +1,44 @@
|
||||
/**************************************************************************
|
||||
* Copyright (c) 2016, STMicroelectronics - All Rights Reserved
|
||||
|
||||
License terms: BSD 3-clause "New" or "Revised" License.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright notice, this
|
||||
list of conditions and the following disclaimer.
|
||||
|
||||
2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
|
||||
3. Neither the name of the copyright holder nor the names of its contributors
|
||||
may be used to endorse or promote products derived from this software
|
||||
without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
||||
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef STMVL53L5_SPI_H
|
||||
#define STMVL53L5_SPI_H
|
||||
|
||||
struct spi_data_t {
|
||||
struct spi_device *device;
|
||||
u16 nusers;
|
||||
struct mutex mutex;
|
||||
};
|
||||
|
||||
int stmvl53l5_spi_write(struct spi_data_t *spi_data, int index, uint8_t *data, uint16_t len);
|
||||
int stmvl53l5_spi_read(struct spi_data_t *spi_data, int index, uint8_t *data, uint16_t len);
|
||||
|
||||
#endif
|
||||
43027
drivers/input/stmvl53l5/vl53l5_fw_data.h
Normal file
43027
drivers/input/stmvl53l5/vl53l5_fw_data.h
Normal file
File diff suppressed because it is too large
Load Diff
@@ -12,6 +12,11 @@ menuconfig INPUT_TOUCHSCREEN
|
||||
|
||||
if INPUT_TOUCHSCREEN
|
||||
|
||||
config TOUCHSCREEN_QGKI_GOODIX
|
||||
default n
|
||||
bool "QGKI config"
|
||||
|
||||
|
||||
config TOUCHSCREEN_PROPERTIES
|
||||
def_tristate INPUT
|
||||
depends on INPUT
|
||||
@@ -1317,10 +1322,28 @@ source "drivers/input/touchscreen/focaltech_touch/Kconfig"
|
||||
|
||||
source "drivers/input/touchscreen/synaptics_tcm/Kconfig"
|
||||
|
||||
source "drivers/input/touchscreen/fts_521/Kconfig"
|
||||
|
||||
source "drivers/input/touchscreen/fts_dual/Kconfig"
|
||||
|
||||
source "drivers/input/touchscreen/xiaomi/Kconfig"
|
||||
|
||||
source "drivers/input/touchscreen/fts_spi/Kconfig"
|
||||
|
||||
source "drivers/input/touchscreen/cyttsp5/Kconfig"
|
||||
|
||||
source "drivers/input/touchscreen/zinitix_bt541/Kconfig"
|
||||
|
||||
source "drivers/input/touchscreen/focaltech_spi/Kconfig"
|
||||
|
||||
source "drivers/input/touchscreen/gt9897t/Kconfig"
|
||||
|
||||
source "drivers/input/touchscreen/focaltech_3658u/Kconfig"
|
||||
|
||||
config TOUCHSCREEN_SYNAPTICS_DSX
|
||||
bool "Synaptics DSX Touchscreen Driver"
|
||||
depends on I2C
|
||||
default y
|
||||
default n
|
||||
help
|
||||
Say Y here if you have a Synaptics Touchscreen.
|
||||
|
||||
@@ -1331,6 +1354,14 @@ config TOUCHSCREEN_SYNAPTICS_DSX
|
||||
|
||||
source "drivers/input/touchscreen/synaptics_dsx/Kconfig"
|
||||
|
||||
source "drivers/input/touchscreen/synaptics_s3908p/Kconfig"
|
||||
|
||||
source "drivers/input/touchscreen/synaptics_touch/Kconfig"
|
||||
|
||||
source "drivers/input/touchscreen/nt36xxx/Kconfig"
|
||||
|
||||
source "drivers/input/touchscreen/goodix_9916/Kconfig"
|
||||
|
||||
source "drivers/input/touchscreen/focaltech_3680/Kconfig"
|
||||
|
||||
endif
|
||||
|
||||
@@ -113,5 +113,16 @@ obj-$(CONFIG_TOUCHSCREEN_IQS5XX) += iqs5xx.o
|
||||
obj-$(CONFIG_TOUCHSCREEN_ST) += st/
|
||||
obj-$(CONFIG_TOUCHSCREEN_FTS) += focaltech_touch/
|
||||
obj-$(CONFIG_TOUCHSCREEN_SYNAPTICS_TCM) += synaptics_tcm/
|
||||
obj-$(CONFIG_TOUCHSCREEN_XIAOMI_TOUCHFEATURE) += xiaomi/
|
||||
obj-$(CONFIG_TOUCHSCREEN_ST_FTS_V521_DUAL) += fts_dual/
|
||||
obj-$(CONFIG_TOUCHSCREEN_CYPRESS_CYTTSP5) += cyttsp5/
|
||||
obj-$(CONFIG_TOUCHSCREEN_ZINITIX_BT541) += zinitix_bt541/
|
||||
obj-$(CONFIG_TOUCHSCREEN_FOCALTECH) += focaltech_spi/
|
||||
obj-$(CONFIG_TOUCHSCREEN_GOODIX_BRL) += gt9897t/
|
||||
obj-$(CONFIG_TOUCHSCREEN_SYNAPTICS_DSX) += synaptics_dsx/
|
||||
obj-$(CONFIG_TOUCHSCREEN_FOCALTECH_3658U) += focaltech_3658u/
|
||||
obj-$(CONFIG_TOUCHSCREEN_NT36XXX) += nt36xxx/
|
||||
obj-$(CONFIG_TOUCHSCREEN_SYNAPTICS_TCM_S3908P) += synaptics_s3908p/
|
||||
obj-$(CONFIG_TOUCHSCREEN_SYNAPTICS_TCM_S3908P_TOUCH) += synaptics_touch/
|
||||
obj-$(CONFIG_TOUCHSCREEN_GOODIX_BRL_9916) += goodix_9916/
|
||||
obj-$(CONFIG_TOUCHSCREEN_FOCALTECH_3680) += focaltech_3680/
|
||||
|
||||
199
drivers/input/touchscreen/cyttsp5/Kconfig
Normal file
199
drivers/input/touchscreen/cyttsp5/Kconfig
Normal file
@@ -0,0 +1,199 @@
|
||||
config TOUCHSCREEN_CYPRESS_CYTTSP5
|
||||
tristate "Parade TrueTouch Gen5 Touchscreen Driver"
|
||||
help
|
||||
Core driver for Parade TrueTouch(tm) Standard Product
|
||||
Geneartion5 touchscreen controllers.
|
||||
|
||||
Say Y here if you have a Parade Gen5 touchscreen.
|
||||
|
||||
If unsure, say N.
|
||||
|
||||
To compile this driver as a module, choose M here: the
|
||||
module will be called cyttsp5.
|
||||
|
||||
config TOUCHSCREEN_CYPRESS_CYTTSP5_DEVICETREE_SUPPORT
|
||||
bool "Enable Device Tree support"
|
||||
depends on TOUCHSCREEN_CYPRESS_CYTTSP5 && OF
|
||||
help
|
||||
Say Y here to enable support for device tree.
|
||||
|
||||
If unsure, say N.
|
||||
|
||||
config TOUCHSCREEN_CYPRESS_CYTTSP5_I2C
|
||||
tristate "Parade TrueTouch Gen5 I2C"
|
||||
depends on TOUCHSCREEN_CYPRESS_CYTTSP5
|
||||
select I2C
|
||||
help
|
||||
Say Y here to enable I2C bus interface to Parade TrueTouch(tm)
|
||||
Standard Product Generation5 touchscreen controller.
|
||||
|
||||
If unsure, say Y.
|
||||
|
||||
To compile this driver as a module, choose M here: the
|
||||
module will be called cyttsp5_i2c.
|
||||
|
||||
config TOUCHSCREEN_CYPRESS_CYTTSP5_SPI
|
||||
tristate "Parade TrueTouch Gen5 SPI"
|
||||
depends on TOUCHSCREEN_CYPRESS_CYTTSP5
|
||||
select SPI
|
||||
help
|
||||
Say Y here to enable SPI bus interface to Parade TrueTouch(tm)
|
||||
Standard Product Generation5 touchscreen controller.
|
||||
|
||||
If unsure, say N.
|
||||
|
||||
To compile this driver as a module, choose M here: the
|
||||
module will be called cyttsp5_spi.
|
||||
|
||||
choice
|
||||
bool "Parade TrueTouch Gen5 MultiTouch Protocol"
|
||||
depends on TOUCHSCREEN_CYPRESS_CYTTSP5
|
||||
default TOUCHSCREEN_CYPRESS_CYTTSP5_MT_B
|
||||
help
|
||||
This option controls which MultiTouch protocol will be used to
|
||||
report the touch events.
|
||||
|
||||
config TOUCHSCREEN_CYPRESS_CYTTSP5_MT_A
|
||||
bool "Protocol A"
|
||||
help
|
||||
Select to enable MultiTouch touch reporting using protocol A
|
||||
on Parade TrueTouch(tm) Standard Product Generation4 touchscreen
|
||||
controller.
|
||||
|
||||
config TOUCHSCREEN_CYPRESS_CYTTSP5_MT_B
|
||||
bool "Protocol B"
|
||||
help
|
||||
Select to enable MultiTouch touch reporting using protocol B
|
||||
on Parade TrueTouch(tm) Standard Product Generation4 touchscreen
|
||||
controller.
|
||||
|
||||
endchoice
|
||||
|
||||
config TOUCHSCREEN_CYPRESS_CYTTSP5_BUTTON
|
||||
bool "Parade TrueTouch Gen5 MultiTouch CapSense Button"
|
||||
depends on TOUCHSCREEN_CYPRESS_CYTTSP5
|
||||
help
|
||||
Say Y here to enable CapSense reporting on Parade TrueTouch(tm)
|
||||
Standard Product Generation5 touchscreen controller.
|
||||
|
||||
If unsure, say N.
|
||||
|
||||
config TOUCHSCREEN_CYPRESS_CYTTSP5_PROXIMITY
|
||||
bool "Parade TrueTouch Gen5 Proximity"
|
||||
depends on TOUCHSCREEN_CYPRESS_CYTTSP5
|
||||
help
|
||||
Say Y here to enable proximity reporting on Parade TrueTouch(tm)
|
||||
Standard Product Generation5 touchscreen controller.
|
||||
|
||||
If unsure, say N.
|
||||
|
||||
config TOUCHSCREEN_CYPRESS_CYTTSP5_DEVICE_ACCESS
|
||||
tristate "Parade TrueTouch Gen5 MultiTouch Device Access"
|
||||
depends on TOUCHSCREEN_CYPRESS_CYTTSP5
|
||||
help
|
||||
Say Y here to enable Parade TrueTouch(tm) Standard Product
|
||||
Generation5 touchscreen controller device access module.
|
||||
|
||||
This modules adds an interface to access touchscreen
|
||||
controller using driver sysfs nodes.
|
||||
|
||||
If unsure, say N.
|
||||
|
||||
To compile this driver as a module, choose M here: the
|
||||
module will be called cyttsp5_device_access.
|
||||
|
||||
config TOUCHSCREEN_CYPRESS_CYTTSP5_DEVICE_ACCESS_API
|
||||
bool "Enable Device Access kernel API"
|
||||
depends on TOUCHSCREEN_CYPRESS_CYTTSP5_DEVICE_ACCESS
|
||||
help
|
||||
Say Y here to enable Device access kernel API which provides
|
||||
access to Parade TrueTouch(tm) Standard Product Generation5
|
||||
touchscreen controller for other modules.
|
||||
|
||||
If unsure, say N.
|
||||
|
||||
config TOUCHSCREEN_CYPRESS_CYTTSP5_TEST_DEVICE_ACCESS_API
|
||||
tristate "Simple Test module for Device Access kernel API"
|
||||
depends on TOUCHSCREEN_CYPRESS_CYTTSP5_DEVICE_ACCESS
|
||||
depends on TOUCHSCREEN_CYPRESS_CYTTSP5_DEVICE_ACCESS_API
|
||||
help
|
||||
Say Y here to enable test module for Device access kernel API.
|
||||
|
||||
If unsure, say N.
|
||||
|
||||
To compile this driver as a module, choose M here: the
|
||||
module will be called cyttsp5_test_device_access_api.
|
||||
|
||||
config TOUCHSCREEN_CYPRESS_CYTTSP5_LOADER
|
||||
tristate "Parade TrueTouch Gen5 MultiTouch Loader"
|
||||
depends on TOUCHSCREEN_CYPRESS_CYTTSP5
|
||||
help
|
||||
Say Y here to enable Parade TrueTouch(tm) Standard Product
|
||||
Generation5 touchscreen controller FW Loader module.
|
||||
|
||||
This module enables support for Firmware upgrade.
|
||||
|
||||
If unsure, say Y.
|
||||
|
||||
To compile this driver as a module, choose M here: the
|
||||
module will be called cyttsp5_loader.
|
||||
|
||||
config TOUCHSCREEN_CYPRESS_CYTTSP5_PLATFORM_FW_UPGRADE
|
||||
bool "FW upgrade from header file"
|
||||
depends on TOUCHSCREEN_CYPRESS_CYTTSP5_LOADER
|
||||
help
|
||||
Say Y here to include Parade TrueTouch(tm) Standard Product
|
||||
Generation5 device Firmware into driver.
|
||||
|
||||
Need proper header file for this.
|
||||
|
||||
If unsure, say N.
|
||||
|
||||
config TOUCHSCREEN_CYPRESS_CYTTSP5_BINARY_FW_UPGRADE
|
||||
bool "FW upgrade from binary file"
|
||||
depends on TOUCHSCREEN_CYPRESS_CYTTSP5_LOADER
|
||||
help
|
||||
Say Y here to include Parade TrueTouch(tm) Standard Product
|
||||
Generation5 device Firmware into kernel as binary blob.
|
||||
|
||||
This should be enabled for manual FW upgrade support.
|
||||
|
||||
If unsure, say Y.
|
||||
|
||||
config TOUCHSCREEN_CYPRESS_CYTTSP5_PLATFORM_TTCONFIG_UPGRADE
|
||||
bool "TT Configuration upgrade from header file"
|
||||
depends on TOUCHSCREEN_CYPRESS_CYTTSP5_LOADER
|
||||
help
|
||||
Say Y here to include Parade TrueTouch(tm) Standard Product
|
||||
Generation5 device TrueTouch Configuration into kernel itself.
|
||||
|
||||
Need proper header file for this.
|
||||
|
||||
If unsure, say N.
|
||||
|
||||
config TOUCHSCREEN_CYPRESS_CYTTSP5_MANUAL_TTCONFIG_UPGRADE
|
||||
bool "TT Configuration upgrade via SysFs"
|
||||
depends on TOUCHSCREEN_CYPRESS_CYTTSP5_LOADER
|
||||
help
|
||||
Say Y here to provide a SysFs interface to upgrade TrueTouch
|
||||
Configuration with a binary configuration file.
|
||||
|
||||
Need proper binary version of config file for this
|
||||
feature.
|
||||
|
||||
If unsure, say Y.
|
||||
|
||||
config TOUCHSCREEN_CYPRESS_CYTTSP5_DEBUG_MDL
|
||||
tristate "Parade TrueTouch Gen5 MultiTouch Debug Module"
|
||||
depends on TOUCHSCREEN_CYPRESS_CYTTSP5
|
||||
help
|
||||
Say Y here to enable Parade TrueTouch(tm) Standard Product
|
||||
Generation5 Debug module.
|
||||
|
||||
This module adds support for verbose printing touch
|
||||
information.
|
||||
|
||||
If unsure, say N.
|
||||
|
||||
To compile this driver as a module, choose M here: the
|
||||
module will be called cyttsp5_debug.
|
||||
33
drivers/input/touchscreen/cyttsp5/Makefile
Normal file
33
drivers/input/touchscreen/cyttsp5/Makefile
Normal file
@@ -0,0 +1,33 @@
|
||||
ifneq ($(KERNELRELEASE),)
|
||||
obj-$(CONFIG_TOUCHSCREEN_CYPRESS_CYTTSP5) += cyttsp5.o
|
||||
cyttsp5-y := cyttsp5_core.o cyttsp5_mt_common.o cyttsp5_platform.o \
|
||||
cyttsp5_mtb.o cyttsp5_devtree.o
|
||||
cyttsp5-$(CONFIG_TOUCHSCREEN_CYPRESS_CYTTSP5_BUTTON) += cyttsp5_btn.o
|
||||
cyttsp5-$(CONFIG_TOUCHSCREEN_CYPRESS_CYTTSP5_PROXIMITY) += cyttsp5_proximity.o
|
||||
# obj-$(CONFIG_TOUCHSCREEN_CYPRESS_CYTTSP5_DEVICETREE_SUPPORT) += cyttsp5_devtree.o
|
||||
obj-$(CONFIG_TOUCHSCREEN_CYPRESS_CYTTSP5_I2C) += cyttsp5_i2c.o
|
||||
obj-$(CONFIG_TOUCHSCREEN_CYPRESS_CYTTSP5_SPI) += cyttsp5_spi.o
|
||||
obj-$(CONFIG_TOUCHSCREEN_CYPRESS_CYTTSP5_DEBUG_MDL) += cyttsp5_debug.o
|
||||
obj-$(CONFIG_TOUCHSCREEN_CYPRESS_CYTTSP5_LOADER) += cyttsp5_loader.o
|
||||
obj-$(CONFIG_TOUCHSCREEN_CYPRESS_CYTTSP5_DEVICE_ACCESS) += cyttsp5_device_access.o
|
||||
else
|
||||
KDIR = $(OUT)/obj/KERNEL_OBJ
|
||||
CROSS_COMPILE = $(ANDROID_TOOLCHAIN)/aarch64-linux-android-
|
||||
CLANG = $(ANDROID_BUILD_TOP)/prebuilts/clang/host/linux-x86/clang-r370808
|
||||
REAL_CC = $(CLANG)/bin/clang
|
||||
AR = $(CLANG)/bin/llvm-ar
|
||||
LLVM_NM = $(CLANG)/bin/llvm-nm
|
||||
LD = $(CLANG)/bin/ld.lld
|
||||
|
||||
.PHONY: clean
|
||||
|
||||
default:
|
||||
$(MAKE) ARCH=arm64 CROSS_COMPILE=$(CROSS_COMPILE) REAL_CC=$(REAL_CC) CLANG_TRIPLE=aarch64-linux-gnu- AR=$(AR) LLVM_NM=$(LLVM_NM) LD=$(LD) -C $(KDIR) M=$(PWD) modules
|
||||
clean:
|
||||
@rm -rf *.order *.symvers* .tmp_versions
|
||||
@find -name "*.o*" -o -name "*.mod*" -o -name "*.ko*" | xargs rm -f
|
||||
endif
|
||||
|
||||
|
||||
|
||||
|
||||
369
drivers/input/touchscreen/cyttsp5/cyttsp5_btn.c
Normal file
369
drivers/input/touchscreen/cyttsp5/cyttsp5_btn.c
Normal file
@@ -0,0 +1,369 @@
|
||||
/*
|
||||
* cyttsp5_btn.c
|
||||
* Parade TrueTouch(TM) Standard Product V5 CapSense Reports Module.
|
||||
* For use with Parade touchscreen controllers.
|
||||
* Supported parts include:
|
||||
* CYTMA5XX
|
||||
* CYTMA448
|
||||
* CYTMA445A
|
||||
* CYTT21XXX
|
||||
* CYTT31XXX
|
||||
*
|
||||
* Copyright (C) 2015 Parade Technologies
|
||||
* Copyright (C) 2012-2015 Cypress Semiconductor
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* Contact Parade Technologies at www.paradetech.com <ttdrivers@paradetech.com>
|
||||
*
|
||||
*/
|
||||
|
||||
#include "cyttsp5_regs.h"
|
||||
|
||||
#define CYTTSP5_BTN_NAME "cyttsp5_btn"
|
||||
|
||||
static inline void cyttsp5_btn_key_action(struct cyttsp5_btn_data *bd,
|
||||
int btn_no, int btn_state)
|
||||
{
|
||||
struct device *dev = bd->dev;
|
||||
struct cyttsp5_sysinfo *si = bd->si;
|
||||
|
||||
if (!si->btn[btn_no].enabled ||
|
||||
si->btn[btn_no].state == btn_state)
|
||||
return;
|
||||
|
||||
si->btn[btn_no].state = btn_state;
|
||||
input_report_key(bd->input, si->btn[btn_no].key_code, btn_state);
|
||||
input_sync(bd->input);
|
||||
|
||||
parade_debug(dev, DEBUG_LEVEL_1, "%s: btn=%d key_code=%d %s\n",
|
||||
__func__, btn_no, si->btn[btn_no].key_code,
|
||||
btn_state == CY_BTN_PRESSED ?
|
||||
"PRESSED" : "RELEASED");
|
||||
}
|
||||
|
||||
static void cyttsp5_get_btn_touches(struct cyttsp5_btn_data *bd)
|
||||
{
|
||||
struct cyttsp5_sysinfo *si = bd->si;
|
||||
int num_btns = si->num_btns;
|
||||
int cur_btn;
|
||||
int cur_btn_state;
|
||||
|
||||
for (cur_btn = 0; cur_btn < num_btns; cur_btn++) {
|
||||
/* Get current button state */
|
||||
cur_btn_state = (si->xy_data[0] >> (cur_btn * CY_BITS_PER_BTN))
|
||||
& CY_NUM_BTN_EVENT_ID;
|
||||
|
||||
cyttsp5_btn_key_action(bd, cur_btn, cur_btn_state);
|
||||
}
|
||||
}
|
||||
|
||||
static void cyttsp5_btn_lift_all(struct cyttsp5_btn_data *bd)
|
||||
{
|
||||
struct cyttsp5_sysinfo *si = bd->si;
|
||||
int i;
|
||||
|
||||
if (!si || si->num_btns == 0)
|
||||
return;
|
||||
|
||||
for (i = 0; i < si->num_btns; i++)
|
||||
cyttsp5_btn_key_action(bd, i, CY_BTN_RELEASED);
|
||||
}
|
||||
|
||||
#ifdef VERBOSE_DEBUG
|
||||
static void cyttsp5_log_btn_data(struct cyttsp5_btn_data *bd)
|
||||
{
|
||||
struct device *dev = bd->dev;
|
||||
struct cyttsp5_core_data *cd = dev_get_drvdata(dev);
|
||||
u8 *pr_buf = cd->pr_buf;
|
||||
struct cyttsp5_sysinfo *si = bd->si;
|
||||
int cur;
|
||||
int value;
|
||||
|
||||
for (cur = 0; cur < si->num_btns; cur++) {
|
||||
pr_buf[0] = 0;
|
||||
if (si->xy_data[0] & (1 << cur))
|
||||
value = 1;
|
||||
else
|
||||
value = 0;
|
||||
snprintf(pr_buf, CY_MAX_PRBUF_SIZE, "btn_rec[%d]=0x", cur);
|
||||
snprintf(pr_buf, CY_MAX_PRBUF_SIZE, "%s%X (%02X)",
|
||||
pr_buf, value,
|
||||
le16_to_cpu(si->xy_data[1 + cur * 2]));
|
||||
|
||||
parade_debug(dev, DEBUG_LEVEL_2, "%s: %s\n", __func__, pr_buf);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
/* read xy_data for all current CapSense button touches */
|
||||
static int cyttsp5_xy_worker(struct cyttsp5_btn_data *bd)
|
||||
{
|
||||
struct cyttsp5_sysinfo *si = bd->si;
|
||||
|
||||
/* extract button press/release touch information */
|
||||
if (si->num_btns > 0) {
|
||||
cyttsp5_get_btn_touches(bd);
|
||||
#ifdef VERBOSE_DEBUG
|
||||
/* log button press/release touch information */
|
||||
cyttsp5_log_btn_data(bd);
|
||||
#endif
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int cyttsp5_btn_attention(struct device *dev)
|
||||
{
|
||||
struct cyttsp5_core_data *cd = dev_get_drvdata(dev);
|
||||
struct cyttsp5_btn_data *bd = &cd->bd;
|
||||
int rc;
|
||||
|
||||
if (bd->si->xy_mode[2] != bd->si->desc.btn_report_id)
|
||||
return 0;
|
||||
|
||||
/* core handles handshake */
|
||||
mutex_lock(&bd->btn_lock);
|
||||
rc = cyttsp5_xy_worker(bd);
|
||||
mutex_unlock(&bd->btn_lock);
|
||||
if (rc < 0)
|
||||
dev_err(dev, "%s: xy_worker error r=%d\n", __func__, rc);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int cyttsp5_startup_attention(struct device *dev)
|
||||
{
|
||||
struct cyttsp5_core_data *cd = dev_get_drvdata(dev);
|
||||
struct cyttsp5_btn_data *bd = &cd->bd;
|
||||
|
||||
mutex_lock(&bd->btn_lock);
|
||||
cyttsp5_btn_lift_all(bd);
|
||||
mutex_unlock(&bd->btn_lock);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int cyttsp5_btn_suspend_attention(struct device *dev)
|
||||
{
|
||||
struct cyttsp5_core_data *cd = dev_get_drvdata(dev);
|
||||
struct cyttsp5_btn_data *bd = &cd->bd;
|
||||
|
||||
mutex_lock(&bd->btn_lock);
|
||||
cyttsp5_btn_lift_all(bd);
|
||||
bd->is_suspended = true;
|
||||
mutex_unlock(&bd->btn_lock);
|
||||
|
||||
pm_runtime_put(dev);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int cyttsp5_btn_resume_attention(struct device *dev)
|
||||
{
|
||||
struct cyttsp5_core_data *cd = dev_get_drvdata(dev);
|
||||
struct cyttsp5_btn_data *bd = &cd->bd;
|
||||
|
||||
pm_runtime_get(dev);
|
||||
|
||||
mutex_lock(&bd->btn_lock);
|
||||
bd->is_suspended = false;
|
||||
mutex_unlock(&bd->btn_lock);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int cyttsp5_btn_open(struct input_dev *input)
|
||||
{
|
||||
struct device *dev = input->dev.parent;
|
||||
struct cyttsp5_core_data *cd = dev_get_drvdata(dev);
|
||||
struct cyttsp5_btn_data *bd = &cd->bd;
|
||||
|
||||
pm_runtime_get_sync(dev);
|
||||
|
||||
mutex_lock(&bd->btn_lock);
|
||||
bd->is_suspended = false;
|
||||
mutex_unlock(&bd->btn_lock);
|
||||
|
||||
parade_debug(dev, DEBUG_LEVEL_2, "%s: setup subscriptions\n", __func__);
|
||||
|
||||
/* set up touch call back */
|
||||
_cyttsp5_subscribe_attention(dev, CY_ATTEN_IRQ, CYTTSP5_BTN_NAME,
|
||||
cyttsp5_btn_attention, CY_MODE_OPERATIONAL);
|
||||
|
||||
/* set up startup call back */
|
||||
_cyttsp5_subscribe_attention(dev, CY_ATTEN_STARTUP, CYTTSP5_BTN_NAME,
|
||||
cyttsp5_startup_attention, 0);
|
||||
|
||||
/* set up suspend call back */
|
||||
_cyttsp5_subscribe_attention(dev, CY_ATTEN_SUSPEND, CYTTSP5_BTN_NAME,
|
||||
cyttsp5_btn_suspend_attention, 0);
|
||||
|
||||
/* set up resume call back */
|
||||
_cyttsp5_subscribe_attention(dev, CY_ATTEN_RESUME, CYTTSP5_BTN_NAME,
|
||||
cyttsp5_btn_resume_attention, 0);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void cyttsp5_btn_close(struct input_dev *input)
|
||||
{
|
||||
struct device *dev = input->dev.parent;
|
||||
struct cyttsp5_core_data *cd = dev_get_drvdata(dev);
|
||||
struct cyttsp5_btn_data *bd = &cd->bd;
|
||||
|
||||
_cyttsp5_unsubscribe_attention(dev, CY_ATTEN_IRQ, CYTTSP5_BTN_NAME,
|
||||
cyttsp5_btn_attention, CY_MODE_OPERATIONAL);
|
||||
|
||||
_cyttsp5_unsubscribe_attention(dev, CY_ATTEN_STARTUP, CYTTSP5_BTN_NAME,
|
||||
cyttsp5_startup_attention, 0);
|
||||
|
||||
_cyttsp5_unsubscribe_attention(dev, CY_ATTEN_SUSPEND, CYTTSP5_BTN_NAME,
|
||||
cyttsp5_btn_suspend_attention, 0);
|
||||
|
||||
_cyttsp5_unsubscribe_attention(dev, CY_ATTEN_RESUME, CYTTSP5_BTN_NAME,
|
||||
cyttsp5_btn_resume_attention, 0);
|
||||
|
||||
mutex_lock(&bd->btn_lock);
|
||||
if (!bd->is_suspended) {
|
||||
pm_runtime_put(dev);
|
||||
bd->is_suspended = true;
|
||||
}
|
||||
mutex_unlock(&bd->btn_lock);
|
||||
}
|
||||
|
||||
static int cyttsp5_setup_input_device(struct device *dev)
|
||||
{
|
||||
struct cyttsp5_core_data *cd = dev_get_drvdata(dev);
|
||||
struct cyttsp5_btn_data *bd = &cd->bd;
|
||||
int i;
|
||||
int rc;
|
||||
|
||||
parade_debug(dev, DEBUG_LEVEL_2, "%s: Initialize event signals\n",
|
||||
__func__);
|
||||
__set_bit(EV_KEY, bd->input->evbit);
|
||||
parade_debug(dev, DEBUG_LEVEL_2, "%s: Number of buttons %d\n",
|
||||
__func__, bd->si->num_btns);
|
||||
for (i = 0; i < bd->si->num_btns; i++) {
|
||||
parade_debug(dev, DEBUG_LEVEL_2, "%s: btn:%d keycode:%d\n",
|
||||
__func__, i, bd->si->btn[i].key_code);
|
||||
__set_bit(bd->si->btn[i].key_code, bd->input->keybit);
|
||||
}
|
||||
|
||||
rc = input_register_device(bd->input);
|
||||
if (rc < 0)
|
||||
dev_err(dev, "%s: Error, failed register input device r=%d\n",
|
||||
__func__, rc);
|
||||
else
|
||||
bd->input_device_registered = true;
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int cyttsp5_setup_input_attention(struct device *dev)
|
||||
{
|
||||
struct cyttsp5_core_data *cd = dev_get_drvdata(dev);
|
||||
struct cyttsp5_btn_data *bd = &cd->bd;
|
||||
int rc;
|
||||
|
||||
bd->si = _cyttsp5_request_sysinfo(dev);
|
||||
if (!bd->si)
|
||||
return -1;
|
||||
|
||||
rc = cyttsp5_setup_input_device(dev);
|
||||
|
||||
_cyttsp5_unsubscribe_attention(dev, CY_ATTEN_STARTUP, CYTTSP5_BTN_NAME,
|
||||
cyttsp5_setup_input_attention, 0);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
int cyttsp5_btn_probe(struct device *dev)
|
||||
{
|
||||
struct cyttsp5_core_data *cd = dev_get_drvdata(dev);
|
||||
struct cyttsp5_btn_data *bd = &cd->bd;
|
||||
struct cyttsp5_platform_data *pdata = dev_get_platdata(dev);
|
||||
struct cyttsp5_btn_platform_data *btn_pdata;
|
||||
int rc = 0;
|
||||
|
||||
if (!pdata || !pdata->btn_pdata) {
|
||||
dev_err(dev, "%s: Missing platform data\n", __func__);
|
||||
rc = -ENODEV;
|
||||
goto error_no_pdata;
|
||||
}
|
||||
btn_pdata = pdata->btn_pdata;
|
||||
|
||||
mutex_init(&bd->btn_lock);
|
||||
bd->dev = dev;
|
||||
bd->pdata = btn_pdata;
|
||||
|
||||
/* Create the input device and register it. */
|
||||
parade_debug(dev, DEBUG_LEVEL_2, "%s: Create the input device and register it\n",
|
||||
__func__);
|
||||
bd->input = input_allocate_device();
|
||||
if (!bd->input) {
|
||||
dev_err(dev, "%s: Error, failed to allocate input device\n",
|
||||
__func__);
|
||||
rc = -ENODEV;
|
||||
goto error_alloc_failed;
|
||||
}
|
||||
|
||||
if (bd->pdata->inp_dev_name)
|
||||
bd->input->name = bd->pdata->inp_dev_name;
|
||||
else
|
||||
bd->input->name = CYTTSP5_BTN_NAME;
|
||||
scnprintf(bd->phys, sizeof(bd->phys), "%s/input%d", dev_name(dev),
|
||||
cd->phys_num++);
|
||||
bd->input->phys = bd->phys;
|
||||
bd->input->dev.parent = bd->dev;
|
||||
bd->input->open = cyttsp5_btn_open;
|
||||
bd->input->close = cyttsp5_btn_close;
|
||||
input_set_drvdata(bd->input, bd);
|
||||
|
||||
/* get sysinfo */
|
||||
bd->si = _cyttsp5_request_sysinfo(dev);
|
||||
|
||||
if (bd->si) {
|
||||
rc = cyttsp5_setup_input_device(dev);
|
||||
if (rc)
|
||||
goto error_init_input;
|
||||
} else {
|
||||
dev_err(dev, "%s: Fail get sysinfo pointer from core p=%p\n",
|
||||
__func__, bd->si);
|
||||
_cyttsp5_subscribe_attention(dev, CY_ATTEN_STARTUP,
|
||||
CYTTSP5_BTN_NAME, cyttsp5_setup_input_attention, 0);
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
error_init_input:
|
||||
input_free_device(bd->input);
|
||||
error_alloc_failed:
|
||||
error_no_pdata:
|
||||
dev_err(dev, "%s failed.\n", __func__);
|
||||
return rc;
|
||||
}
|
||||
|
||||
int cyttsp5_btn_release(struct device *dev)
|
||||
{
|
||||
struct cyttsp5_core_data *cd = dev_get_drvdata(dev);
|
||||
struct cyttsp5_btn_data *bd = &cd->bd;
|
||||
|
||||
if (bd->input_device_registered) {
|
||||
input_unregister_device(bd->input);
|
||||
} else {
|
||||
input_free_device(bd->input);
|
||||
_cyttsp5_unsubscribe_attention(dev, CY_ATTEN_STARTUP,
|
||||
CYTTSP5_BTN_NAME, cyttsp5_setup_input_attention, 0);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
6325
drivers/input/touchscreen/cyttsp5/cyttsp5_core.c
Normal file
6325
drivers/input/touchscreen/cyttsp5/cyttsp5_core.c
Normal file
File diff suppressed because it is too large
Load Diff
179
drivers/input/touchscreen/cyttsp5/cyttsp5_core.h
Normal file
179
drivers/input/touchscreen/cyttsp5/cyttsp5_core.h
Normal file
@@ -0,0 +1,179 @@
|
||||
/*
|
||||
* cyttsp5_core.h
|
||||
* Parade TrueTouch(TM) Standard Product V5 Core Module.
|
||||
* For use with Parade touchscreen controllers.
|
||||
* Supported parts include:
|
||||
* CYTMA5XX
|
||||
* CYTMA448
|
||||
* CYTMA445A
|
||||
* CYTT21XXX
|
||||
* CYTT31XXX
|
||||
*
|
||||
* Copyright (C) 2015 Parade Semiconductor
|
||||
* Copyright (C) 2012-2015 Cypress Semiconductor
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* Contact Parade Semiconductor at www.parade.com <ttdrivers@paradetech.com>
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef _LINUX_CYTTSP5_CORE_H
|
||||
#define _LINUX_CYTTSP5_CORE_H
|
||||
|
||||
#include <linux/stringify.h>
|
||||
|
||||
#define CYTTSP5_I2C_NAME "cyttsp5_i2c_adapter"
|
||||
#define CYTTSP5_SPI_NAME "cyttsp5_spi_adapter"
|
||||
|
||||
#define CYTTSP5_CORE_NAME "cyttsp5_core"
|
||||
#define CYTTSP5_MT_NAME "cyttsp5_mt"
|
||||
#define CYTTSP5_BTN_NAME "cyttsp5_btn"
|
||||
#define CYTTSP5_PROXIMITY_NAME "cyttsp5_proximity"
|
||||
|
||||
#define CY_DRIVER_NAME TTDA
|
||||
#define CY_DRIVER_MAJOR 03
|
||||
#define CY_DRIVER_MINOR 08
|
||||
|
||||
#define CY_DRIVER_REVCTRL 874312
|
||||
|
||||
#define CY_DRIVER_VERSION \
|
||||
__stringify(CY_DRIVER_NAME) \
|
||||
"." __stringify(CY_DRIVER_MAJOR) \
|
||||
"." __stringify(CY_DRIVER_MINOR) \
|
||||
"." __stringify(CY_DRIVER_REVCTRL)
|
||||
|
||||
#define CY_DRIVER_DATE "20170125"
|
||||
|
||||
/* abs settings */
|
||||
#define CY_IGNORE_VALUE -1
|
||||
|
||||
enum cyttsp5_core_platform_flags {
|
||||
CY_CORE_FLAG_NONE,
|
||||
CY_CORE_FLAG_POWEROFF_ON_SLEEP = 0x02,
|
||||
CY_CORE_FLAG_RESTORE_PARAMETERS = 0x04,
|
||||
};
|
||||
|
||||
enum cyttsp5_core_platform_easy_wakeup_gesture {
|
||||
CY_CORE_EWG_NONE,
|
||||
CY_CORE_EWG_TAP_TAP,
|
||||
CY_CORE_EWG_TWO_FINGER_SLIDE,
|
||||
CY_CORE_EWG_RESERVED,
|
||||
CY_CORE_EWG_WAKE_ON_INT_FROM_HOST = 0xFF,
|
||||
};
|
||||
|
||||
enum cyttsp5_loader_platform_flags {
|
||||
CY_LOADER_FLAG_NONE,
|
||||
CY_LOADER_FLAG_CALIBRATE_AFTER_FW_UPGRADE,
|
||||
/* Use CONFIG_VER field in TT_CFG to decide TT_CFG update */
|
||||
CY_LOADER_FLAG_CHECK_TTCONFIG_VERSION,
|
||||
CY_LOADER_FLAG_CALIBRATE_AFTER_TTCONFIG_UPGRADE,
|
||||
};
|
||||
|
||||
struct touch_settings {
|
||||
const uint8_t *data;
|
||||
uint32_t size;
|
||||
uint8_t tag;
|
||||
};
|
||||
|
||||
struct cyttsp5_touch_firmware {
|
||||
const uint8_t *img;
|
||||
uint32_t size;
|
||||
const uint8_t *ver;
|
||||
uint8_t vsize;
|
||||
uint8_t panel_id;
|
||||
};
|
||||
|
||||
struct cyttsp5_touch_config {
|
||||
struct touch_settings *param_regs;
|
||||
struct touch_settings *param_size;
|
||||
const uint8_t *fw_ver;
|
||||
uint8_t fw_vsize;
|
||||
uint8_t panel_id;
|
||||
};
|
||||
|
||||
struct cyttsp5_loader_platform_data {
|
||||
struct cyttsp5_touch_firmware *fw;
|
||||
struct cyttsp5_touch_config *ttconfig;
|
||||
struct cyttsp5_touch_firmware **fws;
|
||||
struct cyttsp5_touch_config **ttconfigs;
|
||||
u32 flags;
|
||||
};
|
||||
|
||||
typedef int (*cyttsp5_platform_read) (struct device *dev, void *buf, int size);
|
||||
|
||||
#define CY_TOUCH_SETTINGS_MAX 32
|
||||
|
||||
struct cyttsp5_core_platform_data {
|
||||
int irq_gpio;
|
||||
int rst_gpio;
|
||||
int level_irq_udelay;
|
||||
u16 hid_desc_register;
|
||||
u16 vendor_id;
|
||||
u16 product_id;
|
||||
|
||||
int (*xres)(struct cyttsp5_core_platform_data *pdata,
|
||||
struct device *dev);
|
||||
int (*init)(struct cyttsp5_core_platform_data *pdata,
|
||||
int on, struct device *dev);
|
||||
int (*power)(struct cyttsp5_core_platform_data *pdata,
|
||||
int on, struct device *dev, atomic_t *ignore_irq);
|
||||
int (*detect)(struct cyttsp5_core_platform_data *pdata,
|
||||
struct device *dev, cyttsp5_platform_read read);
|
||||
int (*irq_stat)(struct cyttsp5_core_platform_data *pdata,
|
||||
struct device *dev);
|
||||
struct touch_settings *sett[CY_TOUCH_SETTINGS_MAX];
|
||||
u32 flags;
|
||||
u8 easy_wakeup_gesture;
|
||||
};
|
||||
|
||||
struct touch_framework {
|
||||
const int16_t *abs;
|
||||
uint8_t size;
|
||||
uint8_t enable_vkeys;
|
||||
} __packed;
|
||||
|
||||
enum cyttsp5_mt_platform_flags {
|
||||
CY_MT_FLAG_NONE,
|
||||
CY_MT_FLAG_HOVER = 0x04,
|
||||
CY_MT_FLAG_FLIP = 0x08,
|
||||
CY_MT_FLAG_INV_X = 0x10,
|
||||
CY_MT_FLAG_INV_Y = 0x20,
|
||||
CY_MT_FLAG_VKEYS = 0x40,
|
||||
CY_MT_FLAG_NO_TOUCH_ON_LO = 0x80,
|
||||
};
|
||||
|
||||
struct cyttsp5_mt_platform_data {
|
||||
struct touch_framework *frmwrk;
|
||||
unsigned short flags;
|
||||
char const *inp_dev_name;
|
||||
int vkeys_x;
|
||||
int vkeys_y;
|
||||
};
|
||||
|
||||
struct cyttsp5_btn_platform_data {
|
||||
char const *inp_dev_name;
|
||||
};
|
||||
|
||||
struct cyttsp5_proximity_platform_data {
|
||||
struct touch_framework *frmwrk;
|
||||
char const *inp_dev_name;
|
||||
};
|
||||
|
||||
struct cyttsp5_platform_data {
|
||||
struct cyttsp5_core_platform_data *core_pdata;
|
||||
struct cyttsp5_mt_platform_data *mt_pdata;
|
||||
struct cyttsp5_btn_platform_data *btn_pdata;
|
||||
struct cyttsp5_proximity_platform_data *prox_pdata;
|
||||
struct cyttsp5_loader_platform_data *loader_pdata;
|
||||
};
|
||||
|
||||
#endif /* _LINUX_CYTTSP5_CORE_H */
|
||||
393
drivers/input/touchscreen/cyttsp5/cyttsp5_debug.c
Normal file
393
drivers/input/touchscreen/cyttsp5/cyttsp5_debug.c
Normal file
@@ -0,0 +1,393 @@
|
||||
/*
|
||||
* cyttsp5_debug.c
|
||||
* Parade TrueTouch(TM) Standard Product V5 Debug Module.
|
||||
* For use with Parade touchscreen controllers.
|
||||
* Supported parts include:
|
||||
* CYTMA5XX
|
||||
* CYTMA448
|
||||
* CYTMA445A
|
||||
* CYTT21XXX
|
||||
* CYTT31XXX
|
||||
*
|
||||
* Copyright (C) 2015 Parade Technologies
|
||||
* Copyright (C) 2012-2015 Cypress Semiconductor
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* Contact Parade Technologies at www.paradetech.com <ttdrivers@paradetech.com>
|
||||
*
|
||||
*/
|
||||
|
||||
#include "cyttsp5_regs.h"
|
||||
|
||||
#define CYTTSP5_DEBUG_NAME "cyttsp5_debug"
|
||||
|
||||
struct cyttsp5_debug_data {
|
||||
struct device *dev;
|
||||
struct cyttsp5_sysinfo *si;
|
||||
uint32_t interrupt_count;
|
||||
uint32_t formated_output;
|
||||
struct mutex sysfs_lock;
|
||||
u8 pr_buf[CY_MAX_PRBUF_SIZE];
|
||||
};
|
||||
|
||||
static struct cyttsp5_core_commands *cmd;
|
||||
|
||||
static struct cyttsp5_module debug_module;
|
||||
|
||||
static inline struct cyttsp5_debug_data *cyttsp5_get_debug_data(
|
||||
struct device *dev)
|
||||
{
|
||||
return cyttsp5_get_module_data(dev, &debug_module);
|
||||
}
|
||||
|
||||
/*
|
||||
* This function provide output of combined xy_mode and xy_data.
|
||||
* Required by TTHE.
|
||||
*/
|
||||
static void cyttsp5_pr_buf_op_mode(struct cyttsp5_debug_data *dd, u8 *pr_buf,
|
||||
struct cyttsp5_sysinfo *si, u8 cur_touch)
|
||||
{
|
||||
const char fmt[] = "%02X ";
|
||||
int max = (CY_MAX_PRBUF_SIZE - 1) - sizeof(CY_PR_TRUNCATED);
|
||||
u8 report_id = si->xy_mode[2];
|
||||
int header_size = 0;
|
||||
int report_size = 0;
|
||||
int total_size = 0;
|
||||
int i, k;
|
||||
|
||||
if (report_id == si->desc.tch_report_id) {
|
||||
header_size = si->desc.tch_header_size;
|
||||
report_size = cur_touch * si->desc.tch_record_size;
|
||||
} else if (report_id == si->desc.btn_report_id) {
|
||||
header_size = BTN_INPUT_HEADER_SIZE;
|
||||
report_size = BTN_REPORT_SIZE;
|
||||
}
|
||||
total_size = header_size + report_size;
|
||||
|
||||
pr_buf[0] = 0;
|
||||
for (i = k = 0; i < header_size && i < max; i++, k += 3)
|
||||
scnprintf(pr_buf + k, CY_MAX_PRBUF_SIZE, fmt, si->xy_mode[i]);
|
||||
|
||||
for (i = 0; i < report_size && i < max; i++, k += 3)
|
||||
scnprintf(pr_buf + k, CY_MAX_PRBUF_SIZE, fmt, si->xy_data[i]);
|
||||
|
||||
pr_info("%s=%s%s\n", "cyttsp5_OpModeData", pr_buf,
|
||||
total_size <= max ? "" : CY_PR_TRUNCATED);
|
||||
}
|
||||
|
||||
static void cyttsp5_debug_print(struct device *dev, u8 *pr_buf, u8 *sptr,
|
||||
int size, const char *data_name)
|
||||
{
|
||||
int i, j;
|
||||
int elem_size = sizeof("XX ") - 1;
|
||||
int max = (CY_MAX_PRBUF_SIZE - 1) / elem_size;
|
||||
int limit = size < max ? size : max;
|
||||
|
||||
if (limit < 0)
|
||||
limit = 0;
|
||||
|
||||
pr_buf[0] = 0;
|
||||
for (i = j = 0; i < limit; i++, j += elem_size)
|
||||
scnprintf(pr_buf + j, CY_MAX_PRBUF_SIZE - j, "%02X ", sptr[i]);
|
||||
|
||||
if (size)
|
||||
pr_info("%s[0..%d]=%s%s\n", data_name, size - 1, pr_buf,
|
||||
size <= max ? "" : CY_PR_TRUNCATED);
|
||||
else
|
||||
pr_info("%s[]\n", data_name);
|
||||
}
|
||||
|
||||
static void cyttsp5_debug_formated(struct device *dev, u8 *pr_buf,
|
||||
struct cyttsp5_sysinfo *si, u8 num_cur_tch)
|
||||
{
|
||||
u8 report_id = si->xy_mode[2];
|
||||
int header_size = 0;
|
||||
int report_size = 0;
|
||||
u8 data_name[] = "touch[99]";
|
||||
int max_print_length = 20;
|
||||
int i;
|
||||
|
||||
if (report_id == si->desc.tch_report_id) {
|
||||
header_size = si->desc.tch_header_size;
|
||||
report_size = num_cur_tch * si->desc.tch_record_size;
|
||||
} else if (report_id == si->desc.btn_report_id) {
|
||||
header_size = BTN_INPUT_HEADER_SIZE;
|
||||
report_size = BTN_REPORT_SIZE;
|
||||
}
|
||||
|
||||
/* xy_mode */
|
||||
cyttsp5_debug_print(dev, pr_buf, si->xy_mode, header_size, "xy_mode");
|
||||
|
||||
/* xy_data */
|
||||
if (report_size > max_print_length) {
|
||||
pr_info("xy_data[0..%d]:\n", report_size);
|
||||
for (i = 0; i < report_size - max_print_length;
|
||||
i += max_print_length) {
|
||||
cyttsp5_debug_print(dev, pr_buf, si->xy_data + i,
|
||||
max_print_length, " ");
|
||||
}
|
||||
if (report_size - i)
|
||||
cyttsp5_debug_print(dev, pr_buf, si->xy_data + i,
|
||||
report_size - i, " ");
|
||||
} else {
|
||||
cyttsp5_debug_print(dev, pr_buf, si->xy_data, report_size,
|
||||
"xy_data");
|
||||
}
|
||||
|
||||
/* touches */
|
||||
if (report_id == si->desc.tch_report_id) {
|
||||
for (i = 0; i < num_cur_tch; i++) {
|
||||
scnprintf(data_name, sizeof(data_name) - 1,
|
||||
"touch[%u]", i);
|
||||
cyttsp5_debug_print(dev, pr_buf,
|
||||
si->xy_data + (i * si->desc.tch_record_size),
|
||||
si->desc.tch_record_size, data_name);
|
||||
}
|
||||
}
|
||||
|
||||
/* buttons */
|
||||
if (report_id == si->desc.btn_report_id)
|
||||
cyttsp5_debug_print(dev, pr_buf, si->xy_data, report_size,
|
||||
"button");
|
||||
}
|
||||
|
||||
/* read xy_data for all touches for debug */
|
||||
static int cyttsp5_xy_worker(struct cyttsp5_debug_data *dd)
|
||||
{
|
||||
struct device *dev = dd->dev;
|
||||
struct cyttsp5_sysinfo *si = dd->si;
|
||||
u8 report_reg = si->xy_mode[TOUCH_COUNT_BYTE_OFFSET];
|
||||
u8 num_cur_tch = GET_NUM_TOUCHES(report_reg);
|
||||
uint32_t formated_output;
|
||||
|
||||
mutex_lock(&dd->sysfs_lock);
|
||||
dd->interrupt_count++;
|
||||
formated_output = dd->formated_output;
|
||||
mutex_unlock(&dd->sysfs_lock);
|
||||
|
||||
/* Interrupt */
|
||||
pr_info("Interrupt(%u)\n", dd->interrupt_count);
|
||||
|
||||
if (formated_output)
|
||||
cyttsp5_debug_formated(dev, dd->pr_buf, si, num_cur_tch);
|
||||
else
|
||||
/* print data for TTHE */
|
||||
cyttsp5_pr_buf_op_mode(dd, dd->pr_buf, si, num_cur_tch);
|
||||
|
||||
pr_info("\n");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int cyttsp5_debug_attention(struct device *dev)
|
||||
{
|
||||
struct cyttsp5_debug_data *dd = cyttsp5_get_debug_data(dev);
|
||||
struct cyttsp5_sysinfo *si = dd->si;
|
||||
u8 report_id = si->xy_mode[2];
|
||||
int rc = 0;
|
||||
|
||||
if (report_id != si->desc.tch_report_id
|
||||
&& report_id != si->desc.btn_report_id)
|
||||
return 0;
|
||||
|
||||
/* core handles handshake */
|
||||
rc = cyttsp5_xy_worker(dd);
|
||||
if (rc < 0)
|
||||
dev_err(dev, "%s: xy_worker error r=%d\n", __func__, rc);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
static ssize_t cyttsp5_interrupt_count_show(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
struct cyttsp5_debug_data *dd = cyttsp5_get_debug_data(dev);
|
||||
int val;
|
||||
|
||||
mutex_lock(&dd->sysfs_lock);
|
||||
val = dd->interrupt_count;
|
||||
mutex_unlock(&dd->sysfs_lock);
|
||||
|
||||
return scnprintf(buf, CY_MAX_PRBUF_SIZE, "Interrupt Count: %d\n", val);
|
||||
}
|
||||
|
||||
static ssize_t cyttsp5_interrupt_count_store(struct device *dev,
|
||||
struct device_attribute *attr, const char *buf, size_t size)
|
||||
{
|
||||
struct cyttsp5_debug_data *dd = cyttsp5_get_debug_data(dev);
|
||||
|
||||
mutex_lock(&dd->sysfs_lock);
|
||||
dd->interrupt_count = 0;
|
||||
mutex_unlock(&dd->sysfs_lock);
|
||||
return size;
|
||||
}
|
||||
|
||||
static DEVICE_ATTR(int_count, S_IRUSR | S_IWUSR,
|
||||
cyttsp5_interrupt_count_show, cyttsp5_interrupt_count_store);
|
||||
|
||||
static ssize_t cyttsp5_formated_output_show(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
struct cyttsp5_debug_data *dd = cyttsp5_get_debug_data(dev);
|
||||
int val;
|
||||
|
||||
mutex_lock(&dd->sysfs_lock);
|
||||
val = dd->formated_output;
|
||||
mutex_unlock(&dd->sysfs_lock);
|
||||
|
||||
return scnprintf(buf, CY_MAX_PRBUF_SIZE,
|
||||
"Formated debug output: %x\n", val);
|
||||
}
|
||||
|
||||
static ssize_t cyttsp5_formated_output_store(struct device *dev,
|
||||
struct device_attribute *attr, const char *buf, size_t size)
|
||||
{
|
||||
struct cyttsp5_debug_data *dd = cyttsp5_get_debug_data(dev);
|
||||
unsigned long value;
|
||||
int rc;
|
||||
|
||||
rc = kstrtoul(buf, 10, &value);
|
||||
if (rc < 0) {
|
||||
dev_err(dev, "%s: Invalid value\n", __func__);
|
||||
return size;
|
||||
}
|
||||
|
||||
/* Expecting only 0 or 1 */
|
||||
if (value != 0 && value != 1) {
|
||||
dev_err(dev, "%s: Invalid value %lu\n", __func__, value);
|
||||
return size;
|
||||
}
|
||||
|
||||
mutex_lock(&dd->sysfs_lock);
|
||||
dd->formated_output = value;
|
||||
mutex_unlock(&dd->sysfs_lock);
|
||||
return size;
|
||||
}
|
||||
|
||||
static DEVICE_ATTR(formated_output, S_IRUSR | S_IWUSR,
|
||||
cyttsp5_formated_output_show, cyttsp5_formated_output_store);
|
||||
|
||||
static int cyttsp5_debug_probe(struct device *dev, void **data)
|
||||
{
|
||||
struct cyttsp5_debug_data *dd;
|
||||
int rc;
|
||||
|
||||
/* get context and debug print buffers */
|
||||
dd = kzalloc(sizeof(*dd), GFP_KERNEL);
|
||||
if (!dd) {
|
||||
rc = -ENOMEM;
|
||||
goto cyttsp5_debug_probe_alloc_failed;
|
||||
}
|
||||
|
||||
rc = device_create_file(dev, &dev_attr_int_count);
|
||||
if (rc) {
|
||||
dev_err(dev, "%s: Error, could not create int_count\n",
|
||||
__func__);
|
||||
goto cyttsp5_debug_probe_create_int_count_failed;
|
||||
}
|
||||
|
||||
rc = device_create_file(dev, &dev_attr_formated_output);
|
||||
if (rc) {
|
||||
dev_err(dev, "%s: Error, could not create formated_output\n",
|
||||
__func__);
|
||||
goto cyttsp5_debug_probe_create_formated_failed;
|
||||
}
|
||||
|
||||
mutex_init(&dd->sysfs_lock);
|
||||
dd->dev = dev;
|
||||
*data = dd;
|
||||
|
||||
dd->si = cmd->request_sysinfo(dev);
|
||||
if (!dd->si) {
|
||||
dev_err(dev, "%s: Fail get sysinfo pointer from core\n",
|
||||
__func__);
|
||||
rc = -ENODEV;
|
||||
goto cyttsp5_debug_probe_sysinfo_failed;
|
||||
}
|
||||
|
||||
rc = cmd->subscribe_attention(dev, CY_ATTEN_IRQ, CYTTSP5_DEBUG_NAME,
|
||||
cyttsp5_debug_attention, CY_MODE_OPERATIONAL);
|
||||
if (rc < 0) {
|
||||
dev_err(dev, "%s: Error, could not subscribe attention cb\n",
|
||||
__func__);
|
||||
goto cyttsp5_debug_probe_subscribe_failed;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
cyttsp5_debug_probe_subscribe_failed:
|
||||
cyttsp5_debug_probe_sysinfo_failed:
|
||||
device_remove_file(dev, &dev_attr_formated_output);
|
||||
cyttsp5_debug_probe_create_formated_failed:
|
||||
device_remove_file(dev, &dev_attr_int_count);
|
||||
cyttsp5_debug_probe_create_int_count_failed:
|
||||
kfree(dd);
|
||||
cyttsp5_debug_probe_alloc_failed:
|
||||
dev_err(dev, "%s failed.\n", __func__);
|
||||
return rc;
|
||||
}
|
||||
|
||||
static void cyttsp5_debug_release(struct device *dev, void *data)
|
||||
{
|
||||
struct cyttsp5_debug_data *dd = data;
|
||||
int rc;
|
||||
|
||||
rc = cmd->unsubscribe_attention(dev, CY_ATTEN_IRQ, CYTTSP5_DEBUG_NAME,
|
||||
cyttsp5_debug_attention, CY_MODE_OPERATIONAL);
|
||||
if (rc < 0) {
|
||||
dev_err(dev, "%s: Error, could not un-subscribe attention\n",
|
||||
__func__);
|
||||
goto cyttsp5_debug_release_exit;
|
||||
}
|
||||
|
||||
cyttsp5_debug_release_exit:
|
||||
device_remove_file(dev, &dev_attr_formated_output);
|
||||
device_remove_file(dev, &dev_attr_int_count);
|
||||
kfree(dd);
|
||||
}
|
||||
|
||||
static struct cyttsp5_module debug_module = {
|
||||
.name = CYTTSP5_DEBUG_NAME,
|
||||
.probe = cyttsp5_debug_probe,
|
||||
.release = cyttsp5_debug_release,
|
||||
};
|
||||
|
||||
static int __init cyttsp5_debug_init(void)
|
||||
{
|
||||
int rc;
|
||||
|
||||
cmd = cyttsp5_get_commands();
|
||||
if (!cmd)
|
||||
return -EINVAL;
|
||||
|
||||
rc = cyttsp5_register_module(&debug_module);
|
||||
if (rc < 0) {
|
||||
pr_err("%s: Error, failed registering module\n",
|
||||
__func__);
|
||||
return rc;
|
||||
}
|
||||
|
||||
pr_info("%s: Parade TTSP Debug Driver (Built %s) rc=%d\n",
|
||||
__func__, CY_DRIVER_VERSION, rc);
|
||||
return 0;
|
||||
}
|
||||
module_init(cyttsp5_debug_init);
|
||||
|
||||
static void __exit cyttsp5_debug_exit(void)
|
||||
{
|
||||
cyttsp5_unregister_module(&debug_module);
|
||||
}
|
||||
module_exit(cyttsp5_debug_exit);
|
||||
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_DESCRIPTION("Parade TrueTouch(R) Standard Product Debug Driver");
|
||||
MODULE_AUTHOR("Parade Technologies <ttdrivers@paradetech.com>");
|
||||
@@ -0,0 +1,44 @@
|
||||
/*
|
||||
* cyttsp5_device_access-api.h
|
||||
* Parade TrueTouch(TM) Standard Product V5 Device Access API module.
|
||||
* For use with Parade touchscreen controllers.
|
||||
* Supported parts include:
|
||||
* CYTMA5XX
|
||||
* CYTMA448
|
||||
* CYTMA445A
|
||||
* CYTT21XXX
|
||||
* CYTT31XXX
|
||||
*
|
||||
* Copyright (C) 2015 Parade Semiconductor
|
||||
* Copyright (C) 2012-2015 Cypress Semiconductor
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* Contact Parade Semiconductor at www.parade.com <ttdrivers@paradetech.com>
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef _LINUX_CYTTSP5_DEVICE_ACCESS_API_H
|
||||
#define _LINUX_CYTTSP5_DEVICE_ACCESS_API_H
|
||||
|
||||
#include <linux/types.h>
|
||||
#include <linux/device.h>
|
||||
|
||||
int cyttsp5_device_access_user_command(const char *core_name, u16 read_len,
|
||||
u8 *read_buf, u16 write_len, u8 *write_buf,
|
||||
u16 *actual_read_len);
|
||||
|
||||
int cyttsp5_device_access_user_command_async(const char *core_name,
|
||||
u16 read_len, u8 *read_buf, u16 write_len, u8 *write_buf,
|
||||
void (*cont)(const char *core_name, u16 read_len, u8 *read_buf,
|
||||
u16 write_len, u8 *write_buf, u16 actual_read_length,
|
||||
int rc));
|
||||
#endif /* _LINUX_CYTTSP5_DEVICE_ACCESS_API_H */
|
||||
5321
drivers/input/touchscreen/cyttsp5/cyttsp5_device_access.c
Normal file
5321
drivers/input/touchscreen/cyttsp5/cyttsp5_device_access.c
Normal file
File diff suppressed because it is too large
Load Diff
750
drivers/input/touchscreen/cyttsp5/cyttsp5_devtree.c
Normal file
750
drivers/input/touchscreen/cyttsp5/cyttsp5_devtree.c
Normal file
@@ -0,0 +1,750 @@
|
||||
/*
|
||||
* cyttsp5_devtree.c
|
||||
* Parade TrueTouch(TM) Standard Product V5 Device Tree Support Module.
|
||||
* For use with Parade touchscreen controllers.
|
||||
* Supported parts include:
|
||||
* CYTMA5XX
|
||||
* CYTMA448
|
||||
* CYTMA445A
|
||||
* CYTT21XXX
|
||||
* CYTT31XXX
|
||||
*
|
||||
* Copyright (C) 2015 Parade Technologies
|
||||
* Copyright (C) 2013-2015 Cypress Semiconductor
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* Contact Parade Technologies at www.paradetech.com <ttdrivers@paradetech.com>
|
||||
*
|
||||
*/
|
||||
|
||||
#include <linux/device.h>
|
||||
#include <linux/err.h>
|
||||
#include <linux/of_device.h>
|
||||
#include <linux/of_gpio.h>
|
||||
#include <linux/slab.h>
|
||||
|
||||
/* cyttsp */
|
||||
#include "cyttsp5_regs.h"
|
||||
#include "cyttsp5_platform.h"
|
||||
|
||||
/* #define ENABLE_VIRTUAL_KEYS */
|
||||
|
||||
#define MAX_NAME_LENGTH 64
|
||||
|
||||
enum cyttsp5_device_type {
|
||||
DEVICE_MT,
|
||||
DEVICE_BTN,
|
||||
DEVICE_PROXIMITY,
|
||||
DEVICE_TYPE_MAX,
|
||||
};
|
||||
|
||||
struct cyttsp5_device_pdata_func {
|
||||
void * (*create_and_get_pdata)(struct device_node *);
|
||||
void (*free_pdata)(void *);
|
||||
};
|
||||
|
||||
struct cyttsp5_pdata_ptr {
|
||||
void **pdata;
|
||||
};
|
||||
|
||||
#ifdef ENABLE_VIRTUAL_KEYS
|
||||
static struct kobject *board_properties_kobj;
|
||||
|
||||
struct cyttsp5_virtual_keys {
|
||||
struct kobj_attribute kobj_attr;
|
||||
u16 *data;
|
||||
int size;
|
||||
};
|
||||
#endif
|
||||
|
||||
struct cyttsp5_extended_mt_platform_data {
|
||||
struct cyttsp5_mt_platform_data pdata;
|
||||
#ifdef ENABLE_VIRTUAL_KEYS
|
||||
struct cyttsp5_virtual_keys vkeys;
|
||||
#endif
|
||||
};
|
||||
|
||||
static inline int get_inp_dev_name(struct device_node *dev_node,
|
||||
const char **inp_dev_name)
|
||||
{
|
||||
return of_property_read_string(dev_node, "cy,inp_dev_name",
|
||||
inp_dev_name);
|
||||
}
|
||||
|
||||
static s16 *create_and_get_u16_array(struct device_node *dev_node,
|
||||
const char *name, int *size)
|
||||
{
|
||||
const __be32 *values;
|
||||
s16 *val_array;
|
||||
int len;
|
||||
int sz;
|
||||
int rc;
|
||||
int i;
|
||||
|
||||
values = of_get_property(dev_node, name, &len);
|
||||
if (values == NULL)
|
||||
return NULL;
|
||||
|
||||
sz = len / sizeof(u32);
|
||||
pr_debug("%s: %s size:%d\n", __func__, name, sz);
|
||||
|
||||
val_array = kcalloc(sz, sizeof(s16), GFP_KERNEL);
|
||||
if (!val_array) {
|
||||
rc = -ENOMEM;
|
||||
goto fail;
|
||||
}
|
||||
|
||||
for (i = 0; i < sz; i++)
|
||||
val_array[i] = (s16)be32_to_cpup(values++);
|
||||
|
||||
*size = sz;
|
||||
|
||||
return val_array;
|
||||
|
||||
fail:
|
||||
return ERR_PTR(rc);
|
||||
}
|
||||
|
||||
static struct touch_framework *create_and_get_touch_framework(
|
||||
struct device_node *dev_node)
|
||||
{
|
||||
struct touch_framework *frmwrk;
|
||||
s16 *abs;
|
||||
int size;
|
||||
int rc;
|
||||
|
||||
abs = create_and_get_u16_array(dev_node, "cy,abs", &size);
|
||||
if (IS_ERR_OR_NULL(abs))
|
||||
return (void *)abs;
|
||||
|
||||
/* Check for valid abs size */
|
||||
if (size % CY_NUM_ABS_SET) {
|
||||
rc = -EINVAL;
|
||||
goto fail_free_abs;
|
||||
}
|
||||
|
||||
frmwrk = kzalloc(sizeof(*frmwrk), GFP_KERNEL);
|
||||
if (!frmwrk) {
|
||||
rc = -ENOMEM;
|
||||
goto fail_free_abs;
|
||||
}
|
||||
|
||||
frmwrk->abs = abs;
|
||||
frmwrk->size = size;
|
||||
|
||||
return frmwrk;
|
||||
|
||||
fail_free_abs:
|
||||
kfree(abs);
|
||||
|
||||
return ERR_PTR(rc);
|
||||
}
|
||||
|
||||
static void free_touch_framework(struct touch_framework *frmwrk)
|
||||
{
|
||||
kfree(frmwrk->abs);
|
||||
kfree(frmwrk);
|
||||
}
|
||||
|
||||
#ifdef ENABLE_VIRTUAL_KEYS
|
||||
#define VIRTUAL_KEY_ELEMENT_SIZE 5
|
||||
static ssize_t virtual_keys_show(struct kobject *kobj,
|
||||
struct kobj_attribute *attr, char *buf)
|
||||
{
|
||||
struct cyttsp5_virtual_keys *vkeys = container_of(attr,
|
||||
struct cyttsp5_virtual_keys, kobj_attr);
|
||||
u16 *data = vkeys->data;
|
||||
int size = vkeys->size;
|
||||
int index;
|
||||
int i;
|
||||
|
||||
index = 0;
|
||||
for (i = 0; i < size; i += VIRTUAL_KEY_ELEMENT_SIZE)
|
||||
index += scnprintf(buf + index, CY_MAX_PRBUF_SIZE - index,
|
||||
"0x01:%d:%d:%d:%d:%d\n",
|
||||
data[i], data[i+1], data[i+2], data[i+3], data[i+4]);
|
||||
|
||||
return index;
|
||||
}
|
||||
|
||||
static int setup_virtual_keys(struct device_node *dev_node,
|
||||
const char *inp_dev_name, struct cyttsp5_virtual_keys *vkeys)
|
||||
{
|
||||
char *name;
|
||||
u16 *data;
|
||||
int size;
|
||||
int rc;
|
||||
|
||||
data = create_and_get_u16_array(dev_node, "cy,virtual_keys", &size);
|
||||
if (data == NULL)
|
||||
return 0;
|
||||
else if (IS_ERR(data)) {
|
||||
rc = PTR_ERR(data);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
/* Check for valid virtual keys size */
|
||||
if (size % VIRTUAL_KEY_ELEMENT_SIZE) {
|
||||
rc = -EINVAL;
|
||||
goto fail_free_data;
|
||||
}
|
||||
|
||||
name = kzalloc(MAX_NAME_LENGTH, GFP_KERNEL);
|
||||
if (!name) {
|
||||
rc = -ENOMEM;
|
||||
goto fail_free_data;
|
||||
}
|
||||
|
||||
snprintf(name, MAX_NAME_LENGTH, "virtualkeys.%s", inp_dev_name);
|
||||
|
||||
vkeys->data = data;
|
||||
vkeys->size = size;
|
||||
|
||||
/* TODO: Instantiate in board file and export it */
|
||||
if (board_properties_kobj == NULL)
|
||||
board_properties_kobj =
|
||||
kobject_create_and_add("board_properties", NULL);
|
||||
if (board_properties_kobj == NULL) {
|
||||
pr_err("%s: Cannot get board_properties kobject!\n", __func__);
|
||||
rc = -EINVAL;
|
||||
goto fail_free_name;
|
||||
}
|
||||
|
||||
/* Initialize dynamic SysFs attribute */
|
||||
sysfs_attr_init(&vkeys->kobj_attr.attr);
|
||||
vkeys->kobj_attr.attr.name = name;
|
||||
vkeys->kobj_attr.attr.mode = S_IRUGO;
|
||||
vkeys->kobj_attr.show = virtual_keys_show;
|
||||
|
||||
rc = sysfs_create_file(board_properties_kobj, &vkeys->kobj_attr.attr);
|
||||
if (rc)
|
||||
goto fail_del_kobj;
|
||||
|
||||
return 0;
|
||||
|
||||
fail_del_kobj:
|
||||
kobject_del(board_properties_kobj);
|
||||
fail_free_name:
|
||||
kfree(name);
|
||||
vkeys->kobj_attr.attr.name = NULL;
|
||||
fail_free_data:
|
||||
kfree(data);
|
||||
vkeys->data = NULL;
|
||||
fail:
|
||||
return rc;
|
||||
}
|
||||
|
||||
static void free_virtual_keys(struct cyttsp5_virtual_keys *vkeys)
|
||||
{
|
||||
if (board_properties_kobj)
|
||||
sysfs_remove_file(board_properties_kobj,
|
||||
&vkeys->kobj_attr.attr);
|
||||
|
||||
|
||||
kobject_del(board_properties_kobj);
|
||||
board_properties_kobj = NULL;
|
||||
|
||||
kfree(vkeys->data);
|
||||
kfree(vkeys->kobj_attr.attr.name);
|
||||
}
|
||||
#endif
|
||||
|
||||
static void *create_and_get_mt_pdata(struct device_node *dev_node)
|
||||
{
|
||||
struct cyttsp5_extended_mt_platform_data *ext_pdata;
|
||||
struct cyttsp5_mt_platform_data *pdata;
|
||||
u32 value;
|
||||
int rc;
|
||||
|
||||
ext_pdata = kzalloc(sizeof(*ext_pdata), GFP_KERNEL);
|
||||
if (!ext_pdata) {
|
||||
rc = -ENOMEM;
|
||||
goto fail;
|
||||
}
|
||||
|
||||
pdata = &ext_pdata->pdata;
|
||||
|
||||
rc = get_inp_dev_name(dev_node, &pdata->inp_dev_name);
|
||||
if (rc)
|
||||
goto fail_free_pdata;
|
||||
|
||||
/* Optional fields */
|
||||
rc = of_property_read_u32(dev_node, "cy,flags", &value);
|
||||
if (!rc)
|
||||
pdata->flags = value;
|
||||
|
||||
rc = of_property_read_u32(dev_node, "cy,vkeys_x", &value);
|
||||
if (!rc)
|
||||
pdata->vkeys_x = value;
|
||||
|
||||
rc = of_property_read_u32(dev_node, "cy,vkeys_y", &value);
|
||||
if (!rc)
|
||||
pdata->vkeys_y = value;
|
||||
|
||||
/* Required fields */
|
||||
pdata->frmwrk = create_and_get_touch_framework(dev_node);
|
||||
if (pdata->frmwrk == NULL) {
|
||||
rc = -EINVAL;
|
||||
goto fail_free_pdata;
|
||||
} else if (IS_ERR(pdata->frmwrk)) {
|
||||
rc = PTR_ERR(pdata->frmwrk);
|
||||
goto fail_free_pdata;
|
||||
}
|
||||
#ifdef ENABLE_VIRTUAL_KEYS
|
||||
rc = setup_virtual_keys(dev_node, pdata->inp_dev_name,
|
||||
&ext_pdata->vkeys);
|
||||
if (rc) {
|
||||
pr_err("%s: Cannot setup virtual keys!\n", __func__);
|
||||
goto fail_free_pdata;
|
||||
}
|
||||
#endif
|
||||
return pdata;
|
||||
|
||||
fail_free_pdata:
|
||||
kfree(ext_pdata);
|
||||
fail:
|
||||
return ERR_PTR(rc);
|
||||
}
|
||||
|
||||
static void free_mt_pdata(void *pdata)
|
||||
{
|
||||
struct cyttsp5_mt_platform_data *mt_pdata =
|
||||
(struct cyttsp5_mt_platform_data *)pdata;
|
||||
struct cyttsp5_extended_mt_platform_data *ext_mt_pdata =
|
||||
container_of(mt_pdata,
|
||||
struct cyttsp5_extended_mt_platform_data, pdata);
|
||||
|
||||
free_touch_framework(mt_pdata->frmwrk);
|
||||
#ifdef ENABLE_VIRTUAL_KEYS
|
||||
free_virtual_keys(&ext_mt_pdata->vkeys);
|
||||
#endif
|
||||
kfree(ext_mt_pdata);
|
||||
}
|
||||
|
||||
static void *create_and_get_btn_pdata(struct device_node *dev_node)
|
||||
{
|
||||
struct cyttsp5_btn_platform_data *pdata;
|
||||
int rc;
|
||||
|
||||
pdata = kzalloc(sizeof(*pdata), GFP_KERNEL);
|
||||
if (!pdata) {
|
||||
rc = -ENOMEM;
|
||||
goto fail;
|
||||
}
|
||||
|
||||
rc = get_inp_dev_name(dev_node, &pdata->inp_dev_name);
|
||||
if (rc)
|
||||
goto fail_free_pdata;
|
||||
|
||||
return pdata;
|
||||
|
||||
fail_free_pdata:
|
||||
kfree(pdata);
|
||||
fail:
|
||||
return ERR_PTR(rc);
|
||||
}
|
||||
|
||||
static void free_btn_pdata(void *pdata)
|
||||
{
|
||||
struct cyttsp5_btn_platform_data *btn_pdata =
|
||||
(struct cyttsp5_btn_platform_data *)pdata;
|
||||
|
||||
kfree(btn_pdata);
|
||||
}
|
||||
|
||||
static void *create_and_get_proximity_pdata(struct device_node *dev_node)
|
||||
{
|
||||
struct cyttsp5_proximity_platform_data *pdata;
|
||||
int rc;
|
||||
|
||||
pdata = kzalloc(sizeof(*pdata), GFP_KERNEL);
|
||||
if (!pdata) {
|
||||
rc = -ENOMEM;
|
||||
goto fail;
|
||||
}
|
||||
|
||||
rc = get_inp_dev_name(dev_node, &pdata->inp_dev_name);
|
||||
if (rc)
|
||||
goto fail_free_pdata;
|
||||
|
||||
pdata->frmwrk = create_and_get_touch_framework(dev_node);
|
||||
if (pdata->frmwrk == NULL) {
|
||||
rc = -EINVAL;
|
||||
goto fail_free_pdata;
|
||||
} else if (IS_ERR(pdata->frmwrk)) {
|
||||
rc = PTR_ERR(pdata->frmwrk);
|
||||
goto fail_free_pdata;
|
||||
}
|
||||
|
||||
return pdata;
|
||||
|
||||
fail_free_pdata:
|
||||
kfree(pdata);
|
||||
fail:
|
||||
return ERR_PTR(rc);
|
||||
}
|
||||
|
||||
static void free_proximity_pdata(void *pdata)
|
||||
{
|
||||
struct cyttsp5_proximity_platform_data *proximity_pdata =
|
||||
(struct cyttsp5_proximity_platform_data *)pdata;
|
||||
|
||||
free_touch_framework(proximity_pdata->frmwrk);
|
||||
|
||||
kfree(proximity_pdata);
|
||||
}
|
||||
|
||||
static struct cyttsp5_device_pdata_func device_pdata_funcs[DEVICE_TYPE_MAX] = {
|
||||
[DEVICE_MT] = {
|
||||
.create_and_get_pdata = create_and_get_mt_pdata,
|
||||
.free_pdata = free_mt_pdata,
|
||||
},
|
||||
[DEVICE_BTN] = {
|
||||
.create_and_get_pdata = create_and_get_btn_pdata,
|
||||
.free_pdata = free_btn_pdata,
|
||||
},
|
||||
[DEVICE_PROXIMITY] = {
|
||||
.create_and_get_pdata = create_and_get_proximity_pdata,
|
||||
.free_pdata = free_proximity_pdata,
|
||||
},
|
||||
};
|
||||
|
||||
static struct cyttsp5_pdata_ptr pdata_ptr[DEVICE_TYPE_MAX];
|
||||
|
||||
static const char *device_names[DEVICE_TYPE_MAX] = {
|
||||
[DEVICE_MT] = "cy,mt",
|
||||
[DEVICE_BTN] = "cy,btn",
|
||||
[DEVICE_PROXIMITY] = "cy,proximity",
|
||||
};
|
||||
|
||||
static void set_pdata_ptr(struct cyttsp5_platform_data *pdata)
|
||||
{
|
||||
pdata_ptr[DEVICE_MT].pdata = (void **)&pdata->mt_pdata;
|
||||
pdata_ptr[DEVICE_BTN].pdata = (void **)&pdata->btn_pdata;
|
||||
pdata_ptr[DEVICE_PROXIMITY].pdata = (void **)&pdata->prox_pdata;
|
||||
}
|
||||
|
||||
static int get_device_type(struct device_node *dev_node,
|
||||
enum cyttsp5_device_type *type)
|
||||
{
|
||||
const char *name;
|
||||
enum cyttsp5_device_type t;
|
||||
int rc;
|
||||
|
||||
rc = of_property_read_string(dev_node, "name", &name);
|
||||
if (rc)
|
||||
return rc;
|
||||
|
||||
for (t = 0; t < DEVICE_TYPE_MAX; t++)
|
||||
if (!strncmp(name, device_names[t], MAX_NAME_LENGTH)) {
|
||||
*type = t;
|
||||
return 0;
|
||||
}
|
||||
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
static inline void *create_and_get_device_pdata(struct device_node *dev_node,
|
||||
enum cyttsp5_device_type type)
|
||||
{
|
||||
return device_pdata_funcs[type].create_and_get_pdata(dev_node);
|
||||
}
|
||||
|
||||
static inline void free_device_pdata(enum cyttsp5_device_type type)
|
||||
{
|
||||
device_pdata_funcs[type].free_pdata(*pdata_ptr[type].pdata);
|
||||
}
|
||||
|
||||
static struct touch_settings *create_and_get_touch_setting(
|
||||
struct device_node *core_node, const char *name)
|
||||
{
|
||||
struct touch_settings *setting;
|
||||
char *tag_name;
|
||||
u32 tag_value;
|
||||
u16 *data;
|
||||
int size;
|
||||
int rc;
|
||||
|
||||
data = create_and_get_u16_array(core_node, name, &size);
|
||||
if (IS_ERR_OR_NULL(data))
|
||||
return (void *)data;
|
||||
|
||||
pr_debug("%s: Touch setting:'%s' size:%d\n", __func__, name, size);
|
||||
|
||||
setting = kzalloc(sizeof(*setting), GFP_KERNEL);
|
||||
if (!setting) {
|
||||
rc = -ENOMEM;
|
||||
goto fail_free_data;
|
||||
}
|
||||
|
||||
setting->data = (u8 *)data;
|
||||
setting->size = size;
|
||||
|
||||
tag_name = kzalloc(MAX_NAME_LENGTH, GFP_KERNEL);
|
||||
if (!tag_name) {
|
||||
rc = -ENOMEM;
|
||||
goto fail_free_setting;
|
||||
}
|
||||
|
||||
snprintf(tag_name, MAX_NAME_LENGTH, "%s-tag", name);
|
||||
|
||||
rc = of_property_read_u32(core_node, tag_name, &tag_value);
|
||||
if (!rc)
|
||||
setting->tag = tag_value;
|
||||
|
||||
kfree(tag_name);
|
||||
|
||||
return setting;
|
||||
|
||||
fail_free_setting:
|
||||
kfree(setting);
|
||||
fail_free_data:
|
||||
kfree(data);
|
||||
|
||||
return ERR_PTR(rc);
|
||||
}
|
||||
|
||||
static void free_touch_setting(struct touch_settings *setting)
|
||||
{
|
||||
if (setting) {
|
||||
kfree(setting->data);
|
||||
kfree(setting);
|
||||
}
|
||||
}
|
||||
|
||||
static char *touch_setting_names[CY_IC_GRPNUM_NUM] = {
|
||||
NULL, /* CY_IC_GRPNUM_RESERVED */
|
||||
"cy,cmd_regs", /* CY_IC_GRPNUM_CMD_REGS */
|
||||
"cy,tch_rep", /* CY_IC_GRPNUM_TCH_REP */
|
||||
"cy,data_rec", /* CY_IC_GRPNUM_DATA_REC */
|
||||
"cy,test_rec", /* CY_IC_GRPNUM_TEST_REC */
|
||||
"cy,pcfg_rec", /* CY_IC_GRPNUM_PCFG_REC */
|
||||
"cy,tch_parm_val", /* CY_IC_GRPNUM_TCH_PARM_VAL */
|
||||
"cy,tch_parm_size", /* CY_IC_GRPNUM_TCH_PARM_SIZE */
|
||||
NULL, /* CY_IC_GRPNUM_RESERVED1 */
|
||||
NULL, /* CY_IC_GRPNUM_RESERVED2 */
|
||||
"cy,opcfg_rec", /* CY_IC_GRPNUM_OPCFG_REC */
|
||||
"cy,ddata_rec", /* CY_IC_GRPNUM_DDATA_REC */
|
||||
"cy,mdata_rec", /* CY_IC_GRPNUM_MDATA_REC */
|
||||
"cy,test_regs", /* CY_IC_GRPNUM_TEST_REGS */
|
||||
"cy,btn_keys", /* CY_IC_GRPNUM_BTN_KEYS */
|
||||
NULL, /* CY_IC_GRPNUM_TTHE_REGS */
|
||||
};
|
||||
|
||||
static struct cyttsp5_core_platform_data *create_and_get_core_pdata(
|
||||
struct device_node *core_node)
|
||||
{
|
||||
struct cyttsp5_core_platform_data *pdata;
|
||||
u32 value;
|
||||
int rc;
|
||||
int i;
|
||||
|
||||
pdata = kzalloc(sizeof(*pdata), GFP_KERNEL);
|
||||
if (!pdata) {
|
||||
rc = -ENOMEM;
|
||||
goto fail;
|
||||
}
|
||||
|
||||
/* Required fields */
|
||||
pdata->irq_gpio = of_get_named_gpio_flags(core_node, "cy,irq_gpio", 0, NULL);
|
||||
pdata->rst_gpio = of_get_named_gpio_flags(core_node, "cy,rst_gpio", 0, NULL);
|
||||
|
||||
|
||||
rc = of_property_read_u32(core_node, "cy,hid_desc_register", &value);
|
||||
if (rc)
|
||||
goto fail_free;
|
||||
pdata->hid_desc_register = value;
|
||||
|
||||
/* Optional fields */
|
||||
/* rst_gpio is optional since a platform may use
|
||||
* power cycling instead of using the XRES pin
|
||||
*/
|
||||
|
||||
rc = of_property_read_u32(core_node, "cy,level_irq_udelay", &value);
|
||||
if (!rc)
|
||||
pdata->level_irq_udelay = value;
|
||||
|
||||
rc = of_property_read_u32(core_node, "cy,vendor_id", &value);
|
||||
if (!rc)
|
||||
pdata->vendor_id = value;
|
||||
|
||||
rc = of_property_read_u32(core_node, "cy,product_id", &value);
|
||||
if (!rc)
|
||||
pdata->product_id = value;
|
||||
|
||||
rc = of_property_read_u32(core_node, "cy,flags", &value);
|
||||
if (!rc) {
|
||||
#ifndef CONFIG_FACTORY_BUILD
|
||||
pdata->flags = value;
|
||||
#else
|
||||
pdata->flags = value | CY_CORE_FLAG_POWEROFF_ON_SLEEP;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
rc = of_property_read_u32(core_node, "cy,easy_wakeup_gesture", &value);
|
||||
if (!rc)
|
||||
pdata->easy_wakeup_gesture = (u8)value;
|
||||
|
||||
for (i = 0; (unsigned int)i < ARRAY_SIZE(touch_setting_names); i++) {
|
||||
if (touch_setting_names[i] == NULL)
|
||||
continue;
|
||||
|
||||
pdata->sett[i] = create_and_get_touch_setting(core_node,
|
||||
touch_setting_names[i]);
|
||||
if (IS_ERR(pdata->sett[i])) {
|
||||
rc = PTR_ERR(pdata->sett[i]);
|
||||
goto fail_free_sett;
|
||||
} else if (pdata->sett[i] == NULL)
|
||||
pr_debug("%s: No data for setting '%s'\n", __func__,
|
||||
touch_setting_names[i]);
|
||||
}
|
||||
|
||||
pr_debug("%s: irq_gpio:%d rst_gpio:%d\n"
|
||||
"hid_desc_register:%d level_irq_udelay:%d vendor_id:%d product_id:%d\n"
|
||||
"flags:%d easy_wakeup_gesture:%d\n", __func__,
|
||||
pdata->irq_gpio, pdata->rst_gpio,
|
||||
pdata->hid_desc_register,
|
||||
pdata->level_irq_udelay, pdata->vendor_id, pdata->product_id,
|
||||
pdata->flags, pdata->easy_wakeup_gesture);
|
||||
|
||||
pdata->xres = cyttsp5_xres;
|
||||
pdata->init = cyttsp5_init;
|
||||
pdata->power = cyttsp5_power;
|
||||
pdata->detect = cyttsp5_detect;
|
||||
pdata->irq_stat = cyttsp5_irq_stat;
|
||||
|
||||
return pdata;
|
||||
|
||||
fail_free_sett:
|
||||
for (i--; i >= 0; i--)
|
||||
free_touch_setting(pdata->sett[i]);
|
||||
fail_free:
|
||||
kfree(pdata);
|
||||
fail:
|
||||
return ERR_PTR(rc);
|
||||
}
|
||||
|
||||
static void free_core_pdata(void *pdata)
|
||||
{
|
||||
struct cyttsp5_core_platform_data *core_pdata = pdata;
|
||||
unsigned int i;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(touch_setting_names); i++)
|
||||
free_touch_setting(core_pdata->sett[i]);
|
||||
kfree(core_pdata);
|
||||
}
|
||||
|
||||
int cyttsp5_devtree_create_and_get_pdata(struct device *adap_dev)
|
||||
{
|
||||
struct cyttsp5_platform_data *pdata;
|
||||
struct device_node *core_node, *dev_node, *dev_node_fail;
|
||||
enum cyttsp5_device_type type;
|
||||
int count = 0;
|
||||
int rc = 0;
|
||||
|
||||
if (!adap_dev->of_node)
|
||||
return 0;
|
||||
|
||||
pdata = kzalloc(sizeof(*pdata), GFP_KERNEL);
|
||||
if (!pdata)
|
||||
return -ENOMEM;
|
||||
|
||||
adap_dev->platform_data = pdata;
|
||||
set_pdata_ptr(pdata);
|
||||
|
||||
/* There should be only one core node */
|
||||
for_each_child_of_node(adap_dev->of_node, core_node) {
|
||||
const char *name;
|
||||
|
||||
rc = of_property_read_string(core_node, "name", &name);
|
||||
if (!rc)
|
||||
pr_debug("%s: name:%s\n", __func__, name);
|
||||
|
||||
pdata->core_pdata = create_and_get_core_pdata(core_node);
|
||||
if (IS_ERR(pdata->core_pdata)) {
|
||||
rc = PTR_ERR(pdata->core_pdata);
|
||||
break;
|
||||
}
|
||||
|
||||
/* Increment reference count */
|
||||
of_node_get(core_node);
|
||||
|
||||
for_each_child_of_node(core_node, dev_node) {
|
||||
count++;
|
||||
rc = get_device_type(dev_node, &type);
|
||||
if (rc)
|
||||
break;
|
||||
*pdata_ptr[type].pdata
|
||||
= create_and_get_device_pdata(dev_node, type);
|
||||
if (IS_ERR(*pdata_ptr[type].pdata))
|
||||
rc = PTR_ERR(*pdata_ptr[type].pdata);
|
||||
if (rc)
|
||||
break;
|
||||
/* Increment reference count */
|
||||
of_node_get(dev_node);
|
||||
}
|
||||
|
||||
if (rc) {
|
||||
free_core_pdata(pdata->core_pdata);
|
||||
of_node_put(core_node);
|
||||
for_each_child_of_node(core_node, dev_node_fail) {
|
||||
if (dev_node == dev_node_fail)
|
||||
break;
|
||||
rc = get_device_type(dev_node, &type);
|
||||
if (rc)
|
||||
break;
|
||||
free_device_pdata(type);
|
||||
of_node_put(dev_node);
|
||||
}
|
||||
break;
|
||||
}
|
||||
pdata->loader_pdata = &_cyttsp5_loader_platform_data;
|
||||
}
|
||||
|
||||
pr_debug("%s: %d child node(s) found\n", __func__, count);
|
||||
|
||||
return rc;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(cyttsp5_devtree_create_and_get_pdata);
|
||||
|
||||
int cyttsp5_devtree_clean_pdata(struct device *adap_dev)
|
||||
{
|
||||
struct cyttsp5_platform_data *pdata;
|
||||
struct device_node *core_node, *dev_node;
|
||||
enum cyttsp5_device_type type;
|
||||
int rc = 0;
|
||||
|
||||
if (!adap_dev->of_node)
|
||||
return 0;
|
||||
|
||||
pdata = dev_get_platdata(adap_dev);
|
||||
set_pdata_ptr(pdata);
|
||||
for_each_child_of_node(adap_dev->of_node, core_node) {
|
||||
free_core_pdata(pdata->core_pdata);
|
||||
of_node_put(core_node);
|
||||
for_each_child_of_node(core_node, dev_node) {
|
||||
rc = get_device_type(dev_node, &type);
|
||||
if (rc)
|
||||
break;
|
||||
free_device_pdata(type);
|
||||
of_node_put(dev_node);
|
||||
}
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(cyttsp5_devtree_clean_pdata);
|
||||
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_DESCRIPTION("Parade TrueTouch(R) Standard Product DeviceTree Driver");
|
||||
MODULE_AUTHOR("Parade Technologies <ttdrivers@paradetech.com>");
|
||||
238
drivers/input/touchscreen/cyttsp5/cyttsp5_i2c.c
Normal file
238
drivers/input/touchscreen/cyttsp5/cyttsp5_i2c.c
Normal file
@@ -0,0 +1,238 @@
|
||||
/*
|
||||
* cyttsp5_i2c.c
|
||||
* Parade TrueTouch(TM) Standard Product V5 I2C Module.
|
||||
* For use with Parade touchscreen controllers.
|
||||
* Supported parts include:
|
||||
* CYTMA5XX
|
||||
* CYTMA448
|
||||
* CYTMA445A
|
||||
* CYTT21XXX
|
||||
* CYTT31XXX
|
||||
*
|
||||
* Copyright (C) 2015 Parade Technologies
|
||||
* Copyright (C) 2012-2015 Cypress Semiconductor
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* Contact Parade Technologies at www.paradetech.com <ttdrivers@paradetech.com>
|
||||
*
|
||||
*/
|
||||
|
||||
#include "cyttsp5_regs.h"
|
||||
|
||||
#include <linux/i2c.h>
|
||||
#include <linux/version.h>
|
||||
|
||||
#define CY_I2C_DATA_SIZE (2 * 256)
|
||||
|
||||
extern bool cyttsp5_device_access_is_init(void);
|
||||
extern bool cyttsp5_loader_is_init(void);
|
||||
|
||||
static int cyttsp5_i2c_read_default(struct device *dev, void *buf, int size)
|
||||
{
|
||||
struct i2c_client *client = to_i2c_client(dev);
|
||||
int rc;
|
||||
|
||||
if (!buf || !size || size > CY_I2C_DATA_SIZE)
|
||||
return -EINVAL;
|
||||
|
||||
rc = i2c_master_recv(client, buf, size);
|
||||
|
||||
return (rc < 0) ? rc : rc != size ? -EIO : 0;
|
||||
}
|
||||
|
||||
static int cyttsp5_i2c_read_default_nosize(struct device *dev, u8 *buf, u32 max)
|
||||
{
|
||||
struct i2c_client *client = to_i2c_client(dev);
|
||||
struct i2c_msg msgs[2];
|
||||
u8 msg_count = 1;
|
||||
int rc;
|
||||
u32 size;
|
||||
|
||||
if (!buf)
|
||||
return -EINVAL;
|
||||
|
||||
msgs[0].addr = client->addr;
|
||||
msgs[0].flags = (client->flags & I2C_M_TEN) | I2C_M_RD;
|
||||
msgs[0].len = 2;
|
||||
msgs[0].buf = buf;
|
||||
rc = i2c_transfer(client->adapter, msgs, msg_count);
|
||||
if (rc < 0 || rc != msg_count)
|
||||
return (rc < 0) ? rc : -EIO;
|
||||
|
||||
size = get_unaligned_le16(&buf[0]);
|
||||
if (!size || size == 2 || size >= CY_PIP_1P7_EMPTY_BUF)
|
||||
/*
|
||||
* Before PIP 1.7, empty buffer is 0x0002;
|
||||
* From PIP 1.7, empty buffer is 0xFFXX
|
||||
*/
|
||||
return 0;
|
||||
|
||||
if (size > max)
|
||||
return -EINVAL;
|
||||
|
||||
rc = i2c_master_recv(client, buf, size);
|
||||
|
||||
return (rc < 0) ? rc : rc != (int)size ? -EIO : 0;
|
||||
}
|
||||
|
||||
static int cyttsp5_i2c_write_read_specific(struct device *dev, u8 write_len,
|
||||
u8 *write_buf, u8 *read_buf)
|
||||
{
|
||||
struct i2c_client *client = to_i2c_client(dev);
|
||||
struct i2c_msg msgs[2];
|
||||
u8 msg_count = 1;
|
||||
int rc;
|
||||
|
||||
if (!write_buf || !write_len)
|
||||
return -EINVAL;
|
||||
|
||||
msgs[0].addr = client->addr;
|
||||
msgs[0].flags = client->flags & I2C_M_TEN;
|
||||
msgs[0].len = write_len;
|
||||
msgs[0].buf = write_buf;
|
||||
rc = i2c_transfer(client->adapter, msgs, msg_count);
|
||||
|
||||
if (rc < 0 || rc != msg_count)
|
||||
return (rc < 0) ? rc : -EIO;
|
||||
|
||||
rc = 0;
|
||||
|
||||
if (read_buf)
|
||||
rc = cyttsp5_i2c_read_default_nosize(dev, read_buf,
|
||||
CY_I2C_DATA_SIZE);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
static struct cyttsp5_bus_ops cyttsp5_i2c_bus_ops = {
|
||||
.bustype = BUS_I2C,
|
||||
.read_default = cyttsp5_i2c_read_default,
|
||||
.read_default_nosize = cyttsp5_i2c_read_default_nosize,
|
||||
.write_read_specific = cyttsp5_i2c_write_read_specific,
|
||||
};
|
||||
|
||||
#ifdef CYTTSP5_DEVICETREE_SUPPORT
|
||||
static const struct of_device_id cyttsp5_i2c_of_match[] = {
|
||||
{ .compatible = "cy,cyttsp5_i2c_adapter", },
|
||||
{ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, cyttsp5_i2c_of_match);
|
||||
#endif
|
||||
|
||||
bool probe_done = false;
|
||||
|
||||
bool cyttsp5_is_probe_done(void)
|
||||
{
|
||||
return probe_done;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(cyttsp5_is_probe_done);
|
||||
|
||||
static int cyttsp5_i2c_probe(struct i2c_client *client,
|
||||
const struct i2c_device_id *i2c_id)
|
||||
{
|
||||
struct device *dev = &client->dev;
|
||||
#ifdef CYTTSP5_DEVICETREE_SUPPORT
|
||||
const struct of_device_id *match;
|
||||
#endif
|
||||
int rc;
|
||||
|
||||
if (cyttsp5_device_access_is_init() &&
|
||||
cyttsp5_loader_is_init())
|
||||
pr_info("cyttsp5 loader and device_access is init");
|
||||
|
||||
pr_info("%s: Start probe!", __func__);
|
||||
if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) {
|
||||
dev_err(dev, "I2C functionality not Supported\n");
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
#ifdef CYTTSP5_DEVICETREE_SUPPORT
|
||||
match = of_match_device(of_match_ptr(cyttsp5_i2c_of_match), dev);
|
||||
if (match) {
|
||||
rc = cyttsp5_devtree_create_and_get_pdata(dev);
|
||||
if (rc < 0)
|
||||
return rc;
|
||||
}
|
||||
#endif
|
||||
rc = cyttsp5_probe(&cyttsp5_i2c_bus_ops, &client->dev, client->irq,
|
||||
CY_I2C_DATA_SIZE);
|
||||
|
||||
#ifdef CYTTSP5_DEVICETREE_SUPPORT
|
||||
if (rc && match)
|
||||
cyttsp5_devtree_clean_pdata(dev);
|
||||
#endif
|
||||
probe_done = true;
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int cyttsp5_i2c_remove(struct i2c_client *client)
|
||||
{
|
||||
#ifdef CYTTSP5_DEVICETREE_SUPPORT
|
||||
struct device *dev = &client->dev;
|
||||
const struct of_device_id *match;
|
||||
#endif
|
||||
struct cyttsp5_core_data *cd = i2c_get_clientdata(client);
|
||||
|
||||
cyttsp5_release(cd);
|
||||
|
||||
#ifdef CYTTSP5_DEVICETREE_SUPPORT
|
||||
match = of_match_device(of_match_ptr(cyttsp5_i2c_of_match), dev);
|
||||
if (match)
|
||||
cyttsp5_devtree_clean_pdata(dev);
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct i2c_device_id cyttsp5_i2c_id[] = {
|
||||
{ CYTTSP5_I2C_NAME, 0, },
|
||||
{ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(i2c, cyttsp5_i2c_id);
|
||||
|
||||
static struct i2c_driver cyttsp5_i2c_driver = {
|
||||
.driver = {
|
||||
.name = CYTTSP5_I2C_NAME,
|
||||
.owner = THIS_MODULE,
|
||||
.pm = &cyttsp5_pm_ops,
|
||||
#ifdef CYTTSP5_DEVICETREE_SUPPORT
|
||||
.of_match_table = cyttsp5_i2c_of_match,
|
||||
#endif
|
||||
},
|
||||
.probe = cyttsp5_i2c_probe,
|
||||
.remove = cyttsp5_i2c_remove,
|
||||
.id_table = cyttsp5_i2c_id,
|
||||
};
|
||||
|
||||
#if (KERNEL_VERSION(3, 3, 0) <= LINUX_VERSION_CODE)
|
||||
module_i2c_driver(cyttsp5_i2c_driver);
|
||||
#else
|
||||
static int __init cyttsp5_i2c_init(void)
|
||||
{
|
||||
int rc = i2c_add_driver(&cyttsp5_i2c_driver);
|
||||
|
||||
pr_info("%s: Parade TTSP I2C Driver (Built %s) rc=%d\n",
|
||||
__func__, CY_DRIVER_VERSION, rc);
|
||||
return rc;
|
||||
}
|
||||
module_init(cyttsp5_i2c_init);
|
||||
|
||||
static void __exit cyttsp5_i2c_exit(void)
|
||||
{
|
||||
i2c_del_driver(&cyttsp5_i2c_driver);
|
||||
}
|
||||
module_exit(cyttsp5_i2c_exit);
|
||||
#endif
|
||||
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_DESCRIPTION("Parade TrueTouch(R) Standard Product I2C driver");
|
||||
MODULE_AUTHOR("Parade Technologies <ttdrivers@paradetech.com>");
|
||||
1628
drivers/input/touchscreen/cyttsp5/cyttsp5_loader.c
Normal file
1628
drivers/input/touchscreen/cyttsp5/cyttsp5_loader.c
Normal file
File diff suppressed because it is too large
Load Diff
743
drivers/input/touchscreen/cyttsp5/cyttsp5_mt_common.c
Normal file
743
drivers/input/touchscreen/cyttsp5/cyttsp5_mt_common.c
Normal file
@@ -0,0 +1,743 @@
|
||||
/*
|
||||
* cyttsp5_mt_common.c
|
||||
* Parade TrueTouch(TM) Standard Product V5 Multi-Touch Reports Module.
|
||||
* For use with Parade touchscreen controllers.
|
||||
* Supported parts include:
|
||||
* CYTMA5XX
|
||||
* CYTMA448
|
||||
* CYTMA445A
|
||||
* CYTT21XXX
|
||||
* CYTT31XXX
|
||||
*
|
||||
* Copyright (C) 2015 Parade Technologies
|
||||
* Copyright (C) 2012-2015 Cypress Semiconductor
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* Contact Parade Technologies at www.paradetech.com <ttdrivers@paradetech.com>
|
||||
*
|
||||
*/
|
||||
|
||||
#include "cyttsp5_regs.h"
|
||||
|
||||
#define CYTTSP5_MT_NAME "cyttsp5_mt"
|
||||
|
||||
#define MT_PARAM_SIGNAL(md, sig_ost) PARAM_SIGNAL(md->pdata->frmwrk, sig_ost)
|
||||
#define MT_PARAM_MIN(md, sig_ost) PARAM_MIN(md->pdata->frmwrk, sig_ost)
|
||||
#define MT_PARAM_MAX(md, sig_ost) PARAM_MAX(md->pdata->frmwrk, sig_ost)
|
||||
#define MT_PARAM_FUZZ(md, sig_ost) PARAM_FUZZ(md->pdata->frmwrk, sig_ost)
|
||||
#define MT_PARAM_FLAT(md, sig_ost) PARAM_FLAT(md->pdata->frmwrk, sig_ost)
|
||||
|
||||
static void cyttsp5_mt_lift_all(struct cyttsp5_mt_data *md)
|
||||
{
|
||||
int max = md->si->tch_abs[CY_TCH_T].max;
|
||||
|
||||
if (md->num_prv_rec != 0) {
|
||||
if (md->mt_function.report_slot_liftoff)
|
||||
md->mt_function.report_slot_liftoff(md, max);
|
||||
input_sync(md->input);
|
||||
md->num_prv_rec = 0;
|
||||
}
|
||||
}
|
||||
|
||||
static void cyttsp5_get_touch_axis(struct cyttsp5_mt_data *md,
|
||||
int *axis, int size, int max, u8 *xy_data, int bofs)
|
||||
{
|
||||
int nbyte;
|
||||
int next;
|
||||
|
||||
for (nbyte = 0, *axis = 0, next = 0; nbyte < size; nbyte++) {
|
||||
parade_debug(md->dev, DEBUG_LEVEL_2,
|
||||
"%s: *axis=%02X(%d) size=%d max=%08X xy_data=%p xy_data[%d]=%02X(%d) bofs=%d\n",
|
||||
__func__, *axis, *axis, size, max, xy_data, next,
|
||||
xy_data[next], xy_data[next], bofs);
|
||||
*axis = *axis + ((xy_data[next] >> bofs) << (nbyte * 8));
|
||||
next++;
|
||||
}
|
||||
|
||||
*axis &= max - 1;
|
||||
|
||||
parade_debug(md->dev, DEBUG_LEVEL_2,
|
||||
"%s: *axis=%02X(%d) size=%d max=%08X xy_data=%p xy_data[%d]=%02X(%d)\n",
|
||||
__func__, *axis, *axis, size, max, xy_data, next,
|
||||
xy_data[next], xy_data[next]);
|
||||
}
|
||||
|
||||
static void cyttsp5_get_touch_hdr(struct cyttsp5_mt_data *md,
|
||||
struct cyttsp5_touch *touch, u8 *xy_mode)
|
||||
{
|
||||
struct device *dev = md->dev;
|
||||
struct cyttsp5_sysinfo *si = md->si;
|
||||
enum cyttsp5_tch_hdr hdr;
|
||||
|
||||
for (hdr = CY_TCH_TIME; hdr < CY_TCH_NUM_HDR; hdr++) {
|
||||
if (!si->tch_hdr[hdr].report)
|
||||
continue;
|
||||
cyttsp5_get_touch_axis(md, &touch->hdr[hdr],
|
||||
si->tch_hdr[hdr].size,
|
||||
si->tch_hdr[hdr].max,
|
||||
xy_mode + si->tch_hdr[hdr].ofs,
|
||||
si->tch_hdr[hdr].bofs);
|
||||
parade_debug(dev, DEBUG_LEVEL_2, "%s: get %s=%04X(%d)\n",
|
||||
__func__, cyttsp5_tch_hdr_string[hdr],
|
||||
touch->hdr[hdr], touch->hdr[hdr]);
|
||||
}
|
||||
|
||||
parade_debug(dev, DEBUG_LEVEL_1,
|
||||
"%s: time=%X tch_num=%d lo=%d noise=%d counter=%d\n",
|
||||
__func__,
|
||||
touch->hdr[CY_TCH_TIME],
|
||||
touch->hdr[CY_TCH_NUM],
|
||||
touch->hdr[CY_TCH_LO],
|
||||
touch->hdr[CY_TCH_NOISE],
|
||||
touch->hdr[CY_TCH_COUNTER]);
|
||||
}
|
||||
|
||||
static void cyttsp5_get_touch_record(struct cyttsp5_mt_data *md,
|
||||
struct cyttsp5_touch *touch, u8 *xy_data)
|
||||
{
|
||||
struct device *dev = md->dev;
|
||||
struct cyttsp5_sysinfo *si = md->si;
|
||||
enum cyttsp5_tch_abs abs;
|
||||
|
||||
for (abs = CY_TCH_X; abs < CY_TCH_NUM_ABS; abs++) {
|
||||
if (!si->tch_abs[abs].report)
|
||||
continue;
|
||||
cyttsp5_get_touch_axis(md, &touch->abs[abs],
|
||||
si->tch_abs[abs].size,
|
||||
si->tch_abs[abs].max,
|
||||
xy_data + si->tch_abs[abs].ofs,
|
||||
si->tch_abs[abs].bofs);
|
||||
parade_debug(dev, DEBUG_LEVEL_2, "%s: get %s=%04X(%d)\n",
|
||||
__func__, cyttsp5_tch_abs_string[abs],
|
||||
touch->abs[abs], touch->abs[abs]);
|
||||
}
|
||||
}
|
||||
|
||||
static void cyttsp5_mt_process_touch(struct cyttsp5_mt_data *md,
|
||||
struct cyttsp5_touch *touch)
|
||||
{
|
||||
struct device *dev = md->dev;
|
||||
struct cyttsp5_sysinfo *si = md->si;
|
||||
int tmp;
|
||||
bool flipped;
|
||||
|
||||
|
||||
/* Orientation is signed */
|
||||
touch->abs[CY_TCH_OR] = (int8_t)touch->abs[CY_TCH_OR];
|
||||
|
||||
if (md->pdata->flags & CY_MT_FLAG_FLIP) {
|
||||
tmp = touch->abs[CY_TCH_X];
|
||||
touch->abs[CY_TCH_X] = touch->abs[CY_TCH_Y];
|
||||
touch->abs[CY_TCH_Y] = tmp;
|
||||
if (touch->abs[CY_TCH_OR] > 0)
|
||||
touch->abs[CY_TCH_OR] =
|
||||
md->or_max - touch->abs[CY_TCH_OR];
|
||||
else
|
||||
touch->abs[CY_TCH_OR] =
|
||||
md->or_min - touch->abs[CY_TCH_OR];
|
||||
flipped = true;
|
||||
} else
|
||||
flipped = false;
|
||||
|
||||
if (md->pdata->flags & CY_MT_FLAG_INV_X) {
|
||||
if (flipped)
|
||||
touch->abs[CY_TCH_X] = si->sensing_conf_data.res_y -
|
||||
touch->abs[CY_TCH_X];
|
||||
else
|
||||
touch->abs[CY_TCH_X] = si->sensing_conf_data.res_x -
|
||||
touch->abs[CY_TCH_X];
|
||||
touch->abs[CY_TCH_OR] *= -1;
|
||||
}
|
||||
if (md->pdata->flags & CY_MT_FLAG_INV_Y) {
|
||||
if (flipped)
|
||||
touch->abs[CY_TCH_Y] = si->sensing_conf_data.res_x -
|
||||
touch->abs[CY_TCH_Y];
|
||||
else
|
||||
touch->abs[CY_TCH_Y] = si->sensing_conf_data.res_y -
|
||||
touch->abs[CY_TCH_Y];
|
||||
touch->abs[CY_TCH_OR] *= -1;
|
||||
}
|
||||
|
||||
/* Convert MAJOR/MINOR from mm to resolution */
|
||||
tmp = touch->abs[CY_TCH_MAJ] * 100 * si->sensing_conf_data.res_x;
|
||||
touch->abs[CY_TCH_MAJ] = tmp / si->sensing_conf_data.len_x;
|
||||
tmp = touch->abs[CY_TCH_MIN] * 100 * si->sensing_conf_data.res_x;
|
||||
touch->abs[CY_TCH_MIN] = tmp / si->sensing_conf_data.len_x;
|
||||
|
||||
parade_debug(dev, DEBUG_LEVEL_2, "%s: flip=%s inv-x=%s inv-y=%s x=%04X(%d) y=%04X(%d)\n",
|
||||
__func__, flipped ? "true" : "false",
|
||||
md->pdata->flags & CY_MT_FLAG_INV_X ? "true" : "false",
|
||||
md->pdata->flags & CY_MT_FLAG_INV_Y ? "true" : "false",
|
||||
touch->abs[CY_TCH_X], touch->abs[CY_TCH_X],
|
||||
touch->abs[CY_TCH_Y], touch->abs[CY_TCH_Y]);
|
||||
}
|
||||
|
||||
static void cyttsp5_report_event(struct cyttsp5_mt_data *md, int event,
|
||||
int value)
|
||||
{
|
||||
int sig = MT_PARAM_SIGNAL(md, event);
|
||||
|
||||
if (sig != CY_IGNORE_VALUE)
|
||||
input_report_abs(md->input, sig, value);
|
||||
}
|
||||
|
||||
static int cyttsp5_get_mt_touches(struct cyttsp5_mt_data *md,
|
||||
struct cyttsp5_touch *tch, int num_cur_tch)
|
||||
{
|
||||
struct device *dev = md->dev;
|
||||
struct cyttsp5_sysinfo *si = md->si;
|
||||
int sig;
|
||||
int i, j, t = 0;
|
||||
int mt_sync_count = 0;
|
||||
u8 *tch_addr;
|
||||
unsigned long *ids = NULL;
|
||||
unsigned int len = BITS_TO_LONGS(si->tch_abs[CY_TCH_T].max);
|
||||
|
||||
memset(tch->abs, 0, sizeof(tch->abs));
|
||||
ids = kzalloc(len * sizeof(unsigned long), GFP_KERNEL);
|
||||
if (ids == NULL)
|
||||
return -ENOMEM;
|
||||
|
||||
for (i = 0; i < num_cur_tch; i++) {
|
||||
tch_addr = si->xy_data + (i * si->desc.tch_record_size);
|
||||
cyttsp5_get_touch_record(md, tch, tch_addr);
|
||||
|
||||
/* Discard proximity event */
|
||||
if (tch->abs[CY_TCH_O] == CY_OBJ_PROXIMITY) {
|
||||
parade_debug(dev, DEBUG_LEVEL_2, "%s: Discarding proximity event\n",
|
||||
__func__);
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Validate track_id */
|
||||
t = tch->abs[CY_TCH_T];
|
||||
if (t < md->t_min || t > md->t_max) {
|
||||
dev_err(dev, "%s: tch=%d -> bad trk_id=%d max_id=%d\n",
|
||||
__func__, i, t, md->t_max);
|
||||
if (md->mt_function.input_sync)
|
||||
md->mt_function.input_sync(md->input);
|
||||
mt_sync_count++;
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Lift-off */
|
||||
if (tch->abs[CY_TCH_E] == CY_EV_LIFTOFF) {
|
||||
parade_debug(dev, DEBUG_LEVEL_1, "%s: t=%d e=%d lift-off\n",
|
||||
__func__, t, tch->abs[CY_TCH_E]);
|
||||
goto cyttsp5_get_mt_touches_pr_tch;
|
||||
}
|
||||
|
||||
/* Process touch */
|
||||
cyttsp5_mt_process_touch(md, tch);
|
||||
|
||||
/* use 0 based track id's */
|
||||
t -= md->t_min;
|
||||
|
||||
sig = MT_PARAM_SIGNAL(md, CY_ABS_ID_OST);
|
||||
if (sig != CY_IGNORE_VALUE) {
|
||||
if (md->mt_function.input_report)
|
||||
md->mt_function.input_report(md->input, sig,
|
||||
t, tch->abs[CY_TCH_O]);
|
||||
__set_bit(t, ids);
|
||||
}
|
||||
|
||||
/* If touch type is hover, send P as distance, reset P */
|
||||
if (tch->abs[CY_TCH_O] == CY_OBJ_HOVER) {
|
||||
/* CY_ABS_D_OST signal must be in touch framework */
|
||||
cyttsp5_report_event(md, CY_ABS_D_OST,
|
||||
tch->abs[CY_TCH_P]);
|
||||
tch->abs[CY_TCH_P] = 0;
|
||||
} else
|
||||
cyttsp5_report_event(md, CY_ABS_D_OST, 0);
|
||||
|
||||
|
||||
/* all devices: position and pressure fields */
|
||||
for (j = 0; j <= CY_ABS_W_OST; j++) {
|
||||
if (!si->tch_abs[j].report)
|
||||
continue;
|
||||
cyttsp5_report_event(md, CY_ABS_X_OST + j,
|
||||
tch->abs[CY_TCH_X + j]);
|
||||
}
|
||||
|
||||
/* Get the extended touch fields */
|
||||
for (j = 0; j < CY_NUM_EXT_TCH_FIELDS; j++) {
|
||||
if (!si->tch_abs[CY_ABS_MAJ_OST + j].report)
|
||||
continue;
|
||||
cyttsp5_report_event(md, CY_ABS_MAJ_OST + j,
|
||||
tch->abs[CY_TCH_MAJ + j]);
|
||||
}
|
||||
if (md->mt_function.input_sync)
|
||||
md->mt_function.input_sync(md->input);
|
||||
mt_sync_count++;
|
||||
|
||||
cyttsp5_get_mt_touches_pr_tch:
|
||||
parade_debug(dev, DEBUG_LEVEL_1,
|
||||
"%s: t=%d x=%d y=%d z=%d M=%d m=%d o=%d e=%d obj=%d tip=%d\n",
|
||||
__func__, t,
|
||||
tch->abs[CY_TCH_X],
|
||||
tch->abs[CY_TCH_Y],
|
||||
tch->abs[CY_TCH_P],
|
||||
tch->abs[CY_TCH_MAJ],
|
||||
tch->abs[CY_TCH_MIN],
|
||||
tch->abs[CY_TCH_OR],
|
||||
tch->abs[CY_TCH_E],
|
||||
tch->abs[CY_TCH_O],
|
||||
tch->abs[CY_TCH_TIP]);
|
||||
}
|
||||
|
||||
if (md->mt_function.final_sync)
|
||||
md->mt_function.final_sync(md->input,
|
||||
si->tch_abs[CY_TCH_T].max, mt_sync_count, ids);
|
||||
|
||||
md->num_prv_rec = num_cur_tch;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* read xy_data for all current touches */
|
||||
static int cyttsp5_xy_worker(struct cyttsp5_mt_data *md)
|
||||
{
|
||||
struct device *dev = md->dev;
|
||||
struct cyttsp5_sysinfo *si = md->si;
|
||||
int max_tch = si->sensing_conf_data.max_tch;
|
||||
struct cyttsp5_touch tch;
|
||||
u8 num_cur_tch;
|
||||
int rc = 0;
|
||||
|
||||
cyttsp5_get_touch_hdr(md, &tch, si->xy_mode + 3);
|
||||
|
||||
num_cur_tch = tch.hdr[CY_TCH_NUM];
|
||||
if (num_cur_tch > max_tch) {
|
||||
dev_err(dev, "%s: Num touch err detected (n=%d)\n",
|
||||
__func__, num_cur_tch);
|
||||
num_cur_tch = max_tch;
|
||||
}
|
||||
|
||||
if (tch.hdr[CY_TCH_LO]) {
|
||||
parade_debug(dev, DEBUG_LEVEL_1, "%s: Large area detected\n",
|
||||
__func__);
|
||||
if (md->pdata->flags & CY_MT_FLAG_NO_TOUCH_ON_LO)
|
||||
num_cur_tch = 0;
|
||||
}
|
||||
|
||||
if (num_cur_tch == 0 && md->num_prv_rec == 0)
|
||||
goto cyttsp5_xy_worker_exit;
|
||||
|
||||
/* extract xy_data for all currently reported touches */
|
||||
parade_debug(dev, DEBUG_LEVEL_2, "%s: extract data num_cur_tch=%d\n",
|
||||
__func__, num_cur_tch);
|
||||
if (num_cur_tch)
|
||||
cyttsp5_get_mt_touches(md, &tch, num_cur_tch);
|
||||
else
|
||||
cyttsp5_mt_lift_all(md);
|
||||
|
||||
rc = 0;
|
||||
|
||||
cyttsp5_xy_worker_exit:
|
||||
return rc;
|
||||
}
|
||||
|
||||
static void cyttsp5_mt_send_dummy_event(struct cyttsp5_core_data *cd,
|
||||
struct cyttsp5_mt_data *md)
|
||||
{
|
||||
#ifndef EASYWAKE_TSG6
|
||||
/* TSG5 EasyWake */
|
||||
unsigned long ids = 0;
|
||||
|
||||
/* for easy wakeup */
|
||||
if (md->mt_function.input_report)
|
||||
md->mt_function.input_report(md->input, ABS_MT_TRACKING_ID,
|
||||
0, CY_OBJ_STANDARD_FINGER);
|
||||
if (md->mt_function.input_sync)
|
||||
md->mt_function.input_sync(md->input);
|
||||
if (md->mt_function.final_sync)
|
||||
md->mt_function.final_sync(md->input, 0, 1, &ids);
|
||||
if (md->mt_function.report_slot_liftoff)
|
||||
md->mt_function.report_slot_liftoff(md, 1);
|
||||
if (md->mt_function.final_sync)
|
||||
md->mt_function.final_sync(md->input, 1, 1, &ids);
|
||||
#else
|
||||
/* TSG6 FW1.3 and above only. TSG6 FW1.0 - 1.2 does not */
|
||||
/* support EasyWake, and this function will not be called */
|
||||
u8 key_value = 0;
|
||||
|
||||
switch (cd->gesture_id) {
|
||||
case GESTURE_DOUBLE_TAP:
|
||||
key_value = KEY_WAKEUP;
|
||||
break;
|
||||
case GESTURE_TWO_FINGERS_SLIDE:
|
||||
key_value = KEY_F2;
|
||||
break;
|
||||
case GESTURE_TOUCH_DETECTED:
|
||||
key_value = KEY_F3;
|
||||
break;
|
||||
case GESTURE_PUSH_BUTTON:
|
||||
key_value = KEY_F4;
|
||||
break;
|
||||
case GESTURE_SINGLE_SLIDE_DE_TX:
|
||||
key_value = KEY_F5;
|
||||
break;
|
||||
case GESTURE_SINGLE_SLIDE_IN_TX:
|
||||
key_value = KEY_F6;
|
||||
break;
|
||||
case GESTURE_SINGLE_SLIDE_DE_RX:
|
||||
key_value = KEY_F7;
|
||||
break;
|
||||
case GESTURE_SINGLE_SLIDE_IN_RX:
|
||||
key_value = KEY_F8;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
if (key_value == 0)
|
||||
return;
|
||||
|
||||
input_report_key(md->input, key_value, 1);
|
||||
mdelay(10);
|
||||
input_report_key(md->input, key_value, 0);
|
||||
input_sync(md->input);
|
||||
#endif
|
||||
}
|
||||
|
||||
static int cyttsp5_mt_attention(struct device *dev)
|
||||
{
|
||||
struct cyttsp5_core_data *cd = dev_get_drvdata(dev);
|
||||
struct cyttsp5_mt_data *md = &cd->md;
|
||||
int rc;
|
||||
|
||||
if (md->si->xy_mode[2] != md->si->desc.tch_report_id)
|
||||
return 0;
|
||||
|
||||
/* core handles handshake */
|
||||
mutex_lock(&md->mt_lock);
|
||||
rc = cyttsp5_xy_worker(md);
|
||||
mutex_unlock(&md->mt_lock);
|
||||
if (rc < 0)
|
||||
dev_err(dev, "%s: xy_worker error r=%d\n", __func__, rc);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int cyttsp5_mt_wake_attention(struct device *dev)
|
||||
{
|
||||
struct cyttsp5_core_data *cd = dev_get_drvdata(dev);
|
||||
struct cyttsp5_mt_data *md = &cd->md;
|
||||
|
||||
mutex_lock(&md->mt_lock);
|
||||
cyttsp5_mt_send_dummy_event(cd, md);
|
||||
mutex_unlock(&md->mt_lock);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int cyttsp5_startup_attention(struct device *dev)
|
||||
{
|
||||
struct cyttsp5_core_data *cd = dev_get_drvdata(dev);
|
||||
struct cyttsp5_mt_data *md = &cd->md;
|
||||
|
||||
mutex_lock(&md->mt_lock);
|
||||
cyttsp5_mt_lift_all(md);
|
||||
mutex_unlock(&md->mt_lock);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int cyttsp5_mt_suspend_attention(struct device *dev)
|
||||
{
|
||||
struct cyttsp5_core_data *cd = dev_get_drvdata(dev);
|
||||
struct cyttsp5_mt_data *md = &cd->md;
|
||||
|
||||
mutex_lock(&md->mt_lock);
|
||||
cyttsp5_mt_lift_all(md);
|
||||
md->is_suspended = true;
|
||||
mutex_unlock(&md->mt_lock);
|
||||
|
||||
pm_runtime_put(dev);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int cyttsp5_mt_resume_attention(struct device *dev)
|
||||
{
|
||||
struct cyttsp5_core_data *cd = dev_get_drvdata(dev);
|
||||
struct cyttsp5_mt_data *md = &cd->md;
|
||||
|
||||
pm_runtime_get(dev);
|
||||
|
||||
mutex_lock(&md->mt_lock);
|
||||
md->is_suspended = false;
|
||||
mutex_unlock(&md->mt_lock);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int cyttsp5_mt_open(struct input_dev *input)
|
||||
{
|
||||
struct device *dev = input->dev.parent;
|
||||
struct cyttsp5_core_data *cd = dev_get_drvdata(dev);
|
||||
struct cyttsp5_mt_data *md = &cd->md;
|
||||
|
||||
pm_runtime_get_sync(dev);
|
||||
|
||||
mutex_lock(&md->mt_lock);
|
||||
md->is_suspended = false;
|
||||
mutex_unlock(&md->mt_lock);
|
||||
|
||||
parade_debug(dev, DEBUG_LEVEL_2, "%s: setup subscriptions\n", __func__);
|
||||
|
||||
/* set up touch call back */
|
||||
_cyttsp5_subscribe_attention(dev, CY_ATTEN_IRQ, CYTTSP5_MT_NAME,
|
||||
cyttsp5_mt_attention, CY_MODE_OPERATIONAL);
|
||||
|
||||
/* set up startup call back */
|
||||
_cyttsp5_subscribe_attention(dev, CY_ATTEN_STARTUP, CYTTSP5_MT_NAME,
|
||||
cyttsp5_startup_attention, 0);
|
||||
|
||||
/* set up wakeup call back */
|
||||
_cyttsp5_subscribe_attention(dev, CY_ATTEN_WAKE, CYTTSP5_MT_NAME,
|
||||
cyttsp5_mt_wake_attention, 0);
|
||||
|
||||
/* set up suspend call back */
|
||||
_cyttsp5_subscribe_attention(dev, CY_ATTEN_SUSPEND, CYTTSP5_MT_NAME,
|
||||
cyttsp5_mt_suspend_attention, 0);
|
||||
|
||||
/* set up resume call back */
|
||||
_cyttsp5_subscribe_attention(dev, CY_ATTEN_RESUME, CYTTSP5_MT_NAME,
|
||||
cyttsp5_mt_resume_attention, 0);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void cyttsp5_mt_close(struct input_dev *input)
|
||||
{
|
||||
struct device *dev = input->dev.parent;
|
||||
struct cyttsp5_core_data *cd = dev_get_drvdata(dev);
|
||||
struct cyttsp5_mt_data *md = &cd->md;
|
||||
|
||||
_cyttsp5_unsubscribe_attention(dev, CY_ATTEN_IRQ, CYTTSP5_MT_NAME,
|
||||
cyttsp5_mt_attention, CY_MODE_OPERATIONAL);
|
||||
|
||||
_cyttsp5_unsubscribe_attention(dev, CY_ATTEN_STARTUP, CYTTSP5_MT_NAME,
|
||||
cyttsp5_startup_attention, 0);
|
||||
|
||||
_cyttsp5_unsubscribe_attention(dev, CY_ATTEN_WAKE, CYTTSP5_MT_NAME,
|
||||
cyttsp5_mt_wake_attention, 0);
|
||||
|
||||
_cyttsp5_unsubscribe_attention(dev, CY_ATTEN_SUSPEND, CYTTSP5_MT_NAME,
|
||||
cyttsp5_mt_suspend_attention, 0);
|
||||
|
||||
_cyttsp5_unsubscribe_attention(dev, CY_ATTEN_RESUME, CYTTSP5_MT_NAME,
|
||||
cyttsp5_mt_resume_attention, 0);
|
||||
|
||||
mutex_lock(&md->mt_lock);
|
||||
if (!md->is_suspended) {
|
||||
pm_runtime_put(dev);
|
||||
md->is_suspended = true;
|
||||
}
|
||||
mutex_unlock(&md->mt_lock);
|
||||
}
|
||||
|
||||
static int cyttsp5_setup_input_device(struct device *dev)
|
||||
{
|
||||
struct cyttsp5_core_data *cd = dev_get_drvdata(dev);
|
||||
struct cyttsp5_mt_data *md = &cd->md;
|
||||
int signal = CY_IGNORE_VALUE;
|
||||
int max_x, max_y, max_p, min, max;
|
||||
int max_x_tmp, max_y_tmp;
|
||||
int i;
|
||||
int rc;
|
||||
|
||||
parade_debug(dev, DEBUG_LEVEL_2, "%s: Initialize event signals\n",
|
||||
__func__);
|
||||
__set_bit(EV_ABS, md->input->evbit);
|
||||
__set_bit(EV_REL, md->input->evbit);
|
||||
__set_bit(EV_KEY, md->input->evbit);
|
||||
#ifdef INPUT_PROP_DIRECT
|
||||
__set_bit(INPUT_PROP_DIRECT, md->input->propbit);
|
||||
#endif
|
||||
|
||||
/* If virtualkeys enabled, don't use all screen */
|
||||
if (md->pdata->flags & CY_MT_FLAG_VKEYS) {
|
||||
max_x_tmp = md->pdata->vkeys_x;
|
||||
max_y_tmp = md->pdata->vkeys_y;
|
||||
} else {
|
||||
max_x_tmp = md->si->sensing_conf_data.res_x;
|
||||
max_y_tmp = md->si->sensing_conf_data.res_y;
|
||||
}
|
||||
|
||||
/* get maximum values from the sysinfo data */
|
||||
if (md->pdata->flags & CY_MT_FLAG_FLIP) {
|
||||
max_x = max_y_tmp - 1;
|
||||
max_y = max_x_tmp - 1;
|
||||
} else {
|
||||
max_x = max_x_tmp - 1;
|
||||
max_y = max_y_tmp - 1;
|
||||
}
|
||||
max_p = md->si->sensing_conf_data.max_z;
|
||||
|
||||
/* set event signal capabilities */
|
||||
for (i = 0; i < NUM_SIGNALS(md->pdata->frmwrk); i++) {
|
||||
signal = MT_PARAM_SIGNAL(md, i);
|
||||
if (signal != CY_IGNORE_VALUE) {
|
||||
__set_bit(signal, md->input->absbit);
|
||||
|
||||
min = MT_PARAM_MIN(md, i);
|
||||
max = MT_PARAM_MAX(md, i);
|
||||
if (i == CY_ABS_ID_OST) {
|
||||
/* shift track ids down to start at 0 */
|
||||
max = max - min;
|
||||
min = min - min;
|
||||
} else if (i == CY_ABS_X_OST)
|
||||
max = max_x;
|
||||
else if (i == CY_ABS_Y_OST)
|
||||
max = max_y;
|
||||
else if (i == CY_ABS_P_OST)
|
||||
max = max_p;
|
||||
|
||||
input_set_abs_params(md->input, signal, min, max,
|
||||
MT_PARAM_FUZZ(md, i), MT_PARAM_FLAT(md, i));
|
||||
parade_debug(dev, DEBUG_LEVEL_1,
|
||||
"%s: register signal=%02X min=%d max=%d\n",
|
||||
__func__, signal, min, max);
|
||||
}
|
||||
}
|
||||
|
||||
md->or_min = MT_PARAM_MIN(md, CY_ABS_OR_OST);
|
||||
md->or_max = MT_PARAM_MAX(md, CY_ABS_OR_OST);
|
||||
|
||||
md->t_min = MT_PARAM_MIN(md, CY_ABS_ID_OST);
|
||||
md->t_max = MT_PARAM_MAX(md, CY_ABS_ID_OST);
|
||||
|
||||
rc = md->mt_function.input_register_device(md->input,
|
||||
md->si->tch_abs[CY_TCH_T].max);
|
||||
if (rc < 0)
|
||||
dev_err(dev, "%s: Error, failed register input device r=%d\n",
|
||||
__func__, rc);
|
||||
else
|
||||
md->input_device_registered = true;
|
||||
|
||||
#ifdef EASYWAKE_TSG6
|
||||
input_set_capability(md->input, EV_KEY, KEY_WAKEUP);
|
||||
#if 0
|
||||
input_set_capability(md->input, EV_KEY, KEY_F2);
|
||||
input_set_capability(md->input, EV_KEY, KEY_F3);
|
||||
input_set_capability(md->input, EV_KEY, KEY_F4);
|
||||
input_set_capability(md->input, EV_KEY, KEY_F5);
|
||||
input_set_capability(md->input, EV_KEY, KEY_F6);
|
||||
input_set_capability(md->input, EV_KEY, KEY_F7);
|
||||
input_set_capability(md->input, EV_KEY, KEY_F8);
|
||||
#endif
|
||||
#endif
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int cyttsp5_setup_input_attention(struct device *dev)
|
||||
{
|
||||
struct cyttsp5_core_data *cd = dev_get_drvdata(dev);
|
||||
struct cyttsp5_mt_data *md = &cd->md;
|
||||
int rc;
|
||||
|
||||
md->si = _cyttsp5_request_sysinfo(dev);
|
||||
if (!md->si)
|
||||
return -EINVAL;
|
||||
|
||||
rc = cyttsp5_setup_input_device(dev);
|
||||
|
||||
_cyttsp5_unsubscribe_attention(dev, CY_ATTEN_STARTUP, CYTTSP5_MT_NAME,
|
||||
cyttsp5_setup_input_attention, 0);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
int cyttsp5_mt_probe(struct device *dev)
|
||||
{
|
||||
struct cyttsp5_core_data *cd = dev_get_drvdata(dev);
|
||||
struct cyttsp5_mt_data *md = &cd->md;
|
||||
struct cyttsp5_platform_data *pdata = dev_get_platdata(dev);
|
||||
struct cyttsp5_mt_platform_data *mt_pdata;
|
||||
int rc = 0;
|
||||
|
||||
if (!pdata || !pdata->mt_pdata) {
|
||||
dev_err(dev, "%s: Missing platform data\n", __func__);
|
||||
rc = -ENODEV;
|
||||
goto error_no_pdata;
|
||||
}
|
||||
mt_pdata = pdata->mt_pdata;
|
||||
|
||||
cyttsp5_init_function_ptrs(md);
|
||||
|
||||
mutex_init(&md->mt_lock);
|
||||
md->dev = dev;
|
||||
md->pdata = mt_pdata;
|
||||
|
||||
/* Create the input device and register it. */
|
||||
parade_debug(dev, DEBUG_LEVEL_2,
|
||||
"%s: Create the input device and register it\n", __func__);
|
||||
md->input = input_allocate_device();
|
||||
if (!md->input) {
|
||||
dev_err(dev, "%s: Error, failed to allocate input device\n",
|
||||
__func__);
|
||||
rc = -ENODEV;
|
||||
goto error_alloc_failed;
|
||||
}
|
||||
|
||||
if (md->pdata->inp_dev_name)
|
||||
md->input->name = md->pdata->inp_dev_name;
|
||||
else
|
||||
md->input->name = CYTTSP5_MT_NAME;
|
||||
scnprintf(md->phys, sizeof(md->phys), "%s/input%d", dev_name(dev),
|
||||
cd->phys_num++);
|
||||
md->input->phys = md->phys;
|
||||
md->input->dev.parent = md->dev;
|
||||
md->input->id.vendor = 0x07E4;
|
||||
md->input->id.product = 0x04B9;
|
||||
md->input->open = cyttsp5_mt_open;
|
||||
md->input->close = cyttsp5_mt_close;
|
||||
input_set_drvdata(md->input, md);
|
||||
|
||||
/* get sysinfo */
|
||||
md->si = _cyttsp5_request_sysinfo(dev);
|
||||
|
||||
if (md->si) {
|
||||
rc = cyttsp5_setup_input_device(dev);
|
||||
if (rc)
|
||||
goto error_init_input;
|
||||
} else {
|
||||
dev_err(dev, "%s: Fail get sysinfo pointer from core p=%p\n",
|
||||
__func__, md->si);
|
||||
_cyttsp5_subscribe_attention(dev, CY_ATTEN_STARTUP,
|
||||
CYTTSP5_MT_NAME, cyttsp5_setup_input_attention, 0);
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
error_init_input:
|
||||
input_free_device(md->input);
|
||||
error_alloc_failed:
|
||||
error_no_pdata:
|
||||
dev_err(dev, "%s failed.\n", __func__);
|
||||
return rc;
|
||||
}
|
||||
|
||||
int cyttsp5_mt_release(struct device *dev)
|
||||
{
|
||||
struct cyttsp5_core_data *cd = dev_get_drvdata(dev);
|
||||
struct cyttsp5_mt_data *md = &cd->md;
|
||||
|
||||
if (md->input_device_registered) {
|
||||
input_unregister_device(md->input);
|
||||
} else {
|
||||
input_free_device(md->input);
|
||||
_cyttsp5_unsubscribe_attention(dev, CY_ATTEN_STARTUP,
|
||||
CYTTSP5_MT_NAME, cyttsp5_setup_input_attention, 0);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
85
drivers/input/touchscreen/cyttsp5/cyttsp5_mta.c
Normal file
85
drivers/input/touchscreen/cyttsp5/cyttsp5_mta.c
Normal file
@@ -0,0 +1,85 @@
|
||||
/*
|
||||
* cyttsp5_mta.c
|
||||
* Parade TrueTouch(TM) Standard Product V5 Multi-Touch Protocol A Module.
|
||||
* For use with Parade touchscreen controllers.
|
||||
* Supported parts include:
|
||||
* CYTMA5XX
|
||||
* CYTMA448
|
||||
* CYTMA445A
|
||||
* CYTT21XXX
|
||||
* CYTT31XXX
|
||||
*
|
||||
* Copyright (C) 2015 Parade Technologies
|
||||
* Copyright (C) 2012-2015 Cypress Semiconductor
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* Contact Parade Technologies at www.paradetech.com <ttdrivers@paradetech.com>
|
||||
*
|
||||
*/
|
||||
|
||||
#include "cyttsp5_regs.h"
|
||||
|
||||
static void cyttsp5_final_sync(struct input_dev *input, int max_slots,
|
||||
int mt_sync_count, unsigned long *ids)
|
||||
{
|
||||
if (mt_sync_count)
|
||||
input_sync(input);
|
||||
}
|
||||
|
||||
static void cyttsp5_input_sync(struct input_dev *input)
|
||||
{
|
||||
input_mt_sync(input);
|
||||
}
|
||||
|
||||
static void cyttsp5_input_report(struct input_dev *input, int sig,
|
||||
int t, int type)
|
||||
{
|
||||
if (type == CY_OBJ_STANDARD_FINGER || type == CY_OBJ_GLOVE
|
||||
|| type == CY_OBJ_HOVER) {
|
||||
input_report_key(input, BTN_TOOL_FINGER, CY_BTN_PRESSED);
|
||||
input_report_key(input, BTN_TOOL_PEN, CY_BTN_RELEASED);
|
||||
} else if (type == CY_OBJ_STYLUS) {
|
||||
input_report_key(input, BTN_TOOL_PEN, CY_BTN_PRESSED);
|
||||
input_report_key(input, BTN_TOOL_FINGER, CY_BTN_RELEASED);
|
||||
}
|
||||
|
||||
if (type != CY_OBJ_HOVER)
|
||||
input_report_key(input, BTN_TOUCH, CY_BTN_PRESSED);
|
||||
|
||||
input_report_abs(input, sig, t);
|
||||
}
|
||||
|
||||
static void cyttsp5_report_slot_liftoff(struct cyttsp5_mt_data *md,
|
||||
int max_slots)
|
||||
{
|
||||
input_report_key(md->input, BTN_TOUCH, CY_BTN_RELEASED);
|
||||
input_report_key(md->input, BTN_TOOL_FINGER, CY_BTN_RELEASED);
|
||||
input_report_key(md->input, BTN_TOOL_PEN, CY_BTN_RELEASED);
|
||||
|
||||
}
|
||||
|
||||
static int cyttsp5_input_register_device(struct input_dev *input, int max_slots)
|
||||
{
|
||||
__set_bit(BTN_TOUCH, input->keybit);
|
||||
__set_bit(BTN_TOOL_FINGER, input->keybit);
|
||||
__set_bit(BTN_TOOL_PEN, input->keybit);
|
||||
return input_register_device(input);
|
||||
}
|
||||
|
||||
void cyttsp5_init_function_ptrs(struct cyttsp5_mt_data *md)
|
||||
{
|
||||
md->mt_function.report_slot_liftoff = cyttsp5_report_slot_liftoff;
|
||||
md->mt_function.final_sync = cyttsp5_final_sync;
|
||||
md->mt_function.input_sync = cyttsp5_input_sync;
|
||||
md->mt_function.input_report = cyttsp5_input_report;
|
||||
md->mt_function.input_register_device = cyttsp5_input_register_device;
|
||||
}
|
||||
93
drivers/input/touchscreen/cyttsp5/cyttsp5_mtb.c
Normal file
93
drivers/input/touchscreen/cyttsp5/cyttsp5_mtb.c
Normal file
@@ -0,0 +1,93 @@
|
||||
/*
|
||||
* cyttsp5_mtb.c
|
||||
* Parade TrueTouch(TM) Standard Product V5 Multi-Touch Protocol B Module.
|
||||
* For use with Parade touchscreen controllers.
|
||||
* Supported parts include:
|
||||
* CYTMA5XX
|
||||
* CYTMA448
|
||||
* CYTMA445A
|
||||
* CYTT21XXX
|
||||
* CYTT31XXX
|
||||
*
|
||||
* Copyright (C) 2015 Parade Technologies
|
||||
* Copyright (C) 2012-2015 Cypress Semiconductor
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* Contact Parade Technologies at www.paradetech.com <ttdrivers@paradetech.com>
|
||||
*
|
||||
*/
|
||||
|
||||
#include "cyttsp5_regs.h"
|
||||
#include <linux/input/mt.h>
|
||||
#include <linux/version.h>
|
||||
|
||||
static void cyttsp5_final_sync(struct input_dev *input, int max_slots,
|
||||
int mt_sync_count, unsigned long *ids)
|
||||
{
|
||||
int t;
|
||||
|
||||
for (t = 0; t < max_slots; t++) {
|
||||
if (test_bit(t, ids))
|
||||
continue;
|
||||
input_mt_slot(input, t);
|
||||
input_mt_report_slot_state(input, MT_TOOL_FINGER, false);
|
||||
}
|
||||
|
||||
input_sync(input);
|
||||
}
|
||||
|
||||
static void cyttsp5_input_report(struct input_dev *input, int sig,
|
||||
int t, int type)
|
||||
{
|
||||
input_mt_slot(input, t);
|
||||
|
||||
if (type == CY_OBJ_STANDARD_FINGER || type == CY_OBJ_GLOVE
|
||||
|| type == CY_OBJ_HOVER)
|
||||
input_mt_report_slot_state(input, MT_TOOL_FINGER, true);
|
||||
else if (type == CY_OBJ_STYLUS)
|
||||
input_mt_report_slot_state(input, MT_TOOL_PEN, true);
|
||||
}
|
||||
|
||||
static void cyttsp5_report_slot_liftoff(struct cyttsp5_mt_data *md,
|
||||
int max_slots)
|
||||
{
|
||||
int t;
|
||||
|
||||
if (md->num_prv_rec == 0)
|
||||
return;
|
||||
|
||||
for (t = 0; t < max_slots; t++) {
|
||||
input_mt_slot(md->input, t);
|
||||
input_mt_report_slot_state(md->input,
|
||||
MT_TOOL_FINGER, false);
|
||||
}
|
||||
}
|
||||
|
||||
static int cyttsp5_input_register_device(struct input_dev *input, int max_slots)
|
||||
{
|
||||
#if (KERNEL_VERSION(3, 7, 0) <= LINUX_VERSION_CODE)
|
||||
input_mt_init_slots(input, max_slots, 0);
|
||||
#else
|
||||
input_mt_init_slots(input, max_slots);
|
||||
#endif
|
||||
return input_register_device(input);
|
||||
}
|
||||
|
||||
void cyttsp5_init_function_ptrs(struct cyttsp5_mt_data *md)
|
||||
{
|
||||
md->mt_function.report_slot_liftoff = cyttsp5_report_slot_liftoff;
|
||||
md->mt_function.final_sync = cyttsp5_final_sync;
|
||||
md->mt_function.input_sync = NULL;
|
||||
md->mt_function.input_report = cyttsp5_input_report;
|
||||
md->mt_function.input_register_device = cyttsp5_input_register_device;
|
||||
}
|
||||
|
||||
505
drivers/input/touchscreen/cyttsp5/cyttsp5_platform.c
Normal file
505
drivers/input/touchscreen/cyttsp5/cyttsp5_platform.c
Normal file
@@ -0,0 +1,505 @@
|
||||
/*
|
||||
* cyttsp5_platform.c
|
||||
* Parade TrueTouch(TM) Standard Product V5 Platform Module.
|
||||
* For use with Parade touchscreen controllers.
|
||||
* Supported parts include:
|
||||
* CYTMA5XX
|
||||
* CYTMA448
|
||||
* CYTMA445A
|
||||
* CYTT21XXX
|
||||
* CYTT31XXX
|
||||
*
|
||||
* Copyright (C) 2015 Parade Technologies
|
||||
* Copyright (C) 2013-2015 Cypress Semiconductor
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* Contact Parade Technologies at www.paradetech.com <ttdrivers@paradetech.com>
|
||||
*
|
||||
*/
|
||||
|
||||
#include "cyttsp5_regs.h"
|
||||
#include "cyttsp5_platform.h"
|
||||
|
||||
#ifdef CYTTSP5_PLATFORM_FW_UPGRADE
|
||||
/* FW for Panel ID = 0x00 */
|
||||
#include "cyttsp5_fw_pid00.h"
|
||||
static struct cyttsp5_touch_firmware cyttsp5_firmware_pid00 = {
|
||||
.img = cyttsp4_img_pid00,
|
||||
.size = ARRAY_SIZE(cyttsp4_img_pid00),
|
||||
.ver = cyttsp4_ver_pid00,
|
||||
.vsize = ARRAY_SIZE(cyttsp4_ver_pid00),
|
||||
.panel_id = 0x00,
|
||||
};
|
||||
|
||||
/* FW for Panel ID = 0x01 */
|
||||
#include "cyttsp5_fw_pid01.h"
|
||||
static struct cyttsp5_touch_firmware cyttsp5_firmware_pid01 = {
|
||||
.img = cyttsp4_img_pid01,
|
||||
.size = ARRAY_SIZE(cyttsp4_img_pid01),
|
||||
.ver = cyttsp4_ver_pid01,
|
||||
.vsize = ARRAY_SIZE(cyttsp4_ver_pid01),
|
||||
.panel_id = 0x01,
|
||||
};
|
||||
|
||||
/* FW for Panel ID not enabled (legacy) */
|
||||
#include "cyttsp5_fw.h"
|
||||
static struct cyttsp5_touch_firmware cyttsp5_firmware = {
|
||||
.img = cyttsp4_img,
|
||||
.size = ARRAY_SIZE(cyttsp4_img),
|
||||
.ver = cyttsp4_ver,
|
||||
.vsize = ARRAY_SIZE(cyttsp4_ver),
|
||||
};
|
||||
#else
|
||||
/* FW for Panel ID not enabled (legacy) */
|
||||
static struct cyttsp5_touch_firmware cyttsp5_firmware = {
|
||||
.img = NULL,
|
||||
.size = 0,
|
||||
.ver = NULL,
|
||||
.vsize = 0,
|
||||
};
|
||||
#endif
|
||||
|
||||
#ifdef CYTTSP5_PLATFORM_TTCONFIG_UPGRADE
|
||||
/* TT Config for Panel ID = 0x00 */
|
||||
#include "cyttsp5_params_pid00.h"
|
||||
static struct touch_settings cyttsp5_sett_param_regs_pid00 = {
|
||||
.data = (uint8_t *)&cyttsp4_param_regs_pid00[0],
|
||||
.size = ARRAY_SIZE(cyttsp4_param_regs_pid00),
|
||||
.tag = 0,
|
||||
};
|
||||
|
||||
static struct touch_settings cyttsp5_sett_param_size_pid00 = {
|
||||
.data = (uint8_t *)&cyttsp4_param_size_pid00[0],
|
||||
.size = ARRAY_SIZE(cyttsp4_param_size_pid00),
|
||||
.tag = 0,
|
||||
};
|
||||
|
||||
static struct cyttsp5_touch_config cyttsp5_ttconfig_pid00 = {
|
||||
.param_regs = &cyttsp5_sett_param_regs_pid00,
|
||||
.param_size = &cyttsp5_sett_param_size_pid00,
|
||||
.fw_ver = ttconfig_fw_ver_pid00,
|
||||
.fw_vsize = ARRAY_SIZE(ttconfig_fw_ver_pid00),
|
||||
.panel_id = 0x00,
|
||||
};
|
||||
|
||||
/* TT Config for Panel ID = 0x01 */
|
||||
#include "cyttsp5_params_pid01.h"
|
||||
static struct touch_settings cyttsp5_sett_param_regs_pid01 = {
|
||||
.data = (uint8_t *)&cyttsp4_param_regs_pid01[0],
|
||||
.size = ARRAY_SIZE(cyttsp4_param_regs_pid01),
|
||||
.tag = 0,
|
||||
};
|
||||
|
||||
static struct touch_settings cyttsp5_sett_param_size_pid01 = {
|
||||
.data = (uint8_t *)&cyttsp4_param_size_pid01[0],
|
||||
.size = ARRAY_SIZE(cyttsp4_param_size_pid01),
|
||||
.tag = 0,
|
||||
};
|
||||
|
||||
static struct cyttsp5_touch_config cyttsp5_ttconfig_pid01 = {
|
||||
.param_regs = &cyttsp5_sett_param_regs_pid01,
|
||||
.param_size = &cyttsp5_sett_param_size_pid01,
|
||||
.fw_ver = ttconfig_fw_ver_pid01,
|
||||
.fw_vsize = ARRAY_SIZE(ttconfig_fw_ver_pid01),
|
||||
.panel_id = 0x01,
|
||||
};
|
||||
|
||||
/* TT Config for Panel ID not enabled (legacy)*/
|
||||
#include "cyttsp5_params.h"
|
||||
static struct touch_settings cyttsp5_sett_param_regs = {
|
||||
.data = (uint8_t *)&cyttsp4_param_regs[0],
|
||||
.size = ARRAY_SIZE(cyttsp4_param_regs),
|
||||
.tag = 0,
|
||||
};
|
||||
|
||||
static struct touch_settings cyttsp5_sett_param_size = {
|
||||
.data = (uint8_t *)&cyttsp4_param_size[0],
|
||||
.size = ARRAY_SIZE(cyttsp4_param_size),
|
||||
.tag = 0,
|
||||
};
|
||||
|
||||
static struct cyttsp5_touch_config cyttsp5_ttconfig = {
|
||||
.param_regs = &cyttsp5_sett_param_regs,
|
||||
.param_size = &cyttsp5_sett_param_size,
|
||||
.fw_ver = ttconfig_fw_ver,
|
||||
.fw_vsize = ARRAY_SIZE(ttconfig_fw_ver),
|
||||
};
|
||||
#else
|
||||
/* TT Config for Panel ID not enabled (legacy)*/
|
||||
static struct cyttsp5_touch_config cyttsp5_ttconfig = {
|
||||
.param_regs = NULL,
|
||||
.param_size = NULL,
|
||||
.fw_ver = NULL,
|
||||
.fw_vsize = 0,
|
||||
};
|
||||
#endif
|
||||
|
||||
static struct cyttsp5_touch_firmware *cyttsp5_firmwares[] = {
|
||||
#ifdef CYTTSP5_PLATFORM_FW_UPGRADE
|
||||
&cyttsp5_firmware_pid00,
|
||||
&cyttsp5_firmware_pid01,
|
||||
#endif
|
||||
NULL, /* Last item should always be NULL */
|
||||
};
|
||||
|
||||
static struct cyttsp5_touch_config *cyttsp5_ttconfigs[] = {
|
||||
#ifdef CYTTSP5_PLATFORM_TTCONFIG_UPGRADE
|
||||
&cyttsp5_ttconfig_pid00,
|
||||
&cyttsp5_ttconfig_pid01,
|
||||
#endif
|
||||
NULL, /* Last item should always be NULL */
|
||||
};
|
||||
|
||||
struct cyttsp5_loader_platform_data _cyttsp5_loader_platform_data = {
|
||||
.fw = &cyttsp5_firmware,
|
||||
.ttconfig = &cyttsp5_ttconfig,
|
||||
.fws = cyttsp5_firmwares,
|
||||
.ttconfigs = cyttsp5_ttconfigs,
|
||||
.flags = CY_LOADER_FLAG_NONE,
|
||||
};
|
||||
|
||||
int cyttsp5_xres(struct cyttsp5_core_platform_data *pdata,
|
||||
struct device *dev)
|
||||
{
|
||||
int rst_gpio = pdata->rst_gpio;
|
||||
int rc = 0;
|
||||
|
||||
gpio_set_value(rst_gpio, 1);
|
||||
msleep(3);
|
||||
gpio_set_value(rst_gpio, 0);
|
||||
msleep(1);
|
||||
gpio_set_value(rst_gpio, 1);
|
||||
msleep(5);
|
||||
dev_info(dev,
|
||||
"%s: RESET CYTTSP gpio=%d r=%d\n", __func__,
|
||||
pdata->rst_gpio, rc);
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int cyttsp5_reg_enable(struct device *dev, bool enable)
|
||||
{
|
||||
int rc = 0;
|
||||
struct cyttsp5_core_data *cd = dev_get_drvdata(dev);
|
||||
|
||||
if (!enable) {
|
||||
goto disable_reg;
|
||||
}
|
||||
|
||||
if (cd->avdd_reg) {
|
||||
rc = regulator_enable(cd->avdd_reg);
|
||||
if (rc < 0) {
|
||||
pr_err("%s: Failed to enable pwr regulator\n", __func__);
|
||||
goto avdd_failed;
|
||||
}
|
||||
}
|
||||
|
||||
if (cd->vdd_reg) {
|
||||
rc = regulator_enable(cd->vdd_reg);
|
||||
if (rc < 0) {
|
||||
pr_err("%s: Failed to enable bus regulator\n", __func__);
|
||||
goto vdd_failed;
|
||||
}
|
||||
}
|
||||
|
||||
return rc;
|
||||
|
||||
disable_reg:
|
||||
if (cd->vdd_reg)
|
||||
regulator_disable(cd->vdd_reg);
|
||||
vdd_failed:
|
||||
if (cd->avdd_reg)
|
||||
regulator_disable(cd->avdd_reg);
|
||||
avdd_failed:
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int cyttsp5_reg_init(struct device *dev, bool on)
|
||||
{
|
||||
int rc = 0;
|
||||
struct cyttsp5_core_data *cd = dev_get_drvdata(dev);
|
||||
|
||||
if (!on)
|
||||
goto regulator_put;
|
||||
|
||||
cd->avdd_reg = regulator_get(dev, "avdd");
|
||||
if (IS_ERR(cd->avdd_reg)) {
|
||||
pr_err("%s: Failed to get power regulator\n", __func__);
|
||||
rc = PTR_ERR(cd->avdd_reg);
|
||||
goto regulator_put;
|
||||
}
|
||||
|
||||
cd->vdd_reg = regulator_get(dev, "vdd");
|
||||
if (IS_ERR(cd->vdd_reg)) {
|
||||
pr_err("%s: Failed to get bus pullup regulator\n", __func__);
|
||||
rc = PTR_ERR(cd->vdd_reg);
|
||||
goto regulator_put;
|
||||
}
|
||||
|
||||
rc = cyttsp5_reg_enable(dev, true);
|
||||
if (rc < 0) {
|
||||
pr_err("%s: Failed to enable power!\n", __func__);
|
||||
}
|
||||
|
||||
return rc;
|
||||
|
||||
regulator_put:
|
||||
rc = cyttsp5_reg_enable(dev, false);
|
||||
if (rc < 0) {
|
||||
pr_err("%s: Failed to disable power!\n", __func__);
|
||||
return rc;
|
||||
}
|
||||
|
||||
if (cd->vdd_reg) {
|
||||
regulator_put(cd->vdd_reg);
|
||||
cd->vdd_reg = NULL;
|
||||
}
|
||||
|
||||
if (cd->avdd_reg) {
|
||||
regulator_put(cd->avdd_reg);
|
||||
cd->avdd_reg = NULL;
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int cyttsp5_gpio_init(struct cyttsp5_core_platform_data *pdata, bool enable)
|
||||
{
|
||||
int rc = 0;
|
||||
int rst_gpio = pdata->rst_gpio;
|
||||
int irq_gpio = pdata->irq_gpio;
|
||||
|
||||
if (!enable)
|
||||
goto free_irq_gpio;
|
||||
|
||||
rc = gpio_request(rst_gpio, "cyttsp5_rest_gpio");
|
||||
if (rc < 0) {
|
||||
pr_err("%s: Failed to request reset gpio:%d\n", __func__, rst_gpio);
|
||||
goto fail;
|
||||
}
|
||||
rc = gpio_direction_output(rst_gpio, 0);
|
||||
if (rc < 0) {
|
||||
pr_err("%s: Failed to set gpio %d direction\n", __func__, rst_gpio);
|
||||
goto free_rst_gpio;
|
||||
}
|
||||
|
||||
rc = gpio_request(irq_gpio, "cyttsp5_irq_gpio");
|
||||
if (rc < 0) {
|
||||
pr_err("%s: Failed to request irq gpio:%d\n", __func__, irq_gpio);
|
||||
goto free_rst_gpio;
|
||||
}
|
||||
rc = gpio_direction_input(irq_gpio);
|
||||
if (rc < 0) {
|
||||
pr_err("%s: Failed to set gpio %d direction\n", __func__, irq_gpio);
|
||||
goto free_irq_gpio;
|
||||
}
|
||||
|
||||
return rc;
|
||||
|
||||
free_irq_gpio:
|
||||
gpio_free(irq_gpio);
|
||||
free_rst_gpio:
|
||||
gpio_free(rst_gpio);
|
||||
fail:
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int cyttsp5_pinctrl_init(struct device *dev, bool enable)
|
||||
{
|
||||
int rc = 0;
|
||||
struct cyttsp5_core_data *cd = dev_get_drvdata(dev);
|
||||
|
||||
if (!enable)
|
||||
goto err_pinctrl_lookup;
|
||||
|
||||
cd->ts_pinctrl = devm_pinctrl_get(dev);
|
||||
|
||||
if (IS_ERR_OR_NULL(cd->ts_pinctrl)) {
|
||||
rc = PTR_ERR(cd->ts_pinctrl);
|
||||
dev_err(dev, "Target does not use pinctrl %d\n", rc);
|
||||
goto err_pinctrl_get;
|
||||
}
|
||||
|
||||
cd->pinctrl_state_active =
|
||||
pinctrl_lookup_state(cd->ts_pinctrl, PINCTRL_STATE_ACTIVE);
|
||||
|
||||
if (IS_ERR_OR_NULL(cd->pinctrl_state_active)) {
|
||||
rc = PTR_ERR(cd->pinctrl_state_active);
|
||||
dev_err(dev, "Can not lookup %s pinstate %d\n",
|
||||
PINCTRL_STATE_ACTIVE, rc);
|
||||
goto err_pinctrl_lookup;
|
||||
}
|
||||
|
||||
cd->pinctrl_state_suspend =
|
||||
pinctrl_lookup_state(cd->ts_pinctrl, PINCTRL_STATE_SUSPEND);
|
||||
|
||||
if (IS_ERR_OR_NULL(cd->pinctrl_state_suspend)) {
|
||||
rc = PTR_ERR(cd->pinctrl_state_suspend);
|
||||
dev_err(dev, "Can not lookup %s pinstate %d\n",
|
||||
PINCTRL_STATE_SUSPEND, rc);
|
||||
goto err_pinctrl_lookup;
|
||||
}
|
||||
|
||||
if (cd->ts_pinctrl) {
|
||||
rc = pinctrl_select_state(cd->ts_pinctrl,
|
||||
cd->pinctrl_state_active);
|
||||
if (rc < 0) {
|
||||
dev_err(dev, "%s: Failed to select %s pinstate %d\n",
|
||||
__func__, PINCTRL_STATE_ACTIVE, rc);
|
||||
goto err_pinctrl_lookup;
|
||||
}
|
||||
}
|
||||
return rc;
|
||||
err_pinctrl_lookup:
|
||||
devm_pinctrl_put(cd->ts_pinctrl);
|
||||
err_pinctrl_get:
|
||||
cd->ts_pinctrl = NULL;
|
||||
return rc;
|
||||
}
|
||||
|
||||
int cyttsp5_init(struct cyttsp5_core_platform_data *pdata,
|
||||
int on, struct device *dev)
|
||||
{
|
||||
int rc = 0;
|
||||
if (on) {
|
||||
rc = cyttsp5_pinctrl_init(dev, true);
|
||||
if (rc < 0) {
|
||||
pr_err("%s: Failed to init pinctrl\n", __func__);
|
||||
return rc;
|
||||
}
|
||||
rc = cyttsp5_gpio_init(pdata, true);
|
||||
if (rc < 0) {
|
||||
pr_err("%s: Failed to init gpio\n", __func__);
|
||||
return rc;
|
||||
}
|
||||
rc = cyttsp5_reg_init(dev, true);
|
||||
if (rc < 0) {
|
||||
pr_err("%s: Failed to init regulator\n", __func__);
|
||||
return rc;
|
||||
}
|
||||
pr_info("%s: cyttsp5 pinctrl/gpio/regulator init successful!", __func__);
|
||||
} else {
|
||||
rc = cyttsp5_gpio_init(pdata, false);
|
||||
if (rc < 0) {
|
||||
pr_err("%s: Failed to deinit gpio!\n", __func__);
|
||||
return rc;
|
||||
}
|
||||
|
||||
rc = cyttsp5_pinctrl_init(dev, false);
|
||||
if (rc < 0) {
|
||||
pr_err("%s: Failed to deinit pinctrl!\n", __func__);
|
||||
return rc;
|
||||
}
|
||||
rc = cyttsp5_reg_init(dev, false);
|
||||
if (rc < 0) {
|
||||
pr_err("%s: Failed to deinit regulator!\n", __func__);
|
||||
return rc;
|
||||
}
|
||||
pr_info("%s: cyttsp5 pinctrl/gpio/regulator deinit successful!", __func__);
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int cyttsp5_wakeup(struct cyttsp5_core_platform_data *pdata,
|
||||
struct device *dev, atomic_t *ignore_irq)
|
||||
{
|
||||
int rc = 0;
|
||||
struct cyttsp5_core_data *cd = dev_get_drvdata(dev);
|
||||
|
||||
dev_info(dev, "%s: enable regulator!", __func__);
|
||||
if (cd->ts_pinctrl) {
|
||||
rc = pinctrl_select_state(cd->ts_pinctrl,
|
||||
cd->pinctrl_state_active);
|
||||
if (rc < 0) {
|
||||
dev_err(dev, "%s: Failed to select %s pinstate %d\n",
|
||||
__func__, PINCTRL_STATE_ACTIVE, rc);
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
|
||||
rc = cyttsp5_reg_enable(dev, true);
|
||||
if (rc < 0) {
|
||||
dev_err(dev, "%s: enable regulator failed,r=%d\n", __func__, rc);
|
||||
goto out;
|
||||
}
|
||||
rc = cyttsp5_xres(pdata, dev);
|
||||
if (rc < 0) {
|
||||
dev_err(dev, "%s: reset hw failed,r=%d\n", __func__, rc);
|
||||
goto out;
|
||||
}
|
||||
out:
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int cyttsp5_sleep(struct cyttsp5_core_platform_data *pdata,
|
||||
struct device *dev, atomic_t *ignore_irq)
|
||||
{
|
||||
int rc = 0;
|
||||
struct cyttsp5_core_data *cd = dev_get_drvdata(dev);
|
||||
|
||||
gpio_direction_output(pdata->rst_gpio, 0);
|
||||
dev_info(dev, "%s: disable regulator!", __func__);
|
||||
rc = cyttsp5_reg_enable(dev, false);
|
||||
if (rc < 0)
|
||||
goto out;
|
||||
|
||||
if (cd->ts_pinctrl) {
|
||||
rc = pinctrl_select_state(cd->ts_pinctrl,
|
||||
cd->pinctrl_state_suspend);
|
||||
if (rc < 0) {
|
||||
dev_err(dev, "%s: Failed to select %s pinstate %d\n",
|
||||
__func__, PINCTRL_STATE_SUSPEND, rc);
|
||||
}
|
||||
}
|
||||
out:
|
||||
return rc;
|
||||
}
|
||||
|
||||
int cyttsp5_power(struct cyttsp5_core_platform_data *pdata,
|
||||
int on, struct device *dev, atomic_t *ignore_irq)
|
||||
{
|
||||
if (on)
|
||||
return cyttsp5_wakeup(pdata, dev, ignore_irq);
|
||||
|
||||
return cyttsp5_sleep(pdata, dev, ignore_irq);
|
||||
}
|
||||
|
||||
int cyttsp5_irq_stat(struct cyttsp5_core_platform_data *pdata,
|
||||
struct device *dev)
|
||||
{
|
||||
return gpio_get_value(pdata->irq_gpio);
|
||||
}
|
||||
|
||||
#ifdef CYTTSP5_DETECT_HW
|
||||
int cyttsp5_detect(struct cyttsp5_core_platform_data *pdata,
|
||||
struct device *dev, cyttsp5_platform_read read)
|
||||
{
|
||||
int retry = 3;
|
||||
int rc;
|
||||
char buf[1];
|
||||
|
||||
while (retry--) {
|
||||
/* Perform reset, wait for 100 ms and perform read */
|
||||
parade_debug(dev, DEBUG_LEVEL_2, "%s: Performing a reset\n",
|
||||
__func__);
|
||||
pdata->xres(pdata, dev);
|
||||
msleep(100);
|
||||
rc = read(dev, buf, 1);
|
||||
if (!rc)
|
||||
return 0;
|
||||
|
||||
parade_debug(dev, DEBUG_LEVEL_2, "%s: Read unsuccessful, try=%d\n",
|
||||
__func__, 3 - retry);
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
#endif
|
||||
61
drivers/input/touchscreen/cyttsp5/cyttsp5_platform.h
Normal file
61
drivers/input/touchscreen/cyttsp5/cyttsp5_platform.h
Normal file
@@ -0,0 +1,61 @@
|
||||
/*
|
||||
* cyttsp5_platform.h
|
||||
* Parade TrueTouch(TM) Standard Product V5 Platform Module.
|
||||
* For use with Parade touchscreen controllers.
|
||||
* Supported parts include:
|
||||
* CYTMA5XX
|
||||
* CYTMA448
|
||||
* CYTMA445A
|
||||
* CYTT21XXX
|
||||
* CYTT31XXX
|
||||
*
|
||||
* Copyright (C) 2015 Parade Semiconductor
|
||||
* Copyright (C) 2013-2015 Cypress Semiconductor
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* Contact Parade Semiconductor at www.parade.com <ttdrivers@paradetech.com>
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef _LINUX_CYTTSP5_PLATFORM_H
|
||||
#define _LINUX_CYTTSP5_PLATFORM_H
|
||||
|
||||
#include "cyttsp5_core.h"
|
||||
|
||||
#if defined(CONFIG_TOUCHSCREEN_CYPRESS_CYTTSP5) \
|
||||
|| defined(CONFIG_TOUCHSCREEN_CYPRESS_CYTTSP5_MODULE)
|
||||
extern struct cyttsp5_loader_platform_data _cyttsp5_loader_platform_data;
|
||||
|
||||
int cyttsp5_xres(struct cyttsp5_core_platform_data *pdata, struct device *dev);
|
||||
int cyttsp5_init(struct cyttsp5_core_platform_data *pdata, int on,
|
||||
struct device *dev);
|
||||
int cyttsp5_power(struct cyttsp5_core_platform_data *pdata, int on,
|
||||
struct device *dev, atomic_t *ignore_irq);
|
||||
#define CYTTSP5_DETECT_HW
|
||||
#ifdef CYTTSP5_DETECT_HW
|
||||
int cyttsp5_detect(struct cyttsp5_core_platform_data *pdata,
|
||||
struct device *dev, cyttsp5_platform_read read);
|
||||
#else
|
||||
#define cyttsp5_detect NULL
|
||||
#endif
|
||||
int cyttsp5_irq_stat(struct cyttsp5_core_platform_data *pdata,
|
||||
struct device *dev);
|
||||
#else /* !CONFIG_TOUCHSCREEN_CYPRESS_CYTTSP5 */
|
||||
static struct cyttsp5_loader_platform_data _cyttsp5_loader_platform_data;
|
||||
#define cyttsp5_xres NULL
|
||||
#define cyttsp5_init NULL
|
||||
#define cyttsp5_power NULL
|
||||
#define cyttsp5_irq_stat NULL
|
||||
#define cyttsp5_detect NULL
|
||||
#endif /* CONFIG_TOUCHSCREEN_CYPRESS_CYTTSP5 */
|
||||
|
||||
#endif /* _LINUX_CYTTSP5_PLATFORM_H */
|
||||
555
drivers/input/touchscreen/cyttsp5/cyttsp5_proximity.c
Normal file
555
drivers/input/touchscreen/cyttsp5/cyttsp5_proximity.c
Normal file
@@ -0,0 +1,555 @@
|
||||
/*
|
||||
* cyttsp5_proximity.c
|
||||
* Parade TrueTouch(TM) Standard Product V5 Proximity Module.
|
||||
* For use with Parade touchscreen controllers.
|
||||
* Supported parts include:
|
||||
* CYTMA5XX
|
||||
* CYTMA448
|
||||
* CYTMA445A
|
||||
* CYTT21XXX
|
||||
* CYTT31XXX
|
||||
*
|
||||
* Copyright (C) 2015 Parade Technologies
|
||||
* Copyright (C) 2013-2015 Cypress Semiconductor
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* Contact Parade Technologies at www.paradetech.com <ttdrivers@paradetech.com>
|
||||
*
|
||||
*/
|
||||
|
||||
#include "cyttsp5_regs.h"
|
||||
|
||||
#define CYTTSP5_PROXIMITY_NAME "cyttsp5_proximity"
|
||||
|
||||
/* Timeout value in ms. */
|
||||
#define CYTTSP5_PROXIMITY_REQUEST_EXCLUSIVE_TIMEOUT 1000
|
||||
|
||||
#define CYTTSP5_PROXIMITY_ON 0
|
||||
#define CYTTSP5_PROXIMITY_OFF 1
|
||||
|
||||
static inline struct cyttsp5_proximity_data *get_prox_data(struct device *dev)
|
||||
{
|
||||
struct cyttsp5_core_data *cd = dev_get_drvdata(dev);
|
||||
|
||||
return &cd->pd;
|
||||
}
|
||||
|
||||
static void cyttsp5_report_proximity(struct cyttsp5_proximity_data *pd,
|
||||
bool on)
|
||||
{
|
||||
int val = on ? CYTTSP5_PROXIMITY_ON : CYTTSP5_PROXIMITY_OFF;
|
||||
|
||||
input_report_abs(pd->input, ABS_DISTANCE, val);
|
||||
input_sync(pd->input);
|
||||
}
|
||||
|
||||
static void cyttsp5_get_touch_axis(struct cyttsp5_proximity_data *pd,
|
||||
int *axis, int size, int max, u8 *xy_data, int bofs)
|
||||
{
|
||||
int nbyte;
|
||||
int next;
|
||||
|
||||
for (nbyte = 0, *axis = 0, next = 0; nbyte < size; nbyte++) {
|
||||
parade_debug(pd->dev, DEBUG_LEVEL_2,
|
||||
"%s: *axis=%02X(%d) size=%d max=%08X xy_data=%p xy_data[%d]=%02X(%d) bofs=%d\n",
|
||||
__func__, *axis, *axis, size, max, xy_data, next,
|
||||
xy_data[next], xy_data[next], bofs);
|
||||
*axis = *axis + ((xy_data[next] >> bofs) << (nbyte * 8));
|
||||
next++;
|
||||
}
|
||||
|
||||
*axis &= max - 1;
|
||||
|
||||
parade_debug(pd->dev, DEBUG_LEVEL_2,
|
||||
"%s: *axis=%02X(%d) size=%d max=%08X xy_data=%p xy_data[%d]=%02X(%d)\n",
|
||||
__func__, *axis, *axis, size, max, xy_data, next,
|
||||
xy_data[next], xy_data[next]);
|
||||
}
|
||||
|
||||
static void cyttsp5_get_touch_hdr(struct cyttsp5_proximity_data *pd,
|
||||
struct cyttsp5_touch *touch, u8 *xy_mode)
|
||||
{
|
||||
struct device *dev = pd->dev;
|
||||
struct cyttsp5_sysinfo *si = pd->si;
|
||||
enum cyttsp5_tch_hdr hdr;
|
||||
|
||||
for (hdr = CY_TCH_TIME; hdr < CY_TCH_NUM_HDR; hdr++) {
|
||||
if (!si->tch_hdr[hdr].report)
|
||||
continue;
|
||||
cyttsp5_get_touch_axis(pd, &touch->hdr[hdr],
|
||||
si->tch_hdr[hdr].size,
|
||||
si->tch_hdr[hdr].max,
|
||||
xy_mode + si->tch_hdr[hdr].ofs,
|
||||
si->tch_hdr[hdr].bofs);
|
||||
parade_debug(dev, DEBUG_LEVEL_2, "%s: get %s=%04X(%d)\n",
|
||||
__func__, cyttsp5_tch_hdr_string[hdr],
|
||||
touch->hdr[hdr], touch->hdr[hdr]);
|
||||
}
|
||||
}
|
||||
|
||||
static void cyttsp5_get_touch(struct cyttsp5_proximity_data *pd,
|
||||
struct cyttsp5_touch *touch, u8 *xy_data)
|
||||
{
|
||||
struct device *dev = pd->dev;
|
||||
struct cyttsp5_sysinfo *si = pd->si;
|
||||
enum cyttsp5_tch_abs abs;
|
||||
|
||||
for (abs = CY_TCH_X; abs < CY_TCH_NUM_ABS; abs++) {
|
||||
if (!si->tch_abs[abs].report)
|
||||
continue;
|
||||
cyttsp5_get_touch_axis(pd, &touch->abs[abs],
|
||||
si->tch_abs[abs].size,
|
||||
si->tch_abs[abs].max,
|
||||
xy_data + si->tch_abs[abs].ofs,
|
||||
si->tch_abs[abs].bofs);
|
||||
parade_debug(dev, DEBUG_LEVEL_2, "%s: get %s=%04X(%d)\n",
|
||||
__func__, cyttsp5_tch_abs_string[abs],
|
||||
touch->abs[abs], touch->abs[abs]);
|
||||
}
|
||||
|
||||
parade_debug(dev, DEBUG_LEVEL_2, "%s: x=%04X(%d) y=%04X(%d)\n",
|
||||
__func__, touch->abs[CY_TCH_X], touch->abs[CY_TCH_X],
|
||||
touch->abs[CY_TCH_Y], touch->abs[CY_TCH_Y]);
|
||||
}
|
||||
|
||||
static void cyttsp5_get_proximity_touch(struct cyttsp5_proximity_data *pd,
|
||||
struct cyttsp5_touch *tch, int num_cur_tch)
|
||||
{
|
||||
struct cyttsp5_sysinfo *si = pd->si;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < num_cur_tch; i++) {
|
||||
cyttsp5_get_touch(pd, tch, si->xy_data +
|
||||
(i * si->desc.tch_record_size));
|
||||
|
||||
/* Check for proximity event */
|
||||
if (tch->abs[CY_TCH_O] == CY_OBJ_PROXIMITY) {
|
||||
if (tch->abs[CY_TCH_E] == CY_EV_TOUCHDOWN)
|
||||
cyttsp5_report_proximity(pd, true);
|
||||
else if (tch->abs[CY_TCH_E] == CY_EV_LIFTOFF)
|
||||
cyttsp5_report_proximity(pd, false);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* read xy_data for all current touches */
|
||||
static int cyttsp5_xy_worker(struct cyttsp5_proximity_data *pd)
|
||||
{
|
||||
struct device *dev = pd->dev;
|
||||
struct cyttsp5_sysinfo *si = pd->si;
|
||||
struct cyttsp5_touch tch;
|
||||
u8 num_cur_tch;
|
||||
|
||||
cyttsp5_get_touch_hdr(pd, &tch, si->xy_mode + 3);
|
||||
|
||||
num_cur_tch = tch.hdr[CY_TCH_NUM];
|
||||
if (num_cur_tch > si->sensing_conf_data.max_tch) {
|
||||
dev_err(dev, "%s: Num touch err detected (n=%d)\n",
|
||||
__func__, num_cur_tch);
|
||||
num_cur_tch = si->sensing_conf_data.max_tch;
|
||||
}
|
||||
|
||||
if (tch.hdr[CY_TCH_LO])
|
||||
parade_debug(dev, DEBUG_LEVEL_1, "%s: Large area detected\n",
|
||||
__func__);
|
||||
|
||||
/* extract xy_data for all currently reported touches */
|
||||
parade_debug(dev, DEBUG_LEVEL_2, "%s: extract data num_cur_rec=%d\n",
|
||||
__func__, num_cur_tch);
|
||||
if (num_cur_tch)
|
||||
cyttsp5_get_proximity_touch(pd, &tch, num_cur_tch);
|
||||
else
|
||||
cyttsp5_report_proximity(pd, false);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int cyttsp5_proximity_attention(struct device *dev)
|
||||
{
|
||||
struct cyttsp5_proximity_data *pd = get_prox_data(dev);
|
||||
int rc = 0;
|
||||
|
||||
if (pd->si->xy_mode[2] != pd->si->desc.tch_report_id)
|
||||
return 0;
|
||||
|
||||
mutex_lock(&pd->prox_lock);
|
||||
rc = cyttsp5_xy_worker(pd);
|
||||
mutex_unlock(&pd->prox_lock);
|
||||
if (rc < 0)
|
||||
dev_err(dev, "%s: xy_worker error r=%d\n", __func__, rc);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int cyttsp5_startup_attention(struct device *dev)
|
||||
{
|
||||
struct cyttsp5_proximity_data *pd = get_prox_data(dev);
|
||||
|
||||
mutex_lock(&pd->prox_lock);
|
||||
cyttsp5_report_proximity(pd, false);
|
||||
mutex_unlock(&pd->prox_lock);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int _cyttsp5_set_proximity_via_touchmode_enabled(
|
||||
struct cyttsp5_proximity_data *pd, bool enable)
|
||||
{
|
||||
struct device *dev = pd->dev;
|
||||
u32 touchmode_enabled;
|
||||
int rc;
|
||||
|
||||
rc = cyttsp5_request_nonhid_get_param(dev, 0,
|
||||
CY_RAM_ID_TOUCHMODE_ENABLED, &touchmode_enabled);
|
||||
if (rc)
|
||||
return rc;
|
||||
|
||||
if (enable)
|
||||
touchmode_enabled |= 0x80;
|
||||
else
|
||||
touchmode_enabled &= 0x7F;
|
||||
|
||||
rc = cyttsp5_request_nonhid_set_param(dev, 0,
|
||||
CY_RAM_ID_TOUCHMODE_ENABLED, touchmode_enabled,
|
||||
CY_RAM_ID_TOUCHMODE_ENABLED_SIZE);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int _cyttsp5_set_proximity_via_proximity_enable(
|
||||
struct cyttsp5_proximity_data *pd, bool enable)
|
||||
{
|
||||
struct device *dev = pd->dev;
|
||||
u32 proximity_enable;
|
||||
int rc;
|
||||
|
||||
rc = cyttsp5_request_nonhid_get_param(dev, 0,
|
||||
CY_RAM_ID_PROXIMITY_ENABLE, &proximity_enable);
|
||||
if (rc)
|
||||
return rc;
|
||||
|
||||
if (enable)
|
||||
proximity_enable |= 0x01;
|
||||
else
|
||||
proximity_enable &= 0xFE;
|
||||
|
||||
rc = cyttsp5_request_nonhid_set_param(dev, 0,
|
||||
CY_RAM_ID_PROXIMITY_ENABLE, proximity_enable,
|
||||
CY_RAM_ID_PROXIMITY_ENABLE_SIZE);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int _cyttsp5_set_proximity(struct cyttsp5_proximity_data *pd,
|
||||
bool enable)
|
||||
{
|
||||
if (!IS_PIP_VER_GE(pd->si, 1, 4))
|
||||
return _cyttsp5_set_proximity_via_touchmode_enabled(pd,
|
||||
enable);
|
||||
|
||||
return _cyttsp5_set_proximity_via_proximity_enable(pd, enable);
|
||||
}
|
||||
|
||||
static int _cyttsp5_proximity_enable(struct cyttsp5_proximity_data *pd)
|
||||
{
|
||||
struct device *dev = pd->dev;
|
||||
int rc = 0;
|
||||
|
||||
pm_runtime_get_sync(dev);
|
||||
|
||||
rc = cyttsp5_request_exclusive(dev,
|
||||
CYTTSP5_PROXIMITY_REQUEST_EXCLUSIVE_TIMEOUT);
|
||||
if (rc < 0) {
|
||||
dev_err(dev, "%s: Error on request exclusive r=%d\n",
|
||||
__func__, rc);
|
||||
goto exit;
|
||||
}
|
||||
|
||||
rc = _cyttsp5_set_proximity(pd, true);
|
||||
if (rc < 0) {
|
||||
dev_err(dev, "%s: Error on request enable proximity scantype r=%d\n",
|
||||
__func__, rc);
|
||||
goto exit_release;
|
||||
}
|
||||
|
||||
parade_debug(dev, DEBUG_LEVEL_2, "%s: setup subscriptions\n", __func__);
|
||||
|
||||
/* set up touch call back */
|
||||
_cyttsp5_subscribe_attention(dev, CY_ATTEN_IRQ, CYTTSP5_PROXIMITY_NAME,
|
||||
cyttsp5_proximity_attention, CY_MODE_OPERATIONAL);
|
||||
|
||||
/* set up startup call back */
|
||||
_cyttsp5_subscribe_attention(dev, CY_ATTEN_STARTUP,
|
||||
CYTTSP5_PROXIMITY_NAME, cyttsp5_startup_attention, 0);
|
||||
|
||||
exit_release:
|
||||
cyttsp5_release_exclusive(dev);
|
||||
exit:
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int _cyttsp5_proximity_disable(struct cyttsp5_proximity_data *pd,
|
||||
bool force)
|
||||
{
|
||||
struct device *dev = pd->dev;
|
||||
int rc = 0;
|
||||
|
||||
rc = cyttsp5_request_exclusive(dev,
|
||||
CYTTSP5_PROXIMITY_REQUEST_EXCLUSIVE_TIMEOUT);
|
||||
if (rc < 0) {
|
||||
dev_err(dev, "%s: Error on request exclusive r=%d\n",
|
||||
__func__, rc);
|
||||
goto exit;
|
||||
}
|
||||
|
||||
rc = _cyttsp5_set_proximity(pd, false);
|
||||
if (rc < 0) {
|
||||
dev_err(dev, "%s: Error on request disable proximity scan r=%d\n",
|
||||
__func__, rc);
|
||||
goto exit_release;
|
||||
}
|
||||
|
||||
exit_release:
|
||||
cyttsp5_release_exclusive(dev);
|
||||
|
||||
exit:
|
||||
if (!rc || force) {
|
||||
_cyttsp5_unsubscribe_attention(dev, CY_ATTEN_IRQ,
|
||||
CYTTSP5_PROXIMITY_NAME, cyttsp5_proximity_attention,
|
||||
CY_MODE_OPERATIONAL);
|
||||
|
||||
_cyttsp5_unsubscribe_attention(dev, CY_ATTEN_STARTUP,
|
||||
CYTTSP5_PROXIMITY_NAME, cyttsp5_startup_attention, 0);
|
||||
}
|
||||
|
||||
pm_runtime_put(dev);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
static ssize_t cyttsp5_proximity_enable_show(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
struct cyttsp5_proximity_data *pd = get_prox_data(dev);
|
||||
int val = 0;
|
||||
|
||||
mutex_lock(&pd->sysfs_lock);
|
||||
val = pd->enable_count;
|
||||
mutex_unlock(&pd->sysfs_lock);
|
||||
|
||||
return scnprintf(buf, CY_MAX_PRBUF_SIZE, "%d\n", val);
|
||||
}
|
||||
|
||||
static ssize_t cyttsp5_proximity_enable_store(struct device *dev,
|
||||
struct device_attribute *attr, const char *buf, size_t size)
|
||||
{
|
||||
struct cyttsp5_proximity_data *pd = get_prox_data(dev);
|
||||
unsigned long value;
|
||||
int rc;
|
||||
|
||||
rc = kstrtoul(buf, 10, &value);
|
||||
if (rc < 0 || (value != 0 && value != 1)) {
|
||||
dev_err(dev, "%s: Invalid value\n", __func__);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
mutex_lock(&pd->sysfs_lock);
|
||||
if (value) {
|
||||
if (pd->enable_count++) {
|
||||
parade_debug(dev, DEBUG_LEVEL_2, "%s: '%s' already enabled\n",
|
||||
__func__, pd->input->name);
|
||||
} else {
|
||||
rc = _cyttsp5_proximity_enable(pd);
|
||||
if (rc)
|
||||
pd->enable_count--;
|
||||
}
|
||||
} else {
|
||||
if (--pd->enable_count) {
|
||||
if (pd->enable_count < 0) {
|
||||
dev_err(dev, "%s: '%s' unbalanced disable\n",
|
||||
__func__, pd->input->name);
|
||||
pd->enable_count = 0;
|
||||
}
|
||||
} else {
|
||||
rc = _cyttsp5_proximity_disable(pd, false);
|
||||
if (rc)
|
||||
pd->enable_count++;
|
||||
}
|
||||
}
|
||||
mutex_unlock(&pd->sysfs_lock);
|
||||
|
||||
if (rc)
|
||||
return rc;
|
||||
|
||||
return size;
|
||||
}
|
||||
|
||||
static DEVICE_ATTR(prox_enable, S_IRUSR | S_IWUSR,
|
||||
cyttsp5_proximity_enable_show,
|
||||
cyttsp5_proximity_enable_store);
|
||||
|
||||
static int cyttsp5_setup_input_device_and_sysfs(struct device *dev)
|
||||
{
|
||||
struct cyttsp5_proximity_data *pd = get_prox_data(dev);
|
||||
int signal = CY_IGNORE_VALUE;
|
||||
int i;
|
||||
int rc;
|
||||
|
||||
rc = device_create_file(dev, &dev_attr_prox_enable);
|
||||
if (rc) {
|
||||
dev_err(dev, "%s: Error, could not create enable\n",
|
||||
__func__);
|
||||
goto exit;
|
||||
}
|
||||
|
||||
parade_debug(dev, DEBUG_LEVEL_2, "%s: Initialize event signals\n",
|
||||
__func__);
|
||||
|
||||
__set_bit(EV_ABS, pd->input->evbit);
|
||||
|
||||
/* set event signal capabilities */
|
||||
for (i = 0; i < NUM_SIGNALS(pd->pdata->frmwrk); i++) {
|
||||
signal = PARAM_SIGNAL(pd->pdata->frmwrk, i);
|
||||
if (signal != CY_IGNORE_VALUE) {
|
||||
input_set_abs_params(pd->input, signal,
|
||||
PARAM_MIN(pd->pdata->frmwrk, i),
|
||||
PARAM_MAX(pd->pdata->frmwrk, i),
|
||||
PARAM_FUZZ(pd->pdata->frmwrk, i),
|
||||
PARAM_FLAT(pd->pdata->frmwrk, i));
|
||||
}
|
||||
}
|
||||
|
||||
rc = input_register_device(pd->input);
|
||||
if (rc) {
|
||||
dev_err(dev, "%s: Error, failed register input device r=%d\n",
|
||||
__func__, rc);
|
||||
goto unregister_enable;
|
||||
}
|
||||
|
||||
pd->input_device_registered = true;
|
||||
return rc;
|
||||
|
||||
unregister_enable:
|
||||
device_remove_file(dev, &dev_attr_prox_enable);
|
||||
exit:
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int cyttsp5_setup_input_attention(struct device *dev)
|
||||
{
|
||||
struct cyttsp5_proximity_data *pd = get_prox_data(dev);
|
||||
int rc;
|
||||
|
||||
pd->si = _cyttsp5_request_sysinfo(dev);
|
||||
if (!pd->si)
|
||||
return -EINVAL;
|
||||
|
||||
rc = cyttsp5_setup_input_device_and_sysfs(dev);
|
||||
if (!rc)
|
||||
rc = _cyttsp5_set_proximity(pd, false);
|
||||
|
||||
_cyttsp5_unsubscribe_attention(dev, CY_ATTEN_STARTUP,
|
||||
CYTTSP5_PROXIMITY_NAME, cyttsp5_setup_input_attention, 0);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
int cyttsp5_proximity_probe(struct device *dev)
|
||||
{
|
||||
struct cyttsp5_core_data *cd = dev_get_drvdata(dev);
|
||||
struct cyttsp5_proximity_data *pd = &cd->pd;
|
||||
struct cyttsp5_platform_data *pdata = dev_get_platdata(dev);
|
||||
struct cyttsp5_proximity_platform_data *prox_pdata;
|
||||
int rc = 0;
|
||||
|
||||
if (!pdata || !pdata->prox_pdata) {
|
||||
dev_err(dev, "%s: Missing platform data\n", __func__);
|
||||
rc = -ENODEV;
|
||||
goto error_no_pdata;
|
||||
}
|
||||
prox_pdata = pdata->prox_pdata;
|
||||
|
||||
mutex_init(&pd->prox_lock);
|
||||
mutex_init(&pd->sysfs_lock);
|
||||
pd->dev = dev;
|
||||
pd->pdata = prox_pdata;
|
||||
|
||||
/* Create the input device and register it. */
|
||||
parade_debug(dev, DEBUG_LEVEL_2,
|
||||
"%s: Create the input device and register it\n", __func__);
|
||||
pd->input = input_allocate_device();
|
||||
if (!pd->input) {
|
||||
dev_err(dev, "%s: Error, failed to allocate input device\n",
|
||||
__func__);
|
||||
rc = -ENODEV;
|
||||
goto error_alloc_failed;
|
||||
}
|
||||
|
||||
if (pd->pdata->inp_dev_name)
|
||||
pd->input->name = pd->pdata->inp_dev_name;
|
||||
else
|
||||
pd->input->name = CYTTSP5_PROXIMITY_NAME;
|
||||
scnprintf(pd->phys, sizeof(pd->phys), "%s/input%d", dev_name(dev),
|
||||
cd->phys_num++);
|
||||
pd->input->phys = pd->phys;
|
||||
pd->input->dev.parent = pd->dev;
|
||||
input_set_drvdata(pd->input, pd);
|
||||
|
||||
/* get sysinfo */
|
||||
pd->si = _cyttsp5_request_sysinfo(dev);
|
||||
|
||||
if (pd->si) {
|
||||
rc = cyttsp5_setup_input_device_and_sysfs(dev);
|
||||
if (rc)
|
||||
goto error_init_input;
|
||||
|
||||
rc = _cyttsp5_set_proximity(pd, false);
|
||||
} else {
|
||||
dev_err(dev, "%s: Fail get sysinfo pointer from core p=%p\n",
|
||||
__func__, pd->si);
|
||||
_cyttsp5_subscribe_attention(dev, CY_ATTEN_STARTUP,
|
||||
CYTTSP5_PROXIMITY_NAME, cyttsp5_setup_input_attention,
|
||||
0);
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
error_init_input:
|
||||
input_free_device(pd->input);
|
||||
error_alloc_failed:
|
||||
error_no_pdata:
|
||||
dev_err(dev, "%s failed.\n", __func__);
|
||||
return rc;
|
||||
}
|
||||
|
||||
int cyttsp5_proximity_release(struct device *dev)
|
||||
{
|
||||
struct cyttsp5_proximity_data *pd = get_prox_data(dev);
|
||||
|
||||
if (pd->input_device_registered) {
|
||||
/* Disable proximity sensing */
|
||||
mutex_lock(&pd->sysfs_lock);
|
||||
if (pd->enable_count)
|
||||
_cyttsp5_proximity_disable(pd, true);
|
||||
mutex_unlock(&pd->sysfs_lock);
|
||||
device_remove_file(dev, &dev_attr_prox_enable);
|
||||
input_unregister_device(pd->input);
|
||||
} else {
|
||||
input_free_device(pd->input);
|
||||
_cyttsp5_unsubscribe_attention(dev, CY_ATTEN_STARTUP,
|
||||
CYTTSP5_PROXIMITY_NAME, cyttsp5_setup_input_attention,
|
||||
0);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
1228
drivers/input/touchscreen/cyttsp5/cyttsp5_regs.h
Normal file
1228
drivers/input/touchscreen/cyttsp5/cyttsp5_regs.h
Normal file
File diff suppressed because it is too large
Load Diff
255
drivers/input/touchscreen/cyttsp5/cyttsp5_spi.c
Normal file
255
drivers/input/touchscreen/cyttsp5/cyttsp5_spi.c
Normal file
@@ -0,0 +1,255 @@
|
||||
/*
|
||||
* cyttsp5_spi.c
|
||||
* Parade TrueTouch(TM) Standard Product V5 SPI Module.
|
||||
* For use with Parade touchscreen controllers.
|
||||
* Supported parts include:
|
||||
* CYTMA5XX
|
||||
* CYTMA448
|
||||
* CYTMA445A
|
||||
* CYTT21XXX
|
||||
* CYTT31XXX
|
||||
*
|
||||
* Copyright (C) 2015 Parade Technologies
|
||||
* Copyright (C) 2012-2015 Cypress Semiconductor
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* Contact Parade Technologies at www.paradetech.com <ttdrivers@paradetech.com>
|
||||
*
|
||||
*/
|
||||
|
||||
#include "cyttsp5_regs.h"
|
||||
|
||||
#include <linux/spi/spi.h>
|
||||
#include <linux/version.h>
|
||||
|
||||
#define CY_SPI_WR_OP 0x00 /* r/~w */
|
||||
#define CY_SPI_RD_OP 0x01
|
||||
#define CY_SPI_BITS_PER_WORD 8
|
||||
#define CY_SPI_SYNC_ACK 0x62
|
||||
|
||||
#define CY_SPI_CMD_BYTES 0
|
||||
#define CY_SPI_DATA_SIZE (2 * 256)
|
||||
#define CY_SPI_DATA_BUF_SIZE (CY_SPI_CMD_BYTES + CY_SPI_DATA_SIZE)
|
||||
|
||||
static void cyttsp5_spi_add_rw_msg(struct spi_message *msg,
|
||||
struct spi_transfer *xfer, u8 *w_header, u8 *r_header, u8 op)
|
||||
{
|
||||
xfer->tx_buf = w_header;
|
||||
xfer->rx_buf = r_header;
|
||||
w_header[0] = op;
|
||||
xfer->len = 1;
|
||||
spi_message_add_tail(xfer, msg);
|
||||
}
|
||||
|
||||
static int cyttsp5_spi_xfer(struct device *dev, u8 op, u8 *buf, int length)
|
||||
{
|
||||
struct spi_device *spi = to_spi_device(dev);
|
||||
struct spi_message msg;
|
||||
struct spi_transfer xfer[2];
|
||||
u8 w_header[2];
|
||||
u8 r_header[2];
|
||||
int rc;
|
||||
|
||||
memset(xfer, 0, sizeof(xfer));
|
||||
|
||||
spi_message_init(&msg);
|
||||
cyttsp5_spi_add_rw_msg(&msg, &xfer[0], w_header, r_header, op);
|
||||
|
||||
switch (op) {
|
||||
case CY_SPI_RD_OP:
|
||||
xfer[1].rx_buf = buf;
|
||||
xfer[1].len = length;
|
||||
spi_message_add_tail(&xfer[1], &msg);
|
||||
break;
|
||||
case CY_SPI_WR_OP:
|
||||
xfer[1].tx_buf = buf;
|
||||
xfer[1].len = length;
|
||||
spi_message_add_tail(&xfer[1], &msg);
|
||||
break;
|
||||
default:
|
||||
rc = -EIO;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
rc = spi_sync(spi, &msg);
|
||||
exit:
|
||||
if (rc < 0)
|
||||
parade_debug(dev, DEBUG_LEVEL_2, "%s: spi_sync() error %d\n",
|
||||
__func__, rc);
|
||||
|
||||
if (r_header[0] != CY_SPI_SYNC_ACK)
|
||||
return -EIO;
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int cyttsp5_spi_read_default(struct device *dev, void *buf, int size)
|
||||
{
|
||||
if (!buf || !size)
|
||||
return 0;
|
||||
|
||||
return cyttsp5_spi_xfer(dev, CY_SPI_RD_OP, buf, size);
|
||||
}
|
||||
|
||||
static int cyttsp5_spi_read_default_nosize(struct device *dev, u8 *buf, u32 max)
|
||||
{
|
||||
u32 size;
|
||||
int rc;
|
||||
|
||||
if (!buf)
|
||||
return 0;
|
||||
|
||||
rc = cyttsp5_spi_xfer(dev, CY_SPI_RD_OP, buf, 2);
|
||||
if (rc < 0)
|
||||
return rc;
|
||||
|
||||
size = get_unaligned_le16(&buf[0]);
|
||||
if (!size)
|
||||
return rc;
|
||||
|
||||
if (size > max)
|
||||
return -EINVAL;
|
||||
|
||||
return cyttsp5_spi_read_default(dev, buf, size);
|
||||
}
|
||||
|
||||
static int cyttsp5_spi_write_read_specific(struct device *dev, u8 write_len,
|
||||
u8 *write_buf, u8 *read_buf)
|
||||
{
|
||||
int rc;
|
||||
|
||||
rc = cyttsp5_spi_xfer(dev, CY_SPI_WR_OP, write_buf, write_len);
|
||||
if (rc < 0)
|
||||
return rc;
|
||||
|
||||
if (read_buf)
|
||||
rc = cyttsp5_spi_read_default_nosize(dev, read_buf,
|
||||
CY_SPI_DATA_SIZE);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
static struct cyttsp5_bus_ops cyttsp5_spi_bus_ops = {
|
||||
.bustype = BUS_SPI,
|
||||
.read_default = cyttsp5_spi_read_default,
|
||||
.read_default_nosize = cyttsp5_spi_read_default_nosize,
|
||||
.write_read_specific = cyttsp5_spi_write_read_specific,
|
||||
};
|
||||
|
||||
#ifdef CYTTSP5_DEVICETREE_SUPPORT
|
||||
static const struct of_device_id cyttsp5_spi_of_match[] = {
|
||||
{ .compatible = "cy,cyttsp5_spi_adapter", },
|
||||
{ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, cyttsp5_spi_of_match);
|
||||
#endif
|
||||
|
||||
static int cyttsp5_spi_probe(struct spi_device *spi)
|
||||
{
|
||||
struct device *dev = &spi->dev;
|
||||
#ifdef CYTTSP5_DEVICETREE_SUPPORT
|
||||
const struct of_device_id *match;
|
||||
#endif
|
||||
int rc;
|
||||
|
||||
/* Set up SPI*/
|
||||
spi->bits_per_word = CY_SPI_BITS_PER_WORD;
|
||||
spi->mode = SPI_MODE_0;
|
||||
rc = spi_setup(spi);
|
||||
if (rc < 0) {
|
||||
dev_err(dev, "%s: SPI setup error %d\n", __func__, rc);
|
||||
return rc;
|
||||
}
|
||||
|
||||
#ifdef CYTTSP5_DEVICETREE_SUPPORT
|
||||
match = of_match_device(of_match_ptr(cyttsp5_spi_of_match), dev);
|
||||
if (match) {
|
||||
rc = cyttsp5_devtree_create_and_get_pdata(dev);
|
||||
if (rc < 0)
|
||||
return rc;
|
||||
}
|
||||
#endif
|
||||
|
||||
rc = cyttsp5_probe(&cyttsp5_spi_bus_ops, &spi->dev, spi->irq,
|
||||
CY_SPI_DATA_BUF_SIZE);
|
||||
|
||||
#ifdef CYTTSP5_DEVICETREE_SUPPORT
|
||||
if (rc && match)
|
||||
cyttsp5_devtree_clean_pdata(dev);
|
||||
#endif
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int cyttsp5_spi_remove(struct spi_device *spi)
|
||||
{
|
||||
#ifdef CYTTSP5_DEVICETREE_SUPPORT
|
||||
struct device *dev = &spi->dev;
|
||||
const struct of_device_id *match;
|
||||
#endif
|
||||
struct cyttsp5_core_data *cd = dev_get_drvdata(&spi->dev);
|
||||
|
||||
cyttsp5_release(cd);
|
||||
|
||||
#ifdef CYTTSP5_DEVICETREE_SUPPORT
|
||||
match = of_match_device(of_match_ptr(cyttsp5_spi_of_match), dev);
|
||||
if (match)
|
||||
cyttsp5_devtree_clean_pdata(dev);
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct spi_device_id cyttsp5_spi_id[] = {
|
||||
{ CYTTSP5_SPI_NAME, 0 },
|
||||
{ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(spi, cyttsp5_spi_id);
|
||||
|
||||
static struct spi_driver cyttsp5_spi_driver = {
|
||||
.driver = {
|
||||
.name = CYTTSP5_SPI_NAME,
|
||||
.bus = &spi_bus_type,
|
||||
.owner = THIS_MODULE,
|
||||
.pm = &cyttsp5_pm_ops,
|
||||
#ifdef CYTTSP5_DEVICETREE_SUPPORT
|
||||
.of_match_table = cyttsp5_spi_of_match,
|
||||
#endif
|
||||
},
|
||||
.probe = cyttsp5_spi_probe,
|
||||
.remove = (cyttsp5_spi_remove),
|
||||
.id_table = cyttsp5_spi_id,
|
||||
};
|
||||
|
||||
#if (KERNEL_VERSION(3, 3, 0) <= LINUX_VERSION_CODE)
|
||||
module_spi_driver(cyttsp5_spi_driver);
|
||||
#else
|
||||
static int __init cyttsp5_spi_init(void)
|
||||
{
|
||||
int err = spi_register_driver(&cyttsp5_spi_driver);
|
||||
|
||||
pr_info("%s: Parade TTSP SPI Driver (Built %s) rc=%d\n",
|
||||
__func__, CY_DRIVER_VERSION, err);
|
||||
return err;
|
||||
}
|
||||
module_init(cyttsp5_spi_init);
|
||||
|
||||
static void __exit cyttsp5_spi_exit(void)
|
||||
{
|
||||
spi_unregister_driver(&cyttsp5_spi_driver);
|
||||
}
|
||||
module_exit(cyttsp5_spi_exit);
|
||||
#endif
|
||||
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_DESCRIPTION("Parade TrueTouch(R) Standard Product SPI Driver");
|
||||
MODULE_AUTHOR("Parade Technologies <ttdrivers@paradetech.com>");
|
||||
@@ -0,0 +1,442 @@
|
||||
/*
|
||||
* cyttsp5_test_device_access_api.c
|
||||
* Parade TrueTouch(TM) Standard Product V5 Device Access API test module.
|
||||
* For use with Parade touchscreen controllers.
|
||||
* Supported parts include:
|
||||
* CYTMA5XX
|
||||
* CYTMA448
|
||||
* CYTMA445A
|
||||
* CYTT21XXX
|
||||
* CYTT31XXX
|
||||
*
|
||||
* Copyright (C) 2015 Parade Technologies
|
||||
* Copyright (C) 2012-2015 Cypress Semiconductor
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* Contact Parade Technologies at www.paradetech.com <ttdrivers@paradetech.com>
|
||||
*
|
||||
*/
|
||||
|
||||
#include <linux/module.h>
|
||||
#include "cyttsp5_device_access-api.h"
|
||||
#include <asm/unaligned.h>
|
||||
|
||||
#define BUFFER_SIZE 256
|
||||
|
||||
#define COMMAND_GET_SYSTEM_INFO 2
|
||||
#define COMMAND_SUSPEND_SCANNING 3
|
||||
#define COMMAND_RESUME_SCANNING 4
|
||||
#define COMMAND_GET_PARAMETER 5
|
||||
#define COMMAND_SET_PARAMETER 6
|
||||
|
||||
#define PARAMETER_ACTIVE_DISTANCE_2 0x0B
|
||||
|
||||
struct tt_output_report {
|
||||
__le16 reg_address;
|
||||
__le16 length;
|
||||
u8 report_id;
|
||||
u8 reserved;
|
||||
u8 command;
|
||||
u8 parameters[0];
|
||||
} __packed;
|
||||
|
||||
struct tt_input_report {
|
||||
__le16 length;
|
||||
u8 report_id;
|
||||
u8 reserved;
|
||||
u8 command;
|
||||
u8 return_data[0];
|
||||
} __packed;
|
||||
|
||||
static int prepare_tt_output_report(struct tt_output_report *out,
|
||||
u16 length, u8 command)
|
||||
{
|
||||
put_unaligned_le16(0x04, &out->reg_address);
|
||||
put_unaligned_le16(5 + length, &out->length);
|
||||
|
||||
out->report_id = 0x2f;
|
||||
out->reserved = 0x00;
|
||||
out->command = command;
|
||||
|
||||
return 7 + length;
|
||||
}
|
||||
|
||||
static int check_and_parse_tt_input_report(struct tt_input_report *in,
|
||||
u16 *length, u8 *command)
|
||||
{
|
||||
if (in->report_id != 0x1f)
|
||||
return -EINVAL;
|
||||
|
||||
*length = get_unaligned_le16(&in->length);
|
||||
*command = in->command & 0x7f;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int prepare_get_system_info_report(u8 *buf)
|
||||
{
|
||||
struct tt_output_report *out = (struct tt_output_report *)buf;
|
||||
|
||||
return prepare_tt_output_report(out, 0, COMMAND_GET_SYSTEM_INFO);
|
||||
}
|
||||
|
||||
static int check_get_system_info_response(u8 *buf, u16 read_length)
|
||||
{
|
||||
struct tt_input_report *in = (struct tt_input_report *)buf;
|
||||
u16 length = 0;
|
||||
u8 command = 0;
|
||||
|
||||
if (read_length != 51)
|
||||
return -EINVAL;
|
||||
|
||||
if (check_and_parse_tt_input_report(in, &length, &command)
|
||||
|| command != COMMAND_GET_SYSTEM_INFO
|
||||
|| length != 51)
|
||||
return -EINVAL;
|
||||
|
||||
pr_info("PIP Major Version: %d\n", in->return_data[0]);
|
||||
pr_info("PIP Minor Version: %d\n", in->return_data[1]);
|
||||
pr_info("Touch Firmware Product Id: %d\n",
|
||||
get_unaligned_le16(&in->return_data[2]));
|
||||
pr_info("Touch Firmware Major Version: %d\n", in->return_data[4]);
|
||||
pr_info("Touch Firmware Minor Version: %d\n", in->return_data[5]);
|
||||
pr_info("Touch Firmware Internal Revision Control Number: %d\n",
|
||||
get_unaligned_le32(&in->return_data[6]));
|
||||
pr_info("Customer Specified Firmware/Configuration Version: %d\n",
|
||||
get_unaligned_le16(&in->return_data[10]));
|
||||
pr_info("Bootloader Major Version: %d\n", in->return_data[12]);
|
||||
pr_info("Bootloader Minor Version: %d\n", in->return_data[13]);
|
||||
pr_info("Family ID: 0x%02x\n", in->return_data[14]);
|
||||
pr_info("Revision ID: 0x%02x\n", in->return_data[15]);
|
||||
pr_info("Silicon ID: 0x%02x\n",
|
||||
get_unaligned_le16(&in->return_data[16]));
|
||||
pr_info("Parade Manufacturing ID[0]: 0x%02x\n", in->return_data[18]);
|
||||
pr_info("Parade Manufacturing ID[1]: 0x%02x\n", in->return_data[19]);
|
||||
pr_info("Parade Manufacturing ID[2]: 0x%02x\n", in->return_data[20]);
|
||||
pr_info("Parade Manufacturing ID[3]: 0x%02x\n", in->return_data[21]);
|
||||
pr_info("Parade Manufacturing ID[4]: 0x%02x\n", in->return_data[22]);
|
||||
pr_info("Parade Manufacturing ID[5]: 0x%02x\n", in->return_data[23]);
|
||||
pr_info("Parade Manufacturing ID[6]: 0x%02x\n", in->return_data[24]);
|
||||
pr_info("Parade Manufacturing ID[7]: 0x%02x\n", in->return_data[25]);
|
||||
pr_info("POST Result Code: 0x%02x\n",
|
||||
get_unaligned_le16(&in->return_data[26]));
|
||||
|
||||
pr_info("Number of X Electrodes: %d\n", in->return_data[28]);
|
||||
pr_info("Number of Y Electrodes: %d\n", in->return_data[29]);
|
||||
pr_info("Panel X Axis Length: %d\n",
|
||||
get_unaligned_le16(&in->return_data[30]));
|
||||
pr_info("Panel Y Axis Length: %d\n",
|
||||
get_unaligned_le16(&in->return_data[32]));
|
||||
pr_info("Panel X Axis Resolution: %d\n",
|
||||
get_unaligned_le16(&in->return_data[34]));
|
||||
pr_info("Panel Y Axis Resolution: %d\n",
|
||||
get_unaligned_le16(&in->return_data[36]));
|
||||
pr_info("Panel Pressure Resolution: %d\n",
|
||||
get_unaligned_le16(&in->return_data[38]));
|
||||
pr_info("X_ORG: %d\n", in->return_data[40]);
|
||||
pr_info("Y_ORG: %d\n", in->return_data[41]);
|
||||
pr_info("Panel ID: %d\n", in->return_data[42]);
|
||||
pr_info("Buttons: 0x%02x\n", in->return_data[43]);
|
||||
pr_info("BAL SELF MC: 0x%02x\n", in->return_data[44]);
|
||||
pr_info("Max Number of Touch Records per Refresh Cycle: %d\n",
|
||||
in->return_data[45]);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int prepare_get_parameter_report(u8 *buf, u8 parameter_id)
|
||||
{
|
||||
struct tt_output_report *out = (struct tt_output_report *)buf;
|
||||
|
||||
out->parameters[0] = parameter_id;
|
||||
|
||||
return prepare_tt_output_report(out, 1, COMMAND_GET_PARAMETER);
|
||||
}
|
||||
|
||||
static int check_get_parameter_response(u8 *buf, u16 read_length,
|
||||
u32 *parameter_value)
|
||||
{
|
||||
struct tt_input_report *in = (struct tt_input_report *)buf;
|
||||
u16 length = 0;
|
||||
u8 command = 0;
|
||||
u32 param_value = 0;
|
||||
u8 param_id;
|
||||
u8 param_size = 0;
|
||||
|
||||
if (read_length != 8 && read_length != 9 && read_length != 11)
|
||||
return -EINVAL;
|
||||
|
||||
if (check_and_parse_tt_input_report(in, &length, &command)
|
||||
|| command != COMMAND_GET_PARAMETER
|
||||
|| (length != 8 && length != 9 && length != 11))
|
||||
return -EINVAL;
|
||||
|
||||
param_id = in->return_data[0];
|
||||
|
||||
param_size = in->return_data[1];
|
||||
|
||||
if (param_size == 1)
|
||||
param_value = in->return_data[2];
|
||||
else if (param_size == 2)
|
||||
param_value = get_unaligned_le16(&in->return_data[2]);
|
||||
else if (param_size == 4)
|
||||
param_value = get_unaligned_le32(&in->return_data[2]);
|
||||
else
|
||||
return -EINVAL;
|
||||
|
||||
pr_info("%s: Parameter ID: 0x%02x Value: 0x%02x\n",
|
||||
__func__, param_id, param_value);
|
||||
|
||||
if (parameter_value)
|
||||
*parameter_value = param_value;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int prepare_set_parameter_report(u8 *buf, u8 parameter_id,
|
||||
u8 parameter_size, u32 parameter_value)
|
||||
{
|
||||
struct tt_output_report *out = (struct tt_output_report *)buf;
|
||||
|
||||
out->parameters[0] = parameter_id;
|
||||
out->parameters[1] = parameter_size;
|
||||
|
||||
if (parameter_size == 1)
|
||||
out->parameters[2] = (u8)parameter_value;
|
||||
else if (parameter_size == 2)
|
||||
put_unaligned_le16(parameter_value, &out->parameters[2]);
|
||||
else if (parameter_size == 4)
|
||||
put_unaligned_le32(parameter_value, &out->parameters[2]);
|
||||
else
|
||||
return -EINVAL;
|
||||
|
||||
return prepare_tt_output_report(out, 2 + parameter_size,
|
||||
COMMAND_SET_PARAMETER);
|
||||
}
|
||||
|
||||
static int check_set_parameter_response(u8 *buf, u16 read_length)
|
||||
{
|
||||
struct tt_input_report *in = (struct tt_input_report *)buf;
|
||||
u16 length = 0;
|
||||
u8 command = 0;
|
||||
u8 param_id;
|
||||
u8 param_size = 0;
|
||||
|
||||
if (read_length != 7)
|
||||
return -EINVAL;
|
||||
|
||||
if (check_and_parse_tt_input_report(in, &length, &command)
|
||||
|| command != COMMAND_SET_PARAMETER
|
||||
|| length != 7)
|
||||
return -EINVAL;
|
||||
|
||||
param_id = in->return_data[0];
|
||||
param_size = in->return_data[1];
|
||||
|
||||
pr_info("%s: Parameter ID: 0x%02x Size: 0x%02x\n",
|
||||
__func__, param_id, param_size);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int prepare_suspend_scanning_report(u8 *buf)
|
||||
{
|
||||
struct tt_output_report *out = (struct tt_output_report *)buf;
|
||||
|
||||
return prepare_tt_output_report(out, 0, COMMAND_SUSPEND_SCANNING);
|
||||
}
|
||||
|
||||
static int check_suspend_scanning_response(u8 *buf, u16 read_length)
|
||||
{
|
||||
struct tt_input_report *in = (struct tt_input_report *)buf;
|
||||
u16 length = 0;
|
||||
u8 command = 0;
|
||||
|
||||
if (read_length != 5)
|
||||
return -EINVAL;
|
||||
|
||||
if (check_and_parse_tt_input_report(in, &length, &command)
|
||||
|| command != COMMAND_SUSPEND_SCANNING
|
||||
|| length != 5)
|
||||
return -EINVAL;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int prepare_resume_scanning_report(u8 *buf)
|
||||
{
|
||||
struct tt_output_report *out = (struct tt_output_report *)buf;
|
||||
|
||||
return prepare_tt_output_report(out, 0, COMMAND_RESUME_SCANNING);
|
||||
}
|
||||
|
||||
static int check_resume_scanning_response(u8 *buf, u16 read_length)
|
||||
{
|
||||
struct tt_input_report *in = (struct tt_input_report *)buf;
|
||||
u16 length = 0;
|
||||
u8 command = 0;
|
||||
|
||||
if (read_length != 5)
|
||||
return -EINVAL;
|
||||
|
||||
if (check_and_parse_tt_input_report(in, &length, &command)
|
||||
|| command != COMMAND_RESUME_SCANNING
|
||||
|| length != 5)
|
||||
return -EINVAL;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void cyttsp5_user_command_async_cont(const char *core_name,
|
||||
u16 read_len, u8 *read_buf, u16 write_len, u8 *write_buf,
|
||||
u16 actual_read_length, int rc)
|
||||
{
|
||||
if (rc) {
|
||||
pr_err("%s: suspend scan fails\n", __func__);
|
||||
goto exit;
|
||||
}
|
||||
|
||||
rc = check_suspend_scanning_response(read_buf, actual_read_length);
|
||||
if (rc) {
|
||||
pr_err("%s: check suspend scanning response fails\n", __func__);
|
||||
goto exit;
|
||||
}
|
||||
|
||||
pr_info("%s: suspend scanning succeeds\n", __func__);
|
||||
exit:
|
||||
return;
|
||||
}
|
||||
|
||||
/* Read and write buffers */
|
||||
static u8 write_buf[BUFFER_SIZE];
|
||||
static u8 read_buf[BUFFER_SIZE];
|
||||
|
||||
static uint active_distance;
|
||||
module_param(active_distance, uint, 0);
|
||||
|
||||
static int __init cyttsp5_test_device_access_api_init(void)
|
||||
{
|
||||
u32 initial_active_distance;
|
||||
u16 actual_read_len;
|
||||
int write_len;
|
||||
int rc;
|
||||
|
||||
pr_info("%s: Enter\n", __func__);
|
||||
|
||||
/* CASE 1: Run get system information */
|
||||
write_len = prepare_get_system_info_report(write_buf);
|
||||
|
||||
rc = cyttsp5_device_access_user_command(NULL, sizeof(read_buf),
|
||||
read_buf, write_len, write_buf,
|
||||
&actual_read_len);
|
||||
if (rc)
|
||||
goto exit;
|
||||
|
||||
rc = check_get_system_info_response(read_buf, actual_read_len);
|
||||
if (rc)
|
||||
goto exit;
|
||||
|
||||
/* CASE 2: Run get parameter (Active distance) */
|
||||
write_len = prepare_get_parameter_report(write_buf,
|
||||
PARAMETER_ACTIVE_DISTANCE_2);
|
||||
|
||||
rc = cyttsp5_device_access_user_command(NULL, sizeof(read_buf),
|
||||
read_buf, write_len, write_buf,
|
||||
&actual_read_len);
|
||||
if (rc)
|
||||
goto exit;
|
||||
|
||||
rc = check_get_parameter_response(read_buf, actual_read_len,
|
||||
&initial_active_distance);
|
||||
if (rc)
|
||||
goto exit;
|
||||
|
||||
pr_info("%s: Initial Active Distance: %d\n",
|
||||
__func__, initial_active_distance);
|
||||
|
||||
/* CASE 3: Run set parameter (Active distance) */
|
||||
write_len = prepare_set_parameter_report(write_buf,
|
||||
PARAMETER_ACTIVE_DISTANCE_2, 1,
|
||||
active_distance);
|
||||
|
||||
rc = cyttsp5_device_access_user_command(NULL, sizeof(read_buf),
|
||||
read_buf, write_len, write_buf,
|
||||
&actual_read_len);
|
||||
if (rc)
|
||||
goto exit;
|
||||
|
||||
rc = check_set_parameter_response(read_buf, actual_read_len);
|
||||
if (rc)
|
||||
goto exit;
|
||||
|
||||
pr_info("%s: Active Distance set to %d\n", __func__, active_distance);
|
||||
|
||||
/* CASE 4: Run get parameter (Active distance) */
|
||||
write_len = prepare_get_parameter_report(write_buf,
|
||||
PARAMETER_ACTIVE_DISTANCE_2);
|
||||
|
||||
rc = cyttsp5_device_access_user_command(NULL, sizeof(read_buf),
|
||||
read_buf, write_len, write_buf,
|
||||
&actual_read_len);
|
||||
if (rc)
|
||||
goto exit;
|
||||
|
||||
rc = check_get_parameter_response(read_buf, actual_read_len,
|
||||
&active_distance);
|
||||
if (rc)
|
||||
goto exit;
|
||||
|
||||
pr_info("%s: New Active Distance: %d\n", __func__, active_distance);
|
||||
|
||||
/* CASE 5: Run suspend scanning asynchronously */
|
||||
write_len = prepare_suspend_scanning_report(write_buf);
|
||||
|
||||
preempt_disable();
|
||||
rc = cyttsp5_device_access_user_command_async(NULL,
|
||||
sizeof(read_buf), read_buf, write_len, write_buf,
|
||||
cyttsp5_user_command_async_cont);
|
||||
preempt_enable();
|
||||
if (rc)
|
||||
goto exit;
|
||||
exit:
|
||||
return rc;
|
||||
}
|
||||
module_init(cyttsp5_test_device_access_api_init);
|
||||
|
||||
static void __exit cyttsp5_test_device_access_api_exit(void)
|
||||
{
|
||||
u16 actual_read_len;
|
||||
int write_len;
|
||||
int rc;
|
||||
|
||||
/* CASE 6: Run resume scanning */
|
||||
write_len = prepare_resume_scanning_report(write_buf);
|
||||
|
||||
rc = cyttsp5_device_access_user_command(NULL, sizeof(read_buf),
|
||||
read_buf, write_len, write_buf,
|
||||
&actual_read_len);
|
||||
if (rc)
|
||||
goto exit;
|
||||
|
||||
rc = check_resume_scanning_response(read_buf, actual_read_len);
|
||||
if (rc)
|
||||
goto exit;
|
||||
|
||||
pr_info("%s: resume scanning succeeds\n", __func__);
|
||||
exit:
|
||||
return;
|
||||
}
|
||||
module_exit(cyttsp5_test_device_access_api_exit);
|
||||
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_DESCRIPTION("Parade TrueTouch(R) Standard Product Device Access Driver API Tester");
|
||||
MODULE_AUTHOR("Parade Technologies <ttdrivers@paradetech.com>");
|
||||
20
drivers/input/touchscreen/focaltech_3658u/Kconfig
Normal file
20
drivers/input/touchscreen/focaltech_3658u/Kconfig
Normal file
@@ -0,0 +1,20 @@
|
||||
#
|
||||
# Focaltech Touchscreen driver configuration
|
||||
#
|
||||
|
||||
config TOUCHSCREEN_FOCALTECH_3658U
|
||||
tristate "Focaltech Touchscreen"
|
||||
default n
|
||||
help
|
||||
Say Y here if you have Focaltech touch panel.
|
||||
|
||||
If unsure, say N.
|
||||
|
||||
To compile this driver as a module, choose M here: the
|
||||
module will be called focaltech_touch.
|
||||
|
||||
config TOUCHSCREEN_FTS_DIRECTORY
|
||||
string "Focaltech ts directory name"
|
||||
default "focaltech_touch"
|
||||
depends on TOUCHSCREEN_FTS
|
||||
|
||||
31
drivers/input/touchscreen/focaltech_3658u/Makefile
Normal file
31
drivers/input/touchscreen/focaltech_3658u/Makefile
Normal file
@@ -0,0 +1,31 @@
|
||||
ifneq ($(KERNELRELEASE),)
|
||||
obj-$(CONFIG_TOUCHSCREEN_FOCALTECH_3658U) += focaltech_touch.o
|
||||
focaltech_touch-y := focaltech_core.o \
|
||||
focaltech_ex_fun.o \
|
||||
focaltech_ex_mode.o \
|
||||
focaltech_gesture.o \
|
||||
focaltech_esdcheck.o \
|
||||
focaltech_spi.o \
|
||||
focaltech_point_report_check.o \
|
||||
focaltech_flash.o \
|
||||
focaltech_flash/focaltech_upgrade_ft3658u.o \
|
||||
focaltech_test/focaltech_test.o \
|
||||
focaltech_test/focaltech_test_ini.o \
|
||||
focaltech_test/supported_ic/focaltech_test_ft3658u.o
|
||||
else
|
||||
KDIR = $(OUT)/obj/KERNEL_OBJ
|
||||
CROSS_COMPILE = $(ANDROID_TOOLCHAIN)/aarch64-linux-android-
|
||||
CLANG = $(ANDROID_BUILD_TOP)/prebuilts/clang/host/linux-x86/clang-r370808
|
||||
REAL_CC = $(CLANG)/bin/clang
|
||||
AR = $(CLANG)/bin/llvm-ar
|
||||
LLVM_NM = $(CLANG)/bin/llvm-nm
|
||||
LD = $(CLANG)/bin/ld.lld
|
||||
|
||||
.PHONY: clean
|
||||
|
||||
default:
|
||||
$(MAKE) ARCH=arm64 CROSS_COMPILE=$(CROSS_COMPILE) REAL_CC=$(REAL_CC) CLANG_TRIPLE=aarch64-linux-gnu- AR=$(AR) LLVM_NM=$(LLVM_NM) LD=$(LD) -C $(KDIR) M=$(PWD) modules
|
||||
clean:
|
||||
@rm -rf *.order *.symvers* .tmp_versions
|
||||
@find -name "*.o*" -o -name "*.mod*" -o -name "*.ko*" | xargs rm -f
|
||||
endif
|
||||
185
drivers/input/touchscreen/focaltech_3658u/focaltech_common.h
Normal file
185
drivers/input/touchscreen/focaltech_3658u/focaltech_common.h
Normal file
@@ -0,0 +1,185 @@
|
||||
/*
|
||||
*
|
||||
* FocalTech fts TouchScreen driver.
|
||||
*
|
||||
* Copyright (c) 2012-2020, Focaltech Ltd. All rights reserved.
|
||||
*
|
||||
* This software is licensed under the terms of the GNU General Public
|
||||
* License version 2, as published by the Free Software Foundation, and
|
||||
* may be copied, distributed, and modified under those terms.
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
*/
|
||||
/*****************************************************************************
|
||||
*
|
||||
* File Name: focaltech_common.h
|
||||
*
|
||||
* Author: Focaltech Driver Team
|
||||
*
|
||||
* Created: 2016-08-16
|
||||
*
|
||||
* Abstract:
|
||||
*
|
||||
* Reference:
|
||||
*
|
||||
*****************************************************************************/
|
||||
|
||||
#ifndef __LINUX_FOCALTECH_COMMON_H__
|
||||
#define __LINUX_FOCALTECH_COMMON_H__
|
||||
|
||||
#include "focaltech_config.h"
|
||||
|
||||
/*****************************************************************************
|
||||
* Macro definitions using #define
|
||||
*****************************************************************************/
|
||||
#define FTS_DRIVER_VERSION "Focaltech V3.2 20200422"
|
||||
|
||||
#define BYTE_OFF_0(x) (u8)((x) & 0xFF)
|
||||
#define BYTE_OFF_8(x) (u8)(((x) >> 8) & 0xFF)
|
||||
#define BYTE_OFF_16(x) (u8)(((x) >> 16) & 0xFF)
|
||||
#define BYTE_OFF_24(x) (u8)(((x) >> 24) & 0xFF)
|
||||
#define FLAGBIT(x) (0x00000001 << (x))
|
||||
#define FLAGBITS(x, y) ((0xFFFFFFFF >> (32 - (y) - 1)) & (0xFFFFFFFF << (x)))
|
||||
|
||||
#define FLAG_ICSERIALS_LEN 8
|
||||
#define FLAG_HID_BIT 10
|
||||
#define FLAG_IDC_BIT 11
|
||||
|
||||
#define IC_SERIALS (FTS_CHIP_TYPE & FLAGBITS(0, FLAG_ICSERIALS_LEN-1))
|
||||
#define IC_TO_SERIALS(x) ((x) & FLAGBITS(0, FLAG_ICSERIALS_LEN-1))
|
||||
#define FTS_CHIP_IDC ((FTS_CHIP_TYPE & FLAGBIT(FLAG_IDC_BIT)) == FLAGBIT(FLAG_IDC_BIT))
|
||||
#define FTS_HID_SUPPORTTED ((FTS_CHIP_TYPE & FLAGBIT(FLAG_HID_BIT)) == FLAGBIT(FLAG_HID_BIT))
|
||||
|
||||
#define FTS_CHIP_TYPE_MAPPING {{0x88, 0x56, 0x52, 0x00, 0x00, 0x00, 0x00, 0x56, 0xB2}}
|
||||
|
||||
#define FILE_NAME_LENGTH 128
|
||||
#define ENABLE 1
|
||||
#define DISABLE 0
|
||||
#define VALID 1
|
||||
#define INVALID 0
|
||||
#define FTS_CMD_START1 0x55
|
||||
#define FTS_CMD_START2 0xAA
|
||||
#define FTS_CMD_START_DELAY 12
|
||||
#define FTS_CMD_READ_ID 0x90
|
||||
#define FTS_CMD_READ_ID_LEN 4
|
||||
#define FTS_CMD_READ_ID_LEN_INCELL 1
|
||||
#define FTS_CMD_READ_FW_CONF 0xA8
|
||||
/*register address*/
|
||||
#define FTS_REG_INT_CNT 0x8F
|
||||
#define FTS_REG_FLOW_WORK_CNT 0x91
|
||||
#define FTS_REG_WORKMODE 0x00
|
||||
#define FTS_REG_WORKMODE_FACTORY_VALUE 0x40
|
||||
#define FTS_REG_WORKMODE_WORK_VALUE 0x00
|
||||
#define FTS_REG_ESDCHECK_DISABLE 0x8D
|
||||
#define FTS_REG_CHIP_ID 0xA3
|
||||
#define FTS_REG_CHIP_ID2 0x9F
|
||||
#define FTS_REG_POWER_MODE 0xA5
|
||||
#define FTS_REG_POWER_MODE_SLEEP 0x03
|
||||
#define FTS_REG_FW_VER 0xA6
|
||||
#define FTS_REG_VENDOR_ID 0xA8
|
||||
#define FTS_REG_LCD_BUSY_NUM 0xAB
|
||||
#define FTS_REG_FACE_DEC_MODE_EN 0xB0
|
||||
#define FTS_REG_FACTORY_MODE_DETACH_FLAG 0xB4
|
||||
#define FTS_REG_FACE_DEC_MODE_STATUS 0x01
|
||||
#define FTS_REG_IDE_PARA_VER_ID 0xB5
|
||||
#define FTS_REG_IDE_PARA_STATUS 0xB6
|
||||
#define FTS_REG_GLOVE_MODE_EN 0xC0
|
||||
#define FTS_REG_COVER_MODE_EN 0xC1
|
||||
#define FTS_REG_CHARGER_MODE_EN 0x8B
|
||||
#define FTS_REG_FPS_VALUE 0x8A
|
||||
#define FTS_REG_GESTURE_EN 0xD0
|
||||
#define FTS_REG_GESTURE_OUTPUT_ADDRESS 0xD3
|
||||
#define FTS_REG_MODULE_ID 0xE3
|
||||
#define FTS_REG_LIC_VER 0xE4
|
||||
#define FTS_REG_ESD_SATURATE 0xED
|
||||
#define FTS_REG_FREQUENCY_VAL1 0x98
|
||||
#define FTS_REG_FREQUENCY_VAL2 0x99
|
||||
|
||||
#define FTS_REG_GAME_MODE_EN 0xc3
|
||||
#define FTS_REG_SENSIVITY 0x9d
|
||||
#define FTS_REG_THDIFF 0x85
|
||||
#define FTS_REG_MONITOR_MODE 0x86
|
||||
#define FTS_REG_TIMEENTERMONITOR 0x87
|
||||
#define FTS_REG_ORIENTATION 0x8c
|
||||
#define FTS_REG_EDGE_FILTER_LEVEL 0x9c
|
||||
|
||||
#define FTS_PALM_EN 0x9a
|
||||
#define FTS_PALM_DATA 0x01
|
||||
#define FTS_PALM_ON 0x05
|
||||
#define FTS_PALM_OFF 0x00
|
||||
|
||||
#define FTS_REG_DIFFDATA_EN 0x9e
|
||||
|
||||
#define FTS_SYSFS_ECHO_ON(buf) (buf[0] == '1')
|
||||
#define FTS_SYSFS_ECHO_OFF(buf) (buf[0] == '0')
|
||||
|
||||
#define kfree_safe(pbuf) do {\
|
||||
if (pbuf) {\
|
||||
kfree(pbuf);\
|
||||
pbuf = NULL;\
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
/*****************************************************************************
|
||||
* Alternative mode (When something goes wrong, the modules may be able to solve the problem.)
|
||||
*****************************************************************************/
|
||||
/*
|
||||
* point report check
|
||||
* default: disable
|
||||
*/
|
||||
#define FTS_POINT_REPORT_CHECK_EN 0
|
||||
|
||||
/*****************************************************************************
|
||||
* Global variable or extern global variabls/functions
|
||||
*****************************************************************************/
|
||||
struct ft_chip_t {
|
||||
u64 type;
|
||||
u8 chip_idh;
|
||||
u8 chip_idl;
|
||||
u8 rom_idh;
|
||||
u8 rom_idl;
|
||||
u8 pb_idh;
|
||||
u8 pb_idl;
|
||||
u8 bl_idh;
|
||||
u8 bl_idl;
|
||||
};
|
||||
|
||||
struct ts_ic_info {
|
||||
bool is_incell;
|
||||
bool hid_supported;
|
||||
struct ft_chip_t ids;
|
||||
};
|
||||
|
||||
/*****************************************************************************
|
||||
* DEBUG function define here
|
||||
*****************************************************************************/
|
||||
#if FTS_DEBUG_EN
|
||||
#define FTS_DEBUG(fmt, args...) do { \
|
||||
pr_info("[FTS_TS]%s:"fmt"\n", __func__, ##args); \
|
||||
} while (0)
|
||||
|
||||
#define FTS_FUNC_ENTER() do { \
|
||||
pr_info("[FTS_TS]%s: Enter\n", __func__); \
|
||||
} while (0)
|
||||
|
||||
#define FTS_FUNC_EXIT() do { \
|
||||
pr_info("[FTS_TS]%s: Exit(%d)\n", __func__, __LINE__); \
|
||||
} while (0)
|
||||
#else /* #if FTS_DEBUG_EN*/
|
||||
#define FTS_DEBUG(fmt, args...)
|
||||
#define FTS_FUNC_ENTER()
|
||||
#define FTS_FUNC_EXIT()
|
||||
#endif
|
||||
|
||||
#define FTS_INFO(fmt, args...) do { \
|
||||
pr_info(KERN_INFO "[FTS_TS/I]%s:"fmt"\n", __func__, ##args); \
|
||||
} while (0)
|
||||
|
||||
#define FTS_ERROR(fmt, args...) do { \
|
||||
pr_info(KERN_ERR "[FTS_TS/E]%s:"fmt"\n", __func__, ##args); \
|
||||
} while (0)
|
||||
#endif /* __LINUX_FOCALTECH_COMMON_H__ */
|
||||
280
drivers/input/touchscreen/focaltech_3658u/focaltech_config.h
Normal file
280
drivers/input/touchscreen/focaltech_3658u/focaltech_config.h
Normal file
@@ -0,0 +1,280 @@
|
||||
/*
|
||||
*
|
||||
* FocalTech TouchScreen driver.
|
||||
*
|
||||
* Copyright (c) 2012-2020, FocalTech Systems, Ltd., all rights reserved.
|
||||
*
|
||||
* This software is licensed under the terms of the GNU General Public
|
||||
* License version 2, as published by the Free Software Foundation, and
|
||||
* may be copied, distributed, and modified under those terms.
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
*/
|
||||
/************************************************************************
|
||||
*
|
||||
* File Name: focaltech_config.h
|
||||
*
|
||||
* Author: Focaltech Driver Team
|
||||
*
|
||||
* Created: 2016-08-08
|
||||
*
|
||||
* Abstract: global configurations
|
||||
*
|
||||
* Version: v1.0
|
||||
*
|
||||
************************************************************************/
|
||||
#ifndef _LINUX_FOCLATECH_CONFIG_H_
|
||||
#define _LINUX_FOCLATECH_CONFIG_H_
|
||||
|
||||
/**************************************************/
|
||||
/****** G: A, I: B, S: C, U: D ******************/
|
||||
/****** chip type defines, do not modify *********/
|
||||
#define _FT8716 0x87160805
|
||||
#define _FT8736 0x87360806
|
||||
#define _FT8006M 0x80060807
|
||||
#define _FT8607 0x86070809
|
||||
#define _FT8006U 0x8006D80B
|
||||
#define _FT8006S 0x8006A80B
|
||||
#define _FT8613 0x8613080C
|
||||
#define _FT8719 0x8719080D
|
||||
#define _FT8739 0x8739080E
|
||||
#define _FT8615 0x8615080F
|
||||
#define _FT8201 0x82010810
|
||||
#define _FT8006P 0x86220811
|
||||
#define _FT7251 0x72510812
|
||||
#define _FT7252 0x72520813
|
||||
#define _FT8613S 0x8613C814
|
||||
#define _FT8756 0x87560815
|
||||
#define _FT8302 0x83020816
|
||||
#define _FT8009 0x80090817
|
||||
#define _FT8656 0x86560818
|
||||
#define _FT8006S_AA 0x86320819
|
||||
#define _FT7250 0x7250081A
|
||||
#define _FT7120 0x7120081B
|
||||
#define _FT8720 0x8720081C
|
||||
#define _FT8016 0x8016081D
|
||||
|
||||
|
||||
#define _FT5416 0x54160402
|
||||
#define _FT5426 0x54260402
|
||||
#define _FT5435 0x54350402
|
||||
#define _FT5436 0x54360402
|
||||
#define _FT5526 0x55260402
|
||||
#define _FT5526I 0x5526B402
|
||||
#define _FT5446 0x54460402
|
||||
#define _FT5346 0x53460402
|
||||
#define _FT5446I 0x5446B402
|
||||
#define _FT5346I 0x5346B402
|
||||
#define _FT7661 0x76610402
|
||||
#define _FT7511 0x75110402
|
||||
#define _FT7421 0x74210402
|
||||
#define _FT7681 0x76810402
|
||||
#define _FT3C47U 0x3C47D402
|
||||
#define _FT3417 0x34170402
|
||||
#define _FT3517 0x35170402
|
||||
#define _FT3327 0x33270402
|
||||
#define _FT3427 0x34270402
|
||||
#define _FT7311 0x73110402
|
||||
#define _FT5526_V00 0x5526C402
|
||||
|
||||
#define _FT5626 0x56260401
|
||||
#define _FT5726 0x57260401
|
||||
#define _FT5826B 0x5826B401
|
||||
#define _FT5826S 0x5826C401
|
||||
#define _FT7811 0x78110401
|
||||
#define _FT3D47 0x3D470401
|
||||
#define _FT3617 0x36170401
|
||||
#define _FT3717 0x37170401
|
||||
#define _FT3817B 0x3817B401
|
||||
#define _FT3517U 0x3517D401
|
||||
|
||||
#define _FT6236U 0x6236D003
|
||||
#define _FT6336G 0x6336A003
|
||||
#define _FT6336U 0x6336D003
|
||||
#define _FT6436U 0x6436D003
|
||||
#define _FT6436T 0x6436E003
|
||||
|
||||
#define _FT3267 0x32670004
|
||||
#define _FT3367 0x33670004
|
||||
|
||||
#define _FT3427_003 0x3427D482
|
||||
#define _FT3427G_003 0x3427A482
|
||||
#define _FT5446_003 0x5446D482
|
||||
#define _FT5446_Q03 0x5446C482
|
||||
#define _FT5446_P03 0x5446A481
|
||||
#define _FT5426_003 0x5426D482
|
||||
#define _FT5526_003 0x5526D482
|
||||
|
||||
#define _FT3518 0x35180481
|
||||
#define _FT3518U 0x3518D481
|
||||
#define _FT3558 0x35580481
|
||||
#define _FT3528 0x35280481
|
||||
#define _FT5536 0x55360481
|
||||
#define _FT5536L 0x5536E481
|
||||
#define _FT3418 0x34180481
|
||||
|
||||
#define _FT5446U 0x5446D083
|
||||
#define _FT5456U 0x5456D083
|
||||
#define _FT3417U 0x3417D083
|
||||
#define _FT5426U 0x5426D083
|
||||
#define _FT3428 0x34280083
|
||||
#define _FT3437U 0x3437D083
|
||||
|
||||
#define _FT7302 0x73020084
|
||||
#define _FT7202 0x72020084
|
||||
#define _FT3308 0x33080084
|
||||
#define _FT6446 0x64460084
|
||||
|
||||
#define _FT6346U 0x6346D085
|
||||
#define _FT6346G 0x6346A085
|
||||
#define _FT3067 0x30670085
|
||||
#define _FT3068 0x30680085
|
||||
#define _FT3168 0x31680085
|
||||
#define _FT3268 0x32680085
|
||||
#define _FT6146 0x61460085
|
||||
|
||||
#define _FT5726_003 0x5726D486
|
||||
#define _FT5726_V03 0x5726C486
|
||||
|
||||
#define _FT3618 0x36180487
|
||||
#define _FT5646 0x56460487
|
||||
#define _FT3A58 0x3A580487
|
||||
#define _FT3B58 0x3B580487
|
||||
#define _FT3D58 0x3D580487
|
||||
#define _FT5936 0x59360487
|
||||
#define _FT5A36 0x5A360487
|
||||
#define _FT5B36 0x5B360487
|
||||
#define _FT5D36 0x5D360487
|
||||
#define _FT5946 0x59460487
|
||||
#define _FT5A46 0x5A460487
|
||||
#define _FT5B46 0x5B460487
|
||||
#define _FT5D46 0x5D460487
|
||||
|
||||
#define _FT3658U 0x3658D488
|
||||
|
||||
/*************************************************/
|
||||
|
||||
/*
|
||||
* choose your ic chip type of focaltech
|
||||
*/
|
||||
#define FTS_CHIP_TYPE _FT3658U
|
||||
|
||||
/******************* Enables *********************/
|
||||
/*********** 1 to enable, 0 to disable ***********/
|
||||
|
||||
/*
|
||||
* show debug log info
|
||||
* enable it for debug, disable it for release
|
||||
*/
|
||||
#define FTS_DEBUG_EN 1
|
||||
|
||||
/*
|
||||
* Linux MultiTouch Protocol
|
||||
* 1: Protocol B(default), 0: Protocol A
|
||||
*/
|
||||
#define FTS_MT_PROTOCOL_B_EN 1
|
||||
|
||||
/*
|
||||
* Report Pressure in multitouch
|
||||
* 1:enable(default),0:disable
|
||||
*/
|
||||
#define FTS_REPORT_PRESSURE_EN 0
|
||||
|
||||
/*
|
||||
* Gesture function enable
|
||||
* default: disable
|
||||
*/
|
||||
#define FTS_GESTURE_EN 0
|
||||
|
||||
/*
|
||||
* ESD check & protection
|
||||
* default: disable
|
||||
*/
|
||||
#define FTS_ESDCHECK_EN 0
|
||||
|
||||
/*
|
||||
* Production test enable
|
||||
* 1: enable, 0:disable(default)
|
||||
*/
|
||||
#define FTS_TEST_EN 1
|
||||
|
||||
/*
|
||||
* Pinctrl enable
|
||||
* default: disable
|
||||
*/
|
||||
#define FTS_PINCTRL_EN 1
|
||||
|
||||
/*
|
||||
* Customer power enable
|
||||
* enable it when customer need control TP power
|
||||
* default: disable
|
||||
*/
|
||||
#define FTS_POWER_SOURCE_CUST_EN 1
|
||||
|
||||
/****************************************************/
|
||||
|
||||
/********************** Upgrade ****************************/
|
||||
/*
|
||||
* auto upgrade
|
||||
*/
|
||||
#define FTS_AUTO_UPGRADE_EN 1
|
||||
|
||||
/*
|
||||
* auto upgrade for lcd cfg
|
||||
*/
|
||||
#define FTS_AUTO_LIC_UPGRADE_EN 0
|
||||
|
||||
/*
|
||||
* Numbers of modules support
|
||||
*/
|
||||
#define FTS_GET_MODULE_NUM 0
|
||||
|
||||
/*
|
||||
* module_id: mean vendor_id generally, also maybe gpio or lcm_id...
|
||||
* If means vendor_id, the FTS_MODULE_ID = PANEL_ID << 8 + VENDOR_ID
|
||||
* FTS_GET_MODULE_NUM == 0/1, no check module id, you may ignore them
|
||||
* FTS_GET_MODULE_NUM >= 2, compatible with FTS_MODULE2_ID
|
||||
* FTS_GET_MODULE_NUM >= 3, compatible with FTS_MODULE3_ID
|
||||
*/
|
||||
#define FTS_MODULE_ID 0x0000
|
||||
#define FTS_MODULE2_ID 0x0000
|
||||
#define FTS_MODULE3_ID 0x0000
|
||||
|
||||
/*
|
||||
* Need set the following when get firmware via firmware_request()
|
||||
* For example: if module'vendor is tianma,
|
||||
* #define FTS_MODULE_NAME "tianma"
|
||||
* then file_name will be "focaltech_ts_fw_tianma"
|
||||
* You should rename fw to "focaltech_ts_fw_tianma", and push it into
|
||||
* etc/firmware or by customers
|
||||
*/
|
||||
#define FTS_MODULE_NAME ""
|
||||
#define FTS_MODULE2_NAME ""
|
||||
#define FTS_MODULE3_NAME ""
|
||||
|
||||
/*
|
||||
* FW.i file for auto upgrade, you must replace it with your own
|
||||
* define your own fw_file, the sample one to be replaced is invalid
|
||||
* NOTE: if FTS_GET_MODULE_NUM > 1, it's the fw corresponding with FTS_VENDOR_ID
|
||||
*/
|
||||
#define FTS_UPGRADE_FW_FILE "include/firmware/fw_ft3658_k9.i"
|
||||
|
||||
/*
|
||||
* if FTS_GET_MODULE_NUM >= 2, fw corrsponding with FTS_VENDOR_ID2
|
||||
* define your own fw_file, the sample one is invalid
|
||||
*/
|
||||
#define FTS_UPGRADE_FW2_FILE "include/firmware/fw_sample.i"
|
||||
|
||||
/*
|
||||
* if FTS_GET_MODULE_NUM >= 3, fw corrsponding with FTS_VENDOR_ID3
|
||||
* define your own fw_file, the sample one is invalid
|
||||
*/
|
||||
#define FTS_UPGRADE_FW3_FILE "include/firmware/fw_sample.i"
|
||||
|
||||
/*********************************************************/
|
||||
|
||||
#endif /* _LINUX_FOCLATECH_CONFIG_H_ */
|
||||
2662
drivers/input/touchscreen/focaltech_3658u/focaltech_core.c
Normal file
2662
drivers/input/touchscreen/focaltech_3658u/focaltech_core.c
Normal file
File diff suppressed because it is too large
Load Diff
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user