From 061bfa06a42a9f6cd192bae61a4bf0e746eccb39 Mon Sep 17 00:00:00 2001 From: Harry Wentland Date: Mon, 8 May 2017 15:20:38 -0400 Subject: [PATCH] drm/amdgpu/display: Add dml support for DCN Display mode lib handles clock, watermark, and bandwidth calculations for DCN. Signed-off-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dml/Makefile | 22 + .../gpu/drm/amd/display/dc/dml/dc_features.h | 557 ++++ .../amd/display/dc/dml/display_mode_enums.h | 111 + .../drm/amd/display/dc/dml/display_mode_lib.c | 147 ++ .../drm/amd/display/dc/dml/display_mode_lib.h | 52 + .../amd/display/dc/dml/display_mode_structs.h | 429 +++ .../amd/display/dc/dml/display_mode_support.c | 2326 +++++++++++++++++ .../amd/display/dc/dml/display_mode_support.h | 199 ++ .../amd/display/dc/dml/display_pipe_clocks.c | 367 +++ .../amd/display/dc/dml/display_pipe_clocks.h | 41 + .../amd/display/dc/dml/display_rq_dlg_calc.c | 2254 ++++++++++++++++ .../amd/display/dc/dml/display_rq_dlg_calc.h | 139 + .../display/dc/dml/display_rq_dlg_helpers.c | 320 +++ .../display/dc/dml/display_rq_dlg_helpers.h | 66 + .../amd/display/dc/dml/display_watermark.c | 1281 +++++++++ .../amd/display/dc/dml/display_watermark.h | 98 + .../drm/amd/display/dc/dml/dml_common_defs.c | 148 ++ .../drm/amd/display/dc/dml/dml_common_defs.h | 51 + .../drm/amd/display/dc/dml/soc_bounding_box.c | 73 + .../drm/amd/display/dc/dml/soc_bounding_box.h | 36 + 20 files changed, 8717 insertions(+) create mode 100644 drivers/gpu/drm/amd/display/dc/dml/Makefile create mode 100644 drivers/gpu/drm/amd/display/dc/dml/dc_features.h create mode 100644 drivers/gpu/drm/amd/display/dc/dml/display_mode_enums.h create mode 100644 drivers/gpu/drm/amd/display/dc/dml/display_mode_lib.c create mode 100644 drivers/gpu/drm/amd/display/dc/dml/display_mode_lib.h create mode 100644 drivers/gpu/drm/amd/display/dc/dml/display_mode_structs.h create mode 100644 drivers/gpu/drm/amd/display/dc/dml/display_mode_support.c create mode 100644 drivers/gpu/drm/amd/display/dc/dml/display_mode_support.h create mode 100644 drivers/gpu/drm/amd/display/dc/dml/display_pipe_clocks.c create mode 100644 drivers/gpu/drm/amd/display/dc/dml/display_pipe_clocks.h create mode 100644 drivers/gpu/drm/amd/display/dc/dml/display_rq_dlg_calc.c create mode 100644 drivers/gpu/drm/amd/display/dc/dml/display_rq_dlg_calc.h create mode 100644 drivers/gpu/drm/amd/display/dc/dml/display_rq_dlg_helpers.c create mode 100644 drivers/gpu/drm/amd/display/dc/dml/display_rq_dlg_helpers.h create mode 100644 drivers/gpu/drm/amd/display/dc/dml/display_watermark.c create mode 100644 drivers/gpu/drm/amd/display/dc/dml/display_watermark.h create mode 100644 drivers/gpu/drm/amd/display/dc/dml/dml_common_defs.c create mode 100644 drivers/gpu/drm/amd/display/dc/dml/dml_common_defs.h create mode 100644 drivers/gpu/drm/amd/display/dc/dml/soc_bounding_box.c create mode 100644 drivers/gpu/drm/amd/display/dc/dml/soc_bounding_box.h diff --git a/drivers/gpu/drm/amd/display/dc/dml/Makefile b/drivers/gpu/drm/amd/display/dc/dml/Makefile new file mode 100644 index 000000000000..9d7791d00e97 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/dml/Makefile @@ -0,0 +1,22 @@ +# +# Makefile for the 'utils' sub-component of DAL. +# It provides the general basic services required by other DAL +# subcomponents. + +CFLAGS_display_mode_lib.o := -mhard-float -msse -mpreferred-stack-boundary=4 +CFLAGS_display_pipe_clocks.o := -mhard-float -msse -mpreferred-stack-boundary=4 +CFLAGS_display_rq_dlg_calc.o := -mhard-float -msse -mpreferred-stack-boundary=4 +CFLAGS_display_rq_dlg_helpers.o := -mhard-float -msse -mpreferred-stack-boundary=4 +CFLAGS_display_watermark.o := -mhard-float -msse -mpreferred-stack-boundary=4 +CFLAGS_soc_bounding_box.o := -mhard-float -msse -mpreferred-stack-boundary=4 +CFLAGS_dml_common_defs.o := -mhard-float -msse -mpreferred-stack-boundary=4 +CFLAGS_display_mode_support.o := -mhard-float -msse -mpreferred-stack-boundary=4 + + +DML = display_mode_lib.o display_pipe_clocks.o display_rq_dlg_calc.o \ + display_rq_dlg_helpers.o display_watermark.o \ + soc_bounding_box.o dml_common_defs.o display_mode_support.o + +AMD_DAL_DML = $(addprefix $(AMDDALPATH)/dc/dml/,$(DML)) + +AMD_DISPLAY_FILES += $(AMD_DAL_DML) diff --git a/drivers/gpu/drm/amd/display/dc/dml/dc_features.h b/drivers/gpu/drm/amd/display/dc/dml/dc_features.h new file mode 100644 index 000000000000..745c04cb764a --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/dml/dc_features.h @@ -0,0 +1,557 @@ +/* + * Copyright 2017 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_FEATURES_H__ +#define __DC_FEATURES_H__ + +#define DC__PRESENT 1 +#define DC__PRESENT__1 1 +#define DC__NUM_DPP 4 +#define DC__NUM_DPP__4 1 +#define DC__NUM_DPP__0_PRESENT 1 +#define DC__NUM_DPP__1_PRESENT 1 +#define DC__NUM_DPP__2_PRESENT 1 +#define DC__NUM_DPP__3_PRESENT 1 +#define DC__NUM_DPP__MAX 8 +#define DC__NUM_DPP__MAX__8 1 +#define DC__PIPE_10BIT 0 +#define DC__PIPE_10BIT__0 1 +#define DC__PIPE_10BIT__MAX 1 +#define DC__PIPE_10BIT__MAX__1 1 +#define DC__NUM_OPP 4 +#define DC__NUM_OPP__4 1 +#define DC__NUM_OPP__0_PRESENT 1 +#define DC__NUM_OPP__1_PRESENT 1 +#define DC__NUM_OPP__2_PRESENT 1 +#define DC__NUM_OPP__3_PRESENT 1 +#define DC__NUM_OPP__MAX 6 +#define DC__NUM_OPP__MAX__6 1 +#define DC__NUM_DSC 0 +#define DC__NUM_DSC__0 1 +#define DC__NUM_DSC__MAX 6 +#define DC__NUM_DSC__MAX__6 1 +#define DC__NUM_ABM 1 +#define DC__NUM_ABM__1 1 +#define DC__NUM_ABM__0_PRESENT 1 +#define DC__NUM_ABM__MAX 2 +#define DC__NUM_ABM__MAX__2 1 +#define DC__ODM_PRESENT 0 +#define DC__ODM_PRESENT__0 1 +#define DC__NUM_OTG 4 +#define DC__NUM_OTG__4 1 +#define DC__NUM_OTG__0_PRESENT 1 +#define DC__NUM_OTG__1_PRESENT 1 +#define DC__NUM_OTG__2_PRESENT 1 +#define DC__NUM_OTG__3_PRESENT 1 +#define DC__NUM_OTG__MAX 6 +#define DC__NUM_OTG__MAX__6 1 +#define DC__NUM_DWB 2 +#define DC__NUM_DWB__2 1 +#define DC__NUM_DWB__0_PRESENT 1 +#define DC__NUM_DWB__1_PRESENT 1 +#define DC__NUM_DWB__MAX 2 +#define DC__NUM_DWB__MAX__2 1 +#define DC__NUM_DIG 4 +#define DC__NUM_DIG__4 1 +#define DC__NUM_DIG__0_PRESENT 1 +#define DC__NUM_DIG__1_PRESENT 1 +#define DC__NUM_DIG__2_PRESENT 1 +#define DC__NUM_DIG__3_PRESENT 1 +#define DC__NUM_DIG__MAX 6 +#define DC__NUM_DIG__MAX__6 1 +#define DC__NUM_AUX 4 +#define DC__NUM_AUX__4 1 +#define DC__NUM_AUX__0_PRESENT 1 +#define DC__NUM_AUX__1_PRESENT 1 +#define DC__NUM_AUX__2_PRESENT 1 +#define DC__NUM_AUX__3_PRESENT 1 +#define DC__NUM_AUX__MAX 6 +#define DC__NUM_AUX__MAX__6 1 +#define DC__NUM_AUDIO_STREAMS 4 +#define DC__NUM_AUDIO_STREAMS__4 1 +#define DC__NUM_AUDIO_STREAMS__0_PRESENT 1 +#define DC__NUM_AUDIO_STREAMS__1_PRESENT 1 +#define DC__NUM_AUDIO_STREAMS__2_PRESENT 1 +#define DC__NUM_AUDIO_STREAMS__3_PRESENT 1 +#define DC__NUM_AUDIO_STREAMS__MAX 8 +#define DC__NUM_AUDIO_STREAMS__MAX__8 1 +#define DC__NUM_AUDIO_ENDPOINTS 6 +#define DC__NUM_AUDIO_ENDPOINTS__6 1 +#define DC__NUM_AUDIO_ENDPOINTS__0_PRESENT 1 +#define DC__NUM_AUDIO_ENDPOINTS__1_PRESENT 1 +#define DC__NUM_AUDIO_ENDPOINTS__2_PRESENT 1 +#define DC__NUM_AUDIO_ENDPOINTS__3_PRESENT 1 +#define DC__NUM_AUDIO_ENDPOINTS__4_PRESENT 1 +#define DC__NUM_AUDIO_ENDPOINTS__5_PRESENT 1 +#define DC__NUM_AUDIO_ENDPOINTS__MAX 8 +#define DC__NUM_AUDIO_ENDPOINTS__MAX__8 1 +#define DC__NUM_AUDIO_INPUT_STREAMS 0 +#define DC__NUM_AUDIO_INPUT_STREAMS__0 1 +#define DC__NUM_AUDIO_INPUT_STREAMS__MAX 8 +#define DC__NUM_AUDIO_INPUT_STREAMS__MAX__8 1 +#define DC__NUM_AUDIO_INPUT_ENDPOINTS 0 +#define DC__NUM_AUDIO_INPUT_ENDPOINTS__0 1 +#define DC__NUM_AUDIO_INPUT_ENDPOINTS__MAX 8 +#define DC__NUM_AUDIO_INPUT_ENDPOINTS__MAX__8 1 +#define DC__NUM_CURSOR 1 +#define DC__NUM_CURSOR__1 1 +#define DC__NUM_CURSOR__0_PRESENT 1 +#define DC__NUM_CURSOR__MAX 2 +#define DC__NUM_CURSOR__MAX__2 1 +#define DC__DIGITAL_BYPASS_PRESENT 0 +#define DC__DIGITAL_BYPASS_PRESENT__0 1 +#define DC__HCID_HWMAJVER 1 +#define DC__HCID_HWMAJVER__1 1 +#define DC__HCID_HWMINVER 0 +#define DC__HCID_HWMINVER__0 1 +#define DC__HCID_HWREV 0 +#define DC__HCID_HWREV__0 1 +#define DC__ROMSTRAP_PRESENT 0 +#define DC__ROMSTRAP_PRESENT__0 1 +#define DC__NUM_RBBMIF_DECODES 30 +#define DC__NUM_RBBMIF_DECODES__30 1 +#define DC__NUM_DBG_REGS 36 +#define DC__NUM_DBG_REGS__36 1 +#define DC__NUM_PIPES_UNDERLAY 0 +#define DC__NUM_PIPES_UNDERLAY__0 1 +#define DC__NUM_PIPES_UNDERLAY__MAX 2 +#define DC__NUM_PIPES_UNDERLAY__MAX__2 1 +#define DC__NUM_VCE_ENGINE 1 +#define DC__NUM_VCE_ENGINE__1 1 +#define DC__NUM_VCE_ENGINE__0_PRESENT 1 +#define DC__NUM_VCE_ENGINE__MAX 2 +#define DC__NUM_VCE_ENGINE__MAX__2 1 +#define DC__OTG_EXTERNAL_SYNC_PRESENT 0 +#define DC__OTG_EXTERNAL_SYNC_PRESENT__0 1 +#define DC__OTG_CRC_PRESENT 1 +#define DC__OTG_CRC_PRESENT__1 1 +#define DC__VIP_PRESENT 0 +#define DC__VIP_PRESENT__0 1 +#define DC__DTMTEST_PRESENT 0 +#define DC__DTMTEST_PRESENT__0 1 +#define DC__POWER_GATE_PRESENT 1 +#define DC__POWER_GATE_PRESENT__1 1 +#define DC__MEM_PG 1 +#define DC__MEM_PG__1 1 +#define DC__FMT_SRC_SEL_PRESENT 0 +#define DC__FMT_SRC_SEL_PRESENT__0 1 +#define DC__DIG_FEATURES__HDMI_PRESENT 1 +#define DC__DIG_FEATURES__HDMI_PRESENT__1 1 +#define DC__DIG_FEATURES__DP_PRESENT 1 +#define DC__DIG_FEATURES__DP_PRESENT__1 1 +#define DC__DIG_FEATURES__DP_MST_PRESENT 1 +#define DC__DIG_FEATURES__DP_MST_PRESENT__1 1 +#define DC__DIG_LP_FEATURES__HDMI_PRESENT 0 +#define DC__DIG_LP_FEATURES__HDMI_PRESENT__0 1 +#define DC__DIG_LP_FEATURES__DP_PRESENT 1 +#define DC__DIG_LP_FEATURES__DP_PRESENT__1 1 +#define DC__DIG_LP_FEATURES__DP_MST_PRESENT 0 +#define DC__DIG_LP_FEATURES__DP_MST_PRESENT__0 1 +#define DC__DIG_RESYNC_FIFO_SIZE 14 +#define DC__DIG_RESYNC_FIFO_SIZE__14 1 +#define DC__DIG_RESYNC_FIFO_SIZE__0_PRESENT 1 +#define DC__DIG_RESYNC_FIFO_SIZE__1_PRESENT 1 +#define DC__DIG_RESYNC_FIFO_SIZE__2_PRESENT 1 +#define DC__DIG_RESYNC_FIFO_SIZE__3_PRESENT 1 +#define DC__DIG_RESYNC_FIFO_SIZE__4_PRESENT 1 +#define DC__DIG_RESYNC_FIFO_SIZE__5_PRESENT 1 +#define DC__DIG_RESYNC_FIFO_SIZE__6_PRESENT 1 +#define DC__DIG_RESYNC_FIFO_SIZE__7_PRESENT 1 +#define DC__DIG_RESYNC_FIFO_SIZE__8_PRESENT 1 +#define DC__DIG_RESYNC_FIFO_SIZE__9_PRESENT 1 +#define DC__DIG_RESYNC_FIFO_SIZE__10_PRESENT 1 +#define DC__DIG_RESYNC_FIFO_SIZE__11_PRESENT 1 +#define DC__DIG_RESYNC_FIFO_SIZE__12_PRESENT 1 +#define DC__DIG_RESYNC_FIFO_SIZE__13_PRESENT 1 +#define DC__DIG_RESYNC_FIFO_SIZE__MAX 16 +#define DC__DIG_RESYNC_FIFO_SIZE__MAX__16 1 +#define DC__DAC_RESYNC_FIFO_SIZE 12 +#define DC__DAC_RESYNC_FIFO_SIZE__12 1 +#define DC__DAC_RESYNC_FIFO_SIZE__0_PRESENT 1 +#define DC__DAC_RESYNC_FIFO_SIZE__1_PRESENT 1 +#define DC__DAC_RESYNC_FIFO_SIZE__2_PRESENT 1 +#define DC__DAC_RESYNC_FIFO_SIZE__3_PRESENT 1 +#define DC__DAC_RESYNC_FIFO_SIZE__4_PRESENT 1 +#define DC__DAC_RESYNC_FIFO_SIZE__5_PRESENT 1 +#define DC__DAC_RESYNC_FIFO_SIZE__6_PRESENT 1 +#define DC__DAC_RESYNC_FIFO_SIZE__7_PRESENT 1 +#define DC__DAC_RESYNC_FIFO_SIZE__8_PRESENT 1 +#define DC__DAC_RESYNC_FIFO_SIZE__9_PRESENT 1 +#define DC__DAC_RESYNC_FIFO_SIZE__10_PRESENT 1 +#define DC__DAC_RESYNC_FIFO_SIZE__11_PRESENT 1 +#define DC__DAC_RESYNC_FIFO_SIZE__MAX 16 +#define DC__DAC_RESYNC_FIFO_SIZE__MAX__16 1 +#define DC__DVO_RESYNC_FIFO_SIZE 12 +#define DC__DVO_RESYNC_FIFO_SIZE__12 1 +#define DC__DVO_RESYNC_FIFO_SIZE__0_PRESENT 1 +#define DC__DVO_RESYNC_FIFO_SIZE__1_PRESENT 1 +#define DC__DVO_RESYNC_FIFO_SIZE__2_PRESENT 1 +#define DC__DVO_RESYNC_FIFO_SIZE__3_PRESENT 1 +#define DC__DVO_RESYNC_FIFO_SIZE__4_PRESENT 1 +#define DC__DVO_RESYNC_FIFO_SIZE__5_PRESENT 1 +#define DC__DVO_RESYNC_FIFO_SIZE__6_PRESENT 1 +#define DC__DVO_RESYNC_FIFO_SIZE__7_PRESENT 1 +#define DC__DVO_RESYNC_FIFO_SIZE__8_PRESENT 1 +#define DC__DVO_RESYNC_FIFO_SIZE__9_PRESENT 1 +#define DC__DVO_RESYNC_FIFO_SIZE__10_PRESENT 1 +#define DC__DVO_RESYNC_FIFO_SIZE__11_PRESENT 1 +#define DC__DVO_RESYNC_FIFO_SIZE__MAX 16 +#define DC__DVO_RESYNC_FIFO_SIZE__MAX__16 1 +#define DC__MEM_CDC_PRESENT 1 +#define DC__MEM_CDC_PRESENT__1 1 +#define DC__NUM_HPD 4 +#define DC__NUM_HPD__4 1 +#define DC__NUM_HPD__0_PRESENT 1 +#define DC__NUM_HPD__1_PRESENT 1 +#define DC__NUM_HPD__2_PRESENT 1 +#define DC__NUM_HPD__3_PRESENT 1 +#define DC__NUM_HPD__MAX 6 +#define DC__NUM_HPD__MAX__6 1 +#define DC__NUM_DDC_PAIRS 4 +#define DC__NUM_DDC_PAIRS__4 1 +#define DC__NUM_DDC_PAIRS__0_PRESENT 1 +#define DC__NUM_DDC_PAIRS__1_PRESENT 1 +#define DC__NUM_DDC_PAIRS__2_PRESENT 1 +#define DC__NUM_DDC_PAIRS__3_PRESENT 1 +#define DC__NUM_DDC_PAIRS__MAX 6 +#define DC__NUM_DDC_PAIRS__MAX__6 1 +#define DC__NUM_AUDIO_PLL 0 +#define DC__NUM_AUDIO_PLL__0 1 +#define DC__NUM_AUDIO_PLL__MAX 2 +#define DC__NUM_AUDIO_PLL__MAX__2 1 +#define DC__NUM_PIXEL_PLL 1 +#define DC__NUM_PIXEL_PLL__1 1 +#define DC__NUM_PIXEL_PLL__0_PRESENT 1 +#define DC__NUM_PIXEL_PLL__MAX 4 +#define DC__NUM_PIXEL_PLL__MAX__4 1 +#define DC__NUM_CASCADED_PLL 0 +#define DC__NUM_CASCADED_PLL__0 1 +#define DC__NUM_CASCADED_PLL__MAX 3 +#define DC__NUM_CASCADED_PLL__MAX__3 1 +#define DC__PIXCLK_FROM_PHYPLL 1 +#define DC__PIXCLK_FROM_PHYPLL__1 1 +#define DC__NB_STUTTER_MODE_PRESENT 0 +#define DC__NB_STUTTER_MODE_PRESENT__0 1 +#define DC__I2S0_AND_SPDIF0_PRESENT 0 +#define DC__I2S0_AND_SPDIF0_PRESENT__0 1 +#define DC__I2S1_PRESENT 0 +#define DC__I2S1_PRESENT__0 1 +#define DC__SPDIF1_PRESENT 0 +#define DC__SPDIF1_PRESENT__0 1 +#define DC__DSI_PRESENT 0 +#define DC__DSI_PRESENT__0 1 +#define DC__DACA_PRESENT 0 +#define DC__DACA_PRESENT__0 1 +#define DC__DACB_PRESENT 0 +#define DC__DACB_PRESENT__0 1 +#define DC__NUM_PIPES 4 +#define DC__NUM_PIPES__4 1 +#define DC__NUM_PIPES__0_PRESENT 1 +#define DC__NUM_PIPES__1_PRESENT 1 +#define DC__NUM_PIPES__2_PRESENT 1 +#define DC__NUM_PIPES__3_PRESENT 1 +#define DC__NUM_PIPES__MAX 6 +#define DC__NUM_PIPES__MAX__6 1 +#define DC__NUM_DIG_LP 0 +#define DC__NUM_DIG_LP__0 1 +#define DC__NUM_DIG_LP__MAX 2 +#define DC__NUM_DIG_LP__MAX__2 1 +#define DC__DPDEBUG_PRESENT 0 +#define DC__DPDEBUG_PRESENT__0 1 +#define DC__DISPLAY_WB_PRESENT 1 +#define DC__DISPLAY_WB_PRESENT__1 1 +#define DC__NUM_CWB 0 +#define DC__NUM_CWB__0 1 +#define DC__NUM_CWB__MAX 2 +#define DC__NUM_CWB__MAX__2 1 +#define DC__MVP_PRESENT 0 +#define DC__MVP_PRESENT__0 1 +#define DC__DVO_PRESENT 0 +#define DC__DVO_PRESENT__0 1 +#define DC__ABM_PRESENT 0 +#define DC__ABM_PRESENT__0 1 +#define DC__BPHYC_PLL_PRESENT 0 +#define DC__BPHYC_PLL_PRESENT__0 1 +#define DC__BPHYC_UNIPHY_PRESENT 0 +#define DC__BPHYC_UNIPHY_PRESENT__0 1 +#define DC__PHY_BROADCAST_PRESENT 0 +#define DC__PHY_BROADCAST_PRESENT__0 1 +#define DC__NUM_OF_DCRX_SD 0 +#define DC__NUM_OF_DCRX_SD__0 1 +#define DC__DVO_17BIT_MAPPING 0 +#define DC__DVO_17BIT_MAPPING__0 1 +#define DC__AVSYNC_PRESENT 0 +#define DC__AVSYNC_PRESENT__0 1 +#define DC__NUM_OF_DCRX_PORTS 0 +#define DC__NUM_OF_DCRX_PORTS__0 1 +#define DC__NUM_OF_DCRX_PORTS__MAX 1 +#define DC__NUM_OF_DCRX_PORTS__MAX__1 1 +#define DC__NUM_PHY 4 +#define DC__NUM_PHY__4 1 +#define DC__NUM_PHY__0_PRESENT 1 +#define DC__NUM_PHY__1_PRESENT 1 +#define DC__NUM_PHY__2_PRESENT 1 +#define DC__NUM_PHY__3_PRESENT 1 +#define DC__NUM_PHY__MAX 7 +#define DC__NUM_PHY__MAX__7 1 +#define DC__NUM_PHY_LP 0 +#define DC__NUM_PHY_LP__0 1 +#define DC__NUM_PHY_LP__MAX 2 +#define DC__NUM_PHY_LP__MAX__2 1 +#define DC__SYNC_CELL vid_sync_gf14lpp +#define DC__SYNC_CELL__VID_SYNC_GF14LPP 1 +#define DC__USE_NEW_VSS 1 +#define DC__USE_NEW_VSS__1 1 +#define DC__SYNC_CELL_DISPCLK_NUM_LATCHES 6 +#define DC__SYNC_CELL_DISPCLK_NUM_LATCHES__6 1 +#define DC__SYNC_CELL_DVOCLK_NUM_LATCHES 6 +#define DC__SYNC_CELL_DVOCLK_NUM_LATCHES__6 1 +#define DC__SYNC_CELL_PIXCLK_NUM_LATCHES 6 +#define DC__SYNC_CELL_PIXCLK_NUM_LATCHES__6 1 +#define DC__SYNC_CELL_SYMCLK_NUM_LATCHES 6 +#define DC__SYNC_CELL_SYMCLK_NUM_LATCHES__6 1 +#define DC__SYNC_CELL_DPPCLK_NUM_LATCHES 6 +#define DC__SYNC_CELL_DPPCLK_NUM_LATCHES__6 1 +#define DC__SYNC_CELL_DPREFCLK_NUM_LATCHES 6 +#define DC__SYNC_CELL_DPREFCLK_NUM_LATCHES__6 1 +#define DC__SYNC_CELL_REFCLK_NUM_LATCHES 6 +#define DC__SYNC_CELL_REFCLK_NUM_LATCHES__6 1 +#define DC__SYNC_CELL_PCIE_REFCLK_NUM_LATCHES 6 +#define DC__SYNC_CELL_PCIE_REFCLK_NUM_LATCHES__6 1 +#define DC__SYNC_CELL_MVPCLK_NUM_LATCHES 6 +#define DC__SYNC_CELL_MVPCLK_NUM_LATCHES__6 1 +#define DC__SYNC_CELL_SCLK_NUM_LATCHES 6 +#define DC__SYNC_CELL_SCLK_NUM_LATCHES__6 1 +#define DC__SYNC_CELL_DCEFCLK_NUM_LATCHES 6 +#define DC__SYNC_CELL_DCEFCLK_NUM_LATCHES__6 1 +#define DC__SYNC_CELL_AMCLK_NUM_LATCHES 6 +#define DC__SYNC_CELL_AMCLK_NUM_LATCHES__6 1 +#define DC__SYNC_CELL_DSICLK_NUM_LATCHES 6 +#define DC__SYNC_CELL_DSICLK_NUM_LATCHES__6 1 +#define DC__SYNC_CELL_BYTECLK_NUM_LATCHES 6 +#define DC__SYNC_CELL_BYTECLK_NUM_LATCHES__6 1 +#define DC__SYNC_CELL_ESCCLK_NUM_LATCHES 6 +#define DC__SYNC_CELL_ESCCLK_NUM_LATCHES__6 1 +#define DC__SYNC_CELL_DB_CLK_NUM_LATCHES 6 +#define DC__SYNC_CELL_DB_CLK_NUM_LATCHES__6 1 +#define UNIPHYA_PRESENT 1 +#define UNIPHYA_PRESENT__1 1 +#define DC__UNIPHYA_PRESENT 1 +#define DC__UNIPHYA_PRESENT__1 1 +#define UNIPHYB_PRESENT 1 +#define UNIPHYB_PRESENT__1 1 +#define DC__UNIPHYB_PRESENT 1 +#define DC__UNIPHYB_PRESENT__1 1 +#define UNIPHYC_PRESENT 1 +#define UNIPHYC_PRESENT__1 1 +#define DC__UNIPHYC_PRESENT 1 +#define DC__UNIPHYC_PRESENT__1 1 +#define UNIPHYD_PRESENT 1 +#define UNIPHYD_PRESENT__1 1 +#define DC__UNIPHYD_PRESENT 1 +#define DC__UNIPHYD_PRESENT__1 1 +#define UNIPHYE_PRESENT 0 +#define UNIPHYE_PRESENT__0 1 +#define DC__UNIPHYE_PRESENT 0 +#define DC__UNIPHYE_PRESENT__0 1 +#define UNIPHYF_PRESENT 0 +#define UNIPHYF_PRESENT__0 1 +#define DC__UNIPHYF_PRESENT 0 +#define DC__UNIPHYF_PRESENT__0 1 +#define UNIPHYG_PRESENT 0 +#define UNIPHYG_PRESENT__0 1 +#define DC__UNIPHYG_PRESENT 0 +#define DC__UNIPHYG_PRESENT__0 1 +#define DC__TMDS_LINK tmds_link_dual +#define DC__TMDS_LINK__TMDS_LINK_DUAL 1 +#define DC__WBSCL_PIXBW 8 +#define DC__WBSCL_PIXBW__8 1 +#define DC__DWB_CSC_PRESENT 0 +#define DC__DWB_CSC_PRESENT__0 1 +#define DC__DWB_LUMA_SCL_PRESENT 0 +#define DC__DWB_LUMA_SCL_PRESENT__0 1 +#define DC__DENTIST_INTERFACE_PRESENT 1 +#define DC__DENTIST_INTERFACE_PRESENT__1 1 +#define DC__GENERICA_PRESENT 1 +#define DC__GENERICA_PRESENT__1 1 +#define DC__GENERICB_PRESENT 1 +#define DC__GENERICB_PRESENT__1 1 +#define DC__GENERICC_PRESENT 0 +#define DC__GENERICC_PRESENT__0 1 +#define DC__GENERICD_PRESENT 0 +#define DC__GENERICD_PRESENT__0 1 +#define DC__GENERICE_PRESENT 0 +#define DC__GENERICE_PRESENT__0 1 +#define DC__GENERICF_PRESENT 0 +#define DC__GENERICF_PRESENT__0 1 +#define DC__GENERICG_PRESENT 0 +#define DC__GENERICG_PRESENT__0 1 +#define DC__UNIPHY_VOLTAGE_MODE 1 +#define DC__UNIPHY_VOLTAGE_MODE__1 1 +#define DC__BLON_TYPE dedicated +#define DC__BLON_TYPE__DEDICATED 1 +#define DC__UNIPHY_STAGGER_CH_PRESENT 1 +#define DC__UNIPHY_STAGGER_CH_PRESENT__1 1 +#define DC__XDMA_PRESENT 0 +#define DC__XDMA_PRESENT__0 1 +#define XDMA__PRESENT 0 +#define XDMA__PRESENT__0 1 +#define DC__DP_MEM_PG 0 +#define DC__DP_MEM_PG__0 1 +#define DP__MEM_PG 0 +#define DP__MEM_PG__0 1 +#define DC__AFMT_MEM_PG 0 +#define DC__AFMT_MEM_PG__0 1 +#define AFMT__MEM_PG 0 +#define AFMT__MEM_PG__0 1 +#define DC__HDMI_MEM_PG 0 +#define DC__HDMI_MEM_PG__0 1 +#define HDMI__MEM_PG 0 +#define HDMI__MEM_PG__0 1 +#define DC__I2C_MEM_PG 0 +#define DC__I2C_MEM_PG__0 1 +#define I2C__MEM_PG 0 +#define I2C__MEM_PG__0 1 +#define DC__DSCL_MEM_PG 0 +#define DC__DSCL_MEM_PG__0 1 +#define DSCL__MEM_PG 0 +#define DSCL__MEM_PG__0 1 +#define DC__CM_MEM_PG 0 +#define DC__CM_MEM_PG__0 1 +#define CM__MEM_PG 0 +#define CM__MEM_PG__0 1 +#define DC__OBUF_MEM_PG 0 +#define DC__OBUF_MEM_PG__0 1 +#define OBUF__MEM_PG 0 +#define OBUF__MEM_PG__0 1 +#define DC__WBIF_MEM_PG 1 +#define DC__WBIF_MEM_PG__1 1 +#define WBIF__MEM_PG 1 +#define WBIF__MEM_PG__1 1 +#define DC__VGA_MEM_PG 0 +#define DC__VGA_MEM_PG__0 1 +#define VGA__MEM_PG 0 +#define VGA__MEM_PG__0 1 +#define DC__FMT_MEM_PG 0 +#define DC__FMT_MEM_PG__0 1 +#define FMT__MEM_PG 0 +#define FMT__MEM_PG__0 1 +#define DC__ODM_MEM_PG 0 +#define DC__ODM_MEM_PG__0 1 +#define ODM__MEM_PG 0 +#define ODM__MEM_PG__0 1 +#define DC__DSI_MEM_PG 0 +#define DC__DSI_MEM_PG__0 1 +#define DSI__MEM_PG 0 +#define DSI__MEM_PG__0 1 +#define DC__AZ_MEM_PG 1 +#define DC__AZ_MEM_PG__1 1 +#define AZ__MEM_PG 1 +#define AZ__MEM_PG__1 1 +#define DC__WBSCL_MEM1P1024X64QS_MEM_PG 1 +#define DC__WBSCL_MEM1P1024X64QS_MEM_PG__1 1 +#define WBSCL_MEM1P1024X64QS__MEM_PG 1 +#define WBSCL_MEM1P1024X64QS__MEM_PG__1 1 +#define DC__WBSCL_MEM1P528X64QS_MEM_PG 1 +#define DC__WBSCL_MEM1P528X64QS_MEM_PG__1 1 +#define WBSCL_MEM1P528X64QS__MEM_PG 1 +#define WBSCL_MEM1P528X64QS__MEM_PG__1 1 +#define DC__DMCU_MEM1P1024X32BQS_MEM_PG 1 +#define DC__DMCU_MEM1P1024X32BQS_MEM_PG__1 1 +#define DMCU_MEM1P1024X32BQS__MEM_PG 1 +#define DMCU_MEM1P1024X32BQS__MEM_PG__1 1 +#define DC__HUBBUB_SDP_TAG_INT_MEM_PG 0 +#define DC__HUBBUB_SDP_TAG_INT_MEM_PG__0 1 +#define HUBBUB_SDP_TAG_INT__MEM_PG 0 +#define HUBBUB_SDP_TAG_INT__MEM_PG__0 1 +#define DC__HUBBUB_SDP_TAG_EXT_MEM_PG 0 +#define DC__HUBBUB_SDP_TAG_EXT_MEM_PG__0 1 +#define HUBBUB_SDP_TAG_EXT__MEM_PG 0 +#define HUBBUB_SDP_TAG_EXT__MEM_PG__0 1 +#define DC__HUBBUB_RET_ZERO_MEM_PG 0 +#define DC__HUBBUB_RET_ZERO_MEM_PG__0 1 +#define HUBBUB_RET_ZERO__MEM_PG 0 +#define HUBBUB_RET_ZERO__MEM_PG__0 1 +#define DC__HUBBUB_RET_ROB_MEM_PG 0 +#define DC__HUBBUB_RET_ROB_MEM_PG__0 1 +#define HUBBUB_RET_ROB__MEM_PG 0 +#define HUBBUB_RET_ROB__MEM_PG__0 1 +#define DC__HUBPRET_CUR_ROB_MEM_PG 0 +#define DC__HUBPRET_CUR_ROB_MEM_PG__0 1 +#define HUBPRET_CUR_ROB__MEM_PG 0 +#define HUBPRET_CUR_ROB__MEM_PG__0 1 +#define DC__HUBPRET_CUR_CDC_MEM_PG 0 +#define DC__HUBPRET_CUR_CDC_MEM_PG__0 1 +#define HUBPRET_CUR_CDC__MEM_PG 0 +#define HUBPRET_CUR_CDC__MEM_PG__0 1 +#define DC__HUBPREQ_MPTE_MEM_PG 0 +#define DC__HUBPREQ_MPTE_MEM_PG__0 1 +#define HUBPREQ_MPTE__MEM_PG 0 +#define HUBPREQ_MPTE__MEM_PG__0 1 +#define DC__HUBPREQ_META_MEM_PG 0 +#define DC__HUBPREQ_META_MEM_PG__0 1 +#define HUBPREQ_META__MEM_PG 0 +#define HUBPREQ_META__MEM_PG__0 1 +#define DC__HUBPREQ_DPTE_MEM_PG 0 +#define DC__HUBPREQ_DPTE_MEM_PG__0 1 +#define HUBPREQ_DPTE__MEM_PG 0 +#define HUBPREQ_DPTE__MEM_PG__0 1 +#define DC__HUBPRET_DET_MEM_PG 0 +#define DC__HUBPRET_DET_MEM_PG__0 1 +#define HUBPRET_DET__MEM_PG 0 +#define HUBPRET_DET__MEM_PG__0 1 +#define DC__HUBPRET_PIX_CDC_MEM_PG 0 +#define DC__HUBPRET_PIX_CDC_MEM_PG__0 1 +#define HUBPRET_PIX_CDC__MEM_PG 0 +#define HUBPRET_PIX_CDC__MEM_PG__0 1 +#define DC__TOP_BLKS__DCCG 1 +#define DC__TOP_BLKS__DCHUBBUB 1 +#define DC__TOP_BLKS__DCHUBP 1 +#define DC__TOP_BLKS__HDA 1 +#define DC__TOP_BLKS__DIO 1 +#define DC__TOP_BLKS__DCIO 1 +#define DC__TOP_BLKS__DMU 1 +#define DC__TOP_BLKS__DPP 1 +#define DC__TOP_BLKS__MPC 1 +#define DC__TOP_BLKS__OPP 1 +#define DC__TOP_BLKS__OPTC 1 +#define DC__TOP_BLKS__MMHUBBUB 1 +#define DC__TOP_BLKS__WB 1 +#define DC__TOP_BLKS__MAX 13 +#define DC__TOP_BLKS__MAX__13 1 +#define DC__DCHUBP_DPP_SF_PIXEL_CREDITS 9 +#define DC__DCHUBP_DPP_SF_PIXEL_CREDITS__9 1 +#define DC__DPP_MPC_SF_PIXEL_CREDITS 9 +#define DC__DPP_MPC_SF_PIXEL_CREDITS__9 1 +#define DC__MPC_OPP_SF_PIXEL_CREDITS 8 +#define DC__MPC_OPP_SF_PIXEL_CREDITS__8 1 +#define DC__OPP_OPTC_SF_PIXEL_CREDITS 8 +#define DC__OPP_OPTC_SF_PIXEL_CREDITS__8 1 +#define DC__SFR_SFT_ROUND_TRIP_DELAY 5 +#define DC__SFR_SFT_ROUND_TRIP_DELAY__5 1 +#define DC__REPEATER_PROJECT_MAX 8 +#define DC__REPEATER_PROJECT_MAX__8 1 +#define DC__SURFACE_422_CAPABLE 0 +#define DC__SURFACE_422_CAPABLE__0 1 +#endif diff --git a/drivers/gpu/drm/amd/display/dc/dml/display_mode_enums.h b/drivers/gpu/drm/amd/display/dc/dml/display_mode_enums.h new file mode 100644 index 000000000000..143a3d418de0 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/dml/display_mode_enums.h @@ -0,0 +1,111 @@ +/* + * Copyright 2017 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 __DISPLAY_MODE_ENUMS_H__ +#define __DISPLAY_MODE_ENUMS_H__ +enum output_encoder_class { + dm_dp = 0, + dm_hdmi = 1, + dm_wb = 2 +}; +enum output_format_class { + dm_444 = 0, + dm_420 = 1 +}; +enum source_format_class { + dm_444_16 = 0, + dm_444_32 = 1, + dm_444_64 = 2, + dm_420_8 = 3, + dm_420_10 = 4, + dm_422_8 = 5, + dm_422_10 = 6 +}; +enum output_bpc_class { + dm_out_6 = 0, + dm_out_8 = 1, + dm_out_10 = 2, + dm_out_12 = 3, + dm_out_16 = 4 +}; +enum scan_direction_class { + dm_horz = 0, + dm_vert = 1 +}; +enum dm_swizzle_mode { + dm_sw_linear = 0, + dm_sw_256b_s = 1, + dm_sw_256b_d = 2, + dm_sw_SPARE_0 = 3, + dm_sw_SPARE_1 = 4, + dm_sw_4kb_s = 5, + dm_sw_4kb_d = 6, + dm_sw_SPARE_2 = 7, + dm_sw_SPARE_3 = 8, + dm_sw_64kb_s = 9, + dm_sw_64kb_d = 10, + dm_sw_SPARE_4 = 11, + dm_sw_SPARE_5 = 12, + dm_sw_var_s = 13, + dm_sw_var_d = 14, + dm_sw_SPARE_6 = 15, + dm_sw_SPARE_7 = 16, + dm_sw_64kb_s_t = 17, + dm_sw_64kb_d_t = 18, + dm_sw_SPARE_10 = 19, + dm_sw_SPARE_11 = 20, + dm_sw_4kb_s_x = 21, + dm_sw_4kb_d_x = 22, + dm_sw_SPARE_12 = 23, + dm_sw_SPARE_13 = 24, + dm_sw_64kb_s_x = 25, + dm_sw_64kb_d_x = 26, + dm_sw_SPARE_14 = 27, + dm_sw_SPARE_15 = 28, + dm_sw_var_s_x = 29, + dm_sw_var_d_x = 30 +}; +enum lb_depth { + dm_lb_10 = 30, + dm_lb_8 = 24, + dm_lb_6 = 18, + dm_lb_12 = 36 +}; +enum voltage_state { + dm_vmin = 0, + dm_vmid = 1, + dm_vnom = 2, + dm_vmax = 3, + dm_vmax_exceeded = 4 +}; +enum source_macro_tile_size { + dm_4k_tile = 0, + dm_64k_tile = 1, + dm_256k_tile = 2 +}; +enum cursor_bpp { + dm_cur_2bit = 0, + dm_cur_32bit = 1 +}; +#endif diff --git a/drivers/gpu/drm/amd/display/dc/dml/display_mode_lib.c b/drivers/gpu/drm/amd/display/dc/dml/display_mode_lib.c new file mode 100644 index 000000000000..c02c5522613b --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/dml/display_mode_lib.c @@ -0,0 +1,147 @@ +/* + * Copyright 2017 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 "display_mode_lib.h" + +static void set_soc_bounding_box(struct _vcs_dpi_soc_bounding_box_st *soc, enum dml_project project) +{ + if (project == DML_PROJECT_RAVEN1) { + soc->sr_exit_time_us = 9.0; + soc->sr_enter_plus_exit_time_us = 11.0; + soc->urgent_latency_us = 4.0; + soc->writeback_latency_us = 12.0; + soc->ideal_dram_bw_after_urgent_percent = 80.0; + soc->max_request_size_bytes = 256; + + soc->vmin.dcfclk_mhz = 300.0; + soc->vmin.dispclk_mhz = 608.0; + soc->vmin.dppclk_mhz = 435.0; + soc->vmin.dram_bw_per_chan_gbps = 12.8; + soc->vmin.phyclk_mhz = 540.0; + soc->vmin.socclk_mhz = 208.0; + + soc->vmid.dcfclk_mhz = 600.0; + soc->vmid.dispclk_mhz = 661.0; + soc->vmid.dppclk_mhz = 661.0; + soc->vmid.dram_bw_per_chan_gbps = 12.8; + soc->vmid.phyclk_mhz = 540.0; + soc->vmid.socclk_mhz = 208.0; + + soc->vnom.dcfclk_mhz = 600.0; + soc->vnom.dispclk_mhz = 661.0; + soc->vnom.dppclk_mhz = 661.0; + soc->vnom.dram_bw_per_chan_gbps = 38.4; + soc->vnom.phyclk_mhz = 810; + soc->vnom.socclk_mhz = 208.0; + + soc->vmax.dcfclk_mhz = 600.0; + soc->vmax.dispclk_mhz = 1086.0; + soc->vmax.dppclk_mhz = 661.0; + soc->vmax.dram_bw_per_chan_gbps = 38.4; + soc->vmax.phyclk_mhz = 810.0; + soc->vmax.socclk_mhz = 208.0; + + soc->downspread_percent = 0.5; + soc->dram_page_open_time_ns = 50.0; + soc->dram_rw_turnaround_time_ns = 17.5; + soc->dram_return_buffer_per_channel_bytes = 8192; + soc->round_trip_ping_latency_dcfclk_cycles = 128; + soc->urgent_out_of_order_return_per_channel_bytes = 256; + soc->channel_interleave_bytes = 256; + soc->num_banks = 8; + soc->num_chans = 2; + soc->vmm_page_size_bytes = 4096; + soc->dram_clock_change_latency_us = 17.0; + soc->writeback_dram_clock_change_latency_us = 23.0; + soc->return_bus_width_bytes = 64; + } else { + BREAK_TO_DEBUGGER(); /* Invalid Project Specified */ + } +} + +static void set_ip_params(struct _vcs_dpi_ip_params_st *ip, enum dml_project project) +{ + if (project == DML_PROJECT_RAVEN1) { + ip->rob_buffer_size_kbytes = 64; + ip->det_buffer_size_kbytes = 164; + ip->dpte_buffer_size_in_pte_reqs = 42; + ip->dpp_output_buffer_pixels = 2560; + ip->opp_output_buffer_lines = 1; + ip->pixel_chunk_size_kbytes = 8; + ip->pte_enable = 1; + ip->pte_chunk_size_kbytes = 2; + ip->meta_chunk_size_kbytes = 2; + ip->writeback_chunk_size_kbytes = 2; + ip->line_buffer_size_bits = 589824; + ip->max_line_buffer_lines = 12; + ip->IsLineBufferBppFixed = 0; + ip->LineBufferFixedBpp = -1; + ip->writeback_luma_buffer_size_kbytes = 12; + ip->writeback_chroma_buffer_size_kbytes = 8; + ip->max_num_dpp = 4; + ip->max_num_wb = 2; + ip->max_dchub_pscl_bw_pix_per_clk = 4; + ip->max_pscl_lb_bw_pix_per_clk = 2; + ip->max_lb_vscl_bw_pix_per_clk = 4; + ip->max_vscl_hscl_bw_pix_per_clk = 4; + ip->max_hscl_ratio = 4; + ip->max_vscl_ratio = 4; + ip->hscl_mults = 4; + ip->vscl_mults = 4; + ip->max_hscl_taps = 8; + ip->max_vscl_taps = 8; + ip->dispclk_ramp_margin_percent = 1; + ip->underscan_factor = 1.10; + ip->min_vblank_lines = 14; + ip->dppclk_delay_subtotal = 90; + ip->dispclk_delay_subtotal = 42; + ip->dcfclk_cstate_latency = 10; + ip->max_inter_dcn_tile_repeaters = 8; + ip->can_vstartup_lines_exceed_vsync_plus_back_porch_lines_minus_one = 0; + ip->bug_forcing_LC_req_same_size_fixed = 0; + } else { + BREAK_TO_DEBUGGER(); /* Invalid Project Specified */ + } +} + +static void set_mode_evaluation(struct _vcs_dpi_mode_evaluation_st *me, enum dml_project project) +{ + if (project == DML_PROJECT_RAVEN1) { + me->voltage_override = dm_vmin; + } else { + BREAK_TO_DEBUGGER(); /* Invalid Project Specified */ + } +} + +void dml_init_instance(struct display_mode_lib *lib, enum dml_project project) +{ + if (lib->project != project) { + set_soc_bounding_box(&lib->soc, project); + set_ip_params(&lib->ip, project); + set_mode_evaluation(&lib->me, project); + lib->project = project; + } +} + diff --git a/drivers/gpu/drm/amd/display/dc/dml/display_mode_lib.h b/drivers/gpu/drm/amd/display/dc/dml/display_mode_lib.h new file mode 100644 index 000000000000..e2e311138358 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/dml/display_mode_lib.h @@ -0,0 +1,52 @@ +/* + * Copyright 2017 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 __DISPLAY_MODE_LIB_H__ +#define __DISPLAY_MODE_LIB_H__ + +#include "dml_common_defs.h" +#include "soc_bounding_box.h" +#include "display_watermark.h" +#include "display_pipe_clocks.h" +#include "display_rq_dlg_calc.h" +#include "display_mode_support.h" + +enum dml_project { + DML_PROJECT_UNDEFINED, + DML_PROJECT_RAVEN1 +}; + +struct display_mode_lib { + struct _vcs_dpi_ip_params_st ip; + struct _vcs_dpi_soc_bounding_box_st soc; + struct _vcs_dpi_mode_evaluation_st me; + enum dml_project project; + struct dml_ms_internal_vars vars; + struct _vcs_dpi_wm_calc_pipe_params_st wm_param[DC__NUM_PIPES__MAX]; + struct dal_logger *logger; +}; + +void dml_init_instance(struct display_mode_lib *lib, enum dml_project project); + +#endif diff --git a/drivers/gpu/drm/amd/display/dc/dml/display_mode_structs.h b/drivers/gpu/drm/amd/display/dc/dml/display_mode_structs.h new file mode 100644 index 000000000000..e589a5eadb6a --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/dml/display_mode_structs.h @@ -0,0 +1,429 @@ +/* + * Copyright 2017 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 __DISPLAY_MODE_STRUCTS_H__ +#define __DISPLAY_MODE_STRUCTS_H__ + +struct _vcs_dpi_voltage_scaling_st { + double dcfclk_mhz; + double dispclk_mhz; + double dppclk_mhz; + double dram_bw_per_chan_gbps; + double phyclk_mhz; + double socclk_mhz; +}; + +struct _vcs_dpi_soc_bounding_box_st { + double sr_exit_time_us; + double sr_enter_plus_exit_time_us; + double urgent_latency_us; + double writeback_latency_us; + double ideal_dram_bw_after_urgent_percent; + unsigned int max_request_size_bytes; + struct _vcs_dpi_voltage_scaling_st vmin; + struct _vcs_dpi_voltage_scaling_st vmid; + struct _vcs_dpi_voltage_scaling_st vnom; + struct _vcs_dpi_voltage_scaling_st vmax; + double downspread_percent; + double dram_page_open_time_ns; + double dram_rw_turnaround_time_ns; + double dram_return_buffer_per_channel_bytes; + unsigned int round_trip_ping_latency_dcfclk_cycles; + unsigned int urgent_out_of_order_return_per_channel_bytes; + unsigned int channel_interleave_bytes; + unsigned int num_banks; + unsigned int num_chans; + unsigned int vmm_page_size_bytes; + double dram_clock_change_latency_us; + double writeback_dram_clock_change_latency_us; + unsigned int return_bus_width_bytes; +}; + +struct _vcs_dpi_ip_params_st { + unsigned int rob_buffer_size_kbytes; + unsigned int det_buffer_size_kbytes; + unsigned int dpte_buffer_size_in_pte_reqs; + unsigned int dpp_output_buffer_pixels; + unsigned int opp_output_buffer_lines; + unsigned int pixel_chunk_size_kbytes; + unsigned char pte_enable; + unsigned int pte_chunk_size_kbytes; + unsigned int meta_chunk_size_kbytes; + unsigned int writeback_chunk_size_kbytes; + unsigned int line_buffer_size_bits; + unsigned int max_line_buffer_lines; + unsigned int IsLineBufferBppFixed; + unsigned int LineBufferFixedBpp; + unsigned int writeback_luma_buffer_size_kbytes; + unsigned int writeback_chroma_buffer_size_kbytes; + unsigned int max_num_dpp; + unsigned int max_num_wb; + unsigned int max_dchub_pscl_bw_pix_per_clk; + unsigned int max_pscl_lb_bw_pix_per_clk; + unsigned int max_lb_vscl_bw_pix_per_clk; + unsigned int max_vscl_hscl_bw_pix_per_clk; + double max_hscl_ratio; + double max_vscl_ratio; + unsigned int hscl_mults; + unsigned int vscl_mults; + unsigned int max_hscl_taps; + unsigned int max_vscl_taps; + double dispclk_ramp_margin_percent; + double underscan_factor; + unsigned int min_vblank_lines; + unsigned int dppclk_delay_subtotal; + unsigned int dispclk_delay_subtotal; + unsigned int dcfclk_cstate_latency; + unsigned int max_inter_dcn_tile_repeaters; + unsigned int can_vstartup_lines_exceed_vsync_plus_back_porch_lines_minus_one; + unsigned int bug_forcing_LC_req_same_size_fixed; +}; + +struct _vcs_dpi_display_pipe_source_params_st { + int source_format; + unsigned char dcc; + unsigned int dcc_rate; + unsigned char vm; + int source_scan; + int sw_mode; + int macro_tile_size; + unsigned char is_display_sw; + unsigned int viewport_width; + unsigned int viewport_height; + unsigned int viewport_width_c; + unsigned int viewport_height_c; + unsigned int data_pitch; + unsigned int data_pitch_c; + unsigned int meta_pitch; + unsigned int meta_pitch_c; + unsigned int cur0_src_width; + int cur0_bpp; + unsigned char is_hsplit; + unsigned int hsplit_grp; +}; + +struct _vcs_dpi_display_output_params_st { + int output_bpc; + int output_type; + int output_format; + int output_standard; +}; + +struct _vcs_dpi_display_bandwidth_st { + double total_bw_consumed_gbps; + double guaranteed_urgent_return_bw_gbps; +}; + +struct _vcs_dpi_scaler_ratio_depth_st { + double hscl_ratio; + double vscl_ratio; + double hscl_ratio_c; + double vscl_ratio_c; + double vinit; + double vinit_c; + double vinit_bot; + double vinit_bot_c; + int lb_depth; +}; + +struct _vcs_dpi_scaler_taps_st { + unsigned int htaps; + unsigned int vtaps; + unsigned int htaps_c; + unsigned int vtaps_c; +}; + +struct _vcs_dpi_display_pipe_dest_params_st { + unsigned int recout_width; + unsigned int recout_height; + unsigned int full_recout_width; + unsigned int full_recout_height; + unsigned int hblank_start; + unsigned int hblank_end; + unsigned int vblank_start; + unsigned int vblank_end; + unsigned int htotal; + unsigned int vtotal; + unsigned int vactive; + unsigned int vstartup_start; + unsigned int vupdate_offset; + unsigned int vupdate_width; + unsigned int vready_offset; + unsigned int vsync_plus_back_porch; + unsigned char interlaced; + unsigned char underscan; + double pixel_rate_mhz; + unsigned char syncronized_vblank_all_planes; +}; + +struct _vcs_dpi_display_pipe_params_st { + struct _vcs_dpi_display_pipe_source_params_st src; + struct _vcs_dpi_display_pipe_dest_params_st dest; + struct _vcs_dpi_scaler_ratio_depth_st scale_ratio_depth; + struct _vcs_dpi_scaler_taps_st scale_taps; +}; + +struct _vcs_dpi_display_clocks_and_cfg_st { + int voltage; + double dppclk_mhz; + double refclk_mhz; + double dispclk_mhz; + double dcfclk_mhz; + double socclk_mhz; +}; + +struct _vcs_dpi_display_e2e_pipe_params_st { + struct _vcs_dpi_display_pipe_params_st pipe; + struct _vcs_dpi_display_output_params_st dout; + struct _vcs_dpi_display_clocks_and_cfg_st clks_cfg; +}; + +struct _vcs_dpi_dchub_buffer_sizing_st { + unsigned int swath_width_y; + unsigned int swath_height_y; + unsigned int swath_height_c; + unsigned int detail_buffer_size_y; +}; + +struct _vcs_dpi_watermarks_perf_st { + double stutter_eff_in_active_region_percent; + double urgent_latency_supported_us; + double non_urgent_latency_supported_us; + double dram_clock_change_margin_us; + double dram_access_eff_percent; +}; + +struct _vcs_dpi_cstate_pstate_watermarks_st { + double cstate_exit_us; + double cstate_enter_plus_exit_us; + double pstate_change_us; +}; + +struct _vcs_dpi_wm_calc_pipe_params_st { + unsigned int num_dpp; + int voltage; + int output_type; + double dcfclk_mhz; + double socclk_mhz; + double dppclk_mhz; + double pixclk_mhz; + unsigned char interlace_en; + unsigned char pte_enable; + unsigned char dcc_enable; + double dcc_rate; + double bytes_per_pixel_c; + double bytes_per_pixel_y; + unsigned int swath_width_y; + unsigned int swath_height_y; + unsigned int swath_height_c; + unsigned int det_buffer_size_y; + double h_ratio; + double v_ratio; + unsigned int h_taps; + unsigned int h_total; + unsigned int v_total; + unsigned int v_active; + unsigned int e2e_index; + double display_pipe_line_delivery_time; + double read_bw; + unsigned int lines_in_det_y; + unsigned int lines_in_det_y_rounded_down_to_swath; + double full_det_buffering_time; + double dcfclk_deepsleep_mhz_per_plane; +}; + +struct _vcs_dpi_vratio_pre_st { + double vratio_pre_l; + double vratio_pre_c; +}; + +struct _vcs_dpi_display_data_rq_misc_params_st { + unsigned int full_swath_bytes; + unsigned int stored_swath_bytes; + unsigned int blk256_height; + unsigned int blk256_width; + unsigned int req_height; + unsigned int req_width; +}; + +struct _vcs_dpi_display_data_rq_sizing_params_st { + unsigned int chunk_bytes; + unsigned int min_chunk_bytes; + unsigned int meta_chunk_bytes; + unsigned int min_meta_chunk_bytes; + unsigned int mpte_group_bytes; + unsigned int dpte_group_bytes; +}; + +struct _vcs_dpi_display_data_rq_dlg_params_st { + unsigned int swath_width_ub; + unsigned int swath_height; + unsigned int req_per_swath_ub; + unsigned int meta_pte_bytes_per_frame_ub; + unsigned int dpte_req_per_row_ub; + unsigned int dpte_groups_per_row_ub; + unsigned int dpte_row_height; + unsigned int dpte_bytes_per_row_ub; + unsigned int meta_chunks_per_row_ub; + unsigned int meta_req_per_row_ub; + unsigned int meta_row_height; + unsigned int meta_bytes_per_row_ub; +}; + +struct _vcs_dpi_display_cur_rq_dlg_params_st { + unsigned char enable; + unsigned int swath_height; + unsigned int req_per_line; +}; + +struct _vcs_dpi_display_rq_dlg_params_st { + struct _vcs_dpi_display_data_rq_dlg_params_st rq_l; + struct _vcs_dpi_display_data_rq_dlg_params_st rq_c; + struct _vcs_dpi_display_cur_rq_dlg_params_st rq_cur0; +}; + +struct _vcs_dpi_display_rq_sizing_params_st { + struct _vcs_dpi_display_data_rq_sizing_params_st rq_l; + struct _vcs_dpi_display_data_rq_sizing_params_st rq_c; +}; + +struct _vcs_dpi_display_rq_misc_params_st { + struct _vcs_dpi_display_data_rq_misc_params_st rq_l; + struct _vcs_dpi_display_data_rq_misc_params_st rq_c; +}; + +struct _vcs_dpi_display_rq_params_st { + unsigned char yuv420; + unsigned char yuv420_10bpc; + struct _vcs_dpi_display_rq_misc_params_st misc; + struct _vcs_dpi_display_rq_sizing_params_st sizing; + struct _vcs_dpi_display_rq_dlg_params_st dlg; +}; + +struct _vcs_dpi_display_dlg_regs_st { + unsigned int refcyc_h_blank_end; + unsigned int dlg_vblank_end; + unsigned int min_dst_y_next_start; + unsigned int refcyc_per_htotal; + unsigned int refcyc_x_after_scaler; + unsigned int dst_y_after_scaler; + unsigned int dst_y_prefetch; + unsigned int dst_y_per_vm_vblank; + unsigned int dst_y_per_row_vblank; + unsigned int ref_freq_to_pix_freq; + unsigned int vratio_prefetch; + unsigned int vratio_prefetch_c; + unsigned int refcyc_per_pte_group_vblank_l; + unsigned int refcyc_per_pte_group_vblank_c; + unsigned int refcyc_per_meta_chunk_vblank_l; + unsigned int refcyc_per_meta_chunk_vblank_c; + unsigned int dst_y_per_pte_row_nom_l; + unsigned int dst_y_per_pte_row_nom_c; + unsigned int refcyc_per_pte_group_nom_l; + unsigned int refcyc_per_pte_group_nom_c; + unsigned int dst_y_per_meta_row_nom_l; + unsigned int dst_y_per_meta_row_nom_c; + unsigned int refcyc_per_meta_chunk_nom_l; + unsigned int refcyc_per_meta_chunk_nom_c; + unsigned int refcyc_per_line_delivery_pre_l; + unsigned int refcyc_per_line_delivery_pre_c; + unsigned int refcyc_per_line_delivery_l; + unsigned int refcyc_per_line_delivery_c; + unsigned int chunk_hdl_adjust_cur0; +}; + +struct _vcs_dpi_display_ttu_regs_st { + unsigned int qos_level_low_wm; + unsigned int qos_level_high_wm; + unsigned int min_ttu_vblank; + unsigned int qos_level_flip; + unsigned int refcyc_per_req_delivery_l; + unsigned int refcyc_per_req_delivery_c; + unsigned int refcyc_per_req_delivery_cur0; + unsigned int refcyc_per_req_delivery_pre_l; + unsigned int refcyc_per_req_delivery_pre_c; + unsigned int refcyc_per_req_delivery_pre_cur0; + unsigned int qos_level_fixed_l; + unsigned int qos_level_fixed_c; + unsigned int qos_level_fixed_cur0; + unsigned int qos_ramp_disable_l; + unsigned int qos_ramp_disable_c; + unsigned int qos_ramp_disable_cur0; +}; + +struct _vcs_dpi_display_data_rq_regs_st { + unsigned int chunk_size; + unsigned int min_chunk_size; + unsigned int meta_chunk_size; + unsigned int min_meta_chunk_size; + unsigned int dpte_group_size; + unsigned int mpte_group_size; + unsigned int swath_height; + unsigned int pte_row_height_linear; +}; + +struct _vcs_dpi_display_rq_regs_st { + struct _vcs_dpi_display_data_rq_regs_st rq_regs_l; + struct _vcs_dpi_display_data_rq_regs_st rq_regs_c; + unsigned int drq_expansion_mode; + unsigned int prq_expansion_mode; + unsigned int mrq_expansion_mode; + unsigned int crq_expansion_mode; + unsigned int plane1_base_address; +}; + +struct _vcs_dpi_display_dlg_sys_params_st { + double t_mclk_wm_us; + double t_urg_wm_us; + double t_sr_wm_us; + double t_extra_us; + double t_srx_delay_us; + double deepsleep_dcfclk_mhz; + double total_flip_bw; + unsigned int total_flip_bytes; +}; + +struct _vcs_dpi_display_dlg_prefetch_param_st { + double prefetch_bw; + unsigned int flip_bytes; +}; + +struct _vcs_dpi_display_pipe_clock_st { + double dcfclk_mhz; + double dispclk_mhz; + double dppclk_mhz[4]; + unsigned char dppclk_div[4]; +}; + +struct _vcs_dpi_display_arb_params_st { + int max_req_outstanding; + int min_req_outstanding; + int sat_level_us; +}; + +struct _vcs_dpi_mode_evaluation_st { + int voltage_override; +}; + +#endif /*__DISPLAY_MODE_STRUCTS_H__*/ diff --git a/drivers/gpu/drm/amd/display/dc/dml/display_mode_support.c b/drivers/gpu/drm/amd/display/dc/dml/display_mode_support.c new file mode 100644 index 000000000000..3b4ee74527f5 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/dml/display_mode_support.c @@ -0,0 +1,2326 @@ +/* + * Copyright 2017 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 "display_mode_support.h" +#include "display_mode_lib.h" + +int dml_ms_check( + struct display_mode_lib *mode_lib, + struct _vcs_dpi_display_e2e_pipe_params_st *e2e, + int num_pipes) +{ + struct _vcs_dpi_ip_params_st *ip; + struct _vcs_dpi_soc_bounding_box_st *soc; + struct _vcs_dpi_mode_evaluation_st *me; + struct dml_ms_internal_vars *v; + int num_planes, i, j, ij, k, ijk; + + ip = &(mode_lib->ip); + soc = &(mode_lib->soc); + me = &(mode_lib->me); + v = &(mode_lib->vars); + num_planes = dml_wm_e2e_to_wm(mode_lib, e2e, num_pipes, v->planes); + + //instantiating variables to zero + v->MacroTileBlockWidthC = 0; + v->SwathWidthGranularityC = 0; + + v->DCFCLKPerState[5] = 0; + v->DCFCLKPerState[4] = 0; + v->DCFCLKPerState[3] = 0; + v->DCFCLKPerState[2] = 0; + v->DCFCLKPerState[1] = 0; + v->DCFCLKPerState[0] = 0; + + if (soc->vmin.dcfclk_mhz > 0) { + v->DCFCLKPerState[5] = soc->vmin.dcfclk_mhz; + v->DCFCLKPerState[4] = soc->vmin.dcfclk_mhz; + v->DCFCLKPerState[3] = soc->vmin.dcfclk_mhz; + v->DCFCLKPerState[2] = soc->vmin.dcfclk_mhz; + v->DCFCLKPerState[1] = soc->vmin.dcfclk_mhz; + v->DCFCLKPerState[0] = soc->vmin.dcfclk_mhz; + } + + if (soc->vmid.dcfclk_mhz > 0) { + v->DCFCLKPerState[5] = soc->vmid.dcfclk_mhz; + v->DCFCLKPerState[4] = soc->vmid.dcfclk_mhz; + v->DCFCLKPerState[3] = soc->vmid.dcfclk_mhz; + v->DCFCLKPerState[2] = soc->vmid.dcfclk_mhz; + v->DCFCLKPerState[1] = soc->vmid.dcfclk_mhz; + } + + if (soc->vnom.dcfclk_mhz > 0) { + v->DCFCLKPerState[5] = soc->vnom.dcfclk_mhz; + v->DCFCLKPerState[4] = soc->vnom.dcfclk_mhz; + v->DCFCLKPerState[3] = soc->vnom.dcfclk_mhz; + v->DCFCLKPerState[2] = soc->vnom.dcfclk_mhz; + } + + if (soc->vmax.dcfclk_mhz > 0) { + v->DCFCLKPerState[5] = soc->vmax.dcfclk_mhz; + v->DCFCLKPerState[4] = soc->vmax.dcfclk_mhz; + v->DCFCLKPerState[3] = soc->vmax.dcfclk_mhz; + } + + v->FabricAndDRAMBandwidthPerState[5] = 0; + v->FabricAndDRAMBandwidthPerState[4] = 0; + v->FabricAndDRAMBandwidthPerState[3] = 0; + v->FabricAndDRAMBandwidthPerState[2] = 0; + v->FabricAndDRAMBandwidthPerState[1] = 0; + v->FabricAndDRAMBandwidthPerState[0] = 0; + + if (soc->vmin.dram_bw_per_chan_gbps > 0) { + v->FabricAndDRAMBandwidthPerState[5] = soc->vmin.dram_bw_per_chan_gbps; + v->FabricAndDRAMBandwidthPerState[4] = soc->vmin.dram_bw_per_chan_gbps; + v->FabricAndDRAMBandwidthPerState[3] = soc->vmin.dram_bw_per_chan_gbps; + v->FabricAndDRAMBandwidthPerState[2] = soc->vmin.dram_bw_per_chan_gbps; + v->FabricAndDRAMBandwidthPerState[1] = soc->vmin.dram_bw_per_chan_gbps; + v->FabricAndDRAMBandwidthPerState[0] = soc->vmin.dram_bw_per_chan_gbps; + } + + if (soc->vmid.dram_bw_per_chan_gbps > 0) { + v->FabricAndDRAMBandwidthPerState[5] = soc->vmid.dram_bw_per_chan_gbps; + v->FabricAndDRAMBandwidthPerState[4] = soc->vmid.dram_bw_per_chan_gbps; + v->FabricAndDRAMBandwidthPerState[3] = soc->vmid.dram_bw_per_chan_gbps; + v->FabricAndDRAMBandwidthPerState[2] = soc->vmid.dram_bw_per_chan_gbps; + v->FabricAndDRAMBandwidthPerState[1] = soc->vmid.dram_bw_per_chan_gbps; + } + + if (soc->vnom.dram_bw_per_chan_gbps > 0) { + v->FabricAndDRAMBandwidthPerState[5] = soc->vnom.dram_bw_per_chan_gbps; + v->FabricAndDRAMBandwidthPerState[4] = soc->vnom.dram_bw_per_chan_gbps; + v->FabricAndDRAMBandwidthPerState[3] = soc->vnom.dram_bw_per_chan_gbps; + v->FabricAndDRAMBandwidthPerState[2] = soc->vnom.dram_bw_per_chan_gbps; + } + + if (soc->vmax.dram_bw_per_chan_gbps > 0) { + v->FabricAndDRAMBandwidthPerState[5] = soc->vmax.dram_bw_per_chan_gbps; + v->FabricAndDRAMBandwidthPerState[4] = soc->vmax.dram_bw_per_chan_gbps; + v->FabricAndDRAMBandwidthPerState[3] = soc->vmax.dram_bw_per_chan_gbps; + } + + v->PHYCLKPerState[5] = 0; + v->PHYCLKPerState[4] = 0; + v->PHYCLKPerState[3] = 0; + v->PHYCLKPerState[2] = 0; + v->PHYCLKPerState[1] = 0; + v->PHYCLKPerState[0] = 0; + + if (soc->vmin.phyclk_mhz > 0) { + v->PHYCLKPerState[5] = soc->vmin.phyclk_mhz; + v->PHYCLKPerState[4] = soc->vmin.phyclk_mhz; + v->PHYCLKPerState[3] = soc->vmin.phyclk_mhz; + v->PHYCLKPerState[2] = soc->vmin.phyclk_mhz; + v->PHYCLKPerState[1] = soc->vmin.phyclk_mhz; + v->PHYCLKPerState[0] = soc->vmin.phyclk_mhz; + } + + if (soc->vmid.phyclk_mhz > 0) { + v->PHYCLKPerState[5] = soc->vmid.phyclk_mhz; + v->PHYCLKPerState[4] = soc->vmid.phyclk_mhz; + v->PHYCLKPerState[3] = soc->vmid.phyclk_mhz; + v->PHYCLKPerState[2] = soc->vmid.phyclk_mhz; + v->PHYCLKPerState[1] = soc->vmid.phyclk_mhz; + } + + if (soc->vnom.phyclk_mhz > 0) { + v->PHYCLKPerState[5] = soc->vnom.phyclk_mhz; + v->PHYCLKPerState[4] = soc->vnom.phyclk_mhz; + v->PHYCLKPerState[3] = soc->vnom.phyclk_mhz; + v->PHYCLKPerState[2] = soc->vnom.phyclk_mhz; + } + + if (soc->vmax.phyclk_mhz > 0) { + v->PHYCLKPerState[5] = soc->vmax.phyclk_mhz; + v->PHYCLKPerState[4] = soc->vmax.phyclk_mhz; + v->PHYCLKPerState[3] = soc->vmax.phyclk_mhz; + } + + v->MaxDispclk[5] = 0; + v->MaxDispclk[4] = 0; + v->MaxDispclk[3] = 0; + v->MaxDispclk[2] = 0; + v->MaxDispclk[1] = 0; + v->MaxDispclk[0] = 0; + + if (soc->vmin.dispclk_mhz > 0) { + v->MaxDispclk[5] = soc->vmin.dispclk_mhz; + v->MaxDispclk[4] = soc->vmin.dispclk_mhz; + v->MaxDispclk[3] = soc->vmin.dispclk_mhz; + v->MaxDispclk[2] = soc->vmin.dispclk_mhz; + v->MaxDispclk[1] = soc->vmin.dispclk_mhz; + v->MaxDispclk[0] = soc->vmin.dispclk_mhz; + } + + if (soc->vmid.dispclk_mhz > 0) { + v->MaxDispclk[5] = soc->vmid.dispclk_mhz; + v->MaxDispclk[4] = soc->vmid.dispclk_mhz; + v->MaxDispclk[3] = soc->vmid.dispclk_mhz; + v->MaxDispclk[2] = soc->vmid.dispclk_mhz; + v->MaxDispclk[1] = soc->vmid.dispclk_mhz; + } + + if (soc->vnom.dispclk_mhz > 0) { + v->MaxDispclk[5] = soc->vnom.dispclk_mhz; + v->MaxDispclk[4] = soc->vnom.dispclk_mhz; + v->MaxDispclk[3] = soc->vnom.dispclk_mhz; + v->MaxDispclk[2] = soc->vnom.dispclk_mhz; + } + + if (soc->vmax.dispclk_mhz > 0) { + v->MaxDispclk[5] = soc->vmax.dispclk_mhz; + v->MaxDispclk[4] = soc->vmax.dispclk_mhz; + v->MaxDispclk[3] = soc->vmax.dispclk_mhz; + } + + v->MaxDppclk[5] = 0; + v->MaxDppclk[4] = 0; + v->MaxDppclk[3] = 0; + v->MaxDppclk[2] = 0; + v->MaxDppclk[1] = 0; + v->MaxDppclk[0] = 0; + + if (soc->vmin.dppclk_mhz > 0) { + v->MaxDppclk[5] = soc->vmin.dppclk_mhz; + v->MaxDppclk[4] = soc->vmin.dppclk_mhz; + v->MaxDppclk[3] = soc->vmin.dppclk_mhz; + v->MaxDppclk[2] = soc->vmin.dppclk_mhz; + v->MaxDppclk[1] = soc->vmin.dppclk_mhz; + v->MaxDppclk[0] = soc->vmin.dppclk_mhz; + } + + if (soc->vmid.dppclk_mhz > 0) { + v->MaxDppclk[5] = soc->vmid.dppclk_mhz; + v->MaxDppclk[4] = soc->vmid.dppclk_mhz; + v->MaxDppclk[3] = soc->vmid.dppclk_mhz; + v->MaxDppclk[2] = soc->vmid.dppclk_mhz; + v->MaxDppclk[1] = soc->vmid.dppclk_mhz; + } + + if (soc->vnom.dppclk_mhz > 0) { + v->MaxDppclk[5] = soc->vnom.dppclk_mhz; + v->MaxDppclk[4] = soc->vnom.dppclk_mhz; + v->MaxDppclk[3] = soc->vnom.dppclk_mhz; + v->MaxDppclk[2] = soc->vnom.dppclk_mhz; + } + + if (soc->vmax.dppclk_mhz > 0) { + v->MaxDppclk[5] = soc->vmax.dppclk_mhz; + v->MaxDppclk[4] = soc->vmax.dppclk_mhz; + v->MaxDppclk[3] = soc->vmax.dppclk_mhz; + } + + if (me->voltage_override == dm_vmax) { + v->VoltageOverrideLevel = NumberOfStates - 1; + } else if (me->voltage_override == dm_vnom) { + v->VoltageOverrideLevel = NumberOfStates - 2; + } else if (me->voltage_override == dm_vmid) { + v->VoltageOverrideLevel = NumberOfStates - 3; + } else { + v->VoltageOverrideLevel = 0; + } + + // Scale Ratio Support Check + + v->ScaleRatioSupport = 1; + + for (k = 0; k < num_planes; k++) { + struct _vcs_dpi_scaler_ratio_depth_st scale_ratio_depth = + e2e[v->planes[k].e2e_index].pipe.scale_ratio_depth; + struct _vcs_dpi_scaler_taps_st scale_taps = + e2e[v->planes[k].e2e_index].pipe.scale_taps; + struct _vcs_dpi_display_pipe_source_params_st src = + e2e[v->planes[k].e2e_index].pipe.src; + + if (scale_ratio_depth.hscl_ratio > ip->max_hscl_ratio + || scale_ratio_depth.vscl_ratio > ip->max_vscl_ratio + || scale_ratio_depth.hscl_ratio > scale_taps.htaps + || scale_ratio_depth.vscl_ratio > scale_taps.vtaps + || (src.source_format != dm_444_64 && src.source_format != dm_444_32 + && src.source_format != dm_444_16 + && ((scale_ratio_depth.hscl_ratio / 2 + > scale_taps.htaps_c) + || (scale_ratio_depth.vscl_ratio / 2 + > scale_taps.vtaps_c)))) + + { + v->ScaleRatioSupport = 0; + } + } + + // Source Format, Pixel Format and Scan Support Check + + v->SourceFormatPixelAndScanSupport = 1; + + for (k = 0; k < num_planes; k++) { + struct _vcs_dpi_display_pipe_source_params_st src = + e2e[v->planes[k].e2e_index].pipe.src; + + if ((src.sw_mode == dm_sw_linear && src.source_scan != dm_horz) + || ((src.sw_mode == dm_sw_4kb_d || src.sw_mode == dm_sw_4kb_d_x + || src.sw_mode == dm_sw_64kb_d + || src.sw_mode == dm_sw_64kb_d_t + || src.sw_mode == dm_sw_64kb_d_x + || src.sw_mode == dm_sw_var_d + || src.sw_mode == dm_sw_var_d_x) + && (src.source_format != dm_444_64))) { + v->SourceFormatPixelAndScanSupport = 0; + } + } + + // Bandwidth Support Check + + for (k = 0; k < num_planes; k++) { + struct _vcs_dpi_display_pipe_source_params_st src = + e2e[v->planes[k].e2e_index].pipe.src; + + if (src.source_scan == dm_horz) { + v->SwathWidthYSingleDPP[k] = src.viewport_width; + } else { + v->SwathWidthYSingleDPP[k] = src.viewport_height; + } + + if (src.source_format == dm_444_64) { + v->BytePerPixelInDETY[k] = 8; + v->BytePerPixelInDETC[k] = 0; + } else if (src.source_format == dm_444_32) { + v->BytePerPixelInDETY[k] = 4; + v->BytePerPixelInDETC[k] = 0; + } else if (src.source_format == dm_444_16) { + v->BytePerPixelInDETY[k] = 2; + v->BytePerPixelInDETC[k] = 0; + } else if (src.source_format == dm_420_8) { + v->BytePerPixelInDETY[k] = 1; + v->BytePerPixelInDETC[k] = 2; + } else { + v->BytePerPixelInDETY[k] = 4.00 / 3.00; + v->BytePerPixelInDETC[k] = 8.00 / 3.00; + } + } + + v->TotalReadBandwidthConsumedGBytePerSecond = 0; + + for (k = 0; k < num_planes; k++) { + struct _vcs_dpi_display_pipe_source_params_st src = + e2e[v->planes[k].e2e_index].pipe.src; + struct _vcs_dpi_display_pipe_dest_params_st dest = + e2e[v->planes[k].e2e_index].pipe.dest; + struct _vcs_dpi_scaler_ratio_depth_st scale_ratio_depth = + e2e[v->planes[k].e2e_index].pipe.scale_ratio_depth; + + v->ReadBandwidth[k] = + v->SwathWidthYSingleDPP[k] + * (dml_ceil_ex(v->BytePerPixelInDETY[k], 1) + * scale_ratio_depth.vscl_ratio + + (dml_ceil_ex( + v->BytePerPixelInDETC[k], + 2) / 2) + * (scale_ratio_depth.vscl_ratio + / 2)) + / (dest.htotal / dest.pixel_rate_mhz); + + if (src.dcc == 1) { + v->ReadBandwidth[k] = v->ReadBandwidth[k] * (1 + 1 / 256); + } + + if (ip->pte_enable == 1 && src.source_scan != dm_horz + && (src.sw_mode == dm_sw_4kb_s || src.sw_mode == dm_sw_4kb_s_x + || src.sw_mode == dm_sw_4kb_d + || src.sw_mode == dm_sw_4kb_d_x)) { + v->ReadBandwidth[k] = v->ReadBandwidth[k] * (1 + 1 / 64); + } else if (ip->pte_enable == 1 && src.source_scan == dm_horz + && (src.source_format == dm_444_64 || src.source_format == dm_444_32) + && (src.sw_mode == dm_sw_64kb_s || src.sw_mode == dm_sw_64kb_s_t + || src.sw_mode == dm_sw_64kb_s_x + || src.sw_mode == dm_sw_64kb_d + || src.sw_mode == dm_sw_64kb_d_t + || src.sw_mode == dm_sw_64kb_d_x)) { + v->ReadBandwidth[k] = v->ReadBandwidth[k] * (1 + 1 / 256); + } else if (ip->pte_enable == 1) { + v->ReadBandwidth[k] = v->ReadBandwidth[k] * (1 + 1 / 512); + } + + v->TotalReadBandwidthConsumedGBytePerSecond = + v->TotalReadBandwidthConsumedGBytePerSecond + + v->ReadBandwidth[k] / 1000; + } + + v->TotalWriteBandwidthConsumedGBytePerSecond = 0; + + for (k = 0; k < num_planes; k++) { + struct _vcs_dpi_display_pipe_dest_params_st dest = + e2e[v->planes[k].e2e_index].pipe.dest; + struct _vcs_dpi_display_output_params_st dout = e2e[v->planes[k].e2e_index].dout; + + if (dout.output_type == dm_wb && dout.output_format == dm_444) { + v->WriteBandwidth[k] = dest.recout_width + / (dest.htotal / dest.pixel_rate_mhz) * 4; + } else if (dout.output_type == dm_wb) { + v->WriteBandwidth[k] = dest.recout_width + / (dest.htotal / dest.pixel_rate_mhz) * 1.5; + } else { + v->WriteBandwidth[k] = 0; + } + + v->TotalWriteBandwidthConsumedGBytePerSecond = + v->TotalWriteBandwidthConsumedGBytePerSecond + + v->WriteBandwidth[k] / 1000; + } + + v->TotalBandwidthConsumedGBytePerSecond = v->TotalReadBandwidthConsumedGBytePerSecond + + v->TotalWriteBandwidthConsumedGBytePerSecond; + + v->DCCEnabledInAnyPlane = 0; + + for (k = 0; k < num_planes; k++) { + struct _vcs_dpi_display_pipe_source_params_st src = + e2e[v->planes[k].e2e_index].pipe.src; + + if (src.dcc == 1) { + v->DCCEnabledInAnyPlane = 1; + } + } + + for (i = 0; i < NumberOfStatesPlusTwo; i++) { + v->ReturnBWToDCNPerState = dml_min( + soc->return_bus_width_bytes * v->DCFCLKPerState[i], + v->FabricAndDRAMBandwidthPerState[i] * 1000 + * soc->ideal_dram_bw_after_urgent_percent / 100); + + v->ReturnBWPerState[i] = v->ReturnBWToDCNPerState; + + if (v->DCCEnabledInAnyPlane == 1 + && v->ReturnBWToDCNPerState + > (v->DCFCLKPerState[i] + * soc->return_bus_width_bytes / 4)) { + v->ReturnBWPerState[i] = + dml_min( + v->ReturnBWPerState[i], + v->ReturnBWToDCNPerState * 4 + * (1 + - soc->urgent_latency_us + / ((ip->rob_buffer_size_kbytes + - ip->pixel_chunk_size_kbytes) + * 1024 + / (v->ReturnBWToDCNPerState + - v->DCFCLKPerState[i] + * soc->return_bus_width_bytes + / 4) + + soc->urgent_latency_us))); + } + + v->CriticalPoint = 2 * soc->return_bus_width_bytes * v->DCFCLKPerState[i] + * soc->urgent_latency_us + / (v->ReturnBWToDCNPerState * soc->urgent_latency_us + + (ip->rob_buffer_size_kbytes + - ip->pixel_chunk_size_kbytes) + * 1024); + + if (v->DCCEnabledInAnyPlane == 1 && v->CriticalPoint > 1 && v->CriticalPoint < 4) { + v->ReturnBWPerState[i] = + dml_min( + v->ReturnBWPerState[i], + 4 * v->ReturnBWToDCNPerState + * (ip->rob_buffer_size_kbytes + - ip->pixel_chunk_size_kbytes) + * 1024 + * soc->return_bus_width_bytes + * v->DCFCLKPerState[i] + * soc->urgent_latency_us + / dml_pow( + (v->ReturnBWToDCNPerState + * soc->urgent_latency_us + + (ip->rob_buffer_size_kbytes + - ip->pixel_chunk_size_kbytes) + * 1024), + 2)); + } + + v->ReturnBWToDCNPerState = dml_min( + soc->return_bus_width_bytes * v->DCFCLKPerState[i], + v->FabricAndDRAMBandwidthPerState[i] * 1000); + + if (v->DCCEnabledInAnyPlane == 1 + && v->ReturnBWToDCNPerState + > (v->DCFCLKPerState[i] + * soc->return_bus_width_bytes / 4)) { + v->ReturnBWPerState[i] = + dml_min( + v->ReturnBWPerState[i], + v->ReturnBWToDCNPerState * 4 + * (1 + - soc->urgent_latency_us + / ((ip->rob_buffer_size_kbytes + - ip->pixel_chunk_size_kbytes) + * 1024 + / (v->ReturnBWToDCNPerState + - v->DCFCLKPerState[i] + * soc->return_bus_width_bytes + / 4) + + soc->urgent_latency_us))); + } + + v->CriticalPoint = 2 * soc->return_bus_width_bytes * v->DCFCLKPerState[i] + * soc->urgent_latency_us + / (v->ReturnBWToDCNPerState * soc->urgent_latency_us + + (ip->rob_buffer_size_kbytes + - ip->pixel_chunk_size_kbytes) + * 1024); + + if (v->DCCEnabledInAnyPlane == 1 && v->CriticalPoint > 1 && v->CriticalPoint < 4) { + v->ReturnBWPerState[i] = + dml_min( + v->ReturnBWPerState[i], + 4 * v->ReturnBWToDCNPerState + * (ip->rob_buffer_size_kbytes + - ip->pixel_chunk_size_kbytes) + * 1024 + * soc->return_bus_width_bytes + * v->DCFCLKPerState[i] + * soc->urgent_latency_us + / dml_pow( + (v->ReturnBWToDCNPerState + * soc->urgent_latency_us + + (ip->rob_buffer_size_kbytes + - ip->pixel_chunk_size_kbytes) + * 1024), + 2)); + } + } + + for (i = 0; i < NumberOfStatesPlusTwo; i++) { + if ((v->TotalReadBandwidthConsumedGBytePerSecond * 1000 <= v->ReturnBWPerState[i]) + && (v->TotalBandwidthConsumedGBytePerSecond * 1000 + <= v->FabricAndDRAMBandwidthPerState[i] * 1000 + * soc->ideal_dram_bw_after_urgent_percent + / 100)) { + v->BandwidthSupport[i] = 1; + } else { + v->BandwidthSupport[i] = 0; + } + } + + // Writeback Latency support check + + v->WritebackLatencySupport = 1; + + for (k = 0; k < num_planes; k++) { + struct _vcs_dpi_display_pipe_dest_params_st dest = + e2e[v->planes[k].e2e_index].pipe.dest; + struct _vcs_dpi_display_output_params_st dout = e2e[v->planes[k].e2e_index].dout; + + if (dout.output_type == dm_wb && dout.output_format == dm_444 + && (dest.recout_width / (dest.htotal / dest.pixel_rate_mhz) * 4) + > ((ip->writeback_luma_buffer_size_kbytes + + ip->writeback_chroma_buffer_size_kbytes) + * 1024 / soc->writeback_latency_us)) { + v->WritebackLatencySupport = 0; + } else if (dout.output_type == dm_wb + && (dest.recout_width / (dest.htotal / dest.pixel_rate_mhz)) + > (dml_min( + ip->writeback_luma_buffer_size_kbytes, + 2 + * ip->writeback_chroma_buffer_size_kbytes) + * 1024 / soc->writeback_latency_us)) { + v->WritebackLatencySupport = 0; + } + } + + // Re-ordering Buffer Support Check + + for (i = 0; i < NumberOfStatesPlusTwo; i++) { + v->UrgentRoundTripAndOutOfOrderLatencyPerState[i] = + (soc->round_trip_ping_latency_dcfclk_cycles + 32) + / v->DCFCLKPerState[i] + + soc->urgent_out_of_order_return_per_channel_bytes + * soc->num_chans + / v->ReturnBWPerState[i]; + + if ((ip->rob_buffer_size_kbytes - ip->pixel_chunk_size_kbytes) * 1024 + / v->ReturnBWPerState[i] + > v->UrgentRoundTripAndOutOfOrderLatencyPerState[i]) { + v->ROBSupport[i] = 1; + } else { + v->ROBSupport[i] = 0; + } + } + + // Display IO Support Check + + for (k = 0; k < num_planes; k++) { + struct _vcs_dpi_display_pipe_dest_params_st dest = + e2e[v->planes[k].e2e_index].pipe.dest; + struct _vcs_dpi_display_output_params_st dout = e2e[v->planes[k].e2e_index].dout; + + if (dout.output_format == dm_420) { + v->RequiredOutputBW = dest.pixel_rate_mhz * 3 / 2; + } else { + v->RequiredOutputBW = dest.pixel_rate_mhz * 3; + } + + if (dout.output_type == dm_hdmi) { + v->RequiredPHYCLK[k] = v->RequiredOutputBW / 3; + } else if (dout.output_type == dm_dp) { + v->RequiredPHYCLK[k] = v->RequiredOutputBW / 4; + } else { + v->RequiredPHYCLK[k] = 0; + } + } + + for (i = 0; i < NumberOfStatesPlusTwo; i++) { + v->DIOSupport[i] = 1; + + for (k = 0; k < num_planes; k++) { + struct _vcs_dpi_display_output_params_st dout = + e2e[v->planes[k].e2e_index].dout; + + if ((v->RequiredPHYCLK[k] > v->PHYCLKPerState[i]) + || (dout.output_type == dm_hdmi + && v->RequiredPHYCLK[k] > 600)) { + v->DIOSupport[i] = 0; + } + } + } + + // Total Available Writeback Support Check + + v->TotalNumberOfActiveWriteback = 0; + + for (k = 0; k < num_planes; k++) { + struct _vcs_dpi_display_output_params_st dout = e2e[v->planes[k].e2e_index].dout; + + if (dout.output_type == dm_wb) { + v->TotalNumberOfActiveWriteback = v->TotalNumberOfActiveWriteback + 1; + } + } + + if (v->TotalNumberOfActiveWriteback <= ip->max_num_wb) { + v->TotalAvailableWritebackSupport = 1; + } else { + v->TotalAvailableWritebackSupport = 0; + } + + // Maximum DISPCLK/DPPCLK Support check + + for (k = 0; k < num_planes; k++) { + struct _vcs_dpi_display_pipe_dest_params_st dest = + e2e[v->planes[k].e2e_index].pipe.dest; + struct _vcs_dpi_scaler_ratio_depth_st scale_ratio_depth = + e2e[v->planes[k].e2e_index].pipe.scale_ratio_depth; + struct _vcs_dpi_scaler_taps_st scale_taps = + e2e[v->planes[k].e2e_index].pipe.scale_taps; + + if (scale_ratio_depth.hscl_ratio > 1) { + v->PSCL_FACTOR[k] = dml_min( + ip->max_dchub_pscl_bw_pix_per_clk, + ip->max_pscl_lb_bw_pix_per_clk + * scale_ratio_depth.hscl_ratio + / dml_ceil_ex(scale_taps.htaps / 6, 1)); + } else { + v->PSCL_FACTOR[k] = dml_min( + ip->max_dchub_pscl_bw_pix_per_clk, + ip->max_pscl_lb_bw_pix_per_clk); + } + + if (v->BytePerPixelInDETC[k] == 0) { + v->PSCL_FACTOR_CHROMA[k] = 0; + v->MinDPPCLKUsingSingleDPP[k] = + dest.pixel_rate_mhz + * dml_max( + scale_taps.vtaps / 6 + * dml_min( + 1, + scale_ratio_depth.hscl_ratio), + dml_max( + scale_ratio_depth.hscl_ratio + * scale_ratio_depth.vscl_ratio + / v->PSCL_FACTOR[k], + 1)); + + } else { + if (scale_ratio_depth.hscl_ratio / 2 > 1) { + v->PSCL_FACTOR_CHROMA[k] = dml_min( + ip->max_dchub_pscl_bw_pix_per_clk, + ip->max_pscl_lb_bw_pix_per_clk + * scale_ratio_depth.hscl_ratio / 2 + / dml_ceil_ex( + scale_taps.htaps_c + / 6, + 1)); + } else { + v->PSCL_FACTOR_CHROMA[k] = dml_min( + ip->max_dchub_pscl_bw_pix_per_clk, + ip->max_pscl_lb_bw_pix_per_clk); + } + v->MinDPPCLKUsingSingleDPP[k] = + dest.pixel_rate_mhz + * dml_max( + dml_max( + scale_taps.vtaps + / 6 + * dml_min( + 1, + scale_ratio_depth.hscl_ratio), + scale_ratio_depth.hscl_ratio + * scale_ratio_depth.vscl_ratio + / v->PSCL_FACTOR[k]), + dml_max( + dml_max( + scale_taps.vtaps_c + / 6 + * dml_min( + 1, + scale_ratio_depth.hscl_ratio + / 2), + scale_ratio_depth.hscl_ratio + * scale_ratio_depth.vscl_ratio + / 4 + / v->PSCL_FACTOR_CHROMA[k]), + 1)); + + } + } + + for (k = 0; k < num_planes; k++) { + struct _vcs_dpi_display_pipe_source_params_st src = + e2e[v->planes[k].e2e_index].pipe.src; + struct _vcs_dpi_scaler_ratio_depth_st scale_ratio_depth = + e2e[v->planes[k].e2e_index].pipe.scale_ratio_depth; + struct _vcs_dpi_scaler_taps_st scale_taps = + e2e[v->planes[k].e2e_index].pipe.scale_taps; + + if (src.source_format == dm_444_64 || src.source_format == dm_444_32 + || src.source_format == dm_444_16) { + if (src.sw_mode == dm_sw_linear) { + v->Read256BlockHeightY[k] = 1; + } else if (src.source_format == dm_444_64) { + v->Read256BlockHeightY[k] = 4; + } else { + v->Read256BlockHeightY[k] = 8; + } + + v->Read256BlockWidthY[k] = 256 / dml_ceil_ex(v->BytePerPixelInDETY[k], 1) + / v->Read256BlockHeightY[k]; + v->Read256BlockHeightC[k] = 0; + v->Read256BlockWidthC[k] = 0; + } else { + if (src.sw_mode == dm_sw_linear) { + v->Read256BlockHeightY[k] = 1; + v->Read256BlockHeightC[k] = 1; + } else if (src.source_format == dm_420_8) { + v->Read256BlockHeightY[k] = 16; + v->Read256BlockHeightC[k] = 8; + } else { + v->Read256BlockHeightY[k] = 8; + v->Read256BlockHeightC[k] = 8; + } + + v->Read256BlockWidthY[k] = 256 / dml_ceil_ex(v->BytePerPixelInDETY[k], 1) + / v->Read256BlockHeightY[k]; + v->Read256BlockWidthC[k] = 256 / dml_ceil_ex(v->BytePerPixelInDETC[k], 2) + / v->Read256BlockHeightC[k]; + } + + if (src.source_scan == dm_horz) { + v->MaxSwathHeightY[k] = v->Read256BlockHeightY[k]; + v->MaxSwathHeightC[k] = v->Read256BlockHeightC[k]; + } else { + v->MaxSwathHeightY[k] = v->Read256BlockWidthY[k]; + v->MaxSwathHeightC[k] = v->Read256BlockWidthC[k]; + } + + if (src.source_format == dm_444_64 || src.source_format == dm_444_32 + || src.source_format == dm_444_16) { + if (src.sw_mode == dm_sw_linear + || (src.source_format == dm_444_64 + && (src.sw_mode == dm_sw_4kb_s + || src.sw_mode + == dm_sw_4kb_s_x + || src.sw_mode + == dm_sw_64kb_s + || src.sw_mode + == dm_sw_64kb_s_t + || src.sw_mode + == dm_sw_64kb_s_x + || src.sw_mode + == dm_sw_var_s + || src.sw_mode + == dm_sw_var_s_x) + && src.source_scan == dm_horz)) { + v->MinSwathHeightY[k] = v->MaxSwathHeightY[k]; + } else { + v->MinSwathHeightY[k] = v->MaxSwathHeightY[k] / 2; + } + v->MinSwathHeightC[k] = v->MaxSwathHeightC[k]; + } else { + if (src.sw_mode == dm_sw_linear) { + v->MinSwathHeightY[k] = v->MaxSwathHeightY[k]; + v->MinSwathHeightC[k] = v->MaxSwathHeightC[k]; + } else if (src.source_format == dm_420_8 && src.source_scan == dm_horz) { + v->MinSwathHeightY[k] = v->MaxSwathHeightY[k] / 2; + if (ip->bug_forcing_LC_req_same_size_fixed == 1) { + v->MinSwathHeightC[k] = v->MaxSwathHeightC[k]; + } else { + v->MinSwathHeightC[k] = v->MaxSwathHeightC[k] / 2; + } + } else if (src.source_format == dm_420_10 && src.source_scan == dm_horz) { + v->MinSwathHeightC[k] = v->MaxSwathHeightC[k] / 2; + if (ip->bug_forcing_LC_req_same_size_fixed == 1) { + v->MinSwathHeightY[k] = v->MaxSwathHeightY[k]; + } else { + v->MinSwathHeightY[k] = v->MaxSwathHeightY[k] / 2; + } + } else { + v->MinSwathHeightY[k] = v->MaxSwathHeightY[k]; + v->MinSwathHeightC[k] = v->MaxSwathHeightC[k]; + } + } + + if (src.sw_mode == dm_sw_linear) { + v->MaximumSwathWidth = 8192; + } else { + v->MaximumSwathWidth = 5120; + } + + v->NumberOfDPPRequiredForDETSize = + dml_ceil_ex( + v->SwathWidthYSingleDPP[k] + / dml_min( + v->MaximumSwathWidth, + ip->det_buffer_size_kbytes + * 1024 + / 2 + / (v->BytePerPixelInDETY[k] + * v->MinSwathHeightY[k] + + v->BytePerPixelInDETC[k] + / 2 + * v->MinSwathHeightC[k])), + 1); + + if (v->BytePerPixelInDETC[k] == 0) { + v->NumberOfDPPRequiredForLBSize = + dml_ceil_ex( + (scale_taps.vtaps + + dml_max( + dml_ceil_ex( + scale_ratio_depth.vscl_ratio, + 1) + - 2, + 0)) + * v->SwathWidthYSingleDPP[k] + / dml_max( + scale_ratio_depth.hscl_ratio, + 1) + * scale_ratio_depth.lb_depth + / ip->line_buffer_size_bits, + 1); + } else { + v->NumberOfDPPRequiredForLBSize = + dml_max( + dml_ceil_ex( + (scale_taps.vtaps + + dml_max( + dml_ceil_ex( + scale_ratio_depth.vscl_ratio, + 1) + - 2, + 0)) + * v->SwathWidthYSingleDPP[k] + / dml_max( + scale_ratio_depth.hscl_ratio, + 1) + * scale_ratio_depth.lb_depth + / ip->line_buffer_size_bits, + 1), + dml_ceil_ex( + (scale_taps.vtaps_c + + dml_max( + dml_ceil_ex( + scale_ratio_depth.vscl_ratio + / 2, + 1) + - 2, + 0)) + * v->SwathWidthYSingleDPP[k] + / 2 + / dml_max( + scale_ratio_depth.hscl_ratio + / 2, + 1) + * scale_ratio_depth.lb_depth + / ip->line_buffer_size_bits, + 1)); + } + + v->NumberOfDPPRequiredForDETAndLBSize[k] = dml_max( + v->NumberOfDPPRequiredForDETSize, + v->NumberOfDPPRequiredForLBSize); + + } + + for (i = 0; i < NumberOfStatesPlusTwo; i++) { + for (j = 0; j < 2; j++) { + v->TotalNumberOfActiveDPP[j * NumberOfStatesPlusTwo + i] = 0; + v->RequiredDISPCLK[j * NumberOfStatesPlusTwo + i] = 0; + v->DISPCLK_DPPCLK_Support[j * NumberOfStatesPlusTwo + i] = 1; + + for (k = 0; k < num_planes; k++) { + struct _vcs_dpi_display_pipe_dest_params_st dest = + e2e[v->planes[k].e2e_index].pipe.dest; + ijk = k * 2 * NumberOfStatesPlusTwo + j * NumberOfStatesPlusTwo + i; + + v->MinDispclkUsingSingleDPP = dml_max( + dest.pixel_rate_mhz, + v->MinDPPCLKUsingSingleDPP[k] * (j + 1)) + * (1 + soc->downspread_percent / 100); + v->MinDispclkUsingDualDPP = dml_max( + dest.pixel_rate_mhz, + v->MinDPPCLKUsingSingleDPP[k] / 2 * (j + 1)) + * (1 + soc->downspread_percent / 100); + + if (i < NumberOfStates) { + v->MinDispclkUsingSingleDPP = + v->MinDispclkUsingSingleDPP + * (1 + + ip->dispclk_ramp_margin_percent + / 100); + v->MinDispclkUsingDualDPP = + v->MinDispclkUsingDualDPP + * (1 + + ip->dispclk_ramp_margin_percent + / 100); + } + + if (v->MinDispclkUsingSingleDPP + <= dml_min( + v->MaxDispclk[i], + (j + 1) * v->MaxDppclk[i]) + && v->NumberOfDPPRequiredForDETAndLBSize[k] <= 1) { + v->NoOfDPP[ijk] = 1; + v->RequiredDISPCLK[j * NumberOfStatesPlusTwo + i] = dml_max( + v->RequiredDISPCLK[j * NumberOfStatesPlusTwo + + i], + v->MinDispclkUsingSingleDPP); + } else if (v->MinDispclkUsingDualDPP + <= dml_min( + v->MaxDispclk[i], + (j + 1) * v->MaxDppclk[i])) { + v->NoOfDPP[ijk] = 2; + v->RequiredDISPCLK[j * NumberOfStatesPlusTwo + i] = dml_max( + v->RequiredDISPCLK[j * NumberOfStatesPlusTwo + + i], + v->MinDispclkUsingDualDPP); + } else { + v->NoOfDPP[ijk] = 2; + v->RequiredDISPCLK[j * NumberOfStatesPlusTwo + i] = dml_max( + v->RequiredDISPCLK[j * NumberOfStatesPlusTwo + + i], + v->MinDispclkUsingDualDPP); + v->DISPCLK_DPPCLK_Support[j * NumberOfStatesPlusTwo + i] = + 0; + } + + v->TotalNumberOfActiveDPP[j * NumberOfStatesPlusTwo + i] = + v->TotalNumberOfActiveDPP[j * NumberOfStatesPlusTwo + + i] + v->NoOfDPP[ijk]; + } + + if (v->TotalNumberOfActiveDPP[j * NumberOfStatesPlusTwo + i] + > ip->max_num_dpp) { + v->TotalNumberOfActiveDPP[j * NumberOfStatesPlusTwo + i] = 0; + v->RequiredDISPCLK[j * NumberOfStatesPlusTwo + i] = 0; + v->DISPCLK_DPPCLK_Support[j * NumberOfStatesPlusTwo + i] = 1; + + for (k = 0; k < num_planes; k++) { + struct _vcs_dpi_display_pipe_dest_params_st dest = + e2e[v->planes[k].e2e_index].pipe.dest; + ijk = k * 2 * NumberOfStatesPlusTwo + + j * NumberOfStatesPlusTwo + i; + + v->MinDispclkUsingSingleDPP = dml_max( + dest.pixel_rate_mhz, + v->MinDPPCLKUsingSingleDPP[k] * (j + 1)) + * (1 + soc->downspread_percent / 100); + v->MinDispclkUsingDualDPP = dml_max( + dest.pixel_rate_mhz, + v->MinDPPCLKUsingSingleDPP[k] / 2 * (j + 1)) + * (1 + soc->downspread_percent / 100); + + if (i < NumberOfStates) { + v->MinDispclkUsingSingleDPP = + v->MinDispclkUsingSingleDPP + * (1 + + ip->dispclk_ramp_margin_percent + / 100); + v->MinDispclkUsingDualDPP = + v->MinDispclkUsingDualDPP + * (1 + + ip->dispclk_ramp_margin_percent + / 100); + } + + if (v->NumberOfDPPRequiredForDETAndLBSize[k] <= 1) { + v->NoOfDPP[ijk] = 1; + v->RequiredDISPCLK[j * NumberOfStatesPlusTwo + i] = + dml_max( + v->RequiredDISPCLK[j + * NumberOfStatesPlusTwo + + i], + v->MinDispclkUsingSingleDPP); + if (v->MinDispclkUsingSingleDPP + > dml_min( + v->MaxDispclk[i], + (j + 1) + * v->MaxDppclk[i])) { + v->DISPCLK_DPPCLK_Support[j + * NumberOfStatesPlusTwo + i] = + 0; + } + } else { + v->NoOfDPP[ijk] = 2; + v->RequiredDISPCLK[j * NumberOfStatesPlusTwo + i] = + dml_max( + v->RequiredDISPCLK[j + * NumberOfStatesPlusTwo + + i], + v->MinDispclkUsingDualDPP); + if (v->MinDispclkUsingDualDPP + > dml_min( + v->MaxDispclk[i], + (j + 1) + * v->MaxDppclk[i])) { + v->DISPCLK_DPPCLK_Support[j + * NumberOfStatesPlusTwo + i] = + 0; + } + } + v->TotalNumberOfActiveDPP[j * NumberOfStatesPlusTwo + i] = + v->TotalNumberOfActiveDPP[j + * NumberOfStatesPlusTwo + i] + + v->NoOfDPP[ijk]; + } + } + } + } + + // Viewport Size Check + + v->ViewportSizeSupport = 1; + + for (k = 0; k < num_planes; k++) { + if (v->NumberOfDPPRequiredForDETAndLBSize[k] > 2) { + v->ViewportSizeSupport = 0; + } + } + + // Total Available Pipes Support Check + + for (i = 0; i < NumberOfStatesPlusTwo; i++) { + for (j = 0; j < 2; j++) { + if (v->TotalNumberOfActiveDPP[j * NumberOfStatesPlusTwo + i] + <= ip->max_num_dpp) { + v->TotalAvailablePipesSupport[j * NumberOfStatesPlusTwo + i] = 1; + } else { + v->TotalAvailablePipesSupport[j * NumberOfStatesPlusTwo + i] = 0; + } + } + } + + // Urgent Latency Support Check + + for (j = 0; j < 2; j++) { + for (i = 0; i < NumberOfStatesPlusTwo; i++) { + ij = j * NumberOfStatesPlusTwo + i; + for (k = 0; k < num_planes; k++) { + struct _vcs_dpi_display_pipe_source_params_st src = + e2e[v->planes[k].e2e_index].pipe.src; + struct _vcs_dpi_display_pipe_dest_params_st dest = + e2e[v->planes[k].e2e_index].pipe.dest; + struct _vcs_dpi_scaler_ratio_depth_st scale_ratio_depth = + e2e[v->planes[k].e2e_index].pipe.scale_ratio_depth; + struct _vcs_dpi_scaler_taps_st scale_taps = + e2e[v->planes[k].e2e_index].pipe.scale_taps; + ijk = k * 2 * NumberOfStatesPlusTwo + j * NumberOfStatesPlusTwo + i; + + v->SwathWidthYPerState[ijk] = v->SwathWidthYSingleDPP[k] + / v->NoOfDPP[ijk]; + + v->SwathWidthGranularityY = 256 + / dml_ceil_ex(v->BytePerPixelInDETY[k], 1) + / v->MaxSwathHeightY[k]; + v->RoundedUpMaxSwathSizeBytesY = (dml_ceil_ex( + v->SwathWidthYPerState[ijk] - 1, + v->SwathWidthGranularityY) + + v->SwathWidthGranularityY) + * v->BytePerPixelInDETY[k] * v->MaxSwathHeightY[k]; + if (src.source_format == dm_420_10) { + v->RoundedUpMaxSwathSizeBytesY = dml_ceil_ex( + v->RoundedUpMaxSwathSizeBytesY, + 256) + 256; + } + if (v->MaxSwathHeightC[k] > 0) { + v->SwathWidthGranularityC = 256 + / dml_ceil_ex(v->BytePerPixelInDETC[k], 2) + / v->MaxSwathHeightC[k]; + } + v->RoundedUpMaxSwathSizeBytesC = (dml_ceil_ex( + v->SwathWidthYPerState[ijk] / 2 - 1, + v->SwathWidthGranularityC) + + v->SwathWidthGranularityC) + * v->BytePerPixelInDETC[k] * v->MaxSwathHeightC[k]; + if (src.source_format == dm_420_10) { + v->RoundedUpMaxSwathSizeBytesC = dml_ceil_ex( + v->RoundedUpMaxSwathSizeBytesC, + 256) + 256; + } + + if (v->RoundedUpMaxSwathSizeBytesY + v->RoundedUpMaxSwathSizeBytesC + <= ip->det_buffer_size_kbytes * 1024 / 2) { + v->SwathHeightYPerState[ijk] = v->MaxSwathHeightY[k]; + v->SwathHeightCPerState[ijk] = v->MaxSwathHeightC[k]; + } else { + v->SwathHeightYPerState[ijk] = v->MinSwathHeightY[k]; + v->SwathHeightCPerState[ijk] = v->MinSwathHeightC[k]; + } + + if (v->BytePerPixelInDETC[k] == 0) { + v->LinesInDETLuma = ip->det_buffer_size_kbytes * 1024 + / v->BytePerPixelInDETY[k] + / v->SwathWidthYPerState[ijk]; + + v->LinesInDETChroma = 0; + } else if (v->SwathHeightYPerState[ijk] + <= v->SwathHeightCPerState[ijk]) { + v->LinesInDETLuma = ip->det_buffer_size_kbytes * 1024 / 2 + / v->BytePerPixelInDETY[k] + / v->SwathWidthYPerState[ijk]; + v->LinesInDETChroma = ip->det_buffer_size_kbytes * 1024 / 2 + / v->BytePerPixelInDETC[k] + / (v->SwathWidthYPerState[ijk] / 2); + } else { + v->LinesInDETLuma = ip->det_buffer_size_kbytes * 1024 * 2 + / 3 / v->BytePerPixelInDETY[k] + / v->SwathWidthYPerState[ijk]; + v->LinesInDETChroma = ip->det_buffer_size_kbytes * 1024 / 3 + / v->BytePerPixelInDETY[k] + / (v->SwathWidthYPerState[ijk] / 2); + } + + v->EffectiveLBLatencyHidingSourceLinesLuma = + dml_min( + ip->max_line_buffer_lines, + dml_floor_ex( + ip->line_buffer_size_bits + / scale_ratio_depth.lb_depth + / (v->SwathWidthYPerState[ijk] + / dml_max( + scale_ratio_depth.hscl_ratio, + 1)), + 1)) + - (scale_taps.vtaps - 1); + + v->EffectiveLBLatencyHidingSourceLinesChroma = + dml_min( + ip->max_line_buffer_lines, + dml_floor_ex( + ip->line_buffer_size_bits + / scale_ratio_depth.lb_depth + / (v->SwathWidthYPerState[ijk] + / 2 + / dml_max( + scale_ratio_depth.hscl_ratio + / 2, + 1)), + 1)) + - (scale_taps.vtaps_c - 1); + + v->EffectiveDETLBLinesLuma = + dml_floor_ex( + v->LinesInDETLuma + + dml_min( + v->LinesInDETLuma + * v->RequiredDISPCLK[ij] + * v->BytePerPixelInDETY[k] + * v->PSCL_FACTOR[k] + / v->ReturnBWPerState[i], + v->EffectiveLBLatencyHidingSourceLinesLuma), + v->SwathHeightYPerState[ijk]); + + v->EffectiveDETLBLinesChroma = + dml_floor_ex( + v->LinesInDETChroma + + dml_min( + v->LinesInDETChroma + * v->RequiredDISPCLK[ij] + * v->BytePerPixelInDETC[k] + * v->PSCL_FACTOR_CHROMA[k] + / v->ReturnBWPerState[i], + v->EffectiveLBLatencyHidingSourceLinesChroma), + v->SwathHeightCPerState[ijk]); + + if (v->BytePerPixelInDETC[k] == 0) { + v->UrgentLatencySupportUsPerState[ijk] = + v->EffectiveDETLBLinesLuma + * (dest.htotal + / dest.pixel_rate_mhz) + / scale_ratio_depth.vscl_ratio + - v->EffectiveDETLBLinesLuma + * v->SwathWidthYPerState[ijk] + * dml_ceil_ex( + v->BytePerPixelInDETY[k], + 1) + / (v->ReturnBWPerState[i] + / v->NoOfDPP[ijk]); + } else { + v->UrgentLatencySupportUsPerState[ijk] = + dml_min( + v->EffectiveDETLBLinesLuma + * (dest.htotal + / dest.pixel_rate_mhz) + / scale_ratio_depth.vscl_ratio + - v->EffectiveDETLBLinesLuma + * v->SwathWidthYPerState[ijk] + * dml_ceil_ex( + v->BytePerPixelInDETY[k], + 1) + / (v->ReturnBWPerState[i] + / v->NoOfDPP[ijk]), + v->EffectiveDETLBLinesChroma + * (dest.htotal + / dest.pixel_rate_mhz) + / (scale_ratio_depth.vscl_ratio + / 2) + - v->EffectiveDETLBLinesChroma + * v->SwathWidthYPerState[ijk] + / 2 + * dml_ceil_ex( + v->BytePerPixelInDETC[k], + 2) + / (v->ReturnBWPerState[i] + / v->NoOfDPP[ijk])); + } + + } + } + } + + for (i = 0; i < NumberOfStatesPlusTwo; i++) { + for (j = 0; j < 2; j++) { + ij = j * NumberOfStatesPlusTwo + i; + + v->UrgentLatencySupport[ij] = 1; + for (k = 0; k < num_planes; k++) { + ijk = k * 2 * NumberOfStatesPlusTwo + j * NumberOfStatesPlusTwo + i; + + if (v->UrgentLatencySupportUsPerState[ijk] + < soc->urgent_latency_us / 1) { + v->UrgentLatencySupport[ij] = 0; + } + } + } + } + + // Prefetch Check + + for (i = 0; i < NumberOfStatesPlusTwo; i++) { + for (j = 0; j < 2; j++) { + ij = j * NumberOfStatesPlusTwo + i; + + v->TotalNumberOfDCCActiveDPP[ij] = 0; + for (k = 0; k < num_planes; k++) { + struct _vcs_dpi_display_pipe_source_params_st src = + e2e[v->planes[k].e2e_index].pipe.src; + ijk = k * 2 * NumberOfStatesPlusTwo + j * NumberOfStatesPlusTwo + i; + + if (src.dcc == 1) { + v->TotalNumberOfDCCActiveDPP[ij] = + v->TotalNumberOfDCCActiveDPP[ij] + + v->NoOfDPP[ijk]; + } + } + } + } + + for (i = 0; i < NumberOfStatesPlusTwo; i++) { + for (j = 0; j < 2; j++) { + ij = j * NumberOfStatesPlusTwo + i; + + v->ProjectedDCFCLKDeepSleep = 8; + + for (k = 0; k < num_planes; k++) { + struct _vcs_dpi_display_pipe_dest_params_st dest = + e2e[v->planes[k].e2e_index].pipe.dest; + struct _vcs_dpi_scaler_ratio_depth_st scale_ratio_depth = + e2e[v->planes[k].e2e_index].pipe.scale_ratio_depth; + ijk = k * 2 * NumberOfStatesPlusTwo + j * NumberOfStatesPlusTwo + i; + + v->ProjectedDCFCLKDeepSleep = dml_max( + v->ProjectedDCFCLKDeepSleep, + dest.pixel_rate_mhz / 16); + if (v->BytePerPixelInDETC[k] == 0) { + if (scale_ratio_depth.vscl_ratio <= 1) { + v->ProjectedDCFCLKDeepSleep = + dml_max( + v->ProjectedDCFCLKDeepSleep, + 1.1 + * dml_ceil_ex( + v->BytePerPixelInDETY[k], + 1) + / 64 + * scale_ratio_depth.hscl_ratio + * dest.pixel_rate_mhz + / v->NoOfDPP[ijk]); + } else { + v->ProjectedDCFCLKDeepSleep = + dml_max( + v->ProjectedDCFCLKDeepSleep, + 1.1 + * dml_ceil_ex( + v->BytePerPixelInDETY[k], + 1) + / 64 + * v->PSCL_FACTOR[k] + * v->RequiredDISPCLK[ij] + / (1 + + j)); + } + + } else { + if (scale_ratio_depth.vscl_ratio <= 1) { + v->ProjectedDCFCLKDeepSleep = + dml_max( + v->ProjectedDCFCLKDeepSleep, + 1.1 + * dml_ceil_ex( + v->BytePerPixelInDETY[k], + 1) + / 32 + * scale_ratio_depth.hscl_ratio + * dest.pixel_rate_mhz + / v->NoOfDPP[ijk]); + } else { + v->ProjectedDCFCLKDeepSleep = + dml_max( + v->ProjectedDCFCLKDeepSleep, + 1.1 + * dml_ceil_ex( + v->BytePerPixelInDETY[k], + 1) + / 32 + * v->PSCL_FACTOR[k] + * v->RequiredDISPCLK[ij] + / (1 + + j)); + } + if ((scale_ratio_depth.vscl_ratio / 2) <= 1) { + v->ProjectedDCFCLKDeepSleep = + dml_max( + v->ProjectedDCFCLKDeepSleep, + 1.1 + * dml_ceil_ex( + v->BytePerPixelInDETC[k], + 2) + / 32 + * scale_ratio_depth.hscl_ratio + / 2 + * dest.pixel_rate_mhz + / v->NoOfDPP[ijk]); + } else { + v->ProjectedDCFCLKDeepSleep = + dml_max( + v->ProjectedDCFCLKDeepSleep, + 1.1 + * dml_ceil_ex( + v->BytePerPixelInDETC[k], + 2) + / 32 + * v->PSCL_FACTOR_CHROMA[k] + * v->RequiredDISPCLK[ij] + / (1 + + j)); + } + + } + } + + for (k = 0; k < num_planes; k++) { + struct _vcs_dpi_display_pipe_source_params_st src = + e2e[v->planes[k].e2e_index].pipe.src; + struct _vcs_dpi_display_pipe_dest_params_st dest = + e2e[v->planes[k].e2e_index].pipe.dest; + struct _vcs_dpi_scaler_ratio_depth_st scale_ratio_depth = + e2e[v->planes[k].e2e_index].pipe.scale_ratio_depth; + struct _vcs_dpi_scaler_taps_st scale_taps = + e2e[v->planes[k].e2e_index].pipe.scale_taps; + struct _vcs_dpi_display_output_params_st dout = + e2e[v->planes[k].e2e_index].dout; + ijk = k * 2 * NumberOfStatesPlusTwo + j * NumberOfStatesPlusTwo + i; + + if (src.dcc == 1) { + v->MetaReqHeightY = 8 * v->Read256BlockHeightY[k]; + v->MetaReqWidthY = 64 * 256 + / dml_ceil_ex(v->BytePerPixelInDETY[k], 1) + / v->MetaReqHeightY; + v->MetaSurfaceWidthY = dml_ceil_ex( + src.viewport_width / v->NoOfDPP[ijk] - 1, + v->MetaReqWidthY) + v->MetaReqWidthY; + v->MetaSurfaceHeightY = dml_ceil_ex( + src.viewport_height - 1, + v->MetaReqHeightY) + v->MetaReqHeightY; + if (ip->pte_enable == 1) { + v->MetaPteBytesPerFrameY = + (dml_ceil_ex( + (v->MetaSurfaceWidthY + * v->MetaSurfaceHeightY + * dml_ceil_ex( + v->BytePerPixelInDETY[k], + 1) + / 256.0 + - 4096) + / 8 + / 4096, + 1) + 1) * 64; + } else { + v->MetaPteBytesPerFrameY = 0; + } + if (src.source_scan == dm_horz) { + v->MetaRowBytesY = + v->MetaSurfaceWidthY + * v->MetaReqHeightY + * dml_ceil_ex( + v->BytePerPixelInDETY[k], + 1) + / 256; + } else { + v->MetaRowBytesY = + v->MetaSurfaceHeightY + * v->MetaReqWidthY + * dml_ceil_ex( + v->BytePerPixelInDETY[k], + 1) + / 256; + } + } else { + v->MetaPteBytesPerFrameY = 0; + v->MetaRowBytesY = 0; + } + + if (ip->pte_enable == 1) { + if (src.sw_mode == dm_sw_linear) { + v->MacroTileBlockSizeBytesY = 256; + v->MacroTileBlockHeightY = 1; + } else if (src.sw_mode == dm_sw_4kb_s + || src.sw_mode == dm_sw_4kb_s_x + || src.sw_mode == dm_sw_4kb_d + || src.sw_mode == dm_sw_4kb_d_x) { + v->MacroTileBlockSizeBytesY = 4096; + v->MacroTileBlockHeightY = 4 + * v->Read256BlockHeightY[k]; + } else if (src.sw_mode == dm_sw_64kb_s + || src.sw_mode == dm_sw_64kb_s_t + || src.sw_mode == dm_sw_64kb_s_x + || src.sw_mode == dm_sw_64kb_d + || src.sw_mode == dm_sw_64kb_d_t + || src.sw_mode == dm_sw_64kb_d_x) { + v->MacroTileBlockSizeBytesY = 64 * 1024; + v->MacroTileBlockHeightY = 16 + * v->Read256BlockHeightY[k]; + } else { + v->MacroTileBlockSizeBytesY = 256 * 1024; + v->MacroTileBlockHeightY = 32 + * v->Read256BlockHeightY[k]; + } + if (v->MacroTileBlockSizeBytesY <= 65536) { + v->DataPTEReqHeightY = v->MacroTileBlockHeightY; + } else { + v->DataPTEReqHeightY = 16 + * v->Read256BlockHeightY[k]; + } + v->DataPTEReqWidthY = 4096 + / dml_ceil_ex(v->BytePerPixelInDETY[k], 1) + / v->DataPTEReqHeightY * 8; + if (src.sw_mode == dm_sw_linear) { + v->DPTEBytesPerRowY = + 64 + * (dml_ceil_ex( + (src.viewport_width + / v->NoOfDPP[ijk] + * dml_min( + 128, + dml_pow( + 2, + dml_floor_ex( + dml_log( + ip->dpte_buffer_size_in_pte_reqs + * v->DataPTEReqWidthY + / (src.viewport_width + / v->NoOfDPP[ijk]), + 2), + 1))) + - 1) + / v->DataPTEReqWidthY, + 1) + + 1); + } else if (src.source_scan == dm_horz) { + v->DPTEBytesPerRowY = + 64 + * (dml_ceil_ex( + (src.viewport_width + / v->NoOfDPP[ijk] + - 1) + / v->DataPTEReqWidthY, + 1) + + 1); + } else { + v->DPTEBytesPerRowY = + 64 + * (dml_ceil_ex( + (src.viewport_height + - 1) + / v->DataPTEReqHeightY, + 1) + + 1); + } + } else { + v->DPTEBytesPerRowY = 0; + } + + if (src.source_format != dm_444_64 && src.source_format != dm_444_32 + && src.source_format != dm_444_16) { + if (src.dcc == 1) { + v->MetaReqHeightC = 8 * v->Read256BlockHeightC[k]; + v->MetaReqWidthC = + 64 * 256 + / dml_ceil_ex( + v->BytePerPixelInDETC[k], + 2) + / v->MetaReqHeightC; + v->MetaSurfaceWidthC = dml_ceil_ex( + src.viewport_width / v->NoOfDPP[ijk] + / 2 - 1, + v->MetaReqWidthC) + + v->MetaReqWidthC; + v->MetaSurfaceHeightC = dml_ceil_ex( + src.viewport_height / 2 - 1, + v->MetaReqHeightC) + + v->MetaReqHeightC; + if (ip->pte_enable == 1) { + v->MetaPteBytesPerFrameC = + (dml_ceil_ex( + (v->MetaSurfaceWidthC + * v->MetaSurfaceHeightC + * dml_ceil_ex( + v->BytePerPixelInDETC[k], + 2) + / 256.0 + - 4096) + / 8 + / 4096, + 1) + 1) + * 64; + } else { + v->MetaPteBytesPerFrameC = 0; + } + if (src.source_scan == dm_horz) { + v->MetaRowBytesC = + v->MetaSurfaceWidthC + * v->MetaReqHeightC + * dml_ceil_ex( + v->BytePerPixelInDETC[k], + 2) + / 256; + } else { + v->MetaRowBytesC = + v->MetaSurfaceHeightC + * v->MetaReqWidthC + * dml_ceil_ex( + v->BytePerPixelInDETC[k], + 2) + / 256; + } + } else { + v->MetaPteBytesPerFrameC = 0; + v->MetaRowBytesC = 0; + } + + if (ip->pte_enable == 1) { + if (src.sw_mode == dm_sw_linear) { + v->MacroTileBlockSizeBytesC = 256; + v->MacroTileBlockHeightC = 1; + } else if (src.sw_mode == dm_sw_4kb_s + || src.sw_mode == dm_sw_4kb_s_x + || src.sw_mode == dm_sw_4kb_d + || src.sw_mode == dm_sw_4kb_d_x) { + v->MacroTileBlockSizeBytesC = 4096; + v->MacroTileBlockHeightC = 4 + * v->Read256BlockHeightC[k]; + } else if (src.sw_mode == dm_sw_64kb_s + || src.sw_mode == dm_sw_64kb_s_t + || src.sw_mode == dm_sw_64kb_s_x + || src.sw_mode == dm_sw_64kb_d + || src.sw_mode == dm_sw_64kb_d_t + || src.sw_mode == dm_sw_64kb_d_x) { + v->MacroTileBlockSizeBytesC = 64 * 1024; + v->MacroTileBlockHeightC = 16 + * v->Read256BlockHeightC[k]; + } else { + v->MacroTileBlockSizeBytesC = 256 * 1024; + v->MacroTileBlockHeightC = 32 + * v->Read256BlockHeightC[k]; + } + v->MacroTileBlockWidthC = + v->MacroTileBlockSizeBytesC + / dml_ceil_ex( + v->BytePerPixelInDETC[k], + 2) + / v->MacroTileBlockHeightC; + if (v->MacroTileBlockSizeBytesC <= 65536) { + v->DataPTEReqHeightC = + v->MacroTileBlockHeightC; + } else { + v->DataPTEReqHeightC = 16 + * v->Read256BlockHeightC[k]; + } + v->DataPTEReqWidthC = + 4096 + / dml_ceil_ex( + v->BytePerPixelInDETC[k], + 2) + / v->DataPTEReqHeightC + * 8; + if (src.sw_mode == dm_sw_linear) { + v->DPTEBytesPerRowC = + 64 + * (dml_ceil_ex( + (src.viewport_width + / v->NoOfDPP[ijk] + / 2 + * dml_min( + 128, + dml_pow( + 2, + dml_floor_ex( + dml_log( + ip->dpte_buffer_size_in_pte_reqs + * v->DataPTEReqWidthC + / (src.viewport_width + / v->NoOfDPP[ijk] + / 2), + 2), + 1))) + - 1) + / v->DataPTEReqWidthC, + 1) + + 1); + } else if (src.source_scan == dm_horz) { + v->DPTEBytesPerRowC = + 64 + * (dml_ceil_ex( + (src.viewport_width + / v->NoOfDPP[ijk] + / 2 + - 1) + / v->DataPTEReqWidthC, + 1) + + 1); + } else { + v->DPTEBytesPerRowC = + 64 + * (dml_ceil_ex( + (src.viewport_height + / 2 + - 1) + / v->DataPTEReqHeightC, + 1) + + 1); + } + } else { + v->DPTEBytesPerRowC = 0; + } + } else { + v->DPTEBytesPerRowC = 0; + v->MetaPteBytesPerFrameC = 0; + v->MetaRowBytesC = 0; + } + + v->DPTEBytesPerRow[k] = v->DPTEBytesPerRowY + v->DPTEBytesPerRowC; + v->MetaPTEBytesPerFrame[k] = v->MetaPteBytesPerFrameY + + v->MetaPteBytesPerFrameC; + v->MetaRowBytes[k] = v->MetaRowBytesY + v->MetaRowBytesC; + + v->VInitY = (scale_ratio_depth.vscl_ratio + scale_taps.vtaps + 1 + + dest.interlaced * 0.5 + * scale_ratio_depth.vscl_ratio) + / 2.0; + v->PrefillY[k] = dml_floor_ex(v->VInitY, 1); + v->MaxNumSwY[k] = dml_ceil_ex( + (v->PrefillY[k] - 1.0) + / v->SwathHeightYPerState[ijk], + 1) + 1.0; + + if (v->PrefillY[k] > 1) { + v->MaxPartialSwY = ((int) (v->PrefillY[k] - 2)) + % ((int) v->SwathHeightYPerState[ijk]); + } else { + v->MaxPartialSwY = ((int) (v->PrefillY[k] + + v->SwathHeightYPerState[ijk] - 2)) + % ((int) v->SwathHeightYPerState[ijk]); + } + v->MaxPartialSwY = dml_max(1, v->MaxPartialSwY); + + v->PrefetchLinesY[k] = v->MaxNumSwY[k] + * v->SwathHeightYPerState[ijk] + v->MaxPartialSwY; + + if (src.source_format != dm_444_64 && src.source_format != dm_444_32 + && src.source_format != dm_444_16) { + v->VInitC = + (scale_ratio_depth.vscl_ratio / 2 + + scale_taps.vtaps + 1 + + dest.interlaced * 0.5 + * scale_ratio_depth.vscl_ratio + / 2) / 2.0; + v->PrefillC[k] = dml_floor_ex(v->VInitC, 1); + v->MaxNumSwC[k] = + dml_ceil_ex( + (v->PrefillC[k] - 1.0) + / v->SwathHeightCPerState[ijk], + 1) + 1.0; + if (v->PrefillC[k] > 1) { + v->MaxPartialSwC = + ((int) (v->PrefillC[k] - 2)) + % ((int) v->SwathHeightCPerState[ijk]); + } else { + v->MaxPartialSwC = + ((int) (v->PrefillC[k] + + v->SwathHeightCPerState[ijk] + - 2)) + % ((int) v->SwathHeightCPerState[ijk]); + } + v->MaxPartialSwC = dml_max(1, v->MaxPartialSwC); + + v->PrefetchLinesC[k] = v->MaxNumSwC[k] + * v->SwathHeightCPerState[ijk] + + v->MaxPartialSwC; + } else { + v->PrefetchLinesC[k] = 0; + } + + v->dst_x_after_scaler = 90 * dest.pixel_rate_mhz + / (v->RequiredDISPCLK[ij] / (j + 1)) + + 42 * dest.pixel_rate_mhz / v->RequiredDISPCLK[ij]; + if (v->NoOfDPP[ijk] > 1) { + v->dst_x_after_scaler = v->dst_x_after_scaler + + dest.recout_width / 2.0; + } + + if (dout.output_format == dm_420) { + v->dst_y_after_scaler = 1; + } else { + v->dst_y_after_scaler = 0; + } + + v->TimeCalc = 24 / v->ProjectedDCFCLKDeepSleep; + + v->VUpdateOffset = dml_ceil_ex(dest.htotal / 4, 1); + v->TotalRepeaterDelay = ip->max_inter_dcn_tile_repeaters + * (2 / (v->RequiredDISPCLK[ij] / (j + 1)) + + 3 / v->RequiredDISPCLK[ij]); + v->VUpdateWidth = (14 / v->ProjectedDCFCLKDeepSleep + + 12 / (v->RequiredDISPCLK[ij] / (j + 1)) + + v->TotalRepeaterDelay) * dest.pixel_rate_mhz; + v->VReadyOffset = + dml_max( + 150 + / (v->RequiredDISPCLK[ij] + / (j + + 1)), + v->TotalRepeaterDelay + + 20 + / v->ProjectedDCFCLKDeepSleep + + 10 + / (v->RequiredDISPCLK[ij] + / (j + + 1))) + * dest.pixel_rate_mhz; + + v->TimeSetup = + (v->VUpdateOffset + v->VUpdateWidth + + v->VReadyOffset) + / dest.pixel_rate_mhz; + + v->ExtraLatency = + v->UrgentRoundTripAndOutOfOrderLatencyPerState[i] + + (v->TotalNumberOfActiveDPP[ij] + * ip->pixel_chunk_size_kbytes + + v->TotalNumberOfDCCActiveDPP[ij] + * ip->meta_chunk_size_kbytes) + * 1024 + / v->ReturnBWPerState[i]; + + if (ip->pte_enable == 1) { + v->ExtraLatency = v->ExtraLatency + + v->TotalNumberOfActiveDPP[ij] + * ip->pte_chunk_size_kbytes + * 1024 + / v->ReturnBWPerState[i]; + } + + if (ip->can_vstartup_lines_exceed_vsync_plus_back_porch_lines_minus_one + == 1) { + v->MaximumVStartup = dest.vtotal - dest.vactive - 1; + } else { + v->MaximumVStartup = dest.vsync_plus_back_porch - 1; + } + + v->LineTimesForPrefetch[k] = + v->MaximumVStartup + - soc->urgent_latency_us + / (dest.htotal + / dest.pixel_rate_mhz) + - (v->TimeCalc + v->TimeSetup) + / (dest.htotal + / dest.pixel_rate_mhz) + - (v->dst_y_after_scaler + + v->dst_x_after_scaler + / dest.htotal); + + v->LineTimesForPrefetch[k] = dml_floor_ex( + 4.0 * (v->LineTimesForPrefetch[k] + 0.125), + 1) / 4; + + v->PrefetchBW[k] = + (v->MetaPTEBytesPerFrame[k] + 2 * v->MetaRowBytes[k] + + 2 * v->DPTEBytesPerRow[k] + + v->PrefetchLinesY[k] + * v->SwathWidthYPerState[ijk] + * dml_ceil_ex( + v->BytePerPixelInDETY[k], + 1) + + v->PrefetchLinesC[k] + * v->SwathWidthYPerState[ijk] + / 2 + * dml_ceil_ex( + v->BytePerPixelInDETC[k], + 2)) + / (v->LineTimesForPrefetch[k] + * dest.htotal + / dest.pixel_rate_mhz); + } + + v->BWAvailableForImmediateFlip = v->ReturnBWPerState[i]; + + for (k = 0; k < num_planes; k++) { + v->BWAvailableForImmediateFlip = v->BWAvailableForImmediateFlip + - dml_max(v->ReadBandwidth[k], v->PrefetchBW[k]); + } + + v->TotalImmediateFlipBytes = 0; + + for (k = 0; k < num_planes; k++) { + struct _vcs_dpi_display_pipe_source_params_st src = + e2e[v->planes[k].e2e_index].pipe.src; + + if (src.source_format != dm_420_8 + && src.source_format != dm_420_10) { + v->TotalImmediateFlipBytes = v->TotalImmediateFlipBytes + + v->MetaPTEBytesPerFrame[k] + + v->MetaRowBytes[k] + + v->DPTEBytesPerRow[k]; + } + } + + for (k = 0; k < num_planes; k++) { + struct _vcs_dpi_display_pipe_source_params_st src = + e2e[v->planes[k].e2e_index].pipe.src; + struct _vcs_dpi_display_pipe_dest_params_st dest = + e2e[v->planes[k].e2e_index].pipe.dest; + ijk = k * 2 * NumberOfStatesPlusTwo + j * NumberOfStatesPlusTwo + i; + + if (ip->pte_enable == 1 && src.dcc == 1) { + v->TimeForMetaPTEWithImmediateFlip = + dml_max( + v->MetaPTEBytesPerFrame[k] + / v->PrefetchBW[k], + dml_max( + v->MetaPTEBytesPerFrame[k] + * v->TotalImmediateFlipBytes + / (v->BWAvailableForImmediateFlip + * (v->MetaPTEBytesPerFrame[k] + + v->MetaRowBytes[k] + + v->DPTEBytesPerRow[k])), + dml_max( + v->ExtraLatency, + dml_max( + soc->urgent_latency_us, + dest.htotal + / dest.pixel_rate_mhz + / 4)))); + + v->TimeForMetaPTEWithoutImmediateFlip = + dml_max( + v->MetaPTEBytesPerFrame[k] + / v->PrefetchBW[k], + dml_max( + v->ExtraLatency, + dest.htotal + / dest.pixel_rate_mhz + / 4)); + } else { + v->TimeForMetaPTEWithImmediateFlip = dest.htotal + / dest.pixel_rate_mhz / 4; + v->TimeForMetaPTEWithoutImmediateFlip = dest.htotal + / dest.pixel_rate_mhz / 4; + } + + if (ip->pte_enable == 1 || src.dcc == 1) { + v->TimeForMetaAndDPTERowWithImmediateFlip = + dml_max( + (v->MetaRowBytes[k] + + v->DPTEBytesPerRow[k]) + / v->PrefetchBW[k], + dml_max( + (v->MetaRowBytes[k] + + v->DPTEBytesPerRow[k]) + * v->TotalImmediateFlipBytes + / (v->BWAvailableForImmediateFlip + * (v->MetaPTEBytesPerFrame[k] + + v->MetaRowBytes[k] + + v->DPTEBytesPerRow[k])), + dml_max( + dest.htotal + / dest.pixel_rate_mhz + - v->TimeForMetaPTEWithImmediateFlip, + dml_max( + v->ExtraLatency, + 2 + * soc->urgent_latency_us)))); + + v->TimeForMetaAndDPTERowWithoutImmediateFlip = + dml_max( + (v->MetaRowBytes[k] + + v->DPTEBytesPerRow[k]) + / v->PrefetchBW[k], + dml_max( + dest.htotal + / dest.pixel_rate_mhz + - v->TimeForMetaPTEWithoutImmediateFlip, + v->ExtraLatency)); + } else { + v->TimeForMetaAndDPTERowWithImmediateFlip = + dml_max( + dest.htotal + / dest.pixel_rate_mhz + - v->TimeForMetaPTEWithImmediateFlip, + v->ExtraLatency + - v->TimeForMetaPTEWithImmediateFlip); + v->TimeForMetaAndDPTERowWithoutImmediateFlip = + dml_max( + dest.htotal + / dest.pixel_rate_mhz + - v->TimeForMetaPTEWithoutImmediateFlip, + v->ExtraLatency + - v->TimeForMetaPTEWithoutImmediateFlip); + } + + v->LinesForMetaPTEWithImmediateFlip[k] = + dml_floor_ex( + 4.0 + * (v->TimeForMetaPTEWithImmediateFlip + / (dest.htotal + / dest.pixel_rate_mhz) + + 0.125), + 1) / 4.0; + + v->LinesForMetaPTEWithoutImmediateFlip[k] = + dml_floor_ex( + 4.0 + * (v->TimeForMetaPTEWithoutImmediateFlip + / (dest.htotal + / dest.pixel_rate_mhz) + + 0.125), + 1) / 4.0; + + v->LinesForMetaAndDPTERowWithImmediateFlip[k] = + dml_floor_ex( + 4.0 + * (v->TimeForMetaAndDPTERowWithImmediateFlip + / (dest.htotal + / dest.pixel_rate_mhz) + + 0.125), + 1) / 4.0; + + v->LinesForMetaAndDPTERowWithoutImmediateFlip[k] = + dml_floor_ex( + 4.0 + * (v->TimeForMetaAndDPTERowWithoutImmediateFlip + / (dest.htotal + / dest.pixel_rate_mhz) + + 0.125), + 1) / 4.0; + + v->LineTimesToRequestPrefetchPixelDataWithImmediateFlip = + v->LineTimesForPrefetch[k] + - v->LinesForMetaPTEWithImmediateFlip[k] + - v->LinesForMetaAndDPTERowWithImmediateFlip[k]; + + v->LineTimesToRequestPrefetchPixelDataWithoutImmediateFlip = + v->LineTimesForPrefetch[k] + - v->LinesForMetaPTEWithoutImmediateFlip[k] + - v->LinesForMetaAndDPTERowWithoutImmediateFlip[k]; + + if (v->LineTimesToRequestPrefetchPixelDataWithImmediateFlip > 0) { + v->VRatioPreYWithImmediateFlip[ijk] = + v->PrefetchLinesY[k] + / v->LineTimesToRequestPrefetchPixelDataWithImmediateFlip; + if (v->SwathHeightYPerState[ijk] > 4) { + if (v->LineTimesToRequestPrefetchPixelDataWithImmediateFlip + - (v->PrefillY[k] - 3.0) / 2.0 + > 0) { + v->VRatioPreYWithImmediateFlip[ijk] = + dml_max( + v->VRatioPreYWithImmediateFlip[ijk], + (v->MaxNumSwY[k] + * v->SwathHeightYPerState[ijk]) + / (v->LineTimesToRequestPrefetchPixelDataWithImmediateFlip + - (v->PrefillY[k] + - 3.0) + / 2.0)); + } else { + v->VRatioPreYWithImmediateFlip[ijk] = + 999999; + } + } + v->VRatioPreCWithImmediateFlip[ijk] = + v->PrefetchLinesC[k] + / v->LineTimesToRequestPrefetchPixelDataWithImmediateFlip; + if (v->SwathHeightCPerState[ijk] > 4) { + if (v->LineTimesToRequestPrefetchPixelDataWithImmediateFlip + - (v->PrefillC[k] - 3.0) / 2.0 + > 0) { + v->VRatioPreCWithImmediateFlip[ijk] = + dml_max( + v->VRatioPreCWithImmediateFlip[ijk], + (v->MaxNumSwC[k] + * v->SwathHeightCPerState[ijk]) + / (v->LineTimesToRequestPrefetchPixelDataWithImmediateFlip + - (v->PrefillC[k] + - 3.0) + / 2.0)); + } else { + v->VRatioPreCWithImmediateFlip[ijk] = + 999999; + } + } + + v->RequiredPrefetchPixelDataBWWithImmediateFlip[ijk] = + v->NoOfDPP[ijk] + * (v->PrefetchLinesY[k] + / v->LineTimesToRequestPrefetchPixelDataWithImmediateFlip + * dml_ceil_ex( + v->BytePerPixelInDETY[k], + 1) + + v->PrefetchLinesC[k] + / v->LineTimesToRequestPrefetchPixelDataWithImmediateFlip + * dml_ceil_ex( + v->BytePerPixelInDETC[k], + 2) + / 2) + * v->SwathWidthYPerState[ijk] + / (dest.htotal + / dest.pixel_rate_mhz); + } else { + v->VRatioPreYWithImmediateFlip[ijk] = 999999; + v->VRatioPreCWithImmediateFlip[ijk] = 999999; + v->RequiredPrefetchPixelDataBWWithImmediateFlip[ijk] = + 999999; + } + + if (v->LineTimesToRequestPrefetchPixelDataWithoutImmediateFlip + > 0) { + v->VRatioPreYWithoutImmediateFlip[ijk] = + v->PrefetchLinesY[k] + / v->LineTimesToRequestPrefetchPixelDataWithoutImmediateFlip; + if (v->SwathHeightYPerState[ijk] > 4) { + if (v->LineTimesToRequestPrefetchPixelDataWithoutImmediateFlip + - (v->PrefillY[k] - 3.0) / 2.0 + > 0) { + v->VRatioPreYWithoutImmediateFlip[ijk] = + dml_max( + v->VRatioPreYWithoutImmediateFlip[ijk], + (v->MaxNumSwY[k] + * v->SwathHeightYPerState[ijk]) + / (v->LineTimesToRequestPrefetchPixelDataWithoutImmediateFlip + - (v->PrefillY[k] + - 3.0) + / 2.0)); + } else { + v->VRatioPreYWithoutImmediateFlip[ijk] = + 999999; + } + } + v->VRatioPreCWithoutImmediateFlip[ijk] = + v->PrefetchLinesC[k] + / v->LineTimesToRequestPrefetchPixelDataWithoutImmediateFlip; + if (v->SwathHeightCPerState[ijk] > 4) { + if (v->LineTimesToRequestPrefetchPixelDataWithoutImmediateFlip + - (v->PrefillC[k] - 3.0) / 2.0 + > 0) { + v->VRatioPreCWithoutImmediateFlip[ijk] = + dml_max( + v->VRatioPreCWithoutImmediateFlip[ijk], + (v->MaxNumSwC[k] + * v->SwathHeightCPerState[ijk]) + / (v->LineTimesToRequestPrefetchPixelDataWithoutImmediateFlip + - (v->PrefillC[k] + - 3.0) + / 2.0)); + } else { + v->VRatioPreCWithoutImmediateFlip[ijk] = + 999999; + } + } + + v->RequiredPrefetchPixelDataBWWithoutImmediateFlip[ijk] = + v->NoOfDPP[ijk] + * (v->PrefetchLinesY[k] + / v->LineTimesToRequestPrefetchPixelDataWithoutImmediateFlip + * dml_ceil_ex( + v->BytePerPixelInDETY[k], + 1) + + v->PrefetchLinesC[k] + / v->LineTimesToRequestPrefetchPixelDataWithoutImmediateFlip + * dml_ceil_ex( + v->BytePerPixelInDETC[k], + 2) + / 2) + * v->SwathWidthYPerState[ijk] + / (dest.htotal + / dest.pixel_rate_mhz); + } else { + v->VRatioPreYWithoutImmediateFlip[ijk] = 999999; + v->VRatioPreCWithoutImmediateFlip[ijk] = 999999; + v->RequiredPrefetchPixelDataBWWithoutImmediateFlip[ijk] = + 999999; + } + } + + v->MaximumReadBandwidthWithPrefetchWithImmediateFlip = 0; + + for (k = 0; k < num_planes; k++) { + struct _vcs_dpi_display_pipe_source_params_st src = + e2e[v->planes[k].e2e_index].pipe.src; + struct _vcs_dpi_display_pipe_dest_params_st dest = + e2e[v->planes[k].e2e_index].pipe.dest; + ijk = k * 2 * NumberOfStatesPlusTwo + j * NumberOfStatesPlusTwo + i; + + if (src.source_format != dm_420_8 + && src.source_format != dm_420_10) { + v->MaximumReadBandwidthWithPrefetchWithImmediateFlip = + v->MaximumReadBandwidthWithPrefetchWithImmediateFlip + + dml_max( + v->ReadBandwidth[k], + v->RequiredPrefetchPixelDataBWWithImmediateFlip[ijk]) + + dml_max( + v->MetaPTEBytesPerFrame[k] + / (v->LinesForMetaPTEWithImmediateFlip[k] + * dest.htotal + / dest.pixel_rate_mhz), + (v->MetaRowBytes[k] + + v->DPTEBytesPerRow[k]) + / (v->LinesForMetaAndDPTERowWithImmediateFlip[k] + * dest.htotal + / dest.pixel_rate_mhz)); + } else { + v->MaximumReadBandwidthWithPrefetchWithImmediateFlip = + v->MaximumReadBandwidthWithPrefetchWithImmediateFlip + + dml_max( + v->ReadBandwidth[k], + v->RequiredPrefetchPixelDataBWWithoutImmediateFlip[ijk]); + } + } + + v->MaximumReadBandwidthWithPrefetchWithoutImmediateFlip = 0; + + for (k = 0; k < num_planes; k++) { + ijk = k * 2 * NumberOfStatesPlusTwo + j * NumberOfStatesPlusTwo + i; + + v->MaximumReadBandwidthWithPrefetchWithoutImmediateFlip = + v->MaximumReadBandwidthWithPrefetchWithoutImmediateFlip + + dml_max( + v->ReadBandwidth[k], + v->RequiredPrefetchPixelDataBWWithoutImmediateFlip[ijk]); + } + + v->PrefetchSupportedWithImmediateFlip[ij] = 1; + if (v->MaximumReadBandwidthWithPrefetchWithImmediateFlip + > v->ReturnBWPerState[i]) { + v->PrefetchSupportedWithImmediateFlip[ij] = 0; + } + for (k = 0; k < num_planes; k++) { + if (v->LineTimesForPrefetch[k] < 2 + || v->LinesForMetaPTEWithImmediateFlip[k] >= 8 + || v->LinesForMetaAndDPTERowWithImmediateFlip[k] + >= 16) { + v->PrefetchSupportedWithImmediateFlip[ij] = 0; + } + } + + v->PrefetchSupportedWithoutImmediateFlip[ij] = 1; + if (v->MaximumReadBandwidthWithPrefetchWithoutImmediateFlip + > v->ReturnBWPerState[i]) { + v->PrefetchSupportedWithoutImmediateFlip[ij] = 0; + } + for (k = 0; k < num_planes; k++) { + if (v->LineTimesForPrefetch[k] < 2 + || v->LinesForMetaPTEWithoutImmediateFlip[k] >= 8 + || v->LinesForMetaAndDPTERowWithoutImmediateFlip[k] + >= 16) { + v->PrefetchSupportedWithoutImmediateFlip[ij] = 0; + } + } + } + } + + for (i = 0; i < NumberOfStatesPlusTwo; i++) { + for (j = 0; j < 2; j++) { + ij = j * NumberOfStatesPlusTwo + i; + + v->VRatioInPrefetchSupportedWithImmediateFlip[ij] = 1; + for (k = 0; k < num_planes; k++) { + struct _vcs_dpi_display_pipe_source_params_st src = + e2e[v->planes[k].e2e_index].pipe.src; + ijk = k * 2 * NumberOfStatesPlusTwo + j * NumberOfStatesPlusTwo + i; + + if (((src.source_format != dm_420_8 + && src.source_format != dm_420_10) + && (v->VRatioPreYWithImmediateFlip[ijk] > 4 + || v->VRatioPreCWithImmediateFlip[ijk] + > 4)) + || ((src.source_format == dm_420_8 + || src.source_format == dm_420_10) + && (v->VRatioPreYWithoutImmediateFlip[ijk] + > 4 + || v->VRatioPreCWithoutImmediateFlip[ijk] + > 4))) { + v->VRatioInPrefetchSupportedWithImmediateFlip[ij] = 0; + } + } + v->VRatioInPrefetchSupportedWithoutImmediateFlip[ij] = 1; + for (k = 0; k < num_planes; k++) { + ijk = k * 2 * NumberOfStatesPlusTwo + j * NumberOfStatesPlusTwo + i; + + if (v->VRatioPreYWithoutImmediateFlip[ijk] > 4 + || v->VRatioPreCWithoutImmediateFlip[ijk] > 4) { + v->VRatioInPrefetchSupportedWithoutImmediateFlip[ij] = 0; + } + } + } + } + + // Mode Support, Voltage State and SOC Configuration + + for (i = (NumberOfStatesPlusTwo - 1); i >= 0; i--) // use int type here + { + for (j = 0; j < 2; j++) { + ij = j * NumberOfStatesPlusTwo + i; + + if (v->ScaleRatioSupport == 1 && v->SourceFormatPixelAndScanSupport == 1 + && v->ViewportSizeSupport == 1 + && v->BandwidthSupport[i] == 1 && v->DIOSupport[i] == 1 + && v->UrgentLatencySupport[ij] == 1 && v->ROBSupport[i] == 1 + && v->DISPCLK_DPPCLK_Support[ij] == 1 + && v->TotalAvailablePipesSupport[ij] == 1 + && v->TotalAvailableWritebackSupport == 1 + && v->WritebackLatencySupport == 1) { + if (v->PrefetchSupportedWithImmediateFlip[ij] == 1 + && v->VRatioInPrefetchSupportedWithImmediateFlip[ij] + == 1) { + v->ModeSupportWithImmediateFlip[ij] = 1; + } else { + v->ModeSupportWithImmediateFlip[ij] = 0; + } + if (v->PrefetchSupportedWithoutImmediateFlip[ij] == 1 + && v->VRatioInPrefetchSupportedWithoutImmediateFlip[ij] + == 1) { + v->ModeSupportWithoutImmediateFlip[ij] = 1; + } else { + v->ModeSupportWithoutImmediateFlip[ij] = 0; + } + } else { + v->ModeSupportWithImmediateFlip[ij] = 0; + v->ModeSupportWithoutImmediateFlip[ij] = 0; + } + } + } + + for (i = (NumberOfStatesPlusTwo - 1); i >= 0; i--) // use int type here + { + if ((i == (NumberOfStatesPlusTwo - 1) + || v->ModeSupportWithImmediateFlip[1 * NumberOfStatesPlusTwo + i] + == 1 + || v->ModeSupportWithImmediateFlip[0 * NumberOfStatesPlusTwo + i] + == 1) && i >= v->VoltageOverrideLevel) { + v->VoltageLevelWithImmediateFlip = i; + } + } + + for (i = (NumberOfStatesPlusTwo - 1); i >= 0; i--) // use int type here + { + if ((i == (NumberOfStatesPlusTwo - 1) + || v->ModeSupportWithoutImmediateFlip[1 * NumberOfStatesPlusTwo + i] + == 1 + || v->ModeSupportWithoutImmediateFlip[0 * NumberOfStatesPlusTwo + i] + == 1) && i >= v->VoltageOverrideLevel) { + v->VoltageLevelWithoutImmediateFlip = i; + } + } + + if (v->VoltageLevelWithImmediateFlip == (NumberOfStatesPlusTwo - 1)) { + v->ImmediateFlipSupported = 0; + v->VoltageLevel = v->VoltageLevelWithoutImmediateFlip; + } else { + v->ImmediateFlipSupported = 1; + v->VoltageLevel = v->VoltageLevelWithImmediateFlip; + } + + v->DCFCLK = v->DCFCLKPerState[(int) v->VoltageLevel]; + v->FabricAndDRAMBandwidth = v->FabricAndDRAMBandwidthPerState[(int) v->VoltageLevel]; + + for (j = 0; j < 2; j++) { + v->RequiredDISPCLKPerRatio[j] = v->RequiredDISPCLK[j * NumberOfStatesPlusTwo + + (int) v->VoltageLevel]; + for (k = 0; k < num_planes; k++) { + v->DPPPerPlanePerRatio[k * 2 + j] = v->NoOfDPP[k * 2 * NumberOfStatesPlusTwo + + j * NumberOfStatesPlusTwo + (int) v->VoltageLevel]; + } + v->DISPCLK_DPPCLK_SupportPerRatio[j] = v->DISPCLK_DPPCLK_Support[j + * NumberOfStatesPlusTwo + (int) v->VoltageLevel]; + } + + ASSERT(v->ImmediateFlipSupported || v->MacroTileBlockWidthC || v->DCFCLK || v->FabricAndDRAMBandwidth); + + return (v->VoltageLevel); +} + diff --git a/drivers/gpu/drm/amd/display/dc/dml/display_mode_support.h b/drivers/gpu/drm/amd/display/dc/dml/display_mode_support.h new file mode 100644 index 000000000000..ead4942f998c --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/dml/display_mode_support.h @@ -0,0 +1,199 @@ +/* + * Copyright 2017 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 __DISPLAY_MODE_SUPPORT_H__ +#define __DISPLAY_MODE_SUPPORT_H__ + +#include "dml_common_defs.h" + +struct display_mode_lib; + +#define NumberOfStates 4 +#define NumberOfStatesPlusTwo (NumberOfStates+2) + +struct dml_ms_internal_vars { + double ScaleRatioSupport; + double SourceFormatPixelAndScanSupport; + double TotalReadBandwidthConsumedGBytePerSecond; + double TotalWriteBandwidthConsumedGBytePerSecond; + double TotalBandwidthConsumedGBytePerSecond; + double DCCEnabledInAnyPlane; + double ReturnBWToDCNPerState; + double CriticalPoint; + double WritebackLatencySupport; + double RequiredOutputBW; + double TotalNumberOfActiveWriteback; + double TotalAvailableWritebackSupport; + double MaximumSwathWidth; + double NumberOfDPPRequiredForDETSize; + double NumberOfDPPRequiredForLBSize; + double MinDispclkUsingSingleDPP; + double MinDispclkUsingDualDPP; + double ViewportSizeSupport; + double SwathWidthGranularityY; + double RoundedUpMaxSwathSizeBytesY; + double SwathWidthGranularityC; + double RoundedUpMaxSwathSizeBytesC; + double LinesInDETLuma; + double LinesInDETChroma; + double EffectiveLBLatencyHidingSourceLinesLuma; + double EffectiveLBLatencyHidingSourceLinesChroma; + double EffectiveDETLBLinesLuma; + double EffectiveDETLBLinesChroma; + double ProjectedDCFCLKDeepSleep; + double MetaReqHeightY; + double MetaReqWidthY; + double MetaSurfaceWidthY; + double MetaSurfaceHeightY; + double MetaPteBytesPerFrameY; + double MetaRowBytesY; + double MacroTileBlockSizeBytesY; + double MacroTileBlockHeightY; + double DataPTEReqHeightY; + double DataPTEReqWidthY; + double DPTEBytesPerRowY; + double MetaReqHeightC; + double MetaReqWidthC; + double MetaSurfaceWidthC; + double MetaSurfaceHeightC; + double MetaPteBytesPerFrameC; + double MetaRowBytesC; + double MacroTileBlockSizeBytesC; + double MacroTileBlockHeightC; + double MacroTileBlockWidthC; + double DataPTEReqHeightC; + double DataPTEReqWidthC; + double DPTEBytesPerRowC; + double VInitY; + double MaxPartialSwY; + double VInitC; + double MaxPartialSwC; + double dst_x_after_scaler; + double dst_y_after_scaler; + double TimeCalc; + double VUpdateOffset; + double TotalRepeaterDelay; + double VUpdateWidth; + double VReadyOffset; + double TimeSetup; + double ExtraLatency; + double MaximumVStartup; + double BWAvailableForImmediateFlip; + double TotalImmediateFlipBytes; + double TimeForMetaPTEWithImmediateFlip; + double TimeForMetaPTEWithoutImmediateFlip; + double TimeForMetaAndDPTERowWithImmediateFlip; + double TimeForMetaAndDPTERowWithoutImmediateFlip; + double LineTimesToRequestPrefetchPixelDataWithImmediateFlip; + double LineTimesToRequestPrefetchPixelDataWithoutImmediateFlip; + double MaximumReadBandwidthWithPrefetchWithImmediateFlip; + double MaximumReadBandwidthWithPrefetchWithoutImmediateFlip; + double VoltageOverrideLevel; + double VoltageLevelWithImmediateFlip; + double VoltageLevelWithoutImmediateFlip; + double ImmediateFlipSupported; + double VoltageLevel; + double DCFCLK; + double FabricAndDRAMBandwidth; + double SwathWidthYSingleDPP[DC__NUM_PIPES__MAX]; + double BytePerPixelInDETY[DC__NUM_PIPES__MAX]; + double BytePerPixelInDETC[DC__NUM_PIPES__MAX]; + double ReadBandwidth[DC__NUM_PIPES__MAX]; + double WriteBandwidth[DC__NUM_PIPES__MAX]; + double DCFCLKPerState[NumberOfStatesPlusTwo]; + double FabricAndDRAMBandwidthPerState[NumberOfStatesPlusTwo]; + double ReturnBWPerState[NumberOfStatesPlusTwo]; + double BandwidthSupport[NumberOfStatesPlusTwo]; + double UrgentRoundTripAndOutOfOrderLatencyPerState[NumberOfStatesPlusTwo]; + double ROBSupport[NumberOfStatesPlusTwo]; + double RequiredPHYCLK[DC__NUM_PIPES__MAX]; + double DIOSupport[NumberOfStatesPlusTwo]; + double PHYCLKPerState[NumberOfStatesPlusTwo]; + double PSCL_FACTOR[DC__NUM_PIPES__MAX]; + double PSCL_FACTOR_CHROMA[DC__NUM_PIPES__MAX]; + double MinDPPCLKUsingSingleDPP[DC__NUM_PIPES__MAX]; + double Read256BlockHeightY[DC__NUM_PIPES__MAX]; + double Read256BlockWidthY[DC__NUM_PIPES__MAX]; + double Read256BlockHeightC[DC__NUM_PIPES__MAX]; + double Read256BlockWidthC[DC__NUM_PIPES__MAX]; + double MaxSwathHeightY[DC__NUM_PIPES__MAX]; + double MaxSwathHeightC[DC__NUM_PIPES__MAX]; + double MinSwathHeightY[DC__NUM_PIPES__MAX]; + double MinSwathHeightC[DC__NUM_PIPES__MAX]; + double NumberOfDPPRequiredForDETAndLBSize[DC__NUM_PIPES__MAX]; + double TotalNumberOfActiveDPP[NumberOfStatesPlusTwo * 2]; + double RequiredDISPCLK[NumberOfStatesPlusTwo * 2]; + double DISPCLK_DPPCLK_Support[NumberOfStatesPlusTwo * 2]; + double MaxDispclk[NumberOfStatesPlusTwo]; + double MaxDppclk[NumberOfStatesPlusTwo]; + double NoOfDPP[NumberOfStatesPlusTwo * 2 * DC__NUM_PIPES__MAX]; + double TotalAvailablePipesSupport[NumberOfStatesPlusTwo * 2]; + double SwathWidthYPerState[NumberOfStatesPlusTwo * 2 * DC__NUM_PIPES__MAX]; + double SwathHeightYPerState[NumberOfStatesPlusTwo * 2 * DC__NUM_PIPES__MAX]; + double SwathHeightCPerState[NumberOfStatesPlusTwo * 2 * DC__NUM_PIPES__MAX]; + double DETBufferSizeYPerState[NumberOfStatesPlusTwo * 2 * DC__NUM_PIPES__MAX]; + double UrgentLatencySupportUsPerState[NumberOfStatesPlusTwo * 2 * DC__NUM_PIPES__MAX]; + double UrgentLatencySupport[NumberOfStatesPlusTwo * 2]; + double TotalNumberOfDCCActiveDPP[NumberOfStatesPlusTwo * 2]; + double DPTEBytesPerRow[DC__NUM_PIPES__MAX]; + double MetaPTEBytesPerFrame[DC__NUM_PIPES__MAX]; + double MetaRowBytes[DC__NUM_PIPES__MAX]; + double PrefillY[DC__NUM_PIPES__MAX]; + double MaxNumSwY[DC__NUM_PIPES__MAX]; + double PrefetchLinesY[DC__NUM_PIPES__MAX]; + double PrefillC[DC__NUM_PIPES__MAX]; + double MaxNumSwC[DC__NUM_PIPES__MAX]; + double PrefetchLinesC[DC__NUM_PIPES__MAX]; + double LineTimesForPrefetch[DC__NUM_PIPES__MAX]; + double PrefetchBW[DC__NUM_PIPES__MAX]; + double LinesForMetaPTEWithImmediateFlip[DC__NUM_PIPES__MAX]; + double LinesForMetaPTEWithoutImmediateFlip[DC__NUM_PIPES__MAX]; + double LinesForMetaAndDPTERowWithImmediateFlip[DC__NUM_PIPES__MAX]; + double LinesForMetaAndDPTERowWithoutImmediateFlip[DC__NUM_PIPES__MAX]; + double VRatioPreYWithImmediateFlip[NumberOfStatesPlusTwo * 2 * DC__NUM_PIPES__MAX]; + double VRatioPreCWithImmediateFlip[NumberOfStatesPlusTwo * 2 * DC__NUM_PIPES__MAX]; + double RequiredPrefetchPixelDataBWWithImmediateFlip[NumberOfStatesPlusTwo * 2 + * DC__NUM_PIPES__MAX]; + double VRatioPreYWithoutImmediateFlip[NumberOfStatesPlusTwo * 2 * DC__NUM_PIPES__MAX]; + double VRatioPreCWithoutImmediateFlip[NumberOfStatesPlusTwo * 2 * DC__NUM_PIPES__MAX]; + double RequiredPrefetchPixelDataBWWithoutImmediateFlip[NumberOfStatesPlusTwo * 2 + * DC__NUM_PIPES__MAX]; + double PrefetchSupportedWithImmediateFlip[NumberOfStatesPlusTwo * 2]; + double PrefetchSupportedWithoutImmediateFlip[NumberOfStatesPlusTwo * 2]; + double VRatioInPrefetchSupportedWithImmediateFlip[NumberOfStatesPlusTwo * 2]; + double VRatioInPrefetchSupportedWithoutImmediateFlip[NumberOfStatesPlusTwo * 2]; + double ModeSupportWithImmediateFlip[NumberOfStatesPlusTwo * 2]; + double ModeSupportWithoutImmediateFlip[NumberOfStatesPlusTwo * 2]; + double RequiredDISPCLKPerRatio[2]; + double DPPPerPlanePerRatio[2 * DC__NUM_PIPES__MAX]; + double DISPCLK_DPPCLK_SupportPerRatio[2]; + struct _vcs_dpi_wm_calc_pipe_params_st planes[DC__NUM_PIPES__MAX]; +}; + +int dml_ms_check( + struct display_mode_lib *mode_lib, + struct _vcs_dpi_display_e2e_pipe_params_st *e2e, + int num_pipes); + +#endif diff --git a/drivers/gpu/drm/amd/display/dc/dml/display_pipe_clocks.c b/drivers/gpu/drm/amd/display/dc/dml/display_pipe_clocks.c new file mode 100644 index 000000000000..2e4dc57cafa0 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/dml/display_pipe_clocks.c @@ -0,0 +1,367 @@ +/* + * Copyright 2017 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 "display_pipe_clocks.h" +#include "display_mode_lib.h" +#include "soc_bounding_box.h" + +static enum voltage_state power_state( + struct display_mode_lib *mode_lib, + double dispclk, + double dppclk) +{ + enum voltage_state state1; + enum voltage_state state2; + + if (dispclk <= mode_lib->soc.vmin.dispclk_mhz) + state1 = dm_vmin; + else if (dispclk <= mode_lib->soc.vnom.dispclk_mhz) + state1 = dm_vnom; + else if (dispclk <= mode_lib->soc.vmax.dispclk_mhz) + state1 = dm_vmax; + else + state1 = dm_vmax_exceeded; + + if (dppclk <= mode_lib->soc.vmin.dppclk_mhz) + state2 = dm_vmin; + else if (dppclk <= mode_lib->soc.vnom.dppclk_mhz) + state2 = dm_vnom; + else if (dppclk <= mode_lib->soc.vmax.dppclk_mhz) + state2 = dm_vmax; + else + state2 = dm_vmax_exceeded; + + if (state1 > state2) + return state1; + else + return state2; +} + +static unsigned int dpp_in_grp( + struct _vcs_dpi_display_e2e_pipe_params_st *e2e, + unsigned int num_pipes, + unsigned int hsplit_grp) +{ + unsigned int num_dpp = 0; + unsigned int i; + + for (i = 0; i < num_pipes; i++) { + if (e2e[i].pipe.src.is_hsplit) { + if (e2e[i].pipe.src.hsplit_grp == hsplit_grp) { + num_dpp++; + } + } + } + + if (0 == num_dpp) + num_dpp = 1; + + return num_dpp; +} + +static void calculate_pipe_clk_requirement( + struct display_mode_lib *mode_lib, + struct _vcs_dpi_display_e2e_pipe_params_st *e2e, + unsigned int num_dpp_in_grp, + double *dppclk, + double *dispclk, + bool *dppdiv) +{ + double pscl_throughput = 0.0; + double max_hratio = e2e->pipe.scale_ratio_depth.hscl_ratio; + double max_vratio = e2e->pipe.scale_ratio_depth.vscl_ratio; + double max_htaps = e2e->pipe.scale_taps.htaps; + double max_vtaps = e2e->pipe.scale_taps.vtaps; + double dpp_clock_divider = (double) num_dpp_in_grp; + double dispclk_dppclk_ratio; + double dispclk_ramp_margin_percent; + + if (max_hratio > 1.0) { + double pscl_to_lb = ((double) mode_lib->ip.max_pscl_lb_bw_pix_per_clk * max_hratio) + / dml_ceil(max_htaps / 6.0); + pscl_throughput = dml_min( + pscl_to_lb, + (double) mode_lib->ip.max_dchub_pscl_bw_pix_per_clk); + } else { + pscl_throughput = dml_min( + (double) mode_lib->ip.max_pscl_lb_bw_pix_per_clk, + (double) mode_lib->ip.max_dchub_pscl_bw_pix_per_clk); + } + + DTRACE("pscl_throughput: %f pix per clk", pscl_throughput); + DTRACE("vtaps: %f hratio: %f vratio: %f", max_vtaps, max_hratio, max_vratio); + *dppclk = dml_max( + max_vtaps / 6.0 * dml_min(1.0, max_hratio), + max_hratio * max_vratio / pscl_throughput); + DTRACE("pixel rate multiplier: %f", *dppclk); + *dppclk = dml_max(*dppclk, 1.0); + DTRACE("pixel rate multiplier clamped: %f", *dppclk); + *dppclk = *dppclk * e2e->pipe.dest.pixel_rate_mhz; + + *dppclk = *dppclk / dpp_clock_divider; + DTRACE("dppclk after split: %f", *dppclk); + + if (dpp_clock_divider > 1.0 && (*dppclk < e2e->pipe.dest.pixel_rate_mhz)) { + dispclk_dppclk_ratio = 2.0; + *dppdiv = true; + } else { + dispclk_dppclk_ratio = 1.0; + *dppdiv = false; + } + + dispclk_ramp_margin_percent = mode_lib->ip.dispclk_ramp_margin_percent; + + /* Comment this out because of Gabes possible bug in spreadsheet, + * just to make other cases evident during debug + * + *if(e2e->clks_cfg.voltage == dm_vmax) + * dispclk_ramp_margin_percent = 0.0; + */ + + /* account for ramping margin and downspread */ + *dispclk = dml_max(*dppclk * dispclk_dppclk_ratio, e2e->pipe.dest.pixel_rate_mhz) + * (1.0 + (double) mode_lib->soc.downspread_percent / 100.0) + * (1.0 + (double) dispclk_ramp_margin_percent / 100.0); + + return; +} + +bool dml_clks_pipe_clock_requirement_fit_power_constraint( + struct display_mode_lib *mode_lib, + struct _vcs_dpi_display_e2e_pipe_params_st *e2e, + unsigned int num_dpp_in_grp) +{ + double dppclk = 0; + double dispclk = 0; + bool dppdiv = 0; + + calculate_pipe_clk_requirement(mode_lib, e2e, num_dpp_in_grp, &dppclk, &dispclk, &dppdiv); + + if (power_state(mode_lib, dispclk, dppclk) > e2e->clks_cfg.voltage) { + return false; + } + + return true; +} + +static void get_plane_clks( + struct display_mode_lib *mode_lib, + struct _vcs_dpi_display_e2e_pipe_params_st *e2e, + unsigned int num_pipes, + double *dppclks, + double *dispclks, + bool *dppdiv) +{ + /* it is assumed that the scale ratios passed into the e2e pipe params have already been calculated + * for any split pipe configurations, where extra pixels inthe overlap region do not contribute to + * the scale ratio. This means that we can simply calculate the dppclk for each dpp independently + * and we would expect the same result on any split pipes, which would be handled + */ + unsigned int i; + + for (i = 0; i < num_pipes; i++) { + double num_dpp_in_grp; + double dispclk_ramp_margin_percent; + double dispclk_margined; + + if (e2e[i].pipe.src.is_hsplit) + num_dpp_in_grp = (double) dpp_in_grp( + e2e, + num_pipes, + e2e[i].pipe.src.hsplit_grp); + else + num_dpp_in_grp = 1; + + calculate_pipe_clk_requirement( + mode_lib, + &e2e[i], + num_dpp_in_grp, + &dppclks[i], + &dispclks[i], + &dppdiv[i]); + + dispclk_ramp_margin_percent = mode_lib->ip.dispclk_ramp_margin_percent; + + dispclk_margined = e2e[i].pipe.dest.pixel_rate_mhz + * (1.0 + (double) mode_lib->soc.downspread_percent / 100.0) + * (1.0 + (double) dispclk_ramp_margin_percent / 100.0); + + DTRACE("p%d: requested power state: %d", i, (int) e2e[0].clks_cfg.voltage); + + if (power_state(mode_lib, dispclks[i], dppclks[i]) + > power_state(mode_lib, dispclk_margined, dispclk_margined) + && dispclk_margined > dppclks[i]) { + if (power_state(mode_lib, dispclks[i], dppclks[i]) + > e2e[0].clks_cfg.voltage) { + dispclks[i] = dispclk_margined; + dppclks[i] = dispclk_margined; + dppdiv[i] = false; + } + } + + DTRACE("p%d: dispclk: %f", i, dispclks[i]); + } +} + +static void get_dcfclk( + struct display_mode_lib *mode_lib, + struct _vcs_dpi_display_e2e_pipe_params_st *e2e, + unsigned int num_pipes, + double *dcfclk_mhz) +{ + double bytes_per_pixel_det_y[DC__NUM_PIPES__MAX]; + double bytes_per_pixel_det_c[DC__NUM_PIPES__MAX]; + double swath_width_y[DC__NUM_PIPES__MAX]; + unsigned int i; + double total_read_bandwidth_gbps = 0.0; + + for (i = 0; i < num_pipes; i++) { + if (e2e[i].pipe.src.source_scan == dm_horz) { + swath_width_y[i] = e2e[i].pipe.src.viewport_width * 1.0; + } else { + swath_width_y[i] = e2e[i].pipe.src.viewport_height * 1.0; + } + + switch (e2e[i].pipe.src.source_format) { + case dm_444_64: + bytes_per_pixel_det_y[i] = 8.0; + bytes_per_pixel_det_c[i] = 0.0; + break; + case dm_444_32: + bytes_per_pixel_det_y[i] = 4.0; + bytes_per_pixel_det_c[i] = 0.0; + break; + case dm_444_16: + bytes_per_pixel_det_y[i] = 2.0; + bytes_per_pixel_det_c[i] = 0.0; + break; + case dm_422_8: + bytes_per_pixel_det_y[i] = 2.0; + bytes_per_pixel_det_c[i] = 0.0; + break; + case dm_422_10: + bytes_per_pixel_det_y[i] = 4.0; + bytes_per_pixel_det_c[i] = 0.0; + break; + case dm_420_8: + bytes_per_pixel_det_y[i] = 1.0; + bytes_per_pixel_det_c[i] = 2.0; + break; + case dm_420_10: + bytes_per_pixel_det_y[i] = 4.0 / 3.0; + bytes_per_pixel_det_c[i] = 8.0 / 3.0; + break; + default: + BREAK_TO_DEBUGGER(); /* invalid src_format in get_dcfclk */ + } + } + + for (i = 0; i < num_pipes; i++) { + double read_bandwidth_plane_mbps = 0.0; + read_bandwidth_plane_mbps = (double) swath_width_y[i] + * ((double) bytes_per_pixel_det_y[i] + + (double) bytes_per_pixel_det_c[i] / 2.0) + / ((double) e2e[i].pipe.dest.htotal + / (double) e2e[i].pipe.dest.pixel_rate_mhz) + * e2e[i].pipe.scale_ratio_depth.vscl_ratio; + + if (e2e[i].pipe.src.dcc) { + read_bandwidth_plane_mbps += (read_bandwidth_plane_mbps / 1000.0 / 256.0); + } + + if (e2e[i].pipe.src.vm) { + read_bandwidth_plane_mbps += (read_bandwidth_plane_mbps / 1000.0 / 512.0); + } + + total_read_bandwidth_gbps = total_read_bandwidth_gbps + + read_bandwidth_plane_mbps / 1000.0; + } + + DTRACE("total bandwidth = %f gbps", total_read_bandwidth_gbps); + + (*dcfclk_mhz) = (total_read_bandwidth_gbps * 1000.0) / mode_lib->soc.return_bus_width_bytes; + + DTRACE( + "minimum theoretical dcfclk without stutter and full utilization = %f MHz", + (*dcfclk_mhz)); + +} + +struct _vcs_dpi_display_pipe_clock_st dml_clks_get_pipe_clocks( + struct display_mode_lib *mode_lib, + struct _vcs_dpi_display_e2e_pipe_params_st *e2e, + unsigned int num_pipes) +{ + struct _vcs_dpi_display_pipe_clock_st clocks; + double max_dispclk = 0.0; + double dcfclk; + double dispclks[DC__NUM_PIPES__MAX]; + double dppclks[DC__NUM_PIPES__MAX]; + bool dppdiv[DC__NUM_PIPES__MAX]; + unsigned int i; + + DTRACE("Calculating pipe clocks..."); + + /* this is the theoretical minimum, have to adjust based on valid values for soc */ + get_dcfclk(mode_lib, e2e, num_pipes, &dcfclk); + + /* if(dcfclk > soc.vnom.dcfclk_mhz) + * dcfclk = soc.vmax.dcfclk_mhz; + * else if(dcfclk > soc.vmin.dcfclk_mhz) + * dcfclk = soc.vnom.dcfclk_mhz; + * else + * dcfclk = soc.vmin.dcfclk_mhz; + */ + + dcfclk = dml_socbb_voltage_scaling( + &mode_lib->soc, + (enum voltage_state) e2e[0].clks_cfg.voltage).dcfclk_mhz; + clocks.dcfclk_mhz = dcfclk; + + get_plane_clks(mode_lib, e2e, num_pipes, dppclks, dispclks, dppdiv); + + for (i = 0; i < num_pipes; i++) { + max_dispclk = dml_max(max_dispclk, dispclks[i]); + } + + clocks.dispclk_mhz = max_dispclk; + DTRACE("dispclk: %f Mhz", clocks.dispclk_mhz); + DTRACE("dcfclk: %f Mhz", clocks.dcfclk_mhz); + + for (i = 0; i < num_pipes; i++) { + if (dppclks[i] * 2 < max_dispclk) + dppdiv[i] = 1; + + if (dppdiv[i]) + clocks.dppclk_div[i] = 1; + else + clocks.dppclk_div[i] = 0; + + clocks.dppclk_mhz[i] = max_dispclk / ((dppdiv[i]) ? 2.0 : 1.0); + DTRACE("dppclk%d: %f Mhz", i, clocks.dppclk_mhz[i]); + } + + return clocks; +} diff --git a/drivers/gpu/drm/amd/display/dc/dml/display_pipe_clocks.h b/drivers/gpu/drm/amd/display/dc/dml/display_pipe_clocks.h new file mode 100644 index 000000000000..aed5f33bb04f --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/dml/display_pipe_clocks.h @@ -0,0 +1,41 @@ +/* + * Copyright 2017 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 __DISPLAY_PIPE_CLOCKS_H__ +#define __DISPLAY_PIPE_CLOCKS_H__ + +#include "dml_common_defs.h" + +struct display_mode_lib; + +struct _vcs_dpi_display_pipe_clock_st dml_clks_get_pipe_clocks( + struct display_mode_lib *mode_lib, + struct _vcs_dpi_display_e2e_pipe_params_st *e2e, + unsigned int num_pipes); + +bool dml_clks_pipe_clock_requirement_fit_power_constraint( + struct display_mode_lib *mode_lib, + struct _vcs_dpi_display_e2e_pipe_params_st *e2e, + unsigned int num_dpp_in_grp); +#endif diff --git a/drivers/gpu/drm/amd/display/dc/dml/display_rq_dlg_calc.c b/drivers/gpu/drm/amd/display/dc/dml/display_rq_dlg_calc.c new file mode 100644 index 000000000000..9fccbbffe129 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/dml/display_rq_dlg_calc.c @@ -0,0 +1,2254 @@ +/* + * Copyright 2017 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 "display_rq_dlg_calc.h" +#include "display_mode_lib.h" + +static unsigned int get_bytes_per_element(enum source_format_class source_format, bool is_chroma) +{ + unsigned int ret_val = 0; + + if (source_format == dm_444_16) { + if (!is_chroma) + ret_val = 2; + } else if (source_format == dm_444_32) { + if (!is_chroma) + ret_val = 4; + } else if (source_format == dm_444_64) { + if (!is_chroma) + ret_val = 8; + } else if (source_format == dm_420_8) { + if (is_chroma) + ret_val = 2; + else + ret_val = 1; + } else if (source_format == dm_420_10) { + if (is_chroma) + ret_val = 4; + else + ret_val = 2; + } + return ret_val; +} + +static bool is_dual_plane(enum source_format_class source_format) +{ + bool ret_val = 0; + + if ((source_format == dm_420_8) || (source_format == dm_420_10)) + ret_val = 1; + + return ret_val; +} + +static void get_blk256_size( + unsigned int *blk256_width, + unsigned int *blk256_height, + unsigned int bytes_per_element) +{ + 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 double get_refcyc_per_delivery( + struct display_mode_lib *mode_lib, + double refclk_freq_in_mhz, + double pclk_freq_in_mhz, + int unsigned recout_width, + double vratio, + double hscale_pixel_rate, + int unsigned delivery_width, + int unsigned req_per_swath_ub) +{ + double refcyc_per_delivery = 0.0; + if (vratio <= 1.0) { + refcyc_per_delivery = (double) refclk_freq_in_mhz * (double) recout_width + / pclk_freq_in_mhz / (double) req_per_swath_ub; + } else { + refcyc_per_delivery = (double) refclk_freq_in_mhz * (double) delivery_width + / (double) hscale_pixel_rate / (double) req_per_swath_ub; + } + + DTRACE("DLG: %s: refclk_freq_in_mhz = %3.2f", __func__, refclk_freq_in_mhz); + DTRACE("DLG: %s: pclk_freq_in_mhz = %3.2f", __func__, pclk_freq_in_mhz); + DTRACE("DLG: %s: recout_width = %d", __func__, recout_width); + DTRACE("DLG: %s: vratio = %3.2f", __func__, vratio); + DTRACE("DLG: %s: req_per_swath_ub = %d", __func__, req_per_swath_ub); + DTRACE("DLG: %s: refcyc_per_delivery= %3.2f", __func__, refcyc_per_delivery); + + return refcyc_per_delivery; + +} + +static double get_vratio_pre( + struct display_mode_lib *mode_lib, + unsigned int max_num_sw, + unsigned int max_partial_sw, + unsigned int swath_height, + double vinit, + double l_sw) +{ + double prefill = dml_floor(vinit); + double vratio_pre = 1.0; + + vratio_pre = (max_num_sw * swath_height + max_partial_sw) / l_sw; + + if (swath_height > 4) { + double tmp0 = (max_num_sw * swath_height) / (l_sw - (prefill - 3.0) / 2.0); + if (tmp0 > vratio_pre) + vratio_pre = tmp0; + } + + DTRACE("DLG: %s: max_num_sw = %0d", __func__, max_num_sw); + DTRACE("DLG: %s: max_partial_sw = %0d", __func__, max_partial_sw); + DTRACE("DLG: %s: swath_height = %0d", __func__, swath_height); + DTRACE("DLG: %s: vinit = %3.2f", __func__, vinit); + DTRACE("DLG: %s: vratio_pre = %3.2f", __func__, vratio_pre); + + if (vratio_pre < 1.0) { + DTRACE("WARNING_DLG: %s: vratio_pre=%3.2f < 1.0, set to 1.0", __func__, vratio_pre); + vratio_pre = 1.0; + } + + if (vratio_pre > 4.0) { + DTRACE( + "WARNING_DLG: %s: vratio_pre=%3.2f > 4.0 (max scaling ratio). set to 4.0", + __func__, + vratio_pre); + vratio_pre = 4.0; + } + + return vratio_pre; +} + +static void get_swath_need( + struct display_mode_lib *mode_lib, + unsigned int *max_num_sw, + unsigned int *max_partial_sw, + unsigned int swath_height, + double vinit) +{ + double prefill = dml_floor(vinit); + unsigned int max_partial_sw_int; + + DTRACE("DLG: %s: swath_height = %0d", __func__, swath_height); + DTRACE("DLG: %s: vinit = %3.2f", __func__, vinit); + + ASSERT(prefill > 0.0 && prefill <= 8.0); + + *max_num_sw = (int unsigned) (dml_ceil((prefill - 1.0) / (double) swath_height) + 1.0); /* prefill has to be >= 1 */ + max_partial_sw_int = + (prefill == 1) ? + (swath_height - 1) : + ((int unsigned) (prefill - 2.0) % swath_height); + *max_partial_sw = (max_partial_sw_int < 1) ? 1 : max_partial_sw_int; /* ensure minimum of 1 is used */ + + DTRACE("DLG: %s: max_num_sw = %0d", __func__, *max_num_sw); + DTRACE("DLG: %s: max_partial_sw = %0d", __func__, *max_partial_sw); +} + +static unsigned int get_blk_size_bytes(const enum source_macro_tile_size tile_size) +{ + if (tile_size == dm_256k_tile) + return (256 * 1024); + else if (tile_size == dm_64k_tile) + return (64 * 1024); + else + return (4 * 1024); +} + +static void extract_rq_sizing_regs( + struct display_mode_lib *mode_lib, + struct _vcs_dpi_display_data_rq_regs_st *rq_regs, + const struct _vcs_dpi_display_data_rq_sizing_params_st rq_sizing) +{ + DTRACE("DLG: %s: rq_sizing param", __func__); + print__data_rq_sizing_params_st(mode_lib, rq_sizing); + + rq_regs->chunk_size = dml_log2(rq_sizing.chunk_bytes) - 10; + + if (rq_sizing.min_chunk_bytes == 0) + rq_regs->min_chunk_size = 0; + else + rq_regs->min_chunk_size = dml_log2(rq_sizing.min_chunk_bytes) - 8 + 1; + + rq_regs->meta_chunk_size = dml_log2(rq_sizing.meta_chunk_bytes) - 10; + if (rq_sizing.min_meta_chunk_bytes == 0) + rq_regs->min_meta_chunk_size = 0; + else + rq_regs->min_meta_chunk_size = dml_log2(rq_sizing.min_meta_chunk_bytes) - 6 + 1; + + rq_regs->dpte_group_size = dml_log2(rq_sizing.dpte_group_bytes) - 6; + rq_regs->mpte_group_size = dml_log2(rq_sizing.mpte_group_bytes) - 6; +} + +void extract_rq_regs( + struct display_mode_lib *mode_lib, + struct _vcs_dpi_display_rq_regs_st *rq_regs, + const struct _vcs_dpi_display_rq_params_st rq_param) +{ + unsigned int detile_buf_size_in_bytes = mode_lib->ip.det_buffer_size_kbytes * 1024; + unsigned int detile_buf_plane1_addr = 0; + + extract_rq_sizing_regs(mode_lib, &(rq_regs->rq_regs_l), rq_param.sizing.rq_l); + if (rq_param.yuv420) + extract_rq_sizing_regs(mode_lib, &(rq_regs->rq_regs_c), rq_param.sizing.rq_c); + + rq_regs->rq_regs_l.swath_height = dml_log2(rq_param.dlg.rq_l.swath_height); + rq_regs->rq_regs_c.swath_height = dml_log2(rq_param.dlg.rq_c.swath_height); + + /* FIXME: take the max between luma, chroma chunk size? + * okay for now, as we are setting chunk_bytes to 8kb anyways + */ + if (rq_param.sizing.rq_l.chunk_bytes >= 32 * 1024) { /*32kb */ + rq_regs->drq_expansion_mode = 0; + } else { + rq_regs->drq_expansion_mode = 2; + } + rq_regs->prq_expansion_mode = 1; + rq_regs->mrq_expansion_mode = 1; + rq_regs->crq_expansion_mode = 1; + + if (rq_param.yuv420) { + if ((double) rq_param.misc.rq_l.stored_swath_bytes + / (double) rq_param.misc.rq_c.stored_swath_bytes <= 1.5) { + detile_buf_plane1_addr = (detile_buf_size_in_bytes / 2.0 / 64.0); /* half to chroma */ + } else { + detile_buf_plane1_addr = dml_round_to_multiple( + (unsigned int) ((2.0 * detile_buf_size_in_bytes) / 3.0), + 256, + 0) / 64.0; /* 2/3 to chroma */ + } + } + rq_regs->plane1_base_address = detile_buf_plane1_addr; +} + +static void handle_det_buf_split( + struct display_mode_lib *mode_lib, + struct _vcs_dpi_display_rq_params_st *rq_param, + const struct _vcs_dpi_display_pipe_source_params_st pipe_src_param) +{ + unsigned int total_swath_bytes = 0; + unsigned int swath_bytes_l = 0; + unsigned int swath_bytes_c = 0; + unsigned int full_swath_bytes_packed_l = 0; + unsigned int full_swath_bytes_packed_c = 0; + bool req128_l = 0; + bool req128_c = 0; + bool surf_linear = (pipe_src_param.sw_mode == dm_sw_linear); + bool surf_vert = (pipe_src_param.source_scan == dm_vert); + unsigned int log2_swath_height_l = 0; + unsigned int log2_swath_height_c = 0; + unsigned int detile_buf_size_in_bytes = mode_lib->ip.det_buffer_size_kbytes * 1024; + + full_swath_bytes_packed_l = rq_param->misc.rq_l.full_swath_bytes; + full_swath_bytes_packed_c = rq_param->misc.rq_c.full_swath_bytes; + + if (rq_param->yuv420_10bpc) { + full_swath_bytes_packed_l = dml_round_to_multiple( + rq_param->misc.rq_l.full_swath_bytes * 2 / 3, + 256, + 1) + 256; + full_swath_bytes_packed_c = dml_round_to_multiple( + rq_param->misc.rq_c.full_swath_bytes * 2 / 3, + 256, + 1) + 256; + } + + if (rq_param->yuv420) { + total_swath_bytes = 2 * full_swath_bytes_packed_l + 2 * full_swath_bytes_packed_c; + + if (total_swath_bytes <= detile_buf_size_in_bytes) { /*full 256b request */ + req128_l = 0; + req128_c = 0; + swath_bytes_l = full_swath_bytes_packed_l; + swath_bytes_c = full_swath_bytes_packed_c; + } else { /*128b request (for luma only for yuv420 8bpc) */ + req128_l = 1; + req128_c = 0; + swath_bytes_l = full_swath_bytes_packed_l / 2; + swath_bytes_c = full_swath_bytes_packed_c; + } + + /* Bug workaround, luma and chroma req size needs to be the same. (see: DEGVIDCN10-137) + * TODO: Remove after rtl fix + */ + if (req128_l == 1) { + req128_c = 1; + DTRACE("DLG: %s: bug workaround DEGVIDCN10-137", __func__); + } + + /* Note: assumption, the config that pass in will fit into + * the detiled buffer. + */ + } else { + total_swath_bytes = 2 * full_swath_bytes_packed_l; + + if (total_swath_bytes <= detile_buf_size_in_bytes) + req128_l = 0; + else + req128_l = 1; + + swath_bytes_l = total_swath_bytes; + swath_bytes_c = 0; + } + rq_param->misc.rq_l.stored_swath_bytes = swath_bytes_l; + rq_param->misc.rq_c.stored_swath_bytes = swath_bytes_c; + + if (surf_linear) { + log2_swath_height_l = 0; + log2_swath_height_c = 0; + } else if (!surf_vert) { + log2_swath_height_l = dml_log2(rq_param->misc.rq_l.blk256_height) - req128_l; + log2_swath_height_c = dml_log2(rq_param->misc.rq_c.blk256_height) - req128_c; + } else { + log2_swath_height_l = dml_log2(rq_param->misc.rq_l.blk256_width) - req128_l; + log2_swath_height_c = dml_log2(rq_param->misc.rq_c.blk256_width) - req128_c; + } + rq_param->dlg.rq_l.swath_height = 1 << log2_swath_height_l; + rq_param->dlg.rq_c.swath_height = 1 << log2_swath_height_c; + + DTRACE("DLG: %s: req128_l = %0d", __func__, req128_l); + DTRACE("DLG: %s: req128_c = %0d", __func__, req128_c); + DTRACE("DLG: %s: full_swath_bytes_packed_l = %0d", __func__, full_swath_bytes_packed_l); + DTRACE("DLG: %s: full_swath_bytes_packed_c = %0d", __func__, full_swath_bytes_packed_c); +} + +/* Need refactor. */ +void dml_rq_dlg_get_row_heights( + struct display_mode_lib *mode_lib, + unsigned int *o_dpte_row_height, + unsigned int *o_meta_row_height, + unsigned int vp_width, + unsigned int data_pitch, + int source_format, + int tiling, + int macro_tile_size, + int source_scan, + int is_chroma) +{ + bool surf_linear = (tiling == dm_sw_linear); + bool surf_vert = (source_scan == dm_vert); + + unsigned int bytes_per_element = get_bytes_per_element( + (enum source_format_class) source_format, + is_chroma); + unsigned int log2_bytes_per_element = dml_log2(bytes_per_element); + unsigned int blk256_width = 0; + unsigned int blk256_height = 0; + + unsigned int log2_blk256_height; + unsigned int blk_bytes; + unsigned int log2_blk_bytes; + unsigned int log2_blk_height; + unsigned int log2_blk_width; + unsigned int log2_meta_req_bytes; + unsigned int log2_meta_req_height; + unsigned int log2_meta_req_width; + unsigned int log2_meta_row_height; + unsigned int log2_vmpg_bytes; + unsigned int dpte_buf_in_pte_reqs; + unsigned int log2_vmpg_height; + unsigned int log2_vmpg_width; + unsigned int log2_dpte_req_height_ptes; + unsigned int log2_dpte_req_width_ptes; + unsigned int log2_dpte_req_height; + unsigned int log2_dpte_req_width; + unsigned int log2_dpte_row_height_linear; + unsigned int log2_dpte_row_height; + unsigned int dpte_req_width; + + if (surf_linear) { + blk256_width = 256; + blk256_height = 1; + } else { + get_blk256_size(&blk256_width, &blk256_height, bytes_per_element); + } + + log2_blk256_height = dml_log2((double) blk256_height); + blk_bytes = surf_linear ? + 256 : get_blk_size_bytes((enum source_macro_tile_size) macro_tile_size); + log2_blk_bytes = dml_log2((double) blk_bytes); + log2_blk_height = 0; + log2_blk_width = 0; + + /* remember log rule + * "+" in log is multiply + * "-" in log is divide + * "/2" is like square root + * blk is vertical biased + */ + if (tiling != dm_sw_linear) + log2_blk_height = log2_blk256_height + + dml_ceil((double) (log2_blk_bytes - 8) / 2.0); + else + log2_blk_height = 0; /* blk height of 1 */ + + log2_blk_width = log2_blk_bytes - log2_bytes_per_element - log2_blk_height; + + /* ------- */ + /* meta */ + /* ------- */ + log2_meta_req_bytes = 6; /* meta request is 64b and is 8x8byte meta element */ + + /* each 64b meta request for dcn is 8x8 meta elements and + * a meta element covers one 256b block of the the data surface. + */ + log2_meta_req_height = log2_blk256_height + 3; /* meta req is 8x8 */ + log2_meta_req_width = log2_meta_req_bytes + 8 - log2_bytes_per_element + - log2_meta_req_height; + log2_meta_row_height = 0; + + /* the dimensions of a meta row are meta_row_width x meta_row_height in elements. + * calculate upper bound of the meta_row_width + */ + if (!surf_vert) + log2_meta_row_height = log2_meta_req_height; + else + log2_meta_row_height = log2_meta_req_width; + + *o_meta_row_height = 1 << log2_meta_row_height; + + /* ------ */ + /* dpte */ + /* ------ */ + log2_vmpg_bytes = dml_log2(mode_lib->soc.vmm_page_size_bytes); + dpte_buf_in_pte_reqs = mode_lib->ip.dpte_buffer_size_in_pte_reqs; + + log2_vmpg_height = 0; + log2_vmpg_width = 0; + log2_dpte_req_height_ptes = 0; + log2_dpte_req_width_ptes = 0; + log2_dpte_req_height = 0; + log2_dpte_req_width = 0; + log2_dpte_row_height_linear = 0; + log2_dpte_row_height = 0; + dpte_req_width = 0; /* 64b dpte req width in data element */ + + if (surf_linear) { + log2_vmpg_height = 0; /* one line high */ + } else { + log2_vmpg_height = (log2_vmpg_bytes - 8) / 2 + log2_blk256_height; + } + log2_vmpg_width = log2_vmpg_bytes - log2_bytes_per_element - log2_vmpg_height; + + /* only 3 possible shapes for dpte request in dimensions of ptes: 8x1, 4x2, 2x4. */ + if (log2_blk_bytes <= log2_vmpg_bytes) + log2_dpte_req_height_ptes = 0; + else if (log2_blk_height - log2_vmpg_height >= 2) + log2_dpte_req_height_ptes = 2; + else + log2_dpte_req_height_ptes = log2_blk_height - log2_vmpg_height; + log2_dpte_req_width_ptes = 3 - log2_dpte_req_height_ptes; + + ASSERT((log2_dpte_req_width_ptes == 3 && log2_dpte_req_height_ptes == 0) || /* 8x1 */ + (log2_dpte_req_width_ptes == 2 && log2_dpte_req_height_ptes == 1) || /* 4x2 */ + (log2_dpte_req_width_ptes == 1 && log2_dpte_req_height_ptes == 2)); /* 2x4 */ + + /* the dpte request dimensions in data elements is dpte_req_width x dpte_req_height + * log2_wmpg_width is how much 1 pte represent, now trying to calculate how much 64b pte req represent + */ + log2_dpte_req_height = log2_vmpg_height + log2_dpte_req_height_ptes; + log2_dpte_req_width = log2_vmpg_width + log2_dpte_req_width_ptes; + dpte_req_width = 1 << log2_dpte_req_width; + + /* calculate pitch dpte row buffer can hold + * round the result down to a power of two. + */ + if (surf_linear) { + log2_dpte_row_height_linear = dml_floor( + dml_log2(dpte_buf_in_pte_reqs * dpte_req_width / data_pitch)); + + ASSERT(log2_dpte_row_height_linear >= 3); + + if (log2_dpte_row_height_linear > 7) + log2_dpte_row_height_linear = 7; + + log2_dpte_row_height = log2_dpte_row_height_linear; + } else { + /* the upper bound of the dpte_row_width without dependency on viewport position follows. */ + if (!surf_vert) { + log2_dpte_row_height = log2_dpte_req_height; + } else { + log2_dpte_row_height = + (log2_blk_width < log2_dpte_req_width) ? + log2_blk_width : log2_dpte_req_width; + } + } + + /* From programming guide: + * There is a special case of saving only half of ptes returned due to buffer space limits. + * this case applies to 4 and 8bpe in horizontal access of a vp_width greater than 2560+16 + * when the pte request is 2x4 ptes (which happens when vmpg_bytes =4kb and tile blk_bytes >=64kb). + */ + if (!surf_vert && vp_width > (2560 + 16) && bytes_per_element >= 4 && log2_vmpg_bytes == 12 + && log2_blk_bytes >= 16) { + log2_dpte_row_height = log2_dpte_row_height - 1; /*half of the full height */ + } + + *o_dpte_row_height = 1 << log2_dpte_row_height; +} + +static void get_surf_rq_param( + struct display_mode_lib *mode_lib, + struct _vcs_dpi_display_data_rq_sizing_params_st *rq_sizing_param, + struct _vcs_dpi_display_data_rq_dlg_params_st *rq_dlg_param, + struct _vcs_dpi_display_data_rq_misc_params_st *rq_misc_param, + const struct _vcs_dpi_display_pipe_source_params_st pipe_src_param, + bool is_chroma) +{ + bool mode_422 = 0; + unsigned int vp_width = 0; + unsigned int vp_height = 0; + unsigned int data_pitch = 0; + unsigned int meta_pitch = 0; + unsigned int ppe = mode_422 ? 2 : 1; + bool surf_linear; + bool surf_vert; + unsigned int bytes_per_element; + unsigned int log2_bytes_per_element; + unsigned int blk256_width; + unsigned int blk256_height; + unsigned int log2_blk256_width; + unsigned int log2_blk256_height; + unsigned int blk_bytes; + unsigned int log2_blk_bytes; + unsigned int log2_blk_height; + unsigned int log2_blk_width; + unsigned int log2_meta_req_bytes; + unsigned int log2_meta_req_height; + unsigned int log2_meta_req_width; + unsigned int meta_req_width; + unsigned int meta_req_height; + unsigned int log2_meta_row_height; + unsigned int meta_row_width_ub; + unsigned int log2_meta_chunk_bytes; + unsigned int log2_meta_chunk_height; + unsigned int log2_meta_chunk_width; + unsigned int log2_min_meta_chunk_bytes; + unsigned int min_meta_chunk_width; + unsigned int meta_chunk_width; + unsigned int meta_chunk_per_row_int; + unsigned int meta_row_remainder; + unsigned int meta_chunk_threshold; + unsigned int meta_blk_bytes; + unsigned int meta_blk_height; + unsigned int meta_blk_width; + unsigned int meta_surface_bytes; + unsigned int vmpg_bytes; + unsigned int meta_pte_req_per_frame_ub; + unsigned int meta_pte_bytes_per_frame_ub; + unsigned int log2_vmpg_bytes; + unsigned int dpte_buf_in_pte_reqs; + unsigned int log2_vmpg_height; + unsigned int log2_vmpg_width; + unsigned int log2_dpte_req_height_ptes; + unsigned int log2_dpte_req_width_ptes; + unsigned int log2_dpte_req_height; + unsigned int log2_dpte_req_width; + unsigned int log2_dpte_row_height_linear; + unsigned int log2_dpte_row_height; + unsigned int log2_dpte_group_width; + unsigned int dpte_row_width_ub; + unsigned int dpte_row_height; + unsigned int dpte_req_height; + unsigned int dpte_req_width; + unsigned int dpte_group_width; + unsigned int log2_dpte_group_bytes; + unsigned int log2_dpte_group_length; + unsigned int func_meta_row_height, func_dpte_row_height; + + /* FIXME check if ppe apply for both luma and chroma in 422 case */ + if (is_chroma) { + vp_width = pipe_src_param.viewport_width_c / ppe; + vp_height = pipe_src_param.viewport_height_c; + data_pitch = pipe_src_param.data_pitch_c; + meta_pitch = pipe_src_param.meta_pitch_c; + } else { + vp_width = pipe_src_param.viewport_width / ppe; + vp_height = pipe_src_param.viewport_height; + data_pitch = pipe_src_param.data_pitch; + meta_pitch = pipe_src_param.meta_pitch; + } + + rq_sizing_param->chunk_bytes = 8192; + + if (rq_sizing_param->chunk_bytes == 64 * 1024) + rq_sizing_param->min_chunk_bytes = 0; + else + rq_sizing_param->min_chunk_bytes = 1024; + + rq_sizing_param->meta_chunk_bytes = 2048; + rq_sizing_param->min_meta_chunk_bytes = 256; + + rq_sizing_param->mpte_group_bytes = 2048; + + surf_linear = (pipe_src_param.sw_mode == dm_sw_linear); + surf_vert = (pipe_src_param.source_scan == dm_vert); + + bytes_per_element = get_bytes_per_element( + (enum source_format_class) pipe_src_param.source_format, + is_chroma); + log2_bytes_per_element = dml_log2(bytes_per_element); + blk256_width = 0; + blk256_height = 0; + + if (surf_linear) { + blk256_width = 256 / bytes_per_element; + blk256_height = 1; + } else { + get_blk256_size(&blk256_width, &blk256_height, bytes_per_element); + } + + DTRACE("DLG: %s: surf_linear = %d", __func__, surf_linear); + DTRACE("DLG: %s: surf_vert = %d", __func__, surf_vert); + DTRACE("DLG: %s: blk256_width = %d", __func__, blk256_width); + DTRACE("DLG: %s: blk256_height = %d", __func__, blk256_height); + + log2_blk256_width = dml_log2((double) blk256_width); + log2_blk256_height = dml_log2((double) blk256_height); + blk_bytes = + surf_linear ? 256 : get_blk_size_bytes( + (enum source_macro_tile_size) pipe_src_param.macro_tile_size); + log2_blk_bytes = dml_log2((double) blk_bytes); + log2_blk_height = 0; + log2_blk_width = 0; + + /* remember log rule + * "+" in log is multiply + * "-" in log is divide + * "/2" is like square root + * blk is vertical biased + */ + if (pipe_src_param.sw_mode != dm_sw_linear) + log2_blk_height = log2_blk256_height + + dml_ceil((double) (log2_blk_bytes - 8) / 2.0); + else + log2_blk_height = 0; /* blk height of 1 */ + + log2_blk_width = log2_blk_bytes - log2_bytes_per_element - log2_blk_height; + + if (!surf_vert) { + rq_dlg_param->swath_width_ub = dml_round_to_multiple(vp_width - 1, blk256_width, 1) + + blk256_width; + rq_dlg_param->req_per_swath_ub = rq_dlg_param->swath_width_ub >> log2_blk256_width; + } else { + rq_dlg_param->swath_width_ub = dml_round_to_multiple( + vp_height - 1, + blk256_height, + 1) + blk256_height; + rq_dlg_param->req_per_swath_ub = rq_dlg_param->swath_width_ub >> log2_blk256_height; + } + + if (!surf_vert) + rq_misc_param->full_swath_bytes = rq_dlg_param->swath_width_ub * blk256_height + * bytes_per_element; + else + rq_misc_param->full_swath_bytes = rq_dlg_param->swath_width_ub * blk256_width + * bytes_per_element; + + rq_misc_param->blk256_height = blk256_height; + rq_misc_param->blk256_width = blk256_width; + + /* ------- */ + /* meta */ + /* ------- */ + log2_meta_req_bytes = 6; /* meta request is 64b and is 8x8byte meta element */ + + /* each 64b meta request for dcn is 8x8 meta elements and + * a meta element covers one 256b block of the the data surface. + */ + log2_meta_req_height = log2_blk256_height + 3; /* meta req is 8x8 byte, each byte represent 1 blk256 */ + log2_meta_req_width = log2_meta_req_bytes + 8 - log2_bytes_per_element + - log2_meta_req_height; + meta_req_width = 1 << log2_meta_req_width; + meta_req_height = 1 << log2_meta_req_height; + log2_meta_row_height = 0; + meta_row_width_ub = 0; + + /* the dimensions of a meta row are meta_row_width x meta_row_height in elements. + * calculate upper bound of the meta_row_width + */ + if (!surf_vert) { + log2_meta_row_height = log2_meta_req_height; + meta_row_width_ub = dml_round_to_multiple(vp_width - 1, meta_req_width, 1) + + meta_req_width; + rq_dlg_param->meta_req_per_row_ub = meta_row_width_ub / meta_req_width; + } else { + log2_meta_row_height = log2_meta_req_width; + meta_row_width_ub = dml_round_to_multiple(vp_height - 1, meta_req_height, 1) + + meta_req_height; + rq_dlg_param->meta_req_per_row_ub = meta_row_width_ub / meta_req_height; + } + rq_dlg_param->meta_bytes_per_row_ub = rq_dlg_param->meta_req_per_row_ub * 64; + + log2_meta_chunk_bytes = dml_log2(rq_sizing_param->meta_chunk_bytes); + log2_meta_chunk_height = log2_meta_row_height; + + /*full sized meta chunk width in unit of data elements */ + log2_meta_chunk_width = log2_meta_chunk_bytes + 8 - log2_bytes_per_element + - log2_meta_chunk_height; + log2_min_meta_chunk_bytes = dml_log2(rq_sizing_param->min_meta_chunk_bytes); + min_meta_chunk_width = 1 + << (log2_min_meta_chunk_bytes + 8 - log2_bytes_per_element + - log2_meta_chunk_height); + meta_chunk_width = 1 << log2_meta_chunk_width; + meta_chunk_per_row_int = (unsigned int) (meta_row_width_ub / meta_chunk_width); + meta_row_remainder = meta_row_width_ub % meta_chunk_width; + meta_chunk_threshold = 0; + meta_blk_bytes = 4096; + meta_blk_height = blk256_height * 64; + meta_blk_width = meta_blk_bytes * 256 / bytes_per_element / meta_blk_height; + meta_surface_bytes = meta_pitch + * (dml_round_to_multiple(vp_height - 1, meta_blk_height, 1) + + meta_blk_height) * bytes_per_element / 256; + vmpg_bytes = mode_lib->soc.vmm_page_size_bytes; + meta_pte_req_per_frame_ub = (dml_round_to_multiple( + meta_surface_bytes - vmpg_bytes, + 8 * vmpg_bytes, + 1) + 8 * vmpg_bytes) / (8 * vmpg_bytes); + meta_pte_bytes_per_frame_ub = meta_pte_req_per_frame_ub * 64; /*64B mpte request */ + rq_dlg_param->meta_pte_bytes_per_frame_ub = meta_pte_bytes_per_frame_ub; + + DTRACE("DLG: %s: meta_blk_height = %d", __func__, meta_blk_height); + DTRACE("DLG: %s: meta_blk_width = %d", __func__, meta_blk_width); + DTRACE("DLG: %s: meta_surface_bytes = %d", __func__, meta_surface_bytes); + DTRACE("DLG: %s: meta_pte_req_per_frame_ub = %d", __func__, meta_pte_req_per_frame_ub); + DTRACE("DLG: %s: meta_pte_bytes_per_frame_ub = %d", __func__, meta_pte_bytes_per_frame_ub); + + if (!surf_vert) + meta_chunk_threshold = 2 * min_meta_chunk_width - meta_req_width; + else + meta_chunk_threshold = 2 * min_meta_chunk_width - meta_req_height; + + if (meta_row_remainder <= meta_chunk_threshold) + rq_dlg_param->meta_chunks_per_row_ub = meta_chunk_per_row_int + 1; + else + rq_dlg_param->meta_chunks_per_row_ub = meta_chunk_per_row_int + 2; + + rq_dlg_param->meta_row_height = 1 << log2_meta_row_height; + + /* ------ */ + /* dpte */ + /* ------ */ + log2_vmpg_bytes = dml_log2(mode_lib->soc.vmm_page_size_bytes); + dpte_buf_in_pte_reqs = mode_lib->ip.dpte_buffer_size_in_pte_reqs; + + log2_vmpg_height = 0; + log2_vmpg_width = 0; + log2_dpte_req_height_ptes = 0; + log2_dpte_req_width_ptes = 0; + log2_dpte_req_height = 0; + log2_dpte_req_width = 0; + log2_dpte_row_height_linear = 0; + log2_dpte_row_height = 0; + log2_dpte_group_width = 0; + dpte_row_width_ub = 0; + dpte_row_height = 0; + dpte_req_height = 0; /* 64b dpte req height in data element */ + dpte_req_width = 0; /* 64b dpte req width in data element */ + dpte_group_width = 0; + log2_dpte_group_bytes = 0; + log2_dpte_group_length = 0; + + if (surf_linear) { + log2_vmpg_height = 0; /* one line high */ + } else { + log2_vmpg_height = (log2_vmpg_bytes - 8) / 2 + log2_blk256_height; + } + log2_vmpg_width = log2_vmpg_bytes - log2_bytes_per_element - log2_vmpg_height; + + /* only 3 possible shapes for dpte request in dimensions of ptes: 8x1, 4x2, 2x4. */ + if (log2_blk_bytes <= log2_vmpg_bytes) + log2_dpte_req_height_ptes = 0; + else if (log2_blk_height - log2_vmpg_height >= 2) + log2_dpte_req_height_ptes = 2; + else + log2_dpte_req_height_ptes = log2_blk_height - log2_vmpg_height; + log2_dpte_req_width_ptes = 3 - log2_dpte_req_height_ptes; + + /* Ensure we only have the 3 shapes */ + ASSERT((log2_dpte_req_width_ptes == 3 && log2_dpte_req_height_ptes == 0) || /* 8x1 */ + (log2_dpte_req_width_ptes == 2 && log2_dpte_req_height_ptes == 1) || /* 4x2 */ + (log2_dpte_req_width_ptes == 1 && log2_dpte_req_height_ptes == 2)); /* 2x4 */ + + /* The dpte request dimensions in data elements is dpte_req_width x dpte_req_height + * log2_vmpg_width is how much 1 pte represent, now calculating how much a 64b pte req represent + * That depends on the pte shape (i.e. 8x1, 4x2, 2x4) + */ + log2_dpte_req_height = log2_vmpg_height + log2_dpte_req_height_ptes; + log2_dpte_req_width = log2_vmpg_width + log2_dpte_req_width_ptes; + dpte_req_height = 1 << log2_dpte_req_height; + dpte_req_width = 1 << log2_dpte_req_width; + + /* calculate pitch dpte row buffer can hold + * round the result down to a power of two. + */ + if (surf_linear) { + log2_dpte_row_height_linear = dml_floor( + dml_log2(dpte_buf_in_pte_reqs * dpte_req_width / data_pitch)); + + ASSERT(log2_dpte_row_height_linear >= 3); + + if (log2_dpte_row_height_linear > 7) + log2_dpte_row_height_linear = 7; + + log2_dpte_row_height = log2_dpte_row_height_linear; + rq_dlg_param->dpte_row_height = 1 << log2_dpte_row_height; + + /* For linear, the dpte row is pitch dependent and the pte requests wrap at the pitch boundary. + * the dpte_row_width_ub is the upper bound of data_pitch*dpte_row_height in elements with this unique buffering. + */ + dpte_row_width_ub = dml_round_to_multiple( + data_pitch * dpte_row_height - 1, + dpte_req_width, + 1) + dpte_req_width; + rq_dlg_param->dpte_req_per_row_ub = dpte_row_width_ub / dpte_req_width; + } else { + /* for tiled mode, row height is the same as req height and row store up to vp size upper bound */ + if (!surf_vert) { + log2_dpte_row_height = log2_dpte_req_height; + dpte_row_width_ub = dml_round_to_multiple(vp_width - 1, dpte_req_width, 1) + + dpte_req_width; + rq_dlg_param->dpte_req_per_row_ub = dpte_row_width_ub / dpte_req_width; + } else { + log2_dpte_row_height = + (log2_blk_width < log2_dpte_req_width) ? + log2_blk_width : log2_dpte_req_width; + dpte_row_width_ub = dml_round_to_multiple(vp_height - 1, dpte_req_height, 1) + + dpte_req_height; + rq_dlg_param->dpte_req_per_row_ub = dpte_row_width_ub / dpte_req_height; + } + rq_dlg_param->dpte_row_height = 1 << log2_dpte_row_height; + } + rq_dlg_param->dpte_bytes_per_row_ub = rq_dlg_param->dpte_req_per_row_ub * 64; + + /* From programming guide: + * There is a special case of saving only half of ptes returned due to buffer space limits. + * this case applies to 4 and 8bpe in horizontal access of a vp_width greater than 2560+16 + * when the pte request is 2x4 ptes (which happens when vmpg_bytes =4kb and tile blk_bytes >=64kb). + */ + if (!surf_vert && vp_width > (2560 + 16) && bytes_per_element >= 4 && log2_vmpg_bytes == 12 + && log2_blk_bytes >= 16) { + log2_dpte_row_height = log2_dpte_row_height - 1; /*half of the full height */ + rq_dlg_param->dpte_row_height = 1 << log2_dpte_row_height; + } + + /* the dpte_group_bytes is reduced for the specific case of vertical + * access of a tile surface that has dpte request of 8x1 ptes. + */ + if (!surf_linear & (log2_dpte_req_height_ptes == 0) & surf_vert) /*reduced, in this case, will have page fault within a group */ + rq_sizing_param->dpte_group_bytes = 512; + else + /*full size */ + rq_sizing_param->dpte_group_bytes = 2048; + + /*since pte request size is 64byte, the number of data pte requests per full sized group is as follows. */ + log2_dpte_group_bytes = dml_log2(rq_sizing_param->dpte_group_bytes); + log2_dpte_group_length = log2_dpte_group_bytes - 6; /*length in 64b requests */ + + /* full sized data pte group width in elements */ + if (!surf_vert) + log2_dpte_group_width = log2_dpte_group_length + log2_dpte_req_width; + else + log2_dpte_group_width = log2_dpte_group_length + log2_dpte_req_height; + + dpte_group_width = 1 << log2_dpte_group_width; + + /* since dpte groups are only aligned to dpte_req_width and not dpte_group_width, + * the upper bound for the dpte groups per row is as follows. + */ + rq_dlg_param->dpte_groups_per_row_ub = dml_ceil( + (double) dpte_row_width_ub / dpte_group_width); + + dml_rq_dlg_get_row_heights( + mode_lib, + &func_dpte_row_height, + &func_meta_row_height, + vp_width, + data_pitch, + pipe_src_param.source_format, + pipe_src_param.sw_mode, + pipe_src_param.macro_tile_size, + pipe_src_param.source_scan, + is_chroma); + + /* Just a check to make sure this function and the new one give the same + * result. The standalone get_row_heights() function is based off of the + * code in this function so the same changes need to be made to both. + */ + if (rq_dlg_param->meta_row_height != func_meta_row_height) { + DTRACE( + "MISMATCH: rq_dlg_param->meta_row_height = %d", + rq_dlg_param->meta_row_height); + DTRACE("MISMATCH: func_meta_row_height = %d", func_meta_row_height); + ASSERT(0); + } + + if (rq_dlg_param->dpte_row_height != func_dpte_row_height) { + DTRACE( + "MISMATCH: rq_dlg_param->dpte_row_height = %d", + rq_dlg_param->dpte_row_height); + DTRACE("MISMATCH: func_dpte_row_height = %d", func_dpte_row_height); + ASSERT(0); + } +} + +void dml_rq_dlg_get_rq_params( + struct display_mode_lib *mode_lib, + struct _vcs_dpi_display_rq_params_st *rq_param, + const struct _vcs_dpi_display_pipe_source_params_st pipe_src_param) +{ + /* get param for luma surface */ + rq_param->yuv420 = pipe_src_param.source_format == dm_420_8 + || pipe_src_param.source_format == dm_420_10; + rq_param->yuv420_10bpc = pipe_src_param.source_format == dm_420_10; + + get_surf_rq_param( + mode_lib, + &(rq_param->sizing.rq_l), + &(rq_param->dlg.rq_l), + &(rq_param->misc.rq_l), + pipe_src_param, + 0); + + if (is_dual_plane((enum source_format_class) pipe_src_param.source_format)) { + /* get param for chroma surface */ + get_surf_rq_param( + mode_lib, + &(rq_param->sizing.rq_c), + &(rq_param->dlg.rq_c), + &(rq_param->misc.rq_c), + pipe_src_param, + 1); + } + + /* calculate how to split the det buffer space between luma and chroma */ + handle_det_buf_split(mode_lib, rq_param, pipe_src_param); + print__rq_params_st(mode_lib, *rq_param); +} + +void dml_rq_dlg_get_rq_reg( + struct display_mode_lib *mode_lib, + struct _vcs_dpi_display_rq_regs_st *rq_regs, + const struct _vcs_dpi_display_pipe_source_params_st pipe_src_param) +{ + struct _vcs_dpi_display_rq_params_st rq_param = {0}; + + memset(rq_regs, 0, sizeof(*rq_regs)); + + dml_rq_dlg_get_rq_params(mode_lib, &rq_param, pipe_src_param); + extract_rq_regs(mode_lib, rq_regs, rq_param); + + print__rq_regs_st(mode_lib, *rq_regs); +} + +/* TODO: Need refactor, so this is used by dml_rq_dlg_get_dlg_params as well + * The problem is that there are some intermediate terms that would need by + * some dlg calculation (i.e. rest of prefetch and active prog guide calculation) + */ +void dml_rq_dlg_get_dlg_params_prefetch( + struct display_mode_lib *mode_lib, + struct _vcs_dpi_display_dlg_prefetch_param_st *prefetch_param, + struct _vcs_dpi_display_rq_dlg_params_st rq_dlg_param, + struct _vcs_dpi_display_dlg_sys_params_st dlg_sys_param, + struct _vcs_dpi_display_e2e_pipe_params_st e2e_pipe_param, + const bool cstate_en, + const bool pstate_en, + const bool vm_en) +{ + /* Prefetch */ + unsigned int htotal = e2e_pipe_param.pipe.dest.htotal; + bool interlaced = e2e_pipe_param.pipe.dest.interlaced; + unsigned int min_vblank = mode_lib->ip.min_vblank_lines; + const double prefetch_xy_calc_in_dcfclk = 24.0; /* FIXME: ip_param */ + double min_dcfclk_mhz = dlg_sys_param.deepsleep_dcfclk_mhz; + double t_calc_us = prefetch_xy_calc_in_dcfclk / min_dcfclk_mhz; + + bool dcc_en = e2e_pipe_param.pipe.src.dcc; + bool dual_plane = is_dual_plane( + (enum source_format_class) e2e_pipe_param.pipe.src.source_format); + unsigned int bytes_per_element_l = get_bytes_per_element( + (enum source_format_class) e2e_pipe_param.pipe.src.source_format, + 0); + unsigned int bytes_per_element_c = get_bytes_per_element( + (enum source_format_class) e2e_pipe_param.pipe.src.source_format, + 1); + + double pclk_freq_in_mhz = e2e_pipe_param.pipe.dest.pixel_rate_mhz; + double dppclk_freq_in_mhz = e2e_pipe_param.clks_cfg.dppclk_mhz; + double dispclk_freq_in_mhz = e2e_pipe_param.clks_cfg.dispclk_mhz; + + double line_time_in_us = (htotal / pclk_freq_in_mhz); + double vinit_l = e2e_pipe_param.pipe.scale_ratio_depth.vinit; + double vinit_c = e2e_pipe_param.pipe.scale_ratio_depth.vinit_c; + double vinit_bot_l = e2e_pipe_param.pipe.scale_ratio_depth.vinit_bot; + double vinit_bot_c = e2e_pipe_param.pipe.scale_ratio_depth.vinit_bot_c; + + unsigned int swath_height_l = rq_dlg_param.rq_l.swath_height; + unsigned int swath_width_ub_l = rq_dlg_param.rq_l.swath_width_ub; + unsigned int dpte_bytes_per_row_ub_l = rq_dlg_param.rq_l.dpte_bytes_per_row_ub; + unsigned int meta_pte_bytes_per_frame_ub_l = rq_dlg_param.rq_l.meta_pte_bytes_per_frame_ub; + unsigned int meta_bytes_per_row_ub_l = rq_dlg_param.rq_l.meta_bytes_per_row_ub; + + unsigned int swath_height_c = rq_dlg_param.rq_c.swath_height; + unsigned int swath_width_ub_c = rq_dlg_param.rq_c.swath_width_ub; + unsigned int dpte_bytes_per_row_ub_c = rq_dlg_param.rq_c.dpte_bytes_per_row_ub; + unsigned int vupdate_offset = e2e_pipe_param.pipe.dest.vupdate_offset; + unsigned int vupdate_width = e2e_pipe_param.pipe.dest.vupdate_width; + unsigned int vready_offset = e2e_pipe_param.pipe.dest.vready_offset; + + const unsigned int dppclk_delay_subtotal = mode_lib->ip.dppclk_delay_subtotal; + const unsigned int dispclk_delay_subtotal = mode_lib->ip.dispclk_delay_subtotal; + unsigned int pixel_rate_delay_subtotal = dppclk_delay_subtotal * pclk_freq_in_mhz + / dppclk_freq_in_mhz + + dispclk_delay_subtotal * pclk_freq_in_mhz / dispclk_freq_in_mhz; + unsigned int dst_y_after_scaler = 0; + unsigned int dst_x_after_scaler = 0; + + unsigned int vstartup_start = e2e_pipe_param.pipe.dest.vstartup_start; + + double line_wait; + double line_o; + double line_setup; + double line_calc; + double dst_y_prefetch; + double t_pre_us; + int unsigned vm_bytes; + int unsigned meta_row_bytes; + int unsigned max_num_sw_l; + int unsigned max_num_sw_c; + int unsigned max_partial_sw_l; + int unsigned max_partial_sw_c; + + double max_vinit_l; + double max_vinit_c; + int unsigned lsw_l; + int unsigned lsw_c; + int unsigned sw_bytes_ub_l; + int unsigned sw_bytes_ub_c; + int unsigned sw_bytes; + int unsigned dpte_row_bytes; + + if (interlaced) + vstartup_start = vstartup_start / 2; + + if (vstartup_start >= min_vblank) { + min_vblank = vstartup_start + 1; + DTRACE( + "WARNING_DLG: %s: vstartup_start=%d should be less than min_vblank=%d", + __func__, + vstartup_start, + min_vblank); + } + + if (e2e_pipe_param.pipe.src.is_hsplit) + dst_x_after_scaler = pixel_rate_delay_subtotal + + e2e_pipe_param.pipe.dest.recout_width; + else + dst_x_after_scaler = pixel_rate_delay_subtotal; + + if (e2e_pipe_param.dout.output_format == dm_420) + dst_y_after_scaler = 1; + else + dst_y_after_scaler = 0; + + if (dst_x_after_scaler >= htotal) { + dst_x_after_scaler = dst_x_after_scaler - htotal; + dst_y_after_scaler = dst_y_after_scaler + 1; + } + + DTRACE("DLG: %s: htotal = %d", __func__, htotal); + DTRACE( + "DLG: %s: pixel_rate_delay_subtotal = %d", + __func__, + pixel_rate_delay_subtotal); + DTRACE("DLG: %s: dst_x_after_scaler = %d", __func__, dst_x_after_scaler); + DTRACE("DLG: %s: dst_y_after_scaler = %d", __func__, dst_y_after_scaler); + + line_wait = mode_lib->soc.urgent_latency_us; + if (cstate_en) + line_wait = dml_max(mode_lib->soc.sr_enter_plus_exit_time_us, line_wait); + if (pstate_en) + line_wait = dml_max( + mode_lib->soc.dram_clock_change_latency_us + + mode_lib->soc.urgent_latency_us, + line_wait); + line_wait = line_wait / line_time_in_us; + + line_o = (double) dst_y_after_scaler + dst_x_after_scaler / (double) htotal; + line_setup = (double) (vupdate_offset + vupdate_width + vready_offset) / (double) htotal; + line_calc = t_calc_us / line_time_in_us; + + DTRACE( + "DLG: %s: soc.sr_enter_plus_exit_time_us = %3.2f", + __func__, + (double) mode_lib->soc.sr_enter_plus_exit_time_us); + DTRACE( + "DLG: %s: soc.dram_clock_change_latency_us = %3.2f", + __func__, + (double) mode_lib->soc.dram_clock_change_latency_us); + + DTRACE("DLG: %s: urgent_latency_us = %3.2f", __func__, mode_lib->soc.urgent_latency_us); + DTRACE( + "DLG: %s: t_srx_delay_us = %3.2f", + __func__, + (double) dlg_sys_param.t_srx_delay_us); + DTRACE("DLG: %s: line_time_in_us = %3.2f", __func__, (double) line_time_in_us); + DTRACE("DLG: %s: vupdate_offset = %d", __func__, vupdate_offset); + DTRACE("DLG: %s: vupdate_width = %d", __func__, vupdate_width); + DTRACE("DLG: %s: vready_offset = %d", __func__, vready_offset); + DTRACE("DLG: %s: line_wait = %3.2f", __func__, line_wait); + DTRACE("DLG: %s: line_o = %3.2f", __func__, line_o); + DTRACE("DLG: %s: line_setup = %3.2f", __func__, line_setup); + DTRACE("DLG: %s: line_calc = %3.2f", __func__, line_calc); + + dst_y_prefetch = ((double) min_vblank - 1.0) + - (line_setup + line_calc + line_wait + line_o); + DTRACE("DLG: %s: dst_y_prefetch (before rnd) = %3.2f", __func__, dst_y_prefetch); + ASSERT(dst_y_prefetch >= 2.0); + + dst_y_prefetch = dml_floor(4.0 * (dst_y_prefetch + 0.125)) / 4; + DTRACE("DLG: %s: dst_y_prefetch (after rnd) = %3.2f", __func__, dst_y_prefetch); + + t_pre_us = dst_y_prefetch * line_time_in_us; + vm_bytes = 0; + meta_row_bytes = 0; + + if (dcc_en && vm_en) + vm_bytes = meta_pte_bytes_per_frame_ub_l; + if (dcc_en) + meta_row_bytes = meta_bytes_per_row_ub_l; + + max_num_sw_l = 0; + max_num_sw_c = 0; + max_partial_sw_l = 0; + max_partial_sw_c = 0; + + max_vinit_l = interlaced ? dml_max(vinit_l, vinit_bot_l) : vinit_l; + max_vinit_c = interlaced ? dml_max(vinit_c, vinit_bot_c) : vinit_c; + + get_swath_need(mode_lib, &max_num_sw_l, &max_partial_sw_l, swath_height_l, max_vinit_l); + if (dual_plane) + get_swath_need( + mode_lib, + &max_num_sw_c, + &max_partial_sw_c, + swath_height_c, + max_vinit_c); + + lsw_l = max_num_sw_l * swath_height_l + max_partial_sw_l; + lsw_c = max_num_sw_c * swath_height_c + max_partial_sw_c; + sw_bytes_ub_l = lsw_l * swath_width_ub_l * bytes_per_element_l; + sw_bytes_ub_c = lsw_c * swath_width_ub_c * bytes_per_element_c; + sw_bytes = 0; + dpte_row_bytes = 0; + + if (vm_en) { + if (dual_plane) + dpte_row_bytes = dpte_bytes_per_row_ub_l + dpte_bytes_per_row_ub_c; + else + dpte_row_bytes = dpte_bytes_per_row_ub_l; + } else { + dpte_row_bytes = 0; + } + + if (dual_plane) + sw_bytes = sw_bytes_ub_l + sw_bytes_ub_c; + else + sw_bytes = sw_bytes_ub_l; + + DTRACE("DLG: %s: sw_bytes_ub_l = %d", __func__, sw_bytes_ub_l); + DTRACE("DLG: %s: sw_bytes_ub_c = %d", __func__, sw_bytes_ub_c); + DTRACE("DLG: %s: sw_bytes = %d", __func__, sw_bytes); + DTRACE("DLG: %s: vm_bytes = %d", __func__, vm_bytes); + DTRACE("DLG: %s: meta_row_bytes = %d", __func__, meta_row_bytes); + DTRACE("DLG: %s: dpte_row_bytes = %d", __func__, dpte_row_bytes); + + prefetch_param->prefetch_bw = + (vm_bytes + 2 * dpte_row_bytes + 2 * meta_row_bytes + sw_bytes) / t_pre_us; + prefetch_param->flip_bytes = (vm_bytes + dpte_row_bytes + meta_row_bytes); +} + +/* Note: currently taken in as is. + * Nice to decouple code from hw register implement and extract code that are repeated for luma and chroma. + */ +void dml_rq_dlg_get_dlg_params( + struct display_mode_lib *mode_lib, + struct _vcs_dpi_display_dlg_regs_st *disp_dlg_regs, + struct _vcs_dpi_display_ttu_regs_st *disp_ttu_regs, + const struct _vcs_dpi_display_rq_dlg_params_st rq_dlg_param, + const struct _vcs_dpi_display_dlg_sys_params_st dlg_sys_param, + const struct _vcs_dpi_display_e2e_pipe_params_st e2e_pipe_param, + const bool cstate_en, + const bool pstate_en, + const bool vm_en, + const bool iflip_en) +{ + /* Timing */ + unsigned int htotal = e2e_pipe_param.pipe.dest.htotal; + unsigned int hblank_end = e2e_pipe_param.pipe.dest.hblank_end; + unsigned int vblank_start = e2e_pipe_param.pipe.dest.vblank_start; + unsigned int vblank_end = e2e_pipe_param.pipe.dest.vblank_end; + bool interlaced = e2e_pipe_param.pipe.dest.interlaced; + unsigned int min_vblank = mode_lib->ip.min_vblank_lines; + + double pclk_freq_in_mhz = e2e_pipe_param.pipe.dest.pixel_rate_mhz; + double refclk_freq_in_mhz = e2e_pipe_param.clks_cfg.refclk_mhz; + double dppclk_freq_in_mhz = e2e_pipe_param.clks_cfg.dppclk_mhz; + double dispclk_freq_in_mhz = e2e_pipe_param.clks_cfg.dispclk_mhz; + + double ref_freq_to_pix_freq; + double prefetch_xy_calc_in_dcfclk; + double min_dcfclk_mhz; + double t_calc_us; + double min_ttu_vblank; + double min_dst_y_ttu_vblank; + int unsigned dlg_vblank_start; + bool dcc_en; + bool dual_plane; + bool mode_422; + unsigned int access_dir; + unsigned int bytes_per_element_l; + unsigned int bytes_per_element_c; + unsigned int vp_height_l; + unsigned int vp_width_l; + unsigned int vp_height_c; + unsigned int vp_width_c; + unsigned int htaps_l; + unsigned int htaps_c; + double hratios_l; + double hratios_c; + double vratio_l; + double vratio_c; + double line_time_in_us; + double vinit_l; + double vinit_c; + double vinit_bot_l; + double vinit_bot_c; + unsigned int swath_height_l; + unsigned int swath_width_ub_l; + unsigned int dpte_bytes_per_row_ub_l; + unsigned int dpte_groups_per_row_ub_l; + unsigned int meta_pte_bytes_per_frame_ub_l; + unsigned int meta_bytes_per_row_ub_l; + unsigned int swath_height_c; + unsigned int swath_width_ub_c; + unsigned int dpte_bytes_per_row_ub_c; + unsigned int dpte_groups_per_row_ub_c; + unsigned int meta_chunks_per_row_ub_l; + unsigned int vupdate_offset; + unsigned int vupdate_width; + unsigned int vready_offset; + unsigned int dppclk_delay_subtotal; + unsigned int dispclk_delay_subtotal; + unsigned int pixel_rate_delay_subtotal; + unsigned int vstartup_start; + unsigned int dst_x_after_scaler; + unsigned int dst_y_after_scaler; + double line_wait; + double line_o; + double line_setup; + double line_calc; + double dst_y_prefetch; + double t_pre_us; + int unsigned vm_bytes; + int unsigned meta_row_bytes; + int unsigned max_num_sw_l; + int unsigned max_num_sw_c; + int unsigned max_partial_sw_l; + int unsigned max_partial_sw_c; + double max_vinit_l; + double max_vinit_c; + int unsigned lsw_l; + int unsigned lsw_c; + int unsigned sw_bytes_ub_l; + int unsigned sw_bytes_ub_c; + int unsigned sw_bytes; + int unsigned dpte_row_bytes; + double prefetch_bw; + double flip_bw; + double t_vm_us; + double t_r0_us; + double dst_y_per_vm_vblank; + double dst_y_per_row_vblank; + double min_dst_y_per_vm_vblank; + double min_dst_y_per_row_vblank; + double lsw; + double vratio_pre_l; + double vratio_pre_c; + unsigned int req_per_swath_ub_l; + unsigned int req_per_swath_ub_c; + unsigned int meta_row_height_l; + unsigned int swath_width_pixels_ub_l; + unsigned int swath_width_pixels_ub_c; + unsigned int scaler_rec_in_width_l; + unsigned int scaler_rec_in_width_c; + unsigned int dpte_row_height_l; + unsigned int dpte_row_height_c; + double hscale_pixel_rate_l; + double hscale_pixel_rate_c; + double min_hratio_fact_l; + double min_hratio_fact_c; + double refcyc_per_line_delivery_pre_l; + double refcyc_per_line_delivery_pre_c; + double refcyc_per_line_delivery_l; + double refcyc_per_line_delivery_c; + double refcyc_per_req_delivery_pre_l; + double refcyc_per_req_delivery_pre_c; + double refcyc_per_req_delivery_l; + double refcyc_per_req_delivery_c; + double refcyc_per_req_delivery_pre_cur0; + double refcyc_per_req_delivery_cur0; + int unsigned full_recout_width; + double hratios_cur0; + unsigned int cur0_src_width; + enum cursor_bpp cur0_bpp; + unsigned int cur0_req_size; + unsigned int cur0_req_width; + double cur0_width_ub; + double cur0_req_per_width; + double hactive_cur0; + + memset(disp_dlg_regs, 0, sizeof(*disp_dlg_regs)); + memset(disp_ttu_regs, 0, sizeof(*disp_ttu_regs)); + + DTRACE("DLG: %s: cstate_en = %d", __func__, cstate_en); + DTRACE("DLG: %s: pstate_en = %d", __func__, pstate_en); + DTRACE("DLG: %s: vm_en = %d", __func__, vm_en); + DTRACE("DLG: %s: iflip_en = %d", __func__, iflip_en); + + /* ------------------------- */ + /* Section 1.5.2.1: OTG dependent Params */ + /* ------------------------- */ + DTRACE("DLG: %s: dppclk_freq_in_mhz = %3.2f", __func__, dppclk_freq_in_mhz); + DTRACE("DLG: %s: dispclk_freq_in_mhz = %3.2f", __func__, dispclk_freq_in_mhz); + DTRACE("DLG: %s: refclk_freq_in_mhz = %3.2f", __func__, refclk_freq_in_mhz); + DTRACE("DLG: %s: pclk_freq_in_mhz = %3.2f", __func__, pclk_freq_in_mhz); + DTRACE("DLG: %s: interlaced = %d", __func__, interlaced); + + ref_freq_to_pix_freq = refclk_freq_in_mhz / pclk_freq_in_mhz; + ASSERT(ref_freq_to_pix_freq < 4.0); + disp_dlg_regs->ref_freq_to_pix_freq = + (unsigned int) (ref_freq_to_pix_freq * dml_pow(2, 19)); + disp_dlg_regs->refcyc_per_htotal = (unsigned int) (ref_freq_to_pix_freq * (double) htotal + * dml_pow(2, 8)); + disp_dlg_regs->refcyc_h_blank_end = (unsigned int) ((double) hblank_end + * (double) ref_freq_to_pix_freq); + ASSERT(disp_dlg_regs->refcyc_h_blank_end < (unsigned int) dml_pow(2, 13)); + disp_dlg_regs->dlg_vblank_end = interlaced ? (vblank_end / 2) : vblank_end; /* 15 bits */ + + prefetch_xy_calc_in_dcfclk = 24.0; /* FIXME: ip_param */ + min_dcfclk_mhz = dlg_sys_param.deepsleep_dcfclk_mhz; + t_calc_us = prefetch_xy_calc_in_dcfclk / min_dcfclk_mhz; + min_ttu_vblank = dlg_sys_param.t_urg_wm_us; + if (cstate_en) + min_ttu_vblank = dml_max(dlg_sys_param.t_sr_wm_us, min_ttu_vblank); + if (pstate_en) + min_ttu_vblank = dml_max(dlg_sys_param.t_mclk_wm_us, min_ttu_vblank); + min_ttu_vblank = min_ttu_vblank + t_calc_us; + + min_dst_y_ttu_vblank = min_ttu_vblank * pclk_freq_in_mhz / (double) htotal; + dlg_vblank_start = interlaced ? (vblank_start / 2) : vblank_start; + + disp_dlg_regs->min_dst_y_next_start = (unsigned int) (((double) dlg_vblank_start + + min_dst_y_ttu_vblank) * dml_pow(2, 2)); + ASSERT(disp_dlg_regs->min_dst_y_next_start < (unsigned int) dml_pow(2, 18)); + + DTRACE("DLG: %s: min_dcfclk_mhz = %3.2f", __func__, min_dcfclk_mhz); + DTRACE("DLG: %s: min_ttu_vblank = %3.2f", __func__, min_ttu_vblank); + DTRACE( + "DLG: %s: min_dst_y_ttu_vblank = %3.2f", + __func__, + min_dst_y_ttu_vblank); + DTRACE("DLG: %s: t_calc_us = %3.2f", __func__, t_calc_us); + DTRACE( + "DLG: %s: disp_dlg_regs->min_dst_y_next_start = 0x%0x", + __func__, + disp_dlg_regs->min_dst_y_next_start); + DTRACE( + "DLG: %s: ref_freq_to_pix_freq = %3.2f", + __func__, + ref_freq_to_pix_freq); + + /* ------------------------- */ + /* Section 1.5.2.2: Prefetch, Active and TTU */ + /* ------------------------- */ + /* Prefetch Calc */ + /* Source */ + dcc_en = e2e_pipe_param.pipe.src.dcc; + dual_plane = is_dual_plane( + (enum source_format_class) e2e_pipe_param.pipe.src.source_format); + mode_422 = 0; /* FIXME */ + access_dir = (e2e_pipe_param.pipe.src.source_scan == dm_vert); /* vp access direction: horizontal or vertical accessed */ + bytes_per_element_l = get_bytes_per_element( + (enum source_format_class) e2e_pipe_param.pipe.src.source_format, + 0); + bytes_per_element_c = get_bytes_per_element( + (enum source_format_class) e2e_pipe_param.pipe.src.source_format, + 1); + vp_height_l = e2e_pipe_param.pipe.src.viewport_height; + vp_width_l = e2e_pipe_param.pipe.src.viewport_width; + vp_height_c = e2e_pipe_param.pipe.src.viewport_height_c; + vp_width_c = e2e_pipe_param.pipe.src.viewport_width_c; + + /* Scaling */ + htaps_l = e2e_pipe_param.pipe.scale_taps.htaps; + htaps_c = e2e_pipe_param.pipe.scale_taps.htaps_c; + hratios_l = e2e_pipe_param.pipe.scale_ratio_depth.hscl_ratio; + hratios_c = e2e_pipe_param.pipe.scale_ratio_depth.hscl_ratio_c; + vratio_l = e2e_pipe_param.pipe.scale_ratio_depth.vscl_ratio; + vratio_c = e2e_pipe_param.pipe.scale_ratio_depth.vscl_ratio_c; + + line_time_in_us = (htotal / pclk_freq_in_mhz); + vinit_l = e2e_pipe_param.pipe.scale_ratio_depth.vinit; + vinit_c = e2e_pipe_param.pipe.scale_ratio_depth.vinit_c; + vinit_bot_l = e2e_pipe_param.pipe.scale_ratio_depth.vinit_bot; + vinit_bot_c = e2e_pipe_param.pipe.scale_ratio_depth.vinit_bot_c; + + swath_height_l = rq_dlg_param.rq_l.swath_height; + swath_width_ub_l = rq_dlg_param.rq_l.swath_width_ub; + dpte_bytes_per_row_ub_l = rq_dlg_param.rq_l.dpte_bytes_per_row_ub; + dpte_groups_per_row_ub_l = rq_dlg_param.rq_l.dpte_groups_per_row_ub; + meta_pte_bytes_per_frame_ub_l = rq_dlg_param.rq_l.meta_pte_bytes_per_frame_ub; + meta_bytes_per_row_ub_l = rq_dlg_param.rq_l.meta_bytes_per_row_ub; + + swath_height_c = rq_dlg_param.rq_c.swath_height; + swath_width_ub_c = rq_dlg_param.rq_c.swath_width_ub; + dpte_bytes_per_row_ub_c = rq_dlg_param.rq_c.dpte_bytes_per_row_ub; + dpte_groups_per_row_ub_c = rq_dlg_param.rq_c.dpte_groups_per_row_ub; + + meta_chunks_per_row_ub_l = rq_dlg_param.rq_l.meta_chunks_per_row_ub; + vupdate_offset = e2e_pipe_param.pipe.dest.vupdate_offset; + vupdate_width = e2e_pipe_param.pipe.dest.vupdate_width; + vready_offset = e2e_pipe_param.pipe.dest.vready_offset; + + dppclk_delay_subtotal = mode_lib->ip.dppclk_delay_subtotal; + dispclk_delay_subtotal = mode_lib->ip.dispclk_delay_subtotal; + pixel_rate_delay_subtotal = dppclk_delay_subtotal * pclk_freq_in_mhz / dppclk_freq_in_mhz + + dispclk_delay_subtotal * pclk_freq_in_mhz / dispclk_freq_in_mhz; + + vstartup_start = e2e_pipe_param.pipe.dest.vstartup_start; + + if (interlaced) + vstartup_start = vstartup_start / 2; + + if (vstartup_start >= min_vblank) { + DTRACE( + "WARNING_DLG: %s: vblank_start=%d vblank_end=%d", + __func__, + vblank_start, + vblank_end); + DTRACE( + "WARNING_DLG: %s: vstartup_start=%d should be less than min_vblank=%d", + __func__, + vstartup_start, + min_vblank); + min_vblank = vstartup_start + 1; + DTRACE( + "WARNING_DLG: %s: vstartup_start=%d should be less than min_vblank=%d", + __func__, + vstartup_start, + min_vblank); + } + + dst_x_after_scaler = 0; + dst_y_after_scaler = 0; + + if (e2e_pipe_param.pipe.src.is_hsplit) + dst_x_after_scaler = pixel_rate_delay_subtotal + + e2e_pipe_param.pipe.dest.recout_width; + else + dst_x_after_scaler = pixel_rate_delay_subtotal; + + if (e2e_pipe_param.dout.output_format == dm_420) + dst_y_after_scaler = 1; + else + dst_y_after_scaler = 0; + + if (dst_x_after_scaler >= htotal) { + dst_x_after_scaler = dst_x_after_scaler - htotal; + dst_y_after_scaler = dst_y_after_scaler + 1; + } + + DTRACE("DLG: %s: htotal = %d", __func__, htotal); + DTRACE( + "DLG: %s: pixel_rate_delay_subtotal = %d", + __func__, + pixel_rate_delay_subtotal); + DTRACE("DLG: %s: dst_x_after_scaler = %d", __func__, dst_x_after_scaler); + DTRACE("DLG: %s: dst_y_after_scaler = %d", __func__, dst_y_after_scaler); + + line_wait = mode_lib->soc.urgent_latency_us; + if (cstate_en) + line_wait = dml_max(mode_lib->soc.sr_enter_plus_exit_time_us, line_wait); + if (pstate_en) + line_wait = dml_max( + mode_lib->soc.dram_clock_change_latency_us + + mode_lib->soc.urgent_latency_us, + line_wait); + line_wait = line_wait / line_time_in_us; + + line_o = (double) dst_y_after_scaler + dst_x_after_scaler / (double) htotal; + line_setup = (double) (vupdate_offset + vupdate_width + vready_offset) / (double) htotal; + line_calc = t_calc_us / line_time_in_us; + + DTRACE( + "DLG: %s: soc.sr_enter_plus_exit_time_us = %3.2f", + __func__, + (double) mode_lib->soc.sr_enter_plus_exit_time_us); + DTRACE( + "DLG: %s: soc.dram_clock_change_latency_us = %3.2f", + __func__, + (double) mode_lib->soc.dram_clock_change_latency_us); + DTRACE( + "DLG: %s: soc.urgent_latency_us = %3.2f", + __func__, + mode_lib->soc.urgent_latency_us); + + DTRACE("DLG: %s: swath_height_l = %d", __func__, swath_height_l); + if (dual_plane) + DTRACE("DLG: %s: swath_height_c = %d", __func__, swath_height_c); + + DTRACE( + "DLG: %s: t_srx_delay_us = %3.2f", + __func__, + (double) dlg_sys_param.t_srx_delay_us); + DTRACE("DLG: %s: line_time_in_us = %3.2f", __func__, (double) line_time_in_us); + DTRACE("DLG: %s: vupdate_offset = %d", __func__, vupdate_offset); + DTRACE("DLG: %s: vupdate_width = %d", __func__, vupdate_width); + DTRACE("DLG: %s: vready_offset = %d", __func__, vready_offset); + DTRACE("DLG: %s: line_time_in_us = %3.2f", __func__, line_time_in_us); + DTRACE("DLG: %s: line_wait = %3.2f", __func__, line_wait); + DTRACE("DLG: %s: line_o = %3.2f", __func__, line_o); + DTRACE("DLG: %s: line_setup = %3.2f", __func__, line_setup); + DTRACE("DLG: %s: line_calc = %3.2f", __func__, line_calc); + + dst_y_prefetch = ((double) min_vblank - 1.0) + - (line_setup + line_calc + line_wait + line_o); + DTRACE("DLG: %s: dst_y_prefetch (before rnd) = %3.2f", __func__, dst_y_prefetch); + ASSERT(dst_y_prefetch >= 2.0); + + dst_y_prefetch = dml_floor(4.0 * (dst_y_prefetch + 0.125)) / 4; + DTRACE("DLG: %s: dst_y_prefetch (after rnd) = %3.2f", __func__, dst_y_prefetch); + + t_pre_us = dst_y_prefetch * line_time_in_us; + vm_bytes = 0; + meta_row_bytes = 0; + + if (dcc_en && vm_en) + vm_bytes = meta_pte_bytes_per_frame_ub_l; + if (dcc_en) + meta_row_bytes = meta_bytes_per_row_ub_l; + + max_num_sw_l = 0; + max_num_sw_c = 0; + max_partial_sw_l = 0; + max_partial_sw_c = 0; + + max_vinit_l = interlaced ? dml_max(vinit_l, vinit_bot_l) : vinit_l; + max_vinit_c = interlaced ? dml_max(vinit_c, vinit_bot_c) : vinit_c; + + get_swath_need(mode_lib, &max_num_sw_l, &max_partial_sw_l, swath_height_l, max_vinit_l); + if (dual_plane) + get_swath_need( + mode_lib, + &max_num_sw_c, + &max_partial_sw_c, + swath_height_c, + max_vinit_c); + + lsw_l = max_num_sw_l * swath_height_l + max_partial_sw_l; + lsw_c = max_num_sw_c * swath_height_c + max_partial_sw_c; + sw_bytes_ub_l = lsw_l * swath_width_ub_l * bytes_per_element_l; + sw_bytes_ub_c = lsw_c * swath_width_ub_c * bytes_per_element_c; + sw_bytes = 0; + dpte_row_bytes = 0; + + if (vm_en) { + if (dual_plane) + dpte_row_bytes = dpte_bytes_per_row_ub_l + dpte_bytes_per_row_ub_c; + else + dpte_row_bytes = dpte_bytes_per_row_ub_l; + } else { + dpte_row_bytes = 0; + } + + if (dual_plane) + sw_bytes = sw_bytes_ub_l + sw_bytes_ub_c; + else + sw_bytes = sw_bytes_ub_l; + + DTRACE("DLG: %s: sw_bytes_ub_l = %d", __func__, sw_bytes_ub_l); + DTRACE("DLG: %s: sw_bytes_ub_c = %d", __func__, sw_bytes_ub_c); + DTRACE("DLG: %s: sw_bytes = %d", __func__, sw_bytes); + DTRACE("DLG: %s: vm_bytes = %d", __func__, vm_bytes); + DTRACE("DLG: %s: meta_row_bytes = %d", __func__, meta_row_bytes); + DTRACE("DLG: %s: dpte_row_bytes = %d", __func__, dpte_row_bytes); + + prefetch_bw = (vm_bytes + 2 * dpte_row_bytes + 2 * meta_row_bytes + sw_bytes) / t_pre_us; + flip_bw = ((vm_bytes + dpte_row_bytes + meta_row_bytes) * dlg_sys_param.total_flip_bw) + / (double) dlg_sys_param.total_flip_bytes; + t_vm_us = line_time_in_us / 4.0; + if (vm_en && dcc_en) { + t_vm_us = dml_max( + dlg_sys_param.t_extra_us, + dml_max((double) vm_bytes / prefetch_bw, t_vm_us)); + + if (iflip_en && !dual_plane) { + t_vm_us = dml_max(mode_lib->soc.urgent_latency_us, t_vm_us); + if (flip_bw > 0.) + t_vm_us = dml_max(vm_bytes / flip_bw, t_vm_us); + } + } + + t_r0_us = dml_max(dlg_sys_param.t_extra_us - t_vm_us, line_time_in_us - t_vm_us); + + if (vm_en || dcc_en) { + t_r0_us = dml_max( + (double) (dpte_row_bytes + meta_row_bytes) / prefetch_bw, + dlg_sys_param.t_extra_us); + t_r0_us = dml_max((double) (line_time_in_us - t_vm_us), t_r0_us); + + if (iflip_en && !dual_plane) { + t_r0_us = dml_max(mode_lib->soc.urgent_latency_us * 2.0, t_r0_us); + if (flip_bw > 0.) + t_r0_us = dml_max( + (dpte_row_bytes + meta_row_bytes) / flip_bw, + t_r0_us); + } + } + + disp_dlg_regs->dst_y_after_scaler = dst_y_after_scaler; /* in terms of line */ + disp_dlg_regs->refcyc_x_after_scaler = dst_x_after_scaler * ref_freq_to_pix_freq; /* in terms of refclk */ + ASSERT(disp_dlg_regs->refcyc_x_after_scaler < (unsigned int) dml_pow(2, 13)); + DTRACE( + "DLG: %s: disp_dlg_regs->dst_y_after_scaler = 0x%0x", + __func__, + disp_dlg_regs->dst_y_after_scaler); + DTRACE( + "DLG: %s: disp_dlg_regs->refcyc_x_after_scaler = 0x%0x", + __func__, + disp_dlg_regs->refcyc_x_after_scaler); + + disp_dlg_regs->dst_y_prefetch = (unsigned int) (dst_y_prefetch * dml_pow(2, 2)); + DTRACE( + "DLG: %s: disp_dlg_regs->dst_y_prefetch = %d", + __func__, + disp_dlg_regs->dst_y_prefetch); + + dst_y_per_vm_vblank = 0.0; + dst_y_per_row_vblank = 0.0; + + dst_y_per_vm_vblank = t_vm_us / line_time_in_us; + dst_y_per_vm_vblank = dml_floor(4.0 * (dst_y_per_vm_vblank + 0.125)) / 4.0; + disp_dlg_regs->dst_y_per_vm_vblank = (unsigned int) (dst_y_per_vm_vblank * dml_pow(2, 2)); + + dst_y_per_row_vblank = t_r0_us / line_time_in_us; + dst_y_per_row_vblank = dml_floor(4.0 * (dst_y_per_row_vblank + 0.125)) / 4.0; + disp_dlg_regs->dst_y_per_row_vblank = (unsigned int) (dst_y_per_row_vblank * dml_pow(2, 2)); + + DTRACE("DLG: %s: lsw_l = %d", __func__, lsw_l); + DTRACE("DLG: %s: lsw_c = %d", __func__, lsw_c); + DTRACE("DLG: %s: dpte_bytes_per_row_ub_l = %d", __func__, dpte_bytes_per_row_ub_l); + DTRACE("DLG: %s: dpte_bytes_per_row_ub_c = %d", __func__, dpte_bytes_per_row_ub_c); + + DTRACE("DLG: %s: prefetch_bw = %3.2f", __func__, prefetch_bw); + DTRACE("DLG: %s: flip_bw = %3.2f", __func__, flip_bw); + DTRACE("DLG: %s: t_pre_us = %3.2f", __func__, t_pre_us); + DTRACE("DLG: %s: t_vm_us = %3.2f", __func__, t_vm_us); + DTRACE("DLG: %s: t_r0_us = %3.2f", __func__, t_r0_us); + DTRACE("DLG: %s: dst_y_per_vm_vblank = %3.2f", __func__, dst_y_per_vm_vblank); + DTRACE("DLG: %s: dst_y_per_row_vblank = %3.2f", __func__, dst_y_per_row_vblank); + DTRACE("DLG: %s: dst_y_prefetch = %3.2f", __func__, dst_y_prefetch); + + min_dst_y_per_vm_vblank = 8.0; + min_dst_y_per_row_vblank = 16.0; + if (htotal <= 75) { + min_vblank = 300; + min_dst_y_per_vm_vblank = 100.0; + min_dst_y_per_row_vblank = 100.0; + } + + ASSERT(dst_y_per_vm_vblank < min_dst_y_per_vm_vblank); + ASSERT(dst_y_per_row_vblank < min_dst_y_per_row_vblank); + + ASSERT(dst_y_prefetch > (dst_y_per_vm_vblank + dst_y_per_row_vblank)); + lsw = dst_y_prefetch - (dst_y_per_vm_vblank + dst_y_per_row_vblank); + + DTRACE("DLG: %s: lsw = %3.2f", __func__, lsw); + + vratio_pre_l = get_vratio_pre( + mode_lib, + max_num_sw_l, + max_partial_sw_l, + swath_height_l, + max_vinit_l, + lsw); + vratio_pre_c = 1.0; + if (dual_plane) + vratio_pre_c = get_vratio_pre( + mode_lib, + max_num_sw_c, + max_partial_sw_c, + swath_height_c, + max_vinit_c, + lsw); + + DTRACE("DLG: %s: vratio_pre_l=%3.2f", __func__, vratio_pre_l); + DTRACE("DLG: %s: vratio_pre_c=%3.2f", __func__, vratio_pre_c); + + ASSERT(vratio_pre_l <= 4.0); + if (vratio_pre_l >= 4.0) + disp_dlg_regs->vratio_prefetch = (unsigned int) dml_pow(2, 21) - 1; + else + disp_dlg_regs->vratio_prefetch = (unsigned int) (vratio_pre_l * dml_pow(2, 19)); + + ASSERT(vratio_pre_c <= 4.0); + if (vratio_pre_c >= 4.0) + disp_dlg_regs->vratio_prefetch_c = (unsigned int) dml_pow(2, 21) - 1; + else + disp_dlg_regs->vratio_prefetch_c = (unsigned int) (vratio_pre_c * dml_pow(2, 19)); + + disp_dlg_regs->refcyc_per_pte_group_vblank_l = + (unsigned int) (dst_y_per_row_vblank * (double) htotal + * ref_freq_to_pix_freq / (double) dpte_groups_per_row_ub_l); + ASSERT(disp_dlg_regs->refcyc_per_pte_group_vblank_l < (unsigned int) dml_pow(2, 13)); + + disp_dlg_regs->refcyc_per_pte_group_vblank_c = + (unsigned int) (dst_y_per_row_vblank * (double) htotal + * ref_freq_to_pix_freq / (double) dpte_groups_per_row_ub_c); + ASSERT(disp_dlg_regs->refcyc_per_pte_group_vblank_c < (unsigned int) dml_pow(2, 13)); + + disp_dlg_regs->refcyc_per_meta_chunk_vblank_l = + (unsigned int) (dst_y_per_row_vblank * (double) htotal + * ref_freq_to_pix_freq / (double) meta_chunks_per_row_ub_l); + ASSERT(disp_dlg_regs->refcyc_per_meta_chunk_vblank_l < (unsigned int) dml_pow(2, 13)); + + disp_dlg_regs->refcyc_per_meta_chunk_vblank_c = + disp_dlg_regs->refcyc_per_meta_chunk_vblank_l;/* dcc for 4:2:0 is not supported in dcn1.0. assigned to be the same as _l for now */ + + /* Active */ + req_per_swath_ub_l = rq_dlg_param.rq_l.req_per_swath_ub; + req_per_swath_ub_c = rq_dlg_param.rq_c.req_per_swath_ub; + meta_row_height_l = rq_dlg_param.rq_l.meta_row_height; + swath_width_pixels_ub_l = 0; + swath_width_pixels_ub_c = 0; + scaler_rec_in_width_l = 0; + scaler_rec_in_width_c = 0; + dpte_row_height_l = rq_dlg_param.rq_l.dpte_row_height; + dpte_row_height_c = rq_dlg_param.rq_c.dpte_row_height; + + disp_dlg_regs->dst_y_per_pte_row_nom_l = (unsigned int) ((double) dpte_row_height_l + / (double) vratio_l * dml_pow(2, 2)); + ASSERT(disp_dlg_regs->dst_y_per_pte_row_nom_l < (unsigned int) dml_pow(2, 17)); + + disp_dlg_regs->dst_y_per_pte_row_nom_c = (unsigned int) ((double) dpte_row_height_c + / (double) vratio_c * dml_pow(2, 2)); + ASSERT(disp_dlg_regs->dst_y_per_pte_row_nom_c < (unsigned int) dml_pow(2, 17)); + + disp_dlg_regs->dst_y_per_meta_row_nom_l = (unsigned int) ((double) meta_row_height_l + / (double) vratio_l * dml_pow(2, 2)); + ASSERT(disp_dlg_regs->dst_y_per_meta_row_nom_l < (unsigned int) dml_pow(2, 17)); + + disp_dlg_regs->dst_y_per_meta_row_nom_c = disp_dlg_regs->dst_y_per_meta_row_nom_l; /* dcc for 4:2:0 is not supported in dcn1.0. assigned to be the same as _l for now */ + + disp_dlg_regs->refcyc_per_pte_group_nom_l = (unsigned int) ((double) dpte_row_height_l + / (double) vratio_l * (double) htotal * ref_freq_to_pix_freq + / (double) dpte_groups_per_row_ub_l); + if (disp_dlg_regs->refcyc_per_pte_group_nom_l >= (unsigned int) dml_pow(2, 23)) + disp_dlg_regs->refcyc_per_pte_group_nom_l = dml_pow(2, 23) - 1; + + disp_dlg_regs->refcyc_per_pte_group_nom_c = (unsigned int) ((double) dpte_row_height_c + / (double) vratio_c * (double) htotal * ref_freq_to_pix_freq + / (double) dpte_groups_per_row_ub_c); + if (disp_dlg_regs->refcyc_per_pte_group_nom_c >= (unsigned int) dml_pow(2, 23)) + disp_dlg_regs->refcyc_per_pte_group_nom_c = dml_pow(2, 23) - 1; + + disp_dlg_regs->refcyc_per_meta_chunk_nom_l = (unsigned int) ((double) meta_row_height_l + / (double) vratio_l * (double) htotal * ref_freq_to_pix_freq + / (double) meta_chunks_per_row_ub_l); + if (disp_dlg_regs->refcyc_per_meta_chunk_nom_l >= (unsigned int) dml_pow(2, 23)) + disp_dlg_regs->refcyc_per_meta_chunk_nom_l = dml_pow(2, 23) - 1; + + if (mode_422) { + swath_width_pixels_ub_l = swath_width_ub_l * 2; /* *2 for 2 pixel per element */ + swath_width_pixels_ub_c = swath_width_ub_c * 2; + } else { + swath_width_pixels_ub_l = swath_width_ub_l * 1; + swath_width_pixels_ub_c = swath_width_ub_c * 1; + } + + hscale_pixel_rate_l = 0.; + hscale_pixel_rate_c = 0.; + min_hratio_fact_l = 1.0; + min_hratio_fact_c = 1.0; + + if (htaps_l <= 1) + min_hratio_fact_l = 2.0; + else if (htaps_l <= 6) { + if ((hratios_l * 2.0) > 4.0) + min_hratio_fact_l = 4.0; + else + min_hratio_fact_l = hratios_l * 2.0; + } else { + if (hratios_l > 4.0) + min_hratio_fact_l = 4.0; + else + min_hratio_fact_l = hratios_l; + } + + hscale_pixel_rate_l = min_hratio_fact_l * dppclk_freq_in_mhz; + + if (htaps_c <= 1) + min_hratio_fact_c = 2.0; + else if (htaps_c <= 6) { + if ((hratios_c * 2.0) > 4.0) + min_hratio_fact_c = 4.0; + else + min_hratio_fact_c = hratios_c * 2.0; + } else { + if (hratios_c > 4.0) + min_hratio_fact_c = 4.0; + else + min_hratio_fact_c = hratios_c; + } + + hscale_pixel_rate_c = min_hratio_fact_c * dppclk_freq_in_mhz; + + refcyc_per_line_delivery_pre_l = 0.; + refcyc_per_line_delivery_pre_c = 0.; + refcyc_per_line_delivery_l = 0.; + refcyc_per_line_delivery_c = 0.; + + refcyc_per_req_delivery_pre_l = 0.; + refcyc_per_req_delivery_pre_c = 0.; + refcyc_per_req_delivery_l = 0.; + refcyc_per_req_delivery_c = 0.; + refcyc_per_req_delivery_pre_cur0 = 0.; + refcyc_per_req_delivery_cur0 = 0.; + + full_recout_width = 0; + if (e2e_pipe_param.pipe.src.is_hsplit) { + if (e2e_pipe_param.pipe.dest.full_recout_width == 0) { + DTRACE("DLG: %s: Warningfull_recout_width not set in hsplit mode", __func__); + full_recout_width = e2e_pipe_param.pipe.dest.recout_width * 2; /* assume half split for dcn1 */ + } else + full_recout_width = e2e_pipe_param.pipe.dest.full_recout_width; + } else + full_recout_width = e2e_pipe_param.pipe.dest.recout_width; + + refcyc_per_line_delivery_pre_l = get_refcyc_per_delivery( + mode_lib, + refclk_freq_in_mhz, + pclk_freq_in_mhz, + full_recout_width, + vratio_pre_l, + hscale_pixel_rate_l, + swath_width_pixels_ub_l, + 1); /* per line */ + + refcyc_per_line_delivery_l = get_refcyc_per_delivery( + mode_lib, + refclk_freq_in_mhz, + pclk_freq_in_mhz, + full_recout_width, + vratio_l, + hscale_pixel_rate_l, + swath_width_pixels_ub_l, + 1); /* per line */ + + DTRACE("DLG: %s: full_recout_width = %d", __func__, full_recout_width); + DTRACE("DLG: %s: hscale_pixel_rate_l = %3.2f", __func__, hscale_pixel_rate_l); + DTRACE( + "DLG: %s: refcyc_per_line_delivery_pre_l = %3.2f", + __func__, + refcyc_per_line_delivery_pre_l); + DTRACE( + "DLG: %s: refcyc_per_line_delivery_l = %3.2f", + __func__, + refcyc_per_line_delivery_l); + + disp_dlg_regs->refcyc_per_line_delivery_pre_l = (unsigned int) dml_floor( + refcyc_per_line_delivery_pre_l); + disp_dlg_regs->refcyc_per_line_delivery_l = (unsigned int) dml_floor( + refcyc_per_line_delivery_l); + ASSERT(disp_dlg_regs->refcyc_per_line_delivery_pre_l < (unsigned int) dml_pow(2, 13)); + ASSERT(disp_dlg_regs->refcyc_per_line_delivery_l < (unsigned int) dml_pow(2, 13)); + + if (dual_plane) { + refcyc_per_line_delivery_pre_c = get_refcyc_per_delivery( + mode_lib, + refclk_freq_in_mhz, + pclk_freq_in_mhz, + full_recout_width, + vratio_pre_c, + hscale_pixel_rate_c, + swath_width_pixels_ub_c, + 1); /* per line */ + + refcyc_per_line_delivery_c = get_refcyc_per_delivery( + mode_lib, + refclk_freq_in_mhz, + pclk_freq_in_mhz, + full_recout_width, + vratio_c, + hscale_pixel_rate_c, + swath_width_pixels_ub_c, + 1); /* per line */ + + DTRACE( + "DLG: %s: refcyc_per_line_delivery_pre_c = %3.2f", + __func__, + refcyc_per_line_delivery_pre_c); + DTRACE( + "DLG: %s: refcyc_per_line_delivery_c = %3.2f", + __func__, + refcyc_per_line_delivery_c); + + disp_dlg_regs->refcyc_per_line_delivery_pre_c = (unsigned int) dml_floor( + refcyc_per_line_delivery_pre_c); + disp_dlg_regs->refcyc_per_line_delivery_c = (unsigned int) dml_floor( + refcyc_per_line_delivery_c); + ASSERT(disp_dlg_regs->refcyc_per_line_delivery_pre_c < (unsigned int) dml_pow(2, 13)); ASSERT(disp_dlg_regs->refcyc_per_line_delivery_c < (unsigned int) dml_pow(2, 13)); + } + disp_dlg_regs->chunk_hdl_adjust_cur0 = 3; + + /* TTU - Luma / Chroma */ + if (access_dir) { /* vertical access */ + scaler_rec_in_width_l = vp_height_l; + scaler_rec_in_width_c = vp_height_c; + } else { + scaler_rec_in_width_l = vp_width_l; + scaler_rec_in_width_c = vp_width_c; + } + + refcyc_per_req_delivery_pre_l = get_refcyc_per_delivery( + mode_lib, + refclk_freq_in_mhz, + pclk_freq_in_mhz, + full_recout_width, + vratio_pre_l, + hscale_pixel_rate_l, + scaler_rec_in_width_l, + req_per_swath_ub_l); /* per req */ + refcyc_per_req_delivery_l = get_refcyc_per_delivery( + mode_lib, + refclk_freq_in_mhz, + pclk_freq_in_mhz, + full_recout_width, + vratio_l, + hscale_pixel_rate_l, + scaler_rec_in_width_l, + req_per_swath_ub_l); /* per req */ + + DTRACE( + "DLG: %s: refcyc_per_req_delivery_pre_l = %3.2f", + __func__, + refcyc_per_req_delivery_pre_l); + DTRACE( + "DLG: %s: refcyc_per_req_delivery_l = %3.2f", + __func__, + refcyc_per_req_delivery_l); + + disp_ttu_regs->refcyc_per_req_delivery_pre_l = (unsigned int) (refcyc_per_req_delivery_pre_l + * dml_pow(2, 10)); + disp_ttu_regs->refcyc_per_req_delivery_l = (unsigned int) (refcyc_per_req_delivery_l + * dml_pow(2, 10)); + + ASSERT(refcyc_per_req_delivery_pre_l < dml_pow(2, 13)); + ASSERT(refcyc_per_req_delivery_l < dml_pow(2, 13)); + + if (dual_plane) { + refcyc_per_req_delivery_pre_c = get_refcyc_per_delivery( + mode_lib, + refclk_freq_in_mhz, + pclk_freq_in_mhz, + full_recout_width, + vratio_pre_c, + hscale_pixel_rate_c, + scaler_rec_in_width_c, + req_per_swath_ub_c); /* per req */ + refcyc_per_req_delivery_c = get_refcyc_per_delivery( + mode_lib, + refclk_freq_in_mhz, + pclk_freq_in_mhz, + full_recout_width, + vratio_c, + hscale_pixel_rate_c, + scaler_rec_in_width_c, + req_per_swath_ub_c); /* per req */ + + DTRACE( + "DLG: %s: refcyc_per_req_delivery_pre_c = %3.2f", + __func__, + refcyc_per_req_delivery_pre_c); + DTRACE( + "DLG: %s: refcyc_per_req_delivery_c = %3.2f", + __func__, + refcyc_per_req_delivery_c); + + disp_ttu_regs->refcyc_per_req_delivery_pre_c = + (unsigned int) (refcyc_per_req_delivery_pre_c * dml_pow(2, 10)); + disp_ttu_regs->refcyc_per_req_delivery_c = (unsigned int) (refcyc_per_req_delivery_c + * dml_pow(2, 10)); + + ASSERT(refcyc_per_req_delivery_pre_c < dml_pow(2, 13)); + ASSERT(refcyc_per_req_delivery_c < dml_pow(2, 13)); + } + + /* TTU - Cursor */ + hratios_cur0 = e2e_pipe_param.pipe.scale_ratio_depth.hscl_ratio; + cur0_src_width = e2e_pipe_param.pipe.src.cur0_src_width; /* cursor source width */ + cur0_bpp = (enum cursor_bpp) e2e_pipe_param.pipe.src.cur0_bpp; + cur0_req_size = 0; + cur0_req_width = 0; + cur0_width_ub = 0.0; + cur0_req_per_width = 0.0; + hactive_cur0 = 0.0; + + ASSERT(cur0_src_width <= 256); + + if (cur0_src_width > 0) { + unsigned int cur0_bit_per_pixel = 0; + + if (cur0_bpp == dm_cur_2bit) { + cur0_req_size = 64; /* byte */ + cur0_bit_per_pixel = 2; + } else { /* 32bit */ + cur0_bit_per_pixel = 32; + if (cur0_src_width >= 1 && cur0_src_width <= 16) + cur0_req_size = 64; + else if (cur0_src_width >= 17 && cur0_src_width <= 31) + cur0_req_size = 128; + else + cur0_req_size = 256; + } + + cur0_req_width = (double) cur0_req_size / ((double) cur0_bit_per_pixel / 8.0); + cur0_width_ub = dml_ceil((double) cur0_src_width / (double) cur0_req_width) + * (double) cur0_req_width; + cur0_req_per_width = cur0_width_ub / (double) cur0_req_width; + hactive_cur0 = (double) cur0_src_width / hratios_cur0; /* FIXME: oswin to think about what to do for cursor */ + + if (vratio_pre_l <= 1.0) { + refcyc_per_req_delivery_pre_cur0 = hactive_cur0 * ref_freq_to_pix_freq + / (double) cur0_req_per_width; + } else { + refcyc_per_req_delivery_pre_cur0 = (double) refclk_freq_in_mhz + * (double) cur0_src_width / hscale_pixel_rate_l + / (double) cur0_req_per_width; + } + + disp_ttu_regs->refcyc_per_req_delivery_pre_cur0 = + (unsigned int) (refcyc_per_req_delivery_pre_cur0 * dml_pow(2, 10)); + ASSERT(refcyc_per_req_delivery_pre_cur0 < dml_pow(2, 13)); + + if (vratio_l <= 1.0) { + refcyc_per_req_delivery_cur0 = hactive_cur0 * ref_freq_to_pix_freq + / (double) cur0_req_per_width; + } else { + refcyc_per_req_delivery_cur0 = (double) refclk_freq_in_mhz + * (double) cur0_src_width / hscale_pixel_rate_l + / (double) cur0_req_per_width; + } + + DTRACE("DLG: %s: cur0_req_width = %d", __func__, cur0_req_width); + DTRACE( + "DLG: %s: cur0_width_ub = %3.2f", + __func__, + cur0_width_ub); + DTRACE( + "DLG: %s: cur0_req_per_width = %3.2f", + __func__, + cur0_req_per_width); + DTRACE( + "DLG: %s: hactive_cur0 = %3.2f", + __func__, + hactive_cur0); + DTRACE( + "DLG: %s: refcyc_per_req_delivery_pre_cur0 = %3.2f", + __func__, + refcyc_per_req_delivery_pre_cur0); + DTRACE( + "DLG: %s: refcyc_per_req_delivery_cur0 = %3.2f", + __func__, + refcyc_per_req_delivery_cur0); + + disp_ttu_regs->refcyc_per_req_delivery_cur0 = + (unsigned int) (refcyc_per_req_delivery_cur0 * dml_pow(2, 10)); + ASSERT(refcyc_per_req_delivery_cur0 < dml_pow(2, 13)); + } else { + disp_ttu_regs->refcyc_per_req_delivery_pre_cur0 = 0; + disp_ttu_regs->refcyc_per_req_delivery_cur0 = 0; + } + + /* TTU - Misc */ + disp_ttu_regs->qos_level_low_wm = 0; + ASSERT(disp_ttu_regs->qos_level_low_wm < dml_pow(2, 14)); + disp_ttu_regs->qos_level_high_wm = (unsigned int) (4.0 * (double) htotal + * ref_freq_to_pix_freq); + ASSERT(disp_ttu_regs->qos_level_high_wm < dml_pow(2, 14)); + + disp_ttu_regs->qos_level_flip = 14; + disp_ttu_regs->qos_level_fixed_l = 8; + disp_ttu_regs->qos_level_fixed_c = 8; + disp_ttu_regs->qos_level_fixed_cur0 = 8; + disp_ttu_regs->qos_ramp_disable_l = 0; + disp_ttu_regs->qos_ramp_disable_c = 0; + disp_ttu_regs->qos_ramp_disable_cur0 = 0; + + disp_ttu_regs->min_ttu_vblank = min_ttu_vblank * refclk_freq_in_mhz; + ASSERT(disp_ttu_regs->min_ttu_vblank < dml_pow(2, 24)); + + print__ttu_regs_st(mode_lib, *disp_ttu_regs); + print__dlg_regs_st(mode_lib, *disp_dlg_regs); +} + +void dml_rq_dlg_get_dlg_reg( + struct display_mode_lib *mode_lib, + struct _vcs_dpi_display_dlg_regs_st *dlg_regs, + struct _vcs_dpi_display_ttu_regs_st *ttu_regs, + struct _vcs_dpi_display_e2e_pipe_params_st *e2e_pipe_param, + const int unsigned num_pipes, + const int unsigned pipe_idx, + const bool cstate_en, + const bool pstate_en, + const bool vm_en, + const bool iflip_en) +{ + struct _vcs_dpi_display_rq_params_st rq_param = {0}; + struct _vcs_dpi_display_dlg_sys_params_st dlg_sys_param = {0}; + struct _vcs_dpi_wm_calc_pipe_params_st *wm_param = mode_lib->wm_param; + struct _vcs_dpi_cstate_pstate_watermarks_st cstate_pstate_wm; + struct _vcs_dpi_display_dlg_prefetch_param_st prefetch_param; + double total_ret_bw; + double total_active_bw; + double total_prefetch_bw; + int unsigned total_flip_bytes; + int unsigned num_planes; + int i; + + memset(wm_param, 0, sizeof(mode_lib->wm_param)); + + /* Get watermark and Tex. */ + DTRACE("DLG: Start calculating system setting related parameters. num_pipes=%d", num_pipes); + num_planes = dml_wm_e2e_to_wm(mode_lib, e2e_pipe_param, num_pipes, wm_param); + + cstate_pstate_wm = dml_wm_cstate_pstate_e2e(mode_lib, e2e_pipe_param, num_pipes); + dlg_sys_param.t_mclk_wm_us = cstate_pstate_wm.pstate_change_us; + dlg_sys_param.t_sr_wm_us = cstate_pstate_wm.cstate_enter_plus_exit_us; + dlg_sys_param.t_urg_wm_us = dml_wm_urgent_e2e(mode_lib, e2e_pipe_param, num_pipes); + dlg_sys_param.t_srx_delay_us = mode_lib->ip.dcfclk_cstate_latency + / dml_wm_dcfclk_deepsleep_mhz_e2e(mode_lib, e2e_pipe_param, num_pipes); + dlg_sys_param.t_extra_us = dml_wm_urgent_extra(mode_lib, wm_param, num_planes); + dlg_sys_param.deepsleep_dcfclk_mhz = dml_wm_dcfclk_deepsleep_mhz_e2e( + mode_lib, + e2e_pipe_param, + num_pipes); + + print__dlg_sys_params_st(mode_lib, dlg_sys_param); + + DTRACE("DLG: Start calculating total prefetch bw. num_planes=%d", num_planes); + total_ret_bw = dml_wm_calc_return_bw(mode_lib, wm_param, num_planes); + total_active_bw = dml_wm_calc_total_data_read_bw(mode_lib, wm_param, num_planes); + total_prefetch_bw = 0.0; + total_flip_bytes = 0; + + for (i = 0; i < num_pipes; i++) { + dml_rq_dlg_get_rq_params(mode_lib, &rq_param, e2e_pipe_param[i].pipe.src); + dml_rq_dlg_get_dlg_params_prefetch( + mode_lib, + &prefetch_param, + rq_param.dlg, + dlg_sys_param, + e2e_pipe_param[i], + cstate_en, + pstate_en, + vm_en); + total_prefetch_bw += prefetch_param.prefetch_bw; + total_flip_bytes += prefetch_param.flip_bytes; + DTRACE( + "DLG: pipe=%d, total_prefetch_bw=%3.2f total_flip_bytes=%d", + i, + total_prefetch_bw, + total_flip_bytes); + } + + dlg_sys_param.total_flip_bw = total_ret_bw - dml_max(total_active_bw, total_prefetch_bw); + + DTRACE("DLG: Done calculating total prefetch bw"); + DTRACE("DLG: num_pipes = %d", num_pipes); + DTRACE("DLG: total_ret_bw = %3.2f", total_ret_bw); + DTRACE("DLG: total_active_bw = %3.2f", total_active_bw); + DTRACE("DLG: total_prefetch_bw = %3.2f", total_prefetch_bw); + DTRACE("DLG: total_flip_bw = %3.2f", dlg_sys_param.total_flip_bw); + + if (dlg_sys_param.total_flip_bw < 0.0 && iflip_en) { + DTRACE("WARNING_DLG Insufficient bw for immediate flip!"); + dlg_sys_param.total_flip_bw = 0; + } + + dlg_sys_param.total_flip_bytes = total_flip_bytes; + DTRACE("DLG: total_flip_bytes = %d", dlg_sys_param.total_flip_bytes); + DTRACE("DLG: Done calculating system setting related parameters."); + + /* system parameter calculation done */ + + DTRACE("DLG: Calculation for pipe[%d] start", pipe_idx); + dml_rq_dlg_get_rq_params(mode_lib, &rq_param, e2e_pipe_param[pipe_idx].pipe.src); + dml_rq_dlg_get_dlg_params( + mode_lib, + dlg_regs, + ttu_regs, + rq_param.dlg, + dlg_sys_param, + e2e_pipe_param[pipe_idx], + cstate_en, + pstate_en, + vm_en, + iflip_en); + DTRACE("DLG: Calculation for pipe[%d] end", pipe_idx); +} + +void dml_rq_dlg_get_arb_params( + struct display_mode_lib *mode_lib, + struct _vcs_dpi_display_arb_params_st *arb_param) +{ + memset(arb_param, 0, sizeof(*arb_param)); + arb_param->max_req_outstanding = 256; + arb_param->min_req_outstanding = 68; + arb_param->sat_level_us = 60; +} diff --git a/drivers/gpu/drm/amd/display/dc/dml/display_rq_dlg_calc.h b/drivers/gpu/drm/amd/display/dc/dml/display_rq_dlg_calc.h new file mode 100644 index 000000000000..e63b13fb2887 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/dml/display_rq_dlg_calc.h @@ -0,0 +1,139 @@ +/* + * Copyright 2017 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 __DISPLAY_RQ_DLG_CALC_H__ +#define __DISPLAY_RQ_DLG_CALC_H__ + +#include "dml_common_defs.h" +#include "display_rq_dlg_helpers.h" + +struct display_mode_lib; + +void extract_rq_regs( + struct display_mode_lib *mode_lib, + struct _vcs_dpi_display_rq_regs_st *rq_regs, + const struct _vcs_dpi_display_rq_params_st rq_param); +/* Function: dml_rq_dlg_get_rq_params + * Calculate requestor related parameters that register definition agnostic + * (i.e. this layer does try to separate real values from register defintion) + * Input: + * pipe_src_param - pipe source configuration (e.g. vp, pitch, etc.) + * Output: + * rq_param - values that can be used to setup RQ (e.g. swath_height, plane1_addr, etc.) + */ +void dml_rq_dlg_get_rq_params( + struct display_mode_lib *mode_lib, + struct _vcs_dpi_display_rq_params_st *rq_param, + const struct _vcs_dpi_display_pipe_source_params_st pipe_src_param); + +/* Function: dml_rq_dlg_get_rq_reg + * Main entry point for test to get the register values out of this DML class. + * This function calls and fucntions to calculate + * and then populate the rq_regs struct + * Input: + * pipe_src_param - pipe source configuration (e.g. vp, pitch, etc.) + * Output: + * rq_regs - struct that holds all the RQ registers field value. + * See also: + */ +void dml_rq_dlg_get_rq_reg( + struct display_mode_lib *mode_lib, + struct _vcs_dpi_display_rq_regs_st *rq_regs, + const struct _vcs_dpi_display_pipe_source_params_st pipe_src_param); + +/* Function: dml_rq_dlg_get_dlg_params + * Calculate deadline related parameters + */ +void dml_rq_dlg_get_dlg_params( + struct display_mode_lib *mode_lib, + struct _vcs_dpi_display_dlg_regs_st *dlg_regs, + struct _vcs_dpi_display_ttu_regs_st *ttu_regs, + const struct _vcs_dpi_display_rq_dlg_params_st rq_dlg_param, + const struct _vcs_dpi_display_dlg_sys_params_st dlg_sys_param, + const struct _vcs_dpi_display_e2e_pipe_params_st e2e_pipe_param, + const bool cstate_en, + const bool pstate_en, + const bool vm_en, + const bool iflip_en); + +/* Function: dml_rq_dlg_get_dlg_param_prefetch + * For flip_bw programming guide change, now dml needs to calculate the flip_bytes and prefetch_bw + * for ALL pipes and use this info to calculate the prefetch programming. + * Output: prefetch_param.prefetch_bw and flip_bytes + */ +void dml_rq_dlg_get_dlg_params_prefetch( + struct display_mode_lib *mode_lib, + struct _vcs_dpi_display_dlg_prefetch_param_st *prefetch_param, + struct _vcs_dpi_display_rq_dlg_params_st rq_dlg_param, + struct _vcs_dpi_display_dlg_sys_params_st dlg_sys_param, + struct _vcs_dpi_display_e2e_pipe_params_st e2e_pipe_param, + const bool cstate_en, + const bool pstate_en, + const bool vm_en); + +/* Function: dml_rq_dlg_get_dlg_reg + * Calculate and return DLG and TTU register struct given the system setting + * Output: + * dlg_regs - output DLG register struct + * ttu_regs - output DLG TTU register struct + * Input: + * e2e_pipe_param - "compacted" array of e2e pipe param struct + * num_pipes - num of active "pipe" or "route" + * pipe_idx - index that identifies the e2e_pipe_param that corresponding to this dlg + * cstate - 0: when calculate min_ttu_vblank it is assumed cstate is not required. 1: Normal mode, cstate is considered. + * Added for legacy or unrealistic timing tests. + */ +void dml_rq_dlg_get_dlg_reg( + struct display_mode_lib *mode_lib, + struct _vcs_dpi_display_dlg_regs_st *dlg_regs, + struct _vcs_dpi_display_ttu_regs_st *ttu_regs, + struct _vcs_dpi_display_e2e_pipe_params_st *e2e_pipe_param, + const unsigned int num_pipes, + const unsigned int pipe_idx, + const bool cstate_en, + const bool pstate_en, + const bool vm_en, + const bool iflip_en); + +/* Function: dml_rq_dlg_get_row_heights + * Calculate dpte and meta row heights + */ +void dml_rq_dlg_get_row_heights( + struct display_mode_lib *mode_lib, + unsigned int *o_dpte_row_height, + unsigned int *o_meta_row_height, + unsigned int vp_width, + unsigned int data_pitch, + int source_format, + int tiling, + int macro_tile_size, + int source_scan, + int is_chroma); + +/* Function: dml_rq_dlg_get_arb_params */ +void dml_rq_dlg_get_arb_params( + struct display_mode_lib *mode_lib, + struct _vcs_dpi_display_arb_params_st *arb_param); + +#endif diff --git a/drivers/gpu/drm/amd/display/dc/dml/display_rq_dlg_helpers.c b/drivers/gpu/drm/amd/display/dc/dml/display_rq_dlg_helpers.c new file mode 100644 index 000000000000..3dc11366cd36 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/dml/display_rq_dlg_helpers.c @@ -0,0 +1,320 @@ +/* + * Copyright 2017 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 "display_rq_dlg_helpers.h" + +void print__rq_params_st( + struct display_mode_lib *mode_lib, + struct _vcs_dpi_display_rq_params_st rq_param) +{ + DTRACE("RQ_DLG_CALC: *************************** "); + DTRACE("RQ_DLG_CALC: DISPLAY_RQ_PARAM_ST"); + DTRACE("RQ_DLG_CALC: "); + print__data_rq_sizing_params_st(mode_lib, rq_param.sizing.rq_l); + DTRACE("RQ_DLG_CALC: === "); + print__data_rq_sizing_params_st(mode_lib, rq_param.sizing.rq_c); + + DTRACE("RQ_DLG_CALC: "); + print__data_rq_dlg_params_st(mode_lib, rq_param.dlg.rq_l); + DTRACE("RQ_DLG_CALC: "); + print__data_rq_dlg_params_st(mode_lib, rq_param.dlg.rq_c); + + DTRACE("RQ_DLG_CALC: "); + print__data_rq_misc_params_st(mode_lib, rq_param.misc.rq_l); + DTRACE("RQ_DLG_CALC: "); + print__data_rq_misc_params_st(mode_lib, rq_param.misc.rq_c); + DTRACE("RQ_DLG_CALC: *************************** "); +} + +void print__data_rq_sizing_params_st( + struct display_mode_lib *mode_lib, + struct _vcs_dpi_display_data_rq_sizing_params_st rq_sizing) +{ + DTRACE("RQ_DLG_CALC: ===================================== "); + DTRACE("RQ_DLG_CALC: DISPLAY_DATA_RQ_SIZING_PARAM_ST"); + DTRACE("RQ_DLG_CALC: chunk_bytes = %0d", rq_sizing.chunk_bytes); + DTRACE("RQ_DLG_CALC: min_chunk_bytes = %0d", rq_sizing.min_chunk_bytes); + DTRACE("RQ_DLG_CALC: meta_chunk_bytes = %0d", rq_sizing.meta_chunk_bytes); + DTRACE("RQ_DLG_CALC: min_meta_chunk_bytes = %0d", rq_sizing.min_meta_chunk_bytes); + DTRACE("RQ_DLG_CALC: mpte_group_bytes = %0d", rq_sizing.mpte_group_bytes); + DTRACE("RQ_DLG_CALC: dpte_group_bytes = %0d", rq_sizing.dpte_group_bytes); + DTRACE("RQ_DLG_CALC: ===================================== "); +} + +void print__data_rq_dlg_params_st( + struct display_mode_lib *mode_lib, + struct _vcs_dpi_display_data_rq_dlg_params_st rq_dlg_param) +{ + DTRACE("RQ_DLG_CALC: ===================================== "); + DTRACE("RQ_DLG_CALC: DISPLAY_DATA_RQ_DLG_PARAM_ST"); + DTRACE("RQ_DLG_CALC: swath_width_ub = %0d", rq_dlg_param.swath_width_ub); + DTRACE("RQ_DLG_CALC: swath_height = %0d", rq_dlg_param.swath_height); + DTRACE("RQ_DLG_CALC: req_per_swath_ub = %0d", rq_dlg_param.req_per_swath_ub); + DTRACE( + "RQ_DLG_CALC: meta_pte_bytes_per_frame_ub = %0d", + rq_dlg_param.meta_pte_bytes_per_frame_ub); + DTRACE( + "RQ_DLG_CALC: dpte_req_per_row_ub = %0d", + rq_dlg_param.dpte_req_per_row_ub); + DTRACE( + "RQ_DLG_CALC: dpte_groups_per_row_ub = %0d", + rq_dlg_param.dpte_groups_per_row_ub); + DTRACE("RQ_DLG_CALC: dpte_row_height = %0d", rq_dlg_param.dpte_row_height); + DTRACE( + "RQ_DLG_CALC: dpte_bytes_per_row_ub = %0d", + rq_dlg_param.dpte_bytes_per_row_ub); + DTRACE( + "RQ_DLG_CALC: meta_chunks_per_row_ub = %0d", + rq_dlg_param.meta_chunks_per_row_ub); + DTRACE( + "RQ_DLG_CALC: meta_req_per_row_ub = %0d", + rq_dlg_param.meta_req_per_row_ub); + DTRACE("RQ_DLG_CALC: meta_row_height = %0d", rq_dlg_param.meta_row_height); + DTRACE( + "RQ_DLG_CALC: meta_bytes_per_row_ub = %0d", + rq_dlg_param.meta_bytes_per_row_ub); + DTRACE("RQ_DLG_CALC: ===================================== "); +} + +void print__data_rq_misc_params_st( + struct display_mode_lib *mode_lib, + struct _vcs_dpi_display_data_rq_misc_params_st rq_misc_param) +{ + DTRACE("RQ_DLG_CALC: ===================================== "); + DTRACE("RQ_DLG_CALC: DISPLAY_DATA_RQ_MISC_PARAM_ST"); + DTRACE("RQ_DLG_CALC: full_swath_bytes = %0d", rq_misc_param.full_swath_bytes); + DTRACE("RQ_DLG_CALC: stored_swath_bytes = %0d", rq_misc_param.stored_swath_bytes); + DTRACE("RQ_DLG_CALC: blk256_width = %0d", rq_misc_param.blk256_width); + DTRACE("RQ_DLG_CALC: blk256_height = %0d", rq_misc_param.blk256_height); + DTRACE("RQ_DLG_CALC: req_width = %0d", rq_misc_param.req_width); + DTRACE("RQ_DLG_CALC: req_height = %0d", rq_misc_param.req_height); + DTRACE("RQ_DLG_CALC: ===================================== "); +} + +void print__rq_dlg_params_st( + struct display_mode_lib *mode_lib, + struct _vcs_dpi_display_rq_dlg_params_st rq_dlg_param) +{ + DTRACE("RQ_DLG_CALC: ===================================== "); + DTRACE("RQ_DLG_CALC: DISPLAY_RQ_DLG_PARAM_ST"); + DTRACE("RQ_DLG_CALC: "); + print__data_rq_dlg_params_st(mode_lib, rq_dlg_param.rq_l); + DTRACE("RQ_DLG_CALC: "); + print__data_rq_dlg_params_st(mode_lib, rq_dlg_param.rq_c); + DTRACE("RQ_DLG_CALC: ===================================== "); +} + +void print__dlg_sys_params_st( + struct display_mode_lib *mode_lib, + struct _vcs_dpi_display_dlg_sys_params_st dlg_sys_param) +{ + DTRACE("RQ_DLG_CALC: ===================================== "); + DTRACE("RQ_DLG_CALC: DISPLAY_RQ_DLG_PARAM_ST"); + DTRACE("RQ_DLG_CALC: t_mclk_wm_us = %3.2f", dlg_sys_param.t_mclk_wm_us); + DTRACE("RQ_DLG_CALC: t_urg_wm_us = %3.2f", dlg_sys_param.t_urg_wm_us); + DTRACE("RQ_DLG_CALC: t_sr_wm_us = %3.2f", dlg_sys_param.t_sr_wm_us); + DTRACE("RQ_DLG_CALC: t_extra_us = %3.2f", dlg_sys_param.t_extra_us); + DTRACE("RQ_DLG_CALC: t_srx_delay_us = %3.2f", dlg_sys_param.t_srx_delay_us); + DTRACE("RQ_DLG_CALC: deepsleep_dcfclk_mhz = %3.2f", dlg_sys_param.deepsleep_dcfclk_mhz); + DTRACE("RQ_DLG_CALC: ===================================== "); +} + +void print__data_rq_regs_st( + struct display_mode_lib *mode_lib, + struct _vcs_dpi_display_data_rq_regs_st rq_regs) +{ + DTRACE("RQ_DLG_CALC: ===================================== "); + DTRACE("RQ_DLG_CALC: DISPLAY_DATA_RQ_REGS_ST"); + DTRACE("RQ_DLG_CALC: chunk_size = 0x%0x", rq_regs.chunk_size); + DTRACE("RQ_DLG_CALC: min_chunk_size = 0x%0x", rq_regs.min_chunk_size); + DTRACE("RQ_DLG_CALC: meta_chunk_size = 0x%0x", rq_regs.meta_chunk_size); + DTRACE("RQ_DLG_CALC: min_meta_chunk_size = 0x%0x", rq_regs.min_meta_chunk_size); + DTRACE("RQ_DLG_CALC: dpte_group_size = 0x%0x", rq_regs.dpte_group_size); + DTRACE("RQ_DLG_CALC: mpte_group_size = 0x%0x", rq_regs.mpte_group_size); + DTRACE("RQ_DLG_CALC: swath_height = 0x%0x", rq_regs.swath_height); + DTRACE("RQ_DLG_CALC: pte_row_height_linear = 0x%0x", rq_regs.pte_row_height_linear); + DTRACE("RQ_DLG_CALC: ===================================== "); +} + +void print__rq_regs_st( + struct display_mode_lib *mode_lib, + struct _vcs_dpi_display_rq_regs_st rq_regs) +{ + DTRACE("RQ_DLG_CALC: ===================================== "); + DTRACE("RQ_DLG_CALC: DISPLAY_RQ_REGS_ST"); + DTRACE("RQ_DLG_CALC: "); + print__data_rq_regs_st(mode_lib, rq_regs.rq_regs_l); + DTRACE("RQ_DLG_CALC: "); + print__data_rq_regs_st(mode_lib, rq_regs.rq_regs_c); + DTRACE("RQ_DLG_CALC: drq_expansion_mode = 0x%0x", rq_regs.drq_expansion_mode); + DTRACE("RQ_DLG_CALC: prq_expansion_mode = 0x%0x", rq_regs.prq_expansion_mode); + DTRACE("RQ_DLG_CALC: mrq_expansion_mode = 0x%0x", rq_regs.mrq_expansion_mode); + DTRACE("RQ_DLG_CALC: crq_expansion_mode = 0x%0x", rq_regs.crq_expansion_mode); + DTRACE("RQ_DLG_CALC: plane1_base_address = 0x%0x", rq_regs.plane1_base_address); + DTRACE("RQ_DLG_CALC: ===================================== "); +} + +void print__dlg_regs_st( + struct display_mode_lib *mode_lib, + struct _vcs_dpi_display_dlg_regs_st dlg_regs) +{ + DTRACE("RQ_DLG_CALC: ===================================== "); + DTRACE("RQ_DLG_CALC: DISPLAY_DLG_REGS_ST "); + DTRACE( + "RQ_DLG_CALC: refcyc_h_blank_end = 0x%0x", + dlg_regs.refcyc_h_blank_end); + DTRACE("RQ_DLG_CALC: dlg_vblank_end = 0x%0x", dlg_regs.dlg_vblank_end); + DTRACE( + "RQ_DLG_CALC: min_dst_y_next_start = 0x%0x", + dlg_regs.min_dst_y_next_start); + DTRACE( + "RQ_DLG_CALC: refcyc_per_htotal = 0x%0x", + dlg_regs.refcyc_per_htotal); + DTRACE( + "RQ_DLG_CALC: refcyc_x_after_scaler = 0x%0x", + dlg_regs.refcyc_x_after_scaler); + DTRACE( + "RQ_DLG_CALC: dst_y_after_scaler = 0x%0x", + dlg_regs.dst_y_after_scaler); + DTRACE("RQ_DLG_CALC: dst_y_prefetch = 0x%0x", dlg_regs.dst_y_prefetch); + DTRACE( + "RQ_DLG_CALC: dst_y_per_vm_vblank = 0x%0x", + dlg_regs.dst_y_per_vm_vblank); + DTRACE( + "RQ_DLG_CALC: dst_y_per_row_vblank = 0x%0x", + dlg_regs.dst_y_per_row_vblank); + DTRACE( + "RQ_DLG_CALC: ref_freq_to_pix_freq = 0x%0x", + dlg_regs.ref_freq_to_pix_freq); + DTRACE("RQ_DLG_CALC: vratio_prefetch = 0x%0x", dlg_regs.vratio_prefetch); + DTRACE( + "RQ_DLG_CALC: vratio_prefetch_c = 0x%0x", + dlg_regs.vratio_prefetch_c); + DTRACE( + "RQ_DLG_CALC: refcyc_per_pte_group_vblank_l = 0x%0x", + dlg_regs.refcyc_per_pte_group_vblank_l); + DTRACE( + "RQ_DLG_CALC: refcyc_per_pte_group_vblank_c = 0x%0x", + dlg_regs.refcyc_per_pte_group_vblank_c); + DTRACE( + "RQ_DLG_CALC: refcyc_per_meta_chunk_vblank_l = 0x%0x", + dlg_regs.refcyc_per_meta_chunk_vblank_l); + DTRACE( + "RQ_DLG_CALC: refcyc_per_meta_chunk_vblank_c = 0x%0x", + dlg_regs.refcyc_per_meta_chunk_vblank_c); + DTRACE( + "RQ_DLG_CALC: dst_y_per_pte_row_nom_l = 0x%0x", + dlg_regs.dst_y_per_pte_row_nom_l); + DTRACE( + "RQ_DLG_CALC: dst_y_per_pte_row_nom_c = 0x%0x", + dlg_regs.dst_y_per_pte_row_nom_c); + DTRACE( + "RQ_DLG_CALC: refcyc_per_pte_group_nom_l = 0x%0x", + dlg_regs.refcyc_per_pte_group_nom_l); + DTRACE( + "RQ_DLG_CALC: refcyc_per_pte_group_nom_c = 0x%0x", + dlg_regs.refcyc_per_pte_group_nom_c); + DTRACE( + "RQ_DLG_CALC: dst_y_per_meta_row_nom_l = 0x%0x", + dlg_regs.dst_y_per_meta_row_nom_l); + DTRACE( + "RQ_DLG_CALC: dst_y_per_meta_row_nom_c = 0x%0x", + dlg_regs.dst_y_per_meta_row_nom_c); + DTRACE( + "RQ_DLG_CALC: refcyc_per_meta_chunk_nom_l = 0x%0x", + dlg_regs.refcyc_per_meta_chunk_nom_l); + DTRACE( + "RQ_DLG_CALC: refcyc_per_meta_chunk_nom_c = 0x%0x", + dlg_regs.refcyc_per_meta_chunk_nom_c); + DTRACE( + "RQ_DLG_CALC: refcyc_per_line_delivery_pre_l = 0x%0x", + dlg_regs.refcyc_per_line_delivery_pre_l); + DTRACE( + "RQ_DLG_CALC: refcyc_per_line_delivery_pre_c = 0x%0x", + dlg_regs.refcyc_per_line_delivery_pre_c); + DTRACE( + "RQ_DLG_CALC: refcyc_per_line_delivery_l = 0x%0x", + dlg_regs.refcyc_per_line_delivery_l); + DTRACE( + "RQ_DLG_CALC: refcyc_per_line_delivery_c = 0x%0x", + dlg_regs.refcyc_per_line_delivery_c); + DTRACE( + "RQ_DLG_CALC: chunk_hdl_adjust_cur0 = 0x%0x", + dlg_regs.chunk_hdl_adjust_cur0); + DTRACE("RQ_DLG_CALC: ===================================== "); +} + +void print__ttu_regs_st( + struct display_mode_lib *mode_lib, + struct _vcs_dpi_display_ttu_regs_st ttu_regs) +{ + DTRACE("RQ_DLG_CALC: ===================================== "); + DTRACE("RQ_DLG_CALC: DISPLAY_TTU_REGS_ST "); + DTRACE( + "RQ_DLG_CALC: qos_level_low_wm = 0x%0x", + ttu_regs.qos_level_low_wm); + DTRACE( + "RQ_DLG_CALC: qos_level_high_wm = 0x%0x", + ttu_regs.qos_level_high_wm); + DTRACE("RQ_DLG_CALC: min_ttu_vblank = 0x%0x", ttu_regs.min_ttu_vblank); + DTRACE("RQ_DLG_CALC: qos_level_flip = 0x%0x", ttu_regs.qos_level_flip); + DTRACE( + "RQ_DLG_CALC: refcyc_per_req_delivery_pre_l = 0x%0x", + ttu_regs.refcyc_per_req_delivery_pre_l); + DTRACE( + "RQ_DLG_CALC: refcyc_per_req_delivery_l = 0x%0x", + ttu_regs.refcyc_per_req_delivery_l); + DTRACE( + "RQ_DLG_CALC: refcyc_per_req_delivery_pre_c = 0x%0x", + ttu_regs.refcyc_per_req_delivery_pre_c); + DTRACE( + "RQ_DLG_CALC: refcyc_per_req_delivery_c = 0x%0x", + ttu_regs.refcyc_per_req_delivery_c); + DTRACE( + "RQ_DLG_CALC: refcyc_per_req_delivery_cur0 = 0x%0x", + ttu_regs.refcyc_per_req_delivery_cur0); + DTRACE( + "RQ_DLG_CALC: refcyc_per_req_delivery_pre_cur0 = 0x%0x", + ttu_regs.refcyc_per_req_delivery_pre_cur0); + DTRACE( + "RQ_DLG_CALC: qos_level_fixed_l = 0x%0x", + ttu_regs.qos_level_fixed_l); + DTRACE( + "RQ_DLG_CALC: qos_ramp_disable_l = 0x%0x", + ttu_regs.qos_ramp_disable_l); + DTRACE( + "RQ_DLG_CALC: qos_level_fixed_c = 0x%0x", + ttu_regs.qos_level_fixed_c); + DTRACE( + "RQ_DLG_CALC: qos_ramp_disable_c = 0x%0x", + ttu_regs.qos_ramp_disable_c); + DTRACE( + "RQ_DLG_CALC: qos_level_fixed_cur0 = 0x%0x", + ttu_regs.qos_level_fixed_cur0); + DTRACE( + "RQ_DLG_CALC: qos_ramp_disable_cur0 = 0x%0x", + ttu_regs.qos_ramp_disable_cur0); + DTRACE("RQ_DLG_CALC: ===================================== "); +} diff --git a/drivers/gpu/drm/amd/display/dc/dml/display_rq_dlg_helpers.h b/drivers/gpu/drm/amd/display/dc/dml/display_rq_dlg_helpers.h new file mode 100644 index 000000000000..7403ccaf637b --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/dml/display_rq_dlg_helpers.h @@ -0,0 +1,66 @@ +/* + * Copyright 2017 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 __DISPLAY_RQ_DLG_HELPERS_H__ +#define __DISPLAY_RQ_DLG_HELPERS_H__ + +#include "dml_common_defs.h" +#include "display_mode_lib.h" + +/* Function: Printer functions + * Print various struct + */ +void print__rq_params_st( + struct display_mode_lib *mode_lib, + struct _vcs_dpi_display_rq_params_st rq_param); +void print__data_rq_sizing_params_st( + struct display_mode_lib *mode_lib, + struct _vcs_dpi_display_data_rq_sizing_params_st rq_sizing); +void print__data_rq_dlg_params_st( + struct display_mode_lib *mode_lib, + struct _vcs_dpi_display_data_rq_dlg_params_st rq_dlg_param); +void print__data_rq_misc_params_st( + struct display_mode_lib *mode_lib, + struct _vcs_dpi_display_data_rq_misc_params_st rq_misc_param); +void print__rq_dlg_params_st( + struct display_mode_lib *mode_lib, + struct _vcs_dpi_display_rq_dlg_params_st rq_dlg_param); +void print__dlg_sys_params_st( + struct display_mode_lib *mode_lib, + struct _vcs_dpi_display_dlg_sys_params_st dlg_sys_param); + +void print__data_rq_regs_st( + struct display_mode_lib *mode_lib, + struct _vcs_dpi_display_data_rq_regs_st data_rq_regs); +void print__rq_regs_st( + struct display_mode_lib *mode_lib, + struct _vcs_dpi_display_rq_regs_st rq_regs); +void print__dlg_regs_st( + struct display_mode_lib *mode_lib, + struct _vcs_dpi_display_dlg_regs_st dlg_regs); +void print__ttu_regs_st( + struct display_mode_lib *mode_lib, + struct _vcs_dpi_display_ttu_regs_st ttu_regs); + +#endif diff --git a/drivers/gpu/drm/amd/display/dc/dml/display_watermark.c b/drivers/gpu/drm/amd/display/dc/dml/display_watermark.c new file mode 100644 index 000000000000..390f09391433 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/dml/display_watermark.c @@ -0,0 +1,1281 @@ +/* + * Copyright 2017 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 "display_watermark.h" +#include "display_mode_lib.h" + +static void get_bytes_per_pixel( + enum source_format_class format, + struct _vcs_dpi_wm_calc_pipe_params_st *plane) +{ + switch (format) { + case dm_444_64: + plane->bytes_per_pixel_y = 8.0; + plane->bytes_per_pixel_c = 0.0; + break; + case dm_444_32: + plane->bytes_per_pixel_y = 4.0; + plane->bytes_per_pixel_c = 0.0; + break; + case dm_444_16: + plane->bytes_per_pixel_y = 2.0; + plane->bytes_per_pixel_c = 0.0; + break; + case dm_422_10: + plane->bytes_per_pixel_y = 4.0; + plane->bytes_per_pixel_c = 0.0; + break; + case dm_422_8: + plane->bytes_per_pixel_y = 2.0; + plane->bytes_per_pixel_c = 0.0; + break; + case dm_420_8: + plane->bytes_per_pixel_y = 1.0; + plane->bytes_per_pixel_c = 2.0; + break; + case dm_420_10: + plane->bytes_per_pixel_y = 4.0 / 3; + plane->bytes_per_pixel_c = 8.0 / 3; + break; + default: + BREAK_TO_DEBUGGER(); /* invalid format in get_bytes_per_pixel */ + } +} + +static unsigned int get_swath_width_y( + struct _vcs_dpi_display_pipe_source_params_st *src_param, + unsigned int num_dpp) +{ + unsigned int val; + + /* note that we don't divide by num_dpp here because we have an interface which has already split + * any viewports + */ + if (src_param->source_scan == dm_horz) { + val = src_param->viewport_width; + } else { + val = src_param->viewport_height; + } + + return val; +} + +static void get_swath_height( + struct display_mode_lib *mode_lib, + struct _vcs_dpi_display_pipe_source_params_st *src_param, + struct _vcs_dpi_wm_calc_pipe_params_st *plane, + unsigned int swath_width_y) +{ + double buffer_width; + + if (src_param->source_format == dm_444_64 || src_param->source_format == dm_444_32 + || src_param->source_format == dm_444_16) { + if (src_param->sw_mode == dm_sw_linear) { + plane->swath_height_y = 1; + } else if (src_param->source_format == dm_444_64) { + plane->swath_height_y = 4; + } else { + plane->swath_height_y = 8; + } + + if (src_param->source_scan != dm_horz) { + plane->swath_height_y = 256 / (unsigned int) plane->bytes_per_pixel_y + / plane->swath_height_y; + } + + plane->swath_height_c = 0; + + } else { + if (src_param->sw_mode == dm_sw_linear) { + plane->swath_height_y = 1; + plane->swath_height_c = 1; + } else if (src_param->source_format == dm_420_8) { + plane->swath_height_y = 16; + plane->swath_height_c = 8; + } else { + plane->swath_height_y = 8; + plane->swath_height_c = 8; + } + + if (src_param->source_scan != dm_horz) { + double bytes_per_pixel_c_ceil; + + plane->swath_height_y = 256 / dml_ceil(plane->bytes_per_pixel_y) + / plane->swath_height_y; + + bytes_per_pixel_c_ceil = dml_ceil_2(plane->bytes_per_pixel_c); + + plane->swath_height_c = 256 / bytes_per_pixel_c_ceil + / plane->swath_height_c; + } + } + + /* use swath height min if buffer isn't big enough */ + + buffer_width = ((double) mode_lib->ip.det_buffer_size_kbytes * 1024.0 / 2.0) + / (plane->bytes_per_pixel_y * (double) plane->swath_height_y + + (plane->bytes_per_pixel_c / 2.0 + * (double) plane->swath_height_c)); + + if ((double) swath_width_y <= buffer_width) { + /* do nothing, just keep code structure from Gabes vba */ + } else { + /* substitute swath height with swath height min */ + if (src_param->source_format == dm_444_64 || src_param->source_format == dm_444_32 + || src_param->source_format == dm_444_16) { + if ((src_param->sw_mode == dm_sw_linear) + || (src_param->source_format == dm_444_64 + && (src_param->sw_mode == dm_sw_4kb_s + || src_param->sw_mode + == dm_sw_4kb_s_x + || src_param->sw_mode + == dm_sw_64kb_s + || src_param->sw_mode + == dm_sw_64kb_s_t + || src_param->sw_mode + == dm_sw_64kb_s_x + || src_param->sw_mode + == dm_sw_var_s + || src_param->sw_mode + == dm_sw_var_s_x) + && src_param->source_scan == dm_horz)) { + /* do nothing, just keep code structure from Gabes vba */ + } else { + plane->swath_height_y = plane->swath_height_y / 2; + } + } else { + if (src_param->sw_mode == dm_sw_linear) { + /* do nothing, just keep code structure from Gabes vba */ + } else if (src_param->source_format == dm_420_8 + && src_param->source_scan == dm_horz) { + plane->swath_height_y = plane->swath_height_y / 2; + } else if (src_param->source_format == dm_420_10 + && src_param->source_scan == dm_horz) { + plane->swath_height_c = plane->swath_height_c / 2; + } + } + } + + if (plane->swath_height_c == 0) { + plane->det_buffer_size_y = mode_lib->ip.det_buffer_size_kbytes * 1024.0; + } else if (plane->swath_height_c <= plane->swath_height_y) { + plane->det_buffer_size_y = mode_lib->ip.det_buffer_size_kbytes * 1024.0 / 2.0; + } else { + plane->det_buffer_size_y = mode_lib->ip.det_buffer_size_kbytes * 1024.0 * 2.0 / 3.0; + } +} + +static void calc_display_pipe_line_delivery_time( + struct display_mode_lib *mode_lib, + struct _vcs_dpi_wm_calc_pipe_params_st *planes, + unsigned int num_planes) +{ + unsigned int i; + + for (i = 0; i < num_planes; i++) { + if (planes[i].v_ratio <= 1.0) { + planes[i].display_pipe_line_delivery_time = planes[i].swath_width_y + * planes[i].num_dpp / planes[i].h_ratio + / planes[i].pixclk_mhz; + } else { + double dchub_pscl_bw_per_clk; + + if (planes[i].h_ratio > 1) { + double num_hscl_kernels; + + num_hscl_kernels = dml_ceil((double) planes[i].h_taps / 6); + dchub_pscl_bw_per_clk = + dml_min( + (double) mode_lib->ip.max_dchub_pscl_bw_pix_per_clk, + mode_lib->ip.max_pscl_lb_bw_pix_per_clk + * planes[i].h_ratio + / num_hscl_kernels); + } else { + dchub_pscl_bw_per_clk = + dml_min( + (double) mode_lib->ip.max_dchub_pscl_bw_pix_per_clk, + (double) mode_lib->ip.max_pscl_lb_bw_pix_per_clk); + } + + planes[i].display_pipe_line_delivery_time = planes[i].swath_width_y + / dchub_pscl_bw_per_clk / planes[i].dppclk_mhz; + } + } +} + +static double calc_total_data_read_bw( + struct display_mode_lib *mode_lib, + struct _vcs_dpi_wm_calc_pipe_params_st *planes, + unsigned int num_planes) +{ + double val = 0.0; + unsigned int i; + + for (i = 0; i < num_planes; i++) { + double swath_width_y_plane = planes[i].swath_width_y * planes[i].num_dpp; + + planes[i].read_bw = swath_width_y_plane + * (dml_ceil(planes[i].bytes_per_pixel_y) + + dml_ceil_2(planes[i].bytes_per_pixel_c) / 2) + / (planes[i].h_total / planes[i].pixclk_mhz) * planes[i].v_ratio; + + val += planes[i].read_bw; + + DTRACE("plane[%d] start", i); + DTRACE("read_bw = %f", planes[i].read_bw); + DTRACE("plane[%d] end", i); + } + + return val; +} + +double dml_wm_calc_total_data_read_bw( + struct display_mode_lib *mode_lib, + struct _vcs_dpi_wm_calc_pipe_params_st *planes, + unsigned int num_planes) +{ + return calc_total_data_read_bw(mode_lib, planes, num_planes); +} + +static double calc_dcfclk_mhz( + struct _vcs_dpi_wm_calc_pipe_params_st *planes, + unsigned int num_planes) +{ + double dcfclk_mhz = -1.0; + unsigned int i; + + for (i = 0; i < num_planes; i++) { + /* voltage and dcfclk must be the same for all pipes */ + ASSERT(dcfclk_mhz == -1.0 || dcfclk_mhz == planes[i].dcfclk_mhz); + dcfclk_mhz = planes[i].dcfclk_mhz; + } + + return dcfclk_mhz; +} + +static enum voltage_state find_voltage( + struct _vcs_dpi_wm_calc_pipe_params_st *planes, + unsigned int num_planes) +{ + int voltage = -1; + unsigned int i; + + for (i = 0; i < num_planes; i++) { + ASSERT(voltage == -1 || voltage == planes[i].voltage); + voltage = planes[i].voltage; + } + + return (enum voltage_state) voltage; +} + +static bool find_dcc_enable(struct _vcs_dpi_wm_calc_pipe_params_st *planes, unsigned int num_planes) +{ + unsigned int i; + + for (i = 0; i < num_planes; i++) { + if (planes[i].dcc_enable) { + return true; + } + } + + return false; +} + +static double calc_return_bw( + struct display_mode_lib *mode_lib, + struct _vcs_dpi_wm_calc_pipe_params_st *planes, + unsigned int num_planes) +{ + struct _vcs_dpi_soc_bounding_box_st *soc; + double return_bw_mbps; + double dcfclk_mhz; + double return_bus_bw; + enum voltage_state voltage; + double return_bw_to_dcn; + bool dcc_enable; + double rob_chunk_diff; + double urgent_latency_traffic; + double critical_compression; + struct _vcs_dpi_voltage_scaling_st state; + + soc = &mode_lib->soc; + + dcfclk_mhz = calc_dcfclk_mhz(planes, num_planes); + return_bus_bw = dcfclk_mhz * soc->return_bus_width_bytes; + + DTRACE("INTERMEDIATE dcfclk_mhz = %f", dcfclk_mhz); + DTRACE("INTERMEDIATE return_bus_bw = %f", return_bus_bw); + + voltage = find_voltage(planes, num_planes); + return_bw_to_dcn = dml_socbb_return_bw_mhz(soc, voltage); + + dcc_enable = find_dcc_enable(planes, num_planes); + + return_bw_mbps = return_bw_to_dcn; + DTRACE("INTERMEDIATE return_bw_mbps = %f", return_bw_mbps); + + rob_chunk_diff = + (mode_lib->ip.rob_buffer_size_kbytes - mode_lib->ip.pixel_chunk_size_kbytes) + * 1024.0; + DTRACE("INTERMEDIATE rob_chunk_diff = %f", rob_chunk_diff); + + if (dcc_enable && return_bw_to_dcn > return_bus_bw / 4) { + double dcc_return_bw = + return_bw_to_dcn * 4.0 + * (1.0 + - soc->urgent_latency_us + / (rob_chunk_diff + / (return_bw_to_dcn + - return_bus_bw + / 4.0) + + soc->urgent_latency_us)); + return_bw_mbps = dml_min(return_bw_mbps, dcc_return_bw); + DTRACE("INTERMEDIATE dcc_return_bw = %f", dcc_return_bw); + } + + urgent_latency_traffic = return_bus_bw * soc->urgent_latency_us; + DTRACE("INTERMEDIATE urgent_latency_traffic = %f", urgent_latency_traffic); + critical_compression = 2.0 * urgent_latency_traffic + / (return_bw_to_dcn * soc->urgent_latency_us + rob_chunk_diff); + DTRACE("INTERMEDIATE critical_compression = %f", critical_compression); + + if (dcc_enable && critical_compression > 1.0 && critical_compression < 4.0) { + double crit_return_bw = (4 * return_bw_to_dcn * rob_chunk_diff + * urgent_latency_traffic); + crit_return_bw = crit_return_bw + / dml_pow( + return_bw_to_dcn * soc->urgent_latency_us + + rob_chunk_diff, + 2); + DTRACE("INTERMEDIATE critical_return_bw = %f", crit_return_bw); + return_bw_mbps = dml_min(return_bw_mbps, crit_return_bw); + } + + /* Gabe does this again for some reason using the value of return_bw_mpbs from the previous calculation + * and a lightly different return_bw_to_dcn + */ + + state = dml_socbb_voltage_scaling(soc, voltage); + return_bw_to_dcn = dml_min( + soc->return_bus_width_bytes * dcfclk_mhz, + state.dram_bw_per_chan_gbps * 1000.0 * (double) soc->num_chans); + + DTRACE("INTERMEDIATE rob_chunk_diff = %f", rob_chunk_diff); + + if (dcc_enable && return_bw_to_dcn > return_bus_bw / 4) { + double dcc_return_bw = + return_bw_to_dcn * 4.0 + * (1.0 + - soc->urgent_latency_us + / (rob_chunk_diff + / (return_bw_to_dcn + - return_bus_bw + / 4.0) + + soc->urgent_latency_us)); + return_bw_mbps = dml_min(return_bw_mbps, dcc_return_bw); + DTRACE("INTERMEDIATE dcc_return_bw = %f", dcc_return_bw); + } + + urgent_latency_traffic = return_bus_bw * soc->urgent_latency_us; + DTRACE("INTERMEDIATE urgent_latency_traffic = %f", urgent_latency_traffic); + critical_compression = 2.0 * urgent_latency_traffic + / (return_bw_to_dcn * soc->urgent_latency_us + rob_chunk_diff); + DTRACE("INTERMEDIATE critical_compression = %f", critical_compression); + + /* problem here? */ + if (dcc_enable && critical_compression > 1.0 && critical_compression < 4.0) { + double crit_return_bw = (4 * return_bw_to_dcn * rob_chunk_diff + * urgent_latency_traffic); + crit_return_bw = crit_return_bw + / dml_pow( + return_bw_to_dcn * soc->urgent_latency_us + + rob_chunk_diff, + 2); + DTRACE("INTERMEDIATE critical_return_bw = %f", crit_return_bw); + DTRACE("INTERMEDIATE return_bw_to_dcn = %f", return_bw_to_dcn); + DTRACE("INTERMEDIATE rob_chunk_diff = %f", rob_chunk_diff); + DTRACE("INTERMEDIATE urgent_latency_traffic = %f", urgent_latency_traffic); + + return_bw_mbps = dml_min(return_bw_mbps, crit_return_bw); + } + + DTRACE("INTERMEDIATE final return_bw_mbps = %f", return_bw_mbps); + return return_bw_mbps; +} + +double dml_wm_calc_return_bw( + struct display_mode_lib *mode_lib, + struct _vcs_dpi_wm_calc_pipe_params_st *planes, + unsigned int num_planes) +{ + return calc_return_bw(mode_lib, planes, num_planes); +} + +static double calc_last_pixel_of_line_extra_wm_us( + struct display_mode_lib *mode_lib, + struct _vcs_dpi_wm_calc_pipe_params_st *planes, + unsigned int num_planes) +{ + double val = 0.0; + double total_data_read_bw = calc_total_data_read_bw(mode_lib, planes, num_planes); + int voltage = -1; + unsigned int i; + double return_bw_mbps; + + for (i = 0; i < num_planes; i++) { + /* voltage mode must be the same for all pipes */ + ASSERT(voltage == -1 || voltage == planes[i].voltage); + voltage = planes[i].voltage; + } + return_bw_mbps = calc_return_bw(mode_lib, planes, num_planes); + + for (i = 0; i < num_planes; i++) { + double bytes_pp_y = dml_ceil(planes[i].bytes_per_pixel_y); + double bytes_pp_c = dml_ceil_2(planes[i].bytes_per_pixel_c); + double swath_bytes_y = (double) planes[i].swath_width_y + * (double) planes[i].swath_height_y * (double) bytes_pp_y; + double swath_bytes_c = ((double) planes[i].swath_width_y / 2.0) + * (double) planes[i].swath_height_c * (double) bytes_pp_c; + double data_fabric_line_delivery_time = (swath_bytes_y + swath_bytes_c) + / (return_bw_mbps * planes[i].read_bw / (double) planes[i].num_dpp + / total_data_read_bw); + + DTRACE( + "bytes_pp_y = %f, swath_width_y = %f, swath_height_y = %f, swath_bytes_y = %f", + bytes_pp_y, + (double) planes[i].swath_width_y, + (double) planes[i].swath_height_y, + swath_bytes_y); + DTRACE( + "bytes_pp_c = %f, swath_width_c = %f, swath_height_c = %f, swath_bytes_c = %f", + bytes_pp_c, + ((double) planes[i].swath_width_y / 2.0), + (double) planes[i].swath_height_c, + swath_bytes_c); + DTRACE( + "return_bw_mbps = %f, read_bw = %f, num_dpp = %d, total_data_read_bw = %f", + return_bw_mbps, + planes[i].read_bw, + planes[i].num_dpp, + total_data_read_bw); + DTRACE("data_fabric_line_delivery_time = %f", data_fabric_line_delivery_time); + DTRACE( + "display_pipe_line_delivery_time = %f", + planes[i].display_pipe_line_delivery_time); + + val = dml_max( + val, + data_fabric_line_delivery_time + - planes[i].display_pipe_line_delivery_time); + } + + DTRACE("last_pixel_of_line_extra_wm is %f us", val); + return val; +} + +static bool calc_pte_enable(struct _vcs_dpi_wm_calc_pipe_params_st *planes, unsigned int num_planes) +{ + unsigned int i; + + for (i = 0; i < num_planes; i++) { + if (planes[i].pte_enable) { + return true; + } + } + + return false; +} + +static void calc_lines_in_det_y(struct _vcs_dpi_wm_calc_pipe_params_st *plane) +{ + plane->lines_in_det_y = plane->det_buffer_size_y / plane->bytes_per_pixel_y + / plane->swath_width_y; + plane->lines_in_det_y_rounded_down_to_swath = dml_floor( + (double) plane->lines_in_det_y / plane->swath_height_y) + * plane->swath_height_y; + plane->full_det_buffering_time = plane->lines_in_det_y_rounded_down_to_swath + * (plane->h_total / plane->pixclk_mhz); +} + +/* CHECKME: not obviously 1:1 with calculation described in architectural + * document or spreadsheet */ +static void calc_dcfclk_deepsleep_mhz_per_plane( + struct display_mode_lib *mode_lib, + struct _vcs_dpi_wm_calc_pipe_params_st *plane) +{ + double bus_width_per_pixel; + + if (plane->swath_height_c == 0) { + bus_width_per_pixel = dml_ceil(plane->bytes_per_pixel_y) / 64; + } else { + double bus_width_per_pixel_c; + + bus_width_per_pixel = dml_ceil(plane->bytes_per_pixel_y) / 32; + bus_width_per_pixel_c = dml_ceil(plane->bytes_per_pixel_c) / 32; + if (bus_width_per_pixel < bus_width_per_pixel_c) + bus_width_per_pixel = bus_width_per_pixel_c; + } + + if (plane->v_ratio <= 1) { + plane->dcfclk_deepsleep_mhz_per_plane = 1.1 * plane->pixclk_mhz / plane->num_dpp + * plane->h_ratio * bus_width_per_pixel; + } else if (plane->h_ratio > 1) { + double num_hscl_kernels = dml_ceil((double) plane->h_taps / 6); + double dchub_pscl_bw_per_clk = dml_min( + (double) mode_lib->ip.max_dchub_pscl_bw_pix_per_clk, + mode_lib->ip.max_pscl_lb_bw_pix_per_clk * plane->h_ratio + / num_hscl_kernels); + + plane->dcfclk_deepsleep_mhz_per_plane = 1.1 * plane->dppclk_mhz + * dchub_pscl_bw_per_clk * bus_width_per_pixel; + } else { + double dchub_pscl_bw_per_clk = dml_min( + (double) mode_lib->ip.max_dchub_pscl_bw_pix_per_clk, + (double) mode_lib->ip.max_pscl_lb_bw_pix_per_clk); + + plane->dcfclk_deepsleep_mhz_per_plane = 1.1 * plane->dppclk_mhz + * dchub_pscl_bw_per_clk * bus_width_per_pixel; + } + + plane->dcfclk_deepsleep_mhz_per_plane = dml_max( + plane->dcfclk_deepsleep_mhz_per_plane, + plane->pixclk_mhz / 16); +} + +/* Implementation of expected stutter efficiency from DCN1_Display_Mode.docx */ +double dml_wm_expected_stutter_eff_e2e( + struct display_mode_lib *mode_lib, + struct _vcs_dpi_display_e2e_pipe_params_st *e2e, + unsigned int num_pipes) +{ + double min_full_det_buffering_time_us; + double frame_time_for_min_full_det_buffering_time_us = 0.0; + struct _vcs_dpi_wm_calc_pipe_params_st *planes = mode_lib->wm_param; + unsigned int num_planes; + unsigned int i; + double total_data_read_bw_mbps; + double average_read_bw_gbps; + double min_full_det_buffer_size_bytes; + double rob_fill_size_bytes; + double part_of_burst_that_fits_in_rob; + int voltage; + double dcfclk_mhz; + unsigned int total_writeback; + double return_bw_mbps; + double stutter_burst_time_us; + double stutter_eff_not_including_vblank; + double smallest_vblank_us; + double stutter_eff; + + memset(mode_lib->wm_param, 0, sizeof(mode_lib->wm_param)); + DTRACE("calculating expected stutter efficiency"); + + num_planes = dml_wm_e2e_to_wm(mode_lib, e2e, num_pipes, planes); + + for (i = 0; i < num_planes; i++) { + calc_lines_in_det_y(&planes[i]); + + DTRACE("swath width y plane %d = %d", i, planes[i].swath_width_y); + DTRACE("swath height y plane %d = %d", i, planes[i].swath_height_y); + DTRACE( + "bytes per pixel det y plane %d = %f", + i, + planes[i].bytes_per_pixel_y); + DTRACE( + "bytes per pixel det c plane %d = %f", + i, + planes[i].bytes_per_pixel_c); + DTRACE( + "det buffer size plane %d = %d", + i, + planes[i].det_buffer_size_y); + DTRACE("lines in det plane %d = %d", i, planes[i].lines_in_det_y); + DTRACE( + "lines in det rounded to swaths plane %d = %d", + i, + planes[i].lines_in_det_y_rounded_down_to_swath); + } + + min_full_det_buffering_time_us = 9999.0; + for (i = 0; i < num_planes; i++) { + if (planes[i].full_det_buffering_time < min_full_det_buffering_time_us) { + min_full_det_buffering_time_us = planes[i].full_det_buffering_time; + frame_time_for_min_full_det_buffering_time_us = (double) planes[i].v_total + * planes[i].h_total / planes[i].pixclk_mhz; + } + } + + DTRACE("INTERMEDIATE: min_full_det_buffering_time_us = %f", min_full_det_buffering_time_us); + + total_data_read_bw_mbps = calc_total_data_read_bw(mode_lib, planes, num_planes); + + average_read_bw_gbps = 0.0; + + for (i = 0; i < num_planes; i++) { + if (planes[i].dcc_enable) { + average_read_bw_gbps += planes[i].read_bw / planes[i].dcc_rate / 1000; + } else { + average_read_bw_gbps += planes[i].read_bw / 1000; + } + + if (planes[i].dcc_enable) { + average_read_bw_gbps += planes[i].read_bw / 1000 / 256; + } + + if (planes[i].pte_enable) { + average_read_bw_gbps += planes[i].read_bw / 1000 / 512; + } + } + + min_full_det_buffer_size_bytes = min_full_det_buffering_time_us * total_data_read_bw_mbps; + rob_fill_size_bytes = mode_lib->ip.rob_buffer_size_kbytes * 1024 * total_data_read_bw_mbps + / (average_read_bw_gbps * 1000); + part_of_burst_that_fits_in_rob = dml_min( + min_full_det_buffer_size_bytes, + rob_fill_size_bytes); + + voltage = -1; + dcfclk_mhz = -1.0; + total_writeback = 0; + + for (i = 0; i < num_pipes; i++) { + /* voltage and dcfclk must be the same for all pipes */ + ASSERT(voltage == -1 || voltage == e2e[i].clks_cfg.voltage); + voltage = e2e[i].clks_cfg.voltage; + ASSERT(dcfclk_mhz == -1.0 || dcfclk_mhz == e2e[i].clks_cfg.dcfclk_mhz); + dcfclk_mhz = e2e[i].clks_cfg.dcfclk_mhz; + + if (e2e[i].dout.output_type == dm_wb) + total_writeback++; + } + + return_bw_mbps = calc_return_bw(mode_lib, planes, num_planes); + + DTRACE("INTERMEDIATE: part_of_burst_that_fits_in_rob = %f", part_of_burst_that_fits_in_rob); + DTRACE("INTERMEDIATE: average_read_bw_gbps = %f", average_read_bw_gbps); + DTRACE("INTERMEDIATE: total_data_read_bw_mbps = %f", total_data_read_bw_mbps); + DTRACE("INTERMEDIATE: return_bw_mbps = %f", return_bw_mbps); + + stutter_burst_time_us = part_of_burst_that_fits_in_rob * (average_read_bw_gbps * 1000) + / total_data_read_bw_mbps / return_bw_mbps + + (min_full_det_buffering_time_us * total_data_read_bw_mbps + - part_of_burst_that_fits_in_rob) / (dcfclk_mhz * 64); + DTRACE("INTERMEDIATE: stutter_burst_time_us = %f", stutter_burst_time_us); + + if (total_writeback == 0) { + stutter_eff_not_including_vblank = (1.0 + - ((mode_lib->soc.sr_exit_time_us + stutter_burst_time_us) + / min_full_det_buffering_time_us)) * 100.0; + } else { + stutter_eff_not_including_vblank = 0.0; + } + + DTRACE("stutter_efficiency_not_including_vblank = %f", stutter_eff_not_including_vblank); + + smallest_vblank_us = 9999.0; + + for (i = 0; i < num_pipes; i++) { + double vblank_us; + if (e2e[i].pipe.dest.syncronized_vblank_all_planes != 0 || num_pipes == 1) { + vblank_us = (double) (e2e[i].pipe.dest.vtotal + 1 + - e2e[i].pipe.dest.vblank_start + + e2e[i].pipe.dest.vblank_end * e2e[i].pipe.dest.htotal) + / e2e[i].pipe.dest.pixel_rate_mhz; + } else { + vblank_us = 0.0; + } + + smallest_vblank_us = dml_min(smallest_vblank_us, vblank_us); + } + + DTRACE("smallest vblank = %f us", smallest_vblank_us); + + stutter_eff = 100.0 + * (((stutter_eff_not_including_vblank / 100.0) + * (frame_time_for_min_full_det_buffering_time_us + - smallest_vblank_us) + smallest_vblank_us) + / frame_time_for_min_full_det_buffering_time_us); + + DTRACE("stutter_efficiency = %f", stutter_eff); + + return stutter_eff_not_including_vblank; +} + +double dml_wm_expected_stutter_eff_e2e_with_vblank( + struct display_mode_lib *mode_lib, + struct _vcs_dpi_display_e2e_pipe_params_st *e2e, + unsigned int num_pipes) +{ + double min_full_det_buffering_time_us; + double frame_time_for_min_full_det_buffering_time_us = 0.0; + struct _vcs_dpi_wm_calc_pipe_params_st *planes = mode_lib->wm_param; + unsigned int num_planes; + unsigned int i; + double total_data_read_bw_mbps; + double average_read_bw_gbps; + double min_full_det_buffer_size_bytes; + double rob_fill_size_bytes; + double part_of_burst_that_fits_in_rob; + int voltage; + double dcfclk_mhz; + unsigned int total_writeback; + double return_bw_mbps; + double stutter_burst_time_us; + double stutter_eff_not_including_vblank; + double smallest_vblank_us; + double stutter_eff; + + memset(mode_lib->wm_param, 0, sizeof(mode_lib->wm_param)); + num_planes = dml_wm_e2e_to_wm(mode_lib, e2e, num_pipes, planes); + + for (i = 0; i < num_planes; i++) { + calc_lines_in_det_y(&planes[i]); + } + + min_full_det_buffering_time_us = 9999.0; + for (i = 0; i < num_planes; i++) { + if (planes[i].full_det_buffering_time < min_full_det_buffering_time_us) { + min_full_det_buffering_time_us = planes[i].full_det_buffering_time; + frame_time_for_min_full_det_buffering_time_us = (double) planes[i].v_total + * planes[i].h_total / planes[i].pixclk_mhz; + } + } + + total_data_read_bw_mbps = calc_total_data_read_bw(mode_lib, planes, num_planes); + average_read_bw_gbps = 0.0; + + for (i = 0; i < num_planes; i++) { + if (planes[i].dcc_enable) { + average_read_bw_gbps += planes[i].read_bw / planes[i].dcc_rate / 1000; + } else { + average_read_bw_gbps += planes[i].read_bw / 1000; + } + + if (planes[i].dcc_enable) { + average_read_bw_gbps += planes[i].read_bw / 1000 / 256; + } + + if (planes[i].pte_enable) { + average_read_bw_gbps += planes[i].read_bw / 1000 / 512; + } + } + + min_full_det_buffer_size_bytes = min_full_det_buffering_time_us * total_data_read_bw_mbps; + rob_fill_size_bytes = mode_lib->ip.rob_buffer_size_kbytes * 1024 * total_data_read_bw_mbps + / (average_read_bw_gbps * 1000); + part_of_burst_that_fits_in_rob = dml_min( + min_full_det_buffer_size_bytes, + rob_fill_size_bytes); + + voltage = -1; + dcfclk_mhz = -1.0; + total_writeback = 0; + + for (i = 0; i < num_pipes; i++) { + /* voltage and dcfclk must be the same for all pipes */ + ASSERT(voltage == -1 || voltage == e2e[i].clks_cfg.voltage); + voltage = e2e[i].clks_cfg.voltage; + ASSERT(dcfclk_mhz == -1.0 || dcfclk_mhz == e2e[i].clks_cfg.dcfclk_mhz); + dcfclk_mhz = e2e[i].clks_cfg.dcfclk_mhz; + + if (e2e[i].dout.output_type == dm_wb) + total_writeback++; + } + + return_bw_mbps = calc_return_bw(mode_lib, planes, num_planes); + + stutter_burst_time_us = part_of_burst_that_fits_in_rob * (average_read_bw_gbps * 1000) + / total_data_read_bw_mbps / return_bw_mbps + + (min_full_det_buffering_time_us * total_data_read_bw_mbps + - part_of_burst_that_fits_in_rob) / (dcfclk_mhz * 64); + + if (total_writeback == 0) { + stutter_eff_not_including_vblank = (1.0 + - ((mode_lib->soc.sr_exit_time_us + stutter_burst_time_us) + / min_full_det_buffering_time_us)) * 100.0; + } else { + stutter_eff_not_including_vblank = 0.0; + } + + smallest_vblank_us = 9999.0; + + for (i = 0; i < num_pipes; i++) { + double vblank_us; + if (e2e[i].pipe.dest.syncronized_vblank_all_planes != 0 || num_pipes == 1) { + vblank_us = (double) (e2e[i].pipe.dest.vtotal + 1 + - e2e[i].pipe.dest.vblank_start + + e2e[i].pipe.dest.vblank_end * e2e[i].pipe.dest.htotal) + / e2e[i].pipe.dest.pixel_rate_mhz; + } else { + vblank_us = 0.0; + } + + smallest_vblank_us = dml_min(smallest_vblank_us, vblank_us); + } + + stutter_eff = 100.0 + * (((stutter_eff_not_including_vblank / 100.0) + * (frame_time_for_min_full_det_buffering_time_us + - smallest_vblank_us) + smallest_vblank_us) + / frame_time_for_min_full_det_buffering_time_us); + + + return stutter_eff; +} + +double urgent_extra_calc( + struct display_mode_lib *mode_lib, + double dcfclk_mhz, + double return_bw_mbps, + unsigned int total_active_dpp, + unsigned int total_dcc_active_dpp) +{ + double urgent_extra_latency_us = 0.0; + double urgent_round_trip_ooo_latency_us; + + urgent_round_trip_ooo_latency_us = + (((double) mode_lib->soc.round_trip_ping_latency_dcfclk_cycles + 32) + / dcfclk_mhz) + + (((double) (mode_lib->soc.urgent_out_of_order_return_per_channel_bytes + * mode_lib->soc.num_chans)) / return_bw_mbps); + + DTRACE( + "INTERMEDIATE round_trip_ping_latency_dcfclk_cycles = %d", + mode_lib->soc.round_trip_ping_latency_dcfclk_cycles); + DTRACE("INTERMEDIATE dcfclk_mhz = %f", dcfclk_mhz); + DTRACE( + "INTERMEDIATE urgent_out_of_order_return_per_channel_bytes = %d", + mode_lib->soc.urgent_out_of_order_return_per_channel_bytes); + + urgent_extra_latency_us = urgent_round_trip_ooo_latency_us + + ((double) total_active_dpp * mode_lib->ip.pixel_chunk_size_kbytes + + (double) total_dcc_active_dpp + * mode_lib->ip.meta_chunk_size_kbytes) + * 1024.0 / return_bw_mbps; /* to us */ + + DTRACE( + "INTERMEDIATE urgent_round_trip_ooo_latency_us = %f", + urgent_round_trip_ooo_latency_us); + DTRACE("INTERMEDIATE total_active_dpp = %d", total_active_dpp); + DTRACE( + "INTERMEDIATE pixel_chunk_size_kbytes = %d", + mode_lib->ip.pixel_chunk_size_kbytes); + DTRACE("INTERMEDIATE total_dcc_active_dpp = %d", total_dcc_active_dpp); + DTRACE( + "INTERMEDIATE meta_chunk_size_kbyte = %d", + mode_lib->ip.meta_chunk_size_kbytes); + DTRACE("INTERMEDIATE return_bw_mbps = %f", return_bw_mbps); + + return urgent_extra_latency_us; +} + +double dml_wm_urgent_extra_max(struct display_mode_lib *mode_lib) +{ + unsigned int total_active_dpp = DC__NUM_DPP; + unsigned int total_dcc_active_dpp = total_active_dpp; + double urgent_extra_latency_us = 0.0; + double dcfclk_mhz = 0.0; + double return_bw_mbps = 0.0; + int voltage = dm_vmin; + + /* use minimum voltage */ + return_bw_mbps = dml_socbb_return_bw_mhz(&mode_lib->soc, (enum voltage_state) voltage); + /* use minimum dcfclk */ + dcfclk_mhz = mode_lib->soc.vmin.dcfclk_mhz; + /* use max dpps and dpps with dcc */ + + urgent_extra_latency_us = urgent_extra_calc( + mode_lib, + dcfclk_mhz, + return_bw_mbps, + total_active_dpp, + total_dcc_active_dpp); + + DTRACE("urgent extra max = %f", urgent_extra_latency_us); + return urgent_extra_latency_us; +} + +double dml_wm_urgent_extra( + struct display_mode_lib *mode_lib, + struct _vcs_dpi_wm_calc_pipe_params_st *pipes, + unsigned int num_pipes) +{ + unsigned int total_active_dpp = 0; + unsigned int total_dcc_active_dpp = 0; + double urgent_extra_latency_us = 0.0; + double dcfclk_mhz = 0.0; + double return_bw_mbps = 0.0; + int voltage = -1; + bool pte_enable = false; + unsigned int i; + + for (i = 0; i < num_pipes; i++) { + /* num_dpp must be greater than 0 */ + ASSERT(pipes[i].num_dpp > 0); + + /* voltage mode must be the same for all pipes */ + ASSERT(voltage == -1 || voltage == pipes[i].voltage); + voltage = pipes[i].voltage; + + /* dcfclk for all pipes must be the same */ + ASSERT(dcfclk_mhz == 0.0 || dcfclk_mhz == pipes[i].dcfclk_mhz); + dcfclk_mhz = pipes[i].dcfclk_mhz; + + total_active_dpp += pipes[i].num_dpp; + + if (pipes[i].dcc_enable) { + total_dcc_active_dpp += pipes[i].num_dpp; + } + } + + DTRACE("total active dpps %d", total_active_dpp); + DTRACE("total active dpps with dcc %d", total_dcc_active_dpp); + DTRACE("voltage state is %d", voltage); + + return_bw_mbps = calc_return_bw(mode_lib, pipes, num_pipes); + + DTRACE("return_bandwidth is %f MBps", return_bw_mbps); + + pte_enable = calc_pte_enable(pipes, num_pipes); + + /* calculate the maximum extra latency just for comparison purposes */ + /* dml_wm_urgent_extra_max(); */ + urgent_extra_latency_us = urgent_extra_calc( + mode_lib, + dcfclk_mhz, + return_bw_mbps, + total_active_dpp, + total_dcc_active_dpp); + + DTRACE("INTERMEDIATE urgent_extra_latency_us_before_pte = %f", urgent_extra_latency_us); + + if (pte_enable) { + urgent_extra_latency_us += total_active_dpp * mode_lib->ip.pte_chunk_size_kbytes + * 1024.0 / return_bw_mbps; + + DTRACE("INTERMEDIATE pte_enable = true"); + DTRACE("INTERMEDIATE total_active_dpp = %d", total_active_dpp); + DTRACE( + "INTERMEDIATE pte_chunk_size_kbytes = %d", + mode_lib->ip.pte_chunk_size_kbytes); + DTRACE("INTERMEDIATE return_bw_mbps = %f", return_bw_mbps); + } + + return urgent_extra_latency_us; +} + +double dml_wm_urgent_e2e( + struct display_mode_lib *mode_lib, + struct _vcs_dpi_display_e2e_pipe_params_st *pipes, + unsigned int num_pipes) +{ + struct _vcs_dpi_wm_calc_pipe_params_st *wm = mode_lib->wm_param; + unsigned int combined_pipes; + double urgent_wm; + + memset(mode_lib->wm_param, 0, sizeof(mode_lib->wm_param)); + combined_pipes = dml_wm_e2e_to_wm(mode_lib, pipes, num_pipes, wm); + + urgent_wm = dml_wm_urgent(mode_lib, wm, combined_pipes); + + return urgent_wm; +} + +double dml_wm_urgent( + struct display_mode_lib *mode_lib, + struct _vcs_dpi_wm_calc_pipe_params_st *planes, + unsigned int num_planes) +{ + double urgent_watermark; + double urgent_extra_latency_us; + double last_pixel_of_line_extra_wm_us = 0.0; + + DTRACE("calculating urgent watermark"); + calc_display_pipe_line_delivery_time(mode_lib, planes, num_planes); + urgent_extra_latency_us = dml_wm_urgent_extra(mode_lib, planes, num_planes); + + last_pixel_of_line_extra_wm_us = calc_last_pixel_of_line_extra_wm_us( + mode_lib, + planes, + num_planes); + + urgent_watermark = mode_lib->soc.urgent_latency_us + last_pixel_of_line_extra_wm_us + + urgent_extra_latency_us; + + DTRACE("INTERMEDIATE urgent_latency_us = %f", mode_lib->soc.urgent_latency_us); + DTRACE("INTERMEDIATE last_pixel_of_line_extra_wm_us = %f", last_pixel_of_line_extra_wm_us); + DTRACE("INTERMEDIATE urgent_extra_latency_us = %f", urgent_extra_latency_us); + + DTRACE("urgent_watermark_us = %f", urgent_watermark); + return urgent_watermark; +} + +double dml_wm_pte_meta_urgent(struct display_mode_lib *mode_lib, double urgent_wm_us) +{ + double val; + + val = urgent_wm_us + 2.0 * mode_lib->soc.urgent_latency_us; + DTRACE("pte_meta_urgent_watermark_us = %f", val); + + return val; +} + +double dml_wm_dcfclk_deepsleep_mhz_e2e( + struct display_mode_lib *mode_lib, + struct _vcs_dpi_display_e2e_pipe_params_st *pipes, + unsigned int num_pipes) +{ + struct _vcs_dpi_wm_calc_pipe_params_st *planes = mode_lib->wm_param; + unsigned int num_planes; + double val; + + memset(mode_lib->wm_param, 0, sizeof(mode_lib->wm_param)); + num_planes = dml_wm_e2e_to_wm(mode_lib, pipes, num_pipes, planes); + + val = dml_wm_dcfclk_deepsleep_mhz(mode_lib, planes, num_planes); + + return val; +} + +double dml_wm_dcfclk_deepsleep_mhz( + struct display_mode_lib *mode_lib, + struct _vcs_dpi_wm_calc_pipe_params_st *planes, + unsigned int num_planes) +{ + double val = 8.0; + unsigned int i; + + for (i = 0; i < num_planes; i++) { + calc_dcfclk_deepsleep_mhz_per_plane(mode_lib, &planes[i]); + + if (val < planes[i].dcfclk_deepsleep_mhz_per_plane) { + val = planes[i].dcfclk_deepsleep_mhz_per_plane; + } + + DTRACE("plane[%d] start", i); + DTRACE("dcfclk_deepsleep_per_plane = %f", planes[i].dcfclk_deepsleep_mhz_per_plane); + DTRACE("plane[%d] end", i); + } + + DTRACE("dcfclk_deepsleep_mhz = %f", val); + + return val; +} + +struct _vcs_dpi_cstate_pstate_watermarks_st dml_wm_cstate_pstate_e2e( + struct display_mode_lib *mode_lib, + struct _vcs_dpi_display_e2e_pipe_params_st *pipes, + unsigned int num_pipes) +{ + struct _vcs_dpi_wm_calc_pipe_params_st *wm = mode_lib->wm_param; + unsigned int combined_pipes; + struct _vcs_dpi_cstate_pstate_watermarks_st cstate_pstate_wm; + + memset(mode_lib->wm_param, 0, sizeof(mode_lib->wm_param)); + combined_pipes = dml_wm_e2e_to_wm(mode_lib, pipes, num_pipes, wm); + cstate_pstate_wm = dml_wm_cstate_pstate(mode_lib, wm, combined_pipes); + + + return cstate_pstate_wm; +} + +struct _vcs_dpi_cstate_pstate_watermarks_st dml_wm_cstate_pstate( + struct display_mode_lib *mode_lib, + struct _vcs_dpi_wm_calc_pipe_params_st *pipes, + unsigned int num_pipes) +{ + struct _vcs_dpi_cstate_pstate_watermarks_st wm; + double urgent_extra_latency_us; + double urgent_watermark_us; + double last_pixel_of_line_extra_wm_us; + double dcfclk_deepsleep_freq; + + DTRACE("calculating cstate and pstate watermarks"); + urgent_extra_latency_us = dml_wm_urgent_extra(mode_lib, pipes, num_pipes); + urgent_watermark_us = dml_wm_urgent(mode_lib, pipes, num_pipes); + + last_pixel_of_line_extra_wm_us = calc_last_pixel_of_line_extra_wm_us( + mode_lib, + pipes, + num_pipes); + dcfclk_deepsleep_freq = dml_wm_dcfclk_deepsleep_mhz(mode_lib, pipes, num_pipes); + + wm.cstate_exit_us = mode_lib->soc.sr_exit_time_us + last_pixel_of_line_extra_wm_us + + urgent_extra_latency_us + + mode_lib->ip.dcfclk_cstate_latency / dcfclk_deepsleep_freq; + wm.cstate_enter_plus_exit_us = mode_lib->soc.sr_enter_plus_exit_time_us + + last_pixel_of_line_extra_wm_us + urgent_extra_latency_us; + wm.pstate_change_us = mode_lib->soc.dram_clock_change_latency_us + urgent_watermark_us; + + DTRACE("stutter_exit_watermark_us = %f", wm.cstate_exit_us); + DTRACE("stutter_enter_plus_exit_watermark_us = %f", wm.cstate_enter_plus_exit_us); + DTRACE("dram_clock_change_watermark_us = %f", wm.pstate_change_us); + + return wm; +} + +double dml_wm_writeback_pstate_e2e( + struct display_mode_lib *mode_lib, + struct _vcs_dpi_display_e2e_pipe_params_st *pipes, + unsigned int num_pipes) +{ + struct _vcs_dpi_wm_calc_pipe_params_st *wm = mode_lib->wm_param; + unsigned int combined_pipes; + + memset(mode_lib->wm_param, 0, sizeof(mode_lib->wm_param)); + combined_pipes = dml_wm_e2e_to_wm(mode_lib, pipes, num_pipes, wm); + + + return dml_wm_writeback_pstate(mode_lib, wm, combined_pipes); +} + +double dml_wm_writeback_pstate( + struct display_mode_lib *mode_lib, + struct _vcs_dpi_wm_calc_pipe_params_st *pipes, + unsigned int num_pipes) +{ + unsigned int total_active_wb = 0; + double wm = 0.0; + double socclk_mhz = 0.0; + unsigned int i; + + DTRACE("calculating wb pstate watermark"); + for (i = 0; i < num_pipes; i++) { + if (pipes[i].output_type == dm_wb) + total_active_wb++; + ASSERT(socclk_mhz == 0.0 || socclk_mhz == pipes[i].socclk_mhz); + socclk_mhz = pipes[i].socclk_mhz; + } + + DTRACE("total wb outputs %d", total_active_wb); + DTRACE("socclk frequency %f Mhz", socclk_mhz); + + if (total_active_wb <= 1) { + wm = mode_lib->soc.writeback_dram_clock_change_latency_us; + } else { + wm = mode_lib->soc.writeback_dram_clock_change_latency_us + + (mode_lib->ip.writeback_chunk_size_kbytes * 1024.0) / 32.0 + / socclk_mhz; + } + + DTRACE("wb pstate watermark %f us", wm); + return wm; +} + +unsigned int dml_wm_e2e_to_wm( + struct display_mode_lib *mode_lib, + struct _vcs_dpi_display_e2e_pipe_params_st *e2e, + unsigned int num_pipes, + struct _vcs_dpi_wm_calc_pipe_params_st *wm) +{ + unsigned int num_planes = 0; + bool visited[DC__NUM_PIPES]; + unsigned int i, j; + + for (i = 0; i < num_pipes; i++) { + visited[i] = false; + } + + for (i = 0; i < num_pipes; i++) { + unsigned int num_dpp = 1; + + if (visited[i]) { + continue; + } + + visited[i] = true; + + if (e2e[i].pipe.src.is_hsplit) { + for (j = i + 1; j < num_pipes; j++) { + if (e2e[j].pipe.src.is_hsplit && !visited[j] + && (e2e[i].pipe.src.hsplit_grp + == e2e[j].pipe.src.hsplit_grp)) { + num_dpp++; + visited[j] = true; + } + } + } + + wm[num_planes].num_dpp = num_dpp; + wm[num_planes].voltage = e2e[i].clks_cfg.voltage; + wm[num_planes].output_type = e2e[i].dout.output_type; + wm[num_planes].dcfclk_mhz = e2e[i].clks_cfg.dcfclk_mhz; + wm[num_planes].socclk_mhz = e2e[i].clks_cfg.socclk_mhz; + wm[num_planes].dppclk_mhz = e2e[i].clks_cfg.dppclk_mhz; + wm[num_planes].pixclk_mhz = e2e[i].pipe.dest.pixel_rate_mhz; + + wm[num_planes].pte_enable = e2e[i].pipe.src.vm; + wm[num_planes].dcc_enable = e2e[i].pipe.src.dcc; + wm[num_planes].dcc_rate = e2e[i].pipe.src.dcc_rate; + + get_bytes_per_pixel( + (enum source_format_class) e2e[i].pipe.src.source_format, + &wm[num_planes]); + wm[num_planes].swath_width_y = get_swath_width_y(&e2e[i].pipe.src, num_dpp); + get_swath_height( + mode_lib, + &e2e[i].pipe.src, + &wm[num_planes], + wm[num_planes].swath_width_y); + + wm[num_planes].interlace_en = e2e[i].pipe.dest.interlaced; + wm[num_planes].h_ratio = e2e[i].pipe.scale_ratio_depth.hscl_ratio; + wm[num_planes].v_ratio = e2e[i].pipe.scale_ratio_depth.vscl_ratio; + if (wm[num_planes].interlace_en) { + wm[num_planes].v_ratio = 2 * wm[num_planes].v_ratio; + } + wm[num_planes].h_taps = e2e[i].pipe.scale_taps.htaps; + wm[num_planes].h_total = e2e[i].pipe.dest.htotal; + wm[num_planes].v_total = e2e[i].pipe.dest.vtotal; + wm[num_planes].v_active = e2e[i].pipe.dest.vactive; + wm[num_planes].e2e_index = i; + num_planes++; + } + + for (i = 0; i < num_planes; i++) { + DTRACE("plane[%d] start", i); + DTRACE("voltage = %d", wm[i].voltage); + DTRACE("v_active = %d", wm[i].v_active); + DTRACE("h_total = %d", wm[i].h_total); + DTRACE("v_total = %d", wm[i].v_total); + DTRACE("pixclk_mhz = %f", wm[i].pixclk_mhz); + DTRACE("dcfclk_mhz = %f", wm[i].dcfclk_mhz); + DTRACE("dppclk_mhz = %f", wm[i].dppclk_mhz); + DTRACE("h_ratio = %f", wm[i].h_ratio); + DTRACE("v_ratio = %f", wm[i].v_ratio); + DTRACE("interlaced = %d", wm[i].interlace_en); + DTRACE("h_taps = %d", wm[i].h_taps); + DTRACE("num_dpp = %d", wm[i].num_dpp); + DTRACE("swath_width_y = %d", wm[i].swath_width_y); + DTRACE("swath_height_y = %d", wm[i].swath_height_y); + DTRACE("swath_height_c = %d", wm[i].swath_height_c); + DTRACE("det_buffer_size_y = %d", wm[i].det_buffer_size_y); + DTRACE("dcc_rate = %f", wm[i].dcc_rate); + DTRACE("dcc_enable = %s", wm[i].dcc_enable ? "true" : "false"); + DTRACE("pte_enable = %s", wm[i].pte_enable ? "true" : "false"); + DTRACE("plane[%d] end", i); + } + + return num_planes; +} diff --git a/drivers/gpu/drm/amd/display/dc/dml/display_watermark.h b/drivers/gpu/drm/amd/display/dc/dml/display_watermark.h new file mode 100644 index 000000000000..94cde8b55e08 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/dml/display_watermark.h @@ -0,0 +1,98 @@ +/* + * Copyright 2017 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 __DISPLAY_WATERMARK_H__ +#define __DISPLAY_WATERMARK_H__ + +#include "dml_common_defs.h" + +struct display_mode_lib; + +double dml_wm_urgent_extra( + struct display_mode_lib *mode_lib, + struct _vcs_dpi_wm_calc_pipe_params_st *pipes, + unsigned int num_pipes); +double dml_wm_urgent_extra_max(struct display_mode_lib *mode_lib); + +double dml_wm_urgent_e2e( + struct display_mode_lib *mode_lib, + struct _vcs_dpi_display_e2e_pipe_params_st *pipes, + unsigned int num_pipes); +double dml_wm_urgent( + struct display_mode_lib *mode_lib, + struct _vcs_dpi_wm_calc_pipe_params_st *planes, + unsigned int num_planes); +double dml_wm_pte_meta_urgent(struct display_mode_lib *mode_lib, double urgent_wm_us); +double dml_wm_dcfclk_deepsleep_mhz_e2e( + struct display_mode_lib *mode_lib, + struct _vcs_dpi_display_e2e_pipe_params_st *pipes, + unsigned int num_pipes); +double dml_wm_dcfclk_deepsleep_mhz( + struct display_mode_lib *mode_lib, + struct _vcs_dpi_wm_calc_pipe_params_st *planes, + unsigned int num_planes); + +struct _vcs_dpi_cstate_pstate_watermarks_st dml_wm_cstate_pstate_e2e( + struct display_mode_lib *mode_lib, + struct _vcs_dpi_display_e2e_pipe_params_st *pipes, + unsigned int num_pipes); +struct _vcs_dpi_cstate_pstate_watermarks_st dml_wm_cstate_pstate( + struct display_mode_lib *mode_lib, + struct _vcs_dpi_wm_calc_pipe_params_st *pipes, + unsigned int num_pipes); + +double dml_wm_writeback_pstate_e2e( + struct display_mode_lib *mode_lib, + struct _vcs_dpi_display_e2e_pipe_params_st *pipes, + unsigned int num_pipes); +double dml_wm_writeback_pstate( + struct display_mode_lib *mode_lib, + struct _vcs_dpi_wm_calc_pipe_params_st *pipes, + unsigned int num_pipes); + +double dml_wm_expected_stutter_eff_e2e( + struct display_mode_lib *mode_lib, + struct _vcs_dpi_display_e2e_pipe_params_st *e2e, + unsigned int num_pipes); +double dml_wm_expected_stutter_eff_e2e_with_vblank( + struct display_mode_lib *mode_lib, + struct _vcs_dpi_display_e2e_pipe_params_st *e2e, + unsigned int num_pipes); + +unsigned int dml_wm_e2e_to_wm( + struct display_mode_lib *mode_lib, + struct _vcs_dpi_display_e2e_pipe_params_st *e2e, + unsigned int num_pipes, + struct _vcs_dpi_wm_calc_pipe_params_st *wm); + +double dml_wm_calc_total_data_read_bw( + struct display_mode_lib *mode_lib, + struct _vcs_dpi_wm_calc_pipe_params_st *planes, + unsigned int num_planes); +double dml_wm_calc_return_bw( + struct display_mode_lib *mode_lib, + struct _vcs_dpi_wm_calc_pipe_params_st *planes, + unsigned int num_planes); + +#endif diff --git a/drivers/gpu/drm/amd/display/dc/dml/dml_common_defs.c b/drivers/gpu/drm/amd/display/dc/dml/dml_common_defs.c new file mode 100644 index 000000000000..21349a022de3 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/dml/dml_common_defs.c @@ -0,0 +1,148 @@ +/* + * Copyright 2017 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 "dml_common_defs.h" +#include "../calcs/dcn_calc_math.h" + +double dml_min(double a, double b) +{ + return (double) dcn_bw_min2(a, b); +} + +double dml_max(double a, double b) +{ + return (double) dcn_bw_max2(a, b); +} + +double dml_ceil(double a) +{ + return (double) dcn_bw_ceil2(a, 1); +} + +double dml_floor(double a) +{ + return (double) dcn_bw_floor2(a, 1); +} + +double dml_round(double a) +{ + double round_pt = 0.5; + double ceil = dml_ceil(a); + double floor = dml_floor(a); + + if (a - floor >= round_pt) + return ceil; + else + return floor; +} + +int dml_log2(double x) +{ + return dml_round((double)dcn_bw_log(x, 2)); +} + +double dml_pow(double a, int exp) +{ + return (double) dcn_bw_pow(a, exp); +} + +unsigned int dml_round_to_multiple( + unsigned int num, + unsigned int multiple, + bool up) +{ + unsigned int remainder; + + if (multiple == 0) + return num; + + remainder = num % multiple; + + if (remainder == 0) + return num; + + if (up) + return (num + multiple - remainder); + else + return (num - remainder); +} + +double dml_fmod(double f, int val) +{ + return (double) dcn_bw_mod(f, val); +} + +double dml_ceil_2(double f) +{ + return (double) dcn_bw_ceil2(f, 2); +} + +bool dml_util_is_420(enum source_format_class sorce_format) +{ + bool val = false; + + switch (sorce_format) { + case dm_444_16: + val = false; + break; + case dm_444_32: + val = false; + break; + case dm_444_64: + val = false; + break; + case dm_420_8: + val = true; + break; + case dm_420_10: + val = true; + break; + case dm_422_8: + val = false; + break; + case dm_422_10: + val = false; + break; + default: + BREAK_TO_DEBUGGER(); + } + + return val; +} + +double dml_ceil_ex(double x, double granularity) +{ + return (double) dcn_bw_ceil2(x, granularity); +} + +double dml_floor_ex(double x, double granularity) +{ + return (double) dcn_bw_floor2(x, granularity); +} + +double dml_log(double x, double base) +{ + return (double) dcn_bw_log(x, base); +} diff --git a/drivers/gpu/drm/amd/display/dc/dml/dml_common_defs.h b/drivers/gpu/drm/amd/display/dc/dml/dml_common_defs.h new file mode 100644 index 000000000000..c5340d41eedb --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/dml/dml_common_defs.h @@ -0,0 +1,51 @@ +/* + * Copyright 2017 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_COMMON_DEFS_H__ +#define __DC_COMMON_DEFS_H__ + +#include "dm_services.h" +#include "dc_features.h" +#include "display_mode_structs.h" +#include "display_mode_enums.h" + +#define DTRACE(str, ...) dm_logger_write(mode_lib->logger, LOG_DML, str, ##__VA_ARGS__); + +double dml_min(double a, double b); +double dml_max(double a, double b); +bool dml_util_is_420(enum source_format_class sorce_format); +double dml_ceil_ex(double x, double granularity); +double dml_floor_ex(double x, double granularity); +double dml_log(double x, double base); +double dml_ceil(double a); +double dml_floor(double a); +double dml_round(double a); +int dml_log2(double x); +double dml_pow(double a, int exp); +unsigned int dml_round_to_multiple( + unsigned int num, unsigned int multiple, bool up); +double dml_fmod(double f, int val); +double dml_ceil_2(double f); + +#endif /* __DC_COMMON_DEFS_H__ */ diff --git a/drivers/gpu/drm/amd/display/dc/dml/soc_bounding_box.c b/drivers/gpu/drm/amd/display/dc/dml/soc_bounding_box.c new file mode 100644 index 000000000000..cb143d3d40f0 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/dml/soc_bounding_box.c @@ -0,0 +1,73 @@ +/* + * Copyright 2017 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 "soc_bounding_box.h" +#include "display_mode_lib.h" + +void dml_socbb_set_latencies( + struct display_mode_lib *mode_lib, + struct _vcs_dpi_soc_bounding_box_st *from_box) +{ + struct _vcs_dpi_soc_bounding_box_st *to_box = &mode_lib->soc; + + to_box->dram_clock_change_latency_us = from_box->dram_clock_change_latency_us; + to_box->sr_exit_time_us = from_box->sr_exit_time_us; + to_box->sr_enter_plus_exit_time_us = from_box->sr_enter_plus_exit_time_us; + to_box->urgent_latency_us = from_box->urgent_latency_us; + to_box->writeback_latency_us = from_box->writeback_latency_us; + DTRACE("box.dram_clock_change_latency_us: %f", from_box->dram_clock_change_latency_us); + DTRACE("box.sr_exit_time_us: %f", from_box->sr_exit_time_us); + DTRACE("box.sr_enter_plus_exit_time_us: %f", from_box->sr_enter_plus_exit_time_us); + DTRACE("box.urgent_latency_us: %f", from_box->urgent_latency_us); + DTRACE("box.writeback_latency_us: %f", from_box->writeback_latency_us); + +} + +struct _vcs_dpi_voltage_scaling_st dml_socbb_voltage_scaling( + struct _vcs_dpi_soc_bounding_box_st *box, + enum voltage_state voltage) +{ + switch (voltage) { + case dm_vmin: + return box->vmin; + case dm_vnom: + return box->vnom; + case dm_vmax: + default: + return box->vmax; + } +} + +double dml_socbb_return_bw_mhz(struct _vcs_dpi_soc_bounding_box_st *box, enum voltage_state voltage) +{ + double return_bw; + + struct _vcs_dpi_voltage_scaling_st state = dml_socbb_voltage_scaling(box, voltage); + + return_bw = dml_min( + ((double) box->return_bus_width_bytes) * state.dcfclk_mhz, + state.dram_bw_per_chan_gbps * 1000.0 * (double) box->num_chans + * box->ideal_dram_bw_after_urgent_percent / 100.0); + return return_bw; +} diff --git a/drivers/gpu/drm/amd/display/dc/dml/soc_bounding_box.h b/drivers/gpu/drm/amd/display/dc/dml/soc_bounding_box.h new file mode 100644 index 000000000000..7bbae33f163e --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/dml/soc_bounding_box.h @@ -0,0 +1,36 @@ +/* + * Copyright 2017 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 __SOC_BOUNDING_BOX_H__ +#define __SOC_BOUNDING_BOX_H__ + +#include "dml_common_defs.h" + +struct display_mode_lib; + +void dml_socbb_set_latencies(struct display_mode_lib *mode_lib, struct _vcs_dpi_soc_bounding_box_st *from_box); +struct _vcs_dpi_voltage_scaling_st dml_socbb_voltage_scaling(struct _vcs_dpi_soc_bounding_box_st *box, enum voltage_state voltage); +double dml_socbb_return_bw_mhz(struct _vcs_dpi_soc_bounding_box_st *box, enum voltage_state voltage); + +#endif -- 2.30.2