[PATCH 22/36] drm/amd/display: add CRTC shaper LUT support
Melissa Wen
mwen at igalia.com
Tue May 23 22:15:06 UTC 2023
Map DC shaper LUT to DM CRTC color management. Shaper LUT can be used to
delinearize and/or normalize the color space for computational
efficiency and achiving specific visual styles. Blending usually occurs
in linear space and if a CRTC degamma 1D LUT is set to linearize the
color space, a custom shaper 1D LUT can be used just before applying 3D
LUT.
Signed-off-by: Melissa Wen <mwen at igalia.com>
---
.../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h | 7 +++
.../amd/display/amdgpu_dm/amdgpu_dm_color.c | 54 ++++++++++++++-----
2 files changed, 47 insertions(+), 14 deletions(-)
diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h
index eebe12c353ad..ea76c2957848 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h
@@ -803,6 +803,13 @@ struct dm_crtc_state {
* has a larger set of post-blending color calibration. Here, DC MPC
* color caps are wired up to DM CRTC state:
*/
+ /**
+ * @shaper_lut:
+ *
+ * Post-blending 1D Lookup table used to de-linearize pixel data for 3D
+ * LUT. The blob (if not NULL) is an array of &struct drm_color_lut.
+ */
+ struct drm_property_blob *shaper_lut;
/**
* @lut3d:
*
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 cef8d0d7f37b..934636d7b8d3 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
@@ -443,15 +443,26 @@ static void amdgpu_dm_atomic_lut3d(const struct drm_color_lut *drm_lut,
}
}
-static int amdgpu_dm_atomic_shaper_lut(struct dc_transfer_func *func_shaper)
+static int amdgpu_dm_atomic_shaper_lut(const struct drm_color_lut *shaper_lut,
+ uint32_t shaper_size,
+ struct dc_transfer_func *func_shaper)
{
- /* We don't get DRM shaper LUT yet. We assume the input color space is already
- * delinearized, so we don't need a shaper LUT and we can just BYPASS
- */
- func_shaper->type = TF_TYPE_BYPASS;
- func_shaper->tf = TRANSFER_FUNCTION_LINEAR;
+ int ret = 0;
- return 0;
+ if (shaper_size) {
+ /* If DRM shaper LUT is set, we assume a linear color space
+ * (linearized by DRM degamma 1D LUT or not)
+ */
+ func_shaper->type = TF_TYPE_DISTRIBUTED_POINTS;
+ func_shaper->tf = TRANSFER_FUNCTION_LINEAR;
+
+ ret = __set_output_tf(func_shaper, shaper_lut, shaper_size, false);
+ } else {
+ func_shaper->type = TF_TYPE_BYPASS;
+ func_shaper->tf = TRANSFER_FUNCTION_LINEAR;
+ }
+
+ return ret;
}
/* amdgpu_dm_atomic_shaper_lut3d - set DRM CRTC shaper LUT and 3D LUT to DC
@@ -499,7 +510,8 @@ static int amdgpu_dm_atomic_shaper_lut3d(struct dc *dc,
amdgpu_dm_atomic_lut3d(drm_lut3d, drm_lut3d_size, lut3d_func);
- return amdgpu_dm_atomic_shaper_lut(func_shaper);
+ return amdgpu_dm_atomic_shaper_lut(drm_shaper_lut,
+ drm_shaper_size, func_shaper);
}
/**
@@ -531,12 +543,22 @@ static uint32_t amdgpu_dm_get_lut3d_size(struct amdgpu_device *adev,
int amdgpu_dm_verify_lut3d_size(struct amdgpu_device *adev,
const struct drm_crtc_state *crtc_state)
{
- const struct drm_color_lut *lut3d = NULL;
struct dm_crtc_state *acrtc_state = to_dm_crtc_state(crtc_state);
+ const struct drm_color_lut *shaper = NULL, *lut3d = NULL;
uint32_t exp_size, size;
- exp_size = amdgpu_dm_get_lut3d_size(adev, MAX_COLOR_3DLUT_ENTRIES);
+ /* shaper LUT is only available if 3D LUT color caps*/
+ exp_size = amdgpu_dm_get_lut3d_size(adev, MAX_COLOR_LUT_ENTRIES);
+ shaper = __extract_blob_lut(acrtc_state->shaper_lut, &size);
+ if (shaper && size != exp_size) {
+ drm_dbg(&adev->ddev,
+ "Invalid Shaper LUT size. Should be %u but got %u.\n",
+ exp_size, size);
+ return -EINVAL;
+ }
+
+ exp_size = amdgpu_dm_get_lut3d_size(adev, MAX_COLOR_3DLUT_ENTRIES);
lut3d = __extract_blob_lut(acrtc_state->lut3d, &size);
if (lut3d && size != exp_size) {
@@ -618,15 +640,16 @@ int amdgpu_dm_update_crtc_color_mgmt(struct dm_crtc_state *crtc,
uint32_t degamma_size, regamma_size;
bool has_regamma, has_degamma;
bool is_legacy;
+ const struct drm_color_lut *shaper_lut, *lut3d;
+ uint32_t shaper_size, lut3d_size;
int r;
- const struct drm_color_lut *lut3d;
- uint32_t lut3d_size;
r = amdgpu_dm_verify_lut3d_size(adev, &crtc->base);
if (r)
return r;
lut3d = __extract_blob_lut(crtc->lut3d, &lut3d_size);
+ shaper_lut = __extract_blob_lut(crtc->shaper_lut, &shaper_size);
r = amdgpu_dm_verify_lut_sizes(&crtc->base);
if (r)
@@ -680,11 +703,14 @@ int amdgpu_dm_update_crtc_color_mgmt(struct dm_crtc_state *crtc,
* there is no user-blob.
*/
lut3d_size = lut3d != NULL ? lut3d_size : 0;
+ shaper_size = shaper_lut != NULL ? shaper_size : 0;
r = amdgpu_dm_atomic_shaper_lut3d(adev->dm.dc, ctx, stream,
- NULL, 0,
+ shaper_lut, shaper_size,
lut3d, lut3d_size);
- if (r)
+ if (r) {
+ drm_dbg(&adev->ddev, "Failed on shaper/3D LUTs setup\n");
return r;
+ }
/* Note: OGAM is disabled if 3D LUT is successfully programmed.
* See params and set_output_gamma in
--
2.39.2
More information about the amd-gfx
mailing list