diff mbox series

[v2,3/9] media: rkisp1: Fix source pad format configuration

Message ID 20220823171840.8958-4-laurent.pinchart@ideasonboard.com (mailing list archive)
State New, archived
Headers show
Series media: rkisp1: Fix and improve color space support | expand

Commit Message

Laurent Pinchart Aug. 23, 2022, 5:18 p.m. UTC
The ISP converts Bayer data to YUV when operating normally, and can also
operate in pass-through mode where the input and output formats must
match. Converting from YUV to Bayer isn't possible. If such an invalid
configuration is attempted, adjust it by copying the sink pad media bus
code to the source pad.

Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Reviewed-by: Dafna Hirschfeld <dafna@fastmail.com>
---
 .../platform/rockchip/rkisp1/rkisp1-isp.c     | 40 +++++++++++++++----
 1 file changed, 32 insertions(+), 8 deletions(-)

Comments

Paul Elder Aug. 25, 2022, 2:58 p.m. UTC | #1
On Tue, Aug 23, 2022 at 08:18:34PM +0300, Laurent Pinchart wrote:
> The ISP converts Bayer data to YUV when operating normally, and can also
> operate in pass-through mode where the input and output formats must
> match. Converting from YUV to Bayer isn't possible. If such an invalid
> configuration is attempted, adjust it by copying the sink pad media bus
> code to the source pad.
> 
> Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
> Reviewed-by: Dafna Hirschfeld <dafna@fastmail.com>

Reviewed-by: Paul Elder <paul.elder@ideasonboard.com>

