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
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; return;
adev->kfd.dev = kgd2kfd_probe(adev, vf); 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->kfd.init_complete = kgd2kfd_device_init(adev->kfd.dev,
adev_to_drm(adev), &gpu_resources); 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); 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) { if (adev->kfd.dev) {
kgd2kfd_device_exit(adev->kfd.dev); kgd2kfd_device_exit(adev->kfd.dev);
adev->kfd.dev = NULL; 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/pci.h>
#include <linux/pm_runtime.h> #include <linux/pm_runtime.h>
#include <drm/drm_crtc_helper.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_edid.h>
#include <drm/drm_gem_framebuffer_helper.h> #include <drm/drm_gem_framebuffer_helper.h>
#include <drm/drm_fb_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, .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, uint32_t amdgpu_display_supported_domains(struct amdgpu_device *adev,
uint64_t bo_flags) uint64_t bo_flags)
{ {
@@ -1108,10 +1100,8 @@ static int amdgpu_display_gem_fb_verify_and_init(struct drm_device *dev,
if (ret) if (ret)
goto err; goto err;
if (drm_drv_uses_atomic_modeset(dev)) ret = drm_framebuffer_init(dev, &rfb->base, &amdgpu_fb_funcs);
ret = drm_framebuffer_init(dev, &rfb->base, &amdgpu_fb_funcs_atomic);
else
ret = drm_framebuffer_init(dev, &rfb->base, &amdgpu_fb_funcs);
if (ret) if (ret)
goto err; goto err;

View File

@@ -688,13 +688,16 @@ int amdgpu_bo_create_vm(struct amdgpu_device *adev,
* num of amdgpu_vm_pt entries. * num of amdgpu_vm_pt entries.
*/ */
BUG_ON(bp->bo_ptr_size < sizeof(struct amdgpu_bo_vm)); 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); r = amdgpu_bo_create(adev, bp, &bo_ptr);
if (r) if (r)
return r; return r;
*vmbo_ptr = to_amdgpu_bo_vm(bo_ptr); *vmbo_ptr = to_amdgpu_bo_vm(bo_ptr);
INIT_LIST_HEAD(&(*vmbo_ptr)->shadow_list); 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; return r;
} }

View File

@@ -2877,9 +2877,9 @@ static int amdgpu_bad_page_notifier(struct notifier_block *nb,
err_data.err_addr = err_data.err_addr =
kcalloc(adev->umc.max_ras_err_cnt_per_query, kcalloc(adev->umc.max_ras_err_cnt_per_query,
sizeof(struct eeprom_table_record), GFP_KERNEL); sizeof(struct eeprom_table_record), GFP_KERNEL);
if(!err_data.err_addr) { if (!err_data.err_addr) {
dev_warn(adev->dev, "Failed to alloc memory for " dev_warn(adev->dev,
"umc error address record in mca notifier!\n"); "Failed to alloc memory for umc error record in mca notifier!\n");
return NOTIFY_DONE; return NOTIFY_DONE;
} }
@@ -2889,7 +2889,7 @@ static int amdgpu_bad_page_notifier(struct notifier_block *nb,
if (adev->umc.ras && if (adev->umc.ras &&
adev->umc.ras->convert_ras_error_address) adev->umc.ras->convert_ras_error_address)
adev->umc.ras->convert_ras_error_address(adev, 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) { if (amdgpu_bad_page_threshold != 0) {
amdgpu_ras_add_bad_pages(adev, err_data.err_addr, 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; adev->sdma.instance[instance].fw->data;
version_major = le16_to_cpu(header->header_version_major); version_major = le16_to_cpu(header->header_version_major);
if ((duplicate && instance) || (!duplicate && version_major > 1)) if ((duplicate && instance) || (!duplicate && version_major > 1)) {
return -EINVAL; err = -EINVAL;
goto out;
}
err = amdgpu_sdma_init_inst_ctx(&adev->sdma.instance[instance]); err = amdgpu_sdma_init_inst_ctx(&adev->sdma.instance[instance]);
if (err) 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); ALIGN(le32_to_cpu(sdma_hdr->ctl_ucode_size_bytes), PAGE_SIZE);
break; break;
default: default:
return -EINVAL; err = -EINVAL;
} }
} }
@@ -283,3 +285,24 @@ out:
} }
return err; 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); char *fw_name, u32 instance, bool duplicate);
void amdgpu_sdma_destroy_inst_ctx(struct amdgpu_device *adev, void amdgpu_sdma_destroy_inst_ctx(struct amdgpu_device *adev,
bool duplicate); bool duplicate);
void amdgpu_sdma_unset_buffer_funcs_helper(struct amdgpu_device *adev);
#endif #endif

View File

@@ -424,8 +424,9 @@ error:
static bool amdgpu_mem_visible(struct amdgpu_device *adev, static bool amdgpu_mem_visible(struct amdgpu_device *adev,
struct ttm_resource *mem) 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; struct amdgpu_res_cursor cursor;
u64 end;
if (mem->mem_type == TTM_PL_SYSTEM || if (mem->mem_type == TTM_PL_SYSTEM ||
mem->mem_type == TTM_PL_TT) mem->mem_type == TTM_PL_TT)
@@ -434,12 +435,18 @@ static bool amdgpu_mem_visible(struct amdgpu_device *adev,
return false; return false;
amdgpu_res_first(mem, 0, mem_size, &cursor); 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 */ /* ttm_resource_ioremap only supports contiguous memory */
if (cursor.size != mem_size) if (end != cursor.start)
return false; 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__ #define __AMDGPU_UMC_H__
#include "amdgpu_ras.h" #include "amdgpu_ras.h"
#define UMC_INVALID_ADDR 0x1ULL
/* /*
* (addr / 256) * 4096, the higher 26 bits in ErrorAddr * (addr / 256) * 4096, the higher 26 bits in ErrorAddr
* is the index of 4KB block * is the index of 4KB block
@@ -54,9 +52,8 @@ struct amdgpu_umc_ras {
void (*err_cnt_init)(struct amdgpu_device *adev); void (*err_cnt_init)(struct amdgpu_device *adev);
bool (*query_ras_poison_mode)(struct amdgpu_device *adev); bool (*query_ras_poison_mode)(struct amdgpu_device *adev);
void (*convert_ras_error_address)(struct amdgpu_device *adev, void (*convert_ras_error_address)(struct amdgpu_device *adev,
struct ras_err_data *err_data, struct ras_err_data *err_data, uint64_t err_addr,
uint32_t umc_reg_offset, uint32_t ch_inst, uint32_t ch_inst, uint32_t umc_inst);
uint32_t umc_inst, uint64_t mca_addr);
void (*ecc_info_query_ras_error_count)(struct amdgpu_device *adev, void (*ecc_info_query_ras_error_count)(struct amdgpu_device *adev,
void *ras_error_status); void *ras_error_status);
void (*ecc_info_query_ras_error_address)(struct amdgpu_device *adev, 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) 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; u32 rb_cntl;
int i; int i;
if ((adev->mman.buffer_funcs_ring == sdma0) || amdgpu_sdma_unset_buffer_funcs_helper(adev);
(adev->mman.buffer_funcs_ring == sdma1))
amdgpu_ttm_set_buffer_funcs_status(adev, false);
for (i = 0; i < adev->sdma.num_instances; i++) { for (i = 0; i < adev->sdma.num_instances; i++) {
rb_cntl = RREG32(mmSDMA0_GFX_RB_CNTL + sdma_offsets[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) 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; u32 rb_cntl, ib_cntl;
int i; int i;
if ((adev->mman.buffer_funcs_ring == sdma0) || amdgpu_sdma_unset_buffer_funcs_helper(adev);
(adev->mman.buffer_funcs_ring == sdma1))
amdgpu_ttm_set_buffer_funcs_status(adev, false);
for (i = 0; i < adev->sdma.num_instances; i++) { for (i = 0; i < adev->sdma.num_instances; i++) {
rb_cntl = RREG32(mmSDMA0_GFX_RB_CNTL + sdma_offsets[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) 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; u32 rb_cntl, ib_cntl;
int i; int i;
if ((adev->mman.buffer_funcs_ring == sdma0) || amdgpu_sdma_unset_buffer_funcs_helper(adev);
(adev->mman.buffer_funcs_ring == sdma1))
amdgpu_ttm_set_buffer_funcs_status(adev, false);
for (i = 0; i < adev->sdma.num_instances; i++) { for (i = 0; i < adev->sdma.num_instances; i++) {
rb_cntl = RREG32(mmSDMA0_GFX_RB_CNTL + sdma_offsets[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) static void sdma_v4_0_gfx_stop(struct amdgpu_device *adev)
{ {
struct amdgpu_ring *sdma[AMDGPU_MAX_SDMA_INSTANCES];
u32 rb_cntl, ib_cntl; 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++) { 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 = RREG32_SDMA(i, mmSDMA0_GFX_RB_CNTL);
rb_cntl = REG_SET_FIELD(rb_cntl, SDMA0_GFX_RB_CNTL, RB_ENABLE, 0); rb_cntl = REG_SET_FIELD(rb_cntl, SDMA0_GFX_RB_CNTL, RB_ENABLE, 0);
WREG32_SDMA(i, mmSDMA0_GFX_RB_CNTL, rb_cntl); 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) static void sdma_v4_0_page_stop(struct amdgpu_device *adev)
{ {
struct amdgpu_ring *sdma[AMDGPU_MAX_SDMA_INSTANCES];
u32 rb_cntl, ib_cntl; u32 rb_cntl, ib_cntl;
int i; int i;
bool unset = false;
amdgpu_sdma_unset_buffer_funcs_helper(adev);
for (i = 0; i < adev->sdma.num_instances; i++) { 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 = RREG32_SDMA(i, mmSDMA0_PAGE_RB_CNTL);
rb_cntl = REG_SET_FIELD(rb_cntl, SDMA0_PAGE_RB_CNTL, rb_cntl = REG_SET_FIELD(rb_cntl, SDMA0_PAGE_RB_CNTL,
RB_ENABLE, 0); RB_ENABLE, 0);
@@ -1954,8 +1940,11 @@ static int sdma_v4_0_hw_fini(void *handle)
struct amdgpu_device *adev = (struct amdgpu_device *)handle; struct amdgpu_device *adev = (struct amdgpu_device *)handle;
int i; 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; return 0;
}
for (i = 0; i < adev->sdma.num_instances; i++) { for (i = 0; i < adev->sdma.num_instances; i++) {
amdgpu_irq_put(adev, &adev->sdma.ecc_irq, 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) 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; u32 rb_cntl, ib_cntl;
int i; int i;
if ((adev->mman.buffer_funcs_ring == sdma0) || amdgpu_sdma_unset_buffer_funcs_helper(adev);
(adev->mman.buffer_funcs_ring == sdma1))
amdgpu_ttm_set_buffer_funcs_status(adev, false);
for (i = 0; i < adev->sdma.num_instances; i++) { 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)); 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; 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; return 0;
}
sdma_v5_0_ctx_switch_enable(adev, false); sdma_v5_0_ctx_switch_enable(adev, false);
sdma_v5_0_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) 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; u32 rb_cntl, ib_cntl;
int i; int i;
if ((adev->mman.buffer_funcs_ring == sdma0) || amdgpu_sdma_unset_buffer_funcs_helper(adev);
(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);
for (i = 0; i < adev->sdma.num_instances; i++) { 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)); 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; 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; return 0;
}
sdma_v5_2_ctx_switch_enable(adev, false); sdma_v5_2_ctx_switch_enable(adev, false);
sdma_v5_2_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) 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; u32 rb_cntl, ib_cntl;
int i; int i;
if ((adev->mman.buffer_funcs_ring == sdma0) || amdgpu_sdma_unset_buffer_funcs_helper(adev);
(adev->mman.buffer_funcs_ring == sdma1))
amdgpu_ttm_set_buffer_funcs_status(adev, false);
for (i = 0; i < adev->sdma.num_instances; i++) { 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)); 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); 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); 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 = m->sdmax_rlcx_rb_cntl =
order_base_2(prop->queue_size / 4) << SDMA0_QUEUE0_RB_CNTL__RB_SIZE__SHIFT | order_base_2(prop->queue_size / 4) << SDMA0_QUEUE0_RB_CNTL__RB_SIZE__SHIFT |
1 << SDMA0_QUEUE0_RB_CNTL__RPTR_WRITEBACK_ENABLE__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 = lower_32_bits(prop->hqd_base_gpu_addr >> 8);
m->sdmax_rlcx_rb_base_hi = upper_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; 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; return 0;
}
sdma_v6_0_ctx_switch_enable(adev, false); sdma_v6_0_ctx_switch_enable(adev, false);
sdma_v6_0_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; u32 rb_cntl;
unsigned i; unsigned i;
amdgpu_sdma_unset_buffer_funcs_helper(adev);
for (i = 0; i < adev->sdma.num_instances; i++) { for (i = 0; i < adev->sdma.num_instances; i++) {
ring = &adev->sdma.instance[i].ring; ring = &adev->sdma.instance[i].ring;
/* dma0 */ /* dma0 */
rb_cntl = RREG32(DMA_RB_CNTL + sdma_offsets[i]); rb_cntl = RREG32(DMA_RB_CNTL + sdma_offsets[i]);
rb_cntl &= ~DMA_RB_ENABLE; rb_cntl &= ~DMA_RB_ENABLE;
WREG32(DMA_RB_CNTL + sdma_offsets[i], rb_cntl); 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; AMD_CG_SUPPORT_JPEG_MGCG;
adev->pg_flags = adev->pg_flags =
AMD_PG_SUPPORT_GFX_PG | AMD_PG_SUPPORT_GFX_PG |
AMD_PG_SUPPORT_VCN |
AMD_PG_SUPPORT_VCN_DPG | AMD_PG_SUPPORT_VCN_DPG |
AMD_PG_SUPPORT_JPEG; AMD_PG_SUPPORT_JPEG;
adev->external_rev_id = adev->rev_id + 0x1; 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; 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 && 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, UECC) == 1) {
REG_GET_FIELD(mc_umc_status, MCA_UMC_UMC0_MCUMC_STATUST0, CECC) == 1)) {
err_addr = RREG64_PCIE((mc_umc_addrt0 + umc_reg_offset) * 4); err_addr = RREG64_PCIE((mc_umc_addrt0 + umc_reg_offset) * 4);
/* the lowest lsb bits should be ignored */ /* 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) | ADDR_OF_256B_BLOCK(channel_index) |
OFFSET_IN_256B_BLOCK(err_addr); OFFSET_IN_256B_BLOCK(err_addr);
/* we only save ue error information currently, ce is skipped */ amdgpu_umc_fill_error_record(err_data, err_addr,
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); 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, static void umc_v6_7_ecc_info_query_error_address(struct amdgpu_device *adev,
struct ras_err_data *err_data, struct ras_err_data *err_data,
uint32_t ch_inst, uint32_t ch_inst,
uint32_t umc_inst) uint32_t umc_inst)
{ {
uint64_t mc_umc_status, err_addr, soc_pa, retired_page, column; uint64_t mc_umc_status, err_addr;
uint32_t channel_index;
uint32_t eccinfo_table_idx; uint32_t eccinfo_table_idx;
struct amdgpu_ras *ras = amdgpu_ras_get_context(adev); struct amdgpu_ras *ras = amdgpu_ras_get_context(adev);
eccinfo_table_idx = umc_inst * adev->umc.channel_inst_num + ch_inst; 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; mc_umc_status = ras->umc_ecc.ecc[eccinfo_table_idx].mca_umc_status;
if (mc_umc_status == 0) 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) if (!err_data->err_addr)
return; 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 && 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, UECC) == 1) {
REG_GET_FIELD(mc_umc_status, MCA_UMC_UMC0_MCUMC_STATUST0, CECC) == 1)) {
err_addr = ras->umc_ecc.ecc[eccinfo_table_idx].mca_umc_addr; 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); err_addr = REG_GET_FIELD(err_addr, MCA_UMC_UMC0_MCUMC_ADDRT0, ErrorAddr);
/* translate umc channel address to soc pa, 3 parts are included */ umc_v6_7_convert_error_address(adev, err_data, err_addr,
soc_pa = ADDR_OF_8KB_BLOCK(err_addr) | ch_inst, umc_inst);
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);
}
}
} }
} }
@@ -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, static void umc_v6_7_query_error_address(struct amdgpu_device *adev,
struct ras_err_data *err_data, struct ras_err_data *err_data,
uint32_t umc_reg_offset, uint32_t ch_inst, 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 mc_umc_status_addr;
uint32_t channel_index; uint64_t mc_umc_status = 0, mc_umc_addrt0, err_addr;
uint64_t mc_umc_status = 0, mc_umc_addrt0;
uint64_t err_addr, soc_pa, retired_page, column;
if (mca_addr == UMC_INVALID_ADDR) { mc_umc_status_addr =
mc_umc_status_addr = SOC15_REG_OFFSET(UMC, 0, regMCA_UMC_UMC0_MCUMC_STATUST0);
SOC15_REG_OFFSET(UMC, 0, regMCA_UMC_UMC0_MCUMC_STATUST0); mc_umc_addrt0 =
mc_umc_addrt0 = SOC15_REG_OFFSET(UMC, 0, regMCA_UMC_UMC0_MCUMC_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) if (mc_umc_status == 0)
return; return;
if (!err_data->err_addr) { if (!err_data->err_addr) {
/* clear umc status */ /* clear umc status */
WREG64_PCIE((mc_umc_status_addr + umc_reg_offset) * 4, 0x0ULL); WREG64_PCIE((mc_umc_status_addr + umc_reg_offset) * 4, 0x0ULL);
return; return;
}
} }
channel_index = /* calculate error address if ue error is detected */
adev->umc.channel_idx_tbl[umc_inst * adev->umc.channel_inst_num + ch_inst]; 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 */ umc_v6_7_convert_error_address(adev, err_data, err_addr,
if ((REG_GET_FIELD(mc_umc_status, MCA_UMC_UMC0_MCUMC_STATUST0, Val) == 1 && ch_inst, umc_inst);
(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);
}
}
} }
/* clear umc status */ /* 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, 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, umc_v6_7_query_error_address(adev,
err_data, err_data,
umc_reg_offset, ch_inst, 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, .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_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, .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_addr;
uint64_t mc_umc_status, err_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 = mc_umc_status_addr =
SOC15_REG_OFFSET(UMC, 0, regMCA_UMC_UMC0_MCUMC_STATUST0); 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 + umc_inst * adev->umc.channel_inst_num +
ch_inst]; 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 && 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, 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, UECC) == 1) {
REG_GET_FIELD(mc_umc_status, MCA_UMC_UMC0_MCUMC_STATUST0, CECC) == 1)) {
uint32_t addr_lsb;
uint64_t mc_umc_addrt0;
mc_umc_addrt0 = SOC15_REG_OFFSET(UMC, 0, regMCA_UMC_UMC0_MCUMC_ADDRT0); mc_umc_addrt0 = SOC15_REG_OFFSET(UMC, 0, regMCA_UMC_UMC0_MCUMC_ADDRT0);
err_addr = RREG64_PCIE((mc_umc_addrt0 + umc_reg_offset) * 4); 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 */ /* the lowest lsb bits should be ignored */
addr_lsb = REG_GET_FIELD(mc_umc_status, MCA_UMC_UMC0_MCUMC_STATUST0, AddrLsb); addr_lsb = REG_GET_FIELD(mc_umc_status, MCA_UMC_UMC0_MCUMC_STATUST0, AddrLsb);
err_addr &= ~((0x1ULL << addr_lsb) - 1); 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 */ /* loop for all possibilities of [C6 C5] in normal address. */
if (REG_GET_FIELD(mc_umc_status, MCA_UMC_UMC0_MCUMC_STATUST0, UECC) == 1) { for (col = 0; col < UMC_V8_10_NA_COL_2BITS_POWER_OF_2_NUM; col++) {
uint64_t na_err_addr_base = err_addr & ~(0x3ULL << UMC_V8_10_NA_C5_BIT); na_err_addr = na_err_addr_base | (col << 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. */ /* Mapping normal error address to retired soc physical address. */
for (col = 0; col < UMC_V8_10_NA_COL_2BITS_POWER_OF_2_NUM; col++) { ret = umc_v8_10_swizzle_mode_na_to_pa(adev, channel_index,
na_err_addr = na_err_addr_base | (col << UMC_V8_10_NA_C5_BIT); na_err_addr, &retired_page_addr);
if (ret) {
/* Mapping normal error address to retired soc physical address. */ dev_err(adev->dev, "Failed to map pa from umc na.\n");
ret = umc_v8_10_swizzle_mode_na_to_pa(adev, channel_index, break;
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);
} }
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 = { 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_count = umc_v8_10_query_ras_error_count,
.query_ras_error_address = umc_v8_10_query_ras_error_address, .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, .hw_ops = &umc_v8_10_ras_hw_ops,
}, },
.err_cnt_init = umc_v8_10_err_cnt_init, .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, static void umc_v8_7_ecc_info_query_error_address(struct amdgpu_device *adev,
struct ras_err_data *err_data, struct ras_err_data *err_data,
uint32_t ch_inst, uint32_t ch_inst,
uint32_t umc_inst) uint32_t umc_inst)
{ {
uint64_t mc_umc_status, err_addr, retired_page; uint64_t mc_umc_status, err_addr;
uint32_t channel_index;
uint32_t eccinfo_table_idx; uint32_t eccinfo_table_idx;
struct amdgpu_ras *ras = amdgpu_ras_get_context(adev); struct amdgpu_ras *ras = amdgpu_ras_get_context(adev);
eccinfo_table_idx = umc_inst * adev->umc.channel_inst_num + ch_inst; 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; mc_umc_status = ras->umc_ecc.ecc[eccinfo_table_idx].mca_umc_status;
if (mc_umc_status == 0) 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) if (!err_data->err_addr)
return; 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 && 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, UECC) == 1) {
REG_GET_FIELD(mc_umc_status, MCA_UMC_UMC0_MCUMC_STATUST0, CECC) == 1)) {
err_addr = ras->umc_ecc.ecc[eccinfo_table_idx].mca_umc_addr; 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); err_addr = REG_GET_FIELD(err_addr, MCA_UMC_UMC0_MCUMC_ADDRT0, ErrorAddr);
/* translate umc channel address to soc pa, 3 parts are included */ umc_v8_7_convert_error_address(adev, err_data, err_addr,
retired_page = ADDR_OF_4KB_BLOCK(err_addr) | ch_inst, umc_inst);
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);
} }
} }
@@ -324,14 +330,12 @@ static void umc_v8_7_query_error_address(struct amdgpu_device *adev,
uint32_t umc_inst) uint32_t umc_inst)
{ {
uint32_t lsb, mc_umc_status_addr; uint32_t lsb, mc_umc_status_addr;
uint64_t mc_umc_status, err_addr, retired_page, mc_umc_addrt0; uint64_t mc_umc_status, err_addr, mc_umc_addrt0;
uint32_t channel_index = adev->umc.channel_idx_tbl[umc_inst * adev->umc.channel_inst_num + ch_inst];
mc_umc_status_addr = mc_umc_status_addr =
SOC15_REG_OFFSET(UMC, 0, mmMCA_UMC_UMC0_MCUMC_STATUST0); SOC15_REG_OFFSET(UMC, 0, mmMCA_UMC_UMC0_MCUMC_STATUST0);
mc_umc_addrt0 = mc_umc_addrt0 =
SOC15_REG_OFFSET(UMC, 0, mmMCA_UMC_UMC0_MCUMC_ADDRT0); SOC15_REG_OFFSET(UMC, 0, mmMCA_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) if (mc_umc_status == 0)
@@ -343,10 +347,9 @@ static void umc_v8_7_query_error_address(struct amdgpu_device *adev,
return; 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 && 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, UECC) == 1) {
REG_GET_FIELD(mc_umc_status, MCA_UMC_UMC0_MCUMC_STATUST0, CECC) == 1)) {
err_addr = RREG64_PCIE((mc_umc_addrt0 + umc_reg_offset) * 4); err_addr = RREG64_PCIE((mc_umc_addrt0 + umc_reg_offset) * 4);
/* the lowest lsb bits should be ignored */ /* 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 = REG_GET_FIELD(err_addr, MCA_UMC_UMC0_MCUMC_ADDRT0, ErrorAddr);
err_addr &= ~((0x1ULL << lsb) - 1); err_addr &= ~((0x1ULL << lsb) - 1);
/* translate umc channel address to soc pa, 3 parts are included */ umc_v8_7_convert_error_address(adev, err_data, err_addr,
retired_page = ADDR_OF_4KB_BLOCK(err_addr) | ch_inst, umc_inst);
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);
} }
/* clear umc status */ /* 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 | << SDMA0_QUEUE0_RB_CNTL__RB_SIZE__SHIFT |
q->vmid << SDMA0_QUEUE0_RB_CNTL__RB_VMID__SHIFT | q->vmid << SDMA0_QUEUE0_RB_CNTL__RB_VMID__SHIFT |
1 << SDMA0_QUEUE0_RB_CNTL__RPTR_WRITEBACK_ENABLE__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 = lower_32_bits(q->queue_address >> 8);
m->sdmax_rlcx_rb_base_hi = upper_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]; hw_params.fb[i] = &fb_info->fb[i];
switch (adev->ip_versions[DCE_HWIP][0]) { 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.dpia_supported = true;
hw_params.disable_dpia = adev->dm.dc->debug.dpia_debug.bits.disable_dpia; hw_params.disable_dpia = adev->dm.dc->debug.dpia_debug.bits.disable_dpia;
break; 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 * We also need vupdate irq for the actual core vblank handling
* at end of vblank. * at end of vblank.
*/ */
dm_set_vupdate_irq(new_state->base.crtc, true); WARN_ON(dm_set_vupdate_irq(new_state->base.crtc, true) != 0);
drm_crtc_vblank_get(new_state->base.crtc); WARN_ON(drm_crtc_vblank_get(new_state->base.crtc) != 0);
DRM_DEBUG_DRIVER("%s: crtc=%u VRR off->on: Get vblank ref\n", DRM_DEBUG_DRIVER("%s: crtc=%u VRR off->on: Get vblank ref\n",
__func__, new_state->base.crtc->base.id); __func__, new_state->base.crtc->base.id);
} else if (old_vrr_active && !new_vrr_active) { } else if (old_vrr_active && !new_vrr_active) {
/* Transition VRR active -> inactive: /* Transition VRR active -> inactive:
* Allow vblank irq disable again for fixed refresh rate. * 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_crtc_vblank_put(new_state->base.crtc);
DRM_DEBUG_DRIVER("%s: crtc=%u VRR on->off: Drop vblank ref\n", DRM_DEBUG_DRIVER("%s: crtc=%u VRR on->off: Drop vblank ref\n",
__func__, new_state->base.crtc->base.id); __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); 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 * Enable interrupts for CRTCs that are newly enabled or went through
* a modeset. It was intentionally deferred until after the front end * 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) { for_each_oldnew_crtc_in_state(state, crtc, old_crtc_state, new_crtc_state, i) {
struct amdgpu_crtc *acrtc = to_amdgpu_crtc(crtc); struct amdgpu_crtc *acrtc = to_amdgpu_crtc(crtc);
#ifdef CONFIG_DEBUG_FS #ifdef CONFIG_DEBUG_FS
bool configure_crc = false;
enum amdgpu_dm_pipe_crc_source cur_crc_src; enum amdgpu_dm_pipe_crc_source cur_crc_src;
#if defined(CONFIG_DRM_AMD_SECURE_DISPLAY) #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 #endif
spin_lock_irqsave(&adev_to_drm(adev)->event_lock, flags); spin_lock_irqsave(&adev_to_drm(adev)->event_lock, flags);
cur_crc_src = acrtc->dm_irq_params.crc_src; cur_crc_src = acrtc->dm_irq_params.crc_src;
spin_unlock_irqrestore(&adev_to_drm(adev)->event_lock, flags); spin_unlock_irqrestore(&adev_to_drm(adev)->event_lock, flags);
#endif #endif
dm_new_crtc_state = to_dm_crtc_state(new_crtc_state);
if (new_crtc_state->active && if (new_crtc_state->active &&
(!old_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); dc_stream_retain(dm_new_crtc_state->stream);
acrtc->dm_irq_params.stream = dm_new_crtc_state->stream; acrtc->dm_irq_params.stream = dm_new_crtc_state->stream;
manage_dm_interrupts(adev, acrtc, true); 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 #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 * Frontend may have changed so reapply the CRC capture
* settings for the stream. * 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)) { if (amdgpu_dm_is_valid_crc_source(cur_crc_src)) {
configure_crc = true;
#if defined(CONFIG_DRM_AMD_SECURE_DISPLAY) #if defined(CONFIG_DRM_AMD_SECURE_DISPLAY)
if (amdgpu_dm_crc_window_is_activated(crtc)) { if (amdgpu_dm_crc_window_is_activated(crtc)) {
spin_lock_irqsave(&adev_to_drm(adev)->event_lock, flags); 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); spin_unlock_irqrestore(&adev_to_drm(adev)->event_lock, flags);
} }
#endif #endif
}
if (configure_crc)
if (amdgpu_dm_crtc_configure_crc_source( if (amdgpu_dm_crtc_configure_crc_source(
crtc, dm_new_crtc_state, cur_crc_src)) crtc, dm_new_crtc_state, cur_crc_src))
DRM_DEBUG_DRIVER("Failed to configure crc source"); DRM_DEBUG_DRIVER("Failed to configure crc source");
}
#endif #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 #endif
for_each_oldnew_crtc_in_state(state, crtc, old_crtc_state, new_crtc_state, i) { 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 */ /* Run this here since we want to validate the streams we created */
ret = drm_atomic_helper_check_planes(dev, state); ret = drm_atomic_helper_check_planes(dev, state);
if (ret) { 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) 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; return;
}
if (link->type == dc_connection_none) if (link->type == dc_connection_none) {
link->psr_settings.psr_feature_enabled = false;
return; return;
}
if (link->dpcd_caps.psr_info.psr_version == 0) { if (link->dpcd_caps.psr_info.psr_version == 0) {
link->psr_settings.psr_version = DC_PSR_VERSION_UNSUPPORTED; link->psr_settings.psr_version = DC_PSR_VERSION_UNSUPPORTED;

View File

@@ -51,13 +51,6 @@
#define LAST_RECORD_TYPE 0xff #define LAST_RECORD_TYPE 0xff
#define SMU9_SYSPLL0_ID 0 #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, static enum bp_result get_gpio_i2c_info(struct bios_parser *bp,
struct atom_i2c_record *record, struct atom_i2c_record *record,
struct graphics_object_i2c_info *info); 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) { } else if (dispclk_wdivider == 127 && current_dispclk_wdivider != 127) {
REG_UPDATE(DENTIST_DISPCLK_CNTL, REG_UPDATE(DENTIST_DISPCLK_CNTL,
DENTIST_DISPCLK_WDIVIDER, 126); 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++) { 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 pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i];
struct dccg *dccg = clk_mgr->base.ctx->dc->res_pool->dccg; 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, REG_UPDATE(DENTIST_DISPCLK_CNTL,
DENTIST_DISPCLK_WDIVIDER, dispclk_wdivider); 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, REG_UPDATE(DENTIST_DISPCLK_CNTL,
DENTIST_DPPCLK_WDIVIDER, dppclk_wdivider); DENTIST_DPPCLK_WDIVIDER, dppclk_wdivider);
REG_WAIT(DENTIST_DISPCLK_CNTL, DENTIST_DPPCLK_CHG_DONE, 1, 5, 100); 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) if (!clk_mgr->smu_present)
return; 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[15:0] = 8/9/0 for Z8/Z9/disallow -> existing bits
// Arg[16] = Disallow Z9 -> new bit // Arg[16] = Disallow Z9 -> new bit
switch (support) { switch (support) {
case DCN_ZSTATE_SUPPORT_ALLOW: case DCN_ZSTATE_SUPPORT_ALLOW:
msg_id = VBIOSSMC_MSG_AllowZstatesEntry; msg_id = VBIOSSMC_MSG_AllowZstatesEntry;
param = 9; param = (1 << 10) | (1 << 9) | (1 << 8);
break; break;
case DCN_ZSTATE_SUPPORT_DISALLOW: case DCN_ZSTATE_SUPPORT_DISALLOW:
msg_id = VBIOSSMC_MSG_AllowZstatesEntry; msg_id = VBIOSSMC_MSG_AllowZstatesEntry;
param = 8; param = 0;
break; break;
case DCN_ZSTATE_SUPPORT_ALLOW_Z10_ONLY: case DCN_ZSTATE_SUPPORT_ALLOW_Z10_ONLY:
msg_id = VBIOSSMC_MSG_AllowZstatesEntry; msg_id = VBIOSSMC_MSG_AllowZstatesEntry;
param = 0x00010008; param = (1 << 10);
break; break;
default: //DCN_ZSTATE_SUPPORT_UNKNOWN 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); struct clk_mgr_internal *clk_mgr = TO_CLK_MGR_INTERNAL(clk_mgr_base);
unsigned int num_levels; 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)); memset(&(clk_mgr_base->clks), 0, sizeof(struct dc_clocks));
clk_mgr_base->clks.p_state_change_support = true; clk_mgr_base->clks.p_state_change_support = true;
@@ -180,27 +180,28 @@ void dcn32_init_clocks(struct clk_mgr *clk_mgr_base)
/* DCFCLK */ /* DCFCLK */
dcn32_init_single_clock(clk_mgr, PPCLK_DCFCLK, dcn32_init_single_clock(clk_mgr, PPCLK_DCFCLK,
&clk_mgr_base->bw_params->clk_table.entries[0].dcfclk_mhz, &clk_mgr_base->bw_params->clk_table.entries[0].dcfclk_mhz,
&num_levels); &num_entries_per_clk->num_dcfclk_levels);
num_dcfclk_levels = num_levels;
/* SOCCLK */ /* SOCCLK */
dcn32_init_single_clock(clk_mgr, PPCLK_SOCCLK, dcn32_init_single_clock(clk_mgr, PPCLK_SOCCLK,
&clk_mgr_base->bw_params->clk_table.entries[0].socclk_mhz, &clk_mgr_base->bw_params->clk_table.entries[0].socclk_mhz,
&num_levels); &num_entries_per_clk->num_socclk_levels);
/* DTBCLK */ /* DTBCLK */
if (!clk_mgr->base.ctx->dc->debug.disable_dtb_ref_clk_switch) if (!clk_mgr->base.ctx->dc->debug.disable_dtb_ref_clk_switch)
dcn32_init_single_clock(clk_mgr, PPCLK_DTBCLK, dcn32_init_single_clock(clk_mgr, PPCLK_DTBCLK,
&clk_mgr_base->bw_params->clk_table.entries[0].dtbclk_mhz, &clk_mgr_base->bw_params->clk_table.entries[0].dtbclk_mhz,
&num_levels); &num_entries_per_clk->num_dtbclk_levels);
num_dtbclk_levels = num_levels;
/* DISPCLK */ /* DISPCLK */
dcn32_init_single_clock(clk_mgr, PPCLK_DISPCLK, dcn32_init_single_clock(clk_mgr, PPCLK_DISPCLK,
&clk_mgr_base->bw_params->clk_table.entries[0].dispclk_mhz, &clk_mgr_base->bw_params->clk_table.entries[0].dispclk_mhz,
&num_levels); &num_entries_per_clk->num_dispclk_levels);
num_dispclk_levels = num_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; clk_mgr->dpm_present = true;
if (clk_mgr_base->ctx->dc->debug.min_disp_clk_khz) { 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) if (enter_display_off == safe_to_lower)
dcn30_smu_set_num_of_displays(clk_mgr, display_count); 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) 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 = (new_clocks->dcfclk_khz > (dc->debug.force_min_dcfclk_mhz * 1000)) ?
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.socclk_khz = new_clocks->socclk_khz;
clk_mgr_base->clks.prev_p_state_change_support = clk_mgr_base->clks.p_state_change_support; clk_mgr_base->clks.prev_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; clk_mgr_base->clks.prev_num_ways = clk_mgr_base->clks.num_ways;
if (clk_mgr_base->clks.num_ways != new_clocks->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); 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); 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)) { 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; clk_mgr_base->clks.p_state_change_support = p_state_change_support;
/* to disable P-State switching, set UCLK min = max */ /* to disable P-State switching, set UCLK min = max */
if (!clk_mgr_base->clks.p_state_change_support) if (!clk_mgr_base->clks.p_state_change_support)
dcn32_smu_set_hard_min_by_freq(clk_mgr, PPCLK_UCLK, 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) && /* Always update saved value, even if new value not set due to P-State switching unsupported. Also check safe_to_lower for FCLK */
clk_mgr_base->ctx->dce_version != DCN_VERSION_3_21) { if (safe_to_lower && (clk_mgr_base->clks.fclk_p_state_change_support != clk_mgr_base->clks.fclk_prev_p_state_change_support)) {
clk_mgr_base->clks.fclk_p_state_change_support = fclk_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 && update_fclk) {
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 */
/* 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);
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 */ /* 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; 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 */ /* 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 && if (clk_mgr_base->clks.p_state_change_support &&
(update_uclk || !clk_mgr_base->clks.prev_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)); 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 && 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) {
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)); khz_to_mhz_ceil(clk_mgr_base->clks.dramclk_khz));
else else
dcn32_smu_set_hard_min_by_freq(clk_mgr, PPCLK_UCLK, 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 { } else {
dcn32_smu_set_hard_min_by_freq(clk_mgr, PPCLK_UCLK, dcn32_smu_set_hard_min_by_freq(clk_mgr, PPCLK_UCLK,
clk_mgr_base->bw_params->clk_table.entries[0].memclk_mhz); 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; return;
dcn30_smu_set_hard_max_by_freq(clk_mgr, PPCLK_UCLK, 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 */ /* Get current memclk states, update bounding box */
static void dcn32_get_memclk_states_from_smu(struct clk_mgr *clk_mgr_base) 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_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; unsigned int num_levels;
if (!clk_mgr->smu_present) if (!clk_mgr->smu_present)
return; return;
/* Refresh memclk states */ /* Refresh memclk and fclk states */
dcn32_init_single_clock(clk_mgr, PPCLK_UCLK, dcn32_init_single_clock(clk_mgr, PPCLK_UCLK,
&clk_mgr_base->bw_params->clk_table.entries[0].memclk_mhz, &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; clk_mgr_base->bw_params->clk_table.num_entries = num_levels ? num_levels : 1;
if (clk_mgr->dpm_present && !num_levels) 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; int i, k, l;
struct dc_stream_state *dc_streams[MAX_STREAMS] = {0}; struct dc_stream_state *dc_streams[MAX_STREAMS] = {0};
struct dc_state *old_state; struct dc_state *old_state;
bool subvp_prev_use = false;
dc_z10_restore(dc); dc_z10_restore(dc);
dc_allow_idle_optimizations(dc, false); 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++) for (i = 0; i < context->stream_count; i++)
dc_streams[i] = context->streams[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); 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); result = dc->hwss.apply_ctx_to_hw(dc, context);
if (result != DC_OK) { 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.interdependent_update_lock(dc, context, false);
dc->hwss.post_unlock_program_front_end(dc, context); 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++) { for (i = 0; i < context->stream_count; i++) {
const struct dc_link *link = context->streams[i]->link; 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_resource_state_copy_construct(
dc->current_state, context); 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 */ /*remove old surfaces from context */
if (!dc_rem_all_planes_for_stream(dc, stream, 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, /* Since phantom pipe programming is moved to post_unlock_program_front_end,
* move the SubVP lock to after the phantom pipes have been setup * move the SubVP lock to after the phantom pipes have been setup
*/ */
if (dc->hwss.subvp_pipe_control_lock) if (should_lock_all_pipes && dc->hwss.interdependent_update_lock) {
dc->hwss.subvp_pipe_control_lock(dc, context, false, should_lock_all_pipes, NULL, subvp_prev_use); 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; return;
} }
@@ -3495,6 +3526,9 @@ static void commit_planes_for_stream(struct dc *dc,
if (update_type != UPDATE_TYPE_FAST) if (update_type != UPDATE_TYPE_FAST)
dc->hwss.post_unlock_program_front_end(dc, context); 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 (update_type != UPDATE_TYPE_FAST)
if (dc->hwss.commit_subvp_config) 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); struct dc_stream_status *cur_stream_status = stream_get_status(dc->current_state, stream);
bool force_minimal_pipe_splitting = false; bool force_minimal_pipe_splitting = false;
uint32_t i;
*is_plane_addition = false; *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; 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); struct dc_state *transition_context = dc_create_state(dc);
enum pipe_split_policy tmp_mpc_policy; enum pipe_split_policy tmp_mpc_policy;
bool temp_dynamic_odm_policy; bool temp_dynamic_odm_policy;
bool temp_subvp_policy;
enum dc_status ret = DC_ERROR_UNEXPECTED; enum dc_status ret = DC_ERROR_UNEXPECTED;
unsigned int i, j; 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; temp_dynamic_odm_policy = dc->debug.enable_single_display_2to1_odm_policy;
dc->debug.enable_single_display_2to1_odm_policy = false; 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); dc_resource_state_copy_construct(transition_base_context, transition_context);
//commit minimal state //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.pipe_split_policy = tmp_mpc_policy;
dc->debug.enable_single_display_2to1_odm_policy = temp_dynamic_odm_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) { if (ret != DC_OK) {
/*this should never happen*/ /*this should never happen*/
@@ -4586,6 +4656,37 @@ enum dc_status dc_process_dmub_set_mst_slots(const struct dc *dc,
return DC_OK; 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_disable_accelerated_mode - disable accelerated mode
* @dc: dc structure * @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) { 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); dm_helpers_init_panel_settings(dc_ctx, &link->panel_config, sink);
// Override dc_panel_config if system has specific settings // Override dc_panel_config if system has specific settings
dm_helpers_override_panel_settings(dc_ctx, &link->panel_config); 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)) if (!dc_get_edp_link_panel_inst(dc, link, &panel_inst))
return false; 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 // Don't enter PSR if panel is not connected
return false; return false;
} }
@@ -3375,8 +3378,8 @@ bool dc_link_setup_psr(struct dc_link *link,
case FAMILY_YELLOW_CARP: case FAMILY_YELLOW_CARP:
case AMDGPU_FAMILY_GC_10_3_6: case AMDGPU_FAMILY_GC_10_3_6:
case AMDGPU_FAMILY_GC_11_0_1: case AMDGPU_FAMILY_GC_11_0_1:
if(!dc->debug.disable_z10) if (dc->debug.disable_z10)
psr_context->psr_level.bits.SKIP_CRTC_DISABLE = false; psr_context->psr_level.bits.SKIP_CRTC_DISABLE = true;
break; break;
default: default:
psr_context->psr_level.bits.SKIP_CRTC_DISABLE = true; 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; 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( enum dc_status dpcd_set_lane_settings(
struct dc_link *link, struct dc_link *link,
const struct link_training_settings *link_training_setting, 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); link_training_setting->link_settings.lane_count);
if (is_repeater(link_training_setting, offset)) { 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" 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", " 0x%X VS set = %x PE set = %x max VS Reached = %x max PE Reached = %x\n",
__func__, __func__,
@@ -985,14 +992,6 @@ enum dc_status dpcd_set_lane_settings(
link_training_setting->dpcd_lane_settings[0].bits.MAX_PRE_EMPHASIS_REACHED); link_training_setting->dpcd_lane_settings[0].bits.MAX_PRE_EMPHASIS_REACHED);
} else { } 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", 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__, __func__,
lane0_set_address, 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; result = DP_128b_132b_LT_FAILED;
} else { } else {
dp_set_hw_lane_settings(link, link_res, lt_settings, DPRX); 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++; 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)) { (dp_convert_to_count(link->dpcd_caps.lttpr_caps.phy_repeater_cnt) == 0)) {
ASSERT(0); ASSERT(0);
link->dpcd_caps.lttpr_caps.phy_repeater_cnt = 0x80; 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. */ /* 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) if (is_lttpr_present)
CONN_DATA_DETECT(link, lttpr_dpcd_data, sizeof(lttpr_dpcd_data), "LTTPR Caps: "); 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; 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) { } else if (link->dc->debug.lttpr_mode_override == LTTPR_MODE_NON_LTTPR) {
*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) 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; return LTTPR_MODE_NON_LTTPR;
if (vbios_lttpr_aware) { 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; 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; return LTTPR_MODE_TRANSPARENT;
}
} }
if (link->dc->config.allow_lttpr_non_transparent_mode.bits.DP1_4A && 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; return LTTPR_MODE_NON_TRANSPARENT;
}
DC_LOG_DC("chose LTTPR_MODE_NON_LTTPR.\n");
return LTTPR_MODE_NON_LTTPR; return LTTPR_MODE_NON_LTTPR;
} }
enum lttpr_mode dp_decide_128b_132b_lttpr_mode(struct dc_link *link) 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) 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( cmd.cable_id.data.input.phy_inst = resource_transmitter_to_phy_idx(
link->dc, link->link_enc->transmitter); link->dc, link->link_enc->transmitter);
if (dc_dmub_srv_cmd_with_reply_data(link->ctx->dmub_srv, &cmd) && 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; 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; 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) || lttpr_present = dp_is_lttpr_present(link) ||
(!vbios_lttpr_interop || !link->dc->caps.extended_aux_timeout_support); (!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 /* 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. * 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" * Per VESA eDP spec, "The DPCD revision for eDP v1.4 is 13h"
*/ */
if (link->dpcd_caps.dpcd_rev.raw >= DPCD_REV_13 && 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)) { link->reported_link_cap.link_rate == LINK_RATE_UNKNOWN)) {
// Read DPCD 00010h - 0001Fh 16 bytes at one shot // Read DPCD 00010h - 0001Fh 16 bytes at one shot
core_link_read_dpcd(link, DP_SUPPORTED_LINK_RATES, 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 ASSERT(link || crtc_timing); // invalid input
if (link->dpcd_caps.edp_supported_link_rates_count == 0 || 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; return false;

View File

@@ -1747,7 +1747,6 @@ bool dc_remove_plane_from_context(
for (i = 0; i < stream_status->plane_count; i++) { for (i = 0; i < stream_status->plane_count; i++) {
if (stream_status->plane_states[i] == plane_state) { if (stream_status->plane_states[i] == plane_state) {
dc_plane_state_release(stream_status->plane_states[i]); dc_plane_state_release(stream_status->plane_states[i]);
break; break;
} }
@@ -3683,4 +3682,56 @@ bool is_h_timing_divisible_by_2(struct dc_stream_state *stream)
(stream->timing.h_sync_width % 2 == 0); (stream->timing.h_sync_width % 2 == 0);
} }
return divisible; 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->hwss.set_cursor_attribute(pipe_ctx);
dc_send_update_cursor_info_to_dmu(pipe_ctx, i);
if (dc->hwss.set_cursor_sdr_white_level) if (dc->hwss.set_cursor_sdr_white_level)
dc->hwss.set_cursor_sdr_white_level(pipe_ctx); 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->hwss.set_cursor_position(pipe_ctx);
dc_send_update_cursor_info_to_dmu(pipe_ctx, i);
} }
if (pipe_to_program) 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 */ /* 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 (stream->writeback_info[i].wb_enabled) {
if (i != j) if (j < i)
/* trim the array */ /* trim the array */
stream->writeback_info[j] = stream->writeback_info[i]; stream->writeback_info[j] = stream->writeback_info[i];
j++; j++;

View File

@@ -47,7 +47,7 @@ struct aux_payload;
struct set_config_cmd_payload; struct set_config_cmd_payload;
struct dmub_notification; struct dmub_notification;
#define DC_VER "3.2.205" #define DC_VER "3.2.207"
#define MAX_SURFACES 3 #define MAX_SURFACES 3
#define MAX_PLANES 6 #define MAX_PLANES 6
@@ -821,7 +821,6 @@ struct dc_debug_options {
/* Enable dmub aux for legacy ddc */ /* Enable dmub aux for legacy ddc */
bool enable_dmub_aux_for_legacy_ddc; bool enable_dmub_aux_for_legacy_ddc;
bool disable_fams; bool disable_fams;
bool optimize_edp_link_rate; /* eDP ILR */
/* FEC/PSR1 sequence enable delay in 100us */ /* FEC/PSR1 sequence enable delay in 100us */
uint8_t fec_enable_delay_in100us; uint8_t fec_enable_delay_in100us;
bool enable_driver_sequence_debug; bool enable_driver_sequence_debug;
@@ -1192,6 +1191,8 @@ struct dc_plane_state {
enum dc_irq_source irq_source; enum dc_irq_source irq_source;
struct kref refcount; struct kref refcount;
struct tg_color visual_confirm_color; struct tg_color visual_confirm_color;
bool is_statically_allocated;
}; };
struct dc_plane_info { 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_alloc_slots,
uint8_t *mst_slots_in_use); 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 * DSC Interfaces
******************************************************************************/ ******************************************************************************/

View File

@@ -30,6 +30,7 @@
#include "dc_hw_types.h" #include "dc_hw_types.h"
#include "core_types.h" #include "core_types.h"
#include "../basics/conversion.h" #include "../basics/conversion.h"
#include "cursor_reg_cache.h"
#define CTX dc_dmub_srv->ctx #define CTX dc_dmub_srv->ctx
#define DC_LOGGER CTX->logger #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 // Store the original watermark value for this SubVP config so we can lower it when the
// MCLK switch starts // MCLK switch starts
wm_val_refclk = context->bw_ctx.bw.dcn.watermarks.a.cstate_pstate.pstate_change_ns * 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; 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_cw0_enabled,
diag_data.is_cw6_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_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_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_ */ #endif /* _DMUB_DC_SRV_H_ */

View File

@@ -138,6 +138,10 @@ struct dc_panel_config {
bool disable_dsc_edp; bool disable_dsc_edp;
unsigned int force_dsc_edp_policy; unsigned int force_dsc_edp_policy;
} dsc; } dsc;
/* eDP ILR */
struct ilr {
bool optimize_edp_link_rate; /* eDP ILR */
} ilr;
}; };
/* /*
* A link contains one or more sinks and their connected status. * 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_ENGINE_ACQUIRE:
case AUX_RET_ERROR_UNKNOWN: case AUX_RET_ERROR_UNKNOWN:
default: 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; goto fail;
} }
} }
@@ -953,14 +949,11 @@ bool dce_aux_transfer_with_retries(struct ddc_service *ddc,
fail: fail:
DC_TRACE_LEVEL_MESSAGE(DAL_TRACE_LEVEL_ERROR, DC_TRACE_LEVEL_MESSAGE(DAL_TRACE_LEVEL_ERROR,
LOG_FLAG_Error_I2cAux, LOG_FLAG_Error_I2cAux,
"dce_aux_transfer_with_retries: FAILURE"); "%s: Failure: operation_result=%d",
__func__,
(int)operation_result);
if (!payload_reply) if (!payload_reply)
payload->reply = NULL; 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; return false;
} }

View File

@@ -469,6 +469,7 @@ void dpp1_set_cursor_position(
REG_UPDATE(CURSOR0_CONTROL, REG_UPDATE(CURSOR0_CONTROL,
CUR0_ENABLE, cur_en); CUR0_ENABLE, cur_en);
dpp_base->pos.cur0_ctl.bits.cur0_enable = cur_en;
} }
void dpp1_cnv_set_optional_cursor_attributes( 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"); DC_SYNC_INFO("Setting up OTG reset trigger\n");
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;
opp = grouped_pipes[i]->stream_res.opp; opp = grouped_pipes[i]->stream_res.opp;
tg = grouped_pipes[i]->stream_res.tg; tg = grouped_pipes[i]->stream_res.tg;
tg->funcs->get_otg_active_size(tg, &width, &height); 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++) { for (i = 0; i < group_size; i++) {
if (grouped_pipes[i]->stream == NULL) if (grouped_pipes[i]->stream == NULL)
continue; continue;
if (grouped_pipes[i]->stream && grouped_pipes[i]->stream->mall_stream_config.type == SUBVP_PHANTOM)
continue;
grouped_pipes[i]->stream->vblank_synchronized = false; 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->funcs->enable_reset_trigger(
grouped_pipes[i]->stream_res.tg, grouped_pipes[i]->stream_res.tg,
grouped_pipes[0]->stream_res.tg->inst); grouped_pipes[0]->stream_res.tg->inst);
}
DC_SYNC_INFO("Waiting for trigger\n"); DC_SYNC_INFO("Waiting for trigger\n");
@@ -2268,12 +2279,21 @@ void dcn10_enable_timing_synchronization(
* synchronized. Look at last pipe programmed to reset. * synchronized. Look at last pipe programmed to reset.
*/ */
wait_for_reset_trigger_to_occur(dc_ctx, grouped_pipes[1]->stream_res.tg); if (grouped_pipes[1]->stream && grouped_pipes[1]->stream->mall_stream_config.type != SUBVP_PHANTOM)
for (i = 1; i < group_size; i++) wait_for_reset_trigger_to_occur(dc_ctx, grouped_pipes[1]->stream_res.tg);
grouped_pipes[i]->stream_res.tg->funcs->disable_reset_trigger(
grouped_pipes[i]->stream_res.tg);
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->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; opp = grouped_pipes[i]->stream_res.opp;
tg = grouped_pipes[i]->stream_res.tg; tg = grouped_pipes[i]->stream_res.tg;
tg->funcs->get_otg_active_size(tg, &width, &height); tg->funcs->get_otg_active_size(tg, &width, &height);
@@ -3005,6 +3025,7 @@ void dcn10_prepare_bandwidth(
{ {
struct dce_hwseq *hws = dc->hwseq; struct dce_hwseq *hws = dc->hwseq;
struct hubbub *hubbub = dc->res_pool->hubbub; struct hubbub *hubbub = dc->res_pool->hubbub;
int min_fclk_khz, min_dcfclk_khz, socclk_khz;
if (dc->debug.sanity_checks) if (dc->debug.sanity_checks)
hws->funcs.verify_allow_pstate_change_high(dc); 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) { if (dc->debug.pplib_wm_report_mode == WM_REPORT_OVERRIDE) {
DC_FP_START(); 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(); DC_FP_END();
dcn_bw_notify_pplib_of_wm_ranges(
dc, min_fclk_khz, min_dcfclk_khz, socclk_khz);
} }
if (dc->debug.sanity_checks) if (dc->debug.sanity_checks)
@@ -3041,6 +3065,7 @@ void dcn10_optimize_bandwidth(
{ {
struct dce_hwseq *hws = dc->hwseq; struct dce_hwseq *hws = dc->hwseq;
struct hubbub *hubbub = dc->res_pool->hubbub; struct hubbub *hubbub = dc->res_pool->hubbub;
int min_fclk_khz, min_dcfclk_khz, socclk_khz;
if (dc->debug.sanity_checks) if (dc->debug.sanity_checks)
hws->funcs.verify_allow_pstate_change_high(dc); 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) { if (dc->debug.pplib_wm_report_mode == WM_REPORT_OVERRIDE) {
DC_FP_START(); 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(); DC_FP_END();
dcn_bw_notify_pplib_of_wm_ranges(
dc, min_fclk_khz, min_dcfclk_khz, socclk_khz);
} }
if (dc->debug.sanity_checks) if (dc->debug.sanity_checks)
@@ -3344,127 +3372,6 @@ static bool dcn10_can_pipe_disable_cursor(struct pipe_ctx *pipe_ctx)
return false; 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) void dcn10_set_cursor_position(struct pipe_ctx *pipe_ctx)
{ {
struct dc_cursor_position pos_cpy = pipe_ctx->stream->cursor_position; 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; 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); 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); 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) void dcn10_set_cursor_attribute(struct pipe_ctx *pipe_ctx)
{ {
struct dc_cursor_attributes *attributes = &pipe_ctx->stream->cursor_attributes; 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->funcs->set_cursor_attributes(
pipe_ctx->plane_res.hubp, attributes); pipe_ctx->plane_res.hubp, attributes);
@@ -3810,28 +3697,14 @@ void dcn10_calc_vupdate_position(
uint32_t *start_line, uint32_t *start_line,
uint32_t *end_line) uint32_t *end_line)
{ {
const struct dc_crtc_timing *dc_crtc_timing = &pipe_ctx->stream->timing; const struct dc_crtc_timing *timing = &pipe_ctx->stream->timing;
int vline_int_offset_from_vupdate = int vupdate_pos = dc->hwss.get_vupdate_offset_from_vsync(pipe_ctx);
pipe_ctx->stream->periodic_interrupt.lines_offset;
int vupdate_offset_from_vsync = dc->hwss.get_vupdate_offset_from_vsync(pipe_ctx);
int start_position;
if (vline_int_offset_from_vupdate > 0) if (vupdate_pos >= 0)
vline_int_offset_from_vupdate--; *start_line = vupdate_pos - ((vupdate_pos / timing->v_total) * timing->v_total);
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;
else else
*start_line = dc_crtc_timing->v_total + start_position - 1; *start_line = vupdate_pos + ((-vupdate_pos / timing->v_total) + 1) * timing->v_total - 1;
*end_line = (*start_line + 2) % timing->v_total;
*end_line = *start_line + 2;
if (*end_line >= dc_crtc_timing->v_total)
*end_line = 2;
} }
static void dcn10_cal_vline_position( static void dcn10_cal_vline_position(
@@ -3840,23 +3713,27 @@ static void dcn10_cal_vline_position(
uint32_t *start_line, uint32_t *start_line,
uint32_t *end_line) uint32_t *end_line)
{ {
switch (pipe_ctx->stream->periodic_interrupt.ref_point) { const struct dc_crtc_timing *timing = &pipe_ctx->stream->timing;
case START_V_UPDATE: int vline_pos = pipe_ctx->stream->periodic_interrupt.lines_offset;
dcn10_calc_vupdate_position(
dc, if (pipe_ctx->stream->periodic_interrupt.ref_point == START_V_UPDATE) {
pipe_ctx, if (vline_pos > 0)
start_line, vline_pos--;
end_line); else if (vline_pos < 0)
break; vline_pos++;
case START_V_SYNC:
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 // vsync is line 0 so start_line is just the requested line offset
*start_line = pipe_ctx->stream->periodic_interrupt.lines_offset; *start_line = vline_pos;
*end_line = *start_line + 2; *end_line = (*start_line + 2) % timing->v_total;
break; } else
default:
ASSERT(0); ASSERT(0);
break;
}
} }
void dcn10_setup_periodic_interrupt( 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 /* In case of V_TOTAL_CONTROL is on, make sure OTG_V_TOTAL_MAX and
* OTG_V_TOTAL_MIN are equal to V_TOTAL. * OTG_V_TOTAL_MIN are equal to V_TOTAL.
*/ */
REG_SET(OTG_V_TOTAL_MAX, 0, optc->funcs->set_vtotal_min_max(optc, v_total, v_total);
OTG_V_TOTAL_MAX, v_total);
REG_SET(OTG_V_TOTAL_MIN, 0,
OTG_V_TOTAL_MIN, v_total);
/* v_sync_start = 0, v_sync_end = v_sync_width */ /* v_sync_start = 0, v_sync_end = v_sync_width */
v_sync_end = patched_crtc_timing.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) void optc1_lock(struct timing_generator *optc)
{ {
struct optc *optc1 = DCN10TG_FROM_TG(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, REG_SET(OTG_GLOBAL_CONTROL0, 0,
OTG_MASTER_UPDATE_LOCK_SEL, optc->inst); OTG_MASTER_UPDATE_LOCK_SEL, optc->inst);
@@ -663,12 +653,10 @@ void optc1_lock(struct timing_generator *optc)
OTG_MASTER_UPDATE_LOCK, 1); OTG_MASTER_UPDATE_LOCK, 1);
/* Should be fast, status does not update on maximus */ /* 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, REG_WAIT(OTG_MASTER_UPDATE_LOCK,
UPDATE_LOCK_STATUS, 1, UPDATE_LOCK_STATUS, 1,
1, 10); 1, 10);
}
} }
void optc1_unlock(struct timing_generator *optc) void optc1_unlock(struct timing_generator *optc)
@@ -679,16 +667,6 @@ void optc1_unlock(struct timing_generator *optc)
OTG_MASTER_UPDATE_LOCK, 0); 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, void optc1_get_position(struct timing_generator *optc,
struct crtc_position *position) struct crtc_position *position)
{ {
@@ -941,11 +919,7 @@ void optc1_set_drr(
} }
REG_SET(OTG_V_TOTAL_MAX, 0, optc->funcs->set_vtotal_min_max(optc, params->vertical_total_min - 1, params->vertical_total_max - 1);
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);
REG_UPDATE_5(OTG_V_TOTAL_CONTROL, REG_UPDATE_5(OTG_V_TOTAL_CONTROL,
OTG_V_TOTAL_MIN_SEL, 1, OTG_V_TOTAL_MIN_SEL, 1,
@@ -964,11 +938,7 @@ void optc1_set_drr(
OTG_V_TOTAL_MAX_SEL, 0, OTG_V_TOTAL_MAX_SEL, 0,
OTG_FORCE_LOCK_ON_EVENT, 0); OTG_FORCE_LOCK_ON_EVENT, 0);
REG_SET(OTG_V_TOTAL_MIN, 0, optc->funcs->set_vtotal_min_max(optc, 0, 0);
OTG_V_TOTAL_MIN, 0);
REG_SET(OTG_V_TOTAL_MAX, 0,
OTG_V_TOTAL_MAX, 0);
} }
} }
@@ -1583,11 +1553,11 @@ static const struct timing_generator_funcs dcn10_tg_funcs = {
.enable_crtc_reset = optc1_enable_crtc_reset, .enable_crtc_reset = optc1_enable_crtc_reset,
.disable_reset_trigger = optc1_disable_reset_trigger, .disable_reset_trigger = optc1_disable_reset_trigger,
.lock = optc1_lock, .lock = optc1_lock,
.is_locked = optc1_is_locked,
.unlock = optc1_unlock, .unlock = optc1_unlock,
.enable_optc_clock = optc1_enable_optc_clock, .enable_optc_clock = optc1_enable_optc_clock,
.set_drr = optc1_set_drr, .set_drr = optc1_set_drr,
.get_last_used_drr_vtotal = NULL, .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_static_screen_control = optc1_set_static_screen_control,
.set_test_pattern = optc1_set_test_pattern, .set_test_pattern = optc1_set_test_pattern,
.program_stereo = optc1_program_stereo, .program_stereo = optc1_program_stereo,

View File

@@ -654,7 +654,6 @@ void optc1_set_blank(struct timing_generator *optc,
bool enable_blanking); bool enable_blanking);
bool optc1_is_blanked(struct timing_generator *optc); bool optc1_is_blanked(struct timing_generator *optc);
bool optc1_is_locked(struct timing_generator *optc);
void optc1_program_blank_color( void optc1_program_blank_color(
struct timing_generator *optc, 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( static bool dcn10_resource_construct(
uint8_t num_virtual_links, uint8_t num_virtual_links,
struct dc *dc, struct dc *dc,
@@ -1345,6 +1360,9 @@ static bool dcn10_resource_construct(
int j; int j;
struct dc_context *ctx = dc->ctx; struct dc_context *ctx = dc->ctx;
uint32_t pipe_fuses = read_pipe_fuses(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; 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) && pool->base.pp_smu->rv_funcs.set_pme_wa_enable != NULL)
dc->debug.az_endpoint_mute_only = false; dc->debug.az_endpoint_mute_only = false;
DC_FP_START();
if (!dc->debug.disable_pplib_clock_request) if (!dc->debug.disable_pplib_clock_request) {
dcn_bw_update_from_pplib(dc); /*
* 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); dcn_bw_sync_calcs_and_dml(dc);
if (!dc->debug.disable_pplib_wm_range) { if (!dc->debug.disable_pplib_wm_range) {
dc->res_pool = &pool->base; 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; struct irq_service_init_data init_data;

View File

@@ -617,6 +617,17 @@ void hubp2_cursor_set_attributes(
CURSOR0_DST_Y_OFFSET, 0, CURSOR0_DST_Y_OFFSET, 0,
/* used to shift the cursor chunk request deadline */ /* used to shift the cursor chunk request deadline */
CURSOR0_CHUNK_HDL_ADJUST, 3); 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( void hubp2_dmdata_set_attributes(
@@ -1033,6 +1044,25 @@ void hubp2_cursor_set_position(
REG_SET(CURSOR_DST_OFFSET, 0, REG_SET(CURSOR_DST_OFFSET, 0,
CURSOR_DST_X_OFFSET, dst_x_offset); CURSOR_DST_X_OFFSET, dst_x_offset);
/* TODO Handle surface pixel formats other than 4:4:4 */ /* 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) 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++) { for (i = 0; i < dc->res_pool->pipe_count; i++) {
struct pipe_ctx *pipe = &context->res_ctx.pipe_ctx[i]; struct pipe_ctx *pipe = &context->res_ctx.pipe_ctx[i];
struct pipe_ctx *old_pipe = &dc->current_state->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) 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); 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->funcs->update_clocks(
dc->clk_mgr, dc->clk_mgr,
context, context,
@@ -2033,9 +2019,6 @@ void dcn20_optimize_bandwidth(
pipe_ctx->dlg_regs.optimized_min_dst_y_next_start); 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( 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, .enable_optc_clock = optc1_enable_optc_clock,
.set_drr = optc1_set_drr, .set_drr = optc1_set_drr,
.get_last_used_drr_vtotal = optc2_get_last_used_drr_vtotal, .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, .set_static_screen_control = optc1_set_static_screen_control,
.program_stereo = optc1_program_stereo, .program_stereo = optc1_program_stereo,
.is_stereo_left_eye = optc1_is_stereo_left_eye, .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) void dcn21_dchvm_init(struct hubbub *hubbub)
{ {
struct dcn20_hubbub *hubbub1 = TO_DCN20_HUBBUB(hubbub); struct dcn20_hubbub *hubbub1 = TO_DCN20_HUBBUB(hubbub);
uint32_t riommu_active, prefetch_done; uint32_t riommu_active;
int i; int i;
REG_GET(DCHVM_RIOMMU_STAT0, HOSTVM_PREFETCH_DONE, &prefetch_done);
if (prefetch_done) {
hubbub->riommu_active = true;
return;
}
//Init DCHVM block //Init DCHVM block
REG_UPDATE(DCHVM_CTRL0, HOSTVM_INIT_REQ, 1); 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, .usbc_combo_phy_reset_wa = true,
.dmub_command_table = true, .dmub_command_table = true,
.use_max_lb = true, .use_max_lb = true,
.optimize_edp_link_rate = true
}; };
static const struct dc_debug_options debug_defaults_diags = { 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 .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 { enum dcn20_clk_src_array_id {
DCN20_CLK_SRC_PLL0, DCN20_CLK_SRC_PLL0,
DCN20_CLK_SRC_PLL1, 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; 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 CTX ctx
#define REG(reg_name) \ #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, .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, .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, .update_bw_bounding_box = dcn21_update_bw_bounding_box,
.get_panel_config_defaults = dcn21_get_panel_config_defaults,
}; };
static bool dcn21_resource_construct( static bool dcn21_resource_construct(

View File

@@ -372,6 +372,10 @@ void dpp3_set_cursor_attributes(
REG_UPDATE(CURSOR0_COLOR1, REG_UPDATE(CURSOR0_COLOR1,
CUR0_COLOR1, 0xFFFFFFFF); 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, .enable_crtc_reset = optc1_enable_crtc_reset,
.disable_reset_trigger = optc1_disable_reset_trigger, .disable_reset_trigger = optc1_disable_reset_trigger,
.lock = optc3_lock, .lock = optc3_lock,
.is_locked = optc1_is_locked,
.unlock = optc1_unlock, .unlock = optc1_unlock,
.lock_doublebuffer_enable = optc3_lock_doublebuffer_enable, .lock_doublebuffer_enable = optc3_lock_doublebuffer_enable,
.lock_doublebuffer_disable = optc3_lock_doublebuffer_disable, .lock_doublebuffer_disable = optc3_lock_doublebuffer_disable,
.enable_optc_clock = optc1_enable_optc_clock, .enable_optc_clock = optc1_enable_optc_clock,
.set_drr = optc1_set_drr, .set_drr = optc1_set_drr,
.get_last_used_drr_vtotal = optc2_get_last_used_drr_vtotal, .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, .set_static_screen_control = optc1_set_static_screen_control,
.program_stereo = optc1_program_stereo, .program_stereo = optc1_program_stereo,
.is_stereo_left_eye = optc1_is_stereo_left_eye, .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_h_sync_width = 4;
optc1->min_v_sync_width = 1; optc1->min_v_sync_width = 1;
} }

View File

@@ -1655,6 +1655,9 @@ noinline bool dcn30_internal_validate_bw(
if (!pipes) if (!pipes)
return false; 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); 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); 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) if (repopulate_pipes)
pipe_cnt = dc->res_pool->funcs->populate_dml_pipes(dc, context, pipes, fast_validate); pipe_cnt = dc->res_pool->funcs->populate_dml_pipes(dc, context, pipes, fast_validate);
context->bw_ctx.dml.vba.VoltageLevel = vlevel;
*vlevel_out = vlevel; *vlevel_out = vlevel;
*pipe_cnt_out = pipe_cnt; *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; vmid->masks = &vmid_masks;
} }
hubbub3->num_vmid = res_cap_dcn301.num_vmid; hubbub3->num_vmid = res_cap_dcn301.num_vmid;
return &hubbub3->base; 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_back_porch;
uint32_t h_width; uint32_t h_width;
uint32_t v_height; uint32_t v_height;
unsigned long long v_freq; uint64_t v_freq;
uint8_t misc0 = 0; uint8_t misc0 = 0;
uint8_t misc1 = 0; uint8_t misc1 = 0;
uint8_t hsp; 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; 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; hsp = hw_crtc_timing.flags.HSYNC_POSITIVE_POLARITY ? 0 : 0x80;
vsp = hw_crtc_timing.flags.VSYNC_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 /* 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); struct dcn31_hpo_dp_stream_encoder *enc3 = DCN3_1_HPO_DP_STREAM_ENC_FROM_HPO_STREAM_ENC(enc);
uint32_t dmdata_packet_enabled = 0; 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->funcs->update_generic_info_packet(
enc->vpg, enc->vpg,
0, /* packetIndex */ 0, /* packetIndex */
&info_frame->vsc, &info_frame->vsc,
true); true);
sdp_stream_enable = true;
} if (info_frame->spd.valid)
if (info_frame->spd.valid) {
enc->vpg->funcs->update_generic_info_packet( enc->vpg->funcs->update_generic_info_packet(
enc->vpg, enc->vpg,
2, /* packetIndex */ 2, /* packetIndex */
&info_frame->spd, &info_frame->spd,
true); true);
sdp_stream_enable = true;
} if (info_frame->hdrsmd.valid)
if (info_frame->hdrsmd.valid) {
enc->vpg->funcs->update_generic_info_packet( enc->vpg->funcs->update_generic_info_packet(
enc->vpg, enc->vpg,
3, /* packetIndex */ 3, /* packetIndex */
&info_frame->hdrsmd, &info_frame->hdrsmd,
true); true);
sdp_stream_enable = true;
}
/* enable/disable transmission of packet(s). /* enable/disable transmission of packet(s).
* If enabled, packet transmission begins on the next frame * 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 // Setup manual flow control for EOF via TRIG_A
optc->funcs->setup_manual_trigger(optc); optc->funcs->setup_manual_trigger(optc);
} else { } else {
REG_UPDATE_4(OTG_V_TOTAL_CONTROL, REG_UPDATE_4(OTG_V_TOTAL_CONTROL,
OTG_SET_V_TOTAL_MIN_MASK, 0, 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, .enable_crtc_reset = optc1_enable_crtc_reset,
.disable_reset_trigger = optc1_disable_reset_trigger, .disable_reset_trigger = optc1_disable_reset_trigger,
.lock = optc3_lock, .lock = optc3_lock,
.is_locked = optc1_is_locked,
.unlock = optc1_unlock, .unlock = optc1_unlock,
.lock_doublebuffer_enable = optc3_lock_doublebuffer_enable, .lock_doublebuffer_enable = optc3_lock_doublebuffer_enable,
.lock_doublebuffer_disable = optc3_lock_doublebuffer_disable, .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, .disable_z10 = true,
.optimize_edp_link_rate = true,
.enable_z9_disable_interface = true, /* Allow support for the PMFW interface for disable Z9*/ .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 = { 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 .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) static void dcn31_dpp_destroy(struct dpp **dpp)
{ {
kfree(TO_DCN20_DPP(*dpp)); kfree(TO_DCN20_DPP(*dpp));
@@ -1803,6 +1808,11 @@ validate_out:
return 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 = { static struct dc_cap_funcs cap_funcs = {
.get_dcc_compression_cap = dcn20_get_dcc_compression_cap .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, .release_post_bldn_3dlut = dcn30_release_post_bldn_3dlut,
.update_bw_bounding_box = dcn31_update_bw_bounding_box, .update_bw_bounding_box = dcn31_update_bw_bounding_box,
.patch_unknown_plane_state = dcn20_patch_unknown_plane_state, .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( 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; return two_pix;
} }
void enc314_stream_encoder_dp_blank( static void enc314_stream_encoder_dp_blank(
struct dc_link *link, struct dc_link *link,
struct stream_encoder *enc) 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 = { 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, .disable_dmcu = true,
.force_abm_enable = false, .force_abm_enable = false,
.timing_trace = false, .timing_trace = false,
@@ -914,7 +915,6 @@ static const struct dc_debug_options debug_defaults_drv = {
.afmt = true, .afmt = true,
} }
}, },
.optimize_edp_link_rate = true,
.seamless_boot_odm_combine = true .seamless_boot_odm_combine = true
}; };
@@ -936,6 +936,12 @@ static const struct dc_debug_options debug_defaults_diags = {
.use_max_lb = true .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) static void dcn31_dpp_destroy(struct dpp **dpp)
{ {
kfree(TO_DCN20_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(); 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 = { static struct resource_funcs dcn314_res_pool_funcs = {
.destroy = dcn314_destroy_resource_pool, .destroy = dcn314_destroy_resource_pool,
.link_enc_create = dcn31_link_encoder_create, .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, .release_post_bldn_3dlut = dcn30_release_post_bldn_3dlut,
.update_bw_bounding_box = dcn314_update_bw_bounding_box, .update_bw_bounding_box = dcn314_update_bw_bounding_box,
.patch_unknown_plane_state = dcn20_patch_unknown_plane_state, .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( 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, .afmt = true,
} }
}, },
.optimize_edp_link_rate = true,
.psr_power_use_phy_fsm = 0, .psr_power_use_phy_fsm = 0,
}; };
@@ -907,6 +906,12 @@ static const struct dc_debug_options debug_defaults_diags = {
.use_max_lb = true .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) static void dcn31_dpp_destroy(struct dpp **dpp)
{ {
kfree(TO_DCN20_DPP(*dpp)); kfree(TO_DCN20_DPP(*dpp));
@@ -1708,6 +1713,11 @@ static int dcn315_populate_dml_pipes_from_context(
return pipe_cnt; 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 = { static struct dc_cap_funcs cap_funcs = {
.get_dcc_compression_cap = dcn20_get_dcc_compression_cap .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, .panel_cntl_create = dcn31_panel_cntl_create,
.validate_bandwidth = dcn31_validate_bandwidth, .validate_bandwidth = dcn31_validate_bandwidth,
.calculate_wm_and_dlg = dcn31_calculate_wm_and_dlg, .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, .populate_dml_pipes = dcn315_populate_dml_pipes_from_context,
.acquire_idle_pipe_for_layer = dcn20_acquire_idle_pipe_for_layer, .acquire_idle_pipe_for_layer = dcn20_acquire_idle_pipe_for_layer,
.add_stream_to_ctx = dcn30_add_stream_to_ctx, .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, .release_post_bldn_3dlut = dcn30_release_post_bldn_3dlut,
.update_bw_bounding_box = dcn315_update_bw_bounding_box, .update_bw_bounding_box = dcn315_update_bw_bounding_box,
.patch_unknown_plane_state = dcn20_patch_unknown_plane_state, .patch_unknown_plane_state = dcn20_patch_unknown_plane_state,
.get_panel_config_defaults = dcn315_get_panel_config_defaults,
}; };
static bool dcn315_resource_construct( static bool dcn315_resource_construct(

View File

@@ -885,7 +885,6 @@ static const struct dc_debug_options debug_defaults_drv = {
.afmt = true, .afmt = true,
} }
}, },
.optimize_edp_link_rate = true,
}; };
static const struct dc_debug_options debug_defaults_diags = { 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 .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) static void dcn31_dpp_destroy(struct dpp **dpp)
{ {
kfree(TO_DCN20_DPP(*dpp)); kfree(TO_DCN20_DPP(*dpp));
@@ -1710,6 +1715,11 @@ static int dcn316_populate_dml_pipes_from_context(
return pipe_cnt; 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 = { static struct dc_cap_funcs cap_funcs = {
.get_dcc_compression_cap = dcn20_get_dcc_compression_cap .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, .release_post_bldn_3dlut = dcn30_release_post_bldn_3dlut,
.update_bw_bounding_box = dcn316_update_bw_bounding_box, .update_bw_bounding_box = dcn316_update_bw_bounding_box,
.patch_unknown_plane_state = dcn20_patch_unknown_plane_state, .patch_unknown_plane_state = dcn20_patch_unknown_plane_state,
.get_panel_config_defaults = dcn316_get_panel_config_defaults,
}; };
static bool dcn316_resource_construct( 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 = { static const struct link_encoder_funcs dcn32_link_enc_funcs = {
.read_state = link_enc2_read_state, .read_state = link_enc2_read_state,
.validate_output_with_stream = .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, .is_in_alt_mode = dcn32_link_encoder_is_in_alt_mode,
.get_max_link_cap = dcn32_link_encoder_get_max_link_cap, .get_max_link_cap = dcn32_link_encoder_get_max_link_cap,
.set_dio_phy_mux = dcn31_link_encoder_set_dio_phy_mux, .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( 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, const struct dc_link_settings *link_settings,
enum clock_source_id clock_source); 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__ */ #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; 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( static void enc32_stream_encoder_dp_unblank(
struct dc_link *link, struct dc_link *link,
struct stream_encoder *enc, 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 */ /* 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 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() */ /*this logic should be the same in get_pixel_clock_parameters() */
n_multiply = 1; 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); 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 /* 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) 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); 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, enc3_stream_encoder_update_dp_info_packets,
.stop_dp_info_packets = .stop_dp_info_packets =
enc1_stream_encoder_stop_dp_info_packets, enc1_stream_encoder_stop_dp_info_packets,
.reset_fifo =
enc32_stream_encoder_reset_fifo,
.dp_blank = .dp_blank =
enc1_stream_encoder_dp_blank, enc1_stream_encoder_dp_blank,
.dp_unblank = .dp_unblank =

View File

@@ -71,7 +71,9 @@
SRI(DP_MSE_RATE_UPDATE, DP, id), \ SRI(DP_MSE_RATE_UPDATE, DP, id), \
SRI(DP_PIXEL_FORMAT, DP, id), \ SRI(DP_PIXEL_FORMAT, DP, id), \
SRI(DP_SEC_CNTL, DP, id), \ SRI(DP_SEC_CNTL, DP, id), \
SRI(DP_SEC_CNTL1, DP, id), \
SRI(DP_SEC_CNTL2, DP, id), \ SRI(DP_SEC_CNTL2, DP, id), \
SRI(DP_SEC_CNTL5, DP, id), \
SRI(DP_SEC_CNTL6, DP, id), \ SRI(DP_SEC_CNTL6, DP, id), \
SRI(DP_STEER_FIFO, DP, id), \ SRI(DP_STEER_FIFO, DP, id), \
SRI(DP_VID_M, DP, id), \ SRI(DP_VID_M, DP, id), \
@@ -93,7 +95,7 @@
SRI(DIG_FIFO_CTRL0, DIG, id) 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_PIXEL_ENCODING, mask_sh),\
SE_SF(DP0_DP_PIXEL_FORMAT, DP_COMPONENT_DEPTH, 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),\ 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_CONT, mask_sh),\
SE_SF(DIG0_HDMI_VBI_PACKET_CONTROL, HDMI_GC_SEND, 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_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_CONTROL0, HDMI_AUDIO_INFO_SEND, mask_sh),\
SE_SF(DIG0_HDMI_INFOFRAME_CONTROL1, HDMI_AUDIO_INFO_LINE, mask_sh),\ SE_SF(DIG0_HDMI_INFOFRAME_CONTROL1, HDMI_AUDIO_INFO_LINE, mask_sh),\
SE_SF(DIG0_HDMI_GC, HDMI_GC_AVMUTE, 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_RESET_DONE, mask_sh),\
SE_SF(DIG0_DIG_FIFO_CTRL0, DIG_FIFO_OUTPUT_PIXEL_MODE, 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( void dcn32_dio_stream_encoder_construct(
struct dcn10_stream_encoder *enc1, struct dcn10_stream_encoder *enc1,
struct dc_context *ctx, 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_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_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_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_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_SAT_VC0, SAT_SLOT_COUNT, mask_sh),\
SE_SF(DP_DPHY_SYM320_DP_DPHY_SYM32_VC_RATE_CNTL0, STREAM_VC_RATE_X, 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, .program_watermarks = hubbub32_program_watermarks,
.allow_self_refresh_control = hubbub1_allow_self_refresh_control, .allow_self_refresh_control = hubbub1_allow_self_refresh_control,
.is_allow_self_refresh_enabled = hubbub1_is_allow_self_refresh_enabled, .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_wm_propagate_to_pipes = hubbub32_force_wm_propagate_to_pipes,
.force_pstate_change_control = hubbub3_force_pstate_change_control, .force_pstate_change_control = hubbub3_force_pstate_change_control,
.init_watermarks = hubbub32_init_watermarks, .init_watermarks = hubbub32_init_watermarks,

View File

@@ -79,6 +79,8 @@ void hubp32_phantom_hubp_post_enable(struct hubp *hubp)
uint32_t reg_val; uint32_t reg_val;
struct dcn20_hubp *hubp2 = TO_DCN20_HUBP(hubp); 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_UPDATE(DCHUBP_CNTL, HUBP_BLANK_EN, 1);
reg_val = REG_READ(DCHUBP_CNTL); reg_val = REG_READ(DCHUBP_CNTL);
if (reg_val) { if (reg_val) {
@@ -179,12 +181,12 @@ static struct hubp_funcs dcn32_hubp_funcs = {
.hubp_init = hubp3_init, .hubp_init = hubp3_init,
.set_unbounded_requesting = hubp31_set_unbounded_requesting, .set_unbounded_requesting = hubp31_set_unbounded_requesting,
.hubp_soft_reset = hubp31_soft_reset, .hubp_soft_reset = hubp31_soft_reset,
.hubp_set_flip_int = hubp1_set_flip_int,
.hubp_in_blank = hubp1_in_blank, .hubp_in_blank = hubp1_in_blank,
.hubp_update_force_pstate_disallow = hubp32_update_force_pstate_disallow, .hubp_update_force_pstate_disallow = hubp32_update_force_pstate_disallow,
.phantom_hubp_post_enable = hubp32_phantom_hubp_post_enable, .phantom_hubp_post_enable = hubp32_phantom_hubp_post_enable,
.hubp_update_mall_sel = hubp32_update_mall_sel, .hubp_update_mall_sel = hubp32_update_mall_sel,
.hubp_prepare_subvp_buffering = hubp32_prepare_subvp_buffering, .hubp_prepare_subvp_buffering = hubp32_prepare_subvp_buffering
.hubp_set_flip_int = hubp1_set_flip_int
}; };
bool hubp32_construct( 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) static uint32_t dcn32_calculate_cab_allocation(struct dc *dc, struct dc_state *ctx)
{ {
uint8_t i; int i, j;
int j;
struct dc_stream_state *stream = NULL; struct dc_stream_state *stream = NULL;
struct dc_plane_state *plane = NULL; struct dc_plane_state *plane = NULL;
uint32_t cursor_size = 0; uint32_t cursor_size = 0;
@@ -630,10 +629,9 @@ bool dcn32_set_input_transfer_func(struct dc *dc,
params = &dpp_base->degamma_params; 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 && if (pipe_ctx->stream_res.opp &&
pipe_ctx->stream_res.opp &&
pipe_ctx->stream_res.opp->ctx && pipe_ctx->stream_res.opp->ctx &&
hws->funcs.set_mcm_luts) hws->funcs.set_mcm_luts)
result = hws->funcs.set_mcm_luts(pipe_ctx, plane_state); 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_dmub_srv_query_caps_cmd(dc->ctx->dmub_srv->dmub);
dc->caps.dmub_caps.psr = dc->ctx->dmub_srv->dmub->feature_caps.psr; 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, 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); true);
} }
// Don't program pixel clock after link is already enabled if (pipe_ctx->stream_res.dsc) {
/* if (false == pipe_ctx->clock_source->funcs->program_pix_clk( struct pipe_ctx *current_pipe_ctx = &dc->current_state->res_ctx.pipe_ctx[pipe_ctx->pipe_idx];
pipe_ctx->clock_source,
&pipe_ctx->stream_res.pix_clk_params,
&pipe_ctx->pll_settings)) {
BREAK_TO_DEBUGGER();
}*/
if (pipe_ctx->stream_res.dsc)
update_dsc_on_stream(pipe_ctx, pipe_ctx->stream->timing.flags.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) 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; struct dc_stream_state *stream = pipe_ctx->stream;
unsigned int odm_combine_factor = 0; unsigned int odm_combine_factor = 0;
struct dc *dc = pipe_ctx->stream->ctx->dc;
bool two_pix_per_container = false; bool two_pix_per_container = false;
// For phantom pipes, use the same programming as the main pipes // 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 { } else {
*k1_div = PIXEL_RATE_DIV_BY_1; *k1_div = PIXEL_RATE_DIV_BY_1;
*k2_div = PIXEL_RATE_DIV_BY_4; *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; *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 dc_link *link = stream->link;
struct dce_hwseq *hws = link->dc->hwseq; struct dce_hwseq *hws = link->dc->hwseq;
struct pipe_ctx *odm_pipe; struct pipe_ctx *odm_pipe;
struct dc *dc = pipe_ctx->stream->ctx->dc;
uint32_t pix_per_cycle = 1; uint32_t pix_per_cycle = 1;
params.opp_cnt = 1; params.opp_cnt = 1;
@@ -1245,7 +1248,7 @@ void dcn32_unblank_stream(struct pipe_ctx *pipe_ctx,
pipe_ctx->stream_res.tg->inst); pipe_ctx->stream_res.tg->inst);
} else if (dc_is_dp_signal(pipe_ctx->stream->signal)) { } else if (dc_is_dp_signal(pipe_ctx->stream->signal)) {
if (optc2_is_two_pixels_per_containter(&stream->timing) || params.opp_cnt > 1 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; params.timing.pix_clk_100hz /= 2;
pix_per_cycle = 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; 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) && 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) dc->debug.enable_dp_dig_pixel_rate_div_policy)
return true; return true;
@@ -1394,7 +1400,7 @@ bool dcn32_dsc_pg_status(
break; break;
} }
return pwr_status == 0 ? true : false; return pwr_status == 0;
} }
void dcn32_update_dsc_pg(struct dc *dc, 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. */ /* CRTC disabled, so disable clock. */
REG_WAIT(OTG_CLOCK_CONTROL, REG_WAIT(OTG_CLOCK_CONTROL,
OTG_BUSY, 0, OTG_BUSY, 0,
1, 100000); 1, 150000);
return true; 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.y = 0;
phantom_plane->clip_rect.height = phantom_stream->timing.v_addressable; 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); dc_add_plane_to_context(dc, phantom_stream, phantom_plane, context);
curr_pipe = curr_pipe->bottom_pipe; 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.type = SUBVP_NONE;
pipe->stream->mall_stream_config.paired_stream = NULL; pipe->stream->mall_stream_config.paired_stream = NULL;
} }
if (pipe->plane_state) {
pipe->plane_state->is_phantom = false;
}
} }
return removed_pipe; return removed_pipe;
} }
@@ -1798,14 +1804,39 @@ bool dcn32_validate_bandwidth(struct dc *dc,
int vlevel = 0; int vlevel = 0;
int pipe_cnt = 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); 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); 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(); BW_VAL_TRACE_COUNT();
DC_FP_START(); DC_FP_START();
out = dcn32_internal_validate_bw(dc, context, pipes, &pipe_cnt, &vlevel, fast_validate); out = dcn32_internal_validate_bw(dc, context, pipes, &pipe_cnt, &vlevel, fast_validate);
DC_FP_END(); DC_FP_END();
if (fast_validate)
dcn32_restore_mall_state(dc, context, &mall_temp_config);
if (pipe_cnt == 0) if (pipe_cnt == 0)
goto validate_out; goto validate_out;

