diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-07 18:49:45 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-07 18:49:45 +0000 |
commit | 2c3c1048746a4622d8c89a29670120dc8fab93c4 (patch) | |
tree | 848558de17fb3008cdf4d861b01ac7781903ce39 /drivers/gpu/drm/amd/display/dc/dcn30 | |
parent | Initial commit. (diff) | |
download | linux-2c3c1048746a4622d8c89a29670120dc8fab93c4.tar.xz linux-2c3c1048746a4622d8c89a29670120dc8fab93c4.zip |
Adding upstream version 6.1.76.upstream/6.1.76
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'drivers/gpu/drm/amd/display/dc/dcn30')
36 files changed, 16897 insertions, 0 deletions
diff --git a/drivers/gpu/drm/amd/display/dc/dcn30/Makefile b/drivers/gpu/drm/amd/display/dc/dcn30/Makefile new file mode 100644 index 000000000..b7c2ae9dd --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/dcn30/Makefile @@ -0,0 +1,35 @@ +# +# Copyright 2020 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 +# +# + + +DCN30 = dcn30_init.o dcn30_hubbub.o dcn30_hubp.o dcn30_dpp.o dcn30_optc.o \ + dcn30_dccg.o dcn30_hwseq.o dcn30_mpc.o dcn30_vpg.o \ + dcn30_afmt.o dcn30_dio_stream_encoder.o dcn30_dwb.o \ + dcn30_dpp_cm.o dcn30_dwb_cm.o dcn30_cm_common.o dcn30_mmhubbub.o \ + dcn30_dio_link_encoder.o dcn30_resource.o + +AMD_DAL_DCN30 = $(addprefix $(AMDDALPATH)/dc/dcn30/,$(DCN30)) + +AMD_DISPLAY_FILES += $(AMD_DAL_DCN30) diff --git a/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_afmt.c b/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_afmt.c new file mode 100644 index 000000000..95528e5ef --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_afmt.c @@ -0,0 +1,217 @@ +/* + * Copyright 2020 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 "dc_bios_types.h" +#include "hw_shared.h" +#include "dcn30_afmt.h" +#include "reg_helper.h" + +#define DC_LOGGER \ + afmt3->base.ctx->logger + +#define REG(reg)\ + (afmt3->regs->reg) + +#undef FN +#define FN(reg_name, field_name) \ + afmt3->afmt_shift->field_name, afmt3->afmt_mask->field_name + + +#define CTX \ + afmt3->base.ctx + + +void afmt3_setup_hdmi_audio( + struct afmt *afmt) +{ + struct dcn30_afmt *afmt3 = DCN30_AFMT_FROM_AFMT(afmt); + + if (afmt->funcs->afmt_poweron) + afmt->funcs->afmt_poweron(afmt); + + /* AFMT_AUDIO_PACKET_CONTROL */ + REG_UPDATE(AFMT_AUDIO_PACKET_CONTROL, AFMT_60958_CS_UPDATE, 1); + + /* AFMT_AUDIO_PACKET_CONTROL2 */ + REG_UPDATE_2(AFMT_AUDIO_PACKET_CONTROL2, + AFMT_AUDIO_LAYOUT_OVRD, 0, + AFMT_60958_OSF_OVRD, 0); + + /* AFMT_60958_0__AFMT_60958_CS_CHANNEL_NUMBER_L_MASK & + * AFMT_60958_0__AFMT_60958_CS_CLOCK_ACCURACY_MASK + */ + REG_UPDATE_2(AFMT_60958_0, + AFMT_60958_CS_CHANNEL_NUMBER_L, 1, + AFMT_60958_CS_CLOCK_ACCURACY, 0); + + /* AFMT_60958_1 AFMT_60958_CS_CHALNNEL_NUMBER_R */ + REG_UPDATE(AFMT_60958_1, AFMT_60958_CS_CHANNEL_NUMBER_R, 2); + + /* AFMT_60958_2 now keep this settings until + * Programming guide comes out + */ + REG_UPDATE_6(AFMT_60958_2, + AFMT_60958_CS_CHANNEL_NUMBER_2, 3, + AFMT_60958_CS_CHANNEL_NUMBER_3, 4, + AFMT_60958_CS_CHANNEL_NUMBER_4, 5, + AFMT_60958_CS_CHANNEL_NUMBER_5, 6, + AFMT_60958_CS_CHANNEL_NUMBER_6, 7, + AFMT_60958_CS_CHANNEL_NUMBER_7, 8); +} + +static union audio_cea_channels speakers_to_channels( + struct audio_speaker_flags speaker_flags) +{ + union audio_cea_channels cea_channels = {0}; + + /* these are one to one */ + cea_channels.channels.FL = speaker_flags.FL_FR; + cea_channels.channels.FR = speaker_flags.FL_FR; + cea_channels.channels.LFE = speaker_flags.LFE; + cea_channels.channels.FC = speaker_flags.FC; + + /* if Rear Left and Right exist move RC speaker to channel 7 + * otherwise to channel 5 + */ + if (speaker_flags.RL_RR) { + cea_channels.channels.RL_RC = speaker_flags.RL_RR; + cea_channels.channels.RR = speaker_flags.RL_RR; + cea_channels.channels.RC_RLC_FLC = speaker_flags.RC; + } else { + cea_channels.channels.RL_RC = speaker_flags.RC; + } + + /* FRONT Left Right Center and REAR Left Right Center are exclusive */ + if (speaker_flags.FLC_FRC) { + cea_channels.channels.RC_RLC_FLC = speaker_flags.FLC_FRC; + cea_channels.channels.RRC_FRC = speaker_flags.FLC_FRC; + } else { + cea_channels.channels.RC_RLC_FLC = speaker_flags.RLC_RRC; + cea_channels.channels.RRC_FRC = speaker_flags.RLC_RRC; + } + + return cea_channels; +} + +void afmt3_se_audio_setup( + struct afmt *afmt, + unsigned int az_inst, + struct audio_info *audio_info) +{ + struct dcn30_afmt *afmt3 = DCN30_AFMT_FROM_AFMT(afmt); + + uint32_t speakers = 0; + uint32_t channels = 0; + + ASSERT(audio_info); + /* This should not happen.it does so we don't get BSOD*/ + if (audio_info == NULL) + return; + + speakers = audio_info->flags.info.ALLSPEAKERS; + channels = speakers_to_channels(audio_info->flags.speaker_flags).all; + + /* setup the audio stream source select (audio -> dig mapping) */ + REG_SET(AFMT_AUDIO_SRC_CONTROL, 0, AFMT_AUDIO_SRC_SELECT, az_inst); + + /* Channel allocation */ + REG_UPDATE(AFMT_AUDIO_PACKET_CONTROL2, AFMT_AUDIO_CHANNEL_ENABLE, channels); + + /* Disable forced mem power off */ + if (afmt->funcs->afmt_poweron == NULL) + REG_UPDATE(AFMT_MEM_PWR, AFMT_MEM_PWR_FORCE, 0); +} + +void afmt3_audio_mute_control( + struct afmt *afmt, + bool mute) +{ + struct dcn30_afmt *afmt3 = DCN30_AFMT_FROM_AFMT(afmt); + if (mute && afmt->funcs->afmt_powerdown) + afmt->funcs->afmt_powerdown(afmt); + if (!mute && afmt->funcs->afmt_poweron) + afmt->funcs->afmt_poweron(afmt); + /* enable/disable transmission of audio packets */ + REG_UPDATE(AFMT_AUDIO_PACKET_CONTROL, AFMT_AUDIO_SAMPLE_SEND, !mute); +} + +void afmt3_audio_info_immediate_update( + struct afmt *afmt) +{ + struct dcn30_afmt *afmt3 = DCN30_AFMT_FROM_AFMT(afmt); + + /* update double-buffered AUDIO_INFO registers immediately */ + REG_UPDATE(AFMT_INFOFRAME_CONTROL0, AFMT_AUDIO_INFO_UPDATE, 1); +} + +void afmt3_setup_dp_audio( + struct afmt *afmt) +{ + struct dcn30_afmt *afmt3 = DCN30_AFMT_FROM_AFMT(afmt); + + if (afmt->funcs->afmt_poweron) + afmt->funcs->afmt_poweron(afmt); + + /* AFMT_AUDIO_PACKET_CONTROL */ + REG_UPDATE(AFMT_AUDIO_PACKET_CONTROL, AFMT_60958_CS_UPDATE, 1); + + /* AFMT_AUDIO_PACKET_CONTROL2 */ + /* Program the ATP and AIP next */ + REG_UPDATE_2(AFMT_AUDIO_PACKET_CONTROL2, + AFMT_AUDIO_LAYOUT_OVRD, 0, + AFMT_60958_OSF_OVRD, 0); + + /* AFMT_INFOFRAME_CONTROL0 */ + REG_UPDATE(AFMT_INFOFRAME_CONTROL0, AFMT_AUDIO_INFO_UPDATE, 1); + + /* AFMT_60958_0__AFMT_60958_CS_CLOCK_ACCURACY_MASK */ + REG_UPDATE(AFMT_60958_0, AFMT_60958_CS_CLOCK_ACCURACY, 0); +} + +static struct afmt_funcs dcn30_afmt_funcs = { + .setup_hdmi_audio = afmt3_setup_hdmi_audio, + .se_audio_setup = afmt3_se_audio_setup, + .audio_mute_control = afmt3_audio_mute_control, + .audio_info_immediate_update = afmt3_audio_info_immediate_update, + .setup_dp_audio = afmt3_setup_dp_audio, +}; + +void afmt3_construct(struct dcn30_afmt *afmt3, + struct dc_context *ctx, + uint32_t inst, + const struct dcn30_afmt_registers *afmt_regs, + const struct dcn30_afmt_shift *afmt_shift, + const struct dcn30_afmt_mask *afmt_mask) +{ + afmt3->base.ctx = ctx; + + afmt3->base.inst = inst; + afmt3->base.funcs = &dcn30_afmt_funcs; + + afmt3->regs = afmt_regs; + afmt3->afmt_shift = afmt_shift; + afmt3->afmt_mask = afmt_mask; +} diff --git a/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_afmt.h b/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_afmt.h new file mode 100644 index 000000000..97e0cf62f --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_afmt.h @@ -0,0 +1,171 @@ +/* + * Copyright 2020 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 __DAL_DCN30_AFMT_H__ +#define __DAL_DCN30_AFMT_H__ + + +#define DCN30_AFMT_FROM_AFMT(afmt)\ + container_of(afmt, struct dcn30_afmt, base) + +#define AFMT_DCN3_REG_LIST(id) \ + SRI(AFMT_INFOFRAME_CONTROL0, AFMT, id), \ + SRI(AFMT_VBI_PACKET_CONTROL, AFMT, id), \ + SRI(AFMT_AUDIO_PACKET_CONTROL, AFMT, id), \ + SRI(AFMT_AUDIO_PACKET_CONTROL2, AFMT, id), \ + SRI(AFMT_AUDIO_SRC_CONTROL, AFMT, id), \ + SRI(AFMT_60958_0, AFMT, id), \ + SRI(AFMT_60958_1, AFMT, id), \ + SRI(AFMT_60958_2, AFMT, id), \ + SRI(AFMT_MEM_PWR, AFMT, id) + +struct dcn30_afmt_registers { + uint32_t AFMT_INFOFRAME_CONTROL0; + uint32_t AFMT_VBI_PACKET_CONTROL; + uint32_t AFMT_AUDIO_PACKET_CONTROL; + uint32_t AFMT_AUDIO_PACKET_CONTROL2; + uint32_t AFMT_AUDIO_SRC_CONTROL; + uint32_t AFMT_60958_0; + uint32_t AFMT_60958_1; + uint32_t AFMT_60958_2; + uint32_t AFMT_MEM_PWR; +}; + +#define DCN3_AFMT_MASK_SH_LIST(mask_sh)\ + SE_SF(AFMT0_AFMT_INFOFRAME_CONTROL0, AFMT_AUDIO_INFO_UPDATE, mask_sh),\ + SE_SF(AFMT0_AFMT_AUDIO_SRC_CONTROL, AFMT_AUDIO_SRC_SELECT, mask_sh),\ + SE_SF(AFMT0_AFMT_AUDIO_PACKET_CONTROL2, AFMT_AUDIO_CHANNEL_ENABLE, mask_sh),\ + SE_SF(AFMT0_AFMT_AUDIO_PACKET_CONTROL, AFMT_60958_CS_UPDATE, mask_sh),\ + SE_SF(AFMT0_AFMT_AUDIO_PACKET_CONTROL2, AFMT_AUDIO_LAYOUT_OVRD, mask_sh),\ + SE_SF(AFMT0_AFMT_AUDIO_PACKET_CONTROL2, AFMT_60958_OSF_OVRD, mask_sh),\ + SE_SF(AFMT0_AFMT_60958_0, AFMT_60958_CS_CHANNEL_NUMBER_L, mask_sh),\ + SE_SF(AFMT0_AFMT_60958_0, AFMT_60958_CS_CLOCK_ACCURACY, mask_sh),\ + SE_SF(AFMT0_AFMT_60958_1, AFMT_60958_CS_CHANNEL_NUMBER_R, mask_sh),\ + SE_SF(AFMT0_AFMT_60958_2, AFMT_60958_CS_CHANNEL_NUMBER_2, mask_sh),\ + SE_SF(AFMT0_AFMT_60958_2, AFMT_60958_CS_CHANNEL_NUMBER_3, mask_sh),\ + SE_SF(AFMT0_AFMT_60958_2, AFMT_60958_CS_CHANNEL_NUMBER_4, mask_sh),\ + SE_SF(AFMT0_AFMT_60958_2, AFMT_60958_CS_CHANNEL_NUMBER_5, mask_sh),\ + SE_SF(AFMT0_AFMT_60958_2, AFMT_60958_CS_CHANNEL_NUMBER_6, mask_sh),\ + SE_SF(AFMT0_AFMT_60958_2, AFMT_60958_CS_CHANNEL_NUMBER_7, mask_sh),\ + SE_SF(AFMT0_AFMT_AUDIO_PACKET_CONTROL, AFMT_AUDIO_SAMPLE_SEND, mask_sh),\ + SE_SF(AFMT0_AFMT_MEM_PWR, AFMT_MEM_PWR_FORCE, mask_sh) + +#define AFMT_DCN3_REG_FIELD_LIST(type) \ + type AFMT_AUDIO_INFO_UPDATE;\ + type AFMT_AUDIO_SRC_SELECT;\ + type AFMT_AUDIO_CHANNEL_ENABLE;\ + type AFMT_60958_CS_UPDATE;\ + type AFMT_AUDIO_LAYOUT_OVRD;\ + type AFMT_60958_OSF_OVRD;\ + type AFMT_60958_CS_CHANNEL_NUMBER_L;\ + type AFMT_60958_CS_CLOCK_ACCURACY;\ + type AFMT_60958_CS_CHANNEL_NUMBER_R;\ + type AFMT_60958_CS_CHANNEL_NUMBER_2;\ + type AFMT_60958_CS_CHANNEL_NUMBER_3;\ + type AFMT_60958_CS_CHANNEL_NUMBER_4;\ + type AFMT_60958_CS_CHANNEL_NUMBER_5;\ + type AFMT_60958_CS_CHANNEL_NUMBER_6;\ + type AFMT_60958_CS_CHANNEL_NUMBER_7;\ + type AFMT_AUDIO_SAMPLE_SEND;\ + type AFMT_MEM_PWR_FORCE + +struct dcn30_afmt_shift { + AFMT_DCN3_REG_FIELD_LIST(uint8_t); +}; + +struct dcn30_afmt_mask { + AFMT_DCN3_REG_FIELD_LIST(uint32_t); +}; + + +struct afmt; + +struct afmt_funcs { + + void (*setup_hdmi_audio)( + struct afmt *afmt); + + void (*se_audio_setup)( + struct afmt *afmt, + unsigned int az_inst, + struct audio_info *audio_info); + + void (*audio_mute_control)( + struct afmt *afmt, + bool mute); + + void (*audio_info_immediate_update)( + struct afmt *afmt); + + void (*setup_dp_audio)( + struct afmt *afmt); + + void (*afmt_poweron)( + struct afmt *afmt); + + void (*afmt_powerdown)( + struct afmt *afmt); +}; + +struct afmt { + const struct afmt_funcs *funcs; + struct dc_context *ctx; + int inst; +}; + +struct dcn30_afmt { + struct afmt base; + const struct dcn30_afmt_registers *regs; + const struct dcn30_afmt_shift *afmt_shift; + const struct dcn30_afmt_mask *afmt_mask; +}; + +void afmt3_setup_hdmi_audio( + struct afmt *afmt); + +void afmt3_se_audio_setup( + struct afmt *afmt, + unsigned int az_inst, + struct audio_info *audio_info); + +void afmt3_audio_mute_control( + struct afmt *afmt, + bool mute); + +void afmt3_audio_info_immediate_update( + struct afmt *afmt); + +void afmt3_setup_dp_audio( + struct afmt *afmt); + +void afmt3_construct(struct dcn30_afmt *afmt3, + struct dc_context *ctx, + uint32_t inst, + const struct dcn30_afmt_registers *afmt_regs, + const struct dcn30_afmt_shift *afmt_shift, + const struct dcn30_afmt_mask *afmt_mask); + + +#endif diff --git a/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_cm_common.c b/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_cm_common.c new file mode 100644 index 000000000..e0df9b006 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_cm_common.c @@ -0,0 +1,646 @@ +/* + * Copyright 2020 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 "core_types.h" +#include "reg_helper.h" +#include "dcn30_dpp.h" +#include "basics/conversion.h" +#include "dcn30_cm_common.h" +#include "custom_float.h" + +#define REG(reg) reg + +#define CTX \ + ctx //dpp->base.ctx + +#undef FN +#define FN(reg_name, field_name) \ + reg->shifts.field_name, reg->masks.field_name + +void cm_helper_program_gamcor_xfer_func( + struct dc_context *ctx, + const struct pwl_params *params, + const struct dcn3_xfer_func_reg *reg) +{ + uint32_t reg_region_cur; + unsigned int i = 0; + + REG_SET_2(reg->start_cntl_b, 0, + exp_region_start, params->corner_points[0].blue.custom_float_x, + exp_resion_start_segment, 0); + REG_SET_2(reg->start_cntl_g, 0, + exp_region_start, params->corner_points[0].green.custom_float_x, + exp_resion_start_segment, 0); + REG_SET_2(reg->start_cntl_r, 0, + exp_region_start, params->corner_points[0].red.custom_float_x, + exp_resion_start_segment, 0); + + REG_SET(reg->start_slope_cntl_b, 0, //linear slope at start of curve + field_region_linear_slope, params->corner_points[0].blue.custom_float_slope); + REG_SET(reg->start_slope_cntl_g, 0, + field_region_linear_slope, params->corner_points[0].green.custom_float_slope); + REG_SET(reg->start_slope_cntl_r, 0, + field_region_linear_slope, params->corner_points[0].red.custom_float_slope); + + REG_SET(reg->start_end_cntl1_b, 0, + field_region_end_base, params->corner_points[1].blue.custom_float_y); + REG_SET(reg->start_end_cntl1_g, 0, + field_region_end_base, params->corner_points[1].green.custom_float_y); + REG_SET(reg->start_end_cntl1_r, 0, + field_region_end_base, params->corner_points[1].red.custom_float_y); + + REG_SET_2(reg->start_end_cntl2_b, 0, + field_region_end_slope, params->corner_points[1].blue.custom_float_slope, + field_region_end, params->corner_points[1].blue.custom_float_x); + REG_SET_2(reg->start_end_cntl2_g, 0, + field_region_end_slope, params->corner_points[1].green.custom_float_slope, + field_region_end, params->corner_points[1].green.custom_float_x); + REG_SET_2(reg->start_end_cntl2_r, 0, + field_region_end_slope, params->corner_points[1].red.custom_float_slope, + field_region_end, params->corner_points[1].red.custom_float_x); + + for (reg_region_cur = reg->region_start; + reg_region_cur <= reg->region_end; + reg_region_cur++) { + + const struct gamma_curve *curve0 = &(params->arr_curve_points[2 * i]); + const struct gamma_curve *curve1 = &(params->arr_curve_points[(2 * i) + 1]); + + REG_SET_4(reg_region_cur, 0, + exp_region0_lut_offset, curve0->offset, + exp_region0_num_segments, curve0->segments_num, + exp_region1_lut_offset, curve1->offset, + exp_region1_num_segments, curve1->segments_num); + + i++; + } +} + +/* driver uses 32 regions or less, but DCN HW has 34, extra 2 are set to 0 */ +#define MAX_REGIONS_NUMBER 34 +#define MAX_LOW_POINT 25 +#define NUMBER_REGIONS 32 +#define NUMBER_SW_SEGMENTS 16 + +bool cm3_helper_translate_curve_to_hw_format( + const struct dc_transfer_func *output_tf, + struct pwl_params *lut_params, bool fixpoint) +{ + struct curve_points3 *corner_points; + struct pwl_result_data *rgb_resulted; + struct pwl_result_data *rgb; + struct pwl_result_data *rgb_plus_1; + struct pwl_result_data *rgb_minus_1; + struct fixed31_32 end_value; + + int32_t region_start, region_end; + int32_t i; + uint32_t j, k, seg_distr[MAX_REGIONS_NUMBER], increment, start_index, hw_points; + + if (output_tf == NULL || lut_params == NULL || output_tf->type == TF_TYPE_BYPASS) + return false; + + corner_points = lut_params->corner_points; + rgb_resulted = lut_params->rgb_resulted; + hw_points = 0; + + memset(lut_params, 0, sizeof(struct pwl_params)); + memset(seg_distr, 0, sizeof(seg_distr)); + + if (output_tf->tf == TRANSFER_FUNCTION_PQ || output_tf->tf == TRANSFER_FUNCTION_GAMMA22 || + output_tf->tf == TRANSFER_FUNCTION_HLG) { + /* 32 segments + * segments are from 2^-25 to 2^7 + */ + for (i = 0; i < NUMBER_REGIONS ; i++) + seg_distr[i] = 3; + + region_start = -MAX_LOW_POINT; + region_end = NUMBER_REGIONS - MAX_LOW_POINT; + } else { + /* 11 segments + * segment is from 2^-10 to 2^0 + * There are less than 256 points, for optimization + */ + seg_distr[0] = 3; + seg_distr[1] = 4; + seg_distr[2] = 4; + seg_distr[3] = 4; + seg_distr[4] = 4; + seg_distr[5] = 4; + seg_distr[6] = 4; + seg_distr[7] = 4; + seg_distr[8] = 4; + seg_distr[9] = 4; + seg_distr[10] = 1; + + region_start = -10; + region_end = 1; + } + + for (i = region_end - region_start; i < MAX_REGIONS_NUMBER ; i++) + seg_distr[i] = -1; + + for (k = 0; k < MAX_REGIONS_NUMBER; k++) { + if (seg_distr[k] != -1) + hw_points += (1 << seg_distr[k]); + } + + j = 0; + for (k = 0; k < (region_end - region_start); k++) { + increment = NUMBER_SW_SEGMENTS / (1 << seg_distr[k]); + start_index = (region_start + k + MAX_LOW_POINT) * + NUMBER_SW_SEGMENTS; + for (i = start_index; i < start_index + NUMBER_SW_SEGMENTS; + i += increment) { + if (j == hw_points - 1) + break; + rgb_resulted[j].red = output_tf->tf_pts.red[i]; + rgb_resulted[j].green = output_tf->tf_pts.green[i]; + rgb_resulted[j].blue = output_tf->tf_pts.blue[i]; + j++; + } + } + + /* last point */ + start_index = (region_end + MAX_LOW_POINT) * NUMBER_SW_SEGMENTS; + rgb_resulted[hw_points - 1].red = output_tf->tf_pts.red[start_index]; + rgb_resulted[hw_points - 1].green = output_tf->tf_pts.green[start_index]; + rgb_resulted[hw_points - 1].blue = output_tf->tf_pts.blue[start_index]; + + rgb_resulted[hw_points].red = rgb_resulted[hw_points - 1].red; + rgb_resulted[hw_points].green = rgb_resulted[hw_points - 1].green; + rgb_resulted[hw_points].blue = rgb_resulted[hw_points - 1].blue; + + // All 3 color channels have same x + corner_points[0].red.x = dc_fixpt_pow(dc_fixpt_from_int(2), + dc_fixpt_from_int(region_start)); + corner_points[0].green.x = corner_points[0].red.x; + corner_points[0].blue.x = corner_points[0].red.x; + + corner_points[1].red.x = dc_fixpt_pow(dc_fixpt_from_int(2), + dc_fixpt_from_int(region_end)); + corner_points[1].green.x = corner_points[1].red.x; + corner_points[1].blue.x = corner_points[1].red.x; + + corner_points[0].red.y = rgb_resulted[0].red; + corner_points[0].green.y = rgb_resulted[0].green; + corner_points[0].blue.y = rgb_resulted[0].blue; + + corner_points[0].red.slope = dc_fixpt_div(corner_points[0].red.y, + corner_points[0].red.x); + corner_points[0].green.slope = dc_fixpt_div(corner_points[0].green.y, + corner_points[0].green.x); + corner_points[0].blue.slope = dc_fixpt_div(corner_points[0].blue.y, + corner_points[0].blue.x); + + /* see comment above, m_arrPoints[1].y should be the Y value for the + * region end (m_numOfHwPoints), not last HW point(m_numOfHwPoints - 1) + */ + corner_points[1].red.y = rgb_resulted[hw_points - 1].red; + corner_points[1].green.y = rgb_resulted[hw_points - 1].green; + corner_points[1].blue.y = rgb_resulted[hw_points - 1].blue; + corner_points[1].red.slope = dc_fixpt_zero; + corner_points[1].green.slope = dc_fixpt_zero; + corner_points[1].blue.slope = dc_fixpt_zero; + + if (output_tf->tf == TRANSFER_FUNCTION_PQ || output_tf->tf == TRANSFER_FUNCTION_HLG) { + /* for PQ/HLG, we want to have a straight line from last HW X point, + * and the slope to be such that we hit 1.0 at 10000/1000 nits. + */ + + if (output_tf->tf == TRANSFER_FUNCTION_PQ) + end_value = dc_fixpt_from_int(125); + else + end_value = dc_fixpt_from_fraction(125, 10); + + corner_points[1].red.slope = dc_fixpt_div( + dc_fixpt_sub(dc_fixpt_one, corner_points[1].red.y), + dc_fixpt_sub(end_value, corner_points[1].red.x)); + corner_points[1].green.slope = dc_fixpt_div( + dc_fixpt_sub(dc_fixpt_one, corner_points[1].green.y), + dc_fixpt_sub(end_value, corner_points[1].green.x)); + corner_points[1].blue.slope = dc_fixpt_div( + dc_fixpt_sub(dc_fixpt_one, corner_points[1].blue.y), + dc_fixpt_sub(end_value, corner_points[1].blue.x)); + } + lut_params->hw_points_num = hw_points; + + k = 0; + for (i = 1; i < MAX_REGIONS_NUMBER; i++) { + if (seg_distr[k] != -1) { + lut_params->arr_curve_points[k].segments_num = + seg_distr[k]; + lut_params->arr_curve_points[i].offset = + lut_params->arr_curve_points[k].offset + (1 << seg_distr[k]); + } + k++; + } + + if (seg_distr[k] != -1) + lut_params->arr_curve_points[k].segments_num = seg_distr[k]; + + rgb = rgb_resulted; + rgb_plus_1 = rgb_resulted + 1; + rgb_minus_1 = rgb; + + i = 1; + while (i != hw_points + 1) { + if (i >= hw_points - 1) { + if (dc_fixpt_lt(rgb_plus_1->red, rgb->red)) + rgb_plus_1->red = dc_fixpt_add(rgb->red, rgb_minus_1->delta_red); + if (dc_fixpt_lt(rgb_plus_1->green, rgb->green)) + rgb_plus_1->green = dc_fixpt_add(rgb->green, rgb_minus_1->delta_green); + if (dc_fixpt_lt(rgb_plus_1->blue, rgb->blue)) + rgb_plus_1->blue = dc_fixpt_add(rgb->blue, rgb_minus_1->delta_blue); + } + + rgb->delta_red = dc_fixpt_sub(rgb_plus_1->red, rgb->red); + rgb->delta_green = dc_fixpt_sub(rgb_plus_1->green, rgb->green); + rgb->delta_blue = dc_fixpt_sub(rgb_plus_1->blue, rgb->blue); + + if (fixpoint == true) { + rgb->delta_red_reg = dc_fixpt_clamp_u0d10(rgb->delta_red); + rgb->delta_green_reg = dc_fixpt_clamp_u0d10(rgb->delta_green); + rgb->delta_blue_reg = dc_fixpt_clamp_u0d10(rgb->delta_blue); + rgb->red_reg = dc_fixpt_clamp_u0d14(rgb->red); + rgb->green_reg = dc_fixpt_clamp_u0d14(rgb->green); + rgb->blue_reg = dc_fixpt_clamp_u0d14(rgb->blue); + } + + ++rgb_plus_1; + rgb_minus_1 = rgb; + ++rgb; + ++i; + } + cm3_helper_convert_to_custom_float(rgb_resulted, + lut_params->corner_points, + hw_points, fixpoint); + + return true; +} + +#define NUM_DEGAMMA_REGIONS 12 + + +bool cm3_helper_translate_curve_to_degamma_hw_format( + const struct dc_transfer_func *output_tf, + struct pwl_params *lut_params) +{ + struct curve_points3 *corner_points; + struct pwl_result_data *rgb_resulted; + struct pwl_result_data *rgb; + struct pwl_result_data *rgb_plus_1; + + int32_t region_start, region_end; + int32_t i; + uint32_t j, k, seg_distr[MAX_REGIONS_NUMBER], increment, start_index, hw_points; + + if (output_tf == NULL || lut_params == NULL || output_tf->type == TF_TYPE_BYPASS) + return false; + + corner_points = lut_params->corner_points; + rgb_resulted = lut_params->rgb_resulted; + hw_points = 0; + + memset(lut_params, 0, sizeof(struct pwl_params)); + memset(seg_distr, 0, sizeof(seg_distr)); + + region_start = -NUM_DEGAMMA_REGIONS; + region_end = 0; + + + for (i = region_end - region_start; i < MAX_REGIONS_NUMBER ; i++) + seg_distr[i] = -1; + /* 12 segments + * segments are from 2^-12 to 0 + */ + for (i = 0; i < NUM_DEGAMMA_REGIONS ; i++) + seg_distr[i] = 4; + + for (k = 0; k < MAX_REGIONS_NUMBER; k++) { + if (seg_distr[k] != -1) + hw_points += (1 << seg_distr[k]); + } + + j = 0; + for (k = 0; k < (region_end - region_start); k++) { + increment = NUMBER_SW_SEGMENTS / (1 << seg_distr[k]); + start_index = (region_start + k + MAX_LOW_POINT) * + NUMBER_SW_SEGMENTS; + for (i = start_index; i < start_index + NUMBER_SW_SEGMENTS; + i += increment) { + if (j == hw_points - 1) + break; + rgb_resulted[j].red = output_tf->tf_pts.red[i]; + rgb_resulted[j].green = output_tf->tf_pts.green[i]; + rgb_resulted[j].blue = output_tf->tf_pts.blue[i]; + j++; + } + } + + /* last point */ + start_index = (region_end + MAX_LOW_POINT) * NUMBER_SW_SEGMENTS; + rgb_resulted[hw_points - 1].red = output_tf->tf_pts.red[start_index]; + rgb_resulted[hw_points - 1].green = output_tf->tf_pts.green[start_index]; + rgb_resulted[hw_points - 1].blue = output_tf->tf_pts.blue[start_index]; + + corner_points[0].red.x = dc_fixpt_pow(dc_fixpt_from_int(2), + dc_fixpt_from_int(region_start)); + corner_points[0].green.x = corner_points[0].red.x; + corner_points[0].blue.x = corner_points[0].red.x; + corner_points[1].red.x = dc_fixpt_pow(dc_fixpt_from_int(2), + dc_fixpt_from_int(region_end)); + corner_points[1].green.x = corner_points[1].red.x; + corner_points[1].blue.x = corner_points[1].red.x; + + corner_points[0].red.y = rgb_resulted[0].red; + corner_points[0].green.y = rgb_resulted[0].green; + corner_points[0].blue.y = rgb_resulted[0].blue; + + /* see comment above, m_arrPoints[1].y should be the Y value for the + * region end (m_numOfHwPoints), not last HW point(m_numOfHwPoints - 1) + */ + corner_points[1].red.y = rgb_resulted[hw_points - 1].red; + corner_points[1].green.y = rgb_resulted[hw_points - 1].green; + corner_points[1].blue.y = rgb_resulted[hw_points - 1].blue; + corner_points[1].red.slope = dc_fixpt_zero; + corner_points[1].green.slope = dc_fixpt_zero; + corner_points[1].blue.slope = dc_fixpt_zero; + + if (output_tf->tf == TRANSFER_FUNCTION_PQ) { + /* for PQ, we want to have a straight line from last HW X point, + * and the slope to be such that we hit 1.0 at 10000 nits. + */ + const struct fixed31_32 end_value = + dc_fixpt_from_int(125); + + corner_points[1].red.slope = dc_fixpt_div( + dc_fixpt_sub(dc_fixpt_one, corner_points[1].red.y), + dc_fixpt_sub(end_value, corner_points[1].red.x)); + corner_points[1].green.slope = dc_fixpt_div( + dc_fixpt_sub(dc_fixpt_one, corner_points[1].green.y), + dc_fixpt_sub(end_value, corner_points[1].green.x)); + corner_points[1].blue.slope = dc_fixpt_div( + dc_fixpt_sub(dc_fixpt_one, corner_points[1].blue.y), + dc_fixpt_sub(end_value, corner_points[1].blue.x)); + } + + lut_params->hw_points_num = hw_points; + + k = 0; + for (i = 1; i < MAX_REGIONS_NUMBER; i++) { + if (seg_distr[k] != -1) { + lut_params->arr_curve_points[k].segments_num = + seg_distr[k]; + lut_params->arr_curve_points[i].offset = + lut_params->arr_curve_points[k].offset + (1 << seg_distr[k]); + } + k++; + } + + if (seg_distr[k] != -1) + lut_params->arr_curve_points[k].segments_num = seg_distr[k]; + + rgb = rgb_resulted; + rgb_plus_1 = rgb_resulted + 1; + + i = 1; + while (i != hw_points + 1) { + if (dc_fixpt_lt(rgb_plus_1->red, rgb->red)) + rgb_plus_1->red = rgb->red; + if (dc_fixpt_lt(rgb_plus_1->green, rgb->green)) + rgb_plus_1->green = rgb->green; + if (dc_fixpt_lt(rgb_plus_1->blue, rgb->blue)) + rgb_plus_1->blue = rgb->blue; + + rgb->delta_red = dc_fixpt_sub(rgb_plus_1->red, rgb->red); + rgb->delta_green = dc_fixpt_sub(rgb_plus_1->green, rgb->green); + rgb->delta_blue = dc_fixpt_sub(rgb_plus_1->blue, rgb->blue); + + ++rgb_plus_1; + ++rgb; + ++i; + } + cm3_helper_convert_to_custom_float(rgb_resulted, + lut_params->corner_points, + hw_points, false); + + return true; +} + +bool cm3_helper_convert_to_custom_float( + struct pwl_result_data *rgb_resulted, + struct curve_points3 *corner_points, + uint32_t hw_points_num, + bool fixpoint) +{ + struct custom_float_format fmt; + + struct pwl_result_data *rgb = rgb_resulted; + + uint32_t i = 0; + + fmt.exponenta_bits = 6; + fmt.mantissa_bits = 12; + fmt.sign = false; + + /* corner_points[0] - beginning base, slope offset for R,G,B + * corner_points[1] - end base, slope offset for R,G,B + */ + if (!convert_to_custom_float_format(corner_points[0].red.x, &fmt, + &corner_points[0].red.custom_float_x)) { + BREAK_TO_DEBUGGER(); + return false; + } + if (!convert_to_custom_float_format(corner_points[0].green.x, &fmt, + &corner_points[0].green.custom_float_x)) { + BREAK_TO_DEBUGGER(); + return false; + } + if (!convert_to_custom_float_format(corner_points[0].blue.x, &fmt, + &corner_points[0].blue.custom_float_x)) { + BREAK_TO_DEBUGGER(); + return false; + } + + if (!convert_to_custom_float_format(corner_points[0].red.offset, &fmt, + &corner_points[0].red.custom_float_offset)) { + BREAK_TO_DEBUGGER(); + return false; + } + if (!convert_to_custom_float_format(corner_points[0].green.offset, &fmt, + &corner_points[0].green.custom_float_offset)) { + BREAK_TO_DEBUGGER(); + return false; + } + if (!convert_to_custom_float_format(corner_points[0].blue.offset, &fmt, + &corner_points[0].blue.custom_float_offset)) { + BREAK_TO_DEBUGGER(); + return false; + } + + if (!convert_to_custom_float_format(corner_points[0].red.slope, &fmt, + &corner_points[0].red.custom_float_slope)) { + BREAK_TO_DEBUGGER(); + return false; + } + if (!convert_to_custom_float_format(corner_points[0].green.slope, &fmt, + &corner_points[0].green.custom_float_slope)) { + BREAK_TO_DEBUGGER(); + return false; + } + if (!convert_to_custom_float_format(corner_points[0].blue.slope, &fmt, + &corner_points[0].blue.custom_float_slope)) { + BREAK_TO_DEBUGGER(); + return false; + } + + if (fixpoint == true) { + corner_points[1].red.custom_float_y = + dc_fixpt_clamp_u0d14(corner_points[1].red.y); + corner_points[1].green.custom_float_y = + dc_fixpt_clamp_u0d14(corner_points[1].green.y); + corner_points[1].blue.custom_float_y = + dc_fixpt_clamp_u0d14(corner_points[1].blue.y); + } else { + if (!convert_to_custom_float_format(corner_points[1].red.y, + &fmt, &corner_points[1].red.custom_float_y)) { + BREAK_TO_DEBUGGER(); + return false; + } + if (!convert_to_custom_float_format(corner_points[1].green.y, + &fmt, &corner_points[1].green.custom_float_y)) { + BREAK_TO_DEBUGGER(); + return false; + } + if (!convert_to_custom_float_format(corner_points[1].blue.y, + &fmt, &corner_points[1].blue.custom_float_y)) { + BREAK_TO_DEBUGGER(); + return false; + } + } + + fmt.mantissa_bits = 10; + fmt.sign = false; + + if (!convert_to_custom_float_format(corner_points[1].red.x, &fmt, + &corner_points[1].red.custom_float_x)) { + BREAK_TO_DEBUGGER(); + return false; + } + if (!convert_to_custom_float_format(corner_points[1].green.x, &fmt, + &corner_points[1].green.custom_float_x)) { + BREAK_TO_DEBUGGER(); + return false; + } + if (!convert_to_custom_float_format(corner_points[1].blue.x, &fmt, + &corner_points[1].blue.custom_float_x)) { + BREAK_TO_DEBUGGER(); + return false; + } + + if (!convert_to_custom_float_format(corner_points[1].red.slope, &fmt, + &corner_points[1].red.custom_float_slope)) { + BREAK_TO_DEBUGGER(); + return false; + } + if (!convert_to_custom_float_format(corner_points[1].green.slope, &fmt, + &corner_points[1].green.custom_float_slope)) { + BREAK_TO_DEBUGGER(); + return false; + } + if (!convert_to_custom_float_format(corner_points[1].blue.slope, &fmt, + &corner_points[1].blue.custom_float_slope)) { + BREAK_TO_DEBUGGER(); + return false; + } + + if (hw_points_num == 0 || rgb_resulted == NULL || fixpoint == true) + return true; + + fmt.mantissa_bits = 12; + + while (i != hw_points_num) { + if (!convert_to_custom_float_format(rgb->red, &fmt, + &rgb->red_reg)) { + BREAK_TO_DEBUGGER(); + return false; + } + + if (!convert_to_custom_float_format(rgb->green, &fmt, + &rgb->green_reg)) { + BREAK_TO_DEBUGGER(); + return false; + } + + if (!convert_to_custom_float_format(rgb->blue, &fmt, + &rgb->blue_reg)) { + BREAK_TO_DEBUGGER(); + return false; + } + + if (!convert_to_custom_float_format(rgb->delta_red, &fmt, + &rgb->delta_red_reg)) { + BREAK_TO_DEBUGGER(); + return false; + } + + if (!convert_to_custom_float_format(rgb->delta_green, &fmt, + &rgb->delta_green_reg)) { + BREAK_TO_DEBUGGER(); + return false; + } + + if (!convert_to_custom_float_format(rgb->delta_blue, &fmt, + &rgb->delta_blue_reg)) { + BREAK_TO_DEBUGGER(); + return false; + } + + ++rgb; + ++i; + } + + return true; +} + +bool is_rgb_equal(const struct pwl_result_data *rgb, uint32_t num) +{ + uint32_t i; + bool ret = true; + + for (i = 0 ; i < num; i++) { + if (rgb[i].red_reg != rgb[i].green_reg || + rgb[i].blue_reg != rgb[i].red_reg || + rgb[i].blue_reg != rgb[i].green_reg) { + ret = false; + break; + } + } + return ret; +} + diff --git a/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_cm_common.h b/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_cm_common.h new file mode 100644 index 000000000..bd98b327a --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_cm_common.h @@ -0,0 +1,78 @@ +/* + * Copyright 2020 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 "dcn10/dcn10_cm_common.h" + +#ifndef __DAL_DCN30_CM_COMMON_H__ +#define __DAL_DCN30_CM_COMMON_H__ + +#define TF_HELPER_REG_FIELD_LIST_DCN3(type) \ + TF_HELPER_REG_FIELD_LIST(type);\ + type field_region_start_base;\ + type field_offset + +struct DCN3_xfer_func_shift { + TF_HELPER_REG_FIELD_LIST_DCN3(uint8_t); +}; + +struct DCN3_xfer_func_mask { + TF_HELPER_REG_FIELD_LIST_DCN3(uint32_t); +}; + +struct dcn3_xfer_func_reg { + struct DCN3_xfer_func_shift shifts; + struct DCN3_xfer_func_mask masks; + + TF_HELPER_REG_LIST; + uint32_t offset_b; + uint32_t offset_g; + uint32_t offset_r; + uint32_t start_base_cntl_b; + uint32_t start_base_cntl_g; + uint32_t start_base_cntl_r; +}; + +void cm_helper_program_gamcor_xfer_func( + struct dc_context *ctx, + const struct pwl_params *params, + const struct dcn3_xfer_func_reg *reg); + +bool cm3_helper_translate_curve_to_hw_format( + const struct dc_transfer_func *output_tf, + struct pwl_params *lut_params, bool fixpoint); + +bool cm3_helper_translate_curve_to_degamma_hw_format( + const struct dc_transfer_func *output_tf, + struct pwl_params *lut_params); + +bool cm3_helper_convert_to_custom_float( + struct pwl_result_data *rgb_resulted, + struct curve_points3 *corner_points, + uint32_t hw_points_num, + bool fixpoint); + +bool is_rgb_equal(const struct pwl_result_data *rgb, uint32_t num); + +#endif diff --git a/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_dccg.c b/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_dccg.c new file mode 100644 index 000000000..d445dfefc --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_dccg.c @@ -0,0 +1,103 @@ +/* + * Copyright 2020 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 "reg_helper.h" +#include "core_types.h" +#include "dcn30_dccg.h" + +#define TO_DCN_DCCG(dccg)\ + container_of(dccg, struct dcn_dccg, base) + +#define REG(reg) \ + (dccg_dcn->regs->reg) + +#undef FN +#define FN(reg_name, field_name) \ + dccg_dcn->dccg_shift->field_name, dccg_dcn->dccg_mask->field_name + +#define CTX \ + dccg_dcn->base.ctx +#define DC_LOGGER \ + dccg->ctx->logger + + +static const struct dccg_funcs dccg3_funcs = { + .update_dpp_dto = dccg2_update_dpp_dto, + .get_dccg_ref_freq = dccg2_get_dccg_ref_freq, + .set_fifo_errdet_ovr_en = dccg2_set_fifo_errdet_ovr_en, + .otg_add_pixel = dccg2_otg_add_pixel, + .otg_drop_pixel = dccg2_otg_drop_pixel, + .dccg_init = dccg2_init +}; + +struct dccg *dccg3_create( + struct dc_context *ctx, + const struct dccg_registers *regs, + const struct dccg_shift *dccg_shift, + const struct dccg_mask *dccg_mask) +{ + struct dcn_dccg *dccg_dcn = kzalloc(sizeof(*dccg_dcn), GFP_KERNEL); + struct dccg *base; + + if (dccg_dcn == NULL) { + BREAK_TO_DEBUGGER(); + return NULL; + } + + base = &dccg_dcn->base; + base->ctx = ctx; + base->funcs = &dccg3_funcs; + + dccg_dcn->regs = regs; + dccg_dcn->dccg_shift = dccg_shift; + dccg_dcn->dccg_mask = dccg_mask; + + return &dccg_dcn->base; +} + +struct dccg *dccg30_create( + struct dc_context *ctx, + const struct dccg_registers *regs, + const struct dccg_shift *dccg_shift, + const struct dccg_mask *dccg_mask) +{ + struct dcn_dccg *dccg_dcn = kzalloc(sizeof(*dccg_dcn), GFP_KERNEL); + struct dccg *base; + + if (dccg_dcn == NULL) { + BREAK_TO_DEBUGGER(); + return NULL; + } + + base = &dccg_dcn->base; + base->ctx = ctx; + base->funcs = &dccg3_funcs; + + dccg_dcn->regs = regs; + dccg_dcn->dccg_shift = dccg_shift; + dccg_dcn->dccg_mask = dccg_mask; + + return &dccg_dcn->base; +} diff --git a/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_dccg.h b/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_dccg.h new file mode 100644 index 000000000..35a613bb0 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_dccg.h @@ -0,0 +1,81 @@ +/* + * Copyright 2020 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 __DCN30_DCCG_H__ +#define __DCN30_DCCG_H__ + +#include "dcn20/dcn20_dccg.h" + + +#define DCCG_REG_LIST_DCN3AG() \ + DCCG_COMMON_REG_LIST_DCN_BASE(),\ + SR(PHYASYMCLK_CLOCK_CNTL),\ + SR(PHYBSYMCLK_CLOCK_CNTL),\ + SR(PHYCSYMCLK_CLOCK_CNTL) + + +#define DCCG_REG_LIST_DCN30() \ + DCCG_REG_LIST_DCN2(),\ + DCCG_SRII(PIXEL_RATE_CNTL, OTG, 2),\ + DCCG_SRII(PIXEL_RATE_CNTL, OTG, 3),\ + DCCG_SRII(PIXEL_RATE_CNTL, OTG, 4),\ + DCCG_SRII(PIXEL_RATE_CNTL, OTG, 5),\ + SR(PHYASYMCLK_CLOCK_CNTL),\ + SR(PHYBSYMCLK_CLOCK_CNTL),\ + SR(PHYCSYMCLK_CLOCK_CNTL) + +#define DCCG_MASK_SH_LIST_DCN3AG(mask_sh) \ + DCCG_MASK_SH_LIST_DCN2_1(mask_sh),\ + DCCG_SF(HDMICHARCLK0_CLOCK_CNTL, HDMICHARCLK0_EN, mask_sh),\ + DCCG_SF(HDMICHARCLK0_CLOCK_CNTL, HDMICHARCLK0_SRC_SEL, mask_sh),\ + DCCG_SF(PHYASYMCLK_CLOCK_CNTL, PHYASYMCLK_FORCE_EN, mask_sh),\ + DCCG_SF(PHYASYMCLK_CLOCK_CNTL, PHYASYMCLK_FORCE_SRC_SEL, mask_sh),\ + DCCG_SF(PHYBSYMCLK_CLOCK_CNTL, PHYBSYMCLK_FORCE_EN, mask_sh),\ + DCCG_SF(PHYBSYMCLK_CLOCK_CNTL, PHYBSYMCLK_FORCE_SRC_SEL, mask_sh),\ + DCCG_SF(PHYCSYMCLK_CLOCK_CNTL, PHYCSYMCLK_FORCE_EN, mask_sh),\ + DCCG_SF(PHYCSYMCLK_CLOCK_CNTL, PHYCSYMCLK_FORCE_SRC_SEL, mask_sh) + +#define DCCG_MASK_SH_LIST_DCN3(mask_sh) \ + DCCG_MASK_SH_LIST_DCN2(mask_sh),\ + DCCG_SF(PHYASYMCLK_CLOCK_CNTL, PHYASYMCLK_FORCE_EN, mask_sh),\ + DCCG_SF(PHYASYMCLK_CLOCK_CNTL, PHYASYMCLK_FORCE_SRC_SEL, mask_sh),\ + DCCG_SF(PHYBSYMCLK_CLOCK_CNTL, PHYBSYMCLK_FORCE_EN, mask_sh),\ + DCCG_SF(PHYBSYMCLK_CLOCK_CNTL, PHYBSYMCLK_FORCE_SRC_SEL, mask_sh),\ + DCCG_SF(PHYCSYMCLK_CLOCK_CNTL, PHYCSYMCLK_FORCE_EN, mask_sh),\ + DCCG_SF(PHYCSYMCLK_CLOCK_CNTL, PHYCSYMCLK_FORCE_SRC_SEL, mask_sh),\ + +struct dccg *dccg3_create( + struct dc_context *ctx, + const struct dccg_registers *regs, + const struct dccg_shift *dccg_shift, + const struct dccg_mask *dccg_mask); + +struct dccg *dccg30_create( + struct dc_context *ctx, + const struct dccg_registers *regs, + const struct dccg_shift *dccg_shift, + const struct dccg_mask *dccg_mask); + +#endif //__DCN30_DCCG_H__ diff --git a/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_dio_link_encoder.c b/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_dio_link_encoder.c new file mode 100644 index 000000000..6f3c2fb60 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_dio_link_encoder.c @@ -0,0 +1,260 @@ +/* + * Copyright 2020 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 "reg_helper.h" + +#include "core_types.h" +#include "link_encoder.h" +#include "dcn30_dio_link_encoder.h" +#include "stream_encoder.h" +#include "i2caux_interface.h" +#include "dc_bios_types.h" +/* #include "dcn3ag/dcn3ag_phy_fw.h" */ + +#include "gpio_service_interface.h" + +#define CTX \ + enc10->base.ctx +#define DC_LOGGER \ + enc10->base.ctx->logger + +#define REG(reg)\ + (enc10->link_regs->reg) + +#undef FN +#define FN(reg_name, field_name) \ + enc10->link_shift->field_name, enc10->link_mask->field_name + +#define IND_REG(index) \ + (enc10->link_regs->index) + + +bool dcn30_link_encoder_validate_output_with_stream( + struct link_encoder *enc, + const struct dc_stream_state *stream) +{ + return dcn10_link_encoder_validate_output_with_stream(enc, stream); +} + +static const struct link_encoder_funcs dcn30_link_enc_funcs = { + .read_state = link_enc2_read_state, + .validate_output_with_stream = + dcn30_link_encoder_validate_output_with_stream, + .hw_init = enc3_hw_init, + .setup = dcn10_link_encoder_setup, + .enable_tmds_output = dcn10_link_encoder_enable_tmds_output, + .enable_dp_output = dcn20_link_encoder_enable_dp_output, + .enable_dp_mst_output = dcn10_link_encoder_enable_dp_mst_output, + .disable_output = dcn10_link_encoder_disable_output, + .dp_set_lane_settings = dcn10_link_encoder_dp_set_lane_settings, + .dp_set_phy_pattern = dcn10_link_encoder_dp_set_phy_pattern, + .update_mst_stream_allocation_table = + dcn10_link_encoder_update_mst_stream_allocation_table, + .psr_program_dp_dphy_fast_training = + dcn10_psr_program_dp_dphy_fast_training, + .psr_program_secondary_packet = dcn10_psr_program_secondary_packet, + .connect_dig_be_to_fe = dcn10_link_encoder_connect_dig_be_to_fe, + .enable_hpd = dcn10_link_encoder_enable_hpd, + .disable_hpd = dcn10_link_encoder_disable_hpd, + .is_dig_enabled = dcn10_is_dig_enabled, + .destroy = dcn10_link_encoder_destroy, + .fec_set_enable = enc2_fec_set_enable, + .fec_set_ready = enc2_fec_set_ready, + .fec_is_active = enc2_fec_is_active, + .get_dig_frontend = dcn10_get_dig_frontend, + .get_dig_mode = dcn10_get_dig_mode, + .is_in_alt_mode = dcn20_link_encoder_is_in_alt_mode, + .get_max_link_cap = dcn20_link_encoder_get_max_link_cap, +}; + +void dcn30_link_encoder_construct( + struct dcn20_link_encoder *enc20, + const struct encoder_init_data *init_data, + const struct encoder_feature_support *enc_features, + const struct dcn10_link_enc_registers *link_regs, + const struct dcn10_link_enc_aux_registers *aux_regs, + const struct dcn10_link_enc_hpd_registers *hpd_regs, + const struct dcn10_link_enc_shift *link_shift, + const struct dcn10_link_enc_mask *link_mask) +{ + struct bp_encoder_cap_info bp_cap_info = {0}; + const struct dc_vbios_funcs *bp_funcs = init_data->ctx->dc_bios->funcs; + enum bp_result result = BP_RESULT_OK; + struct dcn10_link_encoder *enc10 = &enc20->enc10; + + enc10->base.funcs = &dcn30_link_enc_funcs; + enc10->base.ctx = init_data->ctx; + enc10->base.id = init_data->encoder; + + enc10->base.hpd_source = init_data->hpd_source; + enc10->base.connector = init_data->connector; + + enc10->base.preferred_engine = ENGINE_ID_UNKNOWN; + + enc10->base.features = *enc_features; + + enc10->base.transmitter = init_data->transmitter; + + /* set the flag to indicate whether driver poll the I2C data pin + * while doing the DP sink detect + */ + +/* if (dal_adapter_service_is_feature_supported(as, + FEATURE_DP_SINK_DETECT_POLL_DATA_PIN)) + enc10->base.features.flags.bits. + DP_SINK_DETECT_POLL_DATA_PIN = true;*/ + + enc10->base.output_signals = + SIGNAL_TYPE_DVI_SINGLE_LINK | + SIGNAL_TYPE_DVI_DUAL_LINK | + SIGNAL_TYPE_LVDS | + SIGNAL_TYPE_DISPLAY_PORT | + SIGNAL_TYPE_DISPLAY_PORT_MST | + SIGNAL_TYPE_EDP | + SIGNAL_TYPE_HDMI_TYPE_A; + + /* For DCE 8.0 and 8.1, by design, UNIPHY is hardwired to DIG_BE. + * SW always assign DIG_FE 1:1 mapped to DIG_FE for non-MST UNIPHY. + * SW assign DIG_FE to non-MST UNIPHY first and MST last. So prefer + * DIG is per UNIPHY and used by SST DP, eDP, HDMI, DVI and LVDS. + * Prefer DIG assignment is decided by board design. + * For DCE 8.0, there are only max 6 UNIPHYs, we assume board design + * and VBIOS will filter out 7 UNIPHY for DCE 8.0. + * By this, adding DIGG should not hurt DCE 8.0. + * This will let DCE 8.1 share DCE 8.0 as much as possible + */ + + enc10->link_regs = link_regs; + enc10->aux_regs = aux_regs; + enc10->hpd_regs = hpd_regs; + enc10->link_shift = link_shift; + enc10->link_mask = link_mask; + + switch (enc10->base.transmitter) { + case TRANSMITTER_UNIPHY_A: + enc10->base.preferred_engine = ENGINE_ID_DIGA; + break; + case TRANSMITTER_UNIPHY_B: + enc10->base.preferred_engine = ENGINE_ID_DIGB; + break; + case TRANSMITTER_UNIPHY_C: + enc10->base.preferred_engine = ENGINE_ID_DIGC; + break; + case TRANSMITTER_UNIPHY_D: + enc10->base.preferred_engine = ENGINE_ID_DIGD; + break; + case TRANSMITTER_UNIPHY_E: + enc10->base.preferred_engine = ENGINE_ID_DIGE; + break; + case TRANSMITTER_UNIPHY_F: + enc10->base.preferred_engine = ENGINE_ID_DIGF; + break; + case TRANSMITTER_UNIPHY_G: + enc10->base.preferred_engine = ENGINE_ID_DIGG; + break; + default: + ASSERT_CRITICAL(false); + enc10->base.preferred_engine = ENGINE_ID_UNKNOWN; + } + + /* default to one to mirror Windows behavior */ + enc10->base.features.flags.bits.HDMI_6GB_EN = 1; + + result = bp_funcs->get_encoder_cap_info(enc10->base.ctx->dc_bios, + enc10->base.id, &bp_cap_info); + + /* Override features with DCE-specific values */ + if (result == BP_RESULT_OK) { + enc10->base.features.flags.bits.IS_HBR2_CAPABLE = + bp_cap_info.DP_HBR2_EN; + enc10->base.features.flags.bits.IS_HBR3_CAPABLE = + bp_cap_info.DP_HBR3_EN; + enc10->base.features.flags.bits.HDMI_6GB_EN = bp_cap_info.HDMI_6GB_EN; + enc10->base.features.flags.bits.IS_DP2_CAPABLE = bp_cap_info.IS_DP2_CAPABLE; + enc10->base.features.flags.bits.IS_UHBR10_CAPABLE = bp_cap_info.DP_UHBR10_EN; + enc10->base.features.flags.bits.IS_UHBR13_5_CAPABLE = bp_cap_info.DP_UHBR13_5_EN; + enc10->base.features.flags.bits.IS_UHBR20_CAPABLE = bp_cap_info.DP_UHBR20_EN; + enc10->base.features.flags.bits.DP_IS_USB_C = + bp_cap_info.DP_IS_USB_C; + } else { + DC_LOG_WARNING("%s: Failed to get encoder_cap_info from VBIOS with error code %d!\n", + __func__, + result); + } + if (enc10->base.ctx->dc->debug.hdmi20_disable) { + enc10->base.features.flags.bits.HDMI_6GB_EN = 0; + } +} + +#define AUX_REG(reg)\ + (enc10->aux_regs->reg) + +#define AUX_REG_READ(reg_name) \ + dm_read_reg(CTX, AUX_REG(reg_name)) + +#define AUX_REG_WRITE(reg_name, val) \ + dm_write_reg(CTX, AUX_REG(reg_name), val) +void enc3_hw_init(struct link_encoder *enc) +{ + struct dcn10_link_encoder *enc10 = TO_DCN10_LINK_ENC(enc); + +/* + 00 - DP_AUX_DPHY_RX_DETECTION_THRESHOLD__1to2 : 1/2 + 01 - DP_AUX_DPHY_RX_DETECTION_THRESHOLD__3to4 : 3/4 + 02 - DP_AUX_DPHY_RX_DETECTION_THRESHOLD__7to8 : 7/8 + 03 - DP_AUX_DPHY_RX_DETECTION_THRESHOLD__15to16 : 15/16 + 04 - DP_AUX_DPHY_RX_DETECTION_THRESHOLD__31to32 : 31/32 + 05 - DP_AUX_DPHY_RX_DETECTION_THRESHOLD__63to64 : 63/64 + 06 - DP_AUX_DPHY_RX_DETECTION_THRESHOLD__127to128 : 127/128 + 07 - DP_AUX_DPHY_RX_DETECTION_THRESHOLD__255to256 : 255/256 +*/ + +/* + AUX_REG_UPDATE_5(AUX_DPHY_RX_CONTROL0, + AUX_RX_START_WINDOW = 1 [6:4] + AUX_RX_RECEIVE_WINDOW = 1 default is 2 [10:8] + AUX_RX_HALF_SYM_DETECT_LEN = 1 [13:12] default is 1 + AUX_RX_TRANSITION_FILTER_EN = 1 [16] default is 1 + AUX_RX_ALLOW_BELOW_THRESHOLD_PHASE_DETECT [17] is 0 default is 0 + AUX_RX_ALLOW_BELOW_THRESHOLD_START [18] is 1 default is 1 + AUX_RX_ALLOW_BELOW_THRESHOLD_STOP [19] is 1 default is 1 + AUX_RX_PHASE_DETECT_LEN, [21,20] = 0x3 default is 3 + AUX_RX_DETECTION_THRESHOLD [30:28] = 1 +*/ + AUX_REG_WRITE(AUX_DPHY_RX_CONTROL0, 0x103d1110); + + AUX_REG_WRITE(AUX_DPHY_TX_CONTROL, 0x21c7a); + + //AUX_DPHY_TX_REF_CONTROL'AUX_TX_REF_DIV HW default is 0x32; + // Set AUX_TX_REF_DIV Divider to generate 2 MHz reference from refclk + // 27MHz -> 0xd + // 100MHz -> 0x32 + // 48MHz -> 0x18 + + // Set TMDS_CTL0 to 1. This is a legacy setting. + REG_UPDATE(TMDS_CTL_BITS, TMDS_CTL0, 1); + + dcn10_aux_initialize(enc10); +} diff --git a/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_dio_link_encoder.h b/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_dio_link_encoder.h new file mode 100644 index 000000000..f2d90f2b8 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_dio_link_encoder.h @@ -0,0 +1,85 @@ +/* + * Copyright 2020 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_LINK_ENCODER__DCN30_H__ +#define __DC_LINK_ENCODER__DCN30_H__ + +#include "dcn20/dcn20_link_encoder.h" + +#define LE_DCN3_REG_LIST(id)\ + SRI(DIG_BE_CNTL, DIG, id), \ + SRI(DIG_BE_EN_CNTL, DIG, id), \ + SRI(TMDS_CTL_BITS, DIG, id), \ + SRI(TMDS_DCBALANCER_CONTROL, DIG, id), \ + SRI(DP_CONFIG, DP, id), \ + SRI(DP_DPHY_CNTL, DP, id), \ + SRI(DP_DPHY_PRBS_CNTL, DP, id), \ + SRI(DP_DPHY_SCRAM_CNTL, DP, id),\ + SRI(DP_DPHY_SYM0, DP, id), \ + SRI(DP_DPHY_SYM1, DP, id), \ + SRI(DP_DPHY_SYM2, DP, id), \ + SRI(DP_DPHY_TRAINING_PATTERN_SEL, DP, id), \ + SRI(DP_LINK_CNTL, DP, id), \ + SRI(DP_LINK_FRAMING_CNTL, DP, id), \ + SRI(DP_MSE_SAT0, DP, id), \ + SRI(DP_MSE_SAT1, DP, id), \ + SRI(DP_MSE_SAT2, DP, id), \ + SRI(DP_MSE_SAT_UPDATE, DP, id), \ + SRI(DP_SEC_CNTL, DP, id), \ + SRI(DP_VID_STREAM_CNTL, DP, id), \ + SRI(DP_DPHY_FAST_TRAINING, DP, id), \ + SRI(DP_SEC_CNTL1, DP, id), \ + SRI(DP_DPHY_BS_SR_SWAP_CNTL, DP, id), \ + SRI(DP_DPHY_HBR2_PATTERN_CONTROL, DP, id) + +#define LINK_ENCODER_MASK_SH_LIST_DCN30(mask_sh) \ + LINK_ENCODER_MASK_SH_LIST_DCN20(mask_sh) + +#define DPCS_DCN3_MASK_SH_LIST(mask_sh)\ + DPCS_DCN2_MASK_SH_LIST(mask_sh),\ + LE_SF(DPCSTX0_DPCSTX_TX_CNTL, DPCS_TX_DATA_ORDER_INVERT_18_BIT, mask_sh),\ + LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL0, RDPCS_PHY_TX_VBOOST_LVL, mask_sh),\ + LE_SF(RDPCSTX0_RDPCSTX_CLOCK_CNTL, RDPCS_TX_CLK_EN, mask_sh),\ + LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL6, RDPCS_PHY_DPALT_DP4, mask_sh),\ + LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL6, RDPCS_PHY_DPALT_DISABLE, mask_sh) + + +void dcn30_link_encoder_construct( + struct dcn20_link_encoder *enc20, + const struct encoder_init_data *init_data, + const struct encoder_feature_support *enc_features, + const struct dcn10_link_enc_registers *link_regs, + const struct dcn10_link_enc_aux_registers *aux_regs, + const struct dcn10_link_enc_hpd_registers *hpd_regs, + const struct dcn10_link_enc_shift *link_shift, + const struct dcn10_link_enc_mask *link_mask); + +void enc3_hw_init(struct link_encoder *enc); + +bool dcn30_link_encoder_validate_output_with_stream( + struct link_encoder *enc, + const struct dc_stream_state *stream); + +#endif /* __DC_LINK_ENCODER__DCN30_H__ */ diff --git a/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_dio_stream_encoder.c b/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_dio_stream_encoder.c new file mode 100644 index 000000000..17df53793 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_dio_stream_encoder.c @@ -0,0 +1,860 @@ +/* + * Copyright 2020 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 "dc_bios_types.h" +#include "dcn30_dio_stream_encoder.h" +#include "reg_helper.h" +#include "hw_shared.h" +#include "core_types.h" +#include <linux/delay.h> + + +#define DC_LOGGER \ + enc1->base.ctx->logger + +#define REG(reg)\ + (enc1->regs->reg) + +#undef FN +#define FN(reg_name, field_name) \ + enc1->se_shift->field_name, enc1->se_mask->field_name + +#define VBI_LINE_0 0 +#define HDMI_CLOCK_CHANNEL_RATE_MORE_340M 340000 + +#define CTX \ + enc1->base.ctx + + +static void enc3_update_hdmi_info_packet( + struct dcn10_stream_encoder *enc1, + uint32_t packet_index, + const struct dc_info_packet *info_packet) +{ + uint32_t cont, send, line; + + if (info_packet->valid) { + enc1->base.vpg->funcs->update_generic_info_packet( + enc1->base.vpg, + packet_index, + info_packet, + true); + + /* enable transmission of packet(s) - + * packet transmission begins on the next frame */ + cont = 1; + /* send packet(s) every frame */ + send = 1; + /* select line number to send packets on */ + line = 2; + } else { + cont = 0; + send = 0; + line = 0; + } + + /* DP_SEC_GSP[x]_LINE_REFERENCE - keep default value REFER_TO_DP_SOF */ + + /* choose which generic packet control to use */ + switch (packet_index) { + case 0: + REG_UPDATE_2(HDMI_GENERIC_PACKET_CONTROL0, + HDMI_GENERIC0_CONT, cont, + HDMI_GENERIC0_SEND, send); + REG_UPDATE(HDMI_GENERIC_PACKET_CONTROL1, + HDMI_GENERIC0_LINE, line); + break; + case 1: + REG_UPDATE_2(HDMI_GENERIC_PACKET_CONTROL0, + HDMI_GENERIC1_CONT, cont, + HDMI_GENERIC1_SEND, send); + REG_UPDATE(HDMI_GENERIC_PACKET_CONTROL1, + HDMI_GENERIC1_LINE, line); + break; + case 2: + REG_UPDATE_2(HDMI_GENERIC_PACKET_CONTROL0, + HDMI_GENERIC2_CONT, cont, + HDMI_GENERIC2_SEND, send); + REG_UPDATE(HDMI_GENERIC_PACKET_CONTROL2, + HDMI_GENERIC2_LINE, line); + break; + case 3: + REG_UPDATE_2(HDMI_GENERIC_PACKET_CONTROL0, + HDMI_GENERIC3_CONT, cont, + HDMI_GENERIC3_SEND, send); + REG_UPDATE(HDMI_GENERIC_PACKET_CONTROL2, + HDMI_GENERIC3_LINE, line); + break; + case 4: + REG_UPDATE_2(HDMI_GENERIC_PACKET_CONTROL0, + HDMI_GENERIC4_CONT, cont, + HDMI_GENERIC4_SEND, send); + REG_UPDATE(HDMI_GENERIC_PACKET_CONTROL3, + HDMI_GENERIC4_LINE, line); + break; + case 5: + REG_UPDATE_2(HDMI_GENERIC_PACKET_CONTROL0, + HDMI_GENERIC5_CONT, cont, + HDMI_GENERIC5_SEND, send); + REG_UPDATE(HDMI_GENERIC_PACKET_CONTROL3, + HDMI_GENERIC5_LINE, line); + break; + case 6: + REG_UPDATE_2(HDMI_GENERIC_PACKET_CONTROL0, + HDMI_GENERIC6_CONT, cont, + HDMI_GENERIC6_SEND, send); + REG_UPDATE(HDMI_GENERIC_PACKET_CONTROL4, + HDMI_GENERIC6_LINE, line); + break; + case 7: + REG_UPDATE_2(HDMI_GENERIC_PACKET_CONTROL0, + HDMI_GENERIC7_CONT, cont, + HDMI_GENERIC7_SEND, send); + REG_UPDATE(HDMI_GENERIC_PACKET_CONTROL4, + HDMI_GENERIC7_LINE, line); + break; + case 8: + REG_UPDATE_2(HDMI_GENERIC_PACKET_CONTROL6, + HDMI_GENERIC8_CONT, cont, + HDMI_GENERIC8_SEND, send); + REG_UPDATE(HDMI_GENERIC_PACKET_CONTROL7, + HDMI_GENERIC8_LINE, line); + break; + case 9: + REG_UPDATE_2(HDMI_GENERIC_PACKET_CONTROL6, + HDMI_GENERIC9_CONT, cont, + HDMI_GENERIC9_SEND, send); + REG_UPDATE(HDMI_GENERIC_PACKET_CONTROL7, + HDMI_GENERIC9_LINE, line); + break; + case 10: + REG_UPDATE_2(HDMI_GENERIC_PACKET_CONTROL6, + HDMI_GENERIC10_CONT, cont, + HDMI_GENERIC10_SEND, send); + REG_UPDATE(HDMI_GENERIC_PACKET_CONTROL8, + HDMI_GENERIC10_LINE, line); + break; + case 11: + REG_UPDATE_2(HDMI_GENERIC_PACKET_CONTROL6, + HDMI_GENERIC11_CONT, cont, + HDMI_GENERIC11_SEND, send); + REG_UPDATE(HDMI_GENERIC_PACKET_CONTROL8, + HDMI_GENERIC11_LINE, line); + break; + case 12: + REG_UPDATE_2(HDMI_GENERIC_PACKET_CONTROL6, + HDMI_GENERIC12_CONT, cont, + HDMI_GENERIC12_SEND, send); + REG_UPDATE(HDMI_GENERIC_PACKET_CONTROL9, + HDMI_GENERIC12_LINE, line); + break; + case 13: + REG_UPDATE_2(HDMI_GENERIC_PACKET_CONTROL6, + HDMI_GENERIC13_CONT, cont, + HDMI_GENERIC13_SEND, send); + REG_UPDATE(HDMI_GENERIC_PACKET_CONTROL9, + HDMI_GENERIC13_LINE, line); + break; + case 14: + REG_UPDATE_2(HDMI_GENERIC_PACKET_CONTROL6, + HDMI_GENERIC14_CONT, cont, + HDMI_GENERIC14_SEND, send); + REG_UPDATE(HDMI_GENERIC_PACKET_CONTROL10, + HDMI_GENERIC14_LINE, line); + break; + default: + /* invalid HW packet index */ + DC_LOG_WARNING( + "Invalid HW packet index: %s()\n", + __func__); + return; + } +} + +void enc3_stream_encoder_update_hdmi_info_packets( + struct stream_encoder *enc, + const struct encoder_info_frame *info_frame) +{ + struct dcn10_stream_encoder *enc1 = DCN10STRENC_FROM_STRENC(enc); + + /* for bring up, disable dp double TODO */ + REG_UPDATE(HDMI_DB_CONTROL, HDMI_DB_DISABLE, 1); + REG_UPDATE(AFMT_CNTL, AFMT_AUDIO_CLOCK_EN, 1); + + /*Always add mandatory packets first followed by optional ones*/ + enc3_update_hdmi_info_packet(enc1, 0, &info_frame->avi); + enc3_update_hdmi_info_packet(enc1, 5, &info_frame->hfvsif); + enc3_update_hdmi_info_packet(enc1, 2, &info_frame->gamut); + enc3_update_hdmi_info_packet(enc1, 1, &info_frame->vendor); + enc3_update_hdmi_info_packet(enc1, 3, &info_frame->spd); + enc3_update_hdmi_info_packet(enc1, 4, &info_frame->hdrsmd); + enc3_update_hdmi_info_packet(enc1, 6, &info_frame->vtem); +} + +void enc3_stream_encoder_stop_hdmi_info_packets( + struct stream_encoder *enc) +{ + struct dcn10_stream_encoder *enc1 = DCN10STRENC_FROM_STRENC(enc); + + /* stop generic packets 0,1 on HDMI */ + REG_SET_4(HDMI_GENERIC_PACKET_CONTROL0, 0, + HDMI_GENERIC0_CONT, 0, + HDMI_GENERIC0_SEND, 0, + HDMI_GENERIC1_CONT, 0, + HDMI_GENERIC1_SEND, 0); + REG_SET_2(HDMI_GENERIC_PACKET_CONTROL1, 0, + HDMI_GENERIC0_LINE, 0, + HDMI_GENERIC1_LINE, 0); + + /* stop generic packets 2,3 on HDMI */ + REG_SET_4(HDMI_GENERIC_PACKET_CONTROL0, 0, + HDMI_GENERIC2_CONT, 0, + HDMI_GENERIC2_SEND, 0, + HDMI_GENERIC3_CONT, 0, + HDMI_GENERIC3_SEND, 0); + REG_SET_2(HDMI_GENERIC_PACKET_CONTROL2, 0, + HDMI_GENERIC2_LINE, 0, + HDMI_GENERIC3_LINE, 0); + + /* stop generic packets 4,5 on HDMI */ + REG_SET_4(HDMI_GENERIC_PACKET_CONTROL0, 0, + HDMI_GENERIC4_CONT, 0, + HDMI_GENERIC4_SEND, 0, + HDMI_GENERIC5_CONT, 0, + HDMI_GENERIC5_SEND, 0); + REG_SET_2(HDMI_GENERIC_PACKET_CONTROL3, 0, + HDMI_GENERIC4_LINE, 0, + HDMI_GENERIC5_LINE, 0); + + /* stop generic packets 6,7 on HDMI */ + REG_SET_4(HDMI_GENERIC_PACKET_CONTROL0, 0, + HDMI_GENERIC6_CONT, 0, + HDMI_GENERIC6_SEND, 0, + HDMI_GENERIC7_CONT, 0, + HDMI_GENERIC7_SEND, 0); + REG_SET_2(HDMI_GENERIC_PACKET_CONTROL4, 0, + HDMI_GENERIC6_LINE, 0, + HDMI_GENERIC7_LINE, 0); + + /* stop generic packets 8,9 on HDMI */ + REG_SET_4(HDMI_GENERIC_PACKET_CONTROL6, 0, + HDMI_GENERIC8_CONT, 0, + HDMI_GENERIC8_SEND, 0, + HDMI_GENERIC9_CONT, 0, + HDMI_GENERIC9_SEND, 0); + REG_SET_2(HDMI_GENERIC_PACKET_CONTROL7, 0, + HDMI_GENERIC8_LINE, 0, + HDMI_GENERIC9_LINE, 0); + + /* stop generic packets 10,11 on HDMI */ + REG_SET_4(HDMI_GENERIC_PACKET_CONTROL6, 0, + HDMI_GENERIC10_CONT, 0, + HDMI_GENERIC10_SEND, 0, + HDMI_GENERIC11_CONT, 0, + HDMI_GENERIC11_SEND, 0); + REG_SET_2(HDMI_GENERIC_PACKET_CONTROL8, 0, + HDMI_GENERIC10_LINE, 0, + HDMI_GENERIC11_LINE, 0); + + /* stop generic packets 12,13 on HDMI */ + REG_SET_4(HDMI_GENERIC_PACKET_CONTROL6, 0, + HDMI_GENERIC12_CONT, 0, + HDMI_GENERIC12_SEND, 0, + HDMI_GENERIC13_CONT, 0, + HDMI_GENERIC13_SEND, 0); + REG_SET_2(HDMI_GENERIC_PACKET_CONTROL9, 0, + HDMI_GENERIC12_LINE, 0, + HDMI_GENERIC13_LINE, 0); + + /* stop generic packet 14 on HDMI */ + REG_SET_2(HDMI_GENERIC_PACKET_CONTROL6, 0, + HDMI_GENERIC14_CONT, 0, + HDMI_GENERIC14_SEND, 0); + REG_UPDATE(HDMI_GENERIC_PACKET_CONTROL10, + HDMI_GENERIC14_LINE, 0); +} + +/* Set DSC-related configuration. + * dsc_mode: 0 disables DSC, other values enable DSC in specified format + * sc_bytes_per_pixel: Bytes per pixel in u3.28 format + * dsc_slice_width: Slice width in pixels + */ +static void enc3_dp_set_dsc_config(struct stream_encoder *enc, + enum optc_dsc_mode dsc_mode, + uint32_t dsc_bytes_per_pixel, + uint32_t dsc_slice_width) +{ + struct dcn10_stream_encoder *enc1 = DCN10STRENC_FROM_STRENC(enc); + + REG_UPDATE_2(DP_DSC_CNTL, + DP_DSC_MODE, dsc_mode, + DP_DSC_SLICE_WIDTH, dsc_slice_width); + + REG_SET(DP_DSC_BYTES_PER_PIXEL, 0, + DP_DSC_BYTES_PER_PIXEL, dsc_bytes_per_pixel); +} + + +void enc3_dp_set_dsc_pps_info_packet(struct stream_encoder *enc, + bool enable, + uint8_t *dsc_packed_pps, + bool immediate_update) +{ + struct dcn10_stream_encoder *enc1 = DCN10STRENC_FROM_STRENC(enc); + + if (enable) { + struct dc_info_packet pps_sdp; + int i; + + /* Configure for PPS packet size (128 bytes) */ + REG_UPDATE(DP_SEC_CNTL2, DP_SEC_GSP11_PPS, 1); + + /* We need turn on clock before programming AFMT block + * + * TODO: We may not need this here anymore since update_generic_info_packet + * no longer touches AFMT + */ + REG_UPDATE(AFMT_CNTL, AFMT_AUDIO_CLOCK_EN, 1); + + /* Load PPS into infoframe (SDP) registers */ + pps_sdp.valid = true; + pps_sdp.hb0 = 0; + pps_sdp.hb1 = DC_DP_INFOFRAME_TYPE_PPS; + pps_sdp.hb2 = 127; + pps_sdp.hb3 = 0; + + for (i = 0; i < 4; i++) { + memcpy(pps_sdp.sb, &dsc_packed_pps[i * 32], 32); + enc1->base.vpg->funcs->update_generic_info_packet( + enc1->base.vpg, + 11 + i, + &pps_sdp, + immediate_update); + } + + /* SW should make sure VBID[6] update line number is bigger + * than PPS transmit line number + */ + REG_UPDATE(DP_GSP11_CNTL, + DP_SEC_GSP11_LINE_NUM, 2); + REG_UPDATE_2(DP_MSA_VBID_MISC, + DP_VBID6_LINE_REFERENCE, 0, + DP_VBID6_LINE_NUM, 3); + + /* Send PPS data at the line number specified above. + * DP spec requires PPS to be sent only when it changes, however since + * decoder has to be able to handle its change on every frame, we're + * sending it always (i.e. on every frame) to reduce the chance it'd be + * missed by decoder. If it turns out required to send PPS only when it + * changes, we can use DP_SEC_GSP11_SEND register. + */ + REG_UPDATE(DP_GSP11_CNTL, + DP_SEC_GSP11_ENABLE, 1); + REG_UPDATE(DP_SEC_CNTL, + DP_SEC_STREAM_ENABLE, 1); + } else { + /* Disable Generic Stream Packet 11 (GSP) transmission */ + REG_UPDATE(DP_GSP11_CNTL, DP_SEC_GSP11_ENABLE, 0); + REG_UPDATE(DP_SEC_CNTL2, DP_SEC_GSP11_PPS, 0); + } +} + + +/* this function read dsc related register fields to be logged later in dcn10_log_hw_state + * into a dcn_dsc_state struct. + */ +static void enc3_read_state(struct stream_encoder *enc, struct enc_state *s) +{ + struct dcn10_stream_encoder *enc1 = DCN10STRENC_FROM_STRENC(enc); + + //if dsc is enabled, continue to read + REG_GET(DP_DSC_CNTL, DP_DSC_MODE, &s->dsc_mode); + if (s->dsc_mode) { + REG_GET(DP_DSC_CNTL, DP_DSC_SLICE_WIDTH, &s->dsc_slice_width); + REG_GET(DP_GSP11_CNTL, DP_SEC_GSP11_LINE_NUM, &s->sec_gsp_pps_line_num); + + REG_GET(DP_MSA_VBID_MISC, DP_VBID6_LINE_REFERENCE, &s->vbid6_line_reference); + REG_GET(DP_MSA_VBID_MISC, DP_VBID6_LINE_NUM, &s->vbid6_line_num); + + REG_GET(DP_GSP11_CNTL, DP_SEC_GSP11_ENABLE, &s->sec_gsp_pps_enable); + REG_GET(DP_SEC_CNTL, DP_SEC_STREAM_ENABLE, &s->sec_stream_enable); + } +} + +void enc3_stream_encoder_update_dp_info_packets( + struct stream_encoder *enc, + const struct encoder_info_frame *info_frame) +{ + struct dcn10_stream_encoder *enc1 = DCN10STRENC_FROM_STRENC(enc); + uint32_t value = 0; + uint32_t dmdata_packet_enabled = 0; + + if (info_frame->vsc.valid) { + enc->vpg->funcs->update_generic_info_packet( + enc->vpg, + 0, /* packetIndex */ + &info_frame->vsc, + true); + } + /* TODO: VSC SDP at packetIndex 1 should be restricted only if PSR-SU on. + * There should have another Infopacket type (e.g. vsc_psrsu) for PSR_SU. + * In addition, currently the driver check the valid bit then update and + * send the corresponding Infopacket. For PSR-SU, the SDP only be sent + * while entering PSR-SU mode. So we need another parameter(e.g. send) + * in dc_info_packet to indicate which infopacket should be enabled by + * default here. + */ + if (info_frame->vsc.valid) { + enc->vpg->funcs->update_generic_info_packet( + enc->vpg, + 1, /* packetIndex */ + &info_frame->vsc, + true); + } + if (info_frame->spd.valid) { + enc->vpg->funcs->update_generic_info_packet( + enc->vpg, + 2, /* packetIndex */ + &info_frame->spd, + true); + } + if (info_frame->hdrsmd.valid) { + enc->vpg->funcs->update_generic_info_packet( + enc->vpg, + 3, /* packetIndex */ + &info_frame->hdrsmd, + true); + } + /* packetIndex 4 is used for send immediate sdp message, and please + * use other packetIndex (such as 5,6) for other info packet + */ + + /* enable/disable transmission of packet(s). + * If enabled, packet transmission begins on the next frame + */ + REG_UPDATE(DP_SEC_CNTL, DP_SEC_GSP0_ENABLE, info_frame->vsc.valid); + REG_UPDATE(DP_SEC_CNTL, DP_SEC_GSP2_ENABLE, info_frame->spd.valid); + REG_UPDATE(DP_SEC_CNTL, DP_SEC_GSP3_ENABLE, info_frame->hdrsmd.valid); + + /* This bit is the master enable bit. + * When enabling secondary stream engine, + * this master bit must also be set. + * This register shared with audio info frame. + * Therefore we need to enable master bit + * if at least on of the fields is not 0 + */ + value = REG_READ(DP_SEC_CNTL); + if (value) + REG_UPDATE(DP_SEC_CNTL, DP_SEC_STREAM_ENABLE, 1); + + /* check if dynamic metadata packet transmission is enabled */ + REG_GET(DP_SEC_METADATA_TRANSMISSION, + DP_SEC_METADATA_PACKET_ENABLE, &dmdata_packet_enabled); + + if (dmdata_packet_enabled) + REG_UPDATE(DP_SEC_CNTL, DP_SEC_STREAM_ENABLE, 1); +} + +static void enc3_dp_set_odm_combine( + struct stream_encoder *enc, + bool odm_combine) +{ + struct dcn10_stream_encoder *enc1 = DCN10STRENC_FROM_STRENC(enc); + + REG_UPDATE(DP_PIXEL_FORMAT, DP_PIXEL_COMBINE, odm_combine); +} + +/* setup stream encoder in dvi mode */ +static void enc3_stream_encoder_dvi_set_stream_attribute( + struct stream_encoder *enc, + struct dc_crtc_timing *crtc_timing, + bool is_dual_link) +{ + struct dcn10_stream_encoder *enc1 = DCN10STRENC_FROM_STRENC(enc); + + if (!enc->ctx->dc->debug.avoid_vbios_exec_table) { + struct bp_encoder_control cntl = {0}; + + cntl.action = ENCODER_CONTROL_SETUP; + cntl.engine_id = enc1->base.id; + cntl.signal = is_dual_link ? + SIGNAL_TYPE_DVI_DUAL_LINK : SIGNAL_TYPE_DVI_SINGLE_LINK; + cntl.enable_dp_audio = false; + cntl.pixel_clock = crtc_timing->pix_clk_100hz / 10; + cntl.lanes_number = (is_dual_link) ? LANE_COUNT_EIGHT : LANE_COUNT_FOUR; + + if (enc1->base.bp->funcs->encoder_control( + enc1->base.bp, &cntl) != BP_RESULT_OK) + return; + + } else { + + //Set pattern for clock channel, default vlue 0x63 does not work + REG_UPDATE(DIG_CLOCK_PATTERN, DIG_CLOCK_PATTERN, 0x1F); + + //DIG_BE_TMDS_DVI_MODE : TMDS-DVI mode is already set in link_encoder_setup + + //DIG_SOURCE_SELECT is already set in dig_connect_to_otg + + /* set DIG_START to 0x1 to reset FIFO */ + REG_UPDATE(DIG_FE_CNTL, DIG_START, 1); + udelay(1); + + /* write 0 to take the FIFO out of reset */ + REG_UPDATE(DIG_FE_CNTL, DIG_START, 0); + udelay(1); + } + + ASSERT(crtc_timing->pixel_encoding == PIXEL_ENCODING_RGB); + ASSERT(crtc_timing->display_color_depth == COLOR_DEPTH_888); + enc1_stream_encoder_set_stream_attribute_helper(enc1, crtc_timing); +} + +/* setup stream encoder in hdmi mode */ +static void enc3_stream_encoder_hdmi_set_stream_attribute( + struct stream_encoder *enc, + struct dc_crtc_timing *crtc_timing, + int actual_pix_clk_khz, + bool enable_audio) +{ + struct dcn10_stream_encoder *enc1 = DCN10STRENC_FROM_STRENC(enc); + + if (!enc->ctx->dc->debug.avoid_vbios_exec_table) { + struct bp_encoder_control cntl = {0}; + + cntl.action = ENCODER_CONTROL_SETUP; + cntl.engine_id = enc1->base.id; + cntl.signal = SIGNAL_TYPE_HDMI_TYPE_A; + cntl.enable_dp_audio = enable_audio; + cntl.pixel_clock = actual_pix_clk_khz; + cntl.lanes_number = LANE_COUNT_FOUR; + + if (enc1->base.bp->funcs->encoder_control( + enc1->base.bp, &cntl) != BP_RESULT_OK) + return; + + } else { + + //Set pattern for clock channel, default vlue 0x63 does not work + REG_UPDATE(DIG_CLOCK_PATTERN, DIG_CLOCK_PATTERN, 0x1F); + + //DIG_BE_TMDS_HDMI_MODE : TMDS-HDMI mode is already set in link_encoder_setup + + //DIG_SOURCE_SELECT is already set in dig_connect_to_otg + + /* set DIG_START to 0x1 to reset FIFO */ + REG_UPDATE(DIG_FE_CNTL, DIG_START, 1); + udelay(1); + + /* write 0 to take the FIFO out of reset */ + REG_UPDATE(DIG_FE_CNTL, DIG_START, 0); + udelay(1); + } + + /* Configure pixel encoding */ + enc1_stream_encoder_set_stream_attribute_helper(enc1, crtc_timing); + + /* setup HDMI engine */ + REG_UPDATE_6(HDMI_CONTROL, + HDMI_PACKET_GEN_VERSION, 1, + HDMI_KEEPOUT_MODE, 1, + HDMI_DEEP_COLOR_ENABLE, 0, + HDMI_DATA_SCRAMBLE_EN, 0, + HDMI_NO_EXTRA_NULL_PACKET_FILLED, 1, + HDMI_CLOCK_CHANNEL_RATE, 0); + + /* Configure color depth */ + switch (crtc_timing->display_color_depth) { + case COLOR_DEPTH_888: + REG_UPDATE(HDMI_CONTROL, HDMI_DEEP_COLOR_DEPTH, 0); + break; + case COLOR_DEPTH_101010: + if (crtc_timing->pixel_encoding == PIXEL_ENCODING_YCBCR422) { + REG_UPDATE_2(HDMI_CONTROL, + HDMI_DEEP_COLOR_DEPTH, 1, + HDMI_DEEP_COLOR_ENABLE, 0); + } else { + REG_UPDATE_2(HDMI_CONTROL, + HDMI_DEEP_COLOR_DEPTH, 1, + HDMI_DEEP_COLOR_ENABLE, 1); + } + break; + case COLOR_DEPTH_121212: + if (crtc_timing->pixel_encoding == PIXEL_ENCODING_YCBCR422) { + REG_UPDATE_2(HDMI_CONTROL, + HDMI_DEEP_COLOR_DEPTH, 2, + HDMI_DEEP_COLOR_ENABLE, 0); + } else { + REG_UPDATE_2(HDMI_CONTROL, + HDMI_DEEP_COLOR_DEPTH, 2, + HDMI_DEEP_COLOR_ENABLE, 1); + } + break; + case COLOR_DEPTH_161616: + REG_UPDATE_2(HDMI_CONTROL, + HDMI_DEEP_COLOR_DEPTH, 3, + HDMI_DEEP_COLOR_ENABLE, 1); + break; + default: + break; + } + + if (actual_pix_clk_khz >= HDMI_CLOCK_CHANNEL_RATE_MORE_340M) { + /* enable HDMI data scrambler + * HDMI_CLOCK_CHANNEL_RATE_MORE_340M + * Clock channel frequency is 1/4 of character rate. + */ + REG_UPDATE_2(HDMI_CONTROL, + HDMI_DATA_SCRAMBLE_EN, 1, + HDMI_CLOCK_CHANNEL_RATE, 1); + } else if (crtc_timing->flags.LTE_340MCSC_SCRAMBLE) { + + /* TODO: New feature for DCE11, still need to implement */ + + /* enable HDMI data scrambler + * HDMI_CLOCK_CHANNEL_FREQ_EQUAL_TO_CHAR_RATE + * Clock channel frequency is the same + * as character rate + */ + REG_UPDATE_2(HDMI_CONTROL, + HDMI_DATA_SCRAMBLE_EN, 1, + HDMI_CLOCK_CHANNEL_RATE, 0); + } + + + /* Enable transmission of General Control packet on every frame */ + REG_UPDATE_3(HDMI_VBI_PACKET_CONTROL, + HDMI_GC_CONT, 1, + HDMI_GC_SEND, 1, + HDMI_NULL_SEND, 1); + + /* Disable Audio Content Protection packet transmission */ + REG_UPDATE(HDMI_VBI_PACKET_CONTROL, HDMI_ACP_SEND, 0); + + /* following belongs to audio */ + /* Enable Audio InfoFrame packet transmission. */ + REG_UPDATE(HDMI_INFOFRAME_CONTROL0, HDMI_AUDIO_INFO_SEND, 1); + + /* update double-buffered AUDIO_INFO registers immediately */ + ASSERT (enc->afmt); + enc->afmt->funcs->audio_info_immediate_update(enc->afmt); + + /* Select line number on which to send Audio InfoFrame packets */ + REG_UPDATE(HDMI_INFOFRAME_CONTROL1, HDMI_AUDIO_INFO_LINE, + VBI_LINE_0 + 2); + + /* set HDMI GC AVMUTE */ + REG_UPDATE(HDMI_GC, HDMI_GC_AVMUTE, 0); +} + +void enc3_audio_mute_control( + struct stream_encoder *enc, + bool mute) +{ + ASSERT (enc->afmt); + enc->afmt->funcs->audio_mute_control(enc->afmt, mute); +} + +void enc3_se_dp_audio_setup( + struct stream_encoder *enc, + unsigned int az_inst, + struct audio_info *info) +{ + ASSERT (enc->afmt); + enc->afmt->funcs->se_audio_setup(enc->afmt, az_inst, info); +} + +#define DP_SEC_AUD_N__DP_SEC_AUD_N__DEFAULT 0x8000 +#define DP_SEC_TIMESTAMP__DP_SEC_TIMESTAMP_MODE__AUTO_CALC 1 + +static void enc3_se_setup_dp_audio( + struct stream_encoder *enc) +{ + struct dcn10_stream_encoder *enc1 = DCN10STRENC_FROM_STRENC(enc); + + /* --- DP Audio packet configurations --- */ + + /* ATP Configuration */ + REG_SET(DP_SEC_AUD_N, 0, + DP_SEC_AUD_N, DP_SEC_AUD_N__DP_SEC_AUD_N__DEFAULT); + + /* Async/auto-calc timestamp mode */ + REG_SET(DP_SEC_TIMESTAMP, 0, DP_SEC_TIMESTAMP_MODE, + DP_SEC_TIMESTAMP__DP_SEC_TIMESTAMP_MODE__AUTO_CALC); + + ASSERT (enc->afmt); + enc->afmt->funcs->setup_dp_audio(enc->afmt); +} + +void enc3_se_dp_audio_enable( + struct stream_encoder *enc) +{ + enc1_se_enable_audio_clock(enc, true); + enc3_se_setup_dp_audio(enc); + enc1_se_enable_dp_audio(enc); +} + +static void enc3_se_setup_hdmi_audio( + struct stream_encoder *enc, + const struct audio_crtc_info *crtc_info) +{ + struct dcn10_stream_encoder *enc1 = DCN10STRENC_FROM_STRENC(enc); + + struct audio_clock_info audio_clock_info = {0}; + + /* Setup audio in AFMT - program AFMT block associated with DIO */ + ASSERT (enc->afmt); + enc->afmt->funcs->setup_hdmi_audio(enc->afmt); + + /* HDMI_AUDIO_PACKET_CONTROL */ + REG_UPDATE(HDMI_AUDIO_PACKET_CONTROL, + HDMI_AUDIO_DELAY_EN, 1); + + /* HDMI_ACR_PACKET_CONTROL */ + REG_UPDATE_3(HDMI_ACR_PACKET_CONTROL, + HDMI_ACR_AUTO_SEND, 1, + HDMI_ACR_SOURCE, 0, + HDMI_ACR_AUDIO_PRIORITY, 0); + + /* Program audio clock sample/regeneration parameters */ + get_audio_clock_info(crtc_info->color_depth, + crtc_info->requested_pixel_clock_100Hz, + crtc_info->calculated_pixel_clock_100Hz, + &audio_clock_info); + DC_LOG_HW_AUDIO( + "\n%s:Input::requested_pixel_clock_100Hz = %d" \ + "calculated_pixel_clock_100Hz = %d \n", __func__, \ + crtc_info->requested_pixel_clock_100Hz, \ + crtc_info->calculated_pixel_clock_100Hz); + + /* HDMI_ACR_32_0__HDMI_ACR_CTS_32_MASK */ + REG_UPDATE(HDMI_ACR_32_0, HDMI_ACR_CTS_32, audio_clock_info.cts_32khz); + + /* HDMI_ACR_32_1__HDMI_ACR_N_32_MASK */ + REG_UPDATE(HDMI_ACR_32_1, HDMI_ACR_N_32, audio_clock_info.n_32khz); + + /* HDMI_ACR_44_0__HDMI_ACR_CTS_44_MASK */ + REG_UPDATE(HDMI_ACR_44_0, HDMI_ACR_CTS_44, audio_clock_info.cts_44khz); + + /* HDMI_ACR_44_1__HDMI_ACR_N_44_MASK */ + REG_UPDATE(HDMI_ACR_44_1, HDMI_ACR_N_44, audio_clock_info.n_44khz); + + /* HDMI_ACR_48_0__HDMI_ACR_CTS_48_MASK */ + REG_UPDATE(HDMI_ACR_48_0, HDMI_ACR_CTS_48, audio_clock_info.cts_48khz); + + /* HDMI_ACR_48_1__HDMI_ACR_N_48_MASK */ + REG_UPDATE(HDMI_ACR_48_1, HDMI_ACR_N_48, audio_clock_info.n_48khz); + + /* Video driver cannot know in advance which sample rate will + * be used by HD Audio driver + * HDMI_ACR_PACKET_CONTROL__HDMI_ACR_N_MULTIPLE field is + * programmed below in interruppt callback + */ +} + +void enc3_se_hdmi_audio_setup( + struct stream_encoder *enc, + unsigned int az_inst, + struct audio_info *info, + struct audio_crtc_info *audio_crtc_info) +{ + enc1_se_enable_audio_clock(enc, true); + enc3_se_setup_hdmi_audio(enc, audio_crtc_info); + ASSERT (enc->afmt); + enc->afmt->funcs->se_audio_setup(enc->afmt, az_inst, info); +} + + +static const struct stream_encoder_funcs dcn30_str_enc_funcs = { + .dp_set_odm_combine = + enc3_dp_set_odm_combine, + .dp_set_stream_attribute = + enc2_stream_encoder_dp_set_stream_attribute, + .hdmi_set_stream_attribute = + enc3_stream_encoder_hdmi_set_stream_attribute, + .dvi_set_stream_attribute = + enc3_stream_encoder_dvi_set_stream_attribute, + .set_throttled_vcp_size = + enc1_stream_encoder_set_throttled_vcp_size, + .update_hdmi_info_packets = + enc3_stream_encoder_update_hdmi_info_packets, + .stop_hdmi_info_packets = + enc3_stream_encoder_stop_hdmi_info_packets, + .update_dp_info_packets = + enc3_stream_encoder_update_dp_info_packets, + .stop_dp_info_packets = + enc1_stream_encoder_stop_dp_info_packets, + .dp_blank = + enc1_stream_encoder_dp_blank, + .dp_unblank = + enc2_stream_encoder_dp_unblank, + .audio_mute_control = enc3_audio_mute_control, + + .dp_audio_setup = enc3_se_dp_audio_setup, + .dp_audio_enable = enc3_se_dp_audio_enable, + .dp_audio_disable = enc1_se_dp_audio_disable, + + .hdmi_audio_setup = enc3_se_hdmi_audio_setup, + .hdmi_audio_disable = enc1_se_hdmi_audio_disable, + .setup_stereo_sync = enc1_setup_stereo_sync, + .set_avmute = enc1_stream_encoder_set_avmute, + .dig_connect_to_otg = enc1_dig_connect_to_otg, + .dig_source_otg = enc1_dig_source_otg, + + .dp_get_pixel_format = enc1_stream_encoder_dp_get_pixel_format, + + .enc_read_state = enc3_read_state, + .dp_set_dsc_config = enc3_dp_set_dsc_config, + .dp_set_dsc_pps_info_packet = enc3_dp_set_dsc_pps_info_packet, + .set_dynamic_metadata = enc2_set_dynamic_metadata, + .hdmi_reset_stream_attribute = enc1_reset_hdmi_stream_attribute, + + .get_fifo_cal_average_level = enc2_get_fifo_cal_average_level, +}; + +void dcn30_dio_stream_encoder_construct( + struct dcn10_stream_encoder *enc1, + struct dc_context *ctx, + struct dc_bios *bp, + enum engine_id eng_id, + struct vpg *vpg, + struct afmt *afmt, + const struct dcn10_stream_enc_registers *regs, + const struct dcn10_stream_encoder_shift *se_shift, + const struct dcn10_stream_encoder_mask *se_mask) +{ + enc1->base.funcs = &dcn30_str_enc_funcs; + enc1->base.ctx = ctx; + enc1->base.id = eng_id; + enc1->base.bp = bp; + enc1->base.vpg = vpg; + enc1->base.afmt = afmt; + enc1->regs = regs; + enc1->se_shift = se_shift; + enc1->se_mask = se_mask; + enc1->base.stream_enc_inst = vpg->inst; +} + diff --git a/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_dio_stream_encoder.h b/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_dio_stream_encoder.h new file mode 100644 index 000000000..54ee230e7 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_dio_stream_encoder.h @@ -0,0 +1,323 @@ +/* + * Copyright 2020 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_DIO_STREAM_ENCODER_DCN30_H__ +#define __DC_DIO_STREAM_ENCODER_DCN30_H__ + +#include "dcn30/dcn30_vpg.h" +#include "dcn30/dcn30_afmt.h" +#include "stream_encoder.h" +#include "dcn20/dcn20_stream_encoder.h" + +/* Register bit field name change */ +#define RDPCSTX0_RDPCSTX_CLOCK_CNTL__RDPCS_SYMCLK_DIV2_GATE_DIS__SHIFT 0x8 +#define RDPCSTX0_RDPCSTX_CLOCK_CNTL__RDPCS_SYMCLK_DIV2_EN__SHIFT 0x9 +#define RDPCSTX0_RDPCSTX_CLOCK_CNTL__RDPCS_SYMCLK_DIV2_CLOCK_ON__SHIFT 0xa +#define DPCSTX0_DPCSTX_TX_CNTL__DPCS_TX_DATA_SWAP__SHIFT 0xe +#define DPCSTX0_DPCSTX_TX_CNTL__DPCS_TX_DATA_ORDER_INVERT__SHIFT 0xf + +#define RDPCSTX0_RDPCSTX_CLOCK_CNTL__RDPCS_SYMCLK_DIV2_GATE_DIS_MASK 0x00000100L +#define RDPCSTX0_RDPCSTX_CLOCK_CNTL__RDPCS_SYMCLK_DIV2_EN_MASK 0x00000200L +#define RDPCSTX0_RDPCSTX_CLOCK_CNTL__RDPCS_SYMCLK_DIV2_CLOCK_ON_MASK 0x00000400L +#define DPCSTX0_DPCSTX_TX_CNTL__DPCS_TX_DATA_SWAP_MASK 0x00004000L +#define DPCSTX0_DPCSTX_TX_CNTL__DPCS_TX_DATA_ORDER_INVERT_MASK 0x00008000L + + +#define SE_DCN3_REG_LIST(id)\ + SRI(AFMT_CNTL, DIG, id), \ + SRI(DIG_FE_CNTL, DIG, id), \ + SRI(HDMI_CONTROL, DIG, id), \ + SRI(HDMI_DB_CONTROL, DIG, id), \ + SRI(HDMI_GC, DIG, id), \ + SRI(HDMI_GENERIC_PACKET_CONTROL0, DIG, id), \ + SRI(HDMI_GENERIC_PACKET_CONTROL1, DIG, id), \ + SRI(HDMI_GENERIC_PACKET_CONTROL2, DIG, id), \ + SRI(HDMI_GENERIC_PACKET_CONTROL3, DIG, id), \ + SRI(HDMI_GENERIC_PACKET_CONTROL4, DIG, id), \ + SRI(HDMI_GENERIC_PACKET_CONTROL5, DIG, id), \ + SRI(HDMI_GENERIC_PACKET_CONTROL6, DIG, id), \ + SRI(HDMI_GENERIC_PACKET_CONTROL7, DIG, id), \ + SRI(HDMI_GENERIC_PACKET_CONTROL8, DIG, id), \ + SRI(HDMI_GENERIC_PACKET_CONTROL9, DIG, id), \ + SRI(HDMI_GENERIC_PACKET_CONTROL10, DIG, id), \ + SRI(HDMI_INFOFRAME_CONTROL0, DIG, id), \ + SRI(HDMI_INFOFRAME_CONTROL1, DIG, id), \ + SRI(HDMI_VBI_PACKET_CONTROL, DIG, id), \ + SRI(HDMI_AUDIO_PACKET_CONTROL, DIG, id),\ + SRI(HDMI_ACR_PACKET_CONTROL, DIG, id),\ + SRI(HDMI_ACR_32_0, DIG, id),\ + SRI(HDMI_ACR_32_1, DIG, id),\ + SRI(HDMI_ACR_44_0, DIG, id),\ + SRI(HDMI_ACR_44_1, DIG, id),\ + SRI(HDMI_ACR_48_0, DIG, id),\ + SRI(HDMI_ACR_48_1, DIG, id),\ + SRI(DP_DB_CNTL, DP, id), \ + SRI(DP_MSA_MISC, DP, id), \ + SRI(DP_MSA_VBID_MISC, DP, id), \ + SRI(DP_MSA_COLORIMETRY, DP, id), \ + SRI(DP_MSA_TIMING_PARAM1, DP, id), \ + SRI(DP_MSA_TIMING_PARAM2, DP, id), \ + SRI(DP_MSA_TIMING_PARAM3, DP, id), \ + SRI(DP_MSA_TIMING_PARAM4, DP, id), \ + SRI(DP_MSE_RATE_CNTL, DP, id), \ + SRI(DP_MSE_RATE_UPDATE, DP, id), \ + SRI(DP_PIXEL_FORMAT, DP, id), \ + SRI(DP_SEC_CNTL, DP, id), \ + SRI(DP_SEC_CNTL1, DP, id), \ + SRI(DP_SEC_CNTL2, DP, id), \ + SRI(DP_SEC_CNTL5, DP, id), \ + SRI(DP_SEC_CNTL6, DP, id), \ + SRI(DP_STEER_FIFO, DP, id), \ + SRI(DP_VID_M, DP, id), \ + SRI(DP_VID_N, DP, id), \ + SRI(DP_VID_STREAM_CNTL, DP, id), \ + SRI(DP_VID_TIMING, DP, id), \ + SRI(DP_SEC_AUD_N, DP, id), \ + SRI(DP_SEC_AUD_N_READBACK, DP, id), \ + SRI(DP_SEC_AUD_M_READBACK, DP, id), \ + SRI(DP_SEC_TIMESTAMP, DP, id), \ + SRI(DP_DSC_CNTL, DP, id), \ + SRI(DP_DSC_BYTES_PER_PIXEL, DP, id), \ + SRI(DP_SEC_METADATA_TRANSMISSION, DP, id), \ + SRI(HDMI_METADATA_PACKET_CONTROL, DIG, id), \ + SRI(DP_SEC_FRAMING4, DP, id), \ + SRI(DP_GSP11_CNTL, DP, id), \ + SRI(DME_CONTROL, DME, id),\ + SRI(DP_SEC_METADATA_TRANSMISSION, DP, id), \ + SRI(HDMI_METADATA_PACKET_CONTROL, DIG, id), \ + SRI(DIG_FE_CNTL, DIG, id), \ + SRI(DIG_FIFO_STATUS, DIG, id), \ + SRI(DIG_CLOCK_PATTERN, DIG, id) + + +#define SE_COMMON_MASK_SH_LIST_DCN30(mask_sh)\ + SE_SF(DP0_DP_PIXEL_FORMAT, DP_PIXEL_ENCODING, mask_sh),\ + SE_SF(DP0_DP_PIXEL_FORMAT, DP_COMPONENT_DEPTH, mask_sh),\ + SE_SF(DIG0_HDMI_CONTROL, HDMI_PACKET_GEN_VERSION, mask_sh),\ + SE_SF(DIG0_HDMI_CONTROL, HDMI_KEEPOUT_MODE, mask_sh),\ + SE_SF(DIG0_HDMI_CONTROL, HDMI_DEEP_COLOR_ENABLE, mask_sh),\ + SE_SF(DIG0_HDMI_CONTROL, HDMI_DEEP_COLOR_DEPTH, mask_sh),\ + SE_SF(DIG0_HDMI_CONTROL, HDMI_DATA_SCRAMBLE_EN, mask_sh),\ + SE_SF(DIG0_HDMI_CONTROL, HDMI_NO_EXTRA_NULL_PACKET_FILLED, mask_sh),\ + SE_SF(DIG0_HDMI_VBI_PACKET_CONTROL, HDMI_GC_CONT, mask_sh),\ + SE_SF(DIG0_HDMI_VBI_PACKET_CONTROL, HDMI_GC_SEND, mask_sh),\ + SE_SF(DIG0_HDMI_VBI_PACKET_CONTROL, HDMI_NULL_SEND, mask_sh),\ + SE_SF(DIG0_HDMI_VBI_PACKET_CONTROL, HDMI_ACP_SEND, mask_sh),\ + SE_SF(DIG0_HDMI_INFOFRAME_CONTROL0, HDMI_AUDIO_INFO_SEND, mask_sh),\ + SE_SF(DIG0_HDMI_INFOFRAME_CONTROL1, HDMI_AUDIO_INFO_LINE, mask_sh),\ + SE_SF(DIG0_HDMI_GC, HDMI_GC_AVMUTE, mask_sh),\ + SE_SF(DP0_DP_MSE_RATE_CNTL, DP_MSE_RATE_X, mask_sh),\ + SE_SF(DP0_DP_MSE_RATE_CNTL, DP_MSE_RATE_Y, mask_sh),\ + SE_SF(DP0_DP_MSE_RATE_UPDATE, DP_MSE_RATE_UPDATE_PENDING, mask_sh),\ + SE_SF(DP0_DP_SEC_CNTL, DP_SEC_GSP0_ENABLE, mask_sh),\ + SE_SF(DP0_DP_SEC_CNTL, DP_SEC_STREAM_ENABLE, mask_sh),\ + SE_SF(DP0_DP_SEC_CNTL, DP_SEC_GSP1_ENABLE, mask_sh),\ + SE_SF(DP0_DP_SEC_CNTL, DP_SEC_GSP2_ENABLE, mask_sh),\ + SE_SF(DP0_DP_SEC_CNTL, DP_SEC_GSP3_ENABLE, mask_sh),\ + SE_SF(DP0_DP_SEC_CNTL, DP_SEC_MPG_ENABLE, mask_sh),\ + SE_SF(DP0_DP_SEC_CNTL2, DP_SEC_GSP4_SEND, mask_sh),\ + SE_SF(DP0_DP_SEC_CNTL2, DP_SEC_GSP4_SEND_PENDING, mask_sh),\ + SE_SF(DP0_DP_SEC_CNTL4, DP_SEC_GSP4_LINE_NUM, mask_sh),\ + SE_SF(DP0_DP_SEC_CNTL2, DP_SEC_GSP4_SEND_ANY_LINE, mask_sh),\ + SE_SF(DP0_DP_VID_STREAM_CNTL, DP_VID_STREAM_DIS_DEFER, mask_sh),\ + SE_SF(DP0_DP_VID_STREAM_CNTL, DP_VID_STREAM_ENABLE, mask_sh),\ + SE_SF(DP0_DP_VID_STREAM_CNTL, DP_VID_STREAM_STATUS, mask_sh),\ + SE_SF(DP0_DP_STEER_FIFO, DP_STEER_FIFO_RESET, mask_sh),\ + SE_SF(DP0_DP_VID_TIMING, DP_VID_M_N_GEN_EN, mask_sh),\ + SE_SF(DP0_DP_VID_N, DP_VID_N, mask_sh),\ + SE_SF(DP0_DP_VID_M, DP_VID_M, mask_sh),\ + SE_SF(DIG0_DIG_FE_CNTL, DIG_START, mask_sh),\ + SE_SF(DIG0_HDMI_AUDIO_PACKET_CONTROL, HDMI_AUDIO_DELAY_EN, mask_sh),\ + SE_SF(DIG0_HDMI_ACR_PACKET_CONTROL, HDMI_ACR_AUTO_SEND, mask_sh),\ + SE_SF(DIG0_HDMI_ACR_PACKET_CONTROL, HDMI_ACR_SOURCE, mask_sh),\ + SE_SF(DIG0_HDMI_ACR_PACKET_CONTROL, HDMI_ACR_AUDIO_PRIORITY, mask_sh),\ + SE_SF(DIG0_HDMI_ACR_32_0, HDMI_ACR_CTS_32, mask_sh),\ + SE_SF(DIG0_HDMI_ACR_32_1, HDMI_ACR_N_32, mask_sh),\ + SE_SF(DIG0_HDMI_ACR_44_0, HDMI_ACR_CTS_44, mask_sh),\ + SE_SF(DIG0_HDMI_ACR_44_1, HDMI_ACR_N_44, mask_sh),\ + SE_SF(DIG0_HDMI_ACR_48_0, HDMI_ACR_CTS_48, mask_sh),\ + SE_SF(DIG0_HDMI_ACR_48_1, HDMI_ACR_N_48, mask_sh),\ + SE_SF(DP0_DP_SEC_AUD_N, DP_SEC_AUD_N, mask_sh),\ + SE_SF(DP0_DP_SEC_AUD_N_READBACK, DP_SEC_AUD_N_READBACK, mask_sh),\ + SE_SF(DP0_DP_SEC_AUD_M_READBACK, DP_SEC_AUD_M_READBACK, mask_sh),\ + SE_SF(DP0_DP_SEC_TIMESTAMP, DP_SEC_TIMESTAMP_MODE, mask_sh),\ + SE_SF(DP0_DP_SEC_CNTL, DP_SEC_ASP_ENABLE, mask_sh),\ + SE_SF(DP0_DP_SEC_CNTL, DP_SEC_ATP_ENABLE, mask_sh),\ + SE_SF(DP0_DP_SEC_CNTL, DP_SEC_AIP_ENABLE, mask_sh),\ + SE_SF(DP0_DP_SEC_CNTL, DP_SEC_ACM_ENABLE, mask_sh),\ + SE_SF(DIG0_AFMT_CNTL, AFMT_AUDIO_CLOCK_EN, mask_sh),\ + SE_SF(DIG0_HDMI_CONTROL, HDMI_CLOCK_CHANNEL_RATE, mask_sh),\ + SE_SF(DIG0_DIG_FE_CNTL, TMDS_PIXEL_ENCODING, mask_sh),\ + SE_SF(DIG0_DIG_FE_CNTL, TMDS_COLOR_FORMAT, mask_sh),\ + SE_SF(DIG0_DIG_FE_CNTL, DIG_STEREOSYNC_SELECT, mask_sh),\ + SE_SF(DIG0_DIG_FE_CNTL, DIG_STEREOSYNC_GATE_EN, mask_sh),\ + SE_SF(DIG0_DIG_FIFO_STATUS, DIG_FIFO_LEVEL_ERROR, mask_sh),\ + SE_SF(DIG0_DIG_FIFO_STATUS, DIG_FIFO_USE_OVERWRITE_LEVEL, mask_sh),\ + SE_SF(DIG0_DIG_FIFO_STATUS, DIG_FIFO_OVERWRITE_LEVEL, mask_sh),\ + SE_SF(DIG0_DIG_FIFO_STATUS, DIG_FIFO_ERROR_ACK, mask_sh),\ + SE_SF(DIG0_DIG_FIFO_STATUS, DIG_FIFO_CAL_AVERAGE_LEVEL, mask_sh),\ + SE_SF(DIG0_DIG_FIFO_STATUS, DIG_FIFO_MAXIMUM_LEVEL, mask_sh),\ + SE_SF(DIG0_DIG_FIFO_STATUS, DIG_FIFO_MINIMUM_LEVEL, mask_sh),\ + SE_SF(DIG0_DIG_FIFO_STATUS, DIG_FIFO_READ_CLOCK_SRC, mask_sh),\ + SE_SF(DIG0_DIG_FIFO_STATUS, DIG_FIFO_CALIBRATED, mask_sh),\ + SE_SF(DIG0_DIG_FIFO_STATUS, DIG_FIFO_FORCE_RECAL_AVERAGE, mask_sh),\ + SE_SF(DIG0_DIG_FIFO_STATUS, DIG_FIFO_FORCE_RECOMP_MINMAX, mask_sh),\ + SE_SF(DP0_DP_SEC_CNTL, DP_SEC_GSP4_ENABLE, mask_sh),\ + SE_SF(DP0_DP_SEC_CNTL, DP_SEC_GSP5_ENABLE, mask_sh),\ + SE_SF(DP0_DP_SEC_CNTL, DP_SEC_GSP6_ENABLE, mask_sh),\ + SE_SF(DP0_DP_SEC_CNTL, DP_SEC_GSP7_ENABLE, mask_sh),\ + SE_SF(DP0_DP_SEC_CNTL1, DP_SEC_GSP5_LINE_REFERENCE, mask_sh),\ + SE_SF(DP0_DP_SEC_CNTL2, DP_SEC_GSP7_SEND, mask_sh),\ + SE_SF(DP0_DP_SEC_CNTL5, DP_SEC_GSP5_LINE_NUM, mask_sh),\ + SE_SF(DP0_DP_SEC_CNTL6, DP_SEC_GSP7_LINE_NUM, mask_sh),\ + SE_SF(DP0_DP_SEC_CNTL2, DP_SEC_GSP11_PPS, mask_sh),\ + SE_SF(DP0_DP_GSP11_CNTL, DP_SEC_GSP11_ENABLE, mask_sh),\ + SE_SF(DP0_DP_GSP11_CNTL, DP_SEC_GSP11_LINE_NUM, mask_sh),\ + SE_SF(DP0_DP_DB_CNTL, DP_DB_DISABLE, mask_sh),\ + SE_SF(DP0_DP_MSA_COLORIMETRY, DP_MSA_MISC0, mask_sh),\ + SE_SF(DP0_DP_MSA_TIMING_PARAM1, DP_MSA_HTOTAL, mask_sh),\ + SE_SF(DP0_DP_MSA_TIMING_PARAM1, DP_MSA_VTOTAL, mask_sh),\ + SE_SF(DP0_DP_MSA_TIMING_PARAM2, DP_MSA_HSTART, mask_sh),\ + SE_SF(DP0_DP_MSA_TIMING_PARAM2, DP_MSA_VSTART, mask_sh),\ + SE_SF(DP0_DP_MSA_TIMING_PARAM3, DP_MSA_HSYNCWIDTH, mask_sh),\ + SE_SF(DP0_DP_MSA_TIMING_PARAM3, DP_MSA_HSYNCPOLARITY, mask_sh),\ + SE_SF(DP0_DP_MSA_TIMING_PARAM3, DP_MSA_VSYNCWIDTH, mask_sh),\ + SE_SF(DP0_DP_MSA_TIMING_PARAM3, DP_MSA_VSYNCPOLARITY, mask_sh),\ + SE_SF(DP0_DP_MSA_TIMING_PARAM4, DP_MSA_HWIDTH, mask_sh),\ + SE_SF(DP0_DP_MSA_TIMING_PARAM4, DP_MSA_VHEIGHT, mask_sh),\ + SE_SF(DIG0_HDMI_DB_CONTROL, HDMI_DB_DISABLE, mask_sh),\ + SE_SF(DP0_DP_VID_TIMING, DP_VID_N_MUL, mask_sh),\ + SE_SF(DIG0_DIG_FE_CNTL, DIG_SOURCE_SELECT, mask_sh), \ + SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL0, HDMI_GENERIC0_CONT, mask_sh),\ + SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL0, HDMI_GENERIC0_SEND, mask_sh),\ + SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL0, HDMI_GENERIC1_CONT, mask_sh),\ + SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL0, HDMI_GENERIC1_SEND, mask_sh),\ + SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL0, HDMI_GENERIC2_CONT, mask_sh),\ + SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL0, HDMI_GENERIC2_SEND, mask_sh),\ + SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL0, HDMI_GENERIC3_CONT, mask_sh),\ + SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL0, HDMI_GENERIC3_SEND, mask_sh),\ + SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL0, HDMI_GENERIC4_CONT, mask_sh),\ + SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL0, HDMI_GENERIC4_SEND, mask_sh),\ + SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL0, HDMI_GENERIC5_CONT, mask_sh),\ + SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL0, HDMI_GENERIC5_SEND, mask_sh),\ + SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL0, HDMI_GENERIC6_CONT, mask_sh),\ + SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL0, HDMI_GENERIC6_SEND, mask_sh),\ + SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL0, HDMI_GENERIC7_CONT, mask_sh),\ + SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL0, HDMI_GENERIC7_SEND, mask_sh),\ + SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL6, HDMI_GENERIC8_CONT, mask_sh),\ + SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL6, HDMI_GENERIC8_SEND, mask_sh),\ + SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL6, HDMI_GENERIC9_CONT, mask_sh),\ + SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL6, HDMI_GENERIC9_SEND, mask_sh),\ + SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL6, HDMI_GENERIC10_CONT, mask_sh),\ + SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL6, HDMI_GENERIC10_SEND, mask_sh),\ + SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL6, HDMI_GENERIC11_CONT, mask_sh),\ + SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL6, HDMI_GENERIC11_SEND, mask_sh),\ + SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL6, HDMI_GENERIC12_CONT, mask_sh),\ + SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL6, HDMI_GENERIC12_SEND, mask_sh),\ + SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL6, HDMI_GENERIC13_CONT, mask_sh),\ + SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL6, HDMI_GENERIC13_SEND, mask_sh),\ + SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL6, HDMI_GENERIC14_CONT, mask_sh),\ + SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL6, HDMI_GENERIC14_SEND, mask_sh),\ + SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL1, HDMI_GENERIC0_LINE, mask_sh),\ + SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL1, HDMI_GENERIC1_LINE, mask_sh),\ + SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL2, HDMI_GENERIC2_LINE, mask_sh),\ + SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL2, HDMI_GENERIC3_LINE, mask_sh),\ + SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL3, HDMI_GENERIC4_LINE, mask_sh),\ + SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL3, HDMI_GENERIC5_LINE, mask_sh),\ + SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL4, HDMI_GENERIC6_LINE, mask_sh),\ + SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL4, HDMI_GENERIC7_LINE, mask_sh),\ + SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL7, HDMI_GENERIC8_LINE, mask_sh),\ + SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL7, HDMI_GENERIC9_LINE, mask_sh),\ + SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL8, HDMI_GENERIC10_LINE, mask_sh),\ + SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL8, HDMI_GENERIC11_LINE, mask_sh),\ + SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL9, HDMI_GENERIC12_LINE, mask_sh),\ + SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL9, HDMI_GENERIC13_LINE, mask_sh),\ + SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL10, HDMI_GENERIC14_LINE, mask_sh),\ + SE_SF(DP0_DP_DSC_CNTL, DP_DSC_MODE, mask_sh),\ + SE_SF(DP0_DP_DSC_CNTL, DP_DSC_SLICE_WIDTH, mask_sh),\ + SE_SF(DP0_DP_DSC_BYTES_PER_PIXEL, DP_DSC_BYTES_PER_PIXEL, mask_sh),\ + SE_SF(DP0_DP_MSA_VBID_MISC, DP_VBID6_LINE_REFERENCE, mask_sh),\ + SE_SF(DP0_DP_MSA_VBID_MISC, DP_VBID6_LINE_NUM, mask_sh),\ + SE_SF(DME0_DME_CONTROL, METADATA_ENGINE_EN, mask_sh),\ + SE_SF(DME0_DME_CONTROL, METADATA_HUBP_REQUESTOR_ID, mask_sh),\ + SE_SF(DME0_DME_CONTROL, METADATA_STREAM_TYPE, mask_sh),\ + SE_SF(DP0_DP_SEC_METADATA_TRANSMISSION, DP_SEC_METADATA_PACKET_ENABLE, mask_sh),\ + SE_SF(DP0_DP_SEC_METADATA_TRANSMISSION, DP_SEC_METADATA_PACKET_LINE_REFERENCE, mask_sh),\ + SE_SF(DP0_DP_SEC_METADATA_TRANSMISSION, DP_SEC_METADATA_PACKET_LINE, mask_sh),\ + SE_SF(DIG0_HDMI_METADATA_PACKET_CONTROL, HDMI_METADATA_PACKET_ENABLE, mask_sh),\ + SE_SF(DIG0_HDMI_METADATA_PACKET_CONTROL, HDMI_METADATA_PACKET_LINE_REFERENCE, mask_sh),\ + SE_SF(DIG0_HDMI_METADATA_PACKET_CONTROL, HDMI_METADATA_PACKET_LINE, mask_sh),\ + SE_SF(DIG0_DIG_FE_CNTL, DOLBY_VISION_EN, mask_sh),\ + SE_SF(DP0_DP_PIXEL_FORMAT, DP_PIXEL_COMBINE, mask_sh),\ + SE_SF(DP0_DP_SEC_FRAMING4, DP_SST_SDP_SPLITTING, mask_sh),\ + SE_SF(DIG0_DIG_CLOCK_PATTERN, DIG_CLOCK_PATTERN, mask_sh) + +void dcn30_dio_stream_encoder_construct( + struct dcn10_stream_encoder *enc1, + struct dc_context *ctx, + struct dc_bios *bp, + enum engine_id eng_id, + struct vpg *vpg, + struct afmt *afmt, + const struct dcn10_stream_enc_registers *regs, + const struct dcn10_stream_encoder_shift *se_shift, + const struct dcn10_stream_encoder_mask *se_mask); + +void enc3_stream_encoder_update_hdmi_info_packets( + struct stream_encoder *enc, + const struct encoder_info_frame *info_frame); + +void enc3_stream_encoder_stop_hdmi_info_packets( + struct stream_encoder *enc); + +void enc3_stream_encoder_update_dp_info_packets( + struct stream_encoder *enc, + const struct encoder_info_frame *info_frame); + +void enc3_audio_mute_control( + struct stream_encoder *enc, + bool mute); + +void enc3_se_dp_audio_setup( + struct stream_encoder *enc, + unsigned int az_inst, + struct audio_info *info); + +void enc3_se_dp_audio_enable( + struct stream_encoder *enc); + +void enc3_se_hdmi_audio_setup( + struct stream_encoder *enc, + unsigned int az_inst, + struct audio_info *info, + struct audio_crtc_info *audio_crtc_info); + +void enc3_dp_set_dsc_pps_info_packet( + struct stream_encoder *enc, + bool enable, + uint8_t *dsc_packed_pps, + bool immediate_update); + +#endif /* __DC_DIO_STREAM_ENCODER_DCN30_H__ */ diff --git a/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_dpp.c b/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_dpp.c new file mode 100644 index 000000000..50dc83404 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_dpp.c @@ -0,0 +1,1490 @@ +/* + * Copyright 2020 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 "core_types.h" +#include "reg_helper.h" +#include "dcn30_dpp.h" +#include "basics/conversion.h" +#include "dcn30_cm_common.h" + +#define REG(reg)\ + dpp->tf_regs->reg + +#define CTX \ + dpp->base.ctx + +#undef FN +#define FN(reg_name, field_name) \ + dpp->tf_shift->field_name, dpp->tf_mask->field_name + + +void dpp30_read_state(struct dpp *dpp_base, struct dcn_dpp_state *s) +{ + struct dcn3_dpp *dpp = TO_DCN30_DPP(dpp_base); + + REG_GET(DPP_CONTROL, + DPP_CLOCK_ENABLE, &s->is_enabled); + + // TODO: Implement for DCN3 +} +/*program post scaler scs block in dpp CM*/ +void dpp3_program_post_csc( + struct dpp *dpp_base, + enum dc_color_space color_space, + enum dcn10_input_csc_select input_select, + const struct out_csc_color_matrix *tbl_entry) +{ + struct dcn3_dpp *dpp = TO_DCN30_DPP(dpp_base); + int i; + int arr_size = sizeof(dpp_input_csc_matrix)/sizeof(struct dpp_input_csc_matrix); + const uint16_t *regval = NULL; + uint32_t cur_select = 0; + enum dcn10_input_csc_select select; + struct color_matrices_reg gam_regs; + + if (input_select == INPUT_CSC_SELECT_BYPASS) { + REG_SET(CM_POST_CSC_CONTROL, 0, CM_POST_CSC_MODE, 0); + return; + } + + if (tbl_entry == NULL) { + for (i = 0; i < arr_size; i++) + if (dpp_input_csc_matrix[i].color_space == color_space) { + regval = dpp_input_csc_matrix[i].regval; + break; + } + + if (regval == NULL) { + BREAK_TO_DEBUGGER(); + return; + } + } else { + regval = tbl_entry->regval; + } + + /* determine which CSC matrix (icsc or coma) we are using + * currently. select the alternate set to double buffer + * the CSC update so CSC is updated on frame boundary + */ + REG_GET(CM_POST_CSC_CONTROL, + CM_POST_CSC_MODE_CURRENT, &cur_select); + + if (cur_select != INPUT_CSC_SELECT_ICSC) + select = INPUT_CSC_SELECT_ICSC; + else + select = INPUT_CSC_SELECT_COMA; + + gam_regs.shifts.csc_c11 = dpp->tf_shift->CM_POST_CSC_C11; + gam_regs.masks.csc_c11 = dpp->tf_mask->CM_POST_CSC_C11; + gam_regs.shifts.csc_c12 = dpp->tf_shift->CM_POST_CSC_C12; + gam_regs.masks.csc_c12 = dpp->tf_mask->CM_POST_CSC_C12; + + if (select == INPUT_CSC_SELECT_ICSC) { + + gam_regs.csc_c11_c12 = REG(CM_POST_CSC_C11_C12); + gam_regs.csc_c33_c34 = REG(CM_POST_CSC_C33_C34); + + } else { + + gam_regs.csc_c11_c12 = REG(CM_POST_CSC_B_C11_C12); + gam_regs.csc_c33_c34 = REG(CM_POST_CSC_B_C33_C34); + + } + + cm_helper_program_color_matrices( + dpp->base.ctx, + regval, + &gam_regs); + + REG_SET(CM_POST_CSC_CONTROL, 0, + CM_POST_CSC_MODE, select); +} + + +/*CNVC degam unit has read only LUTs*/ +void dpp3_set_pre_degam(struct dpp *dpp_base, enum dc_transfer_func_predefined tr) +{ + struct dcn3_dpp *dpp = TO_DCN30_DPP(dpp_base); + int pre_degam_en = 1; + int degamma_lut_selection = 0; + + switch (tr) { + case TRANSFER_FUNCTION_LINEAR: + case TRANSFER_FUNCTION_UNITY: + pre_degam_en = 0; //bypass + break; + case TRANSFER_FUNCTION_SRGB: + degamma_lut_selection = 0; + break; + case TRANSFER_FUNCTION_BT709: + degamma_lut_selection = 4; + break; + case TRANSFER_FUNCTION_PQ: + degamma_lut_selection = 5; + break; + case TRANSFER_FUNCTION_HLG: + degamma_lut_selection = 6; + break; + case TRANSFER_FUNCTION_GAMMA22: + degamma_lut_selection = 1; + break; + case TRANSFER_FUNCTION_GAMMA24: + degamma_lut_selection = 2; + break; + case TRANSFER_FUNCTION_GAMMA26: + degamma_lut_selection = 3; + break; + default: + pre_degam_en = 0; + break; + } + + REG_SET_2(PRE_DEGAM, 0, + PRE_DEGAM_MODE, pre_degam_en, + PRE_DEGAM_SELECT, degamma_lut_selection); +} + +void dpp3_cnv_setup ( + struct dpp *dpp_base, + enum surface_pixel_format format, + enum expansion_mode mode, + struct dc_csc_transform input_csc_color_matrix, + enum dc_color_space input_color_space, + struct cnv_alpha_2bit_lut *alpha_2bit_lut) +{ + struct dcn3_dpp *dpp = TO_DCN30_DPP(dpp_base); + uint32_t pixel_format = 0; + uint32_t alpha_en = 1; + enum dc_color_space color_space = COLOR_SPACE_SRGB; + enum dcn10_input_csc_select select = INPUT_CSC_SELECT_BYPASS; + bool force_disable_cursor = false; + uint32_t is_2bit = 0; + uint32_t alpha_plane_enable = 0; + uint32_t dealpha_en = 0, dealpha_ablnd_en = 0; + uint32_t realpha_en = 0, realpha_ablnd_en = 0; + uint32_t program_prealpha_dealpha = 0; + struct out_csc_color_matrix tbl_entry; + int i; + + REG_SET_2(FORMAT_CONTROL, 0, + CNVC_BYPASS, 0, + FORMAT_EXPANSION_MODE, mode); + + REG_UPDATE(FORMAT_CONTROL, FORMAT_CNV16, 0); + REG_UPDATE(FORMAT_CONTROL, CNVC_BYPASS_MSB_ALIGN, 0); + REG_UPDATE(FORMAT_CONTROL, CLAMP_POSITIVE, 0); + REG_UPDATE(FORMAT_CONTROL, CLAMP_POSITIVE_C, 0); + + REG_UPDATE(FORMAT_CONTROL, FORMAT_CROSSBAR_R, 0); + REG_UPDATE(FORMAT_CONTROL, FORMAT_CROSSBAR_G, 1); + REG_UPDATE(FORMAT_CONTROL, FORMAT_CROSSBAR_B, 2); + + switch (format) { + case SURFACE_PIXEL_FORMAT_GRPH_ARGB1555: + pixel_format = 1; + break; + case SURFACE_PIXEL_FORMAT_GRPH_RGB565: + pixel_format = 3; + alpha_en = 0; + break; + case SURFACE_PIXEL_FORMAT_GRPH_ARGB8888: + case SURFACE_PIXEL_FORMAT_GRPH_ABGR8888: + pixel_format = 8; + break; + case SURFACE_PIXEL_FORMAT_GRPH_ARGB2101010: + case SURFACE_PIXEL_FORMAT_GRPH_ABGR2101010: + pixel_format = 10; + is_2bit = 1; + break; + case SURFACE_PIXEL_FORMAT_VIDEO_420_YCbCr: + force_disable_cursor = false; + pixel_format = 65; + color_space = COLOR_SPACE_YCBCR709; + select = INPUT_CSC_SELECT_ICSC; + break; + case SURFACE_PIXEL_FORMAT_VIDEO_420_YCrCb: + force_disable_cursor = true; + pixel_format = 64; + color_space = COLOR_SPACE_YCBCR709; + select = INPUT_CSC_SELECT_ICSC; + break; + case SURFACE_PIXEL_FORMAT_VIDEO_420_10bpc_YCbCr: + force_disable_cursor = true; + pixel_format = 67; + color_space = COLOR_SPACE_YCBCR709; + select = INPUT_CSC_SELECT_ICSC; + break; + case SURFACE_PIXEL_FORMAT_VIDEO_420_10bpc_YCrCb: + force_disable_cursor = true; + pixel_format = 66; + color_space = COLOR_SPACE_YCBCR709; + select = INPUT_CSC_SELECT_ICSC; + break; + case SURFACE_PIXEL_FORMAT_GRPH_ARGB16161616: + case SURFACE_PIXEL_FORMAT_GRPH_ABGR16161616: + pixel_format = 26; /* ARGB16161616_UNORM */ + break; + case SURFACE_PIXEL_FORMAT_GRPH_ARGB16161616F: + pixel_format = 24; + break; + case SURFACE_PIXEL_FORMAT_GRPH_ABGR16161616F: + pixel_format = 25; + break; + case SURFACE_PIXEL_FORMAT_VIDEO_AYCrCb8888: + pixel_format = 12; + color_space = COLOR_SPACE_YCBCR709; + select = INPUT_CSC_SELECT_ICSC; + break; + case SURFACE_PIXEL_FORMAT_GRPH_RGB111110_FIX: + pixel_format = 112; + break; + case SURFACE_PIXEL_FORMAT_GRPH_BGR101111_FIX: + pixel_format = 113; + break; + case SURFACE_PIXEL_FORMAT_VIDEO_ACrYCb2101010: + pixel_format = 114; + color_space = COLOR_SPACE_YCBCR709; + select = INPUT_CSC_SELECT_ICSC; + is_2bit = 1; + break; + case SURFACE_PIXEL_FORMAT_VIDEO_CrYCbA1010102: + pixel_format = 115; + color_space = COLOR_SPACE_YCBCR709; + select = INPUT_CSC_SELECT_ICSC; + is_2bit = 1; + break; + case SURFACE_PIXEL_FORMAT_GRPH_RGBE: + pixel_format = 116; + alpha_plane_enable = 0; + break; + case SURFACE_PIXEL_FORMAT_GRPH_RGBE_ALPHA: + pixel_format = 116; + alpha_plane_enable = 1; + break; + case SURFACE_PIXEL_FORMAT_GRPH_RGB111110_FLOAT: + pixel_format = 118; + break; + case SURFACE_PIXEL_FORMAT_GRPH_BGR101111_FLOAT: + pixel_format = 119; + break; + default: + break; + } + + /* Set default color space based on format if none is given. */ + color_space = input_color_space ? input_color_space : color_space; + + if (is_2bit == 1 && alpha_2bit_lut != NULL) { + REG_UPDATE(ALPHA_2BIT_LUT, ALPHA_2BIT_LUT0, alpha_2bit_lut->lut0); + REG_UPDATE(ALPHA_2BIT_LUT, ALPHA_2BIT_LUT1, alpha_2bit_lut->lut1); + REG_UPDATE(ALPHA_2BIT_LUT, ALPHA_2BIT_LUT2, alpha_2bit_lut->lut2); + REG_UPDATE(ALPHA_2BIT_LUT, ALPHA_2BIT_LUT3, alpha_2bit_lut->lut3); + } + + REG_SET_2(CNVC_SURFACE_PIXEL_FORMAT, 0, + CNVC_SURFACE_PIXEL_FORMAT, pixel_format, + CNVC_ALPHA_PLANE_ENABLE, alpha_plane_enable); + REG_UPDATE(FORMAT_CONTROL, FORMAT_CONTROL__ALPHA_EN, alpha_en); + + if (program_prealpha_dealpha) { + dealpha_en = 1; + realpha_en = 1; + } + REG_SET_2(PRE_DEALPHA, 0, + PRE_DEALPHA_EN, dealpha_en, + PRE_DEALPHA_ABLND_EN, dealpha_ablnd_en); + REG_SET_2(PRE_REALPHA, 0, + PRE_REALPHA_EN, realpha_en, + PRE_REALPHA_ABLND_EN, realpha_ablnd_en); + + /* If input adjustment exists, program the ICSC with those values. */ + if (input_csc_color_matrix.enable_adjustment == true) { + for (i = 0; i < 12; i++) + tbl_entry.regval[i] = input_csc_color_matrix.matrix[i]; + + tbl_entry.color_space = input_color_space; + + if (color_space >= COLOR_SPACE_YCBCR601) + select = INPUT_CSC_SELECT_ICSC; + else + select = INPUT_CSC_SELECT_BYPASS; + + dpp3_program_post_csc(dpp_base, color_space, select, + &tbl_entry); + } else { + dpp3_program_post_csc(dpp_base, color_space, select, NULL); + } + + if (force_disable_cursor) { + REG_UPDATE(CURSOR_CONTROL, + CURSOR_ENABLE, 0); + REG_UPDATE(CURSOR0_CONTROL, + CUR0_ENABLE, 0); + } +} + +#define IDENTITY_RATIO(ratio) (dc_fixpt_u3d19(ratio) == (1 << 19)) + +void dpp3_set_cursor_attributes( + struct dpp *dpp_base, + struct dc_cursor_attributes *cursor_attributes) +{ + enum dc_cursor_color_format color_format = cursor_attributes->color_format; + struct dcn3_dpp *dpp = TO_DCN30_DPP(dpp_base); + int cur_rom_en = 0; + + if (color_format == CURSOR_MODE_COLOR_PRE_MULTIPLIED_ALPHA || + color_format == CURSOR_MODE_COLOR_UN_PRE_MULTIPLIED_ALPHA) { + if (cursor_attributes->attribute_flags.bits.ENABLE_CURSOR_DEGAMMA) { + cur_rom_en = 1; + } + } + + REG_UPDATE_3(CURSOR0_CONTROL, + CUR0_MODE, color_format, + CUR0_EXPANSION_MODE, 0, + CUR0_ROM_EN, cur_rom_en); + + if (color_format == CURSOR_MODE_MONO) { + /* todo: clarify what to program these to */ + REG_UPDATE(CURSOR0_COLOR0, + CUR0_COLOR0, 0x00000000); + REG_UPDATE(CURSOR0_COLOR1, + CUR0_COLOR1, 0xFFFFFFFF); + } + + dpp_base->att.cur0_ctl.bits.expansion_mode = 0; + dpp_base->att.cur0_ctl.bits.cur0_rom_en = cur_rom_en; + dpp_base->att.cur0_ctl.bits.mode = color_format; +} + + +bool dpp3_get_optimal_number_of_taps( + struct dpp *dpp, + struct scaler_data *scl_data, + const struct scaling_taps *in_taps) +{ + int num_part_y, num_part_c; + int max_taps_y, max_taps_c; + int min_taps_y, min_taps_c; + enum lb_memory_config lb_config; + + if (scl_data->viewport.width > scl_data->h_active && + dpp->ctx->dc->debug.max_downscale_src_width != 0 && + scl_data->viewport.width > dpp->ctx->dc->debug.max_downscale_src_width) + return false; + + /* + * Set default taps if none are provided + * From programming guide: taps = min{ ceil(2*H_RATIO,1), 8} for downscaling + * taps = 4 for upscaling + */ + if (in_taps->h_taps == 0) { + if (dc_fixpt_ceil(scl_data->ratios.horz) > 1) + scl_data->taps.h_taps = min(2 * dc_fixpt_ceil(scl_data->ratios.horz), 8); + else + scl_data->taps.h_taps = 4; + } else + scl_data->taps.h_taps = in_taps->h_taps; + if (in_taps->v_taps == 0) { + if (dc_fixpt_ceil(scl_data->ratios.vert) > 1) + scl_data->taps.v_taps = min(dc_fixpt_ceil(dc_fixpt_mul_int(scl_data->ratios.vert, 2)), 8); + else + scl_data->taps.v_taps = 4; + } else + scl_data->taps.v_taps = in_taps->v_taps; + if (in_taps->v_taps_c == 0) { + if (dc_fixpt_ceil(scl_data->ratios.vert_c) > 1) + scl_data->taps.v_taps_c = min(dc_fixpt_ceil(dc_fixpt_mul_int(scl_data->ratios.vert_c, 2)), 8); + else + scl_data->taps.v_taps_c = 4; + } else + scl_data->taps.v_taps_c = in_taps->v_taps_c; + if (in_taps->h_taps_c == 0) { + if (dc_fixpt_ceil(scl_data->ratios.horz_c) > 1) + scl_data->taps.h_taps_c = min(2 * dc_fixpt_ceil(scl_data->ratios.horz_c), 8); + else + scl_data->taps.h_taps_c = 4; + } else if ((in_taps->h_taps_c % 2) != 0 && in_taps->h_taps_c != 1) + /* Only 1 and even h_taps_c are supported by hw */ + scl_data->taps.h_taps_c = in_taps->h_taps_c - 1; + else + scl_data->taps.h_taps_c = in_taps->h_taps_c; + + /*Ensure we can support the requested number of vtaps*/ + min_taps_y = dc_fixpt_ceil(scl_data->ratios.vert); + min_taps_c = dc_fixpt_ceil(scl_data->ratios.vert_c); + + /* Use LB_MEMORY_CONFIG_3 for 4:2:0 */ + if ((scl_data->format == PIXEL_FORMAT_420BPP8) || (scl_data->format == PIXEL_FORMAT_420BPP10)) + lb_config = LB_MEMORY_CONFIG_3; + else + lb_config = LB_MEMORY_CONFIG_0; + + dpp->caps->dscl_calc_lb_num_partitions( + scl_data, lb_config, &num_part_y, &num_part_c); + + /* MAX_V_TAPS = MIN (NUM_LINES - MAX(CEILING(V_RATIO,1)-2, 0), 8) */ + if (dc_fixpt_ceil(scl_data->ratios.vert) > 2) + max_taps_y = num_part_y - (dc_fixpt_ceil(scl_data->ratios.vert) - 2); + else + max_taps_y = num_part_y; + + if (dc_fixpt_ceil(scl_data->ratios.vert_c) > 2) + max_taps_c = num_part_c - (dc_fixpt_ceil(scl_data->ratios.vert_c) - 2); + else + max_taps_c = num_part_c; + + if (max_taps_y < min_taps_y) + return false; + else if (max_taps_c < min_taps_c) + return false; + + if (scl_data->taps.v_taps > max_taps_y) + scl_data->taps.v_taps = max_taps_y; + + if (scl_data->taps.v_taps_c > max_taps_c) + scl_data->taps.v_taps_c = max_taps_c; + + if (!dpp->ctx->dc->debug.always_scale) { + if (IDENTITY_RATIO(scl_data->ratios.horz)) + scl_data->taps.h_taps = 1; + if (IDENTITY_RATIO(scl_data->ratios.vert)) + scl_data->taps.v_taps = 1; + if (IDENTITY_RATIO(scl_data->ratios.horz_c)) + scl_data->taps.h_taps_c = 1; + if (IDENTITY_RATIO(scl_data->ratios.vert_c)) + scl_data->taps.v_taps_c = 1; + } + + return true; +} + +static void dpp3_deferred_update(struct dpp *dpp_base) +{ + int bypass_state; + struct dcn3_dpp *dpp = TO_DCN30_DPP(dpp_base); + + if (dpp_base->deferred_reg_writes.bits.disable_dscl) { + REG_UPDATE(DSCL_MEM_PWR_CTRL, LUT_MEM_PWR_FORCE, 3); + dpp_base->deferred_reg_writes.bits.disable_dscl = false; + } + + if (dpp_base->deferred_reg_writes.bits.disable_gamcor) { + REG_GET(CM_GAMCOR_CONTROL, CM_GAMCOR_MODE_CURRENT, &bypass_state); + if (bypass_state == 0) { // only program if bypass was latched + REG_UPDATE(CM_MEM_PWR_CTRL, GAMCOR_MEM_PWR_FORCE, 3); + } else + ASSERT(0); // LUT select was updated again before vupdate + dpp_base->deferred_reg_writes.bits.disable_gamcor = false; + } + + if (dpp_base->deferred_reg_writes.bits.disable_blnd_lut) { + REG_GET(CM_BLNDGAM_CONTROL, CM_BLNDGAM_MODE_CURRENT, &bypass_state); + if (bypass_state == 0) { // only program if bypass was latched + REG_UPDATE(CM_MEM_PWR_CTRL, BLNDGAM_MEM_PWR_FORCE, 3); + } else + ASSERT(0); // LUT select was updated again before vupdate + dpp_base->deferred_reg_writes.bits.disable_blnd_lut = false; + } + + if (dpp_base->deferred_reg_writes.bits.disable_3dlut) { + REG_GET(CM_3DLUT_MODE, CM_3DLUT_MODE_CURRENT, &bypass_state); + if (bypass_state == 0) { // only program if bypass was latched + REG_UPDATE(CM_MEM_PWR_CTRL2, HDR3DLUT_MEM_PWR_FORCE, 3); + } else + ASSERT(0); // LUT select was updated again before vupdate + dpp_base->deferred_reg_writes.bits.disable_3dlut = false; + } + + if (dpp_base->deferred_reg_writes.bits.disable_shaper) { + REG_GET(CM_SHAPER_CONTROL, CM_SHAPER_MODE_CURRENT, &bypass_state); + if (bypass_state == 0) { // only program if bypass was latched + REG_UPDATE(CM_MEM_PWR_CTRL2, SHAPER_MEM_PWR_FORCE, 3); + } else + ASSERT(0); // LUT select was updated again before vupdate + dpp_base->deferred_reg_writes.bits.disable_shaper = false; + } +} + +static void dpp3_power_on_blnd_lut( + struct dpp *dpp_base, + bool power_on) +{ + struct dcn3_dpp *dpp = TO_DCN30_DPP(dpp_base); + + if (dpp_base->ctx->dc->debug.enable_mem_low_power.bits.cm) { + if (power_on) { + REG_UPDATE(CM_MEM_PWR_CTRL, BLNDGAM_MEM_PWR_FORCE, 0); + REG_WAIT(CM_MEM_PWR_STATUS, BLNDGAM_MEM_PWR_STATE, 0, 1, 5); + } else { + dpp_base->ctx->dc->optimized_required = true; + dpp_base->deferred_reg_writes.bits.disable_blnd_lut = true; + } + } else { + REG_SET(CM_MEM_PWR_CTRL, 0, + BLNDGAM_MEM_PWR_FORCE, power_on == true ? 0 : 1); + } +} + +static void dpp3_power_on_hdr3dlut( + struct dpp *dpp_base, + bool power_on) +{ + struct dcn3_dpp *dpp = TO_DCN30_DPP(dpp_base); + + if (dpp_base->ctx->dc->debug.enable_mem_low_power.bits.cm) { + if (power_on) { + REG_UPDATE(CM_MEM_PWR_CTRL2, HDR3DLUT_MEM_PWR_FORCE, 0); + REG_WAIT(CM_MEM_PWR_STATUS2, HDR3DLUT_MEM_PWR_STATE, 0, 1, 5); + } else { + dpp_base->ctx->dc->optimized_required = true; + dpp_base->deferred_reg_writes.bits.disable_3dlut = true; + } + } +} + +static void dpp3_power_on_shaper( + struct dpp *dpp_base, + bool power_on) +{ + struct dcn3_dpp *dpp = TO_DCN30_DPP(dpp_base); + + if (dpp_base->ctx->dc->debug.enable_mem_low_power.bits.cm) { + if (power_on) { + REG_UPDATE(CM_MEM_PWR_CTRL2, SHAPER_MEM_PWR_FORCE, 0); + REG_WAIT(CM_MEM_PWR_STATUS2, SHAPER_MEM_PWR_STATE, 0, 1, 5); + } else { + dpp_base->ctx->dc->optimized_required = true; + dpp_base->deferred_reg_writes.bits.disable_shaper = true; + } + } +} + +static void dpp3_configure_blnd_lut( + struct dpp *dpp_base, + bool is_ram_a) +{ + struct dcn3_dpp *dpp = TO_DCN30_DPP(dpp_base); + + REG_UPDATE_2(CM_BLNDGAM_LUT_CONTROL, + CM_BLNDGAM_LUT_WRITE_COLOR_MASK, 7, + CM_BLNDGAM_LUT_HOST_SEL, is_ram_a == true ? 0 : 1); + + REG_SET(CM_BLNDGAM_LUT_INDEX, 0, CM_BLNDGAM_LUT_INDEX, 0); +} + +static void dpp3_program_blnd_pwl( + struct dpp *dpp_base, + const struct pwl_result_data *rgb, + uint32_t num) +{ + uint32_t i; + struct dcn3_dpp *dpp = TO_DCN30_DPP(dpp_base); + uint32_t last_base_value_red = rgb[num-1].red_reg + rgb[num-1].delta_red_reg; + uint32_t last_base_value_green = rgb[num-1].green_reg + rgb[num-1].delta_green_reg; + uint32_t last_base_value_blue = rgb[num-1].blue_reg + rgb[num-1].delta_blue_reg; + + if (is_rgb_equal(rgb, num)) { + for (i = 0 ; i < num; i++) + REG_SET(CM_BLNDGAM_LUT_DATA, 0, CM_BLNDGAM_LUT_DATA, rgb[i].red_reg); + REG_SET(CM_BLNDGAM_LUT_DATA, 0, CM_BLNDGAM_LUT_DATA, last_base_value_red); + } else { + REG_UPDATE(CM_BLNDGAM_LUT_CONTROL, CM_BLNDGAM_LUT_WRITE_COLOR_MASK, 4); + for (i = 0 ; i < num; i++) + REG_SET(CM_BLNDGAM_LUT_DATA, 0, CM_BLNDGAM_LUT_DATA, rgb[i].red_reg); + REG_SET(CM_BLNDGAM_LUT_DATA, 0, CM_BLNDGAM_LUT_DATA, last_base_value_red); + + REG_UPDATE(CM_BLNDGAM_LUT_CONTROL, CM_BLNDGAM_LUT_WRITE_COLOR_MASK, 2); + for (i = 0 ; i < num; i++) + REG_SET(CM_BLNDGAM_LUT_DATA, 0, CM_BLNDGAM_LUT_DATA, rgb[i].green_reg); + REG_SET(CM_BLNDGAM_LUT_DATA, 0, CM_BLNDGAM_LUT_DATA, last_base_value_green); + + REG_UPDATE(CM_BLNDGAM_LUT_CONTROL, CM_BLNDGAM_LUT_WRITE_COLOR_MASK, 1); + for (i = 0 ; i < num; i++) + REG_SET(CM_BLNDGAM_LUT_DATA, 0, CM_BLNDGAM_LUT_DATA, rgb[i].blue_reg); + REG_SET(CM_BLNDGAM_LUT_DATA, 0, CM_BLNDGAM_LUT_DATA, last_base_value_blue); + } +} + +static void dcn3_dpp_cm_get_reg_field( + struct dcn3_dpp *dpp, + struct dcn3_xfer_func_reg *reg) +{ + reg->shifts.exp_region0_lut_offset = dpp->tf_shift->CM_BLNDGAM_RAMA_EXP_REGION0_LUT_OFFSET; + reg->masks.exp_region0_lut_offset = dpp->tf_mask->CM_BLNDGAM_RAMA_EXP_REGION0_LUT_OFFSET; + reg->shifts.exp_region0_num_segments = dpp->tf_shift->CM_BLNDGAM_RAMA_EXP_REGION0_NUM_SEGMENTS; + reg->masks.exp_region0_num_segments = dpp->tf_mask->CM_BLNDGAM_RAMA_EXP_REGION0_NUM_SEGMENTS; + reg->shifts.exp_region1_lut_offset = dpp->tf_shift->CM_BLNDGAM_RAMA_EXP_REGION1_LUT_OFFSET; + reg->masks.exp_region1_lut_offset = dpp->tf_mask->CM_BLNDGAM_RAMA_EXP_REGION1_LUT_OFFSET; + reg->shifts.exp_region1_num_segments = dpp->tf_shift->CM_BLNDGAM_RAMA_EXP_REGION1_NUM_SEGMENTS; + reg->masks.exp_region1_num_segments = dpp->tf_mask->CM_BLNDGAM_RAMA_EXP_REGION1_NUM_SEGMENTS; + + reg->shifts.field_region_end = dpp->tf_shift->CM_BLNDGAM_RAMA_EXP_REGION_END_B; + reg->masks.field_region_end = dpp->tf_mask->CM_BLNDGAM_RAMA_EXP_REGION_END_B; + reg->shifts.field_region_end_slope = dpp->tf_shift->CM_BLNDGAM_RAMA_EXP_REGION_END_SLOPE_B; + reg->masks.field_region_end_slope = dpp->tf_mask->CM_BLNDGAM_RAMA_EXP_REGION_END_SLOPE_B; + reg->shifts.field_region_end_base = dpp->tf_shift->CM_BLNDGAM_RAMA_EXP_REGION_END_BASE_B; + reg->masks.field_region_end_base = dpp->tf_mask->CM_BLNDGAM_RAMA_EXP_REGION_END_BASE_B; + reg->shifts.field_region_linear_slope = dpp->tf_shift->CM_BLNDGAM_RAMA_EXP_REGION_START_SLOPE_B; + reg->masks.field_region_linear_slope = dpp->tf_mask->CM_BLNDGAM_RAMA_EXP_REGION_START_SLOPE_B; + reg->shifts.exp_region_start = dpp->tf_shift->CM_BLNDGAM_RAMA_EXP_REGION_START_B; + reg->masks.exp_region_start = dpp->tf_mask->CM_BLNDGAM_RAMA_EXP_REGION_START_B; + reg->shifts.exp_resion_start_segment = dpp->tf_shift->CM_BLNDGAM_RAMA_EXP_REGION_START_SEGMENT_B; + reg->masks.exp_resion_start_segment = dpp->tf_mask->CM_BLNDGAM_RAMA_EXP_REGION_START_SEGMENT_B; +} + +/*program blnd lut RAM A*/ +static void dpp3_program_blnd_luta_settings( + struct dpp *dpp_base, + const struct pwl_params *params) +{ + struct dcn3_dpp *dpp = TO_DCN30_DPP(dpp_base); + struct dcn3_xfer_func_reg gam_regs; + + dcn3_dpp_cm_get_reg_field(dpp, &gam_regs); + + gam_regs.start_cntl_b = REG(CM_BLNDGAM_RAMA_START_CNTL_B); + gam_regs.start_cntl_g = REG(CM_BLNDGAM_RAMA_START_CNTL_G); + gam_regs.start_cntl_r = REG(CM_BLNDGAM_RAMA_START_CNTL_R); + gam_regs.start_slope_cntl_b = REG(CM_BLNDGAM_RAMA_START_SLOPE_CNTL_B); + gam_regs.start_slope_cntl_g = REG(CM_BLNDGAM_RAMA_START_SLOPE_CNTL_G); + gam_regs.start_slope_cntl_r = REG(CM_BLNDGAM_RAMA_START_SLOPE_CNTL_R); + gam_regs.start_end_cntl1_b = REG(CM_BLNDGAM_RAMA_END_CNTL1_B); + gam_regs.start_end_cntl2_b = REG(CM_BLNDGAM_RAMA_END_CNTL2_B); + gam_regs.start_end_cntl1_g = REG(CM_BLNDGAM_RAMA_END_CNTL1_G); + gam_regs.start_end_cntl2_g = REG(CM_BLNDGAM_RAMA_END_CNTL2_G); + gam_regs.start_end_cntl1_r = REG(CM_BLNDGAM_RAMA_END_CNTL1_R); + gam_regs.start_end_cntl2_r = REG(CM_BLNDGAM_RAMA_END_CNTL2_R); + gam_regs.region_start = REG(CM_BLNDGAM_RAMA_REGION_0_1); + gam_regs.region_end = REG(CM_BLNDGAM_RAMA_REGION_32_33); + + cm_helper_program_gamcor_xfer_func(dpp->base.ctx, params, &gam_regs); +} + +/*program blnd lut RAM B*/ +static void dpp3_program_blnd_lutb_settings( + struct dpp *dpp_base, + const struct pwl_params *params) +{ + struct dcn3_dpp *dpp = TO_DCN30_DPP(dpp_base); + struct dcn3_xfer_func_reg gam_regs; + + dcn3_dpp_cm_get_reg_field(dpp, &gam_regs); + + gam_regs.start_cntl_b = REG(CM_BLNDGAM_RAMB_START_CNTL_B); + gam_regs.start_cntl_g = REG(CM_BLNDGAM_RAMB_START_CNTL_G); + gam_regs.start_cntl_r = REG(CM_BLNDGAM_RAMB_START_CNTL_R); + gam_regs.start_slope_cntl_b = REG(CM_BLNDGAM_RAMB_START_SLOPE_CNTL_B); + gam_regs.start_slope_cntl_g = REG(CM_BLNDGAM_RAMB_START_SLOPE_CNTL_G); + gam_regs.start_slope_cntl_r = REG(CM_BLNDGAM_RAMB_START_SLOPE_CNTL_R); + gam_regs.start_end_cntl1_b = REG(CM_BLNDGAM_RAMB_END_CNTL1_B); + gam_regs.start_end_cntl2_b = REG(CM_BLNDGAM_RAMB_END_CNTL2_B); + gam_regs.start_end_cntl1_g = REG(CM_BLNDGAM_RAMB_END_CNTL1_G); + gam_regs.start_end_cntl2_g = REG(CM_BLNDGAM_RAMB_END_CNTL2_G); + gam_regs.start_end_cntl1_r = REG(CM_BLNDGAM_RAMB_END_CNTL1_R); + gam_regs.start_end_cntl2_r = REG(CM_BLNDGAM_RAMB_END_CNTL2_R); + gam_regs.region_start = REG(CM_BLNDGAM_RAMB_REGION_0_1); + gam_regs.region_end = REG(CM_BLNDGAM_RAMB_REGION_32_33); + + cm_helper_program_gamcor_xfer_func(dpp->base.ctx, params, &gam_regs); +} + +static enum dc_lut_mode dpp3_get_blndgam_current(struct dpp *dpp_base) +{ + enum dc_lut_mode mode; + uint32_t mode_current = 0; + uint32_t in_use = 0; + + struct dcn3_dpp *dpp = TO_DCN30_DPP(dpp_base); + + REG_GET(CM_BLNDGAM_CONTROL, CM_BLNDGAM_MODE_CURRENT, &mode_current); + REG_GET(CM_BLNDGAM_CONTROL, CM_BLNDGAM_SELECT_CURRENT, &in_use); + + switch (mode_current) { + case 0: + case 1: + mode = LUT_BYPASS; + break; + + case 2: + if (in_use == 0) + mode = LUT_RAM_A; + else + mode = LUT_RAM_B; + break; + default: + mode = LUT_BYPASS; + break; + } + + return mode; +} + +static bool dpp3_program_blnd_lut(struct dpp *dpp_base, + const struct pwl_params *params) +{ + enum dc_lut_mode current_mode; + enum dc_lut_mode next_mode; + struct dcn3_dpp *dpp = TO_DCN30_DPP(dpp_base); + + if (params == NULL) { + REG_SET(CM_BLNDGAM_CONTROL, 0, CM_BLNDGAM_MODE, 0); + if (dpp_base->ctx->dc->debug.enable_mem_low_power.bits.cm) + dpp3_power_on_blnd_lut(dpp_base, false); + return false; + } + + current_mode = dpp3_get_blndgam_current(dpp_base); + if (current_mode == LUT_BYPASS || current_mode == LUT_RAM_B) + next_mode = LUT_RAM_A; + else + next_mode = LUT_RAM_B; + + dpp3_power_on_blnd_lut(dpp_base, true); + dpp3_configure_blnd_lut(dpp_base, next_mode == LUT_RAM_A); + + if (next_mode == LUT_RAM_A) + dpp3_program_blnd_luta_settings(dpp_base, params); + else + dpp3_program_blnd_lutb_settings(dpp_base, params); + + dpp3_program_blnd_pwl( + dpp_base, params->rgb_resulted, params->hw_points_num); + + REG_UPDATE_2(CM_BLNDGAM_CONTROL, + CM_BLNDGAM_MODE, 2, + CM_BLNDGAM_SELECT, next_mode == LUT_RAM_A ? 0 : 1); + + return true; +} + + +static void dpp3_program_shaper_lut( + struct dpp *dpp_base, + const struct pwl_result_data *rgb, + uint32_t num) +{ + uint32_t i, red, green, blue; + uint32_t red_delta, green_delta, blue_delta; + uint32_t red_value, green_value, blue_value; + + struct dcn3_dpp *dpp = TO_DCN30_DPP(dpp_base); + + for (i = 0 ; i < num; i++) { + + red = rgb[i].red_reg; + green = rgb[i].green_reg; + blue = rgb[i].blue_reg; + + red_delta = rgb[i].delta_red_reg; + green_delta = rgb[i].delta_green_reg; + blue_delta = rgb[i].delta_blue_reg; + + red_value = ((red_delta & 0x3ff) << 14) | (red & 0x3fff); + green_value = ((green_delta & 0x3ff) << 14) | (green & 0x3fff); + blue_value = ((blue_delta & 0x3ff) << 14) | (blue & 0x3fff); + + REG_SET(CM_SHAPER_LUT_DATA, 0, CM_SHAPER_LUT_DATA, red_value); + REG_SET(CM_SHAPER_LUT_DATA, 0, CM_SHAPER_LUT_DATA, green_value); + REG_SET(CM_SHAPER_LUT_DATA, 0, CM_SHAPER_LUT_DATA, blue_value); + } + +} + +static enum dc_lut_mode dpp3_get_shaper_current(struct dpp *dpp_base) +{ + enum dc_lut_mode mode; + uint32_t state_mode; + struct dcn3_dpp *dpp = TO_DCN30_DPP(dpp_base); + + REG_GET(CM_SHAPER_CONTROL, CM_SHAPER_MODE_CURRENT, &state_mode); + + switch (state_mode) { + case 0: + mode = LUT_BYPASS; + break; + case 1: + mode = LUT_RAM_A; + break; + case 2: + mode = LUT_RAM_B; + break; + default: + mode = LUT_BYPASS; + break; + } + + return mode; +} + +static void dpp3_configure_shaper_lut( + struct dpp *dpp_base, + bool is_ram_a) +{ + struct dcn3_dpp *dpp = TO_DCN30_DPP(dpp_base); + + REG_UPDATE(CM_SHAPER_LUT_WRITE_EN_MASK, + CM_SHAPER_LUT_WRITE_EN_MASK, 7); + REG_UPDATE(CM_SHAPER_LUT_WRITE_EN_MASK, + CM_SHAPER_LUT_WRITE_SEL, is_ram_a == true ? 0:1); + REG_SET(CM_SHAPER_LUT_INDEX, 0, CM_SHAPER_LUT_INDEX, 0); +} + +/*program shaper RAM A*/ + +static void dpp3_program_shaper_luta_settings( + struct dpp *dpp_base, + const struct pwl_params *params) +{ + const struct gamma_curve *curve; + struct dcn3_dpp *dpp = TO_DCN30_DPP(dpp_base); + + REG_SET_2(CM_SHAPER_RAMA_START_CNTL_B, 0, + CM_SHAPER_RAMA_EXP_REGION_START_B, params->corner_points[0].blue.custom_float_x, + CM_SHAPER_RAMA_EXP_REGION_START_SEGMENT_B, 0); + REG_SET_2(CM_SHAPER_RAMA_START_CNTL_G, 0, + CM_SHAPER_RAMA_EXP_REGION_START_G, params->corner_points[0].green.custom_float_x, + CM_SHAPER_RAMA_EXP_REGION_START_SEGMENT_G, 0); + REG_SET_2(CM_SHAPER_RAMA_START_CNTL_R, 0, + CM_SHAPER_RAMA_EXP_REGION_START_R, params->corner_points[0].red.custom_float_x, + CM_SHAPER_RAMA_EXP_REGION_START_SEGMENT_R, 0); + + REG_SET_2(CM_SHAPER_RAMA_END_CNTL_B, 0, + CM_SHAPER_RAMA_EXP_REGION_END_B, params->corner_points[1].blue.custom_float_x, + CM_SHAPER_RAMA_EXP_REGION_END_BASE_B, params->corner_points[1].blue.custom_float_y); + + REG_SET_2(CM_SHAPER_RAMA_END_CNTL_G, 0, + CM_SHAPER_RAMA_EXP_REGION_END_G, params->corner_points[1].green.custom_float_x, + CM_SHAPER_RAMA_EXP_REGION_END_BASE_G, params->corner_points[1].green.custom_float_y); + + REG_SET_2(CM_SHAPER_RAMA_END_CNTL_R, 0, + CM_SHAPER_RAMA_EXP_REGION_END_R, params->corner_points[1].red.custom_float_x, + CM_SHAPER_RAMA_EXP_REGION_END_BASE_R, params->corner_points[1].red.custom_float_y); + + curve = params->arr_curve_points; + REG_SET_4(CM_SHAPER_RAMA_REGION_0_1, 0, + CM_SHAPER_RAMA_EXP_REGION0_LUT_OFFSET, curve[0].offset, + CM_SHAPER_RAMA_EXP_REGION0_NUM_SEGMENTS, curve[0].segments_num, + CM_SHAPER_RAMA_EXP_REGION1_LUT_OFFSET, curve[1].offset, + CM_SHAPER_RAMA_EXP_REGION1_NUM_SEGMENTS, curve[1].segments_num); + + curve += 2; + REG_SET_4(CM_SHAPER_RAMA_REGION_2_3, 0, + CM_SHAPER_RAMA_EXP_REGION2_LUT_OFFSET, curve[0].offset, + CM_SHAPER_RAMA_EXP_REGION2_NUM_SEGMENTS, curve[0].segments_num, + CM_SHAPER_RAMA_EXP_REGION3_LUT_OFFSET, curve[1].offset, + CM_SHAPER_RAMA_EXP_REGION3_NUM_SEGMENTS, curve[1].segments_num); + + curve += 2; + REG_SET_4(CM_SHAPER_RAMA_REGION_4_5, 0, + CM_SHAPER_RAMA_EXP_REGION4_LUT_OFFSET, curve[0].offset, + CM_SHAPER_RAMA_EXP_REGION4_NUM_SEGMENTS, curve[0].segments_num, + CM_SHAPER_RAMA_EXP_REGION5_LUT_OFFSET, curve[1].offset, + CM_SHAPER_RAMA_EXP_REGION5_NUM_SEGMENTS, curve[1].segments_num); + + curve += 2; + REG_SET_4(CM_SHAPER_RAMA_REGION_6_7, 0, + CM_SHAPER_RAMA_EXP_REGION6_LUT_OFFSET, curve[0].offset, + CM_SHAPER_RAMA_EXP_REGION6_NUM_SEGMENTS, curve[0].segments_num, + CM_SHAPER_RAMA_EXP_REGION7_LUT_OFFSET, curve[1].offset, + CM_SHAPER_RAMA_EXP_REGION7_NUM_SEGMENTS, curve[1].segments_num); + + curve += 2; + REG_SET_4(CM_SHAPER_RAMA_REGION_8_9, 0, + CM_SHAPER_RAMA_EXP_REGION8_LUT_OFFSET, curve[0].offset, + CM_SHAPER_RAMA_EXP_REGION8_NUM_SEGMENTS, curve[0].segments_num, + CM_SHAPER_RAMA_EXP_REGION9_LUT_OFFSET, curve[1].offset, + CM_SHAPER_RAMA_EXP_REGION9_NUM_SEGMENTS, curve[1].segments_num); + + curve += 2; + REG_SET_4(CM_SHAPER_RAMA_REGION_10_11, 0, + CM_SHAPER_RAMA_EXP_REGION10_LUT_OFFSET, curve[0].offset, + CM_SHAPER_RAMA_EXP_REGION10_NUM_SEGMENTS, curve[0].segments_num, + CM_SHAPER_RAMA_EXP_REGION11_LUT_OFFSET, curve[1].offset, + CM_SHAPER_RAMA_EXP_REGION11_NUM_SEGMENTS, curve[1].segments_num); + + curve += 2; + REG_SET_4(CM_SHAPER_RAMA_REGION_12_13, 0, + CM_SHAPER_RAMA_EXP_REGION12_LUT_OFFSET, curve[0].offset, + CM_SHAPER_RAMA_EXP_REGION12_NUM_SEGMENTS, curve[0].segments_num, + CM_SHAPER_RAMA_EXP_REGION13_LUT_OFFSET, curve[1].offset, + CM_SHAPER_RAMA_EXP_REGION13_NUM_SEGMENTS, curve[1].segments_num); + + curve += 2; + REG_SET_4(CM_SHAPER_RAMA_REGION_14_15, 0, + CM_SHAPER_RAMA_EXP_REGION14_LUT_OFFSET, curve[0].offset, + CM_SHAPER_RAMA_EXP_REGION14_NUM_SEGMENTS, curve[0].segments_num, + CM_SHAPER_RAMA_EXP_REGION15_LUT_OFFSET, curve[1].offset, + CM_SHAPER_RAMA_EXP_REGION15_NUM_SEGMENTS, curve[1].segments_num); + + curve += 2; + REG_SET_4(CM_SHAPER_RAMA_REGION_16_17, 0, + CM_SHAPER_RAMA_EXP_REGION16_LUT_OFFSET, curve[0].offset, + CM_SHAPER_RAMA_EXP_REGION16_NUM_SEGMENTS, curve[0].segments_num, + CM_SHAPER_RAMA_EXP_REGION17_LUT_OFFSET, curve[1].offset, + CM_SHAPER_RAMA_EXP_REGION17_NUM_SEGMENTS, curve[1].segments_num); + + curve += 2; + REG_SET_4(CM_SHAPER_RAMA_REGION_18_19, 0, + CM_SHAPER_RAMA_EXP_REGION18_LUT_OFFSET, curve[0].offset, + CM_SHAPER_RAMA_EXP_REGION18_NUM_SEGMENTS, curve[0].segments_num, + CM_SHAPER_RAMA_EXP_REGION19_LUT_OFFSET, curve[1].offset, + CM_SHAPER_RAMA_EXP_REGION19_NUM_SEGMENTS, curve[1].segments_num); + + curve += 2; + REG_SET_4(CM_SHAPER_RAMA_REGION_20_21, 0, + CM_SHAPER_RAMA_EXP_REGION20_LUT_OFFSET, curve[0].offset, + CM_SHAPER_RAMA_EXP_REGION20_NUM_SEGMENTS, curve[0].segments_num, + CM_SHAPER_RAMA_EXP_REGION21_LUT_OFFSET, curve[1].offset, + CM_SHAPER_RAMA_EXP_REGION21_NUM_SEGMENTS, curve[1].segments_num); + + curve += 2; + REG_SET_4(CM_SHAPER_RAMA_REGION_22_23, 0, + CM_SHAPER_RAMA_EXP_REGION22_LUT_OFFSET, curve[0].offset, + CM_SHAPER_RAMA_EXP_REGION22_NUM_SEGMENTS, curve[0].segments_num, + CM_SHAPER_RAMA_EXP_REGION23_LUT_OFFSET, curve[1].offset, + CM_SHAPER_RAMA_EXP_REGION23_NUM_SEGMENTS, curve[1].segments_num); + + curve += 2; + REG_SET_4(CM_SHAPER_RAMA_REGION_24_25, 0, + CM_SHAPER_RAMA_EXP_REGION24_LUT_OFFSET, curve[0].offset, + CM_SHAPER_RAMA_EXP_REGION24_NUM_SEGMENTS, curve[0].segments_num, + CM_SHAPER_RAMA_EXP_REGION25_LUT_OFFSET, curve[1].offset, + CM_SHAPER_RAMA_EXP_REGION25_NUM_SEGMENTS, curve[1].segments_num); + + curve += 2; + REG_SET_4(CM_SHAPER_RAMA_REGION_26_27, 0, + CM_SHAPER_RAMA_EXP_REGION26_LUT_OFFSET, curve[0].offset, + CM_SHAPER_RAMA_EXP_REGION26_NUM_SEGMENTS, curve[0].segments_num, + CM_SHAPER_RAMA_EXP_REGION27_LUT_OFFSET, curve[1].offset, + CM_SHAPER_RAMA_EXP_REGION27_NUM_SEGMENTS, curve[1].segments_num); + + curve += 2; + REG_SET_4(CM_SHAPER_RAMA_REGION_28_29, 0, + CM_SHAPER_RAMA_EXP_REGION28_LUT_OFFSET, curve[0].offset, + CM_SHAPER_RAMA_EXP_REGION28_NUM_SEGMENTS, curve[0].segments_num, + CM_SHAPER_RAMA_EXP_REGION29_LUT_OFFSET, curve[1].offset, + CM_SHAPER_RAMA_EXP_REGION29_NUM_SEGMENTS, curve[1].segments_num); + + curve += 2; + REG_SET_4(CM_SHAPER_RAMA_REGION_30_31, 0, + CM_SHAPER_RAMA_EXP_REGION30_LUT_OFFSET, curve[0].offset, + CM_SHAPER_RAMA_EXP_REGION30_NUM_SEGMENTS, curve[0].segments_num, + CM_SHAPER_RAMA_EXP_REGION31_LUT_OFFSET, curve[1].offset, + CM_SHAPER_RAMA_EXP_REGION31_NUM_SEGMENTS, curve[1].segments_num); + + curve += 2; + REG_SET_4(CM_SHAPER_RAMA_REGION_32_33, 0, + CM_SHAPER_RAMA_EXP_REGION32_LUT_OFFSET, curve[0].offset, + CM_SHAPER_RAMA_EXP_REGION32_NUM_SEGMENTS, curve[0].segments_num, + CM_SHAPER_RAMA_EXP_REGION33_LUT_OFFSET, curve[1].offset, + CM_SHAPER_RAMA_EXP_REGION33_NUM_SEGMENTS, curve[1].segments_num); +} + +/*program shaper RAM B*/ +static void dpp3_program_shaper_lutb_settings( + struct dpp *dpp_base, + const struct pwl_params *params) +{ + const struct gamma_curve *curve; + struct dcn3_dpp *dpp = TO_DCN30_DPP(dpp_base); + + REG_SET_2(CM_SHAPER_RAMB_START_CNTL_B, 0, + CM_SHAPER_RAMB_EXP_REGION_START_B, params->corner_points[0].blue.custom_float_x, + CM_SHAPER_RAMB_EXP_REGION_START_SEGMENT_B, 0); + REG_SET_2(CM_SHAPER_RAMB_START_CNTL_G, 0, + CM_SHAPER_RAMB_EXP_REGION_START_G, params->corner_points[0].green.custom_float_x, + CM_SHAPER_RAMB_EXP_REGION_START_SEGMENT_G, 0); + REG_SET_2(CM_SHAPER_RAMB_START_CNTL_R, 0, + CM_SHAPER_RAMB_EXP_REGION_START_R, params->corner_points[0].red.custom_float_x, + CM_SHAPER_RAMB_EXP_REGION_START_SEGMENT_R, 0); + + REG_SET_2(CM_SHAPER_RAMB_END_CNTL_B, 0, + CM_SHAPER_RAMB_EXP_REGION_END_B, params->corner_points[1].blue.custom_float_x, + CM_SHAPER_RAMB_EXP_REGION_END_BASE_B, params->corner_points[1].blue.custom_float_y); + + REG_SET_2(CM_SHAPER_RAMB_END_CNTL_G, 0, + CM_SHAPER_RAMB_EXP_REGION_END_G, params->corner_points[1].green.custom_float_x, + CM_SHAPER_RAMB_EXP_REGION_END_BASE_G, params->corner_points[1].green.custom_float_y); + + REG_SET_2(CM_SHAPER_RAMB_END_CNTL_R, 0, + CM_SHAPER_RAMB_EXP_REGION_END_R, params->corner_points[1].red.custom_float_x, + CM_SHAPER_RAMB_EXP_REGION_END_BASE_R, params->corner_points[1].red.custom_float_y); + + curve = params->arr_curve_points; + REG_SET_4(CM_SHAPER_RAMB_REGION_0_1, 0, + CM_SHAPER_RAMB_EXP_REGION0_LUT_OFFSET, curve[0].offset, + CM_SHAPER_RAMB_EXP_REGION0_NUM_SEGMENTS, curve[0].segments_num, + CM_SHAPER_RAMB_EXP_REGION1_LUT_OFFSET, curve[1].offset, + CM_SHAPER_RAMB_EXP_REGION1_NUM_SEGMENTS, curve[1].segments_num); + + curve += 2; + REG_SET_4(CM_SHAPER_RAMB_REGION_2_3, 0, + CM_SHAPER_RAMB_EXP_REGION2_LUT_OFFSET, curve[0].offset, + CM_SHAPER_RAMB_EXP_REGION2_NUM_SEGMENTS, curve[0].segments_num, + CM_SHAPER_RAMB_EXP_REGION3_LUT_OFFSET, curve[1].offset, + CM_SHAPER_RAMB_EXP_REGION3_NUM_SEGMENTS, curve[1].segments_num); + + curve += 2; + REG_SET_4(CM_SHAPER_RAMB_REGION_4_5, 0, + CM_SHAPER_RAMB_EXP_REGION4_LUT_OFFSET, curve[0].offset, + CM_SHAPER_RAMB_EXP_REGION4_NUM_SEGMENTS, curve[0].segments_num, + CM_SHAPER_RAMB_EXP_REGION5_LUT_OFFSET, curve[1].offset, + CM_SHAPER_RAMB_EXP_REGION5_NUM_SEGMENTS, curve[1].segments_num); + + curve += 2; + REG_SET_4(CM_SHAPER_RAMB_REGION_6_7, 0, + CM_SHAPER_RAMB_EXP_REGION6_LUT_OFFSET, curve[0].offset, + CM_SHAPER_RAMB_EXP_REGION6_NUM_SEGMENTS, curve[0].segments_num, + CM_SHAPER_RAMB_EXP_REGION7_LUT_OFFSET, curve[1].offset, + CM_SHAPER_RAMB_EXP_REGION7_NUM_SEGMENTS, curve[1].segments_num); + + curve += 2; + REG_SET_4(CM_SHAPER_RAMB_REGION_8_9, 0, + CM_SHAPER_RAMB_EXP_REGION8_LUT_OFFSET, curve[0].offset, + CM_SHAPER_RAMB_EXP_REGION8_NUM_SEGMENTS, curve[0].segments_num, + CM_SHAPER_RAMB_EXP_REGION9_LUT_OFFSET, curve[1].offset, + CM_SHAPER_RAMB_EXP_REGION9_NUM_SEGMENTS, curve[1].segments_num); + + curve += 2; + REG_SET_4(CM_SHAPER_RAMB_REGION_10_11, 0, + CM_SHAPER_RAMB_EXP_REGION10_LUT_OFFSET, curve[0].offset, + CM_SHAPER_RAMB_EXP_REGION10_NUM_SEGMENTS, curve[0].segments_num, + CM_SHAPER_RAMB_EXP_REGION11_LUT_OFFSET, curve[1].offset, + CM_SHAPER_RAMB_EXP_REGION11_NUM_SEGMENTS, curve[1].segments_num); + + curve += 2; + REG_SET_4(CM_SHAPER_RAMB_REGION_12_13, 0, + CM_SHAPER_RAMB_EXP_REGION12_LUT_OFFSET, curve[0].offset, + CM_SHAPER_RAMB_EXP_REGION12_NUM_SEGMENTS, curve[0].segments_num, + CM_SHAPER_RAMB_EXP_REGION13_LUT_OFFSET, curve[1].offset, + CM_SHAPER_RAMB_EXP_REGION13_NUM_SEGMENTS, curve[1].segments_num); + + curve += 2; + REG_SET_4(CM_SHAPER_RAMB_REGION_14_15, 0, + CM_SHAPER_RAMB_EXP_REGION14_LUT_OFFSET, curve[0].offset, + CM_SHAPER_RAMB_EXP_REGION14_NUM_SEGMENTS, curve[0].segments_num, + CM_SHAPER_RAMB_EXP_REGION15_LUT_OFFSET, curve[1].offset, + CM_SHAPER_RAMB_EXP_REGION15_NUM_SEGMENTS, curve[1].segments_num); + + curve += 2; + REG_SET_4(CM_SHAPER_RAMB_REGION_16_17, 0, + CM_SHAPER_RAMB_EXP_REGION16_LUT_OFFSET, curve[0].offset, + CM_SHAPER_RAMB_EXP_REGION16_NUM_SEGMENTS, curve[0].segments_num, + CM_SHAPER_RAMB_EXP_REGION17_LUT_OFFSET, curve[1].offset, + CM_SHAPER_RAMB_EXP_REGION17_NUM_SEGMENTS, curve[1].segments_num); + + curve += 2; + REG_SET_4(CM_SHAPER_RAMB_REGION_18_19, 0, + CM_SHAPER_RAMB_EXP_REGION18_LUT_OFFSET, curve[0].offset, + CM_SHAPER_RAMB_EXP_REGION18_NUM_SEGMENTS, curve[0].segments_num, + CM_SHAPER_RAMB_EXP_REGION19_LUT_OFFSET, curve[1].offset, + CM_SHAPER_RAMB_EXP_REGION19_NUM_SEGMENTS, curve[1].segments_num); + + curve += 2; + REG_SET_4(CM_SHAPER_RAMB_REGION_20_21, 0, + CM_SHAPER_RAMB_EXP_REGION20_LUT_OFFSET, curve[0].offset, + CM_SHAPER_RAMB_EXP_REGION20_NUM_SEGMENTS, curve[0].segments_num, + CM_SHAPER_RAMB_EXP_REGION21_LUT_OFFSET, curve[1].offset, + CM_SHAPER_RAMB_EXP_REGION21_NUM_SEGMENTS, curve[1].segments_num); + + curve += 2; + REG_SET_4(CM_SHAPER_RAMB_REGION_22_23, 0, + CM_SHAPER_RAMB_EXP_REGION22_LUT_OFFSET, curve[0].offset, + CM_SHAPER_RAMB_EXP_REGION22_NUM_SEGMENTS, curve[0].segments_num, + CM_SHAPER_RAMB_EXP_REGION23_LUT_OFFSET, curve[1].offset, + CM_SHAPER_RAMB_EXP_REGION23_NUM_SEGMENTS, curve[1].segments_num); + + curve += 2; + REG_SET_4(CM_SHAPER_RAMB_REGION_24_25, 0, + CM_SHAPER_RAMB_EXP_REGION24_LUT_OFFSET, curve[0].offset, + CM_SHAPER_RAMB_EXP_REGION24_NUM_SEGMENTS, curve[0].segments_num, + CM_SHAPER_RAMB_EXP_REGION25_LUT_OFFSET, curve[1].offset, + CM_SHAPER_RAMB_EXP_REGION25_NUM_SEGMENTS, curve[1].segments_num); + + curve += 2; + REG_SET_4(CM_SHAPER_RAMB_REGION_26_27, 0, + CM_SHAPER_RAMB_EXP_REGION26_LUT_OFFSET, curve[0].offset, + CM_SHAPER_RAMB_EXP_REGION26_NUM_SEGMENTS, curve[0].segments_num, + CM_SHAPER_RAMB_EXP_REGION27_LUT_OFFSET, curve[1].offset, + CM_SHAPER_RAMB_EXP_REGION27_NUM_SEGMENTS, curve[1].segments_num); + + curve += 2; + REG_SET_4(CM_SHAPER_RAMB_REGION_28_29, 0, + CM_SHAPER_RAMB_EXP_REGION28_LUT_OFFSET, curve[0].offset, + CM_SHAPER_RAMB_EXP_REGION28_NUM_SEGMENTS, curve[0].segments_num, + CM_SHAPER_RAMB_EXP_REGION29_LUT_OFFSET, curve[1].offset, + CM_SHAPER_RAMB_EXP_REGION29_NUM_SEGMENTS, curve[1].segments_num); + + curve += 2; + REG_SET_4(CM_SHAPER_RAMB_REGION_30_31, 0, + CM_SHAPER_RAMB_EXP_REGION30_LUT_OFFSET, curve[0].offset, + CM_SHAPER_RAMB_EXP_REGION30_NUM_SEGMENTS, curve[0].segments_num, + CM_SHAPER_RAMB_EXP_REGION31_LUT_OFFSET, curve[1].offset, + CM_SHAPER_RAMB_EXP_REGION31_NUM_SEGMENTS, curve[1].segments_num); + + curve += 2; + REG_SET_4(CM_SHAPER_RAMB_REGION_32_33, 0, + CM_SHAPER_RAMB_EXP_REGION32_LUT_OFFSET, curve[0].offset, + CM_SHAPER_RAMB_EXP_REGION32_NUM_SEGMENTS, curve[0].segments_num, + CM_SHAPER_RAMB_EXP_REGION33_LUT_OFFSET, curve[1].offset, + CM_SHAPER_RAMB_EXP_REGION33_NUM_SEGMENTS, curve[1].segments_num); + +} + + +static bool dpp3_program_shaper(struct dpp *dpp_base, + const struct pwl_params *params) +{ + enum dc_lut_mode current_mode; + enum dc_lut_mode next_mode; + + struct dcn3_dpp *dpp = TO_DCN30_DPP(dpp_base); + + if (params == NULL) { + REG_SET(CM_SHAPER_CONTROL, 0, CM_SHAPER_LUT_MODE, 0); + if (dpp_base->ctx->dc->debug.enable_mem_low_power.bits.cm) + dpp3_power_on_shaper(dpp_base, false); + return false; + } + + if (dpp_base->ctx->dc->debug.enable_mem_low_power.bits.cm) + dpp3_power_on_shaper(dpp_base, true); + + current_mode = dpp3_get_shaper_current(dpp_base); + + if (current_mode == LUT_BYPASS || current_mode == LUT_RAM_A) + next_mode = LUT_RAM_B; + else + next_mode = LUT_RAM_A; + + dpp3_configure_shaper_lut(dpp_base, next_mode == LUT_RAM_A); + + if (next_mode == LUT_RAM_A) + dpp3_program_shaper_luta_settings(dpp_base, params); + else + dpp3_program_shaper_lutb_settings(dpp_base, params); + + dpp3_program_shaper_lut( + dpp_base, params->rgb_resulted, params->hw_points_num); + + REG_SET(CM_SHAPER_CONTROL, 0, CM_SHAPER_LUT_MODE, next_mode == LUT_RAM_A ? 1:2); + + return true; + +} + +static enum dc_lut_mode get3dlut_config( + struct dpp *dpp_base, + bool *is_17x17x17, + bool *is_12bits_color_channel) +{ + uint32_t i_mode, i_enable_10bits, lut_size; + enum dc_lut_mode mode; + struct dcn3_dpp *dpp = TO_DCN30_DPP(dpp_base); + + REG_GET(CM_3DLUT_READ_WRITE_CONTROL, + CM_3DLUT_30BIT_EN, &i_enable_10bits); + REG_GET(CM_3DLUT_MODE, + CM_3DLUT_MODE_CURRENT, &i_mode); + + switch (i_mode) { + case 0: + mode = LUT_BYPASS; + break; + case 1: + mode = LUT_RAM_A; + break; + case 2: + mode = LUT_RAM_B; + break; + default: + mode = LUT_BYPASS; + break; + } + if (i_enable_10bits > 0) + *is_12bits_color_channel = false; + else + *is_12bits_color_channel = true; + + REG_GET(CM_3DLUT_MODE, CM_3DLUT_SIZE, &lut_size); + + if (lut_size == 0) + *is_17x17x17 = true; + else + *is_17x17x17 = false; + + return mode; +} +/* + * select ramA or ramB, or bypass + * select color channel size 10 or 12 bits + * select 3dlut size 17x17x17 or 9x9x9 + */ +static void dpp3_set_3dlut_mode( + struct dpp *dpp_base, + enum dc_lut_mode mode, + bool is_color_channel_12bits, + bool is_lut_size17x17x17) +{ + uint32_t lut_mode; + struct dcn3_dpp *dpp = TO_DCN30_DPP(dpp_base); + + if (mode == LUT_BYPASS) + lut_mode = 0; + else if (mode == LUT_RAM_A) + lut_mode = 1; + else + lut_mode = 2; + + REG_UPDATE_2(CM_3DLUT_MODE, + CM_3DLUT_MODE, lut_mode, + CM_3DLUT_SIZE, is_lut_size17x17x17 == true ? 0 : 1); +} + +static void dpp3_select_3dlut_ram( + struct dpp *dpp_base, + enum dc_lut_mode mode, + bool is_color_channel_12bits) +{ + struct dcn3_dpp *dpp = TO_DCN30_DPP(dpp_base); + + REG_UPDATE_2(CM_3DLUT_READ_WRITE_CONTROL, + CM_3DLUT_RAM_SEL, mode == LUT_RAM_A ? 0 : 1, + CM_3DLUT_30BIT_EN, + is_color_channel_12bits == true ? 0:1); +} + + + +static void dpp3_set3dlut_ram12( + struct dpp *dpp_base, + const struct dc_rgb *lut, + uint32_t entries) +{ + uint32_t i, red, green, blue, red1, green1, blue1; + struct dcn3_dpp *dpp = TO_DCN30_DPP(dpp_base); + + for (i = 0 ; i < entries; i += 2) { + red = lut[i].red<<4; + green = lut[i].green<<4; + blue = lut[i].blue<<4; + red1 = lut[i+1].red<<4; + green1 = lut[i+1].green<<4; + blue1 = lut[i+1].blue<<4; + + REG_SET_2(CM_3DLUT_DATA, 0, + CM_3DLUT_DATA0, red, + CM_3DLUT_DATA1, red1); + + REG_SET_2(CM_3DLUT_DATA, 0, + CM_3DLUT_DATA0, green, + CM_3DLUT_DATA1, green1); + + REG_SET_2(CM_3DLUT_DATA, 0, + CM_3DLUT_DATA0, blue, + CM_3DLUT_DATA1, blue1); + + } +} + +/* + * load selected lut with 10 bits color channels + */ +static void dpp3_set3dlut_ram10( + struct dpp *dpp_base, + const struct dc_rgb *lut, + uint32_t entries) +{ + uint32_t i, red, green, blue, value; + struct dcn3_dpp *dpp = TO_DCN30_DPP(dpp_base); + + for (i = 0; i < entries; i++) { + red = lut[i].red; + green = lut[i].green; + blue = lut[i].blue; + + value = (red<<20) | (green<<10) | blue; + + REG_SET(CM_3DLUT_DATA_30BIT, 0, CM_3DLUT_DATA_30BIT, value); + } + +} + + +static void dpp3_select_3dlut_ram_mask( + struct dpp *dpp_base, + uint32_t ram_selection_mask) +{ + struct dcn3_dpp *dpp = TO_DCN30_DPP(dpp_base); + + REG_UPDATE(CM_3DLUT_READ_WRITE_CONTROL, CM_3DLUT_WRITE_EN_MASK, + ram_selection_mask); + REG_SET(CM_3DLUT_INDEX, 0, CM_3DLUT_INDEX, 0); +} + +static bool dpp3_program_3dlut(struct dpp *dpp_base, + struct tetrahedral_params *params) +{ + enum dc_lut_mode mode; + bool is_17x17x17; + bool is_12bits_color_channel; + struct dc_rgb *lut0; + struct dc_rgb *lut1; + struct dc_rgb *lut2; + struct dc_rgb *lut3; + int lut_size0; + int lut_size; + + if (params == NULL) { + dpp3_set_3dlut_mode(dpp_base, LUT_BYPASS, false, false); + if (dpp_base->ctx->dc->debug.enable_mem_low_power.bits.cm) + dpp3_power_on_hdr3dlut(dpp_base, false); + return false; + } + + if (dpp_base->ctx->dc->debug.enable_mem_low_power.bits.cm) + dpp3_power_on_hdr3dlut(dpp_base, true); + + mode = get3dlut_config(dpp_base, &is_17x17x17, &is_12bits_color_channel); + + if (mode == LUT_BYPASS || mode == LUT_RAM_B) + mode = LUT_RAM_A; + else + mode = LUT_RAM_B; + + is_17x17x17 = !params->use_tetrahedral_9; + is_12bits_color_channel = params->use_12bits; + if (is_17x17x17) { + lut0 = params->tetrahedral_17.lut0; + lut1 = params->tetrahedral_17.lut1; + lut2 = params->tetrahedral_17.lut2; + lut3 = params->tetrahedral_17.lut3; + lut_size0 = sizeof(params->tetrahedral_17.lut0)/ + sizeof(params->tetrahedral_17.lut0[0]); + lut_size = sizeof(params->tetrahedral_17.lut1)/ + sizeof(params->tetrahedral_17.lut1[0]); + } else { + lut0 = params->tetrahedral_9.lut0; + lut1 = params->tetrahedral_9.lut1; + lut2 = params->tetrahedral_9.lut2; + lut3 = params->tetrahedral_9.lut3; + lut_size0 = sizeof(params->tetrahedral_9.lut0)/ + sizeof(params->tetrahedral_9.lut0[0]); + lut_size = sizeof(params->tetrahedral_9.lut1)/ + sizeof(params->tetrahedral_9.lut1[0]); + } + + dpp3_select_3dlut_ram(dpp_base, mode, + is_12bits_color_channel); + dpp3_select_3dlut_ram_mask(dpp_base, 0x1); + if (is_12bits_color_channel) + dpp3_set3dlut_ram12(dpp_base, lut0, lut_size0); + else + dpp3_set3dlut_ram10(dpp_base, lut0, lut_size0); + + dpp3_select_3dlut_ram_mask(dpp_base, 0x2); + if (is_12bits_color_channel) + dpp3_set3dlut_ram12(dpp_base, lut1, lut_size); + else + dpp3_set3dlut_ram10(dpp_base, lut1, lut_size); + + dpp3_select_3dlut_ram_mask(dpp_base, 0x4); + if (is_12bits_color_channel) + dpp3_set3dlut_ram12(dpp_base, lut2, lut_size); + else + dpp3_set3dlut_ram10(dpp_base, lut2, lut_size); + + dpp3_select_3dlut_ram_mask(dpp_base, 0x8); + if (is_12bits_color_channel) + dpp3_set3dlut_ram12(dpp_base, lut3, lut_size); + else + dpp3_set3dlut_ram10(dpp_base, lut3, lut_size); + + + dpp3_set_3dlut_mode(dpp_base, mode, is_12bits_color_channel, + is_17x17x17); + + return true; +} +static struct dpp_funcs dcn30_dpp_funcs = { + .dpp_program_gamcor_lut = dpp3_program_gamcor_lut, + .dpp_read_state = dpp30_read_state, + .dpp_reset = dpp_reset, + .dpp_set_scaler = dpp1_dscl_set_scaler_manual_scale, + .dpp_get_optimal_number_of_taps = dpp3_get_optimal_number_of_taps, + .dpp_set_gamut_remap = dpp3_cm_set_gamut_remap, + .dpp_set_csc_adjustment = NULL, + .dpp_set_csc_default = NULL, + .dpp_program_regamma_pwl = NULL, + .dpp_set_pre_degam = dpp3_set_pre_degam, + .dpp_program_input_lut = NULL, + .dpp_full_bypass = dpp1_full_bypass, + .dpp_setup = dpp3_cnv_setup, + .dpp_program_degamma_pwl = NULL, + .dpp_program_cm_dealpha = dpp3_program_cm_dealpha, + .dpp_program_cm_bias = dpp3_program_cm_bias, + .dpp_program_blnd_lut = dpp3_program_blnd_lut, + .dpp_program_shaper_lut = dpp3_program_shaper, + .dpp_program_3dlut = dpp3_program_3dlut, + .dpp_deferred_update = dpp3_deferred_update, + .dpp_program_bias_and_scale = NULL, + .dpp_cnv_set_alpha_keyer = dpp2_cnv_set_alpha_keyer, + .set_cursor_attributes = dpp3_set_cursor_attributes, + .set_cursor_position = dpp1_set_cursor_position, + .set_optional_cursor_attributes = dpp1_cnv_set_optional_cursor_attributes, + .dpp_dppclk_control = dpp1_dppclk_control, + .dpp_set_hdr_multiplier = dpp3_set_hdr_multiplier, +}; + + +static struct dpp_caps dcn30_dpp_cap = { + .dscl_data_proc_format = DSCL_DATA_PRCESSING_FLOAT_FORMAT, + .dscl_calc_lb_num_partitions = dscl2_calc_lb_num_partitions, +}; + +bool dpp3_construct( + struct dcn3_dpp *dpp, + struct dc_context *ctx, + uint32_t inst, + const struct dcn3_dpp_registers *tf_regs, + const struct dcn3_dpp_shift *tf_shift, + const struct dcn3_dpp_mask *tf_mask) +{ + dpp->base.ctx = ctx; + + dpp->base.inst = inst; + dpp->base.funcs = &dcn30_dpp_funcs; + dpp->base.caps = &dcn30_dpp_cap; + + dpp->tf_regs = tf_regs; + dpp->tf_shift = tf_shift; + dpp->tf_mask = tf_mask; + + return true; +} + diff --git a/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_dpp.h b/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_dpp.h new file mode 100644 index 000000000..6263408d7 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_dpp.h @@ -0,0 +1,640 @@ +/* Copyright 2020 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 __DCN30_DPP_H__ +#define __DCN30_DPP_H__ + +#include "dcn20/dcn20_dpp.h" + +#define TO_DCN30_DPP(dpp)\ + container_of(dpp, struct dcn3_dpp, base) + +#define DPP_REG_LIST_DCN30_COMMON(id)\ + SRI(CM_DEALPHA, CM, id),\ + SRI(CM_MEM_PWR_STATUS, CM, id),\ + SRI(CM_BIAS_CR_R, CM, id),\ + SRI(CM_BIAS_Y_G_CB_B, CM, id),\ + SRI(PRE_DEGAM, CNVC_CFG, id),\ + SRI(CM_GAMCOR_CONTROL, CM, id),\ + SRI(CM_GAMCOR_LUT_CONTROL, CM, id),\ + SRI(CM_GAMCOR_LUT_INDEX, CM, id),\ + SRI(CM_GAMCOR_LUT_INDEX, CM, id),\ + SRI(CM_GAMCOR_LUT_DATA, CM, id),\ + SRI(CM_GAMCOR_RAMB_START_CNTL_B, CM, id),\ + SRI(CM_GAMCOR_RAMB_START_CNTL_G, CM, id),\ + SRI(CM_GAMCOR_RAMB_START_CNTL_R, CM, id),\ + SRI(CM_GAMCOR_RAMB_START_SLOPE_CNTL_B, CM, id),\ + SRI(CM_GAMCOR_RAMB_START_SLOPE_CNTL_G, CM, id),\ + SRI(CM_GAMCOR_RAMB_START_SLOPE_CNTL_R, CM, id),\ + SRI(CM_GAMCOR_RAMB_END_CNTL1_B, CM, id),\ + SRI(CM_GAMCOR_RAMB_END_CNTL2_B, CM, id),\ + SRI(CM_GAMCOR_RAMB_END_CNTL1_G, CM, id),\ + SRI(CM_GAMCOR_RAMB_END_CNTL2_G, CM, id),\ + SRI(CM_GAMCOR_RAMB_END_CNTL1_R, CM, id),\ + SRI(CM_GAMCOR_RAMB_END_CNTL2_R, CM, id),\ + SRI(CM_GAMCOR_RAMB_REGION_0_1, CM, id),\ + SRI(CM_GAMCOR_RAMB_REGION_32_33, CM, id),\ + SRI(CM_GAMCOR_RAMB_OFFSET_B, CM, id),\ + SRI(CM_GAMCOR_RAMB_OFFSET_G, CM, id),\ + SRI(CM_GAMCOR_RAMB_OFFSET_R, CM, id),\ + SRI(CM_GAMCOR_RAMB_START_BASE_CNTL_B, CM, id),\ + SRI(CM_GAMCOR_RAMB_START_BASE_CNTL_G, CM, id),\ + SRI(CM_GAMCOR_RAMB_START_BASE_CNTL_R, CM, id),\ + SRI(CM_GAMCOR_RAMA_START_CNTL_B, CM, id),\ + SRI(CM_GAMCOR_RAMA_START_CNTL_G, CM, id),\ + SRI(CM_GAMCOR_RAMA_START_CNTL_R, CM, id),\ + SRI(CM_GAMCOR_RAMA_START_SLOPE_CNTL_B, CM, id),\ + SRI(CM_GAMCOR_RAMA_START_SLOPE_CNTL_G, CM, id),\ + SRI(CM_GAMCOR_RAMA_START_SLOPE_CNTL_R, CM, id),\ + SRI(CM_GAMCOR_RAMA_END_CNTL1_B, CM, id),\ + SRI(CM_GAMCOR_RAMA_END_CNTL2_B, CM, id),\ + SRI(CM_GAMCOR_RAMA_END_CNTL1_G, CM, id),\ + SRI(CM_GAMCOR_RAMA_END_CNTL2_G, CM, id),\ + SRI(CM_GAMCOR_RAMA_END_CNTL1_R, CM, id),\ + SRI(CM_GAMCOR_RAMA_END_CNTL2_R, CM, id),\ + SRI(CM_GAMCOR_RAMA_REGION_0_1, CM, id),\ + SRI(CM_GAMCOR_RAMA_REGION_32_33, CM, id),\ + SRI(CM_GAMCOR_RAMA_OFFSET_B, CM, id),\ + SRI(CM_GAMCOR_RAMA_OFFSET_G, CM, id),\ + SRI(CM_GAMCOR_RAMA_OFFSET_R, CM, id),\ + SRI(CM_GAMCOR_RAMA_START_BASE_CNTL_B, CM, id),\ + SRI(CM_GAMCOR_RAMA_START_BASE_CNTL_G, CM, id),\ + SRI(CM_GAMCOR_RAMA_START_BASE_CNTL_R, CM, id),\ + SRI(CM_GAMUT_REMAP_CONTROL, CM, id),\ + SRI(CM_GAMUT_REMAP_C11_C12, CM, id),\ + SRI(CM_GAMUT_REMAP_C13_C14, CM, id),\ + SRI(CM_GAMUT_REMAP_C21_C22, CM, id),\ + SRI(CM_GAMUT_REMAP_C23_C24, CM, id),\ + SRI(CM_GAMUT_REMAP_C31_C32, CM, id),\ + SRI(CM_GAMUT_REMAP_C33_C34, CM, id),\ + SRI(CM_GAMUT_REMAP_B_C11_C12, CM, id),\ + SRI(CM_GAMUT_REMAP_B_C13_C14, CM, id),\ + SRI(CM_GAMUT_REMAP_B_C21_C22, CM, id),\ + SRI(CM_GAMUT_REMAP_B_C23_C24, CM, id),\ + SRI(CM_GAMUT_REMAP_B_C31_C32, CM, id),\ + SRI(CM_GAMUT_REMAP_B_C33_C34, CM, id),\ + SRI(DSCL_EXT_OVERSCAN_LEFT_RIGHT, DSCL, id), \ + SRI(DSCL_EXT_OVERSCAN_TOP_BOTTOM, DSCL, id), \ + SRI(OTG_H_BLANK, DSCL, id), \ + SRI(OTG_V_BLANK, DSCL, id), \ + SRI(SCL_MODE, DSCL, id), \ + SRI(LB_DATA_FORMAT, DSCL, id), \ + SRI(LB_MEMORY_CTRL, DSCL, id), \ + SRI(DSCL_AUTOCAL, DSCL, id), \ + SRI(SCL_TAP_CONTROL, DSCL, id), \ + SRI(SCL_COEF_RAM_TAP_SELECT, DSCL, id), \ + SRI(SCL_COEF_RAM_TAP_DATA, DSCL, id), \ + SRI(DSCL_2TAP_CONTROL, DSCL, id), \ + SRI(MPC_SIZE, DSCL, id), \ + SRI(SCL_HORZ_FILTER_SCALE_RATIO, DSCL, id), \ + SRI(SCL_VERT_FILTER_SCALE_RATIO, DSCL, id), \ + SRI(SCL_HORZ_FILTER_SCALE_RATIO_C, DSCL, id), \ + SRI(SCL_VERT_FILTER_SCALE_RATIO_C, DSCL, id), \ + SRI(SCL_HORZ_FILTER_INIT, DSCL, id), \ + SRI(SCL_HORZ_FILTER_INIT_C, DSCL, id), \ + SRI(SCL_VERT_FILTER_INIT, DSCL, id), \ + SRI(SCL_VERT_FILTER_INIT_C, DSCL, id), \ + SRI(RECOUT_START, DSCL, id), \ + SRI(RECOUT_SIZE, DSCL, id), \ + SRI(PRE_DEALPHA, CNVC_CFG, id), \ + SRI(PRE_REALPHA, CNVC_CFG, id), \ + SRI(PRE_CSC_MODE, CNVC_CFG, id), \ + SRI(PRE_CSC_C11_C12, CNVC_CFG, id), \ + SRI(PRE_CSC_C33_C34, CNVC_CFG, id), \ + SRI(PRE_CSC_B_C11_C12, CNVC_CFG, id), \ + SRI(PRE_CSC_B_C33_C34, CNVC_CFG, id), \ + SRI(CM_POST_CSC_CONTROL, CM, id), \ + SRI(CM_POST_CSC_C11_C12, CM, id), \ + SRI(CM_POST_CSC_C33_C34, CM, id), \ + SRI(CM_POST_CSC_B_C11_C12, CM, id), \ + SRI(CM_POST_CSC_B_C33_C34, CM, id), \ + SRI(CM_MEM_PWR_CTRL, CM, id), \ + SRI(CM_CONTROL, CM, id), \ + SRI(FORMAT_CONTROL, CNVC_CFG, id), \ + SRI(CNVC_SURFACE_PIXEL_FORMAT, CNVC_CFG, id), \ + SRI(CURSOR0_CONTROL, CNVC_CUR, id), \ + SRI(CURSOR0_COLOR0, CNVC_CUR, id), \ + SRI(CURSOR0_COLOR1, CNVC_CUR, id), \ + SRI(CURSOR0_FP_SCALE_BIAS, CNVC_CUR, id), \ + SRI(DPP_CONTROL, DPP_TOP, id), \ + SRI(CM_HDR_MULT_COEF, CM, id), \ + SRI(CURSOR_CONTROL, CURSOR0_, id), \ + SRI(ALPHA_2BIT_LUT, CNVC_CFG, id), \ + SRI(FCNV_FP_BIAS_R, CNVC_CFG, id), \ + SRI(FCNV_FP_BIAS_G, CNVC_CFG, id), \ + SRI(FCNV_FP_BIAS_B, CNVC_CFG, id), \ + SRI(FCNV_FP_SCALE_R, CNVC_CFG, id), \ + SRI(FCNV_FP_SCALE_G, CNVC_CFG, id), \ + SRI(FCNV_FP_SCALE_B, CNVC_CFG, id), \ + SRI(COLOR_KEYER_CONTROL, CNVC_CFG, id), \ + SRI(COLOR_KEYER_ALPHA, CNVC_CFG, id), \ + SRI(COLOR_KEYER_RED, CNVC_CFG, id), \ + SRI(COLOR_KEYER_GREEN, CNVC_CFG, id), \ + SRI(COLOR_KEYER_BLUE, CNVC_CFG, id), \ + SRI(CURSOR_CONTROL, CURSOR0_, id),\ + SRI(OBUF_MEM_PWR_CTRL, DSCL, id),\ + SRI(DSCL_MEM_PWR_STATUS, DSCL, id), \ + SRI(DSCL_MEM_PWR_CTRL, DSCL, id) + +#define DPP_REG_LIST_DCN30(id)\ + DPP_REG_LIST_DCN30_COMMON(id), \ + TF_REG_LIST_DCN20_COMMON(id), \ + SRI(CM_BLNDGAM_CONTROL, CM, id), \ + SRI(CM_SHAPER_LUT_DATA, CM, id),\ + SRI(CM_MEM_PWR_CTRL2, CM, id), \ + SRI(CM_MEM_PWR_STATUS2, CM, id), \ + SRI(CM_BLNDGAM_RAMA_START_SLOPE_CNTL_B, CM, id),\ + SRI(CM_BLNDGAM_RAMA_START_SLOPE_CNTL_G, CM, id),\ + SRI(CM_BLNDGAM_RAMA_START_SLOPE_CNTL_R, CM, id),\ + SRI(CM_BLNDGAM_RAMB_START_SLOPE_CNTL_B, CM, id),\ + SRI(CM_BLNDGAM_RAMB_START_SLOPE_CNTL_G, CM, id),\ + SRI(CM_BLNDGAM_RAMB_START_SLOPE_CNTL_R, CM, id),\ + SRI(CM_BLNDGAM_LUT_CONTROL, CM, id) + + + +#define DPP_REG_LIST_SH_MASK_DCN30_COMMON(mask_sh)\ + TF_SF(CM0_CM_MEM_PWR_STATUS, GAMCOR_MEM_PWR_STATE, mask_sh),\ + TF_SF(CM0_CM_DEALPHA, CM_DEALPHA_EN, mask_sh),\ + TF_SF(CM0_CM_DEALPHA, CM_DEALPHA_ABLND, mask_sh),\ + TF_SF(CM0_CM_BIAS_CR_R, CM_BIAS_CR_R, mask_sh),\ + TF_SF(CM0_CM_BIAS_Y_G_CB_B, CM_BIAS_Y_G, mask_sh),\ + TF_SF(CM0_CM_BIAS_Y_G_CB_B, CM_BIAS_CB_B, mask_sh),\ + TF_SF(CM0_CM_MEM_PWR_CTRL, GAMCOR_MEM_PWR_DIS, mask_sh),\ + TF_SF(CM0_CM_MEM_PWR_CTRL, GAMCOR_MEM_PWR_FORCE, mask_sh),\ + TF_SF(CNVC_CFG0_PRE_DEGAM, PRE_DEGAM_MODE, mask_sh),\ + TF_SF(CNVC_CFG0_PRE_DEGAM, PRE_DEGAM_SELECT, mask_sh),\ + TF_SF(CM0_CM_GAMCOR_CONTROL, CM_GAMCOR_MODE, mask_sh),\ + TF_SF(CM0_CM_GAMCOR_CONTROL, CM_GAMCOR_SELECT, mask_sh),\ + TF_SF(CM0_CM_GAMCOR_CONTROL, CM_GAMCOR_PWL_DISABLE, mask_sh),\ + TF_SF(CM0_CM_GAMCOR_CONTROL, CM_GAMCOR_MODE_CURRENT, mask_sh),\ + TF_SF(CM0_CM_GAMCOR_CONTROL, CM_GAMCOR_SELECT_CURRENT, mask_sh),\ + TF_SF(CM0_CM_GAMCOR_LUT_INDEX, CM_GAMCOR_LUT_INDEX, mask_sh),\ + TF_SF(CM0_CM_GAMCOR_LUT_DATA, CM_GAMCOR_LUT_DATA, mask_sh),\ + TF_SF(CM0_CM_GAMCOR_LUT_CONTROL, CM_GAMCOR_LUT_WRITE_COLOR_MASK, mask_sh),\ + TF_SF(CM0_CM_GAMCOR_LUT_CONTROL, CM_GAMCOR_LUT_READ_COLOR_SEL, mask_sh),\ + TF_SF(CM0_CM_GAMCOR_LUT_CONTROL, CM_GAMCOR_LUT_READ_DBG, mask_sh),\ + TF_SF(CM0_CM_GAMCOR_LUT_CONTROL, CM_GAMCOR_LUT_HOST_SEL, mask_sh),\ + TF_SF(CM0_CM_GAMCOR_LUT_CONTROL, CM_GAMCOR_LUT_CONFIG_MODE, mask_sh),\ + TF_SF(CM0_CM_GAMCOR_RAMA_START_CNTL_B, CM_GAMCOR_RAMA_EXP_REGION_START_B, mask_sh),\ + TF_SF(CM0_CM_GAMCOR_RAMA_START_CNTL_B, CM_GAMCOR_RAMA_EXP_REGION_START_SEGMENT_B, mask_sh),\ + TF_SF(CM0_CM_GAMCOR_RAMA_START_SLOPE_CNTL_B, CM_GAMCOR_RAMA_EXP_REGION_START_SLOPE_B, mask_sh),\ + TF_SF(CM0_CM_GAMCOR_RAMA_START_BASE_CNTL_B, CM_GAMCOR_RAMA_EXP_REGION_START_BASE_B, mask_sh),\ + TF_SF(CM0_CM_GAMCOR_RAMA_END_CNTL1_B, CM_GAMCOR_RAMA_EXP_REGION_END_BASE_B, mask_sh),\ + TF_SF(CM0_CM_GAMCOR_RAMA_END_CNTL2_B, CM_GAMCOR_RAMA_EXP_REGION_END_B, mask_sh),\ + TF_SF(CM0_CM_GAMCOR_RAMA_END_CNTL2_B, CM_GAMCOR_RAMA_EXP_REGION_END_SLOPE_B, mask_sh),\ + TF_SF(CM0_CM_GAMCOR_RAMA_OFFSET_B, CM_GAMCOR_RAMA_OFFSET_B, mask_sh),\ + TF_SF(CM0_CM_GAMCOR_RAMA_REGION_0_1, CM_GAMCOR_RAMA_EXP_REGION0_LUT_OFFSET, mask_sh),\ + TF_SF(CM0_CM_GAMCOR_RAMA_REGION_0_1, CM_GAMCOR_RAMA_EXP_REGION0_NUM_SEGMENTS, mask_sh),\ + TF_SF(CM0_CM_GAMCOR_RAMA_REGION_0_1, CM_GAMCOR_RAMA_EXP_REGION1_LUT_OFFSET, mask_sh),\ + TF_SF(CM0_CM_GAMCOR_RAMA_REGION_0_1, CM_GAMCOR_RAMA_EXP_REGION1_NUM_SEGMENTS, mask_sh),\ + TF_SF(CM0_CM_GAMUT_REMAP_CONTROL, CM_GAMUT_REMAP_MODE, mask_sh),\ + TF_SF(CM0_CM_GAMUT_REMAP_CONTROL, CM_GAMUT_REMAP_MODE_CURRENT, mask_sh),\ + TF_SF(CM0_CM_GAMUT_REMAP_C11_C12, CM_GAMUT_REMAP_C11, mask_sh),\ + TF_SF(CM0_CM_GAMUT_REMAP_C11_C12, CM_GAMUT_REMAP_C12, mask_sh),\ + TF_SF(CM0_CM_GAMUT_REMAP_C13_C14, CM_GAMUT_REMAP_C13, mask_sh),\ + TF_SF(CM0_CM_GAMUT_REMAP_C13_C14, CM_GAMUT_REMAP_C14, mask_sh),\ + TF_SF(CM0_CM_GAMUT_REMAP_C21_C22, CM_GAMUT_REMAP_C21, mask_sh),\ + TF_SF(CM0_CM_GAMUT_REMAP_C21_C22, CM_GAMUT_REMAP_C22, mask_sh),\ + TF_SF(CM0_CM_GAMUT_REMAP_C23_C24, CM_GAMUT_REMAP_C23, mask_sh),\ + TF_SF(CM0_CM_GAMUT_REMAP_C23_C24, CM_GAMUT_REMAP_C24, mask_sh),\ + TF_SF(CM0_CM_GAMUT_REMAP_C31_C32, CM_GAMUT_REMAP_C31, mask_sh),\ + TF_SF(CM0_CM_GAMUT_REMAP_C31_C32, CM_GAMUT_REMAP_C32, mask_sh),\ + TF_SF(CM0_CM_GAMUT_REMAP_C33_C34, CM_GAMUT_REMAP_C33, mask_sh),\ + TF_SF(CM0_CM_GAMUT_REMAP_C33_C34, CM_GAMUT_REMAP_C34, mask_sh),\ + TF_SF(DSCL0_DSCL_EXT_OVERSCAN_LEFT_RIGHT, EXT_OVERSCAN_LEFT, mask_sh),\ + TF_SF(DSCL0_DSCL_EXT_OVERSCAN_LEFT_RIGHT, EXT_OVERSCAN_RIGHT, mask_sh),\ + TF_SF(DSCL0_DSCL_EXT_OVERSCAN_TOP_BOTTOM, EXT_OVERSCAN_BOTTOM, mask_sh),\ + TF_SF(DSCL0_DSCL_EXT_OVERSCAN_TOP_BOTTOM, EXT_OVERSCAN_TOP, mask_sh),\ + TF_SF(DSCL0_OTG_H_BLANK, OTG_H_BLANK_START, mask_sh),\ + TF_SF(DSCL0_OTG_H_BLANK, OTG_H_BLANK_END, mask_sh),\ + TF_SF(DSCL0_OTG_V_BLANK, OTG_V_BLANK_START, mask_sh),\ + TF_SF(DSCL0_OTG_V_BLANK, OTG_V_BLANK_END, mask_sh),\ + TF_SF(DSCL0_LB_DATA_FORMAT, INTERLEAVE_EN, mask_sh),\ + TF2_SF(DSCL0, LB_DATA_FORMAT__ALPHA_EN, mask_sh),\ + TF_SF(DSCL0_LB_MEMORY_CTRL, MEMORY_CONFIG, mask_sh),\ + TF_SF(DSCL0_LB_MEMORY_CTRL, LB_MAX_PARTITIONS, mask_sh),\ + TF_SF(DSCL0_DSCL_AUTOCAL, AUTOCAL_MODE, mask_sh),\ + TF_SF(DSCL0_DSCL_AUTOCAL, AUTOCAL_NUM_PIPE, mask_sh),\ + TF_SF(DSCL0_DSCL_AUTOCAL, AUTOCAL_PIPE_ID, mask_sh),\ + TF_SF(DSCL0_SCL_TAP_CONTROL, SCL_V_NUM_TAPS, mask_sh),\ + TF_SF(DSCL0_SCL_TAP_CONTROL, SCL_H_NUM_TAPS, mask_sh),\ + TF_SF(DSCL0_SCL_TAP_CONTROL, SCL_V_NUM_TAPS_C, mask_sh),\ + TF_SF(DSCL0_SCL_TAP_CONTROL, SCL_H_NUM_TAPS_C, mask_sh),\ + TF_SF(DSCL0_SCL_COEF_RAM_TAP_SELECT, SCL_COEF_RAM_TAP_PAIR_IDX, mask_sh),\ + TF_SF(DSCL0_SCL_COEF_RAM_TAP_SELECT, SCL_COEF_RAM_PHASE, mask_sh),\ + TF_SF(DSCL0_SCL_COEF_RAM_TAP_SELECT, SCL_COEF_RAM_FILTER_TYPE, mask_sh),\ + TF_SF(DSCL0_SCL_COEF_RAM_TAP_DATA, SCL_COEF_RAM_EVEN_TAP_COEF, mask_sh),\ + TF_SF(DSCL0_SCL_COEF_RAM_TAP_DATA, SCL_COEF_RAM_EVEN_TAP_COEF_EN, mask_sh),\ + TF_SF(DSCL0_SCL_COEF_RAM_TAP_DATA, SCL_COEF_RAM_ODD_TAP_COEF, mask_sh),\ + TF_SF(DSCL0_SCL_COEF_RAM_TAP_DATA, SCL_COEF_RAM_ODD_TAP_COEF_EN, mask_sh),\ + TF_SF(DSCL0_DSCL_2TAP_CONTROL, SCL_H_2TAP_HARDCODE_COEF_EN, mask_sh),\ + TF_SF(DSCL0_DSCL_2TAP_CONTROL, SCL_H_2TAP_SHARP_EN, mask_sh),\ + TF_SF(DSCL0_DSCL_2TAP_CONTROL, SCL_H_2TAP_SHARP_FACTOR, mask_sh),\ + TF_SF(DSCL0_DSCL_2TAP_CONTROL, SCL_V_2TAP_HARDCODE_COEF_EN, mask_sh),\ + TF_SF(DSCL0_DSCL_2TAP_CONTROL, SCL_V_2TAP_SHARP_EN, mask_sh),\ + TF_SF(DSCL0_DSCL_2TAP_CONTROL, SCL_V_2TAP_SHARP_FACTOR, mask_sh),\ + TF_SF(DSCL0_SCL_MODE, SCL_COEF_RAM_SELECT, mask_sh),\ + TF_SF(DSCL0_SCL_MODE, DSCL_MODE, mask_sh),\ + TF_SF(DSCL0_RECOUT_START, RECOUT_START_X, mask_sh),\ + TF_SF(DSCL0_RECOUT_START, RECOUT_START_Y, mask_sh),\ + TF_SF(DSCL0_RECOUT_SIZE, RECOUT_WIDTH, mask_sh),\ + TF_SF(DSCL0_RECOUT_SIZE, RECOUT_HEIGHT, mask_sh),\ + TF_SF(DSCL0_MPC_SIZE, MPC_WIDTH, mask_sh),\ + TF_SF(DSCL0_MPC_SIZE, MPC_HEIGHT, mask_sh),\ + TF_SF(DSCL0_SCL_HORZ_FILTER_SCALE_RATIO, SCL_H_SCALE_RATIO, mask_sh),\ + TF_SF(DSCL0_SCL_VERT_FILTER_SCALE_RATIO, SCL_V_SCALE_RATIO, mask_sh),\ + TF_SF(DSCL0_SCL_HORZ_FILTER_SCALE_RATIO_C, SCL_H_SCALE_RATIO_C, mask_sh),\ + TF_SF(DSCL0_SCL_VERT_FILTER_SCALE_RATIO_C, SCL_V_SCALE_RATIO_C, mask_sh),\ + TF_SF(DSCL0_SCL_HORZ_FILTER_INIT, SCL_H_INIT_FRAC, mask_sh),\ + TF_SF(DSCL0_SCL_HORZ_FILTER_INIT, SCL_H_INIT_INT, mask_sh),\ + TF_SF(DSCL0_SCL_HORZ_FILTER_INIT_C, SCL_H_INIT_FRAC_C, mask_sh),\ + TF_SF(DSCL0_SCL_HORZ_FILTER_INIT_C, SCL_H_INIT_INT_C, mask_sh),\ + TF_SF(DSCL0_SCL_VERT_FILTER_INIT, SCL_V_INIT_FRAC, mask_sh),\ + TF_SF(DSCL0_SCL_VERT_FILTER_INIT, SCL_V_INIT_INT, mask_sh),\ + TF_SF(DSCL0_SCL_VERT_FILTER_INIT_C, SCL_V_INIT_FRAC_C, mask_sh),\ + TF_SF(DSCL0_SCL_VERT_FILTER_INIT_C, SCL_V_INIT_INT_C, mask_sh),\ + TF_SF(DSCL0_SCL_MODE, SCL_CHROMA_COEF_MODE, mask_sh),\ + TF_SF(DSCL0_SCL_MODE, SCL_COEF_RAM_SELECT_CURRENT, mask_sh), \ + TF_SF(CNVC_CFG0_PRE_DEALPHA, PRE_DEALPHA_EN, mask_sh), \ + TF_SF(CNVC_CFG0_PRE_DEALPHA, PRE_DEALPHA_ABLND_EN, mask_sh), \ + TF_SF(CNVC_CFG0_PRE_REALPHA, PRE_REALPHA_EN, mask_sh), \ + TF_SF(CNVC_CFG0_PRE_REALPHA, PRE_REALPHA_ABLND_EN, mask_sh), \ + TF_SF(CNVC_CFG0_PRE_CSC_MODE, PRE_CSC_MODE, mask_sh), \ + TF_SF(CNVC_CFG0_PRE_CSC_MODE, PRE_CSC_MODE_CURRENT, mask_sh), \ + TF_SF(CNVC_CFG0_PRE_CSC_C11_C12, PRE_CSC_C11, mask_sh), \ + TF_SF(CNVC_CFG0_PRE_CSC_C11_C12, PRE_CSC_C12, mask_sh), \ + TF_SF(CNVC_CFG0_PRE_CSC_C33_C34, PRE_CSC_C33, mask_sh), \ + TF_SF(CNVC_CFG0_PRE_CSC_C33_C34, PRE_CSC_C34, mask_sh), \ + TF_SF(CM0_CM_POST_CSC_CONTROL, CM_POST_CSC_MODE, mask_sh), \ + TF_SF(CM0_CM_POST_CSC_CONTROL, CM_POST_CSC_MODE_CURRENT, mask_sh), \ + TF_SF(CM0_CM_POST_CSC_C11_C12, CM_POST_CSC_C11, mask_sh), \ + TF_SF(CM0_CM_POST_CSC_C11_C12, CM_POST_CSC_C12, mask_sh), \ + TF_SF(CM0_CM_POST_CSC_C33_C34, CM_POST_CSC_C33, mask_sh), \ + TF_SF(CM0_CM_POST_CSC_C33_C34, CM_POST_CSC_C34, mask_sh), \ + TF_SF(CNVC_CFG0_FORMAT_CONTROL, CNVC_BYPASS, mask_sh), \ + TF2_SF(CNVC_CFG0, FORMAT_CONTROL__ALPHA_EN, mask_sh), \ + TF_SF(CNVC_CFG0_FORMAT_CONTROL, FORMAT_EXPANSION_MODE, mask_sh), \ + TF_SF(CNVC_CFG0_CNVC_SURFACE_PIXEL_FORMAT, CNVC_SURFACE_PIXEL_FORMAT, mask_sh), \ + TF_SF(CNVC_CFG0_CNVC_SURFACE_PIXEL_FORMAT, CNVC_ALPHA_PLANE_ENABLE, mask_sh), \ + TF_SF(CNVC_CUR0_CURSOR0_CONTROL, CUR0_MODE, mask_sh), \ + TF_SF(CNVC_CUR0_CURSOR0_CONTROL, CUR0_EXPANSION_MODE, mask_sh), \ + TF_SF(CNVC_CUR0_CURSOR0_CONTROL, CUR0_ENABLE, mask_sh), \ + TF_SF(CNVC_CUR0_CURSOR0_COLOR0, CUR0_COLOR0, mask_sh), \ + TF_SF(CNVC_CUR0_CURSOR0_COLOR1, CUR0_COLOR1, mask_sh), \ + TF_SF(CNVC_CUR0_CURSOR0_FP_SCALE_BIAS, CUR0_FP_BIAS, mask_sh), \ + TF_SF(CNVC_CUR0_CURSOR0_FP_SCALE_BIAS, CUR0_FP_SCALE, mask_sh), \ + TF_SF(DPP_TOP0_DPP_CONTROL, DPP_CLOCK_ENABLE, mask_sh), \ + TF_SF(CM0_CM_HDR_MULT_COEF, CM_HDR_MULT_COEF, mask_sh), \ + TF_SF(CM0_CM_CONTROL, CM_BYPASS, mask_sh), \ + TF_SF(CURSOR0_0_CURSOR_CONTROL, CURSOR_MODE, mask_sh), \ + TF_SF(CURSOR0_0_CURSOR_CONTROL, CURSOR_PITCH, mask_sh), \ + TF_SF(CURSOR0_0_CURSOR_CONTROL, CURSOR_LINES_PER_CHUNK, mask_sh), \ + TF_SF(CURSOR0_0_CURSOR_CONTROL, CURSOR_ENABLE, mask_sh), \ + TF_SF(CNVC_CFG0_FORMAT_CONTROL, FORMAT_CNV16, mask_sh), \ + TF_SF(CNVC_CFG0_FORMAT_CONTROL, CNVC_BYPASS_MSB_ALIGN, mask_sh), \ + TF_SF(CNVC_CFG0_FORMAT_CONTROL, CLAMP_POSITIVE, mask_sh), \ + TF_SF(CNVC_CFG0_FORMAT_CONTROL, CLAMP_POSITIVE_C, mask_sh), \ + TF_SF(CNVC_CFG0_FORMAT_CONTROL, FORMAT_CROSSBAR_R, mask_sh), \ + TF_SF(CNVC_CFG0_FORMAT_CONTROL, FORMAT_CROSSBAR_G, mask_sh), \ + TF_SF(CNVC_CFG0_FORMAT_CONTROL, FORMAT_CROSSBAR_B, mask_sh), \ + TF_SF(CNVC_CFG0_ALPHA_2BIT_LUT, ALPHA_2BIT_LUT0, mask_sh), \ + TF_SF(CNVC_CFG0_ALPHA_2BIT_LUT, ALPHA_2BIT_LUT1, mask_sh), \ + TF_SF(CNVC_CFG0_ALPHA_2BIT_LUT, ALPHA_2BIT_LUT2, mask_sh), \ + TF_SF(CNVC_CFG0_ALPHA_2BIT_LUT, ALPHA_2BIT_LUT3, mask_sh), \ + TF_SF(CNVC_CFG0_FCNV_FP_BIAS_R, FCNV_FP_BIAS_R, mask_sh), \ + TF_SF(CNVC_CFG0_FCNV_FP_BIAS_G, FCNV_FP_BIAS_G, mask_sh), \ + TF_SF(CNVC_CFG0_FCNV_FP_BIAS_B, FCNV_FP_BIAS_B, mask_sh), \ + TF_SF(CNVC_CFG0_FCNV_FP_SCALE_R, FCNV_FP_SCALE_R, mask_sh), \ + TF_SF(CNVC_CFG0_FCNV_FP_SCALE_G, FCNV_FP_SCALE_G, mask_sh), \ + TF_SF(CNVC_CFG0_FCNV_FP_SCALE_B, FCNV_FP_SCALE_B, mask_sh), \ + TF_SF(CNVC_CFG0_COLOR_KEYER_CONTROL, COLOR_KEYER_EN, mask_sh), \ + TF_SF(CNVC_CFG0_COLOR_KEYER_CONTROL, COLOR_KEYER_MODE, mask_sh), \ + TF_SF(CNVC_CFG0_COLOR_KEYER_ALPHA, COLOR_KEYER_ALPHA_LOW, mask_sh), \ + TF_SF(CNVC_CFG0_COLOR_KEYER_ALPHA, COLOR_KEYER_ALPHA_HIGH, mask_sh), \ + TF_SF(CNVC_CFG0_COLOR_KEYER_RED, COLOR_KEYER_RED_LOW, mask_sh), \ + TF_SF(CNVC_CFG0_COLOR_KEYER_RED, COLOR_KEYER_RED_HIGH, mask_sh), \ + TF_SF(CNVC_CFG0_COLOR_KEYER_GREEN, COLOR_KEYER_GREEN_LOW, mask_sh), \ + TF_SF(CNVC_CFG0_COLOR_KEYER_GREEN, COLOR_KEYER_GREEN_HIGH, mask_sh), \ + TF_SF(CNVC_CFG0_COLOR_KEYER_BLUE, COLOR_KEYER_BLUE_LOW, mask_sh), \ + TF_SF(CNVC_CFG0_COLOR_KEYER_BLUE, COLOR_KEYER_BLUE_HIGH, mask_sh), \ + TF_SF(CNVC_CUR0_CURSOR0_CONTROL, CUR0_PIX_INV_MODE, mask_sh), \ + TF_SF(CNVC_CUR0_CURSOR0_CONTROL, CUR0_PIXEL_ALPHA_MOD_EN, mask_sh), \ + TF_SF(CNVC_CUR0_CURSOR0_CONTROL, CUR0_ROM_EN, mask_sh),\ + TF_SF(DSCL0_OBUF_MEM_PWR_CTRL, OBUF_MEM_PWR_FORCE, mask_sh),\ + TF_SF(DSCL0_DSCL_MEM_PWR_CTRL, LUT_MEM_PWR_FORCE, mask_sh),\ + TF_SF(DSCL0_DSCL_MEM_PWR_STATUS, LUT_MEM_PWR_STATE, mask_sh) + +#define DPP_REG_LIST_SH_MASK_DCN30_UPDATED(mask_sh)\ + TF_SF(CM0_CM_MEM_PWR_STATUS, BLNDGAM_MEM_PWR_STATE, mask_sh), \ + TF_SF(CM0_CM_MEM_PWR_CTRL2, HDR3DLUT_MEM_PWR_FORCE, mask_sh),\ + TF_SF(CM0_CM_MEM_PWR_CTRL2, SHAPER_MEM_PWR_FORCE, mask_sh),\ + TF_SF(CM0_CM_MEM_PWR_STATUS2, HDR3DLUT_MEM_PWR_STATE, mask_sh),\ + TF_SF(CM0_CM_MEM_PWR_STATUS2, SHAPER_MEM_PWR_STATE, mask_sh),\ + TF_SF(CM0_CM_BLNDGAM_CONTROL, CM_BLNDGAM_MODE, mask_sh), \ + TF_SF(CM0_CM_BLNDGAM_CONTROL, CM_BLNDGAM_MODE_CURRENT, mask_sh), \ + TF_SF(CM0_CM_BLNDGAM_CONTROL, CM_BLNDGAM_SELECT_CURRENT, mask_sh), \ + TF_SF(CM0_CM_BLNDGAM_CONTROL, CM_BLNDGAM_SELECT, mask_sh), \ + TF_SF(CM0_CM_BLNDGAM_RAMB_START_SLOPE_CNTL_B, CM_BLNDGAM_RAMB_EXP_REGION_START_SLOPE_B, mask_sh), \ + TF_SF(CM0_CM_BLNDGAM_RAMB_START_SLOPE_CNTL_G, CM_BLNDGAM_RAMB_EXP_REGION_START_SLOPE_G, mask_sh), \ + TF_SF(CM0_CM_BLNDGAM_RAMB_START_SLOPE_CNTL_R, CM_BLNDGAM_RAMB_EXP_REGION_START_SLOPE_R, mask_sh), \ + TF_SF(CM0_CM_BLNDGAM_RAMB_END_CNTL1_B, CM_BLNDGAM_RAMB_EXP_REGION_END_BASE_B, mask_sh), \ + TF_SF(CM0_CM_BLNDGAM_RAMB_END_CNTL1_G, CM_BLNDGAM_RAMB_EXP_REGION_END_BASE_G, mask_sh), \ + TF_SF(CM0_CM_BLNDGAM_RAMB_END_CNTL1_R, CM_BLNDGAM_RAMB_EXP_REGION_END_BASE_R, mask_sh), \ + TF_SF(CM0_CM_BLNDGAM_RAMA_START_SLOPE_CNTL_B, CM_BLNDGAM_RAMA_EXP_REGION_START_SLOPE_B, mask_sh), \ + TF_SF(CM0_CM_BLNDGAM_RAMA_START_SLOPE_CNTL_G, CM_BLNDGAM_RAMA_EXP_REGION_START_SLOPE_G, mask_sh), \ + TF_SF(CM0_CM_BLNDGAM_RAMA_START_SLOPE_CNTL_R, CM_BLNDGAM_RAMA_EXP_REGION_START_SLOPE_R, mask_sh), \ + TF_SF(CM0_CM_BLNDGAM_RAMA_END_CNTL1_B, CM_BLNDGAM_RAMA_EXP_REGION_END_BASE_B, mask_sh), \ + TF_SF(CM0_CM_BLNDGAM_RAMA_END_CNTL1_G, CM_BLNDGAM_RAMA_EXP_REGION_END_BASE_G, mask_sh), \ + TF_SF(CM0_CM_BLNDGAM_RAMA_END_CNTL1_R, CM_BLNDGAM_RAMA_EXP_REGION_END_BASE_R, mask_sh), \ + TF_SF(CM0_CM_BLNDGAM_RAMA_END_CNTL2_B, CM_BLNDGAM_RAMA_EXP_REGION_END_B, mask_sh), \ + TF_SF(CM0_CM_BLNDGAM_RAMA_END_CNTL2_G, CM_BLNDGAM_RAMA_EXP_REGION_END_G, mask_sh), \ + TF_SF(CM0_CM_BLNDGAM_RAMA_END_CNTL2_R, CM_BLNDGAM_RAMA_EXP_REGION_END_R, mask_sh), \ + TF_SF(CM0_CM_BLNDGAM_LUT_CONTROL, CM_BLNDGAM_LUT_WRITE_COLOR_MASK, mask_sh), \ + TF_SF(CM0_CM_BLNDGAM_LUT_CONTROL, CM_BLNDGAM_LUT_HOST_SEL, mask_sh), \ + TF_SF(CM0_CM_BLNDGAM_LUT_CONTROL, CM_BLNDGAM_LUT_CONFIG_MODE, mask_sh), \ + TF_SF(CM0_CM_3DLUT_MODE, CM_3DLUT_MODE_CURRENT, mask_sh), \ + TF_SF(CM0_CM_SHAPER_CONTROL, CM_SHAPER_MODE_CURRENT, mask_sh) + + +#define DPP_REG_LIST_SH_MASK_DCN30(mask_sh)\ + DPP_REG_LIST_SH_MASK_DCN30_COMMON(mask_sh), \ + TF_REG_LIST_SH_MASK_DCN20_COMMON(mask_sh), \ + DPP_REG_LIST_SH_MASK_DCN30_UPDATED(mask_sh) + +#define DPP_REG_FIELD_LIST_DCN3(type) \ + TF_REG_FIELD_LIST_DCN2_0(type); \ + type FORMAT_CROSSBAR_R; \ + type FORMAT_CROSSBAR_G; \ + type FORMAT_CROSSBAR_B; \ + type CM_DEALPHA_EN;\ + type CM_DEALPHA_ABLND;\ + type CM_BIAS_Y_G;\ + type CM_BIAS_CB_B;\ + type CM_BIAS_CR_R;\ + type GAMCOR_MEM_PWR_DIS; \ + type GAMCOR_MEM_PWR_FORCE; \ + type HDR3DLUT_MEM_PWR_FORCE; \ + type SHAPER_MEM_PWR_FORCE; \ + type PRE_DEGAM_MODE;\ + type PRE_DEGAM_SELECT;\ + type CNVC_ALPHA_PLANE_ENABLE; \ + type PRE_DEALPHA_EN; \ + type PRE_DEALPHA_ABLND_EN; \ + type PRE_REALPHA_EN; \ + type PRE_REALPHA_ABLND_EN; \ + type PRE_CSC_MODE; \ + type PRE_CSC_MODE_CURRENT; \ + type PRE_CSC_C11; \ + type PRE_CSC_C12; \ + type PRE_CSC_C33; \ + type PRE_CSC_C34; \ + type CM_POST_CSC_MODE; \ + type CM_POST_CSC_MODE_CURRENT; \ + type CM_POST_CSC_C11; \ + type CM_POST_CSC_C12; \ + type CM_POST_CSC_C33; \ + type CM_POST_CSC_C34; \ + type CM_GAMCOR_MODE; \ + type CM_GAMCOR_SELECT; \ + type CM_GAMCOR_PWL_DISABLE; \ + type CM_GAMCOR_MODE_CURRENT; \ + type CM_GAMCOR_SELECT_CURRENT; \ + type CM_GAMCOR_LUT_INDEX; \ + type CM_GAMCOR_LUT_DATA; \ + type CM_GAMCOR_LUT_WRITE_COLOR_MASK; \ + type CM_GAMCOR_LUT_READ_COLOR_SEL; \ + type CM_GAMCOR_LUT_READ_DBG; \ + type CM_GAMCOR_LUT_HOST_SEL; \ + type CM_GAMCOR_LUT_CONFIG_MODE; \ + type CM_GAMCOR_LUT_STATUS; \ + type CM_GAMCOR_RAMA_EXP_REGION_START_B; \ + type CM_GAMCOR_RAMA_EXP_REGION_START_SEGMENT_B; \ + type CM_GAMCOR_RAMA_EXP_REGION_START_SLOPE_B; \ + type CM_GAMCOR_RAMA_EXP_REGION_START_BASE_B; \ + type CM_GAMCOR_RAMA_EXP_REGION_END_BASE_B; \ + type CM_GAMCOR_RAMA_EXP_REGION_END_B; \ + type CM_GAMCOR_RAMA_EXP_REGION_END_SLOPE_B; \ + type CM_GAMCOR_RAMA_OFFSET_B; \ + type CM_GAMCOR_RAMA_EXP_REGION0_LUT_OFFSET; \ + type CM_GAMCOR_RAMA_EXP_REGION0_NUM_SEGMENTS; \ + type CM_GAMCOR_RAMA_EXP_REGION1_LUT_OFFSET; \ + type CM_GAMCOR_RAMA_EXP_REGION1_NUM_SEGMENTS;\ + type CM_GAMUT_REMAP_MODE_CURRENT;\ + type CM_BLNDGAM_RAMB_EXP_REGION_START_SLOPE_B; \ + type CM_BLNDGAM_RAMB_EXP_REGION_START_SLOPE_G; \ + type CM_BLNDGAM_RAMB_EXP_REGION_START_SLOPE_R; \ + type CM_BLNDGAM_RAMA_EXP_REGION_START_SLOPE_B; \ + type CM_BLNDGAM_RAMA_EXP_REGION_START_SLOPE_G; \ + type CM_BLNDGAM_RAMA_EXP_REGION_START_SLOPE_R; \ + type CM_BLNDGAM_LUT_WRITE_COLOR_MASK; \ + type CM_BLNDGAM_LUT_HOST_SEL; \ + type CM_BLNDGAM_LUT_CONFIG_MODE; \ + type CM_3DLUT_MODE_CURRENT; \ + type CM_SHAPER_MODE_CURRENT; \ + type CM_BLNDGAM_MODE; \ + type CM_BLNDGAM_MODE_CURRENT; \ + type CM_BLNDGAM_SELECT_CURRENT; \ + type CM_BLNDGAM_SELECT; \ + type GAMCOR_MEM_PWR_STATE; \ + type BLNDGAM_MEM_PWR_STATE; \ + type HDR3DLUT_MEM_PWR_STATE; \ + type SHAPER_MEM_PWR_STATE + +struct dcn3_dpp_shift { + DPP_REG_FIELD_LIST_DCN3(uint8_t); +}; + +struct dcn3_dpp_mask { + DPP_REG_FIELD_LIST_DCN3(uint32_t); +}; + +#define DPP_DCN3_REG_VARIABLE_LIST_COMMON \ + DPP_DCN2_REG_VARIABLE_LIST; \ + uint32_t CM_MEM_PWR_STATUS;\ + uint32_t CM_MEM_PWR_STATUS2;\ + uint32_t CM_MEM_PWR_CTRL2;\ + uint32_t CM_DEALPHA;\ + uint32_t CM_BIAS_CR_R;\ + uint32_t CM_BIAS_Y_G_CB_B;\ + uint32_t PRE_DEGAM;\ + uint32_t PRE_DEALPHA; \ + uint32_t PRE_REALPHA; \ + uint32_t PRE_CSC_MODE; \ + uint32_t PRE_CSC_C11_C12; \ + uint32_t PRE_CSC_C33_C34; \ + uint32_t PRE_CSC_B_C11_C12; \ + uint32_t PRE_CSC_B_C33_C34; \ + uint32_t CM_POST_CSC_CONTROL; \ + uint32_t CM_POST_CSC_C11_C12; \ + uint32_t CM_POST_CSC_C33_C34; \ + uint32_t CM_POST_CSC_B_C11_C12; \ + uint32_t CM_POST_CSC_B_C33_C34; \ + uint32_t CM_GAMUT_REMAP_B_C11_C12; \ + uint32_t CM_GAMUT_REMAP_B_C13_C14; \ + uint32_t CM_GAMUT_REMAP_B_C21_C22; \ + uint32_t CM_GAMUT_REMAP_B_C23_C24; \ + uint32_t CM_GAMUT_REMAP_B_C31_C32; \ + uint32_t CM_GAMUT_REMAP_B_C33_C34; \ + uint32_t CM_GAMCOR_CONTROL; \ + uint32_t CM_GAMCOR_LUT_CONTROL; \ + uint32_t CM_GAMCOR_LUT_INDEX; \ + uint32_t CM_GAMCOR_LUT_DATA; \ + uint32_t CM_GAMCOR_RAMB_START_CNTL_B; \ + uint32_t CM_GAMCOR_RAMB_START_CNTL_G; \ + uint32_t CM_GAMCOR_RAMB_START_CNTL_R; \ + uint32_t CM_GAMCOR_RAMB_START_SLOPE_CNTL_B; \ + uint32_t CM_GAMCOR_RAMB_START_SLOPE_CNTL_G; \ + uint32_t CM_GAMCOR_RAMB_START_SLOPE_CNTL_R; \ + uint32_t CM_GAMCOR_RAMB_END_CNTL1_B; \ + uint32_t CM_GAMCOR_RAMB_END_CNTL2_B; \ + uint32_t CM_GAMCOR_RAMB_END_CNTL1_G; \ + uint32_t CM_GAMCOR_RAMB_END_CNTL2_G; \ + uint32_t CM_GAMCOR_RAMB_END_CNTL1_R; \ + uint32_t CM_GAMCOR_RAMB_END_CNTL2_R; \ + uint32_t CM_GAMCOR_RAMB_REGION_0_1; \ + uint32_t CM_GAMCOR_RAMB_REGION_32_33; \ + uint32_t CM_GAMCOR_RAMB_OFFSET_B; \ + uint32_t CM_GAMCOR_RAMB_OFFSET_G; \ + uint32_t CM_GAMCOR_RAMB_OFFSET_R; \ + uint32_t CM_GAMCOR_RAMB_START_BASE_CNTL_B; \ + uint32_t CM_GAMCOR_RAMB_START_BASE_CNTL_G; \ + uint32_t CM_GAMCOR_RAMB_START_BASE_CNTL_R; \ + uint32_t CM_GAMCOR_RAMA_START_CNTL_B; \ + uint32_t CM_GAMCOR_RAMA_START_CNTL_G; \ + uint32_t CM_GAMCOR_RAMA_START_CNTL_R; \ + uint32_t CM_GAMCOR_RAMA_START_SLOPE_CNTL_B; \ + uint32_t CM_GAMCOR_RAMA_START_SLOPE_CNTL_G; \ + uint32_t CM_GAMCOR_RAMA_START_SLOPE_CNTL_R; \ + uint32_t CM_GAMCOR_RAMA_END_CNTL1_B; \ + uint32_t CM_GAMCOR_RAMA_END_CNTL2_B; \ + uint32_t CM_GAMCOR_RAMA_END_CNTL1_G; \ + uint32_t CM_GAMCOR_RAMA_END_CNTL2_G; \ + uint32_t CM_GAMCOR_RAMA_END_CNTL1_R; \ + uint32_t CM_GAMCOR_RAMA_END_CNTL2_R; \ + uint32_t CM_GAMCOR_RAMA_REGION_0_1; \ + uint32_t CM_GAMCOR_RAMA_REGION_32_33; \ + uint32_t CM_GAMCOR_RAMA_OFFSET_B; \ + uint32_t CM_GAMCOR_RAMA_OFFSET_G; \ + uint32_t CM_GAMCOR_RAMA_OFFSET_R; \ + uint32_t CM_GAMCOR_RAMA_START_BASE_CNTL_B; \ + uint32_t CM_GAMCOR_RAMA_START_BASE_CNTL_G; \ + uint32_t CM_GAMCOR_RAMA_START_BASE_CNTL_R; \ + uint32_t CM_BLNDGAM_RAMA_START_SLOPE_CNTL_B; \ + uint32_t CM_BLNDGAM_RAMA_START_SLOPE_CNTL_G; \ + uint32_t CM_BLNDGAM_RAMA_START_SLOPE_CNTL_R; \ + uint32_t CM_BLNDGAM_RAMB_START_SLOPE_CNTL_B; \ + uint32_t CM_BLNDGAM_RAMB_START_SLOPE_CNTL_G; \ + uint32_t CM_BLNDGAM_RAMB_START_SLOPE_CNTL_R; \ + uint32_t CM_BLNDGAM_LUT_CONTROL + + +struct dcn3_dpp_registers { + DPP_DCN3_REG_VARIABLE_LIST_COMMON; +}; + + +struct dcn3_dpp { + struct dpp base; + + const struct dcn3_dpp_registers *tf_regs; + const struct dcn3_dpp_shift *tf_shift; + const struct dcn3_dpp_mask *tf_mask; + + const uint16_t *filter_v; + const uint16_t *filter_h; + const uint16_t *filter_v_c; + const uint16_t *filter_h_c; + int lb_pixel_depth_supported; + int lb_memory_size; + int lb_bits_per_entry; + bool is_write_to_ram_a_safe; + struct scaler_data scl_data; + struct pwl_params pwl_data; +}; + +bool dpp3_construct(struct dcn3_dpp *dpp3, + struct dc_context *ctx, + uint32_t inst, + const struct dcn3_dpp_registers *tf_regs, + const struct dcn3_dpp_shift *tf_shift, + const struct dcn3_dpp_mask *tf_mask); + +bool dpp3_program_gamcor_lut( + struct dpp *dpp_base, const struct pwl_params *params); + +void dpp3_program_CM_dealpha( + struct dpp *dpp_base, + uint32_t enable, uint32_t additive_blending); + +void dpp30_read_state(struct dpp *dpp_base, + struct dcn_dpp_state *s); + +bool dpp3_get_optimal_number_of_taps( + struct dpp *dpp, + struct scaler_data *scl_data, + const struct scaling_taps *in_taps); + +void dpp3_cnv_setup ( + struct dpp *dpp_base, + enum surface_pixel_format format, + enum expansion_mode mode, + struct dc_csc_transform input_csc_color_matrix, + enum dc_color_space input_color_space, + struct cnv_alpha_2bit_lut *alpha_2bit_lut); + +void dpp3_program_CM_bias( + struct dpp *dpp_base, + struct CM_bias_params *bias_params); + +void dpp3_set_hdr_multiplier( + struct dpp *dpp_base, + uint32_t multiplier); + +void dpp3_cm_set_gamut_remap( + struct dpp *dpp_base, + const struct dpp_grph_csc_adjustment *adjust); + +void dpp3_set_pre_degam(struct dpp *dpp_base, + enum dc_transfer_func_predefined tr); + +void dpp3_set_cursor_attributes( + struct dpp *dpp_base, + struct dc_cursor_attributes *cursor_attributes); + +void dpp3_program_post_csc( + struct dpp *dpp_base, + enum dc_color_space color_space, + enum dcn10_input_csc_select input_select, + const struct out_csc_color_matrix *tbl_entry); + +void dpp3_program_cm_bias( + struct dpp *dpp_base, + struct CM_bias_params *bias_params); + +void dpp3_program_cm_dealpha( + struct dpp *dpp_base, + uint32_t enable, uint32_t additive_blending); + +#endif /* __DC_HWSS_DCN30_H__ */ diff --git a/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_dpp_cm.c b/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_dpp_cm.c new file mode 100644 index 000000000..e43f77c11 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_dpp_cm.c @@ -0,0 +1,410 @@ +/* + * Copyright 2020 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 "core_types.h" +#include "reg_helper.h" +#include "dcn30_dpp.h" +#include "basics/conversion.h" +#include "dcn30_cm_common.h" + +#define REG(reg)\ + dpp->tf_regs->reg + +#define CTX \ + dpp->base.ctx + +#undef FN +#define FN(reg_name, field_name) \ + dpp->tf_shift->field_name, dpp->tf_mask->field_name + +static void dpp3_enable_cm_block( + struct dpp *dpp_base) +{ + struct dcn3_dpp *dpp = TO_DCN30_DPP(dpp_base); + + unsigned int cm_bypass_mode = 0; + + // debug option: put CM in bypass mode + if (dpp_base->ctx->dc->debug.cm_in_bypass) + cm_bypass_mode = 1; + + REG_UPDATE(CM_CONTROL, CM_BYPASS, cm_bypass_mode); +} + +static enum dc_lut_mode dpp30_get_gamcor_current(struct dpp *dpp_base) +{ + enum dc_lut_mode mode; + uint32_t state_mode; + uint32_t lut_mode; + struct dcn3_dpp *dpp = TO_DCN30_DPP(dpp_base); + + REG_GET(CM_GAMCOR_CONTROL, CM_GAMCOR_MODE_CURRENT, &state_mode); + + if (state_mode == 0) + mode = LUT_BYPASS; + + if (state_mode == 2) {//Programmable RAM LUT + REG_GET(CM_GAMCOR_CONTROL, CM_GAMCOR_SELECT_CURRENT, &lut_mode); + if (lut_mode == 0) + mode = LUT_RAM_A; + else + mode = LUT_RAM_B; + } + + return mode; +} + +static void dpp3_program_gammcor_lut( + struct dpp *dpp_base, + const struct pwl_result_data *rgb, + uint32_t num, + bool is_ram_a) +{ + uint32_t i; + struct dcn3_dpp *dpp = TO_DCN30_DPP(dpp_base); + uint32_t last_base_value_red = rgb[num-1].red_reg + rgb[num-1].delta_red_reg; + uint32_t last_base_value_green = rgb[num-1].green_reg + rgb[num-1].delta_green_reg; + uint32_t last_base_value_blue = rgb[num-1].blue_reg + rgb[num-1].delta_blue_reg; + + /*fill in the LUT with all base values to be used by pwl module + * HW auto increments the LUT index: back-to-back write + */ + if (is_rgb_equal(rgb, num)) { + for (i = 0 ; i < num; i++) + REG_SET(CM_GAMCOR_LUT_DATA, 0, CM_GAMCOR_LUT_DATA, rgb[i].red_reg); + + REG_SET(CM_GAMCOR_LUT_DATA, 0, CM_GAMCOR_LUT_DATA, last_base_value_red); + + } else { + REG_UPDATE(CM_GAMCOR_LUT_CONTROL, + CM_GAMCOR_LUT_WRITE_COLOR_MASK, 4); + for (i = 0 ; i < num; i++) + REG_SET(CM_GAMCOR_LUT_DATA, 0, CM_GAMCOR_LUT_DATA, rgb[i].red_reg); + + REG_SET(CM_GAMCOR_LUT_DATA, 0, CM_GAMCOR_LUT_DATA, last_base_value_red); + + REG_SET(CM_GAMCOR_LUT_INDEX, 0, CM_GAMCOR_LUT_INDEX, 0); + + REG_UPDATE(CM_GAMCOR_LUT_CONTROL, + CM_GAMCOR_LUT_WRITE_COLOR_MASK, 2); + for (i = 0 ; i < num; i++) + REG_SET(CM_GAMCOR_LUT_DATA, 0, CM_GAMCOR_LUT_DATA, rgb[i].green_reg); + + REG_SET(CM_GAMCOR_LUT_DATA, 0, CM_GAMCOR_LUT_DATA, last_base_value_green); + + REG_SET(CM_GAMCOR_LUT_INDEX, 0, CM_GAMCOR_LUT_INDEX, 0); + + REG_UPDATE(CM_GAMCOR_LUT_CONTROL, + CM_GAMCOR_LUT_WRITE_COLOR_MASK, 1); + for (i = 0 ; i < num; i++) + REG_SET(CM_GAMCOR_LUT_DATA, 0, CM_GAMCOR_LUT_DATA, rgb[i].blue_reg); + + REG_SET(CM_GAMCOR_LUT_DATA, 0, CM_GAMCOR_LUT_DATA, last_base_value_blue); + } +} + +static void dpp3_power_on_gamcor_lut( + struct dpp *dpp_base, + bool power_on) +{ + struct dcn3_dpp *dpp = TO_DCN30_DPP(dpp_base); + + if (dpp_base->ctx->dc->debug.enable_mem_low_power.bits.cm) { + if (power_on) { + REG_UPDATE(CM_MEM_PWR_CTRL, GAMCOR_MEM_PWR_FORCE, 0); + REG_WAIT(CM_MEM_PWR_STATUS, GAMCOR_MEM_PWR_STATE, 0, 1, 5); + } else { + dpp_base->ctx->dc->optimized_required = true; + dpp_base->deferred_reg_writes.bits.disable_gamcor = true; + } + } else + REG_SET(CM_MEM_PWR_CTRL, 0, + GAMCOR_MEM_PWR_DIS, power_on == true ? 0:1); +} + +void dpp3_program_cm_dealpha( + struct dpp *dpp_base, + uint32_t enable, uint32_t additive_blending) +{ + struct dcn3_dpp *dpp = TO_DCN30_DPP(dpp_base); + + REG_SET_2(CM_DEALPHA, 0, + CM_DEALPHA_EN, enable, + CM_DEALPHA_ABLND, additive_blending); +} + +void dpp3_program_cm_bias( + struct dpp *dpp_base, + struct CM_bias_params *bias_params) +{ + struct dcn3_dpp *dpp = TO_DCN30_DPP(dpp_base); + + REG_SET(CM_BIAS_CR_R, 0, CM_BIAS_CR_R, bias_params->cm_bias_cr_r); + REG_SET_2(CM_BIAS_Y_G_CB_B, 0, + CM_BIAS_Y_G, bias_params->cm_bias_y_g, + CM_BIAS_CB_B, bias_params->cm_bias_cb_b); +} + +static void dpp3_gamcor_reg_field( + struct dcn3_dpp *dpp, + struct dcn3_xfer_func_reg *reg) +{ + + reg->shifts.field_region_start_base = dpp->tf_shift->CM_GAMCOR_RAMA_EXP_REGION_START_BASE_B; + reg->masks.field_region_start_base = dpp->tf_mask->CM_GAMCOR_RAMA_EXP_REGION_START_BASE_B; + reg->shifts.field_offset = dpp->tf_shift->CM_GAMCOR_RAMA_OFFSET_B; + reg->masks.field_offset = dpp->tf_mask->CM_GAMCOR_RAMA_OFFSET_B; + + reg->shifts.exp_region0_lut_offset = dpp->tf_shift->CM_GAMCOR_RAMA_EXP_REGION0_LUT_OFFSET; + reg->masks.exp_region0_lut_offset = dpp->tf_mask->CM_GAMCOR_RAMA_EXP_REGION0_LUT_OFFSET; + reg->shifts.exp_region0_num_segments = dpp->tf_shift->CM_GAMCOR_RAMA_EXP_REGION0_NUM_SEGMENTS; + reg->masks.exp_region0_num_segments = dpp->tf_mask->CM_GAMCOR_RAMA_EXP_REGION0_NUM_SEGMENTS; + reg->shifts.exp_region1_lut_offset = dpp->tf_shift->CM_GAMCOR_RAMA_EXP_REGION1_LUT_OFFSET; + reg->masks.exp_region1_lut_offset = dpp->tf_mask->CM_GAMCOR_RAMA_EXP_REGION1_LUT_OFFSET; + reg->shifts.exp_region1_num_segments = dpp->tf_shift->CM_GAMCOR_RAMA_EXP_REGION1_NUM_SEGMENTS; + reg->masks.exp_region1_num_segments = dpp->tf_mask->CM_GAMCOR_RAMA_EXP_REGION1_NUM_SEGMENTS; + + reg->shifts.field_region_end = dpp->tf_shift->CM_GAMCOR_RAMA_EXP_REGION_END_B; + reg->masks.field_region_end = dpp->tf_mask->CM_GAMCOR_RAMA_EXP_REGION_END_B; + reg->shifts.field_region_end_slope = dpp->tf_shift->CM_GAMCOR_RAMA_EXP_REGION_END_SLOPE_B; + reg->masks.field_region_end_slope = dpp->tf_mask->CM_GAMCOR_RAMA_EXP_REGION_END_SLOPE_B; + reg->shifts.field_region_end_base = dpp->tf_shift->CM_GAMCOR_RAMA_EXP_REGION_END_BASE_B; + reg->masks.field_region_end_base = dpp->tf_mask->CM_GAMCOR_RAMA_EXP_REGION_END_BASE_B; + reg->shifts.field_region_linear_slope = dpp->tf_shift->CM_GAMCOR_RAMA_EXP_REGION_START_SLOPE_B; + reg->masks.field_region_linear_slope = dpp->tf_mask->CM_GAMCOR_RAMA_EXP_REGION_START_SLOPE_B; + reg->shifts.exp_region_start = dpp->tf_shift->CM_GAMCOR_RAMA_EXP_REGION_START_B; + reg->masks.exp_region_start = dpp->tf_mask->CM_GAMCOR_RAMA_EXP_REGION_START_B; + reg->shifts.exp_resion_start_segment = dpp->tf_shift->CM_GAMCOR_RAMA_EXP_REGION_START_SEGMENT_B; + reg->masks.exp_resion_start_segment = dpp->tf_mask->CM_GAMCOR_RAMA_EXP_REGION_START_SEGMENT_B; +} + +static void dpp3_configure_gamcor_lut( + struct dpp *dpp_base, + bool is_ram_a) +{ + struct dcn3_dpp *dpp = TO_DCN30_DPP(dpp_base); + + REG_UPDATE(CM_GAMCOR_LUT_CONTROL, + CM_GAMCOR_LUT_WRITE_COLOR_MASK, 7); + REG_UPDATE(CM_GAMCOR_LUT_CONTROL, + CM_GAMCOR_LUT_HOST_SEL, is_ram_a == true ? 0:1); + REG_SET(CM_GAMCOR_LUT_INDEX, 0, CM_GAMCOR_LUT_INDEX, 0); +} + + +bool dpp3_program_gamcor_lut( + struct dpp *dpp_base, const struct pwl_params *params) +{ + enum dc_lut_mode current_mode; + enum dc_lut_mode next_mode; + struct dcn3_dpp *dpp = TO_DCN30_DPP(dpp_base); + struct dcn3_xfer_func_reg gam_regs; + + dpp3_enable_cm_block(dpp_base); + + if (params == NULL) { //bypass if we have no pwl data + REG_SET(CM_GAMCOR_CONTROL, 0, CM_GAMCOR_MODE, 0); + if (dpp_base->ctx->dc->debug.enable_mem_low_power.bits.cm) + dpp3_power_on_gamcor_lut(dpp_base, false); + return false; + } + dpp3_power_on_gamcor_lut(dpp_base, true); + REG_SET(CM_GAMCOR_CONTROL, 0, CM_GAMCOR_MODE, 2); + + current_mode = dpp30_get_gamcor_current(dpp_base); + if (current_mode == LUT_BYPASS || current_mode == LUT_RAM_A) + next_mode = LUT_RAM_B; + else + next_mode = LUT_RAM_A; + + dpp3_power_on_gamcor_lut(dpp_base, true); + dpp3_configure_gamcor_lut(dpp_base, next_mode == LUT_RAM_A); + + if (next_mode == LUT_RAM_B) { + gam_regs.start_cntl_b = REG(CM_GAMCOR_RAMB_START_CNTL_B); + gam_regs.start_cntl_g = REG(CM_GAMCOR_RAMB_START_CNTL_G); + gam_regs.start_cntl_r = REG(CM_GAMCOR_RAMB_START_CNTL_R); + gam_regs.start_slope_cntl_b = REG(CM_GAMCOR_RAMB_START_SLOPE_CNTL_B); + gam_regs.start_slope_cntl_g = REG(CM_GAMCOR_RAMB_START_SLOPE_CNTL_G); + gam_regs.start_slope_cntl_r = REG(CM_GAMCOR_RAMB_START_SLOPE_CNTL_R); + gam_regs.start_end_cntl1_b = REG(CM_GAMCOR_RAMB_END_CNTL1_B); + gam_regs.start_end_cntl2_b = REG(CM_GAMCOR_RAMB_END_CNTL2_B); + gam_regs.start_end_cntl1_g = REG(CM_GAMCOR_RAMB_END_CNTL1_G); + gam_regs.start_end_cntl2_g = REG(CM_GAMCOR_RAMB_END_CNTL2_G); + gam_regs.start_end_cntl1_r = REG(CM_GAMCOR_RAMB_END_CNTL1_R); + gam_regs.start_end_cntl2_r = REG(CM_GAMCOR_RAMB_END_CNTL2_R); + gam_regs.region_start = REG(CM_GAMCOR_RAMB_REGION_0_1); + gam_regs.region_end = REG(CM_GAMCOR_RAMB_REGION_32_33); + //New registers in DCN3AG/DCN GAMCOR block + gam_regs.offset_b = REG(CM_GAMCOR_RAMB_OFFSET_B); + gam_regs.offset_g = REG(CM_GAMCOR_RAMB_OFFSET_G); + gam_regs.offset_r = REG(CM_GAMCOR_RAMB_OFFSET_R); + gam_regs.start_base_cntl_b = REG(CM_GAMCOR_RAMB_START_BASE_CNTL_B); + gam_regs.start_base_cntl_g = REG(CM_GAMCOR_RAMB_START_BASE_CNTL_G); + gam_regs.start_base_cntl_r = REG(CM_GAMCOR_RAMB_START_BASE_CNTL_R); + } else { + gam_regs.start_cntl_b = REG(CM_GAMCOR_RAMA_START_CNTL_B); + gam_regs.start_cntl_g = REG(CM_GAMCOR_RAMA_START_CNTL_G); + gam_regs.start_cntl_r = REG(CM_GAMCOR_RAMA_START_CNTL_R); + gam_regs.start_slope_cntl_b = REG(CM_GAMCOR_RAMA_START_SLOPE_CNTL_B); + gam_regs.start_slope_cntl_g = REG(CM_GAMCOR_RAMA_START_SLOPE_CNTL_G); + gam_regs.start_slope_cntl_r = REG(CM_GAMCOR_RAMA_START_SLOPE_CNTL_R); + gam_regs.start_end_cntl1_b = REG(CM_GAMCOR_RAMA_END_CNTL1_B); + gam_regs.start_end_cntl2_b = REG(CM_GAMCOR_RAMA_END_CNTL2_B); + gam_regs.start_end_cntl1_g = REG(CM_GAMCOR_RAMA_END_CNTL1_G); + gam_regs.start_end_cntl2_g = REG(CM_GAMCOR_RAMA_END_CNTL2_G); + gam_regs.start_end_cntl1_r = REG(CM_GAMCOR_RAMA_END_CNTL1_R); + gam_regs.start_end_cntl2_r = REG(CM_GAMCOR_RAMA_END_CNTL2_R); + gam_regs.region_start = REG(CM_GAMCOR_RAMA_REGION_0_1); + gam_regs.region_end = REG(CM_GAMCOR_RAMA_REGION_32_33); + //New registers in DCN3AG/DCN GAMCOR block + gam_regs.offset_b = REG(CM_GAMCOR_RAMA_OFFSET_B); + gam_regs.offset_g = REG(CM_GAMCOR_RAMA_OFFSET_G); + gam_regs.offset_r = REG(CM_GAMCOR_RAMA_OFFSET_R); + gam_regs.start_base_cntl_b = REG(CM_GAMCOR_RAMA_START_BASE_CNTL_B); + gam_regs.start_base_cntl_g = REG(CM_GAMCOR_RAMA_START_BASE_CNTL_G); + gam_regs.start_base_cntl_r = REG(CM_GAMCOR_RAMA_START_BASE_CNTL_R); + } + + //get register fields + dpp3_gamcor_reg_field(dpp, &gam_regs); + + //program register set for LUTA/LUTB + cm_helper_program_gamcor_xfer_func(dpp_base->ctx, params, &gam_regs); + + dpp3_program_gammcor_lut(dpp_base, params->rgb_resulted, params->hw_points_num, + next_mode == LUT_RAM_A); + + //select Gamma LUT to use for next frame + REG_UPDATE(CM_GAMCOR_CONTROL, CM_GAMCOR_SELECT, next_mode == LUT_RAM_A ? 0:1); + + return true; +} + +void dpp3_set_hdr_multiplier( + struct dpp *dpp_base, + uint32_t multiplier) +{ + struct dcn3_dpp *dpp = TO_DCN30_DPP(dpp_base); + + REG_UPDATE(CM_HDR_MULT_COEF, CM_HDR_MULT_COEF, multiplier); +} + + +static void program_gamut_remap( + struct dcn3_dpp *dpp, + const uint16_t *regval, + int select) +{ + uint16_t selection = 0; + struct color_matrices_reg gam_regs; + + if (regval == NULL || select == GAMUT_REMAP_BYPASS) { + REG_SET(CM_GAMUT_REMAP_CONTROL, 0, + CM_GAMUT_REMAP_MODE, 0); + return; + } + switch (select) { + case GAMUT_REMAP_COEFF: + selection = 1; + break; + /*this corresponds to GAMUT_REMAP coefficients set B + *we don't have common coefficient sets in dcn3ag/dcn3 + */ + case GAMUT_REMAP_COMA_COEFF: + selection = 2; + break; + default: + break; + } + + gam_regs.shifts.csc_c11 = dpp->tf_shift->CM_GAMUT_REMAP_C11; + gam_regs.masks.csc_c11 = dpp->tf_mask->CM_GAMUT_REMAP_C11; + gam_regs.shifts.csc_c12 = dpp->tf_shift->CM_GAMUT_REMAP_C12; + gam_regs.masks.csc_c12 = dpp->tf_mask->CM_GAMUT_REMAP_C12; + + + if (select == GAMUT_REMAP_COEFF) { + gam_regs.csc_c11_c12 = REG(CM_GAMUT_REMAP_C11_C12); + gam_regs.csc_c33_c34 = REG(CM_GAMUT_REMAP_C33_C34); + + cm_helper_program_color_matrices( + dpp->base.ctx, + regval, + &gam_regs); + + } else if (select == GAMUT_REMAP_COMA_COEFF) { + + gam_regs.csc_c11_c12 = REG(CM_GAMUT_REMAP_B_C11_C12); + gam_regs.csc_c33_c34 = REG(CM_GAMUT_REMAP_B_C33_C34); + + cm_helper_program_color_matrices( + dpp->base.ctx, + regval, + &gam_regs); + + } + //select coefficient set to use + REG_SET( + CM_GAMUT_REMAP_CONTROL, 0, + CM_GAMUT_REMAP_MODE, selection); +} + +void dpp3_cm_set_gamut_remap( + struct dpp *dpp_base, + const struct dpp_grph_csc_adjustment *adjust) +{ + struct dcn3_dpp *dpp = TO_DCN30_DPP(dpp_base); + int i = 0; + int gamut_mode; + + if (adjust->gamut_adjust_type != GRAPHICS_GAMUT_ADJUST_TYPE_SW) + /* Bypass if type is bypass or hw */ + program_gamut_remap(dpp, NULL, GAMUT_REMAP_BYPASS); + else { + struct fixed31_32 arr_matrix[12]; + uint16_t arr_reg_val[12]; + + for (i = 0; i < 12; i++) + arr_matrix[i] = adjust->temperature_matrix[i]; + + convert_float_matrix( + arr_reg_val, arr_matrix, 12); + + //current coefficient set in use + REG_GET(CM_GAMUT_REMAP_CONTROL, CM_GAMUT_REMAP_MODE_CURRENT, &gamut_mode); + + if (gamut_mode == 0) + gamut_mode = 1; //use coefficient set A + else if (gamut_mode == 1) + gamut_mode = 2; + else + gamut_mode = 1; + + //follow dcn2 approach for now - using only coefficient set A + program_gamut_remap(dpp, arr_reg_val, gamut_mode); + } +} diff --git a/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_dwb.c b/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_dwb.c new file mode 100644 index 000000000..f14f69616 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_dwb.c @@ -0,0 +1,264 @@ +/* + * Copyright 2020 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 "reg_helper.h" +#include "resource.h" +#include "dwb.h" +#include "dcn30_dwb.h" + + +#define REG(reg)\ + dwbc30->dwbc_regs->reg + +#define CTX \ + dwbc30->base.ctx + +#undef FN +#define FN(reg_name, field_name) \ + dwbc30->dwbc_shift->field_name, dwbc30->dwbc_mask->field_name + +#define DC_LOGGER \ + dwbc30->base.ctx->logger + +static bool dwb3_get_caps(struct dwbc *dwbc, struct dwb_caps *caps) +{ + if (caps) { + caps->adapter_id = 0; /* we only support 1 adapter currently */ + caps->hw_version = DCN_VERSION_3_0; + caps->num_pipes = 2; + memset(&caps->reserved, 0, sizeof(caps->reserved)); + memset(&caps->reserved2, 0, sizeof(caps->reserved2)); + caps->sw_version = dwb_ver_2_0; + caps->caps.support_dwb = true; + caps->caps.support_ogam = true; + caps->caps.support_wbscl = true; + caps->caps.support_ocsc = false; + caps->caps.support_stereo = true; + return true; + } else { + return false; + } +} + +void dwb3_config_fc(struct dwbc *dwbc, struct dc_dwb_params *params) +{ + struct dcn30_dwbc *dwbc30 = TO_DCN30_DWBC(dwbc); + + /* Set DWB source size */ + REG_UPDATE_2(FC_SOURCE_SIZE, FC_SOURCE_WIDTH, params->cnv_params.src_width, + FC_SOURCE_HEIGHT, params->cnv_params.src_height); + + /* source size is not equal the source size, then enable cropping. */ + if (params->cnv_params.crop_en) { + REG_UPDATE(FC_MODE_CTRL, FC_WINDOW_CROP_EN, 1); + REG_UPDATE(FC_WINDOW_START, FC_WINDOW_START_X, params->cnv_params.crop_x); + REG_UPDATE(FC_WINDOW_START, FC_WINDOW_START_Y, params->cnv_params.crop_y); + REG_UPDATE(FC_WINDOW_SIZE, FC_WINDOW_WIDTH, params->cnv_params.crop_width); + REG_UPDATE(FC_WINDOW_SIZE, FC_WINDOW_HEIGHT, params->cnv_params.crop_height); + } else { + REG_UPDATE(FC_MODE_CTRL, FC_WINDOW_CROP_EN, 0); + } + + /* Set CAPTURE_RATE */ + REG_UPDATE(FC_MODE_CTRL, FC_FRAME_CAPTURE_RATE, params->capture_rate); + + dwb3_set_stereo(dwbc, ¶ms->stereo_params); +} + +bool dwb3_enable(struct dwbc *dwbc, struct dc_dwb_params *params) +{ + struct dcn30_dwbc *dwbc30 = TO_DCN30_DWBC(dwbc); + DC_LOG_DWB("%s dwb3_enabled at inst = %d", __func__, dwbc->inst); + + /* Set WB_ENABLE (not double buffered; capture not enabled) */ + REG_UPDATE(DWB_ENABLE_CLK_CTRL, DWB_ENABLE, 1); + + /* Set FC parameters */ + dwb3_config_fc(dwbc, params); + + /* Program color processing unit */ + dwb3_program_hdr_mult(dwbc, params); + dwb3_set_gamut_remap(dwbc, params); + dwb3_ogam_set_input_transfer_func(dwbc, params->out_transfer_func); + + /* Program output denorm */ + dwb3_set_denorm(dwbc, params); + + /* Enable DWB capture enable (double buffered) */ + REG_UPDATE(FC_MODE_CTRL, FC_FRAME_CAPTURE_EN, DWB_FRAME_CAPTURE_ENABLE); + + /* First pixel count */ + REG_UPDATE(FC_FLOW_CTRL, FC_FIRST_PIXEL_DELAY_COUNT, 96); + + return true; +} + +bool dwb3_disable(struct dwbc *dwbc) +{ + struct dcn30_dwbc *dwbc30 = TO_DCN30_DWBC(dwbc); + + /* disable FC */ + REG_UPDATE(FC_MODE_CTRL, FC_FRAME_CAPTURE_EN, DWB_FRAME_CAPTURE_DISABLE); + + /* disable WB */ + REG_UPDATE(DWB_ENABLE_CLK_CTRL, DWB_ENABLE, 0); + + DC_LOG_DWB("%s dwb3_disabled at inst = %d", __func__, dwbc->inst); + return true; +} + +bool dwb3_update(struct dwbc *dwbc, struct dc_dwb_params *params) +{ + struct dcn30_dwbc *dwbc30 = TO_DCN30_DWBC(dwbc); + unsigned int pre_locked; + + /* + * Check if the caller has already locked DWB registers. + * If so: assume the caller will unlock, so don't touch the lock. + * If not: lock them for this update, then unlock after the + * update is complete. + */ + REG_GET(DWB_UPDATE_CTRL, DWB_UPDATE_LOCK, &pre_locked); + DC_LOG_DWB("%s dwb update, inst = %d", __func__, dwbc->inst); + + if (pre_locked == 0) { + /* Lock DWB registers */ + REG_UPDATE(DWB_UPDATE_CTRL, DWB_UPDATE_LOCK, 1); + } + + /* Set FC parameters */ + dwb3_config_fc(dwbc, params); + + /* Program color processing unit */ + dwb3_program_hdr_mult(dwbc, params); + dwb3_set_gamut_remap(dwbc, params); + dwb3_ogam_set_input_transfer_func(dwbc, params->out_transfer_func); + + /* Program output denorm */ + dwb3_set_denorm(dwbc, params); + + if (pre_locked == 0) { + /* Unlock DWB registers */ + REG_UPDATE(DWB_UPDATE_CTRL, DWB_UPDATE_LOCK, 0); + } + + return true; +} + +bool dwb3_is_enabled(struct dwbc *dwbc) +{ + struct dcn30_dwbc *dwbc30 = TO_DCN30_DWBC(dwbc); + unsigned int dwb_enabled = 0; + unsigned int fc_frame_capture_en = 0; + + REG_GET(DWB_ENABLE_CLK_CTRL, DWB_ENABLE, &dwb_enabled); + REG_GET(FC_MODE_CTRL, FC_FRAME_CAPTURE_EN, &fc_frame_capture_en); + + return ((dwb_enabled != 0) && (fc_frame_capture_en != 0)); +} + +void dwb3_set_stereo(struct dwbc *dwbc, + struct dwb_stereo_params *stereo_params) +{ + struct dcn30_dwbc *dwbc30 = TO_DCN30_DWBC(dwbc); + + if (stereo_params->stereo_enabled) { + REG_UPDATE(FC_MODE_CTRL, FC_EYE_SELECTION, stereo_params->stereo_eye_select); + REG_UPDATE(FC_MODE_CTRL, FC_STEREO_EYE_POLARITY, stereo_params->stereo_polarity); + DC_LOG_DWB("%s dwb stereo enabled", __func__); + } else { + REG_UPDATE(FC_MODE_CTRL, FC_EYE_SELECTION, 0); + DC_LOG_DWB("%s dwb stereo disabled", __func__); + } +} + +void dwb3_set_new_content(struct dwbc *dwbc, + bool is_new_content) +{ + struct dcn30_dwbc *dwbc30 = TO_DCN30_DWBC(dwbc); + + REG_UPDATE(FC_MODE_CTRL, FC_NEW_CONTENT, is_new_content); +} + +void dwb3_set_denorm(struct dwbc *dwbc, struct dc_dwb_params *params) +{ + struct dcn30_dwbc *dwbc30 = TO_DCN30_DWBC(dwbc); + + /* Set output format*/ + REG_UPDATE(DWB_OUT_CTRL, OUT_FORMAT, params->cnv_params.fc_out_format); + + /* Set output denorm */ + if (params->cnv_params.fc_out_format == DWB_OUT_FORMAT_32BPP_ARGB || + params->cnv_params.fc_out_format == DWB_OUT_FORMAT_32BPP_RGBA) { + REG_UPDATE(DWB_OUT_CTRL, OUT_DENORM, params->cnv_params.out_denorm_mode); + REG_UPDATE(DWB_OUT_CTRL, OUT_MAX, params->cnv_params.out_max_pix_val); + REG_UPDATE(DWB_OUT_CTRL, OUT_MIN, params->cnv_params.out_min_pix_val); + } +} + + +const struct dwbc_funcs dcn30_dwbc_funcs = { + .get_caps = dwb3_get_caps, + .enable = dwb3_enable, + .disable = dwb3_disable, + .update = dwb3_update, + .is_enabled = dwb3_is_enabled, + .set_stereo = dwb3_set_stereo, + .set_new_content = dwb3_set_new_content, + .dwb_program_output_csc = NULL, + .dwb_ogam_set_input_transfer_func = dwb3_ogam_set_input_transfer_func, //TODO: rename + .dwb_set_scaler = NULL, +}; + +void dcn30_dwbc_construct(struct dcn30_dwbc *dwbc30, + struct dc_context *ctx, + const struct dcn30_dwbc_registers *dwbc_regs, + const struct dcn30_dwbc_shift *dwbc_shift, + const struct dcn30_dwbc_mask *dwbc_mask, + int inst) +{ + dwbc30->base.ctx = ctx; + + dwbc30->base.inst = inst; + dwbc30->base.funcs = &dcn30_dwbc_funcs; + + dwbc30->dwbc_regs = dwbc_regs; + dwbc30->dwbc_shift = dwbc_shift; + dwbc30->dwbc_mask = dwbc_mask; +} + +void dwb3_set_host_read_rate_control(struct dwbc *dwbc, bool host_read_delay) +{ + struct dcn30_dwbc *dwbc30 = TO_DCN30_DWBC(dwbc); + + /* + * Set maximum delay of host read access to DWBSCL LUT or OGAM LUT if there are no + * idle cycles in HW pipeline (in number of clock cycles times 4) + */ + REG_UPDATE(DWB_HOST_READ_CONTROL, DWB_HOST_READ_RATE_CONTROL, host_read_delay); + + DC_LOG_DWB("%s dwb3_rate_control at inst = %d", __func__, dwbc->inst); +} diff --git a/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_dwb.h b/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_dwb.h new file mode 100644 index 000000000..1010930cf --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_dwb.h @@ -0,0 +1,923 @@ +/* Copyright 2020 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_DWBC_DCN30_H__ +#define __DC_DWBC_DCN30_H__ + +#define TO_DCN30_DWBC(dwbc_base) \ + container_of(dwbc_base, struct dcn30_dwbc, base) + +/* DCN */ +#define BASE_INNER(seg) \ + DCE_BASE__INST0_SEG ## seg + +#define BASE(seg) \ + BASE_INNER(seg) + +#define SF_DWB(reg_name, block, id, field_name, post_fix)\ + .field_name = block ## id ## _ ## reg_name ## __ ## field_name ## post_fix + + /* set field name */ +#define SF_DWB2(reg_name, block, id, field_name, post_fix)\ + .field_name = reg_name ## __ ## field_name ## post_fix + + +#define DWBC_COMMON_REG_LIST_DCN30(inst) \ + SR(DWB_ENABLE_CLK_CTRL),\ + SR(DWB_MEM_PWR_CTRL),\ + SR(FC_MODE_CTRL),\ + SR(FC_FLOW_CTRL),\ + SR(FC_WINDOW_START),\ + SR(FC_WINDOW_SIZE),\ + SR(FC_SOURCE_SIZE),\ + SR(DWB_UPDATE_CTRL),\ + SR(DWB_CRC_CTRL),\ + SR(DWB_CRC_MASK_R_G),\ + SR(DWB_CRC_MASK_B_A),\ + SR(DWB_CRC_VAL_R_G),\ + SR(DWB_CRC_VAL_B_A),\ + SR(DWB_OUT_CTRL),\ + SR(DWB_MMHUBBUB_BACKPRESSURE_CNT_EN),\ + SR(DWB_MMHUBBUB_BACKPRESSURE_CNT),\ + SR(DWB_HOST_READ_CONTROL),\ + SR(DWB_SOFT_RESET),\ + SR(DWB_HDR_MULT_COEF),\ + SR(DWB_GAMUT_REMAP_MODE),\ + SR(DWB_GAMUT_REMAP_COEF_FORMAT),\ + SR(DWB_GAMUT_REMAPA_C11_C12),\ + SR(DWB_GAMUT_REMAPA_C13_C14),\ + SR(DWB_GAMUT_REMAPA_C21_C22),\ + SR(DWB_GAMUT_REMAPA_C23_C24),\ + SR(DWB_GAMUT_REMAPA_C31_C32),\ + SR(DWB_GAMUT_REMAPA_C33_C34),\ + SR(DWB_GAMUT_REMAPB_C11_C12),\ + SR(DWB_GAMUT_REMAPB_C13_C14),\ + SR(DWB_GAMUT_REMAPB_C21_C22),\ + SR(DWB_GAMUT_REMAPB_C23_C24),\ + SR(DWB_GAMUT_REMAPB_C31_C32),\ + SR(DWB_GAMUT_REMAPB_C33_C34),\ + SR(DWB_OGAM_CONTROL),\ + SR(DWB_OGAM_LUT_INDEX),\ + SR(DWB_OGAM_LUT_DATA),\ + SR(DWB_OGAM_LUT_CONTROL),\ + SR(DWB_OGAM_RAMA_START_CNTL_B),\ + SR(DWB_OGAM_RAMA_START_CNTL_G),\ + SR(DWB_OGAM_RAMA_START_CNTL_R),\ + SR(DWB_OGAM_RAMA_START_BASE_CNTL_B),\ + SR(DWB_OGAM_RAMA_START_SLOPE_CNTL_B),\ + SR(DWB_OGAM_RAMA_START_BASE_CNTL_G),\ + SR(DWB_OGAM_RAMA_START_SLOPE_CNTL_G),\ + SR(DWB_OGAM_RAMA_START_BASE_CNTL_R),\ + SR(DWB_OGAM_RAMA_START_SLOPE_CNTL_R),\ + SR(DWB_OGAM_RAMA_END_CNTL1_B),\ + SR(DWB_OGAM_RAMA_END_CNTL2_B),\ + SR(DWB_OGAM_RAMA_END_CNTL1_G),\ + SR(DWB_OGAM_RAMA_END_CNTL2_G),\ + SR(DWB_OGAM_RAMA_END_CNTL1_R),\ + SR(DWB_OGAM_RAMA_END_CNTL2_R),\ + SR(DWB_OGAM_RAMA_OFFSET_B),\ + SR(DWB_OGAM_RAMA_OFFSET_G),\ + SR(DWB_OGAM_RAMA_OFFSET_R),\ + SR(DWB_OGAM_RAMA_REGION_0_1),\ + SR(DWB_OGAM_RAMA_REGION_2_3),\ + SR(DWB_OGAM_RAMA_REGION_4_5),\ + SR(DWB_OGAM_RAMA_REGION_6_7),\ + SR(DWB_OGAM_RAMA_REGION_8_9),\ + SR(DWB_OGAM_RAMA_REGION_10_11),\ + SR(DWB_OGAM_RAMA_REGION_12_13),\ + SR(DWB_OGAM_RAMA_REGION_14_15),\ + SR(DWB_OGAM_RAMA_REGION_16_17),\ + SR(DWB_OGAM_RAMA_REGION_18_19),\ + SR(DWB_OGAM_RAMA_REGION_20_21),\ + SR(DWB_OGAM_RAMA_REGION_22_23),\ + SR(DWB_OGAM_RAMA_REGION_24_25),\ + SR(DWB_OGAM_RAMA_REGION_26_27),\ + SR(DWB_OGAM_RAMA_REGION_28_29),\ + SR(DWB_OGAM_RAMA_REGION_30_31),\ + SR(DWB_OGAM_RAMA_REGION_32_33),\ + SR(DWB_OGAM_RAMB_START_CNTL_B),\ + SR(DWB_OGAM_RAMB_START_CNTL_G),\ + SR(DWB_OGAM_RAMB_START_CNTL_R),\ + SR(DWB_OGAM_RAMB_START_BASE_CNTL_B),\ + SR(DWB_OGAM_RAMB_START_SLOPE_CNTL_B),\ + SR(DWB_OGAM_RAMB_START_BASE_CNTL_G),\ + SR(DWB_OGAM_RAMB_START_SLOPE_CNTL_G),\ + SR(DWB_OGAM_RAMB_START_BASE_CNTL_R),\ + SR(DWB_OGAM_RAMB_START_SLOPE_CNTL_R),\ + SR(DWB_OGAM_RAMB_END_CNTL1_B),\ + SR(DWB_OGAM_RAMB_END_CNTL2_B),\ + SR(DWB_OGAM_RAMB_END_CNTL1_G),\ + SR(DWB_OGAM_RAMB_END_CNTL2_G),\ + SR(DWB_OGAM_RAMB_END_CNTL1_R),\ + SR(DWB_OGAM_RAMB_END_CNTL2_R),\ + SR(DWB_OGAM_RAMB_OFFSET_B),\ + SR(DWB_OGAM_RAMB_OFFSET_G),\ + SR(DWB_OGAM_RAMB_OFFSET_R),\ + SR(DWB_OGAM_RAMB_REGION_0_1),\ + SR(DWB_OGAM_RAMB_REGION_2_3),\ + SR(DWB_OGAM_RAMB_REGION_4_5),\ + SR(DWB_OGAM_RAMB_REGION_6_7),\ + SR(DWB_OGAM_RAMB_REGION_8_9),\ + SR(DWB_OGAM_RAMB_REGION_10_11),\ + SR(DWB_OGAM_RAMB_REGION_12_13),\ + SR(DWB_OGAM_RAMB_REGION_14_15),\ + SR(DWB_OGAM_RAMB_REGION_16_17),\ + SR(DWB_OGAM_RAMB_REGION_18_19),\ + SR(DWB_OGAM_RAMB_REGION_20_21),\ + SR(DWB_OGAM_RAMB_REGION_22_23),\ + SR(DWB_OGAM_RAMB_REGION_24_25),\ + SR(DWB_OGAM_RAMB_REGION_26_27),\ + SR(DWB_OGAM_RAMB_REGION_28_29),\ + SR(DWB_OGAM_RAMB_REGION_30_31),\ + SR(DWB_OGAM_RAMB_REGION_32_33) + + +#define DWBC_COMMON_MASK_SH_LIST_DCN30(mask_sh) \ + SF_DWB2(DWB_ENABLE_CLK_CTRL, DWB_TOP, 0, DWB_ENABLE, mask_sh),\ + SF_DWB2(DWB_ENABLE_CLK_CTRL, DWB_TOP, 0, DISPCLK_R_DWB_GATE_DIS, mask_sh),\ + SF_DWB2(DWB_ENABLE_CLK_CTRL, DWB_TOP, 0, DISPCLK_G_DWB_GATE_DIS, mask_sh),\ + SF_DWB2(DWB_ENABLE_CLK_CTRL, DWB_TOP, 0, DWB_TEST_CLK_SEL, mask_sh),\ + SF_DWB2(DWB_MEM_PWR_CTRL, DWB_TOP, 0, DWB_OGAM_LUT_MEM_PWR_FORCE, mask_sh),\ + SF_DWB2(DWB_MEM_PWR_CTRL, DWB_TOP, 0, DWB_OGAM_LUT_MEM_PWR_DIS, mask_sh),\ + SF_DWB2(DWB_MEM_PWR_CTRL, DWB_TOP, 0, DWB_OGAM_LUT_MEM_PWR_STATE, mask_sh),\ + SF_DWB2(FC_MODE_CTRL, DWB_TOP, 0, FC_FRAME_CAPTURE_EN, mask_sh),\ + SF_DWB2(FC_MODE_CTRL, DWB_TOP, 0, FC_FRAME_CAPTURE_RATE, mask_sh),\ + SF_DWB2(FC_MODE_CTRL, DWB_TOP, 0, FC_WINDOW_CROP_EN, mask_sh),\ + SF_DWB2(FC_MODE_CTRL, DWB_TOP, 0, FC_EYE_SELECTION, mask_sh),\ + SF_DWB2(FC_MODE_CTRL, DWB_TOP, 0, FC_STEREO_EYE_POLARITY, mask_sh),\ + SF_DWB2(FC_MODE_CTRL, DWB_TOP, 0, FC_NEW_CONTENT, mask_sh),\ + SF_DWB2(FC_MODE_CTRL, DWB_TOP, 0, FC_FRAME_CAPTURE_EN_CURRENT, mask_sh),\ + SF_DWB2(FC_FLOW_CTRL, DWB_TOP, 0, FC_FIRST_PIXEL_DELAY_COUNT, mask_sh),\ + SF_DWB2(FC_WINDOW_START, DWB_TOP, 0, FC_WINDOW_START_X, mask_sh),\ + SF_DWB2(FC_WINDOW_START, DWB_TOP, 0, FC_WINDOW_START_Y, mask_sh),\ + SF_DWB2(FC_WINDOW_SIZE, DWB_TOP, 0, FC_WINDOW_WIDTH, mask_sh),\ + SF_DWB2(FC_WINDOW_SIZE, DWB_TOP, 0, FC_WINDOW_HEIGHT, mask_sh),\ + SF_DWB2(FC_SOURCE_SIZE, DWB_TOP, 0, FC_SOURCE_WIDTH, mask_sh),\ + SF_DWB2(FC_SOURCE_SIZE, DWB_TOP, 0, FC_SOURCE_HEIGHT, mask_sh),\ + SF_DWB2(DWB_UPDATE_CTRL, DWB_TOP, 0, DWB_UPDATE_LOCK, mask_sh),\ + SF_DWB2(DWB_UPDATE_CTRL, DWB_TOP, 0, DWB_UPDATE_PENDING, mask_sh),\ + SF_DWB2(DWB_CRC_CTRL, DWB_TOP, 0, DWB_CRC_EN, mask_sh),\ + SF_DWB2(DWB_CRC_CTRL, DWB_TOP, 0, DWB_CRC_CONT_EN, mask_sh),\ + SF_DWB2(DWB_CRC_CTRL, DWB_TOP, 0, DWB_CRC_SRC_SEL, mask_sh),\ + SF_DWB2(DWB_CRC_MASK_R_G, DWB_TOP, 0, DWB_CRC_RED_MASK, mask_sh),\ + SF_DWB2(DWB_CRC_MASK_R_G, DWB_TOP, 0, DWB_CRC_GREEN_MASK, mask_sh),\ + SF_DWB2(DWB_CRC_MASK_B_A, DWB_TOP, 0, DWB_CRC_BLUE_MASK, mask_sh),\ + SF_DWB2(DWB_CRC_MASK_B_A, DWB_TOP, 0, DWB_CRC_A_MASK, mask_sh),\ + SF_DWB2(DWB_CRC_VAL_R_G, DWB_TOP, 0, DWB_CRC_SIG_RED, mask_sh),\ + SF_DWB2(DWB_CRC_VAL_R_G, DWB_TOP, 0, DWB_CRC_SIG_GREEN, mask_sh),\ + SF_DWB2(DWB_CRC_VAL_B_A, DWB_TOP, 0, DWB_CRC_SIG_BLUE, mask_sh),\ + SF_DWB2(DWB_CRC_VAL_B_A, DWB_TOP, 0, DWB_CRC_SIG_A, mask_sh),\ + SF_DWB2(DWB_OUT_CTRL, DWB_TOP, 0, OUT_FORMAT, mask_sh),\ + SF_DWB2(DWB_OUT_CTRL, DWB_TOP, 0, OUT_DENORM, mask_sh),\ + SF_DWB2(DWB_OUT_CTRL, DWB_TOP, 0, OUT_MAX, mask_sh),\ + SF_DWB2(DWB_OUT_CTRL, DWB_TOP, 0, OUT_MIN, mask_sh),\ + SF_DWB2(DWB_MMHUBBUB_BACKPRESSURE_CNT_EN, DWB_TOP, 0, DWB_MMHUBBUB_BACKPRESSURE_CNT_EN, mask_sh),\ + SF_DWB2(DWB_MMHUBBUB_BACKPRESSURE_CNT, DWB_TOP, 0, DWB_MMHUBBUB_MAX_BACKPRESSURE, mask_sh),\ + SF_DWB2(DWB_HOST_READ_CONTROL, DWB_TOP, 0, DWB_HOST_READ_RATE_CONTROL, mask_sh),\ + SF_DWB2(DWB_SOFT_RESET, DWB_TOP, 0, DWB_SOFT_RESET, mask_sh),\ + SF_DWB2(DWB_HDR_MULT_COEF, DWBCP, 0, DWB_HDR_MULT_COEF, mask_sh),\ + SF_DWB2(DWB_GAMUT_REMAP_MODE, DWBCP, 0, DWB_GAMUT_REMAP_MODE, mask_sh),\ + SF_DWB2(DWB_GAMUT_REMAP_MODE, DWBCP, 0, DWB_GAMUT_REMAP_MODE_CURRENT, mask_sh),\ + SF_DWB2(DWB_GAMUT_REMAP_COEF_FORMAT, DWBCP, 0, DWB_GAMUT_REMAP_COEF_FORMAT, mask_sh),\ + SF_DWB2(DWB_GAMUT_REMAPA_C11_C12, DWBCP, 0, DWB_GAMUT_REMAPA_C11, mask_sh),\ + SF_DWB2(DWB_GAMUT_REMAPA_C11_C12, DWBCP, 0, DWB_GAMUT_REMAPA_C12, mask_sh),\ + SF_DWB2(DWB_GAMUT_REMAPA_C13_C14, DWBCP, 0, DWB_GAMUT_REMAPA_C13, mask_sh),\ + SF_DWB2(DWB_GAMUT_REMAPA_C13_C14, DWBCP, 0, DWB_GAMUT_REMAPA_C14, mask_sh),\ + SF_DWB2(DWB_GAMUT_REMAPA_C21_C22, DWBCP, 0, DWB_GAMUT_REMAPA_C21, mask_sh),\ + SF_DWB2(DWB_GAMUT_REMAPA_C21_C22, DWBCP, 0, DWB_GAMUT_REMAPA_C22, mask_sh),\ + SF_DWB2(DWB_GAMUT_REMAPA_C23_C24, DWBCP, 0, DWB_GAMUT_REMAPA_C23, mask_sh),\ + SF_DWB2(DWB_GAMUT_REMAPA_C23_C24, DWBCP, 0, DWB_GAMUT_REMAPA_C24, mask_sh),\ + SF_DWB2(DWB_GAMUT_REMAPA_C31_C32, DWBCP, 0, DWB_GAMUT_REMAPA_C31, mask_sh),\ + SF_DWB2(DWB_GAMUT_REMAPA_C31_C32, DWBCP, 0, DWB_GAMUT_REMAPA_C32, mask_sh),\ + SF_DWB2(DWB_GAMUT_REMAPA_C33_C34, DWBCP, 0, DWB_GAMUT_REMAPA_C33, mask_sh),\ + SF_DWB2(DWB_GAMUT_REMAPA_C33_C34, DWBCP, 0, DWB_GAMUT_REMAPA_C34, mask_sh),\ + SF_DWB2(DWB_GAMUT_REMAPB_C11_C12, DWBCP, 0, DWB_GAMUT_REMAPB_C11, mask_sh),\ + SF_DWB2(DWB_GAMUT_REMAPB_C11_C12, DWBCP, 0, DWB_GAMUT_REMAPB_C12, mask_sh),\ + SF_DWB2(DWB_GAMUT_REMAPB_C13_C14, DWBCP, 0, DWB_GAMUT_REMAPB_C13, mask_sh),\ + SF_DWB2(DWB_GAMUT_REMAPB_C13_C14, DWBCP, 0, DWB_GAMUT_REMAPB_C14, mask_sh),\ + SF_DWB2(DWB_GAMUT_REMAPB_C21_C22, DWBCP, 0, DWB_GAMUT_REMAPB_C21, mask_sh),\ + SF_DWB2(DWB_GAMUT_REMAPB_C21_C22, DWBCP, 0, DWB_GAMUT_REMAPB_C22, mask_sh),\ + SF_DWB2(DWB_GAMUT_REMAPB_C23_C24, DWBCP, 0, DWB_GAMUT_REMAPB_C23, mask_sh),\ + SF_DWB2(DWB_GAMUT_REMAPB_C23_C24, DWBCP, 0, DWB_GAMUT_REMAPB_C24, mask_sh),\ + SF_DWB2(DWB_GAMUT_REMAPB_C31_C32, DWBCP, 0, DWB_GAMUT_REMAPB_C31, mask_sh),\ + SF_DWB2(DWB_GAMUT_REMAPB_C31_C32, DWBCP, 0, DWB_GAMUT_REMAPB_C32, mask_sh),\ + SF_DWB2(DWB_GAMUT_REMAPB_C33_C34, DWBCP, 0, DWB_GAMUT_REMAPB_C33, mask_sh),\ + SF_DWB2(DWB_GAMUT_REMAPB_C33_C34, DWBCP, 0, DWB_GAMUT_REMAPB_C34, mask_sh),\ + SF_DWB2(DWB_OGAM_CONTROL, DWBCP, 0, DWB_OGAM_MODE, mask_sh),\ + SF_DWB2(DWB_OGAM_CONTROL, DWBCP, 0, DWB_OGAM_SELECT, mask_sh),\ + SF_DWB2(DWB_OGAM_CONTROL, DWBCP, 0, DWB_OGAM_PWL_DISABLE, mask_sh),\ + SF_DWB2(DWB_OGAM_CONTROL, DWBCP, 0, DWB_OGAM_MODE_CURRENT, mask_sh),\ + SF_DWB2(DWB_OGAM_CONTROL, DWBCP, 0, DWB_OGAM_SELECT_CURRENT, mask_sh),\ + SF_DWB2(DWB_OGAM_LUT_INDEX, DWBCP, 0, DWB_OGAM_LUT_INDEX, mask_sh),\ + SF_DWB2(DWB_OGAM_LUT_DATA, DWBCP, 0, DWB_OGAM_LUT_DATA, mask_sh),\ + SF_DWB2(DWB_OGAM_LUT_CONTROL, DWBCP, 0, DWB_OGAM_LUT_WRITE_COLOR_MASK, mask_sh),\ + SF_DWB2(DWB_OGAM_LUT_CONTROL, DWBCP, 0, DWB_OGAM_LUT_READ_COLOR_SEL, mask_sh),\ + SF_DWB2(DWB_OGAM_LUT_CONTROL, DWBCP, 0, DWB_OGAM_LUT_READ_DBG, mask_sh),\ + SF_DWB2(DWB_OGAM_LUT_CONTROL, DWBCP, 0, DWB_OGAM_LUT_HOST_SEL, mask_sh),\ + SF_DWB2(DWB_OGAM_LUT_CONTROL, DWBCP, 0, DWB_OGAM_LUT_CONFIG_MODE, mask_sh),\ + SF_DWB2(DWB_OGAM_RAMA_START_CNTL_B, DWBCP, 0, DWB_OGAM_RAMA_EXP_REGION_START_B, mask_sh),\ + SF_DWB2(DWB_OGAM_RAMA_START_CNTL_B, DWBCP, 0, DWB_OGAM_RAMA_EXP_REGION_START_SEGMENT_B, mask_sh),\ + SF_DWB2(DWB_OGAM_RAMA_START_CNTL_G, DWBCP, 0, DWB_OGAM_RAMA_EXP_REGION_START_G, mask_sh),\ + SF_DWB2(DWB_OGAM_RAMA_START_CNTL_G, DWBCP, 0, DWB_OGAM_RAMA_EXP_REGION_START_SEGMENT_G, mask_sh),\ + SF_DWB2(DWB_OGAM_RAMA_START_CNTL_R, DWBCP, 0, DWB_OGAM_RAMA_EXP_REGION_START_R, mask_sh),\ + SF_DWB2(DWB_OGAM_RAMA_START_CNTL_R, DWBCP, 0, DWB_OGAM_RAMA_EXP_REGION_START_SEGMENT_R, mask_sh),\ + SF_DWB2(DWB_OGAM_RAMA_START_BASE_CNTL_B, DWBCP, 0, DWB_OGAM_RAMA_EXP_REGION_START_BASE_B, mask_sh),\ + SF_DWB2(DWB_OGAM_RAMA_START_SLOPE_CNTL_B, DWBCP, 0, DWB_OGAM_RAMA_EXP_REGION_START_SLOPE_B, mask_sh),\ + SF_DWB2(DWB_OGAM_RAMA_START_BASE_CNTL_G, DWBCP, 0, DWB_OGAM_RAMA_EXP_REGION_START_BASE_G, mask_sh),\ + SF_DWB2(DWB_OGAM_RAMA_START_SLOPE_CNTL_G, DWBCP, 0, DWB_OGAM_RAMA_EXP_REGION_START_SLOPE_G, mask_sh),\ + SF_DWB2(DWB_OGAM_RAMA_START_BASE_CNTL_R, DWBCP, 0, DWB_OGAM_RAMA_EXP_REGION_START_BASE_R, mask_sh),\ + SF_DWB2(DWB_OGAM_RAMA_START_SLOPE_CNTL_R, DWBCP, 0, DWB_OGAM_RAMA_EXP_REGION_START_SLOPE_R, mask_sh),\ + SF_DWB2(DWB_OGAM_RAMA_END_CNTL1_B, DWBCP, 0, DWB_OGAM_RAMA_EXP_REGION_END_BASE_B, mask_sh),\ + SF_DWB2(DWB_OGAM_RAMA_END_CNTL2_B, DWBCP, 0, DWB_OGAM_RAMA_EXP_REGION_END_B, mask_sh),\ + SF_DWB2(DWB_OGAM_RAMA_END_CNTL2_B, DWBCP, 0, DWB_OGAM_RAMA_EXP_REGION_END_SLOPE_B, mask_sh),\ + SF_DWB2(DWB_OGAM_RAMA_END_CNTL1_G, DWBCP, 0, DWB_OGAM_RAMA_EXP_REGION_END_BASE_G, mask_sh),\ + SF_DWB2(DWB_OGAM_RAMA_END_CNTL2_G, DWBCP, 0, DWB_OGAM_RAMA_EXP_REGION_END_G, mask_sh),\ + SF_DWB2(DWB_OGAM_RAMA_END_CNTL2_G, DWBCP, 0, DWB_OGAM_RAMA_EXP_REGION_END_SLOPE_G, mask_sh),\ + SF_DWB2(DWB_OGAM_RAMA_END_CNTL1_R, DWBCP, 0, DWB_OGAM_RAMA_EXP_REGION_END_BASE_R, mask_sh),\ + SF_DWB2(DWB_OGAM_RAMA_END_CNTL2_R, DWBCP, 0, DWB_OGAM_RAMA_EXP_REGION_END_R, mask_sh),\ + SF_DWB2(DWB_OGAM_RAMA_END_CNTL2_R, DWBCP, 0, DWB_OGAM_RAMA_EXP_REGION_END_SLOPE_R, mask_sh),\ + SF_DWB2(DWB_OGAM_RAMA_OFFSET_B, DWBCP, 0, DWB_OGAM_RAMA_OFFSET_B, mask_sh),\ + SF_DWB2(DWB_OGAM_RAMA_OFFSET_G, DWBCP, 0, DWB_OGAM_RAMA_OFFSET_G, mask_sh),\ + SF_DWB2(DWB_OGAM_RAMA_OFFSET_R, DWBCP, 0, DWB_OGAM_RAMA_OFFSET_R, mask_sh),\ + SF_DWB2(DWB_OGAM_RAMA_REGION_0_1, DWBCP, 0, DWB_OGAM_RAMA_EXP_REGION0_LUT_OFFSET, mask_sh),\ + SF_DWB2(DWB_OGAM_RAMA_REGION_0_1, DWBCP, 0, DWB_OGAM_RAMA_EXP_REGION0_NUM_SEGMENTS, mask_sh),\ + SF_DWB2(DWB_OGAM_RAMA_REGION_0_1, DWBCP, 0, DWB_OGAM_RAMA_EXP_REGION1_LUT_OFFSET, mask_sh),\ + SF_DWB2(DWB_OGAM_RAMA_REGION_0_1, DWBCP, 0, DWB_OGAM_RAMA_EXP_REGION1_NUM_SEGMENTS, mask_sh),\ + SF_DWB2(DWB_OGAM_RAMA_REGION_2_3, DWBCP, 0, DWB_OGAM_RAMA_EXP_REGION2_LUT_OFFSET, mask_sh),\ + SF_DWB2(DWB_OGAM_RAMA_REGION_2_3, DWBCP, 0, DWB_OGAM_RAMA_EXP_REGION2_NUM_SEGMENTS, mask_sh),\ + SF_DWB2(DWB_OGAM_RAMA_REGION_2_3, DWBCP, 0, DWB_OGAM_RAMA_EXP_REGION3_LUT_OFFSET, mask_sh),\ + SF_DWB2(DWB_OGAM_RAMA_REGION_2_3, DWBCP, 0, DWB_OGAM_RAMA_EXP_REGION3_NUM_SEGMENTS, mask_sh),\ + SF_DWB2(DWB_OGAM_RAMA_REGION_4_5, DWBCP, 0, DWB_OGAM_RAMA_EXP_REGION4_LUT_OFFSET, mask_sh),\ + SF_DWB2(DWB_OGAM_RAMA_REGION_4_5, DWBCP, 0, DWB_OGAM_RAMA_EXP_REGION4_NUM_SEGMENTS, mask_sh),\ + SF_DWB2(DWB_OGAM_RAMA_REGION_4_5, DWBCP, 0, DWB_OGAM_RAMA_EXP_REGION5_LUT_OFFSET, mask_sh),\ + SF_DWB2(DWB_OGAM_RAMA_REGION_4_5, DWBCP, 0, DWB_OGAM_RAMA_EXP_REGION5_NUM_SEGMENTS, mask_sh),\ + SF_DWB2(DWB_OGAM_RAMA_REGION_6_7, DWBCP, 0, DWB_OGAM_RAMA_EXP_REGION6_LUT_OFFSET, mask_sh),\ + SF_DWB2(DWB_OGAM_RAMA_REGION_6_7, DWBCP, 0, DWB_OGAM_RAMA_EXP_REGION6_NUM_SEGMENTS, mask_sh),\ + SF_DWB2(DWB_OGAM_RAMA_REGION_6_7, DWBCP, 0, DWB_OGAM_RAMA_EXP_REGION7_LUT_OFFSET, mask_sh),\ + SF_DWB2(DWB_OGAM_RAMA_REGION_6_7, DWBCP, 0, DWB_OGAM_RAMA_EXP_REGION7_NUM_SEGMENTS, mask_sh),\ + SF_DWB2(DWB_OGAM_RAMA_REGION_8_9, DWBCP, 0, DWB_OGAM_RAMA_EXP_REGION8_LUT_OFFSET, mask_sh),\ + SF_DWB2(DWB_OGAM_RAMA_REGION_8_9, DWBCP, 0, DWB_OGAM_RAMA_EXP_REGION8_NUM_SEGMENTS, mask_sh),\ + SF_DWB2(DWB_OGAM_RAMA_REGION_8_9, DWBCP, 0, DWB_OGAM_RAMA_EXP_REGION9_LUT_OFFSET, mask_sh),\ + SF_DWB2(DWB_OGAM_RAMA_REGION_8_9, DWBCP, 0, DWB_OGAM_RAMA_EXP_REGION9_NUM_SEGMENTS, mask_sh),\ + SF_DWB2(DWB_OGAM_RAMA_REGION_10_11, DWBCP, 0, DWB_OGAM_RAMA_EXP_REGION10_LUT_OFFSET, mask_sh),\ + SF_DWB2(DWB_OGAM_RAMA_REGION_10_11, DWBCP, 0, DWB_OGAM_RAMA_EXP_REGION10_NUM_SEGMENTS, mask_sh),\ + SF_DWB2(DWB_OGAM_RAMA_REGION_10_11, DWBCP, 0, DWB_OGAM_RAMA_EXP_REGION11_LUT_OFFSET, mask_sh),\ + SF_DWB2(DWB_OGAM_RAMA_REGION_10_11, DWBCP, 0, DWB_OGAM_RAMA_EXP_REGION11_NUM_SEGMENTS, mask_sh),\ + SF_DWB2(DWB_OGAM_RAMA_REGION_12_13, DWBCP, 0, DWB_OGAM_RAMA_EXP_REGION12_LUT_OFFSET, mask_sh),\ + SF_DWB2(DWB_OGAM_RAMA_REGION_12_13, DWBCP, 0, DWB_OGAM_RAMA_EXP_REGION12_NUM_SEGMENTS, mask_sh),\ + SF_DWB2(DWB_OGAM_RAMA_REGION_12_13, DWBCP, 0, DWB_OGAM_RAMA_EXP_REGION13_LUT_OFFSET, mask_sh),\ + SF_DWB2(DWB_OGAM_RAMA_REGION_12_13, DWBCP, 0, DWB_OGAM_RAMA_EXP_REGION13_NUM_SEGMENTS, mask_sh),\ + SF_DWB2(DWB_OGAM_RAMA_REGION_14_15, DWBCP, 0, DWB_OGAM_RAMA_EXP_REGION14_LUT_OFFSET, mask_sh),\ + SF_DWB2(DWB_OGAM_RAMA_REGION_14_15, DWBCP, 0, DWB_OGAM_RAMA_EXP_REGION14_NUM_SEGMENTS, mask_sh),\ + SF_DWB2(DWB_OGAM_RAMA_REGION_14_15, DWBCP, 0, DWB_OGAM_RAMA_EXP_REGION15_LUT_OFFSET, mask_sh),\ + SF_DWB2(DWB_OGAM_RAMA_REGION_14_15, DWBCP, 0, DWB_OGAM_RAMA_EXP_REGION15_NUM_SEGMENTS, mask_sh),\ + SF_DWB2(DWB_OGAM_RAMA_REGION_16_17, DWBCP, 0, DWB_OGAM_RAMA_EXP_REGION16_LUT_OFFSET, mask_sh),\ + SF_DWB2(DWB_OGAM_RAMA_REGION_16_17, DWBCP, 0, DWB_OGAM_RAMA_EXP_REGION16_NUM_SEGMENTS, mask_sh),\ + SF_DWB2(DWB_OGAM_RAMA_REGION_16_17, DWBCP, 0, DWB_OGAM_RAMA_EXP_REGION17_LUT_OFFSET, mask_sh),\ + SF_DWB2(DWB_OGAM_RAMA_REGION_16_17, DWBCP, 0, DWB_OGAM_RAMA_EXP_REGION17_NUM_SEGMENTS, mask_sh),\ + SF_DWB2(DWB_OGAM_RAMA_REGION_18_19, DWBCP, 0, DWB_OGAM_RAMA_EXP_REGION18_LUT_OFFSET, mask_sh),\ + SF_DWB2(DWB_OGAM_RAMA_REGION_18_19, DWBCP, 0, DWB_OGAM_RAMA_EXP_REGION18_NUM_SEGMENTS, mask_sh),\ + SF_DWB2(DWB_OGAM_RAMA_REGION_18_19, DWBCP, 0, DWB_OGAM_RAMA_EXP_REGION19_LUT_OFFSET, mask_sh),\ + SF_DWB2(DWB_OGAM_RAMA_REGION_18_19, DWBCP, 0, DWB_OGAM_RAMA_EXP_REGION19_NUM_SEGMENTS, mask_sh),\ + SF_DWB2(DWB_OGAM_RAMA_REGION_20_21, DWBCP, 0, DWB_OGAM_RAMA_EXP_REGION20_LUT_OFFSET, mask_sh),\ + SF_DWB2(DWB_OGAM_RAMA_REGION_20_21, DWBCP, 0, DWB_OGAM_RAMA_EXP_REGION20_NUM_SEGMENTS, mask_sh),\ + SF_DWB2(DWB_OGAM_RAMA_REGION_20_21, DWBCP, 0, DWB_OGAM_RAMA_EXP_REGION21_LUT_OFFSET, mask_sh),\ + SF_DWB2(DWB_OGAM_RAMA_REGION_20_21, DWBCP, 0, DWB_OGAM_RAMA_EXP_REGION21_NUM_SEGMENTS, mask_sh),\ + SF_DWB2(DWB_OGAM_RAMA_REGION_22_23, DWBCP, 0, DWB_OGAM_RAMA_EXP_REGION22_LUT_OFFSET, mask_sh),\ + SF_DWB2(DWB_OGAM_RAMA_REGION_22_23, DWBCP, 0, DWB_OGAM_RAMA_EXP_REGION22_NUM_SEGMENTS, mask_sh),\ + SF_DWB2(DWB_OGAM_RAMA_REGION_22_23, DWBCP, 0, DWB_OGAM_RAMA_EXP_REGION23_LUT_OFFSET, mask_sh),\ + SF_DWB2(DWB_OGAM_RAMA_REGION_22_23, DWBCP, 0, DWB_OGAM_RAMA_EXP_REGION23_NUM_SEGMENTS, mask_sh),\ + SF_DWB2(DWB_OGAM_RAMA_REGION_24_25, DWBCP, 0, DWB_OGAM_RAMA_EXP_REGION24_LUT_OFFSET, mask_sh),\ + SF_DWB2(DWB_OGAM_RAMA_REGION_24_25, DWBCP, 0, DWB_OGAM_RAMA_EXP_REGION24_NUM_SEGMENTS, mask_sh),\ + SF_DWB2(DWB_OGAM_RAMA_REGION_24_25, DWBCP, 0, DWB_OGAM_RAMA_EXP_REGION25_LUT_OFFSET, mask_sh),\ + SF_DWB2(DWB_OGAM_RAMA_REGION_24_25, DWBCP, 0, DWB_OGAM_RAMA_EXP_REGION25_NUM_SEGMENTS, mask_sh),\ + SF_DWB2(DWB_OGAM_RAMA_REGION_26_27, DWBCP, 0, DWB_OGAM_RAMA_EXP_REGION26_LUT_OFFSET, mask_sh),\ + SF_DWB2(DWB_OGAM_RAMA_REGION_26_27, DWBCP, 0, DWB_OGAM_RAMA_EXP_REGION26_NUM_SEGMENTS, mask_sh),\ + SF_DWB2(DWB_OGAM_RAMA_REGION_26_27, DWBCP, 0, DWB_OGAM_RAMA_EXP_REGION27_LUT_OFFSET, mask_sh),\ + SF_DWB2(DWB_OGAM_RAMA_REGION_26_27, DWBCP, 0, DWB_OGAM_RAMA_EXP_REGION27_NUM_SEGMENTS, mask_sh),\ + SF_DWB2(DWB_OGAM_RAMA_REGION_28_29, DWBCP, 0, DWB_OGAM_RAMA_EXP_REGION28_LUT_OFFSET, mask_sh),\ + SF_DWB2(DWB_OGAM_RAMA_REGION_28_29, DWBCP, 0, DWB_OGAM_RAMA_EXP_REGION28_NUM_SEGMENTS, mask_sh),\ + SF_DWB2(DWB_OGAM_RAMA_REGION_28_29, DWBCP, 0, DWB_OGAM_RAMA_EXP_REGION29_LUT_OFFSET, mask_sh),\ + SF_DWB2(DWB_OGAM_RAMA_REGION_28_29, DWBCP, 0, DWB_OGAM_RAMA_EXP_REGION29_NUM_SEGMENTS, mask_sh),\ + SF_DWB2(DWB_OGAM_RAMA_REGION_30_31, DWBCP, 0, DWB_OGAM_RAMA_EXP_REGION30_LUT_OFFSET, mask_sh),\ + SF_DWB2(DWB_OGAM_RAMA_REGION_30_31, DWBCP, 0, DWB_OGAM_RAMA_EXP_REGION30_NUM_SEGMENTS, mask_sh),\ + SF_DWB2(DWB_OGAM_RAMA_REGION_30_31, DWBCP, 0, DWB_OGAM_RAMA_EXP_REGION31_LUT_OFFSET, mask_sh),\ + SF_DWB2(DWB_OGAM_RAMA_REGION_30_31, DWBCP, 0, DWB_OGAM_RAMA_EXP_REGION31_NUM_SEGMENTS, mask_sh),\ + SF_DWB2(DWB_OGAM_RAMA_REGION_32_33, DWBCP, 0, DWB_OGAM_RAMA_EXP_REGION32_LUT_OFFSET, mask_sh),\ + SF_DWB2(DWB_OGAM_RAMA_REGION_32_33, DWBCP, 0, DWB_OGAM_RAMA_EXP_REGION32_NUM_SEGMENTS, mask_sh),\ + SF_DWB2(DWB_OGAM_RAMA_REGION_32_33, DWBCP, 0, DWB_OGAM_RAMA_EXP_REGION33_LUT_OFFSET, mask_sh),\ + SF_DWB2(DWB_OGAM_RAMA_REGION_32_33, DWBCP, 0, DWB_OGAM_RAMA_EXP_REGION33_NUM_SEGMENTS, mask_sh),\ + SF_DWB2(DWB_OGAM_RAMB_START_CNTL_B, DWBCP, 0, DWB_OGAM_RAMB_EXP_REGION_START_B, mask_sh),\ + SF_DWB2(DWB_OGAM_RAMB_START_CNTL_B, DWBCP, 0, DWB_OGAM_RAMB_EXP_REGION_START_SEGMENT_B, mask_sh),\ + SF_DWB2(DWB_OGAM_RAMB_START_CNTL_G, DWBCP, 0, DWB_OGAM_RAMB_EXP_REGION_START_G, mask_sh),\ + SF_DWB2(DWB_OGAM_RAMB_START_CNTL_G, DWBCP, 0, DWB_OGAM_RAMB_EXP_REGION_START_SEGMENT_G, mask_sh),\ + SF_DWB2(DWB_OGAM_RAMB_START_CNTL_R, DWBCP, 0, DWB_OGAM_RAMB_EXP_REGION_START_R, mask_sh),\ + SF_DWB2(DWB_OGAM_RAMB_START_CNTL_R, DWBCP, 0, DWB_OGAM_RAMB_EXP_REGION_START_SEGMENT_R, mask_sh),\ + SF_DWB2(DWB_OGAM_RAMB_START_BASE_CNTL_B, DWBCP, 0, DWB_OGAM_RAMB_EXP_REGION_START_BASE_B, mask_sh),\ + SF_DWB2(DWB_OGAM_RAMB_START_SLOPE_CNTL_B, DWBCP, 0, DWB_OGAM_RAMB_EXP_REGION_START_SLOPE_B, mask_sh),\ + SF_DWB2(DWB_OGAM_RAMB_START_BASE_CNTL_G, DWBCP, 0, DWB_OGAM_RAMB_EXP_REGION_START_BASE_G, mask_sh),\ + SF_DWB2(DWB_OGAM_RAMB_START_SLOPE_CNTL_G, DWBCP, 0, DWB_OGAM_RAMB_EXP_REGION_START_SLOPE_G, mask_sh),\ + SF_DWB2(DWB_OGAM_RAMB_START_BASE_CNTL_R, DWBCP, 0, DWB_OGAM_RAMB_EXP_REGION_START_BASE_R, mask_sh),\ + SF_DWB2(DWB_OGAM_RAMB_START_SLOPE_CNTL_R, DWBCP, 0, DWB_OGAM_RAMB_EXP_REGION_START_SLOPE_R, mask_sh),\ + SF_DWB2(DWB_OGAM_RAMB_END_CNTL1_B, DWBCP, 0, DWB_OGAM_RAMB_EXP_REGION_END_BASE_B, mask_sh),\ + SF_DWB2(DWB_OGAM_RAMB_END_CNTL2_B, DWBCP, 0, DWB_OGAM_RAMB_EXP_REGION_END_B, mask_sh),\ + SF_DWB2(DWB_OGAM_RAMB_END_CNTL2_B, DWBCP, 0, DWB_OGAM_RAMB_EXP_REGION_END_SLOPE_B, mask_sh),\ + SF_DWB2(DWB_OGAM_RAMB_END_CNTL1_G, DWBCP, 0, DWB_OGAM_RAMB_EXP_REGION_END_BASE_G, mask_sh),\ + SF_DWB2(DWB_OGAM_RAMB_END_CNTL2_G, DWBCP, 0, DWB_OGAM_RAMB_EXP_REGION_END_G, mask_sh),\ + SF_DWB2(DWB_OGAM_RAMB_END_CNTL2_G, DWBCP, 0, DWB_OGAM_RAMB_EXP_REGION_END_SLOPE_G, mask_sh),\ + SF_DWB2(DWB_OGAM_RAMB_END_CNTL1_R, DWBCP, 0, DWB_OGAM_RAMB_EXP_REGION_END_BASE_R, mask_sh),\ + SF_DWB2(DWB_OGAM_RAMB_END_CNTL2_R, DWBCP, 0, DWB_OGAM_RAMB_EXP_REGION_END_R, mask_sh),\ + SF_DWB2(DWB_OGAM_RAMB_END_CNTL2_R, DWBCP, 0, DWB_OGAM_RAMB_EXP_REGION_END_SLOPE_R, mask_sh),\ + SF_DWB2(DWB_OGAM_RAMB_OFFSET_B, DWBCP, 0, DWB_OGAM_RAMB_OFFSET_B, mask_sh),\ + SF_DWB2(DWB_OGAM_RAMB_OFFSET_G, DWBCP, 0, DWB_OGAM_RAMB_OFFSET_G, mask_sh),\ + SF_DWB2(DWB_OGAM_RAMB_OFFSET_R, DWBCP, 0, DWB_OGAM_RAMB_OFFSET_R, mask_sh),\ + SF_DWB2(DWB_OGAM_RAMB_REGION_0_1, DWBCP, 0, DWB_OGAM_RAMB_EXP_REGION0_LUT_OFFSET, mask_sh),\ + SF_DWB2(DWB_OGAM_RAMB_REGION_0_1, DWBCP, 0, DWB_OGAM_RAMB_EXP_REGION0_NUM_SEGMENTS, mask_sh),\ + SF_DWB2(DWB_OGAM_RAMB_REGION_0_1, DWBCP, 0, DWB_OGAM_RAMB_EXP_REGION1_LUT_OFFSET, mask_sh),\ + SF_DWB2(DWB_OGAM_RAMB_REGION_0_1, DWBCP, 0, DWB_OGAM_RAMB_EXP_REGION1_NUM_SEGMENTS, mask_sh),\ + SF_DWB2(DWB_OGAM_RAMB_REGION_2_3, DWBCP, 0, DWB_OGAM_RAMB_EXP_REGION2_LUT_OFFSET, mask_sh),\ + SF_DWB2(DWB_OGAM_RAMB_REGION_2_3, DWBCP, 0, DWB_OGAM_RAMB_EXP_REGION2_NUM_SEGMENTS, mask_sh),\ + SF_DWB2(DWB_OGAM_RAMB_REGION_2_3, DWBCP, 0, DWB_OGAM_RAMB_EXP_REGION3_LUT_OFFSET, mask_sh),\ + SF_DWB2(DWB_OGAM_RAMB_REGION_2_3, DWBCP, 0, DWB_OGAM_RAMB_EXP_REGION3_NUM_SEGMENTS, mask_sh),\ + SF_DWB2(DWB_OGAM_RAMB_REGION_4_5, DWBCP, 0, DWB_OGAM_RAMB_EXP_REGION4_LUT_OFFSET, mask_sh),\ + SF_DWB2(DWB_OGAM_RAMB_REGION_4_5, DWBCP, 0, DWB_OGAM_RAMB_EXP_REGION4_NUM_SEGMENTS, mask_sh),\ + SF_DWB2(DWB_OGAM_RAMB_REGION_4_5, DWBCP, 0, DWB_OGAM_RAMB_EXP_REGION5_LUT_OFFSET, mask_sh),\ + SF_DWB2(DWB_OGAM_RAMB_REGION_4_5, DWBCP, 0, DWB_OGAM_RAMB_EXP_REGION5_NUM_SEGMENTS, mask_sh),\ + SF_DWB2(DWB_OGAM_RAMB_REGION_6_7, DWBCP, 0, DWB_OGAM_RAMB_EXP_REGION6_LUT_OFFSET, mask_sh),\ + SF_DWB2(DWB_OGAM_RAMB_REGION_6_7, DWBCP, 0, DWB_OGAM_RAMB_EXP_REGION6_NUM_SEGMENTS, mask_sh),\ + SF_DWB2(DWB_OGAM_RAMB_REGION_6_7, DWBCP, 0, DWB_OGAM_RAMB_EXP_REGION7_LUT_OFFSET, mask_sh),\ + SF_DWB2(DWB_OGAM_RAMB_REGION_6_7, DWBCP, 0, DWB_OGAM_RAMB_EXP_REGION7_NUM_SEGMENTS, mask_sh),\ + SF_DWB2(DWB_OGAM_RAMB_REGION_8_9, DWBCP, 0, DWB_OGAM_RAMB_EXP_REGION8_LUT_OFFSET, mask_sh),\ + SF_DWB2(DWB_OGAM_RAMB_REGION_8_9, DWBCP, 0, DWB_OGAM_RAMB_EXP_REGION8_NUM_SEGMENTS, mask_sh),\ + SF_DWB2(DWB_OGAM_RAMB_REGION_8_9, DWBCP, 0, DWB_OGAM_RAMB_EXP_REGION9_LUT_OFFSET, mask_sh),\ + SF_DWB2(DWB_OGAM_RAMB_REGION_8_9, DWBCP, 0, DWB_OGAM_RAMB_EXP_REGION9_NUM_SEGMENTS, mask_sh),\ + SF_DWB2(DWB_OGAM_RAMB_REGION_10_11, DWBCP, 0, DWB_OGAM_RAMB_EXP_REGION10_LUT_OFFSET, mask_sh),\ + SF_DWB2(DWB_OGAM_RAMB_REGION_10_11, DWBCP, 0, DWB_OGAM_RAMB_EXP_REGION10_NUM_SEGMENTS, mask_sh),\ + SF_DWB2(DWB_OGAM_RAMB_REGION_10_11, DWBCP, 0, DWB_OGAM_RAMB_EXP_REGION11_LUT_OFFSET, mask_sh),\ + SF_DWB2(DWB_OGAM_RAMB_REGION_10_11, DWBCP, 0, DWB_OGAM_RAMB_EXP_REGION11_NUM_SEGMENTS, mask_sh),\ + SF_DWB2(DWB_OGAM_RAMB_REGION_12_13, DWBCP, 0, DWB_OGAM_RAMB_EXP_REGION12_LUT_OFFSET, mask_sh),\ + SF_DWB2(DWB_OGAM_RAMB_REGION_12_13, DWBCP, 0, DWB_OGAM_RAMB_EXP_REGION12_NUM_SEGMENTS, mask_sh),\ + SF_DWB2(DWB_OGAM_RAMB_REGION_12_13, DWBCP, 0, DWB_OGAM_RAMB_EXP_REGION13_LUT_OFFSET, mask_sh),\ + SF_DWB2(DWB_OGAM_RAMB_REGION_12_13, DWBCP, 0, DWB_OGAM_RAMB_EXP_REGION13_NUM_SEGMENTS, mask_sh),\ + SF_DWB2(DWB_OGAM_RAMB_REGION_14_15, DWBCP, 0, DWB_OGAM_RAMB_EXP_REGION14_LUT_OFFSET, mask_sh),\ + SF_DWB2(DWB_OGAM_RAMB_REGION_14_15, DWBCP, 0, DWB_OGAM_RAMB_EXP_REGION14_NUM_SEGMENTS, mask_sh),\ + SF_DWB2(DWB_OGAM_RAMB_REGION_14_15, DWBCP, 0, DWB_OGAM_RAMB_EXP_REGION15_LUT_OFFSET, mask_sh),\ + SF_DWB2(DWB_OGAM_RAMB_REGION_14_15, DWBCP, 0, DWB_OGAM_RAMB_EXP_REGION15_NUM_SEGMENTS, mask_sh),\ + SF_DWB2(DWB_OGAM_RAMB_REGION_16_17, DWBCP, 0, DWB_OGAM_RAMB_EXP_REGION16_LUT_OFFSET, mask_sh),\ + SF_DWB2(DWB_OGAM_RAMB_REGION_16_17, DWBCP, 0, DWB_OGAM_RAMB_EXP_REGION16_NUM_SEGMENTS, mask_sh),\ + SF_DWB2(DWB_OGAM_RAMB_REGION_16_17, DWBCP, 0, DWB_OGAM_RAMB_EXP_REGION17_LUT_OFFSET, mask_sh),\ + SF_DWB2(DWB_OGAM_RAMB_REGION_16_17, DWBCP, 0, DWB_OGAM_RAMB_EXP_REGION17_NUM_SEGMENTS, mask_sh),\ + SF_DWB2(DWB_OGAM_RAMB_REGION_18_19, DWBCP, 0, DWB_OGAM_RAMB_EXP_REGION18_LUT_OFFSET, mask_sh),\ + SF_DWB2(DWB_OGAM_RAMB_REGION_18_19, DWBCP, 0, DWB_OGAM_RAMB_EXP_REGION18_NUM_SEGMENTS, mask_sh),\ + SF_DWB2(DWB_OGAM_RAMB_REGION_18_19, DWBCP, 0, DWB_OGAM_RAMB_EXP_REGION19_LUT_OFFSET, mask_sh),\ + SF_DWB2(DWB_OGAM_RAMB_REGION_18_19, DWBCP, 0, DWB_OGAM_RAMB_EXP_REGION19_NUM_SEGMENTS, mask_sh),\ + SF_DWB2(DWB_OGAM_RAMB_REGION_20_21, DWBCP, 0, DWB_OGAM_RAMB_EXP_REGION20_LUT_OFFSET, mask_sh),\ + SF_DWB2(DWB_OGAM_RAMB_REGION_20_21, DWBCP, 0, DWB_OGAM_RAMB_EXP_REGION20_NUM_SEGMENTS, mask_sh),\ + SF_DWB2(DWB_OGAM_RAMB_REGION_20_21, DWBCP, 0, DWB_OGAM_RAMB_EXP_REGION21_LUT_OFFSET, mask_sh),\ + SF_DWB2(DWB_OGAM_RAMB_REGION_20_21, DWBCP, 0, DWB_OGAM_RAMB_EXP_REGION21_NUM_SEGMENTS, mask_sh),\ + SF_DWB2(DWB_OGAM_RAMB_REGION_22_23, DWBCP, 0, DWB_OGAM_RAMB_EXP_REGION22_LUT_OFFSET, mask_sh),\ + SF_DWB2(DWB_OGAM_RAMB_REGION_22_23, DWBCP, 0, DWB_OGAM_RAMB_EXP_REGION22_NUM_SEGMENTS, mask_sh),\ + SF_DWB2(DWB_OGAM_RAMB_REGION_22_23, DWBCP, 0, DWB_OGAM_RAMB_EXP_REGION23_LUT_OFFSET, mask_sh),\ + SF_DWB2(DWB_OGAM_RAMB_REGION_22_23, DWBCP, 0, DWB_OGAM_RAMB_EXP_REGION23_NUM_SEGMENTS, mask_sh),\ + SF_DWB2(DWB_OGAM_RAMB_REGION_24_25, DWBCP, 0, DWB_OGAM_RAMB_EXP_REGION24_LUT_OFFSET, mask_sh),\ + SF_DWB2(DWB_OGAM_RAMB_REGION_24_25, DWBCP, 0, DWB_OGAM_RAMB_EXP_REGION24_NUM_SEGMENTS, mask_sh),\ + SF_DWB2(DWB_OGAM_RAMB_REGION_24_25, DWBCP, 0, DWB_OGAM_RAMB_EXP_REGION25_LUT_OFFSET, mask_sh),\ + SF_DWB2(DWB_OGAM_RAMB_REGION_24_25, DWBCP, 0, DWB_OGAM_RAMB_EXP_REGION25_NUM_SEGMENTS, mask_sh),\ + SF_DWB2(DWB_OGAM_RAMB_REGION_26_27, DWBCP, 0, DWB_OGAM_RAMB_EXP_REGION26_LUT_OFFSET, mask_sh),\ + SF_DWB2(DWB_OGAM_RAMB_REGION_26_27, DWBCP, 0, DWB_OGAM_RAMB_EXP_REGION26_NUM_SEGMENTS, mask_sh),\ + SF_DWB2(DWB_OGAM_RAMB_REGION_26_27, DWBCP, 0, DWB_OGAM_RAMB_EXP_REGION27_LUT_OFFSET, mask_sh),\ + SF_DWB2(DWB_OGAM_RAMB_REGION_26_27, DWBCP, 0, DWB_OGAM_RAMB_EXP_REGION27_NUM_SEGMENTS, mask_sh),\ + SF_DWB2(DWB_OGAM_RAMB_REGION_28_29, DWBCP, 0, DWB_OGAM_RAMB_EXP_REGION28_LUT_OFFSET, mask_sh),\ + SF_DWB2(DWB_OGAM_RAMB_REGION_28_29, DWBCP, 0, DWB_OGAM_RAMB_EXP_REGION28_NUM_SEGMENTS, mask_sh),\ + SF_DWB2(DWB_OGAM_RAMB_REGION_28_29, DWBCP, 0, DWB_OGAM_RAMB_EXP_REGION29_LUT_OFFSET, mask_sh),\ + SF_DWB2(DWB_OGAM_RAMB_REGION_28_29, DWBCP, 0, DWB_OGAM_RAMB_EXP_REGION29_NUM_SEGMENTS, mask_sh),\ + SF_DWB2(DWB_OGAM_RAMB_REGION_30_31, DWBCP, 0, DWB_OGAM_RAMB_EXP_REGION30_LUT_OFFSET, mask_sh),\ + SF_DWB2(DWB_OGAM_RAMB_REGION_30_31, DWBCP, 0, DWB_OGAM_RAMB_EXP_REGION30_NUM_SEGMENTS, mask_sh),\ + SF_DWB2(DWB_OGAM_RAMB_REGION_30_31, DWBCP, 0, DWB_OGAM_RAMB_EXP_REGION31_LUT_OFFSET, mask_sh),\ + SF_DWB2(DWB_OGAM_RAMB_REGION_30_31, DWBCP, 0, DWB_OGAM_RAMB_EXP_REGION31_NUM_SEGMENTS, mask_sh),\ + SF_DWB2(DWB_OGAM_RAMB_REGION_32_33, DWBCP, 0, DWB_OGAM_RAMB_EXP_REGION32_LUT_OFFSET, mask_sh),\ + SF_DWB2(DWB_OGAM_RAMB_REGION_32_33, DWBCP, 0, DWB_OGAM_RAMB_EXP_REGION32_NUM_SEGMENTS, mask_sh),\ + SF_DWB2(DWB_OGAM_RAMB_REGION_32_33, DWBCP, 0, DWB_OGAM_RAMB_EXP_REGION33_LUT_OFFSET, mask_sh),\ + SF_DWB2(DWB_OGAM_RAMB_REGION_32_33, DWBCP, 0, DWB_OGAM_RAMB_EXP_REGION33_NUM_SEGMENTS, mask_sh) + + +#define DWBC_REG_FIELD_LIST_DCN3_0(type) \ + type DWB_ENABLE;\ + type DISPCLK_R_DWB_GATE_DIS;\ + type DISPCLK_G_DWB_GATE_DIS;\ + type DWB_TEST_CLK_SEL;\ + type DWBSCL_LUT_MEM_PWR_FORCE;\ + type DWBSCL_LUT_MEM_PWR_DIS;\ + type DWBSCL_LUT_MEM_PWR_STATE;\ + type DWBSCL_LB_MEM_PWR_FORCE;\ + type DWBSCL_LB_MEM_PWR_DIS;\ + type DWBSCL_LB_MEM_PWR_STATE;\ + type DWB_OGAM_LUT_MEM_PWR_FORCE;\ + type DWB_OGAM_LUT_MEM_PWR_DIS;\ + type DWB_OGAM_LUT_MEM_PWR_STATE;\ + type FC_FRAME_CAPTURE_EN;\ + type FC_FRAME_CAPTURE_RATE;\ + type FC_WINDOW_CROP_EN;\ + type FC_EYE_SELECTION;\ + type FC_STEREO_EYE_POLARITY;\ + type FC_NEW_CONTENT;\ + type FC_FI_EN;\ + type FC_FI_PHASE;\ + type FC_FRAME_CAPTURE_EN_CURRENT;\ + type FC_FIRST_PIXEL_DELAY_COUNT;\ + type FC_WINDOW_START_X;\ + type FC_WINDOW_START_Y;\ + type FC_WINDOW_WIDTH;\ + type FC_WINDOW_HEIGHT;\ + type FC_SOURCE_WIDTH;\ + type FC_SOURCE_HEIGHT;\ + type DWB_UPDATE_LOCK;\ + type DWB_UPDATE_PENDING;\ + type DWB_CRC_EN;\ + type DWB_CRC_CONT_EN;\ + type DWB_CRC_SRC_SEL;\ + type DWB_CRC_RED_MASK;\ + type DWB_CRC_GREEN_MASK;\ + type DWB_CRC_BLUE_MASK;\ + type DWB_CRC_A_MASK;\ + type DWB_CRC_SIG_RED;\ + type DWB_CRC_SIG_GREEN;\ + type DWB_CRC_SIG_BLUE;\ + type DWB_CRC_SIG_A;\ + type OUT_FORMAT;\ + type OUT_DENORM;\ + type OUT_MAX;\ + type OUT_MIN;\ + type DWB_MMHUBBUB_BACKPRESSURE_CNT_EN;\ + type DWB_MMHUBBUB_MAX_BACKPRESSURE;\ + type DWB_HOST_READ_RATE_CONTROL;\ + type DWBSCL_DATA_OVERFLOW_FLAG;\ + type DWBSCL_DATA_OVERFLOW_ACK;\ + type DWBSCL_DATA_OVERFLOW_MASK;\ + type DWBSCL_DATA_OVERFLOW_INT_STATUS;\ + type DWBSCL_DATA_OVERFLOW_INT_TYPE;\ + type DWBSCL_DATA_OVERFLOW_TYPE;\ + type DWBSCL_DATA_OVERFLOW_OUT_X_CNT;\ + type DWBSCL_DATA_OVERFLOW_OUT_Y_CNT;\ + type DWB_SOFT_RESET;\ + type DWBSCL_COEF_RAM_TAP_PAIR_IDX;\ + type DWBSCL_COEF_RAM_PHASE;\ + type DWBSCL_COEF_RAM_FILTER_TYPE;\ + type DWBSCL_COEF_RAM_SELECT_RD;\ + type DWBSCL_COEF_RAM_EVEN_TAP_COEF;\ + type DWBSCL_COEF_RAM_EVEN_TAP_COEF_EN;\ + type DWBSCL_COEF_RAM_ODD_TAP_COEF;\ + type DWBSCL_COEF_RAM_ODD_TAP_COEF_EN;\ + type DWBSCL_MODE;\ + type DWBSCL_COEF_RAM_SELECT;\ + type DWBSCL_COEF_RAM_SELECT_CURRENT;\ + type DWBSCL_H_NUM_OF_TAPS;\ + type DWBSCL_V_NUM_OF_TAPS;\ + type DWBSCL_H_SCALE_RATIO;\ + type DWBSCL_H_INIT_FRAC;\ + type DWBSCL_H_INIT_INT;\ + type DWBSCL_V_SCALE_RATIO;\ + type DWBSCL_V_INIT_FRAC;\ + type DWBSCL_V_INIT_INT;\ + type DWBSCL_BOUNDARY_MODE;\ + type DWBSCL_BLACK_COLOR_RGB;\ + type DWBSCL_DEST_WIDTH;\ + type DWBSCL_DEST_HEIGHT;\ + type DWB_HDR_MULT_COEF;\ + type DWB_GAMUT_REMAP_MODE;\ + type DWB_GAMUT_REMAP_MODE_CURRENT;\ + type DWB_GAMUT_REMAP_COEF_FORMAT;\ + type DWB_GAMUT_REMAPA_C11;\ + type DWB_GAMUT_REMAPA_C12;\ + type DWB_GAMUT_REMAPA_C13;\ + type DWB_GAMUT_REMAPA_C14;\ + type DWB_GAMUT_REMAPA_C21;\ + type DWB_GAMUT_REMAPA_C22;\ + type DWB_GAMUT_REMAPA_C23;\ + type DWB_GAMUT_REMAPA_C24;\ + type DWB_GAMUT_REMAPA_C31;\ + type DWB_GAMUT_REMAPA_C32;\ + type DWB_GAMUT_REMAPA_C33;\ + type DWB_GAMUT_REMAPA_C34;\ + type DWB_GAMUT_REMAPB_C11;\ + type DWB_GAMUT_REMAPB_C12;\ + type DWB_GAMUT_REMAPB_C13;\ + type DWB_GAMUT_REMAPB_C14;\ + type DWB_GAMUT_REMAPB_C21;\ + type DWB_GAMUT_REMAPB_C22;\ + type DWB_GAMUT_REMAPB_C23;\ + type DWB_GAMUT_REMAPB_C24;\ + type DWB_GAMUT_REMAPB_C31;\ + type DWB_GAMUT_REMAPB_C32;\ + type DWB_GAMUT_REMAPB_C33;\ + type DWB_GAMUT_REMAPB_C34;\ + type DWB_OGAM_MODE;\ + type DWB_OGAM_SELECT;\ + type DWB_OGAM_PWL_DISABLE;\ + type DWB_OGAM_MODE_CURRENT;\ + type DWB_OGAM_SELECT_CURRENT;\ + type DWB_OGAM_LUT_INDEX;\ + type DWB_OGAM_LUT_DATA;\ + type DWB_OGAM_LUT_WRITE_COLOR_MASK;\ + type DWB_OGAM_LUT_READ_COLOR_SEL;\ + type DWB_OGAM_LUT_READ_DBG;\ + type DWB_OGAM_LUT_HOST_SEL;\ + type DWB_OGAM_LUT_CONFIG_MODE;\ + type DWB_OGAM_LUT_STATUS;\ + type DWB_OGAM_RAMA_EXP_REGION_START_B;\ + type DWB_OGAM_RAMA_EXP_REGION_START_SEGMENT_B;\ + type DWB_OGAM_RAMA_EXP_REGION_START_G;\ + type DWB_OGAM_RAMA_EXP_REGION_START_SEGMENT_G;\ + type DWB_OGAM_RAMA_EXP_REGION_START_R;\ + type DWB_OGAM_RAMA_EXP_REGION_START_SEGMENT_R;\ + type DWB_OGAM_RAMA_EXP_REGION_START_BASE_B;\ + type DWB_OGAM_RAMA_EXP_REGION_START_SLOPE_B;\ + type DWB_OGAM_RAMA_EXP_REGION_START_BASE_G;\ + type DWB_OGAM_RAMA_EXP_REGION_START_SLOPE_G;\ + type DWB_OGAM_RAMA_EXP_REGION_START_BASE_R;\ + type DWB_OGAM_RAMA_EXP_REGION_START_SLOPE_R;\ + type DWB_OGAM_RAMA_EXP_REGION_END_BASE_B;\ + type DWB_OGAM_RAMA_EXP_REGION_END_B;\ + type DWB_OGAM_RAMA_EXP_REGION_END_SLOPE_B;\ + type DWB_OGAM_RAMA_EXP_REGION_END_BASE_G;\ + type DWB_OGAM_RAMA_EXP_REGION_END_G;\ + type DWB_OGAM_RAMA_EXP_REGION_END_SLOPE_G;\ + type DWB_OGAM_RAMA_EXP_REGION_END_BASE_R;\ + type DWB_OGAM_RAMA_EXP_REGION_END_R;\ + type DWB_OGAM_RAMA_EXP_REGION_END_SLOPE_R;\ + type DWB_OGAM_RAMA_OFFSET_B;\ + type DWB_OGAM_RAMA_OFFSET_G;\ + type DWB_OGAM_RAMA_OFFSET_R;\ + type DWB_OGAM_RAMA_EXP_REGION0_LUT_OFFSET;\ + type DWB_OGAM_RAMA_EXP_REGION0_NUM_SEGMENTS;\ + type DWB_OGAM_RAMA_EXP_REGION1_LUT_OFFSET;\ + type DWB_OGAM_RAMA_EXP_REGION1_NUM_SEGMENTS;\ + type DWB_OGAM_RAMA_EXP_REGION2_LUT_OFFSET;\ + type DWB_OGAM_RAMA_EXP_REGION2_NUM_SEGMENTS;\ + type DWB_OGAM_RAMA_EXP_REGION3_LUT_OFFSET;\ + type DWB_OGAM_RAMA_EXP_REGION3_NUM_SEGMENTS;\ + type DWB_OGAM_RAMA_EXP_REGION4_LUT_OFFSET;\ + type DWB_OGAM_RAMA_EXP_REGION4_NUM_SEGMENTS;\ + type DWB_OGAM_RAMA_EXP_REGION5_LUT_OFFSET;\ + type DWB_OGAM_RAMA_EXP_REGION5_NUM_SEGMENTS;\ + type DWB_OGAM_RAMA_EXP_REGION6_LUT_OFFSET;\ + type DWB_OGAM_RAMA_EXP_REGION6_NUM_SEGMENTS;\ + type DWB_OGAM_RAMA_EXP_REGION7_LUT_OFFSET;\ + type DWB_OGAM_RAMA_EXP_REGION7_NUM_SEGMENTS;\ + type DWB_OGAM_RAMA_EXP_REGION8_LUT_OFFSET;\ + type DWB_OGAM_RAMA_EXP_REGION8_NUM_SEGMENTS;\ + type DWB_OGAM_RAMA_EXP_REGION9_LUT_OFFSET;\ + type DWB_OGAM_RAMA_EXP_REGION9_NUM_SEGMENTS;\ + type DWB_OGAM_RAMA_EXP_REGION10_LUT_OFFSET;\ + type DWB_OGAM_RAMA_EXP_REGION10_NUM_SEGMENTS;\ + type DWB_OGAM_RAMA_EXP_REGION11_LUT_OFFSET;\ + type DWB_OGAM_RAMA_EXP_REGION11_NUM_SEGMENTS;\ + type DWB_OGAM_RAMA_EXP_REGION12_LUT_OFFSET;\ + type DWB_OGAM_RAMA_EXP_REGION12_NUM_SEGMENTS;\ + type DWB_OGAM_RAMA_EXP_REGION13_LUT_OFFSET;\ + type DWB_OGAM_RAMA_EXP_REGION13_NUM_SEGMENTS;\ + type DWB_OGAM_RAMA_EXP_REGION14_LUT_OFFSET;\ + type DWB_OGAM_RAMA_EXP_REGION14_NUM_SEGMENTS;\ + type DWB_OGAM_RAMA_EXP_REGION15_LUT_OFFSET;\ + type DWB_OGAM_RAMA_EXP_REGION15_NUM_SEGMENTS;\ + type DWB_OGAM_RAMA_EXP_REGION16_LUT_OFFSET;\ + type DWB_OGAM_RAMA_EXP_REGION16_NUM_SEGMENTS;\ + type DWB_OGAM_RAMA_EXP_REGION17_LUT_OFFSET;\ + type DWB_OGAM_RAMA_EXP_REGION17_NUM_SEGMENTS;\ + type DWB_OGAM_RAMA_EXP_REGION18_LUT_OFFSET;\ + type DWB_OGAM_RAMA_EXP_REGION18_NUM_SEGMENTS;\ + type DWB_OGAM_RAMA_EXP_REGION19_LUT_OFFSET;\ + type DWB_OGAM_RAMA_EXP_REGION19_NUM_SEGMENTS;\ + type DWB_OGAM_RAMA_EXP_REGION20_LUT_OFFSET;\ + type DWB_OGAM_RAMA_EXP_REGION20_NUM_SEGMENTS;\ + type DWB_OGAM_RAMA_EXP_REGION21_LUT_OFFSET;\ + type DWB_OGAM_RAMA_EXP_REGION21_NUM_SEGMENTS;\ + type DWB_OGAM_RAMA_EXP_REGION22_LUT_OFFSET;\ + type DWB_OGAM_RAMA_EXP_REGION22_NUM_SEGMENTS;\ + type DWB_OGAM_RAMA_EXP_REGION23_LUT_OFFSET;\ + type DWB_OGAM_RAMA_EXP_REGION23_NUM_SEGMENTS;\ + type DWB_OGAM_RAMA_EXP_REGION24_LUT_OFFSET;\ + type DWB_OGAM_RAMA_EXP_REGION24_NUM_SEGMENTS;\ + type DWB_OGAM_RAMA_EXP_REGION25_LUT_OFFSET;\ + type DWB_OGAM_RAMA_EXP_REGION25_NUM_SEGMENTS;\ + type DWB_OGAM_RAMA_EXP_REGION26_LUT_OFFSET;\ + type DWB_OGAM_RAMA_EXP_REGION26_NUM_SEGMENTS;\ + type DWB_OGAM_RAMA_EXP_REGION27_LUT_OFFSET;\ + type DWB_OGAM_RAMA_EXP_REGION27_NUM_SEGMENTS;\ + type DWB_OGAM_RAMA_EXP_REGION28_LUT_OFFSET;\ + type DWB_OGAM_RAMA_EXP_REGION28_NUM_SEGMENTS;\ + type DWB_OGAM_RAMA_EXP_REGION29_LUT_OFFSET;\ + type DWB_OGAM_RAMA_EXP_REGION29_NUM_SEGMENTS;\ + type DWB_OGAM_RAMA_EXP_REGION30_LUT_OFFSET;\ + type DWB_OGAM_RAMA_EXP_REGION30_NUM_SEGMENTS;\ + type DWB_OGAM_RAMA_EXP_REGION31_LUT_OFFSET;\ + type DWB_OGAM_RAMA_EXP_REGION31_NUM_SEGMENTS;\ + type DWB_OGAM_RAMA_EXP_REGION32_LUT_OFFSET;\ + type DWB_OGAM_RAMA_EXP_REGION32_NUM_SEGMENTS;\ + type DWB_OGAM_RAMA_EXP_REGION33_LUT_OFFSET;\ + type DWB_OGAM_RAMA_EXP_REGION33_NUM_SEGMENTS;\ + type DWB_OGAM_RAMB_EXP_REGION_START_B;\ + type DWB_OGAM_RAMB_EXP_REGION_START_SEGMENT_B;\ + type DWB_OGAM_RAMB_EXP_REGION_START_G;\ + type DWB_OGAM_RAMB_EXP_REGION_START_SEGMENT_G;\ + type DWB_OGAM_RAMB_EXP_REGION_START_R;\ + type DWB_OGAM_RAMB_EXP_REGION_START_SEGMENT_R;\ + type DWB_OGAM_RAMB_EXP_REGION_START_BASE_B;\ + type DWB_OGAM_RAMB_EXP_REGION_START_SLOPE_B;\ + type DWB_OGAM_RAMB_EXP_REGION_START_BASE_G;\ + type DWB_OGAM_RAMB_EXP_REGION_START_SLOPE_G;\ + type DWB_OGAM_RAMB_EXP_REGION_START_BASE_R;\ + type DWB_OGAM_RAMB_EXP_REGION_START_SLOPE_R;\ + type DWB_OGAM_RAMB_EXP_REGION_END_BASE_B;\ + type DWB_OGAM_RAMB_EXP_REGION_END_B;\ + type DWB_OGAM_RAMB_EXP_REGION_END_SLOPE_B;\ + type DWB_OGAM_RAMB_EXP_REGION_END_BASE_G;\ + type DWB_OGAM_RAMB_EXP_REGION_END_G;\ + type DWB_OGAM_RAMB_EXP_REGION_END_SLOPE_G;\ + type DWB_OGAM_RAMB_EXP_REGION_END_BASE_R;\ + type DWB_OGAM_RAMB_EXP_REGION_END_R;\ + type DWB_OGAM_RAMB_EXP_REGION_END_SLOPE_R;\ + type DWB_OGAM_RAMB_OFFSET_B;\ + type DWB_OGAM_RAMB_OFFSET_G;\ + type DWB_OGAM_RAMB_OFFSET_R;\ + type DWB_OGAM_RAMB_EXP_REGION0_LUT_OFFSET;\ + type DWB_OGAM_RAMB_EXP_REGION0_NUM_SEGMENTS;\ + type DWB_OGAM_RAMB_EXP_REGION1_LUT_OFFSET;\ + type DWB_OGAM_RAMB_EXP_REGION1_NUM_SEGMENTS;\ + type DWB_OGAM_RAMB_EXP_REGION2_LUT_OFFSET;\ + type DWB_OGAM_RAMB_EXP_REGION2_NUM_SEGMENTS;\ + type DWB_OGAM_RAMB_EXP_REGION3_LUT_OFFSET;\ + type DWB_OGAM_RAMB_EXP_REGION3_NUM_SEGMENTS;\ + type DWB_OGAM_RAMB_EXP_REGION4_LUT_OFFSET;\ + type DWB_OGAM_RAMB_EXP_REGION4_NUM_SEGMENTS;\ + type DWB_OGAM_RAMB_EXP_REGION5_LUT_OFFSET;\ + type DWB_OGAM_RAMB_EXP_REGION5_NUM_SEGMENTS;\ + type DWB_OGAM_RAMB_EXP_REGION6_LUT_OFFSET;\ + type DWB_OGAM_RAMB_EXP_REGION6_NUM_SEGMENTS;\ + type DWB_OGAM_RAMB_EXP_REGION7_LUT_OFFSET;\ + type DWB_OGAM_RAMB_EXP_REGION7_NUM_SEGMENTS;\ + type DWB_OGAM_RAMB_EXP_REGION8_LUT_OFFSET;\ + type DWB_OGAM_RAMB_EXP_REGION8_NUM_SEGMENTS;\ + type DWB_OGAM_RAMB_EXP_REGION9_LUT_OFFSET;\ + type DWB_OGAM_RAMB_EXP_REGION9_NUM_SEGMENTS;\ + type DWB_OGAM_RAMB_EXP_REGION10_LUT_OFFSET;\ + type DWB_OGAM_RAMB_EXP_REGION10_NUM_SEGMENTS;\ + type DWB_OGAM_RAMB_EXP_REGION11_LUT_OFFSET;\ + type DWB_OGAM_RAMB_EXP_REGION11_NUM_SEGMENTS;\ + type DWB_OGAM_RAMB_EXP_REGION12_LUT_OFFSET;\ + type DWB_OGAM_RAMB_EXP_REGION12_NUM_SEGMENTS;\ + type DWB_OGAM_RAMB_EXP_REGION13_LUT_OFFSET;\ + type DWB_OGAM_RAMB_EXP_REGION13_NUM_SEGMENTS;\ + type DWB_OGAM_RAMB_EXP_REGION14_LUT_OFFSET;\ + type DWB_OGAM_RAMB_EXP_REGION14_NUM_SEGMENTS;\ + type DWB_OGAM_RAMB_EXP_REGION15_LUT_OFFSET;\ + type DWB_OGAM_RAMB_EXP_REGION15_NUM_SEGMENTS;\ + type DWB_OGAM_RAMB_EXP_REGION16_LUT_OFFSET;\ + type DWB_OGAM_RAMB_EXP_REGION16_NUM_SEGMENTS;\ + type DWB_OGAM_RAMB_EXP_REGION17_LUT_OFFSET;\ + type DWB_OGAM_RAMB_EXP_REGION17_NUM_SEGMENTS;\ + type DWB_OGAM_RAMB_EXP_REGION18_LUT_OFFSET;\ + type DWB_OGAM_RAMB_EXP_REGION18_NUM_SEGMENTS;\ + type DWB_OGAM_RAMB_EXP_REGION19_LUT_OFFSET;\ + type DWB_OGAM_RAMB_EXP_REGION19_NUM_SEGMENTS;\ + type DWB_OGAM_RAMB_EXP_REGION20_LUT_OFFSET;\ + type DWB_OGAM_RAMB_EXP_REGION20_NUM_SEGMENTS;\ + type DWB_OGAM_RAMB_EXP_REGION21_LUT_OFFSET;\ + type DWB_OGAM_RAMB_EXP_REGION21_NUM_SEGMENTS;\ + type DWB_OGAM_RAMB_EXP_REGION22_LUT_OFFSET;\ + type DWB_OGAM_RAMB_EXP_REGION22_NUM_SEGMENTS;\ + type DWB_OGAM_RAMB_EXP_REGION23_LUT_OFFSET;\ + type DWB_OGAM_RAMB_EXP_REGION23_NUM_SEGMENTS;\ + type DWB_OGAM_RAMB_EXP_REGION24_LUT_OFFSET;\ + type DWB_OGAM_RAMB_EXP_REGION24_NUM_SEGMENTS;\ + type DWB_OGAM_RAMB_EXP_REGION25_LUT_OFFSET;\ + type DWB_OGAM_RAMB_EXP_REGION25_NUM_SEGMENTS;\ + type DWB_OGAM_RAMB_EXP_REGION26_LUT_OFFSET;\ + type DWB_OGAM_RAMB_EXP_REGION26_NUM_SEGMENTS;\ + type DWB_OGAM_RAMB_EXP_REGION27_LUT_OFFSET;\ + type DWB_OGAM_RAMB_EXP_REGION27_NUM_SEGMENTS;\ + type DWB_OGAM_RAMB_EXP_REGION28_LUT_OFFSET;\ + type DWB_OGAM_RAMB_EXP_REGION28_NUM_SEGMENTS;\ + type DWB_OGAM_RAMB_EXP_REGION29_LUT_OFFSET;\ + type DWB_OGAM_RAMB_EXP_REGION29_NUM_SEGMENTS;\ + type DWB_OGAM_RAMB_EXP_REGION30_LUT_OFFSET;\ + type DWB_OGAM_RAMB_EXP_REGION30_NUM_SEGMENTS;\ + type DWB_OGAM_RAMB_EXP_REGION31_LUT_OFFSET;\ + type DWB_OGAM_RAMB_EXP_REGION31_NUM_SEGMENTS;\ + type DWB_OGAM_RAMB_EXP_REGION32_LUT_OFFSET;\ + type DWB_OGAM_RAMB_EXP_REGION32_NUM_SEGMENTS;\ + type DWB_OGAM_RAMB_EXP_REGION33_LUT_OFFSET;\ + type DWB_OGAM_RAMB_EXP_REGION33_NUM_SEGMENTS; + +struct dcn30_dwbc_registers { + /* DCN3AG */ + /* DWB_TOP */ + uint32_t DWB_ENABLE_CLK_CTRL; + uint32_t DWB_MEM_PWR_CTRL; + uint32_t FC_MODE_CTRL; + uint32_t FC_FLOW_CTRL; + uint32_t FC_WINDOW_START; + uint32_t FC_WINDOW_SIZE; + uint32_t FC_SOURCE_SIZE; + uint32_t DWB_UPDATE_CTRL; + uint32_t DWB_CRC_CTRL; + uint32_t DWB_CRC_MASK_R_G; + uint32_t DWB_CRC_MASK_B_A; + uint32_t DWB_CRC_VAL_R_G; + uint32_t DWB_CRC_VAL_B_A; + uint32_t DWB_OUT_CTRL; + uint32_t DWB_MMHUBBUB_BACKPRESSURE_CNT_EN; + uint32_t DWB_MMHUBBUB_BACKPRESSURE_CNT; + uint32_t DWB_HOST_READ_CONTROL; + uint32_t DWB_SOFT_RESET; + + /* DWBSCL */ + uint32_t DWBSCL_COEF_RAM_TAP_SELECT; + uint32_t DWBSCL_COEF_RAM_TAP_DATA; + uint32_t DWBSCL_MODE; + uint32_t DWBSCL_TAP_CONTROL; + uint32_t DWBSCL_HORZ_FILTER_SCALE_RATIO; + uint32_t DWBSCL_HORZ_FILTER_INIT; + uint32_t DWBSCL_VERT_FILTER_SCALE_RATIO; + uint32_t DWBSCL_VERT_FILTER_INIT; + uint32_t DWBSCL_BOUNDARY_CTRL; + uint32_t DWBSCL_DEST_SIZE; + uint32_t DWBSCL_OVERFLOW_STATUS; + uint32_t DWBSCL_OVERFLOW_COUNTER; + + /* DWBCP */ + uint32_t DWB_HDR_MULT_COEF; + uint32_t DWB_GAMUT_REMAP_MODE; + uint32_t DWB_GAMUT_REMAP_COEF_FORMAT; + uint32_t DWB_GAMUT_REMAPA_C11_C12; + uint32_t DWB_GAMUT_REMAPA_C13_C14; + uint32_t DWB_GAMUT_REMAPA_C21_C22; + uint32_t DWB_GAMUT_REMAPA_C23_C24; + uint32_t DWB_GAMUT_REMAPA_C31_C32; + uint32_t DWB_GAMUT_REMAPA_C33_C34; + uint32_t DWB_GAMUT_REMAPB_C11_C12; + uint32_t DWB_GAMUT_REMAPB_C13_C14; + uint32_t DWB_GAMUT_REMAPB_C21_C22; + uint32_t DWB_GAMUT_REMAPB_C23_C24; + uint32_t DWB_GAMUT_REMAPB_C31_C32; + uint32_t DWB_GAMUT_REMAPB_C33_C34; + uint32_t DWB_OGAM_CONTROL; + uint32_t DWB_OGAM_LUT_INDEX; + uint32_t DWB_OGAM_LUT_DATA; + uint32_t DWB_OGAM_LUT_CONTROL; + uint32_t DWB_OGAM_RAMA_START_CNTL_B; + uint32_t DWB_OGAM_RAMA_START_CNTL_G; + uint32_t DWB_OGAM_RAMA_START_CNTL_R; + uint32_t DWB_OGAM_RAMA_START_BASE_CNTL_B; + uint32_t DWB_OGAM_RAMA_START_SLOPE_CNTL_B; + uint32_t DWB_OGAM_RAMA_START_BASE_CNTL_G; + uint32_t DWB_OGAM_RAMA_START_SLOPE_CNTL_G; + uint32_t DWB_OGAM_RAMA_START_BASE_CNTL_R; + uint32_t DWB_OGAM_RAMA_START_SLOPE_CNTL_R; + uint32_t DWB_OGAM_RAMA_END_CNTL1_B; + uint32_t DWB_OGAM_RAMA_END_CNTL2_B; + uint32_t DWB_OGAM_RAMA_END_CNTL1_G; + uint32_t DWB_OGAM_RAMA_END_CNTL2_G; + uint32_t DWB_OGAM_RAMA_END_CNTL1_R; + uint32_t DWB_OGAM_RAMA_END_CNTL2_R; + uint32_t DWB_OGAM_RAMA_OFFSET_B; + uint32_t DWB_OGAM_RAMA_OFFSET_G; + uint32_t DWB_OGAM_RAMA_OFFSET_R; + uint32_t DWB_OGAM_RAMA_REGION_0_1; + uint32_t DWB_OGAM_RAMA_REGION_2_3; + uint32_t DWB_OGAM_RAMA_REGION_4_5; + uint32_t DWB_OGAM_RAMA_REGION_6_7; + uint32_t DWB_OGAM_RAMA_REGION_8_9; + uint32_t DWB_OGAM_RAMA_REGION_10_11; + uint32_t DWB_OGAM_RAMA_REGION_12_13; + uint32_t DWB_OGAM_RAMA_REGION_14_15; + uint32_t DWB_OGAM_RAMA_REGION_16_17; + uint32_t DWB_OGAM_RAMA_REGION_18_19; + uint32_t DWB_OGAM_RAMA_REGION_20_21; + uint32_t DWB_OGAM_RAMA_REGION_22_23; + uint32_t DWB_OGAM_RAMA_REGION_24_25; + uint32_t DWB_OGAM_RAMA_REGION_26_27; + uint32_t DWB_OGAM_RAMA_REGION_28_29; + uint32_t DWB_OGAM_RAMA_REGION_30_31; + uint32_t DWB_OGAM_RAMA_REGION_32_33; + uint32_t DWB_OGAM_RAMB_START_CNTL_B; + uint32_t DWB_OGAM_RAMB_START_CNTL_G; + uint32_t DWB_OGAM_RAMB_START_CNTL_R; + uint32_t DWB_OGAM_RAMB_START_BASE_CNTL_B; + uint32_t DWB_OGAM_RAMB_START_SLOPE_CNTL_B; + uint32_t DWB_OGAM_RAMB_START_BASE_CNTL_G; + uint32_t DWB_OGAM_RAMB_START_SLOPE_CNTL_G; + uint32_t DWB_OGAM_RAMB_START_BASE_CNTL_R; + uint32_t DWB_OGAM_RAMB_START_SLOPE_CNTL_R; + uint32_t DWB_OGAM_RAMB_END_CNTL1_B; + uint32_t DWB_OGAM_RAMB_END_CNTL2_B; + uint32_t DWB_OGAM_RAMB_END_CNTL1_G; + uint32_t DWB_OGAM_RAMB_END_CNTL2_G; + uint32_t DWB_OGAM_RAMB_END_CNTL1_R; + uint32_t DWB_OGAM_RAMB_END_CNTL2_R; + uint32_t DWB_OGAM_RAMB_OFFSET_B; + uint32_t DWB_OGAM_RAMB_OFFSET_G; + uint32_t DWB_OGAM_RAMB_OFFSET_R; + uint32_t DWB_OGAM_RAMB_REGION_0_1; + uint32_t DWB_OGAM_RAMB_REGION_2_3; + uint32_t DWB_OGAM_RAMB_REGION_4_5; + uint32_t DWB_OGAM_RAMB_REGION_6_7; + uint32_t DWB_OGAM_RAMB_REGION_8_9; + uint32_t DWB_OGAM_RAMB_REGION_10_11; + uint32_t DWB_OGAM_RAMB_REGION_12_13; + uint32_t DWB_OGAM_RAMB_REGION_14_15; + uint32_t DWB_OGAM_RAMB_REGION_16_17; + uint32_t DWB_OGAM_RAMB_REGION_18_19; + uint32_t DWB_OGAM_RAMB_REGION_20_21; + uint32_t DWB_OGAM_RAMB_REGION_22_23; + uint32_t DWB_OGAM_RAMB_REGION_24_25; + uint32_t DWB_OGAM_RAMB_REGION_26_27; + uint32_t DWB_OGAM_RAMB_REGION_28_29; + uint32_t DWB_OGAM_RAMB_REGION_30_31; + uint32_t DWB_OGAM_RAMB_REGION_32_33; +}; + +/* Internal enums / structs */ +enum dwbscl_coef_filter_type_sel { + DWBSCL_COEF_RAM_FILTER_TYPE_VERT_RGB = 0, + DWBSCL_COEF_RAM_FILTER_TYPE_HORZ_RGB = 1 +}; + + +struct dcn30_dwbc_mask { + DWBC_REG_FIELD_LIST_DCN3_0(uint32_t); +}; + +struct dcn30_dwbc_shift { + DWBC_REG_FIELD_LIST_DCN3_0(uint8_t); +}; + +struct dcn30_dwbc { + struct dwbc base; + const struct dcn30_dwbc_registers *dwbc_regs; + const struct dcn30_dwbc_shift *dwbc_shift; + const struct dcn30_dwbc_mask *dwbc_mask; +}; + +void dcn30_dwbc_construct(struct dcn30_dwbc *dwbc30, + struct dc_context *ctx, + const struct dcn30_dwbc_registers *dwbc_regs, + const struct dcn30_dwbc_shift *dwbc_shift, + const struct dcn30_dwbc_mask *dwbc_mask, + int inst); + +bool dwb3_enable(struct dwbc *dwbc, struct dc_dwb_params *params); + +bool dwb3_disable(struct dwbc *dwbc); + +bool dwb3_update(struct dwbc *dwbc, struct dc_dwb_params *params); + +bool dwb3_is_enabled(struct dwbc *dwbc); + +void dwb3_set_stereo(struct dwbc *dwbc, + struct dwb_stereo_params *stereo_params); + +void dwb3_set_new_content(struct dwbc *dwbc, + bool is_new_content); + +void dwb3_config_fc(struct dwbc *dwbc, + struct dc_dwb_params *params); + +void dwb3_set_denorm(struct dwbc *dwbc, struct dc_dwb_params *params); + +void dwb3_program_hdr_mult( + struct dwbc *dwbc, + const struct dc_dwb_params *params); + +void dwb3_set_gamut_remap( + struct dwbc *dwbc, + const struct dc_dwb_params *params); + +bool dwb3_ogam_set_input_transfer_func( + struct dwbc *dwbc, + const struct dc_transfer_func *in_transfer_func_dwb_ogam); + +void dwb3_set_host_read_rate_control(struct dwbc *dwbc, bool host_read_delay); +#endif + + diff --git a/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_dwb_cm.c b/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_dwb_cm.c new file mode 100644 index 000000000..701c7d8bc --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_dwb_cm.c @@ -0,0 +1,392 @@ +/* + * Copyright 2020 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 "reg_helper.h" +#include "fixed31_32.h" +#include "resource.h" +#include "basics/conversion.h" +#include "dwb.h" +#include "dcn30_dwb.h" +#include "dcn30_cm_common.h" +#include "dcn10/dcn10_cm_common.h" + + +#define REG(reg)\ + dwbc30->dwbc_regs->reg + +#define CTX \ + dwbc30->base.ctx + +#undef FN +#define FN(reg_name, field_name) \ + dwbc30->dwbc_shift->field_name, dwbc30->dwbc_mask->field_name + +#define TO_DCN30_DWBC(dwbc_base) \ + container_of(dwbc_base, struct dcn30_dwbc, base) + +static void dwb3_get_reg_field_ogam(struct dcn30_dwbc *dwbc30, + struct dcn3_xfer_func_reg *reg) +{ + reg->shifts.field_region_start_base = dwbc30->dwbc_shift->DWB_OGAM_RAMA_EXP_REGION_START_BASE_B; + reg->masks.field_region_start_base = dwbc30->dwbc_mask->DWB_OGAM_RAMA_EXP_REGION_START_BASE_B; + reg->shifts.field_offset = dwbc30->dwbc_shift->DWB_OGAM_RAMA_OFFSET_B; + reg->masks.field_offset = dwbc30->dwbc_mask->DWB_OGAM_RAMA_OFFSET_B; + + reg->shifts.exp_region0_lut_offset = dwbc30->dwbc_shift->DWB_OGAM_RAMA_EXP_REGION0_LUT_OFFSET; + reg->masks.exp_region0_lut_offset = dwbc30->dwbc_mask->DWB_OGAM_RAMA_EXP_REGION0_LUT_OFFSET; + reg->shifts.exp_region0_num_segments = dwbc30->dwbc_shift->DWB_OGAM_RAMA_EXP_REGION0_NUM_SEGMENTS; + reg->masks.exp_region0_num_segments = dwbc30->dwbc_mask->DWB_OGAM_RAMA_EXP_REGION0_NUM_SEGMENTS; + reg->shifts.exp_region1_lut_offset = dwbc30->dwbc_shift->DWB_OGAM_RAMA_EXP_REGION1_LUT_OFFSET; + reg->masks.exp_region1_lut_offset = dwbc30->dwbc_mask->DWB_OGAM_RAMA_EXP_REGION1_LUT_OFFSET; + reg->shifts.exp_region1_num_segments = dwbc30->dwbc_shift->DWB_OGAM_RAMA_EXP_REGION1_NUM_SEGMENTS; + reg->masks.exp_region1_num_segments = dwbc30->dwbc_mask->DWB_OGAM_RAMA_EXP_REGION1_NUM_SEGMENTS; + + reg->shifts.field_region_end = dwbc30->dwbc_shift->DWB_OGAM_RAMA_EXP_REGION_END_B; + reg->masks.field_region_end = dwbc30->dwbc_mask->DWB_OGAM_RAMA_EXP_REGION_END_B; + reg->shifts.field_region_end_slope = dwbc30->dwbc_shift->DWB_OGAM_RAMA_EXP_REGION_END_SLOPE_B; + reg->masks.field_region_end_slope = dwbc30->dwbc_mask->DWB_OGAM_RAMA_EXP_REGION_END_SLOPE_B; + reg->shifts.field_region_end_base = dwbc30->dwbc_shift->DWB_OGAM_RAMA_EXP_REGION_END_BASE_B; + reg->masks.field_region_end_base = dwbc30->dwbc_mask->DWB_OGAM_RAMA_EXP_REGION_END_BASE_B; + reg->shifts.field_region_linear_slope = dwbc30->dwbc_shift->DWB_OGAM_RAMA_EXP_REGION_START_SLOPE_B; + reg->masks.field_region_linear_slope = dwbc30->dwbc_mask->DWB_OGAM_RAMA_EXP_REGION_START_SLOPE_B; + reg->shifts.exp_region_start = dwbc30->dwbc_shift->DWB_OGAM_RAMA_EXP_REGION_START_B; + reg->masks.exp_region_start = dwbc30->dwbc_mask->DWB_OGAM_RAMA_EXP_REGION_START_B; + reg->shifts.exp_resion_start_segment = dwbc30->dwbc_shift->DWB_OGAM_RAMA_EXP_REGION_START_SEGMENT_B; + reg->masks.exp_resion_start_segment = dwbc30->dwbc_mask->DWB_OGAM_RAMA_EXP_REGION_START_SEGMENT_B; +} + +/*program dwb ogam RAM A*/ +static void dwb3_program_ogam_luta_settings( + struct dcn30_dwbc *dwbc30, + const struct pwl_params *params) +{ + struct dcn3_xfer_func_reg gam_regs; + + dwb3_get_reg_field_ogam(dwbc30, &gam_regs); + + gam_regs.start_cntl_b = REG(DWB_OGAM_RAMA_START_CNTL_B); + gam_regs.start_cntl_g = REG(DWB_OGAM_RAMA_START_CNTL_G); + gam_regs.start_cntl_r = REG(DWB_OGAM_RAMA_START_CNTL_R); + gam_regs.start_base_cntl_b = REG(DWB_OGAM_RAMA_START_BASE_CNTL_B); + gam_regs.start_base_cntl_g = REG(DWB_OGAM_RAMA_START_BASE_CNTL_G); + gam_regs.start_base_cntl_r = REG(DWB_OGAM_RAMA_START_BASE_CNTL_R); + gam_regs.start_slope_cntl_b = REG(DWB_OGAM_RAMA_START_SLOPE_CNTL_B); + gam_regs.start_slope_cntl_g = REG(DWB_OGAM_RAMA_START_SLOPE_CNTL_G); + gam_regs.start_slope_cntl_r = REG(DWB_OGAM_RAMA_START_SLOPE_CNTL_R); + gam_regs.start_end_cntl1_b = REG(DWB_OGAM_RAMA_END_CNTL1_B); + gam_regs.start_end_cntl2_b = REG(DWB_OGAM_RAMA_END_CNTL2_B); + gam_regs.start_end_cntl1_g = REG(DWB_OGAM_RAMA_END_CNTL1_G); + gam_regs.start_end_cntl2_g = REG(DWB_OGAM_RAMA_END_CNTL2_G); + gam_regs.start_end_cntl1_r = REG(DWB_OGAM_RAMA_END_CNTL1_R); + gam_regs.start_end_cntl2_r = REG(DWB_OGAM_RAMA_END_CNTL2_R); + gam_regs.offset_b = REG(DWB_OGAM_RAMA_OFFSET_B); + gam_regs.offset_g = REG(DWB_OGAM_RAMA_OFFSET_G); + gam_regs.offset_r = REG(DWB_OGAM_RAMA_OFFSET_R); + gam_regs.region_start = REG(DWB_OGAM_RAMA_REGION_0_1); + gam_regs.region_end = REG(DWB_OGAM_RAMA_REGION_32_33); + /*todo*/ + cm_helper_program_gamcor_xfer_func(dwbc30->base.ctx, params, &gam_regs); +} + +/*program dwb ogam RAM B*/ +static void dwb3_program_ogam_lutb_settings( + struct dcn30_dwbc *dwbc30, + const struct pwl_params *params) +{ + struct dcn3_xfer_func_reg gam_regs; + + dwb3_get_reg_field_ogam(dwbc30, &gam_regs); + + gam_regs.start_cntl_b = REG(DWB_OGAM_RAMB_START_CNTL_B); + gam_regs.start_cntl_g = REG(DWB_OGAM_RAMB_START_CNTL_G); + gam_regs.start_cntl_r = REG(DWB_OGAM_RAMB_START_CNTL_R); + gam_regs.start_base_cntl_b = REG(DWB_OGAM_RAMB_START_BASE_CNTL_B); + gam_regs.start_base_cntl_g = REG(DWB_OGAM_RAMB_START_BASE_CNTL_G); + gam_regs.start_base_cntl_r = REG(DWB_OGAM_RAMB_START_BASE_CNTL_R); + gam_regs.start_slope_cntl_b = REG(DWB_OGAM_RAMB_START_SLOPE_CNTL_B); + gam_regs.start_slope_cntl_g = REG(DWB_OGAM_RAMB_START_SLOPE_CNTL_G); + gam_regs.start_slope_cntl_r = REG(DWB_OGAM_RAMB_START_SLOPE_CNTL_R); + gam_regs.start_end_cntl1_b = REG(DWB_OGAM_RAMB_END_CNTL1_B); + gam_regs.start_end_cntl2_b = REG(DWB_OGAM_RAMB_END_CNTL2_B); + gam_regs.start_end_cntl1_g = REG(DWB_OGAM_RAMB_END_CNTL1_G); + gam_regs.start_end_cntl2_g = REG(DWB_OGAM_RAMB_END_CNTL2_G); + gam_regs.start_end_cntl1_r = REG(DWB_OGAM_RAMB_END_CNTL1_R); + gam_regs.start_end_cntl2_r = REG(DWB_OGAM_RAMB_END_CNTL2_R); + gam_regs.offset_b = REG(DWB_OGAM_RAMB_OFFSET_B); + gam_regs.offset_g = REG(DWB_OGAM_RAMB_OFFSET_G); + gam_regs.offset_r = REG(DWB_OGAM_RAMB_OFFSET_R); + gam_regs.region_start = REG(DWB_OGAM_RAMB_REGION_0_1); + gam_regs.region_end = REG(DWB_OGAM_RAMB_REGION_32_33); + + cm_helper_program_gamcor_xfer_func(dwbc30->base.ctx, params, &gam_regs); +} + +static enum dc_lut_mode dwb3_get_ogam_current( + struct dcn30_dwbc *dwbc30) +{ + enum dc_lut_mode mode; + uint32_t state_mode; + uint32_t ram_select; + + REG_GET_2(DWB_OGAM_CONTROL, + DWB_OGAM_MODE_CURRENT, &state_mode, + DWB_OGAM_SELECT_CURRENT, &ram_select); + + if (state_mode == 0) { + mode = LUT_BYPASS; + } else if (state_mode == 2) { + if (ram_select == 0) + mode = LUT_RAM_A; + else if (ram_select == 1) + mode = LUT_RAM_B; + else + mode = LUT_BYPASS; + } else { + // Reserved value + mode = LUT_BYPASS; + BREAK_TO_DEBUGGER(); + return mode; + } + return mode; +} + +static void dwb3_configure_ogam_lut( + struct dcn30_dwbc *dwbc30, + bool is_ram_a) +{ + REG_UPDATE_2(DWB_OGAM_LUT_CONTROL, + DWB_OGAM_LUT_WRITE_COLOR_MASK, 7, + DWB_OGAM_LUT_HOST_SEL, (is_ram_a == true) ? 0 : 1); + + REG_SET(DWB_OGAM_LUT_INDEX, 0, DWB_OGAM_LUT_INDEX, 0); +} + +static void dwb3_program_ogam_pwl(struct dcn30_dwbc *dwbc30, + const struct pwl_result_data *rgb, + uint32_t num) +{ + uint32_t i; + + uint32_t last_base_value_red = rgb[num-1].red_reg + rgb[num-1].delta_red_reg; + uint32_t last_base_value_green = rgb[num-1].green_reg + rgb[num-1].delta_green_reg; + uint32_t last_base_value_blue = rgb[num-1].blue_reg + rgb[num-1].delta_blue_reg; + + if (is_rgb_equal(rgb, num)) { + for (i = 0 ; i < num; i++) + REG_SET(DWB_OGAM_LUT_DATA, 0, DWB_OGAM_LUT_DATA, rgb[i].red_reg); + + REG_SET(DWB_OGAM_LUT_DATA, 0, DWB_OGAM_LUT_DATA, last_base_value_red); + + } else { + + REG_UPDATE(DWB_OGAM_LUT_CONTROL, + DWB_OGAM_LUT_WRITE_COLOR_MASK, 4); + + for (i = 0 ; i < num; i++) + REG_SET(DWB_OGAM_LUT_DATA, 0, DWB_OGAM_LUT_DATA, rgb[i].red_reg); + + REG_SET(DWB_OGAM_LUT_DATA, 0, DWB_OGAM_LUT_DATA, last_base_value_red); + + REG_SET(DWB_OGAM_LUT_INDEX, 0, DWB_OGAM_LUT_INDEX, 0); + + REG_UPDATE(DWB_OGAM_LUT_CONTROL, + DWB_OGAM_LUT_WRITE_COLOR_MASK, 2); + + for (i = 0 ; i < num; i++) + REG_SET(DWB_OGAM_LUT_DATA, 0, DWB_OGAM_LUT_DATA, rgb[i].green_reg); + + REG_SET(DWB_OGAM_LUT_DATA, 0, DWB_OGAM_LUT_DATA, last_base_value_green); + + REG_SET(DWB_OGAM_LUT_INDEX, 0, DWB_OGAM_LUT_INDEX, 0); + + REG_UPDATE(DWB_OGAM_LUT_CONTROL, + DWB_OGAM_LUT_WRITE_COLOR_MASK, 1); + + for (i = 0 ; i < num; i++) + REG_SET(DWB_OGAM_LUT_DATA, 0, DWB_OGAM_LUT_DATA, rgb[i].blue_reg); + + REG_SET(DWB_OGAM_LUT_DATA, 0, DWB_OGAM_LUT_DATA, last_base_value_blue); + } +} + +static bool dwb3_program_ogam_lut( + struct dcn30_dwbc *dwbc30, + const struct pwl_params *params) +{ + enum dc_lut_mode current_mode; + enum dc_lut_mode next_mode; + + if (params == NULL) { + REG_SET(DWB_OGAM_CONTROL, 0, DWB_OGAM_MODE, 0); + return false; + } + + REG_SET(DWB_OGAM_CONTROL, 0, DWB_OGAM_MODE, 2); + + current_mode = dwb3_get_ogam_current(dwbc30); + if (current_mode == LUT_BYPASS || current_mode == LUT_RAM_A) + next_mode = LUT_RAM_B; + else + next_mode = LUT_RAM_A; + + dwb3_configure_ogam_lut(dwbc30, next_mode == LUT_RAM_A); + + if (next_mode == LUT_RAM_A) + dwb3_program_ogam_luta_settings(dwbc30, params); + else + dwb3_program_ogam_lutb_settings(dwbc30, params); + + dwb3_program_ogam_pwl( + dwbc30, params->rgb_resulted, params->hw_points_num); + + REG_UPDATE(DWB_OGAM_CONTROL, DWB_OGAM_SELECT, next_mode == LUT_RAM_A ? 0 : 1); + + return true; +} + +bool dwb3_ogam_set_input_transfer_func( + struct dwbc *dwbc, + const struct dc_transfer_func *in_transfer_func_dwb_ogam) +{ + struct dcn30_dwbc *dwbc30 = TO_DCN30_DWBC(dwbc); + bool result = false; + struct pwl_params *dwb_ogam_lut = NULL; + + if (in_transfer_func_dwb_ogam == NULL) + return result; + + dwb_ogam_lut = kzalloc(sizeof(*dwb_ogam_lut), GFP_KERNEL); + + if (dwb_ogam_lut) { + cm_helper_translate_curve_to_hw_format(dwbc->ctx, + in_transfer_func_dwb_ogam, + dwb_ogam_lut, false); + + result = dwb3_program_ogam_lut( + dwbc30, + dwb_ogam_lut); + kfree(dwb_ogam_lut); + dwb_ogam_lut = NULL; + } + + return result; +} + +static void dwb3_program_gamut_remap( + struct dwbc *dwbc, + const uint16_t *regval, + enum cm_gamut_coef_format coef_format, + enum cm_gamut_remap_select select) +{ + struct dcn30_dwbc *dwbc30 = TO_DCN30_DWBC(dwbc); + + struct color_matrices_reg gam_regs; + + if (regval == NULL || select == CM_GAMUT_REMAP_MODE_BYPASS) { + REG_SET(DWB_GAMUT_REMAP_MODE, 0, + DWB_GAMUT_REMAP_MODE, 0); + return; + } + + REG_UPDATE(DWB_GAMUT_REMAP_COEF_FORMAT, DWB_GAMUT_REMAP_COEF_FORMAT, coef_format); + + gam_regs.shifts.csc_c11 = dwbc30->dwbc_shift->DWB_GAMUT_REMAPA_C11; + gam_regs.masks.csc_c11 = dwbc30->dwbc_mask->DWB_GAMUT_REMAPA_C11; + gam_regs.shifts.csc_c12 = dwbc30->dwbc_shift->DWB_GAMUT_REMAPA_C12; + gam_regs.masks.csc_c12 = dwbc30->dwbc_mask->DWB_GAMUT_REMAPA_C12; + + switch (select) { + case CM_GAMUT_REMAP_MODE_RAMA_COEFF: + gam_regs.csc_c11_c12 = REG(DWB_GAMUT_REMAPA_C11_C12); + gam_regs.csc_c33_c34 = REG(DWB_GAMUT_REMAPA_C33_C34); + + cm_helper_program_color_matrices( + dwbc30->base.ctx, + regval, + &gam_regs); + break; + case CM_GAMUT_REMAP_MODE_RAMB_COEFF: + gam_regs.csc_c11_c12 = REG(DWB_GAMUT_REMAPB_C11_C12); + gam_regs.csc_c33_c34 = REG(DWB_GAMUT_REMAPB_C33_C34); + + cm_helper_program_color_matrices( + dwbc30->base.ctx, + regval, + &gam_regs); + break; + case CM_GAMUT_REMAP_MODE_RESERVED: + /* should never happen, bug */ + BREAK_TO_DEBUGGER(); + return; + default: + break; + } + + REG_SET(DWB_GAMUT_REMAP_MODE, 0, + DWB_GAMUT_REMAP_MODE, select); + +} + +void dwb3_set_gamut_remap( + struct dwbc *dwbc, + const struct dc_dwb_params *params) +{ + struct dcn30_dwbc *dwbc30 = TO_DCN30_DWBC(dwbc); + struct cm_grph_csc_adjustment adjust = params->csc_params; + int i = 0; + + if (adjust.gamut_adjust_type != CM_GAMUT_ADJUST_TYPE_SW) { + /* Bypass if type is bypass or hw */ + dwb3_program_gamut_remap(dwbc, NULL, adjust.gamut_coef_format, CM_GAMUT_REMAP_MODE_BYPASS); + } else { + struct fixed31_32 arr_matrix[12]; + uint16_t arr_reg_val[12]; + unsigned int current_mode; + + for (i = 0; i < 12; i++) + arr_matrix[i] = adjust.temperature_matrix[i]; + + convert_float_matrix(arr_reg_val, arr_matrix, 12); + + REG_GET(DWB_GAMUT_REMAP_MODE, DWB_GAMUT_REMAP_MODE_CURRENT, ¤t_mode); + + if (current_mode == CM_GAMUT_REMAP_MODE_RAMA_COEFF) { + dwb3_program_gamut_remap(dwbc, arr_reg_val, + adjust.gamut_coef_format, CM_GAMUT_REMAP_MODE_RAMB_COEFF); + } else { + dwb3_program_gamut_remap(dwbc, arr_reg_val, + adjust.gamut_coef_format, CM_GAMUT_REMAP_MODE_RAMA_COEFF); + } + } +} + +void dwb3_program_hdr_mult( + struct dwbc *dwbc, + const struct dc_dwb_params *params) +{ + struct dcn30_dwbc *dwbc30 = TO_DCN30_DWBC(dwbc); + + REG_UPDATE(DWB_HDR_MULT_COEF, DWB_HDR_MULT_COEF, params->hdr_mult); +} diff --git a/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_hubbub.c b/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_hubbub.c new file mode 100644 index 000000000..152c9c573 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_hubbub.c @@ -0,0 +1,473 @@ +/* + * Copyright 2020 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 "reg_helper.h" +#include "dcn30_hubbub.h" + + +#define CTX \ + hubbub1->base.ctx +#define DC_LOGGER \ + hubbub1->base.ctx->logger +#define REG(reg)\ + hubbub1->regs->reg + +#undef FN +#define FN(reg_name, field_name) \ + hubbub1->shifts->field_name, hubbub1->masks->field_name + +#ifdef NUM_VMID +#undef NUM_VMID +#endif +#define NUM_VMID 16 + + +static uint32_t convert_and_clamp( + uint32_t wm_ns, + uint32_t refclk_mhz, + uint32_t clamp_value) +{ + uint32_t ret_val = 0; + ret_val = wm_ns * refclk_mhz; + ret_val /= 1000; + + if (ret_val > clamp_value) + ret_val = clamp_value; + + return ret_val; +} + +int hubbub3_init_dchub_sys_ctx(struct hubbub *hubbub, + struct dcn_hubbub_phys_addr_config *pa_config) +{ + struct dcn20_hubbub *hubbub1 = TO_DCN20_HUBBUB(hubbub); + struct dcn_vmid_page_table_config phys_config; + + REG_SET(DCN_VM_FB_LOCATION_BASE, 0, + FB_BASE, pa_config->system_aperture.fb_base >> 24); + REG_SET(DCN_VM_FB_LOCATION_TOP, 0, + FB_TOP, pa_config->system_aperture.fb_top >> 24); + REG_SET(DCN_VM_FB_OFFSET, 0, + FB_OFFSET, pa_config->system_aperture.fb_offset >> 24); + REG_SET(DCN_VM_AGP_BOT, 0, + AGP_BOT, pa_config->system_aperture.agp_bot >> 24); + REG_SET(DCN_VM_AGP_TOP, 0, + AGP_TOP, pa_config->system_aperture.agp_top >> 24); + REG_SET(DCN_VM_AGP_BASE, 0, + AGP_BASE, pa_config->system_aperture.agp_base >> 24); + + if (pa_config->gart_config.page_table_start_addr != pa_config->gart_config.page_table_end_addr) { + phys_config.page_table_start_addr = pa_config->gart_config.page_table_start_addr >> 12; + phys_config.page_table_end_addr = pa_config->gart_config.page_table_end_addr >> 12; + phys_config.page_table_base_addr = pa_config->gart_config.page_table_base_addr; + phys_config.depth = 0; + phys_config.block_size = 0; + // Init VMID 0 based on PA config + dcn20_vmid_setup(&hubbub1->vmid[0], &phys_config); + } + + return NUM_VMID; +} + +bool hubbub3_program_watermarks( + struct hubbub *hubbub, + struct dcn_watermark_set *watermarks, + unsigned int refclk_mhz, + bool safe_to_lower) +{ + struct dcn20_hubbub *hubbub1 = TO_DCN20_HUBBUB(hubbub); + bool wm_pending = false; + + if (hubbub21_program_urgent_watermarks(hubbub, watermarks, refclk_mhz, safe_to_lower)) + wm_pending = true; + + if (hubbub21_program_stutter_watermarks(hubbub, watermarks, refclk_mhz, safe_to_lower)) + wm_pending = true; + + if (hubbub21_program_pstate_watermarks(hubbub, watermarks, refclk_mhz, safe_to_lower)) + wm_pending = true; + + /* + * The DCHub arbiter has a mechanism to dynamically rate limit the DCHub request stream to the fabric. + * If the memory controller is fully utilized and the DCHub requestors are + * well ahead of their amortized schedule, then it is safe to prevent the next winner + * from being committed and sent to the fabric. + * The utilization of the memory controller is approximated by ensuring that + * the number of outstanding requests is greater than a threshold specified + * by the ARB_MIN_REQ_OUTSTANDING. To determine that the DCHub requestors are well ahead of the amortized schedule, + * the slack of the next winner is compared with the ARB_SAT_LEVEL in DLG RefClk cycles. + * + * TODO: Revisit request limit after figure out right number. request limit for Renoir isn't decided yet, set maximum value (0x1FF) + * to turn off it for now. + */ + REG_SET(DCHUBBUB_ARB_SAT_LEVEL, 0, + DCHUBBUB_ARB_SAT_LEVEL, 60 * refclk_mhz); + REG_UPDATE(DCHUBBUB_ARB_DF_REQ_OUTSTAND, + DCHUBBUB_ARB_MIN_REQ_OUTSTAND, 0x1FF); + + hubbub1_allow_self_refresh_control(hubbub, !hubbub->ctx->dc->debug.disable_stutter); + + return wm_pending; +} + +bool hubbub3_dcc_support_swizzle( + enum swizzle_mode_values swizzle, + unsigned int bytes_per_element, + enum segment_order *segment_order_horz, + enum segment_order *segment_order_vert) +{ + bool standard_swizzle = false; + bool display_swizzle = false; + bool render_swizzle = false; + + switch (swizzle) { + case DC_SW_4KB_S: + case DC_SW_64KB_S: + case DC_SW_VAR_S: + case DC_SW_4KB_S_X: + case DC_SW_64KB_S_X: + case DC_SW_VAR_S_X: + standard_swizzle = true; + break; + case DC_SW_4KB_R: + case DC_SW_64KB_R: + case DC_SW_VAR_R: + case DC_SW_4KB_R_X: + case DC_SW_64KB_R_X: + case DC_SW_VAR_R_X: + render_swizzle = true; + break; + case DC_SW_4KB_D: + case DC_SW_64KB_D: + case DC_SW_VAR_D: + case DC_SW_4KB_D_X: + case DC_SW_64KB_D_X: + case DC_SW_VAR_D_X: + display_swizzle = true; + break; + default: + break; + } + + if (standard_swizzle) { + if (bytes_per_element == 1) { + *segment_order_horz = segment_order__contiguous; + *segment_order_vert = segment_order__na; + return true; + } + if (bytes_per_element == 2) { + *segment_order_horz = segment_order__non_contiguous; + *segment_order_vert = segment_order__contiguous; + return true; + } + if (bytes_per_element == 4) { + *segment_order_horz = segment_order__non_contiguous; + *segment_order_vert = segment_order__contiguous; + return true; + } + if (bytes_per_element == 8) { + *segment_order_horz = segment_order__na; + *segment_order_vert = segment_order__contiguous; + return true; + } + } + if (render_swizzle) { + if (bytes_per_element == 1) { + *segment_order_horz = segment_order__contiguous; + *segment_order_vert = segment_order__na; + return true; + } + if (bytes_per_element == 2) { + *segment_order_horz = segment_order__non_contiguous; + *segment_order_vert = segment_order__contiguous; + return true; + } + if (bytes_per_element == 4) { + *segment_order_horz = segment_order__contiguous; + *segment_order_vert = segment_order__non_contiguous; + return true; + } + if (bytes_per_element == 8) { + *segment_order_horz = segment_order__contiguous; + *segment_order_vert = segment_order__non_contiguous; + return true; + } + } + if (display_swizzle && bytes_per_element == 8) { + *segment_order_horz = segment_order__contiguous; + *segment_order_vert = segment_order__non_contiguous; + return true; + } + + return false; +} + +static void hubbub3_get_blk256_size(unsigned int *blk256_width, unsigned int *blk256_height, + unsigned int bytes_per_element) +{ + /* copied from DML. might want to refactor DML to leverage from DML */ + /* DML : get_blk256_size */ + if (bytes_per_element == 1) { + *blk256_width = 16; + *blk256_height = 16; + } else if (bytes_per_element == 2) { + *blk256_width = 16; + *blk256_height = 8; + } else if (bytes_per_element == 4) { + *blk256_width = 8; + *blk256_height = 8; + } else if (bytes_per_element == 8) { + *blk256_width = 8; + *blk256_height = 4; + } +} + +static void hubbub3_det_request_size( + unsigned int detile_buf_size, + unsigned int height, + unsigned int width, + unsigned int bpe, + bool *req128_horz_wc, + bool *req128_vert_wc) +{ + unsigned int blk256_height = 0; + unsigned int blk256_width = 0; + unsigned int swath_bytes_horz_wc, swath_bytes_vert_wc; + + hubbub3_get_blk256_size(&blk256_width, &blk256_height, bpe); + + swath_bytes_horz_wc = width * blk256_height * bpe; + swath_bytes_vert_wc = height * blk256_width * bpe; + + *req128_horz_wc = (2 * swath_bytes_horz_wc <= detile_buf_size) ? + false : /* full 256B request */ + true; /* half 128b request */ + + *req128_vert_wc = (2 * swath_bytes_vert_wc <= detile_buf_size) ? + false : /* full 256B request */ + true; /* half 128b request */ +} + +bool hubbub3_get_dcc_compression_cap(struct hubbub *hubbub, + const struct dc_dcc_surface_param *input, + struct dc_surface_dcc_cap *output) +{ + struct dc *dc = hubbub->ctx->dc; + /* implement section 1.6.2.1 of DCN1_Programming_Guide.docx */ + enum dcc_control dcc_control; + unsigned int bpe; + enum segment_order segment_order_horz, segment_order_vert; + bool req128_horz_wc, req128_vert_wc; + + memset(output, 0, sizeof(*output)); + + if (dc->debug.disable_dcc == DCC_DISABLE) + return false; + + if (!hubbub->funcs->dcc_support_pixel_format(input->format, + &bpe)) + return false; + + if (!hubbub->funcs->dcc_support_swizzle(input->swizzle_mode, bpe, + &segment_order_horz, &segment_order_vert)) + return false; + + hubbub3_det_request_size(TO_DCN20_HUBBUB(hubbub)->detile_buf_size, + input->surface_size.height, input->surface_size.width, + bpe, &req128_horz_wc, &req128_vert_wc); + + if (!req128_horz_wc && !req128_vert_wc) { + dcc_control = dcc_control__256_256_xxx; + } else if (input->scan == SCAN_DIRECTION_HORIZONTAL) { + if (!req128_horz_wc) + dcc_control = dcc_control__256_256_xxx; + else if (segment_order_horz == segment_order__contiguous) + dcc_control = dcc_control__128_128_xxx; + else + dcc_control = dcc_control__256_64_64; + } else if (input->scan == SCAN_DIRECTION_VERTICAL) { + if (!req128_vert_wc) + dcc_control = dcc_control__256_256_xxx; + else if (segment_order_vert == segment_order__contiguous) + dcc_control = dcc_control__128_128_xxx; + else + dcc_control = dcc_control__256_64_64; + } else { + if ((req128_horz_wc && + segment_order_horz == segment_order__non_contiguous) || + (req128_vert_wc && + segment_order_vert == segment_order__non_contiguous)) + /* access_dir not known, must use most constraining */ + dcc_control = dcc_control__256_64_64; + else + /* reg128 is true for either horz and vert + * but segment_order is contiguous + */ + dcc_control = dcc_control__128_128_xxx; + } + + /* Exception for 64KB_R_X */ + if ((bpe == 2) && (input->swizzle_mode == DC_SW_64KB_R_X)) + dcc_control = dcc_control__128_128_xxx; + + if (dc->debug.disable_dcc == DCC_HALF_REQ_DISALBE && + dcc_control != dcc_control__256_256_xxx) + return false; + + switch (dcc_control) { + case dcc_control__256_256_xxx: + output->grph.rgb.max_uncompressed_blk_size = 256; + output->grph.rgb.max_compressed_blk_size = 256; + output->grph.rgb.independent_64b_blks = false; + output->grph.rgb.dcc_controls.dcc_256_256_unconstrained = 1; + output->grph.rgb.dcc_controls.dcc_256_128_128 = 1; + break; + case dcc_control__128_128_xxx: + output->grph.rgb.max_uncompressed_blk_size = 128; + output->grph.rgb.max_compressed_blk_size = 128; + output->grph.rgb.independent_64b_blks = false; + output->grph.rgb.dcc_controls.dcc_128_128_uncontrained = 1; + output->grph.rgb.dcc_controls.dcc_256_128_128 = 1; + break; + case dcc_control__256_64_64: + output->grph.rgb.max_uncompressed_blk_size = 256; + output->grph.rgb.max_compressed_blk_size = 64; + output->grph.rgb.independent_64b_blks = true; + output->grph.rgb.dcc_controls.dcc_256_64_64 = 1; + break; + case dcc_control__256_128_128: + output->grph.rgb.max_uncompressed_blk_size = 256; + output->grph.rgb.max_compressed_blk_size = 128; + output->grph.rgb.independent_64b_blks = false; + output->grph.rgb.dcc_controls.dcc_256_128_128 = 1; + break; + } + output->capable = true; + output->const_color_support = true; + + return true; +} + +void hubbub3_force_wm_propagate_to_pipes(struct hubbub *hubbub) +{ + struct dcn20_hubbub *hubbub1 = TO_DCN20_HUBBUB(hubbub); + uint32_t refclk_mhz = hubbub->ctx->dc->res_pool->ref_clocks.dchub_ref_clock_inKhz / 1000; + uint32_t prog_wm_value = convert_and_clamp(hubbub1->watermarks.a.urgent_ns, + refclk_mhz, 0x1fffff); + + REG_SET_2(DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_A, 0, + DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_A, prog_wm_value, + DCHUBBUB_ARB_VM_ROW_URGENCY_WATERMARK_A, prog_wm_value); +} + +void hubbub3_force_pstate_change_control(struct hubbub *hubbub, + bool force, bool allow) +{ + struct dcn20_hubbub *hubbub1 = TO_DCN20_HUBBUB(hubbub); + + REG_UPDATE_2(DCHUBBUB_ARB_DRAM_STATE_CNTL, + DCHUBBUB_ARB_ALLOW_PSTATE_CHANGE_FORCE_VALUE, allow, + DCHUBBUB_ARB_ALLOW_PSTATE_CHANGE_FORCE_ENABLE, force); +} + +/* Copy values from WM set A to all other sets */ +void hubbub3_init_watermarks(struct hubbub *hubbub) +{ + struct dcn20_hubbub *hubbub1 = TO_DCN20_HUBBUB(hubbub); + uint32_t reg; + + reg = REG_READ(DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_A); + REG_WRITE(DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_B, reg); + REG_WRITE(DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_C, reg); + REG_WRITE(DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_D, reg); + + reg = REG_READ(DCHUBBUB_ARB_FRAC_URG_BW_FLIP_A); + REG_WRITE(DCHUBBUB_ARB_FRAC_URG_BW_FLIP_B, reg); + REG_WRITE(DCHUBBUB_ARB_FRAC_URG_BW_FLIP_C, reg); + REG_WRITE(DCHUBBUB_ARB_FRAC_URG_BW_FLIP_D, reg); + + reg = REG_READ(DCHUBBUB_ARB_FRAC_URG_BW_NOM_A); + REG_WRITE(DCHUBBUB_ARB_FRAC_URG_BW_NOM_B, reg); + REG_WRITE(DCHUBBUB_ARB_FRAC_URG_BW_NOM_C, reg); + REG_WRITE(DCHUBBUB_ARB_FRAC_URG_BW_NOM_D, reg); + + reg = REG_READ(DCHUBBUB_ARB_REFCYC_PER_TRIP_TO_MEMORY_A); + REG_WRITE(DCHUBBUB_ARB_REFCYC_PER_TRIP_TO_MEMORY_B, reg); + REG_WRITE(DCHUBBUB_ARB_REFCYC_PER_TRIP_TO_MEMORY_C, reg); + REG_WRITE(DCHUBBUB_ARB_REFCYC_PER_TRIP_TO_MEMORY_D, reg); + + reg = REG_READ(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_A); + REG_WRITE(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_B, reg); + REG_WRITE(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_C, reg); + REG_WRITE(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_D, reg); + + reg = REG_READ(DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_A); + REG_WRITE(DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_B, reg); + REG_WRITE(DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_C, reg); + REG_WRITE(DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_D, reg); + + reg = REG_READ(DCHUBBUB_ARB_ALLOW_DRAM_CLK_CHANGE_WATERMARK_A); + REG_WRITE(DCHUBBUB_ARB_ALLOW_DRAM_CLK_CHANGE_WATERMARK_B, reg); + REG_WRITE(DCHUBBUB_ARB_ALLOW_DRAM_CLK_CHANGE_WATERMARK_C, reg); + REG_WRITE(DCHUBBUB_ARB_ALLOW_DRAM_CLK_CHANGE_WATERMARK_D, reg); +} + +static const struct hubbub_funcs hubbub30_funcs = { + .update_dchub = hubbub2_update_dchub, + .init_dchub_sys_ctx = hubbub3_init_dchub_sys_ctx, + .init_vm_ctx = hubbub2_init_vm_ctx, + .dcc_support_swizzle = hubbub3_dcc_support_swizzle, + .dcc_support_pixel_format = hubbub2_dcc_support_pixel_format, + .get_dcc_compression_cap = hubbub3_get_dcc_compression_cap, + .wm_read_state = hubbub21_wm_read_state, + .get_dchub_ref_freq = hubbub2_get_dchub_ref_freq, + .program_watermarks = hubbub3_program_watermarks, + .allow_self_refresh_control = hubbub1_allow_self_refresh_control, + .is_allow_self_refresh_enabled = hubbub1_is_allow_self_refresh_enabled, + .verify_allow_pstate_change_high = hubbub1_verify_allow_pstate_change_high, + .force_wm_propagate_to_pipes = hubbub3_force_wm_propagate_to_pipes, + .force_pstate_change_control = hubbub3_force_pstate_change_control, + .init_watermarks = hubbub3_init_watermarks, + .hubbub_read_state = hubbub2_read_state, +}; + +void hubbub3_construct(struct dcn20_hubbub *hubbub3, + struct dc_context *ctx, + const struct dcn_hubbub_registers *hubbub_regs, + const struct dcn_hubbub_shift *hubbub_shift, + const struct dcn_hubbub_mask *hubbub_mask) +{ + hubbub3->base.ctx = ctx; + hubbub3->base.funcs = &hubbub30_funcs; + hubbub3->regs = hubbub_regs; + hubbub3->shifts = hubbub_shift; + hubbub3->masks = hubbub_mask; + + hubbub3->debug_test_index_pstate = 0xB; + hubbub3->detile_buf_size = 184 * 1024; /* 184KB for DCN3 */ +} + diff --git a/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_hubbub.h b/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_hubbub.h new file mode 100644 index 000000000..7b597908b --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_hubbub.h @@ -0,0 +1,136 @@ +/* + * Copyright 2020 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_HUBBUB_DCN30_H__ +#define __DC_HUBBUB_DCN30_H__ + +#include "dcn21/dcn21_hubbub.h" + +#define HUBBUB_REG_LIST_DCN3AG(id)\ + HUBBUB_REG_LIST_DCN21() + +#define HUBBUB_MASK_SH_LIST_DCN3AG(mask_sh)\ + HUBBUB_MASK_SH_LIST_DCN21(mask_sh) + +#define HUBBUB_REG_LIST_DCN30(id)\ + HUBBUB_REG_LIST_DCN20_COMMON(), \ + HUBBUB_SR_WATERMARK_REG_LIST(), \ + SR(DCHUBBUB_ARB_FRAC_URG_BW_NOM_A),\ + SR(DCHUBBUB_ARB_FRAC_URG_BW_NOM_B),\ + SR(DCHUBBUB_ARB_FRAC_URG_BW_NOM_C),\ + SR(DCHUBBUB_ARB_FRAC_URG_BW_NOM_D),\ + SR(DCHUBBUB_ARB_FRAC_URG_BW_FLIP_A),\ + SR(DCHUBBUB_ARB_FRAC_URG_BW_FLIP_B),\ + SR(DCHUBBUB_ARB_FRAC_URG_BW_FLIP_C),\ + SR(DCHUBBUB_ARB_FRAC_URG_BW_FLIP_D),\ + SR(DCHUBBUB_ARB_REFCYC_PER_TRIP_TO_MEMORY_A),\ + SR(DCHUBBUB_ARB_REFCYC_PER_TRIP_TO_MEMORY_B),\ + SR(DCHUBBUB_ARB_REFCYC_PER_TRIP_TO_MEMORY_C),\ + SR(DCHUBBUB_ARB_REFCYC_PER_TRIP_TO_MEMORY_D) + +#define HUBBUB_MASK_SH_LIST_DCN30(mask_sh)\ + HUBBUB_MASK_SH_LIST_DCN_COMMON(mask_sh), \ + HUBBUB_MASK_SH_LIST_STUTTER(mask_sh), \ + HUBBUB_SF(DCHUBBUB_GLOBAL_TIMER_CNTL, DCHUBBUB_GLOBAL_TIMER_REFDIV, mask_sh), \ + HUBBUB_SF(DCN_VM_FB_LOCATION_BASE, FB_BASE, mask_sh), \ + HUBBUB_SF(DCN_VM_FB_LOCATION_TOP, FB_TOP, mask_sh), \ + HUBBUB_SF(DCN_VM_FB_OFFSET, FB_OFFSET, mask_sh), \ + HUBBUB_SF(DCN_VM_AGP_BOT, AGP_BOT, mask_sh), \ + HUBBUB_SF(DCN_VM_AGP_TOP, AGP_TOP, mask_sh), \ + HUBBUB_SF(DCN_VM_AGP_BASE, AGP_BASE, mask_sh), \ + HUBBUB_SF(DCHUBBUB_ARB_FRAC_URG_BW_FLIP_A, DCHUBBUB_ARB_FRAC_URG_BW_FLIP_A, mask_sh), \ + HUBBUB_SF(DCHUBBUB_ARB_FRAC_URG_BW_FLIP_B, DCHUBBUB_ARB_FRAC_URG_BW_FLIP_B, mask_sh), \ + HUBBUB_SF(DCHUBBUB_ARB_FRAC_URG_BW_FLIP_C, DCHUBBUB_ARB_FRAC_URG_BW_FLIP_C, mask_sh), \ + HUBBUB_SF(DCHUBBUB_ARB_FRAC_URG_BW_FLIP_D, DCHUBBUB_ARB_FRAC_URG_BW_FLIP_D, mask_sh), \ + HUBBUB_SF(DCHUBBUB_ARB_FRAC_URG_BW_NOM_A, DCHUBBUB_ARB_FRAC_URG_BW_NOM_A, mask_sh), \ + HUBBUB_SF(DCHUBBUB_ARB_FRAC_URG_BW_NOM_B, DCHUBBUB_ARB_FRAC_URG_BW_NOM_B, mask_sh), \ + HUBBUB_SF(DCHUBBUB_ARB_FRAC_URG_BW_NOM_C, DCHUBBUB_ARB_FRAC_URG_BW_NOM_C, mask_sh), \ + HUBBUB_SF(DCHUBBUB_ARB_FRAC_URG_BW_NOM_D, DCHUBBUB_ARB_FRAC_URG_BW_NOM_D, mask_sh), \ + HUBBUB_SF(DCHUBBUB_ARB_REFCYC_PER_TRIP_TO_MEMORY_A, DCHUBBUB_ARB_REFCYC_PER_TRIP_TO_MEMORY_A, mask_sh), \ + HUBBUB_SF(DCHUBBUB_ARB_REFCYC_PER_TRIP_TO_MEMORY_B, DCHUBBUB_ARB_REFCYC_PER_TRIP_TO_MEMORY_B, mask_sh), \ + HUBBUB_SF(DCHUBBUB_ARB_REFCYC_PER_TRIP_TO_MEMORY_C, DCHUBBUB_ARB_REFCYC_PER_TRIP_TO_MEMORY_C, mask_sh), \ + HUBBUB_SF(DCHUBBUB_ARB_REFCYC_PER_TRIP_TO_MEMORY_D, DCHUBBUB_ARB_REFCYC_PER_TRIP_TO_MEMORY_D, mask_sh), \ + HUBBUB_SF(DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_A, DCHUBBUB_ARB_VM_ROW_URGENCY_WATERMARK_A, mask_sh), \ + HUBBUB_SF(DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_B, DCHUBBUB_ARB_VM_ROW_URGENCY_WATERMARK_B, mask_sh), \ + HUBBUB_SF(DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_C, DCHUBBUB_ARB_VM_ROW_URGENCY_WATERMARK_C, mask_sh), \ + HUBBUB_SF(DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_D, DCHUBBUB_ARB_VM_ROW_URGENCY_WATERMARK_D, mask_sh), \ + HUBBUB_SF(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_A, DCHUBBUB_ARB_VM_ROW_ALLOW_SR_ENTER_WATERMARK_A, mask_sh), \ + HUBBUB_SF(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_B, DCHUBBUB_ARB_VM_ROW_ALLOW_SR_ENTER_WATERMARK_B, mask_sh), \ + HUBBUB_SF(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_C, DCHUBBUB_ARB_VM_ROW_ALLOW_SR_ENTER_WATERMARK_C, mask_sh), \ + HUBBUB_SF(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_D, DCHUBBUB_ARB_VM_ROW_ALLOW_SR_ENTER_WATERMARK_D, mask_sh), \ + HUBBUB_SF(DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_A, DCHUBBUB_ARB_VM_ROW_ALLOW_SR_EXIT_WATERMARK_A, mask_sh), \ + HUBBUB_SF(DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_B, DCHUBBUB_ARB_VM_ROW_ALLOW_SR_EXIT_WATERMARK_B, mask_sh), \ + HUBBUB_SF(DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_C, DCHUBBUB_ARB_VM_ROW_ALLOW_SR_EXIT_WATERMARK_C, mask_sh), \ + HUBBUB_SF(DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_D, DCHUBBUB_ARB_VM_ROW_ALLOW_SR_EXIT_WATERMARK_D, mask_sh), \ + HUBBUB_SF(DCHUBBUB_ARB_ALLOW_DRAM_CLK_CHANGE_WATERMARK_A, DCHUBBUB_ARB_VM_ROW_ALLOW_DRAM_CLK_CHANGE_WATERMARK_A, mask_sh), \ + HUBBUB_SF(DCHUBBUB_ARB_ALLOW_DRAM_CLK_CHANGE_WATERMARK_B, DCHUBBUB_ARB_VM_ROW_ALLOW_DRAM_CLK_CHANGE_WATERMARK_B, mask_sh), \ + HUBBUB_SF(DCHUBBUB_ARB_ALLOW_DRAM_CLK_CHANGE_WATERMARK_C, DCHUBBUB_ARB_VM_ROW_ALLOW_DRAM_CLK_CHANGE_WATERMARK_C, mask_sh), \ + HUBBUB_SF(DCHUBBUB_ARB_ALLOW_DRAM_CLK_CHANGE_WATERMARK_D, DCHUBBUB_ARB_VM_ROW_ALLOW_DRAM_CLK_CHANGE_WATERMARK_D, mask_sh), \ + HUBBUB_SF(DCN_VM_FAULT_ADDR_MSB, DCN_VM_FAULT_ADDR_MSB, mask_sh), \ + HUBBUB_SF(DCN_VM_FAULT_ADDR_LSB, DCN_VM_FAULT_ADDR_LSB, mask_sh), \ + HUBBUB_SF(DCN_VM_FAULT_CNTL, DCN_VM_ERROR_STATUS_CLEAR, mask_sh), \ + HUBBUB_SF(DCN_VM_FAULT_CNTL, DCN_VM_ERROR_STATUS_MODE, mask_sh), \ + HUBBUB_SF(DCN_VM_FAULT_CNTL, DCN_VM_ERROR_INTERRUPT_ENABLE, mask_sh), \ + HUBBUB_SF(DCN_VM_FAULT_CNTL, DCN_VM_RANGE_FAULT_DISABLE, mask_sh), \ + HUBBUB_SF(DCN_VM_FAULT_CNTL, DCN_VM_PRQ_FAULT_DISABLE, mask_sh), \ + HUBBUB_SF(DCN_VM_FAULT_STATUS, DCN_VM_ERROR_STATUS, mask_sh), \ + HUBBUB_SF(DCN_VM_FAULT_STATUS, DCN_VM_ERROR_VMID, mask_sh), \ + HUBBUB_SF(DCN_VM_FAULT_STATUS, DCN_VM_ERROR_TABLE_LEVEL, mask_sh), \ + HUBBUB_SF(DCN_VM_FAULT_STATUS, DCN_VM_ERROR_PIPE, mask_sh), \ + HUBBUB_SF(DCN_VM_FAULT_STATUS, DCN_VM_ERROR_INTERRUPT_STATUS, mask_sh) + +void hubbub3_construct(struct dcn20_hubbub *hubbub3, + struct dc_context *ctx, + const struct dcn_hubbub_registers *hubbub_regs, + const struct dcn_hubbub_shift *hubbub_shift, + const struct dcn_hubbub_mask *hubbub_mask); + +int hubbub3_init_dchub_sys_ctx(struct hubbub *hubbub, + struct dcn_hubbub_phys_addr_config *pa_config); + +bool hubbub3_dcc_support_swizzle( + enum swizzle_mode_values swizzle, + unsigned int bytes_per_element, + enum segment_order *segment_order_horz, + enum segment_order *segment_order_vert); + +void hubbub3_force_wm_propagate_to_pipes(struct hubbub *hubbub); + +bool hubbub3_get_dcc_compression_cap(struct hubbub *hubbub, + const struct dc_dcc_surface_param *input, + struct dc_surface_dcc_cap *output); + +bool hubbub3_program_watermarks( + struct hubbub *hubbub, + struct dcn_watermark_set *watermarks, + unsigned int refclk_mhz, + bool safe_to_lower); + +void hubbub3_force_pstate_change_control(struct hubbub *hubbub, + bool force, bool allow); + +void hubbub3_init_watermarks(struct hubbub *hubbub); + +#endif diff --git a/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_hubp.c b/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_hubp.c new file mode 100644 index 000000000..dc3e8df70 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_hubp.c @@ -0,0 +1,530 @@ +/* + * Copyright 2020 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 "dcn30_hubp.h" + +#include "dm_services.h" +#include "dce_calcs.h" +#include "reg_helper.h" +#include "basics/conversion.h" +#include "dcn20/dcn20_hubp.h" +#include "dcn21/dcn21_hubp.h" + +#define REG(reg)\ + hubp2->hubp_regs->reg + +#define CTX \ + hubp2->base.ctx + +#undef FN +#define FN(reg_name, field_name) \ + hubp2->hubp_shift->field_name, hubp2->hubp_mask->field_name + +void hubp3_set_vm_system_aperture_settings(struct hubp *hubp, + struct vm_system_aperture_param *apt) +{ + struct dcn20_hubp *hubp2 = TO_DCN20_HUBP(hubp); + + PHYSICAL_ADDRESS_LOC mc_vm_apt_default; + PHYSICAL_ADDRESS_LOC mc_vm_apt_low; + PHYSICAL_ADDRESS_LOC mc_vm_apt_high; + + // The format of default addr is 48:12 of the 48 bit addr + mc_vm_apt_default.quad_part = apt->sys_default.quad_part >> 12; + + // The format of high/low are 48:18 of the 48 bit addr + mc_vm_apt_low.quad_part = apt->sys_low.quad_part >> 18; + mc_vm_apt_high.quad_part = apt->sys_high.quad_part >> 18; + + REG_SET(DCN_VM_SYSTEM_APERTURE_LOW_ADDR, 0, + MC_VM_SYSTEM_APERTURE_LOW_ADDR, mc_vm_apt_low.quad_part); + + REG_SET(DCN_VM_SYSTEM_APERTURE_HIGH_ADDR, 0, + MC_VM_SYSTEM_APERTURE_HIGH_ADDR, mc_vm_apt_high.quad_part); + + REG_SET_2(DCN_VM_MX_L1_TLB_CNTL, 0, + ENABLE_L1_TLB, 1, + SYSTEM_ACCESS_MODE, 0x3); +} + +bool hubp3_program_surface_flip_and_addr( + struct hubp *hubp, + const struct dc_plane_address *address, + bool flip_immediate) +{ + struct dcn20_hubp *hubp2 = TO_DCN20_HUBP(hubp); + + //program flip type + REG_UPDATE(DCSURF_FLIP_CONTROL, + SURFACE_FLIP_TYPE, flip_immediate); + + // Program VMID reg + if (flip_immediate == 0) + REG_UPDATE(VMID_SETTINGS_0, + VMID, address->vmid); + + if (address->type == PLN_ADDR_TYPE_GRPH_STEREO) { + REG_UPDATE(DCSURF_FLIP_CONTROL, SURFACE_FLIP_MODE_FOR_STEREOSYNC, 0); + REG_UPDATE(DCSURF_FLIP_CONTROL, SURFACE_FLIP_IN_STEREOSYNC, 0x1); + + } else { + // turn off stereo if not in stereo + REG_UPDATE(DCSURF_FLIP_CONTROL, SURFACE_FLIP_MODE_FOR_STEREOSYNC, 0x0); + REG_UPDATE(DCSURF_FLIP_CONTROL, SURFACE_FLIP_IN_STEREOSYNC, 0x0); + } + + /* HW automatically latch rest of address register on write to + * DCSURF_PRIMARY_SURFACE_ADDRESS if SURFACE_UPDATE_LOCK is not used + * + * program high first and then the low addr, order matters! + */ + switch (address->type) { + case PLN_ADDR_TYPE_GRAPHICS: + /* DCN1.0 does not support const color + * TODO: program DCHUBBUB_RET_PATH_DCC_CFGx_0/1 + * base on address->grph.dcc_const_color + * x = 0, 2, 4, 6 for pipe 0, 1, 2, 3 for rgb and luma + * x = 1, 3, 5, 7 for pipe 0, 1, 2, 3 for chroma + */ + + if (address->grph.addr.quad_part == 0) + break; + + REG_UPDATE_2(DCSURF_SURFACE_CONTROL, + PRIMARY_SURFACE_TMZ, address->tmz_surface, + PRIMARY_META_SURFACE_TMZ, address->tmz_surface); + + if (address->grph.meta_addr.quad_part != 0) { + REG_SET(DCSURF_PRIMARY_META_SURFACE_ADDRESS_HIGH, 0, + PRIMARY_META_SURFACE_ADDRESS_HIGH, + address->grph.meta_addr.high_part); + + REG_SET(DCSURF_PRIMARY_META_SURFACE_ADDRESS, 0, + PRIMARY_META_SURFACE_ADDRESS, + address->grph.meta_addr.low_part); + } + + REG_SET(DCSURF_PRIMARY_SURFACE_ADDRESS_HIGH, 0, + PRIMARY_SURFACE_ADDRESS_HIGH, + address->grph.addr.high_part); + + REG_SET(DCSURF_PRIMARY_SURFACE_ADDRESS, 0, + PRIMARY_SURFACE_ADDRESS, + address->grph.addr.low_part); + break; + case PLN_ADDR_TYPE_VIDEO_PROGRESSIVE: + if (address->video_progressive.luma_addr.quad_part == 0 + || address->video_progressive.chroma_addr.quad_part == 0) + break; + + REG_UPDATE_4(DCSURF_SURFACE_CONTROL, + PRIMARY_SURFACE_TMZ, address->tmz_surface, + PRIMARY_SURFACE_TMZ_C, address->tmz_surface, + PRIMARY_META_SURFACE_TMZ, address->tmz_surface, + PRIMARY_META_SURFACE_TMZ_C, address->tmz_surface); + + if (address->video_progressive.luma_meta_addr.quad_part != 0) { + REG_SET(DCSURF_PRIMARY_META_SURFACE_ADDRESS_HIGH_C, 0, + PRIMARY_META_SURFACE_ADDRESS_HIGH_C, + address->video_progressive.chroma_meta_addr.high_part); + + REG_SET(DCSURF_PRIMARY_META_SURFACE_ADDRESS_C, 0, + PRIMARY_META_SURFACE_ADDRESS_C, + address->video_progressive.chroma_meta_addr.low_part); + + REG_SET(DCSURF_PRIMARY_META_SURFACE_ADDRESS_HIGH, 0, + PRIMARY_META_SURFACE_ADDRESS_HIGH, + address->video_progressive.luma_meta_addr.high_part); + + REG_SET(DCSURF_PRIMARY_META_SURFACE_ADDRESS, 0, + PRIMARY_META_SURFACE_ADDRESS, + address->video_progressive.luma_meta_addr.low_part); + } + + REG_SET(DCSURF_PRIMARY_SURFACE_ADDRESS_HIGH_C, 0, + PRIMARY_SURFACE_ADDRESS_HIGH_C, + address->video_progressive.chroma_addr.high_part); + + REG_SET(DCSURF_PRIMARY_SURFACE_ADDRESS_C, 0, + PRIMARY_SURFACE_ADDRESS_C, + address->video_progressive.chroma_addr.low_part); + + REG_SET(DCSURF_PRIMARY_SURFACE_ADDRESS_HIGH, 0, + PRIMARY_SURFACE_ADDRESS_HIGH, + address->video_progressive.luma_addr.high_part); + + REG_SET(DCSURF_PRIMARY_SURFACE_ADDRESS, 0, + PRIMARY_SURFACE_ADDRESS, + address->video_progressive.luma_addr.low_part); + break; + case PLN_ADDR_TYPE_GRPH_STEREO: + if (address->grph_stereo.left_addr.quad_part == 0) + break; + if (address->grph_stereo.right_addr.quad_part == 0) + break; + + REG_UPDATE_8(DCSURF_SURFACE_CONTROL, + PRIMARY_SURFACE_TMZ, address->tmz_surface, + PRIMARY_SURFACE_TMZ_C, address->tmz_surface, + PRIMARY_META_SURFACE_TMZ, address->tmz_surface, + PRIMARY_META_SURFACE_TMZ_C, address->tmz_surface, + SECONDARY_SURFACE_TMZ, address->tmz_surface, + SECONDARY_SURFACE_TMZ_C, address->tmz_surface, + SECONDARY_META_SURFACE_TMZ, address->tmz_surface, + SECONDARY_META_SURFACE_TMZ_C, address->tmz_surface); + + if (address->grph_stereo.right_meta_addr.quad_part != 0) { + + REG_SET(DCSURF_SECONDARY_META_SURFACE_ADDRESS_HIGH_C, 0, + SECONDARY_META_SURFACE_ADDRESS_HIGH_C, + address->grph_stereo.right_alpha_meta_addr.high_part); + + REG_SET(DCSURF_SECONDARY_META_SURFACE_ADDRESS_C, 0, + SECONDARY_META_SURFACE_ADDRESS_C, + address->grph_stereo.right_alpha_meta_addr.low_part); + + REG_SET(DCSURF_SECONDARY_META_SURFACE_ADDRESS_HIGH, 0, + SECONDARY_META_SURFACE_ADDRESS_HIGH, + address->grph_stereo.right_meta_addr.high_part); + + REG_SET(DCSURF_SECONDARY_META_SURFACE_ADDRESS, 0, + SECONDARY_META_SURFACE_ADDRESS, + address->grph_stereo.right_meta_addr.low_part); + } + if (address->grph_stereo.left_meta_addr.quad_part != 0) { + + REG_SET(DCSURF_PRIMARY_META_SURFACE_ADDRESS_HIGH_C, 0, + PRIMARY_META_SURFACE_ADDRESS_HIGH_C, + address->grph_stereo.left_alpha_meta_addr.high_part); + + REG_SET(DCSURF_PRIMARY_META_SURFACE_ADDRESS_C, 0, + PRIMARY_META_SURFACE_ADDRESS_C, + address->grph_stereo.left_alpha_meta_addr.low_part); + + REG_SET(DCSURF_PRIMARY_META_SURFACE_ADDRESS_HIGH, 0, + PRIMARY_META_SURFACE_ADDRESS_HIGH, + address->grph_stereo.left_meta_addr.high_part); + + REG_SET(DCSURF_PRIMARY_META_SURFACE_ADDRESS, 0, + PRIMARY_META_SURFACE_ADDRESS, + address->grph_stereo.left_meta_addr.low_part); + } + + REG_SET(DCSURF_SECONDARY_SURFACE_ADDRESS_HIGH_C, 0, + SECONDARY_SURFACE_ADDRESS_HIGH_C, + address->grph_stereo.right_alpha_addr.high_part); + + REG_SET(DCSURF_SECONDARY_SURFACE_ADDRESS_C, 0, + SECONDARY_SURFACE_ADDRESS_C, + address->grph_stereo.right_alpha_addr.low_part); + + REG_SET(DCSURF_SECONDARY_SURFACE_ADDRESS_HIGH, 0, + SECONDARY_SURFACE_ADDRESS_HIGH, + address->grph_stereo.right_addr.high_part); + + REG_SET(DCSURF_SECONDARY_SURFACE_ADDRESS, 0, + SECONDARY_SURFACE_ADDRESS, + address->grph_stereo.right_addr.low_part); + + REG_SET(DCSURF_PRIMARY_SURFACE_ADDRESS_HIGH_C, 0, + PRIMARY_SURFACE_ADDRESS_HIGH_C, + address->grph_stereo.left_alpha_addr.high_part); + + REG_SET(DCSURF_PRIMARY_SURFACE_ADDRESS_C, 0, + PRIMARY_SURFACE_ADDRESS_C, + address->grph_stereo.left_alpha_addr.low_part); + + REG_SET(DCSURF_PRIMARY_SURFACE_ADDRESS_HIGH, 0, + PRIMARY_SURFACE_ADDRESS_HIGH, + address->grph_stereo.left_addr.high_part); + + REG_SET(DCSURF_PRIMARY_SURFACE_ADDRESS, 0, + PRIMARY_SURFACE_ADDRESS, + address->grph_stereo.left_addr.low_part); + break; + case PLN_ADDR_TYPE_RGBEA: + if (address->rgbea.addr.quad_part == 0 + || address->rgbea.alpha_addr.quad_part == 0) + break; + + REG_UPDATE_4(DCSURF_SURFACE_CONTROL, + PRIMARY_SURFACE_TMZ, address->tmz_surface, + PRIMARY_SURFACE_TMZ_C, address->tmz_surface, + PRIMARY_META_SURFACE_TMZ, address->tmz_surface, + PRIMARY_META_SURFACE_TMZ_C, address->tmz_surface); + + if (address->rgbea.meta_addr.quad_part != 0) { + + REG_SET(DCSURF_PRIMARY_META_SURFACE_ADDRESS_HIGH_C, 0, + PRIMARY_META_SURFACE_ADDRESS_HIGH_C, + address->rgbea.alpha_meta_addr.high_part); + + REG_SET(DCSURF_PRIMARY_META_SURFACE_ADDRESS_C, 0, + PRIMARY_META_SURFACE_ADDRESS_C, + address->rgbea.alpha_meta_addr.low_part); + + REG_SET(DCSURF_PRIMARY_META_SURFACE_ADDRESS_HIGH, 0, + PRIMARY_META_SURFACE_ADDRESS_HIGH, + address->rgbea.meta_addr.high_part); + + REG_SET(DCSURF_PRIMARY_META_SURFACE_ADDRESS, 0, + PRIMARY_META_SURFACE_ADDRESS, + address->rgbea.meta_addr.low_part); + } + + REG_SET(DCSURF_PRIMARY_SURFACE_ADDRESS_HIGH_C, 0, + PRIMARY_SURFACE_ADDRESS_HIGH_C, + address->rgbea.alpha_addr.high_part); + + REG_SET(DCSURF_PRIMARY_SURFACE_ADDRESS_C, 0, + PRIMARY_SURFACE_ADDRESS_C, + address->rgbea.alpha_addr.low_part); + + REG_SET(DCSURF_PRIMARY_SURFACE_ADDRESS_HIGH, 0, + PRIMARY_SURFACE_ADDRESS_HIGH, + address->rgbea.addr.high_part); + + REG_SET(DCSURF_PRIMARY_SURFACE_ADDRESS, 0, + PRIMARY_SURFACE_ADDRESS, + address->rgbea.addr.low_part); + break; + default: + BREAK_TO_DEBUGGER(); + break; + } + + hubp->request_address = *address; + + return true; +} + +static void hubp3_program_tiling( + struct dcn20_hubp *hubp2, + const union dc_tiling_info *info, + const enum surface_pixel_format pixel_format) +{ + REG_UPDATE_4(DCSURF_ADDR_CONFIG, + NUM_PIPES, log_2(info->gfx9.num_pipes), + PIPE_INTERLEAVE, info->gfx9.pipe_interleave, + MAX_COMPRESSED_FRAGS, log_2(info->gfx9.max_compressed_frags), + NUM_PKRS, log_2(info->gfx9.num_pkrs)); + + REG_UPDATE_3(DCSURF_TILING_CONFIG, + SW_MODE, info->gfx9.swizzle, + META_LINEAR, info->gfx9.meta_linear, + PIPE_ALIGNED, info->gfx9.pipe_aligned); + +} + +void hubp3_dcc_control(struct hubp *hubp, bool enable, + enum hubp_ind_block_size blk_size) +{ + uint32_t dcc_en = enable ? 1 : 0; + struct dcn20_hubp *hubp2 = TO_DCN20_HUBP(hubp); + + REG_UPDATE_4(DCSURF_SURFACE_CONTROL, + PRIMARY_SURFACE_DCC_EN, dcc_en, + PRIMARY_SURFACE_DCC_IND_BLK, blk_size, + SECONDARY_SURFACE_DCC_EN, dcc_en, + SECONDARY_SURFACE_DCC_IND_BLK, blk_size); +} + +void hubp3_dcc_control_sienna_cichlid(struct hubp *hubp, + struct dc_plane_dcc_param *dcc) +{ + struct dcn20_hubp *hubp2 = TO_DCN20_HUBP(hubp); + + REG_UPDATE_6(DCSURF_SURFACE_CONTROL, + PRIMARY_SURFACE_DCC_EN, dcc->enable, + PRIMARY_SURFACE_DCC_IND_BLK, dcc->dcc_ind_blk, + PRIMARY_SURFACE_DCC_IND_BLK_C, dcc->dcc_ind_blk_c, + SECONDARY_SURFACE_DCC_EN, dcc->enable, + SECONDARY_SURFACE_DCC_IND_BLK, dcc->dcc_ind_blk, + SECONDARY_SURFACE_DCC_IND_BLK_C, dcc->dcc_ind_blk_c); +} + +void hubp3_dmdata_set_attributes( + struct hubp *hubp, + const struct dc_dmdata_attributes *attr) +{ + struct dcn20_hubp *hubp2 = TO_DCN20_HUBP(hubp); + + /*always HW mode */ + REG_UPDATE(DMDATA_CNTL, + DMDATA_MODE, 1); + + /* for DMDATA flip, need to use SURFACE_UPDATE_LOCK */ + REG_UPDATE(DCSURF_FLIP_CONTROL, SURFACE_UPDATE_LOCK, 1); + + /* toggle DMDATA_UPDATED and set repeat and size */ + REG_UPDATE(DMDATA_CNTL, + DMDATA_UPDATED, 0); + REG_UPDATE_3(DMDATA_CNTL, + DMDATA_UPDATED, 1, + DMDATA_REPEAT, attr->dmdata_repeat, + DMDATA_SIZE, attr->dmdata_size); + + /* set DMDATA address */ + REG_WRITE(DMDATA_ADDRESS_LOW, attr->address.low_part); + REG_UPDATE(DMDATA_ADDRESS_HIGH, + DMDATA_ADDRESS_HIGH, attr->address.high_part); + + REG_UPDATE(DCSURF_FLIP_CONTROL, SURFACE_UPDATE_LOCK, 0); + +} + + +void hubp3_program_surface_config( + struct hubp *hubp, + enum surface_pixel_format format, + union dc_tiling_info *tiling_info, + struct plane_size *plane_size, + enum dc_rotation_angle rotation, + struct dc_plane_dcc_param *dcc, + bool horizontal_mirror, + unsigned int compat_level) +{ + struct dcn20_hubp *hubp2 = TO_DCN20_HUBP(hubp); + + hubp3_dcc_control_sienna_cichlid(hubp, dcc); + hubp3_program_tiling(hubp2, tiling_info, format); + hubp2_program_size(hubp, format, plane_size, dcc); + hubp2_program_rotation(hubp, rotation, horizontal_mirror); + hubp2_program_pixel_format(hubp, format); +} + +static void hubp3_program_deadline( + struct hubp *hubp, + struct _vcs_dpi_display_dlg_regs_st *dlg_attr, + struct _vcs_dpi_display_ttu_regs_st *ttu_attr) +{ + struct dcn20_hubp *hubp2 = TO_DCN20_HUBP(hubp); + + hubp2_program_deadline(hubp, dlg_attr, ttu_attr); + REG_UPDATE(DCN_DMDATA_VM_CNTL, + REFCYC_PER_VM_DMDATA, dlg_attr->refcyc_per_vm_dmdata); +} + +void hubp3_read_state(struct hubp *hubp) +{ + struct dcn20_hubp *hubp2 = TO_DCN20_HUBP(hubp); + struct dcn_hubp_state *s = &hubp2->state; + struct _vcs_dpi_display_rq_regs_st *rq_regs = &s->rq_regs; + + hubp2_read_state_common(hubp); + + REG_GET_7(DCHUBP_REQ_SIZE_CONFIG, + CHUNK_SIZE, &rq_regs->rq_regs_l.chunk_size, + MIN_CHUNK_SIZE, &rq_regs->rq_regs_l.min_chunk_size, + META_CHUNK_SIZE, &rq_regs->rq_regs_l.meta_chunk_size, + MIN_META_CHUNK_SIZE, &rq_regs->rq_regs_l.min_meta_chunk_size, + DPTE_GROUP_SIZE, &rq_regs->rq_regs_l.dpte_group_size, + SWATH_HEIGHT, &rq_regs->rq_regs_l.swath_height, + PTE_ROW_HEIGHT_LINEAR, &rq_regs->rq_regs_l.pte_row_height_linear); + + REG_GET_7(DCHUBP_REQ_SIZE_CONFIG_C, + CHUNK_SIZE_C, &rq_regs->rq_regs_c.chunk_size, + MIN_CHUNK_SIZE_C, &rq_regs->rq_regs_c.min_chunk_size, + META_CHUNK_SIZE_C, &rq_regs->rq_regs_c.meta_chunk_size, + MIN_META_CHUNK_SIZE_C, &rq_regs->rq_regs_c.min_meta_chunk_size, + DPTE_GROUP_SIZE_C, &rq_regs->rq_regs_c.dpte_group_size, + SWATH_HEIGHT_C, &rq_regs->rq_regs_c.swath_height, + PTE_ROW_HEIGHT_LINEAR_C, &rq_regs->rq_regs_c.pte_row_height_linear); + +} + +void hubp3_setup( + struct hubp *hubp, + struct _vcs_dpi_display_dlg_regs_st *dlg_attr, + struct _vcs_dpi_display_ttu_regs_st *ttu_attr, + struct _vcs_dpi_display_rq_regs_st *rq_regs, + struct _vcs_dpi_display_pipe_dest_params_st *pipe_dest) +{ + /* otg is locked when this func is called. Register are double buffered. + * disable the requestors is not needed + */ + hubp2_vready_at_or_After_vsync(hubp, pipe_dest); + hubp21_program_requestor(hubp, rq_regs); + hubp3_program_deadline(hubp, dlg_attr, ttu_attr); +} + +void hubp3_init(struct hubp *hubp) +{ + // DEDCN21-133: Inconsistent row starting line for flip between DPTE and Meta + // This is a chicken bit to enable the ECO fix. + + struct dcn20_hubp *hubp2 = TO_DCN20_HUBP(hubp); + //hubp[i].HUBPREQ_DEBUG.HUBPREQ_DEBUG[26] = 1; + REG_WRITE(HUBPREQ_DEBUG, 1 << 26); +} + +static struct hubp_funcs dcn30_hubp_funcs = { + .hubp_enable_tripleBuffer = hubp2_enable_triplebuffer, + .hubp_is_triplebuffer_enabled = hubp2_is_triplebuffer_enabled, + .hubp_program_surface_flip_and_addr = hubp3_program_surface_flip_and_addr, + .hubp_program_surface_config = hubp3_program_surface_config, + .hubp_is_flip_pending = hubp2_is_flip_pending, + .hubp_setup = hubp3_setup, + .hubp_setup_interdependent = hubp2_setup_interdependent, + .hubp_set_vm_system_aperture_settings = hubp3_set_vm_system_aperture_settings, + .set_blank = hubp2_set_blank, + .set_blank_regs = hubp2_set_blank_regs, + .dcc_control = hubp3_dcc_control, + .mem_program_viewport = min_set_viewport, + .set_cursor_attributes = hubp2_cursor_set_attributes, + .set_cursor_position = hubp2_cursor_set_position, + .hubp_clk_cntl = hubp2_clk_cntl, + .hubp_vtg_sel = hubp2_vtg_sel, + .dmdata_set_attributes = hubp3_dmdata_set_attributes, + .dmdata_load = hubp2_dmdata_load, + .dmdata_status_done = hubp2_dmdata_status_done, + .hubp_read_state = hubp3_read_state, + .hubp_clear_underflow = hubp2_clear_underflow, + .hubp_set_flip_control_surface_gsl = hubp2_set_flip_control_surface_gsl, + .hubp_init = hubp3_init, + .hubp_in_blank = hubp1_in_blank, + .hubp_soft_reset = hubp1_soft_reset, + .hubp_set_flip_int = hubp1_set_flip_int, +}; + +bool hubp3_construct( + struct dcn20_hubp *hubp2, + struct dc_context *ctx, + uint32_t inst, + const struct dcn_hubp2_registers *hubp_regs, + const struct dcn_hubp2_shift *hubp_shift, + const struct dcn_hubp2_mask *hubp_mask) +{ + hubp2->base.funcs = &dcn30_hubp_funcs; + hubp2->base.ctx = ctx; + hubp2->hubp_regs = hubp_regs; + hubp2->hubp_shift = hubp_shift; + hubp2->hubp_mask = hubp_mask; + hubp2->base.inst = inst; + hubp2->base.opp_id = OPP_ID_INVALID; + hubp2->base.mpcc_id = 0xf; + + return true; +} diff --git a/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_hubp.h b/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_hubp.h new file mode 100644 index 000000000..8a32772d4 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_hubp.h @@ -0,0 +1,297 @@ +/* + * Copyright 2020 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_HUBP_DCN30_H__ +#define __DC_HUBP_DCN30_H__ + +#include "dcn20/dcn20_hubp.h" +#include "dcn21/dcn21_hubp.h" + +#define HUBP_REG_LIST_DCN30(id)\ + HUBP_REG_LIST_DCN21(id),\ + SRI(DCN_DMDATA_VM_CNTL, HUBPREQ, id) + + +#define HUBP_MASK_SH_LIST_DCN30_BASE(mask_sh)\ + HUBP_MASK_SH_LIST_DCN21_COMMON(mask_sh),\ + HUBP_SF(HUBP0_DCSURF_SURFACE_CONFIG, ALPHA_PLANE_EN, mask_sh),\ + HUBP_SF(HUBPREQ0_DCN_DMDATA_VM_CNTL, REFCYC_PER_VM_DMDATA, mask_sh),\ + HUBP_SF(HUBPREQ0_DCN_DMDATA_VM_CNTL, DMDATA_VM_FAULT_STATUS, mask_sh),\ + HUBP_SF(HUBPREQ0_DCN_DMDATA_VM_CNTL, DMDATA_VM_FAULT_STATUS_CLEAR, mask_sh),\ + HUBP_SF(HUBPREQ0_DCN_DMDATA_VM_CNTL, DMDATA_VM_UNDERFLOW_STATUS, mask_sh),\ + HUBP_SF(HUBPREQ0_DCN_DMDATA_VM_CNTL, DMDATA_VM_LATE_STATUS, mask_sh),\ + HUBP_SF(HUBPREQ0_DCN_DMDATA_VM_CNTL, DMDATA_VM_UNDERFLOW_STATUS_CLEAR, mask_sh),\ + HUBP_SF(HUBPREQ0_DCN_DMDATA_VM_CNTL, DMDATA_VM_DONE, mask_sh),\ + HUBP_SF(HUBP0_DCSURF_ADDR_CONFIG, NUM_PKRS, mask_sh) + + +#define HUBP_MASK_SH_LIST_DCN30(mask_sh)\ + HUBP_SF(HUBPREQ0_DCN_DMDATA_VM_CNTL, REFCYC_PER_VM_DMDATA, mask_sh),\ + HUBP_SF(HUBPREQ0_DCN_DMDATA_VM_CNTL, DMDATA_VM_FAULT_STATUS, mask_sh),\ + HUBP_SF(HUBPREQ0_DCN_DMDATA_VM_CNTL, DMDATA_VM_FAULT_STATUS_CLEAR, mask_sh),\ + HUBP_SF(HUBPREQ0_DCN_DMDATA_VM_CNTL, DMDATA_VM_UNDERFLOW_STATUS, mask_sh),\ + HUBP_SF(HUBPREQ0_DCN_DMDATA_VM_CNTL, DMDATA_VM_LATE_STATUS, mask_sh),\ + HUBP_SF(HUBPREQ0_DCN_DMDATA_VM_CNTL, DMDATA_VM_UNDERFLOW_STATUS_CLEAR, mask_sh),\ + HUBP_SF(HUBPREQ0_DCN_DMDATA_VM_CNTL, DMDATA_VM_DONE, mask_sh),\ + HUBP_SF(HUBP0_DCHUBP_CNTL, HUBP_BLANK_EN, mask_sh),\ + HUBP_SF(HUBP0_DCHUBP_CNTL, HUBP_TTU_DISABLE, mask_sh),\ + HUBP_SF(HUBP0_DCHUBP_CNTL, HUBP_UNDERFLOW_STATUS, mask_sh),\ + HUBP_SF(HUBP0_DCHUBP_CNTL, HUBP_UNDERFLOW_CLEAR, mask_sh),\ + HUBP_SF(HUBP0_DCHUBP_CNTL, HUBP_NO_OUTSTANDING_REQ, mask_sh),\ + HUBP_SF(HUBP0_DCHUBP_CNTL, HUBP_VTG_SEL, mask_sh),\ + HUBP_SF(HUBP0_DCHUBP_CNTL, HUBP_DISABLE, mask_sh),\ + HUBP_SF(HUBP0_DCHUBP_CNTL, HUBP_IN_BLANK, mask_sh),\ + HUBP_SF(HUBP0_DCSURF_ADDR_CONFIG, NUM_PIPES, mask_sh),\ + HUBP_SF(HUBP0_DCSURF_ADDR_CONFIG, PIPE_INTERLEAVE, mask_sh),\ + HUBP_SF(HUBP0_DCSURF_ADDR_CONFIG, MAX_COMPRESSED_FRAGS, mask_sh),\ + HUBP_SF(HUBP0_DCSURF_ADDR_CONFIG, NUM_PKRS, mask_sh),\ + HUBP_SF(HUBP0_DCSURF_TILING_CONFIG, SW_MODE, mask_sh),\ + HUBP_SF(HUBP0_DCSURF_TILING_CONFIG, META_LINEAR, mask_sh),\ + HUBP_SF(HUBP0_DCSURF_TILING_CONFIG, PIPE_ALIGNED, mask_sh),\ + HUBP_SF(HUBPREQ0_DCSURF_SURFACE_PITCH, PITCH, mask_sh),\ + HUBP_SF(HUBPREQ0_DCSURF_SURFACE_PITCH, META_PITCH, mask_sh),\ + HUBP_SF(HUBPREQ0_DCSURF_SURFACE_PITCH_C, PITCH_C, mask_sh),\ + HUBP_SF(HUBPREQ0_DCSURF_SURFACE_PITCH_C, META_PITCH_C, mask_sh),\ + HUBP_SF(HUBP0_DCSURF_SURFACE_CONFIG, SURFACE_PIXEL_FORMAT, mask_sh),\ + HUBP_SF(HUBPREQ0_DCSURF_FLIP_CONTROL, SURFACE_FLIP_TYPE, mask_sh),\ + HUBP_SF(HUBPREQ0_DCSURF_FLIP_CONTROL, SURFACE_FLIP_MODE_FOR_STEREOSYNC, mask_sh),\ + HUBP_SF(HUBPREQ0_DCSURF_FLIP_CONTROL, SURFACE_FLIP_IN_STEREOSYNC, mask_sh),\ + HUBP_SF(HUBPREQ0_DCSURF_FLIP_CONTROL, SURFACE_FLIP_PENDING, mask_sh),\ + HUBP_SF(HUBPREQ0_DCSURF_FLIP_CONTROL, SURFACE_UPDATE_LOCK, mask_sh),\ + HUBP_SF(HUBP0_DCSURF_PRI_VIEWPORT_DIMENSION, PRI_VIEWPORT_WIDTH, mask_sh),\ + HUBP_SF(HUBP0_DCSURF_PRI_VIEWPORT_DIMENSION, PRI_VIEWPORT_HEIGHT, mask_sh),\ + HUBP_SF(HUBP0_DCSURF_PRI_VIEWPORT_START, PRI_VIEWPORT_X_START, mask_sh),\ + HUBP_SF(HUBP0_DCSURF_PRI_VIEWPORT_START, PRI_VIEWPORT_Y_START, mask_sh),\ + HUBP_SF(HUBP0_DCSURF_SEC_VIEWPORT_DIMENSION, SEC_VIEWPORT_WIDTH, mask_sh),\ + HUBP_SF(HUBP0_DCSURF_SEC_VIEWPORT_DIMENSION, SEC_VIEWPORT_HEIGHT, mask_sh),\ + HUBP_SF(HUBP0_DCSURF_SEC_VIEWPORT_START, SEC_VIEWPORT_X_START, mask_sh),\ + HUBP_SF(HUBP0_DCSURF_SEC_VIEWPORT_START, SEC_VIEWPORT_Y_START, mask_sh),\ + HUBP_SF(HUBP0_DCSURF_PRI_VIEWPORT_DIMENSION_C, PRI_VIEWPORT_WIDTH_C, mask_sh),\ + HUBP_SF(HUBP0_DCSURF_PRI_VIEWPORT_DIMENSION_C, PRI_VIEWPORT_HEIGHT_C, mask_sh),\ + HUBP_SF(HUBP0_DCSURF_PRI_VIEWPORT_START_C, PRI_VIEWPORT_X_START_C, mask_sh),\ + HUBP_SF(HUBP0_DCSURF_PRI_VIEWPORT_START_C, PRI_VIEWPORT_Y_START_C, mask_sh),\ + HUBP_SF(HUBP0_DCSURF_SEC_VIEWPORT_DIMENSION_C, SEC_VIEWPORT_WIDTH_C, mask_sh),\ + HUBP_SF(HUBP0_DCSURF_SEC_VIEWPORT_DIMENSION_C, SEC_VIEWPORT_HEIGHT_C, mask_sh),\ + HUBP_SF(HUBP0_DCSURF_SEC_VIEWPORT_START_C, SEC_VIEWPORT_X_START_C, mask_sh),\ + HUBP_SF(HUBP0_DCSURF_SEC_VIEWPORT_START_C, SEC_VIEWPORT_Y_START_C, mask_sh),\ + HUBP_SF(HUBPREQ0_DCSURF_PRIMARY_SURFACE_ADDRESS_HIGH, PRIMARY_SURFACE_ADDRESS_HIGH, mask_sh),\ + HUBP_SF(HUBPREQ0_DCSURF_PRIMARY_SURFACE_ADDRESS, PRIMARY_SURFACE_ADDRESS, mask_sh),\ + HUBP_SF(HUBPREQ0_DCSURF_SECONDARY_SURFACE_ADDRESS_HIGH, SECONDARY_SURFACE_ADDRESS_HIGH, mask_sh),\ + HUBP_SF(HUBPREQ0_DCSURF_SECONDARY_SURFACE_ADDRESS, SECONDARY_SURFACE_ADDRESS, mask_sh),\ + HUBP_SF(HUBPREQ0_DCSURF_PRIMARY_META_SURFACE_ADDRESS_HIGH, PRIMARY_META_SURFACE_ADDRESS_HIGH, mask_sh),\ + HUBP_SF(HUBPREQ0_DCSURF_PRIMARY_META_SURFACE_ADDRESS, PRIMARY_META_SURFACE_ADDRESS, mask_sh),\ + HUBP_SF(HUBPREQ0_DCSURF_SECONDARY_META_SURFACE_ADDRESS_HIGH, SECONDARY_META_SURFACE_ADDRESS_HIGH, mask_sh),\ + HUBP_SF(HUBPREQ0_DCSURF_SECONDARY_META_SURFACE_ADDRESS, SECONDARY_META_SURFACE_ADDRESS, mask_sh),\ + HUBP_SF(HUBPREQ0_DCSURF_PRIMARY_SURFACE_ADDRESS_HIGH_C, PRIMARY_SURFACE_ADDRESS_HIGH_C, mask_sh),\ + HUBP_SF(HUBPREQ0_DCSURF_PRIMARY_SURFACE_ADDRESS_C, PRIMARY_SURFACE_ADDRESS_C, mask_sh),\ + HUBP_SF(HUBPREQ0_DCSURF_SECONDARY_SURFACE_ADDRESS_HIGH_C, SECONDARY_SURFACE_ADDRESS_HIGH_C, mask_sh),\ + HUBP_SF(HUBPREQ0_DCSURF_SECONDARY_SURFACE_ADDRESS_C, SECONDARY_SURFACE_ADDRESS_C, mask_sh),\ + HUBP_SF(HUBPREQ0_DCSURF_PRIMARY_META_SURFACE_ADDRESS_HIGH_C, PRIMARY_META_SURFACE_ADDRESS_HIGH_C, mask_sh),\ + HUBP_SF(HUBPREQ0_DCSURF_PRIMARY_META_SURFACE_ADDRESS_C, PRIMARY_META_SURFACE_ADDRESS_C, mask_sh),\ + HUBP_SF(HUBPREQ0_DCSURF_SECONDARY_META_SURFACE_ADDRESS_HIGH_C, SECONDARY_META_SURFACE_ADDRESS_HIGH_C, mask_sh),\ + HUBP_SF(HUBPREQ0_DCSURF_SECONDARY_META_SURFACE_ADDRESS_C, SECONDARY_META_SURFACE_ADDRESS_C, mask_sh),\ + HUBP_SF(HUBPREQ0_DCSURF_SURFACE_INUSE, SURFACE_INUSE_ADDRESS, mask_sh),\ + HUBP_SF(HUBPREQ0_DCSURF_SURFACE_INUSE_HIGH, SURFACE_INUSE_ADDRESS_HIGH, mask_sh),\ + HUBP_SF(HUBPREQ0_DCSURF_SURFACE_INUSE_C, SURFACE_INUSE_ADDRESS_C, mask_sh),\ + HUBP_SF(HUBPREQ0_DCSURF_SURFACE_INUSE_HIGH_C, SURFACE_INUSE_ADDRESS_HIGH_C, mask_sh),\ + HUBP_SF(HUBPREQ0_DCSURF_SURFACE_EARLIEST_INUSE, SURFACE_EARLIEST_INUSE_ADDRESS, mask_sh),\ + HUBP_SF(HUBPREQ0_DCSURF_SURFACE_EARLIEST_INUSE_HIGH, SURFACE_EARLIEST_INUSE_ADDRESS_HIGH, mask_sh),\ + HUBP_SF(HUBPREQ0_DCSURF_SURFACE_EARLIEST_INUSE_C, SURFACE_EARLIEST_INUSE_ADDRESS_C, mask_sh),\ + HUBP_SF(HUBPREQ0_DCSURF_SURFACE_EARLIEST_INUSE_HIGH_C, SURFACE_EARLIEST_INUSE_ADDRESS_HIGH_C, mask_sh),\ + HUBP_SF(HUBPREQ0_DCSURF_SURFACE_CONTROL, PRIMARY_SURFACE_TMZ, mask_sh),\ + HUBP_SF(HUBPREQ0_DCSURF_SURFACE_CONTROL, PRIMARY_SURFACE_TMZ_C, mask_sh),\ + HUBP_SF(HUBPREQ0_DCSURF_SURFACE_CONTROL, PRIMARY_META_SURFACE_TMZ, mask_sh),\ + HUBP_SF(HUBPREQ0_DCSURF_SURFACE_CONTROL, PRIMARY_META_SURFACE_TMZ_C, mask_sh),\ + HUBP_SF(HUBPREQ0_DCSURF_SURFACE_CONTROL, PRIMARY_SURFACE_DCC_EN, mask_sh),\ + HUBP_SF(HUBPREQ0_DCSURF_SURFACE_CONTROL, PRIMARY_SURFACE_DCC_IND_BLK, mask_sh),\ + HUBP_SF(HUBPREQ0_DCSURF_SURFACE_CONTROL, PRIMARY_SURFACE_DCC_IND_BLK_C, mask_sh),\ + HUBP_SF(HUBPREQ0_DCSURF_SURFACE_CONTROL, SECONDARY_SURFACE_TMZ, mask_sh),\ + HUBP_SF(HUBPREQ0_DCSURF_SURFACE_CONTROL, SECONDARY_SURFACE_TMZ_C, mask_sh),\ + HUBP_SF(HUBPREQ0_DCSURF_SURFACE_CONTROL, SECONDARY_META_SURFACE_TMZ, mask_sh),\ + HUBP_SF(HUBPREQ0_DCSURF_SURFACE_CONTROL, SECONDARY_META_SURFACE_TMZ_C, mask_sh),\ + HUBP_SF(HUBPREQ0_DCSURF_SURFACE_CONTROL, SECONDARY_SURFACE_DCC_EN, mask_sh),\ + HUBP_SF(HUBPREQ0_DCSURF_SURFACE_CONTROL, SECONDARY_SURFACE_DCC_IND_BLK, mask_sh),\ + HUBP_SF(HUBPREQ0_DCSURF_SURFACE_CONTROL, SECONDARY_SURFACE_DCC_IND_BLK_C, mask_sh),\ + HUBP_SF(HUBPREQ0_DCSURF_SURFACE_FLIP_INTERRUPT, SURFACE_FLIP_INT_MASK, mask_sh),\ + HUBP_SF(HUBPRET0_HUBPRET_CONTROL, DET_BUF_PLANE1_BASE_ADDRESS, mask_sh),\ + HUBP_SF(HUBPRET0_HUBPRET_CONTROL, CROSSBAR_SRC_CB_B, mask_sh),\ + HUBP_SF(HUBPRET0_HUBPRET_CONTROL, CROSSBAR_SRC_CR_R, mask_sh),\ + HUBP_SF(HUBPRET0_HUBPRET_CONTROL, CROSSBAR_SRC_Y_G, mask_sh),\ + HUBP_SF(HUBPRET0_HUBPRET_CONTROL, CROSSBAR_SRC_ALPHA, mask_sh),\ + HUBP_SF(HUBPRET0_HUBPRET_CONTROL, PACK_3TO2_ELEMENT_DISABLE, mask_sh),\ + HUBP_SF(HUBPREQ0_DCN_EXPANSION_MODE, DRQ_EXPANSION_MODE, mask_sh),\ + HUBP_SF(HUBPREQ0_DCN_EXPANSION_MODE, PRQ_EXPANSION_MODE, mask_sh),\ + HUBP_SF(HUBPREQ0_DCN_EXPANSION_MODE, MRQ_EXPANSION_MODE, mask_sh),\ + HUBP_SF(HUBPREQ0_DCN_EXPANSION_MODE, CRQ_EXPANSION_MODE, mask_sh),\ + HUBP_SF(HUBP0_DCHUBP_REQ_SIZE_CONFIG, CHUNK_SIZE, mask_sh),\ + HUBP_SF(HUBP0_DCHUBP_REQ_SIZE_CONFIG, MIN_CHUNK_SIZE, mask_sh),\ + HUBP_SF(HUBP0_DCHUBP_REQ_SIZE_CONFIG, META_CHUNK_SIZE, mask_sh),\ + HUBP_SF(HUBP0_DCHUBP_REQ_SIZE_CONFIG, MIN_META_CHUNK_SIZE, mask_sh),\ + HUBP_SF(HUBP0_DCHUBP_REQ_SIZE_CONFIG, DPTE_GROUP_SIZE, mask_sh),\ + HUBP_SF(HUBP0_DCHUBP_REQ_SIZE_CONFIG, SWATH_HEIGHT, mask_sh),\ + HUBP_SF(HUBP0_DCHUBP_REQ_SIZE_CONFIG, PTE_ROW_HEIGHT_LINEAR, mask_sh),\ + HUBP_SF(HUBP0_DCHUBP_REQ_SIZE_CONFIG_C, CHUNK_SIZE_C, mask_sh),\ + HUBP_SF(HUBP0_DCHUBP_REQ_SIZE_CONFIG_C, MIN_CHUNK_SIZE_C, mask_sh),\ + HUBP_SF(HUBP0_DCHUBP_REQ_SIZE_CONFIG_C, META_CHUNK_SIZE_C, mask_sh),\ + HUBP_SF(HUBP0_DCHUBP_REQ_SIZE_CONFIG_C, MIN_META_CHUNK_SIZE_C, mask_sh),\ + HUBP_SF(HUBP0_DCHUBP_REQ_SIZE_CONFIG_C, DPTE_GROUP_SIZE_C, mask_sh),\ + HUBP_SF(HUBP0_DCHUBP_REQ_SIZE_CONFIG_C, SWATH_HEIGHT_C, mask_sh),\ + HUBP_SF(HUBP0_DCHUBP_REQ_SIZE_CONFIG_C, PTE_ROW_HEIGHT_LINEAR_C, mask_sh),\ + HUBP_SF(HUBPREQ0_BLANK_OFFSET_0, REFCYC_H_BLANK_END, mask_sh),\ + HUBP_SF(HUBPREQ0_BLANK_OFFSET_0, DLG_V_BLANK_END, mask_sh),\ + HUBP_SF(HUBPREQ0_BLANK_OFFSET_1, MIN_DST_Y_NEXT_START, mask_sh),\ + HUBP_SF(HUBPREQ0_DST_DIMENSIONS, REFCYC_PER_HTOTAL, mask_sh),\ + HUBP_SF(HUBPREQ0_DST_AFTER_SCALER, REFCYC_X_AFTER_SCALER, mask_sh),\ + HUBP_SF(HUBPREQ0_DST_AFTER_SCALER, DST_Y_AFTER_SCALER, mask_sh),\ + HUBP_SF(HUBPREQ0_VBLANK_PARAMETERS_0, DST_Y_PER_VM_VBLANK, mask_sh),\ + HUBP_SF(HUBPREQ0_VBLANK_PARAMETERS_0, DST_Y_PER_ROW_VBLANK, mask_sh),\ + HUBP_SF(HUBPREQ0_REF_FREQ_TO_PIX_FREQ, REF_FREQ_TO_PIX_FREQ, mask_sh),\ + HUBP_SF(HUBPREQ0_VBLANK_PARAMETERS_1, REFCYC_PER_PTE_GROUP_VBLANK_L, mask_sh),\ + HUBP_SF(HUBPREQ0_VBLANK_PARAMETERS_3, REFCYC_PER_META_CHUNK_VBLANK_L, mask_sh),\ + HUBP_SF(HUBPREQ0_NOM_PARAMETERS_4, DST_Y_PER_META_ROW_NOM_L, mask_sh),\ + HUBP_SF(HUBPREQ0_NOM_PARAMETERS_5, REFCYC_PER_META_CHUNK_NOM_L, mask_sh),\ + HUBP_SF(HUBPREQ0_PER_LINE_DELIVERY_PRE, REFCYC_PER_LINE_DELIVERY_PRE_L, mask_sh),\ + HUBP_SF(HUBPREQ0_PER_LINE_DELIVERY_PRE, REFCYC_PER_LINE_DELIVERY_PRE_C, mask_sh),\ + HUBP_SF(HUBPREQ0_PER_LINE_DELIVERY, REFCYC_PER_LINE_DELIVERY_L, mask_sh),\ + HUBP_SF(HUBPREQ0_PER_LINE_DELIVERY, REFCYC_PER_LINE_DELIVERY_C, mask_sh),\ + HUBP_SF(HUBPREQ0_VBLANK_PARAMETERS_2, REFCYC_PER_PTE_GROUP_VBLANK_C, mask_sh),\ + HUBP_SF(HUBPREQ0_VBLANK_PARAMETERS_4, REFCYC_PER_META_CHUNK_VBLANK_C, mask_sh),\ + HUBP_SF(HUBPREQ0_NOM_PARAMETERS_6, DST_Y_PER_META_ROW_NOM_C, mask_sh),\ + HUBP_SF(HUBPREQ0_NOM_PARAMETERS_7, REFCYC_PER_META_CHUNK_NOM_C, mask_sh),\ + HUBP_SF(HUBPREQ0_DCN_TTU_QOS_WM, QoS_LEVEL_LOW_WM, mask_sh),\ + HUBP_SF(HUBPREQ0_DCN_TTU_QOS_WM, QoS_LEVEL_HIGH_WM, mask_sh),\ + HUBP_SF(HUBPREQ0_DCN_GLOBAL_TTU_CNTL, MIN_TTU_VBLANK, mask_sh),\ + HUBP_SF(HUBPREQ0_DCN_GLOBAL_TTU_CNTL, QoS_LEVEL_FLIP, mask_sh),\ + HUBP_SF(HUBPREQ0_DCN_GLOBAL_TTU_CNTL, ROW_TTU_MODE, mask_sh),\ + HUBP_SF(HUBPREQ0_DCN_SURF0_TTU_CNTL0, REFCYC_PER_REQ_DELIVERY, mask_sh),\ + HUBP_SF(HUBPREQ0_DCN_SURF0_TTU_CNTL0, QoS_LEVEL_FIXED, mask_sh),\ + HUBP_SF(HUBPREQ0_DCN_SURF0_TTU_CNTL0, QoS_RAMP_DISABLE, mask_sh),\ + HUBP_SF(HUBPREQ0_DCN_SURF0_TTU_CNTL1, REFCYC_PER_REQ_DELIVERY_PRE, mask_sh),\ + HUBP_SF(HUBP0_HUBP_CLK_CNTL, HUBP_CLOCK_ENABLE, mask_sh),\ + HUBP_MASK_SH_LIST_DCN_VM(mask_sh),\ + HUBP_SF(HUBP0_DCSURF_SURFACE_CONFIG, ROTATION_ANGLE, mask_sh),\ + HUBP_SF(HUBP0_DCSURF_SURFACE_CONFIG, H_MIRROR_EN, mask_sh),\ + HUBP_SF(HUBP0_DCSURF_SURFACE_CONFIG, ALPHA_PLANE_EN, mask_sh),\ + HUBP_SF(HUBPREQ0_PREFETCH_SETTINGS, DST_Y_PREFETCH, mask_sh),\ + HUBP_SF(HUBPREQ0_PREFETCH_SETTINGS, VRATIO_PREFETCH, mask_sh),\ + HUBP_SF(HUBPREQ0_PREFETCH_SETTINGS_C, VRATIO_PREFETCH_C, mask_sh),\ + HUBP_SF(HUBPREQ0_DCN_VM_SYSTEM_APERTURE_LOW_ADDR, MC_VM_SYSTEM_APERTURE_LOW_ADDR, mask_sh),\ + HUBP_SF(HUBPREQ0_DCN_VM_SYSTEM_APERTURE_HIGH_ADDR, MC_VM_SYSTEM_APERTURE_HIGH_ADDR, mask_sh),\ + HUBP_SF(HUBPREQ0_CURSOR_SETTINGS, CURSOR0_DST_Y_OFFSET, mask_sh), \ + HUBP_SF(HUBPREQ0_CURSOR_SETTINGS, CURSOR0_CHUNK_HDL_ADJUST, mask_sh), \ + HUBP_SF(CURSOR0_0_CURSOR_SURFACE_ADDRESS_HIGH, CURSOR_SURFACE_ADDRESS_HIGH, mask_sh), \ + HUBP_SF(CURSOR0_0_CURSOR_SURFACE_ADDRESS, CURSOR_SURFACE_ADDRESS, mask_sh), \ + HUBP_SF(CURSOR0_0_CURSOR_SIZE, CURSOR_WIDTH, mask_sh), \ + HUBP_SF(CURSOR0_0_CURSOR_SIZE, CURSOR_HEIGHT, mask_sh), \ + HUBP_SF(CURSOR0_0_CURSOR_CONTROL, CURSOR_MODE, mask_sh), \ + HUBP_SF(CURSOR0_0_CURSOR_CONTROL, CURSOR_2X_MAGNIFY, mask_sh), \ + HUBP_SF(CURSOR0_0_CURSOR_CONTROL, CURSOR_PITCH, mask_sh), \ + HUBP_SF(CURSOR0_0_CURSOR_CONTROL, CURSOR_LINES_PER_CHUNK, mask_sh), \ + HUBP_SF(CURSOR0_0_CURSOR_CONTROL, CURSOR_ENABLE, mask_sh), \ + HUBP_SF(CURSOR0_0_CURSOR_POSITION, CURSOR_X_POSITION, mask_sh), \ + HUBP_SF(CURSOR0_0_CURSOR_POSITION, CURSOR_Y_POSITION, mask_sh), \ + HUBP_SF(CURSOR0_0_CURSOR_HOT_SPOT, CURSOR_HOT_SPOT_X, mask_sh), \ + HUBP_SF(CURSOR0_0_CURSOR_HOT_SPOT, CURSOR_HOT_SPOT_Y, mask_sh), \ + HUBP_SF(CURSOR0_0_CURSOR_DST_OFFSET, CURSOR_DST_X_OFFSET, mask_sh), \ + HUBP_SF(CURSOR0_0_DMDATA_ADDRESS_HIGH, DMDATA_ADDRESS_HIGH, mask_sh), \ + HUBP_SF(CURSOR0_0_DMDATA_CNTL, DMDATA_MODE, mask_sh), \ + HUBP_SF(CURSOR0_0_DMDATA_CNTL, DMDATA_UPDATED, mask_sh), \ + HUBP_SF(CURSOR0_0_DMDATA_CNTL, DMDATA_REPEAT, mask_sh), \ + HUBP_SF(CURSOR0_0_DMDATA_CNTL, DMDATA_SIZE, mask_sh), \ + HUBP_SF(CURSOR0_0_DMDATA_SW_CNTL, DMDATA_SW_UPDATED, mask_sh), \ + HUBP_SF(CURSOR0_0_DMDATA_SW_CNTL, DMDATA_SW_REPEAT, mask_sh), \ + HUBP_SF(CURSOR0_0_DMDATA_SW_CNTL, DMDATA_SW_SIZE, mask_sh), \ + HUBP_SF(CURSOR0_0_DMDATA_QOS_CNTL, DMDATA_QOS_MODE, mask_sh), \ + HUBP_SF(CURSOR0_0_DMDATA_QOS_CNTL, DMDATA_QOS_LEVEL, mask_sh), \ + HUBP_SF(CURSOR0_0_DMDATA_QOS_CNTL, DMDATA_DL_DELTA, mask_sh), \ + HUBP_SF(CURSOR0_0_DMDATA_STATUS, DMDATA_DONE, mask_sh),\ + HUBP_SF(HUBPREQ0_FLIP_PARAMETERS_0, DST_Y_PER_VM_FLIP, mask_sh),\ + HUBP_SF(HUBPREQ0_FLIP_PARAMETERS_0, DST_Y_PER_ROW_FLIP, mask_sh),\ + HUBP_SF(HUBPREQ0_FLIP_PARAMETERS_1, REFCYC_PER_PTE_GROUP_FLIP_L, mask_sh),\ + HUBP_SF(HUBPREQ0_FLIP_PARAMETERS_2, REFCYC_PER_META_CHUNK_FLIP_L, mask_sh),\ + HUBP_SF(HUBP0_DCHUBP_CNTL, HUBP_VREADY_AT_OR_AFTER_VSYNC, mask_sh),\ + HUBP_SF(HUBP0_DCHUBP_CNTL, HUBP_DISABLE_STOP_DATA_DURING_VM, mask_sh),\ + HUBP_SF(HUBPREQ0_DCSURF_FLIP_CONTROL, HUBPREQ_MASTER_UPDATE_LOCK_STATUS, mask_sh),\ + HUBP_SF(HUBPREQ0_DCSURF_FLIP_CONTROL2, SURFACE_GSL_ENABLE, mask_sh),\ + HUBP_SF(HUBPREQ0_DCSURF_FLIP_CONTROL2, SURFACE_TRIPLE_BUFFER_ENABLE, mask_sh),\ + HUBP_SF(HUBPREQ0_VMID_SETTINGS_0, VMID, mask_sh),\ + HUBP_SF(HUBPREQ0_FLIP_PARAMETERS_3, REFCYC_PER_VM_GROUP_FLIP, mask_sh),\ + HUBP_SF(HUBPREQ0_FLIP_PARAMETERS_4, REFCYC_PER_VM_REQ_FLIP, mask_sh),\ + HUBP_SF(HUBPREQ0_FLIP_PARAMETERS_5, REFCYC_PER_PTE_GROUP_FLIP_C, mask_sh),\ + HUBP_SF(HUBPREQ0_FLIP_PARAMETERS_6, REFCYC_PER_META_CHUNK_FLIP_C, mask_sh),\ + HUBP_SF(HUBPREQ0_VBLANK_PARAMETERS_5, REFCYC_PER_VM_GROUP_VBLANK, mask_sh),\ + HUBP_SF(HUBPREQ0_VBLANK_PARAMETERS_6, REFCYC_PER_VM_REQ_VBLANK, mask_sh),\ + HUBP_SF(HUBP0_DCHUBP_REQ_SIZE_CONFIG, VM_GROUP_SIZE, mask_sh) + +bool hubp3_construct( + struct dcn20_hubp *hubp2, + struct dc_context *ctx, + uint32_t inst, + const struct dcn_hubp2_registers *hubp_regs, + const struct dcn_hubp2_shift *hubp_shift, + const struct dcn_hubp2_mask *hubp_mask); + +void hubp3_set_vm_system_aperture_settings(struct hubp *hubp, + struct vm_system_aperture_param *apt); + +bool hubp3_program_surface_flip_and_addr( + struct hubp *hubp, + const struct dc_plane_address *address, + bool flip_immediate); + +void hubp3_program_surface_config( + struct hubp *hubp, + enum surface_pixel_format format, + union dc_tiling_info *tiling_info, + struct plane_size *plane_size, + enum dc_rotation_angle rotation, + struct dc_plane_dcc_param *dcc, + bool horizontal_mirror, + unsigned int compat_level); + +void hubp3_setup( + struct hubp *hubp, + struct _vcs_dpi_display_dlg_regs_st *dlg_attr, + struct _vcs_dpi_display_ttu_regs_st *ttu_attr, + struct _vcs_dpi_display_rq_regs_st *rq_regs, + struct _vcs_dpi_display_pipe_dest_params_st *pipe_dest); + +void hubp3_dcc_control(struct hubp *hubp, bool enable, + enum hubp_ind_block_size blk_size); + +void hubp3_dcc_control_sienna_cichlid(struct hubp *hubp, + struct dc_plane_dcc_param *dcc); + +void hubp3_dmdata_set_attributes( + struct hubp *hubp, + const struct dc_dmdata_attributes *attr); + +void hubp3_read_state(struct hubp *hubp); + +void hubp3_init(struct hubp *hubp); + +#endif /* __DC_HUBP_DCN30_H__ */ + + diff --git a/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_hwseq.c b/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_hwseq.c new file mode 100644 index 000000000..72bec33e3 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_hwseq.c @@ -0,0 +1,1001 @@ +/* + * Copyright 2020 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 "dm_helpers.h" +#include "core_types.h" +#include "resource.h" +#include "dcn30_hwseq.h" +#include "dccg.h" +#include "dce/dce_hwseq.h" +#include "dcn30_mpc.h" +#include "dcn30_dpp.h" +#include "dcn10/dcn10_cm_common.h" +#include "dcn30_cm_common.h" +#include "reg_helper.h" +#include "abm.h" +#include "clk_mgr.h" +#include "hubp.h" +#include "dchubbub.h" +#include "timing_generator.h" +#include "opp.h" +#include "ipp.h" +#include "mpc.h" +#include "mcif_wb.h" +#include "dc_dmub_srv.h" +#include "link_hwss.h" +#include "dpcd_defs.h" +#include "../dcn20/dcn20_hwseq.h" +#include "dcn30_resource.h" +#include "inc/dc_link_dp.h" +#include "inc/link_dpcd.h" + + + + +#define DC_LOGGER_INIT(logger) + +#define CTX \ + hws->ctx +#define REG(reg)\ + hws->regs->reg +#define DC_LOGGER \ + dc->ctx->logger + + +#undef FN +#define FN(reg_name, field_name) \ + hws->shifts->field_name, hws->masks->field_name + +bool dcn30_set_blend_lut( + struct pipe_ctx *pipe_ctx, const struct dc_plane_state *plane_state) +{ + struct dpp *dpp_base = pipe_ctx->plane_res.dpp; + bool result = true; + struct pwl_params *blend_lut = NULL; + + if (plane_state->blend_tf) { + if (plane_state->blend_tf->type == TF_TYPE_HWPWL) + blend_lut = &plane_state->blend_tf->pwl; + else if (plane_state->blend_tf->type == TF_TYPE_DISTRIBUTED_POINTS) { + cm3_helper_translate_curve_to_hw_format( + plane_state->blend_tf, &dpp_base->regamma_params, false); + blend_lut = &dpp_base->regamma_params; + } + } + result = dpp_base->funcs->dpp_program_blnd_lut(dpp_base, blend_lut); + + return result; +} + +static bool dcn30_set_mpc_shaper_3dlut(struct pipe_ctx *pipe_ctx, + const struct dc_stream_state *stream) +{ + struct dpp *dpp_base = pipe_ctx->plane_res.dpp; + int mpcc_id = pipe_ctx->plane_res.hubp->inst; + struct mpc *mpc = pipe_ctx->stream_res.opp->ctx->dc->res_pool->mpc; + bool result = false; + int acquired_rmu = 0; + int mpcc_id_projected = 0; + + const struct pwl_params *shaper_lut = NULL; + //get the shaper lut params + if (stream->func_shaper) { + if (stream->func_shaper->type == TF_TYPE_HWPWL) { + shaper_lut = &stream->func_shaper->pwl; + } else if (stream->func_shaper->type == TF_TYPE_DISTRIBUTED_POINTS) { + cm_helper_translate_curve_to_hw_format(stream->ctx, stream->func_shaper, + &dpp_base->shaper_params, true); + shaper_lut = &dpp_base->shaper_params; + } + } + + if (stream->lut3d_func && + stream->lut3d_func->state.bits.initialized == 1 && + stream->lut3d_func->state.bits.rmu_idx_valid == 1) { + if (stream->lut3d_func->state.bits.rmu_mux_num == 0) + mpcc_id_projected = stream->lut3d_func->state.bits.mpc_rmu0_mux; + else if (stream->lut3d_func->state.bits.rmu_mux_num == 1) + mpcc_id_projected = stream->lut3d_func->state.bits.mpc_rmu1_mux; + else if (stream->lut3d_func->state.bits.rmu_mux_num == 2) + mpcc_id_projected = stream->lut3d_func->state.bits.mpc_rmu2_mux; + if (mpcc_id_projected != mpcc_id) + BREAK_TO_DEBUGGER(); + /* find the reason why logical layer assigned a different + * mpcc_id into acquire_post_bldn_3dlut + */ + acquired_rmu = mpc->funcs->acquire_rmu(mpc, mpcc_id, + stream->lut3d_func->state.bits.rmu_mux_num); + if (acquired_rmu != stream->lut3d_func->state.bits.rmu_mux_num) + BREAK_TO_DEBUGGER(); + + result = mpc->funcs->program_3dlut(mpc, &stream->lut3d_func->lut_3d, + stream->lut3d_func->state.bits.rmu_mux_num); + result = mpc->funcs->program_shaper(mpc, shaper_lut, + stream->lut3d_func->state.bits.rmu_mux_num); + } else { + // loop through the available mux and release the requested mpcc_id + mpc->funcs->release_rmu(mpc, mpcc_id); + } + + return result; +} + +bool dcn30_set_input_transfer_func(struct dc *dc, + struct pipe_ctx *pipe_ctx, + const struct dc_plane_state *plane_state) +{ + struct dce_hwseq *hws = dc->hwseq; + struct dpp *dpp_base = pipe_ctx->plane_res.dpp; + enum dc_transfer_func_predefined tf; + bool result = true; + struct pwl_params *params = NULL; + + if (dpp_base == NULL || plane_state == NULL) + return false; + + tf = TRANSFER_FUNCTION_UNITY; + + if (plane_state->in_transfer_func && + plane_state->in_transfer_func->type == TF_TYPE_PREDEFINED) + tf = plane_state->in_transfer_func->tf; + + dpp_base->funcs->dpp_set_pre_degam(dpp_base, tf); + + if (plane_state->in_transfer_func) { + if (plane_state->in_transfer_func->type == TF_TYPE_HWPWL) + params = &plane_state->in_transfer_func->pwl; + else if (plane_state->in_transfer_func->type == TF_TYPE_DISTRIBUTED_POINTS && + cm3_helper_translate_curve_to_hw_format(plane_state->in_transfer_func, + &dpp_base->degamma_params, false)) + params = &dpp_base->degamma_params; + } + + result = dpp_base->funcs->dpp_program_gamcor_lut(dpp_base, params); + + if (pipe_ctx->stream_res.opp && pipe_ctx->stream_res.opp->ctx) { + if (dpp_base->funcs->dpp_program_blnd_lut) + hws->funcs.set_blend_lut(pipe_ctx, plane_state); + if (dpp_base->funcs->dpp_program_shaper_lut && + dpp_base->funcs->dpp_program_3dlut) + hws->funcs.set_shaper_3dlut(pipe_ctx, plane_state); + } + + return result; +} + +bool dcn30_set_output_transfer_func(struct dc *dc, + struct pipe_ctx *pipe_ctx, + const struct dc_stream_state *stream) +{ + int mpcc_id = pipe_ctx->plane_res.hubp->inst; + struct mpc *mpc = pipe_ctx->stream_res.opp->ctx->dc->res_pool->mpc; + struct pwl_params *params = NULL; + bool ret = false; + + /* program OGAM or 3DLUT only for the top pipe*/ + if (pipe_ctx->top_pipe == NULL) { + /*program rmu shaper and 3dlut in MPC*/ + ret = dcn30_set_mpc_shaper_3dlut(pipe_ctx, stream); + if (ret == false && mpc->funcs->set_output_gamma && stream->out_transfer_func) { + if (stream->out_transfer_func->type == TF_TYPE_HWPWL) + params = &stream->out_transfer_func->pwl; + else if (pipe_ctx->stream->out_transfer_func->type == + TF_TYPE_DISTRIBUTED_POINTS && + cm3_helper_translate_curve_to_hw_format( + stream->out_transfer_func, + &mpc->blender_params, false)) + params = &mpc->blender_params; + /* there are no ROM LUTs in OUTGAM */ + if (stream->out_transfer_func->type == TF_TYPE_PREDEFINED) + BREAK_TO_DEBUGGER(); + } + } + + mpc->funcs->set_output_gamma(mpc, mpcc_id, params); + return ret; +} + +static void dcn30_set_writeback( + struct dc *dc, + struct dc_writeback_info *wb_info, + struct dc_state *context) +{ + struct mcif_wb *mcif_wb; + struct mcif_buf_params *mcif_buf_params; + + ASSERT(wb_info->dwb_pipe_inst < MAX_DWB_PIPES); + ASSERT(wb_info->wb_enabled); + ASSERT(wb_info->mpcc_inst >= 0); + ASSERT(wb_info->mpcc_inst < dc->res_pool->mpcc_count); + mcif_wb = dc->res_pool->mcif_wb[wb_info->dwb_pipe_inst]; + mcif_buf_params = &wb_info->mcif_buf_params; + + /* set DWB MPC mux */ + dc->res_pool->mpc->funcs->set_dwb_mux(dc->res_pool->mpc, + wb_info->dwb_pipe_inst, wb_info->mpcc_inst); + /* set MCIF_WB buffer and arbitration configuration */ + mcif_wb->funcs->config_mcif_buf(mcif_wb, mcif_buf_params, wb_info->dwb_params.dest_height); + mcif_wb->funcs->config_mcif_arb(mcif_wb, &context->bw_ctx.bw.dcn.bw_writeback.mcif_wb_arb[wb_info->dwb_pipe_inst]); +} + +void dcn30_update_writeback( + struct dc *dc, + struct dc_writeback_info *wb_info, + struct dc_state *context) +{ + struct dwbc *dwb; + dwb = dc->res_pool->dwbc[wb_info->dwb_pipe_inst]; + DC_LOG_DWB("%s dwb_pipe_inst = %d, mpcc_inst = %d",\ + __func__, wb_info->dwb_pipe_inst,\ + wb_info->mpcc_inst); + + dcn30_set_writeback(dc, wb_info, context); + + /* update DWB */ + dwb->funcs->update(dwb, &wb_info->dwb_params); +} + +bool dcn30_mmhubbub_warmup( + struct dc *dc, + unsigned int num_dwb, + struct dc_writeback_info *wb_info) +{ + struct dwbc *dwb; + struct mcif_wb *mcif_wb; + struct mcif_warmup_params warmup_params = {0}; + unsigned int i, i_buf; + /*make sure there is no active DWB eanbled */ + for (i = 0; i < num_dwb; i++) { + dwb = dc->res_pool->dwbc[wb_info[i].dwb_pipe_inst]; + if (dwb->dwb_is_efc_transition || dwb->dwb_is_drc) { + /*can not do warmup while any dwb enabled*/ + return false; + } + } + + if (wb_info->mcif_warmup_params.p_vmid == 0) + return false; + + /*check whether this is new interface: warmup big buffer once*/ + if (wb_info->mcif_warmup_params.start_address.quad_part != 0 && + wb_info->mcif_warmup_params.region_size != 0) { + /*mmhubbub is shared, so it does not matter which MCIF*/ + mcif_wb = dc->res_pool->mcif_wb[0]; + /*warmup a big chunk of VM buffer at once*/ + warmup_params.start_address.quad_part = wb_info->mcif_warmup_params.start_address.quad_part; + warmup_params.address_increment = wb_info->mcif_warmup_params.region_size; + warmup_params.region_size = wb_info->mcif_warmup_params.region_size; + warmup_params.p_vmid = wb_info->mcif_warmup_params.p_vmid; + + if (warmup_params.address_increment == 0) + warmup_params.address_increment = dc->dml.soc.vmm_page_size_bytes; + + mcif_wb->funcs->warmup_mcif(mcif_wb, &warmup_params); + return true; + } + /*following is the original: warmup each DWB's mcif buffer*/ + for (i = 0; i < num_dwb; i++) { + dwb = dc->res_pool->dwbc[wb_info[i].dwb_pipe_inst]; + mcif_wb = dc->res_pool->mcif_wb[wb_info[i].dwb_pipe_inst]; + /*warmup is for VM mode only*/ + if (wb_info[i].mcif_buf_params.p_vmid == 0) + return false; + + /* Warmup MCIF_WB */ + for (i_buf = 0; i_buf < MCIF_BUF_COUNT; i_buf++) { + warmup_params.start_address.quad_part = wb_info[i].mcif_buf_params.luma_address[i_buf]; + warmup_params.address_increment = dc->dml.soc.vmm_page_size_bytes; + warmup_params.region_size = wb_info[i].mcif_buf_params.luma_pitch * wb_info[i].dwb_params.dest_height; + warmup_params.p_vmid = wb_info[i].mcif_buf_params.p_vmid; + mcif_wb->funcs->warmup_mcif(mcif_wb, &warmup_params); + } + } + return true; +} + +void dcn30_enable_writeback( + struct dc *dc, + struct dc_writeback_info *wb_info, + struct dc_state *context) +{ + struct dwbc *dwb; + struct mcif_wb *mcif_wb; + struct timing_generator *optc; + + dwb = dc->res_pool->dwbc[wb_info->dwb_pipe_inst]; + mcif_wb = dc->res_pool->mcif_wb[wb_info->dwb_pipe_inst]; + + /* set the OPTC source mux */ + optc = dc->res_pool->timing_generators[dwb->otg_inst]; + DC_LOG_DWB("%s dwb_pipe_inst = %d, mpcc_inst = %d",\ + __func__, wb_info->dwb_pipe_inst,\ + wb_info->mpcc_inst); + if (IS_DIAG_DC(dc->ctx->dce_environment)) { + /*till diags switch to warmup interface*/ + dcn30_mmhubbub_warmup(dc, 1, wb_info); + } + /* Update writeback pipe */ + dcn30_set_writeback(dc, wb_info, context); + + /* Enable MCIF_WB */ + mcif_wb->funcs->enable_mcif(mcif_wb); + /* Enable DWB */ + dwb->funcs->enable(dwb, &wb_info->dwb_params); +} + +void dcn30_disable_writeback( + struct dc *dc, + unsigned int dwb_pipe_inst) +{ + struct dwbc *dwb; + struct mcif_wb *mcif_wb; + + ASSERT(dwb_pipe_inst < MAX_DWB_PIPES); + dwb = dc->res_pool->dwbc[dwb_pipe_inst]; + mcif_wb = dc->res_pool->mcif_wb[dwb_pipe_inst]; + DC_LOG_DWB("%s dwb_pipe_inst = %d",\ + __func__, dwb_pipe_inst); + + /* disable DWB */ + dwb->funcs->disable(dwb); + /* disable MCIF */ + mcif_wb->funcs->disable_mcif(mcif_wb); + /* disable MPC DWB mux */ + dc->res_pool->mpc->funcs->disable_dwb_mux(dc->res_pool->mpc, dwb_pipe_inst); +} + +void dcn30_program_all_writeback_pipes_in_tree( + struct dc *dc, + const struct dc_stream_state *stream, + struct dc_state *context) +{ + struct dc_writeback_info wb_info; + struct dwbc *dwb; + struct dc_stream_status *stream_status = NULL; + int i_wb, i_pipe, i_stream; + DC_LOG_DWB("%s", __func__); + + ASSERT(stream); + for (i_stream = 0; i_stream < context->stream_count; i_stream++) { + if (context->streams[i_stream] == stream) { + stream_status = &context->stream_status[i_stream]; + break; + } + } + ASSERT(stream_status); + + ASSERT(stream->num_wb_info <= dc->res_pool->res_cap->num_dwb); + /* For each writeback pipe */ + for (i_wb = 0; i_wb < stream->num_wb_info; i_wb++) { + + /* copy writeback info to local non-const so mpcc_inst can be set */ + wb_info = stream->writeback_info[i_wb]; + if (wb_info.wb_enabled) { + + /* get the MPCC instance for writeback_source_plane */ + wb_info.mpcc_inst = -1; + for (i_pipe = 0; i_pipe < dc->res_pool->pipe_count; i_pipe++) { + struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i_pipe]; + + if (!pipe_ctx->plane_state) + continue; + + if (pipe_ctx->plane_state == wb_info.writeback_source_plane) { + wb_info.mpcc_inst = pipe_ctx->plane_res.mpcc_inst; + break; + } + } + + if (wb_info.mpcc_inst == -1) { + /* Disable writeback pipe and disconnect from MPCC + * if source plane has been removed + */ + dc->hwss.disable_writeback(dc, wb_info.dwb_pipe_inst); + continue; + } + + ASSERT(wb_info.dwb_pipe_inst < dc->res_pool->res_cap->num_dwb); + dwb = dc->res_pool->dwbc[wb_info.dwb_pipe_inst]; + if (dwb->funcs->is_enabled(dwb)) { + /* writeback pipe already enabled, only need to update */ + dc->hwss.update_writeback(dc, &wb_info, context); + } else { + /* Enable writeback pipe and connect to MPCC */ + dc->hwss.enable_writeback(dc, &wb_info, context); + } + } else { + /* Disable writeback pipe and disconnect from MPCC */ + dc->hwss.disable_writeback(dc, wb_info.dwb_pipe_inst); + } + } +} + +void dcn30_init_hw(struct dc *dc) +{ + struct abm **abms = dc->res_pool->multiple_abms; + struct dce_hwseq *hws = dc->hwseq; + struct dc_bios *dcb = dc->ctx->dc_bios; + struct resource_pool *res_pool = dc->res_pool; + int i; + int edp_num; + uint32_t backlight = MAX_BACKLIGHT_LEVEL; + + if (dc->clk_mgr && dc->clk_mgr->funcs->init_clocks) + dc->clk_mgr->funcs->init_clocks(dc->clk_mgr); + + // Initialize the dccg + if (res_pool->dccg->funcs->dccg_init) + res_pool->dccg->funcs->dccg_init(res_pool->dccg); + + if (IS_FPGA_MAXIMUS_DC(dc->ctx->dce_environment)) { + + REG_WRITE(REFCLK_CNTL, 0); + REG_UPDATE(DCHUBBUB_GLOBAL_TIMER_CNTL, DCHUBBUB_GLOBAL_TIMER_ENABLE, 1); + REG_WRITE(DIO_MEM_PWR_CTRL, 0); + + if (!dc->debug.disable_clock_gate) { + /* enable all DCN clock gating */ + REG_WRITE(DCCG_GATE_DISABLE_CNTL, 0); + + REG_WRITE(DCCG_GATE_DISABLE_CNTL2, 0); + + REG_UPDATE(DCFCLK_CNTL, DCFCLK_GATE_DIS, 0); + } + + //Enable ability to power gate / don't force power on permanently + if (hws->funcs.enable_power_gating_plane) + hws->funcs.enable_power_gating_plane(hws, true); + + return; + } + + if (!dcb->funcs->is_accelerated_mode(dcb)) { + hws->funcs.bios_golden_init(dc); + hws->funcs.disable_vga(dc->hwseq); + } + + if (dc->debug.enable_mem_low_power.bits.dmcu) { + // Force ERAM to shutdown if DMCU is not enabled + if (dc->debug.disable_dmcu || dc->config.disable_dmcu) { + REG_UPDATE(DMU_MEM_PWR_CNTL, DMCU_ERAM_MEM_PWR_FORCE, 3); + } + } + + // Set default OPTC memory power states + if (dc->debug.enable_mem_low_power.bits.optc) { + // Shutdown when unassigned and light sleep in VBLANK + REG_SET_2(ODM_MEM_PWR_CTRL3, 0, ODM_MEM_UNASSIGNED_PWR_MODE, 3, ODM_MEM_VBLANK_PWR_MODE, 1); + } + + if (dc->ctx->dc_bios->fw_info_valid) { + res_pool->ref_clocks.xtalin_clock_inKhz = + dc->ctx->dc_bios->fw_info.pll_info.crystal_frequency; + + if (!IS_FPGA_MAXIMUS_DC(dc->ctx->dce_environment)) { + if (res_pool->dccg && res_pool->hubbub) { + + (res_pool->dccg->funcs->get_dccg_ref_freq)(res_pool->dccg, + dc->ctx->dc_bios->fw_info.pll_info.crystal_frequency, + &res_pool->ref_clocks.dccg_ref_clock_inKhz); + + (res_pool->hubbub->funcs->get_dchub_ref_freq)(res_pool->hubbub, + res_pool->ref_clocks.dccg_ref_clock_inKhz, + &res_pool->ref_clocks.dchub_ref_clock_inKhz); + } else { + // Not all ASICs have DCCG sw component + res_pool->ref_clocks.dccg_ref_clock_inKhz = + res_pool->ref_clocks.xtalin_clock_inKhz; + res_pool->ref_clocks.dchub_ref_clock_inKhz = + res_pool->ref_clocks.xtalin_clock_inKhz; + } + } + } else + ASSERT_CRITICAL(false); + + for (i = 0; i < dc->link_count; i++) { + /* Power up AND update implementation according to the + * required signal (which may be different from the + * default signal on connector). + */ + struct dc_link *link = dc->links[i]; + + link->link_enc->funcs->hw_init(link->link_enc); + + /* Check for enabled DIG to identify enabled display */ + if (link->link_enc->funcs->is_dig_enabled && + link->link_enc->funcs->is_dig_enabled(link->link_enc)) { + link->link_status.link_active = true; + if (link->link_enc->funcs->fec_is_active && + link->link_enc->funcs->fec_is_active(link->link_enc)) + link->fec_state = dc_link_fec_enabled; + } + } + + /* Power gate DSCs */ + for (i = 0; i < res_pool->res_cap->num_dsc; i++) + if (hws->funcs.dsc_pg_control != NULL) + hws->funcs.dsc_pg_control(hws, res_pool->dscs[i]->inst, false); + + /* we want to turn off all dp displays before doing detection */ + dc_link_blank_all_dp_displays(dc); + + if (hws->funcs.enable_power_gating_plane) + hws->funcs.enable_power_gating_plane(dc->hwseq, true); + + /* If taking control over from VBIOS, we may want to optimize our first + * mode set, so we need to skip powering down pipes until we know which + * pipes we want to use. + * Otherwise, if taking control is not possible, we need to power + * everything down. + */ + if (dcb->funcs->is_accelerated_mode(dcb) || !dc->config.seamless_boot_edp_requested) { + hws->funcs.init_pipes(dc, dc->current_state); + if (dc->res_pool->hubbub->funcs->allow_self_refresh_control) + dc->res_pool->hubbub->funcs->allow_self_refresh_control(dc->res_pool->hubbub, + !dc->res_pool->hubbub->ctx->dc->debug.disable_stutter); + } + + /* In headless boot cases, DIG may be turned + * on which causes HW/SW discrepancies. + * To avoid this, power down hardware on boot + * if DIG is turned on and seamless boot not enabled + */ + if (!dc->config.seamless_boot_edp_requested) { + struct dc_link *edp_links[MAX_NUM_EDP]; + struct dc_link *edp_link = NULL; + + get_edp_links(dc, edp_links, &edp_num); + if (edp_num) + edp_link = edp_links[0]; + if (edp_link && edp_link->link_enc->funcs->is_dig_enabled && + edp_link->link_enc->funcs->is_dig_enabled(edp_link->link_enc) && + dc->hwss.edp_backlight_control && + dc->hwss.power_down && + dc->hwss.edp_power_control) { + dc->hwss.edp_backlight_control(edp_link, false); + dc->hwss.power_down(dc); + dc->hwss.edp_power_control(edp_link, false); + } else { + for (i = 0; i < dc->link_count; i++) { + struct dc_link *link = dc->links[i]; + + if (link->link_enc->funcs->is_dig_enabled && + link->link_enc->funcs->is_dig_enabled(link->link_enc) && + dc->hwss.power_down) { + dc->hwss.power_down(dc); + break; + } + + } + } + } + + for (i = 0; i < res_pool->audio_count; i++) { + struct audio *audio = res_pool->audios[i]; + + audio->funcs->hw_init(audio); + } + + for (i = 0; i < dc->link_count; i++) { + struct dc_link *link = dc->links[i]; + + if (link->panel_cntl) + backlight = link->panel_cntl->funcs->hw_init(link->panel_cntl); + } + + for (i = 0; i < dc->res_pool->pipe_count; i++) { + if (abms[i] != NULL) + abms[i]->funcs->abm_init(abms[i], backlight); + } + + /* power AFMT HDMI memory TODO: may move to dis/en output save power*/ + REG_WRITE(DIO_MEM_PWR_CTRL, 0); + + if (!dc->debug.disable_clock_gate) { + /* enable all DCN clock gating */ + REG_WRITE(DCCG_GATE_DISABLE_CNTL, 0); + + REG_WRITE(DCCG_GATE_DISABLE_CNTL2, 0); + + REG_UPDATE(DCFCLK_CNTL, DCFCLK_GATE_DIS, 0); + } + + if (!dcb->funcs->is_accelerated_mode(dcb) && dc->res_pool->hubbub->funcs->init_watermarks) + dc->res_pool->hubbub->funcs->init_watermarks(dc->res_pool->hubbub); + + if (dc->clk_mgr->funcs->notify_wm_ranges) + dc->clk_mgr->funcs->notify_wm_ranges(dc->clk_mgr); + + //if softmax is enabled then hardmax will be set by a different call + if (dc->clk_mgr->funcs->set_hard_max_memclk && !dc->clk_mgr->dc_mode_softmax_enabled) + dc->clk_mgr->funcs->set_hard_max_memclk(dc->clk_mgr); + + if (dc->res_pool->hubbub->funcs->force_pstate_change_control) + dc->res_pool->hubbub->funcs->force_pstate_change_control( + dc->res_pool->hubbub, false, false); + if (dc->res_pool->hubbub->funcs->init_crb) + dc->res_pool->hubbub->funcs->init_crb(dc->res_pool->hubbub); + + // Get DMCUB capabilities + dc_dmub_srv_query_caps_cmd(dc->ctx->dmub_srv->dmub); + dc->caps.dmub_caps.psr = dc->ctx->dmub_srv->dmub->feature_caps.psr; + dc->caps.dmub_caps.mclk_sw = dc->ctx->dmub_srv->dmub->feature_caps.fw_assisted_mclk_switch; +} + +void dcn30_set_avmute(struct pipe_ctx *pipe_ctx, bool enable) +{ + if (pipe_ctx == NULL) + return; + + if (dc_is_hdmi_signal(pipe_ctx->stream->signal) && pipe_ctx->stream_res.stream_enc != NULL) + pipe_ctx->stream_res.stream_enc->funcs->set_avmute( + pipe_ctx->stream_res.stream_enc, + enable); +} + +void dcn30_update_info_frame(struct pipe_ctx *pipe_ctx) +{ + bool is_hdmi_tmds; + bool is_dp; + + ASSERT(pipe_ctx->stream); + + if (pipe_ctx->stream_res.stream_enc == NULL) + return; /* this is not root pipe */ + + is_hdmi_tmds = dc_is_hdmi_tmds_signal(pipe_ctx->stream->signal); + is_dp = dc_is_dp_signal(pipe_ctx->stream->signal); + + if (!is_hdmi_tmds && !is_dp) + return; + + if (is_hdmi_tmds) + pipe_ctx->stream_res.stream_enc->funcs->update_hdmi_info_packets( + pipe_ctx->stream_res.stream_enc, + &pipe_ctx->stream_res.encoder_info_frame); + else + pipe_ctx->stream_res.stream_enc->funcs->update_dp_info_packets( + pipe_ctx->stream_res.stream_enc, + &pipe_ctx->stream_res.encoder_info_frame); +} + +void dcn30_program_dmdata_engine(struct pipe_ctx *pipe_ctx) +{ + struct dc_stream_state *stream = pipe_ctx->stream; + struct hubp *hubp = pipe_ctx->plane_res.hubp; + bool enable = false; + struct stream_encoder *stream_enc = pipe_ctx->stream_res.stream_enc; + enum dynamic_metadata_mode mode = dc_is_dp_signal(stream->signal) + ? dmdata_dp + : dmdata_hdmi; + + /* if using dynamic meta, don't set up generic infopackets */ + if (pipe_ctx->stream->dmdata_address.quad_part != 0) { + pipe_ctx->stream_res.encoder_info_frame.hdrsmd.valid = false; + enable = true; + } + + if (!hubp) + return; + + if (!stream_enc || !stream_enc->funcs->set_dynamic_metadata) + return; + + stream_enc->funcs->set_dynamic_metadata(stream_enc, enable, + hubp->inst, mode); +} + +bool dcn30_apply_idle_power_optimizations(struct dc *dc, bool enable) +{ + union dmub_rb_cmd cmd; + uint32_t tmr_delay = 0, tmr_scale = 0; + struct dc_cursor_attributes cursor_attr; + bool cursor_cache_enable = false; + struct dc_stream_state *stream = NULL; + struct dc_plane_state *plane = NULL; + + if (!dc->ctx->dmub_srv) + return false; + + if (enable) { + if (dc->current_state) { + int i; + + /* First, check no-memory-requests case */ + for (i = 0; i < dc->current_state->stream_count; i++) { + if (dc->current_state->stream_status[i].plane_count) + /* Fail eligibility on a visible stream */ + break; + } + + if (i == dc->current_state->stream_count) { + /* Enable no-memory-requests case */ + memset(&cmd, 0, sizeof(cmd)); + cmd.mall.header.type = DMUB_CMD__MALL; + cmd.mall.header.sub_type = DMUB_CMD__MALL_ACTION_NO_DF_REQ; + cmd.mall.header.payload_bytes = sizeof(cmd.mall) - sizeof(cmd.mall.header); + + dc_dmub_srv_cmd_queue(dc->ctx->dmub_srv, &cmd); + dc_dmub_srv_cmd_execute(dc->ctx->dmub_srv); + + return true; + } + + stream = dc->current_state->streams[0]; + plane = (stream ? dc->current_state->stream_status[0].plane_states[0] : NULL); + + if (stream && plane) { + cursor_cache_enable = stream->cursor_position.enable && + plane->address.grph.cursor_cache_addr.quad_part; + cursor_attr = stream->cursor_attributes; + } + + /* + * Second, check MALL eligibility + * + * single display only, single surface only, 8 and 16 bit formats only, no VM, + * do not use MALL for displays that support PSR as they use D0i3.2 in DMCUB FW + * + * TODO: When we implement multi-display, PSR displays will be allowed if there is + * a non-PSR display present, since in that case we can't do D0i3.2 + */ + if (dc->current_state->stream_count == 1 && + stream->link->psr_settings.psr_version == DC_PSR_VERSION_UNSUPPORTED && + dc->current_state->stream_status[0].plane_count == 1 && + plane->format <= SURFACE_PIXEL_FORMAT_GRPH_ABGR16161616F && + plane->format >= SURFACE_PIXEL_FORMAT_GRPH_ARGB8888 && + plane->address.page_table_base.quad_part == 0 && + dc->hwss.does_plane_fit_in_mall && + dc->hwss.does_plane_fit_in_mall(dc, plane, + cursor_cache_enable ? &cursor_attr : NULL)) { + unsigned int v_total = stream->adjust.v_total_max ? + stream->adjust.v_total_max : stream->timing.v_total; + unsigned int refresh_hz = div_u64((unsigned long long) stream->timing.pix_clk_100hz * + 100LL, (v_total * stream->timing.h_total)); + + /* + * one frame time in microsec: + * Delay_Us = 1000000 / refresh + * dynamic_delay_us = 1000000 / refresh + 2 * stutter_period + * + * one frame time modified by 'additional timer percent' (p): + * Delay_Us_modified = dynamic_delay_us + dynamic_delay_us * p / 100 + * = dynamic_delay_us * (1 + p / 100) + * = (1000000 / refresh + 2 * stutter_period) * (100 + p) / 100 + * = (1000000 + 2 * stutter_period * refresh) * (100 + p) / (100 * refresh) + * + * formula for timer duration based on parameters, from regspec: + * dynamic_delay_us = 65.28 * (64 + MallFrameCacheTmrDly) * 2^MallFrameCacheTmrScale + * + * dynamic_delay_us / 65.28 = (64 + MallFrameCacheTmrDly) * 2^MallFrameCacheTmrScale + * (dynamic_delay_us / 65.28) / 2^MallFrameCacheTmrScale = 64 + MallFrameCacheTmrDly + * MallFrameCacheTmrDly = ((dynamic_delay_us / 65.28) / 2^MallFrameCacheTmrScale) - 64 + * = (1000000 + 2 * stutter_period * refresh) * (100 + p) / (100 * refresh) / 65.28 / 2^MallFrameCacheTmrScale - 64 + * = (1000000 + 2 * stutter_period * refresh) * (100 + p) / (refresh * 6528 * 2^MallFrameCacheTmrScale) - 64 + * + * need to round up the result of the division before the subtraction + */ + unsigned int denom = refresh_hz * 6528; + unsigned int stutter_period = dc->current_state->perf_params.stutter_period_us; + + tmr_delay = div_u64(((1000000LL + 2 * stutter_period * refresh_hz) * + (100LL + dc->debug.mall_additional_timer_percent) + denom - 1), + denom) - 64LL; + + /* In some cases the stutter period is really big (tiny modes) in these + * cases MALL cant be enabled, So skip these cases to avoid a ASSERT() + * + * We can check if stutter_period is more than 1/10th the frame time to + * consider if we can actually meet the range of hysteresis timer + */ + if (stutter_period > 100000/refresh_hz) + return false; + + /* scale should be increased until it fits into 6 bits */ + while (tmr_delay & ~0x3F) { + tmr_scale++; + + if (tmr_scale > 3) { + /* Delay exceeds range of hysteresis timer */ + ASSERT(false); + return false; + } + + denom *= 2; + tmr_delay = div_u64(((1000000LL + 2 * stutter_period * refresh_hz) * + (100LL + dc->debug.mall_additional_timer_percent) + denom - 1), + denom) - 64LL; + } + + /* Copy HW cursor */ + if (cursor_cache_enable) { + memset(&cmd, 0, sizeof(cmd)); + cmd.mall.header.type = DMUB_CMD__MALL; + cmd.mall.header.sub_type = DMUB_CMD__MALL_ACTION_COPY_CURSOR; + cmd.mall.header.payload_bytes = + sizeof(cmd.mall) - sizeof(cmd.mall.header); + + switch (cursor_attr.color_format) { + case CURSOR_MODE_MONO: + cmd.mall.cursor_bpp = 2; + break; + case CURSOR_MODE_COLOR_1BIT_AND: + case CURSOR_MODE_COLOR_PRE_MULTIPLIED_ALPHA: + case CURSOR_MODE_COLOR_UN_PRE_MULTIPLIED_ALPHA: + cmd.mall.cursor_bpp = 32; + break; + + case CURSOR_MODE_COLOR_64BIT_FP_PRE_MULTIPLIED: + case CURSOR_MODE_COLOR_64BIT_FP_UN_PRE_MULTIPLIED: + cmd.mall.cursor_bpp = 64; + break; + } + + cmd.mall.cursor_copy_src.quad_part = cursor_attr.address.quad_part; + cmd.mall.cursor_copy_dst.quad_part = + (plane->address.grph.cursor_cache_addr.quad_part + 2047) & ~2047; + cmd.mall.cursor_width = cursor_attr.width; + cmd.mall.cursor_height = cursor_attr.height; + cmd.mall.cursor_pitch = cursor_attr.pitch; + + dc_dmub_srv_cmd_queue(dc->ctx->dmub_srv, &cmd); + dc_dmub_srv_cmd_execute(dc->ctx->dmub_srv); + dc_dmub_srv_wait_idle(dc->ctx->dmub_srv); + + /* Use copied cursor, and it's okay to not switch back */ + cursor_attr.address.quad_part = cmd.mall.cursor_copy_dst.quad_part; + dc_stream_set_cursor_attributes(stream, &cursor_attr); + } + + /* Enable MALL */ + memset(&cmd, 0, sizeof(cmd)); + cmd.mall.header.type = DMUB_CMD__MALL; + cmd.mall.header.sub_type = DMUB_CMD__MALL_ACTION_ALLOW; + cmd.mall.header.payload_bytes = sizeof(cmd.mall) - sizeof(cmd.mall.header); + cmd.mall.tmr_delay = tmr_delay; + cmd.mall.tmr_scale = tmr_scale; + cmd.mall.debug_bits = dc->debug.mall_error_as_fatal; + + dc_dmub_srv_cmd_queue(dc->ctx->dmub_srv, &cmd); + dc_dmub_srv_cmd_execute(dc->ctx->dmub_srv); + + return true; + } + } + + /* No applicable optimizations */ + return false; + } + + /* Disable MALL */ + memset(&cmd, 0, sizeof(cmd)); + cmd.mall.header.type = DMUB_CMD__MALL; + cmd.mall.header.sub_type = DMUB_CMD__MALL_ACTION_DISALLOW; + cmd.mall.header.payload_bytes = + sizeof(cmd.mall) - sizeof(cmd.mall.header); + + dc_dmub_srv_cmd_queue(dc->ctx->dmub_srv, &cmd); + dc_dmub_srv_cmd_execute(dc->ctx->dmub_srv); + dc_dmub_srv_wait_idle(dc->ctx->dmub_srv); + + return true; +} + +bool dcn30_does_plane_fit_in_mall(struct dc *dc, struct dc_plane_state *plane, struct dc_cursor_attributes *cursor_attr) +{ + // add meta size? + unsigned int surface_size = plane->plane_size.surface_pitch * plane->plane_size.surface_size.height * + (plane->format >= SURFACE_PIXEL_FORMAT_GRPH_ARGB16161616 ? 8 : 4); + unsigned int mall_size = dc->caps.mall_size_total; + unsigned int cursor_size = 0; + + if (dc->debug.mall_size_override) + mall_size = 1024 * 1024 * dc->debug.mall_size_override; + + if (cursor_attr) { + cursor_size = dc->caps.max_cursor_size * dc->caps.max_cursor_size; + + switch (cursor_attr->color_format) { + case CURSOR_MODE_MONO: + cursor_size /= 2; + break; + case CURSOR_MODE_COLOR_1BIT_AND: + case CURSOR_MODE_COLOR_PRE_MULTIPLIED_ALPHA: + case CURSOR_MODE_COLOR_UN_PRE_MULTIPLIED_ALPHA: + cursor_size *= 4; + break; + + case CURSOR_MODE_COLOR_64BIT_FP_PRE_MULTIPLIED: + case CURSOR_MODE_COLOR_64BIT_FP_UN_PRE_MULTIPLIED: + cursor_size *= 8; + break; + } + } + + return (surface_size + cursor_size) < mall_size; +} + +void dcn30_hardware_release(struct dc *dc) +{ + bool subvp_in_use = false; + uint32_t i; + + dc_dmub_srv_p_state_delegate(dc, false, NULL); + dc_dmub_setup_subvp_dmub_command(dc, dc->current_state, false); + + /* SubVP treated the same way as FPO. If driver disable and + * we are using a SubVP config, disable and force on DCN side + * to prevent P-State hang on driver enable. + */ + for (i = 0; i < dc->res_pool->pipe_count; i++) { + struct pipe_ctx *pipe = &dc->current_state->res_ctx.pipe_ctx[i]; + + if (!pipe->stream) + continue; + + if (pipe->stream->mall_stream_config.type == SUBVP_MAIN) { + subvp_in_use = true; + break; + } + } + /* If pstate unsupported, or still supported + * by firmware, force it supported by dcn + */ + if (dc->current_state) + if ((!dc->clk_mgr->clks.p_state_change_support || subvp_in_use || + dc->current_state->bw_ctx.bw.dcn.clk.fw_based_mclk_switching) && + dc->res_pool->hubbub->funcs->force_pstate_change_control) + dc->res_pool->hubbub->funcs->force_pstate_change_control( + dc->res_pool->hubbub, true, true); +} + +void dcn30_set_disp_pattern_generator(const struct dc *dc, + struct pipe_ctx *pipe_ctx, + enum controller_dp_test_pattern test_pattern, + enum controller_dp_color_space color_space, + enum dc_color_depth color_depth, + const struct tg_color *solid_color, + int width, int height, int offset) +{ + pipe_ctx->stream_res.opp->funcs->opp_set_disp_pattern_generator(pipe_ctx->stream_res.opp, test_pattern, + color_space, color_depth, solid_color, width, height, offset); +} + +void dcn30_prepare_bandwidth(struct dc *dc, + struct dc_state *context) +{ + if (dc->clk_mgr->dc_mode_softmax_enabled) + if (dc->clk_mgr->clks.dramclk_khz <= dc->clk_mgr->bw_params->dc_mode_softmax_memclk * 1000 && + context->bw_ctx.bw.dcn.clk.dramclk_khz > dc->clk_mgr->bw_params->dc_mode_softmax_memclk * 1000) + dc->clk_mgr->funcs->set_max_memclk(dc->clk_mgr, dc->clk_mgr->bw_params->clk_table.entries[dc->clk_mgr->bw_params->clk_table.num_entries - 1].memclk_mhz); + + dcn20_prepare_bandwidth(dc, context); + + dc_dmub_srv_p_state_delegate(dc, + context->bw_ctx.bw.dcn.clk.fw_based_mclk_switching, context); +} + diff --git a/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_hwseq.h b/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_hwseq.h new file mode 100644 index 000000000..a24a8e33a --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_hwseq.h @@ -0,0 +1,91 @@ +/* +* Copyright 2020 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_HWSS_DCN30_H__ +#define __DC_HWSS_DCN30_H__ + +#include "hw_sequencer_private.h" +#include "dcn20/dcn20_hwseq.h" +struct dc; + +void dcn30_init_hw(struct dc *dc); +void dcn30_program_all_writeback_pipes_in_tree( + struct dc *dc, + const struct dc_stream_state *stream, + struct dc_state *context); +void dcn30_update_writeback( + struct dc *dc, + struct dc_writeback_info *wb_info, + struct dc_state *context); +void dcn30_enable_writeback( + struct dc *dc, + struct dc_writeback_info *wb_info, + struct dc_state *context); +void dcn30_disable_writeback( + struct dc *dc, + unsigned int dwb_pipe_inst); + +bool dcn30_mmhubbub_warmup( + struct dc *dc, + unsigned int num_dwb, + struct dc_writeback_info *wb_info); + +bool dcn30_set_blend_lut(struct pipe_ctx *pipe_ctx, + const struct dc_plane_state *plane_state); + +bool dcn30_set_input_transfer_func(struct dc *dc, + struct pipe_ctx *pipe_ctx, + const struct dc_plane_state *plane_state); +bool dcn30_set_output_transfer_func(struct dc *dc, + struct pipe_ctx *pipe_ctx, + const struct dc_stream_state *stream); +void dcn30_set_avmute(struct pipe_ctx *pipe_ctx, bool enable); +void dcn30_update_info_frame(struct pipe_ctx *pipe_ctx); +void dcn30_program_dmdata_engine(struct pipe_ctx *pipe_ctx); + +bool dcn30_does_plane_fit_in_mall(struct dc *dc, struct dc_plane_state *plane, + struct dc_cursor_attributes *cursor_attr); + +bool dcn30_apply_idle_power_optimizations(struct dc *dc, bool enable); + +void dcn30_hardware_release(struct dc *dc); + +void dcn30_set_disp_pattern_generator(const struct dc *dc, + struct pipe_ctx *pipe_ctx, + enum controller_dp_test_pattern test_pattern, + enum controller_dp_color_space color_space, + enum dc_color_depth color_depth, + const struct tg_color *solid_color, + int width, int height, int offset); + +void dcn30_set_hubp_blank(const struct dc *dc, + struct pipe_ctx *pipe_ctx, + bool blank_enable); + +void dcn30_prepare_bandwidth(struct dc *dc, + struct dc_state *context); + + +#endif /* __DC_HWSS_DCN30_H__ */ diff --git a/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_init.c b/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_init.c new file mode 100644 index 000000000..3216d10c5 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_init.c @@ -0,0 +1,158 @@ +/* + * Copyright 2016-2020 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 "dce110/dce110_hw_sequencer.h" +#include "dcn10/dcn10_hw_sequencer.h" +#include "dcn20/dcn20_hwseq.h" +#include "dcn21/dcn21_hwseq.h" +#include "dcn30_hwseq.h" + +#include "dcn30_init.h" + +static const struct hw_sequencer_funcs dcn30_funcs = { + .program_gamut_remap = dcn10_program_gamut_remap, + .init_hw = dcn30_init_hw, + .apply_ctx_to_hw = dce110_apply_ctx_to_hw, + .apply_ctx_for_surface = NULL, + .program_front_end_for_ctx = dcn20_program_front_end_for_ctx, + .wait_for_pending_cleared = dcn10_wait_for_pending_cleared, + .post_unlock_program_front_end = dcn20_post_unlock_program_front_end, + .update_plane_addr = dcn20_update_plane_addr, + .update_dchub = dcn10_update_dchub, + .update_pending_status = dcn10_update_pending_status, + .program_output_csc = dcn20_program_output_csc, + .enable_accelerated_mode = dce110_enable_accelerated_mode, + .enable_timing_synchronization = dcn10_enable_timing_synchronization, + .enable_per_frame_crtc_position_reset = dcn10_enable_per_frame_crtc_position_reset, + .update_info_frame = dcn30_update_info_frame, + .send_immediate_sdp_message = dcn10_send_immediate_sdp_message, + .enable_stream = dcn20_enable_stream, + .disable_stream = dce110_disable_stream, + .unblank_stream = dcn20_unblank_stream, + .blank_stream = dce110_blank_stream, + .enable_audio_stream = dce110_enable_audio_stream, + .disable_audio_stream = dce110_disable_audio_stream, + .disable_plane = dcn20_disable_plane, + .disable_pixel_data = dcn20_disable_pixel_data, + .pipe_control_lock = dcn20_pipe_control_lock, + .interdependent_update_lock = dcn10_lock_all_pipes, + .cursor_lock = dcn10_cursor_lock, + .prepare_bandwidth = dcn30_prepare_bandwidth, + .optimize_bandwidth = dcn20_optimize_bandwidth, + .update_bandwidth = dcn20_update_bandwidth, + .set_drr = dcn10_set_drr, + .get_position = dcn10_get_position, + .set_static_screen_control = dcn10_set_static_screen_control, + .setup_stereo = dcn10_setup_stereo, + .set_avmute = dcn30_set_avmute, + .log_hw_state = dcn10_log_hw_state, + .get_hw_state = dcn10_get_hw_state, + .clear_status_bits = dcn10_clear_status_bits, + .wait_for_mpcc_disconnect = dcn10_wait_for_mpcc_disconnect, + .edp_backlight_control = dce110_edp_backlight_control, + .edp_power_control = dce110_edp_power_control, + .edp_wait_for_hpd_ready = dce110_edp_wait_for_hpd_ready, + .edp_wait_for_T12 = dce110_edp_wait_for_T12, + .set_cursor_position = dcn10_set_cursor_position, + .set_cursor_attribute = dcn10_set_cursor_attribute, + .set_cursor_sdr_white_level = dcn10_set_cursor_sdr_white_level, + .setup_periodic_interrupt = dcn10_setup_periodic_interrupt, + .set_clock = dcn10_set_clock, + .get_clock = dcn10_get_clock, + .program_triplebuffer = dcn20_program_triple_buffer, + .enable_writeback = dcn30_enable_writeback, + .disable_writeback = dcn30_disable_writeback, + .update_writeback = dcn30_update_writeback, + .mmhubbub_warmup = dcn30_mmhubbub_warmup, + .dmdata_status_done = dcn20_dmdata_status_done, + .program_dmdata_engine = dcn30_program_dmdata_engine, + .set_dmdata_attributes = dcn20_set_dmdata_attributes, + .init_sys_ctx = dcn20_init_sys_ctx, + .init_vm_ctx = dcn20_init_vm_ctx, + .set_flip_control_gsl = dcn20_set_flip_control_gsl, + .get_vupdate_offset_from_vsync = dcn10_get_vupdate_offset_from_vsync, + .calc_vupdate_position = dcn10_calc_vupdate_position, + .apply_idle_power_optimizations = dcn30_apply_idle_power_optimizations, + .does_plane_fit_in_mall = dcn30_does_plane_fit_in_mall, + .set_backlight_level = dcn21_set_backlight_level, + .set_abm_immediate_disable = dcn21_set_abm_immediate_disable, + .hardware_release = dcn30_hardware_release, + .set_pipe = dcn21_set_pipe, + .enable_lvds_link_output = dce110_enable_lvds_link_output, + .enable_tmds_link_output = dce110_enable_tmds_link_output, + .enable_dp_link_output = dce110_enable_dp_link_output, + .disable_link_output = dce110_disable_link_output, + .set_disp_pattern_generator = dcn30_set_disp_pattern_generator, + .get_dcc_en_bits = dcn10_get_dcc_en_bits, + .update_visual_confirm_color = dcn20_update_visual_confirm_color, + .is_abm_supported = dcn21_is_abm_supported +}; + +static const struct hwseq_private_funcs dcn30_private_funcs = { + .init_pipes = dcn10_init_pipes, + .update_plane_addr = dcn20_update_plane_addr, + .plane_atomic_disconnect = dcn10_plane_atomic_disconnect, + .update_mpcc = dcn20_update_mpcc, + .set_input_transfer_func = dcn30_set_input_transfer_func, + .set_output_transfer_func = dcn30_set_output_transfer_func, + .power_down = dce110_power_down, + .enable_display_power_gating = dcn10_dummy_display_power_gating, + .blank_pixel_data = dcn20_blank_pixel_data, + .reset_hw_ctx_wrap = dcn20_reset_hw_ctx_wrap, + .enable_stream_timing = dcn20_enable_stream_timing, + .edp_backlight_control = dce110_edp_backlight_control, + .disable_stream_gating = dcn20_disable_stream_gating, + .enable_stream_gating = dcn20_enable_stream_gating, + .setup_vupdate_interrupt = dcn20_setup_vupdate_interrupt, + .did_underflow_occur = dcn10_did_underflow_occur, + .init_blank = dcn20_init_blank, + .disable_vga = dcn20_disable_vga, + .bios_golden_init = dcn10_bios_golden_init, + .plane_atomic_disable = dcn20_plane_atomic_disable, + .plane_atomic_power_down = dcn10_plane_atomic_power_down, + .enable_power_gating_plane = dcn20_enable_power_gating_plane, + .dpp_pg_control = dcn20_dpp_pg_control, + .hubp_pg_control = dcn20_hubp_pg_control, + .program_all_writeback_pipes_in_tree = dcn30_program_all_writeback_pipes_in_tree, + .update_odm = dcn20_update_odm, + .dsc_pg_control = dcn20_dsc_pg_control, + .set_hdr_multiplier = dcn10_set_hdr_multiplier, + .verify_allow_pstate_change_high = dcn10_verify_allow_pstate_change_high, + .wait_for_blank_complete = dcn20_wait_for_blank_complete, + .dccg_init = dcn20_dccg_init, + .set_blend_lut = dcn30_set_blend_lut, + .set_shaper_3dlut = dcn20_set_shaper_3dlut, +}; + +void dcn30_hw_sequencer_construct(struct dc *dc) +{ + dc->hwss = dcn30_funcs; + dc->hwseq->funcs = dcn30_private_funcs; + + if (IS_FPGA_MAXIMUS_DC(dc->ctx->dce_environment)) { + dc->hwss.init_hw = dcn20_fpga_init_hw; + dc->hwseq->funcs.init_pipes = NULL; + } +} diff --git a/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_init.h b/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_init.h new file mode 100644 index 000000000..c280ff90b --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_init.h @@ -0,0 +1,33 @@ +/* + * Copyright 2020 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_DCN30_INIT_H__ +#define __DC_DCN30_INIT_H__ + +struct dc; + +void dcn30_hw_sequencer_construct(struct dc *dc); + +#endif /* __DC_DCN30_INIT_H__ */ diff --git a/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_mmhubbub.c b/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_mmhubbub.c new file mode 100644 index 000000000..7a93eff18 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_mmhubbub.c @@ -0,0 +1,239 @@ +/* + * Copyright 2020 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 "reg_helper.h" +#include "resource.h" +#include "mcif_wb.h" +#include "dcn30_mmhubbub.h" + + +#define REG(reg)\ + mcif_wb30->mcif_wb_regs->reg + +#define CTX \ + mcif_wb30->base.ctx + +#undef FN +#define FN(reg_name, field_name) \ + mcif_wb30->mcif_wb_shift->field_name, mcif_wb30->mcif_wb_mask->field_name + +#define MCIF_ADDR(addr) (((unsigned long long)addr & 0xffffffffff) + 0xFE) >> 8 +#define MCIF_ADDR_HIGH(addr) (unsigned long long)addr >> 40 + +/* wbif programming guide: + * 1. set up wbif parameter: + * unsigned long long luma_address[4]; //4 frame buffer + * unsigned long long chroma_address[4]; + * unsigned int luma_pitch; + * unsigned int chroma_pitch; + * unsigned int warmup_pitch=0x10; //256B align, the page size is 4KB when it is 0x10 + * unsigned int slice_lines; //slice size + * unsigned int time_per_pixel; // time per pixel, in ns + * unsigned int arbitration_slice; // 0: 2048 bytes 1: 4096 bytes 2: 8192 Bytes + * unsigned int max_scaled_time; // used for QOS generation + * unsigned int swlock=0x0; + * unsigned int cli_watermark[4]; //4 group urgent watermark + * unsigned int pstate_watermark[4]; //4 group pstate watermark + * unsigned int sw_int_en; // Software interrupt enable, frame end and overflow + * unsigned int sw_slice_int_en; // slice end interrupt enable + * unsigned int sw_overrun_int_en; // overrun error interrupt enable + * unsigned int vce_int_en; // VCE interrupt enable, frame end and overflow + * unsigned int vce_slice_int_en; // VCE slice end interrupt enable, frame end and overflow + * + * 2. configure wbif register + * a. call mmhubbub_config_wbif() + * + * 3. Enable wbif + * call set_wbif_bufmgr_enable(); + * + * 4. wbif_dump_status(), option, for debug purpose + * the bufmgr status can show the progress of write back, can be used for debug purpose + */ + +static void mmhubbub3_warmup_mcif(struct mcif_wb *mcif_wb, + struct mcif_warmup_params *params) +{ + struct dcn30_mmhubbub *mcif_wb30 = TO_DCN30_MMHUBBUB(mcif_wb); + union large_integer start_address_shift = {.quad_part = params->start_address.quad_part >> 5}; + + /* Set base address and region size for warmup */ + REG_SET(MMHUBBUB_WARMUP_BASE_ADDR_HIGH, 0, MMHUBBUB_WARMUP_BASE_ADDR_HIGH, start_address_shift.high_part); + REG_SET(MMHUBBUB_WARMUP_BASE_ADDR_LOW, 0, MMHUBBUB_WARMUP_BASE_ADDR_LOW, start_address_shift.low_part); + REG_SET(MMHUBBUB_WARMUP_ADDR_REGION, 0, MMHUBBUB_WARMUP_ADDR_REGION, params->region_size >> 5); +// REG_SET(MMHUBBUB_WARMUP_P_VMID, 0, MMHUBBUB_WARMUP_P_VMID, params->p_vmid); + + /* Set address increment and enable warmup */ + REG_SET_3(MMHUBBUB_WARMUP_CONTROL_STATUS, 0, MMHUBBUB_WARMUP_EN, true, + MMHUBBUB_WARMUP_SW_INT_EN, true, + MMHUBBUB_WARMUP_INC_ADDR, params->address_increment >> 5); + + /* Wait for an interrupt to signal warmup is completed */ + REG_WAIT(MMHUBBUB_WARMUP_CONTROL_STATUS, MMHUBBUB_WARMUP_SW_INT_STATUS, 1, 20, 100); + + /* Acknowledge interrupt */ + REG_UPDATE(MMHUBBUB_WARMUP_CONTROL_STATUS, MMHUBBUB_WARMUP_SW_INT_ACK, 1); + + /* Disable warmup */ + REG_UPDATE(MMHUBBUB_WARMUP_CONTROL_STATUS, MMHUBBUB_WARMUP_EN, false); +} + +static void mmhubbub3_config_mcif_buf(struct mcif_wb *mcif_wb, + struct mcif_buf_params *params, + unsigned int dest_height) +{ + struct dcn30_mmhubbub *mcif_wb30 = TO_DCN30_MMHUBBUB(mcif_wb); + + /* buffer address for packing mode or Luma in planar mode */ + REG_UPDATE(MCIF_WB_BUF_1_ADDR_Y, MCIF_WB_BUF_1_ADDR_Y, MCIF_ADDR(params->luma_address[0])); + REG_UPDATE(MCIF_WB_BUF_1_ADDR_Y_HIGH, MCIF_WB_BUF_1_ADDR_Y_HIGH, MCIF_ADDR_HIGH(params->luma_address[0])); + + /* buffer address for Chroma in planar mode (unused in packing mode) */ + REG_UPDATE(MCIF_WB_BUF_1_ADDR_C, MCIF_WB_BUF_1_ADDR_C, MCIF_ADDR(params->chroma_address[0])); + REG_UPDATE(MCIF_WB_BUF_1_ADDR_C_HIGH, MCIF_WB_BUF_1_ADDR_C_HIGH, MCIF_ADDR_HIGH(params->chroma_address[0])); + + /* buffer address for packing mode or Luma in planar mode */ + REG_UPDATE(MCIF_WB_BUF_2_ADDR_Y, MCIF_WB_BUF_2_ADDR_Y, MCIF_ADDR(params->luma_address[1])); + REG_UPDATE(MCIF_WB_BUF_2_ADDR_Y_HIGH, MCIF_WB_BUF_2_ADDR_Y_HIGH, MCIF_ADDR_HIGH(params->luma_address[1])); + + /* buffer address for Chroma in planar mode (unused in packing mode) */ + REG_UPDATE(MCIF_WB_BUF_2_ADDR_C, MCIF_WB_BUF_2_ADDR_C, MCIF_ADDR(params->chroma_address[1])); + REG_UPDATE(MCIF_WB_BUF_2_ADDR_C_HIGH, MCIF_WB_BUF_2_ADDR_C_HIGH, MCIF_ADDR_HIGH(params->chroma_address[1])); + + /* buffer address for packing mode or Luma in planar mode */ + REG_UPDATE(MCIF_WB_BUF_3_ADDR_Y, MCIF_WB_BUF_3_ADDR_Y, MCIF_ADDR(params->luma_address[2])); + REG_UPDATE(MCIF_WB_BUF_3_ADDR_Y_HIGH, MCIF_WB_BUF_3_ADDR_Y_HIGH, MCIF_ADDR_HIGH(params->luma_address[2])); + + /* buffer address for Chroma in planar mode (unused in packing mode) */ + REG_UPDATE(MCIF_WB_BUF_3_ADDR_C, MCIF_WB_BUF_3_ADDR_C, MCIF_ADDR(params->chroma_address[2])); + REG_UPDATE(MCIF_WB_BUF_3_ADDR_C_HIGH, MCIF_WB_BUF_3_ADDR_C_HIGH, MCIF_ADDR_HIGH(params->chroma_address[2])); + + /* buffer address for packing mode or Luma in planar mode */ + REG_UPDATE(MCIF_WB_BUF_4_ADDR_Y, MCIF_WB_BUF_4_ADDR_Y, MCIF_ADDR(params->luma_address[3])); + REG_UPDATE(MCIF_WB_BUF_4_ADDR_Y_HIGH, MCIF_WB_BUF_4_ADDR_Y_HIGH, MCIF_ADDR_HIGH(params->luma_address[3])); + + /* buffer address for Chroma in planar mode (unused in packing mode) */ + REG_UPDATE(MCIF_WB_BUF_4_ADDR_C, MCIF_WB_BUF_4_ADDR_C, MCIF_ADDR(params->chroma_address[3])); + REG_UPDATE(MCIF_WB_BUF_4_ADDR_C_HIGH, MCIF_WB_BUF_4_ADDR_C_HIGH, MCIF_ADDR_HIGH(params->chroma_address[3])); + + /* setup luma & chroma size + * should be enough to contain a whole frame Luma data, + * the programmed value is frame buffer size [27:8], 256-byte aligned + */ + REG_UPDATE(MCIF_WB_BUF_LUMA_SIZE, MCIF_WB_BUF_LUMA_SIZE, (params->luma_pitch>>8) * dest_height); + REG_UPDATE(MCIF_WB_BUF_CHROMA_SIZE, MCIF_WB_BUF_CHROMA_SIZE, (params->chroma_pitch>>8) * dest_height); + + /* enable address fence */ + REG_UPDATE(MCIF_WB_BUFMGR_SW_CONTROL, MCIF_WB_BUF_ADDR_FENCE_EN, 1); + + /* setup pitch, the programmed value is [15:8], 256B align */ + REG_UPDATE_2(MCIF_WB_BUF_PITCH, MCIF_WB_BUF_LUMA_PITCH, params->luma_pitch >> 8, + MCIF_WB_BUF_CHROMA_PITCH, params->chroma_pitch >> 8); +} + +static void mmhubbub3_config_mcif_arb(struct mcif_wb *mcif_wb, + struct mcif_arb_params *params) +{ + struct dcn30_mmhubbub *mcif_wb30 = TO_DCN30_MMHUBBUB(mcif_wb); + + /* Programmed by the video driver based on the CRTC timing (for DWB) */ + REG_UPDATE(MCIF_WB_ARBITRATION_CONTROL, MCIF_WB_TIME_PER_PIXEL, params->time_per_pixel); + + /* Programming dwb watermark */ + /* Watermark to generate urgent in MCIF_WB_CLI, value is determined by MCIF_WB_CLI_WATERMARK_MASK. */ + /* Program in ns. A formula will be provided in the pseudo code to calculate the value. */ + REG_UPDATE(MCIF_WB_WATERMARK, MCIF_WB_CLI_WATERMARK_MASK, 0x0); + /* urgent_watermarkA */ + REG_UPDATE(MCIF_WB_WATERMARK, MCIF_WB_CLI_WATERMARK, params->cli_watermark[0]); + REG_UPDATE(MCIF_WB_WATERMARK, MCIF_WB_CLI_WATERMARK_MASK, 0x1); + /* urgent_watermarkB */ + REG_UPDATE(MCIF_WB_WATERMARK, MCIF_WB_CLI_WATERMARK, params->cli_watermark[1]); + REG_UPDATE(MCIF_WB_WATERMARK, MCIF_WB_CLI_WATERMARK_MASK, 0x2); + /* urgent_watermarkC */ + REG_UPDATE(MCIF_WB_WATERMARK, MCIF_WB_CLI_WATERMARK, params->cli_watermark[2]); + REG_UPDATE(MCIF_WB_WATERMARK, MCIF_WB_CLI_WATERMARK_MASK, 0x3); + /* urgent_watermarkD */ + REG_UPDATE(MCIF_WB_WATERMARK, MCIF_WB_CLI_WATERMARK, params->cli_watermark[3]); + + /* Programming nb pstate watermark */ + /* nbp_state_change_watermarkA */ + REG_UPDATE(MCIF_WB_NB_PSTATE_LATENCY_WATERMARK, NB_PSTATE_CHANGE_WATERMARK_MASK, 0x0); + REG_UPDATE(MCIF_WB_NB_PSTATE_LATENCY_WATERMARK, + NB_PSTATE_CHANGE_REFRESH_WATERMARK, params->pstate_watermark[0]); + /* nbp_state_change_watermarkB */ + REG_UPDATE(MCIF_WB_NB_PSTATE_LATENCY_WATERMARK, NB_PSTATE_CHANGE_WATERMARK_MASK, 0x1); + REG_UPDATE(MCIF_WB_NB_PSTATE_LATENCY_WATERMARK, + NB_PSTATE_CHANGE_REFRESH_WATERMARK, params->pstate_watermark[1]); + /* nbp_state_change_watermarkC */ + REG_UPDATE(MCIF_WB_NB_PSTATE_LATENCY_WATERMARK, NB_PSTATE_CHANGE_WATERMARK_MASK, 0x2); + REG_UPDATE(MCIF_WB_NB_PSTATE_LATENCY_WATERMARK, + NB_PSTATE_CHANGE_REFRESH_WATERMARK, params->pstate_watermark[2]); + /* nbp_state_change_watermarkD */ + REG_UPDATE(MCIF_WB_NB_PSTATE_LATENCY_WATERMARK, NB_PSTATE_CHANGE_WATERMARK_MASK, 0x3); + REG_UPDATE(MCIF_WB_NB_PSTATE_LATENCY_WATERMARK, + NB_PSTATE_CHANGE_REFRESH_WATERMARK, params->pstate_watermark[3]); + + /* dram_speed_change_duration */ + REG_UPDATE(MCIF_WB_DRAM_SPEED_CHANGE_DURATION_VBI, + MCIF_WB_DRAM_SPEED_CHANGE_DURATION_VBI, params->dram_speed_change_duration); + + /* max_scaled_time */ + REG_UPDATE(MULTI_LEVEL_QOS_CTRL, MAX_SCALED_TIME_TO_URGENT, params->max_scaled_time); + + /* slice_lines */ + REG_UPDATE(MCIF_WB_BUFMGR_VCE_CONTROL, MCIF_WB_BUFMGR_SLICE_SIZE, params->slice_lines-1); + + /* Set arbitration unit for Luma/Chroma */ + /* arb_unit=2 should be chosen for more efficiency */ + /* Arbitration size, 0: 2048 bytes 1: 4096 bytes 2: 8192 Bytes */ + REG_UPDATE(MCIF_WB_ARBITRATION_CONTROL, MCIF_WB_CLIENT_ARBITRATION_SLICE, params->arbitration_slice); +} + +const struct mcif_wb_funcs dcn30_mmhubbub_funcs = { + .warmup_mcif = mmhubbub3_warmup_mcif, + .enable_mcif = mmhubbub2_enable_mcif, + .disable_mcif = mmhubbub2_disable_mcif, + .config_mcif_buf = mmhubbub3_config_mcif_buf, + .config_mcif_arb = mmhubbub3_config_mcif_arb, + .config_mcif_irq = mmhubbub2_config_mcif_irq, + .dump_frame = mcifwb2_dump_frame, +}; + +void dcn30_mmhubbub_construct(struct dcn30_mmhubbub *mcif_wb30, + struct dc_context *ctx, + const struct dcn30_mmhubbub_registers *mcif_wb_regs, + const struct dcn30_mmhubbub_shift *mcif_wb_shift, + const struct dcn30_mmhubbub_mask *mcif_wb_mask, + int inst) +{ + mcif_wb30->base.ctx = ctx; + + mcif_wb30->base.inst = inst; + mcif_wb30->base.funcs = &dcn30_mmhubbub_funcs; + + mcif_wb30->mcif_wb_regs = mcif_wb_regs; + mcif_wb30->mcif_wb_shift = mcif_wb_shift; + mcif_wb30->mcif_wb_mask = mcif_wb_mask; +} diff --git a/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_mmhubbub.h b/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_mmhubbub.h new file mode 100644 index 000000000..7446e54bf --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_mmhubbub.h @@ -0,0 +1,455 @@ +/* + * Copyright 2020 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_MCIF_WB_DCN30_H__ +#define __DC_MCIF_WB_DCN30_H__ + +#include "dcn20/dcn20_mmhubbub.h" + +#define TO_DCN30_MMHUBBUB(mcif_wb_base) \ + container_of(mcif_wb_base, struct dcn30_mmhubbub, base) + +/* DCN */ +#define BASE_INNER(seg) \ + DCE_BASE__INST0_SEG ## seg + +#define BASE(seg) \ + BASE_INNER(seg) + +#define MCIF_WB_COMMON_REG_LIST_DCN3_0(inst) \ + SRI(MCIF_WB_BUFMGR_SW_CONTROL, MCIF_WB, inst),\ + SRI(MCIF_WB_BUFMGR_STATUS, MCIF_WB, inst),\ + SRI(MCIF_WB_BUF_PITCH, MCIF_WB, inst),\ + SRI(MCIF_WB_BUF_1_STATUS, MCIF_WB, inst),\ + SRI(MCIF_WB_BUF_1_STATUS2, MCIF_WB, inst),\ + SRI(MCIF_WB_BUF_2_STATUS, MCIF_WB, inst),\ + SRI(MCIF_WB_BUF_2_STATUS2, MCIF_WB, inst),\ + SRI(MCIF_WB_BUF_3_STATUS, MCIF_WB, inst),\ + SRI(MCIF_WB_BUF_3_STATUS2, MCIF_WB, inst),\ + SRI(MCIF_WB_BUF_4_STATUS, MCIF_WB, inst),\ + SRI(MCIF_WB_BUF_4_STATUS2, MCIF_WB, inst),\ + SRI(MCIF_WB_ARBITRATION_CONTROL, MCIF_WB, inst),\ + SRI(MCIF_WB_SCLK_CHANGE, MCIF_WB, inst),\ + SRI(MCIF_WB_BUF_1_ADDR_Y, MCIF_WB, inst),\ + SRI(MCIF_WB_BUF_1_ADDR_C, MCIF_WB, inst),\ + SRI(MCIF_WB_BUF_2_ADDR_Y, MCIF_WB, inst),\ + SRI(MCIF_WB_BUF_2_ADDR_C, MCIF_WB, inst),\ + SRI(MCIF_WB_BUF_3_ADDR_Y, MCIF_WB, inst),\ + SRI(MCIF_WB_BUF_3_ADDR_C, MCIF_WB, inst),\ + SRI(MCIF_WB_BUF_4_ADDR_Y, MCIF_WB, inst),\ + SRI(MCIF_WB_BUF_4_ADDR_C, MCIF_WB, inst),\ + SRI(MCIF_WB_BUFMGR_VCE_CONTROL, MCIF_WB, inst),\ + SRI2(MCIF_WB_NB_PSTATE_LATENCY_WATERMARK, MMHUBBUB, inst),\ + SRI(MCIF_WB_NB_PSTATE_CONTROL, MCIF_WB, inst),\ + SRI2(MCIF_WB_WATERMARK, MMHUBBUB, inst),\ + SRI(MCIF_WB_CLOCK_GATER_CONTROL, MCIF_WB, inst),\ + SRI(MCIF_WB_SELF_REFRESH_CONTROL, MCIF_WB, inst),\ + SRI(MULTI_LEVEL_QOS_CTRL, MCIF_WB, inst),\ + SRI(MCIF_WB_BUF_LUMA_SIZE, MCIF_WB, inst),\ + SRI(MCIF_WB_BUF_CHROMA_SIZE, MCIF_WB, inst),\ + SRI(MCIF_WB_BUF_1_ADDR_Y_HIGH, MCIF_WB, inst),\ + SRI(MCIF_WB_BUF_1_ADDR_C_HIGH, MCIF_WB, inst),\ + SRI(MCIF_WB_BUF_2_ADDR_Y_HIGH, MCIF_WB, inst),\ + SRI(MCIF_WB_BUF_2_ADDR_C_HIGH, MCIF_WB, inst),\ + SRI(MCIF_WB_BUF_3_ADDR_Y_HIGH, MCIF_WB, inst),\ + SRI(MCIF_WB_BUF_3_ADDR_C_HIGH, MCIF_WB, inst),\ + SRI(MCIF_WB_BUF_4_ADDR_Y_HIGH, MCIF_WB, inst),\ + SRI(MCIF_WB_BUF_4_ADDR_C_HIGH, MCIF_WB, inst),\ + SRI(MCIF_WB_BUF_1_RESOLUTION, MCIF_WB, inst),\ + SRI(MCIF_WB_BUF_2_RESOLUTION, MCIF_WB, inst),\ + SRI(MCIF_WB_BUF_3_RESOLUTION, MCIF_WB, inst),\ + SRI(MCIF_WB_BUF_4_RESOLUTION, MCIF_WB, inst),\ + SRI2(MMHUBBUB_MEM_PWR_CNTL, MMHUBBUB, inst),\ + SRI2(MMHUBBUB_WARMUP_ADDR_REGION, MMHUBBUB, inst),\ + SRI2(MMHUBBUB_WARMUP_BASE_ADDR_HIGH, MMHUBBUB, inst),\ + SRI2(MMHUBBUB_WARMUP_BASE_ADDR_LOW, MMHUBBUB, inst),\ + SRI2(MMHUBBUB_WARMUP_CONTROL_STATUS, MMHUBBUB, inst),\ + SRI2(MMHUBBUB_WARMUP_P_VMID, MMHUBBUB, inst),\ + SRI(MCIF_WB_DRAM_SPEED_CHANGE_DURATION_VBI, MCIF_WB, inst) + +#define MCIF_WB_COMMON_REG_LIST_DCN30(inst) \ + SRI2(MCIF_WB_BUFMGR_SW_CONTROL, MCIF_WB, inst),\ + SRI2(MCIF_WB_BUFMGR_STATUS, MCIF_WB, inst),\ + SRI2(MCIF_WB_BUF_PITCH, MCIF_WB, inst),\ + SRI2(MCIF_WB_BUF_1_STATUS, MCIF_WB, inst),\ + SRI2(MCIF_WB_BUF_1_STATUS2, MCIF_WB, inst),\ + SRI2(MCIF_WB_BUF_2_STATUS, MCIF_WB, inst),\ + SRI2(MCIF_WB_BUF_2_STATUS2, MCIF_WB, inst),\ + SRI2(MCIF_WB_BUF_3_STATUS, MCIF_WB, inst),\ + SRI2(MCIF_WB_BUF_3_STATUS2, MCIF_WB, inst),\ + SRI2(MCIF_WB_BUF_4_STATUS, MCIF_WB, inst),\ + SRI2(MCIF_WB_BUF_4_STATUS2, MCIF_WB, inst),\ + SRI2(MCIF_WB_ARBITRATION_CONTROL, MCIF_WB, inst),\ + SRI2(MCIF_WB_SCLK_CHANGE, MCIF_WB, inst),\ + SRI2(MCIF_WB_BUF_1_ADDR_Y, MCIF_WB, inst),\ + SRI2(MCIF_WB_BUF_1_ADDR_C, MCIF_WB, inst),\ + SRI2(MCIF_WB_BUF_2_ADDR_Y, MCIF_WB, inst),\ + SRI2(MCIF_WB_BUF_2_ADDR_C, MCIF_WB, inst),\ + SRI2(MCIF_WB_BUF_3_ADDR_Y, MCIF_WB, inst),\ + SRI2(MCIF_WB_BUF_3_ADDR_C, MCIF_WB, inst),\ + SRI2(MCIF_WB_BUF_4_ADDR_Y, MCIF_WB, inst),\ + SRI2(MCIF_WB_BUF_4_ADDR_C, MCIF_WB, inst),\ + SRI2(MCIF_WB_BUFMGR_VCE_CONTROL, MCIF_WB, inst),\ + SRI2(MCIF_WB_NB_PSTATE_LATENCY_WATERMARK, MMHUBBUB, inst),\ + SRI2(MCIF_WB_NB_PSTATE_CONTROL, MCIF_WB, inst),\ + SRI2(MCIF_WB_WATERMARK, MMHUBBUB, inst),\ + SRI2(MCIF_WB_CLOCK_GATER_CONTROL, MCIF_WB, inst),\ + SRI2(MCIF_WB_SELF_REFRESH_CONTROL, MCIF_WB, inst),\ + SRI2(MULTI_LEVEL_QOS_CTRL, MCIF_WB, inst),\ + SRI2(MCIF_WB_BUF_LUMA_SIZE, MCIF_WB, inst),\ + SRI2(MCIF_WB_BUF_CHROMA_SIZE, MCIF_WB, inst),\ + SRI2(MCIF_WB_BUF_1_ADDR_Y_HIGH, MCIF_WB, inst),\ + SRI2(MCIF_WB_BUF_1_ADDR_C_HIGH, MCIF_WB, inst),\ + SRI2(MCIF_WB_BUF_2_ADDR_Y_HIGH, MCIF_WB, inst),\ + SRI2(MCIF_WB_BUF_2_ADDR_C_HIGH, MCIF_WB, inst),\ + SRI2(MCIF_WB_BUF_3_ADDR_Y_HIGH, MCIF_WB, inst),\ + SRI2(MCIF_WB_BUF_3_ADDR_C_HIGH, MCIF_WB, inst),\ + SRI2(MCIF_WB_BUF_4_ADDR_Y_HIGH, MCIF_WB, inst),\ + SRI2(MCIF_WB_BUF_4_ADDR_C_HIGH, MCIF_WB, inst),\ + SRI2(MCIF_WB_BUF_1_RESOLUTION, MCIF_WB, inst),\ + SRI2(MCIF_WB_BUF_2_RESOLUTION, MCIF_WB, inst),\ + SRI2(MCIF_WB_BUF_3_RESOLUTION, MCIF_WB, inst),\ + SRI2(MCIF_WB_BUF_4_RESOLUTION, MCIF_WB, inst),\ + SRI2(MMHUBBUB_MEM_PWR_CNTL, MMHUBBUB, inst),\ + SRI2(MMHUBBUB_WARMUP_ADDR_REGION, MMHUBBUB, inst),\ + SRI2(MMHUBBUB_WARMUP_BASE_ADDR_HIGH, MMHUBBUB, inst),\ + SRI2(MMHUBBUB_WARMUP_BASE_ADDR_LOW, MMHUBBUB, inst),\ + SRI2(MMHUBBUB_WARMUP_CONTROL_STATUS, MMHUBBUB, inst),\ + SRI2(MCIF_WB_DRAM_SPEED_CHANGE_DURATION_VBI, MCIF_WB, inst) + +#define MCIF_WB_COMMON_MASK_SH_LIST_DCN3_0(mask_sh) \ + SF(MCIF_WB0_MCIF_WB_BUFMGR_SW_CONTROL, MCIF_WB_BUFMGR_ENABLE, mask_sh),\ + SF(MCIF_WB0_MCIF_WB_BUFMGR_SW_CONTROL, MCIF_WB_BUFMGR_SW_INT_EN, mask_sh),\ + SF(MCIF_WB0_MCIF_WB_BUFMGR_SW_CONTROL, MCIF_WB_BUFMGR_SW_INT_ACK, mask_sh),\ + SF(MCIF_WB0_MCIF_WB_BUFMGR_SW_CONTROL, MCIF_WB_BUFMGR_SW_SLICE_INT_EN, mask_sh),\ + SF(MCIF_WB0_MCIF_WB_BUFMGR_SW_CONTROL, MCIF_WB_BUFMGR_SW_OVERRUN_INT_EN, mask_sh),\ + SF(MCIF_WB0_MCIF_WB_BUFMGR_SW_CONTROL, MCIF_WB_BUFMGR_SW_LOCK, mask_sh),\ + SF(MCIF_WB0_MCIF_WB_BUFMGR_SW_CONTROL, MCIF_WB_BUF_ADDR_FENCE_EN, mask_sh),\ + SF(MCIF_WB0_MCIF_WB_BUFMGR_STATUS, MCIF_WB_BUFMGR_VCE_INT_STATUS, mask_sh),\ + SF(MCIF_WB0_MCIF_WB_BUFMGR_STATUS, MCIF_WB_BUFMGR_SW_INT_STATUS, mask_sh),\ + SF(MCIF_WB0_MCIF_WB_BUFMGR_STATUS, MCIF_WB_BUFMGR_SW_OVERRUN_INT_STATUS, mask_sh),\ + SF(MCIF_WB0_MCIF_WB_BUFMGR_STATUS, MCIF_WB_BUFMGR_CUR_BUF, mask_sh),\ + SF(MCIF_WB0_MCIF_WB_BUFMGR_STATUS, MCIF_WB_BUFMGR_BUFTAG, mask_sh),\ + SF(MCIF_WB0_MCIF_WB_BUFMGR_STATUS, MCIF_WB_BUFMGR_CUR_LINE_L, mask_sh),\ + SF(MCIF_WB0_MCIF_WB_BUFMGR_STATUS, MCIF_WB_BUFMGR_NEXT_BUF, mask_sh),\ + SF(MCIF_WB0_MCIF_WB_BUF_PITCH, MCIF_WB_BUF_LUMA_PITCH, mask_sh),\ + SF(MCIF_WB0_MCIF_WB_BUF_PITCH, MCIF_WB_BUF_CHROMA_PITCH, mask_sh),\ + SF(MCIF_WB0_MCIF_WB_BUF_1_STATUS, MCIF_WB_BUF_1_ACTIVE, mask_sh),\ + SF(MCIF_WB0_MCIF_WB_BUF_1_STATUS, MCIF_WB_BUF_1_SW_LOCKED, mask_sh),\ + SF(MCIF_WB0_MCIF_WB_BUF_1_STATUS, MCIF_WB_BUF_1_VCE_LOCKED, mask_sh),\ + SF(MCIF_WB0_MCIF_WB_BUF_1_STATUS, MCIF_WB_BUF_1_OVERFLOW, mask_sh),\ + SF(MCIF_WB0_MCIF_WB_BUF_1_STATUS, MCIF_WB_BUF_1_DISABLE, mask_sh),\ + SF(MCIF_WB0_MCIF_WB_BUF_1_STATUS, MCIF_WB_BUF_1_MODE, mask_sh),\ + SF(MCIF_WB0_MCIF_WB_BUF_1_STATUS, MCIF_WB_BUF_1_BUFTAG, mask_sh),\ + SF(MCIF_WB0_MCIF_WB_BUF_1_STATUS, MCIF_WB_BUF_1_NXT_BUF, mask_sh),\ + SF(MCIF_WB0_MCIF_WB_BUF_1_STATUS, MCIF_WB_BUF_1_CUR_LINE_L, mask_sh),\ + SF(MCIF_WB0_MCIF_WB_BUF_1_STATUS2, MCIF_WB_BUF_1_NEW_CONTENT, mask_sh),\ + SF(MCIF_WB0_MCIF_WB_BUF_1_STATUS2, MCIF_WB_BUF_1_COLOR_DEPTH, mask_sh),\ + SF(MCIF_WB0_MCIF_WB_BUF_1_STATUS2, MCIF_WB_BUF_1_TMZ_BLACK_PIXEL, mask_sh),\ + SF(MCIF_WB0_MCIF_WB_BUF_1_STATUS2, MCIF_WB_BUF_1_TMZ, mask_sh),\ + SF(MCIF_WB0_MCIF_WB_BUF_1_STATUS2, MCIF_WB_BUF_1_Y_OVERRUN, mask_sh),\ + SF(MCIF_WB0_MCIF_WB_BUF_1_STATUS2, MCIF_WB_BUF_1_C_OVERRUN, mask_sh),\ + SF(MCIF_WB0_MCIF_WB_BUF_2_STATUS, MCIF_WB_BUF_2_ACTIVE, mask_sh),\ + SF(MCIF_WB0_MCIF_WB_BUF_2_STATUS, MCIF_WB_BUF_2_SW_LOCKED, mask_sh),\ + SF(MCIF_WB0_MCIF_WB_BUF_2_STATUS, MCIF_WB_BUF_2_VCE_LOCKED, mask_sh),\ + SF(MCIF_WB0_MCIF_WB_BUF_2_STATUS, MCIF_WB_BUF_2_OVERFLOW, mask_sh),\ + SF(MCIF_WB0_MCIF_WB_BUF_2_STATUS, MCIF_WB_BUF_2_DISABLE, mask_sh),\ + SF(MCIF_WB0_MCIF_WB_BUF_2_STATUS, MCIF_WB_BUF_2_MODE, mask_sh),\ + SF(MCIF_WB0_MCIF_WB_BUF_2_STATUS, MCIF_WB_BUF_2_BUFTAG, mask_sh),\ + SF(MCIF_WB0_MCIF_WB_BUF_2_STATUS, MCIF_WB_BUF_2_NXT_BUF, mask_sh),\ + SF(MCIF_WB0_MCIF_WB_BUF_2_STATUS, MCIF_WB_BUF_2_CUR_LINE_L, mask_sh),\ + SF(MCIF_WB0_MCIF_WB_BUF_2_STATUS2, MCIF_WB_BUF_2_NEW_CONTENT, mask_sh),\ + SF(MCIF_WB0_MCIF_WB_BUF_2_STATUS2, MCIF_WB_BUF_2_COLOR_DEPTH, mask_sh),\ + SF(MCIF_WB0_MCIF_WB_BUF_2_STATUS2, MCIF_WB_BUF_2_TMZ_BLACK_PIXEL, mask_sh),\ + SF(MCIF_WB0_MCIF_WB_BUF_2_STATUS2, MCIF_WB_BUF_2_TMZ, mask_sh),\ + SF(MCIF_WB0_MCIF_WB_BUF_2_STATUS2, MCIF_WB_BUF_2_Y_OVERRUN, mask_sh),\ + SF(MCIF_WB0_MCIF_WB_BUF_2_STATUS2, MCIF_WB_BUF_2_C_OVERRUN, mask_sh),\ + SF(MCIF_WB0_MCIF_WB_BUF_3_STATUS, MCIF_WB_BUF_3_ACTIVE, mask_sh),\ + SF(MCIF_WB0_MCIF_WB_BUF_3_STATUS, MCIF_WB_BUF_3_SW_LOCKED, mask_sh),\ + SF(MCIF_WB0_MCIF_WB_BUF_3_STATUS, MCIF_WB_BUF_3_VCE_LOCKED, mask_sh),\ + SF(MCIF_WB0_MCIF_WB_BUF_3_STATUS, MCIF_WB_BUF_3_OVERFLOW, mask_sh),\ + SF(MCIF_WB0_MCIF_WB_BUF_3_STATUS, MCIF_WB_BUF_3_DISABLE, mask_sh),\ + SF(MCIF_WB0_MCIF_WB_BUF_3_STATUS, MCIF_WB_BUF_3_MODE, mask_sh),\ + SF(MCIF_WB0_MCIF_WB_BUF_3_STATUS, MCIF_WB_BUF_3_BUFTAG, mask_sh),\ + SF(MCIF_WB0_MCIF_WB_BUF_3_STATUS, MCIF_WB_BUF_3_NXT_BUF, mask_sh),\ + SF(MCIF_WB0_MCIF_WB_BUF_3_STATUS, MCIF_WB_BUF_3_CUR_LINE_L, mask_sh),\ + SF(MCIF_WB0_MCIF_WB_BUF_3_STATUS2, MCIF_WB_BUF_3_NEW_CONTENT, mask_sh),\ + SF(MCIF_WB0_MCIF_WB_BUF_3_STATUS2, MCIF_WB_BUF_3_COLOR_DEPTH, mask_sh),\ + SF(MCIF_WB0_MCIF_WB_BUF_3_STATUS2, MCIF_WB_BUF_3_TMZ_BLACK_PIXEL, mask_sh),\ + SF(MCIF_WB0_MCIF_WB_BUF_3_STATUS2, MCIF_WB_BUF_3_TMZ, mask_sh),\ + SF(MCIF_WB0_MCIF_WB_BUF_3_STATUS2, MCIF_WB_BUF_3_Y_OVERRUN, mask_sh),\ + SF(MCIF_WB0_MCIF_WB_BUF_3_STATUS2, MCIF_WB_BUF_3_C_OVERRUN, mask_sh),\ + SF(MCIF_WB0_MCIF_WB_BUF_4_STATUS, MCIF_WB_BUF_4_ACTIVE, mask_sh),\ + SF(MCIF_WB0_MCIF_WB_BUF_4_STATUS, MCIF_WB_BUF_4_SW_LOCKED, mask_sh),\ + SF(MCIF_WB0_MCIF_WB_BUF_4_STATUS, MCIF_WB_BUF_4_VCE_LOCKED, mask_sh),\ + SF(MCIF_WB0_MCIF_WB_BUF_4_STATUS, MCIF_WB_BUF_4_OVERFLOW, mask_sh),\ + SF(MCIF_WB0_MCIF_WB_BUF_4_STATUS, MCIF_WB_BUF_4_DISABLE, mask_sh),\ + SF(MCIF_WB0_MCIF_WB_BUF_4_STATUS, MCIF_WB_BUF_4_MODE, mask_sh),\ + SF(MCIF_WB0_MCIF_WB_BUF_4_STATUS, MCIF_WB_BUF_4_BUFTAG, mask_sh),\ + SF(MCIF_WB0_MCIF_WB_BUF_4_STATUS, MCIF_WB_BUF_4_NXT_BUF, mask_sh),\ + SF(MCIF_WB0_MCIF_WB_BUF_4_STATUS, MCIF_WB_BUF_4_CUR_LINE_L, mask_sh),\ + SF(MCIF_WB0_MCIF_WB_BUF_4_STATUS2, MCIF_WB_BUF_4_NEW_CONTENT, mask_sh),\ + SF(MCIF_WB0_MCIF_WB_BUF_4_STATUS2, MCIF_WB_BUF_4_COLOR_DEPTH, mask_sh),\ + SF(MCIF_WB0_MCIF_WB_BUF_4_STATUS2, MCIF_WB_BUF_4_TMZ_BLACK_PIXEL, mask_sh),\ + SF(MCIF_WB0_MCIF_WB_BUF_4_STATUS2, MCIF_WB_BUF_4_TMZ, mask_sh),\ + SF(MCIF_WB0_MCIF_WB_BUF_4_STATUS2, MCIF_WB_BUF_4_Y_OVERRUN, mask_sh),\ + SF(MCIF_WB0_MCIF_WB_BUF_4_STATUS2, MCIF_WB_BUF_4_C_OVERRUN, mask_sh),\ + SF(MCIF_WB0_MCIF_WB_ARBITRATION_CONTROL, MCIF_WB_CLIENT_ARBITRATION_SLICE, mask_sh),\ + SF(MCIF_WB0_MCIF_WB_ARBITRATION_CONTROL, MCIF_WB_TIME_PER_PIXEL, mask_sh),\ + SF(MCIF_WB0_MCIF_WB_SCLK_CHANGE, WM_CHANGE_ACK_FORCE_ON, mask_sh),\ + SF(MCIF_WB0_MCIF_WB_BUF_1_ADDR_Y, MCIF_WB_BUF_1_ADDR_Y, mask_sh),\ + SF(MCIF_WB0_MCIF_WB_BUF_1_ADDR_C, MCIF_WB_BUF_1_ADDR_C, mask_sh),\ + SF(MCIF_WB0_MCIF_WB_BUF_2_ADDR_Y, MCIF_WB_BUF_2_ADDR_Y, mask_sh),\ + SF(MCIF_WB0_MCIF_WB_BUF_2_ADDR_C, MCIF_WB_BUF_2_ADDR_C, mask_sh),\ + SF(MCIF_WB0_MCIF_WB_BUF_3_ADDR_Y, MCIF_WB_BUF_3_ADDR_Y, mask_sh),\ + SF(MCIF_WB0_MCIF_WB_BUF_3_ADDR_C, MCIF_WB_BUF_3_ADDR_C, mask_sh),\ + SF(MCIF_WB0_MCIF_WB_BUF_4_ADDR_Y, MCIF_WB_BUF_4_ADDR_Y, mask_sh),\ + SF(MCIF_WB0_MCIF_WB_BUF_4_ADDR_C, MCIF_WB_BUF_4_ADDR_C, mask_sh),\ + SF(MCIF_WB0_MCIF_WB_BUFMGR_VCE_CONTROL, MCIF_WB_BUFMGR_VCE_SLICE_INT_EN, mask_sh),\ + SF(MCIF_WB0_MCIF_WB_BUFMGR_VCE_CONTROL, MCIF_WB_BUFMGR_SLICE_SIZE, mask_sh),\ + SF(MCIF_WB_NB_PSTATE_LATENCY_WATERMARK, NB_PSTATE_CHANGE_REFRESH_WATERMARK, mask_sh),\ + SF(MCIF_WB_NB_PSTATE_LATENCY_WATERMARK, NB_PSTATE_CHANGE_WATERMARK_MASK, mask_sh),\ + SF(MCIF_WB0_MCIF_WB_NB_PSTATE_CONTROL, NB_PSTATE_CHANGE_URGENT_DURING_REQUEST, mask_sh),\ + SF(MCIF_WB0_MCIF_WB_NB_PSTATE_CONTROL, NB_PSTATE_CHANGE_FORCE_ON, mask_sh),\ + SF(MCIF_WB0_MCIF_WB_NB_PSTATE_CONTROL, NB_PSTATE_ALLOW_FOR_URGENT, mask_sh),\ + SF(MCIF_WB_WATERMARK, MCIF_WB_CLI_WATERMARK, mask_sh),\ + SF(MCIF_WB_WATERMARK, MCIF_WB_CLI_WATERMARK_MASK, mask_sh),\ + SF(MCIF_WB0_MCIF_WB_CLOCK_GATER_CONTROL, MCIF_WB_CLI_CLOCK_GATER_OVERRIDE, mask_sh),\ + SF(MCIF_WB0_MCIF_WB_SELF_REFRESH_CONTROL, DIS_REFRESH_UNDER_NBPREQ, mask_sh),\ + SF(MCIF_WB0_MCIF_WB_SELF_REFRESH_CONTROL, PERFRAME_SELF_REFRESH, mask_sh),\ + SF(MCIF_WB0_MULTI_LEVEL_QOS_CTRL, MAX_SCALED_TIME_TO_URGENT, mask_sh),\ + SF(MCIF_WB0_MCIF_WB_BUF_LUMA_SIZE, MCIF_WB_BUF_LUMA_SIZE, mask_sh),\ + SF(MCIF_WB0_MCIF_WB_BUF_CHROMA_SIZE, MCIF_WB_BUF_CHROMA_SIZE, mask_sh),\ + SF(MCIF_WB0_MCIF_WB_BUF_1_ADDR_Y_HIGH, MCIF_WB_BUF_1_ADDR_Y_HIGH, mask_sh),\ + SF(MCIF_WB0_MCIF_WB_BUF_1_ADDR_C_HIGH, MCIF_WB_BUF_1_ADDR_C_HIGH, mask_sh),\ + SF(MCIF_WB0_MCIF_WB_BUF_2_ADDR_Y_HIGH, MCIF_WB_BUF_2_ADDR_Y_HIGH, mask_sh),\ + SF(MCIF_WB0_MCIF_WB_BUF_2_ADDR_C_HIGH, MCIF_WB_BUF_2_ADDR_C_HIGH, mask_sh),\ + SF(MCIF_WB0_MCIF_WB_BUF_3_ADDR_Y_HIGH, MCIF_WB_BUF_3_ADDR_Y_HIGH, mask_sh),\ + SF(MCIF_WB0_MCIF_WB_BUF_3_ADDR_C_HIGH, MCIF_WB_BUF_3_ADDR_C_HIGH, mask_sh),\ + SF(MCIF_WB0_MCIF_WB_BUF_4_ADDR_Y_HIGH, MCIF_WB_BUF_4_ADDR_Y_HIGH, mask_sh),\ + SF(MCIF_WB0_MCIF_WB_BUF_4_ADDR_C_HIGH, MCIF_WB_BUF_4_ADDR_C_HIGH, mask_sh),\ + SF(MCIF_WB0_MCIF_WB_BUF_1_RESOLUTION, MCIF_WB_BUF_1_RESOLUTION_WIDTH, mask_sh),\ + SF(MCIF_WB0_MCIF_WB_BUF_1_RESOLUTION, MCIF_WB_BUF_1_RESOLUTION_HEIGHT, mask_sh),\ + SF(MCIF_WB0_MCIF_WB_BUF_2_RESOLUTION, MCIF_WB_BUF_2_RESOLUTION_WIDTH, mask_sh),\ + SF(MCIF_WB0_MCIF_WB_BUF_2_RESOLUTION, MCIF_WB_BUF_2_RESOLUTION_HEIGHT, mask_sh),\ + SF(MCIF_WB0_MCIF_WB_BUF_3_RESOLUTION, MCIF_WB_BUF_3_RESOLUTION_WIDTH, mask_sh),\ + SF(MCIF_WB0_MCIF_WB_BUF_3_RESOLUTION, MCIF_WB_BUF_3_RESOLUTION_HEIGHT, mask_sh),\ + SF(MCIF_WB0_MCIF_WB_BUF_4_RESOLUTION, MCIF_WB_BUF_4_RESOLUTION_WIDTH, mask_sh),\ + SF(MCIF_WB0_MCIF_WB_BUF_4_RESOLUTION, MCIF_WB_BUF_4_RESOLUTION_HEIGHT, mask_sh),\ + SF(MMHUBBUB_MEM_PWR_CNTL, WBIF_WHOLE_BUF_MODE, mask_sh),\ + SF(MMHUBBUB_WARMUP_ADDR_REGION, MMHUBBUB_WARMUP_ADDR_REGION, mask_sh),\ + SF(MMHUBBUB_WARMUP_BASE_ADDR_HIGH, MMHUBBUB_WARMUP_BASE_ADDR_HIGH, mask_sh),\ + SF(MMHUBBUB_WARMUP_BASE_ADDR_LOW, MMHUBBUB_WARMUP_BASE_ADDR_LOW, mask_sh),\ + SF(MMHUBBUB_WARMUP_CONTROL_STATUS, MMHUBBUB_WARMUP_EN, mask_sh),\ + SF(MMHUBBUB_WARMUP_CONTROL_STATUS, MMHUBBUB_WARMUP_SW_INT_EN, mask_sh),\ + SF(MMHUBBUB_WARMUP_CONTROL_STATUS, MMHUBBUB_WARMUP_SW_INT_STATUS, mask_sh),\ + SF(MMHUBBUB_WARMUP_CONTROL_STATUS, MMHUBBUB_WARMUP_SW_INT_ACK, mask_sh),\ + SF(MMHUBBUB_WARMUP_CONTROL_STATUS, MMHUBBUB_WARMUP_INC_ADDR, mask_sh),\ + SF(MMHUBBUB_WARMUP_P_VMID, MMHUBBUB_WARMUP_P_VMID, mask_sh),\ + SF(MCIF_WB0_MCIF_WB_DRAM_SPEED_CHANGE_DURATION_VBI, MCIF_WB_DRAM_SPEED_CHANGE_DURATION_VBI, mask_sh) + + +#define MCIF_WB_COMMON_MASK_SH_LIST_DCN30(mask_sh) \ + SF(MCIF_WB_BUFMGR_SW_CONTROL, MCIF_WB_BUFMGR_ENABLE, mask_sh),\ + SF(MCIF_WB_BUFMGR_SW_CONTROL, MCIF_WB_BUFMGR_SW_INT_EN, mask_sh),\ + SF(MCIF_WB_BUFMGR_SW_CONTROL, MCIF_WB_BUFMGR_SW_INT_ACK, mask_sh),\ + SF(MCIF_WB_BUFMGR_SW_CONTROL, MCIF_WB_BUFMGR_SW_SLICE_INT_EN, mask_sh),\ + SF(MCIF_WB_BUFMGR_SW_CONTROL, MCIF_WB_BUFMGR_SW_OVERRUN_INT_EN, mask_sh),\ + SF(MCIF_WB_BUFMGR_SW_CONTROL, MCIF_WB_BUFMGR_SW_LOCK, mask_sh),\ + SF(MCIF_WB_BUFMGR_SW_CONTROL, MCIF_WB_BUF_ADDR_FENCE_EN, mask_sh),\ + SF(MCIF_WB_BUFMGR_STATUS, MCIF_WB_BUFMGR_VCE_INT_STATUS, mask_sh),\ + SF(MCIF_WB_BUFMGR_STATUS, MCIF_WB_BUFMGR_SW_INT_STATUS, mask_sh),\ + SF(MCIF_WB_BUFMGR_STATUS, MCIF_WB_BUFMGR_SW_OVERRUN_INT_STATUS, mask_sh),\ + SF(MCIF_WB_BUFMGR_STATUS, MCIF_WB_BUFMGR_CUR_BUF, mask_sh),\ + SF(MCIF_WB_BUFMGR_STATUS, MCIF_WB_BUFMGR_BUFTAG, mask_sh),\ + SF(MCIF_WB_BUFMGR_STATUS, MCIF_WB_BUFMGR_CUR_LINE_L, mask_sh),\ + SF(MCIF_WB_BUFMGR_STATUS, MCIF_WB_BUFMGR_NEXT_BUF, mask_sh),\ + SF(MCIF_WB_BUF_PITCH, MCIF_WB_BUF_LUMA_PITCH, mask_sh),\ + SF(MCIF_WB_BUF_PITCH, MCIF_WB_BUF_CHROMA_PITCH, mask_sh),\ + SF(MCIF_WB_BUF_1_STATUS, MCIF_WB_BUF_1_ACTIVE, mask_sh),\ + SF(MCIF_WB_BUF_1_STATUS, MCIF_WB_BUF_1_SW_LOCKED, mask_sh),\ + SF(MCIF_WB_BUF_1_STATUS, MCIF_WB_BUF_1_VCE_LOCKED, mask_sh),\ + SF(MCIF_WB_BUF_1_STATUS, MCIF_WB_BUF_1_OVERFLOW, mask_sh),\ + SF(MCIF_WB_BUF_1_STATUS, MCIF_WB_BUF_1_DISABLE, mask_sh),\ + SF(MCIF_WB_BUF_1_STATUS, MCIF_WB_BUF_1_MODE, mask_sh),\ + SF(MCIF_WB_BUF_1_STATUS, MCIF_WB_BUF_1_BUFTAG, mask_sh),\ + SF(MCIF_WB_BUF_1_STATUS, MCIF_WB_BUF_1_NXT_BUF, mask_sh),\ + SF(MCIF_WB_BUF_1_STATUS, MCIF_WB_BUF_1_CUR_LINE_L, mask_sh),\ + SF(MCIF_WB_BUF_1_STATUS2, MCIF_WB_BUF_1_NEW_CONTENT, mask_sh),\ + SF(MCIF_WB_BUF_1_STATUS2, MCIF_WB_BUF_1_COLOR_DEPTH, mask_sh),\ + SF(MCIF_WB_BUF_1_STATUS2, MCIF_WB_BUF_1_TMZ_BLACK_PIXEL, mask_sh),\ + SF(MCIF_WB_BUF_1_STATUS2, MCIF_WB_BUF_1_TMZ, mask_sh),\ + SF(MCIF_WB_BUF_1_STATUS2, MCIF_WB_BUF_1_Y_OVERRUN, mask_sh),\ + SF(MCIF_WB_BUF_1_STATUS2, MCIF_WB_BUF_1_C_OVERRUN, mask_sh),\ + SF(MCIF_WB_BUF_2_STATUS, MCIF_WB_BUF_2_ACTIVE, mask_sh),\ + SF(MCIF_WB_BUF_2_STATUS, MCIF_WB_BUF_2_SW_LOCKED, mask_sh),\ + SF(MCIF_WB_BUF_2_STATUS, MCIF_WB_BUF_2_VCE_LOCKED, mask_sh),\ + SF(MCIF_WB_BUF_2_STATUS, MCIF_WB_BUF_2_OVERFLOW, mask_sh),\ + SF(MCIF_WB_BUF_2_STATUS, MCIF_WB_BUF_2_DISABLE, mask_sh),\ + SF(MCIF_WB_BUF_2_STATUS, MCIF_WB_BUF_2_MODE, mask_sh),\ + SF(MCIF_WB_BUF_2_STATUS, MCIF_WB_BUF_2_BUFTAG, mask_sh),\ + SF(MCIF_WB_BUF_2_STATUS, MCIF_WB_BUF_2_NXT_BUF, mask_sh),\ + SF(MCIF_WB_BUF_2_STATUS, MCIF_WB_BUF_2_CUR_LINE_L, mask_sh),\ + SF(MCIF_WB_BUF_2_STATUS2, MCIF_WB_BUF_2_NEW_CONTENT, mask_sh),\ + SF(MCIF_WB_BUF_2_STATUS2, MCIF_WB_BUF_2_COLOR_DEPTH, mask_sh),\ + SF(MCIF_WB_BUF_2_STATUS2, MCIF_WB_BUF_2_TMZ_BLACK_PIXEL, mask_sh),\ + SF(MCIF_WB_BUF_2_STATUS2, MCIF_WB_BUF_2_TMZ, mask_sh),\ + SF(MCIF_WB_BUF_2_STATUS2, MCIF_WB_BUF_2_Y_OVERRUN, mask_sh),\ + SF(MCIF_WB_BUF_2_STATUS2, MCIF_WB_BUF_2_C_OVERRUN, mask_sh),\ + SF(MCIF_WB_BUF_3_STATUS, MCIF_WB_BUF_3_ACTIVE, mask_sh),\ + SF(MCIF_WB_BUF_3_STATUS, MCIF_WB_BUF_3_SW_LOCKED, mask_sh),\ + SF(MCIF_WB_BUF_3_STATUS, MCIF_WB_BUF_3_VCE_LOCKED, mask_sh),\ + SF(MCIF_WB_BUF_3_STATUS, MCIF_WB_BUF_3_OVERFLOW, mask_sh),\ + SF(MCIF_WB_BUF_3_STATUS, MCIF_WB_BUF_3_DISABLE, mask_sh),\ + SF(MCIF_WB_BUF_3_STATUS, MCIF_WB_BUF_3_MODE, mask_sh),\ + SF(MCIF_WB_BUF_3_STATUS, MCIF_WB_BUF_3_BUFTAG, mask_sh),\ + SF(MCIF_WB_BUF_3_STATUS, MCIF_WB_BUF_3_NXT_BUF, mask_sh),\ + SF(MCIF_WB_BUF_3_STATUS, MCIF_WB_BUF_3_CUR_LINE_L, mask_sh),\ + SF(MCIF_WB_BUF_3_STATUS2, MCIF_WB_BUF_3_NEW_CONTENT, mask_sh),\ + SF(MCIF_WB_BUF_3_STATUS2, MCIF_WB_BUF_3_COLOR_DEPTH, mask_sh),\ + SF(MCIF_WB_BUF_3_STATUS2, MCIF_WB_BUF_3_TMZ_BLACK_PIXEL, mask_sh),\ + SF(MCIF_WB_BUF_3_STATUS2, MCIF_WB_BUF_3_TMZ, mask_sh),\ + SF(MCIF_WB_BUF_3_STATUS2, MCIF_WB_BUF_3_Y_OVERRUN, mask_sh),\ + SF(MCIF_WB_BUF_3_STATUS2, MCIF_WB_BUF_3_C_OVERRUN, mask_sh),\ + SF(MCIF_WB_BUF_4_STATUS, MCIF_WB_BUF_4_ACTIVE, mask_sh),\ + SF(MCIF_WB_BUF_4_STATUS, MCIF_WB_BUF_4_SW_LOCKED, mask_sh),\ + SF(MCIF_WB_BUF_4_STATUS, MCIF_WB_BUF_4_VCE_LOCKED, mask_sh),\ + SF(MCIF_WB_BUF_4_STATUS, MCIF_WB_BUF_4_OVERFLOW, mask_sh),\ + SF(MCIF_WB_BUF_4_STATUS, MCIF_WB_BUF_4_DISABLE, mask_sh),\ + SF(MCIF_WB_BUF_4_STATUS, MCIF_WB_BUF_4_MODE, mask_sh),\ + SF(MCIF_WB_BUF_4_STATUS, MCIF_WB_BUF_4_BUFTAG, mask_sh),\ + SF(MCIF_WB_BUF_4_STATUS, MCIF_WB_BUF_4_NXT_BUF, mask_sh),\ + SF(MCIF_WB_BUF_4_STATUS, MCIF_WB_BUF_4_CUR_LINE_L, mask_sh),\ + SF(MCIF_WB_BUF_4_STATUS2, MCIF_WB_BUF_4_NEW_CONTENT, mask_sh),\ + SF(MCIF_WB_BUF_4_STATUS2, MCIF_WB_BUF_4_COLOR_DEPTH, mask_sh),\ + SF(MCIF_WB_BUF_4_STATUS2, MCIF_WB_BUF_4_TMZ_BLACK_PIXEL, mask_sh),\ + SF(MCIF_WB_BUF_4_STATUS2, MCIF_WB_BUF_4_TMZ, mask_sh),\ + SF(MCIF_WB_BUF_4_STATUS2, MCIF_WB_BUF_4_Y_OVERRUN, mask_sh),\ + SF(MCIF_WB_BUF_4_STATUS2, MCIF_WB_BUF_4_C_OVERRUN, mask_sh),\ + SF(MCIF_WB_ARBITRATION_CONTROL, MCIF_WB_CLIENT_ARBITRATION_SLICE, mask_sh),\ + SF(MCIF_WB_ARBITRATION_CONTROL, MCIF_WB_TIME_PER_PIXEL, mask_sh),\ + SF(MCIF_WB_SCLK_CHANGE, WM_CHANGE_ACK_FORCE_ON, mask_sh),\ + SF(MCIF_WB_BUF_1_ADDR_Y, MCIF_WB_BUF_1_ADDR_Y, mask_sh),\ + SF(MCIF_WB_BUF_1_ADDR_C, MCIF_WB_BUF_1_ADDR_C, mask_sh),\ + SF(MCIF_WB_BUF_2_ADDR_Y, MCIF_WB_BUF_2_ADDR_Y, mask_sh),\ + SF(MCIF_WB_BUF_2_ADDR_C, MCIF_WB_BUF_2_ADDR_C, mask_sh),\ + SF(MCIF_WB_BUF_3_ADDR_Y, MCIF_WB_BUF_3_ADDR_Y, mask_sh),\ + SF(MCIF_WB_BUF_3_ADDR_C, MCIF_WB_BUF_3_ADDR_C, mask_sh),\ + SF(MCIF_WB_BUF_4_ADDR_Y, MCIF_WB_BUF_4_ADDR_Y, mask_sh),\ + SF(MCIF_WB_BUF_4_ADDR_C, MCIF_WB_BUF_4_ADDR_C, mask_sh),\ + SF(MCIF_WB_BUFMGR_VCE_CONTROL, MCIF_WB_BUFMGR_VCE_SLICE_INT_EN, mask_sh),\ + SF(MCIF_WB_BUFMGR_VCE_CONTROL, MCIF_WB_BUFMGR_SLICE_SIZE, mask_sh),\ + SF(MCIF_WB_NB_PSTATE_LATENCY_WATERMARK, NB_PSTATE_CHANGE_REFRESH_WATERMARK, mask_sh),\ + SF(MCIF_WB_NB_PSTATE_LATENCY_WATERMARK, NB_PSTATE_CHANGE_WATERMARK_MASK, mask_sh),\ + SF(MCIF_WB_NB_PSTATE_CONTROL, NB_PSTATE_CHANGE_URGENT_DURING_REQUEST, mask_sh),\ + SF(MCIF_WB_NB_PSTATE_CONTROL, NB_PSTATE_CHANGE_FORCE_ON, mask_sh),\ + SF(MCIF_WB_NB_PSTATE_CONTROL, NB_PSTATE_ALLOW_FOR_URGENT, mask_sh),\ + SF(MCIF_WB_WATERMARK, MCIF_WB_CLI_WATERMARK, mask_sh),\ + SF(MCIF_WB_WATERMARK, MCIF_WB_CLI_WATERMARK_MASK, mask_sh),\ + SF(MCIF_WB_CLOCK_GATER_CONTROL, MCIF_WB_CLI_CLOCK_GATER_OVERRIDE, mask_sh),\ + SF(MCIF_WB_SELF_REFRESH_CONTROL, DIS_REFRESH_UNDER_NBPREQ, mask_sh),\ + SF(MCIF_WB_SELF_REFRESH_CONTROL, PERFRAME_SELF_REFRESH, mask_sh),\ + SF(MULTI_LEVEL_QOS_CTRL, MAX_SCALED_TIME_TO_URGENT, mask_sh),\ + SF(MCIF_WB_BUF_LUMA_SIZE, MCIF_WB_BUF_LUMA_SIZE, mask_sh),\ + SF(MCIF_WB_BUF_CHROMA_SIZE, MCIF_WB_BUF_CHROMA_SIZE, mask_sh),\ + SF(MCIF_WB_BUF_1_ADDR_Y_HIGH, MCIF_WB_BUF_1_ADDR_Y_HIGH, mask_sh),\ + SF(MCIF_WB_BUF_1_ADDR_C_HIGH, MCIF_WB_BUF_1_ADDR_C_HIGH, mask_sh),\ + SF(MCIF_WB_BUF_2_ADDR_Y_HIGH, MCIF_WB_BUF_2_ADDR_Y_HIGH, mask_sh),\ + SF(MCIF_WB_BUF_2_ADDR_C_HIGH, MCIF_WB_BUF_2_ADDR_C_HIGH, mask_sh),\ + SF(MCIF_WB_BUF_3_ADDR_Y_HIGH, MCIF_WB_BUF_3_ADDR_Y_HIGH, mask_sh),\ + SF(MCIF_WB_BUF_3_ADDR_C_HIGH, MCIF_WB_BUF_3_ADDR_C_HIGH, mask_sh),\ + SF(MCIF_WB_BUF_4_ADDR_Y_HIGH, MCIF_WB_BUF_4_ADDR_Y_HIGH, mask_sh),\ + SF(MCIF_WB_BUF_4_ADDR_C_HIGH, MCIF_WB_BUF_4_ADDR_C_HIGH, mask_sh),\ + SF(MCIF_WB_BUF_1_RESOLUTION, MCIF_WB_BUF_1_RESOLUTION_WIDTH, mask_sh),\ + SF(MCIF_WB_BUF_1_RESOLUTION, MCIF_WB_BUF_1_RESOLUTION_HEIGHT, mask_sh),\ + SF(MCIF_WB_BUF_2_RESOLUTION, MCIF_WB_BUF_2_RESOLUTION_WIDTH, mask_sh),\ + SF(MCIF_WB_BUF_2_RESOLUTION, MCIF_WB_BUF_2_RESOLUTION_HEIGHT, mask_sh),\ + SF(MCIF_WB_BUF_3_RESOLUTION, MCIF_WB_BUF_3_RESOLUTION_WIDTH, mask_sh),\ + SF(MCIF_WB_BUF_3_RESOLUTION, MCIF_WB_BUF_3_RESOLUTION_HEIGHT, mask_sh),\ + SF(MCIF_WB_BUF_4_RESOLUTION, MCIF_WB_BUF_4_RESOLUTION_WIDTH, mask_sh),\ + SF(MCIF_WB_BUF_4_RESOLUTION, MCIF_WB_BUF_4_RESOLUTION_HEIGHT, mask_sh),\ + SF(MMHUBBUB_WARMUP_ADDR_REGION, MMHUBBUB_WARMUP_ADDR_REGION, mask_sh),\ + SF(MMHUBBUB_WARMUP_BASE_ADDR_HIGH, MMHUBBUB_WARMUP_BASE_ADDR_HIGH, mask_sh),\ + SF(MMHUBBUB_WARMUP_BASE_ADDR_LOW, MMHUBBUB_WARMUP_BASE_ADDR_LOW, mask_sh),\ + SF(MMHUBBUB_WARMUP_CONTROL_STATUS, MMHUBBUB_WARMUP_EN, mask_sh),\ + SF(MMHUBBUB_WARMUP_CONTROL_STATUS, MMHUBBUB_WARMUP_SW_INT_EN, mask_sh),\ + SF(MMHUBBUB_WARMUP_CONTROL_STATUS, MMHUBBUB_WARMUP_SW_INT_STATUS, mask_sh),\ + SF(MMHUBBUB_WARMUP_CONTROL_STATUS, MMHUBBUB_WARMUP_SW_INT_ACK, mask_sh),\ + SF(MMHUBBUB_WARMUP_CONTROL_STATUS, MMHUBBUB_WARMUP_INC_ADDR, mask_sh),\ + SF(MCIF_WB_DRAM_SPEED_CHANGE_DURATION_VBI, MCIF_WB_DRAM_SPEED_CHANGE_DURATION_VBI, mask_sh) + + +#define MCIF_WB_REG_FIELD_LIST_DCN3_0(type) \ + MCIF_WB_REG_FIELD_LIST_DCN2_0(type);\ + type WBIF_WHOLE_BUF_MODE;\ + type MMHUBBUB_WARMUP_ADDR_REGION;\ + type MMHUBBUB_WARMUP_BASE_ADDR_HIGH;\ + type MMHUBBUB_WARMUP_BASE_ADDR_LOW;\ + type MMHUBBUB_WARMUP_EN;\ + type MMHUBBUB_WARMUP_SW_INT_EN;\ + type MMHUBBUB_WARMUP_SW_INT_STATUS;\ + type MMHUBBUB_WARMUP_SW_INT_ACK;\ + type MMHUBBUB_WARMUP_INC_ADDR;\ + type MMHUBBUB_WARMUP_P_VMID;\ + type MCIF_WB_DRAM_SPEED_CHANGE_DURATION_VBI + +#define MCIF_WB_REG_VARIABLE_LIST_DCN3_0 \ + MCIF_WB_REG_VARIABLE_LIST_DCN2_0; \ + uint32_t MMHUBBUB_MEM_PWR_CNTL;\ + uint32_t MMHUBBUB_WARMUP_ADDR_REGION;\ + uint32_t MMHUBBUB_WARMUP_BASE_ADDR_HIGH;\ + uint32_t MMHUBBUB_WARMUP_BASE_ADDR_LOW;\ + uint32_t MMHUBBUB_WARMUP_CONTROL_STATUS;\ + uint32_t MMHUBBUB_WARMUP_P_VMID;\ + uint32_t MCIF_WB_DRAM_SPEED_CHANGE_DURATION_VBI + +struct dcn30_mmhubbub_registers { + MCIF_WB_REG_VARIABLE_LIST_DCN3_0; +}; + + +struct dcn30_mmhubbub_mask { + MCIF_WB_REG_FIELD_LIST_DCN3_0(uint32_t); +}; + +struct dcn30_mmhubbub_shift { + MCIF_WB_REG_FIELD_LIST_DCN3_0(uint8_t); +}; + +struct dcn30_mmhubbub { + struct mcif_wb base; + const struct dcn30_mmhubbub_registers *mcif_wb_regs; + const struct dcn30_mmhubbub_shift *mcif_wb_shift; + const struct dcn30_mmhubbub_mask *mcif_wb_mask; +}; + +void dcn30_mmhubbub_construct(struct dcn30_mmhubbub *mcif_wb30, + struct dc_context *ctx, + const struct dcn30_mmhubbub_registers *mcif_wb_regs, + const struct dcn30_mmhubbub_shift *mcif_wb_shift, + const struct dcn30_mmhubbub_mask *mcif_wb_mask, + int inst); + +#endif diff --git a/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_mpc.c b/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_mpc.c new file mode 100644 index 000000000..ad1c1b703 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_mpc.c @@ -0,0 +1,1461 @@ +/* + * Copyright 2020 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 "reg_helper.h" +#include "dcn30_mpc.h" +#include "dcn30_cm_common.h" +#include "basics/conversion.h" +#include "dcn10/dcn10_cm_common.h" +#include "dc.h" + +#define REG(reg)\ + mpc30->mpc_regs->reg + +#define CTX \ + mpc30->base.ctx + +#undef FN +#define FN(reg_name, field_name) \ + mpc30->mpc_shift->field_name, mpc30->mpc_mask->field_name + + +#define NUM_ELEMENTS(a) (sizeof(a) / sizeof((a)[0])) + + +bool mpc3_is_dwb_idle( + struct mpc *mpc, + int dwb_id) +{ + struct dcn30_mpc *mpc30 = TO_DCN30_MPC(mpc); + unsigned int status; + + REG_GET(DWB_MUX[dwb_id], MPC_DWB0_MUX_STATUS, &status); + + if (status == 0xf) + return true; + else + return false; +} + +void mpc3_set_dwb_mux( + struct mpc *mpc, + int dwb_id, + int mpcc_id) +{ + struct dcn30_mpc *mpc30 = TO_DCN30_MPC(mpc); + + REG_SET(DWB_MUX[dwb_id], 0, + MPC_DWB0_MUX, mpcc_id); +} + +void mpc3_disable_dwb_mux( + struct mpc *mpc, + int dwb_id) +{ + struct dcn30_mpc *mpc30 = TO_DCN30_MPC(mpc); + + REG_SET(DWB_MUX[dwb_id], 0, + MPC_DWB0_MUX, 0xf); +} + +void mpc3_set_out_rate_control( + struct mpc *mpc, + int opp_id, + bool enable, + bool rate_2x_mode, + struct mpc_dwb_flow_control *flow_control) +{ + struct dcn30_mpc *mpc30 = TO_DCN30_MPC(mpc); + + REG_UPDATE_2(MUX[opp_id], + MPC_OUT_RATE_CONTROL_DISABLE, !enable, + MPC_OUT_RATE_CONTROL, rate_2x_mode); + + if (flow_control) + REG_UPDATE_2(MUX[opp_id], + MPC_OUT_FLOW_CONTROL_MODE, flow_control->flow_ctrl_mode, + MPC_OUT_FLOW_CONTROL_COUNT, flow_control->flow_ctrl_cnt1); +} + +enum dc_lut_mode mpc3_get_ogam_current(struct mpc *mpc, int mpcc_id) +{ + /*Contrary to DCN2 and DCN1 wherein a single status register field holds this info; + *in DCN3/3AG, we need to read two separate fields to retrieve the same info + */ + enum dc_lut_mode mode; + uint32_t state_mode; + uint32_t state_ram_lut_in_use; + struct dcn30_mpc *mpc30 = TO_DCN30_MPC(mpc); + + REG_GET_2(MPCC_OGAM_CONTROL[mpcc_id], MPCC_OGAM_MODE_CURRENT, &state_mode, + MPCC_OGAM_SELECT_CURRENT, &state_ram_lut_in_use); + + switch (state_mode) { + case 0: + mode = LUT_BYPASS; + break; + case 2: + switch (state_ram_lut_in_use) { + case 0: + mode = LUT_RAM_A; + break; + case 1: + mode = LUT_RAM_B; + break; + default: + mode = LUT_BYPASS; + break; + } + break; + default: + mode = LUT_BYPASS; + break; + } + + return mode; +} + +void mpc3_power_on_ogam_lut( + struct mpc *mpc, int mpcc_id, + bool power_on) +{ + struct dcn30_mpc *mpc30 = TO_DCN30_MPC(mpc); + + /* + * Powering on: force memory active so the LUT can be updated. + * Powering off: allow entering memory low power mode + * + * Memory low power mode is controlled during MPC OGAM LUT init. + */ + REG_UPDATE(MPCC_MEM_PWR_CTRL[mpcc_id], + MPCC_OGAM_MEM_PWR_DIS, power_on != 0); + + /* Wait for memory to be powered on - we won't be able to write to it otherwise. */ + if (power_on) + REG_WAIT(MPCC_MEM_PWR_CTRL[mpcc_id], MPCC_OGAM_MEM_PWR_STATE, 0, 10, 10); +} + +static void mpc3_configure_ogam_lut( + struct mpc *mpc, int mpcc_id, + bool is_ram_a) +{ + struct dcn30_mpc *mpc30 = TO_DCN30_MPC(mpc); + + REG_UPDATE_2(MPCC_OGAM_LUT_CONTROL[mpcc_id], + MPCC_OGAM_LUT_WRITE_COLOR_MASK, 7, + MPCC_OGAM_LUT_HOST_SEL, is_ram_a == true ? 0:1); + + REG_SET(MPCC_OGAM_LUT_INDEX[mpcc_id], 0, MPCC_OGAM_LUT_INDEX, 0); +} + +static void mpc3_ogam_get_reg_field( + struct mpc *mpc, + struct dcn3_xfer_func_reg *reg) +{ + struct dcn30_mpc *mpc30 = TO_DCN30_MPC(mpc); + + reg->shifts.field_region_start_base = mpc30->mpc_shift->MPCC_OGAM_RAMA_EXP_REGION_START_BASE_B; + reg->masks.field_region_start_base = mpc30->mpc_mask->MPCC_OGAM_RAMA_EXP_REGION_START_BASE_B; + reg->shifts.field_offset = mpc30->mpc_shift->MPCC_OGAM_RAMA_OFFSET_B; + reg->masks.field_offset = mpc30->mpc_mask->MPCC_OGAM_RAMA_OFFSET_B; + + reg->shifts.exp_region0_lut_offset = mpc30->mpc_shift->MPCC_OGAM_RAMA_EXP_REGION0_LUT_OFFSET; + reg->masks.exp_region0_lut_offset = mpc30->mpc_mask->MPCC_OGAM_RAMA_EXP_REGION0_LUT_OFFSET; + reg->shifts.exp_region0_num_segments = mpc30->mpc_shift->MPCC_OGAM_RAMA_EXP_REGION0_NUM_SEGMENTS; + reg->masks.exp_region0_num_segments = mpc30->mpc_mask->MPCC_OGAM_RAMA_EXP_REGION0_NUM_SEGMENTS; + reg->shifts.exp_region1_lut_offset = mpc30->mpc_shift->MPCC_OGAM_RAMA_EXP_REGION1_LUT_OFFSET; + reg->masks.exp_region1_lut_offset = mpc30->mpc_mask->MPCC_OGAM_RAMA_EXP_REGION1_LUT_OFFSET; + reg->shifts.exp_region1_num_segments = mpc30->mpc_shift->MPCC_OGAM_RAMA_EXP_REGION1_NUM_SEGMENTS; + reg->masks.exp_region1_num_segments = mpc30->mpc_mask->MPCC_OGAM_RAMA_EXP_REGION1_NUM_SEGMENTS; + + reg->shifts.field_region_end = mpc30->mpc_shift->MPCC_OGAM_RAMA_EXP_REGION_END_B; + reg->masks.field_region_end = mpc30->mpc_mask->MPCC_OGAM_RAMA_EXP_REGION_END_B; + reg->shifts.field_region_end_slope = mpc30->mpc_shift->MPCC_OGAM_RAMA_EXP_REGION_END_SLOPE_B; + reg->masks.field_region_end_slope = mpc30->mpc_mask->MPCC_OGAM_RAMA_EXP_REGION_END_SLOPE_B; + reg->shifts.field_region_end_base = mpc30->mpc_shift->MPCC_OGAM_RAMA_EXP_REGION_END_BASE_B; + reg->masks.field_region_end_base = mpc30->mpc_mask->MPCC_OGAM_RAMA_EXP_REGION_END_BASE_B; + reg->shifts.field_region_linear_slope = mpc30->mpc_shift->MPCC_OGAM_RAMA_EXP_REGION_START_SLOPE_B; + reg->masks.field_region_linear_slope = mpc30->mpc_mask->MPCC_OGAM_RAMA_EXP_REGION_START_SLOPE_B; + reg->shifts.exp_region_start = mpc30->mpc_shift->MPCC_OGAM_RAMA_EXP_REGION_START_B; + reg->masks.exp_region_start = mpc30->mpc_mask->MPCC_OGAM_RAMA_EXP_REGION_START_B; + reg->shifts.exp_resion_start_segment = mpc30->mpc_shift->MPCC_OGAM_RAMA_EXP_REGION_START_SEGMENT_B; + reg->masks.exp_resion_start_segment = mpc30->mpc_mask->MPCC_OGAM_RAMA_EXP_REGION_START_SEGMENT_B; +} + +static void mpc3_program_luta(struct mpc *mpc, int mpcc_id, + const struct pwl_params *params) +{ + struct dcn30_mpc *mpc30 = TO_DCN30_MPC(mpc); + struct dcn3_xfer_func_reg gam_regs; + + mpc3_ogam_get_reg_field(mpc, &gam_regs); + + gam_regs.start_cntl_b = REG(MPCC_OGAM_RAMA_START_CNTL_B[mpcc_id]); + gam_regs.start_cntl_g = REG(MPCC_OGAM_RAMA_START_CNTL_G[mpcc_id]); + gam_regs.start_cntl_r = REG(MPCC_OGAM_RAMA_START_CNTL_R[mpcc_id]); + gam_regs.start_slope_cntl_b = REG(MPCC_OGAM_RAMA_START_SLOPE_CNTL_B[mpcc_id]); + gam_regs.start_slope_cntl_g = REG(MPCC_OGAM_RAMA_START_SLOPE_CNTL_G[mpcc_id]); + gam_regs.start_slope_cntl_r = REG(MPCC_OGAM_RAMA_START_SLOPE_CNTL_R[mpcc_id]); + gam_regs.start_end_cntl1_b = REG(MPCC_OGAM_RAMA_END_CNTL1_B[mpcc_id]); + gam_regs.start_end_cntl2_b = REG(MPCC_OGAM_RAMA_END_CNTL2_B[mpcc_id]); + gam_regs.start_end_cntl1_g = REG(MPCC_OGAM_RAMA_END_CNTL1_G[mpcc_id]); + gam_regs.start_end_cntl2_g = REG(MPCC_OGAM_RAMA_END_CNTL2_G[mpcc_id]); + gam_regs.start_end_cntl1_r = REG(MPCC_OGAM_RAMA_END_CNTL1_R[mpcc_id]); + gam_regs.start_end_cntl2_r = REG(MPCC_OGAM_RAMA_END_CNTL2_R[mpcc_id]); + gam_regs.region_start = REG(MPCC_OGAM_RAMA_REGION_0_1[mpcc_id]); + gam_regs.region_end = REG(MPCC_OGAM_RAMA_REGION_32_33[mpcc_id]); + //New registers in DCN3AG/DCN OGAM block + gam_regs.offset_b = REG(MPCC_OGAM_RAMA_OFFSET_B[mpcc_id]); + gam_regs.offset_g = REG(MPCC_OGAM_RAMA_OFFSET_G[mpcc_id]); + gam_regs.offset_r = REG(MPCC_OGAM_RAMA_OFFSET_R[mpcc_id]); + gam_regs.start_base_cntl_b = REG(MPCC_OGAM_RAMA_START_BASE_CNTL_B[mpcc_id]); + gam_regs.start_base_cntl_g = REG(MPCC_OGAM_RAMA_START_BASE_CNTL_G[mpcc_id]); + gam_regs.start_base_cntl_r = REG(MPCC_OGAM_RAMA_START_BASE_CNTL_R[mpcc_id]); + + cm_helper_program_gamcor_xfer_func(mpc30->base.ctx, params, &gam_regs); +} + +static void mpc3_program_lutb(struct mpc *mpc, int mpcc_id, + const struct pwl_params *params) +{ + struct dcn30_mpc *mpc30 = TO_DCN30_MPC(mpc); + struct dcn3_xfer_func_reg gam_regs; + + mpc3_ogam_get_reg_field(mpc, &gam_regs); + + gam_regs.start_cntl_b = REG(MPCC_OGAM_RAMB_START_CNTL_B[mpcc_id]); + gam_regs.start_cntl_g = REG(MPCC_OGAM_RAMB_START_CNTL_G[mpcc_id]); + gam_regs.start_cntl_r = REG(MPCC_OGAM_RAMB_START_CNTL_R[mpcc_id]); + gam_regs.start_slope_cntl_b = REG(MPCC_OGAM_RAMB_START_SLOPE_CNTL_B[mpcc_id]); + gam_regs.start_slope_cntl_g = REG(MPCC_OGAM_RAMB_START_SLOPE_CNTL_G[mpcc_id]); + gam_regs.start_slope_cntl_r = REG(MPCC_OGAM_RAMB_START_SLOPE_CNTL_R[mpcc_id]); + gam_regs.start_end_cntl1_b = REG(MPCC_OGAM_RAMB_END_CNTL1_B[mpcc_id]); + gam_regs.start_end_cntl2_b = REG(MPCC_OGAM_RAMB_END_CNTL2_B[mpcc_id]); + gam_regs.start_end_cntl1_g = REG(MPCC_OGAM_RAMB_END_CNTL1_G[mpcc_id]); + gam_regs.start_end_cntl2_g = REG(MPCC_OGAM_RAMB_END_CNTL2_G[mpcc_id]); + gam_regs.start_end_cntl1_r = REG(MPCC_OGAM_RAMB_END_CNTL1_R[mpcc_id]); + gam_regs.start_end_cntl2_r = REG(MPCC_OGAM_RAMB_END_CNTL2_R[mpcc_id]); + gam_regs.region_start = REG(MPCC_OGAM_RAMB_REGION_0_1[mpcc_id]); + gam_regs.region_end = REG(MPCC_OGAM_RAMB_REGION_32_33[mpcc_id]); + //New registers in DCN3AG/DCN OGAM block + gam_regs.offset_b = REG(MPCC_OGAM_RAMB_OFFSET_B[mpcc_id]); + gam_regs.offset_g = REG(MPCC_OGAM_RAMB_OFFSET_G[mpcc_id]); + gam_regs.offset_r = REG(MPCC_OGAM_RAMB_OFFSET_R[mpcc_id]); + gam_regs.start_base_cntl_b = REG(MPCC_OGAM_RAMB_START_BASE_CNTL_B[mpcc_id]); + gam_regs.start_base_cntl_g = REG(MPCC_OGAM_RAMB_START_BASE_CNTL_G[mpcc_id]); + gam_regs.start_base_cntl_r = REG(MPCC_OGAM_RAMB_START_BASE_CNTL_R[mpcc_id]); + + cm_helper_program_gamcor_xfer_func(mpc30->base.ctx, params, &gam_regs); +} + + +static void mpc3_program_ogam_pwl( + struct mpc *mpc, int mpcc_id, + const struct pwl_result_data *rgb, + uint32_t num) +{ + uint32_t i; + struct dcn30_mpc *mpc30 = TO_DCN30_MPC(mpc); + uint32_t last_base_value_red = rgb[num-1].red_reg + rgb[num-1].delta_red_reg; + uint32_t last_base_value_green = rgb[num-1].green_reg + rgb[num-1].delta_green_reg; + uint32_t last_base_value_blue = rgb[num-1].blue_reg + rgb[num-1].delta_blue_reg; + + /*the entries of DCN3AG gamma LUTs take 18bit base values as opposed to + *38 base+delta values per entry in earlier DCN architectures + *last base value for our lut is compute by adding the last base value + *in our data + last delta + */ + + if (is_rgb_equal(rgb, num)) { + for (i = 0 ; i < num; i++) + REG_SET(MPCC_OGAM_LUT_DATA[mpcc_id], 0, MPCC_OGAM_LUT_DATA, rgb[i].red_reg); + + REG_SET(MPCC_OGAM_LUT_DATA[mpcc_id], 0, MPCC_OGAM_LUT_DATA, last_base_value_red); + + } else { + + REG_UPDATE(MPCC_OGAM_LUT_CONTROL[mpcc_id], + MPCC_OGAM_LUT_WRITE_COLOR_MASK, 4); + + for (i = 0 ; i < num; i++) + REG_SET(MPCC_OGAM_LUT_DATA[mpcc_id], 0, MPCC_OGAM_LUT_DATA, rgb[i].red_reg); + + REG_SET(MPCC_OGAM_LUT_DATA[mpcc_id], 0, MPCC_OGAM_LUT_DATA, last_base_value_red); + + REG_SET(MPCC_OGAM_LUT_INDEX[mpcc_id], 0, MPCC_OGAM_LUT_INDEX, 0); + + REG_UPDATE(MPCC_OGAM_LUT_CONTROL[mpcc_id], + MPCC_OGAM_LUT_WRITE_COLOR_MASK, 2); + + for (i = 0 ; i < num; i++) + REG_SET(MPCC_OGAM_LUT_DATA[mpcc_id], 0, MPCC_OGAM_LUT_DATA, rgb[i].green_reg); + + REG_SET(MPCC_OGAM_LUT_DATA[mpcc_id], 0, MPCC_OGAM_LUT_DATA, last_base_value_green); + + REG_SET(MPCC_OGAM_LUT_INDEX[mpcc_id], 0, MPCC_OGAM_LUT_INDEX, 0); + + REG_UPDATE(MPCC_OGAM_LUT_CONTROL[mpcc_id], + MPCC_OGAM_LUT_WRITE_COLOR_MASK, 1); + + for (i = 0 ; i < num; i++) + REG_SET(MPCC_OGAM_LUT_DATA[mpcc_id], 0, MPCC_OGAM_LUT_DATA, rgb[i].blue_reg); + + REG_SET(MPCC_OGAM_LUT_DATA[mpcc_id], 0, MPCC_OGAM_LUT_DATA, last_base_value_blue); + } + +} + +void mpc3_set_output_gamma( + struct mpc *mpc, + int mpcc_id, + const struct pwl_params *params) +{ + enum dc_lut_mode current_mode; + enum dc_lut_mode next_mode; + struct dcn30_mpc *mpc30 = TO_DCN30_MPC(mpc); + + if (mpc->ctx->dc->debug.cm_in_bypass) { + REG_SET(MPCC_OGAM_MODE[mpcc_id], 0, MPCC_OGAM_MODE, 0); + return; + } + + if (params == NULL) { //disable OGAM + REG_SET(MPCC_OGAM_CONTROL[mpcc_id], 0, MPCC_OGAM_MODE, 0); + return; + } + //enable OGAM + REG_SET(MPCC_OGAM_CONTROL[mpcc_id], 0, MPCC_OGAM_MODE, 2); + + current_mode = mpc3_get_ogam_current(mpc, mpcc_id); + if (current_mode == LUT_BYPASS) + next_mode = LUT_RAM_A; + else if (current_mode == LUT_RAM_A) + next_mode = LUT_RAM_B; + else + next_mode = LUT_RAM_A; + + mpc3_power_on_ogam_lut(mpc, mpcc_id, true); + mpc3_configure_ogam_lut(mpc, mpcc_id, next_mode == LUT_RAM_A); + + if (next_mode == LUT_RAM_A) + mpc3_program_luta(mpc, mpcc_id, params); + else + mpc3_program_lutb(mpc, mpcc_id, params); + + mpc3_program_ogam_pwl( + mpc, mpcc_id, params->rgb_resulted, params->hw_points_num); + + /*we need to program 2 fields here as apposed to 1*/ + REG_UPDATE(MPCC_OGAM_CONTROL[mpcc_id], + MPCC_OGAM_SELECT, next_mode == LUT_RAM_A ? 0:1); + + if (mpc->ctx->dc->debug.enable_mem_low_power.bits.mpc) + mpc3_power_on_ogam_lut(mpc, mpcc_id, false); +} + +void mpc3_set_denorm( + struct mpc *mpc, + int opp_id, + enum dc_color_depth output_depth) +{ + struct dcn30_mpc *mpc30 = TO_DCN30_MPC(mpc); + /* De-normalize Fixed U1.13 color data to different target bit depths. 0 is bypass*/ + int denorm_mode = 0; + + switch (output_depth) { + case COLOR_DEPTH_666: + denorm_mode = 1; + break; + case COLOR_DEPTH_888: + denorm_mode = 2; + break; + case COLOR_DEPTH_999: + denorm_mode = 3; + break; + case COLOR_DEPTH_101010: + denorm_mode = 4; + break; + case COLOR_DEPTH_111111: + denorm_mode = 5; + break; + case COLOR_DEPTH_121212: + denorm_mode = 6; + break; + case COLOR_DEPTH_141414: + case COLOR_DEPTH_161616: + default: + /* not valid used case! */ + break; + } + + REG_UPDATE(DENORM_CONTROL[opp_id], + MPC_OUT_DENORM_MODE, denorm_mode); +} + +void mpc3_set_denorm_clamp( + struct mpc *mpc, + int opp_id, + struct mpc_denorm_clamp denorm_clamp) +{ + struct dcn30_mpc *mpc30 = TO_DCN30_MPC(mpc); + + /*program min and max clamp values for the pixel components*/ + REG_UPDATE_2(DENORM_CONTROL[opp_id], + MPC_OUT_DENORM_CLAMP_MAX_R_CR, denorm_clamp.clamp_max_r_cr, + MPC_OUT_DENORM_CLAMP_MIN_R_CR, denorm_clamp.clamp_min_r_cr); + REG_UPDATE_2(DENORM_CLAMP_G_Y[opp_id], + MPC_OUT_DENORM_CLAMP_MAX_G_Y, denorm_clamp.clamp_max_g_y, + MPC_OUT_DENORM_CLAMP_MIN_G_Y, denorm_clamp.clamp_min_g_y); + REG_UPDATE_2(DENORM_CLAMP_B_CB[opp_id], + MPC_OUT_DENORM_CLAMP_MAX_B_CB, denorm_clamp.clamp_max_b_cb, + MPC_OUT_DENORM_CLAMP_MIN_B_CB, denorm_clamp.clamp_min_b_cb); +} + +static enum dc_lut_mode mpc3_get_shaper_current(struct mpc *mpc, uint32_t rmu_idx) +{ + enum dc_lut_mode mode; + uint32_t state_mode; + struct dcn30_mpc *mpc30 = TO_DCN30_MPC(mpc); + + REG_GET(SHAPER_CONTROL[rmu_idx], MPC_RMU_SHAPER_LUT_MODE_CURRENT, &state_mode); + + switch (state_mode) { + case 0: + mode = LUT_BYPASS; + break; + case 1: + mode = LUT_RAM_A; + break; + case 2: + mode = LUT_RAM_B; + break; + default: + mode = LUT_BYPASS; + break; + } + + return mode; +} + +static void mpc3_configure_shaper_lut( + struct mpc *mpc, + bool is_ram_a, + uint32_t rmu_idx) +{ + struct dcn30_mpc *mpc30 = TO_DCN30_MPC(mpc); + + REG_UPDATE(SHAPER_LUT_WRITE_EN_MASK[rmu_idx], + MPC_RMU_SHAPER_LUT_WRITE_EN_MASK, 7); + REG_UPDATE(SHAPER_LUT_WRITE_EN_MASK[rmu_idx], + MPC_RMU_SHAPER_LUT_WRITE_SEL, is_ram_a == true ? 0:1); + REG_SET(SHAPER_LUT_INDEX[rmu_idx], 0, MPC_RMU_SHAPER_LUT_INDEX, 0); +} + +static void mpc3_program_shaper_luta_settings( + struct mpc *mpc, + const struct pwl_params *params, + uint32_t rmu_idx) +{ + const struct gamma_curve *curve; + struct dcn30_mpc *mpc30 = TO_DCN30_MPC(mpc); + + REG_SET_2(SHAPER_RAMA_START_CNTL_B[rmu_idx], 0, + MPC_RMU_SHAPER_RAMA_EXP_REGION_START_B, params->corner_points[0].blue.custom_float_x, + MPC_RMU_SHAPER_RAMA_EXP_REGION_START_SEGMENT_B, 0); + REG_SET_2(SHAPER_RAMA_START_CNTL_G[rmu_idx], 0, + MPC_RMU_SHAPER_RAMA_EXP_REGION_START_B, params->corner_points[0].green.custom_float_x, + MPC_RMU_SHAPER_RAMA_EXP_REGION_START_SEGMENT_B, 0); + REG_SET_2(SHAPER_RAMA_START_CNTL_R[rmu_idx], 0, + MPC_RMU_SHAPER_RAMA_EXP_REGION_START_B, params->corner_points[0].red.custom_float_x, + MPC_RMU_SHAPER_RAMA_EXP_REGION_START_SEGMENT_B, 0); + + REG_SET_2(SHAPER_RAMA_END_CNTL_B[rmu_idx], 0, + MPC_RMU_SHAPER_RAMA_EXP_REGION_END_B, params->corner_points[1].blue.custom_float_x, + MPC_RMU_SHAPER_RAMA_EXP_REGION_END_BASE_B, params->corner_points[1].blue.custom_float_y); + REG_SET_2(SHAPER_RAMA_END_CNTL_G[rmu_idx], 0, + MPC_RMU_SHAPER_RAMA_EXP_REGION_END_B, params->corner_points[1].green.custom_float_x, + MPC_RMU_SHAPER_RAMA_EXP_REGION_END_BASE_B, params->corner_points[1].green.custom_float_y); + REG_SET_2(SHAPER_RAMA_END_CNTL_R[rmu_idx], 0, + MPC_RMU_SHAPER_RAMA_EXP_REGION_END_B, params->corner_points[1].red.custom_float_x, + MPC_RMU_SHAPER_RAMA_EXP_REGION_END_BASE_B, params->corner_points[1].red.custom_float_y); + + curve = params->arr_curve_points; + REG_SET_4(SHAPER_RAMA_REGION_0_1[rmu_idx], 0, + MPC_RMU_SHAPER_RAMA_EXP_REGION0_LUT_OFFSET, curve[0].offset, + MPC_RMU_SHAPER_RAMA_EXP_REGION0_NUM_SEGMENTS, curve[0].segments_num, + MPC_RMU_SHAPER_RAMA_EXP_REGION1_LUT_OFFSET, curve[1].offset, + MPC_RMU_SHAPER_RAMA_EXP_REGION1_NUM_SEGMENTS, curve[1].segments_num); + + curve += 2; + REG_SET_4(SHAPER_RAMA_REGION_2_3[rmu_idx], 0, + MPC_RMU_SHAPER_RAMA_EXP_REGION0_LUT_OFFSET, curve[0].offset, + MPC_RMU_SHAPER_RAMA_EXP_REGION0_NUM_SEGMENTS, curve[0].segments_num, + MPC_RMU_SHAPER_RAMA_EXP_REGION1_LUT_OFFSET, curve[1].offset, + MPC_RMU_SHAPER_RAMA_EXP_REGION1_NUM_SEGMENTS, curve[1].segments_num); + + curve += 2; + REG_SET_4(SHAPER_RAMA_REGION_4_5[rmu_idx], 0, + MPC_RMU_SHAPER_RAMA_EXP_REGION0_LUT_OFFSET, curve[0].offset, + MPC_RMU_SHAPER_RAMA_EXP_REGION0_NUM_SEGMENTS, curve[0].segments_num, + MPC_RMU_SHAPER_RAMA_EXP_REGION1_LUT_OFFSET, curve[1].offset, + MPC_RMU_SHAPER_RAMA_EXP_REGION1_NUM_SEGMENTS, curve[1].segments_num); + + curve += 2; + REG_SET_4(SHAPER_RAMA_REGION_6_7[rmu_idx], 0, + MPC_RMU_SHAPER_RAMA_EXP_REGION0_LUT_OFFSET, curve[0].offset, + MPC_RMU_SHAPER_RAMA_EXP_REGION0_NUM_SEGMENTS, curve[0].segments_num, + MPC_RMU_SHAPER_RAMA_EXP_REGION1_LUT_OFFSET, curve[1].offset, + MPC_RMU_SHAPER_RAMA_EXP_REGION1_NUM_SEGMENTS, curve[1].segments_num); + + curve += 2; + REG_SET_4(SHAPER_RAMA_REGION_8_9[rmu_idx], 0, + MPC_RMU_SHAPER_RAMA_EXP_REGION0_LUT_OFFSET, curve[0].offset, + MPC_RMU_SHAPER_RAMA_EXP_REGION0_NUM_SEGMENTS, curve[0].segments_num, + MPC_RMU_SHAPER_RAMA_EXP_REGION1_LUT_OFFSET, curve[1].offset, + MPC_RMU_SHAPER_RAMA_EXP_REGION1_NUM_SEGMENTS, curve[1].segments_num); + + curve += 2; + REG_SET_4(SHAPER_RAMA_REGION_10_11[rmu_idx], 0, + MPC_RMU_SHAPER_RAMA_EXP_REGION0_LUT_OFFSET, curve[0].offset, + MPC_RMU_SHAPER_RAMA_EXP_REGION0_NUM_SEGMENTS, curve[0].segments_num, + MPC_RMU_SHAPER_RAMA_EXP_REGION1_LUT_OFFSET, curve[1].offset, + MPC_RMU_SHAPER_RAMA_EXP_REGION1_NUM_SEGMENTS, curve[1].segments_num); + + curve += 2; + REG_SET_4(SHAPER_RAMA_REGION_12_13[rmu_idx], 0, + MPC_RMU_SHAPER_RAMA_EXP_REGION0_LUT_OFFSET, curve[0].offset, + MPC_RMU_SHAPER_RAMA_EXP_REGION0_NUM_SEGMENTS, curve[0].segments_num, + MPC_RMU_SHAPER_RAMA_EXP_REGION1_LUT_OFFSET, curve[1].offset, + MPC_RMU_SHAPER_RAMA_EXP_REGION1_NUM_SEGMENTS, curve[1].segments_num); + + curve += 2; + REG_SET_4(SHAPER_RAMA_REGION_14_15[rmu_idx], 0, + MPC_RMU_SHAPER_RAMA_EXP_REGION0_LUT_OFFSET, curve[0].offset, + MPC_RMU_SHAPER_RAMA_EXP_REGION0_NUM_SEGMENTS, curve[0].segments_num, + MPC_RMU_SHAPER_RAMA_EXP_REGION1_LUT_OFFSET, curve[1].offset, + MPC_RMU_SHAPER_RAMA_EXP_REGION1_NUM_SEGMENTS, curve[1].segments_num); + + + curve += 2; + REG_SET_4(SHAPER_RAMA_REGION_16_17[rmu_idx], 0, + MPC_RMU_SHAPER_RAMA_EXP_REGION0_LUT_OFFSET, curve[0].offset, + MPC_RMU_SHAPER_RAMA_EXP_REGION0_NUM_SEGMENTS, curve[0].segments_num, + MPC_RMU_SHAPER_RAMA_EXP_REGION1_LUT_OFFSET, curve[1].offset, + MPC_RMU_SHAPER_RAMA_EXP_REGION1_NUM_SEGMENTS, curve[1].segments_num); + + curve += 2; + REG_SET_4(SHAPER_RAMA_REGION_18_19[rmu_idx], 0, + MPC_RMU_SHAPER_RAMA_EXP_REGION0_LUT_OFFSET, curve[0].offset, + MPC_RMU_SHAPER_RAMA_EXP_REGION0_NUM_SEGMENTS, curve[0].segments_num, + MPC_RMU_SHAPER_RAMA_EXP_REGION1_LUT_OFFSET, curve[1].offset, + MPC_RMU_SHAPER_RAMA_EXP_REGION1_NUM_SEGMENTS, curve[1].segments_num); + + curve += 2; + REG_SET_4(SHAPER_RAMA_REGION_20_21[rmu_idx], 0, + MPC_RMU_SHAPER_RAMA_EXP_REGION0_LUT_OFFSET, curve[0].offset, + MPC_RMU_SHAPER_RAMA_EXP_REGION0_NUM_SEGMENTS, curve[0].segments_num, + MPC_RMU_SHAPER_RAMA_EXP_REGION1_LUT_OFFSET, curve[1].offset, + MPC_RMU_SHAPER_RAMA_EXP_REGION1_NUM_SEGMENTS, curve[1].segments_num); + + curve += 2; + REG_SET_4(SHAPER_RAMA_REGION_22_23[rmu_idx], 0, + MPC_RMU_SHAPER_RAMA_EXP_REGION0_LUT_OFFSET, curve[0].offset, + MPC_RMU_SHAPER_RAMA_EXP_REGION0_NUM_SEGMENTS, curve[0].segments_num, + MPC_RMU_SHAPER_RAMA_EXP_REGION1_LUT_OFFSET, curve[1].offset, + MPC_RMU_SHAPER_RAMA_EXP_REGION1_NUM_SEGMENTS, curve[1].segments_num); + + curve += 2; + REG_SET_4(SHAPER_RAMA_REGION_24_25[rmu_idx], 0, + MPC_RMU_SHAPER_RAMA_EXP_REGION0_LUT_OFFSET, curve[0].offset, + MPC_RMU_SHAPER_RAMA_EXP_REGION0_NUM_SEGMENTS, curve[0].segments_num, + MPC_RMU_SHAPER_RAMA_EXP_REGION1_LUT_OFFSET, curve[1].offset, + MPC_RMU_SHAPER_RAMA_EXP_REGION1_NUM_SEGMENTS, curve[1].segments_num); + + curve += 2; + REG_SET_4(SHAPER_RAMA_REGION_26_27[rmu_idx], 0, + MPC_RMU_SHAPER_RAMA_EXP_REGION0_LUT_OFFSET, curve[0].offset, + MPC_RMU_SHAPER_RAMA_EXP_REGION0_NUM_SEGMENTS, curve[0].segments_num, + MPC_RMU_SHAPER_RAMA_EXP_REGION1_LUT_OFFSET, curve[1].offset, + MPC_RMU_SHAPER_RAMA_EXP_REGION1_NUM_SEGMENTS, curve[1].segments_num); + + curve += 2; + REG_SET_4(SHAPER_RAMA_REGION_28_29[rmu_idx], 0, + MPC_RMU_SHAPER_RAMA_EXP_REGION0_LUT_OFFSET, curve[0].offset, + MPC_RMU_SHAPER_RAMA_EXP_REGION0_NUM_SEGMENTS, curve[0].segments_num, + MPC_RMU_SHAPER_RAMA_EXP_REGION1_LUT_OFFSET, curve[1].offset, + MPC_RMU_SHAPER_RAMA_EXP_REGION1_NUM_SEGMENTS, curve[1].segments_num); + + curve += 2; + REG_SET_4(SHAPER_RAMA_REGION_30_31[rmu_idx], 0, + MPC_RMU_SHAPER_RAMA_EXP_REGION0_LUT_OFFSET, curve[0].offset, + MPC_RMU_SHAPER_RAMA_EXP_REGION0_NUM_SEGMENTS, curve[0].segments_num, + MPC_RMU_SHAPER_RAMA_EXP_REGION1_LUT_OFFSET, curve[1].offset, + MPC_RMU_SHAPER_RAMA_EXP_REGION1_NUM_SEGMENTS, curve[1].segments_num); + + curve += 2; + REG_SET_4(SHAPER_RAMA_REGION_32_33[rmu_idx], 0, + MPC_RMU_SHAPER_RAMA_EXP_REGION0_LUT_OFFSET, curve[0].offset, + MPC_RMU_SHAPER_RAMA_EXP_REGION0_NUM_SEGMENTS, curve[0].segments_num, + MPC_RMU_SHAPER_RAMA_EXP_REGION1_LUT_OFFSET, curve[1].offset, + MPC_RMU_SHAPER_RAMA_EXP_REGION1_NUM_SEGMENTS, curve[1].segments_num); +} + +static void mpc3_program_shaper_lutb_settings( + struct mpc *mpc, + const struct pwl_params *params, + uint32_t rmu_idx) +{ + const struct gamma_curve *curve; + struct dcn30_mpc *mpc30 = TO_DCN30_MPC(mpc); + + REG_SET_2(SHAPER_RAMB_START_CNTL_B[rmu_idx], 0, + MPC_RMU_SHAPER_RAMA_EXP_REGION_START_B, params->corner_points[0].blue.custom_float_x, + MPC_RMU_SHAPER_RAMA_EXP_REGION_START_SEGMENT_B, 0); + REG_SET_2(SHAPER_RAMB_START_CNTL_G[rmu_idx], 0, + MPC_RMU_SHAPER_RAMA_EXP_REGION_START_B, params->corner_points[0].green.custom_float_x, + MPC_RMU_SHAPER_RAMA_EXP_REGION_START_SEGMENT_B, 0); + REG_SET_2(SHAPER_RAMB_START_CNTL_R[rmu_idx], 0, + MPC_RMU_SHAPER_RAMA_EXP_REGION_START_B, params->corner_points[0].red.custom_float_x, + MPC_RMU_SHAPER_RAMA_EXP_REGION_START_SEGMENT_B, 0); + + REG_SET_2(SHAPER_RAMB_END_CNTL_B[rmu_idx], 0, + MPC_RMU_SHAPER_RAMA_EXP_REGION_END_B, params->corner_points[1].blue.custom_float_x, + MPC_RMU_SHAPER_RAMA_EXP_REGION_END_BASE_B, params->corner_points[1].blue.custom_float_y); + REG_SET_2(SHAPER_RAMB_END_CNTL_G[rmu_idx], 0, + MPC_RMU_SHAPER_RAMA_EXP_REGION_END_B, params->corner_points[1].green.custom_float_x, + MPC_RMU_SHAPER_RAMA_EXP_REGION_END_BASE_B, params->corner_points[1].green.custom_float_y); + REG_SET_2(SHAPER_RAMB_END_CNTL_R[rmu_idx], 0, + MPC_RMU_SHAPER_RAMA_EXP_REGION_END_B, params->corner_points[1].red.custom_float_x, + MPC_RMU_SHAPER_RAMA_EXP_REGION_END_BASE_B, params->corner_points[1].red.custom_float_y); + + curve = params->arr_curve_points; + REG_SET_4(SHAPER_RAMB_REGION_0_1[rmu_idx], 0, + MPC_RMU_SHAPER_RAMA_EXP_REGION0_LUT_OFFSET, curve[0].offset, + MPC_RMU_SHAPER_RAMA_EXP_REGION0_NUM_SEGMENTS, curve[0].segments_num, + MPC_RMU_SHAPER_RAMA_EXP_REGION1_LUT_OFFSET, curve[1].offset, + MPC_RMU_SHAPER_RAMA_EXP_REGION1_NUM_SEGMENTS, curve[1].segments_num); + + curve += 2; + REG_SET_4(SHAPER_RAMB_REGION_2_3[rmu_idx], 0, + MPC_RMU_SHAPER_RAMA_EXP_REGION0_LUT_OFFSET, curve[0].offset, + MPC_RMU_SHAPER_RAMA_EXP_REGION0_NUM_SEGMENTS, curve[0].segments_num, + MPC_RMU_SHAPER_RAMA_EXP_REGION1_LUT_OFFSET, curve[1].offset, + MPC_RMU_SHAPER_RAMA_EXP_REGION1_NUM_SEGMENTS, curve[1].segments_num); + + + curve += 2; + REG_SET_4(SHAPER_RAMB_REGION_4_5[rmu_idx], 0, + MPC_RMU_SHAPER_RAMA_EXP_REGION0_LUT_OFFSET, curve[0].offset, + MPC_RMU_SHAPER_RAMA_EXP_REGION0_NUM_SEGMENTS, curve[0].segments_num, + MPC_RMU_SHAPER_RAMA_EXP_REGION1_LUT_OFFSET, curve[1].offset, + MPC_RMU_SHAPER_RAMA_EXP_REGION1_NUM_SEGMENTS, curve[1].segments_num); + + curve += 2; + REG_SET_4(SHAPER_RAMB_REGION_6_7[rmu_idx], 0, + MPC_RMU_SHAPER_RAMA_EXP_REGION0_LUT_OFFSET, curve[0].offset, + MPC_RMU_SHAPER_RAMA_EXP_REGION0_NUM_SEGMENTS, curve[0].segments_num, + MPC_RMU_SHAPER_RAMA_EXP_REGION1_LUT_OFFSET, curve[1].offset, + MPC_RMU_SHAPER_RAMA_EXP_REGION1_NUM_SEGMENTS, curve[1].segments_num); + + curve += 2; + REG_SET_4(SHAPER_RAMB_REGION_8_9[rmu_idx], 0, + MPC_RMU_SHAPER_RAMA_EXP_REGION0_LUT_OFFSET, curve[0].offset, + MPC_RMU_SHAPER_RAMA_EXP_REGION0_NUM_SEGMENTS, curve[0].segments_num, + MPC_RMU_SHAPER_RAMA_EXP_REGION1_LUT_OFFSET, curve[1].offset, + MPC_RMU_SHAPER_RAMA_EXP_REGION1_NUM_SEGMENTS, curve[1].segments_num); + + curve += 2; + REG_SET_4(SHAPER_RAMB_REGION_10_11[rmu_idx], 0, + MPC_RMU_SHAPER_RAMA_EXP_REGION0_LUT_OFFSET, curve[0].offset, + MPC_RMU_SHAPER_RAMA_EXP_REGION0_NUM_SEGMENTS, curve[0].segments_num, + MPC_RMU_SHAPER_RAMA_EXP_REGION1_LUT_OFFSET, curve[1].offset, + MPC_RMU_SHAPER_RAMA_EXP_REGION1_NUM_SEGMENTS, curve[1].segments_num); + + curve += 2; + REG_SET_4(SHAPER_RAMB_REGION_12_13[rmu_idx], 0, + MPC_RMU_SHAPER_RAMA_EXP_REGION0_LUT_OFFSET, curve[0].offset, + MPC_RMU_SHAPER_RAMA_EXP_REGION0_NUM_SEGMENTS, curve[0].segments_num, + MPC_RMU_SHAPER_RAMA_EXP_REGION1_LUT_OFFSET, curve[1].offset, + MPC_RMU_SHAPER_RAMA_EXP_REGION1_NUM_SEGMENTS, curve[1].segments_num); + + curve += 2; + REG_SET_4(SHAPER_RAMB_REGION_14_15[rmu_idx], 0, + MPC_RMU_SHAPER_RAMA_EXP_REGION0_LUT_OFFSET, curve[0].offset, + MPC_RMU_SHAPER_RAMA_EXP_REGION0_NUM_SEGMENTS, curve[0].segments_num, + MPC_RMU_SHAPER_RAMA_EXP_REGION1_LUT_OFFSET, curve[1].offset, + MPC_RMU_SHAPER_RAMA_EXP_REGION1_NUM_SEGMENTS, curve[1].segments_num); + + + curve += 2; + REG_SET_4(SHAPER_RAMB_REGION_16_17[rmu_idx], 0, + MPC_RMU_SHAPER_RAMA_EXP_REGION0_LUT_OFFSET, curve[0].offset, + MPC_RMU_SHAPER_RAMA_EXP_REGION0_NUM_SEGMENTS, curve[0].segments_num, + MPC_RMU_SHAPER_RAMA_EXP_REGION1_LUT_OFFSET, curve[1].offset, + MPC_RMU_SHAPER_RAMA_EXP_REGION1_NUM_SEGMENTS, curve[1].segments_num); + + curve += 2; + REG_SET_4(SHAPER_RAMB_REGION_18_19[rmu_idx], 0, + MPC_RMU_SHAPER_RAMA_EXP_REGION0_LUT_OFFSET, curve[0].offset, + MPC_RMU_SHAPER_RAMA_EXP_REGION0_NUM_SEGMENTS, curve[0].segments_num, + MPC_RMU_SHAPER_RAMA_EXP_REGION1_LUT_OFFSET, curve[1].offset, + MPC_RMU_SHAPER_RAMA_EXP_REGION1_NUM_SEGMENTS, curve[1].segments_num); + + curve += 2; + REG_SET_4(SHAPER_RAMB_REGION_20_21[rmu_idx], 0, + MPC_RMU_SHAPER_RAMA_EXP_REGION0_LUT_OFFSET, curve[0].offset, + MPC_RMU_SHAPER_RAMA_EXP_REGION0_NUM_SEGMENTS, curve[0].segments_num, + MPC_RMU_SHAPER_RAMA_EXP_REGION1_LUT_OFFSET, curve[1].offset, + MPC_RMU_SHAPER_RAMA_EXP_REGION1_NUM_SEGMENTS, curve[1].segments_num); + + curve += 2; + REG_SET_4(SHAPER_RAMB_REGION_22_23[rmu_idx], 0, + MPC_RMU_SHAPER_RAMA_EXP_REGION0_LUT_OFFSET, curve[0].offset, + MPC_RMU_SHAPER_RAMA_EXP_REGION0_NUM_SEGMENTS, curve[0].segments_num, + MPC_RMU_SHAPER_RAMA_EXP_REGION1_LUT_OFFSET, curve[1].offset, + MPC_RMU_SHAPER_RAMA_EXP_REGION1_NUM_SEGMENTS, curve[1].segments_num); + + curve += 2; + REG_SET_4(SHAPER_RAMB_REGION_24_25[rmu_idx], 0, + MPC_RMU_SHAPER_RAMA_EXP_REGION0_LUT_OFFSET, curve[0].offset, + MPC_RMU_SHAPER_RAMA_EXP_REGION0_NUM_SEGMENTS, curve[0].segments_num, + MPC_RMU_SHAPER_RAMA_EXP_REGION1_LUT_OFFSET, curve[1].offset, + MPC_RMU_SHAPER_RAMA_EXP_REGION1_NUM_SEGMENTS, curve[1].segments_num); + + curve += 2; + REG_SET_4(SHAPER_RAMB_REGION_26_27[rmu_idx], 0, + MPC_RMU_SHAPER_RAMA_EXP_REGION0_LUT_OFFSET, curve[0].offset, + MPC_RMU_SHAPER_RAMA_EXP_REGION0_NUM_SEGMENTS, curve[0].segments_num, + MPC_RMU_SHAPER_RAMA_EXP_REGION1_LUT_OFFSET, curve[1].offset, + MPC_RMU_SHAPER_RAMA_EXP_REGION1_NUM_SEGMENTS, curve[1].segments_num); + + curve += 2; + REG_SET_4(SHAPER_RAMB_REGION_28_29[rmu_idx], 0, + MPC_RMU_SHAPER_RAMA_EXP_REGION0_LUT_OFFSET, curve[0].offset, + MPC_RMU_SHAPER_RAMA_EXP_REGION0_NUM_SEGMENTS, curve[0].segments_num, + MPC_RMU_SHAPER_RAMA_EXP_REGION1_LUT_OFFSET, curve[1].offset, + MPC_RMU_SHAPER_RAMA_EXP_REGION1_NUM_SEGMENTS, curve[1].segments_num); + + curve += 2; + REG_SET_4(SHAPER_RAMB_REGION_30_31[rmu_idx], 0, + MPC_RMU_SHAPER_RAMA_EXP_REGION0_LUT_OFFSET, curve[0].offset, + MPC_RMU_SHAPER_RAMA_EXP_REGION0_NUM_SEGMENTS, curve[0].segments_num, + MPC_RMU_SHAPER_RAMA_EXP_REGION1_LUT_OFFSET, curve[1].offset, + MPC_RMU_SHAPER_RAMA_EXP_REGION1_NUM_SEGMENTS, curve[1].segments_num); + + curve += 2; + REG_SET_4(SHAPER_RAMB_REGION_32_33[rmu_idx], 0, + MPC_RMU_SHAPER_RAMA_EXP_REGION0_LUT_OFFSET, curve[0].offset, + MPC_RMU_SHAPER_RAMA_EXP_REGION0_NUM_SEGMENTS, curve[0].segments_num, + MPC_RMU_SHAPER_RAMA_EXP_REGION1_LUT_OFFSET, curve[1].offset, + MPC_RMU_SHAPER_RAMA_EXP_REGION1_NUM_SEGMENTS, curve[1].segments_num); +} + + +static void mpc3_program_shaper_lut( + struct mpc *mpc, + const struct pwl_result_data *rgb, + uint32_t num, + uint32_t rmu_idx) +{ + uint32_t i, red, green, blue; + uint32_t red_delta, green_delta, blue_delta; + uint32_t red_value, green_value, blue_value; + + struct dcn30_mpc *mpc30 = TO_DCN30_MPC(mpc); + + for (i = 0 ; i < num; i++) { + + red = rgb[i].red_reg; + green = rgb[i].green_reg; + blue = rgb[i].blue_reg; + + red_delta = rgb[i].delta_red_reg; + green_delta = rgb[i].delta_green_reg; + blue_delta = rgb[i].delta_blue_reg; + + red_value = ((red_delta & 0x3ff) << 14) | (red & 0x3fff); + green_value = ((green_delta & 0x3ff) << 14) | (green & 0x3fff); + blue_value = ((blue_delta & 0x3ff) << 14) | (blue & 0x3fff); + + REG_SET(SHAPER_LUT_DATA[rmu_idx], 0, MPC_RMU_SHAPER_LUT_DATA, red_value); + REG_SET(SHAPER_LUT_DATA[rmu_idx], 0, MPC_RMU_SHAPER_LUT_DATA, green_value); + REG_SET(SHAPER_LUT_DATA[rmu_idx], 0, MPC_RMU_SHAPER_LUT_DATA, blue_value); + } + +} + +static void mpc3_power_on_shaper_3dlut( + struct mpc *mpc, + uint32_t rmu_idx, + bool power_on) +{ + uint32_t power_status_shaper = 2; + uint32_t power_status_3dlut = 2; + struct dcn30_mpc *mpc30 = TO_DCN30_MPC(mpc); + int max_retries = 10; + + if (rmu_idx == 0) { + REG_SET(MPC_RMU_MEM_PWR_CTRL, 0, + MPC_RMU0_MEM_PWR_DIS, power_on == true ? 1:0); + /* wait for memory to fully power up */ + if (power_on && mpc->ctx->dc->debug.enable_mem_low_power.bits.mpc) { + REG_WAIT(MPC_RMU_MEM_PWR_CTRL, MPC_RMU0_SHAPER_MEM_PWR_STATE, 0, 1, max_retries); + REG_WAIT(MPC_RMU_MEM_PWR_CTRL, MPC_RMU0_3DLUT_MEM_PWR_STATE, 0, 1, max_retries); + } + + /*read status is not mandatory, it is just for debugging*/ + REG_GET(MPC_RMU_MEM_PWR_CTRL, MPC_RMU0_SHAPER_MEM_PWR_STATE, &power_status_shaper); + REG_GET(MPC_RMU_MEM_PWR_CTRL, MPC_RMU0_3DLUT_MEM_PWR_STATE, &power_status_3dlut); + } else if (rmu_idx == 1) { + REG_SET(MPC_RMU_MEM_PWR_CTRL, 0, + MPC_RMU1_MEM_PWR_DIS, power_on == true ? 1:0); + if (power_on && mpc->ctx->dc->debug.enable_mem_low_power.bits.mpc) { + REG_WAIT(MPC_RMU_MEM_PWR_CTRL, MPC_RMU1_SHAPER_MEM_PWR_STATE, 0, 1, max_retries); + REG_WAIT(MPC_RMU_MEM_PWR_CTRL, MPC_RMU1_3DLUT_MEM_PWR_STATE, 0, 1, max_retries); + } + + REG_GET(MPC_RMU_MEM_PWR_CTRL, MPC_RMU1_SHAPER_MEM_PWR_STATE, &power_status_shaper); + REG_GET(MPC_RMU_MEM_PWR_CTRL, MPC_RMU1_3DLUT_MEM_PWR_STATE, &power_status_3dlut); + } + /*TODO Add rmu_idx == 2 for SIENNA_CICHLID */ + if (power_status_shaper != 0 && power_on == true) + BREAK_TO_DEBUGGER(); + + if (power_status_3dlut != 0 && power_on == true) + BREAK_TO_DEBUGGER(); +} + + + +bool mpc3_program_shaper( + struct mpc *mpc, + const struct pwl_params *params, + uint32_t rmu_idx) +{ + enum dc_lut_mode current_mode; + enum dc_lut_mode next_mode; + + struct dcn30_mpc *mpc30 = TO_DCN30_MPC(mpc); + + if (params == NULL) { + REG_SET(SHAPER_CONTROL[rmu_idx], 0, MPC_RMU_SHAPER_LUT_MODE, 0); + return false; + } + + if (mpc->ctx->dc->debug.enable_mem_low_power.bits.mpc) + mpc3_power_on_shaper_3dlut(mpc, rmu_idx, true); + + current_mode = mpc3_get_shaper_current(mpc, rmu_idx); + + if (current_mode == LUT_BYPASS || current_mode == LUT_RAM_A) + next_mode = LUT_RAM_B; + else + next_mode = LUT_RAM_A; + + mpc3_configure_shaper_lut(mpc, next_mode == LUT_RAM_A, rmu_idx); + + if (next_mode == LUT_RAM_A) + mpc3_program_shaper_luta_settings(mpc, params, rmu_idx); + else + mpc3_program_shaper_lutb_settings(mpc, params, rmu_idx); + + mpc3_program_shaper_lut( + mpc, params->rgb_resulted, params->hw_points_num, rmu_idx); + + REG_SET(SHAPER_CONTROL[rmu_idx], 0, MPC_RMU_SHAPER_LUT_MODE, next_mode == LUT_RAM_A ? 1:2); + mpc3_power_on_shaper_3dlut(mpc, rmu_idx, false); + + return true; +} + +static void mpc3_set_3dlut_mode( + struct mpc *mpc, + enum dc_lut_mode mode, + bool is_color_channel_12bits, + bool is_lut_size17x17x17, + uint32_t rmu_idx) +{ + uint32_t lut_mode; + struct dcn30_mpc *mpc30 = TO_DCN30_MPC(mpc); + + if (mode == LUT_BYPASS) + lut_mode = 0; + else if (mode == LUT_RAM_A) + lut_mode = 1; + else + lut_mode = 2; + + REG_UPDATE_2(RMU_3DLUT_MODE[rmu_idx], + MPC_RMU_3DLUT_MODE, lut_mode, + MPC_RMU_3DLUT_SIZE, is_lut_size17x17x17 == true ? 0 : 1); +} + +static enum dc_lut_mode get3dlut_config( + struct mpc *mpc, + bool *is_17x17x17, + bool *is_12bits_color_channel, + int rmu_idx) +{ + uint32_t i_mode, i_enable_10bits, lut_size; + enum dc_lut_mode mode; + struct dcn30_mpc *mpc30 = TO_DCN30_MPC(mpc); + + REG_GET(RMU_3DLUT_MODE[rmu_idx], + MPC_RMU_3DLUT_MODE_CURRENT, &i_mode); + + REG_GET(RMU_3DLUT_READ_WRITE_CONTROL[rmu_idx], + MPC_RMU_3DLUT_30BIT_EN, &i_enable_10bits); + + switch (i_mode) { + case 0: + mode = LUT_BYPASS; + break; + case 1: + mode = LUT_RAM_A; + break; + case 2: + mode = LUT_RAM_B; + break; + default: + mode = LUT_BYPASS; + break; + } + if (i_enable_10bits > 0) + *is_12bits_color_channel = false; + else + *is_12bits_color_channel = true; + + REG_GET(RMU_3DLUT_MODE[rmu_idx], MPC_RMU_3DLUT_SIZE, &lut_size); + + if (lut_size == 0) + *is_17x17x17 = true; + else + *is_17x17x17 = false; + + return mode; +} + +static void mpc3_select_3dlut_ram( + struct mpc *mpc, + enum dc_lut_mode mode, + bool is_color_channel_12bits, + uint32_t rmu_idx) +{ + struct dcn30_mpc *mpc30 = TO_DCN30_MPC(mpc); + + REG_UPDATE_2(RMU_3DLUT_READ_WRITE_CONTROL[rmu_idx], + MPC_RMU_3DLUT_RAM_SEL, mode == LUT_RAM_A ? 0 : 1, + MPC_RMU_3DLUT_30BIT_EN, is_color_channel_12bits == true ? 0:1); +} + +static void mpc3_select_3dlut_ram_mask( + struct mpc *mpc, + uint32_t ram_selection_mask, + uint32_t rmu_idx) +{ + struct dcn30_mpc *mpc30 = TO_DCN30_MPC(mpc); + + REG_UPDATE(RMU_3DLUT_READ_WRITE_CONTROL[rmu_idx], MPC_RMU_3DLUT_WRITE_EN_MASK, + ram_selection_mask); + REG_SET(RMU_3DLUT_INDEX[rmu_idx], 0, MPC_RMU_3DLUT_INDEX, 0); +} + +static void mpc3_set3dlut_ram12( + struct mpc *mpc, + const struct dc_rgb *lut, + uint32_t entries, + uint32_t rmu_idx) +{ + uint32_t i, red, green, blue, red1, green1, blue1; + struct dcn30_mpc *mpc30 = TO_DCN30_MPC(mpc); + + for (i = 0 ; i < entries; i += 2) { + red = lut[i].red<<4; + green = lut[i].green<<4; + blue = lut[i].blue<<4; + red1 = lut[i+1].red<<4; + green1 = lut[i+1].green<<4; + blue1 = lut[i+1].blue<<4; + + REG_SET_2(RMU_3DLUT_DATA[rmu_idx], 0, + MPC_RMU_3DLUT_DATA0, red, + MPC_RMU_3DLUT_DATA1, red1); + + REG_SET_2(RMU_3DLUT_DATA[rmu_idx], 0, + MPC_RMU_3DLUT_DATA0, green, + MPC_RMU_3DLUT_DATA1, green1); + + REG_SET_2(RMU_3DLUT_DATA[rmu_idx], 0, + MPC_RMU_3DLUT_DATA0, blue, + MPC_RMU_3DLUT_DATA1, blue1); + } +} + +static void mpc3_set3dlut_ram10( + struct mpc *mpc, + const struct dc_rgb *lut, + uint32_t entries, + uint32_t rmu_idx) +{ + uint32_t i, red, green, blue, value; + struct dcn30_mpc *mpc30 = TO_DCN30_MPC(mpc); + + for (i = 0; i < entries; i++) { + red = lut[i].red; + green = lut[i].green; + blue = lut[i].blue; + //should we shift red 22bit and green 12? ask Nvenko + value = (red<<20) | (green<<10) | blue; + + REG_SET(RMU_3DLUT_DATA_30BIT[rmu_idx], 0, MPC_RMU_3DLUT_DATA_30BIT, value); + } + +} + + +void mpc3_init_mpcc(struct mpcc *mpcc, int mpcc_inst) +{ + mpcc->mpcc_id = mpcc_inst; + mpcc->dpp_id = 0xf; + mpcc->mpcc_bot = NULL; + mpcc->blnd_cfg.overlap_only = false; + mpcc->blnd_cfg.global_alpha = 0xff; + mpcc->blnd_cfg.global_gain = 0xff; + mpcc->blnd_cfg.background_color_bpc = 4; + mpcc->blnd_cfg.bottom_gain_mode = 0; + mpcc->blnd_cfg.top_gain = 0x1f000; + mpcc->blnd_cfg.bottom_inside_gain = 0x1f000; + mpcc->blnd_cfg.bottom_outside_gain = 0x1f000; + mpcc->sm_cfg.enable = false; + mpcc->shared_bottom = false; +} + +static void program_gamut_remap( + struct dcn30_mpc *mpc30, + int mpcc_id, + const uint16_t *regval, + int select) +{ + uint16_t selection = 0; + struct color_matrices_reg gam_regs; + + if (regval == NULL || select == GAMUT_REMAP_BYPASS) { + REG_SET(MPCC_GAMUT_REMAP_MODE[mpcc_id], 0, + MPCC_GAMUT_REMAP_MODE, GAMUT_REMAP_BYPASS); + return; + } + switch (select) { + case GAMUT_REMAP_COEFF: + selection = 1; + break; + /*this corresponds to GAMUT_REMAP coefficients set B + * we don't have common coefficient sets in dcn3ag/dcn3 + */ + case GAMUT_REMAP_COMA_COEFF: + selection = 2; + break; + default: + break; + } + + gam_regs.shifts.csc_c11 = mpc30->mpc_shift->MPCC_GAMUT_REMAP_C11_A; + gam_regs.masks.csc_c11 = mpc30->mpc_mask->MPCC_GAMUT_REMAP_C11_A; + gam_regs.shifts.csc_c12 = mpc30->mpc_shift->MPCC_GAMUT_REMAP_C12_A; + gam_regs.masks.csc_c12 = mpc30->mpc_mask->MPCC_GAMUT_REMAP_C12_A; + + + if (select == GAMUT_REMAP_COEFF) { + gam_regs.csc_c11_c12 = REG(MPC_GAMUT_REMAP_C11_C12_A[mpcc_id]); + gam_regs.csc_c33_c34 = REG(MPC_GAMUT_REMAP_C33_C34_A[mpcc_id]); + + cm_helper_program_color_matrices( + mpc30->base.ctx, + regval, + &gam_regs); + + } else if (select == GAMUT_REMAP_COMA_COEFF) { + + gam_regs.csc_c11_c12 = REG(MPC_GAMUT_REMAP_C11_C12_B[mpcc_id]); + gam_regs.csc_c33_c34 = REG(MPC_GAMUT_REMAP_C33_C34_B[mpcc_id]); + + cm_helper_program_color_matrices( + mpc30->base.ctx, + regval, + &gam_regs); + + } + //select coefficient set to use + REG_SET(MPCC_GAMUT_REMAP_MODE[mpcc_id], 0, + MPCC_GAMUT_REMAP_MODE, selection); +} + +void mpc3_set_gamut_remap( + struct mpc *mpc, + int mpcc_id, + const struct mpc_grph_gamut_adjustment *adjust) +{ + struct dcn30_mpc *mpc30 = TO_DCN30_MPC(mpc); + int i = 0; + int gamut_mode; + + if (adjust->gamut_adjust_type != GRAPHICS_GAMUT_ADJUST_TYPE_SW) + program_gamut_remap(mpc30, mpcc_id, NULL, GAMUT_REMAP_BYPASS); + else { + struct fixed31_32 arr_matrix[12]; + uint16_t arr_reg_val[12]; + + for (i = 0; i < 12; i++) + arr_matrix[i] = adjust->temperature_matrix[i]; + + convert_float_matrix( + arr_reg_val, arr_matrix, 12); + + //current coefficient set in use + REG_GET(MPCC_GAMUT_REMAP_MODE[mpcc_id], MPCC_GAMUT_REMAP_MODE_CURRENT, &gamut_mode); + + if (gamut_mode == 0) + gamut_mode = 1; //use coefficient set A + else if (gamut_mode == 1) + gamut_mode = 2; + else + gamut_mode = 1; + + program_gamut_remap(mpc30, mpcc_id, arr_reg_val, gamut_mode); + } +} + +bool mpc3_program_3dlut( + struct mpc *mpc, + const struct tetrahedral_params *params, + int rmu_idx) +{ + enum dc_lut_mode mode; + bool is_17x17x17; + bool is_12bits_color_channel; + const struct dc_rgb *lut0; + const struct dc_rgb *lut1; + const struct dc_rgb *lut2; + const struct dc_rgb *lut3; + int lut_size0; + int lut_size; + + if (params == NULL) { + mpc3_set_3dlut_mode(mpc, LUT_BYPASS, false, false, rmu_idx); + return false; + } + mpc3_power_on_shaper_3dlut(mpc, rmu_idx, true); + + mode = get3dlut_config(mpc, &is_17x17x17, &is_12bits_color_channel, rmu_idx); + + if (mode == LUT_BYPASS || mode == LUT_RAM_B) + mode = LUT_RAM_A; + else + mode = LUT_RAM_B; + + is_17x17x17 = !params->use_tetrahedral_9; + is_12bits_color_channel = params->use_12bits; + if (is_17x17x17) { + lut0 = params->tetrahedral_17.lut0; + lut1 = params->tetrahedral_17.lut1; + lut2 = params->tetrahedral_17.lut2; + lut3 = params->tetrahedral_17.lut3; + lut_size0 = sizeof(params->tetrahedral_17.lut0)/ + sizeof(params->tetrahedral_17.lut0[0]); + lut_size = sizeof(params->tetrahedral_17.lut1)/ + sizeof(params->tetrahedral_17.lut1[0]); + } else { + lut0 = params->tetrahedral_9.lut0; + lut1 = params->tetrahedral_9.lut1; + lut2 = params->tetrahedral_9.lut2; + lut3 = params->tetrahedral_9.lut3; + lut_size0 = sizeof(params->tetrahedral_9.lut0)/ + sizeof(params->tetrahedral_9.lut0[0]); + lut_size = sizeof(params->tetrahedral_9.lut1)/ + sizeof(params->tetrahedral_9.lut1[0]); + } + + mpc3_select_3dlut_ram(mpc, mode, + is_12bits_color_channel, rmu_idx); + mpc3_select_3dlut_ram_mask(mpc, 0x1, rmu_idx); + if (is_12bits_color_channel) + mpc3_set3dlut_ram12(mpc, lut0, lut_size0, rmu_idx); + else + mpc3_set3dlut_ram10(mpc, lut0, lut_size0, rmu_idx); + + mpc3_select_3dlut_ram_mask(mpc, 0x2, rmu_idx); + if (is_12bits_color_channel) + mpc3_set3dlut_ram12(mpc, lut1, lut_size, rmu_idx); + else + mpc3_set3dlut_ram10(mpc, lut1, lut_size, rmu_idx); + + mpc3_select_3dlut_ram_mask(mpc, 0x4, rmu_idx); + if (is_12bits_color_channel) + mpc3_set3dlut_ram12(mpc, lut2, lut_size, rmu_idx); + else + mpc3_set3dlut_ram10(mpc, lut2, lut_size, rmu_idx); + + mpc3_select_3dlut_ram_mask(mpc, 0x8, rmu_idx); + if (is_12bits_color_channel) + mpc3_set3dlut_ram12(mpc, lut3, lut_size, rmu_idx); + else + mpc3_set3dlut_ram10(mpc, lut3, lut_size, rmu_idx); + + mpc3_set_3dlut_mode(mpc, mode, is_12bits_color_channel, + is_17x17x17, rmu_idx); + + if (mpc->ctx->dc->debug.enable_mem_low_power.bits.mpc) + mpc3_power_on_shaper_3dlut(mpc, rmu_idx, false); + + return true; +} + +void mpc3_set_output_csc( + struct mpc *mpc, + int opp_id, + const uint16_t *regval, + enum mpc_output_csc_mode ocsc_mode) +{ + struct dcn30_mpc *mpc30 = TO_DCN30_MPC(mpc); + struct color_matrices_reg ocsc_regs; + + REG_WRITE(MPC_OUT_CSC_COEF_FORMAT, 0); + + REG_SET(CSC_MODE[opp_id], 0, MPC_OCSC_MODE, ocsc_mode); + + if (ocsc_mode == MPC_OUTPUT_CSC_DISABLE) + return; + + if (regval == NULL) { + BREAK_TO_DEBUGGER(); + return; + } + + ocsc_regs.shifts.csc_c11 = mpc30->mpc_shift->MPC_OCSC_C11_A; + ocsc_regs.masks.csc_c11 = mpc30->mpc_mask->MPC_OCSC_C11_A; + ocsc_regs.shifts.csc_c12 = mpc30->mpc_shift->MPC_OCSC_C12_A; + ocsc_regs.masks.csc_c12 = mpc30->mpc_mask->MPC_OCSC_C12_A; + + if (ocsc_mode == MPC_OUTPUT_CSC_COEF_A) { + ocsc_regs.csc_c11_c12 = REG(CSC_C11_C12_A[opp_id]); + ocsc_regs.csc_c33_c34 = REG(CSC_C33_C34_A[opp_id]); + } else { + ocsc_regs.csc_c11_c12 = REG(CSC_C11_C12_B[opp_id]); + ocsc_regs.csc_c33_c34 = REG(CSC_C33_C34_B[opp_id]); + } + cm_helper_program_color_matrices( + mpc30->base.ctx, + regval, + &ocsc_regs); +} + +void mpc3_set_ocsc_default( + struct mpc *mpc, + int opp_id, + enum dc_color_space color_space, + enum mpc_output_csc_mode ocsc_mode) +{ + struct dcn30_mpc *mpc30 = TO_DCN30_MPC(mpc); + uint32_t arr_size; + struct color_matrices_reg ocsc_regs; + const uint16_t *regval = NULL; + + REG_WRITE(MPC_OUT_CSC_COEF_FORMAT, 0); + + REG_SET(CSC_MODE[opp_id], 0, MPC_OCSC_MODE, ocsc_mode); + if (ocsc_mode == MPC_OUTPUT_CSC_DISABLE) + return; + + regval = find_color_matrix(color_space, &arr_size); + + if (regval == NULL) { + BREAK_TO_DEBUGGER(); + return; + } + + ocsc_regs.shifts.csc_c11 = mpc30->mpc_shift->MPC_OCSC_C11_A; + ocsc_regs.masks.csc_c11 = mpc30->mpc_mask->MPC_OCSC_C11_A; + ocsc_regs.shifts.csc_c12 = mpc30->mpc_shift->MPC_OCSC_C12_A; + ocsc_regs.masks.csc_c12 = mpc30->mpc_mask->MPC_OCSC_C12_A; + + + if (ocsc_mode == MPC_OUTPUT_CSC_COEF_A) { + ocsc_regs.csc_c11_c12 = REG(CSC_C11_C12_A[opp_id]); + ocsc_regs.csc_c33_c34 = REG(CSC_C33_C34_A[opp_id]); + } else { + ocsc_regs.csc_c11_c12 = REG(CSC_C11_C12_B[opp_id]); + ocsc_regs.csc_c33_c34 = REG(CSC_C33_C34_B[opp_id]); + } + + cm_helper_program_color_matrices( + mpc30->base.ctx, + regval, + &ocsc_regs); +} + +void mpc3_set_rmu_mux( + struct mpc *mpc, + int rmu_idx, + int value) +{ + struct dcn30_mpc *mpc30 = TO_DCN30_MPC(mpc); + + if (rmu_idx == 0) + REG_UPDATE(MPC_RMU_CONTROL, MPC_RMU0_MUX, value); + else if (rmu_idx == 1) + REG_UPDATE(MPC_RMU_CONTROL, MPC_RMU1_MUX, value); + +} + +uint32_t mpc3_get_rmu_mux_status( + struct mpc *mpc, + int rmu_idx) +{ + uint32_t status = 0xf; + struct dcn30_mpc *mpc30 = TO_DCN30_MPC(mpc); + + if (rmu_idx == 0) + REG_GET(MPC_RMU_CONTROL, MPC_RMU0_MUX_STATUS, &status); + else if (rmu_idx == 1) + REG_GET(MPC_RMU_CONTROL, MPC_RMU1_MUX_STATUS, &status); + + return status; +} + +uint32_t mpcc3_acquire_rmu(struct mpc *mpc, int mpcc_id, int rmu_idx) +{ + uint32_t rmu_status; + + //determine if this mpcc is already multiplexed to an RMU unit + rmu_status = mpc3_get_rmu_mux_status(mpc, rmu_idx); + if (rmu_status == mpcc_id) + //return rmu_idx of pre_acquired rmu unit + return rmu_idx; + + if (rmu_status == 0xf) {//rmu unit is disabled + mpc3_set_rmu_mux(mpc, rmu_idx, mpcc_id); + return rmu_idx; + } + + //no vacant RMU units or invalid parameters acquire_post_bldn_3dlut + return -1; +} + +static int mpcc3_release_rmu(struct mpc *mpc, int mpcc_id) +{ + struct dcn30_mpc *mpc30 = TO_DCN30_MPC(mpc); + int rmu_idx; + uint32_t rmu_status; + int released_rmu = -1; + + for (rmu_idx = 0; rmu_idx < mpc30->num_rmu; rmu_idx++) { + rmu_status = mpc3_get_rmu_mux_status(mpc, rmu_idx); + if (rmu_status == mpcc_id) { + mpc3_set_rmu_mux(mpc, rmu_idx, 0xf); + released_rmu = rmu_idx; + break; + } + } + return released_rmu; + +} + +static void mpc3_set_mpc_mem_lp_mode(struct mpc *mpc) +{ + struct dcn30_mpc *mpc30 = TO_DCN30_MPC(mpc); + int mpcc_id; + + if (mpc->ctx->dc->debug.enable_mem_low_power.bits.mpc) { + if (mpc30->mpc_mask->MPC_RMU0_MEM_LOW_PWR_MODE && mpc30->mpc_mask->MPC_RMU1_MEM_LOW_PWR_MODE) { + REG_UPDATE(MPC_RMU_MEM_PWR_CTRL, MPC_RMU0_MEM_LOW_PWR_MODE, 3); + REG_UPDATE(MPC_RMU_MEM_PWR_CTRL, MPC_RMU1_MEM_LOW_PWR_MODE, 3); + } + + if (mpc30->mpc_mask->MPCC_OGAM_MEM_LOW_PWR_MODE) { + for (mpcc_id = 0; mpcc_id < mpc30->num_mpcc; mpcc_id++) + REG_UPDATE(MPCC_MEM_PWR_CTRL[mpcc_id], MPCC_OGAM_MEM_LOW_PWR_MODE, 3); + } + } +} + +const struct mpc_funcs dcn30_mpc_funcs = { + .read_mpcc_state = mpc1_read_mpcc_state, + .insert_plane = mpc1_insert_plane, + .remove_mpcc = mpc1_remove_mpcc, + .mpc_init = mpc1_mpc_init, + .mpc_init_single_inst = mpc1_mpc_init_single_inst, + .update_blending = mpc2_update_blending, + .cursor_lock = mpc1_cursor_lock, + .get_mpcc_for_dpp = mpc1_get_mpcc_for_dpp, + .wait_for_idle = mpc2_assert_idle_mpcc, + .assert_mpcc_idle_before_connect = mpc2_assert_mpcc_idle_before_connect, + .init_mpcc_list_from_hw = mpc1_init_mpcc_list_from_hw, + .set_denorm = mpc3_set_denorm, + .set_denorm_clamp = mpc3_set_denorm_clamp, + .set_output_csc = mpc3_set_output_csc, + .set_ocsc_default = mpc3_set_ocsc_default, + .set_output_gamma = mpc3_set_output_gamma, + .insert_plane_to_secondary = NULL, + .remove_mpcc_from_secondary = NULL, + .set_dwb_mux = mpc3_set_dwb_mux, + .disable_dwb_mux = mpc3_disable_dwb_mux, + .is_dwb_idle = mpc3_is_dwb_idle, + .set_out_rate_control = mpc3_set_out_rate_control, + .set_gamut_remap = mpc3_set_gamut_remap, + .program_shaper = mpc3_program_shaper, + .acquire_rmu = mpcc3_acquire_rmu, + .program_3dlut = mpc3_program_3dlut, + .release_rmu = mpcc3_release_rmu, + .power_on_mpc_mem_pwr = mpc3_power_on_ogam_lut, + .get_mpc_out_mux = mpc1_get_mpc_out_mux, + .set_bg_color = mpc1_set_bg_color, + .set_mpc_mem_lp_mode = mpc3_set_mpc_mem_lp_mode, +}; + +void dcn30_mpc_construct(struct dcn30_mpc *mpc30, + struct dc_context *ctx, + const struct dcn30_mpc_registers *mpc_regs, + const struct dcn30_mpc_shift *mpc_shift, + const struct dcn30_mpc_mask *mpc_mask, + int num_mpcc, + int num_rmu) +{ + int i; + + mpc30->base.ctx = ctx; + + mpc30->base.funcs = &dcn30_mpc_funcs; + + mpc30->mpc_regs = mpc_regs; + mpc30->mpc_shift = mpc_shift; + mpc30->mpc_mask = mpc_mask; + + mpc30->mpcc_in_use_mask = 0; + mpc30->num_mpcc = num_mpcc; + mpc30->num_rmu = num_rmu; + + for (i = 0; i < MAX_MPCC; i++) + mpc3_init_mpcc(&mpc30->base.mpcc_array[i], i); +} + diff --git a/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_mpc.h b/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_mpc.h new file mode 100644 index 000000000..c8a3a6a96 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_mpc.h @@ -0,0 +1,1095 @@ +/* Copyright 2020 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_MPCC_DCN30_H__ +#define __DC_MPCC_DCN30_H__ + +#include "dcn20/dcn20_mpc.h" + +#define MAX_RMU 3 + +#define TO_DCN30_MPC(mpc_base) \ + container_of(mpc_base, struct dcn30_mpc, base) + +#ifdef SRII_MPC_RMU +#undef SRII_MPC_RMU + +#define SRII_MPC_RMU(reg_name, block, id)\ + .RMU##_##reg_name[id] = BASE(mm ## block ## id ## _ ## reg_name ## _BASE_IDX) + \ + mm ## block ## id ## _ ## reg_name + +#endif + + +#define MPC_REG_LIST_DCN3_0(inst)\ + MPC_COMMON_REG_LIST_DCN1_0(inst),\ + SRII(MPCC_TOP_GAIN, MPCC, inst),\ + SRII(MPCC_BOT_GAIN_INSIDE, MPCC, inst),\ + SRII(MPCC_BOT_GAIN_OUTSIDE, MPCC, inst),\ + SRII(MPCC_MEM_PWR_CTRL, MPCC, inst),\ + SRII(MPCC_OGAM_LUT_INDEX, MPCC_OGAM, inst),\ + SRII(MPCC_OGAM_LUT_DATA, MPCC_OGAM, inst), \ + SRII(MPCC_GAMUT_REMAP_COEF_FORMAT, MPCC_OGAM, inst),\ + SRII(MPCC_GAMUT_REMAP_MODE, MPCC_OGAM, inst),\ + SRII(MPC_GAMUT_REMAP_C11_C12_A, MPCC_OGAM, inst),\ + SRII(MPC_GAMUT_REMAP_C33_C34_A, MPCC_OGAM, inst),\ + SRII(MPC_GAMUT_REMAP_C11_C12_B, MPCC_OGAM, inst),\ + SRII(MPC_GAMUT_REMAP_C33_C34_B, MPCC_OGAM, inst),\ + SRII(MPCC_OGAM_RAMA_START_CNTL_B, MPCC_OGAM, inst),\ + SRII(MPCC_OGAM_RAMA_START_CNTL_G, MPCC_OGAM, inst),\ + SRII(MPCC_OGAM_RAMA_START_CNTL_R, MPCC_OGAM, inst),\ + SRII(MPCC_OGAM_RAMA_START_SLOPE_CNTL_B, MPCC_OGAM, inst),\ + SRII(MPCC_OGAM_RAMA_START_SLOPE_CNTL_G, MPCC_OGAM, inst),\ + SRII(MPCC_OGAM_RAMA_START_SLOPE_CNTL_R, MPCC_OGAM, inst),\ + SRII(MPCC_OGAM_RAMA_END_CNTL1_B, MPCC_OGAM, inst),\ + SRII(MPCC_OGAM_RAMA_END_CNTL2_B, MPCC_OGAM, inst),\ + SRII(MPCC_OGAM_RAMA_END_CNTL1_G, MPCC_OGAM, inst),\ + SRII(MPCC_OGAM_RAMA_END_CNTL2_G, MPCC_OGAM, inst),\ + SRII(MPCC_OGAM_RAMA_END_CNTL1_R, MPCC_OGAM, inst),\ + SRII(MPCC_OGAM_RAMA_END_CNTL2_R, MPCC_OGAM, inst),\ + SRII(MPCC_OGAM_RAMA_REGION_0_1, MPCC_OGAM, inst),\ + SRII(MPCC_OGAM_RAMA_REGION_32_33, MPCC_OGAM, inst),\ + SRII(MPCC_OGAM_RAMA_OFFSET_B, MPCC_OGAM, inst),\ + SRII(MPCC_OGAM_RAMA_OFFSET_G, MPCC_OGAM, inst),\ + SRII(MPCC_OGAM_RAMA_OFFSET_R, MPCC_OGAM, inst),\ + SRII(MPCC_OGAM_RAMA_START_BASE_CNTL_B, MPCC_OGAM, inst),\ + SRII(MPCC_OGAM_RAMA_START_BASE_CNTL_G, MPCC_OGAM, inst),\ + SRII(MPCC_OGAM_RAMA_START_BASE_CNTL_R, MPCC_OGAM, inst),\ + SRII(MPCC_OGAM_RAMB_START_CNTL_B, MPCC_OGAM, inst),\ + SRII(MPCC_OGAM_RAMB_START_CNTL_G, MPCC_OGAM, inst),\ + SRII(MPCC_OGAM_RAMB_START_CNTL_R, MPCC_OGAM, inst),\ + SRII(MPCC_OGAM_RAMB_START_SLOPE_CNTL_B, MPCC_OGAM, inst),\ + SRII(MPCC_OGAM_RAMB_START_SLOPE_CNTL_G, MPCC_OGAM, inst),\ + SRII(MPCC_OGAM_RAMB_START_SLOPE_CNTL_R, MPCC_OGAM, inst),\ + SRII(MPCC_OGAM_RAMB_END_CNTL1_B, MPCC_OGAM, inst),\ + SRII(MPCC_OGAM_RAMB_END_CNTL2_B, MPCC_OGAM, inst),\ + SRII(MPCC_OGAM_RAMB_END_CNTL1_G, MPCC_OGAM, inst),\ + SRII(MPCC_OGAM_RAMB_END_CNTL2_G, MPCC_OGAM, inst),\ + SRII(MPCC_OGAM_RAMB_END_CNTL1_R, MPCC_OGAM, inst),\ + SRII(MPCC_OGAM_RAMB_END_CNTL2_R, MPCC_OGAM, inst),\ + SRII(MPCC_OGAM_RAMB_REGION_0_1, MPCC_OGAM, inst),\ + SRII(MPCC_OGAM_RAMB_REGION_32_33, MPCC_OGAM, inst),\ + SRII(MPCC_OGAM_RAMB_OFFSET_B, MPCC_OGAM, inst),\ + SRII(MPCC_OGAM_RAMB_OFFSET_G, MPCC_OGAM, inst),\ + SRII(MPCC_OGAM_RAMB_OFFSET_R, MPCC_OGAM, inst),\ + SRII(MPCC_OGAM_RAMB_START_BASE_CNTL_B, MPCC_OGAM, inst),\ + SRII(MPCC_OGAM_RAMB_START_BASE_CNTL_G, MPCC_OGAM, inst),\ + SRII(MPCC_OGAM_RAMB_START_BASE_CNTL_R, MPCC_OGAM, inst),\ + SRII(MPCC_OGAM_CONTROL, MPCC_OGAM, inst),\ + SRII(MPCC_OGAM_LUT_CONTROL, MPCC_OGAM, inst) + +#define MPC_OUT_MUX_REG_LIST_DCN3_0(inst) \ + MPC_OUT_MUX_COMMON_REG_LIST_DCN1_0(inst),\ + SRII(CSC_MODE, MPC_OUT, inst),\ + SRII(CSC_C11_C12_A, MPC_OUT, inst),\ + SRII(CSC_C33_C34_A, MPC_OUT, inst),\ + SRII(CSC_C11_C12_B, MPC_OUT, inst),\ + SRII(CSC_C33_C34_B, MPC_OUT, inst),\ + SRII(DENORM_CONTROL, MPC_OUT, inst),\ + SRII(DENORM_CLAMP_G_Y, MPC_OUT, inst),\ + SRII(DENORM_CLAMP_B_CB, MPC_OUT, inst), \ + SR(MPC_OUT_CSC_COEF_FORMAT) + +#define MPC_RMU_GLOBAL_REG_LIST_DCN3AG \ + SR(MPC_RMU_CONTROL),\ + SR(MPC_RMU_MEM_PWR_CTRL) + +#define MPC_RMU_REG_LIST_DCN3AG(inst) \ + SRII(SHAPER_CONTROL, MPC_RMU, inst),\ + SRII(SHAPER_OFFSET_R, MPC_RMU, inst),\ + SRII(SHAPER_OFFSET_G, MPC_RMU, inst),\ + SRII(SHAPER_OFFSET_B, MPC_RMU, inst),\ + SRII(SHAPER_SCALE_R, MPC_RMU, inst),\ + SRII(SHAPER_SCALE_G_B, MPC_RMU, inst),\ + SRII(SHAPER_LUT_INDEX, MPC_RMU, inst),\ + SRII(SHAPER_LUT_DATA, MPC_RMU, inst),\ + SRII(SHAPER_LUT_WRITE_EN_MASK, MPC_RMU, inst),\ + SRII(SHAPER_RAMA_START_CNTL_B, MPC_RMU, inst),\ + SRII(SHAPER_RAMA_START_CNTL_G, MPC_RMU, inst),\ + SRII(SHAPER_RAMA_START_CNTL_R, MPC_RMU, inst),\ + SRII(SHAPER_RAMA_END_CNTL_B, MPC_RMU, inst),\ + SRII(SHAPER_RAMA_END_CNTL_G, MPC_RMU, inst),\ + SRII(SHAPER_RAMA_END_CNTL_R, MPC_RMU, inst),\ + SRII(SHAPER_RAMA_REGION_0_1, MPC_RMU, inst),\ + SRII(SHAPER_RAMA_REGION_2_3, MPC_RMU, inst),\ + SRII(SHAPER_RAMA_REGION_4_5, MPC_RMU, inst),\ + SRII(SHAPER_RAMA_REGION_6_7, MPC_RMU, inst),\ + SRII(SHAPER_RAMA_REGION_8_9, MPC_RMU, inst),\ + SRII(SHAPER_RAMA_REGION_10_11, MPC_RMU, inst),\ + SRII(SHAPER_RAMA_REGION_12_13, MPC_RMU, inst),\ + SRII(SHAPER_RAMA_REGION_14_15, MPC_RMU, inst),\ + SRII(SHAPER_RAMA_REGION_16_17, MPC_RMU, inst),\ + SRII(SHAPER_RAMA_REGION_18_19, MPC_RMU, inst),\ + SRII(SHAPER_RAMA_REGION_20_21, MPC_RMU, inst),\ + SRII(SHAPER_RAMA_REGION_22_23, MPC_RMU, inst),\ + SRII(SHAPER_RAMA_REGION_24_25, MPC_RMU, inst),\ + SRII(SHAPER_RAMA_REGION_26_27, MPC_RMU, inst),\ + SRII(SHAPER_RAMA_REGION_28_29, MPC_RMU, inst),\ + SRII(SHAPER_RAMA_REGION_30_31, MPC_RMU, inst),\ + SRII(SHAPER_RAMA_REGION_32_33, MPC_RMU, inst),\ + SRII(SHAPER_RAMB_START_CNTL_B, MPC_RMU, inst),\ + SRII(SHAPER_RAMB_START_CNTL_G, MPC_RMU, inst),\ + SRII(SHAPER_RAMB_START_CNTL_R, MPC_RMU, inst),\ + SRII(SHAPER_RAMB_END_CNTL_B, MPC_RMU, inst),\ + SRII(SHAPER_RAMB_END_CNTL_G, MPC_RMU, inst),\ + SRII(SHAPER_RAMB_END_CNTL_R, MPC_RMU, inst),\ + SRII(SHAPER_RAMB_REGION_0_1, MPC_RMU, inst),\ + SRII(SHAPER_RAMB_REGION_2_3, MPC_RMU, inst),\ + SRII(SHAPER_RAMB_REGION_4_5, MPC_RMU, inst),\ + SRII(SHAPER_RAMB_REGION_6_7, MPC_RMU, inst),\ + SRII(SHAPER_RAMB_REGION_8_9, MPC_RMU, inst),\ + SRII(SHAPER_RAMB_REGION_10_11, MPC_RMU, inst),\ + SRII(SHAPER_RAMB_REGION_12_13, MPC_RMU, inst),\ + SRII(SHAPER_RAMB_REGION_14_15, MPC_RMU, inst),\ + SRII(SHAPER_RAMB_REGION_16_17, MPC_RMU, inst),\ + SRII(SHAPER_RAMB_REGION_18_19, MPC_RMU, inst),\ + SRII(SHAPER_RAMB_REGION_20_21, MPC_RMU, inst),\ + SRII(SHAPER_RAMB_REGION_22_23, MPC_RMU, inst),\ + SRII(SHAPER_RAMB_REGION_24_25, MPC_RMU, inst),\ + SRII(SHAPER_RAMB_REGION_26_27, MPC_RMU, inst),\ + SRII(SHAPER_RAMB_REGION_28_29, MPC_RMU, inst),\ + SRII(SHAPER_RAMB_REGION_30_31, MPC_RMU, inst),\ + SRII(SHAPER_RAMB_REGION_32_33, MPC_RMU, inst),\ + SRII_MPC_RMU(3DLUT_MODE, MPC_RMU, inst),\ + SRII_MPC_RMU(3DLUT_INDEX, MPC_RMU, inst),\ + SRII_MPC_RMU(3DLUT_DATA, MPC_RMU, inst),\ + SRII_MPC_RMU(3DLUT_DATA_30BIT, MPC_RMU, inst),\ + SRII_MPC_RMU(3DLUT_READ_WRITE_CONTROL, MPC_RMU, inst),\ + SRII_MPC_RMU(3DLUT_OUT_NORM_FACTOR, MPC_RMU, inst),\ + SRII_MPC_RMU(3DLUT_OUT_OFFSET_R, MPC_RMU, inst),\ + SRII_MPC_RMU(3DLUT_OUT_OFFSET_G, MPC_RMU, inst),\ + SRII_MPC_RMU(3DLUT_OUT_OFFSET_B, MPC_RMU, inst) + + +#define MPC_DWB_MUX_REG_LIST_DCN3_0(inst) \ + SRII_DWB(DWB_MUX, MUX, MPC_DWB, inst) + +#define MPC_REG_VARIABLE_LIST_DCN3_0 \ + MPC_REG_VARIABLE_LIST_DCN2_0 \ + uint32_t DWB_MUX[MAX_DWB]; \ + uint32_t MPCC_GAMUT_REMAP_COEF_FORMAT[MAX_MPCC]; \ + uint32_t MPCC_GAMUT_REMAP_MODE[MAX_MPCC]; \ + uint32_t MPC_GAMUT_REMAP_C11_C12_A[MAX_MPCC]; \ + uint32_t MPC_GAMUT_REMAP_C33_C34_A[MAX_MPCC]; \ + uint32_t MPC_GAMUT_REMAP_C11_C12_B[MAX_MPCC]; \ + uint32_t MPC_GAMUT_REMAP_C33_C34_B[MAX_MPCC]; \ + uint32_t MPC_RMU_CONTROL; \ + uint32_t MPC_RMU_MEM_PWR_CTRL; \ + uint32_t SHAPER_CONTROL[MAX_RMU]; \ + uint32_t SHAPER_OFFSET_R[MAX_RMU]; \ + uint32_t SHAPER_OFFSET_G[MAX_RMU]; \ + uint32_t SHAPER_OFFSET_B[MAX_RMU]; \ + uint32_t SHAPER_SCALE_R[MAX_RMU]; \ + uint32_t SHAPER_SCALE_G_B[MAX_RMU]; \ + uint32_t SHAPER_LUT_INDEX[MAX_RMU]; \ + uint32_t SHAPER_LUT_DATA[MAX_RMU]; \ + uint32_t SHAPER_LUT_WRITE_EN_MASK[MAX_RMU]; \ + uint32_t SHAPER_RAMA_START_CNTL_B[MAX_RMU]; \ + uint32_t SHAPER_RAMA_START_CNTL_G[MAX_RMU]; \ + uint32_t SHAPER_RAMA_START_CNTL_R[MAX_RMU]; \ + uint32_t SHAPER_RAMA_END_CNTL_B[MAX_RMU]; \ + uint32_t SHAPER_RAMA_END_CNTL_G[MAX_RMU]; \ + uint32_t SHAPER_RAMA_END_CNTL_R[MAX_RMU]; \ + uint32_t SHAPER_RAMA_REGION_0_1[MAX_RMU]; \ + uint32_t SHAPER_RAMA_REGION_2_3[MAX_RMU]; \ + uint32_t SHAPER_RAMA_REGION_4_5[MAX_RMU]; \ + uint32_t SHAPER_RAMA_REGION_6_7[MAX_RMU]; \ + uint32_t SHAPER_RAMA_REGION_8_9[MAX_RMU]; \ + uint32_t SHAPER_RAMA_REGION_10_11[MAX_RMU]; \ + uint32_t SHAPER_RAMA_REGION_12_13[MAX_RMU]; \ + uint32_t SHAPER_RAMA_REGION_14_15[MAX_RMU]; \ + uint32_t SHAPER_RAMA_REGION_16_17[MAX_RMU]; \ + uint32_t SHAPER_RAMA_REGION_18_19[MAX_RMU]; \ + uint32_t SHAPER_RAMA_REGION_20_21[MAX_RMU]; \ + uint32_t SHAPER_RAMA_REGION_22_23[MAX_RMU]; \ + uint32_t SHAPER_RAMA_REGION_24_25[MAX_RMU]; \ + uint32_t SHAPER_RAMA_REGION_26_27[MAX_RMU]; \ + uint32_t SHAPER_RAMA_REGION_28_29[MAX_RMU]; \ + uint32_t SHAPER_RAMA_REGION_30_31[MAX_RMU]; \ + uint32_t SHAPER_RAMA_REGION_32_33[MAX_RMU]; \ + uint32_t MPCC_OGAM_RAMA_START_SLOPE_CNTL_B[MAX_MPCC]; \ + uint32_t MPCC_OGAM_RAMA_START_SLOPE_CNTL_G[MAX_MPCC]; \ + uint32_t MPCC_OGAM_RAMA_START_SLOPE_CNTL_R[MAX_MPCC]; \ + uint32_t MPCC_OGAM_RAMA_OFFSET_B[MAX_MPCC]; \ + uint32_t MPCC_OGAM_RAMA_OFFSET_G[MAX_MPCC]; \ + uint32_t MPCC_OGAM_RAMA_OFFSET_R[MAX_MPCC]; \ + uint32_t MPCC_OGAM_RAMA_START_BASE_CNTL_B[MAX_MPCC]; \ + uint32_t MPCC_OGAM_RAMA_START_BASE_CNTL_G[MAX_MPCC]; \ + uint32_t MPCC_OGAM_RAMA_START_BASE_CNTL_R[MAX_MPCC];\ + uint32_t SHAPER_RAMB_START_CNTL_B[MAX_RMU]; \ + uint32_t SHAPER_RAMB_START_CNTL_G[MAX_RMU]; \ + uint32_t SHAPER_RAMB_START_CNTL_R[MAX_RMU]; \ + uint32_t SHAPER_RAMB_END_CNTL_B[MAX_RMU]; \ + uint32_t SHAPER_RAMB_END_CNTL_G[MAX_RMU]; \ + uint32_t SHAPER_RAMB_END_CNTL_R[MAX_RMU]; \ + uint32_t SHAPER_RAMB_REGION_0_1[MAX_RMU]; \ + uint32_t SHAPER_RAMB_REGION_2_3[MAX_RMU]; \ + uint32_t SHAPER_RAMB_REGION_4_5[MAX_RMU]; \ + uint32_t SHAPER_RAMB_REGION_6_7[MAX_RMU]; \ + uint32_t SHAPER_RAMB_REGION_8_9[MAX_RMU]; \ + uint32_t SHAPER_RAMB_REGION_10_11[MAX_RMU]; \ + uint32_t SHAPER_RAMB_REGION_12_13[MAX_RMU]; \ + uint32_t SHAPER_RAMB_REGION_14_15[MAX_RMU]; \ + uint32_t SHAPER_RAMB_REGION_16_17[MAX_RMU]; \ + uint32_t SHAPER_RAMB_REGION_18_19[MAX_RMU]; \ + uint32_t SHAPER_RAMB_REGION_20_21[MAX_RMU]; \ + uint32_t SHAPER_RAMB_REGION_22_23[MAX_RMU]; \ + uint32_t SHAPER_RAMB_REGION_24_25[MAX_RMU]; \ + uint32_t SHAPER_RAMB_REGION_26_27[MAX_RMU]; \ + uint32_t SHAPER_RAMB_REGION_28_29[MAX_RMU]; \ + uint32_t SHAPER_RAMB_REGION_30_31[MAX_RMU]; \ + uint32_t SHAPER_RAMB_REGION_32_33[MAX_RMU]; \ + uint32_t RMU_3DLUT_MODE[MAX_RMU]; \ + uint32_t RMU_3DLUT_INDEX[MAX_RMU]; \ + uint32_t RMU_3DLUT_DATA[MAX_RMU]; \ + uint32_t RMU_3DLUT_DATA_30BIT[MAX_RMU]; \ + uint32_t RMU_3DLUT_READ_WRITE_CONTROL[MAX_RMU]; \ + uint32_t RMU_3DLUT_OUT_NORM_FACTOR[MAX_RMU]; \ + uint32_t RMU_3DLUT_OUT_OFFSET_R[MAX_RMU]; \ + uint32_t RMU_3DLUT_OUT_OFFSET_G[MAX_RMU]; \ + uint32_t RMU_3DLUT_OUT_OFFSET_B[MAX_RMU]; \ + uint32_t MPCC_OGAM_RAMB_START_SLOPE_CNTL_B[MAX_MPCC]; \ + uint32_t MPCC_OGAM_RAMB_START_SLOPE_CNTL_G[MAX_MPCC]; \ + uint32_t MPCC_OGAM_RAMB_START_SLOPE_CNTL_R[MAX_MPCC]; \ + uint32_t MPCC_OGAM_CONTROL[MAX_MPCC]; \ + uint32_t MPCC_OGAM_LUT_CONTROL[MAX_MPCC]; \ + uint32_t MPCC_OGAM_RAMB_OFFSET_B[MAX_MPCC]; \ + uint32_t MPCC_OGAM_RAMB_OFFSET_G[MAX_MPCC]; \ + uint32_t MPCC_OGAM_RAMB_OFFSET_R[MAX_MPCC]; \ + uint32_t MPCC_OGAM_RAMB_START_BASE_CNTL_B[MAX_MPCC]; \ + uint32_t MPCC_OGAM_RAMB_START_BASE_CNTL_G[MAX_MPCC]; \ + uint32_t MPCC_OGAM_RAMB_START_BASE_CNTL_R[MAX_MPCC]; \ + uint32_t MPC_OUT_CSC_COEF_FORMAT + +#define MPC_REG_VARIABLE_LIST_DCN32 \ + uint32_t MPCC_MOVABLE_CM_LOCATION_CONTROL[MAX_MPCC]; \ + uint32_t MPCC_MCM_SHAPER_CONTROL[MAX_MPCC]; \ + uint32_t MPCC_MCM_SHAPER_OFFSET_R[MAX_MPCC]; \ + uint32_t MPCC_MCM_SHAPER_OFFSET_G[MAX_MPCC]; \ + uint32_t MPCC_MCM_SHAPER_OFFSET_B[MAX_MPCC]; \ + uint32_t MPCC_MCM_SHAPER_SCALE_R[MAX_MPCC]; \ + uint32_t MPCC_MCM_SHAPER_SCALE_G_B[MAX_MPCC]; \ + uint32_t MPCC_MCM_SHAPER_LUT_INDEX[MAX_MPCC]; \ + uint32_t MPCC_MCM_SHAPER_LUT_DATA[MAX_MPCC]; \ + uint32_t MPCC_MCM_SHAPER_LUT_WRITE_EN_MASK[MAX_MPCC]; \ + uint32_t MPCC_MCM_SHAPER_RAMA_START_CNTL_B[MAX_MPCC]; \ + uint32_t MPCC_MCM_SHAPER_RAMA_START_CNTL_G[MAX_MPCC]; \ + uint32_t MPCC_MCM_SHAPER_RAMA_START_CNTL_R[MAX_MPCC]; \ + uint32_t MPCC_MCM_SHAPER_RAMA_END_CNTL_B[MAX_MPCC]; \ + uint32_t MPCC_MCM_SHAPER_RAMA_END_CNTL_G[MAX_MPCC]; \ + uint32_t MPCC_MCM_SHAPER_RAMA_END_CNTL_R[MAX_MPCC]; \ + uint32_t MPCC_MCM_SHAPER_RAMA_REGION_0_1[MAX_MPCC]; \ + uint32_t MPCC_MCM_SHAPER_RAMA_REGION_2_3[MAX_MPCC]; \ + uint32_t MPCC_MCM_SHAPER_RAMA_REGION_4_5[MAX_MPCC]; \ + uint32_t MPCC_MCM_SHAPER_RAMA_REGION_6_7[MAX_MPCC]; \ + uint32_t MPCC_MCM_SHAPER_RAMA_REGION_8_9[MAX_MPCC]; \ + uint32_t MPCC_MCM_SHAPER_RAMA_REGION_10_11[MAX_MPCC]; \ + uint32_t MPCC_MCM_SHAPER_RAMA_REGION_12_13[MAX_MPCC]; \ + uint32_t MPCC_MCM_SHAPER_RAMA_REGION_14_15[MAX_MPCC]; \ + uint32_t MPCC_MCM_SHAPER_RAMA_REGION_16_17[MAX_MPCC]; \ + uint32_t MPCC_MCM_SHAPER_RAMA_REGION_18_19[MAX_MPCC]; \ + uint32_t MPCC_MCM_SHAPER_RAMA_REGION_20_21[MAX_MPCC]; \ + uint32_t MPCC_MCM_SHAPER_RAMA_REGION_22_23[MAX_MPCC]; \ + uint32_t MPCC_MCM_SHAPER_RAMA_REGION_24_25[MAX_MPCC]; \ + uint32_t MPCC_MCM_SHAPER_RAMA_REGION_26_27[MAX_MPCC]; \ + uint32_t MPCC_MCM_SHAPER_RAMA_REGION_28_29[MAX_MPCC]; \ + uint32_t MPCC_MCM_SHAPER_RAMA_REGION_30_31[MAX_MPCC]; \ + uint32_t MPCC_MCM_SHAPER_RAMA_REGION_32_33[MAX_MPCC]; \ + uint32_t MPCC_MCM_SHAPER_RAMB_START_CNTL_B[MAX_MPCC]; \ + uint32_t MPCC_MCM_SHAPER_RAMB_START_CNTL_G[MAX_MPCC]; \ + uint32_t MPCC_MCM_SHAPER_RAMB_START_CNTL_R[MAX_MPCC]; \ + uint32_t MPCC_MCM_SHAPER_RAMB_END_CNTL_B[MAX_MPCC]; \ + uint32_t MPCC_MCM_SHAPER_RAMB_END_CNTL_G[MAX_MPCC]; \ + uint32_t MPCC_MCM_SHAPER_RAMB_END_CNTL_R[MAX_MPCC]; \ + uint32_t MPCC_MCM_SHAPER_RAMB_REGION_0_1[MAX_MPCC]; \ + uint32_t MPCC_MCM_SHAPER_RAMB_REGION_2_3[MAX_MPCC]; \ + uint32_t MPCC_MCM_SHAPER_RAMB_REGION_4_5[MAX_MPCC]; \ + uint32_t MPCC_MCM_SHAPER_RAMB_REGION_6_7[MAX_MPCC]; \ + uint32_t MPCC_MCM_SHAPER_RAMB_REGION_8_9[MAX_MPCC]; \ + uint32_t MPCC_MCM_SHAPER_RAMB_REGION_10_11[MAX_MPCC]; \ + uint32_t MPCC_MCM_SHAPER_RAMB_REGION_12_13[MAX_MPCC]; \ + uint32_t MPCC_MCM_SHAPER_RAMB_REGION_14_15[MAX_MPCC]; \ + uint32_t MPCC_MCM_SHAPER_RAMB_REGION_16_17[MAX_MPCC]; \ + uint32_t MPCC_MCM_SHAPER_RAMB_REGION_18_19[MAX_MPCC]; \ + uint32_t MPCC_MCM_SHAPER_RAMB_REGION_20_21[MAX_MPCC]; \ + uint32_t MPCC_MCM_SHAPER_RAMB_REGION_22_23[MAX_MPCC]; \ + uint32_t MPCC_MCM_SHAPER_RAMB_REGION_24_25[MAX_MPCC]; \ + uint32_t MPCC_MCM_SHAPER_RAMB_REGION_26_27[MAX_MPCC]; \ + uint32_t MPCC_MCM_SHAPER_RAMB_REGION_28_29[MAX_MPCC]; \ + uint32_t MPCC_MCM_SHAPER_RAMB_REGION_30_31[MAX_MPCC]; \ + uint32_t MPCC_MCM_SHAPER_RAMB_REGION_32_33[MAX_MPCC]; \ + uint32_t MPCC_MCM_3DLUT_MODE[MAX_MPCC]; \ + uint32_t MPCC_MCM_3DLUT_INDEX[MAX_MPCC]; \ + uint32_t MPCC_MCM_3DLUT_DATA[MAX_MPCC]; \ + uint32_t MPCC_MCM_3DLUT_DATA_30BIT[MAX_MPCC]; \ + uint32_t MPCC_MCM_3DLUT_READ_WRITE_CONTROL[MAX_MPCC]; \ + uint32_t MPCC_MCM_3DLUT_OUT_NORM_FACTOR[MAX_MPCC]; \ + uint32_t MPCC_MCM_3DLUT_OUT_OFFSET_R[MAX_MPCC]; \ + uint32_t MPCC_MCM_3DLUT_OUT_OFFSET_G[MAX_MPCC]; \ + uint32_t MPCC_MCM_3DLUT_OUT_OFFSET_B[MAX_MPCC]; \ + uint32_t MPCC_MCM_1DLUT_CONTROL[MAX_MPCC]; \ + uint32_t MPCC_MCM_1DLUT_LUT_INDEX[MAX_MPCC]; \ + uint32_t MPCC_MCM_1DLUT_LUT_DATA[MAX_MPCC]; \ + uint32_t MPCC_MCM_1DLUT_LUT_CONTROL[MAX_MPCC]; \ + uint32_t MPCC_MCM_1DLUT_RAMA_START_CNTL_B[MAX_MPCC]; \ + uint32_t MPCC_MCM_1DLUT_RAMA_START_CNTL_G[MAX_MPCC]; \ + uint32_t MPCC_MCM_1DLUT_RAMA_START_CNTL_R[MAX_MPCC]; \ + uint32_t MPCC_MCM_1DLUT_RAMA_START_SLOPE_CNTL_B[MAX_MPCC]; \ + uint32_t MPCC_MCM_1DLUT_RAMA_START_SLOPE_CNTL_G[MAX_MPCC]; \ + uint32_t MPCC_MCM_1DLUT_RAMA_START_SLOPE_CNTL_R[MAX_MPCC]; \ + uint32_t MPCC_MCM_1DLUT_RAMA_START_BASE_CNTL_B[MAX_MPCC]; \ + uint32_t MPCC_MCM_1DLUT_RAMA_START_BASE_CNTL_G[MAX_MPCC]; \ + uint32_t MPCC_MCM_1DLUT_RAMA_START_BASE_CNTL_R[MAX_MPCC]; \ + uint32_t MPCC_MCM_1DLUT_RAMA_END_CNTL1_B[MAX_MPCC]; \ + uint32_t MPCC_MCM_1DLUT_RAMA_END_CNTL2_B[MAX_MPCC]; \ + uint32_t MPCC_MCM_1DLUT_RAMA_END_CNTL1_G[MAX_MPCC]; \ + uint32_t MPCC_MCM_1DLUT_RAMA_END_CNTL2_G[MAX_MPCC]; \ + uint32_t MPCC_MCM_1DLUT_RAMA_END_CNTL1_R[MAX_MPCC]; \ + uint32_t MPCC_MCM_1DLUT_RAMA_END_CNTL2_R[MAX_MPCC]; \ + uint32_t MPCC_MCM_1DLUT_RAMA_OFFSET_B[MAX_MPCC]; \ + uint32_t MPCC_MCM_1DLUT_RAMA_OFFSET_G[MAX_MPCC]; \ + uint32_t MPCC_MCM_1DLUT_RAMA_OFFSET_R[MAX_MPCC]; \ + uint32_t MPCC_MCM_1DLUT_RAMA_REGION_0_1[MAX_MPCC]; \ + uint32_t MPCC_MCM_1DLUT_RAMA_REGION_2_3[MAX_MPCC]; \ + uint32_t MPCC_MCM_1DLUT_RAMA_REGION_4_5[MAX_MPCC]; \ + uint32_t MPCC_MCM_1DLUT_RAMA_REGION_6_7[MAX_MPCC]; \ + uint32_t MPCC_MCM_1DLUT_RAMA_REGION_8_9[MAX_MPCC]; \ + uint32_t MPCC_MCM_1DLUT_RAMA_REGION_10_11[MAX_MPCC]; \ + uint32_t MPCC_MCM_1DLUT_RAMA_REGION_12_13[MAX_MPCC]; \ + uint32_t MPCC_MCM_1DLUT_RAMA_REGION_14_15[MAX_MPCC]; \ + uint32_t MPCC_MCM_1DLUT_RAMA_REGION_16_17[MAX_MPCC]; \ + uint32_t MPCC_MCM_1DLUT_RAMA_REGION_18_19[MAX_MPCC]; \ + uint32_t MPCC_MCM_1DLUT_RAMA_REGION_20_21[MAX_MPCC]; \ + uint32_t MPCC_MCM_1DLUT_RAMA_REGION_22_23[MAX_MPCC]; \ + uint32_t MPCC_MCM_1DLUT_RAMA_REGION_24_25[MAX_MPCC]; \ + uint32_t MPCC_MCM_1DLUT_RAMA_REGION_26_27[MAX_MPCC]; \ + uint32_t MPCC_MCM_1DLUT_RAMA_REGION_28_29[MAX_MPCC]; \ + uint32_t MPCC_MCM_1DLUT_RAMA_REGION_30_31[MAX_MPCC]; \ + uint32_t MPCC_MCM_1DLUT_RAMA_REGION_32_33[MAX_MPCC]; \ + uint32_t MPCC_MCM_1DLUT_RAMB_START_CNTL_B[MAX_MPCC]; \ + uint32_t MPCC_MCM_1DLUT_RAMB_START_CNTL_G[MAX_MPCC]; \ + uint32_t MPCC_MCM_1DLUT_RAMB_START_CNTL_R[MAX_MPCC]; \ + uint32_t MPCC_MCM_1DLUT_RAMB_START_SLOPE_CNTL_B[MAX_MPCC]; \ + uint32_t MPCC_MCM_1DLUT_RAMB_START_SLOPE_CNTL_G[MAX_MPCC]; \ + uint32_t MPCC_MCM_1DLUT_RAMB_START_SLOPE_CNTL_R[MAX_MPCC]; \ + uint32_t MPCC_MCM_1DLUT_RAMB_START_BASE_CNTL_B[MAX_MPCC]; \ + uint32_t MPCC_MCM_1DLUT_RAMB_START_BASE_CNTL_G[MAX_MPCC]; \ + uint32_t MPCC_MCM_1DLUT_RAMB_START_BASE_CNTL_R[MAX_MPCC]; \ + uint32_t MPCC_MCM_1DLUT_RAMB_END_CNTL1_B[MAX_MPCC]; \ + uint32_t MPCC_MCM_1DLUT_RAMB_END_CNTL2_B[MAX_MPCC]; \ + uint32_t MPCC_MCM_1DLUT_RAMB_END_CNTL1_G[MAX_MPCC]; \ + uint32_t MPCC_MCM_1DLUT_RAMB_END_CNTL2_G[MAX_MPCC]; \ + uint32_t MPCC_MCM_1DLUT_RAMB_END_CNTL1_R[MAX_MPCC]; \ + uint32_t MPCC_MCM_1DLUT_RAMB_END_CNTL2_R[MAX_MPCC]; \ + uint32_t MPCC_MCM_1DLUT_RAMB_OFFSET_B[MAX_MPCC]; \ + uint32_t MPCC_MCM_1DLUT_RAMB_OFFSET_G[MAX_MPCC]; \ + uint32_t MPCC_MCM_1DLUT_RAMB_OFFSET_R[MAX_MPCC]; \ + uint32_t MPCC_MCM_1DLUT_RAMB_REGION_0_1[MAX_MPCC]; \ + uint32_t MPCC_MCM_1DLUT_RAMB_REGION_2_3[MAX_MPCC]; \ + uint32_t MPCC_MCM_1DLUT_RAMB_REGION_4_5[MAX_MPCC]; \ + uint32_t MPCC_MCM_1DLUT_RAMB_REGION_6_7[MAX_MPCC]; \ + uint32_t MPCC_MCM_1DLUT_RAMB_REGION_8_9[MAX_MPCC]; \ + uint32_t MPCC_MCM_1DLUT_RAMB_REGION_10_11[MAX_MPCC]; \ + uint32_t MPCC_MCM_1DLUT_RAMB_REGION_12_13[MAX_MPCC]; \ + uint32_t MPCC_MCM_1DLUT_RAMB_REGION_14_15[MAX_MPCC]; \ + uint32_t MPCC_MCM_1DLUT_RAMB_REGION_16_17[MAX_MPCC]; \ + uint32_t MPCC_MCM_1DLUT_RAMB_REGION_18_19[MAX_MPCC]; \ + uint32_t MPCC_MCM_1DLUT_RAMB_REGION_20_21[MAX_MPCC]; \ + uint32_t MPCC_MCM_1DLUT_RAMB_REGION_22_23[MAX_MPCC]; \ + uint32_t MPCC_MCM_1DLUT_RAMB_REGION_24_25[MAX_MPCC]; \ + uint32_t MPCC_MCM_1DLUT_RAMB_REGION_26_27[MAX_MPCC]; \ + uint32_t MPCC_MCM_1DLUT_RAMB_REGION_28_29[MAX_MPCC]; \ + uint32_t MPCC_MCM_1DLUT_RAMB_REGION_30_31[MAX_MPCC]; \ + uint32_t MPCC_MCM_1DLUT_RAMB_REGION_32_33[MAX_MPCC]; \ + uint32_t MPCC_MCM_MEM_PWR_CTRL[MAX_MPCC] + +#define MPC_COMMON_MASK_SH_LIST_DCN3_0(mask_sh) \ + MPC_COMMON_MASK_SH_LIST_DCN1_0(mask_sh),\ + SF(MPCC0_MPCC_CONTROL, MPCC_BG_BPC, mask_sh),\ + SF(MPCC0_MPCC_CONTROL, MPCC_BOT_GAIN_MODE, mask_sh),\ + SF(MPCC0_MPCC_TOP_GAIN, MPCC_TOP_GAIN, mask_sh),\ + SF(MPCC0_MPCC_BOT_GAIN_INSIDE, MPCC_BOT_GAIN_INSIDE, mask_sh),\ + SF(MPCC0_MPCC_BOT_GAIN_OUTSIDE, MPCC_BOT_GAIN_OUTSIDE, mask_sh),\ + SF(MPC_OUT0_CSC_MODE, MPC_OCSC_MODE, mask_sh),\ + SF(MPC_OUT0_CSC_C11_C12_A, MPC_OCSC_C11_A, mask_sh),\ + SF(MPC_OUT0_CSC_C11_C12_A, MPC_OCSC_C12_A, mask_sh),\ + SF(MPCC0_MPCC_STATUS, MPCC_DISABLED, mask_sh),\ + SF(MPCC0_MPCC_MEM_PWR_CTRL, MPCC_OGAM_MEM_PWR_FORCE, mask_sh),\ + SF(MPCC0_MPCC_MEM_PWR_CTRL, MPCC_OGAM_MEM_PWR_DIS, mask_sh),\ + SF(MPCC0_MPCC_MEM_PWR_CTRL, MPCC_OGAM_MEM_PWR_STATE, mask_sh),\ + SF(MPC_OUT0_DENORM_CONTROL, MPC_OUT_DENORM_MODE, mask_sh),\ + SF(MPC_OUT0_DENORM_CONTROL, MPC_OUT_DENORM_CLAMP_MAX_R_CR, mask_sh),\ + SF(MPC_OUT0_DENORM_CONTROL, MPC_OUT_DENORM_CLAMP_MIN_R_CR, mask_sh),\ + SF(MPC_OUT0_DENORM_CLAMP_G_Y, MPC_OUT_DENORM_CLAMP_MAX_G_Y, mask_sh),\ + SF(MPC_OUT0_DENORM_CLAMP_G_Y, MPC_OUT_DENORM_CLAMP_MIN_G_Y, mask_sh),\ + SF(MPC_OUT0_DENORM_CLAMP_B_CB, MPC_OUT_DENORM_CLAMP_MAX_B_CB, mask_sh),\ + SF(MPC_OUT0_DENORM_CLAMP_B_CB, MPC_OUT_DENORM_CLAMP_MIN_B_CB, mask_sh),\ + SF(MPCC_OGAM0_MPCC_GAMUT_REMAP_MODE, MPCC_GAMUT_REMAP_MODE, mask_sh),\ + SF(MPCC_OGAM0_MPCC_GAMUT_REMAP_MODE, MPCC_GAMUT_REMAP_MODE_CURRENT, mask_sh),\ + SF(MPCC_OGAM0_MPCC_GAMUT_REMAP_COEF_FORMAT, MPCC_GAMUT_REMAP_COEF_FORMAT, mask_sh),\ + SF(MPCC_OGAM0_MPC_GAMUT_REMAP_C11_C12_A, MPCC_GAMUT_REMAP_C11_A, mask_sh),\ + SF(MPCC_OGAM0_MPC_GAMUT_REMAP_C11_C12_A, MPCC_GAMUT_REMAP_C12_A, mask_sh),\ + SF(MPC_DWB0_MUX, MPC_DWB0_MUX, mask_sh),\ + SF(MPC_DWB0_MUX, MPC_DWB0_MUX_STATUS, mask_sh),\ + SF(MPC_OUT0_MUX, MPC_OUT_RATE_CONTROL, mask_sh),\ + SF(MPC_OUT0_MUX, MPC_OUT_RATE_CONTROL_DISABLE, mask_sh),\ + SF(MPC_OUT0_MUX, MPC_OUT_FLOW_CONTROL_MODE, mask_sh),\ + SF(MPC_OUT0_MUX, MPC_OUT_FLOW_CONTROL_COUNT, mask_sh), \ + SF(MPC_RMU_CONTROL, MPC_RMU0_MUX, mask_sh), \ + SF(MPC_RMU_CONTROL, MPC_RMU1_MUX, mask_sh), \ + SF(MPC_RMU_CONTROL, MPC_RMU0_MUX_STATUS, mask_sh), \ + SF(MPC_RMU_CONTROL, MPC_RMU1_MUX_STATUS, mask_sh), \ + SF(MPCC_OGAM0_MPCC_OGAM_RAMA_REGION_0_1, MPCC_OGAM_RAMA_EXP_REGION0_LUT_OFFSET, mask_sh),\ + SF(MPCC_OGAM0_MPCC_OGAM_RAMA_REGION_0_1, MPCC_OGAM_RAMA_EXP_REGION0_NUM_SEGMENTS, mask_sh),\ + SF(MPCC_OGAM0_MPCC_OGAM_RAMA_REGION_0_1, MPCC_OGAM_RAMA_EXP_REGION1_LUT_OFFSET, mask_sh),\ + SF(MPCC_OGAM0_MPCC_OGAM_RAMA_REGION_0_1, MPCC_OGAM_RAMA_EXP_REGION1_NUM_SEGMENTS, mask_sh),\ + SF(MPCC_OGAM0_MPCC_OGAM_RAMA_END_CNTL2_B, MPCC_OGAM_RAMA_EXP_REGION_END_SLOPE_B, mask_sh),\ + SF(MPCC_OGAM0_MPCC_OGAM_RAMA_END_CNTL2_B, MPCC_OGAM_RAMA_EXP_REGION_END_B, mask_sh),\ + SF(MPCC_OGAM0_MPCC_OGAM_RAMA_END_CNTL1_B, MPCC_OGAM_RAMA_EXP_REGION_END_BASE_B, mask_sh),\ + SF(MPCC_OGAM0_MPCC_OGAM_RAMA_START_SLOPE_CNTL_B, MPCC_OGAM_RAMA_EXP_REGION_START_SLOPE_B, mask_sh),\ + SF(MPCC_OGAM0_MPCC_OGAM_RAMA_START_BASE_CNTL_B, MPCC_OGAM_RAMA_EXP_REGION_START_BASE_B, mask_sh),\ + SF(MPCC_OGAM0_MPCC_OGAM_RAMA_START_CNTL_B, MPCC_OGAM_RAMA_EXP_REGION_START_B, mask_sh),\ + SF(MPCC_OGAM0_MPCC_OGAM_RAMA_START_CNTL_B, MPCC_OGAM_RAMA_EXP_REGION_START_SEGMENT_B, mask_sh),\ + SF(MPCC_OGAM0_MPCC_OGAM_RAMA_OFFSET_B, MPCC_OGAM_RAMA_OFFSET_B, mask_sh),\ + SF(MPCC_OGAM0_MPCC_OGAM_RAMA_OFFSET_G, MPCC_OGAM_RAMA_OFFSET_G, mask_sh),\ + SF(MPCC_OGAM0_MPCC_OGAM_RAMA_OFFSET_R, MPCC_OGAM_RAMA_OFFSET_R, mask_sh),\ + SF(MPCC_OGAM0_MPCC_OGAM_LUT_INDEX, MPCC_OGAM_LUT_INDEX, mask_sh),\ + SF(MPCC_OGAM0_MPCC_OGAM_CONTROL, MPCC_OGAM_MODE, mask_sh),\ + SF(MPCC_OGAM0_MPCC_OGAM_CONTROL, MPCC_OGAM_SELECT, mask_sh),\ + SF(MPCC_OGAM0_MPCC_OGAM_CONTROL, MPCC_OGAM_PWL_DISABLE, mask_sh),\ + SF(MPCC_OGAM0_MPCC_OGAM_CONTROL, MPCC_OGAM_MODE_CURRENT, mask_sh),\ + SF(MPCC_OGAM0_MPCC_OGAM_CONTROL, MPCC_OGAM_SELECT_CURRENT, mask_sh),\ + SF(MPCC_OGAM0_MPCC_OGAM_LUT_CONTROL, MPCC_OGAM_LUT_WRITE_COLOR_MASK, mask_sh),\ + SF(MPCC_OGAM0_MPCC_OGAM_LUT_CONTROL, MPCC_OGAM_LUT_READ_COLOR_SEL, mask_sh),\ + SF(MPCC_OGAM0_MPCC_OGAM_LUT_CONTROL, MPCC_OGAM_LUT_READ_DBG, mask_sh),\ + SF(MPCC_OGAM0_MPCC_OGAM_LUT_CONTROL, MPCC_OGAM_LUT_HOST_SEL, mask_sh),\ + SF(MPCC_OGAM0_MPCC_OGAM_LUT_CONTROL, MPCC_OGAM_LUT_CONFIG_MODE, mask_sh),\ + SF(MPCC_OGAM0_MPCC_OGAM_LUT_CONTROL, MPCC_OGAM_LUT_STATUS, mask_sh),\ + SF(MPCC_OGAM0_MPCC_OGAM_LUT_DATA, MPCC_OGAM_LUT_DATA, mask_sh),\ + SF(MPC_RMU0_3DLUT_MODE, MPC_RMU_3DLUT_MODE, mask_sh),\ + SF(MPC_RMU0_3DLUT_MODE, MPC_RMU_3DLUT_SIZE, mask_sh),\ + SF(MPC_RMU0_3DLUT_MODE, MPC_RMU_3DLUT_MODE_CURRENT, mask_sh),\ + SF(MPC_RMU0_3DLUT_READ_WRITE_CONTROL, MPC_RMU_3DLUT_WRITE_EN_MASK, mask_sh),\ + SF(MPC_RMU0_3DLUT_READ_WRITE_CONTROL, MPC_RMU_3DLUT_RAM_SEL, mask_sh),\ + SF(MPC_RMU0_3DLUT_READ_WRITE_CONTROL, MPC_RMU_3DLUT_30BIT_EN, mask_sh),\ + SF(MPC_RMU0_3DLUT_READ_WRITE_CONTROL, MPC_RMU_3DLUT_CONFIG_STATUS, mask_sh),\ + SF(MPC_RMU0_3DLUT_READ_WRITE_CONTROL, MPC_RMU_3DLUT_READ_SEL, mask_sh),\ + SF(MPC_RMU0_3DLUT_INDEX, MPC_RMU_3DLUT_INDEX, mask_sh),\ + SF(MPC_RMU0_3DLUT_DATA, MPC_RMU_3DLUT_DATA0, mask_sh),\ + SF(MPC_RMU0_3DLUT_DATA, MPC_RMU_3DLUT_DATA1, mask_sh),\ + SF(MPC_RMU0_3DLUT_DATA_30BIT, MPC_RMU_3DLUT_DATA_30BIT, mask_sh),\ + SF(MPC_RMU0_SHAPER_CONTROL, MPC_RMU_SHAPER_LUT_MODE, mask_sh),\ + SF(MPC_RMU0_SHAPER_CONTROL, MPC_RMU_SHAPER_LUT_MODE_CURRENT, mask_sh),\ + SF(MPC_RMU0_SHAPER_OFFSET_R, MPC_RMU_SHAPER_OFFSET_R, mask_sh),\ + SF(MPC_RMU0_SHAPER_OFFSET_G, MPC_RMU_SHAPER_OFFSET_G, mask_sh),\ + SF(MPC_RMU0_SHAPER_OFFSET_B, MPC_RMU_SHAPER_OFFSET_B, mask_sh),\ + SF(MPC_RMU0_SHAPER_SCALE_R, MPC_RMU_SHAPER_SCALE_R, mask_sh),\ + SF(MPC_RMU0_SHAPER_SCALE_G_B, MPC_RMU_SHAPER_SCALE_G, mask_sh),\ + SF(MPC_RMU0_SHAPER_SCALE_G_B, MPC_RMU_SHAPER_SCALE_B, mask_sh),\ + SF(MPC_RMU0_SHAPER_LUT_INDEX, MPC_RMU_SHAPER_LUT_INDEX, mask_sh),\ + SF(MPC_RMU0_SHAPER_LUT_DATA, MPC_RMU_SHAPER_LUT_DATA, mask_sh),\ + SF(MPC_RMU0_SHAPER_LUT_WRITE_EN_MASK, MPC_RMU_SHAPER_LUT_WRITE_EN_MASK, mask_sh),\ + SF(MPC_RMU0_SHAPER_LUT_WRITE_EN_MASK, MPC_RMU_SHAPER_LUT_WRITE_SEL, mask_sh),\ + SF(MPC_RMU0_SHAPER_LUT_WRITE_EN_MASK, MPC_RMU_SHAPER_CONFIG_STATUS, mask_sh),\ + SF(MPC_RMU0_SHAPER_RAMA_START_CNTL_B, MPC_RMU_SHAPER_RAMA_EXP_REGION_START_B, mask_sh),\ + SF(MPC_RMU0_SHAPER_RAMA_START_CNTL_B, MPC_RMU_SHAPER_RAMA_EXP_REGION_START_SEGMENT_B, mask_sh),\ + SF(MPC_RMU0_SHAPER_RAMA_END_CNTL_B, MPC_RMU_SHAPER_RAMA_EXP_REGION_END_B, mask_sh),\ + SF(MPC_RMU0_SHAPER_RAMA_END_CNTL_B, MPC_RMU_SHAPER_RAMA_EXP_REGION_END_BASE_B, mask_sh),\ + SF(MPC_RMU0_SHAPER_RAMA_REGION_0_1, MPC_RMU_SHAPER_RAMA_EXP_REGION0_LUT_OFFSET, mask_sh),\ + SF(MPC_RMU0_SHAPER_RAMA_REGION_0_1, MPC_RMU_SHAPER_RAMA_EXP_REGION0_NUM_SEGMENTS, mask_sh),\ + SF(MPC_RMU0_SHAPER_RAMA_REGION_0_1, MPC_RMU_SHAPER_RAMA_EXP_REGION1_LUT_OFFSET, mask_sh),\ + SF(MPC_RMU0_SHAPER_RAMA_REGION_0_1, MPC_RMU_SHAPER_RAMA_EXP_REGION1_NUM_SEGMENTS, mask_sh),\ + SF(MPC_RMU_MEM_PWR_CTRL, MPC_RMU0_MEM_PWR_FORCE, mask_sh),\ + SF(MPC_RMU_MEM_PWR_CTRL, MPC_RMU0_MEM_PWR_DIS, mask_sh),\ + SF(MPC_RMU_MEM_PWR_CTRL, MPC_RMU0_SHAPER_MEM_PWR_STATE, mask_sh),\ + SF(MPC_RMU_MEM_PWR_CTRL, MPC_RMU0_3DLUT_MEM_PWR_STATE, mask_sh),\ + SF(MPC_RMU_MEM_PWR_CTRL, MPC_RMU1_MEM_PWR_FORCE, mask_sh),\ + SF(MPC_RMU_MEM_PWR_CTRL, MPC_RMU1_MEM_PWR_DIS, mask_sh),\ + SF(MPC_RMU_MEM_PWR_CTRL, MPC_RMU1_SHAPER_MEM_PWR_STATE, mask_sh),\ + SF(MPC_RMU_MEM_PWR_CTRL, MPC_RMU1_3DLUT_MEM_PWR_STATE, mask_sh),\ + SF(CUR_VUPDATE_LOCK_SET0, CUR_VUPDATE_LOCK_SET, mask_sh) + + +#define MPC_COMMON_MASK_SH_LIST_DCN30(mask_sh) \ + MPC_COMMON_MASK_SH_LIST_DCN1_0(mask_sh),\ + SF(MPCC0_MPCC_CONTROL, MPCC_BG_BPC, mask_sh),\ + SF(MPCC0_MPCC_CONTROL, MPCC_BOT_GAIN_MODE, mask_sh),\ + SF(MPCC0_MPCC_TOP_GAIN, MPCC_TOP_GAIN, mask_sh),\ + SF(MPCC0_MPCC_BOT_GAIN_INSIDE, MPCC_BOT_GAIN_INSIDE, mask_sh),\ + SF(MPCC0_MPCC_BOT_GAIN_OUTSIDE, MPCC_BOT_GAIN_OUTSIDE, mask_sh),\ + SF(MPC_OUT0_CSC_MODE, MPC_OCSC_MODE, mask_sh),\ + SF(MPC_OUT0_CSC_C11_C12_A, MPC_OCSC_C11_A, mask_sh),\ + SF(MPC_OUT0_CSC_C11_C12_A, MPC_OCSC_C12_A, mask_sh),\ + SF(MPCC0_MPCC_STATUS, MPCC_DISABLED, mask_sh),\ + SF(MPCC0_MPCC_MEM_PWR_CTRL, MPCC_OGAM_MEM_PWR_FORCE, mask_sh),\ + SF(MPCC0_MPCC_MEM_PWR_CTRL, MPCC_OGAM_MEM_PWR_DIS, mask_sh),\ + SF(MPCC0_MPCC_MEM_PWR_CTRL, MPCC_OGAM_MEM_LOW_PWR_MODE, mask_sh),\ + SF(MPCC0_MPCC_MEM_PWR_CTRL, MPCC_OGAM_MEM_PWR_STATE, mask_sh),\ + SF(MPC_OUT0_DENORM_CONTROL, MPC_OUT_DENORM_MODE, mask_sh),\ + SF(MPC_OUT0_DENORM_CONTROL, MPC_OUT_DENORM_CLAMP_MAX_R_CR, mask_sh),\ + SF(MPC_OUT0_DENORM_CONTROL, MPC_OUT_DENORM_CLAMP_MIN_R_CR, mask_sh),\ + SF(MPC_OUT0_DENORM_CLAMP_G_Y, MPC_OUT_DENORM_CLAMP_MAX_G_Y, mask_sh),\ + SF(MPC_OUT0_DENORM_CLAMP_G_Y, MPC_OUT_DENORM_CLAMP_MIN_G_Y, mask_sh),\ + SF(MPC_OUT0_DENORM_CLAMP_B_CB, MPC_OUT_DENORM_CLAMP_MAX_B_CB, mask_sh),\ + SF(MPC_OUT0_DENORM_CLAMP_B_CB, MPC_OUT_DENORM_CLAMP_MIN_B_CB, mask_sh),\ + SF(MPCC_OGAM0_MPCC_GAMUT_REMAP_MODE, MPCC_GAMUT_REMAP_MODE, mask_sh),\ + SF(MPCC_OGAM0_MPCC_GAMUT_REMAP_MODE, MPCC_GAMUT_REMAP_MODE_CURRENT, mask_sh),\ + SF(MPCC_OGAM0_MPCC_GAMUT_REMAP_COEF_FORMAT, MPCC_GAMUT_REMAP_COEF_FORMAT, mask_sh),\ + SF(MPCC_OGAM0_MPC_GAMUT_REMAP_C11_C12_A, MPCC_GAMUT_REMAP_C11_A, mask_sh),\ + SF(MPCC_OGAM0_MPC_GAMUT_REMAP_C11_C12_A, MPCC_GAMUT_REMAP_C12_A, mask_sh),\ + SF(MPC_DWB0_MUX, MPC_DWB0_MUX, mask_sh),\ + SF(MPC_DWB0_MUX, MPC_DWB0_MUX_STATUS, mask_sh),\ + SF(MPC_OUT0_MUX, MPC_OUT_RATE_CONTROL, mask_sh),\ + SF(MPC_OUT0_MUX, MPC_OUT_RATE_CONTROL_DISABLE, mask_sh),\ + SF(MPC_OUT0_MUX, MPC_OUT_FLOW_CONTROL_MODE, mask_sh),\ + SF(MPC_OUT0_MUX, MPC_OUT_FLOW_CONTROL_COUNT, mask_sh), \ + SF(MPC_RMU_CONTROL, MPC_RMU0_MUX, mask_sh), \ + SF(MPC_RMU_CONTROL, MPC_RMU1_MUX, mask_sh), \ + SF(MPC_RMU_CONTROL, MPC_RMU0_MUX_STATUS, mask_sh), \ + SF(MPC_RMU_CONTROL, MPC_RMU1_MUX_STATUS, mask_sh), \ + SF(MPCC_OGAM0_MPCC_OGAM_RAMA_REGION_0_1, MPCC_OGAM_RAMA_EXP_REGION0_LUT_OFFSET, mask_sh),\ + SF(MPCC_OGAM0_MPCC_OGAM_RAMA_REGION_0_1, MPCC_OGAM_RAMA_EXP_REGION0_NUM_SEGMENTS, mask_sh),\ + SF(MPCC_OGAM0_MPCC_OGAM_RAMA_REGION_0_1, MPCC_OGAM_RAMA_EXP_REGION1_LUT_OFFSET, mask_sh),\ + SF(MPCC_OGAM0_MPCC_OGAM_RAMA_REGION_0_1, MPCC_OGAM_RAMA_EXP_REGION1_NUM_SEGMENTS, mask_sh),\ + SF(MPCC_OGAM0_MPCC_OGAM_RAMA_END_CNTL2_B, MPCC_OGAM_RAMA_EXP_REGION_END_SLOPE_B, mask_sh),\ + SF(MPCC_OGAM0_MPCC_OGAM_RAMA_END_CNTL2_B, MPCC_OGAM_RAMA_EXP_REGION_END_B, mask_sh),\ + SF(MPCC_OGAM0_MPCC_OGAM_RAMA_END_CNTL1_B, MPCC_OGAM_RAMA_EXP_REGION_END_BASE_B, mask_sh),\ + SF(MPCC_OGAM0_MPCC_OGAM_RAMA_START_SLOPE_CNTL_B, MPCC_OGAM_RAMA_EXP_REGION_START_SLOPE_B, mask_sh),\ + SF(MPCC_OGAM0_MPCC_OGAM_RAMA_START_BASE_CNTL_B, MPCC_OGAM_RAMA_EXP_REGION_START_BASE_B, mask_sh),\ + SF(MPCC_OGAM0_MPCC_OGAM_RAMA_START_CNTL_B, MPCC_OGAM_RAMA_EXP_REGION_START_B, mask_sh),\ + SF(MPCC_OGAM0_MPCC_OGAM_RAMA_START_CNTL_B, MPCC_OGAM_RAMA_EXP_REGION_START_SEGMENT_B, mask_sh),\ + SF(MPCC_OGAM0_MPCC_OGAM_RAMA_OFFSET_B, MPCC_OGAM_RAMA_OFFSET_B, mask_sh),\ + SF(MPCC_OGAM0_MPCC_OGAM_RAMA_OFFSET_G, MPCC_OGAM_RAMA_OFFSET_G, mask_sh),\ + SF(MPCC_OGAM0_MPCC_OGAM_RAMA_OFFSET_R, MPCC_OGAM_RAMA_OFFSET_R, mask_sh),\ + SF(MPCC_OGAM0_MPCC_OGAM_LUT_INDEX, MPCC_OGAM_LUT_INDEX, mask_sh),\ + SF(MPCC_OGAM0_MPCC_OGAM_CONTROL, MPCC_OGAM_MODE, mask_sh),\ + SF(MPCC_OGAM0_MPCC_OGAM_CONTROL, MPCC_OGAM_SELECT, mask_sh),\ + SF(MPCC_OGAM0_MPCC_OGAM_CONTROL, MPCC_OGAM_PWL_DISABLE, mask_sh),\ + SF(MPCC_OGAM0_MPCC_OGAM_CONTROL, MPCC_OGAM_MODE_CURRENT, mask_sh),\ + SF(MPCC_OGAM0_MPCC_OGAM_CONTROL, MPCC_OGAM_SELECT_CURRENT, mask_sh),\ + SF(MPCC_OGAM0_MPCC_OGAM_LUT_CONTROL, MPCC_OGAM_LUT_WRITE_COLOR_MASK, mask_sh),\ + SF(MPCC_OGAM0_MPCC_OGAM_LUT_CONTROL, MPCC_OGAM_LUT_READ_COLOR_SEL, mask_sh),\ + SF(MPCC_OGAM0_MPCC_OGAM_LUT_CONTROL, MPCC_OGAM_LUT_READ_DBG, mask_sh),\ + SF(MPCC_OGAM0_MPCC_OGAM_LUT_CONTROL, MPCC_OGAM_LUT_HOST_SEL, mask_sh),\ + SF(MPCC_OGAM0_MPCC_OGAM_LUT_CONTROL, MPCC_OGAM_LUT_CONFIG_MODE, mask_sh),\ + /*SF(MPCC_OGAM0_MPCC_OGAM_LUT_CONTROL, MPCC_OGAM_LUT_STATUS, mask_sh),*/\ + SF(MPCC_OGAM0_MPCC_OGAM_LUT_DATA, MPCC_OGAM_LUT_DATA, mask_sh),\ + SF(MPC_RMU0_3DLUT_MODE, MPC_RMU_3DLUT_MODE, mask_sh),\ + SF(MPC_RMU0_3DLUT_MODE, MPC_RMU_3DLUT_SIZE, mask_sh),\ + /*SF(MPC_RMU0_3DLUT_MODE, MPC_RMU_3DLUT_MODE_CURRENT, mask_sh),*/\ + SF(MPC_RMU0_3DLUT_READ_WRITE_CONTROL, MPC_RMU_3DLUT_WRITE_EN_MASK, mask_sh),\ + SF(MPC_RMU0_3DLUT_READ_WRITE_CONTROL, MPC_RMU_3DLUT_RAM_SEL, mask_sh),\ + SF(MPC_RMU0_3DLUT_READ_WRITE_CONTROL, MPC_RMU_3DLUT_30BIT_EN, mask_sh),\ + /*SF(MPC_RMU0_3DLUT_READ_WRITE_CONTROL, MPC_RMU_3DLUT_CONFIG_STATUS, mask_sh),*/\ + SF(MPC_RMU0_3DLUT_READ_WRITE_CONTROL, MPC_RMU_3DLUT_READ_SEL, mask_sh),\ + SF(MPC_RMU0_3DLUT_INDEX, MPC_RMU_3DLUT_INDEX, mask_sh),\ + SF(MPC_RMU0_3DLUT_DATA, MPC_RMU_3DLUT_DATA0, mask_sh),\ + SF(MPC_RMU0_3DLUT_DATA, MPC_RMU_3DLUT_DATA1, mask_sh),\ + SF(MPC_RMU0_3DLUT_DATA_30BIT, MPC_RMU_3DLUT_DATA_30BIT, mask_sh),\ + SF(MPC_RMU0_SHAPER_CONTROL, MPC_RMU_SHAPER_LUT_MODE, mask_sh),\ + /*SF(MPC_RMU0_SHAPER_CONTROL, MPC_RMU_SHAPER_LUT_MODE_CURRENT, mask_sh),*/\ + SF(MPC_RMU0_SHAPER_OFFSET_R, MPC_RMU_SHAPER_OFFSET_R, mask_sh),\ + SF(MPC_RMU0_SHAPER_OFFSET_G, MPC_RMU_SHAPER_OFFSET_G, mask_sh),\ + SF(MPC_RMU0_SHAPER_OFFSET_B, MPC_RMU_SHAPER_OFFSET_B, mask_sh),\ + SF(MPC_RMU0_SHAPER_SCALE_R, MPC_RMU_SHAPER_SCALE_R, mask_sh),\ + SF(MPC_RMU0_SHAPER_SCALE_G_B, MPC_RMU_SHAPER_SCALE_G, mask_sh),\ + SF(MPC_RMU0_SHAPER_SCALE_G_B, MPC_RMU_SHAPER_SCALE_B, mask_sh),\ + SF(MPC_RMU0_SHAPER_LUT_INDEX, MPC_RMU_SHAPER_LUT_INDEX, mask_sh),\ + SF(MPC_RMU0_SHAPER_LUT_DATA, MPC_RMU_SHAPER_LUT_DATA, mask_sh),\ + SF(MPC_RMU0_SHAPER_LUT_WRITE_EN_MASK, MPC_RMU_SHAPER_LUT_WRITE_EN_MASK, mask_sh),\ + SF(MPC_RMU0_SHAPER_LUT_WRITE_EN_MASK, MPC_RMU_SHAPER_LUT_WRITE_SEL, mask_sh),\ + /*SF(MPC_RMU0_SHAPER_LUT_WRITE_EN_MASK, MPC_RMU_SHAPER_CONFIG_STATUS, mask_sh),*/\ + SF(MPC_RMU0_SHAPER_RAMA_START_CNTL_B, MPC_RMU_SHAPER_RAMA_EXP_REGION_START_B, mask_sh),\ + SF(MPC_RMU0_SHAPER_RAMA_START_CNTL_B, MPC_RMU_SHAPER_RAMA_EXP_REGION_START_SEGMENT_B, mask_sh),\ + SF(MPC_RMU0_SHAPER_RAMA_END_CNTL_B, MPC_RMU_SHAPER_RAMA_EXP_REGION_END_B, mask_sh),\ + SF(MPC_RMU0_SHAPER_RAMA_END_CNTL_B, MPC_RMU_SHAPER_RAMA_EXP_REGION_END_BASE_B, mask_sh),\ + SF(MPC_RMU0_SHAPER_RAMA_REGION_0_1, MPC_RMU_SHAPER_RAMA_EXP_REGION0_LUT_OFFSET, mask_sh),\ + SF(MPC_RMU0_SHAPER_RAMA_REGION_0_1, MPC_RMU_SHAPER_RAMA_EXP_REGION0_NUM_SEGMENTS, mask_sh),\ + SF(MPC_RMU0_SHAPER_RAMA_REGION_0_1, MPC_RMU_SHAPER_RAMA_EXP_REGION1_LUT_OFFSET, mask_sh),\ + SF(MPC_RMU0_SHAPER_RAMA_REGION_0_1, MPC_RMU_SHAPER_RAMA_EXP_REGION1_NUM_SEGMENTS, mask_sh),\ + SF(MPC_RMU_MEM_PWR_CTRL, MPC_RMU0_MEM_PWR_FORCE, mask_sh),\ + SF(MPC_RMU_MEM_PWR_CTRL, MPC_RMU0_MEM_PWR_DIS, mask_sh),\ + SF(MPC_RMU_MEM_PWR_CTRL, MPC_RMU0_SHAPER_MEM_PWR_STATE, mask_sh),\ + SF(MPC_RMU_MEM_PWR_CTRL, MPC_RMU0_3DLUT_MEM_PWR_STATE, mask_sh),\ + SF(MPC_RMU_MEM_PWR_CTRL, MPC_RMU0_MEM_LOW_PWR_MODE, mask_sh),\ + SF(MPC_RMU_MEM_PWR_CTRL, MPC_RMU1_MEM_PWR_FORCE, mask_sh),\ + SF(MPC_RMU_MEM_PWR_CTRL, MPC_RMU1_MEM_PWR_DIS, mask_sh),\ + SF(MPC_RMU_MEM_PWR_CTRL, MPC_RMU1_SHAPER_MEM_PWR_STATE, mask_sh),\ + SF(MPC_RMU_MEM_PWR_CTRL, MPC_RMU1_3DLUT_MEM_PWR_STATE, mask_sh),\ + SF(MPC_RMU_MEM_PWR_CTRL, MPC_RMU1_MEM_LOW_PWR_MODE, mask_sh),\ + SF(MPC_RMU0_SHAPER_CONTROL, MPC_RMU_SHAPER_MODE_CURRENT, mask_sh),\ + SF(CUR_VUPDATE_LOCK_SET0, CUR_VUPDATE_LOCK_SET, mask_sh) + + +#define MPC_REG_FIELD_LIST_DCN3_0(type) \ + MPC_REG_FIELD_LIST_DCN2_0(type) \ + type MPC_DWB0_MUX;\ + type MPC_DWB0_MUX_STATUS;\ + type MPC_OUT_RATE_CONTROL;\ + type MPC_OUT_RATE_CONTROL_DISABLE;\ + type MPC_OUT_FLOW_CONTROL_MODE;\ + type MPC_OUT_FLOW_CONTROL_COUNT; \ + type MPCC_GAMUT_REMAP_MODE; \ + type MPCC_GAMUT_REMAP_MODE_CURRENT;\ + type MPCC_GAMUT_REMAP_COEF_FORMAT; \ + type MPCC_GAMUT_REMAP_C11_A; \ + type MPCC_GAMUT_REMAP_C12_A; \ + type MPC_RMU0_MUX; \ + type MPC_RMU1_MUX; \ + type MPC_RMU0_MUX_STATUS; \ + type MPC_RMU1_MUX_STATUS; \ + type MPC_RMU0_MEM_PWR_FORCE;\ + type MPC_RMU0_MEM_PWR_DIS;\ + type MPC_RMU0_MEM_LOW_PWR_MODE;\ + type MPC_RMU0_SHAPER_MEM_PWR_STATE;\ + type MPC_RMU0_3DLUT_MEM_PWR_STATE;\ + type MPC_RMU1_MEM_PWR_FORCE;\ + type MPC_RMU1_MEM_PWR_DIS;\ + type MPC_RMU1_MEM_LOW_PWR_MODE;\ + type MPC_RMU1_SHAPER_MEM_PWR_STATE;\ + type MPC_RMU1_3DLUT_MEM_PWR_STATE;\ + type MPCC_OGAM_RAMA_EXP_REGION_START_SLOPE_B; \ + type MPCC_OGAM_RAMA_EXP_REGION_START_BASE_B;\ + type MPCC_OGAM_RAMA_OFFSET_B;\ + type MPCC_OGAM_RAMA_OFFSET_G;\ + type MPCC_OGAM_RAMA_OFFSET_R;\ + type MPCC_OGAM_SELECT; \ + type MPCC_OGAM_PWL_DISABLE; \ + type MPCC_OGAM_MODE_CURRENT; \ + type MPCC_OGAM_SELECT_CURRENT; \ + type MPCC_OGAM_LUT_WRITE_COLOR_MASK; \ + type MPCC_OGAM_LUT_READ_COLOR_SEL; \ + type MPCC_OGAM_LUT_READ_DBG; \ + type MPCC_OGAM_LUT_HOST_SEL; \ + type MPCC_OGAM_LUT_CONFIG_MODE; \ + type MPCC_OGAM_LUT_STATUS; \ + type MPCC_OGAM_RAMA_START_BASE_CNTL_B;\ + type MPCC_OGAM_MEM_LOW_PWR_MODE;\ + type MPCC_OGAM_MEM_PWR_STATE;\ + type MPC_RMU_3DLUT_MODE; \ + type MPC_RMU_3DLUT_SIZE; \ + type MPC_RMU_3DLUT_MODE_CURRENT; \ + type MPC_RMU_3DLUT_WRITE_EN_MASK;\ + type MPC_RMU_3DLUT_RAM_SEL;\ + type MPC_RMU_3DLUT_30BIT_EN;\ + type MPC_RMU_3DLUT_CONFIG_STATUS;\ + type MPC_RMU_3DLUT_READ_SEL;\ + type MPC_RMU_3DLUT_INDEX;\ + type MPC_RMU_3DLUT_DATA0;\ + type MPC_RMU_3DLUT_DATA1;\ + type MPC_RMU_3DLUT_DATA_30BIT;\ + type MPC_RMU_SHAPER_LUT_MODE;\ + type MPC_RMU_SHAPER_LUT_MODE_CURRENT;\ + type MPC_RMU_SHAPER_OFFSET_R;\ + type MPC_RMU_SHAPER_OFFSET_G;\ + type MPC_RMU_SHAPER_OFFSET_B;\ + type MPC_RMU_SHAPER_SCALE_R;\ + type MPC_RMU_SHAPER_SCALE_G;\ + type MPC_RMU_SHAPER_SCALE_B;\ + type MPC_RMU_SHAPER_LUT_INDEX;\ + type MPC_RMU_SHAPER_LUT_DATA;\ + type MPC_RMU_SHAPER_LUT_WRITE_EN_MASK;\ + type MPC_RMU_SHAPER_LUT_WRITE_SEL;\ + type MPC_RMU_SHAPER_CONFIG_STATUS;\ + type MPC_RMU_SHAPER_RAMA_EXP_REGION_START_B;\ + type MPC_RMU_SHAPER_RAMA_EXP_REGION_START_SEGMENT_B;\ + type MPC_RMU_SHAPER_RAMA_EXP_REGION_END_B;\ + type MPC_RMU_SHAPER_RAMA_EXP_REGION_END_BASE_B;\ + type MPC_RMU_SHAPER_RAMA_EXP_REGION0_LUT_OFFSET;\ + type MPC_RMU_SHAPER_RAMA_EXP_REGION0_NUM_SEGMENTS;\ + type MPC_RMU_SHAPER_RAMA_EXP_REGION1_LUT_OFFSET;\ + type MPC_RMU_SHAPER_RAMA_EXP_REGION1_NUM_SEGMENTS;\ + type MPC_RMU_SHAPER_MODE_CURRENT + +#define MPC_REG_FIELD_LIST_DCN32(type) \ + type MPCC_MOVABLE_CM_LOCATION_CNTL;\ + type MPCC_MOVABLE_CM_LOCATION_CNTL_CURRENT;\ + type MPCC_MCM_SHAPER_MEM_PWR_FORCE;\ + type MPCC_MCM_SHAPER_MEM_PWR_DIS;\ + type MPCC_MCM_SHAPER_MEM_LOW_PWR_MODE;\ + type MPCC_MCM_3DLUT_MEM_PWR_FORCE;\ + type MPCC_MCM_3DLUT_MEM_PWR_DIS;\ + type MPCC_MCM_3DLUT_MEM_LOW_PWR_MODE;\ + type MPCC_MCM_1DLUT_MEM_PWR_FORCE;\ + type MPCC_MCM_1DLUT_MEM_PWR_DIS;\ + type MPCC_MCM_1DLUT_MEM_LOW_PWR_MODE;\ + type MPCC_MCM_SHAPER_MEM_PWR_STATE;\ + type MPCC_MCM_3DLUT_MEM_PWR_STATE;\ + type MPCC_MCM_1DLUT_MEM_PWR_STATE;\ + type MPCC_MCM_3DLUT_MODE; \ + type MPCC_MCM_3DLUT_SIZE; \ + type MPCC_MCM_3DLUT_MODE_CURRENT; \ + type MPCC_MCM_3DLUT_WRITE_EN_MASK;\ + type MPCC_MCM_3DLUT_RAM_SEL;\ + type MPCC_MCM_3DLUT_30BIT_EN;\ + type MPCC_MCM_3DLUT_CONFIG_STATUS;\ + type MPCC_MCM_3DLUT_READ_SEL;\ + type MPCC_MCM_3DLUT_INDEX;\ + type MPCC_MCM_3DLUT_DATA0;\ + type MPCC_MCM_3DLUT_DATA1;\ + type MPCC_MCM_3DLUT_DATA_30BIT;\ + type MPCC_MCM_SHAPER_LUT_MODE;\ + type MPCC_MCM_SHAPER_MODE_CURRENT;\ + type MPCC_MCM_SHAPER_OFFSET_R;\ + type MPCC_MCM_SHAPER_OFFSET_G;\ + type MPCC_MCM_SHAPER_OFFSET_B;\ + type MPCC_MCM_SHAPER_SCALE_R;\ + type MPCC_MCM_SHAPER_SCALE_G;\ + type MPCC_MCM_SHAPER_SCALE_B;\ + type MPCC_MCM_SHAPER_LUT_INDEX;\ + type MPCC_MCM_SHAPER_LUT_DATA;\ + type MPCC_MCM_SHAPER_LUT_WRITE_EN_MASK;\ + type MPCC_MCM_SHAPER_LUT_WRITE_SEL;\ + type MPCC_MCM_SHAPER_CONFIG_STATUS;\ + type MPCC_MCM_SHAPER_RAMA_EXP_REGION_START_B;\ + type MPCC_MCM_SHAPER_RAMA_EXP_REGION_START_SEGMENT_B;\ + type MPCC_MCM_SHAPER_RAMA_EXP_REGION_END_B;\ + type MPCC_MCM_SHAPER_RAMA_EXP_REGION_END_BASE_B;\ + type MPCC_MCM_SHAPER_RAMA_EXP_REGION0_LUT_OFFSET;\ + type MPCC_MCM_SHAPER_RAMA_EXP_REGION0_NUM_SEGMENTS;\ + type MPCC_MCM_SHAPER_RAMA_EXP_REGION1_LUT_OFFSET;\ + type MPCC_MCM_SHAPER_RAMA_EXP_REGION1_NUM_SEGMENTS; \ + type MPCC_MCM_1DLUT_MODE;\ + type MPCC_MCM_1DLUT_SELECT;\ + type MPCC_MCM_1DLUT_PWL_DISABLE;\ + type MPCC_MCM_1DLUT_MODE_CURRENT;\ + type MPCC_MCM_1DLUT_SELECT_CURRENT;\ + type MPCC_MCM_1DLUT_LUT_INDEX;\ + type MPCC_MCM_1DLUT_LUT_DATA;\ + type MPCC_MCM_1DLUT_LUT_WRITE_COLOR_MASK;\ + type MPCC_MCM_1DLUT_LUT_READ_COLOR_SEL;\ + type MPCC_MCM_1DLUT_LUT_READ_DBG;\ + type MPCC_MCM_1DLUT_LUT_HOST_SEL;\ + type MPCC_MCM_1DLUT_LUT_CONFIG_MODE;\ + type MPCC_MCM_1DLUT_RAMA_EXP_REGION_START_B;\ + type MPCC_MCM_1DLUT_RAMA_EXP_REGION_START_SEGMENT_B;\ + type MPCC_MCM_1DLUT_RAMA_EXP_REGION_START_SLOPE_B;\ + type MPCC_MCM_1DLUT_RAMA_EXP_REGION_START_BASE_B;\ + type MPCC_MCM_1DLUT_RAMA_EXP_REGION_END_BASE_B;\ + type MPCC_MCM_1DLUT_RAMA_EXP_REGION_END_B;\ + type MPCC_MCM_1DLUT_RAMA_EXP_REGION_END_SLOPE_B;\ + type MPCC_MCM_1DLUT_RAMA_OFFSET_B;\ + type MPCC_MCM_1DLUT_RAMA_OFFSET_G;\ + type MPCC_MCM_1DLUT_RAMA_OFFSET_R;\ + type MPCC_MCM_1DLUT_RAMA_EXP_REGION0_LUT_OFFSET;\ + type MPCC_MCM_1DLUT_RAMA_EXP_REGION0_NUM_SEGMENTS;\ + type MPCC_MCM_1DLUT_RAMA_EXP_REGION1_LUT_OFFSET;\ + type MPCC_MCM_1DLUT_RAMA_EXP_REGION1_NUM_SEGMENTS + + +#define MPC_COMMON_MASK_SH_LIST_DCN303(mask_sh) \ + MPC_COMMON_MASK_SH_LIST_DCN1_0(mask_sh),\ + SF(MPCC0_MPCC_CONTROL, MPCC_BG_BPC, mask_sh),\ + SF(MPCC0_MPCC_CONTROL, MPCC_BOT_GAIN_MODE, mask_sh),\ + SF(MPCC0_MPCC_TOP_GAIN, MPCC_TOP_GAIN, mask_sh),\ + SF(MPCC0_MPCC_BOT_GAIN_INSIDE, MPCC_BOT_GAIN_INSIDE, mask_sh),\ + SF(MPCC0_MPCC_BOT_GAIN_OUTSIDE, MPCC_BOT_GAIN_OUTSIDE, mask_sh),\ + SF(MPC_OUT0_CSC_MODE, MPC_OCSC_MODE, mask_sh),\ + SF(MPC_OUT0_CSC_C11_C12_A, MPC_OCSC_C11_A, mask_sh),\ + SF(MPC_OUT0_CSC_C11_C12_A, MPC_OCSC_C12_A, mask_sh),\ + SF(MPCC0_MPCC_STATUS, MPCC_DISABLED, mask_sh),\ + SF(MPCC0_MPCC_MEM_PWR_CTRL, MPCC_OGAM_MEM_PWR_FORCE, mask_sh),\ + SF(MPCC0_MPCC_MEM_PWR_CTRL, MPCC_OGAM_MEM_PWR_DIS, mask_sh),\ + SF(MPCC0_MPCC_MEM_PWR_CTRL, MPCC_OGAM_MEM_LOW_PWR_MODE, mask_sh),\ + SF(MPCC0_MPCC_MEM_PWR_CTRL, MPCC_OGAM_MEM_PWR_STATE, mask_sh),\ + SF(MPC_OUT0_DENORM_CONTROL, MPC_OUT_DENORM_MODE, mask_sh),\ + SF(MPC_OUT0_DENORM_CONTROL, MPC_OUT_DENORM_CLAMP_MAX_R_CR, mask_sh),\ + SF(MPC_OUT0_DENORM_CONTROL, MPC_OUT_DENORM_CLAMP_MIN_R_CR, mask_sh),\ + SF(MPC_OUT0_DENORM_CLAMP_G_Y, MPC_OUT_DENORM_CLAMP_MAX_G_Y, mask_sh),\ + SF(MPC_OUT0_DENORM_CLAMP_G_Y, MPC_OUT_DENORM_CLAMP_MIN_G_Y, mask_sh),\ + SF(MPC_OUT0_DENORM_CLAMP_B_CB, MPC_OUT_DENORM_CLAMP_MAX_B_CB, mask_sh),\ + SF(MPC_OUT0_DENORM_CLAMP_B_CB, MPC_OUT_DENORM_CLAMP_MIN_B_CB, mask_sh),\ + SF(MPCC_OGAM0_MPCC_GAMUT_REMAP_MODE, MPCC_GAMUT_REMAP_MODE, mask_sh),\ + SF(MPCC_OGAM0_MPCC_GAMUT_REMAP_MODE, MPCC_GAMUT_REMAP_MODE_CURRENT, mask_sh),\ + SF(MPCC_OGAM0_MPCC_GAMUT_REMAP_COEF_FORMAT, MPCC_GAMUT_REMAP_COEF_FORMAT, mask_sh),\ + SF(MPCC_OGAM0_MPC_GAMUT_REMAP_C11_C12_A, MPCC_GAMUT_REMAP_C11_A, mask_sh),\ + SF(MPCC_OGAM0_MPC_GAMUT_REMAP_C11_C12_A, MPCC_GAMUT_REMAP_C12_A, mask_sh),\ + SF(MPC_DWB0_MUX, MPC_DWB0_MUX, mask_sh),\ + SF(MPC_DWB0_MUX, MPC_DWB0_MUX_STATUS, mask_sh),\ + SF(MPC_OUT0_MUX, MPC_OUT_RATE_CONTROL, mask_sh),\ + SF(MPC_OUT0_MUX, MPC_OUT_RATE_CONTROL_DISABLE, mask_sh),\ + SF(MPC_OUT0_MUX, MPC_OUT_FLOW_CONTROL_MODE, mask_sh),\ + SF(MPC_OUT0_MUX, MPC_OUT_FLOW_CONTROL_COUNT, mask_sh), \ + SF(MPC_RMU_CONTROL, MPC_RMU0_MUX, mask_sh), \ + SF(MPC_RMU_CONTROL, MPC_RMU0_MUX_STATUS, mask_sh), \ + SF(MPCC_OGAM0_MPCC_OGAM_RAMA_REGION_0_1, MPCC_OGAM_RAMA_EXP_REGION0_LUT_OFFSET, mask_sh),\ + SF(MPCC_OGAM0_MPCC_OGAM_RAMA_REGION_0_1, MPCC_OGAM_RAMA_EXP_REGION0_NUM_SEGMENTS, mask_sh),\ + SF(MPCC_OGAM0_MPCC_OGAM_RAMA_REGION_0_1, MPCC_OGAM_RAMA_EXP_REGION1_LUT_OFFSET, mask_sh),\ + SF(MPCC_OGAM0_MPCC_OGAM_RAMA_REGION_0_1, MPCC_OGAM_RAMA_EXP_REGION1_NUM_SEGMENTS, mask_sh),\ + SF(MPCC_OGAM0_MPCC_OGAM_RAMA_END_CNTL2_B, MPCC_OGAM_RAMA_EXP_REGION_END_SLOPE_B, mask_sh),\ + SF(MPCC_OGAM0_MPCC_OGAM_RAMA_END_CNTL2_B, MPCC_OGAM_RAMA_EXP_REGION_END_B, mask_sh),\ + SF(MPCC_OGAM0_MPCC_OGAM_RAMA_END_CNTL1_B, MPCC_OGAM_RAMA_EXP_REGION_END_BASE_B, mask_sh),\ + SF(MPCC_OGAM0_MPCC_OGAM_RAMA_START_SLOPE_CNTL_B, MPCC_OGAM_RAMA_EXP_REGION_START_SLOPE_B, mask_sh),\ + SF(MPCC_OGAM0_MPCC_OGAM_RAMA_START_BASE_CNTL_B, MPCC_OGAM_RAMA_EXP_REGION_START_BASE_B, mask_sh),\ + SF(MPCC_OGAM0_MPCC_OGAM_RAMA_START_CNTL_B, MPCC_OGAM_RAMA_EXP_REGION_START_B, mask_sh),\ + SF(MPCC_OGAM0_MPCC_OGAM_RAMA_START_CNTL_B, MPCC_OGAM_RAMA_EXP_REGION_START_SEGMENT_B, mask_sh),\ + SF(MPCC_OGAM0_MPCC_OGAM_RAMA_OFFSET_B, MPCC_OGAM_RAMA_OFFSET_B, mask_sh),\ + SF(MPCC_OGAM0_MPCC_OGAM_RAMA_OFFSET_G, MPCC_OGAM_RAMA_OFFSET_G, mask_sh),\ + SF(MPCC_OGAM0_MPCC_OGAM_RAMA_OFFSET_R, MPCC_OGAM_RAMA_OFFSET_R, mask_sh),\ + SF(MPCC_OGAM0_MPCC_OGAM_LUT_INDEX, MPCC_OGAM_LUT_INDEX, mask_sh),\ + SF(MPCC_OGAM0_MPCC_OGAM_CONTROL, MPCC_OGAM_MODE, mask_sh),\ + SF(MPCC_OGAM0_MPCC_OGAM_CONTROL, MPCC_OGAM_SELECT, mask_sh),\ + SF(MPCC_OGAM0_MPCC_OGAM_CONTROL, MPCC_OGAM_PWL_DISABLE, mask_sh),\ + SF(MPCC_OGAM0_MPCC_OGAM_CONTROL, MPCC_OGAM_MODE_CURRENT, mask_sh),\ + SF(MPCC_OGAM0_MPCC_OGAM_CONTROL, MPCC_OGAM_SELECT_CURRENT, mask_sh),\ + SF(MPCC_OGAM0_MPCC_OGAM_LUT_CONTROL, MPCC_OGAM_LUT_WRITE_COLOR_MASK, mask_sh),\ + SF(MPCC_OGAM0_MPCC_OGAM_LUT_CONTROL, MPCC_OGAM_LUT_READ_COLOR_SEL, mask_sh),\ + SF(MPCC_OGAM0_MPCC_OGAM_LUT_CONTROL, MPCC_OGAM_LUT_READ_DBG, mask_sh),\ + SF(MPCC_OGAM0_MPCC_OGAM_LUT_CONTROL, MPCC_OGAM_LUT_HOST_SEL, mask_sh),\ + SF(MPCC_OGAM0_MPCC_OGAM_LUT_CONTROL, MPCC_OGAM_LUT_CONFIG_MODE, mask_sh),\ + /*SF(MPCC_OGAM0_MPCC_OGAM_LUT_CONTROL, MPCC_OGAM_LUT_STATUS, mask_sh),*/\ + SF(MPCC_OGAM0_MPCC_OGAM_LUT_DATA, MPCC_OGAM_LUT_DATA, mask_sh),\ + SF(MPC_RMU0_3DLUT_MODE, MPC_RMU_3DLUT_MODE, mask_sh),\ + SF(MPC_RMU0_3DLUT_MODE, MPC_RMU_3DLUT_SIZE, mask_sh),\ + /*SF(MPC_RMU0_3DLUT_MODE, MPC_RMU_3DLUT_MODE_CURRENT, mask_sh),*/\ + SF(MPC_RMU0_3DLUT_READ_WRITE_CONTROL, MPC_RMU_3DLUT_WRITE_EN_MASK, mask_sh),\ + SF(MPC_RMU0_3DLUT_READ_WRITE_CONTROL, MPC_RMU_3DLUT_RAM_SEL, mask_sh),\ + SF(MPC_RMU0_3DLUT_READ_WRITE_CONTROL, MPC_RMU_3DLUT_30BIT_EN, mask_sh),\ + /*SF(MPC_RMU0_3DLUT_READ_WRITE_CONTROL, MPC_RMU_3DLUT_CONFIG_STATUS, mask_sh),*/\ + SF(MPC_RMU0_3DLUT_READ_WRITE_CONTROL, MPC_RMU_3DLUT_READ_SEL, mask_sh),\ + SF(MPC_RMU0_3DLUT_INDEX, MPC_RMU_3DLUT_INDEX, mask_sh),\ + SF(MPC_RMU0_3DLUT_DATA, MPC_RMU_3DLUT_DATA0, mask_sh),\ + SF(MPC_RMU0_3DLUT_DATA, MPC_RMU_3DLUT_DATA1, mask_sh),\ + SF(MPC_RMU0_3DLUT_DATA_30BIT, MPC_RMU_3DLUT_DATA_30BIT, mask_sh),\ + SF(MPC_RMU0_SHAPER_CONTROL, MPC_RMU_SHAPER_LUT_MODE, mask_sh),\ + /*SF(MPC_RMU0_SHAPER_CONTROL, MPC_RMU_SHAPER_LUT_MODE_CURRENT, mask_sh),*/\ + SF(MPC_RMU0_SHAPER_OFFSET_R, MPC_RMU_SHAPER_OFFSET_R, mask_sh),\ + SF(MPC_RMU0_SHAPER_OFFSET_G, MPC_RMU_SHAPER_OFFSET_G, mask_sh),\ + SF(MPC_RMU0_SHAPER_OFFSET_B, MPC_RMU_SHAPER_OFFSET_B, mask_sh),\ + SF(MPC_RMU0_SHAPER_SCALE_R, MPC_RMU_SHAPER_SCALE_R, mask_sh),\ + SF(MPC_RMU0_SHAPER_SCALE_G_B, MPC_RMU_SHAPER_SCALE_G, mask_sh),\ + SF(MPC_RMU0_SHAPER_SCALE_G_B, MPC_RMU_SHAPER_SCALE_B, mask_sh),\ + SF(MPC_RMU0_SHAPER_LUT_INDEX, MPC_RMU_SHAPER_LUT_INDEX, mask_sh),\ + SF(MPC_RMU0_SHAPER_LUT_DATA, MPC_RMU_SHAPER_LUT_DATA, mask_sh),\ + SF(MPC_RMU0_SHAPER_LUT_WRITE_EN_MASK, MPC_RMU_SHAPER_LUT_WRITE_EN_MASK, mask_sh),\ + SF(MPC_RMU0_SHAPER_LUT_WRITE_EN_MASK, MPC_RMU_SHAPER_LUT_WRITE_SEL, mask_sh),\ + /*SF(MPC_RMU0_SHAPER_LUT_WRITE_EN_MASK, MPC_RMU_SHAPER_CONFIG_STATUS, mask_sh),*/\ + SF(MPC_RMU0_SHAPER_RAMA_START_CNTL_B, MPC_RMU_SHAPER_RAMA_EXP_REGION_START_B, mask_sh),\ + SF(MPC_RMU0_SHAPER_RAMA_START_CNTL_B, MPC_RMU_SHAPER_RAMA_EXP_REGION_START_SEGMENT_B, mask_sh),\ + SF(MPC_RMU0_SHAPER_RAMA_END_CNTL_B, MPC_RMU_SHAPER_RAMA_EXP_REGION_END_B, mask_sh),\ + SF(MPC_RMU0_SHAPER_RAMA_END_CNTL_B, MPC_RMU_SHAPER_RAMA_EXP_REGION_END_BASE_B, mask_sh),\ + SF(MPC_RMU0_SHAPER_RAMA_REGION_0_1, MPC_RMU_SHAPER_RAMA_EXP_REGION0_LUT_OFFSET, mask_sh),\ + SF(MPC_RMU0_SHAPER_RAMA_REGION_0_1, MPC_RMU_SHAPER_RAMA_EXP_REGION0_NUM_SEGMENTS, mask_sh),\ + SF(MPC_RMU0_SHAPER_RAMA_REGION_0_1, MPC_RMU_SHAPER_RAMA_EXP_REGION1_LUT_OFFSET, mask_sh),\ + SF(MPC_RMU0_SHAPER_RAMA_REGION_0_1, MPC_RMU_SHAPER_RAMA_EXP_REGION1_NUM_SEGMENTS, mask_sh),\ + SF(MPC_RMU_MEM_PWR_CTRL, MPC_RMU0_MEM_PWR_FORCE, mask_sh),\ + SF(MPC_RMU_MEM_PWR_CTRL, MPC_RMU0_MEM_PWR_DIS, mask_sh),\ + SF(MPC_RMU_MEM_PWR_CTRL, MPC_RMU0_SHAPER_MEM_PWR_STATE, mask_sh),\ + SF(MPC_RMU_MEM_PWR_CTRL, MPC_RMU0_3DLUT_MEM_PWR_STATE, mask_sh),\ + SF(MPC_RMU_MEM_PWR_CTRL, MPC_RMU0_MEM_LOW_PWR_MODE, mask_sh),\ + SF(MPC_RMU0_SHAPER_CONTROL, MPC_RMU_SHAPER_MODE_CURRENT, mask_sh),\ + SF(CUR_VUPDATE_LOCK_SET0, CUR_VUPDATE_LOCK_SET, mask_sh) + +#define MPC_REG_FIELD_LIST_DCN3_03(type) \ + MPC_REG_FIELD_LIST_DCN2_0(type) \ + type MPC_DWB0_MUX;\ + type MPC_DWB0_MUX_STATUS;\ + type MPC_OUT_RATE_CONTROL;\ + type MPC_OUT_RATE_CONTROL_DISABLE;\ + type MPC_OUT_FLOW_CONTROL_MODE;\ + type MPC_OUT_FLOW_CONTROL_COUNT; \ + type MPCC_GAMUT_REMAP_MODE; \ + type MPCC_GAMUT_REMAP_MODE_CURRENT;\ + type MPCC_GAMUT_REMAP_COEF_FORMAT; \ + type MPCC_GAMUT_REMAP_C11_A; \ + type MPCC_GAMUT_REMAP_C12_A; \ + type MPC_RMU0_MUX; \ + type MPC_RMU0_MUX_STATUS; \ + type MPC_RMU0_MEM_PWR_FORCE;\ + type MPC_RMU0_MEM_PWR_DIS;\ + type MPC_RMU0_MEM_LOW_PWR_MODE;\ + type MPC_RMU0_SHAPER_MEM_PWR_STATE;\ + type MPC_RMU0_3DLUT_MEM_PWR_STATE;\ + type MPCC_OGAM_RAMA_EXP_REGION_START_SLOPE_B; \ + type MPCC_OGAM_RAMA_EXP_REGION_START_BASE_B;\ + type MPCC_OGAM_RAMA_OFFSET_B;\ + type MPCC_OGAM_RAMA_OFFSET_G;\ + type MPCC_OGAM_RAMA_OFFSET_R;\ + type MPCC_OGAM_SELECT; \ + type MPCC_OGAM_PWL_DISABLE; \ + type MPCC_OGAM_MODE_CURRENT; \ + type MPCC_OGAM_SELECT_CURRENT; \ + type MPCC_OGAM_LUT_WRITE_COLOR_MASK; \ + type MPCC_OGAM_LUT_READ_COLOR_SEL; \ + type MPCC_OGAM_LUT_READ_DBG; \ + type MPCC_OGAM_LUT_HOST_SEL; \ + type MPCC_OGAM_LUT_CONFIG_MODE; \ + type MPCC_OGAM_LUT_STATUS; \ + type MPCC_OGAM_RAMA_START_BASE_CNTL_B;\ + type MPCC_OGAM_MEM_LOW_PWR_MODE;\ + type MPCC_OGAM_MEM_PWR_STATE;\ + type MPC_RMU_3DLUT_MODE; \ + type MPC_RMU_3DLUT_SIZE; \ + type MPC_RMU_3DLUT_MODE_CURRENT; \ + type MPC_RMU_3DLUT_WRITE_EN_MASK;\ + type MPC_RMU_3DLUT_RAM_SEL;\ + type MPC_RMU_3DLUT_30BIT_EN;\ + type MPC_RMU_3DLUT_CONFIG_STATUS;\ + type MPC_RMU_3DLUT_READ_SEL;\ + type MPC_RMU_3DLUT_INDEX;\ + type MPC_RMU_3DLUT_DATA0;\ + type MPC_RMU_3DLUT_DATA1;\ + type MPC_RMU_3DLUT_DATA_30BIT;\ + type MPC_RMU_SHAPER_LUT_MODE;\ + type MPC_RMU_SHAPER_LUT_MODE_CURRENT;\ + type MPC_RMU_SHAPER_OFFSET_R;\ + type MPC_RMU_SHAPER_OFFSET_G;\ + type MPC_RMU_SHAPER_OFFSET_B;\ + type MPC_RMU_SHAPER_SCALE_R;\ + type MPC_RMU_SHAPER_SCALE_G;\ + type MPC_RMU_SHAPER_SCALE_B;\ + type MPC_RMU_SHAPER_LUT_INDEX;\ + type MPC_RMU_SHAPER_LUT_DATA;\ + type MPC_RMU_SHAPER_LUT_WRITE_EN_MASK;\ + type MPC_RMU_SHAPER_LUT_WRITE_SEL;\ + type MPC_RMU_SHAPER_CONFIG_STATUS;\ + type MPC_RMU_SHAPER_RAMA_EXP_REGION_START_B;\ + type MPC_RMU_SHAPER_RAMA_EXP_REGION_START_SEGMENT_B;\ + type MPC_RMU_SHAPER_RAMA_EXP_REGION_END_B;\ + type MPC_RMU_SHAPER_RAMA_EXP_REGION_END_BASE_B;\ + type MPC_RMU_SHAPER_RAMA_EXP_REGION0_LUT_OFFSET;\ + type MPC_RMU_SHAPER_RAMA_EXP_REGION0_NUM_SEGMENTS;\ + type MPC_RMU_SHAPER_RAMA_EXP_REGION1_LUT_OFFSET;\ + type MPC_RMU_SHAPER_RAMA_EXP_REGION1_NUM_SEGMENTS;\ + type MPC_RMU_SHAPER_MODE_CURRENT + +struct dcn30_mpc_registers { + MPC_REG_VARIABLE_LIST_DCN3_0; + MPC_REG_VARIABLE_LIST_DCN32; +}; + +struct dcn30_mpc_shift { + MPC_REG_FIELD_LIST_DCN3_0(uint8_t); + MPC_REG_FIELD_LIST_DCN32(uint8_t); +}; + +struct dcn30_mpc_mask { + MPC_REG_FIELD_LIST_DCN3_0(uint32_t); + MPC_REG_FIELD_LIST_DCN32(uint32_t); +}; + +struct dcn30_mpc { + struct mpc base; + + int mpcc_in_use_mask; + int num_mpcc; + const struct dcn30_mpc_registers *mpc_regs; + const struct dcn30_mpc_shift *mpc_shift; + const struct dcn30_mpc_mask *mpc_mask; + int num_rmu; +}; + +void dcn30_mpc_construct(struct dcn30_mpc *mpc30, + struct dc_context *ctx, + const struct dcn30_mpc_registers *mpc_regs, + const struct dcn30_mpc_shift *mpc_shift, + const struct dcn30_mpc_mask *mpc_mask, + int num_mpcc, + int num_rmu); + +bool mpc3_program_shaper( + struct mpc *mpc, + const struct pwl_params *params, + uint32_t rmu_idx); + +bool mpc3_program_3dlut( + struct mpc *mpc, + const struct tetrahedral_params *params, + int rmu_idx); + +uint32_t mpcc3_acquire_rmu(struct mpc *mpc, + int mpcc_id, int rmu_idx); + +void mpc3_set_denorm( + struct mpc *mpc, + int opp_id, + enum dc_color_depth output_depth); + +void mpc3_set_denorm_clamp( + struct mpc *mpc, + int opp_id, + struct mpc_denorm_clamp denorm_clamp); + +void mpc3_set_output_csc( + struct mpc *mpc, + int opp_id, + const uint16_t *regval, + enum mpc_output_csc_mode ocsc_mode); + +void mpc3_set_ocsc_default( + struct mpc *mpc, + int opp_id, + enum dc_color_space color_space, + enum mpc_output_csc_mode ocsc_mode); + +void mpc3_set_output_gamma( + struct mpc *mpc, + int mpcc_id, + const struct pwl_params *params); + +uint32_t mpc3_get_rmu_mux_status( + struct mpc *mpc, + int rmu_idx); + +void mpc3_set_gamut_remap( + struct mpc *mpc, + int mpcc_id, + const struct mpc_grph_gamut_adjustment *adjust); + +void mpc3_set_rmu_mux( + struct mpc *mpc, + int rmu_idx, + int value); + +void mpc3_set_dwb_mux( + struct mpc *mpc, + int dwb_id, + int mpcc_id); + +void mpc3_disable_dwb_mux( + struct mpc *mpc, + int dwb_id); + +bool mpc3_is_dwb_idle( + struct mpc *mpc, + int dwb_id); + +void mpc3_set_out_rate_control( + struct mpc *mpc, + int opp_id, + bool enable, + bool rate_2x_mode, + struct mpc_dwb_flow_control *flow_control); + +void mpc3_power_on_ogam_lut( + struct mpc *mpc, int mpcc_id, + bool power_on); + +void mpc3_init_mpcc(struct mpcc *mpcc, int mpcc_inst); + +enum dc_lut_mode mpc3_get_ogam_current( + struct mpc *mpc, + int mpcc_id); + +#endif diff --git a/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_opp.h b/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_opp.h new file mode 100644 index 000000000..78f7cf772 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_opp.h @@ -0,0 +1,36 @@ +/* Copyright 2020 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_DCN30_H__ +#define __DC_OPP_DCN30_H__ + +#include "dcn20/dcn20_opp.h" + + +#define OPP_REG_LIST_DCN30(id) \ + OPP_REG_LIST_DCN10(id), \ + OPP_DPG_REG_LIST(id), \ + SRI(FMT_422_CONTROL, FMT, id) + +#endif diff --git a/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_optc.c b/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_optc.c new file mode 100644 index 000000000..94894fd6c --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_optc.c @@ -0,0 +1,382 @@ +/* + * Copyright 2020 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 "reg_helper.h" +#include "dcn30_optc.h" +#include "dc.h" +#include "dcn_calc_math.h" +#include "dc_dmub_srv.h" + +#include "dml/dcn30/dcn30_fpu.h" + +#define REG(reg)\ + optc1->tg_regs->reg + +#define CTX \ + optc1->base.ctx + +#undef FN +#define FN(reg_name, field_name) \ + optc1->tg_shift->field_name, optc1->tg_mask->field_name + +void optc3_triplebuffer_lock(struct timing_generator *optc) +{ + struct optc *optc1 = DCN10TG_FROM_TG(optc); + + REG_UPDATE(OTG_GLOBAL_CONTROL2, + OTG_MASTER_UPDATE_LOCK_SEL, optc->inst); + + REG_SET(OTG_VUPDATE_KEEPOUT, 0, + OTG_MASTER_UPDATE_LOCK_VUPDATE_KEEPOUT_EN, 1); + + REG_SET(OTG_MASTER_UPDATE_LOCK, 0, + OTG_MASTER_UPDATE_LOCK, 1); + + if (optc->ctx->dce_environment != DCE_ENV_FPGA_MAXIMUS) + REG_WAIT(OTG_MASTER_UPDATE_LOCK, + UPDATE_LOCK_STATUS, 1, + 1, 10); +} + +void optc3_lock_doublebuffer_enable(struct timing_generator *optc) +{ + struct optc *optc1 = DCN10TG_FROM_TG(optc); + uint32_t v_blank_start = 0; + uint32_t v_blank_end = 0; + uint32_t h_blank_start = 0; + uint32_t h_blank_end = 0; + + REG_GET_2(OTG_V_BLANK_START_END, + OTG_V_BLANK_START, &v_blank_start, + OTG_V_BLANK_END, &v_blank_end); + REG_GET_2(OTG_H_BLANK_START_END, + OTG_H_BLANK_START, &h_blank_start, + OTG_H_BLANK_END, &h_blank_end); + + REG_UPDATE_2(OTG_GLOBAL_CONTROL1, + MASTER_UPDATE_LOCK_DB_START_Y, v_blank_start - 1, + MASTER_UPDATE_LOCK_DB_END_Y, v_blank_start); + REG_UPDATE_2(OTG_GLOBAL_CONTROL4, + DIG_UPDATE_POSITION_X, h_blank_start - 180 - 1, + DIG_UPDATE_POSITION_Y, v_blank_start - 1); + // there is a DIG_UPDATE_VCOUNT_MODE and it is 0. + + REG_UPDATE_3(OTG_GLOBAL_CONTROL0, + MASTER_UPDATE_LOCK_DB_START_X, h_blank_start - 200 - 1, + MASTER_UPDATE_LOCK_DB_END_X, h_blank_start - 180, + MASTER_UPDATE_LOCK_DB_EN, 1); + REG_UPDATE(OTG_GLOBAL_CONTROL2, GLOBAL_UPDATE_LOCK_EN, 1); + + REG_SET_3(OTG_VUPDATE_KEEPOUT, 0, + MASTER_UPDATE_LOCK_VUPDATE_KEEPOUT_START_OFFSET, 0, + MASTER_UPDATE_LOCK_VUPDATE_KEEPOUT_END_OFFSET, 100, + OTG_MASTER_UPDATE_LOCK_VUPDATE_KEEPOUT_EN, 1); +} + +void optc3_lock_doublebuffer_disable(struct timing_generator *optc) +{ + struct optc *optc1 = DCN10TG_FROM_TG(optc); + + REG_UPDATE_2(OTG_GLOBAL_CONTROL0, + MASTER_UPDATE_LOCK_DB_START_X, 0, + MASTER_UPDATE_LOCK_DB_END_X, 0); + REG_UPDATE_2(OTG_GLOBAL_CONTROL1, + MASTER_UPDATE_LOCK_DB_START_Y, 0, + MASTER_UPDATE_LOCK_DB_END_Y, 0); + + REG_UPDATE(OTG_GLOBAL_CONTROL2, GLOBAL_UPDATE_LOCK_EN, 0); + REG_UPDATE(OTG_GLOBAL_CONTROL0, MASTER_UPDATE_LOCK_DB_EN, 0); +} + +void optc3_lock(struct timing_generator *optc) +{ + struct optc *optc1 = DCN10TG_FROM_TG(optc); + + REG_UPDATE(OTG_GLOBAL_CONTROL2, + OTG_MASTER_UPDATE_LOCK_SEL, optc->inst); + REG_SET(OTG_MASTER_UPDATE_LOCK, 0, + OTG_MASTER_UPDATE_LOCK, 1); + + REG_WAIT(OTG_MASTER_UPDATE_LOCK, + UPDATE_LOCK_STATUS, 1, + 1, 10); +} + +void optc3_set_out_mux(struct timing_generator *optc, enum otg_out_mux_dest dest) +{ + struct optc *optc1 = DCN10TG_FROM_TG(optc); + + REG_UPDATE(OTG_CONTROL, OTG_OUT_MUX, dest); +} + +void optc3_program_blank_color(struct timing_generator *optc, + const struct tg_color *blank_color) +{ + struct optc *optc1 = DCN10TG_FROM_TG(optc); + + REG_SET_3(OTG_BLANK_DATA_COLOR, 0, + OTG_BLANK_DATA_COLOR_BLUE_CB, blank_color->color_b_cb, + OTG_BLANK_DATA_COLOR_GREEN_Y, blank_color->color_g_y, + OTG_BLANK_DATA_COLOR_RED_CR, blank_color->color_r_cr); + + REG_SET_3(OTG_BLANK_DATA_COLOR_EXT, 0, + OTG_BLANK_DATA_COLOR_BLUE_CB_EXT, blank_color->color_b_cb >> 10, + OTG_BLANK_DATA_COLOR_GREEN_Y_EXT, blank_color->color_g_y >> 10, + OTG_BLANK_DATA_COLOR_RED_CR_EXT, blank_color->color_r_cr >> 10); +} + +void optc3_set_drr_trigger_window(struct timing_generator *optc, + uint32_t window_start, uint32_t window_end) +{ + struct optc *optc1 = DCN10TG_FROM_TG(optc); + + REG_SET_2(OTG_DRR_TRIGGER_WINDOW, 0, + OTG_DRR_TRIGGER_WINDOW_START_X, window_start, + OTG_DRR_TRIGGER_WINDOW_END_X, window_end); +} + +void optc3_set_vtotal_change_limit(struct timing_generator *optc, + uint32_t limit) +{ + struct optc *optc1 = DCN10TG_FROM_TG(optc); + + + REG_SET(OTG_DRR_V_TOTAL_CHANGE, 0, + OTG_DRR_V_TOTAL_CHANGE_LIMIT, limit); +} + + +/* Set DSC-related configuration. + * dsc_mode: 0 disables DSC, other values enable DSC in specified format + * sc_bytes_per_pixel: Bytes per pixel in u3.28 format + * dsc_slice_width: Slice width in pixels + */ +void optc3_set_dsc_config(struct timing_generator *optc, + enum optc_dsc_mode dsc_mode, + uint32_t dsc_bytes_per_pixel, + uint32_t dsc_slice_width) +{ + struct optc *optc1 = DCN10TG_FROM_TG(optc); + + optc2_set_dsc_config(optc, dsc_mode, dsc_bytes_per_pixel, dsc_slice_width); + REG_UPDATE(OTG_V_SYNC_A_CNTL, OTG_V_SYNC_MODE, 0); +} + +void optc3_set_odm_bypass(struct timing_generator *optc, + const struct dc_crtc_timing *dc_crtc_timing) +{ + struct optc *optc1 = DCN10TG_FROM_TG(optc); + enum h_timing_div_mode h_div = H_TIMING_NO_DIV; + + REG_SET_5(OPTC_DATA_SOURCE_SELECT, 0, + OPTC_NUM_OF_INPUT_SEGMENT, 0, + OPTC_SEG0_SRC_SEL, optc->inst, + OPTC_SEG1_SRC_SEL, 0xf, + OPTC_SEG2_SRC_SEL, 0xf, + OPTC_SEG3_SRC_SEL, 0xf + ); + + h_div = optc1_is_two_pixels_per_containter(dc_crtc_timing); + REG_SET(OTG_H_TIMING_CNTL, 0, + OTG_H_TIMING_DIV_MODE, h_div); + + REG_SET(OPTC_MEMORY_CONFIG, 0, + OPTC_MEM_SEL, 0); + optc1->opp_count = 1; +} + +static void optc3_set_odm_combine(struct timing_generator *optc, int *opp_id, int opp_cnt, + struct dc_crtc_timing *timing) +{ + struct optc *optc1 = DCN10TG_FROM_TG(optc); + int mpcc_hactive = (timing->h_addressable + timing->h_border_left + timing->h_border_right) + / opp_cnt; + uint32_t memory_mask = 0; + + /* TODO: In pseudocode but does not affect maximus, delete comment if we dont need on asic + * REG_SET(OTG_GLOBAL_CONTROL2, 0, GLOBAL_UPDATE_LOCK_EN, 1); + * Program OTG register MASTER_UPDATE_LOCK_DB_X/Y to the position before DP frame start + * REG_SET_2(OTG_GLOBAL_CONTROL1, 0, + * MASTER_UPDATE_LOCK_DB_X, 160, + * MASTER_UPDATE_LOCK_DB_Y, 240); + */ + + ASSERT(opp_cnt == 2 || opp_cnt == 4); + + /* 2 pieces of memory required for up to 5120 displays, 4 for up to 8192, + * however, for ODM combine we can simplify by always using 4. + */ + if (opp_cnt == 2) { + /* To make sure there's no memory overlap, each instance "reserves" 2 + * memories and they are uniquely combined here. + */ + memory_mask = 0x3 << (opp_id[0] * 2) | 0x3 << (opp_id[1] * 2); + } else if (opp_cnt == 4) { + /* To make sure there's no memory overlap, each instance "reserves" 1 + * memory and they are uniquely combined here. + */ + memory_mask = 0x1 << (opp_id[0] * 2) | 0x1 << (opp_id[1] * 2) | 0x1 << (opp_id[2] * 2) | 0x1 << (opp_id[3] * 2); + } + + if (REG(OPTC_MEMORY_CONFIG)) + REG_SET(OPTC_MEMORY_CONFIG, 0, + OPTC_MEM_SEL, memory_mask); + + if (opp_cnt == 2) { + REG_SET_3(OPTC_DATA_SOURCE_SELECT, 0, + OPTC_NUM_OF_INPUT_SEGMENT, 1, + OPTC_SEG0_SRC_SEL, opp_id[0], + OPTC_SEG1_SRC_SEL, opp_id[1]); + } else if (opp_cnt == 4) { + REG_SET_5(OPTC_DATA_SOURCE_SELECT, 0, + OPTC_NUM_OF_INPUT_SEGMENT, 3, + OPTC_SEG0_SRC_SEL, opp_id[0], + OPTC_SEG1_SRC_SEL, opp_id[1], + OPTC_SEG2_SRC_SEL, opp_id[2], + OPTC_SEG3_SRC_SEL, opp_id[3]); + } + + REG_UPDATE(OPTC_WIDTH_CONTROL, + OPTC_SEGMENT_WIDTH, mpcc_hactive); + + REG_SET(OTG_H_TIMING_CNTL, 0, OTG_H_TIMING_DIV_MODE, opp_cnt - 1); + optc1->opp_count = opp_cnt; +} + +/** + * optc3_set_timing_double_buffer() - DRR double buffering control + * + * Sets double buffer point for V_TOTAL, H_TOTAL, VTOTAL_MIN, + * VTOTAL_MAX, VTOTAL_MIN_SEL and VTOTAL_MAX_SEL registers. + * + * Options: any time, start of frame, dp start of frame (range timing) + */ +static void optc3_set_timing_double_buffer(struct timing_generator *optc, bool enable) +{ + struct optc *optc1 = DCN10TG_FROM_TG(optc); + uint32_t mode = enable ? 2 : 0; + + REG_UPDATE(OTG_DOUBLE_BUFFER_CONTROL, + OTG_DRR_TIMING_DBUF_UPDATE_MODE, mode); +} + +void optc3_wait_drr_doublebuffer_pending_clear(struct timing_generator *optc) +{ + struct optc *optc1 = DCN10TG_FROM_TG(optc); + + REG_WAIT(OTG_DOUBLE_BUFFER_CONTROL, OTG_DRR_TIMING_DBUF_UPDATE_PENDING, 0, 2, 100000); /* 1 vupdate at 5hz */ + +} + +void optc3_set_vtotal_min_max(struct timing_generator *optc, int vtotal_min, int vtotal_max) +{ + struct dc *dc = optc->ctx->dc; + + if (dc->caps.dmub_caps.mclk_sw && !dc->debug.disable_fams) + dc_dmub_srv_drr_update_cmd(dc, optc->inst, vtotal_min, vtotal_max); + else + optc1_set_vtotal_min_max(optc, vtotal_min, vtotal_max); +} + +void optc3_tg_init(struct timing_generator *optc) +{ + optc3_set_timing_double_buffer(optc, true); + optc1_clear_optc_underflow(optc); +} + +static struct timing_generator_funcs dcn30_tg_funcs = { + .validate_timing = optc1_validate_timing, + .program_timing = optc1_program_timing, + .setup_vertical_interrupt0 = optc1_setup_vertical_interrupt0, + .setup_vertical_interrupt1 = optc1_setup_vertical_interrupt1, + .setup_vertical_interrupt2 = optc1_setup_vertical_interrupt2, + .program_global_sync = optc1_program_global_sync, + .enable_crtc = optc2_enable_crtc, + .disable_crtc = optc1_disable_crtc, + /* used by enable_timing_synchronization. Not need for FPGA */ + .is_counter_moving = optc1_is_counter_moving, + .get_position = optc1_get_position, + .get_frame_count = optc1_get_vblank_counter, + .get_scanoutpos = optc1_get_crtc_scanoutpos, + .get_otg_active_size = optc1_get_otg_active_size, + .set_early_control = optc1_set_early_control, + /* used by enable_timing_synchronization. Not need for FPGA */ + .wait_for_state = optc1_wait_for_state, + .set_blank_color = optc3_program_blank_color, + .did_triggered_reset_occur = optc1_did_triggered_reset_occur, + .triplebuffer_lock = optc3_triplebuffer_lock, + .triplebuffer_unlock = optc2_triplebuffer_unlock, + .enable_reset_trigger = optc1_enable_reset_trigger, + .enable_crtc_reset = optc1_enable_crtc_reset, + .disable_reset_trigger = optc1_disable_reset_trigger, + .lock = optc3_lock, + .unlock = optc1_unlock, + .lock_doublebuffer_enable = optc3_lock_doublebuffer_enable, + .lock_doublebuffer_disable = optc3_lock_doublebuffer_disable, + .enable_optc_clock = optc1_enable_optc_clock, + .set_drr = optc1_set_drr, + .get_last_used_drr_vtotal = optc2_get_last_used_drr_vtotal, + .set_vtotal_min_max = optc3_set_vtotal_min_max, + .set_static_screen_control = optc1_set_static_screen_control, + .program_stereo = optc1_program_stereo, + .is_stereo_left_eye = optc1_is_stereo_left_eye, + .tg_init = optc3_tg_init, + .is_tg_enabled = optc1_is_tg_enabled, + .is_optc_underflow_occurred = optc1_is_optc_underflow_occurred, + .clear_optc_underflow = optc1_clear_optc_underflow, + .setup_global_swap_lock = NULL, + .get_crc = optc1_get_crc, + .configure_crc = optc2_configure_crc, + .set_dsc_config = optc3_set_dsc_config, + .get_dsc_status = optc2_get_dsc_status, + .set_dwb_source = NULL, + .set_odm_bypass = optc3_set_odm_bypass, + .set_odm_combine = optc3_set_odm_combine, + .get_optc_source = optc2_get_optc_source, + .set_out_mux = optc3_set_out_mux, + .set_drr_trigger_window = optc3_set_drr_trigger_window, + .set_vtotal_change_limit = optc3_set_vtotal_change_limit, + .set_gsl = optc2_set_gsl, + .set_gsl_source_select = optc2_set_gsl_source_select, + .set_vtg_params = optc1_set_vtg_params, + .program_manual_trigger = optc2_program_manual_trigger, + .setup_manual_trigger = optc2_setup_manual_trigger, + .get_hw_timing = optc1_get_hw_timing, + .wait_drr_doublebuffer_pending_clear = optc3_wait_drr_doublebuffer_pending_clear, +}; + +void dcn30_timing_generator_init(struct optc *optc1) +{ + optc1->base.funcs = &dcn30_tg_funcs; + + optc1->max_h_total = optc1->tg_mask->OTG_H_TOTAL + 1; + optc1->max_v_total = optc1->tg_mask->OTG_V_TOTAL + 1; + + optc1->min_h_blank = 32; + optc1->min_v_blank = 3; + optc1->min_v_blank_interlace = 5; + optc1->min_h_sync_width = 4; + optc1->min_v_sync_width = 1; +} diff --git a/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_optc.h b/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_optc.h new file mode 100644 index 000000000..fb06dc9a4 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_optc.h @@ -0,0 +1,356 @@ +/* + * Copyright 2020 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_OPTC_DCN30_H__ +#define __DC_OPTC_DCN30_H__ + +#include "dcn20/dcn20_optc.h" + +#define V_TOTAL_REGS_DCN30_SRI(inst) + +#define OPTC_COMMON_REG_LIST_DCN3_BASE(inst) \ + SRI(OTG_VSTARTUP_PARAM, OTG, inst),\ + SRI(OTG_VUPDATE_PARAM, OTG, inst),\ + SRI(OTG_VREADY_PARAM, OTG, inst),\ + SRI(OTG_MASTER_UPDATE_LOCK, OTG, inst),\ + SRI(OTG_GLOBAL_CONTROL0, OTG, inst),\ + SRI(OTG_GLOBAL_CONTROL1, OTG, inst),\ + SRI(OTG_GLOBAL_CONTROL2, OTG, inst),\ + SRI(OTG_GLOBAL_CONTROL4, OTG, inst),\ + SRI(OTG_DOUBLE_BUFFER_CONTROL, OTG, inst),\ + SRI(OTG_H_TOTAL, OTG, inst),\ + SRI(OTG_H_BLANK_START_END, OTG, inst),\ + SRI(OTG_H_SYNC_A, OTG, inst),\ + SRI(OTG_H_SYNC_A_CNTL, OTG, inst),\ + SRI(OTG_H_TIMING_CNTL, OTG, inst),\ + SRI(OTG_V_TOTAL, OTG, inst),\ + SRI(OTG_V_BLANK_START_END, OTG, inst),\ + SRI(OTG_V_SYNC_A, OTG, inst),\ + SRI(OTG_V_SYNC_A_CNTL, OTG, inst),\ + SRI(OTG_CONTROL, OTG, inst),\ + SRI(OTG_STEREO_CONTROL, OTG, inst),\ + SRI(OTG_3D_STRUCTURE_CONTROL, OTG, inst),\ + SRI(OTG_STEREO_STATUS, OTG, inst),\ + SRI(OTG_V_TOTAL_MAX, OTG, inst),\ + SRI(OTG_V_TOTAL_MIN, OTG, inst),\ + SRI(OTG_V_TOTAL_CONTROL, OTG, inst),\ + V_TOTAL_REGS_DCN30_SRI(inst)\ + SRI(OTG_TRIGA_CNTL, OTG, inst),\ + SRI(OTG_FORCE_COUNT_NOW_CNTL, OTG, inst),\ + SRI(OTG_STATIC_SCREEN_CONTROL, OTG, inst),\ + SRI(OTG_STATUS_FRAME_COUNT, OTG, inst),\ + SRI(OTG_STATUS, OTG, inst),\ + SRI(OTG_STATUS_POSITION, OTG, inst),\ + SRI(OTG_NOM_VERT_POSITION, OTG, inst),\ + SRI(OTG_BLANK_DATA_COLOR, OTG, inst),\ + SRI(OTG_BLANK_DATA_COLOR_EXT, OTG, inst),\ + SRI(OTG_M_CONST_DTO0, OTG, inst),\ + SRI(OTG_M_CONST_DTO1, OTG, inst),\ + SRI(OTG_CLOCK_CONTROL, OTG, inst),\ + SRI(OTG_VERTICAL_INTERRUPT0_CONTROL, OTG, inst),\ + SRI(OTG_VERTICAL_INTERRUPT0_POSITION, OTG, inst),\ + SRI(OTG_VERTICAL_INTERRUPT1_CONTROL, OTG, inst),\ + SRI(OTG_VERTICAL_INTERRUPT1_POSITION, OTG, inst),\ + SRI(OTG_VERTICAL_INTERRUPT2_CONTROL, OTG, inst),\ + SRI(OTG_VERTICAL_INTERRUPT2_POSITION, OTG, inst),\ + SRI(OPTC_INPUT_CLOCK_CONTROL, ODM, inst),\ + SRI(OPTC_DATA_SOURCE_SELECT, ODM, inst),\ + SRI(OPTC_INPUT_GLOBAL_CONTROL, ODM, inst),\ + SRI(CONTROL, VTG, inst),\ + SRI(OTG_VERT_SYNC_CONTROL, OTG, inst),\ + SRI(OTG_GSL_CONTROL, OTG, inst),\ + SRI(OTG_CRC_CNTL, OTG, inst),\ + SRI(OTG_CRC_CNTL2, OTG, inst),\ + SRI(OTG_CRC0_DATA_RG, OTG, inst),\ + SRI(OTG_CRC0_DATA_B, OTG, inst),\ + SRI(OTG_CRC0_WINDOWA_X_CONTROL, OTG, inst),\ + SRI(OTG_CRC0_WINDOWA_Y_CONTROL, OTG, inst),\ + SRI(OTG_CRC0_WINDOWB_X_CONTROL, OTG, inst),\ + SRI(OTG_CRC0_WINDOWB_Y_CONTROL, OTG, inst),\ + SR(GSL_SOURCE_SELECT),\ + SRI(OTG_TRIGA_MANUAL_TRIG, OTG, inst),\ + SRI(OTG_DRR_CONTROL, OTG, inst) + + +#define OPTC_COMMON_REG_LIST_DCN3_0(inst) \ + OPTC_COMMON_REG_LIST_DCN3_BASE(inst),\ + SRI(OTG_GLOBAL_CONTROL1, OTG, inst),\ + SRI(OTG_GLOBAL_CONTROL2, OTG, inst),\ + SRI(OTG_GSL_WINDOW_X, OTG, inst),\ + SRI(OTG_GSL_WINDOW_Y, OTG, inst),\ + SRI(OTG_VUPDATE_KEEPOUT, OTG, inst),\ + SRI(OTG_DSC_START_POSITION, OTG, inst),\ + SRI(OTG_CRC_CNTL2, OTG, inst),\ + SRI(OTG_DRR_TRIGGER_WINDOW, OTG, inst),\ + SRI(OTG_DRR_V_TOTAL_CHANGE, OTG, inst),\ + SRI(OPTC_DATA_FORMAT_CONTROL, ODM, inst),\ + SRI(OPTC_BYTES_PER_PIXEL, ODM, inst),\ + SRI(OPTC_WIDTH_CONTROL, ODM, inst),\ + SRI(OPTC_MEMORY_CONFIG, ODM, inst),\ + SR(DWB_SOURCE_SELECT) + +#define DCN30_VTOTAL_REGS_SF(mask_sh) + +#define OPTC_COMMON_MASK_SH_LIST_DCN3_BASE(mask_sh)\ + SF(OTG0_OTG_VSTARTUP_PARAM, VSTARTUP_START, mask_sh),\ + SF(OTG0_OTG_VUPDATE_PARAM, VUPDATE_OFFSET, mask_sh),\ + SF(OTG0_OTG_VUPDATE_PARAM, VUPDATE_WIDTH, mask_sh),\ + SF(OTG0_OTG_VREADY_PARAM, VREADY_OFFSET, mask_sh),\ + SF(OTG0_OTG_MASTER_UPDATE_LOCK, OTG_MASTER_UPDATE_LOCK, mask_sh),\ + SF(OTG0_OTG_MASTER_UPDATE_LOCK, UPDATE_LOCK_STATUS, mask_sh),\ + SF(OTG0_OTG_GLOBAL_CONTROL0, MASTER_UPDATE_LOCK_DB_START_X, mask_sh),\ + SF(OTG0_OTG_GLOBAL_CONTROL0, MASTER_UPDATE_LOCK_DB_END_X, mask_sh),\ + SF(OTG0_OTG_GLOBAL_CONTROL0, MASTER_UPDATE_LOCK_DB_EN, mask_sh),\ + SF(OTG0_OTG_GLOBAL_CONTROL1, MASTER_UPDATE_LOCK_DB_START_Y, mask_sh),\ + SF(OTG0_OTG_GLOBAL_CONTROL1, MASTER_UPDATE_LOCK_DB_END_Y, mask_sh),\ + SF(OTG0_OTG_GLOBAL_CONTROL2, OTG_MASTER_UPDATE_LOCK_SEL, mask_sh),\ + SF(OTG0_OTG_GLOBAL_CONTROL4, DIG_UPDATE_POSITION_X, mask_sh),\ + SF(OTG0_OTG_GLOBAL_CONTROL4, DIG_UPDATE_POSITION_Y, mask_sh),\ + SF(OTG0_OTG_DOUBLE_BUFFER_CONTROL, OTG_UPDATE_PENDING, mask_sh),\ + SF(OTG0_OTG_H_TOTAL, OTG_H_TOTAL, mask_sh),\ + SF(OTG0_OTG_H_BLANK_START_END, OTG_H_BLANK_START, mask_sh),\ + SF(OTG0_OTG_H_BLANK_START_END, OTG_H_BLANK_END, mask_sh),\ + SF(OTG0_OTG_H_SYNC_A, OTG_H_SYNC_A_START, mask_sh),\ + SF(OTG0_OTG_H_SYNC_A, OTG_H_SYNC_A_END, mask_sh),\ + SF(OTG0_OTG_H_SYNC_A_CNTL, OTG_H_SYNC_A_POL, mask_sh),\ + SF(OTG0_OTG_V_TOTAL, OTG_V_TOTAL, mask_sh),\ + SF(OTG0_OTG_V_BLANK_START_END, OTG_V_BLANK_START, mask_sh),\ + SF(OTG0_OTG_V_BLANK_START_END, OTG_V_BLANK_END, mask_sh),\ + SF(OTG0_OTG_V_SYNC_A, OTG_V_SYNC_A_START, mask_sh),\ + SF(OTG0_OTG_V_SYNC_A, OTG_V_SYNC_A_END, mask_sh),\ + SF(OTG0_OTG_V_SYNC_A_CNTL, OTG_V_SYNC_A_POL, mask_sh),\ + SF(OTG0_OTG_V_SYNC_A_CNTL, OTG_V_SYNC_MODE, mask_sh),\ + SF(OTG0_OTG_CONTROL, OTG_MASTER_EN, mask_sh),\ + SF(OTG0_OTG_CONTROL, OTG_START_POINT_CNTL, mask_sh),\ + SF(OTG0_OTG_CONTROL, OTG_DISABLE_POINT_CNTL, mask_sh),\ + SF(OTG0_OTG_CONTROL, OTG_FIELD_NUMBER_CNTL, mask_sh),\ + SF(OTG0_OTG_CONTROL, OTG_OUT_MUX, mask_sh),\ + SF(OTG0_OTG_STEREO_CONTROL, OTG_STEREO_EN, mask_sh),\ + SF(OTG0_OTG_STEREO_CONTROL, OTG_STEREO_SYNC_OUTPUT_LINE_NUM, mask_sh),\ + SF(OTG0_OTG_STEREO_CONTROL, OTG_STEREO_SYNC_OUTPUT_POLARITY, mask_sh),\ + SF(OTG0_OTG_STEREO_CONTROL, OTG_STEREO_EYE_FLAG_POLARITY, mask_sh),\ + SF(OTG0_OTG_STEREO_CONTROL, OTG_DISABLE_STEREOSYNC_OUTPUT_FOR_DP, mask_sh),\ + SF(OTG0_OTG_STEREO_STATUS, OTG_STEREO_CURRENT_EYE, mask_sh),\ + SF(OTG0_OTG_3D_STRUCTURE_CONTROL, OTG_3D_STRUCTURE_EN, mask_sh),\ + SF(OTG0_OTG_3D_STRUCTURE_CONTROL, OTG_3D_STRUCTURE_V_UPDATE_MODE, mask_sh),\ + SF(OTG0_OTG_3D_STRUCTURE_CONTROL, OTG_3D_STRUCTURE_STEREO_SEL_OVR, mask_sh),\ + SF(OTG0_OTG_V_TOTAL_MAX, OTG_V_TOTAL_MAX, mask_sh),\ + SF(OTG0_OTG_V_TOTAL_MIN, OTG_V_TOTAL_MIN, mask_sh),\ + SF(OTG0_OTG_V_TOTAL_CONTROL, OTG_V_TOTAL_MIN_SEL, mask_sh),\ + SF(OTG0_OTG_V_TOTAL_CONTROL, OTG_V_TOTAL_MAX_SEL, mask_sh),\ + SF(OTG0_OTG_V_TOTAL_CONTROL, OTG_FORCE_LOCK_ON_EVENT, mask_sh),\ + SF(OTG0_OTG_V_TOTAL_CONTROL, OTG_SET_V_TOTAL_MIN_MASK_EN, mask_sh),\ + SF(OTG0_OTG_V_TOTAL_CONTROL, OTG_SET_V_TOTAL_MIN_MASK, mask_sh),\ + SF(OTG0_OTG_V_TOTAL_CONTROL, OTG_VTOTAL_MID_REPLACING_MIN_EN, mask_sh),\ + SF(OTG0_OTG_V_TOTAL_CONTROL, OTG_VTOTAL_MID_REPLACING_MAX_EN, mask_sh),\ + DCN30_VTOTAL_REGS_SF(mask_sh)\ + SF(OTG0_OTG_FORCE_COUNT_NOW_CNTL, OTG_FORCE_COUNT_NOW_CLEAR, mask_sh),\ + SF(OTG0_OTG_FORCE_COUNT_NOW_CNTL, OTG_FORCE_COUNT_NOW_MODE, mask_sh),\ + SF(OTG0_OTG_FORCE_COUNT_NOW_CNTL, OTG_FORCE_COUNT_NOW_OCCURRED, mask_sh),\ + SF(OTG0_OTG_TRIGA_CNTL, OTG_TRIGA_SOURCE_SELECT, mask_sh),\ + SF(OTG0_OTG_TRIGA_CNTL, OTG_TRIGA_SOURCE_PIPE_SELECT, mask_sh),\ + SF(OTG0_OTG_TRIGA_CNTL, OTG_TRIGA_RISING_EDGE_DETECT_CNTL, mask_sh),\ + SF(OTG0_OTG_TRIGA_CNTL, OTG_TRIGA_FALLING_EDGE_DETECT_CNTL, mask_sh),\ + SF(OTG0_OTG_TRIGA_CNTL, OTG_TRIGA_POLARITY_SELECT, mask_sh),\ + SF(OTG0_OTG_TRIGA_CNTL, OTG_TRIGA_FREQUENCY_SELECT, mask_sh),\ + SF(OTG0_OTG_TRIGA_CNTL, OTG_TRIGA_DELAY, mask_sh),\ + SF(OTG0_OTG_TRIGA_CNTL, OTG_TRIGA_CLEAR, mask_sh),\ + SF(OTG0_OTG_STATIC_SCREEN_CONTROL, OTG_STATIC_SCREEN_EVENT_MASK, mask_sh),\ + SF(OTG0_OTG_STATIC_SCREEN_CONTROL, OTG_STATIC_SCREEN_FRAME_COUNT, mask_sh),\ + SF(OTG0_OTG_STATUS_FRAME_COUNT, OTG_FRAME_COUNT, mask_sh),\ + SF(OTG0_OTG_STATUS, OTG_V_BLANK, mask_sh),\ + SF(OTG0_OTG_STATUS, OTG_V_ACTIVE_DISP, mask_sh),\ + SF(OTG0_OTG_STATUS_POSITION, OTG_HORZ_COUNT, mask_sh),\ + SF(OTG0_OTG_STATUS_POSITION, OTG_VERT_COUNT, mask_sh),\ + SF(OTG0_OTG_NOM_VERT_POSITION, OTG_VERT_COUNT_NOM, mask_sh),\ + SF(OTG0_OTG_BLANK_DATA_COLOR, OTG_BLANK_DATA_COLOR_BLUE_CB, mask_sh),\ + SF(OTG0_OTG_BLANK_DATA_COLOR, OTG_BLANK_DATA_COLOR_GREEN_Y, mask_sh),\ + SF(OTG0_OTG_BLANK_DATA_COLOR, OTG_BLANK_DATA_COLOR_RED_CR, mask_sh),\ + SF(OTG0_OTG_BLANK_DATA_COLOR_EXT, OTG_BLANK_DATA_COLOR_BLUE_CB_EXT, mask_sh),\ + SF(OTG0_OTG_BLANK_DATA_COLOR_EXT, OTG_BLANK_DATA_COLOR_GREEN_Y_EXT, mask_sh),\ + SF(OTG0_OTG_BLANK_DATA_COLOR_EXT, OTG_BLANK_DATA_COLOR_RED_CR_EXT, mask_sh),\ + SF(OTG0_OTG_M_CONST_DTO0, OTG_M_CONST_DTO_PHASE, mask_sh),\ + SF(OTG0_OTG_M_CONST_DTO1, OTG_M_CONST_DTO_MODULO, mask_sh),\ + SF(OTG0_OTG_CLOCK_CONTROL, OTG_BUSY, mask_sh),\ + SF(OTG0_OTG_CLOCK_CONTROL, OTG_CLOCK_EN, mask_sh),\ + SF(OTG0_OTG_CLOCK_CONTROL, OTG_CLOCK_ON, mask_sh),\ + SF(OTG0_OTG_CLOCK_CONTROL, OTG_CLOCK_GATE_DIS, mask_sh),\ + SF(OTG0_OTG_VERTICAL_INTERRUPT0_CONTROL, OTG_VERTICAL_INTERRUPT0_INT_ENABLE, mask_sh),\ + SF(OTG0_OTG_VERTICAL_INTERRUPT0_POSITION, OTG_VERTICAL_INTERRUPT0_LINE_START, mask_sh),\ + SF(OTG0_OTG_VERTICAL_INTERRUPT0_POSITION, OTG_VERTICAL_INTERRUPT0_LINE_END, mask_sh),\ + SF(OTG0_OTG_VERTICAL_INTERRUPT1_CONTROL, OTG_VERTICAL_INTERRUPT1_INT_ENABLE, mask_sh),\ + SF(OTG0_OTG_VERTICAL_INTERRUPT1_POSITION, OTG_VERTICAL_INTERRUPT1_LINE_START, mask_sh),\ + SF(OTG0_OTG_VERTICAL_INTERRUPT2_CONTROL, OTG_VERTICAL_INTERRUPT2_INT_ENABLE, mask_sh),\ + SF(OTG0_OTG_VERTICAL_INTERRUPT2_POSITION, OTG_VERTICAL_INTERRUPT2_LINE_START, mask_sh),\ + SF(ODM0_OPTC_INPUT_CLOCK_CONTROL, OPTC_INPUT_CLK_EN, mask_sh),\ + SF(ODM0_OPTC_INPUT_CLOCK_CONTROL, OPTC_INPUT_CLK_ON, mask_sh),\ + SF(ODM0_OPTC_INPUT_CLOCK_CONTROL, OPTC_INPUT_CLK_GATE_DIS, mask_sh),\ + SF(ODM0_OPTC_INPUT_GLOBAL_CONTROL, OPTC_UNDERFLOW_OCCURRED_STATUS, mask_sh),\ + SF(ODM0_OPTC_INPUT_GLOBAL_CONTROL, OPTC_UNDERFLOW_CLEAR, mask_sh),\ + SF(VTG0_CONTROL, VTG0_ENABLE, mask_sh),\ + SF(VTG0_CONTROL, VTG0_FP2, mask_sh),\ + SF(VTG0_CONTROL, VTG0_VCOUNT_INIT, mask_sh),\ + SF(OTG0_OTG_VERT_SYNC_CONTROL, OTG_FORCE_VSYNC_NEXT_LINE_OCCURRED, mask_sh),\ + SF(OTG0_OTG_VERT_SYNC_CONTROL, OTG_FORCE_VSYNC_NEXT_LINE_CLEAR, mask_sh),\ + SF(OTG0_OTG_VERT_SYNC_CONTROL, OTG_AUTO_FORCE_VSYNC_MODE, mask_sh),\ + SF(OTG0_OTG_GSL_CONTROL, OTG_GSL0_EN, mask_sh),\ + SF(OTG0_OTG_GSL_CONTROL, OTG_GSL1_EN, mask_sh),\ + SF(OTG0_OTG_GSL_CONTROL, OTG_GSL2_EN, mask_sh),\ + SF(OTG0_OTG_GSL_CONTROL, OTG_GSL_MASTER_EN, mask_sh),\ + SF(OTG0_OTG_GSL_CONTROL, OTG_GSL_FORCE_DELAY, mask_sh),\ + SF(OTG0_OTG_GSL_CONTROL, OTG_GSL_CHECK_ALL_FIELDS, mask_sh),\ + SF(OTG0_OTG_CRC_CNTL, OTG_CRC_CONT_EN, mask_sh),\ + SF(OTG0_OTG_CRC_CNTL, OTG_CRC0_SELECT, mask_sh),\ + SF(OTG0_OTG_CRC_CNTL, OTG_CRC_EN, mask_sh),\ + SF(OTG0_OTG_CRC_CNTL2, OTG_CRC_DSC_MODE, mask_sh),\ + SF(OTG0_OTG_CRC_CNTL2, OTG_CRC_DATA_STREAM_COMBINE_MODE, mask_sh),\ + SF(OTG0_OTG_CRC_CNTL2, OTG_CRC_DATA_STREAM_SPLIT_MODE, mask_sh),\ + SF(OTG0_OTG_CRC_CNTL2, OTG_CRC_DATA_FORMAT, mask_sh),\ + SF(OTG0_OTG_CRC0_DATA_RG, CRC0_R_CR, mask_sh),\ + SF(OTG0_OTG_CRC0_DATA_RG, CRC0_G_Y, mask_sh),\ + SF(OTG0_OTG_CRC0_DATA_B, CRC0_B_CB, mask_sh),\ + SF(OTG0_OTG_CRC0_WINDOWA_X_CONTROL, OTG_CRC0_WINDOWA_X_START, mask_sh),\ + SF(OTG0_OTG_CRC0_WINDOWA_X_CONTROL, OTG_CRC0_WINDOWA_X_END, mask_sh),\ + SF(OTG0_OTG_CRC0_WINDOWA_Y_CONTROL, OTG_CRC0_WINDOWA_Y_START, mask_sh),\ + SF(OTG0_OTG_CRC0_WINDOWA_Y_CONTROL, OTG_CRC0_WINDOWA_Y_END, mask_sh),\ + SF(OTG0_OTG_CRC0_WINDOWB_X_CONTROL, OTG_CRC0_WINDOWB_X_START, mask_sh),\ + SF(OTG0_OTG_CRC0_WINDOWB_X_CONTROL, OTG_CRC0_WINDOWB_X_END, mask_sh),\ + SF(OTG0_OTG_CRC0_WINDOWB_Y_CONTROL, OTG_CRC0_WINDOWB_Y_START, mask_sh),\ + SF(OTG0_OTG_CRC0_WINDOWB_Y_CONTROL, OTG_CRC0_WINDOWB_Y_END, mask_sh),\ + SF(OTG0_OTG_TRIGA_MANUAL_TRIG, OTG_TRIGA_MANUAL_TRIG, mask_sh),\ + SF(GSL_SOURCE_SELECT, GSL0_READY_SOURCE_SEL, mask_sh),\ + SF(GSL_SOURCE_SELECT, GSL1_READY_SOURCE_SEL, mask_sh),\ + SF(GSL_SOURCE_SELECT, GSL2_READY_SOURCE_SEL, mask_sh),\ + SF(OTG0_OTG_GLOBAL_CONTROL2, MANUAL_FLOW_CONTROL_SEL, mask_sh),\ + SF(OTG0_OTG_DRR_CONTROL, OTG_V_TOTAL_LAST_USED_BY_DRR, mask_sh) + +#define OPTC_COMMON_MASK_SH_LIST_DCN3_0(mask_sh)\ + OPTC_COMMON_MASK_SH_LIST_DCN3_BASE(mask_sh),\ + SF(OTG0_OTG_GLOBAL_CONTROL2, GLOBAL_UPDATE_LOCK_EN, mask_sh),\ + SF(OTG0_OTG_GSL_WINDOW_X, OTG_GSL_WINDOW_START_X, mask_sh),\ + SF(OTG0_OTG_GSL_WINDOW_X, OTG_GSL_WINDOW_END_X, mask_sh), \ + SF(OTG0_OTG_GSL_WINDOW_Y, OTG_GSL_WINDOW_START_Y, mask_sh),\ + SF(OTG0_OTG_GSL_WINDOW_Y, OTG_GSL_WINDOW_END_Y, mask_sh),\ + SF(OTG0_OTG_VUPDATE_KEEPOUT, OTG_MASTER_UPDATE_LOCK_VUPDATE_KEEPOUT_EN, mask_sh), \ + SF(OTG0_OTG_VUPDATE_KEEPOUT, MASTER_UPDATE_LOCK_VUPDATE_KEEPOUT_START_OFFSET, mask_sh), \ + SF(OTG0_OTG_VUPDATE_KEEPOUT, MASTER_UPDATE_LOCK_VUPDATE_KEEPOUT_END_OFFSET, mask_sh), \ + SF(OTG0_OTG_GSL_CONTROL, OTG_GSL_MASTER_MODE, mask_sh), \ + SF(OTG0_OTG_GSL_CONTROL, OTG_MASTER_UPDATE_LOCK_GSL_EN, mask_sh), \ + SF(OTG0_OTG_DSC_START_POSITION, OTG_DSC_START_POSITION_X, mask_sh), \ + SF(OTG0_OTG_DSC_START_POSITION, OTG_DSC_START_POSITION_LINE_NUM, mask_sh),\ + SF(OTG0_OTG_CRC_CNTL2, OTG_CRC_DSC_MODE, mask_sh),\ + SF(OTG0_OTG_CRC_CNTL2, OTG_CRC_DATA_STREAM_COMBINE_MODE, mask_sh),\ + SF(OTG0_OTG_CRC_CNTL2, OTG_CRC_DATA_STREAM_SPLIT_MODE, mask_sh),\ + SF(OTG0_OTG_CRC_CNTL2, OTG_CRC_DATA_FORMAT, mask_sh),\ + SF(ODM0_OPTC_DATA_SOURCE_SELECT, OPTC_SEG0_SRC_SEL, mask_sh),\ + SF(ODM0_OPTC_DATA_SOURCE_SELECT, OPTC_SEG1_SRC_SEL, mask_sh),\ + SF(ODM0_OPTC_DATA_SOURCE_SELECT, OPTC_NUM_OF_INPUT_SEGMENT, mask_sh),\ + SF(ODM0_OPTC_MEMORY_CONFIG, OPTC_MEM_SEL, mask_sh),\ + SF(ODM0_OPTC_DATA_FORMAT_CONTROL, OPTC_DATA_FORMAT, mask_sh),\ + SF(ODM0_OPTC_DATA_FORMAT_CONTROL, OPTC_DSC_MODE, mask_sh),\ + SF(ODM0_OPTC_BYTES_PER_PIXEL, OPTC_DSC_BYTES_PER_PIXEL, mask_sh),\ + SF(ODM0_OPTC_WIDTH_CONTROL, OPTC_DSC_SLICE_WIDTH, mask_sh),\ + SF(ODM0_OPTC_WIDTH_CONTROL, OPTC_SEGMENT_WIDTH, mask_sh),\ + SF(DWB_SOURCE_SELECT, OPTC_DWB0_SOURCE_SELECT, mask_sh),\ + SF(DWB_SOURCE_SELECT, OPTC_DWB1_SOURCE_SELECT, mask_sh),\ + SF(OTG0_OTG_DRR_TRIGGER_WINDOW, OTG_DRR_TRIGGER_WINDOW_START_X, mask_sh),\ + SF(OTG0_OTG_DRR_TRIGGER_WINDOW, OTG_DRR_TRIGGER_WINDOW_END_X, mask_sh),\ + SF(OTG0_OTG_DRR_V_TOTAL_CHANGE, OTG_DRR_V_TOTAL_CHANGE_LIMIT, mask_sh),\ + SF(OTG0_OTG_H_TIMING_CNTL, OTG_H_TIMING_DIV_BY2, mask_sh),\ + SF(OTG0_OTG_DOUBLE_BUFFER_CONTROL, OTG_DRR_TIMING_DBUF_UPDATE_PENDING, mask_sh),\ + SF(OTG0_OTG_DOUBLE_BUFFER_CONTROL, OTG_DRR_TIMING_DBUF_UPDATE_MODE, mask_sh),\ + SF(OTG0_OTG_DOUBLE_BUFFER_CONTROL, OTG_BLANK_DATA_DOUBLE_BUFFER_EN, mask_sh) + +#define OPTC_COMMON_MASK_SH_LIST_DCN30(mask_sh)\ + OPTC_COMMON_MASK_SH_LIST_DCN3_BASE(mask_sh),\ + SF(OTG0_OTG_GLOBAL_CONTROL2, GLOBAL_UPDATE_LOCK_EN, mask_sh),\ + SF(OTG0_OTG_GSL_WINDOW_X, OTG_GSL_WINDOW_START_X, mask_sh),\ + SF(OTG0_OTG_GSL_WINDOW_X, OTG_GSL_WINDOW_END_X, mask_sh), \ + SF(OTG0_OTG_GSL_WINDOW_Y, OTG_GSL_WINDOW_START_Y, mask_sh),\ + SF(OTG0_OTG_GSL_WINDOW_Y, OTG_GSL_WINDOW_END_Y, mask_sh),\ + SF(OTG0_OTG_VUPDATE_KEEPOUT, OTG_MASTER_UPDATE_LOCK_VUPDATE_KEEPOUT_EN, mask_sh), \ + SF(OTG0_OTG_VUPDATE_KEEPOUT, MASTER_UPDATE_LOCK_VUPDATE_KEEPOUT_START_OFFSET, mask_sh), \ + SF(OTG0_OTG_VUPDATE_KEEPOUT, MASTER_UPDATE_LOCK_VUPDATE_KEEPOUT_END_OFFSET, mask_sh), \ + SF(OTG0_OTG_GSL_CONTROL, OTG_GSL_MASTER_MODE, mask_sh), \ + SF(OTG0_OTG_GSL_CONTROL, OTG_MASTER_UPDATE_LOCK_GSL_EN, mask_sh), \ + SF(OTG0_OTG_DSC_START_POSITION, OTG_DSC_START_POSITION_X, mask_sh), \ + SF(OTG0_OTG_DSC_START_POSITION, OTG_DSC_START_POSITION_LINE_NUM, mask_sh),\ + SF(OTG0_OTG_CRC_CNTL2, OTG_CRC_DSC_MODE, mask_sh),\ + SF(OTG0_OTG_CRC_CNTL2, OTG_CRC_DATA_STREAM_COMBINE_MODE, mask_sh),\ + SF(OTG0_OTG_CRC_CNTL2, OTG_CRC_DATA_STREAM_SPLIT_MODE, mask_sh),\ + SF(OTG0_OTG_CRC_CNTL2, OTG_CRC_DATA_FORMAT, mask_sh),\ + SF(ODM0_OPTC_DATA_SOURCE_SELECT, OPTC_SEG0_SRC_SEL, mask_sh),\ + SF(ODM0_OPTC_DATA_SOURCE_SELECT, OPTC_SEG1_SRC_SEL, mask_sh),\ + SF(ODM0_OPTC_DATA_SOURCE_SELECT, OPTC_SEG2_SRC_SEL, mask_sh),\ + SF(ODM0_OPTC_DATA_SOURCE_SELECT, OPTC_SEG3_SRC_SEL, mask_sh),\ + SF(ODM0_OPTC_DATA_SOURCE_SELECT, OPTC_NUM_OF_INPUT_SEGMENT, mask_sh),\ + SF(ODM0_OPTC_MEMORY_CONFIG, OPTC_MEM_SEL, mask_sh),\ + SF(ODM0_OPTC_DATA_FORMAT_CONTROL, OPTC_DATA_FORMAT, mask_sh),\ + SF(ODM0_OPTC_DATA_FORMAT_CONTROL, OPTC_DSC_MODE, mask_sh),\ + SF(ODM0_OPTC_BYTES_PER_PIXEL, OPTC_DSC_BYTES_PER_PIXEL, mask_sh),\ + SF(ODM0_OPTC_WIDTH_CONTROL, OPTC_DSC_SLICE_WIDTH, mask_sh),\ + SF(ODM0_OPTC_WIDTH_CONTROL, OPTC_SEGMENT_WIDTH, mask_sh),\ + SF(DWB_SOURCE_SELECT, OPTC_DWB0_SOURCE_SELECT, mask_sh),\ + SF(DWB_SOURCE_SELECT, OPTC_DWB1_SOURCE_SELECT, mask_sh),\ + SF(OTG0_OTG_DRR_TRIGGER_WINDOW, OTG_DRR_TRIGGER_WINDOW_START_X, mask_sh),\ + SF(OTG0_OTG_DRR_TRIGGER_WINDOW, OTG_DRR_TRIGGER_WINDOW_END_X, mask_sh),\ + SF(OTG0_OTG_DRR_V_TOTAL_CHANGE, OTG_DRR_V_TOTAL_CHANGE_LIMIT, mask_sh),\ + SF(OTG0_OTG_H_TIMING_CNTL, OTG_H_TIMING_DIV_MODE, mask_sh),\ + SF(OTG0_OTG_DOUBLE_BUFFER_CONTROL, OTG_DRR_TIMING_DBUF_UPDATE_PENDING, mask_sh),\ + SF(OTG0_OTG_DOUBLE_BUFFER_CONTROL, OTG_DRR_TIMING_DBUF_UPDATE_MODE, mask_sh) + +void dcn30_timing_generator_init(struct optc *optc1); + +void optc3_set_out_mux(struct timing_generator *optc, enum otg_out_mux_dest dest); + +void optc3_lock(struct timing_generator *optc); + +void optc3_lock_doublebuffer_enable(struct timing_generator *optc); + +void optc3_lock_doublebuffer_disable(struct timing_generator *optc); + +void optc3_set_drr_trigger_window(struct timing_generator *optc, + uint32_t window_start, uint32_t window_end); + +void optc3_triplebuffer_lock(struct timing_generator *optc); + +void optc3_program_blank_color(struct timing_generator *optc, + const struct tg_color *blank_color); + +void optc3_set_vtotal_change_limit(struct timing_generator *optc, + uint32_t limit); + +void optc3_set_dsc_config(struct timing_generator *optc, + enum optc_dsc_mode dsc_mode, + uint32_t dsc_bytes_per_pixel, + uint32_t dsc_slice_width); + +void optc3_set_timing_db_mode(struct timing_generator *optc, bool enable); + +void optc3_set_odm_bypass(struct timing_generator *optc, + const struct dc_crtc_timing *dc_crtc_timing); +void optc3_tg_init(struct timing_generator *optc); +void optc3_set_vtotal_min_max(struct timing_generator *optc, int vtotal_min, int vtotal_max); +#endif /* __DC_OPTC_DCN30_H__ */ diff --git a/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_resource.c b/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_resource.c new file mode 100644 index 000000000..5a8d1a051 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_resource.c @@ -0,0 +1,2626 @@ +/* + * Copyright 2020 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 "dc.h" + +#include "dcn30_init.h" + +#include "resource.h" +#include "include/irq_service_interface.h" +#include "dcn20/dcn20_resource.h" + +#include "dcn30_resource.h" + +#include "dcn10/dcn10_ipp.h" +#include "dcn30/dcn30_hubbub.h" +#include "dcn30/dcn30_mpc.h" +#include "dcn30/dcn30_hubp.h" +#include "irq/dcn30/irq_service_dcn30.h" +#include "dcn30/dcn30_dpp.h" +#include "dcn30/dcn30_optc.h" +#include "dcn20/dcn20_hwseq.h" +#include "dcn30/dcn30_hwseq.h" +#include "dce110/dce110_hw_sequencer.h" +#include "dcn30/dcn30_opp.h" +#include "dcn20/dcn20_dsc.h" +#include "dcn30/dcn30_vpg.h" +#include "dcn30/dcn30_afmt.h" +#include "dcn30/dcn30_dio_stream_encoder.h" +#include "dcn30/dcn30_dio_link_encoder.h" +#include "dce/dce_clock_source.h" +#include "dce/dce_audio.h" +#include "dce/dce_hwseq.h" +#include "clk_mgr.h" +#include "virtual/virtual_stream_encoder.h" +#include "dce110/dce110_resource.h" +#include "dml/display_mode_vba.h" +#include "dcn30/dcn30_dccg.h" +#include "dcn10/dcn10_resource.h" +#include "dc_link_ddc.h" +#include "dce/dce_panel_cntl.h" + +#include "dcn30/dcn30_dwb.h" +#include "dcn30/dcn30_mmhubbub.h" + +#include "sienna_cichlid_ip_offset.h" +#include "dcn/dcn_3_0_0_offset.h" +#include "dcn/dcn_3_0_0_sh_mask.h" + +#include "nbio/nbio_7_4_offset.h" + +#include "dpcs/dpcs_3_0_0_offset.h" +#include "dpcs/dpcs_3_0_0_sh_mask.h" + +#include "mmhub/mmhub_2_0_0_offset.h" +#include "mmhub/mmhub_2_0_0_sh_mask.h" + +#include "reg_helper.h" +#include "dce/dmub_abm.h" +#include "dce/dmub_psr.h" +#include "dce/dce_aux.h" +#include "dce/dce_i2c.h" + +#include "dml/dcn30/dcn30_fpu.h" +#include "dml/dcn30/display_mode_vba_30.h" +#include "vm_helper.h" +#include "dcn20/dcn20_vmid.h" +#include "amdgpu_socbb.h" +#include "dc_dmub_srv.h" + +#define DC_LOGGER_INIT(logger) + +enum dcn30_clk_src_array_id { + DCN30_CLK_SRC_PLL0, + DCN30_CLK_SRC_PLL1, + DCN30_CLK_SRC_PLL2, + DCN30_CLK_SRC_PLL3, + DCN30_CLK_SRC_PLL4, + DCN30_CLK_SRC_PLL5, + DCN30_CLK_SRC_TOTAL +}; + +/* begin ********************* + * macros to expend register list macro defined in HW object header file + */ + +/* DCN */ +/* TODO awful hack. fixup dcn20_dwb.h */ +#undef BASE_INNER +#define BASE_INNER(seg) DCN_BASE__INST0_SEG ## seg + +#define BASE(seg) BASE_INNER(seg) + +#define SR(reg_name)\ + .reg_name = BASE(mm ## reg_name ## _BASE_IDX) + \ + mm ## reg_name + +#define SRI(reg_name, block, id)\ + .reg_name = BASE(mm ## block ## id ## _ ## reg_name ## _BASE_IDX) + \ + mm ## block ## id ## _ ## reg_name + +#define SRI2(reg_name, block, id)\ + .reg_name = BASE(mm ## reg_name ## _BASE_IDX) + \ + mm ## reg_name + +#define SRIR(var_name, reg_name, block, id)\ + .var_name = BASE(mm ## block ## id ## _ ## reg_name ## _BASE_IDX) + \ + mm ## block ## id ## _ ## reg_name + +#define SRII(reg_name, block, id)\ + .reg_name[id] = BASE(mm ## block ## id ## _ ## reg_name ## _BASE_IDX) + \ + mm ## block ## id ## _ ## reg_name + +#define SRII_MPC_RMU(reg_name, block, id)\ + .RMU##_##reg_name[id] = BASE(mm ## block ## id ## _ ## reg_name ## _BASE_IDX) + \ + mm ## block ## id ## _ ## reg_name + +#define SRII_DWB(reg_name, temp_name, block, id)\ + .reg_name[id] = BASE(mm ## block ## id ## _ ## temp_name ## _BASE_IDX) + \ + mm ## block ## id ## _ ## temp_name + +#define DCCG_SRII(reg_name, block, id)\ + .block ## _ ## reg_name[id] = BASE(mm ## block ## id ## _ ## reg_name ## _BASE_IDX) + \ + mm ## block ## id ## _ ## reg_name + +#define VUPDATE_SRII(reg_name, block, id)\ + .reg_name[id] = BASE(mm ## reg_name ## _ ## block ## id ## _BASE_IDX) + \ + mm ## reg_name ## _ ## block ## id + +/* NBIO */ +#define NBIO_BASE_INNER(seg) \ + NBIO_BASE__INST0_SEG ## seg + +#define NBIO_BASE(seg) \ + NBIO_BASE_INNER(seg) + +#define NBIO_SR(reg_name)\ + .reg_name = NBIO_BASE(mm ## reg_name ## _BASE_IDX) + \ + mm ## reg_name + +/* MMHUB */ +#define MMHUB_BASE_INNER(seg) \ + MMHUB_BASE__INST0_SEG ## seg + +#define MMHUB_BASE(seg) \ + MMHUB_BASE_INNER(seg) + +#define MMHUB_SR(reg_name)\ + .reg_name = MMHUB_BASE(mmMM ## reg_name ## _BASE_IDX) + \ + mmMM ## reg_name + +/* CLOCK */ +#define CLK_BASE_INNER(seg) \ + CLK_BASE__INST0_SEG ## seg + +#define CLK_BASE(seg) \ + CLK_BASE_INNER(seg) + +#define CLK_SRI(reg_name, block, inst)\ + .reg_name = CLK_BASE(mm ## block ## _ ## inst ## _ ## reg_name ## _BASE_IDX) + \ + mm ## block ## _ ## inst ## _ ## reg_name + + +static const struct bios_registers bios_regs = { + NBIO_SR(BIOS_SCRATCH_3), + NBIO_SR(BIOS_SCRATCH_6) +}; + +#define clk_src_regs(index, pllid)\ +[index] = {\ + CS_COMMON_REG_LIST_DCN2_0(index, pllid),\ +} + +static const struct dce110_clk_src_regs clk_src_regs[] = { + clk_src_regs(0, A), + clk_src_regs(1, B), + clk_src_regs(2, C), + clk_src_regs(3, D), + clk_src_regs(4, E), + clk_src_regs(5, F) +}; + +static const struct dce110_clk_src_shift cs_shift = { + CS_COMMON_MASK_SH_LIST_DCN2_0(__SHIFT) +}; + +static const struct dce110_clk_src_mask cs_mask = { + CS_COMMON_MASK_SH_LIST_DCN2_0(_MASK) +}; + +#define abm_regs(id)\ +[id] = {\ + ABM_DCN30_REG_LIST(id)\ +} + +static const struct dce_abm_registers abm_regs[] = { + abm_regs(0), + abm_regs(1), + abm_regs(2), + abm_regs(3), + abm_regs(4), + abm_regs(5), +}; + +static const struct dce_abm_shift abm_shift = { + ABM_MASK_SH_LIST_DCN30(__SHIFT) +}; + +static const struct dce_abm_mask abm_mask = { + ABM_MASK_SH_LIST_DCN30(_MASK) +}; + + + +#define audio_regs(id)\ +[id] = {\ + AUD_COMMON_REG_LIST(id)\ +} + +static const struct dce_audio_registers audio_regs[] = { + audio_regs(0), + audio_regs(1), + audio_regs(2), + audio_regs(3), + audio_regs(4), + audio_regs(5), + audio_regs(6) +}; + +#define DCE120_AUD_COMMON_MASK_SH_LIST(mask_sh)\ + SF(AZF0ENDPOINT0_AZALIA_F0_CODEC_ENDPOINT_INDEX, AZALIA_ENDPOINT_REG_INDEX, mask_sh),\ + SF(AZF0ENDPOINT0_AZALIA_F0_CODEC_ENDPOINT_DATA, AZALIA_ENDPOINT_REG_DATA, mask_sh),\ + AUD_COMMON_MASK_SH_LIST_BASE(mask_sh) + +static const struct dce_audio_shift audio_shift = { + DCE120_AUD_COMMON_MASK_SH_LIST(__SHIFT) +}; + +static const struct dce_audio_mask audio_mask = { + DCE120_AUD_COMMON_MASK_SH_LIST(_MASK) +}; + +#define vpg_regs(id)\ +[id] = {\ + VPG_DCN3_REG_LIST(id)\ +} + +static const struct dcn30_vpg_registers vpg_regs[] = { + vpg_regs(0), + vpg_regs(1), + vpg_regs(2), + vpg_regs(3), + vpg_regs(4), + vpg_regs(5), + vpg_regs(6), +}; + +static const struct dcn30_vpg_shift vpg_shift = { + DCN3_VPG_MASK_SH_LIST(__SHIFT) +}; + +static const struct dcn30_vpg_mask vpg_mask = { + DCN3_VPG_MASK_SH_LIST(_MASK) +}; + +#define afmt_regs(id)\ +[id] = {\ + AFMT_DCN3_REG_LIST(id)\ +} + +static const struct dcn30_afmt_registers afmt_regs[] = { + afmt_regs(0), + afmt_regs(1), + afmt_regs(2), + afmt_regs(3), + afmt_regs(4), + afmt_regs(5), + afmt_regs(6), +}; + +static const struct dcn30_afmt_shift afmt_shift = { + DCN3_AFMT_MASK_SH_LIST(__SHIFT) +}; + +static const struct dcn30_afmt_mask afmt_mask = { + DCN3_AFMT_MASK_SH_LIST(_MASK) +}; + +#define stream_enc_regs(id)\ +[id] = {\ + SE_DCN3_REG_LIST(id)\ +} + +static const struct dcn10_stream_enc_registers stream_enc_regs[] = { + stream_enc_regs(0), + stream_enc_regs(1), + stream_enc_regs(2), + stream_enc_regs(3), + stream_enc_regs(4), + stream_enc_regs(5) +}; + +static const struct dcn10_stream_encoder_shift se_shift = { + SE_COMMON_MASK_SH_LIST_DCN30(__SHIFT) +}; + +static const struct dcn10_stream_encoder_mask se_mask = { + SE_COMMON_MASK_SH_LIST_DCN30(_MASK) +}; + + +#define aux_regs(id)\ +[id] = {\ + DCN2_AUX_REG_LIST(id)\ +} + +static const struct dcn10_link_enc_aux_registers link_enc_aux_regs[] = { + aux_regs(0), + aux_regs(1), + aux_regs(2), + aux_regs(3), + aux_regs(4), + aux_regs(5) +}; + +#define hpd_regs(id)\ +[id] = {\ + HPD_REG_LIST(id)\ +} + +static const struct dcn10_link_enc_hpd_registers link_enc_hpd_regs[] = { + hpd_regs(0), + hpd_regs(1), + hpd_regs(2), + hpd_regs(3), + hpd_regs(4), + hpd_regs(5) +}; + +#define link_regs(id, phyid)\ +[id] = {\ + LE_DCN3_REG_LIST(id), \ + UNIPHY_DCN2_REG_LIST(phyid), \ + DPCS_DCN2_REG_LIST(id), \ + SRI(DP_DPHY_INTERNAL_CTRL, DP, id) \ +} + +static const struct dce110_aux_registers_shift aux_shift = { + DCN_AUX_MASK_SH_LIST(__SHIFT) +}; + +static const struct dce110_aux_registers_mask aux_mask = { + DCN_AUX_MASK_SH_LIST(_MASK) +}; + +static const struct dcn10_link_enc_registers link_enc_regs[] = { + link_regs(0, A), + link_regs(1, B), + link_regs(2, C), + link_regs(3, D), + link_regs(4, E), + link_regs(5, F) +}; + +static const struct dcn10_link_enc_shift le_shift = { + LINK_ENCODER_MASK_SH_LIST_DCN30(__SHIFT),\ + DPCS_DCN2_MASK_SH_LIST(__SHIFT) +}; + +static const struct dcn10_link_enc_mask le_mask = { + LINK_ENCODER_MASK_SH_LIST_DCN30(_MASK),\ + DPCS_DCN2_MASK_SH_LIST(_MASK) +}; + + +static const struct dce_panel_cntl_registers panel_cntl_regs[] = { + { DCN_PANEL_CNTL_REG_LIST() } +}; + +static const struct dce_panel_cntl_shift panel_cntl_shift = { + DCE_PANEL_CNTL_MASK_SH_LIST(__SHIFT) +}; + +static const struct dce_panel_cntl_mask panel_cntl_mask = { + DCE_PANEL_CNTL_MASK_SH_LIST(_MASK) +}; + +#define dpp_regs(id)\ +[id] = {\ + DPP_REG_LIST_DCN30(id),\ +} + +static const struct dcn3_dpp_registers dpp_regs[] = { + dpp_regs(0), + dpp_regs(1), + dpp_regs(2), + dpp_regs(3), + dpp_regs(4), + dpp_regs(5), +}; + +static const struct dcn3_dpp_shift tf_shift = { + DPP_REG_LIST_SH_MASK_DCN30(__SHIFT) +}; + +static const struct dcn3_dpp_mask tf_mask = { + DPP_REG_LIST_SH_MASK_DCN30(_MASK) +}; + +#define opp_regs(id)\ +[id] = {\ + OPP_REG_LIST_DCN30(id),\ +} + +static const struct dcn20_opp_registers opp_regs[] = { + opp_regs(0), + opp_regs(1), + opp_regs(2), + opp_regs(3), + opp_regs(4), + opp_regs(5) +}; + +static const struct dcn20_opp_shift opp_shift = { + OPP_MASK_SH_LIST_DCN20(__SHIFT) +}; + +static const struct dcn20_opp_mask opp_mask = { + OPP_MASK_SH_LIST_DCN20(_MASK) +}; + +#define aux_engine_regs(id)\ +[id] = {\ + AUX_COMMON_REG_LIST0(id), \ + .AUXN_IMPCAL = 0, \ + .AUXP_IMPCAL = 0, \ + .AUX_RESET_MASK = DP_AUX0_AUX_CONTROL__AUX_RESET_MASK, \ +} + +static const struct dce110_aux_registers aux_engine_regs[] = { + aux_engine_regs(0), + aux_engine_regs(1), + aux_engine_regs(2), + aux_engine_regs(3), + aux_engine_regs(4), + aux_engine_regs(5) +}; + +#define dwbc_regs_dcn3(id)\ +[id] = {\ + DWBC_COMMON_REG_LIST_DCN30(id),\ +} + +static const struct dcn30_dwbc_registers dwbc30_regs[] = { + dwbc_regs_dcn3(0), +}; + +static const struct dcn30_dwbc_shift dwbc30_shift = { + DWBC_COMMON_MASK_SH_LIST_DCN30(__SHIFT) +}; + +static const struct dcn30_dwbc_mask dwbc30_mask = { + DWBC_COMMON_MASK_SH_LIST_DCN30(_MASK) +}; + +#define mcif_wb_regs_dcn3(id)\ +[id] = {\ + MCIF_WB_COMMON_REG_LIST_DCN30(id),\ +} + +static const struct dcn30_mmhubbub_registers mcif_wb30_regs[] = { + mcif_wb_regs_dcn3(0) +}; + +static const struct dcn30_mmhubbub_shift mcif_wb30_shift = { + MCIF_WB_COMMON_MASK_SH_LIST_DCN30(__SHIFT) +}; + +static const struct dcn30_mmhubbub_mask mcif_wb30_mask = { + MCIF_WB_COMMON_MASK_SH_LIST_DCN30(_MASK) +}; + +#define dsc_regsDCN20(id)\ +[id] = {\ + DSC_REG_LIST_DCN20(id)\ +} + +static const struct dcn20_dsc_registers dsc_regs[] = { + dsc_regsDCN20(0), + dsc_regsDCN20(1), + dsc_regsDCN20(2), + dsc_regsDCN20(3), + dsc_regsDCN20(4), + dsc_regsDCN20(5) +}; + +static const struct dcn20_dsc_shift dsc_shift = { + DSC_REG_LIST_SH_MASK_DCN20(__SHIFT) +}; + +static const struct dcn20_dsc_mask dsc_mask = { + DSC_REG_LIST_SH_MASK_DCN20(_MASK) +}; + +static const struct dcn30_mpc_registers mpc_regs = { + MPC_REG_LIST_DCN3_0(0), + MPC_REG_LIST_DCN3_0(1), + MPC_REG_LIST_DCN3_0(2), + MPC_REG_LIST_DCN3_0(3), + MPC_REG_LIST_DCN3_0(4), + MPC_REG_LIST_DCN3_0(5), + MPC_OUT_MUX_REG_LIST_DCN3_0(0), + MPC_OUT_MUX_REG_LIST_DCN3_0(1), + MPC_OUT_MUX_REG_LIST_DCN3_0(2), + MPC_OUT_MUX_REG_LIST_DCN3_0(3), + MPC_OUT_MUX_REG_LIST_DCN3_0(4), + MPC_OUT_MUX_REG_LIST_DCN3_0(5), + MPC_RMU_GLOBAL_REG_LIST_DCN3AG, + MPC_RMU_REG_LIST_DCN3AG(0), + MPC_RMU_REG_LIST_DCN3AG(1), + MPC_RMU_REG_LIST_DCN3AG(2), + MPC_DWB_MUX_REG_LIST_DCN3_0(0), +}; + +static const struct dcn30_mpc_shift mpc_shift = { + MPC_COMMON_MASK_SH_LIST_DCN30(__SHIFT) +}; + +static const struct dcn30_mpc_mask mpc_mask = { + MPC_COMMON_MASK_SH_LIST_DCN30(_MASK) +}; + +#define optc_regs(id)\ +[id] = {OPTC_COMMON_REG_LIST_DCN3_0(id)} + + +static const struct dcn_optc_registers optc_regs[] = { + optc_regs(0), + optc_regs(1), + optc_regs(2), + optc_regs(3), + optc_regs(4), + optc_regs(5) +}; + +static const struct dcn_optc_shift optc_shift = { + OPTC_COMMON_MASK_SH_LIST_DCN30(__SHIFT) +}; + +static const struct dcn_optc_mask optc_mask = { + OPTC_COMMON_MASK_SH_LIST_DCN30(_MASK) +}; + +#define hubp_regs(id)\ +[id] = {\ + HUBP_REG_LIST_DCN30(id)\ +} + +static const struct dcn_hubp2_registers hubp_regs[] = { + hubp_regs(0), + hubp_regs(1), + hubp_regs(2), + hubp_regs(3), + hubp_regs(4), + hubp_regs(5) +}; + +static const struct dcn_hubp2_shift hubp_shift = { + HUBP_MASK_SH_LIST_DCN30(__SHIFT) +}; + +static const struct dcn_hubp2_mask hubp_mask = { + HUBP_MASK_SH_LIST_DCN30(_MASK) +}; + +static const struct dcn_hubbub_registers hubbub_reg = { + HUBBUB_REG_LIST_DCN30(0) +}; + +static const struct dcn_hubbub_shift hubbub_shift = { + HUBBUB_MASK_SH_LIST_DCN30(__SHIFT) +}; + +static const struct dcn_hubbub_mask hubbub_mask = { + HUBBUB_MASK_SH_LIST_DCN30(_MASK) +}; + +static const struct dccg_registers dccg_regs = { + DCCG_REG_LIST_DCN30() +}; + +static const struct dccg_shift dccg_shift = { + DCCG_MASK_SH_LIST_DCN3(__SHIFT) +}; + +static const struct dccg_mask dccg_mask = { + DCCG_MASK_SH_LIST_DCN3(_MASK) +}; + +static const struct dce_hwseq_registers hwseq_reg = { + HWSEQ_DCN30_REG_LIST() +}; + +static const struct dce_hwseq_shift hwseq_shift = { + HWSEQ_DCN30_MASK_SH_LIST(__SHIFT) +}; + +static const struct dce_hwseq_mask hwseq_mask = { + HWSEQ_DCN30_MASK_SH_LIST(_MASK) +}; +#define vmid_regs(id)\ +[id] = {\ + DCN20_VMID_REG_LIST(id)\ +} + +static const struct dcn_vmid_registers vmid_regs[] = { + vmid_regs(0), + vmid_regs(1), + vmid_regs(2), + vmid_regs(3), + vmid_regs(4), + vmid_regs(5), + vmid_regs(6), + vmid_regs(7), + vmid_regs(8), + vmid_regs(9), + vmid_regs(10), + vmid_regs(11), + vmid_regs(12), + vmid_regs(13), + vmid_regs(14), + vmid_regs(15) +}; + +static const struct dcn20_vmid_shift vmid_shifts = { + DCN20_VMID_MASK_SH_LIST(__SHIFT) +}; + +static const struct dcn20_vmid_mask vmid_masks = { + DCN20_VMID_MASK_SH_LIST(_MASK) +}; + +static const struct resource_caps res_cap_dcn3 = { + .num_timing_generator = 6, + .num_opp = 6, + .num_video_plane = 6, + .num_audio = 6, + .num_stream_encoder = 6, + .num_pll = 6, + .num_dwb = 1, + .num_ddc = 6, + .num_vmid = 16, + .num_mpc_3dlut = 3, + .num_dsc = 6, +}; + +static const struct dc_plane_cap plane_cap = { + .type = DC_PLANE_TYPE_DCN_UNIVERSAL, + .blends_with_above = true, + .blends_with_below = true, + .per_pixel_alpha = true, + + .pixel_format_support = { + .argb8888 = true, + .nv12 = true, + .fp16 = true, + .p010 = true, + .ayuv = false, + }, + + .max_upscale_factor = { + .argb8888 = 16000, + .nv12 = 16000, + .fp16 = 16000 + }, + + /* 6:1 downscaling ratio: 1000/6 = 166.666 */ + .max_downscale_factor = { + .argb8888 = 167, + .nv12 = 167, + .fp16 = 167 + } +}; + +static const struct dc_debug_options debug_defaults_drv = { + .disable_dmcu = true, //No DMCU on DCN30 + .force_abm_enable = false, + .timing_trace = false, + .clock_trace = true, + .disable_pplib_clock_request = true, + .pipe_split_policy = MPC_SPLIT_DYNAMIC, + .force_single_disp_pipe_split = false, + .disable_dcc = DCC_ENABLE, + .vsr_support = true, + .performance_trace = false, + .max_downscale_src_width = 7680,/*upto 8K*/ + .disable_pplib_wm_range = false, + .scl_reset_length10 = true, + .sanity_checks = false, + .underflow_assert_delay_us = 0xFFFFFFFF, + .dwb_fi_phase = -1, // -1 = disable, + .dmub_command_table = true, + .use_max_lb = true, + .exit_idle_opt_for_cursor_updates = true +}; + +static const struct dc_debug_options debug_defaults_diags = { + .disable_dmcu = true, //No dmcu on DCN30 + .force_abm_enable = false, + .timing_trace = true, + .clock_trace = true, + .disable_dpp_power_gate = true, + .disable_hubp_power_gate = true, + .disable_clock_gate = true, + .disable_pplib_clock_request = true, + .disable_pplib_wm_range = true, + .disable_stutter = false, + .scl_reset_length10 = true, + .dwb_fi_phase = -1, // -1 = disable + .dmub_command_table = true, + .enable_tri_buf = true, + .use_max_lb = true +}; + +static const struct dc_panel_config panel_config_defaults = { + .psr = { + .disable_psr = false, + .disallow_psrsu = false, + }, +}; + +static void dcn30_dpp_destroy(struct dpp **dpp) +{ + kfree(TO_DCN20_DPP(*dpp)); + *dpp = NULL; +} + +static struct dpp *dcn30_dpp_create( + struct dc_context *ctx, + uint32_t inst) +{ + struct dcn3_dpp *dpp = + kzalloc(sizeof(struct dcn3_dpp), GFP_KERNEL); + + if (!dpp) + return NULL; + + if (dpp3_construct(dpp, ctx, inst, + &dpp_regs[inst], &tf_shift, &tf_mask)) + return &dpp->base; + + BREAK_TO_DEBUGGER(); + kfree(dpp); + return NULL; +} + +static struct output_pixel_processor *dcn30_opp_create( + struct dc_context *ctx, uint32_t inst) +{ + struct dcn20_opp *opp = + kzalloc(sizeof(struct dcn20_opp), GFP_KERNEL); + + if (!opp) { + BREAK_TO_DEBUGGER(); + return NULL; + } + + dcn20_opp_construct(opp, ctx, inst, + &opp_regs[inst], &opp_shift, &opp_mask); + return &opp->base; +} + +static struct dce_aux *dcn30_aux_engine_create( + struct dc_context *ctx, + uint32_t inst) +{ + struct aux_engine_dce110 *aux_engine = + kzalloc(sizeof(struct aux_engine_dce110), GFP_KERNEL); + + if (!aux_engine) + return NULL; + + dce110_aux_engine_construct(aux_engine, ctx, inst, + SW_AUX_TIMEOUT_PERIOD_MULTIPLIER * AUX_TIMEOUT_PERIOD, + &aux_engine_regs[inst], + &aux_mask, + &aux_shift, + ctx->dc->caps.extended_aux_timeout_support); + + return &aux_engine->base; +} + +#define i2c_inst_regs(id) { I2C_HW_ENGINE_COMMON_REG_LIST_DCN30(id) } + +static const struct dce_i2c_registers i2c_hw_regs[] = { + i2c_inst_regs(1), + i2c_inst_regs(2), + i2c_inst_regs(3), + i2c_inst_regs(4), + i2c_inst_regs(5), + i2c_inst_regs(6), +}; + +static const struct dce_i2c_shift i2c_shifts = { + I2C_COMMON_MASK_SH_LIST_DCN30(__SHIFT) +}; + +static const struct dce_i2c_mask i2c_masks = { + I2C_COMMON_MASK_SH_LIST_DCN30(_MASK) +}; + +static struct dce_i2c_hw *dcn30_i2c_hw_create( + struct dc_context *ctx, + uint32_t inst) +{ + struct dce_i2c_hw *dce_i2c_hw = + kzalloc(sizeof(struct dce_i2c_hw), GFP_KERNEL); + + if (!dce_i2c_hw) + return NULL; + + dcn2_i2c_hw_construct(dce_i2c_hw, ctx, inst, + &i2c_hw_regs[inst], &i2c_shifts, &i2c_masks); + + return dce_i2c_hw; +} + +static struct mpc *dcn30_mpc_create( + struct dc_context *ctx, + int num_mpcc, + int num_rmu) +{ + struct dcn30_mpc *mpc30 = kzalloc(sizeof(struct dcn30_mpc), + GFP_KERNEL); + + if (!mpc30) + return NULL; + + dcn30_mpc_construct(mpc30, ctx, + &mpc_regs, + &mpc_shift, + &mpc_mask, + num_mpcc, + num_rmu); + + return &mpc30->base; +} + +static struct hubbub *dcn30_hubbub_create(struct dc_context *ctx) +{ + int i; + + struct dcn20_hubbub *hubbub3 = kzalloc(sizeof(struct dcn20_hubbub), + GFP_KERNEL); + + if (!hubbub3) + return NULL; + + hubbub3_construct(hubbub3, ctx, + &hubbub_reg, + &hubbub_shift, + &hubbub_mask); + + + for (i = 0; i < res_cap_dcn3.num_vmid; i++) { + struct dcn20_vmid *vmid = &hubbub3->vmid[i]; + + vmid->ctx = ctx; + + vmid->regs = &vmid_regs[i]; + vmid->shifts = &vmid_shifts; + vmid->masks = &vmid_masks; + } + + return &hubbub3->base; +} + +static struct timing_generator *dcn30_timing_generator_create( + struct dc_context *ctx, + uint32_t instance) +{ + struct optc *tgn10 = + kzalloc(sizeof(struct optc), GFP_KERNEL); + + if (!tgn10) + return NULL; + + tgn10->base.inst = instance; + tgn10->base.ctx = ctx; + + tgn10->tg_regs = &optc_regs[instance]; + tgn10->tg_shift = &optc_shift; + tgn10->tg_mask = &optc_mask; + + dcn30_timing_generator_init(tgn10); + + return &tgn10->base; +} + +static const struct encoder_feature_support link_enc_feature = { + .max_hdmi_deep_color = COLOR_DEPTH_121212, + .max_hdmi_pixel_clock = 600000, + .hdmi_ycbcr420_supported = true, + .dp_ycbcr420_supported = true, + .fec_supported = true, + .flags.bits.IS_HBR2_CAPABLE = true, + .flags.bits.IS_HBR3_CAPABLE = true, + .flags.bits.IS_TPS3_CAPABLE = true, + .flags.bits.IS_TPS4_CAPABLE = true +}; + +static struct link_encoder *dcn30_link_encoder_create( + struct dc_context *ctx, + const struct encoder_init_data *enc_init_data) +{ + struct dcn20_link_encoder *enc20 = + kzalloc(sizeof(struct dcn20_link_encoder), GFP_KERNEL); + + if (!enc20) + return NULL; + + dcn30_link_encoder_construct(enc20, + enc_init_data, + &link_enc_feature, + &link_enc_regs[enc_init_data->transmitter], + &link_enc_aux_regs[enc_init_data->channel - 1], + &link_enc_hpd_regs[enc_init_data->hpd_source], + &le_shift, + &le_mask); + + return &enc20->enc10.base; +} + +static struct panel_cntl *dcn30_panel_cntl_create(const struct panel_cntl_init_data *init_data) +{ + struct dce_panel_cntl *panel_cntl = + kzalloc(sizeof(struct dce_panel_cntl), GFP_KERNEL); + + if (!panel_cntl) + return NULL; + + dce_panel_cntl_construct(panel_cntl, + init_data, + &panel_cntl_regs[init_data->inst], + &panel_cntl_shift, + &panel_cntl_mask); + + return &panel_cntl->base; +} + +static void read_dce_straps( + struct dc_context *ctx, + struct resource_straps *straps) +{ + generic_reg_get(ctx, mmDC_PINSTRAPS + BASE(mmDC_PINSTRAPS_BASE_IDX), + FN(DC_PINSTRAPS, DC_PINSTRAPS_AUDIO), &straps->dc_pinstraps_audio); + +} + +static struct audio *dcn30_create_audio( + struct dc_context *ctx, unsigned int inst) +{ + return dce_audio_create(ctx, inst, + &audio_regs[inst], &audio_shift, &audio_mask); +} + +static struct vpg *dcn30_vpg_create( + struct dc_context *ctx, + uint32_t inst) +{ + struct dcn30_vpg *vpg3 = kzalloc(sizeof(struct dcn30_vpg), GFP_KERNEL); + + if (!vpg3) + return NULL; + + vpg3_construct(vpg3, ctx, inst, + &vpg_regs[inst], + &vpg_shift, + &vpg_mask); + + return &vpg3->base; +} + +static struct afmt *dcn30_afmt_create( + struct dc_context *ctx, + uint32_t inst) +{ + struct dcn30_afmt *afmt3 = kzalloc(sizeof(struct dcn30_afmt), GFP_KERNEL); + + if (!afmt3) + return NULL; + + afmt3_construct(afmt3, ctx, inst, + &afmt_regs[inst], + &afmt_shift, + &afmt_mask); + + return &afmt3->base; +} + +static struct stream_encoder *dcn30_stream_encoder_create(enum engine_id eng_id, + struct dc_context *ctx) +{ + struct dcn10_stream_encoder *enc1; + struct vpg *vpg; + struct afmt *afmt; + int vpg_inst; + int afmt_inst; + + /* Mapping of VPG, AFMT, DME register blocks to DIO block instance */ + if (eng_id <= ENGINE_ID_DIGF) { + vpg_inst = eng_id; + afmt_inst = eng_id; + } else + return NULL; + + enc1 = kzalloc(sizeof(struct dcn10_stream_encoder), GFP_KERNEL); + vpg = dcn30_vpg_create(ctx, vpg_inst); + afmt = dcn30_afmt_create(ctx, afmt_inst); + + if (!enc1 || !vpg || !afmt) { + kfree(enc1); + kfree(vpg); + kfree(afmt); + return NULL; + } + + dcn30_dio_stream_encoder_construct(enc1, ctx, ctx->dc_bios, + eng_id, vpg, afmt, + &stream_enc_regs[eng_id], + &se_shift, &se_mask); + + return &enc1->base; +} + +static struct dce_hwseq *dcn30_hwseq_create(struct dc_context *ctx) +{ + struct dce_hwseq *hws = kzalloc(sizeof(struct dce_hwseq), GFP_KERNEL); + + if (hws) { + hws->ctx = ctx; + hws->regs = &hwseq_reg; + hws->shifts = &hwseq_shift; + hws->masks = &hwseq_mask; + } + return hws; +} +static const struct resource_create_funcs res_create_funcs = { + .read_dce_straps = read_dce_straps, + .create_audio = dcn30_create_audio, + .create_stream_encoder = dcn30_stream_encoder_create, + .create_hwseq = dcn30_hwseq_create, +}; + +static const struct resource_create_funcs res_create_maximus_funcs = { + .read_dce_straps = NULL, + .create_audio = NULL, + .create_stream_encoder = NULL, + .create_hwseq = dcn30_hwseq_create, +}; + +static void dcn30_resource_destruct(struct dcn30_resource_pool *pool) +{ + unsigned int i; + + for (i = 0; i < pool->base.stream_enc_count; i++) { + if (pool->base.stream_enc[i] != NULL) { + if (pool->base.stream_enc[i]->vpg != NULL) { + kfree(DCN30_VPG_FROM_VPG(pool->base.stream_enc[i]->vpg)); + pool->base.stream_enc[i]->vpg = NULL; + } + if (pool->base.stream_enc[i]->afmt != NULL) { + kfree(DCN30_AFMT_FROM_AFMT(pool->base.stream_enc[i]->afmt)); + pool->base.stream_enc[i]->afmt = NULL; + } + kfree(DCN10STRENC_FROM_STRENC(pool->base.stream_enc[i])); + pool->base.stream_enc[i] = NULL; + } + } + + for (i = 0; i < pool->base.res_cap->num_dsc; i++) { + if (pool->base.dscs[i] != NULL) + dcn20_dsc_destroy(&pool->base.dscs[i]); + } + + if (pool->base.mpc != NULL) { + kfree(TO_DCN20_MPC(pool->base.mpc)); + pool->base.mpc = NULL; + } + if (pool->base.hubbub != NULL) { + kfree(pool->base.hubbub); + pool->base.hubbub = NULL; + } + for (i = 0; i < pool->base.pipe_count; i++) { + if (pool->base.dpps[i] != NULL) + dcn30_dpp_destroy(&pool->base.dpps[i]); + + if (pool->base.ipps[i] != NULL) + pool->base.ipps[i]->funcs->ipp_destroy(&pool->base.ipps[i]); + + if (pool->base.hubps[i] != NULL) { + kfree(TO_DCN20_HUBP(pool->base.hubps[i])); + pool->base.hubps[i] = NULL; + } + + if (pool->base.irqs != NULL) { + dal_irq_service_destroy(&pool->base.irqs); + } + } + + for (i = 0; i < pool->base.res_cap->num_ddc; i++) { + if (pool->base.engines[i] != NULL) + dce110_engine_destroy(&pool->base.engines[i]); + if (pool->base.hw_i2cs[i] != NULL) { + kfree(pool->base.hw_i2cs[i]); + pool->base.hw_i2cs[i] = NULL; + } + if (pool->base.sw_i2cs[i] != NULL) { + kfree(pool->base.sw_i2cs[i]); + pool->base.sw_i2cs[i] = NULL; + } + } + + for (i = 0; i < pool->base.res_cap->num_opp; i++) { + if (pool->base.opps[i] != NULL) + pool->base.opps[i]->funcs->opp_destroy(&pool->base.opps[i]); + } + + for (i = 0; i < pool->base.res_cap->num_timing_generator; i++) { + if (pool->base.timing_generators[i] != NULL) { + kfree(DCN10TG_FROM_TG(pool->base.timing_generators[i])); + pool->base.timing_generators[i] = NULL; + } + } + + for (i = 0; i < pool->base.res_cap->num_dwb; i++) { + if (pool->base.dwbc[i] != NULL) { + kfree(TO_DCN30_DWBC(pool->base.dwbc[i])); + pool->base.dwbc[i] = NULL; + } + if (pool->base.mcif_wb[i] != NULL) { + kfree(TO_DCN30_MMHUBBUB(pool->base.mcif_wb[i])); + pool->base.mcif_wb[i] = NULL; + } + } + + for (i = 0; i < pool->base.audio_count; i++) { + if (pool->base.audios[i]) + dce_aud_destroy(&pool->base.audios[i]); + } + + for (i = 0; i < pool->base.clk_src_count; i++) { + if (pool->base.clock_sources[i] != NULL) { + dcn20_clock_source_destroy(&pool->base.clock_sources[i]); + pool->base.clock_sources[i] = NULL; + } + } + + for (i = 0; i < pool->base.res_cap->num_mpc_3dlut; i++) { + if (pool->base.mpc_lut[i] != NULL) { + dc_3dlut_func_release(pool->base.mpc_lut[i]); + pool->base.mpc_lut[i] = NULL; + } + if (pool->base.mpc_shaper[i] != NULL) { + dc_transfer_func_release(pool->base.mpc_shaper[i]); + pool->base.mpc_shaper[i] = NULL; + } + } + + if (pool->base.dp_clock_source != NULL) { + dcn20_clock_source_destroy(&pool->base.dp_clock_source); + pool->base.dp_clock_source = NULL; + } + + for (i = 0; i < pool->base.pipe_count; i++) { + if (pool->base.multiple_abms[i] != NULL) + dce_abm_destroy(&pool->base.multiple_abms[i]); + } + + if (pool->base.psr != NULL) + dmub_psr_destroy(&pool->base.psr); + + if (pool->base.dccg != NULL) + dcn_dccg_destroy(&pool->base.dccg); + + if (pool->base.oem_device != NULL) + dal_ddc_service_destroy(&pool->base.oem_device); +} + +static struct hubp *dcn30_hubp_create( + struct dc_context *ctx, + uint32_t inst) +{ + struct dcn20_hubp *hubp2 = + kzalloc(sizeof(struct dcn20_hubp), GFP_KERNEL); + + if (!hubp2) + return NULL; + + if (hubp3_construct(hubp2, ctx, inst, + &hubp_regs[inst], &hubp_shift, &hubp_mask)) + return &hubp2->base; + + BREAK_TO_DEBUGGER(); + kfree(hubp2); + return NULL; +} + +static bool dcn30_dwbc_create(struct dc_context *ctx, struct resource_pool *pool) +{ + int i; + uint32_t pipe_count = pool->res_cap->num_dwb; + + for (i = 0; i < pipe_count; i++) { + struct dcn30_dwbc *dwbc30 = kzalloc(sizeof(struct dcn30_dwbc), + GFP_KERNEL); + + if (!dwbc30) { + dm_error("DC: failed to create dwbc30!\n"); + return false; + } + + dcn30_dwbc_construct(dwbc30, ctx, + &dwbc30_regs[i], + &dwbc30_shift, + &dwbc30_mask, + i); + + pool->dwbc[i] = &dwbc30->base; + } + return true; +} + +static bool dcn30_mmhubbub_create(struct dc_context *ctx, struct resource_pool *pool) +{ + int i; + uint32_t pipe_count = pool->res_cap->num_dwb; + + for (i = 0; i < pipe_count; i++) { + struct dcn30_mmhubbub *mcif_wb30 = kzalloc(sizeof(struct dcn30_mmhubbub), + GFP_KERNEL); + + if (!mcif_wb30) { + dm_error("DC: failed to create mcif_wb30!\n"); + return false; + } + + dcn30_mmhubbub_construct(mcif_wb30, ctx, + &mcif_wb30_regs[i], + &mcif_wb30_shift, + &mcif_wb30_mask, + i); + + pool->mcif_wb[i] = &mcif_wb30->base; + } + return true; +} + +static struct display_stream_compressor *dcn30_dsc_create( + struct dc_context *ctx, uint32_t inst) +{ + struct dcn20_dsc *dsc = + kzalloc(sizeof(struct dcn20_dsc), GFP_KERNEL); + + if (!dsc) { + BREAK_TO_DEBUGGER(); + return NULL; + } + + dsc2_construct(dsc, ctx, inst, &dsc_regs[inst], &dsc_shift, &dsc_mask); + return &dsc->base; +} + +enum dc_status dcn30_add_stream_to_ctx(struct dc *dc, struct dc_state *new_ctx, struct dc_stream_state *dc_stream) +{ + + return dcn20_add_stream_to_ctx(dc, new_ctx, dc_stream); +} + +static void dcn30_destroy_resource_pool(struct resource_pool **pool) +{ + struct dcn30_resource_pool *dcn30_pool = TO_DCN30_RES_POOL(*pool); + + dcn30_resource_destruct(dcn30_pool); + kfree(dcn30_pool); + *pool = NULL; +} + +static struct clock_source *dcn30_clock_source_create( + struct dc_context *ctx, + struct dc_bios *bios, + enum clock_source_id id, + const struct dce110_clk_src_regs *regs, + bool dp_clk_src) +{ + struct dce110_clk_src *clk_src = + kzalloc(sizeof(struct dce110_clk_src), GFP_KERNEL); + + if (!clk_src) + return NULL; + + if (dcn3_clk_src_construct(clk_src, ctx, bios, id, + regs, &cs_shift, &cs_mask)) { + clk_src->base.dp_clk_src = dp_clk_src; + return &clk_src->base; + } + + BREAK_TO_DEBUGGER(); + return NULL; +} + +int dcn30_populate_dml_pipes_from_context( + struct dc *dc, struct dc_state *context, + display_e2e_pipe_params_st *pipes, + bool fast_validate) +{ + int i, pipe_cnt; + struct resource_context *res_ctx = &context->res_ctx; + + DC_FP_START(); + dcn20_populate_dml_pipes_from_context(dc, context, pipes, fast_validate); + DC_FP_END(); + + for (i = 0, pipe_cnt = 0; i < dc->res_pool->pipe_count; i++) { + if (!res_ctx->pipe_ctx[i].stream) + continue; + + pipes[pipe_cnt++].pipe.scale_ratio_depth.lb_depth = + dm_lb_16; + } + + return pipe_cnt; +} + +void dcn30_populate_dml_writeback_from_context( + struct dc *dc, struct resource_context *res_ctx, display_e2e_pipe_params_st *pipes) +{ + DC_FP_START(); + dcn30_fpu_populate_dml_writeback_from_context(dc, res_ctx, pipes); + DC_FP_END(); +} + +unsigned int dcn30_calc_max_scaled_time( + unsigned int time_per_pixel, + enum mmhubbub_wbif_mode mode, + unsigned int urgent_watermark) +{ + unsigned int time_per_byte = 0; + unsigned int total_free_entry = 0xb40; + unsigned int buf_lh_capability; + unsigned int max_scaled_time; + + if (mode == PACKED_444) /* packed mode 32 bpp */ + time_per_byte = time_per_pixel/4; + else if (mode == PACKED_444_FP16) /* packed mode 64 bpp */ + time_per_byte = time_per_pixel/8; + + if (time_per_byte == 0) + time_per_byte = 1; + + buf_lh_capability = (total_free_entry*time_per_byte*32) >> 6; /* time_per_byte is in u6.6*/ + max_scaled_time = buf_lh_capability - urgent_watermark; + return max_scaled_time; +} + +void dcn30_set_mcif_arb_params( + struct dc *dc, + struct dc_state *context, + display_e2e_pipe_params_st *pipes, + int pipe_cnt) +{ + enum mmhubbub_wbif_mode wbif_mode; + struct display_mode_lib *dml = &context->bw_ctx.dml; + struct mcif_arb_params *wb_arb_params; + int i, j, dwb_pipe; + + /* Writeback MCIF_WB arbitration parameters */ + dwb_pipe = 0; + for (i = 0; i < dc->res_pool->pipe_count; i++) { + + if (!context->res_ctx.pipe_ctx[i].stream) + continue; + + for (j = 0; j < MAX_DWB_PIPES; j++) { + struct dc_writeback_info *writeback_info = &context->res_ctx.pipe_ctx[i].stream->writeback_info[j]; + + if (writeback_info->wb_enabled == false) + continue; + + //wb_arb_params = &context->res_ctx.pipe_ctx[i].stream->writeback_info[j].mcif_arb_params; + wb_arb_params = &context->bw_ctx.bw.dcn.bw_writeback.mcif_wb_arb[dwb_pipe]; + + if (writeback_info->dwb_params.cnv_params.fc_out_format == DWB_OUT_FORMAT_64BPP_ARGB || + writeback_info->dwb_params.cnv_params.fc_out_format == DWB_OUT_FORMAT_64BPP_RGBA) + wbif_mode = PACKED_444_FP16; + else + wbif_mode = PACKED_444; + + DC_FP_START(); + dcn30_fpu_set_mcif_arb_params(wb_arb_params, dml, pipes, pipe_cnt, j); + DC_FP_END(); + wb_arb_params->time_per_pixel = (1000000 << 6) / context->res_ctx.pipe_ctx[i].stream->phy_pix_clk; /* time_per_pixel should be in u6.6 format */ + wb_arb_params->slice_lines = 32; + wb_arb_params->arbitration_slice = 2; /* irrelevant since there is no YUV output */ + wb_arb_params->max_scaled_time = dcn30_calc_max_scaled_time(wb_arb_params->time_per_pixel, + wbif_mode, + wb_arb_params->cli_watermark[0]); /* assume 4 watermark sets have the same value */ + + dwb_pipe++; + + if (dwb_pipe >= MAX_DWB_PIPES) + return; + } + if (dwb_pipe >= MAX_DWB_PIPES) + return; + } + +} + +static struct dc_cap_funcs cap_funcs = { + .get_dcc_compression_cap = dcn20_get_dcc_compression_cap +}; + +bool dcn30_acquire_post_bldn_3dlut( + struct resource_context *res_ctx, + const struct resource_pool *pool, + int mpcc_id, + struct dc_3dlut **lut, + struct dc_transfer_func **shaper) +{ + int i; + bool ret = false; + union dc_3dlut_state *state; + + ASSERT(*lut == NULL && *shaper == NULL); + *lut = NULL; + *shaper = NULL; + + for (i = 0; i < pool->res_cap->num_mpc_3dlut; i++) { + if (!res_ctx->is_mpc_3dlut_acquired[i]) { + *lut = pool->mpc_lut[i]; + *shaper = pool->mpc_shaper[i]; + state = &pool->mpc_lut[i]->state; + res_ctx->is_mpc_3dlut_acquired[i] = true; + state->bits.rmu_idx_valid = 1; + state->bits.rmu_mux_num = i; + if (state->bits.rmu_mux_num == 0) + state->bits.mpc_rmu0_mux = mpcc_id; + else if (state->bits.rmu_mux_num == 1) + state->bits.mpc_rmu1_mux = mpcc_id; + else if (state->bits.rmu_mux_num == 2) + state->bits.mpc_rmu2_mux = mpcc_id; + ret = true; + break; + } + } + return ret; +} + +bool dcn30_release_post_bldn_3dlut( + struct resource_context *res_ctx, + const struct resource_pool *pool, + struct dc_3dlut **lut, + struct dc_transfer_func **shaper) +{ + int i; + bool ret = false; + + for (i = 0; i < pool->res_cap->num_mpc_3dlut; i++) { + if (pool->mpc_lut[i] == *lut && pool->mpc_shaper[i] == *shaper) { + res_ctx->is_mpc_3dlut_acquired[i] = false; + pool->mpc_lut[i]->state.raw = 0; + *lut = NULL; + *shaper = NULL; + ret = true; + break; + } + } + return ret; +} + +static bool is_soc_bounding_box_valid(struct dc *dc) +{ + uint32_t hw_internal_rev = dc->ctx->asic_id.hw_internal_rev; + + if (ASICREV_IS_SIENNA_CICHLID_P(hw_internal_rev)) + return true; + + return false; +} + +static bool init_soc_bounding_box(struct dc *dc, + struct dcn30_resource_pool *pool) +{ + struct _vcs_dpi_soc_bounding_box_st *loaded_bb = &dcn3_0_soc; + struct _vcs_dpi_ip_params_st *loaded_ip = &dcn3_0_ip; + + DC_LOGGER_INIT(dc->ctx->logger); + + if (!is_soc_bounding_box_valid(dc)) { + DC_LOG_ERROR("%s: not valid soc bounding box\n", __func__); + return false; + } + + loaded_ip->max_num_otg = pool->base.res_cap->num_timing_generator; + loaded_ip->max_num_dpp = pool->base.pipe_count; + loaded_ip->clamp_min_dcfclk = dc->config.clamp_min_dcfclk; + dcn20_patch_bounding_box(dc, loaded_bb); + DC_FP_START(); + patch_dcn30_soc_bounding_box(dc, &dcn3_0_soc); + DC_FP_END(); + + return true; +} + +static bool dcn30_split_stream_for_mpc_or_odm( + const struct dc *dc, + struct resource_context *res_ctx, + struct pipe_ctx *pri_pipe, + struct pipe_ctx *sec_pipe, + bool odm) +{ + int pipe_idx = sec_pipe->pipe_idx; + const struct resource_pool *pool = dc->res_pool; + + *sec_pipe = *pri_pipe; + + sec_pipe->pipe_idx = pipe_idx; + sec_pipe->plane_res.mi = pool->mis[pipe_idx]; + sec_pipe->plane_res.hubp = pool->hubps[pipe_idx]; + sec_pipe->plane_res.ipp = pool->ipps[pipe_idx]; + sec_pipe->plane_res.xfm = pool->transforms[pipe_idx]; + sec_pipe->plane_res.dpp = pool->dpps[pipe_idx]; + sec_pipe->plane_res.mpcc_inst = pool->dpps[pipe_idx]->inst; + sec_pipe->stream_res.dsc = NULL; + if (odm) { + if (pri_pipe->next_odm_pipe) { + ASSERT(pri_pipe->next_odm_pipe != sec_pipe); + sec_pipe->next_odm_pipe = pri_pipe->next_odm_pipe; + sec_pipe->next_odm_pipe->prev_odm_pipe = sec_pipe; + } + if (pri_pipe->top_pipe && pri_pipe->top_pipe->next_odm_pipe) { + pri_pipe->top_pipe->next_odm_pipe->bottom_pipe = sec_pipe; + sec_pipe->top_pipe = pri_pipe->top_pipe->next_odm_pipe; + } + if (pri_pipe->bottom_pipe && pri_pipe->bottom_pipe->next_odm_pipe) { + pri_pipe->bottom_pipe->next_odm_pipe->top_pipe = sec_pipe; + sec_pipe->bottom_pipe = pri_pipe->bottom_pipe->next_odm_pipe; + } + pri_pipe->next_odm_pipe = sec_pipe; + sec_pipe->prev_odm_pipe = pri_pipe; + + if (!sec_pipe->top_pipe) + sec_pipe->stream_res.opp = pool->opps[pipe_idx]; + else + sec_pipe->stream_res.opp = sec_pipe->top_pipe->stream_res.opp; + if (sec_pipe->stream->timing.flags.DSC == 1) { + dcn20_acquire_dsc(dc, res_ctx, &sec_pipe->stream_res.dsc, pipe_idx); + ASSERT(sec_pipe->stream_res.dsc); + if (sec_pipe->stream_res.dsc == NULL) + return false; + } + } else { + if (pri_pipe->bottom_pipe) { + ASSERT(pri_pipe->bottom_pipe != sec_pipe); + sec_pipe->bottom_pipe = pri_pipe->bottom_pipe; + sec_pipe->bottom_pipe->top_pipe = sec_pipe; + } + pri_pipe->bottom_pipe = sec_pipe; + sec_pipe->top_pipe = pri_pipe; + + ASSERT(pri_pipe->plane_state); + } + + return true; +} + +static struct pipe_ctx *dcn30_find_split_pipe( + struct dc *dc, + struct dc_state *context, + int old_index) +{ + struct pipe_ctx *pipe = NULL; + int i; + + if (old_index >= 0 && context->res_ctx.pipe_ctx[old_index].stream == NULL) { + pipe = &context->res_ctx.pipe_ctx[old_index]; + pipe->pipe_idx = old_index; + } + + if (!pipe) + for (i = dc->res_pool->pipe_count - 1; i >= 0; i--) { + if (dc->current_state->res_ctx.pipe_ctx[i].top_pipe == NULL + && dc->current_state->res_ctx.pipe_ctx[i].prev_odm_pipe == NULL) { + if (context->res_ctx.pipe_ctx[i].stream == NULL) { + pipe = &context->res_ctx.pipe_ctx[i]; + pipe->pipe_idx = i; + break; + } + } + } + + /* + * May need to fix pipes getting tossed from 1 opp to another on flip + * Add for debugging transient underflow during topology updates: + * ASSERT(pipe); + */ + if (!pipe) + for (i = dc->res_pool->pipe_count - 1; i >= 0; i--) { + if (context->res_ctx.pipe_ctx[i].stream == NULL) { + pipe = &context->res_ctx.pipe_ctx[i]; + pipe->pipe_idx = i; + break; + } + } + + return pipe; +} + +noinline bool dcn30_internal_validate_bw( + struct dc *dc, + struct dc_state *context, + display_e2e_pipe_params_st *pipes, + int *pipe_cnt_out, + int *vlevel_out, + bool fast_validate, + bool allow_self_refresh_only) +{ + bool out = false; + bool repopulate_pipes = false; + int split[MAX_PIPES] = { 0 }; + bool merge[MAX_PIPES] = { false }; + bool newly_split[MAX_PIPES] = { false }; + int pipe_cnt, i, pipe_idx, vlevel; + struct vba_vars_st *vba = &context->bw_ctx.dml.vba; + + ASSERT(pipes); + if (!pipes) + return false; + + context->bw_ctx.dml.vba.maxMpcComb = 0; + context->bw_ctx.dml.vba.VoltageLevel = 0; + context->bw_ctx.dml.vba.DRAMClockChangeSupport[0][0] = dm_dram_clock_change_vactive; + dc->res_pool->funcs->update_soc_for_wm_a(dc, context); + pipe_cnt = dc->res_pool->funcs->populate_dml_pipes(dc, context, pipes, fast_validate); + + if (!pipe_cnt) { + out = true; + goto validate_out; + } + + dml_log_pipe_params(&context->bw_ctx.dml, pipes, pipe_cnt); + + if (!fast_validate || !allow_self_refresh_only) { + /* + * DML favors voltage over p-state, but we're more interested in + * supporting p-state over voltage. We can't support p-state in + * prefetch mode > 0 so try capping the prefetch mode to start. + */ + context->bw_ctx.dml.soc.allow_dram_self_refresh_or_dram_clock_change_in_vblank = + dm_allow_self_refresh_and_mclk_switch; + vlevel = dml_get_voltage_level(&context->bw_ctx.dml, pipes, pipe_cnt); + /* This may adjust vlevel and maxMpcComb */ + if (vlevel < context->bw_ctx.dml.soc.num_states) + vlevel = dcn20_validate_apply_pipe_split_flags(dc, context, vlevel, split, merge); + } + if (allow_self_refresh_only && + (fast_validate || vlevel == context->bw_ctx.dml.soc.num_states || + vba->DRAMClockChangeSupport[vlevel][vba->maxMpcComb] == dm_dram_clock_change_unsupported)) { + /* + * If mode is unsupported or there's still no p-state support + * then fall back to favoring voltage. + * + * We don't actually support prefetch mode 2, so require that we + * at least support prefetch mode 1. + */ + context->bw_ctx.dml.soc.allow_dram_self_refresh_or_dram_clock_change_in_vblank = + dm_allow_self_refresh; + + vlevel = dml_get_voltage_level(&context->bw_ctx.dml, pipes, pipe_cnt); + if (vlevel < context->bw_ctx.dml.soc.num_states) { + memset(split, 0, sizeof(split)); + memset(merge, 0, sizeof(merge)); + vlevel = dcn20_validate_apply_pipe_split_flags(dc, context, vlevel, split, merge); + } + } + + dml_log_mode_support_params(&context->bw_ctx.dml); + + if (vlevel == context->bw_ctx.dml.soc.num_states) + goto validate_fail; + + if (!dc->config.enable_windowed_mpo_odm) { + for (i = 0, pipe_idx = 0; i < dc->res_pool->pipe_count; i++) { + struct pipe_ctx *pipe = &context->res_ctx.pipe_ctx[i]; + struct pipe_ctx *mpo_pipe = pipe->bottom_pipe; + + if (!pipe->stream) + continue; + + /* We only support full screen mpo with ODM */ + if (vba->ODMCombineEnabled[vba->pipe_plane[pipe_idx]] != dm_odm_combine_mode_disabled + && pipe->plane_state && mpo_pipe + && memcmp(&mpo_pipe->plane_res.scl_data.recout, + &pipe->plane_res.scl_data.recout, + sizeof(struct rect)) != 0) { + ASSERT(mpo_pipe->plane_state != pipe->plane_state); + goto validate_fail; + } + pipe_idx++; + } + } + + /* merge pipes if necessary */ + for (i = 0; i < dc->res_pool->pipe_count; i++) { + struct pipe_ctx *pipe = &context->res_ctx.pipe_ctx[i]; + + /*skip pipes that don't need merging*/ + if (!merge[i]) + continue; + + /* if ODM merge we ignore mpc tree, mpo pipes will have their own flags */ + if (pipe->prev_odm_pipe) { + /*split off odm pipe*/ + pipe->prev_odm_pipe->next_odm_pipe = pipe->next_odm_pipe; + if (pipe->next_odm_pipe) + pipe->next_odm_pipe->prev_odm_pipe = pipe->prev_odm_pipe; + + pipe->bottom_pipe = NULL; + pipe->next_odm_pipe = NULL; + pipe->plane_state = NULL; + pipe->stream = NULL; + pipe->top_pipe = NULL; + pipe->prev_odm_pipe = NULL; + if (pipe->stream_res.dsc) + dcn20_release_dsc(&context->res_ctx, dc->res_pool, &pipe->stream_res.dsc); + memset(&pipe->plane_res, 0, sizeof(pipe->plane_res)); + memset(&pipe->stream_res, 0, sizeof(pipe->stream_res)); + repopulate_pipes = true; + } else if (pipe->top_pipe && pipe->top_pipe->plane_state == pipe->plane_state) { + struct pipe_ctx *top_pipe = pipe->top_pipe; + struct pipe_ctx *bottom_pipe = pipe->bottom_pipe; + + top_pipe->bottom_pipe = bottom_pipe; + if (bottom_pipe) + bottom_pipe->top_pipe = top_pipe; + + pipe->top_pipe = NULL; + pipe->bottom_pipe = NULL; + pipe->plane_state = NULL; + pipe->stream = NULL; + memset(&pipe->plane_res, 0, sizeof(pipe->plane_res)); + memset(&pipe->stream_res, 0, sizeof(pipe->stream_res)); + repopulate_pipes = true; + } else + ASSERT(0); /* Should never try to merge master pipe */ + + } + + for (i = 0, pipe_idx = -1; i < dc->res_pool->pipe_count; i++) { + struct pipe_ctx *pipe = &context->res_ctx.pipe_ctx[i]; + struct pipe_ctx *old_pipe = &dc->current_state->res_ctx.pipe_ctx[i]; + struct pipe_ctx *hsplit_pipe = NULL; + bool odm; + int old_index = -1; + + if (!pipe->stream || newly_split[i]) + continue; + + pipe_idx++; + odm = vba->ODMCombineEnabled[vba->pipe_plane[pipe_idx]] != dm_odm_combine_mode_disabled; + + if (!pipe->plane_state && !odm) + continue; + + if (split[i]) { + if (odm) { + if (split[i] == 4 && old_pipe->next_odm_pipe && old_pipe->next_odm_pipe->next_odm_pipe) + old_index = old_pipe->next_odm_pipe->next_odm_pipe->pipe_idx; + else if (old_pipe->next_odm_pipe) + old_index = old_pipe->next_odm_pipe->pipe_idx; + } else { + if (split[i] == 4 && old_pipe->bottom_pipe && old_pipe->bottom_pipe->bottom_pipe && + old_pipe->bottom_pipe->bottom_pipe->plane_state == old_pipe->plane_state) + old_index = old_pipe->bottom_pipe->bottom_pipe->pipe_idx; + else if (old_pipe->bottom_pipe && + old_pipe->bottom_pipe->plane_state == old_pipe->plane_state) + old_index = old_pipe->bottom_pipe->pipe_idx; + } + hsplit_pipe = dcn30_find_split_pipe(dc, context, old_index); + ASSERT(hsplit_pipe); + if (!hsplit_pipe) + goto validate_fail; + + if (!dcn30_split_stream_for_mpc_or_odm( + dc, &context->res_ctx, + pipe, hsplit_pipe, odm)) + goto validate_fail; + + newly_split[hsplit_pipe->pipe_idx] = true; + repopulate_pipes = true; + } + if (split[i] == 4) { + struct pipe_ctx *pipe_4to1; + + if (odm && old_pipe->next_odm_pipe) + old_index = old_pipe->next_odm_pipe->pipe_idx; + else if (!odm && old_pipe->bottom_pipe && + old_pipe->bottom_pipe->plane_state == old_pipe->plane_state) + old_index = old_pipe->bottom_pipe->pipe_idx; + else + old_index = -1; + pipe_4to1 = dcn30_find_split_pipe(dc, context, old_index); + ASSERT(pipe_4to1); + if (!pipe_4to1) + goto validate_fail; + if (!dcn30_split_stream_for_mpc_or_odm( + dc, &context->res_ctx, + pipe, pipe_4to1, odm)) + goto validate_fail; + newly_split[pipe_4to1->pipe_idx] = true; + + if (odm && old_pipe->next_odm_pipe && old_pipe->next_odm_pipe->next_odm_pipe + && old_pipe->next_odm_pipe->next_odm_pipe->next_odm_pipe) + old_index = old_pipe->next_odm_pipe->next_odm_pipe->next_odm_pipe->pipe_idx; + else if (!odm && old_pipe->bottom_pipe && old_pipe->bottom_pipe->bottom_pipe && + old_pipe->bottom_pipe->bottom_pipe->bottom_pipe && + old_pipe->bottom_pipe->bottom_pipe->bottom_pipe->plane_state == old_pipe->plane_state) + old_index = old_pipe->bottom_pipe->bottom_pipe->bottom_pipe->pipe_idx; + else + old_index = -1; + pipe_4to1 = dcn30_find_split_pipe(dc, context, old_index); + ASSERT(pipe_4to1); + if (!pipe_4to1) + goto validate_fail; + if (!dcn30_split_stream_for_mpc_or_odm( + dc, &context->res_ctx, + hsplit_pipe, pipe_4to1, odm)) + goto validate_fail; + newly_split[pipe_4to1->pipe_idx] = true; + } + if (odm) + dcn20_build_mapped_resource(dc, context, pipe->stream); + } + + for (i = 0; i < dc->res_pool->pipe_count; i++) { + struct pipe_ctx *pipe = &context->res_ctx.pipe_ctx[i]; + + if (pipe->plane_state) { + if (!resource_build_scaling_params(pipe)) + goto validate_fail; + } + } + + /* Actual dsc count per stream dsc validation*/ + if (!dcn20_validate_dsc(dc, context)) { + vba->ValidationStatus[vba->soc.num_states] = DML_FAIL_DSC_VALIDATION_FAILURE; + goto validate_fail; + } + + if (repopulate_pipes) + pipe_cnt = dc->res_pool->funcs->populate_dml_pipes(dc, context, pipes, fast_validate); + context->bw_ctx.dml.vba.VoltageLevel = vlevel; + *vlevel_out = vlevel; + *pipe_cnt_out = pipe_cnt; + + out = true; + goto validate_out; + +validate_fail: + out = false; + +validate_out: + return out; +} + +static int get_refresh_rate(struct dc_state *context) +{ + int refresh_rate = 0; + int h_v_total = 0; + struct dc_crtc_timing *timing = NULL; + + if (context == NULL || context->streams[0] == NULL) + return 0; + + /* check if refresh rate at least 120hz */ + timing = &context->streams[0]->timing; + if (timing == NULL) + return 0; + + h_v_total = timing->h_total * timing->v_total; + if (h_v_total == 0) + return 0; + + refresh_rate = ((timing->pix_clk_100hz * 100) / (h_v_total)) + 1; + return refresh_rate; +} + +#define MAX_STRETCHED_V_BLANK 500 // in micro-seconds +/* + * Scaling factor for v_blank stretch calculations considering timing in + * micro-seconds and pixel clock in 100hz. + * Note: the parenthesis are necessary to ensure the correct order of + * operation where V_SCALE is used. + */ +#define V_SCALE (10000 / MAX_STRETCHED_V_BLANK) + +static int get_frame_rate_at_max_stretch_100hz(struct dc_state *context) +{ + struct dc_crtc_timing *timing = NULL; + uint32_t sec_per_100_lines; + uint32_t max_v_blank; + uint32_t curr_v_blank; + uint32_t v_stretch_max; + uint32_t stretched_frame_pix_cnt; + uint32_t scaled_stretched_frame_pix_cnt; + uint32_t scaled_refresh_rate; + + if (context == NULL || context->streams[0] == NULL) + return 0; + + /* check if refresh rate at least 120hz */ + timing = &context->streams[0]->timing; + if (timing == NULL) + return 0; + + sec_per_100_lines = timing->pix_clk_100hz / timing->h_total + 1; + max_v_blank = sec_per_100_lines / V_SCALE + 1; + curr_v_blank = timing->v_total - timing->v_addressable; + v_stretch_max = (max_v_blank > curr_v_blank) ? (max_v_blank - curr_v_blank) : (0); + stretched_frame_pix_cnt = (v_stretch_max + timing->v_total) * timing->h_total; + scaled_stretched_frame_pix_cnt = stretched_frame_pix_cnt / 10000; + scaled_refresh_rate = (timing->pix_clk_100hz) / scaled_stretched_frame_pix_cnt + 1; + + return scaled_refresh_rate; +} + +static bool is_refresh_rate_support_mclk_switch_using_fw_based_vblank_stretch(struct dc_state *context) +{ + int refresh_rate_max_stretch_100hz; + int min_refresh_100hz; + + if (context == NULL || context->streams[0] == NULL) + return false; + + refresh_rate_max_stretch_100hz = get_frame_rate_at_max_stretch_100hz(context); + min_refresh_100hz = context->streams[0]->timing.min_refresh_in_uhz / 10000; + + if (refresh_rate_max_stretch_100hz < min_refresh_100hz) + return false; + + return true; +} + +bool dcn30_can_support_mclk_switch_using_fw_based_vblank_stretch(struct dc *dc, struct dc_state *context) +{ + int refresh_rate = 0; + const int minimum_refreshrate_supported = 120; + + if (context == NULL || context->streams[0] == NULL) + return false; + + if (context->streams[0]->sink->edid_caps.panel_patch.disable_fams) + return false; + + if (dc->debug.disable_fams) + return false; + + if (!dc->caps.dmub_caps.mclk_sw) + return false; + + if (context->bw_ctx.bw.dcn.clk.fw_based_mclk_switching_shut_down) + return false; + + /* more then 1 monitor connected */ + if (context->stream_count != 1) + return false; + + refresh_rate = get_refresh_rate(context); + if (refresh_rate < minimum_refreshrate_supported) + return false; + + if (!is_refresh_rate_support_mclk_switch_using_fw_based_vblank_stretch(context)) + return false; + + // check if freesync enabled + if (!context->streams[0]->allow_freesync) + return false; + + if (context->streams[0]->vrr_active_variable) + return false; + + return true; +} + +/* + * set up FPO watermarks, pstate, dram latency + */ +void dcn30_setup_mclk_switch_using_fw_based_vblank_stretch(struct dc *dc, struct dc_state *context) +{ + ASSERT(dc != NULL && context != NULL); + if (dc == NULL || context == NULL) + return; + + /* Set wm_a.pstate so high natural MCLK switches are impossible: 4 seconds */ + context->bw_ctx.bw.dcn.watermarks.a.cstate_pstate.pstate_change_ns = 4U * 1000U * 1000U * 1000U; +} + +void dcn30_update_soc_for_wm_a(struct dc *dc, struct dc_state *context) +{ + DC_FP_START(); + dcn30_fpu_update_soc_for_wm_a(dc, context); + DC_FP_END(); +} + +void dcn30_calculate_wm_and_dlg( + struct dc *dc, struct dc_state *context, + display_e2e_pipe_params_st *pipes, + int pipe_cnt, + int vlevel) +{ + DC_FP_START(); + dcn30_fpu_calculate_wm_and_dlg(dc, context, pipes, pipe_cnt, vlevel); + DC_FP_END(); +} + +bool dcn30_validate_bandwidth(struct dc *dc, + struct dc_state *context, + bool fast_validate) +{ + bool out = false; + + BW_VAL_TRACE_SETUP(); + + int vlevel = 0; + int pipe_cnt = 0; + display_e2e_pipe_params_st *pipes = kzalloc(dc->res_pool->pipe_count * sizeof(display_e2e_pipe_params_st), GFP_KERNEL); + DC_LOGGER_INIT(dc->ctx->logger); + + BW_VAL_TRACE_COUNT(); + + DC_FP_START(); + out = dcn30_internal_validate_bw(dc, context, pipes, &pipe_cnt, &vlevel, fast_validate, true); + DC_FP_END(); + + if (pipe_cnt == 0) + goto validate_out; + + if (!out) + goto validate_fail; + + BW_VAL_TRACE_END_VOLTAGE_LEVEL(); + + if (fast_validate) { + BW_VAL_TRACE_SKIP(fast); + goto validate_out; + } + + DC_FP_START(); + dc->res_pool->funcs->calculate_wm_and_dlg(dc, context, pipes, pipe_cnt, vlevel); + DC_FP_END(); + + BW_VAL_TRACE_END_WATERMARKS(); + + goto validate_out; + +validate_fail: + DC_LOG_WARNING("Mode Validation Warning: %s failed validation.\n", + dml_get_status_message(context->bw_ctx.dml.vba.ValidationStatus[context->bw_ctx.dml.vba.soc.num_states])); + + BW_VAL_TRACE_SKIP(fail); + out = false; + +validate_out: + kfree(pipes); + + BW_VAL_TRACE_FINISH(); + + return out; +} + +void dcn30_update_bw_bounding_box(struct dc *dc, struct clk_bw_params *bw_params) +{ + unsigned int i, j; + unsigned int num_states = 0; + + unsigned int dcfclk_mhz[DC__VOLTAGE_STATES] = {0}; + unsigned int dram_speed_mts[DC__VOLTAGE_STATES] = {0}; + unsigned int optimal_uclk_for_dcfclk_sta_targets[DC__VOLTAGE_STATES] = {0}; + unsigned int optimal_dcfclk_for_uclk[DC__VOLTAGE_STATES] = {0}; + + unsigned int dcfclk_sta_targets[DC__VOLTAGE_STATES] = {694, 875, 1000, 1200}; + unsigned int num_dcfclk_sta_targets = 4; + unsigned int num_uclk_states; + + struct dc_bounding_box_max_clk dcn30_bb_max_clk; + + memset(&dcn30_bb_max_clk, 0, sizeof(dcn30_bb_max_clk)); + + if (dc->ctx->dc_bios->vram_info.num_chans) + dcn3_0_soc.num_chans = dc->ctx->dc_bios->vram_info.num_chans; + + DC_FP_START(); + dcn30_fpu_update_dram_channel_width_bytes(dc); + DC_FP_END(); + + if (bw_params->clk_table.entries[0].memclk_mhz) { + + for (i = 0; i < MAX_NUM_DPM_LVL; i++) { + if (bw_params->clk_table.entries[i].dcfclk_mhz > dcn30_bb_max_clk.max_dcfclk_mhz) + dcn30_bb_max_clk.max_dcfclk_mhz = bw_params->clk_table.entries[i].dcfclk_mhz; + if (bw_params->clk_table.entries[i].dispclk_mhz > dcn30_bb_max_clk.max_dispclk_mhz) + dcn30_bb_max_clk.max_dispclk_mhz = bw_params->clk_table.entries[i].dispclk_mhz; + if (bw_params->clk_table.entries[i].dppclk_mhz > dcn30_bb_max_clk.max_dppclk_mhz) + dcn30_bb_max_clk.max_dppclk_mhz = bw_params->clk_table.entries[i].dppclk_mhz; + if (bw_params->clk_table.entries[i].phyclk_mhz > dcn30_bb_max_clk.max_phyclk_mhz) + dcn30_bb_max_clk.max_phyclk_mhz = bw_params->clk_table.entries[i].phyclk_mhz; + } + + DC_FP_START(); + dcn30_fpu_update_max_clk(&dcn30_bb_max_clk); + DC_FP_END(); + + if (dcn30_bb_max_clk.max_dcfclk_mhz > dcfclk_sta_targets[num_dcfclk_sta_targets-1]) { + // If max DCFCLK is greater than the max DCFCLK STA target, insert into the DCFCLK STA target array + dcfclk_sta_targets[num_dcfclk_sta_targets] = dcn30_bb_max_clk.max_dcfclk_mhz; + num_dcfclk_sta_targets++; + } else if (dcn30_bb_max_clk.max_dcfclk_mhz < dcfclk_sta_targets[num_dcfclk_sta_targets-1]) { + // If max DCFCLK is less than the max DCFCLK STA target, cap values and remove duplicates + for (i = 0; i < num_dcfclk_sta_targets; i++) { + if (dcfclk_sta_targets[i] > dcn30_bb_max_clk.max_dcfclk_mhz) { + dcfclk_sta_targets[i] = dcn30_bb_max_clk.max_dcfclk_mhz; + break; + } + } + // Update size of array since we "removed" duplicates + num_dcfclk_sta_targets = i + 1; + } + + num_uclk_states = bw_params->clk_table.num_entries; + + // Calculate optimal dcfclk for each uclk + for (i = 0; i < num_uclk_states; i++) { + DC_FP_START(); + dcn30_fpu_get_optimal_dcfclk_fclk_for_uclk(bw_params->clk_table.entries[i].memclk_mhz * 16, + &optimal_dcfclk_for_uclk[i], NULL); + DC_FP_END(); + if (optimal_dcfclk_for_uclk[i] < bw_params->clk_table.entries[0].dcfclk_mhz) { + optimal_dcfclk_for_uclk[i] = bw_params->clk_table.entries[0].dcfclk_mhz; + } + } + + // Calculate optimal uclk for each dcfclk sta target + for (i = 0; i < num_dcfclk_sta_targets; i++) { + for (j = 0; j < num_uclk_states; j++) { + if (dcfclk_sta_targets[i] < optimal_dcfclk_for_uclk[j]) { + optimal_uclk_for_dcfclk_sta_targets[i] = + bw_params->clk_table.entries[j].memclk_mhz * 16; + break; + } + } + } + + i = 0; + j = 0; + // create the final dcfclk and uclk table + while (i < num_dcfclk_sta_targets && j < num_uclk_states && num_states < DC__VOLTAGE_STATES) { + if (dcfclk_sta_targets[i] < optimal_dcfclk_for_uclk[j] && i < num_dcfclk_sta_targets) { + dcfclk_mhz[num_states] = dcfclk_sta_targets[i]; + dram_speed_mts[num_states++] = optimal_uclk_for_dcfclk_sta_targets[i++]; + } else { + if (j < num_uclk_states && optimal_dcfclk_for_uclk[j] <= dcn30_bb_max_clk.max_dcfclk_mhz) { + dcfclk_mhz[num_states] = optimal_dcfclk_for_uclk[j]; + dram_speed_mts[num_states++] = bw_params->clk_table.entries[j++].memclk_mhz * 16; + } else { + j = num_uclk_states; + } + } + } + + while (i < num_dcfclk_sta_targets && num_states < DC__VOLTAGE_STATES) { + dcfclk_mhz[num_states] = dcfclk_sta_targets[i]; + dram_speed_mts[num_states++] = optimal_uclk_for_dcfclk_sta_targets[i++]; + } + + while (j < num_uclk_states && num_states < DC__VOLTAGE_STATES && + optimal_dcfclk_for_uclk[j] <= dcn30_bb_max_clk.max_dcfclk_mhz) { + dcfclk_mhz[num_states] = optimal_dcfclk_for_uclk[j]; + dram_speed_mts[num_states++] = bw_params->clk_table.entries[j++].memclk_mhz * 16; + } + + dcn3_0_soc.num_states = num_states; + DC_FP_START(); + dcn30_fpu_update_bw_bounding_box(dc, bw_params, &dcn30_bb_max_clk, dcfclk_mhz, dram_speed_mts); + DC_FP_END(); + } +} + +static void dcn30_get_panel_config_defaults(struct dc_panel_config *panel_config) +{ + *panel_config = panel_config_defaults; +} + +static const struct resource_funcs dcn30_res_pool_funcs = { + .destroy = dcn30_destroy_resource_pool, + .link_enc_create = dcn30_link_encoder_create, + .panel_cntl_create = dcn30_panel_cntl_create, + .validate_bandwidth = dcn30_validate_bandwidth, + .calculate_wm_and_dlg = dcn30_calculate_wm_and_dlg, + .update_soc_for_wm_a = dcn30_update_soc_for_wm_a, + .populate_dml_pipes = dcn30_populate_dml_pipes_from_context, + .acquire_idle_pipe_for_layer = dcn20_acquire_idle_pipe_for_layer, + .add_stream_to_ctx = dcn30_add_stream_to_ctx, + .add_dsc_to_stream_resource = dcn20_add_dsc_to_stream_resource, + .remove_stream_from_ctx = dcn20_remove_stream_from_ctx, + .populate_dml_writeback_from_context = dcn30_populate_dml_writeback_from_context, + .set_mcif_arb_params = dcn30_set_mcif_arb_params, + .find_first_free_match_stream_enc_for_link = dcn10_find_first_free_match_stream_enc_for_link, + .acquire_post_bldn_3dlut = dcn30_acquire_post_bldn_3dlut, + .release_post_bldn_3dlut = dcn30_release_post_bldn_3dlut, + .update_bw_bounding_box = dcn30_update_bw_bounding_box, + .patch_unknown_plane_state = dcn20_patch_unknown_plane_state, + .get_panel_config_defaults = dcn30_get_panel_config_defaults, +}; + +#define CTX ctx + +#define REG(reg_name) \ + (DCN_BASE.instance[0].segment[mm ## reg_name ## _BASE_IDX] + mm ## reg_name) + +static uint32_t read_pipe_fuses(struct dc_context *ctx) +{ + uint32_t value = REG_READ(CC_DC_PIPE_DIS); + /* Support for max 6 pipes */ + value = value & 0x3f; + return value; +} + +static bool dcn30_resource_construct( + uint8_t num_virtual_links, + struct dc *dc, + struct dcn30_resource_pool *pool) +{ + int i; + struct dc_context *ctx = dc->ctx; + struct irq_service_init_data init_data; + struct ddc_service_init_data ddc_init_data = {0}; + uint32_t pipe_fuses = read_pipe_fuses(ctx); + uint32_t num_pipes = 0; + + if (!(pipe_fuses == 0 || pipe_fuses == 0x3e)) { + BREAK_TO_DEBUGGER(); + dm_error("DC: Unexpected fuse recipe for navi2x !\n"); + /* fault to single pipe */ + pipe_fuses = 0x3e; + } + + DC_FP_START(); + + ctx->dc_bios->regs = &bios_regs; + + pool->base.res_cap = &res_cap_dcn3; + + pool->base.funcs = &dcn30_res_pool_funcs; + + /************************************************* + * Resource + asic cap harcoding * + *************************************************/ + pool->base.underlay_pipe_index = NO_UNDERLAY_PIPE; + pool->base.pipe_count = pool->base.res_cap->num_timing_generator; + pool->base.mpcc_count = pool->base.res_cap->num_timing_generator; + dc->caps.max_downscale_ratio = 600; + dc->caps.i2c_speed_in_khz = 100; + dc->caps.i2c_speed_in_khz_hdcp = 100; /*1.4 w/a not applied by default*/ + dc->caps.max_cursor_size = 256; + dc->caps.min_horizontal_blanking_period = 80; + dc->caps.dmdata_alloc_size = 2048; + dc->caps.mall_size_per_mem_channel = 8; + /* total size = mall per channel * num channels * 1024 * 1024 */ + dc->caps.mall_size_total = dc->caps.mall_size_per_mem_channel * dc->ctx->dc_bios->vram_info.num_chans * 1048576; + dc->caps.cursor_cache_size = dc->caps.max_cursor_size * dc->caps.max_cursor_size * 8; + + dc->caps.max_slave_planes = 2; + dc->caps.max_slave_yuv_planes = 2; + dc->caps.max_slave_rgb_planes = 2; + dc->caps.post_blend_color_processing = true; + dc->caps.force_dp_tps4_for_cp2520 = true; + dc->caps.extended_aux_timeout_support = true; + dc->caps.dmcub_support = true; + + /* Color pipeline capabilities */ + dc->caps.color.dpp.dcn_arch = 1; + dc->caps.color.dpp.input_lut_shared = 0; + dc->caps.color.dpp.icsc = 1; + dc->caps.color.dpp.dgam_ram = 0; // must use gamma_corr + dc->caps.color.dpp.dgam_rom_caps.srgb = 1; + dc->caps.color.dpp.dgam_rom_caps.bt2020 = 1; + dc->caps.color.dpp.dgam_rom_caps.gamma2_2 = 1; + dc->caps.color.dpp.dgam_rom_caps.pq = 1; + dc->caps.color.dpp.dgam_rom_caps.hlg = 1; + dc->caps.color.dpp.post_csc = 1; + dc->caps.color.dpp.gamma_corr = 1; + dc->caps.color.dpp.dgam_rom_for_yuv = 0; + + dc->caps.color.dpp.hw_3d_lut = 1; + dc->caps.color.dpp.ogam_ram = 1; + // no OGAM ROM on DCN3 + dc->caps.color.dpp.ogam_rom_caps.srgb = 0; + dc->caps.color.dpp.ogam_rom_caps.bt2020 = 0; + dc->caps.color.dpp.ogam_rom_caps.gamma2_2 = 0; + dc->caps.color.dpp.ogam_rom_caps.pq = 0; + dc->caps.color.dpp.ogam_rom_caps.hlg = 0; + dc->caps.color.dpp.ocsc = 0; + + dc->caps.color.mpc.gamut_remap = 1; + dc->caps.color.mpc.num_3dluts = pool->base.res_cap->num_mpc_3dlut; //3 + dc->caps.color.mpc.ogam_ram = 1; + dc->caps.color.mpc.ogam_rom_caps.srgb = 0; + dc->caps.color.mpc.ogam_rom_caps.bt2020 = 0; + dc->caps.color.mpc.ogam_rom_caps.gamma2_2 = 0; + dc->caps.color.mpc.ogam_rom_caps.pq = 0; + dc->caps.color.mpc.ogam_rom_caps.hlg = 0; + dc->caps.color.mpc.ocsc = 1; + + dc->caps.dp_hdmi21_pcon_support = true; + + /* read VBIOS LTTPR caps */ + { + if (ctx->dc_bios->funcs->get_lttpr_caps) { + enum bp_result bp_query_result; + uint8_t is_vbios_lttpr_enable = 0; + + bp_query_result = ctx->dc_bios->funcs->get_lttpr_caps(ctx->dc_bios, &is_vbios_lttpr_enable); + dc->caps.vbios_lttpr_enable = (bp_query_result == BP_RESULT_OK) && !!is_vbios_lttpr_enable; + } + + if (ctx->dc_bios->funcs->get_lttpr_interop) { + enum bp_result bp_query_result; + uint8_t is_vbios_interop_enabled = 0; + + bp_query_result = ctx->dc_bios->funcs->get_lttpr_interop(ctx->dc_bios, + &is_vbios_interop_enabled); + dc->caps.vbios_lttpr_aware = (bp_query_result == BP_RESULT_OK) && !!is_vbios_interop_enabled; + } + } + + if (dc->ctx->dce_environment == DCE_ENV_PRODUCTION_DRV) + dc->debug = debug_defaults_drv; + else if (dc->ctx->dce_environment == DCE_ENV_FPGA_MAXIMUS) { + dc->debug = debug_defaults_diags; + } else + dc->debug = debug_defaults_diags; + // Init the vm_helper + if (dc->vm_helper) + vm_helper_init(dc->vm_helper, 16); + + /************************************************* + * Create resources * + *************************************************/ + + /* Clock Sources for Pixel Clock*/ + pool->base.clock_sources[DCN30_CLK_SRC_PLL0] = + dcn30_clock_source_create(ctx, ctx->dc_bios, + CLOCK_SOURCE_COMBO_PHY_PLL0, + &clk_src_regs[0], false); + pool->base.clock_sources[DCN30_CLK_SRC_PLL1] = + dcn30_clock_source_create(ctx, ctx->dc_bios, + CLOCK_SOURCE_COMBO_PHY_PLL1, + &clk_src_regs[1], false); + pool->base.clock_sources[DCN30_CLK_SRC_PLL2] = + dcn30_clock_source_create(ctx, ctx->dc_bios, + CLOCK_SOURCE_COMBO_PHY_PLL2, + &clk_src_regs[2], false); + pool->base.clock_sources[DCN30_CLK_SRC_PLL3] = + dcn30_clock_source_create(ctx, ctx->dc_bios, + CLOCK_SOURCE_COMBO_PHY_PLL3, + &clk_src_regs[3], false); + pool->base.clock_sources[DCN30_CLK_SRC_PLL4] = + dcn30_clock_source_create(ctx, ctx->dc_bios, + CLOCK_SOURCE_COMBO_PHY_PLL4, + &clk_src_regs[4], false); + pool->base.clock_sources[DCN30_CLK_SRC_PLL5] = + dcn30_clock_source_create(ctx, ctx->dc_bios, + CLOCK_SOURCE_COMBO_PHY_PLL5, + &clk_src_regs[5], false); + + pool->base.clk_src_count = DCN30_CLK_SRC_TOTAL; + + /* todo: not reuse phy_pll registers */ + pool->base.dp_clock_source = + dcn30_clock_source_create(ctx, ctx->dc_bios, + CLOCK_SOURCE_ID_DP_DTO, + &clk_src_regs[0], true); + + for (i = 0; i < pool->base.clk_src_count; i++) { + if (pool->base.clock_sources[i] == NULL) { + dm_error("DC: failed to create clock sources!\n"); + BREAK_TO_DEBUGGER(); + goto create_fail; + } + } + + /* DCCG */ + pool->base.dccg = dccg30_create(ctx, &dccg_regs, &dccg_shift, &dccg_mask); + if (pool->base.dccg == NULL) { + dm_error("DC: failed to create dccg!\n"); + BREAK_TO_DEBUGGER(); + goto create_fail; + } + + /* PP Lib and SMU interfaces */ + init_soc_bounding_box(dc, pool); + + num_pipes = dcn3_0_ip.max_num_dpp; + + for (i = 0; i < dcn3_0_ip.max_num_dpp; i++) + if (pipe_fuses & 1 << i) + num_pipes--; + + dcn3_0_ip.max_num_dpp = num_pipes; + dcn3_0_ip.max_num_otg = num_pipes; + + dml_init_instance(&dc->dml, &dcn3_0_soc, &dcn3_0_ip, DML_PROJECT_DCN30); + + /* IRQ */ + init_data.ctx = dc->ctx; + pool->base.irqs = dal_irq_service_dcn30_create(&init_data); + if (!pool->base.irqs) + goto create_fail; + + /* HUBBUB */ + pool->base.hubbub = dcn30_hubbub_create(ctx); + if (pool->base.hubbub == NULL) { + BREAK_TO_DEBUGGER(); + dm_error("DC: failed to create hubbub!\n"); + goto create_fail; + } + + /* HUBPs, DPPs, OPPs and TGs */ + for (i = 0; i < pool->base.pipe_count; i++) { + pool->base.hubps[i] = dcn30_hubp_create(ctx, i); + if (pool->base.hubps[i] == NULL) { + BREAK_TO_DEBUGGER(); + dm_error( + "DC: failed to create hubps!\n"); + goto create_fail; + } + + pool->base.dpps[i] = dcn30_dpp_create(ctx, i); + if (pool->base.dpps[i] == NULL) { + BREAK_TO_DEBUGGER(); + dm_error( + "DC: failed to create dpps!\n"); + goto create_fail; + } + } + + for (i = 0; i < pool->base.res_cap->num_opp; i++) { + pool->base.opps[i] = dcn30_opp_create(ctx, i); + if (pool->base.opps[i] == NULL) { + BREAK_TO_DEBUGGER(); + dm_error( + "DC: failed to create output pixel processor!\n"); + goto create_fail; + } + } + + for (i = 0; i < pool->base.res_cap->num_timing_generator; i++) { + pool->base.timing_generators[i] = dcn30_timing_generator_create( + ctx, i); + if (pool->base.timing_generators[i] == NULL) { + BREAK_TO_DEBUGGER(); + dm_error("DC: failed to create tg!\n"); + goto create_fail; + } + } + pool->base.timing_generator_count = i; + /* PSR */ + pool->base.psr = dmub_psr_create(ctx); + + if (pool->base.psr == NULL) { + dm_error("DC: failed to create PSR obj!\n"); + BREAK_TO_DEBUGGER(); + goto create_fail; + } + + /* ABM */ + for (i = 0; i < pool->base.res_cap->num_timing_generator; i++) { + pool->base.multiple_abms[i] = dmub_abm_create(ctx, + &abm_regs[i], + &abm_shift, + &abm_mask); + if (pool->base.multiple_abms[i] == NULL) { + dm_error("DC: failed to create abm for pipe %d!\n", i); + BREAK_TO_DEBUGGER(); + goto create_fail; + } + } + /* MPC and DSC */ + pool->base.mpc = dcn30_mpc_create(ctx, pool->base.mpcc_count, pool->base.res_cap->num_mpc_3dlut); + if (pool->base.mpc == NULL) { + BREAK_TO_DEBUGGER(); + dm_error("DC: failed to create mpc!\n"); + goto create_fail; + } + + for (i = 0; i < pool->base.res_cap->num_dsc; i++) { + pool->base.dscs[i] = dcn30_dsc_create(ctx, i); + if (pool->base.dscs[i] == NULL) { + BREAK_TO_DEBUGGER(); + dm_error("DC: failed to create display stream compressor %d!\n", i); + goto create_fail; + } + } + + /* DWB and MMHUBBUB */ + if (!dcn30_dwbc_create(ctx, &pool->base)) { + BREAK_TO_DEBUGGER(); + dm_error("DC: failed to create dwbc!\n"); + goto create_fail; + } + + if (!dcn30_mmhubbub_create(ctx, &pool->base)) { + BREAK_TO_DEBUGGER(); + dm_error("DC: failed to create mcif_wb!\n"); + goto create_fail; + } + + /* AUX and I2C */ + for (i = 0; i < pool->base.res_cap->num_ddc; i++) { + pool->base.engines[i] = dcn30_aux_engine_create(ctx, i); + if (pool->base.engines[i] == NULL) { + BREAK_TO_DEBUGGER(); + dm_error( + "DC:failed to create aux engine!!\n"); + goto create_fail; + } + pool->base.hw_i2cs[i] = dcn30_i2c_hw_create(ctx, i); + if (pool->base.hw_i2cs[i] == NULL) { + BREAK_TO_DEBUGGER(); + dm_error( + "DC:failed to create hw i2c!!\n"); + goto create_fail; + } + pool->base.sw_i2cs[i] = NULL; + } + + /* Audio, Stream Encoders including DIG and virtual, MPC 3D LUTs */ + if (!resource_construct(num_virtual_links, dc, &pool->base, + (!IS_FPGA_MAXIMUS_DC(dc->ctx->dce_environment) ? + &res_create_funcs : &res_create_maximus_funcs))) + goto create_fail; + + /* HW Sequencer and Plane caps */ + dcn30_hw_sequencer_construct(dc); + + dc->caps.max_planes = pool->base.pipe_count; + + for (i = 0; i < dc->caps.max_planes; ++i) + dc->caps.planes[i] = plane_cap; + + dc->cap_funcs = cap_funcs; + + if (dc->ctx->dc_bios->fw_info.oem_i2c_present) { + ddc_init_data.ctx = dc->ctx; + ddc_init_data.link = NULL; + ddc_init_data.id.id = dc->ctx->dc_bios->fw_info.oem_i2c_obj_id; + ddc_init_data.id.enum_id = 0; + ddc_init_data.id.type = OBJECT_TYPE_GENERIC; + pool->base.oem_device = dal_ddc_service_create(&ddc_init_data); + } else { + pool->base.oem_device = NULL; + } + + DC_FP_END(); + + return true; + +create_fail: + + DC_FP_END(); + dcn30_resource_destruct(pool); + + return false; +} + +struct resource_pool *dcn30_create_resource_pool( + const struct dc_init_data *init_data, + struct dc *dc) +{ + struct dcn30_resource_pool *pool = + kzalloc(sizeof(struct dcn30_resource_pool), GFP_KERNEL); + + if (!pool) + return NULL; + + if (dcn30_resource_construct(init_data->num_virtual_links, dc, pool)) + return &pool->base; + + BREAK_TO_DEBUGGER(); + kfree(pool); + return NULL; +} diff --git a/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_resource.h b/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_resource.h new file mode 100644 index 000000000..8e6b8b736 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_resource.h @@ -0,0 +1,108 @@ +/* + * Copyright 2020 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 _DCN30_RESOURCE_H_ +#define _DCN30_RESOURCE_H_ + +#include "core_types.h" + +#define TO_DCN30_RES_POOL(pool)\ + container_of(pool, struct dcn30_resource_pool, base) + +struct dc; +struct resource_pool; +struct _vcs_dpi_display_pipe_params_st; + +extern struct _vcs_dpi_ip_params_st dcn3_0_ip; +extern struct _vcs_dpi_soc_bounding_box_st dcn3_0_soc; + +struct dcn30_resource_pool { + struct resource_pool base; +}; +struct resource_pool *dcn30_create_resource_pool( + const struct dc_init_data *init_data, + struct dc *dc); + +void dcn30_set_mcif_arb_params( + struct dc *dc, + struct dc_state *context, + display_e2e_pipe_params_st *pipes, + int pipe_cnt); + +unsigned int dcn30_calc_max_scaled_time( + unsigned int time_per_pixel, + enum mmhubbub_wbif_mode mode, + unsigned int urgent_watermark); + +bool dcn30_validate_bandwidth(struct dc *dc, struct dc_state *context, + bool fast_validate); +bool dcn30_internal_validate_bw( + struct dc *dc, + struct dc_state *context, + display_e2e_pipe_params_st *pipes, + int *pipe_cnt_out, + int *vlevel_out, + bool fast_validate, + bool allow_self_refresh_only); +void dcn30_calculate_wm_and_dlg( + struct dc *dc, struct dc_state *context, + display_e2e_pipe_params_st *pipes, + int pipe_cnt, + int vlevel); +void dcn30_update_soc_for_wm_a(struct dc *dc, struct dc_state *context); +void dcn30_populate_dml_writeback_from_context( + struct dc *dc, struct resource_context *res_ctx, display_e2e_pipe_params_st *pipes); + +int dcn30_populate_dml_pipes_from_context( + struct dc *dc, struct dc_state *context, + display_e2e_pipe_params_st *pipes, + bool fast_validate); + +bool dcn30_acquire_post_bldn_3dlut( + struct resource_context *res_ctx, + const struct resource_pool *pool, + int mpcc_id, + struct dc_3dlut **lut, + struct dc_transfer_func **shaper); + +bool dcn30_release_post_bldn_3dlut( + struct resource_context *res_ctx, + const struct resource_pool *pool, + struct dc_3dlut **lut, + struct dc_transfer_func **shaper); + +enum dc_status dcn30_add_stream_to_ctx( + struct dc *dc, + struct dc_state *new_ctx, + struct dc_stream_state *dc_stream); + +void dcn30_update_bw_bounding_box(struct dc *dc, struct clk_bw_params *bw_params); + +bool dcn30_can_support_mclk_switch_using_fw_based_vblank_stretch(struct dc *dc, struct dc_state *context); +void dcn30_setup_mclk_switch_using_fw_based_vblank_stretch(struct dc *dc, struct dc_state *context); +int dcn30_find_dummy_latency_index_for_fw_based_mclk_switch(struct dc *dc, struct dc_state *context, + display_e2e_pipe_params_st *pipes, int pipe_cnt, int vlevel); + +#endif /* _DCN30_RESOURCE_H_ */ diff --git a/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_vpg.c b/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_vpg.c new file mode 100644 index 000000000..14bc44b1f --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_vpg.c @@ -0,0 +1,264 @@ +/* + * Copyright 2020 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 "dc_bios_types.h" +#include "dcn30_vpg.h" +#include "reg_helper.h" + +#define DC_LOGGER \ + vpg3->base.ctx->logger + +#define REG(reg)\ + (vpg3->regs->reg) + +#undef FN +#define FN(reg_name, field_name) \ + vpg3->vpg_shift->field_name, vpg3->vpg_mask->field_name + + +#define CTX \ + vpg3->base.ctx + + +void vpg3_update_generic_info_packet( + struct vpg *vpg, + uint32_t packet_index, + const struct dc_info_packet *info_packet, + bool immediate_update) +{ + struct dcn30_vpg *vpg3 = DCN30_VPG_FROM_VPG(vpg); + uint32_t i; + + /* TODOFPGA Figure out a proper number for max_retries polling for lock + * use 50 for now. + */ + uint32_t max_retries = 50; + + if (packet_index > 14) + ASSERT(0); + + /* poll dig_update_lock is not locked -> asic internal signal + * assume otg master lock will unlock it + */ + /* REG_WAIT(AFMT_VBI_PACKET_CONTROL, AFMT_GENERIC_LOCK_STATUS, + * 0, 10, max_retries); + */ + + /* TODO: Check if this is required */ + /* check if HW reading GSP memory */ + REG_WAIT(VPG_GENERIC_STATUS, VPG_GENERIC_CONFLICT_OCCURED, + 0, 10, max_retries); + + /* HW does is not reading GSP memory not reading too long -> + * something wrong. clear GPS memory access and notify? + * hw SW is writing to GSP memory + */ + REG_UPDATE(VPG_GENERIC_STATUS, VPG_GENERIC_CONFLICT_CLR, 1); + + /* choose which generic packet to use */ + REG_UPDATE(VPG_GENERIC_PACKET_ACCESS_CTRL, + VPG_GENERIC_DATA_INDEX, packet_index*9); + + /* write generic packet header + * (4th byte is for GENERIC0 only) + */ + REG_SET_4(VPG_GENERIC_PACKET_DATA, 0, + VPG_GENERIC_DATA_BYTE0, info_packet->hb0, + VPG_GENERIC_DATA_BYTE1, info_packet->hb1, + VPG_GENERIC_DATA_BYTE2, info_packet->hb2, + VPG_GENERIC_DATA_BYTE3, info_packet->hb3); + + /* write generic packet contents + * (we never use last 4 bytes) + * there are 8 (0-7) mmDIG0_AFMT_GENERIC0_x registers + */ + { + const uint32_t *content = + (const uint32_t *) &info_packet->sb[0]; + + for (i = 0; i < 8; i++) { + REG_WRITE(VPG_GENERIC_PACKET_DATA, *content++); + } + } + + /* atomically update double-buffered GENERIC0 registers in immediate mode + * (update at next block_update when block_update_lock == 0). + */ + if (immediate_update) { + switch (packet_index) { + case 0: + REG_UPDATE(VPG_GSP_IMMEDIATE_UPDATE_CTRL, + VPG_GENERIC0_IMMEDIATE_UPDATE, 1); + break; + case 1: + REG_UPDATE(VPG_GSP_IMMEDIATE_UPDATE_CTRL, + VPG_GENERIC1_IMMEDIATE_UPDATE, 1); + break; + case 2: + REG_UPDATE(VPG_GSP_IMMEDIATE_UPDATE_CTRL, + VPG_GENERIC2_IMMEDIATE_UPDATE, 1); + break; + case 3: + REG_UPDATE(VPG_GSP_IMMEDIATE_UPDATE_CTRL, + VPG_GENERIC3_IMMEDIATE_UPDATE, 1); + break; + case 4: + REG_UPDATE(VPG_GSP_IMMEDIATE_UPDATE_CTRL, + VPG_GENERIC4_IMMEDIATE_UPDATE, 1); + break; + case 5: + REG_UPDATE(VPG_GSP_IMMEDIATE_UPDATE_CTRL, + VPG_GENERIC5_IMMEDIATE_UPDATE, 1); + break; + case 6: + REG_UPDATE(VPG_GSP_IMMEDIATE_UPDATE_CTRL, + VPG_GENERIC6_IMMEDIATE_UPDATE, 1); + break; + case 7: + REG_UPDATE(VPG_GSP_IMMEDIATE_UPDATE_CTRL, + VPG_GENERIC7_IMMEDIATE_UPDATE, 1); + break; + case 8: + REG_UPDATE(VPG_GSP_IMMEDIATE_UPDATE_CTRL, + VPG_GENERIC8_IMMEDIATE_UPDATE, 1); + break; + case 9: + REG_UPDATE(VPG_GSP_IMMEDIATE_UPDATE_CTRL, + VPG_GENERIC9_IMMEDIATE_UPDATE, 1); + break; + case 10: + REG_UPDATE(VPG_GSP_IMMEDIATE_UPDATE_CTRL, + VPG_GENERIC10_IMMEDIATE_UPDATE, 1); + break; + case 11: + REG_UPDATE(VPG_GSP_IMMEDIATE_UPDATE_CTRL, + VPG_GENERIC11_IMMEDIATE_UPDATE, 1); + break; + case 12: + REG_UPDATE(VPG_GSP_IMMEDIATE_UPDATE_CTRL, + VPG_GENERIC12_IMMEDIATE_UPDATE, 1); + break; + case 13: + REG_UPDATE(VPG_GSP_IMMEDIATE_UPDATE_CTRL, + VPG_GENERIC13_IMMEDIATE_UPDATE, 1); + break; + case 14: + REG_UPDATE(VPG_GSP_IMMEDIATE_UPDATE_CTRL, + VPG_GENERIC14_IMMEDIATE_UPDATE, 1); + break; + default: + break; + } + } else { + switch (packet_index) { + case 0: + REG_UPDATE(VPG_GSP_FRAME_UPDATE_CTRL, + VPG_GENERIC0_FRAME_UPDATE, 1); + break; + case 1: + REG_UPDATE(VPG_GSP_FRAME_UPDATE_CTRL, + VPG_GENERIC1_FRAME_UPDATE, 1); + break; + case 2: + REG_UPDATE(VPG_GSP_FRAME_UPDATE_CTRL, + VPG_GENERIC2_FRAME_UPDATE, 1); + break; + case 3: + REG_UPDATE(VPG_GSP_FRAME_UPDATE_CTRL, + VPG_GENERIC3_FRAME_UPDATE, 1); + break; + case 4: + REG_UPDATE(VPG_GSP_FRAME_UPDATE_CTRL, + VPG_GENERIC4_FRAME_UPDATE, 1); + break; + case 5: + REG_UPDATE(VPG_GSP_FRAME_UPDATE_CTRL, + VPG_GENERIC5_FRAME_UPDATE, 1); + break; + case 6: + REG_UPDATE(VPG_GSP_FRAME_UPDATE_CTRL, + VPG_GENERIC6_FRAME_UPDATE, 1); + break; + case 7: + REG_UPDATE(VPG_GSP_FRAME_UPDATE_CTRL, + VPG_GENERIC7_FRAME_UPDATE, 1); + break; + case 8: + REG_UPDATE(VPG_GSP_FRAME_UPDATE_CTRL, + VPG_GENERIC8_FRAME_UPDATE, 1); + break; + case 9: + REG_UPDATE(VPG_GSP_FRAME_UPDATE_CTRL, + VPG_GENERIC9_FRAME_UPDATE, 1); + break; + case 10: + REG_UPDATE(VPG_GSP_FRAME_UPDATE_CTRL, + VPG_GENERIC10_FRAME_UPDATE, 1); + break; + case 11: + REG_UPDATE(VPG_GSP_FRAME_UPDATE_CTRL, + VPG_GENERIC11_FRAME_UPDATE, 1); + break; + case 12: + REG_UPDATE(VPG_GSP_FRAME_UPDATE_CTRL, + VPG_GENERIC12_FRAME_UPDATE, 1); + break; + case 13: + REG_UPDATE(VPG_GSP_FRAME_UPDATE_CTRL, + VPG_GENERIC13_FRAME_UPDATE, 1); + break; + case 14: + REG_UPDATE(VPG_GSP_FRAME_UPDATE_CTRL, + VPG_GENERIC14_FRAME_UPDATE, 1); + break; + + default: + break; + } + + } +} + +static struct vpg_funcs dcn30_vpg_funcs = { + .update_generic_info_packet = vpg3_update_generic_info_packet, +}; + +void vpg3_construct(struct dcn30_vpg *vpg3, + struct dc_context *ctx, + uint32_t inst, + const struct dcn30_vpg_registers *vpg_regs, + const struct dcn30_vpg_shift *vpg_shift, + const struct dcn30_vpg_mask *vpg_mask) +{ + vpg3->base.ctx = ctx; + + vpg3->base.inst = inst; + vpg3->base.funcs = &dcn30_vpg_funcs; + + vpg3->regs = vpg_regs; + vpg3->vpg_shift = vpg_shift; + vpg3->vpg_mask = vpg_mask; +} diff --git a/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_vpg.h b/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_vpg.h new file mode 100644 index 000000000..ed9a5549c --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_vpg.h @@ -0,0 +1,178 @@ +/* + * Copyright 2020 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 __DAL_DCN30_VPG_H__ +#define __DAL_DCN30_VPG_H__ + + +#define DCN30_VPG_FROM_VPG(vpg)\ + container_of(vpg, struct dcn30_vpg, base) + +#define VPG_DCN3_REG_LIST(id) \ + SRI(VPG_GENERIC_STATUS, VPG, id), \ + SRI(VPG_GENERIC_PACKET_ACCESS_CTRL, VPG, id), \ + SRI(VPG_GENERIC_PACKET_DATA, VPG, id), \ + SRI(VPG_GSP_FRAME_UPDATE_CTRL, VPG, id), \ + SRI(VPG_GSP_IMMEDIATE_UPDATE_CTRL, VPG, id) + +struct dcn30_vpg_registers { + uint32_t VPG_GENERIC_STATUS; + uint32_t VPG_GENERIC_PACKET_ACCESS_CTRL; + uint32_t VPG_GENERIC_PACKET_DATA; + uint32_t VPG_GSP_FRAME_UPDATE_CTRL; + uint32_t VPG_GSP_IMMEDIATE_UPDATE_CTRL; +}; + +#define DCN3_VPG_MASK_SH_LIST(mask_sh)\ + SE_SF(VPG0_VPG_GENERIC_STATUS, VPG_GENERIC_CONFLICT_OCCURED, mask_sh),\ + SE_SF(VPG0_VPG_GENERIC_STATUS, VPG_GENERIC_CONFLICT_CLR, mask_sh),\ + SE_SF(VPG0_VPG_GENERIC_PACKET_ACCESS_CTRL, VPG_GENERIC_DATA_INDEX, mask_sh),\ + SE_SF(VPG0_VPG_GENERIC_PACKET_DATA, VPG_GENERIC_DATA_BYTE0, mask_sh),\ + SE_SF(VPG0_VPG_GENERIC_PACKET_DATA, VPG_GENERIC_DATA_BYTE1, mask_sh),\ + SE_SF(VPG0_VPG_GENERIC_PACKET_DATA, VPG_GENERIC_DATA_BYTE2, mask_sh),\ + SE_SF(VPG0_VPG_GENERIC_PACKET_DATA, VPG_GENERIC_DATA_BYTE3, mask_sh),\ + SE_SF(VPG0_VPG_GSP_FRAME_UPDATE_CTRL, VPG_GENERIC0_FRAME_UPDATE, mask_sh),\ + SE_SF(VPG0_VPG_GSP_FRAME_UPDATE_CTRL, VPG_GENERIC1_FRAME_UPDATE, mask_sh),\ + SE_SF(VPG0_VPG_GSP_FRAME_UPDATE_CTRL, VPG_GENERIC2_FRAME_UPDATE, mask_sh),\ + SE_SF(VPG0_VPG_GSP_FRAME_UPDATE_CTRL, VPG_GENERIC3_FRAME_UPDATE, mask_sh),\ + SE_SF(VPG0_VPG_GSP_FRAME_UPDATE_CTRL, VPG_GENERIC4_FRAME_UPDATE, mask_sh),\ + SE_SF(VPG0_VPG_GSP_FRAME_UPDATE_CTRL, VPG_GENERIC5_FRAME_UPDATE, mask_sh),\ + SE_SF(VPG0_VPG_GSP_FRAME_UPDATE_CTRL, VPG_GENERIC6_FRAME_UPDATE, mask_sh),\ + SE_SF(VPG0_VPG_GSP_FRAME_UPDATE_CTRL, VPG_GENERIC7_FRAME_UPDATE, mask_sh),\ + SE_SF(VPG0_VPG_GSP_FRAME_UPDATE_CTRL, VPG_GENERIC8_FRAME_UPDATE, mask_sh),\ + SE_SF(VPG0_VPG_GSP_FRAME_UPDATE_CTRL, VPG_GENERIC9_FRAME_UPDATE, mask_sh),\ + SE_SF(VPG0_VPG_GSP_FRAME_UPDATE_CTRL, VPG_GENERIC10_FRAME_UPDATE, mask_sh),\ + SE_SF(VPG0_VPG_GSP_FRAME_UPDATE_CTRL, VPG_GENERIC11_FRAME_UPDATE, mask_sh),\ + SE_SF(VPG0_VPG_GSP_FRAME_UPDATE_CTRL, VPG_GENERIC12_FRAME_UPDATE, mask_sh),\ + SE_SF(VPG0_VPG_GSP_FRAME_UPDATE_CTRL, VPG_GENERIC13_FRAME_UPDATE, mask_sh),\ + SE_SF(VPG0_VPG_GSP_FRAME_UPDATE_CTRL, VPG_GENERIC14_FRAME_UPDATE, mask_sh),\ + SE_SF(VPG0_VPG_GSP_IMMEDIATE_UPDATE_CTRL, VPG_GENERIC0_IMMEDIATE_UPDATE, mask_sh),\ + SE_SF(VPG0_VPG_GSP_IMMEDIATE_UPDATE_CTRL, VPG_GENERIC1_IMMEDIATE_UPDATE, mask_sh),\ + SE_SF(VPG0_VPG_GSP_IMMEDIATE_UPDATE_CTRL, VPG_GENERIC2_IMMEDIATE_UPDATE, mask_sh),\ + SE_SF(VPG0_VPG_GSP_IMMEDIATE_UPDATE_CTRL, VPG_GENERIC3_IMMEDIATE_UPDATE, mask_sh),\ + SE_SF(VPG0_VPG_GSP_IMMEDIATE_UPDATE_CTRL, VPG_GENERIC4_IMMEDIATE_UPDATE, mask_sh),\ + SE_SF(VPG0_VPG_GSP_IMMEDIATE_UPDATE_CTRL, VPG_GENERIC5_IMMEDIATE_UPDATE, mask_sh),\ + SE_SF(VPG0_VPG_GSP_IMMEDIATE_UPDATE_CTRL, VPG_GENERIC6_IMMEDIATE_UPDATE, mask_sh),\ + SE_SF(VPG0_VPG_GSP_IMMEDIATE_UPDATE_CTRL, VPG_GENERIC7_IMMEDIATE_UPDATE, mask_sh),\ + SE_SF(VPG0_VPG_GSP_IMMEDIATE_UPDATE_CTRL, VPG_GENERIC8_IMMEDIATE_UPDATE, mask_sh),\ + SE_SF(VPG0_VPG_GSP_IMMEDIATE_UPDATE_CTRL, VPG_GENERIC9_IMMEDIATE_UPDATE, mask_sh),\ + SE_SF(VPG0_VPG_GSP_IMMEDIATE_UPDATE_CTRL, VPG_GENERIC10_IMMEDIATE_UPDATE, mask_sh),\ + SE_SF(VPG0_VPG_GSP_IMMEDIATE_UPDATE_CTRL, VPG_GENERIC11_IMMEDIATE_UPDATE, mask_sh),\ + SE_SF(VPG0_VPG_GSP_IMMEDIATE_UPDATE_CTRL, VPG_GENERIC12_IMMEDIATE_UPDATE, mask_sh),\ + SE_SF(VPG0_VPG_GSP_IMMEDIATE_UPDATE_CTRL, VPG_GENERIC13_IMMEDIATE_UPDATE, mask_sh),\ + SE_SF(VPG0_VPG_GSP_IMMEDIATE_UPDATE_CTRL, VPG_GENERIC14_IMMEDIATE_UPDATE, mask_sh) + +#define VPG_DCN3_REG_FIELD_LIST(type) \ + type VPG_GENERIC_CONFLICT_OCCURED;\ + type VPG_GENERIC_CONFLICT_CLR;\ + type VPG_GENERIC_DATA_INDEX;\ + type VPG_GENERIC_DATA_BYTE0;\ + type VPG_GENERIC_DATA_BYTE1;\ + type VPG_GENERIC_DATA_BYTE2;\ + type VPG_GENERIC_DATA_BYTE3;\ + type VPG_GENERIC0_FRAME_UPDATE;\ + type VPG_GENERIC1_FRAME_UPDATE;\ + type VPG_GENERIC2_FRAME_UPDATE;\ + type VPG_GENERIC3_FRAME_UPDATE;\ + type VPG_GENERIC4_FRAME_UPDATE;\ + type VPG_GENERIC5_FRAME_UPDATE;\ + type VPG_GENERIC6_FRAME_UPDATE;\ + type VPG_GENERIC7_FRAME_UPDATE;\ + type VPG_GENERIC8_FRAME_UPDATE;\ + type VPG_GENERIC9_FRAME_UPDATE;\ + type VPG_GENERIC10_FRAME_UPDATE;\ + type VPG_GENERIC11_FRAME_UPDATE;\ + type VPG_GENERIC12_FRAME_UPDATE;\ + type VPG_GENERIC13_FRAME_UPDATE;\ + type VPG_GENERIC14_FRAME_UPDATE;\ + type VPG_GENERIC0_IMMEDIATE_UPDATE;\ + type VPG_GENERIC1_IMMEDIATE_UPDATE;\ + type VPG_GENERIC2_IMMEDIATE_UPDATE;\ + type VPG_GENERIC3_IMMEDIATE_UPDATE;\ + type VPG_GENERIC4_IMMEDIATE_UPDATE;\ + type VPG_GENERIC5_IMMEDIATE_UPDATE;\ + type VPG_GENERIC6_IMMEDIATE_UPDATE;\ + type VPG_GENERIC7_IMMEDIATE_UPDATE;\ + type VPG_GENERIC8_IMMEDIATE_UPDATE;\ + type VPG_GENERIC9_IMMEDIATE_UPDATE;\ + type VPG_GENERIC10_IMMEDIATE_UPDATE;\ + type VPG_GENERIC11_IMMEDIATE_UPDATE;\ + type VPG_GENERIC12_IMMEDIATE_UPDATE;\ + type VPG_GENERIC13_IMMEDIATE_UPDATE;\ + type VPG_GENERIC14_IMMEDIATE_UPDATE + + +struct dcn30_vpg_shift { + VPG_DCN3_REG_FIELD_LIST(uint8_t); +}; + +struct dcn30_vpg_mask { + VPG_DCN3_REG_FIELD_LIST(uint32_t); +}; + +struct vpg; + +struct vpg_funcs { + void (*update_generic_info_packet)( + struct vpg *vpg, + uint32_t packet_index, + const struct dc_info_packet *info_packet, + bool immediate_update); + + void (*vpg_poweron)( + struct vpg *vpg); + + void (*vpg_powerdown)( + struct vpg *vpg); +}; + +struct vpg { + const struct vpg_funcs *funcs; + struct dc_context *ctx; + int inst; +}; + +struct dcn30_vpg { + struct vpg base; + const struct dcn30_vpg_registers *regs; + const struct dcn30_vpg_shift *vpg_shift; + const struct dcn30_vpg_mask *vpg_mask; +}; + +void vpg3_update_generic_info_packet( + struct vpg *vpg, + uint32_t packet_index, + const struct dc_info_packet *info_packet, + bool immediate_update); + +void vpg3_construct(struct dcn30_vpg *vpg3, + struct dc_context *ctx, + uint32_t inst, + const struct dcn30_vpg_registers *vpg_regs, + const struct dcn30_vpg_shift *vpg_shift, + const struct dcn30_vpg_mask *vpg_mask); + + +#endif |