| From b71933a89e5dc520e92d71acd8125a2a1df7ed01 Mon Sep 17 00:00:00 2001 |
| From: Sasha Levin <sashal@kernel.org> |
| Date: Thu, 4 Nov 2021 11:45:27 +0000 |
| Subject: media: atomisp: fix try_fmt logic |
| |
| From: Mauro Carvalho Chehab <mchehab+huawei@kernel.org> |
| |
| [ Upstream commit c9e9094c4e42124af909b2f5f6ded0498e0854ac ] |
| |
| 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> |
| Signed-off-by: Sasha Levin <sashal@kernel.org> |
| --- |
| .../staging/media/atomisp/pci/atomisp_ioctl.c | 72 ++++++++++++++++++- |
| 1 file changed, 71 insertions(+), 1 deletion(-) |
| |
| diff --git a/drivers/staging/media/atomisp/pci/atomisp_ioctl.c b/drivers/staging/media/atomisp/pci/atomisp_ioctl.c |
| index 29826f8e4143d..54624f8814e04 100644 |
| --- a/drivers/staging/media/atomisp/pci/atomisp_ioctl.c |
| +++ b/drivers/staging/media/atomisp/pci/atomisp_ioctl.c |
| @@ -863,6 +863,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) |
| @@ -874,7 +940,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_s_fmt_cap(struct file *file, void *fh, |
| -- |
| 2.34.1 |
| |