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:
Jean-Baptiste Maneyrol
2026-07-20 12:38:33 +02:00
committed by Jonathan Cameron
parent 1330597c74
commit 8f4b627656

View File

@@ -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");