diff options
Diffstat (limited to 'common/recipes-kernel/linux/linux-yocto-4.14.71/5045-drm-amd-display-Implement-custom-degamma-lut-on-dcn.patch')
-rw-r--r-- | common/recipes-kernel/linux/linux-yocto-4.14.71/5045-drm-amd-display-Implement-custom-degamma-lut-on-dcn.patch | 170 |
1 files changed, 170 insertions, 0 deletions
diff --git a/common/recipes-kernel/linux/linux-yocto-4.14.71/5045-drm-amd-display-Implement-custom-degamma-lut-on-dcn.patch b/common/recipes-kernel/linux/linux-yocto-4.14.71/5045-drm-amd-display-Implement-custom-degamma-lut-on-dcn.patch new file mode 100644 index 00000000..990db1bd --- /dev/null +++ b/common/recipes-kernel/linux/linux-yocto-4.14.71/5045-drm-amd-display-Implement-custom-degamma-lut-on-dcn.patch @@ -0,0 +1,170 @@ +From bc975c0b7995414e3d70a9c1ffb4636debe233bd Mon Sep 17 00:00:00 2001 +From: David Francis <David.Francis@amd.com> +Date: Thu, 12 Jul 2018 15:46:41 -0400 +Subject: [PATCH 5045/5725] 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> +--- + .../drm/amd/display/amdgpu_dm/amdgpu_dm_color.c | 42 ++++++++++++++++------ + drivers/gpu/drm/amd/display/dc/dc_hw_types.h | 2 ++ + .../drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c | 7 ++-- + .../drm/amd/display/modules/color/color_gamma.c | 10 ++++-- + 4 files changed, 46 insertions(+), 15 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 b329393..326f6fb 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; + } + +diff --git a/drivers/gpu/drm/amd/display/dc/dc_hw_types.h b/drivers/gpu/drm/amd/display/dc/dc_hw_types.h +index bbc384f..57f57cf 100644 +--- a/drivers/gpu/drm/amd/display/dc/dc_hw_types.h ++++ b/drivers/gpu/drm/amd/display/dc/dc_hw_types.h +@@ -417,6 +417,7 @@ enum { + GAMMA_RGB_256_ENTRIES = 256, + GAMMA_RGB_FLOAT_1024_ENTRIES = 1024, + GAMMA_CS_TFM_1D_ENTRIES = 4096, ++ GAMMA_CUSTOM_ENTRIES = 4096, + GAMMA_MAX_ENTRIES = 4096 + }; + +@@ -424,6 +425,7 @@ enum dc_gamma_type { + GAMMA_RGB_256 = 1, + GAMMA_RGB_FLOAT_1024 = 2, + GAMMA_CS_TFM_1D = 3, ++ GAMMA_CUSTOM = 4, + }; + + struct dc_csc_transform { +diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c +index 8535d87..9604c13 100644 +--- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c ++++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c +@@ -1228,8 +1228,11 @@ static bool dcn10_set_input_transfer_func(struct pipe_ctx *pipe_ctx, + } else if (tf->type == TF_TYPE_BYPASS) { + dpp_base->funcs->dpp_set_degamma(dpp_base, IPP_DEGAMMA_MODE_BYPASS); + } else { +- /*TF_TYPE_DISTRIBUTED_POINTS*/ +- result = false; ++ cm_helper_translate_curve_to_degamma_hw_format(tf, ++ &dpp_base->degamma_params); ++ dpp_base->funcs->dpp_program_degamma_pwl(dpp_base, ++ &dpp_base->degamma_params); ++ result = true; + } + + return result; +diff --git a/drivers/gpu/drm/amd/display/modules/color/color_gamma.c b/drivers/gpu/drm/amd/display/modules/color/color_gamma.c +index fa9a199..4c67058 100644 +--- a/drivers/gpu/drm/amd/display/modules/color/color_gamma.c ++++ b/drivers/gpu/drm/amd/display/modules/color/color_gamma.c +@@ -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 + * 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( + const struct dc_gamma *ramp, +@@ -1018,7 +1020,7 @@ static void apply_lut_1d( + struct fixed31_32 delta_lut; + 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 + + for (i = 0; i < num_hw_points; i++) { +@@ -1629,7 +1631,9 @@ bool mod_color_calculate_degamma_params(struct dc_transfer_func *input_tf, + map_regamma_hw_to_x_user(ramp, coeff, rgb_user, + coordinates_x, axix_x, curve, + 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; + +-- +2.7.4 + |