Loading Documentation/devicetree/bindings/input/qti-haptics.txt +9 −0 Original line number Diff line number Diff line Loading @@ -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> Loading drivers/input/misc/qti-haptics.c +68 −15 Original line number Diff line number Diff line Loading @@ -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]; Loading Loading @@ -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++) Loading @@ -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); Loading Loading @@ -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 Loading Loading @@ -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; Loading Loading @@ -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; Loading @@ -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); Loading Loading @@ -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); Loading Loading @@ -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; Loading Loading @@ -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); Loading Loading @@ -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) { Loading Loading @@ -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, Loading Loading @@ -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; } Loading Loading @@ -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); Loading @@ -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) { Loading Loading
Documentation/devicetree/bindings/input/qti-haptics.txt +9 −0 Original line number Diff line number Diff line Loading @@ -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> Loading
drivers/input/misc/qti-haptics.c +68 −15 Original line number Diff line number Diff line Loading @@ -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]; Loading Loading @@ -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++) Loading @@ -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); Loading Loading @@ -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 Loading Loading @@ -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; Loading Loading @@ -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; Loading @@ -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); Loading Loading @@ -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); Loading Loading @@ -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; Loading Loading @@ -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); Loading Loading @@ -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) { Loading Loading @@ -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, Loading Loading @@ -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; } Loading Loading @@ -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); Loading @@ -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) { Loading