View File

@@ -45,6 +45,17 @@
extern struct _vcs_dpi_ip_params_st dcn3_2_ip; extern struct _vcs_dpi_ip_params_st dcn3_2_ip;
extern struct _vcs_dpi_soc_bounding_box_st dcn3_2_soc; 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 dcn32_resource_pool {
struct resource_pool base; 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_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 pipe_ctx *dcn32_acquire_idle_pipe_for_head_pipe_in_layer(
struct dc_state *state, struct dc_state *state,
const struct resource_pool *pool, 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, void dcn32_set_det_allocations(struct dc *dc, struct dc_state *context,
display_e2e_pipe_params_st *pipes); 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 */ /* definitions for run time init of reg offsets */
/* CLK SRC */ /* CLK SRC */

View File

@@ -233,6 +233,23 @@ bool dcn32_mpo_in_use(struct dc_state *context)
return false; 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 * 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 } else
dcn32_determine_det_override(dc, context, pipes); 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, .is_in_alt_mode = dcn20_link_encoder_is_in_alt_mode,
.get_max_link_cap = dcn20_link_encoder_get_max_link_cap, .get_max_link_cap = dcn20_link_encoder_get_max_link_cap,
.set_dio_phy_mux = dcn31_link_encoder_set_dio_phy_mux, .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( void dcn321_link_encoder_construct(

View File

@@ -94,8 +94,6 @@
#include "dcn20/dcn20_vmid.h" #include "dcn20/dcn20_vmid.h"
#define DC_LOGGER_INIT(logger) #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 { enum dcn321_clk_src_array_id {
DCN321_CLK_SRC_PLL0, DCN321_CLK_SRC_PLL0,
@@ -1606,7 +1604,7 @@ static struct resource_funcs dcn321_res_pool_funcs = {
.validate_bandwidth = dcn32_validate_bandwidth, .validate_bandwidth = dcn32_validate_bandwidth,
.calculate_wm_and_dlg = dcn32_calculate_wm_and_dlg, .calculate_wm_and_dlg = dcn32_calculate_wm_and_dlg,
.populate_dml_pipes = dcn32_populate_dml_pipes_from_context, .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_stream_to_ctx = dcn30_add_stream_to_ctx,
.add_dsc_to_stream_resource = dcn20_add_dsc_to_stream_resource, .add_dsc_to_stream_resource = dcn20_add_dsc_to_stream_resource,
.remove_stream_from_ctx = dcn20_remove_stream_from_ctx, .remove_stream_from_ctx = dcn20_remove_stream_from_ctx,
@@ -1656,7 +1654,7 @@ static bool dcn321_resource_construct(
#undef REG_STRUCT #undef REG_STRUCT
#define REG_STRUCT dccg_regs #define REG_STRUCT dccg_regs
dccg_regs_init(); dccg_regs_init();
ctx->dc_bios->regs = &bios_regs; ctx->dc_bios->regs = &bios_regs;

View File

@@ -1444,81 +1444,67 @@ unsigned int dcn_find_dcfclk_suits_all(
return dcf_clk; 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; 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) */ ASSERT(fclks->num_levels);
res = dm_pp_get_clock_levels_by_type_with_voltage(
ctx, DM_PP_CLOCK_TYPE_FCLK, &fclks);
if (res) vmin0p65_idx = 0;
res = verify_clock_values(&fclks); 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) { dc->dcn_soc->fabric_and_dram_bandwidth_vmin0p65 =
ASSERT(fclks.num_levels); 32 * (fclks->data[vmin0p65_idx].clocks_in_khz / 1000.0) / 1000.0;
dc->dcn_soc->fabric_and_dram_bandwidth_vmid0p72 =
vmin0p65_idx = 0; dc->dcn_soc->number_of_channels *
vmid0p72_idx = fclks.num_levels - (fclks->data[vmid0p72_idx].clocks_in_khz / 1000.0)
(fclks.num_levels > 2 ? 3 : (fclks.num_levels > 1 ? 2 : 1)); * ddr4_dram_factor_single_Channel / 1000.0;
vnom0p8_idx = fclks.num_levels - (fclks.num_levels > 1 ? 2 : 1); dc->dcn_soc->fabric_and_dram_bandwidth_vnom0p8 =
vmax0p9_idx = fclks.num_levels - 1; dc->dcn_soc->number_of_channels *
(fclks->data[vnom0p8_idx].clocks_in_khz / 1000.0)
dc->dcn_soc->fabric_and_dram_bandwidth_vmin0p65 = * ddr4_dram_factor_single_Channel / 1000.0;
32 * (fclks.data[vmin0p65_idx].clocks_in_khz / 1000.0) / 1000.0; dc->dcn_soc->fabric_and_dram_bandwidth_vmax0p9 =
dc->dcn_soc->fabric_and_dram_bandwidth_vmid0p72 = dc->dcn_soc->number_of_channels *
dc->dcn_soc->number_of_channels * (fclks->data[vmax0p9_idx].clocks_in_khz / 1000.0)
(fclks.data[vmid0p72_idx].clocks_in_khz / 1000.0) * ddr4_dram_factor_single_Channel / 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();
} }
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_funcs_rv *pp = NULL;
struct pp_smu_wm_range_sets ranges = {0}; 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 */ const int overdrive = 5000000; /* 5 GHz to cover Overdrive */
if (dc->res_pool->pp_smu) 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) if (!pp || !pp->set_wm_ranges)
return; 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 /* 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 * depending on DPM state they are in. And update BW MGR GFX Engine and
* Memory clock member variables for Watermarks calculations for each * 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_component_us = 0,
.urgent_latency_adjustment_fabric_clock_reference_mhz = 0, .urgent_latency_adjustment_fabric_clock_reference_mhz = 0,
.num_chans = 4, .num_chans = 4,
.dummy_pstate_latency_us = 10.0
}; };
struct _vcs_dpi_ip_params_st dcn3_16_ip = { 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( void dcn31_calculate_wm_and_dlg_fp(
struct dc *dc, struct dc_state *context, struct dc *dc, struct dc_state *context,
display_e2e_pipe_params_st *pipes, display_e2e_pipe_params_st *pipes,
int pipe_cnt, int pipe_cnt,
int vlevel) 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]; double dcfclk = context->bw_ctx.dml.vba.DCFCLKState[vlevel][context->bw_ctx.dml.vba.maxMpcComb];
dc_assert_fp_enabled(); 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.dcfclk_mhz = dcfclk;
pipes[0].clks_cfg.socclk_mhz = context->bw_ctx.dml.soc.clock_limits[vlevel].socclk_mhz; 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: /* Set A:
* All clocks min required * 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_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.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; 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.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.c = context->bw_ctx.bw.dcn.watermarks.a;
context->bw_ctx.bw.dcn.watermarks.d = 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++) { for (i = 0, pipe_idx = 0; i < dc->res_pool->pipe_count; i++) {
if (!context->res_ctx.pipe_ctx[i].stream) if (!context->res_ctx.pipe_ctx[i].stream)
continue; 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.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); 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); 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) 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)) 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 else
dml_init_instance(&dc->dml, &dcn3_15_soc, &dcn3_15_ip, DML_PROJECT_DCN31_FPGA); 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); int pipe_cnt);
void dcn31_update_soc_for_wm_a(struct dc *dc, struct dc_state *context); 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( void dcn31_calculate_wm_and_dlg_fp(
struct dc *dc, struct dc_state *context, struct dc *dc, struct dc_state *context,

View File

@@ -43,6 +43,8 @@
#define BPP_BLENDED_PIPE 0xffffffff #define BPP_BLENDED_PIPE 0xffffffff
#define DCN31_MAX_DSC_IMAGE_WIDTH 5184 #define DCN31_MAX_DSC_IMAGE_WIDTH 5184
#define DCN31_MAX_FMT_420_BUFFER_WIDTH 4096 #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 // For DML-C changes that hasn't been propagated to VBA yet
//#define __DML_VBA_ALLOW_DELTA__ //#define __DML_VBA_ALLOW_DELTA__
@@ -3775,6 +3777,17 @@ static noinline void CalculatePrefetchSchedulePerPlane(
&v->VReadyOffsetPix[k]); &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) void dml31_ModeSupportAndSystemConfigurationFull(struct display_mode_lib *mode_lib)
{ {
struct vba_vars_st *v = &mode_lib->vba; 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]; 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( CalculateSwathAndDETConfiguration(
false, false,
v->NumberOfActivePlanes, 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; 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 * Finds dummy_latency_index when MCLK switching using firmware based
* vblank stretch is enabled. This function will iterate through the * vblank stretch is enabled. This function will iterate through the
* table of dummy pstate latencies until the lowest value that allows * 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 * dcn32_helper_populate_phantom_dlg_params - Get DLG params for phantom pipes
* and populate pipe_ctx with those params. * 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 * @dc: [in] current dc state
* @context: [in] new dc state * @context: [in] new dc state
* @pipes: [in] DML pipe params array * @pipes: [in] DML pipe params array
* @pipe_cnt: [in] DML pipe count * @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, void dcn32_helper_populate_phantom_dlg_params(struct dc *dc,
struct dc_state *context, 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 * 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 * 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 combine is only chosen if there is no ODM combine requirements / policy in place, and
* MPC is required * MPC is required
* *
* @param [in]: context: New DC state to be programmed * Return: Number of splits expected (1 for 2:1 split, 3 for 4:1 split, 0 for no splits).
* @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).
*
* *******************************************************************************************
*/ */
uint8_t dcn32_predict_pipe_split(struct dc_state *context, uint8_t dcn32_predict_pipe_split(struct dc_state *context,
display_e2e_pipe_params_st *pipe_e2e) 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. * 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 * 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. * that separately.
* *
* - Set phantom backporch = vstartup of main pipe * - 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, void dcn32_set_phantom_stream_timing(struct dc *dc,
struct dc_state *context, 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 * This function assumes that a "used" pipe is a pipe that has
* both a stream and a plane assigned to it. * both a stream and a plane assigned to it.
* *
* @dc: current dc state * Return: Number of free pipes available in the context
* @context: new dc state
*
* Return:
* Number of free pipes available in the context
*/ */
static unsigned int dcn32_get_num_free_pipes(struct dc *dc, struct dc_state *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) * 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 * 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 * 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]). * support MCLK switching naturally [i.e. ACTIVE or VBLANK]).
* *
* @param dc: current dc state * Return: True if a valid pipe assignment was found for Sub-VP. Otherwise false.
* @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.
*/ */
static bool dcn32_assign_subvp_pipe(struct dc *dc, static bool dcn32_assign_subvp_pipe(struct dc *dc,
struct dc_state *context, 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 * This function returns true if there are enough free pipes
* to create the required phantom pipes for any given stream * 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 * pipe which can be used as the phantom pipe for the non pipe
* split pipe. * split pipe.
* *
* @dc: current dc state
* @context: new dc state
*
* Return: * Return:
* True if there are enough free pipes to assign phantom pipes to at least one * 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. * 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: * High level algorithm:
* 1. Find longest microschedule length (in us) between the two SubVP pipes * 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 * pipes still allows for the maximum microschedule to fit in the active
* region for both pipes. * region for both pipes.
* *
* @dc: current dc state * Return: True if the SubVP + SubVP config is schedulable, false otherwise
* @context: new dc state
*
* Return:
* bool - True if the SubVP + SubVP config is schedulable, false otherwise
*/ */
static bool subvp_subvp_schedulable(struct dc *dc, struct dc_state *context) 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: * High level algorithm:
* 1. Get timing for SubVP pipe, phantom pipe, and DRR pipe * 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)) * 3.If (SubVP Active - Prefetch > Stretched DRR frame + max(MALL region, Stretched DRR frame))
* then report the configuration as supported * then report the configuration as supported
* *
* @dc: current dc state * Return: True if the SubVP + DRR config is schedulable, false otherwise
* @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
*/ */
static bool subvp_drr_schedulable(struct dc *dc, struct dc_state *context, struct pipe_ctx *drr_pipe) 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: * High level algorithm:
* 1. Get timing for SubVP pipe, phantom pipe, and VBLANK pipe * 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 * then report the configuration as supported
* 3. If the VBLANK display is DRR, then take the DRR static schedulability path * 3. If the VBLANK display is DRR, then take the DRR static schedulability path
* *
* @dc: current dc state * Return: True if the SubVP + VBLANK/DRR config is schedulable, false otherwise
* @context: new dc state
*
* Return:
* bool - True if the SubVP + VBLANK/DRR config is schedulable, false otherwise
*/ */
static bool subvp_vblank_schedulable(struct dc *dc, struct dc_state *context) 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 * subvp_validate_static_schedulability - Check which SubVP case is calculated
* static analysis based on the case. * and handle static analysis based on the case.
* @dc: current dc state
* @context: new dc state
* @vlevel: Voltage level calculated by DML
* *
* Three cases: * Three cases:
* 1. SubVP + SubVP * 1. SubVP + SubVP
* 2. SubVP + VBLANK (DRR checked internally) * 2. SubVP + VBLANK (DRR checked internally)
* 3. SubVP + VACTIVE (currently unsupported) * 3. SubVP + VACTIVE (currently unsupported)
* *
* @dc: current dc state * Return: True if statically schedulable, false otherwise
* @context: new dc state
* @vlevel: Voltage level calculated by DML
*
* Return:
* bool - True if statically schedulable, false otherwise
*/ */
static bool subvp_validate_static_schedulability(struct dc *dc, static bool subvp_validate_static_schedulability(struct dc *dc,
struct dc_state *context, 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) * 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) && 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 || vba->DRAMClockChangeSupport[*vlevel][vba->maxMpcComb] == dm_dram_clock_change_unsupported ||
dc->debug.force_subvp_mclk_switch)) { 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*/ /*MPC split rules will handle this case*/
pipe->bottom_pipe->top_pipe = NULL; pipe->bottom_pipe->top_pipe = NULL;
} else { } 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) { if (pipe->prev_odm_pipe->bottom_pipe) {
/* 3 plane MPO*/ /* 3 plane MPO*/
pipe->bottom_pipe->top_pipe = pipe->prev_odm_pipe->bottom_pipe; 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->bottom_pipe->top_pipe = pipe->prev_odm_pipe;
pipe->prev_odm_pipe->bottom_pipe = pipe->bottom_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; int i, pipe_idx, vlevel_temp = 0;
double dcfclk = dcn3_2_soc.clock_limits[0].dcfclk_mhz; 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_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] != bool pstate_en = context->bw_ctx.dml.vba.DRAMClockChangeSupport[vlevel][context->bw_ctx.dml.vba.maxMpcComb] !=
dm_dram_clock_change_unsupported; dm_dram_clock_change_unsupported;
unsigned int dummy_latency_index = 0; 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; 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); dcn32_internal_validate_bw(dc, context, pipes, &pipe_cnt, &vlevel, false);
maxMpcComb = context->bw_ctx.dml.vba.maxMpcComb; 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] != pstate_en = context->bw_ctx.dml.vba.DRAMClockChangeSupport[vlevel][maxMpcComb] !=
dm_dram_clock_change_unsupported; 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.dcfclk_mhz = dcfclk_from_validation;
pipes[0].clks_cfg.socclk_mhz = context->bw_ctx.dml.soc.clock_limits[vlevel].socclk_mhz; 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) { 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 = context->bw_ctx.dml.vba.DRAMSpeed;
min_dram_speed_mts_margin = 160; min_dram_speed_mts_margin = 160;
@@ -2275,7 +2268,7 @@ static int build_synthetic_soc_states(struct clk_bw_params *bw_params,
return 0; return 0;
} }
/** /*
* dcn32_update_bw_bounding_box * dcn32_update_bw_bounding_box
* *
* This would override some dcn3_2 ip_or_soc initial parameters hardcoded from * 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.FCLKChangeLatency, v->UrgentLatency,
mode_lib->vba.SREnterPlusExitTime); 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.Dppclk = mode_lib->vba.DPPCLK[k];
v->dummy_vars.DISPCLKDPPCLKDCFCLKDeepSleepPrefetchParametersWatermarksAndPerformanceCalculation.myPipe.Dispclk = mode_lib->vba.DISPCLK; v->dummy_vars.DISPCLKDPPCLKDCFCLKDeepSleepPrefetchParametersWatermarksAndPerformanceCalculation.myPipe.Dispclk = mode_lib->vba.DISPCLK;
v->dummy_vars.DISPCLKDPPCLKDCFCLKDeepSleepPrefetchParametersWatermarksAndPerformanceCalculation.myPipe.PixelClock = mode_lib->vba.PixelClock[k]; 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++) { for (k = 0; k <= mode_lib->vba.NumberOfActiveSurfaces - 1; k++) {
if (!(mode_lib->vba.DSCInputBitPerComponent[k] == 12.0 if (!(mode_lib->vba.DSCInputBitPerComponent[k] == 12.0
|| mode_lib->vba.DSCInputBitPerComponent[k] == 10.0 || mode_lib->vba.DSCInputBitPerComponent[k] == 10.0
|| mode_lib->vba.DSCInputBitPerComponent[k] == 8.0 || mode_lib->vba.DSCInputBitPerComponent[k] == 8.0)
|| mode_lib->vba.DSCInputBitPerComponent[k] > || mode_lib->vba.DSCInputBitPerComponent[k] > mode_lib->vba.MaximumDSCBitsPerComponent) {
mode_lib->vba.MaximumDSCBitsPerComponent)) {
mode_lib->vba.NonsupportedDSCInputBPC = true; 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) if (mode_lib->vba.OutputMultistreamId[k] == k && mode_lib->vba.ForcedOutputLinkBPP[k] == 0)
mode_lib->vba.BPPForMultistreamNotIndicated = true; mode_lib->vba.BPPForMultistreamNotIndicated = true;
for (j = 0; j < mode_lib->vba.NumberOfActiveSurfaces; ++j) { 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.ForcedOutputLinkBPP[k] == 0)
mode_lib->vba.BPPForMultistreamNotIndicated = true; mode_lib->vba.BPPForMultistreamNotIndicated = true;
} }
} }
if ((mode_lib->vba.Output[k] == dm_edp || mode_lib->vba.Output[k] == dm_hdmi)) { 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; mode_lib->vba.MultistreamWithHDMIOreDP = true;
for (j = 0; j < mode_lib->vba.NumberOfActiveSurfaces; ++j) { for (j = 0; j < mode_lib->vba.NumberOfActiveSurfaces; ++j) {
if (mode_lib->vba.OutputMultistreamEn[k] == true && mode_lib->vba.OutputMultistreamId[k] == j) if (mode_lib->vba.OutputMultistreamEn[k] == true && mode_lib->vba.OutputMultistreamId[k] == j)
mode_lib->vba.MultistreamWithHDMIOreDP = true; 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]); mode_lib->vba.PixelClock[k], mode_lib->vba.PixelClockBackEnd[k]);
} }
m = 0;
for (k = 0; k <= mode_lib->vba.NumberOfActiveSurfaces - 1; k++) { for (k = 0; k <= mode_lib->vba.NumberOfActiveSurfaces - 1; k++) {
for (m = 0; m <= mode_lib->vba.NumberOfActiveSurfaces - 1; m++) { for (m = 0; m <= mode_lib->vba.NumberOfActiveSurfaces - 1; m++) {
for (j = 0; j <= mode_lib->vba.NumberOfActiveSurfaces - 1; j++) { 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 //Calculate Return BW
for (i = 0; i < (int) v->soc.num_states; ++i) { for (i = 0; i < (int) v->soc.num_states; ++i) {
for (j = 0; j <= 1; ++j) { 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.ModeIsSupported = mode_lib->vba.ModeSupport[i][0] == true
|| mode_lib->vba.ModeSupport[i][1] == 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; MaximumMPCCombine = 0;
} else { else
MaximumMPCCombine = 1; MaximumMPCCombine = 1;
}
} }
} }

View File

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

View File

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

View File

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

View File

@@ -628,8 +628,23 @@ unsigned int dcn_find_dcfclk_suits_all(
const struct dc *dc, const struct dc *dc,
struct dc_clocks *clocks); struct dc_clocks *clocks);
void dcn_bw_update_from_pplib(struct dc *dc); void dcn_get_soc_clks(
void dcn_bw_notify_pplib_of_wm_ranges(struct dc *dc); 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); 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); 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; 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 */ /* This table is contiguous */
struct clk_limit_table { struct clk_limit_table {
struct clk_limit_table_entry entries[MAX_NUM_DPM_LVL]; 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 { 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__ #define __DAL_DPP_H__
#include "transform.h" #include "transform.h"
#include "cursor_reg_cache.h"
union defer_reg_writes { union defer_reg_writes {
struct { struct {
@@ -58,6 +59,9 @@ struct dpp {
struct pwl_params shaper_params; struct pwl_params shaper_params;
bool cm_bypass_mode; bool cm_bypass_mode;
struct cursor_position_cache_dpp pos;
struct cursor_attribute_cache_dpp att;
}; };
struct dpp_input_csc_matrix { struct dpp_input_csc_matrix {

View File

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

View File

@@ -209,7 +209,6 @@ struct timing_generator_funcs {
void (*set_blank)(struct timing_generator *tg, void (*set_blank)(struct timing_generator *tg,
bool enable_blanking); bool enable_blanking);
bool (*is_blanked)(struct timing_generator *tg); 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_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_blank_color)(struct timing_generator *tg, const struct tg_color *color);
void (*set_colors)(struct timing_generator *tg, 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 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_ */ #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); enum phyd32clk_clock_source phyd32clk = get_phyd32clk_src(pipe_ctx->stream->link);
dto_params.otg_inst = tg->inst; 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.num_odm_segments = get_odm_segment_count(pipe_ctx);
dto_params.timing = &pipe_ctx->stream->timing; dto_params.timing = &pipe_ctx->stream->timing;
dto_params.ref_dtbclk_khz = dc->clk_mgr->funcs->get_dtb_ref_clk_frequency(dc->clk_mgr); 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, const struct link_resource *link_res,
enum signal_type signal) enum signal_type signal)
{ {

View File

@@ -248,6 +248,7 @@ struct dmub_srv_hw_params {
bool disable_dpia; bool disable_dpia;
bool usb4_cm_version; bool usb4_cm_version;
bool fw_in_system_memory; 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 diag_env: 1; /* 1 if diagnostic environment */
uint32_t gpint_scratch8: 1; /* 1 if GPINT is in scratch8*/ uint32_t gpint_scratch8: 1; /* 1 if GPINT is in scratch8*/
uint32_t usb4_cm_version: 1; /**< 1 CM support */ 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 */ } bits; /**< boot bits */
uint32_t all; /**< 32-bit access to 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 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, DMUB_CMD__VBIOS = 128,
}; };
@@ -760,11 +767,6 @@ enum dmub_cmd_dpia_type {
DMUB_CMD__DPIA_MST_ALLOC_SLOTS = 2, 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) #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 */ 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. * 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. * 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. * Cursor dirty rects.
*/ */
@@ -2116,6 +2218,20 @@ struct dmub_cmd_update_cursor_info_data {
* Currently the support is only for 0 or 1 * Currently the support is only for 0 or 1
*/ */
uint8_t panel_inst; 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. * 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. * 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 { struct dmub_optc_state {
uint32_t v_total_max; uint32_t v_total_max;
uint32_t v_total_min; uint32_t v_total_min;
uint32_t v_total_mid;
uint32_t v_total_mid_frame_num;
uint32_t tg_inst; uint32_t tg_inst;
uint32_t enable_manual_trigger;
uint32_t clear_force_vsync;
}; };
struct dmub_rb_cmd_drr_update { struct dmub_rb_cmd_drr_update {
@@ -3235,6 +3347,10 @@ union dmub_rb_cmd {
* Definition of a DMUB_CMD__QUERY_HPD_STATE command. * Definition of a DMUB_CMD__QUERY_HPD_STATE command.
*/ */
struct dmub_rb_cmd_query_hpd_state query_hpd; 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.dpia_supported = params->dpia_supported;
boot_options.bits.enable_dpia = params->disable_dpia ? 0 : 1; boot_options.bits.enable_dpia = params->disable_dpia ? 0 : 1;
boot_options.bits.usb4_cm_version = params->usb4_cm_version; 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.power_optimization = params->power_optimization;
boot_options.bits.sel_mux_phy_c_d_phy_f_g = (dmub->asic == DMUB_ASIC_DCN31B) ? 1 : 0; 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; struct pwl_float_data_ex *rgb = rgb_regamma;
const struct hw_x_point *coord_x = coordinates_x; const struct hw_x_point *coord_x = coordinates_x;
build_coefficients(&coeff, true); build_coefficients(&coeff, TRANSFER_FUNCTION_SRGB);
i = 0; i = 0;
while (i != hw_points_num + 1) { 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_STATUST0_BASE_IDX 2
#define regMCA_UMC_UMC0_MCUMC_ADDRT0 0x03c4 #define regMCA_UMC_UMC0_MCUMC_ADDRT0 0x03c4
#define regMCA_UMC_UMC0_MCUMC_ADDRT0_BASE_IDX 2 #define regMCA_UMC_UMC0_MCUMC_ADDRT0_BASE_IDX 2
#define regUMCCH0_0_GeccCtrl 0x0053
#define regUMCCH0_0_GeccCtrl_BASE_IDX 2
#endif #endif

View File

@@ -90,5 +90,8 @@
#define MCA_UMC_UMC0_MCUMC_ADDRT0__ErrorAddr__SHIFT 0x0 #define MCA_UMC_UMC0_MCUMC_ADDRT0__ErrorAddr__SHIFT 0x0
#define MCA_UMC_UMC0_MCUMC_ADDRT0__Reserved__SHIFT 0x38 #define MCA_UMC_UMC0_MCUMC_ADDRT0__Reserved__SHIFT 0x38
#define MCA_UMC_UMC0_MCUMC_ADDRT0__ErrorAddr_MASK 0x00FFFFFFFFFFFFFFL #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 #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) static void kv_dpm_disable(struct amdgpu_device *adev)
{ {
struct kv_power_info *pi = kv_get_pi(adev); struct kv_power_info *pi = kv_get_pi(adev);
int err;
amdgpu_irq_put(adev, &adev->pm.dpm.thermal.irq, amdgpu_irq_put(adev, &adev->pm.dpm.thermal.irq,
AMDGPU_THERMAL_IRQ_LOW_TO_HIGH); AMDGPU_THERMAL_IRQ_LOW_TO_HIGH);
amdgpu_irq_put(adev, &adev->pm.dpm.thermal.irq, amdgpu_irq_put(adev, &adev->pm.dpm.thermal.irq,
AMDGPU_THERMAL_IRQ_HIGH_TO_LOW); 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) if (adev->asic_type == CHIP_MULLINS)
kv_enable_nb_dpm(adev, false); 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); return -EINVAL);
PP_ASSERT_WITH_CODE( PP_ASSERT_WITH_CODE(
(smu7_power_state->performance_level_count <= (smu7_power_state->performance_level_count <
hwmgr->platform_descriptor.hardwareActivityPerformanceLevels), hwmgr->platform_descriptor.hardwareActivityPerformanceLevels),
"Performance levels exceeds Driver limit!", "Performance levels exceeds Driver limit!",
return -EINVAL); return -EINVAL);

View File

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

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