aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/motor
diff options
context:
space:
mode:
authorDaniel Hillenbrand <codeworkx@cyanogenmod.org>2013-05-25 10:53:54 +0200
committerDaniel Hillenbrand <codeworkx@cyanogenmod.org>2013-05-25 10:53:54 +0200
commit05f0203060035bd2cb8c8f98b8b466b934b1c45b (patch)
tree051a8c9d1a431b27fb5d4fecaf5417487857a400 /drivers/motor
parentab6dfccd8d126b50059d39d031cfa1ddc8f32b84 (diff)
downloadkernel_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')
-rw-r--r--drivers/motor/max8997_vibrator.c91
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;