aboutsummaryrefslogtreecommitdiffstats
path: root/common/recipes-kernel/linux/linux-yocto-4.14.71/5045-drm-amd-display-Implement-custom-degamma-lut-on-dcn.patch
diff options
context:
space:
mode:
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.patch170
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
+