All of lore.kernel.org
 help / color / mirror / Atom feed
From: Harry Wentland <harry.wentland@amd.com>
To: dri-devel@lists.freedesktop.org
Subject: [PATCH 19/29] drm/amd/dal: Add output pixel processing HW programming
Date: Thu, 11 Feb 2016 12:19:59 -0500	[thread overview]
Message-ID: <1455211209-26733-20-git-send-email-harry.wentland@amd.com> (raw)
In-Reply-To: <1455211209-26733-1-git-send-email-harry.wentland@amd.com>

Adds programming for color space conversion (CSC),
regamma, and formatter.

Signed-off-by: Harry Wentland <harry.wentland@amd.com>
Reviewed-by: Alex Deucher <alexander.deucher@amd.com>
---
 drivers/gpu/drm/amd/dal/dc/dce110/dce110_opp.c     |  272 +++
 drivers/gpu/drm/amd/dal/dc/dce110/dce110_opp.h     |  143 ++
 drivers/gpu/drm/amd/dal/dc/dce110/dce110_opp_csc.c |  904 +++++++
 .../drm/amd/dal/dc/dce110/dce110_opp_formatter.c   |  610 +++++
 .../gpu/drm/amd/dal/dc/dce110/dce110_opp_regamma.c | 2474 ++++++++++++++++++++
 5 files changed, 4403 insertions(+)
 create mode 100644 drivers/gpu/drm/amd/dal/dc/dce110/dce110_opp.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/dce110/dce110_opp.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/dce110/dce110_opp_csc.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/dce110/dce110_opp_formatter.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/dce110/dce110_opp_regamma.c

