The colorimetry parameters need to be tested at both sink and source pads. Specifically, for prpencvf, the IC only supports RGB full-range quantization at input and output. Fix this by cleaning up imx_media_fill_default_mbus_fields(), renaming to imx_media_try_colorimetry(), and call it at both sink and source pad try_fmt's. The unrelated check for uninitialized field value is moved out to appropriate places in each subdev try_fmt. Signed-off-by: Steve Longerbeam <slongerbeam@xxxxxxxxx> --- drivers/staging/media/imx/imx-ic-prp.c | 6 +- drivers/staging/media/imx/imx-ic-prpencvf.c | 8 +-- drivers/staging/media/imx/imx-media-csi.c | 19 +++--- drivers/staging/media/imx/imx-media-utils.c | 68 +++++++++++---------- drivers/staging/media/imx/imx-media-vdic.c | 5 +- drivers/staging/media/imx/imx-media.h | 5 +- drivers/staging/media/imx/imx7-media-csi.c | 8 +-- 7 files changed, 62 insertions(+), 57 deletions(-) diff --git a/drivers/staging/media/imx/imx-ic-prp.c b/drivers/staging/media/imx/imx-ic-prp.c index 3d43cdcb4bb9..8010ee706164 100644 --- a/drivers/staging/media/imx/imx-ic-prp.c +++ b/drivers/staging/media/imx/imx-ic-prp.c @@ -197,8 +197,8 @@ static int prp_set_fmt(struct v4l2_subdev *sd, sdformat->format.code = cc->codes[0]; } - imx_media_fill_default_mbus_fields(&sdformat->format, infmt, - true); + if (sdformat->format.field == V4L2_FIELD_ANY) + sdformat->format.field = V4L2_FIELD_NONE; break; case PRP_SRC_PAD_PRPENC: case PRP_SRC_PAD_PRPVF: @@ -207,6 +207,8 @@ static int prp_set_fmt(struct v4l2_subdev *sd, break; } + imx_media_try_colorimetry(&sdformat->format, true); + fmt = __prp_get_fmt(priv, cfg, sdformat->pad, sdformat->which); *fmt = sdformat->format; out: diff --git a/drivers/staging/media/imx/imx-ic-prpencvf.c b/drivers/staging/media/imx/imx-ic-prpencvf.c index 10f2c7684727..b1886a4e362e 100644 --- a/drivers/staging/media/imx/imx-ic-prpencvf.c +++ b/drivers/staging/media/imx/imx-ic-prpencvf.c @@ -899,8 +899,6 @@ static void prp_try_fmt(struct prp_priv *priv, /* propagate colorimetry from sink */ sdformat->format.colorspace = infmt->colorspace; sdformat->format.xfer_func = infmt->xfer_func; - sdformat->format.quantization = infmt->quantization; - sdformat->format.ycbcr_enc = infmt->ycbcr_enc; } else { v4l_bound_align_image(&sdformat->format.width, MIN_W_SINK, MAX_W_SINK, W_ALIGN_SINK, @@ -908,9 +906,11 @@ static void prp_try_fmt(struct prp_priv *priv, MIN_H_SINK, MAX_H_SINK, H_ALIGN_SINK, S_ALIGN); - imx_media_fill_default_mbus_fields(&sdformat->format, infmt, - true); + if (sdformat->format.field == V4L2_FIELD_ANY) + sdformat->format.field = V4L2_FIELD_NONE; } + + imx_media_try_colorimetry(&sdformat->format, true); } static int prp_set_fmt(struct v4l2_subdev *sd, diff --git a/drivers/staging/media/imx/imx-media-csi.c b/drivers/staging/media/imx/imx-media-csi.c index 3b7517348666..cc3e0086b08a 100644 --- a/drivers/staging/media/imx/imx-media-csi.c +++ b/drivers/staging/media/imx/imx-media-csi.c @@ -1369,9 +1369,15 @@ static void csi_try_field(struct csi_priv *priv, struct v4l2_mbus_framefmt *infmt = __csi_get_fmt(priv, cfg, CSI_SINK_PAD, sdformat->which); - /* no restrictions on sink pad field type */ - if (sdformat->pad == CSI_SINK_PAD) + /* + * no restrictions on sink pad field type except must + * be initialized. + */ + if (sdformat->pad == CSI_SINK_PAD) { + if (sdformat->format.field == V4L2_FIELD_ANY) + sdformat->format.field = V4L2_FIELD_NONE; return; + } switch (infmt->field) { case V4L2_FIELD_SEQ_TB: @@ -1449,8 +1455,6 @@ static void csi_try_fmt(struct csi_priv *priv, /* propagate colorimetry from sink */ sdformat->format.colorspace = infmt->colorspace; sdformat->format.xfer_func = infmt->xfer_func; - sdformat->format.quantization = infmt->quantization; - sdformat->format.ycbcr_enc = infmt->ycbcr_enc; break; case CSI_SINK_PAD: @@ -1470,10 +1474,6 @@ static void csi_try_fmt(struct csi_priv *priv, csi_try_field(priv, cfg, sdformat); - imx_media_fill_default_mbus_fields( - &sdformat->format, infmt, - priv->active_output_pad == CSI_SRC_PAD_DIRECT); - /* Reset crop and compose rectangles */ crop->left = 0; crop->top = 0; @@ -1489,6 +1489,9 @@ static void csi_try_fmt(struct csi_priv *priv, break; } + + imx_media_try_colorimetry(&sdformat->format, + priv->active_output_pad == CSI_SRC_PAD_DIRECT); } static int csi_set_fmt(struct v4l2_subdev *sd, diff --git a/drivers/staging/media/imx/imx-media-utils.c b/drivers/staging/media/imx/imx-media-utils.c index 1c63a2765a81..aa7d4be77a7e 100644 --- a/drivers/staging/media/imx/imx-media-utils.c +++ b/drivers/staging/media/imx/imx-media-utils.c @@ -515,21 +515,19 @@ int imx_media_init_cfg(struct v4l2_subdev *sd, EXPORT_SYMBOL_GPL(imx_media_init_cfg); /* - * Check whether the field and colorimetry parameters in tryfmt are - * uninitialized, and if so fill them with the values from fmt, - * or if tryfmt->colorspace has been initialized, all the default - * colorimetry params can be derived from tryfmt->colorspace. + * Default the colorspace in tryfmt to SRGB if set to an unsupported + * colorspace or not initialized. Then set the remaining colorimetry + * parameters based on the colorspace if they are uninitialized. * * tryfmt->code must be set on entry. * * If this format is destined to be routed through the Image Converter, - * quantization and Y`CbCr encoding must be fixed. The IC expects and - * produces fixed quantization and Y`CbCr encoding at its input and output - * (full range for RGB, limited range for YUV, and V4L2_YCBCR_ENC_601). + * quantization and Y`CbCr encoding must be fixed. The IC supports only + * full-range quantization for RGB at its input and output, and only + * BT.601 Y`CbCr encoding. */ -void imx_media_fill_default_mbus_fields(struct v4l2_mbus_framefmt *tryfmt, - struct v4l2_mbus_framefmt *fmt, - bool ic_route) +void imx_media_try_colorimetry(struct v4l2_mbus_framefmt *tryfmt, + bool ic_route) { const struct imx_media_pixfmt *cc; bool is_rgb = false; @@ -537,28 +535,41 @@ void imx_media_fill_default_mbus_fields(struct v4l2_mbus_framefmt *tryfmt, cc = imx_media_find_mbus_format(tryfmt->code, CS_SEL_ANY, true); if (!cc) cc = imx_media_find_ipu_format(tryfmt->code, CS_SEL_ANY); - if (cc && cc->cs != IPUV3_COLORSPACE_YUV) + if (cc && cc->cs == IPUV3_COLORSPACE_RGB) is_rgb = true; - /* fill field if necessary */ - if (tryfmt->field == V4L2_FIELD_ANY) - tryfmt->field = fmt->field; + switch (tryfmt->colorspace) { + case V4L2_COLORSPACE_SMPTE170M: + case V4L2_COLORSPACE_REC709: + case V4L2_COLORSPACE_JPEG: + case V4L2_COLORSPACE_SRGB: + case V4L2_COLORSPACE_BT2020: + case V4L2_COLORSPACE_OPRGB: + case V4L2_COLORSPACE_DCI_P3: + case V4L2_COLORSPACE_RAW: + break; + default: + tryfmt->colorspace = V4L2_COLORSPACE_SRGB; + break; + } + + if (tryfmt->xfer_func == V4L2_XFER_FUNC_DEFAULT) { + tryfmt->xfer_func = + V4L2_MAP_XFER_FUNC_DEFAULT(tryfmt->colorspace); + } + + if (ic_route) { + if (is_rgb || + tryfmt->quantization == V4L2_QUANTIZATION_DEFAULT) + tryfmt->quantization = V4L2_QUANTIZATION_FULL_RANGE; - /* fill colorimetry if necessary */ - if (tryfmt->colorspace == V4L2_COLORSPACE_DEFAULT) { - tryfmt->colorspace = fmt->colorspace; - tryfmt->xfer_func = fmt->xfer_func; - tryfmt->ycbcr_enc = fmt->ycbcr_enc; - tryfmt->quantization = fmt->quantization; + tryfmt->ycbcr_enc = V4L2_YCBCR_ENC_601; } else { - if (tryfmt->xfer_func == V4L2_XFER_FUNC_DEFAULT) { - tryfmt->xfer_func = - V4L2_MAP_XFER_FUNC_DEFAULT(tryfmt->colorspace); - } if (tryfmt->ycbcr_enc == V4L2_YCBCR_ENC_DEFAULT) { tryfmt->ycbcr_enc = V4L2_MAP_YCBCR_ENC_DEFAULT(tryfmt->colorspace); } + if (tryfmt->quantization == V4L2_QUANTIZATION_DEFAULT) { tryfmt->quantization = V4L2_MAP_QUANTIZATION_DEFAULT( @@ -566,15 +577,8 @@ void imx_media_fill_default_mbus_fields(struct v4l2_mbus_framefmt *tryfmt, tryfmt->ycbcr_enc); } } - - if (ic_route) { - tryfmt->quantization = is_rgb ? - V4L2_QUANTIZATION_FULL_RANGE : - V4L2_QUANTIZATION_LIM_RANGE; - tryfmt->ycbcr_enc = V4L2_YCBCR_ENC_601; - } } -EXPORT_SYMBOL_GPL(imx_media_fill_default_mbus_fields); +EXPORT_SYMBOL_GPL(imx_media_try_colorimetry); int imx_media_mbus_fmt_to_pix_fmt(struct v4l2_pix_format *pix, struct v4l2_rect *compose, diff --git a/drivers/staging/media/imx/imx-media-vdic.c b/drivers/staging/media/imx/imx-media-vdic.c index 2808662e2597..a285619afa0f 100644 --- a/drivers/staging/media/imx/imx-media-vdic.c +++ b/drivers/staging/media/imx/imx-media-vdic.c @@ -615,14 +615,13 @@ static void vdic_try_fmt(struct vdic_priv *priv, &sdformat->format.height, MIN_H, MAX_H_VDIC, H_ALIGN, S_ALIGN); - imx_media_fill_default_mbus_fields(&sdformat->format, infmt, - true); - /* input must be interlaced! Choose SEQ_TB if not */ if (!V4L2_FIELD_HAS_BOTH(sdformat->format.field)) sdformat->format.field = V4L2_FIELD_SEQ_TB; break; } + + imx_media_try_colorimetry(&sdformat->format, true); } static int vdic_set_fmt(struct v4l2_subdev *sd, diff --git a/drivers/staging/media/imx/imx-media.h b/drivers/staging/media/imx/imx-media.h index ae964c8d5be1..48c8996d394c 100644 --- a/drivers/staging/media/imx/imx-media.h +++ b/drivers/staging/media/imx/imx-media.h @@ -176,9 +176,8 @@ int imx_media_init_mbus_fmt(struct v4l2_mbus_framefmt *mbus, const struct imx_media_pixfmt **cc); int imx_media_init_cfg(struct v4l2_subdev *sd, struct v4l2_subdev_pad_config *cfg); -void imx_media_fill_default_mbus_fields(struct v4l2_mbus_framefmt *tryfmt, - struct v4l2_mbus_framefmt *fmt, - bool ic_route); +void imx_media_try_colorimetry(struct v4l2_mbus_framefmt *tryfmt, + bool ic_route); int imx_media_mbus_fmt_to_pix_fmt(struct v4l2_pix_format *pix, struct v4l2_rect *compose, const struct v4l2_mbus_framefmt *mbus, diff --git a/drivers/staging/media/imx/imx7-media-csi.c b/drivers/staging/media/imx/imx7-media-csi.c index 3fba7c27c0ec..6e626c10a5f1 100644 --- a/drivers/staging/media/imx/imx7-media-csi.c +++ b/drivers/staging/media/imx/imx7-media-csi.c @@ -1003,8 +1003,6 @@ static int imx7_csi_try_fmt(struct imx7_csi *csi, sdformat->format.colorspace = in_fmt->colorspace; sdformat->format.xfer_func = in_fmt->xfer_func; - sdformat->format.quantization = in_fmt->quantization; - sdformat->format.ycbcr_enc = in_fmt->ycbcr_enc; break; case IMX7_CSI_PAD_SINK: *cc = imx_media_find_mbus_format(sdformat->format.code, @@ -1015,14 +1013,14 @@ static int imx7_csi_try_fmt(struct imx7_csi *csi, false); sdformat->format.code = (*cc)->codes[0]; } - - imx_media_fill_default_mbus_fields(&sdformat->format, in_fmt, - false); break; default: return -EINVAL; break; } + + imx_media_try_colorimetry(&sdformat->format, false); + return 0; } -- 2.17.1