aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSteve Pfetsch <spfetsch@google.com>2016-09-10 18:19:19 -0700
committerSteve Pfetsch <spfetsch@google.com>2016-09-11 12:58:29 -0700
commit895c4a66de92219859cf5939fefb0e4d6fbb1391 (patch)
tree821a20681611ce2832c7bb7b44909b8a17471cbc
parente62667b4a5ba40e93ff0926531a8ddef4bfedb35 (diff)
msm: haptic: reduce haptic intensity except for calls and messagesandroid-7.1.0_r0.2
Introduce a haptic duration threshold below which vibration intensity is automatically reduced. The intensity of brief vibration is reduced so that keyboard, touch, and fingerprint haptics are less audible. Add sysfs nodes for accessing the threshold and the strong/light intensity settings. Bug: 31407746 Change-Id: Ib4704a38255f3171bb13fc2ecc0201940ffa8767
-rwxr-xr-xdrivers/platform/msm/qpnp-haptic.c151
1 files changed, 151 insertions, 0 deletions
diff --git a/drivers/platform/msm/qpnp-haptic.c b/drivers/platform/msm/qpnp-haptic.c
index 5c3da0f46a49..e9ea721f39ba 100755
--- a/drivers/platform/msm/qpnp-haptic.c
+++ b/drivers/platform/msm/qpnp-haptic.c
@@ -81,6 +81,9 @@
#define QPNP_HAP_VMAX_SHIFT 1
#define QPNP_HAP_VMAX_MIN_MV 116
#define QPNP_HAP_VMAX_MAX_MV 3596
+#define QPNP_HAP_VMAX_STRONG_MV 3596
+#define QPNP_HAP_VMAX_LIGHT_MV 500
+#define QPNP_HAP_STRONG_THRESHOLD 330
#define QPNP_HAP_ILIM_MASK 0xFE
#define QPNP_HAP_ILIM_MIN_MV 400
#define QPNP_HAP_ILIM_MAX_MV 800
@@ -259,6 +262,9 @@ struct qpnp_pwm_info {
* @ time_required_to_generate_back_emf_us - the time required for sufficient
back-emf to be generated for auto resonance to be successful
* @ vmax_mv - max voltage in mv
+ * @ timeout_strong_threshold - minimum duration of a strong pulse in ms
+ * @ vmax_strong_mv - voltage used for a strong pulse in mv
+ * @ vmax_light_mv - voltage used for a light pulse in mv
* @ ilim_ma - limiting current in ma
* @ sc_deb_cycles - short circuit debounce cycles
* @ int_pwm_freq_khz - internal pwm frequency in khz
@@ -310,6 +316,9 @@ struct qpnp_hap {
u32 timeout_ms;
u32 time_required_to_generate_back_emf_us;
u32 vmax_mv;
+ u32 timeout_strong_threshold;
+ u32 vmax_strong_mv;
+ u32 vmax_light_mv;
u32 ilim_ma;
u32 sc_deb_cycles;
u32 int_pwm_freq_khz;
@@ -1012,6 +1021,108 @@ static ssize_t qpnp_hap_wf_s7_store(struct device *dev,
return qpnp_hap_wf_samp_store(dev, buf, count, 7);
}
+/* sysfs show for timeout_strong_threshold update */
+static ssize_t qpnp_hap_timeout_strong_threshold_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct timed_output_dev *timed_dev = dev_get_drvdata(dev);
+ struct qpnp_hap *hap = container_of(timed_dev, struct qpnp_hap,
+ timed_dev);
+
+ return snprintf(buf, PAGE_SIZE, "%d\n", hap->timeout_strong_threshold);
+}
+
+/* sysfs store for timeout_strong_threshold */
+static ssize_t qpnp_hap_timeout_strong_threshold_store(struct device *dev,
+ struct device_attribute *attr, const char *buf, size_t count)
+{
+ struct timed_output_dev *timed_dev = dev_get_drvdata(dev);
+ struct qpnp_hap *hap = container_of(timed_dev, struct qpnp_hap,
+ timed_dev);
+ u32 val;
+ ssize_t ret;
+
+ ret = kstrtou32(buf, 10, &val);
+ if (ret)
+ return ret;
+
+ mutex_lock(&hap->wf_lock);
+ hap->timeout_strong_threshold = val;
+ mutex_unlock(&hap->wf_lock);
+
+ return count;
+}
+
+/* sysfs show for vmax_strong_mv update */
+static ssize_t qpnp_hap_vmax_strong_mv_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct timed_output_dev *timed_dev = dev_get_drvdata(dev);
+ struct qpnp_hap *hap = container_of(timed_dev, struct qpnp_hap,
+ timed_dev);
+
+ return snprintf(buf, PAGE_SIZE, "%d\n", hap->vmax_strong_mv);
+}
+
+/* sysfs store for vmax_strong_mv */
+static ssize_t qpnp_hap_vmax_strong_mv_store(struct device *dev,
+ struct device_attribute *attr, const char *buf, size_t count)
+{
+ struct timed_output_dev *timed_dev = dev_get_drvdata(dev);
+ struct qpnp_hap *hap = container_of(timed_dev, struct qpnp_hap,
+ timed_dev);
+ u32 val;
+ ssize_t ret;
+
+ ret = kstrtou32(buf, 10, &val);
+ if (ret)
+ return ret;
+
+ if ((val < QPNP_HAP_VMAX_MIN_MV) || (val > QPNP_HAP_VMAX_MAX_MV))
+ return -EINVAL;
+
+ mutex_lock(&hap->wf_lock);
+ hap->vmax_strong_mv = val;
+ mutex_unlock(&hap->wf_lock);
+
+ return count;
+}
+
+/* sysfs show for vmax_light_mv update */
+static ssize_t qpnp_hap_vmax_light_mv_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct timed_output_dev *timed_dev = dev_get_drvdata(dev);
+ struct qpnp_hap *hap = container_of(timed_dev, struct qpnp_hap,
+ timed_dev);
+
+ return snprintf(buf, PAGE_SIZE, "%d\n", hap->vmax_light_mv);
+}
+
+/* sysfs store for vmax_light_mv */
+static ssize_t qpnp_hap_vmax_light_mv_store(struct device *dev,
+ struct device_attribute *attr, const char *buf, size_t count)
+{
+ struct timed_output_dev *timed_dev = dev_get_drvdata(dev);
+ struct qpnp_hap *hap = container_of(timed_dev, struct qpnp_hap,
+ timed_dev);
+ u32 val;
+ ssize_t ret;
+
+ ret = kstrtou32(buf, 10, &val);
+ if (ret)
+ return ret;
+
+ if ((val < QPNP_HAP_VMAX_MIN_MV) || (val > QPNP_HAP_VMAX_MAX_MV))
+ return -EINVAL;
+
+ mutex_lock(&hap->wf_lock);
+ hap->vmax_light_mv = val;
+ mutex_unlock(&hap->wf_lock);
+
+ return count;
+}
+
/* sysfs show for wave form update */
static ssize_t qpnp_hap_wf_update_show(struct device *dev,
struct device_attribute *attr, char *buf)
@@ -1394,6 +1505,15 @@ static struct device_attribute qpnp_hap_attrs[] = {
__ATTR(min_max_test, (S_IRUGO | S_IWUSR | S_IWGRP),
qpnp_hap_min_max_test_data_show,
qpnp_hap_min_max_test_data_store),
+ __ATTR(timeout_strong_threshold, (S_IRUGO | S_IWUSR | S_IWGRP),
+ qpnp_hap_timeout_strong_threshold_show,
+ qpnp_hap_timeout_strong_threshold_store),
+ __ATTR(vmax_strong_mv, (S_IRUGO | S_IWUSR | S_IWGRP),
+ qpnp_hap_vmax_strong_mv_show,
+ qpnp_hap_vmax_strong_mv_store),
+ __ATTR(vmax_light_mv, (S_IRUGO | S_IWUSR | S_IWGRP),
+ qpnp_hap_vmax_light_mv_show,
+ qpnp_hap_vmax_light_mv_store),
};
static void calculate_lra_code(struct qpnp_hap *hap)
@@ -1635,7 +1755,17 @@ static void qpnp_hap_td_enable(struct timed_output_dev *dev, int value)
}
hap->state = 0;
} else {
+ u32 new_vmax_mv;
VIB_DBG_LOG("enable=%d.\n", value);
+
+ /* Reduce intensity if outside call/message duration */
+ new_vmax_mv = (value >= hap->timeout_strong_threshold) ?
+ hap->vmax_strong_mv : hap->vmax_light_mv;
+ if (new_vmax_mv != hap->vmax_mv) {
+ hap->vmax_mv = new_vmax_mv;
+ qpnp_hap_vmax_config(hap);
+ }
+
value = (value > hap->timeout_ms ?
hap->timeout_ms : value);
hap->state = 1;
@@ -2205,6 +2335,27 @@ static int qpnp_hap_parse_dt(struct qpnp_hap *hap)
return rc;
}
+ hap->timeout_strong_threshold = QPNP_HAP_STRONG_THRESHOLD;
+ rc = of_property_read_u32(spmi->dev.of_node,
+ "qcom,timeout-strong-threshold", &temp);
+ if (!rc) {
+ hap->timeout_strong_threshold = temp;
+ }
+
+ hap->vmax_strong_mv = QPNP_HAP_VMAX_STRONG_MV;
+ rc = of_property_read_u32(spmi->dev.of_node,
+ "qcom,vmax-strong-mv", &temp);
+ if (!rc) {
+ hap->vmax_strong_mv = temp;
+ }
+
+ hap->vmax_light_mv = QPNP_HAP_VMAX_LIGHT_MV;
+ rc = of_property_read_u32(spmi->dev.of_node,
+ "qcom,vmax-light-mv", &temp);
+ if (!rc) {
+ hap->vmax_light_mv = temp;
+ }
+
hap->ilim_ma = QPNP_HAP_ILIM_MIN_MV;
rc = of_property_read_u32(spmi->dev.of_node,
"qcom,ilim-ma", &temp);