diff --git a/drivers/gpu/drm/amd/dal/dc/dce110/dce110_opp.c b/drivers/gpu/drm/amd/dal/dc/dce110/dce110_opp.c
new file mode 100644
index 000000000000..acb405e7b2e7
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/dce110/dce110_opp.c
@@ -0,0 +1,272 @@
+/*
+ * 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
+ *
+ */
+
+#include "dm_services.h"
+
+/* include DCE11 register header files */
+#include "dce/dce_11_0_d.h"
+#include "dce/dce_11_0_sh_mask.h"
+
+#include "dce110_opp.h"
+
+#include "gamma_types.h"
+
+enum {
+	MAX_LUT_ENTRY = 256,
+	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,
+		.opp_set_csc_adjustment = dce110_opp_set_csc_adjustment,
+		.opp_set_csc_default = dce110_opp_set_csc_default,
+		.opp_set_dyn_expansion = dce110_opp_set_dyn_expansion,
+		.opp_set_regamma = dce110_opp_set_regamma
+};
+
+bool dce110_opp_construct(struct dce110_opp *opp110,
+	struct dc_context *ctx,
+	uint32_t inst,
+	const struct dce110_opp_reg_offsets *offsets)
+{
+
+	opp110->base.funcs = &funcs;
+
+	opp110->base.ctx = ctx;
+
+	opp110->base.inst = inst;
+
+	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
new file mode 100644
index 000000000000..e53eb7413948
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/dce110/dce110_opp.h
@@ -0,0 +1,143 @@
+/* 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 __DC_OPP_DCE110_H__
+#define __DC_OPP_DCE110_H__
+
+#include "dc_types.h"
+#include "inc/opp.h"
+#include "gamma_types.h"
+
+struct gamma_parameters;
+
+#define FROM_DCE11_OPP(opp)\
+	container_of(opp, struct dce110_opp, base)
+
+enum dce110_opp_reg_type {
+	DCE110_OPP_REG_DCP = 0,
+	DCE110_OPP_REG_DCFE,
+	DCE110_OPP_REG_FMT,
+
+	DCE110_OPP_REG_MAX
+};
+
+struct dce110_regamma {
+	struct gamma_curve arr_curve_points[16];
+	struct curve_points arr_points[3];
+	uint32_t hw_points_num;
+	struct hw_x_point *coordinates_x;
+	struct pwl_result_data *rgb_resulted;
+
+	/* re-gamma curve */
+	struct pwl_float_data_ex *rgb_regamma;
+	/* coeff used to map user evenly distributed points
+	 * to our hardware points (predefined) for gamma 256 */
+	struct pixel_gamma_point *coeff128;
+	struct pixel_gamma_point *coeff128_oem;
+	/* coeff used to map user evenly distributed points
+	 * to our hardware points (predefined) for gamma 1025 */
+	struct pixel_gamma_point *coeff128_dx;
+	/* evenly distributed points, gamma 256 software points 0-255 */
+	struct gamma_pixel *axis_x_256;
+	/* evenly distributed points, gamma 1025 software points 0-1025 */
+	struct gamma_pixel *axis_x_1025;
+	/* OEM supplied gamma for regamma LUT */
+	struct pwl_float_data *rgb_oem;
+	/* user supplied gamma */
+	struct pwl_float_data *rgb_user;
+	struct dev_c_lut saved_palette[RGB_256X3X16];
+	uint32_t extra_points;
+	bool use_half_points;
+	struct fixed31_32 x_max1;
+	struct fixed31_32 x_max2;
+	struct fixed31_32 x_min;
+	struct fixed31_32 divider1;
+	struct fixed31_32 divider2;
+	struct fixed31_32 divider3;
+};
+
+/* OPP RELATED */
+#define TO_DCE110_OPP(opp)\
+	container_of(opp, struct dce110_opp, base)
+
+struct dce110_opp_reg_offsets {
+	uint32_t fmt_offset;
+	uint32_t dcp_offset;
+	uint32_t dcfe_offset;
+};
+
+struct dce110_opp {
+	struct output_pixel_processor base;
+	struct dce110_opp_reg_offsets offsets;
+	struct dce110_regamma regamma;
+};
+
+bool dce110_opp_construct(struct dce110_opp *opp110,
+	struct dc_context *ctx,
+	uint32_t inst,
+	const struct dce110_opp_reg_offsets *offsets);
+
+void dce110_opp_destroy(struct output_pixel_processor **opp);
+
+/* REGAMMA RELATED */
+void dce110_opp_power_on_regamma_lut(
+	struct output_pixel_processor *opp,
+	bool power_on);
+
+bool dce110_opp_set_regamma(
+	struct output_pixel_processor *opp,
+	const struct gamma_ramp *ramp,
+	const struct gamma_parameters *params,
+	bool force_bypass);
+
+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);
+
+void dce110_opp_set_csc_adjustment(
+	struct output_pixel_processor *opp,
+	const struct grph_csc_adjustment *adjust);
+
+void dce110_opp_set_csc_default(
+	struct output_pixel_processor *opp,
+	const struct default_adjustment *default_adjust);
+
+/* FORMATTER RELATED */
+void dce110_opp_program_bit_depth_reduction(
+	struct output_pixel_processor *opp,
+	const struct bit_depth_reduction_params *params);
+
+void dce110_opp_program_clamping_and_pixel_encoding(
+	struct output_pixel_processor *opp,
+	const struct clamping_and_pixel_encoding_params *params);
+
+
+void dce110_opp_set_dyn_expansion(
+	struct output_pixel_processor *opp,
+	enum color_space color_sp,
+	enum dc_color_depth color_dpth,
+	enum signal_type signal);
+
+#endif
diff --git a/drivers/gpu/drm/amd/dal/dc/dce110/dce110_opp_csc.c b/drivers/gpu/drm/amd/dal/dc/dce110/dce110_opp_csc.c
new file mode 100644
index 000000000000..8f651e9329bc
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/dce110/dce110_opp_csc.c
@@ -0,0 +1,904 @@
+/*
+ * 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
+ *
+ */
+
+#include "dm_services.h"
+#include "dce110_opp.h"
+#include "basics/conversion.h"
+
+/* include DCE11 register header files */
+#include "dce/dce_11_0_d.h"
+#include "dce/dce_11_0_sh_mask.h"
+
+#define DCP_REG(reg)\
+	(reg + opp110->offsets.dcp_offset)
+
+enum {
+	OUTPUT_CSC_MATRIX_SIZE = 12
+};
+
+struct out_csc_color_matrix {
+	enum color_space color_space;
+	uint16_t regval[OUTPUT_CSC_MATRIX_SIZE];
+};
+
+static const struct out_csc_color_matrix global_color_matrix[] = {
+{ COLOR_SPACE_SRGB_FULL_RANGE,
+	{ 0x2000, 0, 0, 0, 0, 0x2000, 0, 0, 0, 0, 0x2000, 0} },
+{ COLOR_SPACE_SRGB_LIMITED_RANGE,
+	{ 0x1B60, 0, 0, 0x200, 0, 0x1B60, 0, 0x200, 0, 0, 0x1B60, 0x200} },
+{ COLOR_SPACE_YCBCR601,
+	{ 0xE00, 0xF447, 0xFDB9, 0x1000, 0x82F, 0x1012, 0x31F, 0x200, 0xFB47,
+		0xF6B9, 0xE00, 0x1000} },
+{ COLOR_SPACE_YCBCR709, { 0xE00, 0xF349, 0xFEB7, 0x1000, 0x5D2, 0x1394, 0x1FA,
+	0x200, 0xFCCB, 0xF535, 0xE00, 0x1000} },
+/*  YOnly same as YCbCr709 but Y in Full range -To do. */
+{ COLOR_SPACE_YCBCR601_YONLY, { 0xE00, 0xF447, 0xFDB9, 0x1000, 0x991,
+	0x12C9, 0x3A6, 0x200, 0xFB47, 0xF6B9, 0xE00, 0x1000} },
+{ COLOR_SPACE_YCBCR709_YONLY, { 0xE00, 0xF349, 0xFEB7, 0x1000, 0x6CE, 0x16E3,
+	0x24F, 0x200, 0xFCCB, 0xF535, 0xE00, 0x1000} }
+};
+
+enum csc_color_mode {
+	/* 00 - BITS2:0 Bypass */
+	CSC_COLOR_MODE_GRAPHICS_BYPASS,
+	/* 01 - hard coded coefficient TV RGB */
+	CSC_COLOR_MODE_GRAPHICS_PREDEFINED,
+	/* 04 - programmable OUTPUT CSC coefficient */
+	CSC_COLOR_MODE_GRAPHICS_OUTPUT_CSC,
+};
+
+static void program_color_matrix(
+	struct dce110_opp *opp110,
+	const struct out_csc_color_matrix *tbl_entry,
+	enum grph_color_adjust_option options)
+{
+	struct dc_context *ctx = opp110->base.ctx;
+	{
+		uint32_t value = 0;
+		uint32_t addr = DCP_REG(mmOUTPUT_CSC_C11_C12);
+		/* fixed S2.13 format */
+		set_reg_field_value(
+			value,
+			tbl_entry->regval[0],
+			OUTPUT_CSC_C11_C12,
+			OUTPUT_CSC_C11);
+
+		set_reg_field_value(
+			value,
+			tbl_entry->regval[1],
+			OUTPUT_CSC_C11_C12,
+			OUTPUT_CSC_C12);
+
+		dm_write_reg(ctx, addr, value);
+	}
+	{
+		uint32_t value = 0;
+		uint32_t addr = DCP_REG(mmOUTPUT_CSC_C13_C14);
+		/* fixed S2.13 format */
+		set_reg_field_value(
+			value,
+			tbl_entry->regval[2],
+			OUTPUT_CSC_C13_C14,
+			OUTPUT_CSC_C13);
+		/* fixed S0.13 format */
+		set_reg_field_value(
+			value,
+			tbl_entry->regval[3],
+			OUTPUT_CSC_C13_C14,
+			OUTPUT_CSC_C14);
+
+		dm_write_reg(ctx, addr, value);
+	}
+	{
+		uint32_t value = 0;
+		uint32_t addr = DCP_REG(mmOUTPUT_CSC_C21_C22);
+		/* fixed S2.13 format */
+		set_reg_field_value(
+			value,
+			tbl_entry->regval[4],
+			OUTPUT_CSC_C21_C22,
+			OUTPUT_CSC_C21);
+		/* fixed S2.13 format */
+		set_reg_field_value(
+			value,
+			tbl_entry->regval[5],
+			OUTPUT_CSC_C21_C22,
+			OUTPUT_CSC_C22);
+
+		dm_write_reg(ctx, addr, value);
+	}
+	{
+		uint32_t value = 0;
+		uint32_t addr = DCP_REG(mmOUTPUT_CSC_C23_C24);
+		/* fixed S2.13 format */
+		set_reg_field_value(
+			value,
+			tbl_entry->regval[6],
+			OUTPUT_CSC_C23_C24,
+			OUTPUT_CSC_C23);
+		/* fixed S0.13 format */
+		set_reg_field_value(
+			value,
+			tbl_entry->regval[7],
+			OUTPUT_CSC_C23_C24,
+			OUTPUT_CSC_C24);
+
+		dm_write_reg(ctx, addr, value);
+	}
+	{
+		uint32_t value = 0;
+		uint32_t addr = DCP_REG(mmOUTPUT_CSC_C31_C32);
+		/* fixed S2.13 format */
+		set_reg_field_value(
+			value,
+			tbl_entry->regval[8],
+			OUTPUT_CSC_C31_C32,
+			OUTPUT_CSC_C31);
+		/* fixed S0.13 format */
+		set_reg_field_value(
+			value,
+			tbl_entry->regval[9],
+			OUTPUT_CSC_C31_C32,
+			OUTPUT_CSC_C32);
+
+		dm_write_reg(ctx, addr, value);
+	}
+	{
+		uint32_t value = 0;
+		uint32_t addr = DCP_REG(mmOUTPUT_CSC_C33_C34);
+		/* fixed S2.13 format */
+		set_reg_field_value(
+			value,
+			tbl_entry->regval[10],
+			OUTPUT_CSC_C33_C34,
+			OUTPUT_CSC_C33);
+		/* fixed S0.13 format */
+		set_reg_field_value(
+			value,
+			tbl_entry->regval[11],
+			OUTPUT_CSC_C33_C34,
+			OUTPUT_CSC_C34);
+
+		dm_write_reg(ctx, addr, value);
+	}
+}
+
+/*
+ * initialize_color_float_adj_reference_values
+ * This initialize display color adjust input from API to HW range for later
+ * calculation use. This is shared by all the display color adjustment.
+ * @param :
+ * @return None
+ */
+static void initialize_color_float_adj_reference_values(
+	const struct grph_csc_adjustment *adjust,
+	struct fixed31_32 *grph_cont,
+	struct fixed31_32 *grph_sat,
+	struct fixed31_32 *grph_bright,
+	struct fixed31_32 *sin_grph_hue,
+	struct fixed31_32 *cos_grph_hue)
+{
+	/* Hue adjustment could be negative. -45 ~ +45 */
+	struct fixed31_32 hue =
+		dal_fixed31_32_mul(
+			dal_fixed31_32_from_fraction(adjust->grph_hue, 180),
+			dal_fixed31_32_pi);
+
+	*sin_grph_hue = dal_fixed31_32_sin(hue);
+	*cos_grph_hue = dal_fixed31_32_cos(hue);
+
+	if (adjust->adjust_divider) {
+		*grph_cont =
+			dal_fixed31_32_from_fraction(
+				adjust->grph_cont,
+				adjust->adjust_divider);
+		*grph_sat =
+			dal_fixed31_32_from_fraction(
+				adjust->grph_sat,
+				adjust->adjust_divider);
+		*grph_bright =
+			dal_fixed31_32_from_fraction(
+				adjust->grph_bright,
+				adjust->adjust_divider);
+	} else {
+		*grph_cont = dal_fixed31_32_from_int(adjust->grph_cont);
+		*grph_sat = dal_fixed31_32_from_int(adjust->grph_sat);
+		*grph_bright = dal_fixed31_32_from_int(adjust->grph_bright);
+	}
+}
+
+static inline struct fixed31_32 fixed31_32_clamp(
+	struct fixed31_32 value,
+	int32_t min_numerator,
+	int32_t max_numerator,
+	int32_t denominator)
+{
+	return dal_fixed31_32_clamp(
+		value,
+		dal_fixed31_32_from_fraction(
+			min_numerator,
+			denominator),
+		dal_fixed31_32_from_fraction(
+			max_numerator,
+			denominator));
+}
+
+static void setup_reg_format(
+	struct fixed31_32 *coefficients,
+	uint16_t *reg_values)
+{
+	enum {
+		LENGTH = 12,
+		DENOMINATOR = 10000
+	};
+
+	static const int32_t min_numerator[] = {
+		-3 * DENOMINATOR,
+		-DENOMINATOR
+	};
+
+	static const int32_t max_numerator[] = {
+		DENOMINATOR,
+		DENOMINATOR
+	};
+
+	static const uint8_t integer_bits[] = { 2, 0 };
+
+	uint32_t i = 0;
+
+	do {
+		const uint32_t index = (i % 4) == 3;
+
+		reg_values[i] = fixed_point_to_int_frac(
+			fixed31_32_clamp(coefficients[(i + 8) % LENGTH],
+				min_numerator[index],
+				max_numerator[index],
+				DENOMINATOR),
+			integer_bits[index], 13);
+
+		++i;
+	} while (i != LENGTH);
+}
+
+/**
+ *****************************************************************************
+ *  Function: setup_adjustments
+ *  @note prepare to setup the values
+ *
+ *  @see
+ *
+ *****************************************************************************
+ */
+static void setup_adjustments(const struct grph_csc_adjustment *adjust,
+	struct dc_csc_adjustments *adjustments)
+{
+	if (adjust->adjust_divider != 0) {
+		adjustments->brightness =
+			dal_fixed31_32_from_fraction(adjust->grph_bright,
+			adjust->adjust_divider);
+		adjustments->contrast =
+			dal_fixed31_32_from_fraction(adjust->grph_cont,
+			adjust->adjust_divider);
+		adjustments->saturation =
+			dal_fixed31_32_from_fraction(adjust->grph_sat,
+			adjust->adjust_divider);
+	} else {
+		adjustments->brightness =
+			dal_fixed31_32_from_fraction(adjust->grph_bright, 1);
+		adjustments->contrast =
+			dal_fixed31_32_from_fraction(adjust->grph_cont, 1);
+		adjustments->saturation =
+			dal_fixed31_32_from_fraction(adjust->grph_sat, 1);
+	}
+
+	/* convert degrees into radians */
+	adjustments->hue =
+		dal_fixed31_32_mul(
+			dal_fixed31_32_from_fraction(adjust->grph_hue, 180),
+			dal_fixed31_32_pi);
+}
+
+static void prepare_tv_rgb_ideal(
+	struct fixed31_32 *matrix)
+{
+	static const int32_t matrix_[] = {
+		85546875, 0, 0, 6250000,
+		0, 85546875, 0, 6250000,
+		0, 0, 85546875, 6250000
+	};
+
+	uint32_t i = 0;
+
+	do {
+		matrix[i] = dal_fixed31_32_from_fraction(
+			matrix_[i],
+			100000000);
+		++i;
+	} while (i != ARRAY_SIZE(matrix_));
+}
+
+/**
+ *****************************************************************************
+ *  Function: dal_transform_wide_gamut_set_rgb_adjustment_legacy
+ *
+ *  @param [in] const struct grph_csc_adjustment *adjust
+ *
+ *  @return
+ *     void
+ *
+ *  @note calculate and program color adjustments for sRGB color space
+ *
+ *  @see
+ *
+ *****************************************************************************
+ */
+static void set_rgb_adjustment_legacy(
+	struct dce110_opp *opp110,
+	const struct grph_csc_adjustment *adjust)
+{
+	const struct fixed31_32 k1 =
+		dal_fixed31_32_from_fraction(701000, 1000000);
+	const struct fixed31_32 k2 =
+		dal_fixed31_32_from_fraction(236568, 1000000);
+	const struct fixed31_32 k3 =
+		dal_fixed31_32_from_fraction(-587000, 1000000);
+	const struct fixed31_32 k4 =
+		dal_fixed31_32_from_fraction(464432, 1000000);
+	const struct fixed31_32 k5 =
+		dal_fixed31_32_from_fraction(-114000, 1000000);
+	const struct fixed31_32 k6 =
+		dal_fixed31_32_from_fraction(-701000, 1000000);
+	const struct fixed31_32 k7 =
+		dal_fixed31_32_from_fraction(-299000, 1000000);
+	const struct fixed31_32 k8 =
+		dal_fixed31_32_from_fraction(-292569, 1000000);
+	const struct fixed31_32 k9 =
+		dal_fixed31_32_from_fraction(413000, 1000000);
+	const struct fixed31_32 k10 =
+		dal_fixed31_32_from_fraction(-92482, 1000000);
+	const struct fixed31_32 k11 =
+		dal_fixed31_32_from_fraction(-114000, 1000000);
+	const struct fixed31_32 k12 =
+		dal_fixed31_32_from_fraction(385051, 1000000);
+	const struct fixed31_32 k13 =
+		dal_fixed31_32_from_fraction(-299000, 1000000);
+	const struct fixed31_32 k14 =
+		dal_fixed31_32_from_fraction(886000, 1000000);
+	const struct fixed31_32 k15 =
+		dal_fixed31_32_from_fraction(-587000, 1000000);
+	const struct fixed31_32 k16 =
+		dal_fixed31_32_from_fraction(-741914, 1000000);
+	const struct fixed31_32 k17 =
+		dal_fixed31_32_from_fraction(886000, 1000000);
+	const struct fixed31_32 k18 =
+		dal_fixed31_32_from_fraction(-144086, 1000000);
+
+	const struct fixed31_32 luma_r =
+		dal_fixed31_32_from_fraction(299, 1000);
+	const struct fixed31_32 luma_g =
+		dal_fixed31_32_from_fraction(587, 1000);
+	const struct fixed31_32 luma_b =
+		dal_fixed31_32_from_fraction(114, 1000);
+
+	struct out_csc_color_matrix tbl_entry;
+	struct fixed31_32 matrix[OUTPUT_CSC_MATRIX_SIZE];
+
+	struct fixed31_32 grph_cont;
+	struct fixed31_32 grph_sat;
+	struct fixed31_32 grph_bright;
+	struct fixed31_32 sin_grph_hue;
+	struct fixed31_32 cos_grph_hue;
+
+	initialize_color_float_adj_reference_values(
+		adjust, &grph_cont, &grph_sat,
+		&grph_bright, &sin_grph_hue, &cos_grph_hue);
+
+	/* COEF_1_1 = GrphCont * (LumaR + GrphSat * (Cos(GrphHue) * K1 +
+	 * Sin(GrphHue) * K2)) */
+	/* (Cos(GrphHue) * K1 + Sin(GrphHue) * K2) */
+	matrix[0] =
+		dal_fixed31_32_add(
+			dal_fixed31_32_mul(cos_grph_hue, k1),
+			dal_fixed31_32_mul(sin_grph_hue, k2));
+	/* GrphSat * (Cos(GrphHue) * K1 + Sin(GrphHue) * K2 */
+	matrix[0] = dal_fixed31_32_mul(grph_sat, matrix[0]);
+	/* (LumaR + GrphSat * (Cos(GrphHue) * K1 + Sin(GrphHue) * K2)) */
+	matrix[0] = dal_fixed31_32_add(luma_r, matrix[0]);
+	/* GrphCont * (LumaR + GrphSat * (Cos(GrphHue) * K1 + Sin(GrphHue) *
+	 * K2)) */
+	matrix[0] = dal_fixed31_32_mul(grph_cont, matrix[0]);
+
+	/* COEF_1_2 = GrphCont * (LumaG + GrphSat * (Cos(GrphHue) * K3 +
+	 * Sin(GrphHue) * K4)) */
+	/* (Cos(GrphHue) * K3 + Sin(GrphHue) * K4) */
+	matrix[1] =
+		dal_fixed31_32_add(
+			dal_fixed31_32_mul(cos_grph_hue, k3),
+			dal_fixed31_32_mul(sin_grph_hue, k4));
+	/* GrphSat * (Cos(GrphHue) * K3 + Sin(GrphHue) * K4) */
+	matrix[1] = dal_fixed31_32_mul(grph_sat, matrix[1]);
+	/* (LumaG + GrphSat * (Cos(GrphHue) * K3 + Sin(GrphHue) * K4)) */
+	matrix[1] = dal_fixed31_32_add(luma_g, matrix[1]);
+	/* GrphCont * (LumaG + GrphSat * (Cos(GrphHue) * K3 + Sin(GrphHue) *
+	 * K4)) */
+	matrix[1] = dal_fixed31_32_mul(grph_cont, matrix[1]);
+
+	/* COEF_1_3 = GrphCont * (LumaB + GrphSat * (Cos(GrphHue) * K5 +
+	 * Sin(GrphHue) * K6)) */
+	/* (Cos(GrphHue) * K5 + Sin(GrphHue) * K6) */
+	matrix[2] =
+		dal_fixed31_32_add(
+			dal_fixed31_32_mul(cos_grph_hue, k5),
+			dal_fixed31_32_mul(sin_grph_hue, k6));
+	/* GrphSat * (Cos(GrphHue) * K5 + Sin(GrphHue) * K6) */
+	matrix[2] = dal_fixed31_32_mul(grph_sat, matrix[2]);
+	/* LumaB + GrphSat * (Cos(GrphHue) * K5 + Sin(GrphHue) * K6) */
+	matrix[2] = dal_fixed31_32_add(luma_b, matrix[2]);
+	/* GrphCont  * (LumaB + GrphSat * (Cos(GrphHue) * K5 + Sin(GrphHue) *
+	 * K6)) */
+	matrix[2] = dal_fixed31_32_mul(grph_cont, matrix[2]);
+
+	/* COEF_1_4 = GrphBright */
+	matrix[3] = grph_bright;
+
+	/* COEF_2_1 = GrphCont * (LumaR + GrphSat * (Cos(GrphHue) * K7 +
+	 * Sin(GrphHue) * K8)) */
+	/* (Cos(GrphHue) * K7 + Sin(GrphHue) * K8) */
+	matrix[4] =
+		dal_fixed31_32_add(
+			dal_fixed31_32_mul(cos_grph_hue, k7),
+			dal_fixed31_32_mul(sin_grph_hue, k8));
+	/* GrphSat * (Cos(GrphHue) * K7 + Sin(GrphHue) * K8) */
+	matrix[4] = dal_fixed31_32_mul(grph_sat, matrix[4]);
+	/* (LumaR + GrphSat * (Cos(GrphHue) * K7 + Sin(GrphHue) * K8)) */
+	matrix[4] = dal_fixed31_32_add(luma_r, matrix[4]);
+	/* GrphCont * (LumaR + GrphSat * (Cos(GrphHue) * K7 + Sin(GrphHue) *
+	 * K8)) */
+	matrix[4] = dal_fixed31_32_mul(grph_cont, matrix[4]);
+
+	/* COEF_2_2 = GrphCont * (LumaG + GrphSat * (Cos(GrphHue) * K9 +
+	 * Sin(GrphHue) * K10)) */
+	/* (Cos(GrphHue) * K9 + Sin(GrphHue) * K10)) */
+	matrix[5] =
+		dal_fixed31_32_add(
+			dal_fixed31_32_mul(cos_grph_hue, k9),
+			dal_fixed31_32_mul(sin_grph_hue, k10));
+	/* GrphSat * (Cos(GrphHue) * K9 + Sin(GrphHue) * K10)) */
+	matrix[5] = dal_fixed31_32_mul(grph_sat, matrix[5]);
+	/* (LumaG + GrphSat * (Cos(GrphHue) * K9 + Sin(GrphHue) * K10)) */
+	matrix[5] = dal_fixed31_32_add(luma_g, matrix[5]);
+	/* GrphCont * (LumaG + GrphSat * (Cos(GrphHue) * K9 + Sin(GrphHue) *
+	 * K10)) */
+	matrix[5] = dal_fixed31_32_mul(grph_cont, matrix[5]);
+
+	/*  COEF_2_3 = GrphCont * (LumaB + GrphSat * (Cos(GrphHue) * K11 +
+	 * Sin(GrphHue) * K12)) */
+	/* (Cos(GrphHue) * K11 + Sin(GrphHue) * K12)) */
+	matrix[6] =
+		dal_fixed31_32_add(
+			dal_fixed31_32_mul(cos_grph_hue, k11),
+			dal_fixed31_32_mul(sin_grph_hue, k12));
+	/* GrphSat * (Cos(GrphHue) * K11 + Sin(GrphHue) * K12)) */
+	matrix[6] = dal_fixed31_32_mul(grph_sat, matrix[6]);
+	/*  (LumaB + GrphSat * (Cos(GrphHue) * K11 + Sin(GrphHue) * K12)) */
+	matrix[6] = dal_fixed31_32_add(luma_b, matrix[6]);
+	/* GrphCont * (LumaB + GrphSat * (Cos(GrphHue) * K11 + Sin(GrphHue) *
+	 * K12)) */
+	matrix[6] = dal_fixed31_32_mul(grph_cont, matrix[6]);
+
+	/* COEF_2_4 = GrphBright */
+	matrix[7] = grph_bright;
+
+	/* COEF_3_1 = GrphCont  * (LumaR + GrphSat * (Cos(GrphHue) * K13 +
+	 * Sin(GrphHue) * K14)) */
+	/* (Cos(GrphHue) * K13 + Sin(GrphHue) * K14)) */
+	matrix[8] =
+		dal_fixed31_32_add(
+			dal_fixed31_32_mul(cos_grph_hue, k13),
+			dal_fixed31_32_mul(sin_grph_hue, k14));
+	/* GrphSat * (Cos(GrphHue) * K13 + Sin(GrphHue) * K14)) */
+	matrix[8] = dal_fixed31_32_mul(grph_sat, matrix[8]);
+	/* (LumaR + GrphSat * (Cos(GrphHue) * K13 + Sin(GrphHue) * K14)) */
+	matrix[8] = dal_fixed31_32_add(luma_r, matrix[8]);
+	/* GrphCont  * (LumaR + GrphSat * (Cos(GrphHue) * K13 + Sin(GrphHue) *
+	 * K14)) */
+	matrix[8] = dal_fixed31_32_mul(grph_cont, matrix[8]);
+
+	/* COEF_3_2    = GrphCont * (LumaG + GrphSat * (Cos(GrphHue) * K15 +
+	 * Sin(GrphHue) * K16)) */
+	/* GrphSat * (Cos(GrphHue) * K15 + Sin(GrphHue) * K16) */
+	matrix[9] =
+		dal_fixed31_32_add(
+			dal_fixed31_32_mul(cos_grph_hue, k15),
+			dal_fixed31_32_mul(sin_grph_hue, k16));
+	/* (LumaG + GrphSat * (Cos(GrphHue) * K15 + Sin(GrphHue) * K16)) */
+	matrix[9] = dal_fixed31_32_mul(grph_sat, matrix[9]);
+	/* (LumaG + GrphSat * (Cos(GrphHue) * K15 + Sin(GrphHue) * K16)) */
+	matrix[9] = dal_fixed31_32_add(luma_g, matrix[9]);
+	 /* GrphCont * (LumaG + GrphSat * (Cos(GrphHue) * K15 + Sin(GrphHue) *
+	  * K16)) */
+	matrix[9] = dal_fixed31_32_mul(grph_cont, matrix[9]);
+
+	/*  COEF_3_3 = GrphCont * (LumaB + GrphSat * (Cos(GrphHue) * K17 +
+	 * Sin(GrphHue) * K18)) */
+	/* (Cos(GrphHue) * K17 + Sin(GrphHue) * K18)) */
+	matrix[10] =
+		dal_fixed31_32_add(
+			dal_fixed31_32_mul(cos_grph_hue, k17),
+			dal_fixed31_32_mul(sin_grph_hue, k18));
+	/*  GrphSat * (Cos(GrphHue) * K17 + Sin(GrphHue) * K18)) */
+	matrix[10] = dal_fixed31_32_mul(grph_sat, matrix[10]);
+	/* (LumaB + GrphSat * (Cos(GrphHue) * K17 + Sin(GrphHue) * K18)) */
+	matrix[10] = dal_fixed31_32_add(luma_b, matrix[10]);
+	 /* GrphCont * (LumaB + GrphSat * (Cos(GrphHue) * K17 + Sin(GrphHue) *
+	  * K18)) */
+	matrix[10] = dal_fixed31_32_mul(grph_cont, matrix[10]);
+
+	/*  COEF_3_4    = GrphBright */
+	matrix[11] = grph_bright;
+
+	tbl_entry.color_space = adjust->c_space;
+
+	convert_float_matrix(tbl_entry.regval, matrix, OUTPUT_CSC_MATRIX_SIZE);
+
+	program_color_matrix(
+		opp110, &tbl_entry, adjust->color_adjust_option);
+}
+
+/**
+ *****************************************************************************
+ *  Function: dal_transform_wide_gamut_set_rgb_limited_range_adjustment
+ *
+ *  @param [in] const struct grph_csc_adjustment *adjust
+ *
+ *  @return
+ *     void
+ *
+ *  @note calculate and program color adjustments for sRGB limited color space
+ *
+ *  @see
+ *
+ *****************************************************************************
+ */
+static void set_rgb_limited_range_adjustment(
+	struct dce110_opp *opp110,
+	const struct grph_csc_adjustment *adjust)
+{
+	struct out_csc_color_matrix reg_matrix;
+	struct fixed31_32 change_matrix[OUTPUT_CSC_MATRIX_SIZE];
+	struct fixed31_32 matrix[OUTPUT_CSC_MATRIX_SIZE];
+	struct dc_csc_adjustments adjustments;
+	struct fixed31_32 ideals[OUTPUT_CSC_MATRIX_SIZE];
+
+	prepare_tv_rgb_ideal(ideals);
+
+	setup_adjustments(adjust, &adjustments);
+
+	calculate_adjustments(ideals, &adjustments, matrix);
+
+	dm_memmove(change_matrix, matrix, sizeof(matrix));
+
+	/* from 1 -> 3 */
+	matrix[8] = change_matrix[0];
+	matrix[9] = change_matrix[1];
+	matrix[10] = change_matrix[2];
+	matrix[11] = change_matrix[3];
+
+	/* from 2 -> 1 */
+	matrix[0] = change_matrix[4];
+	matrix[1] = change_matrix[5];
+	matrix[2] = change_matrix[6];
+	matrix[3] = change_matrix[7];
+
+	/* from 3 -> 2 */
+	matrix[4] = change_matrix[8];
+	matrix[5] = change_matrix[9];
+	matrix[6] = change_matrix[10];
+	matrix[7] = change_matrix[11];
+
+	dm_memset(&reg_matrix, 0, sizeof(struct out_csc_color_matrix));
+
+	setup_reg_format(matrix, reg_matrix.regval);
+
+	program_color_matrix(opp110, &reg_matrix, GRPH_COLOR_MATRIX_SW);
+}
+
+static void prepare_yuv_ideal(
+	bool b601,
+	struct fixed31_32 *matrix)
+{
+	static const int32_t matrix_1[] = {
+		25578516, 50216016, 9752344, 6250000,
+		-14764391, -28985609, 43750000, 50000000,
+		43750000, -36635164, -7114836, 50000000
+	};
+
+	static const int32_t matrix_2[] = {
+		18187266, 61183125, 6176484, 6250000,
+		-10025059, -33724941, 43750000, 50000000,
+		43750000, -39738379, -4011621, 50000000
+	};
+
+	const int32_t *matrix_x = b601 ? matrix_1 : matrix_2;
+
+	uint32_t i = 0;
+
+	do {
+		matrix[i] = dal_fixed31_32_from_fraction(
+			matrix_x[i],
+			100000000);
+		++i;
+	} while (i != ARRAY_SIZE(matrix_1));
+}
+
+/**
+ *****************************************************************************
+ *  Function: dal_transform_wide_gamut_set_yuv_adjustment
+ *
+ *  @param [in] const struct grph_csc_adjustment *adjust
+ *
+ *  @return
+ *     void
+ *
+ *  @note calculate and program color adjustments for YUV  color spaces
+ *
+ *  @see
+ *
+ *****************************************************************************
+ */
+static void set_yuv_adjustment(
+	struct dce110_opp *opp110,
+	const struct grph_csc_adjustment *adjust)
+{
+	bool b601 = (adjust->c_space == COLOR_SPACE_YPBPR601) ||
+		(adjust->c_space == COLOR_SPACE_YCBCR601) ||
+		(adjust->c_space == COLOR_SPACE_YCBCR601_YONLY);
+	struct out_csc_color_matrix reg_matrix;
+	struct fixed31_32 matrix[OUTPUT_CSC_MATRIX_SIZE];
+	struct dc_csc_adjustments adjustments;
+	struct fixed31_32 ideals[OUTPUT_CSC_MATRIX_SIZE];
+
+	prepare_yuv_ideal(b601, ideals);
+
+	setup_adjustments(adjust, &adjustments);
+
+	if ((adjust->c_space == COLOR_SPACE_YCBCR601_YONLY) ||
+		(adjust->c_space == COLOR_SPACE_YCBCR709_YONLY))
+		calculate_adjustments_y_only(
+			ideals, &adjustments, matrix);
+	else
+		calculate_adjustments(
+			ideals, &adjustments, matrix);
+
+	dm_memset(&reg_matrix, 0, sizeof(struct out_csc_color_matrix));
+
+	setup_reg_format(matrix, reg_matrix.regval);
+
+	program_color_matrix(opp110, &reg_matrix, GRPH_COLOR_MATRIX_SW);
+}
+
+static bool configure_graphics_mode(
+	struct dce110_opp *opp110,
+	enum csc_color_mode config,
+	enum graphics_csc_adjust_type csc_adjust_type,
+	enum color_space color_space)
+{
+	struct dc_context *ctx = opp110->base.ctx;
+	uint32_t addr = DCP_REG(mmOUTPUT_CSC_CONTROL);
+	uint32_t value = dm_read_reg(ctx, addr);
+
+	set_reg_field_value(
+		value,
+		0,
+		OUTPUT_CSC_CONTROL,
+		OUTPUT_CSC_GRPH_MODE);
+
+	if (csc_adjust_type == GRAPHICS_CSC_ADJUST_TYPE_SW) {
+		if (config == CSC_COLOR_MODE_GRAPHICS_OUTPUT_CSC) {
+			set_reg_field_value(
+				value,
+				4,
+				OUTPUT_CSC_CONTROL,
+				OUTPUT_CSC_GRPH_MODE);
+		} else {
+
+			switch (color_space) {
+			case COLOR_SPACE_SRGB_FULL_RANGE:
+				/* by pass */
+				set_reg_field_value(
+					value,
+					0,
+					OUTPUT_CSC_CONTROL,
+					OUTPUT_CSC_GRPH_MODE);
+				break;
+			case COLOR_SPACE_SRGB_LIMITED_RANGE:
+				/* TV RGB */
+				set_reg_field_value(
+					value,
+					1,
+					OUTPUT_CSC_CONTROL,
+					OUTPUT_CSC_GRPH_MODE);
+				break;
+			case COLOR_SPACE_YCBCR601:
+			case COLOR_SPACE_YPBPR601:
+			case COLOR_SPACE_YCBCR601_YONLY:
+				/* YCbCr601 */
+				set_reg_field_value(
+					value,
+					2,
+					OUTPUT_CSC_CONTROL,
+					OUTPUT_CSC_GRPH_MODE);
+				break;
+			case COLOR_SPACE_YCBCR709:
+			case COLOR_SPACE_YPBPR709:
+			case COLOR_SPACE_YCBCR709_YONLY:
+				/* YCbCr709 */
+				set_reg_field_value(
+					value,
+					3,
+					OUTPUT_CSC_CONTROL,
+					OUTPUT_CSC_GRPH_MODE);
+				break;
+			default:
+				return false;
+			}
+		}
+	} else if (csc_adjust_type == GRAPHICS_CSC_ADJUST_TYPE_HW) {
+		switch (color_space) {
+		case COLOR_SPACE_SRGB_FULL_RANGE:
+			/* by pass */
+			set_reg_field_value(
+				value,
+				0,
+				OUTPUT_CSC_CONTROL,
+				OUTPUT_CSC_GRPH_MODE);
+			break;
+		case COLOR_SPACE_SRGB_LIMITED_RANGE:
+			/* TV RGB */
+			set_reg_field_value(
+				value,
+				1,
+				OUTPUT_CSC_CONTROL,
+				OUTPUT_CSC_GRPH_MODE);
+			break;
+		case COLOR_SPACE_YCBCR601:
+		case COLOR_SPACE_YPBPR601:
+		case COLOR_SPACE_YCBCR601_YONLY:
+			/* YCbCr601 */
+			set_reg_field_value(
+				value,
+				2,
+				OUTPUT_CSC_CONTROL,
+				OUTPUT_CSC_GRPH_MODE);
+			break;
+		case COLOR_SPACE_YCBCR709:
+		case COLOR_SPACE_YPBPR709:
+		case COLOR_SPACE_YCBCR709_YONLY:
+			 /* YCbCr709 */
+			set_reg_field_value(
+				value,
+				3,
+				OUTPUT_CSC_CONTROL,
+				OUTPUT_CSC_GRPH_MODE);
+			break;
+		default:
+			return false;
+		}
+
+	} else
+		/* by pass */
+		set_reg_field_value(
+			value,
+			0,
+			OUTPUT_CSC_CONTROL,
+			OUTPUT_CSC_GRPH_MODE);
+
+	addr = DCP_REG(mmOUTPUT_CSC_CONTROL);
+	dm_write_reg(ctx, addr, value);
+
+	return true;
+}
+
+void dce110_opp_set_csc_adjustment(
+	struct output_pixel_processor *opp,
+	const struct grph_csc_adjustment *adjust)
+{
+	struct dce110_opp *opp110 = TO_DCE110_OPP(opp);
+	enum csc_color_mode config =
+			CSC_COLOR_MODE_GRAPHICS_OUTPUT_CSC;
+
+	/* Apply color adjustments: brightness, saturation, hue, contrast and
+	 * CSC. No need for different color space routine, color space defines
+	 * the ideal values only, but keep original design to allow quick switch
+	 * to the old legacy routines */
+	switch (adjust->c_space) {
+	case COLOR_SPACE_SRGB_FULL_RANGE:
+		set_rgb_adjustment_legacy(opp110, adjust);
+		break;
+	case COLOR_SPACE_SRGB_LIMITED_RANGE:
+		set_rgb_limited_range_adjustment(
+			opp110, adjust);
+		break;
+	case COLOR_SPACE_YCBCR601:
+	case COLOR_SPACE_YCBCR709:
+	case COLOR_SPACE_YCBCR601_YONLY:
+	case COLOR_SPACE_YCBCR709_YONLY:
+	case COLOR_SPACE_YPBPR601:
+	case COLOR_SPACE_YPBPR709:
+		set_yuv_adjustment(opp110, adjust);
+		break;
+	default:
+		set_rgb_adjustment_legacy(opp110, adjust);
+		break;
+	}
+
+	/*  We did everything ,now program DxOUTPUT_CSC_CONTROL */
+	configure_graphics_mode(opp110, config, adjust->csc_adjust_type,
+		adjust->c_space);
+}
+
+void dce110_opp_set_csc_default(
+	struct output_pixel_processor *opp,
+	const struct default_adjustment *default_adjust)
+{
+	struct dce110_opp *opp110 = TO_DCE110_OPP(opp);
+	enum csc_color_mode config =
+			CSC_COLOR_MODE_GRAPHICS_PREDEFINED;
+
+	if (default_adjust->force_hw_default == false) {
+		const struct out_csc_color_matrix *elm;
+		/* currently parameter not in use */
+		enum grph_color_adjust_option option =
+			GRPH_COLOR_MATRIX_HW_DEFAULT;
+		uint32_t i;
+		/*
+		 * HW default false we program locally defined matrix
+		 * HW default true  we use predefined hw matrix and we
+		 * do not need to program matrix
+		 * OEM wants the HW default via runtime parameter.
+		 */
+		option = GRPH_COLOR_MATRIX_SW;
+
+		for (i = 0; i < ARRAY_SIZE(global_color_matrix); ++i) {
+			elm = &global_color_matrix[i];
+			if (elm->color_space != default_adjust->color_space)
+				continue;
+			/* program the matrix with default values from this
+			 * file */
+			program_color_matrix(opp110, elm, option);
+			config = CSC_COLOR_MODE_GRAPHICS_OUTPUT_CSC;
+			break;
+		}
+	}
+
+	/* configure the what we programmed :
+	 * 1. Default values from this file
+	 * 2. Use hardware default from ROM_A and we do not need to program
+	 * matrix */
+
+	configure_graphics_mode(opp110, config,
+		default_adjust->csc_adjust_type,
+		default_adjust->color_space);
+}
diff --git a/drivers/gpu/drm/amd/dal/dc/dce110/dce110_opp_formatter.c b/drivers/gpu/drm/amd/dal/dc/dce110/dce110_opp_formatter.c
new file mode 100644
index 000000000000..235b92e3af61
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/dce110/dce110_opp_formatter.c
@@ -0,0 +1,610 @@
+/*
+ * 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
+ *
+ */
+
+#include "dm_services.h"
+
+#include "dce/dce_11_0_d.h"
+#include "dce/dce_11_0_sh_mask.h"
+
+#include "dce110_opp.h"
+
+#define FMT_REG(reg)\
+	(reg + opp110->offsets.fmt_offset)
+
+/**
+ *	set_truncation
+ *	1) set truncation depth: 0 for 18 bpp or 1 for 24 bpp
+ *	2) enable truncation
+ *	3) HW remove 12bit FMT support for DCE11 power saving reason.
+ */
+static void set_truncation(
+		struct dce110_opp *opp110,
+		const struct bit_depth_reduction_params *params)
+{
+	uint32_t value = 0;
+	uint32_t addr = FMT_REG(mmFMT_BIT_DEPTH_CONTROL);
+
+	/*Disable truncation*/
+	value = dm_read_reg(opp110->base.ctx, addr);
+	set_reg_field_value(value, 0,
+		FMT_BIT_DEPTH_CONTROL, FMT_TRUNCATE_EN);
+	set_reg_field_value(value, 0,
+		FMT_BIT_DEPTH_CONTROL, FMT_TRUNCATE_DEPTH);
+	set_reg_field_value(value, 0,
+		FMT_BIT_DEPTH_CONTROL, FMT_TRUNCATE_MODE);
+
+	dm_write_reg(opp110->base.ctx, addr, value);
+
+	/* no 10bpc trunc on DCE11*/
+	if (params->flags.TRUNCATE_ENABLED == 0 ||
+		params->flags.TRUNCATE_DEPTH == 2)
+		return;
+
+	/*Set truncation depth and Enable truncation*/
+	set_reg_field_value(value, 1,
+		FMT_BIT_DEPTH_CONTROL, FMT_TRUNCATE_EN);
+	set_reg_field_value(value, params->flags.TRUNCATE_MODE,
+		FMT_BIT_DEPTH_CONTROL, FMT_TRUNCATE_MODE);
+	set_reg_field_value(value, params->flags.TRUNCATE_DEPTH,
+		FMT_BIT_DEPTH_CONTROL, FMT_TRUNCATE_DEPTH);
+
+	dm_write_reg(opp110->base.ctx, addr, value);
+
+}
+
+/**
+ *	set_spatial_dither
+ *	1) set spatial dithering mode: pattern of seed
+ *	2) set spatical dithering depth: 0 for 18bpp or 1 for 24bpp
+ *	3) set random seed
+ *	4) set random mode
+ *		lfsr is reset every frame or not reset
+ *		RGB dithering method
+ *		0: RGB data are all dithered with x^28+x^3+1
+ *		1: R data is dithered with x^28+x^3+1
+ *		G data is dithered with x^28+X^9+1
+ *		B data is dithered with x^28+x^13+1
+ *		enable high pass filter or not
+ *	5) enable spatical dithering
+ */
+static void set_spatial_dither(
+	struct dce110_opp *opp110,
+	const struct bit_depth_reduction_params *params)
+{
+	uint32_t addr = FMT_REG(mmFMT_BIT_DEPTH_CONTROL);
+	uint32_t depth_cntl_value = 0;
+	uint32_t fmt_cntl_value = 0;
+	uint32_t dither_r_value = 0;
+	uint32_t dither_g_value = 0;
+	uint32_t dither_b_value = 0;
+
+	/*Disable spatial (random) dithering*/
+	depth_cntl_value = dm_read_reg(opp110->base.ctx, addr);
+	set_reg_field_value(depth_cntl_value, 0,
+		FMT_BIT_DEPTH_CONTROL, FMT_SPATIAL_DITHER_EN);
+	set_reg_field_value(depth_cntl_value, 0,
+		FMT_BIT_DEPTH_CONTROL, FMT_SPATIAL_DITHER_MODE);
+	set_reg_field_value(depth_cntl_value, 0,
+		FMT_BIT_DEPTH_CONTROL, FMT_SPATIAL_DITHER_DEPTH);
+	set_reg_field_value(depth_cntl_value, 0,
+		FMT_BIT_DEPTH_CONTROL, FMT_TEMPORAL_DITHER_EN);
+	set_reg_field_value(depth_cntl_value, 0,
+		FMT_BIT_DEPTH_CONTROL, FMT_HIGHPASS_RANDOM_ENABLE);
+	set_reg_field_value(depth_cntl_value, 0,
+		FMT_BIT_DEPTH_CONTROL, FMT_FRAME_RANDOM_ENABLE);
+	set_reg_field_value(depth_cntl_value, 0,
+		FMT_BIT_DEPTH_CONTROL, FMT_RGB_RANDOM_ENABLE);
+
+	dm_write_reg(opp110->base.ctx, addr, depth_cntl_value);
+
+	/* no 10bpc on DCE11*/
+	if (params->flags.SPATIAL_DITHER_ENABLED == 0 ||
+		params->flags.SPATIAL_DITHER_DEPTH == 2)
+		return;
+
+	addr = FMT_REG(mmFMT_CONTROL);
+	fmt_cntl_value = dm_read_reg(opp110->base.ctx, addr);
+	/* only use FRAME_COUNTER_MAX if frameRandom == 1*/
+	if (params->flags.FRAME_RANDOM == 1) {
+		if (params->flags.SPATIAL_DITHER_DEPTH == 0 ||
+		params->flags.SPATIAL_DITHER_DEPTH == 1) {
+			set_reg_field_value(fmt_cntl_value, 15,
+				FMT_CONTROL,
+				FMT_SPATIAL_DITHER_FRAME_COUNTER_MAX);
+			set_reg_field_value(fmt_cntl_value, 2,
+				FMT_CONTROL,
+				FMT_SPATIAL_DITHER_FRAME_COUNTER_BIT_SWAP);
+		} else if (params->flags.SPATIAL_DITHER_DEPTH == 2) {
+			set_reg_field_value(fmt_cntl_value, 3,
+				FMT_CONTROL,
+				FMT_SPATIAL_DITHER_FRAME_COUNTER_MAX);
+			set_reg_field_value(fmt_cntl_value, 1,
+				FMT_CONTROL,
+				FMT_SPATIAL_DITHER_FRAME_COUNTER_BIT_SWAP);
+		} else
+			return;
+	} else {
+		set_reg_field_value(fmt_cntl_value, 0,
+			FMT_CONTROL,
+			FMT_SPATIAL_DITHER_FRAME_COUNTER_MAX);
+		set_reg_field_value(fmt_cntl_value, 0,
+			FMT_CONTROL,
+			FMT_SPATIAL_DITHER_FRAME_COUNTER_BIT_SWAP);
+	}
+
+	dm_write_reg(opp110->base.ctx, addr, fmt_cntl_value);
+
+	/*Set seed for random values for
+	 * spatial dithering for R,G,B channels*/
+	addr = FMT_REG(mmFMT_DITHER_RAND_R_SEED);
+	set_reg_field_value(dither_r_value, params->r_seed_value,
+		FMT_DITHER_RAND_R_SEED,
+		FMT_RAND_R_SEED);
+	dm_write_reg(opp110->base.ctx, addr, dither_r_value);
+
+	addr = FMT_REG(mmFMT_DITHER_RAND_G_SEED);
+	set_reg_field_value(dither_g_value,
+		params->g_seed_value,
+		FMT_DITHER_RAND_G_SEED,
+		FMT_RAND_G_SEED);
+	dm_write_reg(opp110->base.ctx, addr, dither_g_value);
+
+	addr = FMT_REG(mmFMT_DITHER_RAND_B_SEED);
+	set_reg_field_value(dither_b_value, params->b_seed_value,
+		FMT_DITHER_RAND_B_SEED,
+		FMT_RAND_B_SEED);
+	dm_write_reg(opp110->base.ctx, addr, dither_b_value);
+
+	/* FMT_OFFSET_R_Cr  31:16 0x0 Setting the zero
+	 * offset for the R/Cr channel, lower 4LSB
+	 * is forced to zeros. Typically set to 0
+	 * RGB and 0x80000 YCbCr.
+	 */
+	/* FMT_OFFSET_G_Y   31:16 0x0 Setting the zero
+	 * offset for the G/Y  channel, lower 4LSB is
+	 * forced to zeros. Typically set to 0 RGB
+	 * and 0x80000 YCbCr.
+	 */
+	/* FMT_OFFSET_B_Cb  31:16 0x0 Setting the zero
+	 * offset for the B/Cb channel, lower 4LSB is
+	 * forced to zeros. Typically set to 0 RGB and
+	 * 0x80000 YCbCr.
+	 */
+
+	/*Set spatial dithering bit depth*/
+	set_reg_field_value(depth_cntl_value,
+		params->flags.SPATIAL_DITHER_DEPTH,
+		FMT_BIT_DEPTH_CONTROL,
+		FMT_SPATIAL_DITHER_DEPTH);
+
+	/* Set spatial dithering mode
+	 * (default is Seed patterrn AAAA...)
+	 */
+	set_reg_field_value(depth_cntl_value,
+		params->flags.SPATIAL_DITHER_MODE,
+		FMT_BIT_DEPTH_CONTROL,
+		FMT_SPATIAL_DITHER_MODE);
+
+	/*Reset only at startup*/
+	set_reg_field_value(depth_cntl_value,
+		params->flags.FRAME_RANDOM,
+		FMT_BIT_DEPTH_CONTROL,
+		FMT_RGB_RANDOM_ENABLE);
+
+	/*Set RGB data dithered with x^28+x^3+1*/
+	set_reg_field_value(depth_cntl_value,
+		params->flags.RGB_RANDOM,
+		FMT_BIT_DEPTH_CONTROL,
+		FMT_RGB_RANDOM_ENABLE);
+
+	/*Disable High pass filter*/
+	set_reg_field_value(depth_cntl_value,
+		params->flags.HIGHPASS_RANDOM,
+		FMT_BIT_DEPTH_CONTROL,
+		FMT_HIGHPASS_RANDOM_ENABLE);
+
+	/*Enable spatial dithering*/
+	set_reg_field_value(depth_cntl_value,
+		1,
+		FMT_BIT_DEPTH_CONTROL,
+		FMT_SPATIAL_DITHER_EN);
+
+	addr = FMT_REG(mmFMT_BIT_DEPTH_CONTROL);
+	dm_write_reg(opp110->base.ctx, addr, depth_cntl_value);
+
+}
+
+/**
+ *	SetTemporalDither (Frame Modulation)
+ *	1) set temporal dither depth
+ *	2) select pattern: from hard-coded pattern or programmable pattern
+ *	3) select optimized strips for BGR or RGB LCD sub-pixel
+ *	4) set s matrix
+ *	5) set t matrix
+ *	6) set grey level for 0.25, 0.5, 0.75
+ *	7) enable temporal dithering
+ */
+static void set_temporal_dither(
+	struct dce110_opp *opp110,
+	const struct bit_depth_reduction_params *params)
+{
+	uint32_t addr = FMT_REG(mmFMT_BIT_DEPTH_CONTROL);
+	uint32_t value;
+
+	/*Disable temporal (frame modulation) dithering first*/
+	value = dm_read_reg(opp110->base.ctx, addr);
+
+	set_reg_field_value(value,
+		0,
+		FMT_BIT_DEPTH_CONTROL,
+		FMT_TEMPORAL_DITHER_EN);
+
+	set_reg_field_value(value,
+		0,
+		FMT_BIT_DEPTH_CONTROL,
+		FMT_TEMPORAL_DITHER_RESET);
+	set_reg_field_value(value,
+		0,
+		FMT_BIT_DEPTH_CONTROL,
+		FMT_TEMPORAL_DITHER_OFFSET);
+	set_reg_field_value(value,
+		0,
+		FMT_BIT_DEPTH_CONTROL,
+		FMT_TEMPORAL_DITHER_DEPTH);
+	set_reg_field_value(value,
+		0,
+		FMT_BIT_DEPTH_CONTROL,
+		FMT_TEMPORAL_LEVEL);
+	set_reg_field_value(value,
+		0,
+		FMT_BIT_DEPTH_CONTROL,
+		FMT_25FRC_SEL);
+
+	set_reg_field_value(value,
+		0,
+		FMT_BIT_DEPTH_CONTROL,
+		FMT_50FRC_SEL);
+
+	set_reg_field_value(value,
+		0,
+		FMT_BIT_DEPTH_CONTROL,
+		FMT_75FRC_SEL);
+
+	dm_write_reg(opp110->base.ctx, addr, value);
+
+	/* no 10bpc dither on DCE11*/
+	if (params->flags.FRAME_MODULATION_ENABLED == 0 ||
+		params->flags.FRAME_MODULATION_DEPTH == 2)
+		return;
+
+	/* Set temporal dithering depth*/
+	set_reg_field_value(value,
+		params->flags.FRAME_MODULATION_DEPTH,
+		FMT_BIT_DEPTH_CONTROL,
+		FMT_TEMPORAL_DITHER_DEPTH);
+
+	set_reg_field_value(value,
+		0,
+		FMT_BIT_DEPTH_CONTROL,
+		FMT_TEMPORAL_DITHER_RESET);
+
+	set_reg_field_value(value,
+		0,
+		FMT_BIT_DEPTH_CONTROL,
+		FMT_TEMPORAL_DITHER_OFFSET);
+
+	/*Select legacy pattern based on FRC and Temporal level*/
+	addr = FMT_REG(mmFMT_TEMPORAL_DITHER_PATTERN_CONTROL);
+	dm_write_reg(opp110->base.ctx, addr, 0);
+	/*Set s matrix*/
+	addr = FMT_REG(
+		mmFMT_TEMPORAL_DITHER_PROGRAMMABLE_PATTERN_S_MATRIX);
+	dm_write_reg(opp110->base.ctx, addr, 0);
+	/*Set t matrix*/
+	addr = FMT_REG(
+		mmFMT_TEMPORAL_DITHER_PROGRAMMABLE_PATTERN_T_MATRIX);
+	dm_write_reg(opp110->base.ctx, addr, 0);
+
+	/*Select patterns for 0.25, 0.5 and 0.75 grey level*/
+	set_reg_field_value(value,
+		params->flags.TEMPORAL_LEVEL,
+		FMT_BIT_DEPTH_CONTROL,
+		FMT_TEMPORAL_LEVEL);
+
+	set_reg_field_value(value,
+		params->flags.FRC25,
+		FMT_BIT_DEPTH_CONTROL,
+		FMT_25FRC_SEL);
+
+	set_reg_field_value(value,
+		params->flags.FRC50,
+		FMT_BIT_DEPTH_CONTROL,
+		FMT_50FRC_SEL);
+
+	set_reg_field_value(value,
+		params->flags.FRC75,
+		FMT_BIT_DEPTH_CONTROL,
+		FMT_75FRC_SEL);
+
+	/*Enable bit reduction by temporal (frame modulation) dithering*/
+	set_reg_field_value(value,
+		1,
+		FMT_BIT_DEPTH_CONTROL,
+		FMT_TEMPORAL_DITHER_EN);
+
+	addr = FMT_REG(mmFMT_BIT_DEPTH_CONTROL);
+	dm_write_reg(opp110->base.ctx, addr, value);
+
+}
+
+/**
+ *	Set Clamping
+ *	1) Set clamping format based on bpc - 0 for 6bpc (No clamping)
+ *		1 for 8 bpc
+ *		2 for 10 bpc
+ *		3 for 12 bpc
+ *		7 for programable
+ *	2) Enable clamp if Limited range requested
+ */
+static void set_clamping(
+	struct dce110_opp *opp110,
+	const struct clamping_and_pixel_encoding_params *params)
+{
+	uint32_t clamp_cntl_value = 0;
+	uint32_t red_clamp_value = 0;
+	uint32_t green_clamp_value = 0;
+	uint32_t blue_clamp_value = 0;
+	uint32_t addr = FMT_REG(mmFMT_CLAMP_CNTL);
+
+	clamp_cntl_value = dm_read_reg(opp110->base.ctx, addr);
+
+	set_reg_field_value(clamp_cntl_value,
+		0,
+		FMT_CLAMP_CNTL,
+		FMT_CLAMP_DATA_EN);
+
+	set_reg_field_value(clamp_cntl_value,
+		0,
+		FMT_CLAMP_CNTL,
+		FMT_CLAMP_COLOR_FORMAT);
+
+	switch (params->clamping_level) {
+	case CLAMPING_FULL_RANGE:
+		break;
+
+	case CLAMPING_LIMITED_RANGE_8BPC:
+		set_reg_field_value(clamp_cntl_value,
+			1,
+			FMT_CLAMP_CNTL,
+			FMT_CLAMP_DATA_EN);
+
+		set_reg_field_value(clamp_cntl_value,
+			1,
+			FMT_CLAMP_CNTL,
+			FMT_CLAMP_COLOR_FORMAT);
+
+		break;
+
+	case CLAMPING_LIMITED_RANGE_10BPC:
+		set_reg_field_value(clamp_cntl_value,
+			1,
+			FMT_CLAMP_CNTL,
+			FMT_CLAMP_DATA_EN);
+
+		set_reg_field_value(clamp_cntl_value,
+			2,
+			FMT_CLAMP_CNTL,
+			FMT_CLAMP_COLOR_FORMAT);
+
+		break;
+	case CLAMPING_LIMITED_RANGE_12BPC:
+		set_reg_field_value(clamp_cntl_value,
+			1,
+			FMT_CLAMP_CNTL,
+			FMT_CLAMP_DATA_EN);
+
+		set_reg_field_value(clamp_cntl_value,
+			3,
+			FMT_CLAMP_CNTL,
+			FMT_CLAMP_COLOR_FORMAT);
+
+		break;
+	case CLAMPING_LIMITED_RANGE_PROGRAMMABLE:
+		set_reg_field_value(clamp_cntl_value,
+			1,
+			FMT_CLAMP_CNTL,
+			FMT_CLAMP_DATA_EN);
+
+		set_reg_field_value(clamp_cntl_value,
+			7,
+			FMT_CLAMP_CNTL,
+			FMT_CLAMP_COLOR_FORMAT);
+
+		/*set the defaults*/
+		set_reg_field_value(red_clamp_value,
+			0x10,
+			FMT_CLAMP_COMPONENT_R,
+			FMT_CLAMP_LOWER_R);
+
+		set_reg_field_value(red_clamp_value,
+			0xFEF,
+			FMT_CLAMP_COMPONENT_R,
+			FMT_CLAMP_UPPER_R);
+
+		addr = FMT_REG(mmFMT_CLAMP_COMPONENT_R);
+		dm_write_reg(opp110->base.ctx, addr, red_clamp_value);
+
+		set_reg_field_value(green_clamp_value,
+			0x10,
+			FMT_CLAMP_COMPONENT_G,
+			FMT_CLAMP_LOWER_G);
+
+		set_reg_field_value(green_clamp_value,
+			0xFEF,
+			FMT_CLAMP_COMPONENT_G,
+			FMT_CLAMP_UPPER_G);
+
+		addr = FMT_REG(mmFMT_CLAMP_COMPONENT_G);
+		dm_write_reg(opp110->base.ctx, addr, green_clamp_value);
+
+		set_reg_field_value(blue_clamp_value,
+			0x10,
+			FMT_CLAMP_COMPONENT_B,
+			FMT_CLAMP_LOWER_B);
+
+		set_reg_field_value(blue_clamp_value,
+			0xFEF,
+			FMT_CLAMP_COMPONENT_B,
+			FMT_CLAMP_UPPER_B);
+
+		addr = FMT_REG(mmFMT_CLAMP_COMPONENT_B);
+		dm_write_reg(opp110->base.ctx, addr, blue_clamp_value);
+
+		break;
+
+	default:
+		break;
+	}
+
+	addr = FMT_REG(mmFMT_CLAMP_CNTL);
+	/*Set clamp control*/
+	dm_write_reg(opp110->base.ctx, addr, clamp_cntl_value);
+
+}
+
+/**
+ *	set_pixel_encoding
+ *
+ *	Set Pixel Encoding
+ *		0: RGB 4:4:4 or YCbCr 4:4:4 or YOnly
+ *		1: YCbCr 4:2:2
+ */
+static void set_pixel_encoding(
+	struct dce110_opp *opp110,
+	const struct clamping_and_pixel_encoding_params *params)
+{
+	uint32_t fmt_cntl_value;
+	uint32_t addr = FMT_REG(mmFMT_CONTROL);
+
+	/*RGB 4:4:4 or YCbCr 4:4:4 - 0; YCbCr 4:2:2 -1.*/
+	fmt_cntl_value = dm_read_reg(opp110->base.ctx, addr);
+
+	set_reg_field_value(fmt_cntl_value,
+		0,
+		FMT_CONTROL,
+		FMT_PIXEL_ENCODING);
+
+	if (params->pixel_encoding == PIXEL_ENCODING_YCBCR422) {
+		set_reg_field_value(fmt_cntl_value,
+			1,
+			FMT_CONTROL,
+			FMT_PIXEL_ENCODING);
+
+		/*00 - Pixels drop mode ,01 - Pixels average mode*/
+		set_reg_field_value(fmt_cntl_value,
+			0,
+			FMT_CONTROL,
+			FMT_SUBSAMPLING_MODE);
+
+		/*00 - Cb before Cr ,01 - Cr before Cb*/
+		set_reg_field_value(fmt_cntl_value,
+			0,
+			FMT_CONTROL,
+			FMT_SUBSAMPLING_ORDER);
+	}
+	dm_write_reg(opp110->base.ctx, addr, fmt_cntl_value);
+
+}
+
+void dce110_opp_program_bit_depth_reduction(
+	struct output_pixel_processor *opp,
+	const struct bit_depth_reduction_params *params)
+{
+	struct dce110_opp *opp110 = TO_DCE110_OPP(opp);
+
+	set_truncation(opp110, params);
+	set_spatial_dither(opp110, params);
+	set_temporal_dither(opp110, params);
+}
+
+void dce110_opp_program_clamping_and_pixel_encoding(
+	struct output_pixel_processor *opp,
+	const struct clamping_and_pixel_encoding_params *params)
+{
+	struct dce110_opp *opp110 = TO_DCE110_OPP(opp);
+
+	set_clamping(opp110, params);
+	set_pixel_encoding(opp110, params);
+}
+
+void dce110_opp_set_dyn_expansion(
+	struct output_pixel_processor *opp,
+	enum color_space color_sp,
+	enum dc_color_depth color_dpth,
+	enum signal_type signal)
+{
+	struct dce110_opp *opp110 = TO_DCE110_OPP(opp);
+	uint32_t value;
+	bool enable_dyn_exp = false;
+	uint32_t addr = FMT_REG(mmFMT_DYNAMIC_EXP_CNTL);
+
+	value = dm_read_reg(opp->ctx, addr);
+
+	set_reg_field_value(value, 0,
+		FMT_DYNAMIC_EXP_CNTL, FMT_DYNAMIC_EXP_EN);
+	set_reg_field_value(value, 0,
+		FMT_DYNAMIC_EXP_CNTL, FMT_DYNAMIC_EXP_MODE);
+
+	/* From HW programming guide:
+		FMT_DYNAMIC_EXP_EN = 0 for limited RGB or YCbCr output
+		FMT_DYNAMIC_EXP_EN = 1 for RGB full range only*/
+	if (color_sp == COLOR_SPACE_SRGB_FULL_RANGE)
+		enable_dyn_exp = true;
+
+	/*00 - 10-bit -> 12-bit dynamic expansion*/
+	/*01 - 8-bit  -> 12-bit dynamic expansion*/
+	if (signal == SIGNAL_TYPE_HDMI_TYPE_A) {
+		switch (color_dpth) {
+		case COLOR_DEPTH_888:
+			set_reg_field_value(value, enable_dyn_exp ? 1:0,
+				FMT_DYNAMIC_EXP_CNTL, FMT_DYNAMIC_EXP_EN);
+			set_reg_field_value(value, 1,
+				FMT_DYNAMIC_EXP_CNTL, FMT_DYNAMIC_EXP_MODE);
+			break;
+		case COLOR_DEPTH_101010:
+			set_reg_field_value(value, enable_dyn_exp ? 1:0,
+				FMT_DYNAMIC_EXP_CNTL, FMT_DYNAMIC_EXP_EN);
+			set_reg_field_value(value, 0,
+				FMT_DYNAMIC_EXP_CNTL, FMT_DYNAMIC_EXP_MODE);
+			break;
+		case COLOR_DEPTH_121212:
+			break;
+		default:
+			break;
+		}
+	}
+
+	dm_write_reg(opp->ctx, addr, value);
+}
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
new file mode 100644
index 000000000000..32cf57dd80d2
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/dce110/dce110_opp_regamma.c
@@ -0,0 +1,2474 @@
+/*
+ * 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
+ *
+ */
+
+#include "dm_services.h"
+
+/* include DCE11 register header files */
+#include "dce/dce_11_0_d.h"
+#include "dce/dce_11_0_sh_mask.h"
+
+#include "dce110_opp.h"
+#include "gamma_types.h"
+
+#define DCP_REG(reg)\
+	(reg + opp110->offsets.dcp_offset)
+
+#define DCFE_REG(reg)\
+	(reg + opp110->offsets.dcfe_offset)
+
+enum {
+	MAX_PWL_ENTRY = 128,
+	MAX_REGIONS_NUMBER = 16
+
+};
+
+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
+ *
+ *     build regamma curve by using predefined hw points
+ *     uses interface parameters ,like EDID coeff.
+ *
+ * @param   : parameters   interface parameters
+ *  @return void
+ *
+ *  @note
+ *
+ *  @see
+ *
+ *****************************************************************************
+ */
+static void regamma_config_regions_and_segments(
+	struct dce110_opp *opp110)
+{
+	struct gamma_curve *curve;
+	uint32_t value = 0;
+
+	{
+		set_reg_field_value(
+			value,
+			opp110->regamma.arr_points[0].custom_float_x,
+			REGAMMA_CNTLA_START_CNTL,
+			REGAMMA_CNTLA_EXP_REGION_START);
+
+		set_reg_field_value(
+			value,
+			0,
+			REGAMMA_CNTLA_START_CNTL,
+			REGAMMA_CNTLA_EXP_REGION_START_SEGMENT);
+
+		dm_write_reg(opp110->base.ctx,
+				DCP_REG(mmREGAMMA_CNTLA_START_CNTL),
+				value);
+	}
+	{
+		value = 0;
+		set_reg_field_value(
+			value,
+			opp110->regamma.arr_points[0].custom_float_slope,
+			REGAMMA_CNTLA_SLOPE_CNTL,
+			REGAMMA_CNTLA_EXP_REGION_LINEAR_SLOPE);
+
+		dm_write_reg(opp110->base.ctx,
+			DCP_REG(mmREGAMMA_CNTLA_SLOPE_CNTL), value);
+	}
+	{
+		value = 0;
+		set_reg_field_value(
+			value,
+			opp110->regamma.arr_points[1].custom_float_x,
+			REGAMMA_CNTLA_END_CNTL1,
+			REGAMMA_CNTLA_EXP_REGION_END);
+
+		dm_write_reg(opp110->base.ctx,
+			DCP_REG(mmREGAMMA_CNTLA_END_CNTL1), value);
+	}
+	{
+		value = 0;
+		set_reg_field_value(
+			value,
+			opp110->regamma.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,
+			REGAMMA_CNTLA_END_CNTL2,
+			REGAMMA_CNTLA_EXP_REGION_END_SLOPE);
+
+		dm_write_reg(opp110->base.ctx,
+			DCP_REG(mmREGAMMA_CNTLA_END_CNTL2), value);
+	}
+
+	curve = opp110->regamma.arr_curve_points;
+
+	{
+		value = 0;
+		set_reg_field_value(
+			value,
+			curve[0].offset,
+			REGAMMA_CNTLA_REGION_0_1,
+			REGAMMA_CNTLA_EXP_REGION0_LUT_OFFSET);
+
+		set_reg_field_value(
+			value,
+			curve[0].segments_num,
+			REGAMMA_CNTLA_REGION_0_1,
+			REGAMMA_CNTLA_EXP_REGION0_NUM_SEGMENTS);
+
+		set_reg_field_value(
+			value,
+			curve[1].offset,
+			REGAMMA_CNTLA_REGION_0_1,
+			REGAMMA_CNTLA_EXP_REGION1_LUT_OFFSET);
+
+		set_reg_field_value(
+			value,
+			curve[1].segments_num,
+			REGAMMA_CNTLA_REGION_0_1,
+			REGAMMA_CNTLA_EXP_REGION1_NUM_SEGMENTS);
+
+		dm_write_reg(
+			opp110->base.ctx,
+			DCP_REG(mmREGAMMA_CNTLA_REGION_0_1),
+			value);
+	}
+
+	curve += 2;
+	{
+		value = 0;
+		set_reg_field_value(
+			value,
+			curve[0].offset,
+			REGAMMA_CNTLA_REGION_2_3,
+			REGAMMA_CNTLA_EXP_REGION2_LUT_OFFSET);
+
+		set_reg_field_value(
+			value,
+			curve[0].segments_num,
+			REGAMMA_CNTLA_REGION_2_3,
+			REGAMMA_CNTLA_EXP_REGION2_NUM_SEGMENTS);
+
+		set_reg_field_value(
+			value,
+			curve[1].offset,
+			REGAMMA_CNTLA_REGION_2_3,
+			REGAMMA_CNTLA_EXP_REGION3_LUT_OFFSET);
+
+		set_reg_field_value(
+			value,
+			curve[1].segments_num,
+			REGAMMA_CNTLA_REGION_2_3,
+			REGAMMA_CNTLA_EXP_REGION3_NUM_SEGMENTS);
+
+		dm_write_reg(opp110->base.ctx,
+			DCP_REG(mmREGAMMA_CNTLA_REGION_2_3),
+			value);
+	}
+
+	curve += 2;
+	{
+		value = 0;
+		set_reg_field_value(
+			value,
+			curve[0].offset,
+			REGAMMA_CNTLA_REGION_4_5,
+			REGAMMA_CNTLA_EXP_REGION4_LUT_OFFSET);
+
+		set_reg_field_value(
+			value,
+			curve[0].segments_num,
+			REGAMMA_CNTLA_REGION_4_5,
+			REGAMMA_CNTLA_EXP_REGION4_NUM_SEGMENTS);
+
+		set_reg_field_value(
+			value,
+			curve[1].offset,
+			REGAMMA_CNTLA_REGION_4_5,
+			REGAMMA_CNTLA_EXP_REGION5_LUT_OFFSET);
+
+		set_reg_field_value(
+			value,
+			curve[1].segments_num,
+			REGAMMA_CNTLA_REGION_4_5,
+			REGAMMA_CNTLA_EXP_REGION5_NUM_SEGMENTS);
+
+		dm_write_reg(opp110->base.ctx,
+			DCP_REG(mmREGAMMA_CNTLA_REGION_4_5),
+			value);
+	}
+
+	curve += 2;
+	{
+		value = 0;
+		set_reg_field_value(
+			value,
+			curve[0].offset,
+			REGAMMA_CNTLA_REGION_6_7,
+			REGAMMA_CNTLA_EXP_REGION6_LUT_OFFSET);
+
+		set_reg_field_value(
+			value,
+			curve[0].segments_num,
+			REGAMMA_CNTLA_REGION_6_7,
+			REGAMMA_CNTLA_EXP_REGION6_NUM_SEGMENTS);
+
+		set_reg_field_value(
+			value,
+			curve[1].offset,
+			REGAMMA_CNTLA_REGION_6_7,
+			REGAMMA_CNTLA_EXP_REGION7_LUT_OFFSET);
+
+		set_reg_field_value(
+			value,
+			curve[1].segments_num,
+			REGAMMA_CNTLA_REGION_6_7,
+			REGAMMA_CNTLA_EXP_REGION7_NUM_SEGMENTS);
+
+		dm_write_reg(opp110->base.ctx,
+			DCP_REG(mmREGAMMA_CNTLA_REGION_6_7),
+			value);
+	}
+
+	curve += 2;
+	{
+		value = 0;
+		set_reg_field_value(
+			value,
+			curve[0].offset,
+			REGAMMA_CNTLA_REGION_8_9,
+			REGAMMA_CNTLA_EXP_REGION8_LUT_OFFSET);
+
+		set_reg_field_value(
+			value,
+			curve[0].segments_num,
+			REGAMMA_CNTLA_REGION_8_9,
+			REGAMMA_CNTLA_EXP_REGION8_NUM_SEGMENTS);
+
+		set_reg_field_value(
+			value,
+			curve[1].offset,
+			REGAMMA_CNTLA_REGION_8_9,
+			REGAMMA_CNTLA_EXP_REGION9_LUT_OFFSET);
+
+		set_reg_field_value(
+			value,
+			curve[1].segments_num,
+			REGAMMA_CNTLA_REGION_8_9,
+			REGAMMA_CNTLA_EXP_REGION9_NUM_SEGMENTS);
+
+		dm_write_reg(opp110->base.ctx,
+			DCP_REG(mmREGAMMA_CNTLA_REGION_8_9),
+			value);
+	}
+
+	curve += 2;
+	{
+		value = 0;
+		set_reg_field_value(
+			value,
+			curve[0].offset,
+			REGAMMA_CNTLA_REGION_10_11,
+			REGAMMA_CNTLA_EXP_REGION10_LUT_OFFSET);
+
+		set_reg_field_value(
+			value,
+			curve[0].segments_num,
+			REGAMMA_CNTLA_REGION_10_11,
+			REGAMMA_CNTLA_EXP_REGION10_NUM_SEGMENTS);
+
+		set_reg_field_value(
+			value,
+			curve[1].offset,
+			REGAMMA_CNTLA_REGION_10_11,
+			REGAMMA_CNTLA_EXP_REGION11_LUT_OFFSET);
+
+		set_reg_field_value(
+			value,
+			curve[1].segments_num,
+			REGAMMA_CNTLA_REGION_10_11,
+			REGAMMA_CNTLA_EXP_REGION11_NUM_SEGMENTS);
+
+		dm_write_reg(opp110->base.ctx,
+			DCP_REG(mmREGAMMA_CNTLA_REGION_10_11),
+			value);
+	}
+
+	curve += 2;
+	{
+		value = 0;
+		set_reg_field_value(
+			value,
+			curve[0].offset,
+			REGAMMA_CNTLA_REGION_12_13,
+			REGAMMA_CNTLA_EXP_REGION12_LUT_OFFSET);
+
+		set_reg_field_value(
+			value,
+			curve[0].segments_num,
+			REGAMMA_CNTLA_REGION_12_13,
+			REGAMMA_CNTLA_EXP_REGION12_NUM_SEGMENTS);
+
+		set_reg_field_value(
+			value,
+			curve[1].offset,
+			REGAMMA_CNTLA_REGION_12_13,
+			REGAMMA_CNTLA_EXP_REGION13_LUT_OFFSET);
+
+		set_reg_field_value(
+			value,
+			curve[1].segments_num,
+			REGAMMA_CNTLA_REGION_12_13,
+			REGAMMA_CNTLA_EXP_REGION13_NUM_SEGMENTS);
+
+		dm_write_reg(opp110->base.ctx,
+			DCP_REG(mmREGAMMA_CNTLA_REGION_12_13),
+			value);
+	}
+
+	curve += 2;
+	{
+		value = 0;
+		set_reg_field_value(
+			value,
+			curve[0].offset,
+			REGAMMA_CNTLA_REGION_14_15,
+			REGAMMA_CNTLA_EXP_REGION14_LUT_OFFSET);
+
+		set_reg_field_value(
+			value,
+			curve[0].segments_num,
+			REGAMMA_CNTLA_REGION_14_15,
+			REGAMMA_CNTLA_EXP_REGION14_NUM_SEGMENTS);
+
+		set_reg_field_value(
+			value,
+			curve[1].offset,
+			REGAMMA_CNTLA_REGION_14_15,
+			REGAMMA_CNTLA_EXP_REGION15_LUT_OFFSET);
+
+		set_reg_field_value(
+			value,
+			curve[1].segments_num,
+			REGAMMA_CNTLA_REGION_14_15,
+			REGAMMA_CNTLA_EXP_REGION15_NUM_SEGMENTS);
+
+		dm_write_reg(opp110->base.ctx,
+			DCP_REG(mmREGAMMA_CNTLA_REGION_14_15),
+			value);
+	}
+}
+
+static void program_pwl(
+	struct dce110_opp *opp110,
+	const struct gamma_parameters *params)
+{
+	uint32_t value;
+
+	{
+		uint8_t max_tries = 10;
+		uint8_t counter = 0;
+
+		/* Power on LUT memory */
+		value = dm_read_reg(opp110->base.ctx,
+				DCFE_REG(mmDCFE_MEM_PWR_CTRL));
+
+		set_reg_field_value(
+			value,
+			1,
+			DCFE_MEM_PWR_CTRL,
+			DCP_REGAMMA_MEM_PWR_DIS);
+
+		dm_write_reg(opp110->base.ctx,
+				DCFE_REG(mmDCFE_MEM_PWR_CTRL), value);
+
+		while (counter < max_tries) {
+			value =
+				dm_read_reg(
+					opp110->base.ctx,
+					DCFE_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(opp110->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__);
+		}
+	}
+
+	value = 0;
+
+	set_reg_field_value(
+		value,
+		7,
+		REGAMMA_LUT_WRITE_EN_MASK,
+		REGAMMA_LUT_WRITE_EN_MASK);
+
+	dm_write_reg(opp110->base.ctx,
+		DCP_REG(mmREGAMMA_LUT_WRITE_EN_MASK), value);
+	dm_write_reg(opp110->base.ctx,
+		DCP_REG(mmREGAMMA_LUT_INDEX), 0);
+
+	/* Program REGAMMA_LUT_DATA */
+	{
+		const uint32_t addr = DCP_REG(mmREGAMMA_LUT_DATA);
+
+		uint32_t i = 0;
+
+		struct pwl_result_data *rgb =
+				opp110->regamma.rgb_resulted;
+
+		while (i != opp110->regamma.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);
+
+			dm_write_reg(opp110->base.ctx, addr,
+				rgb->delta_red_reg);
+			dm_write_reg(opp110->base.ctx, addr,
+				rgb->delta_green_reg);
+			dm_write_reg(opp110->base.ctx, addr,
+				rgb->delta_blue_reg);
+
+			++rgb;
+			++i;
+		}
+	}
+
+	/*  we are done with DCP LUT memory; re-enable low power mode */
+	value = dm_read_reg(opp110->base.ctx, DCFE_REG(mmDCFE_MEM_PWR_CTRL));
+
+	set_reg_field_value(
+		value,
+		0,
+		DCFE_MEM_PWR_CTRL,
+		DCP_REGAMMA_MEM_PWR_DIS);
+
+	dm_write_reg(opp110->base.ctx, DCFE_REG(mmDCFE_MEM_PWR_CTRL), value);
+}
+
+void dce110_opp_power_on_regamma_lut(
+	struct output_pixel_processor *opp,
+	bool power_on)
+{
+	struct dce110_opp *opp110 = TO_DCE110_OPP(opp);
+
+	uint32_t value =
+		dm_read_reg(opp->ctx, DCFE_REG(mmDCFE_MEM_PWR_CTRL));
+
+	set_reg_field_value(
+		value,
+		power_on,
+		DCFE_MEM_PWR_CTRL,
+		DCP_REGAMMA_MEM_PWR_DIS);
+
+	set_reg_field_value(
+		value,
+		power_on,
+		DCFE_MEM_PWR_CTRL,
+		DCP_LUT_MEM_PWR_DIS);
+
+	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;
+}
-- 
2.1.4

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

  parent reply	other threads:[~2016-02-11 17:20 UTC|newest]

