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

Commit cf23f612 authored by Fenglin Wu's avatar Fenglin Wu
Browse files

input: qcom-hv-haptics: update RC_CLK_CAL_COUNT calculation



RC_CLK_CAL_COUNT is the calibration count used in manual RC_CLK_CAL
mode when playing FIFO patterns. For haptics module in PM8350B 2.0,
there are new equations recommended to calculate RC_CLK_CAL_COUNT
based on CAL_TLRA_CL_STS and LAST_GOOD_TLRA_CL_STS status to achieve
better accuracy. Update the driver to support this.

Change-Id: I983c1b1f284006847549d2b3d23a0c1039f8b4c1
Signed-off-by: default avatarFenglin Wu <fenglinw@codeaurora.org>
parent 487ed773
Loading
Loading
Loading
Loading
+77 −28
Original line number Diff line number Diff line
@@ -411,6 +411,7 @@ struct haptics_hw_config {
	u32			cl_t_lra_us;
	u32			preload_effect;
	u32			fifo_empty_thresh;
	u16			rc_clk_cal_count;
	enum drv_sig_shape	drv_wf;
	bool			is_erm;
};
@@ -727,7 +728,7 @@ static int haptics_get_closeloop_lra_period_v1(
		struct haptics_chip *chip)
{
	struct haptics_hw_config *config = &chip->config;
	int rc;
	int rc, freq_diff, f_lra, cl_f_lra;
	u8 val[2];
	u32 tmp, step_ns;
	bool auto_res_cal_done;
@@ -761,7 +762,25 @@ static int haptics_get_closeloop_lra_period_v1(
	tmp = ((val[0] & CAL_TLRA_CL_STS_MSB_MASK) << 8) | val[1];
	config->cl_t_lra_us = (tmp * step_ns) / 1000;

	return haptics_adjust_lra_period(chip, &config->cl_t_lra_us);
	rc = haptics_adjust_lra_period(chip, &config->cl_t_lra_us);
	if (rc < 0)
		return rc;

	/* calculate RC_CLK_CAL_COUNT */
	if (!config->t_lra_us || !config->cl_t_lra_us)
		return -EINVAL;

	f_lra = USEC_PER_SEC / config->t_lra_us;
	if (!f_lra)
		return -EINVAL;

	cl_f_lra = USEC_PER_SEC / config->cl_t_lra_us;
	freq_diff = cl_f_lra - f_lra;

	/* RC_CLK_CAL_COUNT = 600*(1-(clk_adjustment/Fifo_pat_freq)) */
	config->rc_clk_cal_count = 600 - ((600 * freq_diff) / f_lra);

	return 0;
}

#define TLRA_AUTO_RES_ERR_NO_CAL_STEP_PSEC	1667000
@@ -822,12 +841,16 @@ static int haptics_get_closeloop_lra_period_v2(
	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);
		config->cl_t_lra_us = div_u64(tmp, 1000000);
	} else if (rc_clk_cal == CAL_RC_CLK_DISABLED_VAL && auto_res_done) {
		/*
		 * CAL_TLRA_CL_STS_NO_CAL = CAL_TLRA_CL_STS
		 * 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);
		config->cl_t_lra_us = div_u64(tmp, 1000000);
	} else if (rc_clk_cal == CAL_RC_CLK_AUTO_VAL && !auto_res_done) {
		/*
		 * CAL_TLRA_OL = CAL_TLRA_CL_STS;
@@ -842,9 +865,26 @@ 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",
				tlra_ol, tlra_cl_err_sts, cal_tlra_cl_sts);

		tmp = tlra_cl_err_sts * tlra_ol;
		tmp *= TLRA_AUTO_RES_ERR_AUTO_CAL_STEP_PSEC;
		tmp = div_u64(tmp, cal_tlra_cl_sts);
		config->cl_t_lra_us = div_u64(tmp, 1000000);

		/* calculate RC_CLK_CAL_COUNT */
		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)
		 */
		tmp = 360000;
		tmp *= cal_tlra_cl_sts * config->cl_t_lra_us;
		tmp = div_u64(tmp, tlra_ol);
		tmp = div_u64(tmp, 586);
		config->rc_clk_cal_count = div_u64(tmp, config->t_lra_us);
	} else if (rc_clk_cal == CAL_RC_CLK_AUTO_VAL && auto_res_done) {
		/*
		 * CAL_TLRA_CL_STS_W_CAL = CAL_TLRA_CL_STS;
@@ -873,17 +913,34 @@ 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",
				last_good_tlra_cl_sts, cal_tlra_cl_sts);

		tmp = last_good_tlra_cl_sts * last_good_tlra_cl_sts;
		tmp *= TLRA_AUTO_RES_AUTO_CAL_STEP_PSEC;
		tmp = div_u64(tmp, cal_tlra_cl_sts);
		config->cl_t_lra_us = div_u64(tmp, 1000000);

		/* calculate RC_CLK_CAL_COUNT */
		if (!config->t_lra_us || !config->cl_t_lra_us)
			return -EINVAL;

		/*
		 * 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)
		 */
		tmp = 360000;
		tmp *= cal_tlra_cl_sts * config->cl_t_lra_us;
		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);
	} else {
		dev_err(chip->dev, "Can't get close-loop LRA period in rc_clk_cal mode %u\n",
				rc_clk_cal);
		return -EINVAL;
	}

	config->cl_t_lra_us = div_u64(tmp, 1000000);

	return 0;
}

@@ -902,8 +959,9 @@ 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\n",
		chip->config.t_lra_us, chip->config.cl_t_lra_us);
	dev_dbg(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;
}

@@ -1259,26 +1317,17 @@ static int haptics_get_available_fifo_memory(struct haptics_chip *chip)
	return available;
}

static int haptics_adjust_rc_clk(struct haptics_chip *chip)
static int haptics_set_manual_rc_clk_cal(struct haptics_chip *chip)
{
	int rc, freq_diff, cal_count, f_lra, cl_f_lra;
	int rc;
	u16 cal_count = chip->config.rc_clk_cal_count;
	u8 val[2];

	if (!chip->config.t_lra_us || !chip->config.cl_t_lra_us)
		return -EINVAL;

	f_lra = USEC_PER_SEC / chip->config.t_lra_us;
	if (!f_lra)
		return -EINVAL;

	cl_f_lra = USEC_PER_SEC / chip->config.cl_t_lra_us;
	freq_diff = cl_f_lra - f_lra;

	/* RC_CLK_CAL_COUNT = 600*(1-(clk_adjustment/Fifo_pat_freq)) */
	cal_count = 600 - ((600 * freq_diff) / f_lra);
	dev_dbg(chip->dev, "RC clock calibration count:%#x\n", cal_count);
	if (cal_count == 0) {
		dev_dbg(chip->dev, "Ignore setting RC_CLK_CAL_COUNT\n");
		return 0;
	}

	/* Set FIFO pattern frequency adjustment */
	val[0] = (cal_count >> 8) & RC_CLK_CAL_COUNT_MSB_MASK;
	val[1] = cal_count & RC_CLK_CAL_COUNT_LSB_MASK;
	rc = haptics_write(chip, chip->cfg_addr_base,
@@ -1288,7 +1337,8 @@ static int haptics_adjust_rc_clk(struct haptics_chip *chip)

	val[0] = CAL_RC_CLK_MANUAL_VAL << CAL_RC_CLK_SHIFT;
	return haptics_masked_write(chip, chip->cfg_addr_base,
			HAP_CFG_CAL_EN_REG, CAL_RC_CLK_MASK, val[0]);
			HAP_CFG_CAL_EN_REG, CAL_RC_CLK_MASK,
			val[0]);
}

static int haptics_update_fifo_samples(struct haptics_chip *chip,
@@ -1384,13 +1434,11 @@ static int haptics_set_fifo(struct haptics_chip *chip, struct fifo_cfg *fifo)
		return rc;

	if (fifo->period_per_s >= F_8KHZ) {
		rc = haptics_adjust_rc_clk(chip);
		if (rc < 0) {
			dev_err(chip->dev, "RC CLK adjustment failed, rc=%d\n",
				rc);
		/* Set manual RC CLK CAL when playing FIFO */
		rc = haptics_set_manual_rc_clk_cal(chip);
		if (rc < 0)
			return rc;
	}
	}

	atomic_set(&status->written_done, 0);
	atomic_set(&status->cancelled, 0);
@@ -2055,6 +2103,7 @@ static int haptics_hw_init(struct haptics_chip *chip)
	if (rc < 0)
		return rc;

	/* get calibrated close loop period */
	rc = haptics_get_closeloop_lra_period(chip);
	if (rc < 0)
		return rc;