From 4330564057ab3f66dd1d72284d99f15208b5c474 Mon Sep 17 00:00:00 2001 From: Yongqiang Sun Date: Tue, 9 Feb 2016 16:47:42 -0500 Subject: [PATCH 0791/1110] drm/amd/dal: opp for underlay. Signed-off-by: Yongqiang Sun Acked-by: Harry Wentland --- 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