summaryrefslogtreecommitdiffstats
path: root/target/linux/s3c24xx/patches-2.6.24/1304--Acceleration-threshold-configuration-lis302dl-con.patch
blob: 5e9eb2aac9e85d9e0078dc709a7686b1e08d5d4a (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
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
From 35d910f40ce2c7c959edfbaa671f88e8da5fa6b1 Mon Sep 17 00:00:00 2001
From: Simon Kagstrom <simon.kagstrom@gmail.com>
Date: Mon, 13 Oct 2008 12:47:12 +0100
Subject: [PATCH] : Acceleration threshold configuration: lis302dl-configure-threshold-on-bitbang.patch

Configure threshold for accelerometer input

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

This patch, based on bitbang-all-the-way from the andy branch,
implements a configurable acceleration threshold that need to be
exceeded for the accelerometer to generate input data. The threshold can
be set in sysfs:

   cd /sys/devices/.../lis302dl.1/
   echo 10 > threshold

A value of 10 (180 mg, from the lis302dl application note) seems
empirically good to keep the accelerometers quiet while riding a (calm)
train.


The patch moves the sample reading for the accelerometers from
mach-gta02.c to lis302dl.c and instead exports the generic
lis302dl_bitbang function. This is to easier support both "raw" data
reading and reading with a threshold in the future (not yet implemented).

Signed-off-by: Simon Kagstrom <simon.kagstrom@gmail.com>
---
 arch/arm/mach-s3c2440/mach-gta02.c |   35 ++-------------
 drivers/input/misc/lis302dl.c      |   83 ++++++++++++++++++++++++++++++++++--
 include/linux/lis302dl.h           |    3 +
 3 files changed, 87 insertions(+), 34 deletions(-)

diff --git a/arch/arm/mach-s3c2440/mach-gta02.c b/arch/arm/mach-s3c2440/mach-gta02.c
index b19632c..1a9d823 100644
--- a/arch/arm/mach-s3c2440/mach-gta02.c
+++ b/arch/arm/mach-s3c2440/mach-gta02.c
@@ -1050,7 +1050,6 @@ static struct platform_device gta02_vibrator_dev = {
  */
 
 /* #define DEBUG_SPEW_MS */
-#define MG_PER_SAMPLE 18
 
 struct lis302dl_platform_data lis302_pdata_top;
 struct lis302dl_platform_data lis302_pdata_bottom;
@@ -1060,7 +1059,7 @@ struct lis302dl_platform_data lis302_pdata_bottom;
  * only call with interrupts off!
  */
 
-static void __gta02_lis302dl_bitbang(struct lis302dl_info *lis, u8 *tx,
+static void gta02_lis302dl_bitbang(struct lis302dl_info *lis, u8 *tx,
 					     int tx_bytes, u8 *rx, int rx_bytes)
 {
 	struct lis302dl_platform_data *pdata = lis->pdata;
@@ -1124,7 +1123,7 @@ static int gta02_lis302dl_bitbang_read_reg(struct lis302dl_info *lis, u8 reg)
 
 	local_irq_save(flags);
 
-	__gta02_lis302dl_bitbang(lis, &data, 1, &data, 1);
+	gta02_lis302dl_bitbang(lis, &data, 1, &data, 1);
 
 	local_irq_restore(flags);
 
@@ -1139,37 +1138,13 @@ static void gta02_lis302dl_bitbang_write_reg(struct lis302dl_info *lis, u8 reg,
 
 	local_irq_save(flags);
 
-	__gta02_lis302dl_bitbang(lis, &data[0], 2, NULL, 0);
+	gta02_lis302dl_bitbang(lis, &data[0], 2, NULL, 0);
 
 	local_irq_restore(flags);
 
 }
 
 
-static void gta02_lis302dl_bitbang_sample(struct lis302dl_info *lis)
-{
-	u8 data = 0xc0 | LIS302DL_REG_OUT_X; /* read, autoincrement */
-	u8 read[5];
-	unsigned long flags;
-
-	local_irq_save(flags);
-
-	__gta02_lis302dl_bitbang(lis, &data, 1, &read[0], 5);
-
-	local_irq_restore(flags);
-
-	input_report_rel(lis->input_dev, REL_X, MG_PER_SAMPLE * (s8)read[0]);
-	input_report_rel(lis->input_dev, REL_Y, MG_PER_SAMPLE * (s8)read[2]);
-	input_report_rel(lis->input_dev, REL_Z, MG_PER_SAMPLE * (s8)read[4]);
-
-	input_sync(lis->input_dev);
-#ifdef DEBUG_SPEW_MS
-	printk(KERN_INFO "%s: %d %d %d\n", pdata->name, read[0], read[2],
-								       read[4]);
-#endif
-}
-
-
 void gta02_lis302dl_suspend_io(struct lis302dl_info *lis, int resume)
 {
 	struct lis302dl_platform_data *pdata = lis->pdata;
@@ -1210,7 +1185,7 @@ struct lis302dl_platform_data lis302_pdata_top = {
 		.pin_miso	= S3C2410_GPG5,
 		.interrupt	= GTA02_IRQ_GSENSOR_1,
 		.open_drain	= 1, /* altered at runtime by PCB rev */
-		.lis302dl_bitbang_read_sample = gta02_lis302dl_bitbang_sample,
+		.lis302dl_bitbang = gta02_lis302dl_bitbang,
 		.lis302dl_bitbang_reg_read = gta02_lis302dl_bitbang_read_reg,
 		.lis302dl_bitbang_reg_write = gta02_lis302dl_bitbang_write_reg,
 		.lis302dl_suspend_io = gta02_lis302dl_suspend_io,
@@ -1224,7 +1199,7 @@ struct lis302dl_platform_data lis302_pdata_bottom = {
 		.pin_miso	= S3C2410_GPG5,
 		.interrupt	= GTA02_IRQ_GSENSOR_2,
 		.open_drain	= 1, /* altered at runtime by PCB rev */
-		.lis302dl_bitbang_read_sample = gta02_lis302dl_bitbang_sample,
+		.lis302dl_bitbang = gta02_lis302dl_bitbang,
 		.lis302dl_bitbang_reg_read = gta02_lis302dl_bitbang_read_reg,
 		.lis302dl_bitbang_reg_write = gta02_lis302dl_bitbang_write_reg,
 		.lis302dl_suspend_io = gta02_lis302dl_suspend_io,
diff --git a/drivers/input/misc/lis302dl.c b/drivers/input/misc/lis302dl.c
index 1d5781d..1013f4a 100644
--- a/drivers/input/misc/lis302dl.c
+++ b/drivers/input/misc/lis302dl.c
@@ -4,6 +4,8 @@
  * Author: Harald Welte <laforge@openmoko.org>
  *         converted to private bitbang by:
  *         Andy Green <andy@openmoko.com>
+ *         ability to set acceleration threshold added by:
+ *         Simon Kagstrom <simon.kagstrom@gmail.com>
  * All rights reserved.
  *
  * This program is free software; you can redistribute it and/or
@@ -67,6 +69,31 @@ enum lis302dl_intmode {
 	LIS302DL_INTMODE_CLICK		= 0x07,
 };
 
+#define MG_PER_SAMPLE 18
+
+static void lis302dl_bitbang_read_sample(struct lis302dl_info *lis)
+{
+	u8 data = 0xc0 | LIS302DL_REG_OUT_X; /* read, autoincrement */
+	u8 read[5];
+	unsigned long flags;
+
+	local_irq_save(flags);
+
+	(lis->pdata->lis302dl_bitbang)(lis, &data, 1, &read[0], 5);
+
+	local_irq_restore(flags);
+
+	input_report_rel(lis->input_dev, REL_X, MG_PER_SAMPLE * (s8)read[0]);
+	input_report_rel(lis->input_dev, REL_Y, MG_PER_SAMPLE * (s8)read[2]);
+	input_report_rel(lis->input_dev, REL_Z, MG_PER_SAMPLE * (s8)read[4]);
+
+	input_sync(lis->input_dev);
+
+	/* Reset the HP filter */
+	(lis->pdata->lis302dl_bitbang_reg_read)(lis,
+			LIS302DL_REG_HP_FILTER_RESET);
+}
+
 static void __lis302dl_int_mode(struct device *dev, int int_pin,
 			      enum lis302dl_intmode mode)
 {
@@ -108,7 +135,7 @@ static irqreturn_t lis302dl_interrupt(int irq, void *_lis)
 {
 	struct lis302dl_info *lis = _lis;
 
-	(lis->pdata->lis302dl_bitbang_read_sample)(lis);
+	lis302dl_bitbang_read_sample(lis);
 	return IRQ_HANDLED;
 }
 
@@ -187,6 +214,36 @@ static ssize_t set_scale(struct device *dev, struct device_attribute *attr,
 
 static DEVICE_ATTR(full_scale, S_IRUGO | S_IWUSR, show_scale, set_scale);
 
+static ssize_t show_threshold(struct device *dev, struct device_attribute *attr,
+		 char *buf)
+{
+	struct lis302dl_info *lis = dev_get_drvdata(dev);
+
+	return sprintf(buf, "%d\n", lis->threshold);
+}
+
+static ssize_t set_threshold(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 > 255)
+		return -ERANGE;
+
+	/* Set the threshold and write it out if the device is used */
+	lis->threshold = val;
+	if (lis->flags & LIS302DL_F_INPUT_OPEN)
+		(lis->pdata->lis302dl_bitbang_reg_write)(lis,
+				LIS302DL_REG_FF_WU_THS_1, lis->threshold);
+
+	return count;
+}
+
+static DEVICE_ATTR(threshold, S_IRUGO | S_IWUSR, show_threshold, set_threshold);
+
 static ssize_t lis302dl_dump(struct device *dev, struct device_attribute *attr,
 								      char *buf)
 {
@@ -436,6 +493,7 @@ static DEVICE_ATTR(freefall_wakeup_2, S_IRUGO | S_IWUSR, show_freefall_2,
 static struct attribute *lis302dl_sysfs_entries[] = {
 	&dev_attr_sample_rate.attr,
 	&dev_attr_full_scale.attr,
+	&dev_attr_threshold.attr,
 	&dev_attr_dump.attr,
 	&dev_attr_freefall_wakeup_1.attr,
 	&dev_attr_freefall_wakeup_2.attr,
@@ -454,17 +512,32 @@ static int lis302dl_input_open(struct input_dev *inp)
 	struct lis302dl_info *lis = inp->private;
 	u_int8_t ctrl1 = LIS302DL_CTRL1_PD | LIS302DL_CTRL1_Xen |
 			 LIS302DL_CTRL1_Yen | LIS302DL_CTRL1_Zen;
+	u_int8_t ctrl2 = LIS302DL_CTRL2_HPFF1;
 	unsigned long flags;
 
 	local_irq_save(flags);
 	/* make sure we're powered up and generate data ready */
 	__reg_set_bit_mask(lis, LIS302DL_REG_CTRL1, ctrl1, ctrl1);
 
+	(lis->pdata->lis302dl_bitbang_reg_write)(lis, LIS302DL_REG_CTRL2,
+			ctrl2);
+	(lis->pdata->lis302dl_bitbang_reg_write)(lis,
+			LIS302DL_REG_FF_WU_THS_1, lis->threshold);
+	(lis->pdata->lis302dl_bitbang_reg_write)(lis,
+			LIS302DL_REG_FF_WU_DURATION_1, 0);
+
+	/* Clear the HP filter "starting point" */
+	(lis->pdata->lis302dl_bitbang_reg_read)(lis,
+			LIS302DL_REG_HP_FILTER_RESET);
+	(lis->pdata->lis302dl_bitbang_reg_write)(lis,
+			LIS302DL_REG_FF_WU_CFG_1, LIS302DL_FFWUCFG_XHIE |
+			LIS302DL_FFWUCFG_YHIE |	LIS302DL_FFWUCFG_ZHIE);
+
 	lis->flags |= LIS302DL_F_INPUT_OPEN;
 
 	/* kick it off -- since we are edge triggered, if we missed the edge
 	 * permanent low interrupt is death for us */
-	(lis->pdata->lis302dl_bitbang_read_sample)(lis);
+	lis302dl_bitbang_read_sample(lis);
 
 	local_irq_restore(flags);
 
@@ -567,6 +640,8 @@ static int __devinit lis302dl_probe(struct platform_device *pdev)
 	set_bit(BTN_Y, lis->input_dev->keybit);
 	set_bit(BTN_Z, lis->input_dev->keybit);
 */
+	lis->threshold = 1;
+
 	lis->input_dev->private = lis;
 	lis->input_dev->name = pdata->name;
 	 /* SPI Bus not defined as a valid bus for input subsystem*/
@@ -617,8 +692,8 @@ static int __devinit lis302dl_probe(struct platform_device *pdev)
 		(lis->pdata->lis302dl_bitbang_reg_write)(lis,
 					LIS302DL_REG_CTRL3, LIS302DL_CTRL3_IHL);
 
-	__lis302dl_int_mode(lis->dev, 1, LIS302DL_INTMODE_DATA_READY);
-	__lis302dl_int_mode(lis->dev, 2, LIS302DL_INTMODE_DATA_READY);
+	__lis302dl_int_mode(lis->dev, 1, LIS302DL_INTMODE_FF_WU_12);
+	__lis302dl_int_mode(lis->dev, 2, LIS302DL_INTMODE_FF_WU_12);
 
 	(lis->pdata->lis302dl_bitbang_reg_read)(lis, LIS302DL_REG_STATUS);
 	(lis->pdata->lis302dl_bitbang_reg_read)(lis, LIS302DL_REG_FF_WU_SRC_1);
diff --git a/include/linux/lis302dl.h b/include/linux/lis302dl.h
index 4578db4..f3f994d 100644
--- a/include/linux/lis302dl.h
+++ b/include/linux/lis302dl.h
@@ -16,6 +16,8 @@ struct lis302dl_platform_data {
 	unsigned long pin_miso;
 	int open_drain;
 	int interrupt;
+	void (*lis302dl_bitbang)(struct lis302dl_info *lis, u8 *tx,
+			int tx_bytes, u8 *rx, int rx_bytes);
 	void (*lis302dl_bitbang_read_sample)(struct lis302dl_info *);
 	void (*lis302dl_suspend_io)(struct lis302dl_info *, int resuming);
 	int (*lis302dl_bitbang_reg_read)(struct lis302dl_info *, u8 reg);
@@ -28,6 +30,7 @@ struct lis302dl_info {
 	struct device *dev;
 	struct input_dev *input_dev;
 	unsigned int flags;
+	unsigned int threshold;
 	u_int8_t regs[0x40];
 };
 
-- 
1.5.6.5