[PATCH 1/1]: Acceleration threshold configuration: lis302dl-configure-threshold-on-bitbang.patch

Simon Kagstrom simon.kagstrom at gmail.com
Sun Oct 12 20:54:13 CEST 2008


Configure threshold for accelerometer input

From: Simon Kagstrom <simon.kagstrom at 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 at 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 at openmoko.org>
  *         converted to private bitbang by:
  *         Andy Green <andy at openmoko.com>
+ *         ability to set acceleration threshold added by:
+ *         Simon Kagstrom <simon.kagstrom at 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];
 };
 



More information about the openmoko-kernel mailing list