cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

dcn30_dpp_cm.c (14172B)


      1/*
      2 * Copyright 2020 Advanced Micro Devices, Inc.
      3 *
      4 * Permission is hereby granted, free of charge, to any person obtaining a
      5 * copy of this software and associated documentation files (the "Software"),
      6 * to deal in the Software without restriction, including without limitation
      7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
      8 * and/or sell copies of the Software, and to permit persons to whom the
      9 * Software is furnished to do so, subject to the following conditions:
     10 *
     11 * The above copyright notice and this permission notice shall be included in
     12 * all copies or substantial portions of the Software.
     13 *
     14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
     15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
     16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
     17 * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
     18 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
     19 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
     20 * OTHER DEALINGS IN THE SOFTWARE.
     21 *
     22 * Authors: AMD
     23 *
     24 */
     25
     26#include "dm_services.h"
     27#include "core_types.h"
     28#include "reg_helper.h"
     29#include "dcn30_dpp.h"
     30#include "basics/conversion.h"
     31#include "dcn30_cm_common.h"
     32
     33#define REG(reg)\
     34	dpp->tf_regs->reg
     35
     36#define CTX \
     37	dpp->base.ctx
     38
     39#undef FN
     40#define FN(reg_name, field_name) \
     41	dpp->tf_shift->field_name, dpp->tf_mask->field_name
     42
     43static void dpp3_enable_cm_block(
     44		struct dpp *dpp_base)
     45{
     46	struct dcn3_dpp *dpp = TO_DCN30_DPP(dpp_base);
     47
     48	unsigned int cm_bypass_mode = 0;
     49
     50	// debug option: put CM in bypass mode
     51	if (dpp_base->ctx->dc->debug.cm_in_bypass)
     52		cm_bypass_mode = 1;
     53
     54	REG_UPDATE(CM_CONTROL, CM_BYPASS, cm_bypass_mode);
     55}
     56
     57static enum dc_lut_mode dpp30_get_gamcor_current(struct dpp *dpp_base)
     58{
     59	enum dc_lut_mode mode;
     60	uint32_t state_mode;
     61	uint32_t lut_mode;
     62	struct dcn3_dpp *dpp = TO_DCN30_DPP(dpp_base);
     63
     64	REG_GET(CM_GAMCOR_CONTROL,
     65			CM_GAMCOR_MODE_CURRENT, &state_mode);
     66
     67		if (state_mode == 0)
     68			mode = LUT_BYPASS;
     69
     70		if (state_mode == 2) {//Programmable RAM LUT
     71			REG_GET(CM_GAMCOR_CONTROL,
     72					CM_GAMCOR_SELECT_CURRENT, &lut_mode);
     73
     74			if (lut_mode == 0)
     75				mode = LUT_RAM_A;
     76			else
     77				mode = LUT_RAM_B;
     78		}
     79
     80		return mode;
     81}
     82
     83static void dpp3_program_gammcor_lut(
     84		struct dpp *dpp_base,
     85		const struct pwl_result_data *rgb,
     86		uint32_t num,
     87		bool is_ram_a)
     88{
     89	uint32_t i;
     90	struct dcn3_dpp *dpp = TO_DCN30_DPP(dpp_base);
     91	uint32_t last_base_value_red = rgb[num-1].red_reg + rgb[num-1].delta_red_reg;
     92	uint32_t last_base_value_green = rgb[num-1].green_reg + rgb[num-1].delta_green_reg;
     93	uint32_t last_base_value_blue = rgb[num-1].blue_reg + rgb[num-1].delta_blue_reg;
     94
     95	/*fill in the LUT with all base values to be used by pwl module
     96	 * HW auto increments the LUT index: back-to-back write
     97	 */
     98	if (is_rgb_equal(rgb,  num)) {
     99		for (i = 0 ; i < num; i++)
    100			REG_SET(CM_GAMCOR_LUT_DATA, 0, CM_GAMCOR_LUT_DATA, rgb[i].red_reg);
    101
    102		REG_SET(CM_GAMCOR_LUT_DATA, 0, CM_GAMCOR_LUT_DATA, last_base_value_red);
    103
    104	} else {
    105		REG_UPDATE(CM_GAMCOR_LUT_CONTROL,
    106				CM_GAMCOR_LUT_WRITE_COLOR_MASK, 4);
    107		for (i = 0 ; i < num; i++)
    108			REG_SET(CM_GAMCOR_LUT_DATA, 0, CM_GAMCOR_LUT_DATA, rgb[i].red_reg);
    109
    110		REG_SET(CM_GAMCOR_LUT_DATA, 0, CM_GAMCOR_LUT_DATA, last_base_value_red);
    111
    112		REG_SET(CM_GAMCOR_LUT_INDEX, 0, CM_GAMCOR_LUT_INDEX, 0);
    113
    114		REG_UPDATE(CM_GAMCOR_LUT_CONTROL,
    115				CM_GAMCOR_LUT_WRITE_COLOR_MASK, 2);
    116		for (i = 0 ; i < num; i++)
    117			REG_SET(CM_GAMCOR_LUT_DATA, 0, CM_GAMCOR_LUT_DATA, rgb[i].green_reg);
    118
    119		REG_SET(CM_GAMCOR_LUT_DATA, 0, CM_GAMCOR_LUT_DATA, last_base_value_green);
    120
    121		REG_SET(CM_GAMCOR_LUT_INDEX, 0, CM_GAMCOR_LUT_INDEX, 0);
    122
    123		REG_UPDATE(CM_GAMCOR_LUT_CONTROL,
    124				CM_GAMCOR_LUT_WRITE_COLOR_MASK, 1);
    125		for (i = 0 ; i < num; i++)
    126			REG_SET(CM_GAMCOR_LUT_DATA, 0, CM_GAMCOR_LUT_DATA, rgb[i].blue_reg);
    127
    128		REG_SET(CM_GAMCOR_LUT_DATA, 0, CM_GAMCOR_LUT_DATA, last_base_value_blue);
    129	}
    130}
    131
    132static void dpp3_power_on_gamcor_lut(
    133		struct dpp *dpp_base,
    134	bool power_on)
    135{
    136	struct dcn3_dpp *dpp = TO_DCN30_DPP(dpp_base);
    137
    138	if (dpp_base->ctx->dc->debug.enable_mem_low_power.bits.cm) {
    139		if (power_on) {
    140			REG_UPDATE(CM_MEM_PWR_CTRL, GAMCOR_MEM_PWR_FORCE, 0);
    141			REG_WAIT(CM_MEM_PWR_STATUS, GAMCOR_MEM_PWR_STATE, 0, 1, 5);
    142		} else {
    143			dpp_base->ctx->dc->optimized_required = true;
    144			dpp_base->deferred_reg_writes.bits.disable_gamcor = true;
    145		}
    146	} else
    147		REG_SET(CM_MEM_PWR_CTRL, 0,
    148				GAMCOR_MEM_PWR_DIS, power_on == true ? 0:1);
    149}
    150
    151void dpp3_program_cm_dealpha(
    152		struct dpp *dpp_base,
    153	uint32_t enable, uint32_t additive_blending)
    154{
    155	struct dcn3_dpp *dpp = TO_DCN30_DPP(dpp_base);
    156
    157	REG_SET_2(CM_DEALPHA, 0,
    158			CM_DEALPHA_EN, enable,
    159			CM_DEALPHA_ABLND, additive_blending);
    160}
    161
    162void dpp3_program_cm_bias(
    163	struct dpp *dpp_base,
    164	struct CM_bias_params *bias_params)
    165{
    166	struct dcn3_dpp *dpp = TO_DCN30_DPP(dpp_base);
    167
    168	REG_SET(CM_BIAS_CR_R, 0, CM_BIAS_CR_R, bias_params->cm_bias_cr_r);
    169	REG_SET_2(CM_BIAS_Y_G_CB_B, 0,
    170			CM_BIAS_Y_G, bias_params->cm_bias_y_g,
    171			CM_BIAS_CB_B, bias_params->cm_bias_cb_b);
    172}
    173
    174static void dpp3_gamcor_reg_field(
    175		struct dcn3_dpp *dpp,
    176		struct dcn3_xfer_func_reg *reg)
    177{
    178
    179	reg->shifts.field_region_start_base = dpp->tf_shift->CM_GAMCOR_RAMA_EXP_REGION_START_BASE_B;
    180	reg->masks.field_region_start_base = dpp->tf_mask->CM_GAMCOR_RAMA_EXP_REGION_START_BASE_B;
    181	reg->shifts.field_offset = dpp->tf_shift->CM_GAMCOR_RAMA_OFFSET_B;
    182	reg->masks.field_offset = dpp->tf_mask->CM_GAMCOR_RAMA_OFFSET_B;
    183
    184	reg->shifts.exp_region0_lut_offset = dpp->tf_shift->CM_GAMCOR_RAMA_EXP_REGION0_LUT_OFFSET;
    185	reg->masks.exp_region0_lut_offset = dpp->tf_mask->CM_GAMCOR_RAMA_EXP_REGION0_LUT_OFFSET;
    186	reg->shifts.exp_region0_num_segments = dpp->tf_shift->CM_GAMCOR_RAMA_EXP_REGION0_NUM_SEGMENTS;
    187	reg->masks.exp_region0_num_segments = dpp->tf_mask->CM_GAMCOR_RAMA_EXP_REGION0_NUM_SEGMENTS;
    188	reg->shifts.exp_region1_lut_offset = dpp->tf_shift->CM_GAMCOR_RAMA_EXP_REGION1_LUT_OFFSET;
    189	reg->masks.exp_region1_lut_offset = dpp->tf_mask->CM_GAMCOR_RAMA_EXP_REGION1_LUT_OFFSET;
    190	reg->shifts.exp_region1_num_segments = dpp->tf_shift->CM_GAMCOR_RAMA_EXP_REGION1_NUM_SEGMENTS;
    191	reg->masks.exp_region1_num_segments = dpp->tf_mask->CM_GAMCOR_RAMA_EXP_REGION1_NUM_SEGMENTS;
    192
    193	reg->shifts.field_region_end = dpp->tf_shift->CM_GAMCOR_RAMA_EXP_REGION_END_B;
    194	reg->masks.field_region_end = dpp->tf_mask->CM_GAMCOR_RAMA_EXP_REGION_END_B;
    195	reg->shifts.field_region_end_slope = dpp->tf_shift->CM_GAMCOR_RAMA_EXP_REGION_END_SLOPE_B;
    196	reg->masks.field_region_end_slope = dpp->tf_mask->CM_GAMCOR_RAMA_EXP_REGION_END_SLOPE_B;
    197	reg->shifts.field_region_end_base = dpp->tf_shift->CM_GAMCOR_RAMA_EXP_REGION_END_BASE_B;
    198	reg->masks.field_region_end_base = dpp->tf_mask->CM_GAMCOR_RAMA_EXP_REGION_END_BASE_B;
    199	reg->shifts.field_region_linear_slope = dpp->tf_shift->CM_GAMCOR_RAMA_EXP_REGION_START_SLOPE_B;
    200	reg->masks.field_region_linear_slope = dpp->tf_mask->CM_GAMCOR_RAMA_EXP_REGION_START_SLOPE_B;
    201	reg->shifts.exp_region_start = dpp->tf_shift->CM_GAMCOR_RAMA_EXP_REGION_START_B;
    202	reg->masks.exp_region_start = dpp->tf_mask->CM_GAMCOR_RAMA_EXP_REGION_START_B;
    203	reg->shifts.exp_resion_start_segment = dpp->tf_shift->CM_GAMCOR_RAMA_EXP_REGION_START_SEGMENT_B;
    204	reg->masks.exp_resion_start_segment = dpp->tf_mask->CM_GAMCOR_RAMA_EXP_REGION_START_SEGMENT_B;
    205}
    206
    207static void dpp3_configure_gamcor_lut(
    208		struct dpp *dpp_base,
    209		bool is_ram_a)
    210{
    211	struct dcn3_dpp *dpp = TO_DCN30_DPP(dpp_base);
    212
    213	REG_UPDATE(CM_GAMCOR_LUT_CONTROL,
    214			CM_GAMCOR_LUT_WRITE_COLOR_MASK, 7);
    215	REG_UPDATE(CM_GAMCOR_LUT_CONTROL,
    216			CM_GAMCOR_LUT_HOST_SEL, is_ram_a == true ? 0:1);
    217	REG_SET(CM_GAMCOR_LUT_INDEX, 0, CM_GAMCOR_LUT_INDEX, 0);
    218}
    219
    220
    221bool dpp3_program_gamcor_lut(
    222	struct dpp *dpp_base, const struct pwl_params *params)
    223{
    224	enum dc_lut_mode current_mode;
    225	enum dc_lut_mode next_mode;
    226	struct dcn3_dpp *dpp = TO_DCN30_DPP(dpp_base);
    227	struct dcn3_xfer_func_reg gam_regs;
    228
    229	dpp3_enable_cm_block(dpp_base);
    230
    231	if (params == NULL) { //bypass if we have no pwl data
    232		REG_SET(CM_GAMCOR_CONTROL, 0, CM_GAMCOR_MODE, 0);
    233		if (dpp_base->ctx->dc->debug.enable_mem_low_power.bits.cm)
    234			dpp3_power_on_gamcor_lut(dpp_base, false);
    235		return false;
    236	}
    237	dpp3_power_on_gamcor_lut(dpp_base, true);
    238	REG_SET(CM_GAMCOR_CONTROL, 0, CM_GAMCOR_MODE, 2);
    239
    240	current_mode = dpp30_get_gamcor_current(dpp_base);
    241	if (current_mode == LUT_BYPASS || current_mode == LUT_RAM_A)
    242		next_mode = LUT_RAM_B;
    243	else
    244		next_mode = LUT_RAM_A;
    245
    246	dpp3_power_on_gamcor_lut(dpp_base, true);
    247	dpp3_configure_gamcor_lut(dpp_base, next_mode == LUT_RAM_A);
    248
    249	if (next_mode == LUT_RAM_B) {
    250		gam_regs.start_cntl_b = REG(CM_GAMCOR_RAMB_START_CNTL_B);
    251		gam_regs.start_cntl_g = REG(CM_GAMCOR_RAMB_START_CNTL_G);
    252		gam_regs.start_cntl_r = REG(CM_GAMCOR_RAMB_START_CNTL_R);
    253		gam_regs.start_slope_cntl_b = REG(CM_GAMCOR_RAMB_START_SLOPE_CNTL_B);
    254		gam_regs.start_slope_cntl_g = REG(CM_GAMCOR_RAMB_START_SLOPE_CNTL_G);
    255		gam_regs.start_slope_cntl_r = REG(CM_GAMCOR_RAMB_START_SLOPE_CNTL_R);
    256		gam_regs.start_end_cntl1_b = REG(CM_GAMCOR_RAMB_END_CNTL1_B);
    257		gam_regs.start_end_cntl2_b = REG(CM_GAMCOR_RAMB_END_CNTL2_B);
    258		gam_regs.start_end_cntl1_g = REG(CM_GAMCOR_RAMB_END_CNTL1_G);
    259		gam_regs.start_end_cntl2_g = REG(CM_GAMCOR_RAMB_END_CNTL2_G);
    260		gam_regs.start_end_cntl1_r = REG(CM_GAMCOR_RAMB_END_CNTL1_R);
    261		gam_regs.start_end_cntl2_r = REG(CM_GAMCOR_RAMB_END_CNTL2_R);
    262		gam_regs.region_start = REG(CM_GAMCOR_RAMB_REGION_0_1);
    263		gam_regs.region_end = REG(CM_GAMCOR_RAMB_REGION_32_33);
    264		//New registers in DCN3AG/DCN GAMCOR block
    265		gam_regs.offset_b =  REG(CM_GAMCOR_RAMB_OFFSET_B);
    266		gam_regs.offset_g =  REG(CM_GAMCOR_RAMB_OFFSET_G);
    267		gam_regs.offset_r =  REG(CM_GAMCOR_RAMB_OFFSET_R);
    268		gam_regs.start_base_cntl_b = REG(CM_GAMCOR_RAMB_START_BASE_CNTL_B);
    269		gam_regs.start_base_cntl_g = REG(CM_GAMCOR_RAMB_START_BASE_CNTL_G);
    270		gam_regs.start_base_cntl_r = REG(CM_GAMCOR_RAMB_START_BASE_CNTL_R);
    271	} else {
    272		gam_regs.start_cntl_b = REG(CM_GAMCOR_RAMA_START_CNTL_B);
    273		gam_regs.start_cntl_g = REG(CM_GAMCOR_RAMA_START_CNTL_G);
    274		gam_regs.start_cntl_r = REG(CM_GAMCOR_RAMA_START_CNTL_R);
    275		gam_regs.start_slope_cntl_b = REG(CM_GAMCOR_RAMA_START_SLOPE_CNTL_B);
    276		gam_regs.start_slope_cntl_g = REG(CM_GAMCOR_RAMA_START_SLOPE_CNTL_G);
    277		gam_regs.start_slope_cntl_r = REG(CM_GAMCOR_RAMA_START_SLOPE_CNTL_R);
    278		gam_regs.start_end_cntl1_b = REG(CM_GAMCOR_RAMA_END_CNTL1_B);
    279		gam_regs.start_end_cntl2_b = REG(CM_GAMCOR_RAMA_END_CNTL2_B);
    280		gam_regs.start_end_cntl1_g = REG(CM_GAMCOR_RAMA_END_CNTL1_G);
    281		gam_regs.start_end_cntl2_g = REG(CM_GAMCOR_RAMA_END_CNTL2_G);
    282		gam_regs.start_end_cntl1_r = REG(CM_GAMCOR_RAMA_END_CNTL1_R);
    283		gam_regs.start_end_cntl2_r = REG(CM_GAMCOR_RAMA_END_CNTL2_R);
    284		gam_regs.region_start = REG(CM_GAMCOR_RAMA_REGION_0_1);
    285		gam_regs.region_end = REG(CM_GAMCOR_RAMA_REGION_32_33);
    286		//New registers in DCN3AG/DCN GAMCOR block
    287		gam_regs.offset_b =  REG(CM_GAMCOR_RAMA_OFFSET_B);
    288		gam_regs.offset_g =  REG(CM_GAMCOR_RAMA_OFFSET_G);
    289		gam_regs.offset_r =  REG(CM_GAMCOR_RAMA_OFFSET_R);
    290		gam_regs.start_base_cntl_b = REG(CM_GAMCOR_RAMA_START_BASE_CNTL_B);
    291		gam_regs.start_base_cntl_g = REG(CM_GAMCOR_RAMA_START_BASE_CNTL_G);
    292		gam_regs.start_base_cntl_r = REG(CM_GAMCOR_RAMA_START_BASE_CNTL_R);
    293	}
    294
    295	//get register fields
    296	dpp3_gamcor_reg_field(dpp, &gam_regs);
    297
    298	//program register set for LUTA/LUTB
    299	cm_helper_program_gamcor_xfer_func(dpp_base->ctx, params, &gam_regs);
    300
    301	dpp3_program_gammcor_lut(dpp_base, params->rgb_resulted, params->hw_points_num,
    302				 next_mode == LUT_RAM_A);
    303
    304	//select Gamma LUT to use for next frame
    305	REG_UPDATE(CM_GAMCOR_CONTROL, CM_GAMCOR_SELECT, next_mode == LUT_RAM_A ? 0:1);
    306
    307	return true;
    308}
    309
    310void dpp3_set_hdr_multiplier(
    311		struct dpp *dpp_base,
    312		uint32_t multiplier)
    313{
    314	struct dcn3_dpp *dpp = TO_DCN30_DPP(dpp_base);
    315
    316	REG_UPDATE(CM_HDR_MULT_COEF, CM_HDR_MULT_COEF, multiplier);
    317}
    318
    319
    320static void program_gamut_remap(
    321		struct dcn3_dpp *dpp,
    322		const uint16_t *regval,
    323		int select)
    324{
    325	uint16_t selection = 0;
    326	struct color_matrices_reg gam_regs;
    327
    328	if (regval == NULL || select == GAMUT_REMAP_BYPASS) {
    329		REG_SET(CM_GAMUT_REMAP_CONTROL, 0,
    330				CM_GAMUT_REMAP_MODE, 0);
    331		return;
    332	}
    333	switch (select) {
    334	case GAMUT_REMAP_COEFF:
    335		selection = 1;
    336		break;
    337		/*this corresponds to GAMUT_REMAP coefficients set B
    338		 *we don't have common coefficient sets in dcn3ag/dcn3
    339		 */
    340	case GAMUT_REMAP_COMA_COEFF:
    341		selection = 2;
    342		break;
    343	default:
    344		break;
    345	}
    346
    347	gam_regs.shifts.csc_c11 = dpp->tf_shift->CM_GAMUT_REMAP_C11;
    348	gam_regs.masks.csc_c11  = dpp->tf_mask->CM_GAMUT_REMAP_C11;
    349	gam_regs.shifts.csc_c12 = dpp->tf_shift->CM_GAMUT_REMAP_C12;
    350	gam_regs.masks.csc_c12 = dpp->tf_mask->CM_GAMUT_REMAP_C12;
    351
    352
    353	if (select == GAMUT_REMAP_COEFF) {
    354		gam_regs.csc_c11_c12 = REG(CM_GAMUT_REMAP_C11_C12);
    355		gam_regs.csc_c33_c34 = REG(CM_GAMUT_REMAP_C33_C34);
    356
    357		cm_helper_program_color_matrices(
    358				dpp->base.ctx,
    359				regval,
    360				&gam_regs);
    361
    362	} else  if (select == GAMUT_REMAP_COMA_COEFF) {
    363
    364		gam_regs.csc_c11_c12 = REG(CM_GAMUT_REMAP_B_C11_C12);
    365		gam_regs.csc_c33_c34 = REG(CM_GAMUT_REMAP_B_C33_C34);
    366
    367		cm_helper_program_color_matrices(
    368				dpp->base.ctx,
    369				regval,
    370				&gam_regs);
    371
    372	}
    373	//select coefficient set to use
    374	REG_SET(
    375			CM_GAMUT_REMAP_CONTROL, 0,
    376			CM_GAMUT_REMAP_MODE, selection);
    377}
    378
    379void dpp3_cm_set_gamut_remap(
    380	struct dpp *dpp_base,
    381	const struct dpp_grph_csc_adjustment *adjust)
    382{
    383	struct dcn3_dpp *dpp = TO_DCN30_DPP(dpp_base);
    384	int i = 0;
    385	int gamut_mode;
    386
    387	if (adjust->gamut_adjust_type != GRAPHICS_GAMUT_ADJUST_TYPE_SW)
    388		/* Bypass if type is bypass or hw */
    389		program_gamut_remap(dpp, NULL, GAMUT_REMAP_BYPASS);
    390	else {
    391		struct fixed31_32 arr_matrix[12];
    392		uint16_t arr_reg_val[12];
    393
    394		for (i = 0; i < 12; i++)
    395			arr_matrix[i] = adjust->temperature_matrix[i];
    396
    397		convert_float_matrix(
    398			arr_reg_val, arr_matrix, 12);
    399
    400		//current coefficient set in use
    401		REG_GET(CM_GAMUT_REMAP_CONTROL, CM_GAMUT_REMAP_MODE_CURRENT, &gamut_mode);
    402
    403		if (gamut_mode == 0)
    404			gamut_mode = 1; //use coefficient set A
    405		else if (gamut_mode == 1)
    406			gamut_mode = 2;
    407		else
    408			gamut_mode = 1;
    409
    410		//follow dcn2 approach for now - using only coefficient set A
    411		program_gamut_remap(dpp, arr_reg_val, gamut_mode);
    412	}
    413}