diff options
author | Hans de Goede <hdegoede@redhat.com> | 2023-05-29 11:37:35 +0100 |
---|---|---|
committer | Mauro Carvalho Chehab <mchehab@kernel.org> | 2023-06-09 15:31:38 +0100 |
commit | 04eca831605390071be83b87774e4987639e6331 (patch) | |
tree | 91c4fc2049d5720dc7b845aecae6f82f5c5d6d82 /drivers | |
parent | 929eee2fb07aee951c493cfdd87cb19719606d91 (diff) | |
download | linux-04eca831605390071be83b87774e4987639e6331.tar.gz linux-04eca831605390071be83b87774e4987639e6331.tar.bz2 linux-04eca831605390071be83b87774e4987639e6331.zip |
media: atomisp: Add support for sensors which implement selection API / cropping
Sensor drivers which implement set_selection V4L2_SEL_TGT_CROP expect
v4l2_subdev_state.pads[pad].try_crop to have valid contents when calling
set_fmt with which == V4L2_SUBDEV_FORMAT_TRY since the crop-rectangle
may influence the available image size.
Just passing an uninitalized struct v4l2_subdev_pad_config from
the stack to set_fmt with which == V4L2_SUBDEV_FORMAT_TRY will result
in wrong results with such drivers.
Store a per sensor v4l2_subdev_pad_config and add a new
atomisp_init_sensor_crop() function to initialize this before
registering /dev/* nodes with userspace.
Sensor drivers which implement the selection API will allow
the atomisp to properly deal with the extra padding the ISP wants
on a per sensor basis instead of hardcoding this.
atomisp_init_sensor_crop() stores the native and active rects
of the sensor in preparation for using these for this.
Link: https://lore.kernel.org/r/20230529103741.11904-16-hdegoede@redhat.com
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
Reviewed-by: Andy Shevchenko <andy.shevchenko@gmail.com>
Signed-off-by: Mauro Carvalho Chehab <mchehab@kernel.org>
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/staging/media/atomisp/pci/atomisp_cmd.c | 6 | ||||
-rw-r--r-- | drivers/staging/media/atomisp/pci/atomisp_internal.h | 7 | ||||
-rw-r--r-- | drivers/staging/media/atomisp/pci/atomisp_v4l2.c | 55 |
3 files changed, 64 insertions, 4 deletions
diff --git a/drivers/staging/media/atomisp/pci/atomisp_cmd.c b/drivers/staging/media/atomisp/pci/atomisp_cmd.c index e17d057f8867..4564b9ad7223 100644 --- a/drivers/staging/media/atomisp/pci/atomisp_cmd.c +++ b/drivers/staging/media/atomisp/pci/atomisp_cmd.c @@ -3698,9 +3698,8 @@ int atomisp_try_fmt(struct atomisp_device *isp, struct v4l2_pix_format *f, const struct atomisp_format_bridge *fmt, *snr_fmt; struct atomisp_sub_device *asd = &isp->asd; struct atomisp_input_subdev *input = &isp->inputs[asd->input_curr]; - struct v4l2_subdev_pad_config pad_cfg; struct v4l2_subdev_state pad_state = { - .pads = &pad_cfg, + .pads = &input->pad_cfg, }; struct v4l2_subdev_format format = { .which = V4L2_SUBDEV_FORMAT_TRY, @@ -4164,9 +4163,8 @@ static int atomisp_set_fmt_to_snr(struct video_device *vdev, const struct v4l2_p struct atomisp_device *isp = asd->isp; struct atomisp_input_subdev *input = &isp->inputs[asd->input_curr]; const struct atomisp_format_bridge *format; - struct v4l2_subdev_pad_config pad_cfg; struct v4l2_subdev_state pad_state = { - .pads = &pad_cfg, + .pads = &input->pad_cfg, }; struct v4l2_subdev_format vformat = { .which = V4L2_SUBDEV_FORMAT_TRY, diff --git a/drivers/staging/media/atomisp/pci/atomisp_internal.h b/drivers/staging/media/atomisp/pci/atomisp_internal.h index e59c0f1e7f53..14d21c6e227d 100644 --- a/drivers/staging/media/atomisp/pci/atomisp_internal.h +++ b/drivers/staging/media/atomisp/pci/atomisp_internal.h @@ -125,7 +125,14 @@ struct atomisp_input_subdev { unsigned int type; enum atomisp_camera_port port; + bool crop_support; struct v4l2_subdev *camera; + /* Sensor rects for sensors which support crop */ + struct v4l2_rect native_rect; + struct v4l2_rect active_rect; + /* Sensor pad_cfg for which == V4L2_SUBDEV_FORMAT_TRY calls */ + struct v4l2_subdev_pad_config pad_cfg; + struct v4l2_subdev *motor; /* diff --git a/drivers/staging/media/atomisp/pci/atomisp_v4l2.c b/drivers/staging/media/atomisp/pci/atomisp_v4l2.c index a2ce9bbf10df..506f04ca92b1 100644 --- a/drivers/staging/media/atomisp/pci/atomisp_v4l2.c +++ b/drivers/staging/media/atomisp/pci/atomisp_v4l2.c @@ -931,6 +931,59 @@ v4l2_device_failed: return ret; } +static void atomisp_init_sensor(struct atomisp_input_subdev *input) +{ + struct v4l2_subdev_state sd_state = { + .pads = &input->pad_cfg, + }; + struct v4l2_subdev_selection sel = { }; + int err; + + sel.which = V4L2_SUBDEV_FORMAT_ACTIVE; + sel.target = V4L2_SEL_TGT_NATIVE_SIZE; + err = v4l2_subdev_call(input->camera, pad, get_selection, NULL, &sel); + if (err) + return; + + input->native_rect = sel.r; + + sel.which = V4L2_SUBDEV_FORMAT_ACTIVE; + sel.target = V4L2_SEL_TGT_CROP_DEFAULT; + err = v4l2_subdev_call(input->camera, pad, get_selection, NULL, &sel); + if (err) + return; + + input->active_rect = sel.r; + + /* + * The ISP also wants the non-active pixels at the border of the sensor + * for padding, set the crop rect to cover the entire sensor instead + * of only the default active area. + * + * Do this for both try and active formats since the try_crop rect in + * pad_cfg may influence (clamp) future try_fmt calls with which == try. + */ + sel.which = V4L2_SUBDEV_FORMAT_TRY; + sel.target = V4L2_SEL_TGT_CROP; + sel.r = input->native_rect; + err = v4l2_subdev_call(input->camera, pad, set_selection, &sd_state, &sel); + if (err) + return; + + sel.which = V4L2_SUBDEV_FORMAT_ACTIVE; + sel.target = V4L2_SEL_TGT_CROP; + sel.r = input->native_rect; + err = v4l2_subdev_call(input->camera, pad, set_selection, NULL, &sel); + if (err) + return; + + dev_info(input->camera->dev, "Supports crop native %dx%d active %dx%d\n", + input->native_rect.width, input->native_rect.height, + input->active_rect.width, input->active_rect.height); + + input->crop_support = true; +} + int atomisp_register_device_nodes(struct atomisp_device *isp) { struct atomisp_input_subdev *input; @@ -952,6 +1005,8 @@ int atomisp_register_device_nodes(struct atomisp_device *isp) input->port = i; input->camera = isp->sensor_subdevs[i]; + atomisp_init_sensor(input); + /* * HACK: Currently VCM belongs to primary sensor only, but correct * approach must be to acquire from platform code which sensor |