Merge tag 'amd-drm-next-5.12-2021-02-03' of https://gitlab.freedesktop.org/agd5f...
authorDave Airlie <airlied@redhat.com>
Thu, 4 Feb 2021 23:38:19 +0000 (09:38 +1000)
committerDave Airlie <airlied@redhat.com>
Thu, 4 Feb 2021 23:38:23 +0000 (09:38 +1000)
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>
80 files changed:
drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.c
drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.h
drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c
drivers/gpu/drm/amd/amdgpu/amdgpu_device.c
drivers/gpu/drm/amd/amdgpu/amdgpu_display.c
drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c
drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c
drivers/gpu/drm/amd/amdgpu/amdgpu_object.c
drivers/gpu/drm/amd/amdgpu/amdgpu_virt.c
drivers/gpu/drm/amd/amdgpu/amdgpu_vram_mgr.c
drivers/gpu/drm/amd/amdgpu/gfx_v10_0.c
drivers/gpu/drm/amd/amdgpu/mmhub_v2_3.c
drivers/gpu/drm/amd/amdgpu/nv.c
drivers/gpu/drm/amd/amdkfd/Kconfig
drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_debugfs.c
drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_hdcp.c
drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c
drivers/gpu/drm/amd/display/dc/Makefile
drivers/gpu/drm/amd/display/dc/bios/command_table.c
drivers/gpu/drm/amd/display/dc/clk_mgr/dcn10/rv1_clk_mgr.c
drivers/gpu/drm/amd/display/dc/clk_mgr/dcn30/dcn30_clk_mgr.c
drivers/gpu/drm/amd/display/dc/clk_mgr/dcn301/vg_clk_mgr.c
drivers/gpu/drm/amd/display/dc/core/dc.c
drivers/gpu/drm/amd/display/dc/core/dc_link.c
drivers/gpu/drm/amd/display/dc/core/dc_link_ddc.c
drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c
drivers/gpu/drm/amd/display/dc/core/dc_resource.c
drivers/gpu/drm/amd/display/dc/dc.h
drivers/gpu/drm/amd/display/dc/dc_dsc.h
drivers/gpu/drm/amd/display/dc/dc_edid_parser.c [new file with mode: 0644]
drivers/gpu/drm/amd/display/dc/dc_edid_parser.h [new file with mode: 0644]
drivers/gpu/drm/amd/display/dc/dc_hw_types.h
drivers/gpu/drm/amd/display/dc/dc_stream.h
drivers/gpu/drm/amd/display/dc/dce/dce_clock_source.c
drivers/gpu/drm/amd/display/dc/dce/dce_dmcu.c
drivers/gpu/drm/amd/display/dc/dce/dce_dmcu.h
drivers/gpu/drm/amd/display/dc/dce/dce_stream_encoder.c
drivers/gpu/drm/amd/display/dc/dce/dce_transform.c
drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c
drivers/gpu/drm/amd/display/dc/dcn20/dcn20_resource.c
drivers/gpu/drm/amd/display/dc/dcn21/dcn21_resource.c
drivers/gpu/drm/amd/display/dc/dcn30/Makefile
drivers/gpu/drm/amd/display/dc/dcn30/dcn30_hwseq.c
drivers/gpu/drm/amd/display/dc/dcn30/dcn30_hwseq.h
drivers/gpu/drm/amd/display/dc/dcn30/dcn30_resource.c
drivers/gpu/drm/amd/display/dc/dcn301/Makefile
drivers/gpu/drm/amd/display/dc/dcn301/dcn301_resource.c
drivers/gpu/drm/amd/display/dc/dcn302/Makefile
drivers/gpu/drm/amd/display/dc/dcn302/dcn302_resource.c
drivers/gpu/drm/amd/display/dc/dcn302/dcn302_resource.h
drivers/gpu/drm/amd/display/dc/dm_cp_psp.h
drivers/gpu/drm/amd/display/dc/dml/dcn20/display_mode_vba_20v2.c
drivers/gpu/drm/amd/display/dc/dml/dcn30/display_rq_dlg_calc_30.c
drivers/gpu/drm/amd/display/dc/dsc/dc_dsc.c
drivers/gpu/drm/amd/display/dc/inc/hw/dmcu.h
drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h
drivers/gpu/drm/amd/display/dmub/inc/dmub_cmd.h
drivers/gpu/drm/amd/display/dmub/src/dmub_dcn20.c
drivers/gpu/drm/amd/display/dmub/src/dmub_dcn20.h
drivers/gpu/drm/amd/display/dmub/src/dmub_dcn30.c
drivers/gpu/drm/amd/display/dmub/src/dmub_srv.c
drivers/gpu/drm/amd/display/modules/color/color_table.c
drivers/gpu/drm/amd/display/modules/hdcp/hdcp.h
drivers/gpu/drm/amd/display/modules/hdcp/hdcp_psp.c
drivers/gpu/drm/amd/display/modules/inc/mod_hdcp.h
drivers/gpu/drm/amd/display/modules/power/power_helpers.c
drivers/gpu/drm/amd/include/amd_pcie.h
drivers/gpu/drm/amd/pm/amdgpu_pm.c
drivers/gpu/drm/amd/pm/inc/amdgpu_smu.h
drivers/gpu/drm/amd/pm/inc/smu_types.h
drivers/gpu/drm/amd/pm/inc/smu_v11_0.h
drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c
drivers/gpu/drm/amd/pm/swsmu/smu11/arcturus_ppt.c
drivers/gpu/drm/amd/pm/swsmu/smu11/navi10_ppt.c
drivers/gpu/drm/amd/pm/swsmu/smu11/sienna_cichlid_ppt.c
drivers/gpu/drm/amd/pm/swsmu/smu11/smu_v11_0.c
drivers/gpu/drm/amd/pm/swsmu/smu11/vangogh_ppt.c
drivers/gpu/drm/amd/pm/swsmu/smu12/renoir_ppt.c
drivers/gpu/drm/amd/pm/swsmu/smu_cmn.c

