diff options
Diffstat (limited to 'common/recipes-kernel/linux/files/0784-drm-amd-dal-Refactor-opp-gamma-related.patch')
-rw-r--r-- | common/recipes-kernel/linux/files/0784-drm-amd-dal-Refactor-opp-gamma-related.patch | 5401 |
1 files changed, 5401 insertions, 0 deletions
diff --git a/common/recipes-kernel/linux/files/0784-drm-amd-dal-Refactor-opp-gamma-related.patch b/common/recipes-kernel/linux/files/0784-drm-amd-dal-Refactor-opp-gamma-related.patch new file mode 100644 index 00000000..7de664f1 --- /dev/null +++ b/common/recipes-kernel/linux/files/0784-drm-amd-dal-Refactor-opp-gamma-related.patch @@ -0,0 +1,5401 @@ +From f250ee01f34b61d29f2e8ffd841555fe716f1fb8 Mon Sep 17 00:00:00 2001 +From: Yongqiang Sun <yongqiang.sun@amd.com> +Date: Thu, 4 Feb 2016 10:42:38 -0500 +Subject: [PATCH 0784/1110] drm/amd/dal: Refactor opp gamma related. + +Signed-off-by: Yongqiang Sun <yongqiang.sun@amd.com> +Acked-by: Jordan Lazare <Jordan.Lazare@amd.com> +--- + .../gpu/drm/amd/dal/amdgpu_dm/amdgpu_dm_types.c | 10 +- + drivers/gpu/drm/amd/dal/dc/calcs/Makefile | 2 +- + drivers/gpu/drm/amd/dal/dc/calcs/gamma_calcs.c | 1342 +++++++++++++ + drivers/gpu/drm/amd/dal/dc/core/dc_surface.c | 80 +- + drivers/gpu/drm/amd/dal/dc/core/dc_target.c | 77 +- + drivers/gpu/drm/amd/dal/dc/dc.h | 43 +- + drivers/gpu/drm/amd/dal/dc/dc_types.h | 73 - + .../drm/amd/dal/dc/dce110/dce110_hw_sequencer.c | 98 +- + .../drm/amd/dal/dc/dce110/dce110_hw_sequencer.h | 1 + + drivers/gpu/drm/amd/dal/dc/dce110/dce110_ipp.c | 3 - + drivers/gpu/drm/amd/dal/dc/dce110/dce110_ipp.h | 23 +- + .../gpu/drm/amd/dal/dc/dce110/dce110_ipp_gamma.c | 639 +------ + drivers/gpu/drm/amd/dal/dc/dce110/dce110_opp.c | 196 -- + drivers/gpu/drm/amd/dal/dc/dce110/dce110_opp.h | 13 +- + .../gpu/drm/amd/dal/dc/dce110/dce110_opp_regamma.c | 2019 +------------------- + drivers/gpu/drm/amd/dal/dc/dce110/dce110_types.h | 58 + + drivers/gpu/drm/amd/dal/dc/inc/core_types.h | 9 + + drivers/gpu/drm/amd/dal/dc/inc/gamma_calcs.h | 31 + + drivers/gpu/drm/amd/dal/dc/inc/gamma_types.h | 48 - + drivers/gpu/drm/amd/dal/dc/inc/hw_sequencer.h | 6 +- + drivers/gpu/drm/amd/dal/dc/inc/ipp.h | 33 +- + drivers/gpu/drm/amd/dal/dc/inc/opp.h | 17 +- + drivers/gpu/drm/amd/dal/include/video_csc_types.h | 1 - + .../gpu/drm/amd/dal/include/video_gamma_types.h | 1 - + 24 files changed, 1790 insertions(+), 3033 deletions(-) + create mode 100644 drivers/gpu/drm/amd/dal/dc/calcs/gamma_calcs.c + create mode 100644 drivers/gpu/drm/amd/dal/dc/dce110/dce110_types.h + create mode 100644 drivers/gpu/drm/amd/dal/dc/inc/gamma_calcs.h + +diff --git a/drivers/gpu/drm/amd/dal/amdgpu_dm/amdgpu_dm_types.c b/drivers/gpu/drm/amd/dal/amdgpu_dm/amdgpu_dm_types.c +index 3f80880..2cb445d 100644 +--- a/drivers/gpu/drm/amd/dal/amdgpu_dm/amdgpu_dm_types.c ++++ b/drivers/gpu/drm/amd/dal/amdgpu_dm/amdgpu_dm_types.c +@@ -499,16 +499,20 @@ static void fill_gamma_from_crtc( + struct dc_surface *dc_surface) + { + int i; +- struct gamma_ramp *gamma; ++ struct dc_gamma *gamma; + uint16_t *red, *green, *blue; + int end = (crtc->gamma_size > NUM_OF_RAW_GAMMA_RAMP_RGB_256) ? + NUM_OF_RAW_GAMMA_RAMP_RGB_256 : crtc->gamma_size; ++ struct amdgpu_device *adev = crtc->dev->dev_private; + + red = crtc->gamma_store; + green = red + crtc->gamma_size; + blue = green + crtc->gamma_size; + +- gamma = &dc_surface->gamma_correction; ++ gamma = dc_create_gamma(adev->dm.dc); ++ ++ if (gamma == NULL) ++ return; + + for (i = 0; i < end; i++) { + gamma->gamma_ramp_rgb256x3x16.red[i] = +@@ -521,6 +525,8 @@ static void fill_gamma_from_crtc( + + gamma->type = GAMMA_RAMP_RBG256X3X16; + gamma->size = sizeof(gamma->gamma_ramp_rgb256x3x16); ++ ++ dc_surface->gamma_correction = gamma; + } + + static void fill_plane_attributes( +diff --git a/drivers/gpu/drm/amd/dal/dc/calcs/Makefile b/drivers/gpu/drm/amd/dal/dc/calcs/Makefile +index 7f1916b..9ac4ad1 100644 +--- a/drivers/gpu/drm/amd/dal/dc/calcs/Makefile ++++ b/drivers/gpu/drm/amd/dal/dc/calcs/Makefile +@@ -3,7 +3,7 @@ + # It calculates Bandwidth and Watermarks values for HW programming + # + +-BW_CALCS = bandwidth_calcs.o bw_fixed.o scaler_filter.o ++BW_CALCS = bandwidth_calcs.o bw_fixed.o scaler_filter.o gamma_calcs.o + + AMD_DAL_BW_CALCS = $(addprefix $(AMDDALPATH)/dc/calcs/,$(BW_CALCS)) + +diff --git a/drivers/gpu/drm/amd/dal/dc/calcs/gamma_calcs.c b/drivers/gpu/drm/amd/dal/dc/calcs/gamma_calcs.c +new file mode 100644 +index 0000000..e3a41b3 +--- /dev/null ++++ b/drivers/gpu/drm/amd/dal/dc/calcs/gamma_calcs.c +@@ -0,0 +1,1342 @@ ++/* ++ * Copyright 2015 Advanced Micro Devices, Inc. ++ * ++ * Permission is hereby granted, free of charge, to any person obtaining a ++ * copy of this software and associated documentation files (the "Software"), ++ * to deal in the Software without restriction, including without limitation ++ * the rights to use, copy, modify, merge, publish, distribute, sublicense, ++ * and/or sell copies of the Software, and to permit persons to whom the ++ * Software is furnished to do so, subject to the following conditions: ++ * ++ * The above copyright notice and this permission notice shall be included in ++ * all copies or substantial portions of the Software. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR ++ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, ++ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL ++ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR ++ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ++ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR ++ * OTHER DEALINGS IN THE SOFTWARE. ++ * ++ * Authors: AMD ++ * ++ */ ++ ++#include "dm_services.h" ++#include "gamma_calcs.h" ++#include "core_types.h" ++ ++struct curve_config { ++ uint32_t offset; ++ int8_t segments[16]; ++ int8_t begin; ++}; ++ ++static bool build_custom_float( ++ struct fixed31_32 value, ++ const struct custom_float_format *format, ++ bool *negative, ++ uint32_t *mantissa, ++ uint32_t *exponenta) ++{ ++ uint32_t exp_offset = (1 << (format->exponenta_bits - 1)) - 1; ++ ++ const struct fixed31_32 mantissa_constant_plus_max_fraction = ++ dal_fixed31_32_from_fraction( ++ (1LL << (format->mantissa_bits + 1)) - 1, ++ 1LL << format->mantissa_bits); ++ ++ struct fixed31_32 mantiss; ++ ++ if (dal_fixed31_32_eq( ++ value, ++ dal_fixed31_32_zero)) { ++ *negative = false; ++ *mantissa = 0; ++ *exponenta = 0; ++ return true; ++ } ++ ++ if (dal_fixed31_32_lt( ++ value, ++ dal_fixed31_32_zero)) { ++ *negative = format->sign; ++ value = dal_fixed31_32_neg(value); ++ } else { ++ *negative = false; ++ } ++ ++ if (dal_fixed31_32_lt( ++ value, ++ dal_fixed31_32_one)) { ++ uint32_t i = 1; ++ ++ do { ++ value = dal_fixed31_32_shl(value, 1); ++ ++i; ++ } while (dal_fixed31_32_lt( ++ value, ++ dal_fixed31_32_one)); ++ ++ --i; ++ ++ if (exp_offset <= i) { ++ *mantissa = 0; ++ *exponenta = 0; ++ return true; ++ } ++ ++ *exponenta = exp_offset - i; ++ } else if (dal_fixed31_32_le( ++ mantissa_constant_plus_max_fraction, ++ value)) { ++ uint32_t i = 1; ++ ++ do { ++ value = dal_fixed31_32_shr(value, 1); ++ ++i; ++ } while (dal_fixed31_32_lt( ++ mantissa_constant_plus_max_fraction, ++ value)); ++ ++ *exponenta = exp_offset + i - 1; ++ } else { ++ *exponenta = exp_offset; ++ } ++ ++ mantiss = dal_fixed31_32_sub( ++ value, ++ dal_fixed31_32_one); ++ ++ if (dal_fixed31_32_lt( ++ mantiss, ++ dal_fixed31_32_zero) || ++ dal_fixed31_32_lt( ++ dal_fixed31_32_one, ++ mantiss)) ++ mantiss = dal_fixed31_32_zero; ++ else ++ mantiss = dal_fixed31_32_shl( ++ mantiss, ++ format->mantissa_bits); ++ ++ *mantissa = dal_fixed31_32_floor(mantiss); ++ ++ return true; ++} ++ ++static bool setup_custom_float( ++ const struct custom_float_format *format, ++ bool negative, ++ uint32_t mantissa, ++ uint32_t exponenta, ++ uint32_t *result) ++{ ++ uint32_t i = 0; ++ uint32_t j = 0; ++ ++ uint32_t value = 0; ++ ++ /* verification code: ++ * once calculation is ok we can remove it ++ */ ++ ++ const uint32_t mantissa_mask = ++ (1 << (format->mantissa_bits + 1)) - 1; ++ ++ const uint32_t exponenta_mask = ++ (1 << (format->exponenta_bits + 1)) - 1; ++ ++ if (mantissa & ~mantissa_mask) { ++ BREAK_TO_DEBUGGER(); ++ mantissa = mantissa_mask; ++ } ++ ++ if (exponenta & ~exponenta_mask) { ++ BREAK_TO_DEBUGGER(); ++ exponenta = exponenta_mask; ++ } ++ ++ /* end of verification code */ ++ ++ while (i < format->mantissa_bits) { ++ uint32_t mask = 1 << i; ++ ++ if (mantissa & mask) ++ value |= mask; ++ ++ ++i; ++ } ++ ++ while (j < format->exponenta_bits) { ++ uint32_t mask = 1 << j; ++ ++ if (exponenta & mask) ++ value |= mask << i; ++ ++ ++j; ++ } ++ ++ if (negative && format->sign) ++ value |= 1 << (i + j); ++ ++ *result = value; ++ ++ return true; ++} ++ ++ ++static bool convert_to_custom_float_format_ex( ++ struct fixed31_32 value, ++ const struct custom_float_format *format, ++ struct custom_float_value *result) ++{ ++ return build_custom_float( ++ value, format, ++ &result->negative, &result->mantissa, &result->exponenta) && ++ setup_custom_float( ++ format, result->negative, result->mantissa, result->exponenta, ++ &result->value); ++} ++ ++static bool round_custom_float_6_12( ++ struct hw_x_point *x) ++{ ++ struct custom_float_format fmt; ++ ++ struct custom_float_value value; ++ ++ fmt.exponenta_bits = 6; ++ fmt.mantissa_bits = 12; ++ fmt.sign = true; ++ ++ if (!convert_to_custom_float_format_ex( ++ x->x, &fmt, &value)) ++ return false; ++ ++ x->adjusted_x = x->x; ++ ++ if (value.mantissa) { ++ BREAK_TO_DEBUGGER(); ++ ++ return false; ++ } ++ ++ return true; ++} ++ ++static bool build_hw_curve_configuration( ++ const struct curve_config *curve_config, ++ struct gamma_curve *gamma_curve, ++ struct curve_points *curve_points, ++ struct hw_x_point *points, ++ uint32_t *number_of_points) ++{ ++ const int8_t max_regions_number = ARRAY_SIZE(curve_config->segments); ++ ++ int8_t i; ++ ++ uint8_t segments_calculation[8] = { 0 }; ++ ++ struct fixed31_32 region1 = dal_fixed31_32_zero; ++ struct fixed31_32 region2; ++ struct fixed31_32 increment; ++ ++ uint32_t index = 0; ++ uint32_t segments = 0; ++ uint32_t max_number; ++ ++ bool result = false; ++ ++ if (!number_of_points) { ++ BREAK_TO_DEBUGGER(); ++ return false; ++ } ++ ++ max_number = *number_of_points; ++ ++ i = 0; ++ ++ while (i != max_regions_number) { ++ gamma_curve[i].offset = 0; ++ gamma_curve[i].segments_num = 0; ++ ++ ++i; ++ } ++ ++ i = 0; ++ ++ while (i != max_regions_number) { ++ /* number should go in uninterruptible sequence */ ++ if (curve_config->segments[i] == -1) ++ break; ++ ++ ASSERT(curve_config->segments[i] >= 0); ++ ++ segments += (1 << curve_config->segments[i]); ++ ++ ++i; ++ } ++ ++ if (segments > max_number) { ++ BREAK_TO_DEBUGGER(); ++ } else { ++ int32_t divisor; ++ uint32_t offset = 0; ++ int8_t begin = curve_config->begin; ++ int32_t region_number = 0; ++ ++ i = begin; ++ ++ while ((index < max_number) && ++ (region_number < max_regions_number) && ++ (i <= 1)) { ++ int32_t j = 0; ++ ++ segments = curve_config->segments[region_number]; ++ divisor = 1 << segments; ++ ++ if (segments == -1) { ++ if (i > 0) { ++ region1 = dal_fixed31_32_shl( ++ dal_fixed31_32_one, ++ i - 1); ++ region2 = dal_fixed31_32_shl( ++ dal_fixed31_32_one, ++ i); ++ } else { ++ region1 = dal_fixed31_32_shr( ++ dal_fixed31_32_one, ++ -(i - 1)); ++ region2 = dal_fixed31_32_shr( ++ dal_fixed31_32_one, ++ -i); ++ } ++ ++ break; ++ } ++ ++ if (i > -1) { ++ region1 = dal_fixed31_32_shl( ++ dal_fixed31_32_one, ++ i); ++ region2 = dal_fixed31_32_shl( ++ dal_fixed31_32_one, ++ i + 1); ++ } else { ++ region1 = dal_fixed31_32_shr( ++ dal_fixed31_32_one, ++ -i); ++ region2 = dal_fixed31_32_shr( ++ dal_fixed31_32_one, ++ -(i + 1)); ++ } ++ ++ gamma_curve[region_number].offset = offset; ++ gamma_curve[region_number].segments_num = segments; ++ ++ offset += divisor; ++ ++ ++segments_calculation[segments]; ++ ++ increment = dal_fixed31_32_div_int( ++ dal_fixed31_32_sub( ++ region2, ++ region1), ++ divisor); ++ ++ points[index].x = region1; ++ ++ round_custom_float_6_12(points + index); ++ ++ ++index; ++ ++region_number; ++ ++ while ((index < max_number) && (j < divisor - 1)) { ++ region1 = dal_fixed31_32_add( ++ region1, ++ increment); ++ ++ points[index].x = region1; ++ points[index].adjusted_x = region1; ++ ++ ++index; ++ ++j; ++ } ++ ++ ++i; ++ } ++ ++ points[index].x = region1; ++ ++ round_custom_float_6_12(points + index); ++ ++ *number_of_points = index; ++ ++ result = true; ++ } ++ ++ curve_points[0].x = points[0].adjusted_x; ++ curve_points[0].offset = dal_fixed31_32_zero; ++ ++ curve_points[1].x = points[index - 1].adjusted_x; ++ curve_points[1].offset = dal_fixed31_32_zero; ++ ++ curve_points[2].x = points[index].adjusted_x; ++ curve_points[2].offset = dal_fixed31_32_zero; ++ ++ return result; ++} ++ ++static bool setup_distribution_points( ++ struct gamma_curve *arr_curve_points, ++ struct curve_points *arr_points, ++ uint32_t *hw_points_num, ++ struct hw_x_point *coordinates_x) ++{ ++ struct curve_config cfg; ++ ++ cfg.offset = 0; ++ cfg.segments[0] = 3; ++ cfg.segments[1] = 4; ++ cfg.segments[2] = 4; ++ cfg.segments[3] = 4; ++ cfg.segments[4] = 4; ++ cfg.segments[5] = 4; ++ cfg.segments[6] = 4; ++ cfg.segments[7] = 4; ++ cfg.segments[8] = 5; ++ cfg.segments[9] = 5; ++ cfg.segments[10] = 0; ++ cfg.segments[11] = -1; ++ cfg.segments[12] = -1; ++ cfg.segments[13] = -1; ++ cfg.segments[14] = -1; ++ cfg.segments[15] = -1; ++ ++ cfg.begin = -10; ++ ++ if (!build_hw_curve_configuration( ++ &cfg, arr_curve_points, ++ arr_points, ++ coordinates_x, hw_points_num)) { ++ ASSERT_CRITICAL(false); ++ return false; ++ } ++ return true; ++} ++ ++struct dividers { ++ struct fixed31_32 divider1; ++ struct fixed31_32 divider2; ++ struct fixed31_32 divider3; ++}; ++ ++ ++static void build_regamma_coefficients(struct gamma_coefficients *coefficients) ++{ ++ /* 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; ++ ++ numerator1 = numerator01; ++ numerator2 = numerator02; ++ numerator3 = numerator03; ++ numerator4 = numerator04; ++ numerator5 = numerator05; ++ ++ do { ++ coefficients->a0[i] = dal_fixed31_32_from_fraction( ++ numerator1[i], 10000000); ++ coefficients->a1[i] = dal_fixed31_32_from_fraction( ++ numerator2[i], 1000); ++ coefficients->a2[i] = dal_fixed31_32_from_fraction( ++ numerator3[i], 1000); ++ coefficients->a3[i] = dal_fixed31_32_from_fraction( ++ numerator4[i], 1000); ++ coefficients->user_gamma[i] = dal_fixed31_32_from_fraction( ++ numerator5[i], 1000); ++ ++ ++i; ++ } while (i != ARRAY_SIZE(coefficients->a0)); ++} ++ ++static struct fixed31_32 translate_from_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) ++{ ++ const struct fixed31_32 one = dal_fixed31_32_from_int(1); ++ ++ if (dal_fixed31_32_le(arg, dal_fixed31_32_neg(a0))) ++ return dal_fixed31_32_sub( ++ a2, ++ dal_fixed31_32_mul( ++ dal_fixed31_32_add( ++ one, ++ a3), ++ dal_fixed31_32_pow( ++ dal_fixed31_32_neg(arg), ++ dal_fixed31_32_recip(gamma)))); ++ else if (dal_fixed31_32_le(a0, arg)) ++ return dal_fixed31_32_sub( ++ dal_fixed31_32_mul( ++ dal_fixed31_32_add( ++ one, ++ a3), ++ dal_fixed31_32_pow( ++ arg, ++ dal_fixed31_32_recip(gamma))), ++ a2); ++ else ++ return dal_fixed31_32_mul( ++ arg, ++ a1); ++} ++ ++static inline struct fixed31_32 translate_from_linear_space_ex( ++ struct fixed31_32 arg, ++ struct gamma_coefficients *coeff, ++ uint32_t color_index) ++{ ++ return translate_from_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 gamma_pixel *axis_x_256, ++ struct fixed31_32 hw_point, ++ enum channel_name channel, ++ uint32_t *index_to_start, ++ uint32_t *index_left, ++ uint32_t *index_right, ++ enum hw_point_position *pos) ++{ ++ const uint32_t max_number = RGB_256X3X16 + 3; ++ ++ struct fixed31_32 left, right; ++ ++ uint32_t i = *index_to_start; ++ ++ while (i < max_number) { ++ if (channel == CHANNEL_NAME_RED) { ++ left = axis_x_256[i].r; ++ ++ if (i < max_number - 1) ++ right = axis_x_256[i + 1].r; ++ else ++ right = axis_x_256[max_number - 1].r; ++ } else if (channel == CHANNEL_NAME_GREEN) { ++ left = axis_x_256[i].g; ++ ++ if (i < max_number - 1) ++ right = axis_x_256[i + 1].g; ++ else ++ right = axis_x_256[max_number - 1].g; ++ } else { ++ left = axis_x_256[i].b; ++ ++ if (i < max_number - 1) ++ right = axis_x_256[i + 1].b; ++ else ++ right = axis_x_256[max_number - 1].b; ++ } ++ ++ if (dal_fixed31_32_le(left, hw_point) && ++ dal_fixed31_32_le(hw_point, right)) { ++ *index_to_start = i; ++ *index_left = i; ++ ++ if (i < max_number - 1) ++ *index_right = i + 1; ++ else ++ *index_right = max_number - 1; ++ ++ *pos = HW_POINT_POSITION_MIDDLE; ++ ++ return true; ++ } else if ((i == *index_to_start) && ++ dal_fixed31_32_le(hw_point, left)) { ++ *index_to_start = i; ++ *index_left = i; ++ *index_right = i; ++ ++ *pos = HW_POINT_POSITION_LEFT; ++ ++ return true; ++ } else if ((i == max_number - 1) && ++ dal_fixed31_32_le(right, hw_point)) { ++ *index_to_start = i; ++ *index_left = i; ++ *index_right = i; ++ ++ *pos = HW_POINT_POSITION_RIGHT; ++ ++ return true; ++ } ++ ++ ++i; ++ } ++ ++ return false; ++} ++ ++static bool build_custom_gamma_mapping_coefficients_worker( ++ struct pixel_gamma_point *coeff, ++ const struct hw_x_point *coordinates_x, ++ const struct gamma_pixel *axis_x_256, ++ enum channel_name channel, ++ uint32_t number_of_points, ++ enum surface_pixel_format pixel_format) ++{ ++ uint32_t i = 0; ++ ++ while (i <= number_of_points) { ++ struct fixed31_32 coord_x; ++ ++ uint32_t index_to_start = 0; ++ uint32_t index_left = 0; ++ uint32_t index_right = 0; ++ ++ enum hw_point_position hw_pos; ++ ++ struct gamma_point *point; ++ ++ 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) ++ coord_x = coordinates_x[i].regamma_y_green; ++ else ++ coord_x = coordinates_x[i].regamma_y_blue; ++ ++ if (!find_software_points( ++ axis_x_256, coord_x, channel, ++ &index_to_start, &index_left, &index_right, &hw_pos)) { ++ BREAK_TO_DEBUGGER(); ++ return false; ++ } ++ ++ if (index_left >= RGB_256X3X16 + 3) { ++ BREAK_TO_DEBUGGER(); ++ return false; ++ } ++ ++ if (index_right >= RGB_256X3X16 + 3) { ++ BREAK_TO_DEBUGGER(); ++ return false; ++ } ++ ++ if (channel == CHANNEL_NAME_RED) { ++ point = &coeff[i].r; ++ ++ left_pos = axis_x_256[index_left].r; ++ right_pos = axis_x_256[index_right].r; ++ } else if (channel == CHANNEL_NAME_GREEN) { ++ point = &coeff[i].g; ++ ++ left_pos = axis_x_256[index_left].g; ++ right_pos = axis_x_256[index_right].g; ++ } else { ++ point = &coeff[i].b; ++ ++ left_pos = axis_x_256[index_left].b; ++ right_pos = axis_x_256[index_right].b; ++ } ++ ++ if (hw_pos == HW_POINT_POSITION_MIDDLE) ++ point->coeff = dal_fixed31_32_div( ++ dal_fixed31_32_sub( ++ coord_x, ++ left_pos), ++ dal_fixed31_32_sub( ++ right_pos, ++ left_pos)); ++ else if (hw_pos == HW_POINT_POSITION_LEFT) ++ point->coeff = dal_fixed31_32_zero; ++ else if (hw_pos == HW_POINT_POSITION_RIGHT) ++ point->coeff = dal_fixed31_32_from_int(2); ++ else { ++ BREAK_TO_DEBUGGER(); ++ return false; ++ } ++ ++ point->left_index = index_left; ++ point->right_index = index_right; ++ point->pos = hw_pos; ++ ++ ++i; ++ } ++ ++ return true; ++} ++ ++static inline bool build_oem_custom_gamma_mapping_coefficients( ++ struct pixel_gamma_point *coeff128_oem, ++ const struct hw_x_point *coordinates_x, ++ const struct gamma_pixel *axis_x_256, ++ uint32_t number_of_points, ++ enum surface_pixel_format pixel_format) ++{ ++ int i; ++ ++ for (i = 0; i < 3; i++) { ++ if (!build_custom_gamma_mapping_coefficients_worker( ++ coeff128_oem, coordinates_x, axis_x_256, i, ++ number_of_points, pixel_format)) ++ return false; ++ } ++ return true; ++} ++ ++static struct fixed31_32 calculate_mapped_value( ++ struct pwl_float_data *rgb, ++ const struct pixel_gamma_point *coeff, ++ enum channel_name channel, ++ uint32_t max_index) ++{ ++ const struct gamma_point *point; ++ ++ struct fixed31_32 result; ++ ++ if (channel == CHANNEL_NAME_RED) ++ point = &coeff->r; ++ else if (channel == CHANNEL_NAME_GREEN) ++ point = &coeff->g; ++ else ++ point = &coeff->b; ++ ++ if ((point->left_index < 0) || (point->left_index > max_index)) { ++ BREAK_TO_DEBUGGER(); ++ return dal_fixed31_32_zero; ++ } ++ ++ if ((point->right_index < 0) || (point->right_index > max_index)) { ++ BREAK_TO_DEBUGGER(); ++ return dal_fixed31_32_zero; ++ } ++ ++ if (point->pos == HW_POINT_POSITION_MIDDLE) ++ if (channel == CHANNEL_NAME_RED) ++ result = dal_fixed31_32_add( ++ dal_fixed31_32_mul( ++ point->coeff, ++ dal_fixed31_32_sub( ++ rgb[point->right_index].r, ++ rgb[point->left_index].r)), ++ rgb[point->left_index].r); ++ else if (channel == CHANNEL_NAME_GREEN) ++ result = dal_fixed31_32_add( ++ dal_fixed31_32_mul( ++ point->coeff, ++ dal_fixed31_32_sub( ++ rgb[point->right_index].g, ++ rgb[point->left_index].g)), ++ rgb[point->left_index].g); ++ else ++ result = dal_fixed31_32_add( ++ dal_fixed31_32_mul( ++ point->coeff, ++ dal_fixed31_32_sub( ++ rgb[point->right_index].b, ++ rgb[point->left_index].b)), ++ rgb[point->left_index].b); ++ else if (point->pos == HW_POINT_POSITION_LEFT) { ++ BREAK_TO_DEBUGGER(); ++ result = dal_fixed31_32_zero; ++ } else { ++ BREAK_TO_DEBUGGER(); ++ result = dal_fixed31_32_one; ++ } ++ ++ return result; ++} ++ ++static inline struct fixed31_32 calculate_oem_mapped_value( ++ struct pwl_float_data *rgb_oem, ++ const struct pixel_gamma_point *coeff, ++ uint32_t index, ++ enum channel_name channel, ++ uint32_t max_index) ++{ ++ return calculate_mapped_value( ++ rgb_oem, ++ coeff + index, ++ channel, ++ max_index); ++} ++ ++static void build_regamma_curve(struct pwl_float_data_ex *rgb_regamma, ++ struct pwl_float_data *rgb_oem, ++ struct pixel_gamma_point *coeff128_oem, ++ const struct core_gamma *ramp, ++ const struct core_surface *surface, ++ uint32_t hw_points_num, ++ const struct hw_x_point *coordinate_x, ++ const struct gamma_pixel *axis_x, ++ struct dividers dividers) ++{ ++ 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. ++ */ ++ ++ i = 0; ++ ++ while (i != hw_points_num + 1) { ++ rgb->r = translate_from_linear_space_ex( ++ coord_x->adjusted_x, &coeff, 0); ++ rgb->g = translate_from_linear_space_ex( ++ coord_x->adjusted_x, &coeff, 1); ++ rgb->b = translate_from_linear_space_ex( ++ coord_x->adjusted_x, &coeff, 2); ++ ++ ++coord_x; ++ ++rgb; ++ ++i; ++ } ++} ++ ++static bool scale_gamma(struct pwl_float_data *pwl_rgb, ++ const struct core_gamma *ramp, ++ struct dividers dividers) ++{ ++ const struct dc_gamma_ramp_rgb256x3x16 *gamma; ++ const uint16_t max_driver = 0xFFFF; ++ const uint16_t max_os = 0xFF00; ++ uint16_t scaler = max_os; ++ uint32_t i; ++ struct pwl_float_data *rgb = pwl_rgb; ++ struct pwl_float_data *rgb_last = rgb + RGB_256X3X16 - 1; ++ ++ if (ramp->public.type == GAMMA_RAMP_RBG256X3X16) ++ gamma = &ramp->public.gamma_ramp_rgb256x3x16; ++ else ++ return false; /* invalid option */ ++ ++ i = 0; ++ ++ do { ++ if ((gamma->red[i] > max_os) || ++ (gamma->green[i] > max_os) || ++ (gamma->blue[i] > max_os)) { ++ scaler = max_driver; ++ break; ++ } ++ ++i; ++ } while (i != RGB_256X3X16); ++ ++ i = 0; ++ ++ do { ++ rgb->r = dal_fixed31_32_from_fraction( ++ gamma->red[i], scaler); ++ rgb->g = dal_fixed31_32_from_fraction( ++ gamma->green[i], scaler); ++ rgb->b = dal_fixed31_32_from_fraction( ++ gamma->blue[i], scaler); ++ ++ ++rgb; ++ ++i; ++ } while (i != RGB_256X3X16); ++ ++ rgb->r = dal_fixed31_32_mul(rgb_last->r, ++ dividers.divider1); ++ rgb->g = dal_fixed31_32_mul(rgb_last->g, ++ dividers.divider1); ++ rgb->b = dal_fixed31_32_mul(rgb_last->b, ++ dividers.divider1); ++ ++ ++rgb; ++ ++ rgb->r = dal_fixed31_32_mul(rgb_last->r, ++ dividers.divider2); ++ rgb->g = dal_fixed31_32_mul(rgb_last->g, ++ dividers.divider2); ++ rgb->b = dal_fixed31_32_mul(rgb_last->b, ++ dividers.divider2); ++ ++ ++rgb; ++ ++ rgb->r = dal_fixed31_32_mul(rgb_last->r, ++ dividers.divider3); ++ rgb->g = dal_fixed31_32_mul(rgb_last->g, ++ dividers.divider3); ++ rgb->b = dal_fixed31_32_mul(rgb_last->b, ++ dividers.divider3); ++ ++ return true; ++} ++ ++static void build_evenly_distributed_points( ++ struct gamma_pixel *points, ++ uint32_t numberof_points, ++ struct fixed31_32 max_value, ++ struct dividers dividers) ++{ ++ struct gamma_pixel *p = points; ++ struct gamma_pixel *p_last = p + numberof_points - 1; ++ ++ uint32_t i = 0; ++ ++ do { ++ struct fixed31_32 value = dal_fixed31_32_div_int( ++ dal_fixed31_32_mul_int(max_value, i), ++ numberof_points - 1); ++ ++ p->r = value; ++ p->g = value; ++ p->b = value; ++ ++ ++p; ++ ++i; ++ } while (i != numberof_points); ++ ++ p->r = dal_fixed31_32_div(p_last->r, dividers.divider1); ++ p->g = dal_fixed31_32_div(p_last->g, dividers.divider1); ++ p->b = dal_fixed31_32_div(p_last->b, dividers.divider1); ++ ++ ++p; ++ ++ p->r = dal_fixed31_32_div(p_last->r, dividers.divider2); ++ p->g = dal_fixed31_32_div(p_last->g, dividers.divider2); ++ p->b = dal_fixed31_32_div(p_last->b, dividers.divider2); ++ ++ ++p; ++ ++ p->r = dal_fixed31_32_div(p_last->r, dividers.divider3); ++ p->g = dal_fixed31_32_div(p_last->g, dividers.divider3); ++ p->b = dal_fixed31_32_div(p_last->b, dividers.divider3); ++} ++ ++static inline void copy_rgb_regamma_to_coordinates_x( ++ struct hw_x_point *coordinates_x, ++ uint32_t hw_points_num, ++ const struct pwl_float_data_ex *rgb_ex) ++{ ++ struct hw_x_point *coords = coordinates_x; ++ uint32_t i = 0; ++ const struct pwl_float_data_ex *rgb_regamma = rgb_ex; ++ ++ while (i <= hw_points_num) { ++ coords->regamma_y_red = rgb_regamma->r; ++ coords->regamma_y_green = rgb_regamma->g; ++ coords->regamma_y_blue = rgb_regamma->b; ++ ++ ++coords; ++ ++rgb_regamma; ++ ++i; ++ } ++} ++ ++static bool calculate_interpolated_hardware_curve( ++ struct pwl_result_data *rgb, ++ struct pixel_gamma_point *coeff128, ++ struct pwl_float_data *rgb_user, ++ const struct hw_x_point *coordinates_x, ++ const struct gamma_pixel *axis_x_256, ++ uint32_t number_of_points, ++ enum surface_pixel_format pixel_format) ++{ ++ ++ const struct pixel_gamma_point *coeff; ++ struct pixel_gamma_point *coeff_128 = coeff128; ++ uint32_t max_entries = 3 - 1; ++ struct pwl_result_data *rgb_resulted = rgb; ++ ++ uint32_t i = 0; ++ ++ if (!build_oem_custom_gamma_mapping_coefficients( ++ coeff_128, coordinates_x, axis_x_256, ++ number_of_points, ++ pixel_format)) ++ return false; ++ ++ coeff = coeff128; ++ max_entries += RGB_256X3X16; ++ ++ /* TODO: float point case */ ++ ++ while (i <= number_of_points) { ++ rgb_resulted->red = calculate_mapped_value( ++ rgb_user, coeff, CHANNEL_NAME_RED, max_entries); ++ rgb_resulted->green = calculate_mapped_value( ++ rgb_user, coeff, CHANNEL_NAME_GREEN, max_entries); ++ rgb_resulted->blue = calculate_mapped_value( ++ rgb_user, coeff, CHANNEL_NAME_BLUE, max_entries); ++ ++ ++coeff; ++ ++rgb_resulted; ++ ++i; ++ } ++ ++ return true; ++} ++ ++static bool map_regamma_hw_to_x_user( ++ struct pixel_gamma_point *coeff128, ++ struct pwl_float_data *rgb_oem, ++ struct pwl_result_data *rgb_resulted, ++ struct pwl_float_data *rgb_user, ++ struct hw_x_point *coords_x, ++ const struct gamma_pixel *axis_x, ++ const struct dc_gamma *gamma, ++ const struct pwl_float_data_ex *rgb_regamma, ++ struct dividers dividers, ++ uint32_t hw_points_num, ++ const struct core_surface *surface) ++{ ++ /* setup to spare calculated ideal regamma values */ ++ ++ struct pixel_gamma_point *coeff = coeff128; ++ ++ struct hw_x_point *coords = coords_x; ++ ++ copy_rgb_regamma_to_coordinates_x(coords, hw_points_num, rgb_regamma); ++ ++ return calculate_interpolated_hardware_curve( ++ rgb_resulted, coeff, rgb_user, coords, axis_x, ++ hw_points_num, surface->public.format); ++} ++ ++static void build_new_custom_resulted_curve( ++ struct pwl_result_data *rgb_resulted, ++ uint32_t hw_points_num) ++{ ++ struct pwl_result_data *rgb = rgb_resulted; ++ struct pwl_result_data *rgb_plus_1 = rgb + 1; ++ ++ uint32_t i; ++ ++ i = 0; ++ ++ while (i != hw_points_num + 1) { ++ rgb->red = dal_fixed31_32_clamp( ++ rgb->red, dal_fixed31_32_zero, ++ dal_fixed31_32_one); ++ rgb->green = dal_fixed31_32_clamp( ++ rgb->green, dal_fixed31_32_zero, ++ dal_fixed31_32_one); ++ rgb->blue = dal_fixed31_32_clamp( ++ rgb->blue, dal_fixed31_32_zero, ++ dal_fixed31_32_one); ++ ++ ++rgb; ++ ++i; ++ } ++ ++ rgb = rgb_resulted; ++ ++ i = 1; ++ ++ while (i != hw_points_num + 1) { ++ if (dal_fixed31_32_lt(rgb_plus_1->red, rgb->red)) ++ rgb_plus_1->red = rgb->red; ++ if (dal_fixed31_32_lt(rgb_plus_1->green, rgb->green)) ++ rgb_plus_1->green = rgb->green; ++ if (dal_fixed31_32_lt(rgb_plus_1->blue, rgb->blue)) ++ rgb_plus_1->blue = rgb->blue; ++ ++ rgb->delta_red = dal_fixed31_32_sub( ++ rgb_plus_1->red, ++ rgb->red); ++ rgb->delta_green = dal_fixed31_32_sub( ++ rgb_plus_1->green, ++ rgb->green); ++ rgb->delta_blue = dal_fixed31_32_sub( ++ rgb_plus_1->blue, ++ rgb->blue); ++ ++ ++rgb_plus_1; ++ ++rgb; ++ ++i; ++ } ++} ++ ++static void rebuild_curve_configuration_magic( ++ struct curve_points *arr_points, ++ struct pwl_result_data *rgb_resulted, ++ const struct hw_x_point *coordinates_x, ++ uint32_t hw_points_num) ++{ ++ const struct fixed31_32 magic_number = ++ dal_fixed31_32_from_fraction(249, 1000); ++ ++ struct fixed31_32 y_r; ++ struct fixed31_32 y_g; ++ struct fixed31_32 y_b; ++ ++ struct fixed31_32 y1_min; ++ struct fixed31_32 y2_max; ++ struct fixed31_32 y3_max; ++ ++ y_r = rgb_resulted[0].red; ++ y_g = rgb_resulted[0].green; ++ y_b = rgb_resulted[0].blue; ++ ++ y1_min = dal_fixed31_32_min(y_r, dal_fixed31_32_min(y_g, y_b)); ++ ++ arr_points[0].x = coordinates_x[0].adjusted_x; ++ arr_points[0].y = y1_min; ++ arr_points[0].slope = dal_fixed31_32_div( ++ arr_points[0].y, ++ arr_points[0].x); ++ ++ arr_points[1].x = dal_fixed31_32_add( ++ coordinates_x[hw_points_num - 1].adjusted_x, ++ magic_number); ++ ++ arr_points[2].x = arr_points[1].x; ++ ++ y_r = rgb_resulted[hw_points_num - 1].red; ++ y_g = rgb_resulted[hw_points_num - 1].green; ++ y_b = rgb_resulted[hw_points_num - 1].blue; ++ ++ y2_max = dal_fixed31_32_max(y_r, dal_fixed31_32_max(y_g, y_b)); ++ ++ arr_points[1].y = y2_max; ++ ++ y_r = rgb_resulted[hw_points_num].red; ++ y_g = rgb_resulted[hw_points_num].green; ++ y_b = rgb_resulted[hw_points_num].blue; ++ ++ y3_max = dal_fixed31_32_max(y_r, dal_fixed31_32_max(y_g, y_b)); ++ ++ arr_points[2].y = y3_max; ++ ++ arr_points[2].slope = dal_fixed31_32_one; ++} ++ ++static bool convert_to_custom_float_format( ++ struct fixed31_32 value, ++ const struct custom_float_format *format, ++ uint32_t *result) ++{ ++ uint32_t mantissa; ++ uint32_t exponenta; ++ bool negative; ++ ++ return build_custom_float( ++ value, format, &negative, &mantissa, &exponenta) && ++ setup_custom_float( ++ format, negative, mantissa, exponenta, result); ++} ++ ++static bool convert_to_custom_float( ++ struct pwl_result_data *rgb_resulted, ++ struct curve_points *arr_points, ++ uint32_t hw_points_num) ++{ ++ struct custom_float_format fmt; ++ ++ struct pwl_result_data *rgb = rgb_resulted; ++ ++ uint32_t i = 0; ++ ++ fmt.exponenta_bits = 6; ++ fmt.mantissa_bits = 12; ++ fmt.sign = true; ++ ++ if (!convert_to_custom_float_format( ++ arr_points[0].x, ++ &fmt, ++ &arr_points[0].custom_float_x)) { ++ BREAK_TO_DEBUGGER(); ++ return false; ++ } ++ ++ if (!convert_to_custom_float_format( ++ arr_points[0].offset, ++ &fmt, ++ &arr_points[0].custom_float_offset)) { ++ BREAK_TO_DEBUGGER(); ++ return false; ++ } ++ ++ if (!convert_to_custom_float_format( ++ arr_points[0].slope, ++ &fmt, ++ &arr_points[0].custom_float_slope)) { ++ BREAK_TO_DEBUGGER(); ++ return false; ++ } ++ ++ fmt.mantissa_bits = 10; ++ fmt.sign = false; ++ ++ if (!convert_to_custom_float_format( ++ arr_points[1].x, ++ &fmt, ++ &arr_points[1].custom_float_x)) { ++ BREAK_TO_DEBUGGER(); ++ return false; ++ } ++ ++ if (!convert_to_custom_float_format( ++ arr_points[1].y, ++ &fmt, ++ &arr_points[1].custom_float_y)) { ++ BREAK_TO_DEBUGGER(); ++ return false; ++ } ++ ++ if (!convert_to_custom_float_format( ++ arr_points[2].slope, ++ &fmt, ++ &arr_points[2].custom_float_slope)) { ++ BREAK_TO_DEBUGGER(); ++ return false; ++ } ++ ++ fmt.mantissa_bits = 12; ++ fmt.sign = true; ++ ++ while (i != hw_points_num) { ++ if (!convert_to_custom_float_format( ++ rgb->red, ++ &fmt, ++ &rgb->red_reg)) { ++ BREAK_TO_DEBUGGER(); ++ return false; ++ } ++ ++ if (!convert_to_custom_float_format( ++ rgb->green, ++ &fmt, ++ &rgb->green_reg)) { ++ BREAK_TO_DEBUGGER(); ++ return false; ++ } ++ ++ if (!convert_to_custom_float_format( ++ rgb->blue, ++ &fmt, ++ &rgb->blue_reg)) { ++ BREAK_TO_DEBUGGER(); ++ return false; ++ } ++ ++ if (!convert_to_custom_float_format( ++ rgb->delta_red, ++ &fmt, ++ &rgb->delta_red_reg)) { ++ BREAK_TO_DEBUGGER(); ++ return false; ++ } ++ ++ if (!convert_to_custom_float_format( ++ rgb->delta_green, ++ &fmt, ++ &rgb->delta_green_reg)) { ++ BREAK_TO_DEBUGGER(); ++ return false; ++ } ++ ++ if (!convert_to_custom_float_format( ++ rgb->delta_blue, ++ &fmt, ++ &rgb->delta_blue_reg)) { ++ BREAK_TO_DEBUGGER(); ++ return false; ++ } ++ ++ ++rgb; ++ ++i; ++ } ++ ++ return true; ++} ++ ++void calculate_regamma_params(struct regamma_params *params, ++ struct temp_params *temp_params, ++ const struct core_gamma *ramp, ++ const struct core_surface *surface) ++{ ++ struct gamma_curve *arr_curve_points = params->arr_curve_points; ++ struct curve_points *arr_points = params->arr_points; ++ struct hw_x_point *coordinates_x = temp_params->coordinates_x; ++ struct pwl_float_data *rgb_user = temp_params->rgb_user; ++ struct pwl_float_data_ex *rgb_regamma = temp_params->rgb_regamma; ++ struct pwl_float_data *rgb_oem = temp_params->rgb_oem; ++ struct pwl_result_data *rgb_resulted = params->rgb_resulted; ++ struct dividers dividers; ++ struct gamma_pixel *axix_x_256 = temp_params->axix_x_256; ++ struct pixel_gamma_point *coeff128_oem = temp_params->coeff128_oem; ++ struct pixel_gamma_point *coeff128 = temp_params->coeff128; ++ ++ 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); ++ ++ build_evenly_distributed_points( ++ axix_x_256, ++ 256, ++ dal_fixed31_32_one, ++ dividers); ++ ++ scale_gamma(rgb_user, ramp, dividers); ++ ++ setup_distribution_points(arr_curve_points, arr_points, ++ ¶ms->hw_points_num, coordinates_x); ++ ++ build_regamma_curve(rgb_regamma, rgb_oem, coeff128_oem, ++ ramp, surface, params->hw_points_num, ++ coordinates_x, axix_x_256, dividers); ++ ++ map_regamma_hw_to_x_user(coeff128, rgb_oem, rgb_resulted, rgb_user, ++ coordinates_x, axix_x_256, &ramp->public, rgb_regamma, ++ dividers, params->hw_points_num, surface); ++ ++ build_new_custom_resulted_curve(rgb_resulted, params->hw_points_num); ++ ++ rebuild_curve_configuration_magic( ++ arr_points, ++ rgb_resulted, ++ coordinates_x, ++ params->hw_points_num); ++ ++ convert_to_custom_float(rgb_resulted, arr_points, ++ params->hw_points_num); ++} ++ ++ +diff --git a/drivers/gpu/drm/amd/dal/dc/core/dc_surface.c b/drivers/gpu/drm/amd/dal/dc/core/dc_surface.c +index 1a9ee8f..3878a61 100644 +--- a/drivers/gpu/drm/amd/dal/dc/core/dc_surface.c ++++ b/drivers/gpu/drm/amd/dal/dc/core/dc_surface.c +@@ -40,36 +40,33 @@ struct surface { + int ref_count; + }; + ++struct gamma { ++ struct core_gamma protected; ++ int ref_count; ++}; ++ + #define DC_SURFACE_TO_SURFACE(dc_surface) container_of(dc_surface, struct surface, protected.public) + #define CORE_SURFACE_TO_SURFACE(core_surface) container_of(core_surface, struct surface, protected) + ++#define DC_GAMMA_TO_GAMMA(dc_gamma) \ ++ container_of(dc_gamma, struct gamma, protected.public) ++#define CORE_GAMMA_TO_GAMMA(core_gamma) \ ++ container_of(core_gamma, struct gamma, protected) ++ ++ + /******************************************************************************* + * Private functions + ******************************************************************************/ + static bool construct(struct dc_context *ctx, struct surface *surface) + { +- uint32_t i; +- struct gamma_ramp *gamma = +- &surface->protected.public.gamma_correction; +- +- /* construct gamma default value. */ +- for (i = 0; i < NUM_OF_RAW_GAMMA_RAMP_RGB_256; i++) { +- gamma->gamma_ramp_rgb256x3x16.red[i] = +- (unsigned short) (i << 8); +- gamma->gamma_ramp_rgb256x3x16.green[i] = +- (unsigned short) (i << 8); +- gamma->gamma_ramp_rgb256x3x16.blue[i] = +- (unsigned short) (i << 8); +- } +- gamma->type = GAMMA_RAMP_TYPE_RGB256; +- gamma->size = sizeof(gamma->gamma_ramp_rgb256x3x16); +- + surface->protected.ctx = ctx; + return true; + } + + static void destruct(struct surface *surface) + { ++ if (surface->protected.public.gamma_correction) ++ dc_gamma_release(surface->protected.public.gamma_correction); + } + + /******************************************************************************* +@@ -121,3 +118,54 @@ void dc_surface_release(const struct dc_surface *dc_surface) + dm_free(surface->protected.ctx, surface); + } + } ++ ++static bool construct_gamma(struct dc_context *ctx, struct gamma *gamma) ++{ ++ return true; ++} ++ ++static void destruct_gamma(struct gamma *gamma) ++{ ++ ++} ++ ++void dc_gamma_retain(const struct dc_gamma *dc_gamma) ++{ ++ struct gamma *gamma = DC_GAMMA_TO_GAMMA(dc_gamma); ++ ++ ++gamma->ref_count; ++} ++ ++void dc_gamma_release(const struct dc_gamma *dc_gamma) ++{ ++ struct gamma *gamma = DC_GAMMA_TO_GAMMA(dc_gamma); ++ --gamma->ref_count; ++ ++ if (gamma->ref_count == 0) { ++ destruct_gamma(gamma); ++ dm_free(gamma->protected.ctx, gamma); ++ } ++} ++ ++ ++struct dc_gamma *dc_create_gamma(const struct dc *dc) ++{ ++ struct gamma *gamma = dm_alloc(dc->ctx, sizeof(*gamma)); ++ ++ if (gamma == NULL) ++ goto alloc_fail; ++ ++ if (false == construct_gamma(dc->ctx, gamma)) ++ goto construct_fail; ++ ++ dc_gamma_retain(&gamma->protected.public); ++ ++ return &gamma->protected.public; ++ ++construct_fail: ++ dm_free(dc->ctx, gamma); ++ ++alloc_fail: ++ return NULL; ++} ++ +diff --git a/drivers/gpu/drm/amd/dal/dc/core/dc_target.c b/drivers/gpu/drm/amd/dal/dc/core/dc_target.c +index 7980e9f..e8579bc 100644 +--- a/drivers/gpu/drm/amd/dal/dc/core/dc_target.c ++++ b/drivers/gpu/drm/amd/dal/dc/core/dc_target.c +@@ -133,68 +133,6 @@ target_alloc_fail: + return NULL; + } + +-static void build_gamma_params( +- enum pixel_format pixel_format, +- struct gamma_parameters *gamma_param) +-{ +- uint32_t i; +- +- /* translate parameters */ +- gamma_param->surface_pixel_format = pixel_format; +- +- gamma_param->regamma_adjust_type = GRAPHICS_REGAMMA_ADJUST_SW; +- gamma_param->degamma_adjust_type = GRAPHICS_REGAMMA_ADJUST_SW; +- +- gamma_param->selected_gamma_lut = GRAPHICS_GAMMA_LUT_REGAMMA; +- +- /* TODO support non-legacy gamma */ +- gamma_param->disable_adjustments = false; +- gamma_param->flag.bits.config_is_changed = 0; +- gamma_param->flag.bits.regamma_update = 1; +- gamma_param->flag.bits.gamma_update = 1; +- +- /* Set regamma */ +- gamma_param->regamma.features.bits.GRAPHICS_DEGAMMA_SRGB = 1; +- gamma_param->regamma.features.bits.OVERLAY_DEGAMMA_SRGB = 1; +- gamma_param->regamma.features.bits.GAMMA_RAMP_ARRAY = 0; +- gamma_param->regamma.features.bits.APPLY_DEGAMMA = 0; +- +- for (i = 0; i < COEFF_RANGE; i++) { +- gamma_param->regamma.gamma_coeff.a0[i] = REGAMMA_COEFF_A0; +- gamma_param->regamma.gamma_coeff.a1[i] = REGAMMA_COEFF_A1; +- gamma_param->regamma.gamma_coeff.a2[i] = REGAMMA_COEFF_A2; +- gamma_param->regamma.gamma_coeff.a3[i] = REGAMMA_COEFF_A3; +- gamma_param->regamma.gamma_coeff.gamma[i] = REGAMMA_COEFF_GAMMA; +- } +-} +- +- +-static bool program_gamma( +- struct dc_context *ctx, +- struct dc_surface *surface, +- struct input_pixel_processor *ipp, +- struct output_pixel_processor *opp) +-{ +- struct gamma_parameters *gamma_param; +- bool result= false; +- +- gamma_param = dm_alloc(ctx, sizeof(struct gamma_parameters)); +- +- if (!gamma_param) +- goto gamma_param_fail; +- +- build_gamma_params(surface->format, gamma_param); +- +- result = ctx->dc->hwss.set_gamma_ramp(ipp, opp, +- &surface->gamma_correction, +- gamma_param); +- +- dm_free(ctx, gamma_param); +- +-gamma_param_fail: +- return result; +-} +- + static bool validate_surface_address( + struct dc_plane_address address) + { +@@ -298,18 +236,27 @@ bool dc_commit_surfaces_to_target( + for (i = 0; i < new_surface_count; i++) { + struct dc_surface *surface = new_surfaces[i]; + struct core_surface *core_surface = DC_SURFACE_TO_CORE(surface); ++ struct core_stream *stream = ++ DC_STREAM_TO_CORE(target->public.streams[0]); + bool is_valid_address = + validate_surface_address(surface->address); + ++ + dal_logger_write(dc->ctx->logger, + LOG_MAJOR_INTERFACE_TRACE, + LOG_MINOR_COMPONENT_DC, + "0x%x:", + surface); + +- program_gamma(dc->ctx, surface, +- DC_STREAM_TO_CORE(target->public.streams[0])->ipp, +- DC_STREAM_TO_CORE(target->public.streams[0])->opp); ++ if (surface->gamma_correction) { ++ struct core_gamma *gamma = DC_GAMMA_TO_CORE( ++ surface->gamma_correction); ++ ++ dc->hwss.set_gamma_correction( ++ stream->ipp, ++ stream->opp, ++ gamma, core_surface); ++ } + + dc->hwss.set_plane_config(dc, core_surface, target); + +diff --git a/drivers/gpu/drm/amd/dal/dc/dc.h b/drivers/gpu/drm/amd/dal/dc/dc.h +index cc3395d..901c8c4 100644 +--- a/drivers/gpu/drm/amd/dal/dc/dc.h ++++ b/drivers/gpu/drm/amd/dal/dc/dc.h +@@ -59,6 +59,43 @@ void dc_destroy(struct dc **dc); + * Surface Interfaces + ******************************************************************************/ + ++enum { ++ RGB_256X3X16 = 256, ++ FLOAT_GAMMA_RAMP_MAX = 1025 ++}; ++ ++enum dc_gamma_ramp_type { ++ GAMMA_RAMP_RBG256X3X16, ++ GAMMA_RAMP_FLOAT, ++}; ++ ++struct float_rgb { ++ struct fixed32_32 red; ++ struct fixed32_32 green; ++ struct fixed32_32 blue; ++}; ++ ++struct dc_gamma_ramp_float { ++ struct float_rgb scale; ++ struct float_rgb offset; ++ struct float_rgb gamma_curve[FLOAT_GAMMA_RAMP_MAX]; ++}; ++ ++struct dc_gamma_ramp_rgb256x3x16 { ++ uint16_t red[RGB_256X3X16]; ++ uint16_t green[RGB_256X3X16]; ++ uint16_t blue[RGB_256X3X16]; ++}; ++ ++struct dc_gamma { ++ enum dc_gamma_ramp_type type; ++ union { ++ struct dc_gamma_ramp_rgb256x3x16 gamma_ramp_rgb256x3x16; ++ struct dc_gamma_ramp_float gamma_ramp_float; ++ }; ++ uint32_t size; ++}; ++ + struct dc_surface { + bool visible; + bool flip_immediate; +@@ -77,8 +114,7 @@ struct dc_surface { + enum dc_rotation_angle rotation; + enum plane_stereo_format stereo_format; + +- struct gamma_ramp gamma_correction; /* deprecated */ +- struct dc_gamma_ramp gamma; ++ struct dc_gamma *gamma_correction; + }; + + /* +@@ -102,6 +138,9 @@ const struct dc_surface_status* dc_surface_get_status( + void dc_surface_retain(const struct dc_surface *dc_surface); + void dc_surface_release(const struct dc_surface *dc_surface); + ++void dc_gamma_release(const struct dc_gamma *dc_gamma); ++struct dc_gamma *dc_create_gamma(const struct dc *dc); ++ + /* + * This structure holds a surface address. There could be multiple addresses + * in cases such as Stereo 3D, Planar YUV, etc. Other per-flip attributes such +diff --git a/drivers/gpu/drm/amd/dal/dc/dc_types.h b/drivers/gpu/drm/amd/dal/dc/dc_types.h +index 67e62c3..5593c17 100644 +--- a/drivers/gpu/drm/amd/dal/dc/dc_types.h ++++ b/drivers/gpu/drm/amd/dal/dc/dc_types.h +@@ -559,79 +559,6 @@ enum dc_connection_type { + dc_connection_active_dongle + }; + +-/* +- * Gamma ramp representation in DC +- * +- * A gamma ramp is just a curve defined within the range of [min, max] with +- * arbitrary precision. +- * +- * DM is responsible for providing DC with an interface to obtain any y value +- * within that range with a selected precision. +- * +- * bit32 ------------------------------------------------- bit 0 +- * [ padding ][ exponent bits ][ fraction bits ] +- * +- * DC specifies the input x value and precision to the callback function +- * get_gamma_value as well as providing the context and DM returns the y +- * value. +- * +- * If fraction_bits + exponent_bits exceed width of 32 bits, get_gamma_value +- * returns 0. If x is outside the bounds of [min, max], get_gamma_value +- * returns 0. +- * +- */ +-/* TODO: Deprecated */ +-enum { +- RGB_256X3X16 = 256, +- DX_GAMMA_RAMP_MAX = 1025 +-}; +- +-enum gamma_ramp_type { +- GAMMA_RAMP_UNINITIALIZED = 0, +- GAMMA_RAMP_DEFAULT, +- GAMMA_RAMP_RBG256X3X16, +- GAMMA_RAMP_DXGI_1, +-}; +- +-struct dxgi_rgb { +- struct fixed32_32 red; +- struct fixed32_32 green; +- struct fixed32_32 blue; +-}; +- +-struct gamma_ramp_dxgi_1 { +- struct dxgi_rgb scale; +- struct dxgi_rgb offset; +- struct dxgi_rgb gamma_curve[DX_GAMMA_RAMP_MAX]; +-}; +- +-struct gamma_ramp_rgb256x3x16 { +- uint16_t red[RGB_256X3X16]; +- uint16_t green[RGB_256X3X16]; +- uint16_t blue[RGB_256X3X16]; +-}; +- +-struct gamma_ramp { +- enum gamma_ramp_type type; +- union { +- struct gamma_ramp_rgb256x3x16 gamma_ramp_rgb256x3x16; +- struct gamma_ramp_dxgi_1 gamma_ramp_dxgi1; +- }; +- uint32_t size; +-}; +- +- +-struct dc_gamma_ramp { +- uint32_t (*get_gamma_value) ( +- void *context, +- uint8_t exponent_bits, +- uint8_t fraction_bits, +- uint32_t x); +- void *context; +- uint32_t min; +- uint32_t max; +-}; +- + struct dc_csc_adjustments { + struct fixed31_32 contrast; + struct fixed31_32 saturation; +diff --git a/drivers/gpu/drm/amd/dal/dc/dce110/dce110_hw_sequencer.c b/drivers/gpu/drm/amd/dal/dc/dce110/dce110_hw_sequencer.c +index 754e81d..946e42f 100644 +--- a/drivers/gpu/drm/amd/dal/dc/dce110/dce110_hw_sequencer.c ++++ b/drivers/gpu/drm/amd/dal/dc/dce110/dce110_hw_sequencer.c +@@ -42,6 +42,7 @@ + #include "stream_encoder.h" + #include "link_encoder.h" + #include "clock_source.h" ++#include "gamma_calcs.h" + + /* include DCE11 register header files */ + #include "dce/dce_11_0_d.h" +@@ -476,64 +477,83 @@ static bool dce110_enable_display_power_gating( + return false; + } + ++static void build_prescale_params(struct ipp_prescale_params *prescale_params, ++ const struct core_surface *surface) ++{ ++ prescale_params->mode = IPP_PRESCALE_MODE_FIXED_UNSIGNED; ++ ++ switch (surface->public.format) { ++ case SURFACE_PIXEL_FORMAT_GRPH_ARGB8888: ++ case SURFACE_PIXEL_FORMAT_GRPH_BGRA8888: ++ prescale_params->scale = 0x2000; ++ break; ++ case SURFACE_PIXEL_FORMAT_GRPH_ARGB2101010: ++ case SURFACE_PIXEL_FORMAT_GRPH_ABGR2101010: ++ /* TODO */ ++ break; ++ case SURFACE_PIXEL_FORMAT_GRPH_ARGB16161616: ++ case SURFACE_PIXEL_FORMAT_GRPH_ABGR16161616F: ++ /* TODO */ ++ break; ++ default: ++ ASSERT(false); ++ } ++} ++ + + static bool set_gamma_ramp( + struct input_pixel_processor *ipp, + struct output_pixel_processor *opp, +- const struct gamma_ramp *ramp, +- const struct gamma_parameters *params) ++ const struct core_gamma *ramp, ++ const struct core_surface *surface) + { +- /*Power on LUT memory*/ +- opp->funcs->opp_power_on_regamma_lut(opp, true); ++ struct ipp_prescale_params *prescale_params; ++ struct regamma_params *regamma_params; ++ struct temp_params *temp_params; ++ bool result = false; + ++ prescale_params = dm_alloc(opp->ctx, ++ sizeof(struct ipp_prescale_params)); + +- if (params->surface_pixel_format == PIXEL_FORMAT_INDEX8 || +- params->selected_gamma_lut == GRAPHICS_GAMMA_LUT_LEGACY) { +- /* do legacy DCP for 256 colors if we are requested to do so */ +- ipp->funcs->ipp_set_legacy_input_gamma_ramp( +- ipp, ramp, params); ++ if (prescale_params == NULL) ++ goto prescale_alloc_fail; + +- ipp->funcs->ipp_set_legacy_input_gamma_mode(ipp, true); ++ regamma_params = dm_alloc(opp->ctx, ++ sizeof(struct regamma_params)); ++ if (regamma_params == NULL) ++ goto regamma_alloc_fail; + +- /* set bypass */ +- ipp->funcs->ipp_program_prescale(ipp, PIXEL_FORMAT_UNINITIALIZED); ++ temp_params = dm_alloc(opp->ctx, sizeof(struct temp_params)); + +- ipp->funcs->ipp_set_degamma(ipp, params, true); ++ if (temp_params == NULL) ++ goto temp_alloc_fail; + +- opp->funcs->opp_set_regamma(opp, ramp, params, true); +- } else if (params->selected_gamma_lut == +- GRAPHICS_GAMMA_LUT_LEGACY_AND_REGAMMA) { +- if (!opp->funcs->opp_map_legacy_and_regamma_hw_to_x_user( +- opp, ramp, params)) { +- BREAK_TO_DEBUGGER(); +- /* invalid parameters or bug */ +- return false; +- } ++ regamma_params->hw_points_num = GAMMA_HW_POINTS_NUM; + +- /* do legacy DCP for 256 colors if we are requested to do so */ +- ipp->funcs->ipp_set_legacy_input_gamma_ramp( +- ipp, ramp, params); ++ opp->funcs->opp_power_on_regamma_lut(opp, true); + +- ipp->funcs->ipp_set_legacy_input_gamma_mode(ipp, true); ++ build_prescale_params(prescale_params, surface); + +- /* set bypass */ +- ipp->funcs->ipp_program_prescale(ipp, PIXEL_FORMAT_UNINITIALIZED); +- } else { +- ipp->funcs->ipp_set_legacy_input_gamma_mode(ipp, false); ++ ipp->funcs->ipp_program_prescale(ipp, prescale_params); + +- ipp->funcs->ipp_program_prescale(ipp, params->surface_pixel_format); ++ ipp->funcs->ipp_set_degamma(ipp, IPP_DEGAMMA_MODE_sRGB); + +- /* Do degamma step : remove the given gamma value from FB. +- * For FP16 or no degamma do by pass */ +- ipp->funcs->ipp_set_degamma(ipp, params, false); ++ calculate_regamma_params(regamma_params, temp_params, ramp, surface); + +- opp->funcs->opp_set_regamma(opp, ramp, params, false); +- } ++ opp->funcs->opp_set_regamma(opp, regamma_params); + +- /*re-enable low power mode for LUT memory*/ + opp->funcs->opp_power_on_regamma_lut(opp, false); + +- return true; ++ dm_free(opp->ctx, temp_params); ++ ++ result = true; ++ ++temp_alloc_fail: ++ dm_free(opp->ctx, regamma_params); ++regamma_alloc_fail: ++ dm_free(opp->ctx, prescale_params); ++prescale_alloc_fail: ++ return result; + } + + static enum dc_status bios_parser_crtc_source_select( +@@ -1662,7 +1682,7 @@ static const struct hw_sequencer_funcs dce110_funcs = { + .reset_hw_ctx = reset_hw_ctx, + .set_plane_config = set_plane_config, + .update_plane_address = update_plane_address, +- .set_gamma_ramp = set_gamma_ramp, ++ .set_gamma_correction = set_gamma_ramp, + .power_down = power_down, + .enable_accelerated_mode = enable_accelerated_mode, + .enable_timing_synchronization = enable_timing_synchronization, +diff --git a/drivers/gpu/drm/amd/dal/dc/dce110/dce110_hw_sequencer.h b/drivers/gpu/drm/amd/dal/dc/dce110/dce110_hw_sequencer.h +index def54df..eafa345 100644 +--- a/drivers/gpu/drm/amd/dal/dc/dce110/dce110_hw_sequencer.h ++++ b/drivers/gpu/drm/amd/dal/dc/dce110/dce110_hw_sequencer.h +@@ -28,6 +28,7 @@ + + #include "core_types.h" + ++#define GAMMA_HW_POINTS_NUM 256 + struct dc; + + bool dce110_hw_sequencer_construct(struct dc *dc); +diff --git a/drivers/gpu/drm/amd/dal/dc/dce110/dce110_ipp.c b/drivers/gpu/drm/amd/dal/dc/dce110/dce110_ipp.c +index 6ab3527..e67b7e6 100644 +--- a/drivers/gpu/drm/amd/dal/dc/dce110/dce110_ipp.c ++++ b/drivers/gpu/drm/amd/dal/dc/dce110/dce110_ipp.c +@@ -36,9 +36,6 @@ static struct ipp_funcs funcs = { + .ipp_cursor_set_position = dce110_ipp_cursor_set_position, + .ipp_program_prescale = dce110_ipp_program_prescale, + .ipp_set_degamma = dce110_ipp_set_degamma, +- .ipp_set_legacy_input_gamma_mode = dce110_ipp_set_legacy_input_gamma_mode, +- .ipp_set_legacy_input_gamma_ramp = dce110_ipp_set_legacy_input_gamma_ramp, +- .ipp_set_palette = dce110_ipp_set_palette, + }; + + bool dce110_ipp_construct( +diff --git a/drivers/gpu/drm/amd/dal/dc/dce110/dce110_ipp.h b/drivers/gpu/drm/amd/dal/dc/dce110/dce110_ipp.h +index 709906f..dde138c 100644 +--- a/drivers/gpu/drm/amd/dal/dc/dce110/dce110_ipp.h ++++ b/drivers/gpu/drm/amd/dal/dc/dce110/dce110_ipp.h +@@ -42,7 +42,6 @@ struct dce110_ipp_reg_offsets { + struct dce110_ipp { + struct input_pixel_processor base; + struct dce110_ipp_reg_offsets offsets; +- struct dev_c_lut saved_palette[RGB_256X3X16]; + }; + + bool dce110_ipp_construct( +@@ -65,29 +64,11 @@ bool dce110_ipp_cursor_set_attributes( + /* DEGAMMA RELATED */ + bool dce110_ipp_set_degamma( + struct input_pixel_processor *ipp, +- const struct gamma_parameters *params, +- bool force_bypass); ++ enum ipp_degamma_mode mode); + + void dce110_ipp_program_prescale( + struct input_pixel_processor *ipp, +- enum pixel_format pixel_format); +- +-void dce110_ipp_set_legacy_input_gamma_mode( +- struct input_pixel_processor *ipp, +- bool is_legacy); +- +-bool dce110_ipp_set_legacy_input_gamma_ramp( +- struct input_pixel_processor *ipp, +- const struct gamma_ramp *gamma_ramp, +- const struct gamma_parameters *params); +- +-bool dce110_ipp_set_palette( +- struct input_pixel_processor *ipp, +- const struct dev_c_lut *palette, +- uint32_t start, +- uint32_t length, +- enum pixel_format surface_pixel_format); +- ++ struct ipp_prescale_params *params); + /* + * Helper functions to be resused in other ASICs + */ +diff --git a/drivers/gpu/drm/amd/dal/dc/dce110/dce110_ipp_gamma.c b/drivers/gpu/drm/amd/dal/dc/dce110/dce110_ipp_gamma.c +index fcf65f1..dc0ccbb 100644 +--- a/drivers/gpu/drm/amd/dal/dc/dce110/dce110_ipp_gamma.c ++++ b/drivers/gpu/drm/amd/dal/dc/dce110/dce110_ipp_gamma.c +@@ -41,35 +41,6 @@ enum { + MAX_INPUT_LUT_ENTRY = 256 + }; + +-/* CALCULATION OPERATIONS*/ +-static void convert_256_lut_entries_to_gxo_format( +- const struct gamma_ramp_rgb256x3x16 *lut, +- struct dev_c_lut16 *gamma) +-{ +- uint32_t i = 0; +- +- ASSERT(lut); +- ASSERT(gamma); +- +- do { +- gamma->red = lut->red[i]; +- gamma->green = lut->green[i]; +- gamma->blue = lut->blue[i]; +- +- ++gamma; +- ++i; +- } while (i != MAX_INPUT_LUT_ENTRY); +-} +- +-static void convert_udx_gamma_entries_to_gxo_format( +- const struct gamma_ramp_dxgi_1 *lut, +- struct dev_c_lut16 *gamma) +-{ +- /* TODO here we deal with DXGI gamma table, +- * originally, values was expressed as 'float', +- * now values expressed as 'dal_fixed20_12'. */ +-} +- + /*PROTOTYPE DECLARATIONS*/ + static void set_lut_inc( + struct dce110_ipp *ipp110, +@@ -85,111 +56,111 @@ static void program_white_offsets( + struct dce110_ipp *ipp110, + struct dev_c_lut16 *offset); + +-static void program_lut_gamma( +- struct dce110_ipp *ipp110, +- const struct dev_c_lut16 *gamma, +- const struct gamma_parameters *params); +- +-static void program_prescale( +- struct dce110_ipp *ipp110, +- enum pixel_format pixel_format); ++bool dce110_ipp_set_degamma( ++ struct input_pixel_processor *ipp, ++ enum ipp_degamma_mode mode) ++{ ++ struct dce110_ipp *ipp110 = TO_DCE110_IPP(ipp); + +-static void set_legacy_input_gamma_mode( +- struct dce110_ipp *ipp110, +- bool is_legacy); ++ uint32_t value = 0; + +-static bool set_legacy_input_gamma_ramp_rgb256x3x16( +- struct dce110_ipp *ipp110, +- const struct gamma_ramp *gamma_ramp, +- const struct gamma_parameters *params); ++ uint32_t degamma_type = (mode == IPP_DEGAMMA_MODE_sRGB) ? 1 : 0; + +-static bool set_legacy_input_gamma_ramp_dxgi1( +- struct dce110_ipp *ipp110, +- const struct gamma_ramp *gamma_ramp, +- const struct gamma_parameters *params); ++ set_reg_field_value( ++ value, ++ degamma_type, ++ DEGAMMA_CONTROL, ++ GRPH_DEGAMMA_MODE); + +-static bool set_default_gamma( +- struct dce110_ipp *ipp110, +- enum pixel_format surface_pixel_format); ++ set_reg_field_value( ++ value, ++ degamma_type, ++ DEGAMMA_CONTROL, ++ CURSOR_DEGAMMA_MODE); + +-static void set_degamma( +- struct dce110_ipp *ipp110, +- const struct gamma_parameters *params, +- bool force_bypass); ++ set_reg_field_value( ++ value, ++ degamma_type, ++ DEGAMMA_CONTROL, ++ CURSOR2_DEGAMMA_MODE); + +-bool dce110_ipp_set_legacy_input_gamma_ramp( +- struct input_pixel_processor *ipp, +- const struct gamma_ramp *gamma_ramp, +- const struct gamma_parameters *params) +-{ +- struct dce110_ipp *ipp110 = TO_DCE110_IPP(ipp); ++ dm_write_reg(ipp110->base.ctx, DCP_REG(mmDEGAMMA_CONTROL), value); + +- switch (gamma_ramp->type) { +- case GAMMA_RAMP_RBG256X3X16: +- return set_legacy_input_gamma_ramp_rgb256x3x16( +- ipp110, gamma_ramp, params); +- case GAMMA_RAMP_DXGI_1: +- return set_legacy_input_gamma_ramp_dxgi1( +- ipp110, gamma_ramp, params); +- default: +- ASSERT_CRITICAL(false); +- return false; +- } ++ return true; + } + +-bool dce110_ipp_set_palette( ++void dce110_ipp_program_prescale( + struct input_pixel_processor *ipp, +- const struct dev_c_lut *palette, +- uint32_t start, +- uint32_t length, +- enum pixel_format surface_pixel_format) ++ struct ipp_prescale_params *params) + { + struct dce110_ipp *ipp110 = TO_DCE110_IPP(ipp); +- uint32_t i; + +- if (((start + length) > MAX_INPUT_LUT_ENTRY) || (NULL == palette)) { +- BREAK_TO_DEBUGGER(); +- /* wrong input */ +- return false; +- } ++ uint32_t prescale_control = 0; ++ uint32_t prescale_value = 0; ++ uint32_t legacy_lut_control = 0; + +- for (i = start; i < start + length; i++) { +- ipp110->saved_palette[i] = palette[i]; +- ipp110->saved_palette[i] = palette[i]; +- ipp110->saved_palette[i] = palette[i]; +- } ++ prescale_control = dm_read_reg(ipp110->base.ctx, ++ DCP_REG(mmPRESCALE_GRPH_CONTROL)); + +- return set_default_gamma(ipp110, surface_pixel_format); +-} ++ if (params->mode != IPP_PRESCALE_MODE_BYPASS) { + +-bool dce110_ipp_set_degamma( +- struct input_pixel_processor *ipp, +- const struct gamma_parameters *params, +- bool force_bypass) +-{ +- struct dce110_ipp *ipp110 = TO_DCE110_IPP(ipp); ++ set_reg_field_value( ++ prescale_control, ++ 0, ++ PRESCALE_GRPH_CONTROL, ++ GRPH_PRESCALE_BYPASS); + +- set_degamma(ipp110, params, force_bypass); ++ /* ++ * If prescale is in use, then legacy lut should ++ * be bypassed ++ */ ++ legacy_lut_control = dm_read_reg(ipp110->base.ctx, ++ DCP_REG(mmINPUT_GAMMA_CONTROL)); + +- return true; +-} ++ set_reg_field_value( ++ legacy_lut_control, ++ 1, ++ INPUT_GAMMA_CONTROL, ++ GRPH_INPUT_GAMMA_MODE); + +-void dce110_ipp_program_prescale( +- struct input_pixel_processor *ipp, +- enum pixel_format pixel_format) +-{ +- struct dce110_ipp *ipp110 = TO_DCE110_IPP(ipp); ++ dm_write_reg(ipp110->base.ctx, ++ DCP_REG(mmINPUT_GAMMA_CONTROL), ++ legacy_lut_control); ++ } else { ++ set_reg_field_value( ++ prescale_control, ++ 1, ++ PRESCALE_GRPH_CONTROL, ++ GRPH_PRESCALE_BYPASS); ++ } + +- program_prescale(ipp110, pixel_format); +-} ++ set_reg_field_value( ++ prescale_value, ++ params->scale, ++ PRESCALE_VALUES_GRPH_R, ++ GRPH_PRESCALE_SCALE_R); + +-void dce110_ipp_set_legacy_input_gamma_mode( +- struct input_pixel_processor *ipp, +- bool is_legacy) +-{ +- struct dce110_ipp *ipp110 = TO_DCE110_IPP(ipp); ++ set_reg_field_value( ++ prescale_value, ++ params->bias, ++ PRESCALE_VALUES_GRPH_R, ++ GRPH_PRESCALE_BIAS_R); ++ ++ dm_write_reg(ipp110->base.ctx, ++ DCP_REG(mmPRESCALE_GRPH_CONTROL), ++ prescale_control); ++ ++ dm_write_reg(ipp110->base.ctx, ++ DCP_REG(mmPRESCALE_VALUES_GRPH_R), ++ prescale_value); ++ ++ dm_write_reg(ipp110->base.ctx, ++ DCP_REG(mmPRESCALE_VALUES_GRPH_G), ++ prescale_value); + +- set_legacy_input_gamma_mode(ipp110, is_legacy); ++ dm_write_reg(ipp110->base.ctx, ++ DCP_REG(mmPRESCALE_VALUES_GRPH_B), ++ prescale_value); + } + + static void set_lut_inc( +@@ -426,447 +397,3 @@ void dce110_helper_program_black_white_offset( + program_black_offsets(ipp110, &black_offset); + program_white_offsets(ipp110, &white_offset); + } +- +-static void program_lut_gamma( +- struct dce110_ipp *ipp110, +- const struct dev_c_lut16 *gamma, +- const struct gamma_parameters *params) +-{ +- uint32_t i = 0; +- uint32_t value = 0; +- uint32_t addr; +- +- { +- uint8_t max_tries = 10; +- uint8_t counter = 0; +- +- /* Power on LUT memory */ +- value = dm_read_reg( +- ipp110->base.ctx, DCP_REG(mmDCFE_MEM_PWR_CTRL)); +- +- set_reg_field_value( +- value, +- 1, +- DCFE_MEM_PWR_CTRL, +- DCP_REGAMMA_MEM_PWR_DIS); +- +- dm_write_reg( +- ipp110->base.ctx, DCP_REG(mmDCFE_MEM_PWR_CTRL), value); +- +- while (counter < max_tries) { +- value = +- dm_read_reg( +- ipp110->base.ctx, +- DCP_REG(mmDCFE_MEM_PWR_STATUS)); +- +- if (get_reg_field_value( +- value, +- DCFE_MEM_PWR_STATUS, +- DCP_REGAMMA_MEM_PWR_STATE) == 0) +- break; +- +- ++counter; +- } +- +- if (counter == max_tries) { +- dal_logger_write(ipp110->base.ctx->logger, +- LOG_MAJOR_WARNING, +- LOG_MINOR_COMPONENT_CONTROLLER, +- "%s: regamma lut was not powered on in a timely manner, programming still proceeds\n", +- __func__); +- } +- } +- +- dce110_helper_program_black_white_offset(ipp110, params->surface_pixel_format); +- +- dce110_helper_select_lut(ipp110); +- +- if (params->surface_pixel_format == PIXEL_FORMAT_INDEX8) { +- addr = DCP_REG(mmDC_LUT_SEQ_COLOR); +- +- do { +- struct dev_c_lut *index = +- ipp110->saved_palette + i; +- +- set_reg_field_value( +- value, +- gamma[index->red].red, +- DC_LUT_SEQ_COLOR, +- DC_LUT_SEQ_COLOR); +- dm_write_reg(ipp110->base.ctx, addr, value); +- +- +- set_reg_field_value( +- value, +- gamma[index->green].green, +- DC_LUT_SEQ_COLOR, +- DC_LUT_SEQ_COLOR); +- dm_write_reg(ipp110->base.ctx, addr, value); +- +- +- set_reg_field_value( +- value, +- gamma[index->blue].blue, +- DC_LUT_SEQ_COLOR, +- DC_LUT_SEQ_COLOR); +- dm_write_reg(ipp110->base.ctx, addr, value); +- +- ++i; +- } while (i != RGB_256X3X16); +- } else { +- addr = DCP_REG(mmDC_LUT_SEQ_COLOR); +- +- do { +- set_reg_field_value( +- value, +- gamma[i].red, +- DC_LUT_SEQ_COLOR, +- DC_LUT_SEQ_COLOR); +- dm_write_reg(ipp110->base.ctx, addr, value); +- +- +- set_reg_field_value( +- value, +- gamma[i].green, +- DC_LUT_SEQ_COLOR, +- DC_LUT_SEQ_COLOR); +- dm_write_reg(ipp110->base.ctx, addr, value); +- +- +- set_reg_field_value( +- value, +- gamma[i].blue, +- DC_LUT_SEQ_COLOR, +- DC_LUT_SEQ_COLOR); +- dm_write_reg(ipp110->base.ctx, addr, value); +- +- ++i; +- } while (i != RGB_256X3X16); +- } +- +- /* we are done with DCP LUT memory; re-enable low power mode */ +- value = dm_read_reg(ipp110->base.ctx, DCP_REG(mmDCFE_MEM_PWR_CTRL)); +- +- set_reg_field_value( +- value, +- 0, +- DCFE_MEM_PWR_CTRL, +- DCP_REGAMMA_MEM_PWR_DIS); +- +- dm_write_reg(ipp110->base.ctx, DCP_REG(mmDCFE_MEM_PWR_CTRL), value); +-} +- +-static void program_prescale( +- struct dce110_ipp *ipp110, +- enum pixel_format pixel_format) +-{ +- uint32_t prescale_control; +- uint32_t prescale_values_grph_r = 0; +- uint32_t prescale_values_grph_g = 0; +- uint32_t prescale_values_grph_b = 0; +- +- uint32_t prescale_num; +- uint32_t prescale_denom = 1; +- uint16_t prescale_hw; +- uint32_t bias_num = 0; +- uint32_t bias_denom = 1; +- uint16_t bias_hw; +- +- const uint32_t addr_control = DCP_REG(mmPRESCALE_GRPH_CONTROL); +- +- prescale_control = dm_read_reg(ipp110->base.ctx, addr_control); +- +- set_reg_field_value( +- prescale_control, +- 0, +- PRESCALE_GRPH_CONTROL, +- GRPH_PRESCALE_BYPASS); +- +- switch (pixel_format) { +- case PIXEL_FORMAT_RGB565: +- prescale_num = 64; +- prescale_denom = 63; +- break; +- +- case PIXEL_FORMAT_ARGB8888: +- /* This function should only be called when using regamma +- * and bypassing legacy INPUT GAMMA LUT (function name is +- * misleading) +- */ +- prescale_num = 256; +- prescale_denom = 255; +- break; +- +- case PIXEL_FORMAT_ARGB2101010: +- prescale_num = 1024; +- prescale_denom = 1023; +- break; +- +- case PIXEL_FORMAT_ARGB2101010_XRBIAS: +- prescale_num = 1024; +- prescale_denom = 510; +- bias_num = 384; +- bias_denom = 1024; +- break; +- +- case PIXEL_FORMAT_FP16: +- prescale_num = 1; +- break; +- +- default: +- prescale_num = 1; +- +- set_reg_field_value( +- prescale_control, +- 1, +- PRESCALE_GRPH_CONTROL, +- GRPH_PRESCALE_BYPASS); +- } +- +- prescale_hw = fixed_point_to_int_frac( +- dal_fixed31_32_from_fraction(prescale_num, prescale_denom), +- 2, 13); +- +- bias_hw = fixed_point_to_int_frac( +- dal_fixed31_32_from_fraction(bias_num, bias_denom), +- 2, 13); +- +- +- set_reg_field_value( +- prescale_values_grph_r, +- prescale_hw, +- PRESCALE_VALUES_GRPH_R, +- GRPH_PRESCALE_SCALE_R); +- +- set_reg_field_value( +- prescale_values_grph_r, +- bias_hw, +- PRESCALE_VALUES_GRPH_R, +- GRPH_PRESCALE_BIAS_R); +- +- +- set_reg_field_value( +- prescale_values_grph_g, +- prescale_hw, +- PRESCALE_VALUES_GRPH_G, +- GRPH_PRESCALE_SCALE_G); +- +- set_reg_field_value( +- prescale_values_grph_g, +- bias_hw, +- PRESCALE_VALUES_GRPH_G, +- GRPH_PRESCALE_BIAS_G); +- +- +- set_reg_field_value( +- prescale_values_grph_b, +- prescale_hw, +- PRESCALE_VALUES_GRPH_B, +- GRPH_PRESCALE_SCALE_B); +- +- set_reg_field_value( +- prescale_values_grph_b, +- bias_hw, +- PRESCALE_VALUES_GRPH_B, +- GRPH_PRESCALE_BIAS_B); +- +- dm_write_reg(ipp110->base.ctx, +- addr_control, prescale_control); +- +- { +- dm_write_reg(ipp110->base.ctx, +- DCP_REG(mmPRESCALE_VALUES_GRPH_R), +- prescale_values_grph_r); +- } +- +- { +- dm_write_reg(ipp110->base.ctx, +- DCP_REG(mmPRESCALE_VALUES_GRPH_G), +- prescale_values_grph_g); +- } +- +- { +- dm_write_reg(ipp110->base.ctx, +- DCP_REG(mmPRESCALE_VALUES_GRPH_B), +- prescale_values_grph_b); +- } +-} +- +-static void set_legacy_input_gamma_mode( +- struct dce110_ipp *ipp110, +- bool is_legacy) +-{ +- const uint32_t addr = DCP_REG(mmINPUT_GAMMA_CONTROL); +- uint32_t value = dm_read_reg(ipp110->base.ctx, addr); +- +- set_reg_field_value( +- value, +- !is_legacy, +- INPUT_GAMMA_CONTROL, +- GRPH_INPUT_GAMMA_MODE); +- +- dm_write_reg(ipp110->base.ctx, addr, value); +-} +- +-static bool set_legacy_input_gamma_ramp_rgb256x3x16( +- struct dce110_ipp *ipp110, +- const struct gamma_ramp *gamma_ramp, +- const struct gamma_parameters *params) +-{ +- struct dev_c_lut16 *gamma16 = +- dm_alloc( +- ipp110->base.ctx, +- sizeof(struct dev_c_lut16) * MAX_INPUT_LUT_ENTRY); +- +- if (!gamma16) +- return false; +- +- convert_256_lut_entries_to_gxo_format( +- &gamma_ramp->gamma_ramp_rgb256x3x16, gamma16); +- +- if ((params->surface_pixel_format != PIXEL_FORMAT_ARGB2101010) && +- (params->surface_pixel_format != +- PIXEL_FORMAT_ARGB2101010_XRBIAS) && +- (params->surface_pixel_format != PIXEL_FORMAT_FP16)) { +- program_lut_gamma(ipp110, gamma16, params); +- dm_free(ipp110->base.ctx, gamma16); +- return true; +- } +- +- /* TODO process DirectX-specific formats*/ +- dm_free(ipp110->base.ctx, gamma16); +- return false; +-} +- +-static bool set_legacy_input_gamma_ramp_dxgi1( +- struct dce110_ipp *ipp110, +- const struct gamma_ramp *gamma_ramp, +- const struct gamma_parameters *params) +-{ +- struct dev_c_lut16 *gamma16 = +- dm_alloc( +- ipp110->base.ctx, +- sizeof(struct dev_c_lut16) * MAX_INPUT_LUT_ENTRY); +- +- if (!gamma16) +- return false; +- +- convert_udx_gamma_entries_to_gxo_format( +- &gamma_ramp->gamma_ramp_dxgi1, gamma16); +- +- if ((params->surface_pixel_format != PIXEL_FORMAT_ARGB2101010) && +- (params->surface_pixel_format != +- PIXEL_FORMAT_ARGB2101010_XRBIAS) && +- (params->surface_pixel_format != PIXEL_FORMAT_FP16)) { +- program_lut_gamma(ipp110, gamma16, params); +- dm_free(ipp110->base.ctx, gamma16); +- return true; +- } +- +- /* TODO process DirectX-specific formats*/ +- dm_free(ipp110->base.ctx, gamma16); +- return false; +-} +- +-static bool set_default_gamma( +- struct dce110_ipp *ipp110, +- enum pixel_format surface_pixel_format) +-{ +- uint32_t i; +- +- struct dev_c_lut16 *gamma16 = NULL; +- struct gamma_parameters *params = NULL; +- +- gamma16 = dm_alloc( +- ipp110->base.ctx, +- sizeof(struct dev_c_lut16) * MAX_INPUT_LUT_ENTRY); +- +- if (!gamma16) +- return false; +- +- params = dm_alloc(ipp110->base.ctx, sizeof(*params)); +- +- if (!params) { +- dm_free(ipp110->base.ctx, gamma16); +- return false; +- } +- +- for (i = 0; i < MAX_INPUT_LUT_ENTRY; i++) { +- gamma16[i].red = gamma16[i].green = +- gamma16[i].blue = (uint16_t) (i << 8); +- } +- +- params->surface_pixel_format = surface_pixel_format; +- params->regamma_adjust_type = GRAPHICS_REGAMMA_ADJUST_HW; +- params->degamma_adjust_type = GRAPHICS_DEGAMMA_ADJUST_HW; +- params->selected_gamma_lut = GRAPHICS_GAMMA_LUT_REGAMMA; +- params->disable_adjustments = false; +- +- params->regamma.features.value = 0; +- +- params->regamma.features.bits.GAMMA_RAMP_ARRAY = 0; +- params->regamma.features.bits.GRAPHICS_DEGAMMA_SRGB = 1; +- params->regamma.features.bits.OVERLAY_DEGAMMA_SRGB = 1; +- +- for (i = 0; i < 3; i++) { +- params->regamma.gamma_coeff.a0[i] = 31308; +- params->regamma.gamma_coeff.a1[i] = 12920; +- params->regamma.gamma_coeff.a2[i] = 55; +- params->regamma.gamma_coeff.a3[i] = 55; +- params->regamma.gamma_coeff.gamma[i] = 2400; +- +- } +- +- program_lut_gamma(ipp110, gamma16, params); +- +- dm_free(ipp110->base.ctx, gamma16); +- dm_free(ipp110->base.ctx, params); +- +- return true; +-} +- +-static void set_degamma( +- struct dce110_ipp *ipp110, +- const struct gamma_parameters *params, +- bool force_bypass) +-{ +- uint32_t value; +- const uint32_t addr = DCP_REG(mmDEGAMMA_CONTROL); +- uint32_t degamma_type = +- params->regamma.features.bits.GRAPHICS_DEGAMMA_SRGB == 1 ? +- 1 : 2; +- +- value = dm_read_reg(ipp110->base.ctx, addr); +- +- /* if by pass - no degamma +- * when legacy and regamma LUT's we do degamma */ +- if (params->degamma_adjust_type == GRAPHICS_DEGAMMA_ADJUST_BYPASS || +- (params->surface_pixel_format == PIXEL_FORMAT_FP16 && +- params->selected_gamma_lut == +- GRAPHICS_GAMMA_LUT_REGAMMA)) +- degamma_type = 0; +- +- if (force_bypass) +- degamma_type = 0; +- +- set_reg_field_value( +- value, +- degamma_type, +- DEGAMMA_CONTROL, +- GRPH_DEGAMMA_MODE); +- +- set_reg_field_value( +- value, +- degamma_type, +- DEGAMMA_CONTROL, +- CURSOR_DEGAMMA_MODE); +- +- set_reg_field_value( +- value, +- degamma_type, +- DEGAMMA_CONTROL, +- CURSOR2_DEGAMMA_MODE); +- +- dm_write_reg(ipp110->base.ctx, addr, value); +-} +- +diff --git a/drivers/gpu/drm/amd/dal/dc/dce110/dce110_opp.c b/drivers/gpu/drm/amd/dal/dc/dce110/dce110_opp.c +index acb405e..394f187 100644 +--- a/drivers/gpu/drm/amd/dal/dc/dce110/dce110_opp.c ++++ b/drivers/gpu/drm/amd/dal/dc/dce110/dce110_opp.c +@@ -38,55 +38,11 @@ enum { + MAX_NUMBER_OF_ENTRIES = 256 + }; + +-static void build_evenly_distributed_points( +- struct gamma_pixel *points, +- uint32_t numberof_points, +- struct fixed31_32 max_value, +- struct fixed31_32 divider1, +- struct fixed31_32 divider2, +- struct fixed31_32 divider3) +-{ +- struct gamma_pixel *p = points; +- struct gamma_pixel *p_last = p + numberof_points - 1; +- +- uint32_t i = 0; +- +- do { +- struct fixed31_32 value = dal_fixed31_32_div_int( +- dal_fixed31_32_mul_int(max_value, i), +- numberof_points - 1); +- +- p->r = value; +- p->g = value; +- p->b = value; +- +- ++p; +- ++i; +- } while (i != numberof_points); +- +- p->r = dal_fixed31_32_div(p_last->r, divider1); +- p->g = dal_fixed31_32_div(p_last->g, divider1); +- p->b = dal_fixed31_32_div(p_last->b, divider1); +- +- ++p; +- +- p->r = dal_fixed31_32_div(p_last->r, divider2); +- p->g = dal_fixed31_32_div(p_last->g, divider2); +- p->b = dal_fixed31_32_div(p_last->b, divider2); +- +- ++p; +- +- p->r = dal_fixed31_32_div(p_last->r, divider3); +- p->g = dal_fixed31_32_div(p_last->g, divider3); +- p->b = dal_fixed31_32_div(p_last->b, divider3); +-} +- + /*****************************************/ + /* Constructor, Destructor */ + /*****************************************/ + + struct opp_funcs funcs = { +- .opp_map_legacy_and_regamma_hw_to_x_user = dce110_opp_map_legacy_and_regamma_hw_to_x_user, + .opp_power_on_regamma_lut = dce110_opp_power_on_regamma_lut, + .opp_program_bit_depth_reduction = dce110_opp_program_bit_depth_reduction, + .opp_program_clamping_and_pixel_encoding = dce110_opp_program_clamping_and_pixel_encoding, +@@ -101,7 +57,6 @@ bool dce110_opp_construct(struct dce110_opp *opp110, + uint32_t inst, + const struct dce110_opp_reg_offsets *offsets) + { +- + opp110->base.funcs = &funcs; + + opp110->base.ctx = ctx; +@@ -110,162 +65,11 @@ bool dce110_opp_construct(struct dce110_opp *opp110, + + opp110->offsets = *offsets; + +- opp110->regamma.hw_points_num = 128; +- opp110->regamma.coordinates_x = NULL; +- opp110->regamma.rgb_resulted = NULL; +- opp110->regamma.rgb_regamma = NULL; +- opp110->regamma.coeff128 = NULL; +- opp110->regamma.coeff128_oem = NULL; +- opp110->regamma.coeff128_dx = NULL; +- opp110->regamma.axis_x_256 = NULL; +- opp110->regamma.axis_x_1025 = NULL; +- opp110->regamma.rgb_oem = NULL; +- opp110->regamma.rgb_user = NULL; +- opp110->regamma.extra_points = 3; +- opp110->regamma.use_half_points = false; +- opp110->regamma.x_max1 = dal_fixed31_32_one; +- opp110->regamma.x_max2 = dal_fixed31_32_from_int(2); +- opp110->regamma.x_min = dal_fixed31_32_zero; +- opp110->regamma.divider1 = dal_fixed31_32_from_fraction(3, 2); +- opp110->regamma.divider2 = dal_fixed31_32_from_int(2); +- opp110->regamma.divider3 = dal_fixed31_32_from_fraction(5, 2); +- +- opp110->regamma.rgb_user = dm_alloc( +- ctx, +- sizeof(struct pwl_float_data) * +- (DX_GAMMA_RAMP_MAX + opp110->regamma.extra_points)); +- if (!opp110->regamma.rgb_user) +- goto failure_1; +- +- opp110->regamma.rgb_oem = dm_alloc( +- ctx, +- sizeof(struct pwl_float_data) * +- (DX_GAMMA_RAMP_MAX + opp110->regamma.extra_points)); +- if (!opp110->regamma.rgb_oem) +- goto failure_2; +- +- opp110->regamma.rgb_resulted = dm_alloc( +- ctx, +- sizeof(struct pwl_result_data) * +- (MAX_NUMBER_OF_ENTRIES + opp110->regamma.extra_points)); +- if (!opp110->regamma.rgb_resulted) +- goto failure_3; +- +- opp110->regamma.rgb_regamma = dm_alloc( +- ctx, +- sizeof(struct pwl_float_data_ex) * +- (MAX_NUMBER_OF_ENTRIES + opp110->regamma.extra_points)); +- if (!opp110->regamma.rgb_regamma) +- goto failure_4; +- +- opp110->regamma.coordinates_x = dm_alloc( +- ctx, +- sizeof(struct hw_x_point) * +- (MAX_NUMBER_OF_ENTRIES + opp110->regamma.extra_points)); +- if (!opp110->regamma.coordinates_x) +- goto failure_5; +- +- opp110->regamma.axis_x_256 = dm_alloc( +- ctx, +- sizeof(struct gamma_pixel) * +- (MAX_LUT_ENTRY + opp110->regamma.extra_points)); +- if (!opp110->regamma.axis_x_256) +- goto failure_6; +- +- opp110->regamma.axis_x_1025 = dm_alloc( +- ctx, +- sizeof(struct gamma_pixel) * +- (DX_GAMMA_RAMP_MAX + opp110->regamma.extra_points)); +- if (!opp110->regamma.axis_x_1025) +- goto failure_7; +- +- opp110->regamma.coeff128 = dm_alloc( +- ctx, +- sizeof(struct pixel_gamma_point) * +- (MAX_NUMBER_OF_ENTRIES + opp110->regamma.extra_points)); +- if (!opp110->regamma.coeff128) +- goto failure_8; +- +- opp110->regamma.coeff128_oem = dm_alloc( +- ctx, +- sizeof(struct pixel_gamma_point) * +- (MAX_NUMBER_OF_ENTRIES + opp110->regamma.extra_points)); +- if (!opp110->regamma.coeff128_oem) +- goto failure_9; +- +- opp110->regamma.coeff128_dx = dm_alloc( +- ctx, +- sizeof(struct pixel_gamma_point) * +- (MAX_NUMBER_OF_ENTRIES + opp110->regamma.extra_points)); +- if (!opp110->regamma.coeff128_dx) +- goto failure_10; +- +- /* init palette */ +- { +- uint32_t i = 0; +- +- do { +- opp110->regamma.saved_palette[i].red = (uint8_t)i; +- opp110->regamma.saved_palette[i].green = (uint8_t)i; +- opp110->regamma.saved_palette[i].blue = (uint8_t)i; +- +- ++i; +- } while (i != MAX_LUT_ENTRY); +- } +- +- build_evenly_distributed_points( +- opp110->regamma.axis_x_256, +- MAX_LUT_ENTRY, +- opp110->regamma.x_max1, +- opp110->regamma.divider1, +- opp110->regamma.divider2, +- opp110->regamma.divider3); +- +- build_evenly_distributed_points( +- opp110->regamma.axis_x_1025, +- DX_GAMMA_RAMP_MAX, +- opp110->regamma.x_max1, +- opp110->regamma.divider1, +- opp110->regamma.divider2, +- opp110->regamma.divider3); +- +- return true; +- +-failure_10: +- dm_free(ctx, opp110->regamma.coeff128_oem); +-failure_9: +- dm_free(ctx, opp110->regamma.coeff128); +-failure_8: +- dm_free(ctx, opp110->regamma.axis_x_1025); +-failure_7: +- dm_free(ctx, opp110->regamma.axis_x_256); +-failure_6: +- dm_free(ctx, opp110->regamma.coordinates_x); +-failure_5: +- dm_free(ctx, opp110->regamma.rgb_regamma); +-failure_4: +- dm_free(ctx, opp110->regamma.rgb_resulted); +-failure_3: +- dm_free(ctx, opp110->regamma.rgb_oem); +-failure_2: +- dm_free(ctx, opp110->regamma.rgb_user); +-failure_1: +- + return true; + } + + void dce110_opp_destroy(struct output_pixel_processor **opp) + { +- dm_free((*opp)->ctx, FROM_DCE11_OPP(*opp)->regamma.coeff128_dx); +- dm_free((*opp)->ctx, FROM_DCE11_OPP(*opp)->regamma.coeff128_oem); +- dm_free((*opp)->ctx, FROM_DCE11_OPP(*opp)->regamma.coeff128); +- dm_free((*opp)->ctx, FROM_DCE11_OPP(*opp)->regamma.axis_x_1025); +- dm_free((*opp)->ctx, FROM_DCE11_OPP(*opp)->regamma.axis_x_256); +- dm_free((*opp)->ctx, FROM_DCE11_OPP(*opp)->regamma.coordinates_x); +- dm_free((*opp)->ctx, FROM_DCE11_OPP(*opp)->regamma.rgb_regamma); +- dm_free((*opp)->ctx, FROM_DCE11_OPP(*opp)->regamma.rgb_resulted); +- dm_free((*opp)->ctx, FROM_DCE11_OPP(*opp)->regamma.rgb_oem); +- dm_free((*opp)->ctx, FROM_DCE11_OPP(*opp)->regamma.rgb_user); + dm_free((*opp)->ctx, FROM_DCE11_OPP(*opp)); + *opp = NULL; + } +diff --git a/drivers/gpu/drm/amd/dal/dc/dce110/dce110_opp.h b/drivers/gpu/drm/amd/dal/dc/dce110/dce110_opp.h +index e53eb74..3460e18 100644 +--- a/drivers/gpu/drm/amd/dal/dc/dce110/dce110_opp.h ++++ b/drivers/gpu/drm/amd/dal/dc/dce110/dce110_opp.h +@@ -27,7 +27,9 @@ + + #include "dc_types.h" + #include "inc/opp.h" +-#include "gamma_types.h" ++#include "core_types.h" ++ ++#include "gamma_types.h" /* decprecated */ + + struct gamma_parameters; + +@@ -107,14 +109,11 @@ void dce110_opp_power_on_regamma_lut( + + bool dce110_opp_set_regamma( + struct output_pixel_processor *opp, +- const struct gamma_ramp *ramp, +- const struct gamma_parameters *params, +- bool force_bypass); ++ const struct regamma_params *params); + +-bool dce110_opp_map_legacy_and_regamma_hw_to_x_user( ++void dce110_opp_power_on_regamma_lut( + struct output_pixel_processor *opp, +- const struct gamma_ramp *gamma_ramp, +- const struct gamma_parameters *params); ++ bool power_on); + + void dce110_opp_set_csc_adjustment( + struct output_pixel_processor *opp, +diff --git a/drivers/gpu/drm/amd/dal/dc/dce110/dce110_opp_regamma.c b/drivers/gpu/drm/amd/dal/dc/dce110/dce110_opp_regamma.c +index 32cf57d..f7a4bc2 100644 +--- a/drivers/gpu/drm/amd/dal/dc/dce110/dce110_opp_regamma.c ++++ b/drivers/gpu/drm/amd/dal/dc/dce110/dce110_opp_regamma.c +@@ -44,1724 +44,6 @@ enum { + + }; + +-struct curve_config { +- uint32_t offset; +- int8_t segments[MAX_REGIONS_NUMBER]; +- int8_t begin; +-}; +- +-/* BASE */ +-static bool find_software_points( +- struct dce110_opp *opp110, +- struct fixed31_32 hw_point, +- enum channel_name channel, +- uint32_t *index_to_start, +- uint32_t *index_left, +- uint32_t *index_right, +- enum hw_point_position *pos) +-{ +- const uint32_t max_number = +- RGB_256X3X16 + opp110->regamma.extra_points; +- +- struct fixed31_32 left, right; +- +- uint32_t i = *index_to_start; +- +- while (i < max_number) { +- if (channel == CHANNEL_NAME_RED) { +- left = opp110-> +- regamma.axis_x_256[i].r; +- +- if (i < max_number - 1) +- right = opp110-> +- regamma.axis_x_256[i + 1].r; +- else +- right = opp110-> +- regamma.axis_x_256[max_number - 1].r; +- } else if (channel == CHANNEL_NAME_GREEN) { +- left = opp110->regamma.axis_x_256[i].g; +- +- if (i < max_number - 1) +- right = opp110-> +- regamma.axis_x_256[i + 1].g; +- else +- right = opp110-> +- regamma.axis_x_256[max_number - 1].g; +- } else { +- left = opp110->regamma.axis_x_256[i].b; +- +- if (i < max_number - 1) +- right = opp110-> +- regamma.axis_x_256[i + 1].b; +- else +- right = opp110-> +- regamma.axis_x_256[max_number - 1].b; +- } +- +- if (dal_fixed31_32_le(left, hw_point) && +- dal_fixed31_32_le(hw_point, right)) { +- *index_to_start = i; +- *index_left = i; +- +- if (i < max_number - 1) +- *index_right = i + 1; +- else +- *index_right = max_number - 1; +- +- *pos = HW_POINT_POSITION_MIDDLE; +- +- return true; +- } else if ((i == *index_to_start) && +- dal_fixed31_32_le(hw_point, left)) { +- *index_to_start = i; +- *index_left = i; +- *index_right = i; +- +- *pos = HW_POINT_POSITION_LEFT; +- +- return true; +- } else if ((i == max_number - 1) && +- dal_fixed31_32_le(right, hw_point)) { +- *index_to_start = i; +- *index_left = i; +- *index_right = i; +- +- *pos = HW_POINT_POSITION_RIGHT; +- +- return true; +- } +- +- ++i; +- } +- +- return false; +-} +- +-static bool find_software_points_dx( +- struct dce110_opp *opp110, +- struct fixed31_32 hw_point, +- enum channel_name channel, +- uint32_t *index_to_start, +- uint32_t *index_left, +- uint32_t *index_right, +- enum hw_point_position *pos) +-{ +- const uint32_t max_number = DX_GAMMA_RAMP_MAX + +- opp110->regamma.extra_points; +- +- struct fixed31_32 left, right; +- +- uint32_t i = *index_to_start; +- +- while (i < max_number) { +- if (channel == CHANNEL_NAME_RED) { +- left = opp110->regamma.axis_x_1025[i].r; +- +- if (i < DX_GAMMA_RAMP_MAX - 1) +- right = opp110-> +- regamma.axis_x_1025[i + 1].r; +- else +- right = opp110-> +- regamma.axis_x_1025[DX_GAMMA_RAMP_MAX-1].r; +- } else if (channel == CHANNEL_NAME_GREEN) { +- left = opp110->regamma.axis_x_1025[i].g; +- +- if (i < DX_GAMMA_RAMP_MAX - 1) +- right = opp110-> +- regamma.axis_x_1025[i + 1].g; +- else +- right = opp110-> +- regamma.axis_x_1025[DX_GAMMA_RAMP_MAX-1].g; +- } else { +- left = opp110->regamma.axis_x_1025[i].b; +- +- if (i < DX_GAMMA_RAMP_MAX - 1) +- right = opp110-> +- regamma.axis_x_1025[i + 1].b; +- else +- right = opp110-> +- regamma.axis_x_1025[DX_GAMMA_RAMP_MAX-1].b; +- } +- +- if (dal_fixed31_32_le(left, hw_point) && +- dal_fixed31_32_le(hw_point, right)) { +- *index_to_start = i; +- *index_left = i; +- +- if (i < DX_GAMMA_RAMP_MAX - 1) +- *index_right = i + 1; +- else +- *index_right = DX_GAMMA_RAMP_MAX - 1; +- +- *pos = HW_POINT_POSITION_MIDDLE; +- +- return true; +- } else if ((i == *index_to_start) && +- dal_fixed31_32_le(hw_point, left)) { +- *index_to_start = i; +- *index_left = i; +- *index_right = i; +- +- *pos = HW_POINT_POSITION_LEFT; +- +- return true; +- } else if ((i == max_number - 1) && +- dal_fixed31_32_le(right, hw_point)) { +- *index_to_start = i; +- *index_left = i; +- *index_right = i; +- +- *pos = HW_POINT_POSITION_RIGHT; +- +- return true; +- } +- +- ++i; +- } +- +- return false; +-} +- +-static bool build_custom_gamma_mapping_coefficients_worker( +- struct dce110_opp *opp110, +- struct pixel_gamma_point *coeff, +- enum channel_name channel, +- uint32_t number_of_points, +- enum pixel_format pixel_format) +-{ +- uint32_t i = 0; +- +- while (i <= number_of_points) { +- struct fixed31_32 coord_x; +- +- uint32_t index_to_start = 0; +- uint32_t index_left = 0; +- uint32_t index_right = 0; +- +- enum hw_point_position hw_pos; +- +- struct gamma_point *point; +- +- struct fixed31_32 left_pos; +- struct fixed31_32 right_pos; +- +- if (pixel_format == PIXEL_FORMAT_FP16) +- coord_x = opp110-> +- regamma.coordinates_x[i].adjusted_x; +- else if (channel == CHANNEL_NAME_RED) +- coord_x = opp110-> +- regamma.coordinates_x[i].regamma_y_red; +- else if (channel == CHANNEL_NAME_GREEN) +- coord_x = opp110-> +- regamma.coordinates_x[i].regamma_y_green; +- else +- coord_x = opp110-> +- regamma.coordinates_x[i].regamma_y_blue; +- +- if (!find_software_points( +- opp110, coord_x, channel, +- &index_to_start, &index_left, &index_right, &hw_pos)) { +- BREAK_TO_DEBUGGER(); +- return false; +- } +- +- if (index_left >= RGB_256X3X16 + +- opp110->regamma.extra_points) { +- BREAK_TO_DEBUGGER(); +- return false; +- } +- +- if (index_right >= RGB_256X3X16 + +- opp110->regamma.extra_points) { +- BREAK_TO_DEBUGGER(); +- return false; +- } +- +- if (channel == CHANNEL_NAME_RED) { +- point = &coeff[i].r; +- +- left_pos = opp110-> +- regamma.axis_x_256[index_left].r; +- right_pos = opp110-> +- regamma.axis_x_256[index_right].r; +- } else if (channel == CHANNEL_NAME_GREEN) { +- point = &coeff[i].g; +- +- left_pos = opp110-> +- regamma.axis_x_256[index_left].g; +- right_pos = opp110-> +- regamma.axis_x_256[index_right].g; +- } else { +- point = &coeff[i].b; +- +- left_pos = opp110-> +- regamma.axis_x_256[index_left].b; +- right_pos = opp110-> +- regamma.axis_x_256[index_right].b; +- } +- +- if (hw_pos == HW_POINT_POSITION_MIDDLE) +- point->coeff = dal_fixed31_32_div( +- dal_fixed31_32_sub( +- coord_x, +- left_pos), +- dal_fixed31_32_sub( +- right_pos, +- left_pos)); +- else if (hw_pos == HW_POINT_POSITION_LEFT) +- point->coeff = opp110->regamma.x_min; +- else if (hw_pos == HW_POINT_POSITION_RIGHT) +- point->coeff = opp110->regamma.x_max2; +- else { +- BREAK_TO_DEBUGGER(); +- return false; +- } +- +- point->left_index = index_left; +- point->right_index = index_right; +- point->pos = hw_pos; +- +- ++i; +- } +- +- return true; +-} +- +-static inline bool build_custom_gamma_mapping_coefficients( +- struct dce110_opp *opp110, +- enum channel_name channel, +- uint32_t number_of_points, +- enum pixel_format pixel_format) +-{ +- return build_custom_gamma_mapping_coefficients_worker( +- opp110, opp110->regamma.coeff128, channel, +- number_of_points, pixel_format); +-} +- +-static inline bool build_oem_custom_gamma_mapping_coefficients( +- struct dce110_opp *opp110, +- enum channel_name channel, +- uint32_t number_of_points, +- enum pixel_format pixel_format) +-{ +- return build_custom_gamma_mapping_coefficients_worker( +- opp110, opp110->regamma.coeff128_oem, channel, +- number_of_points, pixel_format); +-} +- +-static bool build_custom_dx_gamma_mapping_coefficients( +- struct dce110_opp *opp110, +- enum channel_name channel, +- uint32_t number_of_points, +- enum pixel_format pixel_format) +-{ +- uint32_t i = 0; +- +- while (i <= number_of_points) { +- struct fixed31_32 coord_x; +- +- uint32_t index_to_start = 0; +- uint32_t index_left = 0; +- uint32_t index_right = 0; +- +- enum hw_point_position hw_pos; +- +- struct gamma_point *point; +- +- struct fixed31_32 left_pos; +- struct fixed31_32 right_pos; +- +- if (pixel_format == PIXEL_FORMAT_FP16) +- coord_x = opp110-> +- regamma.coordinates_x[i].adjusted_x; +- else if (channel == CHANNEL_NAME_RED) +- coord_x = opp110-> +- regamma.coordinates_x[i].regamma_y_red; +- else if (channel == CHANNEL_NAME_GREEN) +- coord_x = opp110-> +- regamma.coordinates_x[i].regamma_y_green; +- else +- coord_x = opp110-> +- regamma.coordinates_x[i].regamma_y_blue; +- +- if (!find_software_points_dx( +- opp110, coord_x, channel, +- &index_to_start, &index_left, &index_right, &hw_pos)) { +- BREAK_TO_DEBUGGER(); +- return false; +- } +- +- if (index_left >= DX_GAMMA_RAMP_MAX + +- opp110->regamma.extra_points) { +- BREAK_TO_DEBUGGER(); +- return false; +- } +- +- if (index_right >= DX_GAMMA_RAMP_MAX + +- opp110->regamma.extra_points) { +- BREAK_TO_DEBUGGER(); +- return false; +- } +- +- if (channel == CHANNEL_NAME_RED) { +- point = &opp110->regamma.coeff128_dx[i].r; +- +- left_pos = opp110-> +- regamma.axis_x_1025[index_left].r; +- right_pos = opp110-> +- regamma.axis_x_1025[index_right].r; +- } else if (channel == CHANNEL_NAME_GREEN) { +- point = &opp110->regamma.coeff128_dx[i].g; +- +- left_pos = opp110-> +- regamma.axis_x_1025[index_left].g; +- right_pos = opp110-> +- regamma.axis_x_1025[index_right].g; +- } else { +- point = &opp110->regamma.coeff128_dx[i].b; +- +- left_pos = opp110-> +- regamma.axis_x_1025[index_left].b; +- right_pos = opp110-> +- regamma.axis_x_1025[index_right].b; +- } +- +- if (hw_pos == HW_POINT_POSITION_MIDDLE) +- point->coeff = dal_fixed31_32_div( +- dal_fixed31_32_sub( +- coord_x, +- left_pos), +- dal_fixed31_32_sub( +- right_pos, +- left_pos)); +- else if (hw_pos == HW_POINT_POSITION_LEFT) +- point->coeff = opp110->regamma.x_min; +- else if (hw_pos == HW_POINT_POSITION_RIGHT) +- point->coeff = opp110->regamma.x_max2; +- else { +- BREAK_TO_DEBUGGER(); +- return false; +- } +- +- point->left_index = index_left; +- point->right_index = index_right; +- point->pos = hw_pos; +- +- ++i; +- } +- +- return true; +-} +- +-static struct fixed31_32 calculate_mapped_value( +- struct dce110_opp *opp110, +- struct pwl_float_data *rgb, +- const struct pixel_gamma_point *coeff, +- enum channel_name channel, +- uint32_t max_index) +-{ +- const struct gamma_point *point; +- +- struct fixed31_32 result; +- +- if (channel == CHANNEL_NAME_RED) +- point = &coeff->r; +- else if (channel == CHANNEL_NAME_GREEN) +- point = &coeff->g; +- else +- point = &coeff->b; +- +- if ((point->left_index < 0) || (point->left_index > max_index)) { +- BREAK_TO_DEBUGGER(); +- return dal_fixed31_32_zero; +- } +- +- if ((point->right_index < 0) || (point->right_index > max_index)) { +- BREAK_TO_DEBUGGER(); +- return dal_fixed31_32_zero; +- } +- +- if (point->pos == HW_POINT_POSITION_MIDDLE) +- if (channel == CHANNEL_NAME_RED) +- result = dal_fixed31_32_add( +- dal_fixed31_32_mul( +- point->coeff, +- dal_fixed31_32_sub( +- rgb[point->right_index].r, +- rgb[point->left_index].r)), +- rgb[point->left_index].r); +- else if (channel == CHANNEL_NAME_GREEN) +- result = dal_fixed31_32_add( +- dal_fixed31_32_mul( +- point->coeff, +- dal_fixed31_32_sub( +- rgb[point->right_index].g, +- rgb[point->left_index].g)), +- rgb[point->left_index].g); +- else +- result = dal_fixed31_32_add( +- dal_fixed31_32_mul( +- point->coeff, +- dal_fixed31_32_sub( +- rgb[point->right_index].b, +- rgb[point->left_index].b)), +- rgb[point->left_index].b); +- else if (point->pos == HW_POINT_POSITION_LEFT) { +- BREAK_TO_DEBUGGER(); +- result = opp110->regamma.x_min; +- } else { +- BREAK_TO_DEBUGGER(); +- result = opp110->regamma.x_max1; +- } +- +- return result; +-} +- +-static inline struct fixed31_32 calculate_regamma_user_mapped_value( +- struct dce110_opp *opp110, +- const struct pixel_gamma_point *coeff, +- enum channel_name channel, +- uint32_t max_index) +-{ +- return calculate_mapped_value( +- opp110, opp110->regamma.rgb_oem, +- coeff, channel, max_index); +-} +- +-static inline struct fixed31_32 calculate_user_mapped_value( +- struct dce110_opp *opp110, +- const struct pixel_gamma_point *coeff, +- enum channel_name channel, +- uint32_t max_index) +-{ +- return calculate_mapped_value( +- opp110, opp110->regamma.rgb_user, +- coeff, channel, max_index); +-} +- +-static inline struct fixed31_32 calculate_oem_mapped_value( +- struct dce110_opp *opp110, +- uint32_t index, +- enum channel_name channel, +- uint32_t max_index) +-{ +- return calculate_regamma_user_mapped_value( +- opp110, opp110->regamma.coeff128_oem + +- index, channel, max_index); +-} +- +-static void scale_oem_gamma( +- struct dce110_opp *opp110, +- const struct regamma_ramp *regamma_ramp) +-{ +- const uint16_t max_driver = 0xFFFF; +- const uint16_t max_os = 0xFF00; +- +- uint16_t scale = max_os; +- +- uint32_t i; +- +- struct pwl_float_data *rgb = opp110->regamma.rgb_oem; +- struct pwl_float_data *rgb_last = rgb + RGB_256X3X16 - 1; +- +- /* find OEM maximum */ +- +- i = 0; +- +- do { +- if ((regamma_ramp->gamma[i] > max_os) || +- (regamma_ramp->gamma[i + RGB_256X3X16] > max_os) || +- (regamma_ramp->gamma[i + 2 * RGB_256X3X16] > max_os)) { +- scale = max_driver; +- break; +- } +- +- ++i; +- } while (i != RGB_256X3X16); +- +- /* scale */ +- +- i = 0; +- +- do { +- rgb->r = dal_fixed31_32_div_int( +- dal_fixed31_32_from_int( +- regamma_ramp->gamma[i]), +- scale); +- rgb->g = dal_fixed31_32_div_int( +- dal_fixed31_32_from_int( +- regamma_ramp->gamma[i + RGB_256X3X16]), +- scale); +- rgb->b = dal_fixed31_32_div_int( +- dal_fixed31_32_from_int( +- regamma_ramp->gamma[i + 2 * RGB_256X3X16]), +- scale); +- +- ++rgb; +- ++i; +- } while (i != RGB_256X3X16); +- +- /* add 3 extra points, 2 physical plus 1 virtual */ +- +- rgb->r = dal_fixed31_32_mul(rgb_last->r, +- opp110->regamma.divider1); +- rgb->g = dal_fixed31_32_mul(rgb_last->g, +- opp110->regamma.divider1); +- rgb->b = dal_fixed31_32_mul(rgb_last->b, +- opp110->regamma.divider1); +- +- ++rgb; +- +- rgb->r = dal_fixed31_32_mul(rgb_last->r, +- opp110->regamma.divider2); +- rgb->g = dal_fixed31_32_mul(rgb_last->g, +- opp110->regamma.divider2); +- rgb->b = dal_fixed31_32_mul(rgb_last->b, +- opp110->regamma.divider2); +- +- ++rgb; +- +- rgb->r = dal_fixed31_32_mul(rgb_last->r, +- opp110->regamma.divider3); +- rgb->g = dal_fixed31_32_mul(rgb_last->g, +- opp110->regamma.divider3); +- rgb->b = dal_fixed31_32_mul(rgb_last->b, +- opp110->regamma.divider3); +-} +- +-static inline void copy_rgb_regamma_to_coordinates_x( +- struct dce110_opp *opp110) +-{ +- struct hw_x_point *coords = opp110->regamma.coordinates_x; +- const struct pwl_float_data_ex *rgb_regamma = +- opp110->regamma.rgb_regamma; +- +- uint32_t i = 0; +- +- while (i <= opp110->regamma.hw_points_num) { +- coords->regamma_y_red = rgb_regamma->r; +- coords->regamma_y_green = rgb_regamma->g; +- coords->regamma_y_blue = rgb_regamma->b; +- +- ++coords; +- ++rgb_regamma; +- ++i; +- } +-} +- +-static bool calculate_interpolated_hardware_curve( +- struct dce110_opp *opp110, +- const struct gamma_ramp *gamma_ramp, +- const struct gamma_parameters *params) +-{ +- struct pwl_result_data *rgb_resulted = +- opp110->regamma.rgb_resulted; +- +- const struct pixel_gamma_point *coeff; +- uint32_t max_entries = opp110->regamma.extra_points - 1; +- +- uint32_t i = 0; +- +- if (gamma_ramp->type == GAMMA_RAMP_RBG256X3X16) { +- if (!build_custom_gamma_mapping_coefficients( +- opp110, CHANNEL_NAME_RED, +- opp110->regamma.hw_points_num, +- params->surface_pixel_format)) { +- BREAK_TO_DEBUGGER(); +- return false; +- } +- +- if (!build_custom_gamma_mapping_coefficients( +- opp110, CHANNEL_NAME_GREEN, +- opp110->regamma.hw_points_num, +- params->surface_pixel_format)) { +- BREAK_TO_DEBUGGER(); +- return false; +- } +- +- if (!build_custom_gamma_mapping_coefficients( +- opp110, CHANNEL_NAME_BLUE, +- opp110->regamma.hw_points_num, +- params->surface_pixel_format)) { +- BREAK_TO_DEBUGGER(); +- return false; +- } +- +- coeff = opp110->regamma.coeff128; +- max_entries += RGB_256X3X16; +- } else if (gamma_ramp->type == GAMMA_RAMP_DXGI_1) { +- if (!build_custom_dx_gamma_mapping_coefficients( +- opp110, CHANNEL_NAME_RED, +- opp110->regamma.hw_points_num, +- params->surface_pixel_format)) { +- BREAK_TO_DEBUGGER(); +- return false; +- } +- +- if (!build_custom_dx_gamma_mapping_coefficients( +- opp110, CHANNEL_NAME_GREEN, +- opp110->regamma.hw_points_num, +- params->surface_pixel_format)) { +- BREAK_TO_DEBUGGER(); +- return false; +- } +- +- if (!build_custom_dx_gamma_mapping_coefficients( +- opp110, CHANNEL_NAME_BLUE, +- opp110->regamma.hw_points_num, +- params->surface_pixel_format)) { +- BREAK_TO_DEBUGGER(); +- return false; +- } +- +- coeff = opp110->regamma.coeff128_dx; +- max_entries += DX_GAMMA_RAMP_MAX; +- } else { +- BREAK_TO_DEBUGGER(); +- return false; +- } +- +- while (i <= opp110->regamma.hw_points_num) { +- rgb_resulted->red = calculate_user_mapped_value( +- opp110, coeff, CHANNEL_NAME_RED, max_entries); +- rgb_resulted->green = calculate_user_mapped_value( +- opp110, coeff, CHANNEL_NAME_GREEN, max_entries); +- rgb_resulted->blue = calculate_user_mapped_value( +- opp110, coeff, CHANNEL_NAME_BLUE, max_entries); +- +- ++coeff; +- ++rgb_resulted; +- ++i; +- } +- +- return true; +-} +- +-static void map_standard_regamma_hw_to_x_user( +- struct dce110_opp *opp110, +- enum gamma_ramp_type type, +- const struct gamma_parameters *params) +-{ +- struct pwl_result_data *rgb_resulted = +- opp110->regamma.rgb_resulted; +- const struct pwl_float_data_ex *rgb_regamma = +- opp110->regamma.rgb_regamma; +- +- uint32_t i = 0; +- +- while (i <= opp110->regamma.hw_points_num) { +- rgb_resulted->red = rgb_regamma->r; +- rgb_resulted->green = rgb_regamma->g; +- rgb_resulted->blue = rgb_regamma->b; +- +- ++rgb_resulted; +- ++rgb_regamma; +- ++i; +- } +-} +- +-bool dce110_opp_map_legacy_and_regamma_hw_to_x_user( +- struct output_pixel_processor *opp, +- const struct gamma_ramp *gamma_ramp, +- const struct gamma_parameters *params) +-{ +- struct dce110_opp *opp110 = TO_DCE110_OPP(opp); +- +- if (params->regamma.features.bits.GAMMA_RAMP_ARRAY || +- params->regamma.features.bits.APPLY_DEGAMMA) { +- +- const uint32_t max_entries = +- RGB_256X3X16 + opp110->regamma.extra_points - 1; +- +- const struct pixel_gamma_point *coeff = +- opp110->regamma.coeff128; +- struct pwl_result_data *rgb_resulted = +- opp110->regamma.rgb_resulted; +- +- uint32_t i = 0; +- +- scale_oem_gamma(opp110, ¶ms->regamma.regamma_ramp); +- +- copy_rgb_regamma_to_coordinates_x(opp110); +- +- if (!build_custom_gamma_mapping_coefficients( +- opp110, CHANNEL_NAME_RED, +- opp110->regamma.hw_points_num, +- params->surface_pixel_format)) { +- BREAK_TO_DEBUGGER(); +- return false; +- } +- +- if (!build_custom_gamma_mapping_coefficients( +- opp110, CHANNEL_NAME_GREEN, +- opp110->regamma.hw_points_num, +- params->surface_pixel_format)) { +- BREAK_TO_DEBUGGER(); +- return false; +- } +- +- if (!build_custom_gamma_mapping_coefficients( +- opp110, CHANNEL_NAME_BLUE, +- opp110->regamma.hw_points_num, +- params->surface_pixel_format)) { +- BREAK_TO_DEBUGGER(); +- return false; +- } +- +- while (i <= opp110->regamma.hw_points_num) { +- rgb_resulted->red = +- calculate_regamma_user_mapped_value(opp110, +- coeff, +- CHANNEL_NAME_RED, max_entries); +- rgb_resulted->green = +- calculate_regamma_user_mapped_value(opp110, +- coeff, +- CHANNEL_NAME_GREEN, max_entries); +- rgb_resulted->blue = +- calculate_regamma_user_mapped_value(opp110, +- coeff, +- CHANNEL_NAME_BLUE, max_entries); +- +- ++coeff; +- ++rgb_resulted; +- ++i; +- } +- } else +- map_standard_regamma_hw_to_x_user(opp110, +- gamma_ramp->type, +- params); +- +- return true; +-} +- +-static bool map_regamma_hw_to_x_user( +- struct dce110_opp *opp110, +- const struct gamma_ramp *gamma_ramp, +- const struct gamma_parameters *params) +-{ +- /* setup to spare calculated ideal regamma values */ +- if (params->regamma.features.bits.GAMMA_RAMP_ARRAY || +- params->regamma.features.bits.APPLY_DEGAMMA) { +- +- const uint32_t max_entries = +- RGB_256X3X16 + opp110->regamma.extra_points - 1; +- +- const struct pixel_gamma_point *coeff = +- opp110->regamma.coeff128; +- struct hw_x_point *coords = +- opp110->regamma.coordinates_x; +- +- uint32_t i = 0; +- +- scale_oem_gamma(opp110, ¶ms->regamma.regamma_ramp); +- +- copy_rgb_regamma_to_coordinates_x(opp110); +- +- if (!build_custom_gamma_mapping_coefficients( +- opp110, CHANNEL_NAME_RED, +- opp110->regamma.hw_points_num, +- params->surface_pixel_format)) { +- BREAK_TO_DEBUGGER(); +- return false; +- } +- +- if (!build_custom_gamma_mapping_coefficients( +- opp110, CHANNEL_NAME_GREEN, +- opp110->regamma.hw_points_num, +- params->surface_pixel_format)) { +- BREAK_TO_DEBUGGER(); +- return false; +- } +- +- if (!build_custom_gamma_mapping_coefficients( +- opp110, CHANNEL_NAME_BLUE, +- opp110->regamma.hw_points_num, +- params->surface_pixel_format)) { +- BREAK_TO_DEBUGGER(); +- return false; +- } +- +- while (i <= opp110->regamma.hw_points_num) { +- coords->regamma_y_red = +- calculate_regamma_user_mapped_value(opp110, +- coeff, +- CHANNEL_NAME_RED, max_entries); +- coords->regamma_y_green = +- calculate_regamma_user_mapped_value(opp110, +- coeff, +- CHANNEL_NAME_GREEN, max_entries); +- coords->regamma_y_blue = +- calculate_regamma_user_mapped_value(opp110, +- coeff, +- CHANNEL_NAME_BLUE, max_entries); +- +- ++coeff; +- ++coords; +- ++i; +- } +- } else { +- copy_rgb_regamma_to_coordinates_x(opp110); +- } +- +- return calculate_interpolated_hardware_curve(opp110, gamma_ramp, +- params); +-} +- +-static void build_regamma_coefficients( +- const struct regamma_lut *regamma, +- bool is_degamma_srgb, +- struct gamma_coefficients *coefficients) +-{ +- /* 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 }; +- +- /* Non-sRGB should apply 2.2 */ +- static const int32_t numerator11[3] = { 180000, 180000, 180000 }; +- static const int32_t numerator12[3] = { 4500, 4500, 4500 }; +- static const int32_t numerator13[3] = { 99, 99, 99 }; +- static const int32_t numerator14[3] = { 99, 99, 99 }; +- static const int32_t numerator15[3] = { 2200, 2200, 2200 }; +- +- const int32_t *numerator1; +- const int32_t *numerator2; +- const int32_t *numerator3; +- const int32_t *numerator4; +- const int32_t *numerator5; +- +- uint32_t i = 0; +- +- if (!regamma->features.bits.GAMMA_RAMP_ARRAY) { +- numerator1 = regamma->gamma_coeff.a0; +- numerator2 = regamma->gamma_coeff.a1; +- numerator3 = regamma->gamma_coeff.a2; +- numerator4 = regamma->gamma_coeff.a3; +- numerator5 = regamma->gamma_coeff.gamma; +- } else if (is_degamma_srgb) { +- numerator1 = numerator01; +- numerator2 = numerator02; +- numerator3 = numerator03; +- numerator4 = numerator04; +- numerator5 = numerator05; +- } else { +- numerator1 = numerator11; +- numerator2 = numerator12; +- numerator3 = numerator13; +- numerator4 = numerator14; +- numerator5 = numerator15; +- } +- +- do { +- coefficients->a0[i] = dal_fixed31_32_from_fraction( +- numerator1[i], 10000000); +- coefficients->a1[i] = dal_fixed31_32_from_fraction( +- numerator2[i], 1000); +- coefficients->a2[i] = dal_fixed31_32_from_fraction( +- numerator3[i], 1000); +- coefficients->a3[i] = dal_fixed31_32_from_fraction( +- numerator4[i], 1000); +- coefficients->user_gamma[i] = dal_fixed31_32_from_fraction( +- numerator5[i], 1000); +- +- ++i; +- } while (i != ARRAY_SIZE(regamma->gamma_coeff.a0)); +-} +- +-static struct fixed31_32 translate_from_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) +-{ +- const struct fixed31_32 one = dal_fixed31_32_from_int(1); +- +- if (dal_fixed31_32_le(arg, dal_fixed31_32_neg(a0))) +- return dal_fixed31_32_sub( +- a2, +- dal_fixed31_32_mul( +- dal_fixed31_32_add( +- one, +- a3), +- dal_fixed31_32_pow( +- dal_fixed31_32_neg(arg), +- dal_fixed31_32_recip(gamma)))); +- else if (dal_fixed31_32_le(a0, arg)) +- return dal_fixed31_32_sub( +- dal_fixed31_32_mul( +- dal_fixed31_32_add( +- one, +- a3), +- dal_fixed31_32_pow( +- arg, +- dal_fixed31_32_recip(gamma))), +- a2); +- else +- return dal_fixed31_32_mul( +- arg, +- a1); +-} +- +-static inline struct fixed31_32 translate_from_linear_space_ex( +- struct fixed31_32 arg, +- struct gamma_coefficients *coeff, +- uint32_t color_index) +-{ +- return translate_from_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 build_regamma_curve( +- struct dce110_opp *opp110, +- const struct gamma_parameters *params) +-{ +- struct pwl_float_data_ex *rgb = opp110->regamma.rgb_regamma; +- +- uint32_t i; +- +- struct gamma_coefficients coeff; +- +- struct hw_x_point *coord_x = +- opp110->regamma.coordinates_x; +- +- build_regamma_coefficients( +- ¶ms->regamma, +- params->regamma.features.bits.GRAPHICS_DEGAMMA_SRGB, +- &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. +- */ +- +- i = 0; +- +- while (i != opp110->regamma.hw_points_num + 1) { +- rgb->r = translate_from_linear_space_ex( +- coord_x->adjusted_x, &coeff, 0); +- rgb->g = translate_from_linear_space_ex( +- coord_x->adjusted_x, &coeff, 1); +- rgb->b = translate_from_linear_space_ex( +- coord_x->adjusted_x, &coeff, 2); +- +- ++coord_x; +- ++rgb; +- ++i; +- } +- +- if (params->regamma.features.bits.GAMMA_RAMP_ARRAY && +- !params->regamma.features.bits.APPLY_DEGAMMA) { +- const uint32_t max_entries = +- RGB_256X3X16 + opp110->regamma.extra_points - 1; +- +- /* interpolate between 256 input points and output 185 points */ +- +- scale_oem_gamma(opp110, ¶ms->regamma.regamma_ramp); +- +- if (!build_oem_custom_gamma_mapping_coefficients( +- opp110, CHANNEL_NAME_RED, +- opp110->regamma.hw_points_num, +- params->surface_pixel_format)) { +- BREAK_TO_DEBUGGER(); +- return false; +- } +- +- if (!build_oem_custom_gamma_mapping_coefficients( +- opp110, CHANNEL_NAME_GREEN, +- opp110->regamma.hw_points_num, +- params->surface_pixel_format)) { +- BREAK_TO_DEBUGGER(); +- return false; +- } +- +- if (!build_oem_custom_gamma_mapping_coefficients( +- opp110, CHANNEL_NAME_BLUE, +- opp110->regamma.hw_points_num, +- params->surface_pixel_format)) { +- BREAK_TO_DEBUGGER(); +- return false; +- } +- +- i = 0; +- +- while (i != opp110->regamma.hw_points_num + 1) { +- rgb->r = calculate_oem_mapped_value( +- opp110, i, CHANNEL_NAME_RED, max_entries); +- rgb->g = calculate_oem_mapped_value( +- opp110, i, CHANNEL_NAME_GREEN, max_entries); +- rgb->b = calculate_oem_mapped_value( +- opp110, i, CHANNEL_NAME_BLUE, max_entries); +- ++rgb; +- ++i; +- } +- } +- +- return true; +-} +- +-static void build_new_custom_resulted_curve( +- struct dce110_opp *opp110, +- const struct gamma_parameters *params) +-{ +- struct pwl_result_data *rgb = opp110->regamma.rgb_resulted; +- struct pwl_result_data *rgb_plus_1 = rgb + 1; +- +- uint32_t i; +- +- i = 0; +- +- while (i != opp110->regamma.hw_points_num + 1) { +- rgb->red = dal_fixed31_32_clamp( +- rgb->red, opp110->regamma.x_min, +- opp110->regamma.x_max1); +- rgb->green = dal_fixed31_32_clamp( +- rgb->green, opp110->regamma.x_min, +- opp110->regamma.x_max1); +- rgb->blue = dal_fixed31_32_clamp( +- rgb->blue, opp110->regamma.x_min, +- opp110->regamma.x_max1); +- +- ++rgb; +- ++i; +- } +- +- rgb = opp110->regamma.rgb_resulted; +- +- i = 1; +- +- while (i != opp110->regamma.hw_points_num + 1) { +- if (dal_fixed31_32_lt(rgb_plus_1->red, rgb->red)) +- rgb_plus_1->red = rgb->red; +- if (dal_fixed31_32_lt(rgb_plus_1->green, rgb->green)) +- rgb_plus_1->green = rgb->green; +- if (dal_fixed31_32_lt(rgb_plus_1->blue, rgb->blue)) +- rgb_plus_1->blue = rgb->blue; +- +- rgb->delta_red = dal_fixed31_32_sub( +- rgb_plus_1->red, +- rgb->red); +- rgb->delta_green = dal_fixed31_32_sub( +- rgb_plus_1->green, +- rgb->green); +- rgb->delta_blue = dal_fixed31_32_sub( +- rgb_plus_1->blue, +- rgb->blue); +- +- ++rgb_plus_1; +- ++rgb; +- ++i; +- } +-} +- +-static bool rebuild_curve_configuration_magic( +- struct dce110_opp *opp110) +-{ +- const struct fixed31_32 magic_number = +- dal_fixed31_32_from_fraction(249, 1000); +- +- struct fixed31_32 y_r; +- struct fixed31_32 y_g; +- struct fixed31_32 y_b; +- +- struct fixed31_32 y1_min; +- struct fixed31_32 y2_max; +- struct fixed31_32 y3_max; +- +- y_r = opp110->regamma.rgb_resulted[0].red; +- y_g = opp110->regamma.rgb_resulted[0].green; +- y_b = opp110->regamma.rgb_resulted[0].blue; +- +- y1_min = dal_fixed31_32_min(y_r, dal_fixed31_32_min(y_g, y_b)); +- +- opp110->regamma.arr_points[0].x = +- opp110->regamma.coordinates_x[0].adjusted_x; +- opp110->regamma.arr_points[0].y = y1_min; +- opp110->regamma.arr_points[0].slope = dal_fixed31_32_div( +- opp110->regamma.arr_points[0].y, +- opp110->regamma.arr_points[0].x); +- +- opp110->regamma.arr_points[1].x = dal_fixed31_32_add( +- opp110->regamma.coordinates_x +- [opp110->regamma.hw_points_num - 1].adjusted_x, +- magic_number); +- +- opp110->regamma.arr_points[2].x = +- opp110->regamma.arr_points[1].x; +- +- y_r = opp110->regamma.rgb_resulted +- [opp110->regamma.hw_points_num - 1].red; +- y_g = opp110->regamma.rgb_resulted +- [opp110->regamma.hw_points_num - 1].green; +- y_b = opp110->regamma.rgb_resulted +- [opp110->regamma.hw_points_num - 1].blue; +- +- y2_max = dal_fixed31_32_max(y_r, dal_fixed31_32_max(y_g, y_b)); +- +- opp110->regamma.arr_points[1].y = y2_max; +- +- y_r = opp110->regamma.rgb_resulted +- [opp110->regamma.hw_points_num].red; +- y_g = opp110->regamma.rgb_resulted +- [opp110->regamma.hw_points_num].green; +- y_b = opp110->regamma.rgb_resulted +- [opp110->regamma.hw_points_num].blue; +- +- y3_max = dal_fixed31_32_max(y_r, dal_fixed31_32_max(y_g, y_b)); +- +- opp110->regamma.arr_points[2].y = y3_max; +- +- opp110->regamma.arr_points[2].slope = dal_fixed31_32_one; +- +- return true; +-} +- +-static bool build_custom_float( +- struct fixed31_32 value, +- const struct custom_float_format *format, +- bool *negative, +- uint32_t *mantissa, +- uint32_t *exponenta) +-{ +- uint32_t exp_offset = (1 << (format->exponenta_bits - 1)) - 1; +- +- const struct fixed31_32 mantissa_constant_plus_max_fraction = +- dal_fixed31_32_from_fraction( +- (1LL << (format->mantissa_bits + 1)) - 1, +- 1LL << format->mantissa_bits); +- +- struct fixed31_32 mantiss; +- +- if (dal_fixed31_32_eq( +- value, +- dal_fixed31_32_zero)) { +- *negative = false; +- *mantissa = 0; +- *exponenta = 0; +- return true; +- } +- +- if (dal_fixed31_32_lt( +- value, +- dal_fixed31_32_zero)) { +- *negative = format->sign; +- value = dal_fixed31_32_neg(value); +- } else { +- *negative = false; +- } +- +- if (dal_fixed31_32_lt( +- value, +- dal_fixed31_32_one)) { +- uint32_t i = 1; +- +- do { +- value = dal_fixed31_32_shl(value, 1); +- ++i; +- } while (dal_fixed31_32_lt( +- value, +- dal_fixed31_32_one)); +- +- --i; +- +- if (exp_offset <= i) { +- *mantissa = 0; +- *exponenta = 0; +- return true; +- } +- +- *exponenta = exp_offset - i; +- } else if (dal_fixed31_32_le( +- mantissa_constant_plus_max_fraction, +- value)) { +- uint32_t i = 1; +- +- do { +- value = dal_fixed31_32_shr(value, 1); +- ++i; +- } while (dal_fixed31_32_lt( +- mantissa_constant_plus_max_fraction, +- value)); +- +- *exponenta = exp_offset + i - 1; +- } else { +- *exponenta = exp_offset; +- } +- +- mantiss = dal_fixed31_32_sub( +- value, +- dal_fixed31_32_one); +- +- if (dal_fixed31_32_lt( +- mantiss, +- dal_fixed31_32_zero) || +- dal_fixed31_32_lt( +- dal_fixed31_32_one, +- mantiss)) +- mantiss = dal_fixed31_32_zero; +- else +- mantiss = dal_fixed31_32_shl( +- mantiss, +- format->mantissa_bits); +- +- *mantissa = dal_fixed31_32_floor(mantiss); +- +- return true; +-} +- +-static bool setup_custom_float( +- const struct custom_float_format *format, +- bool negative, +- uint32_t mantissa, +- uint32_t exponenta, +- uint32_t *result) +-{ +- uint32_t i = 0; +- uint32_t j = 0; +- +- uint32_t value = 0; +- +- /* verification code: +- * once calculation is ok we can remove it */ +- +- const uint32_t mantissa_mask = +- (1 << (format->mantissa_bits + 1)) - 1; +- +- const uint32_t exponenta_mask = +- (1 << (format->exponenta_bits + 1)) - 1; +- +- if (mantissa & ~mantissa_mask) { +- BREAK_TO_DEBUGGER(); +- mantissa = mantissa_mask; +- } +- +- if (exponenta & ~exponenta_mask) { +- BREAK_TO_DEBUGGER(); +- exponenta = exponenta_mask; +- } +- +- /* end of verification code */ +- +- while (i < format->mantissa_bits) { +- uint32_t mask = 1 << i; +- +- if (mantissa & mask) +- value |= mask; +- +- ++i; +- } +- +- while (j < format->exponenta_bits) { +- uint32_t mask = 1 << j; +- +- if (exponenta & mask) +- value |= mask << i; +- +- ++j; +- } +- +- if (negative && format->sign) +- value |= 1 << (i + j); +- +- *result = value; +- +- return true; +-} +- +-static bool convert_to_custom_float_format( +- struct fixed31_32 value, +- const struct custom_float_format *format, +- uint32_t *result) +-{ +- uint32_t mantissa; +- uint32_t exponenta; +- bool negative; +- +- return build_custom_float( +- value, format, &negative, &mantissa, &exponenta) && +- setup_custom_float( +- format, negative, mantissa, exponenta, result); +-} +- +-static bool convert_to_custom_float_format_ex( +- struct fixed31_32 value, +- const struct custom_float_format *format, +- struct custom_float_value *result) +-{ +- return build_custom_float( +- value, format, +- &result->negative, &result->mantissa, &result->exponenta) && +- setup_custom_float( +- format, result->negative, result->mantissa, result->exponenta, +- &result->value); +-} +- +-static bool convert_to_custom_float( +- struct dce110_opp *opp110) +-{ +- struct custom_float_format fmt; +- +- struct pwl_result_data *rgb = opp110->regamma.rgb_resulted; +- +- uint32_t i = 0; +- +- fmt.exponenta_bits = 6; +- fmt.mantissa_bits = 12; +- fmt.sign = true; +- +- if (!convert_to_custom_float_format( +- opp110->regamma.arr_points[0].x, +- &fmt, +- &opp110->regamma.arr_points[0].custom_float_x)) { +- BREAK_TO_DEBUGGER(); +- return false; +- } +- +- if (!convert_to_custom_float_format( +- opp110->regamma.arr_points[0].offset, +- &fmt, +- &opp110->regamma.arr_points[0].custom_float_offset)) { +- BREAK_TO_DEBUGGER(); +- return false; +- } +- +- if (!convert_to_custom_float_format( +- opp110->regamma.arr_points[0].slope, +- &fmt, +- &opp110->regamma.arr_points[0].custom_float_slope)) { +- BREAK_TO_DEBUGGER(); +- return false; +- } +- +- fmt.mantissa_bits = 10; +- fmt.sign = false; +- +- if (!convert_to_custom_float_format( +- opp110->regamma.arr_points[1].x, +- &fmt, +- &opp110->regamma.arr_points[1].custom_float_x)) { +- BREAK_TO_DEBUGGER(); +- return false; +- } +- +- if (!convert_to_custom_float_format( +- opp110->regamma.arr_points[1].y, +- &fmt, +- &opp110->regamma.arr_points[1].custom_float_y)) { +- BREAK_TO_DEBUGGER(); +- return false; +- } +- +- if (!convert_to_custom_float_format( +- opp110->regamma.arr_points[2].slope, +- &fmt, +- &opp110->regamma.arr_points[2].custom_float_slope)) { +- BREAK_TO_DEBUGGER(); +- return false; +- } +- +- fmt.mantissa_bits = 12; +- fmt.sign = true; +- +- while (i != opp110->regamma.hw_points_num) { +- if (!convert_to_custom_float_format( +- rgb->red, +- &fmt, +- &rgb->red_reg)) { +- BREAK_TO_DEBUGGER(); +- return false; +- } +- +- if (!convert_to_custom_float_format( +- rgb->green, +- &fmt, +- &rgb->green_reg)) { +- BREAK_TO_DEBUGGER(); +- return false; +- } +- +- if (!convert_to_custom_float_format( +- rgb->blue, +- &fmt, +- &rgb->blue_reg)) { +- BREAK_TO_DEBUGGER(); +- return false; +- } +- +- if (!convert_to_custom_float_format( +- rgb->delta_red, +- &fmt, +- &rgb->delta_red_reg)) { +- BREAK_TO_DEBUGGER(); +- return false; +- } +- +- if (!convert_to_custom_float_format( +- rgb->delta_green, +- &fmt, +- &rgb->delta_green_reg)) { +- BREAK_TO_DEBUGGER(); +- return false; +- } +- +- if (!convert_to_custom_float_format( +- rgb->delta_blue, +- &fmt, +- &rgb->delta_blue_reg)) { +- BREAK_TO_DEBUGGER(); +- return false; +- } +- +- ++rgb; +- ++i; +- } +- +- return true; +-} +- +-static bool round_custom_float_6_12( +- struct hw_x_point *x) +-{ +- struct custom_float_format fmt; +- +- struct custom_float_value value; +- +- fmt.exponenta_bits = 6; +- fmt.mantissa_bits = 12; +- fmt.sign = true; +- +- if (!convert_to_custom_float_format_ex( +- x->x, &fmt, &value)) +- return false; +- +- x->adjusted_x = x->x; +- +- if (value.mantissa) { +- BREAK_TO_DEBUGGER(); +- +- return false; +- } +- +- return true; +-} +- +-static bool build_hw_curve_configuration( +- const struct curve_config *curve_config, +- struct gamma_curve *gamma_curve, +- struct curve_points *curve_points, +- struct hw_x_point *points, +- uint32_t *number_of_points) +-{ +- const int8_t max_regions_number = ARRAY_SIZE(curve_config->segments); +- +- int8_t i; +- +- uint8_t segments_calculation[8] = { 0 }; +- +- struct fixed31_32 region1 = dal_fixed31_32_zero; +- struct fixed31_32 region2; +- struct fixed31_32 increment; +- +- uint32_t index = 0; +- uint32_t segments = 0; +- uint32_t max_number; +- +- bool result = false; +- +- if (!number_of_points) { +- BREAK_TO_DEBUGGER(); +- return false; +- } +- +- max_number = *number_of_points; +- +- i = 0; +- +- while (i != max_regions_number) { +- gamma_curve[i].offset = 0; +- gamma_curve[i].segments_num = 0; +- +- ++i; +- } +- +- i = 0; +- +- while (i != max_regions_number) { +- /* number should go in uninterruptible sequence */ +- if (curve_config->segments[i] == -1) +- break; +- +- ASSERT(curve_config->segments[i] >= 0); +- +- segments += (1 << curve_config->segments[i]); +- +- ++i; +- } +- +- if (segments > max_number) { +- BREAK_TO_DEBUGGER(); +- } else { +- int32_t divisor; +- uint32_t offset = 0; +- int8_t begin = curve_config->begin; +- int32_t region_number = 0; +- +- i = begin; +- +- while ((index < max_number) && +- (region_number < max_regions_number) && +- (i <= 1)) { +- int32_t j = 0; +- +- segments = curve_config->segments[region_number]; +- divisor = 1 << segments; +- +- if (segments == -1) { +- if (i > 0) { +- region1 = dal_fixed31_32_shl( +- dal_fixed31_32_one, +- i - 1); +- region2 = dal_fixed31_32_shl( +- dal_fixed31_32_one, +- i); +- } else { +- region1 = dal_fixed31_32_shr( +- dal_fixed31_32_one, +- -(i - 1)); +- region2 = dal_fixed31_32_shr( +- dal_fixed31_32_one, +- -i); +- } +- +- break; +- } +- +- if (i > -1) { +- region1 = dal_fixed31_32_shl( +- dal_fixed31_32_one, +- i); +- region2 = dal_fixed31_32_shl( +- dal_fixed31_32_one, +- i + 1); +- } else { +- region1 = dal_fixed31_32_shr( +- dal_fixed31_32_one, +- -i); +- region2 = dal_fixed31_32_shr( +- dal_fixed31_32_one, +- -(i + 1)); +- } +- +- gamma_curve[region_number].offset = offset; +- gamma_curve[region_number].segments_num = segments; +- +- offset += divisor; +- +- ++segments_calculation[segments]; +- +- increment = dal_fixed31_32_div_int( +- dal_fixed31_32_sub( +- region2, +- region1), +- divisor); +- +- points[index].x = region1; +- +- round_custom_float_6_12(points + index); +- +- ++index; +- ++region_number; +- +- while ((index < max_number) && (j < divisor - 1)) { +- region1 = dal_fixed31_32_add( +- region1, +- increment); +- +- points[index].x = region1; +- points[index].adjusted_x = region1; +- +- ++index; +- ++j; +- } +- +- ++i; +- } +- +- points[index].x = region1; +- +- round_custom_float_6_12(points + index); +- +- *number_of_points = index; +- +- result = true; +- } +- +- curve_points[0].x = points[0].adjusted_x; +- curve_points[0].offset = dal_fixed31_32_zero; +- +- curve_points[1].x = points[index - 1].adjusted_x; +- curve_points[1].offset = dal_fixed31_32_zero; +- +- curve_points[2].x = points[index].adjusted_x; +- curve_points[2].offset = dal_fixed31_32_zero; +- +- return result; +-} +- +-static bool setup_distribution_points( +- struct dce110_opp *opp110) +-{ +- uint32_t hw_points_num = MAX_PWL_ENTRY * 2; +- +- struct curve_config cfg; +- +- cfg.offset = 0; +- +- cfg.segments[0] = 3; +- cfg.segments[1] = 4; +- cfg.segments[2] = 4; +- cfg.segments[3] = 4; +- cfg.segments[4] = 4; +- cfg.segments[5] = 4; +- cfg.segments[6] = 4; +- cfg.segments[7] = 4; +- cfg.segments[8] = 5; +- cfg.segments[9] = 5; +- cfg.segments[10] = 0; +- cfg.segments[11] = -1; +- cfg.segments[12] = -1; +- cfg.segments[13] = -1; +- cfg.segments[14] = -1; +- cfg.segments[15] = -1; +- +- cfg.begin = -10; +- +- if (!build_hw_curve_configuration( +- &cfg, opp110->regamma.arr_curve_points, +- opp110->regamma.arr_points, +- opp110->regamma.coordinates_x, &hw_points_num)) { +- ASSERT_CRITICAL(false); +- return false; +- } +- +- opp110->regamma.hw_points_num = hw_points_num; +- +- return true; +-} +- +- + /* + ***************************************************************************** + * Function: regamma_config_regions_and_segments +@@ -1779,15 +61,16 @@ static bool setup_distribution_points( + ***************************************************************************** + */ + static void regamma_config_regions_and_segments( +- struct dce110_opp *opp110) ++ struct dce110_opp *opp110, ++ const struct regamma_params *params) + { +- struct gamma_curve *curve; ++ const struct gamma_curve *curve; + uint32_t value = 0; + + { + set_reg_field_value( + value, +- opp110->regamma.arr_points[0].custom_float_x, ++ params->arr_points[0].custom_float_x, + REGAMMA_CNTLA_START_CNTL, + REGAMMA_CNTLA_EXP_REGION_START); + +@@ -1805,7 +88,7 @@ static void regamma_config_regions_and_segments( + value = 0; + set_reg_field_value( + value, +- opp110->regamma.arr_points[0].custom_float_slope, ++ params->arr_points[0].custom_float_slope, + REGAMMA_CNTLA_SLOPE_CNTL, + REGAMMA_CNTLA_EXP_REGION_LINEAR_SLOPE); + +@@ -1816,7 +99,7 @@ static void regamma_config_regions_and_segments( + value = 0; + set_reg_field_value( + value, +- opp110->regamma.arr_points[1].custom_float_x, ++ params->arr_points[1].custom_float_x, + REGAMMA_CNTLA_END_CNTL1, + REGAMMA_CNTLA_EXP_REGION_END); + +@@ -1827,13 +110,13 @@ static void regamma_config_regions_and_segments( + value = 0; + set_reg_field_value( + value, +- opp110->regamma.arr_points[2].custom_float_slope, ++ params->arr_points[2].custom_float_slope, + REGAMMA_CNTLA_END_CNTL2, + REGAMMA_CNTLA_EXP_REGION_END_BASE); + + set_reg_field_value( + value, +- opp110->regamma.arr_points[1].custom_float_y, ++ params->arr_points[1].custom_float_y, + REGAMMA_CNTLA_END_CNTL2, + REGAMMA_CNTLA_EXP_REGION_END_SLOPE); + +@@ -1841,7 +124,7 @@ static void regamma_config_regions_and_segments( + DCP_REG(mmREGAMMA_CNTLA_END_CNTL2), value); + } + +- curve = opp110->regamma.arr_curve_points; ++ curve = params->arr_curve_points; + + { + value = 0; +@@ -2102,7 +385,7 @@ static void regamma_config_regions_and_segments( + + static void program_pwl( + struct dce110_opp *opp110, +- const struct gamma_parameters *params) ++ const struct regamma_params *params) + { + uint32_t value; + +@@ -2110,6 +393,18 @@ static void program_pwl( + uint8_t max_tries = 10; + uint8_t counter = 0; + ++ value = dm_read_reg(opp110->base.ctx, ++ DCP_REG(mmREGAMMA_CONTROL)); ++ ++ set_reg_field_value( ++ value, ++ 3, ++ REGAMMA_CONTROL, ++ GRPH_REGAMMA_MODE); ++ ++ dm_write_reg(opp110->base.ctx, DCP_REG(mmREGAMMA_CONTROL), ++ value); ++ + /* Power on LUT memory */ + value = dm_read_reg(opp110->base.ctx, + DCFE_REG(mmDCFE_MEM_PWR_CTRL)); +@@ -2168,10 +463,9 @@ static void program_pwl( + + uint32_t i = 0; + +- struct pwl_result_data *rgb = +- opp110->regamma.rgb_resulted; ++ const struct pwl_result_data *rgb = params->rgb_resulted; + +- while (i != opp110->regamma.hw_points_num) { ++ while (i != params->hw_points_num) { + dm_write_reg(opp110->base.ctx, addr, rgb->red_reg); + dm_write_reg(opp110->base.ctx, addr, rgb->green_reg); + dm_write_reg(opp110->base.ctx, addr, rgb->blue_reg); +@@ -2200,6 +494,22 @@ static void program_pwl( + dm_write_reg(opp110->base.ctx, DCFE_REG(mmDCFE_MEM_PWR_CTRL), value); + } + ++ ++bool dce110_opp_set_regamma( ++ struct output_pixel_processor *opp, ++ const struct regamma_params *params) ++{ ++ struct dce110_opp *opp110 = TO_DCE110_OPP(opp); ++ ++ /* Setup regions */ ++ regamma_config_regions_and_segments(opp110, params); ++ ++ /* Program PWL */ ++ program_pwl(opp110, params); ++ ++ return true; ++} ++ + void dce110_opp_power_on_regamma_lut( + struct output_pixel_processor *opp, + bool power_on) +@@ -2223,252 +533,3 @@ void dce110_opp_power_on_regamma_lut( + + dm_write_reg(opp->ctx, DCFE_REG(mmDCFE_MEM_PWR_CTRL), value); + } +- +-static bool scale_gamma( +- struct dce110_opp *opp110, +- const struct gamma_ramp *gamma_ramp, +- const struct gamma_parameters *params) +-{ +- const struct gamma_ramp_rgb256x3x16 *gamma; +- bool use_palette = params->surface_pixel_format == PIXEL_FORMAT_INDEX8; +- +- const uint16_t max_driver = 0xFFFF; +- const uint16_t max_os = 0xFF00; +- +- uint16_t scaler = max_os; +- +- uint32_t i; +- +- struct dev_c_lut *palette = opp110->regamma.saved_palette; +- +- struct pwl_float_data *rgb = opp110->regamma.rgb_user; +- struct pwl_float_data *rgb_last = rgb + RGB_256X3X16 - 1; +- +- if (gamma_ramp->type == GAMMA_RAMP_RBG256X3X16) +- gamma = &gamma_ramp->gamma_ramp_rgb256x3x16; +- else +- return false; /* invalid option */ +- +- i = 0; +- +- do { +- if ((gamma->red[i] > max_os) || +- (gamma->green[i] > max_os) || +- (gamma->blue[i] > max_os)) { +- scaler = max_driver; +- break; +- } +- ++i; +- } while (i != RGB_256X3X16); +- +- i = 0; +- +- if (use_palette) +- do { +- rgb->r = dal_fixed31_32_from_fraction( +- gamma->red[palette->red], scaler); +- rgb->g = dal_fixed31_32_from_fraction( +- gamma->green[palette->green], scaler); +- rgb->b = dal_fixed31_32_from_fraction( +- gamma->blue[palette->blue], scaler); +- +- ++palette; +- ++rgb; +- ++i; +- } while (i != RGB_256X3X16); +- else +- do { +- rgb->r = dal_fixed31_32_from_fraction( +- gamma->red[i], scaler); +- rgb->g = dal_fixed31_32_from_fraction( +- gamma->green[i], scaler); +- rgb->b = dal_fixed31_32_from_fraction( +- gamma->blue[i], scaler); +- +- ++rgb; +- ++i; +- } while (i != RGB_256X3X16); +- +- rgb->r = dal_fixed31_32_mul(rgb_last->r, +- opp110->regamma.divider1); +- rgb->g = dal_fixed31_32_mul(rgb_last->g, +- opp110->regamma.divider1); +- rgb->b = dal_fixed31_32_mul(rgb_last->b, +- opp110->regamma.divider1); +- +- ++rgb; +- +- rgb->r = dal_fixed31_32_mul(rgb_last->r, +- opp110->regamma.divider2); +- rgb->g = dal_fixed31_32_mul(rgb_last->g, +- opp110->regamma.divider2); +- rgb->b = dal_fixed31_32_mul(rgb_last->b, +- opp110->regamma.divider2); +- +- ++rgb; +- +- rgb->r = dal_fixed31_32_mul(rgb_last->r, +- opp110->regamma.divider3); +- rgb->g = dal_fixed31_32_mul(rgb_last->g, +- opp110->regamma.divider3); +- rgb->b = dal_fixed31_32_mul(rgb_last->b, +- opp110->regamma.divider3); +- +- return true; +-} +- +- +-static void configure_regamma_mode( +- struct dce110_opp *opp110, +- const struct gamma_parameters *params, +- bool force_bypass) +-{ +- const uint32_t addr = DCP_REG(mmREGAMMA_CONTROL); +- +- enum wide_gamut_regamma_mode mode = +- WIDE_GAMUT_REGAMMA_MODE_GRAPHICS_MATRIX_A; +- +- uint32_t value = dm_read_reg(opp110->base.ctx, addr); +- +- if (force_bypass) { +- +- set_reg_field_value( +- value, +- 0, +- REGAMMA_CONTROL, +- GRPH_REGAMMA_MODE); +- +- dm_write_reg(opp110->base.ctx, addr, value); +- +- return; +- } +- +- if (params->regamma_adjust_type == GRAPHICS_REGAMMA_ADJUST_BYPASS) +- mode = WIDE_GAMUT_REGAMMA_MODE_GRAPHICS_BYPASS; +- else if (params->regamma_adjust_type == GRAPHICS_REGAMMA_ADJUST_HW) { +- if (params->surface_pixel_format == PIXEL_FORMAT_FP16) +- mode = WIDE_GAMUT_REGAMMA_MODE_GRAPHICS_BYPASS; +- else +- mode = WIDE_GAMUT_REGAMMA_MODE_GRAPHICS_SRGB24; +- } +- +- switch (mode) { +- case WIDE_GAMUT_REGAMMA_MODE_GRAPHICS_BYPASS: +- set_reg_field_value( +- value, +- 0, +- REGAMMA_CONTROL, +- GRPH_REGAMMA_MODE); +- break; +- case WIDE_GAMUT_REGAMMA_MODE_GRAPHICS_SRGB24: +- set_reg_field_value( +- value, +- 1, +- REGAMMA_CONTROL, +- GRPH_REGAMMA_MODE); +- break; +- case WIDE_GAMUT_REGAMMA_MODE_GRAPHICS_XYYCC22: +- set_reg_field_value( +- value, +- 2, +- REGAMMA_CONTROL, +- GRPH_REGAMMA_MODE); +- break; +- case WIDE_GAMUT_REGAMMA_MODE_GRAPHICS_MATRIX_A: +- set_reg_field_value( +- value, +- 3, +- REGAMMA_CONTROL, +- GRPH_REGAMMA_MODE); +- break; +- case WIDE_GAMUT_REGAMMA_MODE_GRAPHICS_MATRIX_B: +- set_reg_field_value( +- value, +- 4, +- REGAMMA_CONTROL, +- GRPH_REGAMMA_MODE); +- break; +- default: +- break; +- } +- +- dm_write_reg(opp110->base.ctx, addr, value); +-} +- +-bool dce110_opp_set_regamma( +- struct output_pixel_processor *opp, +- const struct gamma_ramp *ramp, +- const struct gamma_parameters *params, +- bool force_bypass) +-{ +- struct dce110_opp *opp110 = TO_DCE110_OPP(opp); +- +- if (force_bypass) { +- configure_regamma_mode(opp110, params, true); +- } else { +- /* 1. Scale gamma to 0 - 1 to m_pRgbUser */ +- if (!scale_gamma(opp110, ramp, params)) { +- ASSERT_CRITICAL(false); +- /* invalid option */ +- return false; +- } +- +- /* 2. Configure regamma curve without analysis (future task) */ +- /* and program the PWL regions and segments */ +- if (params->regamma_adjust_type == GRAPHICS_REGAMMA_ADJUST_SW || +- params->surface_pixel_format == PIXEL_FORMAT_FP16) { +- +- /* 3. Setup x exponentially distributed points */ +- if (!setup_distribution_points(opp110)) { +- ASSERT_CRITICAL(false); +- /* invalid option */ +- return false; +- } +- +- /* 4. Build ideal regamma curve */ +- if (!build_regamma_curve(opp110, params)) { +- ASSERT_CRITICAL(false); +- /* invalid parameters or bug */ +- return false; +- } +- +- /* 5. Map user gamma (evenly distributed x points) to +- * new curve when x is y from ideal regamma , step 5 */ +- if (!map_regamma_hw_to_x_user( +- opp110, ramp, params)) { +- ASSERT_CRITICAL(false); +- /* invalid parameters or bug */ +- return false; +- } +- +- /* 6.Build and verify resulted curve */ +- build_new_custom_resulted_curve(opp110, params); +- +- /* 7. Build and translate x to hw format */ +- if (!rebuild_curve_configuration_magic(opp110)) { +- ASSERT_CRITICAL(false); +- /* invalid parameters or bug */ +- return false; +- } +- +- /* 8. convert all params to the custom float format */ +- if (!convert_to_custom_float(opp110)) { +- ASSERT_CRITICAL(false); +- /* invalid parameters or bug */ +- return false; +- } +- +- /* 9. program regamma curve configuration */ +- regamma_config_regions_and_segments(opp110); +- +- /* 10. Program PWL */ +- program_pwl(opp110, params); +- } +- +- /* +- * 11. program regamma config +- */ +- configure_regamma_mode(opp110, params, false); +- } +- return true; +-} +diff --git a/drivers/gpu/drm/amd/dal/dc/dce110/dce110_types.h b/drivers/gpu/drm/amd/dal/dc/dce110/dce110_types.h +new file mode 100644 +index 0000000..e61a494 +--- /dev/null ++++ b/drivers/gpu/drm/amd/dal/dc/dce110/dce110_types.h +@@ -0,0 +1,58 @@ ++/* Copyright 2012-15 Advanced Micro Devices, Inc. ++ * ++ * Permission is hereby granted, free of charge, to any person obtaining a ++ * copy of this software and associated documentation files (the "Software"), ++ * to deal in the Software without restriction, including without limitation ++ * the rights to use, copy, modify, merge, publish, distribute, sublicense, ++ * and/or sell copies of the Software, and to permit persons to whom the ++ * Software is furnished to do so, subject to the following conditions: ++ * ++ * The above copyright notice and this permission notice shall be included in ++ * all copies or substantial portions of the Software. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR ++ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, ++ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL ++ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR ++ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ++ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR ++ * OTHER DEALINGS IN THE SOFTWARE. ++ * ++ * Authors: AMD ++ * ++ */ ++ ++#ifndef _DCE110_TYPES_H_ ++#define __DCE110_TYPES_H_ ++ ++#define GAMMA_SEGMENTS_NUM 16 ++struct end_point { ++ uint32_t x_value; ++ uint32_t y_value; ++ uint32_t slope; ++}; ++ ++struct pwl_segment { ++ uint32_t r_value; ++ uint32_t g_value; ++ uint32_t b_value; ++ uint32_t r_delta; ++ uint32_t g_delta; ++ uint32_t b_delta; ++}; ++ ++struct dce110_opp_regamma_params { ++ struct { ++ uint8_t num_segments[GAMMA_SEGMENTS_NUM]; ++ uint16_t offsets[GAMMA_SEGMENTS_NUM]; ++ struct end_point first; ++ struct end_point last; ++ } region_config; ++ ++ struct { ++ struct pwl_segment *segments; ++ int num_pwl_segments; ++ } pwl_config; ++}; ++ ++#endif /* DRIVERS_GPU_DRM_AMD_DAL_DEV_DC_DCE110_DCE110_TYPES_H_ */ +diff --git a/drivers/gpu/drm/amd/dal/dc/inc/core_types.h b/drivers/gpu/drm/amd/dal/dc/inc/core_types.h +index 866853b..e3dbaeb 100644 +--- a/drivers/gpu/drm/amd/dal/dc/inc/core_types.h ++++ b/drivers/gpu/drm/amd/dal/dc/inc/core_types.h +@@ -53,12 +53,21 @@ struct core_target { + #define DC_SURFACE_TO_CORE(dc_surface) \ + container_of(dc_surface, struct core_surface, public) + ++#define DC_GAMMA_TO_CORE(dc_gamma) \ ++ container_of(dc_gamma, struct core_gamma, public) ++ ++ + struct core_surface { + struct dc_surface public; + struct dc_surface_status status; + struct dc_context *ctx; + }; + ++struct core_gamma { ++ struct dc_gamma public; ++ struct dc_context *ctx; ++}; ++ + void enable_surface_flip_reporting(struct dc_surface *dc_surface, + uint32_t controller_id); + +diff --git a/drivers/gpu/drm/amd/dal/dc/inc/gamma_calcs.h b/drivers/gpu/drm/amd/dal/dc/inc/gamma_calcs.h +new file mode 100644 +index 0000000..4e35960 +--- /dev/null ++++ b/drivers/gpu/drm/amd/dal/dc/inc/gamma_calcs.h +@@ -0,0 +1,31 @@ ++/* ++ * gamma_calcs.h ++ * ++ * Created on: Feb 9, 2016 ++ * Author: yonsun ++ */ ++ ++#ifndef DRIVERS_GPU_DRM_AMD_DAL_DEV_DC_INC_GAMMA_CALCS_H_ ++#define DRIVERS_GPU_DRM_AMD_DAL_DEV_DC_INC_GAMMA_CALCS_H_ ++ ++#include "opp.h" ++#include "core_types.h" ++#include "dc.h" ++ ++struct temp_params { ++ struct hw_x_point coordinates_x[256 + 3]; ++ struct pwl_float_data rgb_user[FLOAT_GAMMA_RAMP_MAX + 3]; ++ struct pwl_float_data_ex rgb_regamma[256 + 3]; ++ struct pwl_float_data rgb_oem[FLOAT_GAMMA_RAMP_MAX + 3]; ++ struct gamma_pixel axix_x_256[256]; ++ struct pixel_gamma_point coeff128_oem[256 + 3]; ++ struct pixel_gamma_point coeff128[256 + 3]; ++ ++}; ++ ++void calculate_regamma_params(struct regamma_params *params, ++ struct temp_params *temp_params, ++ const struct core_gamma *ramp, ++ const struct core_surface *surface); ++ ++#endif /* DRIVERS_GPU_DRM_AMD_DAL_DEV_DC_INC_GAMMA_CALCS_H_ */ +diff --git a/drivers/gpu/drm/amd/dal/dc/inc/gamma_types.h b/drivers/gpu/drm/amd/dal/dc/inc/gamma_types.h +index ad21db5..ca23e1b 100644 +--- a/drivers/gpu/drm/amd/dal/dc/inc/gamma_types.h ++++ b/drivers/gpu/drm/amd/dal/dc/inc/gamma_types.h +@@ -41,10 +41,6 @@ struct dev_c_lut16 { + uint16_t blue; + }; + +-struct regamma_ramp { +- uint16_t gamma[RGB_256X3X16 * 3]; +-}; +- + /* used by Graphics and Overlay gamma */ + struct gamma_coeff { + int32_t gamma[3]; +@@ -54,35 +50,6 @@ struct gamma_coeff { + int32_t a3[3]; + }; + +-struct regamma_lut { +- union { +- struct { +- uint32_t GRAPHICS_DEGAMMA_SRGB :1; +- uint32_t OVERLAY_DEGAMMA_SRGB :1; +- uint32_t GAMMA_RAMP_ARRAY :1; +- uint32_t APPLY_DEGAMMA :1; +- uint32_t RESERVED :28; +- } bits; +- uint32_t value; +- } features; +- +- union { +- struct regamma_ramp regamma_ramp; +- struct gamma_coeff gamma_coeff; +- }; +-}; +- +-union gamma_flag { +- struct { +- uint32_t config_is_changed :1; +- uint32_t both_pipe_req :1; +- uint32_t regamma_update :1; +- uint32_t gamma_update :1; +- uint32_t reserved :28; +- } bits; +- uint32_t u_all; +-}; +- + enum graphics_regamma_adjust { + GRAPHICS_REGAMMA_ADJUST_BYPASS = 0, GRAPHICS_REGAMMA_ADJUST_HW, /* without adjustments */ + GRAPHICS_REGAMMA_ADJUST_SW /* use adjustments */ +@@ -99,19 +66,4 @@ enum graphics_degamma_adjust { + GRAPHICS_DEGAMMA_ADJUST_SW /* use adjustments */ + }; + +-struct gamma_parameters { +- union gamma_flag flag; +- enum pixel_format surface_pixel_format; /*OS surface pixel format*/ +- struct regamma_lut regamma; +- +- enum graphics_regamma_adjust regamma_adjust_type; +- enum graphics_degamma_adjust degamma_adjust_type; +- +- enum graphics_gamma_lut selected_gamma_lut; +- +- bool disable_adjustments; +- +- /* here we grow with parameters if necessary */ +-}; +- + #endif +diff --git a/drivers/gpu/drm/amd/dal/dc/inc/hw_sequencer.h b/drivers/gpu/drm/amd/dal/dc/inc/hw_sequencer.h +index 8460dd7..5dd16dc 100644 +--- a/drivers/gpu/drm/amd/dal/dc/inc/hw_sequencer.h ++++ b/drivers/gpu/drm/amd/dal/dc/inc/hw_sequencer.h +@@ -56,11 +56,11 @@ struct hw_sequencer_funcs { + const struct core_surface *surface, + struct core_target *target); + +- bool (*set_gamma_ramp)( ++ bool (*set_gamma_correction)( + struct input_pixel_processor *ipp, + struct output_pixel_processor *opp, +- const struct gamma_ramp *ramp, +- const struct gamma_parameters *params); ++ const struct core_gamma *ramp, ++ const struct core_surface *surface); + + void (*power_down)(struct dc *dc); + +diff --git a/drivers/gpu/drm/amd/dal/dc/inc/ipp.h b/drivers/gpu/drm/amd/dal/dc/inc/ipp.h +index 8e7cc31..c98102f 100644 +--- a/drivers/gpu/drm/amd/dal/dc/inc/ipp.h ++++ b/drivers/gpu/drm/amd/dal/dc/inc/ipp.h +@@ -45,6 +45,25 @@ struct input_pixel_processor { + struct ipp_funcs *funcs; + }; + ++enum ipp_prescale_mode { ++ IPP_PRESCALE_MODE_BYPASS, ++ IPP_PRESCALE_MODE_FIXED_SIGNED, ++ IPP_PRESCALE_MODE_FLOAT_SIGNED, ++ IPP_PRESCALE_MODE_FIXED_UNSIGNED, ++ IPP_PRESCALE_MODE_FLOAT_UNSIGNED ++}; ++ ++struct ipp_prescale_params { ++ enum ipp_prescale_mode mode; ++ uint16_t bias; ++ uint16_t scale; ++}; ++ ++enum ipp_degamma_mode { ++ IPP_DEGAMMA_MODE_BYPASS, ++ IPP_DEGAMMA_MODE_sRGB ++}; ++ + enum wide_gamut_degamma_mode { + /* 00 - BITS1:0 Bypass */ + WIDE_GAMUT_DEGAMMA_MODE_GRAPHICS_BYPASS, +@@ -79,21 +98,11 @@ struct ipp_funcs { + /* DEGAMMA RELATED */ + bool (*ipp_set_degamma)( + struct input_pixel_processor *ipp, +- const struct gamma_parameters *params, +- bool force_bypass); ++ enum ipp_degamma_mode mode); + + void (*ipp_program_prescale)( + struct input_pixel_processor *ipp, +- enum pixel_format pixel_format); +- +- void (*ipp_set_legacy_input_gamma_mode)( +- struct input_pixel_processor *ipp, +- bool is_legacy); +- +- bool (*ipp_set_legacy_input_gamma_ramp)( +- struct input_pixel_processor *ipp, +- const struct gamma_ramp *gamma_ramp, +- const struct gamma_parameters *params); ++ struct ipp_prescale_params *params); + + bool (*ipp_set_palette)( + struct input_pixel_processor *ipp, +diff --git a/drivers/gpu/drm/amd/dal/dc/inc/opp.h b/drivers/gpu/drm/amd/dal/dc/inc/opp.h +index 3071df6..307184a 100644 +--- a/drivers/gpu/drm/amd/dal/dc/inc/opp.h ++++ b/drivers/gpu/drm/amd/dal/dc/inc/opp.h +@@ -263,6 +263,14 @@ enum fmt_stereo_action { + FMT_STEREO_ACTION_UPDATE_POLARITY + }; + ++struct regamma_params { ++ uint32_t *data; ++ struct gamma_curve arr_curve_points[16]; ++ struct curve_points arr_points[3]; ++ struct pwl_result_data rgb_resulted[256 + 3]; ++ uint32_t hw_points_num; ++}; ++ + struct opp_funcs { + void (*opp_power_on_regamma_lut)( + struct output_pixel_processor *opp, +@@ -270,14 +278,7 @@ struct opp_funcs { + + bool (*opp_set_regamma)( + struct output_pixel_processor *opp, +- const struct gamma_ramp *ramp, +- const struct gamma_parameters *params, +- bool force_bypass); +- +- bool (*opp_map_legacy_and_regamma_hw_to_x_user)( +- struct output_pixel_processor *opp, +- const struct gamma_ramp *gamma_ramp, +- const struct gamma_parameters *params); ++ const struct regamma_params *params); + + void (*opp_set_csc_adjustment)( + struct output_pixel_processor *opp, +diff --git a/drivers/gpu/drm/amd/dal/include/video_csc_types.h b/drivers/gpu/drm/amd/dal/include/video_csc_types.h +index c229f5a..e2a9343 100644 +--- a/drivers/gpu/drm/amd/dal/include/video_csc_types.h ++++ b/drivers/gpu/drm/amd/dal/include/video_csc_types.h +@@ -108,7 +108,6 @@ struct ovl_csc_adjustment { + uint32_t matrix_divider; + + /* DCE50 parameters */ +- struct regamma_lut regamma; + enum overlay_gamma_adjust adjust_gamma_type; + enum overlay_csc_adjust_type adjust_csc_type; + enum overlay_gamut_adjust_type adjust_gamut_type; +diff --git a/drivers/gpu/drm/amd/dal/include/video_gamma_types.h b/drivers/gpu/drm/amd/dal/include/video_gamma_types.h +index 6f9cd3f..e910711 100644 +--- a/drivers/gpu/drm/amd/dal/include/video_gamma_types.h ++++ b/drivers/gpu/drm/amd/dal/include/video_gamma_types.h +@@ -49,7 +49,6 @@ struct overlay_gamma_parameters { + int32_t ovl_gamma_cont; + enum overlay_gamma_adjust adjust_type; + enum pixel_format desktop_surface; +- struct regamma_lut regamma; + + /* here we grow with parameters if necessary */ + }; +-- +2.7.4 + |