@@ -471,8 +471,31 @@ static void uvc_video_clock_add_sample(struct uvc_clock *clock,
{
unsigned long flags;
+ /*
+ * If we write new data on the position where we had the last
+ * overflow, remove the overflow pointer. There is no overflow
+ * on the whole circular buffer.
+ */
+ if (clock->head == clock->last_sof_overflow)
+ clock->last_sof_overflow = -1;
+
spin_lock_irqsave(&clock->lock, flags);
+ /* Handle overflows */
+ if (clock->count > 0 && clock->last_sof > sample->dev_sof) {
+ /*
+ * Remove data from the circular buffer that is older than the
+ * last overflow. We only support one overflow per circular
+ * buffer.
+ */
+ if (clock->last_sof_overflow != -1) {
+ clock->count = (clock->head - clock->last_sof_overflow
+ + clock->count) % clock->count;
+ }
+ clock->last_sof_overflow = clock->head;
+ }
+
+ /* Add sample */
clock->samples[clock->head] = *sample;
clock->head = (clock->head + 1) % clock->size;
clock->count = min(clock->count + 1, clock->size);
@@ -616,6 +639,7 @@ static void uvc_video_clock_reset(struct uvc_clock *clock)
clock->head = 0;
clock->count = 0;
clock->last_sof = -1;
+ clock->last_sof_overflow = -1;
clock->sof_offset = -1;
}
@@ -499,6 +499,7 @@ struct uvc_streaming {
unsigned int head;
unsigned int count;
unsigned int size;
+ unsigned int last_sof_overflow;
u16 last_sof;
u16 sof_offset;