Commit 3e399cf2 authored by Hans de Goede's avatar Hans de Goede Committed by Mauro Carvalho Chehab

media: atomisp: Use selection API info to determine sensor padding

Using the selection / crop info to determine the padding values
to use with a specific resolution on specific sensor.

This allows e.g. automatically halving the padding when using
the max binned resolution and also ensures the right amount
of padding is used on models with 2 sensors with different
padding requirements.

Link: https://lore.kernel.org/r/20230529103741.11904-19-hdegoede@redhat.comSigned-off-by: default avatarHans de Goede <hdegoede@redhat.com>
Reviewed-by: default avatarAndy Shevchenko <andy.shevchenko@gmail.com>
Signed-off-by: default avatarMauro Carvalho Chehab <mchehab@kernel.org>
parent 62866c23
...@@ -3690,6 +3690,33 @@ static void atomisp_fill_pix_format(struct v4l2_pix_format *f, ...@@ -3690,6 +3690,33 @@ static void atomisp_fill_pix_format(struct v4l2_pix_format *f,
f->xfer_func = V4L2_XFER_FUNC_709; f->xfer_func = V4L2_XFER_FUNC_709;
} }
/* Get sensor padding values for the non padded width x height resolution */
static void atomisp_get_padding(struct atomisp_device *isp,
u32 width, u32 height,
u32 *padding_w, u32 *padding_h)
{
struct atomisp_input_subdev *input = &isp->inputs[isp->asd.input_curr];
struct v4l2_rect native_rect = input->native_rect;
if (!input->crop_support) {
*padding_w = pad_w;
*padding_h = pad_h;
return;
}
width = min(width, input->active_rect.width);
height = min(height, input->active_rect.height);
if (input->binning_support && width <= (input->active_rect.width / 2) &&
height <= (input->active_rect.height / 2)) {
native_rect.width /= 2;
native_rect.height /= 2;
}
*padding_w = min_t(u32, (native_rect.width - width) & ~1, pad_w);
*padding_h = min_t(u32, (native_rect.height - height) & ~1, pad_h);
}
/* This function looks up the closest available resolution. */ /* This function looks up the closest available resolution. */
int atomisp_try_fmt(struct atomisp_device *isp, struct v4l2_pix_format *f, int atomisp_try_fmt(struct atomisp_device *isp, struct v4l2_pix_format *f,
const struct atomisp_format_bridge **fmt_ret, const struct atomisp_format_bridge **fmt_ret,
...@@ -3704,6 +3731,7 @@ int atomisp_try_fmt(struct atomisp_device *isp, struct v4l2_pix_format *f, ...@@ -3704,6 +3731,7 @@ int atomisp_try_fmt(struct atomisp_device *isp, struct v4l2_pix_format *f,
struct v4l2_subdev_format format = { struct v4l2_subdev_format format = {
.which = V4L2_SUBDEV_FORMAT_TRY, .which = V4L2_SUBDEV_FORMAT_TRY,
}; };
u32 padding_w, padding_h;
int ret; int ret;
if (!input->camera) if (!input->camera)
...@@ -3724,9 +3752,10 @@ int atomisp_try_fmt(struct atomisp_device *isp, struct v4l2_pix_format *f, ...@@ -3724,9 +3752,10 @@ int atomisp_try_fmt(struct atomisp_device *isp, struct v4l2_pix_format *f,
* resolution + padding. Add padding here and remove it again after * resolution + padding. Add padding here and remove it again after
* the set_fmt call, like atomisp_set_fmt_to_snr() does. * the set_fmt call, like atomisp_set_fmt_to_snr() does.
*/ */
atomisp_get_padding(isp, f->width, f->height, &padding_w, &padding_h);
v4l2_fill_mbus_format(&format.format, f, fmt->mbus_code); v4l2_fill_mbus_format(&format.format, f, fmt->mbus_code);
format.format.width += pad_w; format.format.width += padding_w;
format.format.height += pad_h; format.format.height += padding_h;
dev_dbg(isp->dev, "try_mbus_fmt: asking for %ux%u\n", dev_dbg(isp->dev, "try_mbus_fmt: asking for %ux%u\n",
format.format.width, format.format.height); format.format.width, format.format.height);
...@@ -3745,8 +3774,8 @@ int atomisp_try_fmt(struct atomisp_device *isp, struct v4l2_pix_format *f, ...@@ -3745,8 +3774,8 @@ int atomisp_try_fmt(struct atomisp_device *isp, struct v4l2_pix_format *f,
return -EINVAL; return -EINVAL;
} }
f->width = format.format.width - pad_w; f->width = format.format.width - padding_w;
f->height = format.format.height - pad_h; f->height = format.format.height - padding_h;
/* /*
* If the format is jpeg or custom RAW, then the width and height will * If the format is jpeg or custom RAW, then the width and height will
...@@ -4155,7 +4184,6 @@ static void atomisp_check_copy_mode(struct atomisp_sub_device *asd, ...@@ -4155,7 +4184,6 @@ static void atomisp_check_copy_mode(struct atomisp_sub_device *asd,
} }
static int atomisp_set_fmt_to_snr(struct video_device *vdev, const struct v4l2_pix_format *f, static int atomisp_set_fmt_to_snr(struct video_device *vdev, const struct v4l2_pix_format *f,
unsigned int padding_w, unsigned int padding_h,
unsigned int dvs_env_w, unsigned int dvs_env_h) unsigned int dvs_env_w, unsigned int dvs_env_h)
{ {
struct atomisp_video_pipe *pipe = atomisp_to_video_pipe(vdev); struct atomisp_video_pipe *pipe = atomisp_to_video_pipe(vdev);
...@@ -4186,11 +4214,11 @@ static int atomisp_set_fmt_to_snr(struct video_device *vdev, const struct v4l2_p ...@@ -4186,11 +4214,11 @@ static int atomisp_set_fmt_to_snr(struct video_device *vdev, const struct v4l2_p
return -EINVAL; return -EINVAL;
v4l2_fill_mbus_format(ffmt, f, format->mbus_code); v4l2_fill_mbus_format(ffmt, f, format->mbus_code);
ffmt->height += padding_h + dvs_env_h; ffmt->height += asd->sink_pad_padding_h + dvs_env_h;
ffmt->width += padding_w + dvs_env_w; ffmt->width += asd->sink_pad_padding_w + dvs_env_w;
dev_dbg(isp->dev, "s_mbus_fmt: ask %ux%u (padding %ux%u, dvs %ux%u)\n", dev_dbg(isp->dev, "s_mbus_fmt: ask %ux%u (padding %ux%u, dvs %ux%u)\n",
ffmt->width, ffmt->height, padding_w, padding_h, ffmt->width, ffmt->height, asd->sink_pad_padding_w, asd->sink_pad_padding_h,
dvs_env_w, dvs_env_h); dvs_env_w, dvs_env_h);
__atomisp_init_stream_info(ATOMISP_INPUT_STREAM_GENERAL, stream_info); __atomisp_init_stream_info(ATOMISP_INPUT_STREAM_GENERAL, stream_info);
...@@ -4254,7 +4282,6 @@ int atomisp_set_fmt(struct video_device *vdev, struct v4l2_format *f) ...@@ -4254,7 +4282,6 @@ int atomisp_set_fmt(struct video_device *vdev, struct v4l2_format *f)
const struct atomisp_format_bridge *snr_format_bridge; const struct atomisp_format_bridge *snr_format_bridge;
struct ia_css_frame_info output_info; struct ia_css_frame_info output_info;
unsigned int dvs_env_w = 0, dvs_env_h = 0; unsigned int dvs_env_w = 0, dvs_env_h = 0;
unsigned int padding_w = pad_w, padding_h = pad_h;
struct v4l2_mbus_framefmt isp_source_fmt = {0}; struct v4l2_mbus_framefmt isp_source_fmt = {0};
struct v4l2_rect isp_sink_crop; struct v4l2_rect isp_sink_crop;
int ret; int ret;
...@@ -4285,16 +4312,18 @@ int atomisp_set_fmt(struct video_device *vdev, struct v4l2_format *f) ...@@ -4285,16 +4312,18 @@ int atomisp_set_fmt(struct video_device *vdev, struct v4l2_format *f)
V4L2_SUBDEV_FORMAT_ACTIVE, V4L2_SUBDEV_FORMAT_ACTIVE,
ATOMISP_SUBDEV_PAD_SOURCE, &isp_source_fmt); ATOMISP_SUBDEV_PAD_SOURCE, &isp_source_fmt);
if (!atomisp_subdev_format_conversion(asd)) { if (atomisp_subdev_format_conversion(asd)) {
padding_w = 0; atomisp_get_padding(isp, f->fmt.pix.width, f->fmt.pix.height,
padding_h = 0; &asd->sink_pad_padding_w, &asd->sink_pad_padding_h);
} else {
asd->sink_pad_padding_w = 0;
asd->sink_pad_padding_h = 0;
} }
atomisp_get_dis_envelop(asd, f->fmt.pix.width, f->fmt.pix.height, atomisp_get_dis_envelop(asd, f->fmt.pix.width, f->fmt.pix.height,
&dvs_env_w, &dvs_env_h); &dvs_env_w, &dvs_env_h);
ret = atomisp_set_fmt_to_snr(vdev, &f->fmt.pix, ret = atomisp_set_fmt_to_snr(vdev, &f->fmt.pix, dvs_env_w, dvs_env_h);
padding_w, padding_h, dvs_env_w, dvs_env_h);
if (ret) { if (ret) {
dev_warn(isp->dev, dev_warn(isp->dev,
"Set format to sensor failed with %d\n", ret); "Set format to sensor failed with %d\n", ret);
......
...@@ -357,8 +357,6 @@ int atomisp_subdev_set_selection(struct v4l2_subdev *sd, ...@@ -357,8 +357,6 @@ int atomisp_subdev_set_selection(struct v4l2_subdev *sd,
struct v4l2_mbus_framefmt *ffmt[ATOMISP_SUBDEV_PADS_NUM]; struct v4l2_mbus_framefmt *ffmt[ATOMISP_SUBDEV_PADS_NUM];
struct v4l2_rect *crop[ATOMISP_SUBDEV_PADS_NUM], struct v4l2_rect *crop[ATOMISP_SUBDEV_PADS_NUM],
*comp[ATOMISP_SUBDEV_PADS_NUM]; *comp[ATOMISP_SUBDEV_PADS_NUM];
unsigned int padding_w = pad_w;
unsigned int padding_h = pad_h;
if ((pad == ATOMISP_SUBDEV_PAD_SINK && target != V4L2_SEL_TGT_CROP) || if ((pad == ATOMISP_SUBDEV_PAD_SINK && target != V4L2_SEL_TGT_CROP) ||
(pad == ATOMISP_SUBDEV_PAD_SOURCE && target != V4L2_SEL_TGT_COMPOSE)) (pad == ATOMISP_SUBDEV_PAD_SOURCE && target != V4L2_SEL_TGT_COMPOSE))
...@@ -384,18 +382,10 @@ int atomisp_subdev_set_selection(struct v4l2_subdev *sd, ...@@ -384,18 +382,10 @@ int atomisp_subdev_set_selection(struct v4l2_subdev *sd,
crop[pad]->width = ffmt[pad]->width; crop[pad]->width = ffmt[pad]->width;
crop[pad]->height = ffmt[pad]->height; crop[pad]->height = ffmt[pad]->height;
/* Workaround for BYT 1080p perfectshot since the maxinum resolution of
* front camera ov2722 is 1932x1092 and cannot use pad_w > 12*/
if (!strncmp(isp->inputs[isp_sd->input_curr].camera->name,
"ov2722", 6) && crop[pad]->height == 1092) {
padding_w = 12;
padding_h = 12;
}
if (atomisp_subdev_format_conversion(isp_sd) if (atomisp_subdev_format_conversion(isp_sd)
&& crop[pad]->width && crop[pad]->height) { && crop[pad]->width && crop[pad]->height) {
crop[pad]->width -= padding_w; crop[pad]->width -= isp_sd->sink_pad_padding_w;
crop[pad]->height -= padding_h; crop[pad]->height -= isp_sd->sink_pad_padding_h;
} }
if (isp_sd->params.video_dis_en && if (isp_sd->params.video_dis_en &&
......
...@@ -239,6 +239,9 @@ struct atomisp_sub_device { ...@@ -239,6 +239,9 @@ struct atomisp_sub_device {
struct v4l2_subdev subdev; struct v4l2_subdev subdev;
struct media_pad pads[ATOMISP_SUBDEV_PADS_NUM]; struct media_pad pads[ATOMISP_SUBDEV_PADS_NUM];
struct atomisp_pad_format fmt[ATOMISP_SUBDEV_PADS_NUM]; struct atomisp_pad_format fmt[ATOMISP_SUBDEV_PADS_NUM];
/* Padding for currently set sink-pad fmt */
u32 sink_pad_padding_w;
u32 sink_pad_padding_h;
unsigned int output; unsigned int output;
struct atomisp_video_pipe video_out; struct atomisp_video_pipe video_out;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment