aboutsummaryrefslogtreecommitdiffstats
path: root/common/recipes-kernel/linux/files/0784-drm-amd-dal-Refactor-opp-gamma-related.patch
diff options
context:
space:
mode:
Diffstat (limited to 'common/recipes-kernel/linux/files/0784-drm-amd-dal-Refactor-opp-gamma-related.patch')
-rw-r--r--common/recipes-kernel/linux/files/0784-drm-amd-dal-Refactor-opp-gamma-related.patch5401
1 files changed, 5401 insertions, 0 deletions
diff --git a/common/recipes-kernel/linux/files/0784-drm-amd-dal-Refactor-opp-gamma-related.patch b/common/recipes-kernel/linux/files/0784-drm-amd-dal-Refactor-opp-gamma-related.patch
new file mode 100644
index 00000000..7de664f1
--- /dev/null
+++ b/common/recipes-kernel/linux/files/0784-drm-amd-dal-Refactor-opp-gamma-related.patch
@@ -0,0 +1,5401 @@
+From f250ee01f34b61d29f2e8ffd841555fe716f1fb8 Mon Sep 17 00:00:00 2001
+From: Yongqiang Sun <yongqiang.sun@amd.com>
+Date: Thu, 4 Feb 2016 10:42:38 -0500
+Subject: [PATCH 0784/1110] drm/amd/dal: Refactor opp gamma related.
+
+Signed-off-by: Yongqiang Sun <yongqiang.sun@amd.com>
+Acked-by: Jordan Lazare <Jordan.Lazare@amd.com>
+---
+ .../gpu/drm/amd/dal/amdgpu_dm/amdgpu_dm_types.c | 10 +-
+ drivers/gpu/drm/amd/dal/dc/calcs/Makefile | 2 +-
+ drivers/gpu/drm/amd/dal/dc/calcs/gamma_calcs.c | 1342 +++++++++++++
+ drivers/gpu/drm/amd/dal/dc/core/dc_surface.c | 80 +-
+ drivers/gpu/drm/amd/dal/dc/core/dc_target.c | 77 +-
+ drivers/gpu/drm/amd/dal/dc/dc.h | 43 +-
+ drivers/gpu/drm/amd/dal/dc/dc_types.h | 73 -
+ .../drm/amd/dal/dc/dce110/dce110_hw_sequencer.c | 98 +-
+ .../drm/amd/dal/dc/dce110/dce110_hw_sequencer.h | 1 +
+ drivers/gpu/drm/amd/dal/dc/dce110/dce110_ipp.c | 3 -
+ drivers/gpu/drm/amd/dal/dc/dce110/dce110_ipp.h | 23 +-
+ .../gpu/drm/amd/dal/dc/dce110/dce110_ipp_gamma.c | 639 +------
+ drivers/gpu/drm/amd/dal/dc/dce110/dce110_opp.c | 196 --
+ drivers/gpu/drm/amd/dal/dc/dce110/dce110_opp.h | 13 +-
+ .../gpu/drm/amd/dal/dc/dce110/dce110_opp_regamma.c | 2019 +-------------------
+ drivers/gpu/drm/amd/dal/dc/dce110/dce110_types.h | 58 +
+ drivers/gpu/drm/amd/dal/dc/inc/core_types.h | 9 +
+ drivers/gpu/drm/amd/dal/dc/inc/gamma_calcs.h | 31 +
+ drivers/gpu/drm/amd/dal/dc/inc/gamma_types.h | 48 -
+ drivers/gpu/drm/amd/dal/dc/inc/hw_sequencer.h | 6 +-
+ drivers/gpu/drm/amd/dal/dc/inc/ipp.h | 33 +-
+ drivers/gpu/drm/amd/dal/dc/inc/opp.h | 17 +-
+ drivers/gpu/drm/amd/dal/include/video_csc_types.h | 1 -
+ .../gpu/drm/amd/dal/include/video_gamma_types.h | 1 -
+ 24 files changed, 1790 insertions(+), 3033 deletions(-)
+ create mode 100644 drivers/gpu/drm/amd/dal/dc/calcs/gamma_calcs.c
+ create mode 100644 drivers/gpu/drm/amd/dal/dc/dce110/dce110_types.h
+ create mode 100644 drivers/gpu/drm/amd/dal/dc/inc/gamma_calcs.h
+
+diff --git a/drivers/gpu/drm/amd/dal/amdgpu_dm/amdgpu_dm_types.c b/drivers/gpu/drm/amd/dal/amdgpu_dm/amdgpu_dm_types.c
+index 3f80880..2cb445d 100644
+--- a/drivers/gpu/drm/amd/dal/amdgpu_dm/amdgpu_dm_types.c
++++ b/drivers/gpu/drm/amd/dal/amdgpu_dm/amdgpu_dm_types.c
+@@ -499,16 +499,20 @@ static void fill_gamma_from_crtc(
+ struct dc_surface *dc_surface)
+ {
+ int i;
+- struct gamma_ramp *gamma;
++ struct dc_gamma *gamma;
+ uint16_t *red, *green, *blue;
+ int end = (crtc->gamma_size > NUM_OF_RAW_GAMMA_RAMP_RGB_256) ?
+ NUM_OF_RAW_GAMMA_RAMP_RGB_256 : crtc->gamma_size;
++ struct amdgpu_device *adev = crtc->dev->dev_private;
+
+ red = crtc->gamma_store;
+ green = red + crtc->gamma_size;
+ blue = green + crtc->gamma_size;
+
+- gamma = &dc_surface->gamma_correction;
++ gamma = dc_create_gamma(adev->dm.dc);
++
++ if (gamma == NULL)
++ return;
+
+ for (i = 0; i < end; i++) {
+ gamma->gamma_ramp_rgb256x3x16.red[i] =
+@@ -521,6 +525,8 @@ static void fill_gamma_from_crtc(
+
+ gamma->type = GAMMA_RAMP_RBG256X3X16;
+ gamma->size = sizeof(gamma->gamma_ramp_rgb256x3x16);
++
++ dc_surface->gamma_correction = gamma;
+ }
+
+ static void fill_plane_attributes(
+diff --git a/drivers/gpu/drm/amd/dal/dc/calcs/Makefile b/drivers/gpu/drm/amd/dal/dc/calcs/Makefile
+index 7f1916b..9ac4ad1 100644
+--- a/drivers/gpu/drm/amd/dal/dc/calcs/Makefile
++++ b/drivers/gpu/drm/amd/dal/dc/calcs/Makefile
+@@ -3,7 +3,7 @@
+ # It calculates Bandwidth and Watermarks values for HW programming
+ #
+
+-BW_CALCS = bandwidth_calcs.o bw_fixed.o scaler_filter.o
++BW_CALCS = bandwidth_calcs.o bw_fixed.o scaler_filter.o gamma_calcs.o
+
+ AMD_DAL_BW_CALCS = $(addprefix $(AMDDALPATH)/dc/calcs/,$(BW_CALCS))
+
+diff --git a/drivers/gpu/drm/amd/dal/dc/calcs/gamma_calcs.c b/drivers/gpu/drm/amd/dal/dc/calcs/gamma_calcs.c
+new file mode 100644
+index 0000000..e3a41b3
+--- /dev/null
++++ b/drivers/gpu/drm/amd/dal/dc/calcs/gamma_calcs.c
+@@ -0,0 +1,1342 @@
++/*
++ * Copyright 2015 Advanced Micro Devices, Inc.
++ *
++ * Permission is hereby granted, free of charge, to any person obtaining a
++ * copy of this software and associated documentation files (the "Software"),
++ * to deal in the Software without restriction, including without limitation
++ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
++ * and/or sell copies of the Software, and to permit persons to whom the
++ * Software is furnished to do so, subject to the following conditions:
++ *
++ * The above copyright notice and this permission notice shall be included in
++ * all copies or substantial portions of the Software.
++ *
++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
++ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
++ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
++ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
++ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
++ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
++ * OTHER DEALINGS IN THE SOFTWARE.
++ *
++ * Authors: AMD
++ *
++ */
++
++#include "dm_services.h"
++#include "gamma_calcs.h"
++#include "core_types.h"
++
++struct curve_config {
++ uint32_t offset;
++ int8_t segments[16];
++ int8_t begin;
++};
++
++static bool build_custom_float(
++ struct fixed31_32 value,
++ const struct custom_float_format *format,
++ bool *negative,
++ uint32_t *mantissa,
++ uint32_t *exponenta)
++{
++ uint32_t exp_offset = (1 << (format->exponenta_bits - 1)) - 1;
++
++ const struct fixed31_32 mantissa_constant_plus_max_fraction =
++ dal_fixed31_32_from_fraction(
++ (1LL << (format->mantissa_bits + 1)) - 1,
++ 1LL << format->mantissa_bits);
++
++ struct fixed31_32 mantiss;
++
++ if (dal_fixed31_32_eq(
++ value,
++ dal_fixed31_32_zero)) {
++ *negative = false;
++ *mantissa = 0;
++ *exponenta = 0;
++ return true;
++ }
++
++ if (dal_fixed31_32_lt(
++ value,
++ dal_fixed31_32_zero)) {
++ *negative = format->sign;
++ value = dal_fixed31_32_neg(value);
++ } else {
++ *negative = false;
++ }
++
++ if (dal_fixed31_32_lt(
++ value,
++ dal_fixed31_32_one)) {
++ uint32_t i = 1;
++
++ do {
++ value = dal_fixed31_32_shl(value, 1);
++ ++i;
++ } while (dal_fixed31_32_lt(
++ value,
++ dal_fixed31_32_one));
++
++ --i;
++
++ if (exp_offset <= i) {
++ *mantissa = 0;
++ *exponenta = 0;
++ return true;
++ }
++
++ *exponenta = exp_offset - i;
++ } else if (dal_fixed31_32_le(
++ mantissa_constant_plus_max_fraction,
++ value)) {
++ uint32_t i = 1;
++
++ do {
++ value = dal_fixed31_32_shr(value, 1);
++ ++i;
++ } while (dal_fixed31_32_lt(
++ mantissa_constant_plus_max_fraction,
++ value));
++
++ *exponenta = exp_offset + i - 1;
++ } else {
++ *exponenta = exp_offset;
++ }
++
++ mantiss = dal_fixed31_32_sub(
++ value,
++ dal_fixed31_32_one);
++
++ if (dal_fixed31_32_lt(
++ mantiss,
++ dal_fixed31_32_zero) ||
++ dal_fixed31_32_lt(
++ dal_fixed31_32_one,
++ mantiss))
++ mantiss = dal_fixed31_32_zero;
++ else
++ mantiss = dal_fixed31_32_shl(
++ mantiss,
++ format->mantissa_bits);
++
++ *mantissa = dal_fixed31_32_floor(mantiss);
++
++ return true;
++}
++
++static bool setup_custom_float(
++ const struct custom_float_format *format,
++ bool negative,
++ uint32_t mantissa,
++ uint32_t exponenta,
++ uint32_t *result)
++{
++ uint32_t i = 0;
++ uint32_t j = 0;
++
++ uint32_t value = 0;
++
++ /* verification code:
++ * once calculation is ok we can remove it
++ */
++
++ const uint32_t mantissa_mask =
++ (1 << (format->mantissa_bits + 1)) - 1;
++
++ const uint32_t exponenta_mask =
++ (1 << (format->exponenta_bits + 1)) - 1;
++
++ if (mantissa & ~mantissa_mask) {
++ BREAK_TO_DEBUGGER();
++ mantissa = mantissa_mask;
++ }
++
++ if (exponenta & ~exponenta_mask) {
++ BREAK_TO_DEBUGGER();
++ exponenta = exponenta_mask;
++ }
++
++ /* end of verification code */
++
++ while (i < format->mantissa_bits) {
++ uint32_t mask = 1 << i;
++
++ if (mantissa & mask)
++ value |= mask;
++
++ ++i;
++ }
++
++ while (j < format->exponenta_bits) {
++ uint32_t mask = 1 << j;
++
++ if (exponenta & mask)
++ value |= mask << i;
++
++ ++j;
++ }
++
++ if (negative && format->sign)
++ value |= 1 << (i + j);
++
++ *result = value;
++
++ return true;
++}
++
++
++static bool convert_to_custom_float_format_ex(
++ struct fixed31_32 value,
++ const struct custom_float_format *format,
++ struct custom_float_value *result)
++{
++ return build_custom_float(
++ value, format,
++ &result->negative, &result->mantissa, &result->exponenta) &&
++ setup_custom_float(
++ format, result->negative, result->mantissa, result->exponenta,
++ &result->value);
++}
++
++static bool round_custom_float_6_12(
++ struct hw_x_point *x)
++{
++ struct custom_float_format fmt;
++
++ struct custom_float_value value;
++
++ fmt.exponenta_bits = 6;
++ fmt.mantissa_bits = 12;
++ fmt.sign = true;
++
++ if (!convert_to_custom_float_format_ex(
++ x->x, &fmt, &value))
++ return false;
++
++ x->adjusted_x = x->x;
++
++ if (value.mantissa) {
++ BREAK_TO_DEBUGGER();
++
++ return false;
++ }
++
++ return true;
++}
++
++static bool build_hw_curve_configuration(
++ const struct curve_config *curve_config,
++ struct gamma_curve *gamma_curve,
++ struct curve_points *curve_points,
++ struct hw_x_point *points,
++ uint32_t *number_of_points)
++{
++ const int8_t max_regions_number = ARRAY_SIZE(curve_config->segments);
++
++ int8_t i;
++
++ uint8_t segments_calculation[8] = { 0 };
++
++ struct fixed31_32 region1 = dal_fixed31_32_zero;
++ struct fixed31_32 region2;
++ struct fixed31_32 increment;
++
++ uint32_t index = 0;
++ uint32_t segments = 0;
++ uint32_t max_number;
++
++ bool result = false;
++
++ if (!number_of_points) {
++ BREAK_TO_DEBUGGER();
++ return false;
++ }
++
++ max_number = *number_of_points;
++
++ i = 0;
++
++ while (i != max_regions_number) {
++ gamma_curve[i].offset = 0;
++ gamma_curve[i].segments_num = 0;
++
++ ++i;
++ }
++
++ i = 0;
++
++ while (i != max_regions_number) {
++ /* number should go in uninterruptible sequence */
++ if (curve_config->segments[i] == -1)
++ break;
++
++ ASSERT(curve_config->segments[i] >= 0);
++
++ segments += (1 << curve_config->segments[i]);
++
++ ++i;
++ }
++
++ if (segments > max_number) {
++ BREAK_TO_DEBUGGER();
++ } else {
++ int32_t divisor;
++ uint32_t offset = 0;
++ int8_t begin = curve_config->begin;
++ int32_t region_number = 0;
++
++ i = begin;
++
++ while ((index < max_number) &&
++ (region_number < max_regions_number) &&
++ (i <= 1)) {
++ int32_t j = 0;
++
++ segments = curve_config->segments[region_number];
++ divisor = 1 << segments;
++
++ if (segments == -1) {
++ if (i > 0) {
++ region1 = dal_fixed31_32_shl(
++ dal_fixed31_32_one,
++ i - 1);
++ region2 = dal_fixed31_32_shl(
++ dal_fixed31_32_one,
++ i);
++ } else {
++ region1 = dal_fixed31_32_shr(
++ dal_fixed31_32_one,
++ -(i - 1));
++ region2 = dal_fixed31_32_shr(
++ dal_fixed31_32_one,
++ -i);
++ }
++
++ break;
++ }
++
++ if (i > -1) {
++ region1 = dal_fixed31_32_shl(
++ dal_fixed31_32_one,
++ i);
++ region2 = dal_fixed31_32_shl(
++ dal_fixed31_32_one,
++ i + 1);
++ } else {
++ region1 = dal_fixed31_32_shr(
++ dal_fixed31_32_one,
++ -i);
++ region2 = dal_fixed31_32_shr(
++ dal_fixed31_32_one,
++ -(i + 1));
++ }
++
++ gamma_curve[region_number].offset = offset;
++ gamma_curve[region_number].segments_num = segments;
++
++ offset += divisor;
++
++ ++segments_calculation[segments];
++
++ increment = dal_fixed31_32_div_int(
++ dal_fixed31_32_sub(
++ region2,
++ region1),
++ divisor);
++
++ points[index].x = region1;
++
++ round_custom_float_6_12(points + index);
++
++ ++index;
++ ++region_number;
++
++ while ((index < max_number) && (j < divisor - 1)) {
++ region1 = dal_fixed31_32_add(
++ region1,
++ increment);
++
++ points[index].x = region1;
++ points[index].adjusted_x = region1;
++
++ ++index;
++ ++j;
++ }
++
++ ++i;
++ }
++
++ points[index].x = region1;
++
++ round_custom_float_6_12(points + index);
++
++ *number_of_points = index;
++
++ result = true;
++ }
++
++ curve_points[0].x = points[0].adjusted_x;
++ curve_points[0].offset = dal_fixed31_32_zero;
++
++ curve_points[1].x = points[index - 1].adjusted_x;
++ curve_points[1].offset = dal_fixed31_32_zero;
++
++ curve_points[2].x = points[index].adjusted_x;
++ curve_points[2].offset = dal_fixed31_32_zero;
++
++ return result;
++}
++
++static bool setup_distribution_points(
++ struct gamma_curve *arr_curve_points,
++ struct curve_points *arr_points,
++ uint32_t *hw_points_num,
++ struct hw_x_point *coordinates_x)
++{
++ struct curve_config cfg;
++
++ cfg.offset = 0;
++ cfg.segments[0] = 3;
++ cfg.segments[1] = 4;
++ cfg.segments[2] = 4;
++ cfg.segments[3] = 4;
++ cfg.segments[4] = 4;
++ cfg.segments[5] = 4;
++ cfg.segments[6] = 4;
++ cfg.segments[7] = 4;
++ cfg.segments[8] = 5;
++ cfg.segments[9] = 5;
++ cfg.segments[10] = 0;
++ cfg.segments[11] = -1;
++ cfg.segments[12] = -1;
++ cfg.segments[13] = -1;
++ cfg.segments[14] = -1;
++ cfg.segments[15] = -1;
++
++ cfg.begin = -10;
++
++ if (!build_hw_curve_configuration(
++ &cfg, arr_curve_points,
++ arr_points,
++ coordinates_x, hw_points_num)) {
++ ASSERT_CRITICAL(false);
++ return false;
++ }
++ return true;
++}
++
++struct dividers {
++ struct fixed31_32 divider1;
++ struct fixed31_32 divider2;
++ struct fixed31_32 divider3;
++};
++
++
++static void build_regamma_coefficients(struct gamma_coefficients *coefficients)
++{
++ /* sRGB should apply 2.4 */
++ static const int32_t numerator01[3] = { 31308, 31308, 31308 };
++ static const int32_t numerator02[3] = { 12920, 12920, 12920 };
++ static const int32_t numerator03[3] = { 55, 55, 55 };
++ static const int32_t numerator04[3] = { 55, 55, 55 };
++ static const int32_t numerator05[3] = { 2400, 2400, 2400 };
++
++ const int32_t *numerator1;
++ const int32_t *numerator2;
++ const int32_t *numerator3;
++ const int32_t *numerator4;
++ const int32_t *numerator5;
++
++ uint32_t i = 0;
++
++ numerator1 = numerator01;
++ numerator2 = numerator02;
++ numerator3 = numerator03;
++ numerator4 = numerator04;
++ numerator5 = numerator05;
++
++ do {
++ coefficients->a0[i] = dal_fixed31_32_from_fraction(
++ numerator1[i], 10000000);
++ coefficients->a1[i] = dal_fixed31_32_from_fraction(
++ numerator2[i], 1000);
++ coefficients->a2[i] = dal_fixed31_32_from_fraction(
++ numerator3[i], 1000);
++ coefficients->a3[i] = dal_fixed31_32_from_fraction(
++ numerator4[i], 1000);
++ coefficients->user_gamma[i] = dal_fixed31_32_from_fraction(
++ numerator5[i], 1000);
++
++ ++i;
++ } while (i != ARRAY_SIZE(coefficients->a0));
++}
++
++static struct fixed31_32 translate_from_linear_space(
++ struct fixed31_32 arg,
++ struct fixed31_32 a0,
++ struct fixed31_32 a1,
++ struct fixed31_32 a2,
++ struct fixed31_32 a3,
++ struct fixed31_32 gamma)
++{
++ const struct fixed31_32 one = dal_fixed31_32_from_int(1);
++
++ if (dal_fixed31_32_le(arg, dal_fixed31_32_neg(a0)))
++ return dal_fixed31_32_sub(
++ a2,
++ dal_fixed31_32_mul(
++ dal_fixed31_32_add(
++ one,
++ a3),
++ dal_fixed31_32_pow(
++ dal_fixed31_32_neg(arg),
++ dal_fixed31_32_recip(gamma))));
++ else if (dal_fixed31_32_le(a0, arg))
++ return dal_fixed31_32_sub(
++ dal_fixed31_32_mul(
++ dal_fixed31_32_add(
++ one,
++ a3),
++ dal_fixed31_32_pow(
++ arg,
++ dal_fixed31_32_recip(gamma))),
++ a2);
++ else
++ return dal_fixed31_32_mul(
++ arg,
++ a1);
++}
++
++static inline struct fixed31_32 translate_from_linear_space_ex(
++ struct fixed31_32 arg,
++ struct gamma_coefficients *coeff,
++ uint32_t color_index)
++{
++ return translate_from_linear_space(
++ arg,
++ coeff->a0[color_index],
++ coeff->a1[color_index],
++ coeff->a2[color_index],
++ coeff->a3[color_index],
++ coeff->user_gamma[color_index]);
++}
++
++static bool find_software_points(
++ const struct gamma_pixel *axis_x_256,
++ struct fixed31_32 hw_point,
++ enum channel_name channel,
++ uint32_t *index_to_start,
++ uint32_t *index_left,
++ uint32_t *index_right,
++ enum hw_point_position *pos)
++{
++ const uint32_t max_number = RGB_256X3X16 + 3;
++
++ struct fixed31_32 left, right;
++
++ uint32_t i = *index_to_start;
++
++ while (i < max_number) {
++ if (channel == CHANNEL_NAME_RED) {
++ left = axis_x_256[i].r;
++
++ if (i < max_number - 1)
++ right = axis_x_256[i + 1].r;
++ else
++ right = axis_x_256[max_number - 1].r;
++ } else if (channel == CHANNEL_NAME_GREEN) {
++ left = axis_x_256[i].g;
++
++ if (i < max_number - 1)
++ right = axis_x_256[i + 1].g;
++ else
++ right = axis_x_256[max_number - 1].g;
++ } else {
++ left = axis_x_256[i].b;
++
++ if (i < max_number - 1)
++ right = axis_x_256[i + 1].b;
++ else
++ right = axis_x_256[max_number - 1].b;
++ }
++
++ if (dal_fixed31_32_le(left, hw_point) &&
++ dal_fixed31_32_le(hw_point, right)) {
++ *index_to_start = i;
++ *index_left = i;
++
++ if (i < max_number - 1)
++ *index_right = i + 1;
++ else
++ *index_right = max_number - 1;
++
++ *pos = HW_POINT_POSITION_MIDDLE;
++
++ return true;
++ } else if ((i == *index_to_start) &&
++ dal_fixed31_32_le(hw_point, left)) {
++ *index_to_start = i;
++ *index_left = i;
++ *index_right = i;
++
++ *pos = HW_POINT_POSITION_LEFT;
++
++ return true;
++ } else if ((i == max_number - 1) &&
++ dal_fixed31_32_le(right, hw_point)) {
++ *index_to_start = i;
++ *index_left = i;
++ *index_right = i;
++
++ *pos = HW_POINT_POSITION_RIGHT;
++
++ return true;
++ }
++
++ ++i;
++ }
++
++ return false;
++}
++
++static bool build_custom_gamma_mapping_coefficients_worker(
++ struct pixel_gamma_point *coeff,
++ const struct hw_x_point *coordinates_x,
++ const struct gamma_pixel *axis_x_256,
++ enum channel_name channel,
++ uint32_t number_of_points,
++ enum surface_pixel_format pixel_format)
++{
++ uint32_t i = 0;
++
++ while (i <= number_of_points) {
++ struct fixed31_32 coord_x;
++
++ uint32_t index_to_start = 0;
++ uint32_t index_left = 0;
++ uint32_t index_right = 0;
++
++ enum hw_point_position hw_pos;
++
++ struct gamma_point *point;
++
++ struct fixed31_32 left_pos;
++ struct fixed31_32 right_pos;
++
++ /*
++ * TODO: confirm enum in surface_pixel_format
++ * if (pixel_format == PIXEL_FORMAT_FP16)
++ *coord_x = coordinates_x[i].adjusted_x;
++ *else
++ */
++ if (channel == CHANNEL_NAME_RED)
++ coord_x = coordinates_x[i].regamma_y_red;
++ else if (channel == CHANNEL_NAME_GREEN)
++ coord_x = coordinates_x[i].regamma_y_green;
++ else
++ coord_x = coordinates_x[i].regamma_y_blue;
++
++ if (!find_software_points(
++ axis_x_256, coord_x, channel,
++ &index_to_start, &index_left, &index_right, &hw_pos)) {
++ BREAK_TO_DEBUGGER();
++ return false;
++ }
++
++ if (index_left >= RGB_256X3X16 + 3) {
++ BREAK_TO_DEBUGGER();
++ return false;
++ }
++
++ if (index_right >= RGB_256X3X16 + 3) {
++ BREAK_TO_DEBUGGER();
++ return false;
++ }
++
++ if (channel == CHANNEL_NAME_RED) {
++ point = &coeff[i].r;
++
++ left_pos = axis_x_256[index_left].r;
++ right_pos = axis_x_256[index_right].r;
++ } else if (channel == CHANNEL_NAME_GREEN) {
++ point = &coeff[i].g;
++
++ left_pos = axis_x_256[index_left].g;
++ right_pos = axis_x_256[index_right].g;
++ } else {
++ point = &coeff[i].b;
++
++ left_pos = axis_x_256[index_left].b;
++ right_pos = axis_x_256[index_right].b;
++ }
++
++ if (hw_pos == HW_POINT_POSITION_MIDDLE)
++ point->coeff = dal_fixed31_32_div(
++ dal_fixed31_32_sub(
++ coord_x,
++ left_pos),
++ dal_fixed31_32_sub(
++ right_pos,
++ left_pos));
++ else if (hw_pos == HW_POINT_POSITION_LEFT)
++ point->coeff = dal_fixed31_32_zero;
++ else if (hw_pos == HW_POINT_POSITION_RIGHT)
++ point->coeff = dal_fixed31_32_from_int(2);
++ else {
++ BREAK_TO_DEBUGGER();
++ return false;
++ }
++
++ point->left_index = index_left;
++ point->right_index = index_right;
++ point->pos = hw_pos;
++
++ ++i;
++ }
++
++ return true;
++}
++
++static inline bool build_oem_custom_gamma_mapping_coefficients(
++ struct pixel_gamma_point *coeff128_oem,
++ const struct hw_x_point *coordinates_x,
++ const struct gamma_pixel *axis_x_256,
++ uint32_t number_of_points,
++ enum surface_pixel_format pixel_format)
++{
++ int i;
++
++ for (i = 0; i < 3; i++) {
++ if (!build_custom_gamma_mapping_coefficients_worker(
++ coeff128_oem, coordinates_x, axis_x_256, i,
++ number_of_points, pixel_format))
++ return false;
++ }
++ return true;
++}
++
++static struct fixed31_32 calculate_mapped_value(
++ struct pwl_float_data *rgb,
++ const struct pixel_gamma_point *coeff,
++ enum channel_name channel,
++ uint32_t max_index)
++{
++ const struct gamma_point *point;
++
++ struct fixed31_32 result;
++
++ if (channel == CHANNEL_NAME_RED)
++ point = &coeff->r;
++ else if (channel == CHANNEL_NAME_GREEN)
++ point = &coeff->g;
++ else
++ point = &coeff->b;
++
++ if ((point->left_index < 0) || (point->left_index > max_index)) {
++ BREAK_TO_DEBUGGER();
++ return dal_fixed31_32_zero;
++ }
++
++ if ((point->right_index < 0) || (point->right_index > max_index)) {
++ BREAK_TO_DEBUGGER();
++ return dal_fixed31_32_zero;
++ }
++
++ if (point->pos == HW_POINT_POSITION_MIDDLE)
++ if (channel == CHANNEL_NAME_RED)
++ result = dal_fixed31_32_add(
++ dal_fixed31_32_mul(
++ point->coeff,
++ dal_fixed31_32_sub(
++ rgb[point->right_index].r,
++ rgb[point->left_index].r)),
++ rgb[point->left_index].r);
++ else if (channel == CHANNEL_NAME_GREEN)
++ result = dal_fixed31_32_add(
++ dal_fixed31_32_mul(
++ point->coeff,
++ dal_fixed31_32_sub(
++ rgb[point->right_index].g,
++ rgb[point->left_index].g)),
++ rgb[point->left_index].g);
++ else
++ result = dal_fixed31_32_add(
++ dal_fixed31_32_mul(
++ point->coeff,
++ dal_fixed31_32_sub(
++ rgb[point->right_index].b,
++ rgb[point->left_index].b)),
++ rgb[point->left_index].b);
++ else if (point->pos == HW_POINT_POSITION_LEFT) {
++ BREAK_TO_DEBUGGER();
++ result = dal_fixed31_32_zero;
++ } else {
++ BREAK_TO_DEBUGGER();
++ result = dal_fixed31_32_one;
++ }
++
++ return result;
++}
++
++static inline struct fixed31_32 calculate_oem_mapped_value(
++ struct pwl_float_data *rgb_oem,
++ const struct pixel_gamma_point *coeff,
++ uint32_t index,
++ enum channel_name channel,
++ uint32_t max_index)
++{
++ return calculate_mapped_value(
++ rgb_oem,
++ coeff + index,
++ channel,
++ max_index);
++}
++
++static void build_regamma_curve(struct pwl_float_data_ex *rgb_regamma,
++ struct pwl_float_data *rgb_oem,
++ struct pixel_gamma_point *coeff128_oem,
++ const struct core_gamma *ramp,
++ const struct core_surface *surface,
++ uint32_t hw_points_num,
++ const struct hw_x_point *coordinate_x,
++ const struct gamma_pixel *axis_x,
++ struct dividers dividers)
++{
++ uint32_t i;
++
++ struct gamma_coefficients coeff;
++ struct pwl_float_data_ex *rgb = rgb_regamma;
++ const struct hw_x_point *coord_x = coordinate_x;
++
++ build_regamma_coefficients(&coeff);
++
++ /* Use opp110->regamma.coordinates_x to retrieve
++ * coordinates chosen base on given user curve (future task).
++ * The x values are exponentially distributed and currently
++ * it is hard-coded, the user curve shape is ignored.
++ * The future task is to recalculate opp110-
++ * regamma.coordinates_x based on input/user curve,
++ * translation from 256/1025 to 128 pwl points.
++ */
++
++ i = 0;
++
++ while (i != hw_points_num + 1) {
++ rgb->r = translate_from_linear_space_ex(
++ coord_x->adjusted_x, &coeff, 0);
++ rgb->g = translate_from_linear_space_ex(
++ coord_x->adjusted_x, &coeff, 1);
++ rgb->b = translate_from_linear_space_ex(
++ coord_x->adjusted_x, &coeff, 2);
++
++ ++coord_x;
++ ++rgb;
++ ++i;
++ }
++}
++
++static bool scale_gamma(struct pwl_float_data *pwl_rgb,
++ const struct core_gamma *ramp,
++ struct dividers dividers)
++{
++ const struct dc_gamma_ramp_rgb256x3x16 *gamma;
++ const uint16_t max_driver = 0xFFFF;
++ const uint16_t max_os = 0xFF00;
++ uint16_t scaler = max_os;
++ uint32_t i;
++ struct pwl_float_data *rgb = pwl_rgb;
++ struct pwl_float_data *rgb_last = rgb + RGB_256X3X16 - 1;
++
++ if (ramp->public.type == GAMMA_RAMP_RBG256X3X16)
++ gamma = &ramp->public.gamma_ramp_rgb256x3x16;
++ else
++ return false; /* invalid option */
++
++ i = 0;
++
++ do {
++ if ((gamma->red[i] > max_os) ||
++ (gamma->green[i] > max_os) ||
++ (gamma->blue[i] > max_os)) {
++ scaler = max_driver;
++ break;
++ }
++ ++i;
++ } while (i != RGB_256X3X16);
++
++ i = 0;
++
++ do {
++ rgb->r = dal_fixed31_32_from_fraction(
++ gamma->red[i], scaler);
++ rgb->g = dal_fixed31_32_from_fraction(
++ gamma->green[i], scaler);
++ rgb->b = dal_fixed31_32_from_fraction(
++ gamma->blue[i], scaler);
++
++ ++rgb;
++ ++i;
++ } while (i != RGB_256X3X16);
++
++ rgb->r = dal_fixed31_32_mul(rgb_last->r,
++ dividers.divider1);
++ rgb->g = dal_fixed31_32_mul(rgb_last->g,
++ dividers.divider1);
++ rgb->b = dal_fixed31_32_mul(rgb_last->b,
++ dividers.divider1);
++
++ ++rgb;
++
++ rgb->r = dal_fixed31_32_mul(rgb_last->r,
++ dividers.divider2);
++ rgb->g = dal_fixed31_32_mul(rgb_last->g,
++ dividers.divider2);
++ rgb->b = dal_fixed31_32_mul(rgb_last->b,
++ dividers.divider2);
++
++ ++rgb;
++
++ rgb->r = dal_fixed31_32_mul(rgb_last->r,
++ dividers.divider3);
++ rgb->g = dal_fixed31_32_mul(rgb_last->g,
++ dividers.divider3);
++ rgb->b = dal_fixed31_32_mul(rgb_last->b,
++ dividers.divider3);
++
++ return true;
++}
++
++static void build_evenly_distributed_points(
++ struct gamma_pixel *points,
++ uint32_t numberof_points,
++ struct fixed31_32 max_value,
++ struct dividers dividers)
++{
++ struct gamma_pixel *p = points;
++ struct gamma_pixel *p_last = p + numberof_points - 1;
++
++ uint32_t i = 0;
++
++ do {
++ struct fixed31_32 value = dal_fixed31_32_div_int(
++ dal_fixed31_32_mul_int(max_value, i),
++ numberof_points - 1);
++
++ p->r = value;
++ p->g = value;
++ p->b = value;
++
++ ++p;
++ ++i;
++ } while (i != numberof_points);
++
++ p->r = dal_fixed31_32_div(p_last->r, dividers.divider1);
++ p->g = dal_fixed31_32_div(p_last->g, dividers.divider1);
++ p->b = dal_fixed31_32_div(p_last->b, dividers.divider1);
++
++ ++p;
++
++ p->r = dal_fixed31_32_div(p_last->r, dividers.divider2);
++ p->g = dal_fixed31_32_div(p_last->g, dividers.divider2);
++ p->b = dal_fixed31_32_div(p_last->b, dividers.divider2);
++
++ ++p;
++
++ p->r = dal_fixed31_32_div(p_last->r, dividers.divider3);
++ p->g = dal_fixed31_32_div(p_last->g, dividers.divider3);
++ p->b = dal_fixed31_32_div(p_last->b, dividers.divider3);
++}
++
++static inline void copy_rgb_regamma_to_coordinates_x(
++ struct hw_x_point *coordinates_x,
++ uint32_t hw_points_num,
++ const struct pwl_float_data_ex *rgb_ex)
++{
++ struct hw_x_point *coords = coordinates_x;
++ uint32_t i = 0;
++ const struct pwl_float_data_ex *rgb_regamma = rgb_ex;
++
++ while (i <= hw_points_num) {
++ coords->regamma_y_red = rgb_regamma->r;
++ coords->regamma_y_green = rgb_regamma->g;
++ coords->regamma_y_blue = rgb_regamma->b;
++
++ ++coords;
++ ++rgb_regamma;
++ ++i;
++ }
++}
++
++static bool calculate_interpolated_hardware_curve(
++ struct pwl_result_data *rgb,
++ struct pixel_gamma_point *coeff128,
++ struct pwl_float_data *rgb_user,
++ const struct hw_x_point *coordinates_x,
++ const struct gamma_pixel *axis_x_256,
++ uint32_t number_of_points,
++ enum surface_pixel_format pixel_format)
++{
++
++ const struct pixel_gamma_point *coeff;
++ struct pixel_gamma_point *coeff_128 = coeff128;
++ uint32_t max_entries = 3 - 1;
++ struct pwl_result_data *rgb_resulted = rgb;
++
++ uint32_t i = 0;
++
++ if (!build_oem_custom_gamma_mapping_coefficients(
++ coeff_128, coordinates_x, axis_x_256,
++ number_of_points,
++ pixel_format))
++ return false;
++
++ coeff = coeff128;
++ max_entries += RGB_256X3X16;
++
++ /* TODO: float point case */
++
++ while (i <= number_of_points) {
++ rgb_resulted->red = calculate_mapped_value(
++ rgb_user, coeff, CHANNEL_NAME_RED, max_entries);
++ rgb_resulted->green = calculate_mapped_value(
++ rgb_user, coeff, CHANNEL_NAME_GREEN, max_entries);
++ rgb_resulted->blue = calculate_mapped_value(
++ rgb_user, coeff, CHANNEL_NAME_BLUE, max_entries);
++
++ ++coeff;
++ ++rgb_resulted;
++ ++i;
++ }
++
++ return true;
++}
++
++static bool map_regamma_hw_to_x_user(
++ struct pixel_gamma_point *coeff128,
++ struct pwl_float_data *rgb_oem,
++ struct pwl_result_data *rgb_resulted,
++ struct pwl_float_data *rgb_user,
++ struct hw_x_point *coords_x,
++ const struct gamma_pixel *axis_x,
++ const struct dc_gamma *gamma,
++ const struct pwl_float_data_ex *rgb_regamma,
++ struct dividers dividers,
++ uint32_t hw_points_num,
++ const struct core_surface *surface)
++{
++ /* setup to spare calculated ideal regamma values */
++
++ struct pixel_gamma_point *coeff = coeff128;
++
++ struct hw_x_point *coords = coords_x;
++
++ copy_rgb_regamma_to_coordinates_x(coords, hw_points_num, rgb_regamma);
++
++ return calculate_interpolated_hardware_curve(
++ rgb_resulted, coeff, rgb_user, coords, axis_x,
++ hw_points_num, surface->public.format);
++}
++
++static void build_new_custom_resulted_curve(
++ struct pwl_result_data *rgb_resulted,
++ uint32_t hw_points_num)
++{
++ struct pwl_result_data *rgb = rgb_resulted;
++ struct pwl_result_data *rgb_plus_1 = rgb + 1;
++
++ uint32_t i;
++
++ i = 0;
++
++ while (i != hw_points_num + 1) {
++ rgb->red = dal_fixed31_32_clamp(
++ rgb->red, dal_fixed31_32_zero,
++ dal_fixed31_32_one);
++ rgb->green = dal_fixed31_32_clamp(
++ rgb->green, dal_fixed31_32_zero,
++ dal_fixed31_32_one);
++ rgb->blue = dal_fixed31_32_clamp(
++ rgb->blue, dal_fixed31_32_zero,
++ dal_fixed31_32_one);
++
++ ++rgb;
++ ++i;
++ }
++
++ rgb = rgb_resulted;
++
++ i = 1;
++
++ while (i != hw_points_num + 1) {
++ if (dal_fixed31_32_lt(rgb_plus_1->red, rgb->red))
++ rgb_plus_1->red = rgb->red;
++ if (dal_fixed31_32_lt(rgb_plus_1->green, rgb->green))
++ rgb_plus_1->green = rgb->green;
++ if (dal_fixed31_32_lt(rgb_plus_1->blue, rgb->blue))
++ rgb_plus_1->blue = rgb->blue;
++
++ rgb->delta_red = dal_fixed31_32_sub(
++ rgb_plus_1->red,
++ rgb->red);
++ rgb->delta_green = dal_fixed31_32_sub(
++ rgb_plus_1->green,
++ rgb->green);
++ rgb->delta_blue = dal_fixed31_32_sub(
++ rgb_plus_1->blue,
++ rgb->blue);
++
++ ++rgb_plus_1;
++ ++rgb;
++ ++i;
++ }
++}
++
++static void rebuild_curve_configuration_magic(
++ struct curve_points *arr_points,
++ struct pwl_result_data *rgb_resulted,
++ const struct hw_x_point *coordinates_x,
++ uint32_t hw_points_num)
++{
++ const struct fixed31_32 magic_number =
++ dal_fixed31_32_from_fraction(249, 1000);
++
++ struct fixed31_32 y_r;
++ struct fixed31_32 y_g;
++ struct fixed31_32 y_b;
++
++ struct fixed31_32 y1_min;
++ struct fixed31_32 y2_max;
++ struct fixed31_32 y3_max;
++
++ y_r = rgb_resulted[0].red;
++ y_g = rgb_resulted[0].green;
++ y_b = rgb_resulted[0].blue;
++
++ y1_min = dal_fixed31_32_min(y_r, dal_fixed31_32_min(y_g, y_b));
++
++ arr_points[0].x = coordinates_x[0].adjusted_x;
++ arr_points[0].y = y1_min;
++ arr_points[0].slope = dal_fixed31_32_div(
++ arr_points[0].y,
++ arr_points[0].x);
++
++ arr_points[1].x = dal_fixed31_32_add(
++ coordinates_x[hw_points_num - 1].adjusted_x,
++ magic_number);
++
++ arr_points[2].x = arr_points[1].x;
++
++ y_r = rgb_resulted[hw_points_num - 1].red;
++ y_g = rgb_resulted[hw_points_num - 1].green;
++ y_b = rgb_resulted[hw_points_num - 1].blue;
++
++ y2_max = dal_fixed31_32_max(y_r, dal_fixed31_32_max(y_g, y_b));
++
++ arr_points[1].y = y2_max;
++
++ y_r = rgb_resulted[hw_points_num].red;
++ y_g = rgb_resulted[hw_points_num].green;
++ y_b = rgb_resulted[hw_points_num].blue;
++
++ y3_max = dal_fixed31_32_max(y_r, dal_fixed31_32_max(y_g, y_b));
++
++ arr_points[2].y = y3_max;
++
++ arr_points[2].slope = dal_fixed31_32_one;
++}
++
++static bool convert_to_custom_float_format(
++ struct fixed31_32 value,
++ const struct custom_float_format *format,
++ uint32_t *result)
++{
++ uint32_t mantissa;
++ uint32_t exponenta;
++ bool negative;
++
++ return build_custom_float(
++ value, format, &negative, &mantissa, &exponenta) &&
++ setup_custom_float(
++ format, negative, mantissa, exponenta, result);
++}
++
++static bool convert_to_custom_float(
++ struct pwl_result_data *rgb_resulted,
++ struct curve_points *arr_points,
++ uint32_t hw_points_num)
++{
++ struct custom_float_format fmt;
++
++ struct pwl_result_data *rgb = rgb_resulted;
++
++ uint32_t i = 0;
++
++ fmt.exponenta_bits = 6;
++ fmt.mantissa_bits = 12;
++ fmt.sign = true;
++
++ if (!convert_to_custom_float_format(
++ arr_points[0].x,
++ &fmt,
++ &arr_points[0].custom_float_x)) {
++ BREAK_TO_DEBUGGER();
++ return false;
++ }
++
++ if (!convert_to_custom_float_format(
++ arr_points[0].offset,
++ &fmt,
++ &arr_points[0].custom_float_offset)) {
++ BREAK_TO_DEBUGGER();
++ return false;
++ }
++
++ if (!convert_to_custom_float_format(
++ arr_points[0].slope,
++ &fmt,
++ &arr_points[0].custom_float_slope)) {
++ BREAK_TO_DEBUGGER();
++ return false;
++ }
++
++ fmt.mantissa_bits = 10;
++ fmt.sign = false;
++
++ if (!convert_to_custom_float_format(
++ arr_points[1].x,
++ &fmt,
++ &arr_points[1].custom_float_x)) {
++ BREAK_TO_DEBUGGER();
++ return false;
++ }
++
++ if (!convert_to_custom_float_format(
++ arr_points[1].y,
++ &fmt,
++ &arr_points[1].custom_float_y)) {
++ BREAK_TO_DEBUGGER();
++ return false;
++ }
++
++ if (!convert_to_custom_float_format(
++ arr_points[2].slope,
++ &fmt,
++ &arr_points[2].custom_float_slope)) {
++ BREAK_TO_DEBUGGER();
++ return false;
++ }
++
++ fmt.mantissa_bits = 12;
++ fmt.sign = true;
++
++ while (i != hw_points_num) {
++ if (!convert_to_custom_float_format(
++ rgb->red,
++ &fmt,
++ &rgb->red_reg)) {
++ BREAK_TO_DEBUGGER();
++ return false;
++ }
++
++ if (!convert_to_custom_float_format(
++ rgb->green,
++ &fmt,
++ &rgb->green_reg)) {
++ BREAK_TO_DEBUGGER();
++ return false;
++ }
++
++ if (!convert_to_custom_float_format(
++ rgb->blue,
++ &fmt,
++ &rgb->blue_reg)) {
++ BREAK_TO_DEBUGGER();
++ return false;
++ }
++
++ if (!convert_to_custom_float_format(
++ rgb->delta_red,
++ &fmt,
++ &rgb->delta_red_reg)) {
++ BREAK_TO_DEBUGGER();
++ return false;
++ }
++
++ if (!convert_to_custom_float_format(
++ rgb->delta_green,
++ &fmt,
++ &rgb->delta_green_reg)) {
++ BREAK_TO_DEBUGGER();
++ return false;
++ }
++
++ if (!convert_to_custom_float_format(
++ rgb->delta_blue,
++ &fmt,
++ &rgb->delta_blue_reg)) {
++ BREAK_TO_DEBUGGER();
++ return false;
++ }
++
++ ++rgb;
++ ++i;
++ }
++
++ return true;
++}
++
++void calculate_regamma_params(struct regamma_params *params,
++ struct temp_params *temp_params,
++ const struct core_gamma *ramp,
++ const struct core_surface *surface)
++{
++ struct gamma_curve *arr_curve_points = params->arr_curve_points;
++ struct curve_points *arr_points = params->arr_points;
++ struct hw_x_point *coordinates_x = temp_params->coordinates_x;
++ struct pwl_float_data *rgb_user = temp_params->rgb_user;
++ struct pwl_float_data_ex *rgb_regamma = temp_params->rgb_regamma;
++ struct pwl_float_data *rgb_oem = temp_params->rgb_oem;
++ struct pwl_result_data *rgb_resulted = params->rgb_resulted;
++ struct dividers dividers;
++ struct gamma_pixel *axix_x_256 = temp_params->axix_x_256;
++ struct pixel_gamma_point *coeff128_oem = temp_params->coeff128_oem;
++ struct pixel_gamma_point *coeff128 = temp_params->coeff128;
++
++ dividers.divider1 = dal_fixed31_32_from_fraction(3, 2);
++ dividers.divider2 = dal_fixed31_32_from_int(2);
++ dividers.divider3 = dal_fixed31_32_from_fraction(5, 2);
++
++ build_evenly_distributed_points(
++ axix_x_256,
++ 256,
++ dal_fixed31_32_one,
++ dividers);
++
++ scale_gamma(rgb_user, ramp, dividers);
++
++ setup_distribution_points(arr_curve_points, arr_points,
++ &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);
++
++ 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, &params->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, &params->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(
+- &params->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, &params->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
+