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>
This commit is contained in:
parent
929eee2fb0
commit
04eca83160
@ -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,
|
||||
|
@ -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;
|
||||
|
||||
/*
|
||||
|
@ -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
|
||||
|
Loading…
x
Reference in New Issue
Block a user