diff --git a/Documentation/devicetree/bindings/platform/msm/qpnp-haptic.txt b/Documentation/devicetree/bindings/platform/msm/qpnp-haptic.txt index bc535c4e7b19..fe94e40a27cd 100644 --- a/Documentation/devicetree/bindings/platform/msm/qpnp-haptic.txt +++ b/Documentation/devicetree/bindings/platform/msm/qpnp-haptic.txt @@ -30,6 +30,7 @@ Optional Properties: short circuit are <0x3 0xc0 0x0> and <0x3 0xc0 0x1>. - interrupt-names: Specify the interrupt names associated with interrupts. Must be one of "play-irq" or "sc-irq" + - vcc_pon-supply: power-on driver regulator Optional properties for buffer play mode: - qcom,wave-samples : 8 byte buffer representing the wave. The bits in each sample @@ -74,6 +75,7 @@ Example: interrupts = <0x3 0xc0 0x0>, <0x3 0xc0 0x1>; interrupt-names = "sc-irq", "play-irq"; + vcc_pon-supply = <&pon_perph_reg>; qcom,play-mode = "direct"; qcom,wave-play-rate-us = <5263>; qcom,actuator-type = "lra"; diff --git a/drivers/platform/msm/qpnp-haptic.c b/drivers/platform/msm/qpnp-haptic.c index d610522d6638..b6b9db3eb8eb 100644 --- a/drivers/platform/msm/qpnp-haptic.c +++ b/drivers/platform/msm/qpnp-haptic.c @@ -18,6 +18,7 @@ #include #include #include +#include #include #include #include @@ -280,6 +281,7 @@ struct qpnp_pwm_info { */ struct qpnp_hap { struct spmi_device *spmi; + struct regulator *vcc_pon; struct hrtimer hap_timer; struct hrtimer auto_res_err_poll_timer; struct timed_output_dev timed_dev; @@ -320,6 +322,7 @@ struct qpnp_hap { bool state; bool use_play_irq; bool use_sc_irq; + bool manage_pon_supply; bool wf_update; bool pwm_cfg_state; bool buffer_cfg_state; @@ -1630,7 +1633,14 @@ static void qpnp_hap_worker(struct work_struct *work) struct qpnp_hap *hap = container_of(work, struct qpnp_hap, work); u8 val = 0x00; - int rc; + int rc, reg_en; + + if (hap->vcc_pon) { + reg_en = regulator_enable(hap->vcc_pon); + if (reg_en) + pr_err("%s: could not enable vcc_pon regulator\n", + __func__); + } /* Disable haptics module if the duration of short circuit * exceeds the maximum limit (5 secs). @@ -1643,6 +1653,13 @@ static void qpnp_hap_worker(struct work_struct *work) qpnp_hap_mod_enable(hap, hap->state); qpnp_hap_set(hap, hap->state); } + + if (hap->vcc_pon && !reg_en) { + rc = regulator_disable(hap->vcc_pon); + if (rc) + pr_err("%s: could not disable vcc_pon regulator\n", + __func__); + } } /* get time api to know the remaining time */ @@ -2158,6 +2175,9 @@ static int qpnp_hap_parse_dt(struct qpnp_hap *hap) } } + if (of_find_property(spmi->dev.of_node, "vcc_pon-supply", NULL)) + hap->manage_pon_supply = true; + return 0; } @@ -2165,6 +2185,7 @@ static int qpnp_haptic_probe(struct spmi_device *spmi) { struct qpnp_hap *hap; struct resource *hap_resource; + struct regulator *vcc_pon; int rc, i; hap = devm_kzalloc(&spmi->dev, sizeof(*hap), GFP_KERNEL); @@ -2232,6 +2253,17 @@ static int qpnp_haptic_probe(struct spmi_device *spmi) } } + if (hap->manage_pon_supply) { + vcc_pon = regulator_get(&spmi->dev, "vcc_pon"); + if (IS_ERR(vcc_pon)) { + rc = PTR_ERR(vcc_pon); + dev_err(&spmi->dev, + "regulator get failed vcc_pon rc=%d\n", rc); + goto sysfs_fail; + } + hap->vcc_pon = vcc_pon; + } + ghap = hap; return 0; @@ -2268,6 +2300,8 @@ static int qpnp_haptic_remove(struct spmi_device *spmi) timed_output_dev_unregister(&hap->timed_dev); mutex_destroy(&hap->lock); mutex_destroy(&hap->wf_lock); + if (hap->vcc_pon) + regulator_put(hap->vcc_pon); return 0; }