diff options
| author | Linus Torvalds <torvalds@linux-foundation.org> | 2026-02-11 12:55:44 -0800 |
|---|---|---|
| committer | Linus Torvalds <torvalds@linux-foundation.org> | 2026-02-11 12:55:44 -0800 |
| commit | 939faf71cf7ca9ab3d1bd2912ac0e203d4d7156a (patch) | |
| tree | bf81a5b8c95c7095983719a3e0273a73dbe79c34 /drivers/gpu/drm/amd/display | |
| parent | b7ef56a07672e0d7ebe71c9d9b45f959f0c2f8e8 (diff) | |
| parent | 2f5db9b4002470ea19380326c5a390647c56e780 (diff) | |
| download | linux-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')
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(®ion_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, ®ion_params, ®ion_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, ¶m); dpp->funcs->set_cursor_position(dpp, &pos_cpy, ¶m, 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(<_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, ¶ms->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) |
