From ef3616fe663cac801f0730d0d48b418502e15c4d Mon Sep 17 00:00:00 2001 From: Ravi Jain Date: Thu, 29 Feb 2024 13:23:39 +0000 Subject: [PATCH 1/2] dumpstate: touch: Init using touch_predump More info at go/touch_predump Test: Test locally on test device and check predump_touch works. Bug: 287907308 Change-Id: Iadad909a658f4fa1d3bc163b8bfd950e5029c4a5 --- device-felix.mk | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/device-felix.mk b/device-felix.mk index ad942d6..cccef1d 100644 --- a/device-felix.mk +++ b/device-felix.mk @@ -47,8 +47,8 @@ $(call soong_config_set,fp_hal_feature,pixel_product, product_a) include device/google/felix/vibrator/cs40l26/device.mk include device/google/gs-common/bcmbt/bluetooth.mk include device/google/gs-common/display/dump_second_display.mk -include device/google/gs-common/touch/gti/gti.mk -include device/google/gs-common/touch/stm/stm6.mk +include device/google/gs-common/touch/gti/predump_gti_dual.mk +include device/google/gs-common/touch/stm/predump_stm6.mk ifeq ($(filter factory_felix, $(TARGET_PRODUCT)),) include device/google/felix/uwb/uwb_calibration.mk endif From 7105ca38e802591f32236fe1b53f62a3ffa7c43e Mon Sep 17 00:00:00 2001 From: Nathan Kulczak Date: Mon, 31 Jul 2023 20:28:58 +0000 Subject: [PATCH 2/2] vibrator: Format PWLE header in user driver Add PWLE header formatting to user side driver to support new kernel driver and SVC and DVL for OWT effects. Bug: 279055885 Bug: 361011775 Flag: EXEMPT bugfix Test: idlcli Change-Id: I3b447962cc46ab57cf145072bc30303786f581ad Signed-off-by: Nathan Kulczak --- vibrator/cs40l26/Vibrator.cpp | 74 +++++++++++++++++++++++++++++++++++ 1 file changed, 74 insertions(+) diff --git a/vibrator/cs40l26/Vibrator.cpp b/vibrator/cs40l26/Vibrator.cpp index 03f3646..b4b1cbe 100644 --- a/vibrator/cs40l26/Vibrator.cpp +++ b/vibrator/cs40l26/Vibrator.cpp @@ -19,6 +19,7 @@ #include #include #include +#include #include #include #include @@ -84,6 +85,30 @@ static constexpr uint8_t PWLE_CHIRP_BIT = 0x8; // Dynamic/static frequency and static constexpr uint8_t PWLE_BRAKE_BIT = 0x4; static constexpr uint8_t PWLE_AMP_REG_BIT = 0x2; +static constexpr uint8_t PWLE_WT_TYPE = 12; +static constexpr uint8_t PWLE_HEADER_WORD_COUNT = 3; +static constexpr uint8_t PWLE_HEADER_FTR_SHIFT = 8; +static constexpr uint8_t PWLE_SVC_METADATA_WORD_COUNT = 3; +static constexpr uint32_t PWLE_SVC_METADATA_TERMINATOR = 0xFFFFFF; +static constexpr uint8_t PWLE_SEGMENT_WORD_COUNT = 2; +static constexpr uint8_t PWLE_HEADER_WCOUNT_WORD_OFFSET = 2; +static constexpr uint8_t PWLE_WORD_SIZE = sizeof(uint32_t); + +static constexpr uint8_t PWLE_SVC_NO_BRAKING = -1; +static constexpr uint8_t PWLE_SVC_CAT_BRAKING = 0; +static constexpr uint8_t PWLE_SVC_OPEN_BRAKING = 1; +static constexpr uint8_t PWLE_SVC_CLOSED_BRAKING = 2; +static constexpr uint8_t PWLE_SVC_MIXED_BRAKING = 3; + +static constexpr uint32_t PWLE_SVC_MAX_BRAKING_TIME_MS = 1000; + +static constexpr uint8_t PWLE_FTR_BUZZ_BIT = 0x80; +static constexpr uint8_t PWLE_FTR_CLICK_BIT = 0x00; +static constexpr uint8_t PWLE_FTR_DYNAMIC_F0_BIT = 0x10; +static constexpr uint8_t PWLE_FTR_SVC_METADATA_BIT = 0x04; +static constexpr uint8_t PWLE_FTR_DVL_BIT = 0x02; +static constexpr uint8_t PWLE_FTR_LF0T_BIT = 0x01; + static constexpr float PWLE_LEVEL_MIN = 0.0; static constexpr float PWLE_LEVEL_MAX = 1.0; static constexpr float CS40L26_PWLE_LEVEL_MIN = -1.0; @@ -233,10 +258,18 @@ class DspMemChunk { write(8, 0); /* nsections placeholder */ write(8, 0); /* repeat */ } else if (waveformType == WAVEFORM_PWLE) { + write(16, (PWLE_FTR_BUZZ_BIT | PWLE_FTR_DVL_BIT) + << PWLE_HEADER_FTR_SHIFT); /* Feature flag */ + write(8, PWLE_WT_TYPE); /* type12 */ + write(24, PWLE_HEADER_WORD_COUNT); /* Header word count */ + write(24, 0); /* Body word count placeholder */ + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(6, 0, 0) write(24, 0); /* Waveform length placeholder */ write(8, 0); /* Repeat */ write(12, 0); /* Wait time between repeats */ write(8, 0); /* nsections placeholder */ +#endif } else { ALOGE("%s: Invalid type: %u", __func__, waveformType); } @@ -324,6 +357,9 @@ class DspMemChunk { ALOGE("%s: Invalid argument: %u", __func__, totalDuration); return -EINVAL; } +#if LINUX_VERSION_CODE >= KERNEL_VERSION(6, 0, 0) + f += PWLE_HEADER_WORD_COUNT * PWLE_WORD_SIZE; +#endif totalDuration *= 8; /* Unit: 0.125 ms (since wlength played @ 8kHz). */ totalDuration |= WT_LEN_CALCD; /* Bit 23 is for WT_LEN_CALCD; Bit 22 is for WT_INDEFINITE. */ @@ -352,6 +388,9 @@ class DspMemChunk { ALOGE("%s: Invalid argument: %d", __func__, segmentIdx); return -EINVAL; } +#if LINUX_VERSION_CODE >= KERNEL_VERSION(6, 0, 0) + f += PWLE_HEADER_WORD_COUNT * PWLE_WORD_SIZE; +#endif *(f + 7) |= (0xF0 & segmentIdx) >> 4; /* Bit 4 to 7 */ *(f + 9) |= (0x0F & segmentIdx) << 4; /* Bit 3 to 0 */ } else { @@ -361,6 +400,34 @@ class DspMemChunk { return 0; } + + int updateWCount(int segmentCount) { + uint8_t *f = front(); + + if (segmentCount > COMPOSE_SIZE_MAX + 1 /*1st effect may have a delay*/) { + ALOGE("%s: Invalid argument: %d", __func__, segmentCount); + return -EINVAL; + } + if (f == nullptr) { + ALOGE("%s: head does not exist!", __func__); + return -ENOMEM; + } + if (waveformType != WAVEFORM_PWLE) { + ALOGE("%s: Invalid type: %d", __func__, waveformType); + return -EDOM; + } + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(6, 0, 0) + f += PWLE_HEADER_WORD_COUNT * PWLE_WORD_SIZE; +#endif + uint32_t dataSize = segmentCount * PWLE_SEGMENT_WORD_COUNT + PWLE_HEADER_WORD_COUNT; + *(f + 0) = (dataSize >> 24) & 0xFF; + *(f + 1) = (dataSize >> 16) & 0xFF; + *(f + 2) = (dataSize >> 8) & 0xFF; + *(f + 3) = dataSize & 0xFF; + + return 0; + } }; Vibrator::Vibrator(std::unique_ptr hwApiDefault, std::unique_ptr hwCalDefault, @@ -1360,6 +1427,13 @@ ndk::ScopedAStatus Vibrator::composePwle(const std::vector &compo return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT); } + /* Update word count */ + if (ch.updateWCount(segmentIdx) < 0) { + ALOGE("%s: Failed to update the waveform word count", __func__); + return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT); + } + + /* Update waveform length */ if (ch.updateWLength(totalDuration) < 0) { ALOGE("%s: Failed to update the waveform length length", __func__); return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);