From 7644b7452c03bb97a70da3f73176ad93fd8bc2e6 Mon Sep 17 00:00:00 2001 From: Fenglin Wu Date: Mon, 14 Mar 2022 11:20:15 +0800 Subject: [PATCH 1/2] input: qcom-hv-haptics: Update RC_CLK_CAL_COUNT calculation The equations for calculating RC_CLK_CAL_COUNT need to be updated when flag SLEEP_CLK_32K_SCALE is not set. Update it by introducing a coefficient named as SLEEP_CLK_CAL_DIVIDER which is the divider of the 19.2 MHz system clock to generate the sleep clock. Change-Id: I75d16eca3fe160c425af5cf3545272e0d1999a8a Signed-off-by: Fenglin Wu --- drivers/input/misc/qcom-hv-haptics.c | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/drivers/input/misc/qcom-hv-haptics.c b/drivers/input/misc/qcom-hv-haptics.c index 07eafe654a32..32ac21211c1a 100644 --- a/drivers/input/misc/qcom-hv-haptics.c +++ b/drivers/input/misc/qcom-hv-haptics.c @@ -966,6 +966,8 @@ static int haptics_adjust_lra_period(struct haptics_chip *chip, u32 *t_lra_us) ((chip->wa_flags & SLEEP_CLK_32K_SCALE) ? 1627700 : 1666667) #define TLRA_AUTO_RES_AUTO_CAL_STEP_PSEC \ ((chip->wa_flags & SLEEP_CLK_32K_SCALE) ? 813850 : 833333) +#define SLEEP_CLK_CAL_DIVIDER \ + ((chip->wa_flags & SLEEP_CLK_32K_SCALE) ? 600 : 586) static int haptics_get_closeloop_lra_period( struct haptics_chip *chip, bool in_boot) { @@ -1057,10 +1059,10 @@ static int haptics_get_closeloop_lra_period( if (!config->t_lra_us || !config->cl_t_lra_us) return -EINVAL; /* - * RC_CLK_CAL_COUNT = 600 * (CAL_TLRA_OL / TLRA_OL) - * * (600 / 586) * (CL_T_TLRA_US / OL_T_LRA_US) + * RC_CLK_CAL_COUNT = SLEEP_CLK_CAL_DIVIDER * (CAL_TLRA_OL / TLRA_OL) + * * (SLEEP_CLK_CAL_DIVIDER / 586) * (CL_T_TLRA_US / OL_T_LRA_US) */ - tmp = 360000; + tmp = SLEEP_CLK_CAL_DIVIDER * SLEEP_CLK_CAL_DIVIDER; tmp *= cal_tlra_cl_sts * config->cl_t_lra_us; tmp = div_u64(tmp, tlra_ol); tmp = div_u64(tmp, 586); @@ -1095,10 +1097,10 @@ static int haptics_get_closeloop_lra_period( /* * RC_CLK_CAL_COUNT = - * 600 * (CAL_TLRA_CL_STS_AUTO_CAL / LAST_GOOD_TLRA_CL_STS) - * * (600 / 293) * (CL_T_TLRA_US / OL_T_LRA_US) + * SLEEP_CLK_CAL_DIVIDER * (CAL_TLRA_CL_STS_AUTO_CAL / LAST_GOOD_TLRA_CL_STS) + * * (SLEEP_CLK_CAL_DIVIDER / 293) * (CL_T_TLRA_US / OL_T_LRA_US) */ - tmp = 360000; + tmp = SLEEP_CLK_CAL_DIVIDER * SLEEP_CLK_CAL_DIVIDER; tmp *= cal_tlra_cl_sts * config->cl_t_lra_us; tmp = div_u64(tmp, last_good_tlra_cl_sts); tmp = div_u64(tmp, 293); From 83af7dff89786fbecf11bb69b5d30f77b8206f27 Mon Sep 17 00:00:00 2001 From: Fenglin Wu Date: Mon, 21 Mar 2022 15:07:59 +0800 Subject: [PATCH 2/2] input: qcom-hv-haptics: discard 1-byte FIFO write for HAP520 For haptics module with HAP520 HW revision, the HW would only read 1 valid byte in every 4 bytes if the 1-byte FIFO write clashes with the FIFO read operation. To avoid this, don't use 1-byte write but just pad zeros at end of the pattern to keep the samples 4-byte aligned and always use 4-byte write for FIFO programming. Change-Id: I3ebde0fe7378c0dcffb5c51e15e6ffaae5af3e29 Signed-off-by: Fenglin Wu --- drivers/input/misc/qcom-hv-haptics.c | 49 ++++++++++++++++++++-------- 1 file changed, 36 insertions(+), 13 deletions(-) diff --git a/drivers/input/misc/qcom-hv-haptics.c b/drivers/input/misc/qcom-hv-haptics.c index 32ac21211c1a..5ec0b53aff31 100644 --- a/drivers/input/misc/qcom-hv-haptics.c +++ b/drivers/input/misc/qcom-hv-haptics.c @@ -1601,6 +1601,10 @@ static int haptics_update_memory_data(struct haptics_chip *chip, { int rc, count, i; u32 left; + u8 tmp[HAP_PTN_FIFO_DIN_NUM] = {0}; + + if (!length) + return 0; count = length / HAP_PTN_FIFO_DIN_NUM; for (i = 0; i < count; i++) { @@ -1618,6 +1622,24 @@ static int haptics_update_memory_data(struct haptics_chip *chip, left = length % HAP_PTN_FIFO_DIN_NUM; if (left) { + /* + * In HAP520 module, when 1-byte FIFO write clashes + * with the HW FIFO read operation, the HW will only read + * 1 valid byte in every 4 bytes FIFO samples. So avoid + * this by keeping the samples 4-byte aligned and always + * use 4-byte write for HAP520 module. + */ + if (chip->hw_type == HAP520) { + memcpy(tmp, data, left); + rc = haptics_write(chip, chip->ptn_addr_base, + HAP_PTN_FIFO_DIN_0_REG, tmp, + HAP_PTN_FIFO_DIN_NUM); + if (rc < 0) + dev_err(chip->dev, "write FIFO_DIN failed, rc=%d\n", rc); + + return rc; + } + for (i = 0; i < left; i++) { rc = haptics_write(chip, chip->ptn_addr_base, HAP_PTN_FIFO_DIN_1B_REG, @@ -1894,6 +1916,10 @@ static int haptics_set_fifo(struct haptics_chip *chip, struct fifo_cfg *fifo) return available; num = min_t(u32, available, num); + /* Keep the FIFO programming 4-byte aligned if FIFO refilling is needed */ + if ((num < fifo->num_s) && (num % HAP_PTN_FIFO_DIN_NUM)) + num = round_down(num, HAP_PTN_FIFO_DIN_NUM); + rc = haptics_update_fifo_samples(chip, fifo->samples, num, false); if (rc < 0) { dev_err(chip->dev, "write FIFO samples failed, rc=%d\n", rc); @@ -3032,21 +3058,18 @@ static irqreturn_t fifo_empty_irq_handler(int irq, void *data) if (num < 0) goto unlock; - /* - * If 1-byte write is done before a 4-byte write, the hardware - * would insert zeros in between to keep the FIFO samples - * 4-byte aligned, and the inserted 0 values would cause HW - * stop driving hence spurs will be seen on the haptics output. - * So only use 1-byte write at the end of FIFO streaming. - */ - if (samples_left <= num) - num = samples_left; - else if (num % HAP_PTN_FIFO_DIN_NUM) - num -= (num % HAP_PTN_FIFO_DIN_NUM); - samples = fifo->samples + status->samples_written; - /* Write more pattern data into FIFO memory. */ + /* + * Always use 4-byte burst write in the middle of FIFO programming to + * avoid HW padding zeros during 1-byte write which would cause the HW + * stop driving for the unexpected padding zeros. + */ + if (num < samples_left) + num = round_down(num, HAP_PTN_FIFO_DIN_NUM); + else + num = samples_left; + rc = haptics_update_fifo_samples(chip, samples, num, true); if (rc < 0) { dev_err(chip->dev, "Update FIFO samples failed, rc=%d\n",