v4l2: fixed v4l2 compliance issue
authorchanghuang.liang <changhuang.liang@starfivetech.com>
Tue, 19 Jul 2022 02:20:40 +0000 (10:20 +0800)
committermason.huo <mason.huo@starfivetech.com>
Thu, 21 Jul 2022 08:58:11 +0000 (16:58 +0800)
imx219 add set/get frameintervals

Signed-off-by: changhuang.liang <changhuang.liang@starfivetech.com>
drivers/media/platform/starfive/v4l2_driver/imx219_mipi.c
drivers/media/platform/starfive/v4l2_driver/stf_video.c
drivers/media/platform/starfive/v4l2_driver/stf_video.h

index 965a174..40ae5b4 100644 (file)
@@ -136,6 +136,8 @@ struct imx219_mode {
        /* Frame height */
        unsigned int height;
 
+       unsigned int fps;
+
        /* Analog crop rectangle. */
        struct v4l2_rect crop;
 
@@ -475,6 +477,7 @@ static const struct imx219_mode supported_modes[] = {
                /* 8MPix 15fps mode */
                .width = 3280,
                .height = 2464,
+               .fps = 15,
                .crop = {
                        .left = IMX219_PIXEL_ARRAY_LEFT,
                        .top = IMX219_PIXEL_ARRAY_TOP,
@@ -491,6 +494,7 @@ static const struct imx219_mode supported_modes[] = {
                /* 1080P 30fps cropped */
                .width = 1920,
                .height = 1080,
+               .fps = 30,
                .crop = {
                        .left = 688,
                        .top = 700,
@@ -507,6 +511,7 @@ static const struct imx219_mode supported_modes[] = {
                /* 2x2 binned 30fps mode */
                .width = 1640,
                .height = 1232,
+               .fps = 30,
                .crop = {
                        .left = IMX219_PIXEL_ARRAY_LEFT,
                        .top = IMX219_PIXEL_ARRAY_TOP,
@@ -523,6 +528,7 @@ static const struct imx219_mode supported_modes[] = {
                /* 640x480 30fps mode */
                .width = 640,
                .height = 480,
+               .fps = 30,
                .crop = {
                        .left = 1008,
                        .top = 760,
@@ -536,8 +542,6 @@ static const struct imx219_mode supported_modes[] = {
                },
        },
 };
-#define MODE_COUNT_MAX ARRAY_SIZE(supported_modes)
-static int imx219_fps[MODE_COUNT_MAX] = {15, 30, 30, 30};
 
 struct imx219 {
        struct v4l2_subdev sd;
@@ -564,6 +568,7 @@ struct imx219 {
 
        /* Current mode */
        const struct imx219_mode *mode;
+       struct v4l2_fract frame_interval;
 
        /*
         * Mutex for serialized access:
@@ -837,39 +842,101 @@ static int imx219_enum_frame_size(struct v4l2_subdev *sd,
 
        return 0;
 }
+
+static int imx219_try_frame_interval(struct imx219 *imx219,
+                                    struct v4l2_fract *fi,
+                                    u32 w, u32 h)
+{
+       const struct imx219_mode *mode;
+
+       mode = v4l2_find_nearest_size(supported_modes, ARRAY_SIZE(supported_modes),
+                       width, height, w, h);
+       if (!mode || (mode->width != w || mode->height != h))
+               return -EINVAL;
+
+       fi->numerator = 1;
+       fi->denominator = mode->fps;
+
+       return mode->fps;
+}
+
 static int imx219_enum_frame_interval(struct v4l2_subdev *sd,
                        struct v4l2_subdev_state *state,
                        struct v4l2_subdev_frame_interval_enum *fie)
 {
        struct imx219 *imx219 = to_imx219(sd);
+       struct v4l2_fract tpf;
        u32 code;
-       int i = 0;
+       int ret;
 
        if (fie->index >= ARRAY_SIZE(supported_modes) || fie->index)
                return -EINVAL;
 
        mutex_lock(&imx219->mutex);
        code = imx219_get_format_code(imx219, fie->code);
+       if (fie->code != code) {
+               ret = -EINVAL;
+               goto out;
+       }
+
+       ret = imx219_try_frame_interval(imx219, &tpf,
+                               fie->width, fie->height);
+       if (ret < 0) {
+               ret = -EINVAL;
+               goto out;
+       }
+
+       mutex_unlock(&imx219->mutex);
+       fie->interval = tpf;
+
+       return 0;
+
+out:
+       mutex_unlock(&imx219->mutex);
+       return ret;
+}
+
+static int imx219_g_frame_interval(struct v4l2_subdev *sd,
+                                  struct v4l2_subdev_frame_interval *fi)
+{
+       struct imx219 *imx219 = to_imx219(sd);
+
+       mutex_lock(&imx219->mutex);
+       fi->interval = imx219->frame_interval;
        mutex_unlock(&imx219->mutex);
-       if (fie->code != code)
+
+       return 0;
+}
+
+static int imx219_s_frame_interval(struct v4l2_subdev *sd,
+                                  struct v4l2_subdev_frame_interval *fi)
+{
+       struct imx219 *imx219 = to_imx219(sd);
+       const struct imx219_mode *mode = imx219->mode;
+       int frame_rate, ret = 0;
+
+       if (fi->pad != 0)
                return -EINVAL;
 
-       pr_debug("fie->width = %d, fie->height = %d\n", fie->width, fie->height);
-       for (i = 0; i < MODE_COUNT_MAX; i++) {
-               if (fie->width == supported_modes[i].width &&
-                       fie->height == supported_modes[i].height)
-                       break;
+       mutex_lock(&imx219->mutex);
+
+       if (imx219->streaming) {
+               ret = -EBUSY;
+               goto out;
        }
-       if (i == MODE_COUNT_MAX)
-               return -ENOTTY;
 
-       fie->interval.denominator = imx219_fps[i];
-       fie->interval.numerator = 1;
-       fie->code = code;
-       fie->width = supported_modes[i].width;
-       fie->height = supported_modes[i].height;
+       frame_rate = imx219_try_frame_interval(imx219, &fi->interval,
+                                              mode->width, mode->height);
+       if (frame_rate < 0) {
+               ret = -EINVAL;
+               goto out;
+       }
 
-       return 0;
+       imx219->frame_interval = fi->interval;
+
+out:
+       mutex_unlock(&imx219->mutex);
+       return ret;
 }
 
 static void imx219_reset_colorspace(struct v4l2_mbus_framefmt *fmt)
@@ -1269,6 +1336,8 @@ static const struct v4l2_subdev_core_ops imx219_core_ops = {
 };
 
 static const struct v4l2_subdev_video_ops imx219_video_ops = {
+       .g_frame_interval = imx219_g_frame_interval,
+       .s_frame_interval = imx219_s_frame_interval,
        .s_stream = imx219_set_stream,
 };
 
@@ -1506,6 +1575,8 @@ static int imx219_probe(struct i2c_client *client)
 
        /* Set default mode to max resolution */
        imx219->mode = &supported_modes[0];
+       imx219->frame_interval.numerator = 1;
+       imx219->frame_interval.denominator = supported_modes[0].fps;
 
        /* sensor doesn't enter LP-11 state upon power up until and unless
         * streaming is started, so upon power up switch the modes to:
index cc0d3e8..58493fd 100644 (file)
@@ -760,6 +760,8 @@ static int video_enum_framesizes(struct file *file, void *fh,
        struct media_entity *entity = &vdev->entity;
        struct media_entity *sensor;
        struct v4l2_subdev *subdev;
+       struct media_pad *pad;
+       bool support_selection = false;
        int i;
        int ret;
 
@@ -771,8 +773,41 @@ static int video_enum_framesizes(struct file *file, void *fh,
        if (i == video->nformats)
                return -EINVAL;
 
-       sensor = stfcamss_find_sensor(entity);
-       if (sensor) {
+       entity = &vdev->entity;
+       while (1) {
+               pad = &entity->pads[0];
+               if (!(pad->flags & MEDIA_PAD_FL_SINK))
+                       break;
+
+               pad = media_entity_remote_pad(pad);
+               if (!pad || !is_media_entity_v4l2_subdev(pad->entity))
+                       break;
+
+               entity = pad->entity;
+               subdev = media_entity_to_v4l2_subdev(entity);
+
+               if (subdev->ops->pad->set_selection) {
+                       support_selection = true;
+                       break;
+               }
+       }
+
+       if (support_selection) {
+               if (fsize->index)
+                       return -ENOTTY;
+               fsize->type = V4L2_FRMSIZE_TYPE_CONTINUOUS;
+               fsize->stepwise.min_width = STFCAMSS_FRAME_MIN_WIDTH;
+               fsize->stepwise.max_width = STFCAMSS_FRAME_MAX_WIDTH;
+               fsize->stepwise.min_height = STFCAMSS_FRAME_MIN_HEIGHT;
+               fsize->stepwise.max_height = STFCAMSS_FRAME_MAX_HEIGHT;
+               fsize->stepwise.step_width = 1;
+               fsize->stepwise.step_height = 1;
+       } else {
+               entity = &vdev->entity;
+               sensor = stfcamss_find_sensor(entity);
+               if (!sensor)
+                       return -ENOTTY;
+
                subdev = media_entity_to_v4l2_subdev(sensor);
                code.index = 0;
                code.which = V4L2_SUBDEV_FORMAT_ACTIVE;
@@ -788,20 +823,11 @@ static int video_enum_framesizes(struct file *file, void *fh,
                fsize->type = V4L2_FRMSIZE_TYPE_DISCRETE;
                fsize->discrete.width = fse.min_width;
                fsize->discrete.height = fse.min_height;
-       } else {
-               if (fsize->index)
-                       return -EINVAL;
-               fsize->type = V4L2_FRMSIZE_TYPE_CONTINUOUS;
-               fsize->stepwise.min_width = STFCAMSS_FRAME_MIN_WIDTH;
-               fsize->stepwise.max_width = STFCAMSS_FRAME_MAX_WIDTH;
-               fsize->stepwise.min_height = STFCAMSS_FRAME_MIN_HEIGHT;
-               fsize->stepwise.max_height = STFCAMSS_FRAME_MAX_HEIGHT;
-               fsize->stepwise.step_width = 1;
-               fsize->stepwise.step_height = 1;
        }
 
        return 0;
 }
+
 static int video_enum_frameintervals(struct file *file, void *fh,
                                struct v4l2_frmivalenum *fival)
 {
index fb21b92..3f87db2 100644 (file)
@@ -14,9 +14,9 @@
 #include <media/v4l2-ioctl.h>
 
 #define STFCAMSS_FRAME_MIN_WIDTH           64
-#define STFCAMSS_FRAME_MAX_WIDTH           8191
+#define STFCAMSS_FRAME_MAX_WIDTH           1920
 #define STFCAMSS_FRAME_MIN_HEIGHT          64
-#define STFCAMSS_FRAME_MAX_HEIGHT          8191
+#define STFCAMSS_FRAME_MAX_HEIGHT          1080
 #define STFCAMSS_FRAME_WIDTH_ALIGN_8       8
 #define STFCAMSS_FRAME_WIDTH_ALIGN_128     128
 #define STFCAMSS_MIN_BUFFERS               2