aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/motor
diff options
context:
space:
mode:
authorDaniel Hillenbrand <daniel.hillenbrand@codeworkx.de>2012-06-16 14:26:31 +0200
committerDaniel Hillenbrand <daniel.hillenbrand@codeworkx.de>2012-06-16 14:26:31 +0200
commitce7b762837d2ca191580489dd655f8745cc32547 (patch)
tree69da9859daec0b3ea1f38de1e62729634e556eb6 /drivers/motor
parent7b612c781b831df37584f95f37fb42ed7214d22e (diff)
downloadkernel_samsung_smdk4412-ce7b762837d2ca191580489dd655f8745cc32547.zip
kernel_samsung_smdk4412-ce7b762837d2ca191580489dd655f8745cc32547.tar.gz
kernel_samsung_smdk4412-ce7b762837d2ca191580489dd655f8745cc32547.tar.bz2
max77693_haptic: user configurable vibrator intensity
Diffstat (limited to 'drivers/motor')
-rw-r--r--drivers/motor/max77693_haptic.c86
1 files changed, 73 insertions, 13 deletions
diff --git a/drivers/motor/max77693_haptic.c b/drivers/motor/max77693_haptic.c
index f1c816e..16fbece 100644
--- a/drivers/motor/max77693_haptic.c
+++ b/drivers/motor/max77693_haptic.c
@@ -2,6 +2,8 @@
* haptic motor driver for max77693 - max77673_haptic.c
*
* Copyright (C) 2011 ByungChang Cha <bc.cha@samsung.com>
+ * Copyright (C) 2012 The CyanogenMod Project
+ * Daniel Hillenbrand <codeworkx@cyanogenmod.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
@@ -22,6 +24,9 @@
#include <linux/mfd/max77693.h>
#include <linux/mfd/max77693-private.h>
+static unsigned long pwm_val = 50; /* duty in percent */
+static int pwm_duty = 27787; /* duty value, 37050=100%, 27787=50%, 18525=0% */
+
struct max77693_haptic_data {
struct max77693_dev *max77693;
struct i2c_client *i2c;
@@ -152,8 +157,8 @@ static void haptic_work(struct work_struct *work)
max77693_haptic_i2c(hap_data, true);
- pwm_config(hap_data->pwm, hap_data->pdata->duty,
- hap_data->pdata->period);
+ pwm_config(hap_data->pwm, pwm_duty, hap_data->pdata->period);
+ pr_info("[VIB] %s: pwm_config duty=%d\n", __func__, pwm_duty);
pwm_enable(hap_data->pwm);
if (hap_data->pdata->motor_en)
@@ -184,7 +189,7 @@ static void haptic_work(struct work_struct *work)
void vibtonz_en(bool en)
{
if (g_hap_data == NULL) {
- printk(KERN_ERR "[VIB] the motor is not ready!!!");
+ pr_err("[VIB] %s: the motor is not ready!!!", __func__);
return ;
}
@@ -223,30 +228,83 @@ void vibtonz_pwm(int nForce)
{
/* add to avoid the glitch issue */
static int prev_duty;
- int pwm_period = 0, pwm_duty = 0;
+ int pwm_period = 0;
if (g_hap_data == NULL) {
- printk(KERN_ERR "[VIB] the motor is not ready!!!");
+ pr_err("[VIB] %s: the motor is not ready!!!", __func__);
return ;
}
- pwm_period = g_hap_data->pdata->period;
- pwm_duty = pwm_period / 2 + ((pwm_period / 2 - 2) * nForce) / 127;
-
- if (pwm_duty > g_hap_data->pdata->duty)
- pwm_duty = g_hap_data->pdata->duty;
- else if (pwm_period - pwm_duty > g_hap_data->pdata->duty)
- pwm_duty = pwm_period - g_hap_data->pdata->duty;
-
/* add to avoid the glitch issue */
if (prev_duty != pwm_duty) {
prev_duty = pwm_duty;
+
+ pr_debug("[VIB] %s: setting pwm_duty=%d", __func__, pwm_duty);
pwm_config(g_hap_data->pwm, pwm_duty, pwm_period);
}
}
EXPORT_SYMBOL(vibtonz_pwm);
#endif
+static ssize_t pwm_val_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ int count;
+
+ pwm_val = ((pwm_duty - 18525) * 100) / 18525;
+
+ count = sprintf(buf, "%lu\n", pwm_val);
+ pr_debug("[VIB] pwm_val: %lu\n", pwm_val);
+
+ return count;
+}
+
+ssize_t pwm_val_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t size)
+{
+ if (kstrtoul(buf, 0, &pwm_val))
+ pr_err("[VIB] %s: error on storing pwm_val\n", __func__);
+
+ pr_info("[VIB] %s: pwm_val=%lu\n", __func__, pwm_val);
+
+ pwm_duty = (pwm_val * 18525) / 100 + 18525;
+
+ /* make sure new pwm duty is in range */
+ if(pwm_duty > 37050)
+ {
+ pwm_duty = 37050;
+ }
+ else if (pwm_duty < 18525)
+ {
+ pwm_duty = 18525;
+ }
+
+ pr_info("[VIB] %s: pwm_duty=%d\n", __func__, pwm_duty);
+
+ return size;
+}
+static DEVICE_ATTR(pwm_val, S_IRUGO | S_IWUSR,
+ pwm_val_show, pwm_val_store);
+
+static int create_vibrator_sysfs(void)
+{
+ int ret;
+ struct kobject *vibrator_kobj;
+ vibrator_kobj = kobject_create_and_add("vibrator", NULL);
+ if (unlikely(!vibrator_kobj))
+ return -ENOMEM;
+
+ ret = sysfs_create_file(vibrator_kobj,
+ &dev_attr_pwm_val.attr);
+ if (unlikely(ret < 0)) {
+ pr_err("[VIB] sysfs_create_file failed: %d\n", ret);
+ return ret;
+ }
+
+ return 0;
+}
+
static int max77693_haptic_probe(struct platform_device *pdev)
{
int error = 0;
@@ -309,6 +367,8 @@ static int max77693_haptic_probe(struct platform_device *pdev)
hap_data->tout_dev.get_time = haptic_get_time;
hap_data->tout_dev.enable = haptic_enable;
+ create_vibrator_sysfs();
+
#ifdef CONFIG_ANDROID_TIMED_OUTPUT
error = timed_output_dev_register(&hap_data->tout_dev);
if (error < 0) {