diff options
-rw-r--r-- | 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 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 }; |