diff options
author | Daniel Hillenbrand <daniel.hillenbrand@codeworkx.de> | 2012-06-16 14:26:31 +0200 |
---|---|---|
committer | Daniel Hillenbrand <daniel.hillenbrand@codeworkx.de> | 2012-06-16 14:26:31 +0200 |
commit | ce7b762837d2ca191580489dd655f8745cc32547 (patch) | |
tree | 69da9859daec0b3ea1f38de1e62729634e556eb6 /drivers/motor | |
parent | 7b612c781b831df37584f95f37fb42ed7214d22e (diff) | |
download | kernel_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.c | 86 |
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) { |