diff options
author | Daniel Hillenbrand <codeworkx@cyanogenmod.org> | 2013-05-25 10:53:54 +0200 |
---|---|---|
committer | Daniel Hillenbrand <codeworkx@cyanogenmod.org> | 2013-05-25 10:53:54 +0200 |
commit | 05f0203060035bd2cb8c8f98b8b466b934b1c45b (patch) | |
tree | 051a8c9d1a431b27fb5d4fecaf5417487857a400 /drivers/motor/max8997_vibrator.c | |
parent | ab6dfccd8d126b50059d39d031cfa1ddc8f32b84 (diff) | |
download | kernel_samsung_smdk4412-05f0203060035bd2cb8c8f98b8b466b934b1c45b.zip kernel_samsung_smdk4412-05f0203060035bd2cb8c8f98b8b466b934b1c45b.tar.gz kernel_samsung_smdk4412-05f0203060035bd2cb8c8f98b8b466b934b1c45b.tar.bz2 |
u1: import from CyanogenMod/android_kernel_samsung_smdk4210
Change-Id: I9629a4060538c9c4c6a43a86a56826cd7123d1b5
Diffstat (limited to 'drivers/motor/max8997_vibrator.c')
-rw-r--r-- | drivers/motor/max8997_vibrator.c | 91 |
1 files changed, 86 insertions, 5 deletions
diff --git a/drivers/motor/max8997_vibrator.c b/drivers/motor/max8997_vibrator.c index c34716b..c3b07f8 100644 --- a/drivers/motor/max8997_vibrator.c +++ b/drivers/motor/max8997_vibrator.c @@ -1,3 +1,16 @@ +/* + * haptic motor driver for max8997 - max8997_vibrator.c + * + * Copyright (C) 2011 Unknown Samsung Employees (Original file was missing copyright header) + * Copyright (C) 2012 The CyanogenMod Project + * Daniel Hillenbrand <codeworkx@cyanogenmod.com> + * Andrew Dodd <atd7@cornell.edu> + * + * 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 + * published by the Free Software Foundation. + */ + #include <linux/module.h> #include <linux/kernel.h> #include <linux/timed_output.h> @@ -14,6 +27,12 @@ #include "mach/gpio.h" #endif +static int pwm_duty_max; +static int pwm_duty_min; + +static unsigned long pwm_val = 50; /* duty in percent */ +static int pwm_duty; /* duty value */ + struct vibrator_drvdata { struct max8997_motor_data *pdata; struct pwm_device *pwm; @@ -28,7 +47,7 @@ struct vibrator_drvdata { }; #ifdef CONFIG_VIBETONZ -struct vibrator_drvdata *g_data; +static struct vibrator_drvdata *g_data; #endif static int vibetonz_clk_on(struct device *dev, bool en) @@ -89,7 +108,7 @@ static void vibrator_work(struct work_struct *_work) struct vibrator_drvdata *data = container_of(_work, struct vibrator_drvdata, work); - printk(KERN_DEBUG "[VIB] time = %dms\n", data->timeout); + pr_debug("[VIB] time = %dms\n", data->timeout); if (0 == data->timeout) { if (!data->running) @@ -110,8 +129,8 @@ static void vibrator_work(struct work_struct *_work) else regulator_enable(data->regulator); i2c_max8997_hapticmotor(data, true); - pwm_config(data->pwm, - data->pdata->duty, data->pdata->period); + pwm_config(data->pwm, pwm_duty, data->pdata->period); + pr_info("[VIB] %s: pwm_config duty=%d\n", __func__, pwm_duty); pwm_enable(data->pwm); data->running = true; @@ -189,7 +208,6 @@ void vibtonz_pwm(int nForce) /* add to avoid the glitch issue */ static int prev_duty; int pwm_period = data->pdata->period; - int pwm_duty = pwm_period/2 + ((pwm_period/2 - 2) * nForce)/127; #if defined(CONFIG_MACH_P4) if (pwm_duty > data->pdata->duty) @@ -201,12 +219,70 @@ void vibtonz_pwm(int nForce) /* 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(data->pwm, pwm_duty, pwm_period); } } EXPORT_SYMBOL(vibtonz_pwm); + +static ssize_t pwm_val_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + int count; + + pwm_val = ((pwm_duty - pwm_duty_min) * 100) / pwm_duty_min; + + 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 * pwm_duty_min) / 100 + pwm_duty_min; + + /* make sure new pwm duty is in range */ + if(pwm_duty > pwm_duty_max) { + pwm_duty = pwm_duty_max; + } + else if (pwm_duty < pwm_duty_min) { + pwm_duty = pwm_duty_min; + } + + 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); #endif +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 __devinit vibrator_probe(struct platform_device *pdev) { struct max8997_dev *max8997 = dev_get_drvdata(pdev->dev.parent); @@ -247,6 +323,8 @@ static int __devinit vibrator_probe(struct platform_device *pdev) INIT_WORK(&ddata->work, vibrator_work); spin_lock_init(&ddata->lock); + create_vibrator_sysfs(); + ddata->pwm = pwm_request(pdata->pwm_id, "vibrator"); if (IS_ERR(ddata->pwm)) { pr_err("[VIB] Failed to request pwm.\n"); @@ -267,6 +345,9 @@ static int __devinit vibrator_probe(struct platform_device *pdev) #ifdef CONFIG_VIBETONZ g_data = ddata; + pwm_duty_max = g_data->pdata->duty; + pwm_duty_min = pwm_duty_max/2; + pwm_duty = (pwm_duty_min + pwm_duty_max)/2; #endif return 0; |