mirror of https://gitee.com/openkylin/linux.git
drm/amd/display: Implement custom degamma lut on dcn
[Why] Custom degamma lut functions are a feature we would like to support on compatible hardware [How] In atomic check, convert from array of drm_color_lut to dc_transfer_func. On hardware commit, allow for possibility of custom degamma. Both are based on the equivalent regamma pipeline. Signed-off-by: David Francis <David.Francis@amd.com> Reviewed-by: Krunoslav Kovac <Krunoslav.Kovac@amd.com> Acked-by: Bhawanpreet Lakha <Bhawanpreet.Lakha@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
This commit is contained in:
parent
d90e9a3bf5
commit
78e4405cec
|
@ -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
|
* preparation for hardware commit. If no lut is specified by user, we default
|
||||||
* to SRGB degamma.
|
* to SRGB degamma.
|
||||||
*
|
*
|
||||||
* Currently, we only support degamma bypass, or preprogrammed SRGB degamma.
|
* We support degamma bypass, predefined SRGB, and custom degamma
|
||||||
* Programmable degamma is not supported, and an attempt to do so will return
|
|
||||||
* -EINVAL.
|
|
||||||
*
|
*
|
||||||
* RETURNS:
|
* 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,
|
int amdgpu_dm_set_degamma_lut(struct drm_crtc_state *crtc_state,
|
||||||
struct dc_plane_state *dc_plane_state)
|
struct dc_plane_state *dc_plane_state)
|
||||||
{
|
{
|
||||||
struct drm_property_blob *blob = crtc_state->degamma_lut;
|
struct drm_property_blob *blob = crtc_state->degamma_lut;
|
||||||
struct drm_color_lut *lut;
|
struct drm_color_lut *lut;
|
||||||
|
uint32_t lut_size;
|
||||||
|
struct dc_gamma *gamma;
|
||||||
|
bool ret;
|
||||||
|
|
||||||
if (!blob) {
|
if (!blob) {
|
||||||
/* Default to SRGB */
|
/* Default to SRGB */
|
||||||
|
@ -258,11 +261,30 @@ int amdgpu_dm_set_degamma_lut(struct drm_crtc_state *crtc_state,
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Otherwise, assume SRGB, since programmable degamma is not
|
gamma = dc_create_gamma();
|
||||||
* supported.
|
if (!gamma)
|
||||||
*/
|
return -ENOMEM;
|
||||||
dc_plane_state->in_transfer_func->type = TF_TYPE_PREDEFINED;
|
|
||||||
dc_plane_state->in_transfer_func->tf = TRANSFER_FUNCTION_SRGB;
|
lut_size = blob->length / sizeof(struct drm_color_lut);
|
||||||
return -EINVAL;
|
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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -417,6 +417,7 @@ enum {
|
||||||
GAMMA_RGB_256_ENTRIES = 256,
|
GAMMA_RGB_256_ENTRIES = 256,
|
||||||
GAMMA_RGB_FLOAT_1024_ENTRIES = 1024,
|
GAMMA_RGB_FLOAT_1024_ENTRIES = 1024,
|
||||||
GAMMA_CS_TFM_1D_ENTRIES = 4096,
|
GAMMA_CS_TFM_1D_ENTRIES = 4096,
|
||||||
|
GAMMA_CUSTOM_ENTRIES = 4096,
|
||||||
GAMMA_MAX_ENTRIES = 4096
|
GAMMA_MAX_ENTRIES = 4096
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -424,6 +425,7 @@ enum dc_gamma_type {
|
||||||
GAMMA_RGB_256 = 1,
|
GAMMA_RGB_256 = 1,
|
||||||
GAMMA_RGB_FLOAT_1024 = 2,
|
GAMMA_RGB_FLOAT_1024 = 2,
|
||||||
GAMMA_CS_TFM_1D = 3,
|
GAMMA_CS_TFM_1D = 3,
|
||||||
|
GAMMA_CUSTOM = 4,
|
||||||
};
|
};
|
||||||
|
|
||||||
struct dc_csc_transform {
|
struct dc_csc_transform {
|
||||||
|
|
|
@ -1213,8 +1213,11 @@ static bool dcn10_set_input_transfer_func(struct pipe_ctx *pipe_ctx,
|
||||||
} else if (tf->type == TF_TYPE_BYPASS) {
|
} else if (tf->type == TF_TYPE_BYPASS) {
|
||||||
dpp_base->funcs->dpp_set_degamma(dpp_base, IPP_DEGAMMA_MODE_BYPASS);
|
dpp_base->funcs->dpp_set_degamma(dpp_base, IPP_DEGAMMA_MODE_BYPASS);
|
||||||
} else {
|
} else {
|
||||||
/*TF_TYPE_DISTRIBUTED_POINTS*/
|
cm_helper_translate_curve_to_degamma_hw_format(tf,
|
||||||
result = false;
|
&dpp_base->degamma_params);
|
||||||
|
dpp_base->funcs->dpp_program_degamma_pwl(dpp_base,
|
||||||
|
&dpp_base->degamma_params);
|
||||||
|
result = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
|
|
|
@ -997,7 +997,9 @@ static void scale_user_regamma_ramp(struct pwl_float_data *pwl_rgb,
|
||||||
* norm_y = 4095*regamma_y, and index is just truncating to nearest integer
|
* norm_y = 4095*regamma_y, and index is just truncating to nearest integer
|
||||||
* lut1 = lut1D[index], lut2 = lut1D[index+1]
|
* lut1 = lut1D[index], lut2 = lut1D[index+1]
|
||||||
*
|
*
|
||||||
*adjustedY is then linearly interpolating regamma Y between lut1 and lut2
|
* adjustedY is then linearly interpolating regamma Y between lut1 and lut2
|
||||||
|
*
|
||||||
|
* Custom degamma on Linux uses the same interpolation math, so is handled here
|
||||||
*/
|
*/
|
||||||
static void apply_lut_1d(
|
static void apply_lut_1d(
|
||||||
const struct dc_gamma *ramp,
|
const struct dc_gamma *ramp,
|
||||||
|
@ -1018,7 +1020,7 @@ static void apply_lut_1d(
|
||||||
struct fixed31_32 delta_lut;
|
struct fixed31_32 delta_lut;
|
||||||
struct fixed31_32 delta_index;
|
struct fixed31_32 delta_index;
|
||||||
|
|
||||||
if (ramp->type != GAMMA_CS_TFM_1D)
|
if (ramp->type != GAMMA_CS_TFM_1D && ramp->type != GAMMA_CUSTOM)
|
||||||
return; // this is not expected
|
return; // this is not expected
|
||||||
|
|
||||||
for (i = 0; i < num_hw_points; i++) {
|
for (i = 0; i < num_hw_points; i++) {
|
||||||
|
@ -1636,7 +1638,9 @@ bool mod_color_calculate_degamma_params(struct dc_transfer_func *input_tf,
|
||||||
map_regamma_hw_to_x_user(ramp, coeff, rgb_user,
|
map_regamma_hw_to_x_user(ramp, coeff, rgb_user,
|
||||||
coordinates_x, axix_x, curve,
|
coordinates_x, axix_x, curve,
|
||||||
MAX_HW_POINTS, tf_pts,
|
MAX_HW_POINTS, tf_pts,
|
||||||
mapUserRamp);
|
mapUserRamp && ramp->type != GAMMA_CUSTOM);
|
||||||
|
if (ramp->type == GAMMA_CUSTOM)
|
||||||
|
apply_lut_1d(ramp, MAX_HW_POINTS, tf_pts);
|
||||||
|
|
||||||
ret = true;
|
ret = true;
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue