mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2024-08-27 19:29:37 +00:00
Merge tag 'amd-drm-next-5.12-2021-02-03' of https://gitlab.freedesktop.org/agd5f/linux into drm-next
amd-drm-next-5.12-2021-02-03: amdgpu: - Display fixes and cleanups - Vangogh fixes - Fix possible race when there are timeouts on two rings - SR-IOV fixes - Add missing license - DCE 10/12 bpc fixes - Display MALL fixes - Fix SMU user preference settings persistence - Fix retry in gem allocate - Add new PCI DID - Fix for manual fan speed control on cards where it was problematic - Fix regression in pinning GTT - Misc display fixes - Misc code cleanups amdkfd: - Fix config handling - Fix regression in buffer free From: Alex Deucher <alexdeucher@gmail.com> Link: https://patchwork.freedesktop.org/patch/msgid/20210204045717.3823-1-alexander.deucher@amd.com Signed-off-by: Dave Airlie <airlied@redhat.com>
This commit is contained in:
commit
c5cb0db5fc
80 changed files with 1625 additions and 874 deletions
|
@ -47,12 +47,8 @@ int amdgpu_amdkfd_init(void)
|
|||
amdgpu_amdkfd_total_mem_size = si.totalram - si.totalhigh;
|
||||
amdgpu_amdkfd_total_mem_size *= si.mem_unit;
|
||||
|
||||
#ifdef CONFIG_HSA_AMD
|
||||
ret = kgd2kfd_init();
|
||||
amdgpu_amdkfd_gpuvm_init_mem_limits();
|
||||
#else
|
||||
ret = -ENOENT;
|
||||
#endif
|
||||
kfd_initialized = !ret;
|
||||
|
||||
return ret;
|
||||
|
@ -696,86 +692,3 @@ bool amdgpu_amdkfd_have_atomics_support(struct kgd_dev *kgd)
|
|||
|
||||
return adev->have_atomics_support;
|
||||
}
|
||||
|
||||
#ifndef CONFIG_HSA_AMD
|
||||
bool amdkfd_fence_check_mm(struct dma_fence *f, struct mm_struct *mm)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
void amdgpu_amdkfd_unreserve_memory_limit(struct amdgpu_bo *bo)
|
||||
{
|
||||
}
|
||||
|
||||
int amdgpu_amdkfd_remove_fence_on_pt_pd_bos(struct amdgpu_bo *bo)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
void amdgpu_amdkfd_gpuvm_destroy_cb(struct amdgpu_device *adev,
|
||||
struct amdgpu_vm *vm)
|
||||
{
|
||||
}
|
||||
|
||||
struct amdgpu_amdkfd_fence *to_amdgpu_amdkfd_fence(struct dma_fence *f)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int amdgpu_amdkfd_evict_userptr(struct kgd_mem *mem, struct mm_struct *mm)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct kfd_dev *kgd2kfd_probe(struct kgd_dev *kgd, struct pci_dev *pdev,
|
||||
unsigned int asic_type, bool vf)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
bool kgd2kfd_device_init(struct kfd_dev *kfd,
|
||||
struct drm_device *ddev,
|
||||
const struct kgd2kfd_shared_resources *gpu_resources)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
void kgd2kfd_device_exit(struct kfd_dev *kfd)
|
||||
{
|
||||
}
|
||||
|
||||
void kgd2kfd_exit(void)
|
||||
{
|
||||
}
|
||||
|
||||
void kgd2kfd_suspend(struct kfd_dev *kfd, bool run_pm)
|
||||
{
|
||||
}
|
||||
|
||||
int kgd2kfd_resume(struct kfd_dev *kfd, bool run_pm)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
int kgd2kfd_pre_reset(struct kfd_dev *kfd)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
int kgd2kfd_post_reset(struct kfd_dev *kfd)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
void kgd2kfd_interrupt(struct kfd_dev *kfd, const void *ih_ring_entry)
|
||||
{
|
||||
}
|
||||
|
||||
void kgd2kfd_set_sram_ecc_flag(struct kfd_dev *kfd)
|
||||
{
|
||||
}
|
||||
|
||||
void kgd2kfd_smi_event_throttle(struct kfd_dev *kfd, uint32_t throttle_bitmask)
|
||||
{
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -94,11 +94,6 @@ enum kgd_engine_type {
|
|||
KGD_ENGINE_MAX
|
||||
};
|
||||
|
||||
struct amdgpu_amdkfd_fence *amdgpu_amdkfd_fence_create(u64 context,
|
||||
struct mm_struct *mm);
|
||||
bool amdkfd_fence_check_mm(struct dma_fence *f, struct mm_struct *mm);
|
||||
struct amdgpu_amdkfd_fence *to_amdgpu_amdkfd_fence(struct dma_fence *f);
|
||||
int amdgpu_amdkfd_remove_fence_on_pt_pd_bos(struct amdgpu_bo *bo);
|
||||
|
||||
struct amdkfd_process_info {
|
||||
/* List head of all VMs that belong to a KFD process */
|
||||
|
@ -132,8 +127,6 @@ void amdgpu_amdkfd_interrupt(struct amdgpu_device *adev,
|
|||
void amdgpu_amdkfd_device_probe(struct amdgpu_device *adev);
|
||||
void amdgpu_amdkfd_device_init(struct amdgpu_device *adev);
|
||||
void amdgpu_amdkfd_device_fini(struct amdgpu_device *adev);
|
||||
|
||||
int amdgpu_amdkfd_evict_userptr(struct kgd_mem *mem, struct mm_struct *mm);
|
||||
int amdgpu_amdkfd_submit_ib(struct kgd_dev *kgd, enum kgd_engine_type engine,
|
||||
uint32_t vmid, uint64_t gpu_addr,
|
||||
uint32_t *ib_cmd, uint32_t ib_len);
|
||||
|
@ -153,6 +146,38 @@ void amdgpu_amdkfd_gpu_reset(struct kgd_dev *kgd);
|
|||
int amdgpu_queue_mask_bit_to_set_resource_bit(struct amdgpu_device *adev,
|
||||
int queue_bit);
|
||||
|
||||
struct amdgpu_amdkfd_fence *amdgpu_amdkfd_fence_create(u64 context,
|
||||
struct mm_struct *mm);
|
||||
#if IS_ENABLED(CONFIG_HSA_AMD)
|
||||
bool amdkfd_fence_check_mm(struct dma_fence *f, struct mm_struct *mm);
|
||||
struct amdgpu_amdkfd_fence *to_amdgpu_amdkfd_fence(struct dma_fence *f);
|
||||
int amdgpu_amdkfd_remove_fence_on_pt_pd_bos(struct amdgpu_bo *bo);
|
||||
int amdgpu_amdkfd_evict_userptr(struct kgd_mem *mem, struct mm_struct *mm);
|
||||
#else
|
||||
static inline
|
||||
bool amdkfd_fence_check_mm(struct dma_fence *f, struct mm_struct *mm)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
static inline
|
||||
struct amdgpu_amdkfd_fence *to_amdgpu_amdkfd_fence(struct dma_fence *f)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static inline
|
||||
int amdgpu_amdkfd_remove_fence_on_pt_pd_bos(struct amdgpu_bo *bo)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline
|
||||
int amdgpu_amdkfd_evict_userptr(struct kgd_mem *mem, struct mm_struct *mm)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
/* Shared API */
|
||||
int amdgpu_amdkfd_alloc_gtt_mem(struct kgd_dev *kgd, size_t size,
|
||||
void **mem_obj, uint64_t *gpu_addr,
|
||||
|
@ -215,8 +240,6 @@ int amdgpu_amdkfd_gpuvm_acquire_process_vm(struct kgd_dev *kgd,
|
|||
struct file *filp, u32 pasid,
|
||||
void **vm, void **process_info,
|
||||
struct dma_fence **ef);
|
||||
void amdgpu_amdkfd_gpuvm_destroy_cb(struct amdgpu_device *adev,
|
||||
struct amdgpu_vm *vm);
|
||||
void amdgpu_amdkfd_gpuvm_destroy_process_vm(struct kgd_dev *kgd, void *vm);
|
||||
void amdgpu_amdkfd_gpuvm_release_process_vm(struct kgd_dev *kgd, void *vm);
|
||||
uint64_t amdgpu_amdkfd_gpuvm_get_process_page_dir(void *vm);
|
||||
|
@ -236,23 +259,43 @@ int amdgpu_amdkfd_gpuvm_map_gtt_bo_to_kernel(struct kgd_dev *kgd,
|
|||
struct kgd_mem *mem, void **kptr, uint64_t *size);
|
||||
int amdgpu_amdkfd_gpuvm_restore_process_bos(void *process_info,
|
||||
struct dma_fence **ef);
|
||||
|
||||
int amdgpu_amdkfd_gpuvm_get_vm_fault_info(struct kgd_dev *kgd,
|
||||
struct kfd_vm_fault_info *info);
|
||||
|
||||
int amdgpu_amdkfd_gpuvm_import_dmabuf(struct kgd_dev *kgd,
|
||||
struct dma_buf *dmabuf,
|
||||
uint64_t va, void *vm,
|
||||
struct kgd_mem **mem, uint64_t *size,
|
||||
uint64_t *mmap_offset);
|
||||
|
||||
void amdgpu_amdkfd_gpuvm_init_mem_limits(void);
|
||||
void amdgpu_amdkfd_unreserve_memory_limit(struct amdgpu_bo *bo);
|
||||
|
||||
int amdgpu_amdkfd_get_tile_config(struct kgd_dev *kgd,
|
||||
struct tile_config *config);
|
||||
#if IS_ENABLED(CONFIG_HSA_AMD)
|
||||
void amdgpu_amdkfd_gpuvm_init_mem_limits(void);
|
||||
void amdgpu_amdkfd_gpuvm_destroy_cb(struct amdgpu_device *adev,
|
||||
struct amdgpu_vm *vm);
|
||||
void amdgpu_amdkfd_unreserve_memory_limit(struct amdgpu_bo *bo);
|
||||
#else
|
||||
static inline
|
||||
void amdgpu_amdkfd_gpuvm_init_mem_limits(void)
|
||||
{
|
||||
}
|
||||
|
||||
static inline
|
||||
void amdgpu_amdkfd_gpuvm_destroy_cb(struct amdgpu_device *adev,
|
||||
struct amdgpu_vm *vm)
|
||||
{
|
||||
}
|
||||
|
||||
static inline
|
||||
void amdgpu_amdkfd_unreserve_memory_limit(struct amdgpu_bo *bo)
|
||||
{
|
||||
}
|
||||
#endif
|
||||
/* KGD2KFD callbacks */
|
||||
int kgd2kfd_quiesce_mm(struct mm_struct *mm);
|
||||
int kgd2kfd_resume_mm(struct mm_struct *mm);
|
||||
int kgd2kfd_schedule_evict_and_restore_process(struct mm_struct *mm,
|
||||
struct dma_fence *fence);
|
||||
#if IS_ENABLED(CONFIG_HSA_AMD)
|
||||
int kgd2kfd_init(void);
|
||||
void kgd2kfd_exit(void);
|
||||
struct kfd_dev *kgd2kfd_probe(struct kgd_dev *kgd, struct pci_dev *pdev,
|
||||
|
@ -266,11 +309,68 @@ int kgd2kfd_resume(struct kfd_dev *kfd, bool run_pm);
|
|||
int kgd2kfd_pre_reset(struct kfd_dev *kfd);
|
||||
int kgd2kfd_post_reset(struct kfd_dev *kfd);
|
||||
void kgd2kfd_interrupt(struct kfd_dev *kfd, const void *ih_ring_entry);
|
||||
int kgd2kfd_quiesce_mm(struct mm_struct *mm);
|
||||
int kgd2kfd_resume_mm(struct mm_struct *mm);
|
||||
int kgd2kfd_schedule_evict_and_restore_process(struct mm_struct *mm,
|
||||
struct dma_fence *fence);
|
||||
void kgd2kfd_set_sram_ecc_flag(struct kfd_dev *kfd);
|
||||
void kgd2kfd_smi_event_throttle(struct kfd_dev *kfd, uint32_t throttle_bitmask);
|
||||
#else
|
||||
static inline int kgd2kfd_init(void)
|
||||
{
|
||||
return -ENOENT;
|
||||
}
|
||||
|
||||
static inline void kgd2kfd_exit(void)
|
||||
{
|
||||
}
|
||||
|
||||
static inline
|
||||
struct kfd_dev *kgd2kfd_probe(struct kgd_dev *kgd, struct pci_dev *pdev,
|
||||
unsigned int asic_type, bool vf)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static inline
|
||||
bool kgd2kfd_device_init(struct kfd_dev *kfd, struct drm_device *ddev,
|
||||
const struct kgd2kfd_shared_resources *gpu_resources)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
static inline void kgd2kfd_device_exit(struct kfd_dev *kfd)
|
||||
{
|
||||
}
|
||||
|
||||
static inline void kgd2kfd_suspend(struct kfd_dev *kfd, bool run_pm)
|
||||
{
|
||||
}
|
||||
|
||||
static inline int kgd2kfd_resume(struct kfd_dev *kfd, bool run_pm)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline int kgd2kfd_pre_reset(struct kfd_dev *kfd)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline int kgd2kfd_post_reset(struct kfd_dev *kfd)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline
|
||||
void kgd2kfd_interrupt(struct kfd_dev *kfd, const void *ih_ring_entry)
|
||||
{
|
||||
}
|
||||
|
||||
static inline
|
||||
void kgd2kfd_set_sram_ecc_flag(struct kfd_dev *kfd)
|
||||
{
|
||||
}
|
||||
|
||||
static inline
|
||||
void kgd2kfd_smi_event_throttle(struct kfd_dev *kfd, uint32_t throttle_bitmask)
|
||||
{
|
||||
}
|
||||
#endif
|
||||
#endif /* AMDGPU_AMDKFD_H_INCLUDED */
|
||||
|
|
|
@ -26,6 +26,7 @@
|
|||
#include <linux/sched/task.h>
|
||||
|
||||
#include "amdgpu_object.h"
|
||||
#include "amdgpu_gem.h"
|
||||
#include "amdgpu_vm.h"
|
||||
#include "amdgpu_amdkfd.h"
|
||||
#include "amdgpu_dma_buf.h"
|
||||
|
@ -1152,7 +1153,7 @@ int amdgpu_amdkfd_gpuvm_alloc_memory_of_gpu(
|
|||
struct sg_table *sg = NULL;
|
||||
uint64_t user_addr = 0;
|
||||
struct amdgpu_bo *bo;
|
||||
struct amdgpu_bo_param bp;
|
||||
struct drm_gem_object *gobj;
|
||||
u32 domain, alloc_domain;
|
||||
u64 alloc_flags;
|
||||
int ret;
|
||||
|
@ -1220,19 +1221,14 @@ int amdgpu_amdkfd_gpuvm_alloc_memory_of_gpu(
|
|||
pr_debug("\tcreate BO VA 0x%llx size 0x%llx domain %s\n",
|
||||
va, size, domain_string(alloc_domain));
|
||||
|
||||
memset(&bp, 0, sizeof(bp));
|
||||
bp.size = size;
|
||||
bp.byte_align = 1;
|
||||
bp.domain = alloc_domain;
|
||||
bp.flags = alloc_flags;
|
||||
bp.type = bo_type;
|
||||
bp.resv = NULL;
|
||||
ret = amdgpu_bo_create(adev, &bp, &bo);
|
||||
ret = amdgpu_gem_object_create(adev, size, 1, alloc_domain, alloc_flags,
|
||||
bo_type, NULL, &gobj);
|
||||
if (ret) {
|
||||
pr_debug("Failed to create BO on domain %s. ret %d\n",
|
||||
domain_string(alloc_domain), ret);
|
||||
domain_string(alloc_domain), ret);
|
||||
goto err_bo_create;
|
||||
}
|
||||
bo = gem_to_amdgpu_bo(gobj);
|
||||
if (bo_type == ttm_bo_type_sg) {
|
||||
bo->tbo.sg = sg;
|
||||
bo->tbo.ttm->sg = sg;
|
||||
|
|
|
@ -4211,7 +4211,6 @@ bool amdgpu_device_should_recover_gpu(struct amdgpu_device *adev)
|
|||
case CHIP_NAVI12:
|
||||
case CHIP_SIENNA_CICHLID:
|
||||
case CHIP_NAVY_FLOUNDER:
|
||||
case CHIP_VANGOGH:
|
||||
break;
|
||||
default:
|
||||
goto disabled;
|
||||
|
@ -4461,6 +4460,46 @@ static void amdgpu_device_unlock_adev(struct amdgpu_device *adev)
|
|||
up_write(&adev->reset_sem);
|
||||
}
|
||||
|
||||
/*
|
||||
* to lockup a list of amdgpu devices in a hive safely, if not a hive
|
||||
* with multiple nodes, it will be similar as amdgpu_device_lock_adev.
|
||||
*
|
||||
* unlock won't require roll back.
|
||||
*/
|
||||
static int amdgpu_device_lock_hive_adev(struct amdgpu_device *adev, struct amdgpu_hive_info *hive)
|
||||
{
|
||||
struct amdgpu_device *tmp_adev = NULL;
|
||||
|
||||
if (adev->gmc.xgmi.num_physical_nodes > 1) {
|
||||
if (!hive) {
|
||||
dev_err(adev->dev, "Hive is NULL while device has multiple xgmi nodes");
|
||||
return -ENODEV;
|
||||
}
|
||||
list_for_each_entry(tmp_adev, &hive->device_list, gmc.xgmi.head) {
|
||||
if (!amdgpu_device_lock_adev(tmp_adev, hive))
|
||||
goto roll_back;
|
||||
}
|
||||
} else if (!amdgpu_device_lock_adev(adev, hive))
|
||||
return -EAGAIN;
|
||||
|
||||
return 0;
|
||||
roll_back:
|
||||
if (!list_is_first(&tmp_adev->gmc.xgmi.head, &hive->device_list)) {
|
||||
/*
|
||||
* if the lockup iteration break in the middle of a hive,
|
||||
* it may means there may has a race issue,
|
||||
* or a hive device locked up independently.
|
||||
* we may be in trouble and may not, so will try to roll back
|
||||
* the lock and give out a warnning.
|
||||
*/
|
||||
dev_warn(tmp_adev->dev, "Hive lock iteration broke in the middle. Rolling back to unlock");
|
||||
list_for_each_entry_continue_reverse(tmp_adev, &hive->device_list, gmc.xgmi.head) {
|
||||
amdgpu_device_unlock_adev(tmp_adev);
|
||||
}
|
||||
}
|
||||
return -EAGAIN;
|
||||
}
|
||||
|
||||
static void amdgpu_device_resume_display_audio(struct amdgpu_device *adev)
|
||||
{
|
||||
struct pci_dev *p = NULL;
|
||||
|
@ -4574,11 +4613,29 @@ int amdgpu_device_gpu_recover(struct amdgpu_device *adev,
|
|||
DRM_INFO("Bailing on TDR for s_job:%llx, hive: %llx as another already in progress",
|
||||
job ? job->base.id : -1, hive->hive_id);
|
||||
amdgpu_put_xgmi_hive(hive);
|
||||
if (job)
|
||||
drm_sched_increase_karma(&job->base);
|
||||
return 0;
|
||||
}
|
||||
mutex_lock(&hive->hive_lock);
|
||||
}
|
||||
|
||||
/*
|
||||
* lock the device before we try to operate the linked list
|
||||
* if didn't get the device lock, don't touch the linked list since
|
||||
* others may iterating it.
|
||||
*/
|
||||
r = amdgpu_device_lock_hive_adev(adev, hive);
|
||||
if (r) {
|
||||
dev_info(adev->dev, "Bailing on TDR for s_job:%llx, as another already in progress",
|
||||
job ? job->base.id : -1);
|
||||
|
||||
/* even we skipped this reset, still need to set the job to guilty */
|
||||
if (job)
|
||||
drm_sched_increase_karma(&job->base);
|
||||
goto skip_recovery;
|
||||
}
|
||||
|
||||
/*
|
||||
* Build list of devices to reset.
|
||||
* In case we are in XGMI hive mode, resort the device list
|
||||
|
@ -4586,8 +4643,6 @@ int amdgpu_device_gpu_recover(struct amdgpu_device *adev,
|
|||
*/
|
||||
INIT_LIST_HEAD(&device_list);
|
||||
if (adev->gmc.xgmi.num_physical_nodes > 1) {
|
||||
if (!hive)
|
||||
return -ENODEV;
|
||||
if (!list_is_first(&adev->gmc.xgmi.head, &hive->device_list))
|
||||
list_rotate_to_front(&adev->gmc.xgmi.head, &hive->device_list);
|
||||
device_list_handle = &hive->device_list;
|
||||
|
@ -4598,13 +4653,6 @@ int amdgpu_device_gpu_recover(struct amdgpu_device *adev,
|
|||
|
||||
/* block all schedulers and reset given job's ring */
|
||||
list_for_each_entry(tmp_adev, device_list_handle, gmc.xgmi.head) {
|
||||
if (!amdgpu_device_lock_adev(tmp_adev, hive)) {
|
||||
dev_info(tmp_adev->dev, "Bailing on TDR for s_job:%llx, as another already in progress",
|
||||
job ? job->base.id : -1);
|
||||
r = 0;
|
||||
goto skip_recovery;
|
||||
}
|
||||
|
||||
/*
|
||||
* Try to put the audio codec into suspend state
|
||||
* before gpu reset started.
|
||||
|
@ -4742,7 +4790,7 @@ int amdgpu_device_gpu_recover(struct amdgpu_device *adev,
|
|||
amdgpu_put_xgmi_hive(hive);
|
||||
}
|
||||
|
||||
if (r)
|
||||
if (r && r != -EAGAIN)
|
||||
dev_info(adev->dev, "GPU reset end with ret = %d\n", r);
|
||||
return r;
|
||||
}
|
||||
|
@ -4792,7 +4840,13 @@ static void amdgpu_device_get_pcie_info(struct amdgpu_device *adev)
|
|||
CAIL_ASIC_PCIE_LINK_SPEED_SUPPORT_GEN2 |
|
||||
CAIL_ASIC_PCIE_LINK_SPEED_SUPPORT_GEN3);
|
||||
} else {
|
||||
if (speed_cap == PCIE_SPEED_16_0GT)
|
||||
if (speed_cap == PCIE_SPEED_32_0GT)
|
||||
adev->pm.pcie_gen_mask |= (CAIL_ASIC_PCIE_LINK_SPEED_SUPPORT_GEN1 |
|
||||
CAIL_ASIC_PCIE_LINK_SPEED_SUPPORT_GEN2 |
|
||||
CAIL_ASIC_PCIE_LINK_SPEED_SUPPORT_GEN3 |
|
||||
CAIL_ASIC_PCIE_LINK_SPEED_SUPPORT_GEN4 |
|
||||
CAIL_ASIC_PCIE_LINK_SPEED_SUPPORT_GEN5);
|
||||
else if (speed_cap == PCIE_SPEED_16_0GT)
|
||||
adev->pm.pcie_gen_mask |= (CAIL_ASIC_PCIE_LINK_SPEED_SUPPORT_GEN1 |
|
||||
CAIL_ASIC_PCIE_LINK_SPEED_SUPPORT_GEN2 |
|
||||
CAIL_ASIC_PCIE_LINK_SPEED_SUPPORT_GEN3 |
|
||||
|
@ -4812,7 +4866,13 @@ static void amdgpu_device_get_pcie_info(struct amdgpu_device *adev)
|
|||
adev->pm.pcie_gen_mask |= (CAIL_PCIE_LINK_SPEED_SUPPORT_GEN1 |
|
||||
CAIL_PCIE_LINK_SPEED_SUPPORT_GEN2);
|
||||
} else {
|
||||
if (platform_speed_cap == PCIE_SPEED_16_0GT)
|
||||
if (platform_speed_cap == PCIE_SPEED_32_0GT)
|
||||
adev->pm.pcie_gen_mask |= (CAIL_PCIE_LINK_SPEED_SUPPORT_GEN1 |
|
||||
CAIL_PCIE_LINK_SPEED_SUPPORT_GEN2 |
|
||||
CAIL_PCIE_LINK_SPEED_SUPPORT_GEN3 |
|
||||
CAIL_PCIE_LINK_SPEED_SUPPORT_GEN4 |
|
||||
CAIL_PCIE_LINK_SPEED_SUPPORT_GEN5);
|
||||
else if (platform_speed_cap == PCIE_SPEED_16_0GT)
|
||||
adev->pm.pcie_gen_mask |= (CAIL_PCIE_LINK_SPEED_SUPPORT_GEN1 |
|
||||
CAIL_PCIE_LINK_SPEED_SUPPORT_GEN2 |
|
||||
CAIL_PCIE_LINK_SPEED_SUPPORT_GEN3 |
|
||||
|
|
|
@ -926,8 +926,10 @@ amdgpu_display_user_framebuffer_create(struct drm_device *dev,
|
|||
struct drm_file *file_priv,
|
||||
const struct drm_mode_fb_cmd2 *mode_cmd)
|
||||
{
|
||||
struct drm_gem_object *obj;
|
||||
struct amdgpu_framebuffer *amdgpu_fb;
|
||||
struct drm_gem_object *obj;
|
||||
struct amdgpu_bo *bo;
|
||||
uint32_t domains;
|
||||
int ret;
|
||||
|
||||
obj = drm_gem_object_lookup(file_priv, mode_cmd->handles[0]);
|
||||
|
@ -938,7 +940,9 @@ amdgpu_display_user_framebuffer_create(struct drm_device *dev,
|
|||
}
|
||||
|
||||
/* Handle is imported dma-buf, so cannot be migrated to VRAM for scanout */
|
||||
if (obj->import_attach) {
|
||||
bo = gem_to_amdgpu_bo(obj);
|
||||
domains = amdgpu_display_supported_domains(drm_to_adev(dev), bo->flags);
|
||||
if (obj->import_attach && !(domains & AMDGPU_GEM_DOMAIN_GTT)) {
|
||||
drm_dbg_kms(dev, "Cannot create framebuffer from imported dma_buf\n");
|
||||
return ERR_PTR(-EINVAL);
|
||||
}
|
||||
|
|
|
@ -1094,6 +1094,7 @@ static const struct pci_device_id pciidlist[] = {
|
|||
|
||||
/* Sienna_Cichlid */
|
||||
{0x1002, 0x73A0, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_SIENNA_CICHLID},
|
||||
{0x1002, 0x73A1, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_SIENNA_CICHLID},
|
||||
{0x1002, 0x73A2, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_SIENNA_CICHLID},
|
||||
{0x1002, 0x73A3, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_SIENNA_CICHLID},
|
||||
{0x1002, 0x73AB, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_SIENNA_CICHLID},
|
||||
|
|
|
@ -269,8 +269,8 @@ int amdgpu_gem_create_ioctl(struct drm_device *dev, void *data,
|
|||
resv = vm->root.base.bo->tbo.base.resv;
|
||||
}
|
||||
|
||||
retry:
|
||||
initial_domain = (u32)(0xffffffff & args->in.domains);
|
||||
retry:
|
||||
r = amdgpu_gem_object_create(adev, size, args->in.alignment,
|
||||
initial_domain,
|
||||
flags, ttm_bo_type_device, resv, &gobj);
|
||||
|
|
|
@ -897,7 +897,7 @@ int amdgpu_bo_pin_restricted(struct amdgpu_bo *bo, u32 domain,
|
|||
return -EINVAL;
|
||||
|
||||
/* A shared bo cannot be migrated to VRAM */
|
||||
if (bo->prime_shared_count) {
|
||||
if (bo->prime_shared_count || bo->tbo.base.import_attach) {
|
||||
if (domain & AMDGPU_GEM_DOMAIN_GTT)
|
||||
domain = AMDGPU_GEM_DOMAIN_GTT;
|
||||
else
|
||||
|
@ -911,10 +911,16 @@ int amdgpu_bo_pin_restricted(struct amdgpu_bo *bo, u32 domain,
|
|||
|
||||
if (bo->tbo.pin_count) {
|
||||
uint32_t mem_type = bo->tbo.mem.mem_type;
|
||||
uint32_t mem_flags = bo->tbo.mem.placement;
|
||||
|
||||
if (!(domain & amdgpu_mem_type_to_domain(mem_type)))
|
||||
return -EINVAL;
|
||||
|
||||
if ((mem_type == TTM_PL_VRAM) &&
|
||||
(bo->flags & AMDGPU_GEM_CREATE_VRAM_CONTIGUOUS) &&
|
||||
!(mem_flags & TTM_PL_FLAG_CONTIGUOUS))
|
||||
return -EINVAL;
|
||||
|
||||
ttm_bo_pin(&bo->tbo);
|
||||
|
||||
if (max_offset != 0) {
|
||||
|
@ -930,7 +936,6 @@ int amdgpu_bo_pin_restricted(struct amdgpu_bo *bo, u32 domain,
|
|||
if (bo->tbo.base.import_attach)
|
||||
dma_buf_pin(bo->tbo.base.import_attach);
|
||||
|
||||
bo->flags |= AMDGPU_GEM_CREATE_VRAM_CONTIGUOUS;
|
||||
/* force to pin into visible video ram */
|
||||
if (!(bo->flags & AMDGPU_GEM_CREATE_NO_CPU_ACCESS))
|
||||
bo->flags |= AMDGPU_GEM_CREATE_CPU_ACCESS_REQUIRED;
|
||||
|
@ -983,6 +988,7 @@ int amdgpu_bo_pin_restricted(struct amdgpu_bo *bo, u32 domain,
|
|||
*/
|
||||
int amdgpu_bo_pin(struct amdgpu_bo *bo, u32 domain)
|
||||
{
|
||||
bo->flags |= AMDGPU_GEM_CREATE_VRAM_CONTIGUOUS;
|
||||
return amdgpu_bo_pin_restricted(bo, domain, 0, 0);
|
||||
}
|
||||
|
||||
|
|
|
@ -560,10 +560,14 @@ static int amdgpu_virt_write_vf2pf_data(struct amdgpu_device *adev)
|
|||
static void amdgpu_virt_update_vf2pf_work_item(struct work_struct *work)
|
||||
{
|
||||
struct amdgpu_device *adev = container_of(work, struct amdgpu_device, virt.vf2pf_work.work);
|
||||
int ret;
|
||||
|
||||
amdgpu_virt_read_pf2vf_data(adev);
|
||||
ret = amdgpu_virt_read_pf2vf_data(adev);
|
||||
if (ret)
|
||||
goto out;
|
||||
amdgpu_virt_write_vf2pf_data(adev);
|
||||
|
||||
out:
|
||||
schedule_delayed_work(&(adev->virt.vf2pf_work), adev->virt.vf2pf_update_interval_ms);
|
||||
}
|
||||
|
||||
|
@ -571,7 +575,6 @@ void amdgpu_virt_fini_data_exchange(struct amdgpu_device *adev)
|
|||
{
|
||||
if (adev->virt.vf2pf_update_interval_ms != 0) {
|
||||
DRM_INFO("clean up the vf2pf work item\n");
|
||||
flush_delayed_work(&adev->virt.vf2pf_work);
|
||||
cancel_delayed_work_sync(&adev->virt.vf2pf_work);
|
||||
adev->virt.vf2pf_update_interval_ms = 0;
|
||||
}
|
||||
|
|
|
@ -473,6 +473,9 @@ static int amdgpu_vram_mgr_new(struct ttm_resource_manager *man,
|
|||
for (i = 0; pages_left >= pages_per_node; ++i) {
|
||||
unsigned long pages = rounddown_pow_of_two(pages_left);
|
||||
|
||||
/* Limit maximum size to 2GB due to SG table limitations */
|
||||
pages = min(pages, (2UL << (30 - PAGE_SHIFT)));
|
||||
|
||||
r = drm_mm_insert_node_in_range(mm, &nodes[i], pages,
|
||||
pages_per_node, 0,
|
||||
place->fpfn, lpfn,
|
||||
|
|
|
@ -98,6 +98,10 @@
|
|||
#define mmGCR_GENERAL_CNTL_Sienna_Cichlid 0x1580
|
||||
#define mmGCR_GENERAL_CNTL_Sienna_Cichlid_BASE_IDX 0
|
||||
|
||||
#define mmCGTS_TCC_DISABLE_Vangogh 0x5006
|
||||
#define mmCGTS_TCC_DISABLE_Vangogh_BASE_IDX 1
|
||||
#define mmCGTS_USER_TCC_DISABLE_Vangogh 0x5007
|
||||
#define mmCGTS_USER_TCC_DISABLE_Vangogh_BASE_IDX 1
|
||||
#define mmGOLDEN_TSC_COUNT_UPPER_Vangogh 0x0025
|
||||
#define mmGOLDEN_TSC_COUNT_UPPER_Vangogh_BASE_IDX 1
|
||||
#define mmGOLDEN_TSC_COUNT_LOWER_Vangogh 0x0026
|
||||
|
@ -120,6 +124,7 @@
|
|||
#define mmSPI_CONFIG_CNTL_Vangogh_BASE_IDX 1
|
||||
#define mmGCR_GENERAL_CNTL_Vangogh 0x1580
|
||||
#define mmGCR_GENERAL_CNTL_Vangogh_BASE_IDX 0
|
||||
#define RLC_PG_DELAY_3__CGCG_ACTIVE_BEFORE_CGPG_MASK_Vangogh 0x0000FFFFL
|
||||
|
||||
#define mmCP_HYP_PFP_UCODE_ADDR 0x5814
|
||||
#define mmCP_HYP_PFP_UCODE_ADDR_BASE_IDX 1
|
||||
|
@ -3777,9 +3782,6 @@ static void gfx_v10_0_check_gfxoff_flag(struct amdgpu_device *adev)
|
|||
if (!gfx_v10_0_navi10_gfxoff_should_enable(adev))
|
||||
adev->pm.pp_feature &= ~PP_GFXOFF_MASK;
|
||||
break;
|
||||
case CHIP_VANGOGH:
|
||||
adev->pm.pp_feature &= ~PP_GFXOFF_MASK;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
@ -4935,8 +4937,18 @@ static void gfx_v10_0_tcp_harvest(struct amdgpu_device *adev)
|
|||
static void gfx_v10_0_get_tcc_info(struct amdgpu_device *adev)
|
||||
{
|
||||
/* TCCs are global (not instanced). */
|
||||
uint32_t tcc_disable = RREG32_SOC15(GC, 0, mmCGTS_TCC_DISABLE) |
|
||||
RREG32_SOC15(GC, 0, mmCGTS_USER_TCC_DISABLE);
|
||||
uint32_t tcc_disable;
|
||||
|
||||
switch (adev->asic_type) {
|
||||
case CHIP_VANGOGH:
|
||||
tcc_disable = RREG32_SOC15(GC, 0, mmCGTS_TCC_DISABLE_Vangogh) |
|
||||
RREG32_SOC15(GC, 0, mmCGTS_USER_TCC_DISABLE_Vangogh);
|
||||
break;
|
||||
default:
|
||||
tcc_disable = RREG32_SOC15(GC, 0, mmCGTS_TCC_DISABLE) |
|
||||
RREG32_SOC15(GC, 0, mmCGTS_USER_TCC_DISABLE);
|
||||
break;
|
||||
}
|
||||
|
||||
adev->gfx.config.tcc_disabled_mask =
|
||||
REG_GET_FIELD(tcc_disable, CGTS_TCC_DISABLE, TCC_DISABLE) |
|
||||
|
@ -7832,6 +7844,20 @@ static void gfx_v10_cntl_power_gating(struct amdgpu_device *adev, bool enable)
|
|||
data &= ~RLC_PG_CNTL__GFX_POWER_GATING_ENABLE_MASK;
|
||||
|
||||
WREG32_SOC15(GC, 0, mmRLC_PG_CNTL, data);
|
||||
|
||||
/*
|
||||
* CGPG enablement required and the register to program the hysteresis value
|
||||
* RLC_PG_DELAY_3.CGCG_ACTIVE_BEFORE_CGPG to the desired CGPG hysteresis value
|
||||
* in refclk count. Note that RLC FW is modified to take 16 bits from
|
||||
* RLC_PG_DELAY_3[15:0] as the hysteresis instead of just 8 bits.
|
||||
*
|
||||
* The recommendation from RLC team is setting RLC_PG_DELAY_3 to 200us(0x4E20)
|
||||
* as part of CGPG enablement starting point.
|
||||
*/
|
||||
if (enable && (adev->pg_flags & AMD_PG_SUPPORT_GFX_PG) && adev->asic_type == CHIP_VANGOGH) {
|
||||
data = 0x4E20 & RLC_PG_DELAY_3__CGCG_ACTIVE_BEFORE_CGPG_MASK_Vangogh;
|
||||
WREG32_SOC15(GC, 0, mmRLC_PG_DELAY_3, data);
|
||||
}
|
||||
}
|
||||
|
||||
static void gfx_v10_cntl_pg(struct amdgpu_device *adev, bool enable)
|
||||
|
@ -7893,6 +7919,7 @@ static int gfx_v10_0_set_powergating_state(void *handle,
|
|||
break;
|
||||
case CHIP_VANGOGH:
|
||||
gfx_v10_cntl_pg(adev, enable);
|
||||
amdgpu_gfx_off_ctrl(adev, enable);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
|
|
|
@ -531,12 +531,12 @@ mmhub_v2_3_update_medium_grain_light_sleep(struct amdgpu_device *adev,
|
|||
|
||||
if (enable && (adev->cg_flags & AMD_CG_SUPPORT_MC_LS)) {
|
||||
data &= ~MM_ATC_L2_CGTT_CLK_CTRL__MGLS_OVERRIDE_MASK;
|
||||
data1 &= !(DAGB0_WR_CGTT_CLK_CTRL__LS_OVERRIDE_MASK |
|
||||
data1 &= ~(DAGB0_WR_CGTT_CLK_CTRL__LS_OVERRIDE_MASK |
|
||||
DAGB0_WR_CGTT_CLK_CTRL__LS_OVERRIDE_WRITE_MASK |
|
||||
DAGB0_WR_CGTT_CLK_CTRL__LS_OVERRIDE_READ_MASK |
|
||||
DAGB0_WR_CGTT_CLK_CTRL__LS_OVERRIDE_RETURN_MASK |
|
||||
DAGB0_WR_CGTT_CLK_CTRL__LS_OVERRIDE_REGISTER_MASK);
|
||||
data2 &= !(DAGB0_RD_CGTT_CLK_CTRL__LS_OVERRIDE_MASK |
|
||||
data2 &= ~(DAGB0_RD_CGTT_CLK_CTRL__LS_OVERRIDE_MASK |
|
||||
DAGB0_RD_CGTT_CLK_CTRL__LS_OVERRIDE_WRITE_MASK |
|
||||
DAGB0_RD_CGTT_CLK_CTRL__LS_OVERRIDE_READ_MASK |
|
||||
DAGB0_RD_CGTT_CLK_CTRL__LS_OVERRIDE_RETURN_MASK |
|
||||
|
|
|
@ -411,6 +411,10 @@ static int nv_asic_reset(struct amdgpu_device *adev)
|
|||
int ret = 0;
|
||||
struct smu_context *smu = &adev->smu;
|
||||
|
||||
/* skip reset on vangogh for now */
|
||||
if (adev->asic_type == CHIP_VANGOGH)
|
||||
return 0;
|
||||
|
||||
switch (nv_asic_reset_method(adev)) {
|
||||
case AMD_RESET_METHOD_BACO:
|
||||
dev_info(adev->dev, "BACO reset\n");
|
||||
|
|
|
@ -7,6 +7,8 @@ config HSA_AMD
|
|||
bool "HSA kernel driver for AMD GPU devices"
|
||||
depends on DRM_AMDGPU && (X86_64 || ARM64 || PPC64)
|
||||
imply AMD_IOMMU_V2 if X86_64
|
||||
select HMM_MIRROR
|
||||
select MMU_NOTIFIER
|
||||
select DRM_AMDGPU_USERPTR
|
||||
help
|
||||
Enable this if you want to use HSA features on AMD GPU devices.
|
||||
|
|
|
@ -1015,8 +1015,6 @@ static int amdgpu_dm_init(struct amdgpu_device *adev)
|
|||
|
||||
init_data.flags.power_down_display_on_boot = true;
|
||||
|
||||
init_data.soc_bounding_box = adev->dm.soc_bounding_box;
|
||||
|
||||
/* Display Core create. */
|
||||
adev->dm.dc = dc_create(&init_data);
|
||||
|
||||
|
@ -1837,8 +1835,8 @@ static void emulated_link_detect(struct dc_link *link)
|
|||
link->type = dc_connection_none;
|
||||
prev_sink = link->local_sink;
|
||||
|
||||
if (prev_sink != NULL)
|
||||
dc_sink_retain(prev_sink);
|
||||
if (prev_sink)
|
||||
dc_sink_release(prev_sink);
|
||||
|
||||
switch (link->connector_signal) {
|
||||
case SIGNAL_TYPE_HDMI_TYPE_A: {
|
||||
|
@ -1938,7 +1936,7 @@ static void dm_gpureset_commit_state(struct dc_state *dc_state,
|
|||
dc_commit_updates_for_stream(
|
||||
dm->dc, bundle->surface_updates,
|
||||
dc_state->stream_status->plane_count,
|
||||
dc_state->streams[k], &bundle->stream_update, dc_state);
|
||||
dc_state->streams[k], &bundle->stream_update);
|
||||
}
|
||||
|
||||
cleanup:
|
||||
|
@ -1969,8 +1967,7 @@ static void dm_set_dpms_off(struct dc_link *link)
|
|||
|
||||
stream_update.stream = stream_state;
|
||||
dc_commit_updates_for_stream(stream_state->ctx->dc, NULL, 0,
|
||||
stream_state, &stream_update,
|
||||
stream_state->ctx->dc->current_state);
|
||||
stream_state, &stream_update);
|
||||
mutex_unlock(&adev->dm.dc_lock);
|
||||
}
|
||||
|
||||
|
@ -2334,8 +2331,10 @@ void amdgpu_dm_update_connector_after_detect(
|
|||
* TODO: check if we still need the S3 mode update workaround.
|
||||
* If yes, put it here.
|
||||
*/
|
||||
if (aconnector->dc_sink)
|
||||
if (aconnector->dc_sink) {
|
||||
amdgpu_dm_update_freesync_caps(connector, NULL);
|
||||
dc_sink_release(aconnector->dc_sink);
|
||||
}
|
||||
|
||||
aconnector->dc_sink = sink;
|
||||
dc_sink_retain(aconnector->dc_sink);
|
||||
|
@ -2351,8 +2350,6 @@ void amdgpu_dm_update_connector_after_detect(
|
|||
|
||||
drm_connector_update_edid_property(connector,
|
||||
aconnector->edid);
|
||||
drm_add_edid_modes(connector, aconnector->edid);
|
||||
|
||||
if (aconnector->dc_link->aux_mode)
|
||||
drm_dp_cec_set_edid(&aconnector->dm_dp_aux.aux,
|
||||
aconnector->edid);
|
||||
|
@ -6414,8 +6411,33 @@ static int dm_plane_helper_check_state(struct drm_plane_state *state,
|
|||
int min_scale = 0;
|
||||
int max_scale = INT_MAX;
|
||||
|
||||
/* Plane enabled? Get min/max allowed scaling factors from plane caps. */
|
||||
/* Plane enabled? Validate viewport and get scaling factors from plane caps. */
|
||||
if (fb && state->crtc) {
|
||||
/* Validate viewport to cover the case when only the position changes */
|
||||
if (state->plane->type != DRM_PLANE_TYPE_CURSOR) {
|
||||
int viewport_width = state->crtc_w;
|
||||
int viewport_height = state->crtc_h;
|
||||
|
||||
if (state->crtc_x < 0)
|
||||
viewport_width += state->crtc_x;
|
||||
else if (state->crtc_x + state->crtc_w > new_crtc_state->mode.crtc_hdisplay)
|
||||
viewport_width = new_crtc_state->mode.crtc_hdisplay - state->crtc_x;
|
||||
|
||||
if (state->crtc_y < 0)
|
||||
viewport_height += state->crtc_y;
|
||||
else if (state->crtc_y + state->crtc_h > new_crtc_state->mode.crtc_vdisplay)
|
||||
viewport_height = new_crtc_state->mode.crtc_vdisplay - state->crtc_y;
|
||||
|
||||
/* If completely outside of screen, viewport_width and/or viewport_height will be negative,
|
||||
* which is still OK to satisfy the condition below, thereby also covering these cases
|
||||
* (when plane is completely outside of screen).
|
||||
* x2 for width is because of pipe-split.
|
||||
*/
|
||||
if (viewport_width < MIN_VIEWPORT_SIZE*2 || viewport_height < MIN_VIEWPORT_SIZE)
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* Get min/max allowed scaling factors from plane caps. */
|
||||
get_min_max_dc_plane_scaling(state->crtc->dev, fb,
|
||||
&min_downscale, &max_upscale);
|
||||
/*
|
||||
|
@ -7643,7 +7665,7 @@ static void amdgpu_dm_commit_planes(struct drm_atomic_state *state,
|
|||
struct drm_crtc *pcrtc,
|
||||
bool wait_for_vblank)
|
||||
{
|
||||
uint32_t i;
|
||||
int i;
|
||||
uint64_t timestamp_ns;
|
||||
struct drm_plane *plane;
|
||||
struct drm_plane_state *old_plane_state, *new_plane_state;
|
||||
|
@ -7684,7 +7706,7 @@ static void amdgpu_dm_commit_planes(struct drm_atomic_state *state,
|
|||
amdgpu_dm_commit_cursors(state);
|
||||
|
||||
/* update planes when needed */
|
||||
for_each_oldnew_plane_in_state(state, plane, old_plane_state, new_plane_state, i) {
|
||||
for_each_oldnew_plane_in_state_reverse(state, plane, old_plane_state, new_plane_state, i) {
|
||||
struct drm_crtc *crtc = new_plane_state->crtc;
|
||||
struct drm_crtc_state *new_crtc_state;
|
||||
struct drm_framebuffer *fb = new_plane_state->fb;
|
||||
|
@ -7907,8 +7929,7 @@ static void amdgpu_dm_commit_planes(struct drm_atomic_state *state,
|
|||
bundle->surface_updates,
|
||||
planes_count,
|
||||
acrtc_state->stream,
|
||||
&bundle->stream_update,
|
||||
dc_state);
|
||||
&bundle->stream_update);
|
||||
|
||||
/**
|
||||
* Enable or disable the interrupts on the backend.
|
||||
|
@ -8244,13 +8265,13 @@ static void amdgpu_dm_atomic_commit_tail(struct drm_atomic_state *state)
|
|||
struct dm_connector_state *dm_new_con_state = to_dm_connector_state(new_con_state);
|
||||
struct dm_connector_state *dm_old_con_state = to_dm_connector_state(old_con_state);
|
||||
struct amdgpu_crtc *acrtc = to_amdgpu_crtc(dm_new_con_state->base.crtc);
|
||||
struct dc_surface_update dummy_updates[MAX_SURFACES];
|
||||
struct dc_surface_update surface_updates[MAX_SURFACES];
|
||||
struct dc_stream_update stream_update;
|
||||
struct dc_info_packet hdr_packet;
|
||||
struct dc_stream_status *status = NULL;
|
||||
bool abm_changed, hdr_changed, scaling_changed;
|
||||
|
||||
memset(&dummy_updates, 0, sizeof(dummy_updates));
|
||||
memset(&surface_updates, 0, sizeof(surface_updates));
|
||||
memset(&stream_update, 0, sizeof(stream_update));
|
||||
|
||||
if (acrtc) {
|
||||
|
@ -8307,16 +8328,15 @@ static void amdgpu_dm_atomic_commit_tail(struct drm_atomic_state *state)
|
|||
* To fix this, DC should permit updating only stream properties.
|
||||
*/
|
||||
for (j = 0; j < status->plane_count; j++)
|
||||
dummy_updates[j].surface = status->plane_states[0];
|
||||
surface_updates[j].surface = status->plane_states[j];
|
||||
|
||||
|
||||
mutex_lock(&dm->dc_lock);
|
||||
dc_commit_updates_for_stream(dm->dc,
|
||||
dummy_updates,
|
||||
surface_updates,
|
||||
status->plane_count,
|
||||
dm_new_crtc_state->stream,
|
||||
&stream_update,
|
||||
dc_state);
|
||||
&stream_update);
|
||||
mutex_unlock(&dm->dc_lock);
|
||||
}
|
||||
|
||||
|
@ -8453,14 +8473,14 @@ static int dm_force_atomic_commit(struct drm_connector *connector)
|
|||
|
||||
ret = PTR_ERR_OR_ZERO(conn_state);
|
||||
if (ret)
|
||||
goto err;
|
||||
goto out;
|
||||
|
||||
/* Attach crtc to drm_atomic_state*/
|
||||
crtc_state = drm_atomic_get_crtc_state(state, &disconnected_acrtc->base);
|
||||
|
||||
ret = PTR_ERR_OR_ZERO(crtc_state);
|
||||
if (ret)
|
||||
goto err;
|
||||
goto out;
|
||||
|
||||
/* force a restore */
|
||||
crtc_state->mode_changed = true;
|
||||
|
@ -8470,17 +8490,15 @@ static int dm_force_atomic_commit(struct drm_connector *connector)
|
|||
|
||||
ret = PTR_ERR_OR_ZERO(plane_state);
|
||||
if (ret)
|
||||
goto err;
|
||||
|
||||
goto out;
|
||||
|
||||
/* Call commit internally with the state we just constructed */
|
||||
ret = drm_atomic_commit(state);
|
||||
if (!ret)
|
||||
return 0;
|
||||
|
||||
err:
|
||||
DRM_ERROR("Restoring old state failed with %i\n", ret);
|
||||
out:
|
||||
drm_atomic_state_put(state);
|
||||
if (ret)
|
||||
DRM_ERROR("Restoring old state failed with %i\n", ret);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
@ -9687,6 +9705,10 @@ void amdgpu_dm_update_freesync_caps(struct drm_connector *connector,
|
|||
amdgpu_dm_connector->max_vfreq = range->max_vfreq;
|
||||
amdgpu_dm_connector->pixel_clock_mhz =
|
||||
range->pixel_clock_mhz * 10;
|
||||
|
||||
connector->display_info.monitor_range.min_vfreq = range->min_vfreq;
|
||||
connector->display_info.monitor_range.max_vfreq = range->max_vfreq;
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
|
|
|
@ -1063,7 +1063,7 @@ static int dp_dsc_fec_support_show(struct seq_file *m, void *data)
|
|||
* echo 0 > /sys/kernel/debug/dri/0/DP-X/trigger_hotplug
|
||||
*
|
||||
*/
|
||||
static ssize_t dp_trigger_hotplug(struct file *f, const char __user *buf,
|
||||
static ssize_t trigger_hotplug(struct file *f, const char __user *buf,
|
||||
size_t size, loff_t *pos)
|
||||
{
|
||||
struct amdgpu_dm_connector *aconnector = file_inode(f)->i_private;
|
||||
|
@ -2214,9 +2214,9 @@ static const struct file_operations dp_dsc_slice_bpg_offset_debugfs_fops = {
|
|||
.llseek = default_llseek
|
||||
};
|
||||
|
||||
static const struct file_operations dp_trigger_hotplug_debugfs_fops = {
|
||||
static const struct file_operations trigger_hotplug_debugfs_fops = {
|
||||
.owner = THIS_MODULE,
|
||||
.write = dp_trigger_hotplug,
|
||||
.write = trigger_hotplug,
|
||||
.llseek = default_llseek
|
||||
};
|
||||
|
||||
|
@ -2270,7 +2270,6 @@ static const struct {
|
|||
const struct file_operations *fops;
|
||||
} dp_debugfs_entries[] = {
|
||||
{"link_settings", &dp_link_settings_debugfs_fops},
|
||||
{"trigger_hotplug", &dp_trigger_hotplug_debugfs_fops},
|
||||
{"phy_settings", &dp_phy_settings_debugfs_fop},
|
||||
{"test_pattern", &dp_phy_test_pattern_fops},
|
||||
#ifdef CONFIG_DRM_AMD_DC_HDCP
|
||||
|
@ -2367,6 +2366,9 @@ void connector_debugfs_init(struct amdgpu_dm_connector *connector)
|
|||
debugfs_create_file("output_bpc", 0644, dir, connector,
|
||||
&output_bpc_fops);
|
||||
|
||||
debugfs_create_file("trigger_hotplug", 0644, dir, connector,
|
||||
&trigger_hotplug_debugfs_fops);
|
||||
|
||||
connector->debugfs_dpcd_address = 0;
|
||||
connector->debugfs_dpcd_size = 0;
|
||||
|
||||
|
|
|
@ -449,11 +449,12 @@ static void update_config(void *handle, struct cp_psp_stream_config *config)
|
|||
link->mode = mod_hdcp_signal_type_to_operation_mode(aconnector->dc_sink->sink_signal);
|
||||
|
||||
display->controller = CONTROLLER_ID_D0 + config->otg_inst;
|
||||
display->dig_fe = config->stream_enc_inst;
|
||||
link->dig_be = config->link_enc_inst;
|
||||
display->dig_fe = config->dig_fe;
|
||||
link->dig_be = config->dig_be;
|
||||
link->ddc_line = aconnector->dc_link->ddc_hw_inst + 1;
|
||||
link->dp.rev = aconnector->dc_link->dpcd_caps.dpcd_rev.raw;
|
||||
link->dp.mst_supported = config->mst_supported;
|
||||
link->dp.assr_enabled = config->assr_enabled;
|
||||
link->dp.mst_enabled = config->mst_enabled;
|
||||
display->adjust.disable = 1;
|
||||
link->adjust.auth_delay = 3;
|
||||
link->adjust.hdcp1.disable = 0;
|
||||
|
|
|
@ -832,6 +832,9 @@ bool compute_mst_dsc_configs_for_state(struct drm_atomic_state *state,
|
|||
if (computed_streams[i])
|
||||
continue;
|
||||
|
||||
if (dcn20_remove_stream_from_ctx(stream->ctx->dc, dc_state, stream) != DC_OK)
|
||||
return false;
|
||||
|
||||
mutex_lock(&aconnector->mst_mgr.lock);
|
||||
if (!compute_mst_dsc_configs_for_link(state, dc_state, stream->link)) {
|
||||
mutex_unlock(&aconnector->mst_mgr.lock);
|
||||
|
@ -849,7 +852,8 @@ bool compute_mst_dsc_configs_for_state(struct drm_atomic_state *state,
|
|||
stream = dc_state->streams[i];
|
||||
|
||||
if (stream->timing.flags.DSC == 1)
|
||||
dc_stream_add_dsc_to_resource(stream->ctx->dc, dc_state, stream);
|
||||
if (dc_stream_add_dsc_to_resource(stream->ctx->dc, dc_state, stream) != DC_OK)
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
|
|
|
@ -69,5 +69,7 @@ AMD_DISPLAY_FILES += $(AMD_DISPLAY_CORE)
|
|||
AMD_DISPLAY_FILES += $(AMD_DM_REG_UPDATE)
|
||||
|
||||
DC_DMUB += dc_dmub_srv.o
|
||||
DC_EDID += dc_edid_parser.o
|
||||
AMD_DISPLAY_DMUB = $(addprefix $(AMDDALPATH)/dc/,$(DC_DMUB))
|
||||
AMD_DISPLAY_FILES += $(AMD_DISPLAY_DMUB)
|
||||
AMD_DISPLAY_EDID = $(addprefix $(AMDDALPATH)/dc/,$(DC_EDID))
|
||||
AMD_DISPLAY_FILES += $(AMD_DISPLAY_DMUB) $(AMD_DISPLAY_EDID)
|
||||
|
|
|
@ -245,6 +245,23 @@ static enum bp_result encoder_control_digx_v3(
|
|||
cntl->enable_dp_audio);
|
||||
params.ucLaneNum = (uint8_t)(cntl->lanes_number);
|
||||
|
||||
switch (cntl->color_depth) {
|
||||
case COLOR_DEPTH_888:
|
||||
params.ucBitPerColor = PANEL_8BIT_PER_COLOR;
|
||||
break;
|
||||
case COLOR_DEPTH_101010:
|
||||
params.ucBitPerColor = PANEL_10BIT_PER_COLOR;
|
||||
break;
|
||||
case COLOR_DEPTH_121212:
|
||||
params.ucBitPerColor = PANEL_12BIT_PER_COLOR;
|
||||
break;
|
||||
case COLOR_DEPTH_161616:
|
||||
params.ucBitPerColor = PANEL_16BIT_PER_COLOR;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if (EXEC_BIOS_CMD_TABLE(DIGxEncoderControl, params))
|
||||
result = BP_RESULT_OK;
|
||||
|
||||
|
@ -274,6 +291,23 @@ static enum bp_result encoder_control_digx_v4(
|
|||
cntl->enable_dp_audio));
|
||||
params.ucLaneNum = (uint8_t)(cntl->lanes_number);
|
||||
|
||||
switch (cntl->color_depth) {
|
||||
case COLOR_DEPTH_888:
|
||||
params.ucBitPerColor = PANEL_8BIT_PER_COLOR;
|
||||
break;
|
||||
case COLOR_DEPTH_101010:
|
||||
params.ucBitPerColor = PANEL_10BIT_PER_COLOR;
|
||||
break;
|
||||
case COLOR_DEPTH_121212:
|
||||
params.ucBitPerColor = PANEL_12BIT_PER_COLOR;
|
||||
break;
|
||||
case COLOR_DEPTH_161616:
|
||||
params.ucBitPerColor = PANEL_16BIT_PER_COLOR;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if (EXEC_BIOS_CMD_TABLE(DIGxEncoderControl, params))
|
||||
result = BP_RESULT_OK;
|
||||
|
||||
|
@ -1057,6 +1091,19 @@ static enum bp_result set_pixel_clock_v5(
|
|||
* driver choose program it itself, i.e. here we program it
|
||||
* to 888 by default.
|
||||
*/
|
||||
if (bp_params->signal_type == SIGNAL_TYPE_HDMI_TYPE_A)
|
||||
switch (bp_params->color_depth) {
|
||||
case TRANSMITTER_COLOR_DEPTH_30:
|
||||
/* yes this is correct, the atom define is wrong */
|
||||
clk.sPCLKInput.ucMiscInfo |= PIXEL_CLOCK_V5_MISC_HDMI_32BPP;
|
||||
break;
|
||||
case TRANSMITTER_COLOR_DEPTH_36:
|
||||
/* yes this is correct, the atom define is wrong */
|
||||
clk.sPCLKInput.ucMiscInfo |= PIXEL_CLOCK_V5_MISC_HDMI_30BPP;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if (EXEC_BIOS_CMD_TABLE(SetPixelClock, clk))
|
||||
result = BP_RESULT_OK;
|
||||
|
@ -1135,6 +1182,20 @@ static enum bp_result set_pixel_clock_v6(
|
|||
* driver choose program it itself, i.e. here we pass required
|
||||
* target rate that includes deep color.
|
||||
*/
|
||||
if (bp_params->signal_type == SIGNAL_TYPE_HDMI_TYPE_A)
|
||||
switch (bp_params->color_depth) {
|
||||
case TRANSMITTER_COLOR_DEPTH_30:
|
||||
clk.sPCLKInput.ucMiscInfo |= PIXEL_CLOCK_V6_MISC_HDMI_30BPP_V6;
|
||||
break;
|
||||
case TRANSMITTER_COLOR_DEPTH_36:
|
||||
clk.sPCLKInput.ucMiscInfo |= PIXEL_CLOCK_V6_MISC_HDMI_36BPP_V6;
|
||||
break;
|
||||
case TRANSMITTER_COLOR_DEPTH_48:
|
||||
clk.sPCLKInput.ucMiscInfo |= PIXEL_CLOCK_V6_MISC_HDMI_48BPP;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if (EXEC_BIOS_CMD_TABLE(SetPixelClock, clk))
|
||||
result = BP_RESULT_OK;
|
||||
|
|
|
@ -187,17 +187,6 @@ static void ramp_up_dispclk_with_dpp(
|
|||
clk_mgr->base.clks.max_supported_dppclk_khz = new_clocks->max_supported_dppclk_khz;
|
||||
}
|
||||
|
||||
static bool is_mpo_enabled(struct dc_state *context)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < context->stream_count; i++) {
|
||||
if (context->stream_status[i].plane_count > 1)
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
static void rv1_update_clocks(struct clk_mgr *clk_mgr_base,
|
||||
struct dc_state *context,
|
||||
bool safe_to_lower)
|
||||
|
@ -295,22 +284,9 @@ static void rv1_update_clocks(struct clk_mgr *clk_mgr_base,
|
|||
if (pp_smu->set_hard_min_fclk_by_freq &&
|
||||
pp_smu->set_hard_min_dcfclk_by_freq &&
|
||||
pp_smu->set_min_deep_sleep_dcfclk) {
|
||||
// Only increase clocks when display is active and MPO is enabled
|
||||
if (display_count && is_mpo_enabled(context)) {
|
||||
pp_smu->set_hard_min_fclk_by_freq(&pp_smu->pp_smu,
|
||||
((new_clocks->fclk_khz / 1000) * 101) / 100);
|
||||
pp_smu->set_hard_min_dcfclk_by_freq(&pp_smu->pp_smu,
|
||||
((new_clocks->dcfclk_khz / 1000) * 101) / 100);
|
||||
pp_smu->set_min_deep_sleep_dcfclk(&pp_smu->pp_smu,
|
||||
(new_clocks->dcfclk_deep_sleep_khz + 999) / 1000);
|
||||
} else {
|
||||
pp_smu->set_hard_min_fclk_by_freq(&pp_smu->pp_smu,
|
||||
new_clocks->fclk_khz / 1000);
|
||||
pp_smu->set_hard_min_dcfclk_by_freq(&pp_smu->pp_smu,
|
||||
new_clocks->dcfclk_khz / 1000);
|
||||
pp_smu->set_min_deep_sleep_dcfclk(&pp_smu->pp_smu,
|
||||
(new_clocks->dcfclk_deep_sleep_khz + 999) / 1000);
|
||||
}
|
||||
pp_smu->set_hard_min_fclk_by_freq(&pp_smu->pp_smu, new_clocks->fclk_khz / 1000);
|
||||
pp_smu->set_hard_min_dcfclk_by_freq(&pp_smu->pp_smu, new_clocks->dcfclk_khz / 1000);
|
||||
pp_smu->set_min_deep_sleep_dcfclk(&pp_smu->pp_smu, (new_clocks->dcfclk_deep_sleep_khz + 999) / 1000);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -146,15 +146,15 @@ static noinline void dcn3_build_wm_range_table(struct clk_mgr_internal *clk_mgr)
|
|||
clk_mgr->base.bw_params->wm_table.nv_entries[WM_C].pmfw_breakdown.max_uclk = 0xFFFF;
|
||||
|
||||
/* Set D - MALL - SR enter and exit times adjusted for MALL */
|
||||
// clk_mgr->base.bw_params->wm_table.nv_entries[WM_D].valid = true;
|
||||
// clk_mgr->base.bw_params->wm_table.nv_entries[WM_D].dml_input.pstate_latency_us = pstate_latency_us;
|
||||
// clk_mgr->base.bw_params->wm_table.nv_entries[WM_D].dml_input.sr_exit_time_us = 2;
|
||||
// clk_mgr->base.bw_params->wm_table.nv_entries[WM_D].dml_input.sr_enter_plus_exit_time_us = 4;
|
||||
// clk_mgr->base.bw_params->wm_table.nv_entries[WM_D].pmfw_breakdown.wm_type = WATERMARKS_MALL;
|
||||
// clk_mgr->base.bw_params->wm_table.nv_entries[WM_D].pmfw_breakdown.min_dcfclk = 0;
|
||||
// clk_mgr->base.bw_params->wm_table.nv_entries[WM_D].pmfw_breakdown.max_dcfclk = 0xFFFF;
|
||||
// clk_mgr->base.bw_params->wm_table.nv_entries[WM_D].pmfw_breakdown.min_uclk = min_uclk_mhz;
|
||||
// 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].valid = true;
|
||||
clk_mgr->base.bw_params->wm_table.nv_entries[WM_D].dml_input.pstate_latency_us = pstate_latency_us;
|
||||
clk_mgr->base.bw_params->wm_table.nv_entries[WM_D].dml_input.sr_exit_time_us = 2;
|
||||
clk_mgr->base.bw_params->wm_table.nv_entries[WM_D].dml_input.sr_enter_plus_exit_time_us = 4;
|
||||
clk_mgr->base.bw_params->wm_table.nv_entries[WM_D].pmfw_breakdown.wm_type = WATERMARKS_MALL;
|
||||
clk_mgr->base.bw_params->wm_table.nv_entries[WM_D].pmfw_breakdown.min_dcfclk = 0;
|
||||
clk_mgr->base.bw_params->wm_table.nv_entries[WM_D].pmfw_breakdown.max_dcfclk = 0xFFFF;
|
||||
clk_mgr->base.bw_params->wm_table.nv_entries[WM_D].pmfw_breakdown.min_uclk = min_uclk_mhz;
|
||||
clk_mgr->base.bw_params->wm_table.nv_entries[WM_D].pmfw_breakdown.max_uclk = 0xFFFF;
|
||||
}
|
||||
|
||||
void dcn3_init_clocks(struct clk_mgr *clk_mgr_base)
|
||||
|
|
|
@ -75,7 +75,8 @@ int vg_get_active_display_cnt_wa(
|
|||
const struct dc_link *link = dc->links[i];
|
||||
|
||||
/* abusing the fact that the dig and phy are coupled to see if the phy is enabled */
|
||||
if (link->link_enc->funcs->is_dig_enabled(link->link_enc))
|
||||
if (link->link_enc->funcs->is_dig_enabled &&
|
||||
link->link_enc->funcs->is_dig_enabled(link->link_enc))
|
||||
display_count++;
|
||||
}
|
||||
|
||||
|
|
|
@ -175,6 +175,8 @@ static bool create_links(
|
|||
|
||||
connectors_num = bios->funcs->get_connectors_number(bios);
|
||||
|
||||
DC_LOG_DC("BIOS object table - number of connectors: %d", connectors_num);
|
||||
|
||||
if (connectors_num > ENUM_ID_COUNT) {
|
||||
dm_error(
|
||||
"DC: Number of connectors %d exceeds maximum of %d!\n",
|
||||
|
@ -193,6 +195,8 @@ static bool create_links(
|
|||
struct link_init_data link_init_params = {0};
|
||||
struct dc_link *link;
|
||||
|
||||
DC_LOG_DC("BIOS object table - printing link object info for connector number: %d, link_index: %d", i, dc->link_count);
|
||||
|
||||
link_init_params.ctx = dc->ctx;
|
||||
/* next BIOS object table connector */
|
||||
link_init_params.connector_index = i;
|
||||
|
@ -225,6 +229,8 @@ static bool create_links(
|
|||
}
|
||||
}
|
||||
|
||||
DC_LOG_DC("BIOS object table - end");
|
||||
|
||||
for (i = 0; i < num_virtual_links; i++) {
|
||||
struct dc_link *link = kzalloc(sizeof(*link), GFP_KERNEL);
|
||||
struct encoder_init_data enc_init = {0};
|
||||
|
@ -706,7 +712,6 @@ static bool dc_construct(struct dc *dc,
|
|||
}
|
||||
|
||||
dc->dcn_ip = dcn_ip;
|
||||
dc->soc_bounding_box = init_params->soc_bounding_box;
|
||||
#endif
|
||||
|
||||
if (!dc_construct_ctx(dc, init_params)) {
|
||||
|
@ -756,6 +761,10 @@ static bool dc_construct(struct dc *dc,
|
|||
if (!dc->res_pool)
|
||||
goto fail;
|
||||
|
||||
/* set i2c speed if not done by the respective dcnxxx__resource.c */
|
||||
if (dc->caps.i2c_speed_in_khz_hdcp == 0)
|
||||
dc->caps.i2c_speed_in_khz_hdcp = dc->caps.i2c_speed_in_khz;
|
||||
|
||||
dc->clk_mgr = dc_clk_mgr_create(dc->ctx, dc->res_pool->pp_smu, dc->res_pool->dccg);
|
||||
if (!dc->clk_mgr)
|
||||
goto fail;
|
||||
|
@ -763,8 +772,6 @@ static bool dc_construct(struct dc *dc,
|
|||
dc->clk_mgr->force_smu_not_present = init_params->force_smu_not_present;
|
||||
#endif
|
||||
|
||||
dc->debug.force_ignore_link_settings = init_params->force_ignore_link_settings;
|
||||
|
||||
if (dc->res_pool->funcs->update_bw_bounding_box)
|
||||
dc->res_pool->funcs->update_bw_bounding_box(dc, dc->clk_mgr->bw_params);
|
||||
|
||||
|
@ -2686,8 +2693,7 @@ void dc_commit_updates_for_stream(struct dc *dc,
|
|||
struct dc_surface_update *srf_updates,
|
||||
int surface_count,
|
||||
struct dc_stream_state *stream,
|
||||
struct dc_stream_update *stream_update,
|
||||
struct dc_state *state)
|
||||
struct dc_stream_update *stream_update)
|
||||
{
|
||||
const struct dc_stream_status *stream_status;
|
||||
enum surface_update_type update_type;
|
||||
|
@ -2706,6 +2712,12 @@ void dc_commit_updates_for_stream(struct dc *dc,
|
|||
|
||||
|
||||
if (update_type >= UPDATE_TYPE_FULL) {
|
||||
struct dc_plane_state *new_planes[MAX_SURFACES];
|
||||
|
||||
memset(new_planes, 0, sizeof(new_planes));
|
||||
|
||||
for (i = 0; i < surface_count; i++)
|
||||
new_planes[i] = srf_updates[i].surface;
|
||||
|
||||
/* initialize scratch memory for building context */
|
||||
context = dc_create_state(dc);
|
||||
|
@ -2714,15 +2726,21 @@ void dc_commit_updates_for_stream(struct dc *dc,
|
|||
return;
|
||||
}
|
||||
|
||||
dc_resource_state_copy_construct(state, context);
|
||||
dc_resource_state_copy_construct(
|
||||
dc->current_state, context);
|
||||
|
||||
for (i = 0; i < dc->res_pool->pipe_count; i++) {
|
||||
struct pipe_ctx *new_pipe = &context->res_ctx.pipe_ctx[i];
|
||||
struct pipe_ctx *old_pipe = &dc->current_state->res_ctx.pipe_ctx[i];
|
||||
|
||||
if (new_pipe->plane_state && new_pipe->plane_state != old_pipe->plane_state)
|
||||
new_pipe->plane_state->force_full_update = true;
|
||||
/*remove old surfaces from context */
|
||||
if (!dc_rem_all_planes_for_stream(dc, stream, context)) {
|
||||
DC_ERROR("Failed to remove streams for new validate context!\n");
|
||||
return;
|
||||
}
|
||||
|
||||
/* add surface to context */
|
||||
if (!dc_add_all_planes_for_stream(dc, stream, new_planes, surface_count, context)) {
|
||||
DC_ERROR("Failed to add streams for new validate context!\n");
|
||||
return;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
@ -3150,11 +3168,11 @@ void dc_lock_memory_clock_frequency(struct dc *dc)
|
|||
core_link_enable_stream(dc->current_state, &dc->current_state->res_ctx.pipe_ctx[i]);
|
||||
}
|
||||
|
||||
bool dc_is_plane_eligible_for_idle_optimizaitons(struct dc *dc, struct dc_plane_state *plane)
|
||||
bool dc_is_plane_eligible_for_idle_optimizations(struct dc *dc, struct dc_plane_state *plane,
|
||||
struct dc_cursor_attributes *cursor_attr)
|
||||
{
|
||||
if (dc->hwss.does_plane_fit_in_mall && dc->hwss.does_plane_fit_in_mall(dc, plane))
|
||||
if (dc->hwss.does_plane_fit_in_mall && dc->hwss.does_plane_fit_in_mall(dc, plane, cursor_attr))
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
|
@ -1401,10 +1401,12 @@ static bool dc_link_construct(struct dc_link *link,
|
|||
link->link_id =
|
||||
bios->funcs->get_connector_id(bios, init_params->connector_index);
|
||||
|
||||
DC_LOG_DC("BIOS object table - link_id: %d", link->link_id.id);
|
||||
|
||||
if (bios->funcs->get_disp_connector_caps_info) {
|
||||
bios->funcs->get_disp_connector_caps_info(bios, link->link_id, &disp_connect_caps_info);
|
||||
link->is_internal_display = disp_connect_caps_info.INTERNAL_DISPLAY;
|
||||
DC_LOG_DC("BIOS object table - is_internal_display: %d", link->is_internal_display);
|
||||
}
|
||||
|
||||
if (link->link_id.type != OBJECT_TYPE_CONNECTOR) {
|
||||
|
@ -1419,10 +1421,14 @@ static bool dc_link_construct(struct dc_link *link,
|
|||
|
||||
link->hpd_gpio = get_hpd_gpio(link->ctx->dc_bios, link->link_id,
|
||||
link->ctx->gpio_service);
|
||||
|
||||
if (link->hpd_gpio) {
|
||||
dal_gpio_open(link->hpd_gpio, GPIO_MODE_INTERRUPT);
|
||||
dal_gpio_unlock_pin(link->hpd_gpio);
|
||||
link->irq_source_hpd = dal_irq_get_source(link->hpd_gpio);
|
||||
|
||||
DC_LOG_DC("BIOS object table - hpd_gpio id: %d", link->hpd_gpio->id);
|
||||
DC_LOG_DC("BIOS object table - hpd_gpio en: %d", link->hpd_gpio->en);
|
||||
}
|
||||
|
||||
switch (link->link_id.id) {
|
||||
|
@ -1481,6 +1487,11 @@ static bool dc_link_construct(struct dc_link *link,
|
|||
goto ddc_create_fail;
|
||||
}
|
||||
|
||||
if (!link->ddc->ddc_pin) {
|
||||
DC_ERROR("Failed to get I2C info for connector!\n");
|
||||
goto ddc_create_fail;
|
||||
}
|
||||
|
||||
link->ddc_hw_inst =
|
||||
dal_ddc_get_line(dal_ddc_service_get_ddc_pin(link->ddc));
|
||||
|
||||
|
@ -1519,6 +1530,8 @@ static bool dc_link_construct(struct dc_link *link,
|
|||
goto link_enc_create_fail;
|
||||
}
|
||||
|
||||
DC_LOG_DC("BIOS object table - DP_IS_USB_C: %d", link->link_enc->features.flags.bits.DP_IS_USB_C);
|
||||
|
||||
link->link_enc_hw_inst = link->link_enc->transmitter;
|
||||
|
||||
for (i = 0; i < 4; i++) {
|
||||
|
@ -1541,6 +1554,10 @@ static bool dc_link_construct(struct dc_link *link,
|
|||
if (link->device_tag.dev_id.device_type == DEVICE_TYPE_LCD &&
|
||||
link->connector_signal == SIGNAL_TYPE_RGB)
|
||||
continue;
|
||||
|
||||
DC_LOG_DC("BIOS object table - device_tag.acpi_device: %d", link->device_tag.acpi_device);
|
||||
DC_LOG_DC("BIOS object table - device_tag.dev_id.device_type: %d", link->device_tag.dev_id.device_type);
|
||||
DC_LOG_DC("BIOS object table - device_tag.dev_id.enum_id: %d", link->device_tag.dev_id.enum_id);
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -1559,10 +1576,14 @@ static bool dc_link_construct(struct dc_link *link,
|
|||
path->device_acpi_enum == link->device_tag.acpi_device) {
|
||||
link->ddi_channel_mapping = path->channel_mapping;
|
||||
link->chip_caps = path->caps;
|
||||
DC_LOG_DC("BIOS object table - ddi_channel_mapping: 0x%04X", link->ddi_channel_mapping.raw);
|
||||
DC_LOG_DC("BIOS object table - chip_caps: %d", link->chip_caps);
|
||||
} else if (path->device_tag ==
|
||||
link->device_tag.dev_id.raw_device_tag) {
|
||||
link->ddi_channel_mapping = path->channel_mapping;
|
||||
link->chip_caps = path->caps;
|
||||
DC_LOG_DC("BIOS object table - ddi_channel_mapping: 0x%04X", link->ddi_channel_mapping.raw);
|
||||
DC_LOG_DC("BIOS object table - chip_caps: %d", link->chip_caps);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
@ -1581,6 +1602,7 @@ static bool dc_link_construct(struct dc_link *link,
|
|||
|
||||
link->psr_settings.psr_version = DC_PSR_VERSION_UNSUPPORTED;
|
||||
|
||||
DC_LOG_DC("BIOS object table - %s finished successfully.\n", __func__);
|
||||
return true;
|
||||
device_tag_fail:
|
||||
link->link_enc->funcs->destroy(&link->link_enc);
|
||||
|
@ -1597,6 +1619,7 @@ static bool dc_link_construct(struct dc_link *link,
|
|||
link->hpd_gpio = NULL;
|
||||
}
|
||||
|
||||
DC_LOG_DC("BIOS object table - %s failed.\n", __func__);
|
||||
kfree(info);
|
||||
|
||||
return false;
|
||||
|
@ -3146,17 +3169,17 @@ static void update_psp_stream_config(struct pipe_ctx *pipe_ctx, bool dpms_off)
|
|||
{
|
||||
struct cp_psp *cp_psp = &pipe_ctx->stream->ctx->cp_psp;
|
||||
if (cp_psp && cp_psp->funcs.update_stream_config) {
|
||||
struct cp_psp_stream_config config;
|
||||
|
||||
memset(&config, 0, sizeof(config));
|
||||
struct cp_psp_stream_config config = {0};
|
||||
enum dp_panel_mode panel_mode =
|
||||
dp_get_panel_mode(pipe_ctx->stream->link);
|
||||
|
||||
config.otg_inst = (uint8_t) pipe_ctx->stream_res.tg->inst;
|
||||
/*stream_enc_inst*/
|
||||
config.stream_enc_inst = (uint8_t) pipe_ctx->stream_res.stream_enc->stream_enc_inst;
|
||||
config.link_enc_inst = pipe_ctx->stream->link->link_enc_hw_inst;
|
||||
config.dig_fe = (uint8_t) pipe_ctx->stream_res.stream_enc->stream_enc_inst;
|
||||
config.dig_be = pipe_ctx->stream->link->link_enc_hw_inst;
|
||||
config.dpms_off = dpms_off;
|
||||
config.dm_stream_ctx = pipe_ctx->stream->dm_stream_context;
|
||||
config.mst_supported = (pipe_ctx->stream->signal ==
|
||||
config.assr_enabled = (panel_mode == DP_PANEL_MODE_EDP);
|
||||
config.mst_enabled = (pipe_ctx->stream->signal ==
|
||||
SIGNAL_TYPE_DISPLAY_PORT_MST);
|
||||
cp_psp->funcs.update_stream_config(cp_psp->handle, &config);
|
||||
}
|
||||
|
@ -3701,9 +3724,10 @@ bool dc_link_should_enable_fec(const struct dc_link *link)
|
|||
bool is_fec_disable = false;
|
||||
bool ret = false;
|
||||
|
||||
if (link->connector_signal != SIGNAL_TYPE_DISPLAY_PORT_MST &&
|
||||
if ((link->connector_signal != SIGNAL_TYPE_DISPLAY_PORT_MST &&
|
||||
link->local_sink &&
|
||||
link->local_sink->edid_caps.panel_patch.disable_fec)
|
||||
link->local_sink->edid_caps.panel_patch.disable_fec) ||
|
||||
link->connector_signal == SIGNAL_TYPE_EDP) // Disable FEC for eDP
|
||||
is_fec_disable = true;
|
||||
|
||||
if (dc_link_is_fec_supported(link) && !link->dc->debug.disable_fec && !is_fec_disable)
|
||||
|
|
|
@ -37,12 +37,16 @@
|
|||
#include "dc_link_ddc.h"
|
||||
#include "dce/dce_aux.h"
|
||||
|
||||
/*DP to Dual link DVI converter*/
|
||||
#define DC_LOGGER_INIT(logger)
|
||||
|
||||
static const uint8_t DP_VGA_DONGLE_BRANCH_DEV_NAME[] = "DpVga";
|
||||
/* DP to Dual link DVI converter */
|
||||
static const uint8_t DP_DVI_CONVERTER_ID_4[] = "m2DVIa";
|
||||
static const uint8_t DP_DVI_CONVERTER_ID_5[] = "3393N2";
|
||||
|
||||
#define AUX_POWER_UP_WA_DELAY 500
|
||||
#define I2C_OVER_AUX_DEFER_WA_DELAY 70
|
||||
#define DPVGA_DONGLE_AUX_DEFER_WA_DELAY 40
|
||||
#define I2C_OVER_AUX_DEFER_WA_DELAY_1MS 1
|
||||
|
||||
/* CV smart dongle slave address for retrieving supported HDTV modes*/
|
||||
|
@ -194,6 +198,10 @@ static void ddc_service_construct(
|
|||
if (BP_RESULT_OK != dcb->funcs->get_i2c_info(dcb, init_data->id, &i2c_info)) {
|
||||
ddc_service->ddc_pin = NULL;
|
||||
} else {
|
||||
DC_LOGGER_INIT(ddc_service->ctx->logger);
|
||||
DC_LOG_DC("BIOS object table - i2c_line: %d", i2c_info.i2c_line);
|
||||
DC_LOG_DC("BIOS object table - i2c_engine_id: %d", i2c_info.i2c_engine_id);
|
||||
|
||||
hw_info.ddc_channel = i2c_info.i2c_line;
|
||||
if (ddc_service->link != NULL)
|
||||
hw_info.hw_supported = i2c_info.i2c_hw_assist;
|
||||
|
@ -286,6 +294,15 @@ static uint32_t defer_delay_converter_wa(
|
|||
{
|
||||
struct dc_link *link = ddc->link;
|
||||
|
||||
if (link->dpcd_caps.dongle_type == DISPLAY_DONGLE_DP_VGA_CONVERTER &&
|
||||
link->dpcd_caps.branch_dev_id == DP_BRANCH_DEVICE_ID_0080E1 &&
|
||||
!memcmp(link->dpcd_caps.branch_dev_name,
|
||||
DP_VGA_DONGLE_BRANCH_DEV_NAME,
|
||||
sizeof(link->dpcd_caps.branch_dev_name)))
|
||||
|
||||
return defer_delay > DPVGA_DONGLE_AUX_DEFER_WA_DELAY ?
|
||||
defer_delay : DPVGA_DONGLE_AUX_DEFER_WA_DELAY;
|
||||
|
||||
if (link->dpcd_caps.branch_dev_id == DP_BRANCH_DEVICE_ID_0080E1 &&
|
||||
!memcmp(link->dpcd_caps.branch_dev_name,
|
||||
DP_DVI_CONVERTER_ID_4,
|
||||
|
|
|
@ -126,9 +126,7 @@ static void dpcd_set_training_pattern(
|
|||
static enum dc_dp_training_pattern decide_cr_training_pattern(
|
||||
const struct dc_link_settings *link_settings)
|
||||
{
|
||||
enum dc_dp_training_pattern pattern = DP_TRAINING_PATTERN_SEQUENCE_1;
|
||||
|
||||
return pattern;
|
||||
return DP_TRAINING_PATTERN_SEQUENCE_1;
|
||||
}
|
||||
|
||||
static enum dc_dp_training_pattern decide_eq_training_pattern(struct dc_link *link,
|
||||
|
@ -892,14 +890,14 @@ static uint32_t translate_training_aux_read_interval(uint32_t dpcd_aux_read_inte
|
|||
|
||||
switch (dpcd_aux_read_interval) {
|
||||
case 0x01:
|
||||
aux_rd_interval_us = 400;
|
||||
break;
|
||||
case 0x02:
|
||||
aux_rd_interval_us = 4000;
|
||||
break;
|
||||
case 0x03:
|
||||
case 0x02:
|
||||
aux_rd_interval_us = 8000;
|
||||
break;
|
||||
case 0x03:
|
||||
aux_rd_interval_us = 12000;
|
||||
break;
|
||||
case 0x04:
|
||||
aux_rd_interval_us = 16000;
|
||||
break;
|
||||
|
|
|
@ -1153,8 +1153,8 @@ bool resource_build_scaling_params(struct pipe_ctx *pipe_ctx)
|
|||
|
||||
calculate_viewport(pipe_ctx);
|
||||
|
||||
if (pipe_ctx->plane_res.scl_data.viewport.height < 12 ||
|
||||
pipe_ctx->plane_res.scl_data.viewport.width < 12) {
|
||||
if (pipe_ctx->plane_res.scl_data.viewport.height < MIN_VIEWPORT_SIZE ||
|
||||
pipe_ctx->plane_res.scl_data.viewport.width < MIN_VIEWPORT_SIZE) {
|
||||
if (store_h_border_left) {
|
||||
restore_border_left_from_dst(pipe_ctx,
|
||||
store_h_border_left);
|
||||
|
|
|
@ -42,12 +42,13 @@
|
|||
#include "inc/hw/dmcu.h"
|
||||
#include "dml/display_mode_lib.h"
|
||||
|
||||
#define DC_VER "3.2.118"
|
||||
#define DC_VER "3.2.121"
|
||||
|
||||
#define MAX_SURFACES 3
|
||||
#define MAX_PLANES 6
|
||||
#define MAX_STREAMS 6
|
||||
#define MAX_SINKS_PER_LINK 4
|
||||
#define MIN_VIEWPORT_SIZE 12
|
||||
|
||||
/*******************************************************************************
|
||||
* Display Core Interfaces
|
||||
|
@ -502,6 +503,8 @@ struct dc_debug_options {
|
|||
#if defined(CONFIG_DRM_AMD_DC_DCN)
|
||||
bool disable_idle_power_optimizations;
|
||||
unsigned int mall_size_override;
|
||||
unsigned int mall_additional_timer_percent;
|
||||
bool mall_error_as_fatal;
|
||||
#endif
|
||||
bool dmub_command_table; /* for testing only */
|
||||
struct dc_bw_validation_profile bw_val_profile;
|
||||
|
@ -524,7 +527,6 @@ struct dc_debug_options {
|
|||
bool usbc_combo_phy_reset_wa;
|
||||
bool disable_dsc;
|
||||
bool enable_dram_clock_change_one_display_vactive;
|
||||
bool force_ignore_link_settings;
|
||||
union mem_low_power_enable_options enable_mem_low_power;
|
||||
};
|
||||
|
||||
|
@ -636,7 +638,6 @@ struct dc {
|
|||
|
||||
const char *build_id;
|
||||
struct vm_helper *vm_helper;
|
||||
const struct gpu_info_soc_bounding_box_v1_0 *soc_bounding_box;
|
||||
};
|
||||
|
||||
enum frame_buffer_mode {
|
||||
|
@ -674,16 +675,10 @@ struct dc_init_data {
|
|||
struct dc_config flags;
|
||||
uint64_t log_mask;
|
||||
|
||||
/**
|
||||
* gpu_info FW provided soc bounding box struct or 0 if not
|
||||
* available in FW
|
||||
*/
|
||||
const struct gpu_info_soc_bounding_box_v1_0 *soc_bounding_box;
|
||||
struct dpcd_vendor_signature vendor_signature;
|
||||
#if defined(CONFIG_DRM_AMD_DC_DCN)
|
||||
bool force_smu_not_present;
|
||||
#endif
|
||||
bool force_ignore_link_settings;
|
||||
};
|
||||
|
||||
struct dc_callback_init {
|
||||
|
@ -1272,8 +1267,8 @@ enum dc_status dc_set_clock(struct dc *dc, enum dc_clock_type clock_type, uint32
|
|||
void dc_get_clock(struct dc *dc, enum dc_clock_type clock_type, struct dc_clock_config *clock_cfg);
|
||||
#if defined(CONFIG_DRM_AMD_DC_DCN)
|
||||
|
||||
bool dc_is_plane_eligible_for_idle_optimizations(struct dc *dc,
|
||||
struct dc_plane_state *plane);
|
||||
bool dc_is_plane_eligible_for_idle_optimizations(struct dc *dc, struct dc_plane_state *plane,
|
||||
struct dc_cursor_attributes *cursor_attr);
|
||||
|
||||
void dc_allow_idle_optimizations(struct dc *dc, bool allow);
|
||||
|
||||
|
|
|
@ -51,6 +51,7 @@ struct dc_dsc_policy {
|
|||
int min_slice_height; // Must not be less than 8
|
||||
uint32_t max_target_bpp;
|
||||
uint32_t min_target_bpp;
|
||||
uint32_t preferred_bpp_x16;
|
||||
bool enable_dsc_when_not_needed;
|
||||
};
|
||||
|
||||
|
@ -62,8 +63,8 @@ bool dc_dsc_parse_dsc_dpcd(const struct dc *dc,
|
|||
bool dc_dsc_compute_bandwidth_range(
|
||||
const struct display_stream_compressor *dsc,
|
||||
uint32_t dsc_min_slice_height_override,
|
||||
uint32_t min_bpp,
|
||||
uint32_t max_bpp,
|
||||
uint32_t min_bpp_x16,
|
||||
uint32_t max_bpp_x16,
|
||||
const struct dsc_dec_dpcd_caps *dsc_sink_caps,
|
||||
const struct dc_crtc_timing *timing,
|
||||
struct dc_dsc_bw_range *range);
|
||||
|
@ -78,7 +79,7 @@ bool dc_dsc_compute_config(
|
|||
struct dc_dsc_config *dsc_cfg);
|
||||
|
||||
void dc_dsc_get_policy_for_timing(const struct dc_crtc_timing *timing,
|
||||
uint32_t max_target_bpp_limit_override,
|
||||
uint32_t max_target_bpp_limit_override_x16,
|
||||
struct dc_dsc_policy *policy);
|
||||
|
||||
void dc_dsc_policy_set_max_target_bpp_limit(uint32_t limit);
|
||||
|
|
80
drivers/gpu/drm/amd/display/dc/dc_edid_parser.c
Normal file
80
drivers/gpu/drm/amd/display/dc/dc_edid_parser.c
Normal file
|
@ -0,0 +1,80 @@
|
|||
/*
|
||||
* Copyright 2021 Advanced Micro Devices, Inc.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
|
||||
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
|
||||
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||
* OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
* Authors: AMD
|
||||
*
|
||||
*/
|
||||
|
||||
#include "dce/dce_dmcu.h"
|
||||
#include "dc_edid_parser.h"
|
||||
|
||||
bool dc_edid_parser_send_cea(struct dc *dc,
|
||||
int offset,
|
||||
int total_length,
|
||||
uint8_t *data,
|
||||
int length)
|
||||
{
|
||||
struct dmcu *dmcu = dc->res_pool->dmcu;
|
||||
|
||||
if (dmcu &&
|
||||
dmcu->funcs->is_dmcu_initialized(dmcu) &&
|
||||
dmcu->funcs->send_edid_cea) {
|
||||
return dmcu->funcs->send_edid_cea(dmcu,
|
||||
offset,
|
||||
total_length,
|
||||
data,
|
||||
length);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool dc_edid_parser_recv_cea_ack(struct dc *dc, int *offset)
|
||||
{
|
||||
struct dmcu *dmcu = dc->res_pool->dmcu;
|
||||
|
||||
if (dmcu &&
|
||||
dmcu->funcs->is_dmcu_initialized(dmcu) &&
|
||||
dmcu->funcs->recv_edid_cea_ack) {
|
||||
return dmcu->funcs->recv_edid_cea_ack(dmcu, offset);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool dc_edid_parser_recv_amd_vsdb(struct dc *dc,
|
||||
int *version,
|
||||
int *min_frame_rate,
|
||||
int *max_frame_rate)
|
||||
{
|
||||
struct dmcu *dmcu = dc->res_pool->dmcu;
|
||||
|
||||
if (dmcu &&
|
||||
dmcu->funcs->is_dmcu_initialized(dmcu) &&
|
||||
dmcu->funcs->recv_amd_vsdb) {
|
||||
return dmcu->funcs->recv_amd_vsdb(dmcu,
|
||||
version,
|
||||
min_frame_rate,
|
||||
max_frame_rate);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
44
drivers/gpu/drm/amd/display/dc/dc_edid_parser.h
Normal file
44
drivers/gpu/drm/amd/display/dc/dc_edid_parser.h
Normal file
|
@ -0,0 +1,44 @@
|
|||
/*
|
||||
* Copyright 2021 Advanced Micro Devices, Inc.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
|
||||
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
|
||||
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||
* OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
* Authors: AMD
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef _DC_EDID_PARSER_H_
|
||||
#define _DC_EDID_PARSER_H_
|
||||
|
||||
#include "core_types.h"
|
||||
|
||||
bool dc_edid_parser_send_cea(struct dc *dc,
|
||||
int offset,
|
||||
int total_length,
|
||||
uint8_t *data,
|
||||
int length);
|
||||
|
||||
bool dc_edid_parser_recv_cea_ack(struct dc *dc, int *offset);
|
||||
|
||||
bool dc_edid_parser_recv_amd_vsdb(struct dc *dc,
|
||||
int *version,
|
||||
int *min_frame_rate,
|
||||
int *max_frame_rate);
|
||||
|
||||
#endif /* _DC_EDID_PARSER_H_ */
|
|
@ -769,6 +769,7 @@ struct dc_crtc_timing {
|
|||
#endif
|
||||
|
||||
struct dc_crtc_timing_flags flags;
|
||||
uint32_t dsc_fixed_bits_per_pixel_x16; /* DSC target bitrate in 1/16 of bpp (e.g. 128 -> 8bpp) */
|
||||
struct dc_dsc_config dsc_cfg;
|
||||
};
|
||||
|
||||
|
|
|
@ -294,8 +294,7 @@ void dc_commit_updates_for_stream(struct dc *dc,
|
|||
struct dc_surface_update *srf_updates,
|
||||
int surface_count,
|
||||
struct dc_stream_state *stream,
|
||||
struct dc_stream_update *stream_update,
|
||||
struct dc_state *state);
|
||||
struct dc_stream_update *stream_update);
|
||||
/*
|
||||
* Log the current stream state.
|
||||
*/
|
||||
|
|
|
@ -870,6 +870,20 @@ static bool dce110_program_pix_clk(
|
|||
bp_pc_params.flags.SET_EXTERNAL_REF_DIV_SRC =
|
||||
pll_settings->use_external_clk;
|
||||
|
||||
switch (pix_clk_params->color_depth) {
|
||||
case COLOR_DEPTH_101010:
|
||||
bp_pc_params.color_depth = TRANSMITTER_COLOR_DEPTH_30;
|
||||
break;
|
||||
case COLOR_DEPTH_121212:
|
||||
bp_pc_params.color_depth = TRANSMITTER_COLOR_DEPTH_36;
|
||||
break;
|
||||
case COLOR_DEPTH_161616:
|
||||
bp_pc_params.color_depth = TRANSMITTER_COLOR_DEPTH_48;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if (clk_src->bios->funcs->set_pixel_clock(
|
||||
clk_src->bios, &bp_pc_params) != BP_RESULT_OK)
|
||||
return false;
|
||||
|
|
|
@ -57,6 +57,9 @@
|
|||
#define MCP_SYNC_PHY_LOCK 0x90
|
||||
#define MCP_SYNC_PHY_UNLOCK 0x91
|
||||
#define MCP_BL_SET_PWM_FRAC 0x6A /* Enable or disable Fractional PWM */
|
||||
#define MCP_SEND_EDID_CEA 0xA0
|
||||
#define EDID_CEA_CMD_ACK 1
|
||||
#define EDID_CEA_CMD_NACK 2
|
||||
#define MASTER_COMM_CNTL_REG__MASTER_COMM_INTERRUPT_MASK 0x00000001L
|
||||
|
||||
// PSP FW version
|
||||
|
@ -811,6 +814,120 @@ static bool dcn20_unlock_phy(struct dmcu *dmcu)
|
|||
return true;
|
||||
}
|
||||
|
||||
static bool dcn10_send_edid_cea(struct dmcu *dmcu,
|
||||
int offset,
|
||||
int total_length,
|
||||
uint8_t *data,
|
||||
int length)
|
||||
{
|
||||
struct dce_dmcu *dmcu_dce = TO_DCE_DMCU(dmcu);
|
||||
uint32_t header, data1, data2;
|
||||
|
||||
/* If microcontroller is not running, do nothing */
|
||||
if (dmcu->dmcu_state != DMCU_RUNNING)
|
||||
return false;
|
||||
|
||||
if (length > 8 || length <= 0)
|
||||
return false;
|
||||
|
||||
header = ((uint32_t)offset & 0xFFFF) << 16 | (total_length & 0xFFFF);
|
||||
data1 = (((uint32_t)data[0]) << 24) | (((uint32_t)data[1]) << 16) |
|
||||
(((uint32_t)data[2]) << 8) | ((uint32_t)data[3]);
|
||||
data2 = (((uint32_t)data[4]) << 24) | (((uint32_t)data[5]) << 16) |
|
||||
(((uint32_t)data[6]) << 8) | ((uint32_t)data[7]);
|
||||
|
||||
/* waitDMCUReadyForCmd */
|
||||
REG_WAIT(MASTER_COMM_CNTL_REG, MASTER_COMM_INTERRUPT, 0, 1, 10000);
|
||||
|
||||
/* setDMCUParam_Cmd */
|
||||
REG_UPDATE(MASTER_COMM_CMD_REG, MASTER_COMM_CMD_REG_BYTE0, MCP_SEND_EDID_CEA);
|
||||
|
||||
REG_WRITE(MASTER_COMM_DATA_REG1, header);
|
||||
REG_WRITE(MASTER_COMM_DATA_REG2, data1);
|
||||
REG_WRITE(MASTER_COMM_DATA_REG3, data2);
|
||||
|
||||
/* notifyDMCUMsg */
|
||||
REG_UPDATE(MASTER_COMM_CNTL_REG, MASTER_COMM_INTERRUPT, 1);
|
||||
|
||||
/* waitDMCUReadyForCmd */
|
||||
REG_WAIT(MASTER_COMM_CNTL_REG, MASTER_COMM_INTERRUPT, 0, 1, 10000);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool dcn10_get_scp_results(struct dmcu *dmcu,
|
||||
uint32_t *cmd,
|
||||
uint32_t *data1,
|
||||
uint32_t *data2,
|
||||
uint32_t *data3)
|
||||
{
|
||||
struct dce_dmcu *dmcu_dce = TO_DCE_DMCU(dmcu);
|
||||
|
||||
/* If microcontroller is not running, do nothing */
|
||||
if (dmcu->dmcu_state != DMCU_RUNNING)
|
||||
return false;
|
||||
|
||||
*cmd = REG_READ(SLAVE_COMM_CMD_REG);
|
||||
*data1 = REG_READ(SLAVE_COMM_DATA_REG1);
|
||||
*data2 = REG_READ(SLAVE_COMM_DATA_REG2);
|
||||
*data3 = REG_READ(SLAVE_COMM_DATA_REG3);
|
||||
|
||||
/* clear SCP interrupt */
|
||||
REG_UPDATE(SLAVE_COMM_CNTL_REG, SLAVE_COMM_INTERRUPT, 0);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool dcn10_recv_amd_vsdb(struct dmcu *dmcu,
|
||||
int *version,
|
||||
int *min_frame_rate,
|
||||
int *max_frame_rate)
|
||||
{
|
||||
uint32_t data[4];
|
||||
int cmd, ack, len;
|
||||
|
||||
if (!dcn10_get_scp_results(dmcu, &data[0], &data[1], &data[2], &data[3]))
|
||||
return false;
|
||||
|
||||
cmd = data[0] & 0x3FF;
|
||||
len = (data[0] >> 10) & 0x3F;
|
||||
ack = data[1];
|
||||
|
||||
if (cmd != MCP_SEND_EDID_CEA || ack != EDID_CEA_CMD_ACK || len != 12)
|
||||
return false;
|
||||
|
||||
if ((data[2] & 0xFF)) {
|
||||
*version = (data[2] >> 8) & 0xFF;
|
||||
*min_frame_rate = (data[3] >> 16) & 0xFFFF;
|
||||
*max_frame_rate = data[3] & 0xFFFF;
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool dcn10_recv_edid_cea_ack(struct dmcu *dmcu, int *offset)
|
||||
{
|
||||
uint32_t data[4];
|
||||
int cmd, ack;
|
||||
|
||||
if (!dcn10_get_scp_results(dmcu,
|
||||
&data[0], &data[1], &data[2], &data[3]))
|
||||
return false;
|
||||
|
||||
cmd = data[0] & 0x3FF;
|
||||
ack = data[1];
|
||||
|
||||
if (cmd != MCP_SEND_EDID_CEA)
|
||||
return false;
|
||||
|
||||
if (ack == EDID_CEA_CMD_ACK)
|
||||
return true;
|
||||
|
||||
*offset = data[2]; /* nack */
|
||||
return false;
|
||||
}
|
||||
|
||||
#endif //(CONFIG_DRM_AMD_DC_DCN)
|
||||
|
||||
static const struct dmcu_funcs dce_funcs = {
|
||||
|
@ -833,6 +950,9 @@ static const struct dmcu_funcs dcn10_funcs = {
|
|||
.get_psr_state = dcn10_get_dmcu_psr_state,
|
||||
.set_psr_wait_loop = dcn10_psr_wait_loop,
|
||||
.get_psr_wait_loop = dcn10_get_psr_wait_loop,
|
||||
.send_edid_cea = dcn10_send_edid_cea,
|
||||
.recv_amd_vsdb = dcn10_recv_amd_vsdb,
|
||||
.recv_edid_cea_ack = dcn10_recv_edid_cea_ack,
|
||||
.is_dmcu_initialized = dcn10_is_dmcu_initialized
|
||||
};
|
||||
|
||||
|
|
|
@ -40,6 +40,10 @@
|
|||
SR(MASTER_COMM_DATA_REG3), \
|
||||
SR(MASTER_COMM_CMD_REG), \
|
||||
SR(MASTER_COMM_CNTL_REG), \
|
||||
SR(SLAVE_COMM_DATA_REG1), \
|
||||
SR(SLAVE_COMM_DATA_REG2), \
|
||||
SR(SLAVE_COMM_DATA_REG3), \
|
||||
SR(SLAVE_COMM_CMD_REG), \
|
||||
SR(DMCU_IRAM_RD_CTRL), \
|
||||
SR(DMCU_IRAM_RD_DATA), \
|
||||
SR(DMCU_INTERRUPT_TO_UC_EN_MASK), \
|
||||
|
@ -112,6 +116,7 @@
|
|||
DMCU_SF(MASTER_COMM_CMD_REG, \
|
||||
MASTER_COMM_CMD_REG_BYTE0, mask_sh), \
|
||||
DMCU_SF(MASTER_COMM_CNTL_REG, MASTER_COMM_INTERRUPT, mask_sh), \
|
||||
DMCU_SF(SLAVE_COMM_CNTL_REG, SLAVE_COMM_INTERRUPT, mask_sh), \
|
||||
DMCU_SF(DMCU_INTERRUPT_TO_UC_EN_MASK, \
|
||||
STATIC_SCREEN1_INT_TO_UC_EN, mask_sh), \
|
||||
DMCU_SF(DMCU_INTERRUPT_TO_UC_EN_MASK, \
|
||||
|
@ -179,6 +184,7 @@
|
|||
type UC_IN_RESET; \
|
||||
type MASTER_COMM_CMD_REG_BYTE0; \
|
||||
type MASTER_COMM_INTERRUPT; \
|
||||
type SLAVE_COMM_INTERRUPT; \
|
||||
type DPHY_RX_FAST_TRAINING_CAPABLE; \
|
||||
type DPHY_LOAD_BS_COUNT; \
|
||||
type STATIC_SCREEN1_INT_TO_UC_EN; \
|
||||
|
@ -211,6 +217,11 @@ struct dce_dmcu_registers {
|
|||
uint32_t MASTER_COMM_DATA_REG3;
|
||||
uint32_t MASTER_COMM_CMD_REG;
|
||||
uint32_t MASTER_COMM_CNTL_REG;
|
||||
uint32_t SLAVE_COMM_DATA_REG1;
|
||||
uint32_t SLAVE_COMM_DATA_REG2;
|
||||
uint32_t SLAVE_COMM_DATA_REG3;
|
||||
uint32_t SLAVE_COMM_CMD_REG;
|
||||
uint32_t SLAVE_COMM_CNTL_REG;
|
||||
uint32_t DMCU_IRAM_RD_CTRL;
|
||||
uint32_t DMCU_IRAM_RD_DATA;
|
||||
uint32_t DMCU_INTERRUPT_TO_UC_EN_MASK;
|
||||
|
|
|
@ -563,6 +563,7 @@ static void dce110_stream_encoder_hdmi_set_stream_attribute(
|
|||
cntl.enable_dp_audio = enable_audio;
|
||||
cntl.pixel_clock = actual_pix_clk_khz;
|
||||
cntl.lanes_number = LANE_COUNT_FOUR;
|
||||
cntl.color_depth = crtc_timing->display_color_depth;
|
||||
|
||||
if (enc110->base.bp->funcs->encoder_control(
|
||||
enc110->base.bp, &cntl) != BP_RESULT_OK)
|
||||
|
|
|
@ -599,12 +599,12 @@ static void set_clamp(
|
|||
clamp_max = 0x3FC0;
|
||||
break;
|
||||
case COLOR_DEPTH_101010:
|
||||
/* 10bit MSB aligned on 14 bit bus '11 1111 1111 1100' */
|
||||
clamp_max = 0x3FFC;
|
||||
/* 10bit MSB aligned on 14 bit bus '11 1111 1111 0000' */
|
||||
clamp_max = 0x3FF0;
|
||||
break;
|
||||
case COLOR_DEPTH_121212:
|
||||
/* 12bit MSB aligned on 14 bit bus '11 1111 1111 1111' */
|
||||
clamp_max = 0x3FFF;
|
||||
/* 12bit MSB aligned on 14 bit bus '11 1111 1111 1100' */
|
||||
clamp_max = 0x3FFC;
|
||||
break;
|
||||
default:
|
||||
clamp_max = 0x3FC0;
|
||||
|
|
|
@ -1224,6 +1224,7 @@ void dcn10_init_pipes(struct dc *dc, struct dc_state *context)
|
|||
// signals when OTG blanked. This is to prevent pipe from
|
||||
// requesting data while in PSR.
|
||||
tg->funcs->tg_init(tg);
|
||||
hubp->power_gated = true;
|
||||
continue;
|
||||
}
|
||||
|
||||
|
@ -3134,7 +3135,7 @@ void dcn10_setup_stereo(struct pipe_ctx *pipe_ctx, struct dc *dc)
|
|||
|
||||
pipe_ctx->stream_res.opp->funcs->opp_program_stereo(
|
||||
pipe_ctx->stream_res.opp,
|
||||
flags.PROGRAM_STEREO == 1 ? true:false,
|
||||
flags.PROGRAM_STEREO == 1,
|
||||
&stream->timing);
|
||||
|
||||
pipe_ctx->stream_res.tg->funcs->program_stereo(
|
||||
|
|
|
@ -3606,7 +3606,6 @@ static enum dml_project get_dml_project_version(uint32_t hw_internal_rev)
|
|||
static bool init_soc_bounding_box(struct dc *dc,
|
||||
struct dcn20_resource_pool *pool)
|
||||
{
|
||||
const struct gpu_info_soc_bounding_box_v1_0 *bb = dc->soc_bounding_box;
|
||||
struct _vcs_dpi_soc_bounding_box_st *loaded_bb =
|
||||
get_asic_rev_soc_bb(dc->ctx->asic_id.hw_internal_rev);
|
||||
struct _vcs_dpi_ip_params_st *loaded_ip =
|
||||
|
@ -3614,116 +3613,6 @@ static bool init_soc_bounding_box(struct dc *dc,
|
|||
|
||||
DC_LOGGER_INIT(dc->ctx->logger);
|
||||
|
||||
/* TODO: upstream NV12 bounding box when its launched */
|
||||
if (!bb && ASICREV_IS_NAVI12_P(dc->ctx->asic_id.hw_internal_rev)) {
|
||||
DC_LOG_ERROR("%s: not valid soc bounding box/n", __func__);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (bb && ASICREV_IS_NAVI12_P(dc->ctx->asic_id.hw_internal_rev)) {
|
||||
int i;
|
||||
|
||||
dcn2_0_nv12_soc.sr_exit_time_us =
|
||||
fixed16_to_double_to_cpu(bb->sr_exit_time_us);
|
||||
dcn2_0_nv12_soc.sr_enter_plus_exit_time_us =
|
||||
fixed16_to_double_to_cpu(bb->sr_enter_plus_exit_time_us);
|
||||
dcn2_0_nv12_soc.urgent_latency_us =
|
||||
fixed16_to_double_to_cpu(bb->urgent_latency_us);
|
||||
dcn2_0_nv12_soc.urgent_latency_pixel_data_only_us =
|
||||
fixed16_to_double_to_cpu(bb->urgent_latency_pixel_data_only_us);
|
||||
dcn2_0_nv12_soc.urgent_latency_pixel_mixed_with_vm_data_us =
|
||||
fixed16_to_double_to_cpu(bb->urgent_latency_pixel_mixed_with_vm_data_us);
|
||||
dcn2_0_nv12_soc.urgent_latency_vm_data_only_us =
|
||||
fixed16_to_double_to_cpu(bb->urgent_latency_vm_data_only_us);
|
||||
dcn2_0_nv12_soc.urgent_out_of_order_return_per_channel_pixel_only_bytes =
|
||||
le32_to_cpu(bb->urgent_out_of_order_return_per_channel_pixel_only_bytes);
|
||||
dcn2_0_nv12_soc.urgent_out_of_order_return_per_channel_pixel_and_vm_bytes =
|
||||
le32_to_cpu(bb->urgent_out_of_order_return_per_channel_pixel_and_vm_bytes);
|
||||
dcn2_0_nv12_soc.urgent_out_of_order_return_per_channel_vm_only_bytes =
|
||||
le32_to_cpu(bb->urgent_out_of_order_return_per_channel_vm_only_bytes);
|
||||
dcn2_0_nv12_soc.pct_ideal_dram_sdp_bw_after_urgent_pixel_only =
|
||||
fixed16_to_double_to_cpu(bb->pct_ideal_dram_sdp_bw_after_urgent_pixel_only);
|
||||
dcn2_0_nv12_soc.pct_ideal_dram_sdp_bw_after_urgent_pixel_and_vm =
|
||||
fixed16_to_double_to_cpu(bb->pct_ideal_dram_sdp_bw_after_urgent_pixel_and_vm);
|
||||
dcn2_0_nv12_soc.pct_ideal_dram_sdp_bw_after_urgent_vm_only =
|
||||
fixed16_to_double_to_cpu(bb->pct_ideal_dram_sdp_bw_after_urgent_vm_only);
|
||||
dcn2_0_nv12_soc.max_avg_sdp_bw_use_normal_percent =
|
||||
fixed16_to_double_to_cpu(bb->max_avg_sdp_bw_use_normal_percent);
|
||||
dcn2_0_nv12_soc.max_avg_dram_bw_use_normal_percent =
|
||||
fixed16_to_double_to_cpu(bb->max_avg_dram_bw_use_normal_percent);
|
||||
dcn2_0_nv12_soc.writeback_latency_us =
|
||||
fixed16_to_double_to_cpu(bb->writeback_latency_us);
|
||||
dcn2_0_nv12_soc.ideal_dram_bw_after_urgent_percent =
|
||||
fixed16_to_double_to_cpu(bb->ideal_dram_bw_after_urgent_percent);
|
||||
dcn2_0_nv12_soc.max_request_size_bytes =
|
||||
le32_to_cpu(bb->max_request_size_bytes);
|
||||
dcn2_0_nv12_soc.dram_channel_width_bytes =
|
||||
le32_to_cpu(bb->dram_channel_width_bytes);
|
||||
dcn2_0_nv12_soc.fabric_datapath_to_dcn_data_return_bytes =
|
||||
le32_to_cpu(bb->fabric_datapath_to_dcn_data_return_bytes);
|
||||
dcn2_0_nv12_soc.dcn_downspread_percent =
|
||||
fixed16_to_double_to_cpu(bb->dcn_downspread_percent);
|
||||
dcn2_0_nv12_soc.downspread_percent =
|
||||
fixed16_to_double_to_cpu(bb->downspread_percent);
|
||||
dcn2_0_nv12_soc.dram_page_open_time_ns =
|
||||
fixed16_to_double_to_cpu(bb->dram_page_open_time_ns);
|
||||
dcn2_0_nv12_soc.dram_rw_turnaround_time_ns =
|
||||
fixed16_to_double_to_cpu(bb->dram_rw_turnaround_time_ns);
|
||||
dcn2_0_nv12_soc.dram_return_buffer_per_channel_bytes =
|
||||
le32_to_cpu(bb->dram_return_buffer_per_channel_bytes);
|
||||
dcn2_0_nv12_soc.round_trip_ping_latency_dcfclk_cycles =
|
||||
le32_to_cpu(bb->round_trip_ping_latency_dcfclk_cycles);
|
||||
dcn2_0_nv12_soc.urgent_out_of_order_return_per_channel_bytes =
|
||||
le32_to_cpu(bb->urgent_out_of_order_return_per_channel_bytes);
|
||||
dcn2_0_nv12_soc.channel_interleave_bytes =
|
||||
le32_to_cpu(bb->channel_interleave_bytes);
|
||||
dcn2_0_nv12_soc.num_banks =
|
||||
le32_to_cpu(bb->num_banks);
|
||||
dcn2_0_nv12_soc.num_chans =
|
||||
le32_to_cpu(bb->num_chans);
|
||||
dcn2_0_nv12_soc.vmm_page_size_bytes =
|
||||
le32_to_cpu(bb->vmm_page_size_bytes);
|
||||
dcn2_0_nv12_soc.dram_clock_change_latency_us =
|
||||
fixed16_to_double_to_cpu(bb->dram_clock_change_latency_us);
|
||||
// HACK!! Lower uclock latency switch time so we don't switch
|
||||
dcn2_0_nv12_soc.dram_clock_change_latency_us = 10;
|
||||
dcn2_0_nv12_soc.writeback_dram_clock_change_latency_us =
|
||||
fixed16_to_double_to_cpu(bb->writeback_dram_clock_change_latency_us);
|
||||
dcn2_0_nv12_soc.return_bus_width_bytes =
|
||||
le32_to_cpu(bb->return_bus_width_bytes);
|
||||
dcn2_0_nv12_soc.dispclk_dppclk_vco_speed_mhz =
|
||||
le32_to_cpu(bb->dispclk_dppclk_vco_speed_mhz);
|
||||
dcn2_0_nv12_soc.xfc_bus_transport_time_us =
|
||||
le32_to_cpu(bb->xfc_bus_transport_time_us);
|
||||
dcn2_0_nv12_soc.xfc_xbuf_latency_tolerance_us =
|
||||
le32_to_cpu(bb->xfc_xbuf_latency_tolerance_us);
|
||||
dcn2_0_nv12_soc.use_urgent_burst_bw =
|
||||
le32_to_cpu(bb->use_urgent_burst_bw);
|
||||
dcn2_0_nv12_soc.num_states =
|
||||
le32_to_cpu(bb->num_states);
|
||||
|
||||
for (i = 0; i < dcn2_0_nv12_soc.num_states; i++) {
|
||||
dcn2_0_nv12_soc.clock_limits[i].state =
|
||||
le32_to_cpu(bb->clock_limits[i].state);
|
||||
dcn2_0_nv12_soc.clock_limits[i].dcfclk_mhz =
|
||||
fixed16_to_double_to_cpu(bb->clock_limits[i].dcfclk_mhz);
|
||||
dcn2_0_nv12_soc.clock_limits[i].fabricclk_mhz =
|
||||
fixed16_to_double_to_cpu(bb->clock_limits[i].fabricclk_mhz);
|
||||
dcn2_0_nv12_soc.clock_limits[i].dispclk_mhz =
|
||||
fixed16_to_double_to_cpu(bb->clock_limits[i].dispclk_mhz);
|
||||
dcn2_0_nv12_soc.clock_limits[i].dppclk_mhz =
|
||||
fixed16_to_double_to_cpu(bb->clock_limits[i].dppclk_mhz);
|
||||
dcn2_0_nv12_soc.clock_limits[i].phyclk_mhz =
|
||||
fixed16_to_double_to_cpu(bb->clock_limits[i].phyclk_mhz);
|
||||
dcn2_0_nv12_soc.clock_limits[i].socclk_mhz =
|
||||
fixed16_to_double_to_cpu(bb->clock_limits[i].socclk_mhz);
|
||||
dcn2_0_nv12_soc.clock_limits[i].dscclk_mhz =
|
||||
fixed16_to_double_to_cpu(bb->clock_limits[i].dscclk_mhz);
|
||||
dcn2_0_nv12_soc.clock_limits[i].dram_speed_mts =
|
||||
fixed16_to_double_to_cpu(bb->clock_limits[i].dram_speed_mts);
|
||||
}
|
||||
}
|
||||
|
||||
if (pool->base.pp_smu) {
|
||||
struct pp_smu_nv_clock_table max_clocks = {0};
|
||||
unsigned int uclk_states[8] = {0};
|
||||
|
|
|
@ -906,6 +906,8 @@ enum dcn20_clk_src_array_id {
|
|||
DCN20_CLK_SRC_PLL0,
|
||||
DCN20_CLK_SRC_PLL1,
|
||||
DCN20_CLK_SRC_PLL2,
|
||||
DCN20_CLK_SRC_PLL3,
|
||||
DCN20_CLK_SRC_PLL4,
|
||||
DCN20_CLK_SRC_TOTAL_DCN21
|
||||
};
|
||||
|
||||
|
@ -2030,6 +2032,14 @@ static bool dcn21_resource_construct(
|
|||
dcn21_clock_source_create(ctx, ctx->dc_bios,
|
||||
CLOCK_SOURCE_COMBO_PHY_PLL2,
|
||||
&clk_src_regs[2], false);
|
||||
pool->base.clock_sources[DCN20_CLK_SRC_PLL3] =
|
||||
dcn21_clock_source_create(ctx, ctx->dc_bios,
|
||||
CLOCK_SOURCE_COMBO_PHY_PLL3,
|
||||
&clk_src_regs[3], false);
|
||||
pool->base.clock_sources[DCN20_CLK_SRC_PLL4] =
|
||||
dcn21_clock_source_create(ctx, ctx->dc_bios,
|
||||
CLOCK_SOURCE_COMBO_PHY_PLL4,
|
||||
&clk_src_regs[4], false);
|
||||
|
||||
pool->base.clk_src_count = DCN20_CLK_SRC_TOTAL_DCN21;
|
||||
|
||||
|
|
|
@ -32,8 +32,8 @@ DCN30 = dcn30_init.o dcn30_hubbub.o dcn30_hubp.o dcn30_dpp.o dcn30_optc.o \
|
|||
|
||||
|
||||
ifdef CONFIG_X86
|
||||
CFLAGS_$(AMDDALPATH)/dc/dcn30/dcn30_resource.o := -mhard-float -msse
|
||||
CFLAGS_$(AMDDALPATH)/dc/dcn30/dcn30_optc.o := -mhard-float -msse
|
||||
CFLAGS_$(AMDDALPATH)/dc/dcn30/dcn30_resource.o := -msse
|
||||
CFLAGS_$(AMDDALPATH)/dc/dcn30/dcn30_optc.o := -msse
|
||||
endif
|
||||
|
||||
ifdef CONFIG_PPC64
|
||||
|
@ -45,6 +45,8 @@ ifdef CONFIG_CC_IS_GCC
|
|||
ifeq ($(call cc-ifversion, -lt, 0701, y), y)
|
||||
IS_OLD_GCC = 1
|
||||
endif
|
||||
CFLAGS_$(AMDDALPATH)/dc/dcn30/dcn30_resource.o += -mhard-float
|
||||
CFLAGS_$(AMDDALPATH)/dc/dcn30/dcn30_optc.o += -mhard-float
|
||||
endif
|
||||
|
||||
ifdef CONFIG_X86
|
||||
|
|
|
@ -710,8 +710,11 @@ void dcn30_program_dmdata_engine(struct pipe_ctx *pipe_ctx)
|
|||
bool dcn30_apply_idle_power_optimizations(struct dc *dc, bool enable)
|
||||
{
|
||||
union dmub_rb_cmd cmd;
|
||||
unsigned int surface_size, refresh_hz, denom;
|
||||
uint32_t tmr_delay = 0, tmr_scale = 0;
|
||||
struct dc_cursor_attributes cursor_attr;
|
||||
bool cursor_cache_enable = false;
|
||||
struct dc_stream_state *stream = NULL;
|
||||
struct dc_plane_state *plane = NULL;
|
||||
|
||||
if (!dc->ctx->dmub_srv)
|
||||
return false;
|
||||
|
@ -722,72 +725,150 @@ bool dcn30_apply_idle_power_optimizations(struct dc *dc, bool enable)
|
|||
|
||||
/* First, check no-memory-requests case */
|
||||
for (i = 0; i < dc->current_state->stream_count; i++) {
|
||||
if (dc->current_state->stream_status[i]
|
||||
.plane_count)
|
||||
if (dc->current_state->stream_status[i].plane_count)
|
||||
/* Fail eligibility on a visible stream */
|
||||
break;
|
||||
}
|
||||
|
||||
if (dc->current_state->stream_count == 1 // single display only
|
||||
&& dc->current_state->stream_status[0].plane_count == 1 // single surface only
|
||||
&& dc->current_state->stream_status[0].plane_states[0]->address.page_table_base.quad_part == 0 // no VM
|
||||
// Only 8 and 16 bit formats
|
||||
&& dc->current_state->stream_status[0].plane_states[0]->format <= SURFACE_PIXEL_FORMAT_GRPH_ABGR16161616F
|
||||
&& dc->current_state->stream_status[0].plane_states[0]->format >= SURFACE_PIXEL_FORMAT_GRPH_ARGB8888) {
|
||||
surface_size = dc->current_state->stream_status[0].plane_states[0]->plane_size.surface_pitch *
|
||||
dc->current_state->stream_status[0].plane_states[0]->plane_size.surface_size.height *
|
||||
(dc->current_state->stream_status[0].plane_states[0]->format >= SURFACE_PIXEL_FORMAT_GRPH_ARGB16161616 ?
|
||||
8 : 4);
|
||||
} else {
|
||||
// TODO: remove hard code size
|
||||
surface_size = 128 * 1024 * 1024;
|
||||
if (i == dc->current_state->stream_count) {
|
||||
/* Enable no-memory-requests case */
|
||||
memset(&cmd, 0, sizeof(cmd));
|
||||
cmd.mall.header.type = DMUB_CMD__MALL;
|
||||
cmd.mall.header.sub_type = DMUB_CMD__MALL_ACTION_NO_DF_REQ;
|
||||
cmd.mall.header.payload_bytes = sizeof(cmd.mall) - sizeof(cmd.mall.header);
|
||||
|
||||
dc_dmub_srv_cmd_queue(dc->ctx->dmub_srv, &cmd);
|
||||
dc_dmub_srv_cmd_execute(dc->ctx->dmub_srv);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// TODO: remove hard code size
|
||||
if (surface_size < 128 * 1024 * 1024) {
|
||||
refresh_hz = div_u64((unsigned long long) dc->current_state->streams[0]->timing.pix_clk_100hz *
|
||||
100LL,
|
||||
(dc->current_state->streams[0]->timing.v_total *
|
||||
dc->current_state->streams[0]->timing.h_total));
|
||||
stream = dc->current_state->streams[0];
|
||||
plane = (stream ? dc->current_state->stream_status[0].plane_states[0] : NULL);
|
||||
|
||||
if (stream && plane) {
|
||||
cursor_cache_enable = stream->cursor_position.enable &&
|
||||
plane->address.grph.cursor_cache_addr.quad_part;
|
||||
cursor_attr = stream->cursor_attributes;
|
||||
}
|
||||
|
||||
/*
|
||||
* Second, check MALL eligibility
|
||||
*
|
||||
* single display only, single surface only, 8 and 16 bit formats only, no VM,
|
||||
* do not use MALL for displays that support PSR as they use D0i3.2 in DMCUB FW
|
||||
*
|
||||
* TODO: When we implement multi-display, PSR displays will be allowed if there is
|
||||
* a non-PSR display present, since in that case we can't do D0i3.2
|
||||
*/
|
||||
if (dc->current_state->stream_count == 1 &&
|
||||
stream->link->psr_settings.psr_version == DC_PSR_VERSION_UNSUPPORTED &&
|
||||
dc->current_state->stream_status[0].plane_count == 1 &&
|
||||
plane->format <= SURFACE_PIXEL_FORMAT_GRPH_ABGR16161616F &&
|
||||
plane->format >= SURFACE_PIXEL_FORMAT_GRPH_ARGB8888 &&
|
||||
plane->address.page_table_base.quad_part == 0 &&
|
||||
dc->hwss.does_plane_fit_in_mall &&
|
||||
dc->hwss.does_plane_fit_in_mall(dc, plane,
|
||||
cursor_cache_enable ? &cursor_attr : NULL)) {
|
||||
unsigned int v_total = stream->adjust.v_total_max ?
|
||||
stream->adjust.v_total_max : stream->timing.v_total;
|
||||
unsigned int refresh_hz = div_u64((unsigned long long) stream->timing.pix_clk_100hz *
|
||||
100LL, (v_total * stream->timing.h_total));
|
||||
|
||||
/*
|
||||
* Delay_Us = 65.28 * (64 + MallFrameCacheTmrDly) * 2^MallFrameCacheTmrScale
|
||||
* Delay_Us / 65.28 = (64 + MallFrameCacheTmrDly) * 2^MallFrameCacheTmrScale
|
||||
* (Delay_Us / 65.28) / 2^MallFrameCacheTmrScale = 64 + MallFrameCacheTmrDly
|
||||
* MallFrameCacheTmrDly = ((Delay_Us / 65.28) / 2^MallFrameCacheTmrScale) - 64
|
||||
* = (1000000 / refresh) / 65.28 / 2^MallFrameCacheTmrScale - 64
|
||||
* = 1000000 / (refresh * 65.28 * 2^MallFrameCacheTmrScale) - 64
|
||||
* = (1000000 * 100) / (refresh * 6528 * 2^MallFrameCacheTmrScale) - 64
|
||||
* one frame time in microsec:
|
||||
* Delay_Us = 1000000 / refresh
|
||||
* dynamic_delay_us = 1000000 / refresh + 2 * stutter_period
|
||||
*
|
||||
* one frame time modified by 'additional timer percent' (p):
|
||||
* Delay_Us_modified = dynamic_delay_us + dynamic_delay_us * p / 100
|
||||
* = dynamic_delay_us * (1 + p / 100)
|
||||
* = (1000000 / refresh + 2 * stutter_period) * (100 + p) / 100
|
||||
* = (1000000 + 2 * stutter_period * refresh) * (100 + p) / (100 * refresh)
|
||||
*
|
||||
* formula for timer duration based on parameters, from regspec:
|
||||
* dynamic_delay_us = 65.28 * (64 + MallFrameCacheTmrDly) * 2^MallFrameCacheTmrScale
|
||||
*
|
||||
* dynamic_delay_us / 65.28 = (64 + MallFrameCacheTmrDly) * 2^MallFrameCacheTmrScale
|
||||
* (dynamic_delay_us / 65.28) / 2^MallFrameCacheTmrScale = 64 + MallFrameCacheTmrDly
|
||||
* MallFrameCacheTmrDly = ((dynamic_delay_us / 65.28) / 2^MallFrameCacheTmrScale) - 64
|
||||
* = (1000000 + 2 * stutter_period * refresh) * (100 + p) / (100 * refresh) / 65.28 / 2^MallFrameCacheTmrScale - 64
|
||||
* = (1000000 + 2 * stutter_period * refresh) * (100 + p) / (refresh * 6528 * 2^MallFrameCacheTmrScale) - 64
|
||||
*
|
||||
* need to round up the result of the division before the subtraction
|
||||
*/
|
||||
denom = refresh_hz * 6528;
|
||||
tmr_delay = div_u64((100000000LL + denom - 1), denom) - 64LL;
|
||||
unsigned int denom = refresh_hz * 6528;
|
||||
unsigned int stutter_period = dc->current_state->perf_params.stutter_period_us;
|
||||
|
||||
tmr_delay = div_u64(((1000000LL + 2 * stutter_period * refresh_hz) *
|
||||
(100LL + dc->debug.mall_additional_timer_percent) + denom - 1),
|
||||
denom) - 64LL;
|
||||
|
||||
/* scale should be increased until it fits into 6 bits */
|
||||
while (tmr_delay & ~0x3F) {
|
||||
tmr_scale++;
|
||||
|
||||
if (tmr_scale > 3) {
|
||||
/* The delay exceeds the range of the hystersis timer */
|
||||
/* Delay exceeds range of hysteresis timer */
|
||||
ASSERT(false);
|
||||
return false;
|
||||
}
|
||||
|
||||
denom *= 2;
|
||||
tmr_delay = div_u64((100000000LL + denom - 1), denom) - 64LL;
|
||||
tmr_delay = div_u64(((1000000LL + 2 * stutter_period * refresh_hz) *
|
||||
(100LL + dc->debug.mall_additional_timer_percent) + denom - 1),
|
||||
denom) - 64LL;
|
||||
}
|
||||
|
||||
/* Copy HW cursor */
|
||||
if (cursor_cache_enable) {
|
||||
memset(&cmd, 0, sizeof(cmd));
|
||||
cmd.mall.header.type = DMUB_CMD__MALL;
|
||||
cmd.mall.header.sub_type = DMUB_CMD__MALL_ACTION_COPY_CURSOR;
|
||||
cmd.mall.header.payload_bytes =
|
||||
sizeof(cmd.mall) - sizeof(cmd.mall.header);
|
||||
|
||||
switch (cursor_attr.color_format) {
|
||||
case CURSOR_MODE_MONO:
|
||||
cmd.mall.cursor_bpp = 2;
|
||||
break;
|
||||
case CURSOR_MODE_COLOR_1BIT_AND:
|
||||
case CURSOR_MODE_COLOR_PRE_MULTIPLIED_ALPHA:
|
||||
case CURSOR_MODE_COLOR_UN_PRE_MULTIPLIED_ALPHA:
|
||||
cmd.mall.cursor_bpp = 32;
|
||||
break;
|
||||
|
||||
case CURSOR_MODE_COLOR_64BIT_FP_PRE_MULTIPLIED:
|
||||
case CURSOR_MODE_COLOR_64BIT_FP_UN_PRE_MULTIPLIED:
|
||||
cmd.mall.cursor_bpp = 64;
|
||||
break;
|
||||
}
|
||||
|
||||
cmd.mall.cursor_copy_src.quad_part = cursor_attr.address.quad_part;
|
||||
cmd.mall.cursor_copy_dst.quad_part =
|
||||
plane->address.grph.cursor_cache_addr.quad_part;
|
||||
cmd.mall.cursor_width = cursor_attr.width;
|
||||
cmd.mall.cursor_height = cursor_attr.height;
|
||||
cmd.mall.cursor_pitch = cursor_attr.pitch;
|
||||
|
||||
dc_dmub_srv_cmd_queue(dc->ctx->dmub_srv, &cmd);
|
||||
dc_dmub_srv_cmd_execute(dc->ctx->dmub_srv);
|
||||
dc_dmub_srv_wait_idle(dc->ctx->dmub_srv);
|
||||
|
||||
/* Use copied cursor, and it's okay to not switch back */
|
||||
cursor_attr.address.quad_part =
|
||||
plane->address.grph.cursor_cache_addr.quad_part;
|
||||
dc_stream_set_cursor_attributes(stream, &cursor_attr);
|
||||
}
|
||||
|
||||
/* Enable MALL */
|
||||
memset(&cmd, 0, sizeof(cmd));
|
||||
cmd.mall.header.type = DMUB_CMD__MALL;
|
||||
cmd.mall.header.sub_type =
|
||||
DMUB_CMD__MALL_ACTION_ALLOW;
|
||||
cmd.mall.header.payload_bytes =
|
||||
sizeof(cmd.mall) -
|
||||
sizeof(cmd.mall.header);
|
||||
cmd.mall.header.sub_type = DMUB_CMD__MALL_ACTION_ALLOW;
|
||||
cmd.mall.header.payload_bytes = sizeof(cmd.mall) - sizeof(cmd.mall.header);
|
||||
cmd.mall.tmr_delay = tmr_delay;
|
||||
cmd.mall.tmr_scale = tmr_scale;
|
||||
cmd.mall.debug_bits = dc->debug.mall_error_as_fatal;
|
||||
|
||||
dc_dmub_srv_cmd_queue(dc->ctx->dmub_srv, &cmd);
|
||||
dc_dmub_srv_cmd_execute(dc->ctx->dmub_srv);
|
||||
|
@ -814,17 +895,38 @@ bool dcn30_apply_idle_power_optimizations(struct dc *dc, bool enable)
|
|||
return true;
|
||||
}
|
||||
|
||||
bool dcn30_does_plane_fit_in_mall(struct dc *dc, struct dc_plane_state *plane)
|
||||
bool dcn30_does_plane_fit_in_mall(struct dc *dc, struct dc_plane_state *plane, struct dc_cursor_attributes *cursor_attr)
|
||||
{
|
||||
// add meta size?
|
||||
unsigned int surface_size = plane->plane_size.surface_pitch * plane->plane_size.surface_size.height *
|
||||
(plane->format >= SURFACE_PIXEL_FORMAT_GRPH_ARGB16161616 ? 8 : 4);
|
||||
unsigned int mall_size = dc->caps.mall_size_total;
|
||||
unsigned int cursor_size = 0;
|
||||
|
||||
if (dc->debug.mall_size_override)
|
||||
mall_size = 1024 * 1024 * dc->debug.mall_size_override;
|
||||
|
||||
return (surface_size + dc->caps.cursor_cache_size) < mall_size;
|
||||
if (cursor_attr) {
|
||||
cursor_size = dc->caps.max_cursor_size * dc->caps.max_cursor_size;
|
||||
|
||||
switch (cursor_attr->color_format) {
|
||||
case CURSOR_MODE_MONO:
|
||||
cursor_size /= 2;
|
||||
break;
|
||||
case CURSOR_MODE_COLOR_1BIT_AND:
|
||||
case CURSOR_MODE_COLOR_PRE_MULTIPLIED_ALPHA:
|
||||
case CURSOR_MODE_COLOR_UN_PRE_MULTIPLIED_ALPHA:
|
||||
cursor_size *= 4;
|
||||
break;
|
||||
|
||||
case CURSOR_MODE_COLOR_64BIT_FP_PRE_MULTIPLIED:
|
||||
case CURSOR_MODE_COLOR_64BIT_FP_UN_PRE_MULTIPLIED:
|
||||
cursor_size *= 8;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return (surface_size + cursor_size) < mall_size;
|
||||
}
|
||||
|
||||
void dcn30_hardware_release(struct dc *dc)
|
||||
|
|
|
@ -65,7 +65,8 @@ void dcn30_set_avmute(struct pipe_ctx *pipe_ctx, bool enable);
|
|||
void dcn30_update_info_frame(struct pipe_ctx *pipe_ctx);
|
||||
void dcn30_program_dmdata_engine(struct pipe_ctx *pipe_ctx);
|
||||
|
||||
bool dcn30_does_plane_fit_in_mall(struct dc *dc, struct dc_plane_state *plane);
|
||||
bool dcn30_does_plane_fit_in_mall(struct dc *dc, struct dc_plane_state *plane,
|
||||
struct dc_cursor_attributes *cursor_attr);
|
||||
|
||||
bool dcn30_apply_idle_power_optimizations(struct dc *dc, bool enable);
|
||||
|
||||
|
|
|
@ -1716,125 +1716,22 @@ static bool is_soc_bounding_box_valid(struct dc *dc)
|
|||
static bool init_soc_bounding_box(struct dc *dc,
|
||||
struct dcn30_resource_pool *pool)
|
||||
{
|
||||
const struct gpu_info_soc_bounding_box_v1_0 *bb = dc->soc_bounding_box;
|
||||
struct _vcs_dpi_soc_bounding_box_st *loaded_bb = &dcn3_0_soc;
|
||||
struct _vcs_dpi_ip_params_st *loaded_ip = &dcn3_0_ip;
|
||||
|
||||
DC_LOGGER_INIT(dc->ctx->logger);
|
||||
|
||||
if (!bb && !is_soc_bounding_box_valid(dc)) {
|
||||
if (!is_soc_bounding_box_valid(dc)) {
|
||||
DC_LOG_ERROR("%s: not valid soc bounding box/n", __func__);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (bb && !is_soc_bounding_box_valid(dc)) {
|
||||
int i;
|
||||
|
||||
dcn3_0_soc.sr_exit_time_us =
|
||||
fixed16_to_double_to_cpu(bb->sr_exit_time_us);
|
||||
dcn3_0_soc.sr_enter_plus_exit_time_us =
|
||||
fixed16_to_double_to_cpu(bb->sr_enter_plus_exit_time_us);
|
||||
dcn3_0_soc.urgent_latency_us =
|
||||
fixed16_to_double_to_cpu(bb->urgent_latency_us);
|
||||
dcn3_0_soc.urgent_latency_pixel_data_only_us =
|
||||
fixed16_to_double_to_cpu(bb->urgent_latency_pixel_data_only_us);
|
||||
dcn3_0_soc.urgent_latency_pixel_mixed_with_vm_data_us =
|
||||
fixed16_to_double_to_cpu(bb->urgent_latency_pixel_mixed_with_vm_data_us);
|
||||
dcn3_0_soc.urgent_latency_vm_data_only_us =
|
||||
fixed16_to_double_to_cpu(bb->urgent_latency_vm_data_only_us);
|
||||
dcn3_0_soc.urgent_out_of_order_return_per_channel_pixel_only_bytes =
|
||||
le32_to_cpu(bb->urgent_out_of_order_return_per_channel_pixel_only_bytes);
|
||||
dcn3_0_soc.urgent_out_of_order_return_per_channel_pixel_and_vm_bytes =
|
||||
le32_to_cpu(bb->urgent_out_of_order_return_per_channel_pixel_and_vm_bytes);
|
||||
dcn3_0_soc.urgent_out_of_order_return_per_channel_vm_only_bytes =
|
||||
le32_to_cpu(bb->urgent_out_of_order_return_per_channel_vm_only_bytes);
|
||||
dcn3_0_soc.pct_ideal_dram_sdp_bw_after_urgent_pixel_only =
|
||||
fixed16_to_double_to_cpu(bb->pct_ideal_dram_sdp_bw_after_urgent_pixel_only);
|
||||
dcn3_0_soc.pct_ideal_dram_sdp_bw_after_urgent_pixel_and_vm =
|
||||
fixed16_to_double_to_cpu(bb->pct_ideal_dram_sdp_bw_after_urgent_pixel_and_vm);
|
||||
dcn3_0_soc.pct_ideal_dram_sdp_bw_after_urgent_vm_only =
|
||||
fixed16_to_double_to_cpu(bb->pct_ideal_dram_sdp_bw_after_urgent_vm_only);
|
||||
dcn3_0_soc.max_avg_sdp_bw_use_normal_percent =
|
||||
fixed16_to_double_to_cpu(bb->max_avg_sdp_bw_use_normal_percent);
|
||||
dcn3_0_soc.max_avg_dram_bw_use_normal_percent =
|
||||
fixed16_to_double_to_cpu(bb->max_avg_dram_bw_use_normal_percent);
|
||||
dcn3_0_soc.writeback_latency_us =
|
||||
fixed16_to_double_to_cpu(bb->writeback_latency_us);
|
||||
dcn3_0_soc.ideal_dram_bw_after_urgent_percent =
|
||||
fixed16_to_double_to_cpu(bb->ideal_dram_bw_after_urgent_percent);
|
||||
dcn3_0_soc.max_request_size_bytes =
|
||||
le32_to_cpu(bb->max_request_size_bytes);
|
||||
dcn3_0_soc.dram_channel_width_bytes =
|
||||
le32_to_cpu(bb->dram_channel_width_bytes);
|
||||
dcn3_0_soc.fabric_datapath_to_dcn_data_return_bytes =
|
||||
le32_to_cpu(bb->fabric_datapath_to_dcn_data_return_bytes);
|
||||
dcn3_0_soc.dcn_downspread_percent =
|
||||
fixed16_to_double_to_cpu(bb->dcn_downspread_percent);
|
||||
dcn3_0_soc.downspread_percent =
|
||||
fixed16_to_double_to_cpu(bb->downspread_percent);
|
||||
dcn3_0_soc.dram_page_open_time_ns =
|
||||
fixed16_to_double_to_cpu(bb->dram_page_open_time_ns);
|
||||
dcn3_0_soc.dram_rw_turnaround_time_ns =
|
||||
fixed16_to_double_to_cpu(bb->dram_rw_turnaround_time_ns);
|
||||
dcn3_0_soc.dram_return_buffer_per_channel_bytes =
|
||||
le32_to_cpu(bb->dram_return_buffer_per_channel_bytes);
|
||||
dcn3_0_soc.round_trip_ping_latency_dcfclk_cycles =
|
||||
le32_to_cpu(bb->round_trip_ping_latency_dcfclk_cycles);
|
||||
dcn3_0_soc.urgent_out_of_order_return_per_channel_bytes =
|
||||
le32_to_cpu(bb->urgent_out_of_order_return_per_channel_bytes);
|
||||
dcn3_0_soc.channel_interleave_bytes =
|
||||
le32_to_cpu(bb->channel_interleave_bytes);
|
||||
dcn3_0_soc.num_banks =
|
||||
le32_to_cpu(bb->num_banks);
|
||||
dcn3_0_soc.num_chans =
|
||||
le32_to_cpu(bb->num_chans);
|
||||
dcn3_0_soc.gpuvm_min_page_size_bytes =
|
||||
le32_to_cpu(bb->vmm_page_size_bytes);
|
||||
dcn3_0_soc.dram_clock_change_latency_us =
|
||||
fixed16_to_double_to_cpu(bb->dram_clock_change_latency_us);
|
||||
dcn3_0_soc.writeback_dram_clock_change_latency_us =
|
||||
fixed16_to_double_to_cpu(bb->writeback_dram_clock_change_latency_us);
|
||||
dcn3_0_soc.return_bus_width_bytes =
|
||||
le32_to_cpu(bb->return_bus_width_bytes);
|
||||
dcn3_0_soc.dispclk_dppclk_vco_speed_mhz =
|
||||
le32_to_cpu(bb->dispclk_dppclk_vco_speed_mhz);
|
||||
dcn3_0_soc.xfc_bus_transport_time_us =
|
||||
le32_to_cpu(bb->xfc_bus_transport_time_us);
|
||||
dcn3_0_soc.xfc_xbuf_latency_tolerance_us =
|
||||
le32_to_cpu(bb->xfc_xbuf_latency_tolerance_us);
|
||||
dcn3_0_soc.use_urgent_burst_bw =
|
||||
le32_to_cpu(bb->use_urgent_burst_bw);
|
||||
dcn3_0_soc.num_states =
|
||||
le32_to_cpu(bb->num_states);
|
||||
|
||||
for (i = 0; i < dcn3_0_soc.num_states; i++) {
|
||||
dcn3_0_soc.clock_limits[i].state =
|
||||
le32_to_cpu(bb->clock_limits[i].state);
|
||||
dcn3_0_soc.clock_limits[i].dcfclk_mhz =
|
||||
fixed16_to_double_to_cpu(bb->clock_limits[i].dcfclk_mhz);
|
||||
dcn3_0_soc.clock_limits[i].fabricclk_mhz =
|
||||
fixed16_to_double_to_cpu(bb->clock_limits[i].fabricclk_mhz);
|
||||
dcn3_0_soc.clock_limits[i].dispclk_mhz =
|
||||
fixed16_to_double_to_cpu(bb->clock_limits[i].dispclk_mhz);
|
||||
dcn3_0_soc.clock_limits[i].dppclk_mhz =
|
||||
fixed16_to_double_to_cpu(bb->clock_limits[i].dppclk_mhz);
|
||||
dcn3_0_soc.clock_limits[i].phyclk_mhz =
|
||||
fixed16_to_double_to_cpu(bb->clock_limits[i].phyclk_mhz);
|
||||
dcn3_0_soc.clock_limits[i].socclk_mhz =
|
||||
fixed16_to_double_to_cpu(bb->clock_limits[i].socclk_mhz);
|
||||
dcn3_0_soc.clock_limits[i].dscclk_mhz =
|
||||
fixed16_to_double_to_cpu(bb->clock_limits[i].dscclk_mhz);
|
||||
dcn3_0_soc.clock_limits[i].dram_speed_mts =
|
||||
fixed16_to_double_to_cpu(bb->clock_limits[i].dram_speed_mts);
|
||||
}
|
||||
}
|
||||
|
||||
loaded_ip->max_num_otg = pool->base.res_cap->num_timing_generator;
|
||||
loaded_ip->max_num_dpp = pool->base.pipe_count;
|
||||
loaded_ip->clamp_min_dcfclk = dc->config.clamp_min_dcfclk;
|
||||
dcn20_patch_bounding_box(dc, loaded_bb);
|
||||
|
||||
if (!bb && dc->ctx->dc_bios->funcs->get_soc_bb_info) {
|
||||
if (dc->ctx->dc_bios->funcs->get_soc_bb_info) {
|
||||
struct bp_soc_bb_info bb_info = {0};
|
||||
|
||||
if (dc->ctx->dc_bios->funcs->get_soc_bb_info(dc->ctx->dc_bios, &bb_info) == BP_RESULT_OK) {
|
||||
|
@ -2292,17 +2189,15 @@ static noinline void dcn30_calculate_wm_and_dlg_fp(
|
|||
unsigned int min_dram_speed_mts = context->bw_ctx.dml.vba.DRAMSpeed;
|
||||
unsigned int min_dram_speed_mts_margin = 160;
|
||||
|
||||
context->bw_ctx.dml.soc.dram_clock_change_latency_us = dc->clk_mgr->bw_params->dummy_pstate_table[0].dummy_pstate_latency_us;
|
||||
|
||||
if (context->bw_ctx.dml.vba.DRAMClockChangeSupport[vlevel][context->bw_ctx.dml.vba.maxMpcComb] == dm_dram_clock_change_unsupported)
|
||||
min_dram_speed_mts = dc->clk_mgr->bw_params->clk_table.entries[dc->clk_mgr->bw_params->clk_table.num_entries - 1].memclk_mhz * 16;
|
||||
|
||||
for (i = 3; i > 0; i--) {
|
||||
if ((min_dram_speed_mts + min_dram_speed_mts_margin > dc->clk_mgr->bw_params->dummy_pstate_table[i].dram_speed_mts) &&
|
||||
(min_dram_speed_mts - min_dram_speed_mts_margin < dc->clk_mgr->bw_params->dummy_pstate_table[i].dram_speed_mts))
|
||||
context->bw_ctx.dml.soc.dram_clock_change_latency_us = dc->clk_mgr->bw_params->dummy_pstate_table[i].dummy_pstate_latency_us;
|
||||
}
|
||||
/* find largest table entry that is lower than dram speed, but lower than DPM0 still uses DPM0 */
|
||||
for (i = 3; i > 0; i--)
|
||||
if (min_dram_speed_mts + min_dram_speed_mts_margin > dc->clk_mgr->bw_params->dummy_pstate_table[i].dram_speed_mts)
|
||||
break;
|
||||
|
||||
context->bw_ctx.dml.soc.dram_clock_change_latency_us = dc->clk_mgr->bw_params->dummy_pstate_table[i].dummy_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;
|
||||
}
|
||||
|
@ -2437,16 +2332,28 @@ bool dcn30_validate_bandwidth(struct dc *dc,
|
|||
return out;
|
||||
}
|
||||
|
||||
static noinline void get_optimal_dcfclk_fclk_for_uclk(unsigned int uclk_mts,
|
||||
unsigned int *optimal_dcfclk,
|
||||
unsigned int *optimal_fclk)
|
||||
/*
|
||||
* This must be noinline to ensure anything that deals with FP registers
|
||||
* is contained within this call; previously our compiling with hard-float
|
||||
* would result in fp instructions being emitted outside of the boundaries
|
||||
* of the DC_FP_START/END macros, which makes sense as the compiler has no
|
||||
* idea about what is wrapped and what is not
|
||||
*
|
||||
* This is largely just a workaround to avoid breakage introduced with 5.6,
|
||||
* ideally all fp-using code should be moved into its own file, only that
|
||||
* should be compiled with hard-float, and all code exported from there
|
||||
* should be strictly wrapped with DC_FP_START/END
|
||||
*/
|
||||
static noinline void dcn30_get_optimal_dcfclk_fclk_for_uclk(unsigned int uclk_mts,
|
||||
unsigned int *optimal_dcfclk,
|
||||
unsigned int *optimal_fclk)
|
||||
{
|
||||
double bw_from_dram, bw_from_dram1, bw_from_dram2;
|
||||
|
||||
bw_from_dram1 = uclk_mts * dcn3_0_soc.num_chans *
|
||||
dcn3_0_soc.dram_channel_width_bytes * (dcn3_0_soc.max_avg_dram_bw_use_normal_percent / 100);
|
||||
dcn3_0_soc.dram_channel_width_bytes * (dcn3_0_soc.max_avg_dram_bw_use_normal_percent / 100);
|
||||
bw_from_dram2 = uclk_mts * dcn3_0_soc.num_chans *
|
||||
dcn3_0_soc.dram_channel_width_bytes * (dcn3_0_soc.max_avg_sdp_bw_use_normal_percent / 100);
|
||||
dcn3_0_soc.dram_channel_width_bytes * (dcn3_0_soc.max_avg_sdp_bw_use_normal_percent / 100);
|
||||
|
||||
bw_from_dram = (bw_from_dram1 < bw_from_dram2) ? bw_from_dram1 : bw_from_dram2;
|
||||
|
||||
|
@ -2505,7 +2412,7 @@ void dcn30_update_bw_bounding_box(struct dc *dc, struct clk_bw_params *bw_params
|
|||
// Calculate optimal dcfclk for each uclk
|
||||
for (i = 0; i < num_uclk_states; i++) {
|
||||
DC_FP_START();
|
||||
get_optimal_dcfclk_fclk_for_uclk(bw_params->clk_table.entries[i].memclk_mhz * 16,
|
||||
dcn30_get_optimal_dcfclk_fclk_for_uclk(bw_params->clk_table.entries[i].memclk_mhz * 16,
|
||||
&optimal_dcfclk_for_uclk[i], NULL);
|
||||
DC_FP_END();
|
||||
if (optimal_dcfclk_for_uclk[i] < bw_params->clk_table.entries[0].dcfclk_mhz) {
|
||||
|
|
|
@ -14,7 +14,7 @@ DCN301 = dcn301_init.o dcn301_resource.o dcn301_dccg.o \
|
|||
dcn301_dio_link_encoder.o dcn301_hwseq.o dcn301_panel_cntl.o dcn301_hubbub.o
|
||||
|
||||
ifdef CONFIG_X86
|
||||
CFLAGS_$(AMDDALPATH)/dc/dcn301/dcn301_resource.o := -mhard-float -msse
|
||||
CFLAGS_$(AMDDALPATH)/dc/dcn301/dcn301_resource.o := -msse
|
||||
endif
|
||||
|
||||
ifdef CONFIG_PPC64
|
||||
|
@ -25,6 +25,7 @@ ifdef CONFIG_CC_IS_GCC
|
|||
ifeq ($(call cc-ifversion, -lt, 0701, y), y)
|
||||
IS_OLD_GCC = 1
|
||||
endif
|
||||
CFLAGS_$(AMDDALPATH)/dc/dcn301/dcn301_resource.o += -mhard-float
|
||||
endif
|
||||
|
||||
ifdef CONFIG_X86
|
||||
|
|
|
@ -1489,124 +1489,21 @@ static bool is_soc_bounding_box_valid(struct dc *dc)
|
|||
static bool init_soc_bounding_box(struct dc *dc,
|
||||
struct dcn301_resource_pool *pool)
|
||||
{
|
||||
const struct gpu_info_soc_bounding_box_v1_0 *bb = dc->soc_bounding_box;
|
||||
struct _vcs_dpi_soc_bounding_box_st *loaded_bb = &dcn3_01_soc;
|
||||
struct _vcs_dpi_ip_params_st *loaded_ip = &dcn3_01_ip;
|
||||
|
||||
DC_LOGGER_INIT(dc->ctx->logger);
|
||||
|
||||
if (!bb && !is_soc_bounding_box_valid(dc)) {
|
||||
if (!is_soc_bounding_box_valid(dc)) {
|
||||
DC_LOG_ERROR("%s: not valid soc bounding box/n", __func__);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (bb && !is_soc_bounding_box_valid(dc)) {
|
||||
int i;
|
||||
|
||||
dcn3_01_soc.sr_exit_time_us =
|
||||
fixed16_to_double_to_cpu(bb->sr_exit_time_us);
|
||||
dcn3_01_soc.sr_enter_plus_exit_time_us =
|
||||
fixed16_to_double_to_cpu(bb->sr_enter_plus_exit_time_us);
|
||||
dcn3_01_soc.urgent_latency_us =
|
||||
fixed16_to_double_to_cpu(bb->urgent_latency_us);
|
||||
dcn3_01_soc.urgent_latency_pixel_data_only_us =
|
||||
fixed16_to_double_to_cpu(bb->urgent_latency_pixel_data_only_us);
|
||||
dcn3_01_soc.urgent_latency_pixel_mixed_with_vm_data_us =
|
||||
fixed16_to_double_to_cpu(bb->urgent_latency_pixel_mixed_with_vm_data_us);
|
||||
dcn3_01_soc.urgent_latency_vm_data_only_us =
|
||||
fixed16_to_double_to_cpu(bb->urgent_latency_vm_data_only_us);
|
||||
dcn3_01_soc.urgent_out_of_order_return_per_channel_pixel_only_bytes =
|
||||
le32_to_cpu(bb->urgent_out_of_order_return_per_channel_pixel_only_bytes);
|
||||
dcn3_01_soc.urgent_out_of_order_return_per_channel_pixel_and_vm_bytes =
|
||||
le32_to_cpu(bb->urgent_out_of_order_return_per_channel_pixel_and_vm_bytes);
|
||||
dcn3_01_soc.urgent_out_of_order_return_per_channel_vm_only_bytes =
|
||||
le32_to_cpu(bb->urgent_out_of_order_return_per_channel_vm_only_bytes);
|
||||
dcn3_01_soc.pct_ideal_dram_sdp_bw_after_urgent_pixel_only =
|
||||
fixed16_to_double_to_cpu(bb->pct_ideal_dram_sdp_bw_after_urgent_pixel_only);
|
||||
dcn3_01_soc.pct_ideal_dram_sdp_bw_after_urgent_pixel_and_vm =
|
||||
fixed16_to_double_to_cpu(bb->pct_ideal_dram_sdp_bw_after_urgent_pixel_and_vm);
|
||||
dcn3_01_soc.pct_ideal_dram_sdp_bw_after_urgent_vm_only =
|
||||
fixed16_to_double_to_cpu(bb->pct_ideal_dram_sdp_bw_after_urgent_vm_only);
|
||||
dcn3_01_soc.max_avg_sdp_bw_use_normal_percent =
|
||||
fixed16_to_double_to_cpu(bb->max_avg_sdp_bw_use_normal_percent);
|
||||
dcn3_01_soc.max_avg_dram_bw_use_normal_percent =
|
||||
fixed16_to_double_to_cpu(bb->max_avg_dram_bw_use_normal_percent);
|
||||
dcn3_01_soc.writeback_latency_us =
|
||||
fixed16_to_double_to_cpu(bb->writeback_latency_us);
|
||||
dcn3_01_soc.ideal_dram_bw_after_urgent_percent =
|
||||
fixed16_to_double_to_cpu(bb->ideal_dram_bw_after_urgent_percent);
|
||||
dcn3_01_soc.max_request_size_bytes =
|
||||
le32_to_cpu(bb->max_request_size_bytes);
|
||||
dcn3_01_soc.dram_channel_width_bytes =
|
||||
le32_to_cpu(bb->dram_channel_width_bytes);
|
||||
dcn3_01_soc.fabric_datapath_to_dcn_data_return_bytes =
|
||||
le32_to_cpu(bb->fabric_datapath_to_dcn_data_return_bytes);
|
||||
dcn3_01_soc.dcn_downspread_percent =
|
||||
fixed16_to_double_to_cpu(bb->dcn_downspread_percent);
|
||||
dcn3_01_soc.downspread_percent =
|
||||
fixed16_to_double_to_cpu(bb->downspread_percent);
|
||||
dcn3_01_soc.dram_page_open_time_ns =
|
||||
fixed16_to_double_to_cpu(bb->dram_page_open_time_ns);
|
||||
dcn3_01_soc.dram_rw_turnaround_time_ns =
|
||||
fixed16_to_double_to_cpu(bb->dram_rw_turnaround_time_ns);
|
||||
dcn3_01_soc.dram_return_buffer_per_channel_bytes =
|
||||
le32_to_cpu(bb->dram_return_buffer_per_channel_bytes);
|
||||
dcn3_01_soc.round_trip_ping_latency_dcfclk_cycles =
|
||||
le32_to_cpu(bb->round_trip_ping_latency_dcfclk_cycles);
|
||||
dcn3_01_soc.urgent_out_of_order_return_per_channel_bytes =
|
||||
le32_to_cpu(bb->urgent_out_of_order_return_per_channel_bytes);
|
||||
dcn3_01_soc.channel_interleave_bytes =
|
||||
le32_to_cpu(bb->channel_interleave_bytes);
|
||||
dcn3_01_soc.num_banks =
|
||||
le32_to_cpu(bb->num_banks);
|
||||
dcn3_01_soc.num_chans =
|
||||
le32_to_cpu(bb->num_chans);
|
||||
dcn3_01_soc.gpuvm_min_page_size_bytes =
|
||||
le32_to_cpu(bb->vmm_page_size_bytes);
|
||||
dcn3_01_soc.dram_clock_change_latency_us =
|
||||
fixed16_to_double_to_cpu(bb->dram_clock_change_latency_us);
|
||||
dcn3_01_soc.writeback_dram_clock_change_latency_us =
|
||||
fixed16_to_double_to_cpu(bb->writeback_dram_clock_change_latency_us);
|
||||
dcn3_01_soc.return_bus_width_bytes =
|
||||
le32_to_cpu(bb->return_bus_width_bytes);
|
||||
dcn3_01_soc.dispclk_dppclk_vco_speed_mhz =
|
||||
le32_to_cpu(bb->dispclk_dppclk_vco_speed_mhz);
|
||||
dcn3_01_soc.xfc_bus_transport_time_us =
|
||||
le32_to_cpu(bb->xfc_bus_transport_time_us);
|
||||
dcn3_01_soc.xfc_xbuf_latency_tolerance_us =
|
||||
le32_to_cpu(bb->xfc_xbuf_latency_tolerance_us);
|
||||
dcn3_01_soc.use_urgent_burst_bw =
|
||||
le32_to_cpu(bb->use_urgent_burst_bw);
|
||||
dcn3_01_soc.num_states =
|
||||
le32_to_cpu(bb->num_states);
|
||||
|
||||
for (i = 0; i < dcn3_01_soc.num_states; i++) {
|
||||
dcn3_01_soc.clock_limits[i].state =
|
||||
le32_to_cpu(bb->clock_limits[i].state);
|
||||
dcn3_01_soc.clock_limits[i].dcfclk_mhz =
|
||||
fixed16_to_double_to_cpu(bb->clock_limits[i].dcfclk_mhz);
|
||||
dcn3_01_soc.clock_limits[i].fabricclk_mhz =
|
||||
fixed16_to_double_to_cpu(bb->clock_limits[i].fabricclk_mhz);
|
||||
dcn3_01_soc.clock_limits[i].dispclk_mhz =
|
||||
fixed16_to_double_to_cpu(bb->clock_limits[i].dispclk_mhz);
|
||||
dcn3_01_soc.clock_limits[i].dppclk_mhz =
|
||||
fixed16_to_double_to_cpu(bb->clock_limits[i].dppclk_mhz);
|
||||
dcn3_01_soc.clock_limits[i].phyclk_mhz =
|
||||
fixed16_to_double_to_cpu(bb->clock_limits[i].phyclk_mhz);
|
||||
dcn3_01_soc.clock_limits[i].socclk_mhz =
|
||||
fixed16_to_double_to_cpu(bb->clock_limits[i].socclk_mhz);
|
||||
dcn3_01_soc.clock_limits[i].dscclk_mhz =
|
||||
fixed16_to_double_to_cpu(bb->clock_limits[i].dscclk_mhz);
|
||||
dcn3_01_soc.clock_limits[i].dram_speed_mts =
|
||||
fixed16_to_double_to_cpu(bb->clock_limits[i].dram_speed_mts);
|
||||
}
|
||||
}
|
||||
|
||||
loaded_ip->max_num_otg = pool->base.res_cap->num_timing_generator;
|
||||
loaded_ip->max_num_dpp = pool->base.pipe_count;
|
||||
dcn20_patch_bounding_box(dc, loaded_bb);
|
||||
|
||||
if (!bb && dc->ctx->dc_bios->funcs->get_soc_bb_info) {
|
||||
if (dc->ctx->dc_bios->funcs->get_soc_bb_info) {
|
||||
struct bp_soc_bb_info bb_info = {0};
|
||||
|
||||
if (dc->ctx->dc_bios->funcs->get_soc_bb_info(dc->ctx->dc_bios, &bb_info) == BP_RESULT_OK) {
|
||||
|
|
|
@ -13,7 +13,7 @@
|
|||
DCN3_02 = dcn302_init.o dcn302_hwseq.o dcn302_resource.o
|
||||
|
||||
ifdef CONFIG_X86
|
||||
CFLAGS_$(AMDDALPATH)/dc/dcn302/dcn302_resource.o := -mhard-float -msse
|
||||
CFLAGS_$(AMDDALPATH)/dc/dcn302/dcn302_resource.o := -msse
|
||||
endif
|
||||
|
||||
ifdef CONFIG_PPC64
|
||||
|
@ -24,6 +24,7 @@ ifdef CONFIG_CC_IS_GCC
|
|||
ifeq ($(call cc-ifversion, -lt, 0701, y), y)
|
||||
IS_OLD_GCC = 1
|
||||
endif
|
||||
CFLAGS_$(AMDDALPATH)/dc/dcn302/dcn302_resource.o += -mhard-float
|
||||
endif
|
||||
|
||||
ifdef CONFIG_X86
|
||||
|
|
|
@ -54,6 +54,7 @@
|
|||
#include "dce/dce_panel_cntl.h"
|
||||
#include "dce/dmub_abm.h"
|
||||
#include "dce/dmub_psr.h"
|
||||
#include "clk_mgr.h"
|
||||
|
||||
#include "hw_sequencer_private.h"
|
||||
#include "reg_helper.h"
|
||||
|
@ -163,8 +164,8 @@ struct _vcs_dpi_soc_bounding_box_st dcn3_02_soc = {
|
|||
|
||||
.min_dcfclk = 500.0, /* TODO: set this to actual min DCFCLK */
|
||||
.num_states = 1,
|
||||
.sr_exit_time_us = 5.20,
|
||||
.sr_enter_plus_exit_time_us = 9.60,
|
||||
.sr_exit_time_us = 12,
|
||||
.sr_enter_plus_exit_time_us = 20,
|
||||
.urgent_latency_us = 4.0,
|
||||
.urgent_latency_pixel_data_only_us = 4.0,
|
||||
.urgent_latency_pixel_mixed_with_vm_data_us = 4.0,
|
||||
|
@ -191,7 +192,7 @@ struct _vcs_dpi_soc_bounding_box_st dcn3_02_soc = {
|
|||
.num_banks = 8,
|
||||
.gpuvm_min_page_size_bytes = 4096,
|
||||
.hostvm_min_page_size_bytes = 4096,
|
||||
.dram_clock_change_latency_us = 350,
|
||||
.dram_clock_change_latency_us = 404,
|
||||
.dummy_pstate_latency_us = 5,
|
||||
.writeback_dram_clock_change_latency_us = 23.0,
|
||||
.return_bus_width_bytes = 64,
|
||||
|
@ -1229,6 +1230,165 @@ static void dcn302_destroy_resource_pool(struct resource_pool **pool)
|
|||
*pool = NULL;
|
||||
}
|
||||
|
||||
static void dcn302_get_optimal_dcfclk_fclk_for_uclk(unsigned int uclk_mts,
|
||||
unsigned int *optimal_dcfclk,
|
||||
unsigned int *optimal_fclk)
|
||||
{
|
||||
double bw_from_dram, bw_from_dram1, bw_from_dram2;
|
||||
|
||||
bw_from_dram1 = uclk_mts * dcn3_02_soc.num_chans *
|
||||
dcn3_02_soc.dram_channel_width_bytes * (dcn3_02_soc.max_avg_dram_bw_use_normal_percent / 100);
|
||||
bw_from_dram2 = uclk_mts * dcn3_02_soc.num_chans *
|
||||
dcn3_02_soc.dram_channel_width_bytes * (dcn3_02_soc.max_avg_sdp_bw_use_normal_percent / 100);
|
||||
|
||||
bw_from_dram = (bw_from_dram1 < bw_from_dram2) ? bw_from_dram1 : bw_from_dram2;
|
||||
|
||||
if (optimal_fclk)
|
||||
*optimal_fclk = bw_from_dram /
|
||||
(dcn3_02_soc.fabric_datapath_to_dcn_data_return_bytes * (dcn3_02_soc.max_avg_sdp_bw_use_normal_percent / 100));
|
||||
|
||||
if (optimal_dcfclk)
|
||||
*optimal_dcfclk = bw_from_dram /
|
||||
(dcn3_02_soc.return_bus_width_bytes * (dcn3_02_soc.max_avg_sdp_bw_use_normal_percent / 100));
|
||||
}
|
||||
|
||||
void dcn302_update_bw_bounding_box(struct dc *dc, struct clk_bw_params *bw_params)
|
||||
{
|
||||
unsigned int i, j;
|
||||
unsigned int num_states = 0;
|
||||
|
||||
unsigned int dcfclk_mhz[DC__VOLTAGE_STATES] = {0};
|
||||
unsigned int dram_speed_mts[DC__VOLTAGE_STATES] = {0};
|
||||
unsigned int optimal_uclk_for_dcfclk_sta_targets[DC__VOLTAGE_STATES] = {0};
|
||||
unsigned int optimal_dcfclk_for_uclk[DC__VOLTAGE_STATES] = {0};
|
||||
|
||||
unsigned int dcfclk_sta_targets[DC__VOLTAGE_STATES] = {694, 875, 1000, 1200};
|
||||
unsigned int num_dcfclk_sta_targets = 4;
|
||||
unsigned int num_uclk_states;
|
||||
|
||||
|
||||
if (dc->ctx->dc_bios->vram_info.num_chans)
|
||||
dcn3_02_soc.num_chans = dc->ctx->dc_bios->vram_info.num_chans;
|
||||
|
||||
if (dc->ctx->dc_bios->vram_info.dram_channel_width_bytes)
|
||||
dcn3_02_soc.dram_channel_width_bytes = dc->ctx->dc_bios->vram_info.dram_channel_width_bytes;
|
||||
|
||||
dcn3_02_soc.dispclk_dppclk_vco_speed_mhz = dc->clk_mgr->dentist_vco_freq_khz / 1000.0;
|
||||
dc->dml.soc.dispclk_dppclk_vco_speed_mhz = dc->clk_mgr->dentist_vco_freq_khz / 1000.0;
|
||||
|
||||
if (bw_params->clk_table.entries[0].memclk_mhz) {
|
||||
int max_dcfclk_mhz = 0, max_dispclk_mhz = 0, max_dppclk_mhz = 0, max_phyclk_mhz = 0;
|
||||
|
||||
for (i = 0; i < MAX_NUM_DPM_LVL; i++) {
|
||||
if (bw_params->clk_table.entries[i].dcfclk_mhz > max_dcfclk_mhz)
|
||||
max_dcfclk_mhz = bw_params->clk_table.entries[i].dcfclk_mhz;
|
||||
if (bw_params->clk_table.entries[i].dispclk_mhz > max_dispclk_mhz)
|
||||
max_dispclk_mhz = bw_params->clk_table.entries[i].dispclk_mhz;
|
||||
if (bw_params->clk_table.entries[i].dppclk_mhz > max_dppclk_mhz)
|
||||
max_dppclk_mhz = bw_params->clk_table.entries[i].dppclk_mhz;
|
||||
if (bw_params->clk_table.entries[i].phyclk_mhz > max_phyclk_mhz)
|
||||
max_phyclk_mhz = bw_params->clk_table.entries[i].phyclk_mhz;
|
||||
}
|
||||
if (!max_dcfclk_mhz)
|
||||
max_dcfclk_mhz = dcn3_02_soc.clock_limits[0].dcfclk_mhz;
|
||||
if (!max_dispclk_mhz)
|
||||
max_dispclk_mhz = dcn3_02_soc.clock_limits[0].dispclk_mhz;
|
||||
if (!max_dppclk_mhz)
|
||||
max_dppclk_mhz = dcn3_02_soc.clock_limits[0].dppclk_mhz;
|
||||
if (!max_phyclk_mhz)
|
||||
max_phyclk_mhz = dcn3_02_soc.clock_limits[0].phyclk_mhz;
|
||||
|
||||
if (max_dcfclk_mhz > dcfclk_sta_targets[num_dcfclk_sta_targets-1]) {
|
||||
/* If max DCFCLK is greater than the max DCFCLK STA target, insert into the DCFCLK STA target array */
|
||||
dcfclk_sta_targets[num_dcfclk_sta_targets] = max_dcfclk_mhz;
|
||||
num_dcfclk_sta_targets++;
|
||||
} else if (max_dcfclk_mhz < dcfclk_sta_targets[num_dcfclk_sta_targets-1]) {
|
||||
/* If max DCFCLK is less than the max DCFCLK STA target, cap values and remove duplicates */
|
||||
for (i = 0; i < num_dcfclk_sta_targets; i++) {
|
||||
if (dcfclk_sta_targets[i] > max_dcfclk_mhz) {
|
||||
dcfclk_sta_targets[i] = max_dcfclk_mhz;
|
||||
break;
|
||||
}
|
||||
}
|
||||
/* Update size of array since we "removed" duplicates */
|
||||
num_dcfclk_sta_targets = i + 1;
|
||||
}
|
||||
|
||||
num_uclk_states = bw_params->clk_table.num_entries;
|
||||
|
||||
/* Calculate optimal dcfclk for each uclk */
|
||||
for (i = 0; i < num_uclk_states; i++) {
|
||||
dcn302_get_optimal_dcfclk_fclk_for_uclk(bw_params->clk_table.entries[i].memclk_mhz * 16,
|
||||
&optimal_dcfclk_for_uclk[i], NULL);
|
||||
if (optimal_dcfclk_for_uclk[i] < bw_params->clk_table.entries[0].dcfclk_mhz) {
|
||||
optimal_dcfclk_for_uclk[i] = bw_params->clk_table.entries[0].dcfclk_mhz;
|
||||
}
|
||||
}
|
||||
|
||||
/* Calculate optimal uclk for each dcfclk sta target */
|
||||
for (i = 0; i < num_dcfclk_sta_targets; i++) {
|
||||
for (j = 0; j < num_uclk_states; j++) {
|
||||
if (dcfclk_sta_targets[i] < optimal_dcfclk_for_uclk[j]) {
|
||||
optimal_uclk_for_dcfclk_sta_targets[i] =
|
||||
bw_params->clk_table.entries[j].memclk_mhz * 16;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
i = 0;
|
||||
j = 0;
|
||||
/* create the final dcfclk and uclk table */
|
||||
while (i < num_dcfclk_sta_targets && j < num_uclk_states && num_states < DC__VOLTAGE_STATES) {
|
||||
if (dcfclk_sta_targets[i] < optimal_dcfclk_for_uclk[j] && i < num_dcfclk_sta_targets) {
|
||||
dcfclk_mhz[num_states] = dcfclk_sta_targets[i];
|
||||
dram_speed_mts[num_states++] = optimal_uclk_for_dcfclk_sta_targets[i++];
|
||||
} else {
|
||||
if (j < num_uclk_states && optimal_dcfclk_for_uclk[j] <= max_dcfclk_mhz) {
|
||||
dcfclk_mhz[num_states] = optimal_dcfclk_for_uclk[j];
|
||||
dram_speed_mts[num_states++] = bw_params->clk_table.entries[j++].memclk_mhz * 16;
|
||||
} else {
|
||||
j = num_uclk_states;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
while (i < num_dcfclk_sta_targets && num_states < DC__VOLTAGE_STATES) {
|
||||
dcfclk_mhz[num_states] = dcfclk_sta_targets[i];
|
||||
dram_speed_mts[num_states++] = optimal_uclk_for_dcfclk_sta_targets[i++];
|
||||
}
|
||||
|
||||
while (j < num_uclk_states && num_states < DC__VOLTAGE_STATES &&
|
||||
optimal_dcfclk_for_uclk[j] <= max_dcfclk_mhz) {
|
||||
dcfclk_mhz[num_states] = optimal_dcfclk_for_uclk[j];
|
||||
dram_speed_mts[num_states++] = bw_params->clk_table.entries[j++].memclk_mhz * 16;
|
||||
}
|
||||
|
||||
dcn3_02_soc.num_states = num_states;
|
||||
for (i = 0; i < dcn3_02_soc.num_states; i++) {
|
||||
dcn3_02_soc.clock_limits[i].state = i;
|
||||
dcn3_02_soc.clock_limits[i].dcfclk_mhz = dcfclk_mhz[i];
|
||||
dcn3_02_soc.clock_limits[i].fabricclk_mhz = dcfclk_mhz[i];
|
||||
dcn3_02_soc.clock_limits[i].dram_speed_mts = dram_speed_mts[i];
|
||||
|
||||
/* Fill all states with max values of all other clocks */
|
||||
dcn3_02_soc.clock_limits[i].dispclk_mhz = max_dispclk_mhz;
|
||||
dcn3_02_soc.clock_limits[i].dppclk_mhz = max_dppclk_mhz;
|
||||
dcn3_02_soc.clock_limits[i].phyclk_mhz = max_phyclk_mhz;
|
||||
dcn3_02_soc.clock_limits[i].dtbclk_mhz = dcn3_02_soc.clock_limits[0].dtbclk_mhz;
|
||||
/* These clocks cannot come from bw_params, always fill from dcn3_02_soc[1] */
|
||||
/* FCLK, PHYCLK_D18, SOCCLK, DSCCLK */
|
||||
dcn3_02_soc.clock_limits[i].phyclk_d18_mhz = dcn3_02_soc.clock_limits[0].phyclk_d18_mhz;
|
||||
dcn3_02_soc.clock_limits[i].socclk_mhz = dcn3_02_soc.clock_limits[0].socclk_mhz;
|
||||
dcn3_02_soc.clock_limits[i].dscclk_mhz = dcn3_02_soc.clock_limits[0].dscclk_mhz;
|
||||
}
|
||||
/* re-init DML with updated bb */
|
||||
dml_init_instance(&dc->dml, &dcn3_02_soc, &dcn3_02_ip, DML_PROJECT_DCN30);
|
||||
if (dc->current_state)
|
||||
dml_init_instance(&dc->current_state->bw_ctx.dml, &dcn3_02_soc, &dcn3_02_ip, DML_PROJECT_DCN30);
|
||||
}
|
||||
}
|
||||
|
||||
static struct resource_funcs dcn302_res_pool_funcs = {
|
||||
.destroy = dcn302_destroy_resource_pool,
|
||||
.link_enc_create = dcn302_link_encoder_create,
|
||||
|
@ -1245,7 +1405,7 @@ static struct resource_funcs dcn302_res_pool_funcs = {
|
|||
.find_first_free_match_stream_enc_for_link = dcn10_find_first_free_match_stream_enc_for_link,
|
||||
.acquire_post_bldn_3dlut = dcn30_acquire_post_bldn_3dlut,
|
||||
.release_post_bldn_3dlut = dcn30_release_post_bldn_3dlut,
|
||||
.update_bw_bounding_box = dcn30_update_bw_bounding_box,
|
||||
.update_bw_bounding_box = dcn302_update_bw_bounding_box,
|
||||
.patch_unknown_plane_state = dcn20_patch_unknown_plane_state,
|
||||
};
|
||||
|
||||
|
@ -1316,7 +1476,10 @@ static bool dcn302_resource_construct(
|
|||
dc->caps.max_cursor_size = 256;
|
||||
dc->caps.min_horizontal_blanking_period = 80;
|
||||
dc->caps.dmdata_alloc_size = 2048;
|
||||
|
||||
dc->caps.mall_size_per_mem_channel = 4;
|
||||
/* total size = mall per channel * num channels * 1024 * 1024 */
|
||||
dc->caps.mall_size_total = dc->caps.mall_size_per_mem_channel * dc->ctx->dc_bios->vram_info.num_chans * 1048576;
|
||||
dc->caps.cursor_cache_size = dc->caps.max_cursor_size * dc->caps.max_cursor_size * 8;
|
||||
dc->caps.max_slave_planes = 1;
|
||||
dc->caps.post_blend_color_processing = true;
|
||||
dc->caps.force_dp_tps4_for_cp2520 = true;
|
||||
|
|
|
@ -30,4 +30,6 @@
|
|||
|
||||
struct resource_pool *dcn302_create_resource_pool(const struct dc_init_data *init_data, struct dc *dc);
|
||||
|
||||
void dcn302_update_bw_bounding_box(struct dc *dc, struct clk_bw_params *bw_params);
|
||||
|
||||
#endif /* _DCN302_RESOURCE_H_ */
|
||||
|
|
|
@ -30,9 +30,10 @@ struct dc_link;
|
|||
|
||||
struct cp_psp_stream_config {
|
||||
uint8_t otg_inst;
|
||||
uint8_t link_enc_inst;
|
||||
uint8_t stream_enc_inst;
|
||||
uint8_t mst_supported;
|
||||
uint8_t dig_be;
|
||||
uint8_t dig_fe;
|
||||
uint8_t assr_enabled;
|
||||
uint8_t mst_enabled;
|
||||
void *dm_stream_ctx;
|
||||
bool dpms_off;
|
||||
};
|
||||
|
|
|
@ -3263,6 +3263,7 @@ static void CalculateFlipSchedule(
|
|||
|
||||
static unsigned int TruncToValidBPP(
|
||||
double DecimalBPP,
|
||||
double DesiredBPP,
|
||||
bool DSCEnabled,
|
||||
enum output_encoder_class Output,
|
||||
enum output_format_class Format,
|
||||
|
@ -3270,31 +3271,31 @@ static unsigned int TruncToValidBPP(
|
|||
{
|
||||
if (Output == dm_hdmi) {
|
||||
if (Format == dm_420) {
|
||||
if (DecimalBPP >= 18)
|
||||
if (DecimalBPP >= 18 && (DesiredBPP == 0 || DesiredBPP == 18))
|
||||
return 18;
|
||||
else if (DecimalBPP >= 15)
|
||||
else if (DecimalBPP >= 15 && (DesiredBPP == 0 || DesiredBPP == 15))
|
||||
return 15;
|
||||
else if (DecimalBPP >= 12)
|
||||
else if (DecimalBPP >= 12 && (DesiredBPP == 0 || DesiredBPP == 12))
|
||||
return 12;
|
||||
else
|
||||
return BPP_INVALID;
|
||||
} else if (Format == dm_444) {
|
||||
if (DecimalBPP >= 36)
|
||||
if (DecimalBPP >= 36 && (DesiredBPP == 0 || DesiredBPP == 36))
|
||||
return 36;
|
||||
else if (DecimalBPP >= 30)
|
||||
else if (DecimalBPP >= 30 && (DesiredBPP == 0 || DesiredBPP == 30))
|
||||
return 30;
|
||||
else if (DecimalBPP >= 24)
|
||||
else if (DecimalBPP >= 24 && (DesiredBPP == 0 || DesiredBPP == 24))
|
||||
return 24;
|
||||
else if (DecimalBPP >= 18)
|
||||
else if (DecimalBPP >= 18 && (DesiredBPP == 0 || DesiredBPP == 18))
|
||||
return 18;
|
||||
else
|
||||
return BPP_INVALID;
|
||||
} else {
|
||||
if (DecimalBPP / 1.5 >= 24)
|
||||
if (DecimalBPP / 1.5 >= 24 && (DesiredBPP == 0 || DesiredBPP == 24))
|
||||
return 24;
|
||||
else if (DecimalBPP / 1.5 >= 20)
|
||||
else if (DecimalBPP / 1.5 >= 20 && (DesiredBPP == 0 || DesiredBPP == 20))
|
||||
return 20;
|
||||
else if (DecimalBPP / 1.5 >= 16)
|
||||
else if (DecimalBPP / 1.5 >= 16 && (DesiredBPP == 0 || DesiredBPP == 16))
|
||||
return 16;
|
||||
else
|
||||
return BPP_INVALID;
|
||||
|
@ -3302,53 +3303,86 @@ static unsigned int TruncToValidBPP(
|
|||
} else {
|
||||
if (DSCEnabled) {
|
||||
if (Format == dm_420) {
|
||||
if (DecimalBPP < 6)
|
||||
return BPP_INVALID;
|
||||
else if (DecimalBPP >= 1.5 * DSCInputBitPerComponent - 1 / 16)
|
||||
return 1.5 * DSCInputBitPerComponent - 1 / 16;
|
||||
else
|
||||
return dml_floor(16 * DecimalBPP, 1) / 16;
|
||||
if (DesiredBPP == 0) {
|
||||
if (DecimalBPP < 6)
|
||||
return BPP_INVALID;
|
||||
else if (DecimalBPP >= 1.5 * DSCInputBitPerComponent - 1.0 / 16.0)
|
||||
return 1.5 * DSCInputBitPerComponent - 1.0 / 16.0;
|
||||
else
|
||||
return dml_floor(16 * DecimalBPP, 1) / 16.0;
|
||||
} else {
|
||||
if (DecimalBPP < 6
|
||||
|| DesiredBPP < 6
|
||||
|| DesiredBPP > 1.5 * DSCInputBitPerComponent - 1.0 / 16.0
|
||||
|| DecimalBPP < DesiredBPP) {
|
||||
return BPP_INVALID;
|
||||
} else {
|
||||
return DesiredBPP;
|
||||
}
|
||||
}
|
||||
} else if (Format == dm_n422) {
|
||||
if (DecimalBPP < 7)
|
||||
return BPP_INVALID;
|
||||
else if (DecimalBPP >= 2 * DSCInputBitPerComponent - 1 / 16)
|
||||
return 2 * DSCInputBitPerComponent - 1 / 16;
|
||||
else
|
||||
return dml_floor(16 * DecimalBPP, 1) / 16;
|
||||
if (DesiredBPP == 0) {
|
||||
if (DecimalBPP < 7)
|
||||
return BPP_INVALID;
|
||||
else if (DecimalBPP >= 2 * DSCInputBitPerComponent - 1.0 / 16.0)
|
||||
return 2 * DSCInputBitPerComponent - 1.0 / 16.0;
|
||||
else
|
||||
return dml_floor(16 * DecimalBPP, 1) / 16.0;
|
||||
} else {
|
||||
if (DecimalBPP < 7
|
||||
|| DesiredBPP < 7
|
||||
|| DesiredBPP > 2 * DSCInputBitPerComponent - 1.0 / 16.0
|
||||
|| DecimalBPP < DesiredBPP) {
|
||||
return BPP_INVALID;
|
||||
} else {
|
||||
return DesiredBPP;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (DecimalBPP < 8)
|
||||
return BPP_INVALID;
|
||||
else if (DecimalBPP >= 3 * DSCInputBitPerComponent - 1 / 16)
|
||||
return 3 * DSCInputBitPerComponent - 1 / 16;
|
||||
else
|
||||
return dml_floor(16 * DecimalBPP, 1) / 16;
|
||||
if (DesiredBPP == 0) {
|
||||
if (DecimalBPP < 8)
|
||||
return BPP_INVALID;
|
||||
else if (DecimalBPP >= 3 * DSCInputBitPerComponent - 1.0 / 16.0)
|
||||
return 3 * DSCInputBitPerComponent - 1.0 / 16.0;
|
||||
else
|
||||
return dml_floor(16 * DecimalBPP, 1) / 16.0;
|
||||
} else {
|
||||
if (DecimalBPP < 8
|
||||
|| DesiredBPP < 8
|
||||
|| DesiredBPP > 3 * DSCInputBitPerComponent - 1.0 / 16.0
|
||||
|| DecimalBPP < DesiredBPP) {
|
||||
return BPP_INVALID;
|
||||
} else {
|
||||
return DesiredBPP;
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if (Format == dm_420) {
|
||||
if (DecimalBPP >= 18)
|
||||
if (DecimalBPP >= 18 && (DesiredBPP == 0 || DesiredBPP == 18))
|
||||
return 18;
|
||||
else if (DecimalBPP >= 15)
|
||||
else if (DecimalBPP >= 15 && (DesiredBPP == 0 || DesiredBPP == 15))
|
||||
return 15;
|
||||
else if (DecimalBPP >= 12)
|
||||
else if (DecimalBPP >= 12 && (DesiredBPP == 0 || DesiredBPP == 12))
|
||||
return 12;
|
||||
else
|
||||
return BPP_INVALID;
|
||||
} else if (Format == dm_s422 || Format == dm_n422) {
|
||||
if (DecimalBPP >= 24)
|
||||
if (DecimalBPP >= 24 && (DesiredBPP == 0 || DesiredBPP == 24))
|
||||
return 24;
|
||||
else if (DecimalBPP >= 20)
|
||||
else if (DecimalBPP >= 20 && (DesiredBPP == 0 || DesiredBPP == 20))
|
||||
return 20;
|
||||
else if (DecimalBPP >= 16)
|
||||
else if (DecimalBPP >= 16 && (DesiredBPP == 0 || DesiredBPP == 16))
|
||||
return 16;
|
||||
else
|
||||
return BPP_INVALID;
|
||||
} else {
|
||||
if (DecimalBPP >= 36)
|
||||
if (DecimalBPP >= 36 && (DesiredBPP == 0 || DesiredBPP == 36))
|
||||
return 36;
|
||||
else if (DecimalBPP >= 30)
|
||||
else if (DecimalBPP >= 30 && (DesiredBPP == 0 || DesiredBPP == 30))
|
||||
return 30;
|
||||
else if (DecimalBPP >= 24)
|
||||
else if (DecimalBPP >= 24 && (DesiredBPP == 0 || DesiredBPP == 24))
|
||||
return 24;
|
||||
else if (DecimalBPP >= 18)
|
||||
else if (DecimalBPP >= 18 && (DesiredBPP == 0 || DesiredBPP == 18))
|
||||
return 18;
|
||||
else
|
||||
return BPP_INVALID;
|
||||
|
@ -4137,6 +4171,7 @@ void dml20v2_ModeSupportAndSystemConfigurationFull(struct display_mode_lib *mode
|
|||
locals->RequiresFEC[i][k] = 0;
|
||||
locals->OutputBppPerState[i][k] = TruncToValidBPP(
|
||||
dml_min(600.0, mode_lib->vba.PHYCLKPerState[i]) / mode_lib->vba.PixelClockBackEnd[k] * 24,
|
||||
mode_lib->vba.ForcedOutputLinkBPP[k],
|
||||
false,
|
||||
mode_lib->vba.Output[k],
|
||||
mode_lib->vba.OutputFormat[k],
|
||||
|
@ -4153,6 +4188,7 @@ void dml20v2_ModeSupportAndSystemConfigurationFull(struct display_mode_lib *mode
|
|||
mode_lib->vba.Outbpp = TruncToValidBPP(
|
||||
(1.0 - mode_lib->vba.Downspreading / 100.0) * 270.0
|
||||
* mode_lib->vba.OutputLinkDPLanes[k] / mode_lib->vba.PixelClockBackEnd[k] * 8.0,
|
||||
mode_lib->vba.ForcedOutputLinkBPP[k],
|
||||
false,
|
||||
mode_lib->vba.Output[k],
|
||||
mode_lib->vba.OutputFormat[k],
|
||||
|
@ -4160,6 +4196,7 @@ void dml20v2_ModeSupportAndSystemConfigurationFull(struct display_mode_lib *mode
|
|||
mode_lib->vba.OutbppDSC = TruncToValidBPP(
|
||||
(1.0 - mode_lib->vba.Downspreading / 100.0) * (1.0 - mode_lib->vba.EffectiveFECOverhead / 100.0) * 270.0
|
||||
* mode_lib->vba.OutputLinkDPLanes[k] / mode_lib->vba.PixelClockBackEnd[k] * 8.0,
|
||||
mode_lib->vba.ForcedOutputLinkBPP[k],
|
||||
true,
|
||||
mode_lib->vba.Output[k],
|
||||
mode_lib->vba.OutputFormat[k],
|
||||
|
@ -4182,6 +4219,7 @@ void dml20v2_ModeSupportAndSystemConfigurationFull(struct display_mode_lib *mode
|
|||
mode_lib->vba.Outbpp = TruncToValidBPP(
|
||||
(1.0 - mode_lib->vba.Downspreading / 100.0) * 540.0
|
||||
* mode_lib->vba.OutputLinkDPLanes[k] / mode_lib->vba.PixelClockBackEnd[k] * 8.0,
|
||||
mode_lib->vba.ForcedOutputLinkBPP[k],
|
||||
false,
|
||||
mode_lib->vba.Output[k],
|
||||
mode_lib->vba.OutputFormat[k],
|
||||
|
@ -4189,6 +4227,7 @@ void dml20v2_ModeSupportAndSystemConfigurationFull(struct display_mode_lib *mode
|
|||
mode_lib->vba.OutbppDSC = TruncToValidBPP(
|
||||
(1.0 - mode_lib->vba.Downspreading / 100.0) * (1.0 - mode_lib->vba.EffectiveFECOverhead / 100.0) * 540.0
|
||||
* mode_lib->vba.OutputLinkDPLanes[k] / mode_lib->vba.PixelClockBackEnd[k] * 8.0,
|
||||
mode_lib->vba.ForcedOutputLinkBPP[k],
|
||||
true,
|
||||
mode_lib->vba.Output[k],
|
||||
mode_lib->vba.OutputFormat[k],
|
||||
|
@ -4213,6 +4252,7 @@ void dml20v2_ModeSupportAndSystemConfigurationFull(struct display_mode_lib *mode
|
|||
mode_lib->vba.Outbpp = TruncToValidBPP(
|
||||
(1.0 - mode_lib->vba.Downspreading / 100.0) * 810.0
|
||||
* mode_lib->vba.OutputLinkDPLanes[k] / mode_lib->vba.PixelClockBackEnd[k] * 8.0,
|
||||
mode_lib->vba.ForcedOutputLinkBPP[k],
|
||||
false,
|
||||
mode_lib->vba.Output[k],
|
||||
mode_lib->vba.OutputFormat[k],
|
||||
|
@ -4220,6 +4260,7 @@ void dml20v2_ModeSupportAndSystemConfigurationFull(struct display_mode_lib *mode
|
|||
mode_lib->vba.OutbppDSC = TruncToValidBPP(
|
||||
(1.0 - mode_lib->vba.Downspreading / 100.0) * (1.0 - mode_lib->vba.EffectiveFECOverhead / 100.0) * 810.0
|
||||
* mode_lib->vba.OutputLinkDPLanes[k] / mode_lib->vba.PixelClockBackEnd[k] * 8.0,
|
||||
mode_lib->vba.ForcedOutputLinkBPP[k],
|
||||
true,
|
||||
mode_lib->vba.Output[k],
|
||||
mode_lib->vba.OutputFormat[k],
|
||||
|
|
|
@ -165,8 +165,8 @@ static void handle_det_buf_split(struct display_mode_lib *mode_lib,
|
|||
unsigned int swath_bytes_c = 0;
|
||||
unsigned int full_swath_bytes_packed_l = 0;
|
||||
unsigned int full_swath_bytes_packed_c = 0;
|
||||
bool req128_l = 0;
|
||||
bool req128_c = 0;
|
||||
bool req128_l = false;
|
||||
bool req128_c = false;
|
||||
bool surf_linear = (pipe_src_param.sw_mode == dm_sw_linear);
|
||||
bool surf_vert = (pipe_src_param.source_scan == dm_vert);
|
||||
unsigned int log2_swath_height_l = 0;
|
||||
|
@ -191,37 +191,37 @@ static void handle_det_buf_split(struct display_mode_lib *mode_lib,
|
|||
total_swath_bytes = 2 * full_swath_bytes_packed_l;
|
||||
|
||||
if (total_swath_bytes <= detile_buf_size_in_bytes) { //full 256b request
|
||||
req128_l = 0;
|
||||
req128_c = 0;
|
||||
req128_l = false;
|
||||
req128_c = false;
|
||||
swath_bytes_l = full_swath_bytes_packed_l;
|
||||
swath_bytes_c = full_swath_bytes_packed_c;
|
||||
} else if (!rq_param->yuv420) {
|
||||
req128_l = 1;
|
||||
req128_c = 0;
|
||||
req128_l = true;
|
||||
req128_c = false;
|
||||
swath_bytes_c = full_swath_bytes_packed_c;
|
||||
swath_bytes_l = full_swath_bytes_packed_l / 2;
|
||||
} else if ((double)full_swath_bytes_packed_l / (double)full_swath_bytes_packed_c < 1.5) {
|
||||
req128_l = 0;
|
||||
req128_c = 1;
|
||||
req128_l = false;
|
||||
req128_c = true;
|
||||
swath_bytes_l = full_swath_bytes_packed_l;
|
||||
swath_bytes_c = full_swath_bytes_packed_c / 2;
|
||||
|
||||
total_swath_bytes = 2 * swath_bytes_l + 2 * swath_bytes_c;
|
||||
|
||||
if (total_swath_bytes > detile_buf_size_in_bytes) {
|
||||
req128_l = 1;
|
||||
req128_l = true;
|
||||
swath_bytes_l = full_swath_bytes_packed_l / 2;
|
||||
}
|
||||
} else {
|
||||
req128_l = 1;
|
||||
req128_c = 0;
|
||||
req128_l = true;
|
||||
req128_c = false;
|
||||
swath_bytes_l = full_swath_bytes_packed_l/2;
|
||||
swath_bytes_c = full_swath_bytes_packed_c;
|
||||
|
||||
total_swath_bytes = 2 * swath_bytes_l + 2 * swath_bytes_c;
|
||||
|
||||
if (total_swath_bytes > detile_buf_size_in_bytes) {
|
||||
req128_c = 1;
|
||||
req128_c = true;
|
||||
swath_bytes_c = full_swath_bytes_packed_c/2;
|
||||
}
|
||||
}
|
||||
|
@ -1006,8 +1006,8 @@ static void dml_rq_dlg_get_dlg_params(struct display_mode_lib *mode_lib,
|
|||
|
||||
double min_dst_y_ttu_vblank = 0;
|
||||
unsigned int dlg_vblank_start = 0;
|
||||
bool dual_plane = 0;
|
||||
bool mode_422 = 0;
|
||||
bool dual_plane = false;
|
||||
bool mode_422 = false;
|
||||
unsigned int access_dir = 0;
|
||||
unsigned int vp_height_l = 0;
|
||||
unsigned int vp_width_l = 0;
|
||||
|
@ -1021,7 +1021,7 @@ static void dml_rq_dlg_get_dlg_params(struct display_mode_lib *mode_lib,
|
|||
double hratio_c = 0;
|
||||
double vratio_l = 0;
|
||||
double vratio_c = 0;
|
||||
bool scl_enable = 0;
|
||||
bool scl_enable = false;
|
||||
|
||||
double line_time_in_us = 0;
|
||||
// double vinit_l;
|
||||
|
@ -1156,7 +1156,7 @@ static void dml_rq_dlg_get_dlg_params(struct display_mode_lib *mode_lib,
|
|||
// Source
|
||||
// dcc_en = src.dcc;
|
||||
dual_plane = is_dual_plane((enum source_format_class)(src->source_format));
|
||||
mode_422 = 0; // TODO
|
||||
mode_422 = false; // TODO
|
||||
access_dir = (src->source_scan == dm_vert); // vp access direction: horizontal or vertical accessed
|
||||
vp_height_l = src->viewport_height;
|
||||
vp_width_l = src->viewport_width;
|
||||
|
|
|
@ -369,6 +369,11 @@ static bool decide_dsc_target_bpp_x16(
|
|||
/* enough bandwidth without dsc */
|
||||
*target_bpp_x16 = 0;
|
||||
should_use_dsc = false;
|
||||
} else if (policy->preferred_bpp_x16 > 0 &&
|
||||
policy->preferred_bpp_x16 <= range.max_target_bpp_x16 &&
|
||||
policy->preferred_bpp_x16 >= range.min_target_bpp_x16) {
|
||||
*target_bpp_x16 = policy->preferred_bpp_x16;
|
||||
should_use_dsc = true;
|
||||
} else if (target_bandwidth_kbps >= range.max_kbps) {
|
||||
/* use max target bpp allowed */
|
||||
*target_bpp_x16 = range.max_target_bpp_x16;
|
||||
|
@ -545,7 +550,7 @@ static bool setup_dsc_config(
|
|||
int target_bandwidth_kbps,
|
||||
const struct dc_crtc_timing *timing,
|
||||
int min_slice_height_override,
|
||||
int max_dsc_target_bpp_limit_override,
|
||||
int max_dsc_target_bpp_limit_override_x16,
|
||||
struct dc_dsc_config *dsc_cfg)
|
||||
{
|
||||
struct dsc_enc_caps dsc_common_caps;
|
||||
|
@ -564,7 +569,7 @@ static bool setup_dsc_config(
|
|||
|
||||
memset(dsc_cfg, 0, sizeof(struct dc_dsc_config));
|
||||
|
||||
dc_dsc_get_policy_for_timing(timing, max_dsc_target_bpp_limit_override, &policy);
|
||||
dc_dsc_get_policy_for_timing(timing, max_dsc_target_bpp_limit_override_x16, &policy);
|
||||
pic_width = timing->h_addressable + timing->h_border_left + timing->h_border_right;
|
||||
pic_height = timing->v_addressable + timing->v_border_top + timing->v_border_bottom;
|
||||
|
||||
|
@ -865,8 +870,8 @@ bool dc_dsc_parse_dsc_dpcd(const struct dc *dc, const uint8_t *dpcd_dsc_basic_da
|
|||
bool dc_dsc_compute_bandwidth_range(
|
||||
const struct display_stream_compressor *dsc,
|
||||
uint32_t dsc_min_slice_height_override,
|
||||
uint32_t min_bpp,
|
||||
uint32_t max_bpp,
|
||||
uint32_t min_bpp_x16,
|
||||
uint32_t max_bpp_x16,
|
||||
const struct dsc_dec_dpcd_caps *dsc_sink_caps,
|
||||
const struct dc_crtc_timing *timing,
|
||||
struct dc_dsc_bw_range *range)
|
||||
|
@ -883,10 +888,10 @@ bool dc_dsc_compute_bandwidth_range(
|
|||
|
||||
if (is_dsc_possible)
|
||||
is_dsc_possible = setup_dsc_config(dsc_sink_caps, &dsc_enc_caps, 0, timing,
|
||||
dsc_min_slice_height_override, max_bpp, &config);
|
||||
dsc_min_slice_height_override, max_bpp_x16, &config);
|
||||
|
||||
if (is_dsc_possible)
|
||||
get_dsc_bandwidth_range(min_bpp, max_bpp, &dsc_common_caps, timing, range);
|
||||
get_dsc_bandwidth_range(min_bpp_x16, max_bpp_x16, &dsc_common_caps, timing, range);
|
||||
|
||||
return is_dsc_possible;
|
||||
}
|
||||
|
@ -895,7 +900,7 @@ bool dc_dsc_compute_config(
|
|||
const struct display_stream_compressor *dsc,
|
||||
const struct dsc_dec_dpcd_caps *dsc_sink_caps,
|
||||
uint32_t dsc_min_slice_height_override,
|
||||
uint32_t max_target_bpp_limit_override,
|
||||
uint32_t max_target_bpp_limit_override_x16,
|
||||
uint32_t target_bandwidth_kbps,
|
||||
const struct dc_crtc_timing *timing,
|
||||
struct dc_dsc_config *dsc_cfg)
|
||||
|
@ -908,11 +913,11 @@ bool dc_dsc_compute_config(
|
|||
&dsc_enc_caps,
|
||||
target_bandwidth_kbps,
|
||||
timing, dsc_min_slice_height_override,
|
||||
max_target_bpp_limit_override, dsc_cfg);
|
||||
max_target_bpp_limit_override_x16, dsc_cfg);
|
||||
return is_dsc_possible;
|
||||
}
|
||||
|
||||
void dc_dsc_get_policy_for_timing(const struct dc_crtc_timing *timing, uint32_t max_target_bpp_limit_override, struct dc_dsc_policy *policy)
|
||||
void dc_dsc_get_policy_for_timing(const struct dc_crtc_timing *timing, uint32_t max_target_bpp_limit_override_x16, struct dc_dsc_policy *policy)
|
||||
{
|
||||
uint32_t bpc = 0;
|
||||
|
||||
|
@ -967,13 +972,15 @@ void dc_dsc_get_policy_for_timing(const struct dc_crtc_timing *timing, uint32_t
|
|||
return;
|
||||
}
|
||||
|
||||
policy->preferred_bpp_x16 = timing->dsc_fixed_bits_per_pixel_x16;
|
||||
|
||||
/* internal upper limit, default 16 bpp */
|
||||
if (policy->max_target_bpp > dsc_policy_max_target_bpp_limit)
|
||||
policy->max_target_bpp = dsc_policy_max_target_bpp_limit;
|
||||
|
||||
/* apply override */
|
||||
if (max_target_bpp_limit_override && policy->max_target_bpp > max_target_bpp_limit_override)
|
||||
policy->max_target_bpp = max_target_bpp_limit_override;
|
||||
if (max_target_bpp_limit_override_x16 && policy->max_target_bpp > max_target_bpp_limit_override_x16 / 16)
|
||||
policy->max_target_bpp = max_target_bpp_limit_override_x16 / 16;
|
||||
|
||||
/* enable DSC when not needed, default false */
|
||||
if (dsc_policy_enable_dsc_when_not_needed)
|
||||
|
|
|
@ -74,6 +74,16 @@ struct dmcu_funcs {
|
|||
bool (*is_dmcu_initialized)(struct dmcu *dmcu);
|
||||
bool (*lock_phy)(struct dmcu *dmcu);
|
||||
bool (*unlock_phy)(struct dmcu *dmcu);
|
||||
bool (*send_edid_cea)(struct dmcu *dmcu,
|
||||
int offset,
|
||||
int total_length,
|
||||
uint8_t *data,
|
||||
int length);
|
||||
bool (*recv_amd_vsdb)(struct dmcu *dmcu,
|
||||
int *version,
|
||||
int *min_frame_rate,
|
||||
int *max_frame_rate);
|
||||
bool (*recv_edid_cea_ack)(struct dmcu *dmcu, int *offset);
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
|
@ -218,7 +218,8 @@ struct hw_sequencer_funcs {
|
|||
/* Idle Optimization Related */
|
||||
bool (*apply_idle_power_optimizations)(struct dc *dc, bool enable);
|
||||
|
||||
bool (*does_plane_fit_in_mall)(struct dc *dc, struct dc_plane_state *plane);
|
||||
bool (*does_plane_fit_in_mall)(struct dc *dc, struct dc_plane_state *plane,
|
||||
struct dc_cursor_attributes *cursor_attr);
|
||||
|
||||
bool (*is_abm_supported)(struct dc *dc,
|
||||
struct dc_state *context, struct dc_stream_state *stream);
|
||||
|
|
|
@ -47,10 +47,10 @@
|
|||
|
||||
/* Firmware versioning. */
|
||||
#ifdef DMUB_EXPOSE_VERSION
|
||||
#define DMUB_FW_VERSION_GIT_HASH 0xf51b86a
|
||||
#define DMUB_FW_VERSION_GIT_HASH 0xca1cd48c9
|
||||
#define DMUB_FW_VERSION_MAJOR 0
|
||||
#define DMUB_FW_VERSION_MINOR 0
|
||||
#define DMUB_FW_VERSION_REVISION 47
|
||||
#define DMUB_FW_VERSION_REVISION 50
|
||||
#define DMUB_FW_VERSION_TEST 0
|
||||
#define DMUB_FW_VERSION_VBIOS 0
|
||||
#define DMUB_FW_VERSION_HOTFIX 0
|
||||
|
@ -458,6 +458,10 @@ struct dmub_rb_cmd_mall {
|
|||
uint16_t cursor_pitch;
|
||||
uint16_t cursor_height;
|
||||
uint8_t cursor_bpp;
|
||||
uint8_t debug_bits;
|
||||
|
||||
uint8_t reserved1;
|
||||
uint8_t reserved2;
|
||||
};
|
||||
|
||||
struct dmub_cmd_digx_encoder_control_data {
|
||||
|
@ -624,6 +628,7 @@ enum dmub_cmd_mall_type {
|
|||
DMUB_CMD__MALL_ACTION_ALLOW = 0,
|
||||
DMUB_CMD__MALL_ACTION_DISALLOW = 1,
|
||||
DMUB_CMD__MALL_ACTION_COPY_CURSOR = 2,
|
||||
DMUB_CMD__MALL_ACTION_NO_DF_REQ = 3,
|
||||
};
|
||||
|
||||
struct dmub_cmd_psr_copy_settings_data {
|
||||
|
@ -648,6 +653,7 @@ struct dmub_cmd_psr_copy_settings_data {
|
|||
uint8_t multi_disp_optimizations_en;
|
||||
uint16_t init_sdp_deadline;
|
||||
uint16_t pad2;
|
||||
uint32_t line_time_in_us;
|
||||
};
|
||||
|
||||
struct dmub_rb_cmd_psr_copy_settings {
|
||||
|
|
|
@ -81,6 +81,13 @@ static inline void dmub_dcn20_translate_addr(const union dmub_addr *addr_in,
|
|||
addr_out->quad_part = addr_in->quad_part - fb_base + fb_offset;
|
||||
}
|
||||
|
||||
bool dmub_dcn20_use_cached_inbox(struct dmub_srv *dmub)
|
||||
{
|
||||
/* Cached inbox is not supported in this fw version range */
|
||||
return !(dmub->fw_version >= DMUB_FW_VERSION(1, 0, 0) &&
|
||||
dmub->fw_version <= DMUB_FW_VERSION(1, 10, 0));
|
||||
}
|
||||
|
||||
void dmub_dcn20_reset(struct dmub_srv *dmub)
|
||||
{
|
||||
union dmub_gpint_data_register cmd;
|
||||
|
@ -216,7 +223,7 @@ void dmub_dcn20_setup_windows(struct dmub_srv *dmub,
|
|||
dmub_dcn20_translate_addr(&cw4->offset, fb_base, fb_offset, &offset);
|
||||
|
||||
/* New firmware can support CW4. */
|
||||
if (dmub->fw_version > DMUB_FW_VERSION(1, 0, 10)) {
|
||||
if (dmub_dcn20_use_cached_inbox(dmub)) {
|
||||
REG_WRITE(DMCUB_REGION3_CW4_OFFSET, offset.u.low_part);
|
||||
REG_WRITE(DMCUB_REGION3_CW4_OFFSET_HIGH, offset.u.high_part);
|
||||
REG_WRITE(DMCUB_REGION3_CW4_BASE_ADDRESS, cw4->region.base);
|
||||
|
@ -255,7 +262,7 @@ void dmub_dcn20_setup_mailbox(struct dmub_srv *dmub,
|
|||
const struct dmub_region *inbox1)
|
||||
{
|
||||
/* New firmware can support CW4 for the inbox. */
|
||||
if (dmub->fw_version > DMUB_FW_VERSION(1, 0, 10))
|
||||
if (dmub_dcn20_use_cached_inbox(dmub))
|
||||
REG_WRITE(DMCUB_INBOX1_BASE_ADDRESS, inbox1->base);
|
||||
else
|
||||
REG_WRITE(DMCUB_INBOX1_BASE_ADDRESS, 0x80000000);
|
||||
|
|
|
@ -198,4 +198,6 @@ void dmub_dcn20_skip_dmub_panel_power_sequence(struct dmub_srv *dmub, bool skip)
|
|||
|
||||
union dmub_fw_boot_status dmub_dcn20_get_fw_boot_status(struct dmub_srv *dmub);
|
||||
|
||||
bool dmub_dcn20_use_cached_inbox(struct dmub_srv *dmub);
|
||||
|
||||
#endif /* _DMUB_DCN20_H_ */
|
||||
|
|
|
@ -155,7 +155,7 @@ void dmub_dcn30_setup_windows(struct dmub_srv *dmub,
|
|||
offset = cw4->offset;
|
||||
|
||||
/* New firmware can support CW4. */
|
||||
if (dmub->fw_version > DMUB_FW_VERSION(1, 0, 10)) {
|
||||
if (dmub_dcn20_use_cached_inbox(dmub)) {
|
||||
REG_WRITE(DMCUB_REGION3_CW4_OFFSET, offset.u.low_part);
|
||||
REG_WRITE(DMCUB_REGION3_CW4_OFFSET_HIGH, offset.u.high_part);
|
||||
REG_WRITE(DMCUB_REGION3_CW4_BASE_ADDRESS, cw4->region.base);
|
||||
|
|
|
@ -406,6 +406,9 @@ enum dmub_status dmub_srv_hw_init(struct dmub_srv *dmub,
|
|||
dmub->fb_offset = params->fb_offset;
|
||||
dmub->psp_version = params->psp_version;
|
||||
|
||||
if (dmub->hw_funcs.reset)
|
||||
dmub->hw_funcs.reset(dmub);
|
||||
|
||||
if (inst_fb && data_fb) {
|
||||
cw0.offset.quad_part = inst_fb->gpu_addr;
|
||||
cw0.region.base = DMUB_CW0_BASE;
|
||||
|
@ -427,9 +430,6 @@ enum dmub_status dmub_srv_hw_init(struct dmub_srv *dmub,
|
|||
|
||||
}
|
||||
|
||||
if (dmub->hw_funcs.reset)
|
||||
dmub->hw_funcs.reset(dmub);
|
||||
|
||||
if (inst_fb && data_fb && bios_fb && mail_fb && tracebuff_fb &&
|
||||
fw_state_fb && scratch_mem_fb) {
|
||||
cw2.offset.quad_part = data_fb->gpu_addr;
|
||||
|
@ -489,9 +489,6 @@ enum dmub_status dmub_srv_hw_reset(struct dmub_srv *dmub)
|
|||
if (!dmub->sw_init)
|
||||
return DMUB_STATUS_INVALID;
|
||||
|
||||
if (dmub->hw_init == false)
|
||||
return DMUB_STATUS_OK;
|
||||
|
||||
if (dmub->hw_funcs.reset)
|
||||
dmub->hw_funcs.reset(dmub);
|
||||
|
||||
|
|
|
@ -1,10 +1,26 @@
|
|||
/*
|
||||
* Copyright (c) 2019 Advanced Micro Devices, Inc. (unpublished)
|
||||
* Copyright 2019 Advanced Micro Devices, Inc.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
|
||||
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
|
||||
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||
* OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
* Authors: AMD
|
||||
*
|
||||
* All rights reserved. This notice is intended as a precaution against
|
||||
* inadvertent publication and does not imply publication or any waiver
|
||||
* of confidentiality. The year included in the foregoing notice is the
|
||||
* year of creation of the work.
|
||||
*/
|
||||
|
||||
#include "color_table.h"
|
||||
|
|
|
@ -397,7 +397,7 @@ static inline uint8_t is_dp_hdcp(struct mod_hdcp *hdcp)
|
|||
static inline uint8_t is_dp_mst_hdcp(struct mod_hdcp *hdcp)
|
||||
{
|
||||
return (hdcp->connection.link.mode == MOD_HDCP_MODE_DP &&
|
||||
hdcp->connection.link.dp.mst_supported);
|
||||
hdcp->connection.link.dp.mst_enabled);
|
||||
}
|
||||
|
||||
static inline uint8_t is_hdmi_dvi_sl_hdcp(struct mod_hdcp *hdcp)
|
||||
|
|
|
@ -106,7 +106,7 @@ enum mod_hdcp_status mod_hdcp_add_display_to_topology(struct mod_hdcp *hdcp,
|
|||
dtm_cmd->dtm_in_message.topology_update_v2.dig_be = link->dig_be;
|
||||
dtm_cmd->dtm_in_message.topology_update_v2.dig_fe = display->dig_fe;
|
||||
if (is_dp_hdcp(hdcp))
|
||||
dtm_cmd->dtm_in_message.topology_update_v2.is_assr = link->dp.assr_supported;
|
||||
dtm_cmd->dtm_in_message.topology_update_v2.is_assr = link->dp.assr_enabled;
|
||||
|
||||
dtm_cmd->dtm_in_message.topology_update_v2.dp_mst_vcid = display->vc_id;
|
||||
dtm_cmd->dtm_in_message.topology_update_v2.max_hdcp_supported_version =
|
||||
|
|
|
@ -101,8 +101,8 @@ enum mod_hdcp_status {
|
|||
|
||||
struct mod_hdcp_displayport {
|
||||
uint8_t rev;
|
||||
uint8_t assr_supported;
|
||||
uint8_t mst_supported;
|
||||
uint8_t assr_enabled;
|
||||
uint8_t mst_enabled;
|
||||
};
|
||||
|
||||
struct mod_hdcp_hdmi {
|
||||
|
|
|
@ -266,7 +266,7 @@ static void fill_backlight_transform_table_v_2_2(struct dmcu_iram_parameters par
|
|||
* format U4.10.
|
||||
*/
|
||||
for (i = 1; i+1 < num_entries; i++) {
|
||||
lut_index = (params.backlight_lut_array_size - 1) * i / (num_entries - 1);
|
||||
lut_index = DIV_ROUNDUP((i * params.backlight_lut_array_size), num_entries);
|
||||
ASSERT(lut_index < params.backlight_lut_array_size);
|
||||
|
||||
table->backlight_thresholds[i] = (big_endian) ?
|
||||
|
|
|
@ -28,6 +28,7 @@
|
|||
#define CAIL_PCIE_LINK_SPEED_SUPPORT_GEN2 0x00020000
|
||||
#define CAIL_PCIE_LINK_SPEED_SUPPORT_GEN3 0x00040000
|
||||
#define CAIL_PCIE_LINK_SPEED_SUPPORT_GEN4 0x00080000
|
||||
#define CAIL_PCIE_LINK_SPEED_SUPPORT_GEN5 0x00100000
|
||||
#define CAIL_PCIE_LINK_SPEED_SUPPORT_MASK 0xFFFF0000
|
||||
#define CAIL_PCIE_LINK_SPEED_SUPPORT_SHIFT 16
|
||||
|
||||
|
@ -36,6 +37,7 @@
|
|||
#define CAIL_ASIC_PCIE_LINK_SPEED_SUPPORT_GEN2 0x00000002
|
||||
#define CAIL_ASIC_PCIE_LINK_SPEED_SUPPORT_GEN3 0x00000004
|
||||
#define CAIL_ASIC_PCIE_LINK_SPEED_SUPPORT_GEN4 0x00000008
|
||||
#define CAIL_ASIC_PCIE_LINK_SPEED_SUPPORT_GEN5 0x00000010
|
||||
#define CAIL_ASIC_PCIE_LINK_SPEED_SUPPORT_MASK 0x0000FFFF
|
||||
#define CAIL_ASIC_PCIE_LINK_SPEED_SUPPORT_SHIFT 0
|
||||
|
||||
|
|
|
@ -824,8 +824,9 @@ static ssize_t amdgpu_set_pp_od_clk_voltage(struct device *dev,
|
|||
tmp_str++;
|
||||
while (isspace(*++tmp_str));
|
||||
|
||||
while (tmp_str[0]) {
|
||||
sub_str = strsep(&tmp_str, delimiter);
|
||||
while ((sub_str = strsep(&tmp_str, delimiter)) != NULL) {
|
||||
if (strlen(sub_str) == 0)
|
||||
continue;
|
||||
ret = kstrtol(sub_str, 0, ¶meter[parameter_size]);
|
||||
if (ret)
|
||||
return -EINVAL;
|
||||
|
@ -1094,7 +1095,7 @@ static ssize_t amdgpu_get_pp_dpm_sclk(struct device *dev,
|
|||
static ssize_t amdgpu_read_mask(const char *buf, size_t count, uint32_t *mask)
|
||||
{
|
||||
int ret;
|
||||
long level;
|
||||
unsigned long level;
|
||||
char *sub_str = NULL;
|
||||
char *tmp;
|
||||
char buf_cpy[AMDGPU_MASK_BUF_MAX + 1];
|
||||
|
@ -1107,11 +1108,10 @@ static ssize_t amdgpu_read_mask(const char *buf, size_t count, uint32_t *mask)
|
|||
memcpy(buf_cpy, buf, bytes);
|
||||
buf_cpy[bytes] = '\0';
|
||||
tmp = buf_cpy;
|
||||
while (tmp[0]) {
|
||||
sub_str = strsep(&tmp, delimiter);
|
||||
while ((sub_str = strsep(&tmp, delimiter)) != NULL) {
|
||||
if (strlen(sub_str)) {
|
||||
ret = kstrtol(sub_str, 0, &level);
|
||||
if (ret)
|
||||
ret = kstrtoul(sub_str, 0, &level);
|
||||
if (ret || level > 31)
|
||||
return -EINVAL;
|
||||
*mask |= 1 << level;
|
||||
} else
|
||||
|
@ -1869,8 +1869,9 @@ static ssize_t amdgpu_set_pp_power_profile_mode(struct device *dev,
|
|||
i++;
|
||||
memcpy(buf_cpy, buf, count-i);
|
||||
tmp_str = buf_cpy;
|
||||
while (tmp_str[0]) {
|
||||
sub_str = strsep(&tmp_str, delimiter);
|
||||
while ((sub_str = strsep(&tmp_str, delimiter)) != NULL) {
|
||||
if (strlen(sub_str) == 0)
|
||||
continue;
|
||||
ret = kstrtol(sub_str, 0, ¶meter[parameter_size]);
|
||||
if (ret)
|
||||
return -EINVAL;
|
||||
|
|
|
@ -33,6 +33,8 @@
|
|||
#define SMU_TEMPERATURE_UNITS_PER_CENTIGRADES 1000
|
||||
#define SMU_FW_NAME_LEN 0x24
|
||||
|
||||
#define SMU_DPM_USER_PROFILE_RESTORE (1 << 0)
|
||||
|
||||
struct smu_hw_power_state {
|
||||
unsigned int magic;
|
||||
};
|
||||
|
@ -168,6 +170,17 @@ enum smu_memory_pool_size
|
|||
SMU_MEMORY_POOL_SIZE_2_GB = 0x80000000,
|
||||
};
|
||||
|
||||
struct smu_user_dpm_profile {
|
||||
uint32_t fan_mode;
|
||||
uint32_t power_limit;
|
||||
uint32_t fan_speed_percent;
|
||||
uint32_t flags;
|
||||
|
||||
/* user clock state information */
|
||||
uint32_t clk_mask[SMU_CLK_COUNT];
|
||||
uint32_t clk_dependency;
|
||||
};
|
||||
|
||||
#define SMU_TABLE_INIT(tables, table_id, s, a, d) \
|
||||
do { \
|
||||
tables[table_id].size = s; \
|
||||
|
@ -459,7 +472,7 @@ struct smu_context
|
|||
struct work_struct interrupt_work;
|
||||
|
||||
unsigned fan_max_rpm;
|
||||
unsigned manual_fan_speed_rpm;
|
||||
unsigned manual_fan_speed_percent;
|
||||
|
||||
uint32_t gfx_default_hard_min_freq;
|
||||
uint32_t gfx_default_soft_max_freq;
|
||||
|
@ -473,6 +486,8 @@ struct smu_context
|
|||
uint32_t cpu_actual_soft_max_freq;
|
||||
uint32_t cpu_core_id_select;
|
||||
uint16_t cpu_core_num;
|
||||
|
||||
struct smu_user_dpm_profile user_dpm_profile;
|
||||
};
|
||||
|
||||
struct i2c_adapter;
|
||||
|
@ -633,9 +648,9 @@ struct pptable_funcs {
|
|||
bool (*is_dpm_running)(struct smu_context *smu);
|
||||
|
||||
/**
|
||||
* @get_fan_speed_rpm: Get the current fan speed in RPM.
|
||||
* @get_fan_speed_percent: Get the current fan speed in percent.
|
||||
*/
|
||||
int (*get_fan_speed_rpm)(struct smu_context *smu, uint32_t *speed);
|
||||
int (*get_fan_speed_percent)(struct smu_context *smu, uint32_t *speed);
|
||||
|
||||
/**
|
||||
* @set_watermarks_table: Configure and upload the watermarks tables to
|
||||
|
@ -936,9 +951,9 @@ struct pptable_funcs {
|
|||
int (*set_fan_control_mode)(struct smu_context *smu, uint32_t mode);
|
||||
|
||||
/**
|
||||
* @set_fan_speed_rpm: Set a static fan speed in RPM.
|
||||
* @set_fan_speed_percent: Set a static fan speed in percent.
|
||||
*/
|
||||
int (*set_fan_speed_rpm)(struct smu_context *smu, uint32_t speed);
|
||||
int (*set_fan_speed_percent)(struct smu_context *smu, uint32_t speed);
|
||||
|
||||
/**
|
||||
* @set_xgmi_pstate: Set inter-chip global memory interconnect pstate.
|
||||
|
|
|
@ -133,8 +133,6 @@
|
|||
__SMU_DUMMY_MAP(PowerUpSdma), \
|
||||
__SMU_DUMMY_MAP(SetHardMinIspclkByFreq), \
|
||||
__SMU_DUMMY_MAP(SetHardMinVcn), \
|
||||
__SMU_DUMMY_MAP(Spare1), \
|
||||
__SMU_DUMMY_MAP(Spare2), \
|
||||
__SMU_DUMMY_MAP(SetAllowFclkSwitch), \
|
||||
__SMU_DUMMY_MAP(SetMinVideoGfxclkFreq), \
|
||||
__SMU_DUMMY_MAP(ActiveProcessNotify), \
|
||||
|
|
|
@ -203,11 +203,8 @@ int
|
|||
smu_v11_0_set_fan_control_mode(struct smu_context *smu,
|
||||
uint32_t mode);
|
||||
|
||||
int smu_v11_0_set_fan_speed_rpm(struct smu_context *smu,
|
||||
uint32_t speed);
|
||||
|
||||
int smu_v11_0_get_fan_speed_rpm(struct smu_context *smu,
|
||||
uint32_t *speed);
|
||||
int smu_v11_0_set_fan_speed_percent(struct smu_context *smu,
|
||||
uint32_t speed);
|
||||
|
||||
int smu_v11_0_set_xgmi_pstate(struct smu_context *smu,
|
||||
uint32_t pstate);
|
||||
|
|
|
@ -266,6 +266,119 @@ int smu_dpm_set_power_gate(struct smu_context *smu, uint32_t block_type,
|
|||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* smu_set_user_clk_dependencies - set user profile clock dependencies
|
||||
*
|
||||
* @smu: smu_context pointer
|
||||
* @clk: enum smu_clk_type type
|
||||
*
|
||||
* Enable/Disable the clock dependency for the @clk type.
|
||||
*/
|
||||
static void smu_set_user_clk_dependencies(struct smu_context *smu, enum smu_clk_type clk)
|
||||
{
|
||||
if (smu->adev->in_suspend)
|
||||
return;
|
||||
|
||||
/*
|
||||
* mclk, fclk and socclk are interdependent
|
||||
* on each other
|
||||
*/
|
||||
if (clk == SMU_MCLK) {
|
||||
/* reset clock dependency */
|
||||
smu->user_dpm_profile.clk_dependency = 0;
|
||||
/* set mclk dependent clocks(fclk and socclk) */
|
||||
smu->user_dpm_profile.clk_dependency = BIT(SMU_FCLK) | BIT(SMU_SOCCLK);
|
||||
} else if (clk == SMU_FCLK) {
|
||||
/* give priority to mclk, if mclk dependent clocks are set */
|
||||
if (smu->user_dpm_profile.clk_dependency == (BIT(SMU_FCLK) | BIT(SMU_SOCCLK)))
|
||||
return;
|
||||
|
||||
/* reset clock dependency */
|
||||
smu->user_dpm_profile.clk_dependency = 0;
|
||||
/* set fclk dependent clocks(mclk and socclk) */
|
||||
smu->user_dpm_profile.clk_dependency = BIT(SMU_MCLK) | BIT(SMU_SOCCLK);
|
||||
} else if (clk == SMU_SOCCLK) {
|
||||
/* give priority to mclk, if mclk dependent clocks are set */
|
||||
if (smu->user_dpm_profile.clk_dependency == (BIT(SMU_FCLK) | BIT(SMU_SOCCLK)))
|
||||
return;
|
||||
|
||||
/* reset clock dependency */
|
||||
smu->user_dpm_profile.clk_dependency = 0;
|
||||
/* set socclk dependent clocks(mclk and fclk) */
|
||||
smu->user_dpm_profile.clk_dependency = BIT(SMU_MCLK) | BIT(SMU_FCLK);
|
||||
} else
|
||||
/* add clk dependencies here, if any */
|
||||
return;
|
||||
}
|
||||
|
||||
/**
|
||||
* smu_restore_dpm_user_profile - reinstate user dpm profile
|
||||
*
|
||||
* @smu: smu_context pointer
|
||||
*
|
||||
* Restore the saved user power configurations include power limit,
|
||||
* clock frequencies, fan control mode and fan speed.
|
||||
*/
|
||||
static void smu_restore_dpm_user_profile(struct smu_context *smu)
|
||||
{
|
||||
struct smu_dpm_context *smu_dpm_ctx = &(smu->smu_dpm);
|
||||
int ret = 0;
|
||||
|
||||
if (!smu->adev->in_suspend)
|
||||
return;
|
||||
|
||||
if (!smu->pm_enabled || !smu->adev->pm.dpm_enabled)
|
||||
return;
|
||||
|
||||
/* Enable restore flag */
|
||||
smu->user_dpm_profile.flags = SMU_DPM_USER_PROFILE_RESTORE;
|
||||
|
||||
/* set the user dpm power limit */
|
||||
if (smu->user_dpm_profile.power_limit) {
|
||||
ret = smu_set_power_limit(smu, smu->user_dpm_profile.power_limit);
|
||||
if (ret)
|
||||
dev_err(smu->adev->dev, "Failed to set power limit value\n");
|
||||
}
|
||||
|
||||
/* set the user dpm clock configurations */
|
||||
if (smu_dpm_ctx->dpm_level == AMD_DPM_FORCED_LEVEL_MANUAL) {
|
||||
enum smu_clk_type clk_type;
|
||||
|
||||
for (clk_type = 0; clk_type < SMU_CLK_COUNT; clk_type++) {
|
||||
/*
|
||||
* Iterate over smu clk type and force the saved user clk
|
||||
* configs, skip if clock dependency is enabled
|
||||
*/
|
||||
if (!(smu->user_dpm_profile.clk_dependency & BIT(clk_type)) &&
|
||||
smu->user_dpm_profile.clk_mask[clk_type]) {
|
||||
ret = smu_force_clk_levels(smu, clk_type,
|
||||
smu->user_dpm_profile.clk_mask[clk_type]);
|
||||
if (ret)
|
||||
dev_err(smu->adev->dev, "Failed to set clock type = %d\n",
|
||||
clk_type);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* set the user dpm fan configurations */
|
||||
if (smu->user_dpm_profile.fan_mode == AMD_FAN_CTRL_MANUAL) {
|
||||
ret = smu_set_fan_control_mode(smu, smu->user_dpm_profile.fan_mode);
|
||||
if (ret) {
|
||||
dev_err(smu->adev->dev, "Failed to set manual fan control mode\n");
|
||||
return;
|
||||
}
|
||||
|
||||
if (!ret && smu->user_dpm_profile.fan_speed_percent) {
|
||||
ret = smu_set_fan_speed_percent(smu, smu->user_dpm_profile.fan_speed_percent);
|
||||
if (ret)
|
||||
dev_err(smu->adev->dev, "Failed to set manual fan speed\n");
|
||||
}
|
||||
}
|
||||
|
||||
/* Disable restore flag */
|
||||
smu->user_dpm_profile.flags &= ~SMU_DPM_USER_PROFILE_RESTORE;
|
||||
}
|
||||
|
||||
int smu_get_power_num_states(struct smu_context *smu,
|
||||
struct pp_states_info *state_info)
|
||||
{
|
||||
|
@ -499,9 +612,6 @@ static int smu_late_init(void *handle)
|
|||
return ret;
|
||||
}
|
||||
|
||||
if (adev->asic_type == CHIP_VANGOGH)
|
||||
return 0;
|
||||
|
||||
ret = smu_set_default_od_settings(smu);
|
||||
if (ret) {
|
||||
dev_err(adev->dev, "Failed to setup default OD settings!\n");
|
||||
|
@ -529,6 +639,8 @@ static int smu_late_init(void *handle)
|
|||
AMD_PP_TASK_COMPLETE_INIT,
|
||||
false);
|
||||
|
||||
smu_restore_dpm_user_profile(smu);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -1622,6 +1734,12 @@ int smu_force_performance_level(struct smu_context *smu, enum amd_dpm_forced_lev
|
|||
|
||||
mutex_unlock(&smu->mutex);
|
||||
|
||||
/* reset user dpm clock state */
|
||||
if (!ret && smu_dpm_ctx->dpm_level != AMD_DPM_FORCED_LEVEL_MANUAL) {
|
||||
memset(smu->user_dpm_profile.clk_mask, 0, sizeof(smu->user_dpm_profile.clk_mask));
|
||||
smu->user_dpm_profile.clk_dependency = 0;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -1656,8 +1774,13 @@ int smu_force_clk_levels(struct smu_context *smu,
|
|||
|
||||
mutex_lock(&smu->mutex);
|
||||
|
||||
if (smu->ppt_funcs && smu->ppt_funcs->force_clk_levels)
|
||||
if (smu->ppt_funcs && smu->ppt_funcs->force_clk_levels) {
|
||||
ret = smu->ppt_funcs->force_clk_levels(smu, clk_type, mask);
|
||||
if (!ret && smu->user_dpm_profile.flags != SMU_DPM_USER_PROFILE_RESTORE) {
|
||||
smu->user_dpm_profile.clk_mask[clk_type] = mask;
|
||||
smu_set_user_clk_dependencies(smu, clk_type);
|
||||
}
|
||||
}
|
||||
|
||||
mutex_unlock(&smu->mutex);
|
||||
|
||||
|
@ -1899,6 +2022,7 @@ int smu_set_gfx_cgpg(struct smu_context *smu, bool enabled)
|
|||
|
||||
int smu_set_fan_speed_rpm(struct smu_context *smu, uint32_t speed)
|
||||
{
|
||||
u32 percent;
|
||||
int ret = 0;
|
||||
|
||||
if (!smu->pm_enabled || !smu->adev->pm.dpm_enabled)
|
||||
|
@ -1906,8 +2030,12 @@ int smu_set_fan_speed_rpm(struct smu_context *smu, uint32_t speed)
|
|||
|
||||
mutex_lock(&smu->mutex);
|
||||
|
||||
if (smu->ppt_funcs->set_fan_speed_rpm)
|
||||
ret = smu->ppt_funcs->set_fan_speed_rpm(smu, speed);
|
||||
if (smu->ppt_funcs->set_fan_speed_percent) {
|
||||
percent = speed * 100 / smu->fan_max_rpm;
|
||||
ret = smu->ppt_funcs->set_fan_speed_percent(smu, percent);
|
||||
if (!ret && smu->user_dpm_profile.flags != SMU_DPM_USER_PROFILE_RESTORE)
|
||||
smu->user_dpm_profile.fan_speed_percent = percent;
|
||||
}
|
||||
|
||||
mutex_unlock(&smu->mutex);
|
||||
|
||||
|
@ -1949,8 +2077,11 @@ int smu_set_power_limit(struct smu_context *smu, uint32_t limit)
|
|||
if (!limit)
|
||||
limit = smu->current_power_limit;
|
||||
|
||||
if (smu->ppt_funcs->set_power_limit)
|
||||
if (smu->ppt_funcs->set_power_limit) {
|
||||
ret = smu->ppt_funcs->set_power_limit(smu, limit);
|
||||
if (!ret && smu->user_dpm_profile.flags != SMU_DPM_USER_PROFILE_RESTORE)
|
||||
smu->user_dpm_profile.power_limit = limit;
|
||||
}
|
||||
|
||||
out:
|
||||
mutex_unlock(&smu->mutex);
|
||||
|
@ -2127,11 +2258,19 @@ int smu_set_fan_control_mode(struct smu_context *smu, int value)
|
|||
|
||||
mutex_lock(&smu->mutex);
|
||||
|
||||
if (smu->ppt_funcs->set_fan_control_mode)
|
||||
if (smu->ppt_funcs->set_fan_control_mode) {
|
||||
ret = smu->ppt_funcs->set_fan_control_mode(smu, value);
|
||||
if (!ret && smu->user_dpm_profile.flags != SMU_DPM_USER_PROFILE_RESTORE)
|
||||
smu->user_dpm_profile.fan_mode = value;
|
||||
}
|
||||
|
||||
mutex_unlock(&smu->mutex);
|
||||
|
||||
/* reset user dpm fan speed */
|
||||
if (!ret && value != AMD_FAN_CTRL_MANUAL &&
|
||||
smu->user_dpm_profile.flags != SMU_DPM_USER_PROFILE_RESTORE)
|
||||
smu->user_dpm_profile.fan_speed_percent = 0;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -2139,17 +2278,15 @@ int smu_get_fan_speed_percent(struct smu_context *smu, uint32_t *speed)
|
|||
{
|
||||
int ret = 0;
|
||||
uint32_t percent;
|
||||
uint32_t current_rpm;
|
||||
|
||||
if (!smu->pm_enabled || !smu->adev->pm.dpm_enabled)
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
mutex_lock(&smu->mutex);
|
||||
|
||||
if (smu->ppt_funcs->get_fan_speed_rpm) {
|
||||
ret = smu->ppt_funcs->get_fan_speed_rpm(smu, ¤t_rpm);
|
||||
if (smu->ppt_funcs->get_fan_speed_percent) {
|
||||
ret = smu->ppt_funcs->get_fan_speed_percent(smu, &percent);
|
||||
if (!ret) {
|
||||
percent = current_rpm * 100 / smu->fan_max_rpm;
|
||||
*speed = percent > 100 ? 100 : percent;
|
||||
}
|
||||
}
|
||||
|
@ -2163,18 +2300,18 @@ int smu_get_fan_speed_percent(struct smu_context *smu, uint32_t *speed)
|
|||
int smu_set_fan_speed_percent(struct smu_context *smu, uint32_t speed)
|
||||
{
|
||||
int ret = 0;
|
||||
uint32_t rpm;
|
||||
|
||||
if (!smu->pm_enabled || !smu->adev->pm.dpm_enabled)
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
mutex_lock(&smu->mutex);
|
||||
|
||||
if (smu->ppt_funcs->set_fan_speed_rpm) {
|
||||
if (smu->ppt_funcs->set_fan_speed_percent) {
|
||||
if (speed > 100)
|
||||
speed = 100;
|
||||
rpm = speed * smu->fan_max_rpm / 100;
|
||||
ret = smu->ppt_funcs->set_fan_speed_rpm(smu, rpm);
|
||||
ret = smu->ppt_funcs->set_fan_speed_percent(smu, speed);
|
||||
if (!ret && smu->user_dpm_profile.flags != SMU_DPM_USER_PROFILE_RESTORE)
|
||||
smu->user_dpm_profile.fan_speed_percent = speed;
|
||||
}
|
||||
|
||||
mutex_unlock(&smu->mutex);
|
||||
|
@ -2185,14 +2322,17 @@ int smu_set_fan_speed_percent(struct smu_context *smu, uint32_t speed)
|
|||
int smu_get_fan_speed_rpm(struct smu_context *smu, uint32_t *speed)
|
||||
{
|
||||
int ret = 0;
|
||||
u32 percent;
|
||||
|
||||
if (!smu->pm_enabled || !smu->adev->pm.dpm_enabled)
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
mutex_lock(&smu->mutex);
|
||||
|
||||
if (smu->ppt_funcs->get_fan_speed_rpm)
|
||||
ret = smu->ppt_funcs->get_fan_speed_rpm(smu, speed);
|
||||
if (smu->ppt_funcs->get_fan_speed_percent) {
|
||||
ret = smu->ppt_funcs->get_fan_speed_percent(smu, &percent);
|
||||
*speed = percent * smu->fan_max_rpm / 100;
|
||||
}
|
||||
|
||||
mutex_unlock(&smu->mutex);
|
||||
|
||||
|
|
|
@ -1080,15 +1080,27 @@ static int arcturus_read_sensor(struct smu_context *smu,
|
|||
return ret;
|
||||
}
|
||||
|
||||
static int arcturus_get_fan_speed_rpm(struct smu_context *smu,
|
||||
uint32_t *speed)
|
||||
static int arcturus_get_fan_speed_percent(struct smu_context *smu,
|
||||
uint32_t *speed)
|
||||
{
|
||||
int ret;
|
||||
u32 rpm;
|
||||
|
||||
if (!speed)
|
||||
return -EINVAL;
|
||||
|
||||
return arcturus_get_smu_metrics_data(smu,
|
||||
METRICS_CURR_FANSPEED,
|
||||
speed);
|
||||
switch (smu_v11_0_get_fan_control_mode(smu)) {
|
||||
case AMD_FAN_CTRL_AUTO:
|
||||
ret = arcturus_get_smu_metrics_data(smu,
|
||||
METRICS_CURR_FANSPEED,
|
||||
&rpm);
|
||||
if (!ret && smu->fan_max_rpm)
|
||||
*speed = rpm * 100 / smu->fan_max_rpm;
|
||||
return ret;
|
||||
default:
|
||||
*speed = smu->user_dpm_profile.fan_speed_percent;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
static int arcturus_get_fan_parameters(struct smu_context *smu)
|
||||
|
@ -2281,7 +2293,7 @@ static const struct pptable_funcs arcturus_ppt_funcs = {
|
|||
.print_clk_levels = arcturus_print_clk_levels,
|
||||
.force_clk_levels = arcturus_force_clk_levels,
|
||||
.read_sensor = arcturus_read_sensor,
|
||||
.get_fan_speed_rpm = arcturus_get_fan_speed_rpm,
|
||||
.get_fan_speed_percent = arcturus_get_fan_speed_percent,
|
||||
.get_power_profile_mode = arcturus_get_power_profile_mode,
|
||||
.set_power_profile_mode = arcturus_set_power_profile_mode,
|
||||
.set_performance_level = arcturus_set_performance_level,
|
||||
|
@ -2326,7 +2338,7 @@ static const struct pptable_funcs arcturus_ppt_funcs = {
|
|||
.display_clock_voltage_request = smu_v11_0_display_clock_voltage_request,
|
||||
.get_fan_control_mode = smu_v11_0_get_fan_control_mode,
|
||||
.set_fan_control_mode = smu_v11_0_set_fan_control_mode,
|
||||
.set_fan_speed_rpm = smu_v11_0_set_fan_speed_rpm,
|
||||
.set_fan_speed_percent = smu_v11_0_set_fan_speed_percent,
|
||||
.set_xgmi_pstate = smu_v11_0_set_xgmi_pstate,
|
||||
.gfx_off_control = smu_v11_0_gfx_off_control,
|
||||
.register_irq_handler = smu_v11_0_register_irq_handler,
|
||||
|
|
|
@ -1317,15 +1317,27 @@ static bool navi10_is_dpm_running(struct smu_context *smu)
|
|||
return !!(feature_enabled & SMC_DPM_FEATURE);
|
||||
}
|
||||
|
||||
static int navi10_get_fan_speed_rpm(struct smu_context *smu,
|
||||
uint32_t *speed)
|
||||
static int navi10_get_fan_speed_percent(struct smu_context *smu,
|
||||
uint32_t *speed)
|
||||
{
|
||||
int ret;
|
||||
u32 rpm;
|
||||
|
||||
if (!speed)
|
||||
return -EINVAL;
|
||||
|
||||
return navi10_get_smu_metrics_data(smu,
|
||||
METRICS_CURR_FANSPEED,
|
||||
speed);
|
||||
switch (smu_v11_0_get_fan_control_mode(smu)) {
|
||||
case AMD_FAN_CTRL_AUTO:
|
||||
ret = navi10_get_smu_metrics_data(smu,
|
||||
METRICS_CURR_FANSPEED,
|
||||
&rpm);
|
||||
if (!ret && smu->fan_max_rpm)
|
||||
*speed = rpm * 100 / smu->fan_max_rpm;
|
||||
return ret;
|
||||
default:
|
||||
*speed = smu->user_dpm_profile.fan_speed_percent;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
static int navi10_get_fan_parameters(struct smu_context *smu)
|
||||
|
@ -2413,7 +2425,7 @@ static const struct pptable_funcs navi10_ppt_funcs = {
|
|||
.display_config_changed = navi10_display_config_changed,
|
||||
.notify_smc_display_config = navi10_notify_smc_display_config,
|
||||
.is_dpm_running = navi10_is_dpm_running,
|
||||
.get_fan_speed_rpm = navi10_get_fan_speed_rpm,
|
||||
.get_fan_speed_percent = navi10_get_fan_speed_percent,
|
||||
.get_power_profile_mode = navi10_get_power_profile_mode,
|
||||
.set_power_profile_mode = navi10_set_power_profile_mode,
|
||||
.set_watermarks_table = navi10_set_watermarks_table,
|
||||
|
@ -2456,7 +2468,7 @@ static const struct pptable_funcs navi10_ppt_funcs = {
|
|||
.display_clock_voltage_request = smu_v11_0_display_clock_voltage_request,
|
||||
.get_fan_control_mode = smu_v11_0_get_fan_control_mode,
|
||||
.set_fan_control_mode = smu_v11_0_set_fan_control_mode,
|
||||
.set_fan_speed_rpm = smu_v11_0_set_fan_speed_rpm,
|
||||
.set_fan_speed_percent = smu_v11_0_set_fan_speed_percent,
|
||||
.set_xgmi_pstate = smu_v11_0_set_xgmi_pstate,
|
||||
.gfx_off_control = smu_v11_0_gfx_off_control,
|
||||
.register_irq_handler = smu_v11_0_register_irq_handler,
|
||||
|
|
|
@ -1237,15 +1237,27 @@ static bool sienna_cichlid_is_dpm_running(struct smu_context *smu)
|
|||
return !!(feature_enabled & SMC_DPM_FEATURE);
|
||||
}
|
||||
|
||||
static int sienna_cichlid_get_fan_speed_rpm(struct smu_context *smu,
|
||||
uint32_t *speed)
|
||||
static int sienna_cichlid_get_fan_speed_percent(struct smu_context *smu,
|
||||
uint32_t *speed)
|
||||
{
|
||||
int ret;
|
||||
u32 rpm;
|
||||
|
||||
if (!speed)
|
||||
return -EINVAL;
|
||||
|
||||
return sienna_cichlid_get_smu_metrics_data(smu,
|
||||
METRICS_CURR_FANSPEED,
|
||||
speed);
|
||||
switch (smu_v11_0_get_fan_control_mode(smu)) {
|
||||
case AMD_FAN_CTRL_AUTO:
|
||||
ret = sienna_cichlid_get_smu_metrics_data(smu,
|
||||
METRICS_CURR_FANSPEED,
|
||||
&rpm);
|
||||
if (!ret && smu->fan_max_rpm)
|
||||
*speed = rpm * 100 / smu->fan_max_rpm;
|
||||
return ret;
|
||||
default:
|
||||
*speed = smu->user_dpm_profile.fan_speed_percent;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
static int sienna_cichlid_get_fan_parameters(struct smu_context *smu)
|
||||
|
@ -3087,7 +3099,7 @@ static const struct pptable_funcs sienna_cichlid_ppt_funcs = {
|
|||
.display_config_changed = sienna_cichlid_display_config_changed,
|
||||
.notify_smc_display_config = sienna_cichlid_notify_smc_display_config,
|
||||
.is_dpm_running = sienna_cichlid_is_dpm_running,
|
||||
.get_fan_speed_rpm = sienna_cichlid_get_fan_speed_rpm,
|
||||
.get_fan_speed_percent = sienna_cichlid_get_fan_speed_percent,
|
||||
.get_power_profile_mode = sienna_cichlid_get_power_profile_mode,
|
||||
.set_power_profile_mode = sienna_cichlid_set_power_profile_mode,
|
||||
.set_watermarks_table = sienna_cichlid_set_watermarks_table,
|
||||
|
@ -3130,7 +3142,7 @@ static const struct pptable_funcs sienna_cichlid_ppt_funcs = {
|
|||
.display_clock_voltage_request = smu_v11_0_display_clock_voltage_request,
|
||||
.get_fan_control_mode = smu_v11_0_get_fan_control_mode,
|
||||
.set_fan_control_mode = smu_v11_0_set_fan_control_mode,
|
||||
.set_fan_speed_rpm = smu_v11_0_set_fan_speed_rpm,
|
||||
.set_fan_speed_percent = smu_v11_0_set_fan_speed_percent,
|
||||
.set_xgmi_pstate = smu_v11_0_set_xgmi_pstate,
|
||||
.gfx_off_control = smu_v11_0_gfx_off_control,
|
||||
.register_irq_handler = smu_v11_0_register_irq_handler,
|
||||
|
|
|
@ -1137,10 +1137,10 @@ int smu_v11_0_gfx_off_control(struct smu_context *smu, bool enable)
|
|||
uint32_t
|
||||
smu_v11_0_get_fan_control_mode(struct smu_context *smu)
|
||||
{
|
||||
if (!smu_cmn_feature_is_enabled(smu, SMU_FEATURE_FAN_CONTROL_BIT))
|
||||
return AMD_FAN_CTRL_MANUAL;
|
||||
else
|
||||
if (smu_cmn_feature_is_enabled(smu, SMU_FEATURE_FAN_CONTROL_BIT))
|
||||
return AMD_FAN_CTRL_AUTO;
|
||||
else
|
||||
return smu->user_dpm_profile.fan_mode;
|
||||
}
|
||||
|
||||
static int
|
||||
|
@ -1174,6 +1174,35 @@ smu_v11_0_set_fan_static_mode(struct smu_context *smu, uint32_t mode)
|
|||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
smu_v11_0_set_fan_speed_percent(struct smu_context *smu, uint32_t speed)
|
||||
{
|
||||
struct amdgpu_device *adev = smu->adev;
|
||||
uint32_t duty100, duty;
|
||||
uint64_t tmp64;
|
||||
|
||||
if (speed > 100)
|
||||
speed = 100;
|
||||
|
||||
if (smu_v11_0_auto_fan_control(smu, 0))
|
||||
return -EINVAL;
|
||||
|
||||
duty100 = REG_GET_FIELD(RREG32_SOC15(THM, 0, mmCG_FDO_CTRL1),
|
||||
CG_FDO_CTRL1, FMAX_DUTY100);
|
||||
if (!duty100)
|
||||
return -EINVAL;
|
||||
|
||||
tmp64 = (uint64_t)speed * duty100;
|
||||
do_div(tmp64, 100);
|
||||
duty = (uint32_t)tmp64;
|
||||
|
||||
WREG32_SOC15(THM, 0, mmCG_FDO_CTRL0,
|
||||
REG_SET_FIELD(RREG32_SOC15(THM, 0, mmCG_FDO_CTRL0),
|
||||
CG_FDO_CTRL0, FDO_STATIC_DUTY, duty));
|
||||
|
||||
return smu_v11_0_set_fan_static_mode(smu, FDO_PWM_MODE_STATIC);
|
||||
}
|
||||
|
||||
int
|
||||
smu_v11_0_set_fan_control_mode(struct smu_context *smu,
|
||||
uint32_t mode)
|
||||
|
@ -1182,7 +1211,7 @@ smu_v11_0_set_fan_control_mode(struct smu_context *smu,
|
|||
|
||||
switch (mode) {
|
||||
case AMD_FAN_CTRL_NONE:
|
||||
ret = smu_v11_0_set_fan_speed_rpm(smu, smu->fan_max_rpm);
|
||||
ret = smu_v11_0_set_fan_speed_percent(smu, 100);
|
||||
break;
|
||||
case AMD_FAN_CTRL_MANUAL:
|
||||
ret = smu_v11_0_auto_fan_control(smu, 0);
|
||||
|
@ -1202,58 +1231,6 @@ smu_v11_0_set_fan_control_mode(struct smu_context *smu,
|
|||
return ret;
|
||||
}
|
||||
|
||||
int smu_v11_0_set_fan_speed_rpm(struct smu_context *smu,
|
||||
uint32_t speed)
|
||||
{
|
||||
struct amdgpu_device *adev = smu->adev;
|
||||
int ret;
|
||||
uint32_t tach_period, crystal_clock_freq;
|
||||
|
||||
if (!speed)
|
||||
return -EINVAL;
|
||||
|
||||
ret = smu_v11_0_auto_fan_control(smu, 0);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
/*
|
||||
* crystal_clock_freq div by 4 is required since the fan control
|
||||
* module refers to 25MHz
|
||||
*/
|
||||
|
||||
crystal_clock_freq = amdgpu_asic_get_xclk(adev) / 4;
|
||||
tach_period = 60 * crystal_clock_freq * 10000 / (8 * speed);
|
||||
WREG32_SOC15(THM, 0, mmCG_TACH_CTRL,
|
||||
REG_SET_FIELD(RREG32_SOC15(THM, 0, mmCG_TACH_CTRL),
|
||||
CG_TACH_CTRL, TARGET_PERIOD,
|
||||
tach_period));
|
||||
|
||||
ret = smu_v11_0_set_fan_static_mode(smu, FDO_PWM_MODE_STATIC_RPM);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int smu_v11_0_get_fan_speed_rpm(struct smu_context *smu,
|
||||
uint32_t *speed)
|
||||
{
|
||||
struct amdgpu_device *adev = smu->adev;
|
||||
uint32_t tach_period, crystal_clock_freq;
|
||||
uint64_t tmp64;
|
||||
|
||||
tach_period = REG_GET_FIELD(RREG32_SOC15(THM, 0, mmCG_TACH_CTRL),
|
||||
CG_TACH_CTRL, TARGET_PERIOD);
|
||||
if (!tach_period)
|
||||
return -EINVAL;
|
||||
|
||||
crystal_clock_freq = amdgpu_asic_get_xclk(adev);
|
||||
|
||||
tmp64 = (uint64_t)crystal_clock_freq * 60 * 10000;
|
||||
do_div(tmp64, (tach_period * 8));
|
||||
*speed = (uint32_t)tmp64;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int smu_v11_0_set_xgmi_pstate(struct smu_context *smu,
|
||||
uint32_t pstate)
|
||||
{
|
||||
|
|
|
@ -81,7 +81,6 @@ static struct cmn2asic_msg_mapping vangogh_message_map[SMU_MSG_MAX_COUNT] = {
|
|||
MSG_MAP(TransferTableDram2Smu, PPSMC_MSG_TransferTableDram2Smu, 0),
|
||||
MSG_MAP(GfxDeviceDriverReset, PPSMC_MSG_GfxDeviceDriverReset, 0),
|
||||
MSG_MAP(GetEnabledSmuFeatures, PPSMC_MSG_GetEnabledSmuFeatures, 0),
|
||||
MSG_MAP(Spare1, PPSMC_MSG_spare1, 0),
|
||||
MSG_MAP(SetHardMinSocclkByFreq, PPSMC_MSG_SetHardMinSocclkByFreq, 0),
|
||||
MSG_MAP(SetSoftMinFclk, PPSMC_MSG_SetSoftMinFclk, 0),
|
||||
MSG_MAP(SetSoftMinVcn, PPSMC_MSG_SetSoftMinVcn, 0),
|
||||
|
@ -93,7 +92,6 @@ static struct cmn2asic_msg_mapping vangogh_message_map[SMU_MSG_MAX_COUNT] = {
|
|||
MSG_MAP(SetSoftMaxSocclkByFreq, PPSMC_MSG_SetSoftMaxSocclkByFreq, 0),
|
||||
MSG_MAP(SetSoftMaxFclkByFreq, PPSMC_MSG_SetSoftMaxFclkByFreq, 0),
|
||||
MSG_MAP(SetSoftMaxVcn, PPSMC_MSG_SetSoftMaxVcn, 0),
|
||||
MSG_MAP(Spare2, PPSMC_MSG_spare2, 0),
|
||||
MSG_MAP(SetPowerLimitPercentage, PPSMC_MSG_SetPowerLimitPercentage, 0),
|
||||
MSG_MAP(PowerDownJpeg, PPSMC_MSG_PowerDownJpeg, 0),
|
||||
MSG_MAP(PowerUpJpeg, PPSMC_MSG_PowerUpJpeg, 0),
|
||||
|
@ -1424,14 +1422,17 @@ static ssize_t vangogh_get_gpu_metrics(struct smu_context *smu,
|
|||
gpu_metrics->average_socket_power = metrics.CurrentSocketPower;
|
||||
gpu_metrics->average_cpu_power = metrics.Power[0];
|
||||
gpu_metrics->average_soc_power = metrics.Power[1];
|
||||
gpu_metrics->average_gfx_power = metrics.Power[2];
|
||||
memcpy(&gpu_metrics->average_core_power[0],
|
||||
&metrics.CorePower[0],
|
||||
sizeof(uint16_t) * 8);
|
||||
|
||||
gpu_metrics->average_gfxclk_frequency = metrics.GfxclkFrequency;
|
||||
gpu_metrics->average_socclk_frequency = metrics.SocclkFrequency;
|
||||
gpu_metrics->average_uclk_frequency = metrics.MemclkFrequency;
|
||||
gpu_metrics->average_fclk_frequency = metrics.MemclkFrequency;
|
||||
gpu_metrics->average_vclk_frequency = metrics.VclkFrequency;
|
||||
gpu_metrics->average_dclk_frequency = metrics.DclkFrequency;
|
||||
|
||||
memcpy(&gpu_metrics->current_coreclk[0],
|
||||
&metrics.CoreFrequency[0],
|
||||
|
@ -1711,10 +1712,16 @@ static int vangogh_post_smu_init(struct smu_context *smu)
|
|||
adev->gfx.config.max_sh_per_se * adev->gfx.config.max_shader_engines;
|
||||
|
||||
/* allow message will be sent after enable message on Vangogh*/
|
||||
ret = smu_cmn_send_smc_msg(smu, SMU_MSG_EnableGfxOff, NULL);
|
||||
if (ret) {
|
||||
dev_err(adev->dev, "Failed to Enable GfxOff!\n");
|
||||
return ret;
|
||||
if (smu_cmn_feature_is_supported(smu, SMU_FEATURE_DPM_GFXCLK_BIT) &&
|
||||
(adev->pg_flags & AMD_PG_SUPPORT_GFX_PG)) {
|
||||
ret = smu_cmn_send_smc_msg(smu, SMU_MSG_EnableGfxOff, NULL);
|
||||
if (ret) {
|
||||
dev_err(adev->dev, "Failed to Enable GfxOff!\n");
|
||||
return ret;
|
||||
}
|
||||
} else {
|
||||
adev->pm.pp_feature &= ~PP_GFXOFF_MASK;
|
||||
dev_info(adev->dev, "If GFX DPM or power gate disabled, disable GFXOFF\n");
|
||||
}
|
||||
|
||||
/* if all CUs are active, no need to power off any WGPs */
|
||||
|
|
|
@ -56,8 +56,6 @@ static struct cmn2asic_msg_mapping renoir_message_map[SMU_MSG_MAX_COUNT] = {
|
|||
MSG_MAP(PowerUpSdma, PPSMC_MSG_PowerUpSdma, 1),
|
||||
MSG_MAP(SetHardMinIspclkByFreq, PPSMC_MSG_SetHardMinIspclkByFreq, 1),
|
||||
MSG_MAP(SetHardMinVcn, PPSMC_MSG_SetHardMinVcn, 1),
|
||||
MSG_MAP(Spare1, PPSMC_MSG_spare1, 1),
|
||||
MSG_MAP(Spare2, PPSMC_MSG_spare2, 1),
|
||||
MSG_MAP(SetAllowFclkSwitch, PPSMC_MSG_SetAllowFclkSwitch, 1),
|
||||
MSG_MAP(SetMinVideoGfxclkFreq, PPSMC_MSG_SetMinVideoGfxclkFreq, 1),
|
||||
MSG_MAP(ActiveProcessNotify, PPSMC_MSG_ActiveProcessNotify, 1),
|
||||
|
|
|
@ -142,10 +142,15 @@ int smu_cmn_send_smc_msg_with_param(struct smu_context *smu,
|
|||
|
||||
ret = smu_cmn_wait_for_response(smu);
|
||||
if (ret != 0x1) {
|
||||
dev_err(adev->dev, "failed send message: %10s (%d) \tparam: 0x%08x response %#x\n",
|
||||
smu_get_message_name(smu, msg), index, param, ret);
|
||||
if (ret != -ETIME)
|
||||
if (ret == -ETIME) {
|
||||
dev_err(adev->dev, "message: %15s (%d) \tparam: 0x%08x is timeout (no response)\n",
|
||||
smu_get_message_name(smu, msg), index, param);
|
||||
} else {
|
||||
dev_err(adev->dev, "failed send message: %15s (%d) \tparam: 0x%08x response %#x\n",
|
||||
smu_get_message_name(smu, msg), index, param,
|
||||
ret);
|
||||
ret = -EIO;
|
||||
}
|
||||
goto out;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue