Merge tag 'amd-drm-next-6.14-2025-01-10' of https://gitlab.freedesktop.org/agd5f/linux into drm-next

amd-drm-next-6.14-2025-01-10:

amdgpu:
- Fix max surface handling in DC
- clang fixes
- DCN 3.5 fixes
- DCN 4.0.1 fixes
- DC CRC fixes
- DML updates
- DSC fixes
- PSR fixes
- DC add some divide by 0 checks
- SMU13 updates
- SR-IOV fixes
- RAS fixes
- Cleaner shader support for gfx10.3 dGPUs
- fix drm buddy trim handling
- SDMA engine reset updates
_ Fix RB bitmap setup
- Fix doorbell ttm cleanup
- Add CEC notifier support
- DPIA updates
- MST fixes

amdkfd:
- Shader debugger fixes
- Trap handler cleanup
- Cleanup includes
- Eviction fence wq fix

Signed-off-by: Dave Airlie <airlied@redhat.com>

From: Alex Deucher <alexander.deucher@amd.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20250110172731.2960668-1-alexander.deucher@amd.com
This commit is contained in:
Dave Airlie
2025-01-13 11:13:05 +10:00
167 changed files with 4852 additions and 2026 deletions

View File

@@ -1131,6 +1131,9 @@ uint64_t kgd_gfx_v9_hqd_get_pq_addr(struct amdgpu_device *adev,
uint32_t low, high;
uint64_t queue_addr = 0;
if (!amdgpu_gpu_recovery)
return 0;
kgd_gfx_v9_acquire_queue(adev, pipe_id, queue_id, inst);
amdgpu_gfx_rlc_enter_safe_mode(adev, inst);
@@ -1179,6 +1182,9 @@ uint64_t kgd_gfx_v9_hqd_reset(struct amdgpu_device *adev,
uint32_t low, high, pipe_reset_data = 0;
uint64_t queue_addr = 0;
if (!amdgpu_gpu_recovery)
return 0;
kgd_gfx_v9_acquire_queue(adev, pipe_id, queue_id, inst);
amdgpu_gfx_rlc_enter_safe_mode(adev, inst);

View File

@@ -88,10 +88,8 @@ static void amdgpu_gem_object_free(struct drm_gem_object *gobj)
{
struct amdgpu_bo *aobj = gem_to_amdgpu_bo(gobj);
if (aobj) {
amdgpu_hmm_unregister(aobj);
ttm_bo_put(&aobj->tbo);
}
amdgpu_hmm_unregister(aobj);
ttm_bo_put(&aobj->tbo);
}
int amdgpu_gem_object_create(struct amdgpu_device *adev, unsigned long size,

View File

@@ -3020,10 +3020,7 @@ static int psp_hw_init(struct amdgpu_ip_block *ip_block)
struct amdgpu_device *adev = ip_block->adev;
mutex_lock(&adev->firmware.mutex);
/*
* This sequence is just used on hw_init only once, no need on
* resume.
*/
ret = amdgpu_ucode_init_bo(adev);
if (ret)
goto failed;
@@ -3148,6 +3145,10 @@ static int psp_resume(struct amdgpu_ip_block *ip_block)
mutex_lock(&adev->firmware.mutex);
ret = amdgpu_ucode_init_bo(adev);
if (ret)
goto failed;
ret = psp_hw_start(psp);
if (ret)
goto failed;
@@ -3891,10 +3892,12 @@ static ssize_t psp_usbc_pd_fw_sysfs_read(struct device *dev,
{
struct drm_device *ddev = dev_get_drvdata(dev);
struct amdgpu_device *adev = drm_to_adev(ddev);
struct amdgpu_ip_block *ip_block;
uint32_t fw_ver;
int ret;
if (!adev->ip_blocks[AMD_IP_BLOCK_TYPE_PSP].status.late_initialized) {
ip_block = amdgpu_device_ip_get_ip_block(adev, AMD_IP_BLOCK_TYPE_PSP);
if (!ip_block || !ip_block->status.late_initialized) {
dev_info(adev->dev, "PSP block is not ready yet\n.");
return -EBUSY;
}
@@ -3923,8 +3926,10 @@ static ssize_t psp_usbc_pd_fw_sysfs_write(struct device *dev,
struct amdgpu_bo *fw_buf_bo = NULL;
uint64_t fw_pri_mc_addr;
void *fw_pri_cpu_addr;
struct amdgpu_ip_block *ip_block;
if (!adev->ip_blocks[AMD_IP_BLOCK_TYPE_PSP].status.late_initialized) {
ip_block = amdgpu_device_ip_get_ip_block(adev, AMD_IP_BLOCK_TYPE_PSP);
if (!ip_block || !ip_block->status.late_initialized) {
dev_err(adev->dev, "PSP block is not ready yet.");
return -EBUSY;
}

View File

@@ -2832,8 +2832,10 @@ int amdgpu_ras_add_bad_pages(struct amdgpu_device *adev,
mutex_lock(&con->recovery_lock);
data = con->eh_data;
if (!data)
if (!data) {
/* Returning 0 as the absence of eh_data is acceptable */
goto free;
}
for (i = 0; i < pages; i++) {
if (from_rom &&
@@ -2845,26 +2847,34 @@ int amdgpu_ras_add_bad_pages(struct amdgpu_device *adev,
* one row
*/
if (amdgpu_umc_pages_in_a_row(adev, &err_data,
bps[i].retired_page << AMDGPU_GPU_PAGE_SHIFT))
bps[i].retired_page <<
AMDGPU_GPU_PAGE_SHIFT)) {
ret = -EINVAL;
goto free;
else
} else {
find_pages_per_pa = true;
}
} else {
/* unsupported cases */
ret = -EOPNOTSUPP;
goto free;
}
}
} else {
if (amdgpu_umc_pages_in_a_row(adev, &err_data,
bps[i].retired_page << AMDGPU_GPU_PAGE_SHIFT))
bps[i].retired_page << AMDGPU_GPU_PAGE_SHIFT)) {
ret = -EINVAL;
goto free;
}
}
} else {
if (from_rom && !find_pages_per_pa) {
if (bps[i].retired_page & UMC_CHANNEL_IDX_V2) {
/* bad page in any NPS mode in eeprom */
if (amdgpu_ras_mca2pa_by_idx(adev, &bps[i], &err_data))
if (amdgpu_ras_mca2pa_by_idx(adev, &bps[i], &err_data)) {
ret = -EINVAL;
goto free;
}
} else {
/* legacy bad page in eeprom, generated only in
* NPS1 mode
@@ -2881,6 +2891,7 @@ int amdgpu_ras_add_bad_pages(struct amdgpu_device *adev,
/* non-nps1 mode, old RAS TA
* can't support it
*/
ret = -EOPNOTSUPP;
goto free;
}
}

View File

@@ -362,13 +362,13 @@ static int amdgpu_debugfs_sdma_sched_mask_set(void *data, u64 val)
if (!adev)
return -ENODEV;
mask = (1 << adev->sdma.num_instances) - 1;
mask = BIT_ULL(adev->sdma.num_instances) - 1;
if ((val & mask) == 0)
return -EINVAL;
for (i = 0; i < adev->sdma.num_instances; ++i) {
ring = &adev->sdma.instance[i].ring;
if (val & (1 << i))
if (val & BIT_ULL(i))
ring->sched.ready = true;
else
ring->sched.ready = false;

View File

@@ -2066,6 +2066,7 @@ void amdgpu_ttm_fini(struct amdgpu_device *adev)
ttm_range_man_fini(&adev->mman.bdev, AMDGPU_PL_GDS);
ttm_range_man_fini(&adev->mman.bdev, AMDGPU_PL_GWS);
ttm_range_man_fini(&adev->mman.bdev, AMDGPU_PL_OA);
ttm_range_man_fini(&adev->mman.bdev, AMDGPU_PL_DOORBELL);
ttm_device_fini(&adev->mman.bdev);
adev->mman.initialized = false;
DRM_INFO("amdgpu: ttm finalized\n");

View File

@@ -567,7 +567,6 @@ static int amdgpu_vram_mgr_new(struct ttm_resource_manager *man,
else
remaining_size -= size;
}
mutex_unlock(&mgr->lock);
if (bo->flags & AMDGPU_GEM_CREATE_VRAM_CONTIGUOUS && adjust_dcc_size) {
struct drm_buddy_block *dcc_block;
@@ -584,6 +583,7 @@ static int amdgpu_vram_mgr_new(struct ttm_resource_manager *man,
(u64)vres->base.size,
&vres->blocks);
}
mutex_unlock(&mgr->lock);
vres->base.start = 0;
size = max_t(u64, amdgpu_vram_mgr_blocks_size(&vres->blocks),

View File

@@ -45,6 +45,7 @@
#include "clearstate_gfx10.h"
#include "v10_structs.h"
#include "gfx_v10_0.h"
#include "gfx_v10_0_cleaner_shader.h"
#include "nbio_v2_3.h"
/*
@@ -4738,6 +4739,23 @@ static int gfx_v10_0_sw_init(struct amdgpu_ip_block *ip_block)
break;
}
switch (amdgpu_ip_version(adev, GC_HWIP, 0)) {
case IP_VERSION(10, 3, 0):
case IP_VERSION(10, 3, 2):
case IP_VERSION(10, 3, 4):
case IP_VERSION(10, 3, 5):
adev->gfx.cleaner_shader_ptr = gfx_10_3_0_cleaner_shader_hex;
adev->gfx.cleaner_shader_size = sizeof(gfx_10_3_0_cleaner_shader_hex);
if (adev->gfx.me_fw_version >= 64 &&
adev->gfx.pfp_fw_version >= 100 &&
adev->gfx.mec_fw_version >= 122) {
adev->gfx.enable_cleaner_shader = true;
r = amdgpu_gfx_cleaner_shader_sw_init(adev, adev->gfx.cleaner_shader_size);
if (r) {
adev->gfx.enable_cleaner_shader = false;
dev_err(adev->dev, "Failed to initialize cleaner shader\n");
}
}
break;
default:
adev->gfx.enable_cleaner_shader = false;
break;

View File

@@ -0,0 +1,56 @@
/* SPDX-License-Identifier: MIT */
/*
* 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.
*/
/* Define the cleaner shader gfx_10_3_0 */
static const u32 gfx_10_3_0_cleaner_shader_hex[] = {
0xb0804004, 0xbf8a0000,
0xbe8203b8, 0xbefc0380,
0x7e008480, 0x7e028480,
0x7e048480, 0x7e068480,
0x7e088480, 0x7e0a8480,
0x7e0c8480, 0x7e0e8480,
0xbefc0302, 0x80828802,
0xbf84fff5, 0xbe8203ff,
0x80000000, 0x87020002,
0xbf840012, 0xbefe03c1,
0xbeff03c1, 0xd7650001,
0x0001007f, 0xd7660001,
0x0002027e, 0x16020288,
0xbe8203bf, 0xbefc03c1,
0xd9382000, 0x00020201,
0xd9386040, 0x00040401,
0xd70f6a01, 0x000202ff,
0x00000400, 0x80828102,
0xbf84fff7, 0xbefc03ff,
0x00000068, 0xbe803080,
0xbe813080, 0xbe823080,
0xbe833080, 0x80fc847c,
0xbf84fffa, 0xbeea0480,
0xbeec0480, 0xbeee0480,
0xbef00480, 0xbef20480,
0xbef40480, 0xbef60480,
0xbef80480, 0xbefa0480,
0xbf810000, 0xbf9f0000,
0xbf9f0000, 0xbf9f0000,
0xbf9f0000, 0xbf9f0000,
};

View File

@@ -0,0 +1,124 @@
/* SPDX-License-Identifier: MIT */
/*
* 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.
*/
// This shader is to clean LDS, SGPRs and VGPRs. It is first 64 Dwords or 256 bytes of 192 Dwords cleaner shader.
//To turn this shader program on for complitaion change this to main and lower shader main to main_1
// GFX10.3 : Clear SGPRs, VGPRs and LDS
// Launch 32 waves per CU (16 per SIMD) as a workgroup (threadgroup) to fill every wave slot
// Waves are "wave32" and have 64 VGPRs each, which uses all 1024 VGPRs per SIMD
// Waves are launched in "CU" mode, and the workgroup shares 64KB of LDS (half of the WGP's LDS)
// It takes 2 workgroups to use all of LDS: one on each CU of the WGP
// Each wave clears SGPRs 0 - 107
// Each wave clears VGPRs 0 - 63
// The first wave of the workgroup clears its 64KB of LDS
// The shader starts with "S_BARRIER" to ensure SPI has launched all waves of the workgroup
// before any wave in the workgroup could end. Without this, it is possible not all SGPRs get cleared.
shader main
asic(GFX10)
type(CS)
wave_size(32)
// Note: original source code from SQ team
//
// Create 32 waves in a threadgroup (CS waves)
// Each allocates 64 VGPRs
// The workgroup allocates all of LDS (64kbytes)
//
// Takes about 2500 clocks to run.
// (theorhetical fastest = 1024clks vgpr + 640lds = 1660 clks)
//
S_BARRIER
s_mov_b32 s2, 0x00000038 // Loop 64/8=8 times (loop unrolled for performance)
s_mov_b32 m0, 0
//
// CLEAR VGPRs
//
label_0005:
v_movreld_b32 v0, 0
v_movreld_b32 v1, 0
v_movreld_b32 v2, 0
v_movreld_b32 v3, 0
v_movreld_b32 v4, 0
v_movreld_b32 v5, 0
v_movreld_b32 v6, 0
v_movreld_b32 v7, 0
s_mov_b32 m0, s2
s_sub_u32 s2, s2, 8
s_cbranch_scc0 label_0005
//
s_mov_b32 s2, 0x80000000 // Bit31 is first_wave
s_and_b32 s2, s2, s0 // sgpr0 has tg_size (first_wave) term as in ucode only COMPUTE_PGM_RSRC2.tg_size_en is set
s_cbranch_scc0 label_0023 // Clean LDS if its first wave of ThreadGroup/WorkGroup
// CLEAR LDS
//
s_mov_b32 exec_lo, 0xffffffff
s_mov_b32 exec_hi, 0xffffffff
v_mbcnt_lo_u32_b32 v1, exec_hi, 0 // Set V1 to thread-ID (0..63)
v_mbcnt_hi_u32_b32 v1, exec_lo, v1 // Set V1 to thread-ID (0..63)
v_mul_u32_u24 v1, 0x00000008, v1 // * 8, so each thread is a double-dword address (8byte)
s_mov_b32 s2, 0x00000003f // 64 loop iterations
s_mov_b32 m0, 0xffffffff
// Clear all of LDS space
// Each FirstWave of WorkGroup clears 64kbyte block
label_001F:
ds_write2_b64 v1, v[2:3], v[2:3] offset1:32
ds_write2_b64 v1, v[4:5], v[4:5] offset0:64 offset1:96
v_add_co_u32 v1, vcc, 0x00000400, v1
s_sub_u32 s2, s2, 1
s_cbranch_scc0 label_001F
//
// CLEAR SGPRs
//
label_0023:
s_mov_b32 m0, 0x00000068 // Loop 108/4=27 times (loop unrolled for performance)
label_sgpr_loop:
s_movreld_b32 s0, 0
s_movreld_b32 s1, 0
s_movreld_b32 s2, 0
s_movreld_b32 s3, 0
s_sub_u32 m0, m0, 4
s_cbranch_scc0 label_sgpr_loop
//clear vcc
s_mov_b32 flat_scratch_lo, 0 //clear flat scratch lo SGPR
s_mov_b32 flat_scratch_hi, 0 //clear flat scratch hi SGPR
s_mov_b64 vcc, 0 //clear vcc
s_mov_b64 ttmp0, 0 //Clear ttmp0 and ttmp1
s_mov_b64 ttmp2, 0 //Clear ttmp2 and ttmp3
s_mov_b64 ttmp4, 0 //Clear ttmp4 and ttmp5
s_mov_b64 ttmp6, 0 //Clear ttmp6 and ttmp7
s_mov_b64 ttmp8, 0 //Clear ttmp8 and ttmp9
s_mov_b64 ttmp10, 0 //Clear ttmp10 and ttmp11
s_mov_b64 ttmp12, 0 //Clear ttmp12 and ttmp13
s_mov_b64 ttmp14, 0 //Clear ttmp14 and ttmp15
s_endpgm
end

View File

@@ -1891,6 +1891,7 @@ static u32 gfx_v11_0_get_rb_active_bitmap(struct amdgpu_device *adev)
static void gfx_v11_0_setup_rb(struct amdgpu_device *adev)
{
u32 rb_bitmap_per_sa;
u32 rb_bitmap_width_per_sa;
u32 max_sa;
u32 active_sa_bitmap;
@@ -1908,9 +1909,11 @@ static void gfx_v11_0_setup_rb(struct amdgpu_device *adev)
adev->gfx.config.max_sh_per_se;
rb_bitmap_width_per_sa = adev->gfx.config.max_backends_per_se /
adev->gfx.config.max_sh_per_se;
rb_bitmap_per_sa = amdgpu_gfx_create_bitmask(rb_bitmap_width_per_sa);
for (i = 0; i < max_sa; i++) {
if (active_sa_bitmap & (1 << i))
active_rb_bitmap |= (0x3 << (i * rb_bitmap_width_per_sa));
active_rb_bitmap |= (rb_bitmap_per_sa << (i * rb_bitmap_width_per_sa));
}
active_rb_bitmap &= global_active_rb_bitmap;

View File

@@ -1442,11 +1442,19 @@ static int gfx_v12_0_sw_init(struct amdgpu_ip_block *ip_block)
}
}
/* TODO: Add queue reset mask when FW fully supports it */
adev->gfx.gfx_supported_reset =
amdgpu_get_soft_full_reset_mask(&adev->gfx.gfx_ring[0]);
adev->gfx.compute_supported_reset =
amdgpu_get_soft_full_reset_mask(&adev->gfx.compute_ring[0]);
switch (amdgpu_ip_version(adev, GC_HWIP, 0)) {
case IP_VERSION(12, 0, 0):
case IP_VERSION(12, 0, 1):
if ((adev->gfx.me_fw_version >= 2660) &&
(adev->gfx.mec_fw_version >= 2920)) {
adev->gfx.compute_supported_reset |= AMDGPU_RESET_TYPE_PER_QUEUE;
adev->gfx.gfx_supported_reset |= AMDGPU_RESET_TYPE_PER_QUEUE;
}
}
if (!adev->enable_mes_kiq) {
r = amdgpu_gfx_kiq_init(adev, GFX12_MEC_HPD_SIZE, 0);
@@ -1615,6 +1623,7 @@ static u32 gfx_v12_0_get_rb_active_bitmap(struct amdgpu_device *adev)
static void gfx_v12_0_setup_rb(struct amdgpu_device *adev)
{
u32 rb_bitmap_per_sa;
u32 rb_bitmap_width_per_sa;
u32 max_sa;
u32 active_sa_bitmap;
@@ -1632,12 +1641,14 @@ static void gfx_v12_0_setup_rb(struct amdgpu_device *adev)
adev->gfx.config.max_sh_per_se;
rb_bitmap_width_per_sa = adev->gfx.config.max_backends_per_se /
adev->gfx.config.max_sh_per_se;
rb_bitmap_per_sa = amdgpu_gfx_create_bitmask(rb_bitmap_width_per_sa);
for (i = 0; i < max_sa; i++) {
if (active_sa_bitmap & (1 << i))
active_rb_bitmap |= (0x3 << (i * rb_bitmap_width_per_sa));
active_rb_bitmap |= (rb_bitmap_per_sa << (i * rb_bitmap_width_per_sa));
}
active_rb_bitmap |= global_active_rb_bitmap;
active_rb_bitmap &= global_active_rb_bitmap;
adev->gfx.config.backend_enable_mask = active_rb_bitmap;
adev->gfx.config.num_rbs = hweight32(active_rb_bitmap);
}

View File

@@ -5639,8 +5639,6 @@ static void gfx_v8_0_update_medium_grain_clock_gating(struct amdgpu_device *adev
{
uint32_t temp, data;
amdgpu_gfx_rlc_enter_safe_mode(adev, 0);
/* It is disabled by HW by default */
if (enable && (adev->cg_flags & AMD_CG_SUPPORT_GFX_MGCG)) {
if (adev->cg_flags & AMD_CG_SUPPORT_GFX_MGLS) {
@@ -5734,8 +5732,6 @@ static void gfx_v8_0_update_medium_grain_clock_gating(struct amdgpu_device *adev
/* 7- wait for RLC_SERDES_CU_MASTER & RLC_SERDES_NONCU_MASTER idle */
gfx_v8_0_wait_for_rlc_serdes(adev);
}
amdgpu_gfx_rlc_exit_safe_mode(adev, 0);
}
static void gfx_v8_0_update_coarse_grain_clock_gating(struct amdgpu_device *adev,
@@ -5745,8 +5741,6 @@ static void gfx_v8_0_update_coarse_grain_clock_gating(struct amdgpu_device *adev
temp = data = RREG32(mmRLC_CGCG_CGLS_CTRL);
amdgpu_gfx_rlc_enter_safe_mode(adev, 0);
if (enable && (adev->cg_flags & AMD_CG_SUPPORT_GFX_CGCG)) {
temp1 = data1 = RREG32(mmRLC_CGTT_MGCG_OVERRIDE);
data1 &= ~RLC_CGTT_MGCG_OVERRIDE__CGCG_MASK;
@@ -5827,12 +5821,12 @@ static void gfx_v8_0_update_coarse_grain_clock_gating(struct amdgpu_device *adev
}
gfx_v8_0_wait_for_rlc_serdes(adev);
amdgpu_gfx_rlc_exit_safe_mode(adev, 0);
}
static int gfx_v8_0_update_gfx_clock_gating(struct amdgpu_device *adev,
bool enable)
{
amdgpu_gfx_rlc_enter_safe_mode(adev, 0);
if (enable) {
/* CGCG/CGLS should be enabled after MGCG/MGLS/TS(CG/LS)
* === MGCG + MGLS + TS(CG/LS) ===
@@ -5846,6 +5840,8 @@ static int gfx_v8_0_update_gfx_clock_gating(struct amdgpu_device *adev,
gfx_v8_0_update_coarse_grain_clock_gating(adev, enable);
gfx_v8_0_update_medium_grain_clock_gating(adev, enable);
}
amdgpu_gfx_rlc_exit_safe_mode(adev, 0);
return 0;
}

View File

@@ -4964,8 +4964,6 @@ static void gfx_v9_0_update_medium_grain_clock_gating(struct amdgpu_device *adev
{
uint32_t data, def;
amdgpu_gfx_rlc_enter_safe_mode(adev, 0);
/* It is disabled by HW by default */
if (enable && (adev->cg_flags & AMD_CG_SUPPORT_GFX_MGCG)) {
/* 1 - RLC_CGTT_MGCG_OVERRIDE */
@@ -5030,8 +5028,6 @@ static void gfx_v9_0_update_medium_grain_clock_gating(struct amdgpu_device *adev
WREG32_SOC15(GC, 0, mmCP_MEM_SLP_CNTL, data);
}
}
amdgpu_gfx_rlc_exit_safe_mode(adev, 0);
}
static void gfx_v9_0_update_3d_clock_gating(struct amdgpu_device *adev,
@@ -5042,8 +5038,6 @@ static void gfx_v9_0_update_3d_clock_gating(struct amdgpu_device *adev,
if (!adev->gfx.num_gfx_rings)
return;
amdgpu_gfx_rlc_enter_safe_mode(adev, 0);
/* Enable 3D CGCG/CGLS */
if (enable) {
/* write cmd to clear cgcg/cgls ov */
@@ -5085,8 +5079,6 @@ static void gfx_v9_0_update_3d_clock_gating(struct amdgpu_device *adev,
if (def != data)
WREG32_SOC15(GC, 0, mmRLC_CGCG_CGLS_CTRL_3D, data);
}
amdgpu_gfx_rlc_exit_safe_mode(adev, 0);
}
static void gfx_v9_0_update_coarse_grain_clock_gating(struct amdgpu_device *adev,
@@ -5094,8 +5086,6 @@ static void gfx_v9_0_update_coarse_grain_clock_gating(struct amdgpu_device *adev
{
uint32_t def, data;
amdgpu_gfx_rlc_enter_safe_mode(adev, 0);
if (enable && (adev->cg_flags & AMD_CG_SUPPORT_GFX_CGCG)) {
def = data = RREG32_SOC15(GC, 0, mmRLC_CGTT_MGCG_OVERRIDE);
/* unset CGCG override */
@@ -5137,13 +5127,12 @@ static void gfx_v9_0_update_coarse_grain_clock_gating(struct amdgpu_device *adev
if (def != data)
WREG32_SOC15(GC, 0, mmRLC_CGCG_CGLS_CTRL, data);
}
amdgpu_gfx_rlc_exit_safe_mode(adev, 0);
}
static int gfx_v9_0_update_gfx_clock_gating(struct amdgpu_device *adev,
bool enable)
{
amdgpu_gfx_rlc_enter_safe_mode(adev, 0);
if (enable) {
/* CGCG/CGLS should be enabled after MGCG/MGLS
* === MGCG + MGLS ===
@@ -5163,6 +5152,7 @@ static int gfx_v9_0_update_gfx_clock_gating(struct amdgpu_device *adev,
/* === MGCG + MGLS === */
gfx_v9_0_update_medium_grain_clock_gating(adev, enable);
}
amdgpu_gfx_rlc_exit_safe_mode(adev, 0);
return 0;
}

View File

@@ -579,11 +579,16 @@ static int gfx_v9_4_3_init_cp_compute_microcode(struct amdgpu_device *adev,
{
int err;
if (amdgpu_sriov_vf(adev))
if (amdgpu_sriov_vf(adev)) {
err = amdgpu_ucode_request(adev, &adev->gfx.mec_fw,
AMDGPU_UCODE_REQUIRED,
"amdgpu/%s_sjt_mec.bin", chip_name);
else
if (err)
err = amdgpu_ucode_request(adev, &adev->gfx.mec_fw,
AMDGPU_UCODE_REQUIRED,
"amdgpu/%s_mec.bin", chip_name);
} else
err = amdgpu_ucode_request(adev, &adev->gfx.mec_fw,
AMDGPU_UCODE_REQUIRED,
"amdgpu/%s_mec.bin", chip_name);

View File

@@ -1602,7 +1602,7 @@ static int sdma_v4_4_2_reset_queue(struct amdgpu_ring *ring, unsigned int vmid)
int i, r;
u32 inst_mask;
if ((adev->flags & AMD_IS_APU) || amdgpu_sriov_vf(adev))
if (amdgpu_sriov_vf(adev))
return -EINVAL;
/* stop queue */

View File

@@ -34,41 +34,24 @@
* cpp -DASIC_FAMILY=CHIP_PLUM_BONITO cwsr_trap_handler_gfx10.asm -P -o gfx11.sp3
* sp3 gfx11.sp3 -hex gfx11.hex
*
* gfx12:
* cpp -DASIC_FAMILY=CHIP_GFX12 cwsr_trap_handler_gfx10.asm -P -o gfx12.sp3
* sp3 gfx12.sp3 -hex gfx12.hex
*/
#define CHIP_NAVI10 26
#define CHIP_SIENNA_CICHLID 30
#define CHIP_PLUM_BONITO 36
#define CHIP_GFX12 37
#define NO_SQC_STORE (ASIC_FAMILY >= CHIP_SIENNA_CICHLID)
#define HAVE_XNACK (ASIC_FAMILY < CHIP_SIENNA_CICHLID)
#define HAVE_SENDMSG_RTN (ASIC_FAMILY >= CHIP_PLUM_BONITO)
#define HAVE_BUFFER_LDS_LOAD (ASIC_FAMILY < CHIP_PLUM_BONITO)
#define SW_SA_TRAP (ASIC_FAMILY >= CHIP_PLUM_BONITO && ASIC_FAMILY < CHIP_GFX12)
#define SW_SA_TRAP (ASIC_FAMILY == CHIP_PLUM_BONITO)
#define SAVE_AFTER_XNACK_ERROR (HAVE_XNACK && !NO_SQC_STORE) // workaround for TCP store failure after XNACK error when ALLOW_REPLAY=0, for debugger
#define SINGLE_STEP_MISSED_WORKAROUND 1 //workaround for lost MODE.DEBUG_EN exception when SAVECTX raised
#if ASIC_FAMILY < CHIP_GFX12
#define S_COHERENCE glc:1
#define V_COHERENCE slc:1 glc:1
#define S_WAITCNT_0 s_waitcnt 0
#else
#define S_COHERENCE scope:SCOPE_SYS
#define V_COHERENCE scope:SCOPE_SYS
#define S_WAITCNT_0 s_wait_idle
#define HW_REG_SHADER_FLAT_SCRATCH_LO HW_REG_WAVE_SCRATCH_BASE_LO
#define HW_REG_SHADER_FLAT_SCRATCH_HI HW_REG_WAVE_SCRATCH_BASE_HI
#define HW_REG_GPR_ALLOC HW_REG_WAVE_GPR_ALLOC
#define HW_REG_LDS_ALLOC HW_REG_WAVE_LDS_ALLOC
#define HW_REG_MODE HW_REG_WAVE_MODE
#endif
#if ASIC_FAMILY < CHIP_GFX12
var SQ_WAVE_STATUS_SPI_PRIO_MASK = 0x00000006
var SQ_WAVE_STATUS_HALT_MASK = 0x2000
var SQ_WAVE_STATUS_ECC_ERR_MASK = 0x20000
@@ -81,21 +64,6 @@ var S_STATUS_ALWAYS_CLEAR_MASK = SQ_WAVE_STATUS_SPI_PRIO_MASK|SQ_WAVE_STATUS_E
var S_STATUS_HALT_MASK = SQ_WAVE_STATUS_HALT_MASK
var S_SAVE_PC_HI_TRAP_ID_MASK = 0x00FF0000
var S_SAVE_PC_HI_HT_MASK = 0x01000000
#else
var SQ_WAVE_STATE_PRIV_BARRIER_COMPLETE_MASK = 0x4
var SQ_WAVE_STATE_PRIV_SCC_SHIFT = 9
var SQ_WAVE_STATE_PRIV_SYS_PRIO_MASK = 0xC00
var SQ_WAVE_STATE_PRIV_HALT_MASK = 0x4000
var SQ_WAVE_STATE_PRIV_POISON_ERR_MASK = 0x8000
var SQ_WAVE_STATE_PRIV_POISON_ERR_SHIFT = 15
var SQ_WAVE_STATUS_WAVE64_SHIFT = 29
var SQ_WAVE_STATUS_WAVE64_SIZE = 1
var SQ_WAVE_LDS_ALLOC_GRANULARITY = 9
var S_STATUS_HWREG = HW_REG_WAVE_STATE_PRIV
var S_STATUS_ALWAYS_CLEAR_MASK = SQ_WAVE_STATE_PRIV_SYS_PRIO_MASK|SQ_WAVE_STATE_PRIV_POISON_ERR_MASK
var S_STATUS_HALT_MASK = SQ_WAVE_STATE_PRIV_HALT_MASK
var S_SAVE_PC_HI_TRAP_ID_MASK = 0xF0000000
#endif
var SQ_WAVE_STATUS_NO_VGPRS_SHIFT = 24
var SQ_WAVE_LDS_ALLOC_LDS_SIZE_SHIFT = 12
@@ -110,7 +78,6 @@ var SQ_WAVE_GPR_ALLOC_VGPR_SIZE_SHIFT = 8
var SQ_WAVE_GPR_ALLOC_VGPR_SIZE_SHIFT = 12
#endif
#if ASIC_FAMILY < CHIP_GFX12
var SQ_WAVE_TRAPSTS_SAVECTX_MASK = 0x400
var SQ_WAVE_TRAPSTS_EXCP_MASK = 0x1FF
var SQ_WAVE_TRAPSTS_SAVECTX_SHIFT = 10
@@ -161,39 +128,6 @@ var S_TRAPSTS_RESTORE_PART_3_SIZE = 32 - S_TRAPSTS_RESTORE_PART_3_SHIFT
var S_TRAPSTS_HWREG = HW_REG_TRAPSTS
var S_TRAPSTS_SAVE_CONTEXT_MASK = SQ_WAVE_TRAPSTS_SAVECTX_MASK
var S_TRAPSTS_SAVE_CONTEXT_SHIFT = SQ_WAVE_TRAPSTS_SAVECTX_SHIFT
#else
var SQ_WAVE_EXCP_FLAG_PRIV_ADDR_WATCH_MASK = 0xF
var SQ_WAVE_EXCP_FLAG_PRIV_MEM_VIOL_MASK = 0x10
var SQ_WAVE_EXCP_FLAG_PRIV_SAVE_CONTEXT_SHIFT = 5
var SQ_WAVE_EXCP_FLAG_PRIV_SAVE_CONTEXT_MASK = 0x20
var SQ_WAVE_EXCP_FLAG_PRIV_ILLEGAL_INST_MASK = 0x40
var SQ_WAVE_EXCP_FLAG_PRIV_ILLEGAL_INST_SHIFT = 6
var SQ_WAVE_EXCP_FLAG_PRIV_HOST_TRAP_MASK = 0x80
var SQ_WAVE_EXCP_FLAG_PRIV_HOST_TRAP_SHIFT = 7
var SQ_WAVE_EXCP_FLAG_PRIV_WAVE_START_MASK = 0x100
var SQ_WAVE_EXCP_FLAG_PRIV_WAVE_START_SHIFT = 8
var SQ_WAVE_EXCP_FLAG_PRIV_WAVE_END_MASK = 0x200
var SQ_WAVE_EXCP_FLAG_PRIV_TRAP_AFTER_INST_MASK = 0x800
var SQ_WAVE_TRAP_CTRL_ADDR_WATCH_MASK = 0x80
var SQ_WAVE_TRAP_CTRL_TRAP_AFTER_INST_MASK = 0x200
var S_TRAPSTS_HWREG = HW_REG_WAVE_EXCP_FLAG_PRIV
var S_TRAPSTS_SAVE_CONTEXT_MASK = SQ_WAVE_EXCP_FLAG_PRIV_SAVE_CONTEXT_MASK
var S_TRAPSTS_SAVE_CONTEXT_SHIFT = SQ_WAVE_EXCP_FLAG_PRIV_SAVE_CONTEXT_SHIFT
var S_TRAPSTS_NON_MASKABLE_EXCP_MASK = SQ_WAVE_EXCP_FLAG_PRIV_MEM_VIOL_MASK |\
SQ_WAVE_EXCP_FLAG_PRIV_ILLEGAL_INST_MASK |\
SQ_WAVE_EXCP_FLAG_PRIV_HOST_TRAP_MASK |\
SQ_WAVE_EXCP_FLAG_PRIV_WAVE_START_MASK |\
SQ_WAVE_EXCP_FLAG_PRIV_WAVE_END_MASK |\
SQ_WAVE_EXCP_FLAG_PRIV_TRAP_AFTER_INST_MASK
var S_TRAPSTS_RESTORE_PART_1_SIZE = SQ_WAVE_EXCP_FLAG_PRIV_SAVE_CONTEXT_SHIFT
var S_TRAPSTS_RESTORE_PART_2_SHIFT = SQ_WAVE_EXCP_FLAG_PRIV_ILLEGAL_INST_SHIFT
var S_TRAPSTS_RESTORE_PART_2_SIZE = SQ_WAVE_EXCP_FLAG_PRIV_HOST_TRAP_SHIFT - SQ_WAVE_EXCP_FLAG_PRIV_ILLEGAL_INST_SHIFT
var S_TRAPSTS_RESTORE_PART_3_SHIFT = SQ_WAVE_EXCP_FLAG_PRIV_WAVE_START_SHIFT
var S_TRAPSTS_RESTORE_PART_3_SIZE = 32 - S_TRAPSTS_RESTORE_PART_3_SHIFT
var BARRIER_STATE_SIGNAL_OFFSET = 16
var BARRIER_STATE_VALID_OFFSET = 0
#endif
// bits [31:24] unused by SPI debug data
var TTMP11_SAVE_REPLAY_W64H_SHIFT = 31
@@ -305,11 +239,7 @@ L_TRAP_NO_BARRIER:
L_HALTED:
// Host trap may occur while wave is halted.
#if ASIC_FAMILY < CHIP_GFX12
s_and_b32 ttmp2, s_save_pc_hi, S_SAVE_PC_HI_TRAP_ID_MASK
#else
s_and_b32 ttmp2, s_save_trapsts, SQ_WAVE_EXCP_FLAG_PRIV_HOST_TRAP_MASK
#endif
s_cbranch_scc1 L_FETCH_2ND_TRAP
L_CHECK_SAVE:
@@ -336,7 +266,6 @@ L_NOT_HALTED:
// Check for maskable exceptions in trapsts.excp and trapsts.excp_hi.
// Maskable exceptions only cause the wave to enter the trap handler if
// their respective bit in mode.excp_en is set.
#if ASIC_FAMILY < CHIP_GFX12
s_and_b32 ttmp2, s_save_trapsts, SQ_WAVE_TRAPSTS_EXCP_MASK|SQ_WAVE_TRAPSTS_EXCP_HI_MASK
s_cbranch_scc0 L_CHECK_TRAP_ID
@@ -349,17 +278,6 @@ L_NOT_ADDR_WATCH:
s_lshl_b32 ttmp2, ttmp2, SQ_WAVE_MODE_EXCP_EN_SHIFT
s_and_b32 ttmp2, ttmp2, ttmp3
s_cbranch_scc1 L_FETCH_2ND_TRAP
#else
s_getreg_b32 ttmp2, hwreg(HW_REG_WAVE_EXCP_FLAG_USER)
s_and_b32 ttmp3, s_save_trapsts, SQ_WAVE_EXCP_FLAG_PRIV_ADDR_WATCH_MASK
s_cbranch_scc0 L_NOT_ADDR_WATCH
s_or_b32 ttmp2, ttmp2, SQ_WAVE_TRAP_CTRL_ADDR_WATCH_MASK
L_NOT_ADDR_WATCH:
s_getreg_b32 ttmp3, hwreg(HW_REG_WAVE_TRAP_CTRL)
s_and_b32 ttmp2, ttmp3, ttmp2
s_cbranch_scc1 L_FETCH_2ND_TRAP
#endif
L_CHECK_TRAP_ID:
// Check trap_id != 0
@@ -369,13 +287,8 @@ L_CHECK_TRAP_ID:
#if SINGLE_STEP_MISSED_WORKAROUND
// Prioritize single step exception over context save.
// Second-level trap will halt wave and RFE, re-entering for SAVECTX.
#if ASIC_FAMILY < CHIP_GFX12
s_getreg_b32 ttmp2, hwreg(HW_REG_MODE)
s_and_b32 ttmp2, ttmp2, SQ_WAVE_MODE_DEBUG_EN_MASK
#else
// WAVE_TRAP_CTRL is already in ttmp3.
s_and_b32 ttmp3, ttmp3, SQ_WAVE_TRAP_CTRL_TRAP_AFTER_INST_MASK
#endif
s_cbranch_scc1 L_FETCH_2ND_TRAP
#endif
@@ -425,12 +338,7 @@ L_NO_NEXT_TRAP:
s_cbranch_scc1 L_TRAP_CASE
// Host trap will not cause trap re-entry.
#if ASIC_FAMILY < CHIP_GFX12
s_and_b32 ttmp2, s_save_pc_hi, S_SAVE_PC_HI_HT_MASK
#else
s_getreg_b32 ttmp2, hwreg(HW_REG_WAVE_EXCP_FLAG_PRIV)
s_and_b32 ttmp2, ttmp2, SQ_WAVE_EXCP_FLAG_PRIV_HOST_TRAP_MASK
#endif
s_cbranch_scc1 L_EXIT_TRAP
s_or_b32 s_save_status, s_save_status, S_STATUS_HALT_MASK
@@ -457,16 +365,7 @@ L_EXIT_TRAP:
s_and_b64 exec, exec, exec // Restore STATUS.EXECZ, not writable by s_setreg_b32
s_and_b64 vcc, vcc, vcc // Restore STATUS.VCCZ, not writable by s_setreg_b32
#if ASIC_FAMILY < CHIP_GFX12
s_setreg_b32 hwreg(S_STATUS_HWREG), s_save_status
#else
// STATE_PRIV.BARRIER_COMPLETE may have changed since we read it.
// Only restore fields which the trap handler changes.
s_lshr_b32 s_save_status, s_save_status, SQ_WAVE_STATE_PRIV_SCC_SHIFT
s_setreg_b32 hwreg(S_STATUS_HWREG, SQ_WAVE_STATE_PRIV_SCC_SHIFT, \
SQ_WAVE_STATE_PRIV_POISON_ERR_SHIFT - SQ_WAVE_STATE_PRIV_SCC_SHIFT + 1), s_save_status
#endif
s_rfe_b64 [ttmp0, ttmp1]
L_SAVE:
@@ -478,14 +377,6 @@ L_SAVE:
s_endpgm
L_HAVE_VGPRS:
#endif
#if ASIC_FAMILY >= CHIP_GFX12
s_getreg_b32 s_save_tmp, hwreg(HW_REG_WAVE_STATUS)
s_bitcmp1_b32 s_save_tmp, SQ_WAVE_STATUS_NO_VGPRS_SHIFT
s_cbranch_scc0 L_HAVE_VGPRS
s_endpgm
L_HAVE_VGPRS:
#endif
s_and_b32 s_save_pc_hi, s_save_pc_hi, 0x0000ffff //pc[47:32]
s_mov_b32 s_save_tmp, 0
s_setreg_b32 hwreg(S_TRAPSTS_HWREG, S_TRAPSTS_SAVE_CONTEXT_SHIFT, 1), s_save_tmp //clear saveCtx bit
@@ -671,19 +562,6 @@ L_SAVE_HWREG:
s_mov_b32 m0, 0x0 //Next lane of v2 to write to
#endif
#if ASIC_FAMILY >= CHIP_GFX12
// Ensure no further changes to barrier or LDS state.
// STATE_PRIV.BARRIER_COMPLETE may change up to this point.
s_barrier_signal -2
s_barrier_wait -2
// Re-read final state of BARRIER_COMPLETE field for save.
s_getreg_b32 s_save_tmp, hwreg(S_STATUS_HWREG)
s_and_b32 s_save_tmp, s_save_tmp, SQ_WAVE_STATE_PRIV_BARRIER_COMPLETE_MASK
s_andn2_b32 s_save_status, s_save_status, SQ_WAVE_STATE_PRIV_BARRIER_COMPLETE_MASK
s_or_b32 s_save_status, s_save_status, s_save_tmp
#endif
write_hwreg_to_mem(s_save_m0, s_save_buf_rsrc0, s_save_mem_offset)
write_hwreg_to_mem(s_save_pc_lo, s_save_buf_rsrc0, s_save_mem_offset)
s_andn2_b32 s_save_tmp, s_save_pc_hi, S_SAVE_PC_HI_FIRST_WAVE_MASK
@@ -707,21 +585,6 @@ L_SAVE_HWREG:
s_getreg_b32 s_save_m0, hwreg(HW_REG_SHADER_FLAT_SCRATCH_HI)
write_hwreg_to_mem(s_save_m0, s_save_buf_rsrc0, s_save_mem_offset)
#if ASIC_FAMILY >= CHIP_GFX12
s_getreg_b32 s_save_m0, hwreg(HW_REG_WAVE_EXCP_FLAG_USER)
write_hwreg_to_mem(s_save_m0, s_save_buf_rsrc0, s_save_mem_offset)
s_getreg_b32 s_save_m0, hwreg(HW_REG_WAVE_TRAP_CTRL)
write_hwreg_to_mem(s_save_m0, s_save_buf_rsrc0, s_save_mem_offset)
s_getreg_b32 s_save_tmp, hwreg(HW_REG_WAVE_STATUS)
write_hwreg_to_mem(s_save_tmp, s_save_buf_rsrc0, s_save_mem_offset)
s_get_barrier_state s_save_tmp, -1
s_wait_kmcnt (0)
write_hwreg_to_mem(s_save_tmp, s_save_buf_rsrc0, s_save_mem_offset)
#endif
#if NO_SQC_STORE
// Write HWREGs with 16 VGPR lanes. TTMPs occupy space after this.
s_mov_b32 exec_lo, 0xFFFF
@@ -814,9 +677,7 @@ L_SAVE_LDS_NORMAL:
s_and_b32 s_save_alloc_size, s_save_alloc_size, 0xFFFFFFFF //lds_size is zero?
s_cbranch_scc0 L_SAVE_LDS_DONE //no lds used? jump to L_SAVE_DONE
#if ASIC_FAMILY < CHIP_GFX12
s_barrier //LDS is used? wait for other waves in the same TG
#endif
s_and_b32 s_save_tmp, s_save_pc_hi, S_SAVE_PC_HI_FIRST_WAVE_MASK
s_cbranch_scc0 L_SAVE_LDS_DONE
@@ -1081,11 +942,6 @@ L_RESTORE:
s_mov_b32 s_restore_buf_rsrc2, 0 //NUM_RECORDS initial value = 0 (in bytes)
s_mov_b32 s_restore_buf_rsrc3, S_RESTORE_BUF_RSRC_WORD3_MISC
#if ASIC_FAMILY >= CHIP_GFX12
// Save s_restore_spi_init_hi for later use.
s_mov_b32 s_restore_spi_init_hi_save, s_restore_spi_init_hi
#endif
//determine it is wave32 or wave64
get_wave_size2(s_restore_size)
@@ -1320,9 +1176,7 @@ L_RESTORE_SGPR:
// s_barrier with MODE.DEBUG_EN=1, STATUS.PRIV=1 incorrectly asserts debug exception.
// Clear DEBUG_EN before and restore MODE after the barrier.
s_setreg_imm32_b32 hwreg(HW_REG_MODE), 0
#if ASIC_FAMILY < CHIP_GFX12
s_barrier //barrier to ensure the readiness of LDS before access attemps from any other wave in the same TG
#endif
/* restore HW registers */
L_RESTORE_HWREG:
@@ -1334,11 +1188,6 @@ L_RESTORE_HWREG:
s_mov_b32 s_restore_buf_rsrc2, 0x1000000 //NUM_RECORDS in bytes
#if ASIC_FAMILY >= CHIP_GFX12
// Restore s_restore_spi_init_hi before the saved value gets clobbered.
s_mov_b32 s_restore_spi_init_hi, s_restore_spi_init_hi_save
#endif
read_hwreg_from_mem(s_restore_m0, s_restore_buf_rsrc0, s_restore_mem_offset)
read_hwreg_from_mem(s_restore_pc_lo, s_restore_buf_rsrc0, s_restore_mem_offset)
read_hwreg_from_mem(s_restore_pc_hi, s_restore_buf_rsrc0, s_restore_mem_offset)
@@ -1358,44 +1207,6 @@ L_RESTORE_HWREG:
s_setreg_b32 hwreg(HW_REG_SHADER_FLAT_SCRATCH_HI), s_restore_flat_scratch
#if ASIC_FAMILY >= CHIP_GFX12
read_hwreg_from_mem(s_restore_tmp, s_restore_buf_rsrc0, s_restore_mem_offset)
S_WAITCNT_0
s_setreg_b32 hwreg(HW_REG_WAVE_EXCP_FLAG_USER), s_restore_tmp
read_hwreg_from_mem(s_restore_tmp, s_restore_buf_rsrc0, s_restore_mem_offset)
S_WAITCNT_0
s_setreg_b32 hwreg(HW_REG_WAVE_TRAP_CTRL), s_restore_tmp
// Only the first wave needs to restore the workgroup barrier.
s_and_b32 s_restore_tmp, s_restore_spi_init_hi, S_RESTORE_SPI_INIT_FIRST_WAVE_MASK
s_cbranch_scc0 L_SKIP_BARRIER_RESTORE
// Skip over WAVE_STATUS, since there is no state to restore from it
s_add_u32 s_restore_mem_offset, s_restore_mem_offset, 4
read_hwreg_from_mem(s_restore_tmp, s_restore_buf_rsrc0, s_restore_mem_offset)
S_WAITCNT_0
s_bitcmp1_b32 s_restore_tmp, BARRIER_STATE_VALID_OFFSET
s_cbranch_scc0 L_SKIP_BARRIER_RESTORE
// extract the saved signal count from s_restore_tmp
s_lshr_b32 s_restore_tmp, s_restore_tmp, BARRIER_STATE_SIGNAL_OFFSET
// We need to call s_barrier_signal repeatedly to restore the signal
// count of the work group barrier. The member count is already
// initialized with the number of waves in the work group.
L_BARRIER_RESTORE_LOOP:
s_and_b32 s_restore_tmp, s_restore_tmp, s_restore_tmp
s_cbranch_scc0 L_SKIP_BARRIER_RESTORE
s_barrier_signal -1
s_add_i32 s_restore_tmp, s_restore_tmp, -1
s_branch L_BARRIER_RESTORE_LOOP
L_SKIP_BARRIER_RESTORE:
#endif
s_mov_b32 m0, s_restore_m0
s_mov_b32 exec_lo, s_restore_exec_lo
s_mov_b32 exec_hi, s_restore_exec_hi
@@ -1453,13 +1264,6 @@ L_RETURN_WITHOUT_PRIV:
s_setreg_b32 hwreg(S_STATUS_HWREG), s_restore_status // SCC is included, which is changed by previous salu
#if ASIC_FAMILY >= CHIP_GFX12
// Make barrier and LDS state visible to all waves in the group.
// STATE_PRIV.BARRIER_COMPLETE may change after this point.
s_barrier_signal -2
s_barrier_wait -2
#endif
s_rfe_b64 s_restore_pc_lo //Return to the main shader program and resume execution
L_END_PGM:
@@ -1598,11 +1402,7 @@ function get_hwreg_size_bytes
end
function get_wave_size2(s_reg)
#if ASIC_FAMILY < CHIP_GFX12
s_getreg_b32 s_reg, hwreg(HW_REG_IB_STS2,SQ_WAVE_IB_STS2_WAVE64_SHIFT,SQ_WAVE_IB_STS2_WAVE64_SIZE)
#else
s_getreg_b32 s_reg, hwreg(HW_REG_WAVE_STATUS,SQ_WAVE_STATUS_WAVE64_SHIFT,SQ_WAVE_STATUS_WAVE64_SIZE)
#endif
s_lshl_b32 s_reg, s_reg, S_WAVE_SIZE
end

File diff suppressed because it is too large Load Diff

View File

@@ -350,10 +350,27 @@ int kfd_dbg_set_mes_debug_mode(struct kfd_process_device *pdd, bool sq_trap_en)
{
uint32_t spi_dbg_cntl = pdd->spi_dbg_override | pdd->spi_dbg_launch_mode;
uint32_t flags = pdd->process->dbg_flags;
struct amdgpu_device *adev = pdd->dev->adev;
int r;
if (!kfd_dbg_is_per_vmid_supported(pdd->dev))
return 0;
if (!pdd->proc_ctx_cpu_ptr) {
r = amdgpu_amdkfd_alloc_gtt_mem(adev,
AMDGPU_MES_PROC_CTX_SIZE,
&pdd->proc_ctx_bo,
&pdd->proc_ctx_gpu_addr,
&pdd->proc_ctx_cpu_ptr,
false);
if (r) {
dev_err(adev->dev,
"failed to allocate process context bo\n");
return r;
}
memset(pdd->proc_ctx_cpu_ptr, 0, AMDGPU_MES_PROC_CTX_SIZE);
}
return amdgpu_mes_set_shader_debugger(pdd->dev->adev, pdd->proc_ctx_gpu_addr, spi_dbg_cntl,
pdd->watch_points, flags, sq_trap_en);
}

View File

@@ -32,7 +32,7 @@
#include <linux/atomic.h>
#include <linux/workqueue.h>
#include <linux/spinlock.h>
#include <linux/kfd_ioctl.h>
#include <uapi/linux/kfd_ioctl.h>
#include <linux/idr.h>
#include <linux/kfifo.h>
#include <linux/seq_file.h>

View File

@@ -1160,7 +1160,8 @@ static void kfd_process_wq_release(struct work_struct *work)
*/
synchronize_rcu();
ef = rcu_access_pointer(p->ef);
dma_fence_signal(ef);
if (ef)
dma_fence_signal(ef);
kfd_process_remove_sysfs(p);

View File

@@ -8,6 +8,8 @@ config DRM_AMD_DC
bool "AMD DC - Enable new display engine"
default y
depends on BROKEN || !CC_IS_CLANG || ARM64 || LOONGARCH || RISCV || SPARC64 || X86_64
select CEC_CORE
select CEC_NOTIFIER
select SND_HDA_COMPONENT if SND_HDA_CORE
# !CC_IS_CLANG: https://github.com/ClangBuiltLinux/linux/issues/1752
select DRM_AMD_DC_FP if ARCH_HAS_KERNEL_FPU_SUPPORT && !(CC_IS_CLANG && (ARM64 || LOONGARCH || RISCV))

View File

@@ -98,6 +98,7 @@
#include <drm/drm_audio_component.h>
#include <drm/drm_gem_atomic_helper.h>
#include <media/cec-notifier.h>
#include <acpi/video.h>
#include "ivsrcid/dcn/irqsrcs_dcn_1_0.h"
@@ -2158,6 +2159,10 @@ static int amdgpu_dm_init(struct amdgpu_device *adev)
amdgpu_dm_crtc_secure_display_create_contexts(adev);
if (!adev->dm.secure_display_ctx.crtc_ctx)
DRM_ERROR("amdgpu: failed to initialize secure display contexts.\n");
if (amdgpu_ip_version(adev, DCE_HWIP, 0) >= IP_VERSION(4, 0, 1))
adev->dm.secure_display_ctx.support_mul_roi = true;
#endif
DRM_DEBUG_DRIVER("KMS initialized.\n");
@@ -2750,6 +2755,48 @@ out_fail:
mutex_unlock(&mgr->lock);
}
void hdmi_cec_unset_edid(struct amdgpu_dm_connector *aconnector)
{
struct cec_notifier *n = aconnector->notifier;
if (!n)
return;
cec_notifier_phys_addr_invalidate(n);
}
void hdmi_cec_set_edid(struct amdgpu_dm_connector *aconnector)
{
struct drm_connector *connector = &aconnector->base;
struct cec_notifier *n = aconnector->notifier;
if (!n)
return;
cec_notifier_set_phys_addr(n,
connector->display_info.source_physical_address);
}
static void s3_handle_hdmi_cec(struct drm_device *ddev, bool suspend)
{
struct amdgpu_dm_connector *aconnector;
struct drm_connector *connector;
struct drm_connector_list_iter conn_iter;
drm_connector_list_iter_begin(ddev, &conn_iter);
drm_for_each_connector_iter(connector, &conn_iter) {
if (connector->connector_type == DRM_MODE_CONNECTOR_WRITEBACK)
continue;
aconnector = to_amdgpu_dm_connector(connector);
if (suspend)
hdmi_cec_unset_edid(aconnector);
else
hdmi_cec_set_edid(aconnector);
}
drm_connector_list_iter_end(&conn_iter);
}
static void s3_handle_mst(struct drm_device *dev, bool suspend)
{
struct amdgpu_dm_connector *aconnector;
@@ -3021,6 +3068,8 @@ static int dm_suspend(struct amdgpu_ip_block *ip_block)
if (IS_ERR(adev->dm.cached_state))
return PTR_ERR(adev->dm.cached_state);
s3_handle_hdmi_cec(adev_to_drm(adev), true);
s3_handle_mst(adev_to_drm(adev), true);
amdgpu_dm_irq_suspend(adev);
@@ -3293,6 +3342,8 @@ static int dm_resume(struct amdgpu_ip_block *ip_block)
*/
amdgpu_dm_irq_resume_early(adev);
s3_handle_hdmi_cec(ddev, false);
/* On resume we need to rewrite the MSTM control bits to enable MST*/
s3_handle_mst(ddev, false);
@@ -3607,6 +3658,7 @@ void amdgpu_dm_update_connector_after_detect(
dc_sink_retain(aconnector->dc_sink);
if (sink->dc_edid.length == 0) {
aconnector->drm_edid = NULL;
hdmi_cec_unset_edid(aconnector);
if (aconnector->dc_link->aux_mode) {
drm_dp_cec_unset_edid(&aconnector->dm_dp_aux.aux);
}
@@ -3616,6 +3668,7 @@ void amdgpu_dm_update_connector_after_detect(
aconnector->drm_edid = drm_edid_alloc(edid, sink->dc_edid.length);
drm_edid_connector_update(connector, aconnector->drm_edid);
hdmi_cec_set_edid(aconnector);
if (aconnector->dc_link->aux_mode)
drm_dp_cec_attach(&aconnector->dm_dp_aux.aux,
connector->display_info.source_physical_address);
@@ -3632,6 +3685,7 @@ void amdgpu_dm_update_connector_after_detect(
amdgpu_dm_update_freesync_caps(connector, aconnector->drm_edid);
update_connector_ext_caps(aconnector);
} else {
hdmi_cec_unset_edid(aconnector);
drm_dp_cec_unset_edid(&aconnector->dm_dp_aux.aux);
amdgpu_dm_update_freesync_caps(connector, NULL);
aconnector->num_modes = 0;
@@ -7048,6 +7102,7 @@ static void amdgpu_dm_connector_unregister(struct drm_connector *connector)
if (amdgpu_dm_should_create_sysfs(amdgpu_dm_connector))
sysfs_remove_group(&connector->kdev->kobj, &amdgpu_group);
cec_notifier_conn_unregister(amdgpu_dm_connector->notifier);
drm_dp_aux_unregister(&amdgpu_dm_connector->dm_dp_aux.aux);
}
@@ -8284,6 +8339,27 @@ create_i2c(struct ddc_service *ddc_service,
return i2c;
}
int amdgpu_dm_initialize_hdmi_connector(struct amdgpu_dm_connector *aconnector)
{
struct cec_connector_info conn_info;
struct drm_device *ddev = aconnector->base.dev;
struct device *hdmi_dev = ddev->dev;
if (amdgpu_dc_debug_mask & DC_DISABLE_HDMI_CEC) {
drm_info(ddev, "HDMI-CEC feature masked\n");
return -EINVAL;
}
cec_fill_conn_info_from_drm(&conn_info, &aconnector->base);
aconnector->notifier =
cec_notifier_conn_register(hdmi_dev, NULL, &conn_info);
if (!aconnector->notifier) {
drm_err(ddev, "Failed to create cec notifier\n");
return -ENOMEM;
}
return 0;
}
/*
* Note: this function assumes that dc_link_detect() was called for the
@@ -8347,6 +8423,10 @@ static int amdgpu_dm_connector_init(struct amdgpu_display_manager *dm,
drm_connector_attach_encoder(
&aconnector->base, &aencoder->base);
if (connector_type == DRM_MODE_CONNECTOR_HDMIA ||
connector_type == DRM_MODE_CONNECTOR_HDMIB)
amdgpu_dm_initialize_hdmi_connector(aconnector);
if (connector_type == DRM_MODE_CONNECTOR_DisplayPort
|| connector_type == DRM_MODE_CONNECTOR_eDP)
amdgpu_dm_initialize_dp_connector(dm, aconnector, link->link_index);
@@ -8406,16 +8486,6 @@ static void manage_dm_interrupts(struct amdgpu_device *adev,
struct amdgpu_crtc *acrtc,
struct dm_crtc_state *acrtc_state)
{
/*
* We have no guarantee that the frontend index maps to the same
* backend index - some even map to more than one.
*
* TODO: Use a different interrupt or check DC itself for the mapping.
*/
int irq_type =
amdgpu_display_crtc_idx_to_irq_type(
adev,
acrtc->crtc_id);
struct drm_vblank_crtc_config config = {0};
struct dc_crtc_timing *timing;
int offdelay;
@@ -8441,28 +8511,7 @@ static void manage_dm_interrupts(struct amdgpu_device *adev,
drm_crtc_vblank_on_config(&acrtc->base,
&config);
amdgpu_irq_get(
adev,
&adev->pageflip_irq,
irq_type);
#if defined(CONFIG_DRM_AMD_SECURE_DISPLAY)
amdgpu_irq_get(
adev,
&adev->vline0_irq,
irq_type);
#endif
} else {
#if defined(CONFIG_DRM_AMD_SECURE_DISPLAY)
amdgpu_irq_put(
adev,
&adev->vline0_irq,
irq_type);
#endif
amdgpu_irq_put(
adev,
&adev->pageflip_irq,
irq_type);
drm_crtc_vblank_off(&acrtc->base);
}
}
@@ -8933,6 +8982,7 @@ static void amdgpu_dm_enable_self_refresh(struct amdgpu_crtc *acrtc_attach,
struct replay_settings *pr = &acrtc_state->stream->link->replay_settings;
struct amdgpu_dm_connector *aconn =
(struct amdgpu_dm_connector *)acrtc_state->stream->dm_stream_context;
bool vrr_active = amdgpu_dm_crtc_vrr_active(acrtc_state);
if (acrtc_state->update_type > UPDATE_TYPE_FAST) {
if (pr->config.replay_supported && !pr->replay_feature_enabled)
@@ -8959,14 +9009,15 @@ static void amdgpu_dm_enable_self_refresh(struct amdgpu_crtc *acrtc_attach,
* adequate number of fast atomic commits to notify KMD
* of update events. See `vblank_control_worker()`.
*/
if (acrtc_attach->dm_irq_params.allow_sr_entry &&
if (!vrr_active &&
acrtc_attach->dm_irq_params.allow_sr_entry &&
#ifdef CONFIG_DRM_AMD_SECURE_DISPLAY
!amdgpu_dm_crc_window_is_activated(acrtc_state->base.crtc) &&
#endif
(current_ts - psr->psr_dirty_rects_change_timestamp_ns) > 500000000) {
if (pr->replay_feature_enabled && !pr->replay_allow_active)
amdgpu_dm_replay_enable(acrtc_state->stream, true);
if (psr->psr_version >= DC_PSR_VERSION_SU_1 &&
if (psr->psr_version == DC_PSR_VERSION_SU_1 &&
!psr->psr_allow_active && !aconn->disallow_edp_enter_psr)
amdgpu_dm_psr_enable(acrtc_state->stream);
}
@@ -9137,7 +9188,7 @@ static void amdgpu_dm_commit_planes(struct drm_atomic_state *state,
acrtc_state->stream->link->psr_settings.psr_dirty_rects_change_timestamp_ns =
timestamp_ns;
if (acrtc_state->stream->link->psr_settings.psr_allow_active)
amdgpu_dm_psr_disable(acrtc_state->stream);
amdgpu_dm_psr_disable(acrtc_state->stream, true);
mutex_unlock(&dm->dc_lock);
}
}
@@ -9303,11 +9354,11 @@ static void amdgpu_dm_commit_planes(struct drm_atomic_state *state,
bundle->stream_update.abm_level = &acrtc_state->abm_level;
mutex_lock(&dm->dc_lock);
if (acrtc_state->update_type > UPDATE_TYPE_FAST) {
if ((acrtc_state->update_type > UPDATE_TYPE_FAST) || vrr_active) {
if (acrtc_state->stream->link->replay_settings.replay_allow_active)
amdgpu_dm_replay_disable(acrtc_state->stream);
if (acrtc_state->stream->link->psr_settings.psr_allow_active)
amdgpu_dm_psr_disable(acrtc_state->stream);
amdgpu_dm_psr_disable(acrtc_state->stream, true);
}
mutex_unlock(&dm->dc_lock);
@@ -10066,14 +10117,19 @@ static void amdgpu_dm_atomic_commit_tail(struct drm_atomic_state *state)
if (amdgpu_dm_is_valid_crc_source(cur_crc_src)) {
#if defined(CONFIG_DRM_AMD_SECURE_DISPLAY)
if (amdgpu_dm_crc_window_is_activated(crtc)) {
uint8_t cnt;
spin_lock_irqsave(&adev_to_drm(adev)->event_lock, flags);
acrtc->dm_irq_params.window_param.update_win = true;
for (cnt = 0; cnt < MAX_CRC_WINDOW_NUM; cnt++) {
if (acrtc->dm_irq_params.window_param[cnt].enable) {
acrtc->dm_irq_params.window_param[cnt].update_win = true;
/**
* It takes 2 frames for HW to stably generate CRC when
* resuming from suspend, so we set skip_frame_cnt 2.
*/
acrtc->dm_irq_params.window_param.skip_frame_cnt = 2;
/**
* It takes 2 frames for HW to stably generate CRC when
* resuming from suspend, so we set skip_frame_cnt 2.
*/
acrtc->dm_irq_params.window_param[cnt].skip_frame_cnt = 2;
}
}
spin_unlock_irqrestore(&adev_to_drm(adev)->event_lock, flags);
}
#endif
@@ -11161,8 +11217,8 @@ dm_get_plane_scale(struct drm_plane_state *plane_state,
int plane_src_w, plane_src_h;
dm_get_oriented_plane_size(plane_state, &plane_src_w, &plane_src_h);
*out_plane_scale_w = plane_state->crtc_w * 1000 / plane_src_w;
*out_plane_scale_h = plane_state->crtc_h * 1000 / plane_src_h;
*out_plane_scale_w = plane_src_w ? plane_state->crtc_w * 1000 / plane_src_w : 0;
*out_plane_scale_h = plane_src_h ? plane_state->crtc_h * 1000 / plane_src_h : 0;
}
/*
@@ -11416,6 +11472,25 @@ static int dm_crtc_get_cursor_mode(struct amdgpu_device *adev,
return 0;
}
static bool amdgpu_dm_crtc_mem_type_changed(struct drm_device *dev,
struct drm_atomic_state *state,
struct drm_crtc_state *crtc_state)
{
struct drm_plane *plane;
struct drm_plane_state *new_plane_state, *old_plane_state;
drm_for_each_plane_mask(plane, dev, crtc_state->plane_mask) {
new_plane_state = drm_atomic_get_plane_state(state, plane);
old_plane_state = drm_atomic_get_plane_state(state, plane);
if (old_plane_state->fb && new_plane_state->fb &&
get_mem_type(old_plane_state->fb) != get_mem_type(new_plane_state->fb))
return true;
}
return false;
}
/**
* amdgpu_dm_atomic_check() - Atomic check implementation for AMDgpu DM.
*
@@ -11613,10 +11688,6 @@ static int amdgpu_dm_atomic_check(struct drm_device *dev,
/* Remove exiting planes if they are modified */
for_each_oldnew_plane_in_descending_zpos(state, plane, old_plane_state, new_plane_state) {
if (old_plane_state->fb && new_plane_state->fb &&
get_mem_type(old_plane_state->fb) !=
get_mem_type(new_plane_state->fb))
lock_and_validation_needed = true;
ret = dm_update_plane_state(dc, state, plane,
old_plane_state,
@@ -11911,9 +11982,11 @@ static int amdgpu_dm_atomic_check(struct drm_device *dev,
/*
* Only allow async flips for fast updates that don't change
* the FB pitch, the DCC state, rotation, etc.
* the FB pitch, the DCC state, rotation, mem_type, etc.
*/
if (new_crtc_state->async_flip && lock_and_validation_needed) {
if (new_crtc_state->async_flip &&
(lock_and_validation_needed ||
amdgpu_dm_crtc_mem_type_changed(dev, state, new_crtc_state))) {
drm_dbg_atomic(crtc->dev,
"[CRTC:%d:%s] async flips are only supported for fast updates\n",
crtc->base.id, crtc->name);

View File

@@ -671,6 +671,8 @@ struct amdgpu_dm_connector {
uint32_t connector_id;
int bl_idx;
struct cec_notifier *notifier;
/* we need to mind the EDID between detect
and get modes due to analog/digital/tvencoder */
const struct drm_edid *drm_edid;
@@ -697,6 +699,8 @@ struct amdgpu_dm_connector {
struct drm_dp_mst_port *mst_output_port;
struct amdgpu_dm_connector *mst_root;
struct drm_dp_aux *dsc_aux;
uint32_t mst_local_bw;
uint16_t vc_full_pbn;
struct mutex handle_mst_msg_ready;
/* TODO see if we can merge with ddc_bus or make a dm_connector */
@@ -1010,4 +1014,8 @@ void dm_free_gpu_mem(struct amdgpu_device *adev,
bool amdgpu_dm_is_headless(struct amdgpu_device *adev);
void hdmi_cec_set_edid(struct amdgpu_dm_connector *aconnector);
void hdmi_cec_unset_edid(struct amdgpu_dm_connector *aconnector);
int amdgpu_dm_initialize_hdmi_connector(struct amdgpu_dm_connector *aconnector);
#endif /* __AMDGPU_DM_H__ */

View File

@@ -30,6 +30,7 @@
#include "amdgpu_dm.h"
#include "dc.h"
#include "amdgpu_securedisplay.h"
#include "amdgpu_dm_psr.h"
static const char *const pipe_crc_sources[] = {
"none",
@@ -295,33 +296,41 @@ static void amdgpu_dm_set_crc_window_default(struct drm_crtc *crtc, struct dc_st
struct drm_device *drm_dev = crtc->dev;
struct amdgpu_display_manager *dm = &drm_to_adev(drm_dev)->dm;
struct amdgpu_crtc *acrtc = to_amdgpu_crtc(crtc);
bool was_activated;
struct amdgpu_dm_connector *aconnector;
bool was_activated;
uint8_t phy_id;
unsigned long flags;
int i;
spin_lock_irq(&drm_dev->event_lock);
was_activated = acrtc->dm_irq_params.window_param.activated;
acrtc->dm_irq_params.window_param.x_start = 0;
acrtc->dm_irq_params.window_param.y_start = 0;
acrtc->dm_irq_params.window_param.x_end = 0;
acrtc->dm_irq_params.window_param.y_end = 0;
acrtc->dm_irq_params.window_param.activated = false;
acrtc->dm_irq_params.window_param.update_win = false;
acrtc->dm_irq_params.window_param.skip_frame_cnt = 0;
spin_unlock_irq(&drm_dev->event_lock);
spin_lock_irqsave(&drm_dev->event_lock, flags);
was_activated = acrtc->dm_irq_params.crc_window_activated;
for (i = 0; i < MAX_CRC_WINDOW_NUM; i++) {
acrtc->dm_irq_params.window_param[i].x_start = 0;
acrtc->dm_irq_params.window_param[i].y_start = 0;
acrtc->dm_irq_params.window_param[i].x_end = 0;
acrtc->dm_irq_params.window_param[i].y_end = 0;
acrtc->dm_irq_params.window_param[i].enable = false;
acrtc->dm_irq_params.window_param[i].update_win = false;
acrtc->dm_irq_params.window_param[i].skip_frame_cnt = 0;
}
acrtc->dm_irq_params.crc_window_activated = false;
spin_unlock_irqrestore(&drm_dev->event_lock, flags);
/* Disable secure_display if it was enabled */
if (was_activated) {
if (was_activated && dm->secure_display_ctx.op_mode == LEGACY_MODE) {
/* stop ROI update on this crtc */
flush_work(&dm->secure_display_ctx.crtc_ctx[crtc->index].notify_ta_work);
flush_work(&dm->secure_display_ctx.crtc_ctx[crtc->index].forward_roi_work);
aconnector = (struct amdgpu_dm_connector *)stream->dm_stream_context;
if (aconnector && get_phy_id(dm, aconnector, &phy_id))
dc_stream_forward_crc_window(stream, NULL, phy_id, true);
else
if (aconnector && get_phy_id(dm, aconnector, &phy_id)) {
if (dm->secure_display_ctx.support_mul_roi)
dc_stream_forward_multiple_crc_window(stream, NULL, phy_id, true);
else
dc_stream_forward_crc_window(stream, NULL, phy_id, true);
} else {
DRM_DEBUG_DRIVER("%s Can't find matching phy id", __func__);
}
}
}
@@ -335,7 +344,11 @@ static void amdgpu_dm_crtc_notify_ta_to_read(struct work_struct *work)
struct amdgpu_dm_connector *aconnector;
uint8_t phy_inst;
struct amdgpu_display_manager *dm;
struct crc_data crc_cpy[MAX_CRC_WINDOW_NUM];
unsigned long flags;
uint8_t roi_idx = 0;
int ret;
int i;
crtc_ctx = container_of(work, struct secure_display_crtc_context, notify_ta_work);
crtc = crtc_ctx->crtc;
@@ -364,18 +377,36 @@ static void amdgpu_dm_crtc_notify_ta_to_read(struct work_struct *work)
}
mutex_unlock(&crtc->dev->mode_config.mutex);
spin_lock_irqsave(&crtc->dev->event_lock, flags);
memcpy(crc_cpy, crtc_ctx->crc_info.crc, sizeof(struct crc_data) * MAX_CRC_WINDOW_NUM);
spin_unlock_irqrestore(&crtc->dev->event_lock, flags);
/* need lock for multiple crtcs to use the command buffer */
mutex_lock(&psp->securedisplay_context.mutex);
psp_prep_securedisplay_cmd_buf(psp, &securedisplay_cmd,
TA_SECUREDISPLAY_COMMAND__SEND_ROI_CRC);
securedisplay_cmd->securedisplay_in_message.send_roi_crc.phy_id = phy_inst;
/* PSP TA is expected to finish data transmission over I2C within current frame,
* even there are up to 4 crtcs request to send in this frame.
*/
ret = psp_securedisplay_invoke(psp, TA_SECUREDISPLAY_COMMAND__SEND_ROI_CRC);
if (dm->secure_display_ctx.support_mul_roi) {
psp_prep_securedisplay_cmd_buf(psp, &securedisplay_cmd,
TA_SECUREDISPLAY_COMMAND__SEND_ROI_CRC_V2);
securedisplay_cmd->securedisplay_in_message.send_roi_crc_v2.phy_id = phy_inst;
for (i = 0; i < MAX_CRC_WINDOW_NUM; i++) {
if (crc_cpy[i].crc_ready)
roi_idx |= 1 << i;
}
securedisplay_cmd->securedisplay_in_message.send_roi_crc_v2.roi_idx = roi_idx;
ret = psp_securedisplay_invoke(psp, TA_SECUREDISPLAY_COMMAND__SEND_ROI_CRC_V2);
} else {
psp_prep_securedisplay_cmd_buf(psp, &securedisplay_cmd,
TA_SECUREDISPLAY_COMMAND__SEND_ROI_CRC);
securedisplay_cmd->securedisplay_in_message.send_roi_crc.phy_id = phy_inst;
ret = psp_securedisplay_invoke(psp, TA_SECUREDISPLAY_COMMAND__SEND_ROI_CRC);
}
if (!ret) {
if (securedisplay_cmd->status != TA_SECUREDISPLAY_STATUS__SUCCESS)
@@ -393,6 +424,8 @@ amdgpu_dm_forward_crc_window(struct work_struct *work)
struct drm_crtc *crtc;
struct dc_stream_state *stream;
struct amdgpu_dm_connector *aconnector;
struct crc_window roi_cpy[MAX_CRC_WINDOW_NUM];
unsigned long flags;
uint8_t phy_id;
crtc_ctx = container_of(work, struct secure_display_crtc_context, forward_roi_work);
@@ -416,9 +449,17 @@ amdgpu_dm_forward_crc_window(struct work_struct *work)
}
mutex_unlock(&crtc->dev->mode_config.mutex);
spin_lock_irqsave(&crtc->dev->event_lock, flags);
memcpy(roi_cpy, crtc_ctx->roi, sizeof(struct crc_window) * MAX_CRC_WINDOW_NUM);
spin_unlock_irqrestore(&crtc->dev->event_lock, flags);
mutex_lock(&dm->dc_lock);
dc_stream_forward_crc_window(stream, &crtc_ctx->rect,
phy_id, false);
if (dm->secure_display_ctx.support_mul_roi)
dc_stream_forward_multiple_crc_window(stream, roi_cpy,
phy_id, false);
else
dc_stream_forward_crc_window(stream, &roi_cpy[0].rect,
phy_id, false);
mutex_unlock(&dm->dc_lock);
}
@@ -429,7 +470,7 @@ bool amdgpu_dm_crc_window_is_activated(struct drm_crtc *crtc)
bool ret = false;
spin_lock_irq(&drm_dev->event_lock);
ret = acrtc->dm_irq_params.window_param.activated;
ret = acrtc->dm_irq_params.crc_window_activated;
spin_unlock_irq(&drm_dev->event_lock);
return ret;
@@ -467,10 +508,14 @@ int amdgpu_dm_crtc_configure_crc_source(struct drm_crtc *crtc,
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);
/* Enable or disable CRTC CRC generation */
if (dm_is_crc_source_crtc(source) || source == AMDGPU_DM_PIPE_CRC_SOURCE_NONE) {
if (!dc_stream_configure_crc(stream_state->ctx->dc,
stream_state, NULL, enable, enable)) {
stream_state, NULL, enable, enable, 0, true)) {
ret = -EINVAL;
goto unlock;
}
@@ -604,6 +649,17 @@ int amdgpu_dm_crtc_set_crc_source(struct drm_crtc *crtc, const char *src_name)
}
/*
* Reading the CRC requires the vblank interrupt handler to be
* enabled. Keep a reference until CRC capture stops.
*/
enabled = amdgpu_dm_is_valid_crc_source(cur_crc_src);
if (!enabled && enable) {
ret = drm_crtc_vblank_get(crtc);
if (ret)
goto cleanup;
}
#if defined(CONFIG_DRM_AMD_SECURE_DISPLAY)
/* Reset secure_display when we change crc source from debugfs */
amdgpu_dm_set_crc_window_default(crtc, crtc_state->stream);
@@ -614,16 +670,7 @@ int amdgpu_dm_crtc_set_crc_source(struct drm_crtc *crtc, const char *src_name)
goto cleanup;
}
/*
* Reading the CRC requires the vblank interrupt handler to be
* enabled. Keep a reference until CRC capture stops.
*/
enabled = amdgpu_dm_is_valid_crc_source(cur_crc_src);
if (!enabled && enable) {
ret = drm_crtc_vblank_get(crtc);
if (ret)
goto cleanup;
if (dm_is_crc_source_dprx(source)) {
if (drm_dp_start_crc(aux, crtc)) {
DRM_DEBUG_DRIVER("dp start crc failed\n");
@@ -651,7 +698,8 @@ int amdgpu_dm_crtc_set_crc_source(struct drm_crtc *crtc, const char *src_name)
#if defined(CONFIG_DRM_AMD_SECURE_DISPLAY)
/* Initialize phy id mapping table for secure display*/
if (!dm->secure_display_ctx.phy_mapping_updated)
if (dm->secure_display_ctx.op_mode == LEGACY_MODE &&
!dm->secure_display_ctx.phy_mapping_updated)
update_phy_id_mapping(adev);
#endif
@@ -709,7 +757,7 @@ void amdgpu_dm_crtc_handle_crc_irq(struct drm_crtc *crtc)
}
if (dm_is_crc_source_crtc(cur_crc_src)) {
if (!dc_stream_get_crc(stream_state->ctx->dc, stream_state,
if (!dc_stream_get_crc(stream_state->ctx->dc, stream_state, 0,
&crcs[0], &crcs[1], &crcs[2]))
return;
@@ -726,7 +774,16 @@ void amdgpu_dm_crtc_handle_crc_window_irq(struct drm_crtc *crtc)
struct amdgpu_crtc *acrtc = NULL;
struct amdgpu_device *adev = NULL;
struct secure_display_crtc_context *crtc_ctx = NULL;
bool reset_crc_frame_count[MAX_CRC_WINDOW_NUM] = {false};
uint32_t crc_r[MAX_CRC_WINDOW_NUM] = {0};
uint32_t crc_g[MAX_CRC_WINDOW_NUM] = {0};
uint32_t crc_b[MAX_CRC_WINDOW_NUM] = {0};
unsigned long flags1;
bool forward_roi_change = false;
bool notify_ta = false;
bool all_crc_ready = true;
struct dc_stream_state *stream_state;
int i;
if (crtc == NULL)
return;
@@ -734,21 +791,21 @@ void amdgpu_dm_crtc_handle_crc_window_irq(struct drm_crtc *crtc)
acrtc = to_amdgpu_crtc(crtc);
adev = drm_to_adev(crtc->dev);
drm_dev = crtc->dev;
stream_state = to_dm_crtc_state(crtc->state)->stream;
spin_lock_irqsave(&drm_dev->event_lock, flags1);
cur_crc_src = acrtc->dm_irq_params.crc_src;
/* Early return if CRC capture is not enabled. */
if (!amdgpu_dm_is_valid_crc_source(cur_crc_src) ||
!dm_is_crc_source_crtc(cur_crc_src))
goto cleanup;
!dm_is_crc_source_crtc(cur_crc_src)) {
spin_unlock_irqrestore(&drm_dev->event_lock, flags1);
return;
}
if (!acrtc->dm_irq_params.window_param.activated)
goto cleanup;
if (acrtc->dm_irq_params.window_param.skip_frame_cnt) {
acrtc->dm_irq_params.window_param.skip_frame_cnt -= 1;
goto cleanup;
if (!acrtc->dm_irq_params.crc_window_activated) {
spin_unlock_irqrestore(&drm_dev->event_lock, flags1);
return;
}
crtc_ctx = &adev->dm.secure_display_ctx.crtc_ctx[acrtc->crtc_id];
@@ -759,32 +816,110 @@ void amdgpu_dm_crtc_handle_crc_window_irq(struct drm_crtc *crtc)
crtc_ctx->crtc = crtc;
}
if (acrtc->dm_irq_params.window_param.update_win) {
/* prepare work for dmub to update ROI */
crtc_ctx->rect.x = acrtc->dm_irq_params.window_param.x_start;
crtc_ctx->rect.y = acrtc->dm_irq_params.window_param.y_start;
crtc_ctx->rect.width = acrtc->dm_irq_params.window_param.x_end -
acrtc->dm_irq_params.window_param.x_start;
crtc_ctx->rect.height = acrtc->dm_irq_params.window_param.y_end -
acrtc->dm_irq_params.window_param.y_start;
schedule_work(&crtc_ctx->forward_roi_work);
for (i = 0; i < MAX_CRC_WINDOW_NUM; i++) {
struct crc_params crc_window = {
.windowa_x_start = acrtc->dm_irq_params.window_param[i].x_start,
.windowa_y_start = acrtc->dm_irq_params.window_param[i].y_start,
.windowa_x_end = acrtc->dm_irq_params.window_param[i].x_end,
.windowa_y_end = acrtc->dm_irq_params.window_param[i].y_end,
.windowb_x_start = acrtc->dm_irq_params.window_param[i].x_start,
.windowb_y_start = acrtc->dm_irq_params.window_param[i].y_start,
.windowb_x_end = acrtc->dm_irq_params.window_param[i].x_end,
.windowb_y_end = acrtc->dm_irq_params.window_param[i].y_end,
};
acrtc->dm_irq_params.window_param.update_win = false;
crtc_ctx->roi[i].enable = acrtc->dm_irq_params.window_param[i].enable;
/* Statically skip 1 frame, because we may need to wait below things
* before sending ROI to dmub:
* 1. We defer the work by using system workqueue.
* 2. We may need to wait for dc_lock before accessing dmub.
*/
acrtc->dm_irq_params.window_param.skip_frame_cnt = 1;
if (!acrtc->dm_irq_params.window_param[i].enable) {
crtc_ctx->crc_info.crc[i].crc_ready = false;
continue;
}
} else {
/* prepare work for psp to read ROI/CRC and send to I2C */
schedule_work(&crtc_ctx->notify_ta_work);
if (acrtc->dm_irq_params.window_param[i].skip_frame_cnt) {
acrtc->dm_irq_params.window_param[i].skip_frame_cnt -= 1;
crtc_ctx->crc_info.crc[i].crc_ready = false;
continue;
}
if (acrtc->dm_irq_params.window_param[i].update_win) {
crtc_ctx->roi[i].rect.x = crc_window.windowa_x_start;
crtc_ctx->roi[i].rect.y = crc_window.windowa_y_start;
crtc_ctx->roi[i].rect.width = crc_window.windowa_x_end -
crc_window.windowa_x_start;
crtc_ctx->roi[i].rect.height = crc_window.windowa_y_end -
crc_window.windowa_y_start;
if (adev->dm.secure_display_ctx.op_mode == LEGACY_MODE)
/* forward task to dmub to update ROI */
forward_roi_change = true;
else if (adev->dm.secure_display_ctx.op_mode == DISPLAY_CRC_MODE)
/* update ROI via dm*/
dc_stream_configure_crc(stream_state->ctx->dc, stream_state,
&crc_window, true, true, i, false);
reset_crc_frame_count[i] = true;
acrtc->dm_irq_params.window_param[i].update_win = false;
/* Statically skip 1 frame, because we may need to wait below things
* before sending ROI to dmub:
* 1. We defer the work by using system workqueue.
* 2. We may need to wait for dc_lock before accessing dmub.
*/
acrtc->dm_irq_params.window_param[i].skip_frame_cnt = 1;
crtc_ctx->crc_info.crc[i].crc_ready = false;
} else {
if (!dc_stream_get_crc(stream_state->ctx->dc, stream_state, i,
&crc_r[i], &crc_g[i], &crc_b[i]))
DRM_ERROR("Secure Display: fail to get crc from engine %d\n", i);
if (adev->dm.secure_display_ctx.op_mode == LEGACY_MODE)
/* forward task to psp to read ROI/CRC and output via I2C */
notify_ta = true;
else if (adev->dm.secure_display_ctx.op_mode == DISPLAY_CRC_MODE)
/* Avoid ROI window get changed, keep overwriting. */
dc_stream_configure_crc(stream_state->ctx->dc, stream_state,
&crc_window, true, true, i, false);
/* crc ready for psp to read out */
crtc_ctx->crc_info.crc[i].crc_ready = true;
}
}
cleanup:
spin_unlock_irqrestore(&drm_dev->event_lock, flags1);
if (forward_roi_change)
schedule_work(&crtc_ctx->forward_roi_work);
if (notify_ta)
schedule_work(&crtc_ctx->notify_ta_work);
spin_lock_irqsave(&crtc_ctx->crc_info.lock, flags1);
for (i = 0; i < MAX_CRC_WINDOW_NUM; i++) {
crtc_ctx->crc_info.crc[i].crc_R = crc_r[i];
crtc_ctx->crc_info.crc[i].crc_G = crc_g[i];
crtc_ctx->crc_info.crc[i].crc_B = crc_b[i];
if (!crtc_ctx->roi[i].enable) {
crtc_ctx->crc_info.crc[i].frame_count = 0;
continue;
}
if (!crtc_ctx->crc_info.crc[i].crc_ready)
all_crc_ready = false;
if (reset_crc_frame_count[i] || crtc_ctx->crc_info.crc[i].frame_count == UINT_MAX)
/* Reset the reference frame count after user update the ROI
* or it reaches the maximum value.
*/
crtc_ctx->crc_info.crc[i].frame_count = 0;
else
crtc_ctx->crc_info.crc[i].frame_count += 1;
}
spin_unlock_irqrestore(&crtc_ctx->crc_info.lock, flags1);
if (all_crc_ready)
complete_all(&crtc_ctx->crc_info.completion);
}
void amdgpu_dm_crtc_secure_display_create_contexts(struct amdgpu_device *adev)
@@ -805,9 +940,11 @@ void amdgpu_dm_crtc_secure_display_create_contexts(struct amdgpu_device *adev)
INIT_WORK(&crtc_ctx[i].forward_roi_work, amdgpu_dm_forward_crc_window);
INIT_WORK(&crtc_ctx[i].notify_ta_work, amdgpu_dm_crtc_notify_ta_to_read);
crtc_ctx[i].crtc = &adev->mode_info.crtcs[i]->base;
spin_lock_init(&crtc_ctx[i].crc_info.lock);
}
adev->dm.secure_display_ctx.crtc_ctx = crtc_ctx;
return;
adev->dm.secure_display_ctx.op_mode = DISPLAY_CRC_MODE;
}
#endif

View File

@@ -42,6 +42,14 @@ enum amdgpu_dm_pipe_crc_source {
#ifdef CONFIG_DRM_AMD_SECURE_DISPLAY
#define MAX_CRTC 6
enum secure_display_mode {
/* via dmub + psp */
LEGACY_MODE = 0,
/* driver directly */
DISPLAY_CRC_MODE,
SECURE_DISPLAY_MODE_MAX,
};
struct phy_id_mapping {
bool assigned;
bool is_mst;
@@ -51,13 +59,27 @@ struct phy_id_mapping {
u8 rad[8];
};
struct crc_data {
uint32_t crc_R;
uint32_t crc_G;
uint32_t crc_B;
uint32_t frame_count;
bool crc_ready;
};
struct crc_info {
struct crc_data crc[MAX_CRC_WINDOW_NUM];
struct completion completion;
spinlock_t lock;
};
struct crc_window_param {
uint16_t x_start;
uint16_t y_start;
uint16_t x_end;
uint16_t y_end;
/* CRC window is activated or not*/
bool activated;
bool enable;
/* Update crc window during vertical blank or not */
bool update_win;
/* skip reading/writing for few frames */
@@ -74,13 +96,17 @@ struct secure_display_crtc_context {
struct drm_crtc *crtc;
/* Region of Interest (ROI) */
struct rect rect;
struct crc_window roi[MAX_CRC_WINDOW_NUM];
struct crc_info crc_info;
};
struct secure_display_context {
struct secure_display_crtc_context *crtc_ctx;
/* Whether dmub support multiple ROI setting */
bool support_mul_roi;
enum secure_display_mode op_mode;
bool phy_mapping_updated;
int phy_id_mapping_cnt;
struct phy_id_mapping phy_id_mapping[MAX_CRTC];

View File

@@ -93,7 +93,7 @@ int amdgpu_dm_crtc_set_vupdate_irq(struct drm_crtc *crtc, bool enable)
return rc;
}
bool amdgpu_dm_crtc_vrr_active(struct dm_crtc_state *dm_state)
bool amdgpu_dm_crtc_vrr_active(const struct dm_crtc_state *dm_state)
{
return dm_state->freesync_config.state == VRR_STATE_ACTIVE_VARIABLE ||
dm_state->freesync_config.state == VRR_STATE_ACTIVE_FIXED;
@@ -142,7 +142,7 @@ static void amdgpu_dm_crtc_set_panel_sr_feature(
amdgpu_dm_replay_enable(vblank_work->stream, true);
} else if (vblank_enabled) {
if (link->psr_settings.psr_version < DC_PSR_VERSION_SU_1 && is_sr_active)
amdgpu_dm_psr_disable(vblank_work->stream);
amdgpu_dm_psr_disable(vblank_work->stream, false);
} else if (link->psr_settings.psr_feature_enabled &&
allow_sr_entry && !is_sr_active && !is_crc_window_active) {

View File

@@ -37,7 +37,7 @@ int amdgpu_dm_crtc_set_vupdate_irq(struct drm_crtc *crtc, bool enable);
bool amdgpu_dm_crtc_vrr_active_irq(struct amdgpu_crtc *acrtc);
bool amdgpu_dm_crtc_vrr_active(struct dm_crtc_state *dm_state);
bool amdgpu_dm_crtc_vrr_active(const struct dm_crtc_state *dm_state);
int amdgpu_dm_crtc_enable_vblank(struct drm_crtc *crtc);

View File

@@ -25,6 +25,7 @@
#include <linux/string_helpers.h>
#include <linux/uaccess.h>
#include <media/cec-notifier.h>
#include "dc.h"
#include "amdgpu.h"
@@ -2848,6 +2849,67 @@ static int is_dpia_link_show(struct seq_file *m, void *data)
return 0;
}
/**
* hdmi_cec_state_show - Read out the HDMI-CEC feature status
* @m: sequence file.
* @data: unused.
*
* Return 0 on success
*/
static int hdmi_cec_state_show(struct seq_file *m, void *data)
{
struct drm_connector *connector = m->private;
struct amdgpu_dm_connector *aconnector = to_amdgpu_dm_connector(connector);
seq_printf(m, "%s:%d\n", connector->name, connector->base.id);
seq_printf(m, "HDMI-CEC status: %d\n", aconnector->notifier ? 1 : 0);
return 0;
}
/**
* hdmi_cec_state_write - Enable/Disable HDMI-CEC feature from driver side
* @f: file structure.
* @buf: userspace buffer. set to '1' to enable; '0' to disable cec feature.
* @size: size of buffer from userpsace.
* @pos: unused.
*
* Return size on success, error code on failure
*/
static ssize_t hdmi_cec_state_write(struct file *f, const char __user *buf,
size_t size, loff_t *pos)
{
int ret;
bool enable;
struct amdgpu_dm_connector *aconnector = file_inode(f)->i_private;
struct drm_device *ddev = aconnector->base.dev;
if (size == 0)
return -EINVAL;
ret = kstrtobool_from_user(buf, size, &enable);
if (ret) {
drm_dbg_driver(ddev, "invalid user data !\n");
return ret;
}
if (enable) {
if (aconnector->notifier)
return -EINVAL;
ret = amdgpu_dm_initialize_hdmi_connector(aconnector);
if (ret)
return ret;
hdmi_cec_set_edid(aconnector);
} else {
if (!aconnector->notifier)
return -EINVAL;
cec_notifier_conn_unregister(aconnector->notifier);
aconnector->notifier = NULL;
}
return size;
}
DEFINE_SHOW_ATTRIBUTE(dp_dsc_fec_support);
DEFINE_SHOW_ATTRIBUTE(dmub_fw_state);
DEFINE_SHOW_ATTRIBUTE(dmub_tracebuffer);
@@ -2860,6 +2922,7 @@ DEFINE_SHOW_ATTRIBUTE(psr_capability);
DEFINE_SHOW_ATTRIBUTE(dp_is_mst_connector);
DEFINE_SHOW_ATTRIBUTE(dp_mst_progress_status);
DEFINE_SHOW_ATTRIBUTE(is_dpia_link);
DEFINE_SHOW_STORE_ATTRIBUTE(hdmi_cec_state);
static const struct file_operations dp_dsc_clock_en_debugfs_fops = {
.owner = THIS_MODULE,
@@ -2995,7 +3058,8 @@ static const struct {
char *name;
const struct file_operations *fops;
} hdmi_debugfs_entries[] = {
{"hdcp_sink_capability", &hdcp_sink_capability_fops}
{"hdcp_sink_capability", &hdcp_sink_capability_fops},
{"hdmi_cec_state", &hdmi_cec_state_fops}
};
/*
@@ -3480,8 +3544,8 @@ static int crc_win_x_start_set(void *data, u64 val)
struct amdgpu_crtc *acrtc = to_amdgpu_crtc(crtc);
spin_lock_irq(&drm_dev->event_lock);
acrtc->dm_irq_params.window_param.x_start = (uint16_t) val;
acrtc->dm_irq_params.window_param.update_win = false;
acrtc->dm_irq_params.window_param[0].x_start = (uint16_t) val;
acrtc->dm_irq_params.window_param[0].update_win = false;
spin_unlock_irq(&drm_dev->event_lock);
return 0;
@@ -3497,7 +3561,7 @@ static int crc_win_x_start_get(void *data, u64 *val)
struct amdgpu_crtc *acrtc = to_amdgpu_crtc(crtc);
spin_lock_irq(&drm_dev->event_lock);
*val = acrtc->dm_irq_params.window_param.x_start;
*val = acrtc->dm_irq_params.window_param[0].x_start;
spin_unlock_irq(&drm_dev->event_lock);
return 0;
@@ -3517,8 +3581,8 @@ static int crc_win_y_start_set(void *data, u64 val)
struct amdgpu_crtc *acrtc = to_amdgpu_crtc(crtc);
spin_lock_irq(&drm_dev->event_lock);
acrtc->dm_irq_params.window_param.y_start = (uint16_t) val;
acrtc->dm_irq_params.window_param.update_win = false;
acrtc->dm_irq_params.window_param[0].y_start = (uint16_t) val;
acrtc->dm_irq_params.window_param[0].update_win = false;
spin_unlock_irq(&drm_dev->event_lock);
return 0;
@@ -3534,7 +3598,7 @@ static int crc_win_y_start_get(void *data, u64 *val)
struct amdgpu_crtc *acrtc = to_amdgpu_crtc(crtc);
spin_lock_irq(&drm_dev->event_lock);
*val = acrtc->dm_irq_params.window_param.y_start;
*val = acrtc->dm_irq_params.window_param[0].y_start;
spin_unlock_irq(&drm_dev->event_lock);
return 0;
@@ -3553,8 +3617,8 @@ static int crc_win_x_end_set(void *data, u64 val)
struct amdgpu_crtc *acrtc = to_amdgpu_crtc(crtc);
spin_lock_irq(&drm_dev->event_lock);
acrtc->dm_irq_params.window_param.x_end = (uint16_t) val;
acrtc->dm_irq_params.window_param.update_win = false;
acrtc->dm_irq_params.window_param[0].x_end = (uint16_t) val;
acrtc->dm_irq_params.window_param[0].update_win = false;
spin_unlock_irq(&drm_dev->event_lock);
return 0;
@@ -3570,7 +3634,7 @@ static int crc_win_x_end_get(void *data, u64 *val)
struct amdgpu_crtc *acrtc = to_amdgpu_crtc(crtc);
spin_lock_irq(&drm_dev->event_lock);
*val = acrtc->dm_irq_params.window_param.x_end;
*val = acrtc->dm_irq_params.window_param[0].x_end;
spin_unlock_irq(&drm_dev->event_lock);
return 0;
@@ -3589,8 +3653,8 @@ static int crc_win_y_end_set(void *data, u64 val)
struct amdgpu_crtc *acrtc = to_amdgpu_crtc(crtc);
spin_lock_irq(&drm_dev->event_lock);
acrtc->dm_irq_params.window_param.y_end = (uint16_t) val;
acrtc->dm_irq_params.window_param.update_win = false;
acrtc->dm_irq_params.window_param[0].y_end = (uint16_t) val;
acrtc->dm_irq_params.window_param[0].update_win = false;
spin_unlock_irq(&drm_dev->event_lock);
return 0;
@@ -3606,7 +3670,7 @@ static int crc_win_y_end_get(void *data, u64 *val)
struct amdgpu_crtc *acrtc = to_amdgpu_crtc(crtc);
spin_lock_irq(&drm_dev->event_lock);
*val = acrtc->dm_irq_params.window_param.y_end;
*val = acrtc->dm_irq_params.window_param[0].y_end;
spin_unlock_irq(&drm_dev->event_lock);
return 0;
@@ -3629,13 +3693,14 @@ static int crc_win_update_set(void *data, u64 val)
/* PSR may write to OTG CRC window control register,
* so close it before starting secure_display.
*/
amdgpu_dm_psr_disable(acrtc->dm_irq_params.stream);
amdgpu_dm_psr_disable(acrtc->dm_irq_params.stream, true);
spin_lock_irq(&adev_to_drm(adev)->event_lock);
acrtc->dm_irq_params.window_param.activated = true;
acrtc->dm_irq_params.window_param.update_win = true;
acrtc->dm_irq_params.window_param.skip_frame_cnt = 0;
acrtc->dm_irq_params.window_param[0].enable = true;
acrtc->dm_irq_params.window_param[0].update_win = true;
acrtc->dm_irq_params.window_param[0].skip_frame_cnt = 0;
acrtc->dm_irq_params.crc_window_activated = true;
spin_unlock_irq(&adev_to_drm(adev)->event_lock);
mutex_unlock(&adev->dm.dc_lock);

View File

@@ -885,6 +885,12 @@ bool dm_helpers_dp_write_dsc_enable(
return ret;
}
bool dm_helpers_dp_write_hblank_reduction(struct dc_context *ctx, const struct dc_stream_state *stream)
{
// TODO
return false;
}
bool dm_helpers_is_dp_sink_present(struct dc_link *link)
{
bool dp_sink_present;

View File

@@ -39,7 +39,9 @@ struct dm_irq_params {
#ifdef CONFIG_DEBUG_FS
enum amdgpu_dm_pipe_crc_source crc_src;
#ifdef CONFIG_DRM_AMD_SECURE_DISPLAY
struct crc_window_param window_param;
struct crc_window_param window_param[MAX_CRC_WINDOW_NUM];
/* At least one CRC window is activated or not*/
bool crc_window_activated;
#endif
#endif
};

View File

@@ -155,6 +155,17 @@ amdgpu_dm_mst_connector_late_register(struct drm_connector *connector)
return 0;
}
static inline void
amdgpu_dm_mst_reset_mst_connector_setting(struct amdgpu_dm_connector *aconnector)
{
aconnector->drm_edid = NULL;
aconnector->dsc_aux = NULL;
aconnector->mst_output_port->passthrough_aux = NULL;
aconnector->mst_local_bw = 0;
aconnector->vc_full_pbn = 0;
}
static void
amdgpu_dm_mst_connector_early_unregister(struct drm_connector *connector)
{
@@ -182,9 +193,7 @@ amdgpu_dm_mst_connector_early_unregister(struct drm_connector *connector)
dc_sink_release(dc_sink);
aconnector->dc_sink = NULL;
aconnector->drm_edid = NULL;
aconnector->dsc_aux = NULL;
port->passthrough_aux = NULL;
amdgpu_dm_mst_reset_mst_connector_setting(aconnector);
}
aconnector->mst_status = MST_STATUS_DEFAULT;
@@ -504,9 +513,7 @@ dm_dp_mst_detect(struct drm_connector *connector,
dc_sink_release(aconnector->dc_sink);
aconnector->dc_sink = NULL;
aconnector->drm_edid = NULL;
aconnector->dsc_aux = NULL;
port->passthrough_aux = NULL;
amdgpu_dm_mst_reset_mst_connector_setting(aconnector);
amdgpu_dm_set_mst_status(&aconnector->mst_status,
MST_REMOTE_EDID | MST_ALLOCATE_NEW_PAYLOAD | MST_CLEAR_ALLOCATED_PAYLOAD,
@@ -1820,9 +1827,18 @@ enum dc_status dm_dp_mst_is_port_support_mode(
struct drm_dp_mst_port *immediate_upstream_port = NULL;
uint32_t end_link_bw = 0;
/*Get last DP link BW capability*/
if (dp_get_link_current_set_bw(&aconnector->mst_output_port->aux, &end_link_bw)) {
if (stream_kbps > end_link_bw) {
/*Get last DP link BW capability. Mode shall be supported by Legacy peer*/
if (aconnector->mst_output_port->pdt != DP_PEER_DEVICE_DP_LEGACY_CONV &&
aconnector->mst_output_port->pdt != DP_PEER_DEVICE_NONE) {
if (aconnector->vc_full_pbn != aconnector->mst_output_port->full_pbn) {
dp_get_link_current_set_bw(&aconnector->mst_output_port->aux, &end_link_bw);
aconnector->vc_full_pbn = aconnector->mst_output_port->full_pbn;
aconnector->mst_local_bw = end_link_bw;
} else {
end_link_bw = aconnector->mst_local_bw;
}
if (end_link_bw > 0 && stream_kbps > end_link_bw) {
DRM_DEBUG_DRIVER("MST_DSC dsc decode at last link."
"Mode required bw can't fit into last link\n");
return DC_FAIL_BANDWIDTH_VALIDATE;
@@ -1836,11 +1852,15 @@ enum dc_status dm_dp_mst_is_port_support_mode(
if (immediate_upstream_port) {
virtual_channel_bw_in_kbps = kbps_from_pbn(immediate_upstream_port->full_pbn);
virtual_channel_bw_in_kbps = min(root_link_bw_in_kbps, virtual_channel_bw_in_kbps);
if (bw_range.min_kbps > virtual_channel_bw_in_kbps) {
DRM_DEBUG_DRIVER("MST_DSC dsc decode at last link."
"Max dsc compression can't fit into MST available bw\n");
return DC_FAIL_BANDWIDTH_VALIDATE;
}
} else {
/* For topology LCT 1 case - only one mstb*/
virtual_channel_bw_in_kbps = root_link_bw_in_kbps;
}
if (bw_range.min_kbps > virtual_channel_bw_in_kbps) {
DRM_DEBUG_DRIVER("MST_DSC dsc decode at last link."
"Max dsc compression can't fit into MST available bw\n");
return DC_FAIL_BANDWIDTH_VALIDATE;
}
}

View File

@@ -177,7 +177,7 @@ static unsigned int amdgpu_dm_plane_modifier_gfx9_swizzle_mode(uint64_t modifier
return AMD_FMT_MOD_GET(TILE, modifier);
}
static void amdgpu_dm_plane_fill_gfx8_tiling_info_from_flags(union dc_tiling_info *tiling_info,
static void amdgpu_dm_plane_fill_gfx8_tiling_info_from_flags(struct dc_tiling_info *tiling_info,
uint64_t tiling_flags)
{
/* Fill GFX8 params */
@@ -190,6 +190,7 @@ static void amdgpu_dm_plane_fill_gfx8_tiling_info_from_flags(union dc_tiling_inf
tile_split = AMDGPU_TILING_GET(tiling_flags, TILE_SPLIT);
num_banks = AMDGPU_TILING_GET(tiling_flags, NUM_BANKS);
tiling_info->gfxversion = DcGfxVersion8;
/* XXX fix me for VI */
tiling_info->gfx8.num_banks = num_banks;
tiling_info->gfx8.array_mode =
@@ -210,7 +211,7 @@ static void amdgpu_dm_plane_fill_gfx8_tiling_info_from_flags(union dc_tiling_inf
}
static void amdgpu_dm_plane_fill_gfx9_tiling_info_from_device(const struct amdgpu_device *adev,
union dc_tiling_info *tiling_info)
struct dc_tiling_info *tiling_info)
{
/* Fill GFX9 params */
tiling_info->gfx9.num_pipes =
@@ -231,7 +232,7 @@ static void amdgpu_dm_plane_fill_gfx9_tiling_info_from_device(const struct amdgp
}
static void amdgpu_dm_plane_fill_gfx9_tiling_info_from_modifier(const struct amdgpu_device *adev,
union dc_tiling_info *tiling_info,
struct dc_tiling_info *tiling_info,
uint64_t modifier)
{
unsigned int mod_bank_xor_bits = AMD_FMT_MOD_GET(BANK_XOR_BITS, modifier);
@@ -261,7 +262,7 @@ static void amdgpu_dm_plane_fill_gfx9_tiling_info_from_modifier(const struct amd
static int amdgpu_dm_plane_validate_dcc(struct amdgpu_device *adev,
const enum surface_pixel_format format,
const enum dc_rotation_angle rotation,
const union dc_tiling_info *tiling_info,
const struct dc_tiling_info *tiling_info,
const struct dc_plane_dcc_param *dcc,
const struct dc_plane_address *address,
const struct plane_size *plane_size)
@@ -308,7 +309,7 @@ static int amdgpu_dm_plane_fill_gfx9_plane_attributes_from_modifiers(struct amdg
const enum surface_pixel_format format,
const enum dc_rotation_angle rotation,
const struct plane_size *plane_size,
union dc_tiling_info *tiling_info,
struct dc_tiling_info *tiling_info,
struct dc_plane_dcc_param *dcc,
struct dc_plane_address *address)
{
@@ -317,6 +318,7 @@ static int amdgpu_dm_plane_fill_gfx9_plane_attributes_from_modifiers(struct amdg
amdgpu_dm_plane_fill_gfx9_tiling_info_from_modifier(adev, tiling_info, modifier);
tiling_info->gfx9.swizzle = amdgpu_dm_plane_modifier_gfx9_swizzle_mode(modifier);
tiling_info->gfxversion = DcGfxVersion9;
if (amdgpu_dm_plane_modifier_has_dcc(modifier)) {
uint64_t dcc_address = afb->address + afb->base.offsets[1];
@@ -358,7 +360,7 @@ static int amdgpu_dm_plane_fill_gfx12_plane_attributes_from_modifiers(struct amd
const enum surface_pixel_format format,
const enum dc_rotation_angle rotation,
const struct plane_size *plane_size,
union dc_tiling_info *tiling_info,
struct dc_tiling_info *tiling_info,
struct dc_plane_dcc_param *dcc,
struct dc_plane_address *address)
{
@@ -369,6 +371,7 @@ static int amdgpu_dm_plane_fill_gfx12_plane_attributes_from_modifiers(struct amd
amdgpu_dm_plane_fill_gfx9_tiling_info_from_device(adev, tiling_info);
tiling_info->gfx9.swizzle = amdgpu_dm_plane_modifier_gfx9_swizzle_mode(modifier);
tiling_info->gfxversion = DcGfxAddr3;
if (amdgpu_dm_plane_modifier_has_dcc(modifier)) {
int max_compressed_block = AMD_FMT_MOD_GET(DCC_MAX_COMPRESSED_BLOCK, modifier);
@@ -834,7 +837,7 @@ int amdgpu_dm_plane_fill_plane_buffer_attributes(struct amdgpu_device *adev,
const enum surface_pixel_format format,
const enum dc_rotation_angle rotation,
const uint64_t tiling_flags,
union dc_tiling_info *tiling_info,
struct dc_tiling_info *tiling_info,
struct plane_size *plane_size,
struct dc_plane_dcc_param *dcc,
struct dc_plane_address *address,

View File

@@ -47,7 +47,7 @@ int amdgpu_dm_plane_fill_plane_buffer_attributes(struct amdgpu_device *adev,
const enum surface_pixel_format format,
const enum dc_rotation_angle rotation,
const uint64_t tiling_flags,
union dc_tiling_info *tiling_info,
struct dc_tiling_info *tiling_info,
struct plane_size *plane_size,
struct dc_plane_dcc_param *dcc,
struct dc_plane_address *address,

View File

@@ -201,14 +201,13 @@ void amdgpu_dm_psr_enable(struct dc_stream_state *stream)
*
* Return: true if success
*/
bool amdgpu_dm_psr_disable(struct dc_stream_state *stream)
bool amdgpu_dm_psr_disable(struct dc_stream_state *stream, bool wait)
{
unsigned int power_opt = 0;
bool psr_enable = false;
DRM_DEBUG_DRIVER("Disabling psr...\n");
return dc_link_set_psr_allow_active(stream->link, &psr_enable, true, false, &power_opt);
return dc_link_set_psr_allow_active(stream->link, &psr_enable, wait, false, NULL);
}
/*
@@ -251,3 +250,33 @@ bool amdgpu_dm_psr_is_active_allowed(struct amdgpu_display_manager *dm)
return allow_active;
}
/**
* amdgpu_dm_psr_wait_disable() - Wait for eDP panel to exit PSR
* @stream: stream state attached to the eDP link
*
* Waits for a max of 500ms for the eDP panel to exit PSR.
*
* Return: true if panel exited PSR, false otherwise.
*/
bool amdgpu_dm_psr_wait_disable(struct dc_stream_state *stream)
{
enum dc_psr_state psr_state = PSR_STATE0;
struct dc_link *link = stream->link;
int retry_count;
if (link == NULL)
return false;
for (retry_count = 0; retry_count <= 1000; retry_count++) {
dc_link_get_psr_state(link, &psr_state);
if (psr_state == PSR_STATE0)
break;
udelay(500);
}
if (retry_count == 1000)
return false;
return true;
}

View File

@@ -34,8 +34,9 @@
void amdgpu_dm_set_psr_caps(struct dc_link *link);
void amdgpu_dm_psr_enable(struct dc_stream_state *stream);
bool amdgpu_dm_link_setup_psr(struct dc_stream_state *stream);
bool amdgpu_dm_psr_disable(struct dc_stream_state *stream);
bool amdgpu_dm_psr_disable(struct dc_stream_state *stream, bool wait);
bool amdgpu_dm_psr_disable_all(struct amdgpu_display_manager *dm);
bool amdgpu_dm_psr_is_active_allowed(struct amdgpu_display_manager *dm);
bool amdgpu_dm_psr_wait_disable(struct dc_stream_state *stream);
#endif /* AMDGPU_DM_AMDGPU_DM_PSR_H_ */

View File

@@ -3088,11 +3088,12 @@ static enum bp_result construct_integrated_info(
info->ext_disp_conn_info.path[i].ext_encoder_obj_id.id,
info->ext_disp_conn_info.path[i].caps
);
if (info->ext_disp_conn_info.path[i].caps & EXT_DISPLAY_PATH_CAPS__DP_FIXED_VS_EN)
DC_LOG_BIOS("BIOS EXT_DISPLAY_PATH_CAPS__DP_FIXED_VS_EN on path %d\n", i);
if ((info->ext_disp_conn_info.path[i].caps & AMD_EXT_DISPLAY_PATH_CAPS__EXT_CHIP_MASK) == AMD_EXT_DISPLAY_PATH_CAPS__DP_FIXED_VS_EN)
DC_LOG_BIOS("BIOS AMD_EXT_DISPLAY_PATH_CAPS__DP_FIXED_VS_EN on path %d\n", i);
else if (bp->base.ctx->dc->config.force_bios_fixed_vs) {
info->ext_disp_conn_info.path[i].caps |= EXT_DISPLAY_PATH_CAPS__DP_FIXED_VS_EN;
DC_LOG_BIOS("driver forced EXT_DISPLAY_PATH_CAPS__DP_FIXED_VS_EN on path %d\n", i);
info->ext_disp_conn_info.path[i].caps &= ~AMD_EXT_DISPLAY_PATH_CAPS__EXT_CHIP_MASK;
info->ext_disp_conn_info.path[i].caps |= AMD_EXT_DISPLAY_PATH_CAPS__DP_FIXED_VS_EN;
DC_LOG_BIOS("driver forced AMD_EXT_DISPLAY_PATH_CAPS__DP_FIXED_VS_EN on path %d\n", i);
}
}
// Log the Checksum and Voltage Swing

View File

@@ -401,6 +401,7 @@ void dcn35_update_clocks(struct clk_mgr *clk_mgr_base,
if (clk_mgr_base->clks.dtbclk_en && !new_clocks->dtbclk_en) {
if (clk_mgr->base.ctx->dc->config.allow_0_dtb_clk)
dcn35_smu_set_dtbclk(clk_mgr, false);
clk_mgr_base->clks.dtbclk_en = new_clocks->dtbclk_en;
}
/* check that we're not already in lower */
@@ -418,11 +419,17 @@ void dcn35_update_clocks(struct clk_mgr *clk_mgr_base,
}
if (!clk_mgr_base->clks.dtbclk_en && new_clocks->dtbclk_en) {
dcn35_smu_set_dtbclk(clk_mgr, true);
clk_mgr_base->clks.dtbclk_en = new_clocks->dtbclk_en;
int actual_dtbclk = 0;
dcn35_update_clocks_update_dtb_dto(clk_mgr, context, new_clocks->ref_dtbclk_khz);
clk_mgr_base->clks.ref_dtbclk_khz = new_clocks->ref_dtbclk_khz;
dcn35_smu_set_dtbclk(clk_mgr, true);
actual_dtbclk = REG_READ(CLK1_CLK4_CURRENT_CNT);
if (actual_dtbclk) {
clk_mgr_base->clks.ref_dtbclk_khz = new_clocks->ref_dtbclk_khz;
clk_mgr_base->clks.dtbclk_en = new_clocks->dtbclk_en;
}
}
/* check that we're not already in D0 */
@@ -584,12 +591,10 @@ static bool dcn35_is_spll_ssc_enabled(struct clk_mgr *clk_mgr_base)
static void init_clk_states(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;
memset(&(clk_mgr->clks), 0, sizeof(struct dc_clocks));
if (clk_mgr_int->smu_ver >= SMU_VER_THRESHOLD)
clk_mgr->clks.dtbclk_en = true; // request DTBCLK disable on first commit
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;
@@ -600,6 +605,7 @@ static void init_clk_states(struct clk_mgr *clk_mgr)
void dcn35_init_clocks(struct clk_mgr *clk_mgr)
{
struct clk_mgr_internal *clk_mgr_int = TO_CLK_MGR_INTERNAL(clk_mgr);
init_clk_states(clk_mgr);
// to adjust dp_dto reference clock if ssc is enable otherwise to apply dprefclk

View File

@@ -43,7 +43,9 @@
#define DALSMC_MSG_ActiveUclkFclk 0x18
#define DALSMC_MSG_IdleUclkFclk 0x19
#define DALSMC_MSG_SetUclkPstateAllow 0x1A
#define DALSMC_Message_Count 0x1B
#define DALSMC_MSG_SubvpUclkFclk 0x1B
#define DALSMC_MSG_GetNumUmcChannels 0x1C
#define DALSMC_Message_Count 0x1D
typedef enum {
FCLK_SWITCH_DISALLOW,

View File

@@ -628,207 +628,6 @@ static void dcn401_update_clocks_update_dentist(
}
static void dcn401_update_clocks_legacy(struct clk_mgr *clk_mgr_base,
struct dc_state *context,
bool safe_to_lower)
{
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;
bool update_dppclk = false;
bool update_dispclk = false;
bool enter_display_off = false;
bool dpp_clock_lowered = false;
struct dmcu *dmcu = clk_mgr_base->ctx->dc->res_pool->dmcu;
bool force_reset = false;
bool update_uclk = false, update_fclk = false;
bool p_state_change_support;
bool fclk_p_state_change_support;
int total_plane_count;
if (dc->work_arounds.skip_clock_update)
return;
if (clk_mgr_base->clks.dispclk_khz == 0 ||
(dc->debug.force_clock_mode & 0x1)) {
/* This is from resume or boot up, if forced_clock cfg option used,
* we bypass program dispclk and DPPCLK, but need set them for S3.
*/
force_reset = true;
dcn2_read_clocks_from_hw_dentist(clk_mgr_base);
/* Force_clock_mode 0x1: force reset the clock even it is the same clock
* as long as it is in Passive level.
*/
}
display_count = clk_mgr_helper_get_active_display_cnt(dc, context);
if (display_count == 0)
enter_display_off = true;
if (clk_mgr->smu_present) {
if (enter_display_off == safe_to_lower)
dcn401_smu_set_num_of_displays(clk_mgr, display_count);
clk_mgr_base->clks.fclk_prev_p_state_change_support = clk_mgr_base->clks.fclk_p_state_change_support;
total_plane_count = clk_mgr_helper_get_active_plane_cnt(dc, context);
fclk_p_state_change_support = new_clocks->fclk_p_state_change_support || (total_plane_count == 0);
if (should_update_pstate_support(safe_to_lower, fclk_p_state_change_support, clk_mgr_base->clks.fclk_p_state_change_support)) {
clk_mgr_base->clks.fclk_p_state_change_support = fclk_p_state_change_support;
/* To enable FCLK P-state switching, send PSTATE_SUPPORTED message to PMFW */
if (clk_mgr_base->clks.fclk_p_state_change_support) {
/* Handle the code for sending a message to PMFW that FCLK P-state change is supported */
dcn401_smu_send_fclk_pstate_message(clk_mgr, true);
}
}
if (dc->debug.force_min_dcfclk_mhz > 0)
new_clocks->dcfclk_khz = (new_clocks->dcfclk_khz > (dc->debug.force_min_dcfclk_mhz * 1000)) ?
new_clocks->dcfclk_khz : (dc->debug.force_min_dcfclk_mhz * 1000);
if (should_set_clock(safe_to_lower, new_clocks->dcfclk_khz, clk_mgr_base->clks.dcfclk_khz)) {
clk_mgr_base->clks.dcfclk_khz = new_clocks->dcfclk_khz;
if (dcn401_is_ppclk_dpm_enabled(clk_mgr, PPCLK_DCFCLK))
dcn401_smu_set_hard_min_by_freq(clk_mgr, PPCLK_DCFCLK, khz_to_mhz_ceil(clk_mgr_base->clks.dcfclk_khz));
}
if (should_set_clock(safe_to_lower, new_clocks->dcfclk_deep_sleep_khz, clk_mgr_base->clks.dcfclk_deep_sleep_khz)) {
clk_mgr_base->clks.dcfclk_deep_sleep_khz = new_clocks->dcfclk_deep_sleep_khz;
if (dcn401_is_ppclk_dpm_enabled(clk_mgr, PPCLK_DCFCLK))
dcn401_smu_set_min_deep_sleep_dcef_clk(clk_mgr, khz_to_mhz_ceil(clk_mgr_base->clks.dcfclk_deep_sleep_khz));
}
if (should_set_clock(safe_to_lower, new_clocks->socclk_khz, clk_mgr_base->clks.socclk_khz))
/* We don't actually care about socclk, don't notify SMU of hard min */
clk_mgr_base->clks.socclk_khz = new_clocks->socclk_khz;
clk_mgr_base->clks.prev_p_state_change_support = clk_mgr_base->clks.p_state_change_support;
clk_mgr_base->clks.prev_num_ways = clk_mgr_base->clks.num_ways;
if (clk_mgr_base->clks.num_ways != new_clocks->num_ways &&
clk_mgr_base->clks.num_ways < new_clocks->num_ways) {
clk_mgr_base->clks.num_ways = new_clocks->num_ways;
if (dcn401_is_ppclk_dpm_enabled(clk_mgr, PPCLK_UCLK))
dcn401_smu_send_cab_for_uclk_message(clk_mgr, clk_mgr_base->clks.num_ways);
}
p_state_change_support = new_clocks->p_state_change_support || (total_plane_count == 0);
if (should_update_pstate_support(safe_to_lower, p_state_change_support, clk_mgr_base->clks.prev_p_state_change_support)) {
clk_mgr_base->clks.p_state_change_support = p_state_change_support;
clk_mgr_base->clks.fw_based_mclk_switching = p_state_change_support && new_clocks->fw_based_mclk_switching;
/* to disable P-State switching, set UCLK min = max */
if (!clk_mgr_base->clks.p_state_change_support && dcn401_is_ppclk_dpm_enabled(clk_mgr, PPCLK_UCLK))
dcn401_smu_set_hard_min_by_freq(clk_mgr, PPCLK_UCLK,
clk_mgr_base->bw_params->clk_table.entries[clk_mgr_base->bw_params->clk_table.num_entries_per_clk.num_memclk_levels - 1].memclk_mhz);
}
/* Always update saved value, even if new value not set due to P-State switching unsupported. Also check safe_to_lower for FCLK */
if (safe_to_lower && (clk_mgr_base->clks.fclk_p_state_change_support != clk_mgr_base->clks.fclk_prev_p_state_change_support)) {
update_fclk = true;
}
if (!clk_mgr_base->clks.fclk_p_state_change_support &&
update_fclk &&
dcn401_is_ppclk_dpm_enabled(clk_mgr, PPCLK_FCLK)) {
/* Handle code for sending a message to PMFW that FCLK P-state change is not supported */
dcn401_smu_send_fclk_pstate_message(clk_mgr, false);
}
/* Always update saved value, even if new value not set due to P-State switching unsupported */
if (should_set_clock(safe_to_lower, new_clocks->dramclk_khz, clk_mgr_base->clks.dramclk_khz)) {
clk_mgr_base->clks.dramclk_khz = new_clocks->dramclk_khz;
update_uclk = true;
}
/* set UCLK to requested value if P-State switching is supported, or to re-enable P-State switching */
if (clk_mgr_base->clks.p_state_change_support &&
(update_uclk || !clk_mgr_base->clks.prev_p_state_change_support) &&
dcn401_is_ppclk_dpm_enabled(clk_mgr, PPCLK_UCLK))
dcn401_smu_set_hard_min_by_freq(clk_mgr, PPCLK_UCLK, khz_to_mhz_ceil(clk_mgr_base->clks.dramclk_khz));
if (clk_mgr_base->clks.num_ways != new_clocks->num_ways &&
clk_mgr_base->clks.num_ways > new_clocks->num_ways) {
clk_mgr_base->clks.num_ways = new_clocks->num_ways;
if (dcn401_is_ppclk_dpm_enabled(clk_mgr, PPCLK_UCLK))
dcn401_smu_send_cab_for_uclk_message(clk_mgr, clk_mgr_base->clks.num_ways);
}
}
if (should_set_clock(safe_to_lower, new_clocks->dppclk_khz, clk_mgr_base->clks.dppclk_khz)) {
if (clk_mgr_base->clks.dppclk_khz > new_clocks->dppclk_khz)
dpp_clock_lowered = true;
clk_mgr_base->clks.dppclk_khz = new_clocks->dppclk_khz;
clk_mgr_base->clks.actual_dppclk_khz = new_clocks->dppclk_khz;
if (clk_mgr->smu_present && !dpp_clock_lowered && dcn401_is_ppclk_dpm_enabled(clk_mgr, PPCLK_DPPCLK))
clk_mgr_base->clks.actual_dppclk_khz = dcn401_set_hard_min_by_freq_optimized(clk_mgr, PPCLK_DPPCLK, clk_mgr_base->clks.dppclk_khz);
update_dppclk = true;
}
if (should_set_clock(safe_to_lower, new_clocks->dispclk_khz, clk_mgr_base->clks.dispclk_khz)) {
clk_mgr_base->clks.dispclk_khz = new_clocks->dispclk_khz;
if (clk_mgr->smu_present && dcn401_is_ppclk_dpm_enabled(clk_mgr, PPCLK_DISPCLK))
clk_mgr_base->clks.actual_dispclk_khz = dcn401_set_hard_min_by_freq_optimized(clk_mgr, PPCLK_DISPCLK, clk_mgr_base->clks.dispclk_khz);
update_dispclk = true;
}
if (!new_clocks->dtbclk_en && dcn401_is_ppclk_dpm_enabled(clk_mgr, PPCLK_DTBCLK)) {
new_clocks->ref_dtbclk_khz = clk_mgr_base->bw_params->clk_table.entries[0].dtbclk_mhz * 1000;
}
/* clock limits are received with MHz precision, divide by 1000 to prevent setting clocks at every call */
if (!dc->debug.disable_dtb_ref_clk_switch &&
should_set_clock(safe_to_lower, new_clocks->ref_dtbclk_khz / 1000, clk_mgr_base->clks.ref_dtbclk_khz / 1000) &&
dcn401_is_ppclk_dpm_enabled(clk_mgr, PPCLK_DTBCLK)) {
/* DCCG requires KHz precision for DTBCLK */
clk_mgr_base->clks.ref_dtbclk_khz =
dcn401_smu_set_hard_min_by_freq(clk_mgr, PPCLK_DTBCLK, khz_to_mhz_ceil(new_clocks->ref_dtbclk_khz));
dcn401_update_clocks_update_dtb_dto(clk_mgr, context, clk_mgr_base->clks.ref_dtbclk_khz);
}
if (dc->config.forced_clocks == false || (force_reset && safe_to_lower)) {
if (dpp_clock_lowered) {
/* if clock is being lowered, increase DTO before lowering refclk */
dcn401_update_clocks_update_dpp_dto(clk_mgr, context,
safe_to_lower, clk_mgr_base->clks.dppclk_khz);
dcn401_update_clocks_update_dentist(clk_mgr, context);
if (clk_mgr->smu_present && dcn401_is_ppclk_dpm_enabled(clk_mgr, PPCLK_DPPCLK)) {
clk_mgr_base->clks.actual_dppclk_khz = dcn401_set_hard_min_by_freq_optimized(clk_mgr, PPCLK_DPPCLK,
clk_mgr_base->clks.dppclk_khz);
dcn401_update_clocks_update_dpp_dto(clk_mgr, context, safe_to_lower,
clk_mgr_base->clks.actual_dppclk_khz);
}
} else {
/* if clock is being raised, increase refclk before lowering DTO */
if (update_dppclk || update_dispclk)
dcn401_update_clocks_update_dentist(clk_mgr, context);
/* There is a check inside dcn20_update_clocks_update_dpp_dto which ensures
* that we do not lower dto when it is not safe to lower. We do not need to
* compare the current and new dppclk before calling this function.
*/
dcn401_update_clocks_update_dpp_dto(clk_mgr, context,
safe_to_lower, clk_mgr_base->clks.actual_dppclk_khz);
}
}
if (update_dispclk && dmcu && dmcu->funcs->is_dmcu_initialized(dmcu))
/*update dmcu for wait_loop count*/
dmcu->funcs->set_psr_wait_loop(dmcu,
clk_mgr_base->clks.dispclk_khz / 1000 / 7);
}
static void dcn401_execute_block_sequence(struct clk_mgr *clk_mgr_base, unsigned int num_steps)
{
struct clk_mgr_internal *clk_mgr_internal = TO_CLK_MGR_INTERNAL(clk_mgr_base);
@@ -1008,15 +807,15 @@ static unsigned int dcn401_build_update_bandwidth_clocks_sequence(
update_active_fclk = true;
update_idle_fclk = true;
/* To enable FCLK P-state switching, send PSTATE_SUPPORTED message to PMFW */
if (clk_mgr_base->clks.fclk_p_state_change_support) {
/* Handle the code for sending a message to PMFW that FCLK P-state change is supported */
if (dcn401_is_ppclk_dpm_enabled(clk_mgr_internal, PPCLK_FCLK)) {
block_sequence[num_steps].params.update_pstate_support_params.support = true;
block_sequence[num_steps].func = CLK_MGR401_UPDATE_FCLK_PSTATE_SUPPORT;
num_steps++;
}
}
/* To enable FCLK P-state switching, send PSTATE_SUPPORTED message to PMFW (message not supported on DCN401)*/
// if (clk_mgr_base->clks.fclk_p_state_change_support) {
// /* Handle the code for sending a message to PMFW that FCLK P-state change is supported */
// if (dcn401_is_ppclk_dpm_enabled(clk_mgr_internal, PPCLK_FCLK)) {
// block_sequence[num_steps].params.update_pstate_support_params.support = true;
// block_sequence[num_steps].func = CLK_MGR401_UPDATE_FCLK_PSTATE_SUPPORT;
// num_steps++;
// }
// }
}
if (!clk_mgr_base->clks.fclk_p_state_change_support && dcn401_is_ppclk_dpm_enabled(clk_mgr_internal, PPCLK_FCLK)) {
@@ -1224,14 +1023,14 @@ static unsigned int dcn401_build_update_bandwidth_clocks_sequence(
// (*num_steps)++;
// }
/* disable FCLK P-State support if needed */
if (!fclk_p_state_change_support &&
should_update_pstate_support(safe_to_lower, fclk_p_state_change_support, clk_mgr_base->clks.fclk_prev_p_state_change_support) &&
dcn401_is_ppclk_dpm_enabled(clk_mgr_internal, PPCLK_FCLK)) {
block_sequence[num_steps].params.update_pstate_support_params.support = false;
block_sequence[num_steps].func = CLK_MGR401_UPDATE_FCLK_PSTATE_SUPPORT;
num_steps++;
}
/* disable FCLK P-State support if needed (message not supported on DCN401)*/
// if (!fclk_p_state_change_support &&
// should_update_pstate_support(safe_to_lower, fclk_p_state_change_support, clk_mgr_base->clks.fclk_prev_p_state_change_support) &&
// dcn401_is_ppclk_dpm_enabled(clk_mgr_internal, PPCLK_FCLK)) {
// block_sequence[num_steps].params.update_pstate_support_params.support = false;
// block_sequence[num_steps].func = CLK_MGR401_UPDATE_FCLK_PSTATE_SUPPORT;
// num_steps++;
// }
}
if (new_clocks->fw_based_mclk_switching != clk_mgr_base->clks.fw_based_mclk_switching &&
@@ -1412,11 +1211,6 @@ static void dcn401_update_clocks(struct clk_mgr *clk_mgr_base,
unsigned int num_steps = 0;
if (dc->debug.enable_legacy_clock_update) {
dcn401_update_clocks_legacy(clk_mgr_base, context, safe_to_lower);
return;
}
/* build bandwidth related clocks update sequence */
num_steps = dcn401_build_update_bandwidth_clocks_sequence(clk_mgr_base,
context,
@@ -1551,6 +1345,20 @@ static void dcn401_set_hard_min_memclk(struct clk_mgr *clk_mgr_base, bool curren
dcn401_execute_block_sequence(clk_mgr_base, num_steps);
}
static int dcn401_get_hard_min_memclk(struct clk_mgr *clk_mgr_base)
{
struct clk_mgr_internal *clk_mgr = TO_CLK_MGR_INTERNAL(clk_mgr_base);
return clk_mgr->base.ctx->dc->current_state->bw_ctx.bw.dcn.clk.dramclk_khz;
}
static int dcn401_get_hard_min_fclk(struct clk_mgr *clk_mgr_base)
{
struct clk_mgr_internal *clk_mgr = TO_CLK_MGR_INTERNAL(clk_mgr_base);
return clk_mgr->base.ctx->dc->current_state->bw_ctx.bw.dcn.clk.fclk_khz;
}
/* Get current memclk states, update bounding box */
static void dcn401_get_memclk_states_from_smu(struct clk_mgr *clk_mgr_base)
{
@@ -1595,6 +1403,15 @@ static void dcn401_get_memclk_states_from_smu(struct clk_mgr *clk_mgr_base)
if (clk_mgr->dpm_present && !num_levels)
clk_mgr->dpm_present = false;
clk_mgr_base->bw_params->num_channels = dcn401_smu_get_num_of_umc_channels(clk_mgr);
if (clk_mgr_base->ctx->dc_bios) {
/* use BIOS values if none provided by PMFW */
if (clk_mgr_base->bw_params->num_channels == 0) {
clk_mgr_base->bw_params->num_channels = clk_mgr_base->ctx->dc_bios->vram_info.num_chans;
}
clk_mgr_base->bw_params->dram_channel_width_bytes = clk_mgr_base->ctx->dc_bios->vram_info.dram_channel_width_bytes;
}
/* Refresh bounding box */
clk_mgr_base->ctx->dc->res_pool->funcs->update_bw_bounding_box(
clk_mgr->base.ctx->dc, clk_mgr_base->bw_params);
@@ -1684,6 +1501,8 @@ static struct clk_mgr_funcs dcn401_funcs = {
.enable_pme_wa = dcn401_enable_pme_wa,
.is_smu_present = dcn401_is_smu_present,
.get_dispclk_from_dentist = dcn401_get_dispclk_from_dentist,
.get_hard_min_memclk = dcn401_get_hard_min_memclk,
.get_hard_min_fclk = dcn401_get_hard_min_fclk,
};
struct clk_mgr_internal *dcn401_clk_mgr_construct(

View File

@@ -25,6 +25,9 @@
#ifndef DALSMC_MSG_SubvpUclkFclk
#define DALSMC_MSG_SubvpUclkFclk 0x1B
#endif
#ifndef DALSMC_MSG_GetNumUmcChannels
#define DALSMC_MSG_GetNumUmcChannels 0x1C
#endif
/*
* Function to be used instead of REG_WAIT macro because the wait ends when
@@ -334,3 +337,14 @@ void dcn401_smu_set_num_of_displays(struct clk_mgr_internal *clk_mgr, uint32_t n
dcn401_smu_send_msg_with_param(clk_mgr,
DALSMC_MSG_NumOfDisplays, num_displays, NULL);
}
unsigned int dcn401_smu_get_num_of_umc_channels(struct clk_mgr_internal *clk_mgr)
{
unsigned int response = 0;
dcn401_smu_send_msg_with_param(clk_mgr, DALSMC_MSG_GetNumUmcChannels, 0, &response);
smu_print("SMU Get Num UMC Channels: num_umc_channels = %d\n", response);
return response;
}

View File

@@ -28,5 +28,6 @@ bool dcn401_smu_set_subvp_uclk_fclk_hardmin(struct clk_mgr_internal *clk_mgr,
uint16_t fclk_freq_mhz);
void dcn401_smu_set_min_deep_sleep_dcef_clk(struct clk_mgr_internal *clk_mgr, uint32_t freq_mhz);
void dcn401_smu_set_num_of_displays(struct clk_mgr_internal *clk_mgr, uint32_t num_displays);
unsigned int dcn401_smu_get_num_of_umc_channels(struct clk_mgr_internal *clk_mgr);
#endif /* __DCN401_CLK_MGR_SMU_MSG_H_ */

View File

@@ -615,6 +615,68 @@ dc_stream_forward_crc_window(struct dc_stream_state *stream,
return true;
}
static void
dc_stream_forward_dmub_multiple_crc_window(struct dc_dmub_srv *dmub_srv,
struct crc_window *window, struct otg_phy_mux *mux_mapping, bool stop)
{
int i;
union dmub_rb_cmd cmd = {0};
cmd.secure_display.mul_roi_ctl.phy_id = mux_mapping->phy_output_num;
cmd.secure_display.mul_roi_ctl.otg_id = mux_mapping->otg_output_num;
cmd.secure_display.header.type = DMUB_CMD__SECURE_DISPLAY;
if (stop) {
cmd.secure_display.header.sub_type = DMUB_CMD__SECURE_DISPLAY_MULTIPLE_CRC_STOP_UPDATE;
} else {
cmd.secure_display.header.sub_type = DMUB_CMD__SECURE_DISPLAY_MULTIPLE_CRC_WIN_NOTIFY;
for (i = 0; i < MAX_CRC_WINDOW_NUM; i++) {
cmd.secure_display.mul_roi_ctl.roi_ctl[i].x_start = window[i].rect.x;
cmd.secure_display.mul_roi_ctl.roi_ctl[i].y_start = window[i].rect.y;
cmd.secure_display.mul_roi_ctl.roi_ctl[i].x_end = window[i].rect.x + window[i].rect.width;
cmd.secure_display.mul_roi_ctl.roi_ctl[i].y_end = window[i].rect.y + window[i].rect.height;
cmd.secure_display.mul_roi_ctl.roi_ctl[i].enable = window[i].enable;
}
}
dc_wake_and_execute_dmub_cmd(dmub_srv->ctx, &cmd, DM_DMUB_WAIT_TYPE_NO_WAIT);
}
bool
dc_stream_forward_multiple_crc_window(struct dc_stream_state *stream,
struct crc_window *window, uint8_t phy_id, bool stop)
{
struct dc_dmub_srv *dmub_srv;
struct otg_phy_mux mux_mapping;
struct pipe_ctx *pipe;
int i;
struct dc *dc = stream->ctx->dc;
for (i = 0; i < MAX_PIPES; i++) {
pipe = &dc->current_state->res_ctx.pipe_ctx[i];
if (pipe->stream == stream && !pipe->top_pipe && !pipe->prev_odm_pipe)
break;
}
/* Stream not found */
if (i == MAX_PIPES)
return false;
mux_mapping.phy_output_num = phy_id;
mux_mapping.otg_output_num = pipe->stream_res.tg->inst;
dmub_srv = dc->ctx->dmub_srv;
/* forward to dmub only. no dmcu support*/
if (dmub_srv)
dc_stream_forward_dmub_multiple_crc_window(dmub_srv, window, &mux_mapping, stop);
else
return false;
return true;
}
#endif /* CONFIG_DRM_AMD_SECURE_DISPLAY */
/**
@@ -625,15 +687,17 @@ dc_stream_forward_crc_window(struct dc_stream_state *stream,
* @enable: Enable CRC if true, disable otherwise.
* @continuous: Capture CRC on every frame if true. Otherwise, only capture
* once.
* @idx: Capture CRC on which CRC engine instance
* @reset: Reset CRC engine before the configuration
*
* By default, only CRC0 is configured, and the entire frame is used to
* calculate the CRC.
* By default, the entire frame is used to calculate the CRC.
*
* Return: %false if the stream is not found or CRC capture is not supported;
* %true if the stream has been configured.
*/
bool dc_stream_configure_crc(struct dc *dc, struct dc_stream_state *stream,
struct crc_params *crc_window, bool enable, bool continuous)
struct crc_params *crc_window, bool enable, bool continuous,
uint8_t idx, bool reset)
{
struct pipe_ctx *pipe;
struct crc_params param;
@@ -677,6 +741,9 @@ bool dc_stream_configure_crc(struct dc *dc, struct dc_stream_state *stream,
param.continuous_mode = continuous;
param.enable = enable;
param.crc_eng_inst = idx;
param.reset = reset;
tg = pipe->stream_res.tg;
/* Only call if supported */
@@ -691,6 +758,7 @@ bool dc_stream_configure_crc(struct dc *dc, struct dc_stream_state *stream,
*
* @dc: DC object.
* @stream: The DC stream state of the stream to get CRCs from.
* @idx: index of crc engine to get CRC from
* @r_cr: CRC value for the red component.
* @g_y: CRC value for the green component.
* @b_cb: CRC value for the blue component.
@@ -700,7 +768,7 @@ bool dc_stream_configure_crc(struct dc *dc, struct dc_stream_state *stream,
* Return:
* %false if stream is not found, or if CRCs are not enabled.
*/
bool dc_stream_get_crc(struct dc *dc, struct dc_stream_state *stream,
bool dc_stream_get_crc(struct dc *dc, struct dc_stream_state *stream, uint8_t idx,
uint32_t *r_cr, uint32_t *g_y, uint32_t *b_cb)
{
int i;
@@ -721,7 +789,7 @@ bool dc_stream_get_crc(struct dc *dc, struct dc_stream_state *stream,
tg = pipe->stream_res.tg;
if (tg->funcs->get_crc)
return tg->funcs->get_crc(tg, r_cr, g_y, b_cb);
return tg->funcs->get_crc(tg, idx, r_cr, g_y, b_cb);
DC_LOG_WARNING("CRC capture not supported.");
return false;
}
@@ -1173,6 +1241,8 @@ static void dc_update_visual_confirm_color(struct dc *dc, struct dc_state *conte
get_mclk_switch_visual_confirm_color(pipe_ctx, &(pipe_ctx->visual_confirm_color));
else if (dc->debug.visual_confirm == VISUAL_CONFIRM_FAMS2)
get_fams2_visual_confirm_color(dc, context, pipe_ctx, &(pipe_ctx->visual_confirm_color));
else if (dc->debug.visual_confirm == VISUAL_CONFIRM_VABC)
get_vabc_visual_confirm_color(pipe_ctx, &(pipe_ctx->visual_confirm_color));
}
}
}
@@ -2492,7 +2562,7 @@ static enum surface_update_type get_plane_info_update_type(const struct dc *dc,
if (memcmp(&u->plane_info->tiling_info, &u->surface->tiling_info,
sizeof(union dc_tiling_info)) != 0) {
sizeof(struct dc_tiling_info)) != 0) {
update_flags->bits.swizzle_change = 1;
elevate_update_type(&update_type, UPDATE_TYPE_MED);
@@ -4519,7 +4589,7 @@ static bool commit_minimal_transition_based_on_current_context(struct dc *dc,
struct pipe_split_policy_backup policy;
struct dc_state *intermediate_context;
struct dc_state *old_current_state = dc->current_state;
struct dc_surface_update srf_updates[MAX_SURFACE_NUM] = {0};
struct dc_surface_update srf_updates[MAX_SURFACES] = {0};
int surface_count;
/*
@@ -5316,13 +5386,9 @@ void dc_set_power_state(struct dc *dc, enum dc_acpi_cm_power_state power_state)
dc->vm_pa_config.valid) {
dc->hwss.init_sys_ctx(dc->hwseq, dc, &dc->vm_pa_config);
}
/*mark d0 last*/
dc->power_state = power_state;
break;
default:
ASSERT(dc->current_state->stream_count == 0);
/*mark d3 first*/
dc->power_state = power_state;
dc_dmub_srv_notify_fw_dc_power_state(dc->ctx->dmub_srv, power_state);
dc_state_destruct(dc->current_state);
@@ -5446,6 +5512,11 @@ bool dc_set_ips_disable(struct dc *dc, unsigned int disable_ips)
void dc_allow_idle_optimizations_internal(struct dc *dc, bool allow, char const *caller_name)
{
int idle_fclk_khz = 0, idle_dramclk_khz = 0, i = 0;
enum mall_stream_type subvp_pipe_type[MAX_PIPES] = {0};
struct pipe_ctx *pipe = NULL;
struct dc_state *context = dc->current_state;
if (dc->debug.disable_idle_power_optimizations) {
DC_LOG_DEBUG("%s: disabled\n", __func__);
return;
@@ -5470,6 +5541,23 @@ void dc_allow_idle_optimizations_internal(struct dc *dc, bool allow, char const
dc->idle_optimizations_allowed = allow;
DC_LOG_DEBUG("%s: %s\n", __func__, allow ? "enabled" : "disabled");
}
// log idle clocks and sub vp pipe types at idle optimization time
if (dc->clk_mgr != NULL && dc->clk_mgr->funcs->get_hard_min_fclk)
idle_fclk_khz = dc->clk_mgr->funcs->get_hard_min_fclk(dc->clk_mgr);
if (dc->clk_mgr != NULL && dc->clk_mgr->funcs->get_hard_min_memclk)
idle_dramclk_khz = dc->clk_mgr->funcs->get_hard_min_memclk(dc->clk_mgr);
for (i = 0; i < dc->res_pool->pipe_count; i++) {
pipe = &context->res_ctx.pipe_ctx[i];
subvp_pipe_type[i] = dc_state_get_pipe_subvp_type(context, pipe);
}
DC_LOG_DC("%s: allow_idle=%d\n HardMinUClk_Khz=%d HardMinDramclk_Khz=%d\n Pipe_0=%d Pipe_1=%d Pipe_2=%d Pipe_3=%d Pipe_4=%d Pipe_5=%d (caller=%s)\n",
__func__, allow, idle_fclk_khz, idle_dramclk_khz, subvp_pipe_type[0], subvp_pipe_type[1], subvp_pipe_type[2],
subvp_pipe_type[3], subvp_pipe_type[4], subvp_pipe_type[5], caller_name);
}
void dc_exit_ips_for_hw_access_internal(struct dc *dc, const char *caller_name)

View File

@@ -425,6 +425,44 @@ void get_hdr_visual_confirm_color(
}
}
/* Visual Confirm color definition for VABC */
void get_vabc_visual_confirm_color(
struct pipe_ctx *pipe_ctx,
struct tg_color *color)
{
uint32_t color_value = MAX_TG_COLOR_VALUE;
struct dc_link *edp_link = NULL;
if (pipe_ctx && pipe_ctx->stream && pipe_ctx->stream->link) {
if (pipe_ctx->stream->link->connector_signal == SIGNAL_TYPE_EDP)
edp_link = pipe_ctx->stream->link;
}
if (edp_link) {
switch (edp_link->backlight_control_type) {
case BACKLIGHT_CONTROL_PWM:
color->color_r_cr = color_value;
color->color_g_y = 0;
color->color_b_cb = 0;
break;
case BACKLIGHT_CONTROL_AMD_AUX:
color->color_r_cr = 0;
color->color_g_y = color_value;
color->color_b_cb = 0;
break;
case BACKLIGHT_CONTROL_VESA_AUX:
color->color_r_cr = 0;
color->color_g_y = 0;
color->color_b_cb = color_value;
break;
}
} else {
color->color_r_cr = 0;
color->color_g_y = 0;
color->color_b_cb = 0;
}
}
void get_subvp_visual_confirm_color(
struct pipe_ctx *pipe_ctx,
struct tg_color *color)

View File

@@ -125,6 +125,14 @@ uint32_t dc_link_bandwidth_kbps(
return link->dc->link_srv->dp_link_bandwidth_kbps(link, link_settings);
}
uint32_t dc_link_required_hblank_size_bytes(
const struct dc_link *link,
struct dp_audio_bandwidth_params *audio_params)
{
return link->dc->link_srv->dp_required_hblank_size_bytes(link,
audio_params);
}
void dc_get_cur_link_res_map(const struct dc *dc, uint32_t *map)
{
dc->link_srv->get_cur_res_map(dc, map);

View File

@@ -4478,7 +4478,7 @@ static void set_hfvs_info_packet(
static void adaptive_sync_override_dp_info_packets_sdp_line_num(
const struct dc_crtc_timing *timing,
struct enc_sdp_line_num *sdp_line_num,
struct _vcs_dpi_display_pipe_dest_params_st *pipe_dlg_param)
unsigned int vstartup_start)
{
uint32_t asic_blank_start = 0;
uint32_t asic_blank_end = 0;
@@ -4493,8 +4493,8 @@ static void adaptive_sync_override_dp_info_packets_sdp_line_num(
asic_blank_end = (asic_blank_start - tg->v_border_bottom -
tg->v_addressable - tg->v_border_top);
if (pipe_dlg_param->vstartup_start > asic_blank_end) {
v_update = (tg->v_total - (pipe_dlg_param->vstartup_start - asic_blank_end));
if (vstartup_start > asic_blank_end) {
v_update = (tg->v_total - (vstartup_start - asic_blank_end));
sdp_line_num->adaptive_sync_line_num_valid = true;
sdp_line_num->adaptive_sync_line_num = (tg->v_total - v_update - 1);
} else {
@@ -4507,7 +4507,7 @@ static void set_adaptive_sync_info_packet(
struct dc_info_packet *info_packet,
const struct dc_stream_state *stream,
struct encoder_info_frame *info_frame,
struct _vcs_dpi_display_pipe_dest_params_st *pipe_dlg_param)
unsigned int vstartup_start)
{
if (!stream->adaptive_sync_infopacket.valid)
return;
@@ -4515,7 +4515,7 @@ static void set_adaptive_sync_info_packet(
adaptive_sync_override_dp_info_packets_sdp_line_num(
&stream->timing,
&info_frame->sdp_line_num,
pipe_dlg_param);
vstartup_start);
*info_packet = stream->adaptive_sync_infopacket;
}
@@ -4548,6 +4548,7 @@ void resource_build_info_frame(struct pipe_ctx *pipe_ctx)
{
enum signal_type signal = SIGNAL_TYPE_NONE;
struct encoder_info_frame *info = &pipe_ctx->stream_res.encoder_info_frame;
unsigned int vstartup_start = 0;
/* default all packets to invalid */
info->avi.valid = false;
@@ -4561,6 +4562,9 @@ void resource_build_info_frame(struct pipe_ctx *pipe_ctx)
info->adaptive_sync.valid = false;
signal = pipe_ctx->stream->signal;
if (pipe_ctx->stream->ctx->dc->res_pool->funcs->get_vstartup_for_pipe)
vstartup_start = pipe_ctx->stream->ctx->dc->res_pool->funcs->get_vstartup_for_pipe(pipe_ctx);
/* HDMi and DP have different info packets*/
if (dc_is_hdmi_signal(signal)) {
set_avi_info_frame(&info->avi, pipe_ctx);
@@ -4582,7 +4586,7 @@ void resource_build_info_frame(struct pipe_ctx *pipe_ctx)
set_adaptive_sync_info_packet(&info->adaptive_sync,
pipe_ctx->stream,
info,
&pipe_ctx->pipe_dlg_param);
vstartup_start);
}
patch_gamut_packet_checksum(&info->gamut);

View File

@@ -483,9 +483,9 @@ bool dc_state_add_plane(
if (stream_status == NULL) {
dm_error("Existing stream not found; failed to attach surface!\n");
goto out;
} else if (stream_status->plane_count == MAX_SURFACE_NUM) {
} else if (stream_status->plane_count == MAX_SURFACES) {
dm_error("Surface: can not attach plane_state %p! Maximum is: %d\n",
plane_state, MAX_SURFACE_NUM);
plane_state, MAX_SURFACES);
goto out;
} else if (!otg_master_pipe) {
goto out;
@@ -600,7 +600,7 @@ bool dc_state_rem_all_planes_for_stream(
{
int i, old_plane_count;
struct dc_stream_status *stream_status = NULL;
struct dc_plane_state *del_planes[MAX_SURFACE_NUM] = { 0 };
struct dc_plane_state *del_planes[MAX_SURFACES] = { 0 };
for (i = 0; i < state->stream_count; i++)
if (state->streams[i] == stream) {
@@ -875,7 +875,7 @@ bool dc_state_rem_all_phantom_planes_for_stream(
{
int i, old_plane_count;
struct dc_stream_status *stream_status = NULL;
struct dc_plane_state *del_planes[MAX_SURFACE_NUM] = { 0 };
struct dc_plane_state *del_planes[MAX_SURFACES] = { 0 };
for (i = 0; i < state->stream_count; i++)
if (state->streams[i] == phantom_stream) {

View File

@@ -37,6 +37,8 @@
#define DC_LOGGER dc->ctx->logger
#ifndef MIN
#define MIN(X, Y) ((X) < (Y) ? (X) : (Y))
#endif
#ifndef MAX
#define MAX(x, y) ((x > y) ? x : y)
#endif

View File

@@ -55,9 +55,9 @@ struct aux_payload;
struct set_config_cmd_payload;
struct dmub_notification;
#define DC_VER "3.2.314"
#define DC_VER "3.2.316"
#define MAX_SURFACES 3
#define MAX_SURFACES 4
#define MAX_PLANES 6
#define MAX_STREAMS 6
#define MIN_VIEWPORT_SIZE 12
@@ -472,6 +472,7 @@ struct dc_config {
bool disable_hbr_audio_dp2;
bool consolidated_dpia_dp_lt;
bool set_pipe_unlock_order;
bool enable_dpia_pre_training;
};
enum visual_confirm {
@@ -488,6 +489,7 @@ enum visual_confirm {
VISUAL_CONFIRM_MCLK_SWITCH = 16,
VISUAL_CONFIRM_FAMS2 = 19,
VISUAL_CONFIRM_HW_CURSOR = 20,
VISUAL_CONFIRM_VABC = 21,
};
enum dc_psr_power_opts {
@@ -775,7 +777,8 @@ union dpia_debug_options {
uint32_t enable_force_tbt3_work_around:1; /* bit 4 */
uint32_t disable_usb4_pm_support:1; /* bit 5 */
uint32_t enable_consolidated_dpia_dp_lt:1; /* bit 6 */
uint32_t reserved:25;
uint32_t enable_dpia_pre_training:1; /* bit 7 */
uint32_t reserved:24;
} bits;
uint32_t raw;
};
@@ -1060,7 +1063,6 @@ struct dc_debug_options {
uint32_t dml21_disable_pstate_method_mask;
union fw_assisted_mclk_switch_version fams_version;
union dmub_fams2_global_feature_config fams2_config;
bool enable_legacy_clock_update;
unsigned int force_cositing;
unsigned int disable_spl;
unsigned int force_easf;
@@ -1305,7 +1307,7 @@ struct dc_plane_state {
struct rect clip_rect;
struct plane_size plane_size;
union dc_tiling_info tiling_info;
struct dc_tiling_info tiling_info;
struct dc_plane_dcc_param dcc;
@@ -1376,7 +1378,7 @@ struct dc_plane_state {
struct dc_plane_info {
struct plane_size plane_size;
union dc_tiling_info tiling_info;
struct dc_tiling_info tiling_info;
struct dc_plane_dcc_param dcc;
enum surface_pixel_format format;
enum dc_rotation_angle rotation;
@@ -1403,7 +1405,7 @@ struct dc_scratch_space {
* store current value in plane states so we can still recover
* a valid current state during dc update.
*/
struct dc_plane_state plane_states[MAX_SURFACE_NUM];
struct dc_plane_state plane_states[MAX_SURFACES];
struct dc_stream_state stream_state;
};
@@ -2025,6 +2027,24 @@ uint32_t dc_link_bandwidth_kbps(
const struct dc_link *link,
const struct dc_link_settings *link_setting);
struct dp_audio_bandwidth_params {
const struct dc_crtc_timing *crtc_timing;
enum dp_link_encoding link_encoding;
uint32_t channel_count;
uint32_t sample_rate_hz;
};
/* The function calculates the minimum size of hblank (in bytes) needed to
* support the specified channel count and sample rate combination, given the
* link encoding and timing to be used. This calculation is not supported
* for 8b/10b SST.
*
* return - min hblank size in bytes, 0 if 8b/10b SST.
*/
uint32_t dc_link_required_hblank_size_bytes(
const struct dc_link *link,
struct dp_audio_bandwidth_params *audio_params);
/* The function takes a snapshot of current link resource allocation state
* @dc: pointer to dc of the dm calling this
* @map: a dc link resource snapshot defined internally to dc.
@@ -2384,6 +2404,13 @@ struct dc_sink_dsc_caps {
struct dsc_dec_dpcd_caps dsc_dec_caps;
};
struct dc_sink_hblank_expansion_caps {
// 'true' if these are virtual DPCD's HBlank expansion caps (immediately upstream of sink in MST topology),
// 'false' if they are sink's HBlank expansion caps
bool is_virtual_dpcd_hblank_expansion;
struct hblank_expansion_dpcd_caps dpcd_caps;
};
struct dc_sink_fec_caps {
bool is_rx_fec_supported;
bool is_topology_fec_supported;
@@ -2410,6 +2437,7 @@ struct dc_sink {
struct scdc_caps scdc_caps;
struct dc_sink_dsc_caps dsc_caps;
struct dc_sink_fec_caps fec_caps;
struct dc_sink_hblank_expansion_caps hblank_expansion_caps;
bool is_vsc_sdp_colorimetry_supported;

View File

@@ -969,6 +969,21 @@ union dp_sink_video_fallback_formats {
uint8_t raw;
};
union dp_receive_port0_cap {
struct {
uint8_t RESERVED :1;
uint8_t LOCAL_EDID_PRESENT :1;
uint8_t ASSOCIATED_TO_PRECEDING_PORT:1;
uint8_t HBLANK_EXPANSION_CAPABLE :1;
uint8_t BUFFER_SIZE_UNIT :1;
uint8_t BUFFER_SIZE_PER_PORT :1;
uint8_t HBLANK_REDUCTION_CAPABLE :1;
uint8_t RESERVED2:1;
uint8_t BUFFER_SIZE:8;
} bits;
uint8_t raw[2];
};
union dpcd_max_uncompressed_pixel_rate_cap {
struct {
uint16_t max_uncompressed_pixel_rate_cap :15;
@@ -1193,6 +1208,7 @@ struct dpcd_caps {
struct replay_info pr_info;
uint16_t edp_oled_emission_rate;
union dp_receive_port0_cap receive_port0_cap;
};
union dpcd_sink_ext_caps {

View File

@@ -94,6 +94,11 @@ uint32_t dc_dsc_stream_bandwidth_overhead_in_kbps(
const int num_slices_h,
const bool is_dp);
void dc_dsc_dump_decoder_caps(const struct display_stream_compressor *dsc,
const struct dsc_dec_dpcd_caps *dsc_sink_caps);
void dc_dsc_dump_encoder_caps(const struct display_stream_compressor *dsc,
const struct dc_crtc_timing *timing);
/* TODO - Hardware/specs limitation should be owned by dc dsc and returned to DM,
* and DM can choose to OVERRIDE the limitation on CASE BY CASE basis.
* Hardware/specs limitation should not be writable by DM.

View File

@@ -341,89 +341,101 @@ enum swizzle_mode_addr3_values {
DC_ADDR3_SW_UNKNOWN = DC_ADDR3_SW_MAX
};
union dc_tiling_info {
enum dc_gfxversion {
DcGfxVersion7 = 0,
DcGfxVersion8,
DcGfxVersion9,
DcGfxVersion10,
DcGfxVersion11,
DcGfxAddr3,
DcGfxVersionUnknown
};
struct {
/* Specifies the number of memory banks for tiling
* purposes.
* Only applies to 2D and 3D tiling modes.
* POSSIBLE VALUES: 2,4,8,16
*/
unsigned int num_banks;
/* Specifies the number of tiles in the x direction
* to be incorporated into the same bank.
* Only applies to 2D and 3D tiling modes.
* POSSIBLE VALUES: 1,2,4,8
*/
unsigned int bank_width;
unsigned int bank_width_c;
/* Specifies the number of tiles in the y direction to
* be incorporated into the same bank.
* Only applies to 2D and 3D tiling modes.
* POSSIBLE VALUES: 1,2,4,8
*/
unsigned int bank_height;
unsigned int bank_height_c;
/* Specifies the macro tile aspect ratio. Only applies
* to 2D and 3D tiling modes.
*/
unsigned int tile_aspect;
unsigned int tile_aspect_c;
/* Specifies the number of bytes that will be stored
* contiguously for each tile.
* If the tile data requires more storage than this
* amount, it is split into multiple slices.
* This field must not be larger than
* GB_ADDR_CONFIG.DRAM_ROW_SIZE.
* Only applies to 2D and 3D tiling modes.
* For color render targets, TILE_SPLIT >= 256B.
*/
enum tile_split_values tile_split;
enum tile_split_values tile_split_c;
/* Specifies the addressing within a tile.
* 0x0 - DISPLAY_MICRO_TILING
* 0x1 - THIN_MICRO_TILING
* 0x2 - DEPTH_MICRO_TILING
* 0x3 - ROTATED_MICRO_TILING
*/
enum tile_mode_values tile_mode;
enum tile_mode_values tile_mode_c;
/* Specifies the number of pipes and how they are
* interleaved in the surface.
* Refer to memory addressing document for complete
* details and constraints.
*/
unsigned int pipe_config;
/* Specifies the tiling mode of the surface.
* THIN tiles use an 8x8x1 tile size.
* THICK tiles use an 8x8x4 tile size.
* 2D tiling modes rotate banks for successive Z slices
* 3D tiling modes rotate pipes and banks for Z slices
* Refer to memory addressing document for complete
* details and constraints.
*/
enum array_mode_values array_mode;
} gfx8;
struct dc_tiling_info {
unsigned int gfxversion; // Specifies which part of the union to use. Must use DalGfxVersion enum
union {
struct {
/* Specifies the number of memory banks for tiling
* purposes.
* Only applies to 2D and 3D tiling modes.
* POSSIBLE VALUES: 2,4,8,16
*/
unsigned int num_banks;
/* Specifies the number of tiles in the x direction
* to be incorporated into the same bank.
* Only applies to 2D and 3D tiling modes.
* POSSIBLE VALUES: 1,2,4,8
*/
unsigned int bank_width;
unsigned int bank_width_c;
/* Specifies the number of tiles in the y direction to
* be incorporated into the same bank.
* Only applies to 2D and 3D tiling modes.
* POSSIBLE VALUES: 1,2,4,8
*/
unsigned int bank_height;
unsigned int bank_height_c;
/* Specifies the macro tile aspect ratio. Only applies
* to 2D and 3D tiling modes.
*/
unsigned int tile_aspect;
unsigned int tile_aspect_c;
/* Specifies the number of bytes that will be stored
* contiguously for each tile.
* If the tile data requires more storage than this
* amount, it is split into multiple slices.
* This field must not be larger than
* GB_ADDR_CONFIG.DRAM_ROW_SIZE.
* Only applies to 2D and 3D tiling modes.
* For color render targets, TILE_SPLIT >= 256B.
*/
enum tile_split_values tile_split;
enum tile_split_values tile_split_c;
/* Specifies the addressing within a tile.
* 0x0 - DISPLAY_MICRO_TILING
* 0x1 - THIN_MICRO_TILING
* 0x2 - DEPTH_MICRO_TILING
* 0x3 - ROTATED_MICRO_TILING
*/
enum tile_mode_values tile_mode;
enum tile_mode_values tile_mode_c;
/* Specifies the number of pipes and how they are
* interleaved in the surface.
* Refer to memory addressing document for complete
* details and constraints.
*/
unsigned int pipe_config;
/* Specifies the tiling mode of the surface.
* THIN tiles use an 8x8x1 tile size.
* THICK tiles use an 8x8x4 tile size.
* 2D tiling modes rotate banks for successive Z slices
* 3D tiling modes rotate pipes and banks for Z slices
* Refer to memory addressing document for complete
* details and constraints.
*/
enum array_mode_values array_mode;
} gfx8;
struct {
enum swizzle_mode_values swizzle;
unsigned int num_pipes;
unsigned int max_compressed_frags;
unsigned int pipe_interleave;
struct {
enum swizzle_mode_values swizzle;
unsigned int num_pipes;
unsigned int max_compressed_frags;
unsigned int pipe_interleave;
unsigned int num_banks;
unsigned int num_shader_engines;
unsigned int num_rb_per_se;
bool shaderEnable;
unsigned int num_banks;
unsigned int num_shader_engines;
unsigned int num_rb_per_se;
bool shaderEnable;
bool meta_linear;
bool rb_aligned;
bool pipe_aligned;
unsigned int num_pkrs;
} gfx9;/*gfx9, gfx10 and above*/
struct {
enum swizzle_mode_addr3_values swizzle;
} gfx_addr3;/*gfx with addr3 and above*/
bool meta_linear;
bool rb_aligned;
bool pipe_aligned;
unsigned int num_pkrs;
} gfx9;/*gfx9, gfx10 and above*/
struct {
enum swizzle_mode_addr3_values swizzle;
} gfx_addr3;/*gfx with addr3 and above*/
};
};
/* Rotation angle */
@@ -975,6 +987,9 @@ struct dc_crtc_timing {
struct dc_crtc_timing_flags flags;
uint32_t dsc_fixed_bits_per_pixel_x16; /* DSC target bitrate in 1/16 of bpp (e.g. 128 -> 8bpp) */
struct dc_dsc_config dsc_cfg;
/* The number of pixels that HBlank has been expanded by from the original EDID timing. */
uint32_t expanded_hblank;
};
enum trigger_delay {

View File

@@ -56,7 +56,7 @@ struct dc_stream_status {
int plane_count;
int audio_inst;
struct timing_sync_info timing_sync_info;
struct dc_plane_state *plane_states[MAX_SURFACE_NUM];
struct dc_plane_state *plane_states[MAX_SURFACES];
bool is_abm_supported;
struct mall_stream_config mall_stream_config;
bool fpo_in_use;
@@ -539,16 +539,24 @@ bool dc_stream_forward_crc_window(struct dc_stream_state *stream,
struct rect *rect,
uint8_t phy_id,
bool is_stop);
bool dc_stream_forward_multiple_crc_window(struct dc_stream_state *stream,
struct crc_window *window,
uint8_t phy_id,
bool stop);
#endif
bool dc_stream_configure_crc(struct dc *dc,
struct dc_stream_state *stream,
struct crc_params *crc_window,
bool enable,
bool continuous);
bool continuous,
uint8_t idx,
bool reset);
bool dc_stream_get_crc(struct dc *dc,
struct dc_stream_state *stream,
uint8_t idx,
uint32_t *r_cr,
uint32_t *g_y,
uint32_t *b_cb);

View File

@@ -76,7 +76,6 @@ struct dc_perf_trace {
unsigned long last_entry_write;
};
#define MAX_SURFACE_NUM 6
#define NUM_PIXEL_FORMATS 10
enum tiling_mode {
@@ -875,6 +874,14 @@ struct dsc_dec_dpcd_caps {
bool is_dp; /* Decoded format */
};
struct hblank_expansion_dpcd_caps {
bool expansion_supported;
bool reduction_supported;
bool buffer_unit_bytes; /* True: buffer size in bytes. False: buffer size in pixels*/
bool buffer_per_port; /* True: buffer size per port. False: buffer size per lane*/
uint32_t buffer_size; /* Add 1 to value and multiply by 32 */
};
struct dc_golden_table {
uint16_t dc_golden_table_ver;
uint32_t aux_dphy_rx_control0_val;
@@ -932,10 +939,17 @@ enum backlight_control_type {
};
#if defined(CONFIG_DRM_AMD_SECURE_DISPLAY)
#define MAX_CRC_WINDOW_NUM 2
struct otg_phy_mux {
uint8_t phy_output_num;
uint8_t otg_output_num;
};
struct crc_window {
struct rect rect;
bool enable;
};
#endif
enum dc_detect_reason {
@@ -1052,10 +1066,13 @@ enum replay_FW_Message_type {
union replay_error_status {
struct {
unsigned char STATE_TRANSITION_ERROR :1;
unsigned char LINK_CRC_ERROR :1;
unsigned char DESYNC_ERROR :1;
unsigned char RESERVED :5;
unsigned int STATE_TRANSITION_ERROR :1;
unsigned int LINK_CRC_ERROR :1;
unsigned int DESYNC_ERROR :1;
unsigned int RESERVED_3 :1;
unsigned int LOW_RR_INCORRECT_VTOTAL :1;
unsigned int NO_DOUBLED_RR :1;
unsigned int RESERVED_6_7 :2;
} bits;
unsigned char raw;
};
@@ -1102,6 +1119,8 @@ struct replay_config {
union replay_error_status replay_error_status;
/* Replay Low Hz enable Options */
union replay_low_refresh_rate_enable_options low_rr_enable_options;
/* Replay coasting vtotal is within low refresh rate range. */
bool low_rr_activated;
};
/* Replay feature flags*/
@@ -1126,10 +1145,12 @@ struct replay_settings {
uint32_t defer_update_coasting_vtotal_table[PR_COASTING_TYPE_NUM];
/* Maximum link off frame count */
uint32_t link_off_frame_count;
/* Replay pseudo vtotal for abm + ips on full screen video which can improve ips residency */
uint16_t abm_with_ips_on_full_screen_video_pseudo_vtotal;
/* Replay pseudo vtotal for low refresh rate*/
uint16_t low_rr_full_screen_video_pseudo_vtotal;
/* Replay last pseudo vtotal set to DMUB */
uint16_t last_pseudo_vtotal;
/* Replay desync error */
uint32_t replay_desync_error_fail_count;
};
/* To split out "global" and "per-panel" config settings.

View File

@@ -98,7 +98,7 @@ static enum mi_bits_per_pixel get_mi_bpp(
}
static enum mi_tiling_format get_mi_tiling(
union dc_tiling_info *tiling_info)
struct dc_tiling_info *tiling_info)
{
switch (tiling_info->gfx8.array_mode) {
case DC_ARRAY_1D_TILED_THIN1:
@@ -133,7 +133,7 @@ static bool is_vert_scan(enum dc_rotation_angle rotation)
static void dce_mi_program_pte_vm(
struct mem_input *mi,
enum surface_pixel_format format,
union dc_tiling_info *tiling_info,
struct dc_tiling_info *tiling_info,
enum dc_rotation_angle rotation)
{
struct dce_mem_input *dce_mi = TO_DCE_MEM_INPUT(mi);
@@ -430,7 +430,7 @@ static void dce120_mi_program_display_marks(struct mem_input *mi,
}
static void program_tiling(
struct dce_mem_input *dce_mi, const union dc_tiling_info *info)
struct dce_mem_input *dce_mi, const struct dc_tiling_info *info)
{
if (dce_mi->masks->GRPH_SW_MODE) { /* GFX9 */
REG_UPDATE_6(GRPH_CONTROL,
@@ -650,7 +650,7 @@ static void dce_mi_clear_tiling(
static void dce_mi_program_surface_config(
struct mem_input *mi,
enum surface_pixel_format format,
union dc_tiling_info *tiling_info,
struct dc_tiling_info *tiling_info,
struct plane_size *plane_size,
enum dc_rotation_angle rotation,
struct dc_plane_dcc_param *dcc,
@@ -670,7 +670,7 @@ static void dce_mi_program_surface_config(
static void dce60_mi_program_surface_config(
struct mem_input *mi,
enum surface_pixel_format format,
union dc_tiling_info *tiling_info,
struct dc_tiling_info *tiling_info,
struct plane_size *plane_size,
enum dc_rotation_angle rotation, /* not used in DCE6 */
struct dc_plane_dcc_param *dcc,

View File

@@ -63,7 +63,8 @@ void dmub_hw_lock_mgr_inbox0_cmd(struct dc_dmub_srv *dmub_srv,
bool should_use_dmub_lock(struct dc_link *link)
{
if (link->psr_settings.psr_version == DC_PSR_VERSION_SU_1)
if (link->psr_settings.psr_version == DC_PSR_VERSION_SU_1 ||
link->psr_settings.psr_version == DC_PSR_VERSION_1)
return true;
if (link->replay_settings.replay_feature_enabled)

View File

@@ -162,7 +162,7 @@ static void enable(struct dce_mem_input *mem_input110)
static void program_tiling(
struct dce_mem_input *mem_input110,
const union dc_tiling_info *info,
const struct dc_tiling_info *info,
const enum surface_pixel_format pixel_format)
{
uint32_t value = 0;
@@ -523,7 +523,7 @@ static const unsigned int dvmm_Hw_Setting_Linear[4][9] = {
/* Helper to get table entry from surface info */
static const unsigned int *get_dvmm_hw_setting(
union dc_tiling_info *tiling_info,
struct dc_tiling_info *tiling_info,
enum surface_pixel_format format,
bool chroma)
{
@@ -563,7 +563,7 @@ static const unsigned int *get_dvmm_hw_setting(
static void dce_mem_input_v_program_pte_vm(
struct mem_input *mem_input,
enum surface_pixel_format format,
union dc_tiling_info *tiling_info,
struct dc_tiling_info *tiling_info,
enum dc_rotation_angle rotation)
{
struct dce_mem_input *mem_input110 = TO_DCE_MEM_INPUT(mem_input);
@@ -636,7 +636,7 @@ static void dce_mem_input_v_program_pte_vm(
static void dce_mem_input_v_program_surface_config(
struct mem_input *mem_input,
enum surface_pixel_format format,
union dc_tiling_info *tiling_info,
struct dc_tiling_info *tiling_info,
struct plane_size *plane_size,
enum dc_rotation_angle rotation,
struct dc_plane_dcc_param *dcc,

View File

@@ -2127,70 +2127,131 @@ bool dce110_configure_crc(struct timing_generator *tg,
cntl_addr = CRTC_REG(mmCRTC_CRC_CNTL);
/* First, disable CRC before we configure it. */
dm_write_reg(tg->ctx, cntl_addr, 0);
if (!params->enable || params->reset)
/* First, disable CRC before we configure it. */
dm_write_reg(tg->ctx, cntl_addr, 0);
if (!params->enable)
return true;
/* Program frame boundaries */
/* Window A x axis start and end. */
value = 0;
addr = CRTC_REG(mmCRTC_CRC0_WINDOWA_X_CONTROL);
set_reg_field_value(value, params->windowa_x_start,
CRTC_CRC0_WINDOWA_X_CONTROL,
CRTC_CRC0_WINDOWA_X_START);
set_reg_field_value(value, params->windowa_x_end,
CRTC_CRC0_WINDOWA_X_CONTROL,
CRTC_CRC0_WINDOWA_X_END);
dm_write_reg(tg->ctx, addr, value);
switch (params->crc_eng_inst) {
case 0:
/* Window A x axis start and end. */
value = 0;
addr = CRTC_REG(mmCRTC_CRC0_WINDOWA_X_CONTROL);
set_reg_field_value(value, params->windowa_x_start,
CRTC_CRC0_WINDOWA_X_CONTROL,
CRTC_CRC0_WINDOWA_X_START);
set_reg_field_value(value, params->windowa_x_end,
CRTC_CRC0_WINDOWA_X_CONTROL,
CRTC_CRC0_WINDOWA_X_END);
dm_write_reg(tg->ctx, addr, value);
/* Window A y axis start and end. */
value = 0;
addr = CRTC_REG(mmCRTC_CRC0_WINDOWA_Y_CONTROL);
set_reg_field_value(value, params->windowa_y_start,
CRTC_CRC0_WINDOWA_Y_CONTROL,
CRTC_CRC0_WINDOWA_Y_START);
set_reg_field_value(value, params->windowa_y_end,
CRTC_CRC0_WINDOWA_Y_CONTROL,
CRTC_CRC0_WINDOWA_Y_END);
dm_write_reg(tg->ctx, addr, value);
/* Window A y axis start and end. */
value = 0;
addr = CRTC_REG(mmCRTC_CRC0_WINDOWA_Y_CONTROL);
set_reg_field_value(value, params->windowa_y_start,
CRTC_CRC0_WINDOWA_Y_CONTROL,
CRTC_CRC0_WINDOWA_Y_START);
set_reg_field_value(value, params->windowa_y_end,
CRTC_CRC0_WINDOWA_Y_CONTROL,
CRTC_CRC0_WINDOWA_Y_END);
dm_write_reg(tg->ctx, addr, value);
/* Window B x axis start and end. */
value = 0;
addr = CRTC_REG(mmCRTC_CRC0_WINDOWB_X_CONTROL);
set_reg_field_value(value, params->windowb_x_start,
CRTC_CRC0_WINDOWB_X_CONTROL,
CRTC_CRC0_WINDOWB_X_START);
set_reg_field_value(value, params->windowb_x_end,
CRTC_CRC0_WINDOWB_X_CONTROL,
CRTC_CRC0_WINDOWB_X_END);
dm_write_reg(tg->ctx, addr, value);
/* Window B x axis start and end. */
value = 0;
addr = CRTC_REG(mmCRTC_CRC0_WINDOWB_X_CONTROL);
set_reg_field_value(value, params->windowb_x_start,
CRTC_CRC0_WINDOWB_X_CONTROL,
CRTC_CRC0_WINDOWB_X_START);
set_reg_field_value(value, params->windowb_x_end,
CRTC_CRC0_WINDOWB_X_CONTROL,
CRTC_CRC0_WINDOWB_X_END);
dm_write_reg(tg->ctx, addr, value);
/* Window B y axis start and end. */
value = 0;
addr = CRTC_REG(mmCRTC_CRC0_WINDOWB_Y_CONTROL);
set_reg_field_value(value, params->windowb_y_start,
CRTC_CRC0_WINDOWB_Y_CONTROL,
CRTC_CRC0_WINDOWB_Y_START);
set_reg_field_value(value, params->windowb_y_end,
CRTC_CRC0_WINDOWB_Y_CONTROL,
CRTC_CRC0_WINDOWB_Y_END);
dm_write_reg(tg->ctx, addr, value);
/* Window B y axis start and end. */
value = 0;
addr = CRTC_REG(mmCRTC_CRC0_WINDOWB_Y_CONTROL);
set_reg_field_value(value, params->windowb_y_start,
CRTC_CRC0_WINDOWB_Y_CONTROL,
CRTC_CRC0_WINDOWB_Y_START);
set_reg_field_value(value, params->windowb_y_end,
CRTC_CRC0_WINDOWB_Y_CONTROL,
CRTC_CRC0_WINDOWB_Y_END);
dm_write_reg(tg->ctx, addr, value);
/* Set crc mode and selection, and enable. Only using CRC0*/
value = 0;
set_reg_field_value(value, params->continuous_mode ? 1 : 0,
CRTC_CRC_CNTL, CRTC_CRC_CONT_EN);
set_reg_field_value(value, params->selection,
CRTC_CRC_CNTL, CRTC_CRC0_SELECT);
set_reg_field_value(value, 1, CRTC_CRC_CNTL, CRTC_CRC_EN);
dm_write_reg(tg->ctx, cntl_addr, value);
/* Set crc mode and selection, and enable.*/
value = 0;
set_reg_field_value(value, params->continuous_mode ? 1 : 0,
CRTC_CRC_CNTL, CRTC_CRC_CONT_EN);
set_reg_field_value(value, params->selection,
CRTC_CRC_CNTL, CRTC_CRC0_SELECT);
set_reg_field_value(value, 1, CRTC_CRC_CNTL, CRTC_CRC_EN);
dm_write_reg(tg->ctx, cntl_addr, value);
break;
case 1:
/* Window A x axis start and end. */
value = 0;
addr = CRTC_REG(mmCRTC_CRC1_WINDOWA_X_CONTROL);
set_reg_field_value(value, params->windowa_x_start,
CRTC_CRC1_WINDOWA_X_CONTROL,
CRTC_CRC1_WINDOWA_X_START);
set_reg_field_value(value, params->windowa_x_end,
CRTC_CRC1_WINDOWA_X_CONTROL,
CRTC_CRC1_WINDOWA_X_END);
dm_write_reg(tg->ctx, addr, value);
/* Window A y axis start and end. */
value = 0;
addr = CRTC_REG(mmCRTC_CRC1_WINDOWA_Y_CONTROL);
set_reg_field_value(value, params->windowa_y_start,
CRTC_CRC1_WINDOWA_Y_CONTROL,
CRTC_CRC1_WINDOWA_Y_START);
set_reg_field_value(value, params->windowa_y_end,
CRTC_CRC1_WINDOWA_Y_CONTROL,
CRTC_CRC1_WINDOWA_Y_END);
dm_write_reg(tg->ctx, addr, value);
/* Window B x axis start and end. */
value = 0;
addr = CRTC_REG(mmCRTC_CRC1_WINDOWB_X_CONTROL);
set_reg_field_value(value, params->windowb_x_start,
CRTC_CRC1_WINDOWB_X_CONTROL,
CRTC_CRC1_WINDOWB_X_START);
set_reg_field_value(value, params->windowb_x_end,
CRTC_CRC1_WINDOWB_X_CONTROL,
CRTC_CRC1_WINDOWB_X_END);
dm_write_reg(tg->ctx, addr, value);
/* Window B y axis start and end. */
value = 0;
addr = CRTC_REG(mmCRTC_CRC1_WINDOWB_Y_CONTROL);
set_reg_field_value(value, params->windowb_y_start,
CRTC_CRC1_WINDOWB_Y_CONTROL,
CRTC_CRC1_WINDOWB_Y_START);
set_reg_field_value(value, params->windowb_y_end,
CRTC_CRC1_WINDOWB_Y_CONTROL,
CRTC_CRC1_WINDOWB_Y_END);
dm_write_reg(tg->ctx, addr, value);
/* Set crc mode and selection, and enable.*/
value = 0;
set_reg_field_value(value, params->continuous_mode ? 1 : 0,
CRTC_CRC_CNTL, CRTC_CRC_CONT_EN);
set_reg_field_value(value, params->selection,
CRTC_CRC_CNTL, CRTC_CRC1_SELECT);
set_reg_field_value(value, 1, CRTC_CRC_CNTL, CRTC_CRC_EN);
dm_write_reg(tg->ctx, cntl_addr, value);
break;
default:
return false;
}
return true;
}
bool dce110_get_crc(struct timing_generator *tg,
bool dce110_get_crc(struct timing_generator *tg, uint8_t idx,
uint32_t *r_cr, uint32_t *g_y, uint32_t *b_cb)
{
uint32_t addr = 0;
@@ -2206,14 +2267,30 @@ bool dce110_get_crc(struct timing_generator *tg,
if (!field)
return false;
addr = CRTC_REG(mmCRTC_CRC0_DATA_RG);
value = dm_read_reg(tg->ctx, addr);
*r_cr = get_reg_field_value(value, CRTC_CRC0_DATA_RG, CRC0_R_CR);
*g_y = get_reg_field_value(value, CRTC_CRC0_DATA_RG, CRC0_G_Y);
switch (idx) {
case 0:
addr = CRTC_REG(mmCRTC_CRC0_DATA_RG);
value = dm_read_reg(tg->ctx, addr);
*r_cr = get_reg_field_value(value, CRTC_CRC0_DATA_RG, CRC0_R_CR);
*g_y = get_reg_field_value(value, CRTC_CRC0_DATA_RG, CRC0_G_Y);
addr = CRTC_REG(mmCRTC_CRC0_DATA_B);
value = dm_read_reg(tg->ctx, addr);
*b_cb = get_reg_field_value(value, CRTC_CRC0_DATA_B, CRC0_B_CB);
addr = CRTC_REG(mmCRTC_CRC0_DATA_B);
value = dm_read_reg(tg->ctx, addr);
*b_cb = get_reg_field_value(value, CRTC_CRC0_DATA_B, CRC0_B_CB);
break;
case 1:
addr = CRTC_REG(mmCRTC_CRC1_DATA_RG);
value = dm_read_reg(tg->ctx, addr);
*r_cr = get_reg_field_value(value, CRTC_CRC1_DATA_RG, CRC1_R_CR);
*g_y = get_reg_field_value(value, CRTC_CRC1_DATA_RG, CRC1_G_Y);
addr = CRTC_REG(mmCRTC_CRC1_DATA_B);
value = dm_read_reg(tg->ctx, addr);
*b_cb = get_reg_field_value(value, CRTC_CRC1_DATA_B, CRC1_B_CB);
break;
default:
return false;
}
return true;
}

View File

@@ -286,7 +286,7 @@ bool dce110_arm_vert_intr(
bool dce110_configure_crc(struct timing_generator *tg,
const struct crc_params *params);
bool dce110_get_crc(struct timing_generator *tg,
bool dce110_get_crc(struct timing_generator *tg, uint8_t idx,
uint32_t *r_cr, uint32_t *g_y, uint32_t *b_cb);
bool dce110_is_two_pixels_per_container(const struct dc_crtc_timing *timing);

View File

@@ -1100,45 +1100,79 @@ static bool dce120_configure_crc(struct timing_generator *tg,
if (!dce120_is_tg_enabled(tg))
return false;
/* First, disable CRC before we configure it. */
dm_write_reg_soc15(tg->ctx, mmCRTC0_CRTC_CRC_CNTL,
tg110->offsets.crtc, 0);
if (!params->enable || params->reset)
/* First, disable CRC before we configure it. */
dm_write_reg_soc15(tg->ctx, mmCRTC0_CRTC_CRC_CNTL,
tg110->offsets.crtc, 0);
if (!params->enable)
return true;
/* Program frame boundaries */
/* Window A x axis start and end. */
CRTC_REG_UPDATE_2(CRTC0_CRTC_CRC0_WINDOWA_X_CONTROL,
CRTC_CRC0_WINDOWA_X_START, params->windowa_x_start,
CRTC_CRC0_WINDOWA_X_END, params->windowa_x_end);
switch (params->crc_eng_inst) {
case 0:
/* Window A x axis start and end. */
CRTC_REG_UPDATE_2(CRTC0_CRTC_CRC0_WINDOWA_X_CONTROL,
CRTC_CRC0_WINDOWA_X_START, params->windowa_x_start,
CRTC_CRC0_WINDOWA_X_END, params->windowa_x_end);
/* Window A y axis start and end. */
CRTC_REG_UPDATE_2(CRTC0_CRTC_CRC0_WINDOWA_Y_CONTROL,
CRTC_CRC0_WINDOWA_Y_START, params->windowa_y_start,
CRTC_CRC0_WINDOWA_Y_END, params->windowa_y_end);
/* Window A y axis start and end. */
CRTC_REG_UPDATE_2(CRTC0_CRTC_CRC0_WINDOWA_Y_CONTROL,
CRTC_CRC0_WINDOWA_Y_START, params->windowa_y_start,
CRTC_CRC0_WINDOWA_Y_END, params->windowa_y_end);
/* Window B x axis start and end. */
CRTC_REG_UPDATE_2(CRTC0_CRTC_CRC0_WINDOWB_X_CONTROL,
CRTC_CRC0_WINDOWB_X_START, params->windowb_x_start,
CRTC_CRC0_WINDOWB_X_END, params->windowb_x_end);
/* Window B x axis start and end. */
CRTC_REG_UPDATE_2(CRTC0_CRTC_CRC0_WINDOWB_X_CONTROL,
CRTC_CRC0_WINDOWB_X_START, params->windowb_x_start,
CRTC_CRC0_WINDOWB_X_END, params->windowb_x_end);
/* Window B y axis start and end. */
CRTC_REG_UPDATE_2(CRTC0_CRTC_CRC0_WINDOWB_Y_CONTROL,
CRTC_CRC0_WINDOWB_Y_START, params->windowb_y_start,
CRTC_CRC0_WINDOWB_Y_END, params->windowb_y_end);
/* Window B y axis start and end. */
CRTC_REG_UPDATE_2(CRTC0_CRTC_CRC0_WINDOWB_Y_CONTROL,
CRTC_CRC0_WINDOWB_Y_START, params->windowb_y_start,
CRTC_CRC0_WINDOWB_Y_END, params->windowb_y_end);
/* Set crc mode and selection, and enable. Only using CRC0*/
CRTC_REG_UPDATE_3(CRTC0_CRTC_CRC_CNTL,
CRTC_CRC_EN, params->continuous_mode ? 1 : 0,
CRTC_CRC0_SELECT, params->selection,
CRTC_CRC_EN, 1);
/* Set crc mode and selection, and enable.*/
CRTC_REG_UPDATE_3(CRTC0_CRTC_CRC_CNTL,
CRTC_CRC_CONT_EN, params->continuous_mode ? 1 : 0,
CRTC_CRC0_SELECT, params->selection,
CRTC_CRC_EN, 1);
break;
case 1:
/* Window A x axis start and end. */
CRTC_REG_UPDATE_2(CRTC0_CRTC_CRC1_WINDOWA_X_CONTROL,
CRTC_CRC1_WINDOWA_X_START, params->windowa_x_start,
CRTC_CRC1_WINDOWA_X_END, params->windowa_x_end);
/* Window A y axis start and end. */
CRTC_REG_UPDATE_2(CRTC0_CRTC_CRC1_WINDOWA_Y_CONTROL,
CRTC_CRC1_WINDOWA_Y_START, params->windowa_y_start,
CRTC_CRC1_WINDOWA_Y_END, params->windowa_y_end);
/* Window B x axis start and end. */
CRTC_REG_UPDATE_2(CRTC0_CRTC_CRC1_WINDOWB_X_CONTROL,
CRTC_CRC1_WINDOWB_X_START, params->windowb_x_start,
CRTC_CRC1_WINDOWB_X_END, params->windowb_x_end);
/* Window B y axis start and end. */
CRTC_REG_UPDATE_2(CRTC0_CRTC_CRC1_WINDOWB_Y_CONTROL,
CRTC_CRC1_WINDOWB_Y_START, params->windowb_y_start,
CRTC_CRC1_WINDOWB_Y_END, params->windowb_y_end);
/* Set crc mode and selection, and enable */
CRTC_REG_UPDATE_3(CRTC0_CRTC_CRC_CNTL,
CRTC_CRC_CONT_EN, params->continuous_mode ? 1 : 0,
CRTC_CRC1_SELECT, params->selection,
CRTC_CRC_EN, 1);
break;
default:
return false;
}
return true;
}
static bool dce120_get_crc(struct timing_generator *tg, uint32_t *r_cr,
uint32_t *g_y, uint32_t *b_cb)
static bool dce120_get_crc(struct timing_generator *tg, uint8_t idx,
uint32_t *r_cr, uint32_t *g_y, uint32_t *b_cb)
{
struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg);
uint32_t value, field;
@@ -1151,14 +1185,30 @@ static bool dce120_get_crc(struct timing_generator *tg, uint32_t *r_cr,
if (!field)
return false;
value = dm_read_reg_soc15(tg->ctx, mmCRTC0_CRTC_CRC0_DATA_RG,
tg110->offsets.crtc);
*r_cr = get_reg_field_value(value, CRTC0_CRTC_CRC0_DATA_RG, CRC0_R_CR);
*g_y = get_reg_field_value(value, CRTC0_CRTC_CRC0_DATA_RG, CRC0_G_Y);
switch (idx) {
case 0:
value = dm_read_reg_soc15(tg->ctx, mmCRTC0_CRTC_CRC0_DATA_RG,
tg110->offsets.crtc);
*r_cr = get_reg_field_value(value, CRTC0_CRTC_CRC0_DATA_RG, CRC0_R_CR);
*g_y = get_reg_field_value(value, CRTC0_CRTC_CRC0_DATA_RG, CRC0_G_Y);
value = dm_read_reg_soc15(tg->ctx, mmCRTC0_CRTC_CRC0_DATA_B,
tg110->offsets.crtc);
*b_cb = get_reg_field_value(value, CRTC0_CRTC_CRC0_DATA_B, CRC0_B_CB);
value = dm_read_reg_soc15(tg->ctx, mmCRTC0_CRTC_CRC0_DATA_B,
tg110->offsets.crtc);
*b_cb = get_reg_field_value(value, CRTC0_CRTC_CRC0_DATA_B, CRC0_B_CB);
break;
case 1:
value = dm_read_reg_soc15(tg->ctx, mmCRTC0_CRTC_CRC1_DATA_RG,
tg110->offsets.crtc);
*r_cr = get_reg_field_value(value, CRTC0_CRTC_CRC1_DATA_RG, CRC1_R_CR);
*g_y = get_reg_field_value(value, CRTC0_CRTC_CRC1_DATA_RG, CRC1_G_Y);
value = dm_read_reg_soc15(tg->ctx, mmCRTC0_CRTC_CRC1_DATA_B,
tg110->offsets.crtc);
*b_cb = get_reg_field_value(value, CRTC0_CRTC_CRC1_DATA_B, CRC1_B_CB);
break;
default:
return false;
}
return true;
}

View File

@@ -653,8 +653,9 @@ void dcn31_link_encoder_get_max_link_cap(struct link_encoder *enc, struct dc_lin
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)
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);
return;

View File

@@ -28,6 +28,7 @@
#include "link_encoder.h"
#include "dcn31/dcn31_dio_link_encoder.h"
#include "dcn35_dio_link_encoder.h"
#include "dc_dmub_srv.h"
#define CTX \
enc10->base.ctx
#define DC_LOGGER \
@@ -159,6 +160,8 @@ static const struct link_encoder_funcs dcn35_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,
.enable_dpia_output = dcn35_link_encoder_enable_dpia_output,
.disable_dpia_output = dcn35_link_encoder_disable_dpia_output,
};
void dcn35_link_encoder_construct(
@@ -265,3 +268,80 @@ void dcn35_link_encoder_construct(
enc10->base.features.flags.bits.HDMI_6GB_EN = 0;
}
/* DPIA equivalent of link_transmitter_control. */
static bool link_dpia_control(struct dc_context *dc_ctx,
struct dmub_cmd_dig_dpia_control_data *dpia_control)
{
union dmub_rb_cmd cmd;
memset(&cmd, 0, sizeof(cmd));
cmd.dig1_dpia_control.header.type = DMUB_CMD__DPIA;
cmd.dig1_dpia_control.header.sub_type =
DMUB_CMD__DPIA_DIG1_DPIA_CONTROL;
cmd.dig1_dpia_control.header.payload_bytes =
sizeof(cmd.dig1_dpia_control) -
sizeof(cmd.dig1_dpia_control.header);
cmd.dig1_dpia_control.dpia_control = *dpia_control;
dc_wake_and_execute_dmub_cmd(dc_ctx, &cmd, DM_DMUB_WAIT_TYPE_WAIT);
return true;
}
static void link_encoder_disable(struct dcn10_link_encoder *enc10)
{
/* reset training complete */
REG_UPDATE(DP_LINK_CNTL, DP_LINK_TRAINING_COMPLETE, 0);
}
void dcn35_link_encoder_enable_dpia_output(
struct link_encoder *enc,
const struct dc_link_settings *link_settings,
uint8_t dpia_id,
uint8_t digmode,
uint8_t fec_rdy)
{
struct dcn10_link_encoder *enc10 = TO_DCN10_LINK_ENC(enc);
struct dmub_cmd_dig_dpia_control_data dpia_control = { 0 };
enc1_configure_encoder(enc10, link_settings);
dpia_control.action = (uint8_t)TRANSMITTER_CONTROL_ENABLE;
dpia_control.enc_id = enc->preferred_engine;
dpia_control.mode_laneset.digmode = digmode;
dpia_control.lanenum = (uint8_t)link_settings->lane_count;
dpia_control.symclk_10khz = link_settings->link_rate *
LINK_RATE_REF_FREQ_IN_KHZ / 10;
/* DIG_BE_CNTL.DIG_HPD_SELECT set to 5 (hpdsel - 1) to indicate HPD pin unused by DPIA. */
dpia_control.hpdsel = 6;
dpia_control.dpia_id = dpia_id;
dpia_control.fec_rdy = fec_rdy;
DC_LOG_DEBUG("%s: DPIA(%d) - enc_id(%d)\n", __func__, dpia_control.dpia_id, dpia_control.enc_id);
link_dpia_control(enc->ctx, &dpia_control);
}
void dcn35_link_encoder_disable_dpia_output(
struct link_encoder *enc,
uint8_t dpia_id,
uint8_t digmode)
{
struct dcn10_link_encoder *enc10 = TO_DCN10_LINK_ENC(enc);
struct dmub_cmd_dig_dpia_control_data dpia_control = { 0 };
if (enc->funcs->is_dig_enabled && !enc->funcs->is_dig_enabled(enc))
return;
dpia_control.action = (uint8_t)TRANSMITTER_CONTROL_DISABLE;
dpia_control.enc_id = enc->preferred_engine;
dpia_control.mode_laneset.digmode = digmode;
dpia_control.dpia_id = dpia_id;
DC_LOG_DEBUG("%s: DPIA(%d) - enc_id(%d)\n", __func__, dpia_control.dpia_id, dpia_control.enc_id);
link_dpia_control(enc->ctx, &dpia_control);
link_encoder_disable(enc10);
}

View File

@@ -144,4 +144,22 @@ bool dcn35_is_dig_enabled(struct link_encoder *enc);
enum signal_type dcn35_get_dig_mode(struct link_encoder *enc);
void dcn35_link_encoder_setup(struct link_encoder *enc, enum signal_type signal);
/*
* Enable DP transmitter and its encoder for dpia port.
*/
void dcn35_link_encoder_enable_dpia_output(
struct link_encoder *enc,
const struct dc_link_settings *link_settings,
uint8_t dpia_id,
uint8_t digmode,
uint8_t fec_rdy);
/*
* Disable transmitter and its encoder for dpia port.
*/
void dcn35_link_encoder_disable_dpia_output(
struct link_encoder *enc,
uint8_t dpia_id,
uint8_t digmode);
#endif /* __DC_LINK_ENCODER__DCN35_H__ */

View File

@@ -158,6 +158,11 @@ bool dm_helpers_dp_write_dsc_enable(
const struct dc_stream_state *stream,
bool enable
);
bool dm_helpers_dp_write_hblank_reduction(
struct dc_context *ctx,
const struct dc_stream_state *stream);
bool dm_helpers_is_dp_sink_present(
struct dc_link *link);

View File

@@ -1595,6 +1595,7 @@ double dml32_TruncToValidBPP(
unsigned int NonDSCBPP0;
unsigned int NonDSCBPP1;
unsigned int NonDSCBPP2;
unsigned int NonDSCBPP3 = BPP_INVALID;
if (Format == dm_420) {
NonDSCBPP0 = 12;
@@ -1603,6 +1604,7 @@ double dml32_TruncToValidBPP(
MinDSCBPP = 6;
MaxDSCBPP = 1.5 * DSCInputBitPerComponent - 1.0 / 16;
} else if (Format == dm_444) {
NonDSCBPP3 = 18;
NonDSCBPP0 = 24;
NonDSCBPP1 = 30;
NonDSCBPP2 = 36;
@@ -1667,6 +1669,8 @@ double dml32_TruncToValidBPP(
return NonDSCBPP1;
else if (MaxLinkBPP >= NonDSCBPP0)
return 16.0;
else if ((Output == dm_dp2p0 || Output == dm_dp) && NonDSCBPP3 != BPP_INVALID && MaxLinkBPP >= NonDSCBPP3)
return NonDSCBPP3; // Special case to allow 6bpc RGB for DP connections.
else
return BPP_INVALID;
}

View File

@@ -195,9 +195,9 @@ struct _vcs_dpi_soc_bounding_box_st dcn3_5_soc = {
.dcn_downspread_percent = 0.5,
.gpuvm_min_page_size_bytes = 4096,
.hostvm_min_page_size_bytes = 4096,
.do_urgent_latency_adjustment = 1,
.do_urgent_latency_adjustment = 0,
.urgent_latency_adjustment_fabric_clock_component_us = 0,
.urgent_latency_adjustment_fabric_clock_reference_mhz = 3000,
.urgent_latency_adjustment_fabric_clock_reference_mhz = 0,
};
void dcn35_build_wm_range_table_fpu(struct clk_mgr *clk_mgr)

View File

@@ -66,11 +66,15 @@ static inline double dml_max5(double a, double b, double c, double d, double e)
static inline double dml_ceil(double a, double granularity)
{
if (granularity == 0)
return 0;
return (double) dcn_bw_ceil2(a, granularity);
}
static inline double dml_floor(double a, double granularity)
{
if (granularity == 0)
return 0;
return (double) dcn_bw_floor2(a, granularity);
}
@@ -114,11 +118,15 @@ static inline double dml_ceil_2(double f)
static inline double dml_ceil_ex(double x, double granularity)
{
if (granularity == 0)
return 0;
return (double) dcn_bw_ceil2(x, granularity);
}
static inline double dml_floor_ex(double x, double granularity)
{
if (granularity == 0)
return 0;
return (double) dcn_bw_floor2(x, granularity);
}

View File

@@ -29,7 +29,11 @@ dml2_rcflags := $(CC_FLAGS_NO_FPU)
ifneq ($(CONFIG_FRAME_WARN),0)
ifeq ($(filter y,$(CONFIG_KASAN)$(CONFIG_KCSAN)),y)
ifeq ($(CONFIG_CC_IS_CLANG)$(CONFIG_COMPILE_TEST),yy)
frame_warn_flag := -Wframe-larger-than=4096
else
frame_warn_flag := -Wframe-larger-than=3072
endif
else
frame_warn_flag := -Wframe-larger-than=2048
endif

View File

@@ -10,7 +10,6 @@
#include "dml21_utils.h"
#include "dml21_translation_helper.h"
#include "bounding_boxes/dcn4_soc_bb.h"
#include "bounding_boxes/dcn3_soc_bb.h"
static void dml21_init_socbb_params(struct dml2_initialize_instance_in_out *dml_init,
const struct dml2_configuration_options *config,
@@ -20,10 +19,6 @@ static void dml21_init_socbb_params(struct dml2_initialize_instance_in_out *dml_
const struct dml2_soc_qos_parameters *qos_params;
switch (in_dc->ctx->dce_version) {
case DCN_VERSION_3_2: // TODO : Temporary for N-1 validation. Remove this after N-1 validation phase is complete.
soc_bb = &dml2_socbb_dcn31;
qos_params = &dml_dcn31_soc_qos_params;
break;
case DCN_VERSION_4_01:
default:
if (config->bb_from_dmub)
@@ -60,9 +55,6 @@ static void dml21_init_ip_params(struct dml2_initialize_instance_in_out *dml_ini
const struct dml2_ip_capabilities *ip_caps;
switch (in_dc->ctx->dce_version) {
case DCN_VERSION_3_2: // TODO : Temporary for N-1 validation. Remove this after N-1 validation phase is complete.
ip_caps = &dml2_dcn31_max_ip_caps;
break;
case DCN_VERSION_4_01:
default:
ip_caps = &dml2_dcn401_max_ip_caps;
@@ -302,12 +294,17 @@ void dml21_apply_soc_bb_overrides(struct dml2_initialize_instance_in_out *dml_in
dml_soc_bb->power_management_parameters.stutter_exit_latency_us =
(in_dc->ctx->dc_bios->bb_info.dram_sr_exit_latency_100ns + 9) / 10;
if (in_dc->ctx->dc_bios->vram_info.num_chans) {
if (dc_bw_params->num_channels) {
dml_clk_table->dram_config.channel_count = dc_bw_params->num_channels;
dml_soc_bb->mall_allocated_for_dcn_mbytes = in_dc->caps.mall_size_total / 1048576;
} else if (in_dc->ctx->dc_bios->vram_info.num_chans) {
dml_clk_table->dram_config.channel_count = in_dc->ctx->dc_bios->vram_info.num_chans;
dml_soc_bb->mall_allocated_for_dcn_mbytes = in_dc->caps.mall_size_total / 1048576;
}
if (in_dc->ctx->dc_bios->vram_info.dram_channel_width_bytes) {
if (dc_bw_params->dram_channel_width_bytes) {
dml_clk_table->dram_config.channel_width_bytes = dc_bw_params->dram_channel_width_bytes;
} else if (in_dc->ctx->dc_bios->vram_info.dram_channel_width_bytes) {
dml_clk_table->dram_config.channel_width_bytes = in_dc->ctx->dc_bios->vram_info.dram_channel_width_bytes;
}
@@ -721,11 +718,21 @@ static void populate_dml21_surface_config_from_plane_state(
surface->dcc.informative.fraction_of_zero_size_request_plane1 = plane_state->dcc.independent_64b_blks_c;
surface->dcc.plane0.pitch = plane_state->dcc.meta_pitch;
surface->dcc.plane1.pitch = plane_state->dcc.meta_pitch_c;
if (in_dc->ctx->dce_version < DCN_VERSION_4_01) {
/* needed for N-1 testing */
// Update swizzle / array mode based on the gfx_format
switch (plane_state->tiling_info.gfxversion) {
case DcGfxVersion7:
case DcGfxVersion8:
// Placeholder for programming the array_mode
break;
case DcGfxVersion9:
case DcGfxVersion10:
case DcGfxVersion11:
surface->tiling = gfx9_to_dml2_swizzle_mode(plane_state->tiling_info.gfx9.swizzle);
} else {
break;
case DcGfxAddr3:
surface->tiling = gfx_addr3_to_dml2_swizzle_mode(plane_state->tiling_info.gfx_addr3.swizzle);
break;
}
}
@@ -1081,28 +1088,6 @@ void dml21_copy_clocks_to_dc_state(struct dml2_context *in_ctx, struct dc_state
context->bw_ctx.bw.dcn.clk.subvp_prefetch_fclk_khz = in_ctx->v21.mode_programming.programming->min_clocks.dcn4x.svp_prefetch_no_throttle.fclk_khz;
}
void dml21_extract_legacy_watermark_set(const struct dc *in_dc, struct dcn_watermarks *watermark, enum dml2_dchub_watermark_reg_set_index reg_set_idx, struct dml2_context *in_ctx)
{
struct dml2_core_internal_display_mode_lib *mode_lib = &in_ctx->v21.dml_init.dml2_instance->core_instance.clean_me_up.mode_lib;
double refclk_freq_in_mhz = (in_ctx->v21.display_config.overrides.hw.dlg_ref_clk_mhz > 0) ? (double)in_ctx->v21.display_config.overrides.hw.dlg_ref_clk_mhz : mode_lib->soc.dchub_refclk_mhz;
if (reg_set_idx >= DML2_DCHUB_WATERMARK_SET_NUM) {
/* invalid register set index */
return;
}
/* convert to legacy format (time in ns) */
watermark->urgent_ns = ((double)in_ctx->v21.mode_programming.programming->global_regs.wm_regs[reg_set_idx].urgent / refclk_freq_in_mhz) * 1000.0;
watermark->pte_meta_urgent_ns = ((double)in_ctx->v21.mode_programming.programming->global_regs.wm_regs[reg_set_idx].urgent / refclk_freq_in_mhz) * 1000.0;
watermark->cstate_pstate.cstate_enter_plus_exit_ns = ((double)in_ctx->v21.mode_programming.programming->global_regs.wm_regs[reg_set_idx].sr_enter / refclk_freq_in_mhz) * 1000.0;
watermark->cstate_pstate.cstate_exit_ns = ((double)in_ctx->v21.mode_programming.programming->global_regs.wm_regs[reg_set_idx].sr_exit / refclk_freq_in_mhz) * 1000.0;
watermark->cstate_pstate.pstate_change_ns = ((double)in_ctx->v21.mode_programming.programming->global_regs.wm_regs[reg_set_idx].uclk_pstate / refclk_freq_in_mhz) * 1000.0;
watermark->urgent_latency_ns = ((double)in_ctx->v21.mode_programming.programming->global_regs.wm_regs[reg_set_idx].urgent / refclk_freq_in_mhz) * 1000.0;
watermark->cstate_pstate.fclk_pstate_change_ns = ((double)in_ctx->v21.mode_programming.programming->global_regs.wm_regs[reg_set_idx].fclk_pstate / refclk_freq_in_mhz) * 1000.0;
watermark->frac_urg_bw_flip = in_ctx->v21.mode_programming.programming->global_regs.wm_regs[reg_set_idx].frac_urg_bw_flip;
watermark->frac_urg_bw_nom = in_ctx->v21.mode_programming.programming->global_regs.wm_regs[reg_set_idx].frac_urg_bw_nom;
}
static struct dml2_dchub_watermark_regs *wm_set_index_to_dc_wm_set(union dcn_watermark_set *watermarks, const enum dml2_dchub_watermark_reg_set_index wm_index)
{
struct dml2_dchub_watermark_regs *wm_regs = NULL;
@@ -1146,53 +1131,6 @@ void dml21_extract_watermark_sets(const struct dc *in_dc, union dcn_watermark_se
}
}
void dml21_populate_pipe_ctx_dlg_params(struct dml2_context *dml_ctx, struct dc_state *context, struct pipe_ctx *pipe_ctx, struct dml2_per_stream_programming *stream_programming)
{
unsigned int hactive, vactive, hblank_start, vblank_start, hblank_end, vblank_end;
struct dc_crtc_timing *timing = &pipe_ctx->stream->timing;
union dml2_global_sync_programming *global_sync = &stream_programming->global_sync;
hactive = timing->h_addressable + timing->h_border_left + timing->h_border_right + pipe_ctx->hblank_borrow;
vactive = timing->v_addressable + timing->v_border_bottom + timing->v_border_top;
hblank_start = pipe_ctx->stream->timing.h_total - pipe_ctx->stream->timing.h_front_porch;
vblank_start = pipe_ctx->stream->timing.v_total - pipe_ctx->stream->timing.v_front_porch;
hblank_end = hblank_start - timing->h_addressable - timing->h_border_left - timing->h_border_right - pipe_ctx->hblank_borrow;
vblank_end = vblank_start - timing->v_addressable - timing->v_border_top - timing->v_border_bottom;
if (dml_ctx->config.svp_pstate.callbacks.get_pipe_subvp_type(context, pipe_ctx) == SUBVP_PHANTOM) {
/* phantom has its own global sync */
global_sync = &stream_programming->phantom_stream.global_sync;
}
pipe_ctx->pipe_dlg_param.vstartup_start = global_sync->dcn4x.vstartup_lines;
pipe_ctx->pipe_dlg_param.vupdate_offset = global_sync->dcn4x.vupdate_offset_pixels;
pipe_ctx->pipe_dlg_param.vupdate_width = global_sync->dcn4x.vupdate_vupdate_width_pixels;
pipe_ctx->pipe_dlg_param.vready_offset = global_sync->dcn4x.vready_offset_pixels;
pipe_ctx->pipe_dlg_param.pstate_keepout = global_sync->dcn4x.pstate_keepout_start_lines;
pipe_ctx->pipe_dlg_param.otg_inst = pipe_ctx->stream_res.tg->inst;
pipe_ctx->pipe_dlg_param.hactive = hactive;
pipe_ctx->pipe_dlg_param.vactive = vactive;
pipe_ctx->pipe_dlg_param.htotal = pipe_ctx->stream->timing.h_total;
pipe_ctx->pipe_dlg_param.vtotal = pipe_ctx->stream->timing.v_total;
pipe_ctx->pipe_dlg_param.hblank_end = hblank_end;
pipe_ctx->pipe_dlg_param.vblank_end = vblank_end;
pipe_ctx->pipe_dlg_param.hblank_start = hblank_start;
pipe_ctx->pipe_dlg_param.vblank_start = vblank_start;
pipe_ctx->pipe_dlg_param.vfront_porch = pipe_ctx->stream->timing.v_front_porch;
pipe_ctx->pipe_dlg_param.pixel_rate_mhz = pipe_ctx->stream->timing.pix_clk_100hz / 10000.00;
pipe_ctx->pipe_dlg_param.refresh_rate = ((timing->pix_clk_100hz * 100) / timing->h_total) / timing->v_total;
pipe_ctx->pipe_dlg_param.vtotal_max = pipe_ctx->stream->adjust.v_total_max;
pipe_ctx->pipe_dlg_param.vtotal_min = pipe_ctx->stream->adjust.v_total_min;
pipe_ctx->pipe_dlg_param.recout_height = pipe_ctx->plane_res.scl_data.recout.height;
pipe_ctx->pipe_dlg_param.recout_width = pipe_ctx->plane_res.scl_data.recout.width;
pipe_ctx->pipe_dlg_param.full_recout_height = pipe_ctx->plane_res.scl_data.recout.height;
pipe_ctx->pipe_dlg_param.full_recout_width = pipe_ctx->plane_res.scl_data.recout.width;
}
void dml21_map_hw_resources(struct dml2_context *dml_ctx)
{
unsigned int i = 0;

View File

@@ -21,8 +21,6 @@ void dml21_initialize_soc_bb_params(struct dml2_initialize_instance_in_out *dml_
void dml21_initialize_ip_params(struct dml2_initialize_instance_in_out *dml_init, const struct dml2_configuration_options *config, const struct dc *in_dc);
bool dml21_map_dc_state_into_dml_display_cfg(const struct dc *in_dc, struct dc_state *context, struct dml2_context *dml_ctx);
void dml21_copy_clocks_to_dc_state(struct dml2_context *in_ctx, struct dc_state *context);
void dml21_populate_pipe_ctx_dlg_params(struct dml2_context *dml_ctx, struct dc_state *context, struct pipe_ctx *pipe_ctx, struct dml2_per_stream_programming *stream_programming);
void dml21_extract_legacy_watermark_set(const struct dc *in_dc, struct dcn_watermarks *watermark, enum dml2_dchub_watermark_reg_set_index reg_set_idx, struct dml2_context *in_ctx);
void dml21_extract_watermark_sets(const struct dc *in_dc, union dcn_watermark_set *watermarks, struct dml2_context *in_ctx);
void dml21_map_hw_resources(struct dml2_context *dml_ctx);
void dml21_get_pipe_mcache_config(struct dc_state *context, struct pipe_ctx *pipe_ctx, struct dml2_per_plane_programming *pln_prog, struct dml2_pipe_configuration_descriptor *mcache_pipe_config);

View File

@@ -142,108 +142,21 @@ int dml21_find_dc_pipes_for_plane(const struct dc *in_dc,
return num_pipes;
}
void dml21_update_pipe_ctx_dchub_regs(struct dml2_display_rq_regs *rq_regs,
struct dml2_display_dlg_regs *disp_dlg_regs,
struct dml2_display_ttu_regs *disp_ttu_regs,
struct pipe_ctx *out)
void dml21_pipe_populate_global_sync(struct dml2_context *dml_ctx,
struct dc_state *context,
struct pipe_ctx *pipe_ctx,
struct dml2_per_stream_programming *stream_programming)
{
memset(&out->rq_regs, 0, sizeof(out->rq_regs));
out->rq_regs.rq_regs_l.chunk_size = rq_regs->rq_regs_l.chunk_size;
out->rq_regs.rq_regs_l.min_chunk_size = rq_regs->rq_regs_l.min_chunk_size;
//out->rq_regs.rq_regs_l.meta_chunk_size = rq_regs->rq_regs_l.meta_chunk_size;
//out->rq_regs.rq_regs_l.min_meta_chunk_size = rq_regs->rq_regs_l.min_meta_chunk_size;
out->rq_regs.rq_regs_l.dpte_group_size = rq_regs->rq_regs_l.dpte_group_size;
out->rq_regs.rq_regs_l.mpte_group_size = rq_regs->rq_regs_l.mpte_group_size;
out->rq_regs.rq_regs_l.swath_height = rq_regs->rq_regs_l.swath_height;
out->rq_regs.rq_regs_l.pte_row_height_linear = rq_regs->rq_regs_l.pte_row_height_linear;
union dml2_global_sync_programming *global_sync = &stream_programming->global_sync;
out->rq_regs.rq_regs_c.chunk_size = rq_regs->rq_regs_c.chunk_size;
out->rq_regs.rq_regs_c.min_chunk_size = rq_regs->rq_regs_c.min_chunk_size;
//out->rq_regs.rq_regs_c.meta_chunk_size = rq_regs->rq_regs_c.meta_chunk_size;
//out->rq_regs.rq_regs_c.min_meta_chunk_size = rq_regs->rq_regs_c.min_meta_chunk_size;
out->rq_regs.rq_regs_c.dpte_group_size = rq_regs->rq_regs_c.dpte_group_size;
out->rq_regs.rq_regs_c.mpte_group_size = rq_regs->rq_regs_c.mpte_group_size;
out->rq_regs.rq_regs_c.swath_height = rq_regs->rq_regs_c.swath_height;
out->rq_regs.rq_regs_c.pte_row_height_linear = rq_regs->rq_regs_c.pte_row_height_linear;
if (dml_ctx->config.svp_pstate.callbacks.get_pipe_subvp_type(context, pipe_ctx) == SUBVP_PHANTOM) {
/* phantom has its own global sync */
global_sync = &stream_programming->phantom_stream.global_sync;
}
out->rq_regs.drq_expansion_mode = rq_regs->drq_expansion_mode;
out->rq_regs.prq_expansion_mode = rq_regs->prq_expansion_mode;
//out->rq_regs.mrq_expansion_mode = rq_regs->mrq_expansion_mode;
out->rq_regs.crq_expansion_mode = rq_regs->crq_expansion_mode;
out->rq_regs.plane1_base_address = rq_regs->plane1_base_address;
out->unbounded_req = rq_regs->unbounded_request_enabled;
memset(&out->dlg_regs, 0, sizeof(out->dlg_regs));
out->dlg_regs.refcyc_h_blank_end = disp_dlg_regs->refcyc_h_blank_end;
out->dlg_regs.dlg_vblank_end = disp_dlg_regs->dlg_vblank_end;
out->dlg_regs.min_dst_y_next_start = disp_dlg_regs->min_dst_y_next_start;
out->dlg_regs.refcyc_per_htotal = disp_dlg_regs->refcyc_per_htotal;
out->dlg_regs.refcyc_x_after_scaler = disp_dlg_regs->refcyc_x_after_scaler;
out->dlg_regs.dst_y_after_scaler = disp_dlg_regs->dst_y_after_scaler;
out->dlg_regs.dst_y_prefetch = disp_dlg_regs->dst_y_prefetch;
out->dlg_regs.dst_y_per_vm_vblank = disp_dlg_regs->dst_y_per_vm_vblank;
out->dlg_regs.dst_y_per_row_vblank = disp_dlg_regs->dst_y_per_row_vblank;
out->dlg_regs.dst_y_per_vm_flip = disp_dlg_regs->dst_y_per_vm_flip;
out->dlg_regs.dst_y_per_row_flip = disp_dlg_regs->dst_y_per_row_flip;
out->dlg_regs.ref_freq_to_pix_freq = disp_dlg_regs->ref_freq_to_pix_freq;
out->dlg_regs.vratio_prefetch = disp_dlg_regs->vratio_prefetch;
out->dlg_regs.vratio_prefetch_c = disp_dlg_regs->vratio_prefetch_c;
out->dlg_regs.refcyc_per_tdlut_group = disp_dlg_regs->refcyc_per_tdlut_group;
out->dlg_regs.refcyc_per_pte_group_vblank_l = disp_dlg_regs->refcyc_per_pte_group_vblank_l;
out->dlg_regs.refcyc_per_pte_group_vblank_c = disp_dlg_regs->refcyc_per_pte_group_vblank_c;
//out->dlg_regs.refcyc_per_meta_chunk_vblank_l = disp_dlg_regs->refcyc_per_meta_chunk_vblank_l;
//out->dlg_regs.refcyc_per_meta_chunk_vblank_c = disp_dlg_regs->refcyc_per_meta_chunk_vblank_c;
out->dlg_regs.refcyc_per_pte_group_flip_l = disp_dlg_regs->refcyc_per_pte_group_flip_l;
out->dlg_regs.refcyc_per_pte_group_flip_c = disp_dlg_regs->refcyc_per_pte_group_flip_c;
//out->dlg_regs.refcyc_per_meta_chunk_flip_l = disp_dlg_regs->refcyc_per_meta_chunk_flip_l;
//out->dlg_regs.refcyc_per_meta_chunk_flip_c = disp_dlg_regs->refcyc_per_meta_chunk_flip_c;
out->dlg_regs.dst_y_per_pte_row_nom_l = disp_dlg_regs->dst_y_per_pte_row_nom_l;
out->dlg_regs.dst_y_per_pte_row_nom_c = disp_dlg_regs->dst_y_per_pte_row_nom_c;
out->dlg_regs.refcyc_per_pte_group_nom_l = disp_dlg_regs->refcyc_per_pte_group_nom_l;
out->dlg_regs.refcyc_per_pte_group_nom_c = disp_dlg_regs->refcyc_per_pte_group_nom_c;
//out->dlg_regs.dst_y_per_meta_row_nom_l = disp_dlg_regs->dst_y_per_meta_row_nom_l;
//out->dlg_regs.dst_y_per_meta_row_nom_c = disp_dlg_regs->dst_y_per_meta_row_nom_c;
//out->dlg_regs.refcyc_per_meta_chunk_nom_l = disp_dlg_regs->refcyc_per_meta_chunk_nom_l;
//out->dlg_regs.refcyc_per_meta_chunk_nom_c = disp_dlg_regs->refcyc_per_meta_chunk_nom_c;
out->dlg_regs.refcyc_per_line_delivery_pre_l = disp_dlg_regs->refcyc_per_line_delivery_pre_l;
out->dlg_regs.refcyc_per_line_delivery_pre_c = disp_dlg_regs->refcyc_per_line_delivery_pre_c;
out->dlg_regs.refcyc_per_line_delivery_l = disp_dlg_regs->refcyc_per_line_delivery_l;
out->dlg_regs.refcyc_per_line_delivery_c = disp_dlg_regs->refcyc_per_line_delivery_c;
out->dlg_regs.refcyc_per_vm_group_vblank = disp_dlg_regs->refcyc_per_vm_group_vblank;
out->dlg_regs.refcyc_per_vm_group_flip = disp_dlg_regs->refcyc_per_vm_group_flip;
out->dlg_regs.refcyc_per_vm_req_vblank = disp_dlg_regs->refcyc_per_vm_req_vblank;
out->dlg_regs.refcyc_per_vm_req_flip = disp_dlg_regs->refcyc_per_vm_req_flip;
out->dlg_regs.dst_y_offset_cur0 = disp_dlg_regs->dst_y_offset_cur0;
out->dlg_regs.chunk_hdl_adjust_cur0 = disp_dlg_regs->chunk_hdl_adjust_cur0;
//out->dlg_regs.dst_y_offset_cur1 = disp_dlg_regs->dst_y_offset_cur1;
//out->dlg_regs.chunk_hdl_adjust_cur1 = disp_dlg_regs->chunk_hdl_adjust_cur1;
out->dlg_regs.vready_after_vcount0 = disp_dlg_regs->vready_after_vcount0;
out->dlg_regs.dst_y_delta_drq_limit = disp_dlg_regs->dst_y_delta_drq_limit;
out->dlg_regs.refcyc_per_vm_dmdata = disp_dlg_regs->refcyc_per_vm_dmdata;
out->dlg_regs.dmdata_dl_delta = disp_dlg_regs->dmdata_dl_delta;
memset(&out->ttu_regs, 0, sizeof(out->ttu_regs));
out->ttu_regs.qos_level_low_wm = disp_ttu_regs->qos_level_low_wm;
out->ttu_regs.qos_level_high_wm = disp_ttu_regs->qos_level_high_wm;
out->ttu_regs.min_ttu_vblank = disp_ttu_regs->min_ttu_vblank;
out->ttu_regs.qos_level_flip = disp_ttu_regs->qos_level_flip;
out->ttu_regs.refcyc_per_req_delivery_l = disp_ttu_regs->refcyc_per_req_delivery_l;
out->ttu_regs.refcyc_per_req_delivery_c = disp_ttu_regs->refcyc_per_req_delivery_c;
out->ttu_regs.refcyc_per_req_delivery_cur0 = disp_ttu_regs->refcyc_per_req_delivery_cur0;
//out->ttu_regs.refcyc_per_req_delivery_cur1 = disp_ttu_regs->refcyc_per_req_delivery_cur1;
out->ttu_regs.refcyc_per_req_delivery_pre_l = disp_ttu_regs->refcyc_per_req_delivery_pre_l;
out->ttu_regs.refcyc_per_req_delivery_pre_c = disp_ttu_regs->refcyc_per_req_delivery_pre_c;
out->ttu_regs.refcyc_per_req_delivery_pre_cur0 = disp_ttu_regs->refcyc_per_req_delivery_pre_cur0;
//out->ttu_regs.refcyc_per_req_delivery_pre_cur1 = disp_ttu_regs->refcyc_per_req_delivery_pre_cur1;
out->ttu_regs.qos_level_fixed_l = disp_ttu_regs->qos_level_fixed_l;
out->ttu_regs.qos_level_fixed_c = disp_ttu_regs->qos_level_fixed_c;
out->ttu_regs.qos_level_fixed_cur0 = disp_ttu_regs->qos_level_fixed_cur0;
//out->ttu_regs.qos_level_fixed_cur1 = disp_ttu_regs->qos_level_fixed_cur1;
out->ttu_regs.qos_ramp_disable_l = disp_ttu_regs->qos_ramp_disable_l;
out->ttu_regs.qos_ramp_disable_c = disp_ttu_regs->qos_ramp_disable_c;
out->ttu_regs.qos_ramp_disable_cur0 = disp_ttu_regs->qos_ramp_disable_cur0;
//out->ttu_regs.qos_ramp_disable_cur1 = disp_ttu_regs->qos_ramp_disable_cur1;
memcpy(&pipe_ctx->global_sync,
global_sync,
sizeof(union dml2_global_sync_programming));
}
void dml21_populate_mall_allocation_size(struct dc_state *context,
@@ -301,28 +214,16 @@ void dml21_program_dc_pipe(struct dml2_context *dml_ctx, struct dc_state *contex
{
unsigned int pipe_reg_index = 0;
dml21_populate_pipe_ctx_dlg_params(dml_ctx, context, pipe_ctx, stream_prog);
dml21_pipe_populate_global_sync(dml_ctx, context, pipe_ctx, stream_prog);
find_pipe_regs_idx(dml_ctx, pipe_ctx, &pipe_reg_index);
if (dml_ctx->config.svp_pstate.callbacks.get_pipe_subvp_type(context, pipe_ctx) == SUBVP_PHANTOM) {
memcpy(&pipe_ctx->hubp_regs, pln_prog->phantom_plane.pipe_regs[pipe_reg_index], sizeof(struct dml2_dchub_per_pipe_register_set));
pipe_ctx->unbounded_req = false;
/* legacy only, should be removed later */
dml21_update_pipe_ctx_dchub_regs(&pln_prog->phantom_plane.pipe_regs[pipe_reg_index]->rq_regs,
&pln_prog->phantom_plane.pipe_regs[pipe_reg_index]->dlg_regs,
&pln_prog->phantom_plane.pipe_regs[pipe_reg_index]->ttu_regs, pipe_ctx);
pipe_ctx->det_buffer_size_kb = 0;
} else {
memcpy(&pipe_ctx->hubp_regs, pln_prog->pipe_regs[pipe_reg_index], sizeof(struct dml2_dchub_per_pipe_register_set));
pipe_ctx->unbounded_req = pln_prog->pipe_regs[pipe_reg_index]->rq_regs.unbounded_request_enabled;
/* legacy only, should be removed later */
dml21_update_pipe_ctx_dchub_regs(&pln_prog->pipe_regs[pipe_reg_index]->rq_regs,
&pln_prog->pipe_regs[pipe_reg_index]->dlg_regs,
&pln_prog->pipe_regs[pipe_reg_index]->ttu_regs, pipe_ctx);
pipe_ctx->det_buffer_size_kb = pln_prog->pipe_regs[pipe_reg_index]->det_size * 64;
}

View File

@@ -18,10 +18,10 @@ struct dml2_display_ttu_regs;
int dml21_helper_find_dml_pipe_idx_by_stream_id(struct dml2_context *ctx, unsigned int stream_id);
int dml21_find_dml_pipe_idx_by_plane_id(struct dml2_context *ctx, unsigned int plane_id);
bool dml21_get_plane_id(const struct dc_state *state, const struct dc_plane_state *plane, unsigned int *plane_id);
void dml21_update_pipe_ctx_dchub_regs(struct dml2_display_rq_regs *rq_regs,
struct dml2_display_dlg_regs *disp_dlg_regs,
struct dml2_display_ttu_regs *disp_ttu_regs,
struct pipe_ctx *out);
void dml21_pipe_populate_global_sync(struct dml2_context *dml_ctx,
struct dc_state *context,
struct pipe_ctx *pipe_ctx,
struct dml2_per_stream_programming *stream_programming);
void dml21_populate_mall_allocation_size(struct dc_state *context,
struct dml2_context *in_ctx,
struct dml2_per_plane_programming *pln_prog,

View File

@@ -75,7 +75,6 @@ static void dml21_init(const struct dc *in_dc, struct dml2_context **dml_ctx, co
{
switch (in_dc->ctx->dce_version) {
case DCN_VERSION_4_01:
case DCN_VERSION_3_2: // TODO : Temporary for N-1 validation. Remove this after N-1 validation phase is complete.
(*dml_ctx)->v21.dml_init.options.project_id = dml2_project_dcn4x_stage2_auto_drr_svp;
break;
default:
@@ -233,13 +232,6 @@ static bool dml21_mode_check_and_programming(const struct dc *in_dc, struct dc_s
dml21_calculate_rq_and_dlg_params(in_dc, context, &context->res_ctx, dml_ctx, in_dc->res_pool->pipe_count);
dml21_copy_clocks_to_dc_state(dml_ctx, context);
dml21_extract_watermark_sets(in_dc, &context->bw_ctx.bw.dcn.watermarks, dml_ctx);
if (in_dc->ctx->dce_version == DCN_VERSION_3_2) {
dml21_extract_legacy_watermark_set(in_dc, &context->bw_ctx.bw.dcn.watermarks.a, DML2_DCHUB_WATERMARK_SET_A, dml_ctx);
dml21_extract_legacy_watermark_set(in_dc, &context->bw_ctx.bw.dcn.watermarks.b, DML2_DCHUB_WATERMARK_SET_A, dml_ctx);
dml21_extract_legacy_watermark_set(in_dc, &context->bw_ctx.bw.dcn.watermarks.c, DML2_DCHUB_WATERMARK_SET_A, dml_ctx);
dml21_extract_legacy_watermark_set(in_dc, &context->bw_ctx.bw.dcn.watermarks.d, DML2_DCHUB_WATERMARK_SET_A, dml_ctx);
}
dml21_build_fams2_programming(in_dc, context, dml_ctx);
}

View File

@@ -1,401 +0,0 @@
/*
* Copyright 2022 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 __DML_DML_DCN3_SOC_BB__
#define __DML_DML_DCN3_SOC_BB__
#include "dml_top_soc_parameter_types.h"
static const struct dml2_soc_qos_parameters dml_dcn31_soc_qos_params = {
.derate_table = {
.system_active_urgent = {
.dram_derate_percent_pixel = 22,
.dram_derate_percent_vm = 0,
.dram_derate_percent_pixel_and_vm = 0,
.fclk_derate_percent = 76,
.dcfclk_derate_percent = 100,
},
.system_active_average = {
.dram_derate_percent_pixel = 17,
.dram_derate_percent_vm = 0,
.dram_derate_percent_pixel_and_vm = 0,
.fclk_derate_percent = 57,
.dcfclk_derate_percent = 75,
},
.dcn_mall_prefetch_urgent = {
.dram_derate_percent_pixel = 22,
.dram_derate_percent_vm = 0,
.dram_derate_percent_pixel_and_vm = 0,
.fclk_derate_percent = 76,
.dcfclk_derate_percent = 100,
},
.dcn_mall_prefetch_average = {
.dram_derate_percent_pixel = 17,
.dram_derate_percent_vm = 0,
.dram_derate_percent_pixel_and_vm = 0,
.fclk_derate_percent = 57,
.dcfclk_derate_percent = 75,
},
.system_idle_average = {
.dram_derate_percent_pixel = 17,
.dram_derate_percent_vm = 0,
.dram_derate_percent_pixel_and_vm = 0,
.fclk_derate_percent = 57,
.dcfclk_derate_percent = 100,
},
},
.writeback = {
.base_latency_us = 12,
.scaling_factor_us = 0,
.scaling_factor_mhz = 0,
},
.qos_params = {
.dcn4x = {
.df_qos_response_time_fclk_cycles = 300,
.max_round_trip_to_furthest_cs_fclk_cycles = 350,
.mall_overhead_fclk_cycles = 50,
.meta_trip_adder_fclk_cycles = 36,
.average_transport_distance_fclk_cycles = 257,
.umc_urgent_ramp_latency_margin = 50,
.umc_max_latency_margin = 30,
.umc_average_latency_margin = 20,
.fabric_max_transport_latency_margin = 20,
.fabric_average_transport_latency_margin = 10,
.per_uclk_dpm_params = {
{
.minimum_uclk_khz = 97,
.urgent_ramp_uclk_cycles = 472,
.trip_to_memory_uclk_cycles = 827,
.meta_trip_to_memory_uclk_cycles = 827,
.maximum_latency_when_urgent_uclk_cycles = 72,
.average_latency_when_urgent_uclk_cycles = 61,
.maximum_latency_when_non_urgent_uclk_cycles = 827,
.average_latency_when_non_urgent_uclk_cycles = 118,
},
{
.minimum_uclk_khz = 435,
.urgent_ramp_uclk_cycles = 546,
.trip_to_memory_uclk_cycles = 848,
.meta_trip_to_memory_uclk_cycles = 848,
.maximum_latency_when_urgent_uclk_cycles = 146,
.average_latency_when_urgent_uclk_cycles = 90,
.maximum_latency_when_non_urgent_uclk_cycles = 848,
.average_latency_when_non_urgent_uclk_cycles = 135,
},
{
.minimum_uclk_khz = 731,
.urgent_ramp_uclk_cycles = 632,
.trip_to_memory_uclk_cycles = 874,
.meta_trip_to_memory_uclk_cycles = 874,
.maximum_latency_when_urgent_uclk_cycles = 232,
.average_latency_when_urgent_uclk_cycles = 124,
.maximum_latency_when_non_urgent_uclk_cycles = 874,
.average_latency_when_non_urgent_uclk_cycles = 155,
},
{
.minimum_uclk_khz = 1187,
.urgent_ramp_uclk_cycles = 716,
.trip_to_memory_uclk_cycles = 902,
.meta_trip_to_memory_uclk_cycles = 902,
.maximum_latency_when_urgent_uclk_cycles = 316,
.average_latency_when_urgent_uclk_cycles = 160,
.maximum_latency_when_non_urgent_uclk_cycles = 902,
.average_latency_when_non_urgent_uclk_cycles = 177,
},
},
},
},
.qos_type = dml2_qos_param_type_dcn4x,
};
static const struct dml2_soc_bb dml2_socbb_dcn31 = {
.clk_table = {
.uclk = {
.clk_values_khz = {97000, 435000, 731000, 1187000},
.num_clk_values = 4,
},
.fclk = {
.clk_values_khz = {300000, 2500000},
.num_clk_values = 2,
},
.dcfclk = {
.clk_values_khz = {200000, 1800000},
.num_clk_values = 2,
},
.dispclk = {
.clk_values_khz = {100000, 2000000},
.num_clk_values = 2,
},
.dppclk = {
.clk_values_khz = {100000, 2000000},
.num_clk_values = 2,
},
.dtbclk = {
.clk_values_khz = {100000, 2000000},
.num_clk_values = 2,
},
.phyclk = {
.clk_values_khz = {810000, 810000},
.num_clk_values = 2,
},
.socclk = {
.clk_values_khz = {300000, 1600000},
.num_clk_values = 2,
},
.dscclk = {
.clk_values_khz = {666667, 666667},
.num_clk_values = 2,
},
.phyclk_d18 = {
.clk_values_khz = {625000, 625000},
.num_clk_values = 2,
},
.phyclk_d32 = {
.clk_values_khz = {2000000, 2000000},
.num_clk_values = 2,
},
.dram_config = {
.channel_width_bytes = 2,
.channel_count = 16,
.transactions_per_clock = 16,
},
},
.qos_parameters = {
.derate_table = {
.system_active_urgent = {
.dram_derate_percent_pixel = 22,
.dram_derate_percent_vm = 0,
.dram_derate_percent_pixel_and_vm = 0,
.fclk_derate_percent = 76,
.dcfclk_derate_percent = 100,
},
.system_active_average = {
.dram_derate_percent_pixel = 17,
.dram_derate_percent_vm = 0,
.dram_derate_percent_pixel_and_vm = 0,
.fclk_derate_percent = 57,
.dcfclk_derate_percent = 75,
},
.dcn_mall_prefetch_urgent = {
.dram_derate_percent_pixel = 22,
.dram_derate_percent_vm = 0,
.dram_derate_percent_pixel_and_vm = 0,
.fclk_derate_percent = 76,
.dcfclk_derate_percent = 100,
},
.dcn_mall_prefetch_average = {
.dram_derate_percent_pixel = 17,
.dram_derate_percent_vm = 0,
.dram_derate_percent_pixel_and_vm = 0,
.fclk_derate_percent = 57,
.dcfclk_derate_percent = 75,
},
.system_idle_average = {
.dram_derate_percent_pixel = 17,
.dram_derate_percent_vm = 0,
.dram_derate_percent_pixel_and_vm = 0,
.fclk_derate_percent = 57,
.dcfclk_derate_percent = 100,
},
},
.writeback = {
.base_latency_us = 0,
.scaling_factor_us = 0,
.scaling_factor_mhz = 0,
},
.qos_params = {
.dcn4x = {
.df_qos_response_time_fclk_cycles = 300,
.max_round_trip_to_furthest_cs_fclk_cycles = 350,
.mall_overhead_fclk_cycles = 50,
.meta_trip_adder_fclk_cycles = 36,
.average_transport_distance_fclk_cycles = 260,
.umc_urgent_ramp_latency_margin = 50,
.umc_max_latency_margin = 30,
.umc_average_latency_margin = 20,
.fabric_max_transport_latency_margin = 20,
.fabric_average_transport_latency_margin = 10,
.per_uclk_dpm_params = {
{
// State 1
.minimum_uclk_khz = 0,
.urgent_ramp_uclk_cycles = 472,
.trip_to_memory_uclk_cycles = 827,
.meta_trip_to_memory_uclk_cycles = 827,
.maximum_latency_when_urgent_uclk_cycles = 72,
.average_latency_when_urgent_uclk_cycles = 72,
.maximum_latency_when_non_urgent_uclk_cycles = 827,
.average_latency_when_non_urgent_uclk_cycles = 117,
},
{
// State 2
.minimum_uclk_khz = 0,
.urgent_ramp_uclk_cycles = 546,
.trip_to_memory_uclk_cycles = 848,
.meta_trip_to_memory_uclk_cycles = 848,
.maximum_latency_when_urgent_uclk_cycles = 146,
.average_latency_when_urgent_uclk_cycles = 146,
.maximum_latency_when_non_urgent_uclk_cycles = 848,
.average_latency_when_non_urgent_uclk_cycles = 133,
},
{
// State 3
.minimum_uclk_khz = 0,
.urgent_ramp_uclk_cycles = 564,
.trip_to_memory_uclk_cycles = 853,
.meta_trip_to_memory_uclk_cycles = 853,
.maximum_latency_when_urgent_uclk_cycles = 164,
.average_latency_when_urgent_uclk_cycles = 164,
.maximum_latency_when_non_urgent_uclk_cycles = 853,
.average_latency_when_non_urgent_uclk_cycles = 136,
},
{
// State 4
.minimum_uclk_khz = 0,
.urgent_ramp_uclk_cycles = 613,
.trip_to_memory_uclk_cycles = 869,
.meta_trip_to_memory_uclk_cycles = 869,
.maximum_latency_when_urgent_uclk_cycles = 213,
.average_latency_when_urgent_uclk_cycles = 213,
.maximum_latency_when_non_urgent_uclk_cycles = 869,
.average_latency_when_non_urgent_uclk_cycles = 149,
},
{
// State 5
.minimum_uclk_khz = 0,
.urgent_ramp_uclk_cycles = 632,
.trip_to_memory_uclk_cycles = 874,
.meta_trip_to_memory_uclk_cycles = 874,
.maximum_latency_when_urgent_uclk_cycles = 232,
.average_latency_when_urgent_uclk_cycles = 232,
.maximum_latency_when_non_urgent_uclk_cycles = 874,
.average_latency_when_non_urgent_uclk_cycles = 153,
},
{
// State 6
.minimum_uclk_khz = 0,
.urgent_ramp_uclk_cycles = 665,
.trip_to_memory_uclk_cycles = 885,
.meta_trip_to_memory_uclk_cycles = 885,
.maximum_latency_when_urgent_uclk_cycles = 265,
.average_latency_when_urgent_uclk_cycles = 265,
.maximum_latency_when_non_urgent_uclk_cycles = 885,
.average_latency_when_non_urgent_uclk_cycles = 161,
},
{
// State 7
.minimum_uclk_khz = 0,
.urgent_ramp_uclk_cycles = 689,
.trip_to_memory_uclk_cycles = 895,
.meta_trip_to_memory_uclk_cycles = 895,
.maximum_latency_when_urgent_uclk_cycles = 289,
.average_latency_when_urgent_uclk_cycles = 289,
.maximum_latency_when_non_urgent_uclk_cycles = 895,
.average_latency_when_non_urgent_uclk_cycles = 167,
},
{
// State 8
.minimum_uclk_khz = 0,
.urgent_ramp_uclk_cycles = 716,
.trip_to_memory_uclk_cycles = 902,
.meta_trip_to_memory_uclk_cycles = 902,
.maximum_latency_when_urgent_uclk_cycles = 316,
.average_latency_when_urgent_uclk_cycles = 316,
.maximum_latency_when_non_urgent_uclk_cycles = 902,
.average_latency_when_non_urgent_uclk_cycles = 174,
},
},
},
},
.qos_type = dml2_qos_param_type_dcn4x,
},
.power_management_parameters = {
.dram_clk_change_blackout_us = 400,
.fclk_change_blackout_us = 0,
.g7_ppt_blackout_us = 0,
.stutter_enter_plus_exit_latency_us = 50,
.stutter_exit_latency_us = 43,
.z8_stutter_enter_plus_exit_latency_us = 0,
.z8_stutter_exit_latency_us = 0,
},
.vmin_limit = {
.dispclk_khz = 600 * 1000,
},
.dprefclk_mhz = 700,
.xtalclk_mhz = 100,
.pcie_refclk_mhz = 100,
.dchub_refclk_mhz = 50,
.mall_allocated_for_dcn_mbytes = 64,
.max_outstanding_reqs = 512,
.fabric_datapath_to_dcn_data_return_bytes = 64,
.return_bus_width_bytes = 64,
.hostvm_min_page_size_kbytes = 0,
.gpuvm_min_page_size_kbytes = 256,
.phy_downspread_percent = 0,
.dcn_downspread_percent = 0,
.dispclk_dppclk_vco_speed_mhz = 4500,
.do_urgent_latency_adjustment = 0,
.mem_word_bytes = 32,
.num_dcc_mcaches = 8,
.mcache_size_bytes = 2048,
.mcache_line_size_bytes = 32,
.max_fclk_for_uclk_dpm_khz = 1250 * 1000,
};
static const struct dml2_ip_capabilities dml2_dcn31_max_ip_caps = {
.pipe_count = 4,
.otg_count = 4,
.num_dsc = 4,
.max_num_dp2p0_streams = 4,
.max_num_hdmi_frl_outputs = 1,
.max_num_dp2p0_outputs = 4,
.rob_buffer_size_kbytes = 192,
.config_return_buffer_size_in_kbytes = 1152,
.meta_fifo_size_in_kentries = 22,
.compressed_buffer_segment_size_in_kbytes = 64,
.subvp_drr_scheduling_margin_us = 100,
.subvp_prefetch_end_to_mall_start_us = 15,
.subvp_fw_processing_delay = 15,
.fams2 = {
.max_allow_delay_us = 100 * 1000,
.scheduling_delay_us = 50,
.vertical_interrupt_ack_delay_us = 18,
.allow_programming_delay_us = 18,
.min_allow_width_us = 20,
.subvp_df_throttle_delay_us = 100,
.subvp_programming_delay_us = 18,
.subvp_prefetch_to_mall_delay_us = 18,
.drr_programming_delay_us = 18,
},
};
#endif /* __DML_DML_DCN3_SOC_BB__ */

View File

@@ -600,8 +600,8 @@ static void CalculateBytePerPixelAndBlockSizes(
{
*BytePerPixelDETY = 0;
*BytePerPixelDETC = 0;
*BytePerPixelY = 0;
*BytePerPixelC = 0;
*BytePerPixelY = 1;
*BytePerPixelC = 1;
if (SourcePixelFormat == dml2_444_64) {
*BytePerPixelDETY = 8;
@@ -3528,10 +3528,9 @@ static void CalculateUrgentBurstFactor(
dml2_printf("DML::%s: UrgentBurstFactorChroma = %f\n", __func__, *UrgentBurstFactorChroma);
dml2_printf("DML::%s: NotEnoughUrgentLatencyHiding = %d\n", __func__, *NotEnoughUrgentLatencyHiding);
#endif
}
static void CalculateDCFCLKDeepSleep(
static void CalculateDCFCLKDeepSleepTdlut(
const struct dml2_display_cfg *display_cfg,
unsigned int NumberOfActiveSurfaces,
unsigned int BytePerPixelY[],
@@ -3546,6 +3545,10 @@ static void CalculateDCFCLKDeepSleep(
double ReadBandwidthChroma[],
unsigned int ReturnBusWidth,
double dispclk,
unsigned int tdlut_bytes_to_deliver[],
double prefetch_swath_time_us[],
// Output
double *DCFClkDeepSleep)
{
@@ -3580,6 +3583,22 @@ static void CalculateDCFCLKDeepSleep(
}
DCFClkDeepSleepPerSurface[k] = math_max2(DCFClkDeepSleepPerSurface[k], pixel_rate_mhz / 16);
// adjust for 3dlut delivery time
if (display_cfg->plane_descriptors[k].tdlut.setup_for_tdlut && tdlut_bytes_to_deliver[k] > 0) {
double tdlut_required_deepsleep_dcfclk = (double) tdlut_bytes_to_deliver[k] / 64.0 / prefetch_swath_time_us[k];
dml2_printf("DML::%s: k=%d, DCFClkDeepSleepPerSurface = %f\n", __func__, k, DCFClkDeepSleepPerSurface[k]);
dml2_printf("DML::%s: k=%d, tdlut_bytes_to_deliver = %d\n", __func__, k, tdlut_bytes_to_deliver[k]);
dml2_printf("DML::%s: k=%d, prefetch_swath_time_us = %f\n", __func__, k, prefetch_swath_time_us[k]);
dml2_printf("DML::%s: k=%d, tdlut_required_deepsleep_dcfclk = %f\n", __func__, k, tdlut_required_deepsleep_dcfclk);
// increase the deepsleep dcfclk to match the original dispclk throughput rate
if (tdlut_required_deepsleep_dcfclk > DCFClkDeepSleepPerSurface[k]) {
DCFClkDeepSleepPerSurface[k] = math_max2(DCFClkDeepSleepPerSurface[k], tdlut_required_deepsleep_dcfclk);
DCFClkDeepSleepPerSurface[k] = math_max2(DCFClkDeepSleepPerSurface[k], dispclk / 4.0);
}
}
#ifdef __DML_VBA_DEBUG__
dml2_printf("DML::%s: k=%u, PixelClock = %f\n", __func__, k, pixel_rate_mhz);
dml2_printf("DML::%s: k=%u, DCFClkDeepSleepPerSurface = %f\n", __func__, k, DCFClkDeepSleepPerSurface[k]);
@@ -3602,9 +3621,56 @@ static void CalculateDCFCLKDeepSleep(
for (unsigned int k = 0; k < NumberOfActiveSurfaces; ++k) {
*DCFClkDeepSleep = math_max2(*DCFClkDeepSleep, DCFClkDeepSleepPerSurface[k]);
}
dml2_printf("DML::%s: DCFClkDeepSleep = %f (final)\n", __func__, *DCFClkDeepSleep);
}
static void CalculateDCFCLKDeepSleep(
const struct dml2_display_cfg *display_cfg,
unsigned int NumberOfActiveSurfaces,
unsigned int BytePerPixelY[],
unsigned int BytePerPixelC[],
unsigned int SwathWidthY[],
unsigned int SwathWidthC[],
unsigned int DPPPerSurface[],
double PSCL_THROUGHPUT[],
double PSCL_THROUGHPUT_CHROMA[],
double Dppclk[],
double ReadBandwidthLuma[],
double ReadBandwidthChroma[],
unsigned int ReturnBusWidth,
// Output
double *DCFClkDeepSleep)
{
double zero_double[DML2_MAX_PLANES];
unsigned int zero_integer[DML2_MAX_PLANES];
memset(zero_double, 0, DML2_MAX_PLANES * sizeof(double));
memset(zero_integer, 0, DML2_MAX_PLANES * sizeof(unsigned int));
CalculateDCFCLKDeepSleepTdlut(
display_cfg,
NumberOfActiveSurfaces,
BytePerPixelY,
BytePerPixelC,
SwathWidthY,
SwathWidthC,
DPPPerSurface,
PSCL_THROUGHPUT,
PSCL_THROUGHPUT_CHROMA,
Dppclk,
ReadBandwidthLuma,
ReadBandwidthChroma,
ReturnBusWidth,
0,
zero_integer, //tdlut_bytes_to_deliver,
zero_double, //prefetch_swath_time_us,
// Output
DCFClkDeepSleep);
}
static double CalculateWriteBackDelay(
enum dml2_source_format_class WritebackPixelFormat,
double WritebackHRatio,
@@ -4604,6 +4670,7 @@ static void calculate_tdlut_setting(
*p->tdlut_groups_per_2row_ub = 0;
*p->tdlut_opt_time = 0;
*p->tdlut_drain_time = 0;
*p->tdlut_bytes_to_deliver = 0;
*p->tdlut_bytes_per_group = 0;
*p->tdlut_pte_bytes_per_frame = 0;
*p->tdlut_bytes_per_frame = 0;
@@ -4672,6 +4739,7 @@ static void calculate_tdlut_setting(
*p->tdlut_groups_per_2row_ub = (unsigned int)math_ceil2((double) *p->tdlut_bytes_per_frame / *p->tdlut_bytes_per_group, 1);
*p->tdlut_opt_time = (*p->tdlut_bytes_per_frame - p->cursor_buffer_size * 1024) / tdlut_drain_rate;
*p->tdlut_drain_time = p->cursor_buffer_size * 1024 / tdlut_drain_rate;
*p->tdlut_bytes_to_deliver = (unsigned int) (p->cursor_buffer_size * 1024.0);
}
#ifdef __DML_VBA_DEBUG__
@@ -4692,6 +4760,7 @@ static void calculate_tdlut_setting(
dml2_printf("DML::%s: tdlut_delivery_cycles = %u\n", __func__, tdlut_delivery_cycles);
dml2_printf("DML::%s: tdlut_opt_time = %f\n", __func__, *p->tdlut_opt_time);
dml2_printf("DML::%s: tdlut_drain_time = %f\n", __func__, *p->tdlut_drain_time);
dml2_printf("DML::%s: tdlut_bytes_to_deliver = %d\n", __func__, *p->tdlut_bytes_to_deliver);
dml2_printf("DML::%s: tdlut_groups_per_2row_ub = %d\n", __func__, *p->tdlut_groups_per_2row_ub);
#endif
}
@@ -5700,6 +5769,7 @@ static bool CalculatePrefetchSchedule(struct dml2_core_internal_scratch *scratch
s->cursor_prefetch_bytes = (unsigned int)math_max2(p->cursor_bytes_per_chunk, 4 * p->cursor_bytes_per_line);
*p->prefetch_cursor_bw = p->num_cursors * s->cursor_prefetch_bytes / (s->LinesToRequestPrefetchPixelData * s->LineTime);
*p->prefetch_swath_time_us = (s->LinesToRequestPrefetchPixelData * s->LineTime);
#ifdef __DML_VBA_DEBUG__
dml2_printf("DML::%s: TimeForFetchingVM = %f\n", __func__, s->TimeForFetchingVM);
@@ -5710,6 +5780,7 @@ static bool CalculatePrefetchSchedule(struct dml2_core_internal_scratch *scratch
dml2_printf("DML::%s: dst_y_per_row_vblank = %f\n", __func__, *p->dst_y_per_row_vblank);
dml2_printf("DML::%s: LinesToRequestPrefetchPixelData = %f\n", __func__, s->LinesToRequestPrefetchPixelData);
dml2_printf("DML::%s: PrefetchSourceLinesY = %f\n", __func__, p->PrefetchSourceLinesY);
dml2_printf("DML::%s: prefetch_swath_time_us = %f\n", __func__, *p->prefetch_swath_time_us);
dml2_printf("DML::%s: cursor_bytes_per_chunk = %d\n", __func__, p->cursor_bytes_per_chunk);
dml2_printf("DML::%s: cursor_bytes_per_line = %d\n", __func__, p->cursor_bytes_per_line);
@@ -8817,6 +8888,7 @@ static bool dml_core_mode_support(struct dml2_core_calcs_mode_support_ex *in_out
calculate_tdlut_setting_params->tdlut_groups_per_2row_ub = &s->tdlut_groups_per_2row_ub[k];
calculate_tdlut_setting_params->tdlut_opt_time = &s->tdlut_opt_time[k];
calculate_tdlut_setting_params->tdlut_drain_time = &s->tdlut_drain_time[k];
calculate_tdlut_setting_params->tdlut_bytes_to_deliver = &s->tdlut_bytes_to_deliver[k];
calculate_tdlut_setting_params->tdlut_bytes_per_group = &s->tdlut_bytes_per_group[k];
calculate_tdlut_setting(&mode_lib->scratch, calculate_tdlut_setting_params);
@@ -9009,6 +9081,7 @@ static bool dml_core_mode_support(struct dml2_core_calcs_mode_support_ex *in_out
CalculatePrefetchSchedule_params->prefetch_sw_bytes = &s->prefetch_sw_bytes[k];
CalculatePrefetchSchedule_params->Tpre_rounded = &s->Tpre_rounded[k];
CalculatePrefetchSchedule_params->Tpre_oto = &s->Tpre_oto[k];
CalculatePrefetchSchedule_params->prefetch_swath_time_us = &s->prefetch_swath_time_us[k];
mode_lib->ms.NoTimeForPrefetch[k] = CalculatePrefetchSchedule(&mode_lib->scratch, CalculatePrefetchSchedule_params);
@@ -9017,6 +9090,27 @@ static bool dml_core_mode_support(struct dml2_core_calcs_mode_support_ex *in_out
dml2_printf("DML::%s: k=%d, dst_y_per_row_vblank = %f\n", __func__, k, *CalculatePrefetchSchedule_params->dst_y_per_row_vblank);
} // for k num_planes
CalculateDCFCLKDeepSleepTdlut(
display_cfg,
mode_lib->ms.num_active_planes,
mode_lib->ms.BytePerPixelY,
mode_lib->ms.BytePerPixelC,
mode_lib->ms.SwathWidthY,
mode_lib->ms.SwathWidthC,
mode_lib->ms.NoOfDPP,
mode_lib->ms.PSCL_FACTOR,
mode_lib->ms.PSCL_FACTOR_CHROMA,
mode_lib->ms.RequiredDPPCLK,
mode_lib->ms.vactive_sw_bw_l,
mode_lib->ms.vactive_sw_bw_c,
mode_lib->soc.return_bus_width_bytes,
mode_lib->ms.RequiredDISPCLK,
s->tdlut_bytes_to_deliver,
s->prefetch_swath_time_us,
/* Output */
&mode_lib->ms.dcfclk_deepsleep);
for (k = 0; k < mode_lib->ms.num_active_planes; k++) {
if (mode_lib->ms.dst_y_prefetch[k] < 2.0
|| mode_lib->ms.LinesForVM[k] >= 32.0
@@ -10368,12 +10462,6 @@ static bool dml_core_mode_programming(struct dml2_core_calcs_mode_programming_ex
dml2_assert(s->SOCCLK > 0);
#ifdef __DML_VBA_DEBUG__
// dml2_printf_dml_display_cfg_timing(&display_cfg->timing, s->num_active_planes);
// dml2_printf_dml_display_cfg_plane(&display_cfg->plane, s->num_active_planes);
// dml2_printf_dml_display_cfg_surface(&display_cfg->surface, s->num_active_planes);
// dml2_printf_dml_display_cfg_output(&display_cfg->output, s->num_active_planes);
// dml2_printf_dml_display_cfg_hw_resource(&display_cfg->hw, s->num_active_planes);
dml2_printf("DML::%s: num_active_planes = %u\n", __func__, s->num_active_planes);
dml2_printf("DML::%s: num_active_pipes = %u\n", __func__, mode_lib->mp.num_active_pipes);
dml2_printf("DML::%s: Dcfclk = %f\n", __func__, mode_lib->mp.Dcfclk);
@@ -10832,8 +10920,8 @@ static bool dml_core_mode_programming(struct dml2_core_calcs_mode_programming_ex
calculate_tdlut_setting_params->tdlut_groups_per_2row_ub = &s->tdlut_groups_per_2row_ub[k];
calculate_tdlut_setting_params->tdlut_opt_time = &s->tdlut_opt_time[k];
calculate_tdlut_setting_params->tdlut_drain_time = &s->tdlut_drain_time[k];
calculate_tdlut_setting_params->tdlut_bytes_to_deliver = &s->tdlut_bytes_to_deliver[k];
calculate_tdlut_setting_params->tdlut_bytes_per_group = &s->tdlut_bytes_per_group[k];
calculate_tdlut_setting(&mode_lib->scratch, calculate_tdlut_setting_params);
}
@@ -11219,6 +11307,7 @@ static bool dml_core_mode_programming(struct dml2_core_calcs_mode_programming_ex
CalculatePrefetchSchedule_params->prefetch_sw_bytes = &s->prefetch_sw_bytes[k];
CalculatePrefetchSchedule_params->Tpre_rounded = &s->Tpre_rounded[k];
CalculatePrefetchSchedule_params->Tpre_oto = &s->Tpre_oto[k];
CalculatePrefetchSchedule_params->prefetch_swath_time_us = &s->dummy_single[0];
mode_lib->mp.NoTimeToPrefetch[k] = CalculatePrefetchSchedule(&mode_lib->scratch, CalculatePrefetchSchedule_params);

View File

@@ -958,6 +958,7 @@ struct dml2_core_calcs_mode_support_locals {
unsigned int tdlut_groups_per_2row_ub[DML2_MAX_PLANES];
double tdlut_opt_time[DML2_MAX_PLANES];
double tdlut_drain_time[DML2_MAX_PLANES];
unsigned int tdlut_bytes_to_deliver[DML2_MAX_PLANES];
unsigned int tdlut_bytes_per_group[DML2_MAX_PLANES];
unsigned int cursor_bytes_per_chunk[DML2_MAX_PLANES];
@@ -979,6 +980,7 @@ struct dml2_core_calcs_mode_support_locals {
enum dml2_source_format_class pixel_format[DML2_MAX_PLANES];
unsigned int lb_source_lines_l[DML2_MAX_PLANES];
unsigned int lb_source_lines_c[DML2_MAX_PLANES];
double prefetch_swath_time_us[DML2_MAX_PLANES];
};
struct dml2_core_calcs_mode_programming_locals {
@@ -1042,6 +1044,7 @@ struct dml2_core_calcs_mode_programming_locals {
unsigned int tdlut_groups_per_2row_ub[DML2_MAX_PLANES];
double tdlut_opt_time[DML2_MAX_PLANES];
double tdlut_drain_time[DML2_MAX_PLANES];
unsigned int tdlut_bytes_to_deliver[DML2_MAX_PLANES];
unsigned int tdlut_bytes_per_group[DML2_MAX_PLANES];
unsigned int cursor_bytes_per_chunk[DML2_MAX_PLANES];
@@ -1809,6 +1812,7 @@ struct dml2_core_calcs_CalculatePrefetchSchedule_params {
unsigned int *VReadyOffsetPix;
double *prefetch_cursor_bw;
double *prefetch_sw_bytes;
double *prefetch_swath_time_us;
};
struct dml2_core_calcs_CheckGlobalPrefetchAdmissibility_params {
@@ -1993,6 +1997,7 @@ struct dml2_core_calcs_calculate_tdlut_setting_params {
unsigned int *tdlut_groups_per_2row_ub;
double *tdlut_opt_time;
double *tdlut_drain_time;
unsigned int *tdlut_bytes_to_deliver;
unsigned int *tdlut_bytes_per_group;
};
@@ -2137,7 +2142,6 @@ struct dml2_core_calcs_mode_programming_ex {
const struct core_display_cfg_support_info *cfg_support_info;
int min_clk_index;
struct dml2_display_cfg_programming *programming;
};
#endif

View File

@@ -556,7 +556,7 @@ bool dml2_core_utils_is_dual_plane(enum dml2_source_format_class source_format)
{
bool ret_val = 0;
if ((source_format == dml2_420_12) || (source_format == dml2_420_8) || (source_format == dml2_420_10) || (source_format == dml2_rgbe_alpha))
if (dml2_core_utils_is_420(source_format) || dml2_core_utils_is_422_planar(source_format) || (source_format == dml2_rgbe_alpha))
ret_val = 1;
return ret_val;

View File

@@ -212,7 +212,7 @@ static bool add_margin_and_round_to_dfs_grainularity(double clock_khz, double ma
clock_khz *= 1.0 + margin;
divider = (unsigned int)(DFS_DIVIDER_RANGE_SCALE_FACTOR * (vco_freq_khz / clock_khz));
divider = (unsigned int)((int)DFS_DIVIDER_RANGE_SCALE_FACTOR * (vco_freq_khz / clock_khz));
/* we want to floor here to get higher clock than required rather than lower */
if (divider < DFS_DIVIDER_RANGE_2_START) {
@@ -417,11 +417,11 @@ static bool map_min_clocks_to_dpm(const struct dml2_core_mode_support_result *mo
static bool are_timings_trivially_synchronizable(struct dml2_display_cfg *display_config, int mask)
{
unsigned char i;
unsigned int i;
bool identical = true;
bool contains_drr = false;
unsigned char remap_array[DML2_MAX_PLANES];
unsigned char remap_array_size = 0;
unsigned int remap_array[DML2_MAX_PLANES];
unsigned int remap_array_size = 0;
// Create a remap array to enable simple iteration through only masked stream indicies
for (i = 0; i < display_config->num_streams; i++) {
@@ -456,10 +456,10 @@ static bool are_timings_trivially_synchronizable(struct dml2_display_cfg *displa
static int find_smallest_idle_time_in_vblank_us(struct dml2_dpmm_map_mode_to_soc_dpm_params_in_out *in_out, int mask)
{
unsigned char i;
unsigned int i;
int min_idle_us = 0;
unsigned char remap_array[DML2_MAX_PLANES];
unsigned char remap_array_size = 0;
unsigned int remap_array[DML2_MAX_PLANES];
unsigned int remap_array_size = 0;
const struct dml2_core_mode_support_result *mode_support_result = &in_out->display_cfg->mode_support_result;
// Create a remap array to enable simple iteration through only masked stream indicies

View File

@@ -195,11 +195,11 @@ static int count_planes_with_stream_index(const struct dml2_display_cfg *display
static bool are_timings_trivially_synchronizable(struct display_configuation_with_meta *display_config, int mask)
{
unsigned char i;
unsigned int i;
bool identical = true;
bool contains_drr = false;
unsigned char remap_array[DML2_MAX_PLANES];
unsigned char remap_array_size = 0;
unsigned int remap_array[DML2_MAX_PLANES];
unsigned int remap_array_size = 0;
// Create a remap array to enable simple iteration through only masked stream indicies
for (i = 0; i < display_config->display_config.num_streams; i++) {
@@ -347,8 +347,12 @@ static int find_highest_odm_load_stream_index(
int odm_load, highest_odm_load = -1, highest_odm_load_index = -1;
for (i = 0; i < display_config->num_streams; i++) {
odm_load = display_config->stream_descriptors[i].timing.pixel_clock_khz
if (mode_support_result->cfg_support_info.stream_support_info[i].odms_used > 0)
odm_load = display_config->stream_descriptors[i].timing.pixel_clock_khz
/ mode_support_result->cfg_support_info.stream_support_info[i].odms_used;
else
odm_load = 0;
if (odm_load > highest_odm_load) {
highest_odm_load_index = i;
highest_odm_load = odm_load;

View File

@@ -813,8 +813,12 @@ static int find_highest_odm_load_stream_index(
int odm_load, highest_odm_load = -1, highest_odm_load_index = -1;
for (i = 0; i < display_config->num_streams; i++) {
odm_load = display_config->stream_descriptors[i].timing.pixel_clock_khz
if (mode_support_result->cfg_support_info.stream_support_info[i].odms_used > 0)
odm_load = display_config->stream_descriptors[i].timing.pixel_clock_khz
/ mode_support_result->cfg_support_info.stream_support_info[i].odms_used;
else
odm_load = 0;
if (odm_load > highest_odm_load) {
highest_odm_load_index = i;
highest_odm_load = odm_load;
@@ -986,7 +990,7 @@ static bool all_timings_support_vactive(const struct dml2_pmo_instance *pmo,
const struct display_configuation_with_meta *display_config,
unsigned int mask)
{
unsigned char i;
unsigned int i;
bool valid = true;
// Create a remap array to enable simple iteration through only masked stream indicies
@@ -1035,7 +1039,7 @@ static bool all_timings_support_drr(const struct dml2_pmo_instance *pmo,
const struct display_configuation_with_meta *display_config,
unsigned int mask)
{
unsigned char i;
unsigned int i;
for (i = 0; i < DML2_MAX_PLANES; i++) {
const struct dml2_stream_parameters *stream_descriptor;
const struct dml2_fams2_meta *stream_fams2_meta;
@@ -1077,7 +1081,7 @@ static bool all_timings_support_svp(const struct dml2_pmo_instance *pmo,
const struct dml2_plane_parameters *plane_descriptor;
const struct dml2_fams2_meta *stream_fams2_meta;
unsigned int microschedule_vlines;
unsigned char i;
unsigned int i;
unsigned int num_planes_per_stream[DML2_MAX_PLANES] = { 0 };
@@ -1194,7 +1198,7 @@ static enum dml2_uclk_pstate_change_strategy pstate_method_to_uclk_pstate_strate
static bool all_planes_match_method(const struct display_configuation_with_meta *display_cfg, int plane_mask, enum dml2_pstate_method method)
{
unsigned char i;
unsigned int i;
for (i = 0; i < DML2_MAX_PLANES; i++) {
if (is_bit_set_in_bitfield(plane_mask, i)) {
@@ -1372,7 +1376,7 @@ static bool is_config_schedulable(
if (j_disallow_us < jp1_disallow_us) {
/* swap as A < B */
swap(s->pmo_dcn4.sorted_group_gtl_disallow_index[j],
s->pmo_dcn4.sorted_group_gtl_disallow_index[j+1]);
s->pmo_dcn4.sorted_group_gtl_disallow_index[j + 1]);
swapped = true;
}
}
@@ -1431,7 +1435,7 @@ static bool is_config_schedulable(
if (j_period_us < jp1_period_us) {
/* swap as A < B */
swap(s->pmo_dcn4.sorted_group_gtl_period_index[j],
s->pmo_dcn4.sorted_group_gtl_period_index[j+1]);
s->pmo_dcn4.sorted_group_gtl_period_index[j + 1]);
swapped = true;
}
}
@@ -1545,7 +1549,7 @@ static bool validate_pstate_support_strategy_cofunctionality(struct dml2_pmo_ins
{
struct dml2_pmo_scratch *s = &pmo->scratch;
unsigned char stream_index = 0;
unsigned int stream_index = 0;
unsigned int svp_count = 0;
unsigned int svp_stream_mask = 0;
@@ -1609,7 +1613,7 @@ static bool validate_pstate_support_strategy_cofunctionality(struct dml2_pmo_ins
static int get_vactive_pstate_margin(const struct display_configuation_with_meta *display_cfg, int plane_mask)
{
unsigned char i;
unsigned int i;
int min_vactive_margin_us = 0xFFFFFFF;
for (i = 0; i < DML2_MAX_PLANES; i++) {
@@ -1817,7 +1821,7 @@ bool pmo_dcn4_fams2_init_for_pstate_support(struct dml2_pmo_init_for_pstate_supp
const struct dml2_pmo_pstate_strategy *strategy_list = NULL;
struct dml2_pmo_pstate_strategy override_base_strategy = { 0 };
unsigned int strategy_list_size = 0;
unsigned char plane_index, stream_index, i;
unsigned int plane_index, stream_index, i;
bool build_override_strategy = true;
state->performed = true;
@@ -1940,7 +1944,7 @@ static void setup_planes_for_drr_by_mask(struct display_configuation_with_meta *
struct dml2_pmo_instance *pmo,
int plane_mask)
{
unsigned char plane_index;
unsigned int plane_index;
struct dml2_plane_parameters *plane;
for (plane_index = 0; plane_index < display_config->display_config.num_planes; plane_index++) {
@@ -1961,7 +1965,7 @@ static void setup_planes_for_svp_by_mask(struct display_configuation_with_meta *
{
struct dml2_pmo_scratch *scratch = &pmo->scratch;
unsigned char plane_index;
unsigned int plane_index;
int stream_index = -1;
for (plane_index = 0; plane_index < display_config->display_config.num_planes; plane_index++) {
@@ -1984,7 +1988,7 @@ static void setup_planes_for_svp_drr_by_mask(struct display_configuation_with_me
{
struct dml2_pmo_scratch *scratch = &pmo->scratch;
unsigned char plane_index;
unsigned int plane_index;
int stream_index = -1;
for (plane_index = 0; plane_index < display_config->display_config.num_planes; plane_index++) {
@@ -2005,7 +2009,7 @@ static void setup_planes_for_vblank_by_mask(struct display_configuation_with_met
struct dml2_pmo_instance *pmo,
int plane_mask)
{
unsigned char plane_index;
unsigned int plane_index;
struct dml2_plane_parameters *plane;
for (plane_index = 0; plane_index < display_config->display_config.num_planes; plane_index++) {
@@ -2025,7 +2029,7 @@ static void setup_planes_for_vblank_drr_by_mask(struct display_configuation_with
struct dml2_pmo_instance *pmo,
int plane_mask)
{
unsigned char plane_index;
unsigned int plane_index;
struct dml2_plane_parameters *plane;
for (plane_index = 0; plane_index < display_config->display_config.num_planes; plane_index++) {
@@ -2042,7 +2046,7 @@ static void setup_planes_for_vactive_by_mask(struct display_configuation_with_me
struct dml2_pmo_instance *pmo,
int plane_mask)
{
unsigned char plane_index;
unsigned int plane_index;
unsigned int stream_index;
for (plane_index = 0; plane_index < display_config->display_config.num_planes; plane_index++) {
@@ -2063,7 +2067,7 @@ static void setup_planes_for_vactive_drr_by_mask(struct display_configuation_wit
struct dml2_pmo_instance *pmo,
int plane_mask)
{
unsigned char plane_index;
unsigned int plane_index;
unsigned int stream_index;
for (plane_index = 0; plane_index < display_config->display_config.num_planes; plane_index++) {
@@ -2131,7 +2135,7 @@ static bool setup_display_config(struct display_configuation_with_meta *display_
static int get_minimum_reserved_time_us_for_planes(struct display_configuation_with_meta *display_config, int plane_mask)
{
int min_time_us = 0xFFFFFF;
unsigned char plane_index = 0;
unsigned int plane_index = 0;
for (plane_index = 0; plane_index < display_config->display_config.num_planes; plane_index++) {
if (is_bit_set_in_bitfield(plane_mask, plane_index)) {

View File

@@ -15,7 +15,6 @@ bool dml2_initialize_instance(struct dml2_initialize_instance_in_out *in_out)
{
switch (in_out->options.project_id) {
case dml2_project_dcn4x_stage1:
return false;
case dml2_project_dcn4x_stage2:
case dml2_project_dcn4x_stage2_auto_drr_svp:
return dml2_top_soc15_initialize_instance(in_out);

View File

@@ -2,3 +2,9 @@
//
// Copyright 2024 Advanced Micro Devices, Inc.
#include "dml2_top_legacy.h"
#include "dml2_top_soc15.h"
#include "dml2_core_factory.h"
#include "dml2_pmo_factory.h"
#include "display_mode_core_structs.h"

View File

@@ -545,6 +545,7 @@ bool dml2_top_mcache_validate_admissability(struct top_mcache_validate_admissabi
if (odm_combine_factor > 1) {
max_per_pipe_vp_p0 = plane->surface.plane0.width;
temp = (unsigned int)math_ceil(plane->composition.scaler_info.plane0.h_ratio * stream->timing.h_active / odm_combine_factor);
if (temp < max_per_pipe_vp_p0)
max_per_pipe_vp_p0 = temp;

View File

@@ -1,6 +1,7 @@
// SPDX-License-Identifier: MIT
//
// Copyright 2024 Advanced Micro Devices, Inc.
#ifndef __DML2_TOP_SOC15_H__
#define __DML2_TOP_SOC15_H__
#include "dml2_internal_shared_types.h"

View File

@@ -357,8 +357,6 @@ struct dml2_pmo_pstate_strategy {
enum dml2_pstate_method per_stream_pstate_method[DML2_MAX_PLANES];
bool allow_state_increase;
};
struct dml2_core_mode_support_in_out {
/*
* Inputs

View File

@@ -813,7 +813,7 @@ static bool remove_all_phantom_planes_for_stream(struct dml2_context *ctx, struc
{
int i, old_plane_count;
struct dc_stream_status *stream_status = NULL;
struct dc_plane_state *del_planes[MAX_SURFACE_NUM] = { 0 };
struct dc_plane_state *del_planes[MAX_SURFACES] = { 0 };
for (i = 0; i < context->stream_count; i++)
if (context->streams[i] == stream) {

View File

@@ -747,11 +747,10 @@ static inline struct dml2_context *dml2_allocate_memory(void)
static void dml2_init(const struct dc *in_dc, const struct dml2_configuration_options *config, struct dml2_context **dml2)
{
// TODO : Temporarily add DCN_VERSION_3_2 for N-1 validation. Remove DCN_VERSION_3_2 after N-1 validation phase is complete.
if ((in_dc->debug.using_dml21) && (in_dc->ctx->dce_version == DCN_VERSION_4_01 || in_dc->ctx->dce_version == DCN_VERSION_3_2)) {
dml21_reinit(in_dc, dml2, config);
if ((in_dc->debug.using_dml21) && (in_dc->ctx->dce_version == DCN_VERSION_4_01)) {
dml21_reinit(in_dc, dml2, config);
return;
}
}
// Store config options
(*dml2)->config = *config;
@@ -786,10 +785,8 @@ static void dml2_init(const struct dc *in_dc, const struct dml2_configuration_op
bool dml2_create(const struct dc *in_dc, const struct dml2_configuration_options *config, struct dml2_context **dml2)
{
// TODO : Temporarily add DCN_VERSION_3_2 for N-1 validation. Remove DCN_VERSION_3_2 after N-1 validation phase is complete.
if ((in_dc->debug.using_dml21) && (in_dc->ctx->dce_version == DCN_VERSION_4_01 || in_dc->ctx->dce_version == DCN_VERSION_3_2)) {
if ((in_dc->debug.using_dml21) && (in_dc->ctx->dce_version == DCN_VERSION_4_01))
return dml21_create(in_dc, dml2, config);
}
// Allocate Mode Lib Ctx
*dml2 = dml2_allocate_memory();
@@ -857,8 +854,7 @@ void dml2_reinit(const struct dc *in_dc,
const struct dml2_configuration_options *config,
struct dml2_context **dml2)
{
// TODO : Temporarily add DCN_VERSION_3_2 for N-1 validation. Remove DCN_VERSION_3_2 after N-1 validation phase is complete.
if ((in_dc->debug.using_dml21) && (in_dc->ctx->dce_version == DCN_VERSION_4_01 || in_dc->ctx->dce_version == DCN_VERSION_3_2)) {
if ((in_dc->debug.using_dml21) && (in_dc->ctx->dce_version == DCN_VERSION_4_01)) {
dml21_reinit(in_dc, dml2, config);
return;
}

View File

@@ -30,6 +30,9 @@
#include "rc_calc.h"
#include "fixed31_32.h"
#define DC_LOGGER \
dsc->ctx->logger
/* This module's internal functions */
/* default DSC policy target bitrate limit is 16bpp */
@@ -480,6 +483,48 @@ bool dc_dsc_compute_bandwidth_range(
return is_dsc_possible;
}
void dc_dsc_dump_encoder_caps(const struct display_stream_compressor *dsc,
const struct dc_crtc_timing *timing)
{
struct dsc_enc_caps dsc_enc_caps;
get_dsc_enc_caps(dsc, &dsc_enc_caps, timing->pix_clk_100hz);
DC_LOG_DSC("dsc encoder caps:");
DC_LOG_DSC("\tdsc_version 0x%x", dsc_enc_caps.dsc_version);
DC_LOG_DSC("\tslice_caps 0x%x", dsc_enc_caps.slice_caps.raw);
DC_LOG_DSC("\tlb_bit_depth %d", dsc_enc_caps.lb_bit_depth);
DC_LOG_DSC("\tis_block_pred_supported %d", dsc_enc_caps.is_block_pred_supported);
DC_LOG_DSC("\tcolor_formats 0x%x", dsc_enc_caps.color_formats.raw);
DC_LOG_DSC("\tcolor_depth 0x%x", dsc_enc_caps.color_depth.raw);
DC_LOG_DSC("\tmax_total_throughput_mps %d", dsc_enc_caps.max_total_throughput_mps);
DC_LOG_DSC("\tmax_slice_width %d", dsc_enc_caps.max_slice_width);
DC_LOG_DSC("\tbpp_increment_div %d", dsc_enc_caps.bpp_increment_div);
}
void dc_dsc_dump_decoder_caps(const struct display_stream_compressor *dsc,
const struct dsc_dec_dpcd_caps *dsc_sink_caps)
{
DC_LOG_DSC("dsc decoder caps:");
DC_LOG_DSC("\tis_dsc_supported %d", dsc_sink_caps->is_dsc_supported);
DC_LOG_DSC("\tdsc_version 0x%x", dsc_sink_caps->dsc_version);
DC_LOG_DSC("\trc_buffer_size %d", dsc_sink_caps->rc_buffer_size);
DC_LOG_DSC("\tslice_caps1 0x%x", dsc_sink_caps->slice_caps1.raw);
DC_LOG_DSC("\tslice_caps2 0x%x", dsc_sink_caps->slice_caps2.raw);
DC_LOG_DSC("\tlb_bit_depth %d", dsc_sink_caps->lb_bit_depth);
DC_LOG_DSC("\tis_block_pred_supported %d", dsc_sink_caps->is_block_pred_supported);
DC_LOG_DSC("\tedp_max_bits_per_pixel %d", dsc_sink_caps->edp_max_bits_per_pixel);
DC_LOG_DSC("\tcolor_formats 0x%x", dsc_sink_caps->color_formats.raw);
DC_LOG_DSC("\tthroughput_mode_0_mps %d", dsc_sink_caps->throughput_mode_0_mps);
DC_LOG_DSC("\tthroughput_mode_1_mps %d", dsc_sink_caps->throughput_mode_1_mps);
DC_LOG_DSC("\tmax_slice_width %d", dsc_sink_caps->max_slice_width);
DC_LOG_DSC("\tbpp_increment_div %d", dsc_sink_caps->bpp_increment_div);
DC_LOG_DSC("\tbranch_overall_throughput_0_mps %d", dsc_sink_caps->branch_overall_throughput_0_mps);
DC_LOG_DSC("\tbranch_overall_throughput_1_mps %d", dsc_sink_caps->branch_overall_throughput_1_mps);
DC_LOG_DSC("\tbranch_max_line_width %d", dsc_sink_caps->branch_max_line_width);
DC_LOG_DSC("\tis_dp %d", dsc_sink_caps->is_dp);
}
static void get_dsc_enc_caps(
const struct display_stream_compressor *dsc,
struct dsc_enc_caps *dsc_enc_caps,

View File

@@ -140,7 +140,7 @@ void hubp1_vready_workaround(struct hubp *hubp,
void hubp1_program_tiling(
struct hubp *hubp,
const union dc_tiling_info *info,
const struct dc_tiling_info *info,
const enum surface_pixel_format pixel_format)
{
struct dcn10_hubp *hubp1 = TO_DCN10_HUBP(hubp);
@@ -549,7 +549,7 @@ void hubp1_dcc_control(struct hubp *hubp, bool enable,
void hubp1_program_surface_config(
struct hubp *hubp,
enum surface_pixel_format format,
union dc_tiling_info *tiling_info,
struct dc_tiling_info *tiling_info,
struct plane_size *plane_size,
enum dc_rotation_angle rotation,
struct dc_plane_dcc_param *dcc,

View File

@@ -706,7 +706,7 @@ struct dcn10_hubp {
void hubp1_program_surface_config(
struct hubp *hubp,
enum surface_pixel_format format,
union dc_tiling_info *tiling_info,
struct dc_tiling_info *tiling_info,
struct plane_size *plane_size,
enum dc_rotation_angle rotation,
struct dc_plane_dcc_param *dcc,
@@ -739,7 +739,7 @@ void hubp1_program_rotation(
void hubp1_program_tiling(
struct hubp *hubp,
const union dc_tiling_info *info,
const struct dc_tiling_info *info,
const enum surface_pixel_format pixel_format);
void hubp1_dcc_control(struct hubp *hubp,

View File

@@ -310,7 +310,7 @@ void hubp2_setup_interdependent(
*/
static void hubp2_program_tiling(
struct dcn20_hubp *hubp2,
const union dc_tiling_info *info,
const struct dc_tiling_info *info,
const enum surface_pixel_format pixel_format)
{
REG_UPDATE_3(DCSURF_ADDR_CONFIG,
@@ -550,7 +550,7 @@ void hubp2_program_pixel_format(
void hubp2_program_surface_config(
struct hubp *hubp,
enum surface_pixel_format format,
union dc_tiling_info *tiling_info,
struct dc_tiling_info *tiling_info,
struct plane_size *plane_size,
enum dc_rotation_angle rotation,
struct dc_plane_dcc_param *dcc,

View File

@@ -382,7 +382,7 @@ void hubp2_program_pixel_format(
void hubp2_program_surface_config(
struct hubp *hubp,
enum surface_pixel_format format,
union dc_tiling_info *tiling_info,
struct dc_tiling_info *tiling_info,
struct plane_size *plane_size,
enum dc_rotation_angle rotation,
struct dc_plane_dcc_param *dcc,

View File

@@ -42,7 +42,7 @@
static void hubp201_program_surface_config(
struct hubp *hubp,
enum surface_pixel_format format,
union dc_tiling_info *tiling_info,
struct dc_tiling_info *tiling_info,
struct plane_size *plane_size,
enum dc_rotation_angle rotation,
struct dc_plane_dcc_param *dcc,

View File

@@ -318,7 +318,7 @@ bool hubp3_program_surface_flip_and_addr(
void hubp3_program_tiling(
struct dcn20_hubp *hubp2,
const union dc_tiling_info *info,
const struct dc_tiling_info *info,
const enum surface_pixel_format pixel_format)
{
REG_UPDATE_4(DCSURF_ADDR_CONFIG,
@@ -411,7 +411,7 @@ void hubp3_dmdata_set_attributes(
void hubp3_program_surface_config(
struct hubp *hubp,
enum surface_pixel_format format,
union dc_tiling_info *tiling_info,
struct dc_tiling_info *tiling_info,
struct plane_size *plane_size,
enum dc_rotation_angle rotation,
struct dc_plane_dcc_param *dcc,

View File

@@ -264,7 +264,7 @@ bool hubp3_program_surface_flip_and_addr(
void hubp3_program_surface_config(
struct hubp *hubp,
enum surface_pixel_format format,
union dc_tiling_info *tiling_info,
struct dc_tiling_info *tiling_info,
struct plane_size *plane_size,
enum dc_rotation_angle rotation,
struct dc_plane_dcc_param *dcc,
@@ -280,7 +280,7 @@ void hubp3_setup(
void hubp3_program_tiling(
struct dcn20_hubp *hubp2,
const union dc_tiling_info *info,
const struct dc_tiling_info *info,
const enum surface_pixel_format pixel_format);
void hubp3_dcc_control(struct hubp *hubp, bool enable,

View File

@@ -172,7 +172,7 @@ void hubp35_program_pixel_format(
void hubp35_program_surface_config(
struct hubp *hubp,
enum surface_pixel_format format,
union dc_tiling_info *tiling_info,
struct dc_tiling_info *tiling_info,
struct plane_size *plane_size,
enum dc_rotation_angle rotation,
struct dc_plane_dcc_param *dcc,

View File

@@ -65,7 +65,7 @@ void hubp35_program_pixel_format(
void hubp35_program_surface_config(
struct hubp *hubp,
enum surface_pixel_format format,
union dc_tiling_info *tiling_info,
struct dc_tiling_info *tiling_info,
struct plane_size *plane_size,
enum dc_rotation_angle rotation,
struct dc_plane_dcc_param *dcc,

View File

@@ -145,30 +145,44 @@ void hubp401_init(struct hubp *hubp)
}
void hubp401_vready_at_or_After_vsync(struct hubp *hubp,
struct _vcs_dpi_display_pipe_dest_params_st *pipe_dest)
union dml2_global_sync_programming *pipe_global_sync,
struct dc_crtc_timing *timing)
{
uint32_t value = 0;
unsigned int vstartup_lines = pipe_global_sync->dcn4x.vstartup_lines;
unsigned int vupdate_offset_pixels = pipe_global_sync->dcn4x.vupdate_offset_pixels;
unsigned int vupdate_width_pixels = pipe_global_sync->dcn4x.vupdate_vupdate_width_pixels;
unsigned int vready_offset_pixels = pipe_global_sync->dcn4x.vready_offset_pixels;
unsigned int htotal = timing->h_total;
unsigned int vblank_start = 0;
unsigned int vblank_end = 0;
unsigned int pixel_width = 0;
uint32_t reg_value = 0;
bool is_vready_at_or_after_vsync = false;
struct dcn20_hubp *hubp2 = TO_DCN20_HUBP(hubp);
/*
* if (VSTARTUP_START - (VREADY_OFFSET+VUPDATE_WIDTH+VUPDATE_OFFSET)/htotal) <= OTG_V_BLANK_END
* Set HUBP_VREADY_AT_OR_AFTER_VSYNC = 1
* else
* Set HUBP_VREADY_AT_OR_AFTER_VSYNC = 0
*/
if (pipe_dest->htotal != 0) {
if ((pipe_dest->vstartup_start - (pipe_dest->vready_offset+pipe_dest->vupdate_width
+ pipe_dest->vupdate_offset) / pipe_dest->htotal) <= pipe_dest->vblank_end) {
value = 1;
} else
value = 0;
if (htotal != 0) {
vblank_start = timing->v_total - timing->v_front_porch;
vblank_end = vblank_start - timing->v_addressable - timing->v_border_top - timing->v_border_bottom;
pixel_width = vready_offset_pixels + vupdate_width_pixels + vupdate_offset_pixels;
is_vready_at_or_after_vsync = (vstartup_lines - pixel_width / htotal) <= vblank_end;
if (is_vready_at_or_after_vsync)
reg_value = 1;
}
REG_UPDATE(DCHUBP_CNTL, HUBP_VREADY_AT_OR_AFTER_VSYNC, value);
REG_UPDATE(DCHUBP_CNTL, HUBP_VREADY_AT_OR_AFTER_VSYNC, reg_value);
}
void hubp401_program_requestor(
struct hubp *hubp,
struct _vcs_dpi_display_rq_regs_st *rq_regs)
struct dml2_display_rq_regs *rq_regs)
{
struct dcn20_hubp *hubp2 = TO_DCN20_HUBP(hubp);
@@ -196,8 +210,8 @@ void hubp401_program_requestor(
void hubp401_program_deadline(
struct hubp *hubp,
struct _vcs_dpi_display_dlg_regs_st *dlg_attr,
struct _vcs_dpi_display_ttu_regs_st *ttu_attr)
struct dml2_display_dlg_regs *dlg_attr,
struct dml2_display_ttu_regs *ttu_attr)
{
struct dcn20_hubp *hubp2 = TO_DCN20_HUBP(hubp);
@@ -294,66 +308,64 @@ void hubp401_program_deadline(
void hubp401_setup(
struct hubp *hubp,
struct _vcs_dpi_display_dlg_regs_st *dlg_attr,
struct _vcs_dpi_display_ttu_regs_st *ttu_attr,
struct _vcs_dpi_display_rq_regs_st *rq_regs,
struct _vcs_dpi_display_pipe_dest_params_st *pipe_dest)
struct dml2_dchub_per_pipe_register_set *pipe_regs,
union dml2_global_sync_programming *pipe_global_sync,
struct dc_crtc_timing *timing)
{
/* otg is locked when this func is called. Register are double buffered.
* disable the requestors is not needed
*/
hubp401_vready_at_or_After_vsync(hubp, pipe_dest);
hubp401_program_requestor(hubp, rq_regs);
hubp401_program_deadline(hubp, dlg_attr, ttu_attr);
hubp401_vready_at_or_After_vsync(hubp, pipe_global_sync, timing);
hubp401_program_requestor(hubp, &pipe_regs->rq_regs);
hubp401_program_deadline(hubp, &pipe_regs->dlg_regs, &pipe_regs->ttu_regs);
}
void hubp401_setup_interdependent(
struct hubp *hubp,
struct _vcs_dpi_display_dlg_regs_st *dlg_attr,
struct _vcs_dpi_display_ttu_regs_st *ttu_attr)
struct dml2_dchub_per_pipe_register_set *pipe_regs)
{
struct dcn20_hubp *hubp2 = TO_DCN20_HUBP(hubp);
REG_SET_2(PREFETCH_SETTINGS, 0,
DST_Y_PREFETCH, dlg_attr->dst_y_prefetch,
VRATIO_PREFETCH, dlg_attr->vratio_prefetch);
DST_Y_PREFETCH, pipe_regs->dlg_regs.dst_y_prefetch,
VRATIO_PREFETCH, pipe_regs->dlg_regs.vratio_prefetch);
REG_SET(PREFETCH_SETTINGS_C, 0,
VRATIO_PREFETCH_C, dlg_attr->vratio_prefetch_c);
VRATIO_PREFETCH_C, pipe_regs->dlg_regs.vratio_prefetch_c);
REG_SET_2(VBLANK_PARAMETERS_0, 0,
DST_Y_PER_VM_VBLANK, dlg_attr->dst_y_per_vm_vblank,
DST_Y_PER_ROW_VBLANK, dlg_attr->dst_y_per_row_vblank);
DST_Y_PER_VM_VBLANK, pipe_regs->dlg_regs.dst_y_per_vm_vblank,
DST_Y_PER_ROW_VBLANK, pipe_regs->dlg_regs.dst_y_per_row_vblank);
REG_SET_2(FLIP_PARAMETERS_0, 0,
DST_Y_PER_VM_FLIP, dlg_attr->dst_y_per_vm_flip,
DST_Y_PER_ROW_FLIP, dlg_attr->dst_y_per_row_flip);
DST_Y_PER_VM_FLIP, pipe_regs->dlg_regs.dst_y_per_vm_flip,
DST_Y_PER_ROW_FLIP, pipe_regs->dlg_regs.dst_y_per_row_flip);
REG_SET(VBLANK_PARAMETERS_3, 0,
REFCYC_PER_META_CHUNK_VBLANK_L, dlg_attr->refcyc_per_meta_chunk_vblank_l);
REFCYC_PER_META_CHUNK_VBLANK_L, pipe_regs->dlg_regs.refcyc_per_meta_chunk_vblank_l);
REG_SET(VBLANK_PARAMETERS_4, 0,
REFCYC_PER_META_CHUNK_VBLANK_C, dlg_attr->refcyc_per_meta_chunk_vblank_c);
REFCYC_PER_META_CHUNK_VBLANK_C, pipe_regs->dlg_regs.refcyc_per_meta_chunk_vblank_c);
REG_SET(FLIP_PARAMETERS_2, 0,
REFCYC_PER_META_CHUNK_FLIP_L, dlg_attr->refcyc_per_meta_chunk_flip_l);
REFCYC_PER_META_CHUNK_FLIP_L, pipe_regs->dlg_regs.refcyc_per_meta_chunk_flip_l);
REG_SET_2(PER_LINE_DELIVERY_PRE, 0,
REFCYC_PER_LINE_DELIVERY_PRE_L, dlg_attr->refcyc_per_line_delivery_pre_l,
REFCYC_PER_LINE_DELIVERY_PRE_C, dlg_attr->refcyc_per_line_delivery_pre_c);
REFCYC_PER_LINE_DELIVERY_PRE_L, pipe_regs->dlg_regs.refcyc_per_line_delivery_pre_l,
REFCYC_PER_LINE_DELIVERY_PRE_C, pipe_regs->dlg_regs.refcyc_per_line_delivery_pre_c);
REG_SET(DCN_SURF0_TTU_CNTL1, 0,
REFCYC_PER_REQ_DELIVERY_PRE,
ttu_attr->refcyc_per_req_delivery_pre_l);
pipe_regs->ttu_regs.refcyc_per_req_delivery_pre_l);
REG_SET(DCN_SURF1_TTU_CNTL1, 0,
REFCYC_PER_REQ_DELIVERY_PRE,
ttu_attr->refcyc_per_req_delivery_pre_c);
pipe_regs->ttu_regs.refcyc_per_req_delivery_pre_c);
REG_SET(DCN_CUR0_TTU_CNTL1, 0,
REFCYC_PER_REQ_DELIVERY_PRE, ttu_attr->refcyc_per_req_delivery_pre_cur0);
REFCYC_PER_REQ_DELIVERY_PRE, pipe_regs->ttu_regs.refcyc_per_req_delivery_pre_cur0);
REG_SET_2(DCN_GLOBAL_TTU_CNTL, 0,
MIN_TTU_VBLANK, ttu_attr->min_ttu_vblank,
QoS_LEVEL_FLIP, ttu_attr->qos_level_flip);
MIN_TTU_VBLANK, pipe_regs->ttu_regs.min_ttu_vblank,
QoS_LEVEL_FLIP, pipe_regs->ttu_regs.qos_level_flip);
}
@@ -532,7 +544,7 @@ void hubp401_dcc_control(struct hubp *hubp,
void hubp401_program_tiling(
struct dcn20_hubp *hubp2,
const union dc_tiling_info *info,
const struct dc_tiling_info *info,
const enum surface_pixel_format pixel_format)
{
/* DCSURF_ADDR_CONFIG still shows up in reg spec, but does not need to be programmed for DCN4x
@@ -580,7 +592,7 @@ void hubp401_program_size(
void hubp401_program_surface_config(
struct hubp *hubp,
enum surface_pixel_format format,
union dc_tiling_info *tiling_info,
struct dc_tiling_info *tiling_info,
struct plane_size *plane_size,
enum dc_rotation_angle rotation,
struct dc_plane_dcc_param *dcc,
@@ -981,8 +993,8 @@ static struct hubp_funcs dcn401_hubp_funcs = {
.hubp_program_surface_flip_and_addr = hubp401_program_surface_flip_and_addr,
.hubp_program_surface_config = hubp401_program_surface_config,
.hubp_is_flip_pending = hubp2_is_flip_pending,
.hubp_setup = hubp401_setup,
.hubp_setup_interdependent = hubp401_setup_interdependent,
.hubp_setup2 = hubp401_setup,
.hubp_setup_interdependent2 = hubp401_setup_interdependent,
.hubp_set_vm_system_aperture_settings = hubp3_set_vm_system_aperture_settings,
.set_blank = hubp2_set_blank,
.set_blank_regs = hubp2_set_blank_regs,

View File

@@ -256,29 +256,15 @@
void hubp401_update_mall_sel(struct hubp *hubp, uint32_t mall_sel, bool c_cursor);
void hubp401_vready_at_or_After_vsync(struct hubp *hubp,
struct _vcs_dpi_display_pipe_dest_params_st *pipe_dest);
void hubp401_program_requestor(
struct hubp *hubp,
struct _vcs_dpi_display_rq_regs_st *rq_regs);
void hubp401_program_deadline(
struct hubp *hubp,
struct _vcs_dpi_display_dlg_regs_st *dlg_attr,
struct _vcs_dpi_display_ttu_regs_st *ttu_attr);
void hubp401_setup(
struct hubp *hubp,
struct _vcs_dpi_display_dlg_regs_st *dlg_attr,
struct _vcs_dpi_display_ttu_regs_st *ttu_attr,
struct _vcs_dpi_display_rq_regs_st *rq_regs,
struct _vcs_dpi_display_pipe_dest_params_st *pipe_dest);
struct dml2_dchub_per_pipe_register_set *pipe_regs,
union dml2_global_sync_programming *pipe_global_sync,
struct dc_crtc_timing *timing);
void hubp401_setup_interdependent(
struct hubp *hubp,
struct _vcs_dpi_display_dlg_regs_st *dlg_attr,
struct _vcs_dpi_display_ttu_regs_st *ttu_attr);
struct dml2_dchub_per_pipe_register_set *pipe_regs);
bool hubp401_program_surface_flip_and_addr(
struct hubp *hubp,
@@ -290,7 +276,7 @@ void hubp401_dcc_control(struct hubp *hubp,
void hubp401_program_tiling(
struct dcn20_hubp *hubp2,
const union dc_tiling_info *info,
const struct dc_tiling_info *info,
const enum surface_pixel_format pixel_format);
void hubp401_program_size(
@@ -302,7 +288,7 @@ void hubp401_program_size(
void hubp401_program_surface_config(
struct hubp *hubp,
enum surface_pixel_format format,
union dc_tiling_info *tiling_info,
struct dc_tiling_info *tiling_info,
struct plane_size *plane_size,
enum dc_rotation_angle rotation,
struct dc_plane_dcc_param *dcc,
@@ -365,4 +351,17 @@ void hubp401_program_3dlut_fl_mode(struct hubp *hubp, enum hubp_3dlut_fl_mode mo
void hubp401_clear_tiling(struct hubp *hubp);
void hubp401_vready_at_or_After_vsync(struct hubp *hubp,
union dml2_global_sync_programming *pipe_global_sync,
struct dc_crtc_timing *timing);
void hubp401_program_requestor(
struct hubp *hubp,
struct dml2_display_rq_regs *rq_regs);
void hubp401_program_deadline(
struct hubp *hubp,
struct dml2_display_dlg_regs *dlg_attr,
struct dml2_display_ttu_regs *ttu_attr);
#endif /* __DC_HUBP_DCN401_H__ */

View File

@@ -1288,7 +1288,7 @@ static void dcn20_power_on_plane_resources(
}
}
static void dcn20_enable_plane(struct dc *dc, struct pipe_ctx *pipe_ctx,
void dcn20_enable_plane(struct dc *dc, struct pipe_ctx *pipe_ctx,
struct dc_state *context)
{
//if (dc->debug.sanity_checks) {
@@ -1467,7 +1467,7 @@ void dcn20_pipe_control_lock(
}
}
static void dcn20_detect_pipe_changes(struct dc_state *old_state,
void dcn20_detect_pipe_changes(struct dc_state *old_state,
struct dc_state *new_state,
struct pipe_ctx *old_pipe,
struct pipe_ctx *new_pipe)
@@ -1655,7 +1655,7 @@ static void dcn20_detect_pipe_changes(struct dc_state *old_state,
}
}
static void dcn20_update_dchubp_dpp(
void dcn20_update_dchubp_dpp(
struct dc *dc,
struct pipe_ctx *pipe_ctx,
struct dc_state *context)
@@ -1678,25 +1678,41 @@ static void dcn20_update_dchubp_dpp(
* VTG is within DCHUBBUB which is commond block share by each pipe HUBP.
* VTG is 1:1 mapping with OTG. Each pipe HUBP will select which VTG
*/
if (pipe_ctx->update_flags.bits.hubp_rq_dlg_ttu) {
hubp->funcs->hubp_vtg_sel(hubp, pipe_ctx->stream_res.tg->inst);
hubp->funcs->hubp_setup(
hubp,
&pipe_ctx->dlg_regs,
&pipe_ctx->ttu_regs,
&pipe_ctx->rq_regs,
&pipe_ctx->pipe_dlg_param);
if (hubp->funcs->hubp_setup2) {
hubp->funcs->hubp_setup2(
hubp,
&pipe_ctx->hubp_regs,
&pipe_ctx->global_sync,
&pipe_ctx->stream->timing);
} else {
hubp->funcs->hubp_setup(
hubp,
&pipe_ctx->dlg_regs,
&pipe_ctx->ttu_regs,
&pipe_ctx->rq_regs,
&pipe_ctx->pipe_dlg_param);
}
}
if (pipe_ctx->update_flags.bits.unbounded_req && hubp->funcs->set_unbounded_requesting)
hubp->funcs->set_unbounded_requesting(hubp, pipe_ctx->unbounded_req);
if (pipe_ctx->update_flags.bits.hubp_interdependent)
hubp->funcs->hubp_setup_interdependent(
hubp,
&pipe_ctx->dlg_regs,
&pipe_ctx->ttu_regs);
if (pipe_ctx->update_flags.bits.hubp_interdependent) {
if (hubp->funcs->hubp_setup_interdependent2) {
hubp->funcs->hubp_setup_interdependent2(
hubp,
&pipe_ctx->hubp_regs);
} else {
hubp->funcs->hubp_setup_interdependent(
hubp,
&pipe_ctx->dlg_regs,
&pipe_ctx->ttu_regs);
}
}
if (pipe_ctx->update_flags.bits.enable ||
pipe_ctx->update_flags.bits.plane_changed ||
@@ -1756,10 +1772,9 @@ static void dcn20_update_dchubp_dpp(
&pipe_ctx->plane_res.scl_data.viewport_c);
viewport_changed = true;
}
if (hubp->funcs->hubp_program_mcache_id_and_split_coordinate)
hubp->funcs->hubp_program_mcache_id_and_split_coordinate(
hubp,
&pipe_ctx->mcache_regs);
if (hubp->funcs->hubp_program_mcache_id_and_split_coordinate)
hubp->funcs->hubp_program_mcache_id_and_split_coordinate(hubp, &pipe_ctx->mcache_regs);
/* Any updates are handled in dc interface, just need to apply existing for plane enable */
if ((pipe_ctx->update_flags.bits.enable || pipe_ctx->update_flags.bits.opp_changed ||
@@ -1838,7 +1853,7 @@ static void dcn20_update_dchubp_dpp(
hubp->funcs->phantom_hubp_post_enable(hubp);
}
static int calculate_vready_offset_for_group(struct pipe_ctx *pipe)
static int dcn20_calculate_vready_offset_for_group(struct pipe_ctx *pipe)
{
struct pipe_ctx *other_pipe;
int vready_offset = pipe->pipe_dlg_param.vready_offset;
@@ -1864,6 +1879,30 @@ static int calculate_vready_offset_for_group(struct pipe_ctx *pipe)
return vready_offset;
}
static void dcn20_program_tg(
struct dc *dc,
struct pipe_ctx *pipe_ctx,
struct dc_state *context,
struct dce_hwseq *hws)
{
pipe_ctx->stream_res.tg->funcs->program_global_sync(
pipe_ctx->stream_res.tg,
dcn20_calculate_vready_offset_for_group(pipe_ctx),
pipe_ctx->pipe_dlg_param.vstartup_start,
pipe_ctx->pipe_dlg_param.vupdate_offset,
pipe_ctx->pipe_dlg_param.vupdate_width,
pipe_ctx->pipe_dlg_param.pstate_keepout);
if (dc_state_get_pipe_subvp_type(context, pipe_ctx) != SUBVP_PHANTOM)
pipe_ctx->stream_res.tg->funcs->wait_for_state(pipe_ctx->stream_res.tg, CRTC_STATE_VACTIVE);
pipe_ctx->stream_res.tg->funcs->set_vtg_params(
pipe_ctx->stream_res.tg, &pipe_ctx->stream->timing, true);
if (hws->funcs.setup_vupdate_interrupt)
hws->funcs.setup_vupdate_interrupt(dc, pipe_ctx);
}
static void dcn20_program_pipe(
struct dc *dc,
struct pipe_ctx *pipe_ctx,
@@ -1874,33 +1913,17 @@ static void dcn20_program_pipe(
/* Only need to unblank on top pipe */
if (resource_is_pipe_type(pipe_ctx, OTG_MASTER)) {
if (pipe_ctx->update_flags.bits.enable ||
pipe_ctx->update_flags.bits.odm ||
pipe_ctx->stream->update_flags.bits.abm_level)
pipe_ctx->update_flags.bits.odm ||
pipe_ctx->stream->update_flags.bits.abm_level)
hws->funcs.blank_pixel_data(dc, pipe_ctx,
!pipe_ctx->plane_state ||
!pipe_ctx->plane_state->visible);
!pipe_ctx->plane_state ||
!pipe_ctx->plane_state->visible);
}
/* Only update TG on top pipe */
if (pipe_ctx->update_flags.bits.global_sync && !pipe_ctx->top_pipe
&& !pipe_ctx->prev_odm_pipe) {
pipe_ctx->stream_res.tg->funcs->program_global_sync(
pipe_ctx->stream_res.tg,
calculate_vready_offset_for_group(pipe_ctx),
pipe_ctx->pipe_dlg_param.vstartup_start,
pipe_ctx->pipe_dlg_param.vupdate_offset,
pipe_ctx->pipe_dlg_param.vupdate_width,
pipe_ctx->pipe_dlg_param.pstate_keepout);
if (dc_state_get_pipe_subvp_type(context, pipe_ctx) != SUBVP_PHANTOM)
pipe_ctx->stream_res.tg->funcs->wait_for_state(pipe_ctx->stream_res.tg, CRTC_STATE_VACTIVE);
pipe_ctx->stream_res.tg->funcs->set_vtg_params(
pipe_ctx->stream_res.tg, &pipe_ctx->stream->timing, true);
if (hws->funcs.setup_vupdate_interrupt)
hws->funcs.setup_vupdate_interrupt(dc, pipe_ctx);
}
&& !pipe_ctx->prev_odm_pipe)
dcn20_program_tg(dc, pipe_ctx, context, hws);
if (pipe_ctx->update_flags.bits.odm)
hws->funcs.update_odm(dc, context, pipe_ctx);
@@ -1931,22 +1954,22 @@ static void dcn20_program_pipe(
dcn20_update_dchubp_dpp(dc, pipe_ctx, context);
if (pipe_ctx->plane_state && (pipe_ctx->update_flags.bits.enable ||
pipe_ctx->plane_state->update_flags.bits.hdr_mult))
pipe_ctx->plane_state->update_flags.bits.hdr_mult))
hws->funcs.set_hdr_multiplier(pipe_ctx);
if (hws->funcs.populate_mcm_luts) {
if (pipe_ctx->plane_state) {
hws->funcs.populate_mcm_luts(dc, pipe_ctx, pipe_ctx->plane_state->mcm_luts,
pipe_ctx->plane_state->lut_bank_a);
pipe_ctx->plane_state->lut_bank_a);
pipe_ctx->plane_state->lut_bank_a = !pipe_ctx->plane_state->lut_bank_a;
}
}
if (pipe_ctx->plane_state &&
(pipe_ctx->plane_state->update_flags.bits.in_transfer_func_change ||
pipe_ctx->plane_state->update_flags.bits.gamma_change ||
pipe_ctx->plane_state->update_flags.bits.lut_3d ||
pipe_ctx->update_flags.bits.enable))
(pipe_ctx->plane_state->update_flags.bits.in_transfer_func_change ||
pipe_ctx->plane_state->update_flags.bits.gamma_change ||
pipe_ctx->plane_state->update_flags.bits.lut_3d ||
pipe_ctx->update_flags.bits.enable))
hws->funcs.set_input_transfer_func(dc, pipe_ctx, pipe_ctx->plane_state);
/* dcn10_translate_regamma_to_hw_format takes 750us to finish
@@ -1954,10 +1977,10 @@ static void dcn20_program_pipe(
* updating on slave planes
*/
if (pipe_ctx->update_flags.bits.enable ||
pipe_ctx->update_flags.bits.plane_changed ||
pipe_ctx->stream->update_flags.bits.out_tf ||
(pipe_ctx->plane_state &&
pipe_ctx->plane_state->update_flags.bits.output_tf_change))
pipe_ctx->update_flags.bits.plane_changed ||
pipe_ctx->stream->update_flags.bits.out_tf ||
(pipe_ctx->plane_state &&
pipe_ctx->plane_state->update_flags.bits.output_tf_change))
hws->funcs.set_output_transfer_func(dc, pipe_ctx, pipe_ctx->stream);
/* If the pipe has been enabled or has a different opp, we
@@ -1966,7 +1989,7 @@ static void dcn20_program_pipe(
* causes a different pipe to be chosen to odm combine with.
*/
if (pipe_ctx->update_flags.bits.enable
|| pipe_ctx->update_flags.bits.opp_changed) {
|| pipe_ctx->update_flags.bits.opp_changed) {
pipe_ctx->stream_res.opp->funcs->opp_set_dyn_expansion(
pipe_ctx->stream_res.opp,
@@ -1996,14 +2019,14 @@ static void dcn20_program_pipe(
memset(&params, 0, sizeof(params));
odm_opp->funcs->opp_program_bit_depth_reduction(odm_opp, &params);
dc->hwss.set_disp_pattern_generator(dc,
pipe_ctx,
pipe_ctx->stream_res.test_pattern_params.test_pattern,
pipe_ctx->stream_res.test_pattern_params.color_space,
pipe_ctx->stream_res.test_pattern_params.color_depth,
NULL,
pipe_ctx->stream_res.test_pattern_params.width,
pipe_ctx->stream_res.test_pattern_params.height,
pipe_ctx->stream_res.test_pattern_params.offset);
pipe_ctx,
pipe_ctx->stream_res.test_pattern_params.test_pattern,
pipe_ctx->stream_res.test_pattern_params.color_space,
pipe_ctx->stream_res.test_pattern_params.color_depth,
NULL,
pipe_ctx->stream_res.test_pattern_params.width,
pipe_ctx->stream_res.test_pattern_params.height,
pipe_ctx->stream_res.test_pattern_params.offset);
}
}
@@ -2012,11 +2035,12 @@ void dcn20_program_front_end_for_ctx(
struct dc_state *context)
{
int i;
struct dce_hwseq *hws = dc->hwseq;
DC_LOGGER_INIT(dc->ctx->logger);
unsigned int prev_hubp_count = 0;
unsigned int hubp_count = 0;
struct pipe_ctx *pipe;
struct dce_hwseq *hws = dc->hwseq;
struct pipe_ctx *pipe = NULL;
DC_LOGGER_INIT(dc->ctx->logger);
if (resource_is_pipe_topology_changed(dc->current_state, context))
resource_log_pipe_topology_update(dc, context);
@@ -2029,7 +2053,7 @@ void dcn20_program_front_end_for_ctx(
ASSERT(!pipe->plane_state->triplebuffer_flips);
/*turn off triple buffer for full update*/
dc->hwss.program_triplebuffer(
dc, pipe, pipe->plane_state->triplebuffer_flips);
dc, pipe, pipe->plane_state->triplebuffer_flips);
}
}
}
@@ -2044,30 +2068,31 @@ void dcn20_program_front_end_for_ctx(
if (prev_hubp_count == 0 && hubp_count > 0) {
if (dc->res_pool->hubbub->funcs->force_pstate_change_control)
dc->res_pool->hubbub->funcs->force_pstate_change_control(
dc->res_pool->hubbub, true, false);
dc->res_pool->hubbub, true, false);
udelay(500);
}
/* Set pipe update flags and lock pipes */
for (i = 0; i < dc->res_pool->pipe_count; i++)
dcn20_detect_pipe_changes(dc->current_state, context, &dc->current_state->res_ctx.pipe_ctx[i],
&context->res_ctx.pipe_ctx[i]);
&context->res_ctx.pipe_ctx[i]);
/* When disabling phantom pipes, turn on phantom OTG first (so we can get double
* buffer updates properly)
*/
for (i = 0; i < dc->res_pool->pipe_count; i++) {
struct dc_stream_state *stream = dc->current_state->res_ctx.pipe_ctx[i].stream;
pipe = &dc->current_state->res_ctx.pipe_ctx[i];
if (context->res_ctx.pipe_ctx[i].update_flags.bits.disable && stream &&
dc_state_get_pipe_subvp_type(dc->current_state, pipe) == SUBVP_PHANTOM) {
dc_state_get_pipe_subvp_type(dc->current_state, pipe) == SUBVP_PHANTOM) {
struct timing_generator *tg = dc->current_state->res_ctx.pipe_ctx[i].stream_res.tg;
if (tg->funcs->enable_crtc) {
if (dc->hwseq->funcs.blank_pixel_data) {
if (dc->hwseq->funcs.blank_pixel_data)
dc->hwseq->funcs.blank_pixel_data(dc, pipe, true);
}
tg->funcs->enable_crtc(tg);
}
}
@@ -2075,15 +2100,15 @@ void dcn20_program_front_end_for_ctx(
/* OTG blank before disabling all front ends */
for (i = 0; i < dc->res_pool->pipe_count; i++)
if (context->res_ctx.pipe_ctx[i].update_flags.bits.disable
&& !context->res_ctx.pipe_ctx[i].top_pipe
&& !context->res_ctx.pipe_ctx[i].prev_odm_pipe
&& context->res_ctx.pipe_ctx[i].stream)
&& !context->res_ctx.pipe_ctx[i].top_pipe
&& !context->res_ctx.pipe_ctx[i].prev_odm_pipe
&& context->res_ctx.pipe_ctx[i].stream)
hws->funcs.blank_pixel_data(dc, &context->res_ctx.pipe_ctx[i], true);
/* Disconnect mpcc */
for (i = 0; i < dc->res_pool->pipe_count; i++)
if (context->res_ctx.pipe_ctx[i].update_flags.bits.disable
|| context->res_ctx.pipe_ctx[i].update_flags.bits.opp_changed) {
|| context->res_ctx.pipe_ctx[i].update_flags.bits.opp_changed) {
struct hubbub *hubbub = dc->res_pool->hubbub;
/* Phantom pipe DET should be 0, but if a pipe in use is being transitioned to phantom
@@ -2093,13 +2118,18 @@ void dcn20_program_front_end_for_ctx(
* DET allocation.
*/
if ((context->res_ctx.pipe_ctx[i].update_flags.bits.disable ||
(context->res_ctx.pipe_ctx[i].plane_state && dc_state_get_pipe_subvp_type(context, &context->res_ctx.pipe_ctx[i]) == SUBVP_PHANTOM))) {
(context->res_ctx.pipe_ctx[i].plane_state &&
dc_state_get_pipe_subvp_type(context, &context->res_ctx.pipe_ctx[i])
== SUBVP_PHANTOM))) {
if (hubbub->funcs->program_det_size)
hubbub->funcs->program_det_size(hubbub, dc->current_state->res_ctx.pipe_ctx[i].plane_res.hubp->inst, 0);
hubbub->funcs->program_det_size(hubbub,
dc->current_state->res_ctx.pipe_ctx[i].plane_res.hubp->inst, 0);
if (dc->res_pool->hubbub->funcs->program_det_segments)
dc->res_pool->hubbub->funcs->program_det_segments(hubbub, dc->current_state->res_ctx.pipe_ctx[i].plane_res.hubp->inst, 0);
dc->res_pool->hubbub->funcs->program_det_segments(
hubbub, dc->current_state->res_ctx.pipe_ctx[i].plane_res.hubp->inst, 0);
}
hws->funcs.plane_atomic_disconnect(dc, dc->current_state, &dc->current_state->res_ctx.pipe_ctx[i]);
hws->funcs.plane_atomic_disconnect(dc, dc->current_state,
&dc->current_state->res_ctx.pipe_ctx[i]);
DC_LOG_DC("Reset mpcc for pipe %d\n", dc->current_state->res_ctx.pipe_ctx[i].pipe_idx);
}
@@ -2107,9 +2137,9 @@ void dcn20_program_front_end_for_ctx(
for (i = 0; i < dc->res_pool->pipe_count; i++) {
pipe = &context->res_ctx.pipe_ctx[i];
if (resource_is_pipe_type(pipe, OTG_MASTER) &&
!resource_is_pipe_type(pipe, DPP_PIPE) &&
pipe->update_flags.bits.odm &&
hws->funcs.update_odm)
!resource_is_pipe_type(pipe, DPP_PIPE) &&
pipe->update_flags.bits.odm &&
hws->funcs.update_odm)
hws->funcs.update_odm(dc, context, pipe);
}
@@ -2127,25 +2157,28 @@ void dcn20_program_front_end_for_ctx(
else {
/* Don't program phantom pipes in the regular front end programming sequence.
* There is an MPO transition case where a pipe being used by a video plane is
* transitioned directly to be a phantom pipe when closing the MPO video. However
* the phantom pipe will program a new HUBP_VTG_SEL (update takes place right away),
* but the MPO still exists until the double buffered update of the main pipe so we
* will get a frame of underflow if the phantom pipe is programmed here.
* transitioned directly to be a phantom pipe when closing the MPO video.
* However the phantom pipe will program a new HUBP_VTG_SEL (update takes place
* right away) but the MPO still exists until the double buffered update of the
* main pipe so we will get a frame of underflow if the phantom pipe is
* programmed here.
*/
if (pipe->stream && dc_state_get_pipe_subvp_type(context, pipe) != SUBVP_PHANTOM)
if (pipe->stream &&
dc_state_get_pipe_subvp_type(context, pipe) != SUBVP_PHANTOM)
dcn20_program_pipe(dc, pipe, context);
}
pipe = pipe->bottom_pipe;
}
}
/* Program secondary blending tree and writeback pipes */
pipe = &context->res_ctx.pipe_ctx[i];
if (!pipe->top_pipe && !pipe->prev_odm_pipe
&& pipe->stream && pipe->stream->num_wb_info > 0
&& (pipe->update_flags.raw || (pipe->plane_state && pipe->plane_state->update_flags.raw)
|| pipe->stream->update_flags.raw)
&& hws->funcs.program_all_writeback_pipes_in_tree)
&& pipe->stream && pipe->stream->num_wb_info > 0
&& (pipe->update_flags.raw || (pipe->plane_state && pipe->plane_state->update_flags.raw)
|| pipe->stream->update_flags.raw)
&& hws->funcs.program_all_writeback_pipes_in_tree)
hws->funcs.program_all_writeback_pipes_in_tree(dc, pipe->stream, context);
/* Avoid underflow by check of pipe line read when adding 2nd plane. */
@@ -2164,7 +2197,7 @@ void dcn20_program_front_end_for_ctx(
* buffered pending status clear and reset opp head pipe's none double buffered
* registers to their initial state.
*/
static void post_unlock_reset_opp(struct dc *dc,
void dcn20_post_unlock_reset_opp(struct dc *dc,
struct pipe_ctx *opp_head)
{
struct display_stream_compressor *dsc = opp_head->stream_res.dsc;
@@ -2201,16 +2234,17 @@ void dcn20_post_unlock_program_front_end(
struct dc *dc,
struct dc_state *context)
{
int i;
const unsigned int TIMEOUT_FOR_PIPE_ENABLE_US = 100000;
// Timeout for pipe enable
unsigned int timeout_us = 100000;
unsigned int polling_interval_us = 1;
struct dce_hwseq *hwseq = dc->hwseq;
int i;
for (i = 0; i < dc->res_pool->pipe_count; i++)
if (resource_is_pipe_type(&dc->current_state->res_ctx.pipe_ctx[i], OPP_HEAD) &&
!resource_is_pipe_type(&context->res_ctx.pipe_ctx[i], OPP_HEAD))
post_unlock_reset_opp(dc,
&dc->current_state->res_ctx.pipe_ctx[i]);
!resource_is_pipe_type(&context->res_ctx.pipe_ctx[i], OPP_HEAD))
dcn20_post_unlock_reset_opp(dc,
&dc->current_state->res_ctx.pipe_ctx[i]);
for (i = 0; i < dc->res_pool->pipe_count; i++)
if (context->res_ctx.pipe_ctx[i].update_flags.bits.disable)
@@ -2226,11 +2260,12 @@ void dcn20_post_unlock_program_front_end(
struct pipe_ctx *pipe = &context->res_ctx.pipe_ctx[i];
// Don't check flip pending on phantom pipes
if (pipe->plane_state && !pipe->top_pipe && pipe->update_flags.bits.enable &&
dc_state_get_pipe_subvp_type(context, pipe) != SUBVP_PHANTOM) {
dc_state_get_pipe_subvp_type(context, pipe) != SUBVP_PHANTOM) {
struct hubp *hubp = pipe->plane_res.hubp;
int j = 0;
for (j = 0; j < TIMEOUT_FOR_PIPE_ENABLE_US / polling_interval_us
&& hubp->funcs->hubp_is_flip_pending(hubp); j++)
for (j = 0; j < timeout_us / polling_interval_us
&& hubp->funcs->hubp_is_flip_pending(hubp); j++)
udelay(polling_interval_us);
}
}
@@ -2244,15 +2279,14 @@ void dcn20_post_unlock_program_front_end(
* before we've transitioned to 2:1 or 4:1
*/
if (resource_is_pipe_type(old_pipe, OTG_MASTER) && resource_is_pipe_type(pipe, OTG_MASTER) &&
resource_get_odm_slice_count(old_pipe) < resource_get_odm_slice_count(pipe) &&
dc_state_get_pipe_subvp_type(context, pipe) != SUBVP_PHANTOM) {
resource_get_odm_slice_count(old_pipe) < resource_get_odm_slice_count(pipe) &&
dc_state_get_pipe_subvp_type(context, pipe) != SUBVP_PHANTOM) {
int j = 0;
struct timing_generator *tg = pipe->stream_res.tg;
if (tg->funcs->get_optc_double_buffer_pending) {
for (j = 0; j < TIMEOUT_FOR_PIPE_ENABLE_US / polling_interval_us
&& tg->funcs->get_optc_double_buffer_pending(tg); j++)
for (j = 0; j < timeout_us / polling_interval_us
&& tg->funcs->get_optc_double_buffer_pending(tg); j++)
udelay(polling_interval_us);
}
}
@@ -2260,7 +2294,7 @@ void dcn20_post_unlock_program_front_end(
if (dc->res_pool->hubbub->funcs->force_pstate_change_control)
dc->res_pool->hubbub->funcs->force_pstate_change_control(
dc->res_pool->hubbub, false, false);
dc->res_pool->hubbub, false, false);
for (i = 0; i < dc->res_pool->pipe_count; i++) {
struct pipe_ctx *pipe = &context->res_ctx.pipe_ctx[i];
@@ -2291,11 +2325,11 @@ void dcn20_post_unlock_program_front_end(
return;
/* P-State support transitions:
* Natural -> FPO: P-State disabled in prepare, force disallow anytime is safe
* FPO -> Natural: Unforce anytime after FW disable is safe (P-State will assert naturally)
* Unsupported -> FPO: P-State enabled in optimize, force disallow anytime is safe
* FPO -> Unsupported: P-State disabled in prepare, unforce disallow anytime is safe
* FPO <-> SubVP: Force disallow is maintained on the FPO / SubVP pipes
* Natural -> FPO: P-State disabled in prepare, force disallow anytime is safe
* FPO -> Natural: Unforce anytime after FW disable is safe (P-State will assert naturally)
* Unsupported -> FPO: P-State enabled in optimize, force disallow anytime is safe
* FPO -> Unsupported: P-State disabled in prepare, unforce disallow anytime is safe
* FPO <-> SubVP: Force disallow is maintained on the FPO / SubVP pipes
*/
if (hwseq->funcs.update_force_pstate)
dc->hwseq->funcs.update_force_pstate(dc, context);
@@ -2310,12 +2344,11 @@ void dcn20_post_unlock_program_front_end(
if (hwseq->wa.DEGVIDCN21)
dc->res_pool->hubbub->funcs->apply_DEDCN21_147_wa(dc->res_pool->hubbub);
/* WA for stutter underflow during MPO transitions when adding 2nd plane */
if (hwseq->wa.disallow_self_refresh_during_multi_plane_transition) {
if (dc->current_state->stream_status[0].plane_count == 1 &&
context->stream_status[0].plane_count > 1) {
context->stream_status[0].plane_count > 1) {
struct timing_generator *tg = dc->res_pool->timing_generators[0];
@@ -2463,7 +2496,7 @@ bool dcn20_update_bandwidth(
pipe_ctx->stream_res.tg->funcs->program_global_sync(
pipe_ctx->stream_res.tg,
calculate_vready_offset_for_group(pipe_ctx),
dcn20_calculate_vready_offset_for_group(pipe_ctx),
pipe_ctx->pipe_dlg_param.vstartup_start,
pipe_ctx->pipe_dlg_param.vupdate_offset,
pipe_ctx->pipe_dlg_param.vupdate_width,

Some files were not shown because too many files have changed in this diff Show More