From f250ee01f34b61d29f2e8ffd841555fe716f1fb8 Mon Sep 17 00:00:00 2001 From: Yongqiang Sun 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 Acked-by: Jordan Lazare --- .../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