From c38c0c90d733f47b5d15e0a14e747ce9b043fcc2 Mon Sep 17 00:00:00 2001 From: Fenglin Wu Date: Tue, 1 Mar 2022 09:52:26 +0800 Subject: [PATCH] input: qcom-hv-haptics: discard 1-byte FIFO write for HAP_PTN_V2 For haptics module with HAP_PTN_V2 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 | 60 +++++++++++++++++----------- 1 file changed, 37 insertions(+), 23 deletions(-) diff --git a/drivers/input/misc/qcom-hv-haptics.c b/drivers/input/misc/qcom-hv-haptics.c index 5682800756b1..029970344159 100644 --- a/drivers/input/misc/qcom-hv-haptics.c +++ b/drivers/input/misc/qcom-hv-haptics.c @@ -1818,13 +1818,17 @@ static int haptics_set_manual_rc_clk_cal(struct haptics_chip *chip) static int haptics_update_fifo_samples(struct haptics_chip *chip, u8 *samples, u32 length) { - int rc, count, i; + int rc = 0, count, i, remain; + u8 tmp[HAP_PTN_V2_FIFO_DIN_NUM] = {0}; if (samples == NULL) { dev_err(chip->dev, "no FIFO samples available\n"); return -EINVAL; } + if (!length) + return 0; + if (chip->ptn_revision == HAP_PTN_V1) { for (i = 0; i < length; i++) { rc = haptics_update_fifo_sample_v1(chip, samples[i]); @@ -1833,6 +1837,7 @@ static int haptics_update_fifo_samples(struct haptics_chip *chip, } } else { count = length / HAP_PTN_V2_FIFO_DIN_NUM; + remain = length % HAP_PTN_V2_FIFO_DIN_NUM; for (i = 0; i < count; i++) { rc = haptics_update_fifo_sample_v2(chip, samples, HAP_PTN_V2_FIFO_DIN_NUM); @@ -1842,16 +1847,26 @@ static int haptics_update_fifo_samples(struct haptics_chip *chip, samples += HAP_PTN_V2_FIFO_DIN_NUM; } - if (length % HAP_PTN_V2_FIFO_DIN_NUM) { - rc = haptics_update_fifo_sample_v2(chip, - samples, - length % HAP_PTN_V2_FIFO_DIN_NUM); - if (rc < 0) - return rc; + if (remain) { + /* + * In HAP_PTN_V2 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 HAP_PTN_V2 module. + */ + if (chip->ptn_revision == HAP_PTN_V2) { + memcpy(tmp, samples, remain); + rc = haptics_update_fifo_sample_v2(chip, + tmp, HAP_PTN_V2_FIFO_DIN_NUM); + } else { + rc = haptics_update_fifo_sample_v2(chip, + samples, remain); + } } } - return 0; + return rc; } static int haptics_set_fifo_playrate(struct haptics_chip *chip, @@ -1984,6 +1999,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_V2_FIFO_DIN_NUM)) + num = round_down(num, HAP_PTN_V2_FIFO_DIN_NUM); + rc = haptics_update_fifo_samples(chip, fifo->samples, num); if (rc < 0) { dev_err(chip->dev, "write FIFO samples failed, rc=%d\n", rc); @@ -2875,23 +2894,18 @@ static irqreturn_t fifo_empty_irq_handler(int irq, void *data) if (num < 0) goto unlock; - /* - * With HAPTICS_PATTERN module revision 2.0 and above, if use - * 1-byte write before 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 ((chip->ptn_revision >= HAP_PTN_V2) && - (num % HAP_PTN_V2_FIFO_DIN_NUM)) - num -= (num % HAP_PTN_V2_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_V2_FIFO_DIN_NUM); + else + num = samples_left; + rc = haptics_update_fifo_samples(chip, samples, num); if (rc < 0) { dev_err(chip->dev, "Update FIFO samples failed, rc=%d\n",