summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDave Airlie <airlied@redhat.com>2021-02-05 09:38:19 +1000
committerDave Airlie <airlied@redhat.com>2021-02-05 09:38:23 +1000
commitc5cb0db5fcce640574f5b73b2b4030b5b60f3700 (patch)
tree8396d017fae43a2c491e310e0254929e56d62e14
parent54c820d05ee8156b1379ca0efd011b77e23cabb2 (diff)
parentc915ef890d5dc79f483e1ca3b3a5b5f1a170690c (diff)
downloadlinux-c5cb0db5fcce640574f5b73b2b4030b5b60f3700.tar.bz2
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>
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.c87
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.h138
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c16
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_device.c86
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_display.c8
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c1
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c2
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_object.c10
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_virt.c7
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_vram_mgr.c3
-rw-r--r--drivers/gpu/drm/amd/amdgpu/gfx_v10_0.c37
-rw-r--r--drivers/gpu/drm/amd/amdgpu/mmhub_v2_3.c4
-rw-r--r--drivers/gpu/drm/amd/amdgpu/nv.c4
-rw-r--r--drivers/gpu/drm/amd/amdkfd/Kconfig2
-rw-r--r--drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c80
-rw-r--r--drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_debugfs.c10
-rw-r--r--drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_hdcp.c7
-rw-r--r--drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c6
-rw-r--r--drivers/gpu/drm/amd/display/dc/Makefile4
-rw-r--r--drivers/gpu/drm/amd/display/dc/bios/command_table.c61
-rw-r--r--drivers/gpu/drm/amd/display/dc/clk_mgr/dcn10/rv1_clk_mgr.c30
-rw-r--r--drivers/gpu/drm/amd/display/dc/clk_mgr/dcn30/dcn30_clk_mgr.c18
-rw-r--r--drivers/gpu/drm/amd/display/dc/clk_mgr/dcn301/vg_clk_mgr.c3
-rw-r--r--drivers/gpu/drm/amd/display/dc/core/dc.c46
-rw-r--r--drivers/gpu/drm/amd/display/dc/core/dc_link.c42
-rw-r--r--drivers/gpu/drm/amd/display/dc/core/dc_link_ddc.c19
-rw-r--r--drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c10
-rw-r--r--drivers/gpu/drm/amd/display/dc/core/dc_resource.c4
-rw-r--r--drivers/gpu/drm/amd/display/dc/dc.h17
-rw-r--r--drivers/gpu/drm/amd/display/dc/dc_dsc.h7
-rw-r--r--drivers/gpu/drm/amd/display/dc/dc_edid_parser.c80
-rw-r--r--drivers/gpu/drm/amd/display/dc/dc_edid_parser.h44
-rw-r--r--drivers/gpu/drm/amd/display/dc/dc_hw_types.h1
-rw-r--r--drivers/gpu/drm/amd/display/dc/dc_stream.h3
-rw-r--r--drivers/gpu/drm/amd/display/dc/dce/dce_clock_source.c14
-rw-r--r--drivers/gpu/drm/amd/display/dc/dce/dce_dmcu.c120
-rw-r--r--drivers/gpu/drm/amd/display/dc/dce/dce_dmcu.h11
-rw-r--r--drivers/gpu/drm/amd/display/dc/dce/dce_stream_encoder.c1
-rw-r--r--drivers/gpu/drm/amd/display/dc/dce/dce_transform.c8
-rw-r--r--drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c3
-rw-r--r--drivers/gpu/drm/amd/display/dc/dcn20/dcn20_resource.c111
-rw-r--r--drivers/gpu/drm/amd/display/dc/dcn21/dcn21_resource.c10
-rw-r--r--drivers/gpu/drm/amd/display/dc/dcn30/Makefile6
-rw-r--r--drivers/gpu/drm/amd/display/dc/dcn30/dcn30_hwseq.c182
-rw-r--r--drivers/gpu/drm/amd/display/dc/dcn30/dcn30_hwseq.h3
-rw-r--r--drivers/gpu/drm/amd/display/dc/dcn30/dcn30_resource.c143
-rw-r--r--drivers/gpu/drm/amd/display/dc/dcn301/Makefile3
-rw-r--r--drivers/gpu/drm/amd/display/dc/dcn301/dcn301_resource.c107
-rw-r--r--drivers/gpu/drm/amd/display/dc/dcn302/Makefile3
-rw-r--r--drivers/gpu/drm/amd/display/dc/dcn302/dcn302_resource.c173
-rw-r--r--drivers/gpu/drm/amd/display/dc/dcn302/dcn302_resource.h2
-rw-r--r--drivers/gpu/drm/amd/display/dc/dm_cp_psp.h7
-rw-r--r--drivers/gpu/drm/amd/display/dc/dml/dcn20/display_mode_vba_20v2.c117
-rw-r--r--drivers/gpu/drm/amd/display/dc/dml/dcn30/display_rq_dlg_calc_30.c32
-rw-r--r--drivers/gpu/drm/amd/display/dc/dsc/dc_dsc.c29
-rw-r--r--drivers/gpu/drm/amd/display/dc/inc/hw/dmcu.h10
-rw-r--r--drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h3
-rw-r--r--drivers/gpu/drm/amd/display/dmub/inc/dmub_cmd.h10
-rw-r--r--drivers/gpu/drm/amd/display/dmub/src/dmub_dcn20.c11
-rw-r--r--drivers/gpu/drm/amd/display/dmub/src/dmub_dcn20.h2
-rw-r--r--drivers/gpu/drm/amd/display/dmub/src/dmub_dcn30.c2
-rw-r--r--drivers/gpu/drm/amd/display/dmub/src/dmub_srv.c9
-rw-r--r--drivers/gpu/drm/amd/display/modules/color/color_table.c26
-rw-r--r--drivers/gpu/drm/amd/display/modules/hdcp/hdcp.h2
-rw-r--r--drivers/gpu/drm/amd/display/modules/hdcp/hdcp_psp.c2
-rw-r--r--drivers/gpu/drm/amd/display/modules/inc/mod_hdcp.h4
-rw-r--r--drivers/gpu/drm/amd/display/modules/power/power_helpers.c2
-rw-r--r--drivers/gpu/drm/amd/include/amd_pcie.h2
-rw-r--r--drivers/gpu/drm/amd/pm/amdgpu_pm.c19
-rw-r--r--drivers/gpu/drm/amd/pm/inc/amdgpu_smu.h25
-rw-r--r--drivers/gpu/drm/amd/pm/inc/smu_types.h2
-rw-r--r--drivers/gpu/drm/amd/pm/inc/smu_v11_0.h7
-rw-r--r--drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c176
-rw-r--r--drivers/gpu/drm/amd/pm/swsmu/smu11/arcturus_ppt.c26
-rw-r--r--drivers/gpu/drm/amd/pm/swsmu/smu11/navi10_ppt.c26
-rw-r--r--drivers/gpu/drm/amd/pm/swsmu/smu11/sienna_cichlid_ppt.c26
-rw-r--r--drivers/gpu/drm/amd/pm/swsmu/smu11/smu_v11_0.c89
-rw-r--r--drivers/gpu/drm/amd/pm/swsmu/smu11/vangogh_ppt.c19
-rw-r--r--drivers/gpu/drm/amd/pm/swsmu/smu12/renoir_ppt.c2
-rw-r--r--drivers/gpu/drm/amd/pm/swsmu/smu_cmn.c11
80 files changed, 1623 insertions, 872 deletions
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.c
index db96d69eb45e..c5343a5eecbe 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.c
@@ -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
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.h
index ea391ca7f2f1..a81d9cacf9b8 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.h
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.h
@@ -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 */
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c
index 0849b68e784f..ac0a432a9bf7 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c
@@ -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;
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c
index 00b6ba5740f3..51bea409e513 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c
@@ -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,20 +4613,36 @@ 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
* to put adev in the 1st position.
*/
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 @@ skip_recovery:
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 |
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_display.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_display.c
index f764803c53a4..48cb33e5b382 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_display.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_display.c
@@ -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);
}
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c
index effa9062f541..8fde2318a03c 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c
@@ -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},
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c
index a5c42c3004a0..b443907afcea 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c
@@ -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);
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_object.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_object.c
index 6cc9919b12cc..4b29b8205442 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_object.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_object.c
@@ -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 @@ error:
*/
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);
}
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_virt.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_virt.c
index e223fca3ed00..5da04d45b637 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_virt.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_virt.c
@@ -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;
}
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vram_mgr.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_vram_mgr.c
index d2de2a720a3d..c89b66bb70e2 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vram_mgr.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vram_mgr.c
@@ -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,
diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v10_0.c b/drivers/gpu/drm/amd/amdgpu/gfx_v10_0.c
index 1d604fcb9b77..024460b9775d 100644
--- a/drivers/gpu/drm/amd/amdgpu/gfx_v10_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/gfx_v10_0.c
@@ -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;
diff --git a/drivers/gpu/drm/amd/amdgpu/mmhub_v2_3.c b/drivers/gpu/drm/amd/amdgpu/mmhub_v2_3.c
index 1961745e89c7..ab9be5ad5a5f 100644
--- a/drivers/gpu/drm/amd/amdgpu/mmhub_v2_3.c
+++ b/drivers/gpu/drm/amd/amdgpu/mmhub_v2_3.c
@@ -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 |
diff --git a/drivers/gpu/drm/amd/amdgpu/nv.c b/drivers/gpu/drm/amd/amdgpu/nv.c
index b9722282d1b8..66279f0c6808 100644
--- a/drivers/gpu/drm/amd/amdgpu/nv.c
+++ b/drivers/gpu/drm/amd/amdgpu/nv.c
@@ -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");
diff --git a/drivers/gpu/drm/amd/amdkfd/Kconfig b/drivers/gpu/drm/amd/amdkfd/Kconfig
index e8fb10c41f16..f02c938f75da 100644
--- a/drivers/gpu/drm/amd/amdkfd/Kconfig
+++ b/drivers/gpu/drm/amd/amdkfd/Kconfig
@@ -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.
diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
index c64e469ac6b0..f47551c9b2f1 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
@@ -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;
}
diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_debugfs.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_debugfs.c
index d645f3e4610e..360952129b6d 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_debugfs.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_debugfs.c
@@ -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;
diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_hdcp.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_hdcp.c
index c2cd184f0bbd..b297ddc24d3a 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_hdcp.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_hdcp.c
@@ -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;
diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c
index 5b0a4a7479e2..41b09ab22233 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c
@@ -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;
diff --git a/drivers/gpu/drm/amd/display/dc/Makefile b/drivers/gpu/drm/amd/display/dc/Makefile
index bf8fe0471b8f..5bf2f2375b40 100644
--- a/drivers/gpu/drm/amd/display/dc/Makefile
+++ b/drivers/gpu/drm/amd/display/dc/Makefile
@@ -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)
diff --git a/drivers/gpu/drm/amd/display/dc/bios/command_table.c b/drivers/gpu/drm/amd/display/dc/bios/command_table.c
index 070459e3e407..afc10b954ffa 100644
--- a/drivers/gpu/drm/amd/display/dc/bios/command_table.c
+++ b/drivers/gpu/drm/amd/display/dc/bios/command_table.c
@@ -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;
diff --git a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn10/rv1_clk_mgr.c b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn10/rv1_clk_mgr.c
index 75b8240ed059..e133edc587d3 100644
--- a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn10/rv1_clk_mgr.c
+++ b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn10/rv1_clk_mgr.c
@@ -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);
}
}
}
diff --git a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn30/dcn30_clk_mgr.c b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn30/dcn30_clk_mgr.c
index ab98c259ef69..c7e5a64e06af 100644
--- a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn30/dcn30_clk_mgr.c
+++ b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn30/dcn30_clk_mgr.c
@@ -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)
diff --git a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn301/vg_clk_mgr.c b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn301/vg_clk_mgr.c
index 991b9c5beaa3..aadb801447a7 100644
--- a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn301/vg_clk_mgr.c
+++ b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn301/vg_clk_mgr.c
@@ -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++;
}
diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c
index a667480cc3a3..8d5378f53243 100644
--- a/drivers/gpu/drm/amd/display/dc/core/dc.c
+++ b/drivers/gpu/drm/amd/display/dc/core/dc.c
@@ -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];
+ /*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;
+ }
- if (new_pipe->plane_state && new_pipe->plane_state != old_pipe->plane_state)
- new_pipe->plane_state->force_full_update = true;
+ /* 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;
}
diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link.c b/drivers/gpu/drm/amd/display/dc/core/dc_link.c
index 9885ef21cc05..8506739a22f7 100644
--- a/drivers/gpu/drm/amd/display/dc/core/dc_link.c
+++ b/drivers/gpu/drm/amd/display/dc/core/dc_link.c
@@ -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 @@ create_fail:
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)
diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link_ddc.c b/drivers/gpu/drm/amd/display/dc/core/dc_link_ddc.c
index c5936e064360..ae6484ab567b 100644
--- a/drivers/gpu/drm/amd/display/dc/core/dc_link_ddc.c
+++ b/drivers/gpu/drm/amd/display/dc/core/dc_link_ddc.c
@@ -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,
diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c b/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c
index 4149b8771462..c1391bfb7a9b 100644
--- a/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c
+++ b/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c
@@ -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,13 +890,13 @@ 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;
+ aux_rd_interval_us = 4000;
break;
case 0x02:
- aux_rd_interval_us = 4000;
+ aux_rd_interval_us = 8000;
break;
case 0x03:
- aux_rd_interval_us = 8000;
+ aux_rd_interval_us = 12000;
break;
case 0x04:
aux_rd_interval_us = 16000;
diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c
index 68b65a090d17..0c26c2ade782 100644
--- a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c
+++ b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c
@@ -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);
diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h
index f3ba02cc85d2..739a39eeb941 100644
--- a/drivers/gpu/drm/amd/display/dc/dc.h
+++ b/drivers/gpu/drm/amd/display/dc/dc.h
@@ -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);
diff --git a/drivers/gpu/drm/amd/display/dc/dc_dsc.h b/drivers/gpu/drm/amd/display/dc/dc_dsc.h
index ec55b77727d5..e99273bff46d 100644
--- a/drivers/gpu/drm/amd/display/dc/dc_dsc.h
+++ b/drivers/gpu/drm/amd/display/dc/dc_dsc.h
@@ -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);
diff --git a/drivers/gpu/drm/amd/display/dc/dc_edid_parser.c b/drivers/gpu/drm/amd/display/dc/dc_edid_parser.c
new file mode 100644
index 000000000000..0db5b49e9d5e
--- /dev/null
+++ b/drivers/gpu/drm/amd/display/dc/dc_edid_parser.c
@@ -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;
+}
diff --git a/drivers/gpu/drm/amd/display/dc/dc_edid_parser.h b/drivers/gpu/drm/amd/display/dc/dc_edid_parser.h
new file mode 100644
index 000000000000..da67ec06f0a2
--- /dev/null
+++ b/drivers/gpu/drm/amd/display/dc/dc_edid_parser.h
@@ -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_ */
diff --git a/drivers/gpu/drm/amd/display/dc/dc_hw_types.h b/drivers/gpu/drm/amd/display/dc/dc_hw_types.h
index b41e6367b15e..09e8be5f7a1e 100644
--- a/drivers/gpu/drm/amd/display/dc/dc_hw_types.h
+++ b/drivers/gpu/drm/amd/display/dc/dc_hw_types.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;
};
diff --git a/drivers/gpu/drm/amd/display/dc/dc_stream.h b/drivers/gpu/drm/amd/display/dc/dc_stream.h
index 80b67b860091..a4f7ec888c67 100644
--- a/drivers/gpu/drm/amd/display/dc/dc_stream.h
+++ b/drivers/gpu/drm/amd/display/dc/dc_stream.h
@@ -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.
*/
diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_clock_source.c b/drivers/gpu/drm/amd/display/dc/dce/dce_clock_source.c
index 10938a8c9500..17ec63253fc3 100644
--- a/drivers/gpu/drm/amd/display/dc/dce/dce_clock_source.c
+++ b/drivers/gpu/drm/amd/display/dc/dce/dce_clock_source.c
@@ -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;
diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_dmcu.c b/drivers/gpu/drm/amd/display/dc/dce/dce_dmcu.c
index 30264fc151a2..ddc789daf3b1 100644
--- a/drivers/gpu/drm/amd/display/dc/dce/dce_dmcu.c
+++ b/drivers/gpu/drm/amd/display/dc/dce/dce_dmcu.c
@@ -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
};
diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_dmcu.h b/drivers/gpu/drm/amd/display/dc/dce/dce_dmcu.h
index cefb7f5bf42c..ff726b35ef6a 100644
--- a/drivers/gpu/drm/amd/display/dc/dce/dce_dmcu.h
+++ b/drivers/gpu/drm/amd/display/dc/dce/dce_dmcu.h
@@ -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;
diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_stream_encoder.c b/drivers/gpu/drm/amd/display/dc/dce/dce_stream_encoder.c
index 265eaef30a51..8d4263da59f2 100644
--- a/drivers/gpu/drm/amd/display/dc/dce/dce_stream_encoder.c
+++ b/drivers/gpu/drm/amd/display/dc/dce/dce_stream_encoder.c
@@ -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)
diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_transform.c b/drivers/gpu/drm/amd/display/dc/dce/dce_transform.c
index abbaa6b0b2db..151dc7bf6d23 100644
--- a/drivers/gpu/drm/amd/display/dc/dce/dce_transform.c
+++ b/drivers/gpu/drm/amd/display/dc/dce/dce_transform.c
@@ -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;
diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c
index 7a30d1d9b535..89912bb5014f 100644
--- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c
+++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c
@@ -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(
diff --git a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_resource.c b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_resource.c
index 5ed18cac57e8..064f158ce671 100644
--- a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_resource.c
+++ b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_resource.c
@@ -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};
diff --git a/drivers/gpu/drm/amd/display/dc/dcn21/dcn21_resource.c b/drivers/gpu/drm/amd/display/dc/dcn21/dcn21_resource.c
index b000b43a820d..674376428916 100644
--- a/drivers/gpu/drm/amd/display/dc/dcn21/dcn21_resource.c
+++ b/drivers/gpu/drm/amd/display/dc/dcn21/dcn21_resource.c
@@ -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;
diff --git a/drivers/gpu/drm/amd/display/dc/dcn30/Makefile b/drivers/gpu/drm/amd/display/dc/dcn30/Makefile
index c20331eb62e0..dfd77b3cc84d 100644
--- a/drivers/gpu/drm/amd/display/dc/dcn30/Makefile
+++ b/drivers/gpu/drm/amd/display/dc/dcn30/Makefile
@@ -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
diff --git a/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_hwseq.c b/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_hwseq.c
index e5cc8f8c363f..9620fb8a27dc 100644
--- a/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_hwseq.c
+++ b/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_hwseq.c
@@ -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;
+ }
+
+ 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;
}
- // 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));
+ /*
+ * 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)
diff --git a/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_hwseq.h b/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_hwseq.h
index 1103f6356e90..3b7d4812e311 100644
--- a/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_hwseq.h
+++ b/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_hwseq.h
@@ -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);
diff --git a/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_resource.c b/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_resource.c
index e5bb15d8487b..8d0f663489ac 100644
--- a/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_resource.c
+++ b/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_resource.c
@@ -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 @@ validate_out:
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) {
diff --git a/drivers/gpu/drm/amd/display/dc/dcn301/Makefile b/drivers/gpu/drm/amd/display/dc/dcn301/Makefile
index 3ca7d911d25c..09264716d1dc 100644
--- a/drivers/gpu/drm/amd/display/dc/dcn301/Makefile
+++ b/drivers/gpu/drm/amd/display/dc/dcn301/Makefile
@@ -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
diff --git a/drivers/gpu/drm/amd/display/dc/dcn301/dcn301_resource.c b/drivers/gpu/drm/amd/display/dc/dcn301/dcn301_resource.c
index 35f5bf08ae96..5d4b2c60192e 100644
--- a/drivers/gpu/drm/amd/display/dc/dcn301/dcn301_resource.c
+++ b/drivers/gpu/drm/amd/display/dc/dcn301/dcn301_resource.c
@@ -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) {
diff --git a/drivers/gpu/drm/amd/display/dc/dcn302/Makefile b/drivers/gpu/drm/amd/display/dc/dcn302/Makefile
index 8d4924b7dc22..101620a8867a 100644
--- a/drivers/gpu/drm/amd/display/dc/dcn302/Makefile
+++ b/drivers/gpu/drm/amd/display/dc/dcn302/Makefile
@@ -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
diff --git a/drivers/gpu/drm/amd/display/dc/dcn302/dcn302_resource.c b/drivers/gpu/drm/amd/display/dc/dcn302/dcn302_resource.c
index 22ba0be88faf..4b659b63f75b 100644
--- a/drivers/gpu/drm/amd/display/dc/dcn302/dcn302_resource.c
+++ b/drivers/gpu/drm/amd/display/dc/dcn302/dcn302_resource.c
@@ -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;
diff --git a/drivers/gpu/drm/amd/display/dc/dcn302/dcn302_resource.h b/drivers/gpu/drm/amd/display/dc/dcn302/dcn302_resource.h
index 71f7deed18e3..42d2c73e30bc 100644
--- a/drivers/gpu/drm/amd/display/dc/dcn302/dcn302_resource.h
+++ b/drivers/gpu/drm/amd/display/dc/dcn302/dcn302_resource.h
@@ -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_ */
diff --git a/drivers/gpu/drm/amd/display/dc/dm_cp_psp.h b/drivers/gpu/drm/amd/display/dc/dm_cp_psp.h
index 5da7677627a1..cac0b2c0d31b 100644
--- a/drivers/gpu/drm/amd/display/dc/dm_cp_psp.h
+++ b/drivers/gpu/drm/amd/display/dc/dm_cp_psp.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;
};
diff --git a/drivers/gpu/drm/amd/display/dc/dml/dcn20/display_mode_vba_20v2.c b/drivers/gpu/drm/amd/display/dc/dml/dcn20/display_mode_vba_20v2.c
index 80170f9721ce..47e8e71113ee 100644
--- a/drivers/gpu/drm/amd/display/dc/dml/dcn20/display_mode_vba_20v2.c
+++ b/drivers/gpu/drm/amd/display/dc/dml/dcn20/display_mode_vba_20v2.c
@@ -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],
diff --git a/drivers/gpu/drm/amd/display/dc/dml/dcn30/display_rq_dlg_calc_30.c b/drivers/gpu/drm/amd/display/dc/dml/dcn30/display_rq_dlg_calc_30.c
index 5b5916b5bc71..0f14f205ebe5 100644
--- a/drivers/gpu/drm/amd/display/dc/dml/dcn30/display_rq_dlg_calc_30.c
+++ b/drivers/gpu/drm/amd/display/dc/dml/dcn30/display_rq_dlg_calc_30.c
@@ -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;
diff --git a/drivers/gpu/drm/amd/display/dc/dsc/dc_dsc.c b/drivers/gpu/drm/amd/display/dc/dsc/dc_dsc.c
index c62d0eddc9c6..82a805088204 100644
--- a/drivers/gpu/drm/amd/display/dc/dsc/dc_dsc.c
+++ b/drivers/gpu/drm/amd/display/dc/dsc/dc_dsc.c
@@ -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)
diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/dmcu.h b/drivers/gpu/drm/amd/display/dc/inc/hw/dmcu.h
index 69d9fbfb4bec..cd1c0dc32bf8 100644
--- a/drivers/gpu/drm/amd/display/dc/inc/hw/dmcu.h
+++ b/drivers/gpu/drm/amd/display/dc/inc/hw/dmcu.h
@@ -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
diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h b/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h
index 48378beb71c0..0586ab2ffd6a 100644
--- a/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h
+++ b/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h
@@ -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);
diff --git a/drivers/gpu/drm/amd/display/dmub/inc/dmub_cmd.h b/drivers/gpu/drm/amd/display/dmub/inc/dmub_cmd.h
index 249a076d6f69..5aaa35c8c172 100644
--- a/drivers/gpu/drm/amd/display/dmub/inc/dmub_cmd.h
+++ b/drivers/gpu/drm/amd/display/dmub/inc/dmub_cmd.h
@@ -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 {
diff --git a/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn20.c b/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn20.c
index cafba1d23c6a..8e8e65fa83c0 100644
--- a/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn20.c
+++ b/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn20.c
@@ -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);
diff --git a/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn20.h b/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn20.h
index d438f365cbb0..a62be9c0652e 100644
--- a/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn20.h
+++ b/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn20.h
@@ -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_ */
diff --git a/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn30.c b/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn30.c
index 7e6f4dbabe45..b4bc0df2f14a 100644
--- a/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn30.c
+++ b/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn30.c
@@ -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);
diff --git a/drivers/gpu/drm/amd/display/dmub/src/dmub_srv.c b/drivers/gpu/drm/amd/display/dmub/src/dmub_srv.c
index f388d36af0b6..61f64a295f06 100644
--- a/drivers/gpu/drm/amd/display/dmub/src/dmub_srv.c
+++ b/drivers/gpu/drm/amd/display/dmub/src/dmub_srv.c
@@ -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);
diff --git a/drivers/gpu/drm/amd/display/modules/color/color_table.c b/drivers/gpu/drm/amd/display/modules/color/color_table.c
index 692e536e7d05..410f2a82b9a2 100644
--- a/drivers/gpu/drm/amd/display/modules/color/color_table.c
+++ b/drivers/gpu/drm/amd/display/modules/color/color_table.c
@@ -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"
diff --git a/drivers/gpu/drm/amd/display/modules/hdcp/hdcp.h b/drivers/gpu/drm/amd/display/modules/hdcp/hdcp.h
index 6c678cfb82e3..5c22cf7e6118 100644
--- a/drivers/gpu/drm/amd/display/modules/hdcp/hdcp.h
+++ b/drivers/gpu/drm/amd/display/modules/hdcp/hdcp.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)
diff --git a/drivers/gpu/drm/amd/display/modules/hdcp/hdcp_psp.c b/drivers/gpu/drm/amd/display/modules/hdcp/hdcp_psp.c
index 3a367a5968ae..b26ed64eaf98 100644
--- a/drivers/gpu/drm/amd/display/modules/hdcp/hdcp_psp.c
+++ b/drivers/gpu/drm/amd/display/modules/hdcp/hdcp_psp.c
@@ -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 =
diff --git a/drivers/gpu/drm/amd/display/modules/inc/mod_hdcp.h b/drivers/gpu/drm/amd/display/modules/inc/mod_hdcp.h
index eed560eecbab..d223ed3be5d3 100644
--- a/drivers/gpu/drm/amd/display/modules/inc/mod_hdcp.h
+++ b/drivers/gpu/drm/amd/display/modules/inc/mod_hdcp.h
@@ -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 {
diff --git a/drivers/gpu/drm/amd/display/modules/power/power_helpers.c b/drivers/gpu/drm/amd/display/modules/power/power_helpers.c
index 3d4c66933f51..6270ecbd2438 100644
--- a/drivers/gpu/drm/amd/display/modules/power/power_helpers.c
+++ b/drivers/gpu/drm/amd/display/modules/power/power_helpers.c
@@ -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) ?
diff --git a/drivers/gpu/drm/amd/include/amd_pcie.h b/drivers/gpu/drm/amd/include/amd_pcie.h
index 9cb9ceb4d74d..a1ece3eecdf5 100644
--- a/drivers/gpu/drm/amd/include/amd_pcie.h
+++ b/drivers/gpu/drm/amd/include/amd_pcie.h
@@ -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
diff --git a/drivers/gpu/drm/amd/pm/amdgpu_pm.c b/drivers/gpu/drm/amd/pm/amdgpu_pm.c
index e9b569b76716..cf475ac01b27 100644
--- a/drivers/gpu/drm/amd/pm/amdgpu_pm.c
+++ b/drivers/gpu/drm/amd/pm/amdgpu_pm.c
@@ -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, &parameter[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, &parameter[parameter_size]);
if (ret)
return -EINVAL;
diff --git a/drivers/gpu/drm/amd/pm/inc/amdgpu_smu.h b/drivers/gpu/drm/amd/pm/inc/amdgpu_smu.h
index a087e00382e6..44279c2afccb 100644
--- a/drivers/gpu/drm/amd/pm/inc/amdgpu_smu.h
+++ b/drivers/gpu/drm/amd/pm/inc/amdgpu_smu.h
@@ -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.
diff --git a/drivers/gpu/drm/amd/pm/inc/smu_types.h b/drivers/gpu/drm/amd/pm/inc/smu_types.h
index b76270e8767c..68c87d4b1ce3 100644
--- a/drivers/gpu/drm/amd/pm/inc/smu_types.h
+++ b/drivers/gpu/drm/amd/pm/inc/smu_types.h
@@ -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), \
diff --git a/drivers/gpu/drm/amd/pm/inc/smu_v11_0.h b/drivers/gpu/drm/amd/pm/inc/smu_v11_0.h
index 102a0cf12d7a..c7d57e9555cc 100644
--- a/drivers/gpu/drm/amd/pm/inc/smu_v11_0.h
+++ b/drivers/gpu/drm/amd/pm/inc/smu_v11_0.h
@@ -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);
diff --git a/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c b/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c
index 7fe61ad3ed10..c00f3f531965 100644
--- a/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c
+++ b/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c
@@ -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, &current_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);
diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu11/arcturus_ppt.c b/drivers/gpu/drm/amd/pm/swsmu/smu11/arcturus_ppt.c
index cd7b411457ff..f0cc4de9ced5 100644
--- a/drivers/gpu/drm/amd/pm/swsmu/smu11/arcturus_ppt.c
+++ b/drivers/gpu/drm/amd/pm/swsmu/smu11/arcturus_ppt.c
@@ -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,
diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu11/navi10_ppt.c b/drivers/gpu/drm/amd/pm/swsmu/smu11/navi10_ppt.c
index 7ebf9588983f..f7f78daffd27 100644
--- a/drivers/gpu/drm/amd/pm/swsmu/smu11/navi10_ppt.c
+++ b/drivers/gpu/drm/amd/pm/swsmu/smu11/navi10_ppt.c
@@ -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,
diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu11/sienna_cichlid_ppt.c b/drivers/gpu/drm/amd/pm/swsmu/smu11/sienna_cichlid_ppt.c
index 24f3c96a5e5e..e3ba40d9f83f 100644
--- a/drivers/gpu/drm/amd/pm/swsmu/smu11/sienna_cichlid_ppt.c
+++ b/drivers/gpu/drm/amd/pm/swsmu/smu11/sienna_cichlid_ppt.c
@@ -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,
diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu11/smu_v11_0.c b/drivers/gpu/drm/amd/pm/swsmu/smu11/smu_v11_0.c
index 147efe12973c..cf6176afd4d5 100644
--- a/drivers/gpu/drm/amd/pm/swsmu/smu11/smu_v11_0.c
+++ b/drivers/gpu/drm/amd/pm/swsmu/smu11/smu_v11_0.c
@@ -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
@@ -1175,6 +1175,35 @@ smu_v11_0_set_fan_static_mode(struct smu_context *smu, uint32_t mode)
}
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)
{
diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu11/vangogh_ppt.c b/drivers/gpu/drm/amd/pm/swsmu/smu11/vangogh_ppt.c
index dc41abe7b1d3..f0f06ef47b9e 100644
--- a/drivers/gpu/drm/amd/pm/swsmu/smu11/vangogh_ppt.c
+++ b/drivers/gpu/drm/amd/pm/swsmu/smu11/vangogh_ppt.c
@@ -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 */
diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu12/renoir_ppt.c b/drivers/gpu/drm/amd/pm/swsmu/smu12/renoir_ppt.c
index 185698bb0027..ab15570305f7 100644
--- a/drivers/gpu/drm/amd/pm/swsmu/smu12/renoir_ppt.c
+++ b/drivers/gpu/drm/amd/pm/swsmu/smu12/renoir_ppt.c
@@ -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),
diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu_cmn.c b/drivers/gpu/drm/amd/pm/swsmu/smu_cmn.c
index e4eff6d9f092..d9ecaa04d14e 100644
--- a/drivers/gpu/drm/amd/pm/swsmu/smu_cmn.c
+++ b/drivers/gpu/drm/amd/pm/swsmu/smu_cmn.c
@@ -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;
}