summaryrefslogtreecommitdiff
path: root/drivers/leds/leds-qpnp-haptics.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/leds/leds-qpnp-haptics.c')
-rw-r--r--drivers/leds/leds-qpnp-haptics.c100
1 files changed, 100 insertions, 0 deletions
diff --git a/drivers/leds/leds-qpnp-haptics.c b/drivers/leds/leds-qpnp-haptics.c
index 9c62ab6521e8..72babedcf009 100644
--- a/drivers/leds/leds-qpnp-haptics.c
+++ b/drivers/leds/leds-qpnp-haptics.c
@@ -359,8 +359,11 @@ struct hap_chip {
bool play_irq_en;
bool auto_res_err_recovery_hw;
bool vcc_pon_enabled;
+ int vmax_override;
};
+struct hap_chip *gchip;
+
static int qpnp_haptics_parse_buffer_dt(struct hap_chip *chip);
static int qpnp_haptics_parse_pwm_dt(struct hap_chip *chip);
@@ -1331,6 +1334,34 @@ static int qpnp_haptics_auto_mode_config(struct hap_chip *chip, int time_ms)
return 0;
}
+void set_vibrate(int val)
+{
+ int rc;
+
+ if (val > gchip->max_play_time_ms)
+ return;
+
+ mutex_lock(&gchip->param_lock);
+ rc = qpnp_haptics_auto_mode_config(gchip, val);
+ if (rc < 0) {
+ pr_err("Unable to do auto mode config\n");
+ mutex_unlock(&gchip->param_lock);
+ return;
+ }
+
+ gchip->play_time_ms = val;
+ mutex_unlock(&gchip->param_lock);
+
+ hrtimer_cancel(&gchip->stop_timer);
+ if (is_sw_lra_auto_resonance_control(gchip))
+ hrtimer_cancel(&gchip->auto_res_err_poll_timer);
+ cancel_work_sync(&gchip->haptics_work);
+
+ atomic_set(&gchip->state, 1);
+ schedule_work(&gchip->haptics_work);
+
+}
+
static irqreturn_t qpnp_haptics_play_irq_handler(int irq, void *data)
{
struct hap_chip *chip = data;
@@ -1521,6 +1552,9 @@ static ssize_t qpnp_haptics_store_activate(struct device *dev,
if (val != 0 && val != 1)
return count;
+ if (chip->vmax_mv <= HAP_VMAX_MIN_MV && (val != 0))
+ return count;
+
if (val) {
hrtimer_cancel(&chip->stop_timer);
if (is_sw_lra_auto_resonance_control(chip))
@@ -1761,6 +1795,9 @@ static ssize_t qpnp_haptics_store_vmax(struct device *dev,
if (rc < 0)
return rc;
+ if (chip->vmax_override)
+ return count;
+
old_vmax_mv = chip->vmax_mv;
chip->vmax_mv = data;
rc = qpnp_haptics_vmax_config(chip, chip->vmax_mv, false);
@@ -1772,6 +1809,65 @@ static ssize_t qpnp_haptics_store_vmax(struct device *dev,
return count;
}
+static ssize_t qpnp_haptics_show_vmax_mv_user(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_mv_user(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_vmax_override(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_override);
+}
+
+static ssize_t qpnp_haptics_store_vmax_override(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;
+
+ rc = kstrtoint(buf, 10, &data);
+ if (rc < 0)
+ return rc;
+
+ if (data != 0 && data != 1)
+ return count;
+
+ chip->vmax_override = !!data;
+
+ return count;
+}
+
static ssize_t qpnp_haptics_show_lra_auto_mode(struct device *dev,
struct device_attribute *attr, char *buf)
{
@@ -1814,6 +1910,8 @@ static struct device_attribute qpnp_haptics_attrs[] = {
__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(vmax_override, 0664, qpnp_haptics_show_vmax_override, qpnp_haptics_store_vmax_override),
+ __ATTR(vmax_mv_user, 0664, qpnp_haptics_show_vmax_mv_user, qpnp_haptics_store_vmax_mv_user),
__ATTR(lra_auto_mode, 0664, qpnp_haptics_show_lra_auto_mode,
qpnp_haptics_store_lra_auto_mode),
};
@@ -2481,6 +2579,8 @@ static int qpnp_haptics_probe(struct platform_device *pdev)
}
}
+ gchip = chip;
+
return 0;
sysfs_fail: