drm fixes for 6.1-rc1

amdgpu:
 - DC mutex fix
 - DC SubVP fixes
 - DCN 3.2.x fixes
 - DCN 3.1.x fixes
 - SDMA 6.x fixes
 - Enable DPIA for 3.1.4
 - VRR fixes
 - VRAM BO swapping fix
 - Revert dirty fb helper change
 - SR-IOV suspend/resume fixes
 - Work around GCC array bounds check fail warning
 - UMC 8.10 fixes
 - Misc fixes and cleanups
 
 i915:
 - Round to closest in g4x+ HDMI clock readout
 - Update MOCS table for EHL
 - Fix PSR_IMR/IIR field handling
 - Fix watermark calculations for gen12+/DG2 modifiers
 - Reject excessive dotclocks early
 - Fix revocation of non-persistent contexts
 - Handle migration for dpt
 - Fix display problems after resume
 - Allow control over the flags when migrating
 - Consider DG2_RC_CCS_CC when migrating buffers
 -----BEGIN PGP SIGNATURE-----
 
 iQIzBAABCAAdFiEEEKbZHaGwW9KfbeusDHTzWXnEhr4FAmNIrI0ACgkQDHTzWXnE
 hr4muRAAm6mywF0G9LhtVuYhpl5A8EZR5as4PxE1nSdLs4t1+OSJ6MfJoY/Ihvc6
 LMzMadDMHoZbY/9z0MZDJEfeBSTRjTu1+g8u63d0tMf0YqI8/3D53sOodlULftc4
 9YwjyB4G2xol/fk81Z5IgIcFilW5M8OjqMHuswxb0k92aF3arkHkVT+w0Njd26dK
 Fqxm7Z8FbdQFlWeZLaY43K4CGQUqMtg2Xcc+F/ciNAs9a6QwTudaenchSdXMBzCW
 OMv14KLDG3YO+tndOESmKVE9qJ0X/7J8mzUpxfzbcAalGJQpctTGPiy/UBLQvOzx
 BKOSCVRg+1LPRnpnj9nZWCrs5oWCaDWr1XjYNP7za8wukHIr3sGRST1sDkVqzeKw
 Ct62V9H5ix3I9UG/QXSguY30Vq/w7zPJQuQy+CWNKGjsXR8hVyCc2NTIk1FlDMww
 vRjOD9stbSdX5hGS/lSi2xZ9ERPi2L73bPQblosKl3Gi65kScvdzl2F9PSuMGsik
 rK1PB2I7dj1gJp4f8RmQZCrN0UlfH/YAVn5rpZSejAE+mFGG0/qzgBkIkNhAHB9s
 3cg/EiDRbGQ6zxffE6GGP4HN6E9vVtuOVJl8sGR90aDRvVyTXKgTXiXRfHGc9BZj
 xc6sRPQjjWvHVopN354A9bJs3InT9rwEOw/0PHhK1GXE4htkGpc=
 =X1UY
 -----END PGP SIGNATURE-----

Merge tag 'drm-next-2022-10-14' of git://anongit.freedesktop.org/drm/drm

Pull more drm updates from Dave Airlie:
 "Round of fixes for the merge window stuff, bunch of amdgpu and i915
  changes, this should have the gcc11 warning fix, amongst other
  changes.

  amdgpu:
   - DC mutex fix
   - DC SubVP fixes
   - DCN 3.2.x fixes
   - DCN 3.1.x fixes
   - SDMA 6.x fixes
   - Enable DPIA for 3.1.4
   - VRR fixes
   - VRAM BO swapping fix
   - Revert dirty fb helper change
   - SR-IOV suspend/resume fixes
   - Work around GCC array bounds check fail warning
   - UMC 8.10 fixes
   - Misc fixes and cleanups

  i915:
   - Round to closest in g4x+ HDMI clock readout
   - Update MOCS table for EHL
   - Fix PSR_IMR/IIR field handling
   - Fix watermark calculations for gen12+/DG2 modifiers
   - Reject excessive dotclocks early
   - Fix revocation of non-persistent contexts
   - Handle migration for dpt
   - Fix display problems after resume
   - Allow control over the flags when migrating
   - Consider DG2_RC_CCS_CC when migrating buffers"

* tag 'drm-next-2022-10-14' of git://anongit.freedesktop.org/drm/drm: (110 commits)
  drm/amd/display: Add HUBP surface flip interrupt handler
  drm/i915/display: consider DG2_RC_CCS_CC when migrating buffers
  drm/i915: allow control over the flags when migrating
  drm/amd/display: Simplify bool conversion
  drm/amd/display: fix transfer function passed to build_coefficients()
  drm/amd/display: add a license to cursor_reg_cache.h
  drm/amd/display: make virtual_disable_link_output static
  drm/amd/display: fix indentation in dc.c
  drm/amd/display: make dcn32_split_stream_for_mpc_or_odm static
  drm/amd/display: fix build error on arm64
  drm/amd/display: 3.2.207
  drm/amd/display: Clean some DCN32 macros
  drm/amdgpu: Add poison mode query for umc v8_10_0
  drm/amdgpu: Update umc v8_10_0 headers
  drm/amdgpu: fix coding style issue for mca notifier
  drm/amdgpu: define convert_error_address for umc v8.7
  drm/amdgpu: define RAS convert_error_address API
  drm/amdgpu: remove check for CE in RAS error address query
  drm/i915: Fix display problems after resume
  drm/amd/display: fix array-bounds error in dc_stream_remove_writeback() [take 2]
  ...
This commit is contained in:
Linus Torvalds 2022-10-13 21:56:34 -07:00
commit 9c9155a350
116 changed files with 1832 additions and 1083 deletions

View File

@ -75,9 +75,6 @@ void amdgpu_amdkfd_device_probe(struct amdgpu_device *adev)
return;
adev->kfd.dev = kgd2kfd_probe(adev, vf);
if (adev->kfd.dev)
amdgpu_amdkfd_total_mem_size += adev->gmc.real_vram_size;
}
/**
@ -201,6 +198,8 @@ void amdgpu_amdkfd_device_init(struct amdgpu_device *adev)
adev->kfd.init_complete = kgd2kfd_device_init(adev->kfd.dev,
adev_to_drm(adev), &gpu_resources);
amdgpu_amdkfd_total_mem_size += adev->gmc.real_vram_size;
INIT_WORK(&adev->kfd.reset_work, amdgpu_amdkfd_reset_work);
}
}
@ -210,6 +209,7 @@ void amdgpu_amdkfd_device_fini_sw(struct amdgpu_device *adev)
if (adev->kfd.dev) {
kgd2kfd_device_exit(adev->kfd.dev);
adev->kfd.dev = NULL;
amdgpu_amdkfd_total_mem_size -= adev->gmc.real_vram_size;
}
}

View File

@ -38,8 +38,6 @@
#include <linux/pci.h>
#include <linux/pm_runtime.h>
#include <drm/drm_crtc_helper.h>
#include <drm/drm_damage_helper.h>
#include <drm/drm_drv.h>
#include <drm/drm_edid.h>
#include <drm/drm_gem_framebuffer_helper.h>
#include <drm/drm_fb_helper.h>
@ -500,12 +498,6 @@ static const struct drm_framebuffer_funcs amdgpu_fb_funcs = {
.create_handle = drm_gem_fb_create_handle,
};
static const struct drm_framebuffer_funcs amdgpu_fb_funcs_atomic = {
.destroy = drm_gem_fb_destroy,
.create_handle = drm_gem_fb_create_handle,
.dirty = drm_atomic_helper_dirtyfb,
};
uint32_t amdgpu_display_supported_domains(struct amdgpu_device *adev,
uint64_t bo_flags)
{
@ -1108,10 +1100,8 @@ static int amdgpu_display_gem_fb_verify_and_init(struct drm_device *dev,
if (ret)
goto err;
if (drm_drv_uses_atomic_modeset(dev))
ret = drm_framebuffer_init(dev, &rfb->base, &amdgpu_fb_funcs_atomic);
else
ret = drm_framebuffer_init(dev, &rfb->base, &amdgpu_fb_funcs);
ret = drm_framebuffer_init(dev, &rfb->base, &amdgpu_fb_funcs);
if (ret)
goto err;

View File

@ -688,13 +688,16 @@ int amdgpu_bo_create_vm(struct amdgpu_device *adev,
* num of amdgpu_vm_pt entries.
*/
BUG_ON(bp->bo_ptr_size < sizeof(struct amdgpu_bo_vm));
bp->destroy = &amdgpu_bo_vm_destroy;
r = amdgpu_bo_create(adev, bp, &bo_ptr);
if (r)
return r;
*vmbo_ptr = to_amdgpu_bo_vm(bo_ptr);
INIT_LIST_HEAD(&(*vmbo_ptr)->shadow_list);
/* Set destroy callback to amdgpu_bo_vm_destroy after vmbo->shadow_list
* is initialized.
*/
bo_ptr->tbo.destroy = &amdgpu_bo_vm_destroy;
return r;
}

View File

