summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authordianlujitao <dianlujitao@gmail.com>2016-07-01 22:17:42 +0800
committerMichael Bestas <mkbestas@lineageos.org>2019-12-23 23:43:38 +0200
commit39d21bfc38cb4e2b90ca7422b7526786c0ec9e06 (patch)
treeedf73d207289801b18748939f0c572f4edd1b618
parent39ba8d7f26a7972f3d6d673460f29377ad4fbcec (diff)
msm: qpnp-haptic: set up sysfs interface for common cmhw implementation
* Export vmax_mv as vtg_level * Add min/max/default voltage sysfs entries * Make min/max voltage adjustable via DT Change-Id: Iefa3accdb75fcef9bcb2d4c730ca0a72763994f3
-rw-r--r--drivers/soc/qcom/qpnp-haptic.c81
1 files changed, 74 insertions, 7 deletions
diff --git a/drivers/soc/qcom/qpnp-haptic.c b/drivers/soc/qcom/qpnp-haptic.c
index 064608fc81cf..c4f311f4afc4 100644
--- a/drivers/soc/qcom/qpnp-haptic.c
+++ b/drivers/soc/qcom/qpnp-haptic.c
@@ -364,6 +364,9 @@ struct qpnp_hap {
u32 timeout_ms;
u32 time_required_to_generate_back_emf_us;
u32 vmax_mv;
+ u32 vtg_min;
+ u32 vtg_max;
+ u32 vtg_default;
u32 ilim_ma;
u32 sc_deb_cycles;
u32 int_pwm_freq_khz;
@@ -889,12 +892,12 @@ static int qpnp_hap_vmax_config(struct qpnp_hap *hap, int vmax_mv,
if (hap->pmic_subtype != PM660_SUBTYPE)
overdrive = false;
- if (vmax_mv < QPNP_HAP_VMAX_MIN_MV)
- vmax_mv = QPNP_HAP_VMAX_MIN_MV;
- else if (vmax_mv > QPNP_HAP_VMAX_MAX_MV)
- vmax_mv = QPNP_HAP_VMAX_MAX_MV;
+ if (vmax_mv < hap->vtg_min)
+ vmax_mv = hap->vtg_min;
+ else if (vmax_mv > hap->vtg_max)
+ vmax_mv = hap->vtg_max;
- val = (vmax_mv / QPNP_HAP_VMAX_MIN_MV) << QPNP_HAP_VMAX_SHIFT;
+ val = (vmax_mv / hap->vtg_min) << QPNP_HAP_VMAX_SHIFT;
if (overdrive)
val |= QPNP_HAP_VMAX_OVD_BIT;
rc = qpnp_hap_masked_write_reg(hap, QPNP_HAP_VMAX_REG(hap->base),
@@ -1788,9 +1791,43 @@ static ssize_t qpnp_hap_vmax_store(struct device *dev,
return rc;
hap->vmax_mv = data;
+ rc = qpnp_hap_vmax_config(hap, hap->vmax_mv, true);
+ if (rc)
+ return rc;
+
return count;
}
+static ssize_t qpnp_hap_min_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->vtg_min);
+}
+
+static ssize_t qpnp_hap_max_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->vtg_max);
+}
+
+static ssize_t qpnp_hap_default_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->vtg_default);
+}
+
/* sysfs attributes */
static struct device_attribute qpnp_hap_attrs[] = {
__ATTR(wf_s0, 0664, qpnp_hap_wf_s0_show, qpnp_hap_wf_s0_store),
@@ -1822,6 +1859,10 @@ static struct device_attribute qpnp_hap_attrs[] = {
qpnp_hap_override_auto_mode_show,
qpnp_hap_override_auto_mode_store),
__ATTR(vmax_mv, 0664, qpnp_hap_vmax_show, qpnp_hap_vmax_store),
+ __ATTR(vtg_level, 0664, qpnp_hap_vmax_show, qpnp_hap_vmax_store),
+ __ATTR(vtg_min, 0664, qpnp_hap_min_show, NULL),
+ __ATTR(vtg_max, 0664, qpnp_hap_max_show, NULL),
+ __ATTR(vtg_default, 0664, qpnp_hap_default_show, NULL),
};
static int calculate_lra_code(struct qpnp_hap *hap)
@@ -2148,7 +2189,7 @@ static int qpnp_hap_auto_mode_config(struct qpnp_hap *hap, int time_ms)
ares_cfg.calibrate_at_eop = -EINVAL;
}
- vmax_mv = QPNP_HAP_VMAX_MAX_MV;
+ vmax_mv = hap->vtg_max;
rc = qpnp_hap_vmax_config(hap, vmax_mv, true);
if (rc < 0)
return rc;
@@ -2859,7 +2900,25 @@ static int qpnp_hap_parse_dt(struct qpnp_hap *hap)
return rc;
}
- hap->vmax_mv = QPNP_HAP_VMAX_MAX_MV;
+ hap->vtg_min = QPNP_HAP_VMAX_MIN_MV;
+ rc = of_property_read_u32(pdev->dev.of_node, "qcom,vtg-min", &temp);
+ if (!rc) {
+ hap->vtg_min = temp;
+ } else if (rc != -EINVAL) {
+ pr_err("Unable to read vtg_min\n");
+ return rc;
+ }
+
+ hap->vtg_max = QPNP_HAP_VMAX_MAX_MV;
+ rc = of_property_read_u32(pdev->dev.of_node, "qcom,vtg-max", &temp);
+ if (!rc) {
+ hap->vtg_max = temp;
+ } else if (rc != -EINVAL) {
+ pr_err("Unable to read vtg_max\n");
+ return rc;
+ }
+
+ hap->vmax_mv = hap->vtg_max;
rc = of_property_read_u32(pdev->dev.of_node, "qcom,vmax-mv", &temp);
if (!rc) {
hap->vmax_mv = temp;
@@ -2868,6 +2927,14 @@ static int qpnp_hap_parse_dt(struct qpnp_hap *hap)
return rc;
}
+ if (hap->vmax_mv < hap->vtg_min) {
+ hap->vmax_mv = hap->vtg_min;
+ } else if (hap->vmax_mv > hap->vtg_max) {
+ hap->vmax_mv = hap->vtg_max;
+ }
+
+ hap->vtg_default = hap->vmax_mv;
+
hap->ilim_ma = QPNP_HAP_ILIM_MIN_MV;
rc = of_property_read_u32(pdev->dev.of_node, "qcom,ilim-ma", &temp);
if (!rc) {