index db96d69..c5343a5 100644 (file)
@@ -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
index ea391ca..a81d9ca 100644 (file)
@@ -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 */
index 0849b68..ac0a432 100644 (file)
@@ -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;
index 00b6ba5..51bea40 100644 (file)
@@ -4211,7 +4211,6 @@ bool amdgpu_device_should_recover_gpu(struct amdgpu_device *adev)
                case CHIP_NAVI12:
                case CHIP_SIENNA_CICHLID:
                case CHIP_NAVY_FLOUNDER:
-               case CHIP_VANGOGH:
                        break;
                default:
                        goto disabled;
@@ -4461,6 +4460,46 @@ static void amdgpu_device_unlock_adev(struct amdgpu_device *adev)
        up_write(&adev->reset_sem);
 }
 
+/*
+ * to lockup a list of amdgpu devices in a hive safely, if not a hive
+ * with multiple nodes, it will be similar as amdgpu_device_lock_adev.
+ *
+ * unlock won't require roll back.
+ */
+static int amdgpu_device_lock_hive_adev(struct amdgpu_device *adev, struct amdgpu_hive_info *hive)
+{
+       struct amdgpu_device *tmp_adev = NULL;
+
+       if (adev->gmc.xgmi.num_physical_nodes > 1) {
+               if (!hive) {
+                       dev_err(adev->dev, "Hive is NULL while device has multiple xgmi nodes");
+                       return -ENODEV;
+               }
+               list_for_each_entry(tmp_adev, &hive->device_list, gmc.xgmi.head) {
+                       if (!amdgpu_device_lock_adev(tmp_adev, hive))
+                               goto roll_back;
+               }
+       } else if (!amdgpu_device_lock_adev(adev, hive))
+               return -EAGAIN;
+
+       return 0;
+roll_back:
+       if (!list_is_first(&tmp_adev->gmc.xgmi.head, &hive->device_list)) {
+               /*
+                * if the lockup iteration break in the middle of a hive,
+                * it may means there may has a race issue,
+                * or a hive device locked up independently.
+                * we may be in trouble and may not, so will try to roll back
+                * the lock and give out a warnning.
+                */
+               dev_warn(tmp_adev->dev, "Hive lock iteration broke in the middle. Rolling back to unlock");
+               list_for_each_entry_continue_reverse(tmp_adev, &hive->device_list, gmc.xgmi.head) {
+                       amdgpu_device_unlock_adev(tmp_adev);
+               }
+       }
+       return -EAGAIN;
+}
+
 static void amdgpu_device_resume_display_audio(struct amdgpu_device *adev)
 {
        struct pci_dev *p = NULL;
@@ -4574,11 +4613,29 @@ int amdgpu_device_gpu_recover(struct amdgpu_device *adev,
                        DRM_INFO("Bailing on TDR for s_job:%llx, hive: %llx as another already in progress",
                                job ? job->base.id : -1, hive->hive_id);
                        amdgpu_put_xgmi_hive(hive);
+                       if (job)
+                               drm_sched_increase_karma(&job->base);
                        return 0;
                }
                mutex_lock(&hive->hive_lock);
        }
 
