diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2023-02-22 18:28:03 -0800 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2023-02-22 18:28:03 -0800 |
commit | a5c95ca18a98d742d0a4a04063c32556b5b66378 (patch) | |
tree | fdd897b23a1c45b3d03bd1e75e5df42057f339d1 /drivers/gpu/drm/amd/display/dc/dml/dcn32/dcn32_fpu.c | |
parent | 307e14c039063f0c9bd7a18a7add8f940580dcc9 (diff) | |
parent | a48bba98380cb0b43dcd01d276c7efc282e3c33f (diff) |
Merge tag 'drm-next-2023-02-23' of git://anongit.freedesktop.org/drm/drm
Pull drm updates from Dave Airlie:
"There are a bunch of changes all over in the usual places.
Highlights:
- habanalabs moves from misc to accel
- first accel driver for Intel VPU (Versatile Processing Unit)
inference engine
- dropped all the ancient legacy DRI1 drivers. I think it's been at
least 10 years since anyone has heard about these.
- Intel DG2 updates and prelim Meteorlake enablement
- etnaviv adds support for Versilicon NPU device (a GPU like engine
with inference accelerators)
Detailed summary:
Removals:
- remove legacy dri1 drivers: i810, mga, r128, savage, sis, tdfx, via
New driver:
- intel VPU accelerator driver
- habanalabs comes via drm tree now
drm/core:
- use drm_dbg_ helpers in several places
- Document defaults for CRTC backgrounds
- Document use of drm_minor
edid:
- improve mode parsing and refactoring
connector:
- support analog TV mode property
media:
- add some common formats
udmabuf:
- add vmap/vunmap methods
fourcc:
- add XRGB1555 and RGB565 formats
- document open source user waiver
firmware:
- fix color-format selection for system framebuffer
format-helper:
- Add conversion from XRGB8888 to various sysfb formats
- Make XRGB8888 the only driver-emulated legacy format
- Add conversion from XRGB8888 to XBGR8888 and ABGR8888
fb-helper:
- fix preferred depth and bpp values across drivers
- Avoid blank consoles from selecting an incorrect color format
probe-helper:
- Enable/disable HPD on connectors
scheduler:
- Fix lockup in drm_sched_entity_kill()
- Deprecate drm_sched_resubmit_jobs()
bridge:
- remove unused functions
- implement i2c probe_new in various drivers
- ite-it6505: Locking fixes, Cache EDID data
- ite-it66121: Support IT6610 chip
- lontium-tl9611: Fix HDMI on DragonBoard 845c
- parade-ps8640: Use atomic bridge functions
- Support i.MX93 LDB plus DT bindings
debugfs:
- add per device helpers and convert drivers
displayport:
- mst fixes
- add DP adaptive sync DPCD definitions
fbdev:
- always pick 32bpp as default
- remove some unused code
simpledrm:
- support system memory framebuffers
panel:
- add orientation quirks for Lenovo Yoga Tab 3 X90F and DynaBook K50
- Use ktime_get_boottime() to measure power-down delay
- Fix auto-suspend delay
- Visionox VTDR6130 AMOLED DSI
- Support Himax HX8394
- Convert many drivers to common generic DSI write-sequence helper
- AUO A030JTN01
ttm:
- drop bo wait wrapper
- fix MIPS build
habanalabs:
- moved driver to accel subsystem
- gaudi2 decoder error improvement
- more trace events
- Gaudi2 abrupt reset by firmware support
- add uAPI to flush memory transactions
- add uAPI to pass through userspace reqs to fw
- remove dma-buf export by handle
amdgpu:
- add new INFO queries for peak and min sclk/mclk for profile modes
- Add PCIe info to the INFO IOCTL
- secure display support for multiple displays
- DML optimizations
- DCN 3.2 updates
- PSR updates
- DP 2.1 updates
- SR-IOV RAS updates
- VCN RAS support
- SMU 13.x updates
- Switch 1 element arrays to flexible arrays
- Add RAS support for DF 4.3
- Stack size improvements
- S0ix rework
- Allow 0 as a vram limit on APUs
- Handle profiling modes for SMU13.x
- Fix possible segfault in failure case
- Rework FW requests to happen in early_init for all IPs so that we
don't lose the sbios console if FW is missing
- Fix power reporting on certain firmwares for CZN/RN
- Allow S0ix without BIOS support
- Enable freesync over PCon
- Re-enable the AGP aperture on GMC 11.x
amdkfd:
- Error handling fixes
- PASID fixes
- Fix for cleared VRAM BOs
- Fix cleanup if GPUVM creation fails
- Memory accounting fix
- Use resource_size rather than open codeing it
- GC11 mGPU fix
radeon:
- Switch 1 element arrays to flexible arrays
- Fix memory leak on shutdown
- move to new logging
i915:
- Meteorlake display/OA/GSC fw/workarounds enabling
- DP MST DSC support
- Gamma/degamma readout support for the state checker
- Enable SDP split support for DP 2.0
- Add probe blocking support to i915.force_probe parameter
- Enable Xe HP 4tile support
- Avoid display direct calls to uncore
- Fix HuC delayed load memory leaks
- Add DG2 workarounds Wa_18018764978 and Wa_18019271663
- Improve suspend / resume times with VT-d scanout workaround active
- Fix DG2 visual corruption on small BAR systems by not forgetting to
copy CCS aux state
- Fix TLB invalidation for Gen12.50 video and compute engines
- Enable HF-EEODB by switching HDMI, DP and LVDS to use struct
drm_edid
- Start using unversioned DMC firmware paths for new platforms
- ELD refactor: Stop using hardware buffer, precompute ELD
- lots of display code refactoring
nouveau:
- drop legacy ioctl support
- replace 0-sized array
msm:
- dpu/dsi/mdss: Support for SM8350, SM8450 SM8550 and SC8280XP platform
- Added bindings for SM8150
- dpu: Partial support for DSC on SM8150 and SM8250
- dpu: Fixed color transformation matrix being lost on suspend/resume
- dp: Support SDM845 and SC8280XP platforms
- dp: Support for limiting DP link rate via DT property
- dsi: Validate display modes according to the DSI OPP table
- dsi: DSI PHY support for the SM6375 platform
- Add MSM_SUBMIT_BO_NO_IMPLICI
- a2xx: Support to load legacy firmware
- a6xx: GPU devcore dump updates for a650/a660
- GPU devfreq tuning and fixes
- Turn 8960 HDMI PHY into clock provider,
- Make 8960 HDMI PHY use PXO clock from DT
etnaviv:
- experimental versilicon NPU support
- report GPU load via fdinfo format
- MMU fault message improvements
tegra:
- rework syncpoint interrupt
mediatek:
- DSI timing fix
- fix config deps
ast:
- various fixes
exynos:
- restore bridge chain order fixes
gud:
- convert to shadow plane buffers
- perform flushing synchronously during atomic update
- Use new debugfs helpers
arm/hdlcd:
- Use new debugfs helper
ili9486:
- Support 16-bit pixel data
imx:
- Split off IPUv3 driver
mipi-dbi:
- convert to DRM shadow-plane helpers
- rsp driver changes
- Support separate I/O-voltage supply
mxsfb:
- Depend on ARCH_MXS or ARCH_MXC
sun4i:
- convert to new TV mode property
vc4:
- convert to new TV mode property
- kunit tests
- Support RGB565 and RGB666 formats
- convert dsi driver to bridge
- Various HVS an CRTC fixes
v3d:
- Do not opencode drm_gem_object_lookup()
virtio:
- improve tracing
vkms:
- support small cursors in IGT tests
- Fix SEGFAULT from incorrect GEM-buffer mapping
rcar-du:
- fixes and improvements"
* tag 'drm-next-2023-02-23' of git://anongit.freedesktop.org/drm/drm: (1455 commits)
msm/fbdev: fix unused variable warning with clang.
drm/fb-helper: Remove drm_fb_helper_unprepare() from drm_fb_helper_fini()
dma-buf: make kobj_type structure constant
drm/shmem-helper: Fix locking for drm_gem_shmem_get_pages_sgt()
drm/amd/display: disable SubVP + DRR to prevent underflow
drm/amd/display: Fail atomic_check early on normalize_zpos error
drm/amd/pm: avoid unaligned access warnings
drm/amd/display: avoid unaligned access warnings
drm/amd/display: Remove duplicate/repeating expressions
drm/amd/display: Remove duplicate/repeating expression
drm/amd/display: Make variables declaration inside ifdef guard
drm/amd/display: Fix excess arguments on kernel-doc
drm/amd/display: Add previously missing includes
drm/amd/amdgpu: Add function prototypes to headers
drm/amd/display: Add function prototypes to headers
drm/amd/display: Turn global functions into static
drm/amd/display: remove unused _calculate_degamma_curve function
drm/amd/display: remove unused func declaration from resource headers
drm/amd/display: unset initial value for tf since it's never used
drm/amd/display: camel case cleanup in color_gamma file
...
Diffstat (limited to 'drivers/gpu/drm/amd/display/dc/dml/dcn32/dcn32_fpu.c')
-rw-r--r-- | drivers/gpu/drm/amd/display/dc/dml/dcn32/dcn32_fpu.c | 212 |
1 files changed, 185 insertions, 27 deletions
diff --git a/drivers/gpu/drm/amd/display/dc/dml/dcn32/dcn32_fpu.c b/drivers/gpu/drm/amd/display/dc/dml/dcn32/dcn32_fpu.c index f94abd124021..e47828e3b6d5 100644 --- a/drivers/gpu/drm/amd/display/dc/dml/dcn32/dcn32_fpu.c +++ b/drivers/gpu/drm/amd/display/dc/dml/dcn32/dcn32_fpu.c @@ -24,13 +24,14 @@ * */ #include "dcn32_fpu.h" -#include "dc_link_dp.h" #include "dcn32/dcn32_resource.h" #include "dcn20/dcn20_resource.h" #include "display_mode_vba_util_32.h" +#include "dml/dcn32/display_mode_vba_32.h" // We need this includes for WATERMARKS_* defines #include "clk_mgr/dcn32/dcn32_smu13_driver_if.h" #include "dcn30/dcn30_resource.h" +#include "link.h" #define DC_LOGGER_INIT(logger) @@ -691,9 +692,11 @@ static bool dcn32_assign_subvp_pipe(struct dc *dc, * to combine this with SubVP can cause issues with the scheduling). * - Not TMZ surface */ - if (pipe->plane_state && !pipe->top_pipe && + if (pipe->plane_state && !pipe->top_pipe && !dcn32_is_center_timing(pipe) && !dcn32_is_psr_capable(pipe) && pipe->stream->mall_stream_config.type == SUBVP_NONE && refresh_rate < 120 && !pipe->plane_state->address.tmz_surface && - vba->ActiveDRAMClockChangeLatencyMarginPerState[vba->VoltageLevel][vba->maxMpcComb][vba->pipe_plane[pipe_idx]] <= 0) { + (vba->ActiveDRAMClockChangeLatencyMarginPerState[vba->VoltageLevel][vba->maxMpcComb][vba->pipe_plane[pipe_idx]] <= 0 || + (vba->ActiveDRAMClockChangeLatencyMarginPerState[vba->VoltageLevel][vba->maxMpcComb][vba->pipe_plane[pipe_idx]] > 0 && + dcn32_allow_subvp_with_active_margin(pipe)))) { while (pipe) { num_pipes++; pipe = pipe->bottom_pipe; @@ -877,6 +880,10 @@ static bool subvp_drr_schedulable(struct dc *dc, struct dc_state *context, struc int16_t stretched_drr_us = 0; int16_t drr_stretched_vblank_us = 0; int16_t max_vblank_mallregion = 0; + const struct dc_config *config = &dc->config; + + if (config->disable_subvp_drr) + return false; // Find SubVP pipe for (i = 0; i < dc->res_pool->pipe_count; i++) { @@ -977,10 +984,12 @@ static bool subvp_vblank_schedulable(struct dc *dc, struct dc_state *context) if (!subvp_pipe && pipe->stream->mall_stream_config.type == SUBVP_MAIN) subvp_pipe = pipe; } - // Use ignore_msa_timing_param flag to identify as DRR - if (found && context->res_ctx.pipe_ctx[vblank_index].stream->ignore_msa_timing_param) { - // SUBVP + DRR case - schedulable = subvp_drr_schedulable(dc, context, &context->res_ctx.pipe_ctx[vblank_index]); + // Use ignore_msa_timing_param and VRR active, or Freesync flag to identify as DRR On + if (found && context->res_ctx.pipe_ctx[vblank_index].stream->ignore_msa_timing_param && + (context->res_ctx.pipe_ctx[vblank_index].stream->allow_freesync || + context->res_ctx.pipe_ctx[vblank_index].stream->vrr_active_variable)) { + // SUBVP + DRR case -- only allowed if run through DRR validation path + schedulable = false; } else if (found) { main_timing = &subvp_pipe->stream->timing; phantom_timing = &subvp_pipe->stream->mall_stream_config.paired_stream->timing; @@ -1084,12 +1093,12 @@ static void dcn32_full_validate_bw_helper(struct dc *dc, { struct vba_vars_st *vba = &context->bw_ctx.dml.vba; unsigned int dc_pipe_idx = 0; + int i = 0; bool found_supported_config = false; struct pipe_ctx *pipe = NULL; uint32_t non_subvp_pipes = 0; bool drr_pipe_found = false; uint32_t drr_pipe_index = 0; - uint32_t i = 0; dc_assert_fp_enabled(); @@ -1169,15 +1178,25 @@ static void dcn32_full_validate_bw_helper(struct dc *dc, pipes[0].clks_cfg.dppclk_mhz = get_dppclk_calculated(&context->bw_ctx.dml, pipes, *pipe_cnt, 0); *vlevel = dml_get_voltage_level(&context->bw_ctx.dml, pipes, *pipe_cnt); + /* Check that vlevel requested supports pstate or not + * if not, select the lowest vlevel that supports it + */ + for (i = *vlevel; i < context->bw_ctx.dml.soc.num_states; i++) { + if (vba->DRAMClockChangeSupport[i][vba->maxMpcComb] != dm_dram_clock_change_unsupported) { + *vlevel = i; + break; + } + } + if (*vlevel < context->bw_ctx.dml.soc.num_states && vba->DRAMClockChangeSupport[*vlevel][vba->maxMpcComb] != dm_dram_clock_change_unsupported && subvp_validate_static_schedulability(dc, context, *vlevel)) { found_supported_config = true; - } else if (*vlevel < context->bw_ctx.dml.soc.num_states && - vba->DRAMClockChangeSupport[*vlevel][vba->maxMpcComb] == dm_dram_clock_change_unsupported) { - /* Case where 1 SubVP is added, and DML reports MCLK unsupported. This handles - * the case for SubVP + DRR, where the DRR display does not support MCLK switch - * at it's native refresh rate / timing. + } else if (*vlevel < context->bw_ctx.dml.soc.num_states) { + /* Case where 1 SubVP is added, and DML reports MCLK unsupported or DRR is allowed. + * This handles the case for SubVP + DRR, where the DRR display does not support MCLK + * switch at it's native refresh rate / timing, or DRR is allowed for the non-subvp + * display. */ for (i = 0; i < dc->res_pool->pipe_count; i++) { pipe = &context->res_ctx.pipe_ctx[i]; @@ -1185,7 +1204,7 @@ static void dcn32_full_validate_bw_helper(struct dc *dc, pipe->stream->mall_stream_config.type == SUBVP_NONE) { non_subvp_pipes++; // Use ignore_msa_timing_param flag to identify as DRR - if (pipe->stream->ignore_msa_timing_param) { + if (pipe->stream->ignore_msa_timing_param && pipe->stream->allow_freesync) { drr_pipe_found = true; drr_pipe_index = i; } @@ -1194,6 +1213,15 @@ static void dcn32_full_validate_bw_helper(struct dc *dc, // If there is only 1 remaining non SubVP pipe that is DRR, check static // schedulability for SubVP + DRR. if (non_subvp_pipes == 1 && drr_pipe_found) { + /* find lowest vlevel that supports the config */ + for (i = *vlevel; i >= 0; i--) { + if (vba->ModeSupport[i][vba->maxMpcComb]) { + *vlevel = i; + } else { + break; + } + } + found_supported_config = subvp_drr_schedulable(dc, context, &context->res_ctx.pipe_ctx[drr_pipe_index]); } @@ -1242,12 +1270,44 @@ static bool is_dtbclk_required(struct dc *dc, struct dc_state *context) for (i = 0; i < dc->res_pool->pipe_count; i++) { if (!context->res_ctx.pipe_ctx[i].stream) continue; - if (is_dp_128b_132b_signal(&context->res_ctx.pipe_ctx[i])) + if (link_is_dp_128b_132b_signal(&context->res_ctx.pipe_ctx[i])) return true; } return false; } +static void dcn20_adjust_freesync_v_startup(const struct dc_crtc_timing *dc_crtc_timing, int *vstartup_start) +{ + struct dc_crtc_timing patched_crtc_timing; + uint32_t asic_blank_end = 0; + uint32_t asic_blank_start = 0; + uint32_t newVstartup = 0; + + patched_crtc_timing = *dc_crtc_timing; + + if (patched_crtc_timing.flags.INTERLACE == 1) { + if (patched_crtc_timing.v_front_porch < 2) + patched_crtc_timing.v_front_porch = 2; + } else { + if (patched_crtc_timing.v_front_porch < 1) + patched_crtc_timing.v_front_porch = 1; + } + + /* blank_start = frame end - front porch */ + asic_blank_start = patched_crtc_timing.v_total - + patched_crtc_timing.v_front_porch; + + /* blank_end = blank_start - active */ + asic_blank_end = asic_blank_start - + patched_crtc_timing.v_border_bottom - + patched_crtc_timing.v_addressable - + patched_crtc_timing.v_border_top; + + newVstartup = asic_blank_end + (patched_crtc_timing.v_total - asic_blank_start); + + *vstartup_start = ((newVstartup > *vstartup_start) ? newVstartup : *vstartup_start); +} + static void dcn32_calculate_dlg_params(struct dc *dc, struct dc_state *context, display_e2e_pipe_params_st *pipes, int pipe_cnt, int vlevel) @@ -1270,7 +1330,6 @@ static void dcn32_calculate_dlg_params(struct dc *dc, struct dc_state *context, context->bw_ctx.bw.dcn.clk.p_state_change_support = context->bw_ctx.dml.vba.DRAMClockChangeSupport[vlevel][context->bw_ctx.dml.vba.maxMpcComb] != dm_dram_clock_change_unsupported; - context->bw_ctx.bw.dcn.clk.num_ways = dcn32_helper_calculate_num_ways_for_subvp(dc, context); context->bw_ctx.bw.dcn.clk.dppclk_khz = 0; context->bw_ctx.bw.dcn.clk.dtbclk_en = is_dtbclk_required(dc, context); @@ -1294,6 +1353,10 @@ static void dcn32_calculate_dlg_params(struct dc *dc, struct dc_state *context, unbounded_req_enabled = false; } + context->bw_ctx.bw.dcn.mall_ss_size_bytes = 0; + context->bw_ctx.bw.dcn.mall_ss_psr_active_size_bytes = 0; + context->bw_ctx.bw.dcn.mall_subvp_size_bytes = 0; + for (i = 0, pipe_idx = 0; i < dc->res_pool->pipe_count; i++) { if (!context->res_ctx.pipe_ctx[i].stream) continue; @@ -1325,6 +1388,34 @@ static void dcn32_calculate_dlg_params(struct dc *dc, struct dc_state *context, else context->res_ctx.pipe_ctx[i].plane_res.bw.dppclk_khz = 0; context->res_ctx.pipe_ctx[i].pipe_dlg_param = pipes[pipe_idx].pipe.dest; + + context->res_ctx.pipe_ctx[i].surface_size_in_mall_bytes = get_surface_size_in_mall(&context->bw_ctx.dml, pipes, pipe_cnt, pipe_idx); + + /* MALL Allocation Sizes */ + /* count from active, top pipes per plane only */ + if (context->res_ctx.pipe_ctx[i].stream && context->res_ctx.pipe_ctx[i].plane_state && + (context->res_ctx.pipe_ctx[i].top_pipe == NULL || + context->res_ctx.pipe_ctx[i].plane_state != context->res_ctx.pipe_ctx[i].top_pipe->plane_state) && + context->res_ctx.pipe_ctx[i].prev_odm_pipe == NULL) { + /* SS: all active surfaces stored in MALL */ + if (context->res_ctx.pipe_ctx[i].stream->mall_stream_config.type != SUBVP_PHANTOM) { + context->bw_ctx.bw.dcn.mall_ss_size_bytes += context->res_ctx.pipe_ctx[i].surface_size_in_mall_bytes; + + if (context->res_ctx.pipe_ctx[i].stream->link->psr_settings.psr_version == DC_PSR_VERSION_UNSUPPORTED) { + /* SS PSR On: all active surfaces part of streams not supporting PSR stored in MALL */ + context->bw_ctx.bw.dcn.mall_ss_psr_active_size_bytes += context->res_ctx.pipe_ctx[i].surface_size_in_mall_bytes; + } + } else { + /* SUBVP: phantom surfaces only stored in MALL */ + context->bw_ctx.bw.dcn.mall_subvp_size_bytes += context->res_ctx.pipe_ctx[i].surface_size_in_mall_bytes; + } + } + + if (context->res_ctx.pipe_ctx[i].stream->adaptive_sync_infopacket.valid) + dcn20_adjust_freesync_v_startup( + &context->res_ctx.pipe_ctx[i].stream->timing, + &context->res_ctx.pipe_ctx[i].pipe_dlg_param.vstartup_start); + pipe_idx++; } /* If DCN isn't making memory requests we can allow pstate change and lower clocks */ @@ -1345,6 +1436,8 @@ static void dcn32_calculate_dlg_params(struct dc *dc, struct dc_state *context, context->bw_ctx.bw.dcn.clk.max_supported_dispclk_khz = context->bw_ctx.dml.soc.clock_limits[vlevel].dispclk_mhz * 1000; + context->bw_ctx.bw.dcn.clk.num_ways = dcn32_helper_calculate_num_ways_for_subvp(dc, context); + context->bw_ctx.bw.dcn.compbuf_size_kb = context->bw_ctx.dml.ip.config_return_buffer_size_in_kbytes; for (i = 0; i < dc->res_pool->pipe_count; i++) { @@ -1530,6 +1623,7 @@ bool dcn32_internal_validate_bw(struct dc *dc, } dml_log_pipe_params(&context->bw_ctx.dml, pipes, pipe_cnt); + context->bw_ctx.dml.soc.max_vratio_pre = dcn32_determine_max_vratio_prefetch(dc, context); if (!fast_validate) dcn32_full_validate_bw_helper(dc, context, pipes, &vlevel, split, merge, &pipe_cnt); @@ -1549,16 +1643,12 @@ bool dcn32_internal_validate_bw(struct dc *dc, * to support with Prefetch mode 1 (dm_prefetch_support_fclk_and_stutter == 2) */ context->bw_ctx.dml.soc.allow_for_pstate_or_stutter_in_vblank_final = - dm_prefetch_support_fclk_and_stutter; + dm_prefetch_support_none; + context->bw_ctx.dml.validate_max_state = fast_validate; vlevel = dml_get_voltage_level(&context->bw_ctx.dml, pipes, pipe_cnt); - /* Last attempt with Prefetch mode 2 (dm_prefetch_support_stutter == 3) */ - if (vlevel == context->bw_ctx.dml.soc.num_states) { - context->bw_ctx.dml.soc.allow_for_pstate_or_stutter_in_vblank_final = - dm_prefetch_support_stutter; - vlevel = dml_get_voltage_level(&context->bw_ctx.dml, pipes, pipe_cnt); - } + context->bw_ctx.dml.validate_max_state = false; if (vlevel < context->bw_ctx.dml.soc.num_states) { memset(split, 0, sizeof(split)); @@ -1645,6 +1735,7 @@ bool dcn32_internal_validate_bw(struct dc *dc, dcn20_release_dsc(&context->res_ctx, dc->res_pool, &pipe->stream_res.dsc); memset(&pipe->plane_res, 0, sizeof(pipe->plane_res)); memset(&pipe->stream_res, 0, sizeof(pipe->stream_res)); + memset(&pipe->link_res, 0, sizeof(pipe->link_res)); repopulate_pipes = true; } else if (pipe->top_pipe && pipe->top_pipe->plane_state == pipe->plane_state) { struct pipe_ctx *top_pipe = pipe->top_pipe; @@ -1660,6 +1751,7 @@ bool dcn32_internal_validate_bw(struct dc *dc, pipe->stream = NULL; memset(&pipe->plane_res, 0, sizeof(pipe->plane_res)); memset(&pipe->stream_res, 0, sizeof(pipe->stream_res)); + memset(&pipe->link_res, 0, sizeof(pipe->link_res)); repopulate_pipes = true; } else ASSERT(0); /* Should never try to merge master pipe */ @@ -1834,7 +1926,7 @@ void dcn32_calculate_wm_and_dlg_fpu(struct dc *dc, struct dc_state *context, bool subvp_in_use = dcn32_subvp_in_use(dc, context); unsigned int min_dram_speed_mts_margin; bool need_fclk_lat_as_dummy = false; - bool is_subvp_p_drr = true; + bool is_subvp_p_drr = false; dc_assert_fp_enabled(); @@ -1842,7 +1934,8 @@ void dcn32_calculate_wm_and_dlg_fpu(struct dc *dc, struct dc_state *context, if (subvp_in_use) { /* Override DRAMClockChangeSupport for SubVP + DRR case where the DRR cannot switch without stretching it's VBLANK */ if (!pstate_en) { - context->bw_ctx.dml.vba.DRAMClockChangeSupport[vlevel][context->bw_ctx.dml.vba.maxMpcComb] = dm_dram_clock_change_vblank_w_mall_sub_vp; + context->bw_ctx.dml.vba.DRAMClockChangeSupport[vlevel][maxMpcComb] = dm_dram_clock_change_vblank_w_mall_sub_vp; + context->bw_ctx.dml.soc.allow_for_pstate_or_stutter_in_vblank_final = dm_prefetch_support_fclk_and_stutter; pstate_en = true; is_subvp_p_drr = true; } @@ -1860,8 +1953,9 @@ void dcn32_calculate_wm_and_dlg_fpu(struct dc *dc, struct dc_state *context, context->bw_ctx.dml.soc.dram_clock_change_latency_us = dc->clk_mgr->bw_params->wm_table.nv_entries[WM_A].dml_input.pstate_latency_us; dcn32_internal_validate_bw(dc, context, pipes, &pipe_cnt, &vlevel, false); + maxMpcComb = context->bw_ctx.dml.vba.maxMpcComb; if (is_subvp_p_drr) { - context->bw_ctx.dml.vba.DRAMClockChangeSupport[vlevel][context->bw_ctx.dml.vba.maxMpcComb] = dm_dram_clock_change_vblank_w_mall_sub_vp; + context->bw_ctx.dml.vba.DRAMClockChangeSupport[vlevel][maxMpcComb] = dm_dram_clock_change_vblank_w_mall_sub_vp; } } @@ -2038,6 +2132,10 @@ void dcn32_calculate_wm_and_dlg_fpu(struct dc *dc, struct dc_state *context, */ context->bw_ctx.bw.dcn.watermarks.a = context->bw_ctx.bw.dcn.watermarks.c; context->bw_ctx.bw.dcn.watermarks.a.cstate_pstate.pstate_change_ns = 0; + /* Calculate FCLK p-state change watermark based on FCLK pstate change latency in case + * UCLK p-state is not supported, to avoid underflow in case FCLK pstate is supported + */ + context->bw_ctx.bw.dcn.watermarks.a.cstate_pstate.fclk_pstate_change_ns = get_fclk_watermark(&context->bw_ctx.dml, pipes, pipe_cnt) * 1000; } else { /* Set A: * All clocks min. @@ -2443,8 +2541,11 @@ void dcn32_update_bw_bounding_box_fpu(struct dc *dc, struct clk_bw_params *bw_pa } /* Override from VBIOS for num_chan */ - if (dc->ctx->dc_bios->vram_info.num_chans) + if (dc->ctx->dc_bios->vram_info.num_chans) { dcn3_2_soc.num_chans = dc->ctx->dc_bios->vram_info.num_chans; + dcn3_2_soc.mall_allocated_for_dcn_mbytes = (double)(dcn32_calc_num_avail_chans_for_mall(dc, + dc->ctx->dc_bios->vram_info.num_chans) * dc->caps.mall_size_per_mem_channel); + } if (dc->ctx->dc_bios->vram_info.dram_channel_width_bytes) dcn3_2_soc.dram_channel_width_bytes = dc->ctx->dc_bios->vram_info.dram_channel_width_bytes; @@ -2622,3 +2723,60 @@ void dcn32_zero_pipe_dcc_fraction(display_e2e_pipe_params_st *pipes, pipes[pipe_cnt].pipe.src.dcc_fraction_of_zs_req_luma = 0; pipes[pipe_cnt].pipe.src.dcc_fraction_of_zs_req_chroma = 0; } + +bool dcn32_allow_subvp_with_active_margin(struct pipe_ctx *pipe) +{ + bool allow = false; + uint32_t refresh_rate = 0; + + /* Allow subvp on displays that have active margin for 2560x1440@60hz displays + * only for now. There must be no scaling as well. + * + * For now we only enable on 2560x1440@60hz displays to enable 4K60 + 1440p60 configs + * for p-state switching. + */ + if (pipe->stream && pipe->plane_state) { + refresh_rate = (pipe->stream->timing.pix_clk_100hz * 100 + + pipe->stream->timing.v_total * pipe->stream->timing.h_total - 1) + / (double)(pipe->stream->timing.v_total * pipe->stream->timing.h_total); + if (pipe->stream->timing.v_addressable == 1440 && + pipe->stream->timing.h_addressable == 2560 && + refresh_rate >= 55 && refresh_rate <= 65 && + pipe->plane_state->src_rect.height == 1440 && + pipe->plane_state->src_rect.width == 2560 && + pipe->plane_state->dst_rect.height == 1440 && + pipe->plane_state->dst_rect.width == 2560) + allow = true; + } + return allow; +} + +/** + * ******************************************************************************************* + * dcn32_determine_max_vratio_prefetch: Determine max Vratio for prefetch by driver policy + * + * @param [in]: dc: Current DC state + * @param [in]: context: New DC state to be programmed + * + * @return: Max vratio for prefetch + * + * ******************************************************************************************* + */ +double dcn32_determine_max_vratio_prefetch(struct dc *dc, struct dc_state *context) +{ + double max_vratio_pre = __DML_MAX_BW_RATIO_PRE__; // Default value is 4 + int i; + + /* For single display MPO configs, allow the max vratio to be 8 + * if any plane is YUV420 format + */ + if (context->stream_count == 1 && context->stream_status[0].plane_count > 1) { + for (i = 0; i < context->stream_status[0].plane_count; i++) { + if (context->stream_status[0].plane_states[i]->format == SURFACE_PIXEL_FORMAT_VIDEO_420_YCbCr || + context->stream_status[0].plane_states[i]->format == SURFACE_PIXEL_FORMAT_VIDEO_420_YCrCb) { + max_vratio_pre = __DML_MAX_VRATIO_PRE__; + } + } + } + return max_vratio_pre; +} |