mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2026-05-09 22:14:36 -04:00
media: atomisp: fix VIDIOC_S_FMT logic
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>
This commit is contained in:
@@ -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 @@ int atomisp_set_fmt(struct video_device *vdev, struct v4l2_format *f)
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user