{
        const struct ov5640_mode_info *mode;
        enum ov5640_frame_rate rate = OV5640_30_FPS;
-       u32 minfps, maxfps, fps;
+       int minfps, maxfps, best_fps, fps;
+       int i;
 
        minfps = ov5640_framerates[OV5640_15_FPS];
        maxfps = ov5640_framerates[OV5640_30_FPS];
                return OV5640_30_FPS;
        }
 
-       fps = DIV_ROUND_CLOSEST(fi->denominator, fi->numerator);
+       fps = clamp_val(DIV_ROUND_CLOSEST(fi->denominator, fi->numerator),
+                       minfps, maxfps);
 
-       fi->numerator = 1;
-       if (fps > maxfps)
-               fi->denominator = maxfps;
-       else if (fps < minfps)
-               fi->denominator = minfps;
-       else if (2 * fps >= 2 * minfps + (maxfps - minfps))
-               fi->denominator = maxfps;
-       else
-               fi->denominator = minfps;
+       best_fps = minfps;
+       for (i = 0; i < ARRAY_SIZE(ov5640_framerates); i++) {
+               int curr_fps = ov5640_framerates[i];
 
-       rate = (fi->denominator == minfps) ? OV5640_15_FPS : OV5640_30_FPS;
+               if (abs(curr_fps - fps) < abs(best_fps - fps)) {
+                       best_fps = curr_fps;
+                       rate = i;
+               }
+       }
+
+       fi->numerator = 1;
+       fi->denominator = best_fps;
 
        mode = ov5640_find_mode(sensor, rate, width, height, false);
        return mode ? rate : -EINVAL;