OSDN Git Service

media: atomisp: fix VIDIOC_S_FMT logic
authorMauro Carvalho Chehab <mchehab+huawei@kernel.org>
Thu, 4 Nov 2021 11:23:14 +0000 (11:23 +0000)
committerMauro Carvalho Chehab <mchehab+huawei@kernel.org>
Mon, 15 Nov 2021 08:11:45 +0000 (08:11 +0000)
There are several issues on S_FMT implementation:

- it doesn't properly handle pad_h/pad_w;
- it reports a wrong visible size to userspace;
- it allows setting the format to a raw mode, which
  currently causes the pipeline to break.

Address such issues, for it to start working with generic
apps.

Signed-off-by: Mauro Carvalho Chehab <mchehab+huawei@kernel.org>
drivers/staging/media/atomisp/pci/atomisp_cmd.c

index 76c9e89..851046e 100644 (file)
@@ -5635,13 +5635,17 @@ int atomisp_set_fmt(struct video_device *vdev, struct v4l2_format *f)
        const struct atomisp_format_bridge *format_bridge;
        const struct atomisp_format_bridge *snr_format_bridge;
        struct ia_css_frame_info output_info, raw_output_info;
-       struct v4l2_pix_format snr_fmt = f->fmt.pix;
-       struct v4l2_pix_format backup_fmt = snr_fmt, s_fmt;
+       struct v4l2_pix_format snr_fmt;
+       struct v4l2_pix_format backup_fmt, s_fmt;
        unsigned int dvs_env_w = 0, dvs_env_h = 0;
        unsigned int padding_w = pad_w, padding_h = pad_h;
        bool res_overflow = false, crop_needs_override = false;
        struct v4l2_mbus_framefmt *isp_sink_fmt;
        struct v4l2_mbus_framefmt isp_source_fmt = {0};
+       struct v4l2_subdev_format vformat = {
+               .which = V4L2_SUBDEV_FORMAT_ACTIVE,
+       };
+       struct v4l2_mbus_framefmt *ffmt = &vformat.format;
        struct v4l2_rect isp_sink_crop;
        u16 source_pad = atomisp_subdev_source_pad(vdev);
        struct v4l2_subdev_fh fh;
@@ -5672,9 +5676,38 @@ int atomisp_set_fmt(struct video_device *vdev, struct v4l2_format *f)
        if (!format_bridge)
                return -EINVAL;
 
+       /* Currently, raw formats are broken!!! */
+
+       if (format_bridge->sh_fmt == IA_CSS_FRAME_FORMAT_RAW) {
+               f->fmt.pix.pixelformat = V4L2_PIX_FMT_YUV420;
+
+               format_bridge = atomisp_get_format_bridge(f->fmt.pix.pixelformat);
+               if (!format_bridge)
+                       return -EINVAL;
+       }
        pipe->sh_fmt = format_bridge->sh_fmt;
        pipe->pix.pixelformat = f->fmt.pix.pixelformat;
 
+       /* Ensure that the resolution is equal or below the maximum supported */
+
+       vformat.which = V4L2_SUBDEV_FORMAT_ACTIVE;
+       v4l2_fill_mbus_format(ffmt, &f->fmt.pix, format_bridge->mbus_code);
+       ffmt->height += padding_h;
+       ffmt->width += padding_w;
+
+       ret = v4l2_subdev_call(isp->inputs[asd->input_curr].camera, pad,
+                              set_fmt, NULL, &vformat);
+       if (ret)
+               return ret;
+
+       f->fmt.pix.width = ffmt->width - padding_w;
+       f->fmt.pix.height = ffmt->height - padding_h;
+
+       snr_fmt = f->fmt.pix;
+       backup_fmt = snr_fmt;
+
+       /**********************************************************************/
+
        if (source_pad == ATOMISP_SUBDEV_PAD_SOURCE_VF ||
            (source_pad == ATOMISP_SUBDEV_PAD_SOURCE_PREVIEW
             && asd->run_mode->val == ATOMISP_RUN_MODE_VIDEO)) {
@@ -6080,6 +6113,15 @@ done:
        else
                isp->need_gfx_throttle = true;
 
+       /* Report the needed sizes */
+       f->fmt.pix.sizeimage = pipe->pix.sizeimage;
+       f->fmt.pix.bytesperline = pipe->pix.bytesperline;
+
+       dev_dbg(isp->dev, "%s: %dx%d, image size: %d, %d bytes per line\n",
+               __func__,
+               f->fmt.pix.width, f->fmt.pix.height,
+               f->fmt.pix.sizeimage, f->fmt.pix.bytesperline);
+
        return 0;
 }