aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--drivers/input/misc/lis302dl.c44
1 files changed, 37 insertions, 7 deletions
diff --git a/drivers/input/misc/lis302dl.c b/drivers/input/misc/lis302dl.c
index a7fb86a2504..2e3d92decab 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
};