Blob Blame History Raw
From: Aric Cyr <aric.cyr@amd.com>
Date: Tue, 20 Dec 2016 20:24:24 -0500
Subject: drm/amd/display: Implement gamma correction using input LUT
Git-commit: d7194cf6b8ddf0344e70834397d0b1af2cc5fe05
Patch-mainline: v4.15-rc1
References: FATE#326289 FATE#326079 FATE#326049 FATE#322398 FATE#326166

The dc_gamma in dc_surface will be programmed to the input
LUT if provided.  If dc_gamma is not provided in dc_surface
regamma may be used to emulate gamma.

Some refactor and cleanup included as well.

Signed-off-by: Aric Cyr <aric.cyr@amd.com>
Reviewed-by: Tony Cheng <Tony.Cheng@amd.com>
Acked-by: Harry Wentland <Harry.Wentland@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
Acked-by: Petr Tesarik <ptesarik@suse.com>
---
 drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c      |   17 
 drivers/gpu/drm/amd/display/dc/calcs/gamma_calcs.c           |   29 -
 drivers/gpu/drm/amd/display/dc/dc.h                          |   36 -
 drivers/gpu/drm/amd/display/dc/dc_hw_types.h                 |   10 
 drivers/gpu/drm/amd/display/dc/dce/dce_opp.c                 |    2 
 drivers/gpu/drm/amd/display/dc/dce/dce_opp.h                 |    4 
 drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c  |   17 
 drivers/gpu/drm/amd/display/dc/dce110/dce110_ipp.c           |    1 
 drivers/gpu/drm/amd/display/dc/dce110/dce110_ipp.h           |   11 
 drivers/gpu/drm/amd/display/dc/dce110/dce110_ipp_gamma.c     |  306 ++---------
 drivers/gpu/drm/amd/display/dc/dce110/dce110_opp_regamma_v.c |    1 
 drivers/gpu/drm/amd/display/dc/dce110/dce110_opp_v.c         |    2 
 drivers/gpu/drm/amd/display/dc/dce110/dce110_opp_v.h         |    4 
 drivers/gpu/drm/amd/display/dc/dce80/dce80_ipp.c             |    1 
 drivers/gpu/drm/amd/display/dc/dce80/dce80_ipp.h             |    2 
 drivers/gpu/drm/amd/display/dc/dce80/dce80_ipp_gamma.c       |    5 
 drivers/gpu/drm/amd/display/dc/inc/gamma_types.h             |   38 -
 drivers/gpu/drm/amd/display/dc/inc/hw/ipp.h                  |    4 
 drivers/gpu/drm/amd/display/dc/inc/hw/opp.h                  |    1 
 drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h            |    2 
 drivers/gpu/drm/amd/display/modules/color/color.c            |    6 
 21 files changed, 139 insertions(+), 360 deletions(-)

--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c
@@ -521,14 +521,11 @@ static void fill_gamma_from_crtc(
 		return;
 
 	for (i = 0; i < NUM_OF_RAW_GAMMA_RAMP_RGB_256; i++) {
-		gamma->gamma_ramp_rgb256x3x16.red[i] = lut[i].red;
-		gamma->gamma_ramp_rgb256x3x16.green[i] = lut[i].green;
-		gamma->gamma_ramp_rgb256x3x16.blue[i] = lut[i].blue;
+		gamma->red[i] = lut[i].red;
+		gamma->green[i] = lut[i].green;
+		gamma->blue[i] = lut[i].blue;
 	}
 
-	gamma->type = GAMMA_RAMP_RBG256X3X16;
-	gamma->size = sizeof(gamma->gamma_ramp_rgb256x3x16);
-
 	dc_surface->gamma_correction = gamma;
 
 	input_tf = dc_create_transfer_func();
@@ -822,6 +819,12 @@ static void fill_stream_properties_from_
 
 	stream->output_color_space = get_output_color_space(timing_out);
 
+	{
+		struct dc_transfer_func *tf = dc_create_transfer_func();
+		tf->type = TF_TYPE_PREDEFINED;
+		tf->tf = TRANSFER_FUNCTION_SRGB;
+		stream->out_transfer_func = tf;
+	}
 }
 
 static void fill_audio_info(
@@ -3066,7 +3069,7 @@ static bool is_dp_capable_without_timing
 	    dc_read_dpcd(dc, amdgpu_connector->dc_link->link_index,
 			 DP_DOWN_STREAM_PORT_COUNT,
 			 &dpcd_data, sizeof(dpcd_data)) )
