@@ -3688,6 +3688,33 @@ static void atomisp_fill_pix_format(struct v4l2_pix_format *f,
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. */
int atomisp_try_fmt(struct atomisp_device *isp, struct v4l2_pix_format *f,
const struct atomisp_format_bridge **fmt_ret,
@@ -3702,6 +3729,7 @@ int atomisp_try_fmt(struct atomisp_device *isp, struct v4l2_pix_format *f,
struct v4l2_subdev_format format = {
.which = V4L2_SUBDEV_FORMAT_TRY,
};
+ u32 padding_w, padding_h;
int ret;
if (!input->camera)
@@ -3722,9 +3750,10 @@ int atomisp_try_fmt(struct atomisp_device *isp, struct v4l2_pix_format *f,
* resolution + padding. Add padding here and remove it again after
* 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);
- format.format.width += pad_w;
- format.format.height += pad_h;
+ format.format.width += padding_w;
+ format.format.height += padding_h;
dev_dbg(isp->dev, "try_mbus_fmt: asking for %ux%u\n",
format.format.width, format.format.height);
@@ -3743,8 +3772,8 @@ int atomisp_try_fmt(struct atomisp_device *isp, struct v4l2_pix_format *f,
return -EINVAL;
}
- f->width = format.format.width - pad_w;
- f->height = format.format.height - pad_h;
+ f->width = format.format.width - padding_w;
+ f->height = format.format.height - padding_h;
/*
* If the format is jpeg or custom RAW, then the width and height will
@@ -4153,7 +4182,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,
- unsigned int padding_w, unsigned int padding_h,
unsigned int dvs_env_w, unsigned int dvs_env_h)
{
struct atomisp_video_pipe *pipe = atomisp_to_video_pipe(vdev);
@@ -4184,11 +4212,11 @@ static int atomisp_set_fmt_to_snr(struct video_device *vdev, const struct v4l2_p
return -EINVAL;
v4l2_fill_mbus_format(ffmt, f, format->mbus_code);
- ffmt->height += padding_h + dvs_env_h;
- ffmt->width += padding_w + dvs_env_w;
+ ffmt->height += asd->sink_pad_padding_h + dvs_env_h;
+ 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",
- 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);
__atomisp_init_stream_info(ATOMISP_INPUT_STREAM_GENERAL, stream_info);
@@ -4252,7 +4280,6 @@ int atomisp_set_fmt(struct video_device *vdev, struct v4l2_format *f)
const struct atomisp_format_bridge *snr_format_bridge;
struct ia_css_frame_info output_info;
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_rect isp_sink_crop;
int ret;
@@ -4283,16 +4310,18 @@ int atomisp_set_fmt(struct video_device *vdev, struct v4l2_format *f)
V4L2_SUBDEV_FORMAT_ACTIVE,
ATOMISP_SUBDEV_PAD_SOURCE, &isp_source_fmt);
- if (!atomisp_subdev_format_conversion(asd)) {
- padding_w = 0;
- padding_h = 0;
+ if (atomisp_subdev_format_conversion(asd)) {
+ atomisp_get_padding(isp, f->fmt.pix.width, f->fmt.pix.height,
+ &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,
&dvs_env_w, &dvs_env_h);
- ret = atomisp_set_fmt_to_snr(vdev, &f->fmt.pix,
- padding_w, padding_h, dvs_env_w, dvs_env_h);
+ ret = atomisp_set_fmt_to_snr(vdev, &f->fmt.pix, dvs_env_w, dvs_env_h);
if (ret) {
dev_warn(isp->dev,
"Set format to sensor failed with %d\n", ret);
@@ -357,8 +357,6 @@ int atomisp_subdev_set_selection(struct v4l2_subdev *sd,
struct v4l2_mbus_framefmt *ffmt[ATOMISP_SUBDEV_PADS_NUM];
struct v4l2_rect *crop[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) ||
(pad == ATOMISP_SUBDEV_PAD_SOURCE && target != V4L2_SEL_TGT_COMPOSE))
@@ -384,18 +382,10 @@ int atomisp_subdev_set_selection(struct v4l2_subdev *sd,
crop[pad]->width = ffmt[pad]->width;
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)
&& crop[pad]->width && crop[pad]->height) {
- crop[pad]->width -= padding_w;
- crop[pad]->height -= padding_h;
+ crop[pad]->width -= isp_sd->sink_pad_padding_w;
+ crop[pad]->height -= isp_sd->sink_pad_padding_h;
}
if (isp_sd->params.video_dis_en &&
@@ -239,6 +239,9 @@ struct atomisp_sub_device {
struct v4l2_subdev subdev;
struct media_pad pads[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;
struct atomisp_video_pipe video_out;