Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 8d0283a3 authored by Fenglin Wu's avatar Fenglin Wu Committed by Gerrit - the friendly Code Review server
Browse files

input: qcom-hv-haptics: reset FIFO play logic when hBoost is busy



Currently, when waiting for hBoost ready times out, error code -EBUSY is
returned. In addition to that, reset the FIFO play logic so that the
following FIFO requests can still be served.

Meanwhile, add 100us before updating HAPTICS_EN for hBoost to have
enough time to handle its power transition as per the hardware
recommendation.

Change-Id: Iebfc98b589bda747e4c2b6fdf6ff78d2f46ece5d
Signed-off-by: default avatarFenglin Wu <quic_fenglinw@quicinc.com>
parent d6a2023c
Loading
Loading
Loading
Loading
+61 −38
Original line number Diff line number Diff line
// SPDX-License-Identifier: GPL-2.0-only
/*
 * Copyright (c) 2020-2021, The Linux Foundation. All rights reserved.
 * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved.
 */

#include <linux/atomic.h>
@@ -1919,10 +1920,17 @@ static int haptics_toggle_module_enable(struct haptics_chip *chip)
{
	int rc;

	/*
	 * Updating HAPTICS_EN would vote hBoost enable status. Add 100us
	 * delay before updating HAPTICS_EN for hBoost to have enough time
	 * to handle its power transition.
	 */
	usleep_range(100, 101);
	rc = haptics_module_enable(chip, false);
	if (rc < 0)
		return rc;

	usleep_range(100, 101);
	return haptics_module_enable(chip, true);
}

@@ -2374,6 +2382,46 @@ static u8 get_direct_play_max_amplitude(struct haptics_chip *chip)
	return (u8)amplitude;
}

static int haptics_stop_fifo_play(struct haptics_chip *chip)
{
	int rc;
	u8 val;

	if (atomic_read(&chip->play.fifo_status.is_busy) == 0) {
		dev_dbg(chip->dev, "FIFO playing is not in progress\n");
		return 0;
	}

	rc = haptics_enable_play(chip, false);
	if (rc < 0)
		return rc;

	/* restore FIFO play rate back to T_LRA */
	rc = haptics_set_fifo_playrate(chip, T_LRA);
	if (rc < 0)
		return rc;

	haptics_fifo_empty_irq_config(chip, false);
	kvfree(chip->custom_effect->fifo->samples);
	chip->custom_effect->fifo->samples = NULL;

	atomic_set(&chip->play.fifo_status.is_busy, 0);

	/*
	 * All other playing modes would use AUTO mode RC
	 * calibration except FIFO streaming mode, so restore
	 * back to AUTO RC calibration after FIFO playing.
	 */
	val = CAL_RC_CLK_AUTO_VAL << CAL_RC_CLK_SHIFT;
	rc = haptics_masked_write(chip, chip->cfg_addr_base,
			HAP_CFG_CAL_EN_REG, CAL_RC_CLK_MASK, val);
	if (rc < 0)
		return rc;

	dev_dbg(chip->dev, "stopped FIFO playing successfully\n");
	return 0;
}

static int haptics_upload_effect(struct input_dev *dev,
		struct ff_effect *effect, struct ff_effect *old)
{
@@ -2443,46 +2491,21 @@ static int haptics_upload_effect(struct input_dev *dev,
		return rc;
	}

	return haptics_wait_hboost_ready(chip);
}

static int haptics_stop_fifo_play(struct haptics_chip *chip)
{
	int rc;
	u8 val;

	if (atomic_read(&chip->play.fifo_status.is_busy) == 0) {
		dev_dbg(chip->dev, "FIFO playing is not in progress\n");
		return 0;
	}

	rc = haptics_enable_play(chip, false);
	if (rc < 0)
		return rc;

	/* restore FIFO play rate back to T_LRA */
	rc = haptics_set_fifo_playrate(chip, T_LRA);
	if (rc < 0)
		return rc;

	haptics_fifo_empty_irq_config(chip, false);
	kvfree(chip->custom_effect->fifo->samples);
	chip->custom_effect->fifo->samples = NULL;

	atomic_set(&chip->play.fifo_status.is_busy, 0);

	rc = haptics_wait_hboost_ready(chip);
	if (rc < 0 && chip->play.pattern_src == FIFO) {
		/*
	 * All other playing modes would use AUTO mode RC
	 * calibration except FIFO streaming mode, so restore
	 * back to AUTO RC calibration after FIFO playing.
		 * Call haptics_stop_fifo_play(chip) explicitly if hBoost is
		 * not ready for the FIFO play. This drops current FIFO play
		 * but it restores the SW back to initial status so that the
		 * following FIFO play requests can still be served.
		 */
	val = CAL_RC_CLK_AUTO_VAL << CAL_RC_CLK_SHIFT;
	rc = haptics_masked_write(chip, chip->cfg_addr_base,
			HAP_CFG_CAL_EN_REG, CAL_RC_CLK_MASK, val);
	if (rc < 0)
		dev_dbg(chip->dev, "stop FIFO play explicitly to restore SW status\n");
		mutex_lock(&chip->play.lock);
		haptics_stop_fifo_play(chip);
		mutex_unlock(&chip->play.lock);
		return rc;
	}

	dev_dbg(chip->dev, "stopped FIFO playing successfully\n");
	return 0;
}