-		capable = dpcd_data & DP_MSA_TIMING_PAR_IGNORED? true:false;
+		capable = (dpcd_data & DP_MSA_TIMING_PAR_IGNORED) ? true:false;
 
 	return capable;
 }
--- a/drivers/gpu/drm/amd/display/dc/calcs/gamma_calcs.c
+++ b/drivers/gpu/drm/amd/display/dc/calcs/gamma_calcs.c
@@ -573,7 +573,7 @@ static bool find_software_points(
 	uint32_t *index_right,
 	enum hw_point_position *pos)
 {
-	const uint32_t max_number = RGB_256X3X16 + 3;
+	const uint32_t max_number = INPUT_LUT_ENTRIES + 3;
 
 	struct fixed31_32 left, right;
 
@@ -686,12 +686,12 @@ static bool build_custom_gamma_mapping_c
 			return false;
 		}
 
-		if (index_left >= RGB_256X3X16 + 3) {
+		if (index_left >= INPUT_LUT_ENTRIES + 3) {
 			BREAK_TO_DEBUGGER();
 			return false;
 		}
 
-		if (index_right >= RGB_256X3X16 + 3) {
+		if (index_right >= INPUT_LUT_ENTRIES + 3) {
 			BREAK_TO_DEBUGGER();
 			return false;
 		}
@@ -958,20 +958,13 @@ static bool scale_gamma(struct pwl_float
 		const struct core_gamma *ramp,
 		struct dividers dividers)
 {
-	const struct dc_gamma_ramp_rgb256x3x16 *gamma;
+	const struct dc_gamma *gamma = &ramp->public;
 	const uint16_t max_driver = 0xFFFF;
 	const uint16_t max_os = 0xFF00;
 	uint16_t scaler = max_os;
-	uint32_t i;
+	uint32_t i = 0;
 	struct pwl_float_data *rgb = pwl_rgb;
-	struct pwl_float_data *rgb_last = rgb + RGB_256X3X16 - 1;
-
-	if (ramp->public.type == GAMMA_RAMP_RBG256X3X16)
-		gamma = &ramp->public.gamma_ramp_rgb256x3x16;
-	else
-		return false; /* invalid option */
-
-	i = 0;
+	struct pwl_float_data *rgb_last = rgb + INPUT_LUT_ENTRIES - 1;
 
 	do {
 		if ((gamma->red[i] > max_os) ||
@@ -981,7 +974,7 @@ static bool scale_gamma(struct pwl_float
 			break;
 		}
 		++i;
-	} while (i != RGB_256X3X16);
+	} while (i != INPUT_LUT_ENTRIES);
 
 	i = 0;
 
@@ -995,7 +988,7 @@ static bool scale_gamma(struct pwl_float
 
 		++rgb;
 		++i;
-	} while (i != RGB_256X3X16);
+	} while (i != INPUT_LUT_ENTRIES);
 
 	rgb->r = dal_fixed31_32_mul(rgb_last->r,
 			dividers.divider1);
@@ -1110,7 +1103,7 @@ static bool calculate_interpolated_hardw
 		return false;
 
 	coeff = coeff128;
-	max_entries += RGB_256X3X16;
+	max_entries += INPUT_LUT_ENTRIES;
 
 	/* TODO: float point case */
 
@@ -1440,13 +1433,13 @@ bool calculate_regamma_params(struct pwl
 	coordinates_x = dm_alloc(sizeof(*coordinates_x)*(256 + 3));
 	if (!coordinates_x)
 		goto coordinates_x_alloc_fail;
-	rgb_user = dm_alloc(sizeof(*rgb_user) * (FLOAT_GAMMA_RAMP_MAX + 3));
+	rgb_user = dm_alloc(sizeof(*rgb_user) * (TRANSFER_FUNC_POINTS + 3));
 	if (!rgb_user)
 		goto rgb_user_alloc_fail;
 	rgb_regamma = dm_alloc(sizeof(*rgb_regamma) * (256 + 3));
 	if (!rgb_regamma)
 		goto rgb_regamma_alloc_fail;
-	rgb_oem = dm_alloc(sizeof(*rgb_oem) * (FLOAT_GAMMA_RAMP_MAX + 3));
+	rgb_oem = dm_alloc(sizeof(*rgb_oem) * (TRANSFER_FUNC_POINTS + 3));
 	if (!rgb_oem)
 		goto rgb_oem_alloc_fail;
 	axix_x_256 = dm_alloc(sizeof(*axix_x_256) * (256 + 3));
--- a/drivers/gpu/drm/amd/display/dc/dc.h
+++ b/drivers/gpu/drm/amd/display/dc/dc.h
@@ -183,43 +183,9 @@ void dc_destroy(struct dc **dc);
  ******************************************************************************/
 
 enum {
-	RGB_256X3X16 = 256,
-	FLOAT_GAMMA_RAMP_MAX = 1025,
 	TRANSFER_FUNC_POINTS = 1025
 };
 
-enum dc_gamma_ramp_type {
-	GAMMA_RAMP_RBG256X3X16,
-	GAMMA_RAMP_FLOAT,
-};
-
-struct float_rgb {
-	struct fixed32_32 red;
-	struct fixed32_32 green;
-	struct fixed32_32 blue;
-};
-
-struct dc_gamma_ramp_float {
-	struct float_rgb scale;
-	struct float_rgb offset;
-	struct float_rgb gamma_curve[FLOAT_GAMMA_RAMP_MAX];
-};
-
-struct dc_gamma_ramp_rgb256x3x16 {
-	uint16_t red[RGB_256X3X16];
-	uint16_t green[RGB_256X3X16];
-	uint16_t blue[RGB_256X3X16];
-};
-
-struct dc_gamma {
-	enum dc_gamma_ramp_type type;
-	union {
-		struct dc_gamma_ramp_rgb256x3x16 gamma_ramp_rgb256x3x16;
-		struct dc_gamma_ramp_float gamma_ramp_float;
-	};
-	uint32_t size;
-};
-
 enum dc_transfer_func_type {
 	TF_TYPE_PREDEFINED,
 	TF_TYPE_DISTRIBUTED_POINTS,
@@ -266,9 +232,7 @@ struct dc_surface {
 	bool horizontal_mirror;
 	enum plane_stereo_format stereo_format;
 
-	/* TO BE REMOVED AFTER BELOW TRANSFER FUNCTIONS IMPLEMENTED */
 	const struct dc_gamma *gamma_correction;
-
 	const struct dc_transfer_func *in_transfer_func;
 };
 
--- a/drivers/gpu/drm/amd/display/dc/dc_hw_types.h
+++ b/drivers/gpu/drm/amd/display/dc/dc_hw_types.h
@@ -370,6 +370,16 @@ struct dc_cursor_mi_param {
 
 /* IPP related types */
 
+enum {
+	INPUT_LUT_ENTRIES = 256
+};
+
+struct dc_gamma {
+	uint16_t red[INPUT_LUT_ENTRIES];
+	uint16_t green[INPUT_LUT_ENTRIES];
+	uint16_t blue[INPUT_LUT_ENTRIES];
+};
+
 /* Used by both ipp amd opp functions*/
 /* TODO: to be consolidated with enum color_space */
 
--- a/drivers/gpu/drm/amd/display/dc/dce/dce_opp.c
+++ b/drivers/gpu/drm/amd/display/dc/dce/dce_opp.c
@@ -28,8 +28,6 @@
 
 #include "dce_opp.h"
 
-#include "gamma_types.h"
-
 #include "reg_helper.h"
 
 #define REG(reg)\
--- a/drivers/gpu/drm/amd/display/dc/dce/dce_opp.h
+++ b/drivers/gpu/drm/amd/display/dc/dce/dce_opp.h
@@ -29,10 +29,6 @@
 #include "opp.h"
 #include "core_types.h"
 
-#include "gamma_types.h" /* decprecated */
-
-struct gamma_parameters;
-
 #define FROM_DCE11_OPP(opp)\
 	container_of(opp, struct dce110_opp, base)
 
--- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c
+++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c
@@ -228,10 +228,11 @@ static void build_prescale_params(struct
 		break;
 	default:
 		ASSERT(false);
+		break;
 	}
 }
 
-static bool dce110_set_degamma(
+static bool dce110_set_input_transfer_func(
 	struct pipe_ctx *pipe_ctx,
 	const struct core_surface *surface)
 {
@@ -249,6 +250,9 @@ static bool dce110_set_degamma(
 	build_prescale_params(&prescale_params, surface);
 	ipp->funcs->ipp_program_prescale(ipp, &prescale_params);
 
+	if (surface->public.gamma_correction)
+	    ipp->funcs->ipp_program_input_lut(ipp, surface->public.gamma_correction);
+
 	if (tf == NULL) {
 		/* Default case if no input transfer function specified */
 		ipp->funcs->ipp_set_degamma(ipp,
@@ -272,6 +276,7 @@ static bool dce110_set_degamma(
 			break;
 		default:
 			result = false;
+			break;
 		}
 	} else {
 		/*TF_TYPE_DISTRIBUTED_POINTS - Not supported in DCE 11*/
@@ -303,8 +308,11 @@ static bool dce110_set_output_transfer_f
 
 	opp->funcs->opp_power_on_regamma_lut(opp, true);
 
-	if (ramp && calculate_regamma_params(
-				regamma_params, ramp, surface, stream)) {
+	if (stream->public.out_transfer_func &&
+	    stream->public.out_transfer_func->type == TF_TYPE_PREDEFINED &&
+	    stream->public.out_transfer_func->tf == TRANSFER_FUNCTION_SRGB) {
+		opp->funcs->opp_set_regamma_mode(opp, OPP_REGAMMA_SRGB);
+	} else if (ramp && calculate_regamma_params(regamma_params, ramp, surface, stream)) {
 		opp->funcs->opp_program_regamma_pwl(opp, regamma_params);
 		opp->funcs->opp_set_regamma_mode(opp, OPP_REGAMMA_USER);
 	} else {
@@ -1318,7 +1326,6 @@ enum dc_status dce110_apply_ctx_to_hw(
 			* instead of per pipe.
 			*/
 			struct audio_output audio_output;
-			struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i];
 
 			build_audio_output(pipe_ctx, &audio_output);
 
@@ -1945,7 +1952,7 @@ static const struct hw_sequencer_funcs d
 	.set_plane_config = set_plane_config,
 	.update_plane_addr = update_plane_addr,
 	.update_pending_status = dce110_update_pending_status,
-	.set_input_transfer_func = dce110_set_degamma,
+	.set_input_transfer_func = dce110_set_input_transfer_func,
 	.set_output_transfer_func = dce110_set_output_transfer_func,
 	.power_down = dce110_power_down,
 	.enable_accelerated_mode = dce110_enable_accelerated_mode,
--- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_ipp.c
+++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_ipp.c
@@ -35,6 +35,7 @@ static const struct ipp_funcs funcs = {
 		.ipp_cursor_set_attributes = dce110_ipp_cursor_set_attributes,
 		.ipp_cursor_set_position = dce110_ipp_cursor_set_position,
 		.ipp_program_prescale = dce110_ipp_program_prescale,
+		.ipp_program_input_lut = dce110_ipp_program_input_lut,
 		.ipp_set_degamma = dce110_ipp_set_degamma,
 };
 
--- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_ipp.h
+++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_ipp.h
@@ -28,9 +28,6 @@
 
 #include "ipp.h"
 
-struct gamma_parameters;
-struct dev_c_lut;
-
 #define TO_DCE110_IPP(input_pixel_processor)\
 	container_of(input_pixel_processor, struct dce110_ipp, base)
 
@@ -69,9 +66,9 @@ bool dce110_ipp_set_degamma(
 void dce110_ipp_program_prescale(
 	struct input_pixel_processor *ipp,
 	struct ipp_prescale_params *params);
-/*
- * Helper functions to be resused in other ASICs
- */
-void dce110_helper_select_lut(struct dce110_ipp *ipp110);
+
+void dce110_ipp_program_input_lut(
+	struct input_pixel_processor *ipp,
+	const struct dc_gamma *gamma);
 
 #endif /*__DC_IPP_DCE110_H__*/
--- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_ipp_gamma.c
+++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_ipp_gamma.c
@@ -32,21 +32,39 @@
 #include "dce/dce_11_0_sh_mask.h"
 
 #include "dce110_ipp.h"
-#include "gamma_types.h"
 
 #define DCP_REG(reg)\
-	(reg + ipp110->offsets.dcp_offset)
+	(mm##reg + ipp110->offsets.dcp_offset)
+
+#define DCP_REG_SET_N(reg_name, n, ...)	\
+	generic_reg_update_ex(ipp110->base.ctx, \
+			DCP_REG(reg_name), \
+			0, n, __VA_ARGS__)
+
+#define DCP_REG_SET(reg, field1, val1) \
+		DCP_REG_SET_N(reg, 1, FD(reg##__##field1), val1)
+
+#define DCP_REG_SET_2(reg, field1, val1, field2, val2) \
+		DCP_REG_SET_N(reg, 2, \
+			FD(reg##__##field1), val1, \
+			FD(reg##__##field2), val2)
+
+#define DCP_REG_SET_3(reg, field1, val1, field2, val2, field3, val3) \
+		DCP_REG_SET_N(reg, 3, \
+			FD(reg##__##field1), val1, \
+			FD(reg##__##field2), val2, \
+			FD(reg##__##field3), val3)
+
+#define DCP_REG_UPDATE_N(reg_name, n, ...)	\
+	generic_reg_update_ex(ipp110->base.ctx, \
+			DCP_REG(reg_name), \
+			dm_read_reg(ipp110->base.ctx, DCP_REG(reg_name)), \
+			n, __VA_ARGS__)
+
+#define DCP_REG_UPDATE(reg, field, val)	\
+		DCP_REG_UPDATE_N(reg, 1, FD(reg##__##field), val)
+
 
-enum {
-	MAX_INPUT_LUT_ENTRY = 256
-};
-
-/*PROTOTYPE DECLARATIONS*/
-static void set_lut_inc(
-	struct dce110_ipp *ipp110,
-	uint8_t inc,
-	bool is_float,
-	bool is_signed);
 
 bool dce110_ipp_set_degamma(
 	struct input_pixel_processor *ipp,
@@ -61,25 +79,11 @@ bool dce110_ipp_set_degamma(
 	ASSERT(mode == IPP_DEGAMMA_MODE_BYPASS ||
 			mode == IPP_DEGAMMA_MODE_HW_sRGB);
 
-	set_reg_field_value(
-		value,
-		degamma_type,
-		DEGAMMA_CONTROL,
-		GRPH_DEGAMMA_MODE);
-
-	set_reg_field_value(
-		value,
-		degamma_type,
-		DEGAMMA_CONTROL,
-		CURSOR_DEGAMMA_MODE);
-
-	set_reg_field_value(
-		value,
-		degamma_type,
+	DCP_REG_SET_3(
 		DEGAMMA_CONTROL,
-		CURSOR2_DEGAMMA_MODE);
-
-	dm_write_reg(ipp110->base.ctx, DCP_REG(mmDEGAMMA_CONTROL), value);
+		GRPH_DEGAMMA_MODE, degamma_type,
+		CURSOR_DEGAMMA_MODE, degamma_type,
+		CURSOR2_DEGAMMA_MODE, degamma_type);
 
 	return true;
 }
@@ -90,214 +94,70 @@ void dce110_ipp_program_prescale(
 {
 	struct dce110_ipp *ipp110 = TO_DCE110_IPP(ipp);
 
-	uint32_t prescale_control = 0;
-	uint32_t prescale_value = 0;
-	uint32_t legacy_lut_control = 0;
-
-	prescale_control = dm_read_reg(ipp110->base.ctx,
-			DCP_REG(mmPRESCALE_GRPH_CONTROL));
+	/* set to bypass mode first before change */
+	DCP_REG_UPDATE(PRESCALE_GRPH_CONTROL,
+		GRPH_PRESCALE_BYPASS, 1);
+
+	DCP_REG_SET_2(PRESCALE_VALUES_GRPH_R,
+		GRPH_PRESCALE_SCALE_R, params->scale,
+		GRPH_PRESCALE_BIAS_R, params->bias);
+
+	DCP_REG_SET_2(PRESCALE_VALUES_GRPH_G,
+		GRPH_PRESCALE_SCALE_G, params->scale,
+		GRPH_PRESCALE_BIAS_G, params->bias);
+
+	DCP_REG_SET_2(PRESCALE_VALUES_GRPH_B,
+		GRPH_PRESCALE_SCALE_B, params->scale,
+		GRPH_PRESCALE_BIAS_B, params->bias);
 
 	if (params->mode != IPP_PRESCALE_MODE_BYPASS) {
-
-		set_reg_field_value(
-			prescale_control,
-			0,
-			PRESCALE_GRPH_CONTROL,
-			GRPH_PRESCALE_BYPASS);
-
-		/*
-		 * If prescale is in use, then legacy lut should
-		 * be bypassed
-		 */
-		legacy_lut_control = dm_read_reg(ipp110->base.ctx,
-			DCP_REG(mmINPUT_GAMMA_CONTROL));
-
-		set_reg_field_value(
-			legacy_lut_control,
-			1,
-			INPUT_GAMMA_CONTROL,
-			GRPH_INPUT_GAMMA_MODE);
-
-		dm_write_reg(ipp110->base.ctx,
-			DCP_REG(mmINPUT_GAMMA_CONTROL),
-			legacy_lut_control);
-	} else {
-		set_reg_field_value(
-			prescale_control,
-			1,
-			PRESCALE_GRPH_CONTROL,
-			GRPH_PRESCALE_BYPASS);
+		/* If prescale is in use, then legacy lut should be bypassed */
+		DCP_REG_UPDATE(PRESCALE_GRPH_CONTROL, GRPH_PRESCALE_BYPASS, 0);
+		DCP_REG_UPDATE(INPUT_GAMMA_CONTROL, GRPH_INPUT_GAMMA_MODE, 1);
 	}
-
-	set_reg_field_value(
-		prescale_value,
-		params->scale,
-		PRESCALE_VALUES_GRPH_R,
-		GRPH_PRESCALE_SCALE_R);
-
-	set_reg_field_value(
-		prescale_value,
-		params->bias,
-		PRESCALE_VALUES_GRPH_R,
-		GRPH_PRESCALE_BIAS_R);
-
-	dm_write_reg(ipp110->base.ctx,
-		DCP_REG(mmPRESCALE_GRPH_CONTROL),
-		prescale_control);
-
-	dm_write_reg(ipp110->base.ctx,
-		DCP_REG(mmPRESCALE_VALUES_GRPH_R),
-		prescale_value);
-
-	dm_write_reg(ipp110->base.ctx,
-		DCP_REG(mmPRESCALE_VALUES_GRPH_G),
-		prescale_value);
-
-	dm_write_reg(ipp110->base.ctx,
-		DCP_REG(mmPRESCALE_VALUES_GRPH_B),
-		prescale_value);
 }
 
-static void set_lut_inc(
-	struct dce110_ipp *ipp110,
-	uint8_t inc,
-	bool is_float,
-	bool is_signed)
+static void dce110_helper_select_lut(struct dce110_ipp *ipp110)
 {
-	const uint32_t addr = DCP_REG(mmDC_LUT_CONTROL);
+	/* enable all */
+	DCP_REG_SET(DC_LUT_WRITE_EN_MASK, DC_LUT_WRITE_EN_MASK, 0x7);
 
-	uint32_t value = dm_read_reg(ipp110->base.ctx, addr);
+	/* 256 entry mode */
+	DCP_REG_UPDATE(DC_LUT_RW_MODE, DC_LUT_RW_MODE, 0);
 
-	set_reg_field_value(
-		value,
-		inc,
-		DC_LUT_CONTROL,
-		DC_LUT_INC_R);
-
-	set_reg_field_value(
-		value,
-		inc,
-		DC_LUT_CONTROL,
-		DC_LUT_INC_G);
-
-	set_reg_field_value(
-		value,
-		inc,
-		DC_LUT_CONTROL,
-		DC_LUT_INC_B);
-
-	set_reg_field_value(
-		value,
-		is_float,
-		DC_LUT_CONTROL,
-		DC_LUT_DATA_R_FLOAT_POINT_EN);
-
-	set_reg_field_value(
-		value,
-		is_float,
-		DC_LUT_CONTROL,
-		DC_LUT_DATA_G_FLOAT_POINT_EN);
-
-	set_reg_field_value(
-		value,
-		is_float,
-		DC_LUT_CONTROL,
-		DC_LUT_DATA_B_FLOAT_POINT_EN);
-
-	set_reg_field_value(
-		value,
-		is_signed,
-		DC_LUT_CONTROL,
-		DC_LUT_DATA_R_SIGNED_EN);
-
-	set_reg_field_value(
-		value,
-		is_signed,
-		DC_LUT_CONTROL,
-		DC_LUT_DATA_G_SIGNED_EN);
-
-	set_reg_field_value(
-		value,
-		is_signed,
-		DC_LUT_CONTROL,
-		DC_LUT_DATA_B_SIGNED_EN);
+	/* LUT-256, unsigned, integer, new u0.12 format */
+	DCP_REG_SET_3(DC_LUT_CONTROL,
+		DC_LUT_DATA_R_FORMAT, 3,
+		DC_LUT_DATA_G_FORMAT, 3,
+		DC_LUT_DATA_B_FORMAT, 3);
 
-	dm_write_reg(ipp110->base.ctx, addr, value);
+	/* start from index 0 */
+	DCP_REG_SET(DC_LUT_RW_INDEX, DC_LUT_RW_INDEX, 0);
 }
 
-void dce110_helper_select_lut(struct dce110_ipp *ipp110)
+void dce110_ipp_program_input_lut(
+	struct input_pixel_processor *ipp,
+	const struct dc_gamma *gamma)
 {
-	uint32_t value = 0;
-
-	set_lut_inc(ipp110, 0, false, false);
-
-	{
-		const uint32_t addr = DCP_REG(mmDC_LUT_WRITE_EN_MASK);
-
-		value = dm_read_reg(ipp110->base.ctx, addr);
-
-		/* enable all */
-		set_reg_field_value(
-			value,
-			0x7,
-			DC_LUT_WRITE_EN_MASK,
-			DC_LUT_WRITE_EN_MASK);
-
-		dm_write_reg(ipp110->base.ctx, addr, value);
-	}
-
-	{
-		const uint32_t addr = DCP_REG(mmDC_LUT_RW_MODE);
-
-		value = dm_read_reg(ipp110->base.ctx, addr);
-
-		set_reg_field_value(
-			value,
-			0,
-			DC_LUT_RW_MODE,
-			DC_LUT_RW_MODE);
-
-		dm_write_reg(ipp110->base.ctx, addr, value);
-	}
-
-	{
-		const uint32_t addr = DCP_REG(mmDC_LUT_CONTROL);
-
-		value = dm_read_reg(ipp110->base.ctx, addr);
+	int i;
+	struct dce110_ipp *ipp110 = TO_DCE110_IPP(ipp);
 
-		/* 00 - new u0.12 */
-		set_reg_field_value(
-			value,
-			3,
-			DC_LUT_CONTROL,
-			DC_LUT_DATA_R_FORMAT);
-
-		set_reg_field_value(
-			value,
-			3,
-			DC_LUT_CONTROL,
-			DC_LUT_DATA_G_FORMAT);
-
-		set_reg_field_value(
-			value,
-			3,
-			DC_LUT_CONTROL,
-			DC_LUT_DATA_B_FORMAT);
+	dce110_helper_select_lut(ipp110);
 
-		dm_write_reg(ipp110->base.ctx, addr, value);
+	/* power on LUT memory and give it time to settle */
+	DCP_REG_SET(DCFE_MEM_PWR_CTRL, DCP_LUT_MEM_PWR_DIS, 1);
+	udelay(10);
+
+	for (i = 0; i < INPUT_LUT_ENTRIES; i++) {
+		DCP_REG_SET(DC_LUT_SEQ_COLOR, DC_LUT_SEQ_COLOR, gamma->red[i]);
+		DCP_REG_SET(DC_LUT_SEQ_COLOR, DC_LUT_SEQ_COLOR, gamma->green[i]);
+		DCP_REG_SET(DC_LUT_SEQ_COLOR, DC_LUT_SEQ_COLOR, gamma->blue[i]);
 	}
 
-	{
-		const uint32_t addr = DCP_REG(mmDC_LUT_RW_INDEX);
+	/* power off LUT memory */
+	DCP_REG_SET(DCFE_MEM_PWR_CTRL, DCP_LUT_MEM_PWR_DIS, 0);
 
-		value = dm_read_reg(ipp110->base.ctx, addr);
-
-		set_reg_field_value(
-			value,
-			0,
-			DC_LUT_RW_INDEX,
-			DC_LUT_RW_INDEX);
-
-		dm_write_reg(ipp110->base.ctx, addr, value);
-	}
+	/* bypass prescale, enable legacy LUT */
+	DCP_REG_UPDATE(PRESCALE_GRPH_CONTROL, GRPH_PRESCALE_BYPASS, 1);
+	DCP_REG_UPDATE(INPUT_GAMMA_CONTROL, GRPH_INPUT_GAMMA_MODE, 0);
 }
--- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_opp_regamma_v.c
+++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_opp_regamma_v.c
@@ -30,7 +30,6 @@
 #include "dce/dce_11_0_sh_mask.h"
 
 #include "dce/dce_opp.h"
-#include "gamma_types.h"
 
 static void power_on_lut(struct output_pixel_processor *opp,
 	bool power_on, bool inputgamma, bool regamma)
--- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_opp_v.c
+++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_opp_v.c
@@ -32,8 +32,6 @@
 #include "dce/dce_opp.h"
 #include "dce110_opp_v.h"
 
-#include "gamma_types.h"
-
 /*****************************************/
 /* Constructor, Destructor               */
 /*****************************************/
--- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_opp_v.h
+++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_opp_v.h
@@ -29,10 +29,6 @@
 #include "opp.h"
 #include "core_types.h"
 
-#include "gamma_types.h" /* decprecated */
-
-struct gamma_parameters;
-
 bool dce110_opp_v_construct(struct dce110_opp *opp110,
 	struct dc_context *ctx);
 
--- a/drivers/gpu/drm/amd/display/dc/dce80/dce80_ipp.c
+++ b/drivers/gpu/drm/amd/display/dc/dce80/dce80_ipp.c
@@ -37,6 +37,7 @@ static const struct ipp_funcs funcs = {
 		.ipp_cursor_set_attributes = dce110_ipp_cursor_set_attributes,
 		.ipp_cursor_set_position = dce110_ipp_cursor_set_position,
 		.ipp_program_prescale = dce110_ipp_program_prescale,
+		.ipp_program_input_lut = dce110_ipp_program_input_lut,
 		.ipp_set_degamma = dce110_ipp_set_degamma,
 };
 
--- a/drivers/gpu/drm/amd/display/dc/dce80/dce80_ipp.h
+++ b/drivers/gpu/drm/amd/display/dc/dce80/dce80_ipp.h
@@ -33,8 +33,6 @@
 
 struct dce110_ipp;
 struct dce110_ipp_reg_offsets;
-struct gamma_parameters;
-struct dev_c_lut;
 
 bool dce80_ipp_construct(
 	struct dce110_ipp *ipp,
--- a/drivers/gpu/drm/amd/display/dc/dce80/dce80_ipp_gamma.c
+++ b/drivers/gpu/drm/amd/display/dc/dce80/dce80_ipp_gamma.c
@@ -34,15 +34,10 @@
 
 #include "dce80_ipp.h"
 #include "dce110/dce110_ipp.h"
-#include "gamma_types.h"
 
 #define DCP_REG(reg)\
 	(reg + ipp80->offsets.dcp_offset)
 
-enum {
-	MAX_INPUT_LUT_ENTRY = 256
-};
-
 /*PROTOTYPE DECLARATIONS*/
 
 static void set_legacy_input_gamma_mode(
--- a/drivers/gpu/drm/amd/display/dc/inc/gamma_types.h
+++ /dev/null
@@ -1,38 +0,0 @@
-/*
- * 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 GAMMA_TYPES_H_
-
-#define GAMMA_TYPES_H_
-
-#include "dc_types.h"
-
-/* TODO: Used in IPP and OPP */
-
-struct dev_c_lut16 {
-	uint16_t red;
-	uint16_t green;
-	uint16_t blue;
-};
-#endif
--- a/drivers/gpu/drm/amd/display/dc/inc/hw/ipp.h
+++ b/drivers/gpu/drm/amd/display/dc/inc/hw/ipp.h
@@ -110,6 +110,10 @@ struct ipp_funcs {
 			struct input_pixel_processor *ipp,
 			struct ipp_prescale_params *params);
 
+	void (*ipp_program_input_lut)(
+			struct input_pixel_processor *ipp,
+			const struct dc_gamma *gamma);
+
 	/*** DEGAMMA RELATED ***/
 	bool (*ipp_set_degamma)(
 		struct input_pixel_processor *ipp,
--- a/drivers/gpu/drm/amd/display/dc/inc/hw/opp.h
+++ b/drivers/gpu/drm/amd/display/dc/inc/hw/opp.h
@@ -30,7 +30,6 @@
 #include "transform.h"
 
 struct fixed31_32;
-struct gamma_parameters;
 
 /* TODO: Need cleanup */
 enum clamping_range {
--- a/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h
+++ b/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h
@@ -28,8 +28,6 @@
 #include "core_types.h"
 #include "timing_generator.h"
 
-struct gamma_parameters;
-
 enum pipe_gating_control {
 	PIPE_GATING_CONTROL_DISABLE = 0,
 	PIPE_GATING_CONTROL_ENABLE,
--- a/drivers/gpu/drm/amd/display/modules/color/color.c
+++ b/drivers/gpu/drm/amd/display/modules/color/color.c
@@ -2433,7 +2433,7 @@ bool mod_color_set_input_gamma_correctio
 
 		if (surface != NULL) {
 			struct dc_transfer_func *input_tf =
-					dc_create_transfer_func(core_color->dc);
+					dc_create_transfer_func();
 			struct dc_surface_update updates = {0};
 
 			if (input_tf != NULL) {
@@ -2724,7 +2724,7 @@ bool mod_color_update_gamut_info(struct
 		/* 3. ---- SET DEGAMMA ---- */
 		struct dc_transfer_func *input_tf = NULL;
 
-		input_tf = dc_create_transfer_func(core_color->dc);
+		input_tf = dc_create_transfer_func();
 
 		if (input_tf != NULL) {
 			input_tf->type = TF_TYPE_PREDEFINED;
@@ -2747,7 +2747,7 @@ bool mod_color_update_gamut_info(struct
 		/* 4. ---- SET REGAMMA ---- */
 		struct dc_transfer_func *output_tf = NULL;
 
-		output_tf = dc_create_transfer_func(core_color->dc);
+		output_tf = dc_create_transfer_func();
 
 		if (output_tf != NULL) {
 			output_tf->type = TF_TYPE_PREDEFINED;