@ -2877,9 +2877,9 @@ static int amdgpu_bad_page_notifier(struct notifier_block *nb,
err_data.err_addr =
kcalloc(adev->umc.max_ras_err_cnt_per_query,
sizeof(struct eeprom_table_record), GFP_KERNEL);
if(!err_data.err_addr) {
dev_warn(adev->dev, "Failed to alloc memory for "
"umc error address record in mca notifier!\n");
if (!err_data.err_addr) {
dev_warn(adev->dev,
"Failed to alloc memory for umc error record in mca notifier!\n");
return NOTIFY_DONE;
}
@ -2889,7 +2889,7 @@ static int amdgpu_bad_page_notifier(struct notifier_block *nb,
if (adev->umc.ras &&
adev->umc.ras->convert_ras_error_address)
adev->umc.ras->convert_ras_error_address(adev,
&err_data, 0, ch_inst, umc_inst, m->addr);
&err_data, m->addr, ch_inst, umc_inst);
if (amdgpu_bad_page_threshold != 0) {
amdgpu_ras_add_bad_pages(adev, err_data.err_addr,

View File

@ -222,8 +222,10 @@ int amdgpu_sdma_init_microcode(struct amdgpu_device *adev,
adev->sdma.instance[instance].fw->data;
version_major = le16_to_cpu(header->header_version_major);
if ((duplicate && instance) || (!duplicate && version_major > 1))
return -EINVAL;
if ((duplicate && instance) || (!duplicate && version_major > 1)) {
err = -EINVAL;
goto out;
}
err = amdgpu_sdma_init_inst_ctx(&adev->sdma.instance[instance]);
if (err)
@ -272,7 +274,7 @@ int amdgpu_sdma_init_microcode(struct amdgpu_device *adev,
ALIGN(le32_to_cpu(sdma_hdr->ctl_ucode_size_bytes), PAGE_SIZE);
break;
default:
return -EINVAL;
err = -EINVAL;
}
}
@ -283,3 +285,24 @@ out:
}
return err;
}
void amdgpu_sdma_unset_buffer_funcs_helper(struct amdgpu_device *adev)
{
struct amdgpu_ring *sdma;
int i;
for (i = 0; i < adev->sdma.num_instances; i++) {
if (adev->sdma.has_page_queue) {
sdma = &adev->sdma.instance[i].page;
if (adev->mman.buffer_funcs_ring == sdma) {
amdgpu_ttm_set_buffer_funcs_status(adev, false);
break;
}
}
sdma = &adev->sdma.instance[i].ring;
if (adev->mman.buffer_funcs_ring == sdma) {
amdgpu_ttm_set_buffer_funcs_status(adev, false);
break;
}
}
}

View File

@ -128,4 +128,6 @@ int amdgpu_sdma_init_microcode(struct amdgpu_device *adev,
char *fw_name, u32 instance, bool duplicate);
void amdgpu_sdma_destroy_inst_ctx(struct amdgpu_device *adev,
bool duplicate);
void amdgpu_sdma_unset_buffer_funcs_helper(struct amdgpu_device *adev);
#endif

View File

@ -424,8 +424,9 @@ error:
static bool amdgpu_mem_visible(struct amdgpu_device *adev,
struct ttm_resource *mem)
{
uint64_t mem_size = (u64)mem->num_pages << PAGE_SHIFT;
u64 mem_size = (u64)mem->num_pages << PAGE_SHIFT;
struct amdgpu_res_cursor cursor;
u64 end;
if (mem->mem_type == TTM_PL_SYSTEM ||
mem->mem_type == TTM_PL_TT)
@ -434,12 +435,18 @@ static bool amdgpu_mem_visible(struct amdgpu_device *adev,
return false;
amdgpu_res_first(mem, 0, mem_size, &cursor);
end = cursor.start + cursor.size;
while (cursor.remaining) {
amdgpu_res_next(&cursor, cursor.size);
/* ttm_resource_ioremap only supports contiguous memory */
if (cursor.size != mem_size)
return false;
/* ttm_resource_ioremap only supports contiguous memory */
if (end != cursor.start)
return false;
return cursor.start + cursor.size <= adev->gmc.visible_vram_size;
end = cursor.start + cursor.size;
}
return end <= adev->gmc.visible_vram_size;
}
/*

View File

@ -22,8 +22,6 @@
#define __AMDGPU_UMC_H__
#include "amdgpu_ras.h"
#define UMC_INVALID_ADDR 0x1ULL
/*
* (addr / 256) * 4096, the higher 26 bits in ErrorAddr
* is the index of 4KB block
@ -54,9 +52,8 @@ struct amdgpu_umc_ras {
void (*err_cnt_init)(struct amdgpu_device *adev);
bool (*query_ras_poison_mode)(struct amdgpu_device *adev);
void (*convert_ras_error_address)(struct amdgpu_device *adev,
struct ras_err_data *err_data,
uint32_t umc_reg_offset, uint32_t ch_inst,
uint32_t umc_inst, uint64_t mca_addr);
struct ras_err_data *err_data, uint64_t err_addr,
uint32_t ch_inst, uint32_t umc_inst);
void (*ecc_info_query_ras_error_count)(struct amdgpu_device *adev,
void *ras_error_status);
void (*ecc_info_query_ras_error_address)(struct amdgpu_device *adev,

View File

@ -309,14 +309,10 @@ static void cik_sdma_ring_emit_fence(struct amdgpu_ring *ring, u64 addr, u64 seq
*/
static void cik_sdma_gfx_stop(struct amdgpu_device *adev)
{
struct amdgpu_ring *sdma0 = &adev->sdma.instance[0].ring;
struct amdgpu_ring *sdma1 = &adev->sdma.instance[1].ring;
u32 rb_cntl;
int i;
if ((adev->mman.buffer_funcs_ring == sdma0) ||
(adev->mman.buffer_funcs_ring == sdma1))
amdgpu_ttm_set_buffer_funcs_status(adev, false);
amdgpu_sdma_unset_buffer_funcs_helper(adev);
for (i = 0; i < adev->sdma.num_instances; i++) {
rb_cntl = RREG32(mmSDMA0_GFX_RB_CNTL + sdma_offsets[i]);

View File

@ -342,14 +342,10 @@ static void sdma_v2_4_ring_emit_fence(struct amdgpu_ring *ring, u64 addr, u64 se
*/
static void sdma_v2_4_gfx_stop(struct amdgpu_device *adev)
{
struct amdgpu_ring *sdma0 = &adev->sdma.instance[0].ring;
struct amdgpu_ring *sdma1 = &adev->sdma.instance[1].ring;
u32 rb_cntl, ib_cntl;
int i;
if ((adev->mman.buffer_funcs_ring == sdma0) ||
(adev->mman.buffer_funcs_ring == sdma1))
amdgpu_ttm_set_buffer_funcs_status(adev, false);
amdgpu_sdma_unset_buffer_funcs_helper(adev);
for (i = 0; i < adev->sdma.num_instances; i++) {
rb_cntl = RREG32(mmSDMA0_GFX_RB_CNTL + sdma_offsets[i]);

View File

@ -516,14 +516,10 @@ static void sdma_v3_0_ring_emit_fence(struct amdgpu_ring *ring, u64 addr, u64 se
*/
static void sdma_v3_0_gfx_stop(struct amdgpu_device *adev)
{
struct amdgpu_ring *sdma0 = &adev->sdma.instance[0].ring;
struct amdgpu_ring *sdma1 = &adev->sdma.instance[1].ring;
u32 rb_cntl, ib_cntl;
int i;
if ((adev->mman.buffer_funcs_ring == sdma0) ||
(adev->mman.buffer_funcs_ring == sdma1))
amdgpu_ttm_set_buffer_funcs_status(adev, false);
amdgpu_sdma_unset_buffer_funcs_helper(adev);
for (i = 0; i < adev->sdma.num_instances; i++) {
rb_cntl = RREG32(mmSDMA0_GFX_RB_CNTL + sdma_offsets[i]);

View File

@ -915,18 +915,12 @@ static void sdma_v4_0_ring_emit_fence(struct amdgpu_ring *ring, u64 addr, u64 se
*/
static void sdma_v4_0_gfx_stop(struct amdgpu_device *adev)
{
struct amdgpu_ring *sdma[AMDGPU_MAX_SDMA_INSTANCES];
u32 rb_cntl, ib_cntl;
int i, unset = 0;
int i;
amdgpu_sdma_unset_buffer_funcs_helper(adev);
for (i = 0; i < adev->sdma.num_instances; i++) {
sdma[i] = &adev->sdma.instance[i].ring;
if ((adev->mman.buffer_funcs_ring == sdma[i]) && unset != 1) {
amdgpu_ttm_set_buffer_funcs_status(adev, false);
unset = 1;
}
rb_cntl = RREG32_SDMA(i, mmSDMA0_GFX_RB_CNTL);
rb_cntl = REG_SET_FIELD(rb_cntl, SDMA0_GFX_RB_CNTL, RB_ENABLE, 0);
WREG32_SDMA(i, mmSDMA0_GFX_RB_CNTL, rb_cntl);
@ -957,20 +951,12 @@ static void sdma_v4_0_rlc_stop(struct amdgpu_device *adev)
*/
static void sdma_v4_0_page_stop(struct amdgpu_device *adev)
{
struct amdgpu_ring *sdma[AMDGPU_MAX_SDMA_INSTANCES];
u32 rb_cntl, ib_cntl;
int i;
bool unset = false;
amdgpu_sdma_unset_buffer_funcs_helper(adev);
for (i = 0; i < adev->sdma.num_instances; i++) {
sdma[i] = &adev->sdma.instance[i].page;
if ((adev->mman.buffer_funcs_ring == sdma[i]) &&
(!unset)) {
amdgpu_ttm_set_buffer_funcs_status(adev, false);
unset = true;
}
rb_cntl = RREG32_SDMA(i, mmSDMA0_PAGE_RB_CNTL);
rb_cntl = REG_SET_FIELD(rb_cntl, SDMA0_PAGE_RB_CNTL,
RB_ENABLE, 0);
@ -1954,8 +1940,11 @@ static int sdma_v4_0_hw_fini(void *handle)
struct amdgpu_device *adev = (struct amdgpu_device *)handle;
int i;
if (amdgpu_sriov_vf(adev))
if (amdgpu_sriov_vf(adev)) {
/* disable the scheduler for SDMA */
amdgpu_sdma_unset_buffer_funcs_helper(adev);
return 0;
}
for (i = 0; i < adev->sdma.num_instances; i++) {
amdgpu_irq_put(adev, &adev->sdma.ecc_irq,

View File

@ -584,14 +584,10 @@ static void sdma_v5_0_ring_emit_fence(struct amdgpu_ring *ring, u64 addr, u64 se
*/
static void sdma_v5_0_gfx_stop(struct amdgpu_device *adev)
{
struct amdgpu_ring *sdma0 = &adev->sdma.instance[0].ring;
struct amdgpu_ring *sdma1 = &adev->sdma.instance[1].ring;
u32 rb_cntl, ib_cntl;
int i;
if ((adev->mman.buffer_funcs_ring == sdma0) ||
(adev->mman.buffer_funcs_ring == sdma1))
amdgpu_ttm_set_buffer_funcs_status(adev, false);
amdgpu_sdma_unset_buffer_funcs_helper(adev);
for (i = 0; i < adev->sdma.num_instances; i++) {
rb_cntl = RREG32_SOC15_IP(GC, sdma_v5_0_get_reg_offset(adev, i, mmSDMA0_GFX_RB_CNTL));
@ -1460,8 +1456,11 @@ static int sdma_v5_0_hw_fini(void *handle)
{
struct amdgpu_device *adev = (struct amdgpu_device *)handle;
if (amdgpu_sriov_vf(adev))
if (amdgpu_sriov_vf(adev)) {
/* disable the scheduler for SDMA */
amdgpu_sdma_unset_buffer_funcs_helper(adev);
return 0;
}
sdma_v5_0_ctx_switch_enable(adev, false);
sdma_v5_0_enable(adev, false);

View File

@ -414,18 +414,10 @@ static void sdma_v5_2_ring_emit_fence(struct amdgpu_ring *ring, u64 addr, u64 se
*/
static void sdma_v5_2_gfx_stop(struct amdgpu_device *adev)
{
struct amdgpu_ring *sdma0 = &adev->sdma.instance[0].ring;
struct amdgpu_ring *sdma1 = &adev->sdma.instance[1].ring;
struct amdgpu_ring *sdma2 = &adev->sdma.instance[2].ring;
struct amdgpu_ring *sdma3 = &adev->sdma.instance[3].ring;
u32 rb_cntl, ib_cntl;
int i;
if ((adev->mman.buffer_funcs_ring == sdma0) ||
(adev->mman.buffer_funcs_ring == sdma1) ||
(adev->mman.buffer_funcs_ring == sdma2) ||
(adev->mman.buffer_funcs_ring == sdma3))
amdgpu_ttm_set_buffer_funcs_status(adev, false);
amdgpu_sdma_unset_buffer_funcs_helper(adev);
for (i = 0; i < adev->sdma.num_instances; i++) {
rb_cntl = RREG32_SOC15_IP(GC, sdma_v5_2_get_reg_offset(adev, i, mmSDMA0_GFX_RB_CNTL));
@ -1357,8 +1349,11 @@ static int sdma_v5_2_hw_fini(void *handle)
{
struct amdgpu_device *adev = (struct amdgpu_device *)handle;
if (amdgpu_sriov_vf(adev))
if (amdgpu_sriov_vf(adev)) {
/* disable the scheduler for SDMA */
amdgpu_sdma_unset_buffer_funcs_helper(adev);
return 0;
}
sdma_v5_2_ctx_switch_enable(adev, false);
sdma_v5_2_enable(adev, false);

View File

@ -398,14 +398,10 @@ static void sdma_v6_0_ring_emit_fence(struct amdgpu_ring *ring, u64 addr, u64 se
*/
static void sdma_v6_0_gfx_stop(struct amdgpu_device *adev)
{
struct amdgpu_ring *sdma0 = &adev->sdma.instance[0].ring;
struct amdgpu_ring *sdma1 = &adev->sdma.instance[1].ring;
u32 rb_cntl, ib_cntl;
int i;
if ((adev->mman.buffer_funcs_ring == sdma0) ||
(adev->mman.buffer_funcs_ring == sdma1))
amdgpu_ttm_set_buffer_funcs_status(adev, false);
amdgpu_sdma_unset_buffer_funcs_helper(adev);
for (i = 0; i < adev->sdma.num_instances; i++) {
rb_cntl = RREG32_SOC15_IP(GC, sdma_v6_0_get_reg_offset(adev, i, regSDMA0_QUEUE0_RB_CNTL));
@ -415,9 +411,6 @@ static void sdma_v6_0_gfx_stop(struct amdgpu_device *adev)
ib_cntl = REG_SET_FIELD(ib_cntl, SDMA0_QUEUE0_IB_CNTL, IB_ENABLE, 0);
WREG32_SOC15_IP(GC, sdma_v6_0_get_reg_offset(adev, i, regSDMA0_QUEUE0_IB_CNTL), ib_cntl);
}
sdma0->sched.ready = false;
sdma1->sched.ready = false;
}
/**
@ -846,7 +839,8 @@ static int sdma_v6_0_mqd_init(struct amdgpu_device *adev, void *mqd,
m->sdmax_rlcx_rb_cntl =
order_base_2(prop->queue_size / 4) << SDMA0_QUEUE0_RB_CNTL__RB_SIZE__SHIFT |
1 << SDMA0_QUEUE0_RB_CNTL__RPTR_WRITEBACK_ENABLE__SHIFT |
4 << SDMA0_QUEUE0_RB_CNTL__RPTR_WRITEBACK_TIMER__SHIFT;
4 << SDMA0_QUEUE0_RB_CNTL__RPTR_WRITEBACK_TIMER__SHIFT |
1 << SDMA0_QUEUE0_RB_CNTL__F32_WPTR_POLL_ENABLE__SHIFT;
m->sdmax_rlcx_rb_base = lower_32_bits(prop->hqd_base_gpu_addr >> 8);
m->sdmax_rlcx_rb_base_hi = upper_32_bits(prop->hqd_base_gpu_addr >> 8);
@ -1317,8 +1311,11 @@ static int sdma_v6_0_hw_fini(void *handle)
{
struct amdgpu_device *adev = (struct amdgpu_device *)handle;
if (amdgpu_sriov_vf(adev))
if (amdgpu_sriov_vf(adev)) {
/* disable the scheduler for SDMA */
amdgpu_sdma_unset_buffer_funcs_helper(adev);
return 0;
}
sdma_v6_0_ctx_switch_enable(adev, false);
sdma_v6_0_enable(adev, false);

View File

@ -116,15 +116,14 @@ static void si_dma_stop(struct amdgpu_device *adev)
u32 rb_cntl;
unsigned i;
amdgpu_sdma_unset_buffer_funcs_helper(adev);
for (i = 0; i < adev->sdma.num_instances; i++) {
ring = &adev->sdma.instance[i].ring;
/* dma0 */
rb_cntl = RREG32(DMA_RB_CNTL + sdma_offsets[i]);
rb_cntl &= ~DMA_RB_ENABLE;
WREG32(DMA_RB_CNTL + sdma_offsets[i], rb_cntl);
if (adev->mman.buffer_funcs_ring == ring)
amdgpu_ttm_set_buffer_funcs_status(adev, false);
}
}

View File

@ -629,6 +629,7 @@ static int soc21_common_early_init(void *handle)
AMD_CG_SUPPORT_JPEG_MGCG;
adev->pg_flags =
AMD_PG_SUPPORT_GFX_PG |
AMD_PG_SUPPORT_VCN |
AMD_PG_SUPPORT_VCN_DPG |
AMD_PG_SUPPORT_JPEG;
adev->external_rev_id = adev->rev_id + 0x1;

View File

@ -327,10 +327,9 @@ static void umc_v6_1_query_error_address(struct amdgpu_device *adev,
return;
}
/* calculate error address if ue/ce error is detected */
/* calculate error address if ue error is detected */
if (REG_GET_FIELD(mc_umc_status, MCA_UMC_UMC0_MCUMC_STATUST0, Val) == 1 &&
(REG_GET_FIELD(mc_umc_status, MCA_UMC_UMC0_MCUMC_STATUST0, UECC) == 1 ||
REG_GET_FIELD(mc_umc_status, MCA_UMC_UMC0_MCUMC_STATUST0, CECC) == 1)) {
REG_GET_FIELD(mc_umc_status, MCA_UMC_UMC0_MCUMC_STATUST0, UECC) == 1) {
err_addr = RREG64_PCIE((mc_umc_addrt0 + umc_reg_offset) * 4);
/* the lowest lsb bits should be ignored */
@ -343,10 +342,7 @@ static void umc_v6_1_query_error_address(struct amdgpu_device *adev,
ADDR_OF_256B_BLOCK(channel_index) |
OFFSET_IN_256B_BLOCK(err_addr);
/* we only save ue error information currently, ce is skipped */
if (REG_GET_FIELD(mc_umc_status, MCA_UMC_UMC0_MCUMC_STATUST0, UECC)
== 1)
amdgpu_umc_fill_error_record(err_data, err_addr,
amdgpu_umc_fill_error_record(err_data, err_addr,
retired_page, channel_index, umc_inst);
}

View File

@ -187,20 +187,51 @@ static void umc_v6_7_ecc_info_query_ras_error_count(struct amdgpu_device *adev,
}
}
static void umc_v6_7_convert_error_address(struct amdgpu_device *adev,
struct ras_err_data *err_data, uint64_t err_addr,
uint32_t ch_inst, uint32_t umc_inst)
{
uint32_t channel_index;
uint64_t soc_pa, retired_page, column;
channel_index =
adev->umc.channel_idx_tbl[umc_inst * adev->umc.channel_inst_num + ch_inst];
/* translate umc channel address to soc pa, 3 parts are included */
soc_pa = ADDR_OF_8KB_BLOCK(err_addr) |
ADDR_OF_256B_BLOCK(channel_index) |
OFFSET_IN_256B_BLOCK(err_addr);
/* The umc channel bits are not original values, they are hashed */
SET_CHANNEL_HASH(channel_index, soc_pa);
/* clear [C4 C3 C2] in soc physical address */
soc_pa &= ~(0x7ULL << UMC_V6_7_PA_C2_BIT);
/* loop for all possibilities of [C4 C3 C2] */
for (column = 0; column < UMC_V6_7_NA_MAP_PA_NUM; column++) {
retired_page = soc_pa | (column << UMC_V6_7_PA_C2_BIT);
dev_info(adev->dev, "Error Address(PA): 0x%llx\n", retired_page);
amdgpu_umc_fill_error_record(err_data, err_addr,
retired_page, channel_index, umc_inst);
/* shift R14 bit */
retired_page ^= (0x1ULL << UMC_V6_7_PA_R14_BIT);
dev_info(adev->dev, "Error Address(PA): 0x%llx\n", retired_page);
amdgpu_umc_fill_error_record(err_data, err_addr,
retired_page, channel_index, umc_inst);
}
}
static void umc_v6_7_ecc_info_query_error_address(struct amdgpu_device *adev,
struct ras_err_data *err_data,
uint32_t ch_inst,
uint32_t umc_inst)
{
uint64_t mc_umc_status, err_addr, soc_pa, retired_page, column;
uint32_t channel_index;
uint64_t mc_umc_status, err_addr;
uint32_t eccinfo_table_idx;
struct amdgpu_ras *ras = amdgpu_ras_get_context(adev);
eccinfo_table_idx = umc_inst * adev->umc.channel_inst_num + ch_inst;
channel_index =
adev->umc.channel_idx_tbl[umc_inst * adev->umc.channel_inst_num + ch_inst];
mc_umc_status = ras->umc_ecc.ecc[eccinfo_table_idx].mca_umc_status;
if (mc_umc_status == 0)
@ -209,42 +240,15 @@ static void umc_v6_7_ecc_info_query_error_address(struct amdgpu_device *adev,
if (!err_data->err_addr)
return;
/* calculate error address if ue/ce error is detected */
/* calculate error address if ue error is detected */
if (REG_GET_FIELD(mc_umc_status, MCA_UMC_UMC0_MCUMC_STATUST0, Val) == 1 &&
(REG_GET_FIELD(mc_umc_status, MCA_UMC_UMC0_MCUMC_STATUST0, UECC) == 1 ||
REG_GET_FIELD(mc_umc_status, MCA_UMC_UMC0_MCUMC_STATUST0, CECC) == 1)) {
REG_GET_FIELD(mc_umc_status, MCA_UMC_UMC0_MCUMC_STATUST0, UECC) == 1) {
err_addr = ras->umc_ecc.ecc[eccinfo_table_idx].mca_umc_addr;
err_addr = REG_GET_FIELD(err_addr, MCA_UMC_UMC0_MCUMC_ADDRT0, ErrorAddr);
/* translate umc channel address to soc pa, 3 parts are included */
soc_pa = ADDR_OF_8KB_BLOCK(err_addr) |
ADDR_OF_256B_BLOCK(channel_index) |
OFFSET_IN_256B_BLOCK(err_addr);
/* The umc channel bits are not original values, they are hashed */
SET_CHANNEL_HASH(channel_index, soc_pa);
/* clear [C4 C3 C2] in soc physical address */
soc_pa &= ~(0x7ULL << UMC_V6_7_PA_C2_BIT);
/* we only save ue error information currently, ce is skipped */
if (REG_GET_FIELD(mc_umc_status, MCA_UMC_UMC0_MCUMC_STATUST0, UECC)
== 1) {
/* loop for all possibilities of [C4 C3 C2] */
for (column = 0; column < UMC_V6_7_NA_MAP_PA_NUM; column++) {
retired_page = soc_pa | (column << UMC_V6_7_PA_C2_BIT);
dev_info(adev->dev, "Error Address(PA): 0x%llx\n", retired_page);
amdgpu_umc_fill_error_record(err_data, err_addr,
retired_page, channel_index, umc_inst);
/* shift R14 bit */
retired_page ^= (0x1ULL << UMC_V6_7_PA_R14_BIT);
dev_info(adev->dev, "Error Address(PA): 0x%llx\n", retired_page);
amdgpu_umc_fill_error_record(err_data, err_addr,
retired_page, channel_index, umc_inst);
}
}
umc_v6_7_convert_error_address(adev, err_data, err_addr,
ch_inst, umc_inst);
}
}
@ -453,81 +457,40 @@ static void umc_v6_7_query_ras_error_count(struct amdgpu_device *adev,
static void umc_v6_7_query_error_address(struct amdgpu_device *adev,
struct ras_err_data *err_data,
uint32_t umc_reg_offset, uint32_t ch_inst,
uint32_t umc_inst, uint64_t mca_addr)
uint32_t umc_inst)
{
uint32_t mc_umc_status_addr;
uint32_t channel_index;
uint64_t mc_umc_status = 0, mc_umc_addrt0;
uint64_t err_addr, soc_pa, retired_page, column;
uint64_t mc_umc_status = 0, mc_umc_addrt0, err_addr;
if (mca_addr == UMC_INVALID_ADDR) {
mc_umc_status_addr =
SOC15_REG_OFFSET(UMC, 0, regMCA_UMC_UMC0_MCUMC_STATUST0);
mc_umc_addrt0 =
SOC15_REG_OFFSET(UMC, 0, regMCA_UMC_UMC0_MCUMC_ADDRT0);
mc_umc_status_addr =
SOC15_REG_OFFSET(UMC, 0, regMCA_UMC_UMC0_MCUMC_STATUST0);
mc_umc_addrt0 =
SOC15_REG_OFFSET(UMC, 0, regMCA_UMC_UMC0_MCUMC_ADDRT0);
mc_umc_status = RREG64_PCIE((mc_umc_status_addr + umc_reg_offset) * 4);
mc_umc_status = RREG64_PCIE((mc_umc_status_addr + umc_reg_offset) * 4);
if (mc_umc_status == 0)
return;
if (mc_umc_status == 0)
return;
if (!err_data->err_addr) {
/* clear umc status */
WREG64_PCIE((mc_umc_status_addr + umc_reg_offset) * 4, 0x0ULL);
return;
}
if (!err_data->err_addr) {
/* clear umc status */
WREG64_PCIE((mc_umc_status_addr + umc_reg_offset) * 4, 0x0ULL);
return;
}
channel_index =
adev->umc.channel_idx_tbl[umc_inst * adev->umc.channel_inst_num + ch_inst];
/* calculate error address if ue error is detected */
if (REG_GET_FIELD(mc_umc_status, MCA_UMC_UMC0_MCUMC_STATUST0, Val) == 1 &&
REG_GET_FIELD(mc_umc_status, MCA_UMC_UMC0_MCUMC_STATUST0, UECC) == 1) {
err_addr = RREG64_PCIE((mc_umc_addrt0 + umc_reg_offset) * 4);
err_addr =
REG_GET_FIELD(err_addr, MCA_UMC_UMC0_MCUMC_ADDRT0, ErrorAddr);
/* calculate error address if ue/ce error is detected */
if ((REG_GET_FIELD(mc_umc_status, MCA_UMC_UMC0_MCUMC_STATUST0, Val) == 1 &&
(REG_GET_FIELD(mc_umc_status, MCA_UMC_UMC0_MCUMC_STATUST0, UECC) == 1 ||
REG_GET_FIELD(mc_umc_status, MCA_UMC_UMC0_MCUMC_STATUST0, CECC) == 1)) ||
mca_addr != UMC_INVALID_ADDR) {
if (mca_addr == UMC_INVALID_ADDR) {
err_addr = RREG64_PCIE((mc_umc_addrt0 + umc_reg_offset) * 4);
err_addr =
REG_GET_FIELD(err_addr, MCA_UMC_UMC0_MCUMC_ADDRT0, ErrorAddr);
} else {
err_addr = mca_addr;
}
/* translate umc channel address to soc pa, 3 parts are included */
soc_pa = ADDR_OF_8KB_BLOCK(err_addr) |
ADDR_OF_256B_BLOCK(channel_index) |
OFFSET_IN_256B_BLOCK(err_addr);
/* The umc channel bits are not original values, they are hashed */
SET_CHANNEL_HASH(channel_index, soc_pa);
/* clear [C4 C3 C2] in soc physical address */
soc_pa &= ~(0x7ULL << UMC_V6_7_PA_C2_BIT);
/* we only save ue error information currently, ce is skipped */
if (REG_GET_FIELD(mc_umc_status, MCA_UMC_UMC0_MCUMC_STATUST0, UECC)
== 1 ||
mca_addr != UMC_INVALID_ADDR) {
/* loop for all possibilities of [C4 C3 C2] */
for (column = 0; column < UMC_V6_7_NA_MAP_PA_NUM; column++) {
retired_page = soc_pa | (column << UMC_V6_7_PA_C2_BIT);
dev_info(adev->dev, "Error Address(PA): 0x%llx\n", retired_page);
amdgpu_umc_fill_error_record(err_data, err_addr,
retired_page, channel_index, umc_inst);
/* shift R14 bit */
retired_page ^= (0x1ULL << UMC_V6_7_PA_R14_BIT);
dev_info(adev->dev, "Error Address(PA): 0x%llx\n", retired_page);
amdgpu_umc_fill_error_record(err_data, err_addr,
retired_page, channel_index, umc_inst);
}
}
umc_v6_7_convert_error_address(adev, err_data, err_addr,
ch_inst, umc_inst);
}
/* clear umc status */
if (mca_addr == UMC_INVALID_ADDR)
WREG64_PCIE((mc_umc_status_addr + umc_reg_offset) * 4, 0x0ULL);
WREG64_PCIE((mc_umc_status_addr + umc_reg_offset) * 4, 0x0ULL);
}
static void umc_v6_7_query_ras_error_address(struct amdgpu_device *adev,
@ -549,7 +512,7 @@ static void umc_v6_7_query_ras_error_address(struct amdgpu_device *adev,
umc_v6_7_query_error_address(adev,
err_data,
umc_reg_offset, ch_inst,
umc_inst, UMC_INVALID_ADDR);
umc_inst);
}
}
@ -590,5 +553,5 @@ struct amdgpu_umc_ras umc_v6_7_ras = {
.query_ras_poison_mode = umc_v6_7_query_ras_poison_mode,
.ecc_info_query_ras_error_count = umc_v6_7_ecc_info_query_ras_error_count,
.ecc_info_query_ras_error_address = umc_v6_7_ecc_info_query_ras_error_address,
.convert_ras_error_address = umc_v6_7_query_error_address,
.convert_ras_error_address = umc_v6_7_convert_error_address,
};

View File

@ -208,7 +208,10 @@ static void umc_v8_10_query_error_address(struct amdgpu_device *adev,
{
uint64_t mc_umc_status_addr;
uint64_t mc_umc_status, err_addr;
uint32_t channel_index;
uint64_t mc_umc_addrt0, na_err_addr_base;
uint64_t na_err_addr, retired_page_addr;
uint32_t channel_index, addr_lsb, col = 0;
int ret = 0;
mc_umc_status_addr =
SOC15_REG_OFFSET(UMC, 0, regMCA_UMC_UMC0_MCUMC_STATUST0);
@ -229,13 +232,10 @@ static void umc_v8_10_query_error_address(struct amdgpu_device *adev,
umc_inst * adev->umc.channel_inst_num +
ch_inst];
/* calculate error address if ue/ce error is detected */
/* calculate error address if ue error is detected */
if (REG_GET_FIELD(mc_umc_status, MCA_UMC_UMC0_MCUMC_STATUST0, Val) == 1 &&
REG_GET_FIELD(mc_umc_status, MCA_UMC_UMC0_MCUMC_STATUST0, AddrV) == 1 &&
(REG_GET_FIELD(mc_umc_status, MCA_UMC_UMC0_MCUMC_STATUST0, UECC) == 1 ||
REG_GET_FIELD(mc_umc_status, MCA_UMC_UMC0_MCUMC_STATUST0, CECC) == 1)) {
uint32_t addr_lsb;
uint64_t mc_umc_addrt0;
REG_GET_FIELD(mc_umc_status, MCA_UMC_UMC0_MCUMC_STATUST0, UECC) == 1) {
mc_umc_addrt0 = SOC15_REG_OFFSET(UMC, 0, regMCA_UMC_UMC0_MCUMC_ADDRT0);
err_addr = RREG64_PCIE((mc_umc_addrt0 + umc_reg_offset) * 4);
@ -243,32 +243,24 @@ static void umc_v8_10_query_error_address(struct amdgpu_device *adev,
/* the lowest lsb bits should be ignored */
addr_lsb = REG_GET_FIELD(mc_umc_status, MCA_UMC_UMC0_MCUMC_STATUST0, AddrLsb);
err_addr &= ~((0x1ULL << addr_lsb) - 1);
na_err_addr_base = err_addr & ~(0x3ULL << UMC_V8_10_NA_C5_BIT);
/* we only save ue error information currently, ce is skipped */
if (REG_GET_FIELD(mc_umc_status, MCA_UMC_UMC0_MCUMC_STATUST0, UECC) == 1) {
uint64_t na_err_addr_base = err_addr & ~(0x3ULL << UMC_V8_10_NA_C5_BIT);
uint64_t na_err_addr, retired_page_addr;
uint32_t col = 0;
int ret = 0;
/* loop for all possibilities of [C6 C5] in normal address. */
for (col = 0; col < UMC_V8_10_NA_COL_2BITS_POWER_OF_2_NUM; col++) {
na_err_addr = na_err_addr_base | (col << UMC_V8_10_NA_C5_BIT);
/* loop for all possibilities of [C6 C5] in normal address. */
for (col = 0; col < UMC_V8_10_NA_COL_2BITS_POWER_OF_2_NUM; col++) {
na_err_addr = na_err_addr_base | (col << UMC_V8_10_NA_C5_BIT);
/* Mapping normal error address to retired soc physical address. */
ret = umc_v8_10_swizzle_mode_na_to_pa(adev, channel_index,
na_err_addr, &retired_page_addr);
if (ret) {
dev_err(adev->dev, "Failed to map pa from umc na.\n");
break;
}
dev_info(adev->dev, "Error Address(PA): 0x%llx\n",
retired_page_addr);
amdgpu_umc_fill_error_record(err_data, na_err_addr,
retired_page_addr, channel_index, umc_inst);
/* Mapping normal error address to retired soc physical address. */
ret = umc_v8_10_swizzle_mode_na_to_pa(adev, channel_index,
na_err_addr, &retired_page_addr);
if (ret) {
dev_err(adev->dev, "Failed to map pa from umc na.\n");
break;
}
dev_info(adev->dev, "Error Address(PA): 0x%llx\n",
retired_page_addr);
amdgpu_umc_fill_error_record(err_data, na_err_addr,
retired_page_addr, channel_index, umc_inst);
}
}
@ -338,6 +330,31 @@ static void umc_v8_10_err_cnt_init(struct amdgpu_device *adev)
}
}
static uint32_t umc_v8_10_query_ras_poison_mode_per_channel(
struct amdgpu_device *adev,
uint32_t umc_reg_offset)
{
uint32_t ecc_ctrl_addr, ecc_ctrl;
ecc_ctrl_addr =
SOC15_REG_OFFSET(UMC, 0, regUMCCH0_0_GeccCtrl);
ecc_ctrl = RREG32_PCIE((ecc_ctrl_addr +
umc_reg_offset) * 4);
return REG_GET_FIELD(ecc_ctrl, UMCCH0_0_GeccCtrl, UCFatalEn);
}
static bool umc_v8_10_query_ras_poison_mode(struct amdgpu_device *adev)
{
uint32_t umc_reg_offset = 0;
/* Enabling fatal error in umc node0 instance0 channel0 will be
* considered as fatal error mode
*/
umc_reg_offset = get_umc_v8_10_reg_offset(adev, 0, 0, 0);
return !umc_v8_10_query_ras_poison_mode_per_channel(adev, umc_reg_offset);
}
const struct amdgpu_ras_block_hw_ops umc_v8_10_ras_hw_ops = {
.query_ras_error_count = umc_v8_10_query_ras_error_count,
.query_ras_error_address = umc_v8_10_query_ras_error_address,
@ -348,4 +365,5 @@ struct amdgpu_umc_ras umc_v8_10_ras = {
.hw_ops = &umc_v8_10_ras_hw_ops,
},
.err_cnt_init = umc_v8_10_err_cnt_init,
.query_ras_poison_mode = umc_v8_10_query_ras_poison_mode,
};

View File

@ -108,20 +108,35 @@ static void umc_v8_7_ecc_info_query_ras_error_count(struct amdgpu_device *adev,
}
}
static void umc_v8_7_convert_error_address(struct amdgpu_device *adev,
struct ras_err_data *err_data, uint64_t err_addr,
uint32_t ch_inst, uint32_t umc_inst)
{
uint64_t retired_page;
uint32_t channel_index;
channel_index =
adev->umc.channel_idx_tbl[umc_inst * adev->umc.channel_inst_num + ch_inst];
/* translate umc channel address to soc pa, 3 parts are included */
retired_page = ADDR_OF_4KB_BLOCK(err_addr) |
ADDR_OF_256B_BLOCK(channel_index) |
OFFSET_IN_256B_BLOCK(err_addr);
amdgpu_umc_fill_error_record(err_data, err_addr,
retired_page, channel_index, umc_inst);
}
static void umc_v8_7_ecc_info_query_error_address(struct amdgpu_device *adev,
struct ras_err_data *err_data,
uint32_t ch_inst,
uint32_t umc_inst)
{
uint64_t mc_umc_status, err_addr, retired_page;
uint32_t channel_index;
uint64_t mc_umc_status, err_addr;
uint32_t eccinfo_table_idx;
struct amdgpu_ras *ras = amdgpu_ras_get_context(adev);
eccinfo_table_idx = umc_inst * adev->umc.channel_inst_num + ch_inst;
channel_index =
adev->umc.channel_idx_tbl[umc_inst * adev->umc.channel_inst_num + ch_inst];
mc_umc_status = ras->umc_ecc.ecc[eccinfo_table_idx].mca_umc_status;
if (mc_umc_status == 0)
@ -130,24 +145,15 @@ static void umc_v8_7_ecc_info_query_error_address(struct amdgpu_device *adev,
if (!err_data->err_addr)
return;
/* calculate error address if ue/ce error is detected */
/* calculate error address if ue error is detected */
if (REG_GET_FIELD(mc_umc_status, MCA_UMC_UMC0_MCUMC_STATUST0, Val) == 1 &&
(REG_GET_FIELD(mc_umc_status, MCA_UMC_UMC0_MCUMC_STATUST0, UECC) == 1 ||
REG_GET_FIELD(mc_umc_status, MCA_UMC_UMC0_MCUMC_STATUST0, CECC) == 1)) {
REG_GET_FIELD(mc_umc_status, MCA_UMC_UMC0_MCUMC_STATUST0, UECC) == 1) {
err_addr = ras->umc_ecc.ecc[eccinfo_table_idx].mca_umc_addr;
err_addr = REG_GET_FIELD(err_addr, MCA_UMC_UMC0_MCUMC_ADDRT0, ErrorAddr);
/* translate umc channel address to soc pa, 3 parts are included */
retired_page = ADDR_OF_4KB_BLOCK(err_addr) |
ADDR_OF_256B_BLOCK(channel_index) |
OFFSET_IN_256B_BLOCK(err_addr);
/* we only save ue error information currently, ce is skipped */
if (REG_GET_FIELD(mc_umc_status, MCA_UMC_UMC0_MCUMC_STATUST0, UECC)
== 1)
amdgpu_umc_fill_error_record(err_data, err_addr,
retired_page, channel_index, umc_inst);
umc_v8_7_convert_error_address(adev, err_data, err_addr,
ch_inst, umc_inst);
}
}
@ -324,14 +330,12 @@ static void umc_v8_7_query_error_address(struct amdgpu_device *adev,
uint32_t umc_inst)
{
uint32_t lsb, mc_umc_status_addr;
uint64_t mc_umc_status, err_addr, retired_page, mc_umc_addrt0;
uint32_t channel_index = adev->umc.channel_idx_tbl[umc_inst * adev->umc.channel_inst_num + ch_inst];
uint64_t mc_umc_status, err_addr, mc_umc_addrt0;
mc_umc_status_addr =
SOC15_REG_OFFSET(UMC, 0, mmMCA_UMC_UMC0_MCUMC_STATUST0);
mc_umc_addrt0 =
SOC15_REG_OFFSET(UMC, 0, mmMCA_UMC_UMC0_MCUMC_ADDRT0);
mc_umc_status = RREG64_PCIE((mc_umc_status_addr + umc_reg_offset) * 4);
if (mc_umc_status == 0)
@ -343,10 +347,9 @@ static void umc_v8_7_query_error_address(struct amdgpu_device *adev,
return;
}
/* calculate error address if ue/ce error is detected */
/* calculate error address if ue error is detected */
if (REG_GET_FIELD(mc_umc_status, MCA_UMC_UMC0_MCUMC_STATUST0, Val) == 1 &&
(REG_GET_FIELD(mc_umc_status, MCA_UMC_UMC0_MCUMC_STATUST0, UECC) == 1 ||
REG_GET_FIELD(mc_umc_status, MCA_UMC_UMC0_MCUMC_STATUST0, CECC) == 1)) {
REG_GET_FIELD(mc_umc_status, MCA_UMC_UMC0_MCUMC_STATUST0, UECC) == 1) {
err_addr = RREG64_PCIE((mc_umc_addrt0 + umc_reg_offset) * 4);
/* the lowest lsb bits should be ignored */
@ -354,16 +357,8 @@ static void umc_v8_7_query_error_address(struct amdgpu_device *adev,
err_addr = REG_GET_FIELD(err_addr, MCA_UMC_UMC0_MCUMC_ADDRT0, ErrorAddr);
err_addr &= ~((0x1ULL << lsb) - 1);
/* translate umc channel address to soc pa, 3 parts are included */
retired_page = ADDR_OF_4KB_BLOCK(err_addr) |
ADDR_OF_256B_BLOCK(channel_index) |
OFFSET_IN_256B_BLOCK(err_addr);
/* we only save ue error information currently, ce is skipped */
if (REG_GET_FIELD(mc_umc_status, MCA_UMC_UMC0_MCUMC_STATUST0, UECC)
== 1)
amdgpu_umc_fill_error_record(err_data, err_addr,
retired_page, channel_index, umc_inst);
umc_v8_7_convert_error_address(adev, err_data, err_addr,
ch_inst, umc_inst);
}
/* clear umc status */

View File

@ -333,7 +333,8 @@ static void update_mqd_sdma(struct mqd_manager *mm, void *mqd,
<< SDMA0_QUEUE0_RB_CNTL__RB_SIZE__SHIFT |
q->vmid << SDMA0_QUEUE0_RB_CNTL__RB_VMID__SHIFT |
1 << SDMA0_QUEUE0_RB_CNTL__RPTR_WRITEBACK_ENABLE__SHIFT |
6 << SDMA0_QUEUE0_RB_CNTL__RPTR_WRITEBACK_TIMER__SHIFT;
6 << SDMA0_QUEUE0_RB_CNTL__RPTR_WRITEBACK_TIMER__SHIFT |
1 << SDMA0_QUEUE0_RB_CNTL__F32_WPTR_POLL_ENABLE__SHIFT;
m->sdmax_rlcx_rb_base = lower_32_bits(q->queue_address >> 8);
m->sdmax_rlcx_rb_base_hi = upper_32_bits(q->queue_address >> 8);

View File

@ -1110,7 +1110,8 @@ static int dm_dmub_hw_init(struct amdgpu_device *adev)
hw_params.fb[i] = &fb_info->fb[i];
switch (adev->ip_versions[DCE_HWIP][0]) {
case IP_VERSION(3, 1, 3): /* Only for this asic hw internal rev B0 */
case IP_VERSION(3, 1, 3):
case IP_VERSION(3, 1, 4):
hw_params.dpia_supported = true;
hw_params.disable_dpia = adev->dm.dc->debug.dpia_debug.bits.disable_dpia;
break;
@ -7478,15 +7479,15 @@ static void amdgpu_dm_handle_vrr_transition(struct dm_crtc_state *old_state,
* We also need vupdate irq for the actual core vblank handling
* at end of vblank.
*/
dm_set_vupdate_irq(new_state->base.crtc, true);
drm_crtc_vblank_get(new_state->base.crtc);
WARN_ON(dm_set_vupdate_irq(new_state->base.crtc, true) != 0);
WARN_ON(drm_crtc_vblank_get(new_state->base.crtc) != 0);
DRM_DEBUG_DRIVER("%s: crtc=%u VRR off->on: Get vblank ref\n",
__func__, new_state->base.crtc->base.id);
} else if (old_vrr_active && !new_vrr_active) {
/* Transition VRR active -> inactive:
* Allow vblank irq disable again for fixed refresh rate.
*/
dm_set_vupdate_irq(new_state->base.crtc, false);
WARN_ON(dm_set_vupdate_irq(new_state->base.crtc, false) != 0);
drm_crtc_vblank_put(new_state->base.crtc);
DRM_DEBUG_DRIVER("%s: crtc=%u VRR on->off: Drop vblank ref\n",
__func__, new_state->base.crtc->base.id);
@ -8242,23 +8243,6 @@ static void amdgpu_dm_atomic_commit_tail(struct drm_atomic_state *state)
mutex_unlock(&dm->dc_lock);
}
/* Count number of newly disabled CRTCs for dropping PM refs later. */
for_each_oldnew_crtc_in_state(state, crtc, old_crtc_state,
new_crtc_state, i) {
if (old_crtc_state->active && !new_crtc_state->active)
crtc_disable_count++;
dm_new_crtc_state = to_dm_crtc_state(new_crtc_state);
dm_old_crtc_state = to_dm_crtc_state(old_crtc_state);
/* For freesync config update on crtc state and params for irq */
update_stream_irq_parameters(dm, dm_new_crtc_state);
/* Handle vrr on->off / off->on transitions */
amdgpu_dm_handle_vrr_transition(dm_old_crtc_state,
dm_new_crtc_state);
}
/**
* Enable interrupts for CRTCs that are newly enabled or went through
* a modeset. It was intentionally deferred until after the front end
@ -8268,16 +8252,29 @@ static void amdgpu_dm_atomic_commit_tail(struct drm_atomic_state *state)
for_each_oldnew_crtc_in_state(state, crtc, old_crtc_state, new_crtc_state, i) {
struct amdgpu_crtc *acrtc = to_amdgpu_crtc(crtc);
#ifdef CONFIG_DEBUG_FS
bool configure_crc = false;
enum amdgpu_dm_pipe_crc_source cur_crc_src;
#if defined(CONFIG_DRM_AMD_SECURE_DISPLAY)
struct crc_rd_work *crc_rd_wrk = dm->crc_rd_wrk;
struct crc_rd_work *crc_rd_wrk;
#endif
#endif
/* Count number of newly disabled CRTCs for dropping PM refs later. */
if (old_crtc_state->active && !new_crtc_state->active)
crtc_disable_count++;
dm_new_crtc_state = to_dm_crtc_state(new_crtc_state);
dm_old_crtc_state = to_dm_crtc_state(old_crtc_state);
/* For freesync config update on crtc state and params for irq */
update_stream_irq_parameters(dm, dm_new_crtc_state);
#ifdef CONFIG_DEBUG_FS
#if defined(CONFIG_DRM_AMD_SECURE_DISPLAY)
crc_rd_wrk = dm->crc_rd_wrk;
#endif
spin_lock_irqsave(&adev_to_drm(adev)->event_lock, flags);
cur_crc_src = acrtc->dm_irq_params.crc_src;
spin_unlock_irqrestore(&adev_to_drm(adev)->event_lock, flags);
#endif
dm_new_crtc_state = to_dm_crtc_state(new_crtc_state);
if (new_crtc_state->active &&
(!old_crtc_state->active ||
@ -8285,16 +8282,19 @@ static void amdgpu_dm_atomic_commit_tail(struct drm_atomic_state *state)
dc_stream_retain(dm_new_crtc_state->stream);
acrtc->dm_irq_params.stream = dm_new_crtc_state->stream;
manage_dm_interrupts(adev, acrtc, true);
}
/* Handle vrr on->off / off->on transitions */
amdgpu_dm_handle_vrr_transition(dm_old_crtc_state, dm_new_crtc_state);
#ifdef CONFIG_DEBUG_FS
if (new_crtc_state->active &&
(!old_crtc_state->active ||
drm_atomic_crtc_needs_modeset(new_crtc_state))) {
/**
* Frontend may have changed so reapply the CRC capture
* settings for the stream.
*/
dm_new_crtc_state = to_dm_crtc_state(new_crtc_state);
if (amdgpu_dm_is_valid_crc_source(cur_crc_src)) {
configure_crc = true;
#if defined(CONFIG_DRM_AMD_SECURE_DISPLAY)
if (amdgpu_dm_crc_window_is_activated(crtc)) {
spin_lock_irqsave(&adev_to_drm(adev)->event_lock, flags);
@ -8306,12 +8306,10 @@ static void amdgpu_dm_atomic_commit_tail(struct drm_atomic_state *state)
spin_unlock_irqrestore(&adev_to_drm(adev)->event_lock, flags);
}
#endif
}
if (configure_crc)
if (amdgpu_dm_crtc_configure_crc_source(
crtc, dm_new_crtc_state, cur_crc_src))
DRM_DEBUG_DRIVER("Failed to configure crc source");
}
#endif
}
}
@ -9392,10 +9390,6 @@ static int amdgpu_dm_atomic_check(struct drm_device *dev,
}
}
}
if (!pre_validate_dsc(state, &dm_state, vars)) {
ret = -EINVAL;
goto fail;
}
}
#endif
for_each_oldnew_crtc_in_state(state, crtc, old_crtc_state, new_crtc_state, i) {
@ -9529,6 +9523,15 @@ static int amdgpu_dm_atomic_check(struct drm_device *dev,
}
}
#if defined(CONFIG_DRM_AMD_DC_DCN)
if (dc_resource_is_dsc_encoding_supported(dc)) {
if (!pre_validate_dsc(state, &dm_state, vars)) {
ret = -EINVAL;
goto fail;
}
}
#endif
/* Run this here since we want to validate the streams we created */
ret = drm_atomic_helper_check_planes(dev, state);
if (ret) {

View File

@ -60,11 +60,15 @@ static bool link_supports_psrsu(struct dc_link *link)
*/
void amdgpu_dm_set_psr_caps(struct dc_link *link)
{
if (!(link->connector_signal & SIGNAL_TYPE_EDP))
if (!(link->connector_signal & SIGNAL_TYPE_EDP)) {
link->psr_settings.psr_feature_enabled = false;
return;
}
if (link->type == dc_connection_none)
if (link->type == dc_connection_none) {
link->psr_settings.psr_feature_enabled = false;
return;
}
if (link->dpcd_caps.psr_info.psr_version == 0) {
link->psr_settings.psr_version = DC_PSR_VERSION_UNSUPPORTED;

View File

@ -51,13 +51,6 @@
#define LAST_RECORD_TYPE 0xff
#define SMU9_SYSPLL0_ID 0
struct i2c_id_config_access {
uint8_t bfI2C_LineMux:4;
uint8_t bfHW_EngineID:3;
uint8_t bfHW_Capable:1;
uint8_t ucAccess;
};
static enum bp_result get_gpio_i2c_info(struct bios_parser *bp,
struct atom_i2c_record *record,
struct graphics_object_i2c_info *info);

View File

@ -179,7 +179,7 @@ void dcn20_update_clocks_update_dentist(struct clk_mgr_internal *clk_mgr, struct
} else if (dispclk_wdivider == 127 && current_dispclk_wdivider != 127) {
REG_UPDATE(DENTIST_DISPCLK_CNTL,
DENTIST_DISPCLK_WDIVIDER, 126);
REG_WAIT(DENTIST_DISPCLK_CNTL, DENTIST_DISPCLK_CHG_DONE, 1, 50, 100);
REG_WAIT(DENTIST_DISPCLK_CNTL, DENTIST_DISPCLK_CHG_DONE, 1, 50, 2000);
for (i = 0; i < clk_mgr->base.ctx->dc->res_pool->pipe_count; i++) {
struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i];
struct dccg *dccg = clk_mgr->base.ctx->dc->res_pool->dccg;
@ -206,7 +206,7 @@ void dcn20_update_clocks_update_dentist(struct clk_mgr_internal *clk_mgr, struct
REG_UPDATE(DENTIST_DISPCLK_CNTL,
DENTIST_DISPCLK_WDIVIDER, dispclk_wdivider);
REG_WAIT(DENTIST_DISPCLK_CNTL, DENTIST_DISPCLK_CHG_DONE, 1, 50, 1000);
REG_WAIT(DENTIST_DISPCLK_CNTL, DENTIST_DISPCLK_CHG_DONE, 1, 50, 2000);
REG_UPDATE(DENTIST_DISPCLK_CNTL,
DENTIST_DPPCLK_WDIVIDER, dppclk_wdivider);
REG_WAIT(DENTIST_DISPCLK_CNTL, DENTIST_DPPCLK_CHG_DONE, 1, 5, 100);

View File

@ -339,29 +339,24 @@ void dcn314_smu_set_zstate_support(struct clk_mgr_internal *clk_mgr, enum dcn_zs
if (!clk_mgr->smu_present)
return;
if (!clk_mgr->base.ctx->dc->debug.enable_z9_disable_interface &&
(support == DCN_ZSTATE_SUPPORT_ALLOW_Z10_ONLY))
support = DCN_ZSTATE_SUPPORT_DISALLOW;
// Arg[15:0] = 8/9/0 for Z8/Z9/disallow -> existing bits
// Arg[16] = Disallow Z9 -> new bit
switch (support) {
case DCN_ZSTATE_SUPPORT_ALLOW:
msg_id = VBIOSSMC_MSG_AllowZstatesEntry;
param = 9;
param = (1 << 10) | (1 << 9) | (1 << 8);
break;
case DCN_ZSTATE_SUPPORT_DISALLOW:
msg_id = VBIOSSMC_MSG_AllowZstatesEntry;
param = 8;
param = 0;
break;
case DCN_ZSTATE_SUPPORT_ALLOW_Z10_ONLY:
msg_id = VBIOSSMC_MSG_AllowZstatesEntry;
param = 0x00010008;
param = (1 << 10);
break;
default: //DCN_ZSTATE_SUPPORT_UNKNOWN

View File

@ -156,7 +156,7 @@ void dcn32_init_clocks(struct clk_mgr *clk_mgr_base)
{
struct clk_mgr_internal *clk_mgr = TO_CLK_MGR_INTERNAL(clk_mgr_base);
unsigned int num_levels;
unsigned int num_dcfclk_levels, num_dtbclk_levels, num_dispclk_levels;
struct clk_limit_num_entries *num_entries_per_clk = &clk_mgr_base->bw_params->clk_table.num_entries_per_clk;
memset(&(clk_mgr_base->clks), 0, sizeof(struct dc_clocks));
clk_mgr_base->clks.p_state_change_support = true;
@ -180,27 +180,28 @@ void dcn32_init_clocks(struct clk_mgr *clk_mgr_base)
/* DCFCLK */
dcn32_init_single_clock(clk_mgr, PPCLK_DCFCLK,
&clk_mgr_base->bw_params->clk_table.entries[0].dcfclk_mhz,
&num_levels);
num_dcfclk_levels = num_levels;
&num_entries_per_clk->num_dcfclk_levels);
/* SOCCLK */
dcn32_init_single_clock(clk_mgr, PPCLK_SOCCLK,
&clk_mgr_base->bw_params->clk_table.entries[0].socclk_mhz,
&num_levels);
&num_entries_per_clk->num_socclk_levels);
/* DTBCLK */
if (!clk_mgr->base.ctx->dc->debug.disable_dtb_ref_clk_switch)
dcn32_init_single_clock(clk_mgr, PPCLK_DTBCLK,
&clk_mgr_base->bw_params->clk_table.entries[0].dtbclk_mhz,
&num_levels);
num_dtbclk_levels = num_levels;
&num_entries_per_clk->num_dtbclk_levels);
/* DISPCLK */
dcn32_init_single_clock(clk_mgr, PPCLK_DISPCLK,
&clk_mgr_base->bw_params->clk_table.entries[0].dispclk_mhz,
&num_levels);
num_dispclk_levels = num_levels;
&num_entries_per_clk->num_dispclk_levels);
num_levels = num_entries_per_clk->num_dispclk_levels;
if (num_dcfclk_levels && num_dtbclk_levels && num_dispclk_levels)
if (num_entries_per_clk->num_dcfclk_levels &&
num_entries_per_clk->num_dtbclk_levels &&
num_entries_per_clk->num_dispclk_levels)
clk_mgr->dpm_present = true;
if (clk_mgr_base->ctx->dc->debug.min_disp_clk_khz) {
@ -333,6 +334,21 @@ static void dcn32_update_clocks(struct clk_mgr *clk_mgr_base,
if (enter_display_off == safe_to_lower)
dcn30_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 FCLK_PSTATE_SUPPORTED message to PMFW */
if (clk_mgr_base->ctx->dce_version != DCN_VERSION_3_21 && 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 */
dcn32_smu_send_fclk_pstate_message(clk_mgr, FCLK_PSTATE_SUPPORTED);
}
}
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);
@ -352,7 +368,6 @@ static void dcn32_update_clocks(struct clk_mgr *clk_mgr_base,
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.fclk_prev_p_state_change_support = clk_mgr_base->clks.fclk_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 &&
@ -361,27 +376,25 @@ static void dcn32_update_clocks(struct clk_mgr *clk_mgr_base,
dcn32_smu_send_cab_for_uclk_message(clk_mgr, clk_mgr_base->clks.num_ways);
}
total_plane_count = clk_mgr_helper_get_active_plane_cnt(dc, context);
p_state_change_support = new_clocks->p_state_change_support || (total_plane_count == 0);
fclk_p_state_change_support = new_clocks->fclk_p_state_change_support || (total_plane_count == 0);
if (should_update_pstate_support(safe_to_lower, p_state_change_support, clk_mgr_base->clks.p_state_change_support)) {
clk_mgr_base->clks.p_state_change_support = p_state_change_support;
/* to disable P-State switching, set UCLK min = max */
if (!clk_mgr_base->clks.p_state_change_support)
dcn32_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 - 1].memclk_mhz);
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);
}
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->ctx->dce_version != DCN_VERSION_3_21) {
clk_mgr_base->clks.fclk_p_state_change_support = fclk_p_state_change_support;
/* 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;
}
/* To disable FCLK P-state switching, send FCLK_PSTATE_NOTSUPPORTED message to PMFW */
if (clk_mgr_base->ctx->dce_version != DCN_VERSION_3_21 && !clk_mgr_base->clks.fclk_p_state_change_support) {
/* Handle code for sending a message to PMFW that FCLK P-state change is not supported */
dcn32_smu_send_fclk_pstate_message(clk_mgr, FCLK_PSTATE_NOTSUPPORTED);
}
if (clk_mgr_base->ctx->dce_version != DCN_VERSION_3_21 && !clk_mgr_base->clks.fclk_p_state_change_support && update_fclk) {
/* Handle code for sending a message to PMFW that FCLK P-state change is not supported */
dcn32_smu_send_fclk_pstate_message(clk_mgr, FCLK_PSTATE_NOTSUPPORTED);
}
/* Always update saved value, even if new value not set due to P-State switching unsupported */
@ -390,21 +403,11 @@ static void dcn32_update_clocks(struct clk_mgr *clk_mgr_base,
update_uclk = true;
}
/* 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;
}
/* 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))
dcn32_smu_set_hard_min_by_freq(clk_mgr, PPCLK_UCLK, khz_to_mhz_ceil(clk_mgr_base->clks.dramclk_khz));
if (clk_mgr_base->ctx->dce_version != DCN_VERSION_3_21 && clk_mgr_base->clks.fclk_p_state_change_support && update_fclk) {
/* Handle the code for sending a message to PMFW that FCLK P-state change is supported */
dcn32_smu_send_fclk_pstate_message(clk_mgr, FCLK_PSTATE_SUPPORTED);
}
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;
@ -632,7 +635,7 @@ static void dcn32_set_hard_min_memclk(struct clk_mgr *clk_mgr_base, bool current
khz_to_mhz_ceil(clk_mgr_base->clks.dramclk_khz));
else
dcn32_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 - 1].memclk_mhz);
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);
} else {
dcn32_smu_set_hard_min_by_freq(clk_mgr, PPCLK_UCLK,
clk_mgr_base->bw_params->clk_table.entries[0].memclk_mhz);
@ -648,22 +651,34 @@ static void dcn32_set_hard_max_memclk(struct clk_mgr *clk_mgr_base)
return;
dcn30_smu_set_hard_max_by_freq(clk_mgr, PPCLK_UCLK,
clk_mgr_base->bw_params->clk_table.entries[clk_mgr_base->bw_params->clk_table.num_entries - 1].memclk_mhz);
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);
}
/* Get current memclk states, update bounding box */
static void dcn32_get_memclk_states_from_smu(struct clk_mgr *clk_mgr_base)
{
struct clk_mgr_internal *clk_mgr = TO_CLK_MGR_INTERNAL(clk_mgr_base);
struct clk_limit_num_entries *num_entries_per_clk = &clk_mgr_base->bw_params->clk_table.num_entries_per_clk;
unsigned int num_levels;
if (!clk_mgr->smu_present)
return;
/* Refresh memclk states */
/* Refresh memclk and fclk states */
dcn32_init_single_clock(clk_mgr, PPCLK_UCLK,
&clk_mgr_base->bw_params->clk_table.entries[0].memclk_mhz,
&num_levels);
&num_entries_per_clk->num_memclk_levels);
dcn32_init_single_clock(clk_mgr, PPCLK_FCLK,
&clk_mgr_base->bw_params->clk_table.entries[0].fclk_mhz,
&num_entries_per_clk->num_fclk_levels);
if (num_entries_per_clk->num_memclk_levels >= num_entries_per_clk->num_fclk_levels) {
num_levels = num_entries_per_clk->num_memclk_levels;
} else {
num_levels = num_entries_per_clk->num_fclk_levels;
}
clk_mgr_base->bw_params->clk_table.num_entries = num_levels ? num_levels : 1;
if (clk_mgr->dpm_present && !num_levels)

View File

@ -1734,10 +1734,20 @@ static enum dc_status dc_commit_state_no_check(struct dc *dc, struct dc_state *c
int i, k, l;
struct dc_stream_state *dc_streams[MAX_STREAMS] = {0};
struct dc_state *old_state;
bool subvp_prev_use = false;
dc_z10_restore(dc);
dc_allow_idle_optimizations(dc, false);
for (i = 0; i < dc->res_pool->pipe_count; i++) {
struct pipe_ctx *old_pipe = &dc->current_state->res_ctx.pipe_ctx[i];
/* Check old context for SubVP */
subvp_prev_use |= (old_pipe->stream && old_pipe->stream->mall_stream_config.type == SUBVP_PHANTOM);
if (subvp_prev_use)
break;
}
for (i = 0; i < context->stream_count; i++)
dc_streams[i] = context->streams[i];
@ -1777,6 +1787,9 @@ static enum dc_status dc_commit_state_no_check(struct dc *dc, struct dc_state *c
dc->hwss.wait_for_mpcc_disconnect(dc, dc->res_pool, pipe);
}
if (dc->hwss.subvp_pipe_control_lock)
dc->hwss.subvp_pipe_control_lock(dc, context, true, true, NULL, subvp_prev_use);
result = dc->hwss.apply_ctx_to_hw(dc, context);
if (result != DC_OK) {
@ -1794,6 +1807,12 @@ static enum dc_status dc_commit_state_no_check(struct dc *dc, struct dc_state *c
dc->hwss.interdependent_update_lock(dc, context, false);
dc->hwss.post_unlock_program_front_end(dc, context);
}
if (dc->hwss.commit_subvp_config)
dc->hwss.commit_subvp_config(dc, context);
if (dc->hwss.subvp_pipe_control_lock)
dc->hwss.subvp_pipe_control_lock(dc, context, false, true, NULL, subvp_prev_use);
for (i = 0; i < context->stream_count; i++) {
const struct dc_link *link = context->streams[i]->link;
@ -2927,6 +2946,12 @@ static bool update_planes_and_stream_state(struct dc *dc,
dc_resource_state_copy_construct(
dc->current_state, context);
/* For each full update, remove all existing phantom pipes first.
* Ensures that we have enough pipes for newly added MPO planes
*/
if (dc->res_pool->funcs->remove_phantom_pipes)
dc->res_pool->funcs->remove_phantom_pipes(dc, context);
/*remove old surfaces from context */
if (!dc_rem_all_planes_for_stream(dc, stream, context)) {
@ -3334,8 +3359,14 @@ static void commit_planes_for_stream(struct dc *dc,
/* Since phantom pipe programming is moved to post_unlock_program_front_end,
* move the SubVP lock to after the phantom pipes have been setup
*/
if (dc->hwss.subvp_pipe_control_lock)
dc->hwss.subvp_pipe_control_lock(dc, context, false, should_lock_all_pipes, NULL, subvp_prev_use);
if (should_lock_all_pipes && dc->hwss.interdependent_update_lock) {
if (dc->hwss.subvp_pipe_control_lock)
dc->hwss.subvp_pipe_control_lock(dc, context, false, should_lock_all_pipes, NULL, subvp_prev_use);
} else {
if (dc->hwss.subvp_pipe_control_lock)
dc->hwss.subvp_pipe_control_lock(dc, context, false, should_lock_all_pipes, NULL, subvp_prev_use);
}
return;
}
@ -3495,6 +3526,9 @@ static void commit_planes_for_stream(struct dc *dc,
if (update_type != UPDATE_TYPE_FAST)
dc->hwss.post_unlock_program_front_end(dc, context);
if (update_type != UPDATE_TYPE_FAST)
if (dc->hwss.commit_subvp_config)
dc->hwss.commit_subvp_config(dc, context);
if (update_type != UPDATE_TYPE_FAST)
if (dc->hwss.commit_subvp_config)
@ -3542,6 +3576,7 @@ static bool could_mpcc_tree_change_for_active_pipes(struct dc *dc,
struct dc_stream_status *cur_stream_status = stream_get_status(dc->current_state, stream);
bool force_minimal_pipe_splitting = false;
uint32_t i;
*is_plane_addition = false;
@ -3573,6 +3608,36 @@ static bool could_mpcc_tree_change_for_active_pipes(struct dc *dc,
}
}
/* For SubVP pipe split case when adding MPO video
* we need to add a minimal transition. In this case
* there will be 2 streams (1 main stream, 1 phantom
* stream).
*/
if (cur_stream_status &&
dc->current_state->stream_count == 2 &&
stream->mall_stream_config.type == SUBVP_MAIN) {
bool is_pipe_split = false;
for (i = 0; i < dc->res_pool->pipe_count; i++) {
if (dc->current_state->res_ctx.pipe_ctx[i].stream == stream &&
(dc->current_state->res_ctx.pipe_ctx[i].bottom_pipe ||
dc->current_state->res_ctx.pipe_ctx[i].next_odm_pipe)) {
is_pipe_split = true;
break;
}
}
/* determine if minimal transition is required due to SubVP*/
if (surface_count > 0 && is_pipe_split) {
if (cur_stream_status->plane_count > surface_count) {
force_minimal_pipe_splitting = true;
} else if (cur_stream_status->plane_count < surface_count) {
force_minimal_pipe_splitting = true;
*is_plane_addition = true;
}
}
}
return force_minimal_pipe_splitting;
}
@ -3582,6 +3647,7 @@ static bool commit_minimal_transition_state(struct dc *dc,
struct dc_state *transition_context = dc_create_state(dc);
enum pipe_split_policy tmp_mpc_policy;
bool temp_dynamic_odm_policy;
bool temp_subvp_policy;
enum dc_status ret = DC_ERROR_UNEXPECTED;
unsigned int i, j;
@ -3596,6 +3662,9 @@ static bool commit_minimal_transition_state(struct dc *dc,
temp_dynamic_odm_policy = dc->debug.enable_single_display_2to1_odm_policy;
dc->debug.enable_single_display_2to1_odm_policy = false;
temp_subvp_policy = dc->debug.force_disable_subvp;
dc->debug.force_disable_subvp = true;
dc_resource_state_copy_construct(transition_base_context, transition_context);
//commit minimal state
@ -3624,6 +3693,7 @@ static bool commit_minimal_transition_state(struct dc *dc,
dc->debug.pipe_split_policy = tmp_mpc_policy;
dc->debug.enable_single_display_2to1_odm_policy = temp_dynamic_odm_policy;
dc->debug.force_disable_subvp = temp_subvp_policy;
if (ret != DC_OK) {
/*this should never happen*/
@ -4586,6 +4656,37 @@ enum dc_status dc_process_dmub_set_mst_slots(const struct dc *dc,
return DC_OK;
}
/**
*****************************************************************************
* Function: dc_process_dmub_dpia_hpd_int_enable
*
* @brief
* Submits dpia hpd int enable command to dmub via inbox message
*
* @param
* [in] dc: dc structure
* [in] hpd_int_enable: 1 for hpd int enable, 0 to disable
*
* @return
* None
*****************************************************************************
*/
void dc_process_dmub_dpia_hpd_int_enable(const struct dc *dc,
uint32_t hpd_int_enable)
{
union dmub_rb_cmd cmd = {0};
struct dc_dmub_srv *dmub_srv = dc->ctx->dmub_srv;
cmd.dpia_hpd_int_enable.header.type = DMUB_CMD__DPIA_HPD_INT_ENABLE;
cmd.dpia_hpd_int_enable.enable = hpd_int_enable;
dc_dmub_srv_cmd_queue(dmub_srv, &cmd);
dc_dmub_srv_cmd_execute(dmub_srv);
dc_dmub_srv_wait_idle(dmub_srv);
DC_LOG_DEBUG("%s: hpd_int_enable(%d)\n", __func__, hpd_int_enable);
}
/**
* dc_disable_accelerated_mode - disable accelerated mode
* @dc: dc structure

View File

@ -1307,7 +1307,10 @@ static bool detect_link_and_local_sink(struct dc_link *link,
}
if (link->connector_signal == SIGNAL_TYPE_EDP) {
// Init dc_panel_config
/* Init dc_panel_config by HW config */
if (dc_ctx->dc->res_pool->funcs->get_panel_config_defaults)
dc_ctx->dc->res_pool->funcs->get_panel_config_defaults(&link->panel_config);
/* Pickup base DM settings */
dm_helpers_init_panel_settings(dc_ctx, &link->panel_config, sink);
// Override dc_panel_config if system has specific settings
dm_helpers_override_panel_settings(dc_ctx, &link->panel_config);
@ -3143,7 +3146,7 @@ bool dc_link_set_psr_allow_active(struct dc_link *link, const bool *allow_active
if (!dc_get_edp_link_panel_inst(dc, link, &panel_inst))
return false;
if (allow_active && link->type == dc_connection_none) {
if ((allow_active != NULL) && (*allow_active == true) && (link->type == dc_connection_none)) {
// Don't enter PSR if panel is not connected
return false;
}
@ -3375,8 +3378,8 @@ bool dc_link_setup_psr(struct dc_link *link,
case FAMILY_YELLOW_CARP:
case AMDGPU_FAMILY_GC_10_3_6:
case AMDGPU_FAMILY_GC_11_0_1:
if(!dc->debug.disable_z10)
psr_context->psr_level.bits.SKIP_CRTC_DISABLE = false;
if (dc->debug.disable_z10)
psr_context->psr_level.bits.SKIP_CRTC_DISABLE = true;
break;
default:
psr_context->psr_level.bits.SKIP_CRTC_DISABLE = true;

View File

@ -944,6 +944,23 @@ enum dc_status dp_get_lane_status_and_lane_adjust(
return status;
}
static enum dc_status dpcd_128b_132b_set_lane_settings(
struct dc_link *link,
const struct link_training_settings *link_training_setting)
{
enum dc_status status = core_link_write_dpcd(link,
DP_TRAINING_LANE0_SET,
(uint8_t *)(link_training_setting->dpcd_lane_settings),
sizeof(link_training_setting->dpcd_lane_settings));
DC_LOG_HW_LINK_TRAINING("%s:\n 0x%X TX_FFE_PRESET_VALUE = %x\n",
__func__,
DP_TRAINING_LANE0_SET,
link_training_setting->dpcd_lane_settings[0].tx_ffe.PRESET_VALUE);
return status;
}
enum dc_status dpcd_set_lane_settings(
struct dc_link *link,
const struct link_training_settings *link_training_setting,
@ -964,16 +981,6 @@ enum dc_status dpcd_set_lane_settings(
link_training_setting->link_settings.lane_count);
if (is_repeater(link_training_setting, offset)) {
if (dp_get_link_encoding_format(&link_training_setting->link_settings) ==
DP_128b_132b_ENCODING)
DC_LOG_HW_LINK_TRAINING("%s:\n LTTPR Repeater ID: %d\n"
" 0x%X TX_FFE_PRESET_VALUE = %x\n",
__func__,
offset,
lane0_set_address,
link_training_setting->dpcd_lane_settings[0].tx_ffe.PRESET_VALUE);
else if (dp_get_link_encoding_format(&link_training_setting->link_settings) ==
DP_8b_10b_ENCODING)
DC_LOG_HW_LINK_TRAINING("%s\n LTTPR Repeater ID: %d\n"
" 0x%X VS set = %x PE set = %x max VS Reached = %x max PE Reached = %x\n",
__func__,
@ -985,14 +992,6 @@ enum dc_status dpcd_set_lane_settings(
link_training_setting->dpcd_lane_settings[0].bits.MAX_PRE_EMPHASIS_REACHED);
} else {
if (dp_get_link_encoding_format(&link_training_setting->link_settings) ==
DP_128b_132b_ENCODING)
DC_LOG_HW_LINK_TRAINING("%s:\n 0x%X TX_FFE_PRESET_VALUE = %x\n",
__func__,
lane0_set_address,
link_training_setting->dpcd_lane_settings[0].tx_ffe.PRESET_VALUE);
else if (dp_get_link_encoding_format(&link_training_setting->link_settings) ==
DP_8b_10b_ENCODING)
DC_LOG_HW_LINK_TRAINING("%s\n 0x%X VS set = %x PE set = %x max VS Reached = %x max PE Reached = %x\n",
__func__,
lane0_set_address,
@ -2023,7 +2022,7 @@ static enum link_training_result dp_perform_128b_132b_channel_eq_done_sequence(
result = DP_128b_132b_LT_FAILED;
} else {
dp_set_hw_lane_settings(link, link_res, lt_settings, DPRX);
dpcd_set_lane_settings(link, lt_settings, DPRX);
dpcd_128b_132b_set_lane_settings(link, lt_settings);
}
loop_count++;
}
@ -5090,6 +5089,7 @@ bool dp_retrieve_lttpr_cap(struct dc_link *link)
(dp_convert_to_count(link->dpcd_caps.lttpr_caps.phy_repeater_cnt) == 0)) {
ASSERT(0);
link->dpcd_caps.lttpr_caps.phy_repeater_cnt = 0x80;
DC_LOG_DC("lttpr_caps forced phy_repeater_cnt = %d\n", link->dpcd_caps.lttpr_caps.phy_repeater_cnt);
}
/* Attempt to train in LTTPR transparent mode if repeater count exceeds 8. */
@ -5098,6 +5098,7 @@ bool dp_retrieve_lttpr_cap(struct dc_link *link)
if (is_lttpr_present)
CONN_DATA_DETECT(link, lttpr_dpcd_data, sizeof(lttpr_dpcd_data), "LTTPR Caps: ");
DC_LOG_DC("is_lttpr_present = %d\n", is_lttpr_present);
return is_lttpr_present;
}
@ -5134,6 +5135,7 @@ void dp_get_lttpr_mode_override(struct dc_link *link, enum lttpr_mode *override)
} else if (link->dc->debug.lttpr_mode_override == LTTPR_MODE_NON_LTTPR) {
*override = LTTPR_MODE_NON_LTTPR;
}
DC_LOG_DC("lttpr_mode_override chose LTTPR_MODE = %d\n", (uint8_t)(*override));
}
enum lttpr_mode dp_decide_8b_10b_lttpr_mode(struct dc_link *link)
@ -5146,22 +5148,34 @@ enum lttpr_mode dp_decide_8b_10b_lttpr_mode(struct dc_link *link)
return LTTPR_MODE_NON_LTTPR;
if (vbios_lttpr_aware) {
if (vbios_lttpr_force_non_transparent)
if (vbios_lttpr_force_non_transparent) {
DC_LOG_DC("chose LTTPR_MODE_NON_TRANSPARENT due to VBIOS DCE_INFO_CAPS_LTTPR_SUPPORT_ENABLE set to 1.\n");
return LTTPR_MODE_NON_TRANSPARENT;
else
} else {
DC_LOG_DC("chose LTTPR_MODE_NON_TRANSPARENT by default due to VBIOS not set DCE_INFO_CAPS_LTTPR_SUPPORT_ENABLE set to 1.\n");
return LTTPR_MODE_TRANSPARENT;
}
}
if (link->dc->config.allow_lttpr_non_transparent_mode.bits.DP1_4A &&
link->dc->caps.extended_aux_timeout_support)
link->dc->caps.extended_aux_timeout_support) {
DC_LOG_DC("chose LTTPR_MODE_NON_TRANSPARENT by default and dc->config.allow_lttpr_non_transparent_mode.bits.DP1_4A set to 1.\n");
return LTTPR_MODE_NON_TRANSPARENT;
}
DC_LOG_DC("chose LTTPR_MODE_NON_LTTPR.\n");
return LTTPR_MODE_NON_LTTPR;
}
enum lttpr_mode dp_decide_128b_132b_lttpr_mode(struct dc_link *link)
{
return dp_is_lttpr_present(link) ? LTTPR_MODE_NON_TRANSPARENT : LTTPR_MODE_NON_LTTPR;
enum lttpr_mode mode = LTTPR_MODE_NON_LTTPR;
if (dp_is_lttpr_present(link))
mode = LTTPR_MODE_NON_TRANSPARENT;
DC_LOG_DC("128b_132b chose LTTPR_MODE %d.\n", mode);
return mode;
}
static bool get_usbc_cable_id(struct dc_link *link, union dp_cable_id *cable_id)
@ -5179,9 +5193,10 @@ static bool get_usbc_cable_id(struct dc_link *link, union dp_cable_id *cable_id)
cmd.cable_id.data.input.phy_inst = resource_transmitter_to_phy_idx(
link->dc, link->link_enc->transmitter);
if (dc_dmub_srv_cmd_with_reply_data(link->ctx->dmub_srv, &cmd) &&
cmd.cable_id.header.ret_status == 1)
cmd.cable_id.header.ret_status == 1) {
cable_id->raw = cmd.cable_id.data.output_raw;
DC_LOG_DC("usbc_cable_id = %d.\n", cable_id->raw);
}
return cmd.cable_id.header.ret_status == 1;
}
@ -5228,6 +5243,7 @@ static enum dc_status wa_try_to_wake_dprx(struct dc_link *link, uint64_t timeout
lttpr_present = dp_is_lttpr_present(link) ||
(!vbios_lttpr_interop || !link->dc->caps.extended_aux_timeout_support);
DC_LOG_DC("lttpr_present = %d.\n", lttpr_present ? 1 : 0);
/* Issue an AUX read to test DPRX responsiveness. If LTTPR is supported the first read is expected to
* be to determine LTTPR capabilities. Otherwise trying to read power state should be an innocuous AUX read.
@ -5795,7 +5811,7 @@ void detect_edp_sink_caps(struct dc_link *link)
* Per VESA eDP spec, "The DPCD revision for eDP v1.4 is 13h"
*/
if (link->dpcd_caps.dpcd_rev.raw >= DPCD_REV_13 &&
(link->dc->debug.optimize_edp_link_rate ||
(link->panel_config.ilr.optimize_edp_link_rate ||
link->reported_link_cap.link_rate == LINK_RATE_UNKNOWN)) {
// Read DPCD 00010h - 0001Fh 16 bytes at one shot
core_link_read_dpcd(link, DP_SUPPORTED_LINK_RATES,
@ -6744,7 +6760,7 @@ bool is_edp_ilr_optimization_required(struct dc_link *link, struct dc_crtc_timin
ASSERT(link || crtc_timing); // invalid input
if (link->dpcd_caps.edp_supported_link_rates_count == 0 ||
!link->dc->debug.optimize_edp_link_rate)
!link->panel_config.ilr.optimize_edp_link_rate)
return false;

View File

@ -1747,7 +1747,6 @@ bool dc_remove_plane_from_context(
for (i = 0; i < stream_status->plane_count; i++) {
if (stream_status->plane_states[i] == plane_state) {
dc_plane_state_release(stream_status->plane_states[i]);
break;
}
@ -3683,4 +3682,56 @@ bool is_h_timing_divisible_by_2(struct dc_stream_state *stream)
(stream->timing.h_sync_width % 2 == 0);
}
return divisible;
}
bool dc_resource_acquire_secondary_pipe_for_mpc_odm(
const struct dc *dc,
struct dc_state *state,
struct pipe_ctx *pri_pipe,
struct pipe_ctx *sec_pipe,
bool odm)
{
int pipe_idx = sec_pipe->pipe_idx;
struct pipe_ctx *sec_top, *sec_bottom, *sec_next, *sec_prev;
const struct resource_pool *pool = dc->res_pool;
sec_top = sec_pipe->top_pipe;
sec_bottom = sec_pipe->bottom_pipe;
sec_next = sec_pipe->next_odm_pipe;
sec_prev = sec_pipe->prev_odm_pipe;
*sec_pipe = *pri_pipe;
sec_pipe->top_pipe = sec_top;
sec_pipe->bottom_pipe = sec_bottom;
sec_pipe->next_odm_pipe = sec_next;
sec_pipe->prev_odm_pipe = sec_prev;
sec_pipe->pipe_idx = pipe_idx;
sec_pipe->plane_res.mi = pool->mis[pipe_idx];
sec_pipe->plane_res.hubp = pool->hubps[pipe_idx];
sec_pipe->plane_res.ipp = pool->ipps[pipe_idx];
sec_pipe->plane_res.xfm = pool->transforms[pipe_idx];
sec_pipe->plane_res.dpp = pool->dpps[pipe_idx];
sec_pipe->plane_res.mpcc_inst = pool->dpps[pipe_idx]->inst;
sec_pipe->stream_res.dsc = NULL;
if (odm) {
if (!sec_pipe->top_pipe)
sec_pipe->stream_res.opp = pool->opps[pipe_idx];
else
sec_pipe->stream_res.opp = sec_pipe->top_pipe->stream_res.opp;
if (sec_pipe->stream->timing.flags.DSC == 1) {
#if defined(CONFIG_DRM_AMD_DC_DCN)
dcn20_acquire_dsc(dc, &state->res_ctx, &sec_pipe->stream_res.dsc, pipe_idx);
#endif
ASSERT(sec_pipe->stream_res.dsc);
if (sec_pipe->stream_res.dsc == NULL)
return false;
}
#if defined(CONFIG_DRM_AMD_DC_DCN)
dcn20_build_mapped_resource(dc, state, sec_pipe->stream);
#endif
}
return true;
}

View File

@ -276,6 +276,8 @@ static void program_cursor_attributes(
}
dc->hwss.set_cursor_attribute(pipe_ctx);
dc_send_update_cursor_info_to_dmu(pipe_ctx, i);
if (dc->hwss.set_cursor_sdr_white_level)
dc->hwss.set_cursor_sdr_white_level(pipe_ctx);
}
@ -382,6 +384,8 @@ static void program_cursor_position(
}
dc->hwss.set_cursor_position(pipe_ctx);
dc_send_update_cursor_info_to_dmu(pipe_ctx, i);
}
if (pipe_to_program)
@ -520,9 +524,9 @@ bool dc_stream_remove_writeback(struct dc *dc,
}
/* remove writeback info for disabled writeback pipes from stream */
for (i = 0, j = 0; i < stream->num_wb_info && j < MAX_DWB_PIPES; i++) {
for (i = 0, j = 0; i < stream->num_wb_info; i++) {
if (stream->writeback_info[i].wb_enabled) {
if (i != j)
if (j < i)
/* trim the array */
stream->writeback_info[j] = stream->writeback_info[i];
j++;

View File

@ -47,7 +47,7 @@ struct aux_payload;
struct set_config_cmd_payload;
struct dmub_notification;
#define DC_VER "3.2.205"
#define DC_VER "3.2.207"
#define MAX_SURFACES 3
#define MAX_PLANES 6
@ -821,7 +821,6 @@ struct dc_debug_options {
/* Enable dmub aux for legacy ddc */
bool enable_dmub_aux_for_legacy_ddc;
bool disable_fams;
bool optimize_edp_link_rate; /* eDP ILR */
/* FEC/PSR1 sequence enable delay in 100us */
uint8_t fec_enable_delay_in100us;
bool enable_driver_sequence_debug;
@ -1192,6 +1191,8 @@ struct dc_plane_state {
enum dc_irq_source irq_source;
struct kref refcount;
struct tg_color visual_confirm_color;
bool is_statically_allocated;
};
struct dc_plane_info {
@ -1611,6 +1612,9 @@ enum dc_status dc_process_dmub_set_mst_slots(const struct dc *dc,
uint8_t mst_alloc_slots,
uint8_t *mst_slots_in_use);
void dc_process_dmub_dpia_hpd_int_enable(const struct dc *dc,
uint32_t hpd_int_enable);
/*******************************************************************************
* DSC Interfaces
******************************************************************************/

View File

@ -30,6 +30,7 @@
#include "dc_hw_types.h"
#include "core_types.h"
#include "../basics/conversion.h"
#include "cursor_reg_cache.h"
#define CTX dc_dmub_srv->ctx
#define DC_LOGGER CTX->logger
@ -780,7 +781,7 @@ void dc_dmub_setup_subvp_dmub_command(struct dc *dc,
// Store the original watermark value for this SubVP config so we can lower it when the
// MCLK switch starts
wm_val_refclk = context->bw_ctx.bw.dcn.watermarks.a.cstate_pstate.pstate_change_ns *
dc->res_pool->ref_clocks.dchub_ref_clock_inKhz / 1000 / 1000;
(dc->res_pool->ref_clocks.dchub_ref_clock_inKhz / 1000) / 1000;
cmd.fw_assisted_mclk_switch_v2.config_data.watermark_a_cache = wm_val_refclk < 0xFFFF ? wm_val_refclk : 0xFFFF;
}
@ -880,3 +881,147 @@ void dc_dmub_srv_log_diagnostic_data(struct dc_dmub_srv *dc_dmub_srv)
diag_data.is_cw0_enabled,
diag_data.is_cw6_enabled);
}
static bool dc_dmub_should_update_cursor_data(struct pipe_ctx *pipe_ctx)
{
if (pipe_ctx->plane_state != NULL) {
if (pipe_ctx->plane_state->address.type == PLN_ADDR_TYPE_VIDEO_PROGRESSIVE)
return false;
}
if ((pipe_ctx->stream->link->psr_settings.psr_version == DC_PSR_VERSION_SU_1 ||
pipe_ctx->stream->link->psr_settings.psr_version == DC_PSR_VERSION_1) &&
pipe_ctx->stream->ctx->dce_version >= DCN_VERSION_3_1)
return true;
return false;
}
static void dc_build_cursor_update_payload0(
struct pipe_ctx *pipe_ctx, uint8_t p_idx,
struct dmub_cmd_update_cursor_payload0 *payload)
{
struct hubp *hubp = pipe_ctx->plane_res.hubp;
unsigned int panel_inst = 0;
if (!dc_get_edp_link_panel_inst(hubp->ctx->dc,
pipe_ctx->stream->link, &panel_inst))
return;
/* Payload: Cursor Rect is built from position & attribute
* x & y are obtained from postion
*/
payload->cursor_rect.x = hubp->cur_rect.x;
payload->cursor_rect.y = hubp->cur_rect.y;
/* w & h are obtained from attribute */
payload->cursor_rect.width = hubp->cur_rect.w;
payload->cursor_rect.height = hubp->cur_rect.h;
payload->enable = hubp->pos.cur_ctl.bits.cur_enable;
payload->pipe_idx = p_idx;
payload->cmd_version = DMUB_CMD_PSR_CONTROL_VERSION_1;
payload->panel_inst = panel_inst;
}
static void dc_send_cmd_to_dmu(struct dc_dmub_srv *dmub_srv,
union dmub_rb_cmd *cmd)
{
dc_dmub_srv_cmd_queue(dmub_srv, cmd);
dc_dmub_srv_cmd_execute(dmub_srv);
dc_dmub_srv_wait_idle(dmub_srv);
}
static void dc_build_cursor_position_update_payload0(
struct dmub_cmd_update_cursor_payload0 *pl, const uint8_t p_idx,
const struct hubp *hubp, const struct dpp *dpp)
{
/* Hubp */
pl->position_cfg.pHubp.cur_ctl.raw = hubp->pos.cur_ctl.raw;
pl->position_cfg.pHubp.position.raw = hubp->pos.position.raw;
pl->position_cfg.pHubp.hot_spot.raw = hubp->pos.hot_spot.raw;
pl->position_cfg.pHubp.dst_offset.raw = hubp->pos.dst_offset.raw;
/* dpp */
pl->position_cfg.pDpp.cur0_ctl.raw = dpp->pos.cur0_ctl.raw;
pl->position_cfg.pipe_idx = p_idx;
}
static void dc_build_cursor_attribute_update_payload1(
struct dmub_cursor_attributes_cfg *pl_A, const uint8_t p_idx,
const struct hubp *hubp, const struct dpp *dpp)
{
/* Hubp */
pl_A->aHubp.SURFACE_ADDR_HIGH = hubp->att.SURFACE_ADDR_HIGH;
pl_A->aHubp.SURFACE_ADDR = hubp->att.SURFACE_ADDR;
pl_A->aHubp.cur_ctl.raw = hubp->att.cur_ctl.raw;
pl_A->aHubp.size.raw = hubp->att.size.raw;
pl_A->aHubp.settings.raw = hubp->att.settings.raw;
/* dpp */
pl_A->aDpp.cur0_ctl.raw = dpp->att.cur0_ctl.raw;
}
/**
* ***************************************************************************************
* dc_send_update_cursor_info_to_dmu: Populate the DMCUB Cursor update info command
*
* This function would store the cursor related information and pass it into dmub
*
* @param [in] pCtx: pipe context
* @param [in] pipe_idx: pipe index
*
* @return: void
*
* ***************************************************************************************
*/
void dc_send_update_cursor_info_to_dmu(
struct pipe_ctx *pCtx, uint8_t pipe_idx)
{
union dmub_rb_cmd cmd = { 0 };
union dmub_cmd_update_cursor_info_data *update_cursor_info =
&cmd.update_cursor_info.update_cursor_info_data;
if (!dc_dmub_should_update_cursor_data(pCtx))
return;
/*
* Since we use multi_cmd_pending for dmub command, the 2nd command is
* only assigned to store cursor attributes info.
* 1st command can view as 2 parts, 1st is for PSR/Replay data, the other
* is to store cursor position info.
*
* Command heaer type must be the same type if using multi_cmd_pending.
* Besides, while process 2nd command in DMU, the sub type is useless.
* So it's meanless to pass the sub type header with different type.
*/
{
/* Build Payload#0 Header */
cmd.update_cursor_info.header.type = DMUB_CMD__UPDATE_CURSOR_INFO;
cmd.update_cursor_info.header.payload_bytes =
sizeof(cmd.update_cursor_info.update_cursor_info_data);
cmd.update_cursor_info.header.multi_cmd_pending = 1; /* To combine multi dmu cmd, 1st cmd */
/* Prepare Payload */
dc_build_cursor_update_payload0(pCtx, pipe_idx, &update_cursor_info->payload0);
dc_build_cursor_position_update_payload0(&update_cursor_info->payload0, pipe_idx,
pCtx->plane_res.hubp, pCtx->plane_res.dpp);
/* Send update_curosr_info to queue */
dc_dmub_srv_cmd_queue(pCtx->stream->ctx->dmub_srv, &cmd);
}
{
/* Build Payload#1 Header */
memset(update_cursor_info, 0, sizeof(union dmub_cmd_update_cursor_info_data));
cmd.update_cursor_info.header.type = DMUB_CMD__UPDATE_CURSOR_INFO;
cmd.update_cursor_info.header.payload_bytes = sizeof(struct cursor_attributes_cfg);
cmd.update_cursor_info.header.multi_cmd_pending = 0; /* Indicate it's the last command. */
dc_build_cursor_attribute_update_payload1(
&cmd.update_cursor_info.update_cursor_info_data.payload1.attribute_cfg,
pipe_idx, pCtx->plane_res.hubp, pCtx->plane_res.dpp);
/* Combine 2nd cmds update_curosr_info to DMU */
dc_send_cmd_to_dmu(pCtx->stream->ctx->dmub_srv, &cmd);
}
}

View File

@ -88,4 +88,5 @@ bool dc_dmub_srv_get_diagnostic_data(struct dc_dmub_srv *dc_dmub_srv, struct dmu
void dc_dmub_setup_subvp_dmub_command(struct dc *dc, struct dc_state *context, bool enable);
void dc_dmub_srv_log_diagnostic_data(struct dc_dmub_srv *dc_dmub_srv);
void dc_send_update_cursor_info_to_dmu(struct pipe_ctx *pCtx, uint8_t pipe_idx);
#endif /* _DMUB_DC_SRV_H_ */

View File

@ -138,6 +138,10 @@ struct dc_panel_config {
bool disable_dsc_edp;
unsigned int force_dsc_edp_policy;
} dsc;
/* eDP ILR */
struct ilr {
bool optimize_edp_link_rate; /* eDP ILR */
} ilr;
};
/*
* A link contains one or more sinks and their connected status.

View File

@ -942,10 +942,6 @@ bool dce_aux_transfer_with_retries(struct ddc_service *ddc,
case AUX_RET_ERROR_ENGINE_ACQUIRE:
case AUX_RET_ERROR_UNKNOWN:
default:
DC_TRACE_LEVEL_MESSAGE(DAL_TRACE_LEVEL_INFORMATION,
LOG_FLAG_I2cAux_DceAux,
"dce_aux_transfer_with_retries: Failure: operation_result=%d",
(int)operation_result);
goto fail;
}
}
@ -953,14 +949,11 @@ bool dce_aux_transfer_with_retries(struct ddc_service *ddc,
fail:
DC_TRACE_LEVEL_MESSAGE(DAL_TRACE_LEVEL_ERROR,
LOG_FLAG_Error_I2cAux,
"dce_aux_transfer_with_retries: FAILURE");
"%s: Failure: operation_result=%d",
__func__,
(int)operation_result);
if (!payload_reply)
payload->reply = NULL;
DC_TRACE_LEVEL_MESSAGE(DAL_TRACE_LEVEL_ERROR,
WPP_BIT_FLAG_DC_ERROR,
"AUX transaction failed. Result: %d",
operation_result);
return false;
}

View File

@ -469,6 +469,7 @@ void dpp1_set_cursor_position(
REG_UPDATE(CURSOR0_CONTROL,
CUR0_ENABLE, cur_en);
dpp_base->pos.cur0_ctl.bits.cur0_enable = cur_en;
}
void dpp1_cnv_set_optional_cursor_attributes(

View File

@ -2244,6 +2244,9 @@ void dcn10_enable_timing_synchronization(
DC_SYNC_INFO("Setting up OTG reset trigger\n");
for (i = 1; i < group_size; i++) {
if (grouped_pipes[i]->stream && grouped_pipes[i]->stream->mall_stream_config.type == SUBVP_PHANTOM)
continue;
opp = grouped_pipes[i]->stream_res.opp;
tg = grouped_pipes[i]->stream_res.tg;
tg->funcs->get_otg_active_size(tg, &width, &height);
@ -2254,13 +2257,21 @@ void dcn10_enable_timing_synchronization(
for (i = 0; i < group_size; i++) {
if (grouped_pipes[i]->stream == NULL)
continue;
if (grouped_pipes[i]->stream && grouped_pipes[i]->stream->mall_stream_config.type == SUBVP_PHANTOM)
continue;
grouped_pipes[i]->stream->vblank_synchronized = false;
}
for (i = 1; i < group_size; i++)
for (i = 1; i < group_size; i++) {
if (grouped_pipes[i]->stream && grouped_pipes[i]->stream->mall_stream_config.type == SUBVP_PHANTOM)
continue;
grouped_pipes[i]->stream_res.tg->funcs->enable_reset_trigger(
grouped_pipes[i]->stream_res.tg,
grouped_pipes[0]->stream_res.tg->inst);
}
DC_SYNC_INFO("Waiting for trigger\n");
@ -2268,12 +2279,21 @@ void dcn10_enable_timing_synchronization(
* synchronized. Look at last pipe programmed to reset.
*/
wait_for_reset_trigger_to_occur(dc_ctx, grouped_pipes[1]->stream_res.tg);
for (i = 1; i < group_size; i++)
grouped_pipes[i]->stream_res.tg->funcs->disable_reset_trigger(
grouped_pipes[i]->stream_res.tg);
if (grouped_pipes[1]->stream && grouped_pipes[1]->stream->mall_stream_config.type != SUBVP_PHANTOM)
wait_for_reset_trigger_to_occur(dc_ctx, grouped_pipes[1]->stream_res.tg);
for (i = 1; i < group_size; i++) {
if (grouped_pipes[i]->stream && grouped_pipes[i]->stream->mall_stream_config.type == SUBVP_PHANTOM)
continue;
grouped_pipes[i]->stream_res.tg->funcs->disable_reset_trigger(
grouped_pipes[i]->stream_res.tg);
}
for (i = 1; i < group_size; i++) {
if (grouped_pipes[i]->stream && grouped_pipes[i]->stream->mall_stream_config.type == SUBVP_PHANTOM)
continue;
opp = grouped_pipes[i]->stream_res.opp;
tg = grouped_pipes[i]->stream_res.tg;
tg->funcs->get_otg_active_size(tg, &width, &height);
@ -3005,6 +3025,7 @@ void dcn10_prepare_bandwidth(
{
struct dce_hwseq *hws = dc->hwseq;
struct hubbub *hubbub = dc->res_pool->hubbub;
int min_fclk_khz, min_dcfclk_khz, socclk_khz;
if (dc->debug.sanity_checks)
hws->funcs.verify_allow_pstate_change_high(dc);
@ -3027,8 +3048,11 @@ void dcn10_prepare_bandwidth(
if (dc->debug.pplib_wm_report_mode == WM_REPORT_OVERRIDE) {
DC_FP_START();
dcn_bw_notify_pplib_of_wm_ranges(dc);
dcn_get_soc_clks(
dc, &min_fclk_khz, &min_dcfclk_khz, &socclk_khz);
DC_FP_END();
dcn_bw_notify_pplib_of_wm_ranges(
dc, min_fclk_khz, min_dcfclk_khz, socclk_khz);
}
if (dc->debug.sanity_checks)
@ -3041,6 +3065,7 @@ void dcn10_optimize_bandwidth(
{
struct dce_hwseq *hws = dc->hwseq;
struct hubbub *hubbub = dc->res_pool->hubbub;
int min_fclk_khz, min_dcfclk_khz, socclk_khz;
if (dc->debug.sanity_checks)
hws->funcs.verify_allow_pstate_change_high(dc);
@ -3064,8 +3089,11 @@ void dcn10_optimize_bandwidth(
if (dc->debug.pplib_wm_report_mode == WM_REPORT_OVERRIDE) {
DC_FP_START();
dcn_bw_notify_pplib_of_wm_ranges(dc);
dcn_get_soc_clks(
dc, &min_fclk_khz, &min_dcfclk_khz, &socclk_khz);
DC_FP_END();
dcn_bw_notify_pplib_of_wm_ranges(
dc, min_fclk_khz, min_dcfclk_khz, socclk_khz);
}
if (dc->debug.sanity_checks)
@ -3344,127 +3372,6 @@ static bool dcn10_can_pipe_disable_cursor(struct pipe_ctx *pipe_ctx)
return false;
}
static bool dcn10_dmub_should_update_cursor_data(
struct pipe_ctx *pipe_ctx,
struct dc_debug_options *debug)
{
if (pipe_ctx->plane_state->address.type == PLN_ADDR_TYPE_VIDEO_PROGRESSIVE)
return false;
if (dcn10_can_pipe_disable_cursor(pipe_ctx))
return false;
if ((pipe_ctx->stream->link->psr_settings.psr_version == DC_PSR_VERSION_SU_1 || pipe_ctx->stream->link->psr_settings.psr_version == DC_PSR_VERSION_1)
&& pipe_ctx->stream->ctx->dce_version >= DCN_VERSION_3_1)
return true;
return false;
}
static void dcn10_dmub_update_cursor_data(
struct pipe_ctx *pipe_ctx,
struct hubp *hubp,
const struct dc_cursor_mi_param *param,
const struct dc_cursor_position *cur_pos,
const struct dc_cursor_attributes *cur_attr)
{
union dmub_rb_cmd cmd;
struct dmub_cmd_update_cursor_info_data *update_cursor_info;
const struct dc_cursor_position *pos;
const struct dc_cursor_attributes *attr;
int src_x_offset = 0;
int src_y_offset = 0;
int x_hotspot = 0;
int cursor_height = 0;
int cursor_width = 0;
uint32_t cur_en = 0;
unsigned int panel_inst = 0;
struct dc_debug_options *debug = &hubp->ctx->dc->debug;
if (!dcn10_dmub_should_update_cursor_data(pipe_ctx, debug))
return;
/**
* if cur_pos == NULL means the caller is from cursor_set_attribute
* then driver use previous cursor position data
* if cur_attr == NULL means the caller is from cursor_set_position
* then driver use previous cursor attribute
* if cur_pos or cur_attr is not NULL then update it
*/
if (cur_pos != NULL)
pos = cur_pos;
else
pos = &hubp->curs_pos;
if (cur_attr != NULL)
attr = cur_attr;
else
attr = &hubp->curs_attr;
if (!dc_get_edp_link_panel_inst(hubp->ctx->dc, pipe_ctx->stream->link, &panel_inst))
return;
src_x_offset = pos->x - pos->x_hotspot - param->viewport.x;
src_y_offset = pos->y - pos->y_hotspot - param->viewport.y;
x_hotspot = pos->x_hotspot;
cursor_height = (int)attr->height;
cursor_width = (int)attr->width;
cur_en = pos->enable ? 1:0;
// Rotated cursor width/height and hotspots tweaks for offset calculation
if (param->rotation == ROTATION_ANGLE_90 || param->rotation == ROTATION_ANGLE_270) {
swap(cursor_height, cursor_width);
if (param->rotation == ROTATION_ANGLE_90) {
src_x_offset = pos->x - pos->y_hotspot - param->viewport.x;
src_y_offset = pos->y - pos->x_hotspot - param->viewport.y;
}
} else if (param->rotation == ROTATION_ANGLE_180) {
src_x_offset = pos->x - param->viewport.x;
src_y_offset = pos->y - param->viewport.y;
}
if (param->mirror) {
x_hotspot = param->viewport.width - x_hotspot;
src_x_offset = param->viewport.x + param->viewport.width - src_x_offset;
}
if (src_x_offset >= (int)param->viewport.width)
cur_en = 0; /* not visible beyond right edge*/
if (src_x_offset + cursor_width <= 0)
cur_en = 0; /* not visible beyond left edge*/
if (src_y_offset >= (int)param->viewport.height)
cur_en = 0; /* not visible beyond bottom edge*/
if (src_y_offset + cursor_height <= 0)
cur_en = 0; /* not visible beyond top edge*/
// Cursor bitmaps have different hotspot values
// There's a possibility that the above logic returns a negative value, so we clamp them to 0
if (src_x_offset < 0)
src_x_offset = 0;
if (src_y_offset < 0)
src_y_offset = 0;
memset(&cmd, 0x0, sizeof(cmd));
cmd.update_cursor_info.header.type = DMUB_CMD__UPDATE_CURSOR_INFO;
cmd.update_cursor_info.header.payload_bytes =
sizeof(cmd.update_cursor_info.update_cursor_info_data);
update_cursor_info = &cmd.update_cursor_info.update_cursor_info_data;
update_cursor_info->cursor_rect.x = src_x_offset + param->viewport.x;
update_cursor_info->cursor_rect.y = src_y_offset + param->viewport.y;
update_cursor_info->cursor_rect.width = attr->width;
update_cursor_info->cursor_rect.height = attr->height;
update_cursor_info->enable = cur_en;
update_cursor_info->pipe_idx = pipe_ctx->pipe_idx;
update_cursor_info->cmd_version = DMUB_CMD_PSR_CONTROL_VERSION_1;
update_cursor_info->panel_inst = panel_inst;
dc_dmub_srv_cmd_queue(pipe_ctx->stream->ctx->dmub_srv, &cmd);
dc_dmub_srv_cmd_execute(pipe_ctx->stream->ctx->dmub_srv);
dc_dmub_srv_wait_idle(pipe_ctx->stream->ctx->dmub_srv);
}
void dcn10_set_cursor_position(struct pipe_ctx *pipe_ctx)
{
struct dc_cursor_position pos_cpy = pipe_ctx->stream->cursor_position;
@ -3699,7 +3606,6 @@ void dcn10_set_cursor_position(struct pipe_ctx *pipe_ctx)
pipe_ctx->plane_res.scl_data.viewport.height - pos_cpy.y;
}
dcn10_dmub_update_cursor_data(pipe_ctx, hubp, &param, &pos_cpy, NULL);
hubp->funcs->set_cursor_position(hubp, &pos_cpy, &param);
dpp->funcs->set_cursor_position(dpp, &pos_cpy, &param, hubp->curs_attr.width, hubp->curs_attr.height);
}
@ -3707,25 +3613,6 @@ void dcn10_set_cursor_position(struct pipe_ctx *pipe_ctx)
void dcn10_set_cursor_attribute(struct pipe_ctx *pipe_ctx)
{
struct dc_cursor_attributes *attributes = &pipe_ctx->stream->cursor_attributes;
struct dc_cursor_mi_param param = { 0 };
/**
* If enter PSR without cursor attribute update
* the cursor attribute of dmub_restore_plane
* are initial value. call dmub to exit PSR and
* restore plane then update cursor attribute to
* avoid override with initial value
*/
if (pipe_ctx->plane_state != NULL) {
param.pixel_clk_khz = pipe_ctx->stream->timing.pix_clk_100hz / 10;
param.ref_clk_khz = pipe_ctx->stream->ctx->dc->res_pool->ref_clocks.dchub_ref_clock_inKhz;
param.viewport = pipe_ctx->plane_res.scl_data.viewport;
param.h_scale_ratio = pipe_ctx->plane_res.scl_data.ratios.horz;
param.v_scale_ratio = pipe_ctx->plane_res.scl_data.ratios.vert;
param.rotation = pipe_ctx->plane_state->rotation;
param.mirror = pipe_ctx->plane_state->horizontal_mirror;
dcn10_dmub_update_cursor_data(pipe_ctx, pipe_ctx->plane_res.hubp, &param, NULL, attributes);
}
pipe_ctx->plane_res.hubp->funcs->set_cursor_attributes(
pipe_ctx->plane_res.hubp, attributes);
@ -3810,28 +3697,14 @@ void dcn10_calc_vupdate_position(
uint32_t *start_line,
uint32_t *end_line)
{
const struct dc_crtc_timing *dc_crtc_timing = &pipe_ctx->stream->timing;
int vline_int_offset_from_vupdate =
pipe_ctx->stream->periodic_interrupt.lines_offset;
int vupdate_offset_from_vsync = dc->hwss.get_vupdate_offset_from_vsync(pipe_ctx);
int start_position;
const struct dc_crtc_timing *timing = &pipe_ctx->stream->timing;
int vupdate_pos = dc->hwss.get_vupdate_offset_from_vsync(pipe_ctx);
if (vline_int_offset_from_vupdate > 0)
vline_int_offset_from_vupdate--;
else if (vline_int_offset_from_vupdate < 0)
vline_int_offset_from_vupdate++;
start_position = vline_int_offset_from_vupdate + vupdate_offset_from_vsync;
if (start_position >= 0)
*start_line = start_position;
if (vupdate_pos >= 0)
*start_line = vupdate_pos - ((vupdate_pos / timing->v_total) * timing->v_total);
else
*start_line = dc_crtc_timing->v_total + start_position - 1;
*end_line = *start_line + 2;
if (*end_line >= dc_crtc_timing->v_total)
*end_line = 2;
*start_line = vupdate_pos + ((-vupdate_pos / timing->v_total) + 1) * timing->v_total - 1;
*end_line = (*start_line + 2) % timing->v_total;
}
static void dcn10_cal_vline_position(
@ -3840,23 +3713,27 @@ static void dcn10_cal_vline_position(
uint32_t *start_line,
uint32_t *end_line)
{
switch (pipe_ctx->stream->periodic_interrupt.ref_point) {
case START_V_UPDATE:
dcn10_calc_vupdate_position(
dc,
pipe_ctx,
start_line,
end_line);
break;
case START_V_SYNC:
const struct dc_crtc_timing *timing = &pipe_ctx->stream->timing;
int vline_pos = pipe_ctx->stream->periodic_interrupt.lines_offset;
if (pipe_ctx->stream->periodic_interrupt.ref_point == START_V_UPDATE) {
if (vline_pos > 0)
vline_pos--;
else if (vline_pos < 0)
vline_pos++;
vline_pos += dc->hwss.get_vupdate_offset_from_vsync(pipe_ctx);
if (vline_pos >= 0)
*start_line = vline_pos - ((vline_pos / timing->v_total) * timing->v_total);
else
*start_line = vline_pos + ((-vline_pos / timing->v_total) + 1) * timing->v_total - 1;
*end_line = (*start_line + 2) % timing->v_total;
} else if (pipe_ctx->stream->periodic_interrupt.ref_point == START_V_SYNC) {
// vsync is line 0 so start_line is just the requested line offset
*start_line = pipe_ctx->stream->periodic_interrupt.lines_offset;
*end_line = *start_line + 2;
break;
default:
*start_line = vline_pos;
*end_line = (*start_line + 2) % timing->v_total;
} else
ASSERT(0);
break;
}
}
void dcn10_setup_periodic_interrupt(

View File

@ -207,10 +207,7 @@ void optc1_program_timing(
/* In case of V_TOTAL_CONTROL is on, make sure OTG_V_TOTAL_MAX and
* OTG_V_TOTAL_MIN are equal to V_TOTAL.
*/
REG_SET(OTG_V_TOTAL_MAX, 0,
OTG_V_TOTAL_MAX, v_total);
REG_SET(OTG_V_TOTAL_MIN, 0,
OTG_V_TOTAL_MIN, v_total);
optc->funcs->set_vtotal_min_max(optc, v_total, v_total);
/* v_sync_start = 0, v_sync_end = v_sync_width */
v_sync_end = patched_crtc_timing.v_sync_width;
@ -649,13 +646,6 @@ uint32_t optc1_get_vblank_counter(struct timing_generator *optc)
void optc1_lock(struct timing_generator *optc)
{
struct optc *optc1 = DCN10TG_FROM_TG(optc);
uint32_t regval = 0;
regval = REG_READ(OTG_CONTROL);
/* otg is not running, do not need to be locked */
if ((regval & 0x1) == 0x0)
return;
REG_SET(OTG_GLOBAL_CONTROL0, 0,
OTG_MASTER_UPDATE_LOCK_SEL, optc->inst);
@ -663,12 +653,10 @@ void optc1_lock(struct timing_generator *optc)
OTG_MASTER_UPDATE_LOCK, 1);
/* Should be fast, status does not update on maximus */
if (optc->ctx->dce_environment != DCE_ENV_FPGA_MAXIMUS) {
if (optc->ctx->dce_environment != DCE_ENV_FPGA_MAXIMUS)
REG_WAIT(OTG_MASTER_UPDATE_LOCK,
UPDATE_LOCK_STATUS, 1,
1, 10);
}
}
void optc1_unlock(struct timing_generator *optc)
@ -679,16 +667,6 @@ void optc1_unlock(struct timing_generator *optc)
OTG_MASTER_UPDATE_LOCK, 0);
}
bool optc1_is_locked(struct timing_generator *optc)
{
struct optc *optc1 = DCN10TG_FROM_TG(optc);
uint32_t locked;
REG_GET(OTG_MASTER_UPDATE_LOCK, UPDATE_LOCK_STATUS, &locked);
return (locked == 1);
}
void optc1_get_position(struct timing_generator *optc,
struct crtc_position *position)
{
@ -941,11 +919,7 @@ void optc1_set_drr(
}
REG_SET(OTG_V_TOTAL_MAX, 0,
OTG_V_TOTAL_MAX, params->vertical_total_max - 1);
REG_SET(OTG_V_TOTAL_MIN, 0,
OTG_V_TOTAL_MIN, params->vertical_total_min - 1);
optc->funcs->set_vtotal_min_max(optc, params->vertical_total_min - 1, params->vertical_total_max - 1);
REG_UPDATE_5(OTG_V_TOTAL_CONTROL,
OTG_V_TOTAL_MIN_SEL, 1,
@ -964,11 +938,7 @@ void optc1_set_drr(
OTG_V_TOTAL_MAX_SEL, 0,
OTG_FORCE_LOCK_ON_EVENT, 0);
REG_SET(OTG_V_TOTAL_MIN, 0,
OTG_V_TOTAL_MIN, 0);
REG_SET(OTG_V_TOTAL_MAX, 0,
OTG_V_TOTAL_MAX, 0);
optc->funcs->set_vtotal_min_max(optc, 0, 0);
}
}
@ -1583,11 +1553,11 @@ static const struct timing_generator_funcs dcn10_tg_funcs = {
.enable_crtc_reset = optc1_enable_crtc_reset,
.disable_reset_trigger = optc1_disable_reset_trigger,
.lock = optc1_lock,
.is_locked = optc1_is_locked,
.unlock = optc1_unlock,
.enable_optc_clock = optc1_enable_optc_clock,
.set_drr = optc1_set_drr,
.get_last_used_drr_vtotal = NULL,
.set_vtotal_min_max = optc1_set_vtotal_min_max,
.set_static_screen_control = optc1_set_static_screen_control,
.set_test_pattern = optc1_set_test_pattern,
.program_stereo = optc1_program_stereo,

View File

@ -654,7 +654,6 @@ void optc1_set_blank(struct timing_generator *optc,
bool enable_blanking);
bool optc1_is_blanked(struct timing_generator *optc);
bool optc1_is_locked(struct timing_generator *optc);
void optc1_program_blank_color(
struct timing_generator *optc,

View File

@ -1336,6 +1336,21 @@ static noinline void dcn10_resource_construct_fp(
}
}
static bool verify_clock_values(struct dm_pp_clock_levels_with_voltage *clks)
{
int i;
if (clks->num_levels == 0)
return false;
for (i = 0; i < clks->num_levels; i++)
/* Ensure that the result is sane */
if (clks->data[i].clocks_in_khz == 0)
return false;
return true;
}
static bool dcn10_resource_construct(
uint8_t num_virtual_links,
struct dc *dc,
@ -1345,6 +1360,9 @@ static bool dcn10_resource_construct(
int j;
struct dc_context *ctx = dc->ctx;
uint32_t pipe_fuses = read_pipe_fuses(ctx);
struct dm_pp_clock_levels_with_voltage fclks = {0}, dcfclks = {0};
int min_fclk_khz, min_dcfclk_khz, socclk_khz;
bool res;
ctx->dc_bios->regs = &bios_regs;
@ -1523,15 +1541,53 @@ static bool dcn10_resource_construct(
&& pool->base.pp_smu->rv_funcs.set_pme_wa_enable != NULL)
dc->debug.az_endpoint_mute_only = false;
DC_FP_START();
if (!dc->debug.disable_pplib_clock_request)
dcn_bw_update_from_pplib(dc);
if (!dc->debug.disable_pplib_clock_request) {
/*
* TODO: This is not the proper way to obtain
* fabric_and_dram_bandwidth, should be min(fclk, memclk).
*/
res = dm_pp_get_clock_levels_by_type_with_voltage(
ctx, DM_PP_CLOCK_TYPE_FCLK, &fclks);
DC_FP_START();
if (res)
res = verify_clock_values(&fclks);
if (res)
dcn_bw_update_from_pplib_fclks(dc, &fclks);
else
BREAK_TO_DEBUGGER();
DC_FP_END();
res = dm_pp_get_clock_levels_by_type_with_voltage(
ctx, DM_PP_CLOCK_TYPE_DCFCLK, &dcfclks);
DC_FP_START();
if (res)
res = verify_clock_values(&dcfclks);
if (res)
dcn_bw_update_from_pplib_dcfclks(dc, &dcfclks);
else
BREAK_TO_DEBUGGER();
DC_FP_END();
}
dcn_bw_sync_calcs_and_dml(dc);
if (!dc->debug.disable_pplib_wm_range) {
dc->res_pool = &pool->base;
dcn_bw_notify_pplib_of_wm_ranges(dc);
DC_FP_START();
dcn_get_soc_clks(
dc, &min_fclk_khz, &min_dcfclk_khz, &socclk_khz);
DC_FP_END();
dcn_bw_notify_pplib_of_wm_ranges(
dc, min_fclk_khz, min_dcfclk_khz, socclk_khz);
}
DC_FP_END();
{
struct irq_service_init_data init_data;

View File

@ -617,6 +617,17 @@ void hubp2_cursor_set_attributes(
CURSOR0_DST_Y_OFFSET, 0,
/* used to shift the cursor chunk request deadline */
CURSOR0_CHUNK_HDL_ADJUST, 3);
hubp->att.SURFACE_ADDR_HIGH = attr->address.high_part;
hubp->att.SURFACE_ADDR = attr->address.low_part;
hubp->att.size.bits.width = attr->width;
hubp->att.size.bits.height = attr->height;
hubp->att.cur_ctl.bits.mode = attr->color_format;
hubp->att.cur_ctl.bits.pitch = hw_pitch;
hubp->att.cur_ctl.bits.line_per_chunk = lpc;
hubp->att.cur_ctl.bits.cur_2x_magnify = attr->attribute_flags.bits.ENABLE_MAGNIFICATION;
hubp->att.settings.bits.dst_y_offset = 0;
hubp->att.settings.bits.chunk_hdl_adjust = 3;
}
void hubp2_dmdata_set_attributes(
@ -1033,6 +1044,25 @@ void hubp2_cursor_set_position(
REG_SET(CURSOR_DST_OFFSET, 0,
CURSOR_DST_X_OFFSET, dst_x_offset);
/* TODO Handle surface pixel formats other than 4:4:4 */
/* Cursor Position Register Config */
hubp->pos.cur_ctl.bits.cur_enable = cur_en;
hubp->pos.position.bits.x_pos = pos->x;
hubp->pos.position.bits.y_pos = pos->y;
hubp->pos.hot_spot.bits.x_hot = x_hotspot;
hubp->pos.hot_spot.bits.y_hot = y_hotspot;
hubp->pos.dst_offset.bits.dst_x_offset = dst_x_offset;
/* Cursor Rectangle Cache
* Cursor bitmaps have different hotspot values
* There's a possibility that the above logic returns a negative value,
* so we clamp them to 0
*/
if (src_x_offset < 0)
src_x_offset = 0;
if (src_y_offset < 0)
src_y_offset = 0;
/* Save necessary cursor info x, y position. w, h is saved in attribute func. */
hubp->cur_rect.x = src_x_offset + param->viewport.x;
hubp->cur_rect.y = src_y_offset + param->viewport.y;
}
void hubp2_clk_cntl(struct hubp *hubp, bool enable)

View File

@ -1860,24 +1860,6 @@ void dcn20_post_unlock_program_front_end(
}
}
for (i = 0; i < dc->res_pool->pipe_count; i++) {
struct pipe_ctx *pipe = &context->res_ctx.pipe_ctx[i];
struct pipe_ctx *mpcc_pipe;
if (pipe->vtp_locked) {
dc->hwseq->funcs.wait_for_blank_complete(pipe->stream_res.opp);
pipe->plane_res.hubp->funcs->set_blank(pipe->plane_res.hubp, true);
pipe->vtp_locked = false;
for (mpcc_pipe = pipe->bottom_pipe; mpcc_pipe; mpcc_pipe = mpcc_pipe->bottom_pipe)
mpcc_pipe->plane_res.hubp->funcs->set_blank(mpcc_pipe->plane_res.hubp, true);
for (i = 0; i < dc->res_pool->pipe_count; i++)
if (context->res_ctx.pipe_ctx[i].update_flags.bits.disable)
dc->hwss.disable_plane(dc, &dc->current_state->res_ctx.pipe_ctx[i]);
}
}
for (i = 0; i < dc->res_pool->pipe_count; i++) {
struct pipe_ctx *pipe = &context->res_ctx.pipe_ctx[i];
struct pipe_ctx *old_pipe = &dc->current_state->res_ctx.pipe_ctx[i];
@ -2018,6 +2000,10 @@ void dcn20_optimize_bandwidth(
context->bw_ctx.bw.dcn.clk.dramclk_khz <= dc->clk_mgr->bw_params->dc_mode_softmax_memclk * 1000)
dc->clk_mgr->funcs->set_max_memclk(dc->clk_mgr, dc->clk_mgr->bw_params->dc_mode_softmax_memclk);
/* increase compbuf size */
if (hubbub->funcs->program_compbuf_size)
hubbub->funcs->program_compbuf_size(hubbub, context->bw_ctx.bw.dcn.compbuf_size_kb, true);
dc->clk_mgr->funcs->update_clocks(
dc->clk_mgr,
context,
@ -2033,9 +2019,6 @@ void dcn20_optimize_bandwidth(
pipe_ctx->dlg_regs.optimized_min_dst_y_next_start);
}
}
/* increase compbuf size */
if (hubbub->funcs->program_compbuf_size)
hubbub->funcs->program_compbuf_size(hubbub, context->bw_ctx.bw.dcn.compbuf_size_kb, true);
}
bool dcn20_update_bandwidth(

View File

@ -529,6 +529,7 @@ static struct timing_generator_funcs dcn20_tg_funcs = {
.enable_optc_clock = optc1_enable_optc_clock,
.set_drr = optc1_set_drr,
.get_last_used_drr_vtotal = optc2_get_last_used_drr_vtotal,
.set_vtotal_min_max = optc1_set_vtotal_min_max,
.set_static_screen_control = optc1_set_static_screen_control,
.program_stereo = optc1_program_stereo,
.is_stereo_left_eye = optc1_is_stereo_left_eye,

View File

@ -67,15 +67,9 @@ static uint32_t convert_and_clamp(
void dcn21_dchvm_init(struct hubbub *hubbub)
{
struct dcn20_hubbub *hubbub1 = TO_DCN20_HUBBUB(hubbub);
uint32_t riommu_active, prefetch_done;
uint32_t riommu_active;
int i;
REG_GET(DCHVM_RIOMMU_STAT0, HOSTVM_PREFETCH_DONE, &prefetch_done);
if (prefetch_done) {
hubbub->riommu_active = true;
return;
}
//Init DCHVM block
REG_UPDATE(DCHVM_CTRL0, HOSTVM_INIT_REQ, 1);

View File

@ -657,7 +657,6 @@ static const struct dc_debug_options debug_defaults_drv = {
.usbc_combo_phy_reset_wa = true,
.dmub_command_table = true,
.use_max_lb = true,
.optimize_edp_link_rate = true
};
static const struct dc_debug_options debug_defaults_diags = {
@ -677,6 +676,12 @@ static const struct dc_debug_options debug_defaults_diags = {
.use_max_lb = true
};
static const struct dc_panel_config panel_config_defaults = {
.ilr = {
.optimize_edp_link_rate = true,
},
};
enum dcn20_clk_src_array_id {
DCN20_CLK_SRC_PLL0,
DCN20_CLK_SRC_PLL1,
@ -1367,6 +1372,11 @@ static struct panel_cntl *dcn21_panel_cntl_create(const struct panel_cntl_init_d
return &panel_cntl->base;
}
static void dcn21_get_panel_config_defaults(struct dc_panel_config *panel_config)
{
*panel_config = panel_config_defaults;
}
#define CTX ctx
#define REG(reg_name) \
@ -1408,6 +1418,7 @@ static const struct resource_funcs dcn21_res_pool_funcs = {
.set_mcif_arb_params = dcn20_set_mcif_arb_params,
.find_first_free_match_stream_enc_for_link = dcn10_find_first_free_match_stream_enc_for_link,
.update_bw_bounding_box = dcn21_update_bw_bounding_box,
.get_panel_config_defaults = dcn21_get_panel_config_defaults,
};
static bool dcn21_resource_construct(

View File

@ -372,6 +372,10 @@ void dpp3_set_cursor_attributes(
REG_UPDATE(CURSOR0_COLOR1,
CUR0_COLOR1, 0xFFFFFFFF);
}
dpp_base->att.cur0_ctl.bits.expansion_mode = 0;
dpp_base->att.cur0_ctl.bits.cur0_rom_en = cur_rom_en;
dpp_base->att.cur0_ctl.bits.mode = color_format;
}

View File

@ -319,13 +319,13 @@ static struct timing_generator_funcs dcn30_tg_funcs = {
.enable_crtc_reset = optc1_enable_crtc_reset,
.disable_reset_trigger = optc1_disable_reset_trigger,
.lock = optc3_lock,
.is_locked = optc1_is_locked,
.unlock = optc1_unlock,
.lock_doublebuffer_enable = optc3_lock_doublebuffer_enable,
.lock_doublebuffer_disable = optc3_lock_doublebuffer_disable,
.enable_optc_clock = optc1_enable_optc_clock,
.set_drr = optc1_set_drr,
.get_last_used_drr_vtotal = optc2_get_last_used_drr_vtotal,
.set_vtotal_min_max = optc3_set_vtotal_min_max,
.set_static_screen_control = optc1_set_static_screen_control,
.program_stereo = optc1_program_stereo,
.is_stereo_left_eye = optc1_is_stereo_left_eye,
@ -366,4 +366,3 @@ void dcn30_timing_generator_init(struct optc *optc1)
optc1->min_h_sync_width = 4;
optc1->min_v_sync_width = 1;
}

View File

@ -1655,6 +1655,9 @@ noinline bool dcn30_internal_validate_bw(
if (!pipes)
return false;
context->bw_ctx.dml.vba.maxMpcComb = 0;
context->bw_ctx.dml.vba.VoltageLevel = 0;
context->bw_ctx.dml.vba.DRAMClockChangeSupport[0][0] = dm_dram_clock_change_vactive;
dc->res_pool->funcs->update_soc_for_wm_a(dc, context);
pipe_cnt = dc->res_pool->funcs->populate_dml_pipes(dc, context, pipes, fast_validate);
@ -1873,6 +1876,7 @@ noinline bool dcn30_internal_validate_bw(
if (repopulate_pipes)
pipe_cnt = dc->res_pool->funcs->populate_dml_pipes(dc, context, pipes, fast_validate);
context->bw_ctx.dml.vba.VoltageLevel = vlevel;
*vlevel_out = vlevel;
*pipe_cnt_out = pipe_cnt;

View File

@ -852,7 +852,7 @@ static struct hubbub *dcn301_hubbub_create(struct dc_context *ctx)
vmid->masks = &vmid_masks;
}
hubbub3->num_vmid = res_cap_dcn301.num_vmid;
hubbub3->num_vmid = res_cap_dcn301.num_vmid;
return &hubbub3->base;
}

View File

@ -197,7 +197,7 @@ static void dcn31_hpo_dp_stream_enc_set_stream_attribute(
uint32_t h_back_porch;
uint32_t h_width;
uint32_t v_height;
unsigned long long v_freq;
uint64_t v_freq;
uint8_t misc0 = 0;
uint8_t misc1 = 0;
uint8_t hsp;
@ -360,7 +360,7 @@ static void dcn31_hpo_dp_stream_enc_set_stream_attribute(
v_height = hw_crtc_timing.v_border_top + hw_crtc_timing.v_addressable + hw_crtc_timing.v_border_bottom;
hsp = hw_crtc_timing.flags.HSYNC_POSITIVE_POLARITY ? 0 : 0x80;
vsp = hw_crtc_timing.flags.VSYNC_POSITIVE_POLARITY ? 0 : 0x80;
v_freq = hw_crtc_timing.pix_clk_100hz * 100;
v_freq = (uint64_t)hw_crtc_timing.pix_clk_100hz * 100;
/* MSA Packet Mapping to 32-bit Link Symbols - DP2 spec, section 2.7.4.1
*
@ -436,32 +436,28 @@ static void dcn31_hpo_dp_stream_enc_update_dp_info_packets(
{
struct dcn31_hpo_dp_stream_encoder *enc3 = DCN3_1_HPO_DP_STREAM_ENC_FROM_HPO_STREAM_ENC(enc);
uint32_t dmdata_packet_enabled = 0;
bool sdp_stream_enable = false;
if (info_frame->vsc.valid) {
if (info_frame->vsc.valid)
enc->vpg->funcs->update_generic_info_packet(
enc->vpg,
0, /* packetIndex */
&info_frame->vsc,
true);
sdp_stream_enable = true;
}
if (info_frame->spd.valid) {
if (info_frame->spd.valid)
enc->vpg->funcs->update_generic_info_packet(
enc->vpg,
2, /* packetIndex */
&info_frame->spd,
true);
sdp_stream_enable = true;
}
if (info_frame->hdrsmd.valid) {
if (info_frame->hdrsmd.valid)
enc->vpg->funcs->update_generic_info_packet(
enc->vpg,
3, /* packetIndex */
&info_frame->hdrsmd,
true);
sdp_stream_enable = true;
}
/* enable/disable transmission of packet(s).
* If enabled, packet transmission begins on the next frame
*/

View File

@ -201,7 +201,6 @@ void optc31_set_drr(
// Setup manual flow control for EOF via TRIG_A
optc->funcs->setup_manual_trigger(optc);
} else {
REG_UPDATE_4(OTG_V_TOTAL_CONTROL,
OTG_SET_V_TOTAL_MIN_MASK, 0,
@ -260,7 +259,6 @@ static struct timing_generator_funcs dcn31_tg_funcs = {
.enable_crtc_reset = optc1_enable_crtc_reset,
.disable_reset_trigger = optc1_disable_reset_trigger,
.lock = optc3_lock,
.is_locked = optc1_is_locked,
.unlock = optc1_unlock,
.lock_doublebuffer_enable = optc3_lock_doublebuffer_enable,
.lock_doublebuffer_disable = optc3_lock_doublebuffer_disable,

View File

@ -888,9 +888,8 @@ static const struct dc_debug_options debug_defaults_drv = {
}
},
.disable_z10 = true,
.optimize_edp_link_rate = true,
.enable_z9_disable_interface = true, /* Allow support for the PMFW interface for disable Z9*/
.dml_hostvm_override = DML_HOSTVM_NO_OVERRIDE,
.dml_hostvm_override = DML_HOSTVM_OVERRIDE_FALSE,
};
static const struct dc_debug_options debug_defaults_diags = {
@ -911,6 +910,12 @@ static const struct dc_debug_options debug_defaults_diags = {
.use_max_lb = true
};
static const struct dc_panel_config panel_config_defaults = {
.ilr = {
.optimize_edp_link_rate = true,
},
};
static void dcn31_dpp_destroy(struct dpp **dpp)
{
kfree(TO_DCN20_DPP(*dpp));
@ -1803,6 +1808,11 @@ validate_out:
return out;
}
static void dcn31_get_panel_config_defaults(struct dc_panel_config *panel_config)
{
*panel_config = panel_config_defaults;
}
static struct dc_cap_funcs cap_funcs = {
.get_dcc_compression_cap = dcn20_get_dcc_compression_cap
};
@ -1829,6 +1839,7 @@ static struct resource_funcs dcn31_res_pool_funcs = {
.release_post_bldn_3dlut = dcn30_release_post_bldn_3dlut,
.update_bw_bounding_box = dcn31_update_bw_bounding_box,
.patch_unknown_plane_state = dcn20_patch_unknown_plane_state,
.get_panel_config_defaults = dcn31_get_panel_config_defaults,
};
static struct clock_source *dcn30_clock_source_create(

View File

@ -262,7 +262,7 @@ static bool is_two_pixels_per_containter(const struct dc_crtc_timing *timing)
return two_pix;
}
void enc314_stream_encoder_dp_blank(
static void enc314_stream_encoder_dp_blank(
struct dc_link *link,
struct stream_encoder *enc)
{

View File

@ -881,7 +881,8 @@ static const struct dc_plane_cap plane_cap = {
};
static const struct dc_debug_options debug_defaults_drv = {
.disable_z10 = true, /*hw not support it*/
.disable_z10 = false,
.enable_z9_disable_interface = true,
.disable_dmcu = true,
.force_abm_enable = false,
.timing_trace = false,
@ -914,7 +915,6 @@ static const struct dc_debug_options debug_defaults_drv = {
.afmt = true,
}
},
.optimize_edp_link_rate = true,
.seamless_boot_odm_combine = true
};
@ -936,6 +936,12 @@ static const struct dc_debug_options debug_defaults_diags = {
.use_max_lb = true
};
static const struct dc_panel_config panel_config_defaults = {
.ilr = {
.optimize_edp_link_rate = true,
},
};
static void dcn31_dpp_destroy(struct dpp **dpp)
{
kfree(TO_DCN20_DPP(*dpp));
@ -1675,6 +1681,11 @@ static void dcn314_update_bw_bounding_box(struct dc *dc, struct clk_bw_params *b
DC_FP_END();
}
static void dcn314_get_panel_config_defaults(struct dc_panel_config *panel_config)
{
*panel_config = panel_config_defaults;
}
static struct resource_funcs dcn314_res_pool_funcs = {
.destroy = dcn314_destroy_resource_pool,
.link_enc_create = dcn31_link_encoder_create,
@ -1697,6 +1708,7 @@ static struct resource_funcs dcn314_res_pool_funcs = {
.release_post_bldn_3dlut = dcn30_release_post_bldn_3dlut,
.update_bw_bounding_box = dcn314_update_bw_bounding_box,
.patch_unknown_plane_state = dcn20_patch_unknown_plane_state,
.get_panel_config_defaults = dcn314_get_panel_config_defaults,
};
static struct clock_source *dcn30_clock_source_create(

View File

@ -885,7 +885,6 @@ static const struct dc_debug_options debug_defaults_drv = {
.afmt = true,
}
},
.optimize_edp_link_rate = true,
.psr_power_use_phy_fsm = 0,
};
@ -907,6 +906,12 @@ static const struct dc_debug_options debug_defaults_diags = {
.use_max_lb = true
};
static const struct dc_panel_config panel_config_defaults = {
.ilr = {
.optimize_edp_link_rate = true,
},
};
static void dcn31_dpp_destroy(struct dpp **dpp)
{
kfree(TO_DCN20_DPP(*dpp));
@ -1708,6 +1713,11 @@ static int dcn315_populate_dml_pipes_from_context(
return pipe_cnt;
}
static void dcn315_get_panel_config_defaults(struct dc_panel_config *panel_config)
{
*panel_config = panel_config_defaults;
}
static struct dc_cap_funcs cap_funcs = {
.get_dcc_compression_cap = dcn20_get_dcc_compression_cap
};
@ -1721,7 +1731,7 @@ static struct resource_funcs dcn315_res_pool_funcs = {
.panel_cntl_create = dcn31_panel_cntl_create,
.validate_bandwidth = dcn31_validate_bandwidth,
.calculate_wm_and_dlg = dcn31_calculate_wm_and_dlg,
.update_soc_for_wm_a = dcn31_update_soc_for_wm_a,
.update_soc_for_wm_a = dcn315_update_soc_for_wm_a,
.populate_dml_pipes = dcn315_populate_dml_pipes_from_context,
.acquire_idle_pipe_for_layer = dcn20_acquire_idle_pipe_for_layer,
.add_stream_to_ctx = dcn30_add_stream_to_ctx,
@ -1734,6 +1744,7 @@ static struct resource_funcs dcn315_res_pool_funcs = {
.release_post_bldn_3dlut = dcn30_release_post_bldn_3dlut,
.update_bw_bounding_box = dcn315_update_bw_bounding_box,
.patch_unknown_plane_state = dcn20_patch_unknown_plane_state,
.get_panel_config_defaults = dcn315_get_panel_config_defaults,
};
static bool dcn315_resource_construct(

View File

@ -885,7 +885,6 @@ static const struct dc_debug_options debug_defaults_drv = {
.afmt = true,
}
},
.optimize_edp_link_rate = true,
};
static const struct dc_debug_options debug_defaults_diags = {
@ -906,6 +905,12 @@ static const struct dc_debug_options debug_defaults_diags = {
.use_max_lb = true
};
static const struct dc_panel_config panel_config_defaults = {
.ilr = {
.optimize_edp_link_rate = true,
},
};
static void dcn31_dpp_destroy(struct dpp **dpp)
{
kfree(TO_DCN20_DPP(*dpp));
@ -1710,6 +1715,11 @@ static int dcn316_populate_dml_pipes_from_context(
return pipe_cnt;
}
static void dcn316_get_panel_config_defaults(struct dc_panel_config *panel_config)
{
*panel_config = panel_config_defaults;
}
static struct dc_cap_funcs cap_funcs = {
.get_dcc_compression_cap = dcn20_get_dcc_compression_cap
};
@ -1736,6 +1746,7 @@ static struct resource_funcs dcn316_res_pool_funcs = {
.release_post_bldn_3dlut = dcn30_release_post_bldn_3dlut,
.update_bw_bounding_box = dcn316_update_bw_bounding_box,
.patch_unknown_plane_state = dcn20_patch_unknown_plane_state,
.get_panel_config_defaults = dcn316_get_panel_config_defaults,
};
static bool dcn316_resource_construct(

View File

@ -150,12 +150,6 @@ static void dcn32_link_encoder_get_max_link_cap(struct link_encoder *enc,
}
void enc32_set_dig_output_mode(struct link_encoder *enc, uint8_t pix_per_container)
{
struct dcn10_link_encoder *enc10 = TO_DCN10_LINK_ENC(enc);
REG_UPDATE(DIG_FIFO_CTRL0, DIG_FIFO_OUTPUT_PIXEL_MODE, pix_per_container);
}
static const struct link_encoder_funcs dcn32_link_enc_funcs = {
.read_state = link_enc2_read_state,
.validate_output_with_stream =
@ -186,7 +180,6 @@ static const struct link_encoder_funcs dcn32_link_enc_funcs = {
.is_in_alt_mode = dcn32_link_encoder_is_in_alt_mode,
.get_max_link_cap = dcn32_link_encoder_get_max_link_cap,
.set_dio_phy_mux = dcn31_link_encoder_set_dio_phy_mux,
.set_dig_output_mode = enc32_set_dig_output_mode,
};
void dcn32_link_encoder_construct(

View File

@ -53,8 +53,4 @@ void dcn32_link_encoder_enable_dp_output(
const struct dc_link_settings *link_settings,
enum clock_source_id clock_source);
void enc32_set_dig_output_mode(
struct link_encoder *enc,
uint8_t pix_per_container);
#endif /* __DC_LINK_ENCODER__DCN32_H__ */

View File

@ -243,6 +243,39 @@ static bool is_two_pixels_per_containter(const struct dc_crtc_timing *timing)
return two_pix;
}
static bool is_h_timing_divisible_by_2(const struct dc_crtc_timing *timing)
{
/* math borrowed from function of same name in inc/resource
* checks if h_timing is divisible by 2
*/
bool divisible = false;
uint16_t h_blank_start = 0;
uint16_t h_blank_end = 0;
if (timing) {
h_blank_start = timing->h_total - timing->h_front_porch;
h_blank_end = h_blank_start - timing->h_addressable;
/* HTOTAL, Hblank start/end, and Hsync start/end all must be
* divisible by 2 in order for the horizontal timing params
* to be considered divisible by 2. Hsync start is always 0.
*/
divisible = (timing->h_total % 2 == 0) &&
(h_blank_start % 2 == 0) &&
(h_blank_end % 2 == 0) &&
(timing->h_sync_width % 2 == 0);
}
return divisible;
}
static bool is_dp_dig_pixel_rate_div_policy(struct dc *dc, const struct dc_crtc_timing *timing)
{
/* should be functionally the same as dcn32_is_dp_dig_pixel_rate_div_policy for DP encoders*/
return is_h_timing_divisible_by_2(timing) &&
dc->debug.enable_dp_dig_pixel_rate_div_policy;
}
static void enc32_stream_encoder_dp_unblank(
struct dc_link *link,
struct stream_encoder *enc,
@ -259,7 +292,7 @@ static void enc32_stream_encoder_dp_unblank(
/* YCbCr 4:2:0 : Computed VID_M will be 2X the input rate */
if (is_two_pixels_per_containter(&param->timing) || param->opp_cnt > 1
|| dc->debug.enable_dp_dig_pixel_rate_div_policy) {
|| is_dp_dig_pixel_rate_div_policy(dc, &param->timing)) {
/*this logic should be the same in get_pixel_clock_parameters() */
n_multiply = 1;
}
@ -355,7 +388,7 @@ static void enc32_dp_set_dsc_config(struct stream_encoder *enc,
{
struct dcn10_stream_encoder *enc1 = DCN10STRENC_FROM_STRENC(enc);
REG_UPDATE(DP_DSC_CNTL, DP_DSC_MODE, dsc_mode);
REG_UPDATE(DP_DSC_CNTL, DP_DSC_MODE, dsc_mode == OPTC_DSC_DISABLED ? 0 : 1);
}
/* this function read dsc related register fields to be logged later in dcn10_log_hw_state
@ -378,24 +411,6 @@ static void enc32_read_state(struct stream_encoder *enc, struct enc_state *s)
}
}
static void enc32_stream_encoder_reset_fifo(struct stream_encoder *enc)
{
struct dcn10_stream_encoder *enc1 = DCN10STRENC_FROM_STRENC(enc);
uint32_t fifo_enabled;
REG_GET(DIG_FIFO_CTRL0, DIG_FIFO_ENABLE, &fifo_enabled);
if (fifo_enabled == 0) {
/* reset DIG resync FIFO */
REG_UPDATE(DIG_FIFO_CTRL0, DIG_FIFO_RESET, 1);
/* TODO: fix timeout when wait for DIG_FIFO_RESET_DONE */
//REG_WAIT(DIG_FIFO_CTRL0, DIG_FIFO_RESET_DONE, 1, 1, 100);
udelay(1);
REG_UPDATE(DIG_FIFO_CTRL0, DIG_FIFO_RESET, 0);
REG_WAIT(DIG_FIFO_CTRL0, DIG_FIFO_RESET_DONE, 0, 1, 100);
}
}
static void enc32_set_dig_input_mode(struct stream_encoder *enc, unsigned int pix_per_container)
{
struct dcn10_stream_encoder *enc1 = DCN10STRENC_FROM_STRENC(enc);
@ -425,8 +440,6 @@ static const struct stream_encoder_funcs dcn32_str_enc_funcs = {
enc3_stream_encoder_update_dp_info_packets,
.stop_dp_info_packets =
enc1_stream_encoder_stop_dp_info_packets,
.reset_fifo =
enc32_stream_encoder_reset_fifo,
.dp_blank =
enc1_stream_encoder_dp_blank,
.dp_unblank =

View File

@ -71,7 +71,9 @@
SRI(DP_MSE_RATE_UPDATE, DP, id), \
SRI(DP_PIXEL_FORMAT, DP, id), \
SRI(DP_SEC_CNTL, DP, id), \
SRI(DP_SEC_CNTL1, DP, id), \
SRI(DP_SEC_CNTL2, DP, id), \
SRI(DP_SEC_CNTL5, DP, id), \
SRI(DP_SEC_CNTL6, DP, id), \
SRI(DP_STEER_FIFO, DP, id), \
SRI(DP_VID_M, DP, id), \
@ -93,7 +95,7 @@
SRI(DIG_FIFO_CTRL0, DIG, id)
#define SE_COMMON_MASK_SH_LIST_DCN32_BASE(mask_sh)\
#define SE_COMMON_MASK_SH_LIST_DCN32(mask_sh)\
SE_SF(DP0_DP_PIXEL_FORMAT, DP_PIXEL_ENCODING, mask_sh),\
SE_SF(DP0_DP_PIXEL_FORMAT, DP_COMPONENT_DEPTH, mask_sh),\
SE_SF(DP0_DP_PIXEL_FORMAT, DP_PIXEL_PER_CYCLE_PROCESSING_MODE, mask_sh),\
@ -106,6 +108,7 @@
SE_SF(DIG0_HDMI_VBI_PACKET_CONTROL, HDMI_GC_CONT, mask_sh),\
SE_SF(DIG0_HDMI_VBI_PACKET_CONTROL, HDMI_GC_SEND, mask_sh),\
SE_SF(DIG0_HDMI_VBI_PACKET_CONTROL, HDMI_NULL_SEND, mask_sh),\
SE_SF(DIG0_HDMI_VBI_PACKET_CONTROL, HDMI_ACP_SEND, mask_sh),\
SE_SF(DIG0_HDMI_INFOFRAME_CONTROL0, HDMI_AUDIO_INFO_SEND, mask_sh),\
SE_SF(DIG0_HDMI_INFOFRAME_CONTROL1, HDMI_AUDIO_INFO_LINE, mask_sh),\
SE_SF(DIG0_HDMI_GC, HDMI_GC_AVMUTE, mask_sh),\
@ -244,15 +247,6 @@
SE_SF(DIG0_DIG_FIFO_CTRL0, DIG_FIFO_RESET_DONE, mask_sh),\
SE_SF(DIG0_DIG_FIFO_CTRL0, DIG_FIFO_OUTPUT_PIXEL_MODE, mask_sh)
#if defined(CONFIG_DRM_AMD_DC_HDCP)
#define SE_COMMON_MASK_SH_LIST_DCN32(mask_sh)\
SE_COMMON_MASK_SH_LIST_DCN32_BASE(mask_sh),\
SE_SF(DIG0_HDMI_VBI_PACKET_CONTROL, HDMI_ACP_SEND, mask_sh)
#else
#define SE_COMMON_MASK_SH_LIST_DCN32(mask_sh)\
SE_COMMON_MASK_SH_LIST_DCN32_BASE(mask_sh)
#endif
void dcn32_dio_stream_encoder_construct(
struct dcn10_stream_encoder *enc1,
struct dc_context *ctx,

View File

@ -47,6 +47,7 @@
SE_SF(DP_DPHY_SYM320_DP_DPHY_SYM32_TP_CONFIG, TP_PRBS_SEL1, mask_sh),\
SE_SF(DP_DPHY_SYM320_DP_DPHY_SYM32_TP_CONFIG, TP_PRBS_SEL2, mask_sh),\
SE_SF(DP_DPHY_SYM320_DP_DPHY_SYM32_TP_CONFIG, TP_PRBS_SEL3, mask_sh),\
SE_SF(DP_DPHY_SYM320_DP_DPHY_SYM32_TP_SQ_PULSE, TP_SQ_PULSE_WIDTH, mask_sh),\
SE_SF(DP_DPHY_SYM320_DP_DPHY_SYM32_SAT_VC0, SAT_STREAM_SOURCE, mask_sh),\
SE_SF(DP_DPHY_SYM320_DP_DPHY_SYM32_SAT_VC0, SAT_SLOT_COUNT, mask_sh),\
SE_SF(DP_DPHY_SYM320_DP_DPHY_SYM32_VC_RATE_CNTL0, STREAM_VC_RATE_X, mask_sh),\

View File

@ -936,6 +936,7 @@ static const struct hubbub_funcs hubbub32_funcs = {
.program_watermarks = hubbub32_program_watermarks,
.allow_self_refresh_control = hubbub1_allow_self_refresh_control,
.is_allow_self_refresh_enabled = hubbub1_is_allow_self_refresh_enabled,
.verify_allow_pstate_change_high = hubbub1_verify_allow_pstate_change_high,
.force_wm_propagate_to_pipes = hubbub32_force_wm_propagate_to_pipes,
.force_pstate_change_control = hubbub3_force_pstate_change_control,
.init_watermarks = hubbub32_init_watermarks,

View File

@ -79,6 +79,8 @@ void hubp32_phantom_hubp_post_enable(struct hubp *hubp)
uint32_t reg_val;
struct dcn20_hubp *hubp2 = TO_DCN20_HUBP(hubp);
/* For phantom pipe enable, disable GSL */
REG_UPDATE(DCSURF_FLIP_CONTROL2, SURFACE_GSL_ENABLE, 0);
REG_UPDATE(DCHUBP_CNTL, HUBP_BLANK_EN, 1);
reg_val = REG_READ(DCHUBP_CNTL);
if (reg_val) {
@ -179,12 +181,12 @@ static struct hubp_funcs dcn32_hubp_funcs = {
.hubp_init = hubp3_init,
.set_unbounded_requesting = hubp31_set_unbounded_requesting,
.hubp_soft_reset = hubp31_soft_reset,
.hubp_set_flip_int = hubp1_set_flip_int,
.hubp_in_blank = hubp1_in_blank,
.hubp_update_force_pstate_disallow = hubp32_update_force_pstate_disallow,
.phantom_hubp_post_enable = hubp32_phantom_hubp_post_enable,
.hubp_update_mall_sel = hubp32_update_mall_sel,
.hubp_prepare_subvp_buffering = hubp32_prepare_subvp_buffering,
.hubp_set_flip_int = hubp1_set_flip_int
.hubp_prepare_subvp_buffering = hubp32_prepare_subvp_buffering
};
bool hubp32_construct(

View File

@ -206,8 +206,7 @@ static bool dcn32_check_no_memory_request_for_cab(struct dc *dc)
*/
static uint32_t dcn32_calculate_cab_allocation(struct dc *dc, struct dc_state *ctx)
{
uint8_t i;
int j;
int i, j;
struct dc_stream_state *stream = NULL;
struct dc_plane_state *plane = NULL;
uint32_t cursor_size = 0;
@ -630,10 +629,9 @@ bool dcn32_set_input_transfer_func(struct dc *dc,
params = &dpp_base->degamma_params;
}
result = dpp_base->funcs->dpp_program_gamcor_lut(dpp_base, params);
dpp_base->funcs->dpp_program_gamcor_lut(dpp_base, params);
if (result &&
pipe_ctx->stream_res.opp &&
if (pipe_ctx->stream_res.opp &&
pipe_ctx->stream_res.opp->ctx &&
hws->funcs.set_mcm_luts)
result = hws->funcs.set_mcm_luts(pipe_ctx, plane_state);
@ -991,6 +989,10 @@ void dcn32_init_hw(struct dc *dc)
dc_dmub_srv_query_caps_cmd(dc->ctx->dmub_srv->dmub);
dc->caps.dmub_caps.psr = dc->ctx->dmub_srv->dmub->feature_caps.psr;
}
/* Enable support for ODM and windowed MPO if policy flag is set */
if (dc->debug.enable_single_display_2to1_odm_policy)
dc->config.enable_windowed_mpo_odm = true;
}
static int calc_mpc_flow_ctrl_cnt(const struct dc_stream_state *stream,
@ -1145,23 +1147,25 @@ void dcn32_update_odm(struct dc *dc, struct dc_state *context, struct pipe_ctx *
true);
}
// Don't program pixel clock after link is already enabled
/* if (false == pipe_ctx->clock_source->funcs->program_pix_clk(
pipe_ctx->clock_source,
&pipe_ctx->stream_res.pix_clk_params,
&pipe_ctx->pll_settings)) {
BREAK_TO_DEBUGGER();
}*/
if (pipe_ctx->stream_res.dsc) {
struct pipe_ctx *current_pipe_ctx = &dc->current_state->res_ctx.pipe_ctx[pipe_ctx->pipe_idx];
if (pipe_ctx->stream_res.dsc)
update_dsc_on_stream(pipe_ctx, pipe_ctx->stream->timing.flags.DSC);
/* Check if no longer using pipe for ODM, then need to disconnect DSC for that pipe */
if (!pipe_ctx->next_odm_pipe && current_pipe_ctx->next_odm_pipe &&
current_pipe_ctx->next_odm_pipe->stream_res.dsc) {
struct display_stream_compressor *dsc = current_pipe_ctx->next_odm_pipe->stream_res.dsc;
/* disconnect DSC block from stream */
dsc->funcs->dsc_disconnect(dsc);
}
}
}
unsigned int dcn32_calculate_dccg_k1_k2_values(struct pipe_ctx *pipe_ctx, unsigned int *k1_div, unsigned int *k2_div)
{
struct dc_stream_state *stream = pipe_ctx->stream;
unsigned int odm_combine_factor = 0;
struct dc *dc = pipe_ctx->stream->ctx->dc;
bool two_pix_per_container = false;
// For phantom pipes, use the same programming as the main pipes
@ -1189,7 +1193,7 @@ unsigned int dcn32_calculate_dccg_k1_k2_values(struct pipe_ctx *pipe_ctx, unsign
} else {
*k1_div = PIXEL_RATE_DIV_BY_1;
*k2_div = PIXEL_RATE_DIV_BY_4;
if ((odm_combine_factor == 2) || dc->debug.enable_dp_dig_pixel_rate_div_policy)
if ((odm_combine_factor == 2) || dcn32_is_dp_dig_pixel_rate_div_policy(pipe_ctx))
*k2_div = PIXEL_RATE_DIV_BY_2;
}
}
@ -1226,7 +1230,6 @@ void dcn32_unblank_stream(struct pipe_ctx *pipe_ctx,
struct dc_link *link = stream->link;
struct dce_hwseq *hws = link->dc->hwseq;
struct pipe_ctx *odm_pipe;
struct dc *dc = pipe_ctx->stream->ctx->dc;
uint32_t pix_per_cycle = 1;
params.opp_cnt = 1;
@ -1245,7 +1248,7 @@ void dcn32_unblank_stream(struct pipe_ctx *pipe_ctx,
pipe_ctx->stream_res.tg->inst);
} else if (dc_is_dp_signal(pipe_ctx->stream->signal)) {
if (optc2_is_two_pixels_per_containter(&stream->timing) || params.opp_cnt > 1
|| dc->debug.enable_dp_dig_pixel_rate_div_policy) {
|| dcn32_is_dp_dig_pixel_rate_div_policy(pipe_ctx)) {
params.timing.pix_clk_100hz /= 2;
pix_per_cycle = 2;
}
@ -1262,6 +1265,9 @@ bool dcn32_is_dp_dig_pixel_rate_div_policy(struct pipe_ctx *pipe_ctx)
{
struct dc *dc = pipe_ctx->stream->ctx->dc;
if (!is_h_timing_divisible_by_2(pipe_ctx->stream))
return false;
if (dc_is_dp_signal(pipe_ctx->stream->signal) && !is_dp_128b_132b_signal(pipe_ctx) &&
dc->debug.enable_dp_dig_pixel_rate_div_policy)
return true;
@ -1394,7 +1400,7 @@ bool dcn32_dsc_pg_status(
break;
}
return pwr_status == 0 ? true : false;
return pwr_status == 0;
}
void dcn32_update_dsc_pg(struct dc *dc,

View File

@ -151,7 +151,7 @@ static bool optc32_disable_crtc(struct timing_generator *optc)
/* CRTC disabled, so disable clock. */
REG_WAIT(OTG_CLOCK_CONTROL,
OTG_BUSY, 0,
1, 100000);
1, 150000);
return true;
}

View File

@ -1680,6 +1680,8 @@ static void dcn32_enable_phantom_plane(struct dc *dc,
phantom_plane->clip_rect.y = 0;
phantom_plane->clip_rect.height = phantom_stream->timing.v_addressable;
phantom_plane->is_phantom = true;
dc_add_plane_to_context(dc, phantom_stream, phantom_plane, context);
curr_pipe = curr_pipe->bottom_pipe;
@ -1749,6 +1751,10 @@ bool dcn32_remove_phantom_pipes(struct dc *dc, struct dc_state *context)
pipe->stream->mall_stream_config.type = SUBVP_NONE;
pipe->stream->mall_stream_config.paired_stream = NULL;
}
if (pipe->plane_state) {
pipe->plane_state->is_phantom = false;
}
}
return removed_pipe;
}
@ -1798,14 +1804,39 @@ bool dcn32_validate_bandwidth(struct dc *dc,
int vlevel = 0;
int pipe_cnt = 0;
display_e2e_pipe_params_st *pipes = kzalloc(dc->res_pool->pipe_count * sizeof(display_e2e_pipe_params_st), GFP_KERNEL);
struct mall_temp_config mall_temp_config;
/* To handle Freesync properly, setting FreeSync DML parameters
* to its default state for the first stage of validation
*/
context->bw_ctx.bw.dcn.clk.fw_based_mclk_switching = false;
context->bw_ctx.dml.soc.dram_clock_change_requirement_final = true;
DC_LOGGER_INIT(dc->ctx->logger);
/* For fast validation, there are situations where a shallow copy of
* of the dc->current_state is created for the validation. In this case
* we want to save and restore the mall config because we always
* teardown subvp at the beginning of validation (and don't attempt
* to add it back if it's fast validation). If we don't restore the
* subvp config in cases of fast validation + shallow copy of the
* dc->current_state, the dc->current_state will have a partially
* removed subvp state when we did not intend to remove it.
*/
if (fast_validate) {
memset(&mall_temp_config, 0, sizeof(mall_temp_config));
dcn32_save_mall_state(dc, context, &mall_temp_config);
}
BW_VAL_TRACE_COUNT();
DC_FP_START();
out = dcn32_internal_validate_bw(dc, context, pipes, &pipe_cnt, &vlevel, fast_validate);
DC_FP_END();
if (fast_validate)
dcn32_restore_mall_state(dc, context, &mall_temp_config);
if (pipe_cnt == 0)
goto validate_out;

View File

@ -45,6 +45,17 @@
extern struct _vcs_dpi_ip_params_st dcn3_2_ip;
extern struct _vcs_dpi_soc_bounding_box_st dcn3_2_soc;
/* Temp struct used to save and restore MALL config
* during validation.
*
* TODO: Move MALL config into dc_state instead of stream struct
* to avoid needing to save/restore.
*/
struct mall_temp_config {
struct mall_stream_config mall_stream_config[MAX_PIPES];
bool is_phantom_plane[MAX_PIPES];
};
struct dcn32_resource_pool {
struct resource_pool base;
};
@ -108,6 +119,8 @@ bool dcn32_subvp_in_use(struct dc *dc,
bool dcn32_mpo_in_use(struct dc_state *context);
bool dcn32_any_surfaces_rotated(struct dc *dc, struct dc_state *context);
struct pipe_ctx *dcn32_acquire_idle_pipe_for_head_pipe_in_layer(
struct dc_state *state,
const struct resource_pool *pool,
@ -120,6 +133,15 @@ void dcn32_determine_det_override(struct dc *dc,
void dcn32_set_det_allocations(struct dc *dc, struct dc_state *context,
display_e2e_pipe_params_st *pipes);
void dcn32_save_mall_state(struct dc *dc,
struct dc_state *context,
struct mall_temp_config *temp_config);
void dcn32_restore_mall_state(struct dc *dc,
struct dc_state *context,
struct mall_temp_config *temp_config);
/* definitions for run time init of reg offsets */
/* CLK SRC */

View File

@ -233,6 +233,23 @@ bool dcn32_mpo_in_use(struct dc_state *context)
return false;
}
bool dcn32_any_surfaces_rotated(struct dc *dc, struct dc_state *context)
{
uint32_t i;
for (i = 0; i < dc->res_pool->pipe_count; i++) {
struct pipe_ctx *pipe = &context->res_ctx.pipe_ctx[i];
if (!pipe->stream)
continue;
if (pipe->plane_state && pipe->plane_state->rotation != ROTATION_ANGLE_0)
return true;
}
return false;
}
/**
* *******************************************************************************************
* dcn32_determine_det_override: Determine DET allocation for each pipe
@ -363,3 +380,74 @@ void dcn32_set_det_allocations(struct dc *dc, struct dc_state *context,
} else
dcn32_determine_det_override(dc, context, pipes);
}
/**
* *******************************************************************************************
* dcn32_save_mall_state: Save MALL (SubVP) state for fast validation cases
*
* This function saves the MALL (SubVP) case for fast validation cases. For fast validation,
* there are situations where a shallow copy of the dc->current_state is created for the
* validation. In this case we want to save and restore the mall config because we always
* teardown subvp at the beginning of validation (and don't attempt to add it back if it's
* fast validation). If we don't restore the subvp config in cases of fast validation +
* shallow copy of the dc->current_state, the dc->current_state will have a partially
* removed subvp state when we did not intend to remove it.
*
* NOTE: This function ONLY works if the streams are not moved to a different pipe in the
* validation. We don't expect this to happen in fast_validation=1 cases.
*
* @param [in]: dc: Current DC state
* @param [in]: context: New DC state to be programmed
* @param [out]: temp_config: struct used to cache the existing MALL state
*
* @return: void
*
* *******************************************************************************************
*/
void dcn32_save_mall_state(struct dc *dc,
struct dc_state *context,
struct mall_temp_config *temp_config)
{
uint32_t i;
for (i = 0; i < dc->res_pool->pipe_count; i++) {
struct pipe_ctx *pipe = &context->res_ctx.pipe_ctx[i];
if (pipe->stream)
temp_config->mall_stream_config[i] = pipe->stream->mall_stream_config;
if (pipe->plane_state)
temp_config->is_phantom_plane[i] = pipe->plane_state->is_phantom;
}
}
/**
* *******************************************************************************************
* dcn32_restore_mall_state: Restore MALL (SubVP) state for fast validation cases
*
* Restore the MALL state based on the previously saved state from dcn32_save_mall_state
*
* @param [in]: dc: Current DC state
* @param [in/out]: context: New DC state to be programmed, restore MALL state into here
* @param [in]: temp_config: struct that has the cached MALL state
*
* @return: void
*
* *******************************************************************************************
*/
void dcn32_restore_mall_state(struct dc *dc,
struct dc_state *context,
struct mall_temp_config *temp_config)
{
uint32_t i;
for (i = 0; i < dc->res_pool->pipe_count; i++) {
struct pipe_ctx *pipe = &context->res_ctx.pipe_ctx[i];
if (pipe->stream)
pipe->stream->mall_stream_config = temp_config->mall_stream_config[i];
if (pipe->plane_state)
pipe->plane_state->is_phantom = temp_config->is_phantom_plane[i];
}
}

View File

@ -91,7 +91,6 @@ static const struct link_encoder_funcs dcn321_link_enc_funcs = {
.is_in_alt_mode = dcn20_link_encoder_is_in_alt_mode,
.get_max_link_cap = dcn20_link_encoder_get_max_link_cap,
.set_dio_phy_mux = dcn31_link_encoder_set_dio_phy_mux,
.set_dig_output_mode = enc32_set_dig_output_mode,
};
void dcn321_link_encoder_construct(

View File

@ -94,8 +94,6 @@
#include "dcn20/dcn20_vmid.h"
#define DC_LOGGER_INIT(logger)
#define fixed16_to_double(x) (((double)x) / ((double) (1 << 16)))
#define fixed16_to_double_to_cpu(x) fixed16_to_double(le32_to_cpu(x))
enum dcn321_clk_src_array_id {
DCN321_CLK_SRC_PLL0,
@ -1606,7 +1604,7 @@ static struct resource_funcs dcn321_res_pool_funcs = {
.validate_bandwidth = dcn32_validate_bandwidth,
.calculate_wm_and_dlg = dcn32_calculate_wm_and_dlg,
.populate_dml_pipes = dcn32_populate_dml_pipes_from_context,
.acquire_idle_pipe_for_layer = dcn20_acquire_idle_pipe_for_layer,
.acquire_idle_pipe_for_head_pipe_in_layer = dcn32_acquire_idle_pipe_for_head_pipe_in_layer,
.add_stream_to_ctx = dcn30_add_stream_to_ctx,
.add_dsc_to_stream_resource = dcn20_add_dsc_to_stream_resource,
.remove_stream_from_ctx = dcn20_remove_stream_from_ctx,
@ -1656,7 +1654,7 @@ static bool dcn321_resource_construct(
#undef REG_STRUCT
#define REG_STRUCT dccg_regs
dccg_regs_init();
dccg_regs_init();
ctx->dc_bios->regs = &bios_regs;

View File

@ -1444,81 +1444,67 @@ unsigned int dcn_find_dcfclk_suits_all(
return dcf_clk;
}
static bool verify_clock_values(struct dm_pp_clock_levels_with_voltage *clks)
void dcn_bw_update_from_pplib_fclks(
struct dc *dc,
struct dm_pp_clock_levels_with_voltage *fclks)
{
int i;
if (clks->num_levels == 0)
return false;
for (i = 0; i < clks->num_levels; i++)
/* Ensure that the result is sane */
if (clks->data[i].clocks_in_khz == 0)
return false;
return true;
}
void dcn_bw_update_from_pplib(struct dc *dc)
{
struct dc_context *ctx = dc->ctx;
struct dm_pp_clock_levels_with_voltage fclks = {0}, dcfclks = {0};
bool res;
unsigned vmin0p65_idx, vmid0p72_idx, vnom0p8_idx, vmax0p9_idx;
/* TODO: This is not the proper way to obtain fabric_and_dram_bandwidth, should be min(fclk, memclk) */
res = dm_pp_get_clock_levels_by_type_with_voltage(
ctx, DM_PP_CLOCK_TYPE_FCLK, &fclks);
ASSERT(fclks->num_levels);
if (res)
res = verify_clock_values(&fclks);
vmin0p65_idx = 0;
vmid0p72_idx = fclks->num_levels -
(fclks->num_levels > 2 ? 3 : (fclks->num_levels > 1 ? 2 : 1));
vnom0p8_idx = fclks->num_levels - (fclks->num_levels > 1 ? 2 : 1);
vmax0p9_idx = fclks->num_levels - 1;
if (res) {
ASSERT(fclks.num_levels);
vmin0p65_idx = 0;
vmid0p72_idx = fclks.num_levels -
(fclks.num_levels > 2 ? 3 : (fclks.num_levels > 1 ? 2 : 1));
vnom0p8_idx = fclks.num_levels - (fclks.num_levels > 1 ? 2 : 1);
vmax0p9_idx = fclks.num_levels - 1;
dc->dcn_soc->fabric_and_dram_bandwidth_vmin0p65 =
32 * (fclks.data[vmin0p65_idx].clocks_in_khz / 1000.0) / 1000.0;
dc->dcn_soc->fabric_and_dram_bandwidth_vmid0p72 =
dc->dcn_soc->number_of_channels *
(fclks.data[vmid0p72_idx].clocks_in_khz / 1000.0)
* ddr4_dram_factor_single_Channel / 1000.0;
dc->dcn_soc->fabric_and_dram_bandwidth_vnom0p8 =
dc->dcn_soc->number_of_channels *
(fclks.data[vnom0p8_idx].clocks_in_khz / 1000.0)
* ddr4_dram_factor_single_Channel / 1000.0;
dc->dcn_soc->fabric_and_dram_bandwidth_vmax0p9 =
dc->dcn_soc->number_of_channels *
(fclks.data[vmax0p9_idx].clocks_in_khz / 1000.0)
* ddr4_dram_factor_single_Channel / 1000.0;
} else
BREAK_TO_DEBUGGER();
res = dm_pp_get_clock_levels_by_type_with_voltage(
ctx, DM_PP_CLOCK_TYPE_DCFCLK, &dcfclks);
if (res)
res = verify_clock_values(&dcfclks);
if (res && dcfclks.num_levels >= 3) {
dc->dcn_soc->dcfclkv_min0p65 = dcfclks.data[0].clocks_in_khz / 1000.0;
dc->dcn_soc->dcfclkv_mid0p72 = dcfclks.data[dcfclks.num_levels - 3].clocks_in_khz / 1000.0;
dc->dcn_soc->dcfclkv_nom0p8 = dcfclks.data[dcfclks.num_levels - 2].clocks_in_khz / 1000.0;
dc->dcn_soc->dcfclkv_max0p9 = dcfclks.data[dcfclks.num_levels - 1].clocks_in_khz / 1000.0;
} else
BREAK_TO_DEBUGGER();
dc->dcn_soc->fabric_and_dram_bandwidth_vmin0p65 =
32 * (fclks->data[vmin0p65_idx].clocks_in_khz / 1000.0) / 1000.0;
dc->dcn_soc->fabric_and_dram_bandwidth_vmid0p72 =
dc->dcn_soc->number_of_channels *
(fclks->data[vmid0p72_idx].clocks_in_khz / 1000.0)
* ddr4_dram_factor_single_Channel / 1000.0;
dc->dcn_soc->fabric_and_dram_bandwidth_vnom0p8 =
dc->dcn_soc->number_of_channels *
(fclks->data[vnom0p8_idx].clocks_in_khz / 1000.0)
* ddr4_dram_factor_single_Channel / 1000.0;
dc->dcn_soc->fabric_and_dram_bandwidth_vmax0p9 =
dc->dcn_soc->number_of_channels *
(fclks->data[vmax0p9_idx].clocks_in_khz / 1000.0)
* ddr4_dram_factor_single_Channel / 1000.0;
}
void dcn_bw_notify_pplib_of_wm_ranges(struct dc *dc)
void dcn_bw_update_from_pplib_dcfclks(
struct dc *dc,
struct dm_pp_clock_levels_with_voltage *dcfclks)
{
if (dcfclks->num_levels >= 3) {
dc->dcn_soc->dcfclkv_min0p65 = dcfclks->data[0].clocks_in_khz / 1000.0;
dc->dcn_soc->dcfclkv_mid0p72 = dcfclks->data[dcfclks->num_levels - 3].clocks_in_khz / 1000.0;
dc->dcn_soc->dcfclkv_nom0p8 = dcfclks->data[dcfclks->num_levels - 2].clocks_in_khz / 1000.0;
dc->dcn_soc->dcfclkv_max0p9 = dcfclks->data[dcfclks->num_levels - 1].clocks_in_khz / 1000.0;
}
}
void dcn_get_soc_clks(
struct dc *dc,
int *min_fclk_khz,
int *min_dcfclk_khz,
int *socclk_khz)
{
*min_fclk_khz = dc->dcn_soc->fabric_and_dram_bandwidth_vmin0p65 * 1000000 / 32;
*min_dcfclk_khz = dc->dcn_soc->dcfclkv_min0p65 * 1000;
*socclk_khz = dc->dcn_soc->socclk * 1000;
}
void dcn_bw_notify_pplib_of_wm_ranges(
struct dc *dc,
int min_fclk_khz,
int min_dcfclk_khz,
int socclk_khz)
{
struct pp_smu_funcs_rv *pp = NULL;
struct pp_smu_wm_range_sets ranges = {0};
int min_fclk_khz, min_dcfclk_khz, socclk_khz;
const int overdrive = 5000000; /* 5 GHz to cover Overdrive */
if (dc->res_pool->pp_smu)
@ -1526,10 +1512,6 @@ void dcn_bw_notify_pplib_of_wm_ranges(struct dc *dc)
if (!pp || !pp->set_wm_ranges)
return;
min_fclk_khz = dc->dcn_soc->fabric_and_dram_bandwidth_vmin0p65 * 1000000 / 32;
min_dcfclk_khz = dc->dcn_soc->dcfclkv_min0p65 * 1000;
socclk_khz = dc->dcn_soc->socclk * 1000;
/* Now notify PPLib/SMU about which Watermarks sets they should select
* depending on DPM state they are in. And update BW MGR GFX Engine and
* Memory clock member variables for Watermarks calculations for each

View File

@ -292,6 +292,7 @@ static struct _vcs_dpi_soc_bounding_box_st dcn3_15_soc = {
.urgent_latency_adjustment_fabric_clock_component_us = 0,
.urgent_latency_adjustment_fabric_clock_reference_mhz = 0,
.num_chans = 4,
.dummy_pstate_latency_us = 10.0
};
struct _vcs_dpi_ip_params_st dcn3_16_ip = {
@ -459,13 +460,30 @@ void dcn31_update_soc_for_wm_a(struct dc *dc, struct dc_state *context)
}
}
void dcn315_update_soc_for_wm_a(struct dc *dc, struct dc_state *context)
{
dc_assert_fp_enabled();
if (dc->clk_mgr->bw_params->wm_table.entries[WM_A].valid) {
/* For 315 pstate change is only supported if possible in vactive */
if (context->bw_ctx.dml.vba.DRAMClockChangeSupport[context->bw_ctx.dml.vba.VoltageLevel][context->bw_ctx.dml.vba.maxMpcComb] != dm_dram_clock_change_vactive)
context->bw_ctx.dml.soc.dram_clock_change_latency_us = context->bw_ctx.dml.soc.dummy_pstate_latency_us;
else
context->bw_ctx.dml.soc.dram_clock_change_latency_us = dc->clk_mgr->bw_params->wm_table.entries[WM_A].pstate_latency_us;
context->bw_ctx.dml.soc.sr_enter_plus_exit_time_us =
dc->clk_mgr->bw_params->wm_table.entries[WM_A].sr_enter_plus_exit_time_us;
context->bw_ctx.dml.soc.sr_exit_time_us =
dc->clk_mgr->bw_params->wm_table.entries[WM_A].sr_exit_time_us;
}
}
void dcn31_calculate_wm_and_dlg_fp(
struct dc *dc, struct dc_state *context,
display_e2e_pipe_params_st *pipes,
int pipe_cnt,
int vlevel)
{
int i, pipe_idx;
int i, pipe_idx, active_dpp_count = 0;
double dcfclk = context->bw_ctx.dml.vba.DCFCLKState[vlevel][context->bw_ctx.dml.vba.maxMpcComb];
dc_assert_fp_enabled();
@ -486,72 +504,6 @@ void dcn31_calculate_wm_and_dlg_fp(
pipes[0].clks_cfg.dcfclk_mhz = dcfclk;
pipes[0].clks_cfg.socclk_mhz = context->bw_ctx.dml.soc.clock_limits[vlevel].socclk_mhz;
#if 0 // TODO
/* Set B:
* TODO
*/
if (dc->clk_mgr->bw_params->wm_table.nv_entries[WM_B].valid) {
if (vlevel == 0) {
pipes[0].clks_cfg.voltage = 1;
pipes[0].clks_cfg.dcfclk_mhz = context->bw_ctx.dml.soc.clock_limits[0].dcfclk_mhz;
}
context->bw_ctx.dml.soc.dram_clock_change_latency_us = dc->clk_mgr->bw_params->wm_table.nv_entries[WM_B].dml_input.pstate_latency_us;
context->bw_ctx.dml.soc.sr_enter_plus_exit_time_us = dc->clk_mgr->bw_params->wm_table.nv_entries[WM_B].dml_input.sr_enter_plus_exit_time_us;
context->bw_ctx.dml.soc.sr_exit_time_us = dc->clk_mgr->bw_params->wm_table.nv_entries[WM_B].dml_input.sr_exit_time_us;
}
context->bw_ctx.bw.dcn.watermarks.b.urgent_ns = get_wm_urgent(&context->bw_ctx.dml, pipes, pipe_cnt) * 1000;
context->bw_ctx.bw.dcn.watermarks.b.cstate_pstate.cstate_enter_plus_exit_ns = get_wm_stutter_enter_exit(&context->bw_ctx.dml, pipes, pipe_cnt) * 1000;
context->bw_ctx.bw.dcn.watermarks.b.cstate_pstate.cstate_exit_ns = get_wm_stutter_exit(&context->bw_ctx.dml, pipes, pipe_cnt) * 1000;
context->bw_ctx.bw.dcn.watermarks.b.cstate_pstate.cstate_enter_plus_exit_z8_ns = get_wm_z8_stutter_enter_exit(&context->bw_ctx.dml, pipes, pipe_cnt) * 1000;
context->bw_ctx.bw.dcn.watermarks.b.cstate_pstate.cstate_exit_z8_ns = get_wm_z8_stutter_exit(&context->bw_ctx.dml, pipes, pipe_cnt) * 1000;
context->bw_ctx.bw.dcn.watermarks.b.cstate_pstate.pstate_change_ns = get_wm_dram_clock_change(&context->bw_ctx.dml, pipes, pipe_cnt) * 1000;
context->bw_ctx.bw.dcn.watermarks.b.pte_meta_urgent_ns = get_wm_memory_trip(&context->bw_ctx.dml, pipes, pipe_cnt) * 1000;
context->bw_ctx.bw.dcn.watermarks.b.frac_urg_bw_nom = get_fraction_of_urgent_bandwidth(&context->bw_ctx.dml, pipes, pipe_cnt) * 1000;
context->bw_ctx.bw.dcn.watermarks.b.frac_urg_bw_flip = get_fraction_of_urgent_bandwidth_imm_flip(&context->bw_ctx.dml, pipes, pipe_cnt) * 1000;
context->bw_ctx.bw.dcn.watermarks.b.urgent_latency_ns = get_urgent_latency(&context->bw_ctx.dml, pipes, pipe_cnt) * 1000;
pipes[0].clks_cfg.voltage = vlevel;
pipes[0].clks_cfg.dcfclk_mhz = dcfclk;
/* Set C:
* TODO
*/
if (dc->clk_mgr->bw_params->wm_table.nv_entries[WM_C].valid) {
context->bw_ctx.dml.soc.dram_clock_change_latency_us = dc->clk_mgr->bw_params->wm_table.nv_entries[WM_C].dml_input.pstate_latency_us;
context->bw_ctx.dml.soc.sr_enter_plus_exit_time_us = dc->clk_mgr->bw_params->wm_table.nv_entries[WM_C].dml_input.sr_enter_plus_exit_time_us;
context->bw_ctx.dml.soc.sr_exit_time_us = dc->clk_mgr->bw_params->wm_table.nv_entries[WM_C].dml_input.sr_exit_time_us;
}
context->bw_ctx.bw.dcn.watermarks.c.urgent_ns = get_wm_urgent(&context->bw_ctx.dml, pipes, pipe_cnt) * 1000;
context->bw_ctx.bw.dcn.watermarks.c.cstate_pstate.cstate_enter_plus_exit_ns = get_wm_stutter_enter_exit(&context->bw_ctx.dml, pipes, pipe_cnt) * 1000;
context->bw_ctx.bw.dcn.watermarks.c.cstate_pstate.cstate_exit_ns = get_wm_stutter_exit(&context->bw_ctx.dml, pipes, pipe_cnt) * 1000;
context->bw_ctx.bw.dcn.watermarks.c.cstate_pstate.cstate_enter_plus_exit_z8_ns = get_wm_z8_stutter_enter_exit(&context->bw_ctx.dml, pipes, pipe_cnt) * 1000;
context->bw_ctx.bw.dcn.watermarks.c.cstate_pstate.cstate_exit_z8_ns = get_wm_z8_stutter_exit(&context->bw_ctx.dml, pipes, pipe_cnt) * 1000;
context->bw_ctx.bw.dcn.watermarks.c.cstate_pstate.pstate_change_ns = get_wm_dram_clock_change(&context->bw_ctx.dml, pipes, pipe_cnt) * 1000;
context->bw_ctx.bw.dcn.watermarks.c.pte_meta_urgent_ns = get_wm_memory_trip(&context->bw_ctx.dml, pipes, pipe_cnt) * 1000;
context->bw_ctx.bw.dcn.watermarks.c.frac_urg_bw_nom = get_fraction_of_urgent_bandwidth(&context->bw_ctx.dml, pipes, pipe_cnt) * 1000;
context->bw_ctx.bw.dcn.watermarks.c.frac_urg_bw_flip = get_fraction_of_urgent_bandwidth_imm_flip(&context->bw_ctx.dml, pipes, pipe_cnt) * 1000;
context->bw_ctx.bw.dcn.watermarks.c.urgent_latency_ns = get_urgent_latency(&context->bw_ctx.dml, pipes, pipe_cnt) * 1000;
/* Set D:
* TODO
*/
if (dc->clk_mgr->bw_params->wm_table.nv_entries[WM_D].valid) {
context->bw_ctx.dml.soc.dram_clock_change_latency_us = dc->clk_mgr->bw_params->wm_table.nv_entries[WM_D].dml_input.pstate_latency_us;
context->bw_ctx.dml.soc.sr_enter_plus_exit_time_us = dc->clk_mgr->bw_params->wm_table.nv_entries[WM_D].dml_input.sr_enter_plus_exit_time_us;
context->bw_ctx.dml.soc.sr_exit_time_us = dc->clk_mgr->bw_params->wm_table.nv_entries[WM_D].dml_input.sr_exit_time_us;
}
context->bw_ctx.bw.dcn.watermarks.d.urgent_ns = get_wm_urgent(&context->bw_ctx.dml, pipes, pipe_cnt) * 1000;
context->bw_ctx.bw.dcn.watermarks.d.cstate_pstate.cstate_enter_plus_exit_ns = get_wm_stutter_enter_exit(&context->bw_ctx.dml, pipes, pipe_cnt) * 1000;
context->bw_ctx.bw.dcn.watermarks.d.cstate_pstate.cstate_exit_ns = get_wm_stutter_exit(&context->bw_ctx.dml, pipes, pipe_cnt) * 1000;
context->bw_ctx.bw.dcn.watermarks.d.cstate_pstate.pstate_change_ns = get_wm_dram_clock_change(&context->bw_ctx.dml, pipes, pipe_cnt) * 1000;
context->bw_ctx.bw.dcn.watermarks.d.cstate_pstate.cstate_enter_plus_exit_z8_ns = get_wm_z8_stutter_enter_exit(&context->bw_ctx.dml, pipes, pipe_cnt) * 1000;
context->bw_ctx.bw.dcn.watermarks.d.cstate_pstate.cstate_exit_z8_ns = get_wm_z8_stutter_exit(&context->bw_ctx.dml, pipes, pipe_cnt) * 1000;
context->bw_ctx.bw.dcn.watermarks.d.pte_meta_urgent_ns = get_wm_memory_trip(&context->bw_ctx.dml, pipes, pipe_cnt) * 1000;
context->bw_ctx.bw.dcn.watermarks.d.frac_urg_bw_nom = get_fraction_of_urgent_bandwidth(&context->bw_ctx.dml, pipes, pipe_cnt) * 1000;
context->bw_ctx.bw.dcn.watermarks.d.frac_urg_bw_flip = get_fraction_of_urgent_bandwidth_imm_flip(&context->bw_ctx.dml, pipes, pipe_cnt) * 1000;
context->bw_ctx.bw.dcn.watermarks.d.urgent_latency_ns = get_urgent_latency(&context->bw_ctx.dml, pipes, pipe_cnt) * 1000;
#endif
/* Set A:
* All clocks min required
*
@ -568,16 +520,17 @@ void dcn31_calculate_wm_and_dlg_fp(
context->bw_ctx.bw.dcn.watermarks.a.frac_urg_bw_nom = get_fraction_of_urgent_bandwidth(&context->bw_ctx.dml, pipes, pipe_cnt) * 1000;
context->bw_ctx.bw.dcn.watermarks.a.frac_urg_bw_flip = get_fraction_of_urgent_bandwidth_imm_flip(&context->bw_ctx.dml, pipes, pipe_cnt) * 1000;
context->bw_ctx.bw.dcn.watermarks.a.urgent_latency_ns = get_urgent_latency(&context->bw_ctx.dml, pipes, pipe_cnt) * 1000;
/* TODO: remove: */
context->bw_ctx.bw.dcn.watermarks.b = context->bw_ctx.bw.dcn.watermarks.a;
context->bw_ctx.bw.dcn.watermarks.c = context->bw_ctx.bw.dcn.watermarks.a;
context->bw_ctx.bw.dcn.watermarks.d = context->bw_ctx.bw.dcn.watermarks.a;
/* end remove*/
for (i = 0, pipe_idx = 0; i < dc->res_pool->pipe_count; i++) {
if (!context->res_ctx.pipe_ctx[i].stream)
continue;
if (context->res_ctx.pipe_ctx[i].plane_state)
active_dpp_count++;
pipes[pipe_idx].clks_cfg.dispclk_mhz = get_dispclk_calculated(&context->bw_ctx.dml, pipes, pipe_cnt);
pipes[pipe_idx].clks_cfg.dppclk_mhz = get_dppclk_calculated(&context->bw_ctx.dml, pipes, pipe_cnt, pipe_idx);
@ -594,6 +547,9 @@ void dcn31_calculate_wm_and_dlg_fp(
}
dcn20_calculate_dlg_params(dc, context, pipes, pipe_cnt, vlevel);
/* For 31x apu pstate change is only supported if possible in vactive or if there are no active dpps */
context->bw_ctx.bw.dcn.clk.p_state_change_support =
context->bw_ctx.dml.vba.DRAMClockChangeSupport[vlevel][context->bw_ctx.dml.vba.maxMpcComb] == dm_dram_clock_change_vactive || !active_dpp_count;
}
void dcn31_update_bw_bounding_box(struct dc *dc, struct clk_bw_params *bw_params)
@ -739,7 +695,7 @@ void dcn315_update_bw_bounding_box(struct dc *dc, struct clk_bw_params *bw_param
}
if (!IS_FPGA_MAXIMUS_DC(dc->ctx->dce_environment))
dml_init_instance(&dc->dml, &dcn3_15_soc, &dcn3_15_ip, DML_PROJECT_DCN31);
dml_init_instance(&dc->dml, &dcn3_15_soc, &dcn3_15_ip, DML_PROJECT_DCN315);
else
dml_init_instance(&dc->dml, &dcn3_15_soc, &dcn3_15_ip, DML_PROJECT_DCN31_FPGA);
}

View File

@ -35,6 +35,7 @@ void dcn31_zero_pipe_dcc_fraction(display_e2e_pipe_params_st *pipes,
int pipe_cnt);
void dcn31_update_soc_for_wm_a(struct dc *dc, struct dc_state *context);
void dcn315_update_soc_for_wm_a(struct dc *dc, struct dc_state *context);
void dcn31_calculate_wm_and_dlg_fp(
struct dc *dc, struct dc_state *context,

View File

@ -43,6 +43,8 @@
#define BPP_BLENDED_PIPE 0xffffffff
#define DCN31_MAX_DSC_IMAGE_WIDTH 5184
#define DCN31_MAX_FMT_420_BUFFER_WIDTH 4096
#define DCN3_15_MIN_COMPBUF_SIZE_KB 128
#define DCN3_15_MAX_DET_SIZE 384
// For DML-C changes that hasn't been propagated to VBA yet
//#define __DML_VBA_ALLOW_DELTA__
@ -3775,6 +3777,17 @@ static noinline void CalculatePrefetchSchedulePerPlane(
&v->VReadyOffsetPix[k]);
}
static void PatchDETBufferSizeInKByte(unsigned int NumberOfActivePlanes, int NoOfDPPThisState[], unsigned int config_return_buffer_size_in_kbytes, unsigned int *DETBufferSizeInKByte)
{
int i, total_pipes = 0;
for (i = 0; i < NumberOfActivePlanes; i++)
total_pipes += NoOfDPPThisState[i];
*DETBufferSizeInKByte = ((config_return_buffer_size_in_kbytes - DCN3_15_MIN_COMPBUF_SIZE_KB) / 64 / total_pipes) * 64;
if (*DETBufferSizeInKByte > DCN3_15_MAX_DET_SIZE)
*DETBufferSizeInKByte = DCN3_15_MAX_DET_SIZE;
}
void dml31_ModeSupportAndSystemConfigurationFull(struct display_mode_lib *mode_lib)
{
struct vba_vars_st *v = &mode_lib->vba;
@ -4533,6 +4546,8 @@ void dml31_ModeSupportAndSystemConfigurationFull(struct display_mode_lib *mode_l
v->ODMCombineEnableThisState[k] = v->ODMCombineEnablePerState[i][k];
}
if (v->NumberOfActivePlanes > 1 && mode_lib->project == DML_PROJECT_DCN315)
PatchDETBufferSizeInKByte(v->NumberOfActivePlanes, v->NoOfDPPThisState, v->ip.config_return_buffer_size_in_kbytes, &v->DETBufferSizeInKByte[0]);
CalculateSwathAndDETConfiguration(
false,
v->NumberOfActivePlanes,

View File

@ -243,7 +243,7 @@ void dcn32_build_wm_range_table_fpu(struct clk_mgr_internal *clk_mgr)
clk_mgr->base.bw_params->wm_table.nv_entries[WM_D].pmfw_breakdown.max_uclk = 0xFFFF;
}
/**
/*
* Finds dummy_latency_index when MCLK switching using firmware based
* vblank stretch is enabled. This function will iterate through the
* table of dummy pstate latencies until the lowest value that allows
@ -290,15 +290,14 @@ int dcn32_find_dummy_latency_index_for_fw_based_mclk_switch(struct dc *dc,
/**
* dcn32_helper_populate_phantom_dlg_params - Get DLG params for phantom pipes
* and populate pipe_ctx with those params.
*
* This function must be called AFTER the phantom pipes are added to context
* and run through DML (so that the DLG params for the phantom pipes can be
* populated), and BEFORE we program the timing for the phantom pipes.
*
* @dc: [in] current dc state
* @context: [in] new dc state
* @pipes: [in] DML pipe params array
* @pipe_cnt: [in] DML pipe count
*
* This function must be called AFTER the phantom pipes are added to context
* and run through DML (so that the DLG params for the phantom pipes can be
* populated), and BEFORE we program the timing for the phantom pipes.
*/
void dcn32_helper_populate_phantom_dlg_params(struct dc *dc,
struct dc_state *context,
@ -331,8 +330,9 @@ void dcn32_helper_populate_phantom_dlg_params(struct dc *dc,
}
/**
* *******************************************************************************************
* dcn32_predict_pipe_split: Predict if pipe split will occur for a given DML pipe
* dcn32_predict_pipe_split - Predict if pipe split will occur for a given DML pipe
* @context: [in] New DC state to be programmed
* @pipe_e2e: [in] DML pipe end to end context
*
* This function takes in a DML pipe (pipe_e2e) and predicts if pipe split is required (both
* ODM and MPC). For pipe split, ODM combine is determined by the ODM mode, and MPC combine is
@ -343,12 +343,7 @@ void dcn32_helper_populate_phantom_dlg_params(struct dc *dc,
* - MPC combine is only chosen if there is no ODM combine requirements / policy in place, and
* MPC is required
*
* @param [in]: context: New DC state to be programmed
* @param [in]: pipe_e2e: DML pipe end to end context
*
* @return: Number of splits expected (1 for 2:1 split, 3 for 4:1 split, 0 for no splits).
*
* *******************************************************************************************
* Return: Number of splits expected (1 for 2:1 split, 3 for 4:1 split, 0 for no splits).
*/
uint8_t dcn32_predict_pipe_split(struct dc_state *context,
display_e2e_pipe_params_st *pipe_e2e)
@ -504,7 +499,14 @@ void insert_entry_into_table_sorted(struct _vcs_dpi_voltage_scaling_st *table,
}
/**
* dcn32_set_phantom_stream_timing: Set timing params for the phantom stream
* dcn32_set_phantom_stream_timing - Set timing params for the phantom stream
* @dc: current dc state
* @context: new dc state
* @ref_pipe: Main pipe for the phantom stream
* @phantom_stream: target phantom stream state
* @pipes: DML pipe params
* @pipe_cnt: number of DML pipes
* @dc_pipe_idx: DC pipe index for the main pipe (i.e. ref_pipe)
*
* Set timing params of the phantom stream based on calculated output from DML.
* This function first gets the DML pipe index using the DC pipe index, then
@ -517,13 +519,6 @@ void insert_entry_into_table_sorted(struct _vcs_dpi_voltage_scaling_st *table,
* that separately.
*
* - Set phantom backporch = vstartup of main pipe
*
* @dc: current dc state
* @context: new dc state
* @ref_pipe: Main pipe for the phantom stream
* @pipes: DML pipe params
* @pipe_cnt: number of DML pipes
* @dc_pipe_idx: DC pipe index for the main pipe (i.e. ref_pipe)
*/
void dcn32_set_phantom_stream_timing(struct dc *dc,
struct dc_state *context,
@ -592,16 +587,14 @@ void dcn32_set_phantom_stream_timing(struct dc *dc,
}
/**
* dcn32_get_num_free_pipes: Calculate number of free pipes
* dcn32_get_num_free_pipes - Calculate number of free pipes
* @dc: current dc state
* @context: new dc state
*
* This function assumes that a "used" pipe is a pipe that has
* both a stream and a plane assigned to it.
*
* @dc: current dc state
* @context: new dc state
*
* Return:
* Number of free pipes available in the context
* Return: Number of free pipes available in the context
*/
static unsigned int dcn32_get_num_free_pipes(struct dc *dc, struct dc_state *context)
{
@ -625,7 +618,10 @@ static unsigned int dcn32_get_num_free_pipes(struct dc *dc, struct dc_state *con
}
/**
* dcn32_assign_subvp_pipe: Function to decide which pipe will use Sub-VP.
* dcn32_assign_subvp_pipe - Function to decide which pipe will use Sub-VP.
* @dc: current dc state
* @context: new dc state
* @index: [out] dc pipe index for the pipe chosen to have phantom pipes assigned
*
* We enter this function if we are Sub-VP capable (i.e. enough pipes available)
* and regular P-State switching (i.e. VACTIVE/VBLANK) is not supported, or if
@ -639,12 +635,7 @@ static unsigned int dcn32_get_num_free_pipes(struct dc *dc, struct dc_state *con
* for determining which should be the SubVP pipe (need a way to determine if a pipe / plane doesn't
* support MCLK switching naturally [i.e. ACTIVE or VBLANK]).
*
* @param dc: current dc state
* @param context: new dc state
* @param index: [out] dc pipe index for the pipe chosen to have phantom pipes assigned
*
* Return:
* True if a valid pipe assignment was found for Sub-VP. Otherwise false.
* Return: True if a valid pipe assignment was found for Sub-VP. Otherwise false.
*/
static bool dcn32_assign_subvp_pipe(struct dc *dc,
struct dc_state *context,
@ -711,7 +702,9 @@ static bool dcn32_assign_subvp_pipe(struct dc *dc,
}
/**
* dcn32_enough_pipes_for_subvp: Function to check if there are "enough" pipes for SubVP.
* dcn32_enough_pipes_for_subvp - Function to check if there are "enough" pipes for SubVP.
* @dc: current dc state
* @context: new dc state
*
* This function returns true if there are enough free pipes
* to create the required phantom pipes for any given stream
@ -723,9 +716,6 @@ static bool dcn32_assign_subvp_pipe(struct dc *dc,
* pipe which can be used as the phantom pipe for the non pipe
* split pipe.
*
* @dc: current dc state
* @context: new dc state
*
* Return:
* True if there are enough free pipes to assign phantom pipes to at least one
* stream that does not already have phantom pipes assigned. Otherwise false.
@ -764,7 +754,9 @@ static bool dcn32_enough_pipes_for_subvp(struct dc *dc, struct dc_state *context
}
/**
* subvp_subvp_schedulable: Determine if SubVP + SubVP config is schedulable
* subvp_subvp_schedulable - Determine if SubVP + SubVP config is schedulable
* @dc: current dc state
* @context: new dc state
*
* High level algorithm:
* 1. Find longest microschedule length (in us) between the two SubVP pipes
@ -772,11 +764,7 @@ static bool dcn32_enough_pipes_for_subvp(struct dc *dc, struct dc_state *context
* pipes still allows for the maximum microschedule to fit in the active
* region for both pipes.
*
* @dc: current dc state
* @context: new dc state
*
* Return:
* bool - True if the SubVP + SubVP config is schedulable, false otherwise
* Return: True if the SubVP + SubVP config is schedulable, false otherwise
*/
static bool subvp_subvp_schedulable(struct dc *dc, struct dc_state *context)
{
@ -836,7 +824,10 @@ static bool subvp_subvp_schedulable(struct dc *dc, struct dc_state *context)
}
/**
* subvp_drr_schedulable: Determine if SubVP + DRR config is schedulable
* subvp_drr_schedulable - Determine if SubVP + DRR config is schedulable
* @dc: current dc state
* @context: new dc state
* @drr_pipe: DRR pipe_ctx for the SubVP + DRR config
*
* High level algorithm:
* 1. Get timing for SubVP pipe, phantom pipe, and DRR pipe
@ -845,12 +836,7 @@ static bool subvp_subvp_schedulable(struct dc *dc, struct dc_state *context)
* 3.If (SubVP Active - Prefetch > Stretched DRR frame + max(MALL region, Stretched DRR frame))
* then report the configuration as supported
*
* @dc: current dc state
* @context: new dc state
* @drr_pipe: DRR pipe_ctx for the SubVP + DRR config
*
* Return:
* bool - True if the SubVP + DRR config is schedulable, false otherwise
* Return: True if the SubVP + DRR config is schedulable, false otherwise
*/
static bool subvp_drr_schedulable(struct dc *dc, struct dc_state *context, struct pipe_ctx *drr_pipe)
{
@ -914,7 +900,9 @@ static bool subvp_drr_schedulable(struct dc *dc, struct dc_state *context, struc
/**
* subvp_vblank_schedulable: Determine if SubVP + VBLANK config is schedulable
* subvp_vblank_schedulable - Determine if SubVP + VBLANK config is schedulable
* @dc: current dc state
* @context: new dc state
*
* High level algorithm:
* 1. Get timing for SubVP pipe, phantom pipe, and VBLANK pipe
@ -922,11 +910,7 @@ static bool subvp_drr_schedulable(struct dc *dc, struct dc_state *context, struc
* then report the configuration as supported
* 3. If the VBLANK display is DRR, then take the DRR static schedulability path
*
* @dc: current dc state
* @context: new dc state
*
* Return:
* bool - True if the SubVP + VBLANK/DRR config is schedulable, false otherwise
* Return: True if the SubVP + VBLANK/DRR config is schedulable, false otherwise
*/
static bool subvp_vblank_schedulable(struct dc *dc, struct dc_state *context)
{
@ -1003,20 +987,18 @@ static bool subvp_vblank_schedulable(struct dc *dc, struct dc_state *context)
}
/**
* subvp_validate_static_schedulability: Check which SubVP case is calculated and handle
* static analysis based on the case.
* subvp_validate_static_schedulability - Check which SubVP case is calculated
* and handle static analysis based on the case.
* @dc: current dc state
* @context: new dc state
* @vlevel: Voltage level calculated by DML
*
* Three cases:
* 1. SubVP + SubVP
* 2. SubVP + VBLANK (DRR checked internally)
* 3. SubVP + VACTIVE (currently unsupported)
*
* @dc: current dc state
* @context: new dc state
* @vlevel: Voltage level calculated by DML
*
* Return:
* bool - True if statically schedulable, false otherwise
* Return: True if statically schedulable, false otherwise
*/
static bool subvp_validate_static_schedulability(struct dc *dc,
struct dc_state *context,
@ -1115,7 +1097,8 @@ static void dcn32_full_validate_bw_helper(struct dc *dc,
* 5. (Config doesn't support MCLK in VACTIVE/VBLANK || dc->debug.force_subvp_mclk_switch)
*/
if (!dc->debug.force_disable_subvp && dcn32_all_pipes_have_stream_and_plane(dc, context) &&
!dcn32_mpo_in_use(context) && (*vlevel == context->bw_ctx.dml.soc.num_states ||
!dcn32_mpo_in_use(context) && !dcn32_any_surfaces_rotated(dc, context) &&
(*vlevel == context->bw_ctx.dml.soc.num_states ||
vba->DRAMClockChangeSupport[*vlevel][vba->maxMpcComb] == dm_dram_clock_change_unsupported ||
dc->debug.force_subvp_mclk_switch)) {
@ -1597,6 +1580,9 @@ bool dcn32_internal_validate_bw(struct dc *dc,
/*MPC split rules will handle this case*/
pipe->bottom_pipe->top_pipe = NULL;
} else {
/* when merging an ODM pipes, the bottom MPC pipe must now point to
* the previous ODM pipe and its associated stream assets
*/
if (pipe->prev_odm_pipe->bottom_pipe) {
/* 3 plane MPO*/
pipe->bottom_pipe->top_pipe = pipe->prev_odm_pipe->bottom_pipe;
@ -1606,6 +1592,8 @@ bool dcn32_internal_validate_bw(struct dc *dc,
pipe->bottom_pipe->top_pipe = pipe->prev_odm_pipe;
pipe->prev_odm_pipe->bottom_pipe = pipe->bottom_pipe;
}
memcpy(&pipe->bottom_pipe->stream_res, &pipe->bottom_pipe->top_pipe->stream_res, sizeof(struct stream_resource));
}
}
@ -1781,6 +1769,7 @@ void dcn32_calculate_wm_and_dlg_fpu(struct dc *dc, struct dc_state *context,
int i, pipe_idx, vlevel_temp = 0;
double dcfclk = dcn3_2_soc.clock_limits[0].dcfclk_mhz;
double dcfclk_from_validation = context->bw_ctx.dml.vba.DCFCLKState[vlevel][context->bw_ctx.dml.vba.maxMpcComb];
double dcfclk_from_fw_based_mclk_switching = dcfclk_from_validation;
bool pstate_en = context->bw_ctx.dml.vba.DRAMClockChangeSupport[vlevel][context->bw_ctx.dml.vba.maxMpcComb] !=
dm_dram_clock_change_unsupported;
unsigned int dummy_latency_index = 0;
@ -1816,7 +1805,7 @@ void dcn32_calculate_wm_and_dlg_fpu(struct dc *dc, struct dc_state *context,
dc->clk_mgr->bw_params->wm_table.nv_entries[WM_A].dml_input.pstate_latency_us;
dcn32_internal_validate_bw(dc, context, pipes, &pipe_cnt, &vlevel, false);
maxMpcComb = context->bw_ctx.dml.vba.maxMpcComb;
dcfclk = context->bw_ctx.dml.vba.DCFCLKState[vlevel][context->bw_ctx.dml.vba.maxMpcComb];
dcfclk_from_fw_based_mclk_switching = context->bw_ctx.dml.vba.DCFCLKState[vlevel][context->bw_ctx.dml.vba.maxMpcComb];
pstate_en = context->bw_ctx.dml.vba.DRAMClockChangeSupport[vlevel][maxMpcComb] !=
dm_dram_clock_change_unsupported;
}
@ -1902,6 +1891,10 @@ void dcn32_calculate_wm_and_dlg_fpu(struct dc *dc, struct dc_state *context,
pipes[0].clks_cfg.dcfclk_mhz = dcfclk_from_validation;
pipes[0].clks_cfg.socclk_mhz = context->bw_ctx.dml.soc.clock_limits[vlevel].socclk_mhz;
if (context->bw_ctx.bw.dcn.clk.fw_based_mclk_switching) {
pipes[0].clks_cfg.dcfclk_mhz = dcfclk_from_fw_based_mclk_switching;
}
if (dc->clk_mgr->bw_params->wm_table.nv_entries[WM_C].valid) {
min_dram_speed_mts = context->bw_ctx.dml.vba.DRAMSpeed;
min_dram_speed_mts_margin = 160;
@ -2275,7 +2268,7 @@ static int build_synthetic_soc_states(struct clk_bw_params *bw_params,
return 0;
}
/**
/*
* dcn32_update_bw_bounding_box
*
* This would override some dcn3_2 ip_or_soc initial parameters hardcoded from

View File

@ -733,6 +733,8 @@ static void DISPCLKDPPCLKDCFCLKDeepSleepPrefetchParametersWatermarksAndPerforman
mode_lib->vba.FCLKChangeLatency, v->UrgentLatency,
mode_lib->vba.SREnterPlusExitTime);
memset(&v->dummy_vars.DISPCLKDPPCLKDCFCLKDeepSleepPrefetchParametersWatermarksAndPerformanceCalculation.myPipe, 0, sizeof(DmlPipe));
v->dummy_vars.DISPCLKDPPCLKDCFCLKDeepSleepPrefetchParametersWatermarksAndPerformanceCalculation.myPipe.Dppclk = mode_lib->vba.DPPCLK[k];
v->dummy_vars.DISPCLKDPPCLKDCFCLKDeepSleepPrefetchParametersWatermarksAndPerformanceCalculation.myPipe.Dispclk = mode_lib->vba.DISPCLK;
v->dummy_vars.DISPCLKDPPCLKDCFCLKDeepSleepPrefetchParametersWatermarksAndPerformanceCalculation.myPipe.PixelClock = mode_lib->vba.PixelClock[k];
@ -2252,9 +2254,8 @@ void dml32_ModeSupportAndSystemConfigurationFull(struct display_mode_lib *mode_l
for (k = 0; k <= mode_lib->vba.NumberOfActiveSurfaces - 1; k++) {
if (!(mode_lib->vba.DSCInputBitPerComponent[k] == 12.0
|| mode_lib->vba.DSCInputBitPerComponent[k] == 10.0
|| mode_lib->vba.DSCInputBitPerComponent[k] == 8.0
|| mode_lib->vba.DSCInputBitPerComponent[k] >
mode_lib->vba.MaximumDSCBitsPerComponent)) {
|| mode_lib->vba.DSCInputBitPerComponent[k] == 8.0)
|| mode_lib->vba.DSCInputBitPerComponent[k] > mode_lib->vba.MaximumDSCBitsPerComponent) {
mode_lib->vba.NonsupportedDSCInputBPC = true;
}
}
@ -2330,16 +2331,15 @@ void dml32_ModeSupportAndSystemConfigurationFull(struct display_mode_lib *mode_l
if (mode_lib->vba.OutputMultistreamId[k] == k && mode_lib->vba.ForcedOutputLinkBPP[k] == 0)
mode_lib->vba.BPPForMultistreamNotIndicated = true;
for (j = 0; j < mode_lib->vba.NumberOfActiveSurfaces; ++j) {
if (mode_lib->vba.OutputMultistreamId[k] == j && mode_lib->vba.OutputMultistreamEn[k]
if (mode_lib->vba.OutputMultistreamId[k] == j
&& mode_lib->vba.ForcedOutputLinkBPP[k] == 0)
mode_lib->vba.BPPForMultistreamNotIndicated = true;
}
}
if ((mode_lib->vba.Output[k] == dm_edp || mode_lib->vba.Output[k] == dm_hdmi)) {
if (mode_lib->vba.OutputMultistreamId[k] == k && mode_lib->vba.OutputMultistreamEn[k])
if (mode_lib->vba.OutputMultistreamEn[k] == true && mode_lib->vba.OutputMultistreamId[k] == k)
mode_lib->vba.MultistreamWithHDMIOreDP = true;
for (j = 0; j < mode_lib->vba.NumberOfActiveSurfaces; ++j) {
if (mode_lib->vba.OutputMultistreamEn[k] == true && mode_lib->vba.OutputMultistreamId[k] == j)
mode_lib->vba.MultistreamWithHDMIOreDP = true;
@ -2478,8 +2478,6 @@ void dml32_ModeSupportAndSystemConfigurationFull(struct display_mode_lib *mode_l
mode_lib->vba.PixelClock[k], mode_lib->vba.PixelClockBackEnd[k]);
}
m = 0;
for (k = 0; k <= mode_lib->vba.NumberOfActiveSurfaces - 1; k++) {
for (m = 0; m <= mode_lib->vba.NumberOfActiveSurfaces - 1; m++) {
for (j = 0; j <= mode_lib->vba.NumberOfActiveSurfaces - 1; j++) {
@ -2856,8 +2854,6 @@ void dml32_ModeSupportAndSystemConfigurationFull(struct display_mode_lib *mode_l
}
}
m = 0;
//Calculate Return BW
for (i = 0; i < (int) v->soc.num_states; ++i) {
for (j = 0; j <= 1; ++j) {
@ -3618,11 +3614,10 @@ void dml32_ModeSupportAndSystemConfigurationFull(struct display_mode_lib *mode_l
mode_lib->vba.ModeIsSupported = mode_lib->vba.ModeSupport[i][0] == true
|| mode_lib->vba.ModeSupport[i][1] == true;
if (mode_lib->vba.ModeSupport[i][0] == true) {
if (mode_lib->vba.ModeSupport[i][0] == true)
MaximumMPCCombine = 0;
} else {
else
MaximumMPCCombine = 1;
}
}
}

View File

@ -114,6 +114,7 @@ void dml_init_instance(struct display_mode_lib *lib,
break;
case DML_PROJECT_DCN31:
case DML_PROJECT_DCN31_FPGA:
case DML_PROJECT_DCN315:
lib->funcs = dml31_funcs;
break;
case DML_PROJECT_DCN314:

View File

@ -40,6 +40,7 @@ enum dml_project {
DML_PROJECT_DCN21,
DML_PROJECT_DCN30,
DML_PROJECT_DCN31,
DML_PROJECT_DCN315,
DML_PROJECT_DCN31_FPGA,
DML_PROJECT_DCN314,
DML_PROJECT_DCN32,

View File

@ -39,6 +39,8 @@
#include "panel_cntl.h"
#define MAX_CLOCK_SOURCES 7
#define MAX_SVP_PHANTOM_STREAMS 2
#define MAX_SVP_PHANTOM_PLANES 2
void enable_surface_flip_reporting(struct dc_plane_state *plane_state,
uint32_t controller_id);
@ -232,6 +234,7 @@ struct resource_funcs {
unsigned int index);
bool (*remove_phantom_pipes)(struct dc *dc, struct dc_state *context);
void (*get_panel_config_defaults)(struct dc_panel_config *panel_config);
};
struct audio_support{
@ -438,7 +441,6 @@ struct pipe_ctx {
union pipe_update_flags update_flags;
struct dwbc *dwbc;
struct mcif_wb *mcif_wb;
bool vtp_locked;
};
/* Data used for dynamic link encoder assignment.
@ -492,6 +494,8 @@ struct dcn_bw_output {
struct dcn_watermark_set watermarks;
struct dcn_bw_writeback bw_writeback;
int compbuf_size_kb;
unsigned int legacy_svp_drr_stream_index;
bool legacy_svp_drr_stream_index_valid;
};
union bw_output {

View File

@ -628,8 +628,23 @@ unsigned int dcn_find_dcfclk_suits_all(
const struct dc *dc,
struct dc_clocks *clocks);
void dcn_bw_update_from_pplib(struct dc *dc);
void dcn_bw_notify_pplib_of_wm_ranges(struct dc *dc);
void dcn_get_soc_clks(
struct dc *dc,
int *min_fclk_khz,
int *min_dcfclk_khz,
int *socclk_khz);
void dcn_bw_update_from_pplib_fclks(
struct dc *dc,
struct dm_pp_clock_levels_with_voltage *fclks);
void dcn_bw_update_from_pplib_dcfclks(
struct dc *dc,
struct dm_pp_clock_levels_with_voltage *dcfclks);
void dcn_bw_notify_pplib_of_wm_ranges(
struct dc *dc,
int min_fclk_khz,
int min_dcfclk_khz,
int socclk_khz);
void dcn_bw_sync_calcs_and_dml(struct dc *dc);
enum source_macro_tile_size swizzle_mode_to_macro_tile_size(enum swizzle_mode_values sw_mode);

View File

@ -95,10 +95,23 @@ struct clk_limit_table_entry {
unsigned int wck_ratio;
};
struct clk_limit_num_entries {
unsigned int num_dcfclk_levels;
unsigned int num_fclk_levels;
unsigned int num_memclk_levels;
unsigned int num_socclk_levels;
unsigned int num_dtbclk_levels;
unsigned int num_dispclk_levels;
unsigned int num_dppclk_levels;
unsigned int num_phyclk_levels;
unsigned int num_phyclk_d18_levels;
};
/* This table is contiguous */
struct clk_limit_table {
struct clk_limit_table_entry entries[MAX_NUM_DPM_LVL];
unsigned int num_entries;
struct clk_limit_num_entries num_entries_per_clk;
unsigned int num_entries; /* highest populated dpm level for back compatibility */
};
struct wm_range_table_entry {

View File

@ -0,0 +1,99 @@
/* SPDX-License-Identifier: MIT */
/* Copyright © 2022 Advanced Micro Devices, Inc. All rights reserved. */
#ifndef __DAL_CURSOR_CACHE_H__
#define __DAL_CURSOR_CACHE_H__
union reg_cursor_control_cfg {
struct {
uint32_t cur_enable: 1;
uint32_t reser0: 3;
uint32_t cur_2x_magnify: 1;
uint32_t reser1: 3;
uint32_t mode: 3;
uint32_t reser2: 5;
uint32_t pitch: 2;
uint32_t reser3: 6;
uint32_t line_per_chunk: 5;
uint32_t reser4: 3;
} bits;
uint32_t raw;
};
struct cursor_position_cache_hubp {
union reg_cursor_control_cfg cur_ctl;
union reg_position_cfg {
struct {
uint32_t x_pos: 16;
uint32_t y_pos: 16;
} bits;
uint32_t raw;
} position;
union reg_hot_spot_cfg {
struct {
uint32_t x_hot: 16;
uint32_t y_hot: 16;
} bits;
uint32_t raw;
} hot_spot;
union reg_dst_offset_cfg {
struct {
uint32_t dst_x_offset: 13;
uint32_t reserved: 19;
} bits;
uint32_t raw;
} dst_offset;
};
struct cursor_attribute_cache_hubp {
uint32_t SURFACE_ADDR_HIGH;
uint32_t SURFACE_ADDR;
union reg_cursor_control_cfg cur_ctl;
union reg_cursor_size_cfg {
struct {
uint32_t width: 16;
uint32_t height: 16;
} bits;
uint32_t raw;
} size;
union reg_cursor_settings_cfg {
struct {
uint32_t dst_y_offset: 8;
uint32_t chunk_hdl_adjust: 2;
uint32_t reserved: 22;
} bits;
uint32_t raw;
} settings;
};
struct cursor_rect {
uint32_t x;
uint32_t y;
uint32_t w;
uint32_t h;
};
union reg_cur0_control_cfg {
struct {
uint32_t cur0_enable: 1;
uint32_t expansion_mode: 1;
uint32_t reser0: 1;
uint32_t cur0_rom_en: 1;
uint32_t mode: 3;
uint32_t reserved: 25;
} bits;
uint32_t raw;
};
struct cursor_position_cache_dpp {
union reg_cur0_control_cfg cur0_ctl;
};
struct cursor_attribute_cache_dpp {
union reg_cur0_control_cfg cur0_ctl;
};
struct cursor_attributes_cfg {
struct cursor_attribute_cache_hubp aHubp;
struct cursor_attribute_cache_dpp aDpp;
};
#endif

View File

@ -28,6 +28,7 @@
#define __DAL_DPP_H__
#include "transform.h"
#include "cursor_reg_cache.h"
union defer_reg_writes {
struct {
@ -58,6 +59,9 @@ struct dpp {
struct pwl_params shaper_params;
bool cm_bypass_mode;
struct cursor_position_cache_dpp pos;
struct cursor_attribute_cache_dpp att;
};
struct dpp_input_csc_matrix {

View File

@ -27,6 +27,7 @@
#define __DAL_HUBP_H__
#include "mem_input.h"
#include "cursor_reg_cache.h"
#define OPP_ID_INVALID 0xf
#define MAX_TTU 0xffffff
@ -65,6 +66,10 @@ struct hubp {
struct dc_cursor_attributes curs_attr;
struct dc_cursor_position curs_pos;
bool power_gated;
struct cursor_position_cache_hubp pos;
struct cursor_attribute_cache_hubp att;
struct cursor_rect cur_rect;
};
struct surface_flip_registers {

View File

@ -209,7 +209,6 @@ struct timing_generator_funcs {
void (*set_blank)(struct timing_generator *tg,
bool enable_blanking);
bool (*is_blanked)(struct timing_generator *tg);
bool (*is_locked)(struct timing_generator *tg);
void (*set_overscan_blank_color) (struct timing_generator *tg, const struct tg_color *color);
void (*set_blank_color)(struct timing_generator *tg, const struct tg_color *color);
void (*set_colors)(struct timing_generator *tg,

View File

@ -230,4 +230,10 @@ const struct link_hwss *get_link_hwss(const struct dc_link *link,
bool is_h_timing_divisible_by_2(struct dc_stream_state *stream);
bool dc_resource_acquire_secondary_pipe_for_mpc_odm(
const struct dc *dc,
struct dc_state *state,
struct pipe_ctx *pri_pipe,
struct pipe_ctx *sec_pipe,
bool odm);
#endif /* DRIVERS_GPU_DRM_AMD_DC_DEV_DC_INC_RESOURCE_H_ */

View File

@ -111,7 +111,7 @@ static void setup_hpo_dp_stream_encoder(struct pipe_ctx *pipe_ctx)
enum phyd32clk_clock_source phyd32clk = get_phyd32clk_src(pipe_ctx->stream->link);
dto_params.otg_inst = tg->inst;
dto_params.pixclk_khz = pipe_ctx->stream->phy_pix_clk;
dto_params.pixclk_khz = pipe_ctx->stream->timing.pix_clk_100hz / 10;
dto_params.num_odm_segments = get_odm_segment_count(pipe_ctx);
dto_params.timing = &pipe_ctx->stream->timing;
dto_params.ref_dtbclk_khz = dc->clk_mgr->funcs->get_dtb_ref_clk_frequency(dc->clk_mgr);

View File

@ -37,7 +37,7 @@ void virtual_reset_stream_encoder(struct pipe_ctx *pipe_ctx)
{
}
void virtual_disable_link_output(struct dc_link *link,
static void virtual_disable_link_output(struct dc_link *link,
const struct link_resource *link_res,
enum signal_type signal)
{

View File

@ -248,6 +248,7 @@ struct dmub_srv_hw_params {
bool disable_dpia;
bool usb4_cm_version;
bool fw_in_system_memory;
bool dpia_hpd_int_enable_supported;
};
/**

View File

@ -400,8 +400,9 @@ union dmub_fw_boot_options {
uint32_t diag_env: 1; /* 1 if diagnostic environment */
uint32_t gpint_scratch8: 1; /* 1 if GPINT is in scratch8*/
uint32_t usb4_cm_version: 1; /**< 1 CM support */
uint32_t dpia_hpd_int_enable_supported: 1; /* 1 if dpia hpd int enable supported */
uint32_t reserved : 17; /**< reserved */
uint32_t reserved : 16; /**< reserved */
} bits; /**< boot bits */
uint32_t all; /**< 32-bit access to bits */
};
@ -728,6 +729,12 @@ enum dmub_cmd_type {
/**
* Command type used for all VBIOS interface commands.
*/
/**
* Command type used to set DPIA HPD interrupt state
*/
DMUB_CMD__DPIA_HPD_INT_ENABLE = 86,
DMUB_CMD__VBIOS = 128,
};
@ -760,11 +767,6 @@ enum dmub_cmd_dpia_type {
DMUB_CMD__DPIA_MST_ALLOC_SLOTS = 2,
};
enum dmub_cmd_header_sub_type {
DMUB_CMD__SUB_TYPE_GENERAL = 0,
DMUB_CMD__SUB_TYPE_CURSOR_POSITION = 1
};
#pragma pack(push, 1)
/**
@ -1260,6 +1262,14 @@ struct dmub_rb_cmd_set_mst_alloc_slots {
struct dmub_cmd_mst_alloc_slots_control_data mst_slots_control; /* mst slots control */
};
/**
* DMUB command structure for DPIA HPD int enable control.
*/
struct dmub_rb_cmd_dpia_hpd_int_enable {
struct dmub_cmd_header header; /* header */
uint32_t enable; /* dpia hpd interrupt enable */
};
/**
* struct dmub_rb_cmd_dpphy_init - DPPHY init.
*/
@ -2089,7 +2099,99 @@ struct dmub_rb_cmd_update_dirty_rect {
/**
* Data passed from driver to FW in a DMUB_CMD__UPDATE_CURSOR_INFO command.
*/
struct dmub_cmd_update_cursor_info_data {
union dmub_reg_cursor_control_cfg {
struct {
uint32_t cur_enable: 1;
uint32_t reser0: 3;
uint32_t cur_2x_magnify: 1;
uint32_t reser1: 3;
uint32_t mode: 3;
uint32_t reser2: 5;
uint32_t pitch: 2;
uint32_t reser3: 6;
uint32_t line_per_chunk: 5;
uint32_t reser4: 3;
} bits;
uint32_t raw;
};
struct dmub_cursor_position_cache_hubp {
union dmub_reg_cursor_control_cfg cur_ctl;
union dmub_reg_position_cfg {
struct {
uint32_t cur_x_pos: 16;
uint32_t cur_y_pos: 16;
} bits;
uint32_t raw;
} position;
union dmub_reg_hot_spot_cfg {
struct {
uint32_t hot_x: 16;
uint32_t hot_y: 16;
} bits;
uint32_t raw;
} hot_spot;
union dmub_reg_dst_offset_cfg {
struct {
uint32_t dst_x_offset: 13;
uint32_t reserved: 19;
} bits;
uint32_t raw;
} dst_offset;
};
union dmub_reg_cur0_control_cfg {
struct {
uint32_t cur0_enable: 1;
uint32_t expansion_mode: 1;
uint32_t reser0: 1;
uint32_t cur0_rom_en: 1;
uint32_t mode: 3;
uint32_t reserved: 25;
} bits;
uint32_t raw;
};
struct dmub_cursor_position_cache_dpp {
union dmub_reg_cur0_control_cfg cur0_ctl;
};
struct dmub_cursor_position_cfg {
struct dmub_cursor_position_cache_hubp pHubp;
struct dmub_cursor_position_cache_dpp pDpp;
uint8_t pipe_idx;
/*
* Padding is required. To be 4 Bytes Aligned.
*/
uint8_t padding[3];
};
struct dmub_cursor_attribute_cache_hubp {
uint32_t SURFACE_ADDR_HIGH;
uint32_t SURFACE_ADDR;
union dmub_reg_cursor_control_cfg cur_ctl;
union dmub_reg_cursor_size_cfg {
struct {
uint32_t width: 16;
uint32_t height: 16;
} bits;
uint32_t raw;
} size;
union dmub_reg_cursor_settings_cfg {
struct {
uint32_t dst_y_offset: 8;
uint32_t chunk_hdl_adjust: 2;
uint32_t reserved: 22;
} bits;
uint32_t raw;
} settings;
};
struct dmub_cursor_attribute_cache_dpp {
union dmub_reg_cur0_control_cfg cur0_ctl;
};
struct dmub_cursor_attributes_cfg {
struct dmub_cursor_attribute_cache_hubp aHubp;
struct dmub_cursor_attribute_cache_dpp aDpp;
};
struct dmub_cmd_update_cursor_payload0 {
/**
* Cursor dirty rects.
*/
@ -2116,6 +2218,20 @@ struct dmub_cmd_update_cursor_info_data {
* Currently the support is only for 0 or 1
*/
uint8_t panel_inst;
/**
* Cursor Position Register.
* Registers contains Hubp & Dpp modules
*/
struct dmub_cursor_position_cfg position_cfg;
};
struct dmub_cmd_update_cursor_payload1 {
struct dmub_cursor_attributes_cfg attribute_cfg;
};
union dmub_cmd_update_cursor_info_data {
struct dmub_cmd_update_cursor_payload0 payload0;
struct dmub_cmd_update_cursor_payload1 payload1;
};
/**
* Definition of a DMUB_CMD__UPDATE_CURSOR_INFO command.
@ -2128,7 +2244,7 @@ struct dmub_rb_cmd_update_cursor_info {
/**
* Data passed from driver to FW in a DMUB_CMD__UPDATE_CURSOR_INFO command.
*/
struct dmub_cmd_update_cursor_info_data update_cursor_info_data;
union dmub_cmd_update_cursor_info_data update_cursor_info_data;
};
/**
@ -2825,11 +2941,7 @@ struct dmub_rb_cmd_get_visual_confirm_color {
struct dmub_optc_state {
uint32_t v_total_max;
uint32_t v_total_min;
uint32_t v_total_mid;
uint32_t v_total_mid_frame_num;
uint32_t tg_inst;
uint32_t enable_manual_trigger;
uint32_t clear_force_vsync;
};
struct dmub_rb_cmd_drr_update {
@ -3235,6 +3347,10 @@ union dmub_rb_cmd {
* Definition of a DMUB_CMD__QUERY_HPD_STATE command.
*/
struct dmub_rb_cmd_query_hpd_state query_hpd;
/**
* Definition of a DMUB_CMD__DPIA_HPD_INT_ENABLE command.
*/
struct dmub_rb_cmd_dpia_hpd_int_enable dpia_hpd_int_enable;
};
/**

View File

@ -350,6 +350,7 @@ void dmub_dcn31_enable_dmub_boot_options(struct dmub_srv *dmub, const struct dmu
boot_options.bits.dpia_supported = params->dpia_supported;
boot_options.bits.enable_dpia = params->disable_dpia ? 0 : 1;
boot_options.bits.usb4_cm_version = params->usb4_cm_version;
boot_options.bits.dpia_hpd_int_enable_supported = params->dpia_hpd_int_enable_supported;
boot_options.bits.power_optimization = params->power_optimization;
boot_options.bits.sel_mux_phy_c_d_phy_f_g = (dmub->asic == DMUB_ASIC_DCN31B) ? 1 : 0;

View File

@ -1692,7 +1692,7 @@ static void apply_degamma_for_user_regamma(struct pwl_float_data_ex *rgb_regamma
struct pwl_float_data_ex *rgb = rgb_regamma;
const struct hw_x_point *coord_x = coordinates_x;
build_coefficients(&coeff, true);
build_coefficients(&coeff, TRANSFER_FUNCTION_SRGB);
i = 0;
while (i != hw_points_num + 1) {

View File

@ -29,5 +29,7 @@
#define regMCA_UMC_UMC0_MCUMC_STATUST0_BASE_IDX 2
#define regMCA_UMC_UMC0_MCUMC_ADDRT0 0x03c4
#define regMCA_UMC_UMC0_MCUMC_ADDRT0_BASE_IDX 2
#define regUMCCH0_0_GeccCtrl 0x0053
#define regUMCCH0_0_GeccCtrl_BASE_IDX 2
#endif

View File

@ -90,5 +90,8 @@
#define MCA_UMC_UMC0_MCUMC_ADDRT0__ErrorAddr__SHIFT 0x0
#define MCA_UMC_UMC0_MCUMC_ADDRT0__Reserved__SHIFT 0x38
#define MCA_UMC_UMC0_MCUMC_ADDRT0__ErrorAddr_MASK 0x00FFFFFFFFFFFFFFL
//UMCCH0_0_GeccCtrl
#define UMCCH0_0_GeccCtrl__UCFatalEn__SHIFT 0xd
#define UMCCH0_0_GeccCtrl__UCFatalEn_MASK 0x00002000L
#endif

View File

@ -1384,13 +1384,16 @@ static int kv_dpm_enable(struct amdgpu_device *adev)
static void kv_dpm_disable(struct amdgpu_device *adev)
{
struct kv_power_info *pi = kv_get_pi(adev);
int err;
amdgpu_irq_put(adev, &adev->pm.dpm.thermal.irq,
AMDGPU_THERMAL_IRQ_LOW_TO_HIGH);
amdgpu_irq_put(adev, &adev->pm.dpm.thermal.irq,
AMDGPU_THERMAL_IRQ_HIGH_TO_LOW);
amdgpu_kv_smc_bapm_enable(adev, false);
err = amdgpu_kv_smc_bapm_enable(adev, false);
if (err)
DRM_ERROR("amdgpu_kv_smc_bapm_enable failed\n");
if (adev->asic_type == CHIP_MULLINS)
kv_enable_nb_dpm(adev, false);

View File

@ -3603,7 +3603,7 @@ static int smu7_get_pp_table_entry_callback_func_v1(struct pp_hwmgr *hwmgr,
return -EINVAL);
PP_ASSERT_WITH_CODE(
(smu7_power_state->performance_level_count <=
(smu7_power_state->performance_level_count <
hwmgr->platform_descriptor.hardwareActivityPerformanceLevels),
"Performance levels exceeds Driver limit!",
return -EINVAL);

View File

@ -3155,7 +3155,7 @@ static int vega10_get_pp_table_entry_callback_func(struct pp_hwmgr *hwmgr,
return -1);
PP_ASSERT_WITH_CODE(
(vega10_ps->performance_level_count <=
(vega10_ps->performance_level_count <
hwmgr->platform_descriptor.
hardwareActivityPerformanceLevels),
"Performance levels exceeds Driver limit!",

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