{
        struct uvc_streaming_control probe;
        struct v4l2_fract timeperframe;
-       uint32_t interval;
+       struct uvc_format *format;
+       struct uvc_frame *frame;
+       __u32 interval, maxd;
+       unsigned int i;
        int ret;
 
        if (parm->type != stream->type)
                return -EBUSY;
        }
 
+       format = stream->cur_format;
+       frame = stream->cur_frame;
        probe = stream->ctrl;
-       probe.dwFrameInterval =
-               uvc_try_frame_interval(stream->cur_frame, interval);
+       probe.dwFrameInterval = uvc_try_frame_interval(frame, interval);
+       maxd = abs((__s32)probe.dwFrameInterval - interval);
+
+       /* Try frames with matching size to find the best frame interval. */
+       for (i = 0; i < format->nframes && maxd != 0; i++) {
+               __u32 d, ival;
+
+               if (&format->frame[i] == stream->cur_frame)
+                       continue;
+
+               if (format->frame[i].wWidth != stream->cur_frame->wWidth ||
+                   format->frame[i].wHeight != stream->cur_frame->wHeight)
+                       continue;
+
+               ival = uvc_try_frame_interval(&format->frame[i], interval);
+               d = abs((__s32)ival - interval);
+               if (d >= maxd)
+                       continue;
+
+               frame = &format->frame[i];
+               probe.bFrameIndex = frame->bFrameIndex;
+               probe.dwFrameInterval = ival;
+               maxd = d;
+       }
 
        /* Probe the device with the new settings. */
        ret = uvc_probe_video(stream, &probe);
        }
 
        stream->ctrl = probe;
+       stream->cur_frame = frame;
        mutex_unlock(&stream->mutex);
 
        /* Return the actual frame period. */
        struct uvc_streaming *stream = handle->stream;
        struct uvc_format *format = NULL;
        struct uvc_frame *frame;
-       int i;
+       unsigned int index;
+       unsigned int i;
 
        /* Look for the given pixel format */
        for (i = 0; i < stream->nformats; i++) {
        if (format == NULL)
                return -EINVAL;
 
-       if (fsize->index >= format->nframes)
+       /* Skip duplicate frame sizes */
+       for (i = 0, index = 0; i < format->nframes; i++) {
+               if (i && frame->wWidth == format->frame[i].wWidth &&
+                   frame->wHeight == format->frame[i].wHeight)
+                       continue;
+               frame = &format->frame[i];
+               if (index == fsize->index)
+                       break;
+               index++;
+       }
+
+       if (i == format->nframes)
                return -EINVAL;
 
-       frame = &format->frame[fsize->index];
        fsize->type = V4L2_FRMSIZE_TYPE_DISCRETE;
        fsize->discrete.width = frame->wWidth;
        fsize->discrete.height = frame->wHeight;
        struct uvc_streaming *stream = handle->stream;
        struct uvc_format *format = NULL;
        struct uvc_frame *frame = NULL;
-       int i;
+       unsigned int nintervals;
+       unsigned int index;
+       unsigned int i;
 
        /* Look for the given pixel format and frame size */
        for (i = 0; i < stream->nformats; i++) {
        if (format == NULL)
                return -EINVAL;
 
+       index = fival->index;
        for (i = 0; i < format->nframes; i++) {
                if (format->frame[i].wWidth == fival->width &&
                    format->frame[i].wHeight == fival->height) {
                        frame = &format->frame[i];
-                       break;
+                       nintervals = frame->bFrameIntervalType ?: 1;
+                       if (index < nintervals)
+                               break;
+                       index -= nintervals;
                }
        }
-       if (frame == NULL)
+       if (i == format->nframes)
                return -EINVAL;
 
        if (frame->bFrameIntervalType) {
-               if (fival->index >= frame->bFrameIntervalType)
-                       return -EINVAL;
-
                fival->type = V4L2_FRMIVAL_TYPE_DISCRETE;
                fival->discrete.numerator =
-                       frame->dwFrameInterval[fival->index];
+                       frame->dwFrameInterval[index];
                fival->discrete.denominator = 10000000;
                uvc_simplify_fraction(&fival->discrete.numerator,
                        &fival->discrete.denominator, 8, 333);
        } else {
-               if (fival->index)
-                       return -EINVAL;
-
                fival->type = V4L2_FRMIVAL_TYPE_STEPWISE;
                fival->stepwise.min.numerator = frame->dwFrameInterval[0];
                fival->stepwise.min.denominator = 10000000;