diff options
Diffstat (limited to 'common/recipes-kernel/linux/files/0791-drm-amd-dal-opp-for-underlay.patch')
-rw-r--r-- | common/recipes-kernel/linux/files/0791-drm-amd-dal-opp-for-underlay.patch | 1822 |
1 files changed, 1822 insertions, 0 deletions
diff --git a/common/recipes-kernel/linux/files/0791-drm-amd-dal-opp-for-underlay.patch b/common/recipes-kernel/linux/files/0791-drm-amd-dal-opp-for-underlay.patch new file mode 100644 index 00000000..21736168 --- /dev/null +++ b/common/recipes-kernel/linux/files/0791-drm-amd-dal-opp-for-underlay.patch @@ -0,0 +1,1822 @@ +From 4330564057ab3f66dd1d72284d99f15208b5c474 Mon Sep 17 00:00:00 2001 +From: Yongqiang Sun <yongqiang.sun@amd.com> +Date: Tue, 9 Feb 2016 16:47:42 -0500 +Subject: [PATCH 0791/1110] drm/amd/dal: opp for underlay. + +Signed-off-by: Yongqiang Sun <yongqiang.sun@amd.com> +Acked-by: Harry Wentland <harry.wentland@amd.com> +--- + drivers/gpu/drm/amd/dal/dc/dce110/Makefile | 2 +- + drivers/gpu/drm/amd/dal/dc/dce110/dce110_opp.c | 3 +- + .../gpu/drm/amd/dal/dc/dce110/dce110_opp_csc_v.c | 1050 ++++++++++++++++++++ + .../drm/amd/dal/dc/dce110/dce110_opp_regamma_v.c | 520 ++++++++++ + drivers/gpu/drm/amd/dal/dc/dce110/dce110_opp_v.c | 75 ++ + drivers/gpu/drm/amd/dal/dc/dce110/dce110_opp_v.h | 55 + + .../gpu/drm/amd/dal/dc/dce110/dce110_resource.c | 2 +- + drivers/gpu/drm/amd/dal/dc/inc/opp.h | 15 + + 8 files changed, 1719 insertions(+), 3 deletions(-) + create mode 100644 drivers/gpu/drm/amd/dal/dc/dce110/dce110_opp_csc_v.c + create mode 100644 drivers/gpu/drm/amd/dal/dc/dce110/dce110_opp_regamma_v.c + create mode 100644 drivers/gpu/drm/amd/dal/dc/dce110/dce110_opp_v.c + create mode 100644 drivers/gpu/drm/amd/dal/dc/dce110/dce110_opp_v.h + +diff --git a/drivers/gpu/drm/amd/dal/dc/dce110/Makefile b/drivers/gpu/drm/amd/dal/dc/dce110/Makefile +index 71aa9d8..deae715 100644 +--- a/drivers/gpu/drm/amd/dal/dc/dce110/Makefile ++++ b/drivers/gpu/drm/amd/dal/dc/dce110/Makefile +@@ -9,7 +9,7 @@ dce110_timing_generator.o dce110_transform.o dce110_transform_v.o \ + dce110_transform_gamut.o dce110_transform_scl.o dce110_opp_csc.o\ + dce110_compressor.o dce110_mem_input.o dce110_hw_sequencer.o \ + dce110_resource.o dce110_transform_bit_depth.o dce110_clock_source.o \ +-dce110_timing_generator_v.o ++dce110_opp_regamma_v.o dce110_opp_csc_v.o dce110_timing_generator_v.o + + AMD_DAL_DCE110 = $(addprefix $(AMDDALPATH)/dc/dce110/,$(DCE110)) + +diff --git a/drivers/gpu/drm/amd/dal/dc/dce110/dce110_opp.c b/drivers/gpu/drm/amd/dal/dc/dce110/dce110_opp.c +index 394f187..86bf8c0 100644 +--- a/drivers/gpu/drm/amd/dal/dc/dce110/dce110_opp.c ++++ b/drivers/gpu/drm/amd/dal/dc/dce110/dce110_opp.c +@@ -49,7 +49,8 @@ struct opp_funcs funcs = { + .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 ++ .opp_set_regamma = dce110_opp_set_regamma, ++ .opp_destroy = dce110_opp_destroy, + }; + + bool dce110_opp_construct(struct dce110_opp *opp110, +diff --git a/drivers/gpu/drm/amd/dal/dc/dce110/dce110_opp_csc_v.c b/drivers/gpu/drm/amd/dal/dc/dce110/dce110_opp_csc_v.c +new file mode 100644 +index 0000000..6ca749e +--- /dev/null ++++ b/drivers/gpu/drm/amd/dal/dc/dce110/dce110_opp_csc_v.c +@@ -0,0 +1,1050 @@ ++/* ++ * 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 "video_csc_types.h" ++ ++/* include DCE11 register header files */ ++#include "dce/dce_11_0_d.h" ++#include "dce/dce_11_0_sh_mask.h" ++#include "dce/dce_11_0_enum.h" ++ ++enum { ++ OUTPUT_CSC_MATRIX_SIZE = 12 ++}; ++ ++/* constrast:0 - 2.0, default 1.0 */ ++#define UNDERLAY_CONTRAST_DEFAULT 100 ++#define UNDERLAY_CONTRAST_MAX 200 ++#define UNDERLAY_CONTRAST_MIN 0 ++#define UNDERLAY_CONTRAST_STEP 1 ++#define UNDERLAY_CONTRAST_DIVIDER 100 ++ ++/* Saturation: 0 - 2.0; default 1.0 */ ++#define UNDERLAY_SATURATION_DEFAULT 100 /*1.00*/ ++#define UNDERLAY_SATURATION_MIN 0 ++#define UNDERLAY_SATURATION_MAX 200 /* 2.00 */ ++#define UNDERLAY_SATURATION_STEP 1 /* 0.01 */ ++/*actual max overlay saturation ++ * value = UNDERLAY_SATURATION_MAX /UNDERLAY_SATURATION_DIVIDER ++ */ ++ ++/* Hue */ ++#define UNDERLAY_HUE_DEFAULT 0 ++#define UNDERLAY_HUE_MIN -300 ++#define UNDERLAY_HUE_MAX 300 ++#define UNDERLAY_HUE_STEP 5 ++#define UNDERLAY_HUE_DIVIDER 10 /* HW range: -30 ~ +30 */ ++#define UNDERLAY_SATURATION_DIVIDER 100 ++ ++/* Brightness: in DAL usually -.25 ~ .25. ++ * In MMD is -100 to +100 in 16-235 range; which when scaled to full range is ++ * ~-116 to +116. When normalized this is about 0.4566. ++ * With 100 divider this becomes 46, but we may use another for better precision ++ * The ideal one is 100/219 ((100/255)*(255/219)), ++ * i.e. min/max = +-100, divider = 219 ++ * default 0.0 ++ */ ++#define UNDERLAY_BRIGHTNESS_DEFAULT 0 ++#define UNDERLAY_BRIGHTNESS_MIN -46 /* ~116/255 */ ++#define UNDERLAY_BRIGHTNESS_MAX 46 ++#define UNDERLAY_BRIGHTNESS_STEP 1 /* .01 */ ++#define UNDERLAY_BRIGHTNESS_DIVIDER 100 ++ ++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_v( ++ 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 cntl_value = dm_read_reg(ctx, mmCOL_MAN_OUTPUT_CSC_CONTROL); ++ bool use_set_a = (get_reg_field_value(cntl_value, ++ COL_MAN_OUTPUT_CSC_CONTROL, ++ OUTPUT_CSC_MODE) != 4); ++ ++ set_reg_field_value( ++ cntl_value, ++ 0, ++ COL_MAN_OUTPUT_CSC_CONTROL, ++ OUTPUT_CSC_MODE); ++ ++ if (use_set_a) { ++ { ++ uint32_t value = 0; ++ uint32_t addr = mmOUTPUT_CSC_C11_C12_A; ++ /* fixed S2.13 format */ ++ set_reg_field_value( ++ value, ++ tbl_entry->regval[0], ++ OUTPUT_CSC_C11_C12_A, ++ OUTPUT_CSC_C11_A); ++ ++ set_reg_field_value( ++ value, ++ tbl_entry->regval[1], ++ OUTPUT_CSC_C11_C12_A, ++ OUTPUT_CSC_C12_A); ++ ++ dm_write_reg(ctx, addr, value); ++ } ++ { ++ uint32_t value = 0; ++ uint32_t addr = mmOUTPUT_CSC_C13_C14_A; ++ /* fixed S2.13 format */ ++ set_reg_field_value( ++ value, ++ tbl_entry->regval[2], ++ OUTPUT_CSC_C13_C14_A, ++ OUTPUT_CSC_C13_A); ++ /* fixed S0.13 format */ ++ set_reg_field_value( ++ value, ++ tbl_entry->regval[3], ++ OUTPUT_CSC_C13_C14_A, ++ OUTPUT_CSC_C14_A); ++ ++ dm_write_reg(ctx, addr, value); ++ } ++ { ++ uint32_t value = 0; ++ uint32_t addr = mmOUTPUT_CSC_C21_C22_A; ++ /* fixed S2.13 format */ ++ set_reg_field_value( ++ value, ++ tbl_entry->regval[4], ++ OUTPUT_CSC_C21_C22_A, ++ OUTPUT_CSC_C21_A); ++ /* fixed S2.13 format */ ++ set_reg_field_value( ++ value, ++ tbl_entry->regval[5], ++ OUTPUT_CSC_C21_C22_A, ++ OUTPUT_CSC_C22_A); ++ ++ dm_write_reg(ctx, addr, value); ++ } ++ { ++ uint32_t value = 0; ++ uint32_t addr = mmOUTPUT_CSC_C23_C24_A; ++ /* fixed S2.13 format */ ++ set_reg_field_value( ++ value, ++ tbl_entry->regval[6], ++ OUTPUT_CSC_C23_C24_A, ++ OUTPUT_CSC_C23_A); ++ /* fixed S0.13 format */ ++ set_reg_field_value( ++ value, ++ tbl_entry->regval[7], ++ OUTPUT_CSC_C23_C24_A, ++ OUTPUT_CSC_C24_A); ++ ++ dm_write_reg(ctx, addr, value); ++ } ++ { ++ uint32_t value = 0; ++ uint32_t addr = mmOUTPUT_CSC_C31_C32_A; ++ /* fixed S2.13 format */ ++ set_reg_field_value( ++ value, ++ tbl_entry->regval[8], ++ OUTPUT_CSC_C31_C32_A, ++ OUTPUT_CSC_C31_A); ++ /* fixed S0.13 format */ ++ set_reg_field_value( ++ value, ++ tbl_entry->regval[9], ++ OUTPUT_CSC_C31_C32_A, ++ OUTPUT_CSC_C32_A); ++ ++ dm_write_reg(ctx, addr, value); ++ } ++ { ++ uint32_t value = 0; ++ uint32_t addr = mmOUTPUT_CSC_C33_C34_A; ++ /* fixed S2.13 format */ ++ set_reg_field_value( ++ value, ++ tbl_entry->regval[10], ++ OUTPUT_CSC_C33_C34_A, ++ OUTPUT_CSC_C33_A); ++ /* fixed S0.13 format */ ++ set_reg_field_value( ++ value, ++ tbl_entry->regval[11], ++ OUTPUT_CSC_C33_C34_A, ++ OUTPUT_CSC_C34_A); ++ ++ dm_write_reg(ctx, addr, value); ++ } ++ set_reg_field_value( ++ cntl_value, ++ 4, ++ COL_MAN_OUTPUT_CSC_CONTROL, ++ OUTPUT_CSC_MODE); ++ } else { ++ { ++ uint32_t value = 0; ++ uint32_t addr = mmOUTPUT_CSC_C11_C12_B; ++ /* fixed S2.13 format */ ++ set_reg_field_value( ++ value, ++ tbl_entry->regval[0], ++ OUTPUT_CSC_C11_C12_B, ++ OUTPUT_CSC_C11_B); ++ ++ set_reg_field_value( ++ value, ++ tbl_entry->regval[1], ++ OUTPUT_CSC_C11_C12_B, ++ OUTPUT_CSC_C12_B); ++ ++ dm_write_reg(ctx, addr, value); ++ } ++ { ++ uint32_t value = 0; ++ uint32_t addr = mmOUTPUT_CSC_C13_C14_B; ++ /* fixed S2.13 format */ ++ set_reg_field_value( ++ value, ++ tbl_entry->regval[2], ++ OUTPUT_CSC_C13_C14_B, ++ OUTPUT_CSC_C13_B); ++ /* fixed S0.13 format */ ++ set_reg_field_value( ++ value, ++ tbl_entry->regval[3], ++ OUTPUT_CSC_C13_C14_B, ++ OUTPUT_CSC_C14_B); ++ ++ dm_write_reg(ctx, addr, value); ++ } ++ { ++ uint32_t value = 0; ++ uint32_t addr = mmOUTPUT_CSC_C21_C22_B; ++ /* fixed S2.13 format */ ++ set_reg_field_value( ++ value, ++ tbl_entry->regval[4], ++ OUTPUT_CSC_C21_C22_B, ++ OUTPUT_CSC_C21_B); ++ /* fixed S2.13 format */ ++ set_reg_field_value( ++ value, ++ tbl_entry->regval[5], ++ OUTPUT_CSC_C21_C22_B, ++ OUTPUT_CSC_C22_B); ++ ++ dm_write_reg(ctx, addr, value); ++ } ++ { ++ uint32_t value = 0; ++ uint32_t addr = mmOUTPUT_CSC_C23_C24_B; ++ /* fixed S2.13 format */ ++ set_reg_field_value( ++ value, ++ tbl_entry->regval[6], ++ OUTPUT_CSC_C23_C24_B, ++ OUTPUT_CSC_C23_B); ++ /* fixed S0.13 format */ ++ set_reg_field_value( ++ value, ++ tbl_entry->regval[7], ++ OUTPUT_CSC_C23_C24_B, ++ OUTPUT_CSC_C24_B); ++ ++ dm_write_reg(ctx, addr, value); ++ } ++ { ++ uint32_t value = 0; ++ uint32_t addr = mmOUTPUT_CSC_C31_C32_B; ++ /* fixed S2.13 format */ ++ set_reg_field_value( ++ value, ++ tbl_entry->regval[8], ++ OUTPUT_CSC_C31_C32_B, ++ OUTPUT_CSC_C31_B); ++ /* fixed S0.13 format */ ++ set_reg_field_value( ++ value, ++ tbl_entry->regval[9], ++ OUTPUT_CSC_C31_C32_B, ++ OUTPUT_CSC_C32_B); ++ ++ dm_write_reg(ctx, addr, value); ++ } ++ { ++ uint32_t value = 0; ++ uint32_t addr = mmOUTPUT_CSC_C33_C34_B; ++ /* fixed S2.13 format */ ++ set_reg_field_value( ++ value, ++ tbl_entry->regval[10], ++ OUTPUT_CSC_C33_C34_B, ++ OUTPUT_CSC_C33_B); ++ /* fixed S0.13 format */ ++ set_reg_field_value( ++ value, ++ tbl_entry->regval[11], ++ OUTPUT_CSC_C33_C34_B, ++ OUTPUT_CSC_C34_B); ++ ++ dm_write_reg(ctx, addr, value); ++ } ++ set_reg_field_value( ++ cntl_value, ++ 5, ++ COL_MAN_OUTPUT_CSC_CONTROL, ++ OUTPUT_CSC_MODE); ++ } ++ ++ dm_write_reg(ctx, mmCOL_MAN_OUTPUT_CSC_CONTROL, cntl_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); ++} ++ ++/** ++ ***************************************************************************** ++ * 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_v( ++ opp110, &tbl_entry, adjust->color_adjust_option); ++} ++ ++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(®_matrix, 0, sizeof(struct out_csc_color_matrix)); ++ ++ setup_reg_format(matrix, reg_matrix.regval); ++ ++ program_color_matrix_v(opp110, ®_matrix, GRPH_COLOR_MATRIX_SW); ++} ++ ++static bool configure_graphics_mode_v( ++ 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 = mmCOL_MAN_OUTPUT_CSC_CONTROL; ++ uint32_t value = dm_read_reg(ctx, addr); ++ ++ set_reg_field_value( ++ value, ++ 0, ++ COL_MAN_OUTPUT_CSC_CONTROL, ++ OUTPUT_CSC_MODE); ++ ++ if (csc_adjust_type == GRAPHICS_CSC_ADJUST_TYPE_SW) { ++ if (config == CSC_COLOR_MODE_GRAPHICS_OUTPUT_CSC) ++ return true; ++ ++ switch (color_space) { ++ case COLOR_SPACE_SRGB_FULL_RANGE: ++ /* by pass */ ++ set_reg_field_value( ++ value, ++ 0, ++ COL_MAN_OUTPUT_CSC_CONTROL, ++ OUTPUT_CSC_MODE); ++ break; ++ case COLOR_SPACE_SRGB_LIMITED_RANGE: ++ /* not supported for underlay on CZ */ ++ return false; ++ ++ case COLOR_SPACE_YCBCR601: ++ case COLOR_SPACE_YPBPR601: ++ case COLOR_SPACE_YCBCR601_YONLY: ++ /* YCbCr601 */ ++ set_reg_field_value( ++ value, ++ 2, ++ COL_MAN_OUTPUT_CSC_CONTROL, ++ OUTPUT_CSC_MODE); ++ break; ++ case COLOR_SPACE_YCBCR709: ++ case COLOR_SPACE_YPBPR709: ++ case COLOR_SPACE_YCBCR709_YONLY: ++ /* YCbCr709 */ ++ set_reg_field_value( ++ value, ++ 3, ++ COL_MAN_OUTPUT_CSC_CONTROL, ++ OUTPUT_CSC_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, ++ COL_MAN_OUTPUT_CSC_CONTROL, ++ OUTPUT_CSC_MODE); ++ break; ++ case COLOR_SPACE_SRGB_LIMITED_RANGE: ++ /* not supported for underlay on CZ */ ++ return false; ++ case COLOR_SPACE_YCBCR601: ++ case COLOR_SPACE_YPBPR601: ++ case COLOR_SPACE_YCBCR601_YONLY: ++ /* YCbCr601 */ ++ set_reg_field_value( ++ value, ++ 2, ++ COL_MAN_OUTPUT_CSC_CONTROL, ++ OUTPUT_CSC_MODE); ++ break; ++ case COLOR_SPACE_YCBCR709: ++ case COLOR_SPACE_YPBPR709: ++ case COLOR_SPACE_YCBCR709_YONLY: ++ /* YCbCr709 */ ++ set_reg_field_value( ++ value, ++ 3, ++ COL_MAN_OUTPUT_CSC_CONTROL, ++ OUTPUT_CSC_MODE); ++ break; ++ default: ++ return false; ++ } ++ ++ } else ++ /* by pass */ ++ set_reg_field_value( ++ value, ++ 0, ++ COL_MAN_OUTPUT_CSC_CONTROL, ++ OUTPUT_CSC_MODE); ++ ++ addr = mmCOL_MAN_OUTPUT_CSC_CONTROL; ++ dm_write_reg(ctx, addr, value); ++ ++ return true; ++} ++ ++static void set_Denormalization(struct output_pixel_processor *opp, ++ enum dc_color_depth color_depth) ++{ ++ uint32_t value = dm_read_reg(opp->ctx, mmDENORM_CLAMP_CONTROL); ++ ++ switch (color_depth) { ++ case COLOR_DEPTH_888: ++ /* 255/256 for 8 bit output color depth */ ++ set_reg_field_value( ++ value, ++ 1, ++ DENORM_CLAMP_CONTROL, ++ DENORM_MODE); ++ break; ++ case COLOR_DEPTH_101010: ++ /* 1023/1024 for 10 bit output color depth */ ++ set_reg_field_value( ++ value, ++ 2, ++ DENORM_CLAMP_CONTROL, ++ DENORM_MODE); ++ break; ++ case COLOR_DEPTH_121212: ++ /* 4095/4096 for 12 bit output color depth */ ++ set_reg_field_value( ++ value, ++ 3, ++ DENORM_CLAMP_CONTROL, ++ DENORM_MODE); ++ break; ++ default: ++ /* not valid case */ ++ break; ++ } ++ ++ set_reg_field_value( ++ value, ++ 1, ++ DENORM_CLAMP_CONTROL, ++ DENORM_10BIT_OUT); ++ ++ dm_write_reg(opp->ctx, mmDENORM_CLAMP_CONTROL, value); ++} ++ ++ ++void dce110_opp_v_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_v(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_v(opp110, config, ++ default_adjust->csc_adjust_type, ++ default_adjust->color_space); ++ ++ set_Denormalization(opp, default_adjust->color_depth); ++} ++ ++void dce110_opp_v_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_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_v(opp110, config, adjust->csc_adjust_type, ++ adjust->c_space); ++ ++ set_Denormalization(opp, adjust->color_depth); ++} +diff --git a/drivers/gpu/drm/amd/dal/dc/dce110/dce110_opp_regamma_v.c b/drivers/gpu/drm/amd/dal/dc/dce110/dce110_opp_regamma_v.c +new file mode 100644 +index 0000000..4f6cc9c +--- /dev/null ++++ b/drivers/gpu/drm/amd/dal/dc/dce110/dce110_opp_regamma_v.c +@@ -0,0 +1,520 @@ ++/* ++ * 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" ++ ++static void power_on_lut(struct output_pixel_processor *opp, ++ bool power_on, bool inputgamma, bool regamma) ++{ ++ uint32_t value = dm_read_reg(opp->ctx, mmDCFEV_MEM_PWR_CTRL); ++ int i; ++ ++ if (power_on) { ++ if (inputgamma) ++ set_reg_field_value( ++ value, ++ 1, ++ DCFEV_MEM_PWR_CTRL, ++ COL_MAN_INPUT_GAMMA_MEM_PWR_DIS); ++ if (regamma) ++ set_reg_field_value( ++ value, ++ 1, ++ DCFEV_MEM_PWR_CTRL, ++ COL_MAN_GAMMA_CORR_MEM_PWR_DIS); ++ } else { ++ if (inputgamma) ++ set_reg_field_value( ++ value, ++ 0, ++ DCFEV_MEM_PWR_CTRL, ++ COL_MAN_INPUT_GAMMA_MEM_PWR_DIS); ++ if (regamma) ++ set_reg_field_value( ++ value, ++ 0, ++ DCFEV_MEM_PWR_CTRL, ++ COL_MAN_GAMMA_CORR_MEM_PWR_DIS); ++ } ++ ++ dm_write_reg(opp->ctx, mmDCFEV_MEM_PWR_CTRL, value); ++ ++ for (i = 0; i < 3; i++) { ++ value = dm_read_reg(opp->ctx, mmDCFEV_MEM_PWR_CTRL); ++ if (get_reg_field_value(value, ++ DCFEV_MEM_PWR_CTRL, ++ COL_MAN_INPUT_GAMMA_MEM_PWR_DIS) && ++ get_reg_field_value(value, ++ DCFEV_MEM_PWR_CTRL, ++ COL_MAN_GAMMA_CORR_MEM_PWR_DIS)) ++ break; ++ ++ dm_delay_in_microseconds(opp->ctx, 2); ++ } ++} ++ ++static void set_bypass_input_gamma(struct dce110_opp *opp110) ++{ ++ uint32_t value; ++ ++ value = dm_read_reg(opp110->base.ctx, ++ mmCOL_MAN_INPUT_GAMMA_CONTROL1); ++ ++ set_reg_field_value( ++ value, ++ 0, ++ COL_MAN_INPUT_GAMMA_CONTROL1, ++ INPUT_GAMMA_MODE); ++ ++ dm_write_reg(opp110->base.ctx, ++ mmCOL_MAN_INPUT_GAMMA_CONTROL1, value); ++} ++ ++static void configure_regamma_mode(struct dce110_opp *opp110, uint32_t mode) ++{ ++ uint32_t value = 0; ++ ++ set_reg_field_value( ++ value, ++ mode, ++ GAMMA_CORR_CONTROL, ++ GAMMA_CORR_MODE); ++ ++ dm_write_reg(opp110->base.ctx, mmGAMMA_CORR_CONTROL, 0); ++} ++ ++/* ++ ***************************************************************************** ++ * 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, const struct regamma_params *params) ++{ ++ const struct gamma_curve *curve; ++ uint32_t value = 0; ++ ++ { ++ set_reg_field_value( ++ value, ++ params->arr_points[0].custom_float_x, ++ GAMMA_CORR_CNTLA_START_CNTL, ++ GAMMA_CORR_CNTLA_EXP_REGION_START); ++ ++ set_reg_field_value( ++ value, ++ 0, ++ GAMMA_CORR_CNTLA_START_CNTL, ++ GAMMA_CORR_CNTLA_EXP_REGION_START_SEGMENT); ++ ++ dm_write_reg(opp110->base.ctx, mmGAMMA_CORR_CNTLA_START_CNTL, ++ value); ++ } ++ { ++ value = 0; ++ set_reg_field_value( ++ value, ++ params->arr_points[0].custom_float_slope, ++ GAMMA_CORR_CNTLA_SLOPE_CNTL, ++ GAMMA_CORR_CNTLA_EXP_REGION_LINEAR_SLOPE); ++ ++ dm_write_reg(opp110->base.ctx, ++ mmGAMMA_CORR_CNTLA_SLOPE_CNTL, value); ++ } ++ { ++ value = 0; ++ set_reg_field_value( ++ value, ++ params->arr_points[1].custom_float_x, ++ GAMMA_CORR_CNTLA_END_CNTL1, ++ GAMMA_CORR_CNTLA_EXP_REGION_END); ++ ++ dm_write_reg(opp110->base.ctx, ++ mmGAMMA_CORR_CNTLA_END_CNTL1, value); ++ } ++ { ++ value = 0; ++ set_reg_field_value( ++ value, ++ params->arr_points[2].custom_float_slope, ++ GAMMA_CORR_CNTLA_END_CNTL2, ++ GAMMA_CORR_CNTLA_EXP_REGION_END_BASE); ++ ++ set_reg_field_value( ++ value, ++ params->arr_points[1].custom_float_y, ++ GAMMA_CORR_CNTLA_END_CNTL2, ++ GAMMA_CORR_CNTLA_EXP_REGION_END_SLOPE); ++ ++ dm_write_reg(opp110->base.ctx, ++ mmGAMMA_CORR_CNTLA_END_CNTL2, value); ++ } ++ ++ curve = params->arr_curve_points; ++ ++ { ++ value = 0; ++ set_reg_field_value( ++ value, ++ curve[0].offset, ++ GAMMA_CORR_CNTLA_REGION_0_1, ++ GAMMA_CORR_CNTLA_EXP_REGION0_LUT_OFFSET); ++ ++ set_reg_field_value( ++ value, ++ curve[0].segments_num, ++ GAMMA_CORR_CNTLA_REGION_0_1, ++ GAMMA_CORR_CNTLA_EXP_REGION0_NUM_SEGMENTS); ++ ++ set_reg_field_value( ++ value, ++ curve[1].offset, ++ GAMMA_CORR_CNTLA_REGION_0_1, ++ GAMMA_CORR_CNTLA_EXP_REGION1_LUT_OFFSET); ++ ++ set_reg_field_value( ++ value, ++ curve[1].segments_num, ++ GAMMA_CORR_CNTLA_REGION_0_1, ++ GAMMA_CORR_CNTLA_EXP_REGION1_NUM_SEGMENTS); ++ ++ dm_write_reg( ++ opp110->base.ctx, ++ mmGAMMA_CORR_CNTLA_REGION_0_1, ++ value); ++ } ++ ++ curve += 2; ++ { ++ value = 0; ++ set_reg_field_value( ++ value, ++ curve[0].offset, ++ GAMMA_CORR_CNTLA_REGION_2_3, ++ GAMMA_CORR_CNTLA_EXP_REGION2_LUT_OFFSET); ++ ++ set_reg_field_value( ++ value, ++ curve[0].segments_num, ++ GAMMA_CORR_CNTLA_REGION_2_3, ++ GAMMA_CORR_CNTLA_EXP_REGION2_NUM_SEGMENTS); ++ ++ set_reg_field_value( ++ value, ++ curve[1].offset, ++ GAMMA_CORR_CNTLA_REGION_2_3, ++ GAMMA_CORR_CNTLA_EXP_REGION3_LUT_OFFSET); ++ ++ set_reg_field_value( ++ value, ++ curve[1].segments_num, ++ GAMMA_CORR_CNTLA_REGION_2_3, ++ GAMMA_CORR_CNTLA_EXP_REGION3_NUM_SEGMENTS); ++ ++ dm_write_reg(opp110->base.ctx, ++ mmGAMMA_CORR_CNTLA_REGION_2_3, ++ value); ++ } ++ ++ curve += 2; ++ { ++ value = 0; ++ set_reg_field_value( ++ value, ++ curve[0].offset, ++ GAMMA_CORR_CNTLA_REGION_4_5, ++ GAMMA_CORR_CNTLA_EXP_REGION4_LUT_OFFSET); ++ ++ set_reg_field_value( ++ value, ++ curve[0].segments_num, ++ GAMMA_CORR_CNTLA_REGION_4_5, ++ GAMMA_CORR_CNTLA_EXP_REGION4_NUM_SEGMENTS); ++ ++ set_reg_field_value( ++ value, ++ curve[1].offset, ++ GAMMA_CORR_CNTLA_REGION_4_5, ++ GAMMA_CORR_CNTLA_EXP_REGION5_LUT_OFFSET); ++ ++ set_reg_field_value( ++ value, ++ curve[1].segments_num, ++ GAMMA_CORR_CNTLA_REGION_4_5, ++ GAMMA_CORR_CNTLA_EXP_REGION5_NUM_SEGMENTS); ++ ++ dm_write_reg(opp110->base.ctx, ++ mmGAMMA_CORR_CNTLA_REGION_4_5, ++ value); ++ } ++ ++ curve += 2; ++ { ++ value = 0; ++ set_reg_field_value( ++ value, ++ curve[0].offset, ++ GAMMA_CORR_CNTLA_REGION_6_7, ++ GAMMA_CORR_CNTLA_EXP_REGION6_LUT_OFFSET); ++ ++ set_reg_field_value( ++ value, ++ curve[0].segments_num, ++ GAMMA_CORR_CNTLA_REGION_6_7, ++ GAMMA_CORR_CNTLA_EXP_REGION6_NUM_SEGMENTS); ++ ++ set_reg_field_value( ++ value, ++ curve[1].offset, ++ GAMMA_CORR_CNTLA_REGION_6_7, ++ GAMMA_CORR_CNTLA_EXP_REGION7_LUT_OFFSET); ++ ++ set_reg_field_value( ++ value, ++ curve[1].segments_num, ++ GAMMA_CORR_CNTLA_REGION_6_7, ++ GAMMA_CORR_CNTLA_EXP_REGION7_NUM_SEGMENTS); ++ ++ dm_write_reg(opp110->base.ctx, ++ mmGAMMA_CORR_CNTLA_REGION_6_7, ++ value); ++ } ++ ++ curve += 2; ++ { ++ value = 0; ++ set_reg_field_value( ++ value, ++ curve[0].offset, ++ GAMMA_CORR_CNTLA_REGION_8_9, ++ GAMMA_CORR_CNTLA_EXP_REGION8_LUT_OFFSET); ++ ++ set_reg_field_value( ++ value, ++ curve[0].segments_num, ++ GAMMA_CORR_CNTLA_REGION_8_9, ++ GAMMA_CORR_CNTLA_EXP_REGION8_NUM_SEGMENTS); ++ ++ set_reg_field_value( ++ value, ++ curve[1].offset, ++ GAMMA_CORR_CNTLA_REGION_8_9, ++ GAMMA_CORR_CNTLA_EXP_REGION9_LUT_OFFSET); ++ ++ set_reg_field_value( ++ value, ++ curve[1].segments_num, ++ GAMMA_CORR_CNTLA_REGION_8_9, ++ GAMMA_CORR_CNTLA_EXP_REGION9_NUM_SEGMENTS); ++ ++ dm_write_reg(opp110->base.ctx, ++ mmGAMMA_CORR_CNTLA_REGION_8_9, ++ value); ++ } ++ ++ curve += 2; ++ { ++ value = 0; ++ set_reg_field_value( ++ value, ++ curve[0].offset, ++ GAMMA_CORR_CNTLA_REGION_10_11, ++ GAMMA_CORR_CNTLA_EXP_REGION10_LUT_OFFSET); ++ ++ set_reg_field_value( ++ value, ++ curve[0].segments_num, ++ GAMMA_CORR_CNTLA_REGION_10_11, ++ GAMMA_CORR_CNTLA_EXP_REGION10_NUM_SEGMENTS); ++ ++ set_reg_field_value( ++ value, ++ curve[1].offset, ++ GAMMA_CORR_CNTLA_REGION_10_11, ++ GAMMA_CORR_CNTLA_EXP_REGION11_LUT_OFFSET); ++ ++ set_reg_field_value( ++ value, ++ curve[1].segments_num, ++ GAMMA_CORR_CNTLA_REGION_10_11, ++ GAMMA_CORR_CNTLA_EXP_REGION11_NUM_SEGMENTS); ++ ++ dm_write_reg(opp110->base.ctx, ++ mmGAMMA_CORR_CNTLA_REGION_10_11, ++ value); ++ } ++ ++ curve += 2; ++ { ++ value = 0; ++ set_reg_field_value( ++ value, ++ curve[0].offset, ++ GAMMA_CORR_CNTLA_REGION_12_13, ++ GAMMA_CORR_CNTLA_EXP_REGION12_LUT_OFFSET); ++ ++ set_reg_field_value( ++ value, ++ curve[0].segments_num, ++ GAMMA_CORR_CNTLA_REGION_12_13, ++ GAMMA_CORR_CNTLA_EXP_REGION12_NUM_SEGMENTS); ++ ++ set_reg_field_value( ++ value, ++ curve[1].offset, ++ GAMMA_CORR_CNTLA_REGION_12_13, ++ GAMMA_CORR_CNTLA_EXP_REGION13_LUT_OFFSET); ++ ++ set_reg_field_value( ++ value, ++ curve[1].segments_num, ++ GAMMA_CORR_CNTLA_REGION_12_13, ++ GAMMA_CORR_CNTLA_EXP_REGION13_NUM_SEGMENTS); ++ ++ dm_write_reg(opp110->base.ctx, ++ mmGAMMA_CORR_CNTLA_REGION_12_13, ++ value); ++ } ++ ++ curve += 2; ++ { ++ value = 0; ++ set_reg_field_value( ++ value, ++ curve[0].offset, ++ GAMMA_CORR_CNTLA_REGION_14_15, ++ GAMMA_CORR_CNTLA_EXP_REGION14_LUT_OFFSET); ++ ++ set_reg_field_value( ++ value, ++ curve[0].segments_num, ++ GAMMA_CORR_CNTLA_REGION_14_15, ++ GAMMA_CORR_CNTLA_EXP_REGION14_NUM_SEGMENTS); ++ ++ set_reg_field_value( ++ value, ++ curve[1].offset, ++ GAMMA_CORR_CNTLA_REGION_14_15, ++ GAMMA_CORR_CNTLA_EXP_REGION15_LUT_OFFSET); ++ ++ set_reg_field_value( ++ value, ++ curve[1].segments_num, ++ GAMMA_CORR_CNTLA_REGION_14_15, ++ GAMMA_CORR_CNTLA_EXP_REGION15_NUM_SEGMENTS); ++ ++ dm_write_reg(opp110->base.ctx, ++ mmGAMMA_CORR_CNTLA_REGION_14_15, ++ value); ++ } ++} ++ ++static void program_pwl(struct dce110_opp *opp110, ++ const struct regamma_params *params) ++{ ++ uint32_t value = 0; ++ ++ set_reg_field_value( ++ value, ++ 7, ++ GAMMA_CORR_LUT_WRITE_EN_MASK, ++ GAMMA_CORR_LUT_WRITE_EN_MASK); ++ ++ dm_write_reg(opp110->base.ctx, ++ mmGAMMA_CORR_LUT_WRITE_EN_MASK, value); ++ ++ dm_write_reg(opp110->base.ctx, ++ mmGAMMA_CORR_LUT_INDEX, 0); ++ ++ /* Program REGAMMA_LUT_DATA */ ++ { ++ const uint32_t addr = mmGAMMA_CORR_LUT_DATA; ++ uint32_t i = 0; ++ const struct pwl_result_data *rgb = ++ params->rgb_resulted; ++ ++ while (i != params->hw_points_num) { ++ dm_write_reg(opp110->base.ctx, addr, rgb->red_reg); ++ dm_write_reg(opp110->base.ctx, addr, rgb->green_reg); ++ dm_write_reg(opp110->base.ctx, addr, rgb->blue_reg); ++ ++ 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; ++ } ++ } ++} ++ ++bool dce110_opp_set_regamma_v( ++ struct output_pixel_processor *opp, ++ const struct regamma_params *params) ++{ ++ struct dce110_opp *opp110 = TO_DCE110_OPP(opp); ++ ++ /* Setup regions */ ++ regamma_config_regions_and_segments(opp110, params); ++ ++ set_bypass_input_gamma(opp110); ++ ++ /* Power on gamma LUT memory */ ++ power_on_lut(opp, true, false, true); ++ ++ /* Program PWL */ ++ program_pwl(opp110, params); ++ ++ /* program regamma config */ ++ configure_regamma_mode(opp110, 1); ++ ++ /* Power return to auto back */ ++ power_on_lut(opp, false, false, true); ++ ++ return true; ++} ++ ++ +diff --git a/drivers/gpu/drm/amd/dal/dc/dce110/dce110_opp_v.c b/drivers/gpu/drm/amd/dal/dc/dce110/dce110_opp_v.c +new file mode 100644 +index 0000000..9764940 +--- /dev/null ++++ b/drivers/gpu/drm/amd/dal/dc/dce110/dce110_opp_v.c +@@ -0,0 +1,75 @@ ++/* ++ * 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 "dce110_opp_v.h" ++ ++#include "gamma_types.h" ++ ++/*****************************************/ ++/* Constructor, Destructor */ ++/*****************************************/ ++ ++struct opp_funcs funcs = { ++ .opp_set_regamma = dce110_opp_set_regamma_v, ++ ++ .opp_set_csc_default = dce110_opp_v_set_csc_default, ++ ++ .opp_set_csc_adjustment = dce110_opp_v_set_csc_adjustment, ++ ++ .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_dyn_expansion = dce110_opp_set_dyn_expansion, ++ .opp_destroy = dce110_opp_destroy, ++}; ++ ++bool dce110_opp_v_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; ++ ++ return true; ++} ++ ++ ++ ++ +diff --git a/drivers/gpu/drm/amd/dal/dc/dce110/dce110_opp_v.h b/drivers/gpu/drm/amd/dal/dc/dce110/dce110_opp_v.h +new file mode 100644 +index 0000000..56365aa +--- /dev/null ++++ b/drivers/gpu/drm/amd/dal/dc/dce110/dce110_opp_v.h +@@ -0,0 +1,55 @@ ++/* 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_V_H__ ++#define __DC_OPP_DCE110_V_H__ ++ ++#include "dc_types.h" ++#include "inc/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, ++ uint32_t inst, ++ const struct dce110_opp_reg_offsets *offsets); ++ ++/* underlay callbacks */ ++void dce110_opp_v_set_csc_default( ++ struct output_pixel_processor *opp, ++ const struct default_adjustment *default_adjust); ++ ++void dce110_opp_v_set_csc_adjustment( ++ struct output_pixel_processor *opp, ++ const struct grph_csc_adjustment *adjust); ++ ++bool dce110_opp_set_regamma_v( ++ struct output_pixel_processor *opp, ++ const struct regamma_params *params); ++ ++ ++#endif /* __DC_OPP_DCE110_V_H__ */ +diff --git a/drivers/gpu/drm/amd/dal/dc/dce110/dce110_resource.c b/drivers/gpu/drm/amd/dal/dc/dce110/dce110_resource.c +index 42e7306..c65f401 100644 +--- a/drivers/gpu/drm/amd/dal/dc/dce110/dce110_resource.c ++++ b/drivers/gpu/drm/amd/dal/dc/dce110/dce110_resource.c +@@ -1229,7 +1229,7 @@ audio_create_fail: + controller_create_fail: + for (i = 0; i < pool->pipe_count; i++) { + if (pool->opps[i] != NULL) +- dce110_opp_destroy(&pool->opps[i]); ++ pool->opps[i]->funcs->opp_destroy(&pool->opps[i]); + + if (pool->transforms[i] != NULL) + dce110_transform_destroy(&pool->transforms[i]); +diff --git a/drivers/gpu/drm/amd/dal/dc/inc/opp.h b/drivers/gpu/drm/amd/dal/dc/inc/opp.h +index 307184a..74dbea9 100644 +--- a/drivers/gpu/drm/amd/dal/dc/inc/opp.h ++++ b/drivers/gpu/drm/amd/dal/dc/inc/opp.h +@@ -29,6 +29,8 @@ + #include "dc_types.h" + #include "grph_object_id.h" + #include "grph_csc_types.h" ++#include "video_csc_types.h" ++#include "hw_sequencer_types.h" + + struct fixed31_32; + struct gamma_parameters; +@@ -303,6 +305,19 @@ struct opp_funcs { + enum color_space color_sp, + enum dc_color_depth color_dpth, + enum signal_type signal); ++ ++ /* underlay related */ ++ void (*opp_get_underlay_adjustment_range)( ++ struct output_pixel_processor *opp, ++ enum ovl_csc_adjust_item overlay_adjust_item, ++ struct hw_adjustment_range *range); ++ ++ void (*opp_set_ovl_csc_adjustment)( ++ struct output_pixel_processor *opp, ++ const struct ovl_csc_adjustment *adjust, ++ enum color_space c_space); ++ ++ void (*opp_destroy)(struct output_pixel_processor **opp); + }; + + #endif +-- +2.7.4 + |