| From 2a53db2a4e98d6fcefd27e5a8e638bb10ad64991 Mon Sep 17 00:00:00 2001 |
| From: Sasha Levin <sashal@kernel.org> |
| Date: Tue, 3 Sep 2019 17:11:40 -0300 |
| Subject: media: ov6650: Fix some format attributes not under control |
| |
| From: Janusz Krzysztofik <jmkrzyszt@gmail.com> |
| |
| [ Upstream commit 1c6a2b63095154bbf9e8f38d79487a728331bf65 ] |
| |
| User arguments passed to .get/set_fmt() pad operation callbacks may |
| contain unsupported values. The driver takes control over frame size |
| and pixel code as well as colorspace and field attributes but has never |
| cared for remainig format attributes, i.e., ycbcr_enc, quantization |
| and xfer_func, introduced by commit 11ff030c7365 ("[media] |
| v4l2-mediabus: improve colorspace support"). Fix it. |
| |
| Set up a static v4l2_mbus_framefmt structure with attributes |
| initialized to reasonable defaults and use it for updating content of |
| user provided arguments. In case of V4L2_SUBDEV_FORMAT_ACTIVE, |
| postpone frame size update, now performed from inside ov6650_s_fmt() |
| helper, util the user argument is first updated in ov6650_set_fmt() with |
| default frame format content. For V4L2_SUBDEV_FORMAT_TRY, don't copy |
| all attributes to pad config, only those handled by the driver, then |
| fill the response with the default frame format updated with resulting |
| pad config format code and frame size. |
| |
| Fixes: 11ff030c7365 ("[media] v4l2-mediabus: improve colorspace support") |
| Signed-off-by: Janusz Krzysztofik <jmkrzyszt@gmail.com> |
| Signed-off-by: Sakari Ailus <sakari.ailus@linux.intel.com> |
| Signed-off-by: Mauro Carvalho Chehab <mchehab+samsung@kernel.org> |
| Signed-off-by: Sasha Levin <sashal@kernel.org> |
| --- |
| drivers/media/i2c/soc_camera/ov6650.c | 51 ++++++++++++++++++++------- |
| 1 file changed, 39 insertions(+), 12 deletions(-) |
| |
| diff --git a/drivers/media/i2c/soc_camera/ov6650.c b/drivers/media/i2c/soc_camera/ov6650.c |
| index e9271ad9ee4c1..3b118d45d433b 100644 |
| --- a/drivers/media/i2c/soc_camera/ov6650.c |
| +++ b/drivers/media/i2c/soc_camera/ov6650.c |
| @@ -215,6 +215,17 @@ static u32 ov6650_codes[] = { |
| MEDIA_BUS_FMT_Y8_1X8, |
| }; |
| |
| +static const struct v4l2_mbus_framefmt ov6650_def_fmt = { |
| + .width = W_CIF, |
| + .height = H_CIF, |
| + .code = MEDIA_BUS_FMT_SBGGR8_1X8, |
| + .colorspace = V4L2_COLORSPACE_SRGB, |
| + .field = V4L2_FIELD_NONE, |
| + .ycbcr_enc = V4L2_YCBCR_ENC_DEFAULT, |
| + .quantization = V4L2_QUANTIZATION_DEFAULT, |
| + .xfer_func = V4L2_XFER_FUNC_DEFAULT, |
| +}; |
| + |
| /* read a register */ |
| static int ov6650_reg_read(struct i2c_client *client, u8 reg, u8 *val) |
| { |
| @@ -511,11 +522,13 @@ static int ov6650_get_fmt(struct v4l2_subdev *sd, |
| if (format->pad) |
| return -EINVAL; |
| |
| + /* initialize response with default media bus frame format */ |
| + *mf = ov6650_def_fmt; |
| + |
| + /* update media bus format code and frame size */ |
| mf->width = priv->rect.width >> priv->half_scale; |
| mf->height = priv->rect.height >> priv->half_scale; |
| mf->code = priv->code; |
| - mf->colorspace = V4L2_COLORSPACE_SRGB; |
| - mf->field = V4L2_FIELD_NONE; |
| |
| return 0; |
| } |
| @@ -678,10 +691,6 @@ static int ov6650_s_fmt(struct v4l2_subdev *sd, struct v4l2_mbus_framefmt *mf) |
| if (!ret) |
| priv->code = code; |
| |
| - if (!ret) { |
| - mf->width = priv->rect.width >> half_scale; |
| - mf->height = priv->rect.height >> half_scale; |
| - } |
| return ret; |
| } |
| |
| @@ -700,9 +709,6 @@ static int ov6650_set_fmt(struct v4l2_subdev *sd, |
| v4l_bound_align_image(&mf->width, 2, W_CIF, 1, |
| &mf->height, 2, H_CIF, 1, 0); |
| |
| - mf->field = V4L2_FIELD_NONE; |
| - mf->colorspace = V4L2_COLORSPACE_SRGB; |
| - |
| switch (mf->code) { |
| case MEDIA_BUS_FMT_Y10_1X10: |
| mf->code = MEDIA_BUS_FMT_Y8_1X8; |
| @@ -718,10 +724,31 @@ static int ov6650_set_fmt(struct v4l2_subdev *sd, |
| break; |
| } |
| |
| - if (format->which == V4L2_SUBDEV_FORMAT_ACTIVE) |
| - return ov6650_s_fmt(sd, mf); |
| - cfg->try_fmt = *mf; |
| + if (format->which == V4L2_SUBDEV_FORMAT_TRY) { |
| + /* store media bus format code and frame size in pad config */ |
| + cfg->try_fmt.width = mf->width; |
| + cfg->try_fmt.height = mf->height; |
| + cfg->try_fmt.code = mf->code; |
| |
| + /* return default mbus frame format updated with pad config */ |
| + *mf = ov6650_def_fmt; |
| + mf->width = cfg->try_fmt.width; |
| + mf->height = cfg->try_fmt.height; |
| + mf->code = cfg->try_fmt.code; |
| + |
| + } else { |
| + /* apply new media bus format code and frame size */ |
| + int ret = ov6650_s_fmt(sd, mf); |
| + |
| + if (ret) |
| + return ret; |
| + |
| + /* return default format updated with active size and code */ |
| + *mf = ov6650_def_fmt; |
| + mf->width = priv->rect.width >> priv->half_scale; |
| + mf->height = priv->rect.height >> priv->half_scale; |
| + mf->code = priv->code; |
| + } |
| return 0; |
| } |
| |
| -- |
| 2.20.1 |
| |