mirror of
git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2026-04-14 10:19:08 +08:00
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:
@@ -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);
|
||||
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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");
|
||||
|
||||
@@ -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),
|
||||
|
||||
@@ -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;
|
||||
|
||||
56
drivers/gpu/drm/amd/amdgpu/gfx_v10_0_cleaner_shader.h
Normal file
56
drivers/gpu/drm/amd/amdgpu/gfx_v10_0_cleaner_shader.h
Normal 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,
|
||||
};
|
||||
124
drivers/gpu/drm/amd/amdgpu/gfx_v10_3_0_cleaner_shader.asm
Normal file
124
drivers/gpu/drm/amd/amdgpu/gfx_v10_3_0_cleaner_shader.asm
Normal 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
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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 */
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
1126
drivers/gpu/drm/amd/amdkfd/cwsr_trap_handler_gfx12.asm
Normal file
1126
drivers/gpu/drm/amd/amdkfd/cwsr_trap_handler_gfx12.asm
Normal file
File diff suppressed because it is too large
Load Diff
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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))
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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__ */
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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];
|
||||
|
||||
@@ -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) {
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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
|
||||
};
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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_ */
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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(
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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_ */
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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__ */
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
@@ -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__ */
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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)) {
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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"
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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__ */
|
||||
|
||||
@@ -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(¶ms, 0, sizeof(params));
|
||||
odm_opp->funcs->opp_program_bit_depth_reduction(odm_opp, ¶ms);
|
||||
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
Reference in New Issue
Block a user