[PATCH 1/3] fix-lis302dl-get-status-confirm-data-ready.patch

Andy Green andy at openmoko.com
Tue Feb 3 10:42:42 CET 2009


Level interrupts solve the sticky loss of service from accels issue.
But currently, we get two service actions per one interrupt, leading to
information getting read and sent to the input subsystem twice.

This patch makes the ISR confirm with the lis302dl status register
that there is fresh data before accepting it, it works around the
issue and allows use of the other information in the status reg by
another patch.

Signed-off-by: Andy Green <andy at openmoko.com>
---

 drivers/input/misc/lis302dl.c |   44 ++++++++++++++++++++++++++++++++++-------
 1 files changed, 37 insertions(+), 7 deletions(-)

diff --git a/drivers/input/misc/lis302dl.c b/drivers/input/misc/lis302dl.c
index a7fb86a..2e3d92d 100644
--- a/drivers/input/misc/lis302dl.c
+++ b/drivers/input/misc/lis302dl.c
@@ -213,23 +213,42 @@ static void _report_btn_double(struct input_dev *inp, int btn)
 
 static void lis302dl_bitbang_read_sample(struct lis302dl_info *lis)
 {
-	u8 data = 0xc0 | LIS302DL_REG_OUT_X; /* read, autoincrement */
-	u8 read[5];
+	u8 data = 0xc0 | LIS302DL_REG_STATUS; /* read, autoincrement */
+	u8 read[(LIS302DL_REG_OUT_Z - LIS302DL_REG_STATUS) + 1];
 	unsigned long flags;
 	int mg_per_sample;
 
 	local_irq_save(flags);
 	mg_per_sample = __threshold_to_mg(lis, 1);
 
-	(lis->pdata->lis302dl_bitbang)(lis, &data, 1, &read[0], 5);
+	(lis->pdata->lis302dl_bitbang)(lis, &data, 1, &read[0], sizeof(read));
 
 	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]);
+	/*
+	 * at the minute the test below fails 50% of the time due to
+	 * a problem with level interrupts causing ISRs to get called twice.
+	 * This is a workaround for that, but actually this test is still
+	 * valid and the information can be used for overrrun stats.
+	 */
 
-	input_sync(lis->input_dev);
+	/* has any kind of overrun been observed by the lis302dl? */
+	if (read[0] & (LIS302DL_STATUS_XOR |
+		       LIS302DL_STATUS_YOR |
+		       LIS302DL_STATUS_ZOR))
+		lis->overruns++;
+
+	/* we have a valid sample set? */
+	if (read[0] & LIS302DL_STATUS_XYZDA) {
+		input_report_rel(lis->input_dev, REL_X, mg_per_sample *
+			    (s8)read[LIS302DL_REG_OUT_X - LIS302DL_REG_STATUS]);
+		input_report_rel(lis->input_dev, REL_Y, mg_per_sample *
+			    (s8)read[LIS302DL_REG_OUT_Y - LIS302DL_REG_STATUS]);
+		input_report_rel(lis->input_dev, REL_Z, mg_per_sample *
+			    (s8)read[LIS302DL_REG_OUT_Z - LIS302DL_REG_STATUS]);
+
+		input_sync(lis->input_dev);
+	}
 
 	/* Reset the HP filter */
 	__reg_read(lis,	LIS302DL_REG_HP_FILTER_RESET);
@@ -246,6 +265,16 @@ static irqreturn_t lis302dl_interrupt(int irq, void *_lis)
 
 /* sysfs */
 
+static ssize_t show_overruns(struct device *dev, struct device_attribute *attr,
+			 char *buf)
+{
+	struct lis302dl_info *lis = dev_get_drvdata(dev);
+
+	return sprintf(buf, "%u\n", lis->overruns);
+}
+
+static DEVICE_ATTR(overruns, S_IRUGO, show_overruns, NULL);
+
 static ssize_t show_rate(struct device *dev, struct device_attribute *attr,
 			 char *buf)
 {
@@ -505,6 +534,7 @@ static struct attribute *lis302dl_sysfs_entries[] = {
 	&dev_attr_dump.attr,
 	&dev_attr_wakeup_threshold.attr,
 	&dev_attr_wakeup_duration.attr,
+	&dev_attr_overruns.attr,
 	NULL
 };
 




More information about the openmoko-kernel mailing list