Now that we have everything in place to compute the clock rate at runtime,
we can enable the 60fps framerate for the mode we tested it with.

Signed-off-by: Maxime Ripard <maxime.rip...@bootlin.com>
---
 drivers/media/i2c/ov5640.c | 33 +++++++++++++++++++++++++--------
 1 file changed, 25 insertions(+), 8 deletions(-)

diff --git a/drivers/media/i2c/ov5640.c b/drivers/media/i2c/ov5640.c
index 690ed0238763..c01bbc5f9f34 100644
--- a/drivers/media/i2c/ov5640.c
+++ b/drivers/media/i2c/ov5640.c
@@ -112,6 +112,7 @@ enum ov5640_mode_id {
 enum ov5640_frame_rate {
        OV5640_15_FPS = 0,
        OV5640_30_FPS,
+       OV5640_60_FPS,
        OV5640_NUM_FRAMERATES,
 };
 
@@ -140,6 +141,7 @@ MODULE_PARM_DESC(virtual_channel,
 static const int ov5640_framerates[] = {
        [OV5640_15_FPS] = 15,
        [OV5640_30_FPS] = 30,
+       [OV5640_60_FPS] = 60,
 };
 
 /* regulator supplies */
@@ -1398,12 +1400,19 @@ ov5640_find_mode(struct ov5640_dev *sensor, enum 
ov5640_frame_rate fr,
                                /* try to find another mode */
                                continue;
 
+                       /* Only 640x480 can operate at 60fps (for now) */
+                       if (fr == OV5640_60_FPS &&
+                           width != 640 && height != 480)
+                               /* try to find another mode */
+                               continue;
+
                        break;
                }
        }
 
+       /* VGA is the only mode that supports all the framerates */
        if (nearest && i < 0)
-               mode = &ov5640_mode_data[0];
+               mode = &ov5640_mode_data[OV5640_MODE_VGA_640_480];
 
        return mode;
 }
@@ -1848,12 +1857,13 @@ static int ov5640_try_frame_interval(struct ov5640_dev 
*sensor,
        int ret;
 
        minfps = ov5640_framerates[OV5640_15_FPS];
-       maxfps = ov5640_framerates[OV5640_30_FPS];
+       maxfps = ov5640_framerates[OV5640_60_FPS];
 
        if (fi->numerator == 0) {
                fi->denominator = maxfps;
                fi->numerator = 1;
-               return OV5640_30_FPS;
+               ret = OV5640_60_FPS;
+               goto find_mode;
        }
 
        fps = DIV_ROUND_CLOSEST(fi->denominator, fi->numerator);
@@ -1865,11 +1875,15 @@ static int ov5640_try_frame_interval(struct ov5640_dev 
*sensor,
                fi->denominator = minfps;
        else if (2 * fps >= 2 * minfps + (maxfps - minfps))
                fi->denominator = maxfps;
+
+       if (fi->denominator == minfps)
+               ret = OV5640_15_FPS;
+       else if (fi->denominator == maxfps)
+               ret = OV5640_60_FPS;
        else
-               fi->denominator = minfps;
-
-       ret = (fi->denominator == minfps) ? OV5640_15_FPS : OV5640_30_FPS;
+               ret = OV5640_30_FPS;
 
+find_mode:
        mode = ov5640_find_mode(sensor, ret, width, height, false);
        return mode ? ret : -EINVAL;
 }
@@ -2458,8 +2472,11 @@ static int ov5640_s_frame_interval(struct v4l2_subdev 
*sd,
 
        frame_rate = ov5640_try_frame_interval(sensor, &fi->interval,
                                               mode->hact, mode->vact);
-       if (frame_rate < 0)
-               frame_rate = OV5640_15_FPS;
+       if (frame_rate < 0) {
+               /* Always return a valid frame interval value */
+               fi->interval = sensor->frame_interval;
+               goto out;
+       }
 
        sensor->current_fr = frame_rate;
        sensor->frame_interval = fi->interval;
-- 
2.17.0

Reply via email to