/* Copyright (c) 2014-2018, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and * only version 2 as published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. */ #define pr_fmt(fmt) "haptics: %s: " fmt, __func__ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include /* Register definitions */ #define HAP_STATUS_1_REG(chip) (chip->base + 0x0A) #define HAP_BUSY_BIT BIT(1) #define SC_FLAG_BIT BIT(3) #define AUTO_RES_ERROR_BIT BIT(4) #define HAP_LRA_AUTO_RES_LO_REG(chip) (chip->base + 0x0B) #define HAP_LRA_AUTO_RES_HI_REG(chip) (chip->base + 0x0C) #define HAP_INT_RT_STS_REG(chip) (chip->base + 0x10) #define SC_INT_RT_STS_BIT BIT(0) #define PLAY_INT_RT_STS_BIT BIT(1) #define HAP_EN_CTL_REG(chip) (chip->base + 0x46) #define HAP_EN_BIT BIT(7) #define HAP_EN_CTL2_REG(chip) (chip->base + 0x48) #define BRAKE_EN_BIT BIT(0) #define HAP_AUTO_RES_CTRL_REG(chip) (chip->base + 0x4B) #define AUTO_RES_EN_BIT BIT(7) #define AUTO_RES_ERR_RECOVERY_BIT BIT(3) #define HAP_CFG1_REG(chip) (chip->base + 0x4C) #define HAP_ACT_TYPE_MASK BIT(0) #define HAP_LRA 0 #define HAP_ERM 1 #define HAP_CFG2_REG(chip) (chip->base + 0x4D) #define HAP_WAVE_SINE 0 #define HAP_WAVE_SQUARE 1 #define HAP_LRA_RES_TYPE_MASK BIT(0) #define HAP_SEL_REG(chip) (chip->base + 0x4E) #define HAP_WF_SOURCE_MASK GENMASK(5, 4) #define HAP_WF_SOURCE_SHIFT 4 #define HAP_LRA_AUTO_RES_REG(chip) (chip->base + 0x4F) /* For pmi8998 */ #define LRA_AUTO_RES_MODE_MASK GENMASK(6, 4) #define LRA_AUTO_RES_MODE_SHIFT 4 #define LRA_HIGH_Z_MASK GENMASK(3, 2) #define LRA_HIGH_Z_SHIFT 2 #define LRA_RES_CAL_MASK GENMASK(1, 0) #define HAP_RES_CAL_PERIOD_MIN 4 #define HAP_RES_CAL_PERIOD_MAX 32 /* For pm660 */ #define PM660_AUTO_RES_MODE_BIT BIT(7) #define PM660_AUTO_RES_MODE_SHIFT 7 #define PM660_CAL_DURATION_MASK GENMASK(6, 5) #define PM660_CAL_DURATION_SHIFT 5 #define PM660_QWD_DRIVE_DURATION_BIT BIT(4) #define PM660_QWD_DRIVE_DURATION_SHIFT 4 #define PM660_CAL_EOP_BIT BIT(3) #define PM660_CAL_EOP_SHIFT 3 #define PM660_LRA_RES_CAL_MASK GENMASK(2, 0) #define HAP_PM660_RES_CAL_PERIOD_MAX 256 #define HAP_VMAX_CFG_REG(chip) (chip->base + 0x51) #define HAP_VMAX_OVD_BIT BIT(6) #define HAP_VMAX_MASK GENMASK(5, 1) #define HAP_VMAX_SHIFT 1 #define HAP_VMAX_MIN_MV 116 #define HAP_VMAX_MAX_MV 3596 #define HAP_ILIM_CFG_REG(chip) (chip->base + 0x52) #define HAP_ILIM_SEL_MASK BIT(0) #define HAP_ILIM_400_MA 0 #define HAP_ILIM_800_MA 1 #define HAP_SC_DEB_REG(chip) (chip->base + 0x53) #define HAP_SC_DEB_MASK GENMASK(2, 0) #define HAP_SC_DEB_CYCLES_MIN 0 #define HAP_DEF_SC_DEB_CYCLES 8 #define HAP_SC_DEB_CYCLES_MAX 32 #define HAP_RATE_CFG1_REG(chip) (chip->base + 0x54) #define HAP_RATE_CFG1_MASK GENMASK(7, 0) #define HAP_RATE_CFG2_REG(chip) (chip->base + 0x55) #define HAP_RATE_CFG2_MASK GENMASK(3, 0) /* Shift needed to convert drive period upper bits [11:8] */ #define HAP_RATE_CFG2_SHIFT 8 #define HAP_INT_PWM_REG(chip) (chip->base + 0x56) #define INT_PWM_FREQ_SEL_MASK GENMASK(1, 0) #define INT_PWM_FREQ_253_KHZ 0 #define INT_PWM_FREQ_505_KHZ 1 #define INT_PWM_FREQ_739_KHZ 2 #define INT_PWM_FREQ_1076_KHZ 3 #define HAP_EXT_PWM_REG(chip) (chip->base + 0x57) #define EXT_PWM_FREQ_SEL_MASK GENMASK(1, 0) #define EXT_PWM_FREQ_25_KHZ 0 #define EXT_PWM_FREQ_50_KHZ 1 #define EXT_PWM_FREQ_75_KHZ 2 #define EXT_PWM_FREQ_100_KHZ 3 #define HAP_PWM_CAP_REG(chip) (chip->base + 0x58) #define HAP_SC_CLR_REG(chip) (chip->base + 0x59) #define SC_CLR_BIT BIT(0) #define HAP_BRAKE_REG(chip) (chip->base + 0x5C) #define HAP_BRAKE_PAT_MASK 0x3 #define HAP_WF_REPEAT_REG(chip) (chip->base + 0x5E) #define WF_REPEAT_MASK GENMASK(6, 4) #define WF_REPEAT_SHIFT 4 #define WF_REPEAT_MIN 1 #define WF_REPEAT_MAX 128 #define WF_S_REPEAT_MASK GENMASK(1, 0) #define WF_S_REPEAT_MIN 1 #define WF_S_REPEAT_MAX 8 #define HAP_WF_S1_REG(chip) (chip->base + 0x60) #define HAP_WF_SIGN_BIT BIT(7) #define HAP_WF_OVD_BIT BIT(6) #define HAP_WF_SAMP_MAX GENMASK(5, 1) #define HAP_WF_SAMPLE_LEN 8 #define HAP_PLAY_REG(chip) (chip->base + 0x70) #define PLAY_BIT BIT(7) #define PAUSE_BIT BIT(0) #define HAP_SEC_ACCESS_REG(chip) (chip->base + 0xD0) #define HAP_TEST2_REG(chip) (chip->base + 0xE3) #define HAP_EXT_PWM_DTEST_MASK GENMASK(6, 4) #define HAP_EXT_PWM_DTEST_SHIFT 4 #define PWM_MAX_DTEST_LINES 4 #define HAP_EXT_PWM_PEAK_DATA 0x7F #define HAP_EXT_PWM_HALF_DUTY 50 #define HAP_EXT_PWM_FULL_DUTY 100 #define HAP_EXT_PWM_DATA_FACTOR 39 /* Other definitions */ #define HAP_BRAKE_PAT_LEN 4 #define HAP_WAVE_SAMP_LEN 8 #define NUM_WF_SET 4 #define HAP_WAVE_SAMP_SET_LEN (HAP_WAVE_SAMP_LEN * NUM_WF_SET) #define HAP_RATE_CFG_STEP_US 5 #define HAP_WAVE_PLAY_RATE_US_MIN 0 #define HAP_DEF_WAVE_PLAY_RATE_US 5715 #define HAP_WAVE_PLAY_RATE_US_MAX 20475 #define HAP_MAX_PLAY_TIME_MS 15000 enum hap_brake_pat { NO_BRAKE = 0, BRAKE_VMAX_4, BRAKE_VMAX_2, BRAKE_VMAX, }; enum hap_auto_res_mode { HAP_AUTO_RES_NONE, HAP_AUTO_RES_ZXD, HAP_AUTO_RES_QWD, HAP_AUTO_RES_MAX_QWD, HAP_AUTO_RES_ZXD_EOP, }; enum hap_pm660_auto_res_mode { HAP_PM660_AUTO_RES_ZXD, HAP_PM660_AUTO_RES_QWD, }; /* high Z option lines */ enum hap_high_z { HAP_LRA_HIGH_Z_NONE, /* opt0 for PM660 */ HAP_LRA_HIGH_Z_OPT1, HAP_LRA_HIGH_Z_OPT2, HAP_LRA_HIGH_Z_OPT3, }; /* play modes */ enum hap_mode { HAP_DIRECT, HAP_BUFFER, HAP_AUDIO, HAP_PWM, }; /* wave/sample repeat */ enum hap_rep_type { HAP_WAVE_REPEAT = 1, HAP_WAVE_SAMP_REPEAT, }; /* status flags */ enum hap_status { AUTO_RESONANCE_ENABLED = BIT(0), }; enum hap_play_control { HAP_STOP, HAP_PAUSE, HAP_PLAY, }; /* pwm channel parameters */ struct pwm_param { struct pwm_device *pwm_dev; u32 duty_us; u32 period_us; }; /* * hap_lra_ares_param - Haptic auto_resonance parameters * @ lra_qwd_drive_duration - LRA QWD drive duration * @ calibrate_at_eop - Calibrate at EOP * @ lra_res_cal_period - LRA resonance calibration period * @ auto_res_mode - auto resonace mode * @ lra_high_z - high z option line */ struct hap_lra_ares_param { int lra_qwd_drive_duration; int calibrate_at_eop; enum hap_high_z lra_high_z; u16 lra_res_cal_period; u8 auto_res_mode; }; /* * hap_chip - Haptics data structure * @ pdev - platform device pointer * @ regmap - regmap pointer * @ bus_lock - spin lock for bus read/write * @ play_lock - mutex lock for haptics play/enable control * @ haptics_work - haptics worker * @ stop_timer - hrtimer for stopping haptics * @ auto_res_err_poll_timer - hrtimer for auto-resonance error * @ base - base address * @ play_irq - irq for play * @ sc_irq - irq for short circuit * @ pwm_data - pwm configuration * @ ares_cfg - auto resonance configuration * @ play_time_ms - play time set by the user in ms * @ max_play_time_ms - max play time in ms * @ vmax_mv - max voltage in mv * @ ilim_ma - limiting current in ma * @ sc_deb_cycles - short circuit debounce cycles * @ wave_play_rate_us - play rate for waveform * @ last_rate_cfg - Last rate config updated * @ wave_rep_cnt - waveform repeat count * @ wave_s_rep_cnt - waveform sample repeat count * @ wf_samp_len - waveform sample length * @ ext_pwm_freq_khz - external pwm frequency in KHz * @ ext_pwm_dtest_line - DTEST line for external pwm * @ status_flags - status * @ play_mode - play mode * @ act_type - actuator type * @ wave_shape - waveform shape * @ wave_samp_idx - wave sample id used to refer start of a sample set * @ wave_samp - array of wave samples * @ brake_pat - pattern for active breaking * @ en_brake - brake state * @ misc_clk_trim_error_reg - MISC clock trim error register if present * @ clk_trim_error_code - MISC clock trim error code * @ drive_period_code_max_limit - calculated drive period code with percentage variation on the higher side. * @ drive_period_code_min_limit - calculated drive period code with percentage variation on the lower side * @ drive_period_code_max_var_pct - maximum limit of percentage variation of drive period code * @ drive_period_code_min_var_pct - minimum limit of percentage variation of drive period code * @ last_sc_time - Last time short circuit was detected * @ sc_count - counter to determine the duration of short circuit condition * @ perm_disable - Flag to disable module permanently * @ state - current state of haptics * @ module_en - module enable status of haptics * @ lra_auto_mode - Auto mode selection * @ play_irq_en - Play interrupt enable status * @ auto_res_err_recovery_hw - Enable auto resonance error recovery by HW */ struct hap_chip { struct platform_device *pdev; struct regmap *regmap; struct pmic_revid_data *revid; struct led_classdev cdev; spinlock_t bus_lock; struct mutex play_lock; struct mutex param_lock; struct work_struct haptics_work; struct hrtimer stop_timer; struct hrtimer auto_res_err_poll_timer; u16 base; int play_irq; int sc_irq; struct pwm_param pwm_data; struct hap_lra_ares_param ares_cfg; u32 play_time_ms; u32 max_play_time_ms; u32 vmax_mv; u8 ilim_ma; u32 sc_deb_cycles; u32 wave_play_rate_us; u16 last_rate_cfg; u32 wave_rep_cnt; u32 wave_s_rep_cnt; u32 wf_samp_len; u32 ext_pwm_freq_khz; u8 ext_pwm_dtest_line; u32 status_flags; enum hap_mode play_mode; u8 act_type; u8 wave_shape; u8 wave_samp_idx; u32 wave_samp[HAP_WAVE_SAMP_SET_LEN]; u32 brake_pat[HAP_BRAKE_PAT_LEN]; bool en_brake; u32 misc_clk_trim_error_reg; u8 clk_trim_error_code; u16 drive_period_code_max_limit; u16 drive_period_code_min_limit; u8 drive_period_code_max_var_pct; u8 drive_period_code_min_var_pct; ktime_t last_sc_time; u8 sc_count; bool perm_disable; atomic_t state; bool module_en; bool lra_auto_mode; bool play_irq_en; bool auto_res_err_recovery_hw; }; static int qpnp_haptics_parse_buffer_dt(struct hap_chip *chip); static int qpnp_haptics_parse_pwm_dt(struct hap_chip *chip); static int qpnp_haptics_read_reg(struct hap_chip *chip, u16 addr, u8 *val, int len) { int rc; rc = regmap_bulk_read(chip->regmap, addr, val, len); if (rc < 0) pr_err("Error reading address: 0x%x - rc %d\n", addr, rc); return rc; } static inline bool is_secure(u16 addr) { return ((addr & 0xFF) > 0xD0); } static int qpnp_haptics_write_reg(struct hap_chip *chip, u16 addr, u8 *val, int len) { unsigned long flags; unsigned int unlock = 0xA5; int rc = 0, i; spin_lock_irqsave(&chip->bus_lock, flags); if (is_secure(addr)) { for (i = 0; i < len; i++) { rc = regmap_write(chip->regmap, HAP_SEC_ACCESS_REG(chip), unlock); if (rc < 0) { pr_err("Error writing unlock code - rc %d\n", rc); goto out; } rc = regmap_write(chip->regmap, addr + i, val[i]); if (rc < 0) { pr_err("Error writing address 0x%x - rc %d\n", addr + i, rc); goto out; } } } else { if (len > 1) rc = regmap_bulk_write(chip->regmap, addr, val, len); else rc = regmap_write(chip->regmap, addr, *val); } if (rc < 0) pr_err("Error writing address: 0x%x - rc %d\n", addr, rc); out: spin_unlock_irqrestore(&chip->bus_lock, flags); return rc; } static int qpnp_haptics_masked_write_reg(struct hap_chip *chip, u16 addr, u8 mask, u8 val) { unsigned long flags; unsigned int unlock = 0xA5; int rc; spin_lock_irqsave(&chip->bus_lock, flags); if (is_secure(addr)) { rc = regmap_write(chip->regmap, HAP_SEC_ACCESS_REG(chip), unlock); if (rc < 0) { pr_err("Error writing unlock code - rc %d\n", rc); goto out; } } rc = regmap_update_bits(chip->regmap, addr, mask, val); if (rc < 0) pr_err("Error writing address: 0x%x - rc %d\n", addr, rc); if (!rc) pr_debug("wrote to address 0x%x = 0x%x\n", addr, val); out: spin_unlock_irqrestore(&chip->bus_lock, flags); return rc; } static inline int get_buffer_mode_duration(struct hap_chip *chip) { int sample_count, sample_duration; sample_count = chip->wave_rep_cnt * chip->wave_s_rep_cnt * chip->wf_samp_len; sample_duration = sample_count * chip->wave_play_rate_us; pr_debug("sample_count: %d sample_duration: %d\n", sample_count, sample_duration); return (sample_duration / 1000); } static bool is_sw_lra_auto_resonance_control(struct hap_chip *chip) { if (chip->act_type != HAP_LRA) return false; if (chip->auto_res_err_recovery_hw) return false; /* * For short pattern in auto mode, we use buffer mode and auto * resonance is not needed. */ if (chip->lra_auto_mode && chip->play_mode == HAP_BUFFER) return false; return true; } #define HAPTICS_BACK_EMF_DELAY_US 20000 static int qpnp_haptics_auto_res_enable(struct hap_chip *chip, bool enable) { int rc = 0; u32 delay_us = HAPTICS_BACK_EMF_DELAY_US; u8 val; bool auto_res_mode_qwd; if (chip->act_type != HAP_LRA) return 0; if (chip->revid->pmic_subtype == PM660_SUBTYPE) auto_res_mode_qwd = (chip->ares_cfg.auto_res_mode == HAP_PM660_AUTO_RES_QWD); else auto_res_mode_qwd = (chip->ares_cfg.auto_res_mode == HAP_AUTO_RES_QWD); /* * Do not enable auto resonance if auto mode is enabled and auto * resonance mode is QWD, meaning long pattern. */ if (chip->lra_auto_mode && auto_res_mode_qwd && enable) { pr_debug("auto_mode enabled, not enabling auto_res\n"); return 0; } /* * For auto resonance detection to work properly, sufficient back-emf * has to be generated. In general, back-emf takes some time to build * up. When the auto resonance mode is chosen as QWD, high-z will be * applied for every LRA cycle and hence there won't be enough back-emf * at the start-up. Hence, the motor needs to vibrate for few LRA cycles * after the PLAY bit is asserted. Enable the auto resonance after * 'time_required_to_generate_back_emf_us' is completed. */ if (auto_res_mode_qwd && enable) usleep_range(delay_us, delay_us + 1); val = enable ? AUTO_RES_EN_BIT : 0; if (chip->revid->pmic_subtype == PM660_SUBTYPE) rc = qpnp_haptics_masked_write_reg(chip, HAP_AUTO_RES_CTRL_REG(chip), AUTO_RES_EN_BIT, val); else rc = qpnp_haptics_masked_write_reg(chip, HAP_TEST2_REG(chip), AUTO_RES_EN_BIT, val); if (rc < 0) return rc; if (enable) chip->status_flags |= AUTO_RESONANCE_ENABLED; else chip->status_flags &= ~AUTO_RESONANCE_ENABLED; pr_debug("auto_res %sabled\n", enable ? "en" : "dis"); return rc; } static int qpnp_haptics_update_rate_cfg(struct hap_chip *chip, u16 play_rate) { int rc; u8 val[2]; if (chip->last_rate_cfg == play_rate) { pr_debug("Same rate_cfg %x\n", play_rate); return 0; } val[0] = play_rate & HAP_RATE_CFG1_MASK; val[1] = (play_rate >> HAP_RATE_CFG2_SHIFT) & HAP_RATE_CFG2_MASK; rc = qpnp_haptics_write_reg(chip, HAP_RATE_CFG1_REG(chip), val, 2); if (rc < 0) return rc; pr_debug("Play rate code 0x%x\n", play_rate); chip->last_rate_cfg = play_rate; return 0; } static void qpnp_haptics_update_lra_frequency(struct hap_chip *chip) { u8 lra_auto_res[2], val; u32 play_rate_code; u16 rate_cfg; int rc; rc = qpnp_haptics_read_reg(chip, HAP_LRA_AUTO_RES_LO_REG(chip), lra_auto_res, 2); if (rc < 0) { pr_err("Error in reading LRA_AUTO_RES_LO/HI, rc=%d\n", rc); return; } play_rate_code = (lra_auto_res[1] & 0xF0) << 4 | (lra_auto_res[0] & 0xFF); pr_debug("lra_auto_res_lo = 0x%x lra_auto_res_hi = 0x%x play_rate_code = 0x%x\n", lra_auto_res[0], lra_auto_res[1], play_rate_code); rc = qpnp_haptics_read_reg(chip, HAP_STATUS_1_REG(chip), &val, 1); if (rc < 0) return; /* * If the drive period code read from AUTO_RES_LO and AUTO_RES_HI * registers is more than the max limit percent variation or less * than the min limit percent variation specified through DT, then * auto-resonance is disabled. */ if ((val & AUTO_RES_ERROR_BIT) || ((play_rate_code <= chip->drive_period_code_min_limit) || (play_rate_code >= chip->drive_period_code_max_limit))) { if (val & AUTO_RES_ERROR_BIT) pr_debug("Auto-resonance error %x\n", val); else pr_debug("play rate %x out of bounds [min: 0x%x, max: 0x%x]\n", play_rate_code, chip->drive_period_code_min_limit, chip->drive_period_code_max_limit); rc = qpnp_haptics_auto_res_enable(chip, false); if (rc < 0) pr_debug("Auto-resonance disable failed\n"); return; } /* * bits[7:4] of AUTO_RES_HI should be written to bits[3:0] of RATE_CFG2 */ lra_auto_res[1] >>= 4; rate_cfg = lra_auto_res[1] << 8 | lra_auto_res[0]; rc = qpnp_haptics_update_rate_cfg(chip, rate_cfg); if (rc < 0) pr_debug("Error in updating rate_cfg\n"); } #define MAX_RETRIES 5 #define HAP_CYCLES 4 static bool is_haptics_idle(struct hap_chip *chip) { unsigned long wait_time_us; int rc, i; u8 val; rc = qpnp_haptics_read_reg(chip, HAP_STATUS_1_REG(chip), &val, 1); if (rc < 0) return false; if (!(val & HAP_BUSY_BIT)) return true; if (chip->play_time_ms <= 20) wait_time_us = chip->play_time_ms * 1000; else wait_time_us = chip->wave_play_rate_us * HAP_CYCLES; for (i = 0; i < MAX_RETRIES; i++) { /* wait for play_rate cycles */ usleep_range(wait_time_us, wait_time_us + 1); if (chip->play_mode == HAP_DIRECT || chip->play_mode == HAP_PWM) return true; rc = qpnp_haptics_read_reg(chip, HAP_STATUS_1_REG(chip), &val, 1); if (rc < 0) return false; if (!(val & HAP_BUSY_BIT)) return true; } if (i >= MAX_RETRIES && (val & HAP_BUSY_BIT)) { pr_debug("Haptics Busy after %d retries\n", i); return false; } return true; } static int qpnp_haptics_mod_enable(struct hap_chip *chip, bool enable) { u8 val; int rc; if (chip->module_en == enable) return 0; if (!enable) { if (!is_haptics_idle(chip)) pr_debug("Disabling module forcibly\n"); } val = enable ? HAP_EN_BIT : 0; rc = qpnp_haptics_write_reg(chip, HAP_EN_CTL_REG(chip), &val, 1); if (rc < 0) return rc; chip->module_en = enable; return 0; } static int qpnp_haptics_play_control(struct hap_chip *chip, enum hap_play_control ctrl) { u8 val; int rc; switch (ctrl) { case HAP_STOP: val = 0; break; case HAP_PAUSE: val = PAUSE_BIT; break; case HAP_PLAY: val = PLAY_BIT; break; default: return 0; } rc = qpnp_haptics_write_reg(chip, HAP_PLAY_REG(chip), &val, 1); if (rc < 0) { pr_err("Error in writing to PLAY_REG, rc=%d\n", rc); return rc; } pr_debug("haptics play ctrl: %d\n", ctrl); return rc; } #define AUTO_RES_ERR_POLL_TIME_NS (20 * NSEC_PER_MSEC) static int qpnp_haptics_play(struct hap_chip *chip, bool enable) { int rc = 0, time_ms = chip->play_time_ms; if (chip->perm_disable && enable) return 0; mutex_lock(&chip->play_lock); if (enable) { if (chip->play_mode == HAP_PWM) { rc = pwm_enable(chip->pwm_data.pwm_dev); if (rc < 0) { pr_err("Error in enabling PWM, rc=%d\n", rc); goto out; } } rc = qpnp_haptics_auto_res_enable(chip, false); if (rc < 0) { pr_err("Error in disabling auto_res, rc=%d\n", rc); goto out; } rc = qpnp_haptics_mod_enable(chip, true); if (rc < 0) { pr_err("Error in enabling module, rc=%d\n", rc); goto out; } rc = qpnp_haptics_play_control(chip, HAP_PLAY); if (rc < 0) { pr_err("Error in enabling play, rc=%d\n", rc); goto out; } if (chip->play_mode == HAP_BUFFER) time_ms = get_buffer_mode_duration(chip); hrtimer_start(&chip->stop_timer, ktime_set(time_ms / MSEC_PER_SEC, (time_ms % MSEC_PER_SEC) * NSEC_PER_MSEC), HRTIMER_MODE_REL); rc = qpnp_haptics_auto_res_enable(chip, true); if (rc < 0) { pr_err("Error in enabling auto_res, rc=%d\n", rc); goto out; } if (is_sw_lra_auto_resonance_control(chip)) hrtimer_start(&chip->auto_res_err_poll_timer, ktime_set(0, AUTO_RES_ERR_POLL_TIME_NS), HRTIMER_MODE_REL); } else { rc = qpnp_haptics_play_control(chip, HAP_STOP); if (rc < 0) { pr_err("Error in disabling play, rc=%d\n", rc); goto out; } if (is_sw_lra_auto_resonance_control(chip)) { if (chip->status_flags & AUTO_RESONANCE_ENABLED) qpnp_haptics_update_lra_frequency(chip); hrtimer_cancel(&chip->auto_res_err_poll_timer); } if (chip->play_mode == HAP_PWM) pwm_disable(chip->pwm_data.pwm_dev); if (chip->play_mode == HAP_BUFFER) chip->wave_samp_idx = 0; } out: mutex_unlock(&chip->play_lock); return rc; } static void qpnp_haptics_work(struct work_struct *work) { struct hap_chip *chip = container_of(work, struct hap_chip, haptics_work); int rc; bool enable; enable = atomic_read(&chip->state); pr_debug("state: %d\n", enable); rc = qpnp_haptics_play(chip, enable); if (rc < 0) pr_err("Error in %sing haptics, rc=%d\n", enable ? "play" : "stopp", rc); } static enum hrtimer_restart hap_stop_timer(struct hrtimer *timer) { struct hap_chip *chip = container_of(timer, struct hap_chip, stop_timer); atomic_set(&chip->state, 0); schedule_work(&chip->haptics_work); return HRTIMER_NORESTART; } static enum hrtimer_restart hap_auto_res_err_poll_timer(struct hrtimer *timer) { struct hap_chip *chip = container_of(timer, struct hap_chip, auto_res_err_poll_timer); if (!(chip->status_flags & AUTO_RESONANCE_ENABLED)) return HRTIMER_NORESTART; qpnp_haptics_update_lra_frequency(chip); hrtimer_forward(&chip->auto_res_err_poll_timer, ktime_get(), ktime_set(0, AUTO_RES_ERR_POLL_TIME_NS)); return HRTIMER_NORESTART; } static int qpnp_haptics_suspend(struct device *dev) { struct hap_chip *chip = dev_get_drvdata(dev); int rc; rc = qpnp_haptics_play(chip, false); if (rc < 0) pr_err("Error in stopping haptics, rc=%d\n", rc); rc = qpnp_haptics_mod_enable(chip, false); if (rc < 0) pr_err("Error in disabling module, rc=%d\n", rc); return 0; } static int qpnp_haptics_wave_rep_config(struct hap_chip *chip, enum hap_rep_type type) { int rc; u8 val = 0, mask = 0; if (type & HAP_WAVE_REPEAT) { if (chip->wave_rep_cnt < WF_REPEAT_MIN) chip->wave_rep_cnt = WF_REPEAT_MIN; else if (chip->wave_rep_cnt > WF_REPEAT_MAX) chip->wave_rep_cnt = WF_REPEAT_MAX; mask = WF_REPEAT_MASK; val = ilog2(chip->wave_rep_cnt) << WF_REPEAT_SHIFT; } if (type & HAP_WAVE_SAMP_REPEAT) { if (chip->wave_s_rep_cnt < WF_S_REPEAT_MIN) chip->wave_s_rep_cnt = WF_S_REPEAT_MIN; else if (chip->wave_s_rep_cnt > WF_S_REPEAT_MAX) chip->wave_s_rep_cnt = WF_S_REPEAT_MAX; mask |= WF_S_REPEAT_MASK; val |= ilog2(chip->wave_s_rep_cnt); } rc = qpnp_haptics_masked_write_reg(chip, HAP_WF_REPEAT_REG(chip), mask, val); return rc; } /* configuration api for buffer mode */ static int qpnp_haptics_buffer_config(struct hap_chip *chip, u32 *wave_samp, bool overdrive) { u8 buf[HAP_WAVE_SAMP_LEN]; u32 *ptr; int rc, i; if (wave_samp) { ptr = wave_samp; } else { if (chip->wave_samp_idx >= ARRAY_SIZE(chip->wave_samp)) { pr_err("Incorrect wave_samp_idx %d\n", chip->wave_samp_idx); return -EINVAL; } ptr = &chip->wave_samp[chip->wave_samp_idx]; } /* Don't set override bit in waveform sample for PM660 */ if (chip->revid->pmic_subtype == PM660_SUBTYPE) overdrive = false; /* Configure WAVE_SAMPLE1 to WAVE_SAMPLE8 register */ for (i = 0; i < HAP_WAVE_SAMP_LEN; i++) { buf[i] = ptr[i]; if (buf[i]) buf[i] |= (overdrive ? HAP_WF_OVD_BIT : 0); } rc = qpnp_haptics_write_reg(chip, HAP_WF_S1_REG(chip), buf, HAP_WAVE_SAMP_LEN); return rc; } /* configuration api for pwm */ static int qpnp_haptics_pwm_config(struct hap_chip *chip) { u8 val = 0; int rc; if (chip->ext_pwm_freq_khz == 0) return 0; /* Configure the EXTERNAL_PWM register */ if (chip->ext_pwm_freq_khz <= EXT_PWM_FREQ_25_KHZ) { chip->ext_pwm_freq_khz = EXT_PWM_FREQ_25_KHZ; val = 0; } else if (chip->ext_pwm_freq_khz <= EXT_PWM_FREQ_50_KHZ) { chip->ext_pwm_freq_khz = EXT_PWM_FREQ_50_KHZ; val = 1; } else if (chip->ext_pwm_freq_khz <= EXT_PWM_FREQ_75_KHZ) { chip->ext_pwm_freq_khz = EXT_PWM_FREQ_75_KHZ; val = 2; } else { chip->ext_pwm_freq_khz = EXT_PWM_FREQ_100_KHZ; val = 3; } rc = qpnp_haptics_masked_write_reg(chip, HAP_EXT_PWM_REG(chip), EXT_PWM_FREQ_SEL_MASK, val); if (rc < 0) return rc; if (chip->ext_pwm_dtest_line < 0 || chip->ext_pwm_dtest_line > PWM_MAX_DTEST_LINES) { pr_err("invalid dtest line\n"); return -EINVAL; } if (chip->ext_pwm_dtest_line > 0) { /* disable auto res for PWM mode */ val = chip->ext_pwm_dtest_line << HAP_EXT_PWM_DTEST_SHIFT; rc = qpnp_haptics_masked_write_reg(chip, HAP_TEST2_REG(chip), HAP_EXT_PWM_DTEST_MASK | AUTO_RES_EN_BIT, val); if (rc < 0) return rc; } rc = pwm_config(chip->pwm_data.pwm_dev, chip->pwm_data.duty_us * NSEC_PER_USEC, chip->pwm_data.period_us * NSEC_PER_USEC); if (rc < 0) { pr_err("pwm_config failed, rc=%d\n", rc); return rc; } return 0; } static int qpnp_haptics_lra_auto_res_config(struct hap_chip *chip, struct hap_lra_ares_param *tmp_cfg) { struct hap_lra_ares_param *ares_cfg; int rc; u8 val = 0, mask = 0; /* disable auto resonance for ERM */ if (chip->act_type == HAP_ERM) { val = 0x00; rc = qpnp_haptics_write_reg(chip, HAP_LRA_AUTO_RES_REG(chip), &val, 1); return rc; } if (chip->auto_res_err_recovery_hw) { rc = qpnp_haptics_masked_write_reg(chip, HAP_AUTO_RES_CTRL_REG(chip), AUTO_RES_ERR_RECOVERY_BIT, AUTO_RES_ERR_RECOVERY_BIT); if (rc < 0) return rc; } if (tmp_cfg) ares_cfg = tmp_cfg; else ares_cfg = &chip->ares_cfg; if (ares_cfg->lra_res_cal_period < HAP_RES_CAL_PERIOD_MIN) ares_cfg->lra_res_cal_period = HAP_RES_CAL_PERIOD_MIN; if (chip->revid->pmic_subtype == PM660_SUBTYPE) { if (ares_cfg->lra_res_cal_period > HAP_PM660_RES_CAL_PERIOD_MAX) ares_cfg->lra_res_cal_period = HAP_PM660_RES_CAL_PERIOD_MAX; if (ares_cfg->auto_res_mode == HAP_PM660_AUTO_RES_QWD) ares_cfg->lra_res_cal_period = 0; if (ares_cfg->lra_res_cal_period) val = ilog2(ares_cfg->lra_res_cal_period / HAP_RES_CAL_PERIOD_MIN) + 1; } else { if (ares_cfg->lra_res_cal_period > HAP_RES_CAL_PERIOD_MAX) ares_cfg->lra_res_cal_period = HAP_RES_CAL_PERIOD_MAX; if (ares_cfg->lra_res_cal_period) val = ilog2(ares_cfg->lra_res_cal_period / HAP_RES_CAL_PERIOD_MIN); } if (chip->revid->pmic_subtype == PM660_SUBTYPE) { val |= ares_cfg->auto_res_mode << PM660_AUTO_RES_MODE_SHIFT; mask = PM660_AUTO_RES_MODE_BIT; val |= ares_cfg->lra_high_z << PM660_CAL_DURATION_SHIFT; mask |= PM660_CAL_DURATION_MASK; if (ares_cfg->lra_qwd_drive_duration != -EINVAL) { val |= ares_cfg->lra_qwd_drive_duration << PM660_QWD_DRIVE_DURATION_SHIFT; mask |= PM660_QWD_DRIVE_DURATION_BIT; } if (ares_cfg->calibrate_at_eop != -EINVAL) { val |= ares_cfg->calibrate_at_eop << PM660_CAL_EOP_SHIFT; mask |= PM660_CAL_EOP_BIT; } mask |= PM660_LRA_RES_CAL_MASK; } else { val |= (ares_cfg->auto_res_mode << LRA_AUTO_RES_MODE_SHIFT); val |= (ares_cfg->lra_high_z << LRA_HIGH_Z_SHIFT); mask = LRA_AUTO_RES_MODE_MASK | LRA_HIGH_Z_MASK | LRA_RES_CAL_MASK; } pr_debug("mode: %d hi_z period: %d cal_period: %d\n", ares_cfg->auto_res_mode, ares_cfg->lra_high_z, ares_cfg->lra_res_cal_period); rc = qpnp_haptics_masked_write_reg(chip, HAP_LRA_AUTO_RES_REG(chip), mask, val); return rc; } /* configuration api for play mode */ static int qpnp_haptics_play_mode_config(struct hap_chip *chip) { u8 val = 0; int rc; if (!is_haptics_idle(chip)) return -EBUSY; val = chip->play_mode << HAP_WF_SOURCE_SHIFT; rc = qpnp_haptics_masked_write_reg(chip, HAP_SEL_REG(chip), HAP_WF_SOURCE_MASK, val); if (!rc) { if (chip->play_mode == HAP_BUFFER && !chip->play_irq_en) { enable_irq(chip->play_irq); chip->play_irq_en = true; } else if (chip->play_mode != HAP_BUFFER && chip->play_irq_en) { disable_irq(chip->play_irq); chip->play_irq_en = false; } } return rc; } /* configuration api for max voltage */ static int qpnp_haptics_vmax_config(struct hap_chip *chip, int vmax_mv, bool overdrive) { u8 val = 0; int rc; if (vmax_mv < 0) return -EINVAL; /* Allow setting override bit in VMAX_CFG only for PM660 */ if (chip->revid->pmic_subtype != PM660_SUBTYPE) overdrive = false; if (vmax_mv < HAP_VMAX_MIN_MV) vmax_mv = HAP_VMAX_MIN_MV; else if (vmax_mv > HAP_VMAX_MAX_MV) vmax_mv = HAP_VMAX_MAX_MV; val = DIV_ROUND_CLOSEST(vmax_mv, HAP_VMAX_MIN_MV); val <<= HAP_VMAX_SHIFT; if (overdrive) val |= HAP_VMAX_OVD_BIT; rc = qpnp_haptics_masked_write_reg(chip, HAP_VMAX_CFG_REG(chip), HAP_VMAX_MASK | HAP_VMAX_OVD_BIT, val); return rc; } /* configuration api for ilim */ static int qpnp_haptics_ilim_config(struct hap_chip *chip) { int rc; if (chip->ilim_ma < HAP_ILIM_400_MA) chip->ilim_ma = HAP_ILIM_400_MA; else if (chip->ilim_ma > HAP_ILIM_800_MA) chip->ilim_ma = HAP_ILIM_800_MA; rc = qpnp_haptics_masked_write_reg(chip, HAP_ILIM_CFG_REG(chip), HAP_ILIM_SEL_MASK, chip->ilim_ma); return rc; } /* configuration api for short circuit debounce */ static int qpnp_haptics_sc_deb_config(struct hap_chip *chip) { u8 val = 0; int rc; if (chip->sc_deb_cycles < HAP_SC_DEB_CYCLES_MIN) chip->sc_deb_cycles = HAP_SC_DEB_CYCLES_MIN; else if (chip->sc_deb_cycles > HAP_SC_DEB_CYCLES_MAX) chip->sc_deb_cycles = HAP_SC_DEB_CYCLES_MAX; if (chip->sc_deb_cycles != HAP_SC_DEB_CYCLES_MIN) val = ilog2(chip->sc_deb_cycles / HAP_DEF_SC_DEB_CYCLES) + 1; else val = HAP_SC_DEB_CYCLES_MIN; rc = qpnp_haptics_masked_write_reg(chip, HAP_SC_DEB_REG(chip), HAP_SC_DEB_MASK, val); return rc; } static int qpnp_haptics_brake_config(struct hap_chip *chip, u32 *brake_pat) { int rc, i; u32 temp, *ptr; u8 val; /* Configure BRAKE register */ rc = qpnp_haptics_masked_write_reg(chip, HAP_EN_CTL2_REG(chip), BRAKE_EN_BIT, (u8)chip->en_brake); if (rc < 0) return rc; /* If braking is not enabled, skip configuring brake pattern */ if (!chip->en_brake) return 0; if (!brake_pat) ptr = chip->brake_pat; else ptr = brake_pat; for (i = HAP_BRAKE_PAT_LEN - 1, val = 0; i >= 0; i--) { ptr[i] &= HAP_BRAKE_PAT_MASK; temp = i << 1; val |= ptr[i] << temp; } rc = qpnp_haptics_write_reg(chip, HAP_BRAKE_REG(chip), &val, 1); if (rc < 0) return rc; return 0; } static int qpnp_haptics_auto_mode_config(struct hap_chip *chip, int time_ms) { struct hap_lra_ares_param ares_cfg; enum hap_mode old_play_mode; u8 old_ares_mode; u32 brake_pat[HAP_BRAKE_PAT_LEN] = {0}; u32 wave_samp[HAP_WAVE_SAMP_LEN] = {0}; int rc, vmax_mv; if (!chip->lra_auto_mode) return false; /* For now, this is for LRA only */ if (chip->act_type == HAP_ERM) return 0; old_ares_mode = chip->ares_cfg.auto_res_mode; old_play_mode = chip->play_mode; pr_debug("auto_mode, time_ms: %d\n", time_ms); if (time_ms <= 20) { wave_samp[0] = HAP_WF_SAMP_MAX; wave_samp[1] = HAP_WF_SAMP_MAX; chip->wf_samp_len = 2; if (time_ms > 15) { wave_samp[2] = HAP_WF_SAMP_MAX; chip->wf_samp_len = 3; } /* short pattern */ rc = qpnp_haptics_parse_buffer_dt(chip); if (!rc) { rc = qpnp_haptics_wave_rep_config(chip, HAP_WAVE_REPEAT | HAP_WAVE_SAMP_REPEAT); if (rc < 0) { pr_err("Error in configuring wave_rep config %d\n", rc); return rc; } rc = qpnp_haptics_buffer_config(chip, wave_samp, true); if (rc < 0) { pr_err("Error in configuring buffer mode %d\n", rc); return rc; } } ares_cfg.lra_high_z = HAP_LRA_HIGH_Z_OPT1; ares_cfg.lra_res_cal_period = HAP_RES_CAL_PERIOD_MIN; if (chip->revid->pmic_subtype == PM660_SUBTYPE) { ares_cfg.auto_res_mode = HAP_PM660_AUTO_RES_QWD; ares_cfg.lra_qwd_drive_duration = 0; ares_cfg.calibrate_at_eop = 0; } else { ares_cfg.auto_res_mode = HAP_AUTO_RES_ZXD_EOP; ares_cfg.lra_qwd_drive_duration = -EINVAL; ares_cfg.calibrate_at_eop = -EINVAL; } vmax_mv = HAP_VMAX_MAX_MV; rc = qpnp_haptics_vmax_config(chip, vmax_mv, true); if (rc < 0) return rc; /* enable play_irq for buffer mode */ if (chip->play_irq >= 0 && !chip->play_irq_en) { enable_irq(chip->play_irq); chip->play_irq_en = true; } brake_pat[0] = BRAKE_VMAX; chip->play_mode = HAP_BUFFER; chip->wave_shape = HAP_WAVE_SQUARE; } else { /* long pattern */ ares_cfg.lra_high_z = HAP_LRA_HIGH_Z_OPT1; if (chip->revid->pmic_subtype == PM660_SUBTYPE) { ares_cfg.auto_res_mode = HAP_PM660_AUTO_RES_ZXD; ares_cfg.lra_res_cal_period = HAP_PM660_RES_CAL_PERIOD_MAX; ares_cfg.lra_qwd_drive_duration = 0; ares_cfg.calibrate_at_eop = 1; } else { ares_cfg.auto_res_mode = HAP_AUTO_RES_QWD; ares_cfg.lra_res_cal_period = HAP_RES_CAL_PERIOD_MAX; ares_cfg.lra_qwd_drive_duration = -EINVAL; ares_cfg.calibrate_at_eop = -EINVAL; } vmax_mv = chip->vmax_mv; rc = qpnp_haptics_vmax_config(chip, vmax_mv, false); if (rc < 0) return rc; /* enable play_irq for direct mode */ if (chip->play_irq >= 0 && chip->play_irq_en) { disable_irq(chip->play_irq); chip->play_irq_en = false; } chip->play_mode = HAP_DIRECT; chip->wave_shape = HAP_WAVE_SINE; } chip->ares_cfg.auto_res_mode = ares_cfg.auto_res_mode; rc = qpnp_haptics_lra_auto_res_config(chip, &ares_cfg); if (rc < 0) { chip->ares_cfg.auto_res_mode = old_ares_mode; return rc; } rc = qpnp_haptics_play_mode_config(chip); if (rc < 0) { chip->play_mode = old_play_mode; return rc; } rc = qpnp_haptics_brake_config(chip, brake_pat); if (rc < 0) return rc; rc = qpnp_haptics_masked_write_reg(chip, HAP_CFG2_REG(chip), HAP_LRA_RES_TYPE_MASK, chip->wave_shape); if (rc < 0) return rc; return 0; } static irqreturn_t qpnp_haptics_play_irq_handler(int irq, void *data) { struct hap_chip *chip = data; int rc; if (chip->play_mode != HAP_BUFFER) goto irq_handled; if (chip->wave_samp[chip->wave_samp_idx + HAP_WAVE_SAMP_LEN] > 0) { chip->wave_samp_idx += HAP_WAVE_SAMP_LEN; if (chip->wave_samp_idx >= ARRAY_SIZE(chip->wave_samp)) { pr_debug("Samples over\n"); } else { pr_debug("moving to next sample set %d\n", chip->wave_samp_idx); /* Moving to next set of wave sample */ rc = qpnp_haptics_buffer_config(chip, NULL, false); if (rc < 0) { pr_err("Error in configuring buffer, rc=%d\n", rc); goto irq_handled; } } } irq_handled: return IRQ_HANDLED; } #define SC_MAX_COUNT 5 #define SC_COUNT_RST_DELAY_US 1000000 static irqreturn_t qpnp_haptics_sc_irq_handler(int irq, void *data) { struct hap_chip *chip = data; int rc; u8 val; s64 sc_delta_time_us; ktime_t temp; rc = qpnp_haptics_read_reg(chip, HAP_STATUS_1_REG(chip), &val, 1); if (rc < 0) goto irq_handled; if (!(val & SC_FLAG_BIT)) { chip->sc_count = 0; goto irq_handled; } pr_debug("SC irq fired\n"); temp = ktime_get(); sc_delta_time_us = ktime_us_delta(temp, chip->last_sc_time); chip->last_sc_time = temp; if (sc_delta_time_us > SC_COUNT_RST_DELAY_US) chip->sc_count = 0; else chip->sc_count++; val = SC_CLR_BIT; rc = qpnp_haptics_write_reg(chip, HAP_SC_CLR_REG(chip), &val, 1); if (rc < 0) { pr_err("Error in writing to SC_CLR_REG, rc=%d\n", rc); goto irq_handled; } /* Permanently disable module if SC condition persists */ if (chip->sc_count > SC_MAX_COUNT) { pr_crit("SC persists, permanently disabling haptics\n"); rc = qpnp_haptics_mod_enable(chip, false); if (rc < 0) { pr_err("Error in disabling module, rc=%d\n", rc); goto irq_handled; } chip->perm_disable = true; } irq_handled: return IRQ_HANDLED; } /* All sysfs show/store functions below */ #define HAP_STR_SIZE 128 static int parse_string(const char *in_buf, char *out_buf) { int i; if (snprintf(out_buf, HAP_STR_SIZE, "%s", in_buf) > HAP_STR_SIZE) return -EINVAL; for (i = 0; i < strlen(out_buf); i++) { if (out_buf[i] == ' ' || out_buf[i] == '\n' || out_buf[i] == '\t') { out_buf[i] = '\0'; break; } } return 0; } static ssize_t qpnp_haptics_show_state(struct device *dev, struct device_attribute *attr, char *buf) { struct led_classdev *cdev = dev_get_drvdata(dev); struct hap_chip *chip = container_of(cdev, struct hap_chip, cdev); return snprintf(buf, PAGE_SIZE, "%d\n", chip->module_en); } static ssize_t qpnp_haptics_store_state(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { /* At present, nothing to do with setting state */ return count; } static ssize_t qpnp_haptics_show_duration(struct device *dev, struct device_attribute *attr, char *buf) { struct led_classdev *cdev = dev_get_drvdata(dev); struct hap_chip *chip = container_of(cdev, struct hap_chip, cdev); ktime_t time_rem; s64 time_us = 0; if (hrtimer_active(&chip->stop_timer)) { time_rem = hrtimer_get_remaining(&chip->stop_timer); time_us = ktime_to_us(time_rem); } return snprintf(buf, PAGE_SIZE, "%lld\n", div_s64(time_us, 1000)); } static ssize_t qpnp_haptics_store_duration(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { struct led_classdev *cdev = dev_get_drvdata(dev); struct hap_chip *chip = container_of(cdev, struct hap_chip, cdev); u32 val; int rc; rc = kstrtouint(buf, 0, &val); if (rc < 0) return rc; /* setting 0 on duration is NOP for now */ if (val <= 0) return count; if (val > chip->max_play_time_ms) return -EINVAL; mutex_lock(&chip->param_lock); rc = qpnp_haptics_auto_mode_config(chip, val); if (rc < 0) { pr_err("Unable to do auto mode config\n"); mutex_unlock(&chip->param_lock); return rc; } chip->play_time_ms = val; mutex_unlock(&chip->param_lock); return count; } static ssize_t qpnp_haptics_show_activate(struct device *dev, struct device_attribute *attr, char *buf) { /* For now nothing to show */ return snprintf(buf, PAGE_SIZE, "%d\n", 0); } static ssize_t qpnp_haptics_store_activate(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { struct led_classdev *cdev = dev_get_drvdata(dev); struct hap_chip *chip = container_of(cdev, struct hap_chip, cdev); u32 val; int rc; rc = kstrtouint(buf, 0, &val); if (rc < 0) return rc; if (val != 0 && val != 1) return count; if (val) { hrtimer_cancel(&chip->stop_timer); if (is_sw_lra_auto_resonance_control(chip)) hrtimer_cancel(&chip->auto_res_err_poll_timer); cancel_work_sync(&chip->haptics_work); atomic_set(&chip->state, 1); schedule_work(&chip->haptics_work); } else { rc = qpnp_haptics_mod_enable(chip, false); if (rc < 0) { pr_err("Error in disabling module, rc=%d\n", rc); return rc; } } return count; } static ssize_t qpnp_haptics_show_play_mode(struct device *dev, struct device_attribute *attr, char *buf) { struct led_classdev *cdev = dev_get_drvdata(dev); struct hap_chip *chip = container_of(cdev, struct hap_chip, cdev); char *str; if (chip->play_mode == HAP_BUFFER) str = "buffer"; else if (chip->play_mode == HAP_DIRECT) str = "direct"; else if (chip->play_mode == HAP_AUDIO) str = "audio"; else if (chip->play_mode == HAP_PWM) str = "pwm"; else return -EINVAL; return snprintf(buf, PAGE_SIZE, "%s\n", str); } static ssize_t qpnp_haptics_store_play_mode(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { struct led_classdev *cdev = dev_get_drvdata(dev); struct hap_chip *chip = container_of(cdev, struct hap_chip, cdev); char str[HAP_STR_SIZE + 1]; int rc = 0, temp, old_mode; rc = parse_string(buf, str); if (rc < 0) return rc; if (strcmp(str, "buffer") == 0) temp = HAP_BUFFER; else if (strcmp(str, "direct") == 0) temp = HAP_DIRECT; else if (strcmp(str, "audio") == 0) temp = HAP_AUDIO; else if (strcmp(str, "pwm") == 0) temp = HAP_PWM; else return -EINVAL; if (temp == chip->play_mode) return count; if (temp == HAP_BUFFER) { rc = qpnp_haptics_parse_buffer_dt(chip); if (!rc) { rc = qpnp_haptics_wave_rep_config(chip, HAP_WAVE_REPEAT | HAP_WAVE_SAMP_REPEAT); if (rc < 0) { pr_err("Error in configuring wave_rep config %d\n", rc); return rc; } } rc = qpnp_haptics_buffer_config(chip, NULL, true); } else if (temp == HAP_PWM) { rc = qpnp_haptics_parse_pwm_dt(chip); if (!rc) rc = qpnp_haptics_pwm_config(chip); } if (rc < 0) return rc; rc = qpnp_haptics_mod_enable(chip, false); if (rc < 0) return rc; old_mode = chip->play_mode; chip->play_mode = temp; rc = qpnp_haptics_play_mode_config(chip); if (rc < 0) { chip->play_mode = old_mode; return rc; } if (chip->play_mode == HAP_AUDIO) { rc = qpnp_haptics_mod_enable(chip, true); if (rc < 0) { chip->play_mode = old_mode; return rc; } } return count; } static ssize_t qpnp_haptics_show_wf_samp(struct device *dev, struct device_attribute *attr, char *buf) { struct led_classdev *cdev = dev_get_drvdata(dev); struct hap_chip *chip = container_of(cdev, struct hap_chip, cdev); char str[HAP_STR_SIZE + 1]; char *ptr = str; int i, len = 0; for (i = 0; i < ARRAY_SIZE(chip->wave_samp); i++) { len = scnprintf(ptr, HAP_STR_SIZE, "%x ", chip->wave_samp[i]); ptr += len; } ptr[len] = '\0'; return snprintf(buf, PAGE_SIZE, "%s\n", str); } static ssize_t qpnp_haptics_store_wf_samp(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { struct led_classdev *cdev = dev_get_drvdata(dev); struct hap_chip *chip = container_of(cdev, struct hap_chip, cdev); u8 samp[HAP_WAVE_SAMP_SET_LEN] = {0}; int bytes_read, rc; unsigned int data, pos = 0, i = 0; while (pos < count && i < ARRAY_SIZE(samp) && sscanf(buf + pos, "%x%n", &data, &bytes_read) == 1) { /* bit 0 is not used in WF_Sx */ samp[i++] = data & GENMASK(7, 1); pos += bytes_read; } chip->wf_samp_len = i; for (i = 0; i < ARRAY_SIZE(chip->wave_samp); i++) chip->wave_samp[i] = samp[i]; rc = qpnp_haptics_buffer_config(chip, NULL, false); if (rc < 0) { pr_err("Error in configuring buffer mode %d\n", rc); return rc; } return count; } static ssize_t qpnp_haptics_show_wf_rep_count(struct device *dev, struct device_attribute *attr, char *buf) { struct led_classdev *cdev = dev_get_drvdata(dev); struct hap_chip *chip = container_of(cdev, struct hap_chip, cdev); return snprintf(buf, PAGE_SIZE, "%d\n", chip->wave_rep_cnt); } static ssize_t qpnp_haptics_store_wf_rep_count(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { struct led_classdev *cdev = dev_get_drvdata(dev); struct hap_chip *chip = container_of(cdev, struct hap_chip, cdev); int data, rc, old_wave_rep_cnt; rc = kstrtoint(buf, 10, &data); if (rc < 0) return rc; old_wave_rep_cnt = chip->wave_rep_cnt; chip->wave_rep_cnt = data; rc = qpnp_haptics_wave_rep_config(chip, HAP_WAVE_REPEAT); if (rc < 0) { chip->wave_rep_cnt = old_wave_rep_cnt; return rc; } return count; } static ssize_t qpnp_haptics_show_wf_s_rep_count(struct device *dev, struct device_attribute *attr, char *buf) { struct led_classdev *cdev = dev_get_drvdata(dev); struct hap_chip *chip = container_of(cdev, struct hap_chip, cdev); return snprintf(buf, PAGE_SIZE, "%d\n", chip->wave_s_rep_cnt); } static ssize_t qpnp_haptics_store_wf_s_rep_count(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { struct led_classdev *cdev = dev_get_drvdata(dev); struct hap_chip *chip = container_of(cdev, struct hap_chip, cdev); int data, rc, old_wave_s_rep_cnt; rc = kstrtoint(buf, 10, &data); if (rc < 0) return rc; old_wave_s_rep_cnt = chip->wave_s_rep_cnt; chip->wave_s_rep_cnt = data; rc = qpnp_haptics_wave_rep_config(chip, HAP_WAVE_SAMP_REPEAT); if (rc < 0) { chip->wave_s_rep_cnt = old_wave_s_rep_cnt; return rc; } return count; } static ssize_t qpnp_haptics_show_vmax(struct device *dev, struct device_attribute *attr, char *buf) { struct led_classdev *cdev = dev_get_drvdata(dev); struct hap_chip *chip = container_of(cdev, struct hap_chip, cdev); return snprintf(buf, PAGE_SIZE, "%d\n", chip->vmax_mv); } static ssize_t qpnp_haptics_store_vmax(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { struct led_classdev *cdev = dev_get_drvdata(dev); struct hap_chip *chip = container_of(cdev, struct hap_chip, cdev); int data, rc, old_vmax_mv; rc = kstrtoint(buf, 10, &data); if (rc < 0) return rc; old_vmax_mv = chip->vmax_mv; chip->vmax_mv = data; rc = qpnp_haptics_vmax_config(chip, chip->vmax_mv, false); if (rc < 0) { chip->vmax_mv = old_vmax_mv; return rc; } return count; } static ssize_t qpnp_haptics_show_lra_auto_mode(struct device *dev, struct device_attribute *attr, char *buf) { struct led_classdev *cdev = dev_get_drvdata(dev); struct hap_chip *chip = container_of(cdev, struct hap_chip, cdev); return snprintf(buf, PAGE_SIZE, "%d\n", chip->lra_auto_mode); } static ssize_t qpnp_haptics_store_lra_auto_mode(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { struct led_classdev *cdev = dev_get_drvdata(dev); struct hap_chip *chip = container_of(cdev, struct hap_chip, cdev); int rc, data; rc = kstrtoint(buf, 10, &data); if (rc < 0) return rc; if (data != 0 && data != 1) return count; chip->lra_auto_mode = !!data; return count; } static struct device_attribute qpnp_haptics_attrs[] = { __ATTR(state, 0664, qpnp_haptics_show_state, qpnp_haptics_store_state), __ATTR(duration, 0664, qpnp_haptics_show_duration, qpnp_haptics_store_duration), __ATTR(activate, 0664, qpnp_haptics_show_activate, qpnp_haptics_store_activate), __ATTR(play_mode, 0664, qpnp_haptics_show_play_mode, qpnp_haptics_store_play_mode), __ATTR(wf_samp, 0664, qpnp_haptics_show_wf_samp, qpnp_haptics_store_wf_samp), __ATTR(wf_rep_count, 0664, qpnp_haptics_show_wf_rep_count, qpnp_haptics_store_wf_rep_count), __ATTR(wf_s_rep_count, 0664, qpnp_haptics_show_wf_s_rep_count, qpnp_haptics_store_wf_s_rep_count), __ATTR(vmax_mv, 0664, qpnp_haptics_show_vmax, qpnp_haptics_store_vmax), __ATTR(lra_auto_mode, 0664, qpnp_haptics_show_lra_auto_mode, qpnp_haptics_store_lra_auto_mode), }; /* Dummy functions for brightness */ static enum led_brightness qpnp_haptics_brightness_get(struct led_classdev *cdev) { return 0; } static void qpnp_haptics_brightness_set(struct led_classdev *cdev, enum led_brightness level) { } static int qpnp_haptics_config(struct hap_chip *chip) { u8 rc_clk_err_deci_pct; u16 play_rate = 0; int rc; /* Configure the CFG1 register for actuator type */ rc = qpnp_haptics_masked_write_reg(chip, HAP_CFG1_REG(chip), HAP_ACT_TYPE_MASK, chip->act_type); if (rc < 0) return rc; /* Configure auto resonance parameters */ rc = qpnp_haptics_lra_auto_res_config(chip, NULL); if (rc < 0) return rc; /* Configure the PLAY MODE register */ rc = qpnp_haptics_play_mode_config(chip); if (rc < 0) return rc; /* Configure the VMAX register */ rc = qpnp_haptics_vmax_config(chip, chip->vmax_mv, false); if (rc < 0) return rc; /* Configure the ILIM register */ rc = qpnp_haptics_ilim_config(chip); if (rc < 0) return rc; /* Configure the short circuit debounce register */ rc = qpnp_haptics_sc_deb_config(chip); if (rc < 0) return rc; /* Configure the WAVE SHAPE register */ rc = qpnp_haptics_masked_write_reg(chip, HAP_CFG2_REG(chip), HAP_LRA_RES_TYPE_MASK, chip->wave_shape); if (rc < 0) return rc; play_rate = chip->wave_play_rate_us / HAP_RATE_CFG_STEP_US; /* * The frequency of 19.2 MHz RC clock is subject to variation. Currently * some PMI chips have MISC_TRIM_ERROR_RC19P2_CLK register present in * MISC peripheral. This register holds the trim error of RC clock. */ if (chip->act_type == HAP_LRA && chip->misc_clk_trim_error_reg) { /* * Error is available in bits[3:0] and each LSB is 0.7%. * Bit 7 is the sign bit for error code. If it is set, then a * negative error correction needs to be made. Otherwise, a * positive error correction needs to be made. */ rc_clk_err_deci_pct = (chip->clk_trim_error_code & 0x0F) * 7; if (chip->clk_trim_error_code & BIT(7)) play_rate = (play_rate * (1000 - rc_clk_err_deci_pct)) / 1000; else play_rate = (play_rate * (1000 + rc_clk_err_deci_pct)) / 1000; pr_debug("TRIM register = 0x%x, play_rate=%d\n", chip->clk_trim_error_code, play_rate); } /* * Configure RATE_CFG1 and RATE_CFG2 registers. * Note: For ERM these registers act as play rate and * for LRA these represent resonance period */ rc = qpnp_haptics_update_rate_cfg(chip, play_rate); if (chip->act_type == HAP_LRA) { chip->drive_period_code_max_limit = (play_rate * (100 + chip->drive_period_code_max_var_pct)) / 100; chip->drive_period_code_min_limit = (play_rate * (100 - chip->drive_period_code_min_var_pct)) / 100; pr_debug("Drive period code max limit %x min limit %x\n", chip->drive_period_code_max_limit, chip->drive_period_code_min_limit); } rc = qpnp_haptics_brake_config(chip, NULL); if (rc < 0) return rc; if (chip->play_mode == HAP_BUFFER) { rc = qpnp_haptics_wave_rep_config(chip, HAP_WAVE_REPEAT | HAP_WAVE_SAMP_REPEAT); if (rc < 0) return rc; rc = qpnp_haptics_buffer_config(chip, NULL, false); } else if (chip->play_mode == HAP_PWM) { rc = qpnp_haptics_pwm_config(chip); } else if (chip->play_mode == HAP_AUDIO) { rc = qpnp_haptics_mod_enable(chip, true); } if (rc < 0) return rc; /* setup play irq */ if (chip->play_irq >= 0) { rc = devm_request_threaded_irq(&chip->pdev->dev, chip->play_irq, NULL, qpnp_haptics_play_irq_handler, IRQF_ONESHOT, "haptics_play_irq", chip); if (rc < 0) { pr_err("Unable to request play(%d) IRQ(err:%d)\n", chip->play_irq, rc); return rc; } /* use play_irq only for buffer mode */ if (chip->play_mode != HAP_BUFFER) { disable_irq(chip->play_irq); chip->play_irq_en = false; } } /* setup short circuit irq */ if (chip->sc_irq >= 0) { rc = devm_request_threaded_irq(&chip->pdev->dev, chip->sc_irq, NULL, qpnp_haptics_sc_irq_handler, IRQF_ONESHOT, "haptics_sc_irq", chip); if (rc < 0) { pr_err("Unable to request sc(%d) IRQ(err:%d)\n", chip->sc_irq, rc); return rc; } } return rc; } static int qpnp_haptics_parse_buffer_dt(struct hap_chip *chip) { struct device_node *node = chip->pdev->dev.of_node; u32 temp; int rc, i, wf_samp_len; if (chip->wave_rep_cnt > 0 || chip->wave_s_rep_cnt > 0) return 0; chip->wave_rep_cnt = WF_REPEAT_MIN; rc = of_property_read_u32(node, "qcom,wave-rep-cnt", &temp); if (!rc) { chip->wave_rep_cnt = temp; } else if (rc != -EINVAL) { pr_err("Unable to read rep cnt rc=%d\n", rc); return rc; } chip->wave_s_rep_cnt = WF_S_REPEAT_MIN; rc = of_property_read_u32(node, "qcom,wave-samp-rep-cnt", &temp); if (!rc) { chip->wave_s_rep_cnt = temp; } else if (rc != -EINVAL) { pr_err("Unable to read samp rep cnt rc=%d\n", rc); return rc; } wf_samp_len = of_property_count_elems_of_size(node, "qcom,wave-samples", sizeof(u32)); if (wf_samp_len > 0) { if (wf_samp_len > HAP_WAVE_SAMP_SET_LEN) { pr_err("Invalid length for wave samples\n"); return -EINVAL; } rc = of_property_read_u32_array(node, "qcom,wave-samples", chip->wave_samp, wf_samp_len); if (rc < 0) { pr_err("Error in reading qcom,wave-samples, rc=%d\n", rc); return rc; } } else { /* Use default values */ for (i = 0; i < HAP_WAVE_SAMP_LEN; i++) chip->wave_samp[i] = HAP_WF_SAMP_MAX; wf_samp_len = HAP_WAVE_SAMP_LEN; } chip->wf_samp_len = wf_samp_len; return 0; } static int qpnp_haptics_parse_pwm_dt(struct hap_chip *chip) { struct device_node *node = chip->pdev->dev.of_node; u32 temp; int rc; if (chip->pwm_data.period_us > 0 && chip->pwm_data.duty_us > 0) return 0; chip->pwm_data.pwm_dev = of_pwm_get(node, NULL); if (IS_ERR(chip->pwm_data.pwm_dev)) { rc = PTR_ERR(chip->pwm_data.pwm_dev); pr_err("Cannot get PWM device rc=%d\n", rc); chip->pwm_data.pwm_dev = NULL; return rc; } rc = of_property_read_u32(node, "qcom,period-us", &temp); if (!rc) { chip->pwm_data.period_us = temp; } else { pr_err("Cannot read PWM period rc=%d\n", rc); return rc; } rc = of_property_read_u32(node, "qcom,duty-us", &temp); if (!rc) { chip->pwm_data.duty_us = temp; } else { pr_err("Cannot read PWM duty rc=%d\n", rc); return rc; } rc = of_property_read_u32(node, "qcom,ext-pwm-dtest-line", &temp); if (!rc) chip->ext_pwm_dtest_line = temp; rc = of_property_read_u32(node, "qcom,ext-pwm-freq-khz", &temp); if (!rc) { chip->ext_pwm_freq_khz = temp; } else if (rc != -EINVAL) { pr_err("Unable to read ext pwm freq rc=%d\n", rc); return rc; } return 0; } static int qpnp_haptics_parse_dt(struct hap_chip *chip) { struct device_node *node = chip->pdev->dev.of_node; struct device_node *revid_node, *misc_node; const char *temp_str; int rc, temp; rc = of_property_read_u32(node, "reg", &temp); if (rc < 0) { pr_err("Couldn't find reg in node = %s rc = %d\n", node->full_name, rc); return rc; } if (temp <= 0) { pr_err("Invalid base address %x\n", temp); return -EINVAL; } chip->base = (u16)temp; revid_node = of_parse_phandle(node, "qcom,pmic-revid", 0); if (!revid_node) { pr_err("Missing qcom,pmic-revid property\n"); return -EINVAL; } chip->revid = get_revid_data(revid_node); of_node_put(revid_node); if (IS_ERR_OR_NULL(chip->revid)) { pr_err("Unable to get pmic_revid rc=%ld\n", PTR_ERR(chip->revid)); /* * the revid peripheral must be registered, any failure * here only indicates that the rev-id module has not * probed yet. */ return -EPROBE_DEFER; } if (of_find_property(node, "qcom,pmic-misc", NULL)) { misc_node = of_parse_phandle(node, "qcom,pmic-misc", 0); if (!misc_node) return -EINVAL; rc = of_property_read_u32(node, "qcom,misc-clk-trim-error-reg", &chip->misc_clk_trim_error_reg); if (rc < 0 || !chip->misc_clk_trim_error_reg) { pr_err("Invalid or missing misc-clk-trim-error-reg\n"); of_node_put(misc_node); return rc; } rc = qpnp_misc_read_reg(misc_node, chip->misc_clk_trim_error_reg, &chip->clk_trim_error_code); if (rc < 0) { pr_err("Couldn't get clk_trim_error_code, rc=%d\n", rc); of_node_put(misc_node); return -EPROBE_DEFER; } of_node_put(misc_node); } chip->play_irq = platform_get_irq_byname(chip->pdev, "hap-play-irq"); if (chip->play_irq < 0) { pr_err("Unable to get play irq\n"); return chip->play_irq; } chip->sc_irq = platform_get_irq_byname(chip->pdev, "hap-sc-irq"); if (chip->sc_irq < 0) { pr_err("Unable to get sc irq\n"); return chip->sc_irq; } chip->act_type = HAP_LRA; rc = of_property_read_u32(node, "qcom,actuator-type", &temp); if (!rc) { if (temp != HAP_LRA && temp != HAP_ERM) { pr_err("Incorrect actuator type\n"); return -EINVAL; } chip->act_type = temp; } chip->lra_auto_mode = of_property_read_bool(node, "qcom,lra-auto-mode"); rc = of_property_read_string(node, "qcom,play-mode", &temp_str); if (!rc) { if (strcmp(temp_str, "direct") == 0) chip->play_mode = HAP_DIRECT; else if (strcmp(temp_str, "buffer") == 0) chip->play_mode = HAP_BUFFER; else if (strcmp(temp_str, "pwm") == 0) chip->play_mode = HAP_PWM; else if (strcmp(temp_str, "audio") == 0) chip->play_mode = HAP_AUDIO; else { pr_err("Invalid play mode\n"); return -EINVAL; } } else { if (rc == -EINVAL && chip->act_type == HAP_LRA) { pr_info("Play mode not specified, using auto mode\n"); chip->lra_auto_mode = true; } else { pr_err("Unable to read play mode\n"); return rc; } } chip->max_play_time_ms = HAP_MAX_PLAY_TIME_MS; rc = of_property_read_u32(node, "qcom,max-play-time-ms", &temp); if (!rc) { chip->max_play_time_ms = temp; } else if (rc != -EINVAL) { pr_err("Unable to read max-play-time rc=%d\n", rc); return rc; } chip->vmax_mv = HAP_VMAX_MAX_MV; rc = of_property_read_u32(node, "qcom,vmax-mv", &temp); if (!rc) { chip->vmax_mv = temp; } else if (rc != -EINVAL) { pr_err("Unable to read Vmax rc=%d\n", rc); return rc; } chip->ilim_ma = HAP_ILIM_400_MA; rc = of_property_read_u32(node, "qcom,ilim-ma", &temp); if (!rc) { chip->ilim_ma = (u8)temp; } else if (rc != -EINVAL) { pr_err("Unable to read ILIM rc=%d\n", rc); return rc; } chip->sc_deb_cycles = HAP_DEF_SC_DEB_CYCLES; rc = of_property_read_u32(node, "qcom,sc-dbc-cycles", &temp); if (!rc) { chip->sc_deb_cycles = temp; } else if (rc != -EINVAL) { pr_err("Unable to read sc debounce rc=%d\n", rc); return rc; } chip->wave_shape = HAP_WAVE_SQUARE; rc = of_property_read_string(node, "qcom,wave-shape", &temp_str); if (!rc) { if (strcmp(temp_str, "sine") == 0) chip->wave_shape = HAP_WAVE_SINE; else if (strcmp(temp_str, "square") == 0) chip->wave_shape = HAP_WAVE_SQUARE; else { pr_err("Unsupported wave shape\n"); return -EINVAL; } } else if (rc != -EINVAL) { pr_err("Unable to read wave shape rc=%d\n", rc); return rc; } chip->wave_play_rate_us = HAP_DEF_WAVE_PLAY_RATE_US; rc = of_property_read_u32(node, "qcom,wave-play-rate-us", &temp); if (!rc) { chip->wave_play_rate_us = temp; } else if (rc != -EINVAL) { pr_err("Unable to read play rate rc=%d\n", rc); return rc; } if (chip->wave_play_rate_us < HAP_WAVE_PLAY_RATE_US_MIN) chip->wave_play_rate_us = HAP_WAVE_PLAY_RATE_US_MIN; else if (chip->wave_play_rate_us > HAP_WAVE_PLAY_RATE_US_MAX) chip->wave_play_rate_us = HAP_WAVE_PLAY_RATE_US_MAX; chip->en_brake = of_property_read_bool(node, "qcom,en-brake"); rc = of_property_count_elems_of_size(node, "qcom,brake-pattern", sizeof(u32)); if (rc > 0) { if (rc != HAP_BRAKE_PAT_LEN) { pr_err("Invalid length for brake pattern\n"); return -EINVAL; } rc = of_property_read_u32_array(node, "qcom,brake-pattern", chip->brake_pat, HAP_BRAKE_PAT_LEN); if (rc < 0) { pr_err("Error in reading qcom,brake-pattern, rc=%d\n", rc); return rc; } } /* Read the following properties only for LRA */ if (chip->act_type == HAP_LRA) { rc = of_property_read_string(node, "qcom,lra-auto-res-mode", &temp_str); if (!rc) { if (chip->revid->pmic_subtype == PM660_SUBTYPE) { chip->ares_cfg.auto_res_mode = HAP_PM660_AUTO_RES_QWD; if (strcmp(temp_str, "zxd") == 0) chip->ares_cfg.auto_res_mode = HAP_PM660_AUTO_RES_ZXD; else if (strcmp(temp_str, "qwd") == 0) chip->ares_cfg.auto_res_mode = HAP_PM660_AUTO_RES_QWD; } else { chip->ares_cfg.auto_res_mode = HAP_AUTO_RES_ZXD_EOP; if (strcmp(temp_str, "none") == 0) chip->ares_cfg.auto_res_mode = HAP_AUTO_RES_NONE; else if (strcmp(temp_str, "zxd") == 0) chip->ares_cfg.auto_res_mode = HAP_AUTO_RES_ZXD; else if (strcmp(temp_str, "qwd") == 0) chip->ares_cfg.auto_res_mode = HAP_AUTO_RES_QWD; else if (strcmp(temp_str, "max-qwd") == 0) chip->ares_cfg.auto_res_mode = HAP_AUTO_RES_MAX_QWD; else chip->ares_cfg.auto_res_mode = HAP_AUTO_RES_ZXD_EOP; } } else if (rc != -EINVAL) { pr_err("Unable to read auto res mode rc=%d\n", rc); return rc; } chip->ares_cfg.lra_high_z = HAP_LRA_HIGH_Z_OPT3; rc = of_property_read_string(node, "qcom,lra-high-z", &temp_str); if (!rc) { if (strcmp(temp_str, "none") == 0) chip->ares_cfg.lra_high_z = HAP_LRA_HIGH_Z_NONE; else if (strcmp(temp_str, "opt1") == 0) chip->ares_cfg.lra_high_z = HAP_LRA_HIGH_Z_OPT1; else if (strcmp(temp_str, "opt2") == 0) chip->ares_cfg.lra_high_z = HAP_LRA_HIGH_Z_OPT2; else chip->ares_cfg.lra_high_z = HAP_LRA_HIGH_Z_OPT3; if (chip->revid->pmic_subtype == PM660_SUBTYPE) { if (strcmp(temp_str, "opt0") == 0) chip->ares_cfg.lra_high_z = HAP_LRA_HIGH_Z_NONE; } } else if (rc != -EINVAL) { pr_err("Unable to read LRA high-z rc=%d\n", rc); return rc; } chip->ares_cfg.lra_res_cal_period = HAP_RES_CAL_PERIOD_MAX; rc = of_property_read_u32(node, "qcom,lra-res-cal-period", &temp); if (!rc) { chip->ares_cfg.lra_res_cal_period = temp; } else if (rc != -EINVAL) { pr_err("Unable to read cal period rc=%d\n", rc); return rc; } chip->ares_cfg.lra_qwd_drive_duration = -EINVAL; chip->ares_cfg.calibrate_at_eop = -EINVAL; if (chip->revid->pmic_subtype == PM660_SUBTYPE) { rc = of_property_read_u32(node, "qcom,lra-qwd-drive-duration", &chip->ares_cfg.lra_qwd_drive_duration); if (rc && rc != -EINVAL) { pr_err("Unable to read LRA QWD drive duration rc=%d\n", rc); return rc; } rc = of_property_read_u32(node, "qcom,lra-calibrate-at-eop", &chip->ares_cfg.calibrate_at_eop); if (rc && rc != -EINVAL) { pr_err("Unable to read Calibrate at EOP rc=%d\n", rc); return rc; } } chip->drive_period_code_max_var_pct = 25; rc = of_property_read_u32(node, "qcom,drive-period-code-max-variation-pct", &temp); if (!rc) { if (temp > 0 && temp < 100) chip->drive_period_code_max_var_pct = (u8)temp; } else if (rc != -EINVAL) { pr_err("Unable to read drive period code max var pct rc=%d\n", rc); return rc; } chip->drive_period_code_min_var_pct = 25; rc = of_property_read_u32(node, "qcom,drive-period-code-min-variation-pct", &temp); if (!rc) { if (temp > 0 && temp < 100) chip->drive_period_code_min_var_pct = (u8)temp; } else if (rc != -EINVAL) { pr_err("Unable to read drive period code min var pct rc=%d\n", rc); return rc; } chip->auto_res_err_recovery_hw = of_property_read_bool(node, "qcom,auto-res-err-recovery-hw"); if (chip->revid->pmic_subtype != PM660_SUBTYPE) chip->auto_res_err_recovery_hw = false; } if (rc == -EINVAL) rc = 0; if (chip->play_mode == HAP_BUFFER) rc = qpnp_haptics_parse_buffer_dt(chip); else if (chip->play_mode == HAP_PWM) rc = qpnp_haptics_parse_pwm_dt(chip); return rc; } static int qpnp_haptics_probe(struct platform_device *pdev) { struct hap_chip *chip; int rc, i; chip = devm_kzalloc(&pdev->dev, sizeof(*chip), GFP_KERNEL); if (!chip) return -ENOMEM; chip->regmap = dev_get_regmap(pdev->dev.parent, NULL); if (!chip->regmap) { dev_err(&pdev->dev, "Couldn't get parent's regmap\n"); return -EINVAL; } chip->pdev = pdev; rc = qpnp_haptics_parse_dt(chip); if (rc < 0) { dev_err(&pdev->dev, "Error in parsing DT parameters, rc=%d\n", rc); return rc; } spin_lock_init(&chip->bus_lock); mutex_init(&chip->play_lock); mutex_init(&chip->param_lock); INIT_WORK(&chip->haptics_work, qpnp_haptics_work); rc = qpnp_haptics_config(chip); if (rc < 0) { dev_err(&pdev->dev, "Error in configuring haptics, rc=%d\n", rc); goto fail; } hrtimer_init(&chip->stop_timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL); chip->stop_timer.function = hap_stop_timer; hrtimer_init(&chip->auto_res_err_poll_timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL); chip->auto_res_err_poll_timer.function = hap_auto_res_err_poll_timer; dev_set_drvdata(&pdev->dev, chip); chip->cdev.name = "vibrator"; chip->cdev.brightness_get = qpnp_haptics_brightness_get; chip->cdev.brightness_set = qpnp_haptics_brightness_set; chip->cdev.max_brightness = 100; rc = devm_led_classdev_register(&pdev->dev, &chip->cdev); if (rc < 0) { dev_err(&pdev->dev, "Error in registering led class device, rc=%d\n", rc); goto register_fail; } for (i = 0; i < ARRAY_SIZE(qpnp_haptics_attrs); i++) { rc = sysfs_create_file(&chip->cdev.dev->kobj, &qpnp_haptics_attrs[i].attr); if (rc < 0) { dev_err(&pdev->dev, "Error in creating sysfs file, rc=%d\n", rc); goto sysfs_fail; } } return 0; sysfs_fail: for (--i; i >= 0; i--) sysfs_remove_file(&chip->cdev.dev->kobj, &qpnp_haptics_attrs[i].attr); register_fail: cancel_work_sync(&chip->haptics_work); hrtimer_cancel(&chip->auto_res_err_poll_timer); hrtimer_cancel(&chip->stop_timer); fail: mutex_destroy(&chip->play_lock); mutex_destroy(&chip->param_lock); if (chip->pwm_data.pwm_dev) pwm_put(chip->pwm_data.pwm_dev); dev_set_drvdata(&pdev->dev, NULL); return rc; } static int qpnp_haptics_remove(struct platform_device *pdev) { struct hap_chip *chip = dev_get_drvdata(&pdev->dev); cancel_work_sync(&chip->haptics_work); hrtimer_cancel(&chip->auto_res_err_poll_timer); hrtimer_cancel(&chip->stop_timer); mutex_destroy(&chip->play_lock); mutex_destroy(&chip->param_lock); if (chip->pwm_data.pwm_dev) pwm_put(chip->pwm_data.pwm_dev); dev_set_drvdata(&pdev->dev, NULL); return 0; } static const struct dev_pm_ops qpnp_haptics_pm_ops = { .suspend = qpnp_haptics_suspend, }; static const struct of_device_id hap_match_table[] = { { .compatible = "qcom,qpnp-haptics" }, { }, }; static struct platform_driver qpnp_haptics_driver = { .driver = { .name = "qcom,qpnp-haptics", .of_match_table = hap_match_table, .pm = &qpnp_haptics_pm_ops, }, .probe = qpnp_haptics_probe, .remove = qpnp_haptics_remove, }; module_platform_driver(qpnp_haptics_driver); MODULE_DESCRIPTION("QPNP haptics driver"); MODULE_LICENSE("GPL v2");