summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAmy Zhang <Amy.Zhang@amd.com>2017-01-05 17:12:20 -0500
committerAlex Deucher <alexander.deucher@amd.com>2017-09-26 17:09:48 -0400
commitfcd2f4bf8bbe73ac860d1be275a22a54a8d8d385 (patch)
tree30a5335d72e4447205c7cef07e0c6a0a411edf43
parent457b74cb3773a1950e49c2d4826d1b295c59bdf1 (diff)
downloadlinux-stable-fcd2f4bf8bbe73ac860d1be275a22a54a8d8d385.tar.gz
linux-stable-fcd2f4bf8bbe73ac860d1be275a22a54a8d8d385.tar.bz2
linux-stable-fcd2f4bf8bbe73ac860d1be275a22a54a8d8d385.zip
drm/amd/display: Output Transfer Function Regamma Refactor
- Create translation function to translate logical format to hw format - Refactor to use transfer function in dc instead of input gamma Signed-off-by: Amy Zhang <Amy.Zhang@amd.com> Acked-by: Harry Wentland <Harry.Wentland@amd.com> Reviewed-by: Anthony Koo <Anthony.Koo@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
-rw-r--r--drivers/gpu/drm/amd/display/dc/basics/fixpt31_32.c9
-rw-r--r--drivers/gpu/drm/amd/display/dc/calcs/Makefile2
-rw-r--r--drivers/gpu/drm/amd/display/dc/calcs/gamma_calcs.c1481
-rw-r--r--drivers/gpu/drm/amd/display/dc/core/dc.c10
-rw-r--r--drivers/gpu/drm/amd/display/dc/dc.h11
-rw-r--r--drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c440
-rw-r--r--drivers/gpu/drm/amd/display/dc/inc/gamma_calcs.h20
-rw-r--r--drivers/gpu/drm/amd/display/dc/inc/hw/opp.h2
-rw-r--r--drivers/gpu/drm/amd/display/include/fixed31_32.h8
9 files changed, 466 insertions, 1517 deletions
diff --git a/drivers/gpu/drm/amd/display/dc/basics/fixpt31_32.c b/drivers/gpu/drm/amd/display/dc/basics/fixpt31_32.c
index 5a6e46843502..546ed67c6f83 100644
--- a/drivers/gpu/drm/amd/display/dc/basics/fixpt31_32.c
+++ b/drivers/gpu/drm/amd/display/dc/basics/fixpt31_32.c
@@ -246,6 +246,15 @@ struct fixed31_32 dal_fixed31_32_add(
return res;
}
+struct fixed31_32 dal_fixed31_32_add_int(
+ struct fixed31_32 arg1,
+ int32_t arg2)
+{
+ return dal_fixed31_32_add(
+ arg1,
+ dal_fixed31_32_from_int(arg2));
+}
+
struct fixed31_32 dal_fixed31_32_sub_int(
struct fixed31_32 arg1,
int32_t arg2)
diff --git a/drivers/gpu/drm/amd/display/dc/calcs/Makefile b/drivers/gpu/drm/amd/display/dc/calcs/Makefile
index 4001933e7808..4bb08aea6a03 100644
--- a/drivers/gpu/drm/amd/display/dc/calcs/Makefile
+++ b/drivers/gpu/drm/amd/display/dc/calcs/Makefile
@@ -3,7 +3,7 @@
# It calculates Bandwidth and Watermarks values for HW programming
#
-BW_CALCS = bandwidth_calcs.o bw_fixed.o gamma_calcs.o
+BW_CALCS = bandwidth_calcs.o bw_fixed.o
AMD_DAL_BW_CALCS = $(addprefix $(AMDDALPATH)/dc/calcs/,$(BW_CALCS))
diff --git a/drivers/gpu/drm/amd/display/dc/calcs/gamma_calcs.c b/drivers/gpu/drm/amd/display/dc/calcs/gamma_calcs.c
deleted file mode 100644
index fd300db833c7..000000000000
--- a/drivers/gpu/drm/amd/display/dc/calcs/gamma_calcs.c
+++ /dev/null
@@ -1,1481 +0,0 @@
-/*
- * 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"
-
-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 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;
-
- int8_t num_regions = 0;
-
- 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]);
- ++num_regions;
-
- ++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 < (begin + num_regions))) {
- 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;
- points[index].adjusted_x = region1;
-
- ++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;
- points[index].adjusted_x = region1;
-
- *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_pq(
- struct gamma_curve *arr_curve_points,
- struct curve_points *arr_points,
- uint32_t *hw_points_num,
- struct hw_x_point *coordinates_x,
- enum surface_pixel_format format)
-{
- struct curve_config cfg;
-
- cfg.offset = 0;
- cfg.segments[0] = 2;
- cfg.segments[1] = 2;
- cfg.segments[2] = 2;
- cfg.segments[3] = 2;
- cfg.segments[4] = 2;
- cfg.segments[5] = 2;
- cfg.segments[6] = 3;
- cfg.segments[7] = 4;
- cfg.segments[8] = 4;
- cfg.segments[9] = 4;
- cfg.segments[10] = 4;
- cfg.segments[11] = 5;
- cfg.segments[12] = 5;
- cfg.segments[13] = 5;
- cfg.segments[14] = 5;
- cfg.segments[15] = 5;
-
- if (format == SURFACE_PIXEL_FORMAT_GRPH_ARGB16161616F ||
- format == SURFACE_PIXEL_FORMAT_GRPH_ABGR16161616F)
- cfg.begin = -11;
- else
- cfg.begin = -16;
-
- if (!build_hw_curve_configuration(
- &cfg, arr_curve_points,
- arr_points,
- coordinates_x, hw_points_num)) {
- ASSERT_CRITICAL(false);
- return false;
- }
- return true;
-}
-
-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 = INPUT_LUT_ENTRIES + 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 >= INPUT_LUT_ENTRIES + 3) {
- BREAK_TO_DEBUGGER();
- return false;
- }
-
- if (index_right >= INPUT_LUT_ENTRIES + 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 compute_pq(struct fixed31_32 in_x, struct fixed31_32 *out_y)
-{
- /* consts for PQ gamma formula. */
- const struct fixed31_32 m1 =
- dal_fixed31_32_from_fraction(159301758, 1000000000);
- const struct fixed31_32 m2 =
- dal_fixed31_32_from_fraction(7884375, 100000);
- const struct fixed31_32 c1 =
- dal_fixed31_32_from_fraction(8359375, 10000000);
- const struct fixed31_32 c2 =
- dal_fixed31_32_from_fraction(188515625, 10000000);
- const struct fixed31_32 c3 =
- dal_fixed31_32_from_fraction(186875, 10000);
-
- struct fixed31_32 l_pow_m1;
- struct fixed31_32 base;
-
- if (dal_fixed31_32_lt(in_x, dal_fixed31_32_zero))
- in_x = dal_fixed31_32_zero;
-
- l_pow_m1 = dal_fixed31_32_pow(in_x, m1);
- base = dal_fixed31_32_div(
- dal_fixed31_32_add(c1,
- (dal_fixed31_32_mul(c2, l_pow_m1))),
- dal_fixed31_32_add(dal_fixed31_32_one,
- (dal_fixed31_32_mul(c3, l_pow_m1))));
- *out_y = dal_fixed31_32_pow(base, m2);
-}
-
-static void build_regamma_curve_pq(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 pwl_float_data_ex *rgb = rgb_regamma;
- const struct hw_x_point *coord_x = coordinate_x;
- struct fixed31_32 x;
- struct fixed31_32 output;
- struct fixed31_32 scaling_factor =
- dal_fixed31_32_from_fraction(8, 1000);
-
- /* use coord_x to retrieve coordinates chosen base on given user curve
- * the x values are exponentially distributed and currently it is hard
- * coded, the user curve shape is ignored. Need to recalculate coord_x
- * based on input curve, translation from 256/1025 to 128 PWL points.
- */
- for (i = 0; i <= hw_points_num; i++) {
- /* Multiply 0.008 as regamma is 0-1 and FP16 input is 0-125.
- * FP 1.0 = 80nits
- */
- x = dal_fixed31_32_mul(coord_x->adjusted_x, scaling_factor);
-
- compute_pq(x, &output);
-
- /* should really not happen? */
- if (dal_fixed31_32_lt(output, dal_fixed31_32_zero))
- output = dal_fixed31_32_zero;
- else if (dal_fixed31_32_lt(dal_fixed31_32_one, output))
- output = dal_fixed31_32_one;
-
- rgb->r = output;
- rgb->g = output;
- rgb->b = output;
-
- ++coord_x;
- ++rgb;
- }
-}
-
-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 *gamma = &ramp->public;
- const uint16_t max_driver = 0xFFFF;
- const uint16_t max_os = 0xFF00;
- uint16_t scaler = max_os;
- uint32_t i = 0;
- struct pwl_float_data *rgb = pwl_rgb;
- struct pwl_float_data *rgb_last = rgb + INPUT_LUT_ENTRIES - 1;
-
- do {
- if ((gamma->red[i] > max_os) ||
- (gamma->green[i] > max_os) ||
- (gamma->blue[i] > max_os)) {
- scaler = max_driver;
- break;
- }
- ++i;
- } while (i != INPUT_LUT_ENTRIES);
-
- 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 != INPUT_LUT_ENTRIES);
-
- 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 += INPUT_LUT_ENTRIES;
-
- /* 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,
- enum dc_transfer_func_predefined tf)
-{
- struct fixed31_32 y_r;
- struct fixed31_32 y_g;
- struct fixed31_32 y_b;
-
- struct fixed31_32 y1_min;
- 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);
-
- /* this should be cleaned up as it's confusing my understanding (KK) is
- * that REGAMMA_CNTLA_EXP_REGION_END is the X value for the region end
- * REGAMMA_CNTLA_EXP_REGION_END_BASE is Y value for the above X
- * REGAMMA_CNTLA_EXP_REGION_END_SLOPE is the slope beyond (X,Y) above
- * currently when programming REGION_END = m_arrPoints[1].x,
- * REGION_END_BASE = m_arrPoints[1].y, REGION_END_SLOPE=1
- * we don't use m_arrPoints[2] at all after this function,
- * and its purpose isn't clear to me
- */
- arr_points[1].x = coordinates_x[hw_points_num].adjusted_x;
- arr_points[2].x = coordinates_x[hw_points_num].adjusted_x;
-
- y_r = rgb_resulted[hw_points_num].red;
- y_g = rgb_resulted[hw_points_num].green;
- y_b = rgb_resulted[hw_points_num].blue;
-
- /* see comment above, m_arrPoints[1].y should be the Y value for the
- * region end (m_numOfHwPoints), not last HW point(m_numOfHwPoints - 1)
- */
- y3_max = dal_fixed31_32_max(y_r, dal_fixed31_32_max(y_g, y_b));
-
- arr_points[1].y = y3_max;
- arr_points[2].y = y3_max;
-
- arr_points[2].slope = dal_fixed31_32_zero;
-
- /* for PQ, we want to have a straight line from last HW X point, and the
- * slope to be such that we hit 1.0 at 10000 nits.
- */
- if (tf == TRANSFER_FUNCTION_PQ) {
- const struct fixed31_32 end_value =
- dal_fixed31_32_from_int(125);
-
- arr_points[2].slope = dal_fixed31_32_div(
- dal_fixed31_32_sub(dal_fixed31_32_one, arr_points[1].y),
- dal_fixed31_32_sub(end_value, arr_points[1].x));
- }
-}
-
-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;
-}
-
-bool calculate_regamma_params(struct pwl_params *params,
- const struct core_gamma *ramp,
- const struct core_surface *surface,
- const struct core_stream *stream)
-{
- struct gamma_curve *arr_curve_points = params->arr_curve_points;
- struct curve_points *arr_points = params->arr_points;
- struct pwl_result_data *rgb_resulted = params->rgb_resulted;
- struct dividers dividers;
-
- struct hw_x_point *coordinates_x = NULL;
- struct pwl_float_data *rgb_user = NULL ;
- struct pwl_float_data_ex *rgb_regamma = NULL;
- struct pwl_float_data *rgb_oem = NULL;
- struct gamma_pixel *axix_x_256 = NULL;
- struct pixel_gamma_point *coeff128_oem = NULL;
- struct pixel_gamma_point *coeff128 = NULL;
-
- enum dc_transfer_func_predefined tf = TRANSFER_FUNCTION_SRGB;
-
- bool ret = false;
-
- coordinates_x = dm_alloc(sizeof(*coordinates_x)*(256 + 3));
- if (!coordinates_x)
- goto coordinates_x_alloc_fail;
- rgb_user = dm_alloc(sizeof(*rgb_user) * (TRANSFER_FUNC_POINTS + 3));
- if (!rgb_user)
- goto rgb_user_alloc_fail;
- rgb_regamma = dm_alloc(sizeof(*rgb_regamma) * (256 + 3));
- if (!rgb_regamma)
- goto rgb_regamma_alloc_fail;
- rgb_oem = dm_alloc(sizeof(*rgb_oem) * (TRANSFER_FUNC_POINTS + 3));
- if (!rgb_oem)
- goto rgb_oem_alloc_fail;
- axix_x_256 = dm_alloc(sizeof(*axix_x_256) * (256 + 3));
- if (!axix_x_256)
- goto axix_x_256_alloc_fail;
- coeff128_oem = dm_alloc(sizeof(*coeff128_oem) * (256 + 3));
- if (!coeff128_oem)
- goto coeff128_oem_alloc_fail;
- coeff128 = dm_alloc(sizeof(*coeff128) * (256 + 3));
- if (!coeff128)
- goto coeff128_alloc_fail;
-
- dividers.divider1 = dal_fixed31_32_from_fraction(3, 2);
- dividers.divider2 = dal_fixed31_32_from_int(2);
- dividers.divider3 = dal_fixed31_32_from_fraction(5, 2);
-
- if (stream->public.out_transfer_func)
- tf = stream->public.out_transfer_func->tf;
-
- build_evenly_distributed_points(
- axix_x_256,
- 256,
- dal_fixed31_32_one,
- dividers);
-
- scale_gamma(rgb_user, ramp, dividers);
-
- if (tf == TRANSFER_FUNCTION_PQ) {
- setup_distribution_points_pq(arr_curve_points, arr_points,
- &params->hw_points_num, coordinates_x,
- surface->public.format);
- build_regamma_curve_pq(rgb_regamma, rgb_oem, coeff128_oem,
- ramp, surface, params->hw_points_num,
- coordinates_x, axix_x_256, dividers);
- } else {
- setup_distribution_points(arr_curve_points, arr_points,
- &params->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,
- tf);
-
- convert_to_custom_float(rgb_resulted, arr_points,
- params->hw_points_num);
-
- ret = true;
-
- dm_free(coeff128);
-coeff128_alloc_fail:
- dm_free(coeff128_oem);
-coeff128_oem_alloc_fail:
- dm_free(axix_x_256);
-axix_x_256_alloc_fail:
- dm_free(rgb_oem);
-rgb_oem_alloc_fail:
- dm_free(rgb_regamma);
-rgb_regamma_alloc_fail:
- dm_free(rgb_user);
-rgb_user_alloc_fail:
- dm_free(coordinates_x);
-coordinates_x_alloc_fail:
- return ret;
-
-}
-
diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c
index 7d4299b9ee1f..948f82a56472 100644
--- a/drivers/gpu/drm/amd/display/dc/core/dc.c
+++ b/drivers/gpu/drm/amd/display/dc/core/dc.c
@@ -1519,23 +1519,23 @@ void dc_update_surfaces_for_stream(struct dc *dc, struct dc_surface_update *upda
if (dc->debug.disable_color_module)
continue; /* skip below color updates */
- if (updates[i].hdr_static_metadata) {
- resource_build_info_frame(pipe_ctx);
- core_dc->hwss.update_info_frame(pipe_ctx);
- }
if (is_new_pipe_surface[j] ||
updates[i].in_transfer_func)
core_dc->hwss.set_input_transfer_func(
pipe_ctx, pipe_ctx->surface);
if (is_new_pipe_surface[j] ||
- updates[i].gamma ||
updates[i].out_transfer_func)
core_dc->hwss.set_output_transfer_func(
pipe_ctx,
pipe_ctx->surface,
pipe_ctx->stream);
+ if (updates[i].hdr_static_metadata) {
+ resource_build_info_frame(pipe_ctx);
+ core_dc->hwss.update_info_frame(pipe_ctx);
+ }
+
}
if (apply_ctx) {
core_dc->hwss.apply_ctx_for_surface(core_dc, surface, context);
diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h
index b814e7b76bbc..f53b41339951 100644
--- a/drivers/gpu/drm/amd/display/dc/dc.h
+++ b/drivers/gpu/drm/amd/display/dc/dc.h
@@ -213,11 +213,14 @@ enum dc_transfer_func_type {
};
struct dc_transfer_func_distributed_points {
- uint16_t red[TRANSFER_FUNC_POINTS];
- uint16_t green[TRANSFER_FUNC_POINTS];
- uint16_t blue[TRANSFER_FUNC_POINTS];
+ struct fixed31_32 red[TRANSFER_FUNC_POINTS];
+ struct fixed31_32 green[TRANSFER_FUNC_POINTS];
+ struct fixed31_32 blue[TRANSFER_FUNC_POINTS];
+
uint16_t end_exponent;
- uint16_t x_point_at_y1;
+ uint16_t x_point_at_y1_red;
+ uint16_t x_point_at_y1_green;
+ uint16_t x_point_at_y1_blue;
};
enum dc_transfer_func_predefined {
diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c
index 415b12accd2c..6e70cf7b99ef 100644
--- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c
+++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c
@@ -42,7 +42,6 @@
#include "stream_encoder.h"
#include "link_encoder.h"
#include "clock_source.h"
-#include "gamma_calcs.h"
#include "audio.h"
#include "dce/dce_hwseq.h"
@@ -286,6 +285,436 @@ static bool dce110_set_input_transfer_func(
return result;
}
+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(
+ 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;
+}
+
+static bool dce110_translate_regamma_to_hw_format(const struct dc_transfer_func
+ *output_tf, struct pwl_params *regamma_params)
+{
+ if (output_tf == NULL || regamma_params == NULL)
+ return false;
+
+ struct gamma_curve *arr_curve_points = regamma_params->arr_curve_points;
+ struct curve_points *arr_points = regamma_params->arr_points;
+ struct pwl_result_data *rgb_resulted = regamma_params->rgb_resulted;
+ struct fixed31_32 y_r;
+ struct fixed31_32 y_g;
+ struct fixed31_32 y_b;
+ struct fixed31_32 y1_min;
+ struct fixed31_32 y3_max;
+
+ int32_t segment_start, segment_end;
+ uint32_t hw_points, start_index;
+ uint32_t i, j;
+
+ memset(regamma_params, 0, sizeof(struct pwl_params));
+
+ if (output_tf->tf == TRANSFER_FUNCTION_PQ) {
+ /* 16 segments x 16 points
+ * segments are from 2^-11 to 2^5
+ */
+ segment_start = -11;
+ segment_end = 5;
+
+ } else {
+ /* 10 segments x 16 points
+ * segment is from 2^-10 to 2^0
+ */
+ segment_start = -10;
+ segment_end = 0;
+ }
+
+ hw_points = (segment_end - segment_start) * 16;
+ j = 0;
+ /* (segment + 25) * 32, every 2nd point */
+ start_index = (segment_start + 25) * 32;
+ for (i = start_index; i <= 1025; i += 2) {
+ if (j > hw_points)
+ break;
+ rgb_resulted[j].red = output_tf->tf_pts.red[i];
+ rgb_resulted[j].green = output_tf->tf_pts.green[i];
+ rgb_resulted[j].blue = output_tf->tf_pts.blue[i];
+ j++;
+ }
+
+ arr_points[0].x = dal_fixed31_32_pow(dal_fixed31_32_from_int(2),
+ dal_fixed31_32_from_int(segment_start));
+ arr_points[1].x = dal_fixed31_32_pow(dal_fixed31_32_from_int(2),
+ dal_fixed31_32_from_int(segment_end));
+ arr_points[2].x = dal_fixed31_32_pow(dal_fixed31_32_from_int(2),
+ dal_fixed31_32_from_int(segment_end));
+
+ 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].y = y1_min;
+ arr_points[0].slope = dal_fixed31_32_div(
+ arr_points[0].y,
+ arr_points[0].x);
+
+ y_r = rgb_resulted[hw_points - 1].red;
+ y_g = rgb_resulted[hw_points - 1].green;
+ y_b = rgb_resulted[hw_points - 1].blue;
+
+ /* see comment above, m_arrPoints[1].y should be the Y value for the
+ * region end (m_numOfHwPoints), not last HW point(m_numOfHwPoints - 1)
+ */
+ y3_max = dal_fixed31_32_max(y_r, dal_fixed31_32_max(y_g, y_b));
+
+ arr_points[1].y = y3_max;
+ arr_points[2].y = y3_max;
+
+ arr_points[1].slope = dal_fixed31_32_zero;
+ arr_points[2].slope = dal_fixed31_32_zero;
+
+ if (output_tf->tf == TRANSFER_FUNCTION_PQ) {
+ /* for PQ, we want to have a straight line from last HW X point,
+ * and the slope to be such that we hit 1.0 at 10000 nits.
+ */
+ const struct fixed31_32 end_value =
+ dal_fixed31_32_from_int(125);
+
+ arr_points[1].slope = dal_fixed31_32_div(
+ dal_fixed31_32_sub(dal_fixed31_32_one, arr_points[1].y),
+ dal_fixed31_32_sub(end_value, arr_points[1].x));
+ arr_points[2].slope = dal_fixed31_32_div(
+ dal_fixed31_32_sub(dal_fixed31_32_one, arr_points[1].y),
+ dal_fixed31_32_sub(end_value, arr_points[1].x));
+ }
+
+ regamma_params->hw_points_num = hw_points;
+
+ for (i = 0; i < segment_end - segment_start; i++) {
+ regamma_params->arr_curve_points[i].offset = i * 16;
+ regamma_params->arr_curve_points[i].segments_num = 4;
+ }
+
+ struct pwl_result_data *rgb = rgb_resulted;
+ struct pwl_result_data *rgb_plus_1 = rgb_resulted + 1;
+
+ i = 1;
+
+ while (i != hw_points + 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;
+ }
+
+ convert_to_custom_float(rgb_resulted, arr_points, hw_points);
+
+ return true;
+}
+
static bool dce110_set_output_transfer_func(
struct pipe_ctx *pipe_ctx,
const struct core_surface *surface, /* Surface - To be removed */
@@ -308,10 +737,13 @@ static bool dce110_set_output_transfer_func(
opp->funcs->opp_power_on_regamma_lut(opp, true);
if (stream->public.out_transfer_func &&
- stream->public.out_transfer_func->type == TF_TYPE_PREDEFINED &&
- stream->public.out_transfer_func->tf == TRANSFER_FUNCTION_SRGB) {
+ stream->public.out_transfer_func->type ==
+ TF_TYPE_PREDEFINED &&
+ stream->public.out_transfer_func->tf ==
+ TRANSFER_FUNCTION_SRGB) {
opp->funcs->opp_set_regamma_mode(opp, OPP_REGAMMA_SRGB);
- } else if (ramp && calculate_regamma_params(regamma_params, ramp, surface, stream)) {
+ } else if (dce110_translate_regamma_to_hw_format(
+ stream->public.out_transfer_func, regamma_params)) {
opp->funcs->opp_program_regamma_pwl(opp, regamma_params);
opp->funcs->opp_set_regamma_mode(opp, OPP_REGAMMA_USER);
} else {
diff --git a/drivers/gpu/drm/amd/display/dc/inc/gamma_calcs.h b/drivers/gpu/drm/amd/display/dc/inc/gamma_calcs.h
deleted file mode 100644
index 0712268856c2..000000000000
--- a/drivers/gpu/drm/amd/display/dc/inc/gamma_calcs.h
+++ /dev/null
@@ -1,20 +0,0 @@
-/*
- * gamma_calcs.h
- *
- * Created on: Feb 9, 2016
- * Author: yonsun
- */
-
-#ifndef DRIVERS_GPU_DRM_AMD_DC_DEV_DC_INC_GAMMA_CALCS_H_
-#define DRIVERS_GPU_DRM_AMD_DC_DEV_DC_INC_GAMMA_CALCS_H_
-
-#include "opp.h"
-#include "core_types.h"
-#include "dc.h"
-
-bool calculate_regamma_params(struct pwl_params *params,
- const struct core_gamma *ramp,
- const struct core_surface *surface,
- const struct core_stream *stream);
-
-#endif /* DRIVERS_GPU_DRM_AMD_DC_DEV_DC_INC_GAMMA_CALCS_H_ */
diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/opp.h b/drivers/gpu/drm/amd/display/dc/inc/hw/opp.h
index a1f31a4410a3..bef5e2cacbe3 100644
--- a/drivers/gpu/drm/amd/display/dc/inc/hw/opp.h
+++ b/drivers/gpu/drm/amd/display/dc/inc/hw/opp.h
@@ -138,9 +138,7 @@ struct custom_float_value {
struct hw_x_point {
uint32_t custom_float_x;
- uint32_t custom_float_x_adjusted;
struct fixed31_32 x;
- struct fixed31_32 adjusted_x;
struct fixed31_32 regamma_y_red;
struct fixed31_32 regamma_y_green;
struct fixed31_32 regamma_y_blue;
diff --git a/drivers/gpu/drm/amd/display/include/fixed31_32.h b/drivers/gpu/drm/amd/display/include/fixed31_32.h
index c28de167250f..5a4364dfd2f7 100644
--- a/drivers/gpu/drm/amd/display/include/fixed31_32.h
+++ b/drivers/gpu/drm/amd/display/include/fixed31_32.h
@@ -192,6 +192,14 @@ struct fixed31_32 dal_fixed31_32_add(
/*
* @brief
+ * result = arg1 + arg2
+ */
+struct fixed31_32 dal_fixed31_32_add_int(
+ struct fixed31_32 arg1,
+ int32_t arg2);
+
+/*
+ * @brief
* result = arg1 - arg2
*/
struct fixed31_32 dal_fixed31_32_sub_int(