media: atomisp: fix try_fmt logic
authorMauro Carvalho Chehab <mchehab+huawei@kernel.org>
Thu, 4 Nov 2021 11:45:27 +0000 (11:45 +0000)
committerMauro Carvalho Chehab <mchehab+huawei@kernel.org>
Mon, 15 Nov 2021 08:11:46 +0000 (08:11 +0000)
The internal try_fmt logic is not meant to provide everything
that the V4L2 API should provide. Also, it doesn't decrement
the pads that are used only internally by the driver, but aren't
part of the device's output.

Fix it.

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

index 851046ecbdbf1539d2a672c7d550df5c5250a7c8..0ddee36cdcd72fc7cd44bf81148b6c2bca84a5b3 100644 (file)
@@ -4918,13 +4918,6 @@ int atomisp_try_fmt(struct video_device *vdev, struct v4l2_pix_format *f,
        }
 
        f->pixelformat = fmt->pixelformat;
-       /*
-        * FIXME: do we need to setup this differently, depending on the
-        * sensor or the pipeline?
-        */
-       f->colorspace = V4L2_COLORSPACE_REC709;
-       f->ycbcr_enc = V4L2_YCBCR_ENC_709;
-       f->xfer_func = V4L2_XFER_FUNC_709;
 
        /*
         * If the format is jpeg or custom RAW, then the width and height will
index 84ff97dabbed0677363349a409ee84d8d601073d..1e6da6116a068856b160ccc9b2244a5cd5d992a9 100644 (file)
@@ -847,6 +847,72 @@ static int atomisp_g_fmt_file(struct file *file, void *fh,
        return 0;
 }
 
+static int atomisp_adjust_fmt(struct v4l2_format *f)
+{
+       const struct atomisp_format_bridge *format_bridge;
+       u32 padded_width;
+
+       format_bridge = atomisp_get_format_bridge(f->fmt.pix.pixelformat);
+
+       padded_width = f->fmt.pix.width + pad_w;
+
+       if (format_bridge->planar) {
+               f->fmt.pix.bytesperline = padded_width;
+               f->fmt.pix.sizeimage = PAGE_ALIGN(f->fmt.pix.height *
+                                                 DIV_ROUND_UP(format_bridge->depth *
+                                                 padded_width, 8));
+       } else {
+               f->fmt.pix.bytesperline = DIV_ROUND_UP(format_bridge->depth *
+                                                     padded_width, 8);
+               f->fmt.pix.sizeimage = PAGE_ALIGN(f->fmt.pix.height * f->fmt.pix.bytesperline);
+       }
+
+       if (f->fmt.pix.field == V4L2_FIELD_ANY)
+               f->fmt.pix.field = V4L2_FIELD_NONE;
+
+       format_bridge = atomisp_get_format_bridge(f->fmt.pix.pixelformat);
+       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;
+       }
+
+       padded_width = f->fmt.pix.width + pad_w;
+
+       if (format_bridge->planar) {
+               f->fmt.pix.bytesperline = padded_width;
+               f->fmt.pix.sizeimage = PAGE_ALIGN(f->fmt.pix.height *
+                                                 DIV_ROUND_UP(format_bridge->depth *
+                                                 padded_width, 8));
+       } else {
+               f->fmt.pix.bytesperline = DIV_ROUND_UP(format_bridge->depth *
+                                                     padded_width, 8);
+               f->fmt.pix.sizeimage = PAGE_ALIGN(f->fmt.pix.height * f->fmt.pix.bytesperline);
+       }
+
+       if (f->fmt.pix.field == V4L2_FIELD_ANY)
+               f->fmt.pix.field = V4L2_FIELD_NONE;
+
+       /*
+        * FIXME: do we need to setup this differently, depending on the
+        * sensor or the pipeline?
+        */
+       f->fmt.pix.colorspace = V4L2_COLORSPACE_REC709;
+       f->fmt.pix.ycbcr_enc = V4L2_YCBCR_ENC_709;
+       f->fmt.pix.xfer_func = V4L2_XFER_FUNC_709;
+
+       f->fmt.pix.width -= pad_w;
+       f->fmt.pix.height -= pad_h;
+
+       return 0;
+}
+
 /* This function looks up the closest available resolution. */
 static int atomisp_try_fmt_cap(struct file *file, void *fh,
                               struct v4l2_format *f)
@@ -858,7 +924,11 @@ static int atomisp_try_fmt_cap(struct file *file, void *fh,
        rt_mutex_lock(&isp->mutex);
        ret = atomisp_try_fmt(vdev, &f->fmt.pix, NULL);
        rt_mutex_unlock(&isp->mutex);
-       return ret;
+
+       if (ret)
+               return ret;
+
+       return atomisp_adjust_fmt(f);
 }
 
 static int atomisp_g_fmt_cap(struct file *file, void *fh,