struct v4l2_subdev_format *sdformat)
{
struct prp_priv *priv = sd_to_priv(sd);
+ struct v4l2_mbus_framefmt *fmt, *infmt;
const struct imx_media_pixfmt *cc;
- struct v4l2_mbus_framefmt *fmt;
int ret = 0;
u32 code;
goto out;
}
+ infmt = __prp_get_fmt(priv, cfg, PRP_SINK_PAD, sdformat->which);
+
switch (sdformat->pad) {
case PRP_SINK_PAD:
v4l_bound_align_image(&sdformat->format.width, MIN_W, MAX_W,
cc = imx_media_find_ipu_format(code, CS_SEL_ANY);
sdformat->format.code = cc->codes[0];
}
+
+ imx_media_fill_default_mbus_fields(&sdformat->format, infmt,
+ true);
break;
case PRP_SRC_PAD_PRPENC:
case PRP_SRC_PAD_PRPVF:
/* Output pads mirror input pad */
- fmt = __prp_get_fmt(priv, cfg, PRP_SINK_PAD, sdformat->which);
- sdformat->format = *fmt;
+ sdformat->format = *infmt;
break;
}
struct v4l2_subdev_format *sdformat,
const struct imx_media_pixfmt **cc)
{
+ struct v4l2_mbus_framefmt *infmt;
+
*cc = imx_media_find_ipu_format(sdformat->format.code, CS_SEL_ANY);
if (!*cc) {
u32 code;
sdformat->format.code = (*cc)->codes[0];
}
- if (sdformat->pad == PRPENCVF_SRC_PAD) {
- struct v4l2_mbus_framefmt *infmt =
- __prp_get_fmt(priv, cfg, PRPENCVF_SINK_PAD,
- sdformat->which);
+ infmt = __prp_get_fmt(priv, cfg, PRPENCVF_SINK_PAD, sdformat->which);
+ if (sdformat->pad == PRPENCVF_SRC_PAD) {
if (sdformat->format.field != V4L2_FIELD_NONE)
sdformat->format.field = infmt->field;
prp_bound_align_output(&sdformat->format, infmt,
priv->rot_mode);
+
+ /* 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,
&sdformat->format.height,
MIN_H_SINK, MAX_H_SINK, H_ALIGN_SINK,
S_ALIGN);
+
+ imx_media_fill_default_mbus_fields(&sdformat->format, infmt,
+ true);
}
}
struct v4l2_mbus_framefmt *infmt;
u32 code;
+ infmt = __csi_get_fmt(priv, cfg, CSI_SINK_PAD, sdformat->which);
+
switch (sdformat->pad) {
case CSI_SRC_PAD_DIRECT:
case CSI_SRC_PAD_IDMAC:
- infmt = __csi_get_fmt(priv, cfg, CSI_SINK_PAD,
- sdformat->which);
incc = imx_media_find_mbus_format(infmt->code,
CS_SEL_ANY, true);
sdformat->format.field = (infmt->height == 480) ?
V4L2_FIELD_SEQ_TB : V4L2_FIELD_SEQ_BT;
}
+
+ /* 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:
v4l_bound_align_image(&sdformat->format.width, MIN_W, MAX_W,
CS_SEL_ANY, false);
sdformat->format.code = (*cc)->codes[0];
}
+
+ imx_media_fill_default_mbus_fields(
+ &sdformat->format, infmt,
+ priv->active_output_pad == CSI_SRC_PAD_DIRECT);
break;
}
}
}
EXPORT_SYMBOL_GPL(imx_media_init_mbus_fmt);
+/*
+ * 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.
+ *
+ * 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).
+ */
+void imx_media_fill_default_mbus_fields(struct v4l2_mbus_framefmt *tryfmt,
+ struct v4l2_mbus_framefmt *fmt,
+ bool ic_route)
+{
+ const struct imx_media_pixfmt *cc;
+ bool is_rgb = false;
+
+ 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)
+ is_rgb = true;
+
+ /* fill field if necessary */
+ if (tryfmt->field == V4L2_FIELD_ANY)
+ tryfmt->field = fmt->field;
+
+ /* 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;
+ } 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(
+ is_rgb, tryfmt->colorspace,
+ 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);
+
int imx_media_mbus_fmt_to_pix_fmt(struct v4l2_pix_format *pix,
struct v4l2_mbus_framefmt *mbus,
const struct imx_media_pixfmt *cc)
sdformat->format.code = (*cc)->codes[0];
}
+ infmt = __vdic_get_fmt(priv, cfg, priv->active_input_pad,
+ sdformat->which);
+
switch (sdformat->pad) {
case VDIC_SRC_PAD_DIRECT:
- infmt = __vdic_get_fmt(priv, cfg, priv->active_input_pad,
- sdformat->which);
sdformat->format = *infmt;
/* output is always progressive! */
sdformat->format.field = V4L2_FIELD_NONE;
&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;
int imx_media_init_mbus_fmt(struct v4l2_mbus_framefmt *mbus,
u32 width, u32 height, u32 code, u32 field,
const struct imx_media_pixfmt **cc);
-
+void imx_media_fill_default_mbus_fields(struct v4l2_mbus_framefmt *tryfmt,
+ struct v4l2_mbus_framefmt *fmt,
+ bool ic_route);
int imx_media_mbus_fmt_to_pix_fmt(struct v4l2_pix_format *pix,
struct v4l2_mbus_framefmt *mbus,
const struct imx_media_pixfmt *cc);