summaryrefslogtreecommitdiff
path: root/drivers/gpu/drm/amd/display
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2026-02-11 12:55:44 -0800
committerLinus Torvalds <torvalds@linux-foundation.org>2026-02-11 12:55:44 -0800
commit939faf71cf7ca9ab3d1bd2912ac0e203d4d7156a (patch)
treebf81a5b8c95c7095983719a3e0273a73dbe79c34 /drivers/gpu/drm/amd/display
parentb7ef56a07672e0d7ebe71c9d9b45f959f0c2f8e8 (diff)
parent2f5db9b4002470ea19380326c5a390647c56e780 (diff)
downloadlinux-next-939faf71cf7ca9ab3d1bd2912ac0e203d4d7156a.tar.gz
linux-next-939faf71cf7ca9ab3d1bd2912ac0e203d4d7156a.zip
Merge tag 'drm-next-2026-02-11' of https://gitlab.freedesktop.org/drm/kernel
Pull drm updates from Dave Airlie: "Highlights: - amdgpu support for lots of new IP blocks which means newer GPUs - xe has a lot of SR-IOV and SVM improvements - lots of intel display refactoring across i915/xe - msm has more support for gen8 platforms - Given up on kgdb/kms integration, it's too hard on modern hw core: - drop kgdb support - replace system workqueue with percpu - account for property blobs in memcg - MAINTAINERS updates for xe + buddy rust: - Fix documentation for Registration constructors - Use pin_init::zeroed() for fops initialization - Annotate DRM helpers with __rust_helper - Improve safety documentation for gem::Object::new() - Update AlwaysRefCounted imports - mm: Prevent integer overflow in page_align() atomic: - add drm_device pointer to drm_private_obj - introduce gamma/degamma LUT size check buddy: - fix free_trees memory leak - prevent BUG_ON bridge: - introduce drm_bridge_unplug/enter/exit - add connector argument to .hpd_notify - lots of recounting conversions - convert rockchip inno hdmi to bridge - lontium-lt9611uxc: switch to HDMI audio helpers - dw-hdmi-qp: add support for HPD-less setups - Algoltek AG6311 support panels: - edp: CSW MNE007QB3-1, AUO B140HAN06.4, AUO B140QAX01.H - st75751: add SPI support - Sitronix ST7920, Samsung LTL106HL02 - LG LH546WF1-ED01, HannStar HSD156J - BOE NV130WUM-T08 - Innolux G150XGE-L05 - Anbernic RG-DS dma-buf: - improve sg_table debugging - add tracepoints - call clear_page instead of memset - start to introduce cgroup memory accounting in heaps - remove sysfs stats dma-fence: - add new helpers dp: - mst: avoid oob access with vcpi=0 hdmi: - limit infoframes exposure to userspace gem: - reduce page table overhead with THP - fix leak in drm_gem_get_unmapped_area gpuvm: - API sanitation for rust bindings sched: - introduce new helpers panic: - report invalid panic modes - add kunit tests i915/xe display: - Expose sharpness only if num_scalers is >= 2 - Add initial Xe3P_LPD for NVL - BMG FBC support - Add MTL+ platforms to support dpll framework _ fix DIMM_S DRM decoding on ICL - Return to using AUX interrupts - PSR/Panel replay refactoring - use consolidation HDMI tables - Xe3_LPD CD2X dividier changes xe: - vfio: add vfio_pci for intel GPU - multi queue support - dynamic pagemaps and multi-device SVM - expose temp attribs in hwmon - NO_COMPRESSION bo flag - expose MERT OA unit - sysfs survivability refactor - SRIOV PF: add MERT support - enable SR-IOV VF migration - Enable I2C/NVM on Crescent Island - Xe3p page reclaimation support - introduce SRIOV scheduler groups - add SoC remappt support in system controller - insert compiler barriers in GuC code - define NVL GuC firmware - handle GT resume failure - fix drm scheduler layering violations - enable GSC loading and PXP for PTL - disable GuC Power DCC strategy on PTL - unregister drm device on probe error i915: - move to kernel standard fault injection - bump recommended GuC version for DG2 and MTL amdgpu: - SMUIO 15.x, PSP 15.x support - IH 6.1.1/7.1 support - MMHUB 3.4/4.2 support - GC 11.5.4/12.1 support - SDMA 6.1.4/7.1/7.11.4 support - JPEG 5.3 support - UserQ updates - GC 9 gfx queue reset support - TTM memory ops parallelization - convert legacy logging to new helpers - DC analog fixes amdkfd: - GC 11.5.4/12.1 suppport - SDMA 6.1.4/7.1 support - per context support - increase kfd process hash table - Reserved SDMA rework radeon: - convert legacy logging to new helpers - use devm for i2c adapters msm: - GPU - Document a612/RGMU dt bindings - UBWC 6.0 support (for A840 / Kaanapali) - a225 support - DPU: - Switch to use virtual planes by default - Fix DSI CMD panels on DPU 3.x - Rewrite format handling to remove intermediate representation - Fix watchdog on DPU 8.x+ - Fix TE / Vsync source setting on DPU 8.x+ - Add 3D_Mux on SC7280 - Kaanapali platform support - Fix UBWC register programming - Make RM reserve DSPP-enabled mixers for CRTCs with LMs - Gamma correction support - DP: - Enable support for eDP 1.4+ link rate tables - Fix MDSS1 DP indices on SA8775P, making them to work - Fix msm_dp_ctrl_config_msa() to work with LLVM 20 - DSI: - Document QCS8300 as compatible with SA8775P - Kaanapali platform support - DSI PHY: - switch to divider_determine_rate() - MDP5: - Drop support for MSM8998, SDM660 and SDM630 (switch over to DPU) - MDSS: - Kaanapali platform support - Fixed UBWC register programming nova-core: - Prepare for Turing support. This includes parsing and handling Turing-specific firmware headers and sections as well as a Turing Falcon HAL implementation - Get rid of the Result<impl PinInit<T, E>> anti-pattern - Relocate initializer-specific code into the appropriate initializer - Use CStr::from_bytes_until_nul() to remove custom helpers - Improve handling of unexpected firmware values - Clean up redundant debug prints - Replace c_str!() with native Rust C-string literals - Update nova-core task list nova: - Align GEM object size to system page size tyr: - Use generated uAPI bindings for GpuInfo - Replace manual sleeps with read_poll_timeout() - Replace c_str!() with native Rust C-string literals - Suppress warnings for unread fields - Fix incorrect register name in print statement nouveau: - fix big page table support races in PTE management - improve reclocking on tegra 186+ amdxdna: - fix suspend race conditions - improve handling of zero tail pointers - fix cu_idx overwritten during command setup - enable hardware context priority - remove NPU2 support - update message buffer allocation requirements - update firmware version check ast: - support imported cursor buffers - big endian fixes etnaviv: - add PPU flop reset support imagination: - add AM62P support - introduce hw version checks ivpu: - implement warm boot flow panfrost: - add bo sync ioctl - add GPU_PM_RT support for RZ/G3E SoC panthor: - add bo sync ioctl - enable timestamp propagation - scheduler robustness improvements - VM termination fixes - huge page support rockchip: - RK3368 HDMI Support - get rid of atomic_check fixups - RK3506 support - RK3576/RK3588 improved HPD handling rz-du: - RZ/V2H(P) MIPI-DSI Support v3d: - fix DMA segment size - convert to new logging helpers mediatek: - move DP training to hotplug thread - convert logging to new helpers - add support for HS speed DSI - Genio 510/700/1200-EVK, Radxa NIO-12L HDMI support atmel-hlcdc: - switch to drmm resource - support nomodeset - use newer helpers hisilicon: - fix various DP bugs renesas: - fix kernel panic on reboot exynos: - fix vidi_connection_ioctl using wrong device - fix vidi_connection deref user ptr - fix concurrency regression with vidi_context vkms: - add configfs support for display configuration * tag 'drm-next-2026-02-11' of https://gitlab.freedesktop.org/drm/kernel: (1610 commits) drm/xe/pm: Disable D3Cold for BMG only on specific platforms drm/xe: Fix kerneldoc for xe_tlb_inval_job_alloc_dep drm/xe: Fix kerneldoc for xe_gt_tlb_inval_init_early drm/xe: Fix kerneldoc for xe_migrate_exec_queue drm/xe/query: Fix topology query pointer advance drm/xe/guc: Fix kernel-doc warning in GuC scheduler ABI header drm/xe/guc: Fix CFI violation in debugfs access. accel/amdxdna: Move RPM resume into job run function accel/amdxdna: Fix incorrect DPM level after suspend/resume nouveau/vmm: start tracking if the LPT PTE is valid. (v6) nouveau/vmm: increase size of vmm pte tracker struct to u32 (v2) nouveau/vmm: rewrite pte tracker using a struct and bitfields. accel/amdxdna: Fix incorrect error code returned for failed chain command accel/amdxdna: Remove hardware context status drm/bridge: imx8qxp-pixel-combiner: Fix bailout for imx8qxp_pc_bridge_probe() drm/panel: ilitek-ili9882t: Remove duplicate initializers in tianma_il79900a_dsc drm/i915/display: fix the pixel normalization handling for xe3p_lpd drm/exynos: vidi: use ctx->lock to protect struct vidi_context member variables related to memory alloc/free drm/exynos: vidi: fix to avoid directly dereferencing user pointer drm/exynos: vidi: use priv->vidi_dev for ctx lookup in vidi_connection_ioctl() ...
Diffstat (limited to 'drivers/gpu/drm/amd/display')
-rw-r--r--drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c135
-rw-r--r--drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h19
-rw-r--r--drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_color.c3
-rw-r--r--drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_crc.c29
-rw-r--r--drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_debugfs.c73
-rw-r--r--drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_hdcp.c8
-rw-r--r--drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c6
-rw-r--r--drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_plane.c22
-rw-r--r--drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_replay.c9
-rw-r--r--drivers/gpu/drm/amd/display/amdgpu_dm/dc_fpu.h8
-rw-r--r--drivers/gpu/drm/amd/display/dc/clk_mgr/dcn314/dcn314_clk_mgr.c133
-rw-r--r--drivers/gpu/drm/amd/display/dc/clk_mgr/dcn314/dcn314_clk_mgr.h5
-rw-r--r--drivers/gpu/drm/amd/display/dc/clk_mgr/dcn315/dcn315_clk_mgr.c90
-rw-r--r--drivers/gpu/drm/amd/display/dc/clk_mgr/dcn315/dcn315_clk_mgr.h1
-rw-r--r--drivers/gpu/drm/amd/display/dc/clk_mgr/dcn35/dcn35_clk_mgr.c2
-rw-r--r--drivers/gpu/drm/amd/display/dc/core/dc.c648
-rw-r--r--drivers/gpu/drm/amd/display/dc/core/dc_hw_sequencer.c10
-rw-r--r--drivers/gpu/drm/amd/display/dc/core/dc_link_exports.c23
-rw-r--r--drivers/gpu/drm/amd/display/dc/core/dc_stream.c44
-rw-r--r--drivers/gpu/drm/amd/display/dc/dc.h95
-rw-r--r--drivers/gpu/drm/amd/display/dc/dc_dmub_srv.c54
-rw-r--r--drivers/gpu/drm/amd/display/dc/dc_dp_types.h35
-rw-r--r--drivers/gpu/drm/amd/display/dc/dc_hw_types.h6
-rw-r--r--drivers/gpu/drm/amd/display/dc/dc_stream.h31
-rw-r--r--drivers/gpu/drm/amd/display/dc/dc_types.h29
-rw-r--r--drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.c49
-rw-r--r--drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.h8
-rw-r--r--drivers/gpu/drm/amd/display/dc/dce/dmub_hw_lock_mgr.c2
-rw-r--r--drivers/gpu/drm/amd/display/dc/dce/dmub_replay.c13
-rw-r--r--drivers/gpu/drm/amd/display/dc/dcn201/dcn201_link_encoder.c3
-rw-r--r--drivers/gpu/drm/amd/display/dc/dcn21/dcn21_link_encoder.c3
-rw-r--r--drivers/gpu/drm/amd/display/dc/dio/dcn10/dcn10_link_encoder.c43
-rw-r--r--drivers/gpu/drm/amd/display/dc/dio/dcn10/dcn10_link_encoder.h11
-rw-r--r--drivers/gpu/drm/amd/display/dc/dio/dcn20/dcn20_link_encoder.c3
-rw-r--r--drivers/gpu/drm/amd/display/dc/dio/dcn30/dcn30_dio_link_encoder.c3
-rw-r--r--drivers/gpu/drm/amd/display/dc/dio/dcn301/dcn301_dio_link_encoder.c3
-rw-r--r--drivers/gpu/drm/amd/display/dc/dio/dcn31/dcn31_dio_link_encoder.c3
-rw-r--r--drivers/gpu/drm/amd/display/dc/dio/dcn32/dcn32_dio_link_encoder.c18
-rw-r--r--drivers/gpu/drm/amd/display/dc/dio/dcn321/dcn321_dio_link_encoder.c3
-rw-r--r--drivers/gpu/drm/amd/display/dc/dio/dcn35/dcn35_dio_link_encoder.c4
-rw-r--r--drivers/gpu/drm/amd/display/dc/dio/dcn401/dcn401_dio_link_encoder.c3
-rw-r--r--drivers/gpu/drm/amd/display/dc/dm_helpers.h1
-rw-r--r--drivers/gpu/drm/amd/display/dc/dml2_0/Makefile8
-rw-r--r--drivers/gpu/drm/amd/display/dc/dml2_0/dml21/dml21_utils.c3
-rw-r--r--drivers/gpu/drm/amd/display/dc/dml2_0/dml21/dml21_wrapper.h7
-rw-r--r--drivers/gpu/drm/amd/display/dc/dml2_0/dml21/inc/dml_top_display_cfg_types.h1
-rw-r--r--drivers/gpu/drm/amd/display/dc/dml2_0/dml21/inc/dml_top_types.h1
-rw-r--r--drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_core/dml2_core_dcn4_calcs.c5
-rw-r--r--drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_core/dml2_core_shared_types.h1
-rw-r--r--drivers/gpu/drm/amd/display/dc/dml2_0/dml2_wrapper.c599
-rw-r--r--drivers/gpu/drm/amd/display/dc/dml2_0/dml2_wrapper.h9
-rw-r--r--drivers/gpu/drm/amd/display/dc/dml2_0/dml2_wrapper_fpu.c604
-rw-r--r--drivers/gpu/drm/amd/display/dc/dml2_0/dml2_wrapper_fpu.h25
-rw-r--r--drivers/gpu/drm/amd/display/dc/dpp/dcn10/dcn10_dpp.h1
-rw-r--r--drivers/gpu/drm/amd/display/dc/dpp/dcn401/dcn401_dpp.h9
-rw-r--r--drivers/gpu/drm/amd/display/dc/dpp/dcn401/dcn401_dpp_dscl.c102
-rw-r--r--drivers/gpu/drm/amd/display/dc/dsc/dc_dsc.c2
-rw-r--r--drivers/gpu/drm/amd/display/dc/hubbub/dcn10/dcn10_hubbub.c18
-rw-r--r--drivers/gpu/drm/amd/display/dc/hubbub/dcn10/dcn10_hubbub.h10
-rw-r--r--drivers/gpu/drm/amd/display/dc/hubp/dcn401/dcn401_hubp.c14
-rw-r--r--drivers/gpu/drm/amd/display/dc/hwss/dce110/dce110_hwseq.c58
-rw-r--r--drivers/gpu/drm/amd/display/dc/hwss/dcn10/dcn10_hwseq.c11
-rw-r--r--drivers/gpu/drm/amd/display/dc/hwss/dcn10/dcn10_hwseq.h2
-rw-r--r--drivers/gpu/drm/amd/display/dc/hwss/dcn20/dcn20_hwseq.c18
-rw-r--r--drivers/gpu/drm/amd/display/dc/hwss/dcn201/dcn201_hwseq.c1
-rw-r--r--drivers/gpu/drm/amd/display/dc/hwss/dcn30/dcn30_hwseq.c1
-rw-r--r--drivers/gpu/drm/amd/display/dc/hwss/dcn30/dcn30_init.c1
-rw-r--r--drivers/gpu/drm/amd/display/dc/hwss/dcn301/dcn301_init.c1
-rw-r--r--drivers/gpu/drm/amd/display/dc/hwss/dcn31/dcn31_hwseq.c17
-rw-r--r--drivers/gpu/drm/amd/display/dc/hwss/dcn31/dcn31_init.c1
-rw-r--r--drivers/gpu/drm/amd/display/dc/hwss/dcn314/dcn314_hwseq.c2
-rw-r--r--drivers/gpu/drm/amd/display/dc/hwss/dcn314/dcn314_init.c1
-rw-r--r--drivers/gpu/drm/amd/display/dc/hwss/dcn32/dcn32_hwseq.c8
-rw-r--r--drivers/gpu/drm/amd/display/dc/hwss/dcn32/dcn32_init.c1
-rw-r--r--drivers/gpu/drm/amd/display/dc/hwss/dcn35/dcn35_hwseq.c56
-rw-r--r--drivers/gpu/drm/amd/display/dc/hwss/dcn35/dcn35_hwseq.h3
-rw-r--r--drivers/gpu/drm/amd/display/dc/hwss/dcn35/dcn35_init.c3
-rw-r--r--drivers/gpu/drm/amd/display/dc/hwss/dcn351/dcn351_init.c1
-rw-r--r--drivers/gpu/drm/amd/display/dc/hwss/dcn401/dcn401_hwseq.c28
-rw-r--r--drivers/gpu/drm/amd/display/dc/hwss/dcn401/dcn401_init.c1
-rw-r--r--drivers/gpu/drm/amd/display/dc/hwss/hw_sequencer.h13
-rw-r--r--drivers/gpu/drm/amd/display/dc/inc/core_types.h8
-rw-r--r--drivers/gpu/drm/amd/display/dc/inc/hw/dccg.h1
-rw-r--r--drivers/gpu/drm/amd/display/dc/inc/hw/dchubbub.h28
-rw-r--r--drivers/gpu/drm/amd/display/dc/inc/hw/link_encoder.h6
-rw-r--r--drivers/gpu/drm/amd/display/dc/inc/link_service.h11
-rw-r--r--drivers/gpu/drm/amd/display/dc/link/Makefile2
-rw-r--r--drivers/gpu/drm/amd/display/dc/link/accessories/link_dp_cts.c3
-rw-r--r--drivers/gpu/drm/amd/display/dc/link/link_detection.c79
-rw-r--r--drivers/gpu/drm/amd/display/dc/link/link_dpms.c141
-rw-r--r--drivers/gpu/drm/amd/display/dc/link/link_factory.c264
-rw-r--r--drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_capability.c54
-rw-r--r--drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_irq_handler.c43
-rw-r--r--drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_panel_replay.c353
-rw-r--r--drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_panel_replay.h38
-rw-r--r--drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_training_fixed_vs_pe_retimer.c2
-rw-r--r--drivers/gpu/drm/amd/display/dc/link/protocols/link_edp_panel_control.c147
-rw-r--r--drivers/gpu/drm/amd/display/dc/link/protocols/link_edp_panel_control.h3
-rw-r--r--drivers/gpu/drm/amd/display/dc/link/protocols/link_hpd.c165
-rw-r--r--drivers/gpu/drm/amd/display/dc/link/protocols/link_hpd.h1
-rw-r--r--drivers/gpu/drm/amd/display/dc/os_types.h2
-rw-r--r--drivers/gpu/drm/amd/display/dc/resource/dce110/dce110_resource.c2
-rw-r--r--drivers/gpu/drm/amd/display/dc/resource/dcn20/dcn20_resource.c8
-rw-r--r--drivers/gpu/drm/amd/display/dc/resource/dcn21/dcn21_resource.c2
-rw-r--r--drivers/gpu/drm/amd/display/dc/resource/dcn31/dcn31_resource.c11
-rw-r--r--drivers/gpu/drm/amd/display/dc/resource/dcn32/dcn32_resource.h5
-rw-r--r--drivers/gpu/drm/amd/display/dc/resource/dcn35/dcn35_resource.c2
-rw-r--r--drivers/gpu/drm/amd/display/dc/resource/dcn351/dcn351_resource.c2
-rw-r--r--drivers/gpu/drm/amd/display/dc/resource/dcn401/dcn401_resource.c2
-rw-r--r--drivers/gpu/drm/amd/display/dc/resource/dcn401/dcn401_resource.h3
-rw-r--r--drivers/gpu/drm/amd/display/dc/sspl/dc_spl.c189
-rw-r--r--drivers/gpu/drm/amd/display/dc/sspl/dc_spl.h8
-rw-r--r--drivers/gpu/drm/amd/display/dc/sspl/dc_spl_filters.c4
-rw-r--r--drivers/gpu/drm/amd/display/dc/sspl/dc_spl_filters.h4
-rw-r--r--drivers/gpu/drm/amd/display/dc/sspl/dc_spl_isharp_filters.c31
-rw-r--r--drivers/gpu/drm/amd/display/dc/sspl/dc_spl_isharp_filters.h16
-rw-r--r--drivers/gpu/drm/amd/display/dc/sspl/dc_spl_scl_easf_filters.c155
-rw-r--r--drivers/gpu/drm/amd/display/dc/sspl/dc_spl_scl_easf_filters.h37
-rw-r--r--drivers/gpu/drm/amd/display/dc/sspl/dc_spl_scl_filters.c27
-rw-r--r--drivers/gpu/drm/amd/display/dc/sspl/dc_spl_scl_filters.h3
-rw-r--r--drivers/gpu/drm/amd/display/dc/sspl/spl_custom_float.c11
-rw-r--r--drivers/gpu/drm/amd/display/dc/sspl/spl_custom_float.h4
-rw-r--r--drivers/gpu/drm/amd/display/dc/sspl/spl_fixpt31_32.c78
-rw-r--r--drivers/gpu/drm/amd/display/dc/sspl/spl_fixpt31_32.h56
-rw-r--r--drivers/gpu/drm/amd/display/dc/sspl/spl_os_types.h9
-rw-r--r--drivers/gpu/drm/amd/display/dmub/dmub_srv.h49
-rw-r--r--drivers/gpu/drm/amd/display/dmub/inc/dmub_cmd.h190
-rw-r--r--drivers/gpu/drm/amd/display/dmub/src/dmub_dcn20.c6
-rw-r--r--drivers/gpu/drm/amd/display/dmub/src/dmub_dcn30.c6
-rw-r--r--drivers/gpu/drm/amd/display/dmub/src/dmub_dcn31.c6
-rw-r--r--drivers/gpu/drm/amd/display/dmub/src/dmub_dcn32.c6
-rw-r--r--drivers/gpu/drm/amd/display/dmub/src/dmub_dcn35.c9
-rw-r--r--drivers/gpu/drm/amd/display/dmub/src/dmub_dcn401.c6
-rw-r--r--drivers/gpu/drm/amd/display/dmub/src/dmub_srv.c64
-rw-r--r--drivers/gpu/drm/amd/display/include/dpcd_defs.h32
-rw-r--r--drivers/gpu/drm/amd/display/modules/inc/mod_info_packet.h6
-rw-r--r--drivers/gpu/drm/amd/display/modules/info_packet/info_packet.c369
-rw-r--r--drivers/gpu/drm/amd/display/modules/power/power_helpers.c8
138 files changed, 3785 insertions, 2330 deletions
diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
index a8a59126b2d2..0b4fc654e76f 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
@@ -152,12 +152,6 @@ MODULE_FIRMWARE(FIRMWARE_DCN_36_DMUB);
#define FIRMWARE_DCN_401_DMUB "amdgpu/dcn_4_0_1_dmcub.bin"
MODULE_FIRMWARE(FIRMWARE_DCN_401_DMUB);
-/* Number of bytes in PSP header for firmware. */
-#define PSP_HEADER_BYTES 0x100
-
-/* Number of bytes in PSP footer for firmware. */
-#define PSP_FOOTER_BYTES 0x100
-
/**
* DOC: overview
*
@@ -1143,7 +1137,7 @@ static int amdgpu_dm_audio_component_get_eld(struct device *kdev, int port,
mutex_unlock(&adev->dm.audio_lock);
- DRM_DEBUG_KMS("Get ELD : idx=%d ret=%d en=%d\n", port, ret, *enabled);
+ drm_dbg_kms(adev_to_drm(adev), "Get ELD : idx=%d ret=%d en=%d\n", port, ret, *enabled);
return ret;
}
@@ -1237,7 +1231,7 @@ static void amdgpu_dm_audio_eld_notify(struct amdgpu_device *adev, int pin)
struct drm_audio_component *acomp = adev->dm.audio_component;
if (acomp && acomp->audio_ops && acomp->audio_ops->pin_eld_notify) {
- DRM_DEBUG_KMS("Notify ELD: %d\n", pin);
+ drm_dbg_kms(adev_to_drm(adev), "Notify ELD: %d\n", pin);
acomp->audio_ops->pin_eld_notify(acomp->audio_ops->audio_ptr,
pin, -1);
@@ -1298,15 +1292,14 @@ static int dm_dmub_hw_init(struct amdgpu_device *adev)
fw_inst_const = dmub_fw->data +
le32_to_cpu(hdr->header.ucode_array_offset_bytes) +
- PSP_HEADER_BYTES;
+ PSP_HEADER_BYTES_256;
fw_bss_data = dmub_fw->data +
le32_to_cpu(hdr->header.ucode_array_offset_bytes) +
le32_to_cpu(hdr->inst_const_bytes);
/* Copy firmware and bios info into FB memory. */
- fw_inst_const_size = le32_to_cpu(hdr->inst_const_bytes) -
- PSP_HEADER_BYTES - PSP_FOOTER_BYTES;
+ fw_inst_const_size = adev->dm.fw_inst_size;
fw_bss_data_size = le32_to_cpu(hdr->bss_data_bytes);
@@ -1343,8 +1336,8 @@ static int dm_dmub_hw_init(struct amdgpu_device *adev)
/* Initialize hardware. */
memset(&hw_params, 0, sizeof(hw_params));
- hw_params.fb_base = adev->gmc.fb_start;
- hw_params.fb_offset = adev->vm_manager.vram_base_offset;
+ hw_params.soc_fb_info.fb_base = adev->gmc.fb_start;
+ hw_params.soc_fb_info.fb_offset = adev->vm_manager.vram_base_offset;
/* backdoor load firmware and trigger dmub running */
if (adev->firmware.load_type != AMDGPU_FW_LOAD_PSP)
@@ -2105,7 +2098,7 @@ static int amdgpu_dm_init(struct amdgpu_device *adev)
drm_err(adev_to_drm(adev),
"failed to initialize freesync_module.\n");
} else
- drm_dbg_driver(adev_to_drm(adev), "amdgpu: freesync_module init done %p.\n",
+ drm_dbg_driver(adev_to_drm(adev), "freesync_module init done %p.\n",
adev->dm.freesync_module);
amdgpu_dm_init_color_mod();
@@ -2127,7 +2120,9 @@ static int amdgpu_dm_init(struct amdgpu_device *adev)
if (!adev->dm.hdcp_workqueue)
drm_err(adev_to_drm(adev), "failed to initialize hdcp_workqueue.\n");
else
- drm_dbg_driver(adev_to_drm(adev), "amdgpu: hdcp_workqueue init done %p.\n", adev->dm.hdcp_workqueue);
+ drm_dbg_driver(adev_to_drm(adev),
+ "hdcp_workqueue init done %p.\n",
+ adev->dm.hdcp_workqueue);
dc_init_callbacks(adev->dm.dc, &init_params);
}
@@ -2382,7 +2377,7 @@ static int load_dmcu_fw(struct amdgpu_device *adev)
}
if (adev->firmware.load_type != AMDGPU_FW_LOAD_PSP) {
- DRM_DEBUG_KMS("dm: DMCU firmware not supported on direct or SMU loading\n");
+ drm_dbg_kms(adev_to_drm(adev), "dm: DMCU firmware not supported on direct or SMU loading\n");
return 0;
}
@@ -2390,7 +2385,7 @@ static int load_dmcu_fw(struct amdgpu_device *adev)
"%s", fw_name_dmcu);
if (r == -ENODEV) {
/* DMCU firmware is not necessary, so don't raise a fuss if it's missing */
- DRM_DEBUG_KMS("dm: DMCU firmware not found\n");
+ drm_dbg_kms(adev_to_drm(adev), "dm: DMCU firmware not found\n");
adev->dm.fw_dmcu = NULL;
return 0;
}
@@ -2414,7 +2409,7 @@ static int load_dmcu_fw(struct amdgpu_device *adev)
adev->dm.dmcu_fw_version = le32_to_cpu(hdr->header.ucode_version);
- DRM_DEBUG_KMS("PSP loading DMCU firmware\n");
+ drm_dbg_kms(adev_to_drm(adev), "PSP loading DMCU firmware\n");
return 0;
}
@@ -2437,9 +2432,11 @@ static void amdgpu_dm_dmub_reg_write(void *ctx, uint32_t address,
static int dm_dmub_sw_init(struct amdgpu_device *adev)
{
struct dmub_srv_create_params create_params;
+ struct dmub_srv_fw_meta_info_params fw_meta_info_params;
struct dmub_srv_region_params region_params;
struct dmub_srv_region_info region_info;
struct dmub_srv_memory_params memory_params;
+ struct dmub_fw_meta_info fw_info;
struct dmub_srv_fb_info *fb_info;
struct dmub_srv *dmub_srv;
const struct dmcub_firmware_header_v1_0 *hdr;
@@ -2547,22 +2544,37 @@ static int dm_dmub_sw_init(struct amdgpu_device *adev)
return -EINVAL;
}
+ /* Extract the FW meta info. */
+ memset(&fw_meta_info_params, 0, sizeof(fw_meta_info_params));
+
+ fw_meta_info_params.inst_const_size = le32_to_cpu(hdr->inst_const_bytes) -
+ PSP_HEADER_BYTES_256;
+ fw_meta_info_params.bss_data_size = le32_to_cpu(hdr->bss_data_bytes);
+ fw_meta_info_params.fw_inst_const = adev->dm.dmub_fw->data +
+ le32_to_cpu(hdr->header.ucode_array_offset_bytes) +
+ PSP_HEADER_BYTES_256;
+ fw_meta_info_params.fw_bss_data = region_params.bss_data_size ? adev->dm.dmub_fw->data +
+ le32_to_cpu(hdr->header.ucode_array_offset_bytes) +
+ le32_to_cpu(hdr->inst_const_bytes) : NULL;
+ fw_meta_info_params.custom_psp_footer_size = 0;
+
+ status = dmub_srv_get_fw_meta_info_from_raw_fw(&fw_meta_info_params, &fw_info);
+ if (status != DMUB_STATUS_OK) {
+ /* Skip returning early, just log the error. */
+ drm_err(adev_to_drm(adev), "Error getting DMUB FW meta info: %d\n", status);
+ // return -EINVAL;
+ }
+
/* Calculate the size of all the regions for the DMUB service. */
memset(&region_params, 0, sizeof(region_params));
- region_params.inst_const_size = le32_to_cpu(hdr->inst_const_bytes) -
- PSP_HEADER_BYTES - PSP_FOOTER_BYTES;
- region_params.bss_data_size = le32_to_cpu(hdr->bss_data_bytes);
+ region_params.inst_const_size = fw_meta_info_params.inst_const_size;
+ region_params.bss_data_size = fw_meta_info_params.bss_data_size;
region_params.vbios_size = adev->bios_size;
- region_params.fw_bss_data = region_params.bss_data_size ?
- adev->dm.dmub_fw->data +
- le32_to_cpu(hdr->header.ucode_array_offset_bytes) +
- le32_to_cpu(hdr->inst_const_bytes) : NULL;
- region_params.fw_inst_const =
- adev->dm.dmub_fw->data +
- le32_to_cpu(hdr->header.ucode_array_offset_bytes) +
- PSP_HEADER_BYTES;
+ region_params.fw_bss_data = fw_meta_info_params.fw_bss_data;
+ region_params.fw_inst_const = fw_meta_info_params.fw_inst_const;
region_params.window_memory_type = window_memory_type;
+ region_params.fw_info = (status == DMUB_STATUS_OK) ? &fw_info : NULL;
status = dmub_srv_calc_region_info(dmub_srv, &region_params,
&region_info);
@@ -2609,6 +2621,7 @@ static int dm_dmub_sw_init(struct amdgpu_device *adev)
}
adev->dm.bb_from_dmub = dm_dmub_get_vbios_bounding_box(adev);
+ adev->dm.fw_inst_size = fw_meta_info_params.inst_const_size;
return 0;
}
@@ -4144,7 +4157,7 @@ static void schedule_hpd_rx_offload_work(struct amdgpu_device *adev, struct hpd_
offload_work->adev = adev;
queue_work(offload_wq->wq, &offload_work->work);
- DRM_DEBUG_KMS("queue work to handle hpd_rx offload work");
+ drm_dbg_kms(adev_to_drm(adev), "queue work to handle hpd_rx offload work");
}
static void handle_hpd_rx_irq(void *param)
@@ -4973,7 +4986,7 @@ static void amdgpu_dm_update_backlight_caps(struct amdgpu_display_manager *dm,
caps->min_input_signal < 0 ||
spread > AMDGPU_DM_DEFAULT_MAX_BACKLIGHT ||
spread < AMDGPU_DM_MIN_SPREAD) {
- DRM_DEBUG_KMS("DM: Invalid backlight caps: min=%d, max=%d\n",
+ drm_dbg_kms(adev_to_drm(dm->adev), "DM: Invalid backlight caps: min=%d, max=%d\n",
caps->min_input_signal, caps->max_input_signal);
caps->caps_valid = false;
}
@@ -5518,7 +5531,7 @@ static int amdgpu_dm_initialize_drm_device(struct amdgpu_device *adev)
}
break;
default:
- DRM_DEBUG_KMS("Unsupported DCN IP version for outbox: 0x%X\n",
+ drm_dbg_kms(adev_to_drm(adev), "Unsupported DCN IP version for outbox: 0x%X\n",
amdgpu_ip_version(adev, DCE_HWIP, 0));
}
@@ -6421,7 +6434,8 @@ ffu:
&flip_addrs->dirty_rect_count, true);
}
-static void update_stream_scaling_settings(const struct drm_display_mode *mode,
+static void update_stream_scaling_settings(struct drm_device *dev,
+ const struct drm_display_mode *mode,
const struct dm_connector_state *dm_state,
struct dc_stream_state *stream)
{
@@ -6471,8 +6485,8 @@ static void update_stream_scaling_settings(const struct drm_display_mode *mode,
stream->src = src;
stream->dst = dst;
- DRM_DEBUG_KMS("Destination Rectangle x:%d y:%d width:%d height:%d\n",
- dst.x, dst.y, dst.width, dst.height);
+ drm_dbg_kms(dev, "Destination Rectangle x:%d y:%d width:%d height:%d\n",
+ dst.x, dst.y, dst.width, dst.height);
}
@@ -7360,7 +7374,7 @@ create_stream_for_sink(struct drm_connector *connector,
apply_dsc_policy_for_stream(aconnector, sink, stream, &dsc_caps);
#endif
- update_stream_scaling_settings(&mode, dm_state, stream);
+ update_stream_scaling_settings(dev, &mode, dm_state, stream);
fill_audio_info(
&stream->audio_info,
@@ -7434,7 +7448,7 @@ amdgpu_dm_connector_poll(struct amdgpu_dm_connector *aconnector, bool force)
*
* Only allow to poll such a connector again when forcing.
*/
- if (!force && link->local_sink && link->type == dc_connection_dac_load)
+ if (!force && link->local_sink && link->type == dc_connection_analog_load)
return connector->status;
mutex_lock(&aconnector->hpd_lock);
@@ -8097,7 +8111,7 @@ create_validate_stream_for_sink(struct drm_connector *connector,
dc_result = dm_validate_stream_and_context(adev->dm.dc, stream);
if (dc_result != DC_OK) {
- DRM_DEBUG_KMS("Pruned mode %d x %d (clk %d) %s %s -- %s\n",
+ drm_dbg_kms(connector->dev, "Pruned mode %d x %d (clk %d) %s %s -- %s\n",
drm_mode->hdisplay,
drm_mode->vdisplay,
drm_mode->clock,
@@ -8449,7 +8463,7 @@ static int dm_encoder_helper_atomic_check(struct drm_encoder *encoder,
drm_dp_atomic_find_time_slots(state, mst_mgr, mst_port,
dm_new_connector_state->pbn);
if (dm_new_connector_state->vcpi_slots < 0) {
- DRM_DEBUG_ATOMIC("failed finding vcpi slots: %d\n", (int)dm_new_connector_state->vcpi_slots);
+ drm_dbg_atomic(connector->dev, "failed finding vcpi slots: %d\n", (int)dm_new_connector_state->vcpi_slots);
return dm_new_connector_state->vcpi_slots;
}
return 0;
@@ -9642,7 +9656,7 @@ static void update_freesync_state_on_stream(
new_stream->allow_freesync = mod_freesync_get_freesync_enabled(&vrr_params);
if (new_crtc_state->freesync_vrr_info_changed)
- DRM_DEBUG_KMS("VRR packet update: crtc=%u enabled=%d state=%d",
+ drm_dbg_kms(adev_to_drm(adev), "VRR packet update: crtc=%u enabled=%d state=%d",
new_crtc_state->base.crtc->base.id,
(int)new_crtc_state->base.vrr_enabled,
(int)vrr_params.state);
@@ -10908,7 +10922,7 @@ static void amdgpu_dm_atomic_commit_tail(struct drm_atomic_state *state)
stream_update.stream = dm_new_crtc_state->stream;
if (scaling_changed) {
- update_stream_scaling_settings(&dm_new_con_state->base.crtc->mode,
+ update_stream_scaling_settings(dev, &dm_new_con_state->base.crtc->mode,
dm_new_con_state, dm_new_crtc_state->stream);
stream_update.src = dm_new_crtc_state->stream->src;
@@ -11588,7 +11602,7 @@ static int dm_update_crtc_state(struct amdgpu_display_manager *dm,
dc_stream_retain(new_stream);
- DRM_DEBUG_ATOMIC("Enabling DRM crtc: %d\n",
+ drm_dbg_atomic(adev_to_drm(adev), "Enabling DRM crtc: %d\n",
crtc->base.id);
if (dc_state_add_stream(
@@ -11627,7 +11641,7 @@ skip_modeset:
/* Scaling or underscan settings */
if (is_scaling_state_different(dm_old_conn_state, dm_new_conn_state) ||
drm_atomic_crtc_needs_modeset(new_crtc_state))
- update_stream_scaling_settings(
+ update_stream_scaling_settings(adev_to_drm(adev),
&new_crtc_state->mode, dm_new_conn_state, dm_new_crtc_state->stream);
/* ABM settings */
@@ -11818,14 +11832,14 @@ static int dm_check_cursor_fb(struct amdgpu_crtc *new_acrtc,
if (fb->width > new_acrtc->max_cursor_width ||
fb->height > new_acrtc->max_cursor_height) {
- DRM_DEBUG_ATOMIC("Bad cursor FB size %dx%d\n",
+ drm_dbg_atomic(adev_to_drm(adev), "Bad cursor FB size %dx%d\n",
new_plane_state->fb->width,
new_plane_state->fb->height);
return -EINVAL;
}
if (new_plane_state->src_w != fb->width << 16 ||
new_plane_state->src_h != fb->height << 16) {
- DRM_DEBUG_ATOMIC("Cropping not supported for cursor plane\n");
+ drm_dbg_atomic(adev_to_drm(adev), "Cropping not supported for cursor plane\n");
return -EINVAL;
}
@@ -11833,7 +11847,7 @@ static int dm_check_cursor_fb(struct amdgpu_crtc *new_acrtc,
pitch = fb->pitches[0] / fb->format->cpp[0];
if (fb->width != pitch) {
- DRM_DEBUG_ATOMIC("Cursor FB width %d doesn't match pitch %d",
+ drm_dbg_atomic(adev_to_drm(adev), "Cursor FB width %d doesn't match pitch %d",
fb->width, pitch);
return -EINVAL;
}
@@ -11845,7 +11859,7 @@ static int dm_check_cursor_fb(struct amdgpu_crtc *new_acrtc,
/* FB pitch is supported by cursor plane */
break;
default:
- DRM_DEBUG_ATOMIC("Bad cursor FB pitch %d px\n", pitch);
+ drm_dbg_atomic(adev_to_drm(adev), "Bad cursor FB pitch %d px\n", pitch);
return -EINVAL;
}
@@ -11853,7 +11867,7 @@ static int dm_check_cursor_fb(struct amdgpu_crtc *new_acrtc,
* check tiling flags when the FB doesn't have a modifier.
*/
if (!(fb->flags & DRM_MODE_FB_MODIFIERS)) {
- if (adev->family >= AMDGPU_FAMILY_GC_12_0_0) {
+ if (adev->family == AMDGPU_FAMILY_GC_12_0_0) {
linear = AMDGPU_TILING_GET(afb->tiling_flags, GFX12_SWIZZLE_MODE) == 0;
} else if (adev->family >= AMDGPU_FAMILY_AI) {
linear = AMDGPU_TILING_GET(afb->tiling_flags, SWIZZLE_MODE) == 0;
@@ -11863,7 +11877,7 @@ static int dm_check_cursor_fb(struct amdgpu_crtc *new_acrtc,
AMDGPU_TILING_GET(afb->tiling_flags, MICRO_TILE_MODE) == 0;
}
if (!linear) {
- DRM_DEBUG_ATOMIC("Cursor FB not linear");
+ drm_dbg_atomic(adev_to_drm(adev), "Cursor FB not linear");
return -EINVAL;
}
}
@@ -11890,7 +11904,7 @@ static int dm_check_native_cursor_state(struct drm_crtc *new_plane_crtc,
new_acrtc = to_amdgpu_crtc(new_plane_crtc);
if (new_plane_state->src_x != 0 || new_plane_state->src_y != 0) {
- DRM_DEBUG_ATOMIC("Cropping not supported for cursor plane\n");
+ drm_dbg_atomic(new_plane_crtc->dev, "Cropping not supported for cursor plane\n");
return -EINVAL;
}
@@ -11989,7 +12003,7 @@ static int dm_update_plane_state(struct dc *dc,
if (!dm_old_crtc_state->stream)
return 0;
- DRM_DEBUG_ATOMIC("Disabling DRM plane: %d on DRM crtc %d\n",
+ drm_dbg_atomic(old_plane_crtc->dev, "Disabling DRM plane: %d on DRM crtc %d\n",
plane->base.id, old_plane_crtc->base.id);
ret = dm_atomic_get_state(state, &dm_state);
@@ -12042,7 +12056,7 @@ static int dm_update_plane_state(struct dc *dc,
goto out;
}
- DRM_DEBUG_ATOMIC("Enabling DRM plane: %d on DRM crtc %d\n",
+ drm_dbg_atomic(new_plane_crtc->dev, "Enabling DRM plane: %d on DRM crtc %d\n",
plane->base.id, new_plane_crtc->base.id);
ret = fill_dc_plane_attributes(
@@ -13132,9 +13146,24 @@ static int parse_amd_vsdb(struct amdgpu_dm_connector *aconnector,
if (ieeeId == HDMI_AMD_VENDOR_SPECIFIC_DATA_BLOCK_IEEE_REGISTRATION_ID &&
amd_vsdb->version == HDMI_AMD_VENDOR_SPECIFIC_DATA_BLOCK_VERSION_3) {
+ u8 panel_type;
vsdb_info->replay_mode = (amd_vsdb->feature_caps & AMD_VSDB_VERSION_3_FEATURECAP_REPLAYMODE) ? true : false;
vsdb_info->amd_vsdb_version = HDMI_AMD_VENDOR_SPECIFIC_DATA_BLOCK_VERSION_3;
- DRM_DEBUG_KMS("Panel supports Replay Mode: %d\n", vsdb_info->replay_mode);
+ drm_dbg_kms(aconnector->base.dev, "Panel supports Replay Mode: %d\n", vsdb_info->replay_mode);
+ panel_type = (amd_vsdb->color_space_eotf_support & AMD_VDSB_VERSION_3_PANEL_TYPE_MASK) >> AMD_VDSB_VERSION_3_PANEL_TYPE_SHIFT;
+ switch (panel_type) {
+ case AMD_VSDB_PANEL_TYPE_OLED:
+ aconnector->dc_link->panel_type = PANEL_TYPE_OLED;
+ break;
+ case AMD_VSDB_PANEL_TYPE_MINILED:
+ aconnector->dc_link->panel_type = PANEL_TYPE_MINILED;
+ break;
+ default:
+ aconnector->dc_link->panel_type = PANEL_TYPE_NONE;
+ break;
+ }
+ drm_dbg_kms(aconnector->base.dev, "Panel type: %d\n",
+ aconnector->dc_link->panel_type);
return true;
}
diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h
index beb0d04d3e68..800813671748 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h
@@ -55,8 +55,17 @@
#define HDMI_AMD_VENDOR_SPECIFIC_DATA_BLOCK_IEEE_REGISTRATION_ID 0x00001A
#define AMD_VSDB_VERSION_3_FEATURECAP_REPLAYMODE 0x40
+#define AMD_VDSB_VERSION_3_PANEL_TYPE_MASK 0xC0
+#define AMD_VDSB_VERSION_3_PANEL_TYPE_SHIFT 6
#define HDMI_AMD_VENDOR_SPECIFIC_DATA_BLOCK_VERSION_3 0x3
+enum amd_vsdb_panel_type {
+ AMD_VSDB_PANEL_TYPE_DEFAULT = 0,
+ AMD_VSDB_PANEL_TYPE_MINILED,
+ AMD_VSDB_PANEL_TYPE_OLED,
+ AMD_VSDB_PANEL_TYPE_RESERVED,
+};
+
#define AMDGPU_HDR_MULT_DEFAULT (0x100000000LL)
/*
@@ -92,6 +101,8 @@ struct amd_vsdb_block {
unsigned char ieee_id[3];
unsigned char version;
unsigned char feature_caps;
+ unsigned char reserved[3];
+ unsigned char color_space_eotf_support;
};
struct common_irq_params {
@@ -417,6 +428,13 @@ struct amdgpu_display_manager {
uint32_t dmcub_fw_version;
/**
+ * @fw_inst_size:
+ *
+ * Size of the firmware instruction buffer.
+ */
+ uint32_t fw_inst_size;
+
+ /**
* @cgs_device:
*
* The Common Graphics Services device. It provides an interface for
@@ -811,6 +829,7 @@ struct amdgpu_dm_connector {
int sr_skip_count;
bool disallow_edp_enter_psr;
+ bool disallow_edp_enter_replay;
/* Record progress status of mst*/
uint8_t mst_status;
diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_color.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_color.c
index 1dcc79b35225..20a76d81d532 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_color.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_color.c
@@ -23,6 +23,9 @@
* Authors: AMD
*
*/
+
+#include <drm/drm_colorop.h>
+
#include "amdgpu.h"
#include "amdgpu_mode.h"
#include "amdgpu_dm.h"
diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_crc.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_crc.c
index e20aa7438066..5851f2d55dde 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_crc.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_crc.c
@@ -32,6 +32,7 @@
#include "dc.h"
#include "amdgpu_securedisplay.h"
#include "amdgpu_dm_psr.h"
+#include "amdgpu_dm_replay.h"
static const char *const pipe_crc_sources[] = {
"none",
@@ -105,7 +106,9 @@ static void update_phy_id_mapping(struct amdgpu_device *adev)
continue;
if (idx >= AMDGPU_DM_MAX_CRTC) {
- DRM_WARN("%s connected connectors exceed max crtc\n", __func__);
+ drm_warn(adev_to_drm(adev),
+ "%s connected connectors exceed max crtc\n",
+ __func__);
mutex_unlock(&ddev->mode_config.mutex);
return;
}
@@ -500,6 +503,7 @@ int amdgpu_dm_crtc_configure_crc_source(struct drm_crtc *crtc,
{
struct amdgpu_device *adev = drm_to_adev(crtc->dev);
struct dc_stream_state *stream_state = dm_crtc_state->stream;
+ struct amdgpu_dm_connector *aconnector = NULL;
bool enable = amdgpu_dm_is_valid_crc_source(source);
int ret = 0;
@@ -507,11 +511,22 @@ int amdgpu_dm_crtc_configure_crc_source(struct drm_crtc *crtc,
if (!stream_state)
return -EINVAL;
+ /* Get connector from stream */
+ aconnector = (struct amdgpu_dm_connector *)stream_state->dm_stream_context;
+
mutex_lock(&adev->dm.dc_lock);
- /* For PSR1, check that the panel has exited PSR */
- if (stream_state->link->psr_settings.psr_version < DC_PSR_VERSION_SU_1)
- amdgpu_dm_psr_wait_disable(stream_state);
+
+ if (enable) {
+ /* For PSR1, check that the panel has exited PSR */
+ if (stream_state->link->psr_settings.psr_version < DC_PSR_VERSION_SU_1)
+ amdgpu_dm_psr_wait_disable(stream_state);
+
+ /* Set flag to disallow enter replay when CRC source is enabled */
+ if (aconnector)
+ aconnector->disallow_edp_enter_replay = true;
+ amdgpu_dm_replay_disable(stream_state);
+ }
/* Enable or disable CRTC CRC generation */
if (dm_is_crc_source_crtc(source) || source == AMDGPU_DM_PIPE_CRC_SOURCE_NONE) {
@@ -534,6 +549,12 @@ int amdgpu_dm_crtc_configure_crc_source(struct drm_crtc *crtc,
DYN_EXPANSION_AUTO);
}
+ if (!enable) {
+ /* Clear flag to allow enter replay when CRC source is disabled */
+ if (aconnector)
+ aconnector->disallow_edp_enter_replay = false;
+ }
+
unlock:
mutex_unlock(&adev->dm.dc_lock);
diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_debugfs.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_debugfs.c
index a9839485f2a2..b9ed29ec60dc 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_debugfs.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_debugfs.c
@@ -95,7 +95,7 @@ static int parse_write_buffer_into_params(char *wr_buf, uint32_t wr_buf_size,
return -EFAULT;
}
- /* check number of parameters. isspace could not differ space and \n */
+ /* check number of parameters. isspace could not differ space and\n */
while ((*wr_buf_ptr != 0xa) && (wr_buf_count < wr_buf_size)) {
/* skip space*/
while (isspace(*wr_buf_ptr) && (wr_buf_count < wr_buf_size)) {
@@ -2710,6 +2710,65 @@ static int ips_status_show(struct seq_file *m, void *unused)
}
/*
+ * IPS residency information from DMUB service. Read only.
+ *
+ * For time-window (segment) measurement:
+ * 1) echo 1 > /sys/kernel/debug/dri/0/amdgpu_dm_ips_residency_cntl
+ * 2) sleep <seconds>
+ * 3) echo 0 > /sys/kernel/debug/dri/0/amdgpu_dm_ips_residency_cntl
+ * 4) cat /sys/kernel/debug/dri/0/amdgpu_dm_ips_residency
+ */
+static int ips_residency_show(struct seq_file *m, void *unused)
+{
+ struct amdgpu_device *adev = m->private;
+ struct dc *dc = adev->dm.dc;
+ uint8_t panel_inst = 0;
+ enum ips_residency_mode mode;
+ struct dmub_ips_residency_info info;
+
+ mutex_lock(&adev->dm.dc_lock);
+
+ mode = IPS_RESIDENCY__IPS1_RCG;
+ if (!dc_dmub_srv_ips_query_residency_info(dc->ctx, panel_inst, &info, mode)) {
+ seq_printf(m, "ISP query failed\n");
+ } else {
+ unsigned int pct, frac;
+ pct = info.residency_millipercent / 1000;
+ frac = info.residency_millipercent % 1000;
+
+ seq_printf(m, "IPS residency: %u.%03u%% \n", pct, frac);
+ seq_printf(m, " entry_counter: %u\n", info.entry_counter);
+ seq_printf(m, " total_time_us: %llu\n",
+ (unsigned long long)info.total_time_us);
+ seq_printf(m, " total_inactive_time_us: %llu\n",
+ (unsigned long long)info.total_inactive_time_us);
+ }
+ mutex_unlock(&adev->dm.dc_lock);
+ return 0;
+}
+
+static int ips_residency_cntl_get(void *data, u64 *val)
+{
+ *val = 0;
+ return 0;
+}
+
+static int ips_residency_cntl_set(void *data, u64 val)
+{
+ struct amdgpu_device *adev = data;
+ struct dc *dc = adev->dm.dc;
+ uint8_t panel_inst = 0;
+ int ret = 0;
+
+ mutex_lock(&adev->dm.dc_lock);
+ if (!dc_dmub_srv_ips_residency_cntl(dc->ctx, panel_inst, !!val))
+ ret = -EIO;
+ mutex_unlock(&adev->dm.dc_lock);
+
+ return ret;
+}
+
+/*
* Backlight at this moment. Read only.
* As written to display, taking ABM and backlight lut into account.
* Ranges from 0x0 to 0x10000 (= 100% PWM)
@@ -3370,9 +3429,12 @@ DEFINE_DEBUGFS_ATTRIBUTE(disallow_edp_enter_psr_fops,
disallow_edp_enter_psr_get,
disallow_edp_enter_psr_set, "%llu\n");
+DEFINE_DEBUGFS_ATTRIBUTE(ips_residency_cntl_fops, ips_residency_cntl_get,
+ ips_residency_cntl_set, "%llu\n");
DEFINE_SHOW_ATTRIBUTE(current_backlight);
DEFINE_SHOW_ATTRIBUTE(target_backlight);
DEFINE_SHOW_ATTRIBUTE(ips_status);
+DEFINE_SHOW_ATTRIBUTE(ips_residency);
static const struct {
char *name;
@@ -4271,7 +4333,14 @@ void dtn_debugfs_init(struct amdgpu_device *adev)
debugfs_create_file_unsafe("amdgpu_dm_disable_hpd", 0644, root, adev,
&disable_hpd_ops);
- if (adev->dm.dc->caps.ips_support)
+ if (adev->dm.dc->caps.ips_support) {
debugfs_create_file_unsafe("amdgpu_dm_ips_status", 0644, root, adev,
&ips_status_fops);
+
+ debugfs_create_file_unsafe("amdgpu_dm_ips_residency_cntl", 0644, root, adev,
+ &ips_residency_cntl_fops);
+
+ debugfs_create_file_unsafe("amdgpu_dm_ips_residency", 0644, root, adev,
+ &ips_residency_fops);
+ }
}
diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_hdcp.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_hdcp.c
index 85ce558cefc5..a10401675f53 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_hdcp.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_hdcp.c
@@ -503,7 +503,8 @@ static bool enable_assr(void *handle, struct dc_link *link)
struct ta_dtm_shared_memory *dtm_cmd;
if (!psp->dtm_context.context.initialized) {
- DRM_INFO("Failed to enable ASSR, DTM TA is not initialized.");
+ drm_info(adev_to_drm(psp->adev),
+ "Failed to enable ASSR, DTM TA is not initialized.");
return false;
}
@@ -520,7 +521,8 @@ static bool enable_assr(void *handle, struct dc_link *link)
psp_dtm_invoke(psp, dtm_cmd->cmd_id);
if (dtm_cmd->dtm_status != TA_DTM_STATUS__SUCCESS) {
- DRM_INFO("Failed to enable ASSR");
+ drm_info(adev_to_drm(psp->adev),
+ "Failed to enable ASSR");
return false;
}
@@ -813,7 +815,7 @@ struct hdcp_workqueue *hdcp_create_workqueue(struct amdgpu_device *adev,
sysfs_bin_attr_init(&hdcp_work[0].attr);
if (sysfs_create_bin_file(&adev->dev->kobj, &hdcp_work[0].attr))
- DRM_WARN("Failed to create device file hdcp_srm");
+ drm_warn(adev_to_drm(adev), "Failed to create device file hdcp_srm\n");
return hdcp_work;
diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c
index e5e993d3ef74..1f41d6540b83 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c
@@ -1121,6 +1121,12 @@ void dm_set_dcn_clocks(struct dc_context *ctx, struct dc_clocks *clks)
/* TODO: something */
}
+void dm_helpers_dmu_timeout(struct dc_context *ctx)
+{
+ // TODO:
+ //amdgpu_device_gpu_recover(dc_context->driver-context, NULL);
+}
+
void dm_helpers_smu_timeout(struct dc_context *ctx, unsigned int msg_id, unsigned int param, unsigned int timeout_us)
{
// TODO:
diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_plane.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_plane.c
index 7c4496fb4b9d..d3e62f511c8f 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_plane.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_plane.c
@@ -278,7 +278,7 @@ static int amdgpu_dm_plane_validate_dcc(struct amdgpu_device *adev,
if (!dcc->enable)
return 0;
- if (adev->family < AMDGPU_FAMILY_GC_12_0_0 &&
+ if (adev->family != AMDGPU_FAMILY_GC_12_0_0 &&
format >= SURFACE_PIXEL_FORMAT_VIDEO_BEGIN)
return -EINVAL;
@@ -901,7 +901,7 @@ int amdgpu_dm_plane_fill_plane_buffer_attributes(struct amdgpu_device *adev,
upper_32_bits(chroma_addr);
}
- if (adev->family >= AMDGPU_FAMILY_GC_12_0_0) {
+ if (adev->family == AMDGPU_FAMILY_GC_12_0_0) {
ret = amdgpu_dm_plane_fill_gfx12_plane_attributes_from_modifiers(adev, afb, format,
rotation, plane_size,
tiling_info, dcc,
@@ -1676,8 +1676,8 @@ dm_atomic_plane_set_property(struct drm_plane *plane,
if (property == adev->mode_info.plane_degamma_lut_property) {
ret = drm_property_replace_blob_from_id(plane->dev,
&dm_plane_state->degamma_lut,
- val, -1,
- sizeof(struct drm_color_lut),
+ val,
+ -1, -1, sizeof(struct drm_color_lut),
&replaced);
dm_plane_state->base.color_mgmt_changed |= replaced;
return ret;
@@ -1695,15 +1695,15 @@ dm_atomic_plane_set_property(struct drm_plane *plane,
ret = drm_property_replace_blob_from_id(plane->dev,
&dm_plane_state->ctm,
val,
- sizeof(struct drm_color_ctm_3x4), -1,
+ -1, sizeof(struct drm_color_ctm_3x4), -1,
&replaced);
dm_plane_state->base.color_mgmt_changed |= replaced;
return ret;
} else if (property == adev->mode_info.plane_shaper_lut_property) {
ret = drm_property_replace_blob_from_id(plane->dev,
&dm_plane_state->shaper_lut,
- val, -1,
- sizeof(struct drm_color_lut),
+ val,
+ -1, -1, sizeof(struct drm_color_lut),
&replaced);
dm_plane_state->base.color_mgmt_changed |= replaced;
return ret;
@@ -1715,16 +1715,16 @@ dm_atomic_plane_set_property(struct drm_plane *plane,
} else if (property == adev->mode_info.plane_lut3d_property) {
ret = drm_property_replace_blob_from_id(plane->dev,
&dm_plane_state->lut3d,
- val, -1,
- sizeof(struct drm_color_lut),
+ val,
+ -1, -1, sizeof(struct drm_color_lut),
&replaced);
dm_plane_state->base.color_mgmt_changed |= replaced;
return ret;
} else if (property == adev->mode_info.plane_blend_lut_property) {
ret = drm_property_replace_blob_from_id(plane->dev,
&dm_plane_state->blend_lut,
- val, -1,
- sizeof(struct drm_color_lut),
+ val,
+ -1, -1, sizeof(struct drm_color_lut),
&replaced);
dm_plane_state->base.color_mgmt_changed |= replaced;
return ret;
diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_replay.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_replay.c
index da94e3544b65..8c150b001105 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_replay.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_replay.c
@@ -154,14 +154,21 @@ bool amdgpu_dm_replay_enable(struct dc_stream_state *stream, bool wait)
{
bool replay_active = true;
struct dc_link *link = NULL;
+ struct amdgpu_dm_connector *aconnector = NULL;
if (stream == NULL)
return false;
+ /* Check if replay is disabled by connector flag */
+ aconnector = (struct amdgpu_dm_connector *)stream->dm_stream_context;
+ if (!aconnector || aconnector->disallow_edp_enter_replay) {
+ return false;
+ }
+
link = stream->link;
if (link) {
- link->dc->link_srv->edp_setup_replay(link, stream);
+ link->dc->link_srv->dp_setup_replay(link, stream);
link->dc->link_srv->edp_set_coasting_vtotal(link, stream->timing.v_total, 0);
DRM_DEBUG_DRIVER("Enabling replay...\n");
link->dc->link_srv->edp_set_replay_allow_active(link, &replay_active, wait, false, NULL);
diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/dc_fpu.h b/drivers/gpu/drm/amd/display/amdgpu_dm/dc_fpu.h
index b8275b397920..4e921632bc4e 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/dc_fpu.h
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/dc_fpu.h
@@ -31,4 +31,12 @@ void dc_assert_fp_enabled(void);
void dc_fpu_begin(const char *function_name, const int line);
void dc_fpu_end(const char *function_name, const int line);
+#ifndef _LINUX_FPU_COMPILATION_UNIT
+#define DC_FP_START() dc_fpu_begin(__func__, __LINE__)
+#define DC_FP_END() dc_fpu_end(__func__, __LINE__)
+#else
+#define DC_FP_START() BUILD_BUG()
+#define DC_FP_END() BUILD_BUG()
+#endif
+
#endif /* __DC_FPU_H__ */
diff --git a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn314/dcn314_clk_mgr.c b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn314/dcn314_clk_mgr.c
index db687a13174d..0cb37827a62b 100644
--- a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn314/dcn314_clk_mgr.c
+++ b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn314/dcn314_clk_mgr.c
@@ -77,7 +77,6 @@ static const struct IP_BASE CLK_BASE = { { { { 0x00016C00, 0x02401800, 0, 0, 0,
#undef DC_LOGGER
#define DC_LOGGER \
clk_mgr->base.base.ctx->logger
-
#define regCLK1_CLK_PLL_REQ 0x0237
#define regCLK1_CLK_PLL_REQ_BASE_IDX 0
@@ -88,70 +87,8 @@ static const struct IP_BASE CLK_BASE = { { { { 0x00016C00, 0x02401800, 0, 0, 0,
#define CLK1_CLK_PLL_REQ__PllSpineDiv_MASK 0x0000F000L
#define CLK1_CLK_PLL_REQ__FbMult_frac_MASK 0xFFFF0000L
-#define regCLK1_CLK0_DFS_CNTL 0x0269
-#define regCLK1_CLK0_DFS_CNTL_BASE_IDX 0
-#define regCLK1_CLK1_DFS_CNTL 0x026c
-#define regCLK1_CLK1_DFS_CNTL_BASE_IDX 0
-#define regCLK1_CLK2_DFS_CNTL 0x026f
-#define regCLK1_CLK2_DFS_CNTL_BASE_IDX 0
-#define regCLK1_CLK3_DFS_CNTL 0x0272
-#define regCLK1_CLK3_DFS_CNTL_BASE_IDX 0
-#define regCLK1_CLK4_DFS_CNTL 0x0275
-#define regCLK1_CLK4_DFS_CNTL_BASE_IDX 0
-#define regCLK1_CLK5_DFS_CNTL 0x0278
-#define regCLK1_CLK5_DFS_CNTL_BASE_IDX 0
-
-#define regCLK1_CLK0_CURRENT_CNT 0x02fb
-#define regCLK1_CLK0_CURRENT_CNT_BASE_IDX 0
-#define regCLK1_CLK1_CURRENT_CNT 0x02fc
-#define regCLK1_CLK1_CURRENT_CNT_BASE_IDX 0
-#define regCLK1_CLK2_CURRENT_CNT 0x02fd
-#define regCLK1_CLK2_CURRENT_CNT_BASE_IDX 0
-#define regCLK1_CLK3_CURRENT_CNT 0x02fe
-#define regCLK1_CLK3_CURRENT_CNT_BASE_IDX 0
-#define regCLK1_CLK4_CURRENT_CNT 0x02ff
-#define regCLK1_CLK4_CURRENT_CNT_BASE_IDX 0
-#define regCLK1_CLK5_CURRENT_CNT 0x0300
-#define regCLK1_CLK5_CURRENT_CNT_BASE_IDX 0
-
-#define regCLK1_CLK0_BYPASS_CNTL 0x028a
-#define regCLK1_CLK0_BYPASS_CNTL_BASE_IDX 0
-#define regCLK1_CLK1_BYPASS_CNTL 0x0293
-#define regCLK1_CLK1_BYPASS_CNTL_BASE_IDX 0
#define regCLK1_CLK2_BYPASS_CNTL 0x029c
#define regCLK1_CLK2_BYPASS_CNTL_BASE_IDX 0
-#define regCLK1_CLK3_BYPASS_CNTL 0x02a5
-#define regCLK1_CLK3_BYPASS_CNTL_BASE_IDX 0
-#define regCLK1_CLK4_BYPASS_CNTL 0x02ae
-#define regCLK1_CLK4_BYPASS_CNTL_BASE_IDX 0
-#define regCLK1_CLK5_BYPASS_CNTL 0x02b7
-#define regCLK1_CLK5_BYPASS_CNTL_BASE_IDX 0
-
-#define regCLK1_CLK0_DS_CNTL 0x0283
-#define regCLK1_CLK0_DS_CNTL_BASE_IDX 0
-#define regCLK1_CLK1_DS_CNTL 0x028c
-#define regCLK1_CLK1_DS_CNTL_BASE_IDX 0
-#define regCLK1_CLK2_DS_CNTL 0x0295
-#define regCLK1_CLK2_DS_CNTL_BASE_IDX 0
-#define regCLK1_CLK3_DS_CNTL 0x029e
-#define regCLK1_CLK3_DS_CNTL_BASE_IDX 0
-#define regCLK1_CLK4_DS_CNTL 0x02a7
-#define regCLK1_CLK4_DS_CNTL_BASE_IDX 0
-#define regCLK1_CLK5_DS_CNTL 0x02b0
-#define regCLK1_CLK5_DS_CNTL_BASE_IDX 0
-
-#define regCLK1_CLK0_ALLOW_DS 0x0284
-#define regCLK1_CLK0_ALLOW_DS_BASE_IDX 0
-#define regCLK1_CLK1_ALLOW_DS 0x028d
-#define regCLK1_CLK1_ALLOW_DS_BASE_IDX 0
-#define regCLK1_CLK2_ALLOW_DS 0x0296
-#define regCLK1_CLK2_ALLOW_DS_BASE_IDX 0
-#define regCLK1_CLK3_ALLOW_DS 0x029f
-#define regCLK1_CLK3_ALLOW_DS_BASE_IDX 0
-#define regCLK1_CLK4_ALLOW_DS 0x02a8
-#define regCLK1_CLK4_ALLOW_DS_BASE_IDX 0
-#define regCLK1_CLK5_ALLOW_DS 0x02b1
-#define regCLK1_CLK5_ALLOW_DS_BASE_IDX 0
#define CLK1_CLK2_BYPASS_CNTL__CLK2_BYPASS_SEL__SHIFT 0x0
#define CLK1_CLK2_BYPASS_CNTL__CLK2_BYPASS_DIV__SHIFT 0x10
@@ -248,8 +185,6 @@ void dcn314_init_clocks(struct clk_mgr *clk_mgr)
{
struct clk_mgr_internal *clk_mgr_int = TO_CLK_MGR_INTERNAL(clk_mgr);
uint32_t ref_dtbclk = clk_mgr->clks.ref_dtbclk_khz;
- struct clk_mgr_dcn314 *clk_mgr_dcn314 = TO_CLK_MGR_DCN314(clk_mgr_int);
- struct clk_log_info log_info = {0};
memset(&(clk_mgr->clks), 0, sizeof(struct dc_clocks));
// Assumption is that boot state always supports pstate
@@ -265,9 +200,6 @@ void dcn314_init_clocks(struct clk_mgr *clk_mgr)
dce_adjust_dp_ref_freq_for_ss(clk_mgr_int, clk_mgr->dprefclk_khz);
else
clk_mgr->dp_dto_source_clock_in_khz = clk_mgr->dprefclk_khz;
-
- dcn314_dump_clk_registers(&clk_mgr->boot_snapshot, &clk_mgr_dcn314->base.base, &log_info);
- clk_mgr->clks.dispclk_khz = clk_mgr->boot_snapshot.dispclk * 1000;
}
void dcn314_update_clocks(struct clk_mgr *clk_mgr_base,
@@ -278,7 +210,7 @@ void dcn314_update_clocks(struct clk_mgr *clk_mgr_base,
struct clk_mgr_internal *clk_mgr = TO_CLK_MGR_INTERNAL(clk_mgr_base);
struct dc_clocks *new_clocks = &context->bw_ctx.bw.dcn.clk;
struct dc *dc = clk_mgr_base->ctx->dc;
- int display_count;
+ int display_count = 0;
bool update_dppclk = false;
bool update_dispclk = false;
bool dpp_clock_lowered = false;
@@ -287,7 +219,6 @@ void dcn314_update_clocks(struct clk_mgr *clk_mgr_base,
return;
display_count = dcn314_get_active_display_cnt_wa(dc, context);
-
/*
* if it is safe to lower, but we are already in the lower state, we don't have to do anything
* also if safe to lower is false, we just go in the higher state
@@ -363,7 +294,7 @@ void dcn314_update_clocks(struct clk_mgr *clk_mgr_base,
}
if (should_set_clock(safe_to_lower, new_clocks->dispclk_khz, clk_mgr_base->clks.dispclk_khz) &&
- (new_clocks->dispclk_khz > 0 || (safe_to_lower && display_count == 0))) {
+ (new_clocks->dispclk_khz > 0 || (safe_to_lower && display_count == 0))) {
int requested_dispclk_khz = new_clocks->dispclk_khz;
dcn314_disable_otg_wa(clk_mgr_base, context, safe_to_lower, true);
@@ -374,7 +305,6 @@ void dcn314_update_clocks(struct clk_mgr *clk_mgr_base,
dcn314_smu_set_dispclk(clk_mgr, requested_dispclk_khz);
clk_mgr_base->clks.dispclk_khz = new_clocks->dispclk_khz;
-
dcn314_disable_otg_wa(clk_mgr_base, context, safe_to_lower, false);
update_dispclk = true;
@@ -462,65 +392,10 @@ bool dcn314_are_clock_states_equal(struct dc_clocks *a,
return true;
}
-
-static void dcn314_dump_clk_registers_internal(struct dcn35_clk_internal *internal, struct clk_mgr *clk_mgr_base)
-{
- struct clk_mgr_internal *clk_mgr = TO_CLK_MGR_INTERNAL(clk_mgr_base);
-
- // read dtbclk
- internal->CLK1_CLK4_CURRENT_CNT = REG_READ(CLK1_CLK4_CURRENT_CNT);
- internal->CLK1_CLK4_BYPASS_CNTL = REG_READ(CLK1_CLK4_BYPASS_CNTL);
-
- // read dcfclk
- internal->CLK1_CLK3_CURRENT_CNT = REG_READ(CLK1_CLK3_CURRENT_CNT);
- internal->CLK1_CLK3_BYPASS_CNTL = REG_READ(CLK1_CLK3_BYPASS_CNTL);
-
- // read dcf deep sleep divider
- internal->CLK1_CLK3_DS_CNTL = REG_READ(CLK1_CLK3_DS_CNTL);
- internal->CLK1_CLK3_ALLOW_DS = REG_READ(CLK1_CLK3_ALLOW_DS);
-
- // read dppclk
- internal->CLK1_CLK1_CURRENT_CNT = REG_READ(CLK1_CLK1_CURRENT_CNT);
- internal->CLK1_CLK1_BYPASS_CNTL = REG_READ(CLK1_CLK1_BYPASS_CNTL);
-
- // read dprefclk
- internal->CLK1_CLK2_CURRENT_CNT = REG_READ(CLK1_CLK2_CURRENT_CNT);
- internal->CLK1_CLK2_BYPASS_CNTL = REG_READ(CLK1_CLK2_BYPASS_CNTL);
-
- // read dispclk
- internal->CLK1_CLK0_CURRENT_CNT = REG_READ(CLK1_CLK0_CURRENT_CNT);
- internal->CLK1_CLK0_BYPASS_CNTL = REG_READ(CLK1_CLK0_BYPASS_CNTL);
-}
-
-void dcn314_dump_clk_registers(struct clk_state_registers_and_bypass *regs_and_bypass,
+static void dcn314_dump_clk_registers(struct clk_state_registers_and_bypass *regs_and_bypass,
struct clk_mgr *clk_mgr_base, struct clk_log_info *log_info)
{
-
- struct dcn35_clk_internal internal = {0};
-
- dcn314_dump_clk_registers_internal(&internal, clk_mgr_base);
-
- regs_and_bypass->dcfclk = internal.CLK1_CLK3_CURRENT_CNT / 10;
- regs_and_bypass->dcf_deep_sleep_divider = internal.CLK1_CLK3_DS_CNTL / 10;
- regs_and_bypass->dcf_deep_sleep_allow = internal.CLK1_CLK3_ALLOW_DS;
- regs_and_bypass->dprefclk = internal.CLK1_CLK2_CURRENT_CNT / 10;
- regs_and_bypass->dispclk = internal.CLK1_CLK0_CURRENT_CNT / 10;
- regs_and_bypass->dppclk = internal.CLK1_CLK1_CURRENT_CNT / 10;
- regs_and_bypass->dtbclk = internal.CLK1_CLK4_CURRENT_CNT / 10;
-
- regs_and_bypass->dppclk_bypass = internal.CLK1_CLK1_BYPASS_CNTL & 0x0007;
- if (regs_and_bypass->dppclk_bypass > 4)
- regs_and_bypass->dppclk_bypass = 0;
- regs_and_bypass->dcfclk_bypass = internal.CLK1_CLK3_BYPASS_CNTL & 0x0007;
- if (regs_and_bypass->dcfclk_bypass > 4)
- regs_and_bypass->dcfclk_bypass = 0;
- regs_and_bypass->dispclk_bypass = internal.CLK1_CLK0_BYPASS_CNTL & 0x0007;
- if (regs_and_bypass->dispclk_bypass > 4)
- regs_and_bypass->dispclk_bypass = 0;
- regs_and_bypass->dprefclk_bypass = internal.CLK1_CLK2_BYPASS_CNTL & 0x0007;
- if (regs_and_bypass->dprefclk_bypass > 4)
- regs_and_bypass->dprefclk_bypass = 0;
-
+ return;
}
static struct clk_bw_params dcn314_bw_params = {
diff --git a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn314/dcn314_clk_mgr.h b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn314/dcn314_clk_mgr.h
index 0577eb527bc3..002c28e80720 100644
--- a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn314/dcn314_clk_mgr.h
+++ b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn314/dcn314_clk_mgr.h
@@ -65,9 +65,4 @@ void dcn314_clk_mgr_construct(struct dc_context *ctx,
void dcn314_clk_mgr_destroy(struct clk_mgr_internal *clk_mgr_int);
-
-void dcn314_dump_clk_registers(struct clk_state_registers_and_bypass *regs_and_bypass,
- struct clk_mgr *clk_mgr_base, struct clk_log_info *log_info);
-
-
#endif //__DCN314_CLK_MGR_H__
diff --git a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn315/dcn315_clk_mgr.c b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn315/dcn315_clk_mgr.c
index 3a881451e9da..c49268db85f6 100644
--- a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn315/dcn315_clk_mgr.c
+++ b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn315/dcn315_clk_mgr.c
@@ -40,7 +40,7 @@
#include "dm_helpers.h"
#include "dc_dmub_srv.h"
-#include "reg_helper.h"
+
#include "logger_types.h"
#undef DC_LOGGER
#define DC_LOGGER \
@@ -48,43 +48,9 @@
#include "link_service.h"
-#define MAX_INSTANCE 7
-#define MAX_SEGMENT 8
-
-struct IP_BASE_INSTANCE {
- unsigned int segment[MAX_SEGMENT];
-};
-
-struct IP_BASE {
- struct IP_BASE_INSTANCE instance[MAX_INSTANCE];
-};
-
-static const struct IP_BASE CLK_BASE = { { { { 0x00016C00, 0x02401800, 0, 0, 0, 0, 0, 0 } },
- { { 0x00016E00, 0x02401C00, 0, 0, 0, 0, 0, 0 } },
- { { 0x00017000, 0x02402000, 0, 0, 0, 0, 0, 0 } },
- { { 0x00017200, 0x02402400, 0, 0, 0, 0, 0, 0 } },
- { { 0x0001B000, 0x0242D800, 0, 0, 0, 0, 0, 0 } },
- { { 0x0001B200, 0x0242DC00, 0, 0, 0, 0, 0, 0 } } } };
-
-#define regCLK1_CLK0_CURRENT_CNT 0x0314
-#define regCLK1_CLK0_CURRENT_CNT_BASE_IDX 0
-#define regCLK1_CLK1_CURRENT_CNT 0x0315
-#define regCLK1_CLK1_CURRENT_CNT_BASE_IDX 0
-#define regCLK1_CLK2_CURRENT_CNT 0x0316
-#define regCLK1_CLK2_CURRENT_CNT_BASE_IDX 0
-#define regCLK1_CLK3_CURRENT_CNT 0x0317
-#define regCLK1_CLK3_CURRENT_CNT_BASE_IDX 0
-#define regCLK1_CLK4_CURRENT_CNT 0x0318
-#define regCLK1_CLK4_CURRENT_CNT_BASE_IDX 0
-#define regCLK1_CLK5_CURRENT_CNT 0x0319
-#define regCLK1_CLK5_CURRENT_CNT_BASE_IDX 0
-
#define TO_CLK_MGR_DCN315(clk_mgr)\
container_of(clk_mgr, struct clk_mgr_dcn315, base)
-#define REG(reg_name) \
- (CLK_BASE.instance[0].segment[reg ## reg_name ## _BASE_IDX] + reg ## reg_name)
-
#define UNSUPPORTED_DCFCLK 10000000
#define MIN_DPP_DISP_CLK 100000
@@ -172,7 +138,7 @@ static void dcn315_update_clocks(struct clk_mgr *clk_mgr_base,
if (dc->work_arounds.skip_clock_update)
return;
- clk_mgr_base->clks.zstate_support = new_clocks->zstate_support;
+ display_count = dcn315_get_active_display_cnt_wa(dc, context);
/*
* if it is safe to lower, but we are already in the lower state, we don't have to do anything
* also if safe to lower is false, we just go in the higher state
@@ -185,7 +151,6 @@ static void dcn315_update_clocks(struct clk_mgr *clk_mgr_base,
}
/* check that we're not already in lower */
if (clk_mgr_base->clks.pwr_state != DCN_PWR_STATE_LOW_POWER) {
- display_count = dcn315_get_active_display_cnt_wa(dc, context);
/* if we can go lower, go lower */
if (display_count == 0) {
union display_idle_optimization_u idle_info = { 0 };
@@ -279,38 +244,9 @@ static void dcn315_update_clocks(struct clk_mgr *clk_mgr_base,
dc_wake_and_execute_dmub_cmd(dc->ctx, &cmd, DM_DMUB_WAIT_TYPE_WAIT);
}
-static void dcn315_dump_clk_registers_internal(struct dcn35_clk_internal *internal, struct clk_mgr *clk_mgr_base)
-{
- struct clk_mgr_internal *clk_mgr = TO_CLK_MGR_INTERNAL(clk_mgr_base);
-
- // read dtbclk
- internal->CLK1_CLK4_CURRENT_CNT = REG_READ(CLK1_CLK4_CURRENT_CNT);
-
- // read dcfclk
- internal->CLK1_CLK3_CURRENT_CNT = REG_READ(CLK1_CLK3_CURRENT_CNT);
-
- // read dppclk
- internal->CLK1_CLK1_CURRENT_CNT = REG_READ(CLK1_CLK1_CURRENT_CNT);
-
- // read dprefclk
- internal->CLK1_CLK2_CURRENT_CNT = REG_READ(CLK1_CLK2_CURRENT_CNT);
-
- // read dispclk
- internal->CLK1_CLK0_CURRENT_CNT = REG_READ(CLK1_CLK0_CURRENT_CNT);
-}
-
static void dcn315_dump_clk_registers(struct clk_state_registers_and_bypass *regs_and_bypass,
struct clk_mgr *clk_mgr_base, struct clk_log_info *log_info)
{
- struct dcn35_clk_internal internal = {0};
-
- dcn315_dump_clk_registers_internal(&internal, clk_mgr_base);
-
- regs_and_bypass->dcfclk = internal.CLK1_CLK3_CURRENT_CNT / 10;
- regs_and_bypass->dprefclk = internal.CLK1_CLK2_CURRENT_CNT / 10;
- regs_and_bypass->dispclk = internal.CLK1_CLK0_CURRENT_CNT / 10;
- regs_and_bypass->dppclk = internal.CLK1_CLK1_CURRENT_CNT / 10;
- regs_and_bypass->dtbclk = internal.CLK1_CLK4_CURRENT_CNT / 10;
return;
}
@@ -657,32 +593,13 @@ static struct clk_mgr_funcs dcn315_funcs = {
.get_dp_ref_clk_frequency = dce12_get_dp_ref_freq_khz,
.get_dtb_ref_clk_frequency = dcn31_get_dtb_ref_freq_khz,
.update_clocks = dcn315_update_clocks,
- .init_clocks = dcn315_init_clocks,
+ .init_clocks = dcn31_init_clocks,
.enable_pme_wa = dcn315_enable_pme_wa,
.are_clock_states_equal = dcn31_are_clock_states_equal,
.notify_wm_ranges = dcn315_notify_wm_ranges
};
extern struct clk_mgr_funcs dcn3_fpga_funcs;
-void dcn315_init_clocks(struct clk_mgr *clk_mgr)
-{
- struct clk_mgr_internal *clk_mgr_int = TO_CLK_MGR_INTERNAL(clk_mgr);
- uint32_t ref_dtbclk = clk_mgr->clks.ref_dtbclk_khz;
- struct clk_mgr_dcn315 *clk_mgr_dcn315 = TO_CLK_MGR_DCN315(clk_mgr_int);
- struct clk_log_info log_info = {0};
-
- memset(&(clk_mgr->clks), 0, sizeof(struct dc_clocks));
- // Assumption is that boot state always supports pstate
- clk_mgr->clks.ref_dtbclk_khz = ref_dtbclk; // restore ref_dtbclk
- clk_mgr->clks.p_state_change_support = true;
- clk_mgr->clks.prev_p_state_change_support = true;
- clk_mgr->clks.pwr_state = DCN_PWR_STATE_UNKNOWN;
- clk_mgr->clks.zstate_support = DCN_ZSTATE_SUPPORT_UNKNOWN;
-
- dcn315_dump_clk_registers(&clk_mgr->boot_snapshot, &clk_mgr_dcn315->base.base, &log_info);
- clk_mgr->clks.dispclk_khz = clk_mgr->boot_snapshot.dispclk * 1000;
-}
-
void dcn315_clk_mgr_construct(
struct dc_context *ctx,
struct clk_mgr_dcn315 *clk_mgr,
@@ -743,7 +660,6 @@ void dcn315_clk_mgr_construct(
/* Saved clocks configured at boot for debug purposes */
dcn315_dump_clk_registers(&clk_mgr->base.base.boot_snapshot,
&clk_mgr->base.base, &log_info);
- clk_mgr->base.base.clks.dispclk_khz = clk_mgr->base.base.boot_snapshot.dispclk * 1000;
clk_mgr->base.base.dprefclk_khz = 600000;
clk_mgr->base.base.dprefclk_khz = dcn315_smu_get_dpref_clk(&clk_mgr->base);
diff --git a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn315/dcn315_clk_mgr.h b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn315/dcn315_clk_mgr.h
index 642ae3d4a790..ac36ddf5dd1a 100644
--- a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn315/dcn315_clk_mgr.h
+++ b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn315/dcn315_clk_mgr.h
@@ -44,7 +44,6 @@ void dcn315_clk_mgr_construct(struct dc_context *ctx,
struct pp_smu_funcs *pp_smu,
struct dccg *dccg);
-void dcn315_init_clocks(struct clk_mgr *clk_mgr);
void dcn315_clk_mgr_destroy(struct clk_mgr_internal *clk_mgr_int);
#endif //__DCN315_CLK_MGR_H__
diff --git a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn35/dcn35_clk_mgr.c b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn35/dcn35_clk_mgr.c
index dfd0c9505af0..72558cc55a9a 100644
--- a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn35/dcn35_clk_mgr.c
+++ b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn35/dcn35_clk_mgr.c
@@ -405,7 +405,6 @@ void dcn35_update_clocks(struct clk_mgr *clk_mgr_base,
if (new_clocks->zstate_support != DCN_ZSTATE_SUPPORT_DISALLOW &&
new_clocks->zstate_support != clk_mgr_base->clks.zstate_support) {
dcn35_smu_set_zstate_support(clk_mgr, new_clocks->zstate_support);
- dm_helpers_enable_periodic_detection(clk_mgr_base->ctx, true);
clk_mgr_base->clks.zstate_support = new_clocks->zstate_support;
}
@@ -425,7 +424,6 @@ void dcn35_update_clocks(struct clk_mgr *clk_mgr_base,
if (new_clocks->zstate_support == DCN_ZSTATE_SUPPORT_DISALLOW &&
new_clocks->zstate_support != clk_mgr_base->clks.zstate_support) {
dcn35_smu_set_zstate_support(clk_mgr, DCN_ZSTATE_SUPPORT_DISALLOW);
- dm_helpers_enable_periodic_detection(clk_mgr_base->ctx, false);
clk_mgr_base->clks.zstate_support = new_clocks->zstate_support;
}
diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c
index 8be9cbd43e18..cb85b7ac2697 100644
--- a/drivers/gpu/drm/amd/display/dc/core/dc.c
+++ b/drivers/gpu/drm/amd/display/dc/core/dc.c
@@ -784,7 +784,7 @@ bool dc_stream_get_crc(struct dc *dc, struct dc_stream_state *stream, uint8_t id
uint32_t *r_cr, uint32_t *g_y, uint32_t *b_cb)
{
int i;
- struct pipe_ctx *pipe;
+ struct pipe_ctx *pipe = NULL;
struct timing_generator *tg;
dc_exit_ips_for_hw_access(dc);
@@ -2963,6 +2963,11 @@ static struct surface_update_descriptor check_update_surfaces_for_stream(
{
struct surface_update_descriptor overall_type = { UPDATE_TYPE_FAST, LOCK_DESCRIPTOR_NONE };
+ /* When countdown finishes, promote this flip to full to trigger deferred final transition */
+ if (check_config->deferred_transition_state && !check_config->transition_countdown_to_steady_state) {
+ elevate_update_type(&overall_type, UPDATE_TYPE_FULL, LOCK_DESCRIPTOR_GLOBAL);
+ }
+
if (stream_update && stream_update->pending_test_pattern) {
elevate_update_type(&overall_type, UPDATE_TYPE_FULL, LOCK_DESCRIPTOR_GLOBAL);
}
@@ -3441,6 +3446,49 @@ static bool full_update_required_weak(
const struct dc_stream_update *stream_update,
const struct dc_stream_state *stream);
+struct pipe_split_policy_backup {
+ bool dynamic_odm_policy;
+ bool subvp_policy;
+ enum pipe_split_policy mpc_policy;
+ char force_odm[MAX_PIPES];
+};
+
+static void backup_and_set_minimal_pipe_split_policy(struct dc *dc,
+ struct dc_state *context,
+ struct pipe_split_policy_backup *policy)
+{
+ int i;
+
+ if (!dc->config.is_vmin_only_asic) {
+ policy->mpc_policy = dc->debug.pipe_split_policy;
+ dc->debug.pipe_split_policy = MPC_SPLIT_AVOID;
+ }
+ policy->dynamic_odm_policy = dc->debug.enable_single_display_2to1_odm_policy;
+ dc->debug.enable_single_display_2to1_odm_policy = false;
+ policy->subvp_policy = dc->debug.force_disable_subvp;
+ dc->debug.force_disable_subvp = true;
+ for (i = 0; i < context->stream_count; i++) {
+ policy->force_odm[i] = context->streams[i]->debug.force_odm_combine_segments;
+ if (context->streams[i]->debug.allow_transition_for_forced_odm)
+ context->streams[i]->debug.force_odm_combine_segments = 0;
+ }
+}
+
+static void restore_minimal_pipe_split_policy(struct dc *dc,
+ struct dc_state *context,
+ struct pipe_split_policy_backup *policy)
+{
+ uint8_t i;
+
+ if (!dc->config.is_vmin_only_asic)
+ dc->debug.pipe_split_policy = policy->mpc_policy;
+ dc->debug.enable_single_display_2to1_odm_policy =
+ policy->dynamic_odm_policy;
+ dc->debug.force_disable_subvp = policy->subvp_policy;
+ for (i = 0; i < context->stream_count; i++)
+ context->streams[i]->debug.force_odm_combine_segments = policy->force_odm[i];
+}
+
/**
* update_planes_and_stream_state() - The function takes planes and stream
* updates as inputs and determines the appropriate update type. If update type
@@ -3591,10 +3639,30 @@ static bool update_planes_and_stream_state(struct dc *dc,
}
if (update_type == UPDATE_TYPE_FULL) {
+ struct pipe_split_policy_backup policy;
+ bool minimize = false;
+
+ if (dc->check_config.deferred_transition_state) {
+ if (dc->check_config.transition_countdown_to_steady_state) {
+ /* During countdown, all new contexts created as minimal transition states */
+ minimize = true;
+ } else {
+ dc->check_config.deferred_transition_state = false;
+ }
+ }
+
+ if (minimize)
+ backup_and_set_minimal_pipe_split_policy(dc, context, &policy);
+
if (dc->res_pool->funcs->validate_bandwidth(dc, context, DC_VALIDATE_MODE_AND_PROGRAMMING) != DC_OK) {
+ if (minimize)
+ restore_minimal_pipe_split_policy(dc, context, &policy);
BREAK_TO_DEBUGGER();
goto fail;
}
+
+ if (minimize)
+ restore_minimal_pipe_split_policy(dc, context, &policy);
}
update_seamless_boot_flags(dc, context, surface_count, stream);
@@ -3781,7 +3849,7 @@ static bool dc_dmub_should_send_dirty_rect_cmd(struct dc *dc, struct dc_stream_s
void dc_dmub_update_dirty_rect(struct dc *dc,
int surface_count,
struct dc_stream_state *stream,
- struct dc_surface_update *srf_updates,
+ const struct dc_surface_update *srf_updates,
struct dc_state *context)
{
union dmub_rb_cmd cmd;
@@ -4086,7 +4154,7 @@ static void commit_planes_for_stream_fast(struct dc *dc,
}
static void commit_planes_for_stream(struct dc *dc,
- struct dc_surface_update *srf_updates,
+ const struct dc_surface_update *srf_updates,
int surface_count,
struct dc_stream_state *stream,
struct dc_stream_update *stream_update,
@@ -4622,48 +4690,6 @@ static bool could_mpcc_tree_change_for_active_pipes(struct dc *dc,
return force_minimal_pipe_splitting;
}
-struct pipe_split_policy_backup {
- bool dynamic_odm_policy;
- bool subvp_policy;
- enum pipe_split_policy mpc_policy;
- char force_odm[MAX_PIPES];
-};
-
-static void backup_and_set_minimal_pipe_split_policy(struct dc *dc,
- struct dc_state *context,
- struct pipe_split_policy_backup *policy)
-{
- int i;
-
- if (!dc->config.is_vmin_only_asic) {
- policy->mpc_policy = dc->debug.pipe_split_policy;
- dc->debug.pipe_split_policy = MPC_SPLIT_AVOID;
- }
- policy->dynamic_odm_policy = dc->debug.enable_single_display_2to1_odm_policy;
- dc->debug.enable_single_display_2to1_odm_policy = false;
- policy->subvp_policy = dc->debug.force_disable_subvp;
- dc->debug.force_disable_subvp = true;
- for (i = 0; i < context->stream_count; i++) {
- policy->force_odm[i] = context->streams[i]->debug.force_odm_combine_segments;
- if (context->streams[i]->debug.allow_transition_for_forced_odm)
- context->streams[i]->debug.force_odm_combine_segments = 0;
- }
-}
-
-static void restore_minimal_pipe_split_policy(struct dc *dc,
- struct dc_state *context,
- struct pipe_split_policy_backup *policy)
-{
- uint8_t i;
-
- if (!dc->config.is_vmin_only_asic)
- dc->debug.pipe_split_policy = policy->mpc_policy;
- dc->debug.enable_single_display_2to1_odm_policy =
- policy->dynamic_odm_policy;
- dc->debug.force_disable_subvp = policy->subvp_policy;
- for (i = 0; i < context->stream_count; i++)
- context->streams[i]->debug.force_odm_combine_segments = policy->force_odm[i];
-}
static void release_minimal_transition_state(struct dc *dc,
struct dc_state *minimal_transition_context,
@@ -4773,6 +4799,7 @@ static int initialize_empty_surface_updates(
static bool commit_minimal_transition_based_on_new_context(struct dc *dc,
struct dc_state *new_context,
struct dc_stream_state *stream,
+ struct dc_stream_update *stream_update,
struct dc_surface_update *srf_updates,
int surface_count)
{
@@ -4790,7 +4817,7 @@ static bool commit_minimal_transition_based_on_new_context(struct dc *dc,
new_context)) {
DC_LOG_DC("commit minimal transition state: base = new state\n");
commit_planes_for_stream(dc, srf_updates,
- surface_count, stream, NULL,
+ surface_count, stream, stream_update,
UPDATE_TYPE_FULL, intermediate_context);
swap_and_release_current_context(
dc, intermediate_context, stream);
@@ -4884,8 +4911,8 @@ static bool commit_minimal_transition_state_in_dc_update(struct dc *dc,
int surface_count)
{
bool success = commit_minimal_transition_based_on_new_context(
- dc, new_context, stream, srf_updates,
- surface_count);
+ dc, new_context, stream, NULL,
+ srf_updates, surface_count);
if (!success)
success = commit_minimal_transition_based_on_current_context(dc,
new_context, stream);
@@ -5294,32 +5321,63 @@ static void commit_planes_and_stream_update_with_new_context(struct dc *dc,
enum surface_update_type update_type,
struct dc_state *new_context)
{
+ bool skip_new_context = false;
ASSERT(update_type >= UPDATE_TYPE_FULL);
- if (!dc->hwss.is_pipe_topology_transition_seamless(dc,
- dc->current_state, new_context))
- /*
- * It is required by the feature design that all pipe topologies
- * using extra free pipes for power saving purposes such as
- * dynamic ODM or SubVp shall only be enabled when it can be
- * transitioned seamlessly to AND from its minimal transition
- * state. A minimal transition state is defined as the same dc
- * state but with all power saving features disabled. So it uses
- * the minimum pipe topology. When we can't seamlessly
- * transition from state A to state B, we will insert the
- * minimal transition state A' or B' in between so seamless
- * transition between A and B can be made possible.
- */
- commit_minimal_transition_state_in_dc_update(dc, new_context,
- stream, srf_updates, surface_count);
+ /*
+ * It is required by the feature design that all pipe topologies
+ * using extra free pipes for power saving purposes such as
+ * dynamic ODM or SubVp shall only be enabled when it can be
+ * transitioned seamlessly to AND from its minimal transition
+ * state. A minimal transition state is defined as the same dc
+ * state but with all power saving features disabled. So it uses
+ * the minimum pipe topology. When we can't seamlessly
+ * transition from state A to state B, we will insert the
+ * minimal transition state A' or B' in between so seamless
+ * transition between A and B can be made possible.
+ *
+ * To optimize for the time it takes to execute flips,
+ * the transition from the minimal state to the final state is
+ * deferred until a steady state (no more transitions) is reached.
+ */
+ if (!dc->hwss.is_pipe_topology_transition_seamless(dc, dc->current_state, new_context)) {
+ if (!dc->debug.disable_deferred_minimal_transitions) {
+ dc->check_config.deferred_transition_state = true;
+ dc->check_config.transition_countdown_to_steady_state =
+ dc->debug.num_fast_flips_to_steady_state_override ?
+ dc->debug.num_fast_flips_to_steady_state_override :
+ NUM_FAST_FLIPS_TO_STEADY_STATE;
+
+ if (commit_minimal_transition_based_on_new_context(dc, new_context, stream, stream_update,
+ srf_updates, surface_count)) {
+ skip_new_context = true;
+ dc_state_release(new_context);
+ new_context = dc->current_state;
+ } else {
+ /*
+ * In this case a new mpo plane is being enabled on pipes that were
+ * previously in use, and the surface update to the existing plane
+ * includes an alpha box where the new plane will be, so the update
+ * from minimal to final cannot be deferred as the alpha box would
+ * be visible to the user
+ */
+ commit_minimal_transition_based_on_current_context(dc, new_context, stream);
+ }
+ } else {
+ commit_minimal_transition_state_in_dc_update(dc, new_context, stream,
+ srf_updates, surface_count);
+ }
+ } else if (dc->check_config.deferred_transition_state) {
+ /* reset countdown as steady state not reached */
+ dc->check_config.transition_countdown_to_steady_state =
+ dc->debug.num_fast_flips_to_steady_state_override ?
+ dc->debug.num_fast_flips_to_steady_state_override :
+ NUM_FAST_FLIPS_TO_STEADY_STATE;
+ }
- commit_planes_for_stream(
- dc,
- srf_updates,
- surface_count,
- stream,
- stream_update,
- update_type,
- new_context);
+ if (!skip_new_context) {
+ commit_planes_for_stream(dc, srf_updates, surface_count, stream, stream_update, update_type, new_context);
+ swap_and_release_current_context(dc, new_context, stream);
+ }
}
static bool update_planes_and_stream_v3(struct dc *dc,
@@ -5349,11 +5407,13 @@ static bool update_planes_and_stream_v3(struct dc *dc,
commit_planes_and_stream_update_on_current_context(dc,
srf_updates, surface_count, stream,
stream_update, update_type);
+
+ if (dc->check_config.transition_countdown_to_steady_state)
+ dc->check_config.transition_countdown_to_steady_state--;
} else {
commit_planes_and_stream_update_with_new_context(dc,
srf_updates, surface_count, stream,
stream_update, update_type, new_context);
- swap_and_release_current_context(dc, new_context, stream);
}
return true;
@@ -5377,35 +5437,23 @@ bool dc_update_planes_and_stream(struct dc *dc,
struct dc_stream_state *stream,
struct dc_stream_update *stream_update)
{
- bool ret = false;
+ struct dc_update_scratch_space *scratch = dc_update_planes_and_stream_init(
+ dc,
+ srf_updates,
+ surface_count,
+ stream,
+ stream_update
+ );
+ bool more = true;
- dc_exit_ips_for_hw_access(dc);
- /*
- * update planes and stream version 3 separates FULL and FAST updates
- * to their own sequences. It aims to clean up frequent checks for
- * update type resulting unnecessary branching in logic flow. It also
- * adds a new commit minimal transition sequence, which detects the need
- * for minimal transition based on the actual comparison of current and
- * new states instead of "predicting" it based on per feature software
- * policy.i.e could_mpcc_tree_change_for_active_pipes. The new commit
- * minimal transition sequence is made universal to any power saving
- * features that would use extra free pipes such as Dynamic ODM/MPC
- * Combine, MPO or SubVp. Therefore there is no longer a need to
- * specially handle compatibility problems with transitions among those
- * features as they are now transparent to the new sequence.
- */
- if (dc->ctx->dce_version >= DCN_VERSION_4_01 || dc->ctx->dce_version == DCN_VERSION_3_2 ||
- dc->ctx->dce_version == DCN_VERSION_3_21)
- ret = update_planes_and_stream_v3(dc, srf_updates,
- surface_count, stream, stream_update);
- else
- ret = update_planes_and_stream_v2(dc, srf_updates,
- surface_count, stream, stream_update);
- if (ret && (dc->ctx->dce_version >= DCN_VERSION_3_2 ||
- dc->ctx->dce_version == DCN_VERSION_3_01))
- clear_update_flags(srf_updates, surface_count, stream);
+ while (more) {
+ if (!dc_update_planes_and_stream_prepare(scratch))
+ return false;
- return ret;
+ dc_update_planes_and_stream_execute(scratch);
+ more = dc_update_planes_and_stream_cleanup(scratch);
+ }
+ return true;
}
void dc_commit_updates_for_stream(struct dc *dc,
@@ -7091,3 +7139,403 @@ void dc_log_preos_dmcub_info(const struct dc *dc)
{
dc_dmub_srv_log_preos_dmcub_info(dc->ctx->dmub_srv);
}
+
+bool dc_get_qos_info(struct dc *dc, struct dc_qos_info *info)
+{
+ const struct dc_clocks *clk = &dc->current_state->bw_ctx.bw.dcn.clk;
+ struct memory_qos qos;
+
+ memset(info, 0, sizeof(*info));
+
+ // Check if measurement function is available
+ if (!dc->hwss.measure_memory_qos) {
+ return false;
+ }
+
+ // Call unified measurement function
+ dc->hwss.measure_memory_qos(dc, &qos);
+
+ // Populate info from measured qos
+ info->actual_peak_bw_in_mbps = qos.peak_bw_mbps;
+ info->actual_avg_bw_in_mbps = qos.avg_bw_mbps;
+ info->actual_min_latency_in_ns = qos.min_latency_ns;
+ info->actual_max_latency_in_ns = qos.max_latency_ns;
+ info->actual_avg_latency_in_ns = qos.avg_latency_ns;
+ info->dcn_bandwidth_ub_in_mbps = (uint32_t)(clk->fclk_khz / 1000 * 64);
+
+ return true;
+}
+
+enum update_v3_flow {
+ UPDATE_V3_FLOW_INVALID,
+ UPDATE_V3_FLOW_NO_NEW_CONTEXT_CONTEXT_FAST,
+ UPDATE_V3_FLOW_NO_NEW_CONTEXT_CONTEXT_FULL,
+ UPDATE_V3_FLOW_NEW_CONTEXT_SEAMLESS,
+ UPDATE_V3_FLOW_NEW_CONTEXT_MINIMAL_NEW,
+ UPDATE_V3_FLOW_NEW_CONTEXT_MINIMAL_CURRENT,
+};
+
+struct dc_update_scratch_space {
+ struct dc *dc;
+ struct dc_surface_update *surface_updates;
+ int surface_count;
+ struct dc_stream_state *stream;
+ struct dc_stream_update *stream_update;
+ bool update_v3;
+ bool do_clear_update_flags;
+ enum surface_update_type update_type;
+ struct dc_state *new_context;
+ enum update_v3_flow flow;
+ struct dc_state *backup_context;
+ struct dc_state *intermediate_context;
+ struct pipe_split_policy_backup intermediate_policy;
+ struct dc_surface_update intermediate_updates[MAX_SURFACES];
+ int intermediate_count;
+};
+
+size_t dc_update_scratch_space_size(void)
+{
+ return sizeof(struct dc_update_scratch_space);
+}
+
+static bool update_planes_and_stream_prepare_v2(
+ struct dc_update_scratch_space *scratch
+)
+{
+ // v2 is too tangled to break into stages, so just execute everything under lock
+ dc_exit_ips_for_hw_access(scratch->dc);
+ return update_planes_and_stream_v2(
+ scratch->dc,
+ scratch->surface_updates,
+ scratch->surface_count,
+ scratch->stream,
+ scratch->stream_update
+ );
+}
+
+static void update_planes_and_stream_execute_v2(
+ const struct dc_update_scratch_space *scratch
+)
+{
+ // Nothing to do, see `update_planes_and_stream_prepare_v2`
+ (void) scratch;
+}
+
+static bool update_planes_and_stream_cleanup_v2(
+ const struct dc_update_scratch_space *scratch
+)
+{
+ if (scratch->do_clear_update_flags)
+ clear_update_flags(scratch->surface_updates, scratch->surface_count, scratch->stream);
+
+ return false;
+}
+
+static void update_planes_and_stream_cleanup_v3_release_minimal(
+ struct dc_update_scratch_space *scratch,
+ bool backup
+);
+
+static bool update_planes_and_stream_prepare_v3_intermediate_seamless(
+ struct dc_update_scratch_space *scratch
+)
+{
+ return is_pipe_topology_transition_seamless_with_intermediate_step(
+ scratch->dc,
+ scratch->dc->current_state,
+ scratch->intermediate_context,
+ scratch->new_context
+ );
+}
+
+static void transition_countdown_init(struct dc *dc)
+{
+ dc->check_config.transition_countdown_to_steady_state =
+ dc->debug.num_fast_flips_to_steady_state_override ?
+ dc->debug.num_fast_flips_to_steady_state_override :
+ NUM_FAST_FLIPS_TO_STEADY_STATE;
+}
+
+static bool update_planes_and_stream_prepare_v3(
+ struct dc_update_scratch_space *scratch
+)
+{
+ if (scratch->flow == UPDATE_V3_FLOW_NEW_CONTEXT_SEAMLESS) {
+ return true;
+ }
+ ASSERT(scratch->flow == UPDATE_V3_FLOW_INVALID);
+ dc_exit_ips_for_hw_access(scratch->dc);
+
+ if (!update_planes_and_stream_state(
+ scratch->dc,
+ scratch->surface_updates,
+ scratch->surface_count,
+ scratch->stream,
+ scratch->stream_update,
+ &scratch->update_type,
+ &scratch->new_context
+ )) {
+ return false;
+ }
+
+ if (scratch->new_context == scratch->dc->current_state) {
+ ASSERT(scratch->update_type < UPDATE_TYPE_FULL);
+
+ // TODO: Do we need this to be alive in execute?
+ struct dc_fast_update fast_update[MAX_SURFACES] = { 0 };
+
+ populate_fast_updates(
+ fast_update,
+ scratch->surface_updates,
+ scratch->surface_count,
+ scratch->stream_update
+ );
+ const bool fast = fast_update_only(
+ scratch->dc,
+ fast_update,
+ scratch->surface_updates,
+ scratch->surface_count,
+ scratch->stream_update,
+ scratch->stream
+ )
+ // TODO: Can this be used to skip `populate_fast_updates`?
+ && !scratch->dc->check_config.enable_legacy_fast_update;
+ scratch->flow = fast
+ ? UPDATE_V3_FLOW_NO_NEW_CONTEXT_CONTEXT_FAST
+ : UPDATE_V3_FLOW_NO_NEW_CONTEXT_CONTEXT_FULL;
+ return true;
+ }
+
+ ASSERT(scratch->update_type >= UPDATE_TYPE_FULL);
+
+ const bool seamless = scratch->dc->hwss.is_pipe_topology_transition_seamless(
+ scratch->dc,
+ scratch->dc->current_state,
+ scratch->new_context
+ );
+ if (seamless) {
+ scratch->flow = UPDATE_V3_FLOW_NEW_CONTEXT_SEAMLESS;
+ if (scratch->dc->check_config.deferred_transition_state)
+ /* reset countdown as steady state not reached */
+ transition_countdown_init(scratch->dc);
+ return true;
+ }
+
+ if (!scratch->dc->debug.disable_deferred_minimal_transitions) {
+ scratch->dc->check_config.deferred_transition_state = true;
+ transition_countdown_init(scratch->dc);
+ }
+
+ scratch->intermediate_context = create_minimal_transition_state(
+ scratch->dc,
+ scratch->new_context,
+ &scratch->intermediate_policy
+ );
+ if (scratch->intermediate_context) {
+ if (update_planes_and_stream_prepare_v3_intermediate_seamless(scratch)) {
+ scratch->flow = UPDATE_V3_FLOW_NEW_CONTEXT_MINIMAL_NEW;
+ return true;
+ }
+
+ update_planes_and_stream_cleanup_v3_release_minimal(scratch, false);
+ }
+
+ scratch->backup_context = scratch->dc->current_state;
+ restore_planes_and_stream_state(&scratch->dc->scratch.current_state, scratch->stream);
+ dc_state_retain(scratch->backup_context);
+ scratch->intermediate_context = create_minimal_transition_state(
+ scratch->dc,
+ scratch->backup_context,
+ &scratch->intermediate_policy
+ );
+ if (scratch->intermediate_context) {
+ if (update_planes_and_stream_prepare_v3_intermediate_seamless(scratch)) {
+ scratch->flow = UPDATE_V3_FLOW_NEW_CONTEXT_MINIMAL_CURRENT;
+ scratch->intermediate_count = initialize_empty_surface_updates(
+ scratch->stream, scratch->intermediate_updates
+ );
+ return true;
+ }
+
+ update_planes_and_stream_cleanup_v3_release_minimal(scratch, true);
+ }
+
+ scratch->flow = UPDATE_V3_FLOW_INVALID;
+ dc_state_release(scratch->backup_context);
+ restore_planes_and_stream_state(&scratch->dc->scratch.new_state, scratch->stream);
+ return false;
+}
+
+static void update_planes_and_stream_execute_v3_commit(
+ const struct dc_update_scratch_space *scratch,
+ bool intermediate_update,
+ bool intermediate_context,
+ bool use_stream_update
+)
+{
+ commit_planes_for_stream(
+ scratch->dc,
+ intermediate_update ? scratch->intermediate_updates : scratch->surface_updates,
+ intermediate_update ? scratch->intermediate_count : scratch->surface_count,
+ scratch->stream,
+ use_stream_update ? scratch->stream_update : NULL,
+ intermediate_context ? UPDATE_TYPE_FULL : scratch->update_type,
+ // `dc->current_state` only used in `NO_NEW_CONTEXT`, where it is equal to `new_context`
+ intermediate_context ? scratch->intermediate_context : scratch->new_context
+ );
+}
+
+static void update_planes_and_stream_execute_v3(
+ const struct dc_update_scratch_space *scratch
+)
+{
+ switch (scratch->flow) {
+ case UPDATE_V3_FLOW_NO_NEW_CONTEXT_CONTEXT_FAST:
+ commit_planes_for_stream_fast(
+ scratch->dc,
+ scratch->surface_updates,
+ scratch->surface_count,
+ scratch->stream,
+ scratch->stream_update,
+ scratch->update_type,
+ scratch->new_context
+ );
+ break;
+
+ case UPDATE_V3_FLOW_NO_NEW_CONTEXT_CONTEXT_FULL:
+ case UPDATE_V3_FLOW_NEW_CONTEXT_SEAMLESS:
+ update_planes_and_stream_execute_v3_commit(scratch, false, false, true);
+ break;
+
+ case UPDATE_V3_FLOW_NEW_CONTEXT_MINIMAL_NEW:
+ update_planes_and_stream_execute_v3_commit(scratch, false, true,
+ scratch->dc->check_config.deferred_transition_state);
+ break;
+
+ case UPDATE_V3_FLOW_NEW_CONTEXT_MINIMAL_CURRENT:
+ update_planes_and_stream_execute_v3_commit(scratch, true, true, false);
+ break;
+
+ case UPDATE_V3_FLOW_INVALID:
+ default:
+ ASSERT(false);
+ }
+}
+
+static void update_planes_and_stream_cleanup_v3_release_minimal(
+ struct dc_update_scratch_space *scratch,
+ bool backup
+)
+{
+ release_minimal_transition_state(
+ scratch->dc,
+ scratch->intermediate_context,
+ backup ? scratch->backup_context : scratch->new_context,
+ &scratch->intermediate_policy
+ );
+}
+
+static void update_planes_and_stream_cleanup_v3_intermediate(
+ struct dc_update_scratch_space *scratch,
+ bool backup
+)
+{
+ swap_and_release_current_context(scratch->dc, scratch->intermediate_context, scratch->stream);
+ dc_state_retain(scratch->dc->current_state);
+ update_planes_and_stream_cleanup_v3_release_minimal(scratch, backup);
+}
+
+static bool update_planes_and_stream_cleanup_v3(
+ struct dc_update_scratch_space *scratch
+)
+{
+ switch (scratch->flow) {
+ case UPDATE_V3_FLOW_NO_NEW_CONTEXT_CONTEXT_FAST:
+ case UPDATE_V3_FLOW_NO_NEW_CONTEXT_CONTEXT_FULL:
+ if (scratch->dc->check_config.transition_countdown_to_steady_state)
+ scratch->dc->check_config.transition_countdown_to_steady_state--;
+ break;
+
+ case UPDATE_V3_FLOW_NEW_CONTEXT_SEAMLESS:
+ swap_and_release_current_context(scratch->dc, scratch->new_context, scratch->stream);
+ break;
+
+ case UPDATE_V3_FLOW_NEW_CONTEXT_MINIMAL_NEW:
+ update_planes_and_stream_cleanup_v3_intermediate(scratch, false);
+ if (scratch->dc->check_config.deferred_transition_state) {
+ dc_state_release(scratch->new_context);
+ } else {
+ scratch->flow = UPDATE_V3_FLOW_NEW_CONTEXT_SEAMLESS;
+ return true;
+ }
+ break;
+
+ case UPDATE_V3_FLOW_NEW_CONTEXT_MINIMAL_CURRENT:
+ update_planes_and_stream_cleanup_v3_intermediate(scratch, true);
+ dc_state_release(scratch->backup_context);
+ restore_planes_and_stream_state(&scratch->dc->scratch.new_state, scratch->stream);
+ scratch->flow = UPDATE_V3_FLOW_NEW_CONTEXT_SEAMLESS;
+ return true;
+
+ case UPDATE_V3_FLOW_INVALID:
+ default:
+ ASSERT(false);
+ }
+
+ if (scratch->do_clear_update_flags)
+ clear_update_flags(scratch->surface_updates, scratch->surface_count, scratch->stream);
+
+ return false;
+}
+
+struct dc_update_scratch_space *dc_update_planes_and_stream_init(
+ struct dc *dc,
+ struct dc_surface_update *surface_updates,
+ int surface_count,
+ struct dc_stream_state *stream,
+ struct dc_stream_update *stream_update
+)
+{
+ const enum dce_version version = dc->ctx->dce_version;
+ struct dc_update_scratch_space *scratch = stream->update_scratch;
+
+ *scratch = (struct dc_update_scratch_space){
+ .dc = dc,
+ .surface_updates = surface_updates,
+ .surface_count = surface_count,
+ .stream = stream,
+ .stream_update = stream_update,
+ .update_v3 = version >= DCN_VERSION_4_01 || version == DCN_VERSION_3_2 || version == DCN_VERSION_3_21,
+ .do_clear_update_flags = version >= DCN_VERSION_1_0,
+ };
+
+ return scratch;
+}
+
+bool dc_update_planes_and_stream_prepare(
+ struct dc_update_scratch_space *scratch
+)
+{
+ return scratch->update_v3
+ ? update_planes_and_stream_prepare_v3(scratch)
+ : update_planes_and_stream_prepare_v2(scratch);
+}
+
+void dc_update_planes_and_stream_execute(
+ const struct dc_update_scratch_space *scratch
+)
+{
+ scratch->update_v3
+ ? update_planes_and_stream_execute_v3(scratch)
+ : update_planes_and_stream_execute_v2(scratch);
+}
+
+bool dc_update_planes_and_stream_cleanup(
+ struct dc_update_scratch_space *scratch
+)
+{
+ return scratch->update_v3
+ ? update_planes_and_stream_cleanup_v3(scratch)
+ : update_planes_and_stream_cleanup_v2(scratch);
+}
+
diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/core/dc_hw_sequencer.c
index e2763b60482a..052d573408c3 100644
--- a/drivers/gpu/drm/amd/display/dc/core/dc_hw_sequencer.c
+++ b/drivers/gpu/drm/amd/display/dc/core/dc_hw_sequencer.c
@@ -741,6 +741,7 @@ void hwss_build_fast_sequence(struct dc *dc,
struct dce_hwseq *hws = dc->hwseq;
struct pipe_ctx *current_pipe = NULL;
struct pipe_ctx *current_mpc_pipe = NULL;
+ bool is_dmub_lock_required = false;
unsigned int i = 0;
*num_steps = 0; // Initialize to 0
@@ -763,11 +764,12 @@ void hwss_build_fast_sequence(struct dc *dc,
(*num_steps)++;
}
if (dc->hwss.dmub_hw_control_lock_fast) {
+ is_dmub_lock_required = dc_state_is_fams2_in_use(dc, context) ||
+ dmub_hw_lock_mgr_does_link_require_lock(dc, stream->link);
+
block_sequence[*num_steps].params.dmub_hw_control_lock_fast_params.dc = dc;
block_sequence[*num_steps].params.dmub_hw_control_lock_fast_params.lock = true;
- block_sequence[*num_steps].params.dmub_hw_control_lock_fast_params.is_required =
- dc_state_is_fams2_in_use(dc, context) ||
- dmub_hw_lock_mgr_does_link_require_lock(dc, stream->link);
+ block_sequence[*num_steps].params.dmub_hw_control_lock_fast_params.is_required = is_dmub_lock_required;
block_sequence[*num_steps].func = DMUB_HW_CONTROL_LOCK_FAST;
(*num_steps)++;
}
@@ -906,7 +908,7 @@ void hwss_build_fast_sequence(struct dc *dc,
if (dc->hwss.dmub_hw_control_lock_fast) {
block_sequence[*num_steps].params.dmub_hw_control_lock_fast_params.dc = dc;
block_sequence[*num_steps].params.dmub_hw_control_lock_fast_params.lock = false;
- block_sequence[*num_steps].params.dmub_hw_control_lock_fast_params.is_required = dc_state_is_fams2_in_use(dc, context);
+ block_sequence[*num_steps].params.dmub_hw_control_lock_fast_params.is_required = is_dmub_lock_required;
block_sequence[*num_steps].func = DMUB_HW_CONTROL_LOCK_FAST;
(*num_steps)++;
}
diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link_exports.c b/drivers/gpu/drm/amd/display/dc/core/dc_link_exports.c
index 9acd30019717..7bb4504889be 100644
--- a/drivers/gpu/drm/amd/display/dc/core/dc_link_exports.c
+++ b/drivers/gpu/drm/amd/display/dc/core/dc_link_exports.c
@@ -491,6 +491,28 @@ bool dc_link_get_replay_state(const struct dc_link *link, uint64_t *state)
return link->dc->link_srv->edp_get_replay_state(link, state);
}
+bool dc_link_set_pr_enable(struct dc_link *link, bool enable)
+{
+ return link->dc->link_srv->dp_pr_enable(link, enable);
+}
+
+bool dc_link_update_pr_state(struct dc_link *link,
+ struct dmub_cmd_pr_update_state_data *update_state_data)
+{
+ return link->dc->link_srv->dp_pr_update_state(link, update_state_data);
+}
+
+bool dc_link_set_pr_general_cmd(struct dc_link *link,
+ struct dmub_cmd_pr_general_cmd_data *general_cmd_data)
+{
+ return link->dc->link_srv->dp_pr_set_general_cmd(link, general_cmd_data);
+}
+
+bool dc_link_get_pr_state(const struct dc_link *link, uint64_t *state)
+{
+ return link->dc->link_srv->dp_pr_get_state(link, state);
+}
+
bool dc_link_wait_for_t12(struct dc_link *link)
{
return link->dc->link_srv->edp_wait_for_t12(link);
@@ -527,4 +549,3 @@ void dc_link_get_alpm_support(struct dc_link *link,
{
link->dc->link_srv->edp_get_alpm_support(link, auxless_support, auxwake_support);
}
-
diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_stream.c b/drivers/gpu/drm/amd/display/dc/core/dc_stream.c
index 129cd5f84983..f59020f1a722 100644
--- a/drivers/gpu/drm/amd/display/dc/core/dc_stream.c
+++ b/drivers/gpu/drm/amd/display/dc/core/dc_stream.c
@@ -151,6 +151,7 @@ static void dc_stream_free(struct kref *kref)
struct dc_stream_state *stream = container_of(kref, struct dc_stream_state, refcount);
dc_stream_destruct(stream);
+ kfree(stream->update_scratch);
kfree(stream);
}
@@ -164,26 +165,32 @@ void dc_stream_release(struct dc_stream_state *stream)
struct dc_stream_state *dc_create_stream_for_sink(
struct dc_sink *sink)
{
- struct dc_stream_state *stream;
+ struct dc_stream_state *stream = NULL;
if (sink == NULL)
- return NULL;
+ goto fail;
stream = kzalloc(sizeof(struct dc_stream_state), GFP_KERNEL);
if (stream == NULL)
- goto alloc_fail;
+ goto fail;
+
+ stream->update_scratch = kzalloc((int32_t) dc_update_scratch_space_size(), GFP_KERNEL);
+ if (stream->update_scratch == NULL)
+ goto fail;
if (dc_stream_construct(stream, sink) == false)
- goto construct_fail;
+ goto fail;
kref_init(&stream->refcount);
return stream;
-construct_fail:
- kfree(stream);
+fail:
+ if (stream) {
+ kfree(stream->update_scratch);
+ kfree(stream);
+ }
-alloc_fail:
return NULL;
}
@@ -195,6 +202,16 @@ struct dc_stream_state *dc_copy_stream(const struct dc_stream_state *stream)
if (!new_stream)
return NULL;
+ // Scratch is not meant to be reused across copies, as might have self-referential pointers
+ new_stream->update_scratch = kzalloc(
+ (int32_t) dc_update_scratch_space_size(),
+ GFP_KERNEL
+ );
+ if (!new_stream->update_scratch) {
+ kfree(new_stream);
+ return NULL;
+ }
+
if (new_stream->sink)
dc_sink_retain(new_stream->sink);
@@ -498,6 +515,19 @@ bool dc_stream_program_cursor_position(
}
}
+ /* apply manual trigger */
+ int i;
+
+ for (i = 0; i < dc->res_pool->pipe_count; i++) {
+ struct pipe_ctx *pipe_ctx = &dc->current_state->res_ctx.pipe_ctx[i];
+
+ /* trigger event on first pipe with current stream */
+ if (stream == pipe_ctx->stream) {
+ pipe_ctx->stream_res.tg->funcs->program_manual_trigger(pipe_ctx->stream_res.tg);
+ break;
+ }
+ }
+
return true;
}
diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h
index 29edfa51ea2c..ab19b6230945 100644
--- a/drivers/gpu/drm/amd/display/dc/dc.h
+++ b/drivers/gpu/drm/amd/display/dc/dc.h
@@ -63,7 +63,7 @@ struct dcn_dsc_reg_state;
struct dcn_optc_reg_state;
struct dcn_dccg_reg_state;
-#define DC_VER "3.2.359"
+#define DC_VER "3.2.367"
/**
* MAX_SURFACES - representative of the upper bound of surfaces that can be piped to a single CRTC
@@ -82,6 +82,8 @@ struct dcn_dccg_reg_state;
#define MAX_DPIA_PER_HOST_ROUTER 3
#define MAX_DPIA_NUM (MAX_HOST_ROUTERS_NUM * MAX_DPIA_PER_HOST_ROUTER)
+#define NUM_FAST_FLIPS_TO_STEADY_STATE 20
+
/* Display Core Interfaces */
struct dc_versions {
const char *dc_ver;
@@ -293,6 +295,9 @@ struct dc_check_config {
*/
unsigned int max_optimizable_video_width;
bool enable_legacy_fast_update;
+
+ bool deferred_transition_state;
+ unsigned int transition_countdown_to_steady_state;
};
struct dc_caps {
@@ -951,6 +956,19 @@ struct dc_bounding_box_overrides {
int min_dcfclk_mhz;
};
+struct dc_qos_info {
+ uint32_t actual_peak_bw_in_mbps;
+ uint32_t qos_bandwidth_lb_in_mbps;
+ uint32_t actual_avg_bw_in_mbps;
+ uint32_t calculated_avg_bw_in_mbps;
+ uint32_t actual_max_latency_in_ns;
+ uint32_t actual_min_latency_in_ns;
+ uint32_t qos_max_latency_ub_in_ns;
+ uint32_t actual_avg_latency_in_ns;
+ uint32_t qos_avg_latency_ub_in_ns;
+ uint32_t dcn_bandwidth_ub_in_mbps;
+};
+
struct dc_state;
struct resource_pool;
struct dce_hwseq;
@@ -1188,6 +1206,11 @@ struct dc_debug_options {
short auxless_alpm_lfps_t1t2_offset_us;
bool disable_stutter_for_wm_program;
bool enable_block_sequence_programming;
+ uint32_t custom_psp_footer_size;
+ bool disable_deferred_minimal_transitions;
+ unsigned int num_fast_flips_to_steady_state_override;
+ bool enable_dmu_recovery;
+ unsigned int force_vmin_threshold;
};
@@ -1707,13 +1730,13 @@ struct dc_scratch_space {
struct dc_link_status link_status;
struct dprx_states dprx_states;
- struct gpio *hpd_gpio;
enum dc_link_fec_state fec_state;
bool is_dds;
bool is_display_mux_present;
bool link_powered_externally; // Used to bypass hardware sequencing delays when panel is powered down forcibly
struct dc_panel_config panel_config;
+ enum dc_panel_type panel_type;
struct phy_state phy_state;
uint32_t phy_transition_bitmask;
// BW ALLOCATON USB4 ONLY
@@ -2455,6 +2478,48 @@ bool dc_link_set_replay_allow_active(struct dc_link *dc_link, const bool *enable
bool dc_link_get_replay_state(const struct dc_link *dc_link, uint64_t *state);
+/*
+ * Enable or disable Panel Replay on the specified link:
+ *
+ * @link: pointer to the dc_link struct instance
+ * @enable: enable or disable Panel Replay
+ *
+ * return: true if successful, false otherwise
+ */
+bool dc_link_set_pr_enable(struct dc_link *link, bool enable);
+
+/*
+ * Update Panel Replay state parameters:
+ *
+ * @link: pointer to the dc_link struct instance
+ * @update_state_data: pointer to state update data structure
+ *
+ * return: true if successful, false otherwise
+ */
+bool dc_link_update_pr_state(struct dc_link *link,
+ struct dmub_cmd_pr_update_state_data *update_state_data);
+
+/*
+ * Send general command to Panel Replay firmware:
+ *
+ * @link: pointer to the dc_link struct instance
+ * @general_cmd_data: pointer to general command data structure
+ *
+ * return: true if successful, false otherwise
+ */
+bool dc_link_set_pr_general_cmd(struct dc_link *link,
+ struct dmub_cmd_pr_general_cmd_data *general_cmd_data);
+
+/*
+ * Get Panel Replay state:
+ *
+ * @link: pointer to the dc_link struct instance
+ * @state: pointer to store the Panel Replay state
+ *
+ * return: true if successful, false otherwise
+ */
+bool dc_link_get_pr_state(const struct dc_link *link, uint64_t *state);
+
/* On eDP links this function call will stall until T12 has elapsed.
* If the panel is not in power off state, this function will return
* immediately.
@@ -2793,7 +2858,7 @@ void dc_get_underflow_debug_data_for_otg(struct dc *dc, int primary_otg_inst, st
void dc_get_power_feature_status(struct dc *dc, int primary_otg_inst, struct power_features *out_data);
-/**
+/*
* Software state variables used to program register fields across the display pipeline
*/
struct dc_register_software_state {
@@ -3280,4 +3345,28 @@ struct dc_register_software_state {
*/
bool dc_capture_register_software_state(struct dc *dc, struct dc_register_software_state *state);
+/**
+ * dc_get_qos_info() - Retrieve Quality of Service (QoS) information from display core
+ * @dc: DC context containing current display configuration
+ * @info: Pointer to dc_qos_info structure to populate with QoS metrics
+ *
+ * This function retrieves QoS metrics from the display core that can be used by
+ * benchmark tools to analyze display system performance. The function may take
+ * several milliseconds to execute due to hardware measurement requirements.
+ *
+ * QoS information includes:
+ * - Bandwidth bounds (lower limits in Mbps)
+ * - Latency bounds (upper limits in nanoseconds)
+ * - Hardware-measured bandwidth metrics (peak/average in Mbps)
+ * - Hardware-measured latency metrics (maximum/average in nanoseconds)
+ *
+ * The function will populate the provided dc_qos_info structure with current
+ * QoS measurements. If hardware measurement functions are not available for
+ * the current DCN version, the function returns false with zero'd info structure.
+ *
+ * Return: true if QoS information was successfully retrieved, false if measurement
+ * functions are unavailable or hardware measurements cannot be performed
+ */
+bool dc_get_qos_info(struct dc *dc, struct dc_qos_info *info);
+
#endif /* DC_INTERFACE_H_ */
diff --git a/drivers/gpu/drm/amd/display/dc/dc_dmub_srv.c b/drivers/gpu/drm/amd/display/dc/dc_dmub_srv.c
index 7b09af1cb306..dc1b3f6c22c9 100644
--- a/drivers/gpu/drm/amd/display/dc/dc_dmub_srv.c
+++ b/drivers/gpu/drm/amd/display/dc/dc_dmub_srv.c
@@ -41,6 +41,8 @@
#define DC_LOGGER CTX->logger
#define GPINT_RETRY_NUM 20
+#define MAX_WAIT_US 100000
+
static void dc_dmub_srv_construct(struct dc_dmub_srv *dc_srv, struct dc *dc,
struct dmub_srv *dmub)
{
@@ -48,6 +50,13 @@ static void dc_dmub_srv_construct(struct dc_dmub_srv *dc_srv, struct dc *dc,
dc_srv->ctx = dc->ctx;
}
+static void dc_dmub_srv_handle_failure(struct dc_dmub_srv *dc_dmub_srv)
+{
+ dc_dmub_srv_log_diagnostic_data(dc_dmub_srv);
+ if (dc_dmub_srv->ctx->dc->debug.enable_dmu_recovery)
+ dm_helpers_dmu_timeout(dc_dmub_srv->ctx);
+}
+
struct dc_dmub_srv *dc_dmub_srv_create(struct dc *dc, struct dmub_srv *dmub)
{
struct dc_dmub_srv *dc_srv =
@@ -84,12 +93,12 @@ bool dc_dmub_srv_wait_for_pending(struct dc_dmub_srv *dc_dmub_srv)
dmub = dc_dmub_srv->dmub;
do {
- status = dmub_srv_wait_for_pending(dmub, 100000);
+ status = dmub_srv_wait_for_pending(dmub, MAX_WAIT_US);
} while (dc_dmub_srv->ctx->dc->debug.disable_timeout && status != DMUB_STATUS_OK);
if (status != DMUB_STATUS_OK) {
DC_ERROR("Error waiting for DMUB idle: status=%d\n", status);
- dc_dmub_srv_log_diagnostic_data(dc_dmub_srv);
+ dc_dmub_srv_handle_failure(dc_dmub_srv);
}
return status == DMUB_STATUS_OK;
@@ -104,7 +113,7 @@ void dc_dmub_srv_clear_inbox0_ack(struct dc_dmub_srv *dc_dmub_srv)
status = dmub_srv_clear_inbox0_ack(dmub);
if (status != DMUB_STATUS_OK) {
DC_ERROR("Error clearing INBOX0 ack: status=%d\n", status);
- dc_dmub_srv_log_diagnostic_data(dc_dmub_srv);
+ dc_dmub_srv_handle_failure(dc_dmub_srv);
}
}
@@ -114,10 +123,10 @@ void dc_dmub_srv_wait_for_inbox0_ack(struct dc_dmub_srv *dc_dmub_srv)
struct dc_context *dc_ctx = dc_dmub_srv->ctx;
enum dmub_status status = DMUB_STATUS_OK;
- status = dmub_srv_wait_for_inbox0_ack(dmub, 100000);
+ status = dmub_srv_wait_for_inbox0_ack(dmub, MAX_WAIT_US);
if (status != DMUB_STATUS_OK) {
DC_ERROR("Error waiting for INBOX0 HW Lock Ack\n");
- dc_dmub_srv_log_diagnostic_data(dc_dmub_srv);
+ dc_dmub_srv_handle_failure(dc_dmub_srv);
}
}
@@ -131,7 +140,7 @@ void dc_dmub_srv_send_inbox0_cmd(struct dc_dmub_srv *dc_dmub_srv,
status = dmub_srv_send_inbox0_cmd(dmub, data);
if (status != DMUB_STATUS_OK) {
DC_ERROR("Error sending INBOX0 cmd\n");
- dc_dmub_srv_log_diagnostic_data(dc_dmub_srv);
+ dc_dmub_srv_handle_failure(dc_dmub_srv);
}
}
@@ -153,7 +162,7 @@ static bool dc_dmub_srv_reg_cmd_list_queue_execute(struct dc_dmub_srv *dc_dmub_s
for (i = 0 ; i < count; i++) {
/* confirm no messages pending */
do {
- status = dmub_srv_wait_for_idle(dmub, 100000);
+ status = dmub_srv_wait_for_idle(dmub, MAX_WAIT_US);
} while (dc_dmub_srv->ctx->dc->debug.disable_timeout && status != DMUB_STATUS_OK);
/* queue command */
@@ -169,7 +178,7 @@ static bool dc_dmub_srv_reg_cmd_list_queue_execute(struct dc_dmub_srv *dc_dmub_s
if (status != DMUB_STATUS_OK) {
if (status != DMUB_STATUS_POWER_STATE_D3) {
DC_ERROR("Error starting DMUB execution: status=%d\n", status);
- dc_dmub_srv_log_diagnostic_data(dc_dmub_srv);
+ dc_dmub_srv_handle_failure(dc_dmub_srv);
}
return false;
}
@@ -208,7 +217,7 @@ static bool dc_dmub_srv_fb_cmd_list_queue_execute(struct dc_dmub_srv *dc_dmub_sr
return false;
do {
- status = dmub_srv_wait_for_inbox_free(dmub, 100000, count - i);
+ status = dmub_srv_wait_for_inbox_free(dmub, MAX_WAIT_US, count - i);
} while (dc_dmub_srv->ctx->dc->debug.disable_timeout && status != DMUB_STATUS_OK);
/* Requeue the command. */
@@ -218,7 +227,7 @@ static bool dc_dmub_srv_fb_cmd_list_queue_execute(struct dc_dmub_srv *dc_dmub_sr
if (status != DMUB_STATUS_OK) {
if (status != DMUB_STATUS_POWER_STATE_D3) {
DC_ERROR("Error queueing DMUB command: status=%d\n", status);
- dc_dmub_srv_log_diagnostic_data(dc_dmub_srv);
+ dc_dmub_srv_handle_failure(dc_dmub_srv);
}
return false;
}
@@ -228,7 +237,7 @@ static bool dc_dmub_srv_fb_cmd_list_queue_execute(struct dc_dmub_srv *dc_dmub_sr
if (status != DMUB_STATUS_OK) {
if (status != DMUB_STATUS_POWER_STATE_D3) {
DC_ERROR("Error starting DMUB execution: status=%d\n", status);
- dc_dmub_srv_log_diagnostic_data(dc_dmub_srv);
+ dc_dmub_srv_handle_failure(dc_dmub_srv);
}
return false;
}
@@ -271,7 +280,7 @@ bool dc_dmub_srv_wait_for_idle(struct dc_dmub_srv *dc_dmub_srv,
// Wait for DMUB to process command
if (wait_type != DM_DMUB_WAIT_TYPE_NO_WAIT) {
do {
- status = dmub_srv_wait_for_idle(dmub, 100000);
+ status = dmub_srv_wait_for_idle(dmub, MAX_WAIT_US);
} while (dc_dmub_srv->ctx->dc->debug.disable_timeout && status != DMUB_STATUS_OK);
if (status != DMUB_STATUS_OK) {
@@ -282,7 +291,7 @@ bool dc_dmub_srv_wait_for_idle(struct dc_dmub_srv *dc_dmub_srv,
dmub->debug.timeout_info.timeout_cmd = *cmd_list;
dmub->debug.timeout_info.timestamp = dm_get_timestamp(dc_dmub_srv->ctx);
}
- dc_dmub_srv_log_diagnostic_data(dc_dmub_srv);
+ dc_dmub_srv_handle_failure(dc_dmub_srv);
return false;
}
@@ -999,6 +1008,7 @@ void dc_dmub_srv_log_diagnostic_data(struct dc_dmub_srv *dc_dmub_srv)
DC_LOG_DEBUG(" is_traceport_en : %d", dc_dmub_srv->dmub->debug.is_traceport_en);
DC_LOG_DEBUG(" is_cw0_en : %d", dc_dmub_srv->dmub->debug.is_cw0_enabled);
DC_LOG_DEBUG(" is_cw6_en : %d", dc_dmub_srv->dmub->debug.is_cw6_enabled);
+ DC_LOG_DEBUG(" is_pwait : %d", dc_dmub_srv->dmub->debug.is_pwait);
}
static bool dc_dmub_should_update_cursor_data(struct pipe_ctx *pipe_ctx)
@@ -1833,9 +1843,10 @@ static void dc_dmub_srv_rb_based_fams2_update_config(struct dc *dc,
/* apply feature configuration based on current driver state */
global_cmd->config.global.features.bits.enable_visual_confirm = dc->debug.visual_confirm == VISUAL_CONFIRM_FAMS2;
- global_cmd->config.global.features.bits.enable = enable;
+ global_cmd->config.global.features.bits.enable = enable && context->bw_ctx.bw.dcn.fams2_global_config.features.bits.enable;
+ global_cmd->config.global.features.bits.enable_ppt_check = dc->debug.fams2_config.bits.enable_ppt_check;
- if (enable && context->bw_ctx.bw.dcn.fams2_global_config.features.bits.enable) {
+ if (enable) {
/* set multi pending for global, and unset for last stream cmd */
global_cmd->header.multi_cmd_pending = 1;
cmd[2 * context->bw_ctx.bw.dcn.fams2_global_config.num_streams].fams2_config.header.multi_cmd_pending = 0;
@@ -1862,16 +1873,16 @@ static void dc_dmub_srv_ib_based_fams2_update_config(struct dc *dc,
cmd.ib_fams2_config.ib_data.src.quad_part = dc->ctx->dmub_srv->dmub->ib_mem_gart.gpu_addr;
cmd.ib_fams2_config.ib_data.size = sizeof(*config);
- if (enable && context->bw_ctx.bw.dcn.fams2_global_config.features.bits.enable) {
+ if (enable) {
+ /* send global configuration parameters */
+ memcpy(&config->global, &context->bw_ctx.bw.dcn.fams2_global_config,
+ sizeof(struct dmub_cmd_fams2_global_config));
+
/* copy static feature configuration overrides */
config->global.features.bits.enable_stall_recovery = dc->debug.fams2_config.bits.enable_stall_recovery;
config->global.features.bits.enable_offload_flip = dc->debug.fams2_config.bits.enable_offload_flip;
config->global.features.bits.enable_debug = dc->debug.fams2_config.bits.enable_debug;
- /* send global configuration parameters */
- memcpy(&config->global, &context->bw_ctx.bw.dcn.fams2_global_config,
- sizeof(struct dmub_cmd_fams2_global_config));
-
/* construct per-stream configs */
for (i = 0; i < context->bw_ctx.bw.dcn.fams2_global_config.num_streams; i++) {
/* copy stream static base state */
@@ -1887,7 +1898,8 @@ static void dc_dmub_srv_ib_based_fams2_update_config(struct dc *dc,
}
config->global.features.bits.enable_visual_confirm = dc->debug.visual_confirm == VISUAL_CONFIRM_FAMS2;
- config->global.features.bits.enable = enable;
+ config->global.features.bits.enable = enable && context->bw_ctx.bw.dcn.fams2_global_config.features.bits.enable;
+ config->global.features.bits.enable_ppt_check = dc->debug.fams2_config.bits.enable_ppt_check;
dm_execute_dmub_cmd_list(dc->ctx, 1, &cmd, DM_DMUB_WAIT_TYPE_WAIT);
}
diff --git a/drivers/gpu/drm/amd/display/dc/dc_dp_types.h b/drivers/gpu/drm/amd/display/dc/dc_dp_types.h
index 79e1696def63..5e3646b7550c 100644
--- a/drivers/gpu/drm/amd/display/dc/dc_dp_types.h
+++ b/drivers/gpu/drm/amd/display/dc/dc_dp_types.h
@@ -1167,6 +1167,25 @@ union dpcd_panel_replay_capability_supported {
unsigned char raw;
};
+union dpcd_panel_replay_capability {
+ struct {
+ unsigned char RESERVED :2;
+ unsigned char DSC_DECODE_NOT_SUPPORTED :1;
+ unsigned char ASYNC_VIDEO_TIMING_NOT_SUPPORTED :1;
+ unsigned char DSC_CRC_OF_MULTI_SU_SUPPORTED :1;
+ unsigned char PR_SU_GRANULARITY_NEEDED :1;
+ unsigned char SU_Y_GRANULARITY_EXT_CAP_SUPPORTED :1;
+ unsigned char LINK_OFF_SUPPORTED_IN_PR_ACTIVE :1;
+ } bits;
+ unsigned char raw;
+};
+
+struct dpcd_panel_replay_selective_update_info {
+ uint16_t pr_su_x_granularity;
+ uint8_t pr_su_y_granularity;
+ uint16_t pr_su_y_granularity_extended_caps;
+};
+
enum dpcd_downstream_port_max_bpc {
DOWN_STREAM_MAX_8BPC = 0,
DOWN_STREAM_MAX_10BPC,
@@ -1290,12 +1309,15 @@ struct dpcd_caps {
struct edp_psr_info psr_info;
struct replay_info pr_info;
- union dpcd_panel_replay_capability_supported pr_caps_supported;
+ union dpcd_panel_replay_capability_supported vesa_replay_caps_supported;
+ union dpcd_panel_replay_capability vesa_replay_caps;
+ struct dpcd_panel_replay_selective_update_info vesa_replay_su_info;
uint16_t edp_oled_emission_rate;
union dp_receive_port0_cap receive_port0_cap;
/* Indicates the number of SST links supported by MSO (Multi-Stream Output) */
uint8_t mso_cap_sst_links_supported;
uint8_t dp_edp_general_cap_2;
+ uint16_t drr_granularity;
};
union dpcd_sink_ext_caps {
@@ -1401,6 +1423,17 @@ union dpcd_sink_active_vtotal_control_mode {
unsigned char raw;
};
+union pr_error_status {
+ struct {
+ unsigned char LINK_CRC_ERROR :1;
+ unsigned char RFB_STORAGE_ERROR :1;
+ unsigned char VSC_SDP_ERROR :1;
+ unsigned char ASSDP_MISSING_ERROR :1;
+ unsigned char RESERVED :4;
+ } bits;
+ unsigned char raw;
+};
+
union psr_error_status {
struct {
unsigned char LINK_CRC_ERROR :1;
diff --git a/drivers/gpu/drm/amd/display/dc/dc_hw_types.h b/drivers/gpu/drm/amd/display/dc/dc_hw_types.h
index 667852517246..cfa569a7bff1 100644
--- a/drivers/gpu/drm/amd/display/dc/dc_hw_types.h
+++ b/drivers/gpu/drm/amd/display/dc/dc_hw_types.h
@@ -491,6 +491,12 @@ struct dc_cursor_position {
* for each plane.
*/
bool translate_by_source;
+
+ /**
+ * @use_viewport_for_clip: Use viewport position for clip_x calculation
+ * instead of clip_rect. Required to protect against clip being overwritten
+ */
+ bool use_viewport_for_clip;
};
struct dc_cursor_mi_param {
diff --git a/drivers/gpu/drm/amd/display/dc/dc_stream.h b/drivers/gpu/drm/amd/display/dc/dc_stream.h
index 321cfe92d799..719b98d8e8ca 100644
--- a/drivers/gpu/drm/amd/display/dc/dc_stream.h
+++ b/drivers/gpu/drm/amd/display/dc/dc_stream.h
@@ -315,6 +315,8 @@ struct dc_stream_state {
struct luminance_data lumin_data;
bool scaler_sharpener_update;
bool sharpening_required;
+
+ struct dc_update_scratch_space *update_scratch;
};
#define ABM_LEVEL_IMMEDIATE_DISABLE 255
@@ -390,6 +392,33 @@ bool dc_update_planes_and_stream(struct dc *dc,
struct dc_stream_state *dc_stream,
struct dc_stream_update *stream_update);
+struct dc_update_scratch_space;
+
+size_t dc_update_scratch_space_size(void);
+
+struct dc_update_scratch_space *dc_update_planes_and_stream_init(
+ struct dc *dc,
+ struct dc_surface_update *surface_updates,
+ int surface_count,
+ struct dc_stream_state *dc_stream,
+ struct dc_stream_update *stream_update
+);
+
+// Locked, false is failed
+bool dc_update_planes_and_stream_prepare(
+ struct dc_update_scratch_space *scratch
+);
+
+// Unlocked
+void dc_update_planes_and_stream_execute(
+ const struct dc_update_scratch_space *scratch
+);
+
+// Locked, true if call again
+bool dc_update_planes_and_stream_cleanup(
+ struct dc_update_scratch_space *scratch
+);
+
/*
* Set up surface attributes and associate to a stream
* The surfaces parameter is an absolute set of all surface active for the stream.
@@ -597,7 +626,7 @@ struct pipe_ctx *dc_stream_get_pipe_ctx(struct dc_stream_state *stream);
void dc_dmub_update_dirty_rect(struct dc *dc,
int surface_count,
struct dc_stream_state *stream,
- struct dc_surface_update *srf_updates,
+ const struct dc_surface_update *srf_updates,
struct dc_state *context);
bool dc_stream_is_cursor_limit_pending(struct dc *dc, struct dc_stream_state *stream);
diff --git a/drivers/gpu/drm/amd/display/dc/dc_types.h b/drivers/gpu/drm/amd/display/dc/dc_types.h
index f46039f64203..0e953059ff6d 100644
--- a/drivers/gpu/drm/amd/display/dc/dc_types.h
+++ b/drivers/gpu/drm/amd/display/dc/dc_types.h
@@ -275,6 +275,7 @@ enum dc_timing_source {
TIMING_SOURCE_CV,
TIMING_SOURCE_TV,
TIMING_SOURCE_HDMI_VIC,
+ TIMING_SOURCE_CEA_VIC,
/* implicitly specified by display device, still safe but less important*/
TIMING_SOURCE_DEFAULT,
@@ -354,7 +355,7 @@ enum dc_connection_type {
dc_connection_single,
dc_connection_mst_branch,
dc_connection_sst_branch,
- dc_connection_dac_load
+ dc_connection_analog_load
};
struct dc_csc_adjustments {
@@ -963,6 +964,13 @@ struct display_endpoint_id {
enum display_endpoint_type ep_type;
};
+enum dc_panel_type {
+ PANEL_TYPE_NONE = 0, // UNKONWN, not determined yet
+ PANEL_TYPE_LCD = 1,
+ PANEL_TYPE_OLED = 2,
+ PANEL_TYPE_MINILED = 3,
+};
+
enum backlight_control_type {
BACKLIGHT_CONTROL_PWM = 0,
BACKLIGHT_CONTROL_VESA_AUX = 1,
@@ -1078,6 +1086,7 @@ enum replay_coasting_vtotal_type {
PR_COASTING_TYPE_STATIC,
PR_COASTING_TYPE_FULL_SCREEN_VIDEO,
PR_COASTING_TYPE_TEST_HARNESS,
+ PR_COASTING_TYPE_VIDEO_CONFERENCING_V2,
PR_COASTING_TYPE_NUM,
};
@@ -1099,7 +1108,6 @@ enum replay_FW_Message_type {
Replay_Set_Residency_Frameupdate_Timer,
Replay_Set_Pseudo_VTotal,
Replay_Disabled_Adaptive_Sync_SDP,
- Replay_Set_Version,
Replay_Set_General_Cmd,
};
@@ -1134,6 +1142,17 @@ union replay_low_refresh_rate_enable_options {
unsigned int raw;
};
+union replay_optimization {
+ struct {
+ //BIT[0-3]: Replay Teams Optimization
+ unsigned int TEAMS_OPTIMIZATION_VER_1 :1;
+ unsigned int TEAMS_OPTIMIZATION_VER_2 :1;
+ unsigned int RESERVED_2_3 :2;
+ } bits;
+
+ unsigned int raw;
+};
+
struct replay_config {
/* Replay version */
enum dc_replay_version replay_version;
@@ -1171,6 +1190,10 @@ struct replay_config {
enum dc_alpm_mode alpm_mode;
/* Replay full screen only */
bool os_request_force_ffu;
+ /* Replay optimization */
+ union replay_optimization replay_optimization;
+ /* Replay sub feature Frame Skipping is supported */
+ bool frame_skip_supported;
};
/* Replay feature flags*/
@@ -1207,6 +1230,8 @@ struct replay_settings {
uint32_t replay_desync_error_fail_count;
/* The frame skip number dal send to DMUB */
uint16_t frame_skip_number;
+ /* Current Panel Replay event */
+ uint32_t replay_events;
};
/* To split out "global" and "per-panel" config settings.
diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.c b/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.c
index 87dbb8d7ed27..7f0766b5fa3d 100644
--- a/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.c
+++ b/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.c
@@ -117,6 +117,8 @@ static const struct link_encoder_funcs dce110_lnk_enc_funcs = {
.destroy = dce110_link_encoder_destroy,
.get_max_link_cap = dce110_link_encoder_get_max_link_cap,
.get_dig_frontend = dce110_get_dig_frontend,
+ .get_hpd_state = dce110_get_hpd_state,
+ .program_hpd_filter = dce110_program_hpd_filter,
};
static enum bp_result link_transmitter_control(
@@ -850,7 +852,9 @@ void dce110_link_encoder_construct(
enc110->base.funcs = &dce110_lnk_enc_funcs;
enc110->base.ctx = init_data->ctx;
enc110->base.id = init_data->encoder;
+ enc110->base.analog_id = init_data->analog_encoder;
+ enc110->base.hpd_gpio = init_data->hpd_gpio;
enc110->base.hpd_source = init_data->hpd_source;
enc110->base.connector = init_data->connector;
@@ -1053,6 +1057,11 @@ void dce110_link_encoder_hw_init(
void dce110_link_encoder_destroy(struct link_encoder **enc)
{
+ if ((*enc)->hpd_gpio) {
+ dal_gpio_destroy_irq(&(*enc)->hpd_gpio);
+ (*enc)->hpd_gpio = NULL;
+ }
+
kfree(TO_DCE110_LINK_ENC(*enc));
*enc = NULL;
}
@@ -1751,6 +1760,40 @@ void dce110_link_encoder_get_max_link_cap(struct link_encoder *enc,
*link_settings = max_link_cap;
}
+bool dce110_get_hpd_state(struct link_encoder *enc)
+{
+ uint32_t state = 0;
+
+ if (!enc->hpd_gpio)
+ return false;
+
+ dal_gpio_lock_pin(enc->hpd_gpio);
+ dal_gpio_get_value(enc->hpd_gpio, &state);
+ dal_gpio_unlock_pin(enc->hpd_gpio);
+
+ return state;
+}
+
+bool dce110_program_hpd_filter(struct link_encoder *enc, int delay_on_connect_in_ms, int delay_on_disconnect_in_ms)
+{
+ /* Setup HPD filtering */
+ if (enc->hpd_gpio && dal_gpio_lock_pin(enc->hpd_gpio) == GPIO_RESULT_OK) {
+ struct gpio_hpd_config config;
+
+ config.delay_on_connect = delay_on_connect_in_ms;
+ config.delay_on_disconnect = delay_on_disconnect_in_ms;
+
+ dal_irq_setup_hpd_filter(enc->hpd_gpio, &config);
+
+ dal_gpio_unlock_pin(enc->hpd_gpio);
+
+ return true;
+ } else {
+ ASSERT(0);
+ return false;
+ }
+}
+
#if defined(CONFIG_DRM_AMD_DC_SI)
static const struct link_encoder_funcs dce60_lnk_enc_funcs = {
.validate_output_with_stream =
@@ -1775,7 +1818,9 @@ static const struct link_encoder_funcs dce60_lnk_enc_funcs = {
.is_dig_enabled = dce110_is_dig_enabled,
.destroy = dce110_link_encoder_destroy,
.get_max_link_cap = dce110_link_encoder_get_max_link_cap,
- .get_dig_frontend = dce110_get_dig_frontend
+ .get_dig_frontend = dce110_get_dig_frontend,
+ .get_hpd_state = dce110_get_hpd_state,
+ .program_hpd_filter = dce110_program_hpd_filter,
};
void dce60_link_encoder_construct(
@@ -1793,7 +1838,9 @@ void dce60_link_encoder_construct(
enc110->base.funcs = &dce60_lnk_enc_funcs;
enc110->base.ctx = init_data->ctx;
enc110->base.id = init_data->encoder;
+ enc110->base.analog_id = init_data->analog_encoder;
+ enc110->base.hpd_gpio = init_data->hpd_gpio;
enc110->base.hpd_source = init_data->hpd_source;
enc110->base.connector = init_data->connector;
diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.h b/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.h
index c58b69bc319b..9ba533aa6f88 100644
--- a/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.h
+++ b/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.h
@@ -130,11 +130,6 @@
SRI(DP_DPHY_HBR2_PATTERN_CONTROL, DP, id), \
SR(DCI_MEM_PWR_STATUS)
-#define LE_DCN10_REG_LIST(id)\
- LE_COMMON_REG_LIST_BASE(id), \
- SRI(DP_DPHY_BS_SR_SWAP_CNTL, DP, id), \
- SRI(DP_DPHY_INTERNAL_CTRL, DP, id), \
- SRI(DP_DPHY_HBR2_PATTERN_CONTROL, DP, id)
struct dce110_link_enc_aux_registers {
uint32_t AUX_CONTROL;
@@ -319,4 +314,7 @@ bool dce110_is_dig_enabled(struct link_encoder *enc);
void dce110_link_encoder_get_max_link_cap(struct link_encoder *enc,
struct dc_link_settings *link_settings);
+bool dce110_get_hpd_state(struct link_encoder *enc);
+bool dce110_program_hpd_filter(struct link_encoder *enc, int delay_on_connect_in_ms, int delay_on_disconnect_in_ms);
+
#endif /* __DC_LINK_ENCODER__DCE110_H__ */
diff --git a/drivers/gpu/drm/amd/display/dc/dce/dmub_hw_lock_mgr.c b/drivers/gpu/drm/amd/display/dc/dce/dmub_hw_lock_mgr.c
index 5bfa2b0d2afd..7116fdd4c7ec 100644
--- a/drivers/gpu/drm/amd/display/dc/dce/dmub_hw_lock_mgr.c
+++ b/drivers/gpu/drm/amd/display/dc/dce/dmub_hw_lock_mgr.c
@@ -69,7 +69,7 @@ bool dmub_hw_lock_mgr_does_link_require_lock(const struct dc *dc, const struct d
if (link->psr_settings.psr_version == DC_PSR_VERSION_SU_1)
return true;
- if (link->replay_settings.replay_feature_enabled)
+ if (link->replay_settings.replay_feature_enabled && dc_is_embedded_signal(link->connector_signal))
return true;
if (link->psr_settings.psr_version == DC_PSR_VERSION_1) {
diff --git a/drivers/gpu/drm/amd/display/dc/dce/dmub_replay.c b/drivers/gpu/drm/amd/display/dc/dce/dmub_replay.c
index cf1372aaff6c..fd8244c94687 100644
--- a/drivers/gpu/drm/amd/display/dc/dce/dmub_replay.c
+++ b/drivers/gpu/drm/amd/display/dc/dce/dmub_replay.c
@@ -387,19 +387,6 @@ static void dmub_replay_send_cmd(struct dmub_replay *dmub,
cmd.replay_disabled_adaptive_sync_sdp.data.force_disabled =
cmd_element->disabled_adaptive_sync_sdp_data.force_disabled;
break;
- case Replay_Set_Version:
- //Header
- cmd.replay_set_version.header.sub_type =
- DMUB_CMD__REPLAY_SET_VERSION;
- cmd.replay_set_version.header.payload_bytes =
- sizeof(struct dmub_rb_cmd_replay_set_version) -
- sizeof(struct dmub_cmd_header);
- //Cmd Body
- cmd.replay_set_version.replay_set_version_data.panel_inst =
- cmd_element->version_data.panel_inst;
- cmd.replay_set_version.replay_set_version_data.version =
- cmd_element->version_data.version;
- break;
case Replay_Set_General_Cmd:
//Header
cmd.replay_set_general_cmd.header.sub_type =
diff --git a/drivers/gpu/drm/amd/display/dc/dcn201/dcn201_link_encoder.c b/drivers/gpu/drm/amd/display/dc/dcn201/dcn201_link_encoder.c
index 8d31fa131cd6..9459e8f28338 100644
--- a/drivers/gpu/drm/amd/display/dc/dcn201/dcn201_link_encoder.c
+++ b/drivers/gpu/drm/amd/display/dc/dcn201/dcn201_link_encoder.c
@@ -104,6 +104,8 @@ static const struct link_encoder_funcs dcn201_link_enc_funcs = {
.fec_is_active = enc2_fec_is_active,
.is_in_alt_mode = dcn201_link_encoder_is_in_alt_mode,
.get_max_link_cap = dcn201_link_encoder_get_max_link_cap,
+ .get_hpd_state = dcn10_get_hpd_state,
+ .program_hpd_filter = dcn10_program_hpd_filter,
};
void dcn201_link_encoder_construct(
@@ -125,6 +127,7 @@ void dcn201_link_encoder_construct(
enc10->base.ctx = init_data->ctx;
enc10->base.id = init_data->encoder;
+ enc10->base.hpd_gpio = init_data->hpd_gpio;
enc10->base.hpd_source = init_data->hpd_source;
enc10->base.connector = init_data->connector;
diff --git a/drivers/gpu/drm/amd/display/dc/dcn21/dcn21_link_encoder.c b/drivers/gpu/drm/amd/display/dc/dcn21/dcn21_link_encoder.c
index eb9abb9f9698..36456c9971c8 100644
--- a/drivers/gpu/drm/amd/display/dc/dcn21/dcn21_link_encoder.c
+++ b/drivers/gpu/drm/amd/display/dc/dcn21/dcn21_link_encoder.c
@@ -325,6 +325,8 @@ static const struct link_encoder_funcs dcn21_link_enc_funcs = {
.get_dig_frontend = dcn10_get_dig_frontend,
.is_in_alt_mode = dcn20_link_encoder_is_in_alt_mode,
.get_max_link_cap = dcn20_link_encoder_get_max_link_cap,
+ .get_hpd_state = dcn10_get_hpd_state,
+ .program_hpd_filter = dcn10_program_hpd_filter,
};
void dcn21_link_encoder_construct(
@@ -346,6 +348,7 @@ void dcn21_link_encoder_construct(
enc10->base.ctx = init_data->ctx;
enc10->base.id = init_data->encoder;
+ enc10->base.hpd_gpio = init_data->hpd_gpio;
enc10->base.hpd_source = init_data->hpd_source;
enc10->base.connector = init_data->connector;
diff --git a/drivers/gpu/drm/amd/display/dc/dio/dcn10/dcn10_link_encoder.c b/drivers/gpu/drm/amd/display/dc/dio/dcn10/dcn10_link_encoder.c
index 1c1228116487..13e14aad3daa 100644
--- a/drivers/gpu/drm/amd/display/dc/dio/dcn10/dcn10_link_encoder.c
+++ b/drivers/gpu/drm/amd/display/dc/dio/dcn10/dcn10_link_encoder.c
@@ -88,8 +88,11 @@ static const struct link_encoder_funcs dcn10_lnk_enc_funcs = {
.get_dig_mode = dcn10_get_dig_mode,
.destroy = dcn10_link_encoder_destroy,
.get_max_link_cap = dcn10_link_encoder_get_max_link_cap,
+ .get_hpd_state = dcn10_get_hpd_state,
+ .program_hpd_filter = dcn10_program_hpd_filter,
};
+
static enum bp_result link_transmitter_control(
struct dcn10_link_encoder *enc10,
struct bp_transmitter_control *cntl)
@@ -682,6 +685,7 @@ void dcn10_link_encoder_construct(
enc10->base.ctx = init_data->ctx;
enc10->base.id = init_data->encoder;
+ enc10->base.hpd_gpio = init_data->hpd_gpio;
enc10->base.hpd_source = init_data->hpd_source;
enc10->base.connector = init_data->connector;
@@ -873,6 +877,11 @@ void dcn10_link_encoder_hw_init(
void dcn10_link_encoder_destroy(struct link_encoder **enc)
{
+ if ((*enc)->hpd_gpio) {
+ dal_gpio_destroy_irq(&(*enc)->hpd_gpio);
+ (*enc)->hpd_gpio = NULL;
+ }
+
kfree(TO_DCN10_LINK_ENC(*enc));
*enc = NULL;
}
@@ -1472,3 +1481,37 @@ void dcn10_link_encoder_get_max_link_cap(struct link_encoder *enc,
*link_settings = max_link_cap;
}
+
+bool dcn10_get_hpd_state(struct link_encoder *enc)
+{
+ uint32_t state = 0;
+
+ if (!enc->hpd_gpio)
+ return false;
+
+ dal_gpio_lock_pin(enc->hpd_gpio);
+ dal_gpio_get_value(enc->hpd_gpio, &state);
+ dal_gpio_unlock_pin(enc->hpd_gpio);
+
+ return state;
+}
+
+bool dcn10_program_hpd_filter(struct link_encoder *enc, int delay_on_connect_in_ms, int delay_on_disconnect_in_ms)
+{
+ /* Setup HPD filtering */
+ if (enc->hpd_gpio && dal_gpio_lock_pin(enc->hpd_gpio) == GPIO_RESULT_OK) {
+ struct gpio_hpd_config config;
+
+ config.delay_on_connect = delay_on_connect_in_ms;
+ config.delay_on_disconnect = delay_on_disconnect_in_ms;
+
+ dal_irq_setup_hpd_filter(enc->hpd_gpio, &config);
+
+ dal_gpio_unlock_pin(enc->hpd_gpio);
+
+ return true;
+ } else {
+ ASSERT(0);
+ return false;
+ }
+}
diff --git a/drivers/gpu/drm/amd/display/dc/dio/dcn10/dcn10_link_encoder.h b/drivers/gpu/drm/amd/display/dc/dio/dcn10/dcn10_link_encoder.h
index b7a89c39f445..eedbd5d2756e 100644
--- a/drivers/gpu/drm/amd/display/dc/dio/dcn10/dcn10_link_encoder.h
+++ b/drivers/gpu/drm/amd/display/dc/dio/dcn10/dcn10_link_encoder.h
@@ -79,6 +79,8 @@ struct dcn10_link_enc_aux_registers {
struct dcn10_link_enc_hpd_registers {
uint32_t DC_HPD_CONTROL;
+ uint32_t DC_HPD_INT_STATUS;
+ uint32_t DC_HPD_TOGGLE_FILT_CNTL;
};
struct dcn10_link_enc_registers {
@@ -274,7 +276,10 @@ struct dcn10_link_enc_registers {
type TMDS_CTL0;\
type AUX_HPD_SEL;\
type AUX_LS_READ_EN;\
- type AUX_RX_RECEIVE_WINDOW
+ type AUX_RX_RECEIVE_WINDOW;\
+ type DC_HPD_SENSE;\
+ type DC_HPD_CONNECT_INT_DELAY;\
+ type DC_HPD_DISCONNECT_INT_DELAY
#define DCN20_LINK_ENCODER_DPCS_REG_FIELD_LIST(type) \
@@ -656,4 +661,8 @@ enum signal_type dcn10_get_dig_mode(
void dcn10_link_encoder_get_max_link_cap(struct link_encoder *enc,
struct dc_link_settings *link_settings);
+
+bool dcn10_get_hpd_state(struct link_encoder *enc);
+bool dcn10_program_hpd_filter(struct link_encoder *enc, int delay_on_connect_in_ms, int delay_on_disconnect_in_ms);
+
#endif /* __DC_LINK_ENCODER__DCN10_H__ */
diff --git a/drivers/gpu/drm/amd/display/dc/dio/dcn20/dcn20_link_encoder.c b/drivers/gpu/drm/amd/display/dc/dio/dcn20/dcn20_link_encoder.c
index 51a57dae1811..3bd35f3392dc 100644
--- a/drivers/gpu/drm/amd/display/dc/dio/dcn20/dcn20_link_encoder.c
+++ b/drivers/gpu/drm/amd/display/dc/dio/dcn20/dcn20_link_encoder.c
@@ -384,6 +384,8 @@ static const struct link_encoder_funcs dcn20_link_enc_funcs = {
.get_dig_frontend = dcn10_get_dig_frontend,
.is_in_alt_mode = dcn20_link_encoder_is_in_alt_mode,
.get_max_link_cap = dcn20_link_encoder_get_max_link_cap,
+ .get_hpd_state = dcn10_get_hpd_state,
+ .program_hpd_filter = dcn10_program_hpd_filter,
};
void dcn20_link_encoder_construct(
@@ -405,6 +407,7 @@ void dcn20_link_encoder_construct(
enc10->base.ctx = init_data->ctx;
enc10->base.id = init_data->encoder;
+ enc10->base.hpd_gpio = init_data->hpd_gpio;
enc10->base.hpd_source = init_data->hpd_source;
enc10->base.connector = init_data->connector;
diff --git a/drivers/gpu/drm/amd/display/dc/dio/dcn30/dcn30_dio_link_encoder.c b/drivers/gpu/drm/amd/display/dc/dio/dcn30/dcn30_dio_link_encoder.c
index b8e31b5ea114..57b9ae5fca1d 100644
--- a/drivers/gpu/drm/amd/display/dc/dio/dcn30/dcn30_dio_link_encoder.c
+++ b/drivers/gpu/drm/amd/display/dc/dio/dcn30/dcn30_dio_link_encoder.c
@@ -84,6 +84,8 @@ static const struct link_encoder_funcs dcn30_link_enc_funcs = {
.get_dig_mode = dcn10_get_dig_mode,
.is_in_alt_mode = dcn20_link_encoder_is_in_alt_mode,
.get_max_link_cap = dcn20_link_encoder_get_max_link_cap,
+ .get_hpd_state = dcn10_get_hpd_state,
+ .program_hpd_filter = dcn10_program_hpd_filter,
};
void dcn30_link_encoder_construct(
@@ -105,6 +107,7 @@ void dcn30_link_encoder_construct(
enc10->base.ctx = init_data->ctx;
enc10->base.id = init_data->encoder;
+ enc10->base.hpd_gpio = init_data->hpd_gpio;
enc10->base.hpd_source = init_data->hpd_source;
enc10->base.connector = init_data->connector;
diff --git a/drivers/gpu/drm/amd/display/dc/dio/dcn301/dcn301_dio_link_encoder.c b/drivers/gpu/drm/amd/display/dc/dio/dcn301/dcn301_dio_link_encoder.c
index 1b39a6e8a1ac..47d84a2a48ce 100644
--- a/drivers/gpu/drm/amd/display/dc/dio/dcn301/dcn301_dio_link_encoder.c
+++ b/drivers/gpu/drm/amd/display/dc/dio/dcn301/dcn301_dio_link_encoder.c
@@ -73,6 +73,8 @@ static const struct link_encoder_funcs dcn301_link_enc_funcs = {
.get_dig_mode = dcn10_get_dig_mode,
.is_in_alt_mode = dcn20_link_encoder_is_in_alt_mode,
.get_max_link_cap = dcn20_link_encoder_get_max_link_cap,
+ .get_hpd_state = dcn10_get_hpd_state,
+ .program_hpd_filter = dcn10_program_hpd_filter,
};
void dcn301_link_encoder_construct(
@@ -94,6 +96,7 @@ void dcn301_link_encoder_construct(
enc10->base.ctx = init_data->ctx;
enc10->base.id = init_data->encoder;
+ enc10->base.hpd_gpio = init_data->hpd_gpio;
enc10->base.hpd_source = init_data->hpd_source;
enc10->base.connector = init_data->connector;
diff --git a/drivers/gpu/drm/amd/display/dc/dio/dcn31/dcn31_dio_link_encoder.c b/drivers/gpu/drm/amd/display/dc/dio/dcn31/dcn31_dio_link_encoder.c
index 84cc2ddc52fe..07d362ef0daf 100644
--- a/drivers/gpu/drm/amd/display/dc/dio/dcn31/dcn31_dio_link_encoder.c
+++ b/drivers/gpu/drm/amd/display/dc/dio/dcn31/dcn31_dio_link_encoder.c
@@ -276,6 +276,8 @@ static const struct link_encoder_funcs dcn31_link_enc_funcs = {
.is_in_alt_mode = dcn31_link_encoder_is_in_alt_mode,
.get_max_link_cap = dcn31_link_encoder_get_max_link_cap,
.set_dio_phy_mux = dcn31_link_encoder_set_dio_phy_mux,
+ .get_hpd_state = dcn10_get_hpd_state,
+ .program_hpd_filter = dcn10_program_hpd_filter,
};
void dcn31_link_encoder_construct(
@@ -297,6 +299,7 @@ void dcn31_link_encoder_construct(
enc10->base.ctx = init_data->ctx;
enc10->base.id = init_data->encoder;
+ enc10->base.hpd_gpio = init_data->hpd_gpio;
enc10->base.hpd_source = init_data->hpd_source;
enc10->base.connector = init_data->connector;
diff --git a/drivers/gpu/drm/amd/display/dc/dio/dcn32/dcn32_dio_link_encoder.c b/drivers/gpu/drm/amd/display/dc/dio/dcn32/dcn32_dio_link_encoder.c
index 06907e8a4eda..65d28cb07b04 100644
--- a/drivers/gpu/drm/amd/display/dc/dio/dcn32/dcn32_dio_link_encoder.c
+++ b/drivers/gpu/drm/amd/display/dc/dio/dcn32/dcn32_dio_link_encoder.c
@@ -188,9 +188,18 @@ void dcn32_link_encoder_get_max_link_cap(struct link_encoder *enc,
if (!query_dp_alt_from_dmub(enc, &cmd))
return;
- if (cmd.query_dp_alt.data.is_usb &&
- cmd.query_dp_alt.data.is_dp4 == 0)
- link_settings->lane_count = MIN(LANE_COUNT_TWO, link_settings->lane_count);
+ /*
+ * USB-C DisplayPort Alt Mode lane count limitation logic:
+ * When USB and DP share the same USB-C connector, hardware must allocate
+ * some lanes for USB data, limiting DP to maximum 2 lanes instead of 4.
+ * This ensures USB functionality remains available while DP is active.
+ */
+ if (cmd.query_dp_alt.data.is_dp_alt_disable == 0 &&
+ cmd.query_dp_alt.data.is_usb &&
+ cmd.query_dp_alt.data.is_dp4 == 0) {
+ link_settings->lane_count =
+ MIN(LANE_COUNT_TWO, link_settings->lane_count);
+ }
}
@@ -224,6 +233,8 @@ static const struct link_encoder_funcs dcn32_link_enc_funcs = {
.is_in_alt_mode = dcn32_link_encoder_is_in_alt_mode,
.get_max_link_cap = dcn32_link_encoder_get_max_link_cap,
.set_dio_phy_mux = dcn31_link_encoder_set_dio_phy_mux,
+ .get_hpd_state = dcn10_get_hpd_state,
+ .program_hpd_filter = dcn10_program_hpd_filter,
};
void dcn32_link_encoder_construct(
@@ -245,6 +256,7 @@ void dcn32_link_encoder_construct(
enc10->base.ctx = init_data->ctx;
enc10->base.id = init_data->encoder;
+ enc10->base.hpd_gpio = init_data->hpd_gpio;
enc10->base.hpd_source = init_data->hpd_source;
enc10->base.connector = init_data->connector;
diff --git a/drivers/gpu/drm/amd/display/dc/dio/dcn321/dcn321_dio_link_encoder.c b/drivers/gpu/drm/amd/display/dc/dio/dcn321/dcn321_dio_link_encoder.c
index 2ed382a8e79c..968f89295b64 100644
--- a/drivers/gpu/drm/amd/display/dc/dio/dcn321/dcn321_dio_link_encoder.c
+++ b/drivers/gpu/drm/amd/display/dc/dio/dcn321/dcn321_dio_link_encoder.c
@@ -89,6 +89,8 @@ static const struct link_encoder_funcs dcn321_link_enc_funcs = {
.is_in_alt_mode = dcn20_link_encoder_is_in_alt_mode,
.get_max_link_cap = dcn20_link_encoder_get_max_link_cap,
.set_dio_phy_mux = dcn31_link_encoder_set_dio_phy_mux,
+ .get_hpd_state = dcn10_get_hpd_state,
+ .program_hpd_filter = dcn10_program_hpd_filter,
};
void dcn321_link_encoder_construct(
@@ -110,6 +112,7 @@ void dcn321_link_encoder_construct(
enc10->base.ctx = init_data->ctx;
enc10->base.id = init_data->encoder;
+ enc10->base.hpd_gpio = init_data->hpd_gpio;
enc10->base.hpd_source = init_data->hpd_source;
enc10->base.connector = init_data->connector;
diff --git a/drivers/gpu/drm/amd/display/dc/dio/dcn35/dcn35_dio_link_encoder.c b/drivers/gpu/drm/amd/display/dc/dio/dcn35/dcn35_dio_link_encoder.c
index 9972911330b6..20bf04dac609 100644
--- a/drivers/gpu/drm/amd/display/dc/dio/dcn35/dcn35_dio_link_encoder.c
+++ b/drivers/gpu/drm/amd/display/dc/dio/dcn35/dcn35_dio_link_encoder.c
@@ -120,7 +120,6 @@ void dcn35_link_encoder_setup(
void dcn35_link_encoder_init(struct link_encoder *enc)
{
enc31_hw_init(enc);
- dcn35_link_encoder_set_fgcg(enc, enc->ctx->dc->debug.enable_fine_grain_clock_gating.bits.dio);
}
void dcn35_link_encoder_set_fgcg(struct link_encoder *enc, bool enable)
@@ -162,6 +161,8 @@ static const struct link_encoder_funcs dcn35_link_enc_funcs = {
.set_dio_phy_mux = dcn31_link_encoder_set_dio_phy_mux,
.enable_dpia_output = dcn35_link_encoder_enable_dpia_output,
.disable_dpia_output = dcn35_link_encoder_disable_dpia_output,
+ .get_hpd_state = dcn10_get_hpd_state,
+ .program_hpd_filter = dcn10_program_hpd_filter,
};
void dcn35_link_encoder_construct(
@@ -183,6 +184,7 @@ void dcn35_link_encoder_construct(
enc10->base.ctx = init_data->ctx;
enc10->base.id = init_data->encoder;
+ enc10->base.hpd_gpio = init_data->hpd_gpio;
enc10->base.hpd_source = init_data->hpd_source;
enc10->base.connector = init_data->connector;
diff --git a/drivers/gpu/drm/amd/display/dc/dio/dcn401/dcn401_dio_link_encoder.c b/drivers/gpu/drm/amd/display/dc/dio/dcn401/dcn401_dio_link_encoder.c
index 7e558ca195ef..e1f0a1bf1075 100644
--- a/drivers/gpu/drm/amd/display/dc/dio/dcn401/dcn401_dio_link_encoder.c
+++ b/drivers/gpu/drm/amd/display/dc/dio/dcn401/dcn401_dio_link_encoder.c
@@ -215,6 +215,8 @@ static const struct link_encoder_funcs dcn401_link_enc_funcs = {
.is_in_alt_mode = dcn32_link_encoder_is_in_alt_mode,
.get_max_link_cap = dcn32_link_encoder_get_max_link_cap,
.set_dio_phy_mux = dcn31_link_encoder_set_dio_phy_mux,
+ .get_hpd_state = dcn10_get_hpd_state,
+ .program_hpd_filter = dcn10_program_hpd_filter,
};
void dcn401_link_encoder_construct(
@@ -236,6 +238,7 @@ void dcn401_link_encoder_construct(
enc10->base.ctx = init_data->ctx;
enc10->base.id = init_data->encoder;
+ enc10->base.hpd_gpio = init_data->hpd_gpio;
enc10->base.hpd_source = init_data->hpd_source;
enc10->base.connector = init_data->connector;
diff --git a/drivers/gpu/drm/amd/display/dc/dm_helpers.h b/drivers/gpu/drm/amd/display/dc/dm_helpers.h
index 9d160b39e8c5..7014b8c2c956 100644
--- a/drivers/gpu/drm/amd/display/dc/dm_helpers.h
+++ b/drivers/gpu/drm/amd/display/dc/dm_helpers.h
@@ -197,6 +197,7 @@ void dm_set_phyd32clk(struct dc_context *ctx, int freq_khz);
bool dm_helpers_dmub_outbox_interrupt_control(struct dc_context *ctx, bool enable);
+void dm_helpers_dmu_timeout(struct dc_context *ctx);
void dm_helpers_smu_timeout(struct dc_context *ctx, unsigned int msg_id, unsigned int param, unsigned int timeout_us);
// 0x1 = Result_OK, 0xFE = Result_UnkmownCmd, 0x0 = Status_Busy
diff --git a/drivers/gpu/drm/amd/display/dc/dml2_0/Makefile b/drivers/gpu/drm/amd/display/dc/dml2_0/Makefile
index 97e068b6bf6b..30cfc0848792 100644
--- a/drivers/gpu/drm/amd/display/dc/dml2_0/Makefile
+++ b/drivers/gpu/drm/amd/display/dc/dml2_0/Makefile
@@ -55,7 +55,7 @@ subdir-ccflags-y += -I$(FULL_AMD_DISPLAY_PATH)/dc/dml2_0/dml21/
CFLAGS_$(AMDDALPATH)/dc/dml2_0/display_mode_core.o := $(dml2_ccflags) $(frame_warn_flag)
CFLAGS_$(AMDDALPATH)/dc/dml2_0/display_mode_util.o := $(dml2_ccflags)
-CFLAGS_$(AMDDALPATH)/dc/dml2_0/dml2_wrapper.o := $(dml2_ccflags)
+CFLAGS_$(AMDDALPATH)/dc/dml2_0/dml2_wrapper_fpu.o := $(dml2_ccflags)
CFLAGS_$(AMDDALPATH)/dc/dml2_0/dml2_utils.o := $(dml2_ccflags)
CFLAGS_$(AMDDALPATH)/dc/dml2_0/dml2_policy.o := $(dml2_ccflags)
CFLAGS_$(AMDDALPATH)/dc/dml2_0/dml2_translation_helper.o := $(dml2_ccflags)
@@ -65,7 +65,7 @@ CFLAGS_$(AMDDALPATH)/dc/dml2_0/dml2_dc_resource_mgmt.o := $(dml2_ccflags)
CFLAGS_REMOVE_$(AMDDALPATH)/dc/dml2_0/display_mode_core.o := $(dml2_rcflags)
CFLAGS_REMOVE_$(AMDDALPATH)/dc/dml2_0/display_mode_util.o := $(dml2_rcflags)
-CFLAGS_REMOVE_$(AMDDALPATH)/dc/dml2_0/dml2_wrapper.o := $(dml2_rcflags)
+CFLAGS_REMOVE_$(AMDDALPATH)/dc/dml2_0/dml2_wrapper_fpu.o := $(dml2_rcflags)
CFLAGS_REMOVE_$(AMDDALPATH)/dc/dml2_0/dml2_utils.o := $(dml2_rcflags)
CFLAGS_REMOVE_$(AMDDALPATH)/dc/dml2_0/dml2_policy.o := $(dml2_rcflags)
CFLAGS_REMOVE_$(AMDDALPATH)/dc/dml2_0/dml2_translation_helper.o := $(dml2_rcflags)
@@ -73,7 +73,7 @@ CFLAGS_REMOVE_$(AMDDALPATH)/dc/dml2_0/dml2_mall_phantom.o := $(dml2_rcflags)
CFLAGS_REMOVE_$(AMDDALPATH)/dc/dml2_0/dml_display_rq_dlg_calc.o := $(dml2_rcflags)
CFLAGS_REMOVE_$(AMDDALPATH)/dc/dml2_0/dml2_dc_resource_mgmt.o := $(dml2_rcflags)
-DML2 = display_mode_core.o display_mode_util.o dml2_wrapper.o \
+DML2 = display_mode_core.o display_mode_util.o dml2_wrapper_fpu.o dml2_wrapper.o \
dml2_utils.o dml2_policy.o dml2_translation_helper.o dml2_dc_resource_mgmt.o dml2_mall_phantom.o \
dml_display_rq_dlg_calc.o
@@ -95,7 +95,6 @@ CFLAGS_$(AMDDALPATH)/dc/dml2_0/dml21/src/dml2_pmo/dml2_pmo_dcn3.o := $(dml2_ccfl
CFLAGS_$(AMDDALPATH)/dc/dml2_0/dml21/src/dml2_pmo/dml2_pmo_dcn4_fams2.o := $(dml2_ccflags)
CFLAGS_$(AMDDALPATH)/dc/dml2_0/dml21/src/dml2_pmo/dml2_pmo_factory.o := $(dml2_ccflags)
CFLAGS_$(AMDDALPATH)/dc/dml2_0/dml21/src/dml2_standalone_libraries/lib_float_math.o := $(dml2_ccflags)
-CFLAGS_$(AMDDALPATH)/dc/dml2_0/dml21/src/dml21_wrapper.o := $(dml2_ccflags)
CFLAGS_$(AMDDALPATH)/dc/dml2_0/dml21/dml21_translation_helper.o := $(dml2_ccflags)
CFLAGS_$(AMDDALPATH)/dc/dml2_0/dml21/dml21_utils.o := $(dml2_ccflags)
@@ -113,7 +112,6 @@ CFLAGS_REMOVE_$(AMDDALPATH)/dc/dml2_0/dml21/src/dml2_pmo/dml2_pmo_dcn3.o := $(dm
CFLAGS_REMOVE_$(AMDDALPATH)/dc/dml2_0/dml21/src/dml2_pmo/dml2_pmo_dcn4_fams2.o := $(dml2_rcflags)
CFLAGS_REMOVE_$(AMDDALPATH)/dc/dml2_0/dml21/src/dml2_pmo/dml2_pmo_factory.o := $(dml2_rcflags)
CFLAGS_REMOVE_$(AMDDALPATH)/dc/dml2_0/dml21/src/dml2_standalone_libraries/lib_float_math.o := $(dml2_rcflags)
-CFLAGS_REMOVE_$(AMDDALPATH)/dc/dml2_0/dml21/src/dml21_wrapper.o := $(dml2_rcflags)
CFLAGS_REMOVE_$(AMDDALPATH)/dc/dml2_0/dml21/dml21_translation_helper.o := $(dml2_rcflags)
CFLAGS_REMOVE_$(AMDDALPATH)/dc/dml2_0/dml21/dml21_utils.o := $(dml2_rcflags)
diff --git a/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/dml21_utils.c b/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/dml21_utils.c
index ee721606b883..f667026cb43e 100644
--- a/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/dml21_utils.c
+++ b/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/dml21_utils.c
@@ -387,7 +387,8 @@ void dml21_build_fams2_programming(const struct dc *dc,
memset(&context->bw_ctx.bw.dcn.fams2_stream_sub_params_v2, 0, sizeof(union dmub_fams2_stream_static_sub_state_v2) * DML2_MAX_PLANES);
memset(&context->bw_ctx.bw.dcn.fams2_global_config, 0, sizeof(struct dmub_cmd_fams2_global_config));
- if (dml_ctx->v21.mode_programming.programming->fams2_required) {
+ if ((dml_ctx->v21.mode_programming.programming->fams2_required) ||
+ (dml_ctx->v21.mode_programming.programming->legacy_pstate_info_for_dmu)) {
for (i = 0; i < context->stream_count; i++) {
int dml_stream_idx;
struct dc_stream_state *phantom_stream;
diff --git a/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/dml21_wrapper.h b/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/dml21_wrapper.h
index 15f92029d2e5..b508bbcc0e16 100644
--- a/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/dml21_wrapper.h
+++ b/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/dml21_wrapper.h
@@ -17,9 +17,9 @@ struct dml2_context;
enum dc_validate_mode;
/**
- * dml2_create - Creates dml21_context.
+ * dml21_create - Creates dml21_context.
* @in_dc: dc.
- * @dml2: Created dml21 context.
+ * @dml_ctx: Created dml21 context.
* @config: dml21 configuration options.
*
* Create of DML21 is done as part of dc_state creation.
@@ -40,6 +40,7 @@ void dml21_reinit(const struct dc *in_dc, struct dml2_context *dml_ctx, const st
* dml21_validate - Determines if a display configuration is supported or not.
* @in_dc: dc.
* @context: dc_state to be validated.
+ * @dml_ctx: dml21 context.
* @validate_mode: DC_VALIDATE_MODE_ONLY and DC_VALIDATE_MODE_AND_STATE_INDEX
* will not populate context.res_ctx.
*
@@ -53,7 +54,7 @@ void dml21_reinit(const struct dc *in_dc, struct dml2_context *dml_ctx, const st
* -dml21_check_mode_support - for DC_VALIDATE_MODE_ONLY and DC_VALIDATE_MODE_AND_STATE_INDEX option
* Calculates if dc_state can be supported for the input display
* config.
-
+ *
* Context: Two threads may not invoke this function concurrently unless they reference
* separate dc_states for validation.
* Return: True if mode is supported, false otherwise.
diff --git a/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/inc/dml_top_display_cfg_types.h b/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/inc/dml_top_display_cfg_types.h
index 35aa954248cd..b44762e21550 100644
--- a/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/inc/dml_top_display_cfg_types.h
+++ b/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/inc/dml_top_display_cfg_types.h
@@ -407,6 +407,7 @@ struct dml2_plane_parameters {
unsigned int hostvm_min_page_size_kbytes;
enum dml2_svp_mode_override legacy_svp_config; //TODO remove in favor of svp_config
+ bool use_max_lsw;
struct {
// HW specific overrides, there's almost no reason to mess with these
diff --git a/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/inc/dml_top_types.h b/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/inc/dml_top_types.h
index 452e4a2e72c0..943fd3f040c3 100644
--- a/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/inc/dml_top_types.h
+++ b/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/inc/dml_top_types.h
@@ -418,6 +418,7 @@ struct dml2_display_cfg_programming {
/* indicates this configuration requires FW to support */
bool fams2_required;
+ bool legacy_pstate_info_for_dmu;
struct dmub_cmd_fams2_global_config fams2_global_config;
struct {
diff --git a/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_core/dml2_core_dcn4_calcs.c b/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_core/dml2_core_dcn4_calcs.c
index a02e9fd6b5ca..01b87be24ce3 100644
--- a/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_core/dml2_core_dcn4_calcs.c
+++ b/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_core/dml2_core_dcn4_calcs.c
@@ -326,6 +326,7 @@ dml_get_var_func(stutter_efficiency, double, mode_lib->mp.StutterEfficiency);
dml_get_var_func(stutter_efficiency_no_vblank, double, mode_lib->mp.StutterEfficiencyNotIncludingVBlank);
dml_get_var_func(stutter_num_bursts, double, mode_lib->mp.NumberOfStutterBurstsPerFrame);
dml_get_var_func(stutter_efficiency_z8, double, mode_lib->mp.Z8StutterEfficiency);
+dml_get_var_func(stutter_efficiency_no_vblank_z8, double, mode_lib->mp.Z8StutterEfficiencyNotIncludingVBlank);
dml_get_var_func(stutter_num_bursts_z8, double, mode_lib->mp.Z8NumberOfStutterBurstsPerFrame);
dml_get_var_func(stutter_period, double, mode_lib->mp.StutterPeriod);
dml_get_var_func(stutter_efficiency_z8_bestcase, double, mode_lib->mp.Z8StutterEfficiencyBestCase);
@@ -13198,8 +13199,8 @@ void dml2_core_calcs_get_informative(const struct dml2_core_internal_display_mod
out->informative.power_management.stutter_efficiency_with_vblank = dml_get_stutter_efficiency(mode_lib);
out->informative.power_management.stutter_num_bursts = dml_get_stutter_num_bursts(mode_lib);
- out->informative.power_management.z8.stutter_efficiency = dml_get_stutter_efficiency_z8(mode_lib);
- out->informative.power_management.z8.stutter_efficiency_with_vblank = dml_get_stutter_efficiency(mode_lib);
+ out->informative.power_management.z8.stutter_efficiency = dml_get_stutter_efficiency_no_vblank_z8(mode_lib);
+ out->informative.power_management.z8.stutter_efficiency_with_vblank = dml_get_stutter_efficiency_z8(mode_lib);
out->informative.power_management.z8.stutter_num_bursts = dml_get_stutter_num_bursts_z8(mode_lib);
out->informative.power_management.z8.stutter_period = dml_get_stutter_period(mode_lib);
diff --git a/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_core/dml2_core_shared_types.h b/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_core/dml2_core_shared_types.h
index 1087a8c926ff..953f40fde1e1 100644
--- a/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_core/dml2_core_shared_types.h
+++ b/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_core/dml2_core_shared_types.h
@@ -1950,6 +1950,7 @@ struct dml2_core_calcs_CalculatePrefetchSchedule_params {
double Ttrip;
double Turg;
bool setup_for_tdlut;
+ bool use_max_lsw;
unsigned int tdlut_pte_bytes_per_frame;
unsigned int tdlut_bytes_per_frame;
double tdlut_opt_time;
diff --git a/drivers/gpu/drm/amd/display/dc/dml2_0/dml2_wrapper.c b/drivers/gpu/drm/amd/display/dc/dml2_0/dml2_wrapper.c
index 9deb03a18ccc..307186eb6af0 100644
--- a/drivers/gpu/drm/amd/display/dc/dml2_0/dml2_wrapper.c
+++ b/drivers/gpu/drm/amd/display/dc/dml2_0/dml2_wrapper.c
@@ -1,549 +1,12 @@
-/* SPDX-License-Identifier: MIT */
+// SPDX-License-Identifier: MIT
/*
- * Copyright 2023 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.
+ * Copyright 2025 Advanced Micro Devices, Inc.
*
* Authors: AMD
- *
*/
-#include "display_mode_core.h"
#include "dml2_internal_types.h"
-#include "dml2_utils.h"
-#include "dml2_policy.h"
-#include "dml2_translation_helper.h"
-#include "dml2_mall_phantom.h"
-#include "dml2_dc_resource_mgmt.h"
-#include "dml21_wrapper.h"
-
-static void initialize_dml2_ip_params(struct dml2_context *dml2, const struct dc *in_dc, struct ip_params_st *out)
-{
- if (dml2->config.use_native_soc_bb_construction)
- dml2_init_ip_params(dml2, in_dc, out);
- else
- dml2_translate_ip_params(in_dc, out);
-}
-
-static void initialize_dml2_soc_bbox(struct dml2_context *dml2, const struct dc *in_dc, struct soc_bounding_box_st *out)
-{
- if (dml2->config.use_native_soc_bb_construction)
- dml2_init_socbb_params(dml2, in_dc, out);
- else
- dml2_translate_socbb_params(in_dc, out);
-}
-
-static void initialize_dml2_soc_states(struct dml2_context *dml2,
- const struct dc *in_dc, const struct soc_bounding_box_st *in_bbox, struct soc_states_st *out)
-{
- if (dml2->config.use_native_soc_bb_construction)
- dml2_init_soc_states(dml2, in_dc, in_bbox, out);
- else
- dml2_translate_soc_states(in_dc, out, in_dc->dml.soc.num_states);
-}
-
-static void map_hw_resources(struct dml2_context *dml2,
- struct dml_display_cfg_st *in_out_display_cfg, struct dml_mode_support_info_st *mode_support_info)
-{
- unsigned int num_pipes = 0;
- int i, j;
-
- for (i = 0; i < __DML_NUM_PLANES__; i++) {
- in_out_display_cfg->hw.ODMMode[i] = mode_support_info->ODMMode[i];
- in_out_display_cfg->hw.DPPPerSurface[i] = mode_support_info->DPPPerSurface[i];
- in_out_display_cfg->hw.DSCEnabled[i] = mode_support_info->DSCEnabled[i];
- in_out_display_cfg->hw.NumberOfDSCSlices[i] = mode_support_info->NumberOfDSCSlices[i];
- in_out_display_cfg->hw.DLGRefClkFreqMHz = 24;
- if (dml2->v20.dml_core_ctx.project != dml_project_dcn35 &&
- dml2->v20.dml_core_ctx.project != dml_project_dcn36 &&
- dml2->v20.dml_core_ctx.project != dml_project_dcn351) {
- /*dGPU default as 50Mhz*/
- in_out_display_cfg->hw.DLGRefClkFreqMHz = 50;
- }
- for (j = 0; j < mode_support_info->DPPPerSurface[i]; j++) {
- if (i >= __DML2_WRAPPER_MAX_STREAMS_PLANES__) {
- dml_print("DML::%s: Index out of bounds: i=%d, __DML2_WRAPPER_MAX_STREAMS_PLANES__=%d\n",
- __func__, i, __DML2_WRAPPER_MAX_STREAMS_PLANES__);
- break;
- }
- dml2->v20.scratch.dml_to_dc_pipe_mapping.dml_pipe_idx_to_stream_id[num_pipes] = dml2->v20.scratch.dml_to_dc_pipe_mapping.disp_cfg_to_stream_id[i];
- dml2->v20.scratch.dml_to_dc_pipe_mapping.dml_pipe_idx_to_stream_id_valid[num_pipes] = true;
- dml2->v20.scratch.dml_to_dc_pipe_mapping.dml_pipe_idx_to_plane_id[num_pipes] = dml2->v20.scratch.dml_to_dc_pipe_mapping.disp_cfg_to_plane_id[i];
- dml2->v20.scratch.dml_to_dc_pipe_mapping.dml_pipe_idx_to_plane_id_valid[num_pipes] = true;
- num_pipes++;
- }
- }
-}
-
-static unsigned int pack_and_call_dml_mode_support_ex(struct dml2_context *dml2,
- const struct dml_display_cfg_st *display_cfg,
- struct dml_mode_support_info_st *evaluation_info,
- enum dc_validate_mode validate_mode)
-{
- struct dml2_wrapper_scratch *s = &dml2->v20.scratch;
-
- s->mode_support_params.mode_lib = &dml2->v20.dml_core_ctx;
- s->mode_support_params.in_display_cfg = display_cfg;
- if (validate_mode == DC_VALIDATE_MODE_ONLY)
- s->mode_support_params.in_start_state_idx = dml2->v20.dml_core_ctx.states.num_states - 1;
- else
- s->mode_support_params.in_start_state_idx = 0;
- s->mode_support_params.out_evaluation_info = evaluation_info;
-
- memset(evaluation_info, 0, sizeof(struct dml_mode_support_info_st));
- s->mode_support_params.out_lowest_state_idx = 0;
-
- return dml_mode_support_ex(&s->mode_support_params);
-}
-
-static bool optimize_configuration(struct dml2_context *dml2, struct dml2_wrapper_optimize_configuration_params *p)
-{
- int unused_dpps = p->ip_params->max_num_dpp;
- int i;
- int odms_needed;
- int largest_blend_and_timing = 0;
- bool optimization_done = false;
-
- for (i = 0; i < (int) p->cur_display_config->num_timings; i++) {
- if (p->cur_display_config->plane.BlendingAndTiming[i] > largest_blend_and_timing)
- largest_blend_and_timing = p->cur_display_config->plane.BlendingAndTiming[i];
- }
-
- if (p->new_policy != p->cur_policy)
- *p->new_policy = *p->cur_policy;
-
- if (p->new_display_config != p->cur_display_config)
- *p->new_display_config = *p->cur_display_config;
-
-
- // Optimize Clocks
- if (!optimization_done) {
- if (largest_blend_and_timing == 0 && p->cur_policy->ODMUse[0] == dml_odm_use_policy_combine_as_needed && dml2->config.minimize_dispclk_using_odm) {
- odms_needed = dml2_util_get_maximum_odm_combine_for_output(dml2->config.optimize_odm_4to1,
- p->cur_display_config->output.OutputEncoder[0], p->cur_mode_support_info->DSCEnabled[0]) - 1;
-
- if (odms_needed <= unused_dpps) {
- if (odms_needed == 1) {
- p->new_policy->ODMUse[0] = dml_odm_use_policy_combine_2to1;
- optimization_done = true;
- } else if (odms_needed == 3) {
- p->new_policy->ODMUse[0] = dml_odm_use_policy_combine_4to1;
- optimization_done = true;
- } else
- optimization_done = false;
- }
- }
- }
-
- return optimization_done;
-}
-
-static int calculate_lowest_supported_state_for_temp_read(struct dml2_context *dml2, struct dc_state *display_state,
- enum dc_validate_mode validate_mode)
-{
- struct dml2_calculate_lowest_supported_state_for_temp_read_scratch *s = &dml2->v20.scratch.dml2_calculate_lowest_supported_state_for_temp_read_scratch;
- struct dml2_wrapper_scratch *s_global = &dml2->v20.scratch;
-
- unsigned int dml_result = 0;
- int result = -1, i, j;
-
- build_unoptimized_policy_settings(dml2->v20.dml_core_ctx.project, &dml2->v20.dml_core_ctx.policy);
-
- /* Zero out before each call before proceeding */
- memset(s, 0, sizeof(struct dml2_calculate_lowest_supported_state_for_temp_read_scratch));
- memset(&s_global->mode_support_params, 0, sizeof(struct dml_mode_support_ex_params_st));
- memset(&s_global->dml_to_dc_pipe_mapping, 0, sizeof(struct dml2_dml_to_dc_pipe_mapping));
-
- for (i = 0; i < dml2->config.dcn_pipe_count; i++) {
- /* Calling resource_build_scaling_params will populate the pipe params
- * with the necessary information needed for correct DML calculations
- * This is also done in DML1 driver code path and hence display_state
- * cannot be const.
- */
- struct pipe_ctx *pipe = &display_state->res_ctx.pipe_ctx[i];
-
- if (pipe->plane_state) {
- if (!dml2->config.callbacks.build_scaling_params(pipe)) {
- ASSERT(false);
- return false;
- }
- }
- }
-
- map_dc_state_into_dml_display_cfg(dml2, display_state, &s->cur_display_config);
-
- for (i = 0; i < dml2->v20.dml_core_ctx.states.num_states; i++) {
- s->uclk_change_latencies[i] = dml2->v20.dml_core_ctx.states.state_array[i].dram_clock_change_latency_us;
- }
-
- for (i = 0; i < 4; i++) {
- for (j = 0; j < dml2->v20.dml_core_ctx.states.num_states; j++) {
- dml2->v20.dml_core_ctx.states.state_array[j].dram_clock_change_latency_us = s_global->dummy_pstate_table[i].dummy_pstate_latency_us;
- }
-
- dml_result = pack_and_call_dml_mode_support_ex(dml2, &s->cur_display_config, &s->evaluation_info,
- validate_mode);
-
- if (dml_result && s->evaluation_info.DRAMClockChangeSupport[0] == dml_dram_clock_change_vactive) {
- map_hw_resources(dml2, &s->cur_display_config, &s->evaluation_info);
- dml_result = dml_mode_programming(&dml2->v20.dml_core_ctx, s_global->mode_support_params.out_lowest_state_idx, &s->cur_display_config, true);
-
- ASSERT(dml_result);
-
- dml2_extract_watermark_set(&dml2->v20.g6_temp_read_watermark_set, &dml2->v20.dml_core_ctx);
- dml2->v20.g6_temp_read_watermark_set.cstate_pstate.fclk_pstate_change_ns = dml2->v20.g6_temp_read_watermark_set.cstate_pstate.pstate_change_ns;
-
- result = s_global->mode_support_params.out_lowest_state_idx;
-
- while (dml2->v20.dml_core_ctx.states.state_array[result].dram_speed_mts < s_global->dummy_pstate_table[i].dram_speed_mts)
- result++;
-
- break;
- }
- }
-
- for (i = 0; i < dml2->v20.dml_core_ctx.states.num_states; i++) {
- dml2->v20.dml_core_ctx.states.state_array[i].dram_clock_change_latency_us = s->uclk_change_latencies[i];
- }
-
- return result;
-}
-
-static void copy_dummy_pstate_table(struct dummy_pstate_entry *dest, struct dummy_pstate_entry *src, unsigned int num_entries)
-{
- for (int i = 0; i < num_entries; i++) {
- dest[i] = src[i];
- }
-}
-
-static bool are_timings_requiring_odm_doing_blending(const struct dml_display_cfg_st *display_cfg,
- const struct dml_mode_support_info_st *evaluation_info)
-{
- unsigned int planes_per_timing[__DML_NUM_PLANES__] = {0};
- int i;
-
- for (i = 0; i < display_cfg->num_surfaces; i++)
- planes_per_timing[display_cfg->plane.BlendingAndTiming[i]]++;
-
- for (i = 0; i < __DML_NUM_PLANES__; i++) {
- if (planes_per_timing[i] > 1 && evaluation_info->ODMMode[i] != dml_odm_mode_bypass)
- return true;
- }
-
- return false;
-}
-
-static bool does_configuration_meet_sw_policies(struct dml2_context *ctx, const struct dml_display_cfg_st *display_cfg,
- const struct dml_mode_support_info_st *evaluation_info)
-{
- bool pass = true;
-
- if (!ctx->config.enable_windowed_mpo_odm) {
- if (are_timings_requiring_odm_doing_blending(display_cfg, evaluation_info))
- pass = false;
- }
-
- return pass;
-}
-
-static bool dml_mode_support_wrapper(struct dml2_context *dml2,
- struct dc_state *display_state,
- enum dc_validate_mode validate_mode)
-{
- struct dml2_wrapper_scratch *s = &dml2->v20.scratch;
- unsigned int result = 0, i;
- unsigned int optimized_result = true;
-
- build_unoptimized_policy_settings(dml2->v20.dml_core_ctx.project, &dml2->v20.dml_core_ctx.policy);
-
- /* Zero out before each call before proceeding */
- memset(&s->cur_display_config, 0, sizeof(struct dml_display_cfg_st));
- memset(&s->mode_support_params, 0, sizeof(struct dml_mode_support_ex_params_st));
- memset(&s->dml_to_dc_pipe_mapping, 0, sizeof(struct dml2_dml_to_dc_pipe_mapping));
- memset(&s->optimize_configuration_params, 0, sizeof(struct dml2_wrapper_optimize_configuration_params));
-
- for (i = 0; i < dml2->config.dcn_pipe_count; i++) {
- /* Calling resource_build_scaling_params will populate the pipe params
- * with the necessary information needed for correct DML calculations
- * This is also done in DML1 driver code path and hence display_state
- * cannot be const.
- */
- struct pipe_ctx *pipe = &display_state->res_ctx.pipe_ctx[i];
-
- if (pipe->plane_state) {
- if (!dml2->config.callbacks.build_scaling_params(pipe)) {
- ASSERT(false);
- return false;
- }
- }
- }
-
- map_dc_state_into_dml_display_cfg(dml2, display_state, &s->cur_display_config);
- if (!dml2->config.skip_hw_state_mapping)
- dml2_apply_det_buffer_allocation_policy(dml2, &s->cur_display_config);
-
- result = pack_and_call_dml_mode_support_ex(dml2,
- &s->cur_display_config,
- &s->mode_support_info,
- validate_mode);
-
- if (result)
- result = does_configuration_meet_sw_policies(dml2, &s->cur_display_config, &s->mode_support_info);
-
- // Try to optimize
- if (result) {
- s->cur_policy = dml2->v20.dml_core_ctx.policy;
- s->optimize_configuration_params.dml_core_ctx = &dml2->v20.dml_core_ctx;
- s->optimize_configuration_params.config = &dml2->config;
- s->optimize_configuration_params.ip_params = &dml2->v20.dml_core_ctx.ip;
- s->optimize_configuration_params.cur_display_config = &s->cur_display_config;
- s->optimize_configuration_params.cur_mode_support_info = &s->mode_support_info;
- s->optimize_configuration_params.cur_policy = &s->cur_policy;
- s->optimize_configuration_params.new_display_config = &s->new_display_config;
- s->optimize_configuration_params.new_policy = &s->new_policy;
-
- while (optimized_result && optimize_configuration(dml2, &s->optimize_configuration_params)) {
- dml2->v20.dml_core_ctx.policy = s->new_policy;
- optimized_result = pack_and_call_dml_mode_support_ex(dml2,
- &s->new_display_config,
- &s->mode_support_info,
- validate_mode);
-
- if (optimized_result)
- optimized_result = does_configuration_meet_sw_policies(dml2, &s->new_display_config, &s->mode_support_info);
-
- // If the new optimized state is supposed, then set current = new
- if (optimized_result) {
- s->cur_display_config = s->new_display_config;
- s->cur_policy = s->new_policy;
- } else {
- // Else, restore policy to current
- dml2->v20.dml_core_ctx.policy = s->cur_policy;
- }
- }
-
- // Optimize ended with a failed config, so we need to restore DML state to last passing
- if (!optimized_result) {
- result = pack_and_call_dml_mode_support_ex(dml2,
- &s->cur_display_config,
- &s->mode_support_info,
- validate_mode);
- }
- }
-
- if (result)
- map_hw_resources(dml2, &s->cur_display_config, &s->mode_support_info);
-
- return result;
-}
-
-static bool call_dml_mode_support_and_programming(struct dc_state *context, enum dc_validate_mode validate_mode)
-{
- unsigned int result = 0;
- unsigned int min_state = 0;
- int min_state_for_g6_temp_read = 0;
-
-
- if (!context)
- return false;
-
- struct dml2_context *dml2 = context->bw_ctx.dml2;
- struct dml2_wrapper_scratch *s = &dml2->v20.scratch;
-
- if (!context->streams[0]->sink->link->dc->caps.is_apu) {
- min_state_for_g6_temp_read = calculate_lowest_supported_state_for_temp_read(dml2, context,
- validate_mode);
-
- ASSERT(min_state_for_g6_temp_read >= 0);
- }
-
- result = dml_mode_support_wrapper(dml2, context, validate_mode);
-
- /* Upon trying to sett certain frequencies in FRL, min_state_for_g6_temp_read is reported as -1. This leads to an invalid value of min_state causing crashes later on.
- * Use the default logic for min_state only when min_state_for_g6_temp_read is a valid value. In other cases, use the value calculated by the DML directly.
- */
- if (!context->streams[0]->sink->link->dc->caps.is_apu) {
- if (min_state_for_g6_temp_read >= 0)
- min_state = min_state_for_g6_temp_read > s->mode_support_params.out_lowest_state_idx ? min_state_for_g6_temp_read : s->mode_support_params.out_lowest_state_idx;
- else
- min_state = s->mode_support_params.out_lowest_state_idx;
- }
-
- if (result) {
- if (!context->streams[0]->sink->link->dc->caps.is_apu) {
- result = dml_mode_programming(&dml2->v20.dml_core_ctx, min_state, &s->cur_display_config, true);
- } else {
- result = dml_mode_programming(&dml2->v20.dml_core_ctx, s->mode_support_params.out_lowest_state_idx, &s->cur_display_config, true);
- }
- }
- return result;
-}
-
-static bool dml2_validate_and_build_resource(const struct dc *in_dc, struct dc_state *context,
- enum dc_validate_mode validate_mode)
-{
- struct dml2_context *dml2 = context->bw_ctx.dml2;
- struct dml2_wrapper_scratch *s = &dml2->v20.scratch;
- struct dml2_dcn_clocks out_clks;
- unsigned int result = 0;
- bool need_recalculation = false;
- uint32_t cstate_enter_plus_exit_z8_ns;
-
- if (context->stream_count == 0) {
- unsigned int lowest_state_idx = 0;
-
- out_clks.p_state_supported = true;
- out_clks.dispclk_khz = 0; /* No requirement, and lowest index will generally be maximum dispclk. */
- out_clks.dcfclk_khz = (unsigned int)dml2->v20.dml_core_ctx.states.state_array[lowest_state_idx].dcfclk_mhz * 1000;
- out_clks.fclk_khz = (unsigned int)dml2->v20.dml_core_ctx.states.state_array[lowest_state_idx].fabricclk_mhz * 1000;
- out_clks.uclk_mts = (unsigned int)dml2->v20.dml_core_ctx.states.state_array[lowest_state_idx].dram_speed_mts;
- out_clks.phyclk_khz = (unsigned int)dml2->v20.dml_core_ctx.states.state_array[lowest_state_idx].phyclk_mhz * 1000;
- out_clks.socclk_khz = (unsigned int)dml2->v20.dml_core_ctx.states.state_array[lowest_state_idx].socclk_mhz * 1000;
- out_clks.ref_dtbclk_khz = (unsigned int)dml2->v20.dml_core_ctx.states.state_array[lowest_state_idx].dtbclk_mhz * 1000;
- context->bw_ctx.bw.dcn.clk.dtbclk_en = false;
- dml2_copy_clocks_to_dc_state(&out_clks, context);
- return true;
- }
-
- /* Zero out before each call before proceeding */
- memset(&dml2->v20.scratch, 0, sizeof(struct dml2_wrapper_scratch));
- memset(&dml2->v20.dml_core_ctx.policy, 0, sizeof(struct dml_mode_eval_policy_st));
- memset(&dml2->v20.dml_core_ctx.ms, 0, sizeof(struct mode_support_st));
- memset(&dml2->v20.dml_core_ctx.mp, 0, sizeof(struct mode_program_st));
-
- /* Initialize DET scratch */
- dml2_initialize_det_scratch(dml2);
-
- copy_dummy_pstate_table(s->dummy_pstate_table, in_dc->clk_mgr->bw_params->dummy_pstate_table, 4);
-
- result = call_dml_mode_support_and_programming(context, validate_mode);
- /* Call map dc pipes to map the pipes based on the DML output. For correctly determining if recalculation
- * is required or not, the resource context needs to correctly reflect the number of active pipes. We would
- * only know the correct number if active pipes after dml2_map_dc_pipes is called.
- */
- if (result && !dml2->config.skip_hw_state_mapping)
- dml2_map_dc_pipes(dml2, context, &s->cur_display_config, &s->dml_to_dc_pipe_mapping, in_dc->current_state);
-
- /* Verify and update DET Buffer configuration if needed. dml2_verify_det_buffer_configuration will check if DET Buffer
- * size needs to be updated. If yes it will update the DETOverride variable and set need_recalculation flag to true.
- * Based on that flag, run mode support again. Verification needs to be run after dml_mode_programming because the getters
- * return correct det buffer values only after dml_mode_programming is called.
- */
- if (result && !dml2->config.skip_hw_state_mapping) {
- need_recalculation = dml2_verify_det_buffer_configuration(dml2, context, &dml2->det_helper_scratch);
- if (need_recalculation) {
- /* Engage the DML again if recalculation is required. */
- call_dml_mode_support_and_programming(context, validate_mode);
- if (!dml2->config.skip_hw_state_mapping) {
- dml2_map_dc_pipes(dml2, context, &s->cur_display_config, &s->dml_to_dc_pipe_mapping, in_dc->current_state);
- }
- need_recalculation = dml2_verify_det_buffer_configuration(dml2, context, &dml2->det_helper_scratch);
- ASSERT(need_recalculation == false);
- }
- }
-
- if (result) {
- unsigned int lowest_state_idx = s->mode_support_params.out_lowest_state_idx;
- out_clks.dispclk_khz = (unsigned int)dml2->v20.dml_core_ctx.mp.Dispclk_calculated * 1000;
- out_clks.p_state_supported = s->mode_support_info.DRAMClockChangeSupport[0] != dml_dram_clock_change_unsupported;
- if (in_dc->config.use_default_clock_table &&
- (lowest_state_idx < dml2->v20.dml_core_ctx.states.num_states - 1)) {
- lowest_state_idx = dml2->v20.dml_core_ctx.states.num_states - 1;
- out_clks.dispclk_khz = (unsigned int)dml2->v20.dml_core_ctx.states.state_array[lowest_state_idx].dispclk_mhz * 1000;
- }
-
- out_clks.dcfclk_khz = (unsigned int)dml2->v20.dml_core_ctx.states.state_array[lowest_state_idx].dcfclk_mhz * 1000;
- out_clks.fclk_khz = (unsigned int)dml2->v20.dml_core_ctx.states.state_array[lowest_state_idx].fabricclk_mhz * 1000;
- out_clks.uclk_mts = (unsigned int)dml2->v20.dml_core_ctx.states.state_array[lowest_state_idx].dram_speed_mts;
- out_clks.phyclk_khz = (unsigned int)dml2->v20.dml_core_ctx.states.state_array[lowest_state_idx].phyclk_mhz * 1000;
- out_clks.socclk_khz = (unsigned int)dml2->v20.dml_core_ctx.states.state_array[lowest_state_idx].socclk_mhz * 1000;
- out_clks.ref_dtbclk_khz = (unsigned int)dml2->v20.dml_core_ctx.states.state_array[lowest_state_idx].dtbclk_mhz * 1000;
- context->bw_ctx.bw.dcn.clk.dtbclk_en = is_dtbclk_required(in_dc, context);
-
- if (!dml2->config.skip_hw_state_mapping) {
- /* Call dml2_calculate_rq_and_dlg_params */
- dml2_calculate_rq_and_dlg_params(in_dc, context, &context->res_ctx, dml2, in_dc->res_pool->pipe_count);
- }
-
- dml2_copy_clocks_to_dc_state(&out_clks, context);
- dml2_extract_watermark_set(&context->bw_ctx.bw.dcn.watermarks.a, &dml2->v20.dml_core_ctx);
- dml2_extract_watermark_set(&context->bw_ctx.bw.dcn.watermarks.b, &dml2->v20.dml_core_ctx);
- if (context->streams[0]->sink->link->dc->caps.is_apu)
- dml2_extract_watermark_set(&context->bw_ctx.bw.dcn.watermarks.c, &dml2->v20.dml_core_ctx);
- else
- memcpy(&context->bw_ctx.bw.dcn.watermarks.c, &dml2->v20.g6_temp_read_watermark_set, sizeof(context->bw_ctx.bw.dcn.watermarks.c));
- dml2_extract_watermark_set(&context->bw_ctx.bw.dcn.watermarks.d, &dml2->v20.dml_core_ctx);
- dml2_extract_writeback_wm(context, &dml2->v20.dml_core_ctx);
- //copy for deciding zstate use
- context->bw_ctx.dml.vba.StutterPeriod = context->bw_ctx.dml2->v20.dml_core_ctx.mp.StutterPeriod;
-
- cstate_enter_plus_exit_z8_ns = context->bw_ctx.bw.dcn.watermarks.a.cstate_pstate.cstate_enter_plus_exit_z8_ns;
-
- if (context->bw_ctx.dml.vba.StutterPeriod < in_dc->debug.minimum_z8_residency_time &&
- cstate_enter_plus_exit_z8_ns < in_dc->debug.minimum_z8_residency_time * 1000)
- cstate_enter_plus_exit_z8_ns = in_dc->debug.minimum_z8_residency_time * 1000;
-
- context->bw_ctx.bw.dcn.watermarks.a.cstate_pstate.cstate_enter_plus_exit_z8_ns = cstate_enter_plus_exit_z8_ns;
- }
-
- return result;
-}
-
-static bool dml2_validate_only(struct dc_state *context, enum dc_validate_mode validate_mode)
-{
- struct dml2_context *dml2;
- unsigned int result = 0;
-
- if (!context || context->stream_count == 0)
- return true;
-
- dml2 = context->bw_ctx.dml2;
-
- /* Zero out before each call before proceeding */
- memset(&dml2->v20.scratch, 0, sizeof(struct dml2_wrapper_scratch));
- memset(&dml2->v20.dml_core_ctx.policy, 0, sizeof(struct dml_mode_eval_policy_st));
- memset(&dml2->v20.dml_core_ctx.ms, 0, sizeof(struct mode_support_st));
- memset(&dml2->v20.dml_core_ctx.mp, 0, sizeof(struct mode_program_st));
-
- build_unoptimized_policy_settings(dml2->v20.dml_core_ctx.project, &dml2->v20.dml_core_ctx.policy);
-
- map_dc_state_into_dml_display_cfg(dml2, context, &dml2->v20.scratch.cur_display_config);
- if (!dml2->config.skip_hw_state_mapping)
- dml2_apply_det_buffer_allocation_policy(dml2, &dml2->v20.scratch.cur_display_config);
-
- result = pack_and_call_dml_mode_support_ex(dml2,
- &dml2->v20.scratch.cur_display_config,
- &dml2->v20.scratch.mode_support_info,
- validate_mode);
-
- if (result)
- result = does_configuration_meet_sw_policies(dml2, &dml2->v20.scratch.cur_display_config, &dml2->v20.scratch.mode_support_info);
-
- return result == 1;
-}
-
-static void dml2_apply_debug_options(const struct dc *dc, struct dml2_context *dml2)
-{
- if (dc->debug.override_odm_optimization) {
- dml2->config.minimize_dispclk_using_odm = dc->debug.minimize_dispclk_using_odm;
- }
-}
+#include "dml2_wrapper_fpu.h"
bool dml2_validate(const struct dc *in_dc, struct dc_state *context, struct dml2_context *dml2,
enum dc_validate_mode validate_mode)
@@ -573,11 +36,6 @@ bool dml2_validate(const struct dc *in_dc, struct dc_state *context, struct dml2
return out;
}
-static inline struct dml2_context *dml2_allocate_memory(void)
-{
- return (struct dml2_context *) vzalloc(sizeof(struct dml2_context));
-}
-
static void dml2_init(const struct dc *in_dc, const struct dml2_configuration_options *config, struct dml2_context **dml2)
{
if ((in_dc->debug.using_dml21) && (in_dc->ctx->dce_version >= DCN_VERSION_4_01)) {
@@ -640,57 +98,6 @@ bool dml2_create(const struct dc *in_dc, const struct dml2_configuration_options
return true;
}
-void dml2_destroy(struct dml2_context *dml2)
-{
- if (!dml2)
- return;
-
- if (dml2->architecture == dml2_architecture_21)
- dml21_destroy(dml2);
- vfree(dml2);
-}
-
-void dml2_extract_dram_and_fclk_change_support(struct dml2_context *dml2,
- unsigned int *fclk_change_support, unsigned int *dram_clk_change_support)
-{
- *fclk_change_support = (unsigned int) dml2->v20.dml_core_ctx.ms.support.FCLKChangeSupport[0];
- *dram_clk_change_support = (unsigned int) dml2->v20.dml_core_ctx.ms.support.DRAMClockChangeSupport[0];
-}
-
-void dml2_prepare_mcache_programming(struct dc *in_dc, struct dc_state *context, struct dml2_context *dml2)
-{
- if (dml2->architecture == dml2_architecture_21)
- dml21_prepare_mcache_programming(in_dc, context, dml2);
-}
-
-void dml2_copy(struct dml2_context *dst_dml2,
- struct dml2_context *src_dml2)
-{
- if (src_dml2->architecture == dml2_architecture_21) {
- dml21_copy(dst_dml2, src_dml2);
- return;
- }
- /* copy Mode Lib Ctx */
- memcpy(dst_dml2, src_dml2, sizeof(struct dml2_context));
-}
-
-bool dml2_create_copy(struct dml2_context **dst_dml2,
- struct dml2_context *src_dml2)
-{
- if (src_dml2->architecture == dml2_architecture_21)
- return dml21_create_copy(dst_dml2, src_dml2);
- /* Allocate Mode Lib Ctx */
- *dst_dml2 = dml2_allocate_memory();
-
- if (!(*dst_dml2))
- return false;
-
- /* copy Mode Lib Ctx */
- dml2_copy(*dst_dml2, src_dml2);
-
- return true;
-}
-
void dml2_reinit(const struct dc *in_dc,
const struct dml2_configuration_options *config,
struct dml2_context **dml2)
diff --git a/drivers/gpu/drm/amd/display/dc/dml2_0/dml2_wrapper.h b/drivers/gpu/drm/amd/display/dc/dml2_0/dml2_wrapper.h
index c384e141cebc..9a9c27962f68 100644
--- a/drivers/gpu/drm/amd/display/dc/dml2_0/dml2_wrapper.h
+++ b/drivers/gpu/drm/amd/display/dc/dml2_0/dml2_wrapper.h
@@ -306,4 +306,13 @@ bool dml2_validate(const struct dc *in_dc,
void dml2_extract_dram_and_fclk_change_support(struct dml2_context *dml2,
unsigned int *fclk_change_support, unsigned int *dram_clk_change_support);
void dml2_prepare_mcache_programming(struct dc *in_dc, struct dc_state *context, struct dml2_context *dml2);
+
+void dml2_apply_debug_options(const struct dc *dc, struct dml2_context *dml2);
+bool dml2_validate_only(struct dc_state *context, enum dc_validate_mode validate_mode);
+bool dml2_validate_and_build_resource(const struct dc *in_dc, struct dc_state *context,
+ enum dc_validate_mode validate_mode);
+
+struct dml2_context *dml2_allocate_memory(void);
+
#endif //_DML2_WRAPPER_H_
+
diff --git a/drivers/gpu/drm/amd/display/dc/dml2_0/dml2_wrapper_fpu.c b/drivers/gpu/drm/amd/display/dc/dml2_0/dml2_wrapper_fpu.c
new file mode 100644
index 000000000000..203eef747262
--- /dev/null
+++ b/drivers/gpu/drm/amd/display/dc/dml2_0/dml2_wrapper_fpu.c
@@ -0,0 +1,604 @@
+/* SPDX-License-Identifier: MIT */
+/*
+ * Copyright 2023 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_core.h"
+#include "dml2_internal_types.h"
+#include "dml2_utils.h"
+#include "dml2_policy.h"
+#include "dml2_translation_helper.h"
+#include "dml2_mall_phantom.h"
+#include "dml2_dc_resource_mgmt.h"
+#include "dml21_wrapper.h"
+#include "dml2_wrapper_fpu.h"
+
+void initialize_dml2_ip_params(struct dml2_context *dml2, const struct dc *in_dc, struct ip_params_st *out)
+{
+ if (dml2->config.use_native_soc_bb_construction)
+ dml2_init_ip_params(dml2, in_dc, out);
+ else
+ dml2_translate_ip_params(in_dc, out);
+}
+
+void initialize_dml2_soc_bbox(struct dml2_context *dml2, const struct dc *in_dc, struct soc_bounding_box_st *out)
+{
+ if (dml2->config.use_native_soc_bb_construction)
+ dml2_init_socbb_params(dml2, in_dc, out);
+ else
+ dml2_translate_socbb_params(in_dc, out);
+}
+
+void initialize_dml2_soc_states(struct dml2_context *dml2,
+ const struct dc *in_dc, const struct soc_bounding_box_st *in_bbox, struct soc_states_st *out)
+{
+ if (dml2->config.use_native_soc_bb_construction)
+ dml2_init_soc_states(dml2, in_dc, in_bbox, out);
+ else
+ dml2_translate_soc_states(in_dc, out, in_dc->dml.soc.num_states);
+}
+
+static void map_hw_resources(struct dml2_context *dml2,
+ struct dml_display_cfg_st *in_out_display_cfg, struct dml_mode_support_info_st *mode_support_info)
+{
+ unsigned int num_pipes = 0;
+ int i, j;
+
+ for (i = 0; i < __DML_NUM_PLANES__; i++) {
+ in_out_display_cfg->hw.ODMMode[i] = mode_support_info->ODMMode[i];
+ in_out_display_cfg->hw.DPPPerSurface[i] = mode_support_info->DPPPerSurface[i];
+ in_out_display_cfg->hw.DSCEnabled[i] = mode_support_info->DSCEnabled[i];
+ in_out_display_cfg->hw.NumberOfDSCSlices[i] = mode_support_info->NumberOfDSCSlices[i];
+ in_out_display_cfg->hw.DLGRefClkFreqMHz = 24;
+ if (dml2->v20.dml_core_ctx.project != dml_project_dcn35 &&
+ dml2->v20.dml_core_ctx.project != dml_project_dcn36 &&
+ dml2->v20.dml_core_ctx.project != dml_project_dcn351) {
+ /*dGPU default as 50Mhz*/
+ in_out_display_cfg->hw.DLGRefClkFreqMHz = 50;
+ }
+ for (j = 0; j < mode_support_info->DPPPerSurface[i]; j++) {
+ if (i >= __DML2_WRAPPER_MAX_STREAMS_PLANES__) {
+ dml_print("DML::%s: Index out of bounds: i=%d, __DML2_WRAPPER_MAX_STREAMS_PLANES__=%d\n",
+ __func__, i, __DML2_WRAPPER_MAX_STREAMS_PLANES__);
+ break;
+ }
+ dml2->v20.scratch.dml_to_dc_pipe_mapping.dml_pipe_idx_to_stream_id[num_pipes] = dml2->v20.scratch.dml_to_dc_pipe_mapping.disp_cfg_to_stream_id[i];
+ dml2->v20.scratch.dml_to_dc_pipe_mapping.dml_pipe_idx_to_stream_id_valid[num_pipes] = true;
+ dml2->v20.scratch.dml_to_dc_pipe_mapping.dml_pipe_idx_to_plane_id[num_pipes] = dml2->v20.scratch.dml_to_dc_pipe_mapping.disp_cfg_to_plane_id[i];
+ dml2->v20.scratch.dml_to_dc_pipe_mapping.dml_pipe_idx_to_plane_id_valid[num_pipes] = true;
+ num_pipes++;
+ }
+ }
+}
+
+static unsigned int pack_and_call_dml_mode_support_ex(struct dml2_context *dml2,
+ const struct dml_display_cfg_st *display_cfg,
+ struct dml_mode_support_info_st *evaluation_info,
+ enum dc_validate_mode validate_mode)
+{
+ struct dml2_wrapper_scratch *s = &dml2->v20.scratch;
+
+ s->mode_support_params.mode_lib = &dml2->v20.dml_core_ctx;
+ s->mode_support_params.in_display_cfg = display_cfg;
+ if (validate_mode == DC_VALIDATE_MODE_ONLY)
+ s->mode_support_params.in_start_state_idx = dml2->v20.dml_core_ctx.states.num_states - 1;
+ else
+ s->mode_support_params.in_start_state_idx = 0;
+ s->mode_support_params.out_evaluation_info = evaluation_info;
+
+ memset(evaluation_info, 0, sizeof(struct dml_mode_support_info_st));
+ s->mode_support_params.out_lowest_state_idx = 0;
+
+ return dml_mode_support_ex(&s->mode_support_params);
+}
+
+static bool optimize_configuration(struct dml2_context *dml2, struct dml2_wrapper_optimize_configuration_params *p)
+{
+ int unused_dpps = p->ip_params->max_num_dpp;
+ int i;
+ int odms_needed;
+ int largest_blend_and_timing = 0;
+ bool optimization_done = false;
+
+ for (i = 0; i < (int) p->cur_display_config->num_timings; i++) {
+ if (p->cur_display_config->plane.BlendingAndTiming[i] > largest_blend_and_timing)
+ largest_blend_and_timing = p->cur_display_config->plane.BlendingAndTiming[i];
+ }
+
+ if (p->new_policy != p->cur_policy)
+ *p->new_policy = *p->cur_policy;
+
+ if (p->new_display_config != p->cur_display_config)
+ *p->new_display_config = *p->cur_display_config;
+
+
+ // Optimize Clocks
+ if (!optimization_done) {
+ if (largest_blend_and_timing == 0 && p->cur_policy->ODMUse[0] == dml_odm_use_policy_combine_as_needed && dml2->config.minimize_dispclk_using_odm) {
+ odms_needed = dml2_util_get_maximum_odm_combine_for_output(dml2->config.optimize_odm_4to1,
+ p->cur_display_config->output.OutputEncoder[0], p->cur_mode_support_info->DSCEnabled[0]) - 1;
+
+ if (odms_needed <= unused_dpps) {
+ if (odms_needed == 1) {
+ p->new_policy->ODMUse[0] = dml_odm_use_policy_combine_2to1;
+ optimization_done = true;
+ } else if (odms_needed == 3) {
+ p->new_policy->ODMUse[0] = dml_odm_use_policy_combine_4to1;
+ optimization_done = true;
+ } else
+ optimization_done = false;
+ }
+ }
+ }
+
+ return optimization_done;
+}
+
+static int calculate_lowest_supported_state_for_temp_read(struct dml2_context *dml2, struct dc_state *display_state,
+ enum dc_validate_mode validate_mode)
+{
+ struct dml2_calculate_lowest_supported_state_for_temp_read_scratch *s = &dml2->v20.scratch.dml2_calculate_lowest_supported_state_for_temp_read_scratch;
+ struct dml2_wrapper_scratch *s_global = &dml2->v20.scratch;
+
+ unsigned int dml_result = 0;
+ int result = -1, i, j;
+
+ build_unoptimized_policy_settings(dml2->v20.dml_core_ctx.project, &dml2->v20.dml_core_ctx.policy);
+
+ /* Zero out before each call before proceeding */
+ memset(s, 0, sizeof(struct dml2_calculate_lowest_supported_state_for_temp_read_scratch));
+ memset(&s_global->mode_support_params, 0, sizeof(struct dml_mode_support_ex_params_st));
+ memset(&s_global->dml_to_dc_pipe_mapping, 0, sizeof(struct dml2_dml_to_dc_pipe_mapping));
+
+ for (i = 0; i < dml2->config.dcn_pipe_count; i++) {
+ /* Calling resource_build_scaling_params will populate the pipe params
+ * with the necessary information needed for correct DML calculations
+ * This is also done in DML1 driver code path and hence display_state
+ * cannot be const.
+ */
+ struct pipe_ctx *pipe = &display_state->res_ctx.pipe_ctx[i];
+
+ if (pipe->plane_state) {
+ if (!dml2->config.callbacks.build_scaling_params(pipe)) {
+ ASSERT(false);
+ return false;
+ }
+ }
+ }
+
+ map_dc_state_into_dml_display_cfg(dml2, display_state, &s->cur_display_config);
+
+ for (i = 0; i < dml2->v20.dml_core_ctx.states.num_states; i++) {
+ s->uclk_change_latencies[i] = dml2->v20.dml_core_ctx.states.state_array[i].dram_clock_change_latency_us;
+ }
+
+ for (i = 0; i < 4; i++) {
+ for (j = 0; j < dml2->v20.dml_core_ctx.states.num_states; j++) {
+ dml2->v20.dml_core_ctx.states.state_array[j].dram_clock_change_latency_us = s_global->dummy_pstate_table[i].dummy_pstate_latency_us;
+ }
+
+ dml_result = pack_and_call_dml_mode_support_ex(dml2, &s->cur_display_config, &s->evaluation_info,
+ validate_mode);
+
+ if (dml_result && s->evaluation_info.DRAMClockChangeSupport[0] == dml_dram_clock_change_vactive) {
+ map_hw_resources(dml2, &s->cur_display_config, &s->evaluation_info);
+ dml_result = dml_mode_programming(&dml2->v20.dml_core_ctx, s_global->mode_support_params.out_lowest_state_idx, &s->cur_display_config, true);
+
+ ASSERT(dml_result);
+
+ dml2_extract_watermark_set(&dml2->v20.g6_temp_read_watermark_set, &dml2->v20.dml_core_ctx);
+ dml2->v20.g6_temp_read_watermark_set.cstate_pstate.fclk_pstate_change_ns = dml2->v20.g6_temp_read_watermark_set.cstate_pstate.pstate_change_ns;
+
+ result = s_global->mode_support_params.out_lowest_state_idx;
+
+ while (dml2->v20.dml_core_ctx.states.state_array[result].dram_speed_mts < s_global->dummy_pstate_table[i].dram_speed_mts)
+ result++;
+
+ break;
+ }
+ }
+
+ for (i = 0; i < dml2->v20.dml_core_ctx.states.num_states; i++) {
+ dml2->v20.dml_core_ctx.states.state_array[i].dram_clock_change_latency_us = s->uclk_change_latencies[i];
+ }
+
+ return result;
+}
+
+static void copy_dummy_pstate_table(struct dummy_pstate_entry *dest, struct dummy_pstate_entry *src, unsigned int num_entries)
+{
+ for (int i = 0; i < num_entries; i++) {
+ dest[i] = src[i];
+ }
+}
+
+static bool are_timings_requiring_odm_doing_blending(const struct dml_display_cfg_st *display_cfg,
+ const struct dml_mode_support_info_st *evaluation_info)
+{
+ unsigned int planes_per_timing[__DML_NUM_PLANES__] = {0};
+ int i;
+
+ for (i = 0; i < display_cfg->num_surfaces; i++)
+ planes_per_timing[display_cfg->plane.BlendingAndTiming[i]]++;
+
+ for (i = 0; i < __DML_NUM_PLANES__; i++) {
+ if (planes_per_timing[i] > 1 && evaluation_info->ODMMode[i] != dml_odm_mode_bypass)
+ return true;
+ }
+
+ return false;
+}
+
+static bool does_configuration_meet_sw_policies(struct dml2_context *ctx, const struct dml_display_cfg_st *display_cfg,
+ const struct dml_mode_support_info_st *evaluation_info)
+{
+ bool pass = true;
+
+ if (!ctx->config.enable_windowed_mpo_odm) {
+ if (are_timings_requiring_odm_doing_blending(display_cfg, evaluation_info))
+ pass = false;
+ }
+
+ return pass;
+}
+
+static bool dml_mode_support_wrapper(struct dml2_context *dml2,
+ struct dc_state *display_state,
+ enum dc_validate_mode validate_mode)
+{
+ struct dml2_wrapper_scratch *s = &dml2->v20.scratch;
+ unsigned int result = 0, i;
+ unsigned int optimized_result = true;
+
+ build_unoptimized_policy_settings(dml2->v20.dml_core_ctx.project, &dml2->v20.dml_core_ctx.policy);
+
+ /* Zero out before each call before proceeding */
+ memset(&s->cur_display_config, 0, sizeof(struct dml_display_cfg_st));
+ memset(&s->mode_support_params, 0, sizeof(struct dml_mode_support_ex_params_st));
+ memset(&s->dml_to_dc_pipe_mapping, 0, sizeof(struct dml2_dml_to_dc_pipe_mapping));
+ memset(&s->optimize_configuration_params, 0, sizeof(struct dml2_wrapper_optimize_configuration_params));
+
+ for (i = 0; i < dml2->config.dcn_pipe_count; i++) {
+ /* Calling resource_build_scaling_params will populate the pipe params
+ * with the necessary information needed for correct DML calculations
+ * This is also done in DML1 driver code path and hence display_state
+ * cannot be const.
+ */
+ struct pipe_ctx *pipe = &display_state->res_ctx.pipe_ctx[i];
+
+ if (pipe->plane_state) {
+ if (!dml2->config.callbacks.build_scaling_params(pipe)) {
+ ASSERT(false);
+ return false;
+ }
+ }
+ }
+
+ map_dc_state_into_dml_display_cfg(dml2, display_state, &s->cur_display_config);
+ if (!dml2->config.skip_hw_state_mapping)
+ dml2_apply_det_buffer_allocation_policy(dml2, &s->cur_display_config);
+
+ result = pack_and_call_dml_mode_support_ex(dml2,
+ &s->cur_display_config,
+ &s->mode_support_info,
+ validate_mode);
+
+ if (result)
+ result = does_configuration_meet_sw_policies(dml2, &s->cur_display_config, &s->mode_support_info);
+
+ // Try to optimize
+ if (result) {
+ s->cur_policy = dml2->v20.dml_core_ctx.policy;
+ s->optimize_configuration_params.dml_core_ctx = &dml2->v20.dml_core_ctx;
+ s->optimize_configuration_params.config = &dml2->config;
+ s->optimize_configuration_params.ip_params = &dml2->v20.dml_core_ctx.ip;
+ s->optimize_configuration_params.cur_display_config = &s->cur_display_config;
+ s->optimize_configuration_params.cur_mode_support_info = &s->mode_support_info;
+ s->optimize_configuration_params.cur_policy = &s->cur_policy;
+ s->optimize_configuration_params.new_display_config = &s->new_display_config;
+ s->optimize_configuration_params.new_policy = &s->new_policy;
+
+ while (optimized_result && optimize_configuration(dml2, &s->optimize_configuration_params)) {
+ dml2->v20.dml_core_ctx.policy = s->new_policy;
+ optimized_result = pack_and_call_dml_mode_support_ex(dml2,
+ &s->new_display_config,
+ &s->mode_support_info,
+ validate_mode);
+
+ if (optimized_result)
+ optimized_result = does_configuration_meet_sw_policies(dml2, &s->new_display_config, &s->mode_support_info);
+
+ // If the new optimized state is supposed, then set current = new
+ if (optimized_result) {
+ s->cur_display_config = s->new_display_config;
+ s->cur_policy = s->new_policy;
+ } else {
+ // Else, restore policy to current
+ dml2->v20.dml_core_ctx.policy = s->cur_policy;
+ }
+ }
+
+ // Optimize ended with a failed config, so we need to restore DML state to last passing
+ if (!optimized_result) {
+ result = pack_and_call_dml_mode_support_ex(dml2,
+ &s->cur_display_config,
+ &s->mode_support_info,
+ validate_mode);
+ }
+ }
+
+ if (result)
+ map_hw_resources(dml2, &s->cur_display_config, &s->mode_support_info);
+
+ return result;
+}
+
+static bool call_dml_mode_support_and_programming(struct dc_state *context, enum dc_validate_mode validate_mode)
+{
+ unsigned int result = 0;
+ unsigned int min_state = 0;
+ int min_state_for_g6_temp_read = 0;
+
+
+ if (!context)
+ return false;
+
+ struct dml2_context *dml2 = context->bw_ctx.dml2;
+ struct dml2_wrapper_scratch *s = &dml2->v20.scratch;
+
+ if (!context->streams[0]->sink->link->dc->caps.is_apu) {
+ min_state_for_g6_temp_read = calculate_lowest_supported_state_for_temp_read(dml2, context,
+ validate_mode);
+
+ ASSERT(min_state_for_g6_temp_read >= 0);
+ }
+
+ result = dml_mode_support_wrapper(dml2, context, validate_mode);
+
+ /* Upon trying to sett certain frequencies in FRL, min_state_for_g6_temp_read is reported as -1. This leads to an invalid value of min_state causing crashes later on.
+ * Use the default logic for min_state only when min_state_for_g6_temp_read is a valid value. In other cases, use the value calculated by the DML directly.
+ */
+ if (!context->streams[0]->sink->link->dc->caps.is_apu) {
+ if (min_state_for_g6_temp_read >= 0)
+ min_state = min_state_for_g6_temp_read > s->mode_support_params.out_lowest_state_idx ? min_state_for_g6_temp_read : s->mode_support_params.out_lowest_state_idx;
+ else
+ min_state = s->mode_support_params.out_lowest_state_idx;
+ }
+
+ if (result) {
+ if (!context->streams[0]->sink->link->dc->caps.is_apu) {
+ result = dml_mode_programming(&dml2->v20.dml_core_ctx, min_state, &s->cur_display_config, true);
+ } else {
+ result = dml_mode_programming(&dml2->v20.dml_core_ctx, s->mode_support_params.out_lowest_state_idx, &s->cur_display_config, true);
+ }
+ }
+ return result;
+}
+
+bool dml2_validate_and_build_resource(const struct dc *in_dc, struct dc_state *context,
+ enum dc_validate_mode validate_mode)
+{
+ struct dml2_context *dml2 = context->bw_ctx.dml2;
+ struct dml2_wrapper_scratch *s = &dml2->v20.scratch;
+ struct dml2_dcn_clocks out_clks;
+ unsigned int result = 0;
+ bool need_recalculation = false;
+ uint32_t cstate_enter_plus_exit_z8_ns;
+
+ if (context->stream_count == 0) {
+ unsigned int lowest_state_idx = 0;
+
+ out_clks.p_state_supported = true;
+ out_clks.dispclk_khz = 0; /* No requirement, and lowest index will generally be maximum dispclk. */
+ out_clks.dcfclk_khz = (unsigned int)dml2->v20.dml_core_ctx.states.state_array[lowest_state_idx].dcfclk_mhz * 1000;
+ out_clks.fclk_khz = (unsigned int)dml2->v20.dml_core_ctx.states.state_array[lowest_state_idx].fabricclk_mhz * 1000;
+ out_clks.uclk_mts = (unsigned int)dml2->v20.dml_core_ctx.states.state_array[lowest_state_idx].dram_speed_mts;
+ out_clks.phyclk_khz = (unsigned int)dml2->v20.dml_core_ctx.states.state_array[lowest_state_idx].phyclk_mhz * 1000;
+ out_clks.socclk_khz = (unsigned int)dml2->v20.dml_core_ctx.states.state_array[lowest_state_idx].socclk_mhz * 1000;
+ out_clks.ref_dtbclk_khz = (unsigned int)dml2->v20.dml_core_ctx.states.state_array[lowest_state_idx].dtbclk_mhz * 1000;
+ context->bw_ctx.bw.dcn.clk.dtbclk_en = false;
+ dml2_copy_clocks_to_dc_state(&out_clks, context);
+ return true;
+ }
+
+ /* Zero out before each call before proceeding */
+ memset(&dml2->v20.scratch, 0, sizeof(struct dml2_wrapper_scratch));
+ memset(&dml2->v20.dml_core_ctx.policy, 0, sizeof(struct dml_mode_eval_policy_st));
+ memset(&dml2->v20.dml_core_ctx.ms, 0, sizeof(struct mode_support_st));
+ memset(&dml2->v20.dml_core_ctx.mp, 0, sizeof(struct mode_program_st));
+
+ /* Initialize DET scratch */
+ dml2_initialize_det_scratch(dml2);
+
+ copy_dummy_pstate_table(s->dummy_pstate_table, in_dc->clk_mgr->bw_params->dummy_pstate_table, 4);
+
+ result = call_dml_mode_support_and_programming(context, validate_mode);
+ /* Call map dc pipes to map the pipes based on the DML output. For correctly determining if recalculation
+ * is required or not, the resource context needs to correctly reflect the number of active pipes. We would
+ * only know the correct number if active pipes after dml2_map_dc_pipes is called.
+ */
+ if (result && !dml2->config.skip_hw_state_mapping)
+ dml2_map_dc_pipes(dml2, context, &s->cur_display_config, &s->dml_to_dc_pipe_mapping, in_dc->current_state);
+
+ /* Verify and update DET Buffer configuration if needed. dml2_verify_det_buffer_configuration will check if DET Buffer
+ * size needs to be updated. If yes it will update the DETOverride variable and set need_recalculation flag to true.
+ * Based on that flag, run mode support again. Verification needs to be run after dml_mode_programming because the getters
+ * return correct det buffer values only after dml_mode_programming is called.
+ */
+ if (result && !dml2->config.skip_hw_state_mapping) {
+ need_recalculation = dml2_verify_det_buffer_configuration(dml2, context, &dml2->det_helper_scratch);
+ if (need_recalculation) {
+ /* Engage the DML again if recalculation is required. */
+ call_dml_mode_support_and_programming(context, validate_mode);
+ if (!dml2->config.skip_hw_state_mapping) {
+ dml2_map_dc_pipes(dml2, context, &s->cur_display_config, &s->dml_to_dc_pipe_mapping, in_dc->current_state);
+ }
+ need_recalculation = dml2_verify_det_buffer_configuration(dml2, context, &dml2->det_helper_scratch);
+ ASSERT(need_recalculation == false);
+ }
+ }
+
+ if (result) {
+ unsigned int lowest_state_idx = s->mode_support_params.out_lowest_state_idx;
+ out_clks.dispclk_khz = (unsigned int)dml2->v20.dml_core_ctx.mp.Dispclk_calculated * 1000;
+ out_clks.p_state_supported = s->mode_support_info.DRAMClockChangeSupport[0] != dml_dram_clock_change_unsupported;
+ if (in_dc->config.use_default_clock_table &&
+ (lowest_state_idx < dml2->v20.dml_core_ctx.states.num_states - 1)) {
+ lowest_state_idx = dml2->v20.dml_core_ctx.states.num_states - 1;
+ out_clks.dispclk_khz = (unsigned int)dml2->v20.dml_core_ctx.states.state_array[lowest_state_idx].dispclk_mhz * 1000;
+ }
+
+ out_clks.dcfclk_khz = (unsigned int)dml2->v20.dml_core_ctx.states.state_array[lowest_state_idx].dcfclk_mhz * 1000;
+ out_clks.fclk_khz = (unsigned int)dml2->v20.dml_core_ctx.states.state_array[lowest_state_idx].fabricclk_mhz * 1000;
+ out_clks.uclk_mts = (unsigned int)dml2->v20.dml_core_ctx.states.state_array[lowest_state_idx].dram_speed_mts;
+ out_clks.phyclk_khz = (unsigned int)dml2->v20.dml_core_ctx.states.state_array[lowest_state_idx].phyclk_mhz * 1000;
+ out_clks.socclk_khz = (unsigned int)dml2->v20.dml_core_ctx.states.state_array[lowest_state_idx].socclk_mhz * 1000;
+ out_clks.ref_dtbclk_khz = (unsigned int)dml2->v20.dml_core_ctx.states.state_array[lowest_state_idx].dtbclk_mhz * 1000;
+ context->bw_ctx.bw.dcn.clk.dtbclk_en = is_dtbclk_required(in_dc, context);
+
+ if (!dml2->config.skip_hw_state_mapping) {
+ /* Call dml2_calculate_rq_and_dlg_params */
+ dml2_calculate_rq_and_dlg_params(in_dc, context, &context->res_ctx, dml2, in_dc->res_pool->pipe_count);
+ }
+
+ dml2_copy_clocks_to_dc_state(&out_clks, context);
+ dml2_extract_watermark_set(&context->bw_ctx.bw.dcn.watermarks.a, &dml2->v20.dml_core_ctx);
+ dml2_extract_watermark_set(&context->bw_ctx.bw.dcn.watermarks.b, &dml2->v20.dml_core_ctx);
+ if (context->streams[0]->sink->link->dc->caps.is_apu)
+ dml2_extract_watermark_set(&context->bw_ctx.bw.dcn.watermarks.c, &dml2->v20.dml_core_ctx);
+ else
+ memcpy(&context->bw_ctx.bw.dcn.watermarks.c, &dml2->v20.g6_temp_read_watermark_set, sizeof(context->bw_ctx.bw.dcn.watermarks.c));
+ dml2_extract_watermark_set(&context->bw_ctx.bw.dcn.watermarks.d, &dml2->v20.dml_core_ctx);
+ dml2_extract_writeback_wm(context, &dml2->v20.dml_core_ctx);
+ //copy for deciding zstate use
+ context->bw_ctx.dml.vba.StutterPeriod = context->bw_ctx.dml2->v20.dml_core_ctx.mp.StutterPeriod;
+
+ cstate_enter_plus_exit_z8_ns = context->bw_ctx.bw.dcn.watermarks.a.cstate_pstate.cstate_enter_plus_exit_z8_ns;
+
+ if (context->bw_ctx.dml.vba.StutterPeriod < in_dc->debug.minimum_z8_residency_time &&
+ cstate_enter_plus_exit_z8_ns < in_dc->debug.minimum_z8_residency_time * 1000)
+ cstate_enter_plus_exit_z8_ns = in_dc->debug.minimum_z8_residency_time * 1000;
+
+ context->bw_ctx.bw.dcn.watermarks.a.cstate_pstate.cstate_enter_plus_exit_z8_ns = cstate_enter_plus_exit_z8_ns;
+ }
+
+ return result;
+}
+
+bool dml2_validate_only(struct dc_state *context, enum dc_validate_mode validate_mode)
+{
+ struct dml2_context *dml2;
+ unsigned int result = 0;
+
+ if (!context || context->stream_count == 0)
+ return true;
+
+ dml2 = context->bw_ctx.dml2;
+
+ /* Zero out before each call before proceeding */
+ memset(&dml2->v20.scratch, 0, sizeof(struct dml2_wrapper_scratch));
+ memset(&dml2->v20.dml_core_ctx.policy, 0, sizeof(struct dml_mode_eval_policy_st));
+ memset(&dml2->v20.dml_core_ctx.ms, 0, sizeof(struct mode_support_st));
+ memset(&dml2->v20.dml_core_ctx.mp, 0, sizeof(struct mode_program_st));
+
+ build_unoptimized_policy_settings(dml2->v20.dml_core_ctx.project, &dml2->v20.dml_core_ctx.policy);
+
+ map_dc_state_into_dml_display_cfg(dml2, context, &dml2->v20.scratch.cur_display_config);
+ if (!dml2->config.skip_hw_state_mapping)
+ dml2_apply_det_buffer_allocation_policy(dml2, &dml2->v20.scratch.cur_display_config);
+
+ result = pack_and_call_dml_mode_support_ex(dml2,
+ &dml2->v20.scratch.cur_display_config,
+ &dml2->v20.scratch.mode_support_info,
+ validate_mode);
+
+ if (result)
+ result = does_configuration_meet_sw_policies(dml2, &dml2->v20.scratch.cur_display_config, &dml2->v20.scratch.mode_support_info);
+
+ return result == 1;
+}
+
+void dml2_apply_debug_options(const struct dc *dc, struct dml2_context *dml2)
+{
+ if (dc->debug.override_odm_optimization) {
+ dml2->config.minimize_dispclk_using_odm = dc->debug.minimize_dispclk_using_odm;
+ }
+}
+
+inline struct dml2_context *dml2_allocate_memory(void)
+{
+ return (struct dml2_context *) vzalloc(sizeof(struct dml2_context));
+}
+
+void dml2_destroy(struct dml2_context *dml2)
+{
+ if (!dml2)
+ return;
+
+ if (dml2->architecture == dml2_architecture_21)
+ dml21_destroy(dml2);
+ vfree(dml2);
+}
+
+void dml2_extract_dram_and_fclk_change_support(struct dml2_context *dml2,
+ unsigned int *fclk_change_support, unsigned int *dram_clk_change_support)
+{
+ *fclk_change_support = (unsigned int) dml2->v20.dml_core_ctx.ms.support.FCLKChangeSupport[0];
+ *dram_clk_change_support = (unsigned int) dml2->v20.dml_core_ctx.ms.support.DRAMClockChangeSupport[0];
+}
+
+void dml2_prepare_mcache_programming(struct dc *in_dc, struct dc_state *context, struct dml2_context *dml2)
+{
+ if (dml2->architecture == dml2_architecture_21)
+ dml21_prepare_mcache_programming(in_dc, context, dml2);
+}
+
+void dml2_copy(struct dml2_context *dst_dml2,
+ struct dml2_context *src_dml2)
+{
+ if (src_dml2->architecture == dml2_architecture_21) {
+ dml21_copy(dst_dml2, src_dml2);
+ return;
+ }
+ /* copy Mode Lib Ctx */
+ memcpy(dst_dml2, src_dml2, sizeof(struct dml2_context));
+}
+
+bool dml2_create_copy(struct dml2_context **dst_dml2,
+ struct dml2_context *src_dml2)
+{
+ if (src_dml2->architecture == dml2_architecture_21)
+ return dml21_create_copy(dst_dml2, src_dml2);
+ /* Allocate Mode Lib Ctx */
+ *dst_dml2 = dml2_allocate_memory();
+
+ if (!(*dst_dml2))
+ return false;
+
+ /* copy Mode Lib Ctx */
+ dml2_copy(*dst_dml2, src_dml2);
+
+ return true;
+}
+
diff --git a/drivers/gpu/drm/amd/display/dc/dml2_0/dml2_wrapper_fpu.h b/drivers/gpu/drm/amd/display/dc/dml2_0/dml2_wrapper_fpu.h
new file mode 100644
index 000000000000..573df874b901
--- /dev/null
+++ b/drivers/gpu/drm/amd/display/dc/dml2_0/dml2_wrapper_fpu.h
@@ -0,0 +1,25 @@
+/* SPDX-License-Identifier: MIT */
+/*
+ * Copyright 2025 Advanced Micro Devices, Inc.
+ *
+ * Authors: AMD
+ */
+
+#ifndef _DML2_WRAPPER_FPU_H_
+#define _DML2_WRAPPER_FPU_H_
+
+#include "os_types.h"
+
+struct dml2_context;
+struct dc;
+struct ip_params_st;
+struct soc_bounding_box_st;
+struct soc_states_st;
+
+void initialize_dml2_ip_params(struct dml2_context *dml2, const struct dc *in_dc, struct ip_params_st *out);
+void initialize_dml2_soc_bbox(struct dml2_context *dml2, const struct dc *in_dc, struct soc_bounding_box_st *out);
+void initialize_dml2_soc_states(struct dml2_context *dml2,
+ const struct dc *in_dc, const struct soc_bounding_box_st *in_bbox, struct soc_states_st *out);
+
+#endif //_DML2_WRAPPER_FPU_H_
+
diff --git a/drivers/gpu/drm/amd/display/dc/dpp/dcn10/dcn10_dpp.h b/drivers/gpu/drm/amd/display/dc/dpp/dcn10/dcn10_dpp.h
index b12f34345a58..890d04b1ddaf 100644
--- a/drivers/gpu/drm/amd/display/dc/dpp/dcn10/dcn10_dpp.h
+++ b/drivers/gpu/drm/amd/display/dc/dpp/dcn10/dcn10_dpp.h
@@ -545,6 +545,7 @@
type SCL_COEF_RAM_SELECT_CURRENT; \
type LUT_MEM_PWR_FORCE; \
type LUT_MEM_PWR_STATE; \
+ type LUT_MEM_PWR_DIS; \
type CM_GAMUT_REMAP_MODE; \
type CM_GAMUT_REMAP_C11; \
type CM_GAMUT_REMAP_C12; \
diff --git a/drivers/gpu/drm/amd/display/dc/dpp/dcn401/dcn401_dpp.h b/drivers/gpu/drm/amd/display/dc/dpp/dcn401/dcn401_dpp.h
index 5f6b431ec398..58b9f1cd0825 100644
--- a/drivers/gpu/drm/amd/display/dc/dpp/dcn401/dcn401_dpp.h
+++ b/drivers/gpu/drm/amd/display/dc/dpp/dcn401/dcn401_dpp.h
@@ -41,6 +41,7 @@
TF_SF(CM0_CM_BIAS_Y_G_CB_B, CM_BIAS_CB_B, mask_sh),\
TF_SF(CM0_CM_MEM_PWR_CTRL, GAMCOR_MEM_PWR_DIS, mask_sh),\
TF_SF(CM0_CM_MEM_PWR_CTRL, GAMCOR_MEM_PWR_FORCE, mask_sh),\
+ TF_SF(CM0_CM_MEM_PWR_CTRL, GAMCOR_MEM_PWR_DIS, mask_sh),\
TF_SF(CNVC_CFG0_PRE_DEGAM, PRE_DEGAM_MODE, mask_sh),\
TF_SF(CNVC_CFG0_PRE_DEGAM, PRE_DEGAM_SELECT, mask_sh),\
TF_SF(CM0_CM_GAMCOR_CONTROL, CM_GAMCOR_MODE, mask_sh),\
@@ -208,6 +209,7 @@
TF_SF(CM_CUR0_CURSOR0_CONTROL, CUR0_ROM_EN, mask_sh),\
TF_SF(DSCL0_OBUF_MEM_PWR_CTRL, OBUF_MEM_PWR_FORCE, mask_sh),\
TF_SF(DSCL0_DSCL_MEM_PWR_CTRL, LUT_MEM_PWR_FORCE, mask_sh),\
+ TF_SF(DSCL0_DSCL_MEM_PWR_CTRL, LUT_MEM_PWR_DIS, mask_sh),\
TF_SF(DSCL0_DSCL_MEM_PWR_STATUS, LUT_MEM_PWR_STATE, mask_sh),\
TF_SF(DSCL0_DSCL_SC_MODE, SCL_SC_MATRIX_MODE, mask_sh),\
TF_SF(DSCL0_DSCL_SC_MODE, SCL_SC_LTONL_EN, mask_sh),\
@@ -336,6 +338,9 @@
TF_SF(DSCL0_DSCL_SC_MATRIX_C2C3, SCL_SC_MATRIX_C2, mask_sh),\
TF_SF(DSCL0_DSCL_SC_MATRIX_C2C3, SCL_SC_MATRIX_C3, mask_sh),\
TF_SF(DSCL0_ISHARP_DELTA_CTRL, ISHARP_DELTA_LUT_HOST_SELECT, mask_sh),\
+ TF_SF(DSCL0_ISHARP_DELTA_LUT_MEM_PWR_CTRL, ISHARP_DELTA_LUT_MEM_PWR_DIS, mask_sh),\
+ TF_SF(DSCL0_ISHARP_DELTA_LUT_MEM_PWR_CTRL, ISHARP_DELTA_LUT_MEM_PWR_FORCE, mask_sh),\
+ TF_SF(DSCL0_ISHARP_DELTA_LUT_MEM_PWR_CTRL, ISHARP_DELTA_LUT_MEM_PWR_STATE, mask_sh),\
TF_SF(DSCL0_ISHARP_DELTA_DATA, ISHARP_DELTA_DATA, mask_sh),\
TF_SF(DSCL0_ISHARP_DELTA_INDEX, ISHARP_DELTA_INDEX, mask_sh),\
TF_SF(DSCL0_ISHARP_MODE, ISHARP_EN, mask_sh),\
@@ -558,6 +563,9 @@
type ISHARP_DELTA_LUT_SELECT; \
type ISHARP_DELTA_LUT_SELECT_CURRENT; \
type ISHARP_DELTA_LUT_HOST_SELECT; \
+ type ISHARP_DELTA_LUT_MEM_PWR_DIS; \
+ type ISHARP_DELTA_LUT_MEM_PWR_FORCE;\
+ type ISHARP_DELTA_LUT_MEM_PWR_STATE;\
type ISHARP_DELTA_DATA; \
type ISHARP_DELTA_INDEX; \
type ISHARP_NLDELTA_SCLIP_EN_P; \
@@ -629,6 +637,7 @@
uint32_t DSCL_SC_MATRIX_C0C1; \
uint32_t DSCL_SC_MATRIX_C2C3; \
uint32_t ISHARP_MODE; \
+ uint32_t ISHARP_DELTA_LUT_MEM_PWR_CTRL; \
uint32_t ISHARP_NOISEDET_THRESHOLD; \
uint32_t ISHARP_NOISE_GAIN_PWL; \
uint32_t ISHARP_LBA_PWL_SEG0; \
diff --git a/drivers/gpu/drm/amd/display/dc/dpp/dcn401/dcn401_dpp_dscl.c b/drivers/gpu/drm/amd/display/dc/dpp/dcn401/dcn401_dpp_dscl.c
index 6df3419f825f..a62c4733ed3b 100644
--- a/drivers/gpu/drm/amd/display/dc/dpp/dcn401/dcn401_dpp_dscl.c
+++ b/drivers/gpu/drm/amd/display/dc/dpp/dcn401/dcn401_dpp_dscl.c
@@ -966,62 +966,57 @@ static void dpp401_dscl_program_isharp(struct dpp *dpp_base,
ISHARP_FMT_NORM, scl_data->dscl_prog_data.isharp_fmt.norm);
/* Skip remaining register programming if ISHARP is disabled */
- if (!scl_data->dscl_prog_data.isharp_en) {
- PERF_TRACE();
- return;
- }
-
- /* ISHARP_NOISEDET_THRESHOLD */
- REG_SET_2(ISHARP_NOISEDET_THRESHOLD, 0,
- ISHARP_NOISEDET_UTHRE, scl_data->dscl_prog_data.isharp_noise_det.uthreshold,
- ISHARP_NOISEDET_DTHRE, scl_data->dscl_prog_data.isharp_noise_det.dthreshold);
-
- /* ISHARP_NOISE_GAIN_PWL */
- REG_SET_3(ISHARP_NOISE_GAIN_PWL, 0,
- ISHARP_NOISEDET_PWL_START_IN, scl_data->dscl_prog_data.isharp_noise_det.pwl_start_in,
- ISHARP_NOISEDET_PWL_END_IN, scl_data->dscl_prog_data.isharp_noise_det.pwl_end_in,
- ISHARP_NOISEDET_PWL_SLOPE, scl_data->dscl_prog_data.isharp_noise_det.pwl_slope);
-
- /* ISHARP_LBA: IN_SEG, BASE_SEG, SLOPE_SEG */
- REG_SET_3(ISHARP_LBA_PWL_SEG0, 0,
- ISHARP_LBA_PWL_IN_SEG0, scl_data->dscl_prog_data.isharp_lba.in_seg[0],
- ISHARP_LBA_PWL_BASE_SEG0, scl_data->dscl_prog_data.isharp_lba.base_seg[0],
- ISHARP_LBA_PWL_SLOPE_SEG0, scl_data->dscl_prog_data.isharp_lba.slope_seg[0]);
- REG_SET_3(ISHARP_LBA_PWL_SEG1, 0,
- ISHARP_LBA_PWL_IN_SEG1, scl_data->dscl_prog_data.isharp_lba.in_seg[1],
- ISHARP_LBA_PWL_BASE_SEG1, scl_data->dscl_prog_data.isharp_lba.base_seg[1],
- ISHARP_LBA_PWL_SLOPE_SEG1, scl_data->dscl_prog_data.isharp_lba.slope_seg[1]);
- REG_SET_3(ISHARP_LBA_PWL_SEG2, 0,
- ISHARP_LBA_PWL_IN_SEG2, scl_data->dscl_prog_data.isharp_lba.in_seg[2],
- ISHARP_LBA_PWL_BASE_SEG2, scl_data->dscl_prog_data.isharp_lba.base_seg[2],
- ISHARP_LBA_PWL_SLOPE_SEG2, scl_data->dscl_prog_data.isharp_lba.slope_seg[2]);
- REG_SET_3(ISHARP_LBA_PWL_SEG3, 0,
- ISHARP_LBA_PWL_IN_SEG3, scl_data->dscl_prog_data.isharp_lba.in_seg[3],
- ISHARP_LBA_PWL_BASE_SEG3, scl_data->dscl_prog_data.isharp_lba.base_seg[3],
- ISHARP_LBA_PWL_SLOPE_SEG3, scl_data->dscl_prog_data.isharp_lba.slope_seg[3]);
- REG_SET_3(ISHARP_LBA_PWL_SEG4, 0,
- ISHARP_LBA_PWL_IN_SEG4, scl_data->dscl_prog_data.isharp_lba.in_seg[4],
- ISHARP_LBA_PWL_BASE_SEG4, scl_data->dscl_prog_data.isharp_lba.base_seg[4],
- ISHARP_LBA_PWL_SLOPE_SEG4, scl_data->dscl_prog_data.isharp_lba.slope_seg[4]);
- REG_SET_2(ISHARP_LBA_PWL_SEG5, 0,
- ISHARP_LBA_PWL_IN_SEG5, scl_data->dscl_prog_data.isharp_lba.in_seg[5],
- ISHARP_LBA_PWL_BASE_SEG5, scl_data->dscl_prog_data.isharp_lba.base_seg[5]);
-
- /* ISHARP_DELTA_LUT */
- if (!program_isharp_1dlut)
- dpp401_dscl_set_isharp_filter(dpp, scl_data->dscl_prog_data.isharp_delta);
+ if (scl_data->dscl_prog_data.isharp_en) {
+ /* ISHARP_NOISEDET_THRESHOLD */
+ REG_SET_2(ISHARP_NOISEDET_THRESHOLD, 0,
+ ISHARP_NOISEDET_UTHRE, scl_data->dscl_prog_data.isharp_noise_det.uthreshold,
+ ISHARP_NOISEDET_DTHRE, scl_data->dscl_prog_data.isharp_noise_det.dthreshold);
+
+ /* ISHARP_NOISE_GAIN_PWL */
+ REG_SET_3(ISHARP_NOISE_GAIN_PWL, 0,
+ ISHARP_NOISEDET_PWL_START_IN, scl_data->dscl_prog_data.isharp_noise_det.pwl_start_in,
+ ISHARP_NOISEDET_PWL_END_IN, scl_data->dscl_prog_data.isharp_noise_det.pwl_end_in,
+ ISHARP_NOISEDET_PWL_SLOPE, scl_data->dscl_prog_data.isharp_noise_det.pwl_slope);
+
+ /* ISHARP_LBA: IN_SEG, BASE_SEG, SLOPE_SEG */
+ REG_SET_3(ISHARP_LBA_PWL_SEG0, 0,
+ ISHARP_LBA_PWL_IN_SEG0, scl_data->dscl_prog_data.isharp_lba.in_seg[0],
+ ISHARP_LBA_PWL_BASE_SEG0, scl_data->dscl_prog_data.isharp_lba.base_seg[0],
+ ISHARP_LBA_PWL_SLOPE_SEG0, scl_data->dscl_prog_data.isharp_lba.slope_seg[0]);
+ REG_SET_3(ISHARP_LBA_PWL_SEG1, 0,
+ ISHARP_LBA_PWL_IN_SEG1, scl_data->dscl_prog_data.isharp_lba.in_seg[1],
+ ISHARP_LBA_PWL_BASE_SEG1, scl_data->dscl_prog_data.isharp_lba.base_seg[1],
+ ISHARP_LBA_PWL_SLOPE_SEG1, scl_data->dscl_prog_data.isharp_lba.slope_seg[1]);
+ REG_SET_3(ISHARP_LBA_PWL_SEG2, 0,
+ ISHARP_LBA_PWL_IN_SEG2, scl_data->dscl_prog_data.isharp_lba.in_seg[2],
+ ISHARP_LBA_PWL_BASE_SEG2, scl_data->dscl_prog_data.isharp_lba.base_seg[2],
+ ISHARP_LBA_PWL_SLOPE_SEG2, scl_data->dscl_prog_data.isharp_lba.slope_seg[2]);
+ REG_SET_3(ISHARP_LBA_PWL_SEG3, 0,
+ ISHARP_LBA_PWL_IN_SEG3, scl_data->dscl_prog_data.isharp_lba.in_seg[3],
+ ISHARP_LBA_PWL_BASE_SEG3, scl_data->dscl_prog_data.isharp_lba.base_seg[3],
+ ISHARP_LBA_PWL_SLOPE_SEG3, scl_data->dscl_prog_data.isharp_lba.slope_seg[3]);
+ REG_SET_3(ISHARP_LBA_PWL_SEG4, 0,
+ ISHARP_LBA_PWL_IN_SEG4, scl_data->dscl_prog_data.isharp_lba.in_seg[4],
+ ISHARP_LBA_PWL_BASE_SEG4, scl_data->dscl_prog_data.isharp_lba.base_seg[4],
+ ISHARP_LBA_PWL_SLOPE_SEG4, scl_data->dscl_prog_data.isharp_lba.slope_seg[4]);
+ REG_SET_2(ISHARP_LBA_PWL_SEG5, 0,
+ ISHARP_LBA_PWL_IN_SEG5, scl_data->dscl_prog_data.isharp_lba.in_seg[5],
+ ISHARP_LBA_PWL_BASE_SEG5, scl_data->dscl_prog_data.isharp_lba.base_seg[5]);
- /* ISHARP_NLDELTA_SOFT_CLIP */
- REG_SET_6(ISHARP_NLDELTA_SOFT_CLIP, 0,
- ISHARP_NLDELTA_SCLIP_EN_P, scl_data->dscl_prog_data.isharp_nldelta_sclip.enable_p,
- ISHARP_NLDELTA_SCLIP_PIVOT_P, scl_data->dscl_prog_data.isharp_nldelta_sclip.pivot_p,
- ISHARP_NLDELTA_SCLIP_SLOPE_P, scl_data->dscl_prog_data.isharp_nldelta_sclip.slope_p,
- ISHARP_NLDELTA_SCLIP_EN_N, scl_data->dscl_prog_data.isharp_nldelta_sclip.enable_n,
- ISHARP_NLDELTA_SCLIP_PIVOT_N, scl_data->dscl_prog_data.isharp_nldelta_sclip.pivot_n,
- ISHARP_NLDELTA_SCLIP_SLOPE_N, scl_data->dscl_prog_data.isharp_nldelta_sclip.slope_n);
+ /* ISHARP_DELTA_LUT */
+ if (!program_isharp_1dlut)
+ dpp401_dscl_set_isharp_filter(dpp, scl_data->dscl_prog_data.isharp_delta);
+
+ /* ISHARP_NLDELTA_SOFT_CLIP */
+ REG_SET_6(ISHARP_NLDELTA_SOFT_CLIP, 0,
+ ISHARP_NLDELTA_SCLIP_EN_P, scl_data->dscl_prog_data.isharp_nldelta_sclip.enable_p,
+ ISHARP_NLDELTA_SCLIP_PIVOT_P, scl_data->dscl_prog_data.isharp_nldelta_sclip.pivot_p,
+ ISHARP_NLDELTA_SCLIP_SLOPE_P, scl_data->dscl_prog_data.isharp_nldelta_sclip.slope_p,
+ ISHARP_NLDELTA_SCLIP_EN_N, scl_data->dscl_prog_data.isharp_nldelta_sclip.enable_n,
+ ISHARP_NLDELTA_SCLIP_PIVOT_N, scl_data->dscl_prog_data.isharp_nldelta_sclip.pivot_n,
+ ISHARP_NLDELTA_SCLIP_SLOPE_N, scl_data->dscl_prog_data.isharp_nldelta_sclip.slope_n);
/* Blur and Scale Coefficients - SCL_COEF_RAM_TAP_SELECT */
- if (scl_data->dscl_prog_data.isharp_en) {
if (scl_data->dscl_prog_data.filter_blur_scale_v) {
dpp401_dscl_set_scaler_filter(
dpp, scl_data->taps.v_taps,
@@ -1037,6 +1032,7 @@ static void dpp401_dscl_program_isharp(struct dpp *dpp_base,
*bs_coeffs_updated = true;
}
}
+
PERF_TRACE();
} // dpp401_dscl_program_isharp
/**
diff --git a/drivers/gpu/drm/amd/display/dc/dsc/dc_dsc.c b/drivers/gpu/drm/amd/display/dc/dsc/dc_dsc.c
index e4144b244332..5b3584ad5b6b 100644
--- a/drivers/gpu/drm/amd/display/dc/dsc/dc_dsc.c
+++ b/drivers/gpu/drm/amd/display/dc/dsc/dc_dsc.c
@@ -1157,7 +1157,7 @@ static bool setup_dsc_config(
if (!is_dsc_possible)
goto done;
- /* increase miniumum slice count to meet sink slice width limitations */
+ /* increase minimum slice count to meet sink slice width limitations */
min_slices_h = dc_fixpt_ceil(dc_fixpt_max(
dc_fixpt_div_int(dc_fixpt_from_int(pic_width), dsc_common_caps.max_slice_width), // sink min
dc_fixpt_from_int(min_slices_h))); // source min
diff --git a/drivers/gpu/drm/amd/display/dc/hubbub/dcn10/dcn10_hubbub.c b/drivers/gpu/drm/amd/display/dc/hubbub/dcn10/dcn10_hubbub.c
index 7847c1c4927b..97ef8281a476 100644
--- a/drivers/gpu/drm/amd/display/dc/hubbub/dcn10/dcn10_hubbub.c
+++ b/drivers/gpu/drm/amd/display/dc/hubbub/dcn10/dcn10_hubbub.c
@@ -944,3 +944,21 @@ void hubbub1_construct(struct hubbub *hubbub,
hubbub1->debug_test_index_pstate = 0xB;
}
+void dcn10_hubbub_global_timer_enable(struct hubbub *hubbub, bool enable, uint32_t refdiv)
+{
+ struct dcn10_hubbub *hubbub1 = TO_DCN10_HUBBUB(hubbub);
+
+ if (refdiv > 0)
+ REG_UPDATE(DCHUBBUB_GLOBAL_TIMER_CNTL, DCHUBBUB_GLOBAL_TIMER_REFDIV, refdiv);
+
+ REG_UPDATE(DCHUBBUB_GLOBAL_TIMER_CNTL, DCHUBBUB_GLOBAL_TIMER_ENABLE, enable ? 1 : 0);
+}
+
+void dcn10_hubbub_read_fb_aperture(struct hubbub *hubbub, uint32_t *fb_base_value, uint32_t *fb_offset_value)
+{
+ struct dcn10_hubbub *hubbub1 = TO_DCN10_HUBBUB(hubbub);
+
+ REG_GET(DCHUBBUB_SDPIF_FB_BASE, SDPIF_FB_BASE, fb_base_value);
+ REG_GET(DCHUBBUB_SDPIF_FB_OFFSET, SDPIF_FB_OFFSET, fb_offset_value);
+}
+
diff --git a/drivers/gpu/drm/amd/display/dc/hubbub/dcn10/dcn10_hubbub.h b/drivers/gpu/drm/amd/display/dc/hubbub/dcn10/dcn10_hubbub.h
index fa5c4c18ed59..990d3cd8e050 100644
--- a/drivers/gpu/drm/amd/display/dc/hubbub/dcn10/dcn10_hubbub.h
+++ b/drivers/gpu/drm/amd/display/dc/hubbub/dcn10/dcn10_hubbub.h
@@ -437,7 +437,9 @@ struct dcn_hubbub_registers {
type DCHUBBUB_ARB_REFCYC_PER_META_TRIP_A;\
type DCHUBBUB_ARB_REFCYC_PER_META_TRIP_B;\
type DCHUBBUB_ARB_FRAC_URG_BW_MALL_A;\
- type DCHUBBUB_ARB_FRAC_URG_BW_MALL_B
+ type DCHUBBUB_ARB_FRAC_URG_BW_MALL_B;\
+ type DCHUBBUB_ARB_ALLOW_DCFCLK_DEEP_SLEEP_FORCE_VALUE;\
+ type DCHUBBUB_ARB_ALLOW_DCFCLK_DEEP_SLEEP_FORCE_ENABLE
struct dcn_hubbub_shift {
DCN_HUBBUB_REG_FIELD_LIST(uint8_t);
@@ -447,6 +449,7 @@ struct dcn_hubbub_shift {
HUBBUB_REG_FIELD_LIST_DCN32(uint8_t);
HUBBUB_REG_FIELD_LIST_DCN35(uint8_t);
HUBBUB_REG_FIELD_LIST_DCN4_01(uint8_t);
+
};
struct dcn_hubbub_mask {
@@ -457,6 +460,7 @@ struct dcn_hubbub_mask {
HUBBUB_REG_FIELD_LIST_DCN32(uint32_t);
HUBBUB_REG_FIELD_LIST_DCN35(uint32_t);
HUBBUB_REG_FIELD_LIST_DCN4_01(uint32_t);
+
};
struct dc;
@@ -515,4 +519,8 @@ bool hubbub1_program_pstate_watermarks(
unsigned int refclk_mhz,
bool safe_to_lower);
+void dcn10_hubbub_global_timer_enable(struct hubbub *hubbub, bool enable, uint32_t refdiv);
+
+void dcn10_hubbub_read_fb_aperture(struct hubbub *hubbub, uint32_t *fb_base_value, uint32_t *fb_offset_value);
+
#endif
diff --git a/drivers/gpu/drm/amd/display/dc/hubp/dcn401/dcn401_hubp.c b/drivers/gpu/drm/amd/display/dc/hubp/dcn401/dcn401_hubp.c
index f01eae50d02f..c205500290ec 100644
--- a/drivers/gpu/drm/amd/display/dc/hubp/dcn401/dcn401_hubp.c
+++ b/drivers/gpu/drm/amd/display/dc/hubp/dcn401/dcn401_hubp.c
@@ -733,10 +733,8 @@ void hubp401_cursor_set_position(
const struct dc_cursor_mi_param *param)
{
struct dcn20_hubp *hubp2 = TO_DCN20_HUBP(hubp);
- int x_pos = pos->x - param->recout.x;
- int y_pos = pos->y - param->recout.y;
- int rec_x_offset = x_pos - pos->x_hotspot;
- int rec_y_offset = y_pos - pos->y_hotspot;
+ int rec_x_offset = pos->x - pos->x_hotspot;
+ int rec_y_offset = pos->y - pos->y_hotspot;
int dst_x_offset;
int x_pos_viewport = 0;
int x_hot_viewport = 0;
@@ -748,10 +746,10 @@ void hubp401_cursor_set_position(
* within preceeding ODM slices.
*/
if (param->recout.width) {
- x_pos_viewport = x_pos * param->viewport.width / param->recout.width;
+ x_pos_viewport = pos->x * param->viewport.width / param->recout.width;
x_hot_viewport = pos->x_hotspot * param->viewport.width / param->recout.width;
} else {
- ASSERT(!cur_en || x_pos == 0);
+ ASSERT(!cur_en || pos->x == 0);
ASSERT(!cur_en || pos->x_hotspot == 0);
}
@@ -790,8 +788,8 @@ void hubp401_cursor_set_position(
if (!hubp->cursor_offload) {
REG_SET_2(CURSOR_POSITION, 0,
- CURSOR_X_POSITION, x_pos,
- CURSOR_Y_POSITION, y_pos);
+ CURSOR_X_POSITION, pos->x,
+ CURSOR_Y_POSITION, pos->y);
REG_SET_2(CURSOR_HOT_SPOT, 0,
CURSOR_HOT_SPOT_X, pos->x_hotspot,
diff --git a/drivers/gpu/drm/amd/display/dc/hwss/dce110/dce110_hwseq.c b/drivers/gpu/drm/amd/display/dc/hwss/dce110/dce110_hwseq.c
index ebd74b43e935..4659e1b489ba 100644
--- a/drivers/gpu/drm/amd/display/dc/hwss/dce110/dce110_hwseq.c
+++ b/drivers/gpu/drm/amd/display/dc/hwss/dce110/dce110_hwseq.c
@@ -59,6 +59,7 @@
#include "dc_state_priv.h"
#include "dpcd_defs.h"
#include "dsc.h"
+#include "dc_dp_types.h"
/* include DCE11 register header files */
#include "dce/dce_11_0_d.h"
#include "dce/dce_11_0_sh_mask.h"
@@ -728,7 +729,6 @@ void dce110_edp_wait_for_hpd_ready(
{
struct dc_context *ctx = link->ctx;
struct graphics_object_id connector = link->link_enc->connector;
- struct gpio *hpd;
bool edp_hpd_high = false;
uint32_t time_elapsed = 0;
uint32_t timeout = power_up ?
@@ -752,31 +752,16 @@ void dce110_edp_wait_for_hpd_ready(
* we need to wait until SENSE bit is high/low.
*/
- /* obtain HPD */
- /* TODO what to do with this? */
- hpd = ctx->dc->link_srv->get_hpd_gpio(ctx->dc_bios, connector, ctx->gpio_service);
-
- if (!hpd) {
- BREAK_TO_DEBUGGER();
- return;
- }
-
if (link->panel_config.pps.extra_t3_ms > 0) {
int extra_t3_in_ms = link->panel_config.pps.extra_t3_ms;
msleep(extra_t3_in_ms);
}
- dal_gpio_open(hpd, GPIO_MODE_INTERRUPT);
-
/* wait until timeout or panel detected */
do {
- uint32_t detected = 0;
-
- dal_gpio_get_value(hpd, &detected);
-
- if (!(detected ^ power_up)) {
+ if (!(link->dc->link_srv->get_hpd_state(link) ^ power_up)) {
edp_hpd_high = true;
break;
}
@@ -786,10 +771,6 @@ void dce110_edp_wait_for_hpd_ready(
time_elapsed += HPD_CHECK_INTERVAL;
} while (time_elapsed < timeout);
- dal_gpio_close(hpd);
-
- dal_gpio_destroy_irq(&hpd);
-
/* ensure that the panel is detected */
if (!edp_hpd_high)
DC_LOG_DC("%s: wait timed out!\n", __func__);
@@ -1779,20 +1760,25 @@ static void power_down_encoders(struct dc *dc)
int i;
for (i = 0; i < dc->link_count; i++) {
- enum signal_type signal = dc->links[i]->connector_signal;
-
- dc->link_srv->blank_dp_stream(dc->links[i], false);
+ struct dc_link *link = dc->links[i];
+ struct link_encoder *link_enc = link->link_enc;
+ enum signal_type signal = link->connector_signal;
+ dc->link_srv->blank_dp_stream(link, false);
if (signal != SIGNAL_TYPE_EDP)
signal = SIGNAL_TYPE_NONE;
- if (dc->links[i]->ep_type == DISPLAY_ENDPOINT_PHY)
- dc->links[i]->link_enc->funcs->disable_output(
- dc->links[i]->link_enc, signal);
+ if (link->ep_type == DISPLAY_ENDPOINT_PHY)
+ link_enc->funcs->disable_output(link_enc, signal);
- dc->links[i]->link_status.link_active = false;
- memset(&dc->links[i]->cur_link_settings, 0,
- sizeof(dc->links[i]->cur_link_settings));
+ if (link->fec_state == dc_link_fec_enabled) {
+ link_enc->funcs->fec_set_enable(link_enc, false);
+ link_enc->funcs->fec_set_ready(link_enc, false);
+ link->fec_state = dc_link_fec_not_ready;
+ }
+
+ link->link_status.link_active = false;
+ memset(&link->cur_link_settings, 0, sizeof(link->cur_link_settings));
}
}
@@ -1840,6 +1826,9 @@ static void disable_vga_and_power_gate_all_controllers(
struct timing_generator *tg;
struct dc_context *ctx = dc->ctx;
+ if (dc->caps.ips_support)
+ return;
+
for (i = 0; i < dc->res_pool->timing_generator_count; i++) {
tg = dc->res_pool->timing_generators[i];
@@ -1916,13 +1905,16 @@ static void clean_up_dsc_blocks(struct dc *dc)
/* disable DSC in OPTC */
if (i < dc->res_pool->timing_generator_count) {
tg = dc->res_pool->timing_generators[i];
- tg->funcs->set_dsc_config(tg, OPTC_DSC_DISABLED, 0, 0);
+ if (tg->funcs->set_dsc_config)
+ tg->funcs->set_dsc_config(tg, OPTC_DSC_DISABLED, 0, 0);
}
/* disable DSC in stream encoder */
if (i < dc->res_pool->stream_enc_count) {
se = dc->res_pool->stream_enc[i];
- se->funcs->dp_set_dsc_config(se, OPTC_DSC_DISABLED, 0, 0);
- se->funcs->dp_set_dsc_pps_info_packet(se, false, NULL, true);
+ if (se->funcs->dp_set_dsc_config)
+ se->funcs->dp_set_dsc_config(se, OPTC_DSC_DISABLED, 0, 0);
+ if (se->funcs->dp_set_dsc_pps_info_packet)
+ se->funcs->dp_set_dsc_pps_info_packet(se, false, NULL, true);
}
/* disable DSC block */
if (dccg->funcs->set_ref_dscclk)
diff --git a/drivers/gpu/drm/amd/display/dc/hwss/dcn10/dcn10_hwseq.c b/drivers/gpu/drm/amd/display/dc/hwss/dcn10/dcn10_hwseq.c
index fa62e40a9858..c1586364ecd4 100644
--- a/drivers/gpu/drm/amd/display/dc/hwss/dcn10/dcn10_hwseq.c
+++ b/drivers/gpu/drm/amd/display/dc/hwss/dcn10/dcn10_hwseq.c
@@ -2678,8 +2678,7 @@ static void mmhub_read_vm_context0_settings(struct dcn10_hubp *hubp1,
uint32_t fb_base_value;
uint32_t fb_offset_value;
- REG_GET(DCHUBBUB_SDPIF_FB_BASE, SDPIF_FB_BASE, &fb_base_value);
- REG_GET(DCHUBBUB_SDPIF_FB_OFFSET, SDPIF_FB_OFFSET, &fb_offset_value);
+ dcn10_hubbub_read_fb_aperture(hws->ctx->dc->res_pool->hubbub, &fb_base_value, &fb_offset_value);
REG_GET(VM_CONTEXT0_PAGE_TABLE_BASE_ADDR_HI32,
PAGE_DIRECTORY_ENTRY_HI32, &vm0->pte_base.high_part);
@@ -3474,7 +3473,7 @@ void dcn10_set_static_screen_control(struct pipe_ctx **pipe_ctx,
triggers, params->num_frames);
}
-static void dcn10_config_stereo_parameters(
+void dcn10_config_stereo_parameters(
struct dc_stream_state *stream, struct crtc_stereo_flags *flags)
{
enum view_3d_format view_format = stream->view_format;
@@ -3666,7 +3665,11 @@ void dcn10_set_cursor_position(struct pipe_ctx *pipe_ctx)
int y_plane = pipe_ctx->plane_state->dst_rect.y;
int x_pos = pos_cpy.x;
int y_pos = pos_cpy.y;
- int clip_x = pipe_ctx->plane_state->clip_rect.x;
+ bool is_primary_plane = (pipe_ctx->plane_state->layer_index == 0);
+
+ int clip_x = (pos_cpy.use_viewport_for_clip && is_primary_plane &&
+ !odm_combine_on && !pipe_split_on && param.viewport.x != 0)
+ ? param.viewport.x : pipe_ctx->plane_state->clip_rect.x;
int clip_width = pipe_ctx->plane_state->clip_rect.width;
if ((pipe_ctx->top_pipe != NULL) || (pipe_ctx->bottom_pipe != NULL)) {
diff --git a/drivers/gpu/drm/amd/display/dc/hwss/dcn10/dcn10_hwseq.h b/drivers/gpu/drm/amd/display/dc/hwss/dcn10/dcn10_hwseq.h
index 57d30ea225f2..476095c5dd0c 100644
--- a/drivers/gpu/drm/amd/display/dc/hwss/dcn10/dcn10_hwseq.h
+++ b/drivers/gpu/drm/amd/display/dc/hwss/dcn10/dcn10_hwseq.h
@@ -217,5 +217,7 @@ void dcn10_update_visual_confirm_color(
void dcn10_reset_surface_dcc_and_tiling(struct pipe_ctx *pipe_ctx,
struct dc_plane_state *plane_state,
bool clear_tiling);
+void dcn10_config_stereo_parameters(
+ struct dc_stream_state *stream, struct crtc_stereo_flags *flags);
#endif /* __DC_HWSS_DCN10_H__ */
diff --git a/drivers/gpu/drm/amd/display/dc/hwss/dcn20/dcn20_hwseq.c b/drivers/gpu/drm/amd/display/dc/hwss/dcn20/dcn20_hwseq.c
index c8ff8ae85a03..a76436dcbe40 100644
--- a/drivers/gpu/drm/amd/display/dc/hwss/dcn20/dcn20_hwseq.c
+++ b/drivers/gpu/drm/amd/display/dc/hwss/dcn20/dcn20_hwseq.c
@@ -46,6 +46,7 @@
#include "dchubbub.h"
#include "reg_helper.h"
#include "dcn10/dcn10_cm_common.h"
+#include "dcn10/dcn10_hubbub.h"
#include "vm_helper.h"
#include "dccg.h"
#include "dc_dmub_srv.h"
@@ -3058,9 +3059,17 @@ void dcn20_enable_stream(struct pipe_ctx *pipe_ctx)
dccg->funcs->enable_symclk32_se(dccg, dp_hpo_inst, phyd32clk);
}
} else {
- if (dccg->funcs->enable_symclk_se)
- dccg->funcs->enable_symclk_se(dccg, stream_enc->stream_enc_inst,
+ if (dccg->funcs->enable_symclk_se && link_enc) {
+ if (link->ep_type == DISPLAY_ENDPOINT_USB4_DPIA
+ && link->cur_link_settings.link_rate == LINK_RATE_UNKNOWN
+ && !link->link_status.link_active) {
+ if (dccg->funcs->disable_symclk_se)
+ dccg->funcs->disable_symclk_se(dccg, stream_enc->stream_enc_inst,
link_enc->transmitter - TRANSMITTER_UNIPHY_A);
+ } else
+ dccg->funcs->enable_symclk_se(dccg, stream_enc->stream_enc_inst,
+ link_enc->transmitter - TRANSMITTER_UNIPHY_A);
+ }
}
if (dc->res_pool->dccg->funcs->set_pixel_rate_div)
@@ -3145,10 +3154,7 @@ void dcn20_fpga_init_hw(struct dc *dc)
REG_WRITE(RBBMIF_TIMEOUT_DIS, 0xFFFFFFFF);
REG_WRITE(RBBMIF_TIMEOUT_DIS_2, 0xFFFFFFFF);
- hws->funcs.dccg_init(hws);
-
- REG_UPDATE(DCHUBBUB_GLOBAL_TIMER_CNTL, DCHUBBUB_GLOBAL_TIMER_REFDIV, 2);
- REG_UPDATE(DCHUBBUB_GLOBAL_TIMER_CNTL, DCHUBBUB_GLOBAL_TIMER_ENABLE, 1);
+ dcn10_hubbub_global_timer_enable(dc->res_pool->hubbub, true, 2);
if (REG(REFCLK_CNTL))
REG_WRITE(REFCLK_CNTL, 0);
//
diff --git a/drivers/gpu/drm/amd/display/dc/hwss/dcn201/dcn201_hwseq.c b/drivers/gpu/drm/amd/display/dc/hwss/dcn201/dcn201_hwseq.c
index 1635e5a552ad..482053c4ad22 100644
--- a/drivers/gpu/drm/amd/display/dc/hwss/dcn201/dcn201_hwseq.c
+++ b/drivers/gpu/drm/amd/display/dc/hwss/dcn201/dcn201_hwseq.c
@@ -39,6 +39,7 @@
#include "dccg.h"
#include "clk_mgr.h"
#include "reg_helper.h"
+#include "dcn10/dcn10_hubbub.h"
#define CTX \
hws->ctx
diff --git a/drivers/gpu/drm/amd/display/dc/hwss/dcn30/dcn30_hwseq.c b/drivers/gpu/drm/amd/display/dc/hwss/dcn30/dcn30_hwseq.c
index f2d4cd527874..9b95f5883925 100644
--- a/drivers/gpu/drm/amd/display/dc/hwss/dcn30/dcn30_hwseq.c
+++ b/drivers/gpu/drm/amd/display/dc/hwss/dcn30/dcn30_hwseq.c
@@ -36,6 +36,7 @@
#include "dcn10/dcn10_cm_common.h"
#include "dcn30/dcn30_cm_common.h"
#include "reg_helper.h"
+#include "dcn10/dcn10_hubbub.h"
#include "abm.h"
#include "clk_mgr.h"
#include "hubp.h"
diff --git a/drivers/gpu/drm/amd/display/dc/hwss/dcn30/dcn30_init.c b/drivers/gpu/drm/amd/display/dc/hwss/dcn30/dcn30_init.c
index d7ff55669bac..5cbae0cdda96 100644
--- a/drivers/gpu/drm/amd/display/dc/hwss/dcn30/dcn30_init.c
+++ b/drivers/gpu/drm/amd/display/dc/hwss/dcn30/dcn30_init.c
@@ -143,7 +143,6 @@ static const struct hwseq_private_funcs dcn30_private_funcs = {
.set_hdr_multiplier = dcn10_set_hdr_multiplier,
.verify_allow_pstate_change_high = dcn10_verify_allow_pstate_change_high,
.wait_for_blank_complete = dcn20_wait_for_blank_complete,
- .dccg_init = dcn20_dccg_init,
.set_blend_lut = dcn30_set_blend_lut,
.set_shaper_3dlut = dcn20_set_shaper_3dlut,
};
diff --git a/drivers/gpu/drm/amd/display/dc/hwss/dcn301/dcn301_init.c b/drivers/gpu/drm/amd/display/dc/hwss/dcn301/dcn301_init.c
index 8d7ceb7b32b8..33cc48cd0196 100644
--- a/drivers/gpu/drm/amd/display/dc/hwss/dcn301/dcn301_init.c
+++ b/drivers/gpu/drm/amd/display/dc/hwss/dcn301/dcn301_init.c
@@ -140,7 +140,6 @@ static const struct hwseq_private_funcs dcn301_private_funcs = {
.set_hdr_multiplier = dcn10_set_hdr_multiplier,
.verify_allow_pstate_change_high = dcn10_verify_allow_pstate_change_high,
.wait_for_blank_complete = dcn20_wait_for_blank_complete,
- .dccg_init = dcn20_dccg_init,
.set_blend_lut = dcn30_set_blend_lut,
.set_shaper_3dlut = dcn20_set_shaper_3dlut,
};
diff --git a/drivers/gpu/drm/amd/display/dc/hwss/dcn31/dcn31_hwseq.c b/drivers/gpu/drm/amd/display/dc/hwss/dcn31/dcn31_hwseq.c
index d1ecdb92b072..2adbcc105aa6 100644
--- a/drivers/gpu/drm/amd/display/dc/hwss/dcn31/dcn31_hwseq.c
+++ b/drivers/gpu/drm/amd/display/dc/hwss/dcn31/dcn31_hwseq.c
@@ -32,6 +32,7 @@
#include "dce/dce_hwseq.h"
#include "clk_mgr.h"
#include "reg_helper.h"
+#include "dcn10/dcn10_hubbub.h"
#include "abm.h"
#include "hubp.h"
#include "dchubbub.h"
@@ -546,8 +547,22 @@ static void dcn31_reset_back_end_for_pipe(
if (pipe_ctx->stream_res.tg->funcs->set_odm_bypass)
pipe_ctx->stream_res.tg->funcs->set_odm_bypass(
pipe_ctx->stream_res.tg, &pipe_ctx->stream->timing);
+ /*
+ * TODO - convert symclk_ref_cnts for otg to a bit map to solve
+ * the case where the same symclk is shared across multiple otg
+ * instances
+ */
if (dc_is_hdmi_tmds_signal(pipe_ctx->stream->signal))
- pipe_ctx->stream->link->phy_state.symclk_ref_cnts.otg = 0;
+ link->phy_state.symclk_ref_cnts.otg = 0;
+
+ if (pipe_ctx->top_pipe == NULL) {
+ if (link->phy_state.symclk_state == SYMCLK_ON_TX_OFF) {
+ const struct link_hwss *link_hwss = get_link_hwss(link, &pipe_ctx->link_res);
+
+ link_hwss->disable_link_output(link, &pipe_ctx->link_res, pipe_ctx->stream->signal);
+ link->phy_state.symclk_state = SYMCLK_OFF_TX_OFF;
+ }
+ }
set_drr_and_clear_adjust_pending(pipe_ctx, pipe_ctx->stream, NULL);
diff --git a/drivers/gpu/drm/amd/display/dc/hwss/dcn31/dcn31_init.c b/drivers/gpu/drm/amd/display/dc/hwss/dcn31/dcn31_init.c
index 5a6a459da224..e56b9a46aecf 100644
--- a/drivers/gpu/drm/amd/display/dc/hwss/dcn31/dcn31_init.c
+++ b/drivers/gpu/drm/amd/display/dc/hwss/dcn31/dcn31_init.c
@@ -144,7 +144,6 @@ static const struct hwseq_private_funcs dcn31_private_funcs = {
.set_hdr_multiplier = dcn10_set_hdr_multiplier,
.verify_allow_pstate_change_high = dcn10_verify_allow_pstate_change_high,
.wait_for_blank_complete = dcn20_wait_for_blank_complete,
- .dccg_init = dcn20_dccg_init,
.set_blend_lut = dcn30_set_blend_lut,
.set_shaper_3dlut = dcn20_set_shaper_3dlut,
.setup_hpo_hw_control = dcn31_setup_hpo_hw_control,
diff --git a/drivers/gpu/drm/amd/display/dc/hwss/dcn314/dcn314_hwseq.c b/drivers/gpu/drm/amd/display/dc/hwss/dcn314/dcn314_hwseq.c
index 4ee6ed610de0..3e239124c17d 100644
--- a/drivers/gpu/drm/amd/display/dc/hwss/dcn314/dcn314_hwseq.c
+++ b/drivers/gpu/drm/amd/display/dc/hwss/dcn314/dcn314_hwseq.c
@@ -108,7 +108,7 @@ static void update_dsc_on_stream(struct pipe_ctx *pipe_ctx, bool enable)
dsc_cfg.dc_dsc_cfg = stream->timing.dsc_cfg;
ASSERT(dsc_cfg.dc_dsc_cfg.num_slices_h % opp_cnt == 0);
dsc_cfg.dc_dsc_cfg.num_slices_h /= opp_cnt;
- dsc_cfg.dsc_padding = pipe_ctx->dsc_padding_params.dsc_hactive_padding;
+ dsc_cfg.dsc_padding = 0;
dsc->funcs->dsc_set_config(dsc, &dsc_cfg, &dsc_optc_cfg);
dsc->funcs->dsc_enable(dsc, pipe_ctx->stream_res.opp->inst);
diff --git a/drivers/gpu/drm/amd/display/dc/hwss/dcn314/dcn314_init.c b/drivers/gpu/drm/amd/display/dc/hwss/dcn314/dcn314_init.c
index 79faab1125d4..9900c87b4567 100644
--- a/drivers/gpu/drm/amd/display/dc/hwss/dcn314/dcn314_init.c
+++ b/drivers/gpu/drm/amd/display/dc/hwss/dcn314/dcn314_init.c
@@ -149,7 +149,6 @@ static const struct hwseq_private_funcs dcn314_private_funcs = {
.set_hdr_multiplier = dcn10_set_hdr_multiplier,
.verify_allow_pstate_change_high = dcn10_verify_allow_pstate_change_high,
.wait_for_blank_complete = dcn20_wait_for_blank_complete,
- .dccg_init = dcn20_dccg_init,
.set_blend_lut = dcn30_set_blend_lut,
.set_shaper_3dlut = dcn20_set_shaper_3dlut,
.setup_hpo_hw_control = dcn31_setup_hpo_hw_control,
diff --git a/drivers/gpu/drm/amd/display/dc/hwss/dcn32/dcn32_hwseq.c b/drivers/gpu/drm/amd/display/dc/hwss/dcn32/dcn32_hwseq.c
index be1f3caf4096..518794fad9e1 100644
--- a/drivers/gpu/drm/amd/display/dc/hwss/dcn32/dcn32_hwseq.c
+++ b/drivers/gpu/drm/amd/display/dc/hwss/dcn32/dcn32_hwseq.c
@@ -82,6 +82,9 @@ void dcn32_dsc_pg_control(
if (!dc->debug.enable_double_buffered_dsc_pg_support)
return;
+ if (dc->debug.ignore_pg)
+ return;
+
REG_GET(DC_IP_REQUEST_CNTL, IP_REQUEST_EN, &org_ip_request_cntl);
if (org_ip_request_cntl == 0)
REG_SET(DC_IP_REQUEST_CNTL, 0, IP_REQUEST_EN, 1);
@@ -168,6 +171,9 @@ void dcn32_hubp_pg_control(struct dce_hwseq *hws, unsigned int hubp_inst, bool p
if (hws->ctx->dc->debug.disable_hubp_power_gate)
return;
+ if (hws->ctx->dc->debug.ignore_pg)
+ return;
+
if (REG(DOMAIN0_PG_CONFIG) == 0)
return;
@@ -1063,7 +1069,7 @@ void dcn32_update_dsc_on_stream(struct pipe_ctx *pipe_ctx, bool enable)
dsc_cfg.dc_dsc_cfg = stream->timing.dsc_cfg;
ASSERT(dsc_cfg.dc_dsc_cfg.num_slices_h % opp_cnt == 0);
dsc_cfg.dc_dsc_cfg.num_slices_h /= opp_cnt;
- dsc_cfg.dsc_padding = pipe_ctx->dsc_padding_params.dsc_hactive_padding;
+ dsc_cfg.dsc_padding = 0;
if (should_use_dto_dscclk)
dccg->funcs->set_dto_dscclk(dccg, dsc->inst, dsc_cfg.dc_dsc_cfg.num_slices_h);
diff --git a/drivers/gpu/drm/amd/display/dc/hwss/dcn32/dcn32_init.c b/drivers/gpu/drm/amd/display/dc/hwss/dcn32/dcn32_init.c
index c19ef075c882..849dae18b738 100644
--- a/drivers/gpu/drm/amd/display/dc/hwss/dcn32/dcn32_init.c
+++ b/drivers/gpu/drm/amd/display/dc/hwss/dcn32/dcn32_init.c
@@ -154,7 +154,6 @@ static const struct hwseq_private_funcs dcn32_private_funcs = {
.set_hdr_multiplier = dcn10_set_hdr_multiplier,
.verify_allow_pstate_change_high = dcn10_verify_allow_pstate_change_high,
.wait_for_blank_complete = dcn20_wait_for_blank_complete,
- .dccg_init = dcn20_dccg_init,
.set_mcm_luts = dcn32_set_mcm_luts,
.program_mall_pipe_config = dcn32_program_mall_pipe_config,
.update_force_pstate = dcn32_update_force_pstate,
diff --git a/drivers/gpu/drm/amd/display/dc/hwss/dcn35/dcn35_hwseq.c b/drivers/gpu/drm/amd/display/dc/hwss/dcn35/dcn35_hwseq.c
index 7aa0f452e8f7..f7e16fee7594 100644
--- a/drivers/gpu/drm/amd/display/dc/hwss/dcn35/dcn35_hwseq.c
+++ b/drivers/gpu/drm/amd/display/dc/hwss/dcn35/dcn35_hwseq.c
@@ -32,6 +32,7 @@
#include "dce/dce_hwseq.h"
#include "clk_mgr.h"
#include "reg_helper.h"
+#include "dcn10/dcn10_hubbub.h"
#include "abm.h"
#include "hubp.h"
#include "dchubbub.h"
@@ -364,7 +365,7 @@ static void update_dsc_on_stream(struct pipe_ctx *pipe_ctx, bool enable)
dsc_cfg.dc_dsc_cfg = stream->timing.dsc_cfg;
ASSERT(dsc_cfg.dc_dsc_cfg.num_slices_h % opp_cnt == 0);
dsc_cfg.dc_dsc_cfg.num_slices_h /= opp_cnt;
- dsc_cfg.dsc_padding = pipe_ctx->dsc_padding_params.dsc_hactive_padding;
+ dsc_cfg.dsc_padding = 0;
dsc->funcs->dsc_set_config(dsc, &dsc_cfg, &dsc_optc_cfg);
dsc->funcs->dsc_enable(dsc, pipe_ctx->stream_res.opp->inst);
@@ -1631,6 +1632,7 @@ void dcn35_begin_cursor_offload_update(struct dc *dc, const struct pipe_ctx *pip
payload_idx = write_idx % ARRAY_SIZE(cs->offload_streams[stream_idx].payloads);
cs->offload_streams[stream_idx].payloads[payload_idx].write_idx_start = write_idx;
+ cs->offload_streams[stream_idx].payloads[payload_idx].pipe_mask = 0;
if (pipe->plane_res.hubp)
pipe->plane_res.hubp->cursor_offload = true;
@@ -1726,3 +1728,55 @@ void dcn35_program_cursor_offload_now(struct dc *dc, const struct pipe_ctx *pipe
{
dc_dmub_srv_program_cursor_now(dc, pipe);
}
+
+static void disable_link_output_symclk_on_tx_off(struct dc_link *link, enum dp_link_encoding link_encoding)
+{
+ struct dc *dc = link->ctx->dc;
+ struct pipe_ctx *pipe_ctx = NULL;
+ uint8_t i;
+
+ for (i = 0; i < MAX_PIPES; i++) {
+ pipe_ctx = &dc->current_state->res_ctx.pipe_ctx[i];
+ if (pipe_ctx->stream && pipe_ctx->stream->link == link && pipe_ctx->top_pipe == NULL) {
+ pipe_ctx->clock_source->funcs->program_pix_clk(
+ pipe_ctx->clock_source,
+ &pipe_ctx->stream_res.pix_clk_params,
+ link_encoding,
+ &pipe_ctx->pll_settings);
+ break;
+ }
+ }
+}
+
+void dcn35_disable_link_output(struct dc_link *link,
+ const struct link_resource *link_res,
+ enum signal_type signal)
+{
+ struct dc *dc = link->ctx->dc;
+ const struct link_hwss *link_hwss = get_link_hwss(link, link_res);
+ struct dmcu *dmcu = dc->res_pool->dmcu;
+
+ if (signal == SIGNAL_TYPE_EDP &&
+ link->dc->hwss.edp_backlight_control &&
+ !link->skip_implict_edp_power_control)
+ link->dc->hwss.edp_backlight_control(link, false);
+ else if (dmcu != NULL && dmcu->funcs->lock_phy)
+ dmcu->funcs->lock_phy(dmcu);
+
+ if (dc_is_tmds_signal(signal) && link->phy_state.symclk_ref_cnts.otg > 0) {
+ disable_link_output_symclk_on_tx_off(link, DP_UNKNOWN_ENCODING);
+ link->phy_state.symclk_state = SYMCLK_ON_TX_OFF;
+ } else {
+ link_hwss->disable_link_output(link, link_res, signal);
+ link->phy_state.symclk_state = SYMCLK_OFF_TX_OFF;
+ }
+ /*
+ * Add the logic to extract BOTH power up and power down sequences
+ * from enable/disable link output and only call edp panel control
+ * in enable_link_dp and disable_link_dp once.
+ */
+ if (dmcu != NULL && dmcu->funcs->unlock_phy)
+ dmcu->funcs->unlock_phy(dmcu);
+
+ dc->link_srv->dp_trace_source_sequence(link, DPCD_SOURCE_SEQ_AFTER_DISABLE_LINK_PHY);
+}
diff --git a/drivers/gpu/drm/amd/display/dc/hwss/dcn35/dcn35_hwseq.h b/drivers/gpu/drm/amd/display/dc/hwss/dcn35/dcn35_hwseq.h
index 1ff41dba556c..e3459546a908 100644
--- a/drivers/gpu/drm/amd/display/dc/hwss/dcn35/dcn35_hwseq.h
+++ b/drivers/gpu/drm/amd/display/dc/hwss/dcn35/dcn35_hwseq.h
@@ -108,5 +108,8 @@ void dcn35_update_cursor_offload_pipe(struct dc *dc, const struct pipe_ctx *pipe
void dcn35_notify_cursor_offload_drr_update(struct dc *dc, struct dc_state *context,
const struct dc_stream_state *stream);
void dcn35_program_cursor_offload_now(struct dc *dc, const struct pipe_ctx *pipe);
+void dcn35_disable_link_output(struct dc_link *link,
+ const struct link_resource *link_res,
+ enum signal_type signal);
#endif /* __DC_HWSS_DCN35_H__ */
diff --git a/drivers/gpu/drm/amd/display/dc/hwss/dcn35/dcn35_init.c b/drivers/gpu/drm/amd/display/dc/hwss/dcn35/dcn35_init.c
index 5a66c9db2670..6ac8ad97cf13 100644
--- a/drivers/gpu/drm/amd/display/dc/hwss/dcn35/dcn35_init.c
+++ b/drivers/gpu/drm/amd/display/dc/hwss/dcn35/dcn35_init.c
@@ -113,7 +113,7 @@ static const struct hw_sequencer_funcs dcn35_funcs = {
.enable_lvds_link_output = dce110_enable_lvds_link_output,
.enable_tmds_link_output = dce110_enable_tmds_link_output,
.enable_dp_link_output = dce110_enable_dp_link_output,
- .disable_link_output = dcn32_disable_link_output,
+ .disable_link_output = dcn35_disable_link_output,
.z10_restore = dcn35_z10_restore,
.z10_save_init = dcn31_z10_save_init,
.set_disp_pattern_generator = dcn30_set_disp_pattern_generator,
@@ -164,7 +164,6 @@ static const struct hwseq_private_funcs dcn35_private_funcs = {
.set_hdr_multiplier = dcn10_set_hdr_multiplier,
.verify_allow_pstate_change_high = dcn10_verify_allow_pstate_change_high,
.wait_for_blank_complete = dcn20_wait_for_blank_complete,
- .dccg_init = dcn20_dccg_init,
.set_mcm_luts = dcn32_set_mcm_luts,
.setup_hpo_hw_control = dcn35_setup_hpo_hw_control,
.calculate_dccg_k1_k2_values = dcn32_calculate_dccg_k1_k2_values,
diff --git a/drivers/gpu/drm/amd/display/dc/hwss/dcn351/dcn351_init.c b/drivers/gpu/drm/amd/display/dc/hwss/dcn351/dcn351_init.c
index 09e60158f0b5..04c260015eec 100644
--- a/drivers/gpu/drm/amd/display/dc/hwss/dcn351/dcn351_init.c
+++ b/drivers/gpu/drm/amd/display/dc/hwss/dcn351/dcn351_init.c
@@ -153,7 +153,6 @@ static const struct hwseq_private_funcs dcn351_private_funcs = {
.set_hdr_multiplier = dcn10_set_hdr_multiplier,
.verify_allow_pstate_change_high = dcn10_verify_allow_pstate_change_high,
.wait_for_blank_complete = dcn20_wait_for_blank_complete,
- .dccg_init = dcn20_dccg_init,
.set_mcm_luts = dcn32_set_mcm_luts,
.setup_hpo_hw_control = dcn35_setup_hpo_hw_control,
.calculate_dccg_k1_k2_values = dcn32_calculate_dccg_k1_k2_values,
diff --git a/drivers/gpu/drm/amd/display/dc/hwss/dcn401/dcn401_hwseq.c b/drivers/gpu/drm/amd/display/dc/hwss/dcn401/dcn401_hwseq.c
index 5eda7648d0d2..39b6f6d2d7c1 100644
--- a/drivers/gpu/drm/amd/display/dc/hwss/dcn401/dcn401_hwseq.c
+++ b/drivers/gpu/drm/amd/display/dc/hwss/dcn401/dcn401_hwseq.c
@@ -287,6 +287,8 @@ void dcn401_init_hw(struct dc *dc)
for (i = 0; i < dc->link_count; i++) {
struct dc_link *link = dc->links[i];
+ if (link->ep_type != DISPLAY_ENDPOINT_PHY)
+ continue;
if (link->link_enc->funcs->is_dig_enabled &&
link->link_enc->funcs->is_dig_enabled(link->link_enc) &&
hws->funcs.power_down) {
@@ -297,7 +299,6 @@ void dcn401_init_hw(struct dc *dc)
}
}
}
-
for (i = 0; i < res_pool->audio_count; i++) {
struct audio *audio = res_pool->audios[i];
@@ -917,10 +918,10 @@ static void dcn401_enable_stream_calc(
pipe_ctx->stream->link->cur_link_settings.lane_count;
uint32_t active_total_with_borders;
- if (dc->link_srv->dp_is_128b_132b_signal(pipe_ctx))
+ if (dc->link_srv->dp_is_128b_132b_signal(pipe_ctx)) {
*dp_hpo_inst = pipe_ctx->stream_res.hpo_dp_stream_enc->inst;
-
- *phyd32clk = get_phyd32clk_src(pipe_ctx->stream->link);
+ *phyd32clk = get_phyd32clk_src(pipe_ctx->stream->link);
+ }
if (dc_is_tmds_signal(pipe_ctx->stream->signal))
dcn401_calculate_dccg_tmds_div_value(pipe_ctx, tmds_div);
@@ -949,7 +950,7 @@ void dcn401_enable_stream(struct pipe_ctx *pipe_ctx)
const struct link_hwss *link_hwss = get_link_hwss(link, &pipe_ctx->link_res);
struct dc *dc = pipe_ctx->stream->ctx->dc;
struct dccg *dccg = dc->res_pool->dccg;
- enum phyd32clk_clock_source phyd32clk;
+ enum phyd32clk_clock_source phyd32clk = PHYD32CLKA;
int dp_hpo_inst = 0;
unsigned int tmds_div = PIXEL_RATE_DIV_NA;
unsigned int unused_div = PIXEL_RATE_DIV_NA;
@@ -1215,6 +1216,9 @@ void dcn401_set_cursor_position(struct pipe_ctx *pipe_ctx)
if (recout_y_pos + (int)hubp->curs_attr.height <= 0)
pos_cpy.enable = false; /* not visible beyond top edge*/
+ pos_cpy.x = x_pos;
+ pos_cpy.y = y_pos;
+
hubp->funcs->set_cursor_position(hubp, &pos_cpy, &param);
dpp->funcs->set_cursor_position(dpp, &pos_cpy, &param, hubp->curs_attr.width, hubp->curs_attr.height);
}
@@ -1510,14 +1514,15 @@ void dcn401_dmub_hw_control_lock_fast(union block_sequence_params *params)
void dcn401_fams2_update_config(struct dc *dc, struct dc_state *context, bool enable)
{
- bool fams2_required;
+ bool fams2_info_required;
if (!dc->ctx || !dc->ctx->dmub_srv || !dc->debug.fams2_config.bits.enable)
return;
- fams2_required = context->bw_ctx.bw.dcn.fams2_global_config.features.bits.enable;
+ fams2_info_required = context->bw_ctx.bw.dcn.fams2_global_config.features.bits.enable;
+ fams2_info_required |= context->bw_ctx.bw.dcn.fams2_global_config.features.bits.legacy_method_no_fams2;
- dc_dmub_srv_fams2_update_config(dc, context, enable && fams2_required);
+ dc_dmub_srv_fams2_update_config(dc, context, enable && fams2_info_required);
}
static void update_dsc_for_odm_change(struct dc *dc, struct dc_state *context,
@@ -1771,7 +1776,8 @@ void dcn401_unblank_stream(struct pipe_ctx *pipe_ctx,
void dcn401_hardware_release(struct dc *dc)
{
if (!dc->debug.disable_force_pstate_allow_on_hw_release) {
- dc_dmub_srv_fams2_update_config(dc, dc->current_state, false);
+ if (dc->ctx->dmub_srv && dc->debug.fams2_config.bits.enable)
+ dc_dmub_srv_fams2_update_config(dc, dc->current_state, false);
/* If pstate unsupported, or still supported
* by firmware, force it supported by dcn
@@ -1791,7 +1797,9 @@ void dcn401_hardware_release(struct dc *dc)
dc->clk_mgr->clks.p_state_change_support = false;
dc->clk_mgr->funcs->update_clocks(dc->clk_mgr, dc->current_state, true);
}
- dc_dmub_srv_fams2_update_config(dc, dc->current_state, false);
+
+ if (dc->ctx->dmub_srv && dc->debug.fams2_config.bits.enable)
+ dc_dmub_srv_fams2_update_config(dc, dc->current_state, false);
}
}
diff --git a/drivers/gpu/drm/amd/display/dc/hwss/dcn401/dcn401_init.c b/drivers/gpu/drm/amd/display/dc/hwss/dcn401/dcn401_init.c
index 162096ce0bdf..5d0dfb36f3e1 100644
--- a/drivers/gpu/drm/amd/display/dc/hwss/dcn401/dcn401_init.c
+++ b/drivers/gpu/drm/amd/display/dc/hwss/dcn401/dcn401_init.c
@@ -156,7 +156,6 @@ static const struct hwseq_private_funcs dcn401_private_funcs = {
.verify_allow_pstate_change_high = dcn10_verify_allow_pstate_change_high,
.verify_allow_pstate_change_high_sequence = dcn401_verify_allow_pstate_change_high_sequence,
.wait_for_blank_complete = dcn20_wait_for_blank_complete,
- .dccg_init = dcn20_dccg_init,
.set_mcm_luts = dcn401_set_mcm_luts,
.program_mall_pipe_config = dcn32_program_mall_pipe_config,
.program_mall_pipe_config_sequence = dcn401_program_mall_pipe_config_sequence,
diff --git a/drivers/gpu/drm/amd/display/dc/hwss/hw_sequencer.h b/drivers/gpu/drm/amd/display/dc/hwss/hw_sequencer.h
index 8ed9eea40c56..51b0f0fd8fcd 100644
--- a/drivers/gpu/drm/amd/display/dc/hwss/hw_sequencer.h
+++ b/drivers/gpu/drm/amd/display/dc/hwss/hw_sequencer.h
@@ -52,7 +52,7 @@ struct drr_params;
struct dc_underflow_debug_data;
struct dsc_optc_config;
struct vm_system_aperture_param;
-
+struct memory_qos;
struct subvp_pipe_control_lock_fast_params {
struct dc *dc;
bool lock;
@@ -1287,6 +1287,17 @@ struct hw_sequencer_funcs {
void (*get_underflow_debug_data)(const struct dc *dc,
struct timing_generator *tg,
struct dc_underflow_debug_data *out_data);
+
+ /**
+ * measure_memory_qos - Measure memory QoS metrics
+ * @dc: DC structure
+ * @qos: Pointer to memory_qos struct to populate with measured values
+ *
+ * Populates the provided memory_qos struct with peak bandwidth, average bandwidth,
+ * max latency, min latency, and average latency from hardware performance counters.
+ */
+ void (*measure_memory_qos)(struct dc *dc, struct memory_qos *qos);
+
};
void color_space_to_black_color(
diff --git a/drivers/gpu/drm/amd/display/dc/inc/core_types.h b/drivers/gpu/drm/amd/display/dc/inc/core_types.h
index 5ed2cd344804..61d8ef759aca 100644
--- a/drivers/gpu/drm/amd/display/dc/inc/core_types.h
+++ b/drivers/gpu/drm/amd/display/dc/inc/core_types.h
@@ -704,4 +704,12 @@ struct dc_bounding_box_max_clk {
int max_phyclk_mhz;
};
+struct memory_qos {
+ uint32_t peak_bw_mbps;
+ uint32_t avg_bw_mbps;
+ uint32_t max_latency_ns;
+ uint32_t min_latency_ns;
+ uint32_t avg_latency_ns;
+};
+
#endif /* _CORE_TYPES_H_ */
diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/dccg.h b/drivers/gpu/drm/amd/display/dc/inc/hw/dccg.h
index 500a601e99b5..1e6ffd86a4c0 100644
--- a/drivers/gpu/drm/amd/display/dc/inc/hw/dccg.h
+++ b/drivers/gpu/drm/amd/display/dc/inc/hw/dccg.h
@@ -333,6 +333,7 @@ struct dccg_funcs {
void (*set_ref_dscclk)(struct dccg *dccg, uint32_t dsc_inst);
void (*dccg_root_gate_disable_control)(struct dccg *dccg, uint32_t pipe_idx, uint32_t disable_clock_gating);
void (*dccg_read_reg_state)(struct dccg *dccg, struct dcn_dccg_reg_state *dccg_reg_state);
+ void (*dccg_enable_global_fgcg)(struct dccg *dccg, bool enable);
};
#endif //__DAL_DCCG_H__
diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/dchubbub.h b/drivers/gpu/drm/amd/display/dc/inc/hw/dchubbub.h
index 1ddfa30411c8..4307362749f0 100644
--- a/drivers/gpu/drm/amd/display/dc/inc/hw/dchubbub.h
+++ b/drivers/gpu/drm/amd/display/dc/inc/hw/dchubbub.h
@@ -254,30 +254,38 @@ struct hubbub_funcs {
bool (*program_arbiter)(struct hubbub *hubbub, struct dml2_display_arb_regs *arb_regs, bool safe_to_lower);
void (*dchvm_init)(struct hubbub *hubbub);
+ /* Performance monitoring related functions */
struct hubbub_perfmon_funcs {
void (*reset)(struct hubbub *hubbub);
- void (*start_measuring_max_memory_latency_ns)(
+ void (*start_measuring_memory_latencies)(
struct hubbub *hubbub);
- uint32_t (*get_max_memory_latency_ns)(struct hubbub *hubbub,
- uint32_t refclk_mhz, uint32_t *sample_count);
- void (*start_measuring_average_memory_latency_ns)(
+ uint32_t (*get_memory_latencies_ns)(struct hubbub *hubbub,
+ uint32_t refclk_mhz, uint32_t *min_latency_ns,
+ uint32_t *max_latency_ns, uint32_t *avg_latency_ns);
+ void (*start_measuring_urgent_assertion_count)(
struct hubbub *hubbub);
- uint32_t (*get_average_memory_latency_ns)(struct hubbub *hubbub,
- uint32_t refclk_mhz, uint32_t *sample_count);
- void (*start_measuring_urgent_ramp_latency_ns)(
+ bool (*get_urgent_assertion_count)(struct hubbub *hubbub,
+ uint32_t refclk_mhz,
+ uint32_t *assertion_count,
+ uint32_t *deassertion_count,
+ uint32_t *timestamp_us);
+ void (*start_measuring_urgent_ramp_latency)(
struct hubbub *hubbub,
const struct hubbub_urgent_latency_params *params);
uint32_t (*get_urgent_ramp_latency_ns)(struct hubbub *hubbub,
uint32_t refclk_mhz);
- void (*start_measuring_unbounded_bandwidth_mbps)(
+ void (*start_measuring_unbounded_bandwidth)(
struct hubbub *hubbub);
uint32_t (*get_unbounded_bandwidth_mbps)(struct hubbub *hubbub,
uint32_t refclk_mhz, uint32_t *duration_ns);
- void (*start_measuring_average_bandwidth_mbps)(
+ void (*start_measuring_in_order_bandwidth)(
struct hubbub *hubbub);
- uint32_t (*get_average_bandwidth_mbps)(struct hubbub *hubbub,
+ uint32_t (*get_in_order_bandwidth_mbps)(struct hubbub *hubbub,
uint32_t refclk_mhz, uint32_t min_duration_ns,
uint32_t *duration_ns);
+ void (*start_measuring_prefetch_data_size)(
+ struct hubbub *hubbub);
+ uint32_t (*get_prefetch_data_size)(struct hubbub *hubbub);
} perfmon;
struct hubbub_qos_funcs {
diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/link_encoder.h b/drivers/gpu/drm/amd/display/dc/inc/hw/link_encoder.h
index df512920a9fa..d795fc43dc9d 100644
--- a/drivers/gpu/drm/amd/display/dc/inc/hw/link_encoder.h
+++ b/drivers/gpu/drm/amd/display/dc/inc/hw/link_encoder.h
@@ -44,9 +44,11 @@ struct pipe_ctx;
struct encoder_init_data {
enum channel_id channel;
struct graphics_object_id connector;
+ struct gpio *hpd_gpio;
enum hpd_source_id hpd_source;
/* TODO: in DAL2, here was pointer to EventManagerInterface */
struct graphics_object_id encoder;
+ struct graphics_object_id analog_encoder;
enum engine_id analog_engine;
struct dc_context *ctx;
enum transmitter transmitter;
@@ -81,12 +83,14 @@ struct link_encoder {
int32_t aux_channel_offset;
struct dc_context *ctx;
struct graphics_object_id id;
+ struct graphics_object_id analog_id;
struct graphics_object_id connector;
uint32_t output_signals;
enum engine_id preferred_engine;
enum engine_id analog_engine;
struct encoder_feature_support features;
enum transmitter transmitter;
+ struct gpio *hpd_gpio;
enum hpd_source_id hpd_source;
bool usbc_combo_phy;
};
@@ -178,6 +182,8 @@ struct link_encoder_funcs {
void (*disable_dpia_output)(struct link_encoder *link_enc,
uint8_t dpia_id,
uint8_t digmode);
+ bool (*get_hpd_state)(struct link_encoder *enc);
+ bool (*program_hpd_filter)(struct link_encoder *enc, int delay_on_connect_in_ms, int delay_on_disconnect_in_ms);
};
/*
diff --git a/drivers/gpu/drm/amd/display/dc/inc/link_service.h b/drivers/gpu/drm/amd/display/dc/inc/link_service.h
index 6f94e48a24d1..57bb82e94942 100644
--- a/drivers/gpu/drm/amd/display/dc/inc/link_service.h
+++ b/drivers/gpu/drm/amd/display/dc/inc/link_service.h
@@ -114,9 +114,6 @@ struct link_service {
struct dc_sink_init_data *init_data);
void (*remove_remote_sink)(struct dc_link *link, struct dc_sink *sink);
bool (*get_hpd_state)(struct dc_link *link);
- struct gpio *(*get_hpd_gpio)(struct dc_bios *dcb,
- struct graphics_object_id link_id,
- struct gpio_service *gpio_service);
void (*enable_hpd)(const struct dc_link *link);
void (*disable_hpd)(const struct dc_link *link);
void (*enable_hpd_filter)(struct dc_link *link, bool enable);
@@ -286,8 +283,6 @@ struct link_service {
bool (*edp_set_replay_allow_active)(struct dc_link *dc_link,
const bool *enable, bool wait, bool force_static,
const unsigned int *power_opts);
- bool (*edp_setup_replay)(struct dc_link *link,
- const struct dc_stream_state *stream);
bool (*edp_send_replay_cmd)(struct dc_link *link,
enum replay_FW_Message_type msg,
union dmub_replay_cmd_set *cmd_data);
@@ -307,6 +302,12 @@ struct link_service {
bool (*edp_receiver_ready_T9)(struct dc_link *link);
bool (*edp_receiver_ready_T7)(struct dc_link *link);
bool (*edp_power_alpm_dpcd_enable)(struct dc_link *link, bool enable);
+ bool (*dp_setup_replay)(struct dc_link *link, const struct dc_stream_state *stream);
+ bool (*dp_pr_get_panel_inst)(const struct dc *dc, const struct dc_link *link, unsigned int *inst_out);
+ bool (*dp_pr_enable)(struct dc_link *link, bool enable);
+ bool (*dp_pr_update_state)(struct dc_link *link, struct dmub_cmd_pr_update_state_data *update_state_data);
+ bool (*dp_pr_set_general_cmd)(struct dc_link *link, struct dmub_cmd_pr_general_cmd_data *general_cmd_data);
+ bool (*dp_pr_get_state)(const struct dc_link *link, uint64_t *state);
void (*edp_set_panel_power)(struct dc_link *link, bool powerOn);
diff --git a/drivers/gpu/drm/amd/display/dc/link/Makefile b/drivers/gpu/drm/amd/display/dc/link/Makefile
index 84c7af5fa589..84dace27daf7 100644
--- a/drivers/gpu/drm/amd/display/dc/link/Makefile
+++ b/drivers/gpu/drm/amd/display/dc/link/Makefile
@@ -56,7 +56,7 @@ LINK_PROTOCOLS = link_hpd.o link_ddc.o link_dpcd.o link_dp_dpia.o \
link_dp_training.o link_dp_training_8b_10b.o link_dp_training_128b_132b.o \
link_dp_training_dpia.o link_dp_training_auxless.o \
link_dp_training_fixed_vs_pe_retimer.o link_dp_phy.o link_dp_capability.o \
-link_edp_panel_control.o link_dp_irq_handler.o link_dp_dpia_bw.o
+link_edp_panel_control.o link_dp_panel_replay.o link_dp_irq_handler.o link_dp_dpia_bw.o
AMD_DAL_LINK_PROTOCOLS = $(addprefix $(AMDDALPATH)/dc/link/protocols/, \
$(LINK_PROTOCOLS))
diff --git a/drivers/gpu/drm/amd/display/dc/link/accessories/link_dp_cts.c b/drivers/gpu/drm/amd/display/dc/link/accessories/link_dp_cts.c
index 1045c268672e..693d852b1c40 100644
--- a/drivers/gpu/drm/amd/display/dc/link/accessories/link_dp_cts.c
+++ b/drivers/gpu/drm/amd/display/dc/link/accessories/link_dp_cts.c
@@ -81,7 +81,8 @@ static void dp_retrain_link_dp_test(struct dc_link *link,
struct dc *dc = (struct dc *)link->dc;
needs_divider_update = (link->dc->link_srv->dp_get_encoding_format(link_setting) !=
- link->dc->link_srv->dp_get_encoding_format((const struct dc_link_settings *) &link->cur_link_settings));
+ link->dc->link_srv->dp_get_encoding_format((const struct dc_link_settings *) &link->cur_link_settings))
+ || link->ep_type == DISPLAY_ENDPOINT_USB4_DPIA;
udelay(100);
diff --git a/drivers/gpu/drm/amd/display/dc/link/link_detection.c b/drivers/gpu/drm/amd/display/dc/link/link_detection.c
index 7fa6bc97a919..578509e8d0e2 100644
--- a/drivers/gpu/drm/amd/display/dc/link/link_detection.c
+++ b/drivers/gpu/drm/amd/display/dc/link/link_detection.c
@@ -171,6 +171,7 @@ static enum signal_type link_detect_sink_signal_type(struct dc_link *link,
enum dc_detect_reason reason)
{
enum signal_type result;
+ struct audio_support *aud_support;
struct graphics_object_id enc_id;
if (link->is_dig_mapping_flexible)
@@ -183,53 +184,51 @@ static enum signal_type link_detect_sink_signal_type(struct dc_link *link,
if (link->ep_type != DISPLAY_ENDPOINT_PHY)
return result;
- /* Internal digital encoder will detect only dongles
+ /*
+ * Internal digital encoder will detect only dongles
* that require digital signal
*/
- /* Detection mechanism is different
+ /*
+ * Detection mechanism is different
* for different native connectors.
* LVDS connector supports only LVDS signal;
* PCIE is a bus slot, the actual connector needs to be detected first;
* eDP connector supports only eDP signal;
* HDMI should check straps for audio
*/
-
- /* PCIE detects the actual connector on add-on board */
- if (link->link_id.id == CONNECTOR_ID_PCIE) {
- /* ZAZTODO implement PCIE add-on card detection */
- }
-
switch (link->link_id.id) {
- case CONNECTOR_ID_HDMI_TYPE_A: {
- /* check audio support:
+ case CONNECTOR_ID_HDMI_TYPE_A:
+ /*
+ * check audio support:
* if native HDMI is not supported, switch to DVI
*/
- struct audio_support *aud_support =
- &link->dc->res_pool->audio_support;
+ aud_support = &link->dc->res_pool->audio_support;
if (!aud_support->hdmi_audio_native)
- if (link->link_id.id == CONNECTOR_ID_HDMI_TYPE_A)
- result = SIGNAL_TYPE_DVI_SINGLE_LINK;
- }
- break;
+ result = SIGNAL_TYPE_DVI_SINGLE_LINK;
+ break;
case CONNECTOR_ID_DISPLAY_PORT:
- case CONNECTOR_ID_USBC: {
- /* DP HPD short pulse. Passive DP dongle will not
+ case CONNECTOR_ID_USBC:
+ /*
+ * DP HPD short pulse. Passive DP dongle will not
* have short pulse
*/
if (reason != DETECT_REASON_HPDRX) {
- /* Check whether DP signal detected: if not -
+ /*
+ * Check whether DP signal detected: if not -
* we assume signal is DVI; it could be corrected
* to HDMI after dongle detection
*/
if (!dm_helpers_is_dp_sink_present(link))
result = SIGNAL_TYPE_DVI_SINGLE_LINK;
}
- }
- break;
+ break;
+ case CONNECTOR_ID_PCIE:
+ /* ZAZTODO implement PCIE add-on card detection */
+ break;
default:
- break;
+ break;
}
return result;
@@ -626,6 +625,9 @@ static bool detect_dp(struct dc_link *link,
static bool is_same_edid(struct dc_edid *old_edid, struct dc_edid *new_edid)
{
+ if (old_edid == NULL || new_edid == NULL)
+ return false;
+
if (old_edid->length != new_edid->length)
return false;
@@ -1173,19 +1175,20 @@ static bool detect_link_and_local_sink(struct dc_link *link,
* - cheap DVI-A cable or adapter that doesn't connect DDC
*/
if (dc_connector_supports_analog(link->link_id.id)) {
- /* If we didn't do DAC load detection yet, do it now
- * to verify there really is a display connected.
+ /* If we didn't already detect a display using
+ * DAC load detection, we know it isn't connected.
*/
- if (link->type != dc_connection_dac_load &&
- !link_detect_dac_load_detect(link)) {
+ if (link->type != dc_connection_analog_load) {
if (prev_sink)
dc_sink_release(prev_sink);
link_disconnect_sink(link);
return false;
}
- DC_LOG_INFO("%s detected analog display without EDID\n", __func__);
- link->type = dc_connection_dac_load;
+ LINK_INFO("link=%d, analog display detected without EDID\n",
+ link->link_index);
+
+ link->type = dc_connection_analog_load;
sink->edid_caps.analog = true;
break;
}
@@ -1367,17 +1370,17 @@ static bool detect_link_and_local_sink(struct dc_link *link,
}
/**
- * link_detect_analog() - Determines if an analog sink is connected.
+ * link_detect_connection_type_analog() - Determines if an analog sink is connected.
*
* @link: DC link to evaluate (must support analog signalling).
* @type: Updated with the detected connection type:
* dc_connection_single (analog via DDC),
- * dc_connection_dac_load (via load-detect),
+ * dc_connection_analog_load (via load-detect),
* or dc_connection_none.
*
* Return: true if detection completed.
*/
-static bool link_detect_analog(struct dc_link *link, enum dc_connection_type *type)
+static bool link_detect_connection_type_analog(struct dc_link *link, enum dc_connection_type *type)
{
/* Don't care about connectors that don't support an analog signal. */
ASSERT(dc_connector_supports_analog(link->link_id.id));
@@ -1388,7 +1391,7 @@ static bool link_detect_analog(struct dc_link *link, enum dc_connection_type *ty
}
if (link_detect_dac_load_detect(link)) {
- *type = dc_connection_dac_load;
+ *type = dc_connection_analog_load;
return true;
}
@@ -1405,8 +1408,6 @@ static bool link_detect_analog(struct dc_link *link, enum dc_connection_type *ty
*/
bool link_detect_connection_type(struct dc_link *link, enum dc_connection_type *type)
{
- uint32_t is_hpd_high = 0;
-
if (link->connector_signal == SIGNAL_TYPE_LVDS) {
*type = dc_connection_single;
return true;
@@ -1421,7 +1422,7 @@ bool link_detect_connection_type(struct dc_link *link, enum dc_connection_type *
* (So it's high even when no display is connected.)
*/
if (dc_connector_supports_analog(link->link_id.id))
- return link_detect_analog(link, type);
+ return link_detect_connection_type_analog(link, type);
if (link->connector_signal == SIGNAL_TYPE_EDP) {
/*in case it is not on*/
@@ -1441,10 +1442,7 @@ bool link_detect_connection_type(struct dc_link *link, enum dc_connection_type *
}
- if (!query_hpd_status(link, &is_hpd_high))
- goto hpd_gpio_failure;
-
- if (is_hpd_high) {
+ if (link_get_hpd_state(link)) {
*type = dc_connection_single;
/* TODO: need to do the actual detection */
} else {
@@ -1457,9 +1455,6 @@ bool link_detect_connection_type(struct dc_link *link, enum dc_connection_type *
}
return true;
-
-hpd_gpio_failure:
- return false;
}
bool link_detect(struct dc_link *link, enum dc_detect_reason reason)
diff --git a/drivers/gpu/drm/amd/display/dc/link/link_dpms.c b/drivers/gpu/drm/amd/display/dc/link/link_dpms.c
index 6ae134147617..91742bde4dc2 100644
--- a/drivers/gpu/drm/amd/display/dc/link/link_dpms.c
+++ b/drivers/gpu/drm/amd/display/dc/link/link_dpms.c
@@ -46,6 +46,7 @@
#include "protocols/link_dp_capability.h"
#include "protocols/link_dp_training.h"
#include "protocols/link_edp_panel_control.h"
+#include "protocols/link_dp_panel_replay.h"
#include "protocols/link_dp_dpia_bw.h"
#include "dm_helpers.h"
@@ -841,7 +842,7 @@ void link_set_dsc_on_stream(struct pipe_ctx *pipe_ctx, bool enable)
dsc_cfg.dc_dsc_cfg = stream->timing.dsc_cfg;
ASSERT(dsc_cfg.dc_dsc_cfg.num_slices_h % opp_cnt == 0);
dsc_cfg.dc_dsc_cfg.num_slices_h /= opp_cnt;
- dsc_cfg.dsc_padding = pipe_ctx->dsc_padding_params.dsc_hactive_padding;
+ dsc_cfg.dsc_padding = 0;
if (should_use_dto_dscclk)
dccg->funcs->set_dto_dscclk(dccg, dsc->inst, dsc_cfg.dc_dsc_cfg.num_slices_h);
@@ -857,6 +858,7 @@ void link_set_dsc_on_stream(struct pipe_ctx *pipe_ctx, bool enable)
}
dsc_cfg.dc_dsc_cfg.num_slices_h *= opp_cnt;
dsc_cfg.pic_width *= opp_cnt;
+ dsc_cfg.dsc_padding = pipe_ctx->dsc_padding_params.dsc_hactive_padding;
optc_dsc_mode = dsc_optc_cfg.is_pixel_format_444 ? OPTC_DSC_ENABLED_444 : OPTC_DSC_ENABLED_NATIVE_SUBSAMPLED;
@@ -1329,13 +1331,34 @@ static void remove_stream_from_alloc_table(
}
}
+static void print_mst_streams(struct dc_link *link)
+{
+ int i;
+
+ DC_LOGGER_INIT(link->ctx->logger);
+
+ DC_LOG_MST("%s stream_count: %d:\n",
+ __func__,
+ link->mst_stream_alloc_table.stream_count);
+
+ for (i = 0; i < MAX_CONTROLLER_NUM; i++) {
+ DC_LOG_MST("stream_enc[%d]: %p\n", i,
+ (void *) link->mst_stream_alloc_table.stream_allocations[i].stream_enc);
+ DC_LOG_MST("stream[%d].hpo_dp_stream_enc: %p\n", i,
+ (void *) link->mst_stream_alloc_table.stream_allocations[i].hpo_dp_stream_enc);
+ DC_LOG_MST("stream[%d].vcp_id: %d\n", i,
+ link->mst_stream_alloc_table.stream_allocations[i].vcp_id);
+ DC_LOG_MST("stream[%d].slot_count: %d\n", i,
+ link->mst_stream_alloc_table.stream_allocations[i].slot_count);
+ }
+}
+
static enum dc_status deallocate_mst_payload(struct pipe_ctx *pipe_ctx)
{
struct dc_stream_state *stream = pipe_ctx->stream;
struct dc_link *link = stream->link;
struct dc_dp_mst_stream_allocation_table proposed_table = {0};
struct fixed31_32 avg_time_slots_per_mtp = dc_fixpt_from_int(0);
- int i;
bool mst_mode = (link->type == dc_connection_mst_branch);
const struct link_hwss *link_hwss = get_link_hwss(link, &pipe_ctx->link_res);
const struct dc_link_settings empty_link_settings = {0};
@@ -1371,9 +1394,7 @@ static enum dc_status deallocate_mst_payload(struct pipe_ctx *pipe_ctx)
pipe_ctx->stream_res.hpo_dp_stream_enc,
&proposed_table);
else
- DC_LOG_WARNING("Failed to update"
- "MST allocation table for"
- "pipe idx:%d\n",
+ DC_LOG_WARNING("Failed to update MST allocation table for idx %d\n",
pipe_ctx->pipe_idx);
} else {
/* when link is no longer in mst mode (mst hub unplugged),
@@ -1383,25 +1404,7 @@ static enum dc_status deallocate_mst_payload(struct pipe_ctx *pipe_ctx)
pipe_ctx->stream_res.hpo_dp_stream_enc);
}
- DC_LOG_MST("%s"
- "stream_count: %d: ",
- __func__,
- link->mst_stream_alloc_table.stream_count);
-
- for (i = 0; i < MAX_CONTROLLER_NUM; i++) {
- DC_LOG_MST("stream_enc[%d]: %p "
- "stream[%d].hpo_dp_stream_enc: %p "
- "stream[%d].vcp_id: %d "
- "stream[%d].slot_count: %d\n",
- i,
- (void *) link->mst_stream_alloc_table.stream_allocations[i].stream_enc,
- i,
- (void *) link->mst_stream_alloc_table.stream_allocations[i].hpo_dp_stream_enc,
- i,
- link->mst_stream_alloc_table.stream_allocations[i].vcp_id,
- i,
- link->mst_stream_alloc_table.stream_allocations[i].slot_count);
- }
+ print_mst_streams(link);
/* update mst stream allocation table hardware state */
if (link_hwss->ext.update_stream_allocation_table == NULL ||
@@ -1436,7 +1439,6 @@ static enum dc_status allocate_mst_payload(struct pipe_ctx *pipe_ctx)
struct fixed31_32 avg_time_slots_per_mtp;
struct fixed31_32 pbn;
struct fixed31_32 pbn_per_slot;
- int i;
enum act_return_status ret;
const struct link_hwss *link_hwss = get_link_hwss(link, &pipe_ctx->link_res);
DC_LOGGER_INIT(link->ctx->logger);
@@ -1458,30 +1460,10 @@ static enum dc_status allocate_mst_payload(struct pipe_ctx *pipe_ctx)
pipe_ctx->stream_res.hpo_dp_stream_enc,
&proposed_table);
else
- DC_LOG_WARNING("Failed to update"
- "MST allocation table for"
- "pipe idx:%d\n",
+ DC_LOG_WARNING("Failed to update MST allocation table for idx %d\n",
pipe_ctx->pipe_idx);
- DC_LOG_MST("%s "
- "stream_count: %d: \n ",
- __func__,
- link->mst_stream_alloc_table.stream_count);
-
- for (i = 0; i < MAX_CONTROLLER_NUM; i++) {
- DC_LOG_MST("stream_enc[%d]: %p "
- "stream[%d].hpo_dp_stream_enc: %p "
- "stream[%d].vcp_id: %d "
- "stream[%d].slot_count: %d\n",
- i,
- (void *) link->mst_stream_alloc_table.stream_allocations[i].stream_enc,
- i,
- (void *) link->mst_stream_alloc_table.stream_allocations[i].hpo_dp_stream_enc,
- i,
- link->mst_stream_alloc_table.stream_allocations[i].vcp_id,
- i,
- link->mst_stream_alloc_table.stream_allocations[i].slot_count);
- }
+ print_mst_streams(link);
ASSERT(proposed_table.stream_count > 0);
@@ -1746,7 +1728,6 @@ enum dc_status link_reduce_mst_payload(struct pipe_ctx *pipe_ctx, uint32_t bw_in
struct fixed31_32 pbn;
struct fixed31_32 pbn_per_slot;
struct dc_dp_mst_stream_allocation_table proposed_table = {0};
- uint8_t i;
const struct link_hwss *link_hwss = get_link_hwss(link, &pipe_ctx->link_res);
DC_LOGGER_INIT(link->ctx->logger);
@@ -1780,31 +1761,11 @@ enum dc_status link_reduce_mst_payload(struct pipe_ctx *pipe_ctx, uint32_t bw_in
pipe_ctx->stream_res.hpo_dp_stream_enc,
&proposed_table);
} else {
- DC_LOG_WARNING("Failed to update"
- "MST allocation table for"
- "pipe idx:%d\n",
+ DC_LOG_WARNING("Failed to update MST allocation table for idx %d\n",
pipe_ctx->pipe_idx);
}
- DC_LOG_MST("%s "
- "stream_count: %d: \n ",
- __func__,
- link->mst_stream_alloc_table.stream_count);
-
- for (i = 0; i < MAX_CONTROLLER_NUM; i++) {
- DC_LOG_MST("stream_enc[%d]: %p "
- "stream[%d].hpo_dp_stream_enc: %p "
- "stream[%d].vcp_id: %d "
- "stream[%d].slot_count: %d\n",
- i,
- (void *) link->mst_stream_alloc_table.stream_allocations[i].stream_enc,
- i,
- (void *) link->mst_stream_alloc_table.stream_allocations[i].hpo_dp_stream_enc,
- i,
- link->mst_stream_alloc_table.stream_allocations[i].vcp_id,
- i,
- link->mst_stream_alloc_table.stream_allocations[i].slot_count);
- }
+ print_mst_streams(link);
ASSERT(proposed_table.stream_count > 0);
@@ -1834,7 +1795,6 @@ enum dc_status link_increase_mst_payload(struct pipe_ctx *pipe_ctx, uint32_t bw_
struct fixed31_32 pbn;
struct fixed31_32 pbn_per_slot;
struct dc_dp_mst_stream_allocation_table proposed_table = {0};
- uint8_t i;
enum act_return_status ret;
const struct link_hwss *link_hwss = get_link_hwss(link, &pipe_ctx->link_res);
DC_LOGGER_INIT(link->ctx->logger);
@@ -1853,25 +1813,7 @@ enum dc_status link_increase_mst_payload(struct pipe_ctx *pipe_ctx, uint32_t bw_
&proposed_table);
}
- DC_LOG_MST("%s "
- "stream_count: %d: \n ",
- __func__,
- link->mst_stream_alloc_table.stream_count);
-
- for (i = 0; i < MAX_CONTROLLER_NUM; i++) {
- DC_LOG_MST("stream_enc[%d]: %p "
- "stream[%d].hpo_dp_stream_enc: %p "
- "stream[%d].vcp_id: %d "
- "stream[%d].slot_count: %d\n",
- i,
- (void *) link->mst_stream_alloc_table.stream_allocations[i].stream_enc,
- i,
- (void *) link->mst_stream_alloc_table.stream_allocations[i].hpo_dp_stream_enc,
- i,
- link->mst_stream_alloc_table.stream_allocations[i].vcp_id,
- i,
- link->mst_stream_alloc_table.stream_allocations[i].slot_count);
- }
+ print_mst_streams(link);
ASSERT(proposed_table.stream_count > 0);
@@ -1930,7 +1872,7 @@ static void disable_link_dp(struct dc_link *link,
link->dc->hwss.edp_power_control(link, false);
}
- if (signal == SIGNAL_TYPE_DISPLAY_PORT_MST)
+ if (signal == SIGNAL_TYPE_DISPLAY_PORT_MST && link->sink_count == 0)
/* set the sink to SST mode after disabling the link */
enable_mst_on_sink(link, false);
@@ -2081,7 +2023,12 @@ static enum dc_status enable_link_dp(struct dc_state *state,
pipe_ctx->stream->signal == SIGNAL_TYPE_DISPLAY_PORT &&
link->dc->debug.set_mst_en_for_sst) {
enable_mst_on_sink(link, true);
+ } else if (link->dpcd_caps.is_mst_capable &&
+ pipe_ctx->stream->signal == SIGNAL_TYPE_DISPLAY_PORT) {
+ /* disable mst on sink */
+ enable_mst_on_sink(link, false);
}
+
if (pipe_ctx->stream->signal == SIGNAL_TYPE_EDP) {
/*in case it is not on*/
if (!link->dc->config.edp_no_power_sequencing)
@@ -2367,9 +2314,9 @@ void link_set_dpms_off(struct pipe_ctx *pipe_ctx)
if (pipe_ctx->stream->sink) {
if (pipe_ctx->stream->sink->sink_signal != SIGNAL_TYPE_VIRTUAL &&
pipe_ctx->stream->sink->sink_signal != SIGNAL_TYPE_NONE) {
- DC_LOG_DC("%s pipe_ctx dispname=%s signal=%x link=%d\n", __func__,
+ DC_LOG_DC("%s pipe_ctx dispname=%s signal=%x link=%d sink_count=%d\n", __func__,
pipe_ctx->stream->sink->edid_caps.display_name,
- pipe_ctx->stream->signal, link->link_index);
+ pipe_ctx->stream->signal, link->link_index, link->sink_count);
}
}
@@ -2483,10 +2430,11 @@ void link_set_dpms_on(
if (pipe_ctx->stream->sink) {
if (pipe_ctx->stream->sink->sink_signal != SIGNAL_TYPE_VIRTUAL &&
pipe_ctx->stream->sink->sink_signal != SIGNAL_TYPE_NONE) {
- DC_LOG_DC("%s pipe_ctx dispname=%s signal=%x link=%d\n", __func__,
+ DC_LOG_DC("%s pipe_ctx dispname=%s signal=%x link=%d sink_count=%d\n", __func__,
pipe_ctx->stream->sink->edid_caps.display_name,
pipe_ctx->stream->signal,
- link->link_index);
+ link->link_index,
+ link->sink_count);
}
}
@@ -2582,6 +2530,9 @@ void link_set_dpms_on(
link_set_dsc_enable(pipe_ctx, true);
}
+ if (link->replay_settings.config.replay_supported && !dc_is_embedded_signal(link->connector_signal))
+ dp_setup_replay(link, stream);
+
status = enable_link(state, pipe_ctx);
if (status != DC_OK) {
diff --git a/drivers/gpu/drm/amd/display/dc/link/link_factory.c b/drivers/gpu/drm/amd/display/dc/link/link_factory.c
index a6e2b0821969..5fbcf04c6251 100644
--- a/drivers/gpu/drm/amd/display/dc/link/link_factory.c
+++ b/drivers/gpu/drm/amd/display/dc/link/link_factory.c
@@ -41,6 +41,7 @@
#include "protocols/link_dp_phy.h"
#include "protocols/link_dp_training.h"
#include "protocols/link_edp_panel_control.h"
+#include "protocols/link_dp_panel_replay.h"
#include "protocols/link_hpd.h"
#include "gpio_service_interface.h"
#include "atomfirmware.h"
@@ -73,7 +74,6 @@ static void construct_link_service_detection(struct link_service *link_srv)
link_srv->add_remote_sink = link_add_remote_sink;
link_srv->remove_remote_sink = link_remove_remote_sink;
link_srv->get_hpd_state = link_get_hpd_state;
- link_srv->get_hpd_gpio = link_get_hpd_gpio;
link_srv->enable_hpd = link_enable_hpd;
link_srv->disable_hpd = link_disable_hpd;
link_srv->enable_hpd_filter = link_enable_hpd_filter;
@@ -215,7 +215,6 @@ static void construct_link_service_edp_panel_control(struct link_service *link_s
link_srv->edp_get_replay_state = edp_get_replay_state;
link_srv->edp_set_replay_allow_active = edp_set_replay_allow_active;
- link_srv->edp_setup_replay = edp_setup_replay;
link_srv->edp_send_replay_cmd = edp_send_replay_cmd;
link_srv->edp_set_coasting_vtotal = edp_set_coasting_vtotal;
link_srv->edp_replay_residency = edp_replay_residency;
@@ -232,6 +231,18 @@ static void construct_link_service_edp_panel_control(struct link_service *link_s
link_srv->edp_set_panel_power = edp_set_panel_power;
}
+/* link dp panel replay implements DP panel replay functionality.
+ */
+static void construct_link_service_dp_panel_replay(struct link_service *link_srv)
+{
+ link_srv->dp_setup_replay = dp_setup_replay;
+ link_srv->dp_pr_get_panel_inst = dp_pr_get_panel_inst;
+ link_srv->dp_pr_enable = dp_pr_enable;
+ link_srv->dp_pr_update_state = dp_pr_update_state;
+ link_srv->dp_pr_set_general_cmd = dp_pr_set_general_cmd;
+ link_srv->dp_pr_get_state = dp_pr_get_state;
+}
+
/* link dp cts implements dp compliance test automation protocols and manual
* testing interfaces for debugging and certification purpose.
*/
@@ -284,6 +295,7 @@ static void construct_link_service(struct link_service *link_srv)
construct_link_service_dp_phy_or_dpia(link_srv);
construct_link_service_dp_irq_handler(link_srv);
construct_link_service_edp_panel_control(link_srv);
+ construct_link_service_dp_panel_replay(link_srv);
construct_link_service_dp_cts(link_srv);
construct_link_service_dp_trace(link_srv);
}
@@ -350,24 +362,6 @@ static enum transmitter translate_encoder_to_transmitter(
return TRANSMITTER_UNKNOWN;
}
break;
- case ENCODER_ID_EXTERNAL_NUTMEG:
- switch (encoder.enum_id) {
- case ENUM_ID_1:
- return TRANSMITTER_NUTMEG_CRT;
- default:
- return TRANSMITTER_UNKNOWN;
- }
- break;
- case ENCODER_ID_EXTERNAL_TRAVIS:
- switch (encoder.enum_id) {
- case ENUM_ID_1:
- return TRANSMITTER_TRAVIS_CRT;
- case ENUM_ID_2:
- return TRANSMITTER_TRAVIS_LCD;
- default:
- return TRANSMITTER_UNKNOWN;
- }
- break;
default:
return TRANSMITTER_UNKNOWN;
}
@@ -377,11 +371,6 @@ static void link_destruct(struct dc_link *link)
{
int i;
- if (link->hpd_gpio) {
- dal_gpio_destroy_irq(&link->hpd_gpio);
- link->hpd_gpio = NULL;
- }
-
if (link->ddc)
link_destroy_ddc_service(&link->ddc);
@@ -451,20 +440,19 @@ static enum channel_id get_ddc_line(struct dc_link *link)
return channel;
}
-static enum engine_id find_analog_engine(struct dc_link *link)
+static enum engine_id find_analog_engine(struct dc_link *link, struct graphics_object_id *enc)
{
struct dc_bios *bp = link->ctx->dc_bios;
- struct graphics_object_id encoder = {0};
enum bp_result bp_result = BP_RESULT_OK;
int i;
for (i = 0; i < 3; i++) {
- bp_result = bp->funcs->get_src_obj(bp, link->link_id, i, &encoder);
+ bp_result = bp->funcs->get_src_obj(bp, link->link_id, i, enc);
if (bp_result != BP_RESULT_OK)
return ENGINE_ID_UNKNOWN;
- switch (encoder.id) {
+ switch (enc->id) {
case ENCODER_ID_INTERNAL_DAC1:
case ENCODER_ID_INTERNAL_KLDSCP_DAC1:
return ENGINE_ID_DACA;
@@ -474,17 +462,10 @@ static enum engine_id find_analog_engine(struct dc_link *link)
}
}
+ memset(enc, 0, sizeof(*enc));
return ENGINE_ID_UNKNOWN;
}
-static bool transmitter_supported(const enum transmitter transmitter)
-{
- return transmitter != TRANSMITTER_UNKNOWN &&
- transmitter != TRANSMITTER_NUTMEG_CRT &&
- transmitter != TRANSMITTER_TRAVIS_CRT &&
- transmitter != TRANSMITTER_TRAVIS_LCD;
-}
-
static bool analog_engine_supported(const enum engine_id engine_id)
{
return engine_id == ENGINE_ID_DACA ||
@@ -502,6 +483,9 @@ static bool construct_phy(struct dc_link *link,
struct dc_bios *bios = init_params->dc->ctx->dc_bios;
const struct dc_vbios_funcs *bp_funcs = bios->funcs;
struct bp_disp_connector_caps_info disp_connect_caps_info = { 0 };
+ struct graphics_object_id link_encoder = { 0 };
+ enum transmitter transmitter_from_encoder;
+ enum engine_id link_analog_engine;
DC_LOGGER_INIT(dc_ctx->logger);
@@ -522,21 +506,21 @@ static bool construct_phy(struct dc_link *link,
link->link_id =
bios->funcs->get_connector_id(bios, init_params->connector_index);
- /* Determine early if the link has any supported encoders,
- * so that we avoid initializing DDC and HPD, etc.
- */
- bp_funcs->get_src_obj(bios, link->link_id, 0, &enc_init_data.encoder);
- enc_init_data.transmitter = translate_encoder_to_transmitter(enc_init_data.encoder);
- enc_init_data.analog_engine = find_analog_engine(link);
-
link->ep_type = DISPLAY_ENDPOINT_PHY;
DC_LOG_DC("BIOS object table - link_id: %d", link->link_id.id);
- if (!transmitter_supported(enc_init_data.transmitter) &&
- !analog_engine_supported(enc_init_data.analog_engine)) {
+ /* Determine early if the link has any supported encoders,
+ * so that we avoid initializing DDC and HPD, etc.
+ */
+ bp_funcs->get_src_obj(bios, link->link_id, 0, &link_encoder);
+ transmitter_from_encoder = translate_encoder_to_transmitter(link_encoder);
+ link_analog_engine = find_analog_engine(link, &enc_init_data.analog_encoder);
+
+ if (transmitter_from_encoder == TRANSMITTER_UNKNOWN &&
+ !analog_engine_supported(link_analog_engine)) {
DC_LOG_WARNING("link_id %d has unsupported encoder\n", link->link_id.id);
- goto unsupported_fail;
+ goto create_fail;
}
if (bios->funcs->get_disp_connector_caps_info) {
@@ -555,25 +539,77 @@ static bool construct_phy(struct dc_link *link,
if (link->dc->res_pool->funcs->link_init)
link->dc->res_pool->funcs->link_init(link);
- link->hpd_gpio = link_get_hpd_gpio(link->ctx->dc_bios, link->link_id,
+ ddc_service_init_data.ctx = link->ctx;
+ ddc_service_init_data.id = link->link_id;
+ ddc_service_init_data.link = link;
+ link->ddc = link_create_ddc_service(&ddc_service_init_data);
+
+ if (!link->ddc) {
+ DC_ERROR("Failed to create ddc_service!\n");
+ goto ddc_create_fail;
+ }
+
+ if (!link->ddc->ddc_pin) {
+ DC_ERROR("Failed to get I2C info for connector!\n");
+ goto ddc_create_fail;
+ }
+
+ link->ddc_hw_inst =
+ dal_ddc_get_line(get_ddc_pin(link->ddc));
+
+ enc_init_data.ctx = dc_ctx;
+ enc_init_data.connector = link->link_id;
+ enc_init_data.channel = get_ddc_line(link);
+ enc_init_data.transmitter = transmitter_from_encoder;
+ enc_init_data.analog_engine = find_analog_engine(link, &enc_init_data.analog_encoder);
+ enc_init_data.encoder = link_encoder;
+ enc_init_data.analog_engine = link_analog_engine;
+ enc_init_data.hpd_gpio = link_get_hpd_gpio(link->ctx->dc_bios, link->link_id,
link->ctx->gpio_service);
- if (link->hpd_gpio) {
- dal_gpio_open(link->hpd_gpio, GPIO_MODE_INTERRUPT);
- dal_gpio_unlock_pin(link->hpd_gpio);
- link->irq_source_hpd = dal_irq_get_source(link->hpd_gpio);
+ if (enc_init_data.hpd_gpio) {
+ dal_gpio_open(enc_init_data.hpd_gpio, GPIO_MODE_INTERRUPT);
+ dal_gpio_unlock_pin(enc_init_data.hpd_gpio);
+ link->irq_source_hpd = dal_irq_get_source(enc_init_data.hpd_gpio);
+ enc_init_data.hpd_source = get_hpd_line(link);
+ link->hpd_src = enc_init_data.hpd_source;
+
+ DC_LOG_DC("BIOS object table - hpd_gpio id: %d", enc_init_data.hpd_gpio->id);
+ DC_LOG_DC("BIOS object table - hpd_gpio en: %d", enc_init_data.hpd_gpio->en);
+ } else {
+ struct graphics_object_hpd_info hpd_info;
+
+ if (link->ctx->dc_bios->funcs->get_hpd_info(link->ctx->dc_bios, link->link_id, &hpd_info) == BP_RESULT_OK) {
+ link->hpd_src = hpd_info.hpd_int_gpio_uid - 1;
+ link->irq_source_hpd = DC_IRQ_SOURCE_HPD1 + link->hpd_src;
+ enc_init_data.hpd_source = link->hpd_src;
+ DC_LOG_DC("BIOS object table - hpd_int_gpio_uid id: %d", hpd_info.hpd_int_gpio_uid);
+ } else {
+ ASSERT(0);
+ enc_init_data.hpd_source = HPD_SOURCEID_UNKNOWN;
+ }
+ }
- DC_LOG_DC("BIOS object table - hpd_gpio id: %d", link->hpd_gpio->id);
- DC_LOG_DC("BIOS object table - hpd_gpio en: %d", link->hpd_gpio->en);
+ link->link_enc =
+ link->dc->res_pool->funcs->link_enc_create(dc_ctx, &enc_init_data);
+
+ if (!link->link_enc) {
+ DC_ERROR("Failed to create link encoder!\n");
+ goto link_enc_create_fail;
}
+ DC_LOG_DC("BIOS object table - DP_IS_USB_C: %d", link->link_enc->features.flags.bits.DP_IS_USB_C);
+ DC_LOG_DC("BIOS object table - IS_DP2_CAPABLE: %d", link->link_enc->features.flags.bits.IS_DP2_CAPABLE);
+
switch (link->link_id.id) {
case CONNECTOR_ID_HDMI_TYPE_A:
link->connector_signal = SIGNAL_TYPE_HDMI_TYPE_A;
- if (link->hpd_gpio)
+ if (link->link_enc->hpd_gpio)
link->irq_source_read_request =
- dal_irq_get_read_request(link->hpd_gpio);
+ dal_irq_get_read_request(link->link_enc->hpd_gpio);
+ else if (link->hpd_src != HPD_SOURCEID_UNKNOWN)
+ link->irq_source_read_request = DC_IRQ_SOURCE_DCI2C_RR_DDC1 + link->hpd_src;
break;
case CONNECTOR_ID_SINGLE_LINK_DVID:
case CONNECTOR_ID_SINGLE_LINK_DVII:
@@ -591,9 +627,11 @@ static bool construct_phy(struct dc_link *link,
case CONNECTOR_ID_USBC:
link->connector_signal = SIGNAL_TYPE_DISPLAY_PORT;
- if (link->hpd_gpio)
+ if (link->link_enc->hpd_gpio)
link->irq_source_hpd_rx =
- dal_irq_get_rx_source(link->hpd_gpio);
+ dal_irq_get_rx_source(link->link_enc->hpd_gpio);
+ else if (link->hpd_src != HPD_SOURCEID_UNKNOWN)
+ link->irq_source_hpd_rx = DC_IRQ_SOURCE_HPD1RX + link->hpd_src;
break;
case CONNECTOR_ID_EDP:
@@ -603,37 +641,45 @@ static bool construct_phy(struct dc_link *link,
goto create_fail;
link->connector_signal = SIGNAL_TYPE_EDP;
+ if (!link->dc->config.allow_edp_hotplug_detection
+ && !is_smartmux_suported(link))
+ link->irq_source_hpd = DC_IRQ_SOURCE_INVALID;
- if (link->hpd_gpio) {
- if (!link->dc->config.allow_edp_hotplug_detection
- && !is_smartmux_suported(link))
- link->irq_source_hpd = DC_IRQ_SOURCE_INVALID;
-
- switch (link->dc->config.allow_edp_hotplug_detection) {
- case HPD_EN_FOR_ALL_EDP:
+ switch (link->dc->config.allow_edp_hotplug_detection) {
+ case HPD_EN_FOR_ALL_EDP:
+ if (link->link_enc->hpd_gpio) {
link->irq_source_hpd_rx =
- dal_irq_get_rx_source(link->hpd_gpio);
- break;
- case HPD_EN_FOR_PRIMARY_EDP_ONLY:
- if (link->link_index == 0)
+ dal_irq_get_rx_source(link->link_enc->hpd_gpio);
+ } else if (link->hpd_src != HPD_SOURCEID_UNKNOWN) {
+ link->irq_source_hpd_rx = DC_IRQ_SOURCE_HPD1RX + link->hpd_src;
+ }
+ break;
+ case HPD_EN_FOR_PRIMARY_EDP_ONLY:
+ if (link->link_index == 0) {
+ if (link->link_enc->hpd_gpio) {
link->irq_source_hpd_rx =
- dal_irq_get_rx_source(link->hpd_gpio);
- else
- link->irq_source_hpd = DC_IRQ_SOURCE_INVALID;
- break;
- case HPD_EN_FOR_SECONDARY_EDP_ONLY:
- if (link->link_index == 1)
+ dal_irq_get_rx_source(link->link_enc->hpd_gpio);
+ } else if (link->hpd_src != HPD_SOURCEID_UNKNOWN) {
+ link->irq_source_hpd_rx = DC_IRQ_SOURCE_HPD1RX + link->hpd_src;
+ }
+ } else
+ link->irq_source_hpd = DC_IRQ_SOURCE_INVALID;
+ break;
+ case HPD_EN_FOR_SECONDARY_EDP_ONLY:
+ if (link->link_index == 1) {
+ if (link->link_enc->hpd_gpio) {
link->irq_source_hpd_rx =
- dal_irq_get_rx_source(link->hpd_gpio);
- else
- link->irq_source_hpd = DC_IRQ_SOURCE_INVALID;
- break;
- default:
+ dal_irq_get_rx_source(link->link_enc->hpd_gpio);
+ } else if (link->hpd_src != HPD_SOURCEID_UNKNOWN) {
+ link->irq_source_hpd_rx = DC_IRQ_SOURCE_HPD1RX + link->hpd_src;
+ }
+ } else
link->irq_source_hpd = DC_IRQ_SOURCE_INVALID;
- break;
- }
+ break;
+ default:
+ link->irq_source_hpd = DC_IRQ_SOURCE_INVALID;
+ break;
}
-
break;
case CONNECTOR_ID_LVDS:
link->connector_signal = SIGNAL_TYPE_LVDS;
@@ -648,42 +694,6 @@ static bool construct_phy(struct dc_link *link,
init_params->connector_index,
signal_type_to_string(link->connector_signal));
- ddc_service_init_data.ctx = link->ctx;
- ddc_service_init_data.id = link->link_id;
- ddc_service_init_data.link = link;
- link->ddc = link_create_ddc_service(&ddc_service_init_data);
-
- if (!link->ddc) {
- DC_ERROR("Failed to create ddc_service!\n");
- goto ddc_create_fail;
- }
-
- if (!link->ddc->ddc_pin) {
- DC_ERROR("Failed to get I2C info for connector!\n");
- goto ddc_create_fail;
- }
-
- link->ddc_hw_inst =
- dal_ddc_get_line(get_ddc_pin(link->ddc));
-
- enc_init_data.ctx = dc_ctx;
- enc_init_data.connector = link->link_id;
- enc_init_data.channel = get_ddc_line(link);
- enc_init_data.hpd_source = get_hpd_line(link);
-
- link->hpd_src = enc_init_data.hpd_source;
-
- link->link_enc =
- link->dc->res_pool->funcs->link_enc_create(dc_ctx, &enc_init_data);
-
- if (!link->link_enc) {
- DC_ERROR("Failed to create link encoder!\n");
- goto link_enc_create_fail;
- }
-
- DC_LOG_DC("BIOS object table - DP_IS_USB_C: %d", link->link_enc->features.flags.bits.DP_IS_USB_C);
- DC_LOG_DC("BIOS object table - IS_DP2_CAPABLE: %d", link->link_enc->features.flags.bits.IS_DP2_CAPABLE);
-
/* Update link encoder tracking variables. These are used for the dynamic
* assignment of link encoders to streams.
*/
@@ -792,21 +802,17 @@ static bool construct_phy(struct dc_link *link,
DC_LOG_DC("BIOS object table - %s finished successfully.\n", __func__);
return true;
device_tag_fail:
- link->link_enc->funcs->destroy(&link->link_enc);
link_enc_create_fail:
- if (link->panel_cntl != NULL)
- link->panel_cntl->funcs->destroy(&link->panel_cntl);
panel_cntl_create_fail:
- link_destroy_ddc_service(&link->ddc);
ddc_create_fail:
create_fail:
+ if (link->ddc)
+ link_destroy_ddc_service(&link->ddc);
+ if (link->panel_cntl)
+ link->panel_cntl->funcs->destroy(&link->panel_cntl);
+ if (link->link_enc)
+ link->link_enc->funcs->destroy(&link->link_enc);
- if (link->hpd_gpio) {
- dal_gpio_destroy_irq(&link->hpd_gpio);
- link->hpd_gpio = NULL;
- }
-
-unsupported_fail:
DC_LOG_DC("BIOS object table - %s failed.\n", __func__);
return false;
}
diff --git a/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_capability.c b/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_capability.c
index ad90a0106938..cdc7587cf0b6 100644
--- a/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_capability.c
+++ b/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_capability.c
@@ -1593,6 +1593,41 @@ static bool dpcd_read_sink_ext_caps(struct dc_link *link)
return true;
}
+static void retrieve_vesa_replay_su_info(struct dc_link *link)
+{
+ uint8_t dpcd_data = 0;
+
+ core_link_read_dpcd(link,
+ DP_PR_SU_X_GRANULARITY_LOW,
+ &dpcd_data,
+ sizeof(dpcd_data));
+ link->dpcd_caps.vesa_replay_su_info.pr_su_x_granularity = dpcd_data;
+
+ core_link_read_dpcd(link,
+ DP_PR_SU_X_GRANULARITY_HIGH,
+ &dpcd_data,
+ sizeof(dpcd_data));
+ link->dpcd_caps.vesa_replay_su_info.pr_su_x_granularity |= (dpcd_data << 8);
+
+ core_link_read_dpcd(link,
+ DP_PR_SU_Y_GRANULARITY,
+ &dpcd_data,
+ sizeof(dpcd_data));
+ link->dpcd_caps.vesa_replay_su_info.pr_su_y_granularity = dpcd_data;
+
+ core_link_read_dpcd(link,
+ DP_PR_SU_Y_GRANULARITY_EXTENDED_CAP_LOW,
+ &dpcd_data,
+ sizeof(dpcd_data));
+ link->dpcd_caps.vesa_replay_su_info.pr_su_y_granularity_extended_caps = dpcd_data;
+
+ core_link_read_dpcd(link,
+ DP_PR_SU_Y_GRANULARITY_EXTENDED_CAP_HIGH,
+ &dpcd_data,
+ sizeof(dpcd_data));
+ link->dpcd_caps.vesa_replay_su_info.pr_su_y_granularity_extended_caps |= (dpcd_data << 8);
+}
+
enum dc_status dp_retrieve_lttpr_cap(struct dc_link *link)
{
uint8_t lttpr_dpcd_data[10] = {0};
@@ -2094,8 +2129,16 @@ static bool retrieve_link_cap(struct dc_link *link)
core_link_read_dpcd(link,
DP_PANEL_REPLAY_CAPABILITY_SUPPORT,
- &link->dpcd_caps.pr_caps_supported.raw,
- sizeof(link->dpcd_caps.pr_caps_supported.raw));
+ &link->dpcd_caps.vesa_replay_caps_supported.raw,
+ sizeof(link->dpcd_caps.vesa_replay_caps_supported.raw));
+
+ core_link_read_dpcd(link,
+ DP_PANEL_REPLAY_CAPABILITY,
+ &link->dpcd_caps.vesa_replay_caps.raw,
+ sizeof(link->dpcd_caps.vesa_replay_caps.raw));
+
+ /* Read VESA Panel Replay Selective Update caps */
+ retrieve_vesa_replay_su_info(link);
/* Read DP tunneling information. */
status = dpcd_get_tunneling_device_data(link);
@@ -2220,6 +2263,13 @@ void detect_edp_sink_caps(struct dc_link *link)
sizeof(link->dpcd_caps.edp_oled_emission_rate));
/*
+ * Read DRR granularity
+ */
+ core_link_read_dpcd(link, DP_SINK_DRR_GRANULARITY,
+ (uint8_t *)&link->dpcd_caps.drr_granularity,
+ sizeof(link->dpcd_caps.drr_granularity));
+
+ /*
* Read Multi-SST (Single Stream Transport) capability
* for eDP version 1.4 or higher.
*/
diff --git a/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_irq_handler.c b/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_irq_handler.c
index 4b01ab0a5a7f..cc18a3bebef2 100644
--- a/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_irq_handler.c
+++ b/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_irq_handler.c
@@ -34,10 +34,12 @@
#include "link_dp_training.h"
#include "link_dp_capability.h"
#include "link_edp_panel_control.h"
+#include "link_dp_panel_replay.h"
#include "link/accessories/link_dp_trace.h"
#include "link/link_dpms.h"
#include "dm_helpers.h"
#include "link_dp_dpia_bw.h"
+#include "link_dp_panel_replay.h"
#define DC_LOGGER \
link->ctx->logger
@@ -185,6 +187,42 @@ static bool handle_hpd_irq_psr_sink(struct dc_link *link)
return false;
}
+static void handle_hpd_irq_vesa_replay_sink(struct dc_link *link)
+{
+ union pr_error_status pr_error_status = {0};
+
+ if (!link->replay_settings.replay_feature_enabled ||
+ link->replay_settings.config.replay_version != DC_VESA_PANEL_REPLAY)
+ return;
+
+ dm_helpers_dp_read_dpcd(
+ link->ctx,
+ link,
+ DP_PR_ERROR_STATUS,
+ &pr_error_status.raw,
+ sizeof(pr_error_status.raw));
+
+ if (pr_error_status.bits.LINK_CRC_ERROR ||
+ pr_error_status.bits.RFB_STORAGE_ERROR ||
+ pr_error_status.bits.VSC_SDP_ERROR ||
+ pr_error_status.bits.ASSDP_MISSING_ERROR) {
+
+ /* Acknowledge and clear error bits */
+ dm_helpers_dp_write_dpcd(
+ link->ctx,
+ link,
+ DP_PR_ERROR_STATUS, /*DpcdAddress_PR_Error_Status*/
+ &pr_error_status.raw,
+ sizeof(pr_error_status.raw));
+
+ /* Replay error, disable and re-enable Replay */
+ if (link->replay_settings.replay_allow_active) {
+ dp_pr_enable(link, false);
+ dp_pr_enable(link, true);
+ }
+ }
+}
+
static void handle_hpd_irq_replay_sink(struct dc_link *link)
{
union dpcd_replay_configuration replay_configuration = {0};
@@ -196,6 +234,11 @@ static void handle_hpd_irq_replay_sink(struct dc_link *link)
if (!link->replay_settings.replay_feature_enabled)
return;
+ if (link->replay_settings.config.replay_version != DC_FREESYNC_REPLAY) {
+ handle_hpd_irq_vesa_replay_sink(link);
+ return;
+ }
+
while (retries < 10) {
ret = dm_helpers_dp_read_dpcd(
link->ctx,
diff --git a/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_panel_replay.c b/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_panel_replay.c
new file mode 100644
index 000000000000..bbd6f93f5c98
--- /dev/null
+++ b/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_panel_replay.c
@@ -0,0 +1,353 @@
+/*
+ * Copyright 2025 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 "link_dp_panel_replay.h"
+#include "link_edp_panel_control.h"
+#include "link_dpcd.h"
+#include "dm_helpers.h"
+#include "dc/dc_dmub_srv.h"
+#include "dce/dmub_replay.h"
+
+#define DC_LOGGER \
+ link->ctx->logger
+
+#define DP_SINK_PR_ENABLE_AND_CONFIGURATION 0x37B
+
+static bool dp_setup_panel_replay(struct dc_link *link, const struct dc_stream_state *stream)
+{
+ /* To-do: Setup Replay */
+ struct dc *dc;
+ struct dmub_replay *replay;
+ int i;
+ unsigned int panel_inst;
+ struct replay_context replay_context = { 0 };
+ unsigned int lineTimeInNs = 0;
+
+ union panel_replay_enable_and_configuration_1 pr_config_1 = { 0 };
+ union panel_replay_enable_and_configuration_2 pr_config_2 = { 0 };
+
+ union dpcd_alpm_configuration alpm_config;
+
+ replay_context.controllerId = CONTROLLER_ID_UNDEFINED;
+
+ if (!link)
+ return false;
+
+ //Clear Panel Replay enable & config
+ dm_helpers_dp_write_dpcd(link->ctx, link,
+ DP_PANEL_REPLAY_ENABLE_AND_CONFIGURATION_1,
+ (uint8_t *)&(pr_config_1.raw), sizeof(uint8_t));
+
+ dm_helpers_dp_write_dpcd(link->ctx, link,
+ DP_PANEL_REPLAY_ENABLE_AND_CONFIGURATION_2,
+ (uint8_t *)&(pr_config_2.raw), sizeof(uint8_t));
+
+ if (!(link->replay_settings.config.replay_supported))
+ return false;
+
+ dc = link->ctx->dc;
+
+ //not sure should keep or not
+ replay = dc->res_pool->replay;
+
+ if (!replay)
+ return false;
+
+ if (!dp_pr_get_panel_inst(dc, link, &panel_inst))
+ return false;
+
+ replay_context.aux_inst = link->ddc->ddc_pin->hw_info.ddc_channel;
+ replay_context.digbe_inst = link->link_enc->transmitter;
+ replay_context.digfe_inst = link->link_enc->preferred_engine;
+
+ for (i = 0; i < MAX_PIPES; i++) {
+ if (dc->current_state->res_ctx.pipe_ctx[i].stream
+ == stream) {
+ /* dmcu -1 for all controller id values,
+ * therefore +1 here
+ */
+ replay_context.controllerId =
+ dc->current_state->res_ctx.pipe_ctx[i].stream_res.tg->inst + 1;
+ break;
+ }
+ }
+
+ lineTimeInNs =
+ ((stream->timing.h_total * 1000000) /
+ (stream->timing.pix_clk_100hz / 10)) + 1;
+
+ replay_context.line_time_in_ns = lineTimeInNs;
+
+ link->replay_settings.replay_feature_enabled = dp_pr_copy_settings(link, &replay_context);
+
+ if (link->replay_settings.replay_feature_enabled) {
+ if (dc_is_embedded_signal(link->connector_signal)) {
+ pr_config_1.bits.PANEL_REPLAY_ENABLE = 1;
+ pr_config_1.bits.PANEL_REPLAY_CRC_ENABLE = 1;
+ pr_config_1.bits.IRQ_HPD_ASSDP_MISSING = 1;
+ pr_config_1.bits.IRQ_HPD_VSCSDP_UNCORRECTABLE_ERROR = 1;
+ pr_config_1.bits.IRQ_HPD_RFB_ERROR = 1;
+ pr_config_1.bits.IRQ_HPD_ACTIVE_FRAME_CRC_ERROR = 1;
+ pr_config_1.bits.PANEL_REPLAY_SELECTIVE_UPDATE_ENABLE = 1;
+ pr_config_1.bits.PANEL_REPLAY_EARLY_TRANSPORT_ENABLE = 1;
+ } else {
+ pr_config_1.bits.PANEL_REPLAY_ENABLE = 1;
+ }
+
+ pr_config_2.bits.SINK_REFRESH_RATE_UNLOCK_GRANTED = 0;
+
+ if (link->dpcd_caps.vesa_replay_caps.bits.SU_Y_GRANULARITY_EXT_CAP_SUPPORTED)
+ pr_config_2.bits.SU_Y_GRANULARITY_EXT_VALUE_ENABLED = 1;
+
+ pr_config_2.bits.SU_REGION_SCAN_LINE_CAPTURE_INDICATION = 0;
+
+ dm_helpers_dp_write_dpcd(link->ctx, link,
+ DP_PANEL_REPLAY_ENABLE_AND_CONFIGURATION_1,
+ (uint8_t *)&(pr_config_1.raw), sizeof(uint8_t));
+
+ dm_helpers_dp_write_dpcd(link->ctx, link,
+ DP_PANEL_REPLAY_ENABLE_AND_CONFIGURATION_2,
+ (uint8_t *)&(pr_config_2.raw), sizeof(uint8_t));
+
+ //ALPM Setup
+ memset(&alpm_config, 0, sizeof(alpm_config));
+ alpm_config.bits.ENABLE = link->replay_settings.config.alpm_mode != DC_ALPM_UNSUPPORTED ? 1 : 0;
+
+ if (link->replay_settings.config.alpm_mode == DC_ALPM_AUXLESS) {
+ alpm_config.bits.ALPM_MODE_SEL = 1;
+ alpm_config.bits.ACDS_PERIOD_DURATION = 1;
+ }
+
+ dm_helpers_dp_write_dpcd(
+ link->ctx,
+ link,
+ DP_RECEIVER_ALPM_CONFIG,
+ &alpm_config.raw,
+ sizeof(alpm_config.raw));
+ }
+
+ return true;
+}
+
+
+bool dp_pr_get_panel_inst(const struct dc *dc,
+ const struct dc_link *link,
+ unsigned int *inst_out)
+{
+ if (!dc || !link || !inst_out)
+ return false;
+
+ if (!dc_is_dp_sst_signal(link->connector_signal)) /* only supoprt DP sst (eDP included) for now */
+ return false;
+
+ for (unsigned int i = 0; i < MAX_PIPES; i++) {
+ if (dc->current_state->res_ctx.pipe_ctx[i].stream &&
+ dc->current_state->res_ctx.pipe_ctx[i].stream->link == link) {
+ /* *inst_out is equal to otg number */
+ if (dc->current_state->res_ctx.pipe_ctx[i].stream_res.tg)
+ *inst_out = dc->current_state->res_ctx.pipe_ctx[i].stream_res.tg->inst;
+ else
+ *inst_out = 0;
+
+ return true;
+ }
+ }
+
+ return false;
+}
+
+bool dp_setup_replay(struct dc_link *link, const struct dc_stream_state *stream)
+{
+ if (!link)
+ return false;
+ if (link->replay_settings.config.replay_version == DC_VESA_PANEL_REPLAY)
+ return dp_setup_panel_replay(link, stream);
+ else if (link->replay_settings.config.replay_version == DC_FREESYNC_REPLAY)
+ return edp_setup_freesync_replay(link, stream);
+ else
+ return false;
+}
+
+bool dp_pr_enable(struct dc_link *link, bool enable)
+{
+ struct dc *dc = link->ctx->dc;
+ unsigned int panel_inst = 0;
+ union dmub_rb_cmd cmd;
+
+ if (!dp_pr_get_panel_inst(dc, link, &panel_inst))
+ return false;
+
+ if (link->replay_settings.replay_allow_active != enable) {
+ //for sending PR enable commands to DMUB
+ memset(&cmd, 0, sizeof(cmd));
+
+ cmd.pr_enable.header.type = DMUB_CMD__PR;
+ cmd.pr_enable.header.sub_type = DMUB_CMD__PR_ENABLE;
+ cmd.pr_enable.header.payload_bytes = sizeof(struct dmub_cmd_pr_enable_data);
+ cmd.pr_enable.data.panel_inst = panel_inst;
+ cmd.pr_enable.data.enable = enable ? 1 : 0;
+
+ dc_wake_and_execute_dmub_cmd(dc->ctx, &cmd, DM_DMUB_WAIT_TYPE_WAIT);
+
+ link->replay_settings.replay_allow_active = enable;
+ }
+ return true;
+}
+
+bool dp_pr_copy_settings(struct dc_link *link, struct replay_context *replay_context)
+{
+ struct dc *dc = link->ctx->dc;
+ unsigned int panel_inst = 0;
+ union dmub_rb_cmd cmd;
+ struct pipe_ctx *pipe_ctx = NULL;
+
+ if (!dp_pr_get_panel_inst(dc, link, &panel_inst))
+ return false;
+
+ for (unsigned int i = 0; i < MAX_PIPES; i++) {
+ if (dc->current_state->res_ctx.pipe_ctx[i].stream &&
+ dc->current_state->res_ctx.pipe_ctx[i].stream->link &&
+ dc->current_state->res_ctx.pipe_ctx[i].stream->link == link &&
+ dc_is_dp_sst_signal(dc->current_state->res_ctx.pipe_ctx[i].stream->link->connector_signal)) {
+ pipe_ctx = &dc->current_state->res_ctx.pipe_ctx[i];
+ /* todo: need update for MST */
+ break;
+ }
+ }
+
+ if (!pipe_ctx)
+ return false;
+
+ memset(&cmd, 0, sizeof(cmd));
+ cmd.pr_copy_settings.header.type = DMUB_CMD__PR;
+ cmd.pr_copy_settings.header.sub_type = DMUB_CMD__PR_COPY_SETTINGS;
+ cmd.pr_copy_settings.header.payload_bytes = sizeof(struct dmub_cmd_pr_copy_settings_data);
+ cmd.pr_copy_settings.data.panel_inst = panel_inst;
+ // HW inst
+ cmd.pr_copy_settings.data.aux_inst = replay_context->aux_inst;
+ cmd.pr_copy_settings.data.digbe_inst = replay_context->digbe_inst;
+ cmd.pr_copy_settings.data.digfe_inst = replay_context->digfe_inst;
+ if (pipe_ctx->plane_res.dpp)
+ cmd.pr_copy_settings.data.dpp_inst = pipe_ctx->plane_res.dpp->inst;
+ else
+ cmd.pr_copy_settings.data.dpp_inst = 0;
+ if (pipe_ctx->stream_res.tg)
+ cmd.pr_copy_settings.data.otg_inst = pipe_ctx->stream_res.tg->inst;
+ else
+ cmd.pr_copy_settings.data.otg_inst = 0;
+
+ cmd.pr_copy_settings.data.dpphy_inst = link->link_enc->transmitter;
+
+ cmd.pr_copy_settings.data.line_time_in_ns = replay_context->line_time_in_ns;
+ cmd.pr_copy_settings.data.flags.bitfields.fec_enable_status = (link->fec_state == dc_link_fec_enabled);
+ cmd.pr_copy_settings.data.flags.bitfields.dsc_enable_status = (pipe_ctx->stream->timing.flags.DSC == 1);
+ cmd.pr_copy_settings.data.debug.u32All = link->replay_settings.config.debug_flags;
+
+ cmd.pr_copy_settings.data.su_granularity_needed = link->dpcd_caps.vesa_replay_caps.bits.PR_SU_GRANULARITY_NEEDED;
+ cmd.pr_copy_settings.data.su_x_granularity = link->dpcd_caps.vesa_replay_su_info.pr_su_x_granularity;
+ cmd.pr_copy_settings.data.su_y_granularity = link->dpcd_caps.vesa_replay_su_info.pr_su_y_granularity;
+ cmd.pr_copy_settings.data.su_y_granularity_extended_caps =
+ link->dpcd_caps.vesa_replay_su_info.pr_su_y_granularity_extended_caps;
+
+ if (pipe_ctx->stream->timing.dsc_cfg.num_slices_v > 0)
+ cmd.pr_copy_settings.data.dsc_slice_height = (pipe_ctx->stream->timing.v_addressable +
+ pipe_ctx->stream->timing.v_border_top + pipe_ctx->stream->timing.v_border_bottom) /
+ pipe_ctx->stream->timing.dsc_cfg.num_slices_v;
+
+ dc_wake_and_execute_dmub_cmd(dc->ctx, &cmd, DM_DMUB_WAIT_TYPE_WAIT);
+ return true;
+}
+
+bool dp_pr_update_state(struct dc_link *link, struct dmub_cmd_pr_update_state_data *update_state_data)
+{
+ struct dc *dc = link->ctx->dc;
+ unsigned int panel_inst = 0;
+ union dmub_rb_cmd cmd;
+
+ if (!dp_pr_get_panel_inst(dc, link, &panel_inst))
+ return false;
+
+ memset(&cmd, 0, sizeof(cmd));
+ memcpy(&cmd.pr_update_state.data, update_state_data, sizeof(struct dmub_cmd_pr_update_state_data));
+
+ cmd.pr_update_state.header.type = DMUB_CMD__PR;
+ cmd.pr_update_state.header.sub_type = DMUB_CMD__PR_UPDATE_STATE;
+ cmd.pr_update_state.header.payload_bytes = sizeof(struct dmub_cmd_pr_update_state_data);
+ cmd.pr_update_state.data.panel_inst = panel_inst;
+
+ dc_wake_and_execute_dmub_cmd(dc->ctx, &cmd, DM_DMUB_WAIT_TYPE_WAIT);
+ return true;
+}
+
+bool dp_pr_set_general_cmd(struct dc_link *link, struct dmub_cmd_pr_general_cmd_data *general_cmd_data)
+{
+ struct dc *dc = link->ctx->dc;
+ unsigned int panel_inst = 0;
+ union dmub_rb_cmd cmd;
+
+ if (!dp_pr_get_panel_inst(dc, link, &panel_inst))
+ return false;
+
+ memset(&cmd, 0, sizeof(cmd));
+ memcpy(&cmd.pr_general_cmd.data, general_cmd_data, sizeof(struct dmub_cmd_pr_general_cmd_data));
+
+ cmd.pr_general_cmd.header.type = DMUB_CMD__PR;
+ cmd.pr_general_cmd.header.sub_type = DMUB_CMD__PR_GENERAL_CMD;
+ cmd.pr_general_cmd.header.payload_bytes = sizeof(struct dmub_cmd_pr_general_cmd_data);
+ cmd.pr_general_cmd.data.panel_inst = panel_inst;
+
+ dc_wake_and_execute_dmub_cmd(dc->ctx, &cmd, DM_DMUB_WAIT_TYPE_WAIT);
+ return true;
+}
+
+bool dp_pr_get_state(const struct dc_link *link, uint64_t *state)
+{
+ const struct dc *dc = link->ctx->dc;
+ unsigned int panel_inst = 0;
+ uint32_t retry_count = 0;
+ uint32_t replay_state = 0;
+
+ if (!dp_pr_get_panel_inst(dc, link, &panel_inst))
+ return false;
+
+ do {
+ // Send gpint command and wait for ack
+ if (!dc_wake_and_execute_gpint(dc->ctx, DMUB_GPINT__GET_REPLAY_STATE, panel_inst,
+ &replay_state, DM_DMUB_WAIT_TYPE_WAIT_WITH_REPLY)) {
+ // Return invalid state when GPINT times out
+ replay_state = PR_STATE_INVALID;
+ }
+ /* Copy 32-bit result into 64-bit output */
+ *state = replay_state;
+ } while (++retry_count <= 1000 && *state == PR_STATE_INVALID);
+
+ // Assert if max retry hit
+ if (retry_count >= 1000 && *state == PR_STATE_INVALID) {
+ ASSERT(0);
+ /* To-do: Add retry fail log */
+ }
+
+ return true;
+}
diff --git a/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_panel_replay.h b/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_panel_replay.h
new file mode 100644
index 000000000000..5522d5911fd1
--- /dev/null
+++ b/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_panel_replay.h
@@ -0,0 +1,38 @@
+/*
+ * Copyright 2025 Advanced Micro Devices, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+#ifndef __DC_LINK_DP_PANEL_REPLAY_H__
+#define __DC_LINK_DP_PANEL_REPLAY_H__
+
+#include "link_service.h"
+
+bool dp_setup_replay(struct dc_link *link, const struct dc_stream_state *stream);
+bool dp_pr_get_panel_inst(const struct dc *dc, const struct dc_link *link, unsigned int *inst_out);
+bool dp_pr_enable(struct dc_link *link, bool enable);
+bool dp_pr_copy_settings(struct dc_link *link, struct replay_context *replay_context);
+bool dp_pr_update_state(struct dc_link *link, struct dmub_cmd_pr_update_state_data *update_state_data);
+bool dp_pr_set_general_cmd(struct dc_link *link, struct dmub_cmd_pr_general_cmd_data *general_cmd_data);
+bool dp_pr_get_state(const struct dc_link *link, uint64_t *state);
+
+#endif /* __DC_LINK_DP_PANEL_REPLAY_H__ */ \ No newline at end of file
diff --git a/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_training_fixed_vs_pe_retimer.c b/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_training_fixed_vs_pe_retimer.c
index ce174ce5579c..6a7c4a59ff4c 100644
--- a/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_training_fixed_vs_pe_retimer.c
+++ b/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_training_fixed_vs_pe_retimer.c
@@ -271,7 +271,7 @@ enum link_training_result dp_perform_fixed_vs_pe_training_sequence(
rate = get_dpcd_link_rate(&lt_settings->link_settings);
// Only perform toggle if FIXED_VS LTTPR reports no IEEE OUI
- if (memcmp("\x0,\x0,\x0", &link->dpcd_caps.lttpr_caps.lttpr_ieee_oui[0], 3) == 0) {
+ if (memcmp("\x00\x00\x00", &link->dpcd_caps.lttpr_caps.lttpr_ieee_oui[0], 3) == 0) {
/* Vendor specific: Toggle link rate */
toggle_rate = (rate == 0x6) ? 0xA : 0x6;
diff --git a/drivers/gpu/drm/amd/display/dc/link/protocols/link_edp_panel_control.c b/drivers/gpu/drm/amd/display/dc/link/protocols/link_edp_panel_control.c
index c56e69eb27ef..aa02b38e183a 100644
--- a/drivers/gpu/drm/amd/display/dc/link/protocols/link_edp_panel_control.c
+++ b/drivers/gpu/drm/amd/display/dc/link/protocols/link_edp_panel_control.c
@@ -39,6 +39,7 @@
#include "dce/dmub_replay.h"
#include "abm.h"
#include "resource.h"
+#include "link_dp_panel_replay.h"
#define DC_LOGGER \
link->ctx->logger
#define DC_LOGGER_INIT(logger)
@@ -91,11 +92,10 @@ void dp_set_panel_mode(struct dc_link *link, enum dp_panel_mode panel_mode)
}
link->panel_mode = panel_mode;
- DC_LOG_DETECTION_DP_CAPS("Link: %d eDP panel mode supported: %d "
- "eDP panel mode enabled: %d \n",
- link->link_index,
- link->dpcd_caps.panel_mode_edp,
- panel_mode_edp);
+ DC_LOG_DETECTION_DP_CAPS("%d eDP panel mode supported: %d, enabled: %d\n",
+ link->link_index,
+ link->dpcd_caps.panel_mode_edp,
+ panel_mode_edp);
}
enum dp_panel_mode dp_get_panel_mode(struct dc_link *link)
@@ -943,7 +943,7 @@ bool edp_set_replay_allow_active(struct dc_link *link, const bool *allow_active,
if (replay == NULL && force_static)
return false;
- if (!dc_get_edp_link_panel_inst(dc, link, &panel_inst))
+ if (!dp_pr_get_panel_inst(dc, link, &panel_inst))
return false;
/* Set power optimization flag */
@@ -974,7 +974,7 @@ bool edp_get_replay_state(const struct dc_link *link, uint64_t *state)
unsigned int panel_inst;
enum replay_state pr_state = REPLAY_STATE_0;
- if (!dc_get_edp_link_panel_inst(dc, link, &panel_inst))
+ if (!dp_pr_get_panel_inst(dc, link, &panel_inst))
return false;
if (replay != NULL && link->replay_settings.replay_feature_enabled)
@@ -984,117 +984,8 @@ bool edp_get_replay_state(const struct dc_link *link, uint64_t *state)
return true;
}
-static bool edp_setup_panel_replay(struct dc_link *link, const struct dc_stream_state *stream)
-{
- /* To-do: Setup Replay */
- struct dc *dc;
- struct dmub_replay *replay;
- int i;
- unsigned int panel_inst;
- struct replay_context replay_context = { 0 };
- unsigned int lineTimeInNs = 0;
-
- union panel_replay_enable_and_configuration_1 pr_config_1 = { 0 };
- union panel_replay_enable_and_configuration_2 pr_config_2 = { 0 };
-
- union dpcd_alpm_configuration alpm_config;
-
- replay_context.controllerId = CONTROLLER_ID_UNDEFINED;
-
- if (!link)
- return false;
-
- //Clear Panel Replay enable & config
- dm_helpers_dp_write_dpcd(link->ctx, link,
- DP_PANEL_REPLAY_ENABLE_AND_CONFIGURATION_1,
- (uint8_t *)&(pr_config_1.raw), sizeof(uint8_t));
-
- dm_helpers_dp_write_dpcd(link->ctx, link,
- DP_PANEL_REPLAY_ENABLE_AND_CONFIGURATION_2,
- (uint8_t *)&(pr_config_2.raw), sizeof(uint8_t));
-
- if (!(link->replay_settings.config.replay_supported))
- return false;
-
- dc = link->ctx->dc;
-
- //not sure should keep or not
- replay = dc->res_pool->replay;
-
- if (!replay)
- return false;
-
- if (!dc_get_edp_link_panel_inst(dc, link, &panel_inst))
- return false;
-
- replay_context.aux_inst = link->ddc->ddc_pin->hw_info.ddc_channel;
- replay_context.digbe_inst = link->link_enc->transmitter;
- replay_context.digfe_inst = link->link_enc->preferred_engine;
- for (i = 0; i < MAX_PIPES; i++) {
- if (dc->current_state->res_ctx.pipe_ctx[i].stream
- == stream) {
- /* dmcu -1 for all controller id values,
- * therefore +1 here
- */
- replay_context.controllerId =
- dc->current_state->res_ctx.pipe_ctx[i].stream_res.tg->inst + 1;
- break;
- }
- }
-
- lineTimeInNs =
- ((stream->timing.h_total * 1000000) /
- (stream->timing.pix_clk_100hz / 10)) + 1;
-
- replay_context.line_time_in_ns = lineTimeInNs;
-
- link->replay_settings.replay_feature_enabled =
- replay->funcs->replay_copy_settings(replay, link, &replay_context, panel_inst);
-
- if (link->replay_settings.replay_feature_enabled) {
- pr_config_1.bits.PANEL_REPLAY_ENABLE = 1;
- pr_config_1.bits.PANEL_REPLAY_CRC_ENABLE = 1;
- pr_config_1.bits.IRQ_HPD_ASSDP_MISSING = 1;
- pr_config_1.bits.IRQ_HPD_VSCSDP_UNCORRECTABLE_ERROR = 1;
- pr_config_1.bits.IRQ_HPD_RFB_ERROR = 1;
- pr_config_1.bits.IRQ_HPD_ACTIVE_FRAME_CRC_ERROR = 1;
- pr_config_1.bits.PANEL_REPLAY_SELECTIVE_UPDATE_ENABLE = 1;
- pr_config_1.bits.PANEL_REPLAY_EARLY_TRANSPORT_ENABLE = 1;
-
- pr_config_2.bits.SINK_REFRESH_RATE_UNLOCK_GRANTED = 0;
- pr_config_2.bits.SU_Y_GRANULARITY_EXT_VALUE_ENABLED = 0;
- pr_config_2.bits.SU_REGION_SCAN_LINE_CAPTURE_INDICATION = 0;
-
- dm_helpers_dp_write_dpcd(link->ctx, link,
- DP_PANEL_REPLAY_ENABLE_AND_CONFIGURATION_1,
- (uint8_t *)&(pr_config_1.raw), sizeof(uint8_t));
-
- dm_helpers_dp_write_dpcd(link->ctx, link,
- DP_PANEL_REPLAY_ENABLE_AND_CONFIGURATION_2,
- (uint8_t *)&(pr_config_2.raw), sizeof(uint8_t));
-
- //ALPM Setup
- memset(&alpm_config, 0, sizeof(alpm_config));
- alpm_config.bits.ENABLE = link->replay_settings.config.alpm_mode != DC_ALPM_UNSUPPORTED ? 1 : 0;
-
- if (link->replay_settings.config.alpm_mode == DC_ALPM_AUXLESS) {
- alpm_config.bits.ALPM_MODE_SEL = 1;
- alpm_config.bits.ACDS_PERIOD_DURATION = 1;
- }
-
- dm_helpers_dp_write_dpcd(
- link->ctx,
- link,
- DP_RECEIVER_ALPM_CONFIG,
- &alpm_config.raw,
- sizeof(alpm_config.raw));
- }
-
- return true;
-}
-
-static bool edp_setup_freesync_replay(struct dc_link *link, const struct dc_stream_state *stream)
+bool edp_setup_freesync_replay(struct dc_link *link, const struct dc_stream_state *stream)
{
/* To-do: Setup Replay */
struct dc *dc;
@@ -1130,7 +1021,7 @@ static bool edp_setup_freesync_replay(struct dc_link *link, const struct dc_stre
if (!replay)
return false;
- if (!dc_get_edp_link_panel_inst(dc, link, &panel_inst))
+ if (!dp_pr_get_panel_inst(dc, link, &panel_inst))
return false;
replay_context.aux_inst = link->ddc->ddc_pin->hw_info.ddc_channel;
@@ -1190,17 +1081,6 @@ static bool edp_setup_freesync_replay(struct dc_link *link, const struct dc_stre
return true;
}
-bool edp_setup_replay(struct dc_link *link, const struct dc_stream_state *stream)
-{
- if (!link)
- return false;
- if (link->replay_settings.config.replay_version == DC_VESA_PANEL_REPLAY)
- return edp_setup_panel_replay(link, stream);
- else if (link->replay_settings.config.replay_version == DC_FREESYNC_REPLAY)
- return edp_setup_freesync_replay(link, stream);
- else
- return false;
-}
/*
* This is general Interface for Replay to set an 32 bit variable to dmub
@@ -1220,7 +1100,7 @@ bool edp_send_replay_cmd(struct dc_link *link,
DC_LOGGER_INIT(link->ctx->logger);
- if (dc_get_edp_link_panel_inst(dc, link, &panel_inst))
+ if (dp_pr_get_panel_inst(dc, link, &panel_inst))
cmd_data->panel_inst = panel_inst;
else {
DC_LOG_DC("%s(): get edp panel inst fail ", __func__);
@@ -1241,7 +1121,7 @@ bool edp_set_coasting_vtotal(struct dc_link *link, uint32_t coasting_vtotal, uin
if (!replay)
return false;
- if (!dc_get_edp_link_panel_inst(dc, link, &panel_inst))
+ if (!dp_pr_get_panel_inst(dc, link, &panel_inst))
return false;
if (coasting_vtotal && (link->replay_settings.coasting_vtotal != coasting_vtotal ||
@@ -1261,7 +1141,7 @@ bool edp_replay_residency(const struct dc_link *link,
struct dmub_replay *replay = dc->res_pool->replay;
unsigned int panel_inst;
- if (!dc_get_edp_link_panel_inst(dc, link, &panel_inst))
+ if (!dp_pr_get_panel_inst(dc, link, &panel_inst))
return false;
if (!residency)
@@ -1282,7 +1162,7 @@ bool edp_set_replay_power_opt_and_coasting_vtotal(struct dc_link *link,
struct dmub_replay *replay = dc->res_pool->replay;
unsigned int panel_inst;
- if (!dc_get_edp_link_panel_inst(dc, link, &panel_inst))
+ if (!dp_pr_get_panel_inst(dc, link, &panel_inst))
return false;
/* Only both power and coasting vtotal changed, this func could return true */
@@ -1305,6 +1185,7 @@ bool edp_set_replay_power_opt_and_coasting_vtotal(struct dc_link *link,
return true;
}
+
static struct abm *get_abm_from_stream_res(const struct dc_link *link)
{
int i;
diff --git a/drivers/gpu/drm/amd/display/dc/link/protocols/link_edp_panel_control.h b/drivers/gpu/drm/amd/display/dc/link/protocols/link_edp_panel_control.h
index dd79c7cd2828..8fdb76d9953e 100644
--- a/drivers/gpu/drm/amd/display/dc/link/protocols/link_edp_panel_control.h
+++ b/drivers/gpu/drm/amd/display/dc/link/protocols/link_edp_panel_control.h
@@ -54,8 +54,6 @@ bool edp_set_sink_vtotal_in_psr_active(const struct dc_link *link,
void edp_get_psr_residency(const struct dc_link *link, uint32_t *residency, enum psr_residency_mode mode);
bool edp_set_replay_allow_active(struct dc_link *dc_link, const bool *enable,
bool wait, bool force_static, const unsigned int *power_opts);
-bool edp_setup_replay(struct dc_link *link,
- const struct dc_stream_state *stream);
bool edp_send_replay_cmd(struct dc_link *link,
enum replay_FW_Message_type msg,
union dmub_replay_cmd_set *cmd_data);
@@ -75,6 +73,7 @@ void edp_add_delay_for_T9(struct dc_link *link);
bool edp_receiver_ready_T9(struct dc_link *link);
bool edp_receiver_ready_T7(struct dc_link *link);
bool edp_power_alpm_dpcd_enable(struct dc_link *link, bool enable);
+bool edp_setup_freesync_replay(struct dc_link *link, const struct dc_stream_state *stream);
void edp_set_panel_power(struct dc_link *link, bool powerOn);
void edp_set_panel_assr(struct dc_link *link, struct pipe_ctx *pipe_ctx,
enum dp_panel_mode *panel_mode, bool enable);
diff --git a/drivers/gpu/drm/amd/display/dc/link/protocols/link_hpd.c b/drivers/gpu/drm/amd/display/dc/link/protocols/link_hpd.c
index caa617883f62..29f3a03687b2 100644
--- a/drivers/gpu/drm/amd/display/dc/link/protocols/link_hpd.c
+++ b/drivers/gpu/drm/amd/display/dc/link/protocols/link_hpd.c
@@ -35,62 +35,75 @@
bool link_get_hpd_state(struct dc_link *link)
{
- uint32_t state = 0;
-
- dal_gpio_lock_pin(link->hpd_gpio);
- dal_gpio_get_value(link->hpd_gpio, &state);
- dal_gpio_unlock_pin(link->hpd_gpio);
-
- return state;
+ if (link->link_enc)
+ return link->link_enc->funcs->get_hpd_state(link->link_enc);
+ else
+ return false;
}
void link_enable_hpd(const struct dc_link *link)
{
- struct link_encoder *encoder = link->link_enc;
-
- if (encoder != NULL && encoder->funcs->enable_hpd != NULL)
- encoder->funcs->enable_hpd(encoder);
+ if (link->link_enc)
+ link->link_enc->funcs->enable_hpd(link->link_enc);
}
void link_disable_hpd(const struct dc_link *link)
{
- struct link_encoder *encoder = link->link_enc;
-
- if (encoder != NULL && encoder->funcs->enable_hpd != NULL)
- encoder->funcs->disable_hpd(encoder);
+ if (link->link_enc)
+ link->link_enc->funcs->disable_hpd(link->link_enc);
}
void link_enable_hpd_filter(struct dc_link *link, bool enable)
{
- struct gpio *hpd;
-
if (enable) {
link->is_hpd_filter_disabled = false;
program_hpd_filter(link);
} else {
link->is_hpd_filter_disabled = true;
- /* Obtain HPD handle */
- hpd = link_get_hpd_gpio(link->ctx->dc_bios, link->link_id, link->ctx->gpio_service);
-
- if (!hpd)
- return;
-
- /* Setup HPD filtering */
- if (dal_gpio_open(hpd, GPIO_MODE_INTERRUPT) == GPIO_RESULT_OK) {
- struct gpio_hpd_config config;
+ if (link->link_enc)
+ link->link_enc->funcs->program_hpd_filter(link->link_enc, 0, 0);
+ }
+}
- config.delay_on_connect = 0;
- config.delay_on_disconnect = 0;
+bool program_hpd_filter(const struct dc_link *link)
+{
+ int delay_on_connect_in_ms = 0;
+ int delay_on_disconnect_in_ms = 0;
- dal_irq_setup_hpd_filter(hpd, &config);
+ if (link->is_hpd_filter_disabled || !link->link_enc) {
+ ASSERT(link->link_enc);
+ return false;
+ }
- dal_gpio_close(hpd);
- } else {
- ASSERT_CRITICAL(false);
- }
- /* Release HPD handle */
- dal_gpio_destroy_irq(&hpd);
+ /* Verify feature is supported */
+ switch (link->connector_signal) {
+ case SIGNAL_TYPE_DVI_SINGLE_LINK:
+ case SIGNAL_TYPE_DVI_DUAL_LINK:
+ case SIGNAL_TYPE_HDMI_TYPE_A:
+ /* Program hpd filter */
+ delay_on_connect_in_ms = 500;
+ delay_on_disconnect_in_ms = 100;
+ break;
+ case SIGNAL_TYPE_DISPLAY_PORT:
+ case SIGNAL_TYPE_DISPLAY_PORT_MST:
+ /* Program hpd filter to allow DP signal to settle */
+ /* 500: not able to detect MST <-> SST switch as HPD is low for
+ * only 100ms on DELL U2413
+ * 0: some passive dongle still show aux mode instead of i2c
+ * 20-50: not enough to hide bouncing HPD with passive dongle.
+ * also see intermittent i2c read issues.
+ */
+ delay_on_connect_in_ms = 80;
+ delay_on_disconnect_in_ms = 0;
+ break;
+ case SIGNAL_TYPE_LVDS:
+ case SIGNAL_TYPE_EDP:
+ default:
+ /* Don't program hpd filter */
+ return false;
}
+
+ return link->link_enc->funcs->program_hpd_filter(link->link_enc, delay_on_connect_in_ms, delay_on_disconnect_in_ms);
}
struct gpio *link_get_hpd_gpio(struct dc_bios *dcb,
@@ -108,7 +121,6 @@ struct gpio *link_get_hpd_gpio(struct dc_bios *dcb,
hpd_info.hpd_int_gpio_uid, &pin_info);
if (bp_result != BP_RESULT_OK) {
- ASSERT(bp_result == BP_RESULT_NORECORD);
return NULL;
}
@@ -117,21 +129,6 @@ struct gpio *link_get_hpd_gpio(struct dc_bios *dcb,
pin_info.mask);
}
-bool query_hpd_status(struct dc_link *link, uint32_t *is_hpd_high)
-{
- struct gpio *hpd_pin = link_get_hpd_gpio(
- link->ctx->dc_bios, link->link_id,
- link->ctx->gpio_service);
- if (!hpd_pin)
- return false;
-
- dal_gpio_open(hpd_pin, GPIO_MODE_INTERRUPT);
- dal_gpio_get_value(hpd_pin, is_hpd_high);
- dal_gpio_close(hpd_pin);
- dal_gpio_destroy_irq(&hpd_pin);
- return true;
-}
-
enum hpd_source_id get_hpd_line(struct dc_link *link)
{
struct gpio *hpd;
@@ -172,69 +169,3 @@ enum hpd_source_id get_hpd_line(struct dc_link *link)
return hpd_id;
}
-
-bool program_hpd_filter(const struct dc_link *link)
-{
- bool result = false;
- struct gpio *hpd;
- int delay_on_connect_in_ms = 0;
- int delay_on_disconnect_in_ms = 0;
-
- if (link->is_hpd_filter_disabled)
- return false;
- /* Verify feature is supported */
- switch (link->connector_signal) {
- case SIGNAL_TYPE_DVI_SINGLE_LINK:
- case SIGNAL_TYPE_DVI_DUAL_LINK:
- case SIGNAL_TYPE_HDMI_TYPE_A:
- /* Program hpd filter */
- delay_on_connect_in_ms = 500;
- delay_on_disconnect_in_ms = 100;
- break;
- case SIGNAL_TYPE_DISPLAY_PORT:
- case SIGNAL_TYPE_DISPLAY_PORT_MST:
- /* Program hpd filter to allow DP signal to settle */
- /* 500: not able to detect MST <-> SST switch as HPD is low for
- * only 100ms on DELL U2413
- * 0: some passive dongle still show aux mode instead of i2c
- * 20-50: not enough to hide bouncing HPD with passive dongle.
- * also see intermittent i2c read issues.
- */
- delay_on_connect_in_ms = 80;
- delay_on_disconnect_in_ms = 0;
- break;
- case SIGNAL_TYPE_LVDS:
- case SIGNAL_TYPE_EDP:
- default:
- /* Don't program hpd filter */
- return false;
- }
-
- /* Obtain HPD handle */
- hpd = link_get_hpd_gpio(link->ctx->dc_bios, link->link_id,
- link->ctx->gpio_service);
-
- if (!hpd)
- return result;
-
- /* Setup HPD filtering */
- if (dal_gpio_open(hpd, GPIO_MODE_INTERRUPT) == GPIO_RESULT_OK) {
- struct gpio_hpd_config config;
-
- config.delay_on_connect = delay_on_connect_in_ms;
- config.delay_on_disconnect = delay_on_disconnect_in_ms;
-
- dal_irq_setup_hpd_filter(hpd, &config);
-
- dal_gpio_close(hpd);
-
- result = true;
- } else {
- ASSERT_CRITICAL(false);
- }
-
- /* Release HPD handle */
- dal_gpio_destroy_irq(&hpd);
-
- return result;
-}
diff --git a/drivers/gpu/drm/amd/display/dc/link/protocols/link_hpd.h b/drivers/gpu/drm/amd/display/dc/link/protocols/link_hpd.h
index af529328ba17..b4e449de960e 100644
--- a/drivers/gpu/drm/amd/display/dc/link/protocols/link_hpd.h
+++ b/drivers/gpu/drm/amd/display/dc/link/protocols/link_hpd.h
@@ -43,7 +43,6 @@ bool program_hpd_filter(const struct dc_link *link);
* Returns true if HPD high.
*/
bool dpia_query_hpd_status(struct dc_link *link);
-bool query_hpd_status(struct dc_link *link, uint32_t *is_hpd_high);
bool link_get_hpd_state(struct dc_link *link);
struct gpio *link_get_hpd_gpio(struct dc_bios *dcb,
struct graphics_object_id link_id,
diff --git a/drivers/gpu/drm/amd/display/dc/os_types.h b/drivers/gpu/drm/amd/display/dc/os_types.h
index 782316348941..6af831710489 100644
--- a/drivers/gpu/drm/amd/display/dc/os_types.h
+++ b/drivers/gpu/drm/amd/display/dc/os_types.h
@@ -55,8 +55,6 @@
#if defined(CONFIG_DRM_AMD_DC_FP)
#include "amdgpu_dm/dc_fpu.h"
-#define DC_FP_START() dc_fpu_begin(__func__, __LINE__)
-#define DC_FP_END() dc_fpu_end(__func__, __LINE__)
#endif /* CONFIG_DRM_AMD_DC_FP */
/*
diff --git a/drivers/gpu/drm/amd/display/dc/resource/dce110/dce110_resource.c b/drivers/gpu/drm/amd/display/dc/resource/dce110/dce110_resource.c
index cd54382c0af3..7c09825cd9bd 100644
--- a/drivers/gpu/drm/amd/display/dc/resource/dce110/dce110_resource.c
+++ b/drivers/gpu/drm/amd/display/dc/resource/dce110/dce110_resource.c
@@ -895,6 +895,8 @@ static void get_pixel_clock_parameters(
*/
pixel_clk_params->requested_pix_clk_100hz = stream->timing.pix_clk_100hz;
pixel_clk_params->encoder_object_id = stream->link->link_enc->id;
+ if (dc_is_rgb_signal(pipe_ctx->stream->signal))
+ pixel_clk_params->encoder_object_id = stream->link->link_enc->analog_id;
pixel_clk_params->signal_type = pipe_ctx->stream->signal;
pixel_clk_params->controller_id = pipe_ctx->stream_res.tg->inst + 1;
/* TODO: un-hardcode*/
diff --git a/drivers/gpu/drm/amd/display/dc/resource/dcn20/dcn20_resource.c b/drivers/gpu/drm/amd/display/dc/resource/dcn20/dcn20_resource.c
index 6679c1a14f2f..46985eb2a623 100644
--- a/drivers/gpu/drm/amd/display/dc/resource/dcn20/dcn20_resource.c
+++ b/drivers/gpu/drm/amd/display/dc/resource/dcn20/dcn20_resource.c
@@ -1660,8 +1660,8 @@ bool dcn20_validate_dsc(struct dc *dc, struct dc_state *new_ctx)
if (pipe_ctx->top_pipe || pipe_ctx->prev_odm_pipe || !stream || !stream->timing.flags.DSC)
continue;
- dsc_cfg.pic_width = (stream->timing.h_addressable + stream->timing.h_border_left
- + stream->timing.h_border_right) / opp_cnt;
+ dsc_cfg.pic_width = (stream->timing.h_addressable + pipe_ctx->dsc_padding_params.dsc_hactive_padding
+ + stream->timing.h_border_left + stream->timing.h_border_right) / opp_cnt;
dsc_cfg.pic_height = stream->timing.v_addressable + stream->timing.v_border_top
+ stream->timing.v_border_bottom;
dsc_cfg.pixel_encoding = stream->timing.pixel_encoding;
@@ -1669,7 +1669,7 @@ bool dcn20_validate_dsc(struct dc *dc, struct dc_state *new_ctx)
dsc_cfg.is_odm = pipe_ctx->next_odm_pipe ? true : false;
dsc_cfg.dc_dsc_cfg = stream->timing.dsc_cfg;
dsc_cfg.dc_dsc_cfg.num_slices_h /= opp_cnt;
- dsc_cfg.dsc_padding = pipe_ctx->dsc_padding_params.dsc_hactive_padding;
+ dsc_cfg.dsc_padding = 0;
if (!pipe_ctx->stream_res.dsc->funcs->dsc_validate_stream(pipe_ctx->stream_res.dsc, &dsc_cfg))
return false;
@@ -2022,9 +2022,7 @@ bool dcn20_fast_validate_bw(
dcn20_merge_pipes_for_validate(dc, context);
- DC_FP_START();
pipe_cnt = dc->res_pool->funcs->populate_dml_pipes(dc, context, pipes, validate_mode);
- DC_FP_END();
*pipe_cnt_out = pipe_cnt;
diff --git a/drivers/gpu/drm/amd/display/dc/resource/dcn21/dcn21_resource.c b/drivers/gpu/drm/amd/display/dc/resource/dcn21/dcn21_resource.c
index 2060acd5ae09..967e813a45e5 100644
--- a/drivers/gpu/drm/amd/display/dc/resource/dcn21/dcn21_resource.c
+++ b/drivers/gpu/drm/amd/display/dc/resource/dcn21/dcn21_resource.c
@@ -785,9 +785,7 @@ bool dcn21_fast_validate_bw(struct dc *dc,
dcn20_merge_pipes_for_validate(dc, context);
- DC_FP_START();
pipe_cnt = dc->res_pool->funcs->populate_dml_pipes(dc, context, pipes, validate_mode);
- DC_FP_END();
*pipe_cnt_out = pipe_cnt;
diff --git a/drivers/gpu/drm/amd/display/dc/resource/dcn31/dcn31_resource.c b/drivers/gpu/drm/amd/display/dc/resource/dcn31/dcn31_resource.c
index 0d667b54ccf8..e853ea110310 100644
--- a/drivers/gpu/drm/amd/display/dc/resource/dcn31/dcn31_resource.c
+++ b/drivers/gpu/drm/amd/display/dc/resource/dcn31/dcn31_resource.c
@@ -2250,12 +2250,15 @@ enum dc_status dcn31_update_dc_state_for_encoder_switch(struct dc_link *link,
int i;
#if defined(CONFIG_DRM_AMD_DC_FP)
- for (i = 0; i < state->stream_count; i++)
- if (state->streams[i] && state->streams[i]->link && state->streams[i]->link == link)
- link->dc->hwss.calculate_pix_rate_divider((struct dc *)link->dc, state, state->streams[i]);
+ if (link->dc->hwss.calculate_pix_rate_divider) {
+ for (i = 0; i < state->stream_count; i++)
+ if (state->streams[i] && state->streams[i]->link && state->streams[i]->link == link)
+ link->dc->hwss.calculate_pix_rate_divider((struct dc *)link->dc, state, state->streams[i]);
+ }
for (i = 0; i < pipe_count; i++) {
- link->dc->res_pool->funcs->build_pipe_pix_clk_params(&pipes[i]);
+ if (link->dc->res_pool->funcs->build_pipe_pix_clk_params)
+ link->dc->res_pool->funcs->build_pipe_pix_clk_params(&pipes[i]);
// Setup audio
if (pipes[i].stream_res.audio != NULL)
diff --git a/drivers/gpu/drm/amd/display/dc/resource/dcn32/dcn32_resource.h b/drivers/gpu/drm/amd/display/dc/resource/dcn32/dcn32_resource.h
index 99f0432288b4..91be493e0bb6 100644
--- a/drivers/gpu/drm/amd/display/dc/resource/dcn32/dcn32_resource.h
+++ b/drivers/gpu/drm/amd/display/dc/resource/dcn32/dcn32_resource.h
@@ -317,7 +317,10 @@ unsigned int dcn32_get_max_hw_cursor_size(const struct dc *dc,
AUX_REG_LIST_RI(id), SRI_ARR(AUX_DPHY_TX_CONTROL, DP_AUX, id)
/* HDP */
-#define HPD_REG_LIST_RI(id) SRI_ARR(DC_HPD_CONTROL, HPD, id)
+#define HPD_REG_LIST_RI(id) \
+ (SRI_ARR(DC_HPD_CONTROL, HPD, id), \
+ SRI_ARR(DC_HPD_INT_STATUS, HPD, id), \
+ SRI_ARR(DC_HPD_TOGGLE_FILT_CNTL, HPD, id))
/* Link encoder */
#define LE_DCN3_REG_LIST_RI(id) \
diff --git a/drivers/gpu/drm/amd/display/dc/resource/dcn35/dcn35_resource.c b/drivers/gpu/drm/amd/display/dc/resource/dcn35/dcn35_resource.c
index d056e5fd5458..45454a097264 100644
--- a/drivers/gpu/drm/amd/display/dc/resource/dcn35/dcn35_resource.c
+++ b/drivers/gpu/drm/amd/display/dc/resource/dcn35/dcn35_resource.c
@@ -788,7 +788,7 @@ static const struct dc_debug_options debug_defaults_drv = {
};
static const struct dc_check_config config_defaults = {
- .enable_legacy_fast_update = true,
+ .enable_legacy_fast_update = false,
};
static const struct dc_panel_config panel_config_defaults = {
diff --git a/drivers/gpu/drm/amd/display/dc/resource/dcn351/dcn351_resource.c b/drivers/gpu/drm/amd/display/dc/resource/dcn351/dcn351_resource.c
index 9fab3169069c..e3c587165807 100644
--- a/drivers/gpu/drm/amd/display/dc/resource/dcn351/dcn351_resource.c
+++ b/drivers/gpu/drm/amd/display/dc/resource/dcn351/dcn351_resource.c
@@ -768,7 +768,7 @@ static const struct dc_debug_options debug_defaults_drv = {
};
static const struct dc_check_config config_defaults = {
- .enable_legacy_fast_update = true,
+ .enable_legacy_fast_update = false,
};
static const struct dc_panel_config panel_config_defaults = {
diff --git a/drivers/gpu/drm/amd/display/dc/resource/dcn401/dcn401_resource.c b/drivers/gpu/drm/amd/display/dc/resource/dcn401/dcn401_resource.c
index 875ae97489d3..1cdbb65da4a3 100644
--- a/drivers/gpu/drm/amd/display/dc/resource/dcn401/dcn401_resource.c
+++ b/drivers/gpu/drm/amd/display/dc/resource/dcn401/dcn401_resource.c
@@ -1772,7 +1772,7 @@ static int dcn401_get_power_profile(const struct dc_state *context)
return dpm_level;
}
-static unsigned int dcn401_get_vstartup_for_pipe(struct pipe_ctx *pipe_ctx)
+unsigned int dcn401_get_vstartup_for_pipe(struct pipe_ctx *pipe_ctx)
{
return pipe_ctx->global_sync.dcn4x.vstartup_lines;
}
diff --git a/drivers/gpu/drm/amd/display/dc/resource/dcn401/dcn401_resource.h b/drivers/gpu/drm/amd/display/dc/resource/dcn401/dcn401_resource.h
index e1fa2e80a15a..08bec1755617 100644
--- a/drivers/gpu/drm/amd/display/dc/resource/dcn401/dcn401_resource.h
+++ b/drivers/gpu/drm/amd/display/dc/resource/dcn401/dcn401_resource.h
@@ -28,6 +28,8 @@ enum dc_status dcn401_validate_bandwidth(struct dc *dc,
void dcn401_prepare_mcache_programming(struct dc *dc, struct dc_state *context);
+unsigned int dcn401_get_vstartup_for_pipe(struct pipe_ctx *pipe_ctx);
+
/* Following are definitions for run time init of reg offsets */
/* HUBP */
@@ -394,6 +396,7 @@ void dcn401_prepare_mcache_programming(struct dc *dc, struct dc_state *context);
SRI_ARR(DSCL_SC_MATRIX_C0C1, DSCL, id), \
SRI_ARR(DSCL_SC_MATRIX_C2C3, DSCL, id), \
SRI_ARR(ISHARP_MODE, DSCL, id), \
+ SRI_ARR(ISHARP_DELTA_LUT_MEM_PWR_CTRL, DSCL, id), \
SRI_ARR(ISHARP_NOISEDET_THRESHOLD, DSCL, id), \
SRI_ARR(ISHARP_NOISE_GAIN_PWL, DSCL, id), \
SRI_ARR(ISHARP_LBA_PWL_SEG0, DSCL, id), \
diff --git a/drivers/gpu/drm/amd/display/dc/sspl/dc_spl.c b/drivers/gpu/drm/amd/display/dc/sspl/dc_spl.c
index 7a839984dbc0..d8aebaff7c3f 100644
--- a/drivers/gpu/drm/amd/display/dc/sspl/dc_spl.c
+++ b/drivers/gpu/drm/amd/display/dc/sspl/dc_spl.c
@@ -7,7 +7,7 @@
#include "dc_spl_isharp_filters.h"
#include "spl_debug.h"
-#define IDENTITY_RATIO(ratio) (spl_fixpt_u3d19(ratio) == (1 << 19))
+#define IDENTITY_RATIO(ratio) (SPL_NAMESPACE(spl_fixpt_u3d19(ratio)) == (1 << 19))
#define MIN_VIEWPORT_SIZE 12
static bool spl_is_yuv420(enum spl_pixel_format format)
@@ -161,22 +161,24 @@ static struct spl_rect calculate_plane_rec_in_timing_active(
struct spl_fixed31_32 temp;
- temp = spl_fixpt_from_fraction(rec_in->x * (long long)stream_dst->width,
- stream_src->width);
+ temp = SPL_NAMESPACE(spl_fixpt_from_fraction(
+ rec_in->x * (long long)stream_dst->width,
+ stream_src->width));
rec_out.x = stream_dst->x + spl_fixpt_round(temp);
- temp = spl_fixpt_from_fraction(
+ temp = SPL_NAMESPACE(spl_fixpt_from_fraction(
(rec_in->x + rec_in->width) * (long long)stream_dst->width,
- stream_src->width);
+ stream_src->width));
rec_out.width = stream_dst->x + spl_fixpt_round(temp) - rec_out.x;
- temp = spl_fixpt_from_fraction(rec_in->y * (long long)stream_dst->height,
- stream_src->height);
+ temp = SPL_NAMESPACE(spl_fixpt_from_fraction(
+ rec_in->y * (long long)stream_dst->height,
+ stream_src->height));
rec_out.y = stream_dst->y + spl_fixpt_round(temp);
- temp = spl_fixpt_from_fraction(
+ temp = SPL_NAMESPACE(spl_fixpt_from_fraction(
(rec_in->y + rec_in->height) * (long long)stream_dst->height,
- stream_src->height);
+ stream_src->height));
rec_out.height = stream_dst->y + spl_fixpt_round(temp) - rec_out.y;
return rec_out;
@@ -224,7 +226,8 @@ static struct spl_rect calculate_mpc_slice_in_timing_active(
/* extra pixels in the division remainder need to go to pipes after
* the extra pixel index minus one(epimo) defined here as:
*/
- if (mpc_slice_idx > epimo && spl_in->basic_in.custom_width == 0) {
+ if ((use_recout_width_aligned == false) &&
+ mpc_slice_idx > epimo && spl_in->basic_in.custom_width == 0) {
mpc_rec.x += mpc_slice_idx - epimo - 1;
mpc_rec.width += 1;
}
@@ -442,12 +445,12 @@ static void spl_calculate_scaling_ratios(struct spl_in *spl_in,
spl_in->basic_in.rotation == SPL_ROTATION_ANGLE_270)
spl_swap(surf_src.height, surf_src.width);
- spl_scratch->scl_data.ratios.horz = spl_fixpt_from_fraction(
+ spl_scratch->scl_data.ratios.horz = SPL_NAMESPACE(spl_fixpt_from_fraction(
surf_src.width,
- spl_in->basic_in.dst_rect.width);
- spl_scratch->scl_data.ratios.vert = spl_fixpt_from_fraction(
+ spl_in->basic_in.dst_rect.width));
+ spl_scratch->scl_data.ratios.vert = SPL_NAMESPACE(spl_fixpt_from_fraction(
surf_src.height,
- spl_in->basic_in.dst_rect.height);
+ spl_in->basic_in.dst_rect.height));
if (spl_in->basic_out.view_format == SPL_VIEW_3D_SIDE_BY_SIDE)
spl_scratch->scl_data.ratios.horz.value *= 2;
@@ -480,14 +483,14 @@ static void spl_calculate_scaling_ratios(struct spl_in *spl_in,
* that is output/input. Currently we calculate input/output
* Store 1/ratio in recip_ratio for those lookups
*/
- spl_scratch->scl_data.recip_ratios.horz = spl_fixpt_recip(
- spl_scratch->scl_data.ratios.horz);
- spl_scratch->scl_data.recip_ratios.vert = spl_fixpt_recip(
- spl_scratch->scl_data.ratios.vert);
- spl_scratch->scl_data.recip_ratios.horz_c = spl_fixpt_recip(
- spl_scratch->scl_data.ratios.horz_c);
- spl_scratch->scl_data.recip_ratios.vert_c = spl_fixpt_recip(
- spl_scratch->scl_data.ratios.vert_c);
+ spl_scratch->scl_data.recip_ratios.horz = SPL_NAMESPACE(spl_fixpt_recip(
+ spl_scratch->scl_data.ratios.horz));
+ spl_scratch->scl_data.recip_ratios.vert = SPL_NAMESPACE(spl_fixpt_recip(
+ spl_scratch->scl_data.ratios.vert));
+ spl_scratch->scl_data.recip_ratios.horz_c = SPL_NAMESPACE(spl_fixpt_recip(
+ spl_scratch->scl_data.ratios.horz_c));
+ spl_scratch->scl_data.recip_ratios.vert_c = SPL_NAMESPACE(spl_fixpt_recip(
+ spl_scratch->scl_data.ratios.vert_c));
}
/* Calculate Viewport size */
@@ -646,11 +649,11 @@ static void spl_calculate_inits_and_viewports(struct spl_in *spl_in,
switch (spl_in->basic_in.cositing) {
case CHROMA_COSITING_TOPLEFT:
- init_adj_h = spl_fixpt_from_fraction(h_sign, 4);
- init_adj_v = spl_fixpt_from_fraction(v_sign, 4);
+ init_adj_h = SPL_NAMESPACE(spl_fixpt_from_fraction(h_sign, 4));
+ init_adj_v = SPL_NAMESPACE(spl_fixpt_from_fraction(v_sign, 4));
break;
case CHROMA_COSITING_LEFT:
- init_adj_h = spl_fixpt_from_fraction(h_sign, 4);
+ init_adj_h = SPL_NAMESPACE(spl_fixpt_from_fraction(h_sign, 4));
init_adj_v = spl_fixpt_zero;
break;
case CHROMA_COSITING_NONE:
@@ -939,16 +942,16 @@ static void spl_get_taps_non_adaptive_scaler(
* Max downscale supported is 6.0x. Add ASSERT to catch if go beyond that
*/
check_max_downscale = spl_fixpt_le(spl_scratch->scl_data.ratios.horz,
- spl_fixpt_from_fraction(6, 1));
+ SPL_NAMESPACE(spl_fixpt_from_fraction(6, 1)));
SPL_ASSERT(check_max_downscale);
check_max_downscale = spl_fixpt_le(spl_scratch->scl_data.ratios.vert,
- spl_fixpt_from_fraction(6, 1));
+ SPL_NAMESPACE(spl_fixpt_from_fraction(6, 1)));
SPL_ASSERT(check_max_downscale);
check_max_downscale = spl_fixpt_le(spl_scratch->scl_data.ratios.horz_c,
- spl_fixpt_from_fraction(6, 1));
+ SPL_NAMESPACE(spl_fixpt_from_fraction(6, 1)));
SPL_ASSERT(check_max_downscale);
check_max_downscale = spl_fixpt_le(spl_scratch->scl_data.ratios.vert_c,
- spl_fixpt_from_fraction(6, 1));
+ SPL_NAMESPACE(spl_fixpt_from_fraction(6, 1)));
SPL_ASSERT(check_max_downscale);
@@ -1194,35 +1197,39 @@ static void spl_set_manual_ratio_init_data(struct dscl_prog_data *dscl_prog_data
{
struct spl_fixed31_32 bot;
- dscl_prog_data->ratios.h_scale_ratio = spl_fixpt_u3d19(scl_data->ratios.horz) << 5;
- dscl_prog_data->ratios.v_scale_ratio = spl_fixpt_u3d19(scl_data->ratios.vert) << 5;
- dscl_prog_data->ratios.h_scale_ratio_c = spl_fixpt_u3d19(scl_data->ratios.horz_c) << 5;
- dscl_prog_data->ratios.v_scale_ratio_c = spl_fixpt_u3d19(scl_data->ratios.vert_c) << 5;
+ dscl_prog_data->ratios.h_scale_ratio = SPL_NAMESPACE(spl_fixpt_u3d19(
+ scl_data->ratios.horz)) << 5;
+ dscl_prog_data->ratios.v_scale_ratio = SPL_NAMESPACE(spl_fixpt_u3d19(
+ scl_data->ratios.vert)) << 5;
+ dscl_prog_data->ratios.h_scale_ratio_c = SPL_NAMESPACE(spl_fixpt_u3d19(
+ scl_data->ratios.horz_c)) << 5;
+ dscl_prog_data->ratios.v_scale_ratio_c = SPL_NAMESPACE(spl_fixpt_u3d19(
+ scl_data->ratios.vert_c)) << 5;
/*
* 0.24 format for fraction, first five bits zeroed
*/
dscl_prog_data->init.h_filter_init_frac =
- spl_fixpt_u0d19(scl_data->inits.h) << 5;
+ SPL_NAMESPACE(spl_fixpt_u0d19(scl_data->inits.h)) << 5;
dscl_prog_data->init.h_filter_init_int =
spl_fixpt_floor(scl_data->inits.h);
dscl_prog_data->init.h_filter_init_frac_c =
- spl_fixpt_u0d19(scl_data->inits.h_c) << 5;
+ SPL_NAMESPACE(spl_fixpt_u0d19(scl_data->inits.h_c)) << 5;
dscl_prog_data->init.h_filter_init_int_c =
spl_fixpt_floor(scl_data->inits.h_c);
dscl_prog_data->init.v_filter_init_frac =
- spl_fixpt_u0d19(scl_data->inits.v) << 5;
+ SPL_NAMESPACE(spl_fixpt_u0d19(scl_data->inits.v)) << 5;
dscl_prog_data->init.v_filter_init_int =
spl_fixpt_floor(scl_data->inits.v);
dscl_prog_data->init.v_filter_init_frac_c =
- spl_fixpt_u0d19(scl_data->inits.v_c) << 5;
+ SPL_NAMESPACE(spl_fixpt_u0d19(scl_data->inits.v_c)) << 5;
dscl_prog_data->init.v_filter_init_int_c =
spl_fixpt_floor(scl_data->inits.v_c);
bot = spl_fixpt_add(scl_data->inits.v, scl_data->ratios.vert);
- dscl_prog_data->init.v_filter_init_bot_frac = spl_fixpt_u0d19(bot) << 5;
+ dscl_prog_data->init.v_filter_init_bot_frac = SPL_NAMESPACE(spl_fixpt_u0d19(bot)) << 5;
dscl_prog_data->init.v_filter_init_bot_int = spl_fixpt_floor(bot);
bot = spl_fixpt_add(scl_data->inits.v_c, scl_data->ratios.vert_c);
- dscl_prog_data->init.v_filter_init_bot_frac_c = spl_fixpt_u0d19(bot) << 5;
+ dscl_prog_data->init.v_filter_init_bot_frac_c = SPL_NAMESPACE(spl_fixpt_u0d19(bot)) << 5;
dscl_prog_data->init.v_filter_init_bot_int_c = spl_fixpt_floor(bot);
}
@@ -1270,7 +1277,7 @@ static void spl_set_dscl_prog_data(struct spl_in *spl_in, struct spl_scratch *sp
// Set viewport_c
dscl_prog_data->viewport_c = spl_scratch->scl_data.viewport_c;
// Set filters data
- spl_set_filters_data(dscl_prog_data, data, enable_easf_v, enable_easf_h);
+ SPL_NAMESPACE(spl_set_filters_data(dscl_prog_data, data, enable_easf_v, enable_easf_h));
}
/* Calculate C0-C3 coefficients based on HDR_mult */
@@ -1286,28 +1293,31 @@ static void spl_calculate_c0_c3_hdr(struct dscl_prog_data *dscl_prog_data, uint3
else
hdr_multx100_int = 100; /* default for 80 nits otherwise */
- hdr_mult = spl_fixpt_from_fraction((long long)hdr_multx100_int, 100LL);
- c0_mult = spl_fixpt_from_fraction(2126LL, 10000LL);
- c1_mult = spl_fixpt_from_fraction(7152LL, 10000LL);
- c2_mult = spl_fixpt_from_fraction(722LL, 10000LL);
+ hdr_mult = SPL_NAMESPACE(spl_fixpt_from_fraction((long long)hdr_multx100_int, 100LL));
+ c0_mult = SPL_NAMESPACE(spl_fixpt_from_fraction(2126LL, 10000LL));
+ c1_mult = SPL_NAMESPACE(spl_fixpt_from_fraction(7152LL, 10000LL));
+ c2_mult = SPL_NAMESPACE(spl_fixpt_from_fraction(722LL, 10000LL));
- c0_calc = spl_fixpt_mul(hdr_mult, spl_fixpt_mul(c0_mult, spl_fixpt_from_fraction(
- 16384LL, 125LL)));
- c1_calc = spl_fixpt_mul(hdr_mult, spl_fixpt_mul(c1_mult, spl_fixpt_from_fraction(
- 16384LL, 125LL)));
- c2_calc = spl_fixpt_mul(hdr_mult, spl_fixpt_mul(c2_mult, spl_fixpt_from_fraction(
- 16384LL, 125LL)));
+ c0_calc = SPL_NAMESPACE(spl_fixpt_mul(hdr_mult, SPL_NAMESPACE(spl_fixpt_mul(c0_mult,
+ SPL_NAMESPACE(spl_fixpt_from_fraction(16384LL, 125LL))))));
+ c1_calc = SPL_NAMESPACE(spl_fixpt_mul(hdr_mult, SPL_NAMESPACE(spl_fixpt_mul(c1_mult,
+ SPL_NAMESPACE(spl_fixpt_from_fraction(16384LL, 125LL))))));
+ c2_calc = SPL_NAMESPACE(spl_fixpt_mul(hdr_mult, SPL_NAMESPACE(spl_fixpt_mul(c2_mult,
+ SPL_NAMESPACE(spl_fixpt_from_fraction(16384LL, 125LL))))));
fmt.exponenta_bits = 5;
fmt.mantissa_bits = 10;
fmt.sign = true;
// fp1.5.10, C0 coefficient (LN_rec709: HDR_MULT * 0.212600 * 2^14/125)
- spl_convert_to_custom_float_format(c0_calc, &fmt, &dscl_prog_data->easf_matrix_c0);
+ SPL_NAMESPACE(spl_convert_to_custom_float_format(c0_calc, &fmt,
+ &dscl_prog_data->easf_matrix_c0));
// fp1.5.10, C1 coefficient (LN_rec709: HDR_MULT * 0.715200 * 2^14/125)
- spl_convert_to_custom_float_format(c1_calc, &fmt, &dscl_prog_data->easf_matrix_c1);
+ SPL_NAMESPACE(spl_convert_to_custom_float_format(c1_calc, &fmt,
+ &dscl_prog_data->easf_matrix_c1));
// fp1.5.10, C2 coefficient (LN_rec709: HDR_MULT * 0.072200 * 2^14/125)
- spl_convert_to_custom_float_format(c2_calc, &fmt, &dscl_prog_data->easf_matrix_c2);
+ SPL_NAMESPACE(spl_convert_to_custom_float_format(c2_calc, &fmt,
+ &dscl_prog_data->easf_matrix_c2));
dscl_prog_data->easf_matrix_c3 = 0x0; // fp1.5.10, C3 coefficient
}
@@ -1325,48 +1335,48 @@ static void spl_set_easf_data(struct spl_scratch *spl_scratch, struct spl_out *s
dscl_prog_data->easf_v_bf1_en = 1; // 1-bit, BF1 calculation enable, 0=disable, 1=enable
dscl_prog_data->easf_v_bf2_mode = 0xF; // 4-bit, BF2 calculation mode
/* 2-bit, BF3 chroma mode correction calculation mode */
- dscl_prog_data->easf_v_bf3_mode = spl_get_v_bf3_mode(
- spl_scratch->scl_data.recip_ratios.vert);
+ dscl_prog_data->easf_v_bf3_mode = SPL_NAMESPACE(spl_get_v_bf3_mode(
+ spl_scratch->scl_data.recip_ratios.vert));
/* FP1.5.10 [ minCoef ]*/
dscl_prog_data->easf_v_ringest_3tap_dntilt_uptilt =
- spl_get_3tap_dntilt_uptilt_offset(spl_scratch->scl_data.taps.v_taps,
- spl_scratch->scl_data.recip_ratios.vert);
+ SPL_NAMESPACE(spl_get_3tap_dntilt_uptilt_offset(spl_scratch->scl_data.taps.v_taps,
+ spl_scratch->scl_data.recip_ratios.vert));
/* FP1.5.10 [ upTiltMaxVal ]*/
dscl_prog_data->easf_v_ringest_3tap_uptilt_max =
- spl_get_3tap_uptilt_maxval(spl_scratch->scl_data.taps.v_taps,
- spl_scratch->scl_data.recip_ratios.vert);
+ SPL_NAMESPACE(spl_get_3tap_uptilt_maxval(spl_scratch->scl_data.taps.v_taps,
+ spl_scratch->scl_data.recip_ratios.vert));
/* FP1.5.10 [ dnTiltSlope ]*/
dscl_prog_data->easf_v_ringest_3tap_dntilt_slope =
- spl_get_3tap_dntilt_slope(spl_scratch->scl_data.taps.v_taps,
- spl_scratch->scl_data.recip_ratios.vert);
+ SPL_NAMESPACE(spl_get_3tap_dntilt_slope(spl_scratch->scl_data.taps.v_taps,
+ spl_scratch->scl_data.recip_ratios.vert));
/* FP1.5.10 [ upTilt1Slope ]*/
dscl_prog_data->easf_v_ringest_3tap_uptilt1_slope =
- spl_get_3tap_uptilt1_slope(spl_scratch->scl_data.taps.v_taps,
- spl_scratch->scl_data.recip_ratios.vert);
+ SPL_NAMESPACE(spl_get_3tap_uptilt1_slope(spl_scratch->scl_data.taps.v_taps,
+ spl_scratch->scl_data.recip_ratios.vert));
/* FP1.5.10 [ upTilt2Slope ]*/
dscl_prog_data->easf_v_ringest_3tap_uptilt2_slope =
- spl_get_3tap_uptilt2_slope(spl_scratch->scl_data.taps.v_taps,
- spl_scratch->scl_data.recip_ratios.vert);
+ SPL_NAMESPACE(spl_get_3tap_uptilt2_slope(spl_scratch->scl_data.taps.v_taps,
+ spl_scratch->scl_data.recip_ratios.vert));
/* FP1.5.10 [ upTilt2Offset ]*/
dscl_prog_data->easf_v_ringest_3tap_uptilt2_offset =
- spl_get_3tap_uptilt2_offset(spl_scratch->scl_data.taps.v_taps,
- spl_scratch->scl_data.recip_ratios.vert);
+ SPL_NAMESPACE(spl_get_3tap_uptilt2_offset(spl_scratch->scl_data.taps.v_taps,
+ spl_scratch->scl_data.recip_ratios.vert));
/* FP1.5.10; (2.0) Ring reducer gain for 4 or 6-tap mode [H_REDUCER_GAIN4] */
dscl_prog_data->easf_v_ringest_eventap_reduceg1 =
- spl_get_reducer_gain4(spl_scratch->scl_data.taps.v_taps,
- spl_scratch->scl_data.recip_ratios.vert);
+ SPL_NAMESPACE(spl_get_reducer_gain4(spl_scratch->scl_data.taps.v_taps,
+ spl_scratch->scl_data.recip_ratios.vert));
/* FP1.5.10; (2.5) Ring reducer gain for 6-tap mode [V_REDUCER_GAIN6] */
dscl_prog_data->easf_v_ringest_eventap_reduceg2 =
- spl_get_reducer_gain6(spl_scratch->scl_data.taps.v_taps,
- spl_scratch->scl_data.recip_ratios.vert);
+ SPL_NAMESPACE(spl_get_reducer_gain6(spl_scratch->scl_data.taps.v_taps,
+ spl_scratch->scl_data.recip_ratios.vert));
/* FP1.5.10; (-0.135742) Ring gain for 6-tap set to -139/1024 */
dscl_prog_data->easf_v_ringest_eventap_gain1 =
- spl_get_gainRing4(spl_scratch->scl_data.taps.v_taps,
- spl_scratch->scl_data.recip_ratios.vert);
+ SPL_NAMESPACE(spl_get_gainRing4(spl_scratch->scl_data.taps.v_taps,
+ spl_scratch->scl_data.recip_ratios.vert));
/* FP1.5.10; (-0.024414) Ring gain for 6-tap set to -25/1024 */
dscl_prog_data->easf_v_ringest_eventap_gain2 =
- spl_get_gainRing6(spl_scratch->scl_data.taps.v_taps,
- spl_scratch->scl_data.recip_ratios.vert);
+ SPL_NAMESPACE(spl_get_gainRing6(spl_scratch->scl_data.taps.v_taps,
+ spl_scratch->scl_data.recip_ratios.vert));
dscl_prog_data->easf_v_bf_maxa = 63; //Vertical Max BF value A in U0.6 format.Selected if V_FCNTL == 0
dscl_prog_data->easf_v_bf_maxb = 63; //Vertical Max BF value A in U0.6 format.Selected if V_FCNTL == 1
dscl_prog_data->easf_v_bf_mina = 0; //Vertical Min BF value A in U0.6 format.Selected if V_FCNTL == 0
@@ -1491,24 +1501,24 @@ static void spl_set_easf_data(struct spl_scratch *spl_scratch, struct spl_out *s
dscl_prog_data->easf_h_bf2_mode =
0xF; // 4-bit, BF2 calculation mode
/* 2-bit, BF3 chroma mode correction calculation mode */
- dscl_prog_data->easf_h_bf3_mode = spl_get_h_bf3_mode(
- spl_scratch->scl_data.recip_ratios.horz);
+ dscl_prog_data->easf_h_bf3_mode = SPL_NAMESPACE(spl_get_h_bf3_mode(
+ spl_scratch->scl_data.recip_ratios.horz));
/* FP1.5.10; (2.0) Ring reducer gain for 4 or 6-tap mode [H_REDUCER_GAIN4] */
dscl_prog_data->easf_h_ringest_eventap_reduceg1 =
- spl_get_reducer_gain4(spl_scratch->scl_data.taps.h_taps,
- spl_scratch->scl_data.recip_ratios.horz);
+ SPL_NAMESPACE(spl_get_reducer_gain4(spl_scratch->scl_data.taps.h_taps,
+ spl_scratch->scl_data.recip_ratios.horz));
/* FP1.5.10; (2.5) Ring reducer gain for 6-tap mode [V_REDUCER_GAIN6] */
dscl_prog_data->easf_h_ringest_eventap_reduceg2 =
- spl_get_reducer_gain6(spl_scratch->scl_data.taps.h_taps,
- spl_scratch->scl_data.recip_ratios.horz);
+ SPL_NAMESPACE(spl_get_reducer_gain6(spl_scratch->scl_data.taps.h_taps,
+ spl_scratch->scl_data.recip_ratios.horz));
/* FP1.5.10; (-0.135742) Ring gain for 6-tap set to -139/1024 */
dscl_prog_data->easf_h_ringest_eventap_gain1 =
- spl_get_gainRing4(spl_scratch->scl_data.taps.h_taps,
- spl_scratch->scl_data.recip_ratios.horz);
+ SPL_NAMESPACE(spl_get_gainRing4(spl_scratch->scl_data.taps.h_taps,
+ spl_scratch->scl_data.recip_ratios.horz));
/* FP1.5.10; (-0.024414) Ring gain for 6-tap set to -25/1024 */
dscl_prog_data->easf_h_ringest_eventap_gain2 =
- spl_get_gainRing6(spl_scratch->scl_data.taps.h_taps,
- spl_scratch->scl_data.recip_ratios.horz);
+ SPL_NAMESPACE(spl_get_gainRing6(spl_scratch->scl_data.taps.h_taps,
+ spl_scratch->scl_data.recip_ratios.horz));
dscl_prog_data->easf_h_bf_maxa = 63; //Horz Max BF value A in U0.6 format.Selected if H_FCNTL==0
dscl_prog_data->easf_h_bf_maxb = 63; //Horz Max BF value B in U0.6 format.Selected if H_FCNTL==1
dscl_prog_data->easf_h_bf_mina = 0; //Horz Min BF value B in U0.6 format.Selected if H_FCNTL==0
@@ -1689,9 +1699,9 @@ static void spl_set_isharp_data(struct dscl_prog_data *dscl_prog_data,
return;
}
- spl_build_isharp_1dlut_from_reference_curve(ratio, setup, adp_sharpness,
- scale_to_sharpness_policy);
- memcpy(dscl_prog_data->isharp_delta, spl_get_pregen_filter_isharp_1D_lut(setup),
+ SPL_NAMESPACE(spl_build_isharp_1dlut_from_reference_curve(ratio, setup, adp_sharpness,
+ scale_to_sharpness_policy));
+ memcpy(dscl_prog_data->isharp_delta, SPL_NAMESPACE(spl_get_pregen_filter_isharp_1D_lut(setup)),
sizeof(uint32_t) * ISHARP_LUT_TABLE_SIZE);
dscl_prog_data->sharpness_level = adp_sharpness.sharpness_level;
@@ -1810,7 +1820,7 @@ static void spl_set_isharp_data(struct dscl_prog_data *dscl_prog_data,
}
// Set the values as per lookup table
- spl_set_blur_scale_data(dscl_prog_data, data);
+ SPL_NAMESPACE(spl_set_blur_scale_data(dscl_prog_data, data));
}
/* Calculate recout, scaling ratio, and viewport, then get optimal number of taps */
@@ -1922,4 +1932,3 @@ bool SPL_NAMESPACE(spl_get_number_of_taps(struct spl_in *spl_in, struct spl_out
spl_set_taps_data(dscl_prog_data, data);
return res;
}
-
diff --git a/drivers/gpu/drm/amd/display/dc/sspl/dc_spl.h b/drivers/gpu/drm/amd/display/dc/sspl/dc_spl.h
index d621c42a237e..f9503c368db5 100644
--- a/drivers/gpu/drm/amd/display/dc/sspl/dc_spl.h
+++ b/drivers/gpu/drm/amd/display/dc/sspl/dc_spl.h
@@ -9,14 +9,6 @@
#define BLACK_OFFSET_RGB_Y 0x0
#define BLACK_OFFSET_CBCR 0x8000
-#ifndef SPL_PFX_
-#define SPL_PFX_
-#endif
-
-#define SPL_EXPAND2(a, b) a##b
-#define SPL_EXPAND(a, b) SPL_EXPAND2(a, b)
-#define SPL_NAMESPACE(symbol) SPL_EXPAND(SPL_PFX_, symbol)
-
/* SPL interfaces */
diff --git a/drivers/gpu/drm/amd/display/dc/sspl/dc_spl_filters.c b/drivers/gpu/drm/amd/display/dc/sspl/dc_spl_filters.c
index 99238644e0a1..088aba3c00a1 100644
--- a/drivers/gpu/drm/amd/display/dc/sspl/dc_spl_filters.c
+++ b/drivers/gpu/drm/amd/display/dc/sspl/dc_spl_filters.c
@@ -4,8 +4,8 @@
#include "dc_spl_filters.h"
-void convert_filter_s1_10_to_s1_12(const uint16_t *s1_10_filter,
- uint16_t *s1_12_filter, int num_taps)
+void SPL_NAMESPACE(convert_filter_s1_10_to_s1_12(const uint16_t *s1_10_filter,
+ uint16_t *s1_12_filter, int num_taps))
{
int num_entries = NUM_PHASES_COEFF * num_taps;
int i;
diff --git a/drivers/gpu/drm/amd/display/dc/sspl/dc_spl_filters.h b/drivers/gpu/drm/amd/display/dc/sspl/dc_spl_filters.h
index 20439cdbdb10..f3ee51c42bf2 100644
--- a/drivers/gpu/drm/amd/display/dc/sspl/dc_spl_filters.h
+++ b/drivers/gpu/drm/amd/display/dc/sspl/dc_spl_filters.h
@@ -9,7 +9,7 @@
#define NUM_PHASES_COEFF 33
-void convert_filter_s1_10_to_s1_12(const uint16_t *s1_10_filter,
- uint16_t *s1_12_filter, int num_taps);
+void SPL_NAMESPACE(convert_filter_s1_10_to_s1_12(const uint16_t *s1_10_filter,
+ uint16_t *s1_12_filter, int num_taps));
#endif /* __DC_SPL_FILTERS_H__ */
diff --git a/drivers/gpu/drm/amd/display/dc/sspl/dc_spl_isharp_filters.c b/drivers/gpu/drm/amd/display/dc/sspl/dc_spl_isharp_filters.c
index 12acdd34e6a6..1d9edb89e47a 100644
--- a/drivers/gpu/drm/amd/display/dc/sspl/dc_spl_isharp_filters.c
+++ b/drivers/gpu/drm/amd/display/dc/sspl/dc_spl_isharp_filters.c
@@ -367,8 +367,8 @@ static unsigned int spl_calculate_sharpness_level_adj(struct spl_fixed31_32 rati
sharpness_level_down_adj = 0;
lookup_ptr = sharpness_level_adj;
while (j < NUM_SHARPNESS_ADJ_LEVELS) {
- ratio_level = spl_fixpt_from_fraction(lookup_ptr->ratio_numer,
- lookup_ptr->ratio_denom);
+ ratio_level = SPL_NAMESPACE(spl_fixpt_from_fraction(lookup_ptr->ratio_numer,
+ lookup_ptr->ratio_denom));
if (ratio.value >= ratio_level.value) {
sharpness_level_down_adj = lookup_ptr->level_down_adj;
break;
@@ -447,8 +447,9 @@ static unsigned int spl_calculate_sharpness_level(struct spl_fixed31_32 ratio,
return sharpness_level;
}
-void spl_build_isharp_1dlut_from_reference_curve(struct spl_fixed31_32 ratio, enum system_setup setup,
- struct adaptive_sharpness sharpness, enum scale_to_sharpness_policy scale_to_sharpness_policy)
+void SPL_NAMESPACE(spl_build_isharp_1dlut_from_reference_curve(
+ struct spl_fixed31_32 ratio, enum system_setup setup,
+ struct adaptive_sharpness sharpness, enum scale_to_sharpness_policy scale_to_sharpness_policy))
{
uint8_t *byte_ptr_1dlut_src, *byte_ptr_1dlut_dst;
struct spl_fixed31_32 sharp_base, sharp_calc, sharp_level;
@@ -461,7 +462,7 @@ void spl_build_isharp_1dlut_from_reference_curve(struct spl_fixed31_32 ratio, en
unsigned int sharpnessX1000 = spl_calculate_sharpness_level(ratio,
sharpness.sharpness_level, setup,
sharpness.sharpness_range, scale_to_sharpness_policy);
- sharp_level = spl_fixpt_from_fraction(sharpnessX1000, 1000);
+ sharp_level = SPL_NAMESPACE(spl_fixpt_from_fraction(sharpnessX1000, 1000));
/*
* Check if pregen 1dlut table is already precalculated
@@ -486,10 +487,11 @@ void spl_build_isharp_1dlut_from_reference_curve(struct spl_fixed31_32 ratio, en
memset(byte_ptr_1dlut_dst, 0, size_1dlut);
for (j = 0; j < size_1dlut; j++) {
sharp_base = spl_fixpt_from_int((int)*byte_ptr_1dlut_src);
- sharp_calc = spl_fixpt_mul(sharp_base, sharp_level);
+ sharp_calc = SPL_NAMESPACE(spl_fixpt_mul(sharp_base, sharp_level));
sharp_calc = spl_fixpt_div(sharp_calc, spl_fixpt_from_int(3));
sharp_calc = spl_fixpt_min(spl_fixpt_from_int(255), sharp_calc);
- sharp_calc = spl_fixpt_add(sharp_calc, spl_fixpt_from_fraction(1, 2));
+ sharp_calc = spl_fixpt_add(sharp_calc,
+ SPL_NAMESPACE(spl_fixpt_from_fraction(1, 2)));
sharp_calc_int = spl_fixpt_floor(sharp_calc);
/* Clamp it at 0x7F so it doesn't wrap */
if (sharp_calc_int > 127)
@@ -506,12 +508,12 @@ void spl_build_isharp_1dlut_from_reference_curve(struct spl_fixed31_32 ratio, en
filter_isharp_1D_lut_pregen[setup].sharpness_denom = 1000;
}
-uint32_t *spl_get_pregen_filter_isharp_1D_lut(enum system_setup setup)
+uint32_t *SPL_NAMESPACE(spl_get_pregen_filter_isharp_1D_lut(enum system_setup setup))
{
return filter_isharp_1D_lut_pregen[setup].value;
}
-const uint16_t *spl_dscl_get_blur_scale_coeffs_64p(int taps)
+const uint16_t *SPL_NAMESPACE(spl_dscl_get_blur_scale_coeffs_64p(int taps))
{
if (taps == 3)
return filter_isharp_bs_3tap_64p_s1_12;
@@ -526,7 +528,7 @@ const uint16_t *spl_dscl_get_blur_scale_coeffs_64p(int taps)
}
}
-const uint16_t *spl_dscl_get_blur_scale_coeffs_64p_s1_10(int taps)
+const uint16_t *SPL_NAMESPACE(spl_dscl_get_blur_scale_coeffs_64p_s1_10(int taps))
{
if (taps == 3)
return filter_isharp_bs_3tap_64p;
@@ -541,13 +543,12 @@ const uint16_t *spl_dscl_get_blur_scale_coeffs_64p_s1_10(int taps)
}
}
-void spl_set_blur_scale_data(struct dscl_prog_data *dscl_prog_data,
- const struct spl_scaler_data *data)
+void SPL_NAMESPACE(spl_set_blur_scale_data(struct dscl_prog_data *dscl_prog_data,
+ const struct spl_scaler_data *data))
{
dscl_prog_data->filter_blur_scale_h =
- spl_dscl_get_blur_scale_coeffs_64p(data->taps.h_taps);
+ SPL_NAMESPACE(spl_dscl_get_blur_scale_coeffs_64p(data->taps.h_taps));
dscl_prog_data->filter_blur_scale_v =
- spl_dscl_get_blur_scale_coeffs_64p(data->taps.v_taps);
+ SPL_NAMESPACE(spl_dscl_get_blur_scale_coeffs_64p(data->taps.v_taps));
}
-
diff --git a/drivers/gpu/drm/amd/display/dc/sspl/dc_spl_isharp_filters.h b/drivers/gpu/drm/amd/display/dc/sspl/dc_spl_isharp_filters.h
index f5e3d3ecc913..d4082d4969e4 100644
--- a/drivers/gpu/drm/amd/display/dc/sspl/dc_spl_isharp_filters.h
+++ b/drivers/gpu/drm/amd/display/dc/sspl/dc_spl_isharp_filters.h
@@ -28,15 +28,17 @@ enum system_setup {
NUM_SHARPNESS_SETUPS
};
-void spl_set_blur_scale_data(struct dscl_prog_data *dscl_prog_data,
- const struct spl_scaler_data *data);
+void SPL_NAMESPACE(spl_set_blur_scale_data(struct dscl_prog_data *dscl_prog_data,
+ const struct spl_scaler_data *data));
-void spl_build_isharp_1dlut_from_reference_curve(struct spl_fixed31_32 ratio, enum system_setup setup,
- struct adaptive_sharpness sharpness, enum scale_to_sharpness_policy scale_to_sharpness_policy);
-uint32_t *spl_get_pregen_filter_isharp_1D_lut(enum system_setup setup);
+void SPL_NAMESPACE(spl_build_isharp_1dlut_from_reference_curve(
+ struct spl_fixed31_32 ratio, enum system_setup setup,
+ struct adaptive_sharpness sharpness,
+ enum scale_to_sharpness_policy scale_to_sharpness_policy));
+uint32_t *SPL_NAMESPACE(spl_get_pregen_filter_isharp_1D_lut(enum system_setup setup));
// public API
-const uint16_t *spl_dscl_get_blur_scale_coeffs_64p(int taps);
-const uint16_t *spl_dscl_get_blur_scale_coeffs_64p_s1_10(int taps);
+const uint16_t *SPL_NAMESPACE(spl_dscl_get_blur_scale_coeffs_64p(int taps));
+const uint16_t *SPL_NAMESPACE(spl_dscl_get_blur_scale_coeffs_64p_s1_10(int taps));
#endif /* __DC_SPL_ISHARP_FILTERS_H__ */
diff --git a/drivers/gpu/drm/amd/display/dc/sspl/dc_spl_scl_easf_filters.c b/drivers/gpu/drm/amd/display/dc/sspl/dc_spl_scl_easf_filters.c
index 0d1bd81ff04a..de16ee586073 100644
--- a/drivers/gpu/drm/amd/display/dc/sspl/dc_spl_scl_easf_filters.c
+++ b/drivers/gpu/drm/amd/display/dc/sspl/dc_spl_scl_easf_filters.c
@@ -2194,19 +2194,19 @@ static struct scale_ratio_to_reg_value_lookup easf_3tap_uptilt2_offset_lookup[]
static const uint16_t *spl_get_easf_filter_3tap_64p(struct spl_fixed31_32 ratio)
{
- if (ratio.value < spl_fixpt_from_fraction(3, 10).value)
+ if (ratio.value < SPL_NAMESPACE(spl_fixpt_from_fraction(3, 10)).value)
return easf_filter_3tap_64p_ratio_0_30_s1_12;
- else if (ratio.value < spl_fixpt_from_fraction(4, 10).value)
+ else if (ratio.value < SPL_NAMESPACE(spl_fixpt_from_fraction(4, 10)).value)
return easf_filter_3tap_64p_ratio_0_40_s1_12;
- else if (ratio.value < spl_fixpt_from_fraction(5, 10).value)
+ else if (ratio.value < SPL_NAMESPACE(spl_fixpt_from_fraction(5, 10)).value)
return easf_filter_3tap_64p_ratio_0_50_s1_12;
- else if (ratio.value < spl_fixpt_from_fraction(6, 10).value)
+ else if (ratio.value < SPL_NAMESPACE(spl_fixpt_from_fraction(6, 10)).value)
return easf_filter_3tap_64p_ratio_0_60_s1_12;
- else if (ratio.value < spl_fixpt_from_fraction(7, 10).value)
+ else if (ratio.value < SPL_NAMESPACE(spl_fixpt_from_fraction(7, 10)).value)
return easf_filter_3tap_64p_ratio_0_70_s1_12;
- else if (ratio.value < spl_fixpt_from_fraction(8, 10).value)
+ else if (ratio.value < SPL_NAMESPACE(spl_fixpt_from_fraction(8, 10)).value)
return easf_filter_3tap_64p_ratio_0_80_s1_12;
- else if (ratio.value < spl_fixpt_from_fraction(9, 10).value)
+ else if (ratio.value < SPL_NAMESPACE(spl_fixpt_from_fraction(9, 10)).value)
return easf_filter_3tap_64p_ratio_0_90_s1_12;
else
return easf_filter_3tap_64p_ratio_1_00_s1_12;
@@ -2214,19 +2214,19 @@ static const uint16_t *spl_get_easf_filter_3tap_64p(struct spl_fixed31_32 ratio)
static const uint16_t *spl_get_easf_filter_4tap_64p(struct spl_fixed31_32 ratio)
{
- if (ratio.value < spl_fixpt_from_fraction(3, 10).value)
+ if (ratio.value < SPL_NAMESPACE(spl_fixpt_from_fraction(3, 10)).value)
return easf_filter_4tap_64p_ratio_0_30_s1_12;
- else if (ratio.value < spl_fixpt_from_fraction(4, 10).value)
+ else if (ratio.value < SPL_NAMESPACE(spl_fixpt_from_fraction(4, 10)).value)
return easf_filter_4tap_64p_ratio_0_40_s1_12;
- else if (ratio.value < spl_fixpt_from_fraction(5, 10).value)
+ else if (ratio.value < SPL_NAMESPACE(spl_fixpt_from_fraction(5, 10)).value)
return easf_filter_4tap_64p_ratio_0_50_s1_12;
- else if (ratio.value < spl_fixpt_from_fraction(6, 10).value)
+ else if (ratio.value < SPL_NAMESPACE(spl_fixpt_from_fraction(6, 10)).value)
return easf_filter_4tap_64p_ratio_0_60_s1_12;
- else if (ratio.value < spl_fixpt_from_fraction(7, 10).value)
+ else if (ratio.value < SPL_NAMESPACE(spl_fixpt_from_fraction(7, 10)).value)
return easf_filter_4tap_64p_ratio_0_70_s1_12;
- else if (ratio.value < spl_fixpt_from_fraction(8, 10).value)
+ else if (ratio.value < SPL_NAMESPACE(spl_fixpt_from_fraction(8, 10)).value)
return easf_filter_4tap_64p_ratio_0_80_s1_12;
- else if (ratio.value < spl_fixpt_from_fraction(9, 10).value)
+ else if (ratio.value < SPL_NAMESPACE(spl_fixpt_from_fraction(9, 10)).value)
return easf_filter_4tap_64p_ratio_0_90_s1_12;
else
return easf_filter_4tap_64p_ratio_1_00_s1_12;
@@ -2234,25 +2234,26 @@ static const uint16_t *spl_get_easf_filter_4tap_64p(struct spl_fixed31_32 ratio)
static const uint16_t *spl_get_easf_filter_6tap_64p(struct spl_fixed31_32 ratio)
{
- if (ratio.value < spl_fixpt_from_fraction(3, 10).value)
+ if (ratio.value < SPL_NAMESPACE(spl_fixpt_from_fraction(3, 10)).value)
return easf_filter_6tap_64p_ratio_0_30_s1_12;
- else if (ratio.value < spl_fixpt_from_fraction(4, 10).value)
+ else if (ratio.value < SPL_NAMESPACE(spl_fixpt_from_fraction(4, 10)).value)
return easf_filter_6tap_64p_ratio_0_40_s1_12;
- else if (ratio.value < spl_fixpt_from_fraction(5, 10).value)
+ else if (ratio.value < SPL_NAMESPACE(spl_fixpt_from_fraction(5, 10)).value)
return easf_filter_6tap_64p_ratio_0_50_s1_12;
- else if (ratio.value < spl_fixpt_from_fraction(6, 10).value)
+ else if (ratio.value < SPL_NAMESPACE(spl_fixpt_from_fraction(6, 10)).value)
return easf_filter_6tap_64p_ratio_0_60_s1_12;
- else if (ratio.value < spl_fixpt_from_fraction(7, 10).value)
+ else if (ratio.value < SPL_NAMESPACE(spl_fixpt_from_fraction(7, 10)).value)
return easf_filter_6tap_64p_ratio_0_70_s1_12;
- else if (ratio.value < spl_fixpt_from_fraction(8, 10).value)
+ else if (ratio.value < SPL_NAMESPACE(spl_fixpt_from_fraction(8, 10)).value)
return easf_filter_6tap_64p_ratio_0_80_s1_12;
- else if (ratio.value < spl_fixpt_from_fraction(9, 10).value)
+ else if (ratio.value < SPL_NAMESPACE(spl_fixpt_from_fraction(9, 10)).value)
return easf_filter_6tap_64p_ratio_0_90_s1_12;
else
return easf_filter_6tap_64p_ratio_1_00_s1_12;
}
-const uint16_t *spl_dscl_get_easf_filter_coeffs_64p(int taps, struct spl_fixed31_32 ratio)
+const uint16_t *SPL_NAMESPACE(spl_dscl_get_easf_filter_coeffs_64p(
+ int taps, struct spl_fixed31_32 ratio))
{
if (taps == 6)
return spl_get_easf_filter_6tap_64p(ratio);
@@ -2269,19 +2270,19 @@ const uint16_t *spl_dscl_get_easf_filter_coeffs_64p(int taps, struct spl_fixed31
static const uint16_t *spl_get_easf_filter_3tap_64p_s1_10(struct spl_fixed31_32 ratio)
{
- if (ratio.value < spl_fixpt_from_fraction(3, 10).value)
+ if (ratio.value < SPL_NAMESPACE(spl_fixpt_from_fraction(3, 10)).value)
return easf_filter_3tap_64p_ratio_0_30;
- else if (ratio.value < spl_fixpt_from_fraction(4, 10).value)
+ else if (ratio.value < SPL_NAMESPACE(spl_fixpt_from_fraction(4, 10)).value)
return easf_filter_3tap_64p_ratio_0_40;
- else if (ratio.value < spl_fixpt_from_fraction(5, 10).value)
+ else if (ratio.value < SPL_NAMESPACE(spl_fixpt_from_fraction(5, 10)).value)
return easf_filter_3tap_64p_ratio_0_50;
- else if (ratio.value < spl_fixpt_from_fraction(6, 10).value)
+ else if (ratio.value < SPL_NAMESPACE(spl_fixpt_from_fraction(6, 10)).value)
return easf_filter_3tap_64p_ratio_0_60;
- else if (ratio.value < spl_fixpt_from_fraction(7, 10).value)
+ else if (ratio.value < SPL_NAMESPACE(spl_fixpt_from_fraction(7, 10)).value)
return easf_filter_3tap_64p_ratio_0_70;
- else if (ratio.value < spl_fixpt_from_fraction(8, 10).value)
+ else if (ratio.value < SPL_NAMESPACE(spl_fixpt_from_fraction(8, 10)).value)
return easf_filter_3tap_64p_ratio_0_80;
- else if (ratio.value < spl_fixpt_from_fraction(9, 10).value)
+ else if (ratio.value < SPL_NAMESPACE(spl_fixpt_from_fraction(9, 10)).value)
return easf_filter_3tap_64p_ratio_0_90;
else
return easf_filter_3tap_64p_ratio_1_00;
@@ -2289,19 +2290,19 @@ static const uint16_t *spl_get_easf_filter_3tap_64p_s1_10(struct spl_fixed31_32
static const uint16_t *spl_get_easf_filter_4tap_64p_s1_10(struct spl_fixed31_32 ratio)
{
- if (ratio.value < spl_fixpt_from_fraction(3, 10).value)
+ if (ratio.value < SPL_NAMESPACE(spl_fixpt_from_fraction(3, 10)).value)
return easf_filter_4tap_64p_ratio_0_30;
- else if (ratio.value < spl_fixpt_from_fraction(4, 10).value)
+ else if (ratio.value < SPL_NAMESPACE(spl_fixpt_from_fraction(4, 10)).value)
return easf_filter_4tap_64p_ratio_0_40;
- else if (ratio.value < spl_fixpt_from_fraction(5, 10).value)
+ else if (ratio.value < SPL_NAMESPACE(spl_fixpt_from_fraction(5, 10)).value)
return easf_filter_4tap_64p_ratio_0_50;
- else if (ratio.value < spl_fixpt_from_fraction(6, 10).value)
+ else if (ratio.value < SPL_NAMESPACE(spl_fixpt_from_fraction(6, 10)).value)
return easf_filter_4tap_64p_ratio_0_60;
- else if (ratio.value < spl_fixpt_from_fraction(7, 10).value)
+ else if (ratio.value < SPL_NAMESPACE(spl_fixpt_from_fraction(7, 10)).value)
return easf_filter_4tap_64p_ratio_0_70;
- else if (ratio.value < spl_fixpt_from_fraction(8, 10).value)
+ else if (ratio.value < SPL_NAMESPACE(spl_fixpt_from_fraction(8, 10)).value)
return easf_filter_4tap_64p_ratio_0_80;
- else if (ratio.value < spl_fixpt_from_fraction(9, 10).value)
+ else if (ratio.value < SPL_NAMESPACE(spl_fixpt_from_fraction(9, 10)).value)
return easf_filter_4tap_64p_ratio_0_90;
else
return easf_filter_4tap_64p_ratio_1_00;
@@ -2309,25 +2310,26 @@ static const uint16_t *spl_get_easf_filter_4tap_64p_s1_10(struct spl_fixed31_32
static const uint16_t *spl_get_easf_filter_6tap_64p_s1_10(struct spl_fixed31_32 ratio)
{
- if (ratio.value < spl_fixpt_from_fraction(3, 10).value)
+ if (ratio.value < SPL_NAMESPACE(spl_fixpt_from_fraction(3, 10)).value)
return easf_filter_6tap_64p_ratio_0_30;
- else if (ratio.value < spl_fixpt_from_fraction(4, 10).value)
+ else if (ratio.value < SPL_NAMESPACE(spl_fixpt_from_fraction(4, 10)).value)
return easf_filter_6tap_64p_ratio_0_40;
- else if (ratio.value < spl_fixpt_from_fraction(5, 10).value)
+ else if (ratio.value < SPL_NAMESPACE(spl_fixpt_from_fraction(5, 10)).value)
return easf_filter_6tap_64p_ratio_0_50;
- else if (ratio.value < spl_fixpt_from_fraction(6, 10).value)
+ else if (ratio.value < SPL_NAMESPACE(spl_fixpt_from_fraction(6, 10)).value)
return easf_filter_6tap_64p_ratio_0_60;
- else if (ratio.value < spl_fixpt_from_fraction(7, 10).value)
+ else if (ratio.value < SPL_NAMESPACE(spl_fixpt_from_fraction(7, 10)).value)
return easf_filter_6tap_64p_ratio_0_70;
- else if (ratio.value < spl_fixpt_from_fraction(8, 10).value)
+ else if (ratio.value < SPL_NAMESPACE(spl_fixpt_from_fraction(8, 10)).value)
return easf_filter_6tap_64p_ratio_0_80;
- else if (ratio.value < spl_fixpt_from_fraction(9, 10).value)
+ else if (ratio.value < SPL_NAMESPACE(spl_fixpt_from_fraction(9, 10)).value)
return easf_filter_6tap_64p_ratio_0_90;
else
return easf_filter_6tap_64p_ratio_1_00;
}
-const uint16_t *spl_dscl_get_easf_filter_coeffs_64p_s1_10(int taps, struct spl_fixed31_32 ratio)
+const uint16_t *SPL_NAMESPACE(spl_dscl_get_easf_filter_coeffs_64p_s1_10(
+ int taps, struct spl_fixed31_32 ratio))
{
if (taps == 6)
return spl_get_easf_filter_6tap_64p_s1_10(ratio);
@@ -2342,39 +2344,39 @@ const uint16_t *spl_dscl_get_easf_filter_coeffs_64p_s1_10(int taps, struct spl_f
}
}
-void spl_set_filters_data(struct dscl_prog_data *dscl_prog_data,
+void SPL_NAMESPACE(spl_set_filters_data(struct dscl_prog_data *dscl_prog_data,
const struct spl_scaler_data *data, bool enable_easf_v,
- bool enable_easf_h)
+ bool enable_easf_h))
{
/*
* Old coefficients calculated scaling ratio = input / output
* New coefficients are calculated based on = output / input
*/
if (enable_easf_h) {
- dscl_prog_data->filter_h = spl_dscl_get_easf_filter_coeffs_64p(
- data->taps.h_taps, data->recip_ratios.horz);
+ dscl_prog_data->filter_h = SPL_NAMESPACE(spl_dscl_get_easf_filter_coeffs_64p(
+ data->taps.h_taps, data->recip_ratios.horz));
- dscl_prog_data->filter_h_c = spl_dscl_get_easf_filter_coeffs_64p(
- data->taps.h_taps_c, data->recip_ratios.horz_c);
+ dscl_prog_data->filter_h_c = SPL_NAMESPACE(spl_dscl_get_easf_filter_coeffs_64p(
+ data->taps.h_taps_c, data->recip_ratios.horz_c));
} else {
- dscl_prog_data->filter_h = spl_dscl_get_filter_coeffs_64p(
- data->taps.h_taps, data->ratios.horz);
+ dscl_prog_data->filter_h = SPL_NAMESPACE(spl_dscl_get_filter_coeffs_64p(
+ data->taps.h_taps, data->ratios.horz));
- dscl_prog_data->filter_h_c = spl_dscl_get_filter_coeffs_64p(
- data->taps.h_taps_c, data->ratios.horz_c);
+ dscl_prog_data->filter_h_c = SPL_NAMESPACE(spl_dscl_get_filter_coeffs_64p(
+ data->taps.h_taps_c, data->ratios.horz_c));
}
if (enable_easf_v) {
- dscl_prog_data->filter_v = spl_dscl_get_easf_filter_coeffs_64p(
- data->taps.v_taps, data->recip_ratios.vert);
+ dscl_prog_data->filter_v = SPL_NAMESPACE(spl_dscl_get_easf_filter_coeffs_64p(
+ data->taps.v_taps, data->recip_ratios.vert));
- dscl_prog_data->filter_v_c = spl_dscl_get_easf_filter_coeffs_64p(
- data->taps.v_taps_c, data->recip_ratios.vert_c);
+ dscl_prog_data->filter_v_c = SPL_NAMESPACE(spl_dscl_get_easf_filter_coeffs_64p(
+ data->taps.v_taps_c, data->recip_ratios.vert_c));
} else {
- dscl_prog_data->filter_v = spl_dscl_get_filter_coeffs_64p(
- data->taps.v_taps, data->ratios.vert);
+ dscl_prog_data->filter_v = SPL_NAMESPACE(spl_dscl_get_filter_coeffs_64p(
+ data->taps.v_taps, data->ratios.vert));
- dscl_prog_data->filter_v_c = spl_dscl_get_filter_coeffs_64p(
- data->taps.v_taps_c, data->ratios.vert_c);
+ dscl_prog_data->filter_v_c = SPL_NAMESPACE(spl_dscl_get_filter_coeffs_64p(
+ data->taps.v_taps_c, data->ratios.vert_c));
}
}
@@ -2395,9 +2397,9 @@ static uint32_t spl_easf_get_scale_ratio_to_reg_value(struct spl_fixed31_32 rati
if (lookup_table_index_ptr->numer < 0)
break;
- if (ratio.value < spl_fixpt_from_fraction(
+ if (ratio.value < SPL_NAMESPACE(spl_fixpt_from_fraction(
lookup_table_index_ptr->numer,
- lookup_table_index_ptr->denom).value) {
+ lookup_table_index_ptr->denom)).value) {
value = lookup_table_index_ptr->reg_value;
break;
}
@@ -2406,7 +2408,7 @@ static uint32_t spl_easf_get_scale_ratio_to_reg_value(struct spl_fixed31_32 rati
}
return value;
}
-uint32_t spl_get_v_bf3_mode(struct spl_fixed31_32 ratio)
+uint32_t SPL_NAMESPACE(spl_get_v_bf3_mode(struct spl_fixed31_32 ratio))
{
uint32_t value;
unsigned int num_entries = sizeof(easf_v_bf3_mode_lookup) /
@@ -2415,7 +2417,7 @@ uint32_t spl_get_v_bf3_mode(struct spl_fixed31_32 ratio)
easf_v_bf3_mode_lookup, num_entries);
return value;
}
-uint32_t spl_get_h_bf3_mode(struct spl_fixed31_32 ratio)
+uint32_t SPL_NAMESPACE(spl_get_h_bf3_mode(struct spl_fixed31_32 ratio))
{
uint32_t value;
unsigned int num_entries = sizeof(easf_h_bf3_mode_lookup) /
@@ -2424,7 +2426,7 @@ uint32_t spl_get_h_bf3_mode(struct spl_fixed31_32 ratio)
easf_h_bf3_mode_lookup, num_entries);
return value;
}
-uint32_t spl_get_reducer_gain6(int taps, struct spl_fixed31_32 ratio)
+uint32_t SPL_NAMESPACE(spl_get_reducer_gain6(int taps, struct spl_fixed31_32 ratio))
{
uint32_t value;
unsigned int num_entries;
@@ -2443,7 +2445,7 @@ uint32_t spl_get_reducer_gain6(int taps, struct spl_fixed31_32 ratio)
value = 0;
return value;
}
-uint32_t spl_get_reducer_gain4(int taps, struct spl_fixed31_32 ratio)
+uint32_t SPL_NAMESPACE(spl_get_reducer_gain4(int taps, struct spl_fixed31_32 ratio))
{
uint32_t value;
unsigned int num_entries;
@@ -2462,7 +2464,7 @@ uint32_t spl_get_reducer_gain4(int taps, struct spl_fixed31_32 ratio)
value = 0;
return value;
}
-uint32_t spl_get_gainRing6(int taps, struct spl_fixed31_32 ratio)
+uint32_t SPL_NAMESPACE(spl_get_gainRing6(int taps, struct spl_fixed31_32 ratio))
{
uint32_t value;
unsigned int num_entries;
@@ -2481,7 +2483,7 @@ uint32_t spl_get_gainRing6(int taps, struct spl_fixed31_32 ratio)
value = 0;
return value;
}
-uint32_t spl_get_gainRing4(int taps, struct spl_fixed31_32 ratio)
+uint32_t SPL_NAMESPACE(spl_get_gainRing4(int taps, struct spl_fixed31_32 ratio))
{
uint32_t value;
unsigned int num_entries;
@@ -2500,7 +2502,8 @@ uint32_t spl_get_gainRing4(int taps, struct spl_fixed31_32 ratio)
value = 0;
return value;
}
-uint32_t spl_get_3tap_dntilt_uptilt_offset(int taps, struct spl_fixed31_32 ratio)
+uint32_t SPL_NAMESPACE(spl_get_3tap_dntilt_uptilt_offset(
+ int taps, struct spl_fixed31_32 ratio))
{
uint32_t value;
unsigned int num_entries;
@@ -2514,7 +2517,7 @@ uint32_t spl_get_3tap_dntilt_uptilt_offset(int taps, struct spl_fixed31_32 ratio
value = 0;
return value;
}
-uint32_t spl_get_3tap_uptilt_maxval(int taps, struct spl_fixed31_32 ratio)
+uint32_t SPL_NAMESPACE(spl_get_3tap_uptilt_maxval(int taps, struct spl_fixed31_32 ratio))
{
uint32_t value;
unsigned int num_entries;
@@ -2528,7 +2531,7 @@ uint32_t spl_get_3tap_uptilt_maxval(int taps, struct spl_fixed31_32 ratio)
value = 0;
return value;
}
-uint32_t spl_get_3tap_dntilt_slope(int taps, struct spl_fixed31_32 ratio)
+uint32_t SPL_NAMESPACE(spl_get_3tap_dntilt_slope(int taps, struct spl_fixed31_32 ratio))
{
uint32_t value;
unsigned int num_entries;
@@ -2542,7 +2545,7 @@ uint32_t spl_get_3tap_dntilt_slope(int taps, struct spl_fixed31_32 ratio)
value = 0;
return value;
}
-uint32_t spl_get_3tap_uptilt1_slope(int taps, struct spl_fixed31_32 ratio)
+uint32_t SPL_NAMESPACE(spl_get_3tap_uptilt1_slope(int taps, struct spl_fixed31_32 ratio))
{
uint32_t value;
unsigned int num_entries;
@@ -2556,7 +2559,7 @@ uint32_t spl_get_3tap_uptilt1_slope(int taps, struct spl_fixed31_32 ratio)
value = 0;
return value;
}
-uint32_t spl_get_3tap_uptilt2_slope(int taps, struct spl_fixed31_32 ratio)
+uint32_t SPL_NAMESPACE(spl_get_3tap_uptilt2_slope(int taps, struct spl_fixed31_32 ratio))
{
uint32_t value;
unsigned int num_entries;
@@ -2570,7 +2573,7 @@ uint32_t spl_get_3tap_uptilt2_slope(int taps, struct spl_fixed31_32 ratio)
value = 0;
return value;
}
-uint32_t spl_get_3tap_uptilt2_offset(int taps, struct spl_fixed31_32 ratio)
+uint32_t SPL_NAMESPACE(spl_get_3tap_uptilt2_offset(int taps, struct spl_fixed31_32 ratio))
{
uint32_t value;
unsigned int num_entries;
diff --git a/drivers/gpu/drm/amd/display/dc/sspl/dc_spl_scl_easf_filters.h b/drivers/gpu/drm/amd/display/dc/sspl/dc_spl_scl_easf_filters.h
index 321ae22a04d4..ba1cdb8be417 100644
--- a/drivers/gpu/drm/amd/display/dc/sspl/dc_spl_scl_easf_filters.h
+++ b/drivers/gpu/drm/amd/display/dc/sspl/dc_spl_scl_easf_filters.h
@@ -13,25 +13,28 @@ struct scale_ratio_to_reg_value_lookup {
const uint32_t reg_value;
};
-void spl_set_filters_data(struct dscl_prog_data *dscl_prog_data,
+void SPL_NAMESPACE(spl_set_filters_data(struct dscl_prog_data *dscl_prog_data,
const struct spl_scaler_data *data, bool enable_easf_v,
- bool enable_easf_h);
-
-uint32_t spl_get_v_bf3_mode(struct spl_fixed31_32 ratio);
-uint32_t spl_get_h_bf3_mode(struct spl_fixed31_32 ratio);
-uint32_t spl_get_reducer_gain6(int taps, struct spl_fixed31_32 ratio);
-uint32_t spl_get_reducer_gain4(int taps, struct spl_fixed31_32 ratio);
-uint32_t spl_get_gainRing6(int taps, struct spl_fixed31_32 ratio);
-uint32_t spl_get_gainRing4(int taps, struct spl_fixed31_32 ratio);
-uint32_t spl_get_3tap_dntilt_uptilt_offset(int taps, struct spl_fixed31_32 ratio);
-uint32_t spl_get_3tap_uptilt_maxval(int taps, struct spl_fixed31_32 ratio);
-uint32_t spl_get_3tap_dntilt_slope(int taps, struct spl_fixed31_32 ratio);
-uint32_t spl_get_3tap_uptilt1_slope(int taps, struct spl_fixed31_32 ratio);
-uint32_t spl_get_3tap_uptilt2_slope(int taps, struct spl_fixed31_32 ratio);
-uint32_t spl_get_3tap_uptilt2_offset(int taps, struct spl_fixed31_32 ratio);
+ bool enable_easf_h));
+
+uint32_t SPL_NAMESPACE(spl_get_v_bf3_mode(struct spl_fixed31_32 ratio));
+uint32_t SPL_NAMESPACE(spl_get_h_bf3_mode(struct spl_fixed31_32 ratio));
+uint32_t SPL_NAMESPACE(spl_get_reducer_gain6(int taps, struct spl_fixed31_32 ratio));
+uint32_t SPL_NAMESPACE(spl_get_reducer_gain4(int taps, struct spl_fixed31_32 ratio));
+uint32_t SPL_NAMESPACE(spl_get_gainRing6(int taps, struct spl_fixed31_32 ratio));
+uint32_t SPL_NAMESPACE(spl_get_gainRing4(int taps, struct spl_fixed31_32 ratio));
+uint32_t SPL_NAMESPACE(spl_get_3tap_dntilt_uptilt_offset(
+ int taps, struct spl_fixed31_32 ratio));
+uint32_t SPL_NAMESPACE(spl_get_3tap_uptilt_maxval(int taps, struct spl_fixed31_32 ratio));
+uint32_t SPL_NAMESPACE(spl_get_3tap_dntilt_slope(int taps, struct spl_fixed31_32 ratio));
+uint32_t SPL_NAMESPACE(spl_get_3tap_uptilt1_slope(int taps, struct spl_fixed31_32 ratio));
+uint32_t SPL_NAMESPACE(spl_get_3tap_uptilt2_slope(int taps, struct spl_fixed31_32 ratio));
+uint32_t SPL_NAMESPACE(spl_get_3tap_uptilt2_offset(int taps, struct spl_fixed31_32 ratio));
/* public API */
-const uint16_t *spl_dscl_get_easf_filter_coeffs_64p(int taps, struct spl_fixed31_32 ratio);
-const uint16_t *spl_dscl_get_easf_filter_coeffs_64p_s1_10(int taps, struct spl_fixed31_32 ratio);
+const uint16_t *SPL_NAMESPACE(spl_dscl_get_easf_filter_coeffs_64p(
+ int taps, struct spl_fixed31_32 ratio));
+const uint16_t *SPL_NAMESPACE(spl_dscl_get_easf_filter_coeffs_64p_s1_10(
+ int taps, struct spl_fixed31_32 ratio));
#endif /* __DC_SPL_SCL_EASF_FILTERS_H__ */
diff --git a/drivers/gpu/drm/amd/display/dc/sspl/dc_spl_scl_filters.c b/drivers/gpu/drm/amd/display/dc/sspl/dc_spl_scl_filters.c
index 5e52bdf1ad44..2d73d0dce5ff 100644
--- a/drivers/gpu/drm/amd/display/dc/sspl/dc_spl_scl_filters.c
+++ b/drivers/gpu/drm/amd/display/dc/sspl/dc_spl_scl_filters.c
@@ -1134,9 +1134,9 @@ static const uint16_t *spl_get_filter_3tap_64p(struct spl_fixed31_32 ratio)
{
if (ratio.value < spl_fixpt_one.value)
return filter_3tap_64p_upscale;
- else if (ratio.value < spl_fixpt_from_fraction(4, 3).value)
+ else if (ratio.value < SPL_NAMESPACE(spl_fixpt_from_fraction(4, 3)).value)
return filter_3tap_64p_116;
- else if (ratio.value < spl_fixpt_from_fraction(5, 3).value)
+ else if (ratio.value < SPL_NAMESPACE(spl_fixpt_from_fraction(5, 3)).value)
return filter_3tap_64p_149;
else
return filter_3tap_64p_183;
@@ -1146,9 +1146,9 @@ static const uint16_t *spl_get_filter_4tap_64p(struct spl_fixed31_32 ratio)
{
if (ratio.value < spl_fixpt_one.value)
return filter_4tap_64p_upscale;
- else if (ratio.value < spl_fixpt_from_fraction(4, 3).value)
+ else if (ratio.value < SPL_NAMESPACE(spl_fixpt_from_fraction(4, 3)).value)
return filter_4tap_64p_116;
- else if (ratio.value < spl_fixpt_from_fraction(5, 3).value)
+ else if (ratio.value < SPL_NAMESPACE(spl_fixpt_from_fraction(5, 3)).value)
return filter_4tap_64p_149;
else
return filter_4tap_64p_183;
@@ -1158,9 +1158,9 @@ static const uint16_t *spl_get_filter_5tap_64p(struct spl_fixed31_32 ratio)
{
if (ratio.value < spl_fixpt_one.value)
return filter_5tap_64p_upscale;
- else if (ratio.value < spl_fixpt_from_fraction(4, 3).value)
+ else if (ratio.value < SPL_NAMESPACE(spl_fixpt_from_fraction(4, 3)).value)
return filter_5tap_64p_116;
- else if (ratio.value < spl_fixpt_from_fraction(5, 3).value)
+ else if (ratio.value < SPL_NAMESPACE(spl_fixpt_from_fraction(5, 3)).value)
return filter_5tap_64p_149;
else
return filter_5tap_64p_183;
@@ -1170,9 +1170,9 @@ static const uint16_t *spl_get_filter_6tap_64p(struct spl_fixed31_32 ratio)
{
if (ratio.value < spl_fixpt_one.value)
return filter_6tap_64p_upscale;
- else if (ratio.value < spl_fixpt_from_fraction(4, 3).value)
+ else if (ratio.value < SPL_NAMESPACE(spl_fixpt_from_fraction(4, 3)).value)
return filter_6tap_64p_116;
- else if (ratio.value < spl_fixpt_from_fraction(5, 3).value)
+ else if (ratio.value < SPL_NAMESPACE(spl_fixpt_from_fraction(5, 3)).value)
return filter_6tap_64p_149;
else
return filter_6tap_64p_183;
@@ -1182,9 +1182,9 @@ static const uint16_t *spl_get_filter_7tap_64p(struct spl_fixed31_32 ratio)
{
if (ratio.value < spl_fixpt_one.value)
return filter_7tap_64p_upscale;
- else if (ratio.value < spl_fixpt_from_fraction(4, 3).value)
+ else if (ratio.value < SPL_NAMESPACE(spl_fixpt_from_fraction(4, 3)).value)
return filter_7tap_64p_116;
- else if (ratio.value < spl_fixpt_from_fraction(5, 3).value)
+ else if (ratio.value < SPL_NAMESPACE(spl_fixpt_from_fraction(5, 3)).value)
return filter_7tap_64p_149;
else
return filter_7tap_64p_183;
@@ -1194,9 +1194,9 @@ static const uint16_t *spl_get_filter_8tap_64p(struct spl_fixed31_32 ratio)
{
if (ratio.value < spl_fixpt_one.value)
return filter_8tap_64p_upscale;
- else if (ratio.value < spl_fixpt_from_fraction(4, 3).value)
+ else if (ratio.value < SPL_NAMESPACE(spl_fixpt_from_fraction(4, 3)).value)
return filter_8tap_64p_116;
- else if (ratio.value < spl_fixpt_from_fraction(5, 3).value)
+ else if (ratio.value < SPL_NAMESPACE(spl_fixpt_from_fraction(5, 3)).value)
return filter_8tap_64p_149;
else
return filter_8tap_64p_183;
@@ -1207,7 +1207,8 @@ static const uint16_t *spl_get_filter_2tap_64p(void)
return filter_2tap_64p;
}
-const uint16_t *spl_dscl_get_filter_coeffs_64p(int taps, struct spl_fixed31_32 ratio)
+const uint16_t *SPL_NAMESPACE(spl_dscl_get_filter_coeffs_64p(
+ int taps, struct spl_fixed31_32 ratio))
{
if (taps == 8)
return spl_get_filter_8tap_64p(ratio);
diff --git a/drivers/gpu/drm/amd/display/dc/sspl/dc_spl_scl_filters.h b/drivers/gpu/drm/amd/display/dc/sspl/dc_spl_scl_filters.h
index c315a438d064..445d626863c2 100644
--- a/drivers/gpu/drm/amd/display/dc/sspl/dc_spl_scl_filters.h
+++ b/drivers/gpu/drm/amd/display/dc/sspl/dc_spl_scl_filters.h
@@ -8,6 +8,7 @@
#include "dc_spl_types.h"
/* public API */
-const uint16_t *spl_dscl_get_filter_coeffs_64p(int taps, struct spl_fixed31_32 ratio);
+const uint16_t *SPL_NAMESPACE(spl_dscl_get_filter_coeffs_64p(
+ int taps, struct spl_fixed31_32 ratio));
#endif /* __DC_SPL_SCL_FILTERS_H__ */
diff --git a/drivers/gpu/drm/amd/display/dc/sspl/spl_custom_float.c b/drivers/gpu/drm/amd/display/dc/sspl/spl_custom_float.c
index be2f34d034c5..0700b3dbbda7 100644
--- a/drivers/gpu/drm/amd/display/dc/sspl/spl_custom_float.c
+++ b/drivers/gpu/drm/amd/display/dc/sspl/spl_custom_float.c
@@ -14,8 +14,8 @@ static bool spl_build_custom_float(struct spl_fixed31_32 value,
uint32_t exp_offset = (1 << (format->exponenta_bits - 1)) - 1;
const struct spl_fixed31_32 mantissa_constant_plus_max_fraction =
- spl_fixpt_from_fraction((1LL << (format->mantissa_bits + 1)) - 1,
- 1LL << format->mantissa_bits);
+ SPL_NAMESPACE(spl_fixpt_from_fraction((1LL << (format->mantissa_bits + 1)) - 1,
+ 1LL << format->mantissa_bits));
struct spl_fixed31_32 mantiss;
@@ -134,9 +134,10 @@ static bool spl_setup_custom_float(const struct spl_custom_float_format *format,
return true;
}
-bool spl_convert_to_custom_float_format(struct spl_fixed31_32 value,
- const struct spl_custom_float_format *format,
- uint32_t *result)
+bool SPL_NAMESPACE(spl_convert_to_custom_float_format(
+ struct spl_fixed31_32 value,
+ const struct spl_custom_float_format *format,
+ uint32_t *result))
{
uint32_t mantissa;
uint32_t exponenta;
diff --git a/drivers/gpu/drm/amd/display/dc/sspl/spl_custom_float.h b/drivers/gpu/drm/amd/display/dc/sspl/spl_custom_float.h
index cdc4e107b9de..f3fd8d30e638 100644
--- a/drivers/gpu/drm/amd/display/dc/sspl/spl_custom_float.h
+++ b/drivers/gpu/drm/amd/display/dc/sspl/spl_custom_float.h
@@ -21,9 +21,9 @@ struct spl_custom_float_value {
bool negative;
};
-bool spl_convert_to_custom_float_format(
+bool SPL_NAMESPACE(spl_convert_to_custom_float_format(
struct spl_fixed31_32 value,
const struct spl_custom_float_format *format,
- uint32_t *result);
+ uint32_t *result));
#endif //SPL_CUSTOM_FLOAT_H_
diff --git a/drivers/gpu/drm/amd/display/dc/sspl/spl_fixpt31_32.c b/drivers/gpu/drm/amd/display/dc/sspl/spl_fixpt31_32.c
index ebf0287417e0..ff0bdc3c33c8 100644
--- a/drivers/gpu/drm/amd/display/dc/sspl/spl_fixpt31_32.c
+++ b/drivers/gpu/drm/amd/display/dc/sspl/spl_fixpt31_32.c
@@ -44,7 +44,8 @@ static inline unsigned long long spl_complete_integer_division_u64(
#define GET_FRACTIONAL_PART(x) \
(FRACTIONAL_PART_MASK & (x))
-struct spl_fixed31_32 spl_fixpt_from_fraction(long long numerator, long long denominator)
+struct spl_fixed31_32 SPL_NAMESPACE(spl_fixpt_from_fraction(
+ long long numerator, long long denominator))
{
struct spl_fixed31_32 res;
@@ -96,7 +97,8 @@ struct spl_fixed31_32 spl_fixpt_from_fraction(long long numerator, long long den
return res;
}
-struct spl_fixed31_32 spl_fixpt_mul(struct spl_fixed31_32 arg1, struct spl_fixed31_32 arg2)
+struct spl_fixed31_32 SPL_NAMESPACE(spl_fixpt_mul(
+ struct spl_fixed31_32 arg1, struct spl_fixed31_32 arg2))
{
struct spl_fixed31_32 res;
@@ -147,7 +149,7 @@ struct spl_fixed31_32 spl_fixpt_mul(struct spl_fixed31_32 arg1, struct spl_fixed
return res;
}
-struct spl_fixed31_32 spl_fixpt_sqr(struct spl_fixed31_32 arg)
+struct spl_fixed31_32 SPL_NAMESPACE(spl_fixpt_sqr(struct spl_fixed31_32 arg))
{
struct spl_fixed31_32 res;
@@ -187,19 +189,19 @@ struct spl_fixed31_32 spl_fixpt_sqr(struct spl_fixed31_32 arg)
return res;
}
-struct spl_fixed31_32 spl_fixpt_recip(struct spl_fixed31_32 arg)
+struct spl_fixed31_32 SPL_NAMESPACE(spl_fixpt_recip(struct spl_fixed31_32 arg))
{
/*
* @note
* Good idea to use Newton's method
*/
- return spl_fixpt_from_fraction(
+ return SPL_NAMESPACE(spl_fixpt_from_fraction(
spl_fixpt_one.value,
- arg.value);
+ arg.value));
}
-struct spl_fixed31_32 spl_fixpt_sinc(struct spl_fixed31_32 arg)
+struct spl_fixed31_32 SPL_NAMESPACE(spl_fixpt_sinc(struct spl_fixed31_32 arg))
{
struct spl_fixed31_32 square;
@@ -221,15 +223,15 @@ struct spl_fixed31_32 spl_fixpt_sinc(struct spl_fixed31_32 arg)
spl_fixpt_two_pi.value)));
}
- square = spl_fixpt_sqr(arg_norm);
+ square = SPL_NAMESPACE(spl_fixpt_sqr(arg_norm));
do {
res = spl_fixpt_sub(
spl_fixpt_one,
spl_fixpt_div_int(
- spl_fixpt_mul(
+ SPL_NAMESPACE(spl_fixpt_mul(
square,
- res),
+ res)),
n * (n - 1)));
n -= 2;
@@ -237,24 +239,24 @@ struct spl_fixed31_32 spl_fixpt_sinc(struct spl_fixed31_32 arg)
if (arg.value != arg_norm.value)
res = spl_fixpt_div(
- spl_fixpt_mul(res, arg_norm),
+ SPL_NAMESPACE(spl_fixpt_mul(res, arg_norm)),
arg);
return res;
}
-struct spl_fixed31_32 spl_fixpt_sin(struct spl_fixed31_32 arg)
+struct spl_fixed31_32 SPL_NAMESPACE(spl_fixpt_sin(struct spl_fixed31_32 arg))
{
- return spl_fixpt_mul(
+ return SPL_NAMESPACE(spl_fixpt_mul(
arg,
- spl_fixpt_sinc(arg));
+ SPL_NAMESPACE(spl_fixpt_sinc(arg))));
}
-struct spl_fixed31_32 spl_fixpt_cos(struct spl_fixed31_32 arg)
+struct spl_fixed31_32 SPL_NAMESPACE(spl_fixpt_cos(struct spl_fixed31_32 arg))
{
/* TODO implement argument normalization */
- const struct spl_fixed31_32 square = spl_fixpt_sqr(arg);
+ const struct spl_fixed31_32 square = SPL_NAMESPACE(spl_fixpt_sqr(arg));
struct spl_fixed31_32 res = spl_fixpt_one;
@@ -264,9 +266,9 @@ struct spl_fixed31_32 spl_fixpt_cos(struct spl_fixed31_32 arg)
res = spl_fixpt_sub(
spl_fixpt_one,
spl_fixpt_div_int(
- spl_fixpt_mul(
+ SPL_NAMESPACE(spl_fixpt_mul(
square,
- res),
+ res)),
n * (n - 1)));
n -= 2;
@@ -286,9 +288,9 @@ static struct spl_fixed31_32 spl_fixed31_32_exp_from_taylor_series(struct spl_fi
{
unsigned int n = 9;
- struct spl_fixed31_32 res = spl_fixpt_from_fraction(
+ struct spl_fixed31_32 res = SPL_NAMESPACE(spl_fixpt_from_fraction(
n + 2,
- n + 1);
+ n + 1));
/* TODO find correct res */
SPL_ASSERT(spl_fixpt_lt(arg, spl_fixpt_one));
@@ -297,20 +299,20 @@ static struct spl_fixed31_32 spl_fixed31_32_exp_from_taylor_series(struct spl_fi
res = spl_fixpt_add(
spl_fixpt_one,
spl_fixpt_div_int(
- spl_fixpt_mul(
+ SPL_NAMESPACE(spl_fixpt_mul(
arg,
- res),
+ res)),
n));
while (--n != 1);
return spl_fixpt_add(
spl_fixpt_one,
- spl_fixpt_mul(
+ SPL_NAMESPACE(spl_fixpt_mul(
arg,
- res));
+ res)));
}
-struct spl_fixed31_32 spl_fixpt_exp(struct spl_fixed31_32 arg)
+struct spl_fixed31_32 SPL_NAMESPACE(spl_fixpt_exp(struct spl_fixed31_32 arg))
{
/*
* @brief
@@ -353,7 +355,7 @@ struct spl_fixed31_32 spl_fixpt_exp(struct spl_fixed31_32 arg)
return spl_fixpt_one;
}
-struct spl_fixed31_32 spl_fixpt_log(struct spl_fixed31_32 arg)
+struct spl_fixed31_32 SPL_NAMESPACE(spl_fixpt_log(struct spl_fixed31_32 arg))
{
struct spl_fixed31_32 res = spl_fixpt_neg(spl_fixpt_one);
/* TODO improve 1st estimation */
@@ -371,7 +373,7 @@ struct spl_fixed31_32 spl_fixpt_log(struct spl_fixed31_32 arg)
spl_fixpt_one),
spl_fixpt_div(
arg,
- spl_fixpt_exp(res)));
+ SPL_NAMESPACE(spl_fixpt_exp(res))));
error = spl_fixpt_sub(
res,
@@ -427,37 +429,37 @@ static inline unsigned int spl_clamp_ux_dy(
return min_clamp;
}
-unsigned int spl_fixpt_u4d19(struct spl_fixed31_32 arg)
+unsigned int SPL_NAMESPACE(spl_fixpt_u4d19(struct spl_fixed31_32 arg))
{
return spl_ux_dy(arg.value, 4, 19);
}
-unsigned int spl_fixpt_u3d19(struct spl_fixed31_32 arg)
+unsigned int SPL_NAMESPACE(spl_fixpt_u3d19(struct spl_fixed31_32 arg))
{
return spl_ux_dy(arg.value, 3, 19);
}
-unsigned int spl_fixpt_u2d19(struct spl_fixed31_32 arg)
+unsigned int SPL_NAMESPACE(spl_fixpt_u2d19(struct spl_fixed31_32 arg))
{
return spl_ux_dy(arg.value, 2, 19);
}
-unsigned int spl_fixpt_u0d19(struct spl_fixed31_32 arg)
+unsigned int SPL_NAMESPACE(spl_fixpt_u0d19(struct spl_fixed31_32 arg))
{
return spl_ux_dy(arg.value, 0, 19);
}
-unsigned int spl_fixpt_clamp_u0d14(struct spl_fixed31_32 arg)
+unsigned int SPL_NAMESPACE(spl_fixpt_clamp_u0d14(struct spl_fixed31_32 arg))
{
return spl_clamp_ux_dy(arg.value, 0, 14, 1);
}
-unsigned int spl_fixpt_clamp_u0d10(struct spl_fixed31_32 arg)
+unsigned int SPL_NAMESPACE(spl_fixpt_clamp_u0d10(struct spl_fixed31_32 arg))
{
return spl_clamp_ux_dy(arg.value, 0, 10, 1);
}
-int spl_fixpt_s4d19(struct spl_fixed31_32 arg)
+int SPL_NAMESPACE(spl_fixpt_s4d19(struct spl_fixed31_32 arg))
{
if (arg.value < 0)
return -(int)spl_ux_dy(spl_fixpt_abs(arg).value, 4, 19);
@@ -465,9 +467,9 @@ int spl_fixpt_s4d19(struct spl_fixed31_32 arg)
return spl_ux_dy(arg.value, 4, 19);
}
-struct spl_fixed31_32 spl_fixpt_from_ux_dy(unsigned int value,
+struct spl_fixed31_32 SPL_NAMESPACE(spl_fixpt_from_ux_dy(unsigned int value,
unsigned int integer_bits,
- unsigned int fractional_bits)
+ unsigned int fractional_bits))
{
struct spl_fixed31_32 fixpt_value = spl_fixpt_zero;
struct spl_fixed31_32 fixpt_int_value = spl_fixpt_zero;
@@ -481,10 +483,10 @@ struct spl_fixed31_32 spl_fixpt_from_ux_dy(unsigned int value,
return fixpt_value;
}
-struct spl_fixed31_32 spl_fixpt_from_int_dy(unsigned int int_value,
+struct spl_fixed31_32 SPL_NAMESPACE(spl_fixpt_from_int_dy(unsigned int int_value,
unsigned int frac_value,
unsigned int integer_bits,
- unsigned int fractional_bits)
+ unsigned int fractional_bits))
{
struct spl_fixed31_32 fixpt_value = spl_fixpt_from_int(int_value);
diff --git a/drivers/gpu/drm/amd/display/dc/sspl/spl_fixpt31_32.h b/drivers/gpu/drm/amd/display/dc/sspl/spl_fixpt31_32.h
index 9f349ffe9148..b0e639d6e97d 100644
--- a/drivers/gpu/drm/amd/display/dc/sspl/spl_fixpt31_32.h
+++ b/drivers/gpu/drm/amd/display/dc/sspl/spl_fixpt31_32.h
@@ -60,7 +60,8 @@ static const struct spl_fixed31_32 spl_fixpt_one = { 0x100000000LL };
* @brief
* result = numerator / denominator
*/
-struct spl_fixed31_32 spl_fixpt_from_fraction(long long numerator, long long denominator);
+struct spl_fixed31_32 SPL_NAMESPACE(spl_fixpt_from_fraction(
+ long long numerator, long long denominator));
/*
* @brief
@@ -280,7 +281,8 @@ static inline struct spl_fixed31_32 spl_fixpt_sub_int(struct spl_fixed31_32 arg1
* @brief
* result = arg1 * arg2
*/
-struct spl_fixed31_32 spl_fixpt_mul(struct spl_fixed31_32 arg1, struct spl_fixed31_32 arg2);
+struct spl_fixed31_32 SPL_NAMESPACE(spl_fixpt_mul(
+ struct spl_fixed31_32 arg1, struct spl_fixed31_32 arg2));
/*
@@ -289,14 +291,14 @@ struct spl_fixed31_32 spl_fixpt_mul(struct spl_fixed31_32 arg1, struct spl_fixed
*/
static inline struct spl_fixed31_32 spl_fixpt_mul_int(struct spl_fixed31_32 arg1, int arg2)
{
- return spl_fixpt_mul(arg1, spl_fixpt_from_int(arg2));
+ return SPL_NAMESPACE(spl_fixpt_mul(arg1, spl_fixpt_from_int(arg2)));
}
/*
* @brief
* result = square(arg) := arg * arg
*/
-struct spl_fixed31_32 spl_fixpt_sqr(struct spl_fixed31_32 arg);
+struct spl_fixed31_32 SPL_NAMESPACE(spl_fixpt_sqr(struct spl_fixed31_32 arg));
/*
* @brief
@@ -304,7 +306,8 @@ struct spl_fixed31_32 spl_fixpt_sqr(struct spl_fixed31_32 arg);
*/
static inline struct spl_fixed31_32 spl_fixpt_div_int(struct spl_fixed31_32 arg1, long long arg2)
{
- return spl_fixpt_from_fraction(arg1.value, spl_fixpt_from_int((int)arg2).value);
+ return SPL_NAMESPACE(spl_fixpt_from_fraction(arg1.value,
+ spl_fixpt_from_int((int)arg2).value));
}
/*
@@ -313,7 +316,7 @@ static inline struct spl_fixed31_32 spl_fixpt_div_int(struct spl_fixed31_32 arg1
*/
static inline struct spl_fixed31_32 spl_fixpt_div(struct spl_fixed31_32 arg1, struct spl_fixed31_32 arg2)
{
- return spl_fixpt_from_fraction(arg1.value, arg2.value);
+ return SPL_NAMESPACE(spl_fixpt_from_fraction(arg1.value, arg2.value));
}
/*
@@ -328,7 +331,7 @@ static inline struct spl_fixed31_32 spl_fixpt_div(struct spl_fixed31_32 arg1, st
* @note
* No special actions taken in case argument is zero.
*/
-struct spl_fixed31_32 spl_fixpt_recip(struct spl_fixed31_32 arg);
+struct spl_fixed31_32 SPL_NAMESPACE(spl_fixpt_recip(struct spl_fixed31_32 arg));
/*
* @brief
@@ -343,7 +346,7 @@ struct spl_fixed31_32 spl_fixpt_recip(struct spl_fixed31_32 arg);
* Argument specified in radians,
* internally it's normalized to [-2pi...2pi] range.
*/
-struct spl_fixed31_32 spl_fixpt_sinc(struct spl_fixed31_32 arg);
+struct spl_fixed31_32 SPL_NAMESPACE(spl_fixpt_sinc(struct spl_fixed31_32 arg));
/*
* @brief
@@ -353,7 +356,7 @@ struct spl_fixed31_32 spl_fixpt_sinc(struct spl_fixed31_32 arg);
* Argument specified in radians,
* internally it's normalized to [-2pi...2pi] range.
*/
-struct spl_fixed31_32 spl_fixpt_sin(struct spl_fixed31_32 arg);
+struct spl_fixed31_32 SPL_NAMESPACE(spl_fixpt_sin(struct spl_fixed31_32 arg));
/*
* @brief
@@ -365,7 +368,7 @@ struct spl_fixed31_32 spl_fixpt_sin(struct spl_fixed31_32 arg);
* passing arguments outside that range
* will cause incorrect result!
*/
-struct spl_fixed31_32 spl_fixpt_cos(struct spl_fixed31_32 arg);
+struct spl_fixed31_32 SPL_NAMESPACE(spl_fixpt_cos(struct spl_fixed31_32 arg));
/*
* @brief
@@ -379,7 +382,7 @@ struct spl_fixed31_32 spl_fixpt_cos(struct spl_fixed31_32 arg);
* @note
* Currently, function is verified for abs(arg) <= 1.
*/
-struct spl_fixed31_32 spl_fixpt_exp(struct spl_fixed31_32 arg);
+struct spl_fixed31_32 SPL_NAMESPACE(spl_fixpt_exp(struct spl_fixed31_32 arg));
/*
* @brief
@@ -391,7 +394,7 @@ struct spl_fixed31_32 spl_fixpt_exp(struct spl_fixed31_32 arg);
* Currently, no special actions taken
* in case of invalid argument(s). Take care!
*/
-struct spl_fixed31_32 spl_fixpt_log(struct spl_fixed31_32 arg);
+struct spl_fixed31_32 SPL_NAMESPACE(spl_fixpt_log(struct spl_fixed31_32 arg));
/*
* @brief
@@ -410,10 +413,10 @@ static inline struct spl_fixed31_32 spl_fixpt_pow(struct spl_fixed31_32 arg1, st
if (arg1.value == 0)
return arg2.value == 0 ? spl_fixpt_one : spl_fixpt_zero;
- return spl_fixpt_exp(
- spl_fixpt_mul(
- spl_fixpt_log(arg1),
- arg2));
+ return SPL_NAMESPACE(spl_fixpt_exp(
+ SPL_NAMESPACE(spl_fixpt_mul(
+ SPL_NAMESPACE(spl_fixpt_log(arg1)),
+ arg2))));
}
/*
@@ -482,19 +485,19 @@ static inline int spl_fixpt_ceil(struct spl_fixed31_32 arg)
* fractional
*/
-unsigned int spl_fixpt_u4d19(struct spl_fixed31_32 arg);
+unsigned int SPL_NAMESPACE(spl_fixpt_u4d19(struct spl_fixed31_32 arg));
-unsigned int spl_fixpt_u3d19(struct spl_fixed31_32 arg);
+unsigned int SPL_NAMESPACE(spl_fixpt_u3d19(struct spl_fixed31_32 arg));
-unsigned int spl_fixpt_u2d19(struct spl_fixed31_32 arg);
+unsigned int SPL_NAMESPACE(spl_fixpt_u2d19(struct spl_fixed31_32 arg));
-unsigned int spl_fixpt_u0d19(struct spl_fixed31_32 arg);
+unsigned int SPL_NAMESPACE(spl_fixpt_u0d19(struct spl_fixed31_32 arg));
-unsigned int spl_fixpt_clamp_u0d14(struct spl_fixed31_32 arg);
+unsigned int SPL_NAMESPACE(spl_fixpt_clamp_u0d14(struct spl_fixed31_32 arg));
-unsigned int spl_fixpt_clamp_u0d10(struct spl_fixed31_32 arg);
+unsigned int SPL_NAMESPACE(spl_fixpt_clamp_u0d10(struct spl_fixed31_32 arg));
-int spl_fixpt_s4d19(struct spl_fixed31_32 arg);
+int SPL_NAMESPACE(spl_fixpt_s4d19(struct spl_fixed31_32 arg));
static inline struct spl_fixed31_32 spl_fixpt_truncate(struct spl_fixed31_32 arg, unsigned int frac_bits)
{
@@ -513,10 +516,11 @@ static inline struct spl_fixed31_32 spl_fixpt_truncate(struct spl_fixed31_32 arg
return arg;
}
-struct spl_fixed31_32 spl_fixpt_from_ux_dy(unsigned int value, unsigned int integer_bits, unsigned int fractional_bits);
-struct spl_fixed31_32 spl_fixpt_from_int_dy(unsigned int int_value,
+struct spl_fixed31_32 SPL_NAMESPACE(spl_fixpt_from_ux_dy(unsigned int value,
+ unsigned int integer_bits, unsigned int fractional_bits));
+struct spl_fixed31_32 SPL_NAMESPACE(spl_fixpt_from_int_dy(unsigned int int_value,
unsigned int frac_value,
unsigned int integer_bits,
- unsigned int fractional_bits);
+ unsigned int fractional_bits));
#endif
diff --git a/drivers/gpu/drm/amd/display/dc/sspl/spl_os_types.h b/drivers/gpu/drm/amd/display/dc/sspl/spl_os_types.h
index 2e6ba71960ac..ae2d24c856cf 100644
--- a/drivers/gpu/drm/amd/display/dc/sspl/spl_os_types.h
+++ b/drivers/gpu/drm/amd/display/dc/sspl/spl_os_types.h
@@ -53,4 +53,13 @@ static inline int64_t spl_div64_s64(int64_t dividend, int64_t divisor)
#define spl_min(a, b) (((a) < (b)) ? (a):(b))
#endif
+/* SPL namespace macros */
+#ifndef SPL_PFX_
+#define SPL_PFX_
+#endif
+
+#define SPL_EXPAND2(a, b) a##b
+#define SPL_EXPAND(a, b) SPL_EXPAND2(a, b)
+#define SPL_NAMESPACE(symbol) SPL_EXPAND(SPL_PFX_, symbol)
+
#endif /* _SPL_OS_TYPES_H_ */
diff --git a/drivers/gpu/drm/amd/display/dmub/dmub_srv.h b/drivers/gpu/drm/amd/display/dmub/dmub_srv.h
index 9d0168986fe7..3b6bba017040 100644
--- a/drivers/gpu/drm/amd/display/dmub/dmub_srv.h
+++ b/drivers/gpu/drm/amd/display/dmub/dmub_srv.h
@@ -72,6 +72,9 @@
/* Default tracebuffer size if meta is absent. */
#define DMUB_TRACE_BUFFER_SIZE (64 * 1024)
+#define PSP_HEADER_BYTES_256 0x100 // 256 bytes
+#define PSP_FOOTER_BYTES_256 0x100 // 256 bytes
+
/* Forward declarations */
struct dmub_srv;
struct dmub_srv_common_regs;
@@ -227,6 +230,23 @@ struct dmub_srv_region_params {
const uint8_t *fw_inst_const;
const uint8_t *fw_bss_data;
const enum dmub_window_memory_type *window_memory_type;
+ const struct dmub_fw_meta_info *fw_info;
+};
+
+/**
+ * struct dmub_srv_fw_meta_info_params - params used for fetching fw meta info from fw_image
+ * @inst_const_size: size of the fw inst const section
+ * @bss_data_size: size of the fw bss data section
+ * @fw_inst_const: raw firmware inst const section
+ * @fw_bss_data: raw firmware bss data section
+ * @custom_psp_footer_size: custom psp footer size to use when indexing for fw meta info
+ */
+struct dmub_srv_fw_meta_info_params {
+ uint32_t inst_const_size;
+ uint32_t bss_data_size;
+ const uint8_t *fw_inst_const;
+ const uint8_t *fw_bss_data;
+ uint32_t custom_psp_footer_size;
};
/**
@@ -249,6 +269,7 @@ struct dmub_srv_region_info {
uint32_t gart_size;
uint8_t num_regions;
struct dmub_region regions[DMUB_WINDOW_TOTAL];
+ uint32_t verified_psp_footer_size;
};
/**
@@ -286,6 +307,16 @@ struct dmub_srv_fb_info {
struct dmub_fb fb[DMUB_WINDOW_TOTAL];
};
+/**
+ * struct dmub_soc_fb_info - relevant addresses from the frame buffer
+ * @fb_base: base of the framebuffer aperture
+ * @fb_offset: offset of the framebuffer aperture
+ */
+struct dmub_soc_fb_info {
+ uint64_t fb_base;
+ uint64_t fb_offset;
+};
+
/*
* struct dmub_srv_hw_params - params for dmub hardware initialization
* @fb: framebuffer info for each region
@@ -296,8 +327,7 @@ struct dmub_srv_fb_info {
*/
struct dmub_srv_hw_params {
struct dmub_fb *fb[DMUB_WINDOW_TOTAL];
- uint64_t fb_base;
- uint64_t fb_offset;
+ struct dmub_soc_fb_info soc_fb_info;
uint32_t psp_version;
bool load_inst_const;
bool skip_panel_power_sequence;
@@ -589,8 +619,7 @@ struct dmub_srv {
bool hw_init;
bool dpia_supported;
- uint64_t fb_base;
- uint64_t fb_offset;
+ struct dmub_soc_fb_info soc_fb_info;
uint32_t psp_version;
/* Feature capabilities reported by fw */
@@ -1098,4 +1127,16 @@ enum dmub_status dmub_srv_update_inbox_status(struct dmub_srv *dmub);
*/
bool dmub_srv_get_preos_info(struct dmub_srv *dmub);
+/**
+ * dmub_srv_get_fw_meta_info_from_raw_fw() - Fetch firmware metadata info from raw firmware image
+ * @params: parameters for fetching firmware metadata info
+ * @fw_info_out: output buffer for firmware metadata info
+ *
+ * Return:
+ * DMUB_STATUS_OK - success
+ * DMUB_STATUS_INVALID - no FW meta info found
+ */
+enum dmub_status dmub_srv_get_fw_meta_info_from_raw_fw(struct dmub_srv_fw_meta_info_params *params,
+ struct dmub_fw_meta_info *fw_info_out);
+
#endif /* _DMUB_SRV_H_ */
diff --git a/drivers/gpu/drm/amd/display/dmub/inc/dmub_cmd.h b/drivers/gpu/drm/amd/display/dmub/inc/dmub_cmd.h
index 3f2a0ed02c59..18e0bdfd6ff4 100644
--- a/drivers/gpu/drm/amd/display/dmub/inc/dmub_cmd.h
+++ b/drivers/gpu/drm/amd/display/dmub/inc/dmub_cmd.h
@@ -139,6 +139,33 @@
*/
#define DMUB_CMD_PSR_CONTROL_VERSION_1 0x1
+/**
+ *
+ * dirty rect cmd version legacy
+ */
+#define DMUB_CMD_DIRTY_RECTS_VERSION_UNKNOWN 0x0
+/**
+ * dirty rect cmd version with multi edp support
+ */
+#define DMUB_CMD_DIRTY_RECTS_VERSION_1 0x1
+/**
+ * dirty rect cmd version with external monitor support
+ */
+#define DMUB_CMD_DIRTY_RECTS_VERSION_2 0x2
+
+/**
+ *
+ * Cursor update cmd version legacy
+ */
+#define DMUB_CMD_CURSOR_UPDATE_VERSION_UNKNOWN 0x0
+/**
+ * Cursor update cmd version with multi edp support
+ */
+#define DMUB_CMD_CURSOR_UPDATE_VERSION_1 0x1
+/**
+ * Cursor update cmd version with external monitor support
+ */
+#define DMUB_CMD_CURSOR_UPDATE_VERSION_2 0x2
/**
* ABM control version legacy
@@ -636,17 +663,29 @@ union pr_debug_flags {
/**
* 0x10 (bit 4)
- * @skip_crtc_disabled: CRTC disable skipped
+ * @visual_confirm_rate_control: Enable Visual Confirm rate control detection
*/
- uint32_t skip_crtc_disabled : 1;
+ uint32_t visual_confirm_rate_control : 1;
- /*
+ /**
* 0x20 (bit 5)
- * @visual_confirm_rate_control: Enable Visual Confirm rate control detection
+ * @force_full_frame_update: Force all selective updates to be full frame updates
*/
- uint32_t visual_confirm_rate_control : 1;
+ uint32_t force_full_frame_update : 1;
- uint32_t reserved : 26;
+ /**
+ * 0x40 (bit 6)
+ * @force_dpg_on: Force DPG on
+ */
+ uint32_t force_dpg_on : 1;
+
+ /**
+ * 0x80 (bit 7)
+ * @force_hubp_on: Force Hubp on
+ */
+ uint32_t force_hubp_on : 1;
+
+ uint32_t reserved : 24;
} bitfields;
uint32_t u32All;
@@ -669,19 +708,12 @@ union pr_hw_flags {
* @fec_enable_status: receive fec enable/disable status from driver
*/
uint32_t fec_enable_status : 1;
-
/*
* @smu_optimizations_en: SMU power optimization.
* Only when active display is Replay capable and display enters Replay.
* Trigger interrupt to SMU to powerup/down.
*/
uint32_t smu_optimizations_en : 1;
-
- /**
- * @phy_power_state: Indicates current phy power state
- */
- uint32_t phy_power_state : 1;
-
/**
* @link_power_state: Indicates current link power state
*/
@@ -698,6 +730,7 @@ union pr_hw_flags {
* @alpm_mode: Indicates ALPM mode selected
*/
uint32_t alpm_mode : 2;
+ uint32_t reserved : 23;
} bitfields;
uint32_t u32All;
@@ -1085,7 +1118,10 @@ union dmub_fw_boot_options {
uint32_t lower_hbr3_phy_ssc: 1; /**< 1 to lower hbr3 phy ssc to 0.125 percent */
uint32_t override_hbr3_pll_vco: 1; /**< 1 to override the hbr3 pll vco to 0 */
uint32_t disable_dpia_bw_allocation: 1; /**< 1 to disable the USB4 DPIA BW allocation */
- uint32_t reserved : 4; /**< reserved */
+ uint32_t bootcrc_en_at_preos: 1; /**< 1 to run the boot time crc during warm/cold boot*/
+ uint32_t bootcrc_en_at_S0i3: 1; /**< 1 to run the boot time crc during S0i3 boot*/
+ uint32_t bootcrc_boot_mode: 1; /**< 1 for S0i3 resume and 0 for Warm/cold boot*/
+ uint32_t reserved : 1; /**< reserved */
} bits; /**< boot bits */
uint32_t all; /**< 32-bit access to bits */
};
@@ -1626,9 +1662,9 @@ union dmub_inbox0_cmd_lock_hw {
uint32_t lock_dig: 1;
uint32_t triple_buffer_lock: 1;
- uint32_t lock: 1; /**< Lock */
+ uint32_t lock: 1; /**< Lock */
uint32_t should_release: 1; /**< Release */
- uint32_t reserved: 7; /**< Reserved for extending more clients, HW, etc. */
+ uint32_t reserved: 7; /**< Reserved for extending more clients, HW, etc. */
} bits;
uint32_t all;
};
@@ -2496,6 +2532,7 @@ struct dmub_fams2_drr_stream_static_state {
struct dmub_fams2_cmd_legacy_stream_static_state {
uint16_t vactive_det_fill_delay_otg_vlines;
uint16_t programming_delay_otg_vlines;
+ uint32_t disallow_time_us;
}; //v1
struct dmub_fams2_cmd_subvp_stream_static_state {
@@ -2630,7 +2667,8 @@ union dmub_fams2_global_feature_config {
uint32_t enable_offload_flip: 1;
uint32_t enable_visual_confirm: 1;
uint32_t allow_delay_check_mode: 2;
- uint32_t reserved: 24;
+ uint32_t legacy_method_no_fams2 : 1;
+ uint32_t reserved : 23;
} bits;
uint32_t all;
};
@@ -2647,7 +2685,6 @@ struct dmub_cmd_fams2_global_config {
union dmub_cmd_fams2_config {
struct dmub_cmd_fams2_global_config global;
-// coverity[cert_dcl37_c_violation:FALSE] errno.h, stddef.h, stdint.h not included in atombios.h
struct dmub_fams2_stream_static_state stream; //v0
union {
struct dmub_fams2_cmd_stream_static_base_state base;
@@ -3667,7 +3704,7 @@ struct dmub_cmd_psr_copy_settings_data {
/**
* @ rate_control_caps : Indicate FreeSync PSR Sink Capabilities
*/
- uint8_t rate_control_caps ;
+ uint8_t rate_control_caps;
/*
* Force PSRSU always doing full frame update
*/
@@ -3919,7 +3956,7 @@ struct dmub_cmd_update_dirty_rect_data {
*/
union dmub_psr_su_debug_flags debug_flags;
/**
- * OTG HW instance.
+ * Pipe index.
*/
uint8_t pipe_idx;
/**
@@ -3927,7 +3964,7 @@ struct dmub_cmd_update_dirty_rect_data {
*/
uint8_t dirty_rect_count;
/**
- * PSR control version.
+ * dirty rects cmd version.
*/
uint8_t cmd_version;
/**
@@ -3936,6 +3973,14 @@ struct dmub_cmd_update_dirty_rect_data {
* Currently the support is only for 0 or 1
*/
uint8_t panel_inst;
+ /**
+ * OTG HW instance
+ */
+ uint8_t otg_inst;
+ /**
+ * Padding for 4 byte alignment
+ */
+ uint8_t padding[3];
};
/**
@@ -4061,11 +4106,11 @@ struct dmub_cmd_update_cursor_payload0 {
*/
uint8_t enable;
/**
- * OTG HW instance.
+ * Pipe index.
*/
uint8_t pipe_idx;
/**
- * PSR control version.
+ * Cursor update cmd version.
*/
uint8_t cmd_version;
/**
@@ -4079,6 +4124,14 @@ struct dmub_cmd_update_cursor_payload0 {
* Registers contains Hubp & Dpp modules
*/
struct dmub_cursor_position_cfg position_cfg;
+ /**
+ * OTG HW instance
+ */
+ uint8_t otg_inst;
+ /**
+ * Padding for 4 byte alignment
+ */
+ uint8_t padding[3];
};
struct dmub_cmd_update_cursor_payload1 {
@@ -4277,7 +4330,7 @@ enum pr_state {
// Active and Pending Power Up
PR_STATE_2_PENDING_POWER_UP = 0x33,
// Active and Powered Up, Pending DPG latch
- PR_STATE_2_PENDING_LOCK_FOR_DPG_POWER_ON = 0x34,
+ PR_STATE_2_PENDING_LOCK = 0x34,
// Active and Powered Up, Pending SDP and Unlock
PR_STATE_2_PENDING_SDP_AND_UNLOCK = 0x35,
// Pending transmission of AS SDP for timing sync, but no rfb update
@@ -4327,10 +4380,6 @@ enum dmub_cmd_replay_type {
*/
DMUB_CMD__REPLAY_DISABLED_ADAPTIVE_SYNC_SDP = 8,
/**
- * Set version
- */
- DMUB_CMD__REPLAY_SET_VERSION = 9,
- /**
* Set Replay General command.
*/
DMUB_CMD__REPLAY_SET_GENERAL_CMD = 16,
@@ -4371,6 +4420,7 @@ enum dmub_cmd_replay_general_subtype {
REPLAY_GENERAL_CMD_UPDATE_ERROR_STATUS,
REPLAY_GENERAL_CMD_SET_LOW_RR_ACTIVATE,
REPLAY_GENERAL_CMD_VIDEO_CONFERENCING,
+ REPLAY_GENERAL_CMD_SET_CONTINUOUSLY_RESYNC,
};
struct dmub_alpm_auxless_data {
@@ -4498,40 +4548,6 @@ enum replay_version {
};
/**
- * Data passed from driver to FW in a DMUB_CMD___SET_REPLAY_VERSION command.
- */
-struct dmub_cmd_replay_set_version_data {
- /**
- * Panel Instance.
- * Panel instance to identify which psr_state to use
- * Currently the support is only for 0 or 1
- */
- uint8_t panel_inst;
- /**
- * Replay version that FW should implement.
- */
- enum replay_version version;
- /**
- * Explicit padding to 4 byte boundary.
- */
- uint8_t pad[3];
-};
-
-/**
- * Definition of a DMUB_CMD__REPLAY_SET_VERSION command.
- */
-struct dmub_rb_cmd_replay_set_version {
- /**
- * Command header.
- */
- struct dmub_cmd_header header;
- /**
- * Data passed from driver to FW in a DMUB_CMD__REPLAY_SET_VERSION command.
- */
- struct dmub_cmd_replay_set_version_data replay_set_version_data;
-};
-
-/**
* Definition of a DMUB_CMD__REPLAY_COPY_SETTINGS command.
*/
struct dmub_rb_cmd_replay_copy_settings {
@@ -4922,10 +4938,6 @@ union dmub_replay_cmd_set {
*/
struct dmub_cmd_replay_disabled_adaptive_sync_sdp_data disabled_adaptive_sync_sdp_data;
/**
- * Definition of DMUB_CMD__REPLAY_SET_VERSION command data.
- */
- struct dmub_cmd_replay_set_version_data version_data;
- /**
* Definition of DMUB_CMD__REPLAY_SET_GENERAL_CMD command data.
*/
struct dmub_cmd_replay_set_general_cmd_data set_general_cmd_data;
@@ -5194,8 +5206,8 @@ enum dmub_cmd_lsdma_type {
*/
DMUB_CMD__LSDMA_LINEAR_COPY = 1,
/**
- * LSDMA copies data from source to destination linearly in sub window
- */
+ * LSDMA copies data from source to destination linearly in sub window
+ */
DMUB_CMD__LSDMA_LINEAR_SUB_WINDOW_COPY = 2,
/**
* Send the tiled-to-tiled copy command
@@ -6604,10 +6616,6 @@ struct dmub_cmd_pr_copy_settings_data {
*/
uint8_t panel_inst;
/**
- * Length of each horizontal line in ns.
- */
- uint32_t line_time_in_ns;
- /**
* PHY instance.
*/
uint8_t dpphy_inst;
@@ -6615,10 +6623,10 @@ struct dmub_cmd_pr_copy_settings_data {
* Determines if SMU optimzations are enabled/disabled.
*/
uint8_t smu_optimizations_en;
- /*
- * Use FSM state for Replay power up/down
+ /**
+ * Length of each horizontal line in ns.
*/
- uint8_t use_phy_fsm;
+ uint32_t line_time_in_ns;
/*
* Use FSFT afftet pixel clk
*/
@@ -6632,6 +6640,14 @@ struct dmub_cmd_pr_copy_settings_data {
*/
struct dmub_alpm_auxless_data auxless_alpm_data;
/**
+ * DSC Slice height.
+ */
+ uint16_t dsc_slice_height;
+ /*
+ * Use FSM state for Replay power up/down
+ */
+ uint8_t use_phy_fsm;
+ /**
* @hpo_stream_enc_inst: HPO stream encoder instance
*/
uint8_t hpo_stream_enc_inst;
@@ -6639,10 +6655,26 @@ struct dmub_cmd_pr_copy_settings_data {
* @hpo_link_enc_inst: HPO link encoder instance
*/
uint8_t hpo_link_enc_inst;
+ /*
+ * Selective Update granularity needed.
+ */
+ uint8_t su_granularity_needed;
+ /*
+ * Horizontal granularity for Selective Update.
+ */
+ uint16_t su_x_granularity;
+ /*
+ * Extended caps of vertical granularity for Selective Update.
+ */
+ uint16_t su_y_granularity_extended_caps;
+ /*
+ * Vertical granularity for Selective Update.
+ */
+ uint8_t su_y_granularity;
/**
- * @pad: Align structure to 4 byte boundary.
+ * @main_link_activity_option: Indicates main link activity option selected
*/
- uint8_t pad[2];
+ uint8_t main_link_activity_option;
};
/**
@@ -6992,10 +7024,6 @@ union dmub_rb_cmd {
* Definition of a DMUB_CMD__IDLE_OPT_SET_DC_POWER_STATE command.
*/
struct dmub_rb_cmd_idle_opt_set_dc_power_state idle_opt_set_dc_power_state;
- /**
- * Definition of a DMUB_CMD__REPLAY_SET_VERSION command.
- */
- struct dmub_rb_cmd_replay_set_version replay_set_version;
/*
* Definition of a DMUB_CMD__REPLAY_COPY_SETTINGS command.
*/
diff --git a/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn20.c b/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn20.c
index 73888c1bea93..54df2147e4dc 100644
--- a/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn20.c
+++ b/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn20.c
@@ -63,9 +63,9 @@ static void dmub_dcn20_get_fb_base_offset(struct dmub_srv *dmub,
{
uint32_t tmp;
- if (dmub->fb_base || dmub->fb_offset) {
- *fb_base = dmub->fb_base;
- *fb_offset = dmub->fb_offset;
+ if (dmub->soc_fb_info.fb_base || dmub->soc_fb_info.fb_offset) {
+ *fb_base = dmub->soc_fb_info.fb_base;
+ *fb_offset = dmub->soc_fb_info.fb_offset;
return;
}
diff --git a/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn30.c b/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn30.c
index a4abe951c838..84a6eb3f677d 100644
--- a/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn30.c
+++ b/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn30.c
@@ -63,9 +63,9 @@ static void dmub_dcn30_get_fb_base_offset(struct dmub_srv *dmub,
{
uint32_t tmp;
- if (dmub->fb_base || dmub->fb_offset) {
- *fb_base = dmub->fb_base;
- *fb_offset = dmub->fb_offset;
+ if (dmub->soc_fb_info.fb_base || dmub->soc_fb_info.fb_offset) {
+ *fb_base = dmub->soc_fb_info.fb_base;
+ *fb_offset = dmub->soc_fb_info.fb_offset;
return;
}
diff --git a/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn31.c b/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn31.c
index cd04d7c756c3..a0cefc03b21d 100644
--- a/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn31.c
+++ b/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn31.c
@@ -59,9 +59,9 @@ static void dmub_dcn31_get_fb_base_offset(struct dmub_srv *dmub,
{
uint32_t tmp;
- if (dmub->fb_base || dmub->fb_offset) {
- *fb_base = dmub->fb_base;
- *fb_offset = dmub->fb_offset;
+ if (dmub->soc_fb_info.fb_base || dmub->soc_fb_info.fb_offset) {
+ *fb_base = dmub->soc_fb_info.fb_base;
+ *fb_offset = dmub->soc_fb_info.fb_offset;
return;
}
diff --git a/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn32.c b/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn32.c
index 7e9856289910..2f99a2772599 100644
--- a/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn32.c
+++ b/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn32.c
@@ -65,9 +65,9 @@ static void dmub_dcn32_get_fb_base_offset(struct dmub_srv *dmub,
{
uint32_t tmp;
- if (dmub->fb_base || dmub->fb_offset) {
- *fb_base = dmub->fb_base;
- *fb_offset = dmub->fb_offset;
+ if (dmub->soc_fb_info.fb_base || dmub->soc_fb_info.fb_offset) {
+ *fb_base = dmub->soc_fb_info.fb_base;
+ *fb_offset = dmub->soc_fb_info.fb_offset;
return;
}
diff --git a/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn35.c b/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn35.c
index e13557ed97be..639f9835e5e9 100644
--- a/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn35.c
+++ b/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn35.c
@@ -63,9 +63,9 @@ static void dmub_dcn35_get_fb_base_offset(struct dmub_srv *dmub,
uint32_t tmp;
/*
- if (dmub->fb_base || dmub->fb_offset) {
- *fb_base = dmub->fb_base;
- *fb_offset = dmub->fb_offset;
+ if (dmub->soc_fb_info.fb_base || dmub->soc_fb_info.fb_offset) {
+ *fb_base = dmub->soc_fb_info.fb_base;
+ *fb_offset = dmub->soc_fb_info.fb_offset;
return;
}
*/
@@ -419,6 +419,9 @@ void dmub_dcn35_enable_dmub_boot_options(struct dmub_srv *dmub, const struct dmu
boot_options.bits.enable_non_transparent_setconfig = params->enable_non_transparent_setconfig;
boot_options.bits.lower_hbr3_phy_ssc = params->lower_hbr3_phy_ssc;
boot_options.bits.disable_dpia_bw_allocation = params->disable_dpia_bw_allocation;
+ boot_options.bits.bootcrc_en_at_preos = dmub_dcn35_get_fw_boot_option(dmub).bits.bootcrc_en_at_preos;
+ boot_options.bits.bootcrc_en_at_S0i3 = dmub_dcn35_get_fw_boot_option(dmub).bits.bootcrc_en_at_S0i3;
+ boot_options.bits.bootcrc_boot_mode = dmub_dcn35_get_fw_boot_option(dmub).bits.bootcrc_boot_mode;
REG_WRITE(DMCUB_SCRATCH14, boot_options.all);
}
diff --git a/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn401.c b/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn401.c
index 95542299e3b3..16ed07f0e96d 100644
--- a/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn401.c
+++ b/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn401.c
@@ -39,9 +39,9 @@ static void dmub_dcn401_get_fb_base_offset(struct dmub_srv *dmub,
{
uint32_t tmp;
- if (dmub->fb_base || dmub->fb_offset) {
- *fb_base = dmub->fb_base;
- *fb_offset = dmub->fb_offset;
+ if (dmub->soc_fb_info.fb_base || dmub->soc_fb_info.fb_offset) {
+ *fb_base = dmub->soc_fb_info.fb_base;
+ *fb_offset = dmub->soc_fb_info.fb_offset;
return;
}
diff --git a/drivers/gpu/drm/amd/display/dmub/src/dmub_srv.c b/drivers/gpu/drm/amd/display/dmub/src/dmub_srv.c
index a6ae1d2e9685..83cf4888fb54 100644
--- a/drivers/gpu/drm/amd/display/dmub/src/dmub_srv.c
+++ b/drivers/gpu/drm/amd/display/dmub/src/dmub_srv.c
@@ -66,7 +66,7 @@
#define DMUB_SCRATCH_MEM_SIZE (1024)
/* Default indirect buffer size. */
-#define DMUB_IB_MEM_SIZE (2560)
+#define DMUB_IB_MEM_SIZE (sizeof(struct dmub_fams2_config_v2))
/* Default LSDMA ring buffer size. */
#define DMUB_LSDMA_RB_SIZE (64 * 1024)
@@ -134,7 +134,7 @@ dmub_get_fw_meta_info_from_blob(const uint8_t *blob, uint32_t blob_size, uint32_
}
static const struct dmub_fw_meta_info *
-dmub_get_fw_meta_info(const struct dmub_srv_region_params *params)
+dmub_get_fw_meta_info(const struct dmub_srv_fw_meta_info_params *params)
{
const struct dmub_fw_meta_info *info = NULL;
@@ -159,6 +159,46 @@ dmub_get_fw_meta_info(const struct dmub_srv_region_params *params)
return info;
}
+enum dmub_status
+dmub_srv_get_fw_meta_info_from_raw_fw(struct dmub_srv_fw_meta_info_params *params,
+ struct dmub_fw_meta_info *fw_info_out)
+{
+ const struct dmub_fw_meta_info *fw_info = NULL;
+ uint32_t inst_const_size_temp = params->inst_const_size;
+
+ /* First try custom psp footer size, if present */
+ if (params->custom_psp_footer_size) {
+ params->inst_const_size -= params->custom_psp_footer_size;
+ fw_info = dmub_get_fw_meta_info(params);
+ if (fw_info) {
+ memcpy(fw_info_out, fw_info, sizeof(*fw_info));
+ return DMUB_STATUS_OK;
+ }
+ params->inst_const_size = inst_const_size_temp;
+ }
+
+ /* Try 256-byte psp footer size */
+ params->inst_const_size -= PSP_FOOTER_BYTES_256;
+ fw_info = dmub_get_fw_meta_info(params);
+ if (fw_info) {
+ memcpy(fw_info_out, fw_info, sizeof(*fw_info));
+ return DMUB_STATUS_OK;
+ }
+
+ /* Try 512-byte psp footer size - final attempt */
+ params->inst_const_size -= PSP_FOOTER_BYTES_256; // 256 bytes already subtracted, subtract 256 again
+ fw_info = dmub_get_fw_meta_info(params);
+ if (fw_info) {
+ memcpy(fw_info_out, fw_info, sizeof(*fw_info));
+ return DMUB_STATUS_OK;
+ }
+
+ /* Restore original inst_const_size and subtract default PSP footer size - default behaviour */
+ params->inst_const_size = inst_const_size_temp - PSP_FOOTER_BYTES_256;
+
+ return DMUB_STATUS_INVALID;
+}
+
static bool dmub_srv_hw_setup(struct dmub_srv *dmub, enum dmub_asic asic)
{
struct dmub_srv_hw_funcs *funcs = &dmub->hw_funcs;
@@ -524,7 +564,6 @@ enum dmub_status
const struct dmub_srv_region_params *params,
struct dmub_srv_region_info *out)
{
- const struct dmub_fw_meta_info *fw_info;
uint32_t fw_state_size = DMUB_FW_STATE_SIZE;
uint32_t trace_buffer_size = DMUB_TRACE_BUFFER_SIZE;
uint32_t shared_state_size = DMUB_FW_HEADER_SHARED_STATE_SIZE;
@@ -538,14 +577,12 @@ enum dmub_status
out->num_regions = DMUB_NUM_WINDOWS;
- fw_info = dmub_get_fw_meta_info(params);
-
- if (fw_info) {
- memcpy(&dmub->meta_info, fw_info, sizeof(*fw_info));
+ if (params->fw_info) {
+ memcpy(&dmub->meta_info, params->fw_info, sizeof(*params->fw_info));
- fw_state_size = fw_info->fw_region_size;
- trace_buffer_size = fw_info->trace_buffer_size;
- shared_state_size = fw_info->shared_state_size;
+ fw_state_size = params->fw_info->fw_region_size;
+ trace_buffer_size = params->fw_info->trace_buffer_size;
+ shared_state_size = params->fw_info->shared_state_size;
/**
* If DM didn't fill in a version, then fill it in based on
@@ -555,7 +592,7 @@ enum dmub_status
* pass during creation.
*/
if (dmub->fw_version == 0)
- dmub->fw_version = fw_info->fw_version;
+ dmub->fw_version = params->fw_info->fw_version;
}
window_sizes[DMUB_WINDOW_0_INST_CONST] = params->inst_const_size;
@@ -566,7 +603,7 @@ enum dmub_status
window_sizes[DMUB_WINDOW_5_TRACEBUFF] = trace_buffer_size;
window_sizes[DMUB_WINDOW_6_FW_STATE] = fw_state_size;
window_sizes[DMUB_WINDOW_7_SCRATCH_MEM] = dmub_align(DMUB_SCRATCH_MEM_SIZE, 64);
- window_sizes[DMUB_WINDOW_IB_MEM] = DMUB_IB_MEM_SIZE;
+ window_sizes[DMUB_WINDOW_IB_MEM] = dmub_align(DMUB_IB_MEM_SIZE, 64);
window_sizes[DMUB_WINDOW_SHARED_STATE] = max(DMUB_FW_HEADER_SHARED_STATE_SIZE, shared_state_size);
window_sizes[DMUB_WINDOW_LSDMA_BUFFER] = DMUB_LSDMA_RB_SIZE;
window_sizes[DMUB_WINDOW_CURSOR_OFFLOAD] = dmub_align(sizeof(struct dmub_cursor_offload_v1), 64);
@@ -672,8 +709,7 @@ enum dmub_status dmub_srv_hw_init(struct dmub_srv *dmub,
}
}
- dmub->fb_base = params->fb_base;
- dmub->fb_offset = params->fb_offset;
+ memcpy(&dmub->soc_fb_info, &params->soc_fb_info, sizeof(params->soc_fb_info));
dmub->psp_version = params->psp_version;
if (dmub->hw_funcs.reset)
diff --git a/drivers/gpu/drm/amd/display/include/dpcd_defs.h b/drivers/gpu/drm/amd/display/include/dpcd_defs.h
index 07b937b92efc..1afa10e85eb5 100644
--- a/drivers/gpu/drm/amd/display/include/dpcd_defs.h
+++ b/drivers/gpu/drm/amd/display/include/dpcd_defs.h
@@ -37,6 +37,21 @@
#ifndef DP_PANEL_REPLAY_CAPABILITY // can remove this once the define gets into linux drm_dp_helper.h
#define DP_PANEL_REPLAY_CAPABILITY 0x0b1
#endif /* DP_PANEL_REPLAY_CAPABILITY */
+#ifndef DP_PR_SU_X_GRANULARITY_LOW // can remove this once the define gets into linux drm_dp_helper.h
+#define DP_PR_SU_X_GRANULARITY_LOW 0x0b2
+#endif /* DP_PR_SU_X_GRANULARITY_LOW */
+#ifndef DP_PR_SU_X_GRANULARITY_HIGH // can remove this once the define gets into linux drm_dp_helper.h
+#define DP_PR_SU_X_GRANULARITY_HIGH 0x0b3
+#endif /* DP_PR_SU_X_GRANULARITY_HIGH */
+#ifndef DP_PR_SU_Y_GRANULARITY // can remove this once the define gets into linux drm_dp_helper.h
+#define DP_PR_SU_Y_GRANULARITY 0x0b4
+#endif /* DP_PR_SU_Y_GRANULARITY */
+#ifndef DP_PR_SU_Y_GRANULARITY_EXTENDED_CAP_LOW // can remove this once the define gets into linux drm_dp_helper.h
+#define DP_PR_SU_Y_GRANULARITY_EXTENDED_CAP_LOW 0x0b5
+#endif /* DP_PR_SU_Y_GRANULARITY_EXTENDED_CAP_LOW */
+#ifndef DP_PR_SU_Y_GRANULARITY_EXTENDED_CAP_HIGH // can remove this once the define gets into linux drm_dp_helper.h
+#define DP_PR_SU_Y_GRANULARITY_EXTENDED_CAP_HIGH 0x0b6
+#endif /* DP_PR_SU_Y_GRANULARITY_EXTENDED_CAP_HIGH */
#ifndef DP_PANEL_REPLAY_ENABLE_AND_CONFIGURATION_1 // can remove this once the define gets into linux drm_dp_helper.h
#define DP_PANEL_REPLAY_ENABLE_AND_CONFIGURATION_1 0x1b0
#endif /* DP_PANEL_REPLAY_ENABLE_AND_CONFIGURATION_1 */
@@ -46,6 +61,21 @@
#ifndef DP_PANEL_REPLAY_ENABLE_AND_CONFIGURATION_2 // can remove this once the define gets into linux drm_dp_helper.h
#define DP_PANEL_REPLAY_ENABLE_AND_CONFIGURATION_2 0x1b1
#endif /* DP_PANEL_REPLAY_ENABLE_AND_CONFIGURATION_2 */
+#ifndef DP_PR_ERROR_STATUS // can remove this once the define gets into linux drm_dp_helper.h
+#define DP_PR_ERROR_STATUS 0x2020 /* DP 2.0 */
+#endif /* DP_PR_ERROR_STATUS */
+#ifndef DP_PR_LINK_CRC_ERROR // can remove this once the define gets into linux drm_dp_helper.h
+#define DP_PR_LINK_CRC_ERROR (1 << 0)
+#endif /* DP_PR_LINK_CRC_ERROR */
+#ifndef DP_PR_RFB_STORAGE_ERROR // can remove this once the define gets into linux drm_dp_helper.h
+#define DP_PR_RFB_STORAGE_ERROR (1 << 1)
+#endif /* DP_PR_RFB_STORAGE_ERROR */
+#ifndef DP_PR_VSC_SDP_UNCORRECTABLE_ERROR // can remove this once the define gets into linux drm_dp_helper.h
+#define DP_PR_VSC_SDP_UNCORRECTABLE_ERROR (1 << 2) /* eDP 1.4 */
+#endif /* DP_PR_VSC_SDP_UNCORRECTABLE_ERROR */
+#ifndef DP_PR_ASSDP_MISSING_ERROR // can remove this once the define gets into linux drm_dp_helper.h
+#define DP_PR_ASSDP_MISSING_ERROR (1 << 3) /* eDP 1.5 */
+#endif /* DP_PR_ASSDP_MISSING_ERROR */
enum dpcd_revision {
DPCD_REV_10 = 0x10,
@@ -188,11 +218,13 @@ enum dpcd_psr_sink_states {
#define DP_SOURCE_BACKLIGHT_CURRENT_PEAK 0x326
#define DP_SOURCE_BACKLIGHT_CONTROL 0x32E
#define DP_SOURCE_BACKLIGHT_ENABLE 0x32F
+#define DP_SINK_DRR_GRANULARITY 0x33B
#define DP_SOURCE_MINIMUM_HBLANK_SUPPORTED 0x340
#define DP_SINK_PR_REPLAY_STATUS 0x378
#define DP_SINK_PR_PIXEL_DEVIATION_PER_LINE 0x379
#define DP_SINK_PR_MAX_NUMBER_OF_DEVIATION_LINE 0x37A
#define DP_SINK_EMISSION_RATE 0x37E
+#define DP_SINK_PR_FRAME_SKIP_COUNT 0x337
/* Remove once drm_dp_helper.h is updated upstream */
#ifndef DP_TOTAL_LTTPR_CNT
diff --git a/drivers/gpu/drm/amd/display/modules/inc/mod_info_packet.h b/drivers/gpu/drm/amd/display/modules/inc/mod_info_packet.h
index 66dc9a19aebe..ddd64b7e4c04 100644
--- a/drivers/gpu/drm/amd/display/modules/inc/mod_info_packet.h
+++ b/drivers/gpu/drm/amd/display/modules/inc/mod_info_packet.h
@@ -33,6 +33,12 @@ struct dc_stream_state;
struct dc_info_packet;
struct mod_vrr_params;
+void set_vsc_packet_colorimetry_data(
+ const struct dc_stream_state *stream,
+ struct dc_info_packet *info_packet,
+ enum dc_color_space cs,
+ enum color_transfer_func tf);
+
void mod_build_vsc_infopacket(const struct dc_stream_state *stream,
struct dc_info_packet *info_packet,
enum dc_color_space cs,
diff --git a/drivers/gpu/drm/amd/display/modules/info_packet/info_packet.c b/drivers/gpu/drm/amd/display/modules/info_packet/info_packet.c
index b3d55cac3569..00473c6284d5 100644
--- a/drivers/gpu/drm/amd/display/modules/info_packet/info_packet.c
+++ b/drivers/gpu/drm/amd/display/modules/info_packet/info_packet.c
@@ -42,6 +42,10 @@ enum vsc_packet_revision {
vsc_packet_rev4 = 4,
//05h = 3D stereo + PSR/PSR2 + Y-coordinate + Pixel Encoding/Colorimetry Format
vsc_packet_rev5 = 5,
+ //06h = 3D stereo + PR + Y-coordinate
+ vsc_packet_rev6 = 6,
+ //07h = 3D stereo + PR + Y-coordinate + Pixel Encoding/Colorimetry Format
+ vsc_packet_rev7 = 7,
};
#define HDMI_INFOFRAME_TYPE_VENDOR 0x81
@@ -130,6 +134,163 @@ enum ColorimetryYCCDP {
ColorimetryYCC_DP_ITU2020YCbCr = 7,
};
+/* Helper function to set VSC packet colorimetry data */
+void set_vsc_packet_colorimetry_data(
+ const struct dc_stream_state *stream,
+ struct dc_info_packet *info_packet,
+ enum dc_color_space cs,
+ enum color_transfer_func tf)
+{
+ /* Set VSC SDP fields for pixel encoding and colorimetry format from DP 1.3 specs
+ * Data Bytes DB 18~16
+ * Bits 3:0 (Colorimetry Format) | Bits 7:4 (Pixel Encoding)
+ * ----------------------------------------------------------------------------------------------------
+ * 0x0 = sRGB | 0 = RGB
+ * 0x1 = RGB Wide Gamut Fixed Point
+ * 0x2 = RGB Wide Gamut Floating Point
+ * 0x3 = AdobeRGB
+ * 0x4 = DCI-P3
+ * 0x5 = CustomColorProfile
+ * (others reserved)
+ * ----------------------------------------------------------------------------------------------------
+ * 0x0 = ITU-R BT.601 | 1 = YCbCr444
+ * 0x1 = ITU-R BT.709
+ * 0x2 = xvYCC601
+ * 0x3 = xvYCC709
+ * 0x4 = sYCC601
+ * 0x5 = AdobeYCC601
+ * 0x6 = ITU-R BT.2020 Y'cC'bcC'rc
+ * 0x7 = ITU-R BT.2020 Y'C'bC'r
+ * (others reserved)
+ * ----------------------------------------------------------------------------------------------------
+ * 0x0 = ITU-R BT.601 | 2 = YCbCr422
+ * 0x1 = ITU-R BT.709
+ * 0x2 = xvYCC601
+ * 0x3 = xvYCC709
+ * 0x4 = sYCC601
+ * 0x5 = AdobeYCC601
+ * 0x6 = ITU-R BT.2020 Y'cC'bcC'rc
+ * 0x7 = ITU-R BT.2020 Y'C'bC'r
+ * (others reserved)
+ * ----------------------------------------------------------------------------------------------------
+ * 0x0 = ITU-R BT.601 | 3 = YCbCr420
+ * 0x1 = ITU-R BT.709
+ * 0x2 = xvYCC601
+ * 0x3 = xvYCC709
+ * 0x4 = sYCC601
+ * 0x5 = AdobeYCC601
+ * 0x6 = ITU-R BT.2020 Y'cC'bcC'rc
+ * 0x7 = ITU-R BT.2020 Y'C'bC'r
+ * (others reserved)
+ * ----------------------------------------------------------------------------------------------------
+ * 0x0 =DICOM Part14 Grayscale | 4 = Yonly
+ * Display Function
+ * (others reserved)
+ */
+ unsigned int pixelEncoding = 0;
+ unsigned int colorimetryFormat = 0;
+
+ /* Set Pixel Encoding */
+ switch (stream->timing.pixel_encoding) {
+ case PIXEL_ENCODING_RGB:
+ pixelEncoding = 0x0; /* RGB = 0h */
+ break;
+ case PIXEL_ENCODING_YCBCR444:
+ pixelEncoding = 0x1; /* YCbCr444 = 1h */
+ break;
+ case PIXEL_ENCODING_YCBCR422:
+ pixelEncoding = 0x2; /* YCbCr422 = 2h */
+ break;
+ case PIXEL_ENCODING_YCBCR420:
+ pixelEncoding = 0x3; /* YCbCr420 = 3h */
+ break;
+ default:
+ pixelEncoding = 0x0; /* default RGB = 0h */
+ break;
+ }
+
+ /* Set Colorimetry format based on pixel encoding */
+ switch (stream->timing.pixel_encoding) {
+ case PIXEL_ENCODING_RGB:
+ if ((cs == COLOR_SPACE_SRGB) ||
+ (cs == COLOR_SPACE_SRGB_LIMITED))
+ colorimetryFormat = ColorimetryRGB_DP_sRGB;
+ else if (cs == COLOR_SPACE_ADOBERGB)
+ colorimetryFormat = ColorimetryRGB_DP_AdobeRGB;
+ else if ((cs == COLOR_SPACE_2020_RGB_FULLRANGE) ||
+ (cs == COLOR_SPACE_2020_RGB_LIMITEDRANGE))
+ colorimetryFormat = ColorimetryRGB_DP_ITU_R_BT2020RGB;
+ break;
+
+ case PIXEL_ENCODING_YCBCR444:
+ case PIXEL_ENCODING_YCBCR422:
+ case PIXEL_ENCODING_YCBCR420:
+ /* Note: xvYCC probably not supported correctly here on DP since colorspace translation
+ * loses distinction between BT601 vs xvYCC601 in translation
+ */
+ if (cs == COLOR_SPACE_YCBCR601)
+ colorimetryFormat = ColorimetryYCC_DP_ITU601;
+ else if (cs == COLOR_SPACE_YCBCR709)
+ colorimetryFormat = ColorimetryYCC_DP_ITU709;
+ else if (cs == COLOR_SPACE_ADOBERGB)
+ colorimetryFormat = ColorimetryYCC_DP_AdobeYCC;
+ else if (cs == COLOR_SPACE_2020_YCBCR_LIMITED)
+ colorimetryFormat = ColorimetryYCC_DP_ITU2020YCbCr;
+
+ if (cs == COLOR_SPACE_2020_YCBCR_LIMITED && tf == TRANSFER_FUNC_GAMMA_22)
+ colorimetryFormat = ColorimetryYCC_DP_ITU709;
+ break;
+
+ default:
+ colorimetryFormat = ColorimetryRGB_DP_sRGB;
+ break;
+ }
+
+ info_packet->sb[16] = (pixelEncoding << 4) | colorimetryFormat;
+
+ /* Set color depth */
+ switch (stream->timing.display_color_depth) {
+ case COLOR_DEPTH_666:
+ /* NOTE: This is actually not valid for YCbCr pixel encoding to have 6 bpc
+ * as of DP1.4 spec, but value of 0 probably reserved here for potential future use.
+ */
+ info_packet->sb[17] = 0;
+ break;
+ case COLOR_DEPTH_888:
+ info_packet->sb[17] = 1;
+ break;
+ case COLOR_DEPTH_101010:
+ info_packet->sb[17] = 2;
+ break;
+ case COLOR_DEPTH_121212:
+ info_packet->sb[17] = 3;
+ break;
+ /*case COLOR_DEPTH_141414: -- NO SUCH FORMAT IN DP SPEC */
+ case COLOR_DEPTH_161616:
+ info_packet->sb[17] = 4;
+ break;
+ default:
+ info_packet->sb[17] = 0;
+ break;
+ }
+
+ /* all YCbCr are always limited range */
+ if ((cs == COLOR_SPACE_SRGB_LIMITED) ||
+ (cs == COLOR_SPACE_2020_RGB_LIMITEDRANGE) ||
+ (pixelEncoding != 0x0)) {
+ info_packet->sb[17] |= 0x80; /* DB17 bit 7 set to 1 for CEA timing. */
+ }
+
+ /* Content Type (Bits 2:0)
+ * 0 = Not defined.
+ * 1 = Graphics.
+ * 2 = Photo.
+ * 3 = Video.
+ * 4 = Game.
+ */
+ info_packet->sb[18] = 0;
+}
+
void mod_build_vsc_infopacket(const struct dc_stream_state *stream,
struct dc_info_packet *info_packet,
enum dc_color_space cs,
@@ -137,8 +298,6 @@ void mod_build_vsc_infopacket(const struct dc_stream_state *stream,
{
unsigned int vsc_packet_revision = vsc_packet_undefined;
unsigned int i;
- unsigned int pixelEncoding = 0;
- unsigned int colorimetryFormat = 0;
bool stereo3dSupport = false;
if (stream->timing.timing_3d_format != TIMING_3D_FORMAT_NONE && stream->view_format != VIEW_3D_FORMAT_NONE) {
@@ -158,12 +317,38 @@ void mod_build_vsc_infopacket(const struct dc_stream_state *stream,
if (stream->use_vsc_sdp_for_colorimetry)
vsc_packet_revision = vsc_packet_rev5;
+ /* Check for Panel Replay (highest priority) */
+ if (stream->link->replay_settings.config.replay_version == DC_VESA_PANEL_REPLAY)
+ vsc_packet_revision = stream->use_vsc_sdp_for_colorimetry ? vsc_packet_rev7 : vsc_packet_rev6;
+
/* VSC packet not needed based on the features
* supported by this DP display
*/
if (vsc_packet_revision == vsc_packet_undefined)
return;
+ if (vsc_packet_revision == vsc_packet_rev6) {
+ /* Secondary-data Packet ID = 0*/
+ info_packet->hb0 = 0x00;
+ /* 07h - Packet Type Value indicating Video
+ * Stream Configuration packet
+ */
+ info_packet->hb1 = 0x07;
+ /* 06h = VSC SDP supporting 3D stereo + PR
+ */
+ info_packet->hb2 = 0x06;
+ /* 0Eh = VSC SDP supporting 3D stereo + PR
+ * (HB2 = 06h), with Y-coordinate of first scan
+ * line of the SU region
+ */
+ info_packet->hb3 = 0x10;
+
+ for (i = 0; i < 28; i++)
+ info_packet->sb[i] = 0;
+
+ info_packet->valid = true;
+ }
+
if (vsc_packet_revision == vsc_packet_rev4) {
/* Secondary-data Packet ID = 0*/
info_packet->hb0 = 0x00;
@@ -292,152 +477,22 @@ void mod_build_vsc_infopacket(const struct dc_stream_state *stream,
info_packet->valid = true;
- /* Set VSC SDP fields for pixel encoding and colorimetry format from DP 1.3 specs
- * Data Bytes DB 18~16
- * Bits 3:0 (Colorimetry Format) | Bits 7:4 (Pixel Encoding)
- * ----------------------------------------------------------------------------------------------------
- * 0x0 = sRGB | 0 = RGB
- * 0x1 = RGB Wide Gamut Fixed Point
- * 0x2 = RGB Wide Gamut Floating Point
- * 0x3 = AdobeRGB
- * 0x4 = DCI-P3
- * 0x5 = CustomColorProfile
- * (others reserved)
- * ----------------------------------------------------------------------------------------------------
- * 0x0 = ITU-R BT.601 | 1 = YCbCr444
- * 0x1 = ITU-R BT.709
- * 0x2 = xvYCC601
- * 0x3 = xvYCC709
- * 0x4 = sYCC601
- * 0x5 = AdobeYCC601
- * 0x6 = ITU-R BT.2020 Y'cC'bcC'rc
- * 0x7 = ITU-R BT.2020 Y'C'bC'r
- * (others reserved)
- * ----------------------------------------------------------------------------------------------------
- * 0x0 = ITU-R BT.601 | 2 = YCbCr422
- * 0x1 = ITU-R BT.709
- * 0x2 = xvYCC601
- * 0x3 = xvYCC709
- * 0x4 = sYCC601
- * 0x5 = AdobeYCC601
- * 0x6 = ITU-R BT.2020 Y'cC'bcC'rc
- * 0x7 = ITU-R BT.2020 Y'C'bC'r
- * (others reserved)
- * ----------------------------------------------------------------------------------------------------
- * 0x0 = ITU-R BT.601 | 3 = YCbCr420
- * 0x1 = ITU-R BT.709
- * 0x2 = xvYCC601
- * 0x3 = xvYCC709
- * 0x4 = sYCC601
- * 0x5 = AdobeYCC601
- * 0x6 = ITU-R BT.2020 Y'cC'bcC'rc
- * 0x7 = ITU-R BT.2020 Y'C'bC'r
- * (others reserved)
- * ----------------------------------------------------------------------------------------------------
- * 0x0 =DICOM Part14 Grayscale | 4 = Yonly
- * Display Function
- * (others reserved)
- */
-
- /* Set Pixel Encoding */
- switch (stream->timing.pixel_encoding) {
- case PIXEL_ENCODING_RGB:
- pixelEncoding = 0x0; /* RGB = 0h */
- break;
- case PIXEL_ENCODING_YCBCR444:
- pixelEncoding = 0x1; /* YCbCr444 = 1h */
- break;
- case PIXEL_ENCODING_YCBCR422:
- pixelEncoding = 0x2; /* YCbCr422 = 2h */
- break;
- case PIXEL_ENCODING_YCBCR420:
- pixelEncoding = 0x3; /* YCbCr420 = 3h */
- break;
- default:
- pixelEncoding = 0x0; /* default RGB = 0h */
- break;
- }
-
- /* Set Colorimetry format based on pixel encoding */
- switch (stream->timing.pixel_encoding) {
- case PIXEL_ENCODING_RGB:
- if ((cs == COLOR_SPACE_SRGB) ||
- (cs == COLOR_SPACE_SRGB_LIMITED))
- colorimetryFormat = ColorimetryRGB_DP_sRGB;
- else if (cs == COLOR_SPACE_ADOBERGB)
- colorimetryFormat = ColorimetryRGB_DP_AdobeRGB;
- else if ((cs == COLOR_SPACE_2020_RGB_FULLRANGE) ||
- (cs == COLOR_SPACE_2020_RGB_LIMITEDRANGE))
- colorimetryFormat = ColorimetryRGB_DP_ITU_R_BT2020RGB;
- break;
-
- case PIXEL_ENCODING_YCBCR444:
- case PIXEL_ENCODING_YCBCR422:
- case PIXEL_ENCODING_YCBCR420:
- /* Note: xvYCC probably not supported correctly here on DP since colorspace translation
- * loses distinction between BT601 vs xvYCC601 in translation
- */
- if (cs == COLOR_SPACE_YCBCR601)
- colorimetryFormat = ColorimetryYCC_DP_ITU601;
- else if (cs == COLOR_SPACE_YCBCR709)
- colorimetryFormat = ColorimetryYCC_DP_ITU709;
- else if (cs == COLOR_SPACE_ADOBERGB)
- colorimetryFormat = ColorimetryYCC_DP_AdobeYCC;
- else if (cs == COLOR_SPACE_2020_YCBCR_LIMITED)
- colorimetryFormat = ColorimetryYCC_DP_ITU2020YCbCr;
-
- if (cs == COLOR_SPACE_2020_YCBCR_LIMITED && tf == TRANSFER_FUNC_GAMMA_22)
- colorimetryFormat = ColorimetryYCC_DP_ITU709;
- break;
-
- default:
- colorimetryFormat = ColorimetryRGB_DP_sRGB;
- break;
- }
-
- info_packet->sb[16] = (pixelEncoding << 4) | colorimetryFormat;
+ set_vsc_packet_colorimetry_data(stream, info_packet, cs, tf);
+ }
- /* Set color depth */
- switch (stream->timing.display_color_depth) {
- case COLOR_DEPTH_666:
- /* NOTE: This is actually not valid for YCbCr pixel encoding to have 6 bpc
- * as of DP1.4 spec, but value of 0 probably reserved here for potential future use.
- */
- info_packet->sb[17] = 0;
- break;
- case COLOR_DEPTH_888:
- info_packet->sb[17] = 1;
- break;
- case COLOR_DEPTH_101010:
- info_packet->sb[17] = 2;
- break;
- case COLOR_DEPTH_121212:
- info_packet->sb[17] = 3;
- break;
- /*case COLOR_DEPTH_141414: -- NO SUCH FORMAT IN DP SPEC */
- case COLOR_DEPTH_161616:
- info_packet->sb[17] = 4;
- break;
- default:
- info_packet->sb[17] = 0;
- break;
- }
+ if (vsc_packet_revision == vsc_packet_rev7) {
+ /* Secondary-data Packet ID = 0 */
+ info_packet->hb0 = 0x00;
+ /* 07h - Packet Type Value indicating Video Stream Configuration packet */
+ info_packet->hb1 = 0x07;
+ /* 07h = VSC SDP supporting 3D stereo, PR, and Pixel Encoding/Colorimetry Format indication. */
+ info_packet->hb2 = 0x07;
+ /* 13h = VSC SDP supporting 3D stereo, + PR, + Pixel Encoding/Colorimetry Format indication (HB2 = 07h). */
+ info_packet->hb3 = 0x13;
- /* all YCbCr are always limited range */
- if ((cs == COLOR_SPACE_SRGB_LIMITED) ||
- (cs == COLOR_SPACE_2020_RGB_LIMITEDRANGE) ||
- (pixelEncoding != 0x0)) {
- info_packet->sb[17] |= 0x80; /* DB17 bit 7 set to 1 for CEA timing. */
- }
+ info_packet->valid = true;
- /* Content Type (Bits 2:0)
- * 0 = Not defined.
- * 1 = Graphics.
- * 2 = Photo.
- * 3 = Video.
- * 4 = Game.
- */
- info_packet->sb[18] = 0;
+ set_vsc_packet_colorimetry_data(stream, info_packet, cs, tf);
}
}
@@ -537,7 +592,11 @@ void mod_build_adaptive_sync_infopacket(const struct dc_stream_state *stream,
break;
case FREESYNC_TYPE_PCON_IN_WHITELIST:
case ADAPTIVE_SYNC_TYPE_EDP:
- mod_build_adaptive_sync_infopacket_v1(info_packet);
+ if (stream && stream->link->replay_settings.config.replay_supported &&
+ stream->link->replay_settings.config.replay_version == DC_VESA_PANEL_REPLAY)
+ mod_build_adaptive_sync_infopacket_v2(stream, param, info_packet);
+ else
+ mod_build_adaptive_sync_infopacket_v1(info_packet);
break;
case ADAPTIVE_SYNC_TYPE_NONE:
case FREESYNC_TYPE_PCON_NOT_IN_WHITELIST:
@@ -567,13 +626,15 @@ void mod_build_adaptive_sync_infopacket_v2(const struct dc_stream_state *stream,
info_packet->hb2 = AS_SDP_VER_2;
info_packet->hb3 = AS_DP_SDP_LENGTH;
- //Payload
- info_packet->sb[0] = param->supportMode; //1: AVT; 0: FAVT
- info_packet->sb[1] = (stream->timing.v_total & 0x00FF);
- info_packet->sb[2] = (stream->timing.v_total & 0xFF00) >> 8;
- //info_packet->sb[3] = 0x00; Target RR, not use fot AVT
- info_packet->sb[4] = (param->increase.support << 6 | param->decrease.support << 7);
- info_packet->sb[5] = param->increase.frame_duration_hex;
- info_packet->sb[6] = param->decrease.frame_duration_hex;
+ if (param) {
+ //Payload
+ info_packet->sb[0] = param->supportMode; //1: AVT; 0: FAVT
+ info_packet->sb[1] = (stream->timing.v_total & 0x00FF);
+ info_packet->sb[2] = (stream->timing.v_total & 0xFF00) >> 8;
+ //info_packet->sb[3] = 0x00; Target RR, not use fot AVT
+ info_packet->sb[4] = (param->increase.support << 6 | param->decrease.support << 7);
+ info_packet->sb[5] = param->increase.frame_duration_hex;
+ info_packet->sb[6] = param->decrease.frame_duration_hex;
+ }
}
diff --git a/drivers/gpu/drm/amd/display/modules/power/power_helpers.c b/drivers/gpu/drm/amd/display/modules/power/power_helpers.c
index fd139b219bf9..df3b8383b06d 100644
--- a/drivers/gpu/drm/amd/display/modules/power/power_helpers.c
+++ b/drivers/gpu/drm/amd/display/modules/power/power_helpers.c
@@ -984,7 +984,13 @@ void set_replay_frame_skip_number(struct dc_link *link,
uint32_t *frame_skip_number_array = NULL;
uint32_t frame_skip_number = 0;
- if (link == NULL || flicker_free_refresh_rate_mhz == 0 || coasting_vtotal_refresh_rate_mhz == 0)
+ if (link == NULL)
+ return;
+
+ if (false == link->replay_settings.config.frame_skip_supported)
+ return;
+
+ if (flicker_free_refresh_rate_mhz == 0 || coasting_vtotal_refresh_rate_mhz == 0)
return;
if (is_defer)