aboutsummaryrefslogtreecommitdiffstats
path: root/meta-amd-bsp/recipes-kernel/linux/linux-yocto-4.14.71/0093-drm-amd-display-Implement-gamma-correction-using-inp.patch
diff options
context:
space:
mode:
Diffstat (limited to 'meta-amd-bsp/recipes-kernel/linux/linux-yocto-4.14.71/0093-drm-amd-display-Implement-gamma-correction-using-inp.patch')
-rw-r--r--meta-amd-bsp/recipes-kernel/linux/linux-yocto-4.14.71/0093-drm-amd-display-Implement-gamma-correction-using-inp.patch1006
1 files changed, 1006 insertions, 0 deletions
diff --git a/meta-amd-bsp/recipes-kernel/linux/linux-yocto-4.14.71/0093-drm-amd-display-Implement-gamma-correction-using-inp.patch b/meta-amd-bsp/recipes-kernel/linux/linux-yocto-4.14.71/0093-drm-amd-display-Implement-gamma-correction-using-inp.patch
new file mode 100644
index 00000000..bb10fe46
--- /dev/null
+++ b/meta-amd-bsp/recipes-kernel/linux/linux-yocto-4.14.71/0093-drm-amd-display-Implement-gamma-correction-using-inp.patch
@@ -0,0 +1,1006 @@
+From 734ab62e914908b443ba53c107d9cc5cc18e78f0 Mon Sep 17 00:00:00 2001
+From: Aric Cyr <aric.cyr@amd.com>
+Date: Tue, 20 Dec 2016 20:24:24 -0500
+Subject: [PATCH 0093/4131] drm/amd/display: Implement gamma correction using
+ input LUT
+
+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>
+---
+ .../drm/amd/display/amdgpu_dm/amdgpu_dm_types.c | 25 +-
+ drivers/gpu/drm/amd/display/dc/calcs/gamma_calcs.c | 29 +-
+ drivers/gpu/drm/amd/display/dc/core/dc_surface.c | 6 +-
+ drivers/gpu/drm/amd/display/dc/dc.h | 40 +--
+ 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 -
+ .../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 +-
+ .../drm/amd/display/dc/dce110/dce110_ipp_gamma.c | 304 ++++++---------------
+ .../amd/display/dc/dce110/dce110_opp_regamma_v.c | 1 -
+ .../gpu/drm/amd/display/dc/dce110/dce110_opp_v.c | 2 -
+ .../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 -
+ .../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 +-
+ 22 files changed, 144 insertions(+), 371 deletions(-)
+ delete mode 100644 drivers/gpu/drm/amd/display/dc/inc/gamma_types.h
+
+diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c
+index 6aede70..e7ada89 100644
+--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c
++++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c
+@@ -516,32 +516,25 @@ static void fill_gamma_from_crtc(
+ uint16_t *red, *green, *blue;
+ int end = (crtc->gamma_size > NUM_OF_RAW_GAMMA_RAMP_RGB_256) ?
+ NUM_OF_RAW_GAMMA_RAMP_RGB_256 : crtc->gamma_size;
+- struct amdgpu_device *adev = crtc->dev->dev_private;
+
+ red = crtc->gamma_store;
+ green = red + crtc->gamma_size;
+ blue = green + crtc->gamma_size;
+
+- gamma = dc_create_gamma(adev->dm.dc);
++ gamma = dc_create_gamma();
+
+ if (gamma == NULL)
+ return;
+
+ for (i = 0; i < end; i++) {
+- gamma->gamma_ramp_rgb256x3x16.red[i] =
+- (unsigned short) red[i];
+- gamma->gamma_ramp_rgb256x3x16.green[i] =
+- (unsigned short) green[i];
+- gamma->gamma_ramp_rgb256x3x16.blue[i] =
+- (unsigned short) blue[i];
++ gamma->red[i] = (unsigned short) red[i];
++ gamma->green[i] = (unsigned short) green[i];
++ gamma->blue[i] = (unsigned short) blue[i];
+ }
+
+- gamma->type = GAMMA_RAMP_RBG256X3X16;
+- gamma->size = sizeof(gamma->gamma_ramp_rgb256x3x16);
+-
+ dc_surface->gamma_correction = gamma;
+
+- input_tf = dc_create_transfer_func(adev->dm.dc);
++ input_tf = dc_create_transfer_func();
+
+ if (input_tf == NULL)
+ return;
+@@ -839,6 +832,12 @@ static void fill_stream_properties_from_drm_display_mode(
+
+ 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(
+@@ -3212,7 +3211,7 @@ static bool is_dp_capable_without_timing_msa(
+ 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;
+ }
+diff --git a/drivers/gpu/drm/amd/display/dc/calcs/gamma_calcs.c b/drivers/gpu/drm/amd/display/dc/calcs/gamma_calcs.c
+index f33135b..ca2234e 100644
+--- 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_coefficients_worker(
+ 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_data *pwl_rgb,
+ 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_data *pwl_rgb,
+ break;
+ }
+ ++i;
+- } while (i != RGB_256X3X16);
++ } while (i != INPUT_LUT_ENTRIES);
+
+ i = 0;
+
+@@ -995,7 +988,7 @@ static bool scale_gamma(struct pwl_float_data *pwl_rgb,
+
+ ++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_hardware_curve(
+ 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_params *params,
+ 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));
+diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_surface.c b/drivers/gpu/drm/amd/display/dc/core/dc_surface.c
+index 1ca40a2..3ec1f36 100644
+--- a/drivers/gpu/drm/amd/display/dc/core/dc_surface.c
++++ b/drivers/gpu/drm/amd/display/dc/core/dc_surface.c
+@@ -189,9 +189,8 @@ void dc_gamma_release(const struct dc_gamma *dc_gamma)
+ dm_free(gamma);
+ }
+
+-struct dc_gamma *dc_create_gamma(const struct dc *dc)
++struct dc_gamma *dc_create_gamma()
+ {
+- struct core_dc *core_dc = DC_TO_CORE(dc);
+ struct gamma *gamma = dm_alloc(sizeof(*gamma));
+
+ if (gamma == NULL)
+@@ -221,9 +220,8 @@ void dc_transfer_func_release(const struct dc_transfer_func *dc_tf)
+ dm_free(tf);
+ }
+
+-struct dc_transfer_func *dc_create_transfer_func(const struct dc *dc)
++struct dc_transfer_func *dc_create_transfer_func()
+ {
+- struct core_dc *core_dc = DC_TO_CORE(dc);
+ struct transfer_func *tf = dm_alloc(sizeof(*tf));
+
+ if (tf == NULL)
+diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h
+index 05fcb06..0ee6f41 100644
+--- 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;
+ };
+
+@@ -332,11 +296,11 @@ void dc_surface_release(const struct dc_surface *dc_surface);
+
+ void dc_gamma_retain(const struct dc_gamma *dc_gamma);
+ void dc_gamma_release(const struct dc_gamma *dc_gamma);
+-struct dc_gamma *dc_create_gamma(const struct dc *dc);
++struct dc_gamma *dc_create_gamma(void);
+
+ void dc_transfer_func_retain(const struct dc_transfer_func *dc_tf);
+ void dc_transfer_func_release(const struct dc_transfer_func *dc_tf);
+-struct dc_transfer_func *dc_create_transfer_func(const struct dc *dc);
++struct dc_transfer_func *dc_create_transfer_func(void);
+
+ /*
+ * This structure holds a surface address. There could be multiple addresses
+diff --git a/drivers/gpu/drm/amd/display/dc/dc_hw_types.h b/drivers/gpu/drm/amd/display/dc/dc_hw_types.h
+index 499f6b2..00958bd 100644
+--- 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 */
+
+diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_opp.c b/drivers/gpu/drm/amd/display/dc/dce/dce_opp.c
+index 653f93d..46b1287 100644
+--- 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)\
+diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_opp.h b/drivers/gpu/drm/amd/display/dc/dce/dce_opp.h
+index 1c01a83e..f2828f0 100644
+--- 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)
+
+diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c
+index 2f79075..e4cef9d 100644
+--- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c
++++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c
+@@ -228,10 +228,11 @@ static void build_prescale_params(struct ipp_prescale_params *prescale_params,
+ 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_func(
+
+ 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 dce110_funcs = {
+ .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,
+diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_ipp.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_ipp.c
+index dd69f60..86fa765 100644
+--- 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,
+ };
+
+diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_ipp.h b/drivers/gpu/drm/amd/display/dc/dce110/dce110_ipp.h
+index 56fe327..a374ef2 100644
+--- 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__*/
+diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_ipp_gamma.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_ipp_gamma.c
+index 79a6a6d..c68914b 100644
+--- 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;
++ /* set to bypass mode first before change */
++ DCP_REG_UPDATE(PRESCALE_GRPH_CONTROL,
++ GRPH_PRESCALE_BYPASS, 1);
+
+- prescale_control = dm_read_reg(ipp110->base.ctx,
+- DCP_REG(mmPRESCALE_GRPH_CONTROL));
++ DCP_REG_SET_2(PRESCALE_VALUES_GRPH_R,
++ GRPH_PRESCALE_SCALE_R, params->scale,
++ GRPH_PRESCALE_BIAS_R, params->bias);
+
+- if (params->mode != IPP_PRESCALE_MODE_BYPASS) {
++ DCP_REG_SET_2(PRESCALE_VALUES_GRPH_G,
++ GRPH_PRESCALE_SCALE_G, params->scale,
++ GRPH_PRESCALE_BIAS_G, params->bias);
+
+- 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);
+- }
++ DCP_REG_SET_2(PRESCALE_VALUES_GRPH_B,
++ GRPH_PRESCALE_SCALE_B, params->scale,
++ GRPH_PRESCALE_BIAS_B, params->bias);
+
+- 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)
+-{
+- const uint32_t addr = DCP_REG(mmDC_LUT_CONTROL);
+-
+- uint32_t value = dm_read_reg(ipp110->base.ctx, addr);
+-
+- 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);
+-
+- dm_write_reg(ipp110->base.ctx, addr, value);
++ if (params->mode != IPP_PRESCALE_MODE_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);
++ }
+ }
+
+-void dce110_helper_select_lut(struct dce110_ipp *ipp110)
++static void dce110_helper_select_lut(struct dce110_ipp *ipp110)
+ {
+- 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);
++ /* enable all */
++ DCP_REG_SET(DC_LUT_WRITE_EN_MASK, DC_LUT_WRITE_EN_MASK, 0x7);
+
+- set_reg_field_value(
+- value,
+- 0,
+- DC_LUT_RW_MODE,
+- DC_LUT_RW_MODE);
++ /* 256 entry mode */
++ DCP_REG_UPDATE(DC_LUT_RW_MODE, DC_LUT_RW_MODE, 0);
+
+- dm_write_reg(ipp110->base.ctx, addr, value);
+- }
+-
+- {
+- const uint32_t addr = DCP_REG(mmDC_LUT_CONTROL);
++ /* 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);
+
+- value = dm_read_reg(ipp110->base.ctx, addr);
++ /* start from index 0 */
++ DCP_REG_SET(DC_LUT_RW_INDEX, DC_LUT_RW_INDEX, 0);
++}
+
+- /* 00 - new u0.12 */
+- set_reg_field_value(
+- value,
+- 3,
+- DC_LUT_CONTROL,
+- DC_LUT_DATA_R_FORMAT);
++void dce110_ipp_program_input_lut(
++ struct input_pixel_processor *ipp,
++ const struct dc_gamma *gamma)
++{
++ int i;
++ struct dce110_ipp *ipp110 = TO_DCE110_IPP(ipp);
+
+- set_reg_field_value(
+- value,
+- 3,
+- DC_LUT_CONTROL,
+- DC_LUT_DATA_G_FORMAT);
++ dce110_helper_select_lut(ipp110);
+
+- set_reg_field_value(
+- value,
+- 3,
+- DC_LUT_CONTROL,
+- DC_LUT_DATA_B_FORMAT);
++ /* 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);
+
+- dm_write_reg(ipp110->base.ctx, addr, value);
++ 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);
+-
+- value = dm_read_reg(ipp110->base.ctx, addr);
++ /* power off LUT memory */
++ DCP_REG_SET(DCFE_MEM_PWR_CTRL, DCP_LUT_MEM_PWR_DIS, 0);
+
+- 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);
+ }
+diff --git 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
+index 81fcbc5..8164aa6 100644
+--- 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)
+diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_opp_v.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_opp_v.c
+index dfd63a7..0a9b384 100644
+--- 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 */
+ /*****************************************/
+diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_opp_v.h b/drivers/gpu/drm/amd/display/dc/dce110/dce110_opp_v.h
+index dcdbf86..ac59377 100644
+--- 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);
+
+diff --git a/drivers/gpu/drm/amd/display/dc/dce80/dce80_ipp.c b/drivers/gpu/drm/amd/display/dc/dce80/dce80_ipp.c
+index 86826c2..c195acb 100644
+--- 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,
+ };
+
+diff --git a/drivers/gpu/drm/amd/display/dc/dce80/dce80_ipp.h b/drivers/gpu/drm/amd/display/dc/dce80/dce80_ipp.h
+index d350138..06e8598 100644
+--- 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,
+diff --git a/drivers/gpu/drm/amd/display/dc/dce80/dce80_ipp_gamma.c b/drivers/gpu/drm/amd/display/dc/dce80/dce80_ipp_gamma.c
+index eacb14e..760168d 100644
+--- 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(
+diff --git a/drivers/gpu/drm/amd/display/dc/inc/gamma_types.h b/drivers/gpu/drm/amd/display/dc/inc/gamma_types.h
+deleted file mode 100644
+index 7948d2c..0000000
+--- 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
+diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/ipp.h b/drivers/gpu/drm/amd/display/dc/inc/hw/ipp.h
+index e9ed167..0457bc7 100644
+--- 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,
+diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/opp.h b/drivers/gpu/drm/amd/display/dc/inc/hw/opp.h
+index e615997..a1f31a4 100644
+--- 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 {
+diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h b/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h
+index 0e803ca..895c446 100644
+--- 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,
+diff --git a/drivers/gpu/drm/amd/display/modules/color/color.c b/drivers/gpu/drm/amd/display/modules/color/color.c
+index 6d1b20f..5c578aec 100644
+--- 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_correction(struct mod_color *mod_color,
+
+ 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 mod_color *mod_color,
+ /* 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 mod_color *mod_color,
+ /* 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;
+--
+2.7.4
+