Thread overview: 87+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2016-02-11 17:19 [PATCH 00/29] Enabling new DAL display driver for amdgpu on Carrizo and Tonga Harry Wentland
2016-02-11 17:19 ` [PATCH 01/29] drm/amd/dal: Add dal headers Harry Wentland
2016-02-11 17:19 ` [PATCH 02/29] drm/amd/dal: Add DAL Basic Types and Logger Harry Wentland
2016-02-11 17:19 ` [PATCH 03/29] drm/amd/dal: Fixed point arithmetic Harry Wentland
2016-02-11 17:19 ` [PATCH 04/29] drm/amd/dal: Asic Capabilities Harry Wentland
2016-02-11 17:19 ` [PATCH 05/29] drm/amd/dal: GPIO (General Purpose IO) Harry Wentland
2016-02-11 17:19 ` [PATCH 06/29] drm/amd/dal: Adapter Service Harry Wentland
2016-02-12  0:26   ` Dave Airlie
2016-02-12 14:30     ` Wentland, Harry
2016-02-11 17:19 ` [PATCH 07/29] drm/amd/dal: BIOS Parser Harry Wentland
2016-02-11 17:19 ` [PATCH 08/29] drm/amd/dal: I2C Aux Manager Harry Wentland
2016-02-11 20:19   ` Rob Clark
2016-02-11 20:52     ` Daniel Vetter
2016-02-17  3:23     ` Harry Wentland
2016-02-11 17:19 ` [PATCH 09/29] drm/amd/dal: IRQ Service Harry Wentland
2016-02-11 17:19 ` [PATCH 10/29] drm/amd/dal: GPU Harry Wentland
2016-02-11 17:19 ` [PATCH 11/29] drm/amd/dal: Audio Harry Wentland
2016-02-11 17:19 ` [PATCH 12/29] drm/amd/dal: Bandwidth calculations Harry Wentland
2016-02-11 17:19 ` [PATCH 13/29] drm/amd/dal: Add encoder HW programming Harry Wentland
2016-02-11 17:19 ` [PATCH 14/29] drm/amd/dal: Add clock source " Harry Wentland
2016-02-11 17:19 ` [PATCH 15/29] drm/amd/dal: Add timing generator " Harry Wentland
2016-02-11 17:19 ` [PATCH 16/29] drm/amd/dal: Add surface " Harry Wentland
2016-02-11 17:19 ` [PATCH 17/29] drm/amd/dal: Add framebuffer compression " Harry Wentland
2016-02-11 17:19 ` [PATCH 18/29] drm/amd/dal: Add input pixel processing " Harry Wentland
2016-02-11 17:19 ` Harry Wentland [this message]
2016-02-11 17:20 ` [PATCH 20/29] drm/amd/dal: Add transform & scaler " Harry Wentland
2016-02-11 17:20 ` [PATCH 21/29] drm/amd/dal: Add Carrizo HW sequencer and resource Harry Wentland
2016-02-11 17:20 ` [PATCH 22/29] drm/amd/dal: Add Tonga/Fiji " Harry Wentland
2016-02-11 17:20 ` [PATCH 23/29] drm/amd/dal: Add empty encoder programming for virtual HW Harry Wentland
2016-02-11 17:20 ` [PATCH 24/29] drm/amd/dal: Add display core Harry Wentland
2016-02-11 17:20 ` [PATCH 25/29] drm/amd/dal: Adding amdgpu_dm for dal Harry Wentland
2016-02-11 17:20 ` [PATCH 26/29] drm/amdgpu: Use dal driver for Carrizo, Tonga, and Fiji Harry Wentland
2016-02-11 17:20 ` [PATCH 27/29] drm/amd/dal: Correctly interpret rotation as bit set Harry Wentland
2016-02-11 21:00   ` Oded Gabbay
2016-02-16 16:46     ` Harry Wentland
2016-02-11 17:20 ` [PATCH 28/29] drm/amd/dal: fix flip clean-up state Harry Wentland
2016-02-11 17:20 ` [PATCH 29/29] drm/amd/dal: Force bw programming for DCE 10 until we start calculate BW Harry Wentland
2016-02-11 20:02 ` [PATCH 00/29] Enabling new DAL display driver for amdgpu on Carrizo and Tonga Mike Lothian
2016-02-11 20:05   ` Wentland, Harry
2016-02-11 20:52 ` Dave Airlie
2016-02-11 21:06   ` Daniel Vetter
2016-02-12  0:57     ` Dave Airlie
2016-02-12  5:34     ` Daniel Vetter
2016-02-13  0:05       ` Wentland, Harry
2016-02-14 11:22         ` Jerome Glisse
2016-02-14 13:23           ` Daniel Vetter
2016-02-17  3:28           ` Harry Wentland
2016-02-14 13:32         ` Rob Clark
2016-02-14 13:51           ` Daniel Vetter
2016-02-17  3:26           ` Harry Wentland
2016-02-14 14:01         ` Daniel Vetter
2016-02-17  3:32           ` Harry Wentland
2016-02-14 21:44         ` Daniel Stone
2016-02-16 22:27 ` [PATCH v2 00/26] " Harry Wentland
2016-02-16 22:27   ` [PATCH v2 01/26] drm/amd/dal: Add dal headers Harry Wentland
2016-02-16 22:27   ` [PATCH v2 02/26] drm/amd/dal: Add DAL Basic Types and Logger Harry Wentland
2016-02-16 22:27   ` [PATCH v2 03/26] drm/amd/dal: Fixed point arithmetic Harry Wentland
2016-02-16 22:27   ` [PATCH v2 04/26] drm/amd/dal: Asic Capabilities Harry Wentland
2016-02-16 22:27   ` [PATCH v2 05/26] drm/amd/dal: GPIO (General Purpose IO) Harry Wentland
2016-02-16 22:27   ` [PATCH v2 06/26] drm/amd/dal: Adapter Service Harry Wentland
2016-02-16 22:27   ` [PATCH v2 07/26] drm/amd/dal: BIOS Parser Harry Wentland
2016-02-16 22:27   ` [PATCH v2 08/26] drm/amd/dal: I2C Aux Manager Harry Wentland
2016-02-16 22:27   ` [PATCH v2 09/26] drm/amd/dal: IRQ Service Harry Wentland
2016-02-16 22:27   ` [PATCH v2 10/26] drm/amd/dal: GPU Harry Wentland
2016-02-16 22:27   ` [PATCH v2 11/26] drm/amd/dal: Audio Harry Wentland
2016-02-16 22:27   ` [PATCH v2 12/26] drm/amd/dal: Bandwidth calculations Harry Wentland
2016-02-16 22:27   ` [PATCH v2 13/26] drm/amd/dal: Add encoder HW programming Harry Wentland
2016-02-16 22:27   ` [PATCH v2 14/26] drm/amd/dal: Add clock source " Harry Wentland
2016-02-16 22:27   ` [PATCH v2 15/26] drm/amd/dal: Add timing generator " Harry Wentland
2016-02-16 22:27   ` [PATCH v2 16/26] drm/amd/dal: Add surface " Harry Wentland
2016-02-16 22:27   ` [PATCH v2 17/26] drm/amd/dal: Add framebuffer compression " Harry Wentland
2016-02-16 22:27   ` [PATCH v2 18/26] drm/amd/dal: Add input pixel processing " Harry Wentland
2016-02-16 22:27   ` [PATCH v2 19/26] drm/amd/dal: Add output " Harry Wentland
2016-02-16 22:28   ` [PATCH v2 20/26] drm/amd/dal: Add transform & scaler " Harry Wentland
2016-02-16 22:28   ` [PATCH v2 21/26] drm/amd/dal: Add Carrizo HW sequencer and resource Harry Wentland
2016-02-16 22:28   ` [PATCH v2 22/26] drm/amd/dal: Add Tonga/Fiji " Harry Wentland
2016-02-16 22:28   ` [PATCH v2 23/26] drm/amd/dal: Add empty encoder programming for virtual HW Harry Wentland
2016-02-16 22:28   ` [PATCH v2 24/26] drm/amd/dal: Add display core Harry Wentland
2016-02-16 22:28   ` [PATCH v2 25/26] drm/amd/dal: Adding amdgpu_dm for dal Harry Wentland
2016-02-16 22:28   ` [PATCH v2 26/26] drm/amdgpu: Use dal driver for Carrizo, Tonga, and Fiji Harry Wentland
2016-02-29 21:56 ` [PATCH v3 00/26] Enabling new DAL display driver for amdgpu on Carrizo and Tonga Harry Wentland
2016-02-29 21:56   ` [PATCH v3 01/26] drm/amd/dal: Add dal headers Harry Wentland
2016-02-29 21:56   ` [PATCH v3 05/26] drm/amd/dal: GPIO (General Purpose IO) Harry Wentland
2016-02-29 21:56   ` [PATCH v3 07/26] drm/amd/dal: BIOS Parser Harry Wentland
2016-02-29 21:56   ` [PATCH v3 24/26] drm/amd/dal: Add display core Harry Wentland
2016-02-29 21:56   ` [PATCH v3 25/26] drm/amd/dal: Adding amdgpu_dm for dal Harry Wentland
2016-02-29 21:56   ` [PATCH v3 26/26] drm/amdgpu: Use dal driver for Carrizo, Tonga, and Fiji Harry Wentland

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1455211209-26733-20-git-send-email-harry.wentland@amd.com \
    --to=harry.wentland@amd.com \
    --cc=dri-devel@lists.freedesktop.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.