+       /*
+        * lock the device before we try to operate the linked list
+        * if didn't get the device lock, don't touch the linked list since
+        * others may iterating it.
+        */
+       r = amdgpu_device_lock_hive_adev(adev, hive);
+       if (r) {
+               dev_info(adev->dev, "Bailing on TDR for s_job:%llx, as another already in progress",
+                                       job ? job->base.id : -1);
+
+               /* even we skipped this reset, still need to set the job to guilty */
+               if (job)
+                       drm_sched_increase_karma(&job->base);
+               goto skip_recovery;
+       }
+
        /*
         * Build list of devices to reset.
         * In case we are in XGMI hive mode, resort the device list
@@ -4586,8 +4643,6 @@ int amdgpu_device_gpu_recover(struct amdgpu_device *adev,
         */
        INIT_LIST_HEAD(&device_list);
        if (adev->gmc.xgmi.num_physical_nodes > 1) {
-               if (!hive)
-                       return -ENODEV;
                if (!list_is_first(&adev->gmc.xgmi.head, &hive->device_list))
                        list_rotate_to_front(&adev->gmc.xgmi.head, &hive->device_list);
                device_list_handle = &hive->device_list;
@@ -4598,13 +4653,6 @@ int amdgpu_device_gpu_recover(struct amdgpu_device *adev,
 
        /* block all schedulers and reset given job's ring */
        list_for_each_entry(tmp_adev, device_list_handle, gmc.xgmi.head) {
-               if (!amdgpu_device_lock_adev(tmp_adev, hive)) {
-                       dev_info(tmp_adev->dev, "Bailing on TDR for s_job:%llx, as another already in progress",
-                                 job ? job->base.id : -1);
-                       r = 0;
-                       goto skip_recovery;
-               }
-
                /*
                 * Try to put the audio codec into suspend state
                 * before gpu reset started.
@@ -4742,7 +4790,7 @@ 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 |
index f764803..48cb33e 100644 (file)
@@ -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);
        }
index effa906..8fde231 100644 (file)
@@ -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},
index a5c42c3..b443907 100644 (file)
@@ -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);
index 6cc9919..4b29b82 100644 (file)
@@ -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);
 }
 
index e223fca..5da04d4 100644 (file)
@@ -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;
        }
index d2de2a7..c89b66b 100644 (file)
@@ -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,
index 1d604fc..024460b 100644 (file)
 #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
 #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;
index 1961745..ab9be5a 100644 (file)
@@ -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 |
index b972228..66279f0 100644 (file)
@@ -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");
index e8fb10c..f02c938 100644 (file)
@@ -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.
index c64e469..f47551c 100644 (file)
@@ -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;
                }
 
index d645f3e..3609521 100644 (file)
@@ -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;
 
index c2cd184..b297ddc 100644 (file)
@@ -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;
index 5b0a4a7..41b09ab 100644 (file)
@@ -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;
index bf8fe04..5bf2f23 100644 (file)
@@ -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)
index 070459e..afc10b9 100644 (file)
@@ -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;
index 75b8240..e133edc 100644 (file)
@@ -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);
                }
        }
 }
index ab98c25..c7e5a64 100644 (file)
@@ -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)
index 991b9c5..aadb801 100644 (file)
@@ -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++;
        }
 
index a667480..8d5378f 100644 (file)
@@ -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;
 }
 
index 9885ef2..8506739 100644 (file)
@@ -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)
index c5936e0..ae6484a 100644 (file)
 #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,
index 4149b87..c1391bf 100644 (file)
@@ -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;
index 68b65a0..0c26c2a 100644 (file)
@@ -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);
index f3ba02c..739a39e 100644 (file)
 #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);
 
index ec55b77..e99273b 100644 (file)
@@ -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 (file)
index 0000000..0db5b49
--- /dev/null
@@ -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 (file)
index 0000000..da67ec0
--- /dev/null
@@ -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_ */
index b41e636..09e8be5 100644 (file)
@@ -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;
 };
 
index 80b67b8..a4f7ec8 100644 (file)
@@ -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.
  */
index 10938a8..17ec632 100644 (file)
@@ -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;
index 30264fc..ddc789d 100644 (file)
@@ -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
 };
 
index cefb7f5..ff726b3 100644 (file)
        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), \
        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, \
        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;
