[PATCH 3/5]: lis302dl-configure-duration.patch

Simon Kagstrom simon.kagstrom at gmail.com
Wed Oct 15 20:13:26 CEST 2008


Allow configuration of the duration for thresholds

From: Simon Kagstrom <simon.kagstrom at 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 at 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 */



More information about the openmoko-kernel mailing list