Merge tag 'drm-fixes-5.5-2019-12-12' of git://people.freedesktop.org/~agd5f/linux into drm-fixes
drm-fixes-5.5-2019-12-12: amdgpu: - DC fixes for renoir - Gfx8 fence flush align with mesa - Power profile fix for arcturus - Freesync fix - DC I2c over aux fix - DC aux defer fix - GPU reset fix - GPUVM invalidation semaphore fixes for PCO and SR-IOV - Golden settings updates for gfx10 Signed-off-by: Dave Airlie <airlied@redhat.com> From: Alex Deucher <alexdeucher@gmail.com> Link: https://patchwork.freedesktop.org/patch/msgid/20191212223211.8034-1-alexander.deucher@amd.com
This commit is contained in:
@@ -1,4 +1,4 @@
|
|||||||
# SPDX-License-Identifier: GPL-2.0-only
|
# SPDX-License-Identifier: MIT
|
||||||
menu "ACP (Audio CoProcessor) Configuration"
|
menu "ACP (Audio CoProcessor) Configuration"
|
||||||
|
|
||||||
config DRM_AMD_ACP
|
config DRM_AMD_ACP
|
||||||
|
@@ -1,4 +1,4 @@
|
|||||||
# SPDX-License-Identifier: GPL-2.0-only
|
# SPDX-License-Identifier: MIT
|
||||||
config DRM_AMDGPU_SI
|
config DRM_AMDGPU_SI
|
||||||
bool "Enable amdgpu support for SI parts"
|
bool "Enable amdgpu support for SI parts"
|
||||||
depends on DRM_AMDGPU
|
depends on DRM_AMDGPU
|
||||||
|
@@ -604,11 +604,8 @@ void amdgpu_ctx_mgr_entity_fini(struct amdgpu_ctx_mgr *mgr)
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (i = 0; i < num_entities; i++) {
|
for (i = 0; i < num_entities; i++)
|
||||||
mutex_lock(&ctx->adev->lock_reset);
|
|
||||||
drm_sched_entity_fini(&ctx->entities[0][i].entity);
|
drm_sched_entity_fini(&ctx->entities[0][i].entity);
|
||||||
mutex_unlock(&ctx->adev->lock_reset);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -268,23 +268,29 @@ static void df_v3_6_update_medium_grain_clock_gating(struct amdgpu_device *adev,
|
|||||||
{
|
{
|
||||||
u32 tmp;
|
u32 tmp;
|
||||||
|
|
||||||
|
if (adev->cg_flags & AMD_CG_SUPPORT_DF_MGCG) {
|
||||||
/* Put DF on broadcast mode */
|
/* Put DF on broadcast mode */
|
||||||
adev->df_funcs->enable_broadcast_mode(adev, true);
|
adev->df_funcs->enable_broadcast_mode(adev, true);
|
||||||
|
|
||||||
if (enable && (adev->cg_flags & AMD_CG_SUPPORT_DF_MGCG)) {
|
if (enable) {
|
||||||
tmp = RREG32_SOC15(DF, 0, mmDF_PIE_AON0_DfGlobalClkGater);
|
tmp = RREG32_SOC15(DF, 0,
|
||||||
|
mmDF_PIE_AON0_DfGlobalClkGater);
|
||||||
tmp &= ~DF_PIE_AON0_DfGlobalClkGater__MGCGMode_MASK;
|
tmp &= ~DF_PIE_AON0_DfGlobalClkGater__MGCGMode_MASK;
|
||||||
tmp |= DF_V3_6_MGCG_ENABLE_15_CYCLE_DELAY;
|
tmp |= DF_V3_6_MGCG_ENABLE_15_CYCLE_DELAY;
|
||||||
WREG32_SOC15(DF, 0, mmDF_PIE_AON0_DfGlobalClkGater, tmp);
|
WREG32_SOC15(DF, 0,
|
||||||
|
mmDF_PIE_AON0_DfGlobalClkGater, tmp);
|
||||||
} else {
|
} else {
|
||||||
tmp = RREG32_SOC15(DF, 0, mmDF_PIE_AON0_DfGlobalClkGater);
|
tmp = RREG32_SOC15(DF, 0,
|
||||||
|
mmDF_PIE_AON0_DfGlobalClkGater);
|
||||||
tmp &= ~DF_PIE_AON0_DfGlobalClkGater__MGCGMode_MASK;
|
tmp &= ~DF_PIE_AON0_DfGlobalClkGater__MGCGMode_MASK;
|
||||||
tmp |= DF_V3_6_MGCG_DISABLE;
|
tmp |= DF_V3_6_MGCG_DISABLE;
|
||||||
WREG32_SOC15(DF, 0, mmDF_PIE_AON0_DfGlobalClkGater, tmp);
|
WREG32_SOC15(DF, 0,
|
||||||
|
mmDF_PIE_AON0_DfGlobalClkGater, tmp);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Exit broadcast mode */
|
/* Exit broadcast mode */
|
||||||
adev->df_funcs->enable_broadcast_mode(adev, false);
|
adev->df_funcs->enable_broadcast_mode(adev, false);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void df_v3_6_get_clockgating_state(struct amdgpu_device *adev,
|
static void df_v3_6_get_clockgating_state(struct amdgpu_device *adev,
|
||||||
|
@@ -117,10 +117,13 @@ static const struct soc15_reg_golden golden_settings_gc_10_1[] =
|
|||||||
SOC15_REG_GOLDEN_VALUE(GC, 0, mmGL2C_CGTT_SCLK_CTRL, 0x10000000, 0x10000100),
|
SOC15_REG_GOLDEN_VALUE(GC, 0, mmGL2C_CGTT_SCLK_CTRL, 0x10000000, 0x10000100),
|
||||||
SOC15_REG_GOLDEN_VALUE(GC, 0, mmGL2C_CTRL2, 0xffffffff, 0x1402002f),
|
SOC15_REG_GOLDEN_VALUE(GC, 0, mmGL2C_CTRL2, 0xffffffff, 0x1402002f),
|
||||||
SOC15_REG_GOLDEN_VALUE(GC, 0, mmGL2C_CTRL3, 0xffff9fff, 0x00001188),
|
SOC15_REG_GOLDEN_VALUE(GC, 0, mmGL2C_CTRL3, 0xffff9fff, 0x00001188),
|
||||||
|
SOC15_REG_GOLDEN_VALUE(GC, 0, mmPA_SC_BINNER_TIMEOUT_COUNTER, 0xffffffff, 0x00000800),
|
||||||
SOC15_REG_GOLDEN_VALUE(GC, 0, mmPA_SC_ENHANCE, 0x3fffffff, 0x08000009),
|
SOC15_REG_GOLDEN_VALUE(GC, 0, mmPA_SC_ENHANCE, 0x3fffffff, 0x08000009),
|
||||||
SOC15_REG_GOLDEN_VALUE(GC, 0, mmPA_SC_ENHANCE_1, 0x00400000, 0x04440000),
|
SOC15_REG_GOLDEN_VALUE(GC, 0, mmPA_SC_ENHANCE_1, 0x00400000, 0x04440000),
|
||||||
|
SOC15_REG_GOLDEN_VALUE(GC, 0, mmPA_SC_ENHANCE_2, 0x00000800, 0x00000820),
|
||||||
SOC15_REG_GOLDEN_VALUE(GC, 0, mmPA_SC_LINE_STIPPLE_STATE, 0x0000ff0f, 0x00000000),
|
SOC15_REG_GOLDEN_VALUE(GC, 0, mmPA_SC_LINE_STIPPLE_STATE, 0x0000ff0f, 0x00000000),
|
||||||
SOC15_REG_GOLDEN_VALUE(GC, 0, mmRMI_SPARE, 0xffffffff, 0xffff3101),
|
SOC15_REG_GOLDEN_VALUE(GC, 0, mmRMI_SPARE, 0xffffffff, 0xffff3101),
|
||||||
|
SOC15_REG_GOLDEN_VALUE(GC, 0, mmSPI_CONFIG_CNTL, 0x001f0000, 0x00070104),
|
||||||
SOC15_REG_GOLDEN_VALUE(GC, 0, mmSQ_ALU_CLK_CTRL, 0xffffffff, 0xffffffff),
|
SOC15_REG_GOLDEN_VALUE(GC, 0, mmSQ_ALU_CLK_CTRL, 0xffffffff, 0xffffffff),
|
||||||
SOC15_REG_GOLDEN_VALUE(GC, 0, mmSQ_ARB_CONFIG, 0x00000100, 0x00000130),
|
SOC15_REG_GOLDEN_VALUE(GC, 0, mmSQ_ARB_CONFIG, 0x00000100, 0x00000130),
|
||||||
SOC15_REG_GOLDEN_VALUE(GC, 0, mmSQ_LDS_CLK_CTRL, 0xffffffff, 0xffffffff),
|
SOC15_REG_GOLDEN_VALUE(GC, 0, mmSQ_LDS_CLK_CTRL, 0xffffffff, 0xffffffff),
|
||||||
@@ -162,10 +165,13 @@ static const struct soc15_reg_golden golden_settings_gc_10_1_1[] =
|
|||||||
SOC15_REG_GOLDEN_VALUE(GC, 0, mmGL2C_CGTT_SCLK_CTRL, 0xffff0fff, 0x10000100),
|
SOC15_REG_GOLDEN_VALUE(GC, 0, mmGL2C_CGTT_SCLK_CTRL, 0xffff0fff, 0x10000100),
|
||||||
SOC15_REG_GOLDEN_VALUE(GC, 0, mmGL2C_CTRL2, 0xffffffff, 0x1402002f),
|
SOC15_REG_GOLDEN_VALUE(GC, 0, mmGL2C_CTRL2, 0xffffffff, 0x1402002f),
|
||||||
SOC15_REG_GOLDEN_VALUE(GC, 0, mmGL2C_CTRL3, 0xffffbfff, 0x00000188),
|
SOC15_REG_GOLDEN_VALUE(GC, 0, mmGL2C_CTRL3, 0xffffbfff, 0x00000188),
|
||||||
|
SOC15_REG_GOLDEN_VALUE(GC, 0, mmPA_SC_BINNER_TIMEOUT_COUNTER, 0xffffffff, 0x00000800),
|
||||||
SOC15_REG_GOLDEN_VALUE(GC, 0, mmPA_SC_ENHANCE, 0x3fffffff, 0x08000009),
|
SOC15_REG_GOLDEN_VALUE(GC, 0, mmPA_SC_ENHANCE, 0x3fffffff, 0x08000009),
|
||||||
SOC15_REG_GOLDEN_VALUE(GC, 0, mmPA_SC_ENHANCE_1, 0x00400000, 0x04440000),
|
SOC15_REG_GOLDEN_VALUE(GC, 0, mmPA_SC_ENHANCE_1, 0x00400000, 0x04440000),
|
||||||
|
SOC15_REG_GOLDEN_VALUE(GC, 0, mmPA_SC_ENHANCE_2, 0x00000800, 0x00000820),
|
||||||
SOC15_REG_GOLDEN_VALUE(GC, 0, mmPA_SC_LINE_STIPPLE_STATE, 0x0000ff0f, 0x00000000),
|
SOC15_REG_GOLDEN_VALUE(GC, 0, mmPA_SC_LINE_STIPPLE_STATE, 0x0000ff0f, 0x00000000),
|
||||||
SOC15_REG_GOLDEN_VALUE(GC, 0, mmRMI_SPARE, 0xffffffff, 0xffff3101),
|
SOC15_REG_GOLDEN_VALUE(GC, 0, mmRMI_SPARE, 0xffffffff, 0xffff3101),
|
||||||
|
SOC15_REG_GOLDEN_VALUE(GC, 0, mmSPI_CONFIG_CNTL, 0x001f0000, 0x00070105),
|
||||||
SOC15_REG_GOLDEN_VALUE(GC, 0, mmSQ_ALU_CLK_CTRL, 0xffffffff, 0xffffffff),
|
SOC15_REG_GOLDEN_VALUE(GC, 0, mmSQ_ALU_CLK_CTRL, 0xffffffff, 0xffffffff),
|
||||||
SOC15_REG_GOLDEN_VALUE(GC, 0, mmSQ_ARB_CONFIG, 0x00000133, 0x00000130),
|
SOC15_REG_GOLDEN_VALUE(GC, 0, mmSQ_ARB_CONFIG, 0x00000133, 0x00000130),
|
||||||
SOC15_REG_GOLDEN_VALUE(GC, 0, mmSQ_LDS_CLK_CTRL, 0xffffffff, 0xffffffff),
|
SOC15_REG_GOLDEN_VALUE(GC, 0, mmSQ_LDS_CLK_CTRL, 0xffffffff, 0xffffffff),
|
||||||
|
@@ -6146,7 +6146,23 @@ static void gfx_v8_0_ring_emit_fence_gfx(struct amdgpu_ring *ring, u64 addr,
|
|||||||
bool write64bit = flags & AMDGPU_FENCE_FLAG_64BIT;
|
bool write64bit = flags & AMDGPU_FENCE_FLAG_64BIT;
|
||||||
bool int_sel = flags & AMDGPU_FENCE_FLAG_INT;
|
bool int_sel = flags & AMDGPU_FENCE_FLAG_INT;
|
||||||
|
|
||||||
/* EVENT_WRITE_EOP - flush caches, send int */
|
/* Workaround for cache flush problems. First send a dummy EOP
|
||||||
|
* event down the pipe with seq one below.
|
||||||
|
*/
|
||||||
|
amdgpu_ring_write(ring, PACKET3(PACKET3_EVENT_WRITE_EOP, 4));
|
||||||
|
amdgpu_ring_write(ring, (EOP_TCL1_ACTION_EN |
|
||||||
|
EOP_TC_ACTION_EN |
|
||||||
|
EOP_TC_WB_ACTION_EN |
|
||||||
|
EVENT_TYPE(CACHE_FLUSH_AND_INV_TS_EVENT) |
|
||||||
|
EVENT_INDEX(5)));
|
||||||
|
amdgpu_ring_write(ring, addr & 0xfffffffc);
|
||||||
|
amdgpu_ring_write(ring, (upper_32_bits(addr) & 0xffff) |
|
||||||
|
DATA_SEL(1) | INT_SEL(0));
|
||||||
|
amdgpu_ring_write(ring, lower_32_bits(seq - 1));
|
||||||
|
amdgpu_ring_write(ring, upper_32_bits(seq - 1));
|
||||||
|
|
||||||
|
/* Then send the real EOP event down the pipe:
|
||||||
|
* EVENT_WRITE_EOP - flush caches, send int */
|
||||||
amdgpu_ring_write(ring, PACKET3(PACKET3_EVENT_WRITE_EOP, 4));
|
amdgpu_ring_write(ring, PACKET3(PACKET3_EVENT_WRITE_EOP, 4));
|
||||||
amdgpu_ring_write(ring, (EOP_TCL1_ACTION_EN |
|
amdgpu_ring_write(ring, (EOP_TCL1_ACTION_EN |
|
||||||
EOP_TC_ACTION_EN |
|
EOP_TC_ACTION_EN |
|
||||||
@@ -6888,7 +6904,7 @@ static const struct amdgpu_ring_funcs gfx_v8_0_ring_funcs_gfx = {
|
|||||||
5 + /* COND_EXEC */
|
5 + /* COND_EXEC */
|
||||||
7 + /* PIPELINE_SYNC */
|
7 + /* PIPELINE_SYNC */
|
||||||
VI_FLUSH_GPU_TLB_NUM_WREG * 5 + 9 + /* VM_FLUSH */
|
VI_FLUSH_GPU_TLB_NUM_WREG * 5 + 9 + /* VM_FLUSH */
|
||||||
8 + /* FENCE for VM_FLUSH */
|
12 + /* FENCE for VM_FLUSH */
|
||||||
20 + /* GDS switch */
|
20 + /* GDS switch */
|
||||||
4 + /* double SWITCH_BUFFER,
|
4 + /* double SWITCH_BUFFER,
|
||||||
the first COND_EXEC jump to the place just
|
the first COND_EXEC jump to the place just
|
||||||
@@ -6900,7 +6916,7 @@ static const struct amdgpu_ring_funcs gfx_v8_0_ring_funcs_gfx = {
|
|||||||
31 + /* DE_META */
|
31 + /* DE_META */
|
||||||
3 + /* CNTX_CTRL */
|
3 + /* CNTX_CTRL */
|
||||||
5 + /* HDP_INVL */
|
5 + /* HDP_INVL */
|
||||||
8 + 8 + /* FENCE x2 */
|
12 + 12 + /* FENCE x2 */
|
||||||
2, /* SWITCH_BUFFER */
|
2, /* SWITCH_BUFFER */
|
||||||
.emit_ib_size = 4, /* gfx_v8_0_ring_emit_ib_gfx */
|
.emit_ib_size = 4, /* gfx_v8_0_ring_emit_ib_gfx */
|
||||||
.emit_ib = gfx_v8_0_ring_emit_ib_gfx,
|
.emit_ib = gfx_v8_0_ring_emit_ib_gfx,
|
||||||
|
@@ -219,6 +219,21 @@ static uint32_t gmc_v10_0_get_invalidate_req(unsigned int vmid,
|
|||||||
return req;
|
return req;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* gmc_v10_0_use_invalidate_semaphore - judge whether to use semaphore
|
||||||
|
*
|
||||||
|
* @adev: amdgpu_device pointer
|
||||||
|
* @vmhub: vmhub type
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
static bool gmc_v10_0_use_invalidate_semaphore(struct amdgpu_device *adev,
|
||||||
|
uint32_t vmhub)
|
||||||
|
{
|
||||||
|
return ((vmhub == AMDGPU_MMHUB_0 ||
|
||||||
|
vmhub == AMDGPU_MMHUB_1) &&
|
||||||
|
(!amdgpu_sriov_vf(adev)));
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* GART
|
* GART
|
||||||
* VMID 0 is the physical GPU addresses as used by the kernel.
|
* VMID 0 is the physical GPU addresses as used by the kernel.
|
||||||
@@ -229,6 +244,7 @@ static uint32_t gmc_v10_0_get_invalidate_req(unsigned int vmid,
|
|||||||
static void gmc_v10_0_flush_vm_hub(struct amdgpu_device *adev, uint32_t vmid,
|
static void gmc_v10_0_flush_vm_hub(struct amdgpu_device *adev, uint32_t vmid,
|
||||||
unsigned int vmhub, uint32_t flush_type)
|
unsigned int vmhub, uint32_t flush_type)
|
||||||
{
|
{
|
||||||
|
bool use_semaphore = gmc_v10_0_use_invalidate_semaphore(adev, vmhub);
|
||||||
struct amdgpu_vmhub *hub = &adev->vmhub[vmhub];
|
struct amdgpu_vmhub *hub = &adev->vmhub[vmhub];
|
||||||
u32 tmp = gmc_v10_0_get_invalidate_req(vmid, flush_type);
|
u32 tmp = gmc_v10_0_get_invalidate_req(vmid, flush_type);
|
||||||
/* Use register 17 for GART */
|
/* Use register 17 for GART */
|
||||||
@@ -244,8 +260,7 @@ static void gmc_v10_0_flush_vm_hub(struct amdgpu_device *adev, uint32_t vmid,
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
/* TODO: It needs to continue working on debugging with semaphore for GFXHUB as well. */
|
/* TODO: It needs to continue working on debugging with semaphore for GFXHUB as well. */
|
||||||
if (vmhub == AMDGPU_MMHUB_0 ||
|
if (use_semaphore) {
|
||||||
vmhub == AMDGPU_MMHUB_1) {
|
|
||||||
for (i = 0; i < adev->usec_timeout; i++) {
|
for (i = 0; i < adev->usec_timeout; i++) {
|
||||||
/* a read return value of 1 means semaphore acuqire */
|
/* a read return value of 1 means semaphore acuqire */
|
||||||
tmp = RREG32_NO_KIQ(hub->vm_inv_eng0_sem + eng);
|
tmp = RREG32_NO_KIQ(hub->vm_inv_eng0_sem + eng);
|
||||||
@@ -278,8 +293,7 @@ static void gmc_v10_0_flush_vm_hub(struct amdgpu_device *adev, uint32_t vmid,
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* TODO: It needs to continue working on debugging with semaphore for GFXHUB as well. */
|
/* TODO: It needs to continue working on debugging with semaphore for GFXHUB as well. */
|
||||||
if (vmhub == AMDGPU_MMHUB_0 ||
|
if (use_semaphore)
|
||||||
vmhub == AMDGPU_MMHUB_1)
|
|
||||||
/*
|
/*
|
||||||
* add semaphore release after invalidation,
|
* add semaphore release after invalidation,
|
||||||
* write with 0 means semaphore release
|
* write with 0 means semaphore release
|
||||||
@@ -369,6 +383,7 @@ error_alloc:
|
|||||||
static uint64_t gmc_v10_0_emit_flush_gpu_tlb(struct amdgpu_ring *ring,
|
static uint64_t gmc_v10_0_emit_flush_gpu_tlb(struct amdgpu_ring *ring,
|
||||||
unsigned vmid, uint64_t pd_addr)
|
unsigned vmid, uint64_t pd_addr)
|
||||||
{
|
{
|
||||||
|
bool use_semaphore = gmc_v10_0_use_invalidate_semaphore(ring->adev, ring->funcs->vmhub);
|
||||||
struct amdgpu_vmhub *hub = &ring->adev->vmhub[ring->funcs->vmhub];
|
struct amdgpu_vmhub *hub = &ring->adev->vmhub[ring->funcs->vmhub];
|
||||||
uint32_t req = gmc_v10_0_get_invalidate_req(vmid, 0);
|
uint32_t req = gmc_v10_0_get_invalidate_req(vmid, 0);
|
||||||
unsigned eng = ring->vm_inv_eng;
|
unsigned eng = ring->vm_inv_eng;
|
||||||
@@ -381,8 +396,7 @@ static uint64_t gmc_v10_0_emit_flush_gpu_tlb(struct amdgpu_ring *ring,
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
/* TODO: It needs to continue working on debugging with semaphore for GFXHUB as well. */
|
/* TODO: It needs to continue working on debugging with semaphore for GFXHUB as well. */
|
||||||
if (ring->funcs->vmhub == AMDGPU_MMHUB_0 ||
|
if (use_semaphore)
|
||||||
ring->funcs->vmhub == AMDGPU_MMHUB_1)
|
|
||||||
/* a read return value of 1 means semaphore acuqire */
|
/* a read return value of 1 means semaphore acuqire */
|
||||||
amdgpu_ring_emit_reg_wait(ring,
|
amdgpu_ring_emit_reg_wait(ring,
|
||||||
hub->vm_inv_eng0_sem + eng, 0x1, 0x1);
|
hub->vm_inv_eng0_sem + eng, 0x1, 0x1);
|
||||||
@@ -398,8 +412,7 @@ static uint64_t gmc_v10_0_emit_flush_gpu_tlb(struct amdgpu_ring *ring,
|
|||||||
req, 1 << vmid);
|
req, 1 << vmid);
|
||||||
|
|
||||||
/* TODO: It needs to continue working on debugging with semaphore for GFXHUB as well. */
|
/* TODO: It needs to continue working on debugging with semaphore for GFXHUB as well. */
|
||||||
if (ring->funcs->vmhub == AMDGPU_MMHUB_0 ||
|
if (use_semaphore)
|
||||||
ring->funcs->vmhub == AMDGPU_MMHUB_1)
|
|
||||||
/*
|
/*
|
||||||
* add semaphore release after invalidation,
|
* add semaphore release after invalidation,
|
||||||
* write with 0 means semaphore release
|
* write with 0 means semaphore release
|
||||||
|
@@ -416,6 +416,24 @@ static uint32_t gmc_v9_0_get_invalidate_req(unsigned int vmid,
|
|||||||
return req;
|
return req;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* gmc_v9_0_use_invalidate_semaphore - judge whether to use semaphore
|
||||||
|
*
|
||||||
|
* @adev: amdgpu_device pointer
|
||||||
|
* @vmhub: vmhub type
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
static bool gmc_v9_0_use_invalidate_semaphore(struct amdgpu_device *adev,
|
||||||
|
uint32_t vmhub)
|
||||||
|
{
|
||||||
|
return ((vmhub == AMDGPU_MMHUB_0 ||
|
||||||
|
vmhub == AMDGPU_MMHUB_1) &&
|
||||||
|
(!amdgpu_sriov_vf(adev)) &&
|
||||||
|
(!(adev->asic_type == CHIP_RAVEN &&
|
||||||
|
adev->rev_id < 0x8 &&
|
||||||
|
adev->pdev->device == 0x15d8)));
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* GART
|
* GART
|
||||||
* VMID 0 is the physical GPU addresses as used by the kernel.
|
* VMID 0 is the physical GPU addresses as used by the kernel.
|
||||||
@@ -435,6 +453,7 @@ static uint32_t gmc_v9_0_get_invalidate_req(unsigned int vmid,
|
|||||||
static void gmc_v9_0_flush_gpu_tlb(struct amdgpu_device *adev, uint32_t vmid,
|
static void gmc_v9_0_flush_gpu_tlb(struct amdgpu_device *adev, uint32_t vmid,
|
||||||
uint32_t vmhub, uint32_t flush_type)
|
uint32_t vmhub, uint32_t flush_type)
|
||||||
{
|
{
|
||||||
|
bool use_semaphore = gmc_v9_0_use_invalidate_semaphore(adev, vmhub);
|
||||||
const unsigned eng = 17;
|
const unsigned eng = 17;
|
||||||
u32 j, tmp;
|
u32 j, tmp;
|
||||||
struct amdgpu_vmhub *hub;
|
struct amdgpu_vmhub *hub;
|
||||||
@@ -468,8 +487,7 @@ static void gmc_v9_0_flush_gpu_tlb(struct amdgpu_device *adev, uint32_t vmid,
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
/* TODO: It needs to continue working on debugging with semaphore for GFXHUB as well. */
|
/* TODO: It needs to continue working on debugging with semaphore for GFXHUB as well. */
|
||||||
if (vmhub == AMDGPU_MMHUB_0 ||
|
if (use_semaphore) {
|
||||||
vmhub == AMDGPU_MMHUB_1) {
|
|
||||||
for (j = 0; j < adev->usec_timeout; j++) {
|
for (j = 0; j < adev->usec_timeout; j++) {
|
||||||
/* a read return value of 1 means semaphore acuqire */
|
/* a read return value of 1 means semaphore acuqire */
|
||||||
tmp = RREG32_NO_KIQ(hub->vm_inv_eng0_sem + eng);
|
tmp = RREG32_NO_KIQ(hub->vm_inv_eng0_sem + eng);
|
||||||
@@ -499,8 +517,7 @@ static void gmc_v9_0_flush_gpu_tlb(struct amdgpu_device *adev, uint32_t vmid,
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* TODO: It needs to continue working on debugging with semaphore for GFXHUB as well. */
|
/* TODO: It needs to continue working on debugging with semaphore for GFXHUB as well. */
|
||||||
if (vmhub == AMDGPU_MMHUB_0 ||
|
if (use_semaphore)
|
||||||
vmhub == AMDGPU_MMHUB_1)
|
|
||||||
/*
|
/*
|
||||||
* add semaphore release after invalidation,
|
* add semaphore release after invalidation,
|
||||||
* write with 0 means semaphore release
|
* write with 0 means semaphore release
|
||||||
@@ -518,6 +535,7 @@ static void gmc_v9_0_flush_gpu_tlb(struct amdgpu_device *adev, uint32_t vmid,
|
|||||||
static uint64_t gmc_v9_0_emit_flush_gpu_tlb(struct amdgpu_ring *ring,
|
static uint64_t gmc_v9_0_emit_flush_gpu_tlb(struct amdgpu_ring *ring,
|
||||||
unsigned vmid, uint64_t pd_addr)
|
unsigned vmid, uint64_t pd_addr)
|
||||||
{
|
{
|
||||||
|
bool use_semaphore = gmc_v9_0_use_invalidate_semaphore(ring->adev, ring->funcs->vmhub);
|
||||||
struct amdgpu_device *adev = ring->adev;
|
struct amdgpu_device *adev = ring->adev;
|
||||||
struct amdgpu_vmhub *hub = &adev->vmhub[ring->funcs->vmhub];
|
struct amdgpu_vmhub *hub = &adev->vmhub[ring->funcs->vmhub];
|
||||||
uint32_t req = gmc_v9_0_get_invalidate_req(vmid, 0);
|
uint32_t req = gmc_v9_0_get_invalidate_req(vmid, 0);
|
||||||
@@ -531,8 +549,7 @@ static uint64_t gmc_v9_0_emit_flush_gpu_tlb(struct amdgpu_ring *ring,
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
/* TODO: It needs to continue working on debugging with semaphore for GFXHUB as well. */
|
/* TODO: It needs to continue working on debugging with semaphore for GFXHUB as well. */
|
||||||
if (ring->funcs->vmhub == AMDGPU_MMHUB_0 ||
|
if (use_semaphore)
|
||||||
ring->funcs->vmhub == AMDGPU_MMHUB_1)
|
|
||||||
/* a read return value of 1 means semaphore acuqire */
|
/* a read return value of 1 means semaphore acuqire */
|
||||||
amdgpu_ring_emit_reg_wait(ring,
|
amdgpu_ring_emit_reg_wait(ring,
|
||||||
hub->vm_inv_eng0_sem + eng, 0x1, 0x1);
|
hub->vm_inv_eng0_sem + eng, 0x1, 0x1);
|
||||||
@@ -548,8 +565,7 @@ static uint64_t gmc_v9_0_emit_flush_gpu_tlb(struct amdgpu_ring *ring,
|
|||||||
req, 1 << vmid);
|
req, 1 << vmid);
|
||||||
|
|
||||||
/* TODO: It needs to continue working on debugging with semaphore for GFXHUB as well. */
|
/* TODO: It needs to continue working on debugging with semaphore for GFXHUB as well. */
|
||||||
if (ring->funcs->vmhub == AMDGPU_MMHUB_0 ||
|
if (use_semaphore)
|
||||||
ring->funcs->vmhub == AMDGPU_MMHUB_1)
|
|
||||||
/*
|
/*
|
||||||
* add semaphore release after invalidation,
|
* add semaphore release after invalidation,
|
||||||
* write with 0 means semaphore release
|
* write with 0 means semaphore release
|
||||||
|
@@ -1,4 +1,4 @@
|
|||||||
# SPDX-License-Identifier: GPL-2.0-only
|
# SPDX-License-Identifier: MIT
|
||||||
#
|
#
|
||||||
# Heterogenous system architecture configuration
|
# Heterogenous system architecture configuration
|
||||||
#
|
#
|
||||||
|
@@ -1,4 +1,4 @@
|
|||||||
# SPDX-License-Identifier: GPL-2.0-only
|
# SPDX-License-Identifier: MIT
|
||||||
menu "Display Engine Configuration"
|
menu "Display Engine Configuration"
|
||||||
depends on DRM && DRM_AMDGPU
|
depends on DRM && DRM_AMDGPU
|
||||||
|
|
||||||
|
@@ -1625,6 +1625,7 @@ static enum bp_result construct_integrated_info(
|
|||||||
/* Don't need to check major revision as they are all 1 */
|
/* Don't need to check major revision as they are all 1 */
|
||||||
switch (revision.minor) {
|
switch (revision.minor) {
|
||||||
case 11:
|
case 11:
|
||||||
|
case 12:
|
||||||
result = get_integrated_info_v11(bp, info);
|
result = get_integrated_info_v11(bp, info);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
|
@@ -471,12 +471,28 @@ static void rn_notify_wm_ranges(struct clk_mgr *clk_mgr_base)
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool rn_are_clock_states_equal(struct dc_clocks *a,
|
||||||
|
struct dc_clocks *b)
|
||||||
|
{
|
||||||
|
if (a->dispclk_khz != b->dispclk_khz)
|
||||||
|
return false;
|
||||||
|
else if (a->dppclk_khz != b->dppclk_khz)
|
||||||
|
return false;
|
||||||
|
else if (a->dcfclk_khz != b->dcfclk_khz)
|
||||||
|
return false;
|
||||||
|
else if (a->dcfclk_deep_sleep_khz != b->dcfclk_deep_sleep_khz)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static struct clk_mgr_funcs dcn21_funcs = {
|
static struct clk_mgr_funcs dcn21_funcs = {
|
||||||
.get_dp_ref_clk_frequency = dce12_get_dp_ref_freq_khz,
|
.get_dp_ref_clk_frequency = dce12_get_dp_ref_freq_khz,
|
||||||
.update_clocks = rn_update_clocks,
|
.update_clocks = rn_update_clocks,
|
||||||
.init_clocks = rn_init_clocks,
|
.init_clocks = rn_init_clocks,
|
||||||
.enable_pme_wa = rn_enable_pme_wa,
|
.enable_pme_wa = rn_enable_pme_wa,
|
||||||
/* .dump_clk_registers = rn_dump_clk_registers, */
|
.are_clock_states_equal = rn_are_clock_states_equal,
|
||||||
.notify_wm_ranges = rn_notify_wm_ranges
|
.notify_wm_ranges = rn_notify_wm_ranges
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -518,36 +534,83 @@ struct clk_bw_params rn_bw_params = {
|
|||||||
.num_entries = 4,
|
.num_entries = 4,
|
||||||
},
|
},
|
||||||
|
|
||||||
.wm_table = {
|
};
|
||||||
|
|
||||||
|
struct wm_table ddr4_wm_table = {
|
||||||
|
.entries = {
|
||||||
|
{
|
||||||
|
.wm_inst = WM_A,
|
||||||
|
.wm_type = WM_TYPE_PSTATE_CHG,
|
||||||
|
.pstate_latency_us = 11.72,
|
||||||
|
.sr_exit_time_us = 6.09,
|
||||||
|
.sr_enter_plus_exit_time_us = 7.14,
|
||||||
|
.valid = true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
.wm_inst = WM_B,
|
||||||
|
.wm_type = WM_TYPE_PSTATE_CHG,
|
||||||
|
.pstate_latency_us = 11.72,
|
||||||
|
.sr_exit_time_us = 10.12,
|
||||||
|
.sr_enter_plus_exit_time_us = 11.48,
|
||||||
|
.valid = true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
.wm_inst = WM_C,
|
||||||
|
.wm_type = WM_TYPE_PSTATE_CHG,
|
||||||
|
.pstate_latency_us = 11.72,
|
||||||
|
.sr_exit_time_us = 10.12,
|
||||||
|
.sr_enter_plus_exit_time_us = 11.48,
|
||||||
|
.valid = true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
.wm_inst = WM_D,
|
||||||
|
.wm_type = WM_TYPE_PSTATE_CHG,
|
||||||
|
.pstate_latency_us = 11.72,
|
||||||
|
.sr_exit_time_us = 10.12,
|
||||||
|
.sr_enter_plus_exit_time_us = 11.48,
|
||||||
|
.valid = true,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
struct wm_table lpddr4_wm_table = {
|
||||||
.entries = {
|
.entries = {
|
||||||
{
|
{
|
||||||
.wm_inst = WM_A,
|
.wm_inst = WM_A,
|
||||||
.wm_type = WM_TYPE_PSTATE_CHG,
|
.wm_type = WM_TYPE_PSTATE_CHG,
|
||||||
.pstate_latency_us = 23.84,
|
.pstate_latency_us = 23.84,
|
||||||
|
.sr_exit_time_us = 12.5,
|
||||||
|
.sr_enter_plus_exit_time_us = 17.0,
|
||||||
.valid = true,
|
.valid = true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
.wm_inst = WM_B,
|
.wm_inst = WM_B,
|
||||||
.wm_type = WM_TYPE_PSTATE_CHG,
|
.wm_type = WM_TYPE_PSTATE_CHG,
|
||||||
.pstate_latency_us = 23.84,
|
.pstate_latency_us = 23.84,
|
||||||
|
.sr_exit_time_us = 12.5,
|
||||||
|
.sr_enter_plus_exit_time_us = 17.0,
|
||||||
.valid = true,
|
.valid = true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
.wm_inst = WM_C,
|
.wm_inst = WM_C,
|
||||||
.wm_type = WM_TYPE_PSTATE_CHG,
|
.wm_type = WM_TYPE_PSTATE_CHG,
|
||||||
.pstate_latency_us = 23.84,
|
.pstate_latency_us = 23.84,
|
||||||
|
.sr_exit_time_us = 12.5,
|
||||||
|
.sr_enter_plus_exit_time_us = 17.0,
|
||||||
.valid = true,
|
.valid = true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
.wm_inst = WM_D,
|
.wm_inst = WM_D,
|
||||||
.wm_type = WM_TYPE_PSTATE_CHG,
|
.wm_type = WM_TYPE_PSTATE_CHG,
|
||||||
.pstate_latency_us = 23.84,
|
.pstate_latency_us = 23.84,
|
||||||
|
.sr_exit_time_us = 12.5,
|
||||||
|
.sr_enter_plus_exit_time_us = 17.0,
|
||||||
.valid = true,
|
.valid = true,
|
||||||
},
|
},
|
||||||
},
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
static unsigned int find_dcfclk_for_voltage(struct dpm_clocks *clock_table, unsigned int voltage)
|
static unsigned int find_dcfclk_for_voltage(struct dpm_clocks *clock_table, unsigned int voltage)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
@@ -561,7 +624,7 @@ static unsigned int find_dcfclk_for_voltage(struct dpm_clocks *clock_table, unsi
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void rn_clk_mgr_helper_populate_bw_params(struct clk_bw_params *bw_params, struct dpm_clocks *clock_table, struct hw_asic_id *asic_id)
|
static void rn_clk_mgr_helper_populate_bw_params(struct clk_bw_params *bw_params, struct dpm_clocks *clock_table, struct integrated_info *bios_info)
|
||||||
{
|
{
|
||||||
int i, j = 0;
|
int i, j = 0;
|
||||||
|
|
||||||
@@ -593,8 +656,8 @@ static void rn_clk_mgr_helper_populate_bw_params(struct clk_bw_params *bw_params
|
|||||||
bw_params->clk_table.entries[i].dcfclk_mhz = find_dcfclk_for_voltage(clock_table, clock_table->FClocks[j].Vol);
|
bw_params->clk_table.entries[i].dcfclk_mhz = find_dcfclk_for_voltage(clock_table, clock_table->FClocks[j].Vol);
|
||||||
}
|
}
|
||||||
|
|
||||||
bw_params->vram_type = asic_id->vram_type;
|
bw_params->vram_type = bios_info->memory_type;
|
||||||
bw_params->num_channels = asic_id->vram_width / DDR4_DRAM_WIDTH;
|
bw_params->num_channels = bios_info->ma_channel_number;
|
||||||
|
|
||||||
for (i = 0; i < WM_SET_COUNT; i++) {
|
for (i = 0; i < WM_SET_COUNT; i++) {
|
||||||
bw_params->wm_table.entries[i].wm_inst = i;
|
bw_params->wm_table.entries[i].wm_inst = i;
|
||||||
@@ -669,15 +732,24 @@ void rn_clk_mgr_construct(
|
|||||||
ASSERT(clk_mgr->base.dprefclk_khz == 600000);
|
ASSERT(clk_mgr->base.dprefclk_khz == 600000);
|
||||||
clk_mgr->base.dprefclk_khz = 600000;
|
clk_mgr->base.dprefclk_khz = 600000;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (ctx->dc_bios->integrated_info->memory_type == LpDdr4MemType) {
|
||||||
|
rn_bw_params.wm_table = lpddr4_wm_table;
|
||||||
|
} else {
|
||||||
|
rn_bw_params.wm_table = ddr4_wm_table;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
dce_clock_read_ss_info(clk_mgr);
|
dce_clock_read_ss_info(clk_mgr);
|
||||||
|
|
||||||
|
|
||||||
clk_mgr->base.bw_params = &rn_bw_params;
|
clk_mgr->base.bw_params = &rn_bw_params;
|
||||||
|
|
||||||
if (pp_smu && pp_smu->rn_funcs.get_dpm_clock_table) {
|
if (pp_smu && pp_smu->rn_funcs.get_dpm_clock_table) {
|
||||||
pp_smu->rn_funcs.get_dpm_clock_table(&pp_smu->rn_funcs.pp_smu, &clock_table);
|
pp_smu->rn_funcs.get_dpm_clock_table(&pp_smu->rn_funcs.pp_smu, &clock_table);
|
||||||
rn_clk_mgr_helper_populate_bw_params(clk_mgr->base.bw_params, &clock_table, &ctx->asic_id);
|
if (ctx->dc_bios && ctx->dc_bios->integrated_info) {
|
||||||
|
rn_clk_mgr_helper_populate_bw_params (clk_mgr->base.bw_params, &clock_table, ctx->dc_bios->integrated_info);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!IS_FPGA_MAXIMUS_DC(ctx->dce_environment) && clk_mgr->smu_ver >= 0x00371500) {
|
if (!IS_FPGA_MAXIMUS_DC(ctx->dce_environment) && clk_mgr->smu_ver >= 0x00371500) {
|
||||||
|
@@ -372,7 +372,7 @@ bool dc_link_is_dp_sink_present(struct dc_link *link)
|
|||||||
|
|
||||||
if (GPIO_RESULT_OK != dal_ddc_open(
|
if (GPIO_RESULT_OK != dal_ddc_open(
|
||||||
ddc, GPIO_MODE_INPUT, GPIO_DDC_CONFIG_TYPE_MODE_I2C)) {
|
ddc, GPIO_MODE_INPUT, GPIO_DDC_CONFIG_TYPE_MODE_I2C)) {
|
||||||
dal_gpio_destroy_ddc(&ddc);
|
dal_ddc_close(ddc);
|
||||||
|
|
||||||
return present;
|
return present;
|
||||||
}
|
}
|
||||||
|
@@ -586,7 +586,7 @@ bool dal_ddc_service_query_ddc_data(
|
|||||||
bool dal_ddc_submit_aux_command(struct ddc_service *ddc,
|
bool dal_ddc_submit_aux_command(struct ddc_service *ddc,
|
||||||
struct aux_payload *payload)
|
struct aux_payload *payload)
|
||||||
{
|
{
|
||||||
uint8_t retrieved = 0;
|
uint32_t retrieved = 0;
|
||||||
bool ret = 0;
|
bool ret = 0;
|
||||||
|
|
||||||
if (!ddc)
|
if (!ddc)
|
||||||
|
@@ -3522,7 +3522,14 @@ void dp_set_fec_enable(struct dc_link *link, bool enable)
|
|||||||
if (link_enc->funcs->fec_set_enable &&
|
if (link_enc->funcs->fec_set_enable &&
|
||||||
link->dpcd_caps.fec_cap.bits.FEC_CAPABLE) {
|
link->dpcd_caps.fec_cap.bits.FEC_CAPABLE) {
|
||||||
if (link->fec_state == dc_link_fec_ready && enable) {
|
if (link->fec_state == dc_link_fec_ready && enable) {
|
||||||
msleep(1);
|
/* Accord to DP spec, FEC enable sequence can first
|
||||||
|
* be transmitted anytime after 1000 LL codes have
|
||||||
|
* been transmitted on the link after link training
|
||||||
|
* completion. Using 1 lane RBR should have the maximum
|
||||||
|
* time for transmitting 1000 LL codes which is 6.173 us.
|
||||||
|
* So use 7 microseconds delay instead.
|
||||||
|
*/
|
||||||
|
udelay(7);
|
||||||
link_enc->funcs->fec_set_enable(link_enc, true);
|
link_enc->funcs->fec_set_enable(link_enc, true);
|
||||||
link->fec_state = dc_link_fec_enabled;
|
link->fec_state = dc_link_fec_enabled;
|
||||||
} else if (link->fec_state == dc_link_fec_enabled && !enable) {
|
} else if (link->fec_state == dc_link_fec_enabled && !enable) {
|
||||||
|
@@ -583,6 +583,8 @@ bool dce_aux_transfer_with_retries(struct ddc_service *ddc,
|
|||||||
uint8_t reply;
|
uint8_t reply;
|
||||||
bool payload_reply = true;
|
bool payload_reply = true;
|
||||||
enum aux_channel_operation_result operation_result;
|
enum aux_channel_operation_result operation_result;
|
||||||
|
bool retry_on_defer = false;
|
||||||
|
|
||||||
int aux_ack_retries = 0,
|
int aux_ack_retries = 0,
|
||||||
aux_defer_retries = 0,
|
aux_defer_retries = 0,
|
||||||
aux_i2c_defer_retries = 0,
|
aux_i2c_defer_retries = 0,
|
||||||
@@ -613,8 +615,10 @@ bool dce_aux_transfer_with_retries(struct ddc_service *ddc,
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case AUX_TRANSACTION_REPLY_AUX_DEFER:
|
case AUX_TRANSACTION_REPLY_AUX_DEFER:
|
||||||
case AUX_TRANSACTION_REPLY_I2C_OVER_AUX_NACK:
|
|
||||||
case AUX_TRANSACTION_REPLY_I2C_OVER_AUX_DEFER:
|
case AUX_TRANSACTION_REPLY_I2C_OVER_AUX_DEFER:
|
||||||
|
retry_on_defer = true;
|
||||||
|
/* fall through */
|
||||||
|
case AUX_TRANSACTION_REPLY_I2C_OVER_AUX_NACK:
|
||||||
if (++aux_defer_retries >= AUX_MAX_DEFER_RETRIES) {
|
if (++aux_defer_retries >= AUX_MAX_DEFER_RETRIES) {
|
||||||
goto fail;
|
goto fail;
|
||||||
} else {
|
} else {
|
||||||
@@ -647,6 +651,14 @@ bool dce_aux_transfer_with_retries(struct ddc_service *ddc,
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case AUX_CHANNEL_OPERATION_FAILED_TIMEOUT:
|
case AUX_CHANNEL_OPERATION_FAILED_TIMEOUT:
|
||||||
|
// Check whether a DEFER had occurred before the timeout.
|
||||||
|
// If so, treat timeout as a DEFER.
|
||||||
|
if (retry_on_defer) {
|
||||||
|
if (++aux_defer_retries >= AUX_MAX_DEFER_RETRIES)
|
||||||
|
goto fail;
|
||||||
|
else if (payload->defer_delay > 0)
|
||||||
|
msleep(payload->defer_delay);
|
||||||
|
} else {
|
||||||
if (++aux_timeout_retries >= AUX_MAX_TIMEOUT_RETRIES)
|
if (++aux_timeout_retries >= AUX_MAX_TIMEOUT_RETRIES)
|
||||||
goto fail;
|
goto fail;
|
||||||
else {
|
else {
|
||||||
@@ -657,6 +669,7 @@ bool dce_aux_transfer_with_retries(struct ddc_service *ddc,
|
|||||||
* for 550us therefore no wait is required here.
|
* for 550us therefore no wait is required here.
|
||||||
*/
|
*/
|
||||||
}
|
}
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case AUX_CHANNEL_OPERATION_FAILED_HPD_DISCON:
|
case AUX_CHANNEL_OPERATION_FAILED_HPD_DISCON:
|
||||||
|
@@ -1,3 +1,4 @@
|
|||||||
|
# SPDX-License-Identifier: MIT
|
||||||
#
|
#
|
||||||
# Makefile for DCN.
|
# Makefile for DCN.
|
||||||
|
|
||||||
|
@@ -923,7 +923,9 @@ static const struct resource_caps res_cap_nv14 = {
|
|||||||
.num_dwb = 1,
|
.num_dwb = 1,
|
||||||
.num_ddc = 5,
|
.num_ddc = 5,
|
||||||
.num_vmid = 16,
|
.num_vmid = 16,
|
||||||
|
#ifdef CONFIG_DRM_AMD_DC_DSC_SUPPORT
|
||||||
.num_dsc = 5,
|
.num_dsc = 5,
|
||||||
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
static const struct dc_debug_options debug_defaults_drv = {
|
static const struct dc_debug_options debug_defaults_drv = {
|
||||||
@@ -1536,13 +1538,20 @@ enum dc_status dcn20_build_mapped_resource(const struct dc *dc, struct dc_state
|
|||||||
|
|
||||||
static void acquire_dsc(struct resource_context *res_ctx,
|
static void acquire_dsc(struct resource_context *res_ctx,
|
||||||
const struct resource_pool *pool,
|
const struct resource_pool *pool,
|
||||||
struct display_stream_compressor **dsc)
|
struct display_stream_compressor **dsc,
|
||||||
|
int pipe_idx)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
ASSERT(*dsc == NULL);
|
ASSERT(*dsc == NULL);
|
||||||
*dsc = NULL;
|
*dsc = NULL;
|
||||||
|
|
||||||
|
if (pool->res_cap->num_dsc == pool->res_cap->num_opp) {
|
||||||
|
*dsc = pool->dscs[pipe_idx];
|
||||||
|
res_ctx->is_dsc_acquired[pipe_idx] = true;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
/* Find first free DSC */
|
/* Find first free DSC */
|
||||||
for (i = 0; i < pool->res_cap->num_dsc; i++)
|
for (i = 0; i < pool->res_cap->num_dsc; i++)
|
||||||
if (!res_ctx->is_dsc_acquired[i]) {
|
if (!res_ctx->is_dsc_acquired[i]) {
|
||||||
@@ -1585,7 +1594,7 @@ static enum dc_status add_dsc_to_stream_resource(struct dc *dc,
|
|||||||
if (pipe_ctx->stream != dc_stream)
|
if (pipe_ctx->stream != dc_stream)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
acquire_dsc(&dc_ctx->res_ctx, pool, &pipe_ctx->stream_res.dsc);
|
acquire_dsc(&dc_ctx->res_ctx, pool, &pipe_ctx->stream_res.dsc, i);
|
||||||
|
|
||||||
/* The number of DSCs can be less than the number of pipes */
|
/* The number of DSCs can be less than the number of pipes */
|
||||||
if (!pipe_ctx->stream_res.dsc) {
|
if (!pipe_ctx->stream_res.dsc) {
|
||||||
@@ -1785,7 +1794,7 @@ bool dcn20_split_stream_for_odm(
|
|||||||
next_odm_pipe->stream_res.opp = pool->opps[next_odm_pipe->pipe_idx];
|
next_odm_pipe->stream_res.opp = pool->opps[next_odm_pipe->pipe_idx];
|
||||||
#ifdef CONFIG_DRM_AMD_DC_DSC_SUPPORT
|
#ifdef CONFIG_DRM_AMD_DC_DSC_SUPPORT
|
||||||
if (next_odm_pipe->stream->timing.flags.DSC == 1) {
|
if (next_odm_pipe->stream->timing.flags.DSC == 1) {
|
||||||
acquire_dsc(res_ctx, pool, &next_odm_pipe->stream_res.dsc);
|
acquire_dsc(res_ctx, pool, &next_odm_pipe->stream_res.dsc, next_odm_pipe->pipe_idx);
|
||||||
ASSERT(next_odm_pipe->stream_res.dsc);
|
ASSERT(next_odm_pipe->stream_res.dsc);
|
||||||
if (next_odm_pipe->stream_res.dsc == NULL)
|
if (next_odm_pipe->stream_res.dsc == NULL)
|
||||||
return false;
|
return false;
|
||||||
|
@@ -492,15 +492,23 @@ void enc2_stream_encoder_dp_unblank(
|
|||||||
DP_VID_N_MUL, n_multiply);
|
DP_VID_N_MUL, n_multiply);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* set DIG_START to 0x1 to reset FIFO */
|
/* make sure stream is disabled before resetting steer fifo */
|
||||||
|
REG_UPDATE(DP_VID_STREAM_CNTL, DP_VID_STREAM_ENABLE, false);
|
||||||
|
REG_WAIT(DP_VID_STREAM_CNTL, DP_VID_STREAM_STATUS, 0, 10, 5000);
|
||||||
|
|
||||||
|
/* set DIG_START to 0x1 to reset FIFO */
|
||||||
REG_UPDATE(DIG_FE_CNTL, DIG_START, 1);
|
REG_UPDATE(DIG_FE_CNTL, DIG_START, 1);
|
||||||
|
udelay(1);
|
||||||
|
|
||||||
/* write 0 to take the FIFO out of reset */
|
/* write 0 to take the FIFO out of reset */
|
||||||
|
|
||||||
REG_UPDATE(DIG_FE_CNTL, DIG_START, 0);
|
REG_UPDATE(DIG_FE_CNTL, DIG_START, 0);
|
||||||
|
|
||||||
/* switch DP encoder to CRTC data */
|
/* switch DP encoder to CRTC data, but reset it the fifo first. It may happen
|
||||||
|
* that it overflows during mode transition, and sometimes doesn't recover.
|
||||||
|
*/
|
||||||
|
REG_UPDATE(DP_STEER_FIFO, DP_STEER_FIFO_RESET, 1);
|
||||||
|
udelay(10);
|
||||||
|
|
||||||
REG_UPDATE(DP_STEER_FIFO, DP_STEER_FIFO_RESET, 0);
|
REG_UPDATE(DP_STEER_FIFO, DP_STEER_FIFO_RESET, 0);
|
||||||
|
|
||||||
|
@@ -1,3 +1,4 @@
|
|||||||
|
# SPDX-License-Identifier: MIT
|
||||||
#
|
#
|
||||||
# Makefile for DCN21.
|
# Makefile for DCN21.
|
||||||
|
|
||||||
|
@@ -23,6 +23,8 @@
|
|||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include <linux/slab.h>
|
||||||
|
|
||||||
#include "dm_services.h"
|
#include "dm_services.h"
|
||||||
#include "dc.h"
|
#include "dc.h"
|
||||||
|
|
||||||
@@ -257,7 +259,7 @@ struct _vcs_dpi_soc_bounding_box_st dcn2_1_soc = {
|
|||||||
.vmm_page_size_bytes = 4096,
|
.vmm_page_size_bytes = 4096,
|
||||||
.dram_clock_change_latency_us = 23.84,
|
.dram_clock_change_latency_us = 23.84,
|
||||||
.return_bus_width_bytes = 64,
|
.return_bus_width_bytes = 64,
|
||||||
.dispclk_dppclk_vco_speed_mhz = 3550,
|
.dispclk_dppclk_vco_speed_mhz = 3600,
|
||||||
.xfc_bus_transport_time_us = 4,
|
.xfc_bus_transport_time_us = 4,
|
||||||
.xfc_xbuf_latency_tolerance_us = 4,
|
.xfc_xbuf_latency_tolerance_us = 4,
|
||||||
.use_urgent_burst_bw = 1,
|
.use_urgent_burst_bw = 1,
|
||||||
@@ -1000,6 +1002,8 @@ static void calculate_wm_set_for_vlevel(
|
|||||||
pipes[0].clks_cfg.socclk_mhz = dml->soc.clock_limits[vlevel].socclk_mhz;
|
pipes[0].clks_cfg.socclk_mhz = dml->soc.clock_limits[vlevel].socclk_mhz;
|
||||||
|
|
||||||
dml->soc.dram_clock_change_latency_us = table_entry->pstate_latency_us;
|
dml->soc.dram_clock_change_latency_us = table_entry->pstate_latency_us;
|
||||||
|
dml->soc.sr_exit_time_us = table_entry->sr_exit_time_us;
|
||||||
|
dml->soc.sr_enter_plus_exit_time_us = table_entry->sr_enter_plus_exit_time_us;
|
||||||
|
|
||||||
wm_set->urgent_ns = get_wm_urgent(dml, pipes, pipe_cnt) * 1000;
|
wm_set->urgent_ns = get_wm_urgent(dml, pipes, pipe_cnt) * 1000;
|
||||||
wm_set->cstate_pstate.cstate_enter_plus_exit_ns = get_wm_stutter_enter_exit(dml, pipes, pipe_cnt) * 1000;
|
wm_set->cstate_pstate.cstate_enter_plus_exit_ns = get_wm_stutter_enter_exit(dml, pipes, pipe_cnt) * 1000;
|
||||||
@@ -1017,24 +1021,34 @@ static void calculate_wm_set_for_vlevel(
|
|||||||
|
|
||||||
static void patch_bounding_box(struct dc *dc, struct _vcs_dpi_soc_bounding_box_st *bb)
|
static void patch_bounding_box(struct dc *dc, struct _vcs_dpi_soc_bounding_box_st *bb)
|
||||||
{
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
kernel_fpu_begin();
|
kernel_fpu_begin();
|
||||||
if (dc->bb_overrides.sr_exit_time_ns) {
|
if (dc->bb_overrides.sr_exit_time_ns) {
|
||||||
bb->sr_exit_time_us = dc->bb_overrides.sr_exit_time_ns / 1000.0;
|
for (i = 0; i < WM_SET_COUNT; i++) {
|
||||||
|
dc->clk_mgr->bw_params->wm_table.entries[i].sr_exit_time_us =
|
||||||
|
dc->bb_overrides.sr_exit_time_ns / 1000.0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (dc->bb_overrides.sr_enter_plus_exit_time_ns) {
|
if (dc->bb_overrides.sr_enter_plus_exit_time_ns) {
|
||||||
bb->sr_enter_plus_exit_time_us =
|
for (i = 0; i < WM_SET_COUNT; i++) {
|
||||||
|
dc->clk_mgr->bw_params->wm_table.entries[i].sr_enter_plus_exit_time_us =
|
||||||
dc->bb_overrides.sr_enter_plus_exit_time_ns / 1000.0;
|
dc->bb_overrides.sr_enter_plus_exit_time_ns / 1000.0;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (dc->bb_overrides.urgent_latency_ns) {
|
if (dc->bb_overrides.urgent_latency_ns) {
|
||||||
bb->urgent_latency_us = dc->bb_overrides.urgent_latency_ns / 1000.0;
|
bb->urgent_latency_us = dc->bb_overrides.urgent_latency_ns / 1000.0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (dc->bb_overrides.dram_clock_change_latency_ns) {
|
if (dc->bb_overrides.dram_clock_change_latency_ns) {
|
||||||
bb->dram_clock_change_latency_us =
|
for (i = 0; i < WM_SET_COUNT; i++) {
|
||||||
|
dc->clk_mgr->bw_params->wm_table.entries[i].pstate_latency_us =
|
||||||
dc->bb_overrides.dram_clock_change_latency_ns / 1000.0;
|
dc->bb_overrides.dram_clock_change_latency_ns / 1000.0;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
kernel_fpu_end();
|
kernel_fpu_end();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -1,3 +1,4 @@
|
|||||||
|
# SPDX-License-Identifier: MIT
|
||||||
#
|
#
|
||||||
# Makefile for the 'dsc' sub-component of DAL.
|
# Makefile for the 'dsc' sub-component of DAL.
|
||||||
|
|
||||||
|
@@ -69,6 +69,8 @@ struct wm_range_table_entry {
|
|||||||
unsigned int wm_inst;
|
unsigned int wm_inst;
|
||||||
unsigned int wm_type;
|
unsigned int wm_type;
|
||||||
double pstate_latency_us;
|
double pstate_latency_us;
|
||||||
|
double sr_exit_time_us;
|
||||||
|
double sr_enter_plus_exit_time_us;
|
||||||
bool valid;
|
bool valid;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@@ -42,7 +42,7 @@ struct aux_payload {
|
|||||||
bool write;
|
bool write;
|
||||||
bool mot;
|
bool mot;
|
||||||
uint32_t address;
|
uint32_t address;
|
||||||
uint8_t length;
|
uint32_t length;
|
||||||
uint8_t *data;
|
uint8_t *data;
|
||||||
/*
|
/*
|
||||||
* used to return the reply type of the transaction
|
* used to return the reply type of the transaction
|
||||||
|
@@ -37,8 +37,8 @@
|
|||||||
#define STATIC_SCREEN_RAMP_DELTA_REFRESH_RATE_PER_FRAME ((1000 / 60) * 65)
|
#define STATIC_SCREEN_RAMP_DELTA_REFRESH_RATE_PER_FRAME ((1000 / 60) * 65)
|
||||||
/* Number of elements in the render times cache array */
|
/* Number of elements in the render times cache array */
|
||||||
#define RENDER_TIMES_MAX_COUNT 10
|
#define RENDER_TIMES_MAX_COUNT 10
|
||||||
/* Threshold to exit/exit BTR (to avoid frequent enter-exits at the lower limit) */
|
/* Threshold to exit BTR (to avoid frequent enter-exits at the lower limit) */
|
||||||
#define BTR_MAX_MARGIN 2500
|
#define BTR_EXIT_MARGIN 2000
|
||||||
/* Threshold to change BTR multiplier (to avoid frequent changes) */
|
/* Threshold to change BTR multiplier (to avoid frequent changes) */
|
||||||
#define BTR_DRIFT_MARGIN 2000
|
#define BTR_DRIFT_MARGIN 2000
|
||||||
/*Threshold to exit fixed refresh rate*/
|
/*Threshold to exit fixed refresh rate*/
|
||||||
@@ -254,23 +254,25 @@ static void apply_below_the_range(struct core_freesync *core_freesync,
|
|||||||
unsigned int delta_from_mid_point_in_us_1 = 0xFFFFFFFF;
|
unsigned int delta_from_mid_point_in_us_1 = 0xFFFFFFFF;
|
||||||
unsigned int delta_from_mid_point_in_us_2 = 0xFFFFFFFF;
|
unsigned int delta_from_mid_point_in_us_2 = 0xFFFFFFFF;
|
||||||
unsigned int frames_to_insert = 0;
|
unsigned int frames_to_insert = 0;
|
||||||
|
unsigned int min_frame_duration_in_ns = 0;
|
||||||
|
unsigned int max_render_time_in_us = in_out_vrr->max_duration_in_us;
|
||||||
unsigned int delta_from_mid_point_delta_in_us;
|
unsigned int delta_from_mid_point_delta_in_us;
|
||||||
unsigned int max_render_time_in_us =
|
|
||||||
in_out_vrr->max_duration_in_us - in_out_vrr->btr.margin_in_us;
|
min_frame_duration_in_ns = ((unsigned int) (div64_u64(
|
||||||
|
(1000000000ULL * 1000000),
|
||||||
|
in_out_vrr->max_refresh_in_uhz)));
|
||||||
|
|
||||||
/* Program BTR */
|
/* Program BTR */
|
||||||
if ((last_render_time_in_us + in_out_vrr->btr.margin_in_us / 2) < max_render_time_in_us) {
|
if (last_render_time_in_us + BTR_EXIT_MARGIN < max_render_time_in_us) {
|
||||||
/* Exit Below the Range */
|
/* Exit Below the Range */
|
||||||
if (in_out_vrr->btr.btr_active) {
|
if (in_out_vrr->btr.btr_active) {
|
||||||
in_out_vrr->btr.frame_counter = 0;
|
in_out_vrr->btr.frame_counter = 0;
|
||||||
in_out_vrr->btr.btr_active = false;
|
in_out_vrr->btr.btr_active = false;
|
||||||
}
|
}
|
||||||
} else if (last_render_time_in_us > (max_render_time_in_us + in_out_vrr->btr.margin_in_us / 2)) {
|
} else if (last_render_time_in_us > max_render_time_in_us) {
|
||||||
/* Enter Below the Range */
|
/* Enter Below the Range */
|
||||||
if (!in_out_vrr->btr.btr_active) {
|
|
||||||
in_out_vrr->btr.btr_active = true;
|
in_out_vrr->btr.btr_active = true;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
/* BTR set to "not active" so disengage */
|
/* BTR set to "not active" so disengage */
|
||||||
if (!in_out_vrr->btr.btr_active) {
|
if (!in_out_vrr->btr.btr_active) {
|
||||||
@@ -325,9 +327,7 @@ static void apply_below_the_range(struct core_freesync *core_freesync,
|
|||||||
/* Choose number of frames to insert based on how close it
|
/* Choose number of frames to insert based on how close it
|
||||||
* can get to the mid point of the variable range.
|
* can get to the mid point of the variable range.
|
||||||
*/
|
*/
|
||||||
if ((frame_time_in_us / mid_point_frames_ceil) > in_out_vrr->min_duration_in_us &&
|
if (delta_from_mid_point_in_us_1 < delta_from_mid_point_in_us_2) {
|
||||||
(delta_from_mid_point_in_us_1 < delta_from_mid_point_in_us_2 ||
|
|
||||||
mid_point_frames_floor < 2)) {
|
|
||||||
frames_to_insert = mid_point_frames_ceil;
|
frames_to_insert = mid_point_frames_ceil;
|
||||||
delta_from_mid_point_delta_in_us = delta_from_mid_point_in_us_2 -
|
delta_from_mid_point_delta_in_us = delta_from_mid_point_in_us_2 -
|
||||||
delta_from_mid_point_in_us_1;
|
delta_from_mid_point_in_us_1;
|
||||||
@@ -343,7 +343,7 @@ static void apply_below_the_range(struct core_freesync *core_freesync,
|
|||||||
if (in_out_vrr->btr.frames_to_insert != 0 &&
|
if (in_out_vrr->btr.frames_to_insert != 0 &&
|
||||||
delta_from_mid_point_delta_in_us < BTR_DRIFT_MARGIN) {
|
delta_from_mid_point_delta_in_us < BTR_DRIFT_MARGIN) {
|
||||||
if (((last_render_time_in_us / in_out_vrr->btr.frames_to_insert) <
|
if (((last_render_time_in_us / in_out_vrr->btr.frames_to_insert) <
|
||||||
max_render_time_in_us) &&
|
in_out_vrr->max_duration_in_us) &&
|
||||||
((last_render_time_in_us / in_out_vrr->btr.frames_to_insert) >
|
((last_render_time_in_us / in_out_vrr->btr.frames_to_insert) >
|
||||||
in_out_vrr->min_duration_in_us))
|
in_out_vrr->min_duration_in_us))
|
||||||
frames_to_insert = in_out_vrr->btr.frames_to_insert;
|
frames_to_insert = in_out_vrr->btr.frames_to_insert;
|
||||||
@@ -796,11 +796,6 @@ void mod_freesync_build_vrr_params(struct mod_freesync *mod_freesync,
|
|||||||
refresh_range = in_out_vrr->max_refresh_in_uhz -
|
refresh_range = in_out_vrr->max_refresh_in_uhz -
|
||||||
in_out_vrr->min_refresh_in_uhz;
|
in_out_vrr->min_refresh_in_uhz;
|
||||||
|
|
||||||
in_out_vrr->btr.margin_in_us = in_out_vrr->max_duration_in_us -
|
|
||||||
2 * in_out_vrr->min_duration_in_us;
|
|
||||||
if (in_out_vrr->btr.margin_in_us > BTR_MAX_MARGIN)
|
|
||||||
in_out_vrr->btr.margin_in_us = BTR_MAX_MARGIN;
|
|
||||||
|
|
||||||
in_out_vrr->supported = true;
|
in_out_vrr->supported = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -816,7 +811,6 @@ void mod_freesync_build_vrr_params(struct mod_freesync *mod_freesync,
|
|||||||
in_out_vrr->btr.inserted_duration_in_us = 0;
|
in_out_vrr->btr.inserted_duration_in_us = 0;
|
||||||
in_out_vrr->btr.frames_to_insert = 0;
|
in_out_vrr->btr.frames_to_insert = 0;
|
||||||
in_out_vrr->btr.frame_counter = 0;
|
in_out_vrr->btr.frame_counter = 0;
|
||||||
|
|
||||||
in_out_vrr->btr.mid_point_in_us =
|
in_out_vrr->btr.mid_point_in_us =
|
||||||
(in_out_vrr->min_duration_in_us +
|
(in_out_vrr->min_duration_in_us +
|
||||||
in_out_vrr->max_duration_in_us) / 2;
|
in_out_vrr->max_duration_in_us) / 2;
|
||||||
|
@@ -92,7 +92,6 @@ struct mod_vrr_params_btr {
|
|||||||
uint32_t inserted_duration_in_us;
|
uint32_t inserted_duration_in_us;
|
||||||
uint32_t frames_to_insert;
|
uint32_t frames_to_insert;
|
||||||
uint32_t frame_counter;
|
uint32_t frame_counter;
|
||||||
uint32_t margin_in_us;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
struct mod_vrr_params_fixed_refresh {
|
struct mod_vrr_params_fixed_refresh {
|
||||||
|
@@ -1313,12 +1313,17 @@ static int arcturus_get_power_profile_mode(struct smu_context *smu,
|
|||||||
"VR",
|
"VR",
|
||||||
"COMPUTE",
|
"COMPUTE",
|
||||||
"CUSTOM"};
|
"CUSTOM"};
|
||||||
|
static const char *title[] = {
|
||||||
|
"PROFILE_INDEX(NAME)"};
|
||||||
uint32_t i, size = 0;
|
uint32_t i, size = 0;
|
||||||
int16_t workload_type = 0;
|
int16_t workload_type = 0;
|
||||||
|
|
||||||
if (!smu->pm_enabled || !buf)
|
if (!smu->pm_enabled || !buf)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
|
size += sprintf(buf + size, "%16s\n",
|
||||||
|
title[0]);
|
||||||
|
|
||||||
for (i = 0; i <= PP_SMC_POWER_PROFILE_CUSTOM; i++) {
|
for (i = 0; i <= PP_SMC_POWER_PROFILE_CUSTOM; i++) {
|
||||||
/*
|
/*
|
||||||
* Conv PP_SMC_POWER_PROFILE* to WORKLOAD_PPLIB_*_BIT
|
* Conv PP_SMC_POWER_PROFILE* to WORKLOAD_PPLIB_*_BIT
|
||||||
|
Reference in New Issue
Block a user