Add CSC (Color Space Conversion) colorop to the AMDGPU color pipeline as the first operation, before DEGAM. This colorop handles YUV-to-RGB conversion with support for: - BT.601, BT.709, BT.2020 encoding standards - Limited and full range - Bypass mode for RGB-only workflows
Implement __set_dm_plane_colorop_csc() which maps the CSC colorop's COLOR_ENCODING and COLOR_RANGE properties to DC's color_space enum. This controls which YUV→RGB conversion matrix DC selects from dpp_input_csc_matrix[] and programs into the DPP hardware. The implementation forces a full_update to ensure the DPP gets reprogrammed when the CSC colorop settings change. Co-developed by Claude Sonnet 4.5. Signed-off-by: Harry Wentland <[email protected]> --- .../amd/display/amdgpu_dm/amdgpu_dm_color.c | 75 ++++++++++++++++++- .../amd/display/amdgpu_dm/amdgpu_dm_colorop.c | 25 ++++++- 2 files changed, 98 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_color.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_color.c index cd1e58b8defc..d13b1b2d54cf 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_color.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_color.c @@ -1869,6 +1869,65 @@ amdgpu_dm_plane_set_color_properties(struct drm_plane_state *plane_state, return 0; } +/** + * __set_dm_plane_colorop_csc - Handle CSC colorop for YUV to RGB conversion + * @plane_state: DRM plane state + * @dc_plane_state: DC plane state to update + * @colorop: The CSC colorop + * + * Reads COLOR_ENCODING and COLOR_RANGE from the CSC colorop state and maps + * them to DC's color_space enum, which controls the YUV→RGB conversion matrix. + * + * Returns: + * 0 on success, negative error code on failure + */ +static int +__set_dm_plane_colorop_csc(struct drm_plane_state *plane_state, + struct dc_plane_state *dc_plane_state, + struct drm_colorop *colorop) +{ + struct drm_colorop_state *colorop_state; + enum drm_color_encoding encoding; + enum drm_color_range range; + enum dc_color_space dc_color_space; + bool full_range; + + if (colorop->type != DRM_COLOROP_CSC) + return -EINVAL; + + colorop_state = drm_atomic_get_colorop_state(plane_state->state, colorop); + if (IS_ERR(colorop_state)) + return PTR_ERR(colorop_state); + + encoding = colorop_state->color_encoding; + range = colorop_state->color_range; + full_range = (range == DRM_COLOR_YCBCR_FULL_RANGE); + + switch (encoding) { + case DRM_COLOR_YCBCR_BT601: + dc_color_space = full_range ? COLOR_SPACE_YCBCR601 + : COLOR_SPACE_YCBCR601_LIMITED; + break; + case DRM_COLOR_YCBCR_BT709: + dc_color_space = full_range ? COLOR_SPACE_YCBCR709 + : COLOR_SPACE_YCBCR709_LIMITED; + break; + case DRM_COLOR_YCBCR_BT2020: + dc_color_space = full_range ? COLOR_SPACE_2020_YCBCR_FULL + : COLOR_SPACE_2020_YCBCR_LIMITED; + break; + default: + return -EINVAL; + } + + dc_plane_state->color_space = dc_color_space; + + /* Force full update to ensure DPP gets reprogrammed with new CSC matrix */ + dc_plane_state->update_flags.bits.full_update = 1; + + return 0; +} + static int amdgpu_dm_plane_set_colorop_properties(struct drm_plane_state *plane_state, struct dc_plane_state *dc_plane_state) @@ -1879,10 +1938,24 @@ amdgpu_dm_plane_set_colorop_properties(struct drm_plane_state *plane_state, bool has_3dlut = adev->dm.dc->caps.color.dpp.hw_3d_lut || adev->dm.dc->caps.color.mpc.preblend; int ret; - /* 1D Curve - DEGAM TF */ + /* CSC - Color Space Conversion (YUV to RGB) */ if (!colorop) return -EINVAL; + if (colorop->type == DRM_COLOROP_CSC) { + ret = __set_dm_plane_colorop_csc(plane_state, dc_plane_state, colorop); + if (ret) + return ret; + + /* Move to next colorop */ + colorop = colorop->next; + if (!colorop) { + drm_dbg(dev, "no colorop after CSC found\n"); + return -EINVAL; + } + } + + /* 1D Curve - DEGAM TF */ ret = __set_dm_plane_colorop_degamma(plane_state, dc_plane_state, colorop); if (ret) return ret; diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_colorop.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_colorop.c index 3e05e48a8792..9c24fd1772a6 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_colorop.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_colorop.c @@ -70,6 +70,29 @@ int amdgpu_dm_initialize_default_pipeline(struct drm_plane *plane, struct drm_pr memset(ops, 0, sizeof(ops)); + /* CSC - Color Space Conversion (YUV to RGB) */ + ops[i] = kzalloc(sizeof(struct drm_colorop), GFP_KERNEL); + if (!ops[i]) { + ret = -ENOMEM; + goto cleanup; + } + + ret = drm_plane_colorop_csc_init(dev, ops[i], plane, &dm_colorop_funcs, + 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, + DRM_COLOROP_FLAG_ALLOW_BYPASS); + if (ret) + goto cleanup; + + list->type = ops[i]->base.id; + + i++; + /* 1D curve - DEGAM TF */ ops[i] = kzalloc_obj(*ops[0]); if (!ops[i]) { @@ -83,7 +106,7 @@ int amdgpu_dm_initialize_default_pipeline(struct drm_plane *plane, struct drm_pr if (ret) goto cleanup; - list->type = ops[i]->base.id; + drm_colorop_set_next_property(ops[i-1], ops[i]); i++; -- 2.53.0
