Loading Documentation/devicetree/bindings/input/qti-haptics.txt +40 −26 Original line number Original line Diff line number Diff line Loading @@ -66,19 +66,6 @@ Properties: specified in the LRA actuator datasheet. Allowed values are: specified in the LRA actuator datasheet. Allowed values are: 0 to 20475. If this is not specified, 5715us play rate is used. 0 to 20475. If this is not specified, 5715us play rate is used. - qcom,brake-pattern Usage: optional Value type: <prop-encoded-array> Definition: Specifies the brake pattern with 4 elements used to enable the internal reverse braking. Allowed values for each element are: 0: no brake; 1: brake with (Vmax / 2) strength; 2: brake with Vmax strength; 3: brake with (2 * Vmax) strength; If this property is specified with an array of non-zero values, then the brake pattern is applied at the end of the playing waveform. - qcom,external-waveform-source - qcom,external-waveform-source Usage: optional Usage: optional Value type: <string> Value type: <string> Loading Loading @@ -108,11 +95,12 @@ Following properties are specific only when LRA actuator is used: values: "sine", "square". If this is not specified, sinusoid values: "sine", "square". If this is not specified, sinusoid resonance driver signal is used. resonance driver signal is used. - qcom,lra-auto-resonance-en - qcom,lra-allow-variable-play-rate Usage: optional Usage: optional Value type: <empty> Value type: <empty> Definition: If specified, the hardware feature of LRA auto resonance detection Definition: If specified, "qcom,wf-play-rate-us" for LRA defined in each is enabled for correcting the resonance frequency variation. effect could be different with the resonance period of the LRA actuator. - qcom,lra-auto-resonance-mode - qcom,lra-auto-resonance-mode Usage: optional Usage: optional Loading @@ -136,16 +124,20 @@ waveforms/effects: Usage: required Usage: required Value type: <prop-encoded-array> Value type: <prop-encoded-array> Definition: Specifies the waveform pattern in a byte array that will be Definition: Specifies the waveform pattern in a byte array that will be played for the effect-id. Allowed values for each element played for the effect-id. The bit fields of each byte are: are: 0x00 to 0x1F. [7]: drive direction, 0 - forward; 1 - reverse [6]: overdrive, 0 -- 1x drive; 1 -- 2x drive [5:1]: waveform amplitude [0]: reserved. - qcom,wf-play-rate-us - qcom,wf-play-rate-us Usage: optional Usage: optional Value type: <u32> Value type: <u32> Definition: Specifies the play period in microseconds for each byte pattern. Definition: Specifies the play period in microseconds for each byte pattern. For LRA actuator, For LRA, it should be set equal to the resonance Allowed values are: 0 to 20475. For LRA actuator, if period specified in the LRA actuator datasheet. Allowed values "qcom,lra-allow-variable-play-rate" is defined, it could be are: 0 to 20475. set to other values not equal to the resonance period of the LRA actuator. - qcom,wf-repeat-count - qcom,wf-repeat-count Usage: optional Usage: optional Loading @@ -159,6 +151,25 @@ waveforms/effects: Definition: Specifies the repeat times for each sample defined in Definition: Specifies the repeat times for each sample defined in qcom,wf-pattern. Allowed values are: 1, 2, 4, 8. qcom,wf-pattern. Allowed values are: 1, 2, 4, 8. - qcom,wf-brake-pattern Usage: optional Value type: <prop-encoded-array> Definition: Specifies the brake pattern with 4 elements used to enable the internal reverse braking. Allowed values for each element are: 0: no brake 1: brake with (Vmax / 2) strength 2: brake with Vmax strength 3: brake with (2 * Vmax) strength If this property is specified with an array of non-zero values, then the brake pattern is applied at the end of the playing waveform. - qcom,lra-auto-resonance-disable Usage: optional Value type: <empty> Definition: If specified, the hardware feature of LRA auto resonance detection is disabled. Example: Example: qcom,haptics@c000 { qcom,haptics@c000 { compatible = "qcom,haptics"; compatible = "qcom,haptics"; Loading @@ -169,20 +180,23 @@ Example: qcom,actuator-type = "lra"; qcom,actuator-type = "lra"; qcom,vmax-mv = <1800>; qcom,vmax-mv = <1800>; qcom,ilim-ma = <400>; qcom,ilim-ma = <400>; qcom,play-rate-us = <4255>; qcom,play-rate-us = <8000>; qcom,brake-pattern = [03 02 01 00]; qcom,lra-resonance-sig-shape = "sine"; qcom,lra-resonance-sig-shape = "sine"; qcom,lra-auto-resonance-mode; qcom,lra-auto-resonance-mode = "qwd"; qcom,lra-allow-variable-play-rate; wf_0 { wf_0 { /* CLICK effect */ /* CLICK effect */ qcom,effect-id = <0>; qcom,effect-id = <0>; qcom,wf-pattern = [0a 14 1f 1f 1f 1f 14 0a]; qcom,wf-play-rate-us = <6250>; qcom,wf-pattern = [3e 3e 3e]; qcom,lra-auto-resonance-disable; }; }; wf_5 { wf_5 { /* HEAVY_CLICK effect */ /* HEAVY_CLICK effect */ qcom,effect-id = <5>; qcom,effect-id = <5>; qcom,wf-pattern = [08 0a 1a 1f 1f 1a 0a 08]; qcom,wf-play-rate-us = <6250>; qcom,wf-pattern = [7e 7e 7e]; }; }; }; }; drivers/input/misc/qti-haptics.c +84 −55 Original line number Original line Diff line number Diff line Loading @@ -176,6 +176,10 @@ struct qti_hap_effect { u16 play_rate_us; u16 play_rate_us; u8 wf_repeat_n; u8 wf_repeat_n; u8 wf_s_repeat_n; u8 wf_s_repeat_n; u8 brake[HAP_BRAKE_PATTERN_MAX]; int brake_pattern_length; bool brake_en; bool lra_auto_res_disable; }; }; struct qti_hap_play_info { struct qti_hap_play_info { Loading @@ -194,9 +198,7 @@ struct qti_hap_config { u16 vmax_mv; u16 vmax_mv; u16 ilim_ma; u16 ilim_ma; u16 play_rate_us; u16 play_rate_us; u8 brake[HAP_BRAKE_PATTERN_MAX]; bool lra_allow_variable_play_rate; bool brake_en; bool lra_auto_res_en; bool use_ext_wf_src; bool use_ext_wf_src; }; }; Loading Loading @@ -550,6 +552,21 @@ static int qti_haptics_config_brake(struct qti_hap_chip *chip, u8 *brake) return rc; return rc; } } static int qti_haptics_lra_auto_res_enable(struct qti_hap_chip *chip, bool en) { int rc; u8 addr, val, mask; addr = REG_HAP_AUTO_RES_CTRL; mask = HAP_AUTO_RES_EN_BIT; val = en ? HAP_AUTO_RES_EN_BIT : 0; rc = qti_haptics_masked_write(chip, addr, mask, val); if (rc < 0) dev_err(chip->dev, "set AUTO_RES_CTRL failed, rc=%d\n", rc); return rc; } static int qti_haptics_load_constant_waveform(struct qti_hap_chip *chip) static int qti_haptics_load_constant_waveform(struct qti_hap_chip *chip) { { struct qti_hap_play_info *play = &chip->play; struct qti_hap_play_info *play = &chip->play; Loading @@ -571,6 +588,13 @@ static int qti_haptics_load_constant_waveform(struct qti_hap_chip *chip) if (rc < 0) if (rc < 0) return rc; return rc; /* Enable Auto-Resonance when VMAX wf-src is selected */ if (config->act_type == ACT_LRA) { rc = qti_haptics_lra_auto_res_enable(chip, true); if (rc < 0) return rc; } /* Set WF_SOURCE to VMAX */ /* Set WF_SOURCE to VMAX */ rc = qti_haptics_config_wf_src(chip, INT_WF_VMAX); rc = qti_haptics_config_wf_src(chip, INT_WF_VMAX); if (rc < 0) if (rc < 0) Loading Loading @@ -626,14 +650,22 @@ static int qti_haptics_load_predefined_effect(struct qti_hap_chip *chip, if (rc < 0) if (rc < 0) return rc; return rc; /* override play-rate for ERM here, no need for LRA */ rc = qti_haptics_config_play_rate_us(chip, play->effect->play_rate_us); if (config->act_type == ACT_ERM) { if (rc < 0) rc = qti_haptics_config_play_rate_us(chip, return rc; play->effect->play_rate_us); if (config->act_type == ACT_LRA) { rc = qti_haptics_lra_auto_res_enable(chip, !play->effect->lra_auto_res_disable); if (rc < 0) if (rc < 0) return rc; return rc; } } /* Set brake pattern in the effect */ rc = qti_haptics_config_brake(chip, play->effect->brake); if (rc < 0) return rc; rc = qti_haptics_config_wf_buffer(chip); rc = qti_haptics_config_wf_buffer(chip); if (rc < 0) if (rc < 0) return rc; return rc; Loading Loading @@ -736,16 +768,14 @@ static irqreturn_t qti_haptics_sc_irq_handler(int irq, void *data) static inline void get_play_length(struct qti_hap_play_info *play, static inline void get_play_length(struct qti_hap_play_info *play, int *length_us) int *length_us) { { struct qti_hap_chip *chip = container_of(play, struct qti_hap_chip, play); struct qti_hap_effect *effect = play->effect; struct qti_hap_effect *effect = play->effect; int tmp; int tmp; tmp = effect->pattern_length * effect->play_rate_us; tmp = effect->pattern_length * effect->play_rate_us; tmp *= wf_s_repeat[effect->wf_s_repeat_n]; tmp *= wf_s_repeat[effect->wf_s_repeat_n]; tmp *= wf_repeat[effect->wf_repeat_n]; tmp *= wf_repeat[effect->wf_repeat_n]; if (chip->config.brake_en) if (effect->brake_en) tmp += effect->play_rate_us * HAP_BRAKE_PATTERN_MAX; tmp += effect->play_rate_us * effect->brake_pattern_length; *length_us = tmp; *length_us = tmp; } } Loading Loading @@ -954,9 +984,8 @@ static int qti_haptics_hw_init(struct qti_hap_chip *chip) /* Set HAP_EN_CTL3 */ /* Set HAP_EN_CTL3 */ addr = REG_HAP_EN_CTL3; addr = REG_HAP_EN_CTL3; val = HAP_HBRIDGE_EN_BIT | HAP_PWM_SIGNAL_EN_BIT | HAP_ILIM_EN_BIT | val = HAP_HBRIDGE_EN_BIT | HAP_PWM_SIGNAL_EN_BIT | HAP_ILIM_EN_BIT | HAP_ILIM_CC_EN_BIT | HAP_DAC_EN_BIT | HAP_PWM_CTL_EN_BIT; HAP_ILIM_CC_EN_BIT | HAP_AUTO_RES_RBIAS_EN_BIT | if (config->act_type == ACT_LRA && config->lra_auto_res_en) HAP_DAC_EN_BIT | HAP_PWM_CTL_EN_BIT; val |= HAP_AUTO_RES_RBIAS_EN_BIT; rc = qti_haptics_write(chip, addr, &val, 1); rc = qti_haptics_write(chip, addr, &val, 1); if (rc < 0) { if (rc < 0) { dev_err(chip->dev, "set EN_CTL3 failed, rc=%d\n", rc); dev_err(chip->dev, "set EN_CTL3 failed, rc=%d\n", rc); Loading @@ -981,11 +1010,6 @@ static int qti_haptics_hw_init(struct qti_hap_chip *chip) if (rc < 0) if (rc < 0) return rc; return rc; /* Set default brake pattern */ rc = qti_haptics_config_brake(chip, config->brake); if (rc < 0) return rc; /* Set external waveform source if it's used */ /* Set external waveform source if it's used */ if (config->use_ext_wf_src) { if (config->use_ext_wf_src) { rc = qti_haptics_config_wf_src(chip, config->ext_src); rc = qti_haptics_config_wf_src(chip, config->ext_src); Loading @@ -1008,10 +1032,6 @@ static int qti_haptics_hw_init(struct qti_hap_chip *chip) return rc; return rc; } } /* Skip configurations below if auto-res-en is not set */ if (!config->lra_auto_res_en) return 0; addr = REG_HAP_AUTO_RES_CFG; addr = REG_HAP_AUTO_RES_CFG; mask = HAP_AUTO_RES_MODE_BIT | HAP_CAL_EOP_EN_BIT | HAP_CAL_PERIOD_MASK; mask = HAP_AUTO_RES_MODE_BIT | HAP_CAL_EOP_EN_BIT | HAP_CAL_PERIOD_MASK; val = config->lra_auto_res_mode << HAP_AUTO_RES_MODE_SHIFT; val = config->lra_auto_res_mode << HAP_AUTO_RES_MODE_SHIFT; Loading @@ -1023,8 +1043,9 @@ static int qti_haptics_hw_init(struct qti_hap_chip *chip) } } addr = REG_HAP_AUTO_RES_CTRL; addr = REG_HAP_AUTO_RES_CTRL; val = HAP_AUTO_RES_EN_BIT | HAP_SEL_AUTO_RES_PERIOD | AUTO_RES_EN_DLY(4) val = HAP_AUTO_RES_EN_BIT | HAP_SEL_AUTO_RES_PERIOD | | AUTO_RES_CNT_ERR_DELTA(2) | HAP_AUTO_RES_ERR_RECOVERY_BIT; AUTO_RES_CNT_ERR_DELTA(2) | HAP_AUTO_RES_ERR_RECOVERY_BIT | AUTO_RES_EN_DLY(4); rc = qti_haptics_write(chip, addr, &val, 1); rc = qti_haptics_write(chip, addr, &val, 1); if (rc < 0) { if (rc < 0) { dev_err(chip->dev, "set AUTO_RES_CTRL failed, rc=%d\n", dev_err(chip->dev, "set AUTO_RES_CTRL failed, rc=%d\n", Loading Loading @@ -1096,30 +1117,6 @@ static int qti_haptics_parse_dt(struct qti_hap_chip *chip) config->play_rate_us = (tmp >= HAP_PLAY_RATE_US_MAX) ? config->play_rate_us = (tmp >= HAP_PLAY_RATE_US_MAX) ? HAP_PLAY_RATE_US_MAX : tmp; HAP_PLAY_RATE_US_MAX : tmp; tmp = of_property_count_elems_of_size(node, "qcom,brake-pattern", sizeof(u8)); if (tmp > 0) { if (tmp != HAP_BRAKE_PATTERN_MAX) { dev_err(chip->dev, "brake-pattern should be %d bytes\n", HAP_BRAKE_PATTERN_MAX); return -EINVAL; } rc = of_property_read_u8_array(node, "qcom,brake-pattern", config->brake, HAP_BRAKE_PATTERN_MAX); if (rc < 0) { dev_err(chip->dev, "Failed to get brake-pattern, rc=%d\n", rc); return rc; } for (val = 0, j = 0; j < HAP_BRAKE_PATTERN_MAX; j++) val |= (config->brake[j] & HAP_BRAKE_PATTERN_MASK) << j * HAP_BRAKE_PATTERN_SHIFT; config->brake_en = (val != 0); } if (of_find_property(node, "qcom,external-waveform-source", NULL)) { if (of_find_property(node, "qcom,external-waveform-source", NULL)) { if (!of_property_read_string(node, if (!of_property_read_string(node, "qcom,external-waveform-source", &str)) { "qcom,external-waveform-source", &str)) { Loading Loading @@ -1162,8 +1159,8 @@ static int qti_haptics_parse_dt(struct qti_hap_chip *chip) } } } } config->lra_auto_res_en = of_property_read_bool(node, config->lra_allow_variable_play_rate = of_property_read_bool( "qcom,lra-auto-resonance-en"); node, "qcom,lra-allow-variable-play-rate"); config->lra_auto_res_mode = AUTO_RES_MODE_ZXD; config->lra_auto_res_mode = AUTO_RES_MODE_ZXD; rc = of_property_read_string(node, rc = of_property_read_string(node, Loading Loading @@ -1233,10 +1230,6 @@ static int qti_haptics_parse_dt(struct qti_hap_chip *chip) return rc; return rc; } } for (j = 0; j < effect->pattern_length; j++) effect->pattern[j] = effect->pattern[j] << HAP_WF_AMP_SHIFT; effect->play_rate_us = config->play_rate_us; effect->play_rate_us = config->play_rate_us; rc = of_property_read_u32(child_node, "qcom,wf-play-rate-us", rc = of_property_read_u32(child_node, "qcom,wf-play-rate-us", &tmp); &tmp); Loading @@ -1247,6 +1240,7 @@ static int qti_haptics_parse_dt(struct qti_hap_chip *chip) effect->play_rate_us = tmp; effect->play_rate_us = tmp; if (config->act_type == ACT_LRA && if (config->act_type == ACT_LRA && !config->lra_allow_variable_play_rate && config->play_rate_us != effect->play_rate_us) { config->play_rate_us != effect->play_rate_us) { dev_warn(chip->dev, "play rate should match with LRA resonance frequency\n"); dev_warn(chip->dev, "play rate should match with LRA resonance frequency\n"); effect->play_rate_us = config->play_rate_us; effect->play_rate_us = config->play_rate_us; Loading Loading @@ -1277,6 +1271,41 @@ static int qti_haptics_parse_dt(struct qti_hap_chip *chip) effect->wf_s_repeat_n = j; effect->wf_s_repeat_n = j; } } effect->lra_auto_res_disable = of_property_read_bool(node, "qcom,lra-auto-resonance-disable"); tmp = of_property_count_elems_of_size(child_node, "qcom,wf-brake-pattern", sizeof(u8)); if (tmp <= 0) continue; if (tmp > HAP_BRAKE_PATTERN_MAX) { dev_err(chip->dev, "wf-brake-pattern shouldn't be more than %d bytes\n", HAP_BRAKE_PATTERN_MAX); return -EINVAL; } rc = of_property_read_u8_array(child_node, "qcom,wf-brake-pattern", effect->brake, tmp); if (rc < 0) { dev_err(chip->dev, "Failed to get wf-brake-pattern, rc=%d\n", rc); return rc; } effect->brake_pattern_length = tmp; for (j = tmp - 1; j >= 0; j--) { if (effect->brake[j] != 0) break; effect->brake_pattern_length--; } for (val = 0, j = 0; j < effect->brake_pattern_length; j++) val |= (effect->brake[j] & HAP_BRAKE_PATTERN_MASK) << j * HAP_BRAKE_PATTERN_SHIFT; effect->brake_en = (val != 0); } } return 0; return 0; Loading Loading
Documentation/devicetree/bindings/input/qti-haptics.txt +40 −26 Original line number Original line Diff line number Diff line Loading @@ -66,19 +66,6 @@ Properties: specified in the LRA actuator datasheet. Allowed values are: specified in the LRA actuator datasheet. Allowed values are: 0 to 20475. If this is not specified, 5715us play rate is used. 0 to 20475. If this is not specified, 5715us play rate is used. - qcom,brake-pattern Usage: optional Value type: <prop-encoded-array> Definition: Specifies the brake pattern with 4 elements used to enable the internal reverse braking. Allowed values for each element are: 0: no brake; 1: brake with (Vmax / 2) strength; 2: brake with Vmax strength; 3: brake with (2 * Vmax) strength; If this property is specified with an array of non-zero values, then the brake pattern is applied at the end of the playing waveform. - qcom,external-waveform-source - qcom,external-waveform-source Usage: optional Usage: optional Value type: <string> Value type: <string> Loading Loading @@ -108,11 +95,12 @@ Following properties are specific only when LRA actuator is used: values: "sine", "square". If this is not specified, sinusoid values: "sine", "square". If this is not specified, sinusoid resonance driver signal is used. resonance driver signal is used. - qcom,lra-auto-resonance-en - qcom,lra-allow-variable-play-rate Usage: optional Usage: optional Value type: <empty> Value type: <empty> Definition: If specified, the hardware feature of LRA auto resonance detection Definition: If specified, "qcom,wf-play-rate-us" for LRA defined in each is enabled for correcting the resonance frequency variation. effect could be different with the resonance period of the LRA actuator. - qcom,lra-auto-resonance-mode - qcom,lra-auto-resonance-mode Usage: optional Usage: optional Loading @@ -136,16 +124,20 @@ waveforms/effects: Usage: required Usage: required Value type: <prop-encoded-array> Value type: <prop-encoded-array> Definition: Specifies the waveform pattern in a byte array that will be Definition: Specifies the waveform pattern in a byte array that will be played for the effect-id. Allowed values for each element played for the effect-id. The bit fields of each byte are: are: 0x00 to 0x1F. [7]: drive direction, 0 - forward; 1 - reverse [6]: overdrive, 0 -- 1x drive; 1 -- 2x drive [5:1]: waveform amplitude [0]: reserved. - qcom,wf-play-rate-us - qcom,wf-play-rate-us Usage: optional Usage: optional Value type: <u32> Value type: <u32> Definition: Specifies the play period in microseconds for each byte pattern. Definition: Specifies the play period in microseconds for each byte pattern. For LRA actuator, For LRA, it should be set equal to the resonance Allowed values are: 0 to 20475. For LRA actuator, if period specified in the LRA actuator datasheet. Allowed values "qcom,lra-allow-variable-play-rate" is defined, it could be are: 0 to 20475. set to other values not equal to the resonance period of the LRA actuator. - qcom,wf-repeat-count - qcom,wf-repeat-count Usage: optional Usage: optional Loading @@ -159,6 +151,25 @@ waveforms/effects: Definition: Specifies the repeat times for each sample defined in Definition: Specifies the repeat times for each sample defined in qcom,wf-pattern. Allowed values are: 1, 2, 4, 8. qcom,wf-pattern. Allowed values are: 1, 2, 4, 8. - qcom,wf-brake-pattern Usage: optional Value type: <prop-encoded-array> Definition: Specifies the brake pattern with 4 elements used to enable the internal reverse braking. Allowed values for each element are: 0: no brake 1: brake with (Vmax / 2) strength 2: brake with Vmax strength 3: brake with (2 * Vmax) strength If this property is specified with an array of non-zero values, then the brake pattern is applied at the end of the playing waveform. - qcom,lra-auto-resonance-disable Usage: optional Value type: <empty> Definition: If specified, the hardware feature of LRA auto resonance detection is disabled. Example: Example: qcom,haptics@c000 { qcom,haptics@c000 { compatible = "qcom,haptics"; compatible = "qcom,haptics"; Loading @@ -169,20 +180,23 @@ Example: qcom,actuator-type = "lra"; qcom,actuator-type = "lra"; qcom,vmax-mv = <1800>; qcom,vmax-mv = <1800>; qcom,ilim-ma = <400>; qcom,ilim-ma = <400>; qcom,play-rate-us = <4255>; qcom,play-rate-us = <8000>; qcom,brake-pattern = [03 02 01 00]; qcom,lra-resonance-sig-shape = "sine"; qcom,lra-resonance-sig-shape = "sine"; qcom,lra-auto-resonance-mode; qcom,lra-auto-resonance-mode = "qwd"; qcom,lra-allow-variable-play-rate; wf_0 { wf_0 { /* CLICK effect */ /* CLICK effect */ qcom,effect-id = <0>; qcom,effect-id = <0>; qcom,wf-pattern = [0a 14 1f 1f 1f 1f 14 0a]; qcom,wf-play-rate-us = <6250>; qcom,wf-pattern = [3e 3e 3e]; qcom,lra-auto-resonance-disable; }; }; wf_5 { wf_5 { /* HEAVY_CLICK effect */ /* HEAVY_CLICK effect */ qcom,effect-id = <5>; qcom,effect-id = <5>; qcom,wf-pattern = [08 0a 1a 1f 1f 1a 0a 08]; qcom,wf-play-rate-us = <6250>; qcom,wf-pattern = [7e 7e 7e]; }; }; }; };
drivers/input/misc/qti-haptics.c +84 −55 Original line number Original line Diff line number Diff line Loading @@ -176,6 +176,10 @@ struct qti_hap_effect { u16 play_rate_us; u16 play_rate_us; u8 wf_repeat_n; u8 wf_repeat_n; u8 wf_s_repeat_n; u8 wf_s_repeat_n; u8 brake[HAP_BRAKE_PATTERN_MAX]; int brake_pattern_length; bool brake_en; bool lra_auto_res_disable; }; }; struct qti_hap_play_info { struct qti_hap_play_info { Loading @@ -194,9 +198,7 @@ struct qti_hap_config { u16 vmax_mv; u16 vmax_mv; u16 ilim_ma; u16 ilim_ma; u16 play_rate_us; u16 play_rate_us; u8 brake[HAP_BRAKE_PATTERN_MAX]; bool lra_allow_variable_play_rate; bool brake_en; bool lra_auto_res_en; bool use_ext_wf_src; bool use_ext_wf_src; }; }; Loading Loading @@ -550,6 +552,21 @@ static int qti_haptics_config_brake(struct qti_hap_chip *chip, u8 *brake) return rc; return rc; } } static int qti_haptics_lra_auto_res_enable(struct qti_hap_chip *chip, bool en) { int rc; u8 addr, val, mask; addr = REG_HAP_AUTO_RES_CTRL; mask = HAP_AUTO_RES_EN_BIT; val = en ? HAP_AUTO_RES_EN_BIT : 0; rc = qti_haptics_masked_write(chip, addr, mask, val); if (rc < 0) dev_err(chip->dev, "set AUTO_RES_CTRL failed, rc=%d\n", rc); return rc; } static int qti_haptics_load_constant_waveform(struct qti_hap_chip *chip) static int qti_haptics_load_constant_waveform(struct qti_hap_chip *chip) { { struct qti_hap_play_info *play = &chip->play; struct qti_hap_play_info *play = &chip->play; Loading @@ -571,6 +588,13 @@ static int qti_haptics_load_constant_waveform(struct qti_hap_chip *chip) if (rc < 0) if (rc < 0) return rc; return rc; /* Enable Auto-Resonance when VMAX wf-src is selected */ if (config->act_type == ACT_LRA) { rc = qti_haptics_lra_auto_res_enable(chip, true); if (rc < 0) return rc; } /* Set WF_SOURCE to VMAX */ /* Set WF_SOURCE to VMAX */ rc = qti_haptics_config_wf_src(chip, INT_WF_VMAX); rc = qti_haptics_config_wf_src(chip, INT_WF_VMAX); if (rc < 0) if (rc < 0) Loading Loading @@ -626,14 +650,22 @@ static int qti_haptics_load_predefined_effect(struct qti_hap_chip *chip, if (rc < 0) if (rc < 0) return rc; return rc; /* override play-rate for ERM here, no need for LRA */ rc = qti_haptics_config_play_rate_us(chip, play->effect->play_rate_us); if (config->act_type == ACT_ERM) { if (rc < 0) rc = qti_haptics_config_play_rate_us(chip, return rc; play->effect->play_rate_us); if (config->act_type == ACT_LRA) { rc = qti_haptics_lra_auto_res_enable(chip, !play->effect->lra_auto_res_disable); if (rc < 0) if (rc < 0) return rc; return rc; } } /* Set brake pattern in the effect */ rc = qti_haptics_config_brake(chip, play->effect->brake); if (rc < 0) return rc; rc = qti_haptics_config_wf_buffer(chip); rc = qti_haptics_config_wf_buffer(chip); if (rc < 0) if (rc < 0) return rc; return rc; Loading Loading @@ -736,16 +768,14 @@ static irqreturn_t qti_haptics_sc_irq_handler(int irq, void *data) static inline void get_play_length(struct qti_hap_play_info *play, static inline void get_play_length(struct qti_hap_play_info *play, int *length_us) int *length_us) { { struct qti_hap_chip *chip = container_of(play, struct qti_hap_chip, play); struct qti_hap_effect *effect = play->effect; struct qti_hap_effect *effect = play->effect; int tmp; int tmp; tmp = effect->pattern_length * effect->play_rate_us; tmp = effect->pattern_length * effect->play_rate_us; tmp *= wf_s_repeat[effect->wf_s_repeat_n]; tmp *= wf_s_repeat[effect->wf_s_repeat_n]; tmp *= wf_repeat[effect->wf_repeat_n]; tmp *= wf_repeat[effect->wf_repeat_n]; if (chip->config.brake_en) if (effect->brake_en) tmp += effect->play_rate_us * HAP_BRAKE_PATTERN_MAX; tmp += effect->play_rate_us * effect->brake_pattern_length; *length_us = tmp; *length_us = tmp; } } Loading Loading @@ -954,9 +984,8 @@ static int qti_haptics_hw_init(struct qti_hap_chip *chip) /* Set HAP_EN_CTL3 */ /* Set HAP_EN_CTL3 */ addr = REG_HAP_EN_CTL3; addr = REG_HAP_EN_CTL3; val = HAP_HBRIDGE_EN_BIT | HAP_PWM_SIGNAL_EN_BIT | HAP_ILIM_EN_BIT | val = HAP_HBRIDGE_EN_BIT | HAP_PWM_SIGNAL_EN_BIT | HAP_ILIM_EN_BIT | HAP_ILIM_CC_EN_BIT | HAP_DAC_EN_BIT | HAP_PWM_CTL_EN_BIT; HAP_ILIM_CC_EN_BIT | HAP_AUTO_RES_RBIAS_EN_BIT | if (config->act_type == ACT_LRA && config->lra_auto_res_en) HAP_DAC_EN_BIT | HAP_PWM_CTL_EN_BIT; val |= HAP_AUTO_RES_RBIAS_EN_BIT; rc = qti_haptics_write(chip, addr, &val, 1); rc = qti_haptics_write(chip, addr, &val, 1); if (rc < 0) { if (rc < 0) { dev_err(chip->dev, "set EN_CTL3 failed, rc=%d\n", rc); dev_err(chip->dev, "set EN_CTL3 failed, rc=%d\n", rc); Loading @@ -981,11 +1010,6 @@ static int qti_haptics_hw_init(struct qti_hap_chip *chip) if (rc < 0) if (rc < 0) return rc; return rc; /* Set default brake pattern */ rc = qti_haptics_config_brake(chip, config->brake); if (rc < 0) return rc; /* Set external waveform source if it's used */ /* Set external waveform source if it's used */ if (config->use_ext_wf_src) { if (config->use_ext_wf_src) { rc = qti_haptics_config_wf_src(chip, config->ext_src); rc = qti_haptics_config_wf_src(chip, config->ext_src); Loading @@ -1008,10 +1032,6 @@ static int qti_haptics_hw_init(struct qti_hap_chip *chip) return rc; return rc; } } /* Skip configurations below if auto-res-en is not set */ if (!config->lra_auto_res_en) return 0; addr = REG_HAP_AUTO_RES_CFG; addr = REG_HAP_AUTO_RES_CFG; mask = HAP_AUTO_RES_MODE_BIT | HAP_CAL_EOP_EN_BIT | HAP_CAL_PERIOD_MASK; mask = HAP_AUTO_RES_MODE_BIT | HAP_CAL_EOP_EN_BIT | HAP_CAL_PERIOD_MASK; val = config->lra_auto_res_mode << HAP_AUTO_RES_MODE_SHIFT; val = config->lra_auto_res_mode << HAP_AUTO_RES_MODE_SHIFT; Loading @@ -1023,8 +1043,9 @@ static int qti_haptics_hw_init(struct qti_hap_chip *chip) } } addr = REG_HAP_AUTO_RES_CTRL; addr = REG_HAP_AUTO_RES_CTRL; val = HAP_AUTO_RES_EN_BIT | HAP_SEL_AUTO_RES_PERIOD | AUTO_RES_EN_DLY(4) val = HAP_AUTO_RES_EN_BIT | HAP_SEL_AUTO_RES_PERIOD | | AUTO_RES_CNT_ERR_DELTA(2) | HAP_AUTO_RES_ERR_RECOVERY_BIT; AUTO_RES_CNT_ERR_DELTA(2) | HAP_AUTO_RES_ERR_RECOVERY_BIT | AUTO_RES_EN_DLY(4); rc = qti_haptics_write(chip, addr, &val, 1); rc = qti_haptics_write(chip, addr, &val, 1); if (rc < 0) { if (rc < 0) { dev_err(chip->dev, "set AUTO_RES_CTRL failed, rc=%d\n", dev_err(chip->dev, "set AUTO_RES_CTRL failed, rc=%d\n", Loading Loading @@ -1096,30 +1117,6 @@ static int qti_haptics_parse_dt(struct qti_hap_chip *chip) config->play_rate_us = (tmp >= HAP_PLAY_RATE_US_MAX) ? config->play_rate_us = (tmp >= HAP_PLAY_RATE_US_MAX) ? HAP_PLAY_RATE_US_MAX : tmp; HAP_PLAY_RATE_US_MAX : tmp; tmp = of_property_count_elems_of_size(node, "qcom,brake-pattern", sizeof(u8)); if (tmp > 0) { if (tmp != HAP_BRAKE_PATTERN_MAX) { dev_err(chip->dev, "brake-pattern should be %d bytes\n", HAP_BRAKE_PATTERN_MAX); return -EINVAL; } rc = of_property_read_u8_array(node, "qcom,brake-pattern", config->brake, HAP_BRAKE_PATTERN_MAX); if (rc < 0) { dev_err(chip->dev, "Failed to get brake-pattern, rc=%d\n", rc); return rc; } for (val = 0, j = 0; j < HAP_BRAKE_PATTERN_MAX; j++) val |= (config->brake[j] & HAP_BRAKE_PATTERN_MASK) << j * HAP_BRAKE_PATTERN_SHIFT; config->brake_en = (val != 0); } if (of_find_property(node, "qcom,external-waveform-source", NULL)) { if (of_find_property(node, "qcom,external-waveform-source", NULL)) { if (!of_property_read_string(node, if (!of_property_read_string(node, "qcom,external-waveform-source", &str)) { "qcom,external-waveform-source", &str)) { Loading Loading @@ -1162,8 +1159,8 @@ static int qti_haptics_parse_dt(struct qti_hap_chip *chip) } } } } config->lra_auto_res_en = of_property_read_bool(node, config->lra_allow_variable_play_rate = of_property_read_bool( "qcom,lra-auto-resonance-en"); node, "qcom,lra-allow-variable-play-rate"); config->lra_auto_res_mode = AUTO_RES_MODE_ZXD; config->lra_auto_res_mode = AUTO_RES_MODE_ZXD; rc = of_property_read_string(node, rc = of_property_read_string(node, Loading Loading @@ -1233,10 +1230,6 @@ static int qti_haptics_parse_dt(struct qti_hap_chip *chip) return rc; return rc; } } for (j = 0; j < effect->pattern_length; j++) effect->pattern[j] = effect->pattern[j] << HAP_WF_AMP_SHIFT; effect->play_rate_us = config->play_rate_us; effect->play_rate_us = config->play_rate_us; rc = of_property_read_u32(child_node, "qcom,wf-play-rate-us", rc = of_property_read_u32(child_node, "qcom,wf-play-rate-us", &tmp); &tmp); Loading @@ -1247,6 +1240,7 @@ static int qti_haptics_parse_dt(struct qti_hap_chip *chip) effect->play_rate_us = tmp; effect->play_rate_us = tmp; if (config->act_type == ACT_LRA && if (config->act_type == ACT_LRA && !config->lra_allow_variable_play_rate && config->play_rate_us != effect->play_rate_us) { config->play_rate_us != effect->play_rate_us) { dev_warn(chip->dev, "play rate should match with LRA resonance frequency\n"); dev_warn(chip->dev, "play rate should match with LRA resonance frequency\n"); effect->play_rate_us = config->play_rate_us; effect->play_rate_us = config->play_rate_us; Loading Loading @@ -1277,6 +1271,41 @@ static int qti_haptics_parse_dt(struct qti_hap_chip *chip) effect->wf_s_repeat_n = j; effect->wf_s_repeat_n = j; } } effect->lra_auto_res_disable = of_property_read_bool(node, "qcom,lra-auto-resonance-disable"); tmp = of_property_count_elems_of_size(child_node, "qcom,wf-brake-pattern", sizeof(u8)); if (tmp <= 0) continue; if (tmp > HAP_BRAKE_PATTERN_MAX) { dev_err(chip->dev, "wf-brake-pattern shouldn't be more than %d bytes\n", HAP_BRAKE_PATTERN_MAX); return -EINVAL; } rc = of_property_read_u8_array(child_node, "qcom,wf-brake-pattern", effect->brake, tmp); if (rc < 0) { dev_err(chip->dev, "Failed to get wf-brake-pattern, rc=%d\n", rc); return rc; } effect->brake_pattern_length = tmp; for (j = tmp - 1; j >= 0; j--) { if (effect->brake[j] != 0) break; effect->brake_pattern_length--; } for (val = 0, j = 0; j < effect->brake_pattern_length; j++) val |= (effect->brake[j] & HAP_BRAKE_PATTERN_MASK) << j * HAP_BRAKE_PATTERN_SHIFT; effect->brake_en = (val != 0); } } return 0; return 0; Loading