> ---
>  .../platform/rockchip/rkisp1/rkisp1-isp.c     | 40 +++++++++++++++----
>  1 file changed, 32 insertions(+), 8 deletions(-)
> 
> diff --git a/drivers/media/platform/rockchip/rkisp1/rkisp1-isp.c b/drivers/media/platform/rockchip/rkisp1/rkisp1-isp.c
> index b5bdf427c7e1..d34f32271d74 100644
> --- a/drivers/media/platform/rockchip/rkisp1/rkisp1-isp.c
> +++ b/drivers/media/platform/rockchip/rkisp1/rkisp1-isp.c
> @@ -604,23 +604,43 @@ static void rkisp1_isp_set_src_fmt(struct rkisp1_isp *isp,
>  				   struct v4l2_mbus_framefmt *format,
>  				   unsigned int which)
>  {
> -	const struct rkisp1_mbus_info *mbus_info;
> +	const struct rkisp1_mbus_info *sink_info;
> +	const struct rkisp1_mbus_info *src_info;
> +	struct v4l2_mbus_framefmt *sink_fmt;
>  	struct v4l2_mbus_framefmt *src_fmt;
>  	const struct v4l2_rect *src_crop;
>  
> +	sink_fmt = rkisp1_isp_get_pad_fmt(isp, sd_state,
> +					  RKISP1_ISP_PAD_SINK_VIDEO, which);
>  	src_fmt = rkisp1_isp_get_pad_fmt(isp, sd_state,
>  					 RKISP1_ISP_PAD_SOURCE_VIDEO, which);
>  	src_crop = rkisp1_isp_get_pad_crop(isp, sd_state,
>  					   RKISP1_ISP_PAD_SOURCE_VIDEO, which);
>  
> +	/*
> +	 * Media bus code. The ISP can operate in pass-through mode (Bayer in,
> +	 * Bayer out or YUV in, YUV out) or process Bayer data to YUV, but
> +	 * can't convert from YUV to Bayer.
> +	 */
> +	sink_info = rkisp1_mbus_info_get_by_code(sink_fmt->code);
> +
>  	src_fmt->code = format->code;
> -	mbus_info = rkisp1_mbus_info_get_by_code(src_fmt->code);
> -	if (!mbus_info || !(mbus_info->direction & RKISP1_ISP_SD_SRC)) {
> +	src_info = rkisp1_mbus_info_get_by_code(src_fmt->code);
> +	if (!src_info || !(src_info->direction & RKISP1_ISP_SD_SRC)) {
>  		src_fmt->code = RKISP1_DEF_SRC_PAD_FMT;
> -		mbus_info = rkisp1_mbus_info_get_by_code(src_fmt->code);
> +		src_info = rkisp1_mbus_info_get_by_code(src_fmt->code);
>  	}
> -	if (which == V4L2_SUBDEV_FORMAT_ACTIVE)
> -		isp->src_fmt = mbus_info;
> +
> +	if (sink_info->pixel_enc == V4L2_PIXEL_ENC_YUV &&
> +	    src_info->pixel_enc == V4L2_PIXEL_ENC_BAYER) {
> +		src_fmt->code = sink_fmt->code;
> +		src_info = sink_info;
> +	}
> +
> +	/*
> +	 * The source width and height must be identical to the source crop
> +	 * size.
> +	 */
>  	src_fmt->width  = src_crop->width;
>  	src_fmt->height = src_crop->height;
>  
> @@ -630,14 +650,18 @@ static void rkisp1_isp_set_src_fmt(struct rkisp1_isp *isp,
>  	 */
>  	if (format->flags & V4L2_MBUS_FRAMEFMT_SET_CSC &&
>  	    format->quantization == V4L2_QUANTIZATION_FULL_RANGE &&
> -	    mbus_info->pixel_enc == V4L2_PIXEL_ENC_YUV)
> +	    src_info->pixel_enc == V4L2_PIXEL_ENC_YUV)
>  		src_fmt->quantization = V4L2_QUANTIZATION_FULL_RANGE;
> -	else if (mbus_info->pixel_enc == V4L2_PIXEL_ENC_YUV)
> +	else if (src_info->pixel_enc == V4L2_PIXEL_ENC_YUV)
>  		src_fmt->quantization = V4L2_QUANTIZATION_LIM_RANGE;
>  	else
>  		src_fmt->quantization = V4L2_QUANTIZATION_FULL_RANGE;
>  
>  	*format = *src_fmt;
> +
> +	/* Store the source format info when setting the active format. */
> +	if (which == V4L2_SUBDEV_FORMAT_ACTIVE)
> +		isp->src_fmt = src_info;
>  }
>  
>  static void rkisp1_isp_set_src_crop(struct rkisp1_isp *isp,
diff mbox series

Patch

diff --git a/drivers/media/platform/rockchip/rkisp1/rkisp1-isp.c b/drivers/media/platform/rockchip/rkisp1/rkisp1-isp.c
index b5bdf427c7e1..d34f32271d74 100644
--- a/drivers/media/platform/rockchip/rkisp1/rkisp1-isp.c
+++ b/drivers/media/platform/rockchip/rkisp1/rkisp1-isp.c
@@ -604,23 +604,43 @@  static void rkisp1_isp_set_src_fmt(struct rkisp1_isp *isp,
 				   struct v4l2_mbus_framefmt *format,
 				   unsigned int which)
 {
-	const struct rkisp1_mbus_info *mbus_info;
+	const struct rkisp1_mbus_info *sink_info;
+	const struct rkisp1_mbus_info *src_info;
+	struct v4l2_mbus_framefmt *sink_fmt;
 	struct v4l2_mbus_framefmt *src_fmt;
 	const struct v4l2_rect *src_crop;
 
+	sink_fmt = rkisp1_isp_get_pad_fmt(isp, sd_state,
+					  RKISP1_ISP_PAD_SINK_VIDEO, which);
 	src_fmt = rkisp1_isp_get_pad_fmt(isp, sd_state,
 					 RKISP1_ISP_PAD_SOURCE_VIDEO, which);
 	src_crop = rkisp1_isp_get_pad_crop(isp, sd_state,
 					   RKISP1_ISP_PAD_SOURCE_VIDEO, which);
 
+	/*
+	 * Media bus code. The ISP can operate in pass-through mode (Bayer in,
+	 * Bayer out or YUV in, YUV out) or process Bayer data to YUV, but
+	 * can't convert from YUV to Bayer.
+	 */
+	sink_info = rkisp1_mbus_info_get_by_code(sink_fmt->code);
+
 	src_fmt->code = format->code;
-	mbus_info = rkisp1_mbus_info_get_by_code(src_fmt->code);
-	if (!mbus_info || !(mbus_info->direction & RKISP1_ISP_SD_SRC)) {
+	src_info = rkisp1_mbus_info_get_by_code(src_fmt->code);
+	if (!src_info || !(src_info->direction & RKISP1_ISP_SD_SRC)) {
 		src_fmt->code = RKISP1_DEF_SRC_PAD_FMT;
-		mbus_info = rkisp1_mbus_info_get_by_code(src_fmt->code);
+		src_info = rkisp1_mbus_info_get_by_code(src_fmt->code);
 	}
-	if (which == V4L2_SUBDEV_FORMAT_ACTIVE)
-		isp->src_fmt = mbus_info;
+
+	if (sink_info->pixel_enc == V4L2_PIXEL_ENC_YUV &&
+	    src_info->pixel_enc == V4L2_PIXEL_ENC_BAYER) {
+		src_fmt->code = sink_fmt->code;
+		src_info = sink_info;
+	}
+
+	/*
+	 * The source width and height must be identical to the source crop
+	 * size.
+	 */
 	src_fmt->width  = src_crop->width;
 	src_fmt->height = src_crop->height;
 
@@ -630,14 +650,18 @@  static void rkisp1_isp_set_src_fmt(struct rkisp1_isp *isp,
 	 */
 	if (format->flags & V4L2_MBUS_FRAMEFMT_SET_CSC &&
 	    format->quantization == V4L2_QUANTIZATION_FULL_RANGE &&
-	    mbus_info->pixel_enc == V4L2_PIXEL_ENC_YUV)
+	    src_info->pixel_enc == V4L2_PIXEL_ENC_YUV)
 		src_fmt->quantization = V4L2_QUANTIZATION_FULL_RANGE;
-	else if (mbus_info->pixel_enc == V4L2_PIXEL_ENC_YUV)
+	else if (src_info->pixel_enc == V4L2_PIXEL_ENC_YUV)
 		src_fmt->quantization = V4L2_QUANTIZATION_LIM_RANGE;
 	else
 		src_fmt->quantization = V4L2_QUANTIZATION_FULL_RANGE;
 
 	*format = *src_fmt;
+
+	/* Store the source format info when setting the active format. */
+	if (which == V4L2_SUBDEV_FORMAT_ACTIVE)
+		isp->src_fmt = src_info;
 }
 
 static void rkisp1_isp_set_src_crop(struct rkisp1_isp *isp,