Commit 57c1d5de authored by Deborah Brouwer's avatar Deborah Brouwer Committed by Mauro Carvalho Chehab

media: vivid: fix timestamp and sequence wrapping

The error injection controls that test wrap-around sequence and timestamp
counters were partially broken. Add a menu option for 64 or 32 bit signed
timestamp wrapping. Prevent the timestamp from wrapping around before the
device can be tested.  Remove the sequence count from the timestamp
calculation so that sequence wrapping does not interfere with the
timestamp.  Add consistent time and sequence wrapping to sdr and touch
devices.
Signed-off-by: default avatarDeborah Brouwer <deborahbrouwer3563@gmail.com>
Signed-off-by: default avatarHans Verkuil <hverkuil-cisco@xs4all.nl>
Signed-off-by: default avatarMauro Carvalho Chehab <mchehab@kernel.org>
parent 9a0e3cd5
...@@ -307,7 +307,7 @@ struct vivid_dev { ...@@ -307,7 +307,7 @@ struct vivid_dev {
bool dqbuf_error; bool dqbuf_error;
bool req_validate_error; bool req_validate_error;
bool seq_wrap; bool seq_wrap;
bool time_wrap; u64 time_wrap;
u64 time_wrap_offset; u64 time_wrap_offset;
unsigned perc_dropped_buffers; unsigned perc_dropped_buffers;
enum vivid_signal_mode std_signal_mode[MAX_INPUTS]; enum vivid_signal_mode std_signal_mode[MAX_INPUTS];
...@@ -437,6 +437,7 @@ struct vivid_dev { ...@@ -437,6 +437,7 @@ struct vivid_dev {
bool touch_cap_seq_resync; bool touch_cap_seq_resync;
u32 touch_cap_seq_start; u32 touch_cap_seq_start;
u32 touch_cap_seq_count; u32 touch_cap_seq_count;
u32 touch_cap_with_seq_wrap_count;
bool touch_cap_streaming; bool touch_cap_streaming;
struct v4l2_fract timeperframe_tch_cap; struct v4l2_fract timeperframe_tch_cap;
struct v4l2_pix_format tch_format; struct v4l2_pix_format tch_format;
...@@ -524,7 +525,9 @@ struct vivid_dev { ...@@ -524,7 +525,9 @@ struct vivid_dev {
struct task_struct *kthread_sdr_cap; struct task_struct *kthread_sdr_cap;
unsigned long jiffies_sdr_cap; unsigned long jiffies_sdr_cap;
u32 sdr_cap_seq_offset; u32 sdr_cap_seq_offset;
u32 sdr_cap_seq_start;
u32 sdr_cap_seq_count; u32 sdr_cap_seq_count;
u32 sdr_cap_with_seq_wrap_count;
bool sdr_cap_seq_resync; bool sdr_cap_seq_resync;
/* RDS generator */ /* RDS generator */
......
...@@ -1084,7 +1084,6 @@ static const struct v4l2_ctrl_config vivid_ctrl_display_present = { ...@@ -1084,7 +1084,6 @@ static const struct v4l2_ctrl_config vivid_ctrl_display_present = {
static int vivid_streaming_s_ctrl(struct v4l2_ctrl *ctrl) static int vivid_streaming_s_ctrl(struct v4l2_ctrl *ctrl)
{ {
struct vivid_dev *dev = container_of(ctrl->handler, struct vivid_dev, ctrl_hdl_streaming); struct vivid_dev *dev = container_of(ctrl->handler, struct vivid_dev, ctrl_hdl_streaming);
u64 rem;
switch (ctrl->id) { switch (ctrl->id) {
case VIVID_CID_DQBUF_ERROR: case VIVID_CID_DQBUF_ERROR:
...@@ -1122,20 +1121,10 @@ static int vivid_streaming_s_ctrl(struct v4l2_ctrl *ctrl) ...@@ -1122,20 +1121,10 @@ static int vivid_streaming_s_ctrl(struct v4l2_ctrl *ctrl)
break; break;
case VIVID_CID_TIME_WRAP: case VIVID_CID_TIME_WRAP:
dev->time_wrap = ctrl->val; dev->time_wrap = ctrl->val;
if (ctrl->val == 0) { if (dev->time_wrap == 1)
dev->time_wrap_offset = 0; dev->time_wrap = (1ULL << 63) - NSEC_PER_SEC * 16ULL;
break; else if (dev->time_wrap == 2)
} dev->time_wrap = ((1ULL << 31) - 16) * NSEC_PER_SEC;
/*
* We want to set the time 16 seconds before the 32 bit tv_sec
* value of struct timeval would wrap around. So first we
* calculate ktime_get_ns() % ((1 << 32) * NSEC_PER_SEC), and
* then we set the offset to ((1 << 32) - 16) * NSEC_PER_SEC).
*/
div64_u64_rem(ktime_get_ns(),
0x100000000ULL * NSEC_PER_SEC, &rem);
dev->time_wrap_offset =
(0x100000000ULL - 16) * NSEC_PER_SEC - rem;
break; break;
} }
return 0; return 0;
...@@ -1208,13 +1197,20 @@ static const struct v4l2_ctrl_config vivid_ctrl_seq_wrap = { ...@@ -1208,13 +1197,20 @@ static const struct v4l2_ctrl_config vivid_ctrl_seq_wrap = {
.step = 1, .step = 1,
}; };
static const char * const vivid_ctrl_time_wrap_strings[] = {
"None",
"64 Bit",
"32 Bit",
NULL,
};
static const struct v4l2_ctrl_config vivid_ctrl_time_wrap = { static const struct v4l2_ctrl_config vivid_ctrl_time_wrap = {
.ops = &vivid_streaming_ctrl_ops, .ops = &vivid_streaming_ctrl_ops,
.id = VIVID_CID_TIME_WRAP, .id = VIVID_CID_TIME_WRAP,
.name = "Wrap Timestamp", .name = "Wrap Timestamp",
.type = V4L2_CTRL_TYPE_BOOLEAN, .type = V4L2_CTRL_TYPE_MENU,
.max = 1, .max = ARRAY_SIZE(vivid_ctrl_time_wrap_strings) - 2,
.step = 1, .qmenu = vivid_ctrl_time_wrap_strings,
}; };
......
...@@ -719,8 +719,7 @@ static noinline_for_stack void vivid_thread_vid_cap_tick(struct vivid_dev *dev, ...@@ -719,8 +719,7 @@ static noinline_for_stack void vivid_thread_vid_cap_tick(struct vivid_dev *dev,
if (!vid_cap_buf && !vbi_cap_buf && !meta_cap_buf) if (!vid_cap_buf && !vbi_cap_buf && !meta_cap_buf)
goto update_mv; goto update_mv;
f_time = dev->cap_frame_period * dev->vid_cap_seq_count + f_time = ktime_get_ns() + dev->time_wrap_offset;
dev->cap_stream_start + dev->time_wrap_offset;
if (vid_cap_buf) { if (vid_cap_buf) {
v4l2_ctrl_request_setup(vid_cap_buf->vb.vb2_buf.req_obj.req, v4l2_ctrl_request_setup(vid_cap_buf->vb.vb2_buf.req_obj.req,
...@@ -813,6 +812,10 @@ static int vivid_thread_vid_cap(void *data) ...@@ -813,6 +812,10 @@ static int vivid_thread_vid_cap(void *data)
dev->cap_seq_resync = false; dev->cap_seq_resync = false;
dev->jiffies_vid_cap = jiffies; dev->jiffies_vid_cap = jiffies;
dev->cap_stream_start = ktime_get_ns(); dev->cap_stream_start = ktime_get_ns();
if (dev->time_wrap)
dev->time_wrap_offset = dev->time_wrap - dev->cap_stream_start;
else
dev->time_wrap_offset = 0;
vivid_cap_update_frame_period(dev); vivid_cap_update_frame_period(dev);
for (;;) { for (;;) {
......
...@@ -154,12 +154,13 @@ static int vivid_thread_vid_out(void *data) ...@@ -154,12 +154,13 @@ static int vivid_thread_vid_out(void *data)
/* Resets frame counters */ /* Resets frame counters */
dev->out_seq_offset = 0; dev->out_seq_offset = 0;
if (dev->seq_wrap) dev->out_seq_count = 0;
dev->out_seq_count = 0xffffff80U;
dev->jiffies_vid_out = jiffies; dev->jiffies_vid_out = jiffies;
dev->vid_out_seq_start = dev->vbi_out_seq_start = 0;
dev->meta_out_seq_start = 0;
dev->out_seq_resync = false; dev->out_seq_resync = false;
if (dev->time_wrap)
dev->time_wrap_offset = dev->time_wrap - ktime_get_ns();
else
dev->time_wrap_offset = 0;
for (;;) { for (;;) {
try_to_freeze(); try_to_freeze();
......
...@@ -62,6 +62,10 @@ static int vivid_thread_touch_cap(void *data) ...@@ -62,6 +62,10 @@ static int vivid_thread_touch_cap(void *data)
dev->touch_cap_seq_count = 0; dev->touch_cap_seq_count = 0;
dev->touch_cap_seq_resync = false; dev->touch_cap_seq_resync = false;
dev->jiffies_touch_cap = jiffies; dev->jiffies_touch_cap = jiffies;
if (dev->time_wrap)
dev->time_wrap_offset = dev->time_wrap - ktime_get_ns();
else
dev->time_wrap_offset = 0;
for (;;) { for (;;) {
try_to_freeze(); try_to_freeze();
...@@ -102,6 +106,8 @@ static int vivid_thread_touch_cap(void *data) ...@@ -102,6 +106,8 @@ static int vivid_thread_touch_cap(void *data)
} }
dropped_bufs = buffers_since_start + dev->touch_cap_seq_offset - dev->touch_cap_seq_count; dropped_bufs = buffers_since_start + dev->touch_cap_seq_offset - dev->touch_cap_seq_count;
dev->touch_cap_seq_count = buffers_since_start + dev->touch_cap_seq_offset; dev->touch_cap_seq_count = buffers_since_start + dev->touch_cap_seq_offset;
dev->touch_cap_with_seq_wrap_count =
dev->touch_cap_seq_count - dev->touch_cap_seq_start;
vivid_thread_tch_cap_tick(dev, dropped_bufs); vivid_thread_tch_cap_tick(dev, dropped_bufs);
...@@ -143,6 +149,7 @@ int vivid_start_generating_touch_cap(struct vivid_dev *dev) ...@@ -143,6 +149,7 @@ int vivid_start_generating_touch_cap(struct vivid_dev *dev)
return 0; return 0;
} }
dev->touch_cap_seq_start = dev->seq_wrap * 128;
dev->kthread_touch_cap = kthread_run(vivid_thread_touch_cap, dev, dev->kthread_touch_cap = kthread_run(vivid_thread_touch_cap, dev,
"%s-tch-cap", dev->v4l2_dev.name); "%s-tch-cap", dev->v4l2_dev.name);
......
...@@ -101,7 +101,7 @@ static void vivid_thread_sdr_cap_tick(struct vivid_dev *dev) ...@@ -101,7 +101,7 @@ static void vivid_thread_sdr_cap_tick(struct vivid_dev *dev)
spin_unlock(&dev->slock); spin_unlock(&dev->slock);
if (sdr_cap_buf) { if (sdr_cap_buf) {
sdr_cap_buf->vb.sequence = dev->sdr_cap_seq_count; sdr_cap_buf->vb.sequence = dev->sdr_cap_with_seq_wrap_count;
v4l2_ctrl_request_setup(sdr_cap_buf->vb.vb2_buf.req_obj.req, v4l2_ctrl_request_setup(sdr_cap_buf->vb.vb2_buf.req_obj.req,
&dev->ctrl_hdl_sdr_cap); &dev->ctrl_hdl_sdr_cap);
v4l2_ctrl_request_complete(sdr_cap_buf->vb.vb2_buf.req_obj.req, v4l2_ctrl_request_complete(sdr_cap_buf->vb.vb2_buf.req_obj.req,
...@@ -131,10 +131,13 @@ static int vivid_thread_sdr_cap(void *data) ...@@ -131,10 +131,13 @@ static int vivid_thread_sdr_cap(void *data)
/* Resets frame counters */ /* Resets frame counters */
dev->sdr_cap_seq_offset = 0; dev->sdr_cap_seq_offset = 0;
if (dev->seq_wrap) dev->sdr_cap_seq_count = 0;
dev->sdr_cap_seq_offset = 0xffffff80U;
dev->jiffies_sdr_cap = jiffies; dev->jiffies_sdr_cap = jiffies;
dev->sdr_cap_seq_resync = false; dev->sdr_cap_seq_resync = false;
if (dev->time_wrap)
dev->time_wrap_offset = dev->time_wrap - ktime_get_ns();
else
dev->time_wrap_offset = 0;
for (;;) { for (;;) {
try_to_freeze(); try_to_freeze();
...@@ -174,6 +177,7 @@ static int vivid_thread_sdr_cap(void *data) ...@@ -174,6 +177,7 @@ static int vivid_thread_sdr_cap(void *data)
} }
dev->sdr_cap_seq_count = dev->sdr_cap_seq_count =
buffers_since_start + dev->sdr_cap_seq_offset; buffers_since_start + dev->sdr_cap_seq_offset;
dev->sdr_cap_with_seq_wrap_count = dev->sdr_cap_seq_count - dev->sdr_cap_seq_start;
vivid_thread_sdr_cap_tick(dev); vivid_thread_sdr_cap_tick(dev);
mutex_unlock(&dev->mutex); mutex_unlock(&dev->mutex);
...@@ -263,7 +267,7 @@ static int sdr_cap_start_streaming(struct vb2_queue *vq, unsigned count) ...@@ -263,7 +267,7 @@ static int sdr_cap_start_streaming(struct vb2_queue *vq, unsigned count)
int err = 0; int err = 0;
dprintk(dev, 1, "%s\n", __func__); dprintk(dev, 1, "%s\n", __func__);
dev->sdr_cap_seq_count = 0; dev->sdr_cap_seq_start = dev->seq_wrap * 128;
if (dev->start_streaming_error) { if (dev->start_streaming_error) {
dev->start_streaming_error = false; dev->start_streaming_error = false;
err = -EINVAL; err = -EINVAL;
......
...@@ -262,7 +262,7 @@ void vivid_fillbuff_tch(struct vivid_dev *dev, struct vivid_buffer *buf) ...@@ -262,7 +262,7 @@ void vivid_fillbuff_tch(struct vivid_dev *dev, struct vivid_buffer *buf)
__s16 *tch_buf = vb2_plane_vaddr(&buf->vb.vb2_buf, 0); __s16 *tch_buf = vb2_plane_vaddr(&buf->vb.vb2_buf, 0);
buf->vb.sequence = dev->touch_cap_seq_count; buf->vb.sequence = dev->touch_cap_with_seq_wrap_count;
test_pattern = (buf->vb.sequence / TCH_SEQ_COUNT) % TEST_CASE_MAX; test_pattern = (buf->vb.sequence / TCH_SEQ_COUNT) % TEST_CASE_MAX;
test_pat_idx = buf->vb.sequence % TCH_SEQ_COUNT; test_pat_idx = buf->vb.sequence % TCH_SEQ_COUNT;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment