Skip to contentSkip to conversation

drm/rockchip: vop2: add COLOR_ENCODING and COLOR_RANGE plane properties

PATCH In review Igor Paunovic 1 participant 2 messages Jul 16 – Sep 9

Subsystems (4)
lore
Share & tools
lore
#0 lore raw

PATCH 1/1 drm/rockchip: vop2: add COLOR_ENCODING and COLOR_RANGE plane properties

The VOP2 windows have a YCbCr to RGB conversion block whose coefficient matrix is selected by a per-window CSC mode field, with hardware support for BT.601, BT.709 (both limited range) and BT.2020, plus a BT.601 full range mode. So far the driver hardcodes this to BT.709 limited range for every YUV plane, so BT.601 (SD) and BT.2020 content is converted with the wrong matrix.

Expose the standard COLOR_ENCODING and COLOR_RANGE plane properties and program the window CSC mode from them, so userspace can request the matrix matching the framebuffer. The default stays BT.709 limited range, which matches the previous behaviour. The hardware has no full range mode for the BT.709 and BT.2020 encodings, so that combination is rejected in the plane atomic check.

---
 drivers/gpu/drm/rockchip/rockchip_drm_vop2.c | 40 +++++++++++++++++++-
 1 file changed, 38 insertions(+), 2 deletions(-)
drivers/gpu/drm/rockchip/rockchip_drm_vop2.c +38 -2
index 4cce3e3..22e056b 100644
@@ -667,6 +667,22 @@ static int vop2_convert_csc_mode(int csc_mode)
 	}
 }
 
+static int vop2_convert_color_encoding(enum drm_color_encoding color_encoding,
+				       enum drm_color_range color_range)
+{
+	bool full_range = color_range == DRM_COLOR_YCBCR_FULL_RANGE;
+
+	switch (color_encoding) {
+	case DRM_COLOR_YCBCR_BT601:
+		return full_range ? CSC_BT601F : CSC_BT601L;
+	case DRM_COLOR_YCBCR_BT2020:
+		return CSC_BT2020L;
+	case DRM_COLOR_YCBCR_BT709:
+	default:
+		return CSC_BT709L;
+	}
+}
+
 /*
  * colorspace path:
  *      Input        Win csc                     Output
@@ -707,7 +723,6 @@ static void vop2_setup_csc_mode(struct vop2_video_port *vp,
 	struct rockchip_crtc_state *vcstate = to_rockchip_crtc_state(vp->crtc.state);
 	int is_input_yuv = pstate->fb->format->is_yuv;
 	int is_output_yuv = is_yuv_output(vcstate->bus_format);
-	int input_csc = V4L2_COLORSPACE_DEFAULT;
 	int output_csc = vcstate->color_space;
 	bool r2y_en, y2r_en;
 	int csc_mode;
@@ -715,7 +730,8 @@ static void vop2_setup_csc_mode(struct vop2_video_port *vp,
 	if (is_input_yuv && !is_output_yuv) {
 		y2r_en = true;
 		r2y_en = false;
-		csc_mode = vop2_convert_csc_mode(input_csc);
+		csc_mode = vop2_convert_color_encoding(pstate->color_encoding,
+						       pstate->color_range);
 	} else if (!is_input_yuv && is_output_yuv) {
 		y2r_en = false;
 		r2y_en = true;
@@ -1109,6 +1125,18 @@ static int vop2_plane_atomic_check(struct drm_plane *plane,
 	if (WARN_ON(format < 0))
 		return format;
 
+	/*
+	 * The window CSC hardware has no full range mode for the BT.709 and
+	 * BT.2020 encodings, so reject that combination.
+	 */
+	if (fb->format->is_yuv &&
+	    pstate->color_range == DRM_COLOR_YCBCR_FULL_RANGE &&
+	    pstate->color_encoding != DRM_COLOR_YCBCR_BT601) {
+		drm_dbg_kms(vop2->drm,
+			    "Full range is only supported with BT.601 encoding\n");
+		return -EINVAL;
+	}
+
 	/* Co-ordinates have now been clipped */
 	src_x = src->x1 >> 16;
 	src_w = drm_rect_width(src) >> 16;
@@ -2472,6 +2500,14 @@ static int vop2_plane_init(struct vop2 *vop2, struct vop2_win *win,
 	drm_plane_create_blend_mode_property(&win->base, blend_caps);
 	drm_plane_create_zpos_property(&win->base, win->win_id, 0,
 				       vop2->registered_num_wins - 1);
+	drm_plane_create_color_properties(&win->base,
+					  BIT(DRM_COLOR_YCBCR_BT601) |
+					  BIT(DRM_COLOR_YCBCR_BT709) |
+					  BIT(DRM_COLOR_YCBCR_BT2020),
+					  BIT(DRM_COLOR_YCBCR_LIMITED_RANGE) |
+					  BIT(DRM_COLOR_YCBCR_FULL_RANGE),
+					  DRM_COLOR_YCBCR_BT709,
+					  DRM_COLOR_YCBCR_LIMITED_RANGE);
 
 	return 0;
 }
Signature · 1 line
2.53.0
#1 lore raw

Hi,

Gentle ping on this one - it has had no review since July.

I re-checked it against the tree today rather than assuming it still stands. On drm-misc-next (8ce26b09f652) all five hunks still apply at their original line numbers, with no offset and no fuzz, and nothing merged since exposes these properties. So the gap the patch describes is
unchanged: every YUV plane is still converted with the BT.709 limited range matrix, which is wrong for BT.601 (SD) and BT.2020 content.

One thing worth flagging, since it decides the merge order rather than the content. Cristian's "drm/rockchip: vop2: Switch to enum vop_csc_format" (10/14 of the VOP2 series) touches the same two lines of vop2_setup_csc_mode() that this patch touches. The two changes are complementary rather than conflicting: that patch tightens the type of csc_mode and replaces the "csc_mode = false" assignment, while this one replaces where the value comes from - the hardcoded input_csc is dropped in favour of the plane's COLOR_ENCODING and COLOR_RANGE. Whichever lands second needs a small rebase.

I am happy to do that rebase in either direction. If you would rather have this on top of the VOP2 series, say so and I will send a v2 once it lands, with vop2_convert_color_encoding() returning enum vop_csc_format so the two fit together properly.

Thanks,
Igor