summaryrefslogtreecommitdiffstats
path: root/target/linux/s3c24xx/patches-2.6.24/1308--lis302dl-configure-duration.patch.patch
blob: dbe08b4cdaa3ced7167a5b834652ca818559d312 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
From d3c59382c7e8429e2c86eb92cc2518dce26c4a69 Mon Sep 17 00:00:00 2001
From: Simon Kagstrom <simon.kagstrom@gmail.com>
Date: Thu, 16 Oct 2008 01:19:39 +0100
Subject: [PATCH] : lis302dl-configure-duration.patch

Allow configuration of the duration for thresholds

From: Simon Kagstrom <simon.kagstrom@gmail.com>

This patch allows the configuration of duration used when generating
filtered data (see the lis302dl application note). Also set a flag when
the DR bit in the ctrl1 register is set to change the data rate and
simplify the ms_to_duration utility functions.

The sysfs 'duration' file is used for this.

Signed-off-by: Simon Kagstrom <simon.kagstrom@gmail.com>
---
 drivers/input/misc/lis302dl.c |   63 ++++++++++++++++++++++++++++-------------
 include/linux/lis302dl.h      |    2 +
 2 files changed, 45 insertions(+), 20 deletions(-)

diff --git a/drivers/input/misc/lis302dl.c b/drivers/input/misc/lis302dl.c
index c1b1d67..d738199 100644
--- a/drivers/input/misc/lis302dl.c
+++ b/drivers/input/misc/lis302dl.c
@@ -69,29 +69,17 @@ static void __reg_set_bit_mask(struct lis302dl_info *lis, u8 reg, u8 mask,
 
 static int __ms_to_duration(struct lis302dl_info *lis, int ms)
 {
-	u8 r = __reg_read(lis, LIS302DL_REG_CTRL1);
-
 	/* If we have 400 ms sampling rate, the stepping is 2.5 ms,
 	 * on 100 ms the stepping is 10ms */
-	if (r & LIS302DL_CTRL1_DR) {
-		/* Too large */
-		if (ms > 637)
-			return -1;
-
-		return (ms * 10) / 25;
-	}
+	if (lis->flags & LIS302DL_F_DR)
+		return min((ms * 10) / 25, 637);
 
-	/* Too large value */
-	if (ms > 2550)
-			return -1;
-	return ms / 10;
+	return min(ms / 10, 2550);
 }
 
 static int __duration_to_ms(struct lis302dl_info *lis, int duration)
 {
-	u8 r = __reg_read(lis, LIS302DL_REG_CTRL1);
-
-	if (r & LIS302DL_CTRL1_DR)
+	if (lis->flags & LIS302DL_F_DR)
 		return (duration * 25) / 10;
 
 	return duration * 10;
@@ -218,15 +206,20 @@ static ssize_t set_rate(struct device *dev, struct device_attribute *attr,
 {
 	struct lis302dl_info *lis = dev_get_drvdata(dev);
 	unsigned long flags;
+	int duration_ms = __duration_to_ms(lis, lis->duration);
 
 	local_irq_save(flags);
 
-	if (!strcmp(buf, "400\n"))
+	if (!strcmp(buf, "400\n")) {
 		__reg_set_bit_mask(lis, LIS302DL_REG_CTRL1, LIS302DL_CTRL1_DR,
 				 LIS302DL_CTRL1_DR);
-	else
+		lis->flags |= LIS302DL_F_DR;
+	} else {
 		__reg_set_bit_mask(lis, LIS302DL_REG_CTRL1, LIS302DL_CTRL1_DR,
-									     0);
+				0);
+		lis->flags &= ~LIS302DL_F_DR;
+	}
+	lis->duration = __ms_to_duration(lis, duration_ms);
 	local_irq_restore(flags);
 
 	return count;
@@ -309,6 +302,34 @@ static ssize_t set_threshold(struct device *dev, struct device_attribute *attr,
 
 static DEVICE_ATTR(threshold, S_IRUGO | S_IWUSR, show_threshold, set_threshold);
 
+static ssize_t show_duration(struct device *dev, struct device_attribute *attr,
+		 char *buf)
+{
+	struct lis302dl_info *lis = dev_get_drvdata(dev);
+
+	return sprintf(buf, "%d\n", __duration_to_ms(lis, lis->duration));
+}
+
+static ssize_t set_duration(struct device *dev, struct device_attribute *attr,
+		 const char *buf, size_t count)
+{
+	struct lis302dl_info *lis = dev_get_drvdata(dev);
+	u32 val;
+
+	if (sscanf(buf, "%d\n", &val) != 1)
+		return -EINVAL;
+	if (val < 0 || val > 2550)
+		return -ERANGE;
+
+	lis->duration = __ms_to_duration(lis, val);
+	if (lis->flags & LIS302DL_F_INPUT_OPEN)
+		__reg_write(lis, LIS302DL_REG_FF_WU_DURATION_1, lis->duration);
+
+	return count;
+}
+
+static DEVICE_ATTR(duration, S_IRUGO | S_IWUSR, show_duration, set_duration);
+
 static ssize_t lis302dl_dump(struct device *dev, struct device_attribute *attr,
 								      char *buf)
 {
@@ -528,6 +549,7 @@ static struct attribute *lis302dl_sysfs_entries[] = {
 	&dev_attr_sample_rate.attr,
 	&dev_attr_full_scale.attr,
 	&dev_attr_threshold.attr,
+	&dev_attr_duration.attr,
 	&dev_attr_dump.attr,
 	&dev_attr_freefall_wakeup_1.attr,
 	&dev_attr_freefall_wakeup_2.attr,
@@ -556,7 +578,7 @@ static int lis302dl_input_open(struct input_dev *inp)
 	__reg_write(lis, LIS302DL_REG_CTRL2,
 			ctrl2);
 	__reg_write(lis, LIS302DL_REG_FF_WU_THS_1, lis->threshold);
-	__reg_write(lis, LIS302DL_REG_FF_WU_DURATION_1, 0);
+	__reg_write(lis, LIS302DL_REG_FF_WU_DURATION_1, lis->duration);
 
 	/* Clear the HP filter "starting point" */
 	__reg_read(lis, LIS302DL_REG_HP_FILTER_RESET);
@@ -670,6 +692,7 @@ static int __devinit lis302dl_probe(struct platform_device *pdev)
 	set_bit(BTN_Z, lis->input_dev->keybit);
 */
 	lis->threshold = 1;
+	lis->duration = 0;
 
 	lis->input_dev->private = lis;
 	lis->input_dev->name = pdata->name;
diff --git a/include/linux/lis302dl.h b/include/linux/lis302dl.h
index a756f55..f7aa956 100644
--- a/include/linux/lis302dl.h
+++ b/include/linux/lis302dl.h
@@ -30,6 +30,7 @@ struct lis302dl_info {
 	struct input_dev *input_dev;
 	unsigned int flags;
 	unsigned int threshold;
+	unsigned int duration;
 	u_int8_t regs[0x40];
 };
 
@@ -142,6 +143,7 @@ enum lis302dl_reg_cloik_src {
 #define LIS302DL_F_FS			0x0020 	/* ADC full scale */
 #define LIS302DL_F_INPUT_OPEN 	0x0040  /* Set if input device is opened */
 #define LIS302DL_F_IRQ_WAKE 	0x0080  /* IRQ is setup in wake mode */
+#define LIS302DL_F_DR			0x0100 	/* Data rate, 400Hz/100Hz */
 
 
 #endif /* _LINUX_LIS302DL_H */
-- 
1.5.6.5