Commit 4791bd7d authored by Steve Longerbeam's avatar Steve Longerbeam Committed by Philipp Zabel

media: imx: Try colorimetry at both sink and source pads

Retask imx_media_fill_default_mbus_fields() to try colorimetry parameters,
renaming it to 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.

The IC now supports Rec.709 and BT.601 Y'CbCr encoding, and both limited
and full range quantization for both YUV and RGB space, so allow those
for pipelines that route through the IC.
Signed-off-by: default avatarSteve Longerbeam <slongerbeam@gmail.com>
Acked-by: default avatarHans Verkuil <hverkuil-cisco@xs4all.nl>
Signed-off-by: default avatarPhilipp Zabel <p.zabel@pengutronix.de>
parent 614014cf
...@@ -193,8 +193,8 @@ static int prp_set_fmt(struct v4l2_subdev *sd, ...@@ -193,8 +193,8 @@ static int prp_set_fmt(struct v4l2_subdev *sd,
sdformat->format.code = cc->codes[0]; sdformat->format.code = cc->codes[0];
} }
imx_media_fill_default_mbus_fields(&sdformat->format, infmt, if (sdformat->format.field == V4L2_FIELD_ANY)
true); sdformat->format.field = V4L2_FIELD_NONE;
break; break;
case PRP_SRC_PAD_PRPENC: case PRP_SRC_PAD_PRPENC:
case PRP_SRC_PAD_PRPVF: case PRP_SRC_PAD_PRPVF:
...@@ -203,6 +203,8 @@ static int prp_set_fmt(struct v4l2_subdev *sd, ...@@ -203,6 +203,8 @@ static int prp_set_fmt(struct v4l2_subdev *sd,
break; break;
} }
imx_media_try_colorimetry(&sdformat->format, true);
fmt = __prp_get_fmt(priv, cfg, sdformat->pad, sdformat->which); fmt = __prp_get_fmt(priv, cfg, sdformat->pad, sdformat->which);
*fmt = sdformat->format; *fmt = sdformat->format;
out: out:
......
...@@ -907,8 +907,6 @@ static void prp_try_fmt(struct prp_priv *priv, ...@@ -907,8 +907,6 @@ static void prp_try_fmt(struct prp_priv *priv,
/* propagate colorimetry from sink */ /* propagate colorimetry from sink */
sdformat->format.colorspace = infmt->colorspace; sdformat->format.colorspace = infmt->colorspace;
sdformat->format.xfer_func = infmt->xfer_func; sdformat->format.xfer_func = infmt->xfer_func;
sdformat->format.quantization = infmt->quantization;
sdformat->format.ycbcr_enc = infmt->ycbcr_enc;
} else { } else {
v4l_bound_align_image(&sdformat->format.width, v4l_bound_align_image(&sdformat->format.width,
MIN_W_SINK, MAX_W_SINK, W_ALIGN_SINK, MIN_W_SINK, MAX_W_SINK, W_ALIGN_SINK,
...@@ -916,9 +914,11 @@ static void prp_try_fmt(struct prp_priv *priv, ...@@ -916,9 +914,11 @@ static void prp_try_fmt(struct prp_priv *priv,
MIN_H_SINK, MAX_H_SINK, H_ALIGN_SINK, MIN_H_SINK, MAX_H_SINK, H_ALIGN_SINK,
S_ALIGN); S_ALIGN);
imx_media_fill_default_mbus_fields(&sdformat->format, infmt, if (sdformat->format.field == V4L2_FIELD_ANY)
true); sdformat->format.field = V4L2_FIELD_NONE;
} }
imx_media_try_colorimetry(&sdformat->format, true);
} }
static int prp_set_fmt(struct v4l2_subdev *sd, static int prp_set_fmt(struct v4l2_subdev *sd,
......
...@@ -1375,9 +1375,15 @@ static void csi_try_field(struct csi_priv *priv, ...@@ -1375,9 +1375,15 @@ static void csi_try_field(struct csi_priv *priv,
struct v4l2_mbus_framefmt *infmt = struct v4l2_mbus_framefmt *infmt =
__csi_get_fmt(priv, cfg, CSI_SINK_PAD, sdformat->which); __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; return;
}
switch (infmt->field) { switch (infmt->field) {
case V4L2_FIELD_SEQ_TB: case V4L2_FIELD_SEQ_TB:
...@@ -1455,8 +1461,6 @@ static void csi_try_fmt(struct csi_priv *priv, ...@@ -1455,8 +1461,6 @@ static void csi_try_fmt(struct csi_priv *priv,
/* propagate colorimetry from sink */ /* propagate colorimetry from sink */
sdformat->format.colorspace = infmt->colorspace; sdformat->format.colorspace = infmt->colorspace;
sdformat->format.xfer_func = infmt->xfer_func; sdformat->format.xfer_func = infmt->xfer_func;
sdformat->format.quantization = infmt->quantization;
sdformat->format.ycbcr_enc = infmt->ycbcr_enc;
break; break;
case CSI_SINK_PAD: case CSI_SINK_PAD:
...@@ -1476,10 +1480,6 @@ static void csi_try_fmt(struct csi_priv *priv, ...@@ -1476,10 +1480,6 @@ static void csi_try_fmt(struct csi_priv *priv,
csi_try_field(priv, cfg, sdformat); 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 */ /* Reset crop and compose rectangles */
crop->left = 0; crop->left = 0;
crop->top = 0; crop->top = 0;
...@@ -1495,6 +1495,9 @@ static void csi_try_fmt(struct csi_priv *priv, ...@@ -1495,6 +1495,9 @@ static void csi_try_fmt(struct csi_priv *priv,
break; break;
} }
imx_media_try_colorimetry(&sdformat->format,
priv->active_output_pad == CSI_SRC_PAD_DIRECT);
} }
static int csi_set_fmt(struct v4l2_subdev *sd, static int csi_set_fmt(struct v4l2_subdev *sd,
......
...@@ -511,21 +511,18 @@ int imx_media_init_cfg(struct v4l2_subdev *sd, ...@@ -511,21 +511,18 @@ int imx_media_init_cfg(struct v4l2_subdev *sd,
EXPORT_SYMBOL_GPL(imx_media_init_cfg); EXPORT_SYMBOL_GPL(imx_media_init_cfg);
/* /*
* Check whether the field and colorimetry parameters in tryfmt are * Default the colorspace in tryfmt to SRGB if set to an unsupported
* uninitialized, and if so fill them with the values from fmt, * colorspace or not initialized. Then set the remaining colorimetry
* or if tryfmt->colorspace has been initialized, all the default * parameters based on the colorspace if they are uninitialized.
* colorimetry params can be derived from tryfmt->colorspace.
* *
* tryfmt->code must be set on entry. * tryfmt->code must be set on entry.
* *
* If this format is destined to be routed through the Image Converter, * If this format is destined to be routed through the Image Converter,
* quantization and Y`CbCr encoding must be fixed. The IC expects and * Y`CbCr encoding must be fixed. The IC supports only BT.601 Y`CbCr
* produces fixed quantization and Y`CbCr encoding at its input and output * or Rec.709 Y`CbCr encoding.
* (full range for RGB, limited range for YUV, and V4L2_YCBCR_ENC_601).
*/ */
void imx_media_fill_default_mbus_fields(struct v4l2_mbus_framefmt *tryfmt, void imx_media_try_colorimetry(struct v4l2_mbus_framefmt *tryfmt,
struct v4l2_mbus_framefmt *fmt, bool ic_route)
bool ic_route)
{ {
const struct imx_media_pixfmt *cc; const struct imx_media_pixfmt *cc;
bool is_rgb = false; bool is_rgb = false;
...@@ -533,44 +530,46 @@ void imx_media_fill_default_mbus_fields(struct v4l2_mbus_framefmt *tryfmt, ...@@ -533,44 +530,46 @@ void imx_media_fill_default_mbus_fields(struct v4l2_mbus_framefmt *tryfmt,
cc = imx_media_find_mbus_format(tryfmt->code, CS_SEL_ANY, true); cc = imx_media_find_mbus_format(tryfmt->code, CS_SEL_ANY, true);
if (!cc) if (!cc)
cc = imx_media_find_ipu_format(tryfmt->code, CS_SEL_ANY); 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; is_rgb = true;
/* fill field if necessary */ switch (tryfmt->colorspace) {
if (tryfmt->field == V4L2_FIELD_ANY) case V4L2_COLORSPACE_SMPTE170M:
tryfmt->field = fmt->field; 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);
/* fill colorimetry if necessary */ if (ic_route) {
if (tryfmt->colorspace == V4L2_COLORSPACE_DEFAULT) { if (tryfmt->ycbcr_enc != V4L2_YCBCR_ENC_601 &&
tryfmt->colorspace = fmt->colorspace; tryfmt->ycbcr_enc != V4L2_YCBCR_ENC_709)
tryfmt->xfer_func = fmt->xfer_func; tryfmt->ycbcr_enc = V4L2_YCBCR_ENC_601;
tryfmt->ycbcr_enc = fmt->ycbcr_enc;
tryfmt->quantization = fmt->quantization;
} else { } 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) { if (tryfmt->ycbcr_enc == V4L2_YCBCR_ENC_DEFAULT) {
tryfmt->ycbcr_enc = tryfmt->ycbcr_enc =
V4L2_MAP_YCBCR_ENC_DEFAULT(tryfmt->colorspace); V4L2_MAP_YCBCR_ENC_DEFAULT(tryfmt->colorspace);
} }
if (tryfmt->quantization == V4L2_QUANTIZATION_DEFAULT) {
tryfmt->quantization =
V4L2_MAP_QUANTIZATION_DEFAULT(
is_rgb, tryfmt->colorspace,
tryfmt->ycbcr_enc);
}
} }
if (ic_route) { if (tryfmt->quantization == V4L2_QUANTIZATION_DEFAULT)
tryfmt->quantization = is_rgb ? tryfmt->quantization =
V4L2_QUANTIZATION_FULL_RANGE : V4L2_MAP_QUANTIZATION_DEFAULT(is_rgb,
V4L2_QUANTIZATION_LIM_RANGE; tryfmt->colorspace,
tryfmt->ycbcr_enc = V4L2_YCBCR_ENC_601; tryfmt->ycbcr_enc);
}
} }
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, int imx_media_mbus_fmt_to_pix_fmt(struct v4l2_pix_format *pix,
struct v4l2_rect *compose, struct v4l2_rect *compose,
......
...@@ -617,14 +617,13 @@ static void vdic_try_fmt(struct vdic_priv *priv, ...@@ -617,14 +617,13 @@ static void vdic_try_fmt(struct vdic_priv *priv,
&sdformat->format.height, &sdformat->format.height,
MIN_H, MAX_H_VDIC, H_ALIGN, S_ALIGN); 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 */ /* input must be interlaced! Choose SEQ_TB if not */
if (!V4L2_FIELD_HAS_BOTH(sdformat->format.field)) if (!V4L2_FIELD_HAS_BOTH(sdformat->format.field))
sdformat->format.field = V4L2_FIELD_SEQ_TB; sdformat->format.field = V4L2_FIELD_SEQ_TB;
break; break;
} }
imx_media_try_colorimetry(&sdformat->format, true);
} }
static int vdic_set_fmt(struct v4l2_subdev *sd, static int vdic_set_fmt(struct v4l2_subdev *sd,
......
...@@ -172,9 +172,8 @@ int imx_media_init_mbus_fmt(struct v4l2_mbus_framefmt *mbus, ...@@ -172,9 +172,8 @@ int imx_media_init_mbus_fmt(struct v4l2_mbus_framefmt *mbus,
const struct imx_media_pixfmt **cc); const struct imx_media_pixfmt **cc);
int imx_media_init_cfg(struct v4l2_subdev *sd, int imx_media_init_cfg(struct v4l2_subdev *sd,
struct v4l2_subdev_pad_config *cfg); struct v4l2_subdev_pad_config *cfg);
void imx_media_fill_default_mbus_fields(struct v4l2_mbus_framefmt *tryfmt, void imx_media_try_colorimetry(struct v4l2_mbus_framefmt *tryfmt,
struct v4l2_mbus_framefmt *fmt, bool ic_route);
bool ic_route);
int imx_media_mbus_fmt_to_pix_fmt(struct v4l2_pix_format *pix, int imx_media_mbus_fmt_to_pix_fmt(struct v4l2_pix_format *pix,
struct v4l2_rect *compose, struct v4l2_rect *compose,
const struct v4l2_mbus_framefmt *mbus, const struct v4l2_mbus_framefmt *mbus,
......
...@@ -1003,8 +1003,6 @@ static int imx7_csi_try_fmt(struct imx7_csi *csi, ...@@ -1003,8 +1003,6 @@ static int imx7_csi_try_fmt(struct imx7_csi *csi,
sdformat->format.colorspace = in_fmt->colorspace; sdformat->format.colorspace = in_fmt->colorspace;
sdformat->format.xfer_func = in_fmt->xfer_func; sdformat->format.xfer_func = in_fmt->xfer_func;
sdformat->format.quantization = in_fmt->quantization;
sdformat->format.ycbcr_enc = in_fmt->ycbcr_enc;
break; break;
case IMX7_CSI_PAD_SINK: case IMX7_CSI_PAD_SINK:
*cc = imx_media_find_mbus_format(sdformat->format.code, *cc = imx_media_find_mbus_format(sdformat->format.code,
...@@ -1015,14 +1013,14 @@ static int imx7_csi_try_fmt(struct imx7_csi *csi, ...@@ -1015,14 +1013,14 @@ static int imx7_csi_try_fmt(struct imx7_csi *csi,
false); false);
sdformat->format.code = (*cc)->codes[0]; sdformat->format.code = (*cc)->codes[0];
} }
imx_media_fill_default_mbus_fields(&sdformat->format, in_fmt,
false);
break; break;
default: default:
return -EINVAL; return -EINVAL;
break; break;
} }
imx_media_try_colorimetry(&sdformat->format, false);
return 0; return 0;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment