diff --git a/drivers/usb/gadget/function/uvc.h b/drivers/usb/gadget/function/uvc.h index 9727111959b0..886103a1fe9b 100644 --- a/drivers/usb/gadget/function/uvc.h +++ b/drivers/usb/gadget/function/uvc.h @@ -69,7 +69,7 @@ extern unsigned int uvc_gadget_trace_param; #define UVC_MAX_REQUEST_SIZE 64 #define UVC_MAX_EVENTS 4 -#define UVCG_REQUEST_HEADER_LEN 2 +#define UVCG_REQUEST_HEADER_LEN 12 /* ------------------------------------------------------------------------ * Structures diff --git a/drivers/usb/gadget/function/uvc_queue.c b/drivers/usb/gadget/function/uvc_queue.c index 99dc9adf56ef..2cda982f3765 100644 --- a/drivers/usb/gadget/function/uvc_queue.c +++ b/drivers/usb/gadget/function/uvc_queue.c @@ -142,7 +142,7 @@ int uvcg_queue_init(struct uvc_video_queue *queue, struct device *dev, enum v4l2 queue->queue.mem_ops = &vb2_vmalloc_memops; } - queue->queue.timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC + queue->queue.timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_COPY | V4L2_BUF_FLAG_TSTAMP_SRC_EOF; queue->queue.dev = dev; diff --git a/drivers/usb/gadget/function/uvc_video.c b/drivers/usb/gadget/function/uvc_video.c index 80b3d7545150..c648c49ff044 100644 --- a/drivers/usb/gadget/function/uvc_video.c +++ b/drivers/usb/gadget/function/uvc_video.c @@ -12,6 +12,7 @@ #include #include #include +#include #include @@ -27,13 +28,41 @@ static int uvc_video_encode_header(struct uvc_video *video, struct uvc_buffer *buf, u8 *data, int len) { - data[0] = UVCG_REQUEST_HEADER_LEN; + struct uvc_device *uvc = container_of(video, struct uvc_device, video); + struct usb_composite_dev *cdev = uvc->func.config->cdev; + struct timespec64 ts = ns_to_timespec64(buf->buf.vb2_buf.timestamp); + int pos = 2; + data[1] = UVC_STREAM_EOH | video->fid; - if (buf->bytesused - video->queue.buf_used <= len - UVCG_REQUEST_HEADER_LEN) + if (video->queue.buf_used == 0 && ts.tv_sec) { + /* dwClockFrequency is 48 MHz */ + u32 pts = ((u64)ts.tv_sec * USEC_PER_SEC + ts.tv_nsec / NSEC_PER_USEC) * 48; + + data[1] |= UVC_STREAM_PTS; + put_unaligned_le32(pts, &data[pos]); + pos += 4; + } + + if (cdev->gadget->ops->get_frame) { + u32 sof, stc; + + sof = usb_gadget_frame_number(cdev->gadget); + ktime_get_ts64(&ts); + stc = ((u64)ts.tv_sec * USEC_PER_SEC + ts.tv_nsec / NSEC_PER_USEC) * 48; + + data[1] |= UVC_STREAM_SCR; + put_unaligned_le32(stc, &data[pos]); + put_unaligned_le16(sof, &data[pos+4]); + pos += 6; + } + + data[0] = pos; + + if (buf->bytesused - video->queue.buf_used <= len - pos) data[1] |= UVC_STREAM_EOF; - return UVCG_REQUEST_HEADER_LEN; + return pos; } static int