mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2026-08-31 14:04:27 -04:00
iio: inv_sensors: better timestamp alignment when using watermark
Current interrupt timestamp alignment only changes the final timestamp. When the watermark is in use, we have a batch of samples for each interrupt. The current code doesn't manage to align the timestamp because the jitter is too high. Instead modify the estimated inter interrupt period and use that to adjust the timestamp alignment over the batch in a linear fashion. Signed-off-by: Jean-Baptiste Maneyrol <jean-baptiste.maneyrol@tdk.com> Signed-off-by: Jonathan Cameron <jonathan.cameron@oss.qualcomm.com>
This commit is contained in:
committed by
Jonathan Cameron
parent
1330597c74
commit
8f4b627656
@@ -10,9 +10,7 @@
|
||||
|
||||
#include <linux/iio/common/inv_sensors_timestamp.h>
|
||||
|
||||
/* compute jitter, min and max following jitter in per mille */
|
||||
#define INV_SENSORS_TIMESTAMP_JITTER(_val, _jitter) \
|
||||
(div_s64((_val) * (_jitter), 1000))
|
||||
/* compute min and max following jitter in per mille */
|
||||
#define INV_SENSORS_TIMESTAMP_MIN(_val, _jitter) \
|
||||
(((_val) * (1000 - (_jitter))) / 1000)
|
||||
#define INV_SENSORS_TIMESTAMP_MAX(_val, _jitter) \
|
||||
@@ -102,34 +100,22 @@ static bool inv_update_chip_period(struct inv_sensors_timestamp *ts,
|
||||
/* update chip internal period estimation */
|
||||
new_chip_period = period / ts->mult;
|
||||
inv_update_acc(&ts->chip_period, new_chip_period);
|
||||
ts->period = ts->mult * ts->chip_period.val;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static void inv_align_timestamp_it(struct inv_sensors_timestamp *ts)
|
||||
static u32 inv_align_timestamp_it(struct inv_sensors_timestamp *ts,
|
||||
unsigned int sample_nb)
|
||||
{
|
||||
const s64 period_min = (s64)ts->min_period * ts->mult;
|
||||
const s64 period_max = (s64)ts->max_period * ts->mult;
|
||||
s64 add_max, sub_max;
|
||||
s64 delta, jitter;
|
||||
s64 adjust;
|
||||
s64 new_period;
|
||||
|
||||
/* delta time between last sample and last interrupt */
|
||||
delta = ts->it.lo - ts->timestamp;
|
||||
/* compute new period aligning last timestamp with interrupt timestamp */
|
||||
new_period = div_s64(ts->it.up - ts->timestamp, sample_nb);
|
||||
|
||||
/* adjust timestamp while respecting jitter */
|
||||
add_max = period_max - (s64)ts->period;
|
||||
sub_max = period_min - (s64)ts->period;
|
||||
jitter = INV_SENSORS_TIMESTAMP_JITTER((s64)ts->period, ts->chip.jitter);
|
||||
if (delta > jitter)
|
||||
adjust = add_max;
|
||||
else if (delta < -jitter)
|
||||
adjust = sub_max;
|
||||
else
|
||||
adjust = 0;
|
||||
|
||||
ts->timestamp += adjust;
|
||||
/* ensure that period never overflows the jitter */
|
||||
return clamp(new_period, period_min, period_max);
|
||||
}
|
||||
|
||||
void inv_sensors_timestamp_interrupt(struct inv_sensors_timestamp *ts,
|
||||
@@ -143,6 +129,13 @@ void inv_sensors_timestamp_interrupt(struct inv_sensors_timestamp *ts,
|
||||
if (sample_nb == 0)
|
||||
return;
|
||||
|
||||
/* no previous data, compute theoretical value from interrupt */
|
||||
if (ts->timestamp == 0) {
|
||||
/* elapsed time: sensor period * sensor samples number */
|
||||
interval = (s64)ts->period * (s64)sample_nb;
|
||||
ts->timestamp = timestamp - interval;
|
||||
}
|
||||
|
||||
/* update interrupt timestamp and compute chip and sensor periods */
|
||||
it = &ts->it;
|
||||
it->lo = it->up;
|
||||
@@ -154,17 +147,11 @@ void inv_sensors_timestamp_interrupt(struct inv_sensors_timestamp *ts,
|
||||
valid = inv_update_chip_period(ts, period);
|
||||
}
|
||||
|
||||
/* no previous data, compute theoretical value from interrupt */
|
||||
if (ts->timestamp == 0) {
|
||||
/* elapsed time: sensor period * sensor samples number */
|
||||
interval = (s64)ts->period * (s64)sample_nb;
|
||||
ts->timestamp = it->up - interval;
|
||||
return;
|
||||
}
|
||||
|
||||
/* if interrupt interval is valid, sync with interrupt timestamp */
|
||||
if (valid)
|
||||
inv_align_timestamp_it(ts);
|
||||
ts->period = inv_align_timestamp_it(ts, sample_nb);
|
||||
else
|
||||
ts->period = ts->mult * ts->chip_period.val;
|
||||
}
|
||||
EXPORT_SYMBOL_NS_GPL(inv_sensors_timestamp_interrupt, "IIO_INV_SENSORS_TIMESTAMP");
|
||||
|
||||
|
||||
Reference in New Issue
Block a user