index 265eaef..8d4263d 100644 (file)
@@ -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)
index abbaa6b..151dc7b 100644 (file)
@@ -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;
index 7a30d1d..89912bb 100644 (file)
@@ -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(
index 5ed18ca..064f158 100644 (file)
@@ -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};
index b000b43..6743764 100644 (file)
@@ -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;
 
index c20331e..dfd77b3 100644 (file)
@@ -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
index e5cc8f8..9620fb8 100644 (file)
@@ -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)
index 1103f63..3b7d481 100644 (file)
@@ -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);
 
index e5bb15d..8d0f663 100644 (file)
@@ -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) {
index 3ca7d91..0926471 100644 (file)
@@ -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
index 35f5bf0..5d4b2c6 100644 (file)
@@ -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) {
index 8d4924b..101620a 100644 (file)
@@ -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
index 22ba0be..4b659b6 100644 (file)
@@ -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;
index 71f7dee..42d2c73 100644 (file)
@@ -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_ */
index 5da7677..cac0b2c 100644 (file)
@@ -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;
 };
index 80170f9..47e8e71 100644 (file)
@@ -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],
index 5b5916b..0f14f20 100644 (file)
@@ -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;
index c62d0ed..82a8050 100644 (file)
@@ -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)
index 69d9fbf..cd1c0dc 100644 (file)
@@ -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
index 48378be..0586ab2 100644 (file)
@@ -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);
index 249a076..5aaa35c 100644 (file)
 
 /* 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 {
index cafba1d..8e8e65f 100644 (file)
@@ -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);
index d438f36..a62be9c 100644 (file)
@@ -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_ */
index 7e6f4db..b4bc0df 100644 (file)
@@ -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);
index f388d36..61f64a2 100644 (file)
@@ -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);
 
index 692e536..410f2a8 100644 (file)
@@ -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"
index 6c678cf..5c22cf7 100644 (file)
@@ -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)
index 3a367a5..b26ed64 100644 (file)
@@ -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 =
index eed560e..d223ed3 100644 (file)
@@ -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 {
index 3d4c669..6270ecb 100644 (file)
@@ -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) ?
index 9cb9ceb..a1ece3e 100644 (file)
@@ -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
 
index e9b569b..cf475ac 100644 (file)
@@ -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;
index a087e00..44279c2 100644 (file)
@@ -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.
index b76270e..68c87d4 100644 (file)
        __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),         \
index 102a0cf..c7d57e9 100644 (file)
@@ -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);
index 7fe61ad..c00f3f5 100644 (file)
@@ -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);
 
index cd7b411..f0cc4de 100644 (file)
@@ -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,
index 7ebf958..f7f78da 100644 (file)
@@ -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,
index 24f3c96..e3ba40d 100644 (file)
@@ -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,
index 147efe1..cf6176a 100644 (file)
@@ -1137,10 +1137,10 @@ int smu_v11_0_gfx_off_control(struct smu_context *smu, bool enable)
 uint32_t
 smu_v11_0_get_fan_control_mode(struct smu_context *smu)
 {
-       if (!smu_cmn_feature_is_enabled(smu, SMU_FEATURE_FAN_CONTROL_BIT))
-               return AMD_FAN_CTRL_MANUAL;
-       else
+       if (smu_cmn_feature_is_enabled(smu, SMU_FEATURE_FAN_CONTROL_BIT))
                return AMD_FAN_CTRL_AUTO;
+       else
+               return smu->user_dpm_profile.fan_mode;
 }
 
 static int
@@ -1174,6 +1174,35 @@ smu_v11_0_set_fan_static_mode(struct smu_context *smu, uint32_t mode)
        return 0;
 }
 
+int
+smu_v11_0_set_fan_speed_percent(struct smu_context *smu, uint32_t speed)
+{
+       struct amdgpu_device *adev = smu->adev;
+       uint32_t duty100, duty;
+       uint64_t tmp64;
+
+       if (speed > 100)
+               speed = 100;
+
+       if (smu_v11_0_auto_fan_control(smu, 0))
+               return -EINVAL;
+
+       duty100 = REG_GET_FIELD(RREG32_SOC15(THM, 0, mmCG_FDO_CTRL1),
+                               CG_FDO_CTRL1, FMAX_DUTY100);
+       if (!duty100)
+               return -EINVAL;
+
+       tmp64 = (uint64_t)speed * duty100;
+       do_div(tmp64, 100);
+       duty = (uint32_t)tmp64;
+
+       WREG32_SOC15(THM, 0, mmCG_FDO_CTRL0,
+                    REG_SET_FIELD(RREG32_SOC15(THM, 0, mmCG_FDO_CTRL0),
+                                  CG_FDO_CTRL0, FDO_STATIC_DUTY, duty));
+
+       return smu_v11_0_set_fan_static_mode(smu, FDO_PWM_MODE_STATIC);
+}
+
 int
 smu_v11_0_set_fan_control_mode(struct smu_context *smu,
                               uint32_t mode)
@@ -1182,7 +1211,7 @@ smu_v11_0_set_fan_control_mode(struct smu_context *smu,
 
        switch (mode) {
        case AMD_FAN_CTRL_NONE:
-               ret = smu_v11_0_set_fan_speed_rpm(smu, smu->fan_max_rpm);
+               ret = smu_v11_0_set_fan_speed_percent(smu, 100);
                break;
        case AMD_FAN_CTRL_MANUAL:
                ret = smu_v11_0_auto_fan_control(smu, 0);
@@ -1202,58 +1231,6 @@ smu_v11_0_set_fan_control_mode(struct smu_context *smu,
        return ret;
 }
 
-int smu_v11_0_set_fan_speed_rpm(struct smu_context *smu,
-                                      uint32_t speed)
-{
-       struct amdgpu_device *adev = smu->adev;
-       int ret;
-       uint32_t tach_period, crystal_clock_freq;
-
-       if (!speed)
-               return -EINVAL;
-
-       ret = smu_v11_0_auto_fan_control(smu, 0);
-       if (ret)
-               return ret;
-
-       /*
-        * crystal_clock_freq div by 4 is required since the fan control
-        * module refers to 25MHz
-        */
-
-       crystal_clock_freq = amdgpu_asic_get_xclk(adev) / 4;
-       tach_period = 60 * crystal_clock_freq * 10000 / (8 * speed);
-       WREG32_SOC15(THM, 0, mmCG_TACH_CTRL,
-                    REG_SET_FIELD(RREG32_SOC15(THM, 0, mmCG_TACH_CTRL),
-                                  CG_TACH_CTRL, TARGET_PERIOD,
-                                  tach_period));
-
-       ret = smu_v11_0_set_fan_static_mode(smu, FDO_PWM_MODE_STATIC_RPM);
-
-       return ret;
-}
-
-int smu_v11_0_get_fan_speed_rpm(struct smu_context *smu,
-                               uint32_t *speed)
-{
-       struct amdgpu_device *adev = smu->adev;
-       uint32_t tach_period, crystal_clock_freq;
-       uint64_t tmp64;
-
-       tach_period = REG_GET_FIELD(RREG32_SOC15(THM, 0, mmCG_TACH_CTRL),
-                                   CG_TACH_CTRL, TARGET_PERIOD);
-       if (!tach_period)
-               return -EINVAL;
-
-       crystal_clock_freq = amdgpu_asic_get_xclk(adev);
-
-       tmp64 = (uint64_t)crystal_clock_freq * 60 * 10000;
-       do_div(tmp64, (tach_period * 8));
-       *speed = (uint32_t)tmp64;
-
-       return 0;
-}
-
 int smu_v11_0_set_xgmi_pstate(struct smu_context *smu,
                                     uint32_t pstate)
 {
index dc41abe..f0f06ef 100644 (file)
@@ -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 */
index 185698b..ab15570 100644 (file)
@@ -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),
index e4eff6d..d9ecaa0 100644 (file)
@@ -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;
        }