diff options
Diffstat (limited to 'drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_color.c')
-rw-r--r-- | drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_color.c | 42 |
1 files changed, 32 insertions, 10 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 b329393307e5..326f6fb7e0bc 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 @@ -231,18 +231,21 @@ void amdgpu_dm_set_ctm(struct dm_crtc_state *crtc) * preparation for hardware commit. If no lut is specified by user, we default * to SRGB degamma. * - * Currently, we only support degamma bypass, or preprogrammed SRGB degamma. - * Programmable degamma is not supported, and an attempt to do so will return - * -EINVAL. + * We support degamma bypass, predefined SRGB, and custom degamma * * RETURNS: - * 0 on success, -EINVAL if custom degamma curve is given. + * 0 on success + * -EINVAL if crtc_state has a degamma_lut of invalid size + * -ENOMEM if gamma allocation fails */ int amdgpu_dm_set_degamma_lut(struct drm_crtc_state *crtc_state, struct dc_plane_state *dc_plane_state) { struct drm_property_blob *blob = crtc_state->degamma_lut; struct drm_color_lut *lut; + uint32_t lut_size; + struct dc_gamma *gamma; + bool ret; if (!blob) { /* Default to SRGB */ @@ -258,11 +261,30 @@ int amdgpu_dm_set_degamma_lut(struct drm_crtc_state *crtc_state, return 0; } - /* Otherwise, assume SRGB, since programmable degamma is not - * supported. - */ - dc_plane_state->in_transfer_func->type = TF_TYPE_PREDEFINED; - dc_plane_state->in_transfer_func->tf = TRANSFER_FUNCTION_SRGB; - return -EINVAL; + gamma = dc_create_gamma(); + if (!gamma) + return -ENOMEM; + + lut_size = blob->length / sizeof(struct drm_color_lut); + gamma->num_entries = lut_size; + if (gamma->num_entries == MAX_COLOR_LUT_ENTRIES) + gamma->type = GAMMA_CUSTOM; + else { + dc_gamma_release(&gamma); + return -EINVAL; + } + + __drm_lut_to_dc_gamma(lut, gamma, false); + + dc_plane_state->in_transfer_func->type = TF_TYPE_DISTRIBUTED_POINTS; + ret = mod_color_calculate_degamma_params(dc_plane_state->in_transfer_func, gamma, true); + dc_gamma_release(&gamma); + if (!ret) { + dc_plane_state->in_transfer_func->type = TF_TYPE_BYPASS; + DRM_ERROR("Out of memory when calculating degamma params\n"); + return -ENOMEM; + } + + return 0; } |