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

Commit c2cff697 authored by Linux Build Service Account's avatar Linux Build Service Account Committed by Gerrit - the friendly Code Review server
Browse files

Merge "input: qti-haptics: Add FF_GAIN capability support"

parents 7fbdbb12 d92ef74c
Loading
Loading
Loading
Loading
+9 −0
Original line number Diff line number Diff line
@@ -130,6 +130,15 @@ waveforms/effects:
		 [5:1]: waveform amplitude
		 [0]: reserved.

- qcom,wf-vmax-mv
  Usage:      optional
  Value type: <u32>
  Definition: Specifies the maximum allowed output voltage in millivolts
		for this effect. Value specified here will be rounded
		off to the closest multiple of 116 mV. Allowed values:
		0 to 3596. If this is not specified, the value defined in
		"qcom,vmax-mv" will be applied.

- qcom,wf-play-rate-us
  Usage:      optional
  Value type: <u32>
+68 −15
Original line number Diff line number Diff line
@@ -175,6 +175,7 @@ struct qti_hap_effect {
	u8			*pattern;
	int			pattern_length;
	u16			play_rate_us;
	u16			vmax_mv;
	u8			wf_repeat_n;
	u8			wf_s_repeat_n;
	u8			brake[HAP_BRAKE_PATTERN_MAX];
@@ -527,7 +528,6 @@ static int qti_haptics_config_brake(struct qti_hap_chip *chip, u8 *brake)
{
	u8 addr, mask, val;
	int i, rc;
	bool en = true;

	addr = REG_HAP_BRAKE;
	for (val = 0, i = 0; i < HAP_BRAKE_PATTERN_MAX; i++)
@@ -539,14 +539,12 @@ static int qti_haptics_config_brake(struct qti_hap_chip *chip, u8 *brake)
		dev_err(chip->dev, "write brake pattern failed, rc=%d\n", rc);
		return rc;
	}

	if (val == 0)
		en = false;

	/* Set BRAKE_EN only if brake pattern is non-zero */
	/*
	 * Set BRAKE_EN regardless of the brake pattern, this helps to stop
	 * playing immediately once the valid values in WF_Sx are played.
	 */
	addr = REG_HAP_EN_CTL2;
	mask = HAP_BRAKE_EN_BIT;
	val = en;
	val = mask = HAP_BRAKE_EN_BIT;
	rc = qti_haptics_masked_write(chip, addr, mask, val);
	if (rc < 0)
		dev_err(chip->dev, "set EN_CTL2 failed, rc=%d\n", rc);
@@ -579,6 +577,9 @@ static int qti_haptics_load_constant_waveform(struct qti_hap_chip *chip)
	if (rc < 0)
		return rc;

	rc = qti_haptics_config_play_rate_us(chip, config->play_rate_us);
	if (rc < 0)
		return rc;
	/*
	 * Using VMAX waveform source if playing length is >= 20ms,
	 * otherwise using buffer waveform source and calculate the
@@ -696,7 +697,6 @@ static irqreturn_t qti_haptics_play_irq_handler(int irq, void *data)
	dev_dbg(chip->dev, "play_irq triggered\n");
	if (play->playing_pos == effect->pattern_length) {
		dev_dbg(chip->dev, "waveform playing done\n");
		qti_haptics_play(chip, false);
		if (chip->play_irq_en) {
			disable_irq_nosync(chip->play_irq);
			chip->play_irq_en = false;
@@ -830,10 +830,6 @@ static int qti_haptics_upload_effect(struct input_dev *dev,
			goto disable_vdd;
		}

		level = effect->u.periodic.magnitude;
		tmp = level * config->vmax_mv;
		play->vmax_mv = tmp / 0x7fff;

		if (copy_from_user(data, effect->u.periodic.custom_data,
					sizeof(s16) * CUSTOM_DATA_LEN)) {
			rc = -EFAULT;
@@ -852,6 +848,10 @@ static int qti_haptics_upload_effect(struct input_dev *dev,
			goto disable_vdd;
		}

		level = effect->u.periodic.magnitude;
		tmp = level * chip->predefined[i].vmax_mv;
		play->vmax_mv = tmp / 0x7fff;

		dev_dbg(chip->dev, "upload effect %d, vmax_mv=%d\n",
				chip->predefined[i].id, play->vmax_mv);
		rc = qti_haptics_load_predefined_effect(chip, i);
@@ -918,6 +918,10 @@ static int qti_haptics_playback(struct input_dev *dev, int effect_id, int val)
				enable_irq(chip->play_irq);
				chip->play_irq_en = true;
			}
			/* Toggle PLAY when playing pattern */
			rc = qti_haptics_play(chip, false);
			if (rc < 0)
				return rc;
		} else {
			if (chip->play_irq_en) {
				disable_irq_nosync(chip->play_irq);
@@ -966,6 +970,22 @@ static int qti_haptics_erase(struct input_dev *dev, int effect_id)
	return rc;
}

static void qti_haptics_set_gain(struct input_dev *dev, u16 gain)
{
	struct qti_hap_chip *chip = input_get_drvdata(dev);
	struct qti_hap_config *config = &chip->config;
	struct qti_hap_play_info *play = &chip->play;

	if (gain == 0)
		return;

	if (gain > 0x7fff)
		gain = 0x7fff;

	play->vmax_mv = ((u32)(gain * config->vmax_mv)) / 0x7fff;
	qti_haptics_config_vmax(chip, play->vmax_mv);
}

static int qti_haptics_hw_init(struct qti_hap_chip *chip)
{
	struct qti_hap_config *config = &chip->config;
@@ -1092,7 +1112,7 @@ static int qti_haptics_parse_dt(struct qti_hap_chip *chip)
	struct device_node *child_node;
	struct qti_hap_effect *effect;
	const char *str;
	int rc = 0, tmp, i = 0, j;
	int rc = 0, tmp, i = 0, j, m;
	u8 val;

	rc = of_property_read_u32(node, "reg", &tmp);
@@ -1234,6 +1254,15 @@ static int qti_haptics_parse_dt(struct qti_hap_chip *chip)
			return rc;
		}

		effect->vmax_mv = config->vmax_mv;
		rc = of_property_read_u32(child_node, "qcom,wf-vmax-mv", &tmp);
		if (rc < 0)
			dev_dbg(chip->dev, "Read qcom,wf-vmax-mv failed, rc=%d\n",
					rc);
		else
			effect->vmax_mv = (tmp > HAP_VMAX_MV_MAX) ?
				HAP_VMAX_MV_MAX : tmp;

		rc = of_property_count_elems_of_size(child_node,
				"qcom,wf-pattern", sizeof(u8));
		if (rc < 0) {
@@ -1301,7 +1330,7 @@ static int qti_haptics_parse_dt(struct qti_hap_chip *chip)
			effect->wf_s_repeat_n = j;
		}

		effect->lra_auto_res_disable = of_property_read_bool(node,
		effect->lra_auto_res_disable = of_property_read_bool(child_node,
				"qcom,lra-auto-resonance-disable");

		tmp = of_property_count_elems_of_size(child_node,
@@ -1337,6 +1366,28 @@ static int qti_haptics_parse_dt(struct qti_hap_chip *chip)
		effect->brake_en = (val != 0);
	}

	for (j = 0; j < i; j++) {
		dev_dbg(chip->dev, "effect: %d\n", chip->predefined[j].id);
		dev_dbg(chip->dev, "        vmax: %d mv\n",
				chip->predefined[j].vmax_mv);
		dev_dbg(chip->dev, "        play_rate: %d us\n",
				chip->predefined[j].play_rate_us);
		for (m = 0; m < chip->predefined[j].pattern_length; m++)
			dev_dbg(chip->dev, "        pattern[%d]: 0x%x\n",
					m, chip->predefined[j].pattern[m]);
		for (m = 0; m < chip->predefined[j].brake_pattern_length; m++)
			dev_dbg(chip->dev, "        brake_pattern[%d]: 0x%x\n",
					m, chip->predefined[j].brake[m]);
		dev_dbg(chip->dev, "    brake_en: %d\n",
				chip->predefined[j].brake_en);
		dev_dbg(chip->dev, "    wf_repeat_n: %d\n",
				chip->predefined[j].wf_repeat_n);
		dev_dbg(chip->dev, "    wf_s_repeat_n: %d\n",
				chip->predefined[j].wf_s_repeat_n);
		dev_dbg(chip->dev, "    lra_auto_res_disable: %d\n",
				chip->predefined[j].lra_auto_res_disable);
	}

	return 0;
}

@@ -1404,6 +1455,7 @@ static int qti_haptics_probe(struct platform_device *pdev)
	chip->input_dev = input_dev;

	input_set_capability(input_dev, EV_FF, FF_CONSTANT);
	input_set_capability(input_dev, EV_FF, FF_GAIN);
	if (chip->effects_count != 0) {
		input_set_capability(input_dev, EV_FF, FF_PERIODIC);
		input_set_capability(input_dev, EV_FF, FF_CUSTOM);
@@ -1424,6 +1476,7 @@ static int qti_haptics_probe(struct platform_device *pdev)
	ff->upload = qti_haptics_upload_effect;
	ff->playback = qti_haptics_playback;
	ff->erase = qti_haptics_erase;
	ff->set_gain = qti_haptics_set_gain;

	rc = input_register_device(input_dev);
	if (rc < 0) {