drm/amd/display: add plane shaper LUT support
Map DC shaper LUT to DM plane color management. Shaper LUT can be used to delinearize and/or normalize the color space for computational efficiency and achiving specific visual styles. If a plane degamma is apply to linearize the color space, a custom shaper 1D LUT can be used just before applying 3D LUT. v2: - use DPP color caps to verify plane 3D LUT support - add debug message if shaper LUT programming fails v4: - remove helper to check 3D LUT color caps (Harry) - update desc of lut3d-setup helper from MPC to DPP v5: - remove color_mgmt_changed check that prevents color updates (Joshua) Reviewed-by: Harry Wentland <harry.wentland@amd.com> Signed-off-by: Melissa Wen <mwen@igalia.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
This commit is contained in:
parent
4bc59ddf57
commit
aba8b76baa
3 changed files with 92 additions and 4 deletions
|
@ -8269,6 +8269,7 @@ static void amdgpu_dm_commit_planes(struct drm_atomic_state *state,
|
|||
bundle->surface_updates[planes_count].in_transfer_func = dc_plane->in_transfer_func;
|
||||
bundle->surface_updates[planes_count].gamut_remap_matrix = &dc_plane->gamut_remap_matrix;
|
||||
bundle->surface_updates[planes_count].hdr_mult = dc_plane->hdr_mult;
|
||||
bundle->surface_updates[planes_count].func_shaper = dc_plane->in_shaper_func;
|
||||
}
|
||||
|
||||
amdgpu_dm_plane_fill_dc_scaling_info(dm->adev, new_plane_state,
|
||||
|
|
|
@ -908,6 +908,8 @@ void amdgpu_dm_trigger_timing_sync(struct drm_device *dev);
|
|||
/* 3D LUT max size is 17x17x17 (4913 entries) */
|
||||
#define MAX_COLOR_3DLUT_SIZE 17
|
||||
#define MAX_COLOR_3DLUT_BITDEPTH 12
|
||||
int amdgpu_dm_verify_lut3d_size(struct amdgpu_device *adev,
|
||||
struct drm_plane_state *plane_state);
|
||||
/* 1D LUT size */
|
||||
#define MAX_COLOR_LUT_ENTRIES 4096
|
||||
/* Legacy gamm LUT users such as X doesn't like large LUT sizes */
|
||||
|
|
|
@ -623,6 +623,63 @@ amdgpu_tf_to_dc_tf(enum amdgpu_transfer_function tf)
|
|||
}
|
||||
}
|
||||
|
||||
static int amdgpu_dm_atomic_shaper_lut(const struct drm_color_lut *shaper_lut,
|
||||
uint32_t shaper_size,
|
||||
struct dc_transfer_func *func_shaper)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
if (shaper_size) {
|
||||
/*
|
||||
* If user shaper LUT is set, we assume a linear color space
|
||||
* (linearized by 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_verify_lut3d_size - verifies if 3D LUT is supported and if user
|
||||
* shaper and 3D LUTs match the hw supported size
|
||||
* @adev: amdgpu device
|
||||
* @crtc_state: the DRM CRTC state
|
||||
*
|
||||
* Verifies if pre-blending (DPP) 3D LUT is supported by the HW (DCN 2.0 or
|
||||
* newer) and if the user shaper and 3D LUTs match the supported size.
|
||||
*
|
||||
* Returns:
|
||||
* 0 on success. -EINVAL if lut size are invalid.
|
||||
*/
|
||||
int amdgpu_dm_verify_lut3d_size(struct amdgpu_device *adev,
|
||||
struct drm_plane_state *plane_state)
|
||||
{
|
||||
struct dm_plane_state *dm_plane_state = to_dm_plane_state(plane_state);
|
||||
const struct drm_color_lut *shaper = NULL;
|
||||
uint32_t exp_size, size;
|
||||
bool has_3dlut = adev->dm.dc->caps.color.dpp.hw_3d_lut;
|
||||
|
||||
/* shaper LUT is only available if 3D LUT color caps */
|
||||
exp_size = has_3dlut ? MAX_COLOR_LUT_ENTRIES : 0;
|
||||
shaper = __extract_blob_lut(dm_plane_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;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* amdgpu_dm_verify_lut_sizes - verifies if DRM luts match the hw supported sizes
|
||||
* @crtc_state: the DRM CRTC state
|
||||
|
@ -910,6 +967,30 @@ __set_dm_plane_degamma(struct drm_plane_state *plane_state,
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
amdgpu_dm_plane_set_color_properties(struct drm_plane_state *plane_state,
|
||||
struct dc_plane_state *dc_plane_state)
|
||||
{
|
||||
struct dm_plane_state *dm_plane_state = to_dm_plane_state(plane_state);
|
||||
const struct drm_color_lut *shaper_lut;
|
||||
uint32_t shaper_size;
|
||||
int ret;
|
||||
|
||||
dc_plane_state->hdr_mult = dc_fixpt_from_s3132(dm_plane_state->hdr_mult);
|
||||
|
||||
shaper_lut = __extract_blob_lut(dm_plane_state->shaper_lut, &shaper_size);
|
||||
shaper_size = shaper_lut != NULL ? shaper_size : 0;
|
||||
|
||||
ret = amdgpu_dm_atomic_shaper_lut(shaper_lut, shaper_size,
|
||||
dc_plane_state->in_shaper_func);
|
||||
if (ret)
|
||||
drm_dbg_kms(plane_state->plane->dev,
|
||||
"setting plane %d shaper LUT failed.\n",
|
||||
plane_state->plane->index);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* amdgpu_dm_update_plane_color_mgmt: Maps DRM color management to DC plane.
|
||||
* @crtc: amdgpu_dm crtc state
|
||||
|
@ -927,10 +1008,16 @@ int amdgpu_dm_update_plane_color_mgmt(struct dm_crtc_state *crtc,
|
|||
struct drm_plane_state *plane_state,
|
||||
struct dc_plane_state *dc_plane_state)
|
||||
{
|
||||
struct dm_plane_state *dm_plane_state = to_dm_plane_state(plane_state);
|
||||
struct amdgpu_device *adev = drm_to_adev(crtc->base.state->dev);
|
||||
bool has_crtc_cm_degamma;
|
||||
int ret;
|
||||
|
||||
ret = amdgpu_dm_verify_lut3d_size(adev, plane_state);
|
||||
if (ret) {
|
||||
drm_dbg_driver(&adev->ddev, "amdgpu_dm_verify_lut3d_size() failed\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Initially, we can just bypass the DGM block. */
|
||||
dc_plane_state->in_transfer_func->type = TF_TYPE_BYPASS;
|
||||
dc_plane_state->in_transfer_func->tf = TRANSFER_FUNCTION_LINEAR;
|
||||
|
@ -938,8 +1025,6 @@ int amdgpu_dm_update_plane_color_mgmt(struct dm_crtc_state *crtc,
|
|||
/* After, we start to update values according to color props */
|
||||
has_crtc_cm_degamma = (crtc->cm_has_degamma || crtc->cm_is_degamma_srgb);
|
||||
|
||||
dc_plane_state->hdr_mult = dc_fixpt_from_s3132(dm_plane_state->hdr_mult);
|
||||
|
||||
ret = __set_dm_plane_degamma(plane_state, dc_plane_state);
|
||||
if (ret == -ENOMEM)
|
||||
return ret;
|
||||
|
@ -972,5 +1057,5 @@ int amdgpu_dm_update_plane_color_mgmt(struct dm_crtc_state *crtc,
|
|||
return ret;
|
||||
}
|
||||
|
||||
return 0;
|
||||
return amdgpu_dm_plane_set_color_properties(plane_state, dc_plane_state);
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue