diff options
Diffstat (limited to 'meta-amd-bsp/recipes-kernel/linux/linux-yocto-4.14.71/3576-drm-amd-display-De-PQ-implementation.patch')
-rw-r--r-- | meta-amd-bsp/recipes-kernel/linux/linux-yocto-4.14.71/3576-drm-amd-display-De-PQ-implementation.patch | 785 |
1 files changed, 785 insertions, 0 deletions
diff --git a/meta-amd-bsp/recipes-kernel/linux/linux-yocto-4.14.71/3576-drm-amd-display-De-PQ-implementation.patch b/meta-amd-bsp/recipes-kernel/linux/linux-yocto-4.14.71/3576-drm-amd-display-De-PQ-implementation.patch new file mode 100644 index 00000000..50388442 --- /dev/null +++ b/meta-amd-bsp/recipes-kernel/linux/linux-yocto-4.14.71/3576-drm-amd-display-De-PQ-implementation.patch @@ -0,0 +1,785 @@ +From 4d018e1fdb4780565deb120a8965551bcb923939 Mon Sep 17 00:00:00 2001 +From: Vitaly Prosyak <vitaly.prosyak@amd.com> +Date: Tue, 6 Feb 2018 15:06:23 -0600 +Subject: [PATCH 3576/4131] drm/amd/display: De PQ implementation + +Some refactoring and optimizations in color module. +Added de gamma 2.2 & 2.4, also re gamma 2.2. +Added interface for diagnostic for de gamma & de pq. + +Signed-off-by: Vitaly Prosyak <vitaly.prosyak@amd.com> +Reviewed-by: Krunoslav Kovac <Krunoslav.Kovac@amd.com> +Acked-by: Harry Wentland <harry.wentland@amd.com> +Signed-off-by: Alex Deucher <alexander.deucher@amd.com> +--- + .../gpu/drm/amd/display/dc/dcn10/dcn10_dpp_cm.c | 30 +- + .../drm/amd/display/modules/color/color_gamma.c | 479 +++++++++++++++++---- + .../drm/amd/display/modules/color/color_gamma.h | 8 + + 3 files changed, 442 insertions(+), 75 deletions(-) + +diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp_cm.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp_cm.c +index 2482390..bd3fcdf 100644 +--- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp_cm.c ++++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp_cm.c +@@ -298,6 +298,32 @@ static void dpp1_cm_get_reg_field( + reg->masks.exp_resion_start_segment = dpp->tf_mask->CM_RGAM_RAMB_EXP_REGION_START_SEGMENT_B; + } + ++static void dpp1_cm_get_degamma_reg_field( ++ struct dcn10_dpp *dpp, ++ struct xfer_func_reg *reg) ++{ ++ reg->shifts.exp_region0_lut_offset = dpp->tf_shift->CM_DGAM_RAMA_EXP_REGION0_LUT_OFFSET; ++ reg->masks.exp_region0_lut_offset = dpp->tf_mask->CM_DGAM_RAMA_EXP_REGION0_LUT_OFFSET; ++ reg->shifts.exp_region0_num_segments = dpp->tf_shift->CM_DGAM_RAMA_EXP_REGION0_NUM_SEGMENTS; ++ reg->masks.exp_region0_num_segments = dpp->tf_mask->CM_DGAM_RAMA_EXP_REGION0_NUM_SEGMENTS; ++ reg->shifts.exp_region1_lut_offset = dpp->tf_shift->CM_DGAM_RAMA_EXP_REGION1_LUT_OFFSET; ++ reg->masks.exp_region1_lut_offset = dpp->tf_mask->CM_DGAM_RAMA_EXP_REGION1_LUT_OFFSET; ++ reg->shifts.exp_region1_num_segments = dpp->tf_shift->CM_DGAM_RAMA_EXP_REGION1_NUM_SEGMENTS; ++ reg->masks.exp_region1_num_segments = dpp->tf_mask->CM_DGAM_RAMA_EXP_REGION1_NUM_SEGMENTS; ++ ++ reg->shifts.field_region_end = dpp->tf_shift->CM_DGAM_RAMB_EXP_REGION_END_B; ++ reg->masks.field_region_end = dpp->tf_mask->CM_DGAM_RAMB_EXP_REGION_END_B; ++ reg->shifts.field_region_end_slope = dpp->tf_shift->CM_DGAM_RAMB_EXP_REGION_END_SLOPE_B; ++ reg->masks.field_region_end_slope = dpp->tf_mask->CM_DGAM_RAMB_EXP_REGION_END_SLOPE_B; ++ reg->shifts.field_region_end_base = dpp->tf_shift->CM_DGAM_RAMB_EXP_REGION_END_BASE_B; ++ reg->masks.field_region_end_base = dpp->tf_mask->CM_DGAM_RAMB_EXP_REGION_END_BASE_B; ++ reg->shifts.field_region_linear_slope = dpp->tf_shift->CM_DGAM_RAMB_EXP_REGION_LINEAR_SLOPE_B; ++ reg->masks.field_region_linear_slope = dpp->tf_mask->CM_DGAM_RAMB_EXP_REGION_LINEAR_SLOPE_B; ++ reg->shifts.exp_region_start = dpp->tf_shift->CM_DGAM_RAMB_EXP_REGION_START_B; ++ reg->masks.exp_region_start = dpp->tf_mask->CM_DGAM_RAMB_EXP_REGION_START_B; ++ reg->shifts.exp_resion_start_segment = dpp->tf_shift->CM_DGAM_RAMB_EXP_REGION_START_SEGMENT_B; ++ reg->masks.exp_resion_start_segment = dpp->tf_mask->CM_DGAM_RAMB_EXP_REGION_START_SEGMENT_B; ++} + void dpp1_cm_set_output_csc_adjustment( + struct dpp *dpp_base, + const uint16_t *regval) +@@ -502,7 +528,7 @@ void dpp1_program_degamma_lutb_settings( + struct dcn10_dpp *dpp = TO_DCN10_DPP(dpp_base); + struct xfer_func_reg gam_regs; + +- dpp1_cm_get_reg_field(dpp, &gam_regs); ++ dpp1_cm_get_degamma_reg_field(dpp, &gam_regs); + + gam_regs.start_cntl_b = REG(CM_DGAM_RAMB_START_CNTL_B); + gam_regs.start_cntl_g = REG(CM_DGAM_RAMB_START_CNTL_G); +@@ -531,7 +557,7 @@ void dpp1_program_degamma_luta_settings( + struct dcn10_dpp *dpp = TO_DCN10_DPP(dpp_base); + struct xfer_func_reg gam_regs; + +- dpp1_cm_get_reg_field(dpp, &gam_regs); ++ dpp1_cm_get_degamma_reg_field(dpp, &gam_regs); + + gam_regs.start_cntl_b = REG(CM_DGAM_RAMA_START_CNTL_B); + gam_regs.start_cntl_g = REG(CM_DGAM_RAMA_START_CNTL_G); +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 fde3ae8..a5fd14a 100644 +--- a/drivers/gpu/drm/amd/display/modules/color/color_gamma.c ++++ b/drivers/gpu/drm/amd/display/modules/color/color_gamma.c +@@ -27,14 +27,21 @@ + #include "opp.h" + #include "color_gamma.h" + +-/* MAX_HW_POINTS = NUM_REGIONS * NUM_PTS_IN_REGION */ ++ + #define NUM_PTS_IN_REGION 16 + #define NUM_REGIONS 32 +-#define MAX_HW_POINTS 512 ++#define NUM_DEGAMMA_REGIONS 12 ++#define MAX_HW_POINTS (NUM_PTS_IN_REGION*NUM_REGIONS) ++#define MAX_HW_DEGAMMA_POINTS (NUM_PTS_IN_REGION*NUM_DEGAMMA_REGIONS) + + static struct hw_x_point coordinates_x[MAX_HW_POINTS + 2]; ++static struct hw_x_point degamma_coordinates_x[MAX_HW_DEGAMMA_POINTS + 2]; ++ + static struct fixed31_32 pq_table[MAX_HW_POINTS + 2]; ++static struct fixed31_32 de_pq_table[MAX_HW_DEGAMMA_POINTS + 2]; ++ + static bool pq_initialized; /* = false; */ ++static bool de_pq_initialized; /* = false; */ + + /* one-time setup of X points */ + void setup_x_points_distribution(void) +@@ -45,8 +52,8 @@ void setup_x_points_distribution(void) + uint32_t index; + struct fixed31_32 increment; + +- coordinates_x[NUM_REGIONS * NUM_PTS_IN_REGION].x = region_size; +- coordinates_x[NUM_REGIONS * NUM_PTS_IN_REGION + 1].x = region_size; ++ coordinates_x[MAX_HW_POINTS].x = region_size; ++ coordinates_x[MAX_HW_POINTS + 1].x = region_size; + + for (segment = 6; segment > (6 - NUM_REGIONS); segment--) { + region_size = dal_fixed31_32_div_int(region_size, 2); +@@ -62,6 +69,26 @@ void setup_x_points_distribution(void) + (coordinates_x[index-1].x, increment); + } + } ++ ++ region_size = dal_fixed31_32_from_int(1); ++ degamma_coordinates_x[MAX_HW_DEGAMMA_POINTS].x = region_size; ++ degamma_coordinates_x[MAX_HW_DEGAMMA_POINTS + 1].x = region_size; ++ ++ for (segment = -1; segment > -(NUM_DEGAMMA_REGIONS + 1); segment--) { ++ region_size = dal_fixed31_32_div_int(region_size, 2); ++ increment = dal_fixed31_32_div_int(region_size, ++ NUM_PTS_IN_REGION); ++ seg_offset = (segment + NUM_DEGAMMA_REGIONS) * NUM_PTS_IN_REGION; ++ degamma_coordinates_x[seg_offset].x = region_size; ++ ++ for (index = seg_offset + 1; ++ index < seg_offset + NUM_PTS_IN_REGION; ++ index++) { ++ degamma_coordinates_x[index].x = dal_fixed31_32_add ++ (degamma_coordinates_x[index-1].x, increment); ++ } ++ } ++ + } + + static void compute_pq(struct fixed31_32 in_x, struct fixed31_32 *out_y) +@@ -93,6 +120,40 @@ static void compute_pq(struct fixed31_32 in_x, struct fixed31_32 *out_y) + *out_y = dal_fixed31_32_pow(base, m2); + } + ++static void compute_de_pq(struct fixed31_32 in_x, struct fixed31_32 *out_y) ++{ ++ /* consts for dePQ gamma formula. */ ++ const struct fixed31_32 m1 = ++ dal_fixed31_32_from_fraction(159301758, 1000000000); ++ const struct fixed31_32 m2 = ++ dal_fixed31_32_from_fraction(7884375, 100000); ++ const struct fixed31_32 c1 = ++ dal_fixed31_32_from_fraction(8359375, 10000000); ++ const struct fixed31_32 c2 = ++ dal_fixed31_32_from_fraction(188515625, 10000000); ++ const struct fixed31_32 c3 = ++ dal_fixed31_32_from_fraction(186875, 10000); ++ ++ struct fixed31_32 l_pow_m1; ++ struct fixed31_32 base, div; ++ ++ ++ if (dal_fixed31_32_lt(in_x, dal_fixed31_32_zero)) ++ in_x = dal_fixed31_32_zero; ++ ++ l_pow_m1 = dal_fixed31_32_pow(in_x, ++ dal_fixed31_32_div(dal_fixed31_32_one, m2)); ++ base = dal_fixed31_32_sub(l_pow_m1, c1); ++ ++ if (dal_fixed31_32_lt(base, dal_fixed31_32_zero)) ++ base = dal_fixed31_32_zero; ++ ++ div = dal_fixed31_32_sub(c2, dal_fixed31_32_mul(c3, l_pow_m1)); ++ ++ *out_y = dal_fixed31_32_pow(dal_fixed31_32_div(base, div), ++ dal_fixed31_32_div(dal_fixed31_32_one, m1)); ++ ++} + /* one-time pre-compute PQ values - only for sdr_white_level 80 */ + void precompute_pq(void) + { +@@ -113,46 +174,49 @@ void precompute_pq(void) + } + } + ++/* one-time pre-compute dePQ values - only for max pixel value 125 FP16 */ ++void precompute_de_pq(void) ++{ ++ int i; ++ struct fixed31_32 y; ++ const struct hw_x_point *coord_x = degamma_coordinates_x; ++ struct fixed31_32 scaling_factor = dal_fixed31_32_from_int(125); ++ ++ ++ for (i = 0; i <= MAX_HW_DEGAMMA_POINTS; i++) { ++ compute_de_pq(coord_x->x, &y); ++ de_pq_table[i] = dal_fixed31_32_mul(y, scaling_factor); ++ ++coord_x; ++ } ++} + struct dividers { + struct fixed31_32 divider1; + struct fixed31_32 divider2; + struct fixed31_32 divider3; + }; + +-static void build_regamma_coefficients(struct gamma_coefficients *coefficients) ++static void build_coefficients(struct gamma_coefficients *coefficients, bool is_2_4) + { +- /* sRGB should apply 2.4 */ +- static const int32_t numerator01[3] = { 31308, 31308, 31308 }; +- static const int32_t numerator02[3] = { 12920, 12920, 12920 }; +- static const int32_t numerator03[3] = { 55, 55, 55 }; +- static const int32_t numerator04[3] = { 55, 55, 55 }; +- static const int32_t numerator05[3] = { 2400, 2400, 2400 }; +- +- const int32_t *numerator1; +- const int32_t *numerator2; +- const int32_t *numerator3; +- const int32_t *numerator4; +- const int32_t *numerator5; +- +- uint32_t i = 0; ++ static const int32_t numerator01[] = { 31308, 180000}; ++ static const int32_t numerator02[] = { 12920, 4500}; ++ static const int32_t numerator03[] = { 55, 99}; ++ static const int32_t numerator04[] = { 55, 99}; ++ static const int32_t numerator05[] = { 2400, 2200}; + +- numerator1 = numerator01; +- numerator2 = numerator02; +- numerator3 = numerator03; +- numerator4 = numerator04; +- numerator5 = numerator05; ++ uint32_t i = 0; ++ uint32_t index = is_2_4 == true ? 0:1; + + do { + coefficients->a0[i] = dal_fixed31_32_from_fraction( +- numerator1[i], 10000000); ++ numerator01[index], 10000000); + coefficients->a1[i] = dal_fixed31_32_from_fraction( +- numerator2[i], 1000); ++ numerator02[index], 1000); + coefficients->a2[i] = dal_fixed31_32_from_fraction( +- numerator3[i], 1000); ++ numerator03[index], 1000); + coefficients->a3[i] = dal_fixed31_32_from_fraction( +- numerator4[i], 1000); ++ numerator04[index], 1000); + coefficients->user_gamma[i] = dal_fixed31_32_from_fraction( +- numerator5[i], 1000); ++ numerator05[index], 1000); + + ++i; + } while (i != ARRAY_SIZE(coefficients->a0)); +@@ -197,6 +261,39 @@ static struct fixed31_32 translate_from_linear_space( + a1); + } + ++static struct fixed31_32 translate_to_linear_space( ++ struct fixed31_32 arg, ++ struct fixed31_32 a0, ++ struct fixed31_32 a1, ++ struct fixed31_32 a2, ++ struct fixed31_32 a3, ++ struct fixed31_32 gamma) ++{ ++ struct fixed31_32 linear; ++ ++ a0 = dal_fixed31_32_mul(a0, a1); ++ if (dal_fixed31_32_le(arg, dal_fixed31_32_neg(a0))) ++ ++ linear = dal_fixed31_32_neg( ++ dal_fixed31_32_pow( ++ dal_fixed31_32_div( ++ dal_fixed31_32_sub(a2, arg), ++ dal_fixed31_32_add( ++ dal_fixed31_32_one, a3)), gamma)); ++ ++ else if (dal_fixed31_32_le(dal_fixed31_32_neg(a0), arg) && ++ dal_fixed31_32_le(arg, a0)) ++ linear = dal_fixed31_32_div(arg, a1); ++ else ++ linear = dal_fixed31_32_pow( ++ dal_fixed31_32_div( ++ dal_fixed31_32_add(a2, arg), ++ dal_fixed31_32_add( ++ dal_fixed31_32_one, a3)), gamma); ++ ++ return linear; ++} ++ + static inline struct fixed31_32 translate_from_linear_space_ex( + struct fixed31_32 arg, + struct gamma_coefficients *coeff, +@@ -211,6 +308,22 @@ static inline struct fixed31_32 translate_from_linear_space_ex( + coeff->user_gamma[color_index]); + } + ++ ++static inline struct fixed31_32 translate_to_linear_space_ex( ++ struct fixed31_32 arg, ++ struct gamma_coefficients *coeff, ++ uint32_t color_index) ++{ ++ return translate_to_linear_space( ++ arg, ++ coeff->a0[color_index], ++ coeff->a1[color_index], ++ coeff->a2[color_index], ++ coeff->a3[color_index], ++ coeff->user_gamma[color_index]); ++} ++ ++ + static bool find_software_points( + const struct dc_gamma *ramp, + const struct gamma_pixel *axis_x, +@@ -314,12 +427,6 @@ static bool build_custom_gamma_mapping_coefficients_worker( + struct fixed31_32 left_pos; + struct fixed31_32 right_pos; + +- /* +- * TODO: confirm enum in surface_pixel_format +- * if (pixel_format == PIXEL_FORMAT_FP16) +- *coord_x = coordinates_x[i].adjusted_x; +- *else +- */ + if (channel == CHANNEL_NAME_RED) + coord_x = coordinates_x[i].regamma_y_red; + else if (channel == CHANNEL_NAME_GREEN) +@@ -451,7 +558,7 @@ static struct fixed31_32 calculate_mapped_value( + return result; + } + +-static void build_regamma_curve_pq(struct pwl_float_data_ex *rgb_regamma, ++static void build_pq(struct pwl_float_data_ex *rgb_regamma, + uint32_t hw_points_num, + const struct hw_x_point *coordinate_x, + uint32_t sdr_white_level) +@@ -477,11 +584,6 @@ static void build_regamma_curve_pq(struct pwl_float_data_ex *rgb_regamma, + rgb += start_index; + coord_x += start_index; + +- /* use coord_x to retrieve coordinates chosen base on given user curve +- * the x values are exponentially distributed and currently it is hard +- * coded, the user curve shape is ignored. Need to recalculate coord_x +- * based on input curve, translation from 256/1025 to 128 PWL points. +- */ + for (i = start_index; i <= hw_points_num; i++) { + /* Multiply 0.008 as regamma is 0-1 and FP16 input is 0-125. + * FP 1.0 = 80nits +@@ -508,37 +610,86 @@ static void build_regamma_curve_pq(struct pwl_float_data_ex *rgb_regamma, + } + } + +-static void build_regamma_curve(struct pwl_float_data_ex *rgb_regamma, ++static void build_de_pq(struct pwl_float_data_ex *de_pq, + uint32_t hw_points_num, + const struct hw_x_point *coordinate_x) + { + uint32_t i; ++ struct fixed31_32 output; ++ ++ struct pwl_float_data_ex *rgb = de_pq; ++ const struct hw_x_point *coord_x = degamma_coordinates_x; ++ struct fixed31_32 scaling_factor = dal_fixed31_32_from_int(125); ++ ++ if (!de_pq_initialized) { ++ precompute_de_pq(); ++ de_pq_initialized = true; ++ } ++ ++ ++ for (i = 0; i <= hw_points_num; i++) { ++ output = de_pq_table[i]; ++ /* should really not happen? */ ++ if (dal_fixed31_32_lt(output, dal_fixed31_32_zero)) ++ output = dal_fixed31_32_zero; ++ else if (dal_fixed31_32_lt(scaling_factor, output)) ++ output = scaling_factor; ++ ++ rgb->r = output; ++ rgb->g = output; ++ rgb->b = output; ++ ++ ++coord_x; ++ ++rgb; ++ } ++} ++ ++static void build_regamma(struct pwl_float_data_ex *rgb_regamma, ++ uint32_t hw_points_num, ++ const struct hw_x_point *coordinate_x, bool is_2_4) ++{ ++ uint32_t i; + + struct gamma_coefficients coeff; + struct pwl_float_data_ex *rgb = rgb_regamma; + const struct hw_x_point *coord_x = coordinate_x; + +- build_regamma_coefficients(&coeff); +- +- /* Use opp110->regamma.coordinates_x to retrieve +- * coordinates chosen base on given user curve (future task). +- * The x values are exponentially distributed and currently +- * it is hard-coded, the user curve shape is ignored. +- * The future task is to recalculate opp110- +- * regamma.coordinates_x based on input/user curve, +- * translation from 256/1025 to 128 pwl points. +- */ ++ build_coefficients(&coeff, is_2_4); + + i = 0; + + while (i != hw_points_num + 1) { ++ /*TODO use y vs r,g,b*/ + rgb->r = translate_from_linear_space_ex( + coord_x->x, &coeff, 0); +- rgb->g = translate_from_linear_space_ex( +- coord_x->x, &coeff, 1); +- rgb->b = translate_from_linear_space_ex( +- coord_x->x, &coeff, 2); ++ rgb->g = rgb->r; ++ rgb->b = rgb->r; ++ ++coord_x; ++ ++rgb; ++ ++i; ++ } ++} ++ ++static void build_degamma(struct pwl_float_data_ex *curve, ++ uint32_t hw_points_num, ++ const struct hw_x_point *coordinate_x, bool is_2_4) ++{ ++ uint32_t i; + ++ struct gamma_coefficients coeff; ++ struct pwl_float_data_ex *rgb = curve; ++ const struct hw_x_point *coord_x = degamma_coordinates_x; ++ ++ build_coefficients(&coeff, is_2_4); ++ ++ i = 0; ++ ++ while (i != hw_points_num + 1) { ++ /*TODO use y vs r,g,b*/ ++ rgb->r = translate_to_linear_space_ex( ++ coord_x->x, &coeff, 0); ++ rgb->g = rgb->r; ++ rgb->b = rgb->r; + ++coord_x; + ++rgb; + ++i; +@@ -921,6 +1072,8 @@ static bool map_regamma_hw_to_x_user( + return true; + } + ++#define _EXTRA_POINTS 3 ++ + bool mod_color_calculate_regamma_params(struct dc_transfer_func *output_tf, + const struct dc_gamma *ramp, bool mapUserRamp) + { +@@ -930,7 +1083,7 @@ bool mod_color_calculate_regamma_params(struct dc_transfer_func *output_tf, + struct pwl_float_data *rgb_user = NULL; + struct pwl_float_data_ex *rgb_regamma = NULL; + struct gamma_pixel *axix_x = NULL; +- struct pixel_gamma_point *coeff128 = NULL; ++ struct pixel_gamma_point *coeff = NULL; + enum dc_transfer_func_predefined tf = TRANSFER_FUNCTION_SRGB; + bool ret = false; + +@@ -945,11 +1098,11 @@ bool mod_color_calculate_regamma_params(struct dc_transfer_func *output_tf, + + output_tf->type = TF_TYPE_DISTRIBUTED_POINTS; + +- rgb_user = kzalloc(sizeof(*rgb_user) * (ramp->num_entries + 3), ++ rgb_user = kzalloc(sizeof(*rgb_user) * (ramp->num_entries + _EXTRA_POINTS), + GFP_KERNEL); + if (!rgb_user) + goto rgb_user_alloc_fail; +- rgb_regamma = kzalloc(sizeof(*rgb_regamma) * (MAX_HW_POINTS + 3), ++ rgb_regamma = kzalloc(sizeof(*rgb_regamma) * (MAX_HW_POINTS + _EXTRA_POINTS), + GFP_KERNEL); + if (!rgb_regamma) + goto rgb_regamma_alloc_fail; +@@ -957,9 +1110,9 @@ bool mod_color_calculate_regamma_params(struct dc_transfer_func *output_tf, + GFP_KERNEL); + if (!axix_x) + goto axix_x_alloc_fail; +- coeff128 = kzalloc(sizeof(*coeff128) * (MAX_HW_POINTS + 3), GFP_KERNEL); +- if (!coeff128) +- goto coeff128_alloc_fail; ++ coeff = kzalloc(sizeof(*coeff) * (MAX_HW_POINTS + _EXTRA_POINTS), GFP_KERNEL); ++ if (!coeff) ++ goto coeff_alloc_fail; + + dividers.divider1 = dal_fixed31_32_from_fraction(3, 2); + dividers.divider2 = dal_fixed31_32_from_int(2); +@@ -983,7 +1136,7 @@ bool mod_color_calculate_regamma_params(struct dc_transfer_func *output_tf, + tf_pts->x_point_at_y1_green = 125; + tf_pts->x_point_at_y1_blue = 125; + +- build_regamma_curve_pq(rgb_regamma, ++ build_pq(rgb_regamma, + MAX_HW_POINTS, + coordinates_x, + output_tf->sdr_ref_white_level); +@@ -993,12 +1146,12 @@ bool mod_color_calculate_regamma_params(struct dc_transfer_func *output_tf, + tf_pts->x_point_at_y1_green = 1; + tf_pts->x_point_at_y1_blue = 1; + +- build_regamma_curve(rgb_regamma, ++ build_regamma(rgb_regamma, + MAX_HW_POINTS, +- coordinates_x); ++ coordinates_x, tf == TRANSFER_FUNCTION_SRGB ? true:false); + } + +- map_regamma_hw_to_x_user(ramp, coeff128, rgb_user, ++ map_regamma_hw_to_x_user(ramp, coeff, rgb_user, + coordinates_x, axix_x, rgb_regamma, + MAX_HW_POINTS, tf_pts, + (mapUserRamp || ramp->type != GAMMA_RGB_256) && +@@ -1009,8 +1162,8 @@ bool mod_color_calculate_regamma_params(struct dc_transfer_func *output_tf, + + ret = true; + +- kfree(coeff128); +-coeff128_alloc_fail: ++ kfree(coeff); ++coeff_alloc_fail: + kfree(axix_x); + axix_x_alloc_fail: + kfree(rgb_regamma); +@@ -1024,6 +1177,98 @@ bool mod_color_calculate_regamma_params(struct dc_transfer_func *output_tf, + /*TODO fix me should be 2*/ + #define _EXTRA_POINTS 3 + ++bool mod_color_calculate_degamma_params(struct dc_transfer_func *input_tf, ++ const struct dc_gamma *ramp, bool mapUserRamp) ++{ ++ struct dc_transfer_func_distributed_points *tf_pts = &input_tf->tf_pts; ++ struct dividers dividers; ++ ++ struct pwl_float_data *rgb_user = NULL; ++ struct pwl_float_data_ex *curve = NULL; ++ struct gamma_pixel *axix_x = NULL; ++ struct pixel_gamma_point *coeff = NULL; ++ enum dc_transfer_func_predefined tf = TRANSFER_FUNCTION_SRGB; ++ bool ret = false; ++ ++ if (input_tf->type == TF_TYPE_BYPASS) ++ return false; ++ ++ /* we can use hardcoded curve for plain SRGB TF */ ++ if (input_tf->type == TF_TYPE_PREDEFINED && ++ input_tf->tf == TRANSFER_FUNCTION_SRGB && ++ (!mapUserRamp && ramp->type == GAMMA_RGB_256)) ++ return true; ++ ++ input_tf->type = TF_TYPE_DISTRIBUTED_POINTS; ++ ++ rgb_user = kzalloc(sizeof(*rgb_user) * (ramp->num_entries + _EXTRA_POINTS), ++ GFP_KERNEL); ++ if (!rgb_user) ++ goto rgb_user_alloc_fail; ++ curve = kzalloc(sizeof(*curve) * (MAX_HW_DEGAMMA_POINTS + _EXTRA_POINTS), ++ GFP_KERNEL); ++ if (!curve) ++ goto curve_alloc_fail; ++ axix_x = kzalloc(sizeof(*axix_x) * (ramp->num_entries + _EXTRA_POINTS), ++ GFP_KERNEL); ++ if (!axix_x) ++ goto axix_x_alloc_fail; ++ coeff = kzalloc(sizeof(*coeff) * (MAX_HW_DEGAMMA_POINTS + _EXTRA_POINTS), GFP_KERNEL); ++ if (!coeff) ++ goto coeff_alloc_fail; ++ ++ dividers.divider1 = dal_fixed31_32_from_fraction(3, 2); ++ dividers.divider2 = dal_fixed31_32_from_int(2); ++ dividers.divider3 = dal_fixed31_32_from_fraction(5, 2); ++ ++ tf = input_tf->tf; ++ ++ build_evenly_distributed_points( ++ axix_x, ++ ramp->num_entries, ++ dividers); ++ ++ if (ramp->type == GAMMA_RGB_256 && mapUserRamp) ++ scale_gamma(rgb_user, ramp, dividers); ++ else if (ramp->type == GAMMA_RGB_FLOAT_1024) ++ scale_gamma_dx(rgb_user, ramp, dividers); ++ ++ if (tf == TRANSFER_FUNCTION_PQ) ++ build_de_pq(curve, ++ MAX_HW_DEGAMMA_POINTS, ++ degamma_coordinates_x); ++ else ++ build_degamma(curve, ++ MAX_HW_DEGAMMA_POINTS, ++ degamma_coordinates_x, ++ tf == TRANSFER_FUNCTION_SRGB ? true:false); ++ ++ tf_pts->end_exponent = 0; ++ tf_pts->x_point_at_y1_red = 1; ++ tf_pts->x_point_at_y1_green = 1; ++ tf_pts->x_point_at_y1_blue = 1; ++ ++ map_regamma_hw_to_x_user(ramp, coeff, rgb_user, ++ degamma_coordinates_x, axix_x, curve, ++ MAX_HW_DEGAMMA_POINTS, tf_pts, ++ mapUserRamp); ++ ++ ret = true; ++ ++ kfree(coeff); ++coeff_alloc_fail: ++ kfree(axix_x); ++axix_x_alloc_fail: ++ kfree(curve); ++curve_alloc_fail: ++ kfree(rgb_user); ++rgb_user_alloc_fail: ++ ++ return ret; ++ ++} ++ ++ + bool mod_color_calculate_curve(enum dc_transfer_func_predefined trans, + struct dc_transfer_func_distributed_points *points) + { +@@ -1032,7 +1277,11 @@ bool mod_color_calculate_curve(enum dc_transfer_func_predefined trans, + struct pwl_float_data_ex *rgb_regamma = NULL; + + if (trans == TRANSFER_FUNCTION_UNITY) { +- //setup_x_points_distribution(coordinates_x); ++ points->end_exponent = 0; ++ points->x_point_at_y1_red = 1; ++ points->x_point_at_y1_green = 1; ++ points->x_point_at_y1_blue = 1; ++ + for (i = 0; i < MAX_HW_POINTS ; i++) { + points->red[i] = coordinates_x[i].x; + points->green[i] = coordinates_x[i].x; +@@ -1044,16 +1293,38 @@ bool mod_color_calculate_curve(enum dc_transfer_func_predefined trans, + _EXTRA_POINTS), GFP_KERNEL); + if (!rgb_regamma) + goto rgb_regamma_alloc_fail; +- //setup_x_points_distribution(coordinates_x); ++ points->end_exponent = 7; ++ points->x_point_at_y1_red = 125; ++ points->x_point_at_y1_green = 125; ++ points->x_point_at_y1_blue = 125; ++ ++ ++ build_pq(rgb_regamma, ++ MAX_HW_POINTS, ++ coordinates_x, ++ 80); ++ for (i = 0; i < MAX_HW_POINTS ; i++) { ++ points->red[i] = rgb_regamma[i].r; ++ points->green[i] = rgb_regamma[i].g; ++ points->blue[i] = rgb_regamma[i].b; ++ } ++ ret = true; ++ ++ kfree(rgb_regamma); ++ } else if (trans == TRANSFER_FUNCTION_SRGB || ++ trans == TRANSFER_FUNCTION_BT709) { ++ rgb_regamma = kzalloc(sizeof(*rgb_regamma) * (MAX_HW_POINTS + ++ _EXTRA_POINTS), GFP_KERNEL); ++ if (!rgb_regamma) ++ goto rgb_regamma_alloc_fail; + points->end_exponent = 0; + points->x_point_at_y1_red = 1; + points->x_point_at_y1_green = 1; + points->x_point_at_y1_blue = 1; + +- build_regamma_curve_pq(rgb_regamma, ++ build_regamma(rgb_regamma, + MAX_HW_POINTS, +- coordinates_x, +- 80); ++ coordinates_x, trans == TRANSFER_FUNCTION_SRGB ? true:false); + for (i = 0; i < MAX_HW_POINTS ; i++) { + points->red[i] = rgb_regamma[i].r; + points->green[i] = rgb_regamma[i].g; +@@ -1068,3 +1339,65 @@ bool mod_color_calculate_curve(enum dc_transfer_func_predefined trans, + } + + ++bool mod_color_calculate_degamma_curve(enum dc_transfer_func_predefined trans, ++ struct dc_transfer_func_distributed_points *points) ++{ ++ uint32_t i; ++ bool ret = false; ++ struct pwl_float_data_ex *rgb_degamma = NULL; ++ ++ if (trans == TRANSFER_FUNCTION_UNITY) { ++ ++ for (i = 0; i < MAX_HW_DEGAMMA_POINTS ; i++) { ++ points->red[i] = degamma_coordinates_x[i].x; ++ points->green[i] = degamma_coordinates_x[i].x; ++ points->blue[i] = degamma_coordinates_x[i].x; ++ } ++ ret = true; ++ } else if (trans == TRANSFER_FUNCTION_PQ) { ++ rgb_degamma = kzalloc(sizeof(*rgb_degamma) * (MAX_HW_DEGAMMA_POINTS + ++ _EXTRA_POINTS), GFP_KERNEL); ++ if (!rgb_degamma) ++ goto rgb_degamma_alloc_fail; ++ ++ ++ build_de_pq(rgb_degamma, ++ MAX_HW_DEGAMMA_POINTS, ++ degamma_coordinates_x); ++ for (i = 0; i < MAX_HW_DEGAMMA_POINTS ; i++) { ++ points->red[i] = rgb_degamma[i].r; ++ points->green[i] = rgb_degamma[i].g; ++ points->blue[i] = rgb_degamma[i].b; ++ } ++ ret = true; ++ ++ kfree(rgb_degamma); ++ } else if (trans == TRANSFER_FUNCTION_SRGB || ++ trans == TRANSFER_FUNCTION_BT709) { ++ rgb_degamma = kzalloc(sizeof(*rgb_degamma) * (MAX_HW_DEGAMMA_POINTS + ++ _EXTRA_POINTS), GFP_KERNEL); ++ if (!rgb_degamma) ++ goto rgb_degamma_alloc_fail; ++ ++ build_degamma(rgb_degamma, ++ MAX_HW_DEGAMMA_POINTS, ++ degamma_coordinates_x, trans == TRANSFER_FUNCTION_SRGB ? true:false); ++ for (i = 0; i < MAX_HW_DEGAMMA_POINTS ; i++) { ++ points->red[i] = rgb_degamma[i].r; ++ points->green[i] = rgb_degamma[i].g; ++ points->blue[i] = rgb_degamma[i].b; ++ } ++ ret = true; ++ ++ kfree(rgb_degamma); ++ } ++ points->end_exponent = 0; ++ points->x_point_at_y1_red = 1; ++ points->x_point_at_y1_green = 1; ++ points->x_point_at_y1_blue = 1; ++ ++rgb_degamma_alloc_fail: ++ return ret; ++} ++ ++ +diff --git a/drivers/gpu/drm/amd/display/modules/color/color_gamma.h b/drivers/gpu/drm/amd/display/modules/color/color_gamma.h +index 774c6da..b7f9bc2 100644 +--- a/drivers/gpu/drm/amd/display/modules/color/color_gamma.h ++++ b/drivers/gpu/drm/amd/display/modules/color/color_gamma.h +@@ -34,12 +34,20 @@ enum dc_transfer_func_predefined; + + void setup_x_points_distribution(void); + void precompute_pq(void); ++void precompute_de_pq(void); + + bool mod_color_calculate_regamma_params(struct dc_transfer_func *output_tf, + const struct dc_gamma *ramp, bool mapUserRamp); + ++bool mod_color_calculate_degamma_params(struct dc_transfer_func *output_tf, ++ const struct dc_gamma *ramp, bool mapUserRamp); ++ + bool mod_color_calculate_curve(enum dc_transfer_func_predefined trans, + struct dc_transfer_func_distributed_points *points); + ++bool mod_color_calculate_degamma_curve(enum dc_transfer_func_predefined trans, ++ struct dc_transfer_func_distributed_points *points); ++ ++ + + #endif /* COLOR_MOD_COLOR_GAMMA_H_ */ +-- +2.7.4 + |