@@ -94,6 +94,7 @@ static int uvc_queue_setup(struct vb2_queue *vq,
static int uvc_buffer_prepare(struct vb2_buffer *vb)
{
struct uvc_video_queue *queue = vb2_get_drv_priv(vb->vb2_queue);
+ struct uvc_video *video = container_of(queue, struct uvc_video, queue);
struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
struct uvc_buffer *buf = container_of(vbuf, struct uvc_buffer, buf);
@@ -116,8 +117,14 @@ static int uvc_buffer_prepare(struct vb2_buffer *vb)
buf->length = vb2_plane_size(vb, 0);
if (vb->type == V4L2_BUF_TYPE_VIDEO_CAPTURE)
buf->bytesused = 0;
- else
+ else {
+ unsigned int nreq;
+ nreq = DIV_ROUND_UP(video->interval, video->ep->desc->bInterval * 1250);
buf->bytesused = vb2_get_plane_payload(vb, 0);
+ buf->req_payload_size =
+ DIV_ROUND_UP(buf->bytesused +
+ (nreq * UVCG_REQUEST_HEADER_LEN), nreq);
+ }
return 0;
}
@@ -39,6 +39,7 @@ struct uvc_buffer {
unsigned int offset;
unsigned int length;
unsigned int bytesused;
+ unsigned int req_payload_size;
};
#define UVC_QUEUE_DISCONNECTED (1 << 0)
@@ -136,7 +136,7 @@ uvc_video_encode_isoc_sg(struct usb_request *req, struct uvc_video *video,
unsigned int pending = buf->bytesused - video->queue.buf_used;
struct uvc_request *ureq = req->context;
struct scatterlist *sg, *iter;
- unsigned int len = video->req_size;
+ unsigned int len = buf->req_payload_size;
unsigned int sg_left, part = 0;
unsigned int i;
int header_len;
@@ -145,16 +145,15 @@ uvc_video_encode_isoc_sg(struct usb_request *req, struct uvc_video *video,
sg_init_table(sg, ureq->sgt.nents);
/* Init the header. */
- header_len = uvc_video_encode_header(video, buf, ureq->header,
- video->req_size);
+ header_len = uvc_video_encode_header(video, buf, ureq->header, len);
sg_set_buf(sg, ureq->header, header_len);
len -= header_len;
if (pending <= len)
len = pending;
- req->length = (len == pending) ?
- len + header_len : video->req_size;
+ req->length = (len == pending) ? len + header_len :
+ buf->req_payload_size;
/* Init the pending sgs with payload */
sg = sg_next(sg);
@@ -202,7 +201,7 @@ uvc_video_encode_isoc(struct usb_request *req, struct uvc_video *video,
{
void *mem = req->buf;
struct uvc_request *ureq = req->context;
- int len = video->req_size;
+ int len = buf->req_payload_size;
int ret;
/* Add the header. */
@@ -214,7 +213,7 @@ uvc_video_encode_isoc(struct usb_request *req, struct uvc_video *video,
ret = uvc_video_encode_data(video, buf, mem, len);
len -= ret;
- req->length = video->req_size - len;
+ req->length = buf->req_payload_size - len;
if (buf->bytesused == video->queue.buf_used ||
video->queue.flags & UVC_QUEUE_DROP_INCOMPLETE) {
For uncompressed formats it makes sense to fill the requests with its maximum since the amount of requests and its size is calculated for this exact amount. Compressed formats generate content depending amount of data that is set in the vb2 buffer by the payload_size. When streaming those formats it is even better to scatter that smaller data over all requests. Signed-off-by: Michael Grzeschik <m.grzeschik@pengutronix.de> --- v1 -> v3: new patch --- drivers/usb/gadget/function/uvc_queue.c | 9 ++++++++- drivers/usb/gadget/function/uvc_queue.h | 1 + drivers/usb/gadget/function/uvc_video.c | 13 ++++++------- 3 files changed, 15 insertions(+), 8 deletions(-)