These changes are the raw update to linux-4.4.6-rt14. Kernel sources
[kvmfornfv.git] / kernel / drivers / media / usb / uvc / uvc_video.c
index 20ccc9d..2b276ab 100644 (file)
@@ -119,6 +119,14 @@ static void uvc_fixup_video_ctrl(struct uvc_streaming *stream,
                ctrl->dwMaxVideoFrameSize =
                        frame->dwMaxVideoFrameBufferSize;
 
+       /* The "TOSHIBA Web Camera - 5M" Chicony device (04f2:b50b) seems to
+        * compute the bandwidth on 16 bits and erroneously sign-extend it to
+        * 32 bits, resulting in a huge bandwidth value. Detect and fix that
+        * condition by setting the 16 MSBs to 0 when they're all equal to 1.
+        */
+       if ((ctrl->dwMaxPayloadTransferSize & 0xffff0000) == 0xffff0000)
+               ctrl->dwMaxPayloadTransferSize &= ~0xffff0000;
+
        if (!(format->flags & UVC_FMT_FLAG_COMPRESSED) &&
            stream->dev->quirks & UVC_QUIRK_FIX_BANDWIDTH &&
            stream->intf->num_altsetting > 1) {
@@ -598,7 +606,7 @@ static u16 uvc_video_clock_host_sof(const struct uvc_clock_sample *sample)
  * timestamp of the sliding window to 1s.
  */
 void uvc_video_clock_update(struct uvc_streaming *stream,
-                           struct v4l2_buffer *v4l2_buf,
+                           struct vb2_v4l2_buffer *vbuf,
                            struct uvc_buffer *buf)
 {
        struct uvc_clock *clock = &stream->clock;
@@ -615,6 +623,9 @@ void uvc_video_clock_update(struct uvc_streaming *stream,
        u32 rem;
        u64 y;
 
+       if (!uvc_hw_timestamps_param)
+               return;
+
        spin_lock_irqsave(&clock->lock, flags);
 
        if (clock->count < clock->size)
@@ -688,14 +699,14 @@ void uvc_video_clock_update(struct uvc_streaming *stream,
                  stream->dev->name,
                  sof >> 16, div_u64(((u64)sof & 0xffff) * 1000000LLU, 65536),
                  y, ts.tv_sec, ts.tv_nsec / NSEC_PER_USEC,
-                 v4l2_buf->timestamp.tv_sec,
-                 (unsigned long)v4l2_buf->timestamp.tv_usec,
+                 vbuf->timestamp.tv_sec,
+                 (unsigned long)vbuf->timestamp.tv_usec,
                  x1, first->host_sof, first->dev_sof,
                  x2, last->host_sof, last->dev_sof, y1, y2);
 
        /* Update the V4L2 buffer. */
-       v4l2_buf->timestamp.tv_sec = ts.tv_sec;
-       v4l2_buf->timestamp.tv_usec = ts.tv_nsec / NSEC_PER_USEC;
+       vbuf->timestamp.tv_sec = ts.tv_sec;
+       vbuf->timestamp.tv_usec = ts.tv_nsec / NSEC_PER_USEC;
 
 done:
        spin_unlock_irqrestore(&stream->clock.lock, flags);
@@ -1021,10 +1032,10 @@ static int uvc_video_decode_start(struct uvc_streaming *stream,
 
                uvc_video_get_ts(&ts);
 
-               buf->buf.v4l2_buf.field = V4L2_FIELD_NONE;
-               buf->buf.v4l2_buf.sequence = stream->sequence;
-               buf->buf.v4l2_buf.timestamp.tv_sec = ts.tv_sec;
-               buf->buf.v4l2_buf.timestamp.tv_usec =
+               buf->buf.field = V4L2_FIELD_NONE;
+               buf->buf.sequence = stream->sequence;
+               buf->buf.timestamp.tv_sec = ts.tv_sec;
+               buf->buf.timestamp.tv_usec =
                        ts.tv_nsec / NSEC_PER_USEC;
 
                /* TODO: Handle PTS and SCR. */
@@ -1297,7 +1308,7 @@ static void uvc_video_encode_bulk(struct urb *urb, struct uvc_streaming *stream,
                if (buf->bytesused == stream->queue.buf_used) {
                        stream->queue.buf_used = 0;
                        buf->state = UVC_BUF_STATE_READY;
-                       buf->buf.v4l2_buf.sequence = ++stream->sequence;
+                       buf->buf.sequence = ++stream->sequence;
                        uvc_queue_next_buffer(&stream->queue, buf);
                        stream->last_fid ^= UVC_STREAM_FID;
                }