From c8031019dc95e3ab7cc0b09f1894c5f52dc0c187 Mon Sep 17 00:00:00 2001 From: Arunpravin Paneer Selvam Date: Tue, 10 Oct 2023 07:35:06 -0700 Subject: drm/amdgpu: Implement a new 64bit sequence memory driver MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Developed a new driver which allocates a 64bit memory on each request in sequence order. At the moment, user queue fence memory is the main consumer of this seq64 driver. v2: Worked on review comments from Christian for the following modifications - Move driver name from "semaphore" to "seq64" - Remove unnecessary PT/PD mapping - Move enable_mes check into init/fini functions. v3: Worked on review comments from Christian - drop enable_mes check - use DECLARE_BITMAP for bit array - added kerneldoc for seq64 v4: Worked on review comments from Christian - Rename amdgpu_seq64_get name with amdgpu_seq64_alloc v5: Worked on review comments from Christian - Fix seq64 lockdep warning - move fpriv->seq64_va check into amdgpu_seq64_unmap() - make the function amdgpu_seq64_unmap() return as void. - reserve the buffers as not interruptible. v6: port to drm_exec (Alex) v7: disable for now (Arun) Signed-off-by: Arunpravin Paneer Selvam Reviewed-by: Christian König Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/Makefile | 2 +- drivers/gpu/drm/amd/amdgpu/amdgpu.h | 5 + drivers/gpu/drm/amd/amdgpu/amdgpu_device.c | 7 + drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c | 2 + drivers/gpu/drm/amd/amdgpu/amdgpu_seq64.c | 247 +++++++++++++++++++++++++++++ drivers/gpu/drm/amd/amdgpu/amdgpu_seq64.h | 49 ++++++ 6 files changed, 311 insertions(+), 1 deletion(-) create mode 100644 drivers/gpu/drm/amd/amdgpu/amdgpu_seq64.c create mode 100644 drivers/gpu/drm/amd/amdgpu/amdgpu_seq64.h diff --git a/drivers/gpu/drm/amd/amdgpu/Makefile b/drivers/gpu/drm/amd/amdgpu/Makefile index 2afecc55090f..260e32ef7bae 100644 --- a/drivers/gpu/drm/amd/amdgpu/Makefile +++ b/drivers/gpu/drm/amd/amdgpu/Makefile @@ -80,7 +80,7 @@ amdgpu-y += amdgpu_device.o amdgpu_doorbell_mgr.o amdgpu_kms.o \ amdgpu_umc.o smu_v11_0_i2c.o amdgpu_fru_eeprom.o amdgpu_rap.o \ amdgpu_fw_attestation.o amdgpu_securedisplay.o \ amdgpu_eeprom.o amdgpu_mca.o amdgpu_psp_ta.o amdgpu_lsdma.o \ - amdgpu_ring_mux.o amdgpu_xcp.o + amdgpu_ring_mux.o amdgpu_xcp.o amdgpu_seq64.o amdgpu-$(CONFIG_PROC_FS) += amdgpu_fdinfo.o diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu.h b/drivers/gpu/drm/amd/amdgpu/amdgpu.h index 9d92ca157677..4d100f8d75bf 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu.h @@ -109,6 +109,7 @@ #include "amdgpu_mca.h" #include "amdgpu_ras.h" #include "amdgpu_xcp.h" +#include "amdgpu_seq64.h" #define MAX_GPU_INSTANCE 64 @@ -468,6 +469,7 @@ struct amdgpu_fpriv { struct amdgpu_vm vm; struct amdgpu_bo_va *prt_va; struct amdgpu_bo_va *csa_va; + struct amdgpu_bo_va *seq64_va; struct mutex bo_list_lock; struct idr bo_list_handles; struct amdgpu_ctx_mgr ctx_mgr; @@ -986,6 +988,9 @@ struct amdgpu_device { /* GDS */ struct amdgpu_gds gds; + /* for userq and VM fences */ + struct amdgpu_seq64 seq64; + /* KFD */ struct amdgpu_kfd_dev kfd; diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c index 7eeaf0aa7f81..151f8b950b72 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c @@ -2676,6 +2676,12 @@ static int amdgpu_device_ip_init(struct amdgpu_device *adev) goto init_failed; } } + + r = amdgpu_seq64_init(adev); + if (r) { + DRM_ERROR("allocate seq64 failed %d\n", r); + goto init_failed; + } } } @@ -3138,6 +3144,7 @@ static int amdgpu_device_ip_fini(struct amdgpu_device *adev) amdgpu_device_wb_fini(adev); amdgpu_device_mem_scratch_fini(adev); amdgpu_ib_pool_fini(adev); + amdgpu_seq64_fini(adev); } r = adev->ip_blocks[i].version->funcs->sw_fini((void *)adev); diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c index 583cf03950cd..b5ebafd4a3ad 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c @@ -1428,6 +1428,8 @@ void amdgpu_driver_postclose_kms(struct drm_device *dev, fpriv->csa_va = NULL; } + amdgpu_seq64_unmap(adev, fpriv); + pasid = fpriv->vm.pasid; pd = amdgpu_bo_ref(fpriv->vm.root.bo); if (!WARN_ON(amdgpu_bo_reserve(pd, true))) { diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_seq64.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_seq64.c new file mode 100644 index 000000000000..f3de02193138 --- /dev/null +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_seq64.c @@ -0,0 +1,247 @@ +// SPDX-License-Identifier: MIT +/* + * Copyright 2023 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. + * + */ + +#include "amdgpu.h" +#include "amdgpu_seq64.h" + +#include + +/** + * DOC: amdgpu_seq64 + * + * amdgpu_seq64 allocates a 64bit memory on each request in sequence order. + * seq64 driver is required for user queue fence memory allocation, TLB + * counters and VM updates. It has maximum count of 32768 64 bit slots. + */ + +/** + * amdgpu_seq64_map - Map the seq64 memory to VM + * + * @adev: amdgpu_device pointer + * @vm: vm pointer + * @bo_va: bo_va pointer + * @seq64_addr: seq64 vaddr start address + * @size: seq64 pool size + * + * Map the seq64 memory to the given VM. + * + * Returns: + * 0 on success or a negative error code on failure + */ +int amdgpu_seq64_map(struct amdgpu_device *adev, struct amdgpu_vm *vm, + struct amdgpu_bo_va **bo_va, u64 seq64_addr, + uint32_t size) +{ + struct amdgpu_bo *bo; + struct drm_exec exec; + int r; + + bo = adev->seq64.sbo; + if (!bo) + return -EINVAL; + + drm_exec_init(&exec, DRM_EXEC_INTERRUPTIBLE_WAIT); + drm_exec_until_all_locked(&exec) { + r = amdgpu_vm_lock_pd(vm, &exec, 0); + if (likely(!r)) + r = drm_exec_lock_obj(&exec, &bo->tbo.base); + drm_exec_retry_on_contention(&exec); + if (unlikely(r)) + goto error; + } + + *bo_va = amdgpu_vm_bo_add(adev, vm, bo); + if (!*bo_va) { + r = -ENOMEM; + goto error; + } + + r = amdgpu_vm_bo_map(adev, *bo_va, seq64_addr, 0, size, + AMDGPU_PTE_READABLE | AMDGPU_PTE_WRITEABLE | + AMDGPU_PTE_EXECUTABLE); + if (r) { + DRM_ERROR("failed to do bo_map on userq sem, err=%d\n", r); + amdgpu_vm_bo_del(adev, *bo_va); + goto error; + } + + r = amdgpu_vm_bo_update(adev, *bo_va, false); + if (r) { + DRM_ERROR("failed to do vm_bo_update on userq sem\n"); + amdgpu_vm_bo_del(adev, *bo_va); + goto error; + } + +error: + drm_exec_fini(&exec); + return r; +} + +/** + * amdgpu_seq64_unmap - Unmap the seq64 memory + * + * @adev: amdgpu_device pointer + * @fpriv: DRM file private + * + * Unmap the seq64 memory from the given VM. + */ +void amdgpu_seq64_unmap(struct amdgpu_device *adev, struct amdgpu_fpriv *fpriv) +{ + struct amdgpu_vm *vm; + struct amdgpu_bo *bo; + struct drm_exec exec; + int r; + + if (!fpriv->seq64_va) + return; + + bo = adev->seq64.sbo; + if (!bo) + return; + + vm = &fpriv->vm; + + drm_exec_init(&exec, DRM_EXEC_INTERRUPTIBLE_WAIT); + drm_exec_until_all_locked(&exec) { + r = amdgpu_vm_lock_pd(vm, &exec, 0); + if (likely(!r)) + r = drm_exec_lock_obj(&exec, &bo->tbo.base); + drm_exec_retry_on_contention(&exec); + if (unlikely(r)) + goto error; + } + + amdgpu_vm_bo_del(adev, fpriv->seq64_va); + + fpriv->seq64_va = NULL; + +error: + drm_exec_fini(&exec); +} + +/** + * amdgpu_seq64_alloc - Allocate a 64 bit memory + * + * @adev: amdgpu_device pointer + * @gpu_addr: allocated gpu VA start address + * @cpu_addr: allocated cpu VA start address + * + * Alloc a 64 bit memory from seq64 pool. + * + * Returns: + * 0 on success or a negative error code on failure + */ +int amdgpu_seq64_alloc(struct amdgpu_device *adev, u64 *gpu_addr, + u64 **cpu_addr) +{ + unsigned long bit_pos; + u32 offset; + + bit_pos = find_first_zero_bit(adev->seq64.used, adev->seq64.num_sem); + + if (bit_pos < adev->seq64.num_sem) { + __set_bit(bit_pos, adev->seq64.used); + offset = bit_pos << 6; /* convert to qw offset */ + } else { + return -EINVAL; + } + + *gpu_addr = offset + AMDGPU_SEQ64_VADDR_START; + *cpu_addr = offset + adev->seq64.cpu_base_addr; + + return 0; +} + +/** + * amdgpu_seq64_free - Free the given 64 bit memory + * + * @adev: amdgpu_device pointer + * @gpu_addr: gpu start address to be freed + * + * Free the given 64 bit memory from seq64 pool. + * + */ +void amdgpu_seq64_free(struct amdgpu_device *adev, u64 gpu_addr) +{ + u32 offset; + + offset = gpu_addr - AMDGPU_SEQ64_VADDR_START; + + offset >>= 6; + if (offset < adev->seq64.num_sem) + __clear_bit(offset, adev->seq64.used); +} + +/** + * amdgpu_seq64_fini - Cleanup seq64 driver + * + * @adev: amdgpu_device pointer + * + * Free the memory space allocated for seq64. + * + */ +void amdgpu_seq64_fini(struct amdgpu_device *adev) +{ + amdgpu_bo_free_kernel(&adev->seq64.sbo, + NULL, + (void **)&adev->seq64.cpu_base_addr); +} + +/** + * amdgpu_seq64_init - Initialize seq64 driver + * + * @adev: amdgpu_device pointer + * + * Allocate the required memory space for seq64. + * + * Returns: + * 0 on success or a negative error code on failure + */ +int amdgpu_seq64_init(struct amdgpu_device *adev) +{ + int r; + + if (adev->seq64.sbo) + return 0; + + /* + * AMDGPU_MAX_SEQ64_SLOTS * sizeof(u64) * 8 = AMDGPU_MAX_SEQ64_SLOTS + * 64bit slots + */ + r = amdgpu_bo_create_kernel(adev, AMDGPU_SEQ64_SIZE, + PAGE_SIZE, AMDGPU_GEM_DOMAIN_GTT, + &adev->seq64.sbo, NULL, + (void **)&adev->seq64.cpu_base_addr); + if (r) { + dev_warn(adev->dev, "(%d) create seq64 failed\n", r); + return r; + } + + memset(adev->seq64.cpu_base_addr, 0, AMDGPU_SEQ64_SIZE); + + adev->seq64.num_sem = AMDGPU_MAX_SEQ64_SLOTS; + memset(&adev->seq64.used, 0, sizeof(adev->seq64.used)); + + return 0; +} diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_seq64.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_seq64.h new file mode 100644 index 000000000000..2196e72be508 --- /dev/null +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_seq64.h @@ -0,0 +1,49 @@ +/* SPDX-License-Identifier: MIT */ +/* + * Copyright 2023 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. + * + */ + +#ifndef __AMDGPU_SEQ64_H__ +#define __AMDGPU_SEQ64_H__ + +#define AMDGPU_SEQ64_SIZE (2ULL << 20) +#define AMDGPU_MAX_SEQ64_SLOTS (AMDGPU_SEQ64_SIZE / (sizeof(u64) * 8)) +#define AMDGPU_SEQ64_VADDR_OFFSET 0x50000 +#define AMDGPU_SEQ64_VADDR_START (AMDGPU_VA_RESERVED_SIZE + AMDGPU_SEQ64_VADDR_OFFSET) + +struct amdgpu_seq64 { + struct amdgpu_bo *sbo; + u32 num_sem; + u64 *cpu_base_addr; + DECLARE_BITMAP(used, AMDGPU_MAX_SEQ64_SLOTS); +}; + +void amdgpu_seq64_fini(struct amdgpu_device *adev); +int amdgpu_seq64_init(struct amdgpu_device *adev); +int amdgpu_seq64_alloc(struct amdgpu_device *adev, u64 *gpu_addr, u64 **cpu_addr); +void amdgpu_seq64_free(struct amdgpu_device *adev, u64 gpu_addr); +int amdgpu_seq64_map(struct amdgpu_device *adev, struct amdgpu_vm *vm, + struct amdgpu_bo_va **bo_va, u64 seq64_addr, uint32_t size); +void amdgpu_seq64_unmap(struct amdgpu_device *adev, struct amdgpu_fpriv *fpriv); + +#endif + -- cgit From e6ed364efae39455cb1d6b1895a1d31599608a2b Mon Sep 17 00:00:00 2001 From: Felix Kuehling Date: Wed, 16 Mar 2022 18:46:56 -0400 Subject: drm/amdgpu: update mappings not managed by KFD MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When restoring after an eviction, use amdgpu_vm_handle_moved to update BO VA mappings in KFD VMs that are not managed through the KFD API. This should allow using the render node API to create more flexible memory mappings in KFD VMs. v2: rebase on drm_exec changes (Alex) Signed-off-by: Felix Kuehling Acked-by: Christian König Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c | 28 +++++++++++++++++++----- 1 file changed, 22 insertions(+), 6 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c index 41fbc4fd0fac..b98c0969d3be 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c @@ -2825,12 +2825,6 @@ int amdgpu_amdkfd_gpuvm_restore_process_bos(void *info, struct dma_fence **ef) if (ret) goto validate_map_fail; - ret = process_sync_pds_resv(process_info, &sync_obj); - if (ret) { - pr_debug("Memory eviction: Failed to sync to PD BO moving fence. Try again\n"); - goto validate_map_fail; - } - /* Validate BOs and map them to GPUVM (update VM page tables). */ list_for_each_entry(mem, &process_info->kfd_bo_list, validate_list) { @@ -2881,6 +2875,19 @@ int amdgpu_amdkfd_gpuvm_restore_process_bos(void *info, struct dma_fence **ef) if (failed_size) pr_debug("0x%lx/0x%lx in system\n", failed_size, total_size); + /* Update mappings not managed by KFD */ + list_for_each_entry(peer_vm, &process_info->vm_list_head, + vm_list_node) { + struct amdgpu_device *adev = amdgpu_ttm_adev( + peer_vm->root.bo->tbo.bdev); + + ret = amdgpu_vm_handle_moved(adev, peer_vm, &exec.ticket); + if (ret) { + pr_debug("Memory eviction: handle moved failed. Try again\n"); + goto validate_map_fail; + } + } + /* Update page directories */ ret = process_update_pds(process_info, &sync_obj); if (ret) { @@ -2888,6 +2895,15 @@ int amdgpu_amdkfd_gpuvm_restore_process_bos(void *info, struct dma_fence **ef) goto validate_map_fail; } + /* Sync with fences on all the page tables. They implicitly depend on any + * move fences from amdgpu_vm_handle_moved above. + */ + ret = process_sync_pds_resv(process_info, &sync_obj); + if (ret) { + pr_debug("Memory eviction: Failed to sync to PD BO moving fence. Try again\n"); + goto validate_map_fail; + } + /* Wait for validate and PT updates to finish */ amdgpu_sync_wait(&sync_obj, false); -- cgit From 94e2dae0a8bfd456abfd866f1eee8342f0858012 Mon Sep 17 00:00:00 2001 From: Felix Kuehling Date: Fri, 24 Feb 2023 18:22:32 -0500 Subject: drm/amdkfd: Move TLB flushing logic into amdgpu MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This will make it possible for amdgpu GEM ioctls to flush TLBs on compute VMs. This removes VMID-based TLB flushing and always uses PASID-based flushing. This still works because it scans the VMID-PASID mapping registers to find the right VMID. It's only slightly less efficient. This is not a production use case. Signed-off-by: Felix Kuehling Reviewed-by: Christian König Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.c | 29 -------------------- drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.h | 5 ---- drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c | 44 ++++++++++++++++++++++++++++++ drivers/gpu/drm/amd/amdgpu/amdgpu_vm.h | 5 ++++ drivers/gpu/drm/amd/amdkfd/kfd_priv.h | 10 +++++-- drivers/gpu/drm/amd/amdkfd/kfd_process.c | 31 --------------------- 6 files changed, 57 insertions(+), 67 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.c index b8412202a1b0..6ab17330a6ed 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.c @@ -710,35 +710,6 @@ bool amdgpu_amdkfd_is_kfd_vmid(struct amdgpu_device *adev, u32 vmid) return false; } -int amdgpu_amdkfd_flush_gpu_tlb_vmid(struct amdgpu_device *adev, - uint16_t vmid) -{ - if (adev->family == AMDGPU_FAMILY_AI) { - int i; - - for_each_set_bit(i, adev->vmhubs_mask, AMDGPU_MAX_VMHUBS) - amdgpu_gmc_flush_gpu_tlb(adev, vmid, i, 0); - } else { - amdgpu_gmc_flush_gpu_tlb(adev, vmid, AMDGPU_GFXHUB(0), 0); - } - - return 0; -} - -int amdgpu_amdkfd_flush_gpu_tlb_pasid(struct amdgpu_device *adev, - uint16_t pasid, - enum TLB_FLUSH_TYPE flush_type, - uint32_t inst) -{ - bool all_hub = false; - - if (adev->family == AMDGPU_FAMILY_AI || - adev->family == AMDGPU_FAMILY_RV) - all_hub = true; - - return amdgpu_gmc_flush_gpu_tlb_pasid(adev, pasid, flush_type, all_hub, inst); -} - bool amdgpu_amdkfd_have_atomics_support(struct amdgpu_device *adev) { return adev->have_atomics_support; diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.h index dac983da961d..16794c2eea35 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.h @@ -162,11 +162,6 @@ int amdgpu_amdkfd_submit_ib(struct amdgpu_device *adev, uint32_t *ib_cmd, uint32_t ib_len); void amdgpu_amdkfd_set_compute_idle(struct amdgpu_device *adev, bool idle); bool amdgpu_amdkfd_have_atomics_support(struct amdgpu_device *adev); -int amdgpu_amdkfd_flush_gpu_tlb_vmid(struct amdgpu_device *adev, - uint16_t vmid); -int amdgpu_amdkfd_flush_gpu_tlb_pasid(struct amdgpu_device *adev, - uint16_t pasid, enum TLB_FLUSH_TYPE flush_type, - uint32_t inst); bool amdgpu_amdkfd_is_kfd_vmid(struct amdgpu_device *adev, u32 vmid); diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c index d1b8afd105c9..d59154ddaaed 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c @@ -1437,6 +1437,50 @@ int amdgpu_vm_handle_moved(struct amdgpu_device *adev, return 0; } +/** + * amdgpu_vm_flush_compute_tlb - Flush TLB on compute VM + * + * @adev: amdgpu_device pointer + * @vm: requested vm + * @flush_type: flush type + * + * Flush TLB if needed for a compute VM. + * + * Returns: + * 0 for success. + */ +int amdgpu_vm_flush_compute_tlb(struct amdgpu_device *adev, + struct amdgpu_vm *vm, + uint32_t flush_type, + uint32_t xcc_mask) +{ + uint64_t tlb_seq = amdgpu_vm_tlb_seq(vm); + bool all_hub = false; + int xcc = 0, r = 0; + + WARN_ON_ONCE(!vm->is_compute_context); + + /* + * It can be that we race and lose here, but that is extremely unlikely + * and the worst thing which could happen is that we flush the changes + * into the TLB once more which is harmless. + */ + if (atomic64_xchg(&vm->kfd_last_flushed_seq, tlb_seq) == tlb_seq) + return 0; + + if (adev->family == AMDGPU_FAMILY_AI || + adev->family == AMDGPU_FAMILY_RV) + all_hub = true; + + for_each_inst(xcc, xcc_mask) { + r = amdgpu_gmc_flush_gpu_tlb_pasid(adev, vm->pasid, flush_type, + all_hub, xcc); + if (r) + break; + } + return r; +} + /** * amdgpu_vm_bo_add - add a bo to a specific vm * diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.h index 2cd86d2bf73f..b6cd565562ad 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.h @@ -324,6 +324,7 @@ struct amdgpu_vm { /* Last finished delayed update */ atomic64_t tlb_seq; struct dma_fence *last_tlb_flush; + atomic64_t kfd_last_flushed_seq; /* How many times we had to re-generate the page tables */ uint64_t generation; @@ -445,6 +446,10 @@ int amdgpu_vm_clear_freed(struct amdgpu_device *adev, int amdgpu_vm_handle_moved(struct amdgpu_device *adev, struct amdgpu_vm *vm, struct ww_acquire_ctx *ticket); +int amdgpu_vm_flush_compute_tlb(struct amdgpu_device *adev, + struct amdgpu_vm *vm, + uint32_t flush_type, + uint32_t xcc_mask); void amdgpu_vm_bo_base_init(struct amdgpu_vm_bo_base *base, struct amdgpu_vm *vm, struct amdgpu_bo *bo); int amdgpu_vm_update_range(struct amdgpu_device *adev, struct amdgpu_vm *vm, diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_priv.h b/drivers/gpu/drm/amd/amdkfd/kfd_priv.h index 9cc32f577e38..a40f8cfc6aa5 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_priv.h +++ b/drivers/gpu/drm/amd/amdkfd/kfd_priv.h @@ -748,7 +748,6 @@ struct kfd_process_device { /* VM context for GPUVM allocations */ struct file *drm_file; void *drm_priv; - atomic64_t tlb_seq; /* GPUVM allocations storage */ struct idr alloc_idr; @@ -1462,7 +1461,14 @@ void kfd_signal_reset_event(struct kfd_node *dev); void kfd_signal_poison_consumed_event(struct kfd_node *dev, u32 pasid); -void kfd_flush_tlb(struct kfd_process_device *pdd, enum TLB_FLUSH_TYPE type); +static inline void kfd_flush_tlb(struct kfd_process_device *pdd, + enum TLB_FLUSH_TYPE type) +{ + struct amdgpu_device *adev = pdd->dev->adev; + struct amdgpu_vm *vm = drm_priv_to_vm(pdd->drm_priv); + + amdgpu_vm_flush_compute_tlb(adev, vm, type, pdd->dev->xcc_mask); +} static inline bool kfd_flush_tlb_after_unmap(struct kfd_dev *dev) { diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_process.c b/drivers/gpu/drm/amd/amdkfd/kfd_process.c index 7a33e06f5c90..c10d050e1a61 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_process.c +++ b/drivers/gpu/drm/amd/amdkfd/kfd_process.c @@ -1667,7 +1667,6 @@ int kfd_process_device_init_vm(struct kfd_process_device *pdd, return ret; } pdd->drm_priv = drm_file->private_data; - atomic64_set(&pdd->tlb_seq, 0); ret = kfd_process_device_reserve_ib_mem(pdd); if (ret) @@ -2059,36 +2058,6 @@ int kfd_reserved_mem_mmap(struct kfd_node *dev, struct kfd_process *process, KFD_CWSR_TBA_TMA_SIZE, vma->vm_page_prot); } -void kfd_flush_tlb(struct kfd_process_device *pdd, enum TLB_FLUSH_TYPE type) -{ - struct amdgpu_vm *vm = drm_priv_to_vm(pdd->drm_priv); - uint64_t tlb_seq = amdgpu_vm_tlb_seq(vm); - struct kfd_node *dev = pdd->dev; - uint32_t xcc_mask = dev->xcc_mask; - int xcc = 0; - - /* - * It can be that we race and lose here, but that is extremely unlikely - * and the worst thing which could happen is that we flush the changes - * into the TLB once more which is harmless. - */ - if (atomic64_xchg(&pdd->tlb_seq, tlb_seq) == tlb_seq) - return; - - if (dev->dqm->sched_policy == KFD_SCHED_POLICY_NO_HWS) { - /* Nothing to flush until a VMID is assigned, which - * only happens when the first queue is created. - */ - if (pdd->qpd.vmid) - amdgpu_amdkfd_flush_gpu_tlb_vmid(dev->adev, - pdd->qpd.vmid); - } else { - for_each_inst(xcc, xcc_mask) - amdgpu_amdkfd_flush_gpu_tlb_pasid( - dev->adev, pdd->process->pasid, type, xcc); - } -} - /* assumes caller holds process lock. */ int kfd_process_drain_interrupts(struct kfd_process_device *pdd) { -- cgit From fbbcb3f2b7c269c92218f315d22d6ab00524798a Mon Sep 17 00:00:00 2001 From: Ma Jun Date: Thu, 2 Nov 2023 11:19:46 +0800 Subject: drm/amd/pm: Fix return value and drop redundant param Fix the return value and drop redundant parameter of get_asic_baco_capability function. Signed-off-by: Ma Jun Reviewed-by: Kenneth Feng Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/include/kgd_pp_interface.h | 2 +- drivers/gpu/drm/amd/pm/amdgpu_dpm.c | 8 +++----- drivers/gpu/drm/amd/pm/powerplay/amd_powerplay.c | 11 ++++------- drivers/gpu/drm/amd/pm/powerplay/hwmgr/smu7_baco.c | 7 +++---- drivers/gpu/drm/amd/pm/powerplay/hwmgr/smu7_baco.h | 2 +- drivers/gpu/drm/amd/pm/powerplay/hwmgr/smu9_baco.c | 9 ++++----- drivers/gpu/drm/amd/pm/powerplay/hwmgr/smu9_baco.h | 2 +- drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega20_baco.c | 9 ++++----- drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega20_baco.h | 2 +- drivers/gpu/drm/amd/pm/powerplay/inc/hwmgr.h | 2 +- drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c | 12 +++++------- 11 files changed, 28 insertions(+), 38 deletions(-) diff --git a/drivers/gpu/drm/amd/include/kgd_pp_interface.h b/drivers/gpu/drm/amd/include/kgd_pp_interface.h index cd3c40a86029..b14231f470dc 100644 --- a/drivers/gpu/drm/amd/include/kgd_pp_interface.h +++ b/drivers/gpu/drm/amd/include/kgd_pp_interface.h @@ -421,7 +421,7 @@ struct amd_pm_funcs { int (*set_hard_min_dcefclk_by_freq)(void *handle, uint32_t clock); int (*set_hard_min_fclk_by_freq)(void *handle, uint32_t clock); int (*set_min_deep_sleep_dcefclk)(void *handle, uint32_t clock); - int (*get_asic_baco_capability)(void *handle, bool *cap); + bool (*get_asic_baco_capability)(void *handle); int (*get_asic_baco_state)(void *handle, int *state); int (*set_asic_baco_state)(void *handle, int state); int (*get_ppfeature_status)(void *handle, char *buf); diff --git a/drivers/gpu/drm/amd/pm/amdgpu_dpm.c b/drivers/gpu/drm/amd/pm/amdgpu_dpm.c index 08cb79401410..1ae3b81548fa 100644 --- a/drivers/gpu/drm/amd/pm/amdgpu_dpm.c +++ b/drivers/gpu/drm/amd/pm/amdgpu_dpm.c @@ -185,8 +185,7 @@ bool amdgpu_dpm_is_baco_supported(struct amdgpu_device *adev) { const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs; void *pp_handle = adev->powerplay.pp_handle; - bool baco_cap; - int ret = 0; + bool ret; if (!pp_funcs || !pp_funcs->get_asic_baco_capability) return false; @@ -204,12 +203,11 @@ bool amdgpu_dpm_is_baco_supported(struct amdgpu_device *adev) mutex_lock(&adev->pm.mutex); - ret = pp_funcs->get_asic_baco_capability(pp_handle, - &baco_cap); + ret = pp_funcs->get_asic_baco_capability(pp_handle); mutex_unlock(&adev->pm.mutex); - return ret ? false : baco_cap; + return ret; } int amdgpu_dpm_mode2_reset(struct amdgpu_device *adev) diff --git a/drivers/gpu/drm/amd/pm/powerplay/amd_powerplay.c b/drivers/gpu/drm/amd/pm/powerplay/amd_powerplay.c index 914c15387157..aed0e2cefbf9 100644 --- a/drivers/gpu/drm/amd/pm/powerplay/amd_powerplay.c +++ b/drivers/gpu/drm/amd/pm/powerplay/amd_powerplay.c @@ -1371,21 +1371,18 @@ static int pp_set_active_display_count(void *handle, uint32_t count) return phm_set_active_display_count(hwmgr, count); } -static int pp_get_asic_baco_capability(void *handle, bool *cap) +static bool pp_get_asic_baco_capability(void *handle) { struct pp_hwmgr *hwmgr = handle; - *cap = false; if (!hwmgr) - return -EINVAL; + return false; if (!(hwmgr->not_vf && amdgpu_dpm) || !hwmgr->hwmgr_func->get_asic_baco_capability) - return 0; + return false; - hwmgr->hwmgr_func->get_asic_baco_capability(hwmgr, cap); - - return 0; + return hwmgr->hwmgr_func->get_asic_baco_capability(hwmgr); } static int pp_get_asic_baco_state(void *handle, int *state) diff --git a/drivers/gpu/drm/amd/pm/powerplay/hwmgr/smu7_baco.c b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/smu7_baco.c index 044cda005aed..e8a9471c1898 100644 --- a/drivers/gpu/drm/amd/pm/powerplay/hwmgr/smu7_baco.c +++ b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/smu7_baco.c @@ -33,21 +33,20 @@ #include "smu/smu_7_1_2_d.h" #include "smu/smu_7_1_2_sh_mask.h" -int smu7_baco_get_capability(struct pp_hwmgr *hwmgr, bool *cap) +bool smu7_baco_get_capability(struct pp_hwmgr *hwmgr) { struct amdgpu_device *adev = (struct amdgpu_device *)(hwmgr->adev); uint32_t reg; - *cap = false; if (!phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_BACO)) return 0; reg = RREG32(mmCC_BIF_BX_FUSESTRAP0); if (reg & CC_BIF_BX_FUSESTRAP0__STRAP_BIF_PX_CAPABLE_MASK) - *cap = true; + return true; - return 0; + return false; } int smu7_baco_get_state(struct pp_hwmgr *hwmgr, enum BACO_STATE *state) diff --git a/drivers/gpu/drm/amd/pm/powerplay/hwmgr/smu7_baco.h b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/smu7_baco.h index be0d98abb536..73a773f4ce2e 100644 --- a/drivers/gpu/drm/amd/pm/powerplay/hwmgr/smu7_baco.h +++ b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/smu7_baco.h @@ -25,7 +25,7 @@ #include "hwmgr.h" #include "common_baco.h" -extern int smu7_baco_get_capability(struct pp_hwmgr *hwmgr, bool *cap); +extern bool smu7_baco_get_capability(struct pp_hwmgr *hwmgr); extern int smu7_baco_get_state(struct pp_hwmgr *hwmgr, enum BACO_STATE *state); extern int smu7_baco_set_state(struct pp_hwmgr *hwmgr, enum BACO_STATE state); diff --git a/drivers/gpu/drm/amd/pm/powerplay/hwmgr/smu9_baco.c b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/smu9_baco.c index de0a37f7c632..c66ef9741535 100644 --- a/drivers/gpu/drm/amd/pm/powerplay/hwmgr/smu9_baco.c +++ b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/smu9_baco.c @@ -28,14 +28,13 @@ #include "vega10_inc.h" #include "smu9_baco.h" -int smu9_baco_get_capability(struct pp_hwmgr *hwmgr, bool *cap) +bool smu9_baco_get_capability(struct pp_hwmgr *hwmgr) { struct amdgpu_device *adev = (struct amdgpu_device *)(hwmgr->adev); uint32_t reg, data; - *cap = false; if (!phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_BACO)) - return 0; + return false; WREG32(0x12074, 0xFFF0003B); data = RREG32(0x12075); @@ -44,10 +43,10 @@ int smu9_baco_get_capability(struct pp_hwmgr *hwmgr, bool *cap) reg = RREG32_SOC15(NBIF, 0, mmRCC_BIF_STRAP0); if (reg & RCC_BIF_STRAP0__STRAP_PX_CAPABLE_MASK) - *cap = true; + return true; } - return 0; + return false; } int smu9_baco_get_state(struct pp_hwmgr *hwmgr, enum BACO_STATE *state) diff --git a/drivers/gpu/drm/amd/pm/powerplay/hwmgr/smu9_baco.h b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/smu9_baco.h index 84e90f801ac3..9ff7c2ea1b58 100644 --- a/drivers/gpu/drm/amd/pm/powerplay/hwmgr/smu9_baco.h +++ b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/smu9_baco.h @@ -25,7 +25,7 @@ #include "hwmgr.h" #include "common_baco.h" -extern int smu9_baco_get_capability(struct pp_hwmgr *hwmgr, bool *cap); +extern bool smu9_baco_get_capability(struct pp_hwmgr *hwmgr); extern int smu9_baco_get_state(struct pp_hwmgr *hwmgr, enum BACO_STATE *state); #endif diff --git a/drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega20_baco.c b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega20_baco.c index 994c0d374bfa..dad4c80aee58 100644 --- a/drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega20_baco.c +++ b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega20_baco.c @@ -36,23 +36,22 @@ static const struct soc15_baco_cmd_entry clean_baco_tbl[] = { {CMD_WRITE, SOC15_REG_ENTRY(NBIF, 0, mmBIOS_SCRATCH_7), 0, 0, 0, 0}, }; -int vega20_baco_get_capability(struct pp_hwmgr *hwmgr, bool *cap) +bool vega20_baco_get_capability(struct pp_hwmgr *hwmgr) { struct amdgpu_device *adev = (struct amdgpu_device *)(hwmgr->adev); uint32_t reg; - *cap = false; if (!phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_BACO)) - return 0; + return false; if (((RREG32(0x17569) & 0x20000000) >> 29) == 0x1) { reg = RREG32_SOC15(NBIF, 0, mmRCC_BIF_STRAP0); if (reg & RCC_BIF_STRAP0__STRAP_PX_CAPABLE_MASK) - *cap = true; + return true; } - return 0; + return false; } int vega20_baco_get_state(struct pp_hwmgr *hwmgr, enum BACO_STATE *state) diff --git a/drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega20_baco.h b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega20_baco.h index f06471e712dc..bdad9c915631 100644 --- a/drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega20_baco.h +++ b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega20_baco.h @@ -25,7 +25,7 @@ #include "hwmgr.h" #include "common_baco.h" -extern int vega20_baco_get_capability(struct pp_hwmgr *hwmgr, bool *cap); +extern bool vega20_baco_get_capability(struct pp_hwmgr *hwmgr); extern int vega20_baco_get_state(struct pp_hwmgr *hwmgr, enum BACO_STATE *state); extern int vega20_baco_set_state(struct pp_hwmgr *hwmgr, enum BACO_STATE state); extern int vega20_baco_apply_vdci_flush_workaround(struct pp_hwmgr *hwmgr); diff --git a/drivers/gpu/drm/amd/pm/powerplay/inc/hwmgr.h b/drivers/gpu/drm/amd/pm/powerplay/inc/hwmgr.h index 81650727a5de..6f536159df4d 100644 --- a/drivers/gpu/drm/amd/pm/powerplay/inc/hwmgr.h +++ b/drivers/gpu/drm/amd/pm/powerplay/inc/hwmgr.h @@ -351,7 +351,7 @@ struct pp_hwmgr_func { int (*set_hard_min_fclk_by_freq)(struct pp_hwmgr *hwmgr, uint32_t clock); int (*set_hard_min_gfxclk_by_freq)(struct pp_hwmgr *hwmgr, uint32_t clock); int (*set_soft_max_gfxclk_by_freq)(struct pp_hwmgr *hwmgr, uint32_t clock); - int (*get_asic_baco_capability)(struct pp_hwmgr *hwmgr, bool *cap); + bool (*get_asic_baco_capability)(struct pp_hwmgr *hwmgr); int (*get_asic_baco_state)(struct pp_hwmgr *hwmgr, enum BACO_STATE *state); int (*set_asic_baco_state)(struct pp_hwmgr *hwmgr, enum BACO_STATE state); int (*get_ppfeature_status)(struct pp_hwmgr *hwmgr, char *buf); diff --git a/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c b/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c index 1ead323f1c78..37c2605f9b35 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c +++ b/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c @@ -3005,19 +3005,17 @@ static int smu_set_xgmi_pstate(void *handle, return ret; } -static int smu_get_baco_capability(void *handle, bool *cap) +static bool smu_get_baco_capability(void *handle) { struct smu_context *smu = handle; - *cap = false; - if (!smu->pm_enabled) - return 0; + return false; - if (smu->ppt_funcs && smu->ppt_funcs->baco_is_support) - *cap = smu->ppt_funcs->baco_is_support(smu); + if (!smu->ppt_funcs || !smu->ppt_funcs->baco_is_support) + return false; - return 0; + return smu->ppt_funcs->baco_is_support(smu); } static int smu_baco_set_state(void *handle, int state) -- cgit From b5a52d2afe1b75f9d51461bb235ca40735e99fe7 Mon Sep 17 00:00:00 2001 From: Sam James Date: Sun, 5 Nov 2023 16:06:50 +0000 Subject: amdgpu: Adjust kmalloc_array calls for new -Walloc-size MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit GCC 14 introduces a new -Walloc-size included in -Wextra which errors out on various files in drivers/gpu/drm/amd/amdgpu like: ``` amdgpu_amdkfd_gfx_v8.c:241:15: error: allocation of insufficient size ‘4’ for type ‘uint32_t[2]’ {aka ‘unsigned int[2]'} with size ‘8’ [-Werror=alloc-size] ``` This is because each HQD_N_REGS is actually a uint32_t[2]. Move the * 2 to the size argument so GCC sees we're allocating enough. Originally did 'sizeof(uint32_t) * 2' for the size but a friend suggested 'sizeof(**dump)' better communicates the intent. Link: https://lore.kernel.org/all/87wmuwo7i3.fsf@gentoo.org/ Signed-off-by: Sam James Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_arcturus.c | 2 +- drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gc_9_4_3.c | 2 +- drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gfx_v7.c | 4 ++-- drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gfx_v8.c | 4 ++-- drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gfx_v9.c | 4 ++-- 5 files changed, 8 insertions(+), 8 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_arcturus.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_arcturus.c index 625db444df1c..0ba15dcbe4e1 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_arcturus.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_arcturus.c @@ -200,7 +200,7 @@ int kgd_arcturus_hqd_sdma_dump(struct amdgpu_device *adev, #undef HQD_N_REGS #define HQD_N_REGS (19+6+7+10) - *dump = kmalloc_array(HQD_N_REGS * 2, sizeof(uint32_t), GFP_KERNEL); + *dump = kmalloc_array(HQD_N_REGS, sizeof(**dump), GFP_KERNEL); if (*dump == NULL) return -ENOMEM; diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gc_9_4_3.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gc_9_4_3.c index f6598b9e4faa..a5c7259cf2a3 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gc_9_4_3.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gc_9_4_3.c @@ -141,7 +141,7 @@ static int kgd_gfx_v9_4_3_hqd_sdma_dump(struct amdgpu_device *adev, (*dump)[i++][1] = RREG32(addr); \ } while (0) - *dump = kmalloc_array(HQD_N_REGS * 2, sizeof(uint32_t), GFP_KERNEL); + *dump = kmalloc_array(HQD_N_REGS, sizeof(**dump), GFP_KERNEL); if (*dump == NULL) return -ENOMEM; diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gfx_v7.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gfx_v7.c index 6bf448ab3dff..ca4a6b82817f 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gfx_v7.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gfx_v7.c @@ -214,7 +214,7 @@ static int kgd_hqd_dump(struct amdgpu_device *adev, (*dump)[i++][1] = RREG32(addr); \ } while (0) - *dump = kmalloc_array(HQD_N_REGS * 2, sizeof(uint32_t), GFP_KERNEL); + *dump = kmalloc_array(HQD_N_REGS, sizeof(**dump), GFP_KERNEL); if (*dump == NULL) return -ENOMEM; @@ -301,7 +301,7 @@ static int kgd_hqd_sdma_dump(struct amdgpu_device *adev, #undef HQD_N_REGS #define HQD_N_REGS (19+4) - *dump = kmalloc_array(HQD_N_REGS * 2, sizeof(uint32_t), GFP_KERNEL); + *dump = kmalloc_array(HQD_N_REGS, sizeof(**dump), GFP_KERNEL); if (*dump == NULL) return -ENOMEM; diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gfx_v8.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gfx_v8.c index cd06e4a6d1da..0f3e2944edd7 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gfx_v8.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gfx_v8.c @@ -238,7 +238,7 @@ static int kgd_hqd_dump(struct amdgpu_device *adev, (*dump)[i++][1] = RREG32(addr); \ } while (0) - *dump = kmalloc_array(HQD_N_REGS * 2, sizeof(uint32_t), GFP_KERNEL); + *dump = kmalloc_array(HQD_N_REGS, sizeof(**dump), GFP_KERNEL); if (*dump == NULL) return -ENOMEM; @@ -324,7 +324,7 @@ static int kgd_hqd_sdma_dump(struct amdgpu_device *adev, #undef HQD_N_REGS #define HQD_N_REGS (19+4+2+3+7) - *dump = kmalloc_array(HQD_N_REGS * 2, sizeof(uint32_t), GFP_KERNEL); + *dump = kmalloc_array(HQD_N_REGS, sizeof(**dump), GFP_KERNEL); if (*dump == NULL) return -ENOMEM; diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gfx_v9.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gfx_v9.c index 00fbc0f44c92..5a35a8ca8922 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gfx_v9.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gfx_v9.c @@ -363,7 +363,7 @@ int kgd_gfx_v9_hqd_dump(struct amdgpu_device *adev, (*dump)[i++][1] = RREG32(addr); \ } while (0) - *dump = kmalloc_array(HQD_N_REGS * 2, sizeof(uint32_t), GFP_KERNEL); + *dump = kmalloc_array(HQD_N_REGS, sizeof(**dump), GFP_KERNEL); if (*dump == NULL) return -ENOMEM; @@ -460,7 +460,7 @@ static int kgd_hqd_sdma_dump(struct amdgpu_device *adev, #undef HQD_N_REGS #define HQD_N_REGS (19+6+7+10) - *dump = kmalloc_array(HQD_N_REGS * 2, sizeof(uint32_t), GFP_KERNEL); + *dump = kmalloc_array(HQD_N_REGS, sizeof(**dump), GFP_KERNEL); if (*dump == NULL) return -ENOMEM; -- cgit From d8a3813713c3843351123138c8b191142c266521 Mon Sep 17 00:00:00 2001 From: Abhinav Singh Date: Fri, 3 Nov 2023 21:20:13 +0530 Subject: drm/radeon: Fix warning using plain integer as NULL sparse static analysis tools generate a warning with this message "Using plain integer as NULL pointer". In this case this warning is being shown because we are trying to intialize a pointer to NULL using integer value 0. Signed-off-by: Abhinav Singh Signed-off-by: Alex Deucher --- drivers/gpu/drm/radeon/clearstate_evergreen.h | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/radeon/clearstate_evergreen.h b/drivers/gpu/drm/radeon/clearstate_evergreen.h index 63a1ffbb3ced..3b645558f133 100644 --- a/drivers/gpu/drm/radeon/clearstate_evergreen.h +++ b/drivers/gpu/drm/radeon/clearstate_evergreen.h @@ -1049,7 +1049,7 @@ static const struct cs_extent_def SECT_CONTEXT_defs[] = {SECT_CONTEXT_def_5, 0x0000a29e, 5 }, {SECT_CONTEXT_def_6, 0x0000a2a5, 56 }, {SECT_CONTEXT_def_7, 0x0000a2de, 290 }, - { 0, 0, 0 } + { NULL, 0, 0 } }; static const u32 SECT_CLEAR_def_1[] = { @@ -1060,7 +1060,7 @@ static const u32 SECT_CLEAR_def_1[] = static const struct cs_extent_def SECT_CLEAR_defs[] = { {SECT_CLEAR_def_1, 0x0000ffc0, 3 }, - { 0, 0, 0 } + { NULL, 0, 0 } }; static const u32 SECT_CTRLCONST_def_1[] = { @@ -1070,11 +1070,11 @@ static const u32 SECT_CTRLCONST_def_1[] = static const struct cs_extent_def SECT_CTRLCONST_defs[] = { {SECT_CTRLCONST_def_1, 0x0000f3fc, 2 }, - { 0, 0, 0 } + { NULL, 0, 0 } }; static const struct cs_section_def evergreen_cs_data[] = { { SECT_CONTEXT_defs, SECT_CONTEXT }, { SECT_CLEAR_defs, SECT_CLEAR }, { SECT_CTRLCONST_defs, SECT_CTRLCONST }, - { 0, SECT_NONE } + { NULL, SECT_NONE } }; -- cgit From 857c838c782728318c581cb656fddd74faa89ad2 Mon Sep 17 00:00:00 2001 From: Ma Jun Date: Fri, 3 Nov 2023 09:48:06 +0800 Subject: drm/amd/pm: Move some functions to smu_v13_0.c as generic code Use generic functions and remove the duplicate code Signed-off-by: Ma Jun Reviewed-by: Yang Wang Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0.c | 38 ++++++++++++++++------ .../gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_0_ppt.c | 36 ++------------------ .../gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_7_ppt.c | 36 ++------------------ 3 files changed, 32 insertions(+), 78 deletions(-) diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0.c b/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0.c index cf1b84060bc3..b446f860baf6 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0.c +++ b/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0.c @@ -2283,22 +2283,40 @@ int smu_v13_0_baco_set_state(struct smu_context *smu, int smu_v13_0_baco_enter(struct smu_context *smu) { - int ret = 0; - - ret = smu_v13_0_baco_set_state(smu, - SMU_BACO_STATE_ENTER); - if (ret) - return ret; + struct smu_baco_context *smu_baco = &smu->smu_baco; + struct amdgpu_device *adev = smu->adev; + int ret; - msleep(10); + if (adev->in_runpm && smu_cmn_is_audio_func_enabled(adev)) { + return smu_v13_0_baco_set_armd3_sequence(smu, + (smu_baco->maco_support && amdgpu_runtime_pm != 1) ? + BACO_SEQ_BAMACO : BACO_SEQ_BACO); + } else { + ret = smu_v13_0_baco_set_state(smu, SMU_BACO_STATE_ENTER); + if (!ret) + usleep_range(10000, 11000); - return ret; + return ret; + } } int smu_v13_0_baco_exit(struct smu_context *smu) { - return smu_v13_0_baco_set_state(smu, - SMU_BACO_STATE_EXIT); + struct amdgpu_device *adev = smu->adev; + int ret; + + if (adev->in_runpm && smu_cmn_is_audio_func_enabled(adev)) { + /* Wait for PMFW handling for the Dstate change */ + usleep_range(10000, 11000); + ret = smu_v13_0_baco_set_armd3_sequence(smu, BACO_SEQ_ULPS); + } else { + ret = smu_v13_0_baco_set_state(smu, SMU_BACO_STATE_EXIT); + } + + if (!ret) + adev->gfx.is_poweron = false; + + return ret; } int smu_v13_0_set_gfx_power_up_by_imu(struct smu_context *smu) diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_0_ppt.c b/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_0_ppt.c index 82c4e1f1c6f0..a4debd7ab8bd 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_0_ppt.c +++ b/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_0_ppt.c @@ -2558,38 +2558,6 @@ static int smu_v13_0_0_set_power_profile_mode(struct smu_context *smu, NULL); } -static int smu_v13_0_0_baco_enter(struct smu_context *smu) -{ - struct smu_baco_context *smu_baco = &smu->smu_baco; - struct amdgpu_device *adev = smu->adev; - - if (adev->in_runpm && smu_cmn_is_audio_func_enabled(adev)) - return smu_v13_0_baco_set_armd3_sequence(smu, - (smu_baco->maco_support && amdgpu_runtime_pm != 1) ? - BACO_SEQ_BAMACO : BACO_SEQ_BACO); - else - return smu_v13_0_baco_enter(smu); -} - -static int smu_v13_0_0_baco_exit(struct smu_context *smu) -{ - struct amdgpu_device *adev = smu->adev; - int ret; - - if (adev->in_runpm && smu_cmn_is_audio_func_enabled(adev)) { - /* Wait for PMFW handling for the Dstate change */ - usleep_range(10000, 11000); - ret = smu_v13_0_baco_set_armd3_sequence(smu, BACO_SEQ_ULPS); - } else { - ret = smu_v13_0_baco_exit(smu); - } - - if (!ret) - adev->gfx.is_poweron = false; - - return ret; -} - static bool smu_v13_0_0_is_mode1_reset_supported(struct smu_context *smu) { struct amdgpu_device *adev = smu->adev; @@ -3037,8 +3005,8 @@ static const struct pptable_funcs smu_v13_0_0_ppt_funcs = { .baco_is_support = smu_v13_0_baco_is_support, .baco_get_state = smu_v13_0_baco_get_state, .baco_set_state = smu_v13_0_baco_set_state, - .baco_enter = smu_v13_0_0_baco_enter, - .baco_exit = smu_v13_0_0_baco_exit, + .baco_enter = smu_v13_0_baco_enter, + .baco_exit = smu_v13_0_baco_exit, .mode1_reset_is_support = smu_v13_0_0_is_mode1_reset_supported, .mode1_reset = smu_v13_0_0_mode1_reset, .mode2_reset = smu_v13_0_0_mode2_reset, diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_7_ppt.c b/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_7_ppt.c index 81eafed76045..f5596f031d00 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_7_ppt.c +++ b/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_7_ppt.c @@ -2515,38 +2515,6 @@ static int smu_v13_0_7_set_mp1_state(struct smu_context *smu, return ret; } -static int smu_v13_0_7_baco_enter(struct smu_context *smu) -{ - struct smu_baco_context *smu_baco = &smu->smu_baco; - struct amdgpu_device *adev = smu->adev; - - if (adev->in_runpm && smu_cmn_is_audio_func_enabled(adev)) - return smu_v13_0_baco_set_armd3_sequence(smu, - (smu_baco->maco_support && amdgpu_runtime_pm != 1) ? - BACO_SEQ_BAMACO : BACO_SEQ_BACO); - else - return smu_v13_0_baco_enter(smu); -} - -static int smu_v13_0_7_baco_exit(struct smu_context *smu) -{ - struct amdgpu_device *adev = smu->adev; - int ret; - - if (adev->in_runpm && smu_cmn_is_audio_func_enabled(adev)) { - /* Wait for PMFW handling for the Dstate change */ - usleep_range(10000, 11000); - ret = smu_v13_0_baco_set_armd3_sequence(smu, BACO_SEQ_ULPS); - } else { - ret = smu_v13_0_baco_exit(smu); - } - - if (!ret) - adev->gfx.is_poweron = false; - - return ret; -} - static bool smu_v13_0_7_is_mode1_reset_supported(struct smu_context *smu) { struct amdgpu_device *adev = smu->adev; @@ -2628,8 +2596,8 @@ static const struct pptable_funcs smu_v13_0_7_ppt_funcs = { .baco_is_support = smu_v13_0_baco_is_support, .baco_get_state = smu_v13_0_baco_get_state, .baco_set_state = smu_v13_0_baco_set_state, - .baco_enter = smu_v13_0_7_baco_enter, - .baco_exit = smu_v13_0_7_baco_exit, + .baco_enter = smu_v13_0_baco_enter, + .baco_exit = smu_v13_0_baco_exit, .mode1_reset_is_support = smu_v13_0_7_is_mode1_reset_supported, .mode1_reset = smu_v13_0_mode1_reset, .set_mp1_state = smu_v13_0_7_set_mp1_state, -- cgit From 5ce8eccd53a357f91f2c2fe29918f9c65a1fe970 Mon Sep 17 00:00:00 2001 From: Ma Jun Date: Wed, 8 Nov 2023 16:00:30 +0800 Subject: drm/amd/pm: Make smu_v13_0_baco_set_armd3_sequence() static smu_v13_0_baco_set_armd3_sequence is not used by other files, so make it as static type. Signed-off-by: Ma Jun Reviewed-by: Yang Wang Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/pm/swsmu/inc/smu_v13_0.h | 3 --- drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0.c | 2 +- 2 files changed, 1 insertion(+), 4 deletions(-) diff --git a/drivers/gpu/drm/amd/pm/swsmu/inc/smu_v13_0.h b/drivers/gpu/drm/amd/pm/swsmu/inc/smu_v13_0.h index 95cb919718ae..48f5926d8153 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/inc/smu_v13_0.h +++ b/drivers/gpu/drm/amd/pm/swsmu/inc/smu_v13_0.h @@ -210,9 +210,6 @@ int smu_v13_0_set_azalia_d3_pme(struct smu_context *smu); int smu_v13_0_get_max_sustainable_clocks_by_dc(struct smu_context *smu, struct pp_smu_nv_clock_table *max_clocks); -int smu_v13_0_baco_set_armd3_sequence(struct smu_context *smu, - enum smu_baco_seq baco_seq); - bool smu_v13_0_baco_is_support(struct smu_context *smu); enum smu_baco_state smu_v13_0_baco_get_state(struct smu_context *smu); diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0.c b/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0.c index b446f860baf6..86fc7273d588 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0.c +++ b/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0.c @@ -2199,7 +2199,7 @@ int smu_v13_0_gfx_ulv_control(struct smu_context *smu, return ret; } -int smu_v13_0_baco_set_armd3_sequence(struct smu_context *smu, +static int smu_v13_0_baco_set_armd3_sequence(struct smu_context *smu, enum smu_baco_seq baco_seq) { struct smu_baco_context *smu_baco = &smu->smu_baco; -- cgit From 8a1de314d1890793bbf9e77542574ceda007564e Mon Sep 17 00:00:00 2001 From: Srinivasan Shanmugam Date: Wed, 2 Aug 2023 07:49:14 +0530 Subject: drm/amdgpu: Refactor 'amdgpu_connector_dvi_detect' in amdgpu_connectors.c MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fixes the below: WARNING: Prefer 'unsigned int' to bare use of 'unsigned' WARNING: Missing a blank line after declarations WARNING: Too many leading tabs - consider code refactoring + if (list_connector->connector_type != DRM_MODE_CONNECTOR_VGA) { WARNING: Too many leading tabs - consider code refactoring + if (!amdgpu_display_hpd_sense(adev, amdgpu_connector->hpd.hpd)) { Cc: Guchun Chen Cc: Christian König Cc: Alex Deucher Cc: "Pan, Xinhui" Cc: Rodrigo Siqueira Cc: Aurabindo Pillai Signed-off-by: Srinivasan Shanmugam Acked-by: Guchun Chen Reviewed-by: Aurabindo Pillai Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_connectors.c | 69 ++++++++++++++++---------- 1 file changed, 42 insertions(+), 27 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_connectors.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_connectors.c index 7473a42f7d45..96f63fd39b9e 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_connectors.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_connectors.c @@ -103,7 +103,7 @@ int amdgpu_connector_get_monitor_bpc(struct drm_connector *connector) struct amdgpu_connector *amdgpu_connector = to_amdgpu_connector(connector); struct amdgpu_connector_atom_dig *dig_connector; int bpc = 8; - unsigned mode_clock, max_tmds_clock; + unsigned int mode_clock, max_tmds_clock; switch (connector->connector_type) { case DRM_MODE_CONNECTOR_DVII: @@ -255,6 +255,7 @@ struct edid *amdgpu_connector_edid(struct drm_connector *connector) return amdgpu_connector->edid; } else if (edid_blob) { struct edid *edid = kmemdup(edid_blob->data, edid_blob->length, GFP_KERNEL); + if (edid) amdgpu_connector->edid = edid; } @@ -581,6 +582,7 @@ static int amdgpu_connector_set_property(struct drm_connector *connector, amdgpu_encoder = to_amdgpu_encoder(connector->encoder); } else { const struct drm_connector_helper_funcs *connector_funcs = connector->helper_private; + amdgpu_encoder = to_amdgpu_encoder(connector_funcs->best_encoder(connector)); } @@ -797,6 +799,7 @@ static int amdgpu_connector_set_lcd_property(struct drm_connector *connector, amdgpu_encoder = to_amdgpu_encoder(connector->encoder); else { const struct drm_connector_helper_funcs *connector_funcs = connector->helper_private; + amdgpu_encoder = to_amdgpu_encoder(connector_funcs->best_encoder(connector)); } @@ -979,6 +982,41 @@ amdgpu_connector_check_hpd_status_unchanged(struct drm_connector *connector) return false; } +static void amdgpu_connector_shared_ddc(enum drm_connector_status *status, + struct drm_connector *connector, + struct amdgpu_connector *amdgpu_connector) +{ + struct drm_connector *list_connector; + struct drm_connector_list_iter iter; + struct amdgpu_connector *list_amdgpu_connector; + struct drm_device *dev = connector->dev; + struct amdgpu_device *adev = drm_to_adev(dev); + + if (amdgpu_connector->shared_ddc && *status == connector_status_connected) { + drm_connector_list_iter_begin(dev, &iter); + drm_for_each_connector_iter(list_connector, + &iter) { + if (connector == list_connector) + continue; + list_amdgpu_connector = to_amdgpu_connector(list_connector); + if (list_amdgpu_connector->shared_ddc && + list_amdgpu_connector->ddc_bus->rec.i2c_id == + amdgpu_connector->ddc_bus->rec.i2c_id) { + /* cases where both connectors are digital */ + if (list_connector->connector_type != DRM_MODE_CONNECTOR_VGA) { + /* hpd is our only option in this case */ + if (!amdgpu_display_hpd_sense(adev, + amdgpu_connector->hpd.hpd)) { + amdgpu_connector_free_edid(connector); + *status = connector_status_disconnected; + } + } + } + } + drm_connector_list_iter_end(&iter); + } +} + /* * DVI is complicated * Do a DDC probe, if DDC probe passes, get the full EDID so @@ -1065,32 +1103,7 @@ amdgpu_connector_dvi_detect(struct drm_connector *connector, bool force) * DDC line. The latter is more complex because with DVI<->HDMI adapters * you don't really know what's connected to which port as both are digital. */ - if (amdgpu_connector->shared_ddc && (ret == connector_status_connected)) { - struct drm_connector *list_connector; - struct drm_connector_list_iter iter; - struct amdgpu_connector *list_amdgpu_connector; - - drm_connector_list_iter_begin(dev, &iter); - drm_for_each_connector_iter(list_connector, - &iter) { - if (connector == list_connector) - continue; - list_amdgpu_connector = to_amdgpu_connector(list_connector); - if (list_amdgpu_connector->shared_ddc && - (list_amdgpu_connector->ddc_bus->rec.i2c_id == - amdgpu_connector->ddc_bus->rec.i2c_id)) { - /* cases where both connectors are digital */ - if (list_connector->connector_type != DRM_MODE_CONNECTOR_VGA) { - /* hpd is our only option in this case */ - if (!amdgpu_display_hpd_sense(adev, amdgpu_connector->hpd.hpd)) { - amdgpu_connector_free_edid(connector); - ret = connector_status_disconnected; - } - } - } - } - drm_connector_list_iter_end(&iter); - } + amdgpu_connector_shared_ddc(&ret, connector, amdgpu_connector); } } @@ -1192,6 +1205,7 @@ amdgpu_connector_dvi_encoder(struct drm_connector *connector) static void amdgpu_connector_dvi_force(struct drm_connector *connector) { struct amdgpu_connector *amdgpu_connector = to_amdgpu_connector(connector); + if (connector->force == DRM_FORCE_ON) amdgpu_connector->use_digital = false; if (connector->force == DRM_FORCE_ON_DIGITAL) @@ -1426,6 +1440,7 @@ amdgpu_connector_dp_detect(struct drm_connector *connector, bool force) ret = connector_status_connected; else if (amdgpu_connector->dac_load_detect) { /* try load detection */ const struct drm_encoder_helper_funcs *encoder_funcs = encoder->helper_private; + ret = encoder_funcs->detect(encoder, connector); } } -- cgit From f4fac4163c2f99aada9cc60292f2ea377afe6c71 Mon Sep 17 00:00:00 2001 From: Laurent Morichetti Date: Wed, 8 Nov 2023 16:16:18 -0800 Subject: drm/amdkfd: Clear the VALU exception state in the trap handler The trap handler could be entered with pending VALU exceptions, so clear the exception state before issuing vector instructions. Reviewed-by: Jay Cornwall Acked-by: Alex Deucher Signed-off-by: Laurent Morichetti Tested-by: Lancelot Six Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdkfd/cwsr_trap_handler.h | 664 ++++++++++----------- .../gpu/drm/amd/amdkfd/cwsr_trap_handler_gfx10.asm | 6 + 2 files changed, 338 insertions(+), 332 deletions(-) diff --git a/drivers/gpu/drm/amd/amdkfd/cwsr_trap_handler.h b/drivers/gpu/drm/amd/amdkfd/cwsr_trap_handler.h index d7cd5fa313ff..df75863393fc 100644 --- a/drivers/gpu/drm/amd/amdkfd/cwsr_trap_handler.h +++ b/drivers/gpu/drm/amd/amdkfd/cwsr_trap_handler.h @@ -2069,7 +2069,7 @@ static const uint32_t cwsr_trap_aldebaran_hex[] = { }; static const uint32_t cwsr_trap_gfx10_hex[] = { - 0xbf820001, 0xbf820220, + 0xbf820001, 0xbf820221, 0xb0804004, 0xb978f802, 0x8a78ff78, 0x00020006, 0xb97bf803, 0x876eff78, @@ -2118,391 +2118,391 @@ static const uint32_t cwsr_trap_gfx10_hex[] = { 0xbf900004, 0xbf8cc07f, 0x877aff7f, 0x04000000, 0x8f7a857a, 0x886d7a6d, - 0xbefa037e, 0x877bff7f, - 0x0000ffff, 0xbefe03c1, - 0xbeff03c1, 0xdc5f8000, - 0x007a0000, 0x7e000280, - 0xbefe037a, 0xbeff037b, - 0xb97b02dc, 0x8f7b997b, - 0xb97a3a05, 0x807a817a, - 0xbf0d997b, 0xbf850002, - 0x8f7a897a, 0xbf820001, - 0x8f7a8a7a, 0xb97b1e06, - 0x8f7b8a7b, 0x807a7b7a, + 0x7e008200, 0xbefa037e, 0x877bff7f, 0x0000ffff, - 0x807aff7a, 0x00000200, - 0x807a7e7a, 0x827b807b, - 0xd7610000, 0x00010870, - 0xd7610000, 0x00010a71, - 0xd7610000, 0x00010c72, - 0xd7610000, 0x00010e73, - 0xd7610000, 0x00011074, - 0xd7610000, 0x00011275, - 0xd7610000, 0x00011476, - 0xd7610000, 0x00011677, - 0xd7610000, 0x00011a79, - 0xd7610000, 0x00011c7e, - 0xd7610000, 0x00011e7f, - 0xbefe03ff, 0x00003fff, - 0xbeff0380, 0xdc5f8040, - 0x007a0000, 0xd760007a, - 0x00011d00, 0xd760007b, - 0x00011f00, 0xbefe037a, - 0xbeff037b, 0xbef4037e, - 0x8775ff7f, 0x0000ffff, - 0x8875ff75, 0x00040000, - 0xbef60380, 0xbef703ff, - 0x10807fac, 0xbef1037c, - 0xbef00380, 0xb97302dc, - 0x8f739973, 0xbefe03c1, - 0x907c9973, 0x877c817c, - 0xbf06817c, 0xbf850002, - 0xbeff0380, 0xbf820002, - 0xbeff03c1, 0xbf820009, + 0xbefe03c1, 0xbeff03c1, + 0xdc5f8000, 0x007a0000, + 0x7e000280, 0xbefe037a, + 0xbeff037b, 0xb97b02dc, + 0x8f7b997b, 0xb97a3a05, + 0x807a817a, 0xbf0d997b, + 0xbf850002, 0x8f7a897a, + 0xbf820001, 0x8f7a8a7a, + 0xb97b1e06, 0x8f7b8a7b, + 0x807a7b7a, 0x877bff7f, + 0x0000ffff, 0x807aff7a, + 0x00000200, 0x807a7e7a, + 0x827b807b, 0xd7610000, + 0x00010870, 0xd7610000, + 0x00010a71, 0xd7610000, + 0x00010c72, 0xd7610000, + 0x00010e73, 0xd7610000, + 0x00011074, 0xd7610000, + 0x00011275, 0xd7610000, + 0x00011476, 0xd7610000, + 0x00011677, 0xd7610000, + 0x00011a79, 0xd7610000, + 0x00011c7e, 0xd7610000, + 0x00011e7f, 0xbefe03ff, + 0x00003fff, 0xbeff0380, + 0xdc5f8040, 0x007a0000, + 0xd760007a, 0x00011d00, + 0xd760007b, 0x00011f00, + 0xbefe037a, 0xbeff037b, + 0xbef4037e, 0x8775ff7f, + 0x0000ffff, 0x8875ff75, + 0x00040000, 0xbef60380, + 0xbef703ff, 0x10807fac, + 0xbef1037c, 0xbef00380, + 0xb97302dc, 0x8f739973, + 0xbefe03c1, 0x907c9973, + 0x877c817c, 0xbf06817c, + 0xbf850002, 0xbeff0380, + 0xbf820002, 0xbeff03c1, + 0xbf820009, 0xbef603ff, + 0x01000000, 0xe0704080, + 0x705d0100, 0xe0704100, + 0x705d0200, 0xe0704180, + 0x705d0300, 0xbf820008, 0xbef603ff, 0x01000000, - 0xe0704080, 0x705d0100, - 0xe0704100, 0x705d0200, - 0xe0704180, 0x705d0300, - 0xbf820008, 0xbef603ff, - 0x01000000, 0xe0704100, - 0x705d0100, 0xe0704200, - 0x705d0200, 0xe0704300, - 0x705d0300, 0xb9703a05, - 0x80708170, 0xbf0d9973, - 0xbf850002, 0x8f708970, - 0xbf820001, 0x8f708a70, - 0xb97a1e06, 0x8f7a8a7a, - 0x80707a70, 0x8070ff70, - 0x00000200, 0xbef603ff, - 0x01000000, 0x7e000280, - 0x7e020280, 0x7e040280, - 0xbefc0380, 0xd7610002, - 0x0000f871, 0x807c817c, - 0xd7610002, 0x0000f86c, - 0x807c817c, 0x8a7aff6d, - 0x80000000, 0xd7610002, - 0x0000f87a, 0x807c817c, - 0xd7610002, 0x0000f86e, - 0x807c817c, 0xd7610002, - 0x0000f86f, 0x807c817c, - 0xd7610002, 0x0000f878, - 0x807c817c, 0xb97af803, - 0xd7610002, 0x0000f87a, - 0x807c817c, 0xd7610002, - 0x0000f87b, 0x807c817c, - 0xb971f801, 0xd7610002, - 0x0000f871, 0x807c817c, - 0xb971f814, 0xd7610002, - 0x0000f871, 0x807c817c, - 0xb971f815, 0xd7610002, - 0x0000f871, 0x807c817c, - 0xbefe03ff, 0x0000ffff, - 0xbeff0380, 0xe0704000, - 0x705d0200, 0xbefe03c1, + 0xe0704100, 0x705d0100, + 0xe0704200, 0x705d0200, + 0xe0704300, 0x705d0300, 0xb9703a05, 0x80708170, 0xbf0d9973, 0xbf850002, 0x8f708970, 0xbf820001, 0x8f708a70, 0xb97a1e06, 0x8f7a8a7a, 0x80707a70, + 0x8070ff70, 0x00000200, 0xbef603ff, 0x01000000, - 0xbef90380, 0xbefc0380, - 0xbf800000, 0xbe802f00, - 0xbe822f02, 0xbe842f04, - 0xbe862f06, 0xbe882f08, - 0xbe8a2f0a, 0xbe8c2f0c, - 0xbe8e2f0e, 0xd7610002, - 0x0000f200, 0x80798179, - 0xd7610002, 0x0000f201, + 0x7e000280, 0x7e020280, + 0x7e040280, 0xbefc0380, + 0xd7610002, 0x0000f871, + 0x807c817c, 0xd7610002, + 0x0000f86c, 0x807c817c, + 0x8a7aff6d, 0x80000000, + 0xd7610002, 0x0000f87a, + 0x807c817c, 0xd7610002, + 0x0000f86e, 0x807c817c, + 0xd7610002, 0x0000f86f, + 0x807c817c, 0xd7610002, + 0x0000f878, 0x807c817c, + 0xb97af803, 0xd7610002, + 0x0000f87a, 0x807c817c, + 0xd7610002, 0x0000f87b, + 0x807c817c, 0xb971f801, + 0xd7610002, 0x0000f871, + 0x807c817c, 0xb971f814, + 0xd7610002, 0x0000f871, + 0x807c817c, 0xb971f815, + 0xd7610002, 0x0000f871, + 0x807c817c, 0xbefe03ff, + 0x0000ffff, 0xbeff0380, + 0xe0704000, 0x705d0200, + 0xbefe03c1, 0xb9703a05, + 0x80708170, 0xbf0d9973, + 0xbf850002, 0x8f708970, + 0xbf820001, 0x8f708a70, + 0xb97a1e06, 0x8f7a8a7a, + 0x80707a70, 0xbef603ff, + 0x01000000, 0xbef90380, + 0xbefc0380, 0xbf800000, + 0xbe802f00, 0xbe822f02, + 0xbe842f04, 0xbe862f06, + 0xbe882f08, 0xbe8a2f0a, + 0xbe8c2f0c, 0xbe8e2f0e, + 0xd7610002, 0x0000f200, 0x80798179, 0xd7610002, - 0x0000f202, 0x80798179, - 0xd7610002, 0x0000f203, + 0x0000f201, 0x80798179, + 0xd7610002, 0x0000f202, 0x80798179, 0xd7610002, - 0x0000f204, 0x80798179, - 0xd7610002, 0x0000f205, + 0x0000f203, 0x80798179, + 0xd7610002, 0x0000f204, 0x80798179, 0xd7610002, - 0x0000f206, 0x80798179, - 0xd7610002, 0x0000f207, + 0x0000f205, 0x80798179, + 0xd7610002, 0x0000f206, 0x80798179, 0xd7610002, - 0x0000f208, 0x80798179, - 0xd7610002, 0x0000f209, + 0x0000f207, 0x80798179, + 0xd7610002, 0x0000f208, 0x80798179, 0xd7610002, - 0x0000f20a, 0x80798179, - 0xd7610002, 0x0000f20b, + 0x0000f209, 0x80798179, + 0xd7610002, 0x0000f20a, 0x80798179, 0xd7610002, - 0x0000f20c, 0x80798179, - 0xd7610002, 0x0000f20d, + 0x0000f20b, 0x80798179, + 0xd7610002, 0x0000f20c, 0x80798179, 0xd7610002, - 0x0000f20e, 0x80798179, - 0xd7610002, 0x0000f20f, - 0x80798179, 0xbf06a079, - 0xbf840006, 0xe0704000, - 0x705d0200, 0x8070ff70, - 0x00000080, 0xbef90380, - 0x7e040280, 0x807c907c, - 0xbf0aff7c, 0x00000060, - 0xbf85ffbc, 0xbe802f00, - 0xbe822f02, 0xbe842f04, - 0xbe862f06, 0xbe882f08, - 0xbe8a2f0a, 0xd7610002, - 0x0000f200, 0x80798179, - 0xd7610002, 0x0000f201, + 0x0000f20d, 0x80798179, + 0xd7610002, 0x0000f20e, 0x80798179, 0xd7610002, - 0x0000f202, 0x80798179, - 0xd7610002, 0x0000f203, + 0x0000f20f, 0x80798179, + 0xbf06a079, 0xbf840006, + 0xe0704000, 0x705d0200, + 0x8070ff70, 0x00000080, + 0xbef90380, 0x7e040280, + 0x807c907c, 0xbf0aff7c, + 0x00000060, 0xbf85ffbc, + 0xbe802f00, 0xbe822f02, + 0xbe842f04, 0xbe862f06, + 0xbe882f08, 0xbe8a2f0a, + 0xd7610002, 0x0000f200, 0x80798179, 0xd7610002, - 0x0000f204, 0x80798179, - 0xd7610002, 0x0000f205, + 0x0000f201, 0x80798179, + 0xd7610002, 0x0000f202, 0x80798179, 0xd7610002, - 0x0000f206, 0x80798179, - 0xd7610002, 0x0000f207, + 0x0000f203, 0x80798179, + 0xd7610002, 0x0000f204, 0x80798179, 0xd7610002, - 0x0000f208, 0x80798179, - 0xd7610002, 0x0000f209, + 0x0000f205, 0x80798179, + 0xd7610002, 0x0000f206, 0x80798179, 0xd7610002, - 0x0000f20a, 0x80798179, - 0xd7610002, 0x0000f20b, - 0x80798179, 0xe0704000, - 0x705d0200, 0xbefe03c1, - 0x907c9973, 0x877c817c, - 0xbf06817c, 0xbf850002, - 0xbeff0380, 0xbf820001, - 0xbeff03c1, 0xb97b4306, - 0x877bc17b, 0xbf840044, - 0xbf8a0000, 0x877aff6d, - 0x80000000, 0xbf840040, - 0x8f7b867b, 0x8f7b827b, - 0xbef6037b, 0xb9703a05, - 0x80708170, 0xbf0d9973, - 0xbf850002, 0x8f708970, - 0xbf820001, 0x8f708a70, - 0xb97a1e06, 0x8f7a8a7a, - 0x80707a70, 0x8070ff70, - 0x00000200, 0x8070ff70, - 0x00000080, 0xbef603ff, - 0x01000000, 0xd7650000, - 0x000100c1, 0xd7660000, - 0x000200c1, 0x16000084, - 0x907c9973, 0x877c817c, - 0xbf06817c, 0xbefc0380, - 0xbf850012, 0xbe8303ff, - 0x00000080, 0xbf800000, - 0xbf800000, 0xbf800000, - 0xd8d80000, 0x01000000, - 0xbf8c0000, 0xe0704000, - 0x705d0100, 0x807c037c, - 0x80700370, 0xd5250000, - 0x0001ff00, 0x00000080, - 0xbf0a7b7c, 0xbf85fff4, - 0xbf820011, 0xbe8303ff, - 0x00000100, 0xbf800000, - 0xbf800000, 0xbf800000, - 0xd8d80000, 0x01000000, - 0xbf8c0000, 0xe0704000, - 0x705d0100, 0x807c037c, - 0x80700370, 0xd5250000, - 0x0001ff00, 0x00000100, - 0xbf0a7b7c, 0xbf85fff4, + 0x0000f207, 0x80798179, + 0xd7610002, 0x0000f208, + 0x80798179, 0xd7610002, + 0x0000f209, 0x80798179, + 0xd7610002, 0x0000f20a, + 0x80798179, 0xd7610002, + 0x0000f20b, 0x80798179, + 0xe0704000, 0x705d0200, 0xbefe03c1, 0x907c9973, 0x877c817c, 0xbf06817c, - 0xbf850004, 0xbef003ff, - 0x00000200, 0xbeff0380, - 0xbf820003, 0xbef003ff, - 0x00000400, 0xbeff03c1, - 0xb97b3a05, 0x807b817b, - 0x8f7b827b, 0x907c9973, + 0xbf850002, 0xbeff0380, + 0xbf820001, 0xbeff03c1, + 0xb97b4306, 0x877bc17b, + 0xbf840044, 0xbf8a0000, + 0x877aff6d, 0x80000000, + 0xbf840040, 0x8f7b867b, + 0x8f7b827b, 0xbef6037b, + 0xb9703a05, 0x80708170, + 0xbf0d9973, 0xbf850002, + 0x8f708970, 0xbf820001, + 0x8f708a70, 0xb97a1e06, + 0x8f7a8a7a, 0x80707a70, + 0x8070ff70, 0x00000200, + 0x8070ff70, 0x00000080, + 0xbef603ff, 0x01000000, + 0xd7650000, 0x000100c1, + 0xd7660000, 0x000200c1, + 0x16000084, 0x907c9973, 0x877c817c, 0xbf06817c, - 0xbf850017, 0xbef603ff, - 0x01000000, 0xbefc0384, - 0xbf0a7b7c, 0xbf840037, - 0x7e008700, 0x7e028701, - 0x7e048702, 0x7e068703, - 0xe0704000, 0x705d0000, - 0xe0704080, 0x705d0100, - 0xe0704100, 0x705d0200, - 0xe0704180, 0x705d0300, - 0x807c847c, 0x8070ff70, - 0x00000200, 0xbf0a7b7c, - 0xbf85ffef, 0xbf820025, + 0xbefc0380, 0xbf850012, + 0xbe8303ff, 0x00000080, + 0xbf800000, 0xbf800000, + 0xbf800000, 0xd8d80000, + 0x01000000, 0xbf8c0000, + 0xe0704000, 0x705d0100, + 0x807c037c, 0x80700370, + 0xd5250000, 0x0001ff00, + 0x00000080, 0xbf0a7b7c, + 0xbf85fff4, 0xbf820011, + 0xbe8303ff, 0x00000100, + 0xbf800000, 0xbf800000, + 0xbf800000, 0xd8d80000, + 0x01000000, 0xbf8c0000, + 0xe0704000, 0x705d0100, + 0x807c037c, 0x80700370, + 0xd5250000, 0x0001ff00, + 0x00000100, 0xbf0a7b7c, + 0xbf85fff4, 0xbefe03c1, + 0x907c9973, 0x877c817c, + 0xbf06817c, 0xbf850004, + 0xbef003ff, 0x00000200, + 0xbeff0380, 0xbf820003, + 0xbef003ff, 0x00000400, + 0xbeff03c1, 0xb97b3a05, + 0x807b817b, 0x8f7b827b, + 0x907c9973, 0x877c817c, + 0xbf06817c, 0xbf850017, 0xbef603ff, 0x01000000, 0xbefc0384, 0xbf0a7b7c, - 0xbf840011, 0x7e008700, + 0xbf840037, 0x7e008700, 0x7e028701, 0x7e048702, 0x7e068703, 0xe0704000, - 0x705d0000, 0xe0704100, - 0x705d0100, 0xe0704200, - 0x705d0200, 0xe0704300, + 0x705d0000, 0xe0704080, + 0x705d0100, 0xe0704100, + 0x705d0200, 0xe0704180, 0x705d0300, 0x807c847c, - 0x8070ff70, 0x00000400, + 0x8070ff70, 0x00000200, 0xbf0a7b7c, 0xbf85ffef, - 0xb97b1e06, 0x877bc17b, - 0xbf84000c, 0x8f7b837b, - 0x807b7c7b, 0xbefe03c1, - 0xbeff0380, 0x7e008700, + 0xbf820025, 0xbef603ff, + 0x01000000, 0xbefc0384, + 0xbf0a7b7c, 0xbf840011, + 0x7e008700, 0x7e028701, + 0x7e048702, 0x7e068703, 0xe0704000, 0x705d0000, - 0x807c817c, 0x8070ff70, - 0x00000080, 0xbf0a7b7c, - 0xbf85fff8, 0xbf82013b, - 0xbef4037e, 0x8775ff7f, - 0x0000ffff, 0x8875ff75, - 0x00040000, 0xbef60380, - 0xbef703ff, 0x10807fac, - 0xb97202dc, 0x8f729972, - 0x876eff7f, 0x04000000, - 0xbf840034, 0xbefe03c1, - 0x907c9972, 0x877c817c, - 0xbf06817c, 0xbf850002, - 0xbeff0380, 0xbf820001, - 0xbeff03c1, 0xb96f4306, - 0x876fc16f, 0xbf840029, - 0x8f6f866f, 0x8f6f826f, - 0xbef6036f, 0xb9783a05, - 0x80788178, 0xbf0d9972, - 0xbf850002, 0x8f788978, - 0xbf820001, 0x8f788a78, - 0xb96e1e06, 0x8f6e8a6e, - 0x80786e78, 0x8078ff78, - 0x00000200, 0x8078ff78, - 0x00000080, 0xbef603ff, - 0x01000000, 0x907c9972, - 0x877c817c, 0xbf06817c, - 0xbefc0380, 0xbf850009, - 0xe0310000, 0x781d0000, - 0x807cff7c, 0x00000080, - 0x8078ff78, 0x00000080, - 0xbf0a6f7c, 0xbf85fff8, - 0xbf820008, 0xe0310000, - 0x781d0000, 0x807cff7c, - 0x00000100, 0x8078ff78, - 0x00000100, 0xbf0a6f7c, - 0xbf85fff8, 0xbef80380, + 0xe0704100, 0x705d0100, + 0xe0704200, 0x705d0200, + 0xe0704300, 0x705d0300, + 0x807c847c, 0x8070ff70, + 0x00000400, 0xbf0a7b7c, + 0xbf85ffef, 0xb97b1e06, + 0x877bc17b, 0xbf84000c, + 0x8f7b837b, 0x807b7c7b, + 0xbefe03c1, 0xbeff0380, + 0x7e008700, 0xe0704000, + 0x705d0000, 0x807c817c, + 0x8070ff70, 0x00000080, + 0xbf0a7b7c, 0xbf85fff8, + 0xbf82013b, 0xbef4037e, + 0x8775ff7f, 0x0000ffff, + 0x8875ff75, 0x00040000, + 0xbef60380, 0xbef703ff, + 0x10807fac, 0xb97202dc, + 0x8f729972, 0x876eff7f, + 0x04000000, 0xbf840034, 0xbefe03c1, 0x907c9972, 0x877c817c, 0xbf06817c, 0xbf850002, 0xbeff0380, 0xbf820001, 0xbeff03c1, - 0xb96f3a05, 0x806f816f, - 0x8f6f826f, 0x907c9972, - 0x877c817c, 0xbf06817c, - 0xbf850024, 0xbef603ff, - 0x01000000, 0xbeee0378, + 0xb96f4306, 0x876fc16f, + 0xbf840029, 0x8f6f866f, + 0x8f6f826f, 0xbef6036f, + 0xb9783a05, 0x80788178, + 0xbf0d9972, 0xbf850002, + 0x8f788978, 0xbf820001, + 0x8f788a78, 0xb96e1e06, + 0x8f6e8a6e, 0x80786e78, 0x8078ff78, 0x00000200, - 0xbefc0384, 0xbf0a6f7c, - 0xbf840050, 0xe0304000, - 0x785d0000, 0xe0304080, - 0x785d0100, 0xe0304100, - 0x785d0200, 0xe0304180, - 0x785d0300, 0xbf8c3f70, - 0x7e008500, 0x7e028501, - 0x7e048502, 0x7e068503, - 0x807c847c, 0x8078ff78, - 0x00000200, 0xbf0a6f7c, - 0xbf85ffee, 0xe0304000, - 0x6e5d0000, 0xe0304080, - 0x6e5d0100, 0xe0304100, - 0x6e5d0200, 0xe0304180, - 0x6e5d0300, 0xbf8c3f70, - 0xbf820034, 0xbef603ff, - 0x01000000, 0xbeee0378, - 0x8078ff78, 0x00000400, - 0xbefc0384, 0xbf0a6f7c, - 0xbf840012, 0xe0304000, - 0x785d0000, 0xe0304100, - 0x785d0100, 0xe0304200, - 0x785d0200, 0xe0304300, - 0x785d0300, 0xbf8c3f70, - 0x7e008500, 0x7e028501, - 0x7e048502, 0x7e068503, - 0x807c847c, 0x8078ff78, - 0x00000400, 0xbf0a6f7c, - 0xbf85ffee, 0xb96f1e06, - 0x876fc16f, 0xbf84000e, - 0x8f6f836f, 0x806f7c6f, - 0xbefe03c1, 0xbeff0380, + 0x8078ff78, 0x00000080, + 0xbef603ff, 0x01000000, + 0x907c9972, 0x877c817c, + 0xbf06817c, 0xbefc0380, + 0xbf850009, 0xe0310000, + 0x781d0000, 0x807cff7c, + 0x00000080, 0x8078ff78, + 0x00000080, 0xbf0a6f7c, + 0xbf85fff8, 0xbf820008, + 0xe0310000, 0x781d0000, + 0x807cff7c, 0x00000100, + 0x8078ff78, 0x00000100, + 0xbf0a6f7c, 0xbf85fff8, + 0xbef80380, 0xbefe03c1, + 0x907c9972, 0x877c817c, + 0xbf06817c, 0xbf850002, + 0xbeff0380, 0xbf820001, + 0xbeff03c1, 0xb96f3a05, + 0x806f816f, 0x8f6f826f, + 0x907c9972, 0x877c817c, + 0xbf06817c, 0xbf850024, + 0xbef603ff, 0x01000000, + 0xbeee0378, 0x8078ff78, + 0x00000200, 0xbefc0384, + 0xbf0a6f7c, 0xbf840050, 0xe0304000, 0x785d0000, + 0xe0304080, 0x785d0100, + 0xe0304100, 0x785d0200, + 0xe0304180, 0x785d0300, 0xbf8c3f70, 0x7e008500, - 0x807c817c, 0x8078ff78, - 0x00000080, 0xbf0a6f7c, - 0xbf85fff7, 0xbeff03c1, + 0x7e028501, 0x7e048502, + 0x7e068503, 0x807c847c, + 0x8078ff78, 0x00000200, + 0xbf0a6f7c, 0xbf85ffee, 0xe0304000, 0x6e5d0000, - 0xe0304100, 0x6e5d0100, - 0xe0304200, 0x6e5d0200, - 0xe0304300, 0x6e5d0300, - 0xbf8c3f70, 0xb9783a05, - 0x80788178, 0xbf0d9972, - 0xbf850002, 0x8f788978, - 0xbf820001, 0x8f788a78, - 0xb96e1e06, 0x8f6e8a6e, - 0x80786e78, 0x8078ff78, - 0x00000200, 0x80f8ff78, - 0x00000050, 0xbef603ff, - 0x01000000, 0xbefc03ff, - 0x0000006c, 0x80f89078, - 0xf429003a, 0xf0000000, - 0xbf8cc07f, 0x80fc847c, - 0xbf800000, 0xbe803100, - 0xbe823102, 0x80f8a078, - 0xf42d003a, 0xf0000000, - 0xbf8cc07f, 0x80fc887c, - 0xbf800000, 0xbe803100, - 0xbe823102, 0xbe843104, - 0xbe863106, 0x80f8c078, - 0xf431003a, 0xf0000000, - 0xbf8cc07f, 0x80fc907c, - 0xbf800000, 0xbe803100, - 0xbe823102, 0xbe843104, - 0xbe863106, 0xbe883108, - 0xbe8a310a, 0xbe8c310c, - 0xbe8e310e, 0xbf06807c, - 0xbf84fff0, 0xba80f801, - 0x00000000, 0xbf8a0000, + 0xe0304080, 0x6e5d0100, + 0xe0304100, 0x6e5d0200, + 0xe0304180, 0x6e5d0300, + 0xbf8c3f70, 0xbf820034, + 0xbef603ff, 0x01000000, + 0xbeee0378, 0x8078ff78, + 0x00000400, 0xbefc0384, + 0xbf0a6f7c, 0xbf840012, + 0xe0304000, 0x785d0000, + 0xe0304100, 0x785d0100, + 0xe0304200, 0x785d0200, + 0xe0304300, 0x785d0300, + 0xbf8c3f70, 0x7e008500, + 0x7e028501, 0x7e048502, + 0x7e068503, 0x807c847c, + 0x8078ff78, 0x00000400, + 0xbf0a6f7c, 0xbf85ffee, + 0xb96f1e06, 0x876fc16f, + 0xbf84000e, 0x8f6f836f, + 0x806f7c6f, 0xbefe03c1, + 0xbeff0380, 0xe0304000, + 0x785d0000, 0xbf8c3f70, + 0x7e008500, 0x807c817c, + 0x8078ff78, 0x00000080, + 0xbf0a6f7c, 0xbf85fff7, + 0xbeff03c1, 0xe0304000, + 0x6e5d0000, 0xe0304100, + 0x6e5d0100, 0xe0304200, + 0x6e5d0200, 0xe0304300, + 0x6e5d0300, 0xbf8c3f70, 0xb9783a05, 0x80788178, 0xbf0d9972, 0xbf850002, 0x8f788978, 0xbf820001, 0x8f788a78, 0xb96e1e06, 0x8f6e8a6e, 0x80786e78, 0x8078ff78, 0x00000200, + 0x80f8ff78, 0x00000050, 0xbef603ff, 0x01000000, - 0xf4211bfa, 0xf0000000, - 0x80788478, 0xf4211b3a, + 0xbefc03ff, 0x0000006c, + 0x80f89078, 0xf429003a, + 0xf0000000, 0xbf8cc07f, + 0x80fc847c, 0xbf800000, + 0xbe803100, 0xbe823102, + 0x80f8a078, 0xf42d003a, + 0xf0000000, 0xbf8cc07f, + 0x80fc887c, 0xbf800000, + 0xbe803100, 0xbe823102, + 0xbe843104, 0xbe863106, + 0x80f8c078, 0xf431003a, + 0xf0000000, 0xbf8cc07f, + 0x80fc907c, 0xbf800000, + 0xbe803100, 0xbe823102, + 0xbe843104, 0xbe863106, + 0xbe883108, 0xbe8a310a, + 0xbe8c310c, 0xbe8e310e, + 0xbf06807c, 0xbf84fff0, + 0xba80f801, 0x00000000, + 0xbf8a0000, 0xb9783a05, + 0x80788178, 0xbf0d9972, + 0xbf850002, 0x8f788978, + 0xbf820001, 0x8f788a78, + 0xb96e1e06, 0x8f6e8a6e, + 0x80786e78, 0x8078ff78, + 0x00000200, 0xbef603ff, + 0x01000000, 0xf4211bfa, 0xf0000000, 0x80788478, - 0xf4211b7a, 0xf0000000, - 0x80788478, 0xf4211c3a, + 0xf4211b3a, 0xf0000000, + 0x80788478, 0xf4211b7a, 0xf0000000, 0x80788478, - 0xf4211c7a, 0xf0000000, - 0x80788478, 0xf4211eba, + 0xf4211c3a, 0xf0000000, + 0x80788478, 0xf4211c7a, 0xf0000000, 0x80788478, - 0xf4211efa, 0xf0000000, - 0x80788478, 0xf4211e7a, + 0xf4211eba, 0xf0000000, + 0x80788478, 0xf4211efa, 0xf0000000, 0x80788478, - 0xf4211cfa, 0xf0000000, - 0x80788478, 0xf4211bba, + 0xf4211e7a, 0xf0000000, + 0x80788478, 0xf4211cfa, 0xf0000000, 0x80788478, - 0xbf8cc07f, 0xb9eef814, 0xf4211bba, 0xf0000000, 0x80788478, 0xbf8cc07f, - 0xb9eef815, 0xbefc036f, - 0xbefe0370, 0xbeff0371, - 0x876f7bff, 0x000003ff, - 0xb9ef4803, 0x876f7bff, - 0xfffff800, 0x906f8b6f, - 0xb9efa2c3, 0xb9f3f801, - 0xb96e3a05, 0x806e816e, - 0xbf0d9972, 0xbf850002, - 0x8f6e896e, 0xbf820001, - 0x8f6e8a6e, 0xb96f1e06, - 0x8f6f8a6f, 0x806e6f6e, - 0x806eff6e, 0x00000200, - 0x806e746e, 0x826f8075, - 0x876fff6f, 0x0000ffff, - 0xf4091c37, 0xfa000050, - 0xf4091d37, 0xfa000060, - 0xf4011e77, 0xfa000074, - 0xbf8cc07f, 0x876dff6d, - 0x0000ffff, 0x87fe7e7e, - 0x87ea6a6a, 0xb9faf802, - 0xbe80226c, 0xbf810000, + 0xb9eef814, 0xf4211bba, + 0xf0000000, 0x80788478, + 0xbf8cc07f, 0xb9eef815, + 0xbefc036f, 0xbefe0370, + 0xbeff0371, 0x876f7bff, + 0x000003ff, 0xb9ef4803, + 0x876f7bff, 0xfffff800, + 0x906f8b6f, 0xb9efa2c3, + 0xb9f3f801, 0xb96e3a05, + 0x806e816e, 0xbf0d9972, + 0xbf850002, 0x8f6e896e, + 0xbf820001, 0x8f6e8a6e, + 0xb96f1e06, 0x8f6f8a6f, + 0x806e6f6e, 0x806eff6e, + 0x00000200, 0x806e746e, + 0x826f8075, 0x876fff6f, + 0x0000ffff, 0xf4091c37, + 0xfa000050, 0xf4091d37, + 0xfa000060, 0xf4011e77, + 0xfa000074, 0xbf8cc07f, + 0x876dff6d, 0x0000ffff, + 0x87fe7e7e, 0x87ea6a6a, + 0xb9faf802, 0xbe80226c, + 0xbf810000, 0xbf9f0000, 0xbf9f0000, 0xbf9f0000, 0xbf9f0000, 0xbf9f0000, - 0xbf9f0000, 0x00000000, }; static const uint32_t cwsr_trap_gfx11_hex[] = { diff --git a/drivers/gpu/drm/amd/amdkfd/cwsr_trap_handler_gfx10.asm b/drivers/gpu/drm/amd/amdkfd/cwsr_trap_handler_gfx10.asm index fdab64624422..e0140df0b0ec 100644 --- a/drivers/gpu/drm/amd/amdkfd/cwsr_trap_handler_gfx10.asm +++ b/drivers/gpu/drm/amd/amdkfd/cwsr_trap_handler_gfx10.asm @@ -369,6 +369,12 @@ L_SLEEP: s_or_b32 s_save_pc_hi, s_save_pc_hi, s_save_tmp #if NO_SQC_STORE +#if ASIC_FAMILY <= CHIP_SIENNA_CICHLID + // gfx10: If there was a VALU exception, the exception state must be + // cleared before executing the VALU instructions below. + v_clrexcp +#endif + // Trap temporaries must be saved via VGPR but all VGPRs are in use. // There is no ttmp space to hold the resource constant for VGPR save. // Save v0 by itself since it requires only two SGPRs. -- cgit From efb91fea652a42fcc037d2a9ef4ecd1ffc5ff4b7 Mon Sep 17 00:00:00 2001 From: Aurabindo Pillai Date: Fri, 27 Oct 2023 15:59:48 -0400 Subject: drm/amd/display: Fix a debugfs null pointer error [WHY & HOW] Check whether get_subvp_en() callback exists before calling it. Cc: Mario Limonciello Cc: Alex Deucher Cc: stable@vger.kernel.org Reviewed-by: Alex Hung Acked-by: Alex Hung Signed-off-by: Aurabindo Pillai Tested-by: Daniel Wheeler Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_debugfs.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_debugfs.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_debugfs.c index 13a177d34376..45c972f2630d 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_debugfs.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_debugfs.c @@ -3647,12 +3647,16 @@ static int capabilities_show(struct seq_file *m, void *unused) bool mall_supported = dc->caps.mall_size_total; bool subvp_supported = dc->caps.subvp_fw_processing_delay_us; unsigned int mall_in_use = false; - unsigned int subvp_in_use = dc->cap_funcs.get_subvp_en(dc, dc->current_state); + unsigned int subvp_in_use = false; + struct hubbub *hubbub = dc->res_pool->hubbub; if (hubbub->funcs->get_mall_en) hubbub->funcs->get_mall_en(hubbub, &mall_in_use); + if (dc->cap_funcs.get_subvp_en) + subvp_in_use = dc->cap_funcs.get_subvp_en(dc, dc->current_state); + seq_printf(m, "mall supported: %s, enabled: %s\n", mall_supported ? "yes" : "no", mall_in_use ? "yes" : "no"); seq_printf(m, "sub-viewport supported: %s, enabled: %s\n", -- cgit From ef71bb4119c786f6f1d132b8863698874321798b Mon Sep 17 00:00:00 2001 From: Yang Wang Date: Fri, 10 Nov 2023 13:14:41 +0800 Subject: drm/amdgpu: correct mca ipid die/socket/addr decode correct mca ipid die/socket/addr decode v2: squash in fix from Yang Signed-off-by: Yang Wang Reviewed-by: Hawking Zhang Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_6_ppt.c | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_6_ppt.c b/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_6_ppt.c index 0e5a77c3c2e2..f723a4190ee5 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_6_ppt.c +++ b/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_6_ppt.c @@ -2392,8 +2392,8 @@ static const struct mca_bank_ipid smu_v13_0_6_mca_ipid_table[AMDGPU_MCA_IP_COUNT static void mca_bank_entry_info_decode(struct mca_bank_entry *entry, struct mca_bank_info *info) { - uint64_t ipid = entry->regs[MCA_REG_IDX_IPID]; - uint32_t insthi; + u64 ipid = entry->regs[MCA_REG_IDX_IPID]; + u32 instidhi, instid; /* NOTE: All MCA IPID register share the same format, * so the driver can share the MCMP1 register header file. @@ -2402,9 +2402,15 @@ static void mca_bank_entry_info_decode(struct mca_bank_entry *entry, struct mca_ info->hwid = REG_GET_FIELD(ipid, MCMP1_IPIDT0, HardwareID); info->mcatype = REG_GET_FIELD(ipid, MCMP1_IPIDT0, McaType); - insthi = REG_GET_FIELD(ipid, MCMP1_IPIDT0, InstanceIdHi); - info->aid = ((insthi >> 2) & 0x03); - info->socket_id = insthi & 0x03; + /* + * Unfied DieID Format: SAASS. A:AID, S:Socket. + * Unfied DieID[4] = InstanceId[0] + * Unfied DieID[0:3] = InstanceIdHi[0:3] + */ + instidhi = REG_GET_FIELD(ipid, MCMP1_IPIDT0, InstanceIdHi); + instid = REG_GET_FIELD(ipid, MCMP1_IPIDT0, InstanceIdLo); + info->aid = ((instidhi >> 2) & 0x03); + info->socket_id = ((instid & 0x1) << 2) | (instidhi & 0x03); } static int mca_bank_read_reg(struct amdgpu_device *adev, enum amdgpu_mca_error_type type, @@ -2578,6 +2584,7 @@ static bool mca_gfx_smu_bank_is_valid(const struct mca_ras_info *mca_ras, struct uint32_t instlo; instlo = REG_GET_FIELD(entry->regs[MCA_REG_IDX_IPID], MCMP1_IPIDT0, InstanceIdLo); + instlo &= GENMASK(31, 1); switch (instlo) { case 0x36430400: /* SMNAID XCD 0 */ case 0x38430400: /* SMNAID XCD 1 */ @@ -2596,6 +2603,7 @@ static bool mca_smu_bank_is_valid(const struct mca_ras_info *mca_ras, struct amd uint32_t errcode, instlo; instlo = REG_GET_FIELD(entry->regs[MCA_REG_IDX_IPID], MCMP1_IPIDT0, InstanceIdLo); + instlo &= GENMASK(31, 1); if (instlo != 0x03b30400) return false; -- cgit From fcfc6ceec3ebb725a0d6381a1120e7cd546e1df4 Mon Sep 17 00:00:00 2001 From: Yihan Zhu Date: Mon, 30 Oct 2023 13:29:51 -0400 Subject: drm/amd/display: Enable CM low mem power optimization [WHY & HOW] MPC MCM low mem power optimization still causes color distortion on first SCE enablement, only forces light sleep for it. DPP low memory power optimization still needs this bit to save power. Reviewed-by: Nicholas Kazlauskas Acked-by: Alex Hung Signed-off-by: Yihan Zhu Tested-by: Daniel Wheeler Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dcn32/dcn32_mpc.c | 13 ++++++++----- drivers/gpu/drm/amd/display/dc/dcn35/dcn35_resource.c | 2 +- 2 files changed, 9 insertions(+), 6 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_mpc.c b/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_mpc.c index 994b21ed272f..1a2adb354718 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_mpc.c +++ b/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_mpc.c @@ -71,21 +71,24 @@ void mpc32_power_on_blnd_lut( { struct dcn30_mpc *mpc30 = TO_DCN30_MPC(mpc); +/* if (mpc->ctx->dc->debug.enable_mem_low_power.bits.cm) { if (power_on) { REG_UPDATE(MPCC_MCM_MEM_PWR_CTRL[mpcc_id], MPCC_MCM_1DLUT_MEM_PWR_FORCE, 0); REG_WAIT(MPCC_MCM_MEM_PWR_CTRL[mpcc_id], MPCC_MCM_1DLUT_MEM_PWR_STATE, 0, 1, 5); } else if (!mpc->ctx->dc->debug.disable_mem_low_power) { - ASSERT(false); - /* TODO: change to mpc - * dpp_base->ctx->dc->optimized_required = true; - * dpp_base->deferred_reg_writes.bits.disable_blnd_lut = true; - */ + //TODO: change to mpc + dpp_base->ctx->dc->optimized_required = true; + dpp_base->deferred_reg_writes.bits.disable_blnd_lut = true; } } else { REG_SET(MPCC_MCM_MEM_PWR_CTRL[mpcc_id], 0, MPCC_MCM_1DLUT_MEM_PWR_FORCE, power_on == true ? 0 : 1); } +*/ + + REG_SET(MPCC_MCM_MEM_PWR_CTRL[mpcc_id], 0, + MPCC_MCM_1DLUT_MEM_PWR_FORCE, power_on == true ? 0 : 1); } static enum dc_lut_mode mpc32_get_post1dlut_current(struct mpc *mpc, uint32_t mpcc_id) diff --git a/drivers/gpu/drm/amd/display/dc/dcn35/dcn35_resource.c b/drivers/gpu/drm/amd/display/dc/dcn35/dcn35_resource.c index c7e011d26d41..7a3faf2b1f06 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn35/dcn35_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dcn35/dcn35_resource.c @@ -724,7 +724,7 @@ static const struct dc_debug_options debug_defaults_drv = { .i2c = true, .dmcu = false, // This is previously known to cause hang on S3 cycles if enabled .dscl = true, - .cm = false, + .cm = true, .mpc = true, .optc = true, .vpg = true, -- cgit From c41028a2a16303e5a59e11338d6ef5475945c79d Mon Sep 17 00:00:00 2001 From: Hamza Mahfooz Date: Thu, 9 Nov 2023 16:42:32 -0500 Subject: drm/amd/display: add a debugfs interface for the DMUB trace mask MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit For features that are implemented primarily in DMUB (e.g. PSR), it is useful to be able to trace them at a DMUB level from the kernel, especially when debugging issues. So, introduce a debugfs interface that is able to read and set the DMUB trace mask dynamically at runtime and document how to use it. Cc: Alex Deucher Cc: Mario Limonciello Reviewed-by: Aurabindo Pillai Acked-by: Christian König Signed-off-by: Hamza Mahfooz Signed-off-by: Alex Deucher --- Documentation/gpu/amdgpu/display/dc-debug.rst | 41 +++++++++ .../gpu/amdgpu/display/trace-groups-table.csv | 29 ++++++ .../drm/amd/display/amdgpu_dm/amdgpu_dm_debugfs.c | 101 +++++++++++++++++++++ drivers/gpu/drm/amd/display/dmub/inc/dmub_cmd.h | 40 +++++++- 4 files changed, 209 insertions(+), 2 deletions(-) create mode 100644 Documentation/gpu/amdgpu/display/trace-groups-table.csv diff --git a/Documentation/gpu/amdgpu/display/dc-debug.rst b/Documentation/gpu/amdgpu/display/dc-debug.rst index 40c55a618918..817631b1dbf3 100644 --- a/Documentation/gpu/amdgpu/display/dc-debug.rst +++ b/Documentation/gpu/amdgpu/display/dc-debug.rst @@ -75,3 +75,44 @@ change in real-time by using something like:: When reporting a bug related to DC, consider attaching this log before and after you reproduce the bug. + +DMUB Firmware Debug +=================== + +Sometimes, dmesg logs aren't enough. This is especially true if a feature is +implemented primarily in DMUB firmware. In such cases, all we see in dmesg when +an issue arises is some generic timeout error. So, to get more relevant +information, we can trace DMUB commands by enabling the relevant bits in +`amdgpu_dm_dmub_trace_mask`. + +Currently, we support the tracing of the following groups: + +Trace Groups +------------ + +.. csv-table:: + :header-rows: 1 + :widths: 1, 1 + :file: ./trace-groups-table.csv + +**Note: Not all ASICs support all of the listed trace groups** + +So, to enable just PSR tracing you can use the following command:: + + # echo 0x8020 > /sys/kernel/debug/dri/0/amdgpu_dm_dmub_trace_mask + +Then, you need to enable logging trace events to the buffer, which you can do +using the following:: + + # echo 1 > /sys/kernel/debug/dri/0/amdgpu_dm_dmcub_trace_event_en + +Lastly, after you are able to reproduce the issue you are trying to debug, +you can disable tracing and read the trace log by using the following:: + + # echo 0 > /sys/kernel/debug/dri/0/amdgpu_dm_dmcub_trace_event_en + # cat /sys/kernel/debug/dri/0/amdgpu_dm_dmub_tracebuffer + +So, when reporting bugs related to features such as PSR and ABM, consider +enabling the relevant bits in the mask before reproducing the issue and +attach the log that you obtain from the trace buffer in any bug reports that you +create. diff --git a/Documentation/gpu/amdgpu/display/trace-groups-table.csv b/Documentation/gpu/amdgpu/display/trace-groups-table.csv new file mode 100644 index 000000000000..3f6a50d1d883 --- /dev/null +++ b/Documentation/gpu/amdgpu/display/trace-groups-table.csv @@ -0,0 +1,29 @@ +Name, Mask Value +INFO, 0x1 +IRQ SVC, 0x2 +VBIOS, 0x4 +REGISTER, 0x8 +PHY DBG, 0x10 +PSR, 0x20 +AUX, 0x40 +SMU, 0x80 +MALL, 0x100 +ABM, 0x200 +ALPM, 0x400 +TIMER, 0x800 +HW LOCK MGR, 0x1000 +INBOX1, 0x2000 +PHY SEQ, 0x4000 +PSR STATE, 0x8000 +ZSTATE, 0x10000 +TRANSMITTER CTL, 0x20000 +PANEL CNTL, 0x40000 +FAMS, 0x80000 +DPIA, 0x100000 +SUBVP, 0x200000 +INBOX0, 0x400000 +SDP, 0x4000000 +REPLAY, 0x8000000 +REPLAY RESIDENCY, 0x20000000 +CURSOR INFO, 0x80000000 +IPS, 0x100000000 diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_debugfs.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_debugfs.c index 45c972f2630d..98b41ec7288e 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_debugfs.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_debugfs.c @@ -2971,6 +2971,104 @@ static int allow_edp_hotplug_detection_set(void *data, u64 val) return 0; } +static int dmub_trace_mask_set(void *data, u64 val) +{ + struct amdgpu_device *adev = data; + struct dmub_srv *srv = adev->dm.dc->ctx->dmub_srv->dmub; + enum dmub_gpint_command cmd; + enum dmub_status status; + u64 mask = 0xffff; + u8 shift = 0; + u32 res; + int i; + + if (!srv->fw_version) + return -EINVAL; + + for (i = 0; i < 4; i++) { + res = (val & mask) >> shift; + + switch (i) { + case 0: + cmd = DMUB_GPINT__SET_TRACE_BUFFER_MASK_WORD0; + break; + case 1: + cmd = DMUB_GPINT__SET_TRACE_BUFFER_MASK_WORD1; + break; + case 2: + cmd = DMUB_GPINT__SET_TRACE_BUFFER_MASK_WORD2; + break; + case 3: + cmd = DMUB_GPINT__SET_TRACE_BUFFER_MASK_WORD3; + break; + } + + status = dmub_srv_send_gpint_command(srv, cmd, res, 30); + + if (status == DMUB_STATUS_TIMEOUT) + return -ETIMEDOUT; + else if (status == DMUB_STATUS_INVALID) + return -EINVAL; + else if (status != DMUB_STATUS_OK) + return -EIO; + + usleep_range(100, 1000); + + mask <<= 16; + shift += 16; + } + + return 0; +} + +static int dmub_trace_mask_show(void *data, u64 *val) +{ + enum dmub_gpint_command cmd = DMUB_GPINT__GET_TRACE_BUFFER_MASK_WORD0; + struct amdgpu_device *adev = data; + struct dmub_srv *srv = adev->dm.dc->ctx->dmub_srv->dmub; + enum dmub_status status; + u8 shift = 0; + u64 raw = 0; + u64 res = 0; + int i = 0; + + if (!srv->fw_version) + return -EINVAL; + + while (i < 4) { + status = dmub_srv_send_gpint_command(srv, cmd, 0, 30); + + if (status == DMUB_STATUS_OK) { + status = dmub_srv_get_gpint_response(srv, (u32 *) &raw); + + if (status == DMUB_STATUS_INVALID) + return -EINVAL; + else if (status != DMUB_STATUS_OK) + return -EIO; + } else if (status == DMUB_STATUS_TIMEOUT) { + return -ETIMEDOUT; + } else if (status == DMUB_STATUS_INVALID) { + return -EINVAL; + } else { + return -EIO; + } + + usleep_range(100, 1000); + + cmd++; + res |= (raw << shift); + shift += 16; + i++; + } + + *val = res; + + return 0; +} + +DEFINE_DEBUGFS_ATTRIBUTE(dmub_trace_mask_fops, dmub_trace_mask_show, + dmub_trace_mask_set, "0x%llx\n"); + /* * Set dmcub trace event IRQ enable or disable. * Usage to enable dmcub trace event IRQ: echo 1 > /sys/kernel/debug/dri/0/amdgpu_dm_dmcub_trace_event_en @@ -3884,6 +3982,9 @@ void dtn_debugfs_init(struct amdgpu_device *adev) debugfs_create_file_unsafe("amdgpu_dm_force_timing_sync", 0644, root, adev, &force_timing_sync_ops); + debugfs_create_file_unsafe("amdgpu_dm_dmub_trace_mask", 0644, root, + adev, &dmub_trace_mask_fops); + debugfs_create_file_unsafe("amdgpu_dm_dmcub_trace_event_en", 0644, root, adev, &dmcub_trace_event_state_fops); diff --git a/drivers/gpu/drm/amd/display/dmub/inc/dmub_cmd.h b/drivers/gpu/drm/amd/display/dmub/inc/dmub_cmd.h index ed4379c04715..aa6e6923afed 100644 --- a/drivers/gpu/drm/amd/display/dmub/inc/dmub_cmd.h +++ b/drivers/gpu/drm/amd/display/dmub/inc/dmub_cmd.h @@ -818,18 +818,54 @@ enum dmub_gpint_command { * RETURN: Lower 32-bit mask. */ DMUB_GPINT__UPDATE_TRACE_BUFFER_MASK = 101, + /** - * DESC: Updates the trace buffer lower 32-bit mask. + * DESC: Updates the trace buffer mask bit0~bit15. * ARGS: The new mask * RETURN: Lower 32-bit mask. */ DMUB_GPINT__SET_TRACE_BUFFER_MASK_WORD0 = 102, + /** - * DESC: Updates the trace buffer mask bi0~bit15. + * DESC: Updates the trace buffer mask bit16~bit31. * ARGS: The new mask * RETURN: Lower 32-bit mask. */ DMUB_GPINT__SET_TRACE_BUFFER_MASK_WORD1 = 103, + + /** + * DESC: Updates the trace buffer mask bit32~bit47. + * ARGS: The new mask + * RETURN: Lower 32-bit mask. + */ + DMUB_GPINT__SET_TRACE_BUFFER_MASK_WORD2 = 114, + + /** + * DESC: Updates the trace buffer mask bit48~bit63. + * ARGS: The new mask + * RETURN: Lower 32-bit mask. + */ + DMUB_GPINT__SET_TRACE_BUFFER_MASK_WORD3 = 115, + + /** + * DESC: Read the trace buffer mask bi0~bit15. + */ + DMUB_GPINT__GET_TRACE_BUFFER_MASK_WORD0 = 116, + + /** + * DESC: Read the trace buffer mask bit16~bit31. + */ + DMUB_GPINT__GET_TRACE_BUFFER_MASK_WORD1 = 117, + + /** + * DESC: Read the trace buffer mask bi32~bit47. + */ + DMUB_GPINT__GET_TRACE_BUFFER_MASK_WORD2 = 118, + + /** + * DESC: Updates the trace buffer mask bit32~bit63. + */ + DMUB_GPINT__GET_TRACE_BUFFER_MASK_WORD3 = 119, }; /** -- cgit From 8b8eed05a1c650c27e78bc47d07f7d6c9ba779e8 Mon Sep 17 00:00:00 2001 From: Mounika Adhuri Date: Fri, 6 Oct 2023 15:05:42 +0530 Subject: drm/amd/display: Refactor resource into component directory [WHY] Move all resource files to unique folder resource. [HOW] Created resource folder in dc, moved the dcnxx_resource.c and dcnxx_resource.h files into corresponding new folders inside the resource and made appropriate changes for compilation in Makefiles. Reviewed-by: Martin Leung Acked-by: Alex Hung Signed-off-by: Mounika Adhuri Tested-by: Daniel Wheeler Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/Makefile | 1 + .../amd/display/amdgpu_dm/amdgpu_dm_mst_types.c | 2 +- drivers/gpu/drm/amd/display/dc/Makefile | 5 +- drivers/gpu/drm/amd/display/dc/core/dc_resource.c | 4 +- drivers/gpu/drm/amd/display/dc/dce100/Makefile | 46 - .../drm/amd/display/dc/dce100/dce100_resource.c | 1179 -------- .../drm/amd/display/dc/dce100/dce100_resource.h | 54 - drivers/gpu/drm/amd/display/dc/dce110/Makefile | 4 +- .../drm/amd/display/dc/dce110/dce110_resource.c | 1551 ----------- .../drm/amd/display/dc/dce110/dce110_resource.h | 54 - drivers/gpu/drm/amd/display/dc/dce112/Makefile | 3 +- .../drm/amd/display/dc/dce112/dce112_resource.c | 1431 ---------- .../drm/amd/display/dc/dce112/dce112_resource.h | 57 - drivers/gpu/drm/amd/display/dc/dce120/Makefile | 2 +- .../drm/amd/display/dc/dce120/dce120_resource.c | 1288 --------- .../drm/amd/display/dc/dce120/dce120_resource.h | 39 - drivers/gpu/drm/amd/display/dc/dce80/Makefile | 3 +- .../gpu/drm/amd/display/dc/dce80/dce80_resource.c | 1544 ----------- .../gpu/drm/amd/display/dc/dce80/dce80_resource.h | 47 - drivers/gpu/drm/amd/display/dc/dcn10/Makefile | 2 +- .../gpu/drm/amd/display/dc/dcn10/dcn10_resource.c | 1686 ------------ .../gpu/drm/amd/display/dc/dcn10/dcn10_resource.h | 56 - drivers/gpu/drm/amd/display/dc/dcn20/Makefile | 2 +- .../gpu/drm/amd/display/dc/dcn20/dcn20_resource.c | 2789 ------------------- .../gpu/drm/amd/display/dc/dcn20/dcn20_resource.h | 170 -- drivers/gpu/drm/amd/display/dc/dcn201/Makefile | 2 +- .../drm/amd/display/dc/dcn201/dcn201_resource.c | 1308 --------- .../drm/amd/display/dc/dcn201/dcn201_resource.h | 50 - drivers/gpu/drm/amd/display/dc/dcn21/Makefile | 2 +- .../gpu/drm/amd/display/dc/dcn21/dcn21_resource.c | 1745 ------------ .../gpu/drm/amd/display/dc/dcn21/dcn21_resource.h | 56 - drivers/gpu/drm/amd/display/dc/dcn30/Makefile | 1 - .../gpu/drm/amd/display/dc/dcn30/dcn30_resource.c | 2611 ------------------ .../gpu/drm/amd/display/dc/dcn30/dcn30_resource.h | 108 - drivers/gpu/drm/amd/display/dc/dcn301/Makefile | 2 +- .../drm/amd/display/dc/dcn301/dcn301_resource.c | 1728 ------------ .../drm/amd/display/dc/dcn301/dcn301_resource.h | 45 - drivers/gpu/drm/amd/display/dc/dcn302/Makefile | 2 +- .../drm/amd/display/dc/dcn302/dcn302_resource.c | 1518 ----------- .../drm/amd/display/dc/dcn302/dcn302_resource.h | 38 - drivers/gpu/drm/amd/display/dc/dcn303/Makefile | 2 +- .../drm/amd/display/dc/dcn303/dcn303_resource.c | 1448 ---------- .../drm/amd/display/dc/dcn303/dcn303_resource.h | 38 - drivers/gpu/drm/amd/display/dc/dcn31/Makefile | 2 +- .../gpu/drm/amd/display/dc/dcn31/dcn31_resource.c | 2218 --------------- .../gpu/drm/amd/display/dc/dcn31/dcn31_resource.h | 97 - drivers/gpu/drm/amd/display/dc/dcn314/Makefile | 2 +- .../drm/amd/display/dc/dcn314/dcn314_resource.c | 2180 --------------- .../drm/amd/display/dc/dcn314/dcn314_resource.h | 50 - drivers/gpu/drm/amd/display/dc/dcn315/Makefile | 30 - .../drm/amd/display/dc/dcn315/dcn315_resource.c | 2151 --------------- .../drm/amd/display/dc/dcn315/dcn315_resource.h | 44 - drivers/gpu/drm/amd/display/dc/dcn316/Makefile | 30 - .../drm/amd/display/dc/dcn316/dcn316_resource.c | 2038 -------------- .../drm/amd/display/dc/dcn316/dcn316_resource.h | 44 - drivers/gpu/drm/amd/display/dc/dcn32/Makefile | 2 +- .../gpu/drm/amd/display/dc/dcn32/dcn32_resource.c | 2862 -------------------- .../gpu/drm/amd/display/dc/dcn32/dcn32_resource.h | 1263 --------- .../amd/display/dc/dcn32/dcn32_resource_helpers.c | 2 +- drivers/gpu/drm/amd/display/dc/dcn321/Makefile | 2 +- .../drm/amd/display/dc/dcn321/dcn321_resource.c | 2065 -------------- .../drm/amd/display/dc/dcn321/dcn321_resource.h | 45 - drivers/gpu/drm/amd/display/dc/dcn35/Makefile | 2 +- .../gpu/drm/amd/display/dc/dcn35/dcn35_resource.c | 2141 --------------- .../gpu/drm/amd/display/dc/dcn35/dcn35_resource.h | 310 --- .../gpu/drm/amd/display/dc/dml/calcs/dcn_calcs.c | 2 +- drivers/gpu/drm/amd/display/dc/resource/Makefile | 199 ++ .../display/dc/resource/dce100/dce100_resource.c | 1179 ++++++++ .../display/dc/resource/dce100/dce100_resource.h | 54 + .../display/dc/resource/dce110/dce110_resource.c | 1551 +++++++++++ .../display/dc/resource/dce110/dce110_resource.h | 54 + .../display/dc/resource/dce112/dce112_resource.c | 1431 ++++++++++ .../display/dc/resource/dce112/dce112_resource.h | 57 + .../display/dc/resource/dce120/dce120_resource.c | 1288 +++++++++ .../display/dc/resource/dce120/dce120_resource.h | 39 + .../amd/display/dc/resource/dce80/CMakeLists.txt | 4 + .../amd/display/dc/resource/dce80/dce80_resource.c | 1544 +++++++++++ .../amd/display/dc/resource/dce80/dce80_resource.h | 47 + .../amd/display/dc/resource/dcn10/dcn10_resource.c | 1689 ++++++++++++ .../amd/display/dc/resource/dcn10/dcn10_resource.h | 56 + .../amd/display/dc/resource/dcn20/dcn20_resource.c | 2789 +++++++++++++++++++ .../amd/display/dc/resource/dcn20/dcn20_resource.h | 170 ++ .../display/dc/resource/dcn201/dcn201_resource.c | 1308 +++++++++ .../display/dc/resource/dcn201/dcn201_resource.h | 50 + .../amd/display/dc/resource/dcn21/dcn21_resource.c | 1745 ++++++++++++ .../amd/display/dc/resource/dcn21/dcn21_resource.h | 56 + .../amd/display/dc/resource/dcn30/dcn30_resource.c | 2611 ++++++++++++++++++ .../amd/display/dc/resource/dcn30/dcn30_resource.h | 108 + .../display/dc/resource/dcn301/dcn301_resource.c | 1728 ++++++++++++ .../display/dc/resource/dcn301/dcn301_resource.h | 45 + .../display/dc/resource/dcn302/dcn302_resource.c | 1518 +++++++++++ .../display/dc/resource/dcn302/dcn302_resource.h | 38 + .../display/dc/resource/dcn303/dcn303_resource.c | 1448 ++++++++++ .../display/dc/resource/dcn303/dcn303_resource.h | 38 + .../amd/display/dc/resource/dcn31/dcn31_resource.c | 2218 +++++++++++++++ .../amd/display/dc/resource/dcn31/dcn31_resource.h | 97 + .../display/dc/resource/dcn314/dcn314_resource.c | 2180 +++++++++++++++ .../display/dc/resource/dcn314/dcn314_resource.h | 50 + .../display/dc/resource/dcn315/dcn315_resource.c | 2151 +++++++++++++++ .../display/dc/resource/dcn315/dcn315_resource.h | 44 + .../display/dc/resource/dcn316/dcn316_resource.c | 2038 ++++++++++++++ .../display/dc/resource/dcn316/dcn316_resource.h | 44 + .../amd/display/dc/resource/dcn32/dcn32_resource.c | 2862 ++++++++++++++++++++ .../amd/display/dc/resource/dcn32/dcn32_resource.h | 1263 +++++++++ .../display/dc/resource/dcn321/dcn321_resource.c | 2065 ++++++++++++++ .../display/dc/resource/dcn321/dcn321_resource.h | 45 + .../amd/display/dc/resource/dcn35/dcn35_resource.c | 2141 +++++++++++++++ .../amd/display/dc/resource/dcn35/dcn35_resource.h | 310 +++ 108 files changed, 40376 insertions(+), 40281 deletions(-) delete mode 100644 drivers/gpu/drm/amd/display/dc/dce100/Makefile delete mode 100644 drivers/gpu/drm/amd/display/dc/dce100/dce100_resource.c delete mode 100644 drivers/gpu/drm/amd/display/dc/dce100/dce100_resource.h delete mode 100644 drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c delete mode 100644 drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.h delete mode 100644 drivers/gpu/drm/amd/display/dc/dce112/dce112_resource.c delete mode 100644 drivers/gpu/drm/amd/display/dc/dce112/dce112_resource.h delete mode 100644 drivers/gpu/drm/amd/display/dc/dce120/dce120_resource.c delete mode 100644 drivers/gpu/drm/amd/display/dc/dce120/dce120_resource.h delete mode 100644 drivers/gpu/drm/amd/display/dc/dce80/dce80_resource.c delete mode 100644 drivers/gpu/drm/amd/display/dc/dce80/dce80_resource.h delete mode 100644 drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c delete mode 100644 drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.h delete mode 100644 drivers/gpu/drm/amd/display/dc/dcn20/dcn20_resource.c delete mode 100644 drivers/gpu/drm/amd/display/dc/dcn20/dcn20_resource.h delete mode 100644 drivers/gpu/drm/amd/display/dc/dcn201/dcn201_resource.c delete mode 100644 drivers/gpu/drm/amd/display/dc/dcn201/dcn201_resource.h delete mode 100644 drivers/gpu/drm/amd/display/dc/dcn21/dcn21_resource.c delete mode 100644 drivers/gpu/drm/amd/display/dc/dcn21/dcn21_resource.h delete mode 100644 drivers/gpu/drm/amd/display/dc/dcn30/dcn30_resource.c delete mode 100644 drivers/gpu/drm/amd/display/dc/dcn30/dcn30_resource.h delete mode 100644 drivers/gpu/drm/amd/display/dc/dcn301/dcn301_resource.c delete mode 100644 drivers/gpu/drm/amd/display/dc/dcn301/dcn301_resource.h delete mode 100644 drivers/gpu/drm/amd/display/dc/dcn302/dcn302_resource.c delete mode 100644 drivers/gpu/drm/amd/display/dc/dcn302/dcn302_resource.h delete mode 100644 drivers/gpu/drm/amd/display/dc/dcn303/dcn303_resource.c delete mode 100644 drivers/gpu/drm/amd/display/dc/dcn303/dcn303_resource.h delete mode 100644 drivers/gpu/drm/amd/display/dc/dcn31/dcn31_resource.c delete mode 100644 drivers/gpu/drm/amd/display/dc/dcn31/dcn31_resource.h delete mode 100644 drivers/gpu/drm/amd/display/dc/dcn314/dcn314_resource.c delete mode 100644 drivers/gpu/drm/amd/display/dc/dcn314/dcn314_resource.h delete mode 100644 drivers/gpu/drm/amd/display/dc/dcn315/Makefile delete mode 100644 drivers/gpu/drm/amd/display/dc/dcn315/dcn315_resource.c delete mode 100644 drivers/gpu/drm/amd/display/dc/dcn315/dcn315_resource.h delete mode 100644 drivers/gpu/drm/amd/display/dc/dcn316/Makefile delete mode 100644 drivers/gpu/drm/amd/display/dc/dcn316/dcn316_resource.c delete mode 100644 drivers/gpu/drm/amd/display/dc/dcn316/dcn316_resource.h delete mode 100644 drivers/gpu/drm/amd/display/dc/dcn32/dcn32_resource.c delete mode 100644 drivers/gpu/drm/amd/display/dc/dcn32/dcn32_resource.h delete mode 100644 drivers/gpu/drm/amd/display/dc/dcn321/dcn321_resource.c delete mode 100644 drivers/gpu/drm/amd/display/dc/dcn321/dcn321_resource.h delete mode 100644 drivers/gpu/drm/amd/display/dc/dcn35/dcn35_resource.c delete mode 100644 drivers/gpu/drm/amd/display/dc/dcn35/dcn35_resource.h create mode 100644 drivers/gpu/drm/amd/display/dc/resource/Makefile create mode 100644 drivers/gpu/drm/amd/display/dc/resource/dce100/dce100_resource.c create mode 100644 drivers/gpu/drm/amd/display/dc/resource/dce100/dce100_resource.h create mode 100644 drivers/gpu/drm/amd/display/dc/resource/dce110/dce110_resource.c create mode 100644 drivers/gpu/drm/amd/display/dc/resource/dce110/dce110_resource.h create mode 100644 drivers/gpu/drm/amd/display/dc/resource/dce112/dce112_resource.c create mode 100644 drivers/gpu/drm/amd/display/dc/resource/dce112/dce112_resource.h create mode 100644 drivers/gpu/drm/amd/display/dc/resource/dce120/dce120_resource.c create mode 100644 drivers/gpu/drm/amd/display/dc/resource/dce120/dce120_resource.h create mode 100644 drivers/gpu/drm/amd/display/dc/resource/dce80/CMakeLists.txt create mode 100644 drivers/gpu/drm/amd/display/dc/resource/dce80/dce80_resource.c create mode 100644 drivers/gpu/drm/amd/display/dc/resource/dce80/dce80_resource.h create mode 100644 drivers/gpu/drm/amd/display/dc/resource/dcn10/dcn10_resource.c create mode 100644 drivers/gpu/drm/amd/display/dc/resource/dcn10/dcn10_resource.h create mode 100644 drivers/gpu/drm/amd/display/dc/resource/dcn20/dcn20_resource.c create mode 100644 drivers/gpu/drm/amd/display/dc/resource/dcn20/dcn20_resource.h create mode 100644 drivers/gpu/drm/amd/display/dc/resource/dcn201/dcn201_resource.c create mode 100644 drivers/gpu/drm/amd/display/dc/resource/dcn201/dcn201_resource.h create mode 100644 drivers/gpu/drm/amd/display/dc/resource/dcn21/dcn21_resource.c create mode 100644 drivers/gpu/drm/amd/display/dc/resource/dcn21/dcn21_resource.h create mode 100644 drivers/gpu/drm/amd/display/dc/resource/dcn30/dcn30_resource.c create mode 100644 drivers/gpu/drm/amd/display/dc/resource/dcn30/dcn30_resource.h create mode 100644 drivers/gpu/drm/amd/display/dc/resource/dcn301/dcn301_resource.c create mode 100644 drivers/gpu/drm/amd/display/dc/resource/dcn301/dcn301_resource.h create mode 100644 drivers/gpu/drm/amd/display/dc/resource/dcn302/dcn302_resource.c create mode 100644 drivers/gpu/drm/amd/display/dc/resource/dcn302/dcn302_resource.h create mode 100644 drivers/gpu/drm/amd/display/dc/resource/dcn303/dcn303_resource.c create mode 100644 drivers/gpu/drm/amd/display/dc/resource/dcn303/dcn303_resource.h create mode 100644 drivers/gpu/drm/amd/display/dc/resource/dcn31/dcn31_resource.c create mode 100644 drivers/gpu/drm/amd/display/dc/resource/dcn31/dcn31_resource.h create mode 100644 drivers/gpu/drm/amd/display/dc/resource/dcn314/dcn314_resource.c create mode 100644 drivers/gpu/drm/amd/display/dc/resource/dcn314/dcn314_resource.h create mode 100644 drivers/gpu/drm/amd/display/dc/resource/dcn315/dcn315_resource.c create mode 100644 drivers/gpu/drm/amd/display/dc/resource/dcn315/dcn315_resource.h create mode 100644 drivers/gpu/drm/amd/display/dc/resource/dcn316/dcn316_resource.c create mode 100644 drivers/gpu/drm/amd/display/dc/resource/dcn316/dcn316_resource.h create mode 100644 drivers/gpu/drm/amd/display/dc/resource/dcn32/dcn32_resource.c create mode 100644 drivers/gpu/drm/amd/display/dc/resource/dcn32/dcn32_resource.h create mode 100644 drivers/gpu/drm/amd/display/dc/resource/dcn321/dcn321_resource.c create mode 100644 drivers/gpu/drm/amd/display/dc/resource/dcn321/dcn321_resource.h create mode 100644 drivers/gpu/drm/amd/display/dc/resource/dcn35/dcn35_resource.c create mode 100644 drivers/gpu/drm/amd/display/dc/resource/dcn35/dcn35_resource.h diff --git a/drivers/gpu/drm/amd/display/Makefile b/drivers/gpu/drm/amd/display/Makefile index af17ab8027df..71192fc81a20 100644 --- a/drivers/gpu/drm/amd/display/Makefile +++ b/drivers/gpu/drm/amd/display/Makefile @@ -30,6 +30,7 @@ subdir-ccflags-y += -I$(FULL_AMD_DISPLAY_PATH)/dc/inc/ subdir-ccflags-y += -I$(FULL_AMD_DISPLAY_PATH)/dc/inc/hw subdir-ccflags-y += -I$(FULL_AMD_DISPLAY_PATH)/dc/clk_mgr subdir-ccflags-y += -I$(FULL_AMD_DISPLAY_PATH)/dc/hwss +subdir-ccflags-y += -I$(FULL_AMD_DISPLAY_PATH)/dc/resource subdir-ccflags-y += -I$(FULL_AMD_DISPLAY_PATH)/modules/inc subdir-ccflags-y += -I$(FULL_AMD_DISPLAY_PATH)/modules/freesync subdir-ccflags-y += -I$(FULL_AMD_DISPLAY_PATH)/modules/color diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c index 11da0eebee6c..ec87e31c6fe8 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c @@ -44,7 +44,7 @@ #include "amdgpu_dm_debugfs.h" #endif -#include "dc/dcn20/dcn20_resource.h" +#include "dc/resource/dcn20/dcn20_resource.h" #define PEAK_FACTOR_X1000 1006 diff --git a/drivers/gpu/drm/amd/display/dc/Makefile b/drivers/gpu/drm/amd/display/dc/Makefile index 3a169b78e7e4..ab51a065cf0e 100644 --- a/drivers/gpu/drm/amd/display/dc/Makefile +++ b/drivers/gpu/drm/amd/display/dc/Makefile @@ -22,7 +22,7 @@ # # Makefile for Display Core (dc) component. -DC_LIBS = basics bios dml clk_mgr dce gpio hwss irq link virtual dsc +DC_LIBS = basics bios dml clk_mgr dce gpio hwss irq link virtual dsc resource ifdef CONFIG_DRM_AMD_DC_FP @@ -38,8 +38,6 @@ DC_LIBS += dcn302 DC_LIBS += dcn303 DC_LIBS += dcn31 DC_LIBS += dcn314 -DC_LIBS += dcn315 -DC_LIBS += dcn316 DC_LIBS += dcn32 DC_LIBS += dcn321 DC_LIBS += dcn35 @@ -51,7 +49,6 @@ DC_LIBS += dce120 DC_LIBS += dce112 DC_LIBS += dce110 -DC_LIBS += dce100 DC_LIBS += dce80 ifdef CONFIG_DRM_AMD_DC_SI diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c index a1f1d1003992..6159d819c5c5 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c @@ -69,8 +69,8 @@ #include "dcn314/dcn314_resource.h" #include "dcn315/dcn315_resource.h" #include "dcn316/dcn316_resource.h" -#include "../dcn32/dcn32_resource.h" -#include "../dcn321/dcn321_resource.h" +#include "dcn32/dcn32_resource.h" +#include "dcn321/dcn321_resource.h" #include "dcn35/dcn35_resource.h" #define VISUAL_CONFIRM_BASE_DEFAULT 3 diff --git a/drivers/gpu/drm/amd/display/dc/dce100/Makefile b/drivers/gpu/drm/amd/display/dc/dce100/Makefile deleted file mode 100644 index 0d2f6bbf7558..000000000000 --- a/drivers/gpu/drm/amd/display/dc/dce100/Makefile +++ /dev/null @@ -1,46 +0,0 @@ -# -# Copyright 2017 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. -# -# -# Makefile for the 'controller' sub-component of DAL. -# It provides the control and status of HW CRTC block. - -CFLAGS_$(AMDDALPATH)/dc/dce100/dce100_resource.o = $(call cc-disable-warning, override-init) - -DCE100 = dce100_resource.o - -AMD_DAL_DCE100 = $(addprefix $(AMDDALPATH)/dc/dce100/,$(DCE100)) - -AMD_DISPLAY_FILES += $(AMD_DAL_DCE100) - - -############################################################################### -# DCE 10x -############################################################################### -ifdef 0#CONFIG_DRM_AMD_DC_DCE11_0 -TG_DCE100 = dce100_resource.o - -AMD_DAL_TG_DCE100 = $(addprefix \ - $(AMDDALPATH)/dc/dce100/,$(TG_DCE100)) - -AMD_DISPLAY_FILES += $(AMD_DAL_TG_DCE100) -endif - diff --git a/drivers/gpu/drm/amd/display/dc/dce100/dce100_resource.c b/drivers/gpu/drm/amd/display/dc/dce100/dce100_resource.c deleted file mode 100644 index 53a5f4cb648c..000000000000 --- a/drivers/gpu/drm/amd/display/dc/dce100/dce100_resource.c +++ /dev/null @@ -1,1179 +0,0 @@ -/* - * Copyright 2012-15 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 "dm_services.h" - -#include "link_encoder.h" -#include "stream_encoder.h" - -#include "resource.h" -#include "include/irq_service_interface.h" -#include "virtual/virtual_stream_encoder.h" -#include "dce110/dce110_resource.h" -#include "dce110/dce110_timing_generator.h" -#include "irq/dce110/irq_service_dce110.h" -#include "dce/dce_link_encoder.h" -#include "dce/dce_stream_encoder.h" -#include "dce/dce_mem_input.h" -#include "dce/dce_ipp.h" -#include "dce/dce_transform.h" -#include "dce/dce_opp.h" -#include "dce/dce_clock_source.h" -#include "dce/dce_audio.h" -#include "dce/dce_hwseq.h" -#include "dce100/dce100_hwseq.h" -#include "dce/dce_panel_cntl.h" - -#include "reg_helper.h" - -#include "dce/dce_10_0_d.h" -#include "dce/dce_10_0_sh_mask.h" - -#include "dce/dce_dmcu.h" -#include "dce/dce_aux.h" -#include "dce/dce_abm.h" -#include "dce/dce_i2c.h" - -#include "dce100_resource.h" - -#ifndef mmMC_HUB_RDREQ_DMIF_LIMIT -#include "gmc/gmc_8_2_d.h" -#include "gmc/gmc_8_2_sh_mask.h" -#endif - -#ifndef mmDP_DPHY_INTERNAL_CTRL - #define mmDP_DPHY_INTERNAL_CTRL 0x4aa7 - #define mmDP0_DP_DPHY_INTERNAL_CTRL 0x4aa7 - #define mmDP1_DP_DPHY_INTERNAL_CTRL 0x4ba7 - #define mmDP2_DP_DPHY_INTERNAL_CTRL 0x4ca7 - #define mmDP3_DP_DPHY_INTERNAL_CTRL 0x4da7 - #define mmDP4_DP_DPHY_INTERNAL_CTRL 0x4ea7 - #define mmDP5_DP_DPHY_INTERNAL_CTRL 0x4fa7 - #define mmDP6_DP_DPHY_INTERNAL_CTRL 0x54a7 - #define mmDP7_DP_DPHY_INTERNAL_CTRL 0x56a7 - #define mmDP8_DP_DPHY_INTERNAL_CTRL 0x57a7 -#endif - -#ifndef mmBIOS_SCRATCH_2 - #define mmBIOS_SCRATCH_2 0x05CB - #define mmBIOS_SCRATCH_3 0x05CC - #define mmBIOS_SCRATCH_6 0x05CF -#endif - -#ifndef mmDP_DPHY_BS_SR_SWAP_CNTL - #define mmDP_DPHY_BS_SR_SWAP_CNTL 0x4ADC - #define mmDP0_DP_DPHY_BS_SR_SWAP_CNTL 0x4ADC - #define mmDP1_DP_DPHY_BS_SR_SWAP_CNTL 0x4BDC - #define mmDP2_DP_DPHY_BS_SR_SWAP_CNTL 0x4CDC - #define mmDP3_DP_DPHY_BS_SR_SWAP_CNTL 0x4DDC - #define mmDP4_DP_DPHY_BS_SR_SWAP_CNTL 0x4EDC - #define mmDP5_DP_DPHY_BS_SR_SWAP_CNTL 0x4FDC - #define mmDP6_DP_DPHY_BS_SR_SWAP_CNTL 0x54DC -#endif - -#ifndef mmDP_DPHY_FAST_TRAINING - #define mmDP_DPHY_FAST_TRAINING 0x4ABC - #define mmDP0_DP_DPHY_FAST_TRAINING 0x4ABC - #define mmDP1_DP_DPHY_FAST_TRAINING 0x4BBC - #define mmDP2_DP_DPHY_FAST_TRAINING 0x4CBC - #define mmDP3_DP_DPHY_FAST_TRAINING 0x4DBC - #define mmDP4_DP_DPHY_FAST_TRAINING 0x4EBC - #define mmDP5_DP_DPHY_FAST_TRAINING 0x4FBC - #define mmDP6_DP_DPHY_FAST_TRAINING 0x54BC -#endif - -static const struct dce110_timing_generator_offsets dce100_tg_offsets[] = { - { - .crtc = (mmCRTC0_CRTC_CONTROL - mmCRTC_CONTROL), - .dcp = (mmDCP0_GRPH_CONTROL - mmGRPH_CONTROL), - }, - { - .crtc = (mmCRTC1_CRTC_CONTROL - mmCRTC_CONTROL), - .dcp = (mmDCP1_GRPH_CONTROL - mmGRPH_CONTROL), - }, - { - .crtc = (mmCRTC2_CRTC_CONTROL - mmCRTC_CONTROL), - .dcp = (mmDCP2_GRPH_CONTROL - mmGRPH_CONTROL), - }, - { - .crtc = (mmCRTC3_CRTC_CONTROL - mmCRTC_CONTROL), - .dcp = (mmDCP3_GRPH_CONTROL - mmGRPH_CONTROL), - }, - { - .crtc = (mmCRTC4_CRTC_CONTROL - mmCRTC_CONTROL), - .dcp = (mmDCP4_GRPH_CONTROL - mmGRPH_CONTROL), - }, - { - .crtc = (mmCRTC5_CRTC_CONTROL - mmCRTC_CONTROL), - .dcp = (mmDCP5_GRPH_CONTROL - mmGRPH_CONTROL), - } -}; - -/* set register offset */ -#define SR(reg_name)\ - .reg_name = mm ## reg_name - -/* set register offset with instance */ -#define SRI(reg_name, block, id)\ - .reg_name = mm ## block ## id ## _ ## reg_name - -#define ipp_regs(id)\ -[id] = {\ - IPP_DCE100_REG_LIST_DCE_BASE(id)\ -} - -static const struct dce_ipp_registers ipp_regs[] = { - ipp_regs(0), - ipp_regs(1), - ipp_regs(2), - ipp_regs(3), - ipp_regs(4), - ipp_regs(5) -}; - -static const struct dce_ipp_shift ipp_shift = { - IPP_DCE100_MASK_SH_LIST_DCE_COMMON_BASE(__SHIFT) -}; - -static const struct dce_ipp_mask ipp_mask = { - IPP_DCE100_MASK_SH_LIST_DCE_COMMON_BASE(_MASK) -}; - -#define transform_regs(id)\ -[id] = {\ - XFM_COMMON_REG_LIST_DCE100(id)\ -} - -static const struct dce_transform_registers xfm_regs[] = { - transform_regs(0), - transform_regs(1), - transform_regs(2), - transform_regs(3), - transform_regs(4), - transform_regs(5) -}; - -static const struct dce_transform_shift xfm_shift = { - XFM_COMMON_MASK_SH_LIST_DCE110(__SHIFT) -}; - -static const struct dce_transform_mask xfm_mask = { - XFM_COMMON_MASK_SH_LIST_DCE110(_MASK) -}; - -#define aux_regs(id)\ -[id] = {\ - AUX_REG_LIST(id)\ -} - -static const struct dce110_link_enc_aux_registers link_enc_aux_regs[] = { - aux_regs(0), - aux_regs(1), - aux_regs(2), - aux_regs(3), - aux_regs(4), - aux_regs(5) -}; - -#define hpd_regs(id)\ -[id] = {\ - HPD_REG_LIST(id)\ -} - -static const struct dce110_link_enc_hpd_registers link_enc_hpd_regs[] = { - hpd_regs(0), - hpd_regs(1), - hpd_regs(2), - hpd_regs(3), - hpd_regs(4), - hpd_regs(5) -}; - -#define link_regs(id)\ -[id] = {\ - LE_DCE100_REG_LIST(id)\ -} - -static const struct dce110_link_enc_registers link_enc_regs[] = { - link_regs(0), - link_regs(1), - link_regs(2), - link_regs(3), - link_regs(4), - link_regs(5), - link_regs(6), -}; - -#define stream_enc_regs(id)\ -[id] = {\ - SE_COMMON_REG_LIST_DCE_BASE(id),\ - .AFMT_CNTL = 0,\ -} - -static const struct dce110_stream_enc_registers stream_enc_regs[] = { - stream_enc_regs(0), - stream_enc_regs(1), - stream_enc_regs(2), - stream_enc_regs(3), - stream_enc_regs(4), - stream_enc_regs(5), - stream_enc_regs(6) -}; - -static const struct dce_stream_encoder_shift se_shift = { - SE_COMMON_MASK_SH_LIST_DCE80_100(__SHIFT) -}; - -static const struct dce_stream_encoder_mask se_mask = { - SE_COMMON_MASK_SH_LIST_DCE80_100(_MASK) -}; - -static const struct dce_panel_cntl_registers panel_cntl_regs[] = { - { DCE_PANEL_CNTL_REG_LIST() } -}; - -static const struct dce_panel_cntl_shift panel_cntl_shift = { - DCE_PANEL_CNTL_MASK_SH_LIST(__SHIFT) -}; - -static const struct dce_panel_cntl_mask panel_cntl_mask = { - DCE_PANEL_CNTL_MASK_SH_LIST(_MASK) -}; - -#define opp_regs(id)\ -[id] = {\ - OPP_DCE_100_REG_LIST(id),\ -} - -static const struct dce_opp_registers opp_regs[] = { - opp_regs(0), - opp_regs(1), - opp_regs(2), - opp_regs(3), - opp_regs(4), - opp_regs(5) -}; - -static const struct dce_opp_shift opp_shift = { - OPP_COMMON_MASK_SH_LIST_DCE_100(__SHIFT) -}; - -static const struct dce_opp_mask opp_mask = { - OPP_COMMON_MASK_SH_LIST_DCE_100(_MASK) -}; -#define aux_engine_regs(id)\ -[id] = {\ - AUX_COMMON_REG_LIST(id), \ - .AUX_RESET_MASK = 0 \ -} - -static const struct dce110_aux_registers aux_engine_regs[] = { - aux_engine_regs(0), - aux_engine_regs(1), - aux_engine_regs(2), - aux_engine_regs(3), - aux_engine_regs(4), - aux_engine_regs(5) -}; - -#define audio_regs(id)\ -[id] = {\ - AUD_COMMON_REG_LIST(id)\ -} - -static const struct dce_audio_registers audio_regs[] = { - audio_regs(0), - audio_regs(1), - audio_regs(2), - audio_regs(3), - audio_regs(4), - audio_regs(5), - audio_regs(6), -}; - -static const struct dce_audio_shift audio_shift = { - AUD_COMMON_MASK_SH_LIST(__SHIFT) -}; - -static const struct dce_audio_mask audio_mask = { - AUD_COMMON_MASK_SH_LIST(_MASK) -}; - -#define clk_src_regs(id)\ -[id] = {\ - CS_COMMON_REG_LIST_DCE_100_110(id),\ -} - -static const struct dce110_clk_src_regs clk_src_regs[] = { - clk_src_regs(0), - clk_src_regs(1), - clk_src_regs(2) -}; - -static const struct dce110_clk_src_shift cs_shift = { - CS_COMMON_MASK_SH_LIST_DCE_COMMON_BASE(__SHIFT) -}; - -static const struct dce110_clk_src_mask cs_mask = { - CS_COMMON_MASK_SH_LIST_DCE_COMMON_BASE(_MASK) -}; - -static const struct dce_dmcu_registers dmcu_regs = { - DMCU_DCE110_COMMON_REG_LIST() -}; - -static const struct dce_dmcu_shift dmcu_shift = { - DMCU_MASK_SH_LIST_DCE110(__SHIFT) -}; - -static const struct dce_dmcu_mask dmcu_mask = { - DMCU_MASK_SH_LIST_DCE110(_MASK) -}; - -static const struct dce_abm_registers abm_regs = { - ABM_DCE110_COMMON_REG_LIST() -}; - -static const struct dce_abm_shift abm_shift = { - ABM_MASK_SH_LIST_DCE110(__SHIFT) -}; - -static const struct dce_abm_mask abm_mask = { - ABM_MASK_SH_LIST_DCE110(_MASK) -}; - -#define DCFE_MEM_PWR_CTRL_REG_BASE 0x1b03 - -static const struct bios_registers bios_regs = { - .BIOS_SCRATCH_3 = mmBIOS_SCRATCH_3, - .BIOS_SCRATCH_6 = mmBIOS_SCRATCH_6 -}; - -static const struct resource_caps res_cap = { - .num_timing_generator = 6, - .num_audio = 6, - .num_stream_encoder = 6, - .num_pll = 3, - .num_ddc = 6, -}; - -static const struct dc_plane_cap plane_cap = { - .type = DC_PLANE_TYPE_DCE_RGB, - - .pixel_format_support = { - .argb8888 = true, - .nv12 = false, - .fp16 = true - }, - - .max_upscale_factor = { - .argb8888 = 16000, - .nv12 = 1, - .fp16 = 1 - }, - - .max_downscale_factor = { - .argb8888 = 250, - .nv12 = 1, - .fp16 = 1 - } -}; - -static const struct dc_debug_options debug_defaults = { - .enable_legacy_fast_update = true, -}; - -#define CTX ctx -#define REG(reg) mm ## reg - -#ifndef mmCC_DC_HDMI_STRAPS -#define mmCC_DC_HDMI_STRAPS 0x1918 -#define CC_DC_HDMI_STRAPS__HDMI_DISABLE_MASK 0x40 -#define CC_DC_HDMI_STRAPS__HDMI_DISABLE__SHIFT 0x6 -#define CC_DC_HDMI_STRAPS__AUDIO_STREAM_NUMBER_MASK 0x700 -#define CC_DC_HDMI_STRAPS__AUDIO_STREAM_NUMBER__SHIFT 0x8 -#endif - -static int map_transmitter_id_to_phy_instance( - enum transmitter transmitter) -{ - switch (transmitter) { - case TRANSMITTER_UNIPHY_A: - return 0; - case TRANSMITTER_UNIPHY_B: - return 1; - case TRANSMITTER_UNIPHY_C: - return 2; - case TRANSMITTER_UNIPHY_D: - return 3; - case TRANSMITTER_UNIPHY_E: - return 4; - case TRANSMITTER_UNIPHY_F: - return 5; - case TRANSMITTER_UNIPHY_G: - return 6; - default: - ASSERT(0); - return 0; - } -} - -static void read_dce_straps( - struct dc_context *ctx, - struct resource_straps *straps) -{ - REG_GET_2(CC_DC_HDMI_STRAPS, - HDMI_DISABLE, &straps->hdmi_disable, - AUDIO_STREAM_NUMBER, &straps->audio_stream_number); - - REG_GET(DC_PINSTRAPS, DC_PINSTRAPS_AUDIO, &straps->dc_pinstraps_audio); -} - -static struct audio *create_audio( - struct dc_context *ctx, unsigned int inst) -{ - return dce_audio_create(ctx, inst, - &audio_regs[inst], &audio_shift, &audio_mask); -} - -static struct timing_generator *dce100_timing_generator_create( - struct dc_context *ctx, - uint32_t instance, - const struct dce110_timing_generator_offsets *offsets) -{ - struct dce110_timing_generator *tg110 = - kzalloc(sizeof(struct dce110_timing_generator), GFP_KERNEL); - - if (!tg110) - return NULL; - - dce110_timing_generator_construct(tg110, ctx, instance, offsets); - return &tg110->base; -} - -static struct stream_encoder *dce100_stream_encoder_create( - enum engine_id eng_id, - struct dc_context *ctx) -{ - struct dce110_stream_encoder *enc110 = - kzalloc(sizeof(struct dce110_stream_encoder), GFP_KERNEL); - - if (!enc110) - return NULL; - - dce110_stream_encoder_construct(enc110, ctx, ctx->dc_bios, eng_id, - &stream_enc_regs[eng_id], &se_shift, &se_mask); - return &enc110->base; -} - -#define SRII(reg_name, block, id)\ - .reg_name[id] = mm ## block ## id ## _ ## reg_name - -static const struct dce_hwseq_registers hwseq_reg = { - HWSEQ_DCE10_REG_LIST() -}; - -static const struct dce_hwseq_shift hwseq_shift = { - HWSEQ_DCE10_MASK_SH_LIST(__SHIFT) -}; - -static const struct dce_hwseq_mask hwseq_mask = { - HWSEQ_DCE10_MASK_SH_LIST(_MASK) -}; - -static struct dce_hwseq *dce100_hwseq_create( - struct dc_context *ctx) -{ - struct dce_hwseq *hws = kzalloc(sizeof(struct dce_hwseq), GFP_KERNEL); - - if (hws) { - hws->ctx = ctx; - hws->regs = &hwseq_reg; - hws->shifts = &hwseq_shift; - hws->masks = &hwseq_mask; - } - return hws; -} - -static const struct resource_create_funcs res_create_funcs = { - .read_dce_straps = read_dce_straps, - .create_audio = create_audio, - .create_stream_encoder = dce100_stream_encoder_create, - .create_hwseq = dce100_hwseq_create, -}; - -#define mi_inst_regs(id) { \ - MI_DCE8_REG_LIST(id), \ - .MC_HUB_RDREQ_DMIF_LIMIT = mmMC_HUB_RDREQ_DMIF_LIMIT \ -} -static const struct dce_mem_input_registers mi_regs[] = { - mi_inst_regs(0), - mi_inst_regs(1), - mi_inst_regs(2), - mi_inst_regs(3), - mi_inst_regs(4), - mi_inst_regs(5), -}; - -static const struct dce_mem_input_shift mi_shifts = { - MI_DCE8_MASK_SH_LIST(__SHIFT), - .ENABLE = MC_HUB_RDREQ_DMIF_LIMIT__ENABLE__SHIFT -}; - -static const struct dce_mem_input_mask mi_masks = { - MI_DCE8_MASK_SH_LIST(_MASK), - .ENABLE = MC_HUB_RDREQ_DMIF_LIMIT__ENABLE_MASK -}; - -static const struct dce110_aux_registers_shift aux_shift = { - DCE10_AUX_MASK_SH_LIST(__SHIFT) -}; - -static const struct dce110_aux_registers_mask aux_mask = { - DCE10_AUX_MASK_SH_LIST(_MASK) -}; - -static struct mem_input *dce100_mem_input_create( - struct dc_context *ctx, - uint32_t inst) -{ - struct dce_mem_input *dce_mi = kzalloc(sizeof(struct dce_mem_input), - GFP_KERNEL); - - if (!dce_mi) { - BREAK_TO_DEBUGGER(); - return NULL; - } - - dce_mem_input_construct(dce_mi, ctx, inst, &mi_regs[inst], &mi_shifts, &mi_masks); - dce_mi->wa.single_head_rdreq_dmif_limit = 2; - return &dce_mi->base; -} - -static void dce100_transform_destroy(struct transform **xfm) -{ - kfree(TO_DCE_TRANSFORM(*xfm)); - *xfm = NULL; -} - -static struct transform *dce100_transform_create( - struct dc_context *ctx, - uint32_t inst) -{ - struct dce_transform *transform = - kzalloc(sizeof(struct dce_transform), GFP_KERNEL); - - if (!transform) - return NULL; - - dce_transform_construct(transform, ctx, inst, - &xfm_regs[inst], &xfm_shift, &xfm_mask); - return &transform->base; -} - -static struct input_pixel_processor *dce100_ipp_create( - struct dc_context *ctx, uint32_t inst) -{ - struct dce_ipp *ipp = kzalloc(sizeof(struct dce_ipp), GFP_KERNEL); - - if (!ipp) { - BREAK_TO_DEBUGGER(); - return NULL; - } - - dce_ipp_construct(ipp, ctx, inst, - &ipp_regs[inst], &ipp_shift, &ipp_mask); - return &ipp->base; -} - -static const struct encoder_feature_support link_enc_feature = { - .max_hdmi_deep_color = COLOR_DEPTH_121212, - .max_hdmi_pixel_clock = 300000, - .flags.bits.IS_HBR2_CAPABLE = true, - .flags.bits.IS_TPS3_CAPABLE = true -}; - -static struct link_encoder *dce100_link_encoder_create( - struct dc_context *ctx, - const struct encoder_init_data *enc_init_data) -{ - struct dce110_link_encoder *enc110 = - kzalloc(sizeof(struct dce110_link_encoder), GFP_KERNEL); - int link_regs_id; - - if (!enc110) - return NULL; - - link_regs_id = - map_transmitter_id_to_phy_instance(enc_init_data->transmitter); - - dce110_link_encoder_construct(enc110, - enc_init_data, - &link_enc_feature, - &link_enc_regs[link_regs_id], - &link_enc_aux_regs[enc_init_data->channel - 1], - &link_enc_hpd_regs[enc_init_data->hpd_source]); - return &enc110->base; -} - -static struct panel_cntl *dce100_panel_cntl_create(const struct panel_cntl_init_data *init_data) -{ - struct dce_panel_cntl *panel_cntl = - kzalloc(sizeof(struct dce_panel_cntl), GFP_KERNEL); - - if (!panel_cntl) - return NULL; - - dce_panel_cntl_construct(panel_cntl, - init_data, - &panel_cntl_regs[init_data->inst], - &panel_cntl_shift, - &panel_cntl_mask); - - return &panel_cntl->base; -} - -static struct output_pixel_processor *dce100_opp_create( - struct dc_context *ctx, - uint32_t inst) -{ - struct dce110_opp *opp = - kzalloc(sizeof(struct dce110_opp), GFP_KERNEL); - - if (!opp) - return NULL; - - dce110_opp_construct(opp, - ctx, inst, &opp_regs[inst], &opp_shift, &opp_mask); - return &opp->base; -} - -static struct dce_aux *dce100_aux_engine_create( - struct dc_context *ctx, - uint32_t inst) -{ - struct aux_engine_dce110 *aux_engine = - kzalloc(sizeof(struct aux_engine_dce110), GFP_KERNEL); - - if (!aux_engine) - return NULL; - - dce110_aux_engine_construct(aux_engine, ctx, inst, - SW_AUX_TIMEOUT_PERIOD_MULTIPLIER * AUX_TIMEOUT_PERIOD, - &aux_engine_regs[inst], - &aux_mask, - &aux_shift, - ctx->dc->caps.extended_aux_timeout_support); - - return &aux_engine->base; -} -#define i2c_inst_regs(id) { I2C_HW_ENGINE_COMMON_REG_LIST(id) } - -static const struct dce_i2c_registers i2c_hw_regs[] = { - i2c_inst_regs(1), - i2c_inst_regs(2), - i2c_inst_regs(3), - i2c_inst_regs(4), - i2c_inst_regs(5), - i2c_inst_regs(6), -}; - -static const struct dce_i2c_shift i2c_shifts = { - I2C_COMMON_MASK_SH_LIST_DCE_COMMON_BASE(__SHIFT) -}; - -static const struct dce_i2c_mask i2c_masks = { - I2C_COMMON_MASK_SH_LIST_DCE_COMMON_BASE(_MASK) -}; - -static struct dce_i2c_hw *dce100_i2c_hw_create( - struct dc_context *ctx, - uint32_t inst) -{ - struct dce_i2c_hw *dce_i2c_hw = - kzalloc(sizeof(struct dce_i2c_hw), GFP_KERNEL); - - if (!dce_i2c_hw) - return NULL; - - dce100_i2c_hw_construct(dce_i2c_hw, ctx, inst, - &i2c_hw_regs[inst], &i2c_shifts, &i2c_masks); - - return dce_i2c_hw; -} -static struct clock_source *dce100_clock_source_create( - struct dc_context *ctx, - struct dc_bios *bios, - enum clock_source_id id, - const struct dce110_clk_src_regs *regs, - bool dp_clk_src) -{ - struct dce110_clk_src *clk_src = - kzalloc(sizeof(struct dce110_clk_src), GFP_KERNEL); - - if (!clk_src) - return NULL; - - if (dce110_clk_src_construct(clk_src, ctx, bios, id, - regs, &cs_shift, &cs_mask)) { - clk_src->base.dp_clk_src = dp_clk_src; - return &clk_src->base; - } - - kfree(clk_src); - BREAK_TO_DEBUGGER(); - return NULL; -} - -static void dce100_clock_source_destroy(struct clock_source **clk_src) -{ - kfree(TO_DCE110_CLK_SRC(*clk_src)); - *clk_src = NULL; -} - -static void dce100_resource_destruct(struct dce110_resource_pool *pool) -{ - unsigned int i; - - for (i = 0; i < pool->base.pipe_count; i++) { - if (pool->base.opps[i] != NULL) - dce110_opp_destroy(&pool->base.opps[i]); - - if (pool->base.transforms[i] != NULL) - dce100_transform_destroy(&pool->base.transforms[i]); - - if (pool->base.ipps[i] != NULL) - dce_ipp_destroy(&pool->base.ipps[i]); - - if (pool->base.mis[i] != NULL) { - kfree(TO_DCE_MEM_INPUT(pool->base.mis[i])); - pool->base.mis[i] = NULL; - } - - if (pool->base.timing_generators[i] != NULL) { - kfree(DCE110TG_FROM_TG(pool->base.timing_generators[i])); - pool->base.timing_generators[i] = NULL; - } - } - - for (i = 0; i < pool->base.res_cap->num_ddc; i++) { - if (pool->base.engines[i] != NULL) - dce110_engine_destroy(&pool->base.engines[i]); - if (pool->base.hw_i2cs[i] != NULL) { - kfree(pool->base.hw_i2cs[i]); - pool->base.hw_i2cs[i] = NULL; - } - if (pool->base.sw_i2cs[i] != NULL) { - kfree(pool->base.sw_i2cs[i]); - pool->base.sw_i2cs[i] = NULL; - } - } - - for (i = 0; i < pool->base.stream_enc_count; i++) { - if (pool->base.stream_enc[i] != NULL) - kfree(DCE110STRENC_FROM_STRENC(pool->base.stream_enc[i])); - } - - for (i = 0; i < pool->base.clk_src_count; i++) { - if (pool->base.clock_sources[i] != NULL) - dce100_clock_source_destroy(&pool->base.clock_sources[i]); - } - - if (pool->base.dp_clock_source != NULL) - dce100_clock_source_destroy(&pool->base.dp_clock_source); - - for (i = 0; i < pool->base.audio_count; i++) { - if (pool->base.audios[i] != NULL) - dce_aud_destroy(&pool->base.audios[i]); - } - - if (pool->base.abm != NULL) - dce_abm_destroy(&pool->base.abm); - - if (pool->base.dmcu != NULL) - dce_dmcu_destroy(&pool->base.dmcu); - - if (pool->base.irqs != NULL) - dal_irq_service_destroy(&pool->base.irqs); -} - -static enum dc_status build_mapped_resource( - const struct dc *dc, - struct dc_state *context, - struct dc_stream_state *stream) -{ - struct pipe_ctx *pipe_ctx = resource_get_otg_master_for_stream(&context->res_ctx, stream); - - if (!pipe_ctx) - return DC_ERROR_UNEXPECTED; - - dce110_resource_build_pipe_hw_param(pipe_ctx); - - resource_build_info_frame(pipe_ctx); - - return DC_OK; -} - -static bool dce100_validate_bandwidth( - struct dc *dc, - struct dc_state *context, - bool fast_validate) -{ - int i; - bool at_least_one_pipe = false; - - for (i = 0; i < dc->res_pool->pipe_count; i++) { - if (context->res_ctx.pipe_ctx[i].stream) - at_least_one_pipe = true; - } - - if (at_least_one_pipe) { - /* TODO implement when needed but for now hardcode max value*/ - context->bw_ctx.bw.dce.dispclk_khz = 681000; - context->bw_ctx.bw.dce.yclk_khz = 250000 * MEMORY_TYPE_MULTIPLIER_CZ; - } else { - context->bw_ctx.bw.dce.dispclk_khz = 0; - context->bw_ctx.bw.dce.yclk_khz = 0; - } - - return true; -} - -static bool dce100_validate_surface_sets( - struct dc_state *context) -{ - int i; - - for (i = 0; i < context->stream_count; i++) { - if (context->stream_status[i].plane_count == 0) - continue; - - if (context->stream_status[i].plane_count > 1) - return false; - - if (context->stream_status[i].plane_states[0]->format - >= SURFACE_PIXEL_FORMAT_VIDEO_BEGIN) - return false; - } - - return true; -} - -static enum dc_status dce100_validate_global( - struct dc *dc, - struct dc_state *context) -{ - if (!dce100_validate_surface_sets(context)) - return DC_FAIL_SURFACE_VALIDATE; - - return DC_OK; -} - -enum dc_status dce100_add_stream_to_ctx( - struct dc *dc, - struct dc_state *new_ctx, - struct dc_stream_state *dc_stream) -{ - enum dc_status result = DC_ERROR_UNEXPECTED; - - result = resource_map_pool_resources(dc, new_ctx, dc_stream); - - if (result == DC_OK) - result = resource_map_clock_resources(dc, new_ctx, dc_stream); - - if (result == DC_OK) - result = build_mapped_resource(dc, new_ctx, dc_stream); - - return result; -} - -static void dce100_destroy_resource_pool(struct resource_pool **pool) -{ - struct dce110_resource_pool *dce110_pool = TO_DCE110_RES_POOL(*pool); - - dce100_resource_destruct(dce110_pool); - kfree(dce110_pool); - *pool = NULL; -} - -enum dc_status dce100_validate_plane(const struct dc_plane_state *plane_state, struct dc_caps *caps) -{ - - if (plane_state->format < SURFACE_PIXEL_FORMAT_VIDEO_BEGIN) - return DC_OK; - - return DC_FAIL_SURFACE_VALIDATE; -} - -struct stream_encoder *dce100_find_first_free_match_stream_enc_for_link( - struct resource_context *res_ctx, - const struct resource_pool *pool, - struct dc_stream_state *stream) -{ - int i; - int j = -1; - struct dc_link *link = stream->link; - - for (i = 0; i < pool->stream_enc_count; i++) { - if (!res_ctx->is_stream_enc_acquired[i] && - pool->stream_enc[i]) { - /* Store first available for MST second display - * in daisy chain use case - */ - j = i; - if (pool->stream_enc[i]->id == - link->link_enc->preferred_engine) - return pool->stream_enc[i]; - } - } - - /* - * below can happen in cases when stream encoder is acquired: - * 1) for second MST display in chain, so preferred engine already - * acquired; - * 2) for another link, which preferred engine already acquired by any - * MST configuration. - * - * If signal is of DP type and preferred engine not found, return last available - * - * TODO - This is just a patch up and a generic solution is - * required for non DP connectors. - */ - - if (j >= 0 && link->connector_signal == SIGNAL_TYPE_DISPLAY_PORT) - return pool->stream_enc[j]; - - return NULL; -} - -static const struct resource_funcs dce100_res_pool_funcs = { - .destroy = dce100_destroy_resource_pool, - .link_enc_create = dce100_link_encoder_create, - .panel_cntl_create = dce100_panel_cntl_create, - .validate_bandwidth = dce100_validate_bandwidth, - .validate_plane = dce100_validate_plane, - .add_stream_to_ctx = dce100_add_stream_to_ctx, - .validate_global = dce100_validate_global, - .find_first_free_match_stream_enc_for_link = dce100_find_first_free_match_stream_enc_for_link -}; - -static bool dce100_resource_construct( - uint8_t num_virtual_links, - struct dc *dc, - struct dce110_resource_pool *pool) -{ - unsigned int i; - struct dc_context *ctx = dc->ctx; - struct dc_bios *bp; - - ctx->dc_bios->regs = &bios_regs; - - pool->base.res_cap = &res_cap; - pool->base.funcs = &dce100_res_pool_funcs; - pool->base.underlay_pipe_index = NO_UNDERLAY_PIPE; - - bp = ctx->dc_bios; - - if (bp->fw_info_valid && bp->fw_info.external_clock_source_frequency_for_dp != 0) { - pool->base.dp_clock_source = - dce100_clock_source_create(ctx, bp, CLOCK_SOURCE_ID_EXTERNAL, NULL, true); - - pool->base.clock_sources[0] = - dce100_clock_source_create(ctx, bp, CLOCK_SOURCE_ID_PLL0, &clk_src_regs[0], false); - pool->base.clock_sources[1] = - dce100_clock_source_create(ctx, bp, CLOCK_SOURCE_ID_PLL1, &clk_src_regs[1], false); - pool->base.clock_sources[2] = - dce100_clock_source_create(ctx, bp, CLOCK_SOURCE_ID_PLL2, &clk_src_regs[2], false); - pool->base.clk_src_count = 3; - - } else { - pool->base.dp_clock_source = - dce100_clock_source_create(ctx, bp, CLOCK_SOURCE_ID_PLL0, &clk_src_regs[0], true); - - pool->base.clock_sources[0] = - dce100_clock_source_create(ctx, bp, CLOCK_SOURCE_ID_PLL1, &clk_src_regs[1], false); - pool->base.clock_sources[1] = - dce100_clock_source_create(ctx, bp, CLOCK_SOURCE_ID_PLL2, &clk_src_regs[2], false); - pool->base.clk_src_count = 2; - } - - if (pool->base.dp_clock_source == NULL) { - dm_error("DC: failed to create dp clock source!\n"); - BREAK_TO_DEBUGGER(); - goto res_create_fail; - } - - for (i = 0; i < pool->base.clk_src_count; i++) { - if (pool->base.clock_sources[i] == NULL) { - dm_error("DC: failed to create clock sources!\n"); - BREAK_TO_DEBUGGER(); - goto res_create_fail; - } - } - - pool->base.dmcu = dce_dmcu_create(ctx, - &dmcu_regs, - &dmcu_shift, - &dmcu_mask); - if (pool->base.dmcu == NULL) { - dm_error("DC: failed to create dmcu!\n"); - BREAK_TO_DEBUGGER(); - goto res_create_fail; - } - - pool->base.abm = dce_abm_create(ctx, - &abm_regs, - &abm_shift, - &abm_mask); - if (pool->base.abm == NULL) { - dm_error("DC: failed to create abm!\n"); - BREAK_TO_DEBUGGER(); - goto res_create_fail; - } - - { - struct irq_service_init_data init_data; - init_data.ctx = dc->ctx; - pool->base.irqs = dal_irq_service_dce110_create(&init_data); - if (!pool->base.irqs) - goto res_create_fail; - } - - /************************************************* - * Resource + asic cap harcoding * - *************************************************/ - pool->base.underlay_pipe_index = NO_UNDERLAY_PIPE; - pool->base.pipe_count = res_cap.num_timing_generator; - pool->base.timing_generator_count = pool->base.res_cap->num_timing_generator; - dc->caps.max_downscale_ratio = 200; - dc->caps.i2c_speed_in_khz = 40; - dc->caps.i2c_speed_in_khz = 40; - dc->caps.max_cursor_size = 128; - dc->caps.min_horizontal_blanking_period = 80; - dc->caps.dual_link_dvi = true; - dc->caps.disable_dp_clk_share = true; - dc->caps.extended_aux_timeout_support = false; - dc->debug = debug_defaults; - - for (i = 0; i < pool->base.pipe_count; i++) { - pool->base.timing_generators[i] = - dce100_timing_generator_create( - ctx, - i, - &dce100_tg_offsets[i]); - if (pool->base.timing_generators[i] == NULL) { - BREAK_TO_DEBUGGER(); - dm_error("DC: failed to create tg!\n"); - goto res_create_fail; - } - - pool->base.mis[i] = dce100_mem_input_create(ctx, i); - if (pool->base.mis[i] == NULL) { - BREAK_TO_DEBUGGER(); - dm_error( - "DC: failed to create memory input!\n"); - goto res_create_fail; - } - - pool->base.ipps[i] = dce100_ipp_create(ctx, i); - if (pool->base.ipps[i] == NULL) { - BREAK_TO_DEBUGGER(); - dm_error( - "DC: failed to create input pixel processor!\n"); - goto res_create_fail; - } - - pool->base.transforms[i] = dce100_transform_create(ctx, i); - if (pool->base.transforms[i] == NULL) { - BREAK_TO_DEBUGGER(); - dm_error( - "DC: failed to create transform!\n"); - goto res_create_fail; - } - - pool->base.opps[i] = dce100_opp_create(ctx, i); - if (pool->base.opps[i] == NULL) { - BREAK_TO_DEBUGGER(); - dm_error( - "DC: failed to create output pixel processor!\n"); - goto res_create_fail; - } - } - - for (i = 0; i < pool->base.res_cap->num_ddc; i++) { - pool->base.engines[i] = dce100_aux_engine_create(ctx, i); - if (pool->base.engines[i] == NULL) { - BREAK_TO_DEBUGGER(); - dm_error( - "DC:failed to create aux engine!!\n"); - goto res_create_fail; - } - pool->base.hw_i2cs[i] = dce100_i2c_hw_create(ctx, i); - if (pool->base.hw_i2cs[i] == NULL) { - BREAK_TO_DEBUGGER(); - dm_error( - "DC:failed to create i2c engine!!\n"); - goto res_create_fail; - } - pool->base.sw_i2cs[i] = NULL; - } - - dc->caps.max_planes = pool->base.pipe_count; - - for (i = 0; i < dc->caps.max_planes; ++i) - dc->caps.planes[i] = plane_cap; - - if (!resource_construct(num_virtual_links, dc, &pool->base, - &res_create_funcs)) - goto res_create_fail; - - /* Create hardware sequencer */ - dce100_hw_sequencer_construct(dc); - return true; - -res_create_fail: - dce100_resource_destruct(pool); - - return false; -} - -struct resource_pool *dce100_create_resource_pool( - uint8_t num_virtual_links, - struct dc *dc) -{ - struct dce110_resource_pool *pool = - kzalloc(sizeof(struct dce110_resource_pool), GFP_KERNEL); - - if (!pool) - return NULL; - - if (dce100_resource_construct(num_virtual_links, dc, pool)) - return &pool->base; - - kfree(pool); - BREAK_TO_DEBUGGER(); - return NULL; -} - diff --git a/drivers/gpu/drm/amd/display/dc/dce100/dce100_resource.h b/drivers/gpu/drm/amd/display/dc/dce100/dce100_resource.h deleted file mode 100644 index fecab7c560f5..000000000000 --- a/drivers/gpu/drm/amd/display/dc/dce100/dce100_resource.h +++ /dev/null @@ -1,54 +0,0 @@ -/* - * Copyright 2017 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. - * - * - */ -/* - * dce100_resource.h - * - * Created on: 2016-01-20 - * Author: qyang - */ - -#ifndef DCE100_RESOURCE_H_ -#define DCE100_RESOURCE_H_ - -struct dc; -struct resource_pool; -struct dc_validation_set; - -struct resource_pool *dce100_create_resource_pool( - uint8_t num_virtual_links, - struct dc *dc); - -enum dc_status dce100_validate_plane(const struct dc_plane_state *plane_state, struct dc_caps *caps); - -enum dc_status dce100_add_stream_to_ctx( - struct dc *dc, - struct dc_state *new_ctx, - struct dc_stream_state *dc_stream); - -struct stream_encoder *dce100_find_first_free_match_stream_enc_for_link( - struct resource_context *res_ctx, - const struct resource_pool *pool, - struct dc_stream_state *stream); - -#endif /* DCE100_RESOURCE_H_ */ diff --git a/drivers/gpu/drm/amd/display/dc/dce110/Makefile b/drivers/gpu/drm/amd/display/dc/dce110/Makefile index 695a50ed5ad2..f0777d61c2cb 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/Makefile +++ b/drivers/gpu/drm/amd/display/dc/dce110/Makefile @@ -26,8 +26,8 @@ CFLAGS_$(AMDDALPATH)/dc/dce110/dce110_resource.o = $(call cc-disable-warning, override-init) DCE110 = dce110_timing_generator.o \ -dce110_compressor.o dce110_resource.o \ -dce110_opp_regamma_v.o dce110_opp_csc_v.o dce110_timing_generator_v.o \ +dce110_compressor.o dce110_opp_regamma_v.o \ +dce110_opp_csc_v.o dce110_timing_generator_v.o \ dce110_mem_input_v.o dce110_opp_v.o dce110_transform_v.o AMD_DAL_DCE110 = $(addprefix $(AMDDALPATH)/dc/dce110/,$(DCE110)) diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c deleted file mode 100644 index fe518fd27b08..000000000000 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c +++ /dev/null @@ -1,1551 +0,0 @@ -/* - * Copyright 2012-15 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 "dm_services.h" - -#include "link_encoder.h" -#include "stream_encoder.h" - -#include "resource.h" -#include "dce110/dce110_resource.h" -#include "include/irq_service_interface.h" -#include "dce/dce_audio.h" -#include "dce110/dce110_timing_generator.h" -#include "irq/dce110/irq_service_dce110.h" -#include "dce110/dce110_timing_generator_v.h" -#include "dce/dce_link_encoder.h" -#include "dce/dce_stream_encoder.h" -#include "dce/dce_mem_input.h" -#include "dce110/dce110_mem_input_v.h" -#include "dce/dce_ipp.h" -#include "dce/dce_transform.h" -#include "dce110/dce110_transform_v.h" -#include "dce/dce_opp.h" -#include "dce110/dce110_opp_v.h" -#include "dce/dce_clock_source.h" -#include "dce/dce_hwseq.h" -#include "dce110/dce110_hwseq.h" -#include "dce/dce_aux.h" -#include "dce/dce_abm.h" -#include "dce/dce_dmcu.h" -#include "dce/dce_i2c.h" -#include "dce/dce_panel_cntl.h" - -#define DC_LOGGER \ - dc->ctx->logger - -#include "dce110/dce110_compressor.h" - -#include "reg_helper.h" - -#include "dce/dce_11_0_d.h" -#include "dce/dce_11_0_sh_mask.h" - -#ifndef mmMC_HUB_RDREQ_DMIF_LIMIT -#include "gmc/gmc_8_2_d.h" -#include "gmc/gmc_8_2_sh_mask.h" -#endif - -#ifndef mmDP_DPHY_INTERNAL_CTRL - #define mmDP_DPHY_INTERNAL_CTRL 0x4aa7 - #define mmDP0_DP_DPHY_INTERNAL_CTRL 0x4aa7 - #define mmDP1_DP_DPHY_INTERNAL_CTRL 0x4ba7 - #define mmDP2_DP_DPHY_INTERNAL_CTRL 0x4ca7 - #define mmDP3_DP_DPHY_INTERNAL_CTRL 0x4da7 - #define mmDP4_DP_DPHY_INTERNAL_CTRL 0x4ea7 - #define mmDP5_DP_DPHY_INTERNAL_CTRL 0x4fa7 - #define mmDP6_DP_DPHY_INTERNAL_CTRL 0x54a7 - #define mmDP7_DP_DPHY_INTERNAL_CTRL 0x56a7 - #define mmDP8_DP_DPHY_INTERNAL_CTRL 0x57a7 -#endif - -#ifndef mmBIOS_SCRATCH_2 - #define mmBIOS_SCRATCH_2 0x05CB - #define mmBIOS_SCRATCH_3 0x05CC - #define mmBIOS_SCRATCH_6 0x05CF -#endif - -#ifndef mmDP_DPHY_BS_SR_SWAP_CNTL - #define mmDP_DPHY_BS_SR_SWAP_CNTL 0x4ADC - #define mmDP0_DP_DPHY_BS_SR_SWAP_CNTL 0x4ADC - #define mmDP1_DP_DPHY_BS_SR_SWAP_CNTL 0x4BDC - #define mmDP2_DP_DPHY_BS_SR_SWAP_CNTL 0x4CDC - #define mmDP3_DP_DPHY_BS_SR_SWAP_CNTL 0x4DDC - #define mmDP4_DP_DPHY_BS_SR_SWAP_CNTL 0x4EDC - #define mmDP5_DP_DPHY_BS_SR_SWAP_CNTL 0x4FDC - #define mmDP6_DP_DPHY_BS_SR_SWAP_CNTL 0x54DC -#endif - -#ifndef mmDP_DPHY_FAST_TRAINING - #define mmDP_DPHY_FAST_TRAINING 0x4ABC - #define mmDP0_DP_DPHY_FAST_TRAINING 0x4ABC - #define mmDP1_DP_DPHY_FAST_TRAINING 0x4BBC - #define mmDP2_DP_DPHY_FAST_TRAINING 0x4CBC - #define mmDP3_DP_DPHY_FAST_TRAINING 0x4DBC - #define mmDP4_DP_DPHY_FAST_TRAINING 0x4EBC - #define mmDP5_DP_DPHY_FAST_TRAINING 0x4FBC - #define mmDP6_DP_DPHY_FAST_TRAINING 0x54BC -#endif - -#ifndef DPHY_RX_FAST_TRAINING_CAPABLE - #define DPHY_RX_FAST_TRAINING_CAPABLE 0x1 -#endif - -static const struct dce110_timing_generator_offsets dce110_tg_offsets[] = { - { - .crtc = (mmCRTC0_CRTC_CONTROL - mmCRTC_CONTROL), - .dcp = (mmDCP0_GRPH_CONTROL - mmGRPH_CONTROL), - }, - { - .crtc = (mmCRTC1_CRTC_CONTROL - mmCRTC_CONTROL), - .dcp = (mmDCP1_GRPH_CONTROL - mmGRPH_CONTROL), - }, - { - .crtc = (mmCRTC2_CRTC_CONTROL - mmCRTC_CONTROL), - .dcp = (mmDCP2_GRPH_CONTROL - mmGRPH_CONTROL), - }, - { - .crtc = (mmCRTC3_CRTC_CONTROL - mmCRTC_CONTROL), - .dcp = (mmDCP3_GRPH_CONTROL - mmGRPH_CONTROL), - }, - { - .crtc = (mmCRTC4_CRTC_CONTROL - mmCRTC_CONTROL), - .dcp = (mmDCP4_GRPH_CONTROL - mmGRPH_CONTROL), - }, - { - .crtc = (mmCRTC5_CRTC_CONTROL - mmCRTC_CONTROL), - .dcp = (mmDCP5_GRPH_CONTROL - mmGRPH_CONTROL), - } -}; - -/* set register offset */ -#define SR(reg_name)\ - .reg_name = mm ## reg_name - -/* set register offset with instance */ -#define SRI(reg_name, block, id)\ - .reg_name = mm ## block ## id ## _ ## reg_name - -static const struct dce_dmcu_registers dmcu_regs = { - DMCU_DCE110_COMMON_REG_LIST() -}; - -static const struct dce_dmcu_shift dmcu_shift = { - DMCU_MASK_SH_LIST_DCE110(__SHIFT) -}; - -static const struct dce_dmcu_mask dmcu_mask = { - DMCU_MASK_SH_LIST_DCE110(_MASK) -}; - -static const struct dce_abm_registers abm_regs = { - ABM_DCE110_COMMON_REG_LIST() -}; - -static const struct dce_abm_shift abm_shift = { - ABM_MASK_SH_LIST_DCE110(__SHIFT) -}; - -static const struct dce_abm_mask abm_mask = { - ABM_MASK_SH_LIST_DCE110(_MASK) -}; - -#define ipp_regs(id)\ -[id] = {\ - IPP_DCE110_REG_LIST_DCE_BASE(id)\ -} - -static const struct dce_ipp_registers ipp_regs[] = { - ipp_regs(0), - ipp_regs(1), - ipp_regs(2) -}; - -static const struct dce_ipp_shift ipp_shift = { - IPP_DCE100_MASK_SH_LIST_DCE_COMMON_BASE(__SHIFT) -}; - -static const struct dce_ipp_mask ipp_mask = { - IPP_DCE100_MASK_SH_LIST_DCE_COMMON_BASE(_MASK) -}; - -#define transform_regs(id)\ -[id] = {\ - XFM_COMMON_REG_LIST_DCE110(id)\ -} - -static const struct dce_transform_registers xfm_regs[] = { - transform_regs(0), - transform_regs(1), - transform_regs(2) -}; - -static const struct dce_transform_shift xfm_shift = { - XFM_COMMON_MASK_SH_LIST_DCE110(__SHIFT) -}; - -static const struct dce_transform_mask xfm_mask = { - XFM_COMMON_MASK_SH_LIST_DCE110(_MASK) -}; - -#define aux_regs(id)\ -[id] = {\ - AUX_REG_LIST(id)\ -} - -static const struct dce110_link_enc_aux_registers link_enc_aux_regs[] = { - aux_regs(0), - aux_regs(1), - aux_regs(2), - aux_regs(3), - aux_regs(4), - aux_regs(5) -}; - -#define hpd_regs(id)\ -[id] = {\ - HPD_REG_LIST(id)\ -} - -static const struct dce110_link_enc_hpd_registers link_enc_hpd_regs[] = { - hpd_regs(0), - hpd_regs(1), - hpd_regs(2), - hpd_regs(3), - hpd_regs(4), - hpd_regs(5) -}; - - -#define link_regs(id)\ -[id] = {\ - LE_DCE110_REG_LIST(id)\ -} - -static const struct dce110_link_enc_registers link_enc_regs[] = { - link_regs(0), - link_regs(1), - link_regs(2), - link_regs(3), - link_regs(4), - link_regs(5), - link_regs(6), -}; - -#define stream_enc_regs(id)\ -[id] = {\ - SE_COMMON_REG_LIST(id),\ - .TMDS_CNTL = 0,\ -} - -static const struct dce110_stream_enc_registers stream_enc_regs[] = { - stream_enc_regs(0), - stream_enc_regs(1), - stream_enc_regs(2) -}; - -static const struct dce_stream_encoder_shift se_shift = { - SE_COMMON_MASK_SH_LIST_DCE110(__SHIFT) -}; - -static const struct dce_stream_encoder_mask se_mask = { - SE_COMMON_MASK_SH_LIST_DCE110(_MASK) -}; - -static const struct dce_panel_cntl_registers panel_cntl_regs[] = { - { DCE_PANEL_CNTL_REG_LIST() } -}; - -static const struct dce_panel_cntl_shift panel_cntl_shift = { - DCE_PANEL_CNTL_MASK_SH_LIST(__SHIFT) -}; - -static const struct dce_panel_cntl_mask panel_cntl_mask = { - DCE_PANEL_CNTL_MASK_SH_LIST(_MASK) -}; - -static const struct dce110_aux_registers_shift aux_shift = { - DCE_AUX_MASK_SH_LIST(__SHIFT) -}; - -static const struct dce110_aux_registers_mask aux_mask = { - DCE_AUX_MASK_SH_LIST(_MASK) -}; - -#define opp_regs(id)\ -[id] = {\ - OPP_DCE_110_REG_LIST(id),\ -} - -static const struct dce_opp_registers opp_regs[] = { - opp_regs(0), - opp_regs(1), - opp_regs(2), - opp_regs(3), - opp_regs(4), - opp_regs(5) -}; - -static const struct dce_opp_shift opp_shift = { - OPP_COMMON_MASK_SH_LIST_DCE_110(__SHIFT) -}; - -static const struct dce_opp_mask opp_mask = { - OPP_COMMON_MASK_SH_LIST_DCE_110(_MASK) -}; - -#define aux_engine_regs(id)\ -[id] = {\ - AUX_COMMON_REG_LIST(id), \ - .AUX_RESET_MASK = 0 \ -} - -static const struct dce110_aux_registers aux_engine_regs[] = { - aux_engine_regs(0), - aux_engine_regs(1), - aux_engine_regs(2), - aux_engine_regs(3), - aux_engine_regs(4), - aux_engine_regs(5) -}; - -#define audio_regs(id)\ -[id] = {\ - AUD_COMMON_REG_LIST(id)\ -} - -static const struct dce_audio_registers audio_regs[] = { - audio_regs(0), - audio_regs(1), - audio_regs(2), - audio_regs(3), - audio_regs(4), - audio_regs(5), - audio_regs(6), -}; - -static const struct dce_audio_shift audio_shift = { - AUD_COMMON_MASK_SH_LIST(__SHIFT) -}; - -static const struct dce_audio_mask audio_mask = { - AUD_COMMON_MASK_SH_LIST(_MASK) -}; - -/* AG TBD Needs to be reduced back to 3 pipes once dce10 hw sequencer implemented. */ - - -#define clk_src_regs(id)\ -[id] = {\ - CS_COMMON_REG_LIST_DCE_100_110(id),\ -} - -static const struct dce110_clk_src_regs clk_src_regs[] = { - clk_src_regs(0), - clk_src_regs(1), - clk_src_regs(2) -}; - -static const struct dce110_clk_src_shift cs_shift = { - CS_COMMON_MASK_SH_LIST_DCE_COMMON_BASE(__SHIFT) -}; - -static const struct dce110_clk_src_mask cs_mask = { - CS_COMMON_MASK_SH_LIST_DCE_COMMON_BASE(_MASK) -}; - -static const struct bios_registers bios_regs = { - .BIOS_SCRATCH_3 = mmBIOS_SCRATCH_3, - .BIOS_SCRATCH_6 = mmBIOS_SCRATCH_6 -}; - -static const struct resource_caps carrizo_resource_cap = { - .num_timing_generator = 3, - .num_video_plane = 1, - .num_audio = 3, - .num_stream_encoder = 3, - .num_pll = 2, - .num_ddc = 3, -}; - -static const struct resource_caps stoney_resource_cap = { - .num_timing_generator = 2, - .num_video_plane = 1, - .num_audio = 3, - .num_stream_encoder = 3, - .num_pll = 2, - .num_ddc = 3, -}; - -static const struct dc_plane_cap plane_cap = { - .type = DC_PLANE_TYPE_DCE_RGB, - .per_pixel_alpha = 1, - - .pixel_format_support = { - .argb8888 = true, - .nv12 = false, - .fp16 = true - }, - - .max_upscale_factor = { - .argb8888 = 16000, - .nv12 = 1, - .fp16 = 1 - }, - - .max_downscale_factor = { - .argb8888 = 250, - .nv12 = 1, - .fp16 = 1 - }, - 64, - 64 -}; - -static const struct dc_debug_options debug_defaults = { - .enable_legacy_fast_update = true, -}; - -static const struct dc_plane_cap underlay_plane_cap = { - .type = DC_PLANE_TYPE_DCE_UNDERLAY, - .per_pixel_alpha = 1, - - .pixel_format_support = { - .argb8888 = false, - .nv12 = true, - .fp16 = false - }, - - .max_upscale_factor = { - .argb8888 = 1, - .nv12 = 16000, - .fp16 = 1 - }, - - .max_downscale_factor = { - .argb8888 = 1, - .nv12 = 250, - .fp16 = 1 - }, - 64, - 64 -}; - -#define CTX ctx -#define REG(reg) mm ## reg - -#ifndef mmCC_DC_HDMI_STRAPS -#define mmCC_DC_HDMI_STRAPS 0x4819 -#define CC_DC_HDMI_STRAPS__HDMI_DISABLE_MASK 0x40 -#define CC_DC_HDMI_STRAPS__HDMI_DISABLE__SHIFT 0x6 -#define CC_DC_HDMI_STRAPS__AUDIO_STREAM_NUMBER_MASK 0x700 -#define CC_DC_HDMI_STRAPS__AUDIO_STREAM_NUMBER__SHIFT 0x8 -#endif - -static int map_transmitter_id_to_phy_instance( - enum transmitter transmitter) -{ - switch (transmitter) { - case TRANSMITTER_UNIPHY_A: - return 0; - case TRANSMITTER_UNIPHY_B: - return 1; - case TRANSMITTER_UNIPHY_C: - return 2; - case TRANSMITTER_UNIPHY_D: - return 3; - case TRANSMITTER_UNIPHY_E: - return 4; - case TRANSMITTER_UNIPHY_F: - return 5; - case TRANSMITTER_UNIPHY_G: - return 6; - default: - ASSERT(0); - return 0; - } -} - -static void read_dce_straps( - struct dc_context *ctx, - struct resource_straps *straps) -{ - REG_GET_2(CC_DC_HDMI_STRAPS, - HDMI_DISABLE, &straps->hdmi_disable, - AUDIO_STREAM_NUMBER, &straps->audio_stream_number); - - REG_GET(DC_PINSTRAPS, DC_PINSTRAPS_AUDIO, &straps->dc_pinstraps_audio); -} - -static struct audio *create_audio( - struct dc_context *ctx, unsigned int inst) -{ - return dce_audio_create(ctx, inst, - &audio_regs[inst], &audio_shift, &audio_mask); -} - -static struct timing_generator *dce110_timing_generator_create( - struct dc_context *ctx, - uint32_t instance, - const struct dce110_timing_generator_offsets *offsets) -{ - struct dce110_timing_generator *tg110 = - kzalloc(sizeof(struct dce110_timing_generator), GFP_KERNEL); - - if (!tg110) - return NULL; - - dce110_timing_generator_construct(tg110, ctx, instance, offsets); - return &tg110->base; -} - -static struct stream_encoder *dce110_stream_encoder_create( - enum engine_id eng_id, - struct dc_context *ctx) -{ - struct dce110_stream_encoder *enc110 = - kzalloc(sizeof(struct dce110_stream_encoder), GFP_KERNEL); - - if (!enc110) - return NULL; - - dce110_stream_encoder_construct(enc110, ctx, ctx->dc_bios, eng_id, - &stream_enc_regs[eng_id], - &se_shift, &se_mask); - return &enc110->base; -} - -#define SRII(reg_name, block, id)\ - .reg_name[id] = mm ## block ## id ## _ ## reg_name - -static const struct dce_hwseq_registers hwseq_stoney_reg = { - HWSEQ_ST_REG_LIST() -}; - -static const struct dce_hwseq_registers hwseq_cz_reg = { - HWSEQ_CZ_REG_LIST() -}; - -static const struct dce_hwseq_shift hwseq_shift = { - HWSEQ_DCE11_MASK_SH_LIST(__SHIFT), -}; - -static const struct dce_hwseq_mask hwseq_mask = { - HWSEQ_DCE11_MASK_SH_LIST(_MASK), -}; - -static struct dce_hwseq *dce110_hwseq_create( - struct dc_context *ctx) -{ - struct dce_hwseq *hws = kzalloc(sizeof(struct dce_hwseq), GFP_KERNEL); - - if (hws) { - hws->ctx = ctx; - hws->regs = ASIC_REV_IS_STONEY(ctx->asic_id.hw_internal_rev) ? - &hwseq_stoney_reg : &hwseq_cz_reg; - hws->shifts = &hwseq_shift; - hws->masks = &hwseq_mask; - hws->wa.blnd_crtc_trigger = true; - } - return hws; -} - -static const struct resource_create_funcs res_create_funcs = { - .read_dce_straps = read_dce_straps, - .create_audio = create_audio, - .create_stream_encoder = dce110_stream_encoder_create, - .create_hwseq = dce110_hwseq_create, -}; - -#define mi_inst_regs(id) { \ - MI_DCE11_REG_LIST(id), \ - .MC_HUB_RDREQ_DMIF_LIMIT = mmMC_HUB_RDREQ_DMIF_LIMIT \ -} -static const struct dce_mem_input_registers mi_regs[] = { - mi_inst_regs(0), - mi_inst_regs(1), - mi_inst_regs(2), -}; - -static const struct dce_mem_input_shift mi_shifts = { - MI_DCE11_MASK_SH_LIST(__SHIFT), - .ENABLE = MC_HUB_RDREQ_DMIF_LIMIT__ENABLE__SHIFT -}; - -static const struct dce_mem_input_mask mi_masks = { - MI_DCE11_MASK_SH_LIST(_MASK), - .ENABLE = MC_HUB_RDREQ_DMIF_LIMIT__ENABLE_MASK -}; - - -static struct mem_input *dce110_mem_input_create( - struct dc_context *ctx, - uint32_t inst) -{ - struct dce_mem_input *dce_mi = kzalloc(sizeof(struct dce_mem_input), - GFP_KERNEL); - - if (!dce_mi) { - BREAK_TO_DEBUGGER(); - return NULL; - } - - dce_mem_input_construct(dce_mi, ctx, inst, &mi_regs[inst], &mi_shifts, &mi_masks); - dce_mi->wa.single_head_rdreq_dmif_limit = 3; - return &dce_mi->base; -} - -static void dce110_transform_destroy(struct transform **xfm) -{ - kfree(TO_DCE_TRANSFORM(*xfm)); - *xfm = NULL; -} - -static struct transform *dce110_transform_create( - struct dc_context *ctx, - uint32_t inst) -{ - struct dce_transform *transform = - kzalloc(sizeof(struct dce_transform), GFP_KERNEL); - - if (!transform) - return NULL; - - dce_transform_construct(transform, ctx, inst, - &xfm_regs[inst], &xfm_shift, &xfm_mask); - return &transform->base; -} - -static struct input_pixel_processor *dce110_ipp_create( - struct dc_context *ctx, uint32_t inst) -{ - struct dce_ipp *ipp = kzalloc(sizeof(struct dce_ipp), GFP_KERNEL); - - if (!ipp) { - BREAK_TO_DEBUGGER(); - return NULL; - } - - dce_ipp_construct(ipp, ctx, inst, - &ipp_regs[inst], &ipp_shift, &ipp_mask); - return &ipp->base; -} - -static const struct encoder_feature_support link_enc_feature = { - .max_hdmi_deep_color = COLOR_DEPTH_121212, - .max_hdmi_pixel_clock = 300000, - .flags.bits.IS_HBR2_CAPABLE = true, - .flags.bits.IS_TPS3_CAPABLE = true -}; - -static struct link_encoder *dce110_link_encoder_create( - struct dc_context *ctx, - const struct encoder_init_data *enc_init_data) -{ - struct dce110_link_encoder *enc110 = - kzalloc(sizeof(struct dce110_link_encoder), GFP_KERNEL); - int link_regs_id; - - if (!enc110) - return NULL; - - link_regs_id = - map_transmitter_id_to_phy_instance(enc_init_data->transmitter); - - dce110_link_encoder_construct(enc110, - enc_init_data, - &link_enc_feature, - &link_enc_regs[link_regs_id], - &link_enc_aux_regs[enc_init_data->channel - 1], - &link_enc_hpd_regs[enc_init_data->hpd_source]); - return &enc110->base; -} - -static struct panel_cntl *dce110_panel_cntl_create(const struct panel_cntl_init_data *init_data) -{ - struct dce_panel_cntl *panel_cntl = - kzalloc(sizeof(struct dce_panel_cntl), GFP_KERNEL); - - if (!panel_cntl) - return NULL; - - dce_panel_cntl_construct(panel_cntl, - init_data, - &panel_cntl_regs[init_data->inst], - &panel_cntl_shift, - &panel_cntl_mask); - - return &panel_cntl->base; -} - -static struct output_pixel_processor *dce110_opp_create( - struct dc_context *ctx, - uint32_t inst) -{ - struct dce110_opp *opp = - kzalloc(sizeof(struct dce110_opp), GFP_KERNEL); - - if (!opp) - return NULL; - - dce110_opp_construct(opp, - ctx, inst, &opp_regs[inst], &opp_shift, &opp_mask); - return &opp->base; -} - -static struct dce_aux *dce110_aux_engine_create( - struct dc_context *ctx, - uint32_t inst) -{ - struct aux_engine_dce110 *aux_engine = - kzalloc(sizeof(struct aux_engine_dce110), GFP_KERNEL); - - if (!aux_engine) - return NULL; - - dce110_aux_engine_construct(aux_engine, ctx, inst, - SW_AUX_TIMEOUT_PERIOD_MULTIPLIER * AUX_TIMEOUT_PERIOD, - &aux_engine_regs[inst], - &aux_mask, - &aux_shift, - ctx->dc->caps.extended_aux_timeout_support); - - return &aux_engine->base; -} -#define i2c_inst_regs(id) { I2C_HW_ENGINE_COMMON_REG_LIST(id) } - -static const struct dce_i2c_registers i2c_hw_regs[] = { - i2c_inst_regs(1), - i2c_inst_regs(2), - i2c_inst_regs(3), - i2c_inst_regs(4), - i2c_inst_regs(5), - i2c_inst_regs(6), -}; - -static const struct dce_i2c_shift i2c_shifts = { - I2C_COMMON_MASK_SH_LIST_DCE110(__SHIFT) -}; - -static const struct dce_i2c_mask i2c_masks = { - I2C_COMMON_MASK_SH_LIST_DCE110(_MASK) -}; - -static struct dce_i2c_hw *dce110_i2c_hw_create( - struct dc_context *ctx, - uint32_t inst) -{ - struct dce_i2c_hw *dce_i2c_hw = - kzalloc(sizeof(struct dce_i2c_hw), GFP_KERNEL); - - if (!dce_i2c_hw) - return NULL; - - dce100_i2c_hw_construct(dce_i2c_hw, ctx, inst, - &i2c_hw_regs[inst], &i2c_shifts, &i2c_masks); - - return dce_i2c_hw; -} -static struct clock_source *dce110_clock_source_create( - struct dc_context *ctx, - struct dc_bios *bios, - enum clock_source_id id, - const struct dce110_clk_src_regs *regs, - bool dp_clk_src) -{ - struct dce110_clk_src *clk_src = - kzalloc(sizeof(struct dce110_clk_src), GFP_KERNEL); - - if (!clk_src) - return NULL; - - if (dce110_clk_src_construct(clk_src, ctx, bios, id, - regs, &cs_shift, &cs_mask)) { - clk_src->base.dp_clk_src = dp_clk_src; - return &clk_src->base; - } - - kfree(clk_src); - BREAK_TO_DEBUGGER(); - return NULL; -} - -static void dce110_clock_source_destroy(struct clock_source **clk_src) -{ - struct dce110_clk_src *dce110_clk_src; - - if (!clk_src) - return; - - dce110_clk_src = TO_DCE110_CLK_SRC(*clk_src); - - kfree(dce110_clk_src->dp_ss_params); - kfree(dce110_clk_src->hdmi_ss_params); - kfree(dce110_clk_src->dvi_ss_params); - - kfree(dce110_clk_src); - *clk_src = NULL; -} - -static void dce110_resource_destruct(struct dce110_resource_pool *pool) -{ - unsigned int i; - - for (i = 0; i < pool->base.pipe_count; i++) { - if (pool->base.opps[i] != NULL) - dce110_opp_destroy(&pool->base.opps[i]); - - if (pool->base.transforms[i] != NULL) - dce110_transform_destroy(&pool->base.transforms[i]); - - if (pool->base.ipps[i] != NULL) - dce_ipp_destroy(&pool->base.ipps[i]); - - if (pool->base.mis[i] != NULL) { - kfree(TO_DCE_MEM_INPUT(pool->base.mis[i])); - pool->base.mis[i] = NULL; - } - - if (pool->base.timing_generators[i] != NULL) { - kfree(DCE110TG_FROM_TG(pool->base.timing_generators[i])); - pool->base.timing_generators[i] = NULL; - } - } - - for (i = 0; i < pool->base.res_cap->num_ddc; i++) { - if (pool->base.engines[i] != NULL) - dce110_engine_destroy(&pool->base.engines[i]); - if (pool->base.hw_i2cs[i] != NULL) { - kfree(pool->base.hw_i2cs[i]); - pool->base.hw_i2cs[i] = NULL; - } - if (pool->base.sw_i2cs[i] != NULL) { - kfree(pool->base.sw_i2cs[i]); - pool->base.sw_i2cs[i] = NULL; - } - } - - for (i = 0; i < pool->base.stream_enc_count; i++) { - if (pool->base.stream_enc[i] != NULL) - kfree(DCE110STRENC_FROM_STRENC(pool->base.stream_enc[i])); - } - - for (i = 0; i < pool->base.clk_src_count; i++) { - if (pool->base.clock_sources[i] != NULL) { - dce110_clock_source_destroy(&pool->base.clock_sources[i]); - } - } - - if (pool->base.dp_clock_source != NULL) - dce110_clock_source_destroy(&pool->base.dp_clock_source); - - for (i = 0; i < pool->base.audio_count; i++) { - if (pool->base.audios[i] != NULL) { - dce_aud_destroy(&pool->base.audios[i]); - } - } - - if (pool->base.abm != NULL) - dce_abm_destroy(&pool->base.abm); - - if (pool->base.dmcu != NULL) - dce_dmcu_destroy(&pool->base.dmcu); - - if (pool->base.irqs != NULL) { - dal_irq_service_destroy(&pool->base.irqs); - } -} - - -static void get_pixel_clock_parameters( - const struct pipe_ctx *pipe_ctx, - struct pixel_clk_params *pixel_clk_params) -{ - const struct dc_stream_state *stream = pipe_ctx->stream; - - /*TODO: is this halved for YCbCr 420? in that case we might want to move - * the pixel clock normalization for hdmi up to here instead of doing it - * in pll_adjust_pix_clk - */ - pixel_clk_params->requested_pix_clk_100hz = stream->timing.pix_clk_100hz; - pixel_clk_params->encoder_object_id = stream->link->link_enc->id; - pixel_clk_params->signal_type = pipe_ctx->stream->signal; - pixel_clk_params->controller_id = pipe_ctx->stream_res.tg->inst + 1; - /* TODO: un-hardcode*/ - pixel_clk_params->requested_sym_clk = LINK_RATE_LOW * - LINK_RATE_REF_FREQ_IN_KHZ; - pixel_clk_params->flags.ENABLE_SS = 0; - pixel_clk_params->color_depth = - stream->timing.display_color_depth; - pixel_clk_params->flags.DISPLAY_BLANKED = 1; - pixel_clk_params->flags.SUPPORT_YCBCR420 = (stream->timing.pixel_encoding == - PIXEL_ENCODING_YCBCR420); - pixel_clk_params->pixel_encoding = stream->timing.pixel_encoding; - if (stream->timing.pixel_encoding == PIXEL_ENCODING_YCBCR422) { - pixel_clk_params->color_depth = COLOR_DEPTH_888; - } - if (stream->timing.pixel_encoding == PIXEL_ENCODING_YCBCR420) { - pixel_clk_params->requested_pix_clk_100hz = pixel_clk_params->requested_pix_clk_100hz / 2; - } - if (stream->timing.timing_3d_format == TIMING_3D_FORMAT_HW_FRAME_PACKING) - pixel_clk_params->requested_pix_clk_100hz *= 2; - -} - -void dce110_resource_build_pipe_hw_param(struct pipe_ctx *pipe_ctx) -{ - get_pixel_clock_parameters(pipe_ctx, &pipe_ctx->stream_res.pix_clk_params); - pipe_ctx->clock_source->funcs->get_pix_clk_dividers( - pipe_ctx->clock_source, - &pipe_ctx->stream_res.pix_clk_params, - &pipe_ctx->pll_settings); - resource_build_bit_depth_reduction_params(pipe_ctx->stream, - &pipe_ctx->stream->bit_depth_params); - pipe_ctx->stream->clamping.pixel_encoding = pipe_ctx->stream->timing.pixel_encoding; -} - -static bool is_surface_pixel_format_supported(struct pipe_ctx *pipe_ctx, unsigned int underlay_idx) -{ - if (pipe_ctx->pipe_idx != underlay_idx) - return true; - if (!pipe_ctx->plane_state) - return false; - if (pipe_ctx->plane_state->format < SURFACE_PIXEL_FORMAT_VIDEO_BEGIN) - return false; - return true; -} - -static enum dc_status build_mapped_resource( - const struct dc *dc, - struct dc_state *context, - struct dc_stream_state *stream) -{ - struct pipe_ctx *pipe_ctx = resource_get_otg_master_for_stream(&context->res_ctx, stream); - - if (!pipe_ctx) - return DC_ERROR_UNEXPECTED; - - if (!is_surface_pixel_format_supported(pipe_ctx, - dc->res_pool->underlay_pipe_index)) - return DC_SURFACE_PIXEL_FORMAT_UNSUPPORTED; - - dce110_resource_build_pipe_hw_param(pipe_ctx); - - /* TODO: validate audio ASIC caps, encoder */ - - resource_build_info_frame(pipe_ctx); - - return DC_OK; -} - -static bool dce110_validate_bandwidth( - struct dc *dc, - struct dc_state *context, - bool fast_validate) -{ - bool result = false; - - DC_LOG_BANDWIDTH_CALCS( - "%s: start", - __func__); - - if (bw_calcs( - dc->ctx, - dc->bw_dceip, - dc->bw_vbios, - context->res_ctx.pipe_ctx, - dc->res_pool->pipe_count, - &context->bw_ctx.bw.dce)) - result = true; - - if (!result) - DC_LOG_BANDWIDTH_VALIDATION("%s: %dx%d@%d Bandwidth validation failed!\n", - __func__, - context->streams[0]->timing.h_addressable, - context->streams[0]->timing.v_addressable, - context->streams[0]->timing.pix_clk_100hz / 10); - - if (memcmp(&dc->current_state->bw_ctx.bw.dce, - &context->bw_ctx.bw.dce, sizeof(context->bw_ctx.bw.dce))) { - - DC_LOG_BANDWIDTH_CALCS( - "%s: finish,\n" - "nbpMark_b: %d nbpMark_a: %d urgentMark_b: %d urgentMark_a: %d\n" - "stutMark_b: %d stutMark_a: %d\n" - "nbpMark_b: %d nbpMark_a: %d urgentMark_b: %d urgentMark_a: %d\n" - "stutMark_b: %d stutMark_a: %d\n" - "nbpMark_b: %d nbpMark_a: %d urgentMark_b: %d urgentMark_a: %d\n" - "stutMark_b: %d stutMark_a: %d stutter_mode_enable: %d\n" - "cstate: %d pstate: %d nbpstate: %d sync: %d dispclk: %d\n" - "sclk: %d sclk_sleep: %d yclk: %d blackout_recovery_time_us: %d\n" - , - __func__, - context->bw_ctx.bw.dce.nbp_state_change_wm_ns[0].b_mark, - context->bw_ctx.bw.dce.nbp_state_change_wm_ns[0].a_mark, - context->bw_ctx.bw.dce.urgent_wm_ns[0].b_mark, - context->bw_ctx.bw.dce.urgent_wm_ns[0].a_mark, - context->bw_ctx.bw.dce.stutter_exit_wm_ns[0].b_mark, - context->bw_ctx.bw.dce.stutter_exit_wm_ns[0].a_mark, - context->bw_ctx.bw.dce.nbp_state_change_wm_ns[1].b_mark, - context->bw_ctx.bw.dce.nbp_state_change_wm_ns[1].a_mark, - context->bw_ctx.bw.dce.urgent_wm_ns[1].b_mark, - context->bw_ctx.bw.dce.urgent_wm_ns[1].a_mark, - context->bw_ctx.bw.dce.stutter_exit_wm_ns[1].b_mark, - context->bw_ctx.bw.dce.stutter_exit_wm_ns[1].a_mark, - context->bw_ctx.bw.dce.nbp_state_change_wm_ns[2].b_mark, - context->bw_ctx.bw.dce.nbp_state_change_wm_ns[2].a_mark, - context->bw_ctx.bw.dce.urgent_wm_ns[2].b_mark, - context->bw_ctx.bw.dce.urgent_wm_ns[2].a_mark, - context->bw_ctx.bw.dce.stutter_exit_wm_ns[2].b_mark, - context->bw_ctx.bw.dce.stutter_exit_wm_ns[2].a_mark, - context->bw_ctx.bw.dce.stutter_mode_enable, - context->bw_ctx.bw.dce.cpuc_state_change_enable, - context->bw_ctx.bw.dce.cpup_state_change_enable, - context->bw_ctx.bw.dce.nbp_state_change_enable, - context->bw_ctx.bw.dce.all_displays_in_sync, - context->bw_ctx.bw.dce.dispclk_khz, - context->bw_ctx.bw.dce.sclk_khz, - context->bw_ctx.bw.dce.sclk_deep_sleep_khz, - context->bw_ctx.bw.dce.yclk_khz, - context->bw_ctx.bw.dce.blackout_recovery_time_us); - } - return result; -} - -static enum dc_status dce110_validate_plane(const struct dc_plane_state *plane_state, - struct dc_caps *caps) -{ - if (((plane_state->dst_rect.width * 2) < plane_state->src_rect.width) || - ((plane_state->dst_rect.height * 2) < plane_state->src_rect.height)) - return DC_FAIL_SURFACE_VALIDATE; - - return DC_OK; -} - -static bool dce110_validate_surface_sets( - struct dc_state *context) -{ - int i, j; - - for (i = 0; i < context->stream_count; i++) { - if (context->stream_status[i].plane_count == 0) - continue; - - if (context->stream_status[i].plane_count > 2) - return false; - - for (j = 0; j < context->stream_status[i].plane_count; j++) { - struct dc_plane_state *plane = - context->stream_status[i].plane_states[j]; - - /* underlay validation */ - if (plane->format >= SURFACE_PIXEL_FORMAT_VIDEO_BEGIN) { - - if ((plane->src_rect.width > 1920 || - plane->src_rect.height > 1080)) - return false; - - /* we don't have the logic to support underlay - * only yet so block the use case where we get - * NV12 plane as top layer - */ - if (j == 0) - return false; - - /* irrespective of plane format, - * stream should be RGB encoded - */ - if (context->streams[i]->timing.pixel_encoding - != PIXEL_ENCODING_RGB) - return false; - - } - - } - } - - return true; -} - -static enum dc_status dce110_validate_global( - struct dc *dc, - struct dc_state *context) -{ - if (!dce110_validate_surface_sets(context)) - return DC_FAIL_SURFACE_VALIDATE; - - return DC_OK; -} - -static enum dc_status dce110_add_stream_to_ctx( - struct dc *dc, - struct dc_state *new_ctx, - struct dc_stream_state *dc_stream) -{ - enum dc_status result = DC_ERROR_UNEXPECTED; - - result = resource_map_pool_resources(dc, new_ctx, dc_stream); - - if (result == DC_OK) - result = resource_map_clock_resources(dc, new_ctx, dc_stream); - - - if (result == DC_OK) - result = build_mapped_resource(dc, new_ctx, dc_stream); - - return result; -} - -static struct pipe_ctx *dce110_acquire_underlay( - const struct dc_state *cur_ctx, - struct dc_state *new_ctx, - const struct resource_pool *pool, - const struct pipe_ctx *opp_head_pipe) -{ - struct dc_stream_state *stream = opp_head_pipe->stream; - struct dc *dc = stream->ctx->dc; - struct dce_hwseq *hws = dc->hwseq; - struct resource_context *res_ctx = &new_ctx->res_ctx; - unsigned int underlay_idx = pool->underlay_pipe_index; - struct pipe_ctx *pipe_ctx = &res_ctx->pipe_ctx[underlay_idx]; - - if (res_ctx->pipe_ctx[underlay_idx].stream) - return NULL; - - pipe_ctx->stream_res.tg = pool->timing_generators[underlay_idx]; - pipe_ctx->plane_res.mi = pool->mis[underlay_idx]; - /*pipe_ctx->plane_res.ipp = res_ctx->pool->ipps[underlay_idx];*/ - pipe_ctx->plane_res.xfm = pool->transforms[underlay_idx]; - pipe_ctx->stream_res.opp = pool->opps[underlay_idx]; - pipe_ctx->pipe_idx = underlay_idx; - - pipe_ctx->stream = stream; - - if (!dc->current_state->res_ctx.pipe_ctx[underlay_idx].stream) { - struct tg_color black_color = {0}; - struct dc_bios *dcb = dc->ctx->dc_bios; - - hws->funcs.enable_display_power_gating( - dc, - pipe_ctx->stream_res.tg->inst, - dcb, PIPE_GATING_CONTROL_DISABLE); - - /* - * This is for powering on underlay, so crtc does not - * need to be enabled - */ - - pipe_ctx->stream_res.tg->funcs->program_timing(pipe_ctx->stream_res.tg, - &stream->timing, - 0, - 0, - 0, - 0, - pipe_ctx->stream->signal, - false); - - pipe_ctx->stream_res.tg->funcs->enable_advanced_request( - pipe_ctx->stream_res.tg, - true, - &stream->timing); - - pipe_ctx->plane_res.mi->funcs->allocate_mem_input(pipe_ctx->plane_res.mi, - stream->timing.h_total, - stream->timing.v_total, - stream->timing.pix_clk_100hz / 10, - new_ctx->stream_count); - - color_space_to_black_color(dc, - COLOR_SPACE_YCBCR601, &black_color); - pipe_ctx->stream_res.tg->funcs->set_blank_color( - pipe_ctx->stream_res.tg, - &black_color); - } - - return pipe_ctx; -} - -static void dce110_destroy_resource_pool(struct resource_pool **pool) -{ - struct dce110_resource_pool *dce110_pool = TO_DCE110_RES_POOL(*pool); - - dce110_resource_destruct(dce110_pool); - kfree(dce110_pool); - *pool = NULL; -} - -struct stream_encoder *dce110_find_first_free_match_stream_enc_for_link( - struct resource_context *res_ctx, - const struct resource_pool *pool, - struct dc_stream_state *stream) -{ - int i; - int j = -1; - struct dc_link *link = stream->link; - - for (i = 0; i < pool->stream_enc_count; i++) { - if (!res_ctx->is_stream_enc_acquired[i] && - pool->stream_enc[i]) { - /* Store first available for MST second display - * in daisy chain use case - */ - j = i; - if (pool->stream_enc[i]->id == - link->link_enc->preferred_engine) - return pool->stream_enc[i]; - } - } - - /* - * For CZ and later, we can allow DIG FE and BE to differ for all display types - */ - - if (j >= 0) - return pool->stream_enc[j]; - - return NULL; -} - - -static const struct resource_funcs dce110_res_pool_funcs = { - .destroy = dce110_destroy_resource_pool, - .link_enc_create = dce110_link_encoder_create, - .panel_cntl_create = dce110_panel_cntl_create, - .validate_bandwidth = dce110_validate_bandwidth, - .validate_plane = dce110_validate_plane, - .acquire_free_pipe_as_secondary_dpp_pipe = dce110_acquire_underlay, - .add_stream_to_ctx = dce110_add_stream_to_ctx, - .validate_global = dce110_validate_global, - .find_first_free_match_stream_enc_for_link = dce110_find_first_free_match_stream_enc_for_link -}; - -static bool underlay_create(struct dc_context *ctx, struct resource_pool *pool) -{ - struct dce110_timing_generator *dce110_tgv = kzalloc(sizeof(*dce110_tgv), - GFP_KERNEL); - struct dce_transform *dce110_xfmv = kzalloc(sizeof(*dce110_xfmv), - GFP_KERNEL); - struct dce_mem_input *dce110_miv = kzalloc(sizeof(*dce110_miv), - GFP_KERNEL); - struct dce110_opp *dce110_oppv = kzalloc(sizeof(*dce110_oppv), - GFP_KERNEL); - - if (!dce110_tgv || !dce110_xfmv || !dce110_miv || !dce110_oppv) { - kfree(dce110_tgv); - kfree(dce110_xfmv); - kfree(dce110_miv); - kfree(dce110_oppv); - return false; - } - - dce110_opp_v_construct(dce110_oppv, ctx); - - dce110_timing_generator_v_construct(dce110_tgv, ctx); - dce110_mem_input_v_construct(dce110_miv, ctx); - dce110_transform_v_construct(dce110_xfmv, ctx); - - pool->opps[pool->pipe_count] = &dce110_oppv->base; - pool->timing_generators[pool->pipe_count] = &dce110_tgv->base; - pool->mis[pool->pipe_count] = &dce110_miv->base; - pool->transforms[pool->pipe_count] = &dce110_xfmv->base; - pool->pipe_count++; - - /* update the public caps to indicate an underlay is available */ - ctx->dc->caps.max_slave_planes = 1; - ctx->dc->caps.max_slave_yuv_planes = 1; - ctx->dc->caps.max_slave_rgb_planes = 0; - - return true; -} - -static void bw_calcs_data_update_from_pplib(struct dc *dc) -{ - struct dm_pp_clock_levels clks = {0}; - - /*do system clock*/ - dm_pp_get_clock_levels_by_type( - dc->ctx, - DM_PP_CLOCK_TYPE_ENGINE_CLK, - &clks); - /* convert all the clock fro kHz to fix point mHz */ - dc->bw_vbios->high_sclk = bw_frc_to_fixed( - clks.clocks_in_khz[clks.num_levels-1], 1000); - dc->bw_vbios->mid1_sclk = bw_frc_to_fixed( - clks.clocks_in_khz[clks.num_levels/8], 1000); - dc->bw_vbios->mid2_sclk = bw_frc_to_fixed( - clks.clocks_in_khz[clks.num_levels*2/8], 1000); - dc->bw_vbios->mid3_sclk = bw_frc_to_fixed( - clks.clocks_in_khz[clks.num_levels*3/8], 1000); - dc->bw_vbios->mid4_sclk = bw_frc_to_fixed( - clks.clocks_in_khz[clks.num_levels*4/8], 1000); - dc->bw_vbios->mid5_sclk = bw_frc_to_fixed( - clks.clocks_in_khz[clks.num_levels*5/8], 1000); - dc->bw_vbios->mid6_sclk = bw_frc_to_fixed( - clks.clocks_in_khz[clks.num_levels*6/8], 1000); - dc->bw_vbios->low_sclk = bw_frc_to_fixed( - clks.clocks_in_khz[0], 1000); - dc->sclk_lvls = clks; - - /*do display clock*/ - dm_pp_get_clock_levels_by_type( - dc->ctx, - DM_PP_CLOCK_TYPE_DISPLAY_CLK, - &clks); - dc->bw_vbios->high_voltage_max_dispclk = bw_frc_to_fixed( - clks.clocks_in_khz[clks.num_levels-1], 1000); - dc->bw_vbios->mid_voltage_max_dispclk = bw_frc_to_fixed( - clks.clocks_in_khz[clks.num_levels>>1], 1000); - dc->bw_vbios->low_voltage_max_dispclk = bw_frc_to_fixed( - clks.clocks_in_khz[0], 1000); - - /*do memory clock*/ - dm_pp_get_clock_levels_by_type( - dc->ctx, - DM_PP_CLOCK_TYPE_MEMORY_CLK, - &clks); - - dc->bw_vbios->low_yclk = bw_frc_to_fixed( - clks.clocks_in_khz[0] * MEMORY_TYPE_MULTIPLIER_CZ, 1000); - dc->bw_vbios->mid_yclk = bw_frc_to_fixed( - clks.clocks_in_khz[clks.num_levels>>1] * MEMORY_TYPE_MULTIPLIER_CZ, - 1000); - dc->bw_vbios->high_yclk = bw_frc_to_fixed( - clks.clocks_in_khz[clks.num_levels-1] * MEMORY_TYPE_MULTIPLIER_CZ, - 1000); -} - -static const struct resource_caps *dce110_resource_cap( - struct hw_asic_id *asic_id) -{ - if (ASIC_REV_IS_STONEY(asic_id->hw_internal_rev)) - return &stoney_resource_cap; - else - return &carrizo_resource_cap; -} - -static bool dce110_resource_construct( - uint8_t num_virtual_links, - struct dc *dc, - struct dce110_resource_pool *pool, - struct hw_asic_id asic_id) -{ - unsigned int i; - struct dc_context *ctx = dc->ctx; - struct dc_bios *bp; - - ctx->dc_bios->regs = &bios_regs; - - pool->base.res_cap = dce110_resource_cap(&ctx->asic_id); - pool->base.funcs = &dce110_res_pool_funcs; - - /************************************************* - * Resource + asic cap harcoding * - *************************************************/ - - pool->base.pipe_count = pool->base.res_cap->num_timing_generator; - pool->base.underlay_pipe_index = pool->base.pipe_count; - pool->base.timing_generator_count = pool->base.res_cap->num_timing_generator; - dc->caps.max_downscale_ratio = 150; - dc->caps.i2c_speed_in_khz = 40; - dc->caps.i2c_speed_in_khz_hdcp = 40; - dc->caps.max_cursor_size = 128; - dc->caps.min_horizontal_blanking_period = 80; - dc->caps.is_apu = true; - dc->caps.extended_aux_timeout_support = false; - dc->debug = debug_defaults; - - /************************************************* - * Create resources * - *************************************************/ - - bp = ctx->dc_bios; - - if (bp->fw_info_valid && bp->fw_info.external_clock_source_frequency_for_dp != 0) { - pool->base.dp_clock_source = - dce110_clock_source_create(ctx, bp, CLOCK_SOURCE_ID_EXTERNAL, NULL, true); - - pool->base.clock_sources[0] = - dce110_clock_source_create(ctx, bp, CLOCK_SOURCE_ID_PLL0, - &clk_src_regs[0], false); - pool->base.clock_sources[1] = - dce110_clock_source_create(ctx, bp, CLOCK_SOURCE_ID_PLL1, - &clk_src_regs[1], false); - - pool->base.clk_src_count = 2; - - /* TODO: find out if CZ support 3 PLLs */ - } - - if (pool->base.dp_clock_source == NULL) { - dm_error("DC: failed to create dp clock source!\n"); - BREAK_TO_DEBUGGER(); - goto res_create_fail; - } - - for (i = 0; i < pool->base.clk_src_count; i++) { - if (pool->base.clock_sources[i] == NULL) { - dm_error("DC: failed to create clock sources!\n"); - BREAK_TO_DEBUGGER(); - goto res_create_fail; - } - } - - pool->base.dmcu = dce_dmcu_create(ctx, - &dmcu_regs, - &dmcu_shift, - &dmcu_mask); - if (pool->base.dmcu == NULL) { - dm_error("DC: failed to create dmcu!\n"); - BREAK_TO_DEBUGGER(); - goto res_create_fail; - } - - pool->base.abm = dce_abm_create(ctx, - &abm_regs, - &abm_shift, - &abm_mask); - if (pool->base.abm == NULL) { - dm_error("DC: failed to create abm!\n"); - BREAK_TO_DEBUGGER(); - goto res_create_fail; - } - - { - struct irq_service_init_data init_data; - init_data.ctx = dc->ctx; - pool->base.irqs = dal_irq_service_dce110_create(&init_data); - if (!pool->base.irqs) - goto res_create_fail; - } - - for (i = 0; i < pool->base.pipe_count; i++) { - pool->base.timing_generators[i] = dce110_timing_generator_create( - ctx, i, &dce110_tg_offsets[i]); - if (pool->base.timing_generators[i] == NULL) { - BREAK_TO_DEBUGGER(); - dm_error("DC: failed to create tg!\n"); - goto res_create_fail; - } - - pool->base.mis[i] = dce110_mem_input_create(ctx, i); - if (pool->base.mis[i] == NULL) { - BREAK_TO_DEBUGGER(); - dm_error( - "DC: failed to create memory input!\n"); - goto res_create_fail; - } - - pool->base.ipps[i] = dce110_ipp_create(ctx, i); - if (pool->base.ipps[i] == NULL) { - BREAK_TO_DEBUGGER(); - dm_error( - "DC: failed to create input pixel processor!\n"); - goto res_create_fail; - } - - pool->base.transforms[i] = dce110_transform_create(ctx, i); - if (pool->base.transforms[i] == NULL) { - BREAK_TO_DEBUGGER(); - dm_error( - "DC: failed to create transform!\n"); - goto res_create_fail; - } - - pool->base.opps[i] = dce110_opp_create(ctx, i); - if (pool->base.opps[i] == NULL) { - BREAK_TO_DEBUGGER(); - dm_error( - "DC: failed to create output pixel processor!\n"); - goto res_create_fail; - } - } - - for (i = 0; i < pool->base.res_cap->num_ddc; i++) { - pool->base.engines[i] = dce110_aux_engine_create(ctx, i); - if (pool->base.engines[i] == NULL) { - BREAK_TO_DEBUGGER(); - dm_error( - "DC:failed to create aux engine!!\n"); - goto res_create_fail; - } - pool->base.hw_i2cs[i] = dce110_i2c_hw_create(ctx, i); - if (pool->base.hw_i2cs[i] == NULL) { - BREAK_TO_DEBUGGER(); - dm_error( - "DC:failed to create i2c engine!!\n"); - goto res_create_fail; - } - pool->base.sw_i2cs[i] = NULL; - } - - if (dc->config.fbc_support) - dc->fbc_compressor = dce110_compressor_create(ctx); - - if (!underlay_create(ctx, &pool->base)) - goto res_create_fail; - - if (!resource_construct(num_virtual_links, dc, &pool->base, - &res_create_funcs)) - goto res_create_fail; - - /* Create hardware sequencer */ - dce110_hw_sequencer_construct(dc); - - dc->caps.max_planes = pool->base.pipe_count; - - for (i = 0; i < pool->base.underlay_pipe_index; ++i) - dc->caps.planes[i] = plane_cap; - - dc->caps.planes[pool->base.underlay_pipe_index] = underlay_plane_cap; - - bw_calcs_init(dc->bw_dceip, dc->bw_vbios, dc->ctx->asic_id); - - bw_calcs_data_update_from_pplib(dc); - - return true; - -res_create_fail: - dce110_resource_destruct(pool); - return false; -} - -struct resource_pool *dce110_create_resource_pool( - uint8_t num_virtual_links, - struct dc *dc, - struct hw_asic_id asic_id) -{ - struct dce110_resource_pool *pool = - kzalloc(sizeof(struct dce110_resource_pool), GFP_KERNEL); - - if (!pool) - return NULL; - - if (dce110_resource_construct(num_virtual_links, dc, pool, asic_id)) - return &pool->base; - - kfree(pool); - BREAK_TO_DEBUGGER(); - return NULL; -} diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.h b/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.h deleted file mode 100644 index aa4531e0800e..000000000000 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.h +++ /dev/null @@ -1,54 +0,0 @@ -/* -* Copyright 2012-15 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_RESOURCE_DCE110_H__ -#define __DC_RESOURCE_DCE110_H__ - -#include "core_types.h" - -struct dc; -struct resource_pool; - -#define TO_DCE110_RES_POOL(pool)\ - container_of(pool, struct dce110_resource_pool, base) - -struct dce110_resource_pool { - struct resource_pool base; -}; - -void dce110_resource_build_pipe_hw_param(struct pipe_ctx *pipe_ctx); - -struct resource_pool *dce110_create_resource_pool( - uint8_t num_virtual_links, - struct dc *dc, - struct hw_asic_id asic_id); - -struct stream_encoder *dce110_find_first_free_match_stream_enc_for_link( - struct resource_context *res_ctx, - const struct resource_pool *pool, - struct dc_stream_state *stream); - -#endif /* __DC_RESOURCE_DCE110_H__ */ - diff --git a/drivers/gpu/drm/amd/display/dc/dce112/Makefile b/drivers/gpu/drm/amd/display/dc/dce112/Makefile index e846ef58cab3..7e92effec894 100644 --- a/drivers/gpu/drm/amd/display/dc/dce112/Makefile +++ b/drivers/gpu/drm/amd/display/dc/dce112/Makefile @@ -25,8 +25,7 @@ CFLAGS_$(AMDDALPATH)/dc/dce112/dce112_resource.o = $(call cc-disable-warning, override-init) -DCE112 = dce112_compressor.o \ -dce112_resource.o +DCE112 = dce112_compressor.o AMD_DAL_DCE112 = $(addprefix $(AMDDALPATH)/dc/dce112/,$(DCE112)) diff --git a/drivers/gpu/drm/amd/display/dc/dce112/dce112_resource.c b/drivers/gpu/drm/amd/display/dc/dce112/dce112_resource.c deleted file mode 100644 index d1edac46c9a0..000000000000 --- a/drivers/gpu/drm/amd/display/dc/dce112/dce112_resource.c +++ /dev/null @@ -1,1431 +0,0 @@ -/* -* Copyright 2012-15 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 "dm_services.h" - -#include "link_encoder.h" -#include "stream_encoder.h" - -#include "resource.h" -#include "include/irq_service_interface.h" -#include "dce110/dce110_resource.h" -#include "dce110/dce110_timing_generator.h" - -#include "irq/dce110/irq_service_dce110.h" -#include "dce/dce_mem_input.h" -#include "dce/dce_transform.h" -#include "dce/dce_link_encoder.h" -#include "dce/dce_stream_encoder.h" -#include "dce/dce_audio.h" -#include "dce/dce_opp.h" -#include "dce/dce_ipp.h" -#include "dce/dce_clock_source.h" - -#include "dce/dce_hwseq.h" -#include "dce112/dce112_hwseq.h" -#include "dce/dce_abm.h" -#include "dce/dce_dmcu.h" -#include "dce/dce_aux.h" -#include "dce/dce_i2c.h" -#include "dce/dce_panel_cntl.h" - -#include "reg_helper.h" - -#include "dce/dce_11_2_d.h" -#include "dce/dce_11_2_sh_mask.h" - -#include "dce100/dce100_resource.h" -#include "dce112_resource.h" - -#define DC_LOGGER \ - dc->ctx->logger - -#ifndef mmDP_DPHY_INTERNAL_CTRL - #define mmDP_DPHY_INTERNAL_CTRL 0x4aa7 - #define mmDP0_DP_DPHY_INTERNAL_CTRL 0x4aa7 - #define mmDP1_DP_DPHY_INTERNAL_CTRL 0x4ba7 - #define mmDP2_DP_DPHY_INTERNAL_CTRL 0x4ca7 - #define mmDP3_DP_DPHY_INTERNAL_CTRL 0x4da7 - #define mmDP4_DP_DPHY_INTERNAL_CTRL 0x4ea7 - #define mmDP5_DP_DPHY_INTERNAL_CTRL 0x4fa7 - #define mmDP6_DP_DPHY_INTERNAL_CTRL 0x54a7 - #define mmDP7_DP_DPHY_INTERNAL_CTRL 0x56a7 - #define mmDP8_DP_DPHY_INTERNAL_CTRL 0x57a7 -#endif - -#ifndef mmBIOS_SCRATCH_2 - #define mmBIOS_SCRATCH_2 0x05CB - #define mmBIOS_SCRATCH_3 0x05CC - #define mmBIOS_SCRATCH_6 0x05CF -#endif - -#ifndef mmDP_DPHY_BS_SR_SWAP_CNTL - #define mmDP_DPHY_BS_SR_SWAP_CNTL 0x4ADC - #define mmDP0_DP_DPHY_BS_SR_SWAP_CNTL 0x4ADC - #define mmDP1_DP_DPHY_BS_SR_SWAP_CNTL 0x4BDC - #define mmDP2_DP_DPHY_BS_SR_SWAP_CNTL 0x4CDC - #define mmDP3_DP_DPHY_BS_SR_SWAP_CNTL 0x4DDC - #define mmDP4_DP_DPHY_BS_SR_SWAP_CNTL 0x4EDC - #define mmDP5_DP_DPHY_BS_SR_SWAP_CNTL 0x4FDC - #define mmDP6_DP_DPHY_BS_SR_SWAP_CNTL 0x54DC -#endif - -#ifndef mmDP_DPHY_FAST_TRAINING - #define mmDP_DPHY_FAST_TRAINING 0x4ABC - #define mmDP0_DP_DPHY_FAST_TRAINING 0x4ABC - #define mmDP1_DP_DPHY_FAST_TRAINING 0x4BBC - #define mmDP2_DP_DPHY_FAST_TRAINING 0x4CBC - #define mmDP3_DP_DPHY_FAST_TRAINING 0x4DBC - #define mmDP4_DP_DPHY_FAST_TRAINING 0x4EBC - #define mmDP5_DP_DPHY_FAST_TRAINING 0x4FBC - #define mmDP6_DP_DPHY_FAST_TRAINING 0x54BC -#endif - -enum dce112_clk_src_array_id { - DCE112_CLK_SRC_PLL0, - DCE112_CLK_SRC_PLL1, - DCE112_CLK_SRC_PLL2, - DCE112_CLK_SRC_PLL3, - DCE112_CLK_SRC_PLL4, - DCE112_CLK_SRC_PLL5, - - DCE112_CLK_SRC_TOTAL -}; - -static const struct dce110_timing_generator_offsets dce112_tg_offsets[] = { - { - .crtc = (mmCRTC0_CRTC_CONTROL - mmCRTC_CONTROL), - .dcp = (mmDCP0_GRPH_CONTROL - mmGRPH_CONTROL), - }, - { - .crtc = (mmCRTC1_CRTC_CONTROL - mmCRTC_CONTROL), - .dcp = (mmDCP1_GRPH_CONTROL - mmGRPH_CONTROL), - }, - { - .crtc = (mmCRTC2_CRTC_CONTROL - mmCRTC_CONTROL), - .dcp = (mmDCP2_GRPH_CONTROL - mmGRPH_CONTROL), - }, - { - .crtc = (mmCRTC3_CRTC_CONTROL - mmCRTC_CONTROL), - .dcp = (mmDCP3_GRPH_CONTROL - mmGRPH_CONTROL), - }, - { - .crtc = (mmCRTC4_CRTC_CONTROL - mmCRTC_CONTROL), - .dcp = (mmDCP4_GRPH_CONTROL - mmGRPH_CONTROL), - }, - { - .crtc = (mmCRTC5_CRTC_CONTROL - mmCRTC_CONTROL), - .dcp = (mmDCP5_GRPH_CONTROL - mmGRPH_CONTROL), - } -}; - -/* set register offset */ -#define SR(reg_name)\ - .reg_name = mm ## reg_name - -/* set register offset with instance */ -#define SRI(reg_name, block, id)\ - .reg_name = mm ## block ## id ## _ ## reg_name - -static const struct dce_dmcu_registers dmcu_regs = { - DMCU_DCE110_COMMON_REG_LIST() -}; - -static const struct dce_dmcu_shift dmcu_shift = { - DMCU_MASK_SH_LIST_DCE110(__SHIFT) -}; - -static const struct dce_dmcu_mask dmcu_mask = { - DMCU_MASK_SH_LIST_DCE110(_MASK) -}; - -static const struct dce_abm_registers abm_regs = { - ABM_DCE110_COMMON_REG_LIST() -}; - -static const struct dce_abm_shift abm_shift = { - ABM_MASK_SH_LIST_DCE110(__SHIFT) -}; - -static const struct dce_abm_mask abm_mask = { - ABM_MASK_SH_LIST_DCE110(_MASK) -}; - -static const struct dce110_aux_registers_shift aux_shift = { - DCE_AUX_MASK_SH_LIST(__SHIFT) -}; - -static const struct dce110_aux_registers_mask aux_mask = { - DCE_AUX_MASK_SH_LIST(_MASK) -}; - -#define ipp_regs(id)\ -[id] = {\ - IPP_DCE110_REG_LIST_DCE_BASE(id)\ -} - -static const struct dce_ipp_registers ipp_regs[] = { - ipp_regs(0), - ipp_regs(1), - ipp_regs(2), - ipp_regs(3), - ipp_regs(4), - ipp_regs(5) -}; - -static const struct dce_ipp_shift ipp_shift = { - IPP_DCE100_MASK_SH_LIST_DCE_COMMON_BASE(__SHIFT) -}; - -static const struct dce_ipp_mask ipp_mask = { - IPP_DCE100_MASK_SH_LIST_DCE_COMMON_BASE(_MASK) -}; - -#define transform_regs(id)\ -[id] = {\ - XFM_COMMON_REG_LIST_DCE110(id)\ -} - -static const struct dce_transform_registers xfm_regs[] = { - transform_regs(0), - transform_regs(1), - transform_regs(2), - transform_regs(3), - transform_regs(4), - transform_regs(5) -}; - -static const struct dce_transform_shift xfm_shift = { - XFM_COMMON_MASK_SH_LIST_DCE110(__SHIFT) -}; - -static const struct dce_transform_mask xfm_mask = { - XFM_COMMON_MASK_SH_LIST_DCE110(_MASK) -}; - -#define aux_regs(id)\ -[id] = {\ - AUX_REG_LIST(id)\ -} - -static const struct dce110_link_enc_aux_registers link_enc_aux_regs[] = { - aux_regs(0), - aux_regs(1), - aux_regs(2), - aux_regs(3), - aux_regs(4), - aux_regs(5) -}; - -static const struct dce_panel_cntl_registers panel_cntl_regs[] = { - { DCE_PANEL_CNTL_REG_LIST() } -}; - -static const struct dce_panel_cntl_shift panel_cntl_shift = { - DCE_PANEL_CNTL_MASK_SH_LIST(__SHIFT) -}; - -static const struct dce_panel_cntl_mask panel_cntl_mask = { - DCE_PANEL_CNTL_MASK_SH_LIST(_MASK) -}; - -#define hpd_regs(id)\ -[id] = {\ - HPD_REG_LIST(id)\ -} - -static const struct dce110_link_enc_hpd_registers link_enc_hpd_regs[] = { - hpd_regs(0), - hpd_regs(1), - hpd_regs(2), - hpd_regs(3), - hpd_regs(4), - hpd_regs(5) -}; - -#define link_regs(id)\ -[id] = {\ - LE_DCE110_REG_LIST(id)\ -} - -static const struct dce110_link_enc_registers link_enc_regs[] = { - link_regs(0), - link_regs(1), - link_regs(2), - link_regs(3), - link_regs(4), - link_regs(5), - link_regs(6), -}; - -#define stream_enc_regs(id)\ -[id] = {\ - SE_COMMON_REG_LIST(id),\ - .TMDS_CNTL = 0,\ -} - -static const struct dce110_stream_enc_registers stream_enc_regs[] = { - stream_enc_regs(0), - stream_enc_regs(1), - stream_enc_regs(2), - stream_enc_regs(3), - stream_enc_regs(4), - stream_enc_regs(5) -}; - -static const struct dce_stream_encoder_shift se_shift = { - SE_COMMON_MASK_SH_LIST_DCE112(__SHIFT) -}; - -static const struct dce_stream_encoder_mask se_mask = { - SE_COMMON_MASK_SH_LIST_DCE112(_MASK) -}; - -#define opp_regs(id)\ -[id] = {\ - OPP_DCE_112_REG_LIST(id),\ -} - -static const struct dce_opp_registers opp_regs[] = { - opp_regs(0), - opp_regs(1), - opp_regs(2), - opp_regs(3), - opp_regs(4), - opp_regs(5) -}; - -static const struct dce_opp_shift opp_shift = { - OPP_COMMON_MASK_SH_LIST_DCE_112(__SHIFT) -}; - -static const struct dce_opp_mask opp_mask = { - OPP_COMMON_MASK_SH_LIST_DCE_112(_MASK) -}; - -#define aux_engine_regs(id)\ -[id] = {\ - AUX_COMMON_REG_LIST(id), \ - .AUX_RESET_MASK = 0 \ -} - -static const struct dce110_aux_registers aux_engine_regs[] = { - aux_engine_regs(0), - aux_engine_regs(1), - aux_engine_regs(2), - aux_engine_regs(3), - aux_engine_regs(4), - aux_engine_regs(5) -}; - -#define audio_regs(id)\ -[id] = {\ - AUD_COMMON_REG_LIST(id)\ -} - -static const struct dce_audio_registers audio_regs[] = { - audio_regs(0), - audio_regs(1), - audio_regs(2), - audio_regs(3), - audio_regs(4), - audio_regs(5) -}; - -static const struct dce_audio_shift audio_shift = { - AUD_COMMON_MASK_SH_LIST(__SHIFT) -}; - -static const struct dce_audio_mask audio_mask = { - AUD_COMMON_MASK_SH_LIST(_MASK) -}; - -#define clk_src_regs(index, id)\ -[index] = {\ - CS_COMMON_REG_LIST_DCE_112(id),\ -} - -static const struct dce110_clk_src_regs clk_src_regs[] = { - clk_src_regs(0, A), - clk_src_regs(1, B), - clk_src_regs(2, C), - clk_src_regs(3, D), - clk_src_regs(4, E), - clk_src_regs(5, F) -}; - -static const struct dce110_clk_src_shift cs_shift = { - CS_COMMON_MASK_SH_LIST_DCE_112(__SHIFT) -}; - -static const struct dce110_clk_src_mask cs_mask = { - CS_COMMON_MASK_SH_LIST_DCE_112(_MASK) -}; - -static const struct bios_registers bios_regs = { - .BIOS_SCRATCH_3 = mmBIOS_SCRATCH_3, - .BIOS_SCRATCH_6 = mmBIOS_SCRATCH_6 -}; - -static const struct resource_caps polaris_10_resource_cap = { - .num_timing_generator = 6, - .num_audio = 6, - .num_stream_encoder = 6, - .num_pll = 8, /* why 8? 6 combo PHY PLL + 2 regular PLLs? */ - .num_ddc = 6, -}; - -static const struct resource_caps polaris_11_resource_cap = { - .num_timing_generator = 5, - .num_audio = 5, - .num_stream_encoder = 5, - .num_pll = 8, /* why 8? 6 combo PHY PLL + 2 regular PLLs? */ - .num_ddc = 5, -}; - -static const struct dc_plane_cap plane_cap = { - .type = DC_PLANE_TYPE_DCE_RGB, - - .pixel_format_support = { - .argb8888 = true, - .nv12 = false, - .fp16 = true - }, - - .max_upscale_factor = { - .argb8888 = 16000, - .nv12 = 1, - .fp16 = 1 - }, - - .max_downscale_factor = { - .argb8888 = 250, - .nv12 = 1, - .fp16 = 1 - }, - 64, - 64 -}; - -static const struct dc_debug_options debug_defaults = { - .enable_legacy_fast_update = true, -}; - -#define CTX ctx -#define REG(reg) mm ## reg - -#ifndef mmCC_DC_HDMI_STRAPS -#define mmCC_DC_HDMI_STRAPS 0x4819 -#define CC_DC_HDMI_STRAPS__HDMI_DISABLE_MASK 0x40 -#define CC_DC_HDMI_STRAPS__HDMI_DISABLE__SHIFT 0x6 -#define CC_DC_HDMI_STRAPS__AUDIO_STREAM_NUMBER_MASK 0x700 -#define CC_DC_HDMI_STRAPS__AUDIO_STREAM_NUMBER__SHIFT 0x8 -#endif - -static int map_transmitter_id_to_phy_instance( - enum transmitter transmitter) -{ - switch (transmitter) { - case TRANSMITTER_UNIPHY_A: - return 0; - case TRANSMITTER_UNIPHY_B: - return 1; - case TRANSMITTER_UNIPHY_C: - return 2; - case TRANSMITTER_UNIPHY_D: - return 3; - case TRANSMITTER_UNIPHY_E: - return 4; - case TRANSMITTER_UNIPHY_F: - return 5; - case TRANSMITTER_UNIPHY_G: - return 6; - default: - ASSERT(0); - return 0; - } -} - -static void read_dce_straps( - struct dc_context *ctx, - struct resource_straps *straps) -{ - REG_GET_2(CC_DC_HDMI_STRAPS, - HDMI_DISABLE, &straps->hdmi_disable, - AUDIO_STREAM_NUMBER, &straps->audio_stream_number); - - REG_GET(DC_PINSTRAPS, DC_PINSTRAPS_AUDIO, &straps->dc_pinstraps_audio); -} - -static struct audio *create_audio( - struct dc_context *ctx, unsigned int inst) -{ - return dce_audio_create(ctx, inst, - &audio_regs[inst], &audio_shift, &audio_mask); -} - - -static struct timing_generator *dce112_timing_generator_create( - struct dc_context *ctx, - uint32_t instance, - const struct dce110_timing_generator_offsets *offsets) -{ - struct dce110_timing_generator *tg110 = - kzalloc(sizeof(struct dce110_timing_generator), GFP_KERNEL); - - if (!tg110) - return NULL; - - dce110_timing_generator_construct(tg110, ctx, instance, offsets); - return &tg110->base; -} - -static struct stream_encoder *dce112_stream_encoder_create( - enum engine_id eng_id, - struct dc_context *ctx) -{ - struct dce110_stream_encoder *enc110 = - kzalloc(sizeof(struct dce110_stream_encoder), GFP_KERNEL); - - if (!enc110) - return NULL; - - dce110_stream_encoder_construct(enc110, ctx, ctx->dc_bios, eng_id, - &stream_enc_regs[eng_id], - &se_shift, &se_mask); - return &enc110->base; -} - -#define SRII(reg_name, block, id)\ - .reg_name[id] = mm ## block ## id ## _ ## reg_name - -static const struct dce_hwseq_registers hwseq_reg = { - HWSEQ_DCE112_REG_LIST() -}; - -static const struct dce_hwseq_shift hwseq_shift = { - HWSEQ_DCE112_MASK_SH_LIST(__SHIFT) -}; - -static const struct dce_hwseq_mask hwseq_mask = { - HWSEQ_DCE112_MASK_SH_LIST(_MASK) -}; - -static struct dce_hwseq *dce112_hwseq_create( - struct dc_context *ctx) -{ - struct dce_hwseq *hws = kzalloc(sizeof(struct dce_hwseq), GFP_KERNEL); - - if (hws) { - hws->ctx = ctx; - hws->regs = &hwseq_reg; - hws->shifts = &hwseq_shift; - hws->masks = &hwseq_mask; - } - return hws; -} - -static const struct resource_create_funcs res_create_funcs = { - .read_dce_straps = read_dce_straps, - .create_audio = create_audio, - .create_stream_encoder = dce112_stream_encoder_create, - .create_hwseq = dce112_hwseq_create, -}; - -#define mi_inst_regs(id) { MI_DCE11_2_REG_LIST(id) } -static const struct dce_mem_input_registers mi_regs[] = { - mi_inst_regs(0), - mi_inst_regs(1), - mi_inst_regs(2), - mi_inst_regs(3), - mi_inst_regs(4), - mi_inst_regs(5), -}; - -static const struct dce_mem_input_shift mi_shifts = { - MI_DCE11_2_MASK_SH_LIST(__SHIFT) -}; - -static const struct dce_mem_input_mask mi_masks = { - MI_DCE11_2_MASK_SH_LIST(_MASK) -}; - -static struct mem_input *dce112_mem_input_create( - struct dc_context *ctx, - uint32_t inst) -{ - struct dce_mem_input *dce_mi = kzalloc(sizeof(struct dce_mem_input), - GFP_KERNEL); - - if (!dce_mi) { - BREAK_TO_DEBUGGER(); - return NULL; - } - - dce112_mem_input_construct(dce_mi, ctx, inst, &mi_regs[inst], &mi_shifts, &mi_masks); - return &dce_mi->base; -} - -static void dce112_transform_destroy(struct transform **xfm) -{ - kfree(TO_DCE_TRANSFORM(*xfm)); - *xfm = NULL; -} - -static struct transform *dce112_transform_create( - struct dc_context *ctx, - uint32_t inst) -{ - struct dce_transform *transform = - kzalloc(sizeof(struct dce_transform), GFP_KERNEL); - - if (!transform) - return NULL; - - dce_transform_construct(transform, ctx, inst, - &xfm_regs[inst], &xfm_shift, &xfm_mask); - transform->lb_memory_size = 0x1404; /*5124*/ - return &transform->base; -} - -static const struct encoder_feature_support link_enc_feature = { - .max_hdmi_deep_color = COLOR_DEPTH_121212, - .max_hdmi_pixel_clock = 600000, - .hdmi_ycbcr420_supported = true, - .dp_ycbcr420_supported = false, - .flags.bits.IS_HBR2_CAPABLE = true, - .flags.bits.IS_HBR3_CAPABLE = true, - .flags.bits.IS_TPS3_CAPABLE = true, - .flags.bits.IS_TPS4_CAPABLE = true -}; - -static struct link_encoder *dce112_link_encoder_create( - struct dc_context *ctx, - const struct encoder_init_data *enc_init_data) -{ - struct dce110_link_encoder *enc110 = - kzalloc(sizeof(struct dce110_link_encoder), GFP_KERNEL); - int link_regs_id; - - if (!enc110) - return NULL; - - link_regs_id = - map_transmitter_id_to_phy_instance(enc_init_data->transmitter); - - dce110_link_encoder_construct(enc110, - enc_init_data, - &link_enc_feature, - &link_enc_regs[link_regs_id], - &link_enc_aux_regs[enc_init_data->channel - 1], - &link_enc_hpd_regs[enc_init_data->hpd_source]); - return &enc110->base; -} - -static struct panel_cntl *dce112_panel_cntl_create(const struct panel_cntl_init_data *init_data) -{ - struct dce_panel_cntl *panel_cntl = - kzalloc(sizeof(struct dce_panel_cntl), GFP_KERNEL); - - if (!panel_cntl) - return NULL; - - dce_panel_cntl_construct(panel_cntl, - init_data, - &panel_cntl_regs[init_data->inst], - &panel_cntl_shift, - &panel_cntl_mask); - - return &panel_cntl->base; -} - -static struct input_pixel_processor *dce112_ipp_create( - struct dc_context *ctx, uint32_t inst) -{ - struct dce_ipp *ipp = kzalloc(sizeof(struct dce_ipp), GFP_KERNEL); - - if (!ipp) { - BREAK_TO_DEBUGGER(); - return NULL; - } - - dce_ipp_construct(ipp, ctx, inst, - &ipp_regs[inst], &ipp_shift, &ipp_mask); - return &ipp->base; -} - -static struct output_pixel_processor *dce112_opp_create( - struct dc_context *ctx, - uint32_t inst) -{ - struct dce110_opp *opp = - kzalloc(sizeof(struct dce110_opp), GFP_KERNEL); - - if (!opp) - return NULL; - - dce110_opp_construct(opp, - ctx, inst, &opp_regs[inst], &opp_shift, &opp_mask); - return &opp->base; -} - -static struct dce_aux *dce112_aux_engine_create( - struct dc_context *ctx, - uint32_t inst) -{ - struct aux_engine_dce110 *aux_engine = - kzalloc(sizeof(struct aux_engine_dce110), GFP_KERNEL); - - if (!aux_engine) - return NULL; - - dce110_aux_engine_construct(aux_engine, ctx, inst, - SW_AUX_TIMEOUT_PERIOD_MULTIPLIER * AUX_TIMEOUT_PERIOD, - &aux_engine_regs[inst], - &aux_mask, - &aux_shift, - ctx->dc->caps.extended_aux_timeout_support); - - return &aux_engine->base; -} -#define i2c_inst_regs(id) { I2C_HW_ENGINE_COMMON_REG_LIST(id) } - -static const struct dce_i2c_registers i2c_hw_regs[] = { - i2c_inst_regs(1), - i2c_inst_regs(2), - i2c_inst_regs(3), - i2c_inst_regs(4), - i2c_inst_regs(5), - i2c_inst_regs(6), -}; - -static const struct dce_i2c_shift i2c_shifts = { - I2C_COMMON_MASK_SH_LIST_DCE110(__SHIFT) -}; - -static const struct dce_i2c_mask i2c_masks = { - I2C_COMMON_MASK_SH_LIST_DCE110(_MASK) -}; - -static struct dce_i2c_hw *dce112_i2c_hw_create( - struct dc_context *ctx, - uint32_t inst) -{ - struct dce_i2c_hw *dce_i2c_hw = - kzalloc(sizeof(struct dce_i2c_hw), GFP_KERNEL); - - if (!dce_i2c_hw) - return NULL; - - dce112_i2c_hw_construct(dce_i2c_hw, ctx, inst, - &i2c_hw_regs[inst], &i2c_shifts, &i2c_masks); - - return dce_i2c_hw; -} -static struct clock_source *dce112_clock_source_create( - struct dc_context *ctx, - struct dc_bios *bios, - enum clock_source_id id, - const struct dce110_clk_src_regs *regs, - bool dp_clk_src) -{ - struct dce110_clk_src *clk_src = - kzalloc(sizeof(struct dce110_clk_src), GFP_KERNEL); - - if (!clk_src) - return NULL; - - if (dce112_clk_src_construct(clk_src, ctx, bios, id, - regs, &cs_shift, &cs_mask)) { - clk_src->base.dp_clk_src = dp_clk_src; - return &clk_src->base; - } - - kfree(clk_src); - BREAK_TO_DEBUGGER(); - return NULL; -} - -static void dce112_clock_source_destroy(struct clock_source **clk_src) -{ - kfree(TO_DCE110_CLK_SRC(*clk_src)); - *clk_src = NULL; -} - -static void dce112_resource_destruct(struct dce110_resource_pool *pool) -{ - unsigned int i; - - for (i = 0; i < pool->base.pipe_count; i++) { - if (pool->base.opps[i] != NULL) - dce110_opp_destroy(&pool->base.opps[i]); - - if (pool->base.transforms[i] != NULL) - dce112_transform_destroy(&pool->base.transforms[i]); - - if (pool->base.ipps[i] != NULL) - dce_ipp_destroy(&pool->base.ipps[i]); - - if (pool->base.mis[i] != NULL) { - kfree(TO_DCE_MEM_INPUT(pool->base.mis[i])); - pool->base.mis[i] = NULL; - } - - if (pool->base.timing_generators[i] != NULL) { - kfree(DCE110TG_FROM_TG(pool->base.timing_generators[i])); - pool->base.timing_generators[i] = NULL; - } - } - - for (i = 0; i < pool->base.res_cap->num_ddc; i++) { - if (pool->base.engines[i] != NULL) - dce110_engine_destroy(&pool->base.engines[i]); - if (pool->base.hw_i2cs[i] != NULL) { - kfree(pool->base.hw_i2cs[i]); - pool->base.hw_i2cs[i] = NULL; - } - if (pool->base.sw_i2cs[i] != NULL) { - kfree(pool->base.sw_i2cs[i]); - pool->base.sw_i2cs[i] = NULL; - } - } - - for (i = 0; i < pool->base.stream_enc_count; i++) { - if (pool->base.stream_enc[i] != NULL) - kfree(DCE110STRENC_FROM_STRENC(pool->base.stream_enc[i])); - } - - for (i = 0; i < pool->base.clk_src_count; i++) { - if (pool->base.clock_sources[i] != NULL) { - dce112_clock_source_destroy(&pool->base.clock_sources[i]); - } - } - - if (pool->base.dp_clock_source != NULL) - dce112_clock_source_destroy(&pool->base.dp_clock_source); - - for (i = 0; i < pool->base.audio_count; i++) { - if (pool->base.audios[i] != NULL) { - dce_aud_destroy(&pool->base.audios[i]); - } - } - - if (pool->base.abm != NULL) - dce_abm_destroy(&pool->base.abm); - - if (pool->base.dmcu != NULL) - dce_dmcu_destroy(&pool->base.dmcu); - - if (pool->base.irqs != NULL) { - dal_irq_service_destroy(&pool->base.irqs); - } -} - -static struct clock_source *find_matching_pll( - struct resource_context *res_ctx, - const struct resource_pool *pool, - const struct dc_stream_state *const stream) -{ - switch (stream->link->link_enc->transmitter) { - case TRANSMITTER_UNIPHY_A: - return pool->clock_sources[DCE112_CLK_SRC_PLL0]; - case TRANSMITTER_UNIPHY_B: - return pool->clock_sources[DCE112_CLK_SRC_PLL1]; - case TRANSMITTER_UNIPHY_C: - return pool->clock_sources[DCE112_CLK_SRC_PLL2]; - case TRANSMITTER_UNIPHY_D: - return pool->clock_sources[DCE112_CLK_SRC_PLL3]; - case TRANSMITTER_UNIPHY_E: - return pool->clock_sources[DCE112_CLK_SRC_PLL4]; - case TRANSMITTER_UNIPHY_F: - return pool->clock_sources[DCE112_CLK_SRC_PLL5]; - default: - return NULL; - } - - return NULL; -} - -static enum dc_status build_mapped_resource( - const struct dc *dc, - struct dc_state *context, - struct dc_stream_state *stream) -{ - struct pipe_ctx *pipe_ctx = resource_get_otg_master_for_stream(&context->res_ctx, stream); - - if (!pipe_ctx) - return DC_ERROR_UNEXPECTED; - - dce110_resource_build_pipe_hw_param(pipe_ctx); - - resource_build_info_frame(pipe_ctx); - - return DC_OK; -} - -bool dce112_validate_bandwidth( - struct dc *dc, - struct dc_state *context, - bool fast_validate) -{ - bool result = false; - - DC_LOG_BANDWIDTH_CALCS( - "%s: start", - __func__); - - if (bw_calcs( - dc->ctx, - dc->bw_dceip, - dc->bw_vbios, - context->res_ctx.pipe_ctx, - dc->res_pool->pipe_count, - &context->bw_ctx.bw.dce)) - result = true; - - if (!result) - DC_LOG_BANDWIDTH_VALIDATION( - "%s: Bandwidth validation failed!", - __func__); - - if (memcmp(&dc->current_state->bw_ctx.bw.dce, - &context->bw_ctx.bw.dce, sizeof(context->bw_ctx.bw.dce))) { - - DC_LOG_BANDWIDTH_CALCS( - "%s: finish,\n" - "nbpMark_b: %d nbpMark_a: %d urgentMark_b: %d urgentMark_a: %d\n" - "stutMark_b: %d stutMark_a: %d\n" - "nbpMark_b: %d nbpMark_a: %d urgentMark_b: %d urgentMark_a: %d\n" - "stutMark_b: %d stutMark_a: %d\n" - "nbpMark_b: %d nbpMark_a: %d urgentMark_b: %d urgentMark_a: %d\n" - "stutMark_b: %d stutMark_a: %d stutter_mode_enable: %d\n" - "cstate: %d pstate: %d nbpstate: %d sync: %d dispclk: %d\n" - "sclk: %d sclk_sleep: %d yclk: %d blackout_recovery_time_us: %d\n" - , - __func__, - context->bw_ctx.bw.dce.nbp_state_change_wm_ns[0].b_mark, - context->bw_ctx.bw.dce.nbp_state_change_wm_ns[0].a_mark, - context->bw_ctx.bw.dce.urgent_wm_ns[0].b_mark, - context->bw_ctx.bw.dce.urgent_wm_ns[0].a_mark, - context->bw_ctx.bw.dce.stutter_exit_wm_ns[0].b_mark, - context->bw_ctx.bw.dce.stutter_exit_wm_ns[0].a_mark, - context->bw_ctx.bw.dce.nbp_state_change_wm_ns[1].b_mark, - context->bw_ctx.bw.dce.nbp_state_change_wm_ns[1].a_mark, - context->bw_ctx.bw.dce.urgent_wm_ns[1].b_mark, - context->bw_ctx.bw.dce.urgent_wm_ns[1].a_mark, - context->bw_ctx.bw.dce.stutter_exit_wm_ns[1].b_mark, - context->bw_ctx.bw.dce.stutter_exit_wm_ns[1].a_mark, - context->bw_ctx.bw.dce.nbp_state_change_wm_ns[2].b_mark, - context->bw_ctx.bw.dce.nbp_state_change_wm_ns[2].a_mark, - context->bw_ctx.bw.dce.urgent_wm_ns[2].b_mark, - context->bw_ctx.bw.dce.urgent_wm_ns[2].a_mark, - context->bw_ctx.bw.dce.stutter_exit_wm_ns[2].b_mark, - context->bw_ctx.bw.dce.stutter_exit_wm_ns[2].a_mark, - context->bw_ctx.bw.dce.stutter_mode_enable, - context->bw_ctx.bw.dce.cpuc_state_change_enable, - context->bw_ctx.bw.dce.cpup_state_change_enable, - context->bw_ctx.bw.dce.nbp_state_change_enable, - context->bw_ctx.bw.dce.all_displays_in_sync, - context->bw_ctx.bw.dce.dispclk_khz, - context->bw_ctx.bw.dce.sclk_khz, - context->bw_ctx.bw.dce.sclk_deep_sleep_khz, - context->bw_ctx.bw.dce.yclk_khz, - context->bw_ctx.bw.dce.blackout_recovery_time_us); - } - return result; -} - -enum dc_status resource_map_phy_clock_resources( - const struct dc *dc, - struct dc_state *context, - struct dc_stream_state *stream) -{ - - /* acquire new resources */ - struct pipe_ctx *pipe_ctx = resource_get_otg_master_for_stream( - &context->res_ctx, stream); - - if (!pipe_ctx) - return DC_ERROR_UNEXPECTED; - - if (dc_is_dp_signal(pipe_ctx->stream->signal) - || dc_is_virtual_signal(pipe_ctx->stream->signal)) - pipe_ctx->clock_source = - dc->res_pool->dp_clock_source; - else { - if (stream && stream->link && stream->link->link_enc) - pipe_ctx->clock_source = find_matching_pll( - &context->res_ctx, dc->res_pool, - stream); - } - - if (pipe_ctx->clock_source == NULL) - return DC_NO_CLOCK_SOURCE_RESOURCE; - - resource_reference_clock_source( - &context->res_ctx, - dc->res_pool, - pipe_ctx->clock_source); - - return DC_OK; -} - -static bool dce112_validate_surface_sets( - struct dc_state *context) -{ - int i; - - for (i = 0; i < context->stream_count; i++) { - if (context->stream_status[i].plane_count == 0) - continue; - - if (context->stream_status[i].plane_count > 1) - return false; - - if (context->stream_status[i].plane_states[0]->format - >= SURFACE_PIXEL_FORMAT_VIDEO_BEGIN) - return false; - } - - return true; -} - -enum dc_status dce112_add_stream_to_ctx( - struct dc *dc, - struct dc_state *new_ctx, - struct dc_stream_state *dc_stream) -{ - enum dc_status result; - - result = resource_map_pool_resources(dc, new_ctx, dc_stream); - - if (result == DC_OK) - result = resource_map_phy_clock_resources(dc, new_ctx, dc_stream); - - - if (result == DC_OK) - result = build_mapped_resource(dc, new_ctx, dc_stream); - - return result; -} - -static enum dc_status dce112_validate_global( - struct dc *dc, - struct dc_state *context) -{ - if (!dce112_validate_surface_sets(context)) - return DC_FAIL_SURFACE_VALIDATE; - - return DC_OK; -} - -static void dce112_destroy_resource_pool(struct resource_pool **pool) -{ - struct dce110_resource_pool *dce110_pool = TO_DCE110_RES_POOL(*pool); - - dce112_resource_destruct(dce110_pool); - kfree(dce110_pool); - *pool = NULL; -} - -static const struct resource_funcs dce112_res_pool_funcs = { - .destroy = dce112_destroy_resource_pool, - .link_enc_create = dce112_link_encoder_create, - .panel_cntl_create = dce112_panel_cntl_create, - .validate_bandwidth = dce112_validate_bandwidth, - .validate_plane = dce100_validate_plane, - .add_stream_to_ctx = dce112_add_stream_to_ctx, - .validate_global = dce112_validate_global, - .find_first_free_match_stream_enc_for_link = dce110_find_first_free_match_stream_enc_for_link -}; - -static void bw_calcs_data_update_from_pplib(struct dc *dc) -{ - struct dm_pp_clock_levels_with_latency eng_clks = {0}; - struct dm_pp_clock_levels_with_latency mem_clks = {0}; - struct dm_pp_wm_sets_with_clock_ranges clk_ranges = {0}; - struct dm_pp_clock_levels clks = {0}; - int memory_type_multiplier = MEMORY_TYPE_MULTIPLIER_CZ; - - if (dc->bw_vbios && dc->bw_vbios->memory_type == bw_def_hbm) - memory_type_multiplier = MEMORY_TYPE_HBM; - - /*do system clock TODO PPLIB: after PPLIB implement, - * then remove old way - */ - if (!dm_pp_get_clock_levels_by_type_with_latency( - dc->ctx, - DM_PP_CLOCK_TYPE_ENGINE_CLK, - &eng_clks)) { - - /* This is only for temporary */ - dm_pp_get_clock_levels_by_type( - dc->ctx, - DM_PP_CLOCK_TYPE_ENGINE_CLK, - &clks); - /* convert all the clock fro kHz to fix point mHz */ - dc->bw_vbios->high_sclk = bw_frc_to_fixed( - clks.clocks_in_khz[clks.num_levels-1], 1000); - dc->bw_vbios->mid1_sclk = bw_frc_to_fixed( - clks.clocks_in_khz[clks.num_levels/8], 1000); - dc->bw_vbios->mid2_sclk = bw_frc_to_fixed( - clks.clocks_in_khz[clks.num_levels*2/8], 1000); - dc->bw_vbios->mid3_sclk = bw_frc_to_fixed( - clks.clocks_in_khz[clks.num_levels*3/8], 1000); - dc->bw_vbios->mid4_sclk = bw_frc_to_fixed( - clks.clocks_in_khz[clks.num_levels*4/8], 1000); - dc->bw_vbios->mid5_sclk = bw_frc_to_fixed( - clks.clocks_in_khz[clks.num_levels*5/8], 1000); - dc->bw_vbios->mid6_sclk = bw_frc_to_fixed( - clks.clocks_in_khz[clks.num_levels*6/8], 1000); - dc->bw_vbios->low_sclk = bw_frc_to_fixed( - clks.clocks_in_khz[0], 1000); - - /*do memory clock*/ - dm_pp_get_clock_levels_by_type( - dc->ctx, - DM_PP_CLOCK_TYPE_MEMORY_CLK, - &clks); - - dc->bw_vbios->low_yclk = bw_frc_to_fixed( - clks.clocks_in_khz[0] * memory_type_multiplier, 1000); - dc->bw_vbios->mid_yclk = bw_frc_to_fixed( - clks.clocks_in_khz[clks.num_levels>>1] * memory_type_multiplier, - 1000); - dc->bw_vbios->high_yclk = bw_frc_to_fixed( - clks.clocks_in_khz[clks.num_levels-1] * memory_type_multiplier, - 1000); - - return; - } - - /* convert all the clock fro kHz to fix point mHz TODO: wloop data */ - dc->bw_vbios->high_sclk = bw_frc_to_fixed( - eng_clks.data[eng_clks.num_levels-1].clocks_in_khz, 1000); - dc->bw_vbios->mid1_sclk = bw_frc_to_fixed( - eng_clks.data[eng_clks.num_levels/8].clocks_in_khz, 1000); - dc->bw_vbios->mid2_sclk = bw_frc_to_fixed( - eng_clks.data[eng_clks.num_levels*2/8].clocks_in_khz, 1000); - dc->bw_vbios->mid3_sclk = bw_frc_to_fixed( - eng_clks.data[eng_clks.num_levels*3/8].clocks_in_khz, 1000); - dc->bw_vbios->mid4_sclk = bw_frc_to_fixed( - eng_clks.data[eng_clks.num_levels*4/8].clocks_in_khz, 1000); - dc->bw_vbios->mid5_sclk = bw_frc_to_fixed( - eng_clks.data[eng_clks.num_levels*5/8].clocks_in_khz, 1000); - dc->bw_vbios->mid6_sclk = bw_frc_to_fixed( - eng_clks.data[eng_clks.num_levels*6/8].clocks_in_khz, 1000); - dc->bw_vbios->low_sclk = bw_frc_to_fixed( - eng_clks.data[0].clocks_in_khz, 1000); - - /*do memory clock*/ - dm_pp_get_clock_levels_by_type_with_latency( - dc->ctx, - DM_PP_CLOCK_TYPE_MEMORY_CLK, - &mem_clks); - - /* we don't need to call PPLIB for validation clock since they - * also give us the highest sclk and highest mclk (UMA clock). - * ALSO always convert UMA clock (from PPLIB) to YCLK (HW formula): - * YCLK = UMACLK*m_memoryTypeMultiplier - */ - dc->bw_vbios->low_yclk = bw_frc_to_fixed( - mem_clks.data[0].clocks_in_khz * memory_type_multiplier, 1000); - dc->bw_vbios->mid_yclk = bw_frc_to_fixed( - mem_clks.data[mem_clks.num_levels>>1].clocks_in_khz * memory_type_multiplier, - 1000); - dc->bw_vbios->high_yclk = bw_frc_to_fixed( - mem_clks.data[mem_clks.num_levels-1].clocks_in_khz * memory_type_multiplier, - 1000); - - /* Now notify PPLib/SMU about which Watermarks sets they should select - * depending on DPM state they are in. And update BW MGR GFX Engine and - * Memory clock member variables for Watermarks calculations for each - * Watermark Set - */ - clk_ranges.num_wm_sets = 4; - clk_ranges.wm_clk_ranges[0].wm_set_id = WM_SET_A; - clk_ranges.wm_clk_ranges[0].wm_min_eng_clk_in_khz = - eng_clks.data[0].clocks_in_khz; - clk_ranges.wm_clk_ranges[0].wm_max_eng_clk_in_khz = - eng_clks.data[eng_clks.num_levels*3/8].clocks_in_khz - 1; - clk_ranges.wm_clk_ranges[0].wm_min_mem_clk_in_khz = - mem_clks.data[0].clocks_in_khz; - clk_ranges.wm_clk_ranges[0].wm_max_mem_clk_in_khz = - mem_clks.data[mem_clks.num_levels>>1].clocks_in_khz - 1; - - clk_ranges.wm_clk_ranges[1].wm_set_id = WM_SET_B; - clk_ranges.wm_clk_ranges[1].wm_min_eng_clk_in_khz = - eng_clks.data[eng_clks.num_levels*3/8].clocks_in_khz; - /* 5 GHz instead of data[7].clockInKHz to cover Overdrive */ - clk_ranges.wm_clk_ranges[1].wm_max_eng_clk_in_khz = 5000000; - clk_ranges.wm_clk_ranges[1].wm_min_mem_clk_in_khz = - mem_clks.data[0].clocks_in_khz; - clk_ranges.wm_clk_ranges[1].wm_max_mem_clk_in_khz = - mem_clks.data[mem_clks.num_levels>>1].clocks_in_khz - 1; - - clk_ranges.wm_clk_ranges[2].wm_set_id = WM_SET_C; - clk_ranges.wm_clk_ranges[2].wm_min_eng_clk_in_khz = - eng_clks.data[0].clocks_in_khz; - clk_ranges.wm_clk_ranges[2].wm_max_eng_clk_in_khz = - eng_clks.data[eng_clks.num_levels*3/8].clocks_in_khz - 1; - clk_ranges.wm_clk_ranges[2].wm_min_mem_clk_in_khz = - mem_clks.data[mem_clks.num_levels>>1].clocks_in_khz; - /* 5 GHz instead of data[2].clockInKHz to cover Overdrive */ - clk_ranges.wm_clk_ranges[2].wm_max_mem_clk_in_khz = 5000000; - - clk_ranges.wm_clk_ranges[3].wm_set_id = WM_SET_D; - clk_ranges.wm_clk_ranges[3].wm_min_eng_clk_in_khz = - eng_clks.data[eng_clks.num_levels*3/8].clocks_in_khz; - /* 5 GHz instead of data[7].clockInKHz to cover Overdrive */ - clk_ranges.wm_clk_ranges[3].wm_max_eng_clk_in_khz = 5000000; - clk_ranges.wm_clk_ranges[3].wm_min_mem_clk_in_khz = - mem_clks.data[mem_clks.num_levels>>1].clocks_in_khz; - /* 5 GHz instead of data[2].clockInKHz to cover Overdrive */ - clk_ranges.wm_clk_ranges[3].wm_max_mem_clk_in_khz = 5000000; - - /* Notify PP Lib/SMU which Watermarks to use for which clock ranges */ - dm_pp_notify_wm_clock_changes(dc->ctx, &clk_ranges); -} - -static const struct resource_caps *dce112_resource_cap( - struct hw_asic_id *asic_id) -{ - if (ASIC_REV_IS_POLARIS11_M(asic_id->hw_internal_rev) || - ASIC_REV_IS_POLARIS12_V(asic_id->hw_internal_rev)) - return &polaris_11_resource_cap; - else - return &polaris_10_resource_cap; -} - -static bool dce112_resource_construct( - uint8_t num_virtual_links, - struct dc *dc, - struct dce110_resource_pool *pool) -{ - unsigned int i; - struct dc_context *ctx = dc->ctx; - - ctx->dc_bios->regs = &bios_regs; - - pool->base.res_cap = dce112_resource_cap(&ctx->asic_id); - pool->base.funcs = &dce112_res_pool_funcs; - - /************************************************* - * Resource + asic cap harcoding * - *************************************************/ - pool->base.underlay_pipe_index = NO_UNDERLAY_PIPE; - pool->base.pipe_count = pool->base.res_cap->num_timing_generator; - pool->base.timing_generator_count = pool->base.res_cap->num_timing_generator; - dc->caps.max_downscale_ratio = 200; - dc->caps.i2c_speed_in_khz = 100; - dc->caps.i2c_speed_in_khz_hdcp = 100; /*1.4 w/a not applied by default*/ - dc->caps.max_cursor_size = 128; - dc->caps.min_horizontal_blanking_period = 80; - dc->caps.dual_link_dvi = true; - dc->caps.extended_aux_timeout_support = false; - dc->debug = debug_defaults; - - /************************************************* - * Create resources * - *************************************************/ - - pool->base.clock_sources[DCE112_CLK_SRC_PLL0] = - dce112_clock_source_create( - ctx, ctx->dc_bios, - CLOCK_SOURCE_COMBO_PHY_PLL0, - &clk_src_regs[0], false); - pool->base.clock_sources[DCE112_CLK_SRC_PLL1] = - dce112_clock_source_create( - ctx, ctx->dc_bios, - CLOCK_SOURCE_COMBO_PHY_PLL1, - &clk_src_regs[1], false); - pool->base.clock_sources[DCE112_CLK_SRC_PLL2] = - dce112_clock_source_create( - ctx, ctx->dc_bios, - CLOCK_SOURCE_COMBO_PHY_PLL2, - &clk_src_regs[2], false); - pool->base.clock_sources[DCE112_CLK_SRC_PLL3] = - dce112_clock_source_create( - ctx, ctx->dc_bios, - CLOCK_SOURCE_COMBO_PHY_PLL3, - &clk_src_regs[3], false); - pool->base.clock_sources[DCE112_CLK_SRC_PLL4] = - dce112_clock_source_create( - ctx, ctx->dc_bios, - CLOCK_SOURCE_COMBO_PHY_PLL4, - &clk_src_regs[4], false); - pool->base.clock_sources[DCE112_CLK_SRC_PLL5] = - dce112_clock_source_create( - ctx, ctx->dc_bios, - CLOCK_SOURCE_COMBO_PHY_PLL5, - &clk_src_regs[5], false); - pool->base.clk_src_count = DCE112_CLK_SRC_TOTAL; - - pool->base.dp_clock_source = dce112_clock_source_create( - ctx, ctx->dc_bios, - CLOCK_SOURCE_ID_DP_DTO, &clk_src_regs[0], true); - - - for (i = 0; i < pool->base.clk_src_count; i++) { - if (pool->base.clock_sources[i] == NULL) { - dm_error("DC: failed to create clock sources!\n"); - BREAK_TO_DEBUGGER(); - goto res_create_fail; - } - } - - pool->base.dmcu = dce_dmcu_create(ctx, - &dmcu_regs, - &dmcu_shift, - &dmcu_mask); - if (pool->base.dmcu == NULL) { - dm_error("DC: failed to create dmcu!\n"); - BREAK_TO_DEBUGGER(); - goto res_create_fail; - } - - pool->base.abm = dce_abm_create(ctx, - &abm_regs, - &abm_shift, - &abm_mask); - if (pool->base.abm == NULL) { - dm_error("DC: failed to create abm!\n"); - BREAK_TO_DEBUGGER(); - goto res_create_fail; - } - - { - struct irq_service_init_data init_data; - init_data.ctx = dc->ctx; - pool->base.irqs = dal_irq_service_dce110_create(&init_data); - if (!pool->base.irqs) - goto res_create_fail; - } - - for (i = 0; i < pool->base.pipe_count; i++) { - pool->base.timing_generators[i] = - dce112_timing_generator_create( - ctx, - i, - &dce112_tg_offsets[i]); - if (pool->base.timing_generators[i] == NULL) { - BREAK_TO_DEBUGGER(); - dm_error("DC: failed to create tg!\n"); - goto res_create_fail; - } - - pool->base.mis[i] = dce112_mem_input_create(ctx, i); - if (pool->base.mis[i] == NULL) { - BREAK_TO_DEBUGGER(); - dm_error( - "DC: failed to create memory input!\n"); - goto res_create_fail; - } - - pool->base.ipps[i] = dce112_ipp_create(ctx, i); - if (pool->base.ipps[i] == NULL) { - BREAK_TO_DEBUGGER(); - dm_error( - "DC:failed to create input pixel processor!\n"); - goto res_create_fail; - } - - pool->base.transforms[i] = dce112_transform_create(ctx, i); - if (pool->base.transforms[i] == NULL) { - BREAK_TO_DEBUGGER(); - dm_error( - "DC: failed to create transform!\n"); - goto res_create_fail; - } - - pool->base.opps[i] = dce112_opp_create( - ctx, - i); - if (pool->base.opps[i] == NULL) { - BREAK_TO_DEBUGGER(); - dm_error( - "DC:failed to create output pixel processor!\n"); - goto res_create_fail; - } - } - - for (i = 0; i < pool->base.res_cap->num_ddc; i++) { - pool->base.engines[i] = dce112_aux_engine_create(ctx, i); - if (pool->base.engines[i] == NULL) { - BREAK_TO_DEBUGGER(); - dm_error( - "DC:failed to create aux engine!!\n"); - goto res_create_fail; - } - pool->base.hw_i2cs[i] = dce112_i2c_hw_create(ctx, i); - if (pool->base.hw_i2cs[i] == NULL) { - BREAK_TO_DEBUGGER(); - dm_error( - "DC:failed to create i2c engine!!\n"); - goto res_create_fail; - } - pool->base.sw_i2cs[i] = NULL; - } - - if (!resource_construct(num_virtual_links, dc, &pool->base, - &res_create_funcs)) - goto res_create_fail; - - dc->caps.max_planes = pool->base.pipe_count; - - for (i = 0; i < dc->caps.max_planes; ++i) - dc->caps.planes[i] = plane_cap; - - /* Create hardware sequencer */ - dce112_hw_sequencer_construct(dc); - - bw_calcs_init(dc->bw_dceip, dc->bw_vbios, dc->ctx->asic_id); - - bw_calcs_data_update_from_pplib(dc); - - return true; - -res_create_fail: - dce112_resource_destruct(pool); - return false; -} - -struct resource_pool *dce112_create_resource_pool( - uint8_t num_virtual_links, - struct dc *dc) -{ - struct dce110_resource_pool *pool = - kzalloc(sizeof(struct dce110_resource_pool), GFP_KERNEL); - - if (!pool) - return NULL; - - if (dce112_resource_construct(num_virtual_links, dc, pool)) - return &pool->base; - - kfree(pool); - BREAK_TO_DEBUGGER(); - return NULL; -} diff --git a/drivers/gpu/drm/amd/display/dc/dce112/dce112_resource.h b/drivers/gpu/drm/amd/display/dc/dce112/dce112_resource.h deleted file mode 100644 index 1f57ebc6f9b4..000000000000 --- a/drivers/gpu/drm/amd/display/dc/dce112/dce112_resource.h +++ /dev/null @@ -1,57 +0,0 @@ -/* -* Copyright 2012-15 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_RESOURCE_DCE112_H__ -#define __DC_RESOURCE_DCE112_H__ - -#include "core_types.h" - -struct dc; -struct resource_pool; - -struct resource_pool *dce112_create_resource_pool( - uint8_t num_virtual_links, - struct dc *dc); - -enum dc_status dce112_validate_with_context( - struct dc *dc, - const struct dc_validation_set set[], - int set_count, - struct dc_state *context, - struct dc_state *old_context); - -bool dce112_validate_bandwidth( - struct dc *dc, - struct dc_state *context, - bool fast_validate); - -enum dc_status dce112_add_stream_to_ctx( - struct dc *dc, - struct dc_state *new_ctx, - struct dc_stream_state *dc_stream); - - -#endif /* __DC_RESOURCE_DCE112_H__ */ - diff --git a/drivers/gpu/drm/amd/display/dc/dce120/Makefile b/drivers/gpu/drm/amd/display/dc/dce120/Makefile index 097cf407a15d..1e3ef68a452a 100644 --- a/drivers/gpu/drm/amd/display/dc/dce120/Makefile +++ b/drivers/gpu/drm/amd/display/dc/dce120/Makefile @@ -26,7 +26,7 @@ CFLAGS_$(AMDDALPATH)/dc/dce120/dce120_resource.o = $(call cc-disable-warning, override-init) -DCE120 = dce120_resource.o dce120_timing_generator.o \ +DCE120 = dce120_timing_generator.o AMD_DAL_DCE120 = $(addprefix $(AMDDALPATH)/dc/dce120/,$(DCE120)) diff --git a/drivers/gpu/drm/amd/display/dc/dce120/dce120_resource.c b/drivers/gpu/drm/amd/display/dc/dce120/dce120_resource.c deleted file mode 100644 index 962de79be169..000000000000 --- a/drivers/gpu/drm/amd/display/dc/dce120/dce120_resource.c +++ /dev/null @@ -1,1288 +0,0 @@ -/* -* Copyright 2012-15 Advanced Micro Devices, Inc.cls -* - * - * 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 "dm_services.h" - - -#include "stream_encoder.h" -#include "resource.h" -#include "include/irq_service_interface.h" -#include "dce120_resource.h" - -#include "dce112/dce112_resource.h" - -#include "dce110/dce110_resource.h" -#include "virtual/virtual_stream_encoder.h" -#include "dce120_timing_generator.h" -#include "irq/dce120/irq_service_dce120.h" -#include "dce/dce_opp.h" -#include "dce/dce_clock_source.h" -#include "dce/dce_ipp.h" -#include "dce/dce_mem_input.h" -#include "dce/dce_panel_cntl.h" - -#include "dce110/dce110_hwseq.h" -#include "dce120/dce120_hwseq.h" -#include "dce/dce_transform.h" -#include "clk_mgr.h" -#include "dce/dce_audio.h" -#include "dce/dce_link_encoder.h" -#include "dce/dce_stream_encoder.h" -#include "dce/dce_hwseq.h" -#include "dce/dce_abm.h" -#include "dce/dce_dmcu.h" -#include "dce/dce_aux.h" -#include "dce/dce_i2c.h" - -#include "dce/dce_12_0_offset.h" -#include "dce/dce_12_0_sh_mask.h" -#include "soc15_hw_ip.h" -#include "vega10_ip_offset.h" -#include "nbio/nbio_6_1_offset.h" -#include "mmhub/mmhub_1_0_offset.h" -#include "mmhub/mmhub_1_0_sh_mask.h" -#include "reg_helper.h" - -#include "dce100/dce100_resource.h" - -#ifndef mmDP0_DP_DPHY_INTERNAL_CTRL - #define mmDP0_DP_DPHY_INTERNAL_CTRL 0x210f - #define mmDP0_DP_DPHY_INTERNAL_CTRL_BASE_IDX 2 - #define mmDP1_DP_DPHY_INTERNAL_CTRL 0x220f - #define mmDP1_DP_DPHY_INTERNAL_CTRL_BASE_IDX 2 - #define mmDP2_DP_DPHY_INTERNAL_CTRL 0x230f - #define mmDP2_DP_DPHY_INTERNAL_CTRL_BASE_IDX 2 - #define mmDP3_DP_DPHY_INTERNAL_CTRL 0x240f - #define mmDP3_DP_DPHY_INTERNAL_CTRL_BASE_IDX 2 - #define mmDP4_DP_DPHY_INTERNAL_CTRL 0x250f - #define mmDP4_DP_DPHY_INTERNAL_CTRL_BASE_IDX 2 - #define mmDP5_DP_DPHY_INTERNAL_CTRL 0x260f - #define mmDP5_DP_DPHY_INTERNAL_CTRL_BASE_IDX 2 - #define mmDP6_DP_DPHY_INTERNAL_CTRL 0x270f - #define mmDP6_DP_DPHY_INTERNAL_CTRL_BASE_IDX 2 -#endif - -enum dce120_clk_src_array_id { - DCE120_CLK_SRC_PLL0, - DCE120_CLK_SRC_PLL1, - DCE120_CLK_SRC_PLL2, - DCE120_CLK_SRC_PLL3, - DCE120_CLK_SRC_PLL4, - DCE120_CLK_SRC_PLL5, - - DCE120_CLK_SRC_TOTAL -}; - -static const struct dce110_timing_generator_offsets dce120_tg_offsets[] = { - { - .crtc = (mmCRTC0_CRTC_CONTROL - mmCRTC0_CRTC_CONTROL), - }, - { - .crtc = (mmCRTC1_CRTC_CONTROL - mmCRTC0_CRTC_CONTROL), - }, - { - .crtc = (mmCRTC2_CRTC_CONTROL - mmCRTC0_CRTC_CONTROL), - }, - { - .crtc = (mmCRTC3_CRTC_CONTROL - mmCRTC0_CRTC_CONTROL), - }, - { - .crtc = (mmCRTC4_CRTC_CONTROL - mmCRTC0_CRTC_CONTROL), - }, - { - .crtc = (mmCRTC5_CRTC_CONTROL - mmCRTC0_CRTC_CONTROL), - } -}; - -/* begin ********************* - * macros to expend register list macro defined in HW object header file */ - -#define BASE_INNER(seg) \ - DCE_BASE__INST0_SEG ## seg - -#define NBIO_BASE_INNER(seg) \ - NBIF_BASE__INST0_SEG ## seg - -#define NBIO_BASE(seg) \ - NBIO_BASE_INNER(seg) - -/* compile time expand base address. */ -#define BASE(seg) \ - BASE_INNER(seg) - -#define SR(reg_name)\ - .reg_name = BASE(mm ## reg_name ## _BASE_IDX) + \ - mm ## reg_name - -#define SRI(reg_name, block, id)\ - .reg_name = BASE(mm ## block ## id ## _ ## reg_name ## _BASE_IDX) + \ - mm ## block ## id ## _ ## reg_name - -/* MMHUB */ -#define MMHUB_BASE_INNER(seg) \ - MMHUB_BASE__INST0_SEG ## seg - -#define MMHUB_BASE(seg) \ - MMHUB_BASE_INNER(seg) - -#define MMHUB_SR(reg_name)\ - .reg_name = MMHUB_BASE(mm ## reg_name ## _BASE_IDX) + \ - mm ## reg_name - -/* macros to expend register list macro defined in HW object header file - * end *********************/ - - -static const struct dce_dmcu_registers dmcu_regs = { - DMCU_DCE110_COMMON_REG_LIST() -}; - -static const struct dce_dmcu_shift dmcu_shift = { - DMCU_MASK_SH_LIST_DCE110(__SHIFT) -}; - -static const struct dce_dmcu_mask dmcu_mask = { - DMCU_MASK_SH_LIST_DCE110(_MASK) -}; - -static const struct dce_abm_registers abm_regs = { - ABM_DCE110_COMMON_REG_LIST() -}; - -static const struct dce_abm_shift abm_shift = { - ABM_MASK_SH_LIST_DCE110(__SHIFT) -}; - -static const struct dce_abm_mask abm_mask = { - ABM_MASK_SH_LIST_DCE110(_MASK) -}; - -#define ipp_regs(id)\ -[id] = {\ - IPP_DCE110_REG_LIST_DCE_BASE(id)\ -} - -static const struct dce_ipp_registers ipp_regs[] = { - ipp_regs(0), - ipp_regs(1), - ipp_regs(2), - ipp_regs(3), - ipp_regs(4), - ipp_regs(5) -}; - -static const struct dce_ipp_shift ipp_shift = { - IPP_DCE120_MASK_SH_LIST_SOC_BASE(__SHIFT) -}; - -static const struct dce_ipp_mask ipp_mask = { - IPP_DCE120_MASK_SH_LIST_SOC_BASE(_MASK) -}; - -#define transform_regs(id)\ -[id] = {\ - XFM_COMMON_REG_LIST_DCE110(id)\ -} - -static const struct dce_transform_registers xfm_regs[] = { - transform_regs(0), - transform_regs(1), - transform_regs(2), - transform_regs(3), - transform_regs(4), - transform_regs(5) -}; - -static const struct dce_transform_shift xfm_shift = { - XFM_COMMON_MASK_SH_LIST_SOC_BASE(__SHIFT) -}; - -static const struct dce_transform_mask xfm_mask = { - XFM_COMMON_MASK_SH_LIST_SOC_BASE(_MASK) -}; - -#define aux_regs(id)\ -[id] = {\ - AUX_REG_LIST(id)\ -} - -static const struct dce110_link_enc_aux_registers link_enc_aux_regs[] = { - aux_regs(0), - aux_regs(1), - aux_regs(2), - aux_regs(3), - aux_regs(4), - aux_regs(5) -}; - -#define hpd_regs(id)\ -[id] = {\ - HPD_REG_LIST(id)\ -} - -static const struct dce110_link_enc_hpd_registers link_enc_hpd_regs[] = { - hpd_regs(0), - hpd_regs(1), - hpd_regs(2), - hpd_regs(3), - hpd_regs(4), - hpd_regs(5) -}; - -#define link_regs(id)\ -[id] = {\ - LE_DCE120_REG_LIST(id), \ - SRI(DP_DPHY_INTERNAL_CTRL, DP, id) \ -} - -static const struct dce110_link_enc_registers link_enc_regs[] = { - link_regs(0), - link_regs(1), - link_regs(2), - link_regs(3), - link_regs(4), - link_regs(5), - link_regs(6), -}; - - -#define stream_enc_regs(id)\ -[id] = {\ - SE_COMMON_REG_LIST(id),\ - .TMDS_CNTL = 0,\ -} - -static const struct dce110_stream_enc_registers stream_enc_regs[] = { - stream_enc_regs(0), - stream_enc_regs(1), - stream_enc_regs(2), - stream_enc_regs(3), - stream_enc_regs(4), - stream_enc_regs(5) -}; - -static const struct dce_stream_encoder_shift se_shift = { - SE_COMMON_MASK_SH_LIST_DCE120(__SHIFT) -}; - -static const struct dce_stream_encoder_mask se_mask = { - SE_COMMON_MASK_SH_LIST_DCE120(_MASK) -}; - -static const struct dce_panel_cntl_registers panel_cntl_regs[] = { - { DCE_PANEL_CNTL_REG_LIST() } -}; - -static const struct dce_panel_cntl_shift panel_cntl_shift = { - DCE_PANEL_CNTL_MASK_SH_LIST(__SHIFT) -}; - -static const struct dce_panel_cntl_mask panel_cntl_mask = { - DCE_PANEL_CNTL_MASK_SH_LIST(_MASK) -}; - -static const struct dce110_aux_registers_shift aux_shift = { - DCE12_AUX_MASK_SH_LIST(__SHIFT) -}; - -static const struct dce110_aux_registers_mask aux_mask = { - DCE12_AUX_MASK_SH_LIST(_MASK) -}; - -#define opp_regs(id)\ -[id] = {\ - OPP_DCE_120_REG_LIST(id),\ -} - -static const struct dce_opp_registers opp_regs[] = { - opp_regs(0), - opp_regs(1), - opp_regs(2), - opp_regs(3), - opp_regs(4), - opp_regs(5) -}; - -static const struct dce_opp_shift opp_shift = { - OPP_COMMON_MASK_SH_LIST_DCE_120(__SHIFT) -}; - -static const struct dce_opp_mask opp_mask = { - OPP_COMMON_MASK_SH_LIST_DCE_120(_MASK) -}; - #define aux_engine_regs(id)\ -[id] = {\ - AUX_COMMON_REG_LIST(id), \ - .AUX_RESET_MASK = 0 \ -} - -static const struct dce110_aux_registers aux_engine_regs[] = { - aux_engine_regs(0), - aux_engine_regs(1), - aux_engine_regs(2), - aux_engine_regs(3), - aux_engine_regs(4), - aux_engine_regs(5) -}; - -#define audio_regs(id)\ -[id] = {\ - AUD_COMMON_REG_LIST(id)\ -} - -static const struct dce_audio_registers audio_regs[] = { - audio_regs(0), - audio_regs(1), - audio_regs(2), - audio_regs(3), - audio_regs(4), - audio_regs(5), - audio_regs(6), -}; - -#define DCE120_AUD_COMMON_MASK_SH_LIST(mask_sh)\ - SF(AZF0ENDPOINT0_AZALIA_F0_CODEC_ENDPOINT_INDEX, AZALIA_ENDPOINT_REG_INDEX, mask_sh),\ - SF(AZF0ENDPOINT0_AZALIA_F0_CODEC_ENDPOINT_DATA, AZALIA_ENDPOINT_REG_DATA, mask_sh),\ - AUD_COMMON_MASK_SH_LIST_BASE(mask_sh) - -static const struct dce_audio_shift audio_shift = { - DCE120_AUD_COMMON_MASK_SH_LIST(__SHIFT) -}; - -static const struct dce_audio_mask audio_mask = { - DCE120_AUD_COMMON_MASK_SH_LIST(_MASK) -}; - -static int map_transmitter_id_to_phy_instance( - enum transmitter transmitter) -{ - switch (transmitter) { - case TRANSMITTER_UNIPHY_A: - return 0; - case TRANSMITTER_UNIPHY_B: - return 1; - case TRANSMITTER_UNIPHY_C: - return 2; - case TRANSMITTER_UNIPHY_D: - return 3; - case TRANSMITTER_UNIPHY_E: - return 4; - case TRANSMITTER_UNIPHY_F: - return 5; - case TRANSMITTER_UNIPHY_G: - return 6; - default: - ASSERT(0); - return 0; - } -} - -#define clk_src_regs(index, id)\ -[index] = {\ - CS_COMMON_REG_LIST_DCE_112(id),\ -} - -static const struct dce110_clk_src_regs clk_src_regs[] = { - clk_src_regs(0, A), - clk_src_regs(1, B), - clk_src_regs(2, C), - clk_src_regs(3, D), - clk_src_regs(4, E), - clk_src_regs(5, F) -}; - -static const struct dce110_clk_src_shift cs_shift = { - CS_COMMON_MASK_SH_LIST_DCE_112(__SHIFT) -}; - -static const struct dce110_clk_src_mask cs_mask = { - CS_COMMON_MASK_SH_LIST_DCE_112(_MASK) -}; - -static struct output_pixel_processor *dce120_opp_create( - struct dc_context *ctx, - uint32_t inst) -{ - struct dce110_opp *opp = - kzalloc(sizeof(struct dce110_opp), GFP_KERNEL); - - if (!opp) - return NULL; - - dce110_opp_construct(opp, - ctx, inst, &opp_regs[inst], &opp_shift, &opp_mask); - return &opp->base; -} -static struct dce_aux *dce120_aux_engine_create( - struct dc_context *ctx, - uint32_t inst) -{ - struct aux_engine_dce110 *aux_engine = - kzalloc(sizeof(struct aux_engine_dce110), GFP_KERNEL); - - if (!aux_engine) - return NULL; - - dce110_aux_engine_construct(aux_engine, ctx, inst, - SW_AUX_TIMEOUT_PERIOD_MULTIPLIER * AUX_TIMEOUT_PERIOD, - &aux_engine_regs[inst], - &aux_mask, - &aux_shift, - ctx->dc->caps.extended_aux_timeout_support); - - return &aux_engine->base; -} -#define i2c_inst_regs(id) { I2C_HW_ENGINE_COMMON_REG_LIST(id) } - -static const struct dce_i2c_registers i2c_hw_regs[] = { - i2c_inst_regs(1), - i2c_inst_regs(2), - i2c_inst_regs(3), - i2c_inst_regs(4), - i2c_inst_regs(5), - i2c_inst_regs(6), -}; - -static const struct dce_i2c_shift i2c_shifts = { - I2C_COMMON_MASK_SH_LIST_DCE110(__SHIFT) -}; - -static const struct dce_i2c_mask i2c_masks = { - I2C_COMMON_MASK_SH_LIST_DCE110(_MASK) -}; - -static struct dce_i2c_hw *dce120_i2c_hw_create( - struct dc_context *ctx, - uint32_t inst) -{ - struct dce_i2c_hw *dce_i2c_hw = - kzalloc(sizeof(struct dce_i2c_hw), GFP_KERNEL); - - if (!dce_i2c_hw) - return NULL; - - dce112_i2c_hw_construct(dce_i2c_hw, ctx, inst, - &i2c_hw_regs[inst], &i2c_shifts, &i2c_masks); - - return dce_i2c_hw; -} -static const struct bios_registers bios_regs = { - .BIOS_SCRATCH_3 = mmBIOS_SCRATCH_3 + NBIO_BASE(mmBIOS_SCRATCH_3_BASE_IDX), - .BIOS_SCRATCH_6 = mmBIOS_SCRATCH_6 + NBIO_BASE(mmBIOS_SCRATCH_6_BASE_IDX) -}; - -static const struct resource_caps res_cap = { - .num_timing_generator = 6, - .num_audio = 7, - .num_stream_encoder = 6, - .num_pll = 6, - .num_ddc = 6, -}; - -static const struct dc_plane_cap plane_cap = { - .type = DC_PLANE_TYPE_DCE_RGB, - - .pixel_format_support = { - .argb8888 = true, - .nv12 = false, - .fp16 = true - }, - - .max_upscale_factor = { - .argb8888 = 16000, - .nv12 = 1, - .fp16 = 1 - }, - - .max_downscale_factor = { - .argb8888 = 250, - .nv12 = 1, - .fp16 = 1 - } -}; - -static const struct dc_debug_options debug_defaults = { - .disable_clock_gate = true, - .enable_legacy_fast_update = true, -}; - -static struct clock_source *dce120_clock_source_create( - struct dc_context *ctx, - struct dc_bios *bios, - enum clock_source_id id, - const struct dce110_clk_src_regs *regs, - bool dp_clk_src) -{ - struct dce110_clk_src *clk_src = - kzalloc(sizeof(*clk_src), GFP_KERNEL); - - if (!clk_src) - return NULL; - - if (dce112_clk_src_construct(clk_src, ctx, bios, id, - regs, &cs_shift, &cs_mask)) { - clk_src->base.dp_clk_src = dp_clk_src; - return &clk_src->base; - } - - kfree(clk_src); - BREAK_TO_DEBUGGER(); - return NULL; -} - -static void dce120_clock_source_destroy(struct clock_source **clk_src) -{ - kfree(TO_DCE110_CLK_SRC(*clk_src)); - *clk_src = NULL; -} - - -static bool dce120_hw_sequencer_create(struct dc *dc) -{ - /* All registers used by dce11.2 match those in dce11 in offset and - * structure - */ - dce120_hw_sequencer_construct(dc); - - /*TODO Move to separate file and Override what is needed */ - - return true; -} - -static struct timing_generator *dce120_timing_generator_create( - struct dc_context *ctx, - uint32_t instance, - const struct dce110_timing_generator_offsets *offsets) -{ - struct dce110_timing_generator *tg110 = - kzalloc(sizeof(struct dce110_timing_generator), GFP_KERNEL); - - if (!tg110) - return NULL; - - dce120_timing_generator_construct(tg110, ctx, instance, offsets); - return &tg110->base; -} - -static void dce120_transform_destroy(struct transform **xfm) -{ - kfree(TO_DCE_TRANSFORM(*xfm)); - *xfm = NULL; -} - -static void dce120_resource_destruct(struct dce110_resource_pool *pool) -{ - unsigned int i; - - for (i = 0; i < pool->base.pipe_count; i++) { - if (pool->base.opps[i] != NULL) - dce110_opp_destroy(&pool->base.opps[i]); - - if (pool->base.transforms[i] != NULL) - dce120_transform_destroy(&pool->base.transforms[i]); - - if (pool->base.ipps[i] != NULL) - dce_ipp_destroy(&pool->base.ipps[i]); - - if (pool->base.mis[i] != NULL) { - kfree(TO_DCE_MEM_INPUT(pool->base.mis[i])); - pool->base.mis[i] = NULL; - } - - if (pool->base.irqs != NULL) { - dal_irq_service_destroy(&pool->base.irqs); - } - - if (pool->base.timing_generators[i] != NULL) { - kfree(DCE110TG_FROM_TG(pool->base.timing_generators[i])); - pool->base.timing_generators[i] = NULL; - } - } - - for (i = 0; i < pool->base.res_cap->num_ddc; i++) { - if (pool->base.engines[i] != NULL) - dce110_engine_destroy(&pool->base.engines[i]); - if (pool->base.hw_i2cs[i] != NULL) { - kfree(pool->base.hw_i2cs[i]); - pool->base.hw_i2cs[i] = NULL; - } - if (pool->base.sw_i2cs[i] != NULL) { - kfree(pool->base.sw_i2cs[i]); - pool->base.sw_i2cs[i] = NULL; - } - } - - for (i = 0; i < pool->base.audio_count; i++) { - if (pool->base.audios[i]) - dce_aud_destroy(&pool->base.audios[i]); - } - - for (i = 0; i < pool->base.stream_enc_count; i++) { - if (pool->base.stream_enc[i] != NULL) - kfree(DCE110STRENC_FROM_STRENC(pool->base.stream_enc[i])); - } - - for (i = 0; i < pool->base.clk_src_count; i++) { - if (pool->base.clock_sources[i] != NULL) - dce120_clock_source_destroy( - &pool->base.clock_sources[i]); - } - - if (pool->base.dp_clock_source != NULL) - dce120_clock_source_destroy(&pool->base.dp_clock_source); - - if (pool->base.abm != NULL) - dce_abm_destroy(&pool->base.abm); - - if (pool->base.dmcu != NULL) - dce_dmcu_destroy(&pool->base.dmcu); -} - -static void read_dce_straps( - struct dc_context *ctx, - struct resource_straps *straps) -{ - uint32_t reg_val = dm_read_reg_soc15(ctx, mmCC_DC_MISC_STRAPS, 0); - - straps->audio_stream_number = get_reg_field_value(reg_val, - CC_DC_MISC_STRAPS, - AUDIO_STREAM_NUMBER); - straps->hdmi_disable = get_reg_field_value(reg_val, - CC_DC_MISC_STRAPS, - HDMI_DISABLE); - - reg_val = dm_read_reg_soc15(ctx, mmDC_PINSTRAPS, 0); - straps->dc_pinstraps_audio = get_reg_field_value(reg_val, - DC_PINSTRAPS, - DC_PINSTRAPS_AUDIO); -} - -static struct audio *create_audio( - struct dc_context *ctx, unsigned int inst) -{ - return dce_audio_create(ctx, inst, - &audio_regs[inst], &audio_shift, &audio_mask); -} - -static const struct encoder_feature_support link_enc_feature = { - .max_hdmi_deep_color = COLOR_DEPTH_121212, - .max_hdmi_pixel_clock = 600000, - .hdmi_ycbcr420_supported = true, - .dp_ycbcr420_supported = false, - .flags.bits.IS_HBR2_CAPABLE = true, - .flags.bits.IS_HBR3_CAPABLE = true, - .flags.bits.IS_TPS3_CAPABLE = true, - .flags.bits.IS_TPS4_CAPABLE = true, -}; - -static struct link_encoder *dce120_link_encoder_create( - struct dc_context *ctx, - const struct encoder_init_data *enc_init_data) -{ - struct dce110_link_encoder *enc110 = - kzalloc(sizeof(struct dce110_link_encoder), GFP_KERNEL); - int link_regs_id; - - if (!enc110) - return NULL; - - link_regs_id = - map_transmitter_id_to_phy_instance(enc_init_data->transmitter); - - dce110_link_encoder_construct(enc110, - enc_init_data, - &link_enc_feature, - &link_enc_regs[link_regs_id], - &link_enc_aux_regs[enc_init_data->channel - 1], - &link_enc_hpd_regs[enc_init_data->hpd_source]); - - return &enc110->base; -} - -static struct panel_cntl *dce120_panel_cntl_create(const struct panel_cntl_init_data *init_data) -{ - struct dce_panel_cntl *panel_cntl = - kzalloc(sizeof(struct dce_panel_cntl), GFP_KERNEL); - - if (!panel_cntl) - return NULL; - - dce_panel_cntl_construct(panel_cntl, - init_data, - &panel_cntl_regs[init_data->inst], - &panel_cntl_shift, - &panel_cntl_mask); - - return &panel_cntl->base; -} - -static struct input_pixel_processor *dce120_ipp_create( - struct dc_context *ctx, uint32_t inst) -{ - struct dce_ipp *ipp = kzalloc(sizeof(struct dce_ipp), GFP_KERNEL); - - if (!ipp) { - BREAK_TO_DEBUGGER(); - return NULL; - } - - dce_ipp_construct(ipp, ctx, inst, - &ipp_regs[inst], &ipp_shift, &ipp_mask); - return &ipp->base; -} - -static struct stream_encoder *dce120_stream_encoder_create( - enum engine_id eng_id, - struct dc_context *ctx) -{ - struct dce110_stream_encoder *enc110 = - kzalloc(sizeof(struct dce110_stream_encoder), GFP_KERNEL); - - if (!enc110) - return NULL; - - dce110_stream_encoder_construct(enc110, ctx, ctx->dc_bios, eng_id, - &stream_enc_regs[eng_id], - &se_shift, &se_mask); - return &enc110->base; -} - -#define SRII(reg_name, block, id)\ - .reg_name[id] = BASE(mm ## block ## id ## _ ## reg_name ## _BASE_IDX) + \ - mm ## block ## id ## _ ## reg_name - -static const struct dce_hwseq_registers hwseq_reg = { - HWSEQ_DCE120_REG_LIST() -}; - -static const struct dce_hwseq_shift hwseq_shift = { - HWSEQ_DCE12_MASK_SH_LIST(__SHIFT) -}; - -static const struct dce_hwseq_mask hwseq_mask = { - HWSEQ_DCE12_MASK_SH_LIST(_MASK) -}; - -/* HWSEQ regs for VG20 */ -static const struct dce_hwseq_registers dce121_hwseq_reg = { - HWSEQ_VG20_REG_LIST() -}; - -static const struct dce_hwseq_shift dce121_hwseq_shift = { - HWSEQ_VG20_MASK_SH_LIST(__SHIFT) -}; - -static const struct dce_hwseq_mask dce121_hwseq_mask = { - HWSEQ_VG20_MASK_SH_LIST(_MASK) -}; - -static struct dce_hwseq *dce120_hwseq_create( - struct dc_context *ctx) -{ - struct dce_hwseq *hws = kzalloc(sizeof(struct dce_hwseq), GFP_KERNEL); - - if (hws) { - hws->ctx = ctx; - hws->regs = &hwseq_reg; - hws->shifts = &hwseq_shift; - hws->masks = &hwseq_mask; - } - return hws; -} - -static struct dce_hwseq *dce121_hwseq_create( - struct dc_context *ctx) -{ - struct dce_hwseq *hws = kzalloc(sizeof(struct dce_hwseq), GFP_KERNEL); - - if (hws) { - hws->ctx = ctx; - hws->regs = &dce121_hwseq_reg; - hws->shifts = &dce121_hwseq_shift; - hws->masks = &dce121_hwseq_mask; - } - return hws; -} - -static const struct resource_create_funcs res_create_funcs = { - .read_dce_straps = read_dce_straps, - .create_audio = create_audio, - .create_stream_encoder = dce120_stream_encoder_create, - .create_hwseq = dce120_hwseq_create, -}; - -static const struct resource_create_funcs dce121_res_create_funcs = { - .read_dce_straps = read_dce_straps, - .create_audio = create_audio, - .create_stream_encoder = dce120_stream_encoder_create, - .create_hwseq = dce121_hwseq_create, -}; - - -#define mi_inst_regs(id) { MI_DCE12_REG_LIST(id) } -static const struct dce_mem_input_registers mi_regs[] = { - mi_inst_regs(0), - mi_inst_regs(1), - mi_inst_regs(2), - mi_inst_regs(3), - mi_inst_regs(4), - mi_inst_regs(5), -}; - -static const struct dce_mem_input_shift mi_shifts = { - MI_DCE12_MASK_SH_LIST(__SHIFT) -}; - -static const struct dce_mem_input_mask mi_masks = { - MI_DCE12_MASK_SH_LIST(_MASK) -}; - -static struct mem_input *dce120_mem_input_create( - struct dc_context *ctx, - uint32_t inst) -{ - struct dce_mem_input *dce_mi = kzalloc(sizeof(struct dce_mem_input), - GFP_KERNEL); - - if (!dce_mi) { - BREAK_TO_DEBUGGER(); - return NULL; - } - - dce120_mem_input_construct(dce_mi, ctx, inst, &mi_regs[inst], &mi_shifts, &mi_masks); - return &dce_mi->base; -} - -static struct transform *dce120_transform_create( - struct dc_context *ctx, - uint32_t inst) -{ - struct dce_transform *transform = - kzalloc(sizeof(struct dce_transform), GFP_KERNEL); - - if (!transform) - return NULL; - - dce_transform_construct(transform, ctx, inst, - &xfm_regs[inst], &xfm_shift, &xfm_mask); - transform->lb_memory_size = 0x1404; /*5124*/ - return &transform->base; -} - -static void dce120_destroy_resource_pool(struct resource_pool **pool) -{ - struct dce110_resource_pool *dce110_pool = TO_DCE110_RES_POOL(*pool); - - dce120_resource_destruct(dce110_pool); - kfree(dce110_pool); - *pool = NULL; -} - -static const struct resource_funcs dce120_res_pool_funcs = { - .destroy = dce120_destroy_resource_pool, - .link_enc_create = dce120_link_encoder_create, - .panel_cntl_create = dce120_panel_cntl_create, - .validate_bandwidth = dce112_validate_bandwidth, - .validate_plane = dce100_validate_plane, - .add_stream_to_ctx = dce112_add_stream_to_ctx, - .find_first_free_match_stream_enc_for_link = dce110_find_first_free_match_stream_enc_for_link -}; - -static void bw_calcs_data_update_from_pplib(struct dc *dc) -{ - struct dm_pp_clock_levels_with_latency eng_clks = {0}; - struct dm_pp_clock_levels_with_latency mem_clks = {0}; - struct dm_pp_wm_sets_with_clock_ranges clk_ranges = {0}; - int i; - unsigned int clk; - unsigned int latency; - /*original logic in dal3*/ - int memory_type_multiplier = MEMORY_TYPE_MULTIPLIER_CZ; - - /*do system clock*/ - if (!dm_pp_get_clock_levels_by_type_with_latency( - dc->ctx, - DM_PP_CLOCK_TYPE_ENGINE_CLK, - &eng_clks) || eng_clks.num_levels == 0) { - - eng_clks.num_levels = 8; - clk = 300000; - - for (i = 0; i < eng_clks.num_levels; i++) { - eng_clks.data[i].clocks_in_khz = clk; - clk += 100000; - } - } - - /* convert all the clock fro kHz to fix point mHz TODO: wloop data */ - dc->bw_vbios->high_sclk = bw_frc_to_fixed( - eng_clks.data[eng_clks.num_levels-1].clocks_in_khz, 1000); - dc->bw_vbios->mid1_sclk = bw_frc_to_fixed( - eng_clks.data[eng_clks.num_levels/8].clocks_in_khz, 1000); - dc->bw_vbios->mid2_sclk = bw_frc_to_fixed( - eng_clks.data[eng_clks.num_levels*2/8].clocks_in_khz, 1000); - dc->bw_vbios->mid3_sclk = bw_frc_to_fixed( - eng_clks.data[eng_clks.num_levels*3/8].clocks_in_khz, 1000); - dc->bw_vbios->mid4_sclk = bw_frc_to_fixed( - eng_clks.data[eng_clks.num_levels*4/8].clocks_in_khz, 1000); - dc->bw_vbios->mid5_sclk = bw_frc_to_fixed( - eng_clks.data[eng_clks.num_levels*5/8].clocks_in_khz, 1000); - dc->bw_vbios->mid6_sclk = bw_frc_to_fixed( - eng_clks.data[eng_clks.num_levels*6/8].clocks_in_khz, 1000); - dc->bw_vbios->low_sclk = bw_frc_to_fixed( - eng_clks.data[0].clocks_in_khz, 1000); - - /*do memory clock*/ - if (!dm_pp_get_clock_levels_by_type_with_latency( - dc->ctx, - DM_PP_CLOCK_TYPE_MEMORY_CLK, - &mem_clks) || mem_clks.num_levels == 0) { - - mem_clks.num_levels = 3; - clk = 250000; - latency = 45; - - for (i = 0; i < eng_clks.num_levels; i++) { - mem_clks.data[i].clocks_in_khz = clk; - mem_clks.data[i].latency_in_us = latency; - clk += 500000; - latency -= 5; - } - - } - - /* we don't need to call PPLIB for validation clock since they - * also give us the highest sclk and highest mclk (UMA clock). - * ALSO always convert UMA clock (from PPLIB) to YCLK (HW formula): - * YCLK = UMACLK*m_memoryTypeMultiplier - */ - if (dc->bw_vbios->memory_type == bw_def_hbm) - memory_type_multiplier = MEMORY_TYPE_HBM; - - dc->bw_vbios->low_yclk = bw_frc_to_fixed( - mem_clks.data[0].clocks_in_khz * memory_type_multiplier, 1000); - dc->bw_vbios->mid_yclk = bw_frc_to_fixed( - mem_clks.data[mem_clks.num_levels>>1].clocks_in_khz * memory_type_multiplier, - 1000); - dc->bw_vbios->high_yclk = bw_frc_to_fixed( - mem_clks.data[mem_clks.num_levels-1].clocks_in_khz * memory_type_multiplier, - 1000); - - /* Now notify PPLib/SMU about which Watermarks sets they should select - * depending on DPM state they are in. And update BW MGR GFX Engine and - * Memory clock member variables for Watermarks calculations for each - * Watermark Set - */ - clk_ranges.num_wm_sets = 4; - clk_ranges.wm_clk_ranges[0].wm_set_id = WM_SET_A; - clk_ranges.wm_clk_ranges[0].wm_min_eng_clk_in_khz = - eng_clks.data[0].clocks_in_khz; - clk_ranges.wm_clk_ranges[0].wm_max_eng_clk_in_khz = - eng_clks.data[eng_clks.num_levels*3/8].clocks_in_khz - 1; - clk_ranges.wm_clk_ranges[0].wm_min_mem_clk_in_khz = - mem_clks.data[0].clocks_in_khz; - clk_ranges.wm_clk_ranges[0].wm_max_mem_clk_in_khz = - mem_clks.data[mem_clks.num_levels>>1].clocks_in_khz - 1; - - clk_ranges.wm_clk_ranges[1].wm_set_id = WM_SET_B; - clk_ranges.wm_clk_ranges[1].wm_min_eng_clk_in_khz = - eng_clks.data[eng_clks.num_levels*3/8].clocks_in_khz; - /* 5 GHz instead of data[7].clockInKHz to cover Overdrive */ - clk_ranges.wm_clk_ranges[1].wm_max_eng_clk_in_khz = 5000000; - clk_ranges.wm_clk_ranges[1].wm_min_mem_clk_in_khz = - mem_clks.data[0].clocks_in_khz; - clk_ranges.wm_clk_ranges[1].wm_max_mem_clk_in_khz = - mem_clks.data[mem_clks.num_levels>>1].clocks_in_khz - 1; - - clk_ranges.wm_clk_ranges[2].wm_set_id = WM_SET_C; - clk_ranges.wm_clk_ranges[2].wm_min_eng_clk_in_khz = - eng_clks.data[0].clocks_in_khz; - clk_ranges.wm_clk_ranges[2].wm_max_eng_clk_in_khz = - eng_clks.data[eng_clks.num_levels*3/8].clocks_in_khz - 1; - clk_ranges.wm_clk_ranges[2].wm_min_mem_clk_in_khz = - mem_clks.data[mem_clks.num_levels>>1].clocks_in_khz; - /* 5 GHz instead of data[2].clockInKHz to cover Overdrive */ - clk_ranges.wm_clk_ranges[2].wm_max_mem_clk_in_khz = 5000000; - - clk_ranges.wm_clk_ranges[3].wm_set_id = WM_SET_D; - clk_ranges.wm_clk_ranges[3].wm_min_eng_clk_in_khz = - eng_clks.data[eng_clks.num_levels*3/8].clocks_in_khz; - /* 5 GHz instead of data[7].clockInKHz to cover Overdrive */ - clk_ranges.wm_clk_ranges[3].wm_max_eng_clk_in_khz = 5000000; - clk_ranges.wm_clk_ranges[3].wm_min_mem_clk_in_khz = - mem_clks.data[mem_clks.num_levels>>1].clocks_in_khz; - /* 5 GHz instead of data[2].clockInKHz to cover Overdrive */ - clk_ranges.wm_clk_ranges[3].wm_max_mem_clk_in_khz = 5000000; - - /* Notify PP Lib/SMU which Watermarks to use for which clock ranges */ - dm_pp_notify_wm_clock_changes(dc->ctx, &clk_ranges); -} - -static uint32_t read_pipe_fuses(struct dc_context *ctx) -{ - uint32_t value = dm_read_reg_soc15(ctx, mmCC_DC_PIPE_DIS, 0); - /* VG20 support max 6 pipes */ - value = value & 0x3f; - return value; -} - -static bool dce120_resource_construct( - uint8_t num_virtual_links, - struct dc *dc, - struct dce110_resource_pool *pool) -{ - unsigned int i; - int j; - struct dc_context *ctx = dc->ctx; - struct irq_service_init_data irq_init_data; - static const struct resource_create_funcs *res_funcs; - bool is_vg20 = ASICREV_IS_VEGA20_P(ctx->asic_id.hw_internal_rev); - uint32_t pipe_fuses; - - ctx->dc_bios->regs = &bios_regs; - - pool->base.res_cap = &res_cap; - pool->base.funcs = &dce120_res_pool_funcs; - - /* TODO: Fill more data from GreenlandAsicCapability.cpp */ - pool->base.pipe_count = res_cap.num_timing_generator; - pool->base.timing_generator_count = pool->base.res_cap->num_timing_generator; - pool->base.underlay_pipe_index = NO_UNDERLAY_PIPE; - - dc->caps.max_downscale_ratio = 200; - dc->caps.i2c_speed_in_khz = 100; - dc->caps.i2c_speed_in_khz_hdcp = 100; /*1.4 w/a not applied by default*/ - dc->caps.max_cursor_size = 128; - dc->caps.min_horizontal_blanking_period = 80; - dc->caps.dual_link_dvi = true; - dc->caps.psp_setup_panel_mode = true; - dc->caps.extended_aux_timeout_support = false; - dc->debug = debug_defaults; - - /************************************************* - * Create resources * - *************************************************/ - - pool->base.clock_sources[DCE120_CLK_SRC_PLL0] = - dce120_clock_source_create(ctx, ctx->dc_bios, - CLOCK_SOURCE_COMBO_PHY_PLL0, - &clk_src_regs[0], false); - pool->base.clock_sources[DCE120_CLK_SRC_PLL1] = - dce120_clock_source_create(ctx, ctx->dc_bios, - CLOCK_SOURCE_COMBO_PHY_PLL1, - &clk_src_regs[1], false); - pool->base.clock_sources[DCE120_CLK_SRC_PLL2] = - dce120_clock_source_create(ctx, ctx->dc_bios, - CLOCK_SOURCE_COMBO_PHY_PLL2, - &clk_src_regs[2], false); - pool->base.clock_sources[DCE120_CLK_SRC_PLL3] = - dce120_clock_source_create(ctx, ctx->dc_bios, - CLOCK_SOURCE_COMBO_PHY_PLL3, - &clk_src_regs[3], false); - pool->base.clock_sources[DCE120_CLK_SRC_PLL4] = - dce120_clock_source_create(ctx, ctx->dc_bios, - CLOCK_SOURCE_COMBO_PHY_PLL4, - &clk_src_regs[4], false); - pool->base.clock_sources[DCE120_CLK_SRC_PLL5] = - dce120_clock_source_create(ctx, ctx->dc_bios, - CLOCK_SOURCE_COMBO_PHY_PLL5, - &clk_src_regs[5], false); - pool->base.clk_src_count = DCE120_CLK_SRC_TOTAL; - - pool->base.dp_clock_source = - dce120_clock_source_create(ctx, ctx->dc_bios, - CLOCK_SOURCE_ID_DP_DTO, - &clk_src_regs[0], true); - - for (i = 0; i < pool->base.clk_src_count; i++) { - if (pool->base.clock_sources[i] == NULL) { - dm_error("DC: failed to create clock sources!\n"); - BREAK_TO_DEBUGGER(); - goto clk_src_create_fail; - } - } - - pool->base.dmcu = dce_dmcu_create(ctx, - &dmcu_regs, - &dmcu_shift, - &dmcu_mask); - if (pool->base.dmcu == NULL) { - dm_error("DC: failed to create dmcu!\n"); - BREAK_TO_DEBUGGER(); - goto res_create_fail; - } - - pool->base.abm = dce_abm_create(ctx, - &abm_regs, - &abm_shift, - &abm_mask); - if (pool->base.abm == NULL) { - dm_error("DC: failed to create abm!\n"); - BREAK_TO_DEBUGGER(); - goto res_create_fail; - } - - - irq_init_data.ctx = dc->ctx; - pool->base.irqs = dal_irq_service_dce120_create(&irq_init_data); - if (!pool->base.irqs) - goto irqs_create_fail; - - /* VG20: Pipe harvesting enabled, retrieve valid pipe fuses */ - if (is_vg20) - pipe_fuses = read_pipe_fuses(ctx); - - /* index to valid pipe resource */ - j = 0; - for (i = 0; i < pool->base.pipe_count; i++) { - if (is_vg20) { - if ((pipe_fuses & (1 << i)) != 0) { - dm_error("DC: skip invalid pipe %d!\n", i); - continue; - } - } - - pool->base.timing_generators[j] = - dce120_timing_generator_create( - ctx, - i, - &dce120_tg_offsets[i]); - if (pool->base.timing_generators[j] == NULL) { - BREAK_TO_DEBUGGER(); - dm_error("DC: failed to create tg!\n"); - goto controller_create_fail; - } - - pool->base.mis[j] = dce120_mem_input_create(ctx, i); - - if (pool->base.mis[j] == NULL) { - BREAK_TO_DEBUGGER(); - dm_error( - "DC: failed to create memory input!\n"); - goto controller_create_fail; - } - - pool->base.ipps[j] = dce120_ipp_create(ctx, i); - if (pool->base.ipps[i] == NULL) { - BREAK_TO_DEBUGGER(); - dm_error( - "DC: failed to create input pixel processor!\n"); - goto controller_create_fail; - } - - pool->base.transforms[j] = dce120_transform_create(ctx, i); - if (pool->base.transforms[i] == NULL) { - BREAK_TO_DEBUGGER(); - dm_error( - "DC: failed to create transform!\n"); - goto res_create_fail; - } - - pool->base.opps[j] = dce120_opp_create( - ctx, - i); - if (pool->base.opps[j] == NULL) { - BREAK_TO_DEBUGGER(); - dm_error( - "DC: failed to create output pixel processor!\n"); - } - - /* check next valid pipe */ - j++; - } - - for (i = 0; i < pool->base.res_cap->num_ddc; i++) { - pool->base.engines[i] = dce120_aux_engine_create(ctx, i); - if (pool->base.engines[i] == NULL) { - BREAK_TO_DEBUGGER(); - dm_error( - "DC:failed to create aux engine!!\n"); - goto res_create_fail; - } - pool->base.hw_i2cs[i] = dce120_i2c_hw_create(ctx, i); - if (pool->base.hw_i2cs[i] == NULL) { - BREAK_TO_DEBUGGER(); - dm_error( - "DC:failed to create i2c engine!!\n"); - goto res_create_fail; - } - pool->base.sw_i2cs[i] = NULL; - } - - /* valid pipe num */ - pool->base.pipe_count = j; - pool->base.timing_generator_count = j; - - if (is_vg20) - res_funcs = &dce121_res_create_funcs; - else - res_funcs = &res_create_funcs; - - if (!resource_construct(num_virtual_links, dc, &pool->base, res_funcs)) - goto res_create_fail; - - /* Create hardware sequencer */ - if (!dce120_hw_sequencer_create(dc)) - goto controller_create_fail; - - dc->caps.max_planes = pool->base.pipe_count; - - for (i = 0; i < dc->caps.max_planes; ++i) - dc->caps.planes[i] = plane_cap; - - bw_calcs_init(dc->bw_dceip, dc->bw_vbios, dc->ctx->asic_id); - - bw_calcs_data_update_from_pplib(dc); - - return true; - -irqs_create_fail: -controller_create_fail: -clk_src_create_fail: -res_create_fail: - - dce120_resource_destruct(pool); - - return false; -} - -struct resource_pool *dce120_create_resource_pool( - uint8_t num_virtual_links, - struct dc *dc) -{ - struct dce110_resource_pool *pool = - kzalloc(sizeof(struct dce110_resource_pool), GFP_KERNEL); - - if (!pool) - return NULL; - - if (dce120_resource_construct(num_virtual_links, dc, pool)) - return &pool->base; - - kfree(pool); - BREAK_TO_DEBUGGER(); - return NULL; -} diff --git a/drivers/gpu/drm/amd/display/dc/dce120/dce120_resource.h b/drivers/gpu/drm/amd/display/dc/dce120/dce120_resource.h deleted file mode 100644 index 3d1f3cf012f4..000000000000 --- a/drivers/gpu/drm/amd/display/dc/dce120/dce120_resource.h +++ /dev/null @@ -1,39 +0,0 @@ -/* -* Copyright 2012-15 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_RESOURCE_DCE120_H__ -#define __DC_RESOURCE_DCE120_H__ - -#include "core_types.h" - -struct dc; -struct resource_pool; - -struct resource_pool *dce120_create_resource_pool( - uint8_t num_virtual_links, - struct dc *dc); - -#endif /* __DC_RESOURCE_DCE120_H__ */ - diff --git a/drivers/gpu/drm/amd/display/dc/dce80/Makefile b/drivers/gpu/drm/amd/display/dc/dce80/Makefile index 93dd68c31275..7eefffbdc925 100644 --- a/drivers/gpu/drm/amd/display/dc/dce80/Makefile +++ b/drivers/gpu/drm/amd/display/dc/dce80/Makefile @@ -25,8 +25,7 @@ CFLAGS_$(AMDDALPATH)/dc/dce80/dce80_resource.o = $(call cc-disable-warning, override-init) -DCE80 = dce80_timing_generator.o \ - dce80_resource.o +DCE80 = dce80_timing_generator.o AMD_DAL_DCE80 = $(addprefix $(AMDDALPATH)/dc/dce80/,$(DCE80)) diff --git a/drivers/gpu/drm/amd/display/dc/dce80/dce80_resource.c b/drivers/gpu/drm/amd/display/dc/dce80/dce80_resource.c deleted file mode 100644 index 35a2cce0c2b8..000000000000 --- a/drivers/gpu/drm/amd/display/dc/dce80/dce80_resource.c +++ /dev/null @@ -1,1544 +0,0 @@ -/* - * Copyright 2012-15 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_8_0_d.h" -#include "dce/dce_8_0_sh_mask.h" - -#include "dm_services.h" - -#include "link_encoder.h" -#include "stream_encoder.h" - -#include "resource.h" -#include "include/irq_service_interface.h" -#include "irq/dce80/irq_service_dce80.h" -#include "dce110/dce110_timing_generator.h" -#include "dce110/dce110_resource.h" -#include "dce80/dce80_timing_generator.h" -#include "dce/dce_mem_input.h" -#include "dce/dce_link_encoder.h" -#include "dce/dce_stream_encoder.h" -#include "dce/dce_ipp.h" -#include "dce/dce_transform.h" -#include "dce/dce_opp.h" -#include "dce/dce_clock_source.h" -#include "dce/dce_audio.h" -#include "dce/dce_hwseq.h" -#include "dce80/dce80_hwseq.h" -#include "dce100/dce100_resource.h" -#include "dce/dce_panel_cntl.h" - -#include "reg_helper.h" - -#include "dce/dce_dmcu.h" -#include "dce/dce_aux.h" -#include "dce/dce_abm.h" -#include "dce/dce_i2c.h" -/* TODO remove this include */ - -#ifndef mmMC_HUB_RDREQ_DMIF_LIMIT -#include "gmc/gmc_7_1_d.h" -#include "gmc/gmc_7_1_sh_mask.h" -#endif - -#include "dce80/dce80_resource.h" - -#ifndef mmDP_DPHY_INTERNAL_CTRL -#define mmDP_DPHY_INTERNAL_CTRL 0x1CDE -#define mmDP0_DP_DPHY_INTERNAL_CTRL 0x1CDE -#define mmDP1_DP_DPHY_INTERNAL_CTRL 0x1FDE -#define mmDP2_DP_DPHY_INTERNAL_CTRL 0x42DE -#define mmDP3_DP_DPHY_INTERNAL_CTRL 0x45DE -#define mmDP4_DP_DPHY_INTERNAL_CTRL 0x48DE -#define mmDP5_DP_DPHY_INTERNAL_CTRL 0x4BDE -#define mmDP6_DP_DPHY_INTERNAL_CTRL 0x4EDE -#endif - - -#ifndef mmBIOS_SCRATCH_2 - #define mmBIOS_SCRATCH_2 0x05CB - #define mmBIOS_SCRATCH_3 0x05CC - #define mmBIOS_SCRATCH_6 0x05CF -#endif - -#ifndef mmDP_DPHY_FAST_TRAINING - #define mmDP_DPHY_FAST_TRAINING 0x1CCE - #define mmDP0_DP_DPHY_FAST_TRAINING 0x1CCE - #define mmDP1_DP_DPHY_FAST_TRAINING 0x1FCE - #define mmDP2_DP_DPHY_FAST_TRAINING 0x42CE - #define mmDP3_DP_DPHY_FAST_TRAINING 0x45CE - #define mmDP4_DP_DPHY_FAST_TRAINING 0x48CE - #define mmDP5_DP_DPHY_FAST_TRAINING 0x4BCE - #define mmDP6_DP_DPHY_FAST_TRAINING 0x4ECE -#endif - - -#ifndef mmHPD_DC_HPD_CONTROL - #define mmHPD_DC_HPD_CONTROL 0x189A - #define mmHPD0_DC_HPD_CONTROL 0x189A - #define mmHPD1_DC_HPD_CONTROL 0x18A2 - #define mmHPD2_DC_HPD_CONTROL 0x18AA - #define mmHPD3_DC_HPD_CONTROL 0x18B2 - #define mmHPD4_DC_HPD_CONTROL 0x18BA - #define mmHPD5_DC_HPD_CONTROL 0x18C2 -#endif - -#define DCE11_DIG_FE_CNTL 0x4a00 -#define DCE11_DIG_BE_CNTL 0x4a47 -#define DCE11_DP_SEC 0x4ac3 - -static const struct dce110_timing_generator_offsets dce80_tg_offsets[] = { - { - .crtc = (mmCRTC0_CRTC_CONTROL - mmCRTC_CONTROL), - .dcp = (mmGRPH_CONTROL - mmGRPH_CONTROL), - .dmif = (mmDMIF_PG0_DPG_WATERMARK_MASK_CONTROL - - mmDPG_WATERMARK_MASK_CONTROL), - }, - { - .crtc = (mmCRTC1_CRTC_CONTROL - mmCRTC_CONTROL), - .dcp = (mmDCP1_GRPH_CONTROL - mmGRPH_CONTROL), - .dmif = (mmDMIF_PG1_DPG_WATERMARK_MASK_CONTROL - - mmDPG_WATERMARK_MASK_CONTROL), - }, - { - .crtc = (mmCRTC2_CRTC_CONTROL - mmCRTC_CONTROL), - .dcp = (mmDCP2_GRPH_CONTROL - mmGRPH_CONTROL), - .dmif = (mmDMIF_PG2_DPG_WATERMARK_MASK_CONTROL - - mmDPG_WATERMARK_MASK_CONTROL), - }, - { - .crtc = (mmCRTC3_CRTC_CONTROL - mmCRTC_CONTROL), - .dcp = (mmDCP3_GRPH_CONTROL - mmGRPH_CONTROL), - .dmif = (mmDMIF_PG3_DPG_WATERMARK_MASK_CONTROL - - mmDPG_WATERMARK_MASK_CONTROL), - }, - { - .crtc = (mmCRTC4_CRTC_CONTROL - mmCRTC_CONTROL), - .dcp = (mmDCP4_GRPH_CONTROL - mmGRPH_CONTROL), - .dmif = (mmDMIF_PG4_DPG_WATERMARK_MASK_CONTROL - - mmDPG_WATERMARK_MASK_CONTROL), - }, - { - .crtc = (mmCRTC5_CRTC_CONTROL - mmCRTC_CONTROL), - .dcp = (mmDCP5_GRPH_CONTROL - mmGRPH_CONTROL), - .dmif = (mmDMIF_PG5_DPG_WATERMARK_MASK_CONTROL - - mmDPG_WATERMARK_MASK_CONTROL), - } -}; - -/* set register offset */ -#define SR(reg_name)\ - .reg_name = mm ## reg_name - -/* set register offset with instance */ -#define SRI(reg_name, block, id)\ - .reg_name = mm ## block ## id ## _ ## reg_name - -#define ipp_regs(id)\ -[id] = {\ - IPP_COMMON_REG_LIST_DCE_BASE(id)\ -} - -static const struct dce_ipp_registers ipp_regs[] = { - ipp_regs(0), - ipp_regs(1), - ipp_regs(2), - ipp_regs(3), - ipp_regs(4), - ipp_regs(5) -}; - -static const struct dce_ipp_shift ipp_shift = { - IPP_COMMON_MASK_SH_LIST_DCE_COMMON_BASE(__SHIFT) -}; - -static const struct dce_ipp_mask ipp_mask = { - IPP_COMMON_MASK_SH_LIST_DCE_COMMON_BASE(_MASK) -}; - -#define transform_regs(id)\ -[id] = {\ - XFM_COMMON_REG_LIST_DCE80(id)\ -} - -static const struct dce_transform_registers xfm_regs[] = { - transform_regs(0), - transform_regs(1), - transform_regs(2), - transform_regs(3), - transform_regs(4), - transform_regs(5) -}; - -static const struct dce_transform_shift xfm_shift = { - XFM_COMMON_MASK_SH_LIST_DCE80(__SHIFT) -}; - -static const struct dce_transform_mask xfm_mask = { - XFM_COMMON_MASK_SH_LIST_DCE80(_MASK) -}; - -#define aux_regs(id)\ -[id] = {\ - AUX_REG_LIST(id)\ -} - -static const struct dce110_link_enc_aux_registers link_enc_aux_regs[] = { - aux_regs(0), - aux_regs(1), - aux_regs(2), - aux_regs(3), - aux_regs(4), - aux_regs(5) -}; - -#define hpd_regs(id)\ -[id] = {\ - HPD_REG_LIST(id)\ -} - -static const struct dce110_link_enc_hpd_registers link_enc_hpd_regs[] = { - hpd_regs(0), - hpd_regs(1), - hpd_regs(2), - hpd_regs(3), - hpd_regs(4), - hpd_regs(5) -}; - -#define link_regs(id)\ -[id] = {\ - LE_DCE80_REG_LIST(id)\ -} - -static const struct dce110_link_enc_registers link_enc_regs[] = { - link_regs(0), - link_regs(1), - link_regs(2), - link_regs(3), - link_regs(4), - link_regs(5), - link_regs(6), -}; - -#define stream_enc_regs(id)\ -[id] = {\ - SE_COMMON_REG_LIST_DCE_BASE(id),\ - .AFMT_CNTL = 0,\ -} - -static const struct dce110_stream_enc_registers stream_enc_regs[] = { - stream_enc_regs(0), - stream_enc_regs(1), - stream_enc_regs(2), - stream_enc_regs(3), - stream_enc_regs(4), - stream_enc_regs(5), - stream_enc_regs(6) -}; - -static const struct dce_stream_encoder_shift se_shift = { - SE_COMMON_MASK_SH_LIST_DCE80_100(__SHIFT) -}; - -static const struct dce_stream_encoder_mask se_mask = { - SE_COMMON_MASK_SH_LIST_DCE80_100(_MASK) -}; - -static const struct dce_panel_cntl_registers panel_cntl_regs[] = { - { DCE_PANEL_CNTL_REG_LIST() } -}; - -static const struct dce_panel_cntl_shift panel_cntl_shift = { - DCE_PANEL_CNTL_MASK_SH_LIST(__SHIFT) -}; - -static const struct dce_panel_cntl_mask panel_cntl_mask = { - DCE_PANEL_CNTL_MASK_SH_LIST(_MASK) -}; - -#define opp_regs(id)\ -[id] = {\ - OPP_DCE_80_REG_LIST(id),\ -} - -static const struct dce_opp_registers opp_regs[] = { - opp_regs(0), - opp_regs(1), - opp_regs(2), - opp_regs(3), - opp_regs(4), - opp_regs(5) -}; - -static const struct dce_opp_shift opp_shift = { - OPP_COMMON_MASK_SH_LIST_DCE_80(__SHIFT) -}; - -static const struct dce_opp_mask opp_mask = { - OPP_COMMON_MASK_SH_LIST_DCE_80(_MASK) -}; - -static const struct dce110_aux_registers_shift aux_shift = { - DCE10_AUX_MASK_SH_LIST(__SHIFT) -}; - -static const struct dce110_aux_registers_mask aux_mask = { - DCE10_AUX_MASK_SH_LIST(_MASK) -}; - -#define aux_engine_regs(id)\ -[id] = {\ - AUX_COMMON_REG_LIST(id), \ - .AUX_RESET_MASK = 0 \ -} - -static const struct dce110_aux_registers aux_engine_regs[] = { - aux_engine_regs(0), - aux_engine_regs(1), - aux_engine_regs(2), - aux_engine_regs(3), - aux_engine_regs(4), - aux_engine_regs(5) -}; - -#define audio_regs(id)\ -[id] = {\ - AUD_COMMON_REG_LIST(id)\ -} - -static const struct dce_audio_registers audio_regs[] = { - audio_regs(0), - audio_regs(1), - audio_regs(2), - audio_regs(3), - audio_regs(4), - audio_regs(5), - audio_regs(6), -}; - -static const struct dce_audio_shift audio_shift = { - AUD_COMMON_MASK_SH_LIST(__SHIFT) -}; - -static const struct dce_audio_mask audio_mask = { - AUD_COMMON_MASK_SH_LIST(_MASK) -}; - -#define clk_src_regs(id)\ -[id] = {\ - CS_COMMON_REG_LIST_DCE_80(id),\ -} - - -static const struct dce110_clk_src_regs clk_src_regs[] = { - clk_src_regs(0), - clk_src_regs(1), - clk_src_regs(2) -}; - -static const struct dce110_clk_src_shift cs_shift = { - CS_COMMON_MASK_SH_LIST_DCE_COMMON_BASE(__SHIFT) -}; - -static const struct dce110_clk_src_mask cs_mask = { - CS_COMMON_MASK_SH_LIST_DCE_COMMON_BASE(_MASK) -}; - -static const struct bios_registers bios_regs = { - .BIOS_SCRATCH_3 = mmBIOS_SCRATCH_3, - .BIOS_SCRATCH_6 = mmBIOS_SCRATCH_6 -}; - -static const struct resource_caps res_cap = { - .num_timing_generator = 6, - .num_audio = 6, - .num_stream_encoder = 6, - .num_pll = 3, - .num_ddc = 6, -}; - -static const struct resource_caps res_cap_81 = { - .num_timing_generator = 4, - .num_audio = 7, - .num_stream_encoder = 7, - .num_pll = 3, - .num_ddc = 6, -}; - -static const struct resource_caps res_cap_83 = { - .num_timing_generator = 2, - .num_audio = 6, - .num_stream_encoder = 6, - .num_pll = 2, - .num_ddc = 2, -}; - -static const struct dc_plane_cap plane_cap = { - .type = DC_PLANE_TYPE_DCE_RGB, - - .pixel_format_support = { - .argb8888 = true, - .nv12 = false, - .fp16 = true - }, - - .max_upscale_factor = { - .argb8888 = 16000, - .nv12 = 1, - .fp16 = 1 - }, - - .max_downscale_factor = { - .argb8888 = 250, - .nv12 = 1, - .fp16 = 1 - } -}; - -static const struct dc_debug_options debug_defaults = { - .enable_legacy_fast_update = true, -}; - -static const struct dce_dmcu_registers dmcu_regs = { - DMCU_DCE80_REG_LIST() -}; - -static const struct dce_dmcu_shift dmcu_shift = { - DMCU_MASK_SH_LIST_DCE80(__SHIFT) -}; - -static const struct dce_dmcu_mask dmcu_mask = { - DMCU_MASK_SH_LIST_DCE80(_MASK) -}; -static const struct dce_abm_registers abm_regs = { - ABM_DCE110_COMMON_REG_LIST() -}; - -static const struct dce_abm_shift abm_shift = { - ABM_MASK_SH_LIST_DCE110(__SHIFT) -}; - -static const struct dce_abm_mask abm_mask = { - ABM_MASK_SH_LIST_DCE110(_MASK) -}; - -#define CTX ctx -#define REG(reg) mm ## reg - -#ifndef mmCC_DC_HDMI_STRAPS -#define mmCC_DC_HDMI_STRAPS 0x1918 -#define CC_DC_HDMI_STRAPS__HDMI_DISABLE_MASK 0x40 -#define CC_DC_HDMI_STRAPS__HDMI_DISABLE__SHIFT 0x6 -#define CC_DC_HDMI_STRAPS__AUDIO_STREAM_NUMBER_MASK 0x700 -#define CC_DC_HDMI_STRAPS__AUDIO_STREAM_NUMBER__SHIFT 0x8 -#endif - -static int map_transmitter_id_to_phy_instance( - enum transmitter transmitter) -{ - switch (transmitter) { - case TRANSMITTER_UNIPHY_A: - return 0; - case TRANSMITTER_UNIPHY_B: - return 1; - case TRANSMITTER_UNIPHY_C: - return 2; - case TRANSMITTER_UNIPHY_D: - return 3; - case TRANSMITTER_UNIPHY_E: - return 4; - case TRANSMITTER_UNIPHY_F: - return 5; - case TRANSMITTER_UNIPHY_G: - return 6; - default: - ASSERT(0); - return 0; - } -} - -static void read_dce_straps( - struct dc_context *ctx, - struct resource_straps *straps) -{ - REG_GET_2(CC_DC_HDMI_STRAPS, - HDMI_DISABLE, &straps->hdmi_disable, - AUDIO_STREAM_NUMBER, &straps->audio_stream_number); - - REG_GET(DC_PINSTRAPS, DC_PINSTRAPS_AUDIO, &straps->dc_pinstraps_audio); -} - -static struct audio *create_audio( - struct dc_context *ctx, unsigned int inst) -{ - return dce_audio_create(ctx, inst, - &audio_regs[inst], &audio_shift, &audio_mask); -} - -static struct timing_generator *dce80_timing_generator_create( - struct dc_context *ctx, - uint32_t instance, - const struct dce110_timing_generator_offsets *offsets) -{ - struct dce110_timing_generator *tg110 = - kzalloc(sizeof(struct dce110_timing_generator), GFP_KERNEL); - - if (!tg110) - return NULL; - - dce80_timing_generator_construct(tg110, ctx, instance, offsets); - return &tg110->base; -} - -static struct output_pixel_processor *dce80_opp_create( - struct dc_context *ctx, - uint32_t inst) -{ - struct dce110_opp *opp = - kzalloc(sizeof(struct dce110_opp), GFP_KERNEL); - - if (!opp) - return NULL; - - dce110_opp_construct(opp, - ctx, inst, &opp_regs[inst], &opp_shift, &opp_mask); - return &opp->base; -} - -static struct dce_aux *dce80_aux_engine_create( - struct dc_context *ctx, - uint32_t inst) -{ - struct aux_engine_dce110 *aux_engine = - kzalloc(sizeof(struct aux_engine_dce110), GFP_KERNEL); - - if (!aux_engine) - return NULL; - - dce110_aux_engine_construct(aux_engine, ctx, inst, - SW_AUX_TIMEOUT_PERIOD_MULTIPLIER * AUX_TIMEOUT_PERIOD, - &aux_engine_regs[inst], - &aux_mask, - &aux_shift, - ctx->dc->caps.extended_aux_timeout_support); - - return &aux_engine->base; -} -#define i2c_inst_regs(id) { I2C_HW_ENGINE_COMMON_REG_LIST(id) } - -static const struct dce_i2c_registers i2c_hw_regs[] = { - i2c_inst_regs(1), - i2c_inst_regs(2), - i2c_inst_regs(3), - i2c_inst_regs(4), - i2c_inst_regs(5), - i2c_inst_regs(6), -}; - -static const struct dce_i2c_shift i2c_shifts = { - I2C_COMMON_MASK_SH_LIST_DCE_COMMON_BASE(__SHIFT) -}; - -static const struct dce_i2c_mask i2c_masks = { - I2C_COMMON_MASK_SH_LIST_DCE_COMMON_BASE(_MASK) -}; - -static struct dce_i2c_hw *dce80_i2c_hw_create( - struct dc_context *ctx, - uint32_t inst) -{ - struct dce_i2c_hw *dce_i2c_hw = - kzalloc(sizeof(struct dce_i2c_hw), GFP_KERNEL); - - if (!dce_i2c_hw) - return NULL; - - dce_i2c_hw_construct(dce_i2c_hw, ctx, inst, - &i2c_hw_regs[inst], &i2c_shifts, &i2c_masks); - - return dce_i2c_hw; -} - -static struct dce_i2c_sw *dce80_i2c_sw_create( - struct dc_context *ctx) -{ - struct dce_i2c_sw *dce_i2c_sw = - kzalloc(sizeof(struct dce_i2c_sw), GFP_KERNEL); - - if (!dce_i2c_sw) - return NULL; - - dce_i2c_sw_construct(dce_i2c_sw, ctx); - - return dce_i2c_sw; -} -static struct stream_encoder *dce80_stream_encoder_create( - enum engine_id eng_id, - struct dc_context *ctx) -{ - struct dce110_stream_encoder *enc110 = - kzalloc(sizeof(struct dce110_stream_encoder), GFP_KERNEL); - - if (!enc110) - return NULL; - - dce110_stream_encoder_construct(enc110, ctx, ctx->dc_bios, eng_id, - &stream_enc_regs[eng_id], - &se_shift, &se_mask); - return &enc110->base; -} - -#define SRII(reg_name, block, id)\ - .reg_name[id] = mm ## block ## id ## _ ## reg_name - -static const struct dce_hwseq_registers hwseq_reg = { - HWSEQ_DCE8_REG_LIST() -}; - -static const struct dce_hwseq_shift hwseq_shift = { - HWSEQ_DCE8_MASK_SH_LIST(__SHIFT) -}; - -static const struct dce_hwseq_mask hwseq_mask = { - HWSEQ_DCE8_MASK_SH_LIST(_MASK) -}; - -static struct dce_hwseq *dce80_hwseq_create( - struct dc_context *ctx) -{ - struct dce_hwseq *hws = kzalloc(sizeof(struct dce_hwseq), GFP_KERNEL); - - if (hws) { - hws->ctx = ctx; - hws->regs = &hwseq_reg; - hws->shifts = &hwseq_shift; - hws->masks = &hwseq_mask; - } - return hws; -} - -static const struct resource_create_funcs res_create_funcs = { - .read_dce_straps = read_dce_straps, - .create_audio = create_audio, - .create_stream_encoder = dce80_stream_encoder_create, - .create_hwseq = dce80_hwseq_create, -}; - -#define mi_inst_regs(id) { \ - MI_DCE8_REG_LIST(id), \ - .MC_HUB_RDREQ_DMIF_LIMIT = mmMC_HUB_RDREQ_DMIF_LIMIT \ -} -static const struct dce_mem_input_registers mi_regs[] = { - mi_inst_regs(0), - mi_inst_regs(1), - mi_inst_regs(2), - mi_inst_regs(3), - mi_inst_regs(4), - mi_inst_regs(5), -}; - -static const struct dce_mem_input_shift mi_shifts = { - MI_DCE8_MASK_SH_LIST(__SHIFT), - .ENABLE = MC_HUB_RDREQ_DMIF_LIMIT__ENABLE__SHIFT -}; - -static const struct dce_mem_input_mask mi_masks = { - MI_DCE8_MASK_SH_LIST(_MASK), - .ENABLE = MC_HUB_RDREQ_DMIF_LIMIT__ENABLE_MASK -}; - -static struct mem_input *dce80_mem_input_create( - struct dc_context *ctx, - uint32_t inst) -{ - struct dce_mem_input *dce_mi = kzalloc(sizeof(struct dce_mem_input), - GFP_KERNEL); - - if (!dce_mi) { - BREAK_TO_DEBUGGER(); - return NULL; - } - - dce_mem_input_construct(dce_mi, ctx, inst, &mi_regs[inst], &mi_shifts, &mi_masks); - dce_mi->wa.single_head_rdreq_dmif_limit = 2; - return &dce_mi->base; -} - -static void dce80_transform_destroy(struct transform **xfm) -{ - kfree(TO_DCE_TRANSFORM(*xfm)); - *xfm = NULL; -} - -static struct transform *dce80_transform_create( - struct dc_context *ctx, - uint32_t inst) -{ - struct dce_transform *transform = - kzalloc(sizeof(struct dce_transform), GFP_KERNEL); - - if (!transform) - return NULL; - - dce_transform_construct(transform, ctx, inst, - &xfm_regs[inst], &xfm_shift, &xfm_mask); - transform->prescaler_on = false; - return &transform->base; -} - -static const struct encoder_feature_support link_enc_feature = { - .max_hdmi_deep_color = COLOR_DEPTH_121212, - .max_hdmi_pixel_clock = 297000, - .flags.bits.IS_HBR2_CAPABLE = true, - .flags.bits.IS_TPS3_CAPABLE = true -}; - -static struct link_encoder *dce80_link_encoder_create( - struct dc_context *ctx, - const struct encoder_init_data *enc_init_data) -{ - struct dce110_link_encoder *enc110 = - kzalloc(sizeof(struct dce110_link_encoder), GFP_KERNEL); - int link_regs_id; - - if (!enc110) - return NULL; - - link_regs_id = - map_transmitter_id_to_phy_instance(enc_init_data->transmitter); - - dce110_link_encoder_construct(enc110, - enc_init_data, - &link_enc_feature, - &link_enc_regs[link_regs_id], - &link_enc_aux_regs[enc_init_data->channel - 1], - &link_enc_hpd_regs[enc_init_data->hpd_source]); - return &enc110->base; -} - -static struct panel_cntl *dce80_panel_cntl_create(const struct panel_cntl_init_data *init_data) -{ - struct dce_panel_cntl *panel_cntl = - kzalloc(sizeof(struct dce_panel_cntl), GFP_KERNEL); - - if (!panel_cntl) - return NULL; - - dce_panel_cntl_construct(panel_cntl, - init_data, - &panel_cntl_regs[init_data->inst], - &panel_cntl_shift, - &panel_cntl_mask); - - return &panel_cntl->base; -} - -static struct clock_source *dce80_clock_source_create( - struct dc_context *ctx, - struct dc_bios *bios, - enum clock_source_id id, - const struct dce110_clk_src_regs *regs, - bool dp_clk_src) -{ - struct dce110_clk_src *clk_src = - kzalloc(sizeof(struct dce110_clk_src), GFP_KERNEL); - - if (!clk_src) - return NULL; - - if (dce110_clk_src_construct(clk_src, ctx, bios, id, - regs, &cs_shift, &cs_mask)) { - clk_src->base.dp_clk_src = dp_clk_src; - return &clk_src->base; - } - - kfree(clk_src); - BREAK_TO_DEBUGGER(); - return NULL; -} - -static void dce80_clock_source_destroy(struct clock_source **clk_src) -{ - kfree(TO_DCE110_CLK_SRC(*clk_src)); - *clk_src = NULL; -} - -static struct input_pixel_processor *dce80_ipp_create( - struct dc_context *ctx, uint32_t inst) -{ - struct dce_ipp *ipp = kzalloc(sizeof(struct dce_ipp), GFP_KERNEL); - - if (!ipp) { - BREAK_TO_DEBUGGER(); - return NULL; - } - - dce_ipp_construct(ipp, ctx, inst, - &ipp_regs[inst], &ipp_shift, &ipp_mask); - return &ipp->base; -} - -static void dce80_resource_destruct(struct dce110_resource_pool *pool) -{ - unsigned int i; - - for (i = 0; i < pool->base.pipe_count; i++) { - if (pool->base.opps[i] != NULL) - dce110_opp_destroy(&pool->base.opps[i]); - - if (pool->base.transforms[i] != NULL) - dce80_transform_destroy(&pool->base.transforms[i]); - - if (pool->base.ipps[i] != NULL) - dce_ipp_destroy(&pool->base.ipps[i]); - - if (pool->base.mis[i] != NULL) { - kfree(TO_DCE_MEM_INPUT(pool->base.mis[i])); - pool->base.mis[i] = NULL; - } - - if (pool->base.timing_generators[i] != NULL) { - kfree(DCE110TG_FROM_TG(pool->base.timing_generators[i])); - pool->base.timing_generators[i] = NULL; - } - } - - for (i = 0; i < pool->base.res_cap->num_ddc; i++) { - if (pool->base.engines[i] != NULL) - dce110_engine_destroy(&pool->base.engines[i]); - if (pool->base.hw_i2cs[i] != NULL) { - kfree(pool->base.hw_i2cs[i]); - pool->base.hw_i2cs[i] = NULL; - } - if (pool->base.sw_i2cs[i] != NULL) { - kfree(pool->base.sw_i2cs[i]); - pool->base.sw_i2cs[i] = NULL; - } - } - - for (i = 0; i < pool->base.stream_enc_count; i++) { - if (pool->base.stream_enc[i] != NULL) - kfree(DCE110STRENC_FROM_STRENC(pool->base.stream_enc[i])); - } - - for (i = 0; i < pool->base.clk_src_count; i++) { - if (pool->base.clock_sources[i] != NULL) { - dce80_clock_source_destroy(&pool->base.clock_sources[i]); - } - } - - if (pool->base.abm != NULL) - dce_abm_destroy(&pool->base.abm); - - if (pool->base.dmcu != NULL) - dce_dmcu_destroy(&pool->base.dmcu); - - if (pool->base.dp_clock_source != NULL) - dce80_clock_source_destroy(&pool->base.dp_clock_source); - - for (i = 0; i < pool->base.audio_count; i++) { - if (pool->base.audios[i] != NULL) { - dce_aud_destroy(&pool->base.audios[i]); - } - } - - if (pool->base.irqs != NULL) { - dal_irq_service_destroy(&pool->base.irqs); - } -} - -static bool dce80_validate_bandwidth( - struct dc *dc, - struct dc_state *context, - bool fast_validate) -{ - int i; - bool at_least_one_pipe = false; - - for (i = 0; i < dc->res_pool->pipe_count; i++) { - if (context->res_ctx.pipe_ctx[i].stream) - at_least_one_pipe = true; - } - - if (at_least_one_pipe) { - /* TODO implement when needed but for now hardcode max value*/ - context->bw_ctx.bw.dce.dispclk_khz = 681000; - context->bw_ctx.bw.dce.yclk_khz = 250000 * MEMORY_TYPE_MULTIPLIER_CZ; - } else { - context->bw_ctx.bw.dce.dispclk_khz = 0; - context->bw_ctx.bw.dce.yclk_khz = 0; - } - - return true; -} - -static bool dce80_validate_surface_sets( - struct dc_state *context) -{ - int i; - - for (i = 0; i < context->stream_count; i++) { - if (context->stream_status[i].plane_count == 0) - continue; - - if (context->stream_status[i].plane_count > 1) - return false; - - if (context->stream_status[i].plane_states[0]->format - >= SURFACE_PIXEL_FORMAT_VIDEO_BEGIN) - return false; - } - - return true; -} - -static enum dc_status dce80_validate_global( - struct dc *dc, - struct dc_state *context) -{ - if (!dce80_validate_surface_sets(context)) - return DC_FAIL_SURFACE_VALIDATE; - - return DC_OK; -} - -static void dce80_destroy_resource_pool(struct resource_pool **pool) -{ - struct dce110_resource_pool *dce110_pool = TO_DCE110_RES_POOL(*pool); - - dce80_resource_destruct(dce110_pool); - kfree(dce110_pool); - *pool = NULL; -} - -static const struct resource_funcs dce80_res_pool_funcs = { - .destroy = dce80_destroy_resource_pool, - .link_enc_create = dce80_link_encoder_create, - .panel_cntl_create = dce80_panel_cntl_create, - .validate_bandwidth = dce80_validate_bandwidth, - .validate_plane = dce100_validate_plane, - .add_stream_to_ctx = dce100_add_stream_to_ctx, - .validate_global = dce80_validate_global, - .find_first_free_match_stream_enc_for_link = dce100_find_first_free_match_stream_enc_for_link -}; - -static bool dce80_construct( - uint8_t num_virtual_links, - struct dc *dc, - struct dce110_resource_pool *pool) -{ - unsigned int i; - struct dc_context *ctx = dc->ctx; - struct dc_bios *bp; - - ctx->dc_bios->regs = &bios_regs; - - pool->base.res_cap = &res_cap; - pool->base.funcs = &dce80_res_pool_funcs; - - - /************************************************* - * Resource + asic cap harcoding * - *************************************************/ - pool->base.underlay_pipe_index = NO_UNDERLAY_PIPE; - pool->base.pipe_count = res_cap.num_timing_generator; - pool->base.timing_generator_count = res_cap.num_timing_generator; - dc->caps.max_downscale_ratio = 200; - dc->caps.i2c_speed_in_khz = 40; - dc->caps.i2c_speed_in_khz_hdcp = 40; - dc->caps.max_cursor_size = 128; - dc->caps.min_horizontal_blanking_period = 80; - dc->caps.dual_link_dvi = true; - dc->caps.extended_aux_timeout_support = false; - dc->debug = debug_defaults; - - /************************************************* - * Create resources * - *************************************************/ - - bp = ctx->dc_bios; - - if (bp->fw_info_valid && bp->fw_info.external_clock_source_frequency_for_dp != 0) { - pool->base.dp_clock_source = - dce80_clock_source_create(ctx, bp, CLOCK_SOURCE_ID_EXTERNAL, NULL, true); - - pool->base.clock_sources[0] = - dce80_clock_source_create(ctx, bp, CLOCK_SOURCE_ID_PLL0, &clk_src_regs[0], false); - pool->base.clock_sources[1] = - dce80_clock_source_create(ctx, bp, CLOCK_SOURCE_ID_PLL1, &clk_src_regs[1], false); - pool->base.clock_sources[2] = - dce80_clock_source_create(ctx, bp, CLOCK_SOURCE_ID_PLL2, &clk_src_regs[2], false); - pool->base.clk_src_count = 3; - - } else { - pool->base.dp_clock_source = - dce80_clock_source_create(ctx, bp, CLOCK_SOURCE_ID_PLL0, &clk_src_regs[0], true); - - pool->base.clock_sources[0] = - dce80_clock_source_create(ctx, bp, CLOCK_SOURCE_ID_PLL1, &clk_src_regs[1], false); - pool->base.clock_sources[1] = - dce80_clock_source_create(ctx, bp, CLOCK_SOURCE_ID_PLL2, &clk_src_regs[2], false); - pool->base.clk_src_count = 2; - } - - if (pool->base.dp_clock_source == NULL) { - dm_error("DC: failed to create dp clock source!\n"); - BREAK_TO_DEBUGGER(); - goto res_create_fail; - } - - for (i = 0; i < pool->base.clk_src_count; i++) { - if (pool->base.clock_sources[i] == NULL) { - dm_error("DC: failed to create clock sources!\n"); - BREAK_TO_DEBUGGER(); - goto res_create_fail; - } - } - - pool->base.dmcu = dce_dmcu_create(ctx, - &dmcu_regs, - &dmcu_shift, - &dmcu_mask); - if (pool->base.dmcu == NULL) { - dm_error("DC: failed to create dmcu!\n"); - BREAK_TO_DEBUGGER(); - goto res_create_fail; - } - - pool->base.abm = dce_abm_create(ctx, - &abm_regs, - &abm_shift, - &abm_mask); - if (pool->base.abm == NULL) { - dm_error("DC: failed to create abm!\n"); - BREAK_TO_DEBUGGER(); - goto res_create_fail; - } - - { - struct irq_service_init_data init_data; - init_data.ctx = dc->ctx; - pool->base.irqs = dal_irq_service_dce80_create(&init_data); - if (!pool->base.irqs) - goto res_create_fail; - } - - for (i = 0; i < pool->base.pipe_count; i++) { - pool->base.timing_generators[i] = dce80_timing_generator_create( - ctx, i, &dce80_tg_offsets[i]); - if (pool->base.timing_generators[i] == NULL) { - BREAK_TO_DEBUGGER(); - dm_error("DC: failed to create tg!\n"); - goto res_create_fail; - } - - pool->base.mis[i] = dce80_mem_input_create(ctx, i); - if (pool->base.mis[i] == NULL) { - BREAK_TO_DEBUGGER(); - dm_error("DC: failed to create memory input!\n"); - goto res_create_fail; - } - - pool->base.ipps[i] = dce80_ipp_create(ctx, i); - if (pool->base.ipps[i] == NULL) { - BREAK_TO_DEBUGGER(); - dm_error("DC: failed to create input pixel processor!\n"); - goto res_create_fail; - } - - pool->base.transforms[i] = dce80_transform_create(ctx, i); - if (pool->base.transforms[i] == NULL) { - BREAK_TO_DEBUGGER(); - dm_error("DC: failed to create transform!\n"); - goto res_create_fail; - } - - pool->base.opps[i] = dce80_opp_create(ctx, i); - if (pool->base.opps[i] == NULL) { - BREAK_TO_DEBUGGER(); - dm_error("DC: failed to create output pixel processor!\n"); - goto res_create_fail; - } - } - - for (i = 0; i < pool->base.res_cap->num_ddc; i++) { - pool->base.engines[i] = dce80_aux_engine_create(ctx, i); - if (pool->base.engines[i] == NULL) { - BREAK_TO_DEBUGGER(); - dm_error( - "DC:failed to create aux engine!!\n"); - goto res_create_fail; - } - pool->base.hw_i2cs[i] = dce80_i2c_hw_create(ctx, i); - if (pool->base.hw_i2cs[i] == NULL) { - BREAK_TO_DEBUGGER(); - dm_error( - "DC:failed to create i2c engine!!\n"); - goto res_create_fail; - } - pool->base.sw_i2cs[i] = dce80_i2c_sw_create(ctx); - if (pool->base.sw_i2cs[i] == NULL) { - BREAK_TO_DEBUGGER(); - dm_error( - "DC:failed to create sw i2c!!\n"); - goto res_create_fail; - } - } - - dc->caps.max_planes = pool->base.pipe_count; - - for (i = 0; i < dc->caps.max_planes; ++i) - dc->caps.planes[i] = plane_cap; - - dc->caps.disable_dp_clk_share = true; - - if (!resource_construct(num_virtual_links, dc, &pool->base, - &res_create_funcs)) - goto res_create_fail; - - /* Create hardware sequencer */ - dce80_hw_sequencer_construct(dc); - - return true; - -res_create_fail: - dce80_resource_destruct(pool); - return false; -} - -struct resource_pool *dce80_create_resource_pool( - uint8_t num_virtual_links, - struct dc *dc) -{ - struct dce110_resource_pool *pool = - kzalloc(sizeof(struct dce110_resource_pool), GFP_KERNEL); - - if (!pool) - return NULL; - - if (dce80_construct(num_virtual_links, dc, pool)) - return &pool->base; - - kfree(pool); - BREAK_TO_DEBUGGER(); - return NULL; -} - -static bool dce81_construct( - uint8_t num_virtual_links, - struct dc *dc, - struct dce110_resource_pool *pool) -{ - unsigned int i; - struct dc_context *ctx = dc->ctx; - struct dc_bios *bp; - - ctx->dc_bios->regs = &bios_regs; - - pool->base.res_cap = &res_cap_81; - pool->base.funcs = &dce80_res_pool_funcs; - - - /************************************************* - * Resource + asic cap harcoding * - *************************************************/ - pool->base.underlay_pipe_index = NO_UNDERLAY_PIPE; - pool->base.pipe_count = res_cap_81.num_timing_generator; - pool->base.timing_generator_count = res_cap_81.num_timing_generator; - dc->caps.max_downscale_ratio = 200; - dc->caps.i2c_speed_in_khz = 40; - dc->caps.i2c_speed_in_khz_hdcp = 40; - dc->caps.max_cursor_size = 128; - dc->caps.min_horizontal_blanking_period = 80; - dc->caps.is_apu = true; - - /************************************************* - * Create resources * - *************************************************/ - - bp = ctx->dc_bios; - - if (bp->fw_info_valid && bp->fw_info.external_clock_source_frequency_for_dp != 0) { - pool->base.dp_clock_source = - dce80_clock_source_create(ctx, bp, CLOCK_SOURCE_ID_EXTERNAL, NULL, true); - - pool->base.clock_sources[0] = - dce80_clock_source_create(ctx, bp, CLOCK_SOURCE_ID_PLL0, &clk_src_regs[0], false); - pool->base.clock_sources[1] = - dce80_clock_source_create(ctx, bp, CLOCK_SOURCE_ID_PLL1, &clk_src_regs[1], false); - pool->base.clock_sources[2] = - dce80_clock_source_create(ctx, bp, CLOCK_SOURCE_ID_PLL2, &clk_src_regs[2], false); - pool->base.clk_src_count = 3; - - } else { - pool->base.dp_clock_source = - dce80_clock_source_create(ctx, bp, CLOCK_SOURCE_ID_PLL0, &clk_src_regs[0], true); - - pool->base.clock_sources[0] = - dce80_clock_source_create(ctx, bp, CLOCK_SOURCE_ID_PLL1, &clk_src_regs[1], false); - pool->base.clock_sources[1] = - dce80_clock_source_create(ctx, bp, CLOCK_SOURCE_ID_PLL2, &clk_src_regs[2], false); - pool->base.clk_src_count = 2; - } - - if (pool->base.dp_clock_source == NULL) { - dm_error("DC: failed to create dp clock source!\n"); - BREAK_TO_DEBUGGER(); - goto res_create_fail; - } - - for (i = 0; i < pool->base.clk_src_count; i++) { - if (pool->base.clock_sources[i] == NULL) { - dm_error("DC: failed to create clock sources!\n"); - BREAK_TO_DEBUGGER(); - goto res_create_fail; - } - } - - pool->base.dmcu = dce_dmcu_create(ctx, - &dmcu_regs, - &dmcu_shift, - &dmcu_mask); - if (pool->base.dmcu == NULL) { - dm_error("DC: failed to create dmcu!\n"); - BREAK_TO_DEBUGGER(); - goto res_create_fail; - } - - pool->base.abm = dce_abm_create(ctx, - &abm_regs, - &abm_shift, - &abm_mask); - if (pool->base.abm == NULL) { - dm_error("DC: failed to create abm!\n"); - BREAK_TO_DEBUGGER(); - goto res_create_fail; - } - - { - struct irq_service_init_data init_data; - init_data.ctx = dc->ctx; - pool->base.irqs = dal_irq_service_dce80_create(&init_data); - if (!pool->base.irqs) - goto res_create_fail; - } - - for (i = 0; i < pool->base.pipe_count; i++) { - pool->base.timing_generators[i] = dce80_timing_generator_create( - ctx, i, &dce80_tg_offsets[i]); - if (pool->base.timing_generators[i] == NULL) { - BREAK_TO_DEBUGGER(); - dm_error("DC: failed to create tg!\n"); - goto res_create_fail; - } - - pool->base.mis[i] = dce80_mem_input_create(ctx, i); - if (pool->base.mis[i] == NULL) { - BREAK_TO_DEBUGGER(); - dm_error("DC: failed to create memory input!\n"); - goto res_create_fail; - } - - pool->base.ipps[i] = dce80_ipp_create(ctx, i); - if (pool->base.ipps[i] == NULL) { - BREAK_TO_DEBUGGER(); - dm_error("DC: failed to create input pixel processor!\n"); - goto res_create_fail; - } - - pool->base.transforms[i] = dce80_transform_create(ctx, i); - if (pool->base.transforms[i] == NULL) { - BREAK_TO_DEBUGGER(); - dm_error("DC: failed to create transform!\n"); - goto res_create_fail; - } - - pool->base.opps[i] = dce80_opp_create(ctx, i); - if (pool->base.opps[i] == NULL) { - BREAK_TO_DEBUGGER(); - dm_error("DC: failed to create output pixel processor!\n"); - goto res_create_fail; - } - } - - for (i = 0; i < pool->base.res_cap->num_ddc; i++) { - pool->base.engines[i] = dce80_aux_engine_create(ctx, i); - if (pool->base.engines[i] == NULL) { - BREAK_TO_DEBUGGER(); - dm_error( - "DC:failed to create aux engine!!\n"); - goto res_create_fail; - } - pool->base.hw_i2cs[i] = dce80_i2c_hw_create(ctx, i); - if (pool->base.hw_i2cs[i] == NULL) { - BREAK_TO_DEBUGGER(); - dm_error( - "DC:failed to create i2c engine!!\n"); - goto res_create_fail; - } - pool->base.sw_i2cs[i] = dce80_i2c_sw_create(ctx); - if (pool->base.sw_i2cs[i] == NULL) { - BREAK_TO_DEBUGGER(); - dm_error( - "DC:failed to create sw i2c!!\n"); - goto res_create_fail; - } - } - - dc->caps.max_planes = pool->base.pipe_count; - - for (i = 0; i < dc->caps.max_planes; ++i) - dc->caps.planes[i] = plane_cap; - - dc->caps.disable_dp_clk_share = true; - - if (!resource_construct(num_virtual_links, dc, &pool->base, - &res_create_funcs)) - goto res_create_fail; - - /* Create hardware sequencer */ - dce80_hw_sequencer_construct(dc); - - return true; - -res_create_fail: - dce80_resource_destruct(pool); - return false; -} - -struct resource_pool *dce81_create_resource_pool( - uint8_t num_virtual_links, - struct dc *dc) -{ - struct dce110_resource_pool *pool = - kzalloc(sizeof(struct dce110_resource_pool), GFP_KERNEL); - - if (!pool) - return NULL; - - if (dce81_construct(num_virtual_links, dc, pool)) - return &pool->base; - - kfree(pool); - BREAK_TO_DEBUGGER(); - return NULL; -} - -static bool dce83_construct( - uint8_t num_virtual_links, - struct dc *dc, - struct dce110_resource_pool *pool) -{ - unsigned int i; - struct dc_context *ctx = dc->ctx; - struct dc_bios *bp; - - ctx->dc_bios->regs = &bios_regs; - - pool->base.res_cap = &res_cap_83; - pool->base.funcs = &dce80_res_pool_funcs; - - - /************************************************* - * Resource + asic cap harcoding * - *************************************************/ - pool->base.underlay_pipe_index = NO_UNDERLAY_PIPE; - pool->base.pipe_count = res_cap_83.num_timing_generator; - pool->base.timing_generator_count = res_cap_83.num_timing_generator; - dc->caps.max_downscale_ratio = 200; - dc->caps.i2c_speed_in_khz = 40; - dc->caps.i2c_speed_in_khz_hdcp = 40; - dc->caps.max_cursor_size = 128; - dc->caps.min_horizontal_blanking_period = 80; - dc->caps.is_apu = true; - dc->debug = debug_defaults; - - /************************************************* - * Create resources * - *************************************************/ - - bp = ctx->dc_bios; - - if (bp->fw_info_valid && bp->fw_info.external_clock_source_frequency_for_dp != 0) { - pool->base.dp_clock_source = - dce80_clock_source_create(ctx, bp, CLOCK_SOURCE_ID_EXTERNAL, NULL, true); - - pool->base.clock_sources[0] = - dce80_clock_source_create(ctx, bp, CLOCK_SOURCE_ID_PLL1, &clk_src_regs[0], false); - pool->base.clock_sources[1] = - dce80_clock_source_create(ctx, bp, CLOCK_SOURCE_ID_PLL2, &clk_src_regs[1], false); - pool->base.clk_src_count = 2; - - } else { - pool->base.dp_clock_source = - dce80_clock_source_create(ctx, bp, CLOCK_SOURCE_ID_PLL1, &clk_src_regs[0], true); - - pool->base.clock_sources[0] = - dce80_clock_source_create(ctx, bp, CLOCK_SOURCE_ID_PLL2, &clk_src_regs[1], false); - pool->base.clk_src_count = 1; - } - - if (pool->base.dp_clock_source == NULL) { - dm_error("DC: failed to create dp clock source!\n"); - BREAK_TO_DEBUGGER(); - goto res_create_fail; - } - - for (i = 0; i < pool->base.clk_src_count; i++) { - if (pool->base.clock_sources[i] == NULL) { - dm_error("DC: failed to create clock sources!\n"); - BREAK_TO_DEBUGGER(); - goto res_create_fail; - } - } - - pool->base.dmcu = dce_dmcu_create(ctx, - &dmcu_regs, - &dmcu_shift, - &dmcu_mask); - if (pool->base.dmcu == NULL) { - dm_error("DC: failed to create dmcu!\n"); - BREAK_TO_DEBUGGER(); - goto res_create_fail; - } - - pool->base.abm = dce_abm_create(ctx, - &abm_regs, - &abm_shift, - &abm_mask); - if (pool->base.abm == NULL) { - dm_error("DC: failed to create abm!\n"); - BREAK_TO_DEBUGGER(); - goto res_create_fail; - } - - { - struct irq_service_init_data init_data; - init_data.ctx = dc->ctx; - pool->base.irqs = dal_irq_service_dce80_create(&init_data); - if (!pool->base.irqs) - goto res_create_fail; - } - - for (i = 0; i < pool->base.pipe_count; i++) { - pool->base.timing_generators[i] = dce80_timing_generator_create( - ctx, i, &dce80_tg_offsets[i]); - if (pool->base.timing_generators[i] == NULL) { - BREAK_TO_DEBUGGER(); - dm_error("DC: failed to create tg!\n"); - goto res_create_fail; - } - - pool->base.mis[i] = dce80_mem_input_create(ctx, i); - if (pool->base.mis[i] == NULL) { - BREAK_TO_DEBUGGER(); - dm_error("DC: failed to create memory input!\n"); - goto res_create_fail; - } - - pool->base.ipps[i] = dce80_ipp_create(ctx, i); - if (pool->base.ipps[i] == NULL) { - BREAK_TO_DEBUGGER(); - dm_error("DC: failed to create input pixel processor!\n"); - goto res_create_fail; - } - - pool->base.transforms[i] = dce80_transform_create(ctx, i); - if (pool->base.transforms[i] == NULL) { - BREAK_TO_DEBUGGER(); - dm_error("DC: failed to create transform!\n"); - goto res_create_fail; - } - - pool->base.opps[i] = dce80_opp_create(ctx, i); - if (pool->base.opps[i] == NULL) { - BREAK_TO_DEBUGGER(); - dm_error("DC: failed to create output pixel processor!\n"); - goto res_create_fail; - } - } - - for (i = 0; i < pool->base.res_cap->num_ddc; i++) { - pool->base.engines[i] = dce80_aux_engine_create(ctx, i); - if (pool->base.engines[i] == NULL) { - BREAK_TO_DEBUGGER(); - dm_error( - "DC:failed to create aux engine!!\n"); - goto res_create_fail; - } - pool->base.hw_i2cs[i] = dce80_i2c_hw_create(ctx, i); - if (pool->base.hw_i2cs[i] == NULL) { - BREAK_TO_DEBUGGER(); - dm_error( - "DC:failed to create i2c engine!!\n"); - goto res_create_fail; - } - pool->base.sw_i2cs[i] = dce80_i2c_sw_create(ctx); - if (pool->base.sw_i2cs[i] == NULL) { - BREAK_TO_DEBUGGER(); - dm_error( - "DC:failed to create sw i2c!!\n"); - goto res_create_fail; - } - } - - dc->caps.max_planes = pool->base.pipe_count; - - for (i = 0; i < dc->caps.max_planes; ++i) - dc->caps.planes[i] = plane_cap; - - dc->caps.disable_dp_clk_share = true; - - if (!resource_construct(num_virtual_links, dc, &pool->base, - &res_create_funcs)) - goto res_create_fail; - - /* Create hardware sequencer */ - dce80_hw_sequencer_construct(dc); - - return true; - -res_create_fail: - dce80_resource_destruct(pool); - return false; -} - -struct resource_pool *dce83_create_resource_pool( - uint8_t num_virtual_links, - struct dc *dc) -{ - struct dce110_resource_pool *pool = - kzalloc(sizeof(struct dce110_resource_pool), GFP_KERNEL); - - if (!pool) - return NULL; - - if (dce83_construct(num_virtual_links, dc, pool)) - return &pool->base; - - BREAK_TO_DEBUGGER(); - return NULL; -} diff --git a/drivers/gpu/drm/amd/display/dc/dce80/dce80_resource.h b/drivers/gpu/drm/amd/display/dc/dce80/dce80_resource.h deleted file mode 100644 index eff31ab83a39..000000000000 --- a/drivers/gpu/drm/amd/display/dc/dce80/dce80_resource.h +++ /dev/null @@ -1,47 +0,0 @@ -/* -* Copyright 2012-15 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_RESOURCE_DCE80_H__ -#define __DC_RESOURCE_DCE80_H__ - -#include "core_types.h" - -struct dc; -struct resource_pool; - -struct resource_pool *dce80_create_resource_pool( - uint8_t num_virtual_links, - struct dc *dc); - -struct resource_pool *dce81_create_resource_pool( - uint8_t num_virtual_links, - struct dc *dc); - -struct resource_pool *dce83_create_resource_pool( - uint8_t num_virtual_links, - struct dc *dc); - -#endif /* __DC_RESOURCE_DCE80_H__ */ - diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/Makefile b/drivers/gpu/drm/amd/display/dc/dcn10/Makefile index 2d2007c3e2b6..1eb7418ced3a 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/Makefile +++ b/drivers/gpu/drm/amd/display/dc/dcn10/Makefile @@ -22,7 +22,7 @@ # # Makefile for DCN. -DCN10 = dcn10_init.o dcn10_resource.o dcn10_ipp.o \ +DCN10 = dcn10_init.o dcn10_ipp.o \ dcn10_hw_sequencer_debug.o \ dcn10_dpp.o dcn10_opp.o dcn10_optc.o \ dcn10_hubp.o dcn10_mpc.o \ diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c deleted file mode 100644 index b94c5c97eee7..000000000000 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c +++ /dev/null @@ -1,1686 +0,0 @@ -/* -* Copyright 2016 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 "dm_services.h" -#include "dc.h" - -#include "dcn10_init.h" - -#include "resource.h" -#include "include/irq_service_interface.h" -#include "dcn10_resource.h" -#include "dcn10_ipp.h" -#include "dcn10_mpc.h" -#include "irq/dcn10/irq_service_dcn10.h" -#include "dcn10_dpp.h" -#include "dcn10_optc.h" -#include "dcn10/dcn10_hwseq.h" -#include "dce110/dce110_hwseq.h" -#include "dcn10_opp.h" -#include "dcn10_link_encoder.h" -#include "dcn10_stream_encoder.h" -#include "dce/dce_clock_source.h" -#include "dce/dce_audio.h" -#include "dce/dce_hwseq.h" -#include "virtual/virtual_stream_encoder.h" -#include "dce110/dce110_resource.h" -#include "dce112/dce112_resource.h" -#include "dcn10_hubp.h" -#include "dcn10_hubbub.h" -#include "dce/dce_panel_cntl.h" - -#include "soc15_hw_ip.h" -#include "vega10_ip_offset.h" - -#include "dcn/dcn_1_0_offset.h" -#include "dcn/dcn_1_0_sh_mask.h" - -#include "nbio/nbio_7_0_offset.h" - -#include "mmhub/mmhub_9_1_offset.h" -#include "mmhub/mmhub_9_1_sh_mask.h" - -#include "reg_helper.h" -#include "dce/dce_abm.h" -#include "dce/dce_dmcu.h" -#include "dce/dce_aux.h" -#include "dce/dce_i2c.h" - -#ifndef mmDP0_DP_DPHY_INTERNAL_CTRL - #define mmDP0_DP_DPHY_INTERNAL_CTRL 0x210f - #define mmDP0_DP_DPHY_INTERNAL_CTRL_BASE_IDX 2 - #define mmDP1_DP_DPHY_INTERNAL_CTRL 0x220f - #define mmDP1_DP_DPHY_INTERNAL_CTRL_BASE_IDX 2 - #define mmDP2_DP_DPHY_INTERNAL_CTRL 0x230f - #define mmDP2_DP_DPHY_INTERNAL_CTRL_BASE_IDX 2 - #define mmDP3_DP_DPHY_INTERNAL_CTRL 0x240f - #define mmDP3_DP_DPHY_INTERNAL_CTRL_BASE_IDX 2 - #define mmDP4_DP_DPHY_INTERNAL_CTRL 0x250f - #define mmDP4_DP_DPHY_INTERNAL_CTRL_BASE_IDX 2 - #define mmDP5_DP_DPHY_INTERNAL_CTRL 0x260f - #define mmDP5_DP_DPHY_INTERNAL_CTRL_BASE_IDX 2 - #define mmDP6_DP_DPHY_INTERNAL_CTRL 0x270f - #define mmDP6_DP_DPHY_INTERNAL_CTRL_BASE_IDX 2 -#endif - - -enum dcn10_clk_src_array_id { - DCN10_CLK_SRC_PLL0, - DCN10_CLK_SRC_PLL1, - DCN10_CLK_SRC_PLL2, - DCN10_CLK_SRC_PLL3, - DCN10_CLK_SRC_TOTAL, - DCN101_CLK_SRC_TOTAL = DCN10_CLK_SRC_PLL3 -}; - -/* begin ********************* - * macros to expend register list macro defined in HW object header file */ - -/* DCN */ -#define BASE_INNER(seg) \ - DCE_BASE__INST0_SEG ## seg - -#define BASE(seg) \ - BASE_INNER(seg) - -#define SR(reg_name)\ - .reg_name = BASE(mm ## reg_name ## _BASE_IDX) + \ - mm ## reg_name - -#define SRI(reg_name, block, id)\ - .reg_name = BASE(mm ## block ## id ## _ ## reg_name ## _BASE_IDX) + \ - mm ## block ## id ## _ ## reg_name - - -#define SRII(reg_name, block, id)\ - .reg_name[id] = BASE(mm ## block ## id ## _ ## reg_name ## _BASE_IDX) + \ - mm ## block ## id ## _ ## reg_name - -#define VUPDATE_SRII(reg_name, block, id)\ - .reg_name[id] = BASE(mm ## reg_name ## 0 ## _ ## block ## id ## _BASE_IDX) + \ - mm ## reg_name ## 0 ## _ ## block ## id - -/* set field/register/bitfield name */ -#define SFRB(field_name, reg_name, bitfield, post_fix)\ - .field_name = reg_name ## __ ## bitfield ## post_fix - -/* NBIO */ -#define NBIO_BASE_INNER(seg) \ - NBIF_BASE__INST0_SEG ## seg - -#define NBIO_BASE(seg) \ - NBIO_BASE_INNER(seg) - -#define NBIO_SR(reg_name)\ - .reg_name = NBIO_BASE(mm ## reg_name ## _BASE_IDX) + \ - mm ## reg_name - -/* MMHUB */ -#define MMHUB_BASE_INNER(seg) \ - MMHUB_BASE__INST0_SEG ## seg - -#define MMHUB_BASE(seg) \ - MMHUB_BASE_INNER(seg) - -#define MMHUB_SR(reg_name)\ - .reg_name = MMHUB_BASE(mm ## reg_name ## _BASE_IDX) + \ - mm ## reg_name - -/* macros to expend register list macro defined in HW object header file - * end *********************/ - - -static const struct dce_dmcu_registers dmcu_regs = { - DMCU_DCN10_REG_LIST() -}; - -static const struct dce_dmcu_shift dmcu_shift = { - DMCU_MASK_SH_LIST_DCN10(__SHIFT) -}; - -static const struct dce_dmcu_mask dmcu_mask = { - DMCU_MASK_SH_LIST_DCN10(_MASK) -}; - -static const struct dce_abm_registers abm_regs = { - ABM_DCN10_REG_LIST(0) -}; - -static const struct dce_abm_shift abm_shift = { - ABM_MASK_SH_LIST_DCN10(__SHIFT) -}; - -static const struct dce_abm_mask abm_mask = { - ABM_MASK_SH_LIST_DCN10(_MASK) -}; - -#define stream_enc_regs(id)\ -[id] = {\ - SE_DCN_REG_LIST(id)\ -} - -static const struct dcn10_stream_enc_registers stream_enc_regs[] = { - stream_enc_regs(0), - stream_enc_regs(1), - stream_enc_regs(2), - stream_enc_regs(3), -}; - -static const struct dcn10_stream_encoder_shift se_shift = { - SE_COMMON_MASK_SH_LIST_DCN10(__SHIFT) -}; - -static const struct dcn10_stream_encoder_mask se_mask = { - SE_COMMON_MASK_SH_LIST_DCN10(_MASK) -}; - -#define audio_regs(id)\ -[id] = {\ - AUD_COMMON_REG_LIST(id)\ -} - -static const struct dce_audio_registers audio_regs[] = { - audio_regs(0), - audio_regs(1), - audio_regs(2), - audio_regs(3), -}; - -#define DCE120_AUD_COMMON_MASK_SH_LIST(mask_sh)\ - SF(AZF0ENDPOINT0_AZALIA_F0_CODEC_ENDPOINT_INDEX, AZALIA_ENDPOINT_REG_INDEX, mask_sh),\ - SF(AZF0ENDPOINT0_AZALIA_F0_CODEC_ENDPOINT_DATA, AZALIA_ENDPOINT_REG_DATA, mask_sh),\ - AUD_COMMON_MASK_SH_LIST_BASE(mask_sh) - -static const struct dce_audio_shift audio_shift = { - DCE120_AUD_COMMON_MASK_SH_LIST(__SHIFT) -}; - -static const struct dce_audio_mask audio_mask = { - DCE120_AUD_COMMON_MASK_SH_LIST(_MASK) -}; - -#define aux_regs(id)\ -[id] = {\ - AUX_REG_LIST(id)\ -} - -static const struct dcn10_link_enc_aux_registers link_enc_aux_regs[] = { - aux_regs(0), - aux_regs(1), - aux_regs(2), - aux_regs(3) -}; - -#define hpd_regs(id)\ -[id] = {\ - HPD_REG_LIST(id)\ -} - -static const struct dcn10_link_enc_hpd_registers link_enc_hpd_regs[] = { - hpd_regs(0), - hpd_regs(1), - hpd_regs(2), - hpd_regs(3) -}; - -#define link_regs(id)\ -[id] = {\ - LE_DCN10_REG_LIST(id), \ - SRI(DP_DPHY_INTERNAL_CTRL, DP, id) \ -} - -static const struct dcn10_link_enc_registers link_enc_regs[] = { - link_regs(0), - link_regs(1), - link_regs(2), - link_regs(3) -}; - -static const struct dcn10_link_enc_shift le_shift = { - LINK_ENCODER_MASK_SH_LIST_DCN10(__SHIFT) -}; - -static const struct dcn10_link_enc_mask le_mask = { - LINK_ENCODER_MASK_SH_LIST_DCN10(_MASK) -}; - -static const struct dce_panel_cntl_registers panel_cntl_regs[] = { - { DCN_PANEL_CNTL_REG_LIST() } -}; - -static const struct dce_panel_cntl_shift panel_cntl_shift = { - DCE_PANEL_CNTL_MASK_SH_LIST(__SHIFT) -}; - -static const struct dce_panel_cntl_mask panel_cntl_mask = { - DCE_PANEL_CNTL_MASK_SH_LIST(_MASK) -}; - -static const struct dce110_aux_registers_shift aux_shift = { - DCN10_AUX_MASK_SH_LIST(__SHIFT) -}; - -static const struct dce110_aux_registers_mask aux_mask = { - DCN10_AUX_MASK_SH_LIST(_MASK) -}; - -#define ipp_regs(id)\ -[id] = {\ - IPP_REG_LIST_DCN10(id),\ -} - -static const struct dcn10_ipp_registers ipp_regs[] = { - ipp_regs(0), - ipp_regs(1), - ipp_regs(2), - ipp_regs(3), -}; - -static const struct dcn10_ipp_shift ipp_shift = { - IPP_MASK_SH_LIST_DCN10(__SHIFT) -}; - -static const struct dcn10_ipp_mask ipp_mask = { - IPP_MASK_SH_LIST_DCN10(_MASK), -}; - -#define opp_regs(id)\ -[id] = {\ - OPP_REG_LIST_DCN10(id),\ -} - -static const struct dcn10_opp_registers opp_regs[] = { - opp_regs(0), - opp_regs(1), - opp_regs(2), - opp_regs(3), -}; - -static const struct dcn10_opp_shift opp_shift = { - OPP_MASK_SH_LIST_DCN10(__SHIFT) -}; - -static const struct dcn10_opp_mask opp_mask = { - OPP_MASK_SH_LIST_DCN10(_MASK), -}; - -#define aux_engine_regs(id)\ -[id] = {\ - AUX_COMMON_REG_LIST(id), \ - .AUX_RESET_MASK = 0 \ -} - -static const struct dce110_aux_registers aux_engine_regs[] = { - aux_engine_regs(0), - aux_engine_regs(1), - aux_engine_regs(2), - aux_engine_regs(3), - aux_engine_regs(4), - aux_engine_regs(5) -}; - -#define tf_regs(id)\ -[id] = {\ - TF_REG_LIST_DCN10(id),\ -} - -static const struct dcn_dpp_registers tf_regs[] = { - tf_regs(0), - tf_regs(1), - tf_regs(2), - tf_regs(3), -}; - -static const struct dcn_dpp_shift tf_shift = { - TF_REG_LIST_SH_MASK_DCN10(__SHIFT), - TF_DEBUG_REG_LIST_SH_DCN10 - -}; - -static const struct dcn_dpp_mask tf_mask = { - TF_REG_LIST_SH_MASK_DCN10(_MASK), - TF_DEBUG_REG_LIST_MASK_DCN10 -}; - -static const struct dcn_mpc_registers mpc_regs = { - MPC_COMMON_REG_LIST_DCN1_0(0), - MPC_COMMON_REG_LIST_DCN1_0(1), - MPC_COMMON_REG_LIST_DCN1_0(2), - MPC_COMMON_REG_LIST_DCN1_0(3), - MPC_OUT_MUX_COMMON_REG_LIST_DCN1_0(0), - MPC_OUT_MUX_COMMON_REG_LIST_DCN1_0(1), - MPC_OUT_MUX_COMMON_REG_LIST_DCN1_0(2), - MPC_OUT_MUX_COMMON_REG_LIST_DCN1_0(3) -}; - -static const struct dcn_mpc_shift mpc_shift = { - MPC_COMMON_MASK_SH_LIST_DCN1_0(__SHIFT),\ - SFRB(CUR_VUPDATE_LOCK_SET, CUR0_VUPDATE_LOCK_SET0, CUR0_VUPDATE_LOCK_SET, __SHIFT) -}; - -static const struct dcn_mpc_mask mpc_mask = { - MPC_COMMON_MASK_SH_LIST_DCN1_0(_MASK),\ - SFRB(CUR_VUPDATE_LOCK_SET, CUR0_VUPDATE_LOCK_SET0, CUR0_VUPDATE_LOCK_SET, _MASK) -}; - -#define tg_regs(id)\ -[id] = {TG_COMMON_REG_LIST_DCN1_0(id)} - -static const struct dcn_optc_registers tg_regs[] = { - tg_regs(0), - tg_regs(1), - tg_regs(2), - tg_regs(3), -}; - -static const struct dcn_optc_shift tg_shift = { - TG_COMMON_MASK_SH_LIST_DCN1_0(__SHIFT) -}; - -static const struct dcn_optc_mask tg_mask = { - TG_COMMON_MASK_SH_LIST_DCN1_0(_MASK) -}; - -static const struct bios_registers bios_regs = { - NBIO_SR(BIOS_SCRATCH_3), - NBIO_SR(BIOS_SCRATCH_6) -}; - -#define hubp_regs(id)\ -[id] = {\ - HUBP_REG_LIST_DCN10(id)\ -} - -static const struct dcn_mi_registers hubp_regs[] = { - hubp_regs(0), - hubp_regs(1), - hubp_regs(2), - hubp_regs(3), -}; - -static const struct dcn_mi_shift hubp_shift = { - HUBP_MASK_SH_LIST_DCN10(__SHIFT) -}; - -static const struct dcn_mi_mask hubp_mask = { - HUBP_MASK_SH_LIST_DCN10(_MASK) -}; - -static const struct dcn_hubbub_registers hubbub_reg = { - HUBBUB_REG_LIST_DCN10(0) -}; - -static const struct dcn_hubbub_shift hubbub_shift = { - HUBBUB_MASK_SH_LIST_DCN10(__SHIFT) -}; - -static const struct dcn_hubbub_mask hubbub_mask = { - HUBBUB_MASK_SH_LIST_DCN10(_MASK) -}; - -static int map_transmitter_id_to_phy_instance( - enum transmitter transmitter) -{ - switch (transmitter) { - case TRANSMITTER_UNIPHY_A: - return 0; - break; - case TRANSMITTER_UNIPHY_B: - return 1; - break; - case TRANSMITTER_UNIPHY_C: - return 2; - break; - case TRANSMITTER_UNIPHY_D: - return 3; - break; - default: - ASSERT(0); - return 0; - } -} - -#define clk_src_regs(index, pllid)\ -[index] = {\ - CS_COMMON_REG_LIST_DCN1_0(index, pllid),\ -} - -static const struct dce110_clk_src_regs clk_src_regs[] = { - clk_src_regs(0, A), - clk_src_regs(1, B), - clk_src_regs(2, C), - clk_src_regs(3, D) -}; - -static const struct dce110_clk_src_shift cs_shift = { - CS_COMMON_MASK_SH_LIST_DCN1_0(__SHIFT) -}; - -static const struct dce110_clk_src_mask cs_mask = { - CS_COMMON_MASK_SH_LIST_DCN1_0(_MASK) -}; - -static const struct resource_caps res_cap = { - .num_timing_generator = 4, - .num_opp = 4, - .num_video_plane = 4, - .num_audio = 4, - .num_stream_encoder = 4, - .num_pll = 4, - .num_ddc = 4, -}; - -static const struct resource_caps rv2_res_cap = { - .num_timing_generator = 3, - .num_opp = 3, - .num_video_plane = 3, - .num_audio = 3, - .num_stream_encoder = 3, - .num_pll = 3, - .num_ddc = 4, -}; - -static const struct dc_plane_cap plane_cap = { - .type = DC_PLANE_TYPE_DCN_UNIVERSAL, - .per_pixel_alpha = true, - - .pixel_format_support = { - .argb8888 = true, - .nv12 = true, - .fp16 = true, - .p010 = true - }, - - .max_upscale_factor = { - .argb8888 = 16000, - .nv12 = 16000, - .fp16 = 1 - }, - - .max_downscale_factor = { - .argb8888 = 250, - .nv12 = 250, - .fp16 = 1 - } -}; - -static const struct dc_debug_options debug_defaults_drv = { - .sanity_checks = true, - .disable_dmcu = false, - .force_abm_enable = false, - .timing_trace = false, - .clock_trace = true, - - /* raven smu dones't allow 0 disp clk, - * smu min disp clk limit is 50Mhz - * keep min disp clk 100Mhz avoid smu hang - */ - .min_disp_clk_khz = 100000, - - .disable_pplib_clock_request = false, - .disable_pplib_wm_range = false, - .pplib_wm_report_mode = WM_REPORT_DEFAULT, - .pipe_split_policy = MPC_SPLIT_DYNAMIC, - .force_single_disp_pipe_split = true, - .disable_dcc = DCC_ENABLE, - .voltage_align_fclk = true, - .disable_stereo_support = true, - .vsr_support = true, - .performance_trace = false, - .az_endpoint_mute_only = true, - .recovery_enabled = false, /*enable this by default after testing.*/ - .max_downscale_src_width = 3840, - .underflow_assert_delay_us = 0xFFFFFFFF, - .enable_legacy_fast_update = true, - .using_dml2 = false, -}; - -static const struct dc_debug_options debug_defaults_diags = { - .disable_dmcu = false, - .force_abm_enable = false, - .timing_trace = true, - .clock_trace = true, - .disable_stutter = true, - .disable_pplib_clock_request = true, - .disable_pplib_wm_range = true, - .underflow_assert_delay_us = 0xFFFFFFFF, -}; - -static void dcn10_dpp_destroy(struct dpp **dpp) -{ - kfree(TO_DCN10_DPP(*dpp)); - *dpp = NULL; -} - -static struct dpp *dcn10_dpp_create( - struct dc_context *ctx, - uint32_t inst) -{ - struct dcn10_dpp *dpp = - kzalloc(sizeof(struct dcn10_dpp), GFP_KERNEL); - - if (!dpp) - return NULL; - - dpp1_construct(dpp, ctx, inst, - &tf_regs[inst], &tf_shift, &tf_mask); - return &dpp->base; -} - -static struct input_pixel_processor *dcn10_ipp_create( - struct dc_context *ctx, uint32_t inst) -{ - struct dcn10_ipp *ipp = - kzalloc(sizeof(struct dcn10_ipp), GFP_KERNEL); - - if (!ipp) { - BREAK_TO_DEBUGGER(); - return NULL; - } - - dcn10_ipp_construct(ipp, ctx, inst, - &ipp_regs[inst], &ipp_shift, &ipp_mask); - return &ipp->base; -} - - -static struct output_pixel_processor *dcn10_opp_create( - struct dc_context *ctx, uint32_t inst) -{ - struct dcn10_opp *opp = - kzalloc(sizeof(struct dcn10_opp), GFP_KERNEL); - - if (!opp) { - BREAK_TO_DEBUGGER(); - return NULL; - } - - dcn10_opp_construct(opp, ctx, inst, - &opp_regs[inst], &opp_shift, &opp_mask); - return &opp->base; -} - -static struct dce_aux *dcn10_aux_engine_create(struct dc_context *ctx, - uint32_t inst) -{ - struct aux_engine_dce110 *aux_engine = - kzalloc(sizeof(struct aux_engine_dce110), GFP_KERNEL); - - if (!aux_engine) - return NULL; - - dce110_aux_engine_construct(aux_engine, ctx, inst, - SW_AUX_TIMEOUT_PERIOD_MULTIPLIER * AUX_TIMEOUT_PERIOD, - &aux_engine_regs[inst], - &aux_mask, - &aux_shift, - ctx->dc->caps.extended_aux_timeout_support); - - return &aux_engine->base; -} -#define i2c_inst_regs(id) { I2C_HW_ENGINE_COMMON_REG_LIST(id) } - -static const struct dce_i2c_registers i2c_hw_regs[] = { - i2c_inst_regs(1), - i2c_inst_regs(2), - i2c_inst_regs(3), - i2c_inst_regs(4), - i2c_inst_regs(5), - i2c_inst_regs(6), -}; - -static const struct dce_i2c_shift i2c_shifts = { - I2C_COMMON_MASK_SH_LIST_DCE110(__SHIFT) -}; - -static const struct dce_i2c_mask i2c_masks = { - I2C_COMMON_MASK_SH_LIST_DCE110(_MASK) -}; - -static struct dce_i2c_hw *dcn10_i2c_hw_create(struct dc_context *ctx, - uint32_t inst) -{ - struct dce_i2c_hw *dce_i2c_hw = - kzalloc(sizeof(struct dce_i2c_hw), GFP_KERNEL); - - if (!dce_i2c_hw) - return NULL; - - dcn1_i2c_hw_construct(dce_i2c_hw, ctx, inst, - &i2c_hw_regs[inst], &i2c_shifts, &i2c_masks); - - return dce_i2c_hw; -} -static struct mpc *dcn10_mpc_create(struct dc_context *ctx) -{ - struct dcn10_mpc *mpc10 = kzalloc(sizeof(struct dcn10_mpc), - GFP_KERNEL); - - if (!mpc10) - return NULL; - - dcn10_mpc_construct(mpc10, ctx, - &mpc_regs, - &mpc_shift, - &mpc_mask, - 4); - - return &mpc10->base; -} - -static struct hubbub *dcn10_hubbub_create(struct dc_context *ctx) -{ - struct dcn10_hubbub *dcn10_hubbub = kzalloc(sizeof(struct dcn10_hubbub), - GFP_KERNEL); - - if (!dcn10_hubbub) - return NULL; - - hubbub1_construct(&dcn10_hubbub->base, ctx, - &hubbub_reg, - &hubbub_shift, - &hubbub_mask); - - return &dcn10_hubbub->base; -} - -static struct timing_generator *dcn10_timing_generator_create( - struct dc_context *ctx, - uint32_t instance) -{ - struct optc *tgn10 = - kzalloc(sizeof(struct optc), GFP_KERNEL); - - if (!tgn10) - return NULL; - - tgn10->base.inst = instance; - tgn10->base.ctx = ctx; - - tgn10->tg_regs = &tg_regs[instance]; - tgn10->tg_shift = &tg_shift; - tgn10->tg_mask = &tg_mask; - - dcn10_timing_generator_init(tgn10); - - return &tgn10->base; -} - -static const struct encoder_feature_support link_enc_feature = { - .max_hdmi_deep_color = COLOR_DEPTH_121212, - .max_hdmi_pixel_clock = 600000, - .hdmi_ycbcr420_supported = true, - .dp_ycbcr420_supported = true, - .flags.bits.IS_HBR2_CAPABLE = true, - .flags.bits.IS_HBR3_CAPABLE = true, - .flags.bits.IS_TPS3_CAPABLE = true, - .flags.bits.IS_TPS4_CAPABLE = true -}; - -static struct link_encoder *dcn10_link_encoder_create( - struct dc_context *ctx, - const struct encoder_init_data *enc_init_data) -{ - struct dcn10_link_encoder *enc10 = - kzalloc(sizeof(struct dcn10_link_encoder), GFP_KERNEL); - int link_regs_id; - - if (!enc10) - return NULL; - - link_regs_id = - map_transmitter_id_to_phy_instance(enc_init_data->transmitter); - - dcn10_link_encoder_construct(enc10, - enc_init_data, - &link_enc_feature, - &link_enc_regs[link_regs_id], - &link_enc_aux_regs[enc_init_data->channel - 1], - &link_enc_hpd_regs[enc_init_data->hpd_source], - &le_shift, - &le_mask); - - return &enc10->base; -} - -static struct panel_cntl *dcn10_panel_cntl_create(const struct panel_cntl_init_data *init_data) -{ - struct dce_panel_cntl *panel_cntl = - kzalloc(sizeof(struct dce_panel_cntl), GFP_KERNEL); - - if (!panel_cntl) - return NULL; - - dce_panel_cntl_construct(panel_cntl, - init_data, - &panel_cntl_regs[init_data->inst], - &panel_cntl_shift, - &panel_cntl_mask); - - return &panel_cntl->base; -} - -static struct clock_source *dcn10_clock_source_create( - struct dc_context *ctx, - struct dc_bios *bios, - enum clock_source_id id, - const struct dce110_clk_src_regs *regs, - bool dp_clk_src) -{ - struct dce110_clk_src *clk_src = - kzalloc(sizeof(struct dce110_clk_src), GFP_KERNEL); - - if (!clk_src) - return NULL; - - if (dce112_clk_src_construct(clk_src, ctx, bios, id, - regs, &cs_shift, &cs_mask)) { - clk_src->base.dp_clk_src = dp_clk_src; - return &clk_src->base; - } - - kfree(clk_src); - BREAK_TO_DEBUGGER(); - return NULL; -} - -static void read_dce_straps( - struct dc_context *ctx, - struct resource_straps *straps) -{ - generic_reg_get(ctx, mmDC_PINSTRAPS + BASE(mmDC_PINSTRAPS_BASE_IDX), - FN(DC_PINSTRAPS, DC_PINSTRAPS_AUDIO), &straps->dc_pinstraps_audio); -} - -static struct audio *create_audio( - struct dc_context *ctx, unsigned int inst) -{ - return dce_audio_create(ctx, inst, - &audio_regs[inst], &audio_shift, &audio_mask); -} - -static struct stream_encoder *dcn10_stream_encoder_create( - enum engine_id eng_id, - struct dc_context *ctx) -{ - struct dcn10_stream_encoder *enc1 = - kzalloc(sizeof(struct dcn10_stream_encoder), GFP_KERNEL); - - if (!enc1) - return NULL; - - dcn10_stream_encoder_construct(enc1, ctx, ctx->dc_bios, eng_id, - &stream_enc_regs[eng_id], - &se_shift, &se_mask); - return &enc1->base; -} - -static const struct dce_hwseq_registers hwseq_reg = { - HWSEQ_DCN1_REG_LIST() -}; - -static const struct dce_hwseq_shift hwseq_shift = { - HWSEQ_DCN1_MASK_SH_LIST(__SHIFT) -}; - -static const struct dce_hwseq_mask hwseq_mask = { - HWSEQ_DCN1_MASK_SH_LIST(_MASK) -}; - -static struct dce_hwseq *dcn10_hwseq_create( - struct dc_context *ctx) -{ - struct dce_hwseq *hws = kzalloc(sizeof(struct dce_hwseq), GFP_KERNEL); - - if (hws) { - hws->ctx = ctx; - hws->regs = &hwseq_reg; - hws->shifts = &hwseq_shift; - hws->masks = &hwseq_mask; - hws->wa.DEGVIDCN10_253 = true; - hws->wa.false_optc_underflow = true; - hws->wa.DEGVIDCN10_254 = true; - - if ((ctx->asic_id.chip_family == FAMILY_RV) && - ASICREV_IS_RAVEN2(ctx->asic_id.hw_internal_rev)) - switch (ctx->asic_id.pci_revision_id) { - case PRID_POLLOCK_94: - case PRID_POLLOCK_95: - case PRID_POLLOCK_E9: - case PRID_POLLOCK_EA: - case PRID_POLLOCK_EB: - hws->wa.wait_hubpret_read_start_during_mpo_transition = true; - break; - default: - hws->wa.wait_hubpret_read_start_during_mpo_transition = false; - break; - } - } - return hws; -} - -static const struct resource_create_funcs res_create_funcs = { - .read_dce_straps = read_dce_straps, - .create_audio = create_audio, - .create_stream_encoder = dcn10_stream_encoder_create, - .create_hwseq = dcn10_hwseq_create, -}; - -static void dcn10_clock_source_destroy(struct clock_source **clk_src) -{ - kfree(TO_DCE110_CLK_SRC(*clk_src)); - *clk_src = NULL; -} - -static struct pp_smu_funcs *dcn10_pp_smu_create(struct dc_context *ctx) -{ - struct pp_smu_funcs *pp_smu = kzalloc(sizeof(*pp_smu), GFP_KERNEL); - - if (!pp_smu) - return pp_smu; - - dm_pp_get_funcs(ctx, pp_smu); - return pp_smu; -} - -static void dcn10_resource_destruct(struct dcn10_resource_pool *pool) -{ - unsigned int i; - - for (i = 0; i < pool->base.stream_enc_count; i++) { - if (pool->base.stream_enc[i] != NULL) { - kfree(DCN10STRENC_FROM_STRENC(pool->base.stream_enc[i])); - pool->base.stream_enc[i] = NULL; - } - } - - if (pool->base.mpc != NULL) { - kfree(TO_DCN10_MPC(pool->base.mpc)); - pool->base.mpc = NULL; - } - - kfree(pool->base.hubbub); - pool->base.hubbub = NULL; - - for (i = 0; i < pool->base.pipe_count; i++) { - if (pool->base.opps[i] != NULL) - pool->base.opps[i]->funcs->opp_destroy(&pool->base.opps[i]); - - if (pool->base.dpps[i] != NULL) - dcn10_dpp_destroy(&pool->base.dpps[i]); - - if (pool->base.ipps[i] != NULL) - pool->base.ipps[i]->funcs->ipp_destroy(&pool->base.ipps[i]); - - if (pool->base.hubps[i] != NULL) { - kfree(TO_DCN10_HUBP(pool->base.hubps[i])); - pool->base.hubps[i] = NULL; - } - - if (pool->base.irqs != NULL) { - dal_irq_service_destroy(&pool->base.irqs); - } - - if (pool->base.timing_generators[i] != NULL) { - kfree(DCN10TG_FROM_TG(pool->base.timing_generators[i])); - pool->base.timing_generators[i] = NULL; - } - } - - for (i = 0; i < pool->base.res_cap->num_ddc; i++) { - if (pool->base.engines[i] != NULL) - dce110_engine_destroy(&pool->base.engines[i]); - kfree(pool->base.hw_i2cs[i]); - pool->base.hw_i2cs[i] = NULL; - kfree(pool->base.sw_i2cs[i]); - pool->base.sw_i2cs[i] = NULL; - } - - for (i = 0; i < pool->base.audio_count; i++) { - if (pool->base.audios[i]) - dce_aud_destroy(&pool->base.audios[i]); - } - - for (i = 0; i < pool->base.clk_src_count; i++) { - if (pool->base.clock_sources[i] != NULL) { - dcn10_clock_source_destroy(&pool->base.clock_sources[i]); - pool->base.clock_sources[i] = NULL; - } - } - - if (pool->base.dp_clock_source != NULL) { - dcn10_clock_source_destroy(&pool->base.dp_clock_source); - pool->base.dp_clock_source = NULL; - } - - if (pool->base.abm != NULL) - dce_abm_destroy(&pool->base.abm); - - if (pool->base.dmcu != NULL) - dce_dmcu_destroy(&pool->base.dmcu); - - kfree(pool->base.pp_smu); -} - -static struct hubp *dcn10_hubp_create( - struct dc_context *ctx, - uint32_t inst) -{ - struct dcn10_hubp *hubp1 = - kzalloc(sizeof(struct dcn10_hubp), GFP_KERNEL); - - if (!hubp1) - return NULL; - - dcn10_hubp_construct(hubp1, ctx, inst, - &hubp_regs[inst], &hubp_shift, &hubp_mask); - return &hubp1->base; -} - -static void get_pixel_clock_parameters( - const struct pipe_ctx *pipe_ctx, - struct pixel_clk_params *pixel_clk_params) -{ - const struct dc_stream_state *stream = pipe_ctx->stream; - pixel_clk_params->requested_pix_clk_100hz = stream->timing.pix_clk_100hz; - pixel_clk_params->encoder_object_id = stream->link->link_enc->id; - pixel_clk_params->signal_type = pipe_ctx->stream->signal; - pixel_clk_params->controller_id = pipe_ctx->stream_res.tg->inst + 1; - /* TODO: un-hardcode*/ - pixel_clk_params->requested_sym_clk = LINK_RATE_LOW * - LINK_RATE_REF_FREQ_IN_KHZ; - pixel_clk_params->flags.ENABLE_SS = 0; - pixel_clk_params->color_depth = - stream->timing.display_color_depth; - pixel_clk_params->flags.DISPLAY_BLANKED = 1; - pixel_clk_params->pixel_encoding = stream->timing.pixel_encoding; - - if (stream->timing.pixel_encoding == PIXEL_ENCODING_YCBCR422) - pixel_clk_params->color_depth = COLOR_DEPTH_888; - - if (stream->timing.pixel_encoding == PIXEL_ENCODING_YCBCR420) - pixel_clk_params->requested_pix_clk_100hz /= 2; - if (stream->timing.timing_3d_format == TIMING_3D_FORMAT_HW_FRAME_PACKING) - pixel_clk_params->requested_pix_clk_100hz *= 2; - -} - -static void build_clamping_params(struct dc_stream_state *stream) -{ - stream->clamping.clamping_level = CLAMPING_FULL_RANGE; - stream->clamping.c_depth = stream->timing.display_color_depth; - stream->clamping.pixel_encoding = stream->timing.pixel_encoding; -} - -static void build_pipe_hw_param(struct pipe_ctx *pipe_ctx) -{ - - get_pixel_clock_parameters(pipe_ctx, &pipe_ctx->stream_res.pix_clk_params); - - pipe_ctx->clock_source->funcs->get_pix_clk_dividers( - pipe_ctx->clock_source, - &pipe_ctx->stream_res.pix_clk_params, - &pipe_ctx->pll_settings); - - pipe_ctx->stream->clamping.pixel_encoding = pipe_ctx->stream->timing.pixel_encoding; - - resource_build_bit_depth_reduction_params(pipe_ctx->stream, - &pipe_ctx->stream->bit_depth_params); - build_clamping_params(pipe_ctx->stream); -} - -static enum dc_status build_mapped_resource( - const struct dc *dc, - struct dc_state *context, - struct dc_stream_state *stream) -{ - struct pipe_ctx *pipe_ctx = resource_get_otg_master_for_stream(&context->res_ctx, stream); - - if (!pipe_ctx) - return DC_ERROR_UNEXPECTED; - - build_pipe_hw_param(pipe_ctx); - return DC_OK; -} - -static enum dc_status dcn10_add_stream_to_ctx( - struct dc *dc, - struct dc_state *new_ctx, - struct dc_stream_state *dc_stream) -{ - enum dc_status result = DC_ERROR_UNEXPECTED; - - result = resource_map_pool_resources(dc, new_ctx, dc_stream); - - if (result == DC_OK) - result = resource_map_phy_clock_resources(dc, new_ctx, dc_stream); - - - if (result == DC_OK) - result = build_mapped_resource(dc, new_ctx, dc_stream); - - return result; -} - -static struct pipe_ctx *dcn10_acquire_free_pipe_for_layer( - const struct dc_state *cur_ctx, - struct dc_state *new_ctx, - const struct resource_pool *pool, - const struct pipe_ctx *opp_head_pipe) -{ - struct resource_context *res_ctx = &new_ctx->res_ctx; - struct pipe_ctx *head_pipe = resource_get_otg_master_for_stream(res_ctx, opp_head_pipe->stream); - struct pipe_ctx *idle_pipe = resource_find_free_secondary_pipe_legacy(res_ctx, pool, head_pipe); - - if (!head_pipe) { - ASSERT(0); - return NULL; - } - - if (!idle_pipe) - return NULL; - - idle_pipe->stream = head_pipe->stream; - idle_pipe->stream_res.tg = head_pipe->stream_res.tg; - idle_pipe->stream_res.abm = head_pipe->stream_res.abm; - idle_pipe->stream_res.opp = head_pipe->stream_res.opp; - - idle_pipe->plane_res.hubp = pool->hubps[idle_pipe->pipe_idx]; - idle_pipe->plane_res.ipp = pool->ipps[idle_pipe->pipe_idx]; - idle_pipe->plane_res.dpp = pool->dpps[idle_pipe->pipe_idx]; - idle_pipe->plane_res.mpcc_inst = pool->dpps[idle_pipe->pipe_idx]->inst; - - return idle_pipe; -} - -static bool dcn10_get_dcc_compression_cap(const struct dc *dc, - const struct dc_dcc_surface_param *input, - struct dc_surface_dcc_cap *output) -{ - return dc->res_pool->hubbub->funcs->get_dcc_compression_cap( - dc->res_pool->hubbub, - input, - output); -} - -static void dcn10_destroy_resource_pool(struct resource_pool **pool) -{ - struct dcn10_resource_pool *dcn10_pool = TO_DCN10_RES_POOL(*pool); - - dcn10_resource_destruct(dcn10_pool); - kfree(dcn10_pool); - *pool = NULL; -} - -static bool dcn10_validate_bandwidth( - struct dc *dc, - struct dc_state *context, - bool fast_validate) -{ - bool voltage_supported; - - DC_FP_START(); - voltage_supported = dcn_validate_bandwidth(dc, context, fast_validate); - DC_FP_END(); - - return voltage_supported; -} - -static enum dc_status dcn10_validate_plane(const struct dc_plane_state *plane_state, struct dc_caps *caps) -{ - if (plane_state->format >= SURFACE_PIXEL_FORMAT_VIDEO_BEGIN - && caps->max_video_width != 0 - && plane_state->src_rect.width > caps->max_video_width) - return DC_FAIL_SURFACE_VALIDATE; - - return DC_OK; -} - -static enum dc_status dcn10_validate_global(struct dc *dc, struct dc_state *context) -{ - int i, j; - bool video_down_scaled = false; - bool video_large = false; - bool desktop_large = false; - bool dcc_disabled = false; - bool mpo_enabled = false; - - for (i = 0; i < context->stream_count; i++) { - if (context->stream_status[i].plane_count == 0) - continue; - - if (context->stream_status[i].plane_count > 2) - return DC_FAIL_UNSUPPORTED_1; - - if (context->stream_status[i].plane_count > 1) - mpo_enabled = true; - - for (j = 0; j < context->stream_status[i].plane_count; j++) { - struct dc_plane_state *plane = - context->stream_status[i].plane_states[j]; - - - if (plane->format >= SURFACE_PIXEL_FORMAT_VIDEO_BEGIN) { - - if (plane->src_rect.width > plane->dst_rect.width || - plane->src_rect.height > plane->dst_rect.height) - video_down_scaled = true; - - if (plane->src_rect.width >= 3840) - video_large = true; - - } else { - if (plane->src_rect.width >= 3840) - desktop_large = true; - if (!plane->dcc.enable) - dcc_disabled = true; - } - } - } - - /* Disable MPO in multi-display configurations. */ - if (context->stream_count > 1 && mpo_enabled) - return DC_FAIL_UNSUPPORTED_1; - - /* - * Workaround: On DCN10 there is UMC issue that causes underflow when - * playing 4k video on 4k desktop with video downscaled and single channel - * memory - */ - if (video_large && desktop_large && video_down_scaled && dcc_disabled && - dc->dcn_soc->number_of_channels == 1) - return DC_FAIL_SURFACE_VALIDATE; - - return DC_OK; -} - -static enum dc_status dcn10_patch_unknown_plane_state(struct dc_plane_state *plane_state) -{ - enum surface_pixel_format surf_pix_format = plane_state->format; - unsigned int bpp = resource_pixel_format_to_bpp(surf_pix_format); - - enum swizzle_mode_values swizzle = DC_SW_LINEAR; - - if (bpp == 64) - swizzle = DC_SW_64KB_D; - else - swizzle = DC_SW_64KB_S; - - plane_state->tiling_info.gfx9.swizzle = swizzle; - return DC_OK; -} - -struct stream_encoder *dcn10_find_first_free_match_stream_enc_for_link( - struct resource_context *res_ctx, - const struct resource_pool *pool, - struct dc_stream_state *stream) -{ - int i; - int j = -1; - struct dc_link *link = stream->link; - - for (i = 0; i < pool->stream_enc_count; i++) { - if (!res_ctx->is_stream_enc_acquired[i] && - pool->stream_enc[i]) { - /* Store first available for MST second display - * in daisy chain use case - */ - j = i; - if (link->ep_type == DISPLAY_ENDPOINT_PHY && pool->stream_enc[i]->id == - link->link_enc->preferred_engine) - return pool->stream_enc[i]; - } - } - - /* - * For CZ and later, we can allow DIG FE and BE to differ for all display types - */ - - if (j >= 0) - return pool->stream_enc[j]; - - return NULL; -} - -static const struct dc_cap_funcs cap_funcs = { - .get_dcc_compression_cap = dcn10_get_dcc_compression_cap -}; - -static const struct resource_funcs dcn10_res_pool_funcs = { - .destroy = dcn10_destroy_resource_pool, - .link_enc_create = dcn10_link_encoder_create, - .panel_cntl_create = dcn10_panel_cntl_create, - .validate_bandwidth = dcn10_validate_bandwidth, - .acquire_free_pipe_as_secondary_dpp_pipe = dcn10_acquire_free_pipe_for_layer, - .validate_plane = dcn10_validate_plane, - .validate_global = dcn10_validate_global, - .add_stream_to_ctx = dcn10_add_stream_to_ctx, - .patch_unknown_plane_state = dcn10_patch_unknown_plane_state, - .find_first_free_match_stream_enc_for_link = dcn10_find_first_free_match_stream_enc_for_link -}; - -static uint32_t read_pipe_fuses(struct dc_context *ctx) -{ - uint32_t value = dm_read_reg_soc15(ctx, mmCC_DC_PIPE_DIS, 0); - /* RV1 support max 4 pipes */ - value = value & 0xf; - return value; -} - -static bool verify_clock_values(struct dm_pp_clock_levels_with_voltage *clks) -{ - int i; - - if (clks->num_levels == 0) - return false; - - for (i = 0; i < clks->num_levels; i++) - /* Ensure that the result is sane */ - if (clks->data[i].clocks_in_khz == 0) - return false; - - return true; -} - -static bool dcn10_resource_construct( - uint8_t num_virtual_links, - struct dc *dc, - struct dcn10_resource_pool *pool) -{ - int i; - int j; - struct dc_context *ctx = dc->ctx; - uint32_t pipe_fuses = read_pipe_fuses(ctx); - struct dm_pp_clock_levels_with_voltage fclks = {0}, dcfclks = {0}; - int min_fclk_khz, min_dcfclk_khz, socclk_khz; - bool res; - - ctx->dc_bios->regs = &bios_regs; - - if (ctx->dce_version == DCN_VERSION_1_01) - pool->base.res_cap = &rv2_res_cap; - else - pool->base.res_cap = &res_cap; - pool->base.funcs = &dcn10_res_pool_funcs; - - /* - * TODO fill in from actual raven resource when we create - * more than virtual encoder - */ - - /************************************************* - * Resource + asic cap harcoding * - *************************************************/ - pool->base.underlay_pipe_index = NO_UNDERLAY_PIPE; - - /* max pipe num for ASIC before check pipe fuses */ - pool->base.pipe_count = pool->base.res_cap->num_timing_generator; - - if (dc->ctx->dce_version == DCN_VERSION_1_01) - pool->base.pipe_count = 3; - dc->caps.max_video_width = 3840; - dc->caps.max_downscale_ratio = 200; - dc->caps.i2c_speed_in_khz = 100; - dc->caps.i2c_speed_in_khz_hdcp = 100; /*1.4 w/a not applied by default*/ - dc->caps.max_cursor_size = 256; - dc->caps.min_horizontal_blanking_period = 80; - dc->caps.max_slave_planes = 1; - dc->caps.max_slave_yuv_planes = 1; - dc->caps.max_slave_rgb_planes = 0; - dc->caps.is_apu = true; - dc->caps.post_blend_color_processing = false; - dc->caps.extended_aux_timeout_support = false; - - /* Raven DP PHY HBR2 eye diagram pattern is not stable. Use TP4 */ - dc->caps.force_dp_tps4_for_cp2520 = true; - - /* Color pipeline capabilities */ - dc->caps.color.dpp.dcn_arch = 1; - dc->caps.color.dpp.input_lut_shared = 1; - dc->caps.color.dpp.icsc = 1; - dc->caps.color.dpp.dgam_ram = 1; - dc->caps.color.dpp.dgam_rom_caps.srgb = 1; - dc->caps.color.dpp.dgam_rom_caps.bt2020 = 1; - dc->caps.color.dpp.dgam_rom_caps.gamma2_2 = 0; - dc->caps.color.dpp.dgam_rom_caps.pq = 0; - dc->caps.color.dpp.dgam_rom_caps.hlg = 0; - dc->caps.color.dpp.post_csc = 0; - dc->caps.color.dpp.gamma_corr = 0; - dc->caps.color.dpp.dgam_rom_for_yuv = 1; - - dc->caps.color.dpp.hw_3d_lut = 0; - dc->caps.color.dpp.ogam_ram = 1; // RGAM on DCN1 - dc->caps.color.dpp.ogam_rom_caps.srgb = 1; - dc->caps.color.dpp.ogam_rom_caps.bt2020 = 1; - dc->caps.color.dpp.ogam_rom_caps.gamma2_2 = 0; - dc->caps.color.dpp.ogam_rom_caps.pq = 0; - dc->caps.color.dpp.ogam_rom_caps.hlg = 0; - dc->caps.color.dpp.ocsc = 1; - - /* no post-blend color operations */ - dc->caps.color.mpc.gamut_remap = 0; - dc->caps.color.mpc.num_3dluts = 0; - dc->caps.color.mpc.shared_3d_lut = 0; - dc->caps.color.mpc.ogam_ram = 0; - dc->caps.color.mpc.ogam_rom_caps.srgb = 0; - dc->caps.color.mpc.ogam_rom_caps.bt2020 = 0; - dc->caps.color.mpc.ogam_rom_caps.gamma2_2 = 0; - dc->caps.color.mpc.ogam_rom_caps.pq = 0; - dc->caps.color.mpc.ogam_rom_caps.hlg = 0; - dc->caps.color.mpc.ocsc = 0; - - if (dc->ctx->dce_environment == DCE_ENV_PRODUCTION_DRV) - dc->debug = debug_defaults_drv; - else - dc->debug = debug_defaults_diags; - - /************************************************* - * Create resources * - *************************************************/ - - pool->base.clock_sources[DCN10_CLK_SRC_PLL0] = - dcn10_clock_source_create(ctx, ctx->dc_bios, - CLOCK_SOURCE_COMBO_PHY_PLL0, - &clk_src_regs[0], false); - pool->base.clock_sources[DCN10_CLK_SRC_PLL1] = - dcn10_clock_source_create(ctx, ctx->dc_bios, - CLOCK_SOURCE_COMBO_PHY_PLL1, - &clk_src_regs[1], false); - pool->base.clock_sources[DCN10_CLK_SRC_PLL2] = - dcn10_clock_source_create(ctx, ctx->dc_bios, - CLOCK_SOURCE_COMBO_PHY_PLL2, - &clk_src_regs[2], false); - - if (dc->ctx->dce_version == DCN_VERSION_1_0) { - pool->base.clock_sources[DCN10_CLK_SRC_PLL3] = - dcn10_clock_source_create(ctx, ctx->dc_bios, - CLOCK_SOURCE_COMBO_PHY_PLL3, - &clk_src_regs[3], false); - } - - pool->base.clk_src_count = DCN10_CLK_SRC_TOTAL; - - if (dc->ctx->dce_version == DCN_VERSION_1_01) - pool->base.clk_src_count = DCN101_CLK_SRC_TOTAL; - - pool->base.dp_clock_source = - dcn10_clock_source_create(ctx, ctx->dc_bios, - CLOCK_SOURCE_ID_DP_DTO, - /* todo: not reuse phy_pll registers */ - &clk_src_regs[0], true); - - for (i = 0; i < pool->base.clk_src_count; i++) { - if (pool->base.clock_sources[i] == NULL) { - dm_error("DC: failed to create clock sources!\n"); - BREAK_TO_DEBUGGER(); - goto fail; - } - } - - pool->base.dmcu = dcn10_dmcu_create(ctx, - &dmcu_regs, - &dmcu_shift, - &dmcu_mask); - if (pool->base.dmcu == NULL) { - dm_error("DC: failed to create dmcu!\n"); - BREAK_TO_DEBUGGER(); - goto fail; - } - - pool->base.abm = dce_abm_create(ctx, - &abm_regs, - &abm_shift, - &abm_mask); - if (pool->base.abm == NULL) { - dm_error("DC: failed to create abm!\n"); - BREAK_TO_DEBUGGER(); - goto fail; - } - - dml_init_instance(&dc->dml, &dcn1_0_soc, &dcn1_0_ip, DML_PROJECT_RAVEN1); - memcpy(dc->dcn_ip, &dcn10_ip_defaults, sizeof(dcn10_ip_defaults)); - memcpy(dc->dcn_soc, &dcn10_soc_defaults, sizeof(dcn10_soc_defaults)); - - DC_FP_START(); - dcn10_resource_construct_fp(dc); - DC_FP_END(); - - if (!dc->config.is_vmin_only_asic) - if (ASICREV_IS_RAVEN2(dc->ctx->asic_id.hw_internal_rev)) - switch (dc->ctx->asic_id.pci_revision_id) { - case PRID_DALI_DE: - case PRID_DALI_DF: - case PRID_DALI_E3: - case PRID_DALI_E4: - case PRID_POLLOCK_94: - case PRID_POLLOCK_95: - case PRID_POLLOCK_E9: - case PRID_POLLOCK_EA: - case PRID_POLLOCK_EB: - dc->config.is_vmin_only_asic = true; - break; - default: - break; - } - - pool->base.pp_smu = dcn10_pp_smu_create(ctx); - - /* - * Right now SMU/PPLIB and DAL all have the AZ D3 force PME notification * - * implemented. So AZ D3 should work.For issue 197007. * - */ - if (pool->base.pp_smu != NULL - && pool->base.pp_smu->rv_funcs.set_pme_wa_enable != NULL) - dc->debug.az_endpoint_mute_only = false; - - - if (!dc->debug.disable_pplib_clock_request) { - /* - * TODO: This is not the proper way to obtain - * fabric_and_dram_bandwidth, should be min(fclk, memclk). - */ - res = dm_pp_get_clock_levels_by_type_with_voltage( - ctx, DM_PP_CLOCK_TYPE_FCLK, &fclks); - - DC_FP_START(); - - if (res) - res = verify_clock_values(&fclks); - - if (res) - dcn_bw_update_from_pplib_fclks(dc, &fclks); - else - BREAK_TO_DEBUGGER(); - - DC_FP_END(); - - res = dm_pp_get_clock_levels_by_type_with_voltage( - ctx, DM_PP_CLOCK_TYPE_DCFCLK, &dcfclks); - - DC_FP_START(); - - if (res) - res = verify_clock_values(&dcfclks); - - if (res) - dcn_bw_update_from_pplib_dcfclks(dc, &dcfclks); - else - BREAK_TO_DEBUGGER(); - - DC_FP_END(); - } - - dcn_bw_sync_calcs_and_dml(dc); - if (!dc->debug.disable_pplib_wm_range) { - dc->res_pool = &pool->base; - DC_FP_START(); - dcn_get_soc_clks( - dc, &min_fclk_khz, &min_dcfclk_khz, &socclk_khz); - DC_FP_END(); - dcn_bw_notify_pplib_of_wm_ranges( - dc, min_fclk_khz, min_dcfclk_khz, socclk_khz); - } - - { - struct irq_service_init_data init_data; - init_data.ctx = dc->ctx; - pool->base.irqs = dal_irq_service_dcn10_create(&init_data); - if (!pool->base.irqs) - goto fail; - } - - /* index to valid pipe resource */ - j = 0; - /* mem input -> ipp -> dpp -> opp -> TG */ - for (i = 0; i < pool->base.pipe_count; i++) { - /* if pipe is disabled, skip instance of HW pipe, - * i.e, skip ASIC register instance - */ - if ((pipe_fuses & (1 << i)) != 0) - continue; - - pool->base.hubps[j] = dcn10_hubp_create(ctx, i); - if (pool->base.hubps[j] == NULL) { - BREAK_TO_DEBUGGER(); - dm_error( - "DC: failed to create memory input!\n"); - goto fail; - } - - pool->base.ipps[j] = dcn10_ipp_create(ctx, i); - if (pool->base.ipps[j] == NULL) { - BREAK_TO_DEBUGGER(); - dm_error( - "DC: failed to create input pixel processor!\n"); - goto fail; - } - - pool->base.dpps[j] = dcn10_dpp_create(ctx, i); - if (pool->base.dpps[j] == NULL) { - BREAK_TO_DEBUGGER(); - dm_error( - "DC: failed to create dpp!\n"); - goto fail; - } - - pool->base.opps[j] = dcn10_opp_create(ctx, i); - if (pool->base.opps[j] == NULL) { - BREAK_TO_DEBUGGER(); - dm_error( - "DC: failed to create output pixel processor!\n"); - goto fail; - } - - pool->base.timing_generators[j] = dcn10_timing_generator_create( - ctx, i); - if (pool->base.timing_generators[j] == NULL) { - BREAK_TO_DEBUGGER(); - dm_error("DC: failed to create tg!\n"); - goto fail; - } - /* check next valid pipe */ - j++; - } - - for (i = 0; i < pool->base.res_cap->num_ddc; i++) { - pool->base.engines[i] = dcn10_aux_engine_create(ctx, i); - if (pool->base.engines[i] == NULL) { - BREAK_TO_DEBUGGER(); - dm_error( - "DC:failed to create aux engine!!\n"); - goto fail; - } - pool->base.hw_i2cs[i] = dcn10_i2c_hw_create(ctx, i); - if (pool->base.hw_i2cs[i] == NULL) { - BREAK_TO_DEBUGGER(); - dm_error( - "DC:failed to create hw i2c!!\n"); - goto fail; - } - pool->base.sw_i2cs[i] = NULL; - } - - /* valid pipe num */ - pool->base.pipe_count = j; - pool->base.timing_generator_count = j; - - /* within dml lib, it is hard code to 4. If ASIC pipe is fused, - * the value may be changed - */ - dc->dml.ip.max_num_dpp = pool->base.pipe_count; - dc->dcn_ip->max_num_dpp = pool->base.pipe_count; - - pool->base.mpc = dcn10_mpc_create(ctx); - if (pool->base.mpc == NULL) { - BREAK_TO_DEBUGGER(); - dm_error("DC: failed to create mpc!\n"); - goto fail; - } - - pool->base.hubbub = dcn10_hubbub_create(ctx); - if (pool->base.hubbub == NULL) { - BREAK_TO_DEBUGGER(); - dm_error("DC: failed to create hubbub!\n"); - goto fail; - } - - if (!resource_construct(num_virtual_links, dc, &pool->base, - &res_create_funcs)) - goto fail; - - dcn10_hw_sequencer_construct(dc); - dc->caps.max_planes = pool->base.pipe_count; - - for (i = 0; i < dc->caps.max_planes; ++i) - dc->caps.planes[i] = plane_cap; - - dc->cap_funcs = cap_funcs; - - return true; - -fail: - - dcn10_resource_destruct(pool); - - return false; -} - -struct resource_pool *dcn10_create_resource_pool( - const struct dc_init_data *init_data, - struct dc *dc) -{ - struct dcn10_resource_pool *pool = - kzalloc(sizeof(struct dcn10_resource_pool), GFP_KERNEL); - - if (!pool) - return NULL; - - if (dcn10_resource_construct(init_data->num_virtual_links, dc, pool)) - return &pool->base; - - kfree(pool); - BREAK_TO_DEBUGGER(); - return NULL; -} diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.h b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.h deleted file mode 100644 index bf8e33cd8147..000000000000 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.h +++ /dev/null @@ -1,56 +0,0 @@ -/* -* Copyright 2016 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_RESOURCE_DCN10_H__ -#define __DC_RESOURCE_DCN10_H__ - -#include "core_types.h" -#include "dml/dcn10/dcn10_fpu.h" - -#define TO_DCN10_RES_POOL(pool)\ - container_of(pool, struct dcn10_resource_pool, base) - -struct dc; -struct resource_pool; -struct _vcs_dpi_display_pipe_params_st; - -extern struct _vcs_dpi_ip_params_st dcn1_0_ip; -extern struct _vcs_dpi_soc_bounding_box_st dcn1_0_soc; - -struct dcn10_resource_pool { - struct resource_pool base; -}; -struct resource_pool *dcn10_create_resource_pool( - const struct dc_init_data *init_data, - struct dc *dc); - -struct stream_encoder *dcn10_find_first_free_match_stream_enc_for_link( - struct resource_context *res_ctx, - const struct resource_pool *pool, - struct dc_stream_state *stream); - - -#endif /* __DC_RESOURCE_DCN10_H__ */ - diff --git a/drivers/gpu/drm/amd/display/dc/dcn20/Makefile b/drivers/gpu/drm/amd/display/dc/dcn20/Makefile index d7dc9696a8c8..1cac1eca8111 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn20/Makefile +++ b/drivers/gpu/drm/amd/display/dc/dcn20/Makefile @@ -2,7 +2,7 @@ # # Makefile for DCN. -DCN20 = dcn20_resource.o dcn20_init.o dcn20_dpp.o dcn20_dpp_cm.o dcn20_hubp.o \ +DCN20 = dcn20_init.o dcn20_dpp.o dcn20_dpp_cm.o dcn20_hubp.o \ dcn20_mpc.o dcn20_opp.o dcn20_hubbub.o dcn20_optc.o dcn20_mmhubbub.o \ dcn20_stream_encoder.o dcn20_link_encoder.o dcn20_dccg.o \ dcn20_vmid.o dcn20_dwb.o dcn20_dwb_scl.o diff --git a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_resource.c b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_resource.c deleted file mode 100644 index 0a422fbb14bc..000000000000 --- a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_resource.c +++ /dev/null @@ -1,2789 +0,0 @@ -/* -* Copyright 2016 Advanced Micro Devices, Inc. - * Copyright 2019 Raptor Engineering, LLC - * - * 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 - -#include "dm_services.h" -#include "dc.h" - -#include "dcn20_init.h" - -#include "resource.h" -#include "include/irq_service_interface.h" -#include "dcn20/dcn20_resource.h" - -#include "dml/dcn20/dcn20_fpu.h" - -#include "dcn10/dcn10_hubp.h" -#include "dcn10/dcn10_ipp.h" -#include "dcn20_hubbub.h" -#include "dcn20_mpc.h" -#include "dcn20_hubp.h" -#include "irq/dcn20/irq_service_dcn20.h" -#include "dcn20_dpp.h" -#include "dcn20_optc.h" -#include "dcn20/dcn20_hwseq.h" -#include "dce110/dce110_hwseq.h" -#include "dcn10/dcn10_resource.h" -#include "dcn20_opp.h" - -#include "dcn20_dsc.h" - -#include "dcn20_link_encoder.h" -#include "dcn20_stream_encoder.h" -#include "dce/dce_clock_source.h" -#include "dce/dce_audio.h" -#include "dce/dce_hwseq.h" -#include "virtual/virtual_stream_encoder.h" -#include "dce110/dce110_resource.h" -#include "dml/display_mode_vba.h" -#include "dcn20_dccg.h" -#include "dcn20_vmid.h" -#include "dce/dce_panel_cntl.h" - -#include "navi10_ip_offset.h" - -#include "dcn/dcn_2_0_0_offset.h" -#include "dcn/dcn_2_0_0_sh_mask.h" -#include "dpcs/dpcs_2_0_0_offset.h" -#include "dpcs/dpcs_2_0_0_sh_mask.h" - -#include "nbio/nbio_2_3_offset.h" - -#include "dcn20/dcn20_dwb.h" -#include "dcn20/dcn20_mmhubbub.h" - -#include "mmhub/mmhub_2_0_0_offset.h" -#include "mmhub/mmhub_2_0_0_sh_mask.h" - -#include "reg_helper.h" -#include "dce/dce_abm.h" -#include "dce/dce_dmcu.h" -#include "dce/dce_aux.h" -#include "dce/dce_i2c.h" -#include "vm_helper.h" -#include "link_enc_cfg.h" - -#include "amdgpu_socbb.h" - -#include "link.h" -#define DC_LOGGER_INIT(logger) - -#ifndef mmDP0_DP_DPHY_INTERNAL_CTRL - #define mmDP0_DP_DPHY_INTERNAL_CTRL 0x210f - #define mmDP0_DP_DPHY_INTERNAL_CTRL_BASE_IDX 2 - #define mmDP1_DP_DPHY_INTERNAL_CTRL 0x220f - #define mmDP1_DP_DPHY_INTERNAL_CTRL_BASE_IDX 2 - #define mmDP2_DP_DPHY_INTERNAL_CTRL 0x230f - #define mmDP2_DP_DPHY_INTERNAL_CTRL_BASE_IDX 2 - #define mmDP3_DP_DPHY_INTERNAL_CTRL 0x240f - #define mmDP3_DP_DPHY_INTERNAL_CTRL_BASE_IDX 2 - #define mmDP4_DP_DPHY_INTERNAL_CTRL 0x250f - #define mmDP4_DP_DPHY_INTERNAL_CTRL_BASE_IDX 2 - #define mmDP5_DP_DPHY_INTERNAL_CTRL 0x260f - #define mmDP5_DP_DPHY_INTERNAL_CTRL_BASE_IDX 2 - #define mmDP6_DP_DPHY_INTERNAL_CTRL 0x270f - #define mmDP6_DP_DPHY_INTERNAL_CTRL_BASE_IDX 2 -#endif - - -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_PLL5, - DCN20_CLK_SRC_TOTAL -}; - -/* begin ********************* - * macros to expend register list macro defined in HW object header file */ - -/* DCN */ -#define BASE_INNER(seg) DCN_BASE__INST0_SEG ## seg - -#define BASE(seg) BASE_INNER(seg) - -#define SR(reg_name)\ - .reg_name = BASE(mm ## reg_name ## _BASE_IDX) + \ - mm ## reg_name - -#define SRI(reg_name, block, id)\ - .reg_name = BASE(mm ## block ## id ## _ ## reg_name ## _BASE_IDX) + \ - mm ## block ## id ## _ ## reg_name - -#define SRI2_DWB(reg_name, block, id)\ - .reg_name = BASE(mm ## reg_name ## _BASE_IDX) + \ - mm ## reg_name -#define SF_DWB(reg_name, field_name, post_fix)\ - .field_name = reg_name ## __ ## field_name ## post_fix - -#define SF_DWB2(reg_name, block, id, field_name, post_fix) \ - .field_name = reg_name ## __ ## field_name ## post_fix - -#define SRIR(var_name, reg_name, block, id)\ - .var_name = BASE(mm ## block ## id ## _ ## reg_name ## _BASE_IDX) + \ - mm ## block ## id ## _ ## reg_name - -#define SRII(reg_name, block, id)\ - .reg_name[id] = BASE(mm ## block ## id ## _ ## reg_name ## _BASE_IDX) + \ - mm ## block ## id ## _ ## reg_name - -#define DCCG_SRII(reg_name, block, id)\ - .block ## _ ## reg_name[id] = BASE(mm ## block ## id ## _ ## reg_name ## _BASE_IDX) + \ - mm ## block ## id ## _ ## reg_name - -#define VUPDATE_SRII(reg_name, block, id)\ - .reg_name[id] = BASE(mm ## reg_name ## _ ## block ## id ## _BASE_IDX) + \ - mm ## reg_name ## _ ## block ## id - -/* NBIO */ -#define NBIO_BASE_INNER(seg) \ - NBIO_BASE__INST0_SEG ## seg - -#define NBIO_BASE(seg) \ - NBIO_BASE_INNER(seg) - -#define NBIO_SR(reg_name)\ - .reg_name = NBIO_BASE(mm ## reg_name ## _BASE_IDX) + \ - mm ## reg_name - -/* MMHUB */ -#define MMHUB_BASE_INNER(seg) \ - MMHUB_BASE__INST0_SEG ## seg - -#define MMHUB_BASE(seg) \ - MMHUB_BASE_INNER(seg) - -#define MMHUB_SR(reg_name)\ - .reg_name = MMHUB_BASE(mmMM ## reg_name ## _BASE_IDX) + \ - mmMM ## reg_name - -static const struct bios_registers bios_regs = { - NBIO_SR(BIOS_SCRATCH_3), - NBIO_SR(BIOS_SCRATCH_6) -}; - -#define clk_src_regs(index, pllid)\ -[index] = {\ - CS_COMMON_REG_LIST_DCN2_0(index, pllid),\ -} - -static const struct dce110_clk_src_regs clk_src_regs[] = { - clk_src_regs(0, A), - clk_src_regs(1, B), - clk_src_regs(2, C), - clk_src_regs(3, D), - clk_src_regs(4, E), - clk_src_regs(5, F) -}; - -static const struct dce110_clk_src_shift cs_shift = { - CS_COMMON_MASK_SH_LIST_DCN2_0(__SHIFT) -}; - -static const struct dce110_clk_src_mask cs_mask = { - CS_COMMON_MASK_SH_LIST_DCN2_0(_MASK) -}; - -static const struct dce_dmcu_registers dmcu_regs = { - DMCU_DCN10_REG_LIST() -}; - -static const struct dce_dmcu_shift dmcu_shift = { - DMCU_MASK_SH_LIST_DCN10(__SHIFT) -}; - -static const struct dce_dmcu_mask dmcu_mask = { - DMCU_MASK_SH_LIST_DCN10(_MASK) -}; - -static const struct dce_abm_registers abm_regs = { - ABM_DCN20_REG_LIST() -}; - -static const struct dce_abm_shift abm_shift = { - ABM_MASK_SH_LIST_DCN20(__SHIFT) -}; - -static const struct dce_abm_mask abm_mask = { - ABM_MASK_SH_LIST_DCN20(_MASK) -}; - -#define audio_regs(id)\ -[id] = {\ - AUD_COMMON_REG_LIST(id)\ -} - -static const struct dce_audio_registers audio_regs[] = { - audio_regs(0), - audio_regs(1), - audio_regs(2), - audio_regs(3), - audio_regs(4), - audio_regs(5), - audio_regs(6), -}; - -#define DCE120_AUD_COMMON_MASK_SH_LIST(mask_sh)\ - SF(AZF0ENDPOINT0_AZALIA_F0_CODEC_ENDPOINT_INDEX, AZALIA_ENDPOINT_REG_INDEX, mask_sh),\ - SF(AZF0ENDPOINT0_AZALIA_F0_CODEC_ENDPOINT_DATA, AZALIA_ENDPOINT_REG_DATA, mask_sh),\ - AUD_COMMON_MASK_SH_LIST_BASE(mask_sh) - -static const struct dce_audio_shift audio_shift = { - DCE120_AUD_COMMON_MASK_SH_LIST(__SHIFT) -}; - -static const struct dce_audio_mask audio_mask = { - DCE120_AUD_COMMON_MASK_SH_LIST(_MASK) -}; - -#define stream_enc_regs(id)\ -[id] = {\ - SE_DCN2_REG_LIST(id)\ -} - -static const struct dcn10_stream_enc_registers stream_enc_regs[] = { - stream_enc_regs(0), - stream_enc_regs(1), - stream_enc_regs(2), - stream_enc_regs(3), - stream_enc_regs(4), - stream_enc_regs(5), -}; - -static const struct dcn10_stream_encoder_shift se_shift = { - SE_COMMON_MASK_SH_LIST_DCN20(__SHIFT) -}; - -static const struct dcn10_stream_encoder_mask se_mask = { - SE_COMMON_MASK_SH_LIST_DCN20(_MASK) -}; - - -#define aux_regs(id)\ -[id] = {\ - DCN2_AUX_REG_LIST(id)\ -} - -static const struct dcn10_link_enc_aux_registers link_enc_aux_regs[] = { - aux_regs(0), - aux_regs(1), - aux_regs(2), - aux_regs(3), - aux_regs(4), - aux_regs(5) -}; - -#define hpd_regs(id)\ -[id] = {\ - HPD_REG_LIST(id)\ -} - -static const struct dcn10_link_enc_hpd_registers link_enc_hpd_regs[] = { - hpd_regs(0), - hpd_regs(1), - hpd_regs(2), - hpd_regs(3), - hpd_regs(4), - hpd_regs(5) -}; - -#define link_regs(id, phyid)\ -[id] = {\ - LE_DCN10_REG_LIST(id), \ - UNIPHY_DCN2_REG_LIST(phyid), \ - DPCS_DCN2_REG_LIST(id), \ - SRI(DP_DPHY_INTERNAL_CTRL, DP, id) \ -} - -static const struct dcn10_link_enc_registers link_enc_regs[] = { - link_regs(0, A), - link_regs(1, B), - link_regs(2, C), - link_regs(3, D), - link_regs(4, E), - link_regs(5, F) -}; - -static const struct dcn10_link_enc_shift le_shift = { - LINK_ENCODER_MASK_SH_LIST_DCN20(__SHIFT),\ - DPCS_DCN2_MASK_SH_LIST(__SHIFT) -}; - -static const struct dcn10_link_enc_mask le_mask = { - LINK_ENCODER_MASK_SH_LIST_DCN20(_MASK),\ - DPCS_DCN2_MASK_SH_LIST(_MASK) -}; - -static const struct dce_panel_cntl_registers panel_cntl_regs[] = { - { DCN_PANEL_CNTL_REG_LIST() } -}; - -static const struct dce_panel_cntl_shift panel_cntl_shift = { - DCE_PANEL_CNTL_MASK_SH_LIST(__SHIFT) -}; - -static const struct dce_panel_cntl_mask panel_cntl_mask = { - DCE_PANEL_CNTL_MASK_SH_LIST(_MASK) -}; - -#define ipp_regs(id)\ -[id] = {\ - IPP_REG_LIST_DCN20(id),\ -} - -static const struct dcn10_ipp_registers ipp_regs[] = { - ipp_regs(0), - ipp_regs(1), - ipp_regs(2), - ipp_regs(3), - ipp_regs(4), - ipp_regs(5), -}; - -static const struct dcn10_ipp_shift ipp_shift = { - IPP_MASK_SH_LIST_DCN20(__SHIFT) -}; - -static const struct dcn10_ipp_mask ipp_mask = { - IPP_MASK_SH_LIST_DCN20(_MASK), -}; - -#define opp_regs(id)\ -[id] = {\ - OPP_REG_LIST_DCN20(id),\ -} - -static const struct dcn20_opp_registers opp_regs[] = { - opp_regs(0), - opp_regs(1), - opp_regs(2), - opp_regs(3), - opp_regs(4), - opp_regs(5), -}; - -static const struct dcn20_opp_shift opp_shift = { - OPP_MASK_SH_LIST_DCN20(__SHIFT) -}; - -static const struct dcn20_opp_mask opp_mask = { - OPP_MASK_SH_LIST_DCN20(_MASK) -}; - -#define aux_engine_regs(id)\ -[id] = {\ - AUX_COMMON_REG_LIST0(id), \ - .AUXN_IMPCAL = 0, \ - .AUXP_IMPCAL = 0, \ - .AUX_RESET_MASK = DP_AUX0_AUX_CONTROL__AUX_RESET_MASK, \ -} - -static const struct dce110_aux_registers aux_engine_regs[] = { - aux_engine_regs(0), - aux_engine_regs(1), - aux_engine_regs(2), - aux_engine_regs(3), - aux_engine_regs(4), - aux_engine_regs(5) -}; - -#define tf_regs(id)\ -[id] = {\ - TF_REG_LIST_DCN20(id),\ - TF_REG_LIST_DCN20_COMMON_APPEND(id),\ -} - -static const struct dcn2_dpp_registers tf_regs[] = { - tf_regs(0), - tf_regs(1), - tf_regs(2), - tf_regs(3), - tf_regs(4), - tf_regs(5), -}; - -static const struct dcn2_dpp_shift tf_shift = { - TF_REG_LIST_SH_MASK_DCN20(__SHIFT), - TF_DEBUG_REG_LIST_SH_DCN20 -}; - -static const struct dcn2_dpp_mask tf_mask = { - TF_REG_LIST_SH_MASK_DCN20(_MASK), - TF_DEBUG_REG_LIST_MASK_DCN20 -}; - -#define dwbc_regs_dcn2(id)\ -[id] = {\ - DWBC_COMMON_REG_LIST_DCN2_0(id),\ - } - -static const struct dcn20_dwbc_registers dwbc20_regs[] = { - dwbc_regs_dcn2(0), -}; - -static const struct dcn20_dwbc_shift dwbc20_shift = { - DWBC_COMMON_MASK_SH_LIST_DCN2_0(__SHIFT) -}; - -static const struct dcn20_dwbc_mask dwbc20_mask = { - DWBC_COMMON_MASK_SH_LIST_DCN2_0(_MASK) -}; - -#define mcif_wb_regs_dcn2(id)\ -[id] = {\ - MCIF_WB_COMMON_REG_LIST_DCN2_0(id),\ - } - -static const struct dcn20_mmhubbub_registers mcif_wb20_regs[] = { - mcif_wb_regs_dcn2(0), -}; - -static const struct dcn20_mmhubbub_shift mcif_wb20_shift = { - MCIF_WB_COMMON_MASK_SH_LIST_DCN2_0(__SHIFT) -}; - -static const struct dcn20_mmhubbub_mask mcif_wb20_mask = { - MCIF_WB_COMMON_MASK_SH_LIST_DCN2_0(_MASK) -}; - -static const struct dcn20_mpc_registers mpc_regs = { - MPC_REG_LIST_DCN2_0(0), - MPC_REG_LIST_DCN2_0(1), - MPC_REG_LIST_DCN2_0(2), - MPC_REG_LIST_DCN2_0(3), - MPC_REG_LIST_DCN2_0(4), - MPC_REG_LIST_DCN2_0(5), - MPC_OUT_MUX_REG_LIST_DCN2_0(0), - MPC_OUT_MUX_REG_LIST_DCN2_0(1), - MPC_OUT_MUX_REG_LIST_DCN2_0(2), - MPC_OUT_MUX_REG_LIST_DCN2_0(3), - MPC_OUT_MUX_REG_LIST_DCN2_0(4), - MPC_OUT_MUX_REG_LIST_DCN2_0(5), - MPC_DBG_REG_LIST_DCN2_0() -}; - -static const struct dcn20_mpc_shift mpc_shift = { - MPC_COMMON_MASK_SH_LIST_DCN2_0(__SHIFT), - MPC_DEBUG_REG_LIST_SH_DCN20 -}; - -static const struct dcn20_mpc_mask mpc_mask = { - MPC_COMMON_MASK_SH_LIST_DCN2_0(_MASK), - MPC_DEBUG_REG_LIST_MASK_DCN20 -}; - -#define tg_regs(id)\ -[id] = {TG_COMMON_REG_LIST_DCN2_0(id)} - - -static const struct dcn_optc_registers tg_regs[] = { - tg_regs(0), - tg_regs(1), - tg_regs(2), - tg_regs(3), - tg_regs(4), - tg_regs(5) -}; - -static const struct dcn_optc_shift tg_shift = { - TG_COMMON_MASK_SH_LIST_DCN2_0(__SHIFT) -}; - -static const struct dcn_optc_mask tg_mask = { - TG_COMMON_MASK_SH_LIST_DCN2_0(_MASK) -}; - -#define hubp_regs(id)\ -[id] = {\ - HUBP_REG_LIST_DCN20(id)\ -} - -static const struct dcn_hubp2_registers hubp_regs[] = { - hubp_regs(0), - hubp_regs(1), - hubp_regs(2), - hubp_regs(3), - hubp_regs(4), - hubp_regs(5) -}; - -static const struct dcn_hubp2_shift hubp_shift = { - HUBP_MASK_SH_LIST_DCN20(__SHIFT) -}; - -static const struct dcn_hubp2_mask hubp_mask = { - HUBP_MASK_SH_LIST_DCN20(_MASK) -}; - -static const struct dcn_hubbub_registers hubbub_reg = { - HUBBUB_REG_LIST_DCN20(0) -}; - -static const struct dcn_hubbub_shift hubbub_shift = { - HUBBUB_MASK_SH_LIST_DCN20(__SHIFT) -}; - -static const struct dcn_hubbub_mask hubbub_mask = { - HUBBUB_MASK_SH_LIST_DCN20(_MASK) -}; - -#define vmid_regs(id)\ -[id] = {\ - DCN20_VMID_REG_LIST(id)\ -} - -static const struct dcn_vmid_registers vmid_regs[] = { - vmid_regs(0), - vmid_regs(1), - vmid_regs(2), - vmid_regs(3), - vmid_regs(4), - vmid_regs(5), - vmid_regs(6), - vmid_regs(7), - vmid_regs(8), - vmid_regs(9), - vmid_regs(10), - vmid_regs(11), - vmid_regs(12), - vmid_regs(13), - vmid_regs(14), - vmid_regs(15) -}; - -static const struct dcn20_vmid_shift vmid_shifts = { - DCN20_VMID_MASK_SH_LIST(__SHIFT) -}; - -static const struct dcn20_vmid_mask vmid_masks = { - DCN20_VMID_MASK_SH_LIST(_MASK) -}; - -static const struct dce110_aux_registers_shift aux_shift = { - DCN_AUX_MASK_SH_LIST(__SHIFT) -}; - -static const struct dce110_aux_registers_mask aux_mask = { - DCN_AUX_MASK_SH_LIST(_MASK) -}; - -static int map_transmitter_id_to_phy_instance( - enum transmitter transmitter) -{ - switch (transmitter) { - case TRANSMITTER_UNIPHY_A: - return 0; - break; - case TRANSMITTER_UNIPHY_B: - return 1; - break; - case TRANSMITTER_UNIPHY_C: - return 2; - break; - case TRANSMITTER_UNIPHY_D: - return 3; - break; - case TRANSMITTER_UNIPHY_E: - return 4; - break; - case TRANSMITTER_UNIPHY_F: - return 5; - break; - default: - ASSERT(0); - return 0; - } -} - -#define dsc_regsDCN20(id)\ -[id] = {\ - DSC_REG_LIST_DCN20(id)\ -} - -static const struct dcn20_dsc_registers dsc_regs[] = { - dsc_regsDCN20(0), - dsc_regsDCN20(1), - dsc_regsDCN20(2), - dsc_regsDCN20(3), - dsc_regsDCN20(4), - dsc_regsDCN20(5) -}; - -static const struct dcn20_dsc_shift dsc_shift = { - DSC_REG_LIST_SH_MASK_DCN20(__SHIFT) -}; - -static const struct dcn20_dsc_mask dsc_mask = { - DSC_REG_LIST_SH_MASK_DCN20(_MASK) -}; - -static const struct dccg_registers dccg_regs = { - DCCG_REG_LIST_DCN2() -}; - -static const struct dccg_shift dccg_shift = { - DCCG_MASK_SH_LIST_DCN2(__SHIFT) -}; - -static const struct dccg_mask dccg_mask = { - DCCG_MASK_SH_LIST_DCN2(_MASK) -}; - -static const struct resource_caps res_cap_nv10 = { - .num_timing_generator = 6, - .num_opp = 6, - .num_video_plane = 6, - .num_audio = 7, - .num_stream_encoder = 6, - .num_pll = 6, - .num_dwb = 1, - .num_ddc = 6, - .num_vmid = 16, - .num_dsc = 6, -}; - -static const struct dc_plane_cap plane_cap = { - .type = DC_PLANE_TYPE_DCN_UNIVERSAL, - .per_pixel_alpha = true, - - .pixel_format_support = { - .argb8888 = true, - .nv12 = true, - .fp16 = true, - .p010 = true - }, - - .max_upscale_factor = { - .argb8888 = 16000, - .nv12 = 16000, - .fp16 = 1 - }, - - .max_downscale_factor = { - .argb8888 = 250, - .nv12 = 250, - .fp16 = 1 - }, - 16, - 16 -}; -static const struct resource_caps res_cap_nv14 = { - .num_timing_generator = 5, - .num_opp = 5, - .num_video_plane = 5, - .num_audio = 6, - .num_stream_encoder = 5, - .num_pll = 5, - .num_dwb = 1, - .num_ddc = 5, - .num_vmid = 16, - .num_dsc = 5, -}; - -static const struct dc_debug_options debug_defaults_drv = { - .disable_dmcu = false, - .force_abm_enable = false, - .timing_trace = false, - .clock_trace = true, - .disable_pplib_clock_request = true, - .pipe_split_policy = MPC_SPLIT_AVOID_MULT_DISP, - .force_single_disp_pipe_split = false, - .disable_dcc = DCC_ENABLE, - .vsr_support = true, - .performance_trace = false, - .max_downscale_src_width = 5120,/*upto 5K*/ - .disable_pplib_wm_range = false, - .scl_reset_length10 = true, - .sanity_checks = false, - .underflow_assert_delay_us = 0xFFFFFFFF, - .enable_legacy_fast_update = true, - .using_dml2 = false, -}; - -void dcn20_dpp_destroy(struct dpp **dpp) -{ - kfree(TO_DCN20_DPP(*dpp)); - *dpp = NULL; -} - -struct dpp *dcn20_dpp_create( - struct dc_context *ctx, - uint32_t inst) -{ - struct dcn20_dpp *dpp = - kzalloc(sizeof(struct dcn20_dpp), GFP_ATOMIC); - - if (!dpp) - return NULL; - - if (dpp2_construct(dpp, ctx, inst, - &tf_regs[inst], &tf_shift, &tf_mask)) - return &dpp->base; - - BREAK_TO_DEBUGGER(); - kfree(dpp); - return NULL; -} - -struct input_pixel_processor *dcn20_ipp_create( - struct dc_context *ctx, uint32_t inst) -{ - struct dcn10_ipp *ipp = - kzalloc(sizeof(struct dcn10_ipp), GFP_ATOMIC); - - if (!ipp) { - BREAK_TO_DEBUGGER(); - return NULL; - } - - dcn20_ipp_construct(ipp, ctx, inst, - &ipp_regs[inst], &ipp_shift, &ipp_mask); - return &ipp->base; -} - - -struct output_pixel_processor *dcn20_opp_create( - struct dc_context *ctx, uint32_t inst) -{ - struct dcn20_opp *opp = - kzalloc(sizeof(struct dcn20_opp), GFP_ATOMIC); - - if (!opp) { - BREAK_TO_DEBUGGER(); - return NULL; - } - - dcn20_opp_construct(opp, ctx, inst, - &opp_regs[inst], &opp_shift, &opp_mask); - return &opp->base; -} - -struct dce_aux *dcn20_aux_engine_create( - struct dc_context *ctx, - uint32_t inst) -{ - struct aux_engine_dce110 *aux_engine = - kzalloc(sizeof(struct aux_engine_dce110), GFP_ATOMIC); - - if (!aux_engine) - return NULL; - - dce110_aux_engine_construct(aux_engine, ctx, inst, - SW_AUX_TIMEOUT_PERIOD_MULTIPLIER * AUX_TIMEOUT_PERIOD, - &aux_engine_regs[inst], - &aux_mask, - &aux_shift, - ctx->dc->caps.extended_aux_timeout_support); - - return &aux_engine->base; -} -#define i2c_inst_regs(id) { I2C_HW_ENGINE_COMMON_REG_LIST(id) } - -static const struct dce_i2c_registers i2c_hw_regs[] = { - i2c_inst_regs(1), - i2c_inst_regs(2), - i2c_inst_regs(3), - i2c_inst_regs(4), - i2c_inst_regs(5), - i2c_inst_regs(6), -}; - -static const struct dce_i2c_shift i2c_shifts = { - I2C_COMMON_MASK_SH_LIST_DCN2(__SHIFT) -}; - -static const struct dce_i2c_mask i2c_masks = { - I2C_COMMON_MASK_SH_LIST_DCN2(_MASK) -}; - -struct dce_i2c_hw *dcn20_i2c_hw_create( - struct dc_context *ctx, - uint32_t inst) -{ - struct dce_i2c_hw *dce_i2c_hw = - kzalloc(sizeof(struct dce_i2c_hw), GFP_ATOMIC); - - if (!dce_i2c_hw) - return NULL; - - dcn2_i2c_hw_construct(dce_i2c_hw, ctx, inst, - &i2c_hw_regs[inst], &i2c_shifts, &i2c_masks); - - return dce_i2c_hw; -} -struct mpc *dcn20_mpc_create(struct dc_context *ctx) -{ - struct dcn20_mpc *mpc20 = kzalloc(sizeof(struct dcn20_mpc), - GFP_ATOMIC); - - if (!mpc20) - return NULL; - - dcn20_mpc_construct(mpc20, ctx, - &mpc_regs, - &mpc_shift, - &mpc_mask, - 6); - - return &mpc20->base; -} - -struct hubbub *dcn20_hubbub_create(struct dc_context *ctx) -{ - int i; - struct dcn20_hubbub *hubbub = kzalloc(sizeof(struct dcn20_hubbub), - GFP_ATOMIC); - - if (!hubbub) - return NULL; - - hubbub2_construct(hubbub, ctx, - &hubbub_reg, - &hubbub_shift, - &hubbub_mask); - - for (i = 0; i < res_cap_nv10.num_vmid; i++) { - struct dcn20_vmid *vmid = &hubbub->vmid[i]; - - vmid->ctx = ctx; - - vmid->regs = &vmid_regs[i]; - vmid->shifts = &vmid_shifts; - vmid->masks = &vmid_masks; - } - - return &hubbub->base; -} - -struct timing_generator *dcn20_timing_generator_create( - struct dc_context *ctx, - uint32_t instance) -{ - struct optc *tgn10 = - kzalloc(sizeof(struct optc), GFP_ATOMIC); - - if (!tgn10) - return NULL; - - tgn10->base.inst = instance; - tgn10->base.ctx = ctx; - - tgn10->tg_regs = &tg_regs[instance]; - tgn10->tg_shift = &tg_shift; - tgn10->tg_mask = &tg_mask; - - dcn20_timing_generator_init(tgn10); - - return &tgn10->base; -} - -static const struct encoder_feature_support link_enc_feature = { - .max_hdmi_deep_color = COLOR_DEPTH_121212, - .max_hdmi_pixel_clock = 600000, - .hdmi_ycbcr420_supported = true, - .dp_ycbcr420_supported = true, - .fec_supported = true, - .flags.bits.IS_HBR2_CAPABLE = true, - .flags.bits.IS_HBR3_CAPABLE = true, - .flags.bits.IS_TPS3_CAPABLE = true, - .flags.bits.IS_TPS4_CAPABLE = true -}; - -struct link_encoder *dcn20_link_encoder_create( - struct dc_context *ctx, - const struct encoder_init_data *enc_init_data) -{ - struct dcn20_link_encoder *enc20 = - kzalloc(sizeof(struct dcn20_link_encoder), GFP_KERNEL); - int link_regs_id; - - if (!enc20) - return NULL; - - link_regs_id = - map_transmitter_id_to_phy_instance(enc_init_data->transmitter); - - dcn20_link_encoder_construct(enc20, - enc_init_data, - &link_enc_feature, - &link_enc_regs[link_regs_id], - &link_enc_aux_regs[enc_init_data->channel - 1], - &link_enc_hpd_regs[enc_init_data->hpd_source], - &le_shift, - &le_mask); - - return &enc20->enc10.base; -} - -static struct panel_cntl *dcn20_panel_cntl_create(const struct panel_cntl_init_data *init_data) -{ - struct dce_panel_cntl *panel_cntl = - kzalloc(sizeof(struct dce_panel_cntl), GFP_KERNEL); - - if (!panel_cntl) - return NULL; - - dce_panel_cntl_construct(panel_cntl, - init_data, - &panel_cntl_regs[init_data->inst], - &panel_cntl_shift, - &panel_cntl_mask); - - return &panel_cntl->base; -} - -static struct clock_source *dcn20_clock_source_create( - struct dc_context *ctx, - struct dc_bios *bios, - enum clock_source_id id, - const struct dce110_clk_src_regs *regs, - bool dp_clk_src) -{ - struct dce110_clk_src *clk_src = - kzalloc(sizeof(struct dce110_clk_src), GFP_ATOMIC); - - if (!clk_src) - return NULL; - - if (dcn20_clk_src_construct(clk_src, ctx, bios, id, - regs, &cs_shift, &cs_mask)) { - clk_src->base.dp_clk_src = dp_clk_src; - return &clk_src->base; - } - - kfree(clk_src); - BREAK_TO_DEBUGGER(); - return NULL; -} - -static void read_dce_straps( - struct dc_context *ctx, - struct resource_straps *straps) -{ - generic_reg_get(ctx, mmDC_PINSTRAPS + BASE(mmDC_PINSTRAPS_BASE_IDX), - FN(DC_PINSTRAPS, DC_PINSTRAPS_AUDIO), &straps->dc_pinstraps_audio); -} - -static struct audio *dcn20_create_audio( - struct dc_context *ctx, unsigned int inst) -{ - return dce_audio_create(ctx, inst, - &audio_regs[inst], &audio_shift, &audio_mask); -} - -struct stream_encoder *dcn20_stream_encoder_create( - enum engine_id eng_id, - struct dc_context *ctx) -{ - struct dcn10_stream_encoder *enc1 = - kzalloc(sizeof(struct dcn10_stream_encoder), GFP_KERNEL); - - if (!enc1) - return NULL; - - if (ASICREV_IS_NAVI14_M(ctx->asic_id.hw_internal_rev)) { - if (eng_id >= ENGINE_ID_DIGD) - eng_id++; - } - - dcn20_stream_encoder_construct(enc1, ctx, ctx->dc_bios, eng_id, - &stream_enc_regs[eng_id], - &se_shift, &se_mask); - - return &enc1->base; -} - -static const struct dce_hwseq_registers hwseq_reg = { - HWSEQ_DCN2_REG_LIST() -}; - -static const struct dce_hwseq_shift hwseq_shift = { - HWSEQ_DCN2_MASK_SH_LIST(__SHIFT) -}; - -static const struct dce_hwseq_mask hwseq_mask = { - HWSEQ_DCN2_MASK_SH_LIST(_MASK) -}; - -struct dce_hwseq *dcn20_hwseq_create( - struct dc_context *ctx) -{ - struct dce_hwseq *hws = kzalloc(sizeof(struct dce_hwseq), GFP_KERNEL); - - if (hws) { - hws->ctx = ctx; - hws->regs = &hwseq_reg; - hws->shifts = &hwseq_shift; - hws->masks = &hwseq_mask; - } - return hws; -} - -static const struct resource_create_funcs res_create_funcs = { - .read_dce_straps = read_dce_straps, - .create_audio = dcn20_create_audio, - .create_stream_encoder = dcn20_stream_encoder_create, - .create_hwseq = dcn20_hwseq_create, -}; - -static void dcn20_pp_smu_destroy(struct pp_smu_funcs **pp_smu); - -void dcn20_clock_source_destroy(struct clock_source **clk_src) -{ - kfree(TO_DCE110_CLK_SRC(*clk_src)); - *clk_src = NULL; -} - - -struct display_stream_compressor *dcn20_dsc_create( - struct dc_context *ctx, uint32_t inst) -{ - struct dcn20_dsc *dsc = - kzalloc(sizeof(struct dcn20_dsc), GFP_ATOMIC); - - if (!dsc) { - BREAK_TO_DEBUGGER(); - return NULL; - } - - dsc2_construct(dsc, ctx, inst, &dsc_regs[inst], &dsc_shift, &dsc_mask); - return &dsc->base; -} - -void dcn20_dsc_destroy(struct display_stream_compressor **dsc) -{ - kfree(container_of(*dsc, struct dcn20_dsc, base)); - *dsc = NULL; -} - - -static void dcn20_resource_destruct(struct dcn20_resource_pool *pool) -{ - unsigned int i; - - for (i = 0; i < pool->base.stream_enc_count; i++) { - if (pool->base.stream_enc[i] != NULL) { - kfree(DCN10STRENC_FROM_STRENC(pool->base.stream_enc[i])); - pool->base.stream_enc[i] = NULL; - } - } - - for (i = 0; i < pool->base.res_cap->num_dsc; i++) { - if (pool->base.dscs[i] != NULL) - dcn20_dsc_destroy(&pool->base.dscs[i]); - } - - if (pool->base.mpc != NULL) { - kfree(TO_DCN20_MPC(pool->base.mpc)); - pool->base.mpc = NULL; - } - if (pool->base.hubbub != NULL) { - kfree(pool->base.hubbub); - pool->base.hubbub = NULL; - } - for (i = 0; i < pool->base.pipe_count; i++) { - if (pool->base.dpps[i] != NULL) - dcn20_dpp_destroy(&pool->base.dpps[i]); - - if (pool->base.ipps[i] != NULL) - pool->base.ipps[i]->funcs->ipp_destroy(&pool->base.ipps[i]); - - if (pool->base.hubps[i] != NULL) { - kfree(TO_DCN20_HUBP(pool->base.hubps[i])); - pool->base.hubps[i] = NULL; - } - - if (pool->base.irqs != NULL) { - dal_irq_service_destroy(&pool->base.irqs); - } - } - - for (i = 0; i < pool->base.res_cap->num_ddc; i++) { - if (pool->base.engines[i] != NULL) - dce110_engine_destroy(&pool->base.engines[i]); - if (pool->base.hw_i2cs[i] != NULL) { - kfree(pool->base.hw_i2cs[i]); - pool->base.hw_i2cs[i] = NULL; - } - if (pool->base.sw_i2cs[i] != NULL) { - kfree(pool->base.sw_i2cs[i]); - pool->base.sw_i2cs[i] = NULL; - } - } - - for (i = 0; i < pool->base.res_cap->num_opp; i++) { - if (pool->base.opps[i] != NULL) - pool->base.opps[i]->funcs->opp_destroy(&pool->base.opps[i]); - } - - for (i = 0; i < pool->base.res_cap->num_timing_generator; i++) { - if (pool->base.timing_generators[i] != NULL) { - kfree(DCN10TG_FROM_TG(pool->base.timing_generators[i])); - pool->base.timing_generators[i] = NULL; - } - } - - for (i = 0; i < pool->base.res_cap->num_dwb; i++) { - if (pool->base.dwbc[i] != NULL) { - kfree(TO_DCN20_DWBC(pool->base.dwbc[i])); - pool->base.dwbc[i] = NULL; - } - if (pool->base.mcif_wb[i] != NULL) { - kfree(TO_DCN20_MMHUBBUB(pool->base.mcif_wb[i])); - pool->base.mcif_wb[i] = NULL; - } - } - - for (i = 0; i < pool->base.audio_count; i++) { - if (pool->base.audios[i]) - dce_aud_destroy(&pool->base.audios[i]); - } - - for (i = 0; i < pool->base.clk_src_count; i++) { - if (pool->base.clock_sources[i] != NULL) { - dcn20_clock_source_destroy(&pool->base.clock_sources[i]); - pool->base.clock_sources[i] = NULL; - } - } - - if (pool->base.dp_clock_source != NULL) { - dcn20_clock_source_destroy(&pool->base.dp_clock_source); - pool->base.dp_clock_source = NULL; - } - - - if (pool->base.abm != NULL) - dce_abm_destroy(&pool->base.abm); - - if (pool->base.dmcu != NULL) - dce_dmcu_destroy(&pool->base.dmcu); - - if (pool->base.dccg != NULL) - dcn_dccg_destroy(&pool->base.dccg); - - if (pool->base.pp_smu != NULL) - dcn20_pp_smu_destroy(&pool->base.pp_smu); - - if (pool->base.oem_device != NULL) { - struct dc *dc = pool->base.oem_device->ctx->dc; - - dc->link_srv->destroy_ddc_service(&pool->base.oem_device); - } -} - -struct hubp *dcn20_hubp_create( - struct dc_context *ctx, - uint32_t inst) -{ - struct dcn20_hubp *hubp2 = - kzalloc(sizeof(struct dcn20_hubp), GFP_ATOMIC); - - if (!hubp2) - return NULL; - - if (hubp2_construct(hubp2, ctx, inst, - &hubp_regs[inst], &hubp_shift, &hubp_mask)) - return &hubp2->base; - - BREAK_TO_DEBUGGER(); - kfree(hubp2); - return NULL; -} - -static void get_pixel_clock_parameters( - struct pipe_ctx *pipe_ctx, - struct pixel_clk_params *pixel_clk_params) -{ - const struct dc_stream_state *stream = pipe_ctx->stream; - struct pipe_ctx *odm_pipe; - int opp_cnt = 1; - struct dc_link *link = stream->link; - struct link_encoder *link_enc = NULL; - struct dc *dc = pipe_ctx->stream->ctx->dc; - struct dce_hwseq *hws = dc->hwseq; - - for (odm_pipe = pipe_ctx->next_odm_pipe; odm_pipe; odm_pipe = odm_pipe->next_odm_pipe) - opp_cnt++; - - pixel_clk_params->requested_pix_clk_100hz = stream->timing.pix_clk_100hz; - - link_enc = link_enc_cfg_get_link_enc(link); - if (link_enc) - pixel_clk_params->encoder_object_id = link_enc->id; - - pixel_clk_params->signal_type = pipe_ctx->stream->signal; - pixel_clk_params->controller_id = pipe_ctx->stream_res.tg->inst + 1; - /* TODO: un-hardcode*/ - /* TODO - DP2.0 HW: calculate requested_sym_clk for UHBR rates */ - pixel_clk_params->requested_sym_clk = LINK_RATE_LOW * - LINK_RATE_REF_FREQ_IN_KHZ; - pixel_clk_params->flags.ENABLE_SS = 0; - pixel_clk_params->color_depth = - stream->timing.display_color_depth; - pixel_clk_params->flags.DISPLAY_BLANKED = 1; - pixel_clk_params->pixel_encoding = stream->timing.pixel_encoding; - - if (stream->timing.pixel_encoding == PIXEL_ENCODING_YCBCR422) - pixel_clk_params->color_depth = COLOR_DEPTH_888; - - if (opp_cnt == 4) - pixel_clk_params->requested_pix_clk_100hz /= 4; - else if (optc2_is_two_pixels_per_containter(&stream->timing) || opp_cnt == 2) - pixel_clk_params->requested_pix_clk_100hz /= 2; - else if (hws->funcs.is_dp_dig_pixel_rate_div_policy) { - if (hws->funcs.is_dp_dig_pixel_rate_div_policy(pipe_ctx)) - pixel_clk_params->requested_pix_clk_100hz /= 2; - } - - if (stream->timing.timing_3d_format == TIMING_3D_FORMAT_HW_FRAME_PACKING) - pixel_clk_params->requested_pix_clk_100hz *= 2; - -} - -static void build_clamping_params(struct dc_stream_state *stream) -{ - stream->clamping.clamping_level = CLAMPING_FULL_RANGE; - stream->clamping.c_depth = stream->timing.display_color_depth; - stream->clamping.pixel_encoding = stream->timing.pixel_encoding; -} - -static enum dc_status build_pipe_hw_param(struct pipe_ctx *pipe_ctx) -{ - - get_pixel_clock_parameters(pipe_ctx, &pipe_ctx->stream_res.pix_clk_params); - - pipe_ctx->clock_source->funcs->get_pix_clk_dividers( - pipe_ctx->clock_source, - &pipe_ctx->stream_res.pix_clk_params, - &pipe_ctx->pll_settings); - - pipe_ctx->stream->clamping.pixel_encoding = pipe_ctx->stream->timing.pixel_encoding; - - resource_build_bit_depth_reduction_params(pipe_ctx->stream, - &pipe_ctx->stream->bit_depth_params); - build_clamping_params(pipe_ctx->stream); - - return DC_OK; -} - -enum dc_status dcn20_build_mapped_resource(const struct dc *dc, struct dc_state *context, struct dc_stream_state *stream) -{ - enum dc_status status = DC_OK; - struct pipe_ctx *pipe_ctx = resource_get_otg_master_for_stream(&context->res_ctx, stream); - - if (!pipe_ctx) - return DC_ERROR_UNEXPECTED; - - - status = build_pipe_hw_param(pipe_ctx); - - return status; -} - - -void dcn20_acquire_dsc(const struct dc *dc, - struct resource_context *res_ctx, - struct display_stream_compressor **dsc, - int pipe_idx) -{ - int i; - const struct resource_pool *pool = dc->res_pool; - struct display_stream_compressor *dsc_old = dc->current_state->res_ctx.pipe_ctx[pipe_idx].stream_res.dsc; - - ASSERT(*dsc == NULL); /* If this ASSERT fails, dsc was not released properly */ - *dsc = NULL; - - /* Always do 1-to-1 mapping when number of DSCs is same as number of pipes */ - if (pool->res_cap->num_dsc == pool->res_cap->num_opp) { - *dsc = pool->dscs[pipe_idx]; - res_ctx->is_dsc_acquired[pipe_idx] = true; - return; - } - - /* Return old DSC to avoid the need for re-programming */ - if (dsc_old && !res_ctx->is_dsc_acquired[dsc_old->inst]) { - *dsc = dsc_old; - res_ctx->is_dsc_acquired[dsc_old->inst] = true; - return ; - } - - /* Find first free DSC */ - for (i = 0; i < pool->res_cap->num_dsc; i++) - if (!res_ctx->is_dsc_acquired[i]) { - *dsc = pool->dscs[i]; - res_ctx->is_dsc_acquired[i] = true; - break; - } -} - -void dcn20_release_dsc(struct resource_context *res_ctx, - const struct resource_pool *pool, - struct display_stream_compressor **dsc) -{ - int i; - - for (i = 0; i < pool->res_cap->num_dsc; i++) - if (pool->dscs[i] == *dsc) { - res_ctx->is_dsc_acquired[i] = false; - *dsc = NULL; - break; - } -} - - - -enum dc_status dcn20_add_dsc_to_stream_resource(struct dc *dc, - struct dc_state *dc_ctx, - struct dc_stream_state *dc_stream) -{ - enum dc_status result = DC_OK; - int i; - - /* Get a DSC if required and available */ - for (i = 0; i < dc->res_pool->pipe_count; i++) { - struct pipe_ctx *pipe_ctx = &dc_ctx->res_ctx.pipe_ctx[i]; - - if (pipe_ctx->top_pipe) - continue; - - if (pipe_ctx->stream != dc_stream) - continue; - - if (pipe_ctx->stream_res.dsc) - continue; - - dcn20_acquire_dsc(dc, &dc_ctx->res_ctx, &pipe_ctx->stream_res.dsc, i); - - /* The number of DSCs can be less than the number of pipes */ - if (!pipe_ctx->stream_res.dsc) { - result = DC_NO_DSC_RESOURCE; - } - - break; - } - - return result; -} - - -static enum dc_status remove_dsc_from_stream_resource(struct dc *dc, - struct dc_state *new_ctx, - struct dc_stream_state *dc_stream) -{ - struct pipe_ctx *pipe_ctx = NULL; - int i; - - for (i = 0; i < MAX_PIPES; i++) { - if (new_ctx->res_ctx.pipe_ctx[i].stream == dc_stream && !new_ctx->res_ctx.pipe_ctx[i].top_pipe) { - pipe_ctx = &new_ctx->res_ctx.pipe_ctx[i]; - - if (pipe_ctx->stream_res.dsc) - dcn20_release_dsc(&new_ctx->res_ctx, dc->res_pool, &pipe_ctx->stream_res.dsc); - } - } - - if (!pipe_ctx) - return DC_ERROR_UNEXPECTED; - else - return DC_OK; -} - - -enum dc_status dcn20_add_stream_to_ctx(struct dc *dc, struct dc_state *new_ctx, struct dc_stream_state *dc_stream) -{ - enum dc_status result = DC_ERROR_UNEXPECTED; - - result = resource_map_pool_resources(dc, new_ctx, dc_stream); - - if (result == DC_OK) - result = resource_map_phy_clock_resources(dc, new_ctx, dc_stream); - - /* Get a DSC if required and available */ - if (result == DC_OK && dc_stream->timing.flags.DSC) - result = dcn20_add_dsc_to_stream_resource(dc, new_ctx, dc_stream); - - if (result == DC_OK) - result = dcn20_build_mapped_resource(dc, new_ctx, dc_stream); - - return result; -} - - -enum dc_status dcn20_remove_stream_from_ctx(struct dc *dc, struct dc_state *new_ctx, struct dc_stream_state *dc_stream) -{ - enum dc_status result = DC_OK; - - result = remove_dsc_from_stream_resource(dc, new_ctx, dc_stream); - - return result; -} - -/** - * dcn20_split_stream_for_odm - Check if stream can be splited for ODM - * - * @dc: DC object with resource pool info required for pipe split - * @res_ctx: Persistent state of resources - * @prev_odm_pipe: Reference to the previous ODM pipe - * @next_odm_pipe: Reference to the next ODM pipe - * - * This function takes a logically active pipe and a logically free pipe and - * halves all the scaling parameters that need to be halved while populating - * the free pipe with the required resources and configuring the next/previous - * ODM pipe pointers. - * - * Return: - * Return true if split stream for ODM is possible, otherwise, return false. - */ -bool dcn20_split_stream_for_odm( - const struct dc *dc, - struct resource_context *res_ctx, - struct pipe_ctx *prev_odm_pipe, - struct pipe_ctx *next_odm_pipe) -{ - int pipe_idx = next_odm_pipe->pipe_idx; - const struct resource_pool *pool = dc->res_pool; - - *next_odm_pipe = *prev_odm_pipe; - - next_odm_pipe->pipe_idx = pipe_idx; - next_odm_pipe->plane_res.mi = pool->mis[next_odm_pipe->pipe_idx]; - next_odm_pipe->plane_res.hubp = pool->hubps[next_odm_pipe->pipe_idx]; - next_odm_pipe->plane_res.ipp = pool->ipps[next_odm_pipe->pipe_idx]; - next_odm_pipe->plane_res.xfm = pool->transforms[next_odm_pipe->pipe_idx]; - next_odm_pipe->plane_res.dpp = pool->dpps[next_odm_pipe->pipe_idx]; - next_odm_pipe->plane_res.mpcc_inst = pool->dpps[next_odm_pipe->pipe_idx]->inst; - next_odm_pipe->stream_res.dsc = NULL; - if (prev_odm_pipe->next_odm_pipe && prev_odm_pipe->next_odm_pipe != next_odm_pipe) { - next_odm_pipe->next_odm_pipe = prev_odm_pipe->next_odm_pipe; - next_odm_pipe->next_odm_pipe->prev_odm_pipe = next_odm_pipe; - } - if (prev_odm_pipe->top_pipe && prev_odm_pipe->top_pipe->next_odm_pipe) { - prev_odm_pipe->top_pipe->next_odm_pipe->bottom_pipe = next_odm_pipe; - next_odm_pipe->top_pipe = prev_odm_pipe->top_pipe->next_odm_pipe; - } - if (prev_odm_pipe->bottom_pipe && prev_odm_pipe->bottom_pipe->next_odm_pipe) { - prev_odm_pipe->bottom_pipe->next_odm_pipe->top_pipe = next_odm_pipe; - next_odm_pipe->bottom_pipe = prev_odm_pipe->bottom_pipe->next_odm_pipe; - } - prev_odm_pipe->next_odm_pipe = next_odm_pipe; - next_odm_pipe->prev_odm_pipe = prev_odm_pipe; - - if (prev_odm_pipe->plane_state) { - struct scaler_data *sd = &prev_odm_pipe->plane_res.scl_data; - int new_width; - - /* HACTIVE halved for odm combine */ - sd->h_active /= 2; - /* Calculate new vp and recout for left pipe */ - /* Need at least 16 pixels width per side */ - if (sd->recout.x + 16 >= sd->h_active) - return false; - new_width = sd->h_active - sd->recout.x; - sd->viewport.width -= dc_fixpt_floor(dc_fixpt_mul_int( - sd->ratios.horz, sd->recout.width - new_width)); - sd->viewport_c.width -= dc_fixpt_floor(dc_fixpt_mul_int( - sd->ratios.horz_c, sd->recout.width - new_width)); - sd->recout.width = new_width; - - /* Calculate new vp and recout for right pipe */ - sd = &next_odm_pipe->plane_res.scl_data; - /* HACTIVE halved for odm combine */ - sd->h_active /= 2; - /* Need at least 16 pixels width per side */ - if (new_width <= 16) - return false; - new_width = sd->recout.width + sd->recout.x - sd->h_active; - sd->viewport.width -= dc_fixpt_floor(dc_fixpt_mul_int( - sd->ratios.horz, sd->recout.width - new_width)); - sd->viewport_c.width -= dc_fixpt_floor(dc_fixpt_mul_int( - sd->ratios.horz_c, sd->recout.width - new_width)); - sd->recout.width = new_width; - sd->viewport.x += dc_fixpt_floor(dc_fixpt_mul_int( - sd->ratios.horz, sd->h_active - sd->recout.x)); - sd->viewport_c.x += dc_fixpt_floor(dc_fixpt_mul_int( - sd->ratios.horz_c, sd->h_active - sd->recout.x)); - sd->recout.x = 0; - } - if (!next_odm_pipe->top_pipe) - next_odm_pipe->stream_res.opp = pool->opps[next_odm_pipe->pipe_idx]; - else - next_odm_pipe->stream_res.opp = next_odm_pipe->top_pipe->stream_res.opp; - if (next_odm_pipe->stream->timing.flags.DSC == 1 && !next_odm_pipe->top_pipe) { - dcn20_acquire_dsc(dc, res_ctx, &next_odm_pipe->stream_res.dsc, next_odm_pipe->pipe_idx); - ASSERT(next_odm_pipe->stream_res.dsc); - if (next_odm_pipe->stream_res.dsc == NULL) - return false; - } - - return true; -} - -void dcn20_split_stream_for_mpc( - struct resource_context *res_ctx, - const struct resource_pool *pool, - struct pipe_ctx *primary_pipe, - struct pipe_ctx *secondary_pipe) -{ - int pipe_idx = secondary_pipe->pipe_idx; - struct pipe_ctx *sec_bot_pipe = secondary_pipe->bottom_pipe; - - *secondary_pipe = *primary_pipe; - secondary_pipe->bottom_pipe = sec_bot_pipe; - - secondary_pipe->pipe_idx = pipe_idx; - secondary_pipe->plane_res.mi = pool->mis[secondary_pipe->pipe_idx]; - secondary_pipe->plane_res.hubp = pool->hubps[secondary_pipe->pipe_idx]; - secondary_pipe->plane_res.ipp = pool->ipps[secondary_pipe->pipe_idx]; - secondary_pipe->plane_res.xfm = pool->transforms[secondary_pipe->pipe_idx]; - secondary_pipe->plane_res.dpp = pool->dpps[secondary_pipe->pipe_idx]; - secondary_pipe->plane_res.mpcc_inst = pool->dpps[secondary_pipe->pipe_idx]->inst; - secondary_pipe->stream_res.dsc = NULL; - if (primary_pipe->bottom_pipe && primary_pipe->bottom_pipe != secondary_pipe) { - ASSERT(!secondary_pipe->bottom_pipe); - secondary_pipe->bottom_pipe = primary_pipe->bottom_pipe; - secondary_pipe->bottom_pipe->top_pipe = secondary_pipe; - } - primary_pipe->bottom_pipe = secondary_pipe; - secondary_pipe->top_pipe = primary_pipe; - - ASSERT(primary_pipe->plane_state); -} - -unsigned int dcn20_calc_max_scaled_time( - unsigned int time_per_pixel, - enum mmhubbub_wbif_mode mode, - unsigned int urgent_watermark) -{ - unsigned int time_per_byte = 0; - unsigned int total_y_free_entry = 0x200; /* two memory piece for luma */ - unsigned int total_c_free_entry = 0x140; /* two memory piece for chroma */ - unsigned int small_free_entry, max_free_entry; - unsigned int buf_lh_capability; - unsigned int max_scaled_time; - - if (mode == PACKED_444) /* packed mode */ - time_per_byte = time_per_pixel/4; - else if (mode == PLANAR_420_8BPC) - time_per_byte = time_per_pixel; - else if (mode == PLANAR_420_10BPC) /* p010 */ - time_per_byte = time_per_pixel * 819/1024; - - if (time_per_byte == 0) - time_per_byte = 1; - - small_free_entry = (total_y_free_entry > total_c_free_entry) ? total_c_free_entry : total_y_free_entry; - max_free_entry = (mode == PACKED_444) ? total_y_free_entry + total_c_free_entry : small_free_entry; - buf_lh_capability = max_free_entry*time_per_byte*32/16; /* there is 4bit fraction */ - max_scaled_time = buf_lh_capability - urgent_watermark; - return max_scaled_time; -} - -void dcn20_set_mcif_arb_params( - struct dc *dc, - struct dc_state *context, - display_e2e_pipe_params_st *pipes, - int pipe_cnt) -{ - enum mmhubbub_wbif_mode wbif_mode; - struct mcif_arb_params *wb_arb_params; - int i, j, dwb_pipe; - - /* Writeback MCIF_WB arbitration parameters */ - dwb_pipe = 0; - for (i = 0; i < dc->res_pool->pipe_count; i++) { - - if (!context->res_ctx.pipe_ctx[i].stream) - continue; - - for (j = 0; j < MAX_DWB_PIPES; j++) { - if (context->res_ctx.pipe_ctx[i].stream->writeback_info[j].wb_enabled == false) - continue; - - //wb_arb_params = &context->res_ctx.pipe_ctx[i].stream->writeback_info[j].mcif_arb_params; - wb_arb_params = &context->bw_ctx.bw.dcn.bw_writeback.mcif_wb_arb[dwb_pipe]; - - if (context->res_ctx.pipe_ctx[i].stream->writeback_info[j].dwb_params.out_format == dwb_scaler_mode_yuv420) { - if (context->res_ctx.pipe_ctx[i].stream->writeback_info[j].dwb_params.output_depth == DWB_OUTPUT_PIXEL_DEPTH_8BPC) - wbif_mode = PLANAR_420_8BPC; - else - wbif_mode = PLANAR_420_10BPC; - } else - wbif_mode = PACKED_444; - - DC_FP_START(); - dcn20_fpu_set_wb_arb_params(wb_arb_params, context, pipes, pipe_cnt, i); - DC_FP_END(); - - wb_arb_params->slice_lines = 32; - wb_arb_params->arbitration_slice = 2; - wb_arb_params->max_scaled_time = dcn20_calc_max_scaled_time(wb_arb_params->time_per_pixel, - wbif_mode, - wb_arb_params->cli_watermark[0]); /* assume 4 watermark sets have the same value */ - - dwb_pipe++; - - if (dwb_pipe >= MAX_DWB_PIPES) - return; - } - if (dwb_pipe >= MAX_DWB_PIPES) - return; - } -} - -bool dcn20_validate_dsc(struct dc *dc, struct dc_state *new_ctx) -{ - int i; - - /* Validate DSC config, dsc count validation is already done */ - for (i = 0; i < dc->res_pool->pipe_count; i++) { - struct pipe_ctx *pipe_ctx = &new_ctx->res_ctx.pipe_ctx[i]; - struct dc_stream_state *stream = pipe_ctx->stream; - struct dsc_config dsc_cfg; - struct pipe_ctx *odm_pipe; - int opp_cnt = 1; - - for (odm_pipe = pipe_ctx->next_odm_pipe; odm_pipe; odm_pipe = odm_pipe->next_odm_pipe) - opp_cnt++; - - /* Only need to validate top pipe */ - if (pipe_ctx->top_pipe || pipe_ctx->prev_odm_pipe || !stream || !stream->timing.flags.DSC) - continue; - - dsc_cfg.pic_width = (stream->timing.h_addressable + stream->timing.h_border_left - + stream->timing.h_border_right) / opp_cnt; - dsc_cfg.pic_height = stream->timing.v_addressable + stream->timing.v_border_top - + stream->timing.v_border_bottom; - dsc_cfg.pixel_encoding = stream->timing.pixel_encoding; - dsc_cfg.color_depth = stream->timing.display_color_depth; - dsc_cfg.is_odm = pipe_ctx->next_odm_pipe ? true : false; - dsc_cfg.dc_dsc_cfg = stream->timing.dsc_cfg; - dsc_cfg.dc_dsc_cfg.num_slices_h /= opp_cnt; - - if (!pipe_ctx->stream_res.dsc->funcs->dsc_validate_stream(pipe_ctx->stream_res.dsc, &dsc_cfg)) - return false; - } - return true; -} - -struct pipe_ctx *dcn20_find_secondary_pipe(struct dc *dc, - struct resource_context *res_ctx, - const struct resource_pool *pool, - const struct pipe_ctx *primary_pipe) -{ - struct pipe_ctx *secondary_pipe = NULL; - - if (dc && primary_pipe) { - int j; - int preferred_pipe_idx = 0; - - /* first check the prev dc state: - * if this primary pipe has a bottom pipe in prev. state - * and if the bottom pipe is still available (which it should be), - * pick that pipe as secondary - * Same logic applies for ODM pipes - */ - if (dc->current_state->res_ctx.pipe_ctx[primary_pipe->pipe_idx].next_odm_pipe) { - preferred_pipe_idx = dc->current_state->res_ctx.pipe_ctx[primary_pipe->pipe_idx].next_odm_pipe->pipe_idx; - if (res_ctx->pipe_ctx[preferred_pipe_idx].stream == NULL) { - secondary_pipe = &res_ctx->pipe_ctx[preferred_pipe_idx]; - secondary_pipe->pipe_idx = preferred_pipe_idx; - } - } - if (secondary_pipe == NULL && - dc->current_state->res_ctx.pipe_ctx[primary_pipe->pipe_idx].bottom_pipe) { - preferred_pipe_idx = dc->current_state->res_ctx.pipe_ctx[primary_pipe->pipe_idx].bottom_pipe->pipe_idx; - if (res_ctx->pipe_ctx[preferred_pipe_idx].stream == NULL) { - secondary_pipe = &res_ctx->pipe_ctx[preferred_pipe_idx]; - secondary_pipe->pipe_idx = preferred_pipe_idx; - } - } - - /* - * if this primary pipe does not have a bottom pipe in prev. state - * start backward and find a pipe that did not used to be a bottom pipe in - * prev. dc state. This way we make sure we keep the same assignment as - * last state and will not have to reprogram every pipe - */ - if (secondary_pipe == NULL) { - for (j = dc->res_pool->pipe_count - 1; j >= 0; j--) { - if (dc->current_state->res_ctx.pipe_ctx[j].top_pipe == NULL - && dc->current_state->res_ctx.pipe_ctx[j].prev_odm_pipe == NULL) { - preferred_pipe_idx = j; - - if (res_ctx->pipe_ctx[preferred_pipe_idx].stream == NULL) { - secondary_pipe = &res_ctx->pipe_ctx[preferred_pipe_idx]; - secondary_pipe->pipe_idx = preferred_pipe_idx; - break; - } - } - } - } - /* - * We should never hit this assert unless assignments are shuffled around - * if this happens we will prob. hit a vsync tdr - */ - ASSERT(secondary_pipe); - /* - * search backwards for the second pipe to keep pipe - * assignment more consistent - */ - if (secondary_pipe == NULL) { - for (j = dc->res_pool->pipe_count - 1; j >= 0; j--) { - preferred_pipe_idx = j; - - if (res_ctx->pipe_ctx[preferred_pipe_idx].stream == NULL) { - secondary_pipe = &res_ctx->pipe_ctx[preferred_pipe_idx]; - secondary_pipe->pipe_idx = preferred_pipe_idx; - break; - } - } - } - } - - return secondary_pipe; -} - -void dcn20_merge_pipes_for_validate( - struct dc *dc, - struct dc_state *context) -{ - int i; - - /* merge previously split odm pipes since mode support needs to make the decision */ - for (i = 0; i < dc->res_pool->pipe_count; i++) { - struct pipe_ctx *pipe = &context->res_ctx.pipe_ctx[i]; - struct pipe_ctx *odm_pipe = pipe->next_odm_pipe; - - if (pipe->prev_odm_pipe) - continue; - - pipe->next_odm_pipe = NULL; - while (odm_pipe) { - struct pipe_ctx *next_odm_pipe = odm_pipe->next_odm_pipe; - - odm_pipe->plane_state = NULL; - odm_pipe->stream = NULL; - odm_pipe->top_pipe = NULL; - odm_pipe->bottom_pipe = NULL; - odm_pipe->prev_odm_pipe = NULL; - odm_pipe->next_odm_pipe = NULL; - if (odm_pipe->stream_res.dsc) - dcn20_release_dsc(&context->res_ctx, dc->res_pool, &odm_pipe->stream_res.dsc); - /* Clear plane_res and stream_res */ - memset(&odm_pipe->plane_res, 0, sizeof(odm_pipe->plane_res)); - memset(&odm_pipe->stream_res, 0, sizeof(odm_pipe->stream_res)); - odm_pipe = next_odm_pipe; - } - if (pipe->plane_state) - resource_build_scaling_params(pipe); - } - - /* merge previously mpc split pipes since mode support needs to make the decision */ - for (i = 0; i < dc->res_pool->pipe_count; i++) { - struct pipe_ctx *pipe = &context->res_ctx.pipe_ctx[i]; - struct pipe_ctx *hsplit_pipe = pipe->bottom_pipe; - - if (!hsplit_pipe || hsplit_pipe->plane_state != pipe->plane_state) - continue; - - pipe->bottom_pipe = hsplit_pipe->bottom_pipe; - if (hsplit_pipe->bottom_pipe) - hsplit_pipe->bottom_pipe->top_pipe = pipe; - hsplit_pipe->plane_state = NULL; - hsplit_pipe->stream = NULL; - hsplit_pipe->top_pipe = NULL; - hsplit_pipe->bottom_pipe = NULL; - - /* Clear plane_res and stream_res */ - memset(&hsplit_pipe->plane_res, 0, sizeof(hsplit_pipe->plane_res)); - memset(&hsplit_pipe->stream_res, 0, sizeof(hsplit_pipe->stream_res)); - if (pipe->plane_state) - resource_build_scaling_params(pipe); - } -} - -int dcn20_validate_apply_pipe_split_flags( - struct dc *dc, - struct dc_state *context, - int vlevel, - int *split, - bool *merge) -{ - int i, pipe_idx, vlevel_split; - int plane_count = 0; - bool force_split = false; - bool avoid_split = dc->debug.pipe_split_policy == MPC_SPLIT_AVOID; - struct vba_vars_st *v = &context->bw_ctx.dml.vba; - int max_mpc_comb = v->maxMpcComb; - - if (context->stream_count > 1) { - if (dc->debug.pipe_split_policy == MPC_SPLIT_AVOID_MULT_DISP) - avoid_split = true; - } else if (dc->debug.force_single_disp_pipe_split) - force_split = true; - - for (i = 0; i < dc->res_pool->pipe_count; i++) { - struct pipe_ctx *pipe = &context->res_ctx.pipe_ctx[i]; - - /** - * Workaround for avoiding pipe-split in cases where we'd split - * planes that are too small, resulting in splits that aren't - * valid for the scaler. - */ - if (pipe->plane_state && - (pipe->plane_state->dst_rect.width <= 16 || - pipe->plane_state->dst_rect.height <= 16 || - pipe->plane_state->src_rect.width <= 16 || - pipe->plane_state->src_rect.height <= 16)) - avoid_split = true; - - /* TODO: fix dc bugs and remove this split threshold thing */ - if (pipe->stream && !pipe->prev_odm_pipe && - (!pipe->top_pipe || pipe->top_pipe->plane_state != pipe->plane_state)) - ++plane_count; - } - if (plane_count > dc->res_pool->pipe_count / 2) - avoid_split = true; - - /* W/A: Mode timing with borders may not work well with pipe split, avoid for this corner case */ - for (i = 0; i < dc->res_pool->pipe_count; i++) { - struct pipe_ctx *pipe = &context->res_ctx.pipe_ctx[i]; - struct dc_crtc_timing timing; - - if (!pipe->stream) - continue; - else { - timing = pipe->stream->timing; - if (timing.h_border_left + timing.h_border_right - + timing.v_border_top + timing.v_border_bottom > 0) { - avoid_split = true; - break; - } - } - } - - /* Avoid split loop looks for lowest voltage level that allows most unsplit pipes possible */ - if (avoid_split) { - for (i = 0, pipe_idx = 0; i < dc->res_pool->pipe_count; i++) { - if (!context->res_ctx.pipe_ctx[i].stream) - continue; - - for (vlevel_split = vlevel; vlevel <= context->bw_ctx.dml.soc.num_states; vlevel++) - if (v->NoOfDPP[vlevel][0][pipe_idx] == 1 && - v->ModeSupport[vlevel][0]) - break; - /* Impossible to not split this pipe */ - if (vlevel > context->bw_ctx.dml.soc.num_states) - vlevel = vlevel_split; - else - max_mpc_comb = 0; - pipe_idx++; - } - v->maxMpcComb = max_mpc_comb; - } - - /* Split loop sets which pipe should be split based on dml outputs and dc flags */ - for (i = 0, pipe_idx = 0; i < dc->res_pool->pipe_count; i++) { - struct pipe_ctx *pipe = &context->res_ctx.pipe_ctx[i]; - int pipe_plane = v->pipe_plane[pipe_idx]; - bool split4mpc = context->stream_count == 1 && plane_count == 1 - && dc->config.enable_4to1MPC && dc->res_pool->pipe_count >= 4; - - if (!context->res_ctx.pipe_ctx[i].stream) - continue; - - if (split4mpc || v->NoOfDPP[vlevel][max_mpc_comb][pipe_plane] == 4) - split[i] = 4; - else if (force_split || v->NoOfDPP[vlevel][max_mpc_comb][pipe_plane] == 2) - split[i] = 2; - - if ((pipe->stream->view_format == - VIEW_3D_FORMAT_SIDE_BY_SIDE || - pipe->stream->view_format == - VIEW_3D_FORMAT_TOP_AND_BOTTOM) && - (pipe->stream->timing.timing_3d_format == - TIMING_3D_FORMAT_TOP_AND_BOTTOM || - pipe->stream->timing.timing_3d_format == - TIMING_3D_FORMAT_SIDE_BY_SIDE)) - split[i] = 2; - if (dc->debug.force_odm_combine & (1 << pipe->stream_res.tg->inst)) { - split[i] = 2; - v->ODMCombineEnablePerState[vlevel][pipe_plane] = dm_odm_combine_mode_2to1; - } - if (dc->debug.force_odm_combine_4to1 & (1 << pipe->stream_res.tg->inst)) { - split[i] = 4; - v->ODMCombineEnablePerState[vlevel][pipe_plane] = dm_odm_combine_mode_4to1; - } - /*420 format workaround*/ - if (pipe->stream->timing.h_addressable > 7680 && - pipe->stream->timing.pixel_encoding == PIXEL_ENCODING_YCBCR420) { - split[i] = 4; - } - v->ODMCombineEnabled[pipe_plane] = - v->ODMCombineEnablePerState[vlevel][pipe_plane]; - - if (v->ODMCombineEnabled[pipe_plane] == dm_odm_combine_mode_disabled) { - if (resource_get_mpc_slice_count(pipe) == 2) { - /*If need split for mpc but 2 way split already*/ - if (split[i] == 4) - split[i] = 2; /* 2 -> 4 MPC */ - else if (split[i] == 2) - split[i] = 0; /* 2 -> 2 MPC */ - else if (pipe->top_pipe && pipe->top_pipe->plane_state == pipe->plane_state) - merge[i] = true; /* 2 -> 1 MPC */ - } else if (resource_get_mpc_slice_count(pipe) == 4) { - /*If need split for mpc but 4 way split already*/ - if (split[i] == 2 && ((pipe->top_pipe && !pipe->top_pipe->top_pipe) - || !pipe->bottom_pipe)) { - merge[i] = true; /* 4 -> 2 MPC */ - } else if (split[i] == 0 && pipe->top_pipe && - pipe->top_pipe->plane_state == pipe->plane_state) - merge[i] = true; /* 4 -> 1 MPC */ - split[i] = 0; - } else if (resource_get_odm_slice_count(pipe) > 1) { - /* ODM -> MPC transition */ - if (pipe->prev_odm_pipe) { - split[i] = 0; - merge[i] = true; - } - } - } else { - if (resource_get_odm_slice_count(pipe) == 2) { - /*If need split for odm but 2 way split already*/ - if (split[i] == 4) - split[i] = 2; /* 2 -> 4 ODM */ - else if (split[i] == 2) - split[i] = 0; /* 2 -> 2 ODM */ - else if (pipe->prev_odm_pipe) { - ASSERT(0); /* NOT expected yet */ - merge[i] = true; /* exit ODM */ - } - } else if (resource_get_odm_slice_count(pipe) == 4) { - /*If need split for odm but 4 way split already*/ - if (split[i] == 2 && ((pipe->prev_odm_pipe && !pipe->prev_odm_pipe->prev_odm_pipe) - || !pipe->next_odm_pipe)) { - merge[i] = true; /* 4 -> 2 ODM */ - } else if (split[i] == 0 && pipe->prev_odm_pipe) { - ASSERT(0); /* NOT expected yet */ - merge[i] = true; /* exit ODM */ - } - split[i] = 0; - } else if (resource_get_mpc_slice_count(pipe) > 1) { - /* MPC -> ODM transition */ - ASSERT(0); /* NOT expected yet */ - if (pipe->top_pipe && pipe->top_pipe->plane_state == pipe->plane_state) { - split[i] = 0; - merge[i] = true; - } - } - } - - /* Adjust dppclk when split is forced, do not bother with dispclk */ - if (split[i] != 0 && v->NoOfDPP[vlevel][max_mpc_comb][pipe_idx] == 1) { - DC_FP_START(); - dcn20_fpu_adjust_dppclk(v, vlevel, max_mpc_comb, pipe_idx, false); - DC_FP_END(); - } - pipe_idx++; - } - - return vlevel; -} - -bool dcn20_fast_validate_bw( - struct dc *dc, - struct dc_state *context, - display_e2e_pipe_params_st *pipes, - int *pipe_cnt_out, - int *pipe_split_from, - int *vlevel_out, - bool fast_validate) -{ - bool out = false; - int split[MAX_PIPES] = { 0 }; - int pipe_cnt, i, pipe_idx, vlevel; - - ASSERT(pipes); - if (!pipes) - return false; - - dcn20_merge_pipes_for_validate(dc, context); - - DC_FP_START(); - pipe_cnt = dc->res_pool->funcs->populate_dml_pipes(dc, context, pipes, fast_validate); - DC_FP_END(); - - *pipe_cnt_out = pipe_cnt; - - if (!pipe_cnt) { - out = true; - goto validate_out; - } - - vlevel = dml_get_voltage_level(&context->bw_ctx.dml, pipes, pipe_cnt); - - if (vlevel > context->bw_ctx.dml.soc.num_states) - goto validate_fail; - - vlevel = dcn20_validate_apply_pipe_split_flags(dc, context, vlevel, split, NULL); - - /*initialize pipe_just_split_from to invalid idx*/ - for (i = 0; i < MAX_PIPES; i++) - pipe_split_from[i] = -1; - - for (i = 0, pipe_idx = -1; i < dc->res_pool->pipe_count; i++) { - struct pipe_ctx *pipe = &context->res_ctx.pipe_ctx[i]; - struct pipe_ctx *hsplit_pipe = pipe->bottom_pipe; - - if (!pipe->stream || pipe_split_from[i] >= 0) - continue; - - pipe_idx++; - - if (!pipe->top_pipe && !pipe->plane_state && context->bw_ctx.dml.vba.ODMCombineEnabled[pipe_idx]) { - hsplit_pipe = dcn20_find_secondary_pipe(dc, &context->res_ctx, dc->res_pool, pipe); - ASSERT(hsplit_pipe); - if (!dcn20_split_stream_for_odm( - dc, &context->res_ctx, - pipe, hsplit_pipe)) - goto validate_fail; - pipe_split_from[hsplit_pipe->pipe_idx] = pipe_idx; - dcn20_build_mapped_resource(dc, context, pipe->stream); - } - - if (!pipe->plane_state) - continue; - /* Skip 2nd half of already split pipe */ - if (pipe->top_pipe && pipe->plane_state == pipe->top_pipe->plane_state) - continue; - - /* We do not support mpo + odm at the moment */ - if (hsplit_pipe && hsplit_pipe->plane_state != pipe->plane_state - && context->bw_ctx.dml.vba.ODMCombineEnabled[pipe_idx]) - goto validate_fail; - - if (split[i] == 2) { - if (!hsplit_pipe || hsplit_pipe->plane_state != pipe->plane_state) { - /* pipe not split previously needs split */ - hsplit_pipe = dcn20_find_secondary_pipe(dc, &context->res_ctx, dc->res_pool, pipe); - ASSERT(hsplit_pipe); - if (!hsplit_pipe) { - DC_FP_START(); - dcn20_fpu_adjust_dppclk(&context->bw_ctx.dml.vba, vlevel, context->bw_ctx.dml.vba.maxMpcComb, pipe_idx, true); - DC_FP_END(); - continue; - } - if (context->bw_ctx.dml.vba.ODMCombineEnabled[pipe_idx]) { - if (!dcn20_split_stream_for_odm( - dc, &context->res_ctx, - pipe, hsplit_pipe)) - goto validate_fail; - dcn20_build_mapped_resource(dc, context, pipe->stream); - } else { - dcn20_split_stream_for_mpc( - &context->res_ctx, dc->res_pool, - pipe, hsplit_pipe); - resource_build_scaling_params(pipe); - resource_build_scaling_params(hsplit_pipe); - } - pipe_split_from[hsplit_pipe->pipe_idx] = pipe_idx; - } - } else if (hsplit_pipe && hsplit_pipe->plane_state == pipe->plane_state) { - /* merge should already have been done */ - ASSERT(0); - } - } - /* Actual dsc count per stream dsc validation*/ - if (!dcn20_validate_dsc(dc, context)) { - context->bw_ctx.dml.vba.ValidationStatus[context->bw_ctx.dml.vba.soc.num_states] = - DML_FAIL_DSC_VALIDATION_FAILURE; - goto validate_fail; - } - - *vlevel_out = vlevel; - - out = true; - goto validate_out; - -validate_fail: - out = false; - -validate_out: - return out; -} - -bool dcn20_validate_bandwidth(struct dc *dc, struct dc_state *context, - bool fast_validate) -{ - bool voltage_supported; - display_e2e_pipe_params_st *pipes; - - pipes = kcalloc(dc->res_pool->pipe_count, sizeof(display_e2e_pipe_params_st), GFP_KERNEL); - if (!pipes) - return false; - - DC_FP_START(); - voltage_supported = dcn20_validate_bandwidth_fp(dc, context, fast_validate, pipes); - DC_FP_END(); - - kfree(pipes); - return voltage_supported; -} - -struct pipe_ctx *dcn20_acquire_free_pipe_for_layer( - const struct dc_state *cur_ctx, - struct dc_state *new_ctx, - const struct resource_pool *pool, - const struct pipe_ctx *opp_head) -{ - struct resource_context *res_ctx = &new_ctx->res_ctx; - struct pipe_ctx *otg_master = resource_get_otg_master_for_stream(res_ctx, opp_head->stream); - struct pipe_ctx *sec_dpp_pipe = resource_find_free_secondary_pipe_legacy(res_ctx, pool, otg_master); - - ASSERT(otg_master); - - if (!sec_dpp_pipe) - return NULL; - - sec_dpp_pipe->stream = opp_head->stream; - sec_dpp_pipe->stream_res.tg = opp_head->stream_res.tg; - sec_dpp_pipe->stream_res.opp = opp_head->stream_res.opp; - - sec_dpp_pipe->plane_res.hubp = pool->hubps[sec_dpp_pipe->pipe_idx]; - sec_dpp_pipe->plane_res.ipp = pool->ipps[sec_dpp_pipe->pipe_idx]; - sec_dpp_pipe->plane_res.dpp = pool->dpps[sec_dpp_pipe->pipe_idx]; - sec_dpp_pipe->plane_res.mpcc_inst = pool->dpps[sec_dpp_pipe->pipe_idx]->inst; - - return sec_dpp_pipe; -} - -bool dcn20_get_dcc_compression_cap(const struct dc *dc, - const struct dc_dcc_surface_param *input, - struct dc_surface_dcc_cap *output) -{ - return dc->res_pool->hubbub->funcs->get_dcc_compression_cap( - dc->res_pool->hubbub, - input, - output); -} - -static void dcn20_destroy_resource_pool(struct resource_pool **pool) -{ - struct dcn20_resource_pool *dcn20_pool = TO_DCN20_RES_POOL(*pool); - - dcn20_resource_destruct(dcn20_pool); - kfree(dcn20_pool); - *pool = NULL; -} - - -static struct dc_cap_funcs cap_funcs = { - .get_dcc_compression_cap = dcn20_get_dcc_compression_cap -}; - - -enum dc_status dcn20_patch_unknown_plane_state(struct dc_plane_state *plane_state) -{ - enum surface_pixel_format surf_pix_format = plane_state->format; - unsigned int bpp = resource_pixel_format_to_bpp(surf_pix_format); - - plane_state->tiling_info.gfx9.swizzle = DC_SW_64KB_S; - if (bpp == 64) - plane_state->tiling_info.gfx9.swizzle = DC_SW_64KB_D; - - return DC_OK; -} - -void dcn20_release_pipe(struct dc_state *context, - struct pipe_ctx *pipe, - const struct resource_pool *pool) -{ - if (resource_is_pipe_type(pipe, OPP_HEAD) && pipe->stream_res.dsc) - dcn20_release_dsc(&context->res_ctx, pool, &pipe->stream_res.dsc); - memset(pipe, 0, sizeof(*pipe)); -} - -static const struct resource_funcs dcn20_res_pool_funcs = { - .destroy = dcn20_destroy_resource_pool, - .link_enc_create = dcn20_link_encoder_create, - .panel_cntl_create = dcn20_panel_cntl_create, - .validate_bandwidth = dcn20_validate_bandwidth, - .acquire_free_pipe_as_secondary_dpp_pipe = dcn20_acquire_free_pipe_for_layer, - .release_pipe = dcn20_release_pipe, - .add_stream_to_ctx = dcn20_add_stream_to_ctx, - .add_dsc_to_stream_resource = dcn20_add_dsc_to_stream_resource, - .remove_stream_from_ctx = dcn20_remove_stream_from_ctx, - .populate_dml_writeback_from_context = dcn20_populate_dml_writeback_from_context, - .patch_unknown_plane_state = dcn20_patch_unknown_plane_state, - .set_mcif_arb_params = dcn20_set_mcif_arb_params, - .populate_dml_pipes = dcn20_populate_dml_pipes_from_context, - .find_first_free_match_stream_enc_for_link = dcn10_find_first_free_match_stream_enc_for_link -}; - -bool dcn20_dwbc_create(struct dc_context *ctx, struct resource_pool *pool) -{ - int i; - uint32_t pipe_count = pool->res_cap->num_dwb; - - for (i = 0; i < pipe_count; i++) { - struct dcn20_dwbc *dwbc20 = kzalloc(sizeof(struct dcn20_dwbc), - GFP_KERNEL); - - if (!dwbc20) { - dm_error("DC: failed to create dwbc20!\n"); - return false; - } - dcn20_dwbc_construct(dwbc20, ctx, - &dwbc20_regs[i], - &dwbc20_shift, - &dwbc20_mask, - i); - pool->dwbc[i] = &dwbc20->base; - } - return true; -} - -bool dcn20_mmhubbub_create(struct dc_context *ctx, struct resource_pool *pool) -{ - int i; - uint32_t pipe_count = pool->res_cap->num_dwb; - - ASSERT(pipe_count > 0); - - for (i = 0; i < pipe_count; i++) { - struct dcn20_mmhubbub *mcif_wb20 = kzalloc(sizeof(struct dcn20_mmhubbub), - GFP_KERNEL); - - if (!mcif_wb20) { - dm_error("DC: failed to create mcif_wb20!\n"); - return false; - } - - dcn20_mmhubbub_construct(mcif_wb20, ctx, - &mcif_wb20_regs[i], - &mcif_wb20_shift, - &mcif_wb20_mask, - i); - - pool->mcif_wb[i] = &mcif_wb20->base; - } - return true; -} - -static struct pp_smu_funcs *dcn20_pp_smu_create(struct dc_context *ctx) -{ - struct pp_smu_funcs *pp_smu = kzalloc(sizeof(*pp_smu), GFP_ATOMIC); - - if (!pp_smu) - return pp_smu; - - dm_pp_get_funcs(ctx, pp_smu); - - if (pp_smu->ctx.ver != PP_SMU_VER_NV) - pp_smu = memset(pp_smu, 0, sizeof(struct pp_smu_funcs)); - - return pp_smu; -} - -static void dcn20_pp_smu_destroy(struct pp_smu_funcs **pp_smu) -{ - if (pp_smu && *pp_smu) { - kfree(*pp_smu); - *pp_smu = NULL; - } -} - -static struct _vcs_dpi_soc_bounding_box_st *get_asic_rev_soc_bb( - uint32_t hw_internal_rev) -{ - if (ASICREV_IS_NAVI14_M(hw_internal_rev)) - return &dcn2_0_nv14_soc; - - if (ASICREV_IS_NAVI12_P(hw_internal_rev)) - return &dcn2_0_nv12_soc; - - return &dcn2_0_soc; -} - -static struct _vcs_dpi_ip_params_st *get_asic_rev_ip_params( - uint32_t hw_internal_rev) -{ - /* NV14 */ - if (ASICREV_IS_NAVI14_M(hw_internal_rev)) - return &dcn2_0_nv14_ip; - - /* NV12 and NV10 */ - return &dcn2_0_ip; -} - -static enum dml_project get_dml_project_version(uint32_t hw_internal_rev) -{ - return DML_PROJECT_NAVI10v2; -} - -static bool init_soc_bounding_box(struct dc *dc, - struct dcn20_resource_pool *pool) -{ - 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 = - get_asic_rev_ip_params(dc->ctx->asic_id.hw_internal_rev); - - DC_LOGGER_INIT(dc->ctx->logger); - - if (pool->base.pp_smu) { - struct pp_smu_nv_clock_table max_clocks = {0}; - unsigned int uclk_states[8] = {0}; - unsigned int num_states = 0; - enum pp_smu_status status; - bool clock_limits_available = false; - bool uclk_states_available = false; - - if (pool->base.pp_smu->nv_funcs.get_uclk_dpm_states) { - status = (pool->base.pp_smu->nv_funcs.get_uclk_dpm_states) - (&pool->base.pp_smu->nv_funcs.pp_smu, uclk_states, &num_states); - - uclk_states_available = (status == PP_SMU_RESULT_OK); - } - - if (pool->base.pp_smu->nv_funcs.get_maximum_sustainable_clocks) { - status = (*pool->base.pp_smu->nv_funcs.get_maximum_sustainable_clocks) - (&pool->base.pp_smu->nv_funcs.pp_smu, &max_clocks); - /* SMU cannot set DCF clock to anything equal to or higher than SOC clock - */ - if (max_clocks.dcfClockInKhz >= max_clocks.socClockInKhz) - max_clocks.dcfClockInKhz = max_clocks.socClockInKhz - 1000; - clock_limits_available = (status == PP_SMU_RESULT_OK); - } - - if (clock_limits_available && uclk_states_available && num_states) { - DC_FP_START(); - dcn20_update_bounding_box(dc, loaded_bb, &max_clocks, uclk_states, num_states); - DC_FP_END(); - } else if (clock_limits_available) { - DC_FP_START(); - dcn20_cap_soc_clocks(loaded_bb, max_clocks); - DC_FP_END(); - } - } - - loaded_ip->max_num_otg = pool->base.res_cap->num_timing_generator; - loaded_ip->max_num_dpp = pool->base.pipe_count; - DC_FP_START(); - dcn20_patch_bounding_box(dc, loaded_bb); - DC_FP_END(); - return true; -} - -static bool dcn20_resource_construct( - uint8_t num_virtual_links, - struct dc *dc, - struct dcn20_resource_pool *pool) -{ - int i; - struct dc_context *ctx = dc->ctx; - struct irq_service_init_data init_data; - struct ddc_service_init_data ddc_init_data = {0}; - struct _vcs_dpi_soc_bounding_box_st *loaded_bb = - get_asic_rev_soc_bb(ctx->asic_id.hw_internal_rev); - struct _vcs_dpi_ip_params_st *loaded_ip = - get_asic_rev_ip_params(ctx->asic_id.hw_internal_rev); - enum dml_project dml_project_version = - get_dml_project_version(ctx->asic_id.hw_internal_rev); - - ctx->dc_bios->regs = &bios_regs; - pool->base.funcs = &dcn20_res_pool_funcs; - - if (ASICREV_IS_NAVI14_M(ctx->asic_id.hw_internal_rev)) { - pool->base.res_cap = &res_cap_nv14; - pool->base.pipe_count = 5; - pool->base.mpcc_count = 5; - } else { - pool->base.res_cap = &res_cap_nv10; - pool->base.pipe_count = 6; - pool->base.mpcc_count = 6; - } - /************************************************* - * Resource + asic cap harcoding * - *************************************************/ - pool->base.underlay_pipe_index = NO_UNDERLAY_PIPE; - - dc->caps.max_downscale_ratio = 200; - dc->caps.i2c_speed_in_khz = 100; - dc->caps.i2c_speed_in_khz_hdcp = 100; /*1.4 w/a not applied by default*/ - dc->caps.max_cursor_size = 256; - dc->caps.min_horizontal_blanking_period = 80; - dc->caps.dmdata_alloc_size = 2048; - - dc->caps.max_slave_planes = 1; - dc->caps.max_slave_yuv_planes = 1; - dc->caps.max_slave_rgb_planes = 1; - dc->caps.post_blend_color_processing = true; - dc->caps.force_dp_tps4_for_cp2520 = true; - dc->caps.extended_aux_timeout_support = true; - - /* Color pipeline capabilities */ - dc->caps.color.dpp.dcn_arch = 1; - dc->caps.color.dpp.input_lut_shared = 0; - dc->caps.color.dpp.icsc = 1; - dc->caps.color.dpp.dgam_ram = 1; - dc->caps.color.dpp.dgam_rom_caps.srgb = 1; - dc->caps.color.dpp.dgam_rom_caps.bt2020 = 1; - dc->caps.color.dpp.dgam_rom_caps.gamma2_2 = 0; - dc->caps.color.dpp.dgam_rom_caps.pq = 0; - dc->caps.color.dpp.dgam_rom_caps.hlg = 0; - dc->caps.color.dpp.post_csc = 0; - dc->caps.color.dpp.gamma_corr = 0; - dc->caps.color.dpp.dgam_rom_for_yuv = 1; - - dc->caps.color.dpp.hw_3d_lut = 1; - dc->caps.color.dpp.ogam_ram = 1; - // no OGAM ROM on DCN2, only MPC ROM - dc->caps.color.dpp.ogam_rom_caps.srgb = 0; - dc->caps.color.dpp.ogam_rom_caps.bt2020 = 0; - dc->caps.color.dpp.ogam_rom_caps.gamma2_2 = 0; - dc->caps.color.dpp.ogam_rom_caps.pq = 0; - dc->caps.color.dpp.ogam_rom_caps.hlg = 0; - dc->caps.color.dpp.ocsc = 0; - - dc->caps.color.mpc.gamut_remap = 0; - dc->caps.color.mpc.num_3dluts = 0; - dc->caps.color.mpc.shared_3d_lut = 0; - dc->caps.color.mpc.ogam_ram = 1; - dc->caps.color.mpc.ogam_rom_caps.srgb = 0; - dc->caps.color.mpc.ogam_rom_caps.bt2020 = 0; - dc->caps.color.mpc.ogam_rom_caps.gamma2_2 = 0; - dc->caps.color.mpc.ogam_rom_caps.pq = 0; - dc->caps.color.mpc.ogam_rom_caps.hlg = 0; - dc->caps.color.mpc.ocsc = 1; - - dc->caps.dp_hdmi21_pcon_support = true; - - if (dc->ctx->dce_environment == DCE_ENV_PRODUCTION_DRV) - dc->debug = debug_defaults_drv; - - //dcn2.0x - dc->work_arounds.dedcn20_305_wa = true; - - // Init the vm_helper - if (dc->vm_helper) - vm_helper_init(dc->vm_helper, 16); - - /************************************************* - * Create resources * - *************************************************/ - - pool->base.clock_sources[DCN20_CLK_SRC_PLL0] = - dcn20_clock_source_create(ctx, ctx->dc_bios, - CLOCK_SOURCE_COMBO_PHY_PLL0, - &clk_src_regs[0], false); - pool->base.clock_sources[DCN20_CLK_SRC_PLL1] = - dcn20_clock_source_create(ctx, ctx->dc_bios, - CLOCK_SOURCE_COMBO_PHY_PLL1, - &clk_src_regs[1], false); - pool->base.clock_sources[DCN20_CLK_SRC_PLL2] = - dcn20_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] = - dcn20_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] = - dcn20_clock_source_create(ctx, ctx->dc_bios, - CLOCK_SOURCE_COMBO_PHY_PLL4, - &clk_src_regs[4], false); - pool->base.clock_sources[DCN20_CLK_SRC_PLL5] = - dcn20_clock_source_create(ctx, ctx->dc_bios, - CLOCK_SOURCE_COMBO_PHY_PLL5, - &clk_src_regs[5], false); - pool->base.clk_src_count = DCN20_CLK_SRC_TOTAL; - /* todo: not reuse phy_pll registers */ - pool->base.dp_clock_source = - dcn20_clock_source_create(ctx, ctx->dc_bios, - CLOCK_SOURCE_ID_DP_DTO, - &clk_src_regs[0], true); - - for (i = 0; i < pool->base.clk_src_count; i++) { - if (pool->base.clock_sources[i] == NULL) { - dm_error("DC: failed to create clock sources!\n"); - BREAK_TO_DEBUGGER(); - goto create_fail; - } - } - - pool->base.dccg = dccg2_create(ctx, &dccg_regs, &dccg_shift, &dccg_mask); - if (pool->base.dccg == NULL) { - dm_error("DC: failed to create dccg!\n"); - BREAK_TO_DEBUGGER(); - goto create_fail; - } - - pool->base.dmcu = dcn20_dmcu_create(ctx, - &dmcu_regs, - &dmcu_shift, - &dmcu_mask); - if (pool->base.dmcu == NULL) { - dm_error("DC: failed to create dmcu!\n"); - BREAK_TO_DEBUGGER(); - goto create_fail; - } - - pool->base.abm = dce_abm_create(ctx, - &abm_regs, - &abm_shift, - &abm_mask); - if (pool->base.abm == NULL) { - dm_error("DC: failed to create abm!\n"); - BREAK_TO_DEBUGGER(); - goto create_fail; - } - - pool->base.pp_smu = dcn20_pp_smu_create(ctx); - - - if (!init_soc_bounding_box(dc, pool)) { - dm_error("DC: failed to initialize soc bounding box!\n"); - BREAK_TO_DEBUGGER(); - goto create_fail; - } - - dml_init_instance(&dc->dml, loaded_bb, loaded_ip, dml_project_version); - - if (!dc->debug.disable_pplib_wm_range) { - struct pp_smu_wm_range_sets ranges = {0}; - int i = 0; - - ranges.num_reader_wm_sets = 0; - - if (loaded_bb->num_states == 1) { - ranges.reader_wm_sets[0].wm_inst = i; - ranges.reader_wm_sets[0].min_drain_clk_mhz = PP_SMU_WM_SET_RANGE_CLK_UNCONSTRAINED_MIN; - ranges.reader_wm_sets[0].max_drain_clk_mhz = PP_SMU_WM_SET_RANGE_CLK_UNCONSTRAINED_MAX; - ranges.reader_wm_sets[0].min_fill_clk_mhz = PP_SMU_WM_SET_RANGE_CLK_UNCONSTRAINED_MIN; - ranges.reader_wm_sets[0].max_fill_clk_mhz = PP_SMU_WM_SET_RANGE_CLK_UNCONSTRAINED_MAX; - - ranges.num_reader_wm_sets = 1; - } else if (loaded_bb->num_states > 1) { - for (i = 0; i < 4 && i < loaded_bb->num_states; i++) { - ranges.reader_wm_sets[i].wm_inst = i; - ranges.reader_wm_sets[i].min_drain_clk_mhz = PP_SMU_WM_SET_RANGE_CLK_UNCONSTRAINED_MIN; - ranges.reader_wm_sets[i].max_drain_clk_mhz = PP_SMU_WM_SET_RANGE_CLK_UNCONSTRAINED_MAX; - DC_FP_START(); - dcn20_fpu_set_wm_ranges(i, &ranges, loaded_bb); - DC_FP_END(); - - ranges.num_reader_wm_sets = i + 1; - } - - ranges.reader_wm_sets[0].min_fill_clk_mhz = PP_SMU_WM_SET_RANGE_CLK_UNCONSTRAINED_MIN; - ranges.reader_wm_sets[ranges.num_reader_wm_sets - 1].max_fill_clk_mhz = PP_SMU_WM_SET_RANGE_CLK_UNCONSTRAINED_MAX; - } - - ranges.num_writer_wm_sets = 1; - - ranges.writer_wm_sets[0].wm_inst = 0; - ranges.writer_wm_sets[0].min_fill_clk_mhz = PP_SMU_WM_SET_RANGE_CLK_UNCONSTRAINED_MIN; - ranges.writer_wm_sets[0].max_fill_clk_mhz = PP_SMU_WM_SET_RANGE_CLK_UNCONSTRAINED_MAX; - ranges.writer_wm_sets[0].min_drain_clk_mhz = PP_SMU_WM_SET_RANGE_CLK_UNCONSTRAINED_MIN; - ranges.writer_wm_sets[0].max_drain_clk_mhz = PP_SMU_WM_SET_RANGE_CLK_UNCONSTRAINED_MAX; - - /* Notify PP Lib/SMU which Watermarks to use for which clock ranges */ - if (pool->base.pp_smu->nv_funcs.set_wm_ranges) - pool->base.pp_smu->nv_funcs.set_wm_ranges(&pool->base.pp_smu->nv_funcs.pp_smu, &ranges); - } - - init_data.ctx = dc->ctx; - pool->base.irqs = dal_irq_service_dcn20_create(&init_data); - if (!pool->base.irqs) - goto create_fail; - - /* mem input -> ipp -> dpp -> opp -> TG */ - for (i = 0; i < pool->base.pipe_count; i++) { - pool->base.hubps[i] = dcn20_hubp_create(ctx, i); - if (pool->base.hubps[i] == NULL) { - BREAK_TO_DEBUGGER(); - dm_error( - "DC: failed to create memory input!\n"); - goto create_fail; - } - - pool->base.ipps[i] = dcn20_ipp_create(ctx, i); - if (pool->base.ipps[i] == NULL) { - BREAK_TO_DEBUGGER(); - dm_error( - "DC: failed to create input pixel processor!\n"); - goto create_fail; - } - - pool->base.dpps[i] = dcn20_dpp_create(ctx, i); - if (pool->base.dpps[i] == NULL) { - BREAK_TO_DEBUGGER(); - dm_error( - "DC: failed to create dpps!\n"); - goto create_fail; - } - } - for (i = 0; i < pool->base.res_cap->num_ddc; i++) { - pool->base.engines[i] = dcn20_aux_engine_create(ctx, i); - if (pool->base.engines[i] == NULL) { - BREAK_TO_DEBUGGER(); - dm_error( - "DC:failed to create aux engine!!\n"); - goto create_fail; - } - pool->base.hw_i2cs[i] = dcn20_i2c_hw_create(ctx, i); - if (pool->base.hw_i2cs[i] == NULL) { - BREAK_TO_DEBUGGER(); - dm_error( - "DC:failed to create hw i2c!!\n"); - goto create_fail; - } - pool->base.sw_i2cs[i] = NULL; - } - - for (i = 0; i < pool->base.res_cap->num_opp; i++) { - pool->base.opps[i] = dcn20_opp_create(ctx, i); - if (pool->base.opps[i] == NULL) { - BREAK_TO_DEBUGGER(); - dm_error( - "DC: failed to create output pixel processor!\n"); - goto create_fail; - } - } - - for (i = 0; i < pool->base.res_cap->num_timing_generator; i++) { - pool->base.timing_generators[i] = dcn20_timing_generator_create( - ctx, i); - if (pool->base.timing_generators[i] == NULL) { - BREAK_TO_DEBUGGER(); - dm_error("DC: failed to create tg!\n"); - goto create_fail; - } - } - - pool->base.timing_generator_count = i; - - pool->base.mpc = dcn20_mpc_create(ctx); - if (pool->base.mpc == NULL) { - BREAK_TO_DEBUGGER(); - dm_error("DC: failed to create mpc!\n"); - goto create_fail; - } - - pool->base.hubbub = dcn20_hubbub_create(ctx); - if (pool->base.hubbub == NULL) { - BREAK_TO_DEBUGGER(); - dm_error("DC: failed to create hubbub!\n"); - goto create_fail; - } - - for (i = 0; i < pool->base.res_cap->num_dsc; i++) { - pool->base.dscs[i] = dcn20_dsc_create(ctx, i); - if (pool->base.dscs[i] == NULL) { - BREAK_TO_DEBUGGER(); - dm_error("DC: failed to create display stream compressor %d!\n", i); - goto create_fail; - } - } - - if (!dcn20_dwbc_create(ctx, &pool->base)) { - BREAK_TO_DEBUGGER(); - dm_error("DC: failed to create dwbc!\n"); - goto create_fail; - } - if (!dcn20_mmhubbub_create(ctx, &pool->base)) { - BREAK_TO_DEBUGGER(); - dm_error("DC: failed to create mcif_wb!\n"); - goto create_fail; - } - - if (!resource_construct(num_virtual_links, dc, &pool->base, - &res_create_funcs)) - goto create_fail; - - dcn20_hw_sequencer_construct(dc); - - // IF NV12, set PG function pointer to NULL. It's not that - // PG isn't supported for NV12, it's that we don't want to - // program the registers because that will cause more power - // to be consumed. We could have created dcn20_init_hw to get - // the same effect by checking ASIC rev, but there was a - // request at some point to not check ASIC rev on hw sequencer. - if (ASICREV_IS_NAVI12_P(dc->ctx->asic_id.hw_internal_rev)) { - dc->hwseq->funcs.enable_power_gating_plane = NULL; - dc->debug.disable_dpp_power_gate = true; - dc->debug.disable_hubp_power_gate = true; - } - - - dc->caps.max_planes = pool->base.pipe_count; - - for (i = 0; i < dc->caps.max_planes; ++i) - dc->caps.planes[i] = plane_cap; - - dc->cap_funcs = cap_funcs; - - if (dc->ctx->dc_bios->fw_info.oem_i2c_present) { - ddc_init_data.ctx = dc->ctx; - ddc_init_data.link = NULL; - ddc_init_data.id.id = dc->ctx->dc_bios->fw_info.oem_i2c_obj_id; - ddc_init_data.id.enum_id = 0; - ddc_init_data.id.type = OBJECT_TYPE_GENERIC; - pool->base.oem_device = dc->link_srv->create_ddc_service(&ddc_init_data); - } else { - pool->base.oem_device = NULL; - } - - return true; - -create_fail: - - dcn20_resource_destruct(pool); - - return false; -} - -struct resource_pool *dcn20_create_resource_pool( - const struct dc_init_data *init_data, - struct dc *dc) -{ - struct dcn20_resource_pool *pool = - kzalloc(sizeof(struct dcn20_resource_pool), GFP_ATOMIC); - - if (!pool) - return NULL; - - if (dcn20_resource_construct(init_data->num_virtual_links, dc, pool)) - return &pool->base; - - BREAK_TO_DEBUGGER(); - kfree(pool); - return NULL; -} diff --git a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_resource.h b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_resource.h deleted file mode 100644 index 37ecaccc5d12..000000000000 --- a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_resource.h +++ /dev/null @@ -1,170 +0,0 @@ -/* -* Copyright 2017 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_RESOURCE_DCN20_H__ -#define __DC_RESOURCE_DCN20_H__ - -#include "core_types.h" -#include "dml/dcn20/dcn20_fpu.h" - -#define TO_DCN20_RES_POOL(pool)\ - container_of(pool, struct dcn20_resource_pool, base) - -struct dc; -struct resource_pool; -struct _vcs_dpi_display_pipe_params_st; - -extern struct _vcs_dpi_ip_params_st dcn2_0_ip; -extern struct _vcs_dpi_ip_params_st dcn2_0_nv14_ip; -extern struct _vcs_dpi_soc_bounding_box_st dcn2_0_soc; -extern struct _vcs_dpi_soc_bounding_box_st dcn2_0_nv14_soc; -extern struct _vcs_dpi_soc_bounding_box_st dcn2_0_nv12_soc; - -struct dcn20_resource_pool { - struct resource_pool base; -}; -struct resource_pool *dcn20_create_resource_pool( - const struct dc_init_data *init_data, - struct dc *dc); - -struct link_encoder *dcn20_link_encoder_create( - struct dc_context *ctx, - const struct encoder_init_data *enc_init_data); - -unsigned int dcn20_calc_max_scaled_time( - unsigned int time_per_pixel, - enum mmhubbub_wbif_mode mode, - unsigned int urgent_watermark); - -struct pipe_ctx *dcn20_acquire_free_pipe_for_layer( - const struct dc_state *cur_ctx, - struct dc_state *new_ctx, - const struct resource_pool *pool, - const struct pipe_ctx *opp_head_pipe); -void dcn20_release_pipe(struct dc_state *context, - struct pipe_ctx *pipe, - const struct resource_pool *pool); -struct stream_encoder *dcn20_stream_encoder_create( - enum engine_id eng_id, - struct dc_context *ctx); - -struct dce_hwseq *dcn20_hwseq_create( - struct dc_context *ctx); - -bool dcn20_get_dcc_compression_cap(const struct dc *dc, - const struct dc_dcc_surface_param *input, - struct dc_surface_dcc_cap *output); - -void dcn20_dpp_destroy(struct dpp **dpp); - -struct dpp *dcn20_dpp_create( - struct dc_context *ctx, - uint32_t inst); - -struct input_pixel_processor *dcn20_ipp_create( - struct dc_context *ctx, uint32_t inst); - -struct output_pixel_processor *dcn20_opp_create( - struct dc_context *ctx, uint32_t inst); - -struct dce_aux *dcn20_aux_engine_create( - struct dc_context *ctx, uint32_t inst); - -struct dce_i2c_hw *dcn20_i2c_hw_create( - struct dc_context *ctx, - uint32_t inst); - -void dcn20_clock_source_destroy(struct clock_source **clk_src); - -struct display_stream_compressor *dcn20_dsc_create( - struct dc_context *ctx, uint32_t inst); -void dcn20_dsc_destroy(struct display_stream_compressor **dsc); - -struct hubp *dcn20_hubp_create( - struct dc_context *ctx, - uint32_t inst); -struct timing_generator *dcn20_timing_generator_create( - struct dc_context *ctx, - uint32_t instance); -struct mpc *dcn20_mpc_create(struct dc_context *ctx); -struct hubbub *dcn20_hubbub_create(struct dc_context *ctx); - -bool dcn20_dwbc_create(struct dc_context *ctx, struct resource_pool *pool); -bool dcn20_mmhubbub_create(struct dc_context *ctx, struct resource_pool *pool); - -void dcn20_set_mcif_arb_params( - struct dc *dc, - struct dc_state *context, - display_e2e_pipe_params_st *pipes, - int pipe_cnt); -bool dcn20_validate_bandwidth(struct dc *dc, struct dc_state *context, bool fast_validate); -void dcn20_merge_pipes_for_validate( - struct dc *dc, - struct dc_state *context); -int dcn20_validate_apply_pipe_split_flags( - struct dc *dc, - struct dc_state *context, - int vlevel, - int *split, - bool *merge); -void dcn20_release_dsc(struct resource_context *res_ctx, - const struct resource_pool *pool, - struct display_stream_compressor **dsc); -bool dcn20_validate_dsc(struct dc *dc, struct dc_state *new_ctx); -void dcn20_split_stream_for_mpc( - struct resource_context *res_ctx, - const struct resource_pool *pool, - struct pipe_ctx *primary_pipe, - struct pipe_ctx *secondary_pipe); -bool dcn20_split_stream_for_odm( - const struct dc *dc, - struct resource_context *res_ctx, - struct pipe_ctx *prev_odm_pipe, - struct pipe_ctx *next_odm_pipe); -void dcn20_acquire_dsc(const struct dc *dc, - struct resource_context *res_ctx, - struct display_stream_compressor **dsc, - int pipe_idx); -struct pipe_ctx *dcn20_find_secondary_pipe(struct dc *dc, - struct resource_context *res_ctx, - const struct resource_pool *pool, - const struct pipe_ctx *primary_pipe); -bool dcn20_fast_validate_bw( - struct dc *dc, - struct dc_state *context, - display_e2e_pipe_params_st *pipes, - int *pipe_cnt_out, - int *pipe_split_from, - int *vlevel_out, - bool fast_validate); - -enum dc_status dcn20_build_mapped_resource(const struct dc *dc, struct dc_state *context, struct dc_stream_state *stream); -enum dc_status dcn20_add_stream_to_ctx(struct dc *dc, struct dc_state *new_ctx, struct dc_stream_state *dc_stream); -enum dc_status dcn20_add_dsc_to_stream_resource(struct dc *dc, struct dc_state *dc_ctx, struct dc_stream_state *dc_stream); -enum dc_status dcn20_remove_stream_from_ctx(struct dc *dc, struct dc_state *new_ctx, struct dc_stream_state *dc_stream); -enum dc_status dcn20_patch_unknown_plane_state(struct dc_plane_state *plane_state); - -#endif /* __DC_RESOURCE_DCN20_H__ */ - diff --git a/drivers/gpu/drm/amd/display/dc/dcn201/Makefile b/drivers/gpu/drm/amd/display/dc/dcn201/Makefile index 3a41a97b0729..c069a894db92 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn201/Makefile +++ b/drivers/gpu/drm/amd/display/dc/dcn201/Makefile @@ -1,7 +1,7 @@ # SPDX-License-Identifier: MIT # # Makefile for DCN. -DCN201 = dcn201_init.o dcn201_resource.o \ +DCN201 = dcn201_init.o \ dcn201_hubbub.o\ dcn201_mpc.o dcn201_hubp.o dcn201_opp.o dcn201_optc.o dcn201_dpp.o \ dcn201_dccg.o dcn201_link_encoder.o diff --git a/drivers/gpu/drm/amd/display/dc/dcn201/dcn201_resource.c b/drivers/gpu/drm/amd/display/dc/dcn201/dcn201_resource.c deleted file mode 100644 index bca22d867696..000000000000 --- a/drivers/gpu/drm/amd/display/dc/dcn201/dcn201_resource.c +++ /dev/null @@ -1,1308 +0,0 @@ -/* -* Copyright 2016 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 "dm_services.h" -#include "dc.h" - -#include "dcn201_init.h" -#include "dml/dcn20/dcn20_fpu.h" -#include "resource.h" -#include "include/irq_service_interface.h" -#include "dcn201_resource.h" - -#include "dcn20/dcn20_resource.h" - -#include "dcn10/dcn10_hubp.h" -#include "dcn10/dcn10_ipp.h" -#include "dcn201_mpc.h" -#include "dcn201_hubp.h" -#include "irq/dcn201/irq_service_dcn201.h" -#include "dcn201/dcn201_dpp.h" -#include "dcn201/dcn201_hubbub.h" -#include "dcn201_dccg.h" -#include "dcn201_optc.h" -#include "dcn201/dcn201_hwseq.h" -#include "dce110/dce110_hwseq.h" -#include "dcn201_opp.h" -#include "dcn201/dcn201_link_encoder.h" -#include "dcn20/dcn20_stream_encoder.h" -#include "dce/dce_clock_source.h" -#include "dce/dce_audio.h" -#include "dce/dce_hwseq.h" -#include "virtual/virtual_stream_encoder.h" -#include "dce110/dce110_resource.h" -#include "dce/dce_aux.h" -#include "dce/dce_i2c.h" -#include "dcn201_hubbub.h" -#include "dcn10/dcn10_resource.h" - -#include "cyan_skillfish_ip_offset.h" - -#include "dcn/dcn_2_0_3_offset.h" -#include "dcn/dcn_2_0_3_sh_mask.h" -#include "dpcs/dpcs_2_0_3_offset.h" -#include "dpcs/dpcs_2_0_3_sh_mask.h" - -#include "mmhub/mmhub_2_0_0_offset.h" -#include "mmhub/mmhub_2_0_0_sh_mask.h" -#include "nbio/nbio_7_4_offset.h" - -#include "reg_helper.h" - -#define MIN_DISP_CLK_KHZ 100000 -#define MIN_DPP_CLK_KHZ 100000 - -static struct _vcs_dpi_ip_params_st dcn201_ip = { - .gpuvm_enable = 0, - .hostvm_enable = 0, - .gpuvm_max_page_table_levels = 4, - .hostvm_max_page_table_levels = 4, - .hostvm_cached_page_table_levels = 0, - .pte_group_size_bytes = 2048, - .rob_buffer_size_kbytes = 168, - .det_buffer_size_kbytes = 164, - .dpte_buffer_size_in_pte_reqs_luma = 84, - .pde_proc_buffer_size_64k_reqs = 48, - .dpp_output_buffer_pixels = 2560, - .opp_output_buffer_lines = 1, - .pixel_chunk_size_kbytes = 8, - .pte_chunk_size_kbytes = 2, - .meta_chunk_size_kbytes = 2, - .writeback_chunk_size_kbytes = 2, - .line_buffer_size_bits = 789504, - .is_line_buffer_bpp_fixed = 0, - .line_buffer_fixed_bpp = 0, - .dcc_supported = true, - .max_line_buffer_lines = 12, - .writeback_luma_buffer_size_kbytes = 12, - .writeback_chroma_buffer_size_kbytes = 8, - .writeback_chroma_line_buffer_width_pixels = 4, - .writeback_max_hscl_ratio = 1, - .writeback_max_vscl_ratio = 1, - .writeback_min_hscl_ratio = 1, - .writeback_min_vscl_ratio = 1, - .writeback_max_hscl_taps = 12, - .writeback_max_vscl_taps = 12, - .writeback_line_buffer_luma_buffer_size = 0, - .writeback_line_buffer_chroma_buffer_size = 9600, - .cursor_buffer_size = 8, - .cursor_chunk_size = 2, - .max_num_otg = 2, - .max_num_dpp = 4, - .max_num_wb = 0, - .max_dchub_pscl_bw_pix_per_clk = 4, - .max_pscl_lb_bw_pix_per_clk = 2, - .max_lb_vscl_bw_pix_per_clk = 4, - .max_vscl_hscl_bw_pix_per_clk = 4, - .max_hscl_ratio = 8, - .max_vscl_ratio = 8, - .hscl_mults = 4, - .vscl_mults = 4, - .max_hscl_taps = 8, - .max_vscl_taps = 8, - .dispclk_ramp_margin_percent = 1, - .underscan_factor = 1.10, - .min_vblank_lines = 30, - .dppclk_delay_subtotal = 77, - .dppclk_delay_scl_lb_only = 16, - .dppclk_delay_scl = 50, - .dppclk_delay_cnvc_formatter = 8, - .dppclk_delay_cnvc_cursor = 6, - .dispclk_delay_subtotal = 87, - .dcfclk_cstate_latency = 10, - .max_inter_dcn_tile_repeaters = 8, - .number_of_cursors = 1, -}; - -static struct _vcs_dpi_soc_bounding_box_st dcn201_soc = { - .clock_limits = { - { - .state = 0, - .dscclk_mhz = 400.0, - .dcfclk_mhz = 1000.0, - .fabricclk_mhz = 200.0, - .dispclk_mhz = 300.0, - .dppclk_mhz = 300.0, - .phyclk_mhz = 810.0, - .socclk_mhz = 1254.0, - .dram_speed_mts = 2000.0, - }, - { - .state = 1, - .dscclk_mhz = 400.0, - .dcfclk_mhz = 1000.0, - .fabricclk_mhz = 250.0, - .dispclk_mhz = 1200.0, - .dppclk_mhz = 1200.0, - .phyclk_mhz = 810.0, - .socclk_mhz = 1254.0, - .dram_speed_mts = 3600.0, - }, - { - .state = 2, - .dscclk_mhz = 400.0, - .dcfclk_mhz = 1000.0, - .fabricclk_mhz = 750.0, - .dispclk_mhz = 1200.0, - .dppclk_mhz = 1200.0, - .phyclk_mhz = 810.0, - .socclk_mhz = 1254.0, - .dram_speed_mts = 6800.0, - }, - { - .state = 3, - .dscclk_mhz = 400.0, - .dcfclk_mhz = 1000.0, - .fabricclk_mhz = 250.0, - .dispclk_mhz = 1200.0, - .dppclk_mhz = 1200.0, - .phyclk_mhz = 810.0, - .socclk_mhz = 1254.0, - .dram_speed_mts = 14000.0, - }, - { - .state = 4, - .dscclk_mhz = 400.0, - .dcfclk_mhz = 1000.0, - .fabricclk_mhz = 750.0, - .dispclk_mhz = 1200.0, - .dppclk_mhz = 1200.0, - .phyclk_mhz = 810.0, - .socclk_mhz = 1254.0, - .dram_speed_mts = 14000.0, - } - }, - .num_states = 4, - .sr_exit_time_us = 9.0, - .sr_enter_plus_exit_time_us = 11.0, - .urgent_latency_us = 4.0, - .urgent_latency_pixel_data_only_us = 4.0, - .urgent_latency_pixel_mixed_with_vm_data_us = 4.0, - .urgent_latency_vm_data_only_us = 4.0, - .urgent_out_of_order_return_per_channel_pixel_only_bytes = 256, - .urgent_out_of_order_return_per_channel_pixel_and_vm_bytes = 256, - .urgent_out_of_order_return_per_channel_vm_only_bytes = 256, - .pct_ideal_dram_sdp_bw_after_urgent_pixel_only = 80.0, - .pct_ideal_dram_sdp_bw_after_urgent_pixel_and_vm = 80.0, - .pct_ideal_dram_sdp_bw_after_urgent_vm_only = 80.0, - .max_avg_sdp_bw_use_normal_percent = 80.0, - .max_avg_dram_bw_use_normal_percent = 69.0, - .writeback_latency_us = 12.0, - .ideal_dram_bw_after_urgent_percent = 80.0, - .max_request_size_bytes = 256, - .dram_channel_width_bytes = 2, - .fabric_datapath_to_dcn_data_return_bytes = 64, - .dcn_downspread_percent = 0.3, - .downspread_percent = 0.3, - .dram_page_open_time_ns = 50.0, - .dram_rw_turnaround_time_ns = 17.5, - .dram_return_buffer_per_channel_bytes = 8192, - .round_trip_ping_latency_dcfclk_cycles = 128, - .urgent_out_of_order_return_per_channel_bytes = 256, - .channel_interleave_bytes = 256, - .num_banks = 8, - .num_chans = 16, - .vmm_page_size_bytes = 4096, - .dram_clock_change_latency_us = 250.0, - .writeback_dram_clock_change_latency_us = 23.0, - .return_bus_width_bytes = 64, - .dispclk_dppclk_vco_speed_mhz = 3000, - .use_urgent_burst_bw = 0, -}; - -enum dcn20_clk_src_array_id { - DCN20_CLK_SRC_PLL0, - DCN20_CLK_SRC_PLL1, - DCN20_CLK_SRC_TOTAL_DCN201 -}; - -/* begin ********************* - * macros to expend register list macro defined in HW object header file */ - -/* DCN */ - -#undef BASE_INNER -#define BASE_INNER(seg) DMU_BASE__INST0_SEG ## seg - -#define BASE(seg) BASE_INNER(seg) - -#define SR(reg_name)\ - .reg_name = BASE(mm ## reg_name ## _BASE_IDX) + \ - mm ## reg_name - -#define SRI(reg_name, block, id)\ - .reg_name = BASE(mm ## block ## id ## _ ## reg_name ## _BASE_IDX) + \ - mm ## block ## id ## _ ## reg_name - -#define SRIR(var_name, reg_name, block, id)\ - .var_name = BASE(mm ## block ## id ## _ ## reg_name ## _BASE_IDX) + \ - mm ## block ## id ## _ ## reg_name - -#define SRII(reg_name, block, id)\ - .reg_name[id] = BASE(mm ## block ## id ## _ ## reg_name ## _BASE_IDX) + \ - mm ## block ## id ## _ ## reg_name - -#define SRI_IX(reg_name, block, id)\ - .reg_name = ix ## block ## id ## _ ## reg_name - -#define DCCG_SRII(reg_name, block, id)\ - .block ## _ ## reg_name[id] = BASE(mm ## block ## id ## _ ## reg_name ## _BASE_IDX) + \ - mm ## block ## id ## _ ## reg_name - -#define VUPDATE_SRII(reg_name, block, id)\ - .reg_name[id] = BASE(mm ## reg_name ## _ ## block ## id ## _BASE_IDX) + \ - mm ## reg_name ## _ ## block ## id - -/* NBIO */ -#define NBIO_BASE_INNER(seg) \ - NBIO_BASE__INST0_SEG ## seg - -#define NBIO_BASE(seg) \ - NBIO_BASE_INNER(seg) - -#define NBIO_SR(reg_name)\ - .reg_name = NBIO_BASE(mm ## reg_name ## _BASE_IDX) + \ - mm ## reg_name - -/* MMHUB */ -#define MMHUB_BASE_INNER(seg) \ - MMHUB_BASE__INST0_SEG ## seg - -#define MMHUB_BASE(seg) \ - MMHUB_BASE_INNER(seg) - -#define MMHUB_SR(reg_name)\ - .reg_name = MMHUB_BASE(mmMM ## reg_name ## _BASE_IDX) + \ - mmMM ## reg_name - -static const struct bios_registers bios_regs = { - NBIO_SR(BIOS_SCRATCH_3), - NBIO_SR(BIOS_SCRATCH_6) -}; - -#define clk_src_regs(index, pllid)\ -[index] = {\ - CS_COMMON_REG_LIST_DCN201(index, pllid),\ -} - -static const struct dce110_clk_src_regs clk_src_regs[] = { - clk_src_regs(0, A), - clk_src_regs(1, B) -}; - -static const struct dce110_clk_src_shift cs_shift = { - CS_COMMON_MASK_SH_LIST_DCN2_0(__SHIFT) -}; - -static const struct dce110_clk_src_mask cs_mask = { - CS_COMMON_MASK_SH_LIST_DCN2_0(_MASK) -}; - -#define audio_regs(id)\ -[id] = {\ - AUD_COMMON_REG_LIST(id)\ -} - -static const struct dce_audio_registers audio_regs[] = { - audio_regs(0), - audio_regs(1), -}; - -#define DCE120_AUD_COMMON_MASK_SH_LIST(mask_sh)\ - SF(AZF0ENDPOINT0_AZALIA_F0_CODEC_ENDPOINT_INDEX, AZALIA_ENDPOINT_REG_INDEX, mask_sh),\ - SF(AZF0ENDPOINT0_AZALIA_F0_CODEC_ENDPOINT_DATA, AZALIA_ENDPOINT_REG_DATA, mask_sh),\ - AUD_COMMON_MASK_SH_LIST_BASE(mask_sh) - -static const struct dce_audio_shift audio_shift = { - DCE120_AUD_COMMON_MASK_SH_LIST(__SHIFT) -}; - -static const struct dce_audio_mask audio_mask = { - DCE120_AUD_COMMON_MASK_SH_LIST(_MASK) -}; - -#define stream_enc_regs(id)\ -[id] = {\ - SE_DCN2_REG_LIST(id)\ -} - -static const struct dcn10_stream_enc_registers stream_enc_regs[] = { - stream_enc_regs(0), - stream_enc_regs(1) -}; - -static const struct dcn10_stream_encoder_shift se_shift = { - SE_COMMON_MASK_SH_LIST_DCN20(__SHIFT) -}; - -static const struct dcn10_stream_encoder_mask se_mask = { - SE_COMMON_MASK_SH_LIST_DCN20(_MASK) -}; - -static const struct dce110_aux_registers_shift aux_shift = { - DCN_AUX_MASK_SH_LIST(__SHIFT) -}; - -static const struct dce110_aux_registers_mask aux_mask = { - DCN_AUX_MASK_SH_LIST(_MASK) -}; - -#define aux_regs(id)\ -[id] = {\ - DCN2_AUX_REG_LIST(id)\ -} - -static const struct dcn10_link_enc_aux_registers link_enc_aux_regs[] = { - aux_regs(0), - aux_regs(1), -}; - -#define hpd_regs(id)\ -[id] = {\ - HPD_REG_LIST(id)\ -} - -static const struct dcn10_link_enc_hpd_registers link_enc_hpd_regs[] = { - hpd_regs(0), - hpd_regs(1), -}; - -#define link_regs(id, phyid)\ -[id] = {\ - LE_DCN_COMMON_REG_LIST(id), \ - UNIPHY_DCN2_REG_LIST(phyid) \ -} - -static const struct dcn10_link_enc_registers link_enc_regs[] = { - link_regs(0, A), - link_regs(1, B), -}; - -#define LINK_ENCODER_MASK_SH_LIST_DCN201(mask_sh)\ - LINK_ENCODER_MASK_SH_LIST_DCN20(mask_sh) - -static const struct dcn10_link_enc_shift le_shift = { - LINK_ENCODER_MASK_SH_LIST_DCN201(__SHIFT) -}; - -static const struct dcn10_link_enc_mask le_mask = { - LINK_ENCODER_MASK_SH_LIST_DCN201(_MASK) -}; - -#define ipp_regs(id)\ -[id] = {\ - IPP_REG_LIST_DCN201(id),\ -} - -static const struct dcn10_ipp_registers ipp_regs[] = { - ipp_regs(0), - ipp_regs(1), - ipp_regs(2), - ipp_regs(3), -}; - -static const struct dcn10_ipp_shift ipp_shift = { - IPP_MASK_SH_LIST_DCN201(__SHIFT) -}; - -static const struct dcn10_ipp_mask ipp_mask = { - IPP_MASK_SH_LIST_DCN201(_MASK) -}; - -#define opp_regs(id)\ -[id] = {\ - OPP_REG_LIST_DCN201(id),\ -} - -static const struct dcn201_opp_registers opp_regs[] = { - opp_regs(0), - opp_regs(1), -}; - -static const struct dcn201_opp_shift opp_shift = { - OPP_MASK_SH_LIST_DCN201(__SHIFT) -}; - -static const struct dcn201_opp_mask opp_mask = { - OPP_MASK_SH_LIST_DCN201(_MASK) -}; - -#define aux_engine_regs(id)\ -[id] = {\ - AUX_COMMON_REG_LIST0(id), \ - .AUX_RESET_MASK = 0 \ -} - -static const struct dce110_aux_registers aux_engine_regs[] = { - aux_engine_regs(0), - aux_engine_regs(1) -}; - -#define tf_regs(id)\ -[id] = {\ - TF_REG_LIST_DCN201(id),\ -} - -static const struct dcn201_dpp_registers tf_regs[] = { - tf_regs(0), - tf_regs(1), - tf_regs(2), - tf_regs(3), -}; - -static const struct dcn201_dpp_shift tf_shift = { - TF_REG_LIST_SH_MASK_DCN201(__SHIFT) -}; - -static const struct dcn201_dpp_mask tf_mask = { - TF_REG_LIST_SH_MASK_DCN201(_MASK) -}; - -static const struct dcn201_mpc_registers mpc_regs = { - MPC_REG_LIST_DCN201(0), - MPC_REG_LIST_DCN201(1), - MPC_REG_LIST_DCN201(2), - MPC_REG_LIST_DCN201(3), - MPC_REG_LIST_DCN201(4), - MPC_OUT_MUX_REG_LIST_DCN201(0), - MPC_OUT_MUX_REG_LIST_DCN201(1), -}; - -static const struct dcn201_mpc_shift mpc_shift = { - MPC_COMMON_MASK_SH_LIST_DCN201(__SHIFT) -}; - -static const struct dcn201_mpc_mask mpc_mask = { - MPC_COMMON_MASK_SH_LIST_DCN201(_MASK) -}; - -#define tg_regs_dcn201(id)\ -[id] = {TG_COMMON_REG_LIST_DCN201(id)} - -static const struct dcn_optc_registers tg_regs[] = { - tg_regs_dcn201(0), - tg_regs_dcn201(1) -}; - -static const struct dcn_optc_shift tg_shift = { - TG_COMMON_MASK_SH_LIST_DCN201(__SHIFT) -}; - -static const struct dcn_optc_mask tg_mask = { - TG_COMMON_MASK_SH_LIST_DCN201(_MASK) -}; - -#define hubp_regsDCN201(id)\ -[id] = {\ - HUBP_REG_LIST_DCN201(id)\ -} - -static const struct dcn201_hubp_registers hubp_regs[] = { - hubp_regsDCN201(0), - hubp_regsDCN201(1), - hubp_regsDCN201(2), - hubp_regsDCN201(3) -}; - -static const struct dcn201_hubp_shift hubp_shift = { - HUBP_MASK_SH_LIST_DCN201(__SHIFT) -}; - -static const struct dcn201_hubp_mask hubp_mask = { - HUBP_MASK_SH_LIST_DCN201(_MASK) -}; - -static const struct dcn_hubbub_registers hubbub_reg = { - HUBBUB_REG_LIST_DCN201(0) -}; - -static const struct dcn_hubbub_shift hubbub_shift = { - HUBBUB_MASK_SH_LIST_DCN201(__SHIFT) -}; - -static const struct dcn_hubbub_mask hubbub_mask = { - HUBBUB_MASK_SH_LIST_DCN201(_MASK) -}; - - -static const struct dccg_registers dccg_regs = { - DCCG_COMMON_REG_LIST_DCN_BASE() -}; - -static const struct dccg_shift dccg_shift = { - DCCG_COMMON_MASK_SH_LIST_DCN_COMMON_BASE(__SHIFT) -}; - -static const struct dccg_mask dccg_mask = { - DCCG_COMMON_MASK_SH_LIST_DCN_COMMON_BASE(_MASK) -}; - -static const struct resource_caps res_cap_dnc201 = { - .num_timing_generator = 2, - .num_opp = 2, - .num_video_plane = 4, - .num_audio = 2, - .num_stream_encoder = 2, - .num_pll = 2, - .num_ddc = 2, -}; - -static const struct dc_plane_cap plane_cap = { - .type = DC_PLANE_TYPE_DCN_UNIVERSAL, - .per_pixel_alpha = true, - - .pixel_format_support = { - .argb8888 = true, - .nv12 = false, - .fp16 = true, - .p010 = false, - }, - - .max_upscale_factor = { - .argb8888 = 16000, - .nv12 = 16000, - .fp16 = 1 - }, - - .max_downscale_factor = { - .argb8888 = 250, - .nv12 = 250, - .fp16 = 250 - }, - 64, - 64 -}; - -static const struct dc_debug_options debug_defaults_drv = { - .disable_dmcu = true, - .force_abm_enable = false, - .timing_trace = false, - .clock_trace = true, - .disable_pplib_clock_request = true, - .pipe_split_policy = MPC_SPLIT_DYNAMIC, - .force_single_disp_pipe_split = false, - .disable_dcc = DCC_ENABLE, - .vsr_support = true, - .performance_trace = false, - .az_endpoint_mute_only = true, - .max_downscale_src_width = 3840, - .disable_pplib_wm_range = true, - .scl_reset_length10 = true, - .sanity_checks = false, - .underflow_assert_delay_us = 0xFFFFFFFF, - .enable_tri_buf = false, - .enable_legacy_fast_update = true, - .using_dml2 = false, -}; - -static void dcn201_dpp_destroy(struct dpp **dpp) -{ - kfree(TO_DCN201_DPP(*dpp)); - *dpp = NULL; -} - -static struct dpp *dcn201_dpp_create( - struct dc_context *ctx, - uint32_t inst) -{ - struct dcn201_dpp *dpp = - kzalloc(sizeof(struct dcn201_dpp), GFP_ATOMIC); - - if (!dpp) - return NULL; - - if (dpp201_construct(dpp, ctx, inst, - &tf_regs[inst], &tf_shift, &tf_mask)) - return &dpp->base; - - kfree(dpp); - return NULL; -} - -static struct input_pixel_processor *dcn201_ipp_create( - struct dc_context *ctx, uint32_t inst) -{ - struct dcn10_ipp *ipp = - kzalloc(sizeof(struct dcn10_ipp), GFP_ATOMIC); - - if (!ipp) { - return NULL; - } - - dcn20_ipp_construct(ipp, ctx, inst, - &ipp_regs[inst], &ipp_shift, &ipp_mask); - return &ipp->base; -} - - -static struct output_pixel_processor *dcn201_opp_create( - struct dc_context *ctx, uint32_t inst) -{ - struct dcn201_opp *opp = - kzalloc(sizeof(struct dcn201_opp), GFP_ATOMIC); - - if (!opp) { - return NULL; - } - - dcn201_opp_construct(opp, ctx, inst, - &opp_regs[inst], &opp_shift, &opp_mask); - return &opp->base; -} - -static struct dce_aux *dcn201_aux_engine_create(struct dc_context *ctx, - uint32_t inst) -{ - struct aux_engine_dce110 *aux_engine = - kzalloc(sizeof(struct aux_engine_dce110), GFP_ATOMIC); - - if (!aux_engine) - return NULL; - - dce110_aux_engine_construct(aux_engine, ctx, inst, - SW_AUX_TIMEOUT_PERIOD_MULTIPLIER * AUX_TIMEOUT_PERIOD, - &aux_engine_regs[inst], - &aux_mask, - &aux_shift, - ctx->dc->caps.extended_aux_timeout_support); - - return &aux_engine->base; -} -#define i2c_inst_regs(id) { I2C_HW_ENGINE_COMMON_REG_LIST(id) } - -static const struct dce_i2c_registers i2c_hw_regs[] = { - i2c_inst_regs(1), - i2c_inst_regs(2), -}; - -static const struct dce_i2c_shift i2c_shifts = { - I2C_COMMON_MASK_SH_LIST_DCN2(__SHIFT) -}; - -static const struct dce_i2c_mask i2c_masks = { - I2C_COMMON_MASK_SH_LIST_DCN2(_MASK) -}; - -static struct dce_i2c_hw *dcn201_i2c_hw_create(struct dc_context *ctx, - uint32_t inst) -{ - struct dce_i2c_hw *dce_i2c_hw = - kzalloc(sizeof(struct dce_i2c_hw), GFP_ATOMIC); - - if (!dce_i2c_hw) - return NULL; - - dcn2_i2c_hw_construct(dce_i2c_hw, ctx, inst, - &i2c_hw_regs[inst], &i2c_shifts, &i2c_masks); - - return dce_i2c_hw; -} - -static struct mpc *dcn201_mpc_create(struct dc_context *ctx, uint32_t num_mpcc) -{ - struct dcn201_mpc *mpc201 = kzalloc(sizeof(struct dcn201_mpc), - GFP_ATOMIC); - - if (!mpc201) - return NULL; - - dcn201_mpc_construct(mpc201, ctx, - &mpc_regs, - &mpc_shift, - &mpc_mask, - num_mpcc); - - return &mpc201->base; -} - -static struct hubbub *dcn201_hubbub_create(struct dc_context *ctx) -{ - struct dcn20_hubbub *hubbub = kzalloc(sizeof(struct dcn20_hubbub), - GFP_ATOMIC); - - if (!hubbub) - return NULL; - - hubbub201_construct(hubbub, ctx, - &hubbub_reg, - &hubbub_shift, - &hubbub_mask); - - return &hubbub->base; -} - -static struct timing_generator *dcn201_timing_generator_create( - struct dc_context *ctx, - uint32_t instance) -{ - struct optc *tgn10 = - kzalloc(sizeof(struct optc), GFP_ATOMIC); - - if (!tgn10) - return NULL; - - tgn10->base.inst = instance; - tgn10->base.ctx = ctx; - - tgn10->tg_regs = &tg_regs[instance]; - tgn10->tg_shift = &tg_shift; - tgn10->tg_mask = &tg_mask; - - dcn201_timing_generator_init(tgn10); - - return &tgn10->base; -} - -static const struct encoder_feature_support link_enc_feature = { - .max_hdmi_deep_color = COLOR_DEPTH_121212, - .max_hdmi_pixel_clock = 600000, - .hdmi_ycbcr420_supported = true, - .dp_ycbcr420_supported = true, - .fec_supported = true, - .flags.bits.IS_HBR2_CAPABLE = true, - .flags.bits.IS_HBR3_CAPABLE = true, - .flags.bits.IS_TPS3_CAPABLE = true, - .flags.bits.IS_TPS4_CAPABLE = true -}; - -static struct link_encoder *dcn201_link_encoder_create( - struct dc_context *ctx, - const struct encoder_init_data *enc_init_data) -{ - struct dcn20_link_encoder *enc20 = - kzalloc(sizeof(struct dcn20_link_encoder), GFP_ATOMIC); - struct dcn10_link_encoder *enc10 = &enc20->enc10; - - if (!enc20) - return NULL; - - dcn201_link_encoder_construct(enc20, - enc_init_data, - &link_enc_feature, - &link_enc_regs[enc_init_data->transmitter], - &link_enc_aux_regs[enc_init_data->channel - 1], - &link_enc_hpd_regs[enc_init_data->hpd_source], - &le_shift, - &le_mask); - - return &enc10->base; -} - -static struct clock_source *dcn201_clock_source_create( - struct dc_context *ctx, - struct dc_bios *bios, - enum clock_source_id id, - const struct dce110_clk_src_regs *regs, - bool dp_clk_src) -{ - struct dce110_clk_src *clk_src = - kzalloc(sizeof(struct dce110_clk_src), GFP_ATOMIC); - - if (!clk_src) - return NULL; - - if (dce112_clk_src_construct(clk_src, ctx, bios, id, - regs, &cs_shift, &cs_mask)) { - clk_src->base.dp_clk_src = dp_clk_src; - return &clk_src->base; - } - kfree(clk_src); - return NULL; -} - -static void read_dce_straps( - struct dc_context *ctx, - struct resource_straps *straps) -{ - generic_reg_get(ctx, mmDC_PINSTRAPS + BASE(mmDC_PINSTRAPS_BASE_IDX), - - FN(DC_PINSTRAPS, DC_PINSTRAPS_AUDIO), &straps->dc_pinstraps_audio); -} - -static struct audio *dcn201_create_audio( - struct dc_context *ctx, unsigned int inst) -{ - return dce_audio_create(ctx, inst, - &audio_regs[inst], &audio_shift, &audio_mask); -} - -static struct stream_encoder *dcn201_stream_encoder_create( - enum engine_id eng_id, - struct dc_context *ctx) -{ - struct dcn10_stream_encoder *enc1 = - kzalloc(sizeof(struct dcn10_stream_encoder), GFP_ATOMIC); - - if (!enc1) - return NULL; - - dcn20_stream_encoder_construct(enc1, ctx, ctx->dc_bios, eng_id, - &stream_enc_regs[eng_id], - &se_shift, &se_mask); - - return &enc1->base; -} - -static const struct dce_hwseq_registers hwseq_reg = { - HWSEQ_DCN201_REG_LIST() -}; - -static const struct dce_hwseq_shift hwseq_shift = { - HWSEQ_DCN201_MASK_SH_LIST(__SHIFT) -}; - -static const struct dce_hwseq_mask hwseq_mask = { - HWSEQ_DCN201_MASK_SH_LIST(_MASK) -}; - -static struct dce_hwseq *dcn201_hwseq_create( - struct dc_context *ctx) -{ - struct dce_hwseq *hws = kzalloc(sizeof(struct dce_hwseq), GFP_ATOMIC); - - if (hws) { - hws->ctx = ctx; - hws->regs = &hwseq_reg; - hws->shifts = &hwseq_shift; - hws->masks = &hwseq_mask; - } - return hws; -} - -static const struct resource_create_funcs res_create_funcs = { - .read_dce_straps = read_dce_straps, - .create_audio = dcn201_create_audio, - .create_stream_encoder = dcn201_stream_encoder_create, - .create_hwseq = dcn201_hwseq_create, -}; - -static void dcn201_clock_source_destroy(struct clock_source **clk_src) -{ - kfree(TO_DCE110_CLK_SRC(*clk_src)); - *clk_src = NULL; -} - -static void dcn201_resource_destruct(struct dcn201_resource_pool *pool) -{ - unsigned int i; - - for (i = 0; i < pool->base.stream_enc_count; i++) { - if (pool->base.stream_enc[i] != NULL) { - kfree(DCN10STRENC_FROM_STRENC(pool->base.stream_enc[i])); - pool->base.stream_enc[i] = NULL; - } - } - - - if (pool->base.mpc != NULL) { - kfree(TO_DCN201_MPC(pool->base.mpc)); - pool->base.mpc = NULL; - } - - if (pool->base.hubbub != NULL) { - kfree(pool->base.hubbub); - pool->base.hubbub = NULL; - } - - for (i = 0; i < pool->base.pipe_count; i++) { - if (pool->base.dpps[i] != NULL) - dcn201_dpp_destroy(&pool->base.dpps[i]); - - if (pool->base.ipps[i] != NULL) - pool->base.ipps[i]->funcs->ipp_destroy(&pool->base.ipps[i]); - - if (pool->base.hubps[i] != NULL) { - kfree(TO_DCN10_HUBP(pool->base.hubps[i])); - pool->base.hubps[i] = NULL; - } - - if (pool->base.irqs != NULL) { - dal_irq_service_destroy(&pool->base.irqs); - } - } - - for (i = 0; i < pool->base.res_cap->num_opp; i++) { - if (pool->base.opps[i] != NULL) - pool->base.opps[i]->funcs->opp_destroy(&pool->base.opps[i]); - } - - for (i = 0; i < pool->base.res_cap->num_timing_generator; i++) { - if (pool->base.timing_generators[i] != NULL) { - kfree(DCN10TG_FROM_TG(pool->base.timing_generators[i])); - pool->base.timing_generators[i] = NULL; - } - } - for (i = 0; i < pool->base.audio_count; i++) { - if (pool->base.audios[i]) - dce_aud_destroy(&pool->base.audios[i]); - } - - for (i = 0; i < pool->base.clk_src_count; i++) { - if (pool->base.clock_sources[i] != NULL) { - dcn201_clock_source_destroy(&pool->base.clock_sources[i]); - pool->base.clock_sources[i] = NULL; - } - } - - if (pool->base.dp_clock_source != NULL) { - dcn201_clock_source_destroy(&pool->base.dp_clock_source); - pool->base.dp_clock_source = NULL; - } - - if (pool->base.dccg != NULL) - dcn_dccg_destroy(&pool->base.dccg); -} - -static struct hubp *dcn201_hubp_create( - struct dc_context *ctx, - uint32_t inst) -{ - struct dcn201_hubp *hubp201 = - kzalloc(sizeof(struct dcn201_hubp), GFP_ATOMIC); - - if (!hubp201) - return NULL; - - if (dcn201_hubp_construct(hubp201, ctx, inst, - &hubp_regs[inst], &hubp_shift, &hubp_mask)) - return &hubp201->base; - - kfree(hubp201); - return NULL; -} - -static struct pipe_ctx *dcn201_acquire_free_pipe_for_layer( - const struct dc_state *cur_ctx, - struct dc_state *new_ctx, - const struct resource_pool *pool, - const struct pipe_ctx *opp_head_pipe) -{ - struct resource_context *res_ctx = &new_ctx->res_ctx; - struct pipe_ctx *head_pipe = resource_get_otg_master_for_stream(res_ctx, opp_head_pipe->stream); - struct pipe_ctx *idle_pipe = resource_find_free_secondary_pipe_legacy(res_ctx, pool, head_pipe); - - if (!head_pipe) - ASSERT(0); - - if (!idle_pipe) - return NULL; - - idle_pipe->stream = head_pipe->stream; - idle_pipe->stream_res.tg = head_pipe->stream_res.tg; - idle_pipe->stream_res.opp = head_pipe->stream_res.opp; - - idle_pipe->plane_res.hubp = pool->hubps[idle_pipe->pipe_idx]; - idle_pipe->plane_res.ipp = pool->ipps[idle_pipe->pipe_idx]; - idle_pipe->plane_res.dpp = pool->dpps[idle_pipe->pipe_idx]; - idle_pipe->plane_res.mpcc_inst = pool->dpps[idle_pipe->pipe_idx]->inst; - - return idle_pipe; -} - -static bool dcn201_get_dcc_compression_cap(const struct dc *dc, - const struct dc_dcc_surface_param *input, - struct dc_surface_dcc_cap *output) -{ - return dc->res_pool->hubbub->funcs->get_dcc_compression_cap( - dc->res_pool->hubbub, - input, - output); -} - -static void dcn201_populate_dml_writeback_from_context(struct dc *dc, - struct resource_context *res_ctx, - display_e2e_pipe_params_st *pipes) -{ - DC_FP_START(); - dcn201_populate_dml_writeback_from_context_fpu(dc, res_ctx, pipes); - DC_FP_END(); -} - -static void dcn201_destroy_resource_pool(struct resource_pool **pool) -{ - struct dcn201_resource_pool *dcn201_pool = TO_DCN201_RES_POOL(*pool); - - dcn201_resource_destruct(dcn201_pool); - kfree(dcn201_pool); - *pool = NULL; -} - -static void dcn201_link_init(struct dc_link *link) -{ - if (link->ctx->dc_bios->integrated_info) - link->dp_ss_off = !link->ctx->dc_bios->integrated_info->dp_ss_control; -} - -static struct dc_cap_funcs cap_funcs = { - .get_dcc_compression_cap = dcn201_get_dcc_compression_cap, -}; - -static struct resource_funcs dcn201_res_pool_funcs = { - .link_init = dcn201_link_init, - .destroy = dcn201_destroy_resource_pool, - .link_enc_create = dcn201_link_encoder_create, - .panel_cntl_create = NULL, - .validate_bandwidth = dcn20_validate_bandwidth, - .populate_dml_pipes = dcn20_populate_dml_pipes_from_context, - .add_stream_to_ctx = dcn20_add_stream_to_ctx, - .add_dsc_to_stream_resource = NULL, - .remove_stream_from_ctx = dcn20_remove_stream_from_ctx, - .acquire_free_pipe_as_secondary_dpp_pipe = dcn201_acquire_free_pipe_for_layer, - .release_pipe = dcn20_release_pipe, - .populate_dml_writeback_from_context = dcn201_populate_dml_writeback_from_context, - .patch_unknown_plane_state = dcn20_patch_unknown_plane_state, - .set_mcif_arb_params = dcn20_set_mcif_arb_params, - .find_first_free_match_stream_enc_for_link = dcn10_find_first_free_match_stream_enc_for_link -}; - -static bool dcn201_resource_construct( - uint8_t num_virtual_links, - struct dc *dc, - struct dcn201_resource_pool *pool) -{ - int i; - struct dc_context *ctx = dc->ctx; - - ctx->dc_bios->regs = &bios_regs; - - pool->base.res_cap = &res_cap_dnc201; - pool->base.funcs = &dcn201_res_pool_funcs; - - /************************************************* - * Resource + asic cap harcoding * - *************************************************/ - pool->base.underlay_pipe_index = NO_UNDERLAY_PIPE; - - pool->base.pipe_count = 4; - pool->base.mpcc_count = 5; - dc->caps.max_downscale_ratio = 200; - dc->caps.i2c_speed_in_khz = 100; - dc->caps.i2c_speed_in_khz_hdcp = 5; /*1.5 w/a applied by default*/ - dc->caps.max_cursor_size = 256; - dc->caps.min_horizontal_blanking_period = 80; - dc->caps.dmdata_alloc_size = 2048; - - dc->caps.max_slave_planes = 1; - dc->caps.max_slave_yuv_planes = 1; - dc->caps.max_slave_rgb_planes = 1; - dc->caps.post_blend_color_processing = true; - dc->caps.force_dp_tps4_for_cp2520 = true; - dc->caps.extended_aux_timeout_support = true; - - /* Color pipeline capabilities */ - dc->caps.color.dpp.dcn_arch = 1; - dc->caps.color.dpp.input_lut_shared = 0; - dc->caps.color.dpp.icsc = 1; - dc->caps.color.dpp.dgam_ram = 1; - dc->caps.color.dpp.dgam_rom_caps.srgb = 1; - dc->caps.color.dpp.dgam_rom_caps.bt2020 = 1; - dc->caps.color.dpp.dgam_rom_caps.gamma2_2 = 0; - dc->caps.color.dpp.dgam_rom_caps.pq = 0; - dc->caps.color.dpp.dgam_rom_caps.hlg = 0; - dc->caps.color.dpp.post_csc = 0; - dc->caps.color.dpp.gamma_corr = 0; - dc->caps.color.dpp.dgam_rom_for_yuv = 1; - - dc->caps.color.dpp.hw_3d_lut = 1; - dc->caps.color.dpp.ogam_ram = 1; - // no OGAM ROM on DCN2 - dc->caps.color.dpp.ogam_rom_caps.srgb = 0; - dc->caps.color.dpp.ogam_rom_caps.bt2020 = 0; - dc->caps.color.dpp.ogam_rom_caps.gamma2_2 = 0; - dc->caps.color.dpp.ogam_rom_caps.pq = 0; - dc->caps.color.dpp.ogam_rom_caps.hlg = 0; - dc->caps.color.dpp.ocsc = 0; - - dc->caps.color.mpc.gamut_remap = 0; - dc->caps.color.mpc.num_3dluts = 0; - dc->caps.color.mpc.shared_3d_lut = 0; - dc->caps.color.mpc.ogam_ram = 1; - dc->caps.color.mpc.ogam_rom_caps.srgb = 0; - dc->caps.color.mpc.ogam_rom_caps.bt2020 = 0; - dc->caps.color.mpc.ogam_rom_caps.gamma2_2 = 0; - dc->caps.color.mpc.ogam_rom_caps.pq = 0; - dc->caps.color.mpc.ogam_rom_caps.hlg = 0; - dc->caps.color.mpc.ocsc = 1; - - dc->debug = debug_defaults_drv; - - /*a0 only, remove later*/ - dc->work_arounds.no_connect_phy_config = true; - dc->work_arounds.dedcn20_305_wa = true; - /************************************************* - * Create resources * - *************************************************/ - - pool->base.clock_sources[DCN20_CLK_SRC_PLL0] = - dcn201_clock_source_create(ctx, ctx->dc_bios, - CLOCK_SOURCE_COMBO_PHY_PLL0, - &clk_src_regs[0], false); - pool->base.clock_sources[DCN20_CLK_SRC_PLL1] = - dcn201_clock_source_create(ctx, ctx->dc_bios, - CLOCK_SOURCE_COMBO_PHY_PLL1, - &clk_src_regs[1], false); - - pool->base.clk_src_count = DCN20_CLK_SRC_TOTAL_DCN201; - - /* todo: not reuse phy_pll registers */ - pool->base.dp_clock_source = - dcn201_clock_source_create(ctx, ctx->dc_bios, - CLOCK_SOURCE_ID_DP_DTO, - &clk_src_regs[0], true); - - for (i = 0; i < pool->base.clk_src_count; i++) { - if (pool->base.clock_sources[i] == NULL) { - dm_error("DC: failed to create clock sources!\n"); - goto create_fail; - } - } - - pool->base.dccg = dccg201_create(ctx, &dccg_regs, &dccg_shift, &dccg_mask); - if (pool->base.dccg == NULL) { - dm_error("DC: failed to create dccg!\n"); - goto create_fail; - } - - dcn201_ip.max_num_otg = pool->base.res_cap->num_timing_generator; - dcn201_ip.max_num_dpp = pool->base.pipe_count; - dml_init_instance(&dc->dml, &dcn201_soc, &dcn201_ip, DML_PROJECT_DCN201); - { - struct irq_service_init_data init_data; - init_data.ctx = dc->ctx; - pool->base.irqs = dal_irq_service_dcn201_create(&init_data); - if (!pool->base.irqs) - goto create_fail; - } - - /* mem input -> ipp -> dpp -> opp -> TG */ - for (i = 0; i < pool->base.pipe_count; i++) { - pool->base.hubps[i] = dcn201_hubp_create(ctx, i); - if (pool->base.hubps[i] == NULL) { - dm_error( - "DC: failed to create memory input!\n"); - goto create_fail; - } - - pool->base.ipps[i] = dcn201_ipp_create(ctx, i); - if (pool->base.ipps[i] == NULL) { - dm_error( - "DC: failed to create input pixel processor!\n"); - goto create_fail; - } - - pool->base.dpps[i] = dcn201_dpp_create(ctx, i); - if (pool->base.dpps[i] == NULL) { - dm_error( - "DC: failed to create dpps!\n"); - goto create_fail; - } - } - - for (i = 0; i < pool->base.res_cap->num_opp; i++) { - pool->base.opps[i] = dcn201_opp_create(ctx, i); - if (pool->base.opps[i] == NULL) { - dm_error( - "DC: failed to create output pixel processor!\n"); - goto create_fail; - } - } - - for (i = 0; i < pool->base.res_cap->num_ddc; i++) { - pool->base.engines[i] = dcn201_aux_engine_create(ctx, i); - if (pool->base.engines[i] == NULL) { - dm_error( - "DC:failed to create aux engine!!\n"); - goto create_fail; - } - pool->base.hw_i2cs[i] = dcn201_i2c_hw_create(ctx, i); - if (pool->base.hw_i2cs[i] == NULL) { - dm_error( - "DC:failed to create hw i2c!!\n"); - goto create_fail; - } - pool->base.sw_i2cs[i] = NULL; - } - - for (i = 0; i < pool->base.res_cap->num_timing_generator; i++) { - pool->base.timing_generators[i] = dcn201_timing_generator_create( - ctx, i); - if (pool->base.timing_generators[i] == NULL) { - dm_error("DC: failed to create tg!\n"); - goto create_fail; - } - } - - pool->base.timing_generator_count = i; - - pool->base.mpc = dcn201_mpc_create(ctx, pool->base.mpcc_count); - if (pool->base.mpc == NULL) { - dm_error("DC: failed to create mpc!\n"); - goto create_fail; - } - - pool->base.hubbub = dcn201_hubbub_create(ctx); - if (pool->base.hubbub == NULL) { - dm_error("DC: failed to create hubbub!\n"); - goto create_fail; - } - - if (!resource_construct(num_virtual_links, dc, &pool->base, - &res_create_funcs)) - goto create_fail; - - dcn201_hw_sequencer_construct(dc); - - dc->caps.max_planes = pool->base.pipe_count; - - for (i = 0; i < dc->caps.max_planes; ++i) - dc->caps.planes[i] = plane_cap; - - dc->cap_funcs = cap_funcs; - - return true; - -create_fail: - - dcn201_resource_destruct(pool); - - return false; -} - -struct resource_pool *dcn201_create_resource_pool( - const struct dc_init_data *init_data, - struct dc *dc) -{ - struct dcn201_resource_pool *pool = - kzalloc(sizeof(struct dcn201_resource_pool), GFP_ATOMIC); - - if (!pool) - return NULL; - - if (dcn201_resource_construct(init_data->num_virtual_links, dc, pool)) - return &pool->base; - - kfree(pool); - return NULL; -} diff --git a/drivers/gpu/drm/amd/display/dc/dcn201/dcn201_resource.h b/drivers/gpu/drm/amd/display/dc/dcn201/dcn201_resource.h deleted file mode 100644 index e0467d17d4ae..000000000000 --- a/drivers/gpu/drm/amd/display/dc/dcn201/dcn201_resource.h +++ /dev/null @@ -1,50 +0,0 @@ -/* -* Copyright 2017 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_RESOURCE_DCN201_H__ -#define __DC_RESOURCE_DCN201_H__ - -#include "core_types.h" - -#define RRDPCS_PHY_DP_TX_PSTATE_POWER_UP 0x00000000 -#define RRDPCS_PHY_DP_TX_PSTATE_HOLD 0x00000001 -#define RRDPCS_PHY_DP_TX_PSTATE_HOLD_OFF 0x00000002 -#define RRDPCS_PHY_DP_TX_PSTATE_POWER_DOWN 0x00000003 - -#define TO_DCN201_RES_POOL(pool)\ - container_of(pool, struct dcn201_resource_pool, base) - -struct dc; -struct resource_pool; -struct _vcs_dpi_display_pipe_params_st; - -struct dcn201_resource_pool { - struct resource_pool base; -}; -struct resource_pool *dcn201_create_resource_pool( - const struct dc_init_data *init_data, - struct dc *dc); - -#endif /* __DC_RESOURCE_DCN201_H__ */ diff --git a/drivers/gpu/drm/amd/display/dc/dcn21/Makefile b/drivers/gpu/drm/amd/display/dc/dcn21/Makefile index ce1be0afae4a..dd1eea7212f4 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn21/Makefile +++ b/drivers/gpu/drm/amd/display/dc/dcn21/Makefile @@ -2,7 +2,7 @@ # # Makefile for DCN21. -DCN21 = dcn21_init.o dcn21_hubp.o dcn21_hubbub.o dcn21_resource.o \ +DCN21 = dcn21_init.o dcn21_hubp.o dcn21_hubbub.o \ dcn21_link_encoder.o dcn21_dccg.o AMD_DAL_DCN21 = $(addprefix $(AMDDALPATH)/dc/dcn21/,$(DCN21)) diff --git a/drivers/gpu/drm/amd/display/dc/dcn21/dcn21_resource.c b/drivers/gpu/drm/amd/display/dc/dcn21/dcn21_resource.c deleted file mode 100644 index 42277b280586..000000000000 --- a/drivers/gpu/drm/amd/display/dc/dcn21/dcn21_resource.c +++ /dev/null @@ -1,1745 +0,0 @@ -/* -* Copyright 2018 Advanced Micro Devices, Inc. - * Copyright 2019 Raptor Engineering, LLC - * - * 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 - -#include "dm_services.h" -#include "dc.h" - -#include "dcn21_init.h" - -#include "resource.h" -#include "include/irq_service_interface.h" -#include "dcn20/dcn20_resource.h" -#include "dcn21/dcn21_resource.h" - -#include "dml/dcn20/dcn20_fpu.h" - -#include "clk_mgr.h" -#include "dcn10/dcn10_hubp.h" -#include "dcn10/dcn10_ipp.h" -#include "dcn20/dcn20_hubbub.h" -#include "dcn20/dcn20_mpc.h" -#include "dcn20/dcn20_hubp.h" -#include "dcn21_hubp.h" -#include "irq/dcn21/irq_service_dcn21.h" -#include "dcn20/dcn20_dpp.h" -#include "dcn20/dcn20_optc.h" -#include "dcn21/dcn21_hwseq.h" -#include "dce110/dce110_hwseq.h" -#include "dcn20/dcn20_opp.h" -#include "dcn20/dcn20_dsc.h" -#include "dcn21/dcn21_link_encoder.h" -#include "dcn20/dcn20_stream_encoder.h" -#include "dce/dce_clock_source.h" -#include "dce/dce_audio.h" -#include "dce/dce_hwseq.h" -#include "virtual/virtual_stream_encoder.h" -#include "dml/display_mode_vba.h" -#include "dcn20/dcn20_dccg.h" -#include "dcn21/dcn21_dccg.h" -#include "dcn21_hubbub.h" -#include "dcn10/dcn10_resource.h" -#include "dce/dce_panel_cntl.h" - -#include "dcn20/dcn20_dwb.h" -#include "dcn20/dcn20_mmhubbub.h" -#include "dpcs/dpcs_2_1_0_offset.h" -#include "dpcs/dpcs_2_1_0_sh_mask.h" - -#include "renoir_ip_offset.h" -#include "dcn/dcn_2_1_0_offset.h" -#include "dcn/dcn_2_1_0_sh_mask.h" - -#include "nbio/nbio_7_0_offset.h" - -#include "mmhub/mmhub_2_0_0_offset.h" -#include "mmhub/mmhub_2_0_0_sh_mask.h" - -#include "reg_helper.h" -#include "dce/dce_abm.h" -#include "dce/dce_dmcu.h" -#include "dce/dce_aux.h" -#include "dce/dce_i2c.h" -#include "dcn21_resource.h" -#include "vm_helper.h" -#include "dcn20/dcn20_vmid.h" -#include "dce/dmub_psr.h" -#include "dce/dmub_abm.h" - -/* begin ********************* - * macros to expend register list macro defined in HW object header file */ - -/* DCN */ -#define BASE_INNER(seg) DMU_BASE__INST0_SEG ## seg - -#define BASE(seg) BASE_INNER(seg) - -#define SR(reg_name)\ - .reg_name = BASE(mm ## reg_name ## _BASE_IDX) + \ - mm ## reg_name - -#define SRI(reg_name, block, id)\ - .reg_name = BASE(mm ## block ## id ## _ ## reg_name ## _BASE_IDX) + \ - mm ## block ## id ## _ ## reg_name - -#define SRIR(var_name, reg_name, block, id)\ - .var_name = BASE(mm ## block ## id ## _ ## reg_name ## _BASE_IDX) + \ - mm ## block ## id ## _ ## reg_name - -#define SRII(reg_name, block, id)\ - .reg_name[id] = BASE(mm ## block ## id ## _ ## reg_name ## _BASE_IDX) + \ - mm ## block ## id ## _ ## reg_name - -#define DCCG_SRII(reg_name, block, id)\ - .block ## _ ## reg_name[id] = BASE(mm ## block ## id ## _ ## reg_name ## _BASE_IDX) + \ - mm ## block ## id ## _ ## reg_name - -#define VUPDATE_SRII(reg_name, block, id)\ - .reg_name[id] = BASE(mm ## reg_name ## _ ## block ## id ## _BASE_IDX) + \ - mm ## reg_name ## _ ## block ## id - -/* NBIO */ -#define NBIO_BASE_INNER(seg) \ - NBIF0_BASE__INST0_SEG ## seg - -#define NBIO_BASE(seg) \ - NBIO_BASE_INNER(seg) - -#define NBIO_SR(reg_name)\ - .reg_name = NBIO_BASE(mm ## reg_name ## _BASE_IDX) + \ - mm ## reg_name - -/* MMHUB */ -#define MMHUB_BASE_INNER(seg) \ - MMHUB_BASE__INST0_SEG ## seg - -#define MMHUB_BASE(seg) \ - MMHUB_BASE_INNER(seg) - -#define MMHUB_SR(reg_name)\ - .reg_name = MMHUB_BASE(mmMM ## reg_name ## _BASE_IDX) + \ - mmMM ## reg_name - -#define clk_src_regs(index, pllid)\ -[index] = {\ - CS_COMMON_REG_LIST_DCN2_1(index, pllid),\ -} - -static const struct dce110_clk_src_regs clk_src_regs[] = { - clk_src_regs(0, A), - clk_src_regs(1, B), - clk_src_regs(2, C), - clk_src_regs(3, D), - clk_src_regs(4, E), -}; - -static const struct dce110_clk_src_shift cs_shift = { - CS_COMMON_MASK_SH_LIST_DCN2_0(__SHIFT) -}; - -static const struct dce110_clk_src_mask cs_mask = { - CS_COMMON_MASK_SH_LIST_DCN2_0(_MASK) -}; - -static const struct bios_registers bios_regs = { - NBIO_SR(BIOS_SCRATCH_3), - NBIO_SR(BIOS_SCRATCH_6) -}; - -static const struct dce_dmcu_registers dmcu_regs = { - DMCU_DCN20_REG_LIST() -}; - -static const struct dce_dmcu_shift dmcu_shift = { - DMCU_MASK_SH_LIST_DCN10(__SHIFT) -}; - -static const struct dce_dmcu_mask dmcu_mask = { - DMCU_MASK_SH_LIST_DCN10(_MASK) -}; - -static const struct dce_abm_registers abm_regs = { - ABM_DCN20_REG_LIST() -}; - -static const struct dce_abm_shift abm_shift = { - ABM_MASK_SH_LIST_DCN20(__SHIFT) -}; - -static const struct dce_abm_mask abm_mask = { - ABM_MASK_SH_LIST_DCN20(_MASK) -}; - -#define audio_regs(id)\ -[id] = {\ - AUD_COMMON_REG_LIST(id)\ -} - -static const struct dce_audio_registers audio_regs[] = { - audio_regs(0), - audio_regs(1), - audio_regs(2), - audio_regs(3), - audio_regs(4), - audio_regs(5), -}; - -#define DCE120_AUD_COMMON_MASK_SH_LIST(mask_sh)\ - SF(AZF0ENDPOINT0_AZALIA_F0_CODEC_ENDPOINT_INDEX, AZALIA_ENDPOINT_REG_INDEX, mask_sh),\ - SF(AZF0ENDPOINT0_AZALIA_F0_CODEC_ENDPOINT_DATA, AZALIA_ENDPOINT_REG_DATA, mask_sh),\ - AUD_COMMON_MASK_SH_LIST_BASE(mask_sh) - -static const struct dce_audio_shift audio_shift = { - DCE120_AUD_COMMON_MASK_SH_LIST(__SHIFT) -}; - -static const struct dce_audio_mask audio_mask = { - DCE120_AUD_COMMON_MASK_SH_LIST(_MASK) -}; - -static const struct dccg_registers dccg_regs = { - DCCG_COMMON_REG_LIST_DCN_BASE() -}; - -static const struct dccg_shift dccg_shift = { - DCCG_MASK_SH_LIST_DCN2_1(__SHIFT) -}; - -static const struct dccg_mask dccg_mask = { - DCCG_MASK_SH_LIST_DCN2_1(_MASK) -}; - -#define opp_regs(id)\ -[id] = {\ - OPP_REG_LIST_DCN20(id),\ -} - -static const struct dcn20_opp_registers opp_regs[] = { - opp_regs(0), - opp_regs(1), - opp_regs(2), - opp_regs(3), - opp_regs(4), - opp_regs(5), -}; - -static const struct dcn20_opp_shift opp_shift = { - OPP_MASK_SH_LIST_DCN20(__SHIFT) -}; - -static const struct dcn20_opp_mask opp_mask = { - OPP_MASK_SH_LIST_DCN20(_MASK) -}; - -#define tg_regs(id)\ -[id] = {TG_COMMON_REG_LIST_DCN2_0(id)} - -static const struct dcn_optc_registers tg_regs[] = { - tg_regs(0), - tg_regs(1), - tg_regs(2), - tg_regs(3) -}; - -static const struct dcn_optc_shift tg_shift = { - TG_COMMON_MASK_SH_LIST_DCN2_0(__SHIFT) -}; - -static const struct dcn_optc_mask tg_mask = { - TG_COMMON_MASK_SH_LIST_DCN2_0(_MASK) -}; - -static const struct dcn20_mpc_registers mpc_regs = { - MPC_REG_LIST_DCN2_0(0), - MPC_REG_LIST_DCN2_0(1), - MPC_REG_LIST_DCN2_0(2), - MPC_REG_LIST_DCN2_0(3), - MPC_REG_LIST_DCN2_0(4), - MPC_REG_LIST_DCN2_0(5), - MPC_OUT_MUX_REG_LIST_DCN2_0(0), - MPC_OUT_MUX_REG_LIST_DCN2_0(1), - MPC_OUT_MUX_REG_LIST_DCN2_0(2), - MPC_OUT_MUX_REG_LIST_DCN2_0(3), - MPC_DBG_REG_LIST_DCN2_0() -}; - -static const struct dcn20_mpc_shift mpc_shift = { - MPC_COMMON_MASK_SH_LIST_DCN2_0(__SHIFT), - MPC_DEBUG_REG_LIST_SH_DCN20 -}; - -static const struct dcn20_mpc_mask mpc_mask = { - MPC_COMMON_MASK_SH_LIST_DCN2_0(_MASK), - MPC_DEBUG_REG_LIST_MASK_DCN20 -}; - -#define hubp_regs(id)\ -[id] = {\ - HUBP_REG_LIST_DCN21(id)\ -} - -static const struct dcn_hubp2_registers hubp_regs[] = { - hubp_regs(0), - hubp_regs(1), - hubp_regs(2), - hubp_regs(3) -}; - -static const struct dcn_hubp2_shift hubp_shift = { - HUBP_MASK_SH_LIST_DCN21(__SHIFT) -}; - -static const struct dcn_hubp2_mask hubp_mask = { - HUBP_MASK_SH_LIST_DCN21(_MASK) -}; - -static const struct dcn_hubbub_registers hubbub_reg = { - HUBBUB_REG_LIST_DCN21() -}; - -static const struct dcn_hubbub_shift hubbub_shift = { - HUBBUB_MASK_SH_LIST_DCN21(__SHIFT) -}; - -static const struct dcn_hubbub_mask hubbub_mask = { - HUBBUB_MASK_SH_LIST_DCN21(_MASK) -}; - - -#define vmid_regs(id)\ -[id] = {\ - DCN20_VMID_REG_LIST(id)\ -} - -static const struct dcn_vmid_registers vmid_regs[] = { - vmid_regs(0), - vmid_regs(1), - vmid_regs(2), - vmid_regs(3), - vmid_regs(4), - vmid_regs(5), - vmid_regs(6), - vmid_regs(7), - vmid_regs(8), - vmid_regs(9), - vmid_regs(10), - vmid_regs(11), - vmid_regs(12), - vmid_regs(13), - vmid_regs(14), - vmid_regs(15) -}; - -static const struct dcn20_vmid_shift vmid_shifts = { - DCN20_VMID_MASK_SH_LIST(__SHIFT) -}; - -static const struct dcn20_vmid_mask vmid_masks = { - DCN20_VMID_MASK_SH_LIST(_MASK) -}; - -#define dsc_regsDCN20(id)\ -[id] = {\ - DSC_REG_LIST_DCN20(id)\ -} - -static const struct dcn20_dsc_registers dsc_regs[] = { - dsc_regsDCN20(0), - dsc_regsDCN20(1), - dsc_regsDCN20(2), - dsc_regsDCN20(3), - dsc_regsDCN20(4), - dsc_regsDCN20(5) -}; - -static const struct dcn20_dsc_shift dsc_shift = { - DSC_REG_LIST_SH_MASK_DCN20(__SHIFT) -}; - -static const struct dcn20_dsc_mask dsc_mask = { - DSC_REG_LIST_SH_MASK_DCN20(_MASK) -}; - -#define ipp_regs(id)\ -[id] = {\ - IPP_REG_LIST_DCN20(id),\ -} - -static const struct dcn10_ipp_registers ipp_regs[] = { - ipp_regs(0), - ipp_regs(1), - ipp_regs(2), - ipp_regs(3), -}; - -static const struct dcn10_ipp_shift ipp_shift = { - IPP_MASK_SH_LIST_DCN20(__SHIFT) -}; - -static const struct dcn10_ipp_mask ipp_mask = { - IPP_MASK_SH_LIST_DCN20(_MASK), -}; - -#define opp_regs(id)\ -[id] = {\ - OPP_REG_LIST_DCN20(id),\ -} - - -#define aux_engine_regs(id)\ -[id] = {\ - AUX_COMMON_REG_LIST0(id), \ - .AUXN_IMPCAL = 0, \ - .AUXP_IMPCAL = 0, \ - .AUX_RESET_MASK = DP_AUX0_AUX_CONTROL__AUX_RESET_MASK, \ -} - -static const struct dce110_aux_registers aux_engine_regs[] = { - aux_engine_regs(0), - aux_engine_regs(1), - aux_engine_regs(2), - aux_engine_regs(3), - aux_engine_regs(4), -}; - -#define tf_regs(id)\ -[id] = {\ - TF_REG_LIST_DCN20(id),\ - TF_REG_LIST_DCN20_COMMON_APPEND(id),\ -} - -static const struct dcn2_dpp_registers tf_regs[] = { - tf_regs(0), - tf_regs(1), - tf_regs(2), - tf_regs(3), -}; - -static const struct dcn2_dpp_shift tf_shift = { - TF_REG_LIST_SH_MASK_DCN20(__SHIFT), - TF_DEBUG_REG_LIST_SH_DCN20 -}; - -static const struct dcn2_dpp_mask tf_mask = { - TF_REG_LIST_SH_MASK_DCN20(_MASK), - TF_DEBUG_REG_LIST_MASK_DCN20 -}; - -#define stream_enc_regs(id)\ -[id] = {\ - SE_DCN2_REG_LIST(id)\ -} - -static const struct dcn10_stream_enc_registers stream_enc_regs[] = { - stream_enc_regs(0), - stream_enc_regs(1), - stream_enc_regs(2), - stream_enc_regs(3), - stream_enc_regs(4), -}; - -static const struct dce110_aux_registers_shift aux_shift = { - DCN_AUX_MASK_SH_LIST(__SHIFT) -}; - -static const struct dce110_aux_registers_mask aux_mask = { - DCN_AUX_MASK_SH_LIST(_MASK) -}; - -static const struct dcn10_stream_encoder_shift se_shift = { - SE_COMMON_MASK_SH_LIST_DCN20(__SHIFT) -}; - -static const struct dcn10_stream_encoder_mask se_mask = { - SE_COMMON_MASK_SH_LIST_DCN20(_MASK) -}; - -static void dcn21_pp_smu_destroy(struct pp_smu_funcs **pp_smu); - -static struct input_pixel_processor *dcn21_ipp_create( - struct dc_context *ctx, uint32_t inst) -{ - struct dcn10_ipp *ipp = - kzalloc(sizeof(struct dcn10_ipp), GFP_KERNEL); - - if (!ipp) { - BREAK_TO_DEBUGGER(); - return NULL; - } - - dcn20_ipp_construct(ipp, ctx, inst, - &ipp_regs[inst], &ipp_shift, &ipp_mask); - return &ipp->base; -} - -static struct dpp *dcn21_dpp_create( - struct dc_context *ctx, - uint32_t inst) -{ - struct dcn20_dpp *dpp = - kzalloc(sizeof(struct dcn20_dpp), GFP_KERNEL); - - if (!dpp) - return NULL; - - if (dpp2_construct(dpp, ctx, inst, - &tf_regs[inst], &tf_shift, &tf_mask)) - return &dpp->base; - - BREAK_TO_DEBUGGER(); - kfree(dpp); - return NULL; -} - -static struct dce_aux *dcn21_aux_engine_create( - struct dc_context *ctx, - uint32_t inst) -{ - struct aux_engine_dce110 *aux_engine = - kzalloc(sizeof(struct aux_engine_dce110), GFP_KERNEL); - - if (!aux_engine) - return NULL; - - dce110_aux_engine_construct(aux_engine, ctx, inst, - SW_AUX_TIMEOUT_PERIOD_MULTIPLIER * AUX_TIMEOUT_PERIOD, - &aux_engine_regs[inst], - &aux_mask, - &aux_shift, - ctx->dc->caps.extended_aux_timeout_support); - - return &aux_engine->base; -} - -#define i2c_inst_regs(id) { I2C_HW_ENGINE_COMMON_REG_LIST(id) } - -static const struct dce_i2c_registers i2c_hw_regs[] = { - i2c_inst_regs(1), - i2c_inst_regs(2), - i2c_inst_regs(3), - i2c_inst_regs(4), - i2c_inst_regs(5), -}; - -static const struct dce_i2c_shift i2c_shifts = { - I2C_COMMON_MASK_SH_LIST_DCN2(__SHIFT) -}; - -static const struct dce_i2c_mask i2c_masks = { - I2C_COMMON_MASK_SH_LIST_DCN2(_MASK) -}; - -static struct dce_i2c_hw *dcn21_i2c_hw_create(struct dc_context *ctx, - uint32_t inst) -{ - struct dce_i2c_hw *dce_i2c_hw = - kzalloc(sizeof(struct dce_i2c_hw), GFP_KERNEL); - - if (!dce_i2c_hw) - return NULL; - - dcn2_i2c_hw_construct(dce_i2c_hw, ctx, inst, - &i2c_hw_regs[inst], &i2c_shifts, &i2c_masks); - - return dce_i2c_hw; -} - -static const struct resource_caps res_cap_rn = { - .num_timing_generator = 4, - .num_opp = 4, - .num_video_plane = 4, - .num_audio = 4, // 4 audio endpoints. 4 audio streams - .num_stream_encoder = 5, - .num_pll = 5, // maybe 3 because the last two used for USB-c - .num_dwb = 1, - .num_ddc = 5, - .num_vmid = 16, - .num_dsc = 3, -}; - -#ifdef DIAGS_BUILD -static const struct resource_caps res_cap_rn_FPGA_4pipe = { - .num_timing_generator = 4, - .num_opp = 4, - .num_video_plane = 4, - .num_audio = 7, - .num_stream_encoder = 4, - .num_pll = 4, - .num_dwb = 1, - .num_ddc = 4, - .num_dsc = 0, -}; - -static const struct resource_caps res_cap_rn_FPGA_2pipe_dsc = { - .num_timing_generator = 2, - .num_opp = 2, - .num_video_plane = 2, - .num_audio = 7, - .num_stream_encoder = 2, - .num_pll = 4, - .num_dwb = 1, - .num_ddc = 4, - .num_dsc = 2, -}; -#endif - -static const struct dc_plane_cap plane_cap = { - .type = DC_PLANE_TYPE_DCN_UNIVERSAL, - .per_pixel_alpha = true, - - .pixel_format_support = { - .argb8888 = true, - .nv12 = true, - .fp16 = true, - .p010 = true - }, - - .max_upscale_factor = { - .argb8888 = 16000, - .nv12 = 16000, - .fp16 = 16000 - }, - - .max_downscale_factor = { - .argb8888 = 250, - .nv12 = 250, - .fp16 = 250 - }, - 64, - 64 -}; - -static const struct dc_debug_options debug_defaults_drv = { - .disable_dmcu = false, - .force_abm_enable = false, - .timing_trace = false, - .clock_trace = true, - .disable_pplib_clock_request = true, - .min_disp_clk_khz = 100000, - .pipe_split_policy = MPC_SPLIT_DYNAMIC, - .force_single_disp_pipe_split = false, - .disable_dcc = DCC_ENABLE, - .vsr_support = true, - .performance_trace = false, - .max_downscale_src_width = 4096, - .disable_pplib_wm_range = false, - .scl_reset_length10 = true, - .sanity_checks = true, - .disable_48mhz_pwrdwn = false, - .usbc_combo_phy_reset_wa = true, - .dmub_command_table = true, - .use_max_lb = true, - .enable_legacy_fast_update = true, - .using_dml2 = false, -}; - -static const struct dc_panel_config panel_config_defaults = { - .psr = { - .disable_psr = false, - .disallow_psrsu = false, - .disallow_replay = false, - }, - .ilr = { - .optimize_edp_link_rate = true, - }, -}; - -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 -}; - -static void dcn21_resource_destruct(struct dcn21_resource_pool *pool) -{ - unsigned int i; - - for (i = 0; i < pool->base.stream_enc_count; i++) { - if (pool->base.stream_enc[i] != NULL) { - kfree(DCN10STRENC_FROM_STRENC(pool->base.stream_enc[i])); - pool->base.stream_enc[i] = NULL; - } - } - - for (i = 0; i < pool->base.res_cap->num_dsc; i++) { - if (pool->base.dscs[i] != NULL) - dcn20_dsc_destroy(&pool->base.dscs[i]); - } - - if (pool->base.mpc != NULL) { - kfree(TO_DCN20_MPC(pool->base.mpc)); - pool->base.mpc = NULL; - } - if (pool->base.hubbub != NULL) { - kfree(pool->base.hubbub); - pool->base.hubbub = NULL; - } - for (i = 0; i < pool->base.pipe_count; i++) { - if (pool->base.dpps[i] != NULL) - dcn20_dpp_destroy(&pool->base.dpps[i]); - - if (pool->base.ipps[i] != NULL) - pool->base.ipps[i]->funcs->ipp_destroy(&pool->base.ipps[i]); - - if (pool->base.hubps[i] != NULL) { - kfree(TO_DCN20_HUBP(pool->base.hubps[i])); - pool->base.hubps[i] = NULL; - } - - if (pool->base.irqs != NULL) { - dal_irq_service_destroy(&pool->base.irqs); - } - } - - for (i = 0; i < pool->base.res_cap->num_ddc; i++) { - if (pool->base.engines[i] != NULL) - dce110_engine_destroy(&pool->base.engines[i]); - if (pool->base.hw_i2cs[i] != NULL) { - kfree(pool->base.hw_i2cs[i]); - pool->base.hw_i2cs[i] = NULL; - } - if (pool->base.sw_i2cs[i] != NULL) { - kfree(pool->base.sw_i2cs[i]); - pool->base.sw_i2cs[i] = NULL; - } - } - - for (i = 0; i < pool->base.res_cap->num_opp; i++) { - if (pool->base.opps[i] != NULL) - pool->base.opps[i]->funcs->opp_destroy(&pool->base.opps[i]); - } - - for (i = 0; i < pool->base.res_cap->num_timing_generator; i++) { - if (pool->base.timing_generators[i] != NULL) { - kfree(DCN10TG_FROM_TG(pool->base.timing_generators[i])); - pool->base.timing_generators[i] = NULL; - } - } - - for (i = 0; i < pool->base.res_cap->num_dwb; i++) { - if (pool->base.dwbc[i] != NULL) { - kfree(TO_DCN20_DWBC(pool->base.dwbc[i])); - pool->base.dwbc[i] = NULL; - } - if (pool->base.mcif_wb[i] != NULL) { - kfree(TO_DCN20_MMHUBBUB(pool->base.mcif_wb[i])); - pool->base.mcif_wb[i] = NULL; - } - } - - for (i = 0; i < pool->base.audio_count; i++) { - if (pool->base.audios[i]) - dce_aud_destroy(&pool->base.audios[i]); - } - - for (i = 0; i < pool->base.clk_src_count; i++) { - if (pool->base.clock_sources[i] != NULL) { - dcn20_clock_source_destroy(&pool->base.clock_sources[i]); - pool->base.clock_sources[i] = NULL; - } - } - - if (pool->base.dp_clock_source != NULL) { - dcn20_clock_source_destroy(&pool->base.dp_clock_source); - pool->base.dp_clock_source = NULL; - } - - if (pool->base.abm != NULL) { - if (pool->base.abm->ctx->dc->config.disable_dmcu) - dmub_abm_destroy(&pool->base.abm); - else - dce_abm_destroy(&pool->base.abm); - } - - if (pool->base.dmcu != NULL) - dce_dmcu_destroy(&pool->base.dmcu); - - if (pool->base.psr != NULL) - dmub_psr_destroy(&pool->base.psr); - - if (pool->base.dccg != NULL) - dcn_dccg_destroy(&pool->base.dccg); - - if (pool->base.pp_smu != NULL) - dcn21_pp_smu_destroy(&pool->base.pp_smu); -} - -bool dcn21_fast_validate_bw(struct dc *dc, - struct dc_state *context, - display_e2e_pipe_params_st *pipes, - int *pipe_cnt_out, - int *pipe_split_from, - int *vlevel_out, - bool fast_validate) -{ - bool out = false; - int split[MAX_PIPES] = { 0 }; - int pipe_cnt, i, pipe_idx, vlevel; - - ASSERT(pipes); - if (!pipes) - return false; - - dcn20_merge_pipes_for_validate(dc, context); - - DC_FP_START(); - pipe_cnt = dc->res_pool->funcs->populate_dml_pipes(dc, context, pipes, fast_validate); - DC_FP_END(); - - *pipe_cnt_out = pipe_cnt; - - if (!pipe_cnt) { - out = true; - goto validate_out; - } - /* - * DML favors voltage over p-state, but we're more interested in - * supporting p-state over voltage. We can't support p-state in - * prefetch mode > 0 so try capping the prefetch mode to start. - */ - context->bw_ctx.dml.soc.allow_dram_self_refresh_or_dram_clock_change_in_vblank = - dm_allow_self_refresh_and_mclk_switch; - vlevel = dml_get_voltage_level(&context->bw_ctx.dml, pipes, pipe_cnt); - - if (vlevel > context->bw_ctx.dml.soc.num_states) { - /* - * If mode is unsupported or there's still no p-state support then - * fall back to favoring voltage. - * - * We don't actually support prefetch mode 2, so require that we - * at least support prefetch mode 1. - */ - context->bw_ctx.dml.soc.allow_dram_self_refresh_or_dram_clock_change_in_vblank = - dm_allow_self_refresh; - vlevel = dml_get_voltage_level(&context->bw_ctx.dml, pipes, pipe_cnt); - if (vlevel > context->bw_ctx.dml.soc.num_states) - goto validate_fail; - } - - vlevel = dcn20_validate_apply_pipe_split_flags(dc, context, vlevel, split, NULL); - - for (i = 0, pipe_idx = 0; i < dc->res_pool->pipe_count; i++) { - struct pipe_ctx *pipe = &context->res_ctx.pipe_ctx[i]; - struct pipe_ctx *mpo_pipe = pipe->bottom_pipe; - struct vba_vars_st *vba = &context->bw_ctx.dml.vba; - - if (!pipe->stream) - continue; - - /* We only support full screen mpo with ODM */ - if (vba->ODMCombineEnabled[vba->pipe_plane[pipe_idx]] != dm_odm_combine_mode_disabled - && pipe->plane_state && mpo_pipe - && memcmp(&mpo_pipe->plane_state->clip_rect, - &pipe->stream->src, - sizeof(struct rect)) != 0) { - ASSERT(mpo_pipe->plane_state != pipe->plane_state); - goto validate_fail; - } - pipe_idx++; - } - - /*initialize pipe_just_split_from to invalid idx*/ - for (i = 0; i < MAX_PIPES; i++) - pipe_split_from[i] = -1; - - for (i = 0, pipe_idx = -1; i < dc->res_pool->pipe_count; i++) { - struct pipe_ctx *pipe = &context->res_ctx.pipe_ctx[i]; - struct pipe_ctx *hsplit_pipe = pipe->bottom_pipe; - - if (!pipe->stream || pipe_split_from[i] >= 0) - continue; - - pipe_idx++; - - if (!pipe->top_pipe && !pipe->plane_state && context->bw_ctx.dml.vba.ODMCombineEnabled[pipe_idx]) { - hsplit_pipe = dcn20_find_secondary_pipe(dc, &context->res_ctx, dc->res_pool, pipe); - ASSERT(hsplit_pipe); - if (!dcn20_split_stream_for_odm( - dc, &context->res_ctx, - pipe, hsplit_pipe)) - goto validate_fail; - pipe_split_from[hsplit_pipe->pipe_idx] = pipe_idx; - dcn20_build_mapped_resource(dc, context, pipe->stream); - } - - if (!pipe->plane_state) - continue; - /* Skip 2nd half of already split pipe */ - if (pipe->top_pipe && pipe->plane_state == pipe->top_pipe->plane_state) - continue; - - if (split[i] == 2) { - if (!hsplit_pipe || hsplit_pipe->plane_state != pipe->plane_state) { - /* pipe not split previously needs split */ - hsplit_pipe = dcn20_find_secondary_pipe(dc, &context->res_ctx, dc->res_pool, pipe); - ASSERT(hsplit_pipe); - if (!hsplit_pipe) { - DC_FP_START(); - dcn20_fpu_adjust_dppclk(&context->bw_ctx.dml.vba, vlevel, context->bw_ctx.dml.vba.maxMpcComb, pipe_idx, true); - DC_FP_END(); - continue; - } - if (context->bw_ctx.dml.vba.ODMCombineEnabled[pipe_idx]) { - if (!dcn20_split_stream_for_odm( - dc, &context->res_ctx, - pipe, hsplit_pipe)) - goto validate_fail; - dcn20_build_mapped_resource(dc, context, pipe->stream); - } else { - dcn20_split_stream_for_mpc( - &context->res_ctx, dc->res_pool, - pipe, hsplit_pipe); - resource_build_scaling_params(pipe); - resource_build_scaling_params(hsplit_pipe); - } - pipe_split_from[hsplit_pipe->pipe_idx] = pipe_idx; - } - } else if (hsplit_pipe && hsplit_pipe->plane_state == pipe->plane_state) { - /* merge should already have been done */ - ASSERT(0); - } - } - /* Actual dsc count per stream dsc validation*/ - if (!dcn20_validate_dsc(dc, context)) { - context->bw_ctx.dml.vba.ValidationStatus[context->bw_ctx.dml.vba.soc.num_states] = - DML_FAIL_DSC_VALIDATION_FAILURE; - goto validate_fail; - } - - *vlevel_out = vlevel; - - out = true; - goto validate_out; - -validate_fail: - out = false; - -validate_out: - return out; -} - -/* - * Some of the functions further below use the FPU, so we need to wrap this - * with DC_FP_START()/DC_FP_END(). Use the same approach as for - * dcn20_validate_bandwidth in dcn20_resource.c. - */ -static bool dcn21_validate_bandwidth(struct dc *dc, struct dc_state *context, - bool fast_validate) -{ - bool voltage_supported; - display_e2e_pipe_params_st *pipes; - - pipes = kcalloc(dc->res_pool->pipe_count, sizeof(display_e2e_pipe_params_st), GFP_KERNEL); - if (!pipes) - return false; - - DC_FP_START(); - voltage_supported = dcn21_validate_bandwidth_fp(dc, context, fast_validate, pipes); - DC_FP_END(); - - kfree(pipes); - return voltage_supported; -} - -static void dcn21_destroy_resource_pool(struct resource_pool **pool) -{ - struct dcn21_resource_pool *dcn21_pool = TO_DCN21_RES_POOL(*pool); - - dcn21_resource_destruct(dcn21_pool); - kfree(dcn21_pool); - *pool = NULL; -} - -static struct clock_source *dcn21_clock_source_create( - struct dc_context *ctx, - struct dc_bios *bios, - enum clock_source_id id, - const struct dce110_clk_src_regs *regs, - bool dp_clk_src) -{ - struct dce110_clk_src *clk_src = - kzalloc(sizeof(struct dce110_clk_src), GFP_KERNEL); - - if (!clk_src) - return NULL; - - if (dcn20_clk_src_construct(clk_src, ctx, bios, id, - regs, &cs_shift, &cs_mask)) { - clk_src->base.dp_clk_src = dp_clk_src; - return &clk_src->base; - } - - kfree(clk_src); - BREAK_TO_DEBUGGER(); - return NULL; -} - -static struct hubp *dcn21_hubp_create( - struct dc_context *ctx, - uint32_t inst) -{ - struct dcn21_hubp *hubp21 = - kzalloc(sizeof(struct dcn21_hubp), GFP_KERNEL); - - if (!hubp21) - return NULL; - - if (hubp21_construct(hubp21, ctx, inst, - &hubp_regs[inst], &hubp_shift, &hubp_mask)) - return &hubp21->base; - - BREAK_TO_DEBUGGER(); - kfree(hubp21); - return NULL; -} - -static struct hubbub *dcn21_hubbub_create(struct dc_context *ctx) -{ - int i; - - struct dcn20_hubbub *hubbub = kzalloc(sizeof(struct dcn20_hubbub), - GFP_KERNEL); - - if (!hubbub) - return NULL; - - hubbub21_construct(hubbub, ctx, - &hubbub_reg, - &hubbub_shift, - &hubbub_mask); - - for (i = 0; i < res_cap_rn.num_vmid; i++) { - struct dcn20_vmid *vmid = &hubbub->vmid[i]; - - vmid->ctx = ctx; - - vmid->regs = &vmid_regs[i]; - vmid->shifts = &vmid_shifts; - vmid->masks = &vmid_masks; - } - hubbub->num_vmid = res_cap_rn.num_vmid; - - return &hubbub->base; -} - -static struct output_pixel_processor *dcn21_opp_create(struct dc_context *ctx, - uint32_t inst) -{ - struct dcn20_opp *opp = - kzalloc(sizeof(struct dcn20_opp), GFP_KERNEL); - - if (!opp) { - BREAK_TO_DEBUGGER(); - return NULL; - } - - dcn20_opp_construct(opp, ctx, inst, - &opp_regs[inst], &opp_shift, &opp_mask); - return &opp->base; -} - -static struct timing_generator *dcn21_timing_generator_create(struct dc_context *ctx, - uint32_t instance) -{ - struct optc *tgn10 = - kzalloc(sizeof(struct optc), GFP_KERNEL); - - if (!tgn10) - return NULL; - - tgn10->base.inst = instance; - tgn10->base.ctx = ctx; - - tgn10->tg_regs = &tg_regs[instance]; - tgn10->tg_shift = &tg_shift; - tgn10->tg_mask = &tg_mask; - - dcn20_timing_generator_init(tgn10); - - return &tgn10->base; -} - -static struct mpc *dcn21_mpc_create(struct dc_context *ctx) -{ - struct dcn20_mpc *mpc20 = kzalloc(sizeof(struct dcn20_mpc), - GFP_KERNEL); - - if (!mpc20) - return NULL; - - dcn20_mpc_construct(mpc20, ctx, - &mpc_regs, - &mpc_shift, - &mpc_mask, - 6); - - return &mpc20->base; -} - -static void read_dce_straps( - struct dc_context *ctx, - struct resource_straps *straps) -{ - generic_reg_get(ctx, mmDC_PINSTRAPS + BASE(mmDC_PINSTRAPS_BASE_IDX), - FN(DC_PINSTRAPS, DC_PINSTRAPS_AUDIO), &straps->dc_pinstraps_audio); - -} - - -static struct display_stream_compressor *dcn21_dsc_create(struct dc_context *ctx, - uint32_t inst) -{ - struct dcn20_dsc *dsc = - kzalloc(sizeof(struct dcn20_dsc), GFP_KERNEL); - - if (!dsc) { - BREAK_TO_DEBUGGER(); - return NULL; - } - - dsc2_construct(dsc, ctx, inst, &dsc_regs[inst], &dsc_shift, &dsc_mask); - return &dsc->base; -} - -static struct pp_smu_funcs *dcn21_pp_smu_create(struct dc_context *ctx) -{ - struct pp_smu_funcs *pp_smu = kzalloc(sizeof(*pp_smu), GFP_KERNEL); - - if (!pp_smu) - return pp_smu; - - dm_pp_get_funcs(ctx, pp_smu); - - if (pp_smu->ctx.ver != PP_SMU_VER_RN) - pp_smu = memset(pp_smu, 0, sizeof(struct pp_smu_funcs)); - - - return pp_smu; -} - -static void dcn21_pp_smu_destroy(struct pp_smu_funcs **pp_smu) -{ - if (pp_smu && *pp_smu) { - kfree(*pp_smu); - *pp_smu = NULL; - } -} - -static struct audio *dcn21_create_audio( - struct dc_context *ctx, unsigned int inst) -{ - return dce_audio_create(ctx, inst, - &audio_regs[inst], &audio_shift, &audio_mask); -} - -static struct dc_cap_funcs cap_funcs = { - .get_dcc_compression_cap = dcn20_get_dcc_compression_cap -}; - -static struct stream_encoder *dcn21_stream_encoder_create(enum engine_id eng_id, - struct dc_context *ctx) -{ - struct dcn10_stream_encoder *enc1 = - kzalloc(sizeof(struct dcn10_stream_encoder), GFP_KERNEL); - - if (!enc1) - return NULL; - - dcn20_stream_encoder_construct(enc1, ctx, ctx->dc_bios, eng_id, - &stream_enc_regs[eng_id], - &se_shift, &se_mask); - - return &enc1->base; -} - -static const struct dce_hwseq_registers hwseq_reg = { - HWSEQ_DCN21_REG_LIST() -}; - -static const struct dce_hwseq_shift hwseq_shift = { - HWSEQ_DCN21_MASK_SH_LIST(__SHIFT) -}; - -static const struct dce_hwseq_mask hwseq_mask = { - HWSEQ_DCN21_MASK_SH_LIST(_MASK) -}; - -static struct dce_hwseq *dcn21_hwseq_create( - struct dc_context *ctx) -{ - struct dce_hwseq *hws = kzalloc(sizeof(struct dce_hwseq), GFP_KERNEL); - - if (hws) { - hws->ctx = ctx; - hws->regs = &hwseq_reg; - hws->shifts = &hwseq_shift; - hws->masks = &hwseq_mask; - hws->wa.DEGVIDCN21 = true; - hws->wa.disallow_self_refresh_during_multi_plane_transition = true; - } - return hws; -} - -static const struct resource_create_funcs res_create_funcs = { - .read_dce_straps = read_dce_straps, - .create_audio = dcn21_create_audio, - .create_stream_encoder = dcn21_stream_encoder_create, - .create_hwseq = dcn21_hwseq_create, -}; - -static const struct encoder_feature_support link_enc_feature = { - .max_hdmi_deep_color = COLOR_DEPTH_121212, - .max_hdmi_pixel_clock = 600000, - .hdmi_ycbcr420_supported = true, - .dp_ycbcr420_supported = true, - .fec_supported = true, - .flags.bits.IS_HBR2_CAPABLE = true, - .flags.bits.IS_HBR3_CAPABLE = true, - .flags.bits.IS_TPS3_CAPABLE = true, - .flags.bits.IS_TPS4_CAPABLE = true -}; - - -#define link_regs(id, phyid)\ -[id] = {\ - LE_DCN2_REG_LIST(id), \ - UNIPHY_DCN2_REG_LIST(phyid), \ - DPCS_DCN21_REG_LIST(id), \ - SRI(DP_DPHY_INTERNAL_CTRL, DP, id) \ -} - -static const struct dcn10_link_enc_registers link_enc_regs[] = { - link_regs(0, A), - link_regs(1, B), - link_regs(2, C), - link_regs(3, D), - link_regs(4, E), -}; - -static const struct dce_panel_cntl_registers panel_cntl_regs[] = { - { DCN_PANEL_CNTL_REG_LIST() } -}; - -static const struct dce_panel_cntl_shift panel_cntl_shift = { - DCE_PANEL_CNTL_MASK_SH_LIST(__SHIFT) -}; - -static const struct dce_panel_cntl_mask panel_cntl_mask = { - DCE_PANEL_CNTL_MASK_SH_LIST(_MASK) -}; - -#define aux_regs(id)\ -[id] = {\ - DCN2_AUX_REG_LIST(id)\ -} - -static const struct dcn10_link_enc_aux_registers link_enc_aux_regs[] = { - aux_regs(0), - aux_regs(1), - aux_regs(2), - aux_regs(3), - aux_regs(4) -}; - -#define hpd_regs(id)\ -[id] = {\ - HPD_REG_LIST(id)\ -} - -static const struct dcn10_link_enc_hpd_registers link_enc_hpd_regs[] = { - hpd_regs(0), - hpd_regs(1), - hpd_regs(2), - hpd_regs(3), - hpd_regs(4) -}; - -static const struct dcn10_link_enc_shift le_shift = { - LINK_ENCODER_MASK_SH_LIST_DCN20(__SHIFT),\ - DPCS_DCN21_MASK_SH_LIST(__SHIFT) -}; - -static const struct dcn10_link_enc_mask le_mask = { - LINK_ENCODER_MASK_SH_LIST_DCN20(_MASK),\ - DPCS_DCN21_MASK_SH_LIST(_MASK) -}; - -static int map_transmitter_id_to_phy_instance( - enum transmitter transmitter) -{ - switch (transmitter) { - case TRANSMITTER_UNIPHY_A: - return 0; - break; - case TRANSMITTER_UNIPHY_B: - return 1; - break; - case TRANSMITTER_UNIPHY_C: - return 2; - break; - case TRANSMITTER_UNIPHY_D: - return 3; - break; - case TRANSMITTER_UNIPHY_E: - return 4; - break; - default: - ASSERT(0); - return 0; - } -} - -static struct link_encoder *dcn21_link_encoder_create( - struct dc_context *ctx, - const struct encoder_init_data *enc_init_data) -{ - struct dcn21_link_encoder *enc21 = - kzalloc(sizeof(struct dcn21_link_encoder), GFP_KERNEL); - int link_regs_id; - - if (!enc21) - return NULL; - - link_regs_id = - map_transmitter_id_to_phy_instance(enc_init_data->transmitter); - - dcn21_link_encoder_construct(enc21, - enc_init_data, - &link_enc_feature, - &link_enc_regs[link_regs_id], - &link_enc_aux_regs[enc_init_data->channel - 1], - &link_enc_hpd_regs[enc_init_data->hpd_source], - &le_shift, - &le_mask); - - return &enc21->enc10.base; -} - -static struct panel_cntl *dcn21_panel_cntl_create(const struct panel_cntl_init_data *init_data) -{ - struct dce_panel_cntl *panel_cntl = - kzalloc(sizeof(struct dce_panel_cntl), GFP_KERNEL); - - if (!panel_cntl) - return NULL; - - dce_panel_cntl_construct(panel_cntl, - init_data, - &panel_cntl_regs[init_data->inst], - &panel_cntl_shift, - &panel_cntl_mask); - - return &panel_cntl->base; -} - -static void dcn21_get_panel_config_defaults(struct dc_panel_config *panel_config) -{ - *panel_config = panel_config_defaults; -} - -#define CTX ctx - -#define REG(reg_name) \ - (DCN_BASE.instance[0].segment[mm ## reg_name ## _BASE_IDX] + mm ## reg_name) - -static uint32_t read_pipe_fuses(struct dc_context *ctx) -{ - uint32_t value = REG_READ(CC_DC_PIPE_DIS); - /* RV1 support max 4 pipes */ - value = value & 0xf; - return value; -} - -static enum dc_status dcn21_patch_unknown_plane_state(struct dc_plane_state *plane_state) -{ - if (plane_state->ctx->dc->debug.disable_dcc == DCC_ENABLE) { - plane_state->dcc.enable = 1; - /* align to our worst case block width */ - plane_state->dcc.meta_pitch = ((plane_state->src_rect.width + 1023) / 1024) * 1024; - } - - return dcn20_patch_unknown_plane_state(plane_state); -} - -static const struct resource_funcs dcn21_res_pool_funcs = { - .destroy = dcn21_destroy_resource_pool, - .link_enc_create = dcn21_link_encoder_create, - .panel_cntl_create = dcn21_panel_cntl_create, - .validate_bandwidth = dcn21_validate_bandwidth, - .populate_dml_pipes = dcn21_populate_dml_pipes_from_context, - .add_stream_to_ctx = dcn20_add_stream_to_ctx, - .add_dsc_to_stream_resource = dcn20_add_dsc_to_stream_resource, - .remove_stream_from_ctx = dcn20_remove_stream_from_ctx, - .acquire_free_pipe_as_secondary_dpp_pipe = dcn20_acquire_free_pipe_for_layer, - .release_pipe = dcn20_release_pipe, - .populate_dml_writeback_from_context = dcn20_populate_dml_writeback_from_context, - .patch_unknown_plane_state = dcn21_patch_unknown_plane_state, - .set_mcif_arb_params = dcn20_set_mcif_arb_params, - .find_first_free_match_stream_enc_for_link = dcn10_find_first_free_match_stream_enc_for_link, - .update_bw_bounding_box = dcn21_update_bw_bounding_box, - .get_panel_config_defaults = dcn21_get_panel_config_defaults, -}; - -static bool dcn21_resource_construct( - uint8_t num_virtual_links, - struct dc *dc, - struct dcn21_resource_pool *pool) -{ - int i, j; - struct dc_context *ctx = dc->ctx; - struct irq_service_init_data init_data; - uint32_t pipe_fuses = read_pipe_fuses(ctx); - uint32_t num_pipes; - - ctx->dc_bios->regs = &bios_regs; - - pool->base.res_cap = &res_cap_rn; -#ifdef DIAGS_BUILD - if (IS_FPGA_MAXIMUS_DC(dc->ctx->dce_environment)) - //pool->base.res_cap = &res_cap_nv10_FPGA_2pipe_dsc; - pool->base.res_cap = &res_cap_rn_FPGA_4pipe; -#endif - - pool->base.funcs = &dcn21_res_pool_funcs; - - /************************************************* - * Resource + asic cap harcoding * - *************************************************/ - pool->base.underlay_pipe_index = NO_UNDERLAY_PIPE; - - /* max pipe num for ASIC before check pipe fuses */ - pool->base.pipe_count = pool->base.res_cap->num_timing_generator; - - dc->caps.max_downscale_ratio = 200; - dc->caps.i2c_speed_in_khz = 100; - dc->caps.i2c_speed_in_khz_hdcp = 5; /*1.4 w/a applied by default*/ - dc->caps.max_cursor_size = 256; - dc->caps.min_horizontal_blanking_period = 80; - dc->caps.dmdata_alloc_size = 2048; - - dc->caps.max_slave_planes = 1; - dc->caps.max_slave_yuv_planes = 1; - dc->caps.max_slave_rgb_planes = 1; - dc->caps.post_blend_color_processing = true; - dc->caps.force_dp_tps4_for_cp2520 = true; - dc->caps.extended_aux_timeout_support = true; - dc->caps.dmcub_support = true; - dc->caps.is_apu = true; - - /* Color pipeline capabilities */ - dc->caps.color.dpp.dcn_arch = 1; - dc->caps.color.dpp.input_lut_shared = 0; - dc->caps.color.dpp.icsc = 1; - dc->caps.color.dpp.dgam_ram = 1; - dc->caps.color.dpp.dgam_rom_caps.srgb = 1; - dc->caps.color.dpp.dgam_rom_caps.bt2020 = 1; - dc->caps.color.dpp.dgam_rom_caps.gamma2_2 = 0; - dc->caps.color.dpp.dgam_rom_caps.pq = 0; - dc->caps.color.dpp.dgam_rom_caps.hlg = 0; - dc->caps.color.dpp.post_csc = 0; - dc->caps.color.dpp.gamma_corr = 0; - dc->caps.color.dpp.dgam_rom_for_yuv = 1; - - dc->caps.color.dpp.hw_3d_lut = 1; - dc->caps.color.dpp.ogam_ram = 1; - // no OGAM ROM on DCN2 - dc->caps.color.dpp.ogam_rom_caps.srgb = 0; - dc->caps.color.dpp.ogam_rom_caps.bt2020 = 0; - dc->caps.color.dpp.ogam_rom_caps.gamma2_2 = 0; - dc->caps.color.dpp.ogam_rom_caps.pq = 0; - dc->caps.color.dpp.ogam_rom_caps.hlg = 0; - dc->caps.color.dpp.ocsc = 0; - - dc->caps.color.mpc.gamut_remap = 0; - dc->caps.color.mpc.num_3dluts = 0; - dc->caps.color.mpc.shared_3d_lut = 0; - dc->caps.color.mpc.ogam_ram = 1; - dc->caps.color.mpc.ogam_rom_caps.srgb = 0; - dc->caps.color.mpc.ogam_rom_caps.bt2020 = 0; - dc->caps.color.mpc.ogam_rom_caps.gamma2_2 = 0; - dc->caps.color.mpc.ogam_rom_caps.pq = 0; - dc->caps.color.mpc.ogam_rom_caps.hlg = 0; - dc->caps.color.mpc.ocsc = 1; - - dc->caps.dp_hdmi21_pcon_support = true; - - if (dc->ctx->dce_environment == DCE_ENV_PRODUCTION_DRV) - dc->debug = debug_defaults_drv; - - // Init the vm_helper - if (dc->vm_helper) - vm_helper_init(dc->vm_helper, 16); - - /************************************************* - * Create resources * - *************************************************/ - - pool->base.clock_sources[DCN20_CLK_SRC_PLL0] = - dcn21_clock_source_create(ctx, ctx->dc_bios, - CLOCK_SOURCE_COMBO_PHY_PLL0, - &clk_src_regs[0], false); - pool->base.clock_sources[DCN20_CLK_SRC_PLL1] = - dcn21_clock_source_create(ctx, ctx->dc_bios, - CLOCK_SOURCE_COMBO_PHY_PLL1, - &clk_src_regs[1], false); - pool->base.clock_sources[DCN20_CLK_SRC_PLL2] = - 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; - - /* todo: not reuse phy_pll registers */ - pool->base.dp_clock_source = - dcn21_clock_source_create(ctx, ctx->dc_bios, - CLOCK_SOURCE_ID_DP_DTO, - &clk_src_regs[0], true); - - for (i = 0; i < pool->base.clk_src_count; i++) { - if (pool->base.clock_sources[i] == NULL) { - dm_error("DC: failed to create clock sources!\n"); - BREAK_TO_DEBUGGER(); - goto create_fail; - } - } - - pool->base.dccg = dccg21_create(ctx, &dccg_regs, &dccg_shift, &dccg_mask); - if (pool->base.dccg == NULL) { - dm_error("DC: failed to create dccg!\n"); - BREAK_TO_DEBUGGER(); - goto create_fail; - } - - if (!dc->config.disable_dmcu) { - pool->base.dmcu = dcn21_dmcu_create(ctx, - &dmcu_regs, - &dmcu_shift, - &dmcu_mask); - if (pool->base.dmcu == NULL) { - dm_error("DC: failed to create dmcu!\n"); - BREAK_TO_DEBUGGER(); - goto create_fail; - } - - dc->debug.dmub_command_table = false; - } - - if (dc->config.disable_dmcu) { - pool->base.psr = dmub_psr_create(ctx); - - if (pool->base.psr == NULL) { - dm_error("DC: failed to create psr obj!\n"); - BREAK_TO_DEBUGGER(); - goto create_fail; - } - } - - if (dc->config.disable_dmcu) - pool->base.abm = dmub_abm_create(ctx, - &abm_regs, - &abm_shift, - &abm_mask); - else - pool->base.abm = dce_abm_create(ctx, - &abm_regs, - &abm_shift, - &abm_mask); - - pool->base.pp_smu = dcn21_pp_smu_create(ctx); - - num_pipes = dcn2_1_ip.max_num_dpp; - - for (i = 0; i < dcn2_1_ip.max_num_dpp; i++) - if (pipe_fuses & 1 << i) - num_pipes--; - dcn2_1_ip.max_num_dpp = num_pipes; - dcn2_1_ip.max_num_otg = num_pipes; - - dml_init_instance(&dc->dml, &dcn2_1_soc, &dcn2_1_ip, DML_PROJECT_DCN21); - - init_data.ctx = dc->ctx; - pool->base.irqs = dal_irq_service_dcn21_create(&init_data); - if (!pool->base.irqs) - goto create_fail; - - j = 0; - /* mem input -> ipp -> dpp -> opp -> TG */ - for (i = 0; i < pool->base.pipe_count; i++) { - /* if pipe is disabled, skip instance of HW pipe, - * i.e, skip ASIC register instance - */ - if ((pipe_fuses & (1 << i)) != 0) - continue; - - pool->base.hubps[j] = dcn21_hubp_create(ctx, i); - if (pool->base.hubps[j] == NULL) { - BREAK_TO_DEBUGGER(); - dm_error( - "DC: failed to create memory input!\n"); - goto create_fail; - } - - pool->base.ipps[j] = dcn21_ipp_create(ctx, i); - if (pool->base.ipps[j] == NULL) { - BREAK_TO_DEBUGGER(); - dm_error( - "DC: failed to create input pixel processor!\n"); - goto create_fail; - } - - pool->base.dpps[j] = dcn21_dpp_create(ctx, i); - if (pool->base.dpps[j] == NULL) { - BREAK_TO_DEBUGGER(); - dm_error( - "DC: failed to create dpps!\n"); - goto create_fail; - } - - pool->base.opps[j] = dcn21_opp_create(ctx, i); - if (pool->base.opps[j] == NULL) { - BREAK_TO_DEBUGGER(); - dm_error( - "DC: failed to create output pixel processor!\n"); - goto create_fail; - } - - pool->base.timing_generators[j] = dcn21_timing_generator_create( - ctx, i); - if (pool->base.timing_generators[j] == NULL) { - BREAK_TO_DEBUGGER(); - dm_error("DC: failed to create tg!\n"); - goto create_fail; - } - j++; - } - - for (i = 0; i < pool->base.res_cap->num_ddc; i++) { - pool->base.engines[i] = dcn21_aux_engine_create(ctx, i); - if (pool->base.engines[i] == NULL) { - BREAK_TO_DEBUGGER(); - dm_error( - "DC:failed to create aux engine!!\n"); - goto create_fail; - } - pool->base.hw_i2cs[i] = dcn21_i2c_hw_create(ctx, i); - if (pool->base.hw_i2cs[i] == NULL) { - BREAK_TO_DEBUGGER(); - dm_error( - "DC:failed to create hw i2c!!\n"); - goto create_fail; - } - pool->base.sw_i2cs[i] = NULL; - } - - pool->base.timing_generator_count = j; - pool->base.pipe_count = j; - pool->base.mpcc_count = j; - - pool->base.mpc = dcn21_mpc_create(ctx); - if (pool->base.mpc == NULL) { - BREAK_TO_DEBUGGER(); - dm_error("DC: failed to create mpc!\n"); - goto create_fail; - } - - pool->base.hubbub = dcn21_hubbub_create(ctx); - if (pool->base.hubbub == NULL) { - BREAK_TO_DEBUGGER(); - dm_error("DC: failed to create hubbub!\n"); - goto create_fail; - } - - for (i = 0; i < pool->base.res_cap->num_dsc; i++) { - pool->base.dscs[i] = dcn21_dsc_create(ctx, i); - if (pool->base.dscs[i] == NULL) { - BREAK_TO_DEBUGGER(); - dm_error("DC: failed to create display stream compressor %d!\n", i); - goto create_fail; - } - } - - if (!dcn20_dwbc_create(ctx, &pool->base)) { - BREAK_TO_DEBUGGER(); - dm_error("DC: failed to create dwbc!\n"); - goto create_fail; - } - if (!dcn20_mmhubbub_create(ctx, &pool->base)) { - BREAK_TO_DEBUGGER(); - dm_error("DC: failed to create mcif_wb!\n"); - goto create_fail; - } - - if (!resource_construct(num_virtual_links, dc, &pool->base, - &res_create_funcs)) - goto create_fail; - - dcn21_hw_sequencer_construct(dc); - - dc->caps.max_planes = pool->base.pipe_count; - - for (i = 0; i < dc->caps.max_planes; ++i) - dc->caps.planes[i] = plane_cap; - - dc->cap_funcs = cap_funcs; - - return true; - -create_fail: - - dcn21_resource_destruct(pool); - - return false; -} - -struct resource_pool *dcn21_create_resource_pool( - const struct dc_init_data *init_data, - struct dc *dc) -{ - struct dcn21_resource_pool *pool = - kzalloc(sizeof(struct dcn21_resource_pool), GFP_KERNEL); - - if (!pool) - return NULL; - - if (dcn21_resource_construct(init_data->num_virtual_links, dc, pool)) - return &pool->base; - - BREAK_TO_DEBUGGER(); - kfree(pool); - return NULL; -} diff --git a/drivers/gpu/drm/amd/display/dc/dcn21/dcn21_resource.h b/drivers/gpu/drm/amd/display/dc/dcn21/dcn21_resource.h deleted file mode 100644 index f7ecc002c2f7..000000000000 --- a/drivers/gpu/drm/amd/display/dc/dcn21/dcn21_resource.h +++ /dev/null @@ -1,56 +0,0 @@ -/* - * Copyright 2018 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 _DCN21_RESOURCE_H_ -#define _DCN21_RESOURCE_H_ - -#include "core_types.h" - -#define TO_DCN21_RES_POOL(pool)\ - container_of(pool, struct dcn21_resource_pool, base) - -struct dc; -struct resource_pool; -struct _vcs_dpi_display_pipe_params_st; - -extern struct _vcs_dpi_ip_params_st dcn2_1_ip; -extern struct _vcs_dpi_soc_bounding_box_st dcn2_1_soc; - -struct dcn21_resource_pool { - struct resource_pool base; -}; -struct resource_pool *dcn21_create_resource_pool( - const struct dc_init_data *init_data, - struct dc *dc); -bool dcn21_fast_validate_bw( - struct dc *dc, - struct dc_state *context, - display_e2e_pipe_params_st *pipes, - int *pipe_cnt_out, - int *pipe_split_from, - int *vlevel_out, - bool fast_validate); - -#endif /* _DCN21_RESOURCE_H_ */ diff --git a/drivers/gpu/drm/amd/display/dc/dcn30/Makefile b/drivers/gpu/drm/amd/display/dc/dcn30/Makefile index af4d2065d2c1..9dcf06c0954d 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn30/Makefile +++ b/drivers/gpu/drm/amd/display/dc/dcn30/Makefile @@ -38,7 +38,6 @@ DCN30 := \ dcn30_dwb_cm.o \ dcn30_cm_common.o \ dcn30_mmhubbub.o \ - dcn30_resource.o \ dcn30_dio_link_encoder.o diff --git a/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_resource.c b/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_resource.c deleted file mode 100644 index 7b259cb5f418..000000000000 --- a/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_resource.c +++ /dev/null @@ -1,2611 +0,0 @@ -/* - * Copyright 2020 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 "dm_services.h" -#include "dc.h" - -#include "dcn30_init.h" - -#include "resource.h" -#include "include/irq_service_interface.h" -#include "dcn20/dcn20_resource.h" - -#include "dcn30_resource.h" - -#include "dcn10/dcn10_ipp.h" -#include "dcn30/dcn30_hubbub.h" -#include "dcn30/dcn30_mpc.h" -#include "dcn30/dcn30_hubp.h" -#include "irq/dcn30/irq_service_dcn30.h" -#include "dcn30/dcn30_dpp.h" -#include "dcn30/dcn30_optc.h" -#include "dcn20/dcn20_hwseq.h" -#include "dcn30/dcn30_hwseq.h" -#include "dce110/dce110_hwseq.h" -#include "dcn30/dcn30_opp.h" -#include "dcn20/dcn20_dsc.h" -#include "dcn30/dcn30_vpg.h" -#include "dcn30/dcn30_afmt.h" -#include "dcn30/dcn30_dio_stream_encoder.h" -#include "dcn30/dcn30_dio_link_encoder.h" -#include "dce/dce_clock_source.h" -#include "dce/dce_audio.h" -#include "dce/dce_hwseq.h" -#include "clk_mgr.h" -#include "virtual/virtual_stream_encoder.h" -#include "dce110/dce110_resource.h" -#include "dml/display_mode_vba.h" -#include "dcn30/dcn30_dccg.h" -#include "dcn10/dcn10_resource.h" -#include "link.h" -#include "dce/dce_panel_cntl.h" - -#include "dcn30/dcn30_dwb.h" -#include "dcn30/dcn30_mmhubbub.h" - -#include "sienna_cichlid_ip_offset.h" -#include "dcn/dcn_3_0_0_offset.h" -#include "dcn/dcn_3_0_0_sh_mask.h" - -#include "nbio/nbio_7_4_offset.h" - -#include "dpcs/dpcs_3_0_0_offset.h" -#include "dpcs/dpcs_3_0_0_sh_mask.h" - -#include "mmhub/mmhub_2_0_0_offset.h" -#include "mmhub/mmhub_2_0_0_sh_mask.h" - -#include "reg_helper.h" -#include "dce/dmub_abm.h" -#include "dce/dmub_psr.h" -#include "dce/dce_aux.h" -#include "dce/dce_i2c.h" - -#include "dml/dcn30/dcn30_fpu.h" -#include "dml/dcn30/display_mode_vba_30.h" -#include "vm_helper.h" -#include "dcn20/dcn20_vmid.h" -#include "amdgpu_socbb.h" -#include "dc_dmub_srv.h" - -#define DC_LOGGER \ - dc->ctx->logger -#define DC_LOGGER_INIT(logger) - -enum dcn30_clk_src_array_id { - DCN30_CLK_SRC_PLL0, - DCN30_CLK_SRC_PLL1, - DCN30_CLK_SRC_PLL2, - DCN30_CLK_SRC_PLL3, - DCN30_CLK_SRC_PLL4, - DCN30_CLK_SRC_PLL5, - DCN30_CLK_SRC_TOTAL -}; - -/* begin ********************* - * macros to expend register list macro defined in HW object header file - */ - -/* DCN */ -#define BASE_INNER(seg) DCN_BASE__INST0_SEG ## seg - -#define BASE(seg) BASE_INNER(seg) - -#define SR(reg_name)\ - .reg_name = BASE(mm ## reg_name ## _BASE_IDX) + \ - mm ## reg_name - -#define SRI(reg_name, block, id)\ - .reg_name = BASE(mm ## block ## id ## _ ## reg_name ## _BASE_IDX) + \ - mm ## block ## id ## _ ## reg_name - -#define SRI2(reg_name, block, id)\ - .reg_name = BASE(mm ## reg_name ## _BASE_IDX) + \ - mm ## reg_name - -#define SRIR(var_name, reg_name, block, id)\ - .var_name = BASE(mm ## block ## id ## _ ## reg_name ## _BASE_IDX) + \ - mm ## block ## id ## _ ## reg_name - -#define SRII(reg_name, block, id)\ - .reg_name[id] = BASE(mm ## block ## id ## _ ## reg_name ## _BASE_IDX) + \ - mm ## block ## id ## _ ## reg_name - -#define SRII_MPC_RMU(reg_name, block, id)\ - .RMU##_##reg_name[id] = BASE(mm ## block ## id ## _ ## reg_name ## _BASE_IDX) + \ - mm ## block ## id ## _ ## reg_name - -#define SRII_DWB(reg_name, temp_name, block, id)\ - .reg_name[id] = BASE(mm ## block ## id ## _ ## temp_name ## _BASE_IDX) + \ - mm ## block ## id ## _ ## temp_name - -#define SF_DWB2(reg_name, block, id, field_name, post_fix) \ - .field_name = reg_name ## __ ## field_name ## post_fix - -#define DCCG_SRII(reg_name, block, id)\ - .block ## _ ## reg_name[id] = BASE(mm ## block ## id ## _ ## reg_name ## _BASE_IDX) + \ - mm ## block ## id ## _ ## reg_name - -#define VUPDATE_SRII(reg_name, block, id)\ - .reg_name[id] = BASE(mm ## reg_name ## _ ## block ## id ## _BASE_IDX) + \ - mm ## reg_name ## _ ## block ## id - -/* NBIO */ -#define NBIO_BASE_INNER(seg) \ - NBIO_BASE__INST0_SEG ## seg - -#define NBIO_BASE(seg) \ - NBIO_BASE_INNER(seg) - -#define NBIO_SR(reg_name)\ - .reg_name = NBIO_BASE(mm ## reg_name ## _BASE_IDX) + \ - mm ## reg_name - -/* MMHUB */ -#define MMHUB_BASE_INNER(seg) \ - MMHUB_BASE__INST0_SEG ## seg - -#define MMHUB_BASE(seg) \ - MMHUB_BASE_INNER(seg) - -#define MMHUB_SR(reg_name)\ - .reg_name = MMHUB_BASE(mmMM ## reg_name ## _BASE_IDX) + \ - mmMM ## reg_name - -/* CLOCK */ -#define CLK_BASE_INNER(seg) \ - CLK_BASE__INST0_SEG ## seg - -#define CLK_BASE(seg) \ - CLK_BASE_INNER(seg) - -#define CLK_SRI(reg_name, block, inst)\ - .reg_name = CLK_BASE(mm ## block ## _ ## inst ## _ ## reg_name ## _BASE_IDX) + \ - mm ## block ## _ ## inst ## _ ## reg_name - - -static const struct bios_registers bios_regs = { - NBIO_SR(BIOS_SCRATCH_3), - NBIO_SR(BIOS_SCRATCH_6) -}; - -#define clk_src_regs(index, pllid)\ -[index] = {\ - CS_COMMON_REG_LIST_DCN2_0(index, pllid),\ -} - -static const struct dce110_clk_src_regs clk_src_regs[] = { - clk_src_regs(0, A), - clk_src_regs(1, B), - clk_src_regs(2, C), - clk_src_regs(3, D), - clk_src_regs(4, E), - clk_src_regs(5, F) -}; - -static const struct dce110_clk_src_shift cs_shift = { - CS_COMMON_MASK_SH_LIST_DCN2_0(__SHIFT) -}; - -static const struct dce110_clk_src_mask cs_mask = { - CS_COMMON_MASK_SH_LIST_DCN2_0(_MASK) -}; - -#define abm_regs(id)\ -[id] = {\ - ABM_DCN30_REG_LIST(id)\ -} - -static const struct dce_abm_registers abm_regs[] = { - abm_regs(0), - abm_regs(1), - abm_regs(2), - abm_regs(3), - abm_regs(4), - abm_regs(5), -}; - -static const struct dce_abm_shift abm_shift = { - ABM_MASK_SH_LIST_DCN30(__SHIFT) -}; - -static const struct dce_abm_mask abm_mask = { - ABM_MASK_SH_LIST_DCN30(_MASK) -}; - - - -#define audio_regs(id)\ -[id] = {\ - AUD_COMMON_REG_LIST(id)\ -} - -static const struct dce_audio_registers audio_regs[] = { - audio_regs(0), - audio_regs(1), - audio_regs(2), - audio_regs(3), - audio_regs(4), - audio_regs(5), - audio_regs(6) -}; - -#define DCE120_AUD_COMMON_MASK_SH_LIST(mask_sh)\ - SF(AZF0ENDPOINT0_AZALIA_F0_CODEC_ENDPOINT_INDEX, AZALIA_ENDPOINT_REG_INDEX, mask_sh),\ - SF(AZF0ENDPOINT0_AZALIA_F0_CODEC_ENDPOINT_DATA, AZALIA_ENDPOINT_REG_DATA, mask_sh),\ - AUD_COMMON_MASK_SH_LIST_BASE(mask_sh) - -static const struct dce_audio_shift audio_shift = { - DCE120_AUD_COMMON_MASK_SH_LIST(__SHIFT) -}; - -static const struct dce_audio_mask audio_mask = { - DCE120_AUD_COMMON_MASK_SH_LIST(_MASK) -}; - -#define vpg_regs(id)\ -[id] = {\ - VPG_DCN3_REG_LIST(id)\ -} - -static const struct dcn30_vpg_registers vpg_regs[] = { - vpg_regs(0), - vpg_regs(1), - vpg_regs(2), - vpg_regs(3), - vpg_regs(4), - vpg_regs(5), - vpg_regs(6), -}; - -static const struct dcn30_vpg_shift vpg_shift = { - DCN3_VPG_MASK_SH_LIST(__SHIFT) -}; - -static const struct dcn30_vpg_mask vpg_mask = { - DCN3_VPG_MASK_SH_LIST(_MASK) -}; - -#define afmt_regs(id)\ -[id] = {\ - AFMT_DCN3_REG_LIST(id)\ -} - -static const struct dcn30_afmt_registers afmt_regs[] = { - afmt_regs(0), - afmt_regs(1), - afmt_regs(2), - afmt_regs(3), - afmt_regs(4), - afmt_regs(5), - afmt_regs(6), -}; - -static const struct dcn30_afmt_shift afmt_shift = { - DCN3_AFMT_MASK_SH_LIST(__SHIFT) -}; - -static const struct dcn30_afmt_mask afmt_mask = { - DCN3_AFMT_MASK_SH_LIST(_MASK) -}; - -#define stream_enc_regs(id)\ -[id] = {\ - SE_DCN3_REG_LIST(id)\ -} - -static const struct dcn10_stream_enc_registers stream_enc_regs[] = { - stream_enc_regs(0), - stream_enc_regs(1), - stream_enc_regs(2), - stream_enc_regs(3), - stream_enc_regs(4), - stream_enc_regs(5) -}; - -static const struct dcn10_stream_encoder_shift se_shift = { - SE_COMMON_MASK_SH_LIST_DCN30(__SHIFT) -}; - -static const struct dcn10_stream_encoder_mask se_mask = { - SE_COMMON_MASK_SH_LIST_DCN30(_MASK) -}; - - -#define aux_regs(id)\ -[id] = {\ - DCN2_AUX_REG_LIST(id)\ -} - -static const struct dcn10_link_enc_aux_registers link_enc_aux_regs[] = { - aux_regs(0), - aux_regs(1), - aux_regs(2), - aux_regs(3), - aux_regs(4), - aux_regs(5) -}; - -#define hpd_regs(id)\ -[id] = {\ - HPD_REG_LIST(id)\ -} - -static const struct dcn10_link_enc_hpd_registers link_enc_hpd_regs[] = { - hpd_regs(0), - hpd_regs(1), - hpd_regs(2), - hpd_regs(3), - hpd_regs(4), - hpd_regs(5) -}; - -#define link_regs(id, phyid)\ -[id] = {\ - LE_DCN3_REG_LIST(id), \ - UNIPHY_DCN2_REG_LIST(phyid), \ - DPCS_DCN2_REG_LIST(id), \ - SRI(DP_DPHY_INTERNAL_CTRL, DP, id) \ -} - -static const struct dce110_aux_registers_shift aux_shift = { - DCN_AUX_MASK_SH_LIST(__SHIFT) -}; - -static const struct dce110_aux_registers_mask aux_mask = { - DCN_AUX_MASK_SH_LIST(_MASK) -}; - -static const struct dcn10_link_enc_registers link_enc_regs[] = { - link_regs(0, A), - link_regs(1, B), - link_regs(2, C), - link_regs(3, D), - link_regs(4, E), - link_regs(5, F) -}; - -static const struct dcn10_link_enc_shift le_shift = { - LINK_ENCODER_MASK_SH_LIST_DCN30(__SHIFT),\ - DPCS_DCN2_MASK_SH_LIST(__SHIFT) -}; - -static const struct dcn10_link_enc_mask le_mask = { - LINK_ENCODER_MASK_SH_LIST_DCN30(_MASK),\ - DPCS_DCN2_MASK_SH_LIST(_MASK) -}; - - -static const struct dce_panel_cntl_registers panel_cntl_regs[] = { - { DCN_PANEL_CNTL_REG_LIST() } -}; - -static const struct dce_panel_cntl_shift panel_cntl_shift = { - DCE_PANEL_CNTL_MASK_SH_LIST(__SHIFT) -}; - -static const struct dce_panel_cntl_mask panel_cntl_mask = { - DCE_PANEL_CNTL_MASK_SH_LIST(_MASK) -}; - -#define dpp_regs(id)\ -[id] = {\ - DPP_REG_LIST_DCN30(id),\ -} - -static const struct dcn3_dpp_registers dpp_regs[] = { - dpp_regs(0), - dpp_regs(1), - dpp_regs(2), - dpp_regs(3), - dpp_regs(4), - dpp_regs(5), -}; - -static const struct dcn3_dpp_shift tf_shift = { - DPP_REG_LIST_SH_MASK_DCN30(__SHIFT) -}; - -static const struct dcn3_dpp_mask tf_mask = { - DPP_REG_LIST_SH_MASK_DCN30(_MASK) -}; - -#define opp_regs(id)\ -[id] = {\ - OPP_REG_LIST_DCN30(id),\ -} - -static const struct dcn20_opp_registers opp_regs[] = { - opp_regs(0), - opp_regs(1), - opp_regs(2), - opp_regs(3), - opp_regs(4), - opp_regs(5) -}; - -static const struct dcn20_opp_shift opp_shift = { - OPP_MASK_SH_LIST_DCN20(__SHIFT) -}; - -static const struct dcn20_opp_mask opp_mask = { - OPP_MASK_SH_LIST_DCN20(_MASK) -}; - -#define aux_engine_regs(id)\ -[id] = {\ - AUX_COMMON_REG_LIST0(id), \ - .AUXN_IMPCAL = 0, \ - .AUXP_IMPCAL = 0, \ - .AUX_RESET_MASK = DP_AUX0_AUX_CONTROL__AUX_RESET_MASK, \ -} - -static const struct dce110_aux_registers aux_engine_regs[] = { - aux_engine_regs(0), - aux_engine_regs(1), - aux_engine_regs(2), - aux_engine_regs(3), - aux_engine_regs(4), - aux_engine_regs(5) -}; - -#define dwbc_regs_dcn3(id)\ -[id] = {\ - DWBC_COMMON_REG_LIST_DCN30(id),\ -} - -static const struct dcn30_dwbc_registers dwbc30_regs[] = { - dwbc_regs_dcn3(0), -}; - -static const struct dcn30_dwbc_shift dwbc30_shift = { - DWBC_COMMON_MASK_SH_LIST_DCN30(__SHIFT) -}; - -static const struct dcn30_dwbc_mask dwbc30_mask = { - DWBC_COMMON_MASK_SH_LIST_DCN30(_MASK) -}; - -#define mcif_wb_regs_dcn3(id)\ -[id] = {\ - MCIF_WB_COMMON_REG_LIST_DCN30(id),\ -} - -static const struct dcn30_mmhubbub_registers mcif_wb30_regs[] = { - mcif_wb_regs_dcn3(0) -}; - -static const struct dcn30_mmhubbub_shift mcif_wb30_shift = { - MCIF_WB_COMMON_MASK_SH_LIST_DCN30(__SHIFT) -}; - -static const struct dcn30_mmhubbub_mask mcif_wb30_mask = { - MCIF_WB_COMMON_MASK_SH_LIST_DCN30(_MASK) -}; - -#define dsc_regsDCN20(id)\ -[id] = {\ - DSC_REG_LIST_DCN20(id)\ -} - -static const struct dcn20_dsc_registers dsc_regs[] = { - dsc_regsDCN20(0), - dsc_regsDCN20(1), - dsc_regsDCN20(2), - dsc_regsDCN20(3), - dsc_regsDCN20(4), - dsc_regsDCN20(5) -}; - -static const struct dcn20_dsc_shift dsc_shift = { - DSC_REG_LIST_SH_MASK_DCN20(__SHIFT) -}; - -static const struct dcn20_dsc_mask dsc_mask = { - DSC_REG_LIST_SH_MASK_DCN20(_MASK) -}; - -static const struct dcn30_mpc_registers mpc_regs = { - MPC_REG_LIST_DCN3_0(0), - MPC_REG_LIST_DCN3_0(1), - MPC_REG_LIST_DCN3_0(2), - MPC_REG_LIST_DCN3_0(3), - MPC_REG_LIST_DCN3_0(4), - MPC_REG_LIST_DCN3_0(5), - MPC_OUT_MUX_REG_LIST_DCN3_0(0), - MPC_OUT_MUX_REG_LIST_DCN3_0(1), - MPC_OUT_MUX_REG_LIST_DCN3_0(2), - MPC_OUT_MUX_REG_LIST_DCN3_0(3), - MPC_OUT_MUX_REG_LIST_DCN3_0(4), - MPC_OUT_MUX_REG_LIST_DCN3_0(5), - MPC_RMU_GLOBAL_REG_LIST_DCN3AG, - MPC_RMU_REG_LIST_DCN3AG(0), - MPC_RMU_REG_LIST_DCN3AG(1), - MPC_RMU_REG_LIST_DCN3AG(2), - MPC_DWB_MUX_REG_LIST_DCN3_0(0), -}; - -static const struct dcn30_mpc_shift mpc_shift = { - MPC_COMMON_MASK_SH_LIST_DCN30(__SHIFT) -}; - -static const struct dcn30_mpc_mask mpc_mask = { - MPC_COMMON_MASK_SH_LIST_DCN30(_MASK) -}; - -#define optc_regs(id)\ -[id] = {OPTC_COMMON_REG_LIST_DCN3_0(id)} - - -static const struct dcn_optc_registers optc_regs[] = { - optc_regs(0), - optc_regs(1), - optc_regs(2), - optc_regs(3), - optc_regs(4), - optc_regs(5) -}; - -static const struct dcn_optc_shift optc_shift = { - OPTC_COMMON_MASK_SH_LIST_DCN30(__SHIFT) -}; - -static const struct dcn_optc_mask optc_mask = { - OPTC_COMMON_MASK_SH_LIST_DCN30(_MASK) -}; - -#define hubp_regs(id)\ -[id] = {\ - HUBP_REG_LIST_DCN30(id)\ -} - -static const struct dcn_hubp2_registers hubp_regs[] = { - hubp_regs(0), - hubp_regs(1), - hubp_regs(2), - hubp_regs(3), - hubp_regs(4), - hubp_regs(5) -}; - -static const struct dcn_hubp2_shift hubp_shift = { - HUBP_MASK_SH_LIST_DCN30(__SHIFT) -}; - -static const struct dcn_hubp2_mask hubp_mask = { - HUBP_MASK_SH_LIST_DCN30(_MASK) -}; - -static const struct dcn_hubbub_registers hubbub_reg = { - HUBBUB_REG_LIST_DCN30(0) -}; - -static const struct dcn_hubbub_shift hubbub_shift = { - HUBBUB_MASK_SH_LIST_DCN30(__SHIFT) -}; - -static const struct dcn_hubbub_mask hubbub_mask = { - HUBBUB_MASK_SH_LIST_DCN30(_MASK) -}; - -static const struct dccg_registers dccg_regs = { - DCCG_REG_LIST_DCN30() -}; - -static const struct dccg_shift dccg_shift = { - DCCG_MASK_SH_LIST_DCN3(__SHIFT) -}; - -static const struct dccg_mask dccg_mask = { - DCCG_MASK_SH_LIST_DCN3(_MASK) -}; - -static const struct dce_hwseq_registers hwseq_reg = { - HWSEQ_DCN30_REG_LIST() -}; - -static const struct dce_hwseq_shift hwseq_shift = { - HWSEQ_DCN30_MASK_SH_LIST(__SHIFT) -}; - -static const struct dce_hwseq_mask hwseq_mask = { - HWSEQ_DCN30_MASK_SH_LIST(_MASK) -}; -#define vmid_regs(id)\ -[id] = {\ - DCN20_VMID_REG_LIST(id)\ -} - -static const struct dcn_vmid_registers vmid_regs[] = { - vmid_regs(0), - vmid_regs(1), - vmid_regs(2), - vmid_regs(3), - vmid_regs(4), - vmid_regs(5), - vmid_regs(6), - vmid_regs(7), - vmid_regs(8), - vmid_regs(9), - vmid_regs(10), - vmid_regs(11), - vmid_regs(12), - vmid_regs(13), - vmid_regs(14), - vmid_regs(15) -}; - -static const struct dcn20_vmid_shift vmid_shifts = { - DCN20_VMID_MASK_SH_LIST(__SHIFT) -}; - -static const struct dcn20_vmid_mask vmid_masks = { - DCN20_VMID_MASK_SH_LIST(_MASK) -}; - -static const struct resource_caps res_cap_dcn3 = { - .num_timing_generator = 6, - .num_opp = 6, - .num_video_plane = 6, - .num_audio = 6, - .num_stream_encoder = 6, - .num_pll = 6, - .num_dwb = 1, - .num_ddc = 6, - .num_vmid = 16, - .num_mpc_3dlut = 3, - .num_dsc = 6, -}; - -static const struct dc_plane_cap plane_cap = { - .type = DC_PLANE_TYPE_DCN_UNIVERSAL, - .per_pixel_alpha = true, - - .pixel_format_support = { - .argb8888 = true, - .nv12 = true, - .fp16 = true, - .p010 = true, - .ayuv = false, - }, - - .max_upscale_factor = { - .argb8888 = 16000, - .nv12 = 16000, - .fp16 = 16000 - }, - - /* 6:1 downscaling ratio: 1000/6 = 166.666 */ - .max_downscale_factor = { - .argb8888 = 167, - .nv12 = 167, - .fp16 = 167 - }, - 16, - 16 -}; - -static const struct dc_debug_options debug_defaults_drv = { - .disable_dmcu = true, //No DMCU on DCN30 - .force_abm_enable = false, - .timing_trace = false, - .clock_trace = true, - .disable_pplib_clock_request = true, - .pipe_split_policy = MPC_SPLIT_DYNAMIC, - .force_single_disp_pipe_split = false, - .disable_dcc = DCC_ENABLE, - .vsr_support = true, - .performance_trace = false, - .max_downscale_src_width = 7680,/*upto 8K*/ - .disable_pplib_wm_range = false, - .scl_reset_length10 = true, - .sanity_checks = false, - .underflow_assert_delay_us = 0xFFFFFFFF, - .dwb_fi_phase = -1, // -1 = disable, - .dmub_command_table = true, - .use_max_lb = true, - .exit_idle_opt_for_cursor_updates = true, - .enable_legacy_fast_update = false, - .using_dml2 = false, -}; - -static const struct dc_panel_config panel_config_defaults = { - .psr = { - .disable_psr = false, - .disallow_psrsu = false, - .disallow_replay = false, - }, -}; - -static void dcn30_dpp_destroy(struct dpp **dpp) -{ - kfree(TO_DCN20_DPP(*dpp)); - *dpp = NULL; -} - -static struct dpp *dcn30_dpp_create( - struct dc_context *ctx, - uint32_t inst) -{ - struct dcn3_dpp *dpp = - kzalloc(sizeof(struct dcn3_dpp), GFP_KERNEL); - - if (!dpp) - return NULL; - - if (dpp3_construct(dpp, ctx, inst, - &dpp_regs[inst], &tf_shift, &tf_mask)) - return &dpp->base; - - BREAK_TO_DEBUGGER(); - kfree(dpp); - return NULL; -} - -static struct output_pixel_processor *dcn30_opp_create( - struct dc_context *ctx, uint32_t inst) -{ - struct dcn20_opp *opp = - kzalloc(sizeof(struct dcn20_opp), GFP_KERNEL); - - if (!opp) { - BREAK_TO_DEBUGGER(); - return NULL; - } - - dcn20_opp_construct(opp, ctx, inst, - &opp_regs[inst], &opp_shift, &opp_mask); - return &opp->base; -} - -static struct dce_aux *dcn30_aux_engine_create( - struct dc_context *ctx, - uint32_t inst) -{ - struct aux_engine_dce110 *aux_engine = - kzalloc(sizeof(struct aux_engine_dce110), GFP_KERNEL); - - if (!aux_engine) - return NULL; - - dce110_aux_engine_construct(aux_engine, ctx, inst, - SW_AUX_TIMEOUT_PERIOD_MULTIPLIER * AUX_TIMEOUT_PERIOD, - &aux_engine_regs[inst], - &aux_mask, - &aux_shift, - ctx->dc->caps.extended_aux_timeout_support); - - return &aux_engine->base; -} - -#define i2c_inst_regs(id) { I2C_HW_ENGINE_COMMON_REG_LIST_DCN30(id) } - -static const struct dce_i2c_registers i2c_hw_regs[] = { - i2c_inst_regs(1), - i2c_inst_regs(2), - i2c_inst_regs(3), - i2c_inst_regs(4), - i2c_inst_regs(5), - i2c_inst_regs(6), -}; - -static const struct dce_i2c_shift i2c_shifts = { - I2C_COMMON_MASK_SH_LIST_DCN30(__SHIFT) -}; - -static const struct dce_i2c_mask i2c_masks = { - I2C_COMMON_MASK_SH_LIST_DCN30(_MASK) -}; - -static struct dce_i2c_hw *dcn30_i2c_hw_create( - struct dc_context *ctx, - uint32_t inst) -{ - struct dce_i2c_hw *dce_i2c_hw = - kzalloc(sizeof(struct dce_i2c_hw), GFP_KERNEL); - - if (!dce_i2c_hw) - return NULL; - - dcn2_i2c_hw_construct(dce_i2c_hw, ctx, inst, - &i2c_hw_regs[inst], &i2c_shifts, &i2c_masks); - - return dce_i2c_hw; -} - -static struct mpc *dcn30_mpc_create( - struct dc_context *ctx, - int num_mpcc, - int num_rmu) -{ - struct dcn30_mpc *mpc30 = kzalloc(sizeof(struct dcn30_mpc), - GFP_KERNEL); - - if (!mpc30) - return NULL; - - dcn30_mpc_construct(mpc30, ctx, - &mpc_regs, - &mpc_shift, - &mpc_mask, - num_mpcc, - num_rmu); - - return &mpc30->base; -} - -static struct hubbub *dcn30_hubbub_create(struct dc_context *ctx) -{ - int i; - - struct dcn20_hubbub *hubbub3 = kzalloc(sizeof(struct dcn20_hubbub), - GFP_KERNEL); - - if (!hubbub3) - return NULL; - - hubbub3_construct(hubbub3, ctx, - &hubbub_reg, - &hubbub_shift, - &hubbub_mask); - - - for (i = 0; i < res_cap_dcn3.num_vmid; i++) { - struct dcn20_vmid *vmid = &hubbub3->vmid[i]; - - vmid->ctx = ctx; - - vmid->regs = &vmid_regs[i]; - vmid->shifts = &vmid_shifts; - vmid->masks = &vmid_masks; - } - - return &hubbub3->base; -} - -static struct timing_generator *dcn30_timing_generator_create( - struct dc_context *ctx, - uint32_t instance) -{ - struct optc *tgn10 = - kzalloc(sizeof(struct optc), GFP_KERNEL); - - if (!tgn10) - return NULL; - - tgn10->base.inst = instance; - tgn10->base.ctx = ctx; - - tgn10->tg_regs = &optc_regs[instance]; - tgn10->tg_shift = &optc_shift; - tgn10->tg_mask = &optc_mask; - - dcn30_timing_generator_init(tgn10); - - return &tgn10->base; -} - -static const struct encoder_feature_support link_enc_feature = { - .max_hdmi_deep_color = COLOR_DEPTH_121212, - .max_hdmi_pixel_clock = 600000, - .hdmi_ycbcr420_supported = true, - .dp_ycbcr420_supported = true, - .fec_supported = true, - .flags.bits.IS_HBR2_CAPABLE = true, - .flags.bits.IS_HBR3_CAPABLE = true, - .flags.bits.IS_TPS3_CAPABLE = true, - .flags.bits.IS_TPS4_CAPABLE = true -}; - -static struct link_encoder *dcn30_link_encoder_create( - struct dc_context *ctx, - const struct encoder_init_data *enc_init_data) -{ - struct dcn20_link_encoder *enc20 = - kzalloc(sizeof(struct dcn20_link_encoder), GFP_KERNEL); - - if (!enc20) - return NULL; - - dcn30_link_encoder_construct(enc20, - enc_init_data, - &link_enc_feature, - &link_enc_regs[enc_init_data->transmitter], - &link_enc_aux_regs[enc_init_data->channel - 1], - &link_enc_hpd_regs[enc_init_data->hpd_source], - &le_shift, - &le_mask); - - return &enc20->enc10.base; -} - -static struct panel_cntl *dcn30_panel_cntl_create(const struct panel_cntl_init_data *init_data) -{ - struct dce_panel_cntl *panel_cntl = - kzalloc(sizeof(struct dce_panel_cntl), GFP_KERNEL); - - if (!panel_cntl) - return NULL; - - dce_panel_cntl_construct(panel_cntl, - init_data, - &panel_cntl_regs[init_data->inst], - &panel_cntl_shift, - &panel_cntl_mask); - - return &panel_cntl->base; -} - -static void read_dce_straps( - struct dc_context *ctx, - struct resource_straps *straps) -{ - generic_reg_get(ctx, mmDC_PINSTRAPS + BASE(mmDC_PINSTRAPS_BASE_IDX), - FN(DC_PINSTRAPS, DC_PINSTRAPS_AUDIO), &straps->dc_pinstraps_audio); - -} - -static struct audio *dcn30_create_audio( - struct dc_context *ctx, unsigned int inst) -{ - return dce_audio_create(ctx, inst, - &audio_regs[inst], &audio_shift, &audio_mask); -} - -static struct vpg *dcn30_vpg_create( - struct dc_context *ctx, - uint32_t inst) -{ - struct dcn30_vpg *vpg3 = kzalloc(sizeof(struct dcn30_vpg), GFP_KERNEL); - - if (!vpg3) - return NULL; - - vpg3_construct(vpg3, ctx, inst, - &vpg_regs[inst], - &vpg_shift, - &vpg_mask); - - return &vpg3->base; -} - -static struct afmt *dcn30_afmt_create( - struct dc_context *ctx, - uint32_t inst) -{ - struct dcn30_afmt *afmt3 = kzalloc(sizeof(struct dcn30_afmt), GFP_KERNEL); - - if (!afmt3) - return NULL; - - afmt3_construct(afmt3, ctx, inst, - &afmt_regs[inst], - &afmt_shift, - &afmt_mask); - - return &afmt3->base; -} - -static struct stream_encoder *dcn30_stream_encoder_create(enum engine_id eng_id, - struct dc_context *ctx) -{ - struct dcn10_stream_encoder *enc1; - struct vpg *vpg; - struct afmt *afmt; - int vpg_inst; - int afmt_inst; - - /* Mapping of VPG, AFMT, DME register blocks to DIO block instance */ - if (eng_id <= ENGINE_ID_DIGF) { - vpg_inst = eng_id; - afmt_inst = eng_id; - } else - return NULL; - - enc1 = kzalloc(sizeof(struct dcn10_stream_encoder), GFP_KERNEL); - vpg = dcn30_vpg_create(ctx, vpg_inst); - afmt = dcn30_afmt_create(ctx, afmt_inst); - - if (!enc1 || !vpg || !afmt) { - kfree(enc1); - kfree(vpg); - kfree(afmt); - return NULL; - } - - dcn30_dio_stream_encoder_construct(enc1, ctx, ctx->dc_bios, - eng_id, vpg, afmt, - &stream_enc_regs[eng_id], - &se_shift, &se_mask); - - return &enc1->base; -} - -static struct dce_hwseq *dcn30_hwseq_create(struct dc_context *ctx) -{ - struct dce_hwseq *hws = kzalloc(sizeof(struct dce_hwseq), GFP_KERNEL); - - if (hws) { - hws->ctx = ctx; - hws->regs = &hwseq_reg; - hws->shifts = &hwseq_shift; - hws->masks = &hwseq_mask; - } - return hws; -} -static const struct resource_create_funcs res_create_funcs = { - .read_dce_straps = read_dce_straps, - .create_audio = dcn30_create_audio, - .create_stream_encoder = dcn30_stream_encoder_create, - .create_hwseq = dcn30_hwseq_create, -}; - -static void dcn30_resource_destruct(struct dcn30_resource_pool *pool) -{ - unsigned int i; - - for (i = 0; i < pool->base.stream_enc_count; i++) { - if (pool->base.stream_enc[i] != NULL) { - if (pool->base.stream_enc[i]->vpg != NULL) { - kfree(DCN30_VPG_FROM_VPG(pool->base.stream_enc[i]->vpg)); - pool->base.stream_enc[i]->vpg = NULL; - } - if (pool->base.stream_enc[i]->afmt != NULL) { - kfree(DCN30_AFMT_FROM_AFMT(pool->base.stream_enc[i]->afmt)); - pool->base.stream_enc[i]->afmt = NULL; - } - kfree(DCN10STRENC_FROM_STRENC(pool->base.stream_enc[i])); - pool->base.stream_enc[i] = NULL; - } - } - - for (i = 0; i < pool->base.res_cap->num_dsc; i++) { - if (pool->base.dscs[i] != NULL) - dcn20_dsc_destroy(&pool->base.dscs[i]); - } - - if (pool->base.mpc != NULL) { - kfree(TO_DCN20_MPC(pool->base.mpc)); - pool->base.mpc = NULL; - } - if (pool->base.hubbub != NULL) { - kfree(pool->base.hubbub); - pool->base.hubbub = NULL; - } - for (i = 0; i < pool->base.pipe_count; i++) { - if (pool->base.dpps[i] != NULL) - dcn30_dpp_destroy(&pool->base.dpps[i]); - - if (pool->base.ipps[i] != NULL) - pool->base.ipps[i]->funcs->ipp_destroy(&pool->base.ipps[i]); - - if (pool->base.hubps[i] != NULL) { - kfree(TO_DCN20_HUBP(pool->base.hubps[i])); - pool->base.hubps[i] = NULL; - } - - if (pool->base.irqs != NULL) { - dal_irq_service_destroy(&pool->base.irqs); - } - } - - for (i = 0; i < pool->base.res_cap->num_ddc; i++) { - if (pool->base.engines[i] != NULL) - dce110_engine_destroy(&pool->base.engines[i]); - if (pool->base.hw_i2cs[i] != NULL) { - kfree(pool->base.hw_i2cs[i]); - pool->base.hw_i2cs[i] = NULL; - } - if (pool->base.sw_i2cs[i] != NULL) { - kfree(pool->base.sw_i2cs[i]); - pool->base.sw_i2cs[i] = NULL; - } - } - - for (i = 0; i < pool->base.res_cap->num_opp; i++) { - if (pool->base.opps[i] != NULL) - pool->base.opps[i]->funcs->opp_destroy(&pool->base.opps[i]); - } - - for (i = 0; i < pool->base.res_cap->num_timing_generator; i++) { - if (pool->base.timing_generators[i] != NULL) { - kfree(DCN10TG_FROM_TG(pool->base.timing_generators[i])); - pool->base.timing_generators[i] = NULL; - } - } - - for (i = 0; i < pool->base.res_cap->num_dwb; i++) { - if (pool->base.dwbc[i] != NULL) { - kfree(TO_DCN30_DWBC(pool->base.dwbc[i])); - pool->base.dwbc[i] = NULL; - } - if (pool->base.mcif_wb[i] != NULL) { - kfree(TO_DCN30_MMHUBBUB(pool->base.mcif_wb[i])); - pool->base.mcif_wb[i] = NULL; - } - } - - for (i = 0; i < pool->base.audio_count; i++) { - if (pool->base.audios[i]) - dce_aud_destroy(&pool->base.audios[i]); - } - - for (i = 0; i < pool->base.clk_src_count; i++) { - if (pool->base.clock_sources[i] != NULL) { - dcn20_clock_source_destroy(&pool->base.clock_sources[i]); - pool->base.clock_sources[i] = NULL; - } - } - - for (i = 0; i < pool->base.res_cap->num_mpc_3dlut; i++) { - if (pool->base.mpc_lut[i] != NULL) { - dc_3dlut_func_release(pool->base.mpc_lut[i]); - pool->base.mpc_lut[i] = NULL; - } - if (pool->base.mpc_shaper[i] != NULL) { - dc_transfer_func_release(pool->base.mpc_shaper[i]); - pool->base.mpc_shaper[i] = NULL; - } - } - - if (pool->base.dp_clock_source != NULL) { - dcn20_clock_source_destroy(&pool->base.dp_clock_source); - pool->base.dp_clock_source = NULL; - } - - for (i = 0; i < pool->base.pipe_count; i++) { - if (pool->base.multiple_abms[i] != NULL) - dce_abm_destroy(&pool->base.multiple_abms[i]); - } - - if (pool->base.psr != NULL) - dmub_psr_destroy(&pool->base.psr); - - if (pool->base.dccg != NULL) - dcn_dccg_destroy(&pool->base.dccg); - - if (pool->base.oem_device != NULL) { - struct dc *dc = pool->base.oem_device->ctx->dc; - - dc->link_srv->destroy_ddc_service(&pool->base.oem_device); - } -} - -static struct hubp *dcn30_hubp_create( - struct dc_context *ctx, - uint32_t inst) -{ - struct dcn20_hubp *hubp2 = - kzalloc(sizeof(struct dcn20_hubp), GFP_KERNEL); - - if (!hubp2) - return NULL; - - if (hubp3_construct(hubp2, ctx, inst, - &hubp_regs[inst], &hubp_shift, &hubp_mask)) - return &hubp2->base; - - BREAK_TO_DEBUGGER(); - kfree(hubp2); - return NULL; -} - -static bool dcn30_dwbc_create(struct dc_context *ctx, struct resource_pool *pool) -{ - int i; - uint32_t pipe_count = pool->res_cap->num_dwb; - - for (i = 0; i < pipe_count; i++) { - struct dcn30_dwbc *dwbc30 = kzalloc(sizeof(struct dcn30_dwbc), - GFP_KERNEL); - - if (!dwbc30) { - dm_error("DC: failed to create dwbc30!\n"); - return false; - } - - dcn30_dwbc_construct(dwbc30, ctx, - &dwbc30_regs[i], - &dwbc30_shift, - &dwbc30_mask, - i); - - pool->dwbc[i] = &dwbc30->base; - } - return true; -} - -static bool dcn30_mmhubbub_create(struct dc_context *ctx, struct resource_pool *pool) -{ - int i; - uint32_t pipe_count = pool->res_cap->num_dwb; - - for (i = 0; i < pipe_count; i++) { - struct dcn30_mmhubbub *mcif_wb30 = kzalloc(sizeof(struct dcn30_mmhubbub), - GFP_KERNEL); - - if (!mcif_wb30) { - dm_error("DC: failed to create mcif_wb30!\n"); - return false; - } - - dcn30_mmhubbub_construct(mcif_wb30, ctx, - &mcif_wb30_regs[i], - &mcif_wb30_shift, - &mcif_wb30_mask, - i); - - pool->mcif_wb[i] = &mcif_wb30->base; - } - return true; -} - -static struct display_stream_compressor *dcn30_dsc_create( - struct dc_context *ctx, uint32_t inst) -{ - struct dcn20_dsc *dsc = - kzalloc(sizeof(struct dcn20_dsc), GFP_KERNEL); - - if (!dsc) { - BREAK_TO_DEBUGGER(); - return NULL; - } - - dsc2_construct(dsc, ctx, inst, &dsc_regs[inst], &dsc_shift, &dsc_mask); - return &dsc->base; -} - -enum dc_status dcn30_add_stream_to_ctx(struct dc *dc, struct dc_state *new_ctx, struct dc_stream_state *dc_stream) -{ - - return dcn20_add_stream_to_ctx(dc, new_ctx, dc_stream); -} - -static void dcn30_destroy_resource_pool(struct resource_pool **pool) -{ - struct dcn30_resource_pool *dcn30_pool = TO_DCN30_RES_POOL(*pool); - - dcn30_resource_destruct(dcn30_pool); - kfree(dcn30_pool); - *pool = NULL; -} - -static struct clock_source *dcn30_clock_source_create( - struct dc_context *ctx, - struct dc_bios *bios, - enum clock_source_id id, - const struct dce110_clk_src_regs *regs, - bool dp_clk_src) -{ - struct dce110_clk_src *clk_src = - kzalloc(sizeof(struct dce110_clk_src), GFP_KERNEL); - - if (!clk_src) - return NULL; - - if (dcn3_clk_src_construct(clk_src, ctx, bios, id, - regs, &cs_shift, &cs_mask)) { - clk_src->base.dp_clk_src = dp_clk_src; - return &clk_src->base; - } - - kfree(clk_src); - BREAK_TO_DEBUGGER(); - return NULL; -} - -int dcn30_populate_dml_pipes_from_context( - struct dc *dc, struct dc_state *context, - display_e2e_pipe_params_st *pipes, - bool fast_validate) -{ - int i, pipe_cnt; - struct resource_context *res_ctx = &context->res_ctx; - - DC_FP_START(); - dcn20_populate_dml_pipes_from_context(dc, context, pipes, fast_validate); - DC_FP_END(); - - for (i = 0, pipe_cnt = 0; i < dc->res_pool->pipe_count; i++) { - if (!res_ctx->pipe_ctx[i].stream) - continue; - - pipes[pipe_cnt++].pipe.scale_ratio_depth.lb_depth = - dm_lb_16; - } - - return pipe_cnt; -} - -void dcn30_populate_dml_writeback_from_context( - struct dc *dc, struct resource_context *res_ctx, display_e2e_pipe_params_st *pipes) -{ - DC_FP_START(); - dcn30_fpu_populate_dml_writeback_from_context(dc, res_ctx, pipes); - DC_FP_END(); -} - -unsigned int dcn30_calc_max_scaled_time( - unsigned int time_per_pixel, - enum mmhubbub_wbif_mode mode, - unsigned int urgent_watermark) -{ - unsigned int time_per_byte = 0; - unsigned int total_free_entry = 0xb40; - unsigned int buf_lh_capability; - unsigned int max_scaled_time; - - if (mode == PACKED_444) /* packed mode 32 bpp */ - time_per_byte = time_per_pixel/4; - else if (mode == PACKED_444_FP16) /* packed mode 64 bpp */ - time_per_byte = time_per_pixel/8; - - if (time_per_byte == 0) - time_per_byte = 1; - - buf_lh_capability = (total_free_entry*time_per_byte*32) >> 6; /* time_per_byte is in u6.6*/ - max_scaled_time = buf_lh_capability - urgent_watermark; - return max_scaled_time; -} - -void dcn30_set_mcif_arb_params( - struct dc *dc, - struct dc_state *context, - display_e2e_pipe_params_st *pipes, - int pipe_cnt) -{ - enum mmhubbub_wbif_mode wbif_mode; - struct display_mode_lib *dml = &context->bw_ctx.dml; - struct mcif_arb_params *wb_arb_params; - int i, j, dwb_pipe; - - /* Writeback MCIF_WB arbitration parameters */ - dwb_pipe = 0; - for (i = 0; i < dc->res_pool->pipe_count; i++) { - - if (!context->res_ctx.pipe_ctx[i].stream) - continue; - - for (j = 0; j < MAX_DWB_PIPES; j++) { - struct dc_writeback_info *writeback_info = &context->res_ctx.pipe_ctx[i].stream->writeback_info[j]; - - if (writeback_info->wb_enabled == false) - continue; - - //wb_arb_params = &context->res_ctx.pipe_ctx[i].stream->writeback_info[j].mcif_arb_params; - wb_arb_params = &context->bw_ctx.bw.dcn.bw_writeback.mcif_wb_arb[dwb_pipe]; - - if (writeback_info->dwb_params.cnv_params.fc_out_format == DWB_OUT_FORMAT_64BPP_ARGB || - writeback_info->dwb_params.cnv_params.fc_out_format == DWB_OUT_FORMAT_64BPP_RGBA) - wbif_mode = PACKED_444_FP16; - else - wbif_mode = PACKED_444; - - DC_FP_START(); - dcn30_fpu_set_mcif_arb_params(wb_arb_params, dml, pipes, pipe_cnt, j); - DC_FP_END(); - wb_arb_params->time_per_pixel = (1000000 << 6) / context->res_ctx.pipe_ctx[i].stream->phy_pix_clk; /* time_per_pixel should be in u6.6 format */ - wb_arb_params->slice_lines = 32; - wb_arb_params->arbitration_slice = 2; /* irrelevant since there is no YUV output */ - wb_arb_params->max_scaled_time = dcn30_calc_max_scaled_time(wb_arb_params->time_per_pixel, - wbif_mode, - wb_arb_params->cli_watermark[0]); /* assume 4 watermark sets have the same value */ - - dwb_pipe++; - - if (dwb_pipe >= MAX_DWB_PIPES) - return; - } - if (dwb_pipe >= MAX_DWB_PIPES) - return; - } - -} - -static struct dc_cap_funcs cap_funcs = { - .get_dcc_compression_cap = dcn20_get_dcc_compression_cap -}; - -bool dcn30_acquire_post_bldn_3dlut( - struct resource_context *res_ctx, - const struct resource_pool *pool, - int mpcc_id, - struct dc_3dlut **lut, - struct dc_transfer_func **shaper) -{ - int i; - bool ret = false; - union dc_3dlut_state *state; - - ASSERT(*lut == NULL && *shaper == NULL); - *lut = NULL; - *shaper = NULL; - - for (i = 0; i < pool->res_cap->num_mpc_3dlut; i++) { - if (!res_ctx->is_mpc_3dlut_acquired[i]) { - *lut = pool->mpc_lut[i]; - *shaper = pool->mpc_shaper[i]; - state = &pool->mpc_lut[i]->state; - res_ctx->is_mpc_3dlut_acquired[i] = true; - state->bits.rmu_idx_valid = 1; - state->bits.rmu_mux_num = i; - if (state->bits.rmu_mux_num == 0) - state->bits.mpc_rmu0_mux = mpcc_id; - else if (state->bits.rmu_mux_num == 1) - state->bits.mpc_rmu1_mux = mpcc_id; - else if (state->bits.rmu_mux_num == 2) - state->bits.mpc_rmu2_mux = mpcc_id; - ret = true; - break; - } - } - return ret; -} - -bool dcn30_release_post_bldn_3dlut( - struct resource_context *res_ctx, - const struct resource_pool *pool, - struct dc_3dlut **lut, - struct dc_transfer_func **shaper) -{ - int i; - bool ret = false; - - for (i = 0; i < pool->res_cap->num_mpc_3dlut; i++) { - if (pool->mpc_lut[i] == *lut && pool->mpc_shaper[i] == *shaper) { - res_ctx->is_mpc_3dlut_acquired[i] = false; - pool->mpc_lut[i]->state.raw = 0; - *lut = NULL; - *shaper = NULL; - ret = true; - break; - } - } - return ret; -} - -static bool is_soc_bounding_box_valid(struct dc *dc) -{ - uint32_t hw_internal_rev = dc->ctx->asic_id.hw_internal_rev; - - if (ASICREV_IS_SIENNA_CICHLID_P(hw_internal_rev)) - return true; - - return false; -} - -static bool init_soc_bounding_box(struct dc *dc, - struct dcn30_resource_pool *pool) -{ - 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 (!is_soc_bounding_box_valid(dc)) { - DC_LOG_ERROR("%s: not valid soc bounding box\n", __func__); - return false; - } - - 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); - DC_FP_START(); - patch_dcn30_soc_bounding_box(dc, &dcn3_0_soc); - DC_FP_END(); - - return true; -} - -static bool dcn30_split_stream_for_mpc_or_odm( - const struct dc *dc, - struct resource_context *res_ctx, - struct pipe_ctx *pri_pipe, - struct pipe_ctx *sec_pipe, - bool odm) -{ - int pipe_idx = sec_pipe->pipe_idx; - const struct resource_pool *pool = dc->res_pool; - - *sec_pipe = *pri_pipe; - - sec_pipe->pipe_idx = pipe_idx; - sec_pipe->plane_res.mi = pool->mis[pipe_idx]; - sec_pipe->plane_res.hubp = pool->hubps[pipe_idx]; - sec_pipe->plane_res.ipp = pool->ipps[pipe_idx]; - sec_pipe->plane_res.xfm = pool->transforms[pipe_idx]; - sec_pipe->plane_res.dpp = pool->dpps[pipe_idx]; - sec_pipe->plane_res.mpcc_inst = pool->dpps[pipe_idx]->inst; - sec_pipe->stream_res.dsc = NULL; - if (odm) { - if (pri_pipe->next_odm_pipe) { - ASSERT(pri_pipe->next_odm_pipe != sec_pipe); - sec_pipe->next_odm_pipe = pri_pipe->next_odm_pipe; - sec_pipe->next_odm_pipe->prev_odm_pipe = sec_pipe; - } - if (pri_pipe->top_pipe && pri_pipe->top_pipe->next_odm_pipe) { - pri_pipe->top_pipe->next_odm_pipe->bottom_pipe = sec_pipe; - sec_pipe->top_pipe = pri_pipe->top_pipe->next_odm_pipe; - } - if (pri_pipe->bottom_pipe && pri_pipe->bottom_pipe->next_odm_pipe) { - pri_pipe->bottom_pipe->next_odm_pipe->top_pipe = sec_pipe; - sec_pipe->bottom_pipe = pri_pipe->bottom_pipe->next_odm_pipe; - } - pri_pipe->next_odm_pipe = sec_pipe; - sec_pipe->prev_odm_pipe = pri_pipe; - - if (!sec_pipe->top_pipe) - sec_pipe->stream_res.opp = pool->opps[pipe_idx]; - else - sec_pipe->stream_res.opp = sec_pipe->top_pipe->stream_res.opp; - if (sec_pipe->stream->timing.flags.DSC == 1) { - dcn20_acquire_dsc(dc, res_ctx, &sec_pipe->stream_res.dsc, pipe_idx); - ASSERT(sec_pipe->stream_res.dsc); - if (sec_pipe->stream_res.dsc == NULL) - return false; - } - } else { - if (pri_pipe->bottom_pipe) { - ASSERT(pri_pipe->bottom_pipe != sec_pipe); - sec_pipe->bottom_pipe = pri_pipe->bottom_pipe; - sec_pipe->bottom_pipe->top_pipe = sec_pipe; - } - pri_pipe->bottom_pipe = sec_pipe; - sec_pipe->top_pipe = pri_pipe; - - ASSERT(pri_pipe->plane_state); - } - - return true; -} - -static struct pipe_ctx *dcn30_find_split_pipe( - struct dc *dc, - struct dc_state *context, - int old_index) -{ - struct pipe_ctx *pipe = NULL; - int i; - - if (old_index >= 0 && context->res_ctx.pipe_ctx[old_index].stream == NULL) { - pipe = &context->res_ctx.pipe_ctx[old_index]; - pipe->pipe_idx = old_index; - } - - if (!pipe) - for (i = dc->res_pool->pipe_count - 1; i >= 0; i--) { - if (dc->current_state->res_ctx.pipe_ctx[i].top_pipe == NULL - && dc->current_state->res_ctx.pipe_ctx[i].prev_odm_pipe == NULL) { - if (context->res_ctx.pipe_ctx[i].stream == NULL) { - pipe = &context->res_ctx.pipe_ctx[i]; - pipe->pipe_idx = i; - break; - } - } - } - - /* - * May need to fix pipes getting tossed from 1 opp to another on flip - * Add for debugging transient underflow during topology updates: - * ASSERT(pipe); - */ - if (!pipe) - for (i = dc->res_pool->pipe_count - 1; i >= 0; i--) { - if (context->res_ctx.pipe_ctx[i].stream == NULL) { - pipe = &context->res_ctx.pipe_ctx[i]; - pipe->pipe_idx = i; - break; - } - } - - return pipe; -} - -noinline bool dcn30_internal_validate_bw( - struct dc *dc, - struct dc_state *context, - display_e2e_pipe_params_st *pipes, - int *pipe_cnt_out, - int *vlevel_out, - bool fast_validate, - bool allow_self_refresh_only) -{ - bool out = false; - bool repopulate_pipes = false; - int split[MAX_PIPES] = { 0 }; - bool merge[MAX_PIPES] = { false }; - bool newly_split[MAX_PIPES] = { false }; - int pipe_cnt, i, pipe_idx, vlevel; - struct vba_vars_st *vba = &context->bw_ctx.dml.vba; - - ASSERT(pipes); - if (!pipes) - return false; - - context->bw_ctx.dml.vba.maxMpcComb = 0; - context->bw_ctx.dml.vba.VoltageLevel = 0; - context->bw_ctx.dml.vba.DRAMClockChangeSupport[0][0] = dm_dram_clock_change_vactive; - dc->res_pool->funcs->update_soc_for_wm_a(dc, context); - pipe_cnt = dc->res_pool->funcs->populate_dml_pipes(dc, context, pipes, fast_validate); - - if (!pipe_cnt) { - out = true; - goto validate_out; - } - - dml_log_pipe_params(&context->bw_ctx.dml, pipes, pipe_cnt); - - if (!fast_validate || !allow_self_refresh_only) { - /* - * DML favors voltage over p-state, but we're more interested in - * supporting p-state over voltage. We can't support p-state in - * prefetch mode > 0 so try capping the prefetch mode to start. - */ - context->bw_ctx.dml.soc.allow_dram_self_refresh_or_dram_clock_change_in_vblank = - dm_allow_self_refresh_and_mclk_switch; - vlevel = dml_get_voltage_level(&context->bw_ctx.dml, pipes, pipe_cnt); - /* This may adjust vlevel and maxMpcComb */ - if (vlevel < context->bw_ctx.dml.soc.num_states) - vlevel = dcn20_validate_apply_pipe_split_flags(dc, context, vlevel, split, merge); - } - if (allow_self_refresh_only && - (fast_validate || vlevel == context->bw_ctx.dml.soc.num_states || - vba->DRAMClockChangeSupport[vlevel][vba->maxMpcComb] == dm_dram_clock_change_unsupported)) { - /* - * If mode is unsupported or there's still no p-state support - * then fall back to favoring voltage. - * - * We don't actually support prefetch mode 2, so require that we - * at least support prefetch mode 1. - */ - context->bw_ctx.dml.soc.allow_dram_self_refresh_or_dram_clock_change_in_vblank = - dm_allow_self_refresh; - - vlevel = dml_get_voltage_level(&context->bw_ctx.dml, pipes, pipe_cnt); - if (vlevel < context->bw_ctx.dml.soc.num_states) { - memset(split, 0, sizeof(split)); - memset(merge, 0, sizeof(merge)); - vlevel = dcn20_validate_apply_pipe_split_flags(dc, context, vlevel, split, merge); - } - } - - dml_log_mode_support_params(&context->bw_ctx.dml); - - if (vlevel == context->bw_ctx.dml.soc.num_states) - goto validate_fail; - - if (!dc->config.enable_windowed_mpo_odm) { - for (i = 0, pipe_idx = 0; i < dc->res_pool->pipe_count; i++) { - struct pipe_ctx *pipe = &context->res_ctx.pipe_ctx[i]; - struct pipe_ctx *mpo_pipe = pipe->bottom_pipe; - - if (!pipe->stream) - continue; - - /* We only support full screen mpo with ODM */ - if (vba->ODMCombineEnabled[vba->pipe_plane[pipe_idx]] != dm_odm_combine_mode_disabled - && pipe->plane_state && mpo_pipe - && memcmp(&mpo_pipe->plane_state->clip_rect, - &pipe->stream->src, - sizeof(struct rect)) != 0) { - ASSERT(mpo_pipe->plane_state != pipe->plane_state); - goto validate_fail; - } - pipe_idx++; - } - } - - /* merge pipes if necessary */ - for (i = 0; i < dc->res_pool->pipe_count; i++) { - struct pipe_ctx *pipe = &context->res_ctx.pipe_ctx[i]; - - /*skip pipes that don't need merging*/ - if (!merge[i]) - continue; - - /* if ODM merge we ignore mpc tree, mpo pipes will have their own flags */ - if (pipe->prev_odm_pipe) { - /*split off odm pipe*/ - pipe->prev_odm_pipe->next_odm_pipe = pipe->next_odm_pipe; - if (pipe->next_odm_pipe) - pipe->next_odm_pipe->prev_odm_pipe = pipe->prev_odm_pipe; - - pipe->bottom_pipe = NULL; - pipe->next_odm_pipe = NULL; - pipe->plane_state = NULL; - pipe->stream = NULL; - pipe->top_pipe = NULL; - pipe->prev_odm_pipe = NULL; - if (pipe->stream_res.dsc) - dcn20_release_dsc(&context->res_ctx, dc->res_pool, &pipe->stream_res.dsc); - memset(&pipe->plane_res, 0, sizeof(pipe->plane_res)); - memset(&pipe->stream_res, 0, sizeof(pipe->stream_res)); - repopulate_pipes = true; - } else if (pipe->top_pipe && pipe->top_pipe->plane_state == pipe->plane_state) { - struct pipe_ctx *top_pipe = pipe->top_pipe; - struct pipe_ctx *bottom_pipe = pipe->bottom_pipe; - - top_pipe->bottom_pipe = bottom_pipe; - if (bottom_pipe) - bottom_pipe->top_pipe = top_pipe; - - pipe->top_pipe = NULL; - pipe->bottom_pipe = NULL; - pipe->plane_state = NULL; - pipe->stream = NULL; - memset(&pipe->plane_res, 0, sizeof(pipe->plane_res)); - memset(&pipe->stream_res, 0, sizeof(pipe->stream_res)); - repopulate_pipes = true; - } else - ASSERT(0); /* Should never try to merge master pipe */ - - } - - for (i = 0, pipe_idx = -1; i < dc->res_pool->pipe_count; i++) { - struct pipe_ctx *pipe = &context->res_ctx.pipe_ctx[i]; - struct pipe_ctx *old_pipe = &dc->current_state->res_ctx.pipe_ctx[i]; - struct pipe_ctx *hsplit_pipe = NULL; - bool odm; - int old_index = -1; - - if (!pipe->stream || newly_split[i]) - continue; - - pipe_idx++; - odm = vba->ODMCombineEnabled[vba->pipe_plane[pipe_idx]] != dm_odm_combine_mode_disabled; - - if (!pipe->plane_state && !odm) - continue; - - if (split[i]) { - if (odm) { - if (split[i] == 4 && old_pipe->next_odm_pipe && old_pipe->next_odm_pipe->next_odm_pipe) - old_index = old_pipe->next_odm_pipe->next_odm_pipe->pipe_idx; - else if (old_pipe->next_odm_pipe) - old_index = old_pipe->next_odm_pipe->pipe_idx; - } else { - if (split[i] == 4 && old_pipe->bottom_pipe && old_pipe->bottom_pipe->bottom_pipe && - old_pipe->bottom_pipe->bottom_pipe->plane_state == old_pipe->plane_state) - old_index = old_pipe->bottom_pipe->bottom_pipe->pipe_idx; - else if (old_pipe->bottom_pipe && - old_pipe->bottom_pipe->plane_state == old_pipe->plane_state) - old_index = old_pipe->bottom_pipe->pipe_idx; - } - hsplit_pipe = dcn30_find_split_pipe(dc, context, old_index); - ASSERT(hsplit_pipe); - if (!hsplit_pipe) - goto validate_fail; - - if (!dcn30_split_stream_for_mpc_or_odm( - dc, &context->res_ctx, - pipe, hsplit_pipe, odm)) - goto validate_fail; - - newly_split[hsplit_pipe->pipe_idx] = true; - repopulate_pipes = true; - } - if (split[i] == 4) { - struct pipe_ctx *pipe_4to1; - - if (odm && old_pipe->next_odm_pipe) - old_index = old_pipe->next_odm_pipe->pipe_idx; - else if (!odm && old_pipe->bottom_pipe && - old_pipe->bottom_pipe->plane_state == old_pipe->plane_state) - old_index = old_pipe->bottom_pipe->pipe_idx; - else - old_index = -1; - pipe_4to1 = dcn30_find_split_pipe(dc, context, old_index); - ASSERT(pipe_4to1); - if (!pipe_4to1) - goto validate_fail; - if (!dcn30_split_stream_for_mpc_or_odm( - dc, &context->res_ctx, - pipe, pipe_4to1, odm)) - goto validate_fail; - newly_split[pipe_4to1->pipe_idx] = true; - - if (odm && old_pipe->next_odm_pipe && old_pipe->next_odm_pipe->next_odm_pipe - && old_pipe->next_odm_pipe->next_odm_pipe->next_odm_pipe) - old_index = old_pipe->next_odm_pipe->next_odm_pipe->next_odm_pipe->pipe_idx; - else if (!odm && old_pipe->bottom_pipe && old_pipe->bottom_pipe->bottom_pipe && - old_pipe->bottom_pipe->bottom_pipe->bottom_pipe && - old_pipe->bottom_pipe->bottom_pipe->bottom_pipe->plane_state == old_pipe->plane_state) - old_index = old_pipe->bottom_pipe->bottom_pipe->bottom_pipe->pipe_idx; - else - old_index = -1; - pipe_4to1 = dcn30_find_split_pipe(dc, context, old_index); - ASSERT(pipe_4to1); - if (!pipe_4to1) - goto validate_fail; - if (!dcn30_split_stream_for_mpc_or_odm( - dc, &context->res_ctx, - hsplit_pipe, pipe_4to1, odm)) - goto validate_fail; - newly_split[pipe_4to1->pipe_idx] = true; - } - if (odm) - dcn20_build_mapped_resource(dc, context, pipe->stream); - } - - for (i = 0; i < dc->res_pool->pipe_count; i++) { - struct pipe_ctx *pipe = &context->res_ctx.pipe_ctx[i]; - - if (pipe->plane_state) { - if (!resource_build_scaling_params(pipe)) - goto validate_fail; - } - } - - /* Actual dsc count per stream dsc validation*/ - if (!dcn20_validate_dsc(dc, context)) { - vba->ValidationStatus[vba->soc.num_states] = DML_FAIL_DSC_VALIDATION_FAILURE; - goto validate_fail; - } - - if (repopulate_pipes) - pipe_cnt = dc->res_pool->funcs->populate_dml_pipes(dc, context, pipes, fast_validate); - context->bw_ctx.dml.vba.VoltageLevel = vlevel; - *vlevel_out = vlevel; - *pipe_cnt_out = pipe_cnt; - - out = true; - goto validate_out; - -validate_fail: - out = false; - -validate_out: - return out; -} - -static int get_refresh_rate(struct dc_state *context) -{ - int refresh_rate = 0; - int h_v_total = 0; - struct dc_crtc_timing *timing = NULL; - - if (context == NULL || context->streams[0] == NULL) - return 0; - - /* check if refresh rate at least 120hz */ - timing = &context->streams[0]->timing; - if (timing == NULL) - return 0; - - h_v_total = timing->h_total * timing->v_total; - if (h_v_total == 0) - return 0; - - refresh_rate = ((timing->pix_clk_100hz * 100) / (h_v_total)) + 1; - return refresh_rate; -} - -#define MAX_STRETCHED_V_BLANK 500 // in micro-seconds -/* - * Scaling factor for v_blank stretch calculations considering timing in - * micro-seconds and pixel clock in 100hz. - * Note: the parenthesis are necessary to ensure the correct order of - * operation where V_SCALE is used. - */ -#define V_SCALE (10000 / MAX_STRETCHED_V_BLANK) - -static int get_frame_rate_at_max_stretch_100hz(struct dc_state *context) -{ - struct dc_crtc_timing *timing = NULL; - uint32_t sec_per_100_lines; - uint32_t max_v_blank; - uint32_t curr_v_blank; - uint32_t v_stretch_max; - uint32_t stretched_frame_pix_cnt; - uint32_t scaled_stretched_frame_pix_cnt; - uint32_t scaled_refresh_rate; - - if (context == NULL || context->streams[0] == NULL) - return 0; - - /* check if refresh rate at least 120hz */ - timing = &context->streams[0]->timing; - if (timing == NULL) - return 0; - - sec_per_100_lines = timing->pix_clk_100hz / timing->h_total + 1; - max_v_blank = sec_per_100_lines / V_SCALE + 1; - curr_v_blank = timing->v_total - timing->v_addressable; - v_stretch_max = (max_v_blank > curr_v_blank) ? (max_v_blank - curr_v_blank) : (0); - stretched_frame_pix_cnt = (v_stretch_max + timing->v_total) * timing->h_total; - scaled_stretched_frame_pix_cnt = stretched_frame_pix_cnt / 10000; - scaled_refresh_rate = (timing->pix_clk_100hz) / scaled_stretched_frame_pix_cnt + 1; - - return scaled_refresh_rate; -} - -static bool is_refresh_rate_support_mclk_switch_using_fw_based_vblank_stretch(struct dc_state *context) -{ - int refresh_rate_max_stretch_100hz; - int min_refresh_100hz; - - if (context == NULL || context->streams[0] == NULL) - return false; - - refresh_rate_max_stretch_100hz = get_frame_rate_at_max_stretch_100hz(context); - min_refresh_100hz = context->streams[0]->timing.min_refresh_in_uhz / 10000; - - if (refresh_rate_max_stretch_100hz < min_refresh_100hz) - return false; - - return true; -} - -bool dcn30_can_support_mclk_switch_using_fw_based_vblank_stretch(struct dc *dc, struct dc_state *context) -{ - int refresh_rate = 0; - const int minimum_refreshrate_supported = 120; - - if (context == NULL || context->streams[0] == NULL) - return false; - - if (context->streams[0]->sink->edid_caps.panel_patch.disable_fams) - return false; - - if (dc->debug.disable_fams) - return false; - - if (!dc->caps.dmub_caps.mclk_sw) - return false; - - if (context->bw_ctx.bw.dcn.clk.fw_based_mclk_switching_shut_down) - return false; - - /* more then 1 monitor connected */ - if (context->stream_count != 1) - return false; - - refresh_rate = get_refresh_rate(context); - if (refresh_rate < minimum_refreshrate_supported) - return false; - - if (!is_refresh_rate_support_mclk_switch_using_fw_based_vblank_stretch(context)) - return false; - - if (!context->streams[0]->allow_freesync) - return false; - - if (context->streams[0]->vrr_active_variable && dc->debug.disable_fams_gaming) - return false; - - context->streams[0]->fpo_in_use = true; - - return true; -} - -/* - * set up FPO watermarks, pstate, dram latency - */ -void dcn30_setup_mclk_switch_using_fw_based_vblank_stretch(struct dc *dc, struct dc_state *context) -{ - ASSERT(dc != NULL && context != NULL); - if (dc == NULL || context == NULL) - return; - - /* Set wm_a.pstate so high natural MCLK switches are impossible: 4 seconds */ - context->bw_ctx.bw.dcn.watermarks.a.cstate_pstate.pstate_change_ns = 4U * 1000U * 1000U * 1000U; -} - -void dcn30_update_soc_for_wm_a(struct dc *dc, struct dc_state *context) -{ - DC_FP_START(); - dcn30_fpu_update_soc_for_wm_a(dc, context); - DC_FP_END(); -} - -void dcn30_calculate_wm_and_dlg( - struct dc *dc, struct dc_state *context, - display_e2e_pipe_params_st *pipes, - int pipe_cnt, - int vlevel) -{ - DC_FP_START(); - dcn30_fpu_calculate_wm_and_dlg(dc, context, pipes, pipe_cnt, vlevel); - DC_FP_END(); -} - -bool dcn30_validate_bandwidth(struct dc *dc, - struct dc_state *context, - bool fast_validate) -{ - bool out = false; - - BW_VAL_TRACE_SETUP(); - - int vlevel = 0; - int pipe_cnt = 0; - display_e2e_pipe_params_st *pipes = kzalloc(dc->res_pool->pipe_count * sizeof(display_e2e_pipe_params_st), GFP_KERNEL); - DC_LOGGER_INIT(dc->ctx->logger); - - BW_VAL_TRACE_COUNT(); - - DC_FP_START(); - out = dcn30_internal_validate_bw(dc, context, pipes, &pipe_cnt, &vlevel, fast_validate, true); - DC_FP_END(); - - if (pipe_cnt == 0) - goto validate_out; - - if (!out) - goto validate_fail; - - BW_VAL_TRACE_END_VOLTAGE_LEVEL(); - - if (fast_validate) { - BW_VAL_TRACE_SKIP(fast); - goto validate_out; - } - - DC_FP_START(); - if (dc->res_pool->funcs->calculate_wm_and_dlg) - dc->res_pool->funcs->calculate_wm_and_dlg(dc, context, pipes, pipe_cnt, vlevel); - DC_FP_END(); - - BW_VAL_TRACE_END_WATERMARKS(); - - goto validate_out; - -validate_fail: - DC_LOG_WARNING("Mode Validation Warning: %s failed validation.\n", - dml_get_status_message(context->bw_ctx.dml.vba.ValidationStatus[context->bw_ctx.dml.vba.soc.num_states])); - - BW_VAL_TRACE_SKIP(fail); - out = false; - -validate_out: - kfree(pipes); - - BW_VAL_TRACE_FINISH(); - - return out; -} - -void dcn30_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; - - struct dc_bounding_box_max_clk dcn30_bb_max_clk; - - memset(&dcn30_bb_max_clk, 0, sizeof(dcn30_bb_max_clk)); - - if (dc->ctx->dc_bios->vram_info.num_chans) - dcn3_0_soc.num_chans = dc->ctx->dc_bios->vram_info.num_chans; - - DC_FP_START(); - dcn30_fpu_update_dram_channel_width_bytes(dc); - DC_FP_END(); - - if (bw_params->clk_table.entries[0].memclk_mhz) { - - for (i = 0; i < MAX_NUM_DPM_LVL; i++) { - if (bw_params->clk_table.entries[i].dcfclk_mhz > dcn30_bb_max_clk.max_dcfclk_mhz) - dcn30_bb_max_clk.max_dcfclk_mhz = bw_params->clk_table.entries[i].dcfclk_mhz; - if (bw_params->clk_table.entries[i].dispclk_mhz > dcn30_bb_max_clk.max_dispclk_mhz) - dcn30_bb_max_clk.max_dispclk_mhz = bw_params->clk_table.entries[i].dispclk_mhz; - if (bw_params->clk_table.entries[i].dppclk_mhz > dcn30_bb_max_clk.max_dppclk_mhz) - dcn30_bb_max_clk.max_dppclk_mhz = bw_params->clk_table.entries[i].dppclk_mhz; - if (bw_params->clk_table.entries[i].phyclk_mhz > dcn30_bb_max_clk.max_phyclk_mhz) - dcn30_bb_max_clk.max_phyclk_mhz = bw_params->clk_table.entries[i].phyclk_mhz; - } - - DC_FP_START(); - dcn30_fpu_update_max_clk(&dcn30_bb_max_clk); - DC_FP_END(); - - if (dcn30_bb_max_clk.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] = dcn30_bb_max_clk.max_dcfclk_mhz; - num_dcfclk_sta_targets++; - } else if (dcn30_bb_max_clk.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] > dcn30_bb_max_clk.max_dcfclk_mhz) { - dcfclk_sta_targets[i] = dcn30_bb_max_clk.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++) { - DC_FP_START(); - dcn30_fpu_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) { - 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] <= dcn30_bb_max_clk.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] <= dcn30_bb_max_clk.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_0_soc.num_states = num_states; - DC_FP_START(); - dcn30_fpu_update_bw_bounding_box(dc, bw_params, &dcn30_bb_max_clk, dcfclk_mhz, dram_speed_mts); - DC_FP_END(); - } -} - -static void dcn30_get_panel_config_defaults(struct dc_panel_config *panel_config) -{ - *panel_config = panel_config_defaults; -} - -static const struct resource_funcs dcn30_res_pool_funcs = { - .destroy = dcn30_destroy_resource_pool, - .link_enc_create = dcn30_link_encoder_create, - .panel_cntl_create = dcn30_panel_cntl_create, - .validate_bandwidth = dcn30_validate_bandwidth, - .calculate_wm_and_dlg = dcn30_calculate_wm_and_dlg, - .update_soc_for_wm_a = dcn30_update_soc_for_wm_a, - .populate_dml_pipes = dcn30_populate_dml_pipes_from_context, - .acquire_free_pipe_as_secondary_dpp_pipe = dcn20_acquire_free_pipe_for_layer, - .release_pipe = dcn20_release_pipe, - .add_stream_to_ctx = dcn30_add_stream_to_ctx, - .add_dsc_to_stream_resource = dcn20_add_dsc_to_stream_resource, - .remove_stream_from_ctx = dcn20_remove_stream_from_ctx, - .populate_dml_writeback_from_context = dcn30_populate_dml_writeback_from_context, - .set_mcif_arb_params = dcn30_set_mcif_arb_params, - .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, - .patch_unknown_plane_state = dcn20_patch_unknown_plane_state, - .get_panel_config_defaults = dcn30_get_panel_config_defaults, -}; - -#define CTX ctx - -#define REG(reg_name) \ - (DCN_BASE.instance[0].segment[mm ## reg_name ## _BASE_IDX] + mm ## reg_name) - -static uint32_t read_pipe_fuses(struct dc_context *ctx) -{ - uint32_t value = REG_READ(CC_DC_PIPE_DIS); - /* Support for max 6 pipes */ - value = value & 0x3f; - return value; -} - -static bool dcn30_resource_construct( - uint8_t num_virtual_links, - struct dc *dc, - struct dcn30_resource_pool *pool) -{ - int i; - struct dc_context *ctx = dc->ctx; - struct irq_service_init_data init_data; - struct ddc_service_init_data ddc_init_data = {0}; - uint32_t pipe_fuses = read_pipe_fuses(ctx); - uint32_t num_pipes = 0; - - if (!(pipe_fuses == 0 || pipe_fuses == 0x3e)) { - BREAK_TO_DEBUGGER(); - dm_error("DC: Unexpected fuse recipe for navi2x !\n"); - /* fault to single pipe */ - pipe_fuses = 0x3e; - } - - DC_FP_START(); - - ctx->dc_bios->regs = &bios_regs; - - pool->base.res_cap = &res_cap_dcn3; - - pool->base.funcs = &dcn30_res_pool_funcs; - - /************************************************* - * Resource + asic cap harcoding * - *************************************************/ - pool->base.underlay_pipe_index = NO_UNDERLAY_PIPE; - pool->base.pipe_count = pool->base.res_cap->num_timing_generator; - pool->base.mpcc_count = pool->base.res_cap->num_timing_generator; - dc->caps.max_downscale_ratio = 600; - dc->caps.i2c_speed_in_khz = 100; - dc->caps.i2c_speed_in_khz_hdcp = 100; /*1.4 w/a not applied by default*/ - 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 = 8; - /* 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 = 2; - dc->caps.max_slave_yuv_planes = 2; - dc->caps.max_slave_rgb_planes = 2; - dc->caps.post_blend_color_processing = true; - dc->caps.force_dp_tps4_for_cp2520 = true; - dc->caps.extended_aux_timeout_support = true; - dc->caps.dmcub_support = true; - - /* Color pipeline capabilities */ - dc->caps.color.dpp.dcn_arch = 1; - dc->caps.color.dpp.input_lut_shared = 0; - dc->caps.color.dpp.icsc = 1; - dc->caps.color.dpp.dgam_ram = 0; // must use gamma_corr - dc->caps.color.dpp.dgam_rom_caps.srgb = 1; - dc->caps.color.dpp.dgam_rom_caps.bt2020 = 1; - dc->caps.color.dpp.dgam_rom_caps.gamma2_2 = 1; - dc->caps.color.dpp.dgam_rom_caps.pq = 1; - dc->caps.color.dpp.dgam_rom_caps.hlg = 1; - dc->caps.color.dpp.post_csc = 1; - dc->caps.color.dpp.gamma_corr = 1; - dc->caps.color.dpp.dgam_rom_for_yuv = 0; - - dc->caps.color.dpp.hw_3d_lut = 1; - dc->caps.color.dpp.ogam_ram = 1; - // no OGAM ROM on DCN3 - dc->caps.color.dpp.ogam_rom_caps.srgb = 0; - dc->caps.color.dpp.ogam_rom_caps.bt2020 = 0; - dc->caps.color.dpp.ogam_rom_caps.gamma2_2 = 0; - dc->caps.color.dpp.ogam_rom_caps.pq = 0; - dc->caps.color.dpp.ogam_rom_caps.hlg = 0; - dc->caps.color.dpp.ocsc = 0; - - dc->caps.color.mpc.gamut_remap = 1; - dc->caps.color.mpc.num_3dluts = pool->base.res_cap->num_mpc_3dlut; //3 - dc->caps.color.mpc.ogam_ram = 1; - dc->caps.color.mpc.ogam_rom_caps.srgb = 0; - dc->caps.color.mpc.ogam_rom_caps.bt2020 = 0; - dc->caps.color.mpc.ogam_rom_caps.gamma2_2 = 0; - dc->caps.color.mpc.ogam_rom_caps.pq = 0; - dc->caps.color.mpc.ogam_rom_caps.hlg = 0; - dc->caps.color.mpc.ocsc = 1; - - dc->caps.dp_hdmi21_pcon_support = true; - dc->caps.max_v_total = (1 << 15) - 1; - - /* read VBIOS LTTPR caps */ - { - if (ctx->dc_bios->funcs->get_lttpr_caps) { - enum bp_result bp_query_result; - uint8_t is_vbios_lttpr_enable = 0; - - bp_query_result = ctx->dc_bios->funcs->get_lttpr_caps(ctx->dc_bios, &is_vbios_lttpr_enable); - dc->caps.vbios_lttpr_enable = (bp_query_result == BP_RESULT_OK) && !!is_vbios_lttpr_enable; - } - - if (ctx->dc_bios->funcs->get_lttpr_interop) { - enum bp_result bp_query_result; - uint8_t is_vbios_interop_enabled = 0; - - bp_query_result = ctx->dc_bios->funcs->get_lttpr_interop(ctx->dc_bios, - &is_vbios_interop_enabled); - dc->caps.vbios_lttpr_aware = (bp_query_result == BP_RESULT_OK) && !!is_vbios_interop_enabled; - } - } - - if (dc->ctx->dce_environment == DCE_ENV_PRODUCTION_DRV) - dc->debug = debug_defaults_drv; - - // Init the vm_helper - if (dc->vm_helper) - vm_helper_init(dc->vm_helper, 16); - - /************************************************* - * Create resources * - *************************************************/ - - /* Clock Sources for Pixel Clock*/ - pool->base.clock_sources[DCN30_CLK_SRC_PLL0] = - dcn30_clock_source_create(ctx, ctx->dc_bios, - CLOCK_SOURCE_COMBO_PHY_PLL0, - &clk_src_regs[0], false); - pool->base.clock_sources[DCN30_CLK_SRC_PLL1] = - dcn30_clock_source_create(ctx, ctx->dc_bios, - CLOCK_SOURCE_COMBO_PHY_PLL1, - &clk_src_regs[1], false); - pool->base.clock_sources[DCN30_CLK_SRC_PLL2] = - dcn30_clock_source_create(ctx, ctx->dc_bios, - CLOCK_SOURCE_COMBO_PHY_PLL2, - &clk_src_regs[2], false); - pool->base.clock_sources[DCN30_CLK_SRC_PLL3] = - dcn30_clock_source_create(ctx, ctx->dc_bios, - CLOCK_SOURCE_COMBO_PHY_PLL3, - &clk_src_regs[3], false); - pool->base.clock_sources[DCN30_CLK_SRC_PLL4] = - dcn30_clock_source_create(ctx, ctx->dc_bios, - CLOCK_SOURCE_COMBO_PHY_PLL4, - &clk_src_regs[4], false); - pool->base.clock_sources[DCN30_CLK_SRC_PLL5] = - dcn30_clock_source_create(ctx, ctx->dc_bios, - CLOCK_SOURCE_COMBO_PHY_PLL5, - &clk_src_regs[5], false); - - pool->base.clk_src_count = DCN30_CLK_SRC_TOTAL; - - /* todo: not reuse phy_pll registers */ - pool->base.dp_clock_source = - dcn30_clock_source_create(ctx, ctx->dc_bios, - CLOCK_SOURCE_ID_DP_DTO, - &clk_src_regs[0], true); - - for (i = 0; i < pool->base.clk_src_count; i++) { - if (pool->base.clock_sources[i] == NULL) { - dm_error("DC: failed to create clock sources!\n"); - BREAK_TO_DEBUGGER(); - goto create_fail; - } - } - - /* DCCG */ - pool->base.dccg = dccg30_create(ctx, &dccg_regs, &dccg_shift, &dccg_mask); - if (pool->base.dccg == NULL) { - dm_error("DC: failed to create dccg!\n"); - BREAK_TO_DEBUGGER(); - goto create_fail; - } - - /* PP Lib and SMU interfaces */ - init_soc_bounding_box(dc, pool); - - num_pipes = dcn3_0_ip.max_num_dpp; - - for (i = 0; i < dcn3_0_ip.max_num_dpp; i++) - if (pipe_fuses & 1 << i) - num_pipes--; - - dcn3_0_ip.max_num_dpp = num_pipes; - dcn3_0_ip.max_num_otg = num_pipes; - - dml_init_instance(&dc->dml, &dcn3_0_soc, &dcn3_0_ip, DML_PROJECT_DCN30); - - /* IRQ */ - init_data.ctx = dc->ctx; - pool->base.irqs = dal_irq_service_dcn30_create(&init_data); - if (!pool->base.irqs) - goto create_fail; - - /* HUBBUB */ - pool->base.hubbub = dcn30_hubbub_create(ctx); - if (pool->base.hubbub == NULL) { - BREAK_TO_DEBUGGER(); - dm_error("DC: failed to create hubbub!\n"); - goto create_fail; - } - - /* HUBPs, DPPs, OPPs and TGs */ - for (i = 0; i < pool->base.pipe_count; i++) { - pool->base.hubps[i] = dcn30_hubp_create(ctx, i); - if (pool->base.hubps[i] == NULL) { - BREAK_TO_DEBUGGER(); - dm_error( - "DC: failed to create hubps!\n"); - goto create_fail; - } - - pool->base.dpps[i] = dcn30_dpp_create(ctx, i); - if (pool->base.dpps[i] == NULL) { - BREAK_TO_DEBUGGER(); - dm_error( - "DC: failed to create dpps!\n"); - goto create_fail; - } - } - - for (i = 0; i < pool->base.res_cap->num_opp; i++) { - pool->base.opps[i] = dcn30_opp_create(ctx, i); - if (pool->base.opps[i] == NULL) { - BREAK_TO_DEBUGGER(); - dm_error( - "DC: failed to create output pixel processor!\n"); - goto create_fail; - } - } - - for (i = 0; i < pool->base.res_cap->num_timing_generator; i++) { - pool->base.timing_generators[i] = dcn30_timing_generator_create( - ctx, i); - if (pool->base.timing_generators[i] == NULL) { - BREAK_TO_DEBUGGER(); - dm_error("DC: failed to create tg!\n"); - goto create_fail; - } - } - pool->base.timing_generator_count = i; - /* PSR */ - pool->base.psr = dmub_psr_create(ctx); - - if (pool->base.psr == NULL) { - dm_error("DC: failed to create PSR obj!\n"); - BREAK_TO_DEBUGGER(); - goto create_fail; - } - - /* ABM */ - for (i = 0; i < pool->base.res_cap->num_timing_generator; i++) { - pool->base.multiple_abms[i] = dmub_abm_create(ctx, - &abm_regs[i], - &abm_shift, - &abm_mask); - if (pool->base.multiple_abms[i] == NULL) { - dm_error("DC: failed to create abm for pipe %d!\n", i); - BREAK_TO_DEBUGGER(); - goto create_fail; - } - } - /* MPC and DSC */ - pool->base.mpc = dcn30_mpc_create(ctx, pool->base.mpcc_count, pool->base.res_cap->num_mpc_3dlut); - if (pool->base.mpc == NULL) { - BREAK_TO_DEBUGGER(); - dm_error("DC: failed to create mpc!\n"); - goto create_fail; - } - - for (i = 0; i < pool->base.res_cap->num_dsc; i++) { - pool->base.dscs[i] = dcn30_dsc_create(ctx, i); - if (pool->base.dscs[i] == NULL) { - BREAK_TO_DEBUGGER(); - dm_error("DC: failed to create display stream compressor %d!\n", i); - goto create_fail; - } - } - - /* DWB and MMHUBBUB */ - if (!dcn30_dwbc_create(ctx, &pool->base)) { - BREAK_TO_DEBUGGER(); - dm_error("DC: failed to create dwbc!\n"); - goto create_fail; - } - - if (!dcn30_mmhubbub_create(ctx, &pool->base)) { - BREAK_TO_DEBUGGER(); - dm_error("DC: failed to create mcif_wb!\n"); - goto create_fail; - } - - /* AUX and I2C */ - for (i = 0; i < pool->base.res_cap->num_ddc; i++) { - pool->base.engines[i] = dcn30_aux_engine_create(ctx, i); - if (pool->base.engines[i] == NULL) { - BREAK_TO_DEBUGGER(); - dm_error( - "DC:failed to create aux engine!!\n"); - goto create_fail; - } - pool->base.hw_i2cs[i] = dcn30_i2c_hw_create(ctx, i); - if (pool->base.hw_i2cs[i] == NULL) { - BREAK_TO_DEBUGGER(); - dm_error( - "DC:failed to create hw i2c!!\n"); - goto create_fail; - } - pool->base.sw_i2cs[i] = NULL; - } - - /* Audio, Stream Encoders including DIG and virtual, MPC 3D LUTs */ - if (!resource_construct(num_virtual_links, dc, &pool->base, - &res_create_funcs)) - goto create_fail; - - /* HW Sequencer and Plane caps */ - dcn30_hw_sequencer_construct(dc); - - dc->caps.max_planes = pool->base.pipe_count; - - for (i = 0; i < dc->caps.max_planes; ++i) - dc->caps.planes[i] = plane_cap; - - dc->cap_funcs = cap_funcs; - - if (dc->ctx->dc_bios->fw_info.oem_i2c_present) { - ddc_init_data.ctx = dc->ctx; - ddc_init_data.link = NULL; - ddc_init_data.id.id = dc->ctx->dc_bios->fw_info.oem_i2c_obj_id; - ddc_init_data.id.enum_id = 0; - ddc_init_data.id.type = OBJECT_TYPE_GENERIC; - pool->base.oem_device = dc->link_srv->create_ddc_service(&ddc_init_data); - } else { - pool->base.oem_device = NULL; - } - - DC_FP_END(); - - return true; - -create_fail: - - DC_FP_END(); - dcn30_resource_destruct(pool); - - return false; -} - -struct resource_pool *dcn30_create_resource_pool( - const struct dc_init_data *init_data, - struct dc *dc) -{ - struct dcn30_resource_pool *pool = - kzalloc(sizeof(struct dcn30_resource_pool), GFP_KERNEL); - - if (!pool) - return NULL; - - if (dcn30_resource_construct(init_data->num_virtual_links, dc, pool)) - return &pool->base; - - BREAK_TO_DEBUGGER(); - kfree(pool); - return NULL; -} diff --git a/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_resource.h b/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_resource.h deleted file mode 100644 index 8e6b8b7368fd..000000000000 --- a/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_resource.h +++ /dev/null @@ -1,108 +0,0 @@ -/* - * Copyright 2020 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 _DCN30_RESOURCE_H_ -#define _DCN30_RESOURCE_H_ - -#include "core_types.h" - -#define TO_DCN30_RES_POOL(pool)\ - container_of(pool, struct dcn30_resource_pool, base) - -struct dc; -struct resource_pool; -struct _vcs_dpi_display_pipe_params_st; - -extern struct _vcs_dpi_ip_params_st dcn3_0_ip; -extern struct _vcs_dpi_soc_bounding_box_st dcn3_0_soc; - -struct dcn30_resource_pool { - struct resource_pool base; -}; -struct resource_pool *dcn30_create_resource_pool( - const struct dc_init_data *init_data, - struct dc *dc); - -void dcn30_set_mcif_arb_params( - struct dc *dc, - struct dc_state *context, - display_e2e_pipe_params_st *pipes, - int pipe_cnt); - -unsigned int dcn30_calc_max_scaled_time( - unsigned int time_per_pixel, - enum mmhubbub_wbif_mode mode, - unsigned int urgent_watermark); - -bool dcn30_validate_bandwidth(struct dc *dc, struct dc_state *context, - bool fast_validate); -bool dcn30_internal_validate_bw( - struct dc *dc, - struct dc_state *context, - display_e2e_pipe_params_st *pipes, - int *pipe_cnt_out, - int *vlevel_out, - bool fast_validate, - bool allow_self_refresh_only); -void dcn30_calculate_wm_and_dlg( - struct dc *dc, struct dc_state *context, - display_e2e_pipe_params_st *pipes, - int pipe_cnt, - int vlevel); -void dcn30_update_soc_for_wm_a(struct dc *dc, struct dc_state *context); -void dcn30_populate_dml_writeback_from_context( - struct dc *dc, struct resource_context *res_ctx, display_e2e_pipe_params_st *pipes); - -int dcn30_populate_dml_pipes_from_context( - struct dc *dc, struct dc_state *context, - display_e2e_pipe_params_st *pipes, - bool fast_validate); - -bool dcn30_acquire_post_bldn_3dlut( - struct resource_context *res_ctx, - const struct resource_pool *pool, - int mpcc_id, - struct dc_3dlut **lut, - struct dc_transfer_func **shaper); - -bool dcn30_release_post_bldn_3dlut( - struct resource_context *res_ctx, - const struct resource_pool *pool, - struct dc_3dlut **lut, - struct dc_transfer_func **shaper); - -enum dc_status dcn30_add_stream_to_ctx( - struct dc *dc, - struct dc_state *new_ctx, - struct dc_stream_state *dc_stream); - -void dcn30_update_bw_bounding_box(struct dc *dc, struct clk_bw_params *bw_params); - -bool dcn30_can_support_mclk_switch_using_fw_based_vblank_stretch(struct dc *dc, struct dc_state *context); -void dcn30_setup_mclk_switch_using_fw_based_vblank_stretch(struct dc *dc, struct dc_state *context); -int dcn30_find_dummy_latency_index_for_fw_based_mclk_switch(struct dc *dc, struct dc_state *context, - display_e2e_pipe_params_st *pipes, int pipe_cnt, int vlevel); - -#endif /* _DCN30_RESOURCE_H_ */ diff --git a/drivers/gpu/drm/amd/display/dc/dcn301/Makefile b/drivers/gpu/drm/amd/display/dc/dcn301/Makefile index 30fbc5e06dca..cbf59d7e78c4 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn301/Makefile +++ b/drivers/gpu/drm/amd/display/dc/dcn301/Makefile @@ -10,7 +10,7 @@ # # Makefile for dcn30. -DCN301 = dcn301_init.o dcn301_resource.o dcn301_dccg.o \ +DCN301 = dcn301_init.o dcn301_dccg.o \ dcn301_dio_link_encoder.o dcn301_panel_cntl.o dcn301_hubbub.o \ dcn301_optc.o diff --git a/drivers/gpu/drm/amd/display/dc/dcn301/dcn301_resource.c b/drivers/gpu/drm/amd/display/dc/dcn301/dcn301_resource.c deleted file mode 100644 index f3b75f283aa2..000000000000 --- a/drivers/gpu/drm/amd/display/dc/dcn301/dcn301_resource.c +++ /dev/null @@ -1,1728 +0,0 @@ -/* - * Copyright 2019-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 "dm_services.h" -#include "dc.h" - -#include "dcn301_init.h" - -#include "resource.h" -#include "include/irq_service_interface.h" -#include "dcn30/dcn30_resource.h" -#include "dcn301_resource.h" - -#include "dcn20/dcn20_resource.h" - -#include "dcn10/dcn10_ipp.h" -#include "dcn301/dcn301_hubbub.h" -#include "dcn30/dcn30_mpc.h" -#include "dcn30/dcn30_hubp.h" -#include "irq/dcn30/irq_service_dcn30.h" -#include "dcn30/dcn30_dpp.h" -#include "dcn301/dcn301_optc.h" -#include "dcn20/dcn20_hwseq.h" -#include "dcn30/dcn30_hwseq.h" -#include "dce110/dce110_hwseq.h" -#include "dcn30/dcn30_opp.h" -#include "dcn20/dcn20_dsc.h" -#include "dcn30/dcn30_vpg.h" -#include "dcn30/dcn30_afmt.h" -#include "dce/dce_clock_source.h" -#include "dce/dce_audio.h" -#include "dce/dce_hwseq.h" -#include "clk_mgr.h" -#include "virtual/virtual_stream_encoder.h" -#include "dce110/dce110_resource.h" -#include "dml/display_mode_vba.h" -#include "dcn301/dcn301_dccg.h" -#include "dcn10/dcn10_resource.h" -#include "dcn30/dcn30_dio_stream_encoder.h" -#include "dcn301/dcn301_dio_link_encoder.h" -#include "dcn301_panel_cntl.h" - -#include "vangogh_ip_offset.h" - -#include "dcn30/dcn30_dwb.h" -#include "dcn30/dcn30_mmhubbub.h" - -#include "dcn/dcn_3_0_1_offset.h" -#include "dcn/dcn_3_0_1_sh_mask.h" - -#include "nbio/nbio_7_2_0_offset.h" - -#include "dpcs/dpcs_3_0_0_offset.h" -#include "dpcs/dpcs_3_0_0_sh_mask.h" - -#include "reg_helper.h" -#include "dce/dmub_abm.h" -#include "dce/dce_aux.h" -#include "dce/dce_i2c.h" - -#include "dml/dcn30/dcn30_fpu.h" - -#include "dml/dcn30/display_mode_vba_30.h" -#include "dml/dcn301/dcn301_fpu.h" -#include "vm_helper.h" -#include "dcn20/dcn20_vmid.h" -#include "amdgpu_socbb.h" - -#define TO_DCN301_RES_POOL(pool)\ - container_of(pool, struct dcn301_resource_pool, base) - -#define DC_LOGGER \ - dc->ctx->logger -#define DC_LOGGER_INIT(logger) - -enum dcn301_clk_src_array_id { - DCN301_CLK_SRC_PLL0, - DCN301_CLK_SRC_PLL1, - DCN301_CLK_SRC_PLL2, - DCN301_CLK_SRC_PLL3, - DCN301_CLK_SRC_TOTAL -}; - -/* begin ********************* - * macros to expend register list macro defined in HW object header file - */ - -/* DCN */ -#define BASE_INNER(seg) DCN_BASE__INST0_SEG ## seg - -#define BASE(seg) BASE_INNER(seg) - -#define SR(reg_name)\ - .reg_name = BASE(mm ## reg_name ## _BASE_IDX) + \ - mm ## reg_name - -#define SRI(reg_name, block, id)\ - .reg_name = BASE(mm ## block ## id ## _ ## reg_name ## _BASE_IDX) + \ - mm ## block ## id ## _ ## reg_name - -#define SRI2(reg_name, block, id)\ - .reg_name = BASE(mm ## reg_name ## _BASE_IDX) + \ - mm ## reg_name - -#define SRIR(var_name, reg_name, block, id)\ - .var_name = BASE(mm ## block ## id ## _ ## reg_name ## _BASE_IDX) + \ - mm ## block ## id ## _ ## reg_name - -#define SRII(reg_name, block, id)\ - .reg_name[id] = BASE(mm ## block ## id ## _ ## reg_name ## _BASE_IDX) + \ - mm ## block ## id ## _ ## reg_name - -#define SRII2(reg_name_pre, reg_name_post, id)\ - .reg_name_pre ## _ ## reg_name_post[id] = BASE(mm ## reg_name_pre \ - ## id ## _ ## reg_name_post ## _BASE_IDX) + \ - mm ## reg_name_pre ## id ## _ ## reg_name_post - -#define SRII_MPC_RMU(reg_name, block, id)\ - .RMU##_##reg_name[id] = BASE(mm ## block ## id ## _ ## reg_name ## _BASE_IDX) + \ - mm ## block ## id ## _ ## reg_name - -#define SRII_DWB(reg_name, temp_name, block, id)\ - .reg_name[id] = BASE(mm ## block ## id ## _ ## temp_name ## _BASE_IDX) + \ - mm ## block ## id ## _ ## temp_name - -#define SF_DWB2(reg_name, block, id, field_name, post_fix) \ - .field_name = reg_name ## __ ## field_name ## post_fix - -#define DCCG_SRII(reg_name, block, id)\ - .block ## _ ## reg_name[id] = BASE(mm ## block ## id ## _ ## reg_name ## _BASE_IDX) + \ - mm ## block ## id ## _ ## reg_name - -#define VUPDATE_SRII(reg_name, block, id)\ - .reg_name[id] = BASE(mm ## reg_name ## _ ## block ## id ## _BASE_IDX) + \ - mm ## reg_name ## _ ## block ## id - -/* NBIO */ -#define NBIO_BASE_INNER(seg) \ - NBIO_BASE__INST0_SEG ## seg - -#define NBIO_BASE(seg) \ - NBIO_BASE_INNER(seg) - -#define NBIO_SR(reg_name)\ - .reg_name = NBIO_BASE(regBIF_BX0_ ## reg_name ## _BASE_IDX) + \ - regBIF_BX0_ ## reg_name - -/* MMHUB */ -#define MMHUB_BASE_INNER(seg) \ - MMHUB_BASE__INST0_SEG ## seg - -#define MMHUB_BASE(seg) \ - MMHUB_BASE_INNER(seg) - -#define MMHUB_SR(reg_name)\ - .reg_name = MMHUB_BASE(regMM ## reg_name ## _BASE_IDX) + \ - regMM ## reg_name - -/* CLOCK */ -#define CLK_BASE_INNER(seg) \ - CLK_BASE__INST0_SEG ## seg - -#define CLK_BASE(seg) \ - CLK_BASE_INNER(seg) - -#define CLK_SRI(reg_name, block, inst)\ - .reg_name = CLK_BASE(mm ## block ## _ ## inst ## _ ## reg_name ## _BASE_IDX) + \ - mm ## block ## _ ## inst ## _ ## reg_name - -static const struct bios_registers bios_regs = { - NBIO_SR(BIOS_SCRATCH_3), - NBIO_SR(BIOS_SCRATCH_6) -}; - -#define clk_src_regs(index, pllid)\ -[index] = {\ - CS_COMMON_REG_LIST_DCN3_01(index, pllid),\ -} - -static const struct dce110_clk_src_regs clk_src_regs[] = { - clk_src_regs(0, A), - clk_src_regs(1, B), - clk_src_regs(2, C), - clk_src_regs(3, D) -}; - -static const struct dce110_clk_src_shift cs_shift = { - CS_COMMON_MASK_SH_LIST_DCN2_0(__SHIFT) -}; - -static const struct dce110_clk_src_mask cs_mask = { - CS_COMMON_MASK_SH_LIST_DCN2_0(_MASK) -}; - -#define abm_regs(id)\ -[id] = {\ - ABM_DCN301_REG_LIST(id)\ -} - -static const struct dce_abm_registers abm_regs[] = { - abm_regs(0), - abm_regs(1), - abm_regs(2), - abm_regs(3), -}; - -static const struct dce_abm_shift abm_shift = { - ABM_MASK_SH_LIST_DCN30(__SHIFT) -}; - -static const struct dce_abm_mask abm_mask = { - ABM_MASK_SH_LIST_DCN30(_MASK) -}; - -#define audio_regs(id)\ -[id] = {\ - AUD_COMMON_REG_LIST(id)\ -} - -static const struct dce_audio_registers audio_regs[] = { - audio_regs(0), - audio_regs(1), - audio_regs(2), - audio_regs(3), - audio_regs(4), - audio_regs(5), - audio_regs(6) -}; - -#define DCE120_AUD_COMMON_MASK_SH_LIST(mask_sh)\ - SF(AZF0ENDPOINT0_AZALIA_F0_CODEC_ENDPOINT_INDEX, AZALIA_ENDPOINT_REG_INDEX, mask_sh),\ - SF(AZF0ENDPOINT0_AZALIA_F0_CODEC_ENDPOINT_DATA, AZALIA_ENDPOINT_REG_DATA, mask_sh),\ - AUD_COMMON_MASK_SH_LIST_BASE(mask_sh) - -static const struct dce_audio_shift audio_shift = { - DCE120_AUD_COMMON_MASK_SH_LIST(__SHIFT) -}; - -static const struct dce_audio_mask audio_mask = { - DCE120_AUD_COMMON_MASK_SH_LIST(_MASK) -}; - -#define vpg_regs(id)\ -[id] = {\ - VPG_DCN3_REG_LIST(id)\ -} - -static const struct dcn30_vpg_registers vpg_regs[] = { - vpg_regs(0), - vpg_regs(1), - vpg_regs(2), - vpg_regs(3), -}; - -static const struct dcn30_vpg_shift vpg_shift = { - DCN3_VPG_MASK_SH_LIST(__SHIFT) -}; - -static const struct dcn30_vpg_mask vpg_mask = { - DCN3_VPG_MASK_SH_LIST(_MASK) -}; - -#define afmt_regs(id)\ -[id] = {\ - AFMT_DCN3_REG_LIST(id)\ -} - -static const struct dcn30_afmt_registers afmt_regs[] = { - afmt_regs(0), - afmt_regs(1), - afmt_regs(2), - afmt_regs(3), -}; - -static const struct dcn30_afmt_shift afmt_shift = { - DCN3_AFMT_MASK_SH_LIST(__SHIFT) -}; - -static const struct dcn30_afmt_mask afmt_mask = { - DCN3_AFMT_MASK_SH_LIST(_MASK) -}; - -#define stream_enc_regs(id)\ -[id] = {\ - SE_DCN3_REG_LIST(id)\ -} - -static const struct dcn10_stream_enc_registers stream_enc_regs[] = { - stream_enc_regs(0), - stream_enc_regs(1), - stream_enc_regs(2), - stream_enc_regs(3), -}; - -static const struct dcn10_stream_encoder_shift se_shift = { - SE_COMMON_MASK_SH_LIST_DCN30(__SHIFT) -}; - -static const struct dcn10_stream_encoder_mask se_mask = { - SE_COMMON_MASK_SH_LIST_DCN30(_MASK) -}; - - -#define aux_regs(id)\ -[id] = {\ - DCN2_AUX_REG_LIST(id)\ -} - -static const struct dcn10_link_enc_aux_registers link_enc_aux_regs[] = { - aux_regs(0), - aux_regs(1), - aux_regs(2), - aux_regs(3), -}; - -#define hpd_regs(id)\ -[id] = {\ - HPD_REG_LIST(id)\ -} - -static const struct dcn10_link_enc_hpd_registers link_enc_hpd_regs[] = { - hpd_regs(0), - hpd_regs(1), - hpd_regs(2), - hpd_regs(3), -}; - - -#define link_regs(id, phyid)\ -[id] = {\ - LE_DCN301_REG_LIST(id), \ - UNIPHY_DCN2_REG_LIST(phyid), \ - DPCS_DCN2_REG_LIST(id), \ - SRI(DP_DPHY_INTERNAL_CTRL, DP, id) \ -} - -static const struct dce110_aux_registers_shift aux_shift = { - DCN_AUX_MASK_SH_LIST(__SHIFT) -}; - -static const struct dce110_aux_registers_mask aux_mask = { - DCN_AUX_MASK_SH_LIST(_MASK) -}; - -static const struct dcn10_link_enc_registers link_enc_regs[] = { - link_regs(0, A), - link_regs(1, B), - link_regs(2, C), - link_regs(3, D), -}; - -static const struct dcn10_link_enc_shift le_shift = { - LINK_ENCODER_MASK_SH_LIST_DCN301(__SHIFT),\ - DPCS_DCN2_MASK_SH_LIST(__SHIFT) -}; - -static const struct dcn10_link_enc_mask le_mask = { - LINK_ENCODER_MASK_SH_LIST_DCN301(_MASK),\ - DPCS_DCN2_MASK_SH_LIST(_MASK) -}; - -#define panel_cntl_regs(id)\ -[id] = {\ - DCN301_PANEL_CNTL_REG_LIST(id),\ -} - -static const struct dce_panel_cntl_registers panel_cntl_regs[] = { - panel_cntl_regs(0), - panel_cntl_regs(1), -}; - -static const struct dcn301_panel_cntl_shift panel_cntl_shift = { - DCN301_PANEL_CNTL_MASK_SH_LIST(__SHIFT) -}; - -static const struct dcn301_panel_cntl_mask panel_cntl_mask = { - DCN301_PANEL_CNTL_MASK_SH_LIST(_MASK) -}; - -#define dpp_regs(id)\ -[id] = {\ - DPP_REG_LIST_DCN30(id),\ -} - -static const struct dcn3_dpp_registers dpp_regs[] = { - dpp_regs(0), - dpp_regs(1), - dpp_regs(2), - dpp_regs(3), -}; - -static const struct dcn3_dpp_shift tf_shift = { - DPP_REG_LIST_SH_MASK_DCN30(__SHIFT) -}; - -static const struct dcn3_dpp_mask tf_mask = { - DPP_REG_LIST_SH_MASK_DCN30(_MASK) -}; - -#define opp_regs(id)\ -[id] = {\ - OPP_REG_LIST_DCN30(id),\ -} - -static const struct dcn20_opp_registers opp_regs[] = { - opp_regs(0), - opp_regs(1), - opp_regs(2), - opp_regs(3), -}; - -static const struct dcn20_opp_shift opp_shift = { - OPP_MASK_SH_LIST_DCN20(__SHIFT) -}; - -static const struct dcn20_opp_mask opp_mask = { - OPP_MASK_SH_LIST_DCN20(_MASK) -}; - -#define aux_engine_regs(id)\ -[id] = {\ - AUX_COMMON_REG_LIST0(id), \ - .AUXN_IMPCAL = 0, \ - .AUXP_IMPCAL = 0, \ - .AUX_RESET_MASK = DP_AUX0_AUX_CONTROL__AUX_RESET_MASK, \ -} - -static const struct dce110_aux_registers aux_engine_regs[] = { - aux_engine_regs(0), - aux_engine_regs(1), - aux_engine_regs(2), - aux_engine_regs(3), -}; - -#define dwbc_regs_dcn3(id)\ -[id] = {\ - DWBC_COMMON_REG_LIST_DCN30(id),\ -} - -static const struct dcn30_dwbc_registers dwbc30_regs[] = { - dwbc_regs_dcn3(0), -}; - -static const struct dcn30_dwbc_shift dwbc30_shift = { - DWBC_COMMON_MASK_SH_LIST_DCN30(__SHIFT) -}; - -static const struct dcn30_dwbc_mask dwbc30_mask = { - DWBC_COMMON_MASK_SH_LIST_DCN30(_MASK) -}; - -#define mcif_wb_regs_dcn3(id)\ -[id] = {\ - MCIF_WB_COMMON_REG_LIST_DCN30(id),\ -} - -static const struct dcn30_mmhubbub_registers mcif_wb30_regs[] = { - mcif_wb_regs_dcn3(0) -}; - -static const struct dcn30_mmhubbub_shift mcif_wb30_shift = { - MCIF_WB_COMMON_MASK_SH_LIST_DCN30(__SHIFT) -}; - -static const struct dcn30_mmhubbub_mask mcif_wb30_mask = { - MCIF_WB_COMMON_MASK_SH_LIST_DCN30(_MASK) -}; - -#define dsc_regsDCN20(id)\ -[id] = {\ - DSC_REG_LIST_DCN20(id)\ -} - -static const struct dcn20_dsc_registers dsc_regs[] = { - dsc_regsDCN20(0), - dsc_regsDCN20(1), - dsc_regsDCN20(2), -}; - -static const struct dcn20_dsc_shift dsc_shift = { - DSC_REG_LIST_SH_MASK_DCN20(__SHIFT) -}; - -static const struct dcn20_dsc_mask dsc_mask = { - DSC_REG_LIST_SH_MASK_DCN20(_MASK) -}; - -static const struct dcn30_mpc_registers mpc_regs = { - MPC_REG_LIST_DCN3_0(0), - MPC_REG_LIST_DCN3_0(1), - MPC_REG_LIST_DCN3_0(2), - MPC_REG_LIST_DCN3_0(3), - MPC_OUT_MUX_REG_LIST_DCN3_0(0), - MPC_OUT_MUX_REG_LIST_DCN3_0(1), - MPC_OUT_MUX_REG_LIST_DCN3_0(2), - MPC_OUT_MUX_REG_LIST_DCN3_0(3), - MPC_RMU_GLOBAL_REG_LIST_DCN3AG, - MPC_RMU_REG_LIST_DCN3AG(0), - MPC_RMU_REG_LIST_DCN3AG(1), - MPC_DWB_MUX_REG_LIST_DCN3_0(0), -}; - -static const struct dcn30_mpc_shift mpc_shift = { - MPC_COMMON_MASK_SH_LIST_DCN30(__SHIFT) -}; - -static const struct dcn30_mpc_mask mpc_mask = { - MPC_COMMON_MASK_SH_LIST_DCN30(_MASK) -}; - -#define optc_regs(id)\ -[id] = {OPTC_COMMON_REG_LIST_DCN3_0(id)} - - -static const struct dcn_optc_registers optc_regs[] = { - optc_regs(0), - optc_regs(1), - optc_regs(2), - optc_regs(3), -}; - -static const struct dcn_optc_shift optc_shift = { - OPTC_COMMON_MASK_SH_LIST_DCN30(__SHIFT) -}; - -static const struct dcn_optc_mask optc_mask = { - OPTC_COMMON_MASK_SH_LIST_DCN30(_MASK) -}; - -#define hubp_regs(id)\ -[id] = {\ - HUBP_REG_LIST_DCN30(id)\ -} - -static const struct dcn_hubp2_registers hubp_regs[] = { - hubp_regs(0), - hubp_regs(1), - hubp_regs(2), - hubp_regs(3), -}; - -static const struct dcn_hubp2_shift hubp_shift = { - HUBP_MASK_SH_LIST_DCN30(__SHIFT) -}; - -static const struct dcn_hubp2_mask hubp_mask = { - HUBP_MASK_SH_LIST_DCN30(_MASK) -}; - -static const struct dcn_hubbub_registers hubbub_reg = { - HUBBUB_REG_LIST_DCN301(0) -}; - -static const struct dcn_hubbub_shift hubbub_shift = { - HUBBUB_MASK_SH_LIST_DCN301(__SHIFT) -}; - -static const struct dcn_hubbub_mask hubbub_mask = { - HUBBUB_MASK_SH_LIST_DCN301(_MASK) -}; - -static const struct dccg_registers dccg_regs = { - DCCG_REG_LIST_DCN301() -}; - -static const struct dccg_shift dccg_shift = { - DCCG_MASK_SH_LIST_DCN301(__SHIFT) -}; - -static const struct dccg_mask dccg_mask = { - DCCG_MASK_SH_LIST_DCN301(_MASK) -}; - -static const struct dce_hwseq_registers hwseq_reg = { - HWSEQ_DCN301_REG_LIST() -}; - -static const struct dce_hwseq_shift hwseq_shift = { - HWSEQ_DCN301_MASK_SH_LIST(__SHIFT) -}; - -static const struct dce_hwseq_mask hwseq_mask = { - HWSEQ_DCN301_MASK_SH_LIST(_MASK) -}; -#define vmid_regs(id)\ -[id] = {\ - DCN20_VMID_REG_LIST(id)\ -} - -static const struct dcn_vmid_registers vmid_regs[] = { - vmid_regs(0), - vmid_regs(1), - vmid_regs(2), - vmid_regs(3), - vmid_regs(4), - vmid_regs(5), - vmid_regs(6), - vmid_regs(7), - vmid_regs(8), - vmid_regs(9), - vmid_regs(10), - vmid_regs(11), - vmid_regs(12), - vmid_regs(13), - vmid_regs(14), - vmid_regs(15) -}; - -static const struct dcn20_vmid_shift vmid_shifts = { - DCN20_VMID_MASK_SH_LIST(__SHIFT) -}; - -static const struct dcn20_vmid_mask vmid_masks = { - DCN20_VMID_MASK_SH_LIST(_MASK) -}; - -static struct resource_caps res_cap_dcn301 = { - .num_timing_generator = 4, - .num_opp = 4, - .num_video_plane = 4, - .num_audio = 4, - .num_stream_encoder = 4, - .num_pll = 4, - .num_dwb = 1, - .num_ddc = 4, - .num_vmid = 16, - .num_mpc_3dlut = 2, - .num_dsc = 3, -}; - -static const struct dc_plane_cap plane_cap = { - .type = DC_PLANE_TYPE_DCN_UNIVERSAL, - .per_pixel_alpha = true, - - .pixel_format_support = { - .argb8888 = true, - .nv12 = true, - .fp16 = true, - .p010 = true, - .ayuv = false, - }, - - .max_upscale_factor = { - .argb8888 = 16000, - .nv12 = 16000, - .fp16 = 16000 - }, - - /* 6:1 downscaling ratio: 1000/6 = 166.666 */ - .max_downscale_factor = { - .argb8888 = 167, - .nv12 = 167, - .fp16 = 167 - }, - 64, - 64 -}; - -static const struct dc_debug_options debug_defaults_drv = { - .disable_dmcu = true, - .force_abm_enable = false, - .timing_trace = false, - .clock_trace = true, - .disable_dpp_power_gate = false, - .disable_hubp_power_gate = false, - .disable_clock_gate = true, - .disable_pplib_clock_request = true, - .disable_pplib_wm_range = true, - .pipe_split_policy = MPC_SPLIT_DYNAMIC, - .force_single_disp_pipe_split = false, - .disable_dcc = DCC_ENABLE, - .vsr_support = true, - .performance_trace = false, - .max_downscale_src_width = 7680,/*upto 8K*/ - .scl_reset_length10 = true, - .sanity_checks = false, - .underflow_assert_delay_us = 0xFFFFFFFF, - .dwb_fi_phase = -1, // -1 = disable - .dmub_command_table = true, - .use_max_lb = false, - .exit_idle_opt_for_cursor_updates = true, - .using_dml2 = false, -}; - -static void dcn301_dpp_destroy(struct dpp **dpp) -{ - kfree(TO_DCN20_DPP(*dpp)); - *dpp = NULL; -} - -static struct dpp *dcn301_dpp_create(struct dc_context *ctx, uint32_t inst) -{ - struct dcn3_dpp *dpp = - kzalloc(sizeof(struct dcn3_dpp), GFP_KERNEL); - - if (!dpp) - return NULL; - - if (dpp3_construct(dpp, ctx, inst, - &dpp_regs[inst], &tf_shift, &tf_mask)) - return &dpp->base; - - BREAK_TO_DEBUGGER(); - kfree(dpp); - return NULL; -} -static struct output_pixel_processor *dcn301_opp_create(struct dc_context *ctx, - uint32_t inst) -{ - struct dcn20_opp *opp = - kzalloc(sizeof(struct dcn20_opp), GFP_KERNEL); - - if (!opp) { - BREAK_TO_DEBUGGER(); - return NULL; - } - - dcn20_opp_construct(opp, ctx, inst, - &opp_regs[inst], &opp_shift, &opp_mask); - return &opp->base; -} - -static struct dce_aux *dcn301_aux_engine_create(struct dc_context *ctx, uint32_t inst) -{ - struct aux_engine_dce110 *aux_engine = - kzalloc(sizeof(struct aux_engine_dce110), GFP_KERNEL); - - if (!aux_engine) - return NULL; - - dce110_aux_engine_construct(aux_engine, ctx, inst, - SW_AUX_TIMEOUT_PERIOD_MULTIPLIER * AUX_TIMEOUT_PERIOD, - &aux_engine_regs[inst], - &aux_mask, - &aux_shift, - ctx->dc->caps.extended_aux_timeout_support); - - return &aux_engine->base; -} -#define i2c_inst_regs(id) { I2C_HW_ENGINE_COMMON_REG_LIST(id) } - -static const struct dce_i2c_registers i2c_hw_regs[] = { - i2c_inst_regs(1), - i2c_inst_regs(2), - i2c_inst_regs(3), - i2c_inst_regs(4), -}; - -static const struct dce_i2c_shift i2c_shifts = { - I2C_COMMON_MASK_SH_LIST_DCN2(__SHIFT) -}; - -static const struct dce_i2c_mask i2c_masks = { - I2C_COMMON_MASK_SH_LIST_DCN2(_MASK) -}; - -static struct dce_i2c_hw *dcn301_i2c_hw_create(struct dc_context *ctx, uint32_t inst) -{ - struct dce_i2c_hw *dce_i2c_hw = - kzalloc(sizeof(struct dce_i2c_hw), GFP_KERNEL); - - if (!dce_i2c_hw) - return NULL; - - dcn2_i2c_hw_construct(dce_i2c_hw, ctx, inst, - &i2c_hw_regs[inst], &i2c_shifts, &i2c_masks); - - return dce_i2c_hw; -} -static struct mpc *dcn301_mpc_create( - struct dc_context *ctx, - int num_mpcc, - int num_rmu) -{ - struct dcn30_mpc *mpc30 = kzalloc(sizeof(struct dcn30_mpc), - GFP_KERNEL); - - if (!mpc30) - return NULL; - - dcn30_mpc_construct(mpc30, ctx, - &mpc_regs, - &mpc_shift, - &mpc_mask, - num_mpcc, - num_rmu); - - return &mpc30->base; -} - -static struct hubbub *dcn301_hubbub_create(struct dc_context *ctx) -{ - int i; - - struct dcn20_hubbub *hubbub3 = kzalloc(sizeof(struct dcn20_hubbub), - GFP_KERNEL); - - if (!hubbub3) - return NULL; - - hubbub301_construct(hubbub3, ctx, - &hubbub_reg, - &hubbub_shift, - &hubbub_mask); - - - for (i = 0; i < res_cap_dcn301.num_vmid; i++) { - struct dcn20_vmid *vmid = &hubbub3->vmid[i]; - - vmid->ctx = ctx; - - vmid->regs = &vmid_regs[i]; - vmid->shifts = &vmid_shifts; - vmid->masks = &vmid_masks; - } - - hubbub3->num_vmid = res_cap_dcn301.num_vmid; - - return &hubbub3->base; -} - -static struct timing_generator *dcn301_timing_generator_create( - struct dc_context *ctx, uint32_t instance) -{ - struct optc *tgn10 = - kzalloc(sizeof(struct optc), GFP_KERNEL); - - if (!tgn10) - return NULL; - - tgn10->base.inst = instance; - tgn10->base.ctx = ctx; - - tgn10->tg_regs = &optc_regs[instance]; - tgn10->tg_shift = &optc_shift; - tgn10->tg_mask = &optc_mask; - - dcn301_timing_generator_init(tgn10); - - return &tgn10->base; -} - -static const struct encoder_feature_support link_enc_feature = { - .max_hdmi_deep_color = COLOR_DEPTH_121212, - .max_hdmi_pixel_clock = 600000, - .hdmi_ycbcr420_supported = true, - .dp_ycbcr420_supported = true, - .fec_supported = true, - .flags.bits.IS_HBR2_CAPABLE = true, - .flags.bits.IS_HBR3_CAPABLE = true, - .flags.bits.IS_TPS3_CAPABLE = true, - .flags.bits.IS_TPS4_CAPABLE = true -}; - -static struct link_encoder *dcn301_link_encoder_create( - struct dc_context *ctx, - const struct encoder_init_data *enc_init_data) -{ - struct dcn20_link_encoder *enc20 = - kzalloc(sizeof(struct dcn20_link_encoder), GFP_KERNEL); - - if (!enc20) - return NULL; - - dcn301_link_encoder_construct(enc20, - enc_init_data, - &link_enc_feature, - &link_enc_regs[enc_init_data->transmitter], - &link_enc_aux_regs[enc_init_data->channel - 1], - &link_enc_hpd_regs[enc_init_data->hpd_source], - &le_shift, - &le_mask); - - return &enc20->enc10.base; -} - -static struct panel_cntl *dcn301_panel_cntl_create(const struct panel_cntl_init_data *init_data) -{ - struct dcn301_panel_cntl *panel_cntl = - kzalloc(sizeof(struct dcn301_panel_cntl), GFP_KERNEL); - - if (!panel_cntl) - return NULL; - - dcn301_panel_cntl_construct(panel_cntl, - init_data, - &panel_cntl_regs[init_data->inst], - &panel_cntl_shift, - &panel_cntl_mask); - - return &panel_cntl->base; -} - - -#define CTX ctx - -#define REG(reg_name) \ - (DCN_BASE.instance[0].segment[mm ## reg_name ## _BASE_IDX] + mm ## reg_name) - -static uint32_t read_pipe_fuses(struct dc_context *ctx) -{ - uint32_t value = REG_READ(CC_DC_PIPE_DIS); - /* RV1 support max 4 pipes */ - value = value & 0xf; - return value; -} - - -static void read_dce_straps( - struct dc_context *ctx, - struct resource_straps *straps) -{ - generic_reg_get(ctx, mmDC_PINSTRAPS + BASE(mmDC_PINSTRAPS_BASE_IDX), - FN(DC_PINSTRAPS, DC_PINSTRAPS_AUDIO), &straps->dc_pinstraps_audio); - -} - -static struct audio *dcn301_create_audio( - struct dc_context *ctx, unsigned int inst) -{ - return dce_audio_create(ctx, inst, - &audio_regs[inst], &audio_shift, &audio_mask); -} - -static struct vpg *dcn301_vpg_create( - struct dc_context *ctx, - uint32_t inst) -{ - struct dcn30_vpg *vpg3 = kzalloc(sizeof(struct dcn30_vpg), GFP_KERNEL); - - if (!vpg3) - return NULL; - - vpg3_construct(vpg3, ctx, inst, - &vpg_regs[inst], - &vpg_shift, - &vpg_mask); - - return &vpg3->base; -} - -static struct afmt *dcn301_afmt_create( - struct dc_context *ctx, - uint32_t inst) -{ - struct dcn30_afmt *afmt3 = kzalloc(sizeof(struct dcn30_afmt), GFP_KERNEL); - - if (!afmt3) - return NULL; - - afmt3_construct(afmt3, ctx, inst, - &afmt_regs[inst], - &afmt_shift, - &afmt_mask); - - return &afmt3->base; -} - -static struct stream_encoder *dcn301_stream_encoder_create(enum engine_id eng_id, - struct dc_context *ctx) -{ - struct dcn10_stream_encoder *enc1; - struct vpg *vpg; - struct afmt *afmt; - int vpg_inst; - int afmt_inst; - - /* Mapping of VPG, AFMT, DME register blocks to DIO block instance */ - if (eng_id <= ENGINE_ID_DIGF) { - vpg_inst = eng_id; - afmt_inst = eng_id; - } else - return NULL; - - enc1 = kzalloc(sizeof(struct dcn10_stream_encoder), GFP_KERNEL); - vpg = dcn301_vpg_create(ctx, vpg_inst); - afmt = dcn301_afmt_create(ctx, afmt_inst); - - if (!enc1 || !vpg || !afmt) { - kfree(enc1); - kfree(vpg); - kfree(afmt); - return NULL; - } - - dcn30_dio_stream_encoder_construct(enc1, ctx, ctx->dc_bios, - eng_id, vpg, afmt, - &stream_enc_regs[eng_id], - &se_shift, &se_mask); - - return &enc1->base; -} - -static struct dce_hwseq *dcn301_hwseq_create(struct dc_context *ctx) -{ - struct dce_hwseq *hws = kzalloc(sizeof(struct dce_hwseq), GFP_KERNEL); - - if (hws) { - hws->ctx = ctx; - hws->regs = &hwseq_reg; - hws->shifts = &hwseq_shift; - hws->masks = &hwseq_mask; - } - return hws; -} -static const struct resource_create_funcs res_create_funcs = { - .read_dce_straps = read_dce_straps, - .create_audio = dcn301_create_audio, - .create_stream_encoder = dcn301_stream_encoder_create, - .create_hwseq = dcn301_hwseq_create, -}; - -static void dcn301_destruct(struct dcn301_resource_pool *pool) -{ - unsigned int i; - - for (i = 0; i < pool->base.stream_enc_count; i++) { - if (pool->base.stream_enc[i] != NULL) { - if (pool->base.stream_enc[i]->vpg != NULL) { - kfree(DCN30_VPG_FROM_VPG(pool->base.stream_enc[i]->vpg)); - pool->base.stream_enc[i]->vpg = NULL; - } - if (pool->base.stream_enc[i]->afmt != NULL) { - kfree(DCN30_AFMT_FROM_AFMT(pool->base.stream_enc[i]->afmt)); - pool->base.stream_enc[i]->afmt = NULL; - } - kfree(DCN10STRENC_FROM_STRENC(pool->base.stream_enc[i])); - pool->base.stream_enc[i] = NULL; - } - } - - for (i = 0; i < pool->base.res_cap->num_dsc; i++) { - if (pool->base.dscs[i] != NULL) - dcn20_dsc_destroy(&pool->base.dscs[i]); - } - - if (pool->base.mpc != NULL) { - kfree(TO_DCN20_MPC(pool->base.mpc)); - pool->base.mpc = NULL; - } - if (pool->base.hubbub != NULL) { - kfree(pool->base.hubbub); - pool->base.hubbub = NULL; - } - for (i = 0; i < pool->base.pipe_count; i++) { - if (pool->base.dpps[i] != NULL) - dcn301_dpp_destroy(&pool->base.dpps[i]); - - if (pool->base.ipps[i] != NULL) - pool->base.ipps[i]->funcs->ipp_destroy(&pool->base.ipps[i]); - - if (pool->base.hubps[i] != NULL) { - kfree(TO_DCN20_HUBP(pool->base.hubps[i])); - pool->base.hubps[i] = NULL; - } - - if (pool->base.irqs != NULL) { - dal_irq_service_destroy(&pool->base.irqs); - } - } - - for (i = 0; i < pool->base.res_cap->num_ddc; i++) { - if (pool->base.engines[i] != NULL) - dce110_engine_destroy(&pool->base.engines[i]); - if (pool->base.hw_i2cs[i] != NULL) { - kfree(pool->base.hw_i2cs[i]); - pool->base.hw_i2cs[i] = NULL; - } - if (pool->base.sw_i2cs[i] != NULL) { - kfree(pool->base.sw_i2cs[i]); - pool->base.sw_i2cs[i] = NULL; - } - } - - for (i = 0; i < pool->base.res_cap->num_opp; i++) { - if (pool->base.opps[i] != NULL) - pool->base.opps[i]->funcs->opp_destroy(&pool->base.opps[i]); - } - - for (i = 0; i < pool->base.res_cap->num_timing_generator; i++) { - if (pool->base.timing_generators[i] != NULL) { - kfree(DCN10TG_FROM_TG(pool->base.timing_generators[i])); - pool->base.timing_generators[i] = NULL; - } - } - - for (i = 0; i < pool->base.res_cap->num_dwb; i++) { - if (pool->base.dwbc[i] != NULL) { - kfree(TO_DCN30_DWBC(pool->base.dwbc[i])); - pool->base.dwbc[i] = NULL; - } - if (pool->base.mcif_wb[i] != NULL) { - kfree(TO_DCN30_MMHUBBUB(pool->base.mcif_wb[i])); - pool->base.mcif_wb[i] = NULL; - } - } - - for (i = 0; i < pool->base.audio_count; i++) { - if (pool->base.audios[i]) - dce_aud_destroy(&pool->base.audios[i]); - } - - for (i = 0; i < pool->base.clk_src_count; i++) { - if (pool->base.clock_sources[i] != NULL) { - dcn20_clock_source_destroy(&pool->base.clock_sources[i]); - pool->base.clock_sources[i] = NULL; - } - } - - for (i = 0; i < pool->base.res_cap->num_mpc_3dlut; i++) { - if (pool->base.mpc_lut[i] != NULL) { - dc_3dlut_func_release(pool->base.mpc_lut[i]); - pool->base.mpc_lut[i] = NULL; - } - if (pool->base.mpc_shaper[i] != NULL) { - dc_transfer_func_release(pool->base.mpc_shaper[i]); - pool->base.mpc_shaper[i] = NULL; - } - } - - if (pool->base.dp_clock_source != NULL) { - dcn20_clock_source_destroy(&pool->base.dp_clock_source); - pool->base.dp_clock_source = NULL; - } - - for (i = 0; i < pool->base.res_cap->num_timing_generator; i++) { - if (pool->base.multiple_abms[i] != NULL) - dce_abm_destroy(&pool->base.multiple_abms[i]); - } - - if (pool->base.dccg != NULL) - dcn_dccg_destroy(&pool->base.dccg); -} - -static struct hubp *dcn301_hubp_create(struct dc_context *ctx, uint32_t inst) -{ - struct dcn20_hubp *hubp2 = - kzalloc(sizeof(struct dcn20_hubp), GFP_KERNEL); - - if (!hubp2) - return NULL; - - if (hubp3_construct(hubp2, ctx, inst, - &hubp_regs[inst], &hubp_shift, &hubp_mask)) - return &hubp2->base; - - BREAK_TO_DEBUGGER(); - kfree(hubp2); - return NULL; -} - -static bool dcn301_dwbc_create(struct dc_context *ctx, struct resource_pool *pool) -{ - int i; - uint32_t pipe_count = pool->res_cap->num_dwb; - - for (i = 0; i < pipe_count; i++) { - struct dcn30_dwbc *dwbc30 = kzalloc(sizeof(struct dcn30_dwbc), - GFP_KERNEL); - - if (!dwbc30) { - dm_error("DC: failed to create dwbc30!\n"); - return false; - } - - dcn30_dwbc_construct(dwbc30, ctx, - &dwbc30_regs[i], - &dwbc30_shift, - &dwbc30_mask, - i); - - pool->dwbc[i] = &dwbc30->base; - } - return true; -} - -static bool dcn301_mmhubbub_create(struct dc_context *ctx, struct resource_pool *pool) -{ - int i; - uint32_t pipe_count = pool->res_cap->num_dwb; - - for (i = 0; i < pipe_count; i++) { - struct dcn30_mmhubbub *mcif_wb30 = kzalloc(sizeof(struct dcn30_mmhubbub), - GFP_KERNEL); - - if (!mcif_wb30) { - dm_error("DC: failed to create mcif_wb30!\n"); - return false; - } - - dcn30_mmhubbub_construct(mcif_wb30, ctx, - &mcif_wb30_regs[i], - &mcif_wb30_shift, - &mcif_wb30_mask, - i); - - pool->mcif_wb[i] = &mcif_wb30->base; - } - return true; -} - -static struct display_stream_compressor *dcn301_dsc_create( - struct dc_context *ctx, uint32_t inst) -{ - struct dcn20_dsc *dsc = - kzalloc(sizeof(struct dcn20_dsc), GFP_KERNEL); - - if (!dsc) { - BREAK_TO_DEBUGGER(); - return NULL; - } - - dsc2_construct(dsc, ctx, inst, &dsc_regs[inst], &dsc_shift, &dsc_mask); - return &dsc->base; -} - - -static void dcn301_destroy_resource_pool(struct resource_pool **pool) -{ - struct dcn301_resource_pool *dcn301_pool = TO_DCN301_RES_POOL(*pool); - - dcn301_destruct(dcn301_pool); - kfree(dcn301_pool); - *pool = NULL; -} - -static struct clock_source *dcn301_clock_source_create( - struct dc_context *ctx, - struct dc_bios *bios, - enum clock_source_id id, - const struct dce110_clk_src_regs *regs, - bool dp_clk_src) -{ - struct dce110_clk_src *clk_src = - kzalloc(sizeof(struct dce110_clk_src), GFP_KERNEL); - - if (!clk_src) - return NULL; - - if (dcn301_clk_src_construct(clk_src, ctx, bios, id, - regs, &cs_shift, &cs_mask)) { - clk_src->base.dp_clk_src = dp_clk_src; - return &clk_src->base; - } - - kfree(clk_src); - BREAK_TO_DEBUGGER(); - return NULL; -} - -static struct dc_cap_funcs cap_funcs = { - .get_dcc_compression_cap = dcn20_get_dcc_compression_cap -}; - - -static bool is_soc_bounding_box_valid(struct dc *dc) -{ - uint32_t hw_internal_rev = dc->ctx->asic_id.hw_internal_rev; - - if (ASICREV_IS_VANGOGH(hw_internal_rev)) - return true; - - return false; -} - -static bool init_soc_bounding_box(struct dc *dc, - struct dcn301_resource_pool *pool) -{ - 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 (!is_soc_bounding_box_valid(dc)) { - DC_LOG_ERROR("%s: not valid soc bounding box\n", __func__); - return false; - } - - loaded_ip->max_num_otg = pool->base.res_cap->num_timing_generator; - loaded_ip->max_num_dpp = pool->base.pipe_count; - DC_FP_START(); - dcn20_patch_bounding_box(dc, loaded_bb); - DC_FP_END(); - - 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) { - DC_FP_START(); - dcn301_fpu_init_soc_bounding_box(bb_info); - DC_FP_END(); - } - } - - return true; -} - - -static void set_wm_ranges( - struct pp_smu_funcs *pp_smu, - struct _vcs_dpi_soc_bounding_box_st *loaded_bb) -{ - struct pp_smu_wm_range_sets ranges = {0}; - int i; - - ranges.num_reader_wm_sets = 0; - - if (loaded_bb->num_states == 1) { - ranges.reader_wm_sets[0].wm_inst = 0; - ranges.reader_wm_sets[0].min_drain_clk_mhz = PP_SMU_WM_SET_RANGE_CLK_UNCONSTRAINED_MIN; - ranges.reader_wm_sets[0].max_drain_clk_mhz = PP_SMU_WM_SET_RANGE_CLK_UNCONSTRAINED_MAX; - ranges.reader_wm_sets[0].min_fill_clk_mhz = PP_SMU_WM_SET_RANGE_CLK_UNCONSTRAINED_MIN; - ranges.reader_wm_sets[0].max_fill_clk_mhz = PP_SMU_WM_SET_RANGE_CLK_UNCONSTRAINED_MAX; - - ranges.num_reader_wm_sets = 1; - } else if (loaded_bb->num_states > 1) { - for (i = 0; i < 4 && i < loaded_bb->num_states; i++) { - ranges.reader_wm_sets[i].wm_inst = i; - ranges.reader_wm_sets[i].min_drain_clk_mhz = PP_SMU_WM_SET_RANGE_CLK_UNCONSTRAINED_MIN; - ranges.reader_wm_sets[i].max_drain_clk_mhz = PP_SMU_WM_SET_RANGE_CLK_UNCONSTRAINED_MAX; - DC_FP_START(); - dcn301_fpu_set_wm_ranges(i, &ranges, loaded_bb); - DC_FP_END(); - ranges.num_reader_wm_sets = i + 1; - } - - ranges.reader_wm_sets[0].min_fill_clk_mhz = PP_SMU_WM_SET_RANGE_CLK_UNCONSTRAINED_MIN; - ranges.reader_wm_sets[ranges.num_reader_wm_sets - 1].max_fill_clk_mhz = PP_SMU_WM_SET_RANGE_CLK_UNCONSTRAINED_MAX; - } - - ranges.num_writer_wm_sets = 1; - - ranges.writer_wm_sets[0].wm_inst = 0; - ranges.writer_wm_sets[0].min_fill_clk_mhz = PP_SMU_WM_SET_RANGE_CLK_UNCONSTRAINED_MIN; - ranges.writer_wm_sets[0].max_fill_clk_mhz = PP_SMU_WM_SET_RANGE_CLK_UNCONSTRAINED_MAX; - ranges.writer_wm_sets[0].min_drain_clk_mhz = PP_SMU_WM_SET_RANGE_CLK_UNCONSTRAINED_MIN; - ranges.writer_wm_sets[0].max_drain_clk_mhz = PP_SMU_WM_SET_RANGE_CLK_UNCONSTRAINED_MAX; - - /* Notify PP Lib/SMU which Watermarks to use for which clock ranges */ - pp_smu->nv_funcs.set_wm_ranges(&pp_smu->nv_funcs.pp_smu, &ranges); -} - -static void dcn301_calculate_wm_and_dlg( - struct dc *dc, struct dc_state *context, - display_e2e_pipe_params_st *pipes, - int pipe_cnt, - int vlevel) -{ - DC_FP_START(); - dcn301_calculate_wm_and_dlg_fp(dc, context, pipes, pipe_cnt, vlevel); - DC_FP_END(); -} - -static struct resource_funcs dcn301_res_pool_funcs = { - .destroy = dcn301_destroy_resource_pool, - .link_enc_create = dcn301_link_encoder_create, - .panel_cntl_create = dcn301_panel_cntl_create, - .validate_bandwidth = dcn30_validate_bandwidth, - .calculate_wm_and_dlg = dcn301_calculate_wm_and_dlg, - .update_soc_for_wm_a = dcn30_update_soc_for_wm_a, - .populate_dml_pipes = dcn30_populate_dml_pipes_from_context, - .acquire_free_pipe_as_secondary_dpp_pipe = dcn20_acquire_free_pipe_for_layer, - .release_pipe = dcn20_release_pipe, - .add_stream_to_ctx = dcn30_add_stream_to_ctx, - .add_dsc_to_stream_resource = dcn20_add_dsc_to_stream_resource, - .remove_stream_from_ctx = dcn20_remove_stream_from_ctx, - .populate_dml_writeback_from_context = dcn30_populate_dml_writeback_from_context, - .set_mcif_arb_params = dcn30_set_mcif_arb_params, - .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 = dcn301_update_bw_bounding_box, - .patch_unknown_plane_state = dcn20_patch_unknown_plane_state -}; - -static bool dcn301_resource_construct( - uint8_t num_virtual_links, - struct dc *dc, - struct dcn301_resource_pool *pool) -{ - int i, j; - struct dc_context *ctx = dc->ctx; - struct irq_service_init_data init_data; - uint32_t pipe_fuses = read_pipe_fuses(ctx); - uint32_t num_pipes = 0; - - DC_LOGGER_INIT(dc->ctx->logger); - - ctx->dc_bios->regs = &bios_regs; - - if (dc->ctx->asic_id.chip_id == DEVICE_ID_VGH_1435) - res_cap_dcn301.num_pll = 2; - pool->base.res_cap = &res_cap_dcn301; - - pool->base.funcs = &dcn301_res_pool_funcs; - - /************************************************* - * Resource + asic cap harcoding * - *************************************************/ - pool->base.underlay_pipe_index = NO_UNDERLAY_PIPE; - pool->base.pipe_count = pool->base.res_cap->num_timing_generator; - pool->base.mpcc_count = pool->base.res_cap->num_timing_generator; - dc->caps.max_downscale_ratio = 600; - dc->caps.i2c_speed_in_khz = 100; - dc->caps.i2c_speed_in_khz_hdcp = 5; /*1.4 w/a enabled by default*/ - dc->caps.max_cursor_size = 256; - dc->caps.min_horizontal_blanking_period = 80; - dc->caps.dmdata_alloc_size = 2048; - dc->caps.max_slave_planes = 2; - dc->caps.max_slave_yuv_planes = 2; - dc->caps.max_slave_rgb_planes = 2; - dc->caps.is_apu = true; - dc->caps.post_blend_color_processing = true; - dc->caps.force_dp_tps4_for_cp2520 = true; - dc->caps.extended_aux_timeout_support = true; - dc->caps.dmcub_support = true; - - /* Color pipeline capabilities */ - dc->caps.color.dpp.dcn_arch = 1; - dc->caps.color.dpp.input_lut_shared = 0; - dc->caps.color.dpp.icsc = 1; - dc->caps.color.dpp.dgam_ram = 0; // must use gamma_corr - dc->caps.color.dpp.dgam_rom_caps.srgb = 1; - dc->caps.color.dpp.dgam_rom_caps.bt2020 = 1; - dc->caps.color.dpp.dgam_rom_caps.gamma2_2 = 1; - dc->caps.color.dpp.dgam_rom_caps.pq = 1; - dc->caps.color.dpp.dgam_rom_caps.hlg = 1; - dc->caps.color.dpp.post_csc = 1; - dc->caps.color.dpp.gamma_corr = 1; - dc->caps.color.dpp.dgam_rom_for_yuv = 0; - - dc->caps.color.dpp.hw_3d_lut = 1; - dc->caps.color.dpp.ogam_ram = 1; - // no OGAM ROM on DCN301 - dc->caps.color.dpp.ogam_rom_caps.srgb = 0; - dc->caps.color.dpp.ogam_rom_caps.bt2020 = 0; - dc->caps.color.dpp.ogam_rom_caps.gamma2_2 = 0; - dc->caps.color.dpp.ogam_rom_caps.pq = 0; - dc->caps.color.dpp.ogam_rom_caps.hlg = 0; - dc->caps.color.dpp.ocsc = 0; - - dc->caps.color.mpc.gamut_remap = 1; - dc->caps.color.mpc.num_3dluts = pool->base.res_cap->num_mpc_3dlut; //2 - dc->caps.color.mpc.ogam_ram = 1; - dc->caps.color.mpc.ogam_rom_caps.srgb = 0; - dc->caps.color.mpc.ogam_rom_caps.bt2020 = 0; - dc->caps.color.mpc.ogam_rom_caps.gamma2_2 = 0; - dc->caps.color.mpc.ogam_rom_caps.pq = 0; - dc->caps.color.mpc.ogam_rom_caps.hlg = 0; - dc->caps.color.mpc.ocsc = 1; - - dc->caps.dp_hdmi21_pcon_support = true; - - /* read VBIOS LTTPR caps */ - if (ctx->dc_bios->funcs->get_lttpr_caps) { - enum bp_result bp_query_result; - uint8_t is_vbios_lttpr_enable = 0; - - bp_query_result = ctx->dc_bios->funcs->get_lttpr_caps(ctx->dc_bios, &is_vbios_lttpr_enable); - dc->caps.vbios_lttpr_enable = (bp_query_result == BP_RESULT_OK) && !!is_vbios_lttpr_enable; - } - - if (ctx->dc_bios->funcs->get_lttpr_interop) { - enum bp_result bp_query_result; - uint8_t is_vbios_interop_enabled = 0; - - bp_query_result = ctx->dc_bios->funcs->get_lttpr_interop(ctx->dc_bios, &is_vbios_interop_enabled); - dc->caps.vbios_lttpr_aware = (bp_query_result == BP_RESULT_OK) && !!is_vbios_interop_enabled; - } - - if (dc->ctx->dce_environment == DCE_ENV_PRODUCTION_DRV) - dc->debug = debug_defaults_drv; - - // Init the vm_helper - if (dc->vm_helper) - vm_helper_init(dc->vm_helper, 16); - - /************************************************* - * Create resources * - *************************************************/ - - /* Clock Sources for Pixel Clock*/ - pool->base.clock_sources[DCN301_CLK_SRC_PLL0] = - dcn301_clock_source_create(ctx, ctx->dc_bios, - CLOCK_SOURCE_COMBO_PHY_PLL0, - &clk_src_regs[0], false); - pool->base.clock_sources[DCN301_CLK_SRC_PLL1] = - dcn301_clock_source_create(ctx, ctx->dc_bios, - CLOCK_SOURCE_COMBO_PHY_PLL1, - &clk_src_regs[1], false); - pool->base.clock_sources[DCN301_CLK_SRC_PLL2] = - dcn301_clock_source_create(ctx, ctx->dc_bios, - CLOCK_SOURCE_COMBO_PHY_PLL2, - &clk_src_regs[2], false); - pool->base.clock_sources[DCN301_CLK_SRC_PLL3] = - dcn301_clock_source_create(ctx, ctx->dc_bios, - CLOCK_SOURCE_COMBO_PHY_PLL3, - &clk_src_regs[3], false); - - pool->base.clk_src_count = DCN301_CLK_SRC_TOTAL; - - /* todo: not reuse phy_pll registers */ - pool->base.dp_clock_source = - dcn301_clock_source_create(ctx, ctx->dc_bios, - CLOCK_SOURCE_ID_DP_DTO, - &clk_src_regs[0], true); - - for (i = 0; i < pool->base.clk_src_count; i++) { - if (pool->base.clock_sources[i] == NULL) { - dm_error("DC: failed to create clock sources!\n"); - BREAK_TO_DEBUGGER(); - goto create_fail; - } - } - - /* DCCG */ - pool->base.dccg = dccg301_create(ctx, &dccg_regs, &dccg_shift, &dccg_mask); - if (pool->base.dccg == NULL) { - dm_error("DC: failed to create dccg!\n"); - BREAK_TO_DEBUGGER(); - goto create_fail; - } - - init_soc_bounding_box(dc, pool); - - if (!dc->debug.disable_pplib_wm_range && pool->base.pp_smu->nv_funcs.set_wm_ranges) - set_wm_ranges(pool->base.pp_smu, &dcn3_01_soc); - - num_pipes = dcn3_01_ip.max_num_dpp; - - for (i = 0; i < dcn3_01_ip.max_num_dpp; i++) - if (pipe_fuses & 1 << i) - num_pipes--; - dcn3_01_ip.max_num_dpp = num_pipes; - dcn3_01_ip.max_num_otg = num_pipes; - - - dml_init_instance(&dc->dml, &dcn3_01_soc, &dcn3_01_ip, DML_PROJECT_DCN30); - - /* IRQ */ - init_data.ctx = dc->ctx; - pool->base.irqs = dal_irq_service_dcn30_create(&init_data); - if (!pool->base.irqs) - goto create_fail; - - /* HUBBUB */ - pool->base.hubbub = dcn301_hubbub_create(ctx); - if (pool->base.hubbub == NULL) { - BREAK_TO_DEBUGGER(); - dm_error("DC: failed to create hubbub!\n"); - goto create_fail; - } - - j = 0; - /* HUBPs, DPPs, OPPs and TGs */ - for (i = 0; i < pool->base.pipe_count; i++) { - - /* if pipe is disabled, skip instance of HW pipe, - * i.e, skip ASIC register instance - */ - if ((pipe_fuses & (1 << i)) != 0) { - DC_LOG_DEBUG("%s: fusing pipe %d\n", __func__, i); - continue; - } - - pool->base.hubps[j] = dcn301_hubp_create(ctx, i); - if (pool->base.hubps[j] == NULL) { - BREAK_TO_DEBUGGER(); - dm_error( - "DC: failed to create hubps!\n"); - goto create_fail; - } - - pool->base.dpps[j] = dcn301_dpp_create(ctx, i); - if (pool->base.dpps[j] == NULL) { - BREAK_TO_DEBUGGER(); - dm_error( - "DC: failed to create dpps!\n"); - goto create_fail; - } - - pool->base.opps[j] = dcn301_opp_create(ctx, i); - if (pool->base.opps[j] == NULL) { - BREAK_TO_DEBUGGER(); - dm_error( - "DC: failed to create output pixel processor!\n"); - goto create_fail; - } - - pool->base.timing_generators[j] = dcn301_timing_generator_create(ctx, i); - if (pool->base.timing_generators[j] == NULL) { - BREAK_TO_DEBUGGER(); - dm_error("DC: failed to create tg!\n"); - goto create_fail; - } - j++; - } - pool->base.timing_generator_count = j; - pool->base.pipe_count = j; - pool->base.mpcc_count = j; - - /* ABM (or ABMs for NV2x) */ - /* TODO: */ - for (i = 0; i < pool->base.res_cap->num_timing_generator; i++) { - pool->base.multiple_abms[i] = dmub_abm_create(ctx, - &abm_regs[i], - &abm_shift, - &abm_mask); - if (pool->base.multiple_abms[i] == NULL) { - dm_error("DC: failed to create abm for pipe %d!\n", i); - BREAK_TO_DEBUGGER(); - goto create_fail; - } - } - - /* MPC and DSC */ - pool->base.mpc = dcn301_mpc_create(ctx, pool->base.mpcc_count, pool->base.res_cap->num_mpc_3dlut); - if (pool->base.mpc == NULL) { - BREAK_TO_DEBUGGER(); - dm_error("DC: failed to create mpc!\n"); - goto create_fail; - } - - for (i = 0; i < pool->base.res_cap->num_dsc; i++) { - pool->base.dscs[i] = dcn301_dsc_create(ctx, i); - if (pool->base.dscs[i] == NULL) { - BREAK_TO_DEBUGGER(); - dm_error("DC: failed to create display stream compressor %d!\n", i); - goto create_fail; - } - } - - /* DWB and MMHUBBUB */ - if (!dcn301_dwbc_create(ctx, &pool->base)) { - BREAK_TO_DEBUGGER(); - dm_error("DC: failed to create dwbc!\n"); - goto create_fail; - } - - if (!dcn301_mmhubbub_create(ctx, &pool->base)) { - BREAK_TO_DEBUGGER(); - dm_error("DC: failed to create mcif_wb!\n"); - goto create_fail; - } - - /* AUX and I2C */ - for (i = 0; i < pool->base.res_cap->num_ddc; i++) { - pool->base.engines[i] = dcn301_aux_engine_create(ctx, i); - if (pool->base.engines[i] == NULL) { - BREAK_TO_DEBUGGER(); - dm_error( - "DC:failed to create aux engine!!\n"); - goto create_fail; - } - pool->base.hw_i2cs[i] = dcn301_i2c_hw_create(ctx, i); - if (pool->base.hw_i2cs[i] == NULL) { - BREAK_TO_DEBUGGER(); - dm_error( - "DC:failed to create hw i2c!!\n"); - goto create_fail; - } - pool->base.sw_i2cs[i] = NULL; - } - - /* Audio, Stream Encoders including HPO and virtual, MPC 3D LUTs */ - if (!resource_construct(num_virtual_links, dc, &pool->base, - &res_create_funcs)) - goto create_fail; - - /* HW Sequencer and Plane caps */ - dcn301_hw_sequencer_construct(dc); - - dc->caps.max_planes = pool->base.pipe_count; - - for (i = 0; i < dc->caps.max_planes; ++i) - dc->caps.planes[i] = plane_cap; - - dc->cap_funcs = cap_funcs; - - return true; - -create_fail: - - dcn301_destruct(pool); - - return false; -} - -struct resource_pool *dcn301_create_resource_pool( - const struct dc_init_data *init_data, - struct dc *dc) -{ - struct dcn301_resource_pool *pool = - kzalloc(sizeof(struct dcn301_resource_pool), GFP_KERNEL); - - if (!pool) - return NULL; - - if (dcn301_resource_construct(init_data->num_virtual_links, dc, pool)) - return &pool->base; - - BREAK_TO_DEBUGGER(); - kfree(pool); - return NULL; -} diff --git a/drivers/gpu/drm/amd/display/dc/dcn301/dcn301_resource.h b/drivers/gpu/drm/amd/display/dc/dcn301/dcn301_resource.h deleted file mode 100644 index ae8672680cdd..000000000000 --- a/drivers/gpu/drm/amd/display/dc/dcn301/dcn301_resource.h +++ /dev/null @@ -1,45 +0,0 @@ -/* - * Copyright 2020 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 _DCN301_RESOURCE_H_ -#define _DCN301_RESOURCE_H_ - -#include "core_types.h" - -struct dc; -struct resource_pool; -struct _vcs_dpi_display_pipe_params_st; - -extern struct _vcs_dpi_ip_params_st dcn3_01_ip; -extern struct _vcs_dpi_soc_bounding_box_st dcn3_01_soc; - -struct dcn301_resource_pool { - struct resource_pool base; -}; -struct resource_pool *dcn301_create_resource_pool( - const struct dc_init_data *init_data, - struct dc *dc); - -#endif /* _DCN301_RESOURCE_H_ */ diff --git a/drivers/gpu/drm/amd/display/dc/dcn302/Makefile b/drivers/gpu/drm/amd/display/dc/dcn302/Makefile index 95b66baf39e9..0fcd03569d74 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn302/Makefile +++ b/drivers/gpu/drm/amd/display/dc/dcn302/Makefile @@ -5,7 +5,7 @@ # # Makefile for dcn302. -DCN3_02 = dcn302_init.o dcn302_resource.o +DCN3_02 = dcn302_init.o AMD_DAL_DCN3_02 = $(addprefix $(AMDDALPATH)/dc/dcn302/,$(DCN3_02)) diff --git a/drivers/gpu/drm/amd/display/dc/dcn302/dcn302_resource.c b/drivers/gpu/drm/amd/display/dc/dcn302/dcn302_resource.c deleted file mode 100644 index 63ac984a04f7..000000000000 --- a/drivers/gpu/drm/amd/display/dc/dcn302/dcn302_resource.c +++ /dev/null @@ -1,1518 +0,0 @@ -/* - * Copyright 2020 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 "dcn302_init.h" -#include "dcn302_resource.h" -#include "dcn302_dccg.h" -#include "irq/dcn302/irq_service_dcn302.h" - -#include "dcn30/dcn30_dio_link_encoder.h" -#include "dcn30/dcn30_dio_stream_encoder.h" -#include "dcn30/dcn30_dwb.h" -#include "dcn30/dcn30_dpp.h" -#include "dcn30/dcn30_hubbub.h" -#include "dcn30/dcn30_hubp.h" -#include "dcn30/dcn30_mmhubbub.h" -#include "dcn30/dcn30_mpc.h" -#include "dcn30/dcn30_opp.h" -#include "dcn30/dcn30_optc.h" -#include "dcn30/dcn30_resource.h" - -#include "dcn20/dcn20_dsc.h" -#include "dcn20/dcn20_resource.h" - -#include "dml/dcn30/dcn30_fpu.h" - -#include "dcn10/dcn10_resource.h" - -#include "link.h" -#include "dce/dce_abm.h" -#include "dce/dce_audio.h" -#include "dce/dce_aux.h" -#include "dce/dce_clock_source.h" -#include "dce/dce_hwseq.h" -#include "dce/dce_i2c_hw.h" -#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" -#include "resource.h" -#include "vm_helper.h" - -#include "dml/dcn302/dcn302_fpu.h" - -#include "dimgrey_cavefish_ip_offset.h" -#include "dcn/dcn_3_0_2_offset.h" -#include "dcn/dcn_3_0_2_sh_mask.h" -#include "dpcs/dpcs_3_0_0_offset.h" -#include "dpcs/dpcs_3_0_0_sh_mask.h" -#include "nbio/nbio_7_4_offset.h" -#include "amdgpu_socbb.h" - -#define DC_LOGGER \ - dc->ctx->logger -#define DC_LOGGER_INIT(logger) - -static const struct dc_debug_options debug_defaults_drv = { - .disable_dmcu = true, - .force_abm_enable = false, - .timing_trace = false, - .clock_trace = true, - .disable_pplib_clock_request = true, - .pipe_split_policy = MPC_SPLIT_DYNAMIC, - .force_single_disp_pipe_split = false, - .disable_dcc = DCC_ENABLE, - .vsr_support = true, - .performance_trace = false, - .max_downscale_src_width = 7680,/*upto 8K*/ - .disable_pplib_wm_range = false, - .scl_reset_length10 = true, - .sanity_checks = false, - .underflow_assert_delay_us = 0xFFFFFFFF, - .dwb_fi_phase = -1, // -1 = disable, - .dmub_command_table = true, - .use_max_lb = true, - .exit_idle_opt_for_cursor_updates = true, - .enable_legacy_fast_update = false, - .using_dml2 = false, -}; - -static const struct dc_panel_config panel_config_defaults = { - .psr = { - .disable_psr = false, - .disallow_psrsu = false, - .disallow_replay = false, - }, -}; - -enum dcn302_clk_src_array_id { - DCN302_CLK_SRC_PLL0, - DCN302_CLK_SRC_PLL1, - DCN302_CLK_SRC_PLL2, - DCN302_CLK_SRC_PLL3, - DCN302_CLK_SRC_PLL4, - DCN302_CLK_SRC_TOTAL -}; - -static const struct resource_caps res_cap_dcn302 = { - .num_timing_generator = 5, - .num_opp = 5, - .num_video_plane = 5, - .num_audio = 5, - .num_stream_encoder = 5, - .num_dwb = 1, - .num_ddc = 5, - .num_vmid = 16, - .num_mpc_3dlut = 2, - .num_dsc = 5, -}; - -static const struct dc_plane_cap plane_cap = { - .type = DC_PLANE_TYPE_DCN_UNIVERSAL, - .per_pixel_alpha = true, - .pixel_format_support = { - .argb8888 = true, - .nv12 = true, - .fp16 = true, - .p010 = true, - .ayuv = false, - }, - .max_upscale_factor = { - .argb8888 = 16000, - .nv12 = 16000, - .fp16 = 16000 - }, - /* 6:1 downscaling ratio: 1000/6 = 166.666 */ - .max_downscale_factor = { - .argb8888 = 167, - .nv12 = 167, - .fp16 = 167 - }, - 16, - 16 -}; - -/* NBIO */ -#define NBIO_BASE_INNER(seg) \ - NBIO_BASE__INST0_SEG ## seg - -#define NBIO_BASE(seg) \ - NBIO_BASE_INNER(seg) - -#define NBIO_SR(reg_name)\ - .reg_name = NBIO_BASE(mm ## reg_name ## _BASE_IDX) + \ - mm ## reg_name - -/* DCN */ -#define BASE_INNER(seg) DCN_BASE__INST0_SEG ## seg - -#define BASE(seg) BASE_INNER(seg) - -#define SR(reg_name)\ - .reg_name = BASE(mm ## reg_name ## _BASE_IDX) + mm ## reg_name - -#define SF(reg_name, field_name, post_fix)\ - .field_name = reg_name ## __ ## field_name ## post_fix - -#define SRI(reg_name, block, id)\ - .reg_name = BASE(mm ## block ## id ## _ ## reg_name ## _BASE_IDX) + mm ## block ## id ## _ ## reg_name - -#define SRI2(reg_name, block, id)\ - .reg_name = BASE(mm ## reg_name ## _BASE_IDX) + mm ## reg_name - -#define SRII(reg_name, block, id)\ - .reg_name[id] = BASE(mm ## block ## id ## _ ## reg_name ## _BASE_IDX) + \ - mm ## block ## id ## _ ## reg_name - -#define DCCG_SRII(reg_name, block, id)\ - .block ## _ ## reg_name[id] = BASE(mm ## block ## id ## _ ## reg_name ## _BASE_IDX) + \ - mm ## block ## id ## _ ## reg_name - -#define VUPDATE_SRII(reg_name, block, id)\ - .reg_name[id] = BASE(mm ## reg_name ## _ ## block ## id ## _BASE_IDX) + \ - mm ## reg_name ## _ ## block ## id - -#define SRII_DWB(reg_name, temp_name, block, id)\ - .reg_name[id] = BASE(mm ## block ## id ## _ ## temp_name ## _BASE_IDX) + \ - mm ## block ## id ## _ ## temp_name - -#define SF_DWB2(reg_name, block, id, field_name, post_fix) \ - .field_name = reg_name ## __ ## field_name ## post_fix - -#define SRII_MPC_RMU(reg_name, block, id)\ - .RMU##_##reg_name[id] = BASE(mm ## block ## id ## _ ## reg_name ## _BASE_IDX) + \ - mm ## block ## id ## _ ## reg_name - -static const struct dcn_hubbub_registers hubbub_reg = { - HUBBUB_REG_LIST_DCN30(0) -}; - -static const struct dcn_hubbub_shift hubbub_shift = { - HUBBUB_MASK_SH_LIST_DCN30(__SHIFT) -}; - -static const struct dcn_hubbub_mask hubbub_mask = { - HUBBUB_MASK_SH_LIST_DCN30(_MASK) -}; - -#define vmid_regs(id)\ - [id] = { DCN20_VMID_REG_LIST(id) } - -static const struct dcn_vmid_registers vmid_regs[] = { - vmid_regs(0), - vmid_regs(1), - vmid_regs(2), - vmid_regs(3), - vmid_regs(4), - vmid_regs(5), - vmid_regs(6), - vmid_regs(7), - vmid_regs(8), - vmid_regs(9), - vmid_regs(10), - vmid_regs(11), - vmid_regs(12), - vmid_regs(13), - vmid_regs(14), - vmid_regs(15) -}; - -static const struct dcn20_vmid_shift vmid_shifts = { - DCN20_VMID_MASK_SH_LIST(__SHIFT) -}; - -static const struct dcn20_vmid_mask vmid_masks = { - DCN20_VMID_MASK_SH_LIST(_MASK) -}; - -static struct hubbub *dcn302_hubbub_create(struct dc_context *ctx) -{ - int i; - - struct dcn20_hubbub *hubbub3 = kzalloc(sizeof(struct dcn20_hubbub), GFP_KERNEL); - - if (!hubbub3) - return NULL; - - hubbub3_construct(hubbub3, ctx, &hubbub_reg, &hubbub_shift, &hubbub_mask); - - for (i = 0; i < res_cap_dcn302.num_vmid; i++) { - struct dcn20_vmid *vmid = &hubbub3->vmid[i]; - - vmid->ctx = ctx; - - vmid->regs = &vmid_regs[i]; - vmid->shifts = &vmid_shifts; - vmid->masks = &vmid_masks; - } - - return &hubbub3->base; -} - -#define vpg_regs(id)\ - [id] = { VPG_DCN3_REG_LIST(id) } - -static const struct dcn30_vpg_registers vpg_regs[] = { - vpg_regs(0), - vpg_regs(1), - vpg_regs(2), - vpg_regs(3), - vpg_regs(4), - vpg_regs(5) -}; - -static const struct dcn30_vpg_shift vpg_shift = { - DCN3_VPG_MASK_SH_LIST(__SHIFT) -}; - -static const struct dcn30_vpg_mask vpg_mask = { - DCN3_VPG_MASK_SH_LIST(_MASK) -}; - -static struct vpg *dcn302_vpg_create(struct dc_context *ctx, uint32_t inst) -{ - struct dcn30_vpg *vpg3 = kzalloc(sizeof(struct dcn30_vpg), GFP_KERNEL); - - if (!vpg3) - return NULL; - - vpg3_construct(vpg3, ctx, inst, &vpg_regs[inst], &vpg_shift, &vpg_mask); - - return &vpg3->base; -} - -#define afmt_regs(id)\ - [id] = { AFMT_DCN3_REG_LIST(id) } - -static const struct dcn30_afmt_registers afmt_regs[] = { - afmt_regs(0), - afmt_regs(1), - afmt_regs(2), - afmt_regs(3), - afmt_regs(4), - afmt_regs(5) -}; - -static const struct dcn30_afmt_shift afmt_shift = { - DCN3_AFMT_MASK_SH_LIST(__SHIFT) -}; - -static const struct dcn30_afmt_mask afmt_mask = { - DCN3_AFMT_MASK_SH_LIST(_MASK) -}; - -static struct afmt *dcn302_afmt_create(struct dc_context *ctx, uint32_t inst) -{ - struct dcn30_afmt *afmt3 = kzalloc(sizeof(struct dcn30_afmt), GFP_KERNEL); - - if (!afmt3) - return NULL; - - afmt3_construct(afmt3, ctx, inst, &afmt_regs[inst], &afmt_shift, &afmt_mask); - - return &afmt3->base; -} - -#define audio_regs(id)\ - [id] = { AUD_COMMON_REG_LIST(id) } - -static const struct dce_audio_registers audio_regs[] = { - audio_regs(0), - audio_regs(1), - audio_regs(2), - audio_regs(3), - audio_regs(4), - audio_regs(5), - audio_regs(6) -}; - -#define DCE120_AUD_COMMON_MASK_SH_LIST(mask_sh)\ - SF(AZF0ENDPOINT0_AZALIA_F0_CODEC_ENDPOINT_INDEX, AZALIA_ENDPOINT_REG_INDEX, mask_sh),\ - SF(AZF0ENDPOINT0_AZALIA_F0_CODEC_ENDPOINT_DATA, AZALIA_ENDPOINT_REG_DATA, mask_sh),\ - AUD_COMMON_MASK_SH_LIST_BASE(mask_sh) - -static const struct dce_audio_shift audio_shift = { - DCE120_AUD_COMMON_MASK_SH_LIST(__SHIFT) -}; - -static const struct dce_audio_mask audio_mask = { - DCE120_AUD_COMMON_MASK_SH_LIST(_MASK) -}; - -static struct audio *dcn302_create_audio(struct dc_context *ctx, unsigned int inst) -{ - return dce_audio_create(ctx, inst, &audio_regs[inst], &audio_shift, &audio_mask); -} - -#define stream_enc_regs(id)\ - [id] = { SE_DCN3_REG_LIST(id) } - -static const struct dcn10_stream_enc_registers stream_enc_regs[] = { - stream_enc_regs(0), - stream_enc_regs(1), - stream_enc_regs(2), - stream_enc_regs(3), - stream_enc_regs(4) -}; - -static const struct dcn10_stream_encoder_shift se_shift = { - SE_COMMON_MASK_SH_LIST_DCN30(__SHIFT) -}; - -static const struct dcn10_stream_encoder_mask se_mask = { - SE_COMMON_MASK_SH_LIST_DCN30(_MASK) -}; - -static struct stream_encoder *dcn302_stream_encoder_create(enum engine_id eng_id, struct dc_context *ctx) -{ - struct dcn10_stream_encoder *enc1; - struct vpg *vpg; - struct afmt *afmt; - int vpg_inst; - int afmt_inst; - - /* Mapping of VPG, AFMT, DME register blocks to DIO block instance */ - if (eng_id <= ENGINE_ID_DIGE) { - vpg_inst = eng_id; - afmt_inst = eng_id; - } else - return NULL; - - enc1 = kzalloc(sizeof(struct dcn10_stream_encoder), GFP_KERNEL); - vpg = dcn302_vpg_create(ctx, vpg_inst); - afmt = dcn302_afmt_create(ctx, afmt_inst); - - if (!enc1 || !vpg || !afmt) { - kfree(enc1); - kfree(vpg); - kfree(afmt); - return NULL; - } - - dcn30_dio_stream_encoder_construct(enc1, ctx, ctx->dc_bios, eng_id, vpg, afmt, &stream_enc_regs[eng_id], - &se_shift, &se_mask); - - return &enc1->base; -} - -#define clk_src_regs(index, pllid)\ - [index] = { CS_COMMON_REG_LIST_DCN3_02(index, pllid) } - -static const struct dce110_clk_src_regs clk_src_regs[] = { - clk_src_regs(0, A), - clk_src_regs(1, B), - clk_src_regs(2, C), - clk_src_regs(3, D), - clk_src_regs(4, E) -}; - -static const struct dce110_clk_src_shift cs_shift = { - CS_COMMON_MASK_SH_LIST_DCN2_0(__SHIFT) -}; - -static const struct dce110_clk_src_mask cs_mask = { - CS_COMMON_MASK_SH_LIST_DCN2_0(_MASK) -}; - -static struct clock_source *dcn302_clock_source_create(struct dc_context *ctx, struct dc_bios *bios, - enum clock_source_id id, const struct dce110_clk_src_regs *regs, bool dp_clk_src) -{ - struct dce110_clk_src *clk_src = kzalloc(sizeof(struct dce110_clk_src), GFP_KERNEL); - - if (!clk_src) - return NULL; - - if (dcn3_clk_src_construct(clk_src, ctx, bios, id, regs, &cs_shift, &cs_mask)) { - clk_src->base.dp_clk_src = dp_clk_src; - return &clk_src->base; - } - - kfree(clk_src); - BREAK_TO_DEBUGGER(); - return NULL; -} - -static const struct dce_hwseq_registers hwseq_reg = { - HWSEQ_DCN302_REG_LIST() -}; - -static const struct dce_hwseq_shift hwseq_shift = { - HWSEQ_DCN302_MASK_SH_LIST(__SHIFT) -}; - -static const struct dce_hwseq_mask hwseq_mask = { - HWSEQ_DCN302_MASK_SH_LIST(_MASK) -}; - -static struct dce_hwseq *dcn302_hwseq_create(struct dc_context *ctx) -{ - struct dce_hwseq *hws = kzalloc(sizeof(struct dce_hwseq), GFP_KERNEL); - - if (hws) { - hws->ctx = ctx; - hws->regs = &hwseq_reg; - hws->shifts = &hwseq_shift; - hws->masks = &hwseq_mask; - } - return hws; -} - -#define hubp_regs(id)\ - [id] = { HUBP_REG_LIST_DCN30(id) } - -static const struct dcn_hubp2_registers hubp_regs[] = { - hubp_regs(0), - hubp_regs(1), - hubp_regs(2), - hubp_regs(3), - hubp_regs(4) -}; - -static const struct dcn_hubp2_shift hubp_shift = { - HUBP_MASK_SH_LIST_DCN30(__SHIFT) -}; - -static const struct dcn_hubp2_mask hubp_mask = { - HUBP_MASK_SH_LIST_DCN30(_MASK) -}; - -static struct hubp *dcn302_hubp_create(struct dc_context *ctx, uint32_t inst) -{ - struct dcn20_hubp *hubp2 = kzalloc(sizeof(struct dcn20_hubp), GFP_KERNEL); - - if (!hubp2) - return NULL; - - if (hubp3_construct(hubp2, ctx, inst, &hubp_regs[inst], &hubp_shift, &hubp_mask)) - return &hubp2->base; - - BREAK_TO_DEBUGGER(); - kfree(hubp2); - return NULL; -} - -#define dpp_regs(id)\ - [id] = { DPP_REG_LIST_DCN30(id) } - -static const struct dcn3_dpp_registers dpp_regs[] = { - dpp_regs(0), - dpp_regs(1), - dpp_regs(2), - dpp_regs(3), - dpp_regs(4) -}; - -static const struct dcn3_dpp_shift tf_shift = { - DPP_REG_LIST_SH_MASK_DCN30(__SHIFT) -}; - -static const struct dcn3_dpp_mask tf_mask = { - DPP_REG_LIST_SH_MASK_DCN30(_MASK) -}; - -static struct dpp *dcn302_dpp_create(struct dc_context *ctx, uint32_t inst) -{ - struct dcn3_dpp *dpp = kzalloc(sizeof(struct dcn3_dpp), GFP_KERNEL); - - if (!dpp) - return NULL; - - if (dpp3_construct(dpp, ctx, inst, &dpp_regs[inst], &tf_shift, &tf_mask)) - return &dpp->base; - - BREAK_TO_DEBUGGER(); - kfree(dpp); - return NULL; -} - -#define opp_regs(id)\ - [id] = { OPP_REG_LIST_DCN30(id) } - -static const struct dcn20_opp_registers opp_regs[] = { - opp_regs(0), - opp_regs(1), - opp_regs(2), - opp_regs(3), - opp_regs(4) -}; - -static const struct dcn20_opp_shift opp_shift = { - OPP_MASK_SH_LIST_DCN20(__SHIFT) -}; - -static const struct dcn20_opp_mask opp_mask = { - OPP_MASK_SH_LIST_DCN20(_MASK) -}; - -static struct output_pixel_processor *dcn302_opp_create(struct dc_context *ctx, uint32_t inst) -{ - struct dcn20_opp *opp = kzalloc(sizeof(struct dcn20_opp), GFP_KERNEL); - - if (!opp) { - BREAK_TO_DEBUGGER(); - return NULL; - } - - dcn20_opp_construct(opp, ctx, inst, &opp_regs[inst], &opp_shift, &opp_mask); - return &opp->base; -} - -#define optc_regs(id)\ - [id] = { OPTC_COMMON_REG_LIST_DCN3_0(id) } - -static const struct dcn_optc_registers optc_regs[] = { - optc_regs(0), - optc_regs(1), - optc_regs(2), - optc_regs(3), - optc_regs(4) -}; - -static const struct dcn_optc_shift optc_shift = { - OPTC_COMMON_MASK_SH_LIST_DCN30(__SHIFT) -}; - -static const struct dcn_optc_mask optc_mask = { - OPTC_COMMON_MASK_SH_LIST_DCN30(_MASK) -}; - -static struct timing_generator *dcn302_timing_generator_create(struct dc_context *ctx, uint32_t instance) -{ - struct optc *tgn10 = kzalloc(sizeof(struct optc), GFP_KERNEL); - - if (!tgn10) - return NULL; - - tgn10->base.inst = instance; - tgn10->base.ctx = ctx; - - tgn10->tg_regs = &optc_regs[instance]; - tgn10->tg_shift = &optc_shift; - tgn10->tg_mask = &optc_mask; - - dcn30_timing_generator_init(tgn10); - - return &tgn10->base; -} - -static const struct dcn30_mpc_registers mpc_regs = { - MPC_REG_LIST_DCN3_0(0), - MPC_REG_LIST_DCN3_0(1), - MPC_REG_LIST_DCN3_0(2), - MPC_REG_LIST_DCN3_0(3), - MPC_REG_LIST_DCN3_0(4), - MPC_OUT_MUX_REG_LIST_DCN3_0(0), - MPC_OUT_MUX_REG_LIST_DCN3_0(1), - MPC_OUT_MUX_REG_LIST_DCN3_0(2), - MPC_OUT_MUX_REG_LIST_DCN3_0(3), - MPC_OUT_MUX_REG_LIST_DCN3_0(4), - MPC_RMU_GLOBAL_REG_LIST_DCN3AG, - MPC_RMU_REG_LIST_DCN3AG(0), - MPC_RMU_REG_LIST_DCN3AG(1), - MPC_RMU_REG_LIST_DCN3AG(2), - MPC_DWB_MUX_REG_LIST_DCN3_0(0), -}; - -static const struct dcn30_mpc_shift mpc_shift = { - MPC_COMMON_MASK_SH_LIST_DCN30(__SHIFT) -}; - -static const struct dcn30_mpc_mask mpc_mask = { - MPC_COMMON_MASK_SH_LIST_DCN30(_MASK) -}; - -static struct mpc *dcn302_mpc_create(struct dc_context *ctx, int num_mpcc, int num_rmu) -{ - struct dcn30_mpc *mpc30 = kzalloc(sizeof(struct dcn30_mpc), GFP_KERNEL); - - if (!mpc30) - return NULL; - - dcn30_mpc_construct(mpc30, ctx, &mpc_regs, &mpc_shift, &mpc_mask, num_mpcc, num_rmu); - - return &mpc30->base; -} - -#define dsc_regsDCN20(id)\ -[id] = { DSC_REG_LIST_DCN20(id) } - -static const struct dcn20_dsc_registers dsc_regs[] = { - dsc_regsDCN20(0), - dsc_regsDCN20(1), - dsc_regsDCN20(2), - dsc_regsDCN20(3), - dsc_regsDCN20(4) -}; - -static const struct dcn20_dsc_shift dsc_shift = { - DSC_REG_LIST_SH_MASK_DCN20(__SHIFT) -}; - -static const struct dcn20_dsc_mask dsc_mask = { - DSC_REG_LIST_SH_MASK_DCN20(_MASK) -}; - -static struct display_stream_compressor *dcn302_dsc_create(struct dc_context *ctx, uint32_t inst) -{ - struct dcn20_dsc *dsc = kzalloc(sizeof(struct dcn20_dsc), GFP_KERNEL); - - if (!dsc) { - BREAK_TO_DEBUGGER(); - return NULL; - } - - dsc2_construct(dsc, ctx, inst, &dsc_regs[inst], &dsc_shift, &dsc_mask); - return &dsc->base; -} - -#define dwbc_regs_dcn3(id)\ -[id] = { DWBC_COMMON_REG_LIST_DCN30(id) } - -static const struct dcn30_dwbc_registers dwbc30_regs[] = { - dwbc_regs_dcn3(0) -}; - -static const struct dcn30_dwbc_shift dwbc30_shift = { - DWBC_COMMON_MASK_SH_LIST_DCN30(__SHIFT) -}; - -static const struct dcn30_dwbc_mask dwbc30_mask = { - DWBC_COMMON_MASK_SH_LIST_DCN30(_MASK) -}; - -static bool dcn302_dwbc_create(struct dc_context *ctx, struct resource_pool *pool) -{ - int i; - uint32_t pipe_count = pool->res_cap->num_dwb; - - for (i = 0; i < pipe_count; i++) { - struct dcn30_dwbc *dwbc30 = kzalloc(sizeof(struct dcn30_dwbc), GFP_KERNEL); - - if (!dwbc30) { - dm_error("DC: failed to create dwbc30!\n"); - return false; - } - - dcn30_dwbc_construct(dwbc30, ctx, &dwbc30_regs[i], &dwbc30_shift, &dwbc30_mask, i); - - pool->dwbc[i] = &dwbc30->base; - } - return true; -} - -#define mcif_wb_regs_dcn3(id)\ -[id] = { MCIF_WB_COMMON_REG_LIST_DCN30(id) } - -static const struct dcn30_mmhubbub_registers mcif_wb30_regs[] = { - mcif_wb_regs_dcn3(0) -}; - -static const struct dcn30_mmhubbub_shift mcif_wb30_shift = { - MCIF_WB_COMMON_MASK_SH_LIST_DCN30(__SHIFT) -}; - -static const struct dcn30_mmhubbub_mask mcif_wb30_mask = { - MCIF_WB_COMMON_MASK_SH_LIST_DCN30(_MASK) -}; - -static bool dcn302_mmhubbub_create(struct dc_context *ctx, struct resource_pool *pool) -{ - int i; - uint32_t pipe_count = pool->res_cap->num_dwb; - - for (i = 0; i < pipe_count; i++) { - struct dcn30_mmhubbub *mcif_wb30 = kzalloc(sizeof(struct dcn30_mmhubbub), GFP_KERNEL); - - if (!mcif_wb30) { - dm_error("DC: failed to create mcif_wb30!\n"); - return false; - } - - dcn30_mmhubbub_construct(mcif_wb30, ctx, &mcif_wb30_regs[i], &mcif_wb30_shift, &mcif_wb30_mask, i); - - pool->mcif_wb[i] = &mcif_wb30->base; - } - return true; -} - -#define aux_engine_regs(id)\ -[id] = {\ - AUX_COMMON_REG_LIST0(id), \ - .AUXN_IMPCAL = 0, \ - .AUXP_IMPCAL = 0, \ - .AUX_RESET_MASK = DP_AUX0_AUX_CONTROL__AUX_RESET_MASK, \ -} - -static const struct dce110_aux_registers aux_engine_regs[] = { - aux_engine_regs(0), - aux_engine_regs(1), - aux_engine_regs(2), - aux_engine_regs(3), - aux_engine_regs(4) -}; - -static const struct dce110_aux_registers_shift aux_shift = { - DCN_AUX_MASK_SH_LIST(__SHIFT) -}; - -static const struct dce110_aux_registers_mask aux_mask = { - DCN_AUX_MASK_SH_LIST(_MASK) -}; - -static struct dce_aux *dcn302_aux_engine_create(struct dc_context *ctx, uint32_t inst) -{ - struct aux_engine_dce110 *aux_engine = kzalloc(sizeof(struct aux_engine_dce110), GFP_KERNEL); - - if (!aux_engine) - return NULL; - - dce110_aux_engine_construct(aux_engine, ctx, inst, SW_AUX_TIMEOUT_PERIOD_MULTIPLIER * AUX_TIMEOUT_PERIOD, - &aux_engine_regs[inst], &aux_mask, &aux_shift, ctx->dc->caps.extended_aux_timeout_support); - - return &aux_engine->base; -} - -#define i2c_inst_regs(id) { I2C_HW_ENGINE_COMMON_REG_LIST(id) } - -static const struct dce_i2c_registers i2c_hw_regs[] = { - i2c_inst_regs(1), - i2c_inst_regs(2), - i2c_inst_regs(3), - i2c_inst_regs(4), - i2c_inst_regs(5) -}; - -static const struct dce_i2c_shift i2c_shifts = { - I2C_COMMON_MASK_SH_LIST_DCN2(__SHIFT) -}; - -static const struct dce_i2c_mask i2c_masks = { - I2C_COMMON_MASK_SH_LIST_DCN2(_MASK) -}; - -static struct dce_i2c_hw *dcn302_i2c_hw_create(struct dc_context *ctx, uint32_t inst) -{ - struct dce_i2c_hw *dce_i2c_hw = kzalloc(sizeof(struct dce_i2c_hw), GFP_KERNEL); - - if (!dce_i2c_hw) - return NULL; - - dcn2_i2c_hw_construct(dce_i2c_hw, ctx, inst, &i2c_hw_regs[inst], &i2c_shifts, &i2c_masks); - - return dce_i2c_hw; -} - -static const struct encoder_feature_support link_enc_feature = { - .max_hdmi_deep_color = COLOR_DEPTH_121212, - .max_hdmi_pixel_clock = 600000, - .hdmi_ycbcr420_supported = true, - .dp_ycbcr420_supported = true, - .fec_supported = true, - .flags.bits.IS_HBR2_CAPABLE = true, - .flags.bits.IS_HBR3_CAPABLE = true, - .flags.bits.IS_TPS3_CAPABLE = true, - .flags.bits.IS_TPS4_CAPABLE = true -}; - -#define link_regs(id, phyid)\ - [id] = {\ - LE_DCN3_REG_LIST(id), \ - UNIPHY_DCN2_REG_LIST(phyid), \ - DPCS_DCN2_REG_LIST(id), \ - SRI(DP_DPHY_INTERNAL_CTRL, DP, id) \ - } - -static const struct dcn10_link_enc_registers link_enc_regs[] = { - link_regs(0, A), - link_regs(1, B), - link_regs(2, C), - link_regs(3, D), - link_regs(4, E) -}; - -static const struct dcn10_link_enc_shift le_shift = { - LINK_ENCODER_MASK_SH_LIST_DCN30(__SHIFT), - DPCS_DCN2_MASK_SH_LIST(__SHIFT) -}; - -static const struct dcn10_link_enc_mask le_mask = { - LINK_ENCODER_MASK_SH_LIST_DCN30(_MASK), - DPCS_DCN2_MASK_SH_LIST(_MASK) -}; - -#define aux_regs(id)\ - [id] = { DCN2_AUX_REG_LIST(id) } - -static const struct dcn10_link_enc_aux_registers link_enc_aux_regs[] = { - aux_regs(0), - aux_regs(1), - aux_regs(2), - aux_regs(3), - aux_regs(4) -}; - -#define hpd_regs(id)\ - [id] = { HPD_REG_LIST(id) } - -static const struct dcn10_link_enc_hpd_registers link_enc_hpd_regs[] = { - hpd_regs(0), - hpd_regs(1), - hpd_regs(2), - hpd_regs(3), - hpd_regs(4) -}; - -static struct link_encoder *dcn302_link_encoder_create( - struct dc_context *ctx, - const struct encoder_init_data *enc_init_data) -{ - struct dcn20_link_encoder *enc20 = kzalloc(sizeof(struct dcn20_link_encoder), GFP_KERNEL); - - if (!enc20) - return NULL; - - dcn30_link_encoder_construct(enc20, enc_init_data, &link_enc_feature, - &link_enc_regs[enc_init_data->transmitter], &link_enc_aux_regs[enc_init_data->channel - 1], - &link_enc_hpd_regs[enc_init_data->hpd_source], &le_shift, &le_mask); - - return &enc20->enc10.base; -} - -static const struct dce_panel_cntl_registers panel_cntl_regs[] = { - { DCN_PANEL_CNTL_REG_LIST() } -}; - -static const struct dce_panel_cntl_shift panel_cntl_shift = { - DCE_PANEL_CNTL_MASK_SH_LIST(__SHIFT) -}; - -static const struct dce_panel_cntl_mask panel_cntl_mask = { - DCE_PANEL_CNTL_MASK_SH_LIST(_MASK) -}; - -static struct panel_cntl *dcn302_panel_cntl_create(const struct panel_cntl_init_data *init_data) -{ - struct dce_panel_cntl *panel_cntl = kzalloc(sizeof(struct dce_panel_cntl), GFP_KERNEL); - - if (!panel_cntl) - return NULL; - - dce_panel_cntl_construct(panel_cntl, init_data, &panel_cntl_regs[init_data->inst], - &panel_cntl_shift, &panel_cntl_mask); - - return &panel_cntl->base; -} - -static void read_dce_straps(struct dc_context *ctx, struct resource_straps *straps) -{ - generic_reg_get(ctx, mmDC_PINSTRAPS + BASE(mmDC_PINSTRAPS_BASE_IDX), - FN(DC_PINSTRAPS, DC_PINSTRAPS_AUDIO), &straps->dc_pinstraps_audio); -} - -static const struct resource_create_funcs res_create_funcs = { - .read_dce_straps = read_dce_straps, - .create_audio = dcn302_create_audio, - .create_stream_encoder = dcn302_stream_encoder_create, - .create_hwseq = dcn302_hwseq_create, -}; - -static bool is_soc_bounding_box_valid(struct dc *dc) -{ - uint32_t hw_internal_rev = dc->ctx->asic_id.hw_internal_rev; - - if (ASICREV_IS_DIMGREY_CAVEFISH_P(hw_internal_rev)) - return true; - - return false; -} - -static bool init_soc_bounding_box(struct dc *dc, struct resource_pool *pool) -{ - struct _vcs_dpi_soc_bounding_box_st *loaded_bb = &dcn3_02_soc; - struct _vcs_dpi_ip_params_st *loaded_ip = &dcn3_02_ip; - - DC_LOGGER_INIT(dc->ctx->logger); - - if (!is_soc_bounding_box_valid(dc)) { - DC_LOG_ERROR("%s: not valid soc bounding box\n", __func__); - return false; - } - - loaded_ip->max_num_otg = pool->pipe_count; - loaded_ip->max_num_dpp = pool->pipe_count; - loaded_ip->clamp_min_dcfclk = dc->config.clamp_min_dcfclk; - DC_FP_START(); - dcn20_patch_bounding_box(dc, loaded_bb); - DC_FP_END(); - - 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) { - - DC_FP_START(); - dcn302_fpu_init_soc_bounding_box(bb_info); - DC_FP_END(); - } - } - - return true; -} - -static void dcn302_resource_destruct(struct resource_pool *pool) -{ - unsigned int i; - - for (i = 0; i < pool->stream_enc_count; i++) { - if (pool->stream_enc[i] != NULL) { - if (pool->stream_enc[i]->vpg != NULL) { - kfree(DCN30_VPG_FROM_VPG(pool->stream_enc[i]->vpg)); - pool->stream_enc[i]->vpg = NULL; - } - if (pool->stream_enc[i]->afmt != NULL) { - kfree(DCN30_AFMT_FROM_AFMT(pool->stream_enc[i]->afmt)); - pool->stream_enc[i]->afmt = NULL; - } - kfree(DCN10STRENC_FROM_STRENC(pool->stream_enc[i])); - pool->stream_enc[i] = NULL; - } - } - - for (i = 0; i < pool->res_cap->num_dsc; i++) { - if (pool->dscs[i] != NULL) - dcn20_dsc_destroy(&pool->dscs[i]); - } - - if (pool->mpc != NULL) { - kfree(TO_DCN20_MPC(pool->mpc)); - pool->mpc = NULL; - } - - if (pool->hubbub != NULL) { - kfree(pool->hubbub); - pool->hubbub = NULL; - } - - for (i = 0; i < pool->pipe_count; i++) { - if (pool->dpps[i] != NULL) { - kfree(TO_DCN20_DPP(pool->dpps[i])); - pool->dpps[i] = NULL; - } - - if (pool->hubps[i] != NULL) { - kfree(TO_DCN20_HUBP(pool->hubps[i])); - pool->hubps[i] = NULL; - } - - if (pool->irqs != NULL) - dal_irq_service_destroy(&pool->irqs); - } - - for (i = 0; i < pool->res_cap->num_ddc; i++) { - if (pool->engines[i] != NULL) - dce110_engine_destroy(&pool->engines[i]); - if (pool->hw_i2cs[i] != NULL) { - kfree(pool->hw_i2cs[i]); - pool->hw_i2cs[i] = NULL; - } - if (pool->sw_i2cs[i] != NULL) { - kfree(pool->sw_i2cs[i]); - pool->sw_i2cs[i] = NULL; - } - } - - for (i = 0; i < pool->res_cap->num_opp; i++) { - if (pool->opps[i] != NULL) - pool->opps[i]->funcs->opp_destroy(&pool->opps[i]); - } - - for (i = 0; i < pool->res_cap->num_timing_generator; i++) { - if (pool->timing_generators[i] != NULL) { - kfree(DCN10TG_FROM_TG(pool->timing_generators[i])); - pool->timing_generators[i] = NULL; - } - } - - for (i = 0; i < pool->res_cap->num_dwb; i++) { - if (pool->dwbc[i] != NULL) { - kfree(TO_DCN30_DWBC(pool->dwbc[i])); - pool->dwbc[i] = NULL; - } - if (pool->mcif_wb[i] != NULL) { - kfree(TO_DCN30_MMHUBBUB(pool->mcif_wb[i])); - pool->mcif_wb[i] = NULL; - } - } - - for (i = 0; i < pool->audio_count; i++) { - if (pool->audios[i]) - dce_aud_destroy(&pool->audios[i]); - } - - for (i = 0; i < pool->clk_src_count; i++) { - if (pool->clock_sources[i] != NULL) - dcn20_clock_source_destroy(&pool->clock_sources[i]); - } - - if (pool->dp_clock_source != NULL) - dcn20_clock_source_destroy(&pool->dp_clock_source); - - for (i = 0; i < pool->res_cap->num_mpc_3dlut; i++) { - if (pool->mpc_lut[i] != NULL) { - dc_3dlut_func_release(pool->mpc_lut[i]); - pool->mpc_lut[i] = NULL; - } - if (pool->mpc_shaper[i] != NULL) { - dc_transfer_func_release(pool->mpc_shaper[i]); - pool->mpc_shaper[i] = NULL; - } - } - - for (i = 0; i < pool->pipe_count; i++) { - if (pool->multiple_abms[i] != NULL) - dce_abm_destroy(&pool->multiple_abms[i]); - } - - if (pool->psr != NULL) - dmub_psr_destroy(&pool->psr); - - if (pool->dccg != NULL) - dcn_dccg_destroy(&pool->dccg); - - if (pool->oem_device != NULL) { - struct dc *dc = pool->oem_device->ctx->dc; - - dc->link_srv->destroy_ddc_service(&pool->oem_device); - } -} - -static void dcn302_destroy_resource_pool(struct resource_pool **pool) -{ - dcn302_resource_destruct(*pool); - kfree(*pool); - *pool = NULL; -} - -void dcn302_update_bw_bounding_box(struct dc *dc, struct clk_bw_params *bw_params) -{ - DC_FP_START(); - dcn302_fpu_update_bw_bounding_box(dc, bw_params); - DC_FP_END(); -} - -static void dcn302_get_panel_config_defaults(struct dc_panel_config *panel_config) -{ - *panel_config = panel_config_defaults; -} - -static struct resource_funcs dcn302_res_pool_funcs = { - .destroy = dcn302_destroy_resource_pool, - .link_enc_create = dcn302_link_encoder_create, - .panel_cntl_create = dcn302_panel_cntl_create, - .validate_bandwidth = dcn30_validate_bandwidth, - .calculate_wm_and_dlg = dcn30_calculate_wm_and_dlg, - .update_soc_for_wm_a = dcn30_update_soc_for_wm_a, - .populate_dml_pipes = dcn30_populate_dml_pipes_from_context, - .acquire_free_pipe_as_secondary_dpp_pipe = dcn20_acquire_free_pipe_for_layer, - .release_pipe = dcn20_release_pipe, - .add_stream_to_ctx = dcn30_add_stream_to_ctx, - .add_dsc_to_stream_resource = dcn20_add_dsc_to_stream_resource, - .remove_stream_from_ctx = dcn20_remove_stream_from_ctx, - .populate_dml_writeback_from_context = dcn30_populate_dml_writeback_from_context, - .set_mcif_arb_params = dcn30_set_mcif_arb_params, - .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 = dcn302_update_bw_bounding_box, - .patch_unknown_plane_state = dcn20_patch_unknown_plane_state, - .get_panel_config_defaults = dcn302_get_panel_config_defaults, -}; - -static struct dc_cap_funcs cap_funcs = { - .get_dcc_compression_cap = dcn20_get_dcc_compression_cap -}; - -static const struct bios_registers bios_regs = { - NBIO_SR(BIOS_SCRATCH_3), - NBIO_SR(BIOS_SCRATCH_6) -}; - -static const struct dccg_registers dccg_regs = { - DCCG_REG_LIST_DCN3_02() -}; - -static const struct dccg_shift dccg_shift = { - DCCG_MASK_SH_LIST_DCN3_02(__SHIFT) -}; - -static const struct dccg_mask dccg_mask = { - DCCG_MASK_SH_LIST_DCN3_02(_MASK) -}; - -#define abm_regs(id)\ - [id] = { ABM_DCN302_REG_LIST(id) } - -static const struct dce_abm_registers abm_regs[] = { - abm_regs(0), - abm_regs(1), - abm_regs(2), - abm_regs(3), - abm_regs(4) -}; - -static const struct dce_abm_shift abm_shift = { - ABM_MASK_SH_LIST_DCN30(__SHIFT) -}; - -static const struct dce_abm_mask abm_mask = { - ABM_MASK_SH_LIST_DCN30(_MASK) -}; - -static bool dcn302_resource_construct( - uint8_t num_virtual_links, - struct dc *dc, - struct resource_pool *pool) -{ - int i; - struct dc_context *ctx = dc->ctx; - struct irq_service_init_data init_data; - struct ddc_service_init_data ddc_init_data = {0}; - - ctx->dc_bios->regs = &bios_regs; - - pool->res_cap = &res_cap_dcn302; - - pool->funcs = &dcn302_res_pool_funcs; - - /************************************************* - * Resource + asic cap harcoding * - *************************************************/ - pool->underlay_pipe_index = NO_UNDERLAY_PIPE; - pool->pipe_count = pool->res_cap->num_timing_generator; - pool->mpcc_count = pool->res_cap->num_timing_generator; - dc->caps.max_downscale_ratio = 600; - dc->caps.i2c_speed_in_khz = 100; - dc->caps.i2c_speed_in_khz_hdcp = 5; /*1.4 w/a applied by derfault*/ - 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 = 2; - dc->caps.max_slave_yuv_planes = 2; - dc->caps.max_slave_rgb_planes = 2; - dc->caps.post_blend_color_processing = true; - dc->caps.force_dp_tps4_for_cp2520 = true; - dc->caps.extended_aux_timeout_support = true; - dc->caps.dmcub_support = true; - dc->caps.max_v_total = (1 << 15) - 1; - - /* Color pipeline capabilities */ - dc->caps.color.dpp.dcn_arch = 1; - dc->caps.color.dpp.input_lut_shared = 0; - dc->caps.color.dpp.icsc = 1; - dc->caps.color.dpp.dgam_ram = 0; // must use gamma_corr - dc->caps.color.dpp.dgam_rom_caps.srgb = 1; - dc->caps.color.dpp.dgam_rom_caps.bt2020 = 1; - dc->caps.color.dpp.dgam_rom_caps.gamma2_2 = 1; - dc->caps.color.dpp.dgam_rom_caps.pq = 1; - dc->caps.color.dpp.dgam_rom_caps.hlg = 1; - dc->caps.color.dpp.post_csc = 1; - dc->caps.color.dpp.gamma_corr = 1; - dc->caps.color.dpp.dgam_rom_for_yuv = 0; - - dc->caps.color.dpp.hw_3d_lut = 1; - dc->caps.color.dpp.ogam_ram = 1; - // no OGAM ROM on DCN3 - dc->caps.color.dpp.ogam_rom_caps.srgb = 0; - dc->caps.color.dpp.ogam_rom_caps.bt2020 = 0; - dc->caps.color.dpp.ogam_rom_caps.gamma2_2 = 0; - dc->caps.color.dpp.ogam_rom_caps.pq = 0; - dc->caps.color.dpp.ogam_rom_caps.hlg = 0; - dc->caps.color.dpp.ocsc = 0; - - dc->caps.color.mpc.gamut_remap = 1; - dc->caps.color.mpc.num_3dluts = pool->res_cap->num_mpc_3dlut; //3 - dc->caps.color.mpc.ogam_ram = 1; - dc->caps.color.mpc.ogam_rom_caps.srgb = 0; - dc->caps.color.mpc.ogam_rom_caps.bt2020 = 0; - dc->caps.color.mpc.ogam_rom_caps.gamma2_2 = 0; - dc->caps.color.mpc.ogam_rom_caps.pq = 0; - dc->caps.color.mpc.ogam_rom_caps.hlg = 0; - dc->caps.color.mpc.ocsc = 1; - - dc->caps.dp_hdmi21_pcon_support = true; - - /* read VBIOS LTTPR caps */ - if (ctx->dc_bios->funcs->get_lttpr_caps) { - enum bp_result bp_query_result; - uint8_t is_vbios_lttpr_enable = 0; - - bp_query_result = ctx->dc_bios->funcs->get_lttpr_caps(ctx->dc_bios, &is_vbios_lttpr_enable); - dc->caps.vbios_lttpr_enable = (bp_query_result == BP_RESULT_OK) && !!is_vbios_lttpr_enable; - } - - if (ctx->dc_bios->funcs->get_lttpr_interop) { - enum bp_result bp_query_result; - uint8_t is_vbios_interop_enabled = 0; - - bp_query_result = ctx->dc_bios->funcs->get_lttpr_interop(ctx->dc_bios, - &is_vbios_interop_enabled); - dc->caps.vbios_lttpr_aware = (bp_query_result == BP_RESULT_OK) && !!is_vbios_interop_enabled; - } - - if (dc->ctx->dce_environment == DCE_ENV_PRODUCTION_DRV) - dc->debug = debug_defaults_drv; - - // Init the vm_helper - if (dc->vm_helper) - vm_helper_init(dc->vm_helper, 16); - - /************************************************* - * Create resources * - *************************************************/ - - /* Clock Sources for Pixel Clock*/ - pool->clock_sources[DCN302_CLK_SRC_PLL0] = - dcn302_clock_source_create(ctx, ctx->dc_bios, - CLOCK_SOURCE_COMBO_PHY_PLL0, - &clk_src_regs[0], false); - pool->clock_sources[DCN302_CLK_SRC_PLL1] = - dcn302_clock_source_create(ctx, ctx->dc_bios, - CLOCK_SOURCE_COMBO_PHY_PLL1, - &clk_src_regs[1], false); - pool->clock_sources[DCN302_CLK_SRC_PLL2] = - dcn302_clock_source_create(ctx, ctx->dc_bios, - CLOCK_SOURCE_COMBO_PHY_PLL2, - &clk_src_regs[2], false); - pool->clock_sources[DCN302_CLK_SRC_PLL3] = - dcn302_clock_source_create(ctx, ctx->dc_bios, - CLOCK_SOURCE_COMBO_PHY_PLL3, - &clk_src_regs[3], false); - pool->clock_sources[DCN302_CLK_SRC_PLL4] = - dcn302_clock_source_create(ctx, ctx->dc_bios, - CLOCK_SOURCE_COMBO_PHY_PLL4, - &clk_src_regs[4], false); - - pool->clk_src_count = DCN302_CLK_SRC_TOTAL; - - /* todo: not reuse phy_pll registers */ - pool->dp_clock_source = - dcn302_clock_source_create(ctx, ctx->dc_bios, - CLOCK_SOURCE_ID_DP_DTO, - &clk_src_regs[0], true); - - for (i = 0; i < pool->clk_src_count; i++) { - if (pool->clock_sources[i] == NULL) { - dm_error("DC: failed to create clock sources!\n"); - BREAK_TO_DEBUGGER(); - goto create_fail; - } - } - - /* DCCG */ - pool->dccg = dccg30_create(ctx, &dccg_regs, &dccg_shift, &dccg_mask); - if (pool->dccg == NULL) { - dm_error("DC: failed to create dccg!\n"); - BREAK_TO_DEBUGGER(); - goto create_fail; - } - - /* PP Lib and SMU interfaces */ - init_soc_bounding_box(dc, pool); - - /* DML */ - dml_init_instance(&dc->dml, &dcn3_02_soc, &dcn3_02_ip, DML_PROJECT_DCN30); - - /* IRQ */ - init_data.ctx = dc->ctx; - pool->irqs = dal_irq_service_dcn302_create(&init_data); - if (!pool->irqs) - goto create_fail; - - /* HUBBUB */ - pool->hubbub = dcn302_hubbub_create(ctx); - if (pool->hubbub == NULL) { - BREAK_TO_DEBUGGER(); - dm_error("DC: failed to create hubbub!\n"); - goto create_fail; - } - - /* HUBPs, DPPs, OPPs and TGs */ - for (i = 0; i < pool->pipe_count; i++) { - pool->hubps[i] = dcn302_hubp_create(ctx, i); - if (pool->hubps[i] == NULL) { - BREAK_TO_DEBUGGER(); - dm_error("DC: failed to create hubps!\n"); - goto create_fail; - } - - pool->dpps[i] = dcn302_dpp_create(ctx, i); - if (pool->dpps[i] == NULL) { - BREAK_TO_DEBUGGER(); - dm_error("DC: failed to create dpps!\n"); - goto create_fail; - } - } - - for (i = 0; i < pool->res_cap->num_opp; i++) { - pool->opps[i] = dcn302_opp_create(ctx, i); - if (pool->opps[i] == NULL) { - BREAK_TO_DEBUGGER(); - dm_error("DC: failed to create output pixel processor!\n"); - goto create_fail; - } - } - - for (i = 0; i < pool->res_cap->num_timing_generator; i++) { - pool->timing_generators[i] = dcn302_timing_generator_create(ctx, i); - if (pool->timing_generators[i] == NULL) { - BREAK_TO_DEBUGGER(); - dm_error("DC: failed to create tg!\n"); - goto create_fail; - } - } - pool->timing_generator_count = i; - - /* PSR */ - pool->psr = dmub_psr_create(ctx); - if (pool->psr == NULL) { - dm_error("DC: failed to create psr!\n"); - BREAK_TO_DEBUGGER(); - goto create_fail; - } - - /* ABMs */ - for (i = 0; i < pool->res_cap->num_timing_generator; i++) { - pool->multiple_abms[i] = dmub_abm_create(ctx, &abm_regs[i], &abm_shift, &abm_mask); - if (pool->multiple_abms[i] == NULL) { - dm_error("DC: failed to create abm for pipe %d!\n", i); - BREAK_TO_DEBUGGER(); - goto create_fail; - } - } - - /* MPC and DSC */ - pool->mpc = dcn302_mpc_create(ctx, pool->mpcc_count, pool->res_cap->num_mpc_3dlut); - if (pool->mpc == NULL) { - BREAK_TO_DEBUGGER(); - dm_error("DC: failed to create mpc!\n"); - goto create_fail; - } - - for (i = 0; i < pool->res_cap->num_dsc; i++) { - pool->dscs[i] = dcn302_dsc_create(ctx, i); - if (pool->dscs[i] == NULL) { - BREAK_TO_DEBUGGER(); - dm_error("DC: failed to create display stream compressor %d!\n", i); - goto create_fail; - } - } - - /* DWB and MMHUBBUB */ - if (!dcn302_dwbc_create(ctx, pool)) { - BREAK_TO_DEBUGGER(); - dm_error("DC: failed to create dwbc!\n"); - goto create_fail; - } - - if (!dcn302_mmhubbub_create(ctx, pool)) { - BREAK_TO_DEBUGGER(); - dm_error("DC: failed to create mcif_wb!\n"); - goto create_fail; - } - - /* AUX and I2C */ - for (i = 0; i < pool->res_cap->num_ddc; i++) { - pool->engines[i] = dcn302_aux_engine_create(ctx, i); - if (pool->engines[i] == NULL) { - BREAK_TO_DEBUGGER(); - dm_error("DC:failed to create aux engine!!\n"); - goto create_fail; - } - pool->hw_i2cs[i] = dcn302_i2c_hw_create(ctx, i); - if (pool->hw_i2cs[i] == NULL) { - BREAK_TO_DEBUGGER(); - dm_error("DC:failed to create hw i2c!!\n"); - goto create_fail; - } - pool->sw_i2cs[i] = NULL; - } - - /* Audio, Stream Encoders including HPO and virtual, MPC 3D LUTs */ - if (!resource_construct(num_virtual_links, dc, pool, - &res_create_funcs)) - goto create_fail; - - /* HW Sequencer and Plane caps */ - dcn302_hw_sequencer_construct(dc); - - dc->caps.max_planes = pool->pipe_count; - - for (i = 0; i < dc->caps.max_planes; ++i) - dc->caps.planes[i] = plane_cap; - - dc->cap_funcs = cap_funcs; - - if (dc->ctx->dc_bios->fw_info.oem_i2c_present) { - ddc_init_data.ctx = dc->ctx; - ddc_init_data.link = NULL; - ddc_init_data.id.id = dc->ctx->dc_bios->fw_info.oem_i2c_obj_id; - ddc_init_data.id.enum_id = 0; - ddc_init_data.id.type = OBJECT_TYPE_GENERIC; - pool->oem_device = dc->link_srv->create_ddc_service(&ddc_init_data); - } else { - pool->oem_device = NULL; - } - - return true; - -create_fail: - - dcn302_resource_destruct(pool); - - return false; -} - -struct resource_pool *dcn302_create_resource_pool(const struct dc_init_data *init_data, struct dc *dc) -{ - struct resource_pool *pool = kzalloc(sizeof(struct resource_pool), GFP_KERNEL); - - if (!pool) - return NULL; - - if (dcn302_resource_construct(init_data->num_virtual_links, dc, pool)) - return pool; - - BREAK_TO_DEBUGGER(); - kfree(pool); - return NULL; -} diff --git a/drivers/gpu/drm/amd/display/dc/dcn302/dcn302_resource.h b/drivers/gpu/drm/amd/display/dc/dcn302/dcn302_resource.h deleted file mode 100644 index 9f24e73b92b3..000000000000 --- a/drivers/gpu/drm/amd/display/dc/dcn302/dcn302_resource.h +++ /dev/null @@ -1,38 +0,0 @@ -/* - * Copyright 2020 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 _DCN302_RESOURCE_H_ -#define _DCN302_RESOURCE_H_ - -#include "core_types.h" - -extern struct _vcs_dpi_ip_params_st dcn3_02_ip; -extern struct _vcs_dpi_soc_bounding_box_st dcn3_02_soc; - -struct resource_pool *dcn302_create_resource_pool(const struct dc_init_data *init_data, struct dc *dc); - -void dcn302_update_bw_bounding_box(struct dc *dc, struct clk_bw_params *bw_params); - -#endif /* _DCN302_RESOURCE_H_ */ diff --git a/drivers/gpu/drm/amd/display/dc/dcn303/Makefile b/drivers/gpu/drm/amd/display/dc/dcn303/Makefile index d7b3ad780e5d..a954e316aca2 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn303/Makefile +++ b/drivers/gpu/drm/amd/display/dc/dcn303/Makefile @@ -6,7 +6,7 @@ # # Makefile for dcn303. -DCN3_03 = dcn303_init.o dcn303_resource.o +DCN3_03 = dcn303_init.o AMD_DAL_DCN3_03 = $(addprefix $(AMDDALPATH)/dc/dcn303/,$(DCN3_03)) diff --git a/drivers/gpu/drm/amd/display/dc/dcn303/dcn303_resource.c b/drivers/gpu/drm/amd/display/dc/dcn303/dcn303_resource.c deleted file mode 100644 index 49cb7fde416a..000000000000 --- a/drivers/gpu/drm/amd/display/dc/dcn303/dcn303_resource.c +++ /dev/null @@ -1,1448 +0,0 @@ -// SPDX-License-Identifier: MIT -/* - * Copyright (C) 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 "dcn303_init.h" -#include "dcn303_resource.h" -#include "dcn303_dccg.h" -#include "irq/dcn303/irq_service_dcn303.h" - -#include "dcn30/dcn30_dio_link_encoder.h" -#include "dcn30/dcn30_dio_stream_encoder.h" -#include "dcn30/dcn30_dpp.h" -#include "dcn30/dcn30_dwb.h" -#include "dcn30/dcn30_hubbub.h" -#include "dcn30/dcn30_hubp.h" -#include "dcn30/dcn30_mmhubbub.h" -#include "dcn30/dcn30_mpc.h" -#include "dcn30/dcn30_opp.h" -#include "dcn30/dcn30_optc.h" -#include "dcn30/dcn30_resource.h" - -#include "dcn20/dcn20_dsc.h" -#include "dcn20/dcn20_resource.h" - -#include "dml/dcn30/dcn30_fpu.h" - -#include "dcn10/dcn10_resource.h" - -#include "link.h" - -#include "dce/dce_abm.h" -#include "dce/dce_audio.h" -#include "dce/dce_aux.h" -#include "dce/dce_clock_source.h" -#include "dce/dce_hwseq.h" -#include "dce/dce_i2c_hw.h" -#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" -#include "resource.h" -#include "vm_helper.h" - -#include "sienna_cichlid_ip_offset.h" -#include "dcn/dcn_3_0_3_offset.h" -#include "dcn/dcn_3_0_3_sh_mask.h" -#include "dpcs/dpcs_3_0_3_offset.h" -#include "dpcs/dpcs_3_0_3_sh_mask.h" -#include "nbio/nbio_2_3_offset.h" - -#include "dml/dcn303/dcn303_fpu.h" - -#define DC_LOGGER \ - dc->ctx->logger -#define DC_LOGGER_INIT(logger) - - -static const struct dc_debug_options debug_defaults_drv = { - .disable_dmcu = true, - .force_abm_enable = false, - .timing_trace = false, - .clock_trace = true, - .disable_pplib_clock_request = true, - .pipe_split_policy = MPC_SPLIT_AVOID, - .force_single_disp_pipe_split = false, - .disable_dcc = DCC_ENABLE, - .vsr_support = true, - .performance_trace = false, - .max_downscale_src_width = 7680,/*upto 8K*/ - .disable_pplib_wm_range = false, - .scl_reset_length10 = true, - .sanity_checks = false, - .underflow_assert_delay_us = 0xFFFFFFFF, - .dwb_fi_phase = -1, // -1 = disable, - .dmub_command_table = true, - .exit_idle_opt_for_cursor_updates = true, - .disable_idle_power_optimizations = false, - .using_dml2 = false, -}; - -static const struct dc_panel_config panel_config_defaults = { - .psr = { - .disable_psr = false, - .disallow_psrsu = false, - .disallow_replay = false, - }, -}; - -enum dcn303_clk_src_array_id { - DCN303_CLK_SRC_PLL0, - DCN303_CLK_SRC_PLL1, - DCN303_CLK_SRC_TOTAL -}; - -static const struct resource_caps res_cap_dcn303 = { - .num_timing_generator = 2, - .num_opp = 2, - .num_video_plane = 2, - .num_audio = 2, - .num_stream_encoder = 2, - .num_dwb = 1, - .num_ddc = 2, - .num_vmid = 16, - .num_mpc_3dlut = 1, - .num_dsc = 2, -}; - -static const struct dc_plane_cap plane_cap = { - .type = DC_PLANE_TYPE_DCN_UNIVERSAL, - .per_pixel_alpha = true, - .pixel_format_support = { - .argb8888 = true, - .nv12 = true, - .fp16 = true, - .p010 = true, - .ayuv = false, - }, - .max_upscale_factor = { - .argb8888 = 16000, - .nv12 = 16000, - .fp16 = 16000 - }, - .max_downscale_factor = { - .argb8888 = 600, - .nv12 = 600, - .fp16 = 600 - }, - 16, - 16 -}; - -/* NBIO */ -#define NBIO_BASE_INNER(seg) \ - NBIO_BASE__INST0_SEG ## seg - -#define NBIO_BASE(seg) \ - NBIO_BASE_INNER(seg) - -#define NBIO_SR(reg_name)\ - .reg_name = NBIO_BASE(mm ## reg_name ## _BASE_IDX) + \ - mm ## reg_name - -/* DCN */ -#define BASE_INNER(seg) DCN_BASE__INST0_SEG ## seg - -#define BASE(seg) BASE_INNER(seg) - -#define SR(reg_name)\ - .reg_name = BASE(mm ## reg_name ## _BASE_IDX) + mm ## reg_name - -#define SF(reg_name, field_name, post_fix)\ - .field_name = reg_name ## __ ## field_name ## post_fix - -#define SRI(reg_name, block, id)\ - .reg_name = BASE(mm ## block ## id ## _ ## reg_name ## _BASE_IDX) + mm ## block ## id ## _ ## reg_name - -#define SRI2(reg_name, block, id)\ - .reg_name = BASE(mm ## reg_name ## _BASE_IDX) + mm ## reg_name - -#define SRII(reg_name, block, id)\ - .reg_name[id] = BASE(mm ## block ## id ## _ ## reg_name ## _BASE_IDX) + \ - mm ## block ## id ## _ ## reg_name - -#define DCCG_SRII(reg_name, block, id)\ - .block ## _ ## reg_name[id] = BASE(mm ## block ## id ## _ ## reg_name ## _BASE_IDX) + \ - mm ## block ## id ## _ ## reg_name - -#define VUPDATE_SRII(reg_name, block, id)\ - .reg_name[id] = BASE(mm ## reg_name ## _ ## block ## id ## _BASE_IDX) + \ - mm ## reg_name ## _ ## block ## id - -#define SRII_DWB(reg_name, temp_name, block, id)\ - .reg_name[id] = BASE(mm ## block ## id ## _ ## temp_name ## _BASE_IDX) + \ - mm ## block ## id ## _ ## temp_name - -#define SF_DWB2(reg_name, block, id, field_name, post_fix) \ - .field_name = reg_name ## __ ## field_name ## post_fix - -#define SRII_MPC_RMU(reg_name, block, id)\ - .RMU##_##reg_name[id] = BASE(mm ## block ## id ## _ ## reg_name ## _BASE_IDX) + \ - mm ## block ## id ## _ ## reg_name - -static const struct dcn_hubbub_registers hubbub_reg = { - HUBBUB_REG_LIST_DCN30(0) -}; - -static const struct dcn_hubbub_shift hubbub_shift = { - HUBBUB_MASK_SH_LIST_DCN30(__SHIFT) -}; - -static const struct dcn_hubbub_mask hubbub_mask = { - HUBBUB_MASK_SH_LIST_DCN30(_MASK) -}; - -#define vmid_regs(id)\ - [id] = { DCN20_VMID_REG_LIST(id) } - -static const struct dcn_vmid_registers vmid_regs[] = { - vmid_regs(0), - vmid_regs(1), - vmid_regs(2), - vmid_regs(3), - vmid_regs(4), - vmid_regs(5), - vmid_regs(6), - vmid_regs(7), - vmid_regs(8), - vmid_regs(9), - vmid_regs(10), - vmid_regs(11), - vmid_regs(12), - vmid_regs(13), - vmid_regs(14), - vmid_regs(15) -}; - -static const struct dcn20_vmid_shift vmid_shifts = { - DCN20_VMID_MASK_SH_LIST(__SHIFT) -}; - -static const struct dcn20_vmid_mask vmid_masks = { - DCN20_VMID_MASK_SH_LIST(_MASK) -}; - -static struct hubbub *dcn303_hubbub_create(struct dc_context *ctx) -{ - int i; - - struct dcn20_hubbub *hubbub3 = kzalloc(sizeof(struct dcn20_hubbub), GFP_KERNEL); - - if (!hubbub3) - return NULL; - - hubbub3_construct(hubbub3, ctx, &hubbub_reg, &hubbub_shift, &hubbub_mask); - - for (i = 0; i < res_cap_dcn303.num_vmid; i++) { - struct dcn20_vmid *vmid = &hubbub3->vmid[i]; - - vmid->ctx = ctx; - - vmid->regs = &vmid_regs[i]; - vmid->shifts = &vmid_shifts; - vmid->masks = &vmid_masks; - } - - return &hubbub3->base; -} - -#define vpg_regs(id)\ - [id] = { VPG_DCN3_REG_LIST(id) } - -static const struct dcn30_vpg_registers vpg_regs[] = { - vpg_regs(0), - vpg_regs(1), - vpg_regs(2) -}; - -static const struct dcn30_vpg_shift vpg_shift = { - DCN3_VPG_MASK_SH_LIST(__SHIFT) -}; - -static const struct dcn30_vpg_mask vpg_mask = { - DCN3_VPG_MASK_SH_LIST(_MASK) -}; - -static struct vpg *dcn303_vpg_create(struct dc_context *ctx, uint32_t inst) -{ - struct dcn30_vpg *vpg3 = kzalloc(sizeof(struct dcn30_vpg), GFP_KERNEL); - - if (!vpg3) - return NULL; - - vpg3_construct(vpg3, ctx, inst, &vpg_regs[inst], &vpg_shift, &vpg_mask); - - return &vpg3->base; -} - -#define afmt_regs(id)\ - [id] = { AFMT_DCN3_REG_LIST(id) } - -static const struct dcn30_afmt_registers afmt_regs[] = { - afmt_regs(0), - afmt_regs(1), - afmt_regs(2) -}; - -static const struct dcn30_afmt_shift afmt_shift = { - DCN3_AFMT_MASK_SH_LIST(__SHIFT) -}; - -static const struct dcn30_afmt_mask afmt_mask = { - DCN3_AFMT_MASK_SH_LIST(_MASK) -}; - -static struct afmt *dcn303_afmt_create(struct dc_context *ctx, uint32_t inst) -{ - struct dcn30_afmt *afmt3 = kzalloc(sizeof(struct dcn30_afmt), GFP_KERNEL); - - if (!afmt3) - return NULL; - - afmt3_construct(afmt3, ctx, inst, &afmt_regs[inst], &afmt_shift, &afmt_mask); - - return &afmt3->base; -} - -#define audio_regs(id)\ - [id] = { AUD_COMMON_REG_LIST(id) } - -static const struct dce_audio_registers audio_regs[] = { - audio_regs(0), - audio_regs(1), - audio_regs(2), - audio_regs(3), - audio_regs(4), - audio_regs(5), - audio_regs(6) -}; - -#define DCE120_AUD_COMMON_MASK_SH_LIST(mask_sh)\ - SF(AZF0ENDPOINT0_AZALIA_F0_CODEC_ENDPOINT_INDEX, AZALIA_ENDPOINT_REG_INDEX, mask_sh),\ - SF(AZF0ENDPOINT0_AZALIA_F0_CODEC_ENDPOINT_DATA, AZALIA_ENDPOINT_REG_DATA, mask_sh),\ - AUD_COMMON_MASK_SH_LIST_BASE(mask_sh) - -static const struct dce_audio_shift audio_shift = { - DCE120_AUD_COMMON_MASK_SH_LIST(__SHIFT) -}; - -static const struct dce_audio_mask audio_mask = { - DCE120_AUD_COMMON_MASK_SH_LIST(_MASK) -}; - -static struct audio *dcn303_create_audio(struct dc_context *ctx, unsigned int inst) -{ - return dce_audio_create(ctx, inst, &audio_regs[inst], &audio_shift, &audio_mask); -} - -#define stream_enc_regs(id)\ - [id] = { SE_DCN3_REG_LIST(id) } - -static const struct dcn10_stream_enc_registers stream_enc_regs[] = { - stream_enc_regs(0), - stream_enc_regs(1) -}; - -static const struct dcn10_stream_encoder_shift se_shift = { - SE_COMMON_MASK_SH_LIST_DCN30(__SHIFT) -}; - -static const struct dcn10_stream_encoder_mask se_mask = { - SE_COMMON_MASK_SH_LIST_DCN30(_MASK) -}; - -static struct stream_encoder *dcn303_stream_encoder_create(enum engine_id eng_id, struct dc_context *ctx) -{ - struct dcn10_stream_encoder *enc1; - struct vpg *vpg; - struct afmt *afmt; - int vpg_inst; - int afmt_inst; - - /* Mapping of VPG, AFMT, DME register blocks to DIO block instance */ - if (eng_id <= ENGINE_ID_DIGB) { - vpg_inst = eng_id; - afmt_inst = eng_id; - } else - return NULL; - - enc1 = kzalloc(sizeof(struct dcn10_stream_encoder), GFP_KERNEL); - vpg = dcn303_vpg_create(ctx, vpg_inst); - afmt = dcn303_afmt_create(ctx, afmt_inst); - - if (!enc1 || !vpg || !afmt) { - kfree(enc1); - kfree(vpg); - kfree(afmt); - return NULL; - } - - dcn30_dio_stream_encoder_construct(enc1, ctx, ctx->dc_bios, eng_id, vpg, afmt, &stream_enc_regs[eng_id], - &se_shift, &se_mask); - - return &enc1->base; -} - -#define clk_src_regs(index, pllid)\ - [index] = { CS_COMMON_REG_LIST_DCN3_03(index, pllid) } - -static const struct dce110_clk_src_regs clk_src_regs[] = { - clk_src_regs(0, A), - clk_src_regs(1, B) -}; - -static const struct dce110_clk_src_shift cs_shift = { - CS_COMMON_MASK_SH_LIST_DCN2_0(__SHIFT) -}; - -static const struct dce110_clk_src_mask cs_mask = { - CS_COMMON_MASK_SH_LIST_DCN2_0(_MASK) -}; - -static struct clock_source *dcn303_clock_source_create(struct dc_context *ctx, struct dc_bios *bios, - enum clock_source_id id, const struct dce110_clk_src_regs *regs, bool dp_clk_src) -{ - struct dce110_clk_src *clk_src = kzalloc(sizeof(struct dce110_clk_src), GFP_KERNEL); - - if (!clk_src) - return NULL; - - if (dcn3_clk_src_construct(clk_src, ctx, bios, id, regs, &cs_shift, &cs_mask)) { - clk_src->base.dp_clk_src = dp_clk_src; - return &clk_src->base; - } - - kfree(clk_src); - BREAK_TO_DEBUGGER(); - return NULL; -} - -static const struct dce_hwseq_registers hwseq_reg = { - HWSEQ_DCN303_REG_LIST() -}; - -static const struct dce_hwseq_shift hwseq_shift = { - HWSEQ_DCN303_MASK_SH_LIST(__SHIFT) -}; - -static const struct dce_hwseq_mask hwseq_mask = { - HWSEQ_DCN303_MASK_SH_LIST(_MASK) -}; - -static struct dce_hwseq *dcn303_hwseq_create(struct dc_context *ctx) -{ - struct dce_hwseq *hws = kzalloc(sizeof(struct dce_hwseq), GFP_KERNEL); - - if (hws) { - hws->ctx = ctx; - hws->regs = &hwseq_reg; - hws->shifts = &hwseq_shift; - hws->masks = &hwseq_mask; - } - return hws; -} - -#define hubp_regs(id)\ - [id] = { HUBP_REG_LIST_DCN30(id) } - -static const struct dcn_hubp2_registers hubp_regs[] = { - hubp_regs(0), - hubp_regs(1) -}; - -static const struct dcn_hubp2_shift hubp_shift = { - HUBP_MASK_SH_LIST_DCN30(__SHIFT) -}; - -static const struct dcn_hubp2_mask hubp_mask = { - HUBP_MASK_SH_LIST_DCN30(_MASK) -}; - -static struct hubp *dcn303_hubp_create(struct dc_context *ctx, uint32_t inst) -{ - struct dcn20_hubp *hubp2 = kzalloc(sizeof(struct dcn20_hubp), GFP_KERNEL); - - if (!hubp2) - return NULL; - - if (hubp3_construct(hubp2, ctx, inst, &hubp_regs[inst], &hubp_shift, &hubp_mask)) - return &hubp2->base; - - BREAK_TO_DEBUGGER(); - kfree(hubp2); - return NULL; -} - -#define dpp_regs(id)\ - [id] = { DPP_REG_LIST_DCN30(id) } - -static const struct dcn3_dpp_registers dpp_regs[] = { - dpp_regs(0), - dpp_regs(1) -}; - -static const struct dcn3_dpp_shift tf_shift = { - DPP_REG_LIST_SH_MASK_DCN30(__SHIFT) -}; - -static const struct dcn3_dpp_mask tf_mask = { - DPP_REG_LIST_SH_MASK_DCN30(_MASK) -}; - -static struct dpp *dcn303_dpp_create(struct dc_context *ctx, uint32_t inst) -{ - struct dcn3_dpp *dpp = kzalloc(sizeof(struct dcn3_dpp), GFP_KERNEL); - - if (!dpp) - return NULL; - - if (dpp3_construct(dpp, ctx, inst, &dpp_regs[inst], &tf_shift, &tf_mask)) - return &dpp->base; - - BREAK_TO_DEBUGGER(); - kfree(dpp); - return NULL; -} - -#define opp_regs(id)\ - [id] = { OPP_REG_LIST_DCN30(id) } - -static const struct dcn20_opp_registers opp_regs[] = { - opp_regs(0), - opp_regs(1) -}; - -static const struct dcn20_opp_shift opp_shift = { - OPP_MASK_SH_LIST_DCN20(__SHIFT) -}; - -static const struct dcn20_opp_mask opp_mask = { - OPP_MASK_SH_LIST_DCN20(_MASK) -}; - -static struct output_pixel_processor *dcn303_opp_create(struct dc_context *ctx, uint32_t inst) -{ - struct dcn20_opp *opp = kzalloc(sizeof(struct dcn20_opp), GFP_KERNEL); - - if (!opp) { - BREAK_TO_DEBUGGER(); - return NULL; - } - - dcn20_opp_construct(opp, ctx, inst, &opp_regs[inst], &opp_shift, &opp_mask); - return &opp->base; -} - -#define optc_regs(id)\ - [id] = { OPTC_COMMON_REG_LIST_DCN3_0(id) } - -static const struct dcn_optc_registers optc_regs[] = { - optc_regs(0), - optc_regs(1) -}; - -static const struct dcn_optc_shift optc_shift = { - OPTC_COMMON_MASK_SH_LIST_DCN30(__SHIFT) -}; - -static const struct dcn_optc_mask optc_mask = { - OPTC_COMMON_MASK_SH_LIST_DCN30(_MASK) -}; - -static struct timing_generator *dcn303_timing_generator_create(struct dc_context *ctx, uint32_t instance) -{ - struct optc *tgn10 = kzalloc(sizeof(struct optc), GFP_KERNEL); - - if (!tgn10) - return NULL; - - tgn10->base.inst = instance; - tgn10->base.ctx = ctx; - - tgn10->tg_regs = &optc_regs[instance]; - tgn10->tg_shift = &optc_shift; - tgn10->tg_mask = &optc_mask; - - dcn30_timing_generator_init(tgn10); - - return &tgn10->base; -} - -static const struct dcn30_mpc_registers mpc_regs = { - MPC_REG_LIST_DCN3_0(0), - MPC_REG_LIST_DCN3_0(1), - MPC_OUT_MUX_REG_LIST_DCN3_0(0), - MPC_OUT_MUX_REG_LIST_DCN3_0(1), - MPC_RMU_GLOBAL_REG_LIST_DCN3AG, - MPC_RMU_REG_LIST_DCN3AG(0), - MPC_DWB_MUX_REG_LIST_DCN3_0(0), -}; - -static const struct dcn30_mpc_shift mpc_shift = { - MPC_COMMON_MASK_SH_LIST_DCN303(__SHIFT) -}; - -static const struct dcn30_mpc_mask mpc_mask = { - MPC_COMMON_MASK_SH_LIST_DCN303(_MASK) -}; - -static struct mpc *dcn303_mpc_create(struct dc_context *ctx, int num_mpcc, int num_rmu) -{ - struct dcn30_mpc *mpc30 = kzalloc(sizeof(struct dcn30_mpc), GFP_KERNEL); - - if (!mpc30) - return NULL; - - dcn30_mpc_construct(mpc30, ctx, &mpc_regs, &mpc_shift, &mpc_mask, num_mpcc, num_rmu); - - return &mpc30->base; -} - -#define dsc_regsDCN20(id)\ -[id] = { DSC_REG_LIST_DCN20(id) } - -static const struct dcn20_dsc_registers dsc_regs[] = { - dsc_regsDCN20(0), - dsc_regsDCN20(1) -}; - -static const struct dcn20_dsc_shift dsc_shift = { - DSC_REG_LIST_SH_MASK_DCN20(__SHIFT) -}; - -static const struct dcn20_dsc_mask dsc_mask = { - DSC_REG_LIST_SH_MASK_DCN20(_MASK) -}; - -static struct display_stream_compressor *dcn303_dsc_create(struct dc_context *ctx, uint32_t inst) -{ - struct dcn20_dsc *dsc = kzalloc(sizeof(struct dcn20_dsc), GFP_KERNEL); - - if (!dsc) { - BREAK_TO_DEBUGGER(); - return NULL; - } - - dsc2_construct(dsc, ctx, inst, &dsc_regs[inst], &dsc_shift, &dsc_mask); - return &dsc->base; -} - -#define dwbc_regs_dcn3(id)\ -[id] = { DWBC_COMMON_REG_LIST_DCN30(id) } - -static const struct dcn30_dwbc_registers dwbc30_regs[] = { - dwbc_regs_dcn3(0) -}; - -static const struct dcn30_dwbc_shift dwbc30_shift = { - DWBC_COMMON_MASK_SH_LIST_DCN30(__SHIFT) -}; - -static const struct dcn30_dwbc_mask dwbc30_mask = { - DWBC_COMMON_MASK_SH_LIST_DCN30(_MASK) -}; - -static bool dcn303_dwbc_create(struct dc_context *ctx, struct resource_pool *pool) -{ - int i; - uint32_t pipe_count = pool->res_cap->num_dwb; - - for (i = 0; i < pipe_count; i++) { - struct dcn30_dwbc *dwbc30 = kzalloc(sizeof(struct dcn30_dwbc), GFP_KERNEL); - - if (!dwbc30) { - dm_error("DC: failed to create dwbc30!\n"); - return false; - } - - dcn30_dwbc_construct(dwbc30, ctx, &dwbc30_regs[i], &dwbc30_shift, &dwbc30_mask, i); - - pool->dwbc[i] = &dwbc30->base; - } - return true; -} - -#define mcif_wb_regs_dcn3(id)\ -[id] = { MCIF_WB_COMMON_REG_LIST_DCN30(id) } - -static const struct dcn30_mmhubbub_registers mcif_wb30_regs[] = { - mcif_wb_regs_dcn3(0) -}; - -static const struct dcn30_mmhubbub_shift mcif_wb30_shift = { - MCIF_WB_COMMON_MASK_SH_LIST_DCN30(__SHIFT) -}; - -static const struct dcn30_mmhubbub_mask mcif_wb30_mask = { - MCIF_WB_COMMON_MASK_SH_LIST_DCN30(_MASK) -}; - -static bool dcn303_mmhubbub_create(struct dc_context *ctx, struct resource_pool *pool) -{ - int i; - uint32_t pipe_count = pool->res_cap->num_dwb; - - for (i = 0; i < pipe_count; i++) { - struct dcn30_mmhubbub *mcif_wb30 = kzalloc(sizeof(struct dcn30_mmhubbub), GFP_KERNEL); - - if (!mcif_wb30) { - dm_error("DC: failed to create mcif_wb30!\n"); - return false; - } - - dcn30_mmhubbub_construct(mcif_wb30, ctx, &mcif_wb30_regs[i], &mcif_wb30_shift, &mcif_wb30_mask, i); - - pool->mcif_wb[i] = &mcif_wb30->base; - } - return true; -} - -#define aux_engine_regs(id)\ -[id] = {\ - AUX_COMMON_REG_LIST0(id), \ - .AUXN_IMPCAL = 0, \ - .AUXP_IMPCAL = 0, \ - .AUX_RESET_MASK = DP_AUX0_AUX_CONTROL__AUX_RESET_MASK, \ -} - -static const struct dce110_aux_registers aux_engine_regs[] = { - aux_engine_regs(0), - aux_engine_regs(1) -}; - -static const struct dce110_aux_registers_shift aux_shift = { - DCN_AUX_MASK_SH_LIST(__SHIFT) -}; - -static const struct dce110_aux_registers_mask aux_mask = { - DCN_AUX_MASK_SH_LIST(_MASK) -}; - -static struct dce_aux *dcn303_aux_engine_create(struct dc_context *ctx, uint32_t inst) -{ - struct aux_engine_dce110 *aux_engine = kzalloc(sizeof(struct aux_engine_dce110), GFP_KERNEL); - - if (!aux_engine) - return NULL; - - dce110_aux_engine_construct(aux_engine, ctx, inst, SW_AUX_TIMEOUT_PERIOD_MULTIPLIER * AUX_TIMEOUT_PERIOD, - &aux_engine_regs[inst], &aux_mask, &aux_shift, ctx->dc->caps.extended_aux_timeout_support); - - return &aux_engine->base; -} - -#define i2c_inst_regs(id) { I2C_HW_ENGINE_COMMON_REG_LIST(id) } - -static const struct dce_i2c_registers i2c_hw_regs[] = { - i2c_inst_regs(1), - i2c_inst_regs(2) -}; - -static const struct dce_i2c_shift i2c_shifts = { - I2C_COMMON_MASK_SH_LIST_DCN2(__SHIFT) -}; - -static const struct dce_i2c_mask i2c_masks = { - I2C_COMMON_MASK_SH_LIST_DCN2(_MASK) -}; - -static struct dce_i2c_hw *dcn303_i2c_hw_create(struct dc_context *ctx, uint32_t inst) -{ - struct dce_i2c_hw *dce_i2c_hw = kzalloc(sizeof(struct dce_i2c_hw), GFP_KERNEL); - - if (!dce_i2c_hw) - return NULL; - - dcn2_i2c_hw_construct(dce_i2c_hw, ctx, inst, &i2c_hw_regs[inst], &i2c_shifts, &i2c_masks); - - return dce_i2c_hw; -} - -static const struct encoder_feature_support link_enc_feature = { - .max_hdmi_deep_color = COLOR_DEPTH_121212, - .max_hdmi_pixel_clock = 600000, - .hdmi_ycbcr420_supported = true, - .dp_ycbcr420_supported = true, - .fec_supported = true, - .flags.bits.IS_HBR2_CAPABLE = true, - .flags.bits.IS_HBR3_CAPABLE = true, - .flags.bits.IS_TPS3_CAPABLE = true, - .flags.bits.IS_TPS4_CAPABLE = true -}; - -#define link_regs(id, phyid)\ - [id] = {\ - LE_DCN3_REG_LIST(id), \ - UNIPHY_DCN2_REG_LIST(phyid), \ - SRI(DP_DPHY_INTERNAL_CTRL, DP, id) \ - } - -static const struct dcn10_link_enc_registers link_enc_regs[] = { - link_regs(0, A), - link_regs(1, B) -}; - -static const struct dcn10_link_enc_shift le_shift = { - LINK_ENCODER_MASK_SH_LIST_DCN30(__SHIFT), - DPCS_DCN2_MASK_SH_LIST(__SHIFT) -}; - -static const struct dcn10_link_enc_mask le_mask = { - LINK_ENCODER_MASK_SH_LIST_DCN30(_MASK), - DPCS_DCN2_MASK_SH_LIST(_MASK) -}; - -#define aux_regs(id)\ - [id] = { DCN2_AUX_REG_LIST(id) } - -static const struct dcn10_link_enc_aux_registers link_enc_aux_regs[] = { - aux_regs(0), - aux_regs(1) -}; - -#define hpd_regs(id)\ - [id] = { HPD_REG_LIST(id) } - -static const struct dcn10_link_enc_hpd_registers link_enc_hpd_regs[] = { - hpd_regs(0), - hpd_regs(1) -}; - -static struct link_encoder *dcn303_link_encoder_create( - struct dc_context *ctx, - const struct encoder_init_data *enc_init_data) -{ - struct dcn20_link_encoder *enc20 = kzalloc(sizeof(struct dcn20_link_encoder), GFP_KERNEL); - - if (!enc20) - return NULL; - - dcn30_link_encoder_construct(enc20, enc_init_data, &link_enc_feature, - &link_enc_regs[enc_init_data->transmitter], &link_enc_aux_regs[enc_init_data->channel - 1], - &link_enc_hpd_regs[enc_init_data->hpd_source], &le_shift, &le_mask); - - return &enc20->enc10.base; -} - -static const struct dce_panel_cntl_registers panel_cntl_regs[] = { - { DCN_PANEL_CNTL_REG_LIST() } -}; - -static const struct dce_panel_cntl_shift panel_cntl_shift = { - DCE_PANEL_CNTL_MASK_SH_LIST(__SHIFT) -}; - -static const struct dce_panel_cntl_mask panel_cntl_mask = { - DCE_PANEL_CNTL_MASK_SH_LIST(_MASK) -}; - -static struct panel_cntl *dcn303_panel_cntl_create(const struct panel_cntl_init_data *init_data) -{ - struct dce_panel_cntl *panel_cntl = kzalloc(sizeof(struct dce_panel_cntl), GFP_KERNEL); - - if (!panel_cntl) - return NULL; - - dce_panel_cntl_construct(panel_cntl, init_data, &panel_cntl_regs[init_data->inst], - &panel_cntl_shift, &panel_cntl_mask); - - return &panel_cntl->base; -} - -static void read_dce_straps(struct dc_context *ctx, struct resource_straps *straps) -{ - generic_reg_get(ctx, mmDC_PINSTRAPS + BASE(mmDC_PINSTRAPS_BASE_IDX), - FN(DC_PINSTRAPS, DC_PINSTRAPS_AUDIO), &straps->dc_pinstraps_audio); -} - -static const struct resource_create_funcs res_create_funcs = { - .read_dce_straps = read_dce_straps, - .create_audio = dcn303_create_audio, - .create_stream_encoder = dcn303_stream_encoder_create, - .create_hwseq = dcn303_hwseq_create, -}; - -static bool is_soc_bounding_box_valid(struct dc *dc) -{ - uint32_t hw_internal_rev = dc->ctx->asic_id.hw_internal_rev; - - if (ASICREV_IS_BEIGE_GOBY_P(hw_internal_rev)) - return true; - - return false; -} - -static bool init_soc_bounding_box(struct dc *dc, struct resource_pool *pool) -{ - struct _vcs_dpi_soc_bounding_box_st *loaded_bb = &dcn3_03_soc; - struct _vcs_dpi_ip_params_st *loaded_ip = &dcn3_03_ip; - - DC_LOGGER_INIT(dc->ctx->logger); - - if (!is_soc_bounding_box_valid(dc)) { - DC_LOG_ERROR("%s: not valid soc bounding box/n", __func__); - return false; - } - - loaded_ip->max_num_otg = pool->pipe_count; - loaded_ip->max_num_dpp = pool->pipe_count; - loaded_ip->clamp_min_dcfclk = dc->config.clamp_min_dcfclk; - DC_FP_START(); - dcn20_patch_bounding_box(dc, loaded_bb); - DC_FP_END(); - - 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) { - DC_FP_START(); - dcn303_fpu_init_soc_bounding_box(bb_info); - DC_FP_END(); - } - } - - return true; -} - -static void dcn303_resource_destruct(struct resource_pool *pool) -{ - unsigned int i; - - for (i = 0; i < pool->stream_enc_count; i++) { - if (pool->stream_enc[i] != NULL) { - if (pool->stream_enc[i]->vpg != NULL) { - kfree(DCN30_VPG_FROM_VPG(pool->stream_enc[i]->vpg)); - pool->stream_enc[i]->vpg = NULL; - } - if (pool->stream_enc[i]->afmt != NULL) { - kfree(DCN30_AFMT_FROM_AFMT(pool->stream_enc[i]->afmt)); - pool->stream_enc[i]->afmt = NULL; - } - kfree(DCN10STRENC_FROM_STRENC(pool->stream_enc[i])); - pool->stream_enc[i] = NULL; - } - } - - for (i = 0; i < pool->res_cap->num_dsc; i++) { - if (pool->dscs[i] != NULL) - dcn20_dsc_destroy(&pool->dscs[i]); - } - - if (pool->mpc != NULL) { - kfree(TO_DCN20_MPC(pool->mpc)); - pool->mpc = NULL; - } - - if (pool->hubbub != NULL) { - kfree(pool->hubbub); - pool->hubbub = NULL; - } - - for (i = 0; i < pool->pipe_count; i++) { - if (pool->dpps[i] != NULL) { - kfree(TO_DCN20_DPP(pool->dpps[i])); - pool->dpps[i] = NULL; - } - - if (pool->hubps[i] != NULL) { - kfree(TO_DCN20_HUBP(pool->hubps[i])); - pool->hubps[i] = NULL; - } - - if (pool->irqs != NULL) - dal_irq_service_destroy(&pool->irqs); - } - - for (i = 0; i < pool->res_cap->num_ddc; i++) { - if (pool->engines[i] != NULL) - dce110_engine_destroy(&pool->engines[i]); - if (pool->hw_i2cs[i] != NULL) { - kfree(pool->hw_i2cs[i]); - pool->hw_i2cs[i] = NULL; - } - if (pool->sw_i2cs[i] != NULL) { - kfree(pool->sw_i2cs[i]); - pool->sw_i2cs[i] = NULL; - } - } - - for (i = 0; i < pool->res_cap->num_opp; i++) { - if (pool->opps[i] != NULL) - pool->opps[i]->funcs->opp_destroy(&pool->opps[i]); - } - - for (i = 0; i < pool->res_cap->num_timing_generator; i++) { - if (pool->timing_generators[i] != NULL) { - kfree(DCN10TG_FROM_TG(pool->timing_generators[i])); - pool->timing_generators[i] = NULL; - } - } - - for (i = 0; i < pool->res_cap->num_dwb; i++) { - if (pool->dwbc[i] != NULL) { - kfree(TO_DCN30_DWBC(pool->dwbc[i])); - pool->dwbc[i] = NULL; - } - if (pool->mcif_wb[i] != NULL) { - kfree(TO_DCN30_MMHUBBUB(pool->mcif_wb[i])); - pool->mcif_wb[i] = NULL; - } - } - - for (i = 0; i < pool->audio_count; i++) { - if (pool->audios[i]) - dce_aud_destroy(&pool->audios[i]); - } - - for (i = 0; i < pool->clk_src_count; i++) { - if (pool->clock_sources[i] != NULL) - dcn20_clock_source_destroy(&pool->clock_sources[i]); - } - - if (pool->dp_clock_source != NULL) - dcn20_clock_source_destroy(&pool->dp_clock_source); - - for (i = 0; i < pool->res_cap->num_mpc_3dlut; i++) { - if (pool->mpc_lut[i] != NULL) { - dc_3dlut_func_release(pool->mpc_lut[i]); - pool->mpc_lut[i] = NULL; - } - if (pool->mpc_shaper[i] != NULL) { - dc_transfer_func_release(pool->mpc_shaper[i]); - pool->mpc_shaper[i] = NULL; - } - } - - for (i = 0; i < pool->pipe_count; i++) { - if (pool->multiple_abms[i] != NULL) - dce_abm_destroy(&pool->multiple_abms[i]); - } - - if (pool->psr != NULL) - dmub_psr_destroy(&pool->psr); - - if (pool->dccg != NULL) - dcn_dccg_destroy(&pool->dccg); - - if (pool->oem_device != NULL) { - struct dc *dc = pool->oem_device->ctx->dc; - - dc->link_srv->destroy_ddc_service(&pool->oem_device); - } -} - -static void dcn303_destroy_resource_pool(struct resource_pool **pool) -{ - dcn303_resource_destruct(*pool); - kfree(*pool); - *pool = NULL; -} - -static void dcn303_get_panel_config_defaults(struct dc_panel_config *panel_config) -{ - *panel_config = panel_config_defaults; -} - -void dcn303_update_bw_bounding_box(struct dc *dc, struct clk_bw_params *bw_params) -{ - DC_FP_START(); - dcn303_fpu_update_bw_bounding_box(dc, bw_params); - DC_FP_END(); -} - -static struct resource_funcs dcn303_res_pool_funcs = { - .destroy = dcn303_destroy_resource_pool, - .link_enc_create = dcn303_link_encoder_create, - .panel_cntl_create = dcn303_panel_cntl_create, - .validate_bandwidth = dcn30_validate_bandwidth, - .calculate_wm_and_dlg = dcn30_calculate_wm_and_dlg, - .update_soc_for_wm_a = dcn30_update_soc_for_wm_a, - .populate_dml_pipes = dcn30_populate_dml_pipes_from_context, - .acquire_free_pipe_as_secondary_dpp_pipe = dcn20_acquire_free_pipe_for_layer, - .release_pipe = dcn20_release_pipe, - .add_stream_to_ctx = dcn30_add_stream_to_ctx, - .add_dsc_to_stream_resource = dcn20_add_dsc_to_stream_resource, - .remove_stream_from_ctx = dcn20_remove_stream_from_ctx, - .populate_dml_writeback_from_context = dcn30_populate_dml_writeback_from_context, - .set_mcif_arb_params = dcn30_set_mcif_arb_params, - .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 = dcn303_update_bw_bounding_box, - .patch_unknown_plane_state = dcn20_patch_unknown_plane_state, - .get_panel_config_defaults = dcn303_get_panel_config_defaults, -}; - -static struct dc_cap_funcs cap_funcs = { - .get_dcc_compression_cap = dcn20_get_dcc_compression_cap -}; - -static const struct bios_registers bios_regs = { - NBIO_SR(BIOS_SCRATCH_3), - NBIO_SR(BIOS_SCRATCH_6) -}; - -static const struct dccg_registers dccg_regs = { - DCCG_REG_LIST_DCN3_03() -}; - -static const struct dccg_shift dccg_shift = { - DCCG_MASK_SH_LIST_DCN3_03(__SHIFT) -}; - -static const struct dccg_mask dccg_mask = { - DCCG_MASK_SH_LIST_DCN3_03(_MASK) -}; - -#define abm_regs(id)\ - [id] = { ABM_DCN302_REG_LIST(id) } - -static const struct dce_abm_registers abm_regs[] = { - abm_regs(0), - abm_regs(1) -}; - -static const struct dce_abm_shift abm_shift = { - ABM_MASK_SH_LIST_DCN30(__SHIFT) -}; - -static const struct dce_abm_mask abm_mask = { - ABM_MASK_SH_LIST_DCN30(_MASK) -}; - -static bool dcn303_resource_construct( - uint8_t num_virtual_links, - struct dc *dc, - struct resource_pool *pool) -{ - int i; - struct dc_context *ctx = dc->ctx; - struct irq_service_init_data init_data; - struct ddc_service_init_data ddc_init_data; - - ctx->dc_bios->regs = &bios_regs; - - pool->res_cap = &res_cap_dcn303; - - pool->funcs = &dcn303_res_pool_funcs; - - /************************************************* - * Resource + asic cap harcoding * - *************************************************/ - pool->underlay_pipe_index = NO_UNDERLAY_PIPE; - pool->pipe_count = pool->res_cap->num_timing_generator; - pool->mpcc_count = pool->res_cap->num_timing_generator; - dc->caps.max_downscale_ratio = 600; - dc->caps.i2c_speed_in_khz = 100; - dc->caps.i2c_speed_in_khz_hdcp = 5; /*1.4 w/a applied by derfault*/ - 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 * - 1024 * 1024; - 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; - dc->caps.extended_aux_timeout_support = true; - dc->caps.dmcub_support = true; - dc->caps.max_v_total = (1 << 15) - 1; - - /* Color pipeline capabilities */ - dc->caps.color.dpp.dcn_arch = 1; - dc->caps.color.dpp.input_lut_shared = 0; - dc->caps.color.dpp.icsc = 1; - dc->caps.color.dpp.dgam_ram = 0; // must use gamma_corr - dc->caps.color.dpp.dgam_rom_caps.srgb = 1; - dc->caps.color.dpp.dgam_rom_caps.bt2020 = 1; - dc->caps.color.dpp.dgam_rom_caps.gamma2_2 = 1; - dc->caps.color.dpp.dgam_rom_caps.pq = 1; - dc->caps.color.dpp.dgam_rom_caps.hlg = 1; - dc->caps.color.dpp.post_csc = 1; - dc->caps.color.dpp.gamma_corr = 1; - dc->caps.color.dpp.dgam_rom_for_yuv = 0; - - dc->caps.color.dpp.hw_3d_lut = 1; - dc->caps.color.dpp.ogam_ram = 1; - // no OGAM ROM on DCN3 - dc->caps.color.dpp.ogam_rom_caps.srgb = 0; - dc->caps.color.dpp.ogam_rom_caps.bt2020 = 0; - dc->caps.color.dpp.ogam_rom_caps.gamma2_2 = 0; - dc->caps.color.dpp.ogam_rom_caps.pq = 0; - dc->caps.color.dpp.ogam_rom_caps.hlg = 0; - dc->caps.color.dpp.ocsc = 0; - - dc->caps.color.mpc.gamut_remap = 1; - dc->caps.color.mpc.num_3dluts = pool->res_cap->num_mpc_3dlut; //3 - dc->caps.color.mpc.ogam_ram = 1; - dc->caps.color.mpc.ogam_rom_caps.srgb = 0; - dc->caps.color.mpc.ogam_rom_caps.bt2020 = 0; - dc->caps.color.mpc.ogam_rom_caps.gamma2_2 = 0; - dc->caps.color.mpc.ogam_rom_caps.pq = 0; - dc->caps.color.mpc.ogam_rom_caps.hlg = 0; - dc->caps.color.mpc.ocsc = 1; - - dc->caps.dp_hdmi21_pcon_support = true; - - dc->config.dc_mode_clk_limit_support = true; - /* read VBIOS LTTPR caps */ - if (ctx->dc_bios->funcs->get_lttpr_caps) { - enum bp_result bp_query_result; - uint8_t is_vbios_lttpr_enable = 0; - - bp_query_result = ctx->dc_bios->funcs->get_lttpr_caps(ctx->dc_bios, &is_vbios_lttpr_enable); - dc->caps.vbios_lttpr_enable = (bp_query_result == BP_RESULT_OK) && !!is_vbios_lttpr_enable; - } - - if (ctx->dc_bios->funcs->get_lttpr_interop) { - enum bp_result bp_query_result; - uint8_t is_vbios_interop_enabled = 0; - - bp_query_result = ctx->dc_bios->funcs->get_lttpr_interop(ctx->dc_bios, &is_vbios_interop_enabled); - dc->caps.vbios_lttpr_aware = (bp_query_result == BP_RESULT_OK) && !!is_vbios_interop_enabled; - } - - if (dc->ctx->dce_environment == DCE_ENV_PRODUCTION_DRV) - dc->debug = debug_defaults_drv; - - // Init the vm_helper - if (dc->vm_helper) - vm_helper_init(dc->vm_helper, 16); - - /************************************************* - * Create resources * - *************************************************/ - - /* Clock Sources for Pixel Clock*/ - pool->clock_sources[DCN303_CLK_SRC_PLL0] = - dcn303_clock_source_create(ctx, ctx->dc_bios, - CLOCK_SOURCE_COMBO_PHY_PLL0, - &clk_src_regs[0], false); - pool->clock_sources[DCN303_CLK_SRC_PLL1] = - dcn303_clock_source_create(ctx, ctx->dc_bios, - CLOCK_SOURCE_COMBO_PHY_PLL1, - &clk_src_regs[1], false); - - pool->clk_src_count = DCN303_CLK_SRC_TOTAL; - - /* todo: not reuse phy_pll registers */ - pool->dp_clock_source = - dcn303_clock_source_create(ctx, ctx->dc_bios, - CLOCK_SOURCE_ID_DP_DTO, - &clk_src_regs[0], true); - - for (i = 0; i < pool->clk_src_count; i++) { - if (pool->clock_sources[i] == NULL) { - dm_error("DC: failed to create clock sources!\n"); - BREAK_TO_DEBUGGER(); - goto create_fail; - } - } - - /* DCCG */ - pool->dccg = dccg30_create(ctx, &dccg_regs, &dccg_shift, &dccg_mask); - if (pool->dccg == NULL) { - dm_error("DC: failed to create dccg!\n"); - BREAK_TO_DEBUGGER(); - goto create_fail; - } - - /* PP Lib and SMU interfaces */ - init_soc_bounding_box(dc, pool); - - /* DML */ - dml_init_instance(&dc->dml, &dcn3_03_soc, &dcn3_03_ip, DML_PROJECT_DCN30); - - /* IRQ */ - init_data.ctx = dc->ctx; - pool->irqs = dal_irq_service_dcn303_create(&init_data); - if (!pool->irqs) - goto create_fail; - - /* HUBBUB */ - pool->hubbub = dcn303_hubbub_create(ctx); - if (pool->hubbub == NULL) { - BREAK_TO_DEBUGGER(); - dm_error("DC: failed to create hubbub!\n"); - goto create_fail; - } - - /* HUBPs, DPPs, OPPs and TGs */ - for (i = 0; i < pool->pipe_count; i++) { - pool->hubps[i] = dcn303_hubp_create(ctx, i); - if (pool->hubps[i] == NULL) { - BREAK_TO_DEBUGGER(); - dm_error("DC: failed to create hubps!\n"); - goto create_fail; - } - - pool->dpps[i] = dcn303_dpp_create(ctx, i); - if (pool->dpps[i] == NULL) { - BREAK_TO_DEBUGGER(); - dm_error("DC: failed to create dpps!\n"); - goto create_fail; - } - } - - for (i = 0; i < pool->res_cap->num_opp; i++) { - pool->opps[i] = dcn303_opp_create(ctx, i); - if (pool->opps[i] == NULL) { - BREAK_TO_DEBUGGER(); - dm_error("DC: failed to create output pixel processor!\n"); - goto create_fail; - } - } - - for (i = 0; i < pool->res_cap->num_timing_generator; i++) { - pool->timing_generators[i] = dcn303_timing_generator_create(ctx, i); - if (pool->timing_generators[i] == NULL) { - BREAK_TO_DEBUGGER(); - dm_error("DC: failed to create tg!\n"); - goto create_fail; - } - } - pool->timing_generator_count = i; - - /* PSR */ - pool->psr = dmub_psr_create(ctx); - if (pool->psr == NULL) { - dm_error("DC: failed to create psr!\n"); - BREAK_TO_DEBUGGER(); - goto create_fail; - } - - /* ABM */ - for (i = 0; i < pool->res_cap->num_timing_generator; i++) { - pool->multiple_abms[i] = dmub_abm_create(ctx, &abm_regs[i], &abm_shift, &abm_mask); - if (pool->multiple_abms[i] == NULL) { - dm_error("DC: failed to create abm for pipe %d!\n", i); - BREAK_TO_DEBUGGER(); - goto create_fail; - } - } - - /* MPC and DSC */ - pool->mpc = dcn303_mpc_create(ctx, pool->mpcc_count, pool->res_cap->num_mpc_3dlut); - if (pool->mpc == NULL) { - BREAK_TO_DEBUGGER(); - dm_error("DC: failed to create mpc!\n"); - goto create_fail; - } - - for (i = 0; i < pool->res_cap->num_dsc; i++) { - pool->dscs[i] = dcn303_dsc_create(ctx, i); - if (pool->dscs[i] == NULL) { - BREAK_TO_DEBUGGER(); - dm_error("DC: failed to create display stream compressor %d!\n", i); - goto create_fail; - } - } - - /* DWB and MMHUBBUB */ - if (!dcn303_dwbc_create(ctx, pool)) { - BREAK_TO_DEBUGGER(); - dm_error("DC: failed to create dwbc!\n"); - goto create_fail; - } - - if (!dcn303_mmhubbub_create(ctx, pool)) { - BREAK_TO_DEBUGGER(); - dm_error("DC: failed to create mcif_wb!\n"); - goto create_fail; - } - - /* AUX and I2C */ - for (i = 0; i < pool->res_cap->num_ddc; i++) { - pool->engines[i] = dcn303_aux_engine_create(ctx, i); - if (pool->engines[i] == NULL) { - BREAK_TO_DEBUGGER(); - dm_error("DC:failed to create aux engine!!\n"); - goto create_fail; - } - pool->hw_i2cs[i] = dcn303_i2c_hw_create(ctx, i); - if (pool->hw_i2cs[i] == NULL) { - BREAK_TO_DEBUGGER(); - dm_error("DC:failed to create hw i2c!!\n"); - goto create_fail; - } - pool->sw_i2cs[i] = NULL; - } - - /* Audio, Stream Encoders including HPO and virtual, MPC 3D LUTs */ - if (!resource_construct(num_virtual_links, dc, pool, - &res_create_funcs)) - goto create_fail; - - /* HW Sequencer and Plane caps */ - dcn303_hw_sequencer_construct(dc); - - dc->caps.max_planes = pool->pipe_count; - - for (i = 0; i < dc->caps.max_planes; ++i) - dc->caps.planes[i] = plane_cap; - - dc->cap_funcs = cap_funcs; - - if (dc->ctx->dc_bios->fw_info.oem_i2c_present) { - ddc_init_data.ctx = dc->ctx; - ddc_init_data.link = NULL; - ddc_init_data.id.id = dc->ctx->dc_bios->fw_info.oem_i2c_obj_id; - ddc_init_data.id.enum_id = 0; - ddc_init_data.id.type = OBJECT_TYPE_GENERIC; - pool->oem_device = dc->link_srv->create_ddc_service(&ddc_init_data); - } else { - pool->oem_device = NULL; - } - - return true; - -create_fail: - - dcn303_resource_destruct(pool); - - return false; -} - -struct resource_pool *dcn303_create_resource_pool(const struct dc_init_data *init_data, struct dc *dc) -{ - struct resource_pool *pool = kzalloc(sizeof(struct resource_pool), GFP_KERNEL); - - if (!pool) - return NULL; - - if (dcn303_resource_construct(init_data->num_virtual_links, dc, pool)) - return pool; - - BREAK_TO_DEBUGGER(); - kfree(pool); - return NULL; -} diff --git a/drivers/gpu/drm/amd/display/dc/dcn303/dcn303_resource.h b/drivers/gpu/drm/amd/display/dc/dcn303/dcn303_resource.h deleted file mode 100644 index 37cf1525820b..000000000000 --- a/drivers/gpu/drm/amd/display/dc/dcn303/dcn303_resource.h +++ /dev/null @@ -1,38 +0,0 @@ -// SPDX-License-Identifier: MIT -/* - * Copyright (C) 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 _DCN303_RESOURCE_H_ -#define _DCN303_RESOURCE_H_ - -#include "core_types.h" - -extern struct _vcs_dpi_ip_params_st dcn3_03_ip; -extern struct _vcs_dpi_soc_bounding_box_st dcn3_03_soc; - -struct resource_pool *dcn303_create_resource_pool(const struct dc_init_data *init_data, struct dc *dc); - -void dcn303_update_bw_bounding_box(struct dc *dc, struct clk_bw_params *bw_params); - -#endif /* _DCN303_RESOURCE_H_ */ diff --git a/drivers/gpu/drm/amd/display/dc/dcn31/Makefile b/drivers/gpu/drm/amd/display/dc/dcn31/Makefile index 96e45c9efb46..212287008c0a 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn31/Makefile +++ b/drivers/gpu/drm/amd/display/dc/dcn31/Makefile @@ -10,7 +10,7 @@ # # Makefile for dcn31. -DCN31 = dcn31_resource.o dcn31_hubbub.o dcn31_init.o dcn31_hubp.o \ +DCN31 = dcn31_hubbub.o dcn31_init.o dcn31_hubp.o \ dcn31_dccg.o dcn31_optc.o dcn31_dio_link_encoder.o dcn31_panel_cntl.o \ dcn31_apg.o dcn31_hpo_dp_stream_encoder.o dcn31_hpo_dp_link_encoder.o \ dcn31_afmt.o dcn31_vpg.o diff --git a/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_resource.c b/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_resource.c deleted file mode 100644 index 79416cfb22f0..000000000000 --- a/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_resource.c +++ /dev/null @@ -1,2218 +0,0 @@ -/* - * 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 - * - */ - - -#include "dm_services.h" -#include "dc.h" - -#include "dcn31/dcn31_init.h" - -#include "resource.h" -#include "include/irq_service_interface.h" -#include "dcn31_resource.h" - -#include "dcn20/dcn20_resource.h" -#include "dcn30/dcn30_resource.h" - -#include "dml/dcn30/dcn30_fpu.h" - -#include "dcn10/dcn10_ipp.h" -#include "dcn30/dcn30_hubbub.h" -#include "dcn31/dcn31_hubbub.h" -#include "dcn30/dcn30_mpc.h" -#include "dcn31/dcn31_hubp.h" -#include "irq/dcn31/irq_service_dcn31.h" -#include "dcn30/dcn30_dpp.h" -#include "dcn31/dcn31_optc.h" -#include "dcn20/dcn20_hwseq.h" -#include "dcn30/dcn30_hwseq.h" -#include "dce110/dce110_hwseq.h" -#include "dcn30/dcn30_opp.h" -#include "dcn20/dcn20_dsc.h" -#include "dcn30/dcn30_vpg.h" -#include "dcn30/dcn30_afmt.h" -#include "dcn30/dcn30_dio_stream_encoder.h" -#include "dcn31/dcn31_hpo_dp_stream_encoder.h" -#include "dcn31/dcn31_hpo_dp_link_encoder.h" -#include "dcn31/dcn31_apg.h" -#include "dcn31/dcn31_dio_link_encoder.h" -#include "dcn31/dcn31_vpg.h" -#include "dcn31/dcn31_afmt.h" -#include "dce/dce_clock_source.h" -#include "dce/dce_audio.h" -#include "dce/dce_hwseq.h" -#include "clk_mgr.h" -#include "virtual/virtual_stream_encoder.h" -#include "dce110/dce110_resource.h" -#include "dml/display_mode_vba.h" -#include "dml/dcn31/dcn31_fpu.h" -#include "dcn31/dcn31_dccg.h" -#include "dcn10/dcn10_resource.h" -#include "dcn31_panel_cntl.h" - -#include "dcn30/dcn30_dwb.h" -#include "dcn30/dcn30_mmhubbub.h" - -// TODO: change include headers /amd/include/asic_reg after upstream -#include "yellow_carp_offset.h" -#include "dcn/dcn_3_1_2_offset.h" -#include "dcn/dcn_3_1_2_sh_mask.h" -#include "nbio/nbio_7_2_0_offset.h" -#include "dpcs/dpcs_4_2_0_offset.h" -#include "dpcs/dpcs_4_2_0_sh_mask.h" -#include "mmhub/mmhub_2_3_0_offset.h" -#include "mmhub/mmhub_2_3_0_sh_mask.h" - - -#define regDCHUBBUB_DEBUG_CTRL_0 0x04d6 -#define regDCHUBBUB_DEBUG_CTRL_0_BASE_IDX 2 -#define DCHUBBUB_DEBUG_CTRL_0__DET_DEPTH__SHIFT 0x10 -#define DCHUBBUB_DEBUG_CTRL_0__DET_DEPTH_MASK 0x01FF0000L - -#include "reg_helper.h" -#include "dce/dmub_abm.h" -#include "dce/dmub_psr.h" -#include "dce/dce_aux.h" -#include "dce/dce_i2c.h" -#include "dce/dmub_replay.h" - -#include "dml/dcn30/display_mode_vba_30.h" -#include "vm_helper.h" -#include "dcn20/dcn20_vmid.h" - -#include "link_enc_cfg.h" - -#define DC_LOGGER \ - dc->ctx->logger -#define DC_LOGGER_INIT(logger) - -enum dcn31_clk_src_array_id { - DCN31_CLK_SRC_PLL0, - DCN31_CLK_SRC_PLL1, - DCN31_CLK_SRC_PLL2, - DCN31_CLK_SRC_PLL3, - DCN31_CLK_SRC_PLL4, - DCN30_CLK_SRC_TOTAL -}; - -/* begin ********************* - * macros to expend register list macro defined in HW object header file - */ - -/* DCN */ -#define BASE_INNER(seg) DCN_BASE__INST0_SEG ## seg - -#define BASE(seg) BASE_INNER(seg) - -#define SR(reg_name)\ - .reg_name = BASE(reg ## reg_name ## _BASE_IDX) + \ - reg ## reg_name - -#define SRI(reg_name, block, id)\ - .reg_name = BASE(reg ## block ## id ## _ ## reg_name ## _BASE_IDX) + \ - reg ## block ## id ## _ ## reg_name - -#define SRI2(reg_name, block, id)\ - .reg_name = BASE(reg ## reg_name ## _BASE_IDX) + \ - reg ## reg_name - -#define SRIR(var_name, reg_name, block, id)\ - .var_name = BASE(reg ## block ## id ## _ ## reg_name ## _BASE_IDX) + \ - reg ## block ## id ## _ ## reg_name - -#define SRII(reg_name, block, id)\ - .reg_name[id] = BASE(reg ## block ## id ## _ ## reg_name ## _BASE_IDX) + \ - reg ## block ## id ## _ ## reg_name - -#define SRII_MPC_RMU(reg_name, block, id)\ - .RMU##_##reg_name[id] = BASE(reg ## block ## id ## _ ## reg_name ## _BASE_IDX) + \ - reg ## block ## id ## _ ## reg_name - -#define SRII_DWB(reg_name, temp_name, block, id)\ - .reg_name[id] = BASE(reg ## block ## id ## _ ## temp_name ## _BASE_IDX) + \ - reg ## block ## id ## _ ## temp_name - -#define SF_DWB2(reg_name, block, id, field_name, post_fix) \ - .field_name = reg_name ## __ ## field_name ## post_fix - -#define DCCG_SRII(reg_name, block, id)\ - .block ## _ ## reg_name[id] = BASE(reg ## block ## id ## _ ## reg_name ## _BASE_IDX) + \ - reg ## block ## id ## _ ## reg_name - -#define VUPDATE_SRII(reg_name, block, id)\ - .reg_name[id] = BASE(reg ## reg_name ## _ ## block ## id ## _BASE_IDX) + \ - reg ## reg_name ## _ ## block ## id - -/* NBIO */ -#define NBIO_BASE_INNER(seg) \ - NBIO_BASE__INST0_SEG ## seg - -#define NBIO_BASE(seg) \ - NBIO_BASE_INNER(seg) - -#define NBIO_SR(reg_name)\ - .reg_name = NBIO_BASE(regBIF_BX1_ ## reg_name ## _BASE_IDX) + \ - regBIF_BX1_ ## reg_name - -/* MMHUB */ -#define MMHUB_BASE_INNER(seg) \ - MMHUB_BASE__INST0_SEG ## seg - -#define MMHUB_BASE(seg) \ - MMHUB_BASE_INNER(seg) - -#define MMHUB_SR(reg_name)\ - .reg_name = MMHUB_BASE(mm ## reg_name ## _BASE_IDX) + \ - mm ## reg_name - -/* CLOCK */ -#define CLK_BASE_INNER(seg) \ - CLK_BASE__INST0_SEG ## seg - -#define CLK_BASE(seg) \ - CLK_BASE_INNER(seg) - -#define CLK_SRI(reg_name, block, inst)\ - .reg_name = CLK_BASE(reg ## block ## _ ## inst ## _ ## reg_name ## _BASE_IDX) + \ - reg ## block ## _ ## inst ## _ ## reg_name - - -static const struct bios_registers bios_regs = { - NBIO_SR(BIOS_SCRATCH_3), - NBIO_SR(BIOS_SCRATCH_6) -}; - -#define clk_src_regs(index, pllid)\ -[index] = {\ - CS_COMMON_REG_LIST_DCN3_0(index, pllid),\ -} - -static const struct dce110_clk_src_regs clk_src_regs[] = { - clk_src_regs(0, A), - clk_src_regs(1, B), - clk_src_regs(2, C), - clk_src_regs(3, D), - clk_src_regs(4, E) -}; -/*pll_id being rempped in dmub, in driver it is logical instance*/ -static const struct dce110_clk_src_regs clk_src_regs_b0[] = { - clk_src_regs(0, A), - clk_src_regs(1, B), - clk_src_regs(2, F), - clk_src_regs(3, G), - clk_src_regs(4, E) -}; - -static const struct dce110_clk_src_shift cs_shift = { - CS_COMMON_MASK_SH_LIST_DCN2_0(__SHIFT) -}; - -static const struct dce110_clk_src_mask cs_mask = { - CS_COMMON_MASK_SH_LIST_DCN2_0(_MASK) -}; - -#define abm_regs(id)\ -[id] = {\ - ABM_DCN302_REG_LIST(id)\ -} - -static const struct dce_abm_registers abm_regs[] = { - abm_regs(0), - abm_regs(1), - abm_regs(2), - abm_regs(3), -}; - -static const struct dce_abm_shift abm_shift = { - ABM_MASK_SH_LIST_DCN30(__SHIFT) -}; - -static const struct dce_abm_mask abm_mask = { - ABM_MASK_SH_LIST_DCN30(_MASK) -}; - -#define audio_regs(id)\ -[id] = {\ - AUD_COMMON_REG_LIST(id)\ -} - -static const struct dce_audio_registers audio_regs[] = { - audio_regs(0), - audio_regs(1), - audio_regs(2), - audio_regs(3), - audio_regs(4), - audio_regs(5), - audio_regs(6) -}; - -#define DCE120_AUD_COMMON_MASK_SH_LIST(mask_sh)\ - SF(AZF0ENDPOINT0_AZALIA_F0_CODEC_ENDPOINT_INDEX, AZALIA_ENDPOINT_REG_INDEX, mask_sh),\ - SF(AZF0ENDPOINT0_AZALIA_F0_CODEC_ENDPOINT_DATA, AZALIA_ENDPOINT_REG_DATA, mask_sh),\ - AUD_COMMON_MASK_SH_LIST_BASE(mask_sh) - -static const struct dce_audio_shift audio_shift = { - DCE120_AUD_COMMON_MASK_SH_LIST(__SHIFT) -}; - -static const struct dce_audio_mask audio_mask = { - DCE120_AUD_COMMON_MASK_SH_LIST(_MASK) -}; - -#define vpg_regs(id)\ -[id] = {\ - VPG_DCN31_REG_LIST(id)\ -} - -static const struct dcn31_vpg_registers vpg_regs[] = { - vpg_regs(0), - vpg_regs(1), - vpg_regs(2), - vpg_regs(3), - vpg_regs(4), - vpg_regs(5), - vpg_regs(6), - vpg_regs(7), - vpg_regs(8), - vpg_regs(9), -}; - -static const struct dcn31_vpg_shift vpg_shift = { - DCN31_VPG_MASK_SH_LIST(__SHIFT) -}; - -static const struct dcn31_vpg_mask vpg_mask = { - DCN31_VPG_MASK_SH_LIST(_MASK) -}; - -#define afmt_regs(id)\ -[id] = {\ - AFMT_DCN31_REG_LIST(id)\ -} - -static const struct dcn31_afmt_registers afmt_regs[] = { - afmt_regs(0), - afmt_regs(1), - afmt_regs(2), - afmt_regs(3), - afmt_regs(4), - afmt_regs(5) -}; - -static const struct dcn31_afmt_shift afmt_shift = { - DCN31_AFMT_MASK_SH_LIST(__SHIFT) -}; - -static const struct dcn31_afmt_mask afmt_mask = { - DCN31_AFMT_MASK_SH_LIST(_MASK) -}; - -#define apg_regs(id)\ -[id] = {\ - APG_DCN31_REG_LIST(id)\ -} - -static const struct dcn31_apg_registers apg_regs[] = { - apg_regs(0), - apg_regs(1), - apg_regs(2), - apg_regs(3) -}; - -static const struct dcn31_apg_shift apg_shift = { - DCN31_APG_MASK_SH_LIST(__SHIFT) -}; - -static const struct dcn31_apg_mask apg_mask = { - DCN31_APG_MASK_SH_LIST(_MASK) -}; - -#define stream_enc_regs(id)\ -[id] = {\ - SE_DCN3_REG_LIST(id)\ -} - -/* Some encoders won't be initialized here - but they're logical, not physical. */ -static const struct dcn10_stream_enc_registers stream_enc_regs[ENGINE_ID_COUNT] = { - stream_enc_regs(0), - stream_enc_regs(1), - stream_enc_regs(2), - stream_enc_regs(3), - stream_enc_regs(4) -}; - -static const struct dcn10_stream_encoder_shift se_shift = { - SE_COMMON_MASK_SH_LIST_DCN30(__SHIFT) -}; - -static const struct dcn10_stream_encoder_mask se_mask = { - SE_COMMON_MASK_SH_LIST_DCN30(_MASK) -}; - - -#define aux_regs(id)\ -[id] = {\ - DCN2_AUX_REG_LIST(id)\ -} - -static const struct dcn10_link_enc_aux_registers link_enc_aux_regs[] = { - aux_regs(0), - aux_regs(1), - aux_regs(2), - aux_regs(3), - aux_regs(4) -}; - -#define hpd_regs(id)\ -[id] = {\ - HPD_REG_LIST(id)\ -} - -static const struct dcn10_link_enc_hpd_registers link_enc_hpd_regs[] = { - hpd_regs(0), - hpd_regs(1), - hpd_regs(2), - hpd_regs(3), - hpd_regs(4) -}; - -#define link_regs(id, phyid)\ -[id] = {\ - LE_DCN31_REG_LIST(id), \ - UNIPHY_DCN2_REG_LIST(phyid), \ - DPCS_DCN31_REG_LIST(id), \ -} - -static const struct dce110_aux_registers_shift aux_shift = { - DCN_AUX_MASK_SH_LIST(__SHIFT) -}; - -static const struct dce110_aux_registers_mask aux_mask = { - DCN_AUX_MASK_SH_LIST(_MASK) -}; - -static const struct dcn10_link_enc_registers link_enc_regs[] = { - link_regs(0, A), - link_regs(1, B), - link_regs(2, C), - link_regs(3, D), - link_regs(4, E) -}; - -static const struct dcn10_link_enc_shift le_shift = { - LINK_ENCODER_MASK_SH_LIST_DCN31(__SHIFT), \ - DPCS_DCN31_MASK_SH_LIST(__SHIFT) -}; - -static const struct dcn10_link_enc_mask le_mask = { - LINK_ENCODER_MASK_SH_LIST_DCN31(_MASK), \ - DPCS_DCN31_MASK_SH_LIST(_MASK) -}; - -#define hpo_dp_stream_encoder_reg_list(id)\ -[id] = {\ - DCN3_1_HPO_DP_STREAM_ENC_REG_LIST(id)\ -} - -static const struct dcn31_hpo_dp_stream_encoder_registers hpo_dp_stream_enc_regs[] = { - hpo_dp_stream_encoder_reg_list(0), - hpo_dp_stream_encoder_reg_list(1), - hpo_dp_stream_encoder_reg_list(2), - hpo_dp_stream_encoder_reg_list(3), -}; - -static const struct dcn31_hpo_dp_stream_encoder_shift hpo_dp_se_shift = { - DCN3_1_HPO_DP_STREAM_ENC_MASK_SH_LIST(__SHIFT) -}; - -static const struct dcn31_hpo_dp_stream_encoder_mask hpo_dp_se_mask = { - DCN3_1_HPO_DP_STREAM_ENC_MASK_SH_LIST(_MASK) -}; - -#define hpo_dp_link_encoder_reg_list(id)\ -[id] = {\ - DCN3_1_HPO_DP_LINK_ENC_REG_LIST(id),\ - DCN3_1_RDPCSTX_REG_LIST(0),\ - DCN3_1_RDPCSTX_REG_LIST(1),\ - DCN3_1_RDPCSTX_REG_LIST(2),\ - DCN3_1_RDPCSTX_REG_LIST(3),\ - DCN3_1_RDPCSTX_REG_LIST(4)\ -} - -static const struct dcn31_hpo_dp_link_encoder_registers hpo_dp_link_enc_regs[] = { - hpo_dp_link_encoder_reg_list(0), - hpo_dp_link_encoder_reg_list(1), -}; - -static const struct dcn31_hpo_dp_link_encoder_shift hpo_dp_le_shift = { - DCN3_1_HPO_DP_LINK_ENC_MASK_SH_LIST(__SHIFT) -}; - -static const struct dcn31_hpo_dp_link_encoder_mask hpo_dp_le_mask = { - DCN3_1_HPO_DP_LINK_ENC_MASK_SH_LIST(_MASK) -}; - -#define dpp_regs(id)\ -[id] = {\ - DPP_REG_LIST_DCN30(id),\ -} - -static const struct dcn3_dpp_registers dpp_regs[] = { - dpp_regs(0), - dpp_regs(1), - dpp_regs(2), - dpp_regs(3) -}; - -static const struct dcn3_dpp_shift tf_shift = { - DPP_REG_LIST_SH_MASK_DCN30(__SHIFT) -}; - -static const struct dcn3_dpp_mask tf_mask = { - DPP_REG_LIST_SH_MASK_DCN30(_MASK) -}; - -#define opp_regs(id)\ -[id] = {\ - OPP_REG_LIST_DCN30(id),\ -} - -static const struct dcn20_opp_registers opp_regs[] = { - opp_regs(0), - opp_regs(1), - opp_regs(2), - opp_regs(3) -}; - -static const struct dcn20_opp_shift opp_shift = { - OPP_MASK_SH_LIST_DCN20(__SHIFT) -}; - -static const struct dcn20_opp_mask opp_mask = { - OPP_MASK_SH_LIST_DCN20(_MASK) -}; - -#define aux_engine_regs(id)\ -[id] = {\ - AUX_COMMON_REG_LIST0(id), \ - .AUXN_IMPCAL = 0, \ - .AUXP_IMPCAL = 0, \ - .AUX_RESET_MASK = DP_AUX0_AUX_CONTROL__AUX_RESET_MASK, \ -} - -static const struct dce110_aux_registers aux_engine_regs[] = { - aux_engine_regs(0), - aux_engine_regs(1), - aux_engine_regs(2), - aux_engine_regs(3), - aux_engine_regs(4) -}; - -#define dwbc_regs_dcn3(id)\ -[id] = {\ - DWBC_COMMON_REG_LIST_DCN30(id),\ -} - -static const struct dcn30_dwbc_registers dwbc30_regs[] = { - dwbc_regs_dcn3(0), -}; - -static const struct dcn30_dwbc_shift dwbc30_shift = { - DWBC_COMMON_MASK_SH_LIST_DCN30(__SHIFT) -}; - -static const struct dcn30_dwbc_mask dwbc30_mask = { - DWBC_COMMON_MASK_SH_LIST_DCN30(_MASK) -}; - -#define mcif_wb_regs_dcn3(id)\ -[id] = {\ - MCIF_WB_COMMON_REG_LIST_DCN30(id),\ -} - -static const struct dcn30_mmhubbub_registers mcif_wb30_regs[] = { - mcif_wb_regs_dcn3(0) -}; - -static const struct dcn30_mmhubbub_shift mcif_wb30_shift = { - MCIF_WB_COMMON_MASK_SH_LIST_DCN30(__SHIFT) -}; - -static const struct dcn30_mmhubbub_mask mcif_wb30_mask = { - MCIF_WB_COMMON_MASK_SH_LIST_DCN30(_MASK) -}; - -#define dsc_regsDCN20(id)\ -[id] = {\ - DSC_REG_LIST_DCN20(id)\ -} - -static const struct dcn20_dsc_registers dsc_regs[] = { - dsc_regsDCN20(0), - dsc_regsDCN20(1), - dsc_regsDCN20(2) -}; - -static const struct dcn20_dsc_shift dsc_shift = { - DSC_REG_LIST_SH_MASK_DCN20(__SHIFT) -}; - -static const struct dcn20_dsc_mask dsc_mask = { - DSC_REG_LIST_SH_MASK_DCN20(_MASK) -}; - -static const struct dcn30_mpc_registers mpc_regs = { - MPC_REG_LIST_DCN3_0(0), - MPC_REG_LIST_DCN3_0(1), - MPC_REG_LIST_DCN3_0(2), - MPC_REG_LIST_DCN3_0(3), - MPC_OUT_MUX_REG_LIST_DCN3_0(0), - MPC_OUT_MUX_REG_LIST_DCN3_0(1), - MPC_OUT_MUX_REG_LIST_DCN3_0(2), - MPC_OUT_MUX_REG_LIST_DCN3_0(3), - MPC_RMU_GLOBAL_REG_LIST_DCN3AG, - MPC_RMU_REG_LIST_DCN3AG(0), - MPC_RMU_REG_LIST_DCN3AG(1), - //MPC_RMU_REG_LIST_DCN3AG(2), - MPC_DWB_MUX_REG_LIST_DCN3_0(0), -}; - -static const struct dcn30_mpc_shift mpc_shift = { - MPC_COMMON_MASK_SH_LIST_DCN30(__SHIFT) -}; - -static const struct dcn30_mpc_mask mpc_mask = { - MPC_COMMON_MASK_SH_LIST_DCN30(_MASK) -}; - -#define optc_regs(id)\ -[id] = {OPTC_COMMON_REG_LIST_DCN3_1(id)} - -static const struct dcn_optc_registers optc_regs[] = { - optc_regs(0), - optc_regs(1), - optc_regs(2), - optc_regs(3) -}; - -static const struct dcn_optc_shift optc_shift = { - OPTC_COMMON_MASK_SH_LIST_DCN3_1(__SHIFT) -}; - -static const struct dcn_optc_mask optc_mask = { - OPTC_COMMON_MASK_SH_LIST_DCN3_1(_MASK) -}; - -#define hubp_regs(id)\ -[id] = {\ - HUBP_REG_LIST_DCN30(id)\ -} - -static const struct dcn_hubp2_registers hubp_regs[] = { - hubp_regs(0), - hubp_regs(1), - hubp_regs(2), - hubp_regs(3) -}; - - -static const struct dcn_hubp2_shift hubp_shift = { - HUBP_MASK_SH_LIST_DCN31(__SHIFT) -}; - -static const struct dcn_hubp2_mask hubp_mask = { - HUBP_MASK_SH_LIST_DCN31(_MASK) -}; -static const struct dcn_hubbub_registers hubbub_reg = { - HUBBUB_REG_LIST_DCN31(0) -}; - -static const struct dcn_hubbub_shift hubbub_shift = { - HUBBUB_MASK_SH_LIST_DCN31(__SHIFT) -}; - -static const struct dcn_hubbub_mask hubbub_mask = { - HUBBUB_MASK_SH_LIST_DCN31(_MASK) -}; - -static const struct dccg_registers dccg_regs = { - DCCG_REG_LIST_DCN31() -}; - -static const struct dccg_shift dccg_shift = { - DCCG_MASK_SH_LIST_DCN31(__SHIFT) -}; - -static const struct dccg_mask dccg_mask = { - DCCG_MASK_SH_LIST_DCN31(_MASK) -}; - - -#define SRII2(reg_name_pre, reg_name_post, id)\ - .reg_name_pre ## _ ## reg_name_post[id] = BASE(reg ## reg_name_pre \ - ## id ## _ ## reg_name_post ## _BASE_IDX) + \ - reg ## reg_name_pre ## id ## _ ## reg_name_post - - -#define HWSEQ_DCN31_REG_LIST()\ - SR(DCHUBBUB_GLOBAL_TIMER_CNTL), \ - SR(DCHUBBUB_ARB_HOSTVM_CNTL), \ - SR(DIO_MEM_PWR_CTRL), \ - SR(ODM_MEM_PWR_CTRL3), \ - SR(DMU_MEM_PWR_CNTL), \ - SR(MMHUBBUB_MEM_PWR_CNTL), \ - SR(DCCG_GATE_DISABLE_CNTL), \ - SR(DCCG_GATE_DISABLE_CNTL2), \ - SR(DCFCLK_CNTL),\ - SR(DC_MEM_GLOBAL_PWR_REQ_CNTL), \ - SRII(PIXEL_RATE_CNTL, OTG, 0), \ - SRII(PIXEL_RATE_CNTL, OTG, 1),\ - SRII(PIXEL_RATE_CNTL, OTG, 2),\ - SRII(PIXEL_RATE_CNTL, OTG, 3),\ - SRII(PHYPLL_PIXEL_RATE_CNTL, OTG, 0),\ - SRII(PHYPLL_PIXEL_RATE_CNTL, OTG, 1),\ - SRII(PHYPLL_PIXEL_RATE_CNTL, OTG, 2),\ - SRII(PHYPLL_PIXEL_RATE_CNTL, OTG, 3),\ - SR(MICROSECOND_TIME_BASE_DIV), \ - SR(MILLISECOND_TIME_BASE_DIV), \ - SR(DISPCLK_FREQ_CHANGE_CNTL), \ - SR(RBBMIF_TIMEOUT_DIS), \ - SR(RBBMIF_TIMEOUT_DIS_2), \ - SR(DCHUBBUB_CRC_CTRL), \ - SR(DPP_TOP0_DPP_CRC_CTRL), \ - SR(DPP_TOP0_DPP_CRC_VAL_B_A), \ - SR(DPP_TOP0_DPP_CRC_VAL_R_G), \ - SR(MPC_CRC_CTRL), \ - SR(MPC_CRC_RESULT_GB), \ - SR(MPC_CRC_RESULT_C), \ - SR(MPC_CRC_RESULT_AR), \ - SR(DOMAIN0_PG_CONFIG), \ - SR(DOMAIN1_PG_CONFIG), \ - SR(DOMAIN2_PG_CONFIG), \ - SR(DOMAIN3_PG_CONFIG), \ - SR(DOMAIN16_PG_CONFIG), \ - SR(DOMAIN17_PG_CONFIG), \ - SR(DOMAIN18_PG_CONFIG), \ - SR(DOMAIN0_PG_STATUS), \ - SR(DOMAIN1_PG_STATUS), \ - SR(DOMAIN2_PG_STATUS), \ - SR(DOMAIN3_PG_STATUS), \ - SR(DOMAIN16_PG_STATUS), \ - SR(DOMAIN17_PG_STATUS), \ - SR(DOMAIN18_PG_STATUS), \ - SR(D1VGA_CONTROL), \ - SR(D2VGA_CONTROL), \ - SR(D3VGA_CONTROL), \ - SR(D4VGA_CONTROL), \ - SR(D5VGA_CONTROL), \ - SR(D6VGA_CONTROL), \ - SR(DC_IP_REQUEST_CNTL), \ - SR(AZALIA_AUDIO_DTO), \ - SR(AZALIA_CONTROLLER_CLOCK_GATING), \ - SR(HPO_TOP_HW_CONTROL) - -static const struct dce_hwseq_registers hwseq_reg = { - HWSEQ_DCN31_REG_LIST() -}; - -#define HWSEQ_DCN31_MASK_SH_LIST(mask_sh)\ - HWSEQ_DCN_MASK_SH_LIST(mask_sh), \ - HWS_SF(, DCHUBBUB_GLOBAL_TIMER_CNTL, DCHUBBUB_GLOBAL_TIMER_REFDIV, mask_sh), \ - HWS_SF(, DCHUBBUB_ARB_HOSTVM_CNTL, DISABLE_HOSTVM_FORCE_ALLOW_PSTATE, mask_sh), \ - HWS_SF(, DOMAIN0_PG_CONFIG, DOMAIN_POWER_FORCEON, mask_sh), \ - HWS_SF(, DOMAIN0_PG_CONFIG, DOMAIN_POWER_GATE, mask_sh), \ - HWS_SF(, DOMAIN1_PG_CONFIG, DOMAIN_POWER_FORCEON, mask_sh), \ - HWS_SF(, DOMAIN1_PG_CONFIG, DOMAIN_POWER_GATE, mask_sh), \ - HWS_SF(, DOMAIN2_PG_CONFIG, DOMAIN_POWER_FORCEON, mask_sh), \ - HWS_SF(, DOMAIN2_PG_CONFIG, DOMAIN_POWER_GATE, mask_sh), \ - HWS_SF(, DOMAIN3_PG_CONFIG, DOMAIN_POWER_FORCEON, mask_sh), \ - HWS_SF(, DOMAIN3_PG_CONFIG, DOMAIN_POWER_GATE, mask_sh), \ - HWS_SF(, DOMAIN16_PG_CONFIG, DOMAIN_POWER_FORCEON, mask_sh), \ - HWS_SF(, DOMAIN16_PG_CONFIG, DOMAIN_POWER_GATE, mask_sh), \ - HWS_SF(, DOMAIN17_PG_CONFIG, DOMAIN_POWER_FORCEON, mask_sh), \ - HWS_SF(, DOMAIN17_PG_CONFIG, DOMAIN_POWER_GATE, mask_sh), \ - HWS_SF(, DOMAIN18_PG_CONFIG, DOMAIN_POWER_FORCEON, mask_sh), \ - HWS_SF(, DOMAIN18_PG_CONFIG, DOMAIN_POWER_GATE, mask_sh), \ - HWS_SF(, DOMAIN0_PG_STATUS, DOMAIN_PGFSM_PWR_STATUS, mask_sh), \ - HWS_SF(, DOMAIN1_PG_STATUS, DOMAIN_PGFSM_PWR_STATUS, mask_sh), \ - HWS_SF(, DOMAIN2_PG_STATUS, DOMAIN_PGFSM_PWR_STATUS, mask_sh), \ - HWS_SF(, DOMAIN3_PG_STATUS, DOMAIN_PGFSM_PWR_STATUS, mask_sh), \ - HWS_SF(, DOMAIN16_PG_STATUS, DOMAIN_PGFSM_PWR_STATUS, mask_sh), \ - HWS_SF(, DOMAIN17_PG_STATUS, DOMAIN_PGFSM_PWR_STATUS, mask_sh), \ - HWS_SF(, DOMAIN18_PG_STATUS, DOMAIN_PGFSM_PWR_STATUS, mask_sh), \ - HWS_SF(, DC_IP_REQUEST_CNTL, IP_REQUEST_EN, mask_sh), \ - HWS_SF(, AZALIA_AUDIO_DTO, AZALIA_AUDIO_DTO_MODULE, mask_sh), \ - HWS_SF(, HPO_TOP_CLOCK_CONTROL, HPO_HDMISTREAMCLK_G_GATE_DIS, mask_sh), \ - HWS_SF(, DMU_MEM_PWR_CNTL, DMCU_ERAM_MEM_PWR_FORCE, mask_sh), \ - HWS_SF(, ODM_MEM_PWR_CTRL3, ODM_MEM_UNASSIGNED_PWR_MODE, mask_sh), \ - HWS_SF(, ODM_MEM_PWR_CTRL3, ODM_MEM_VBLANK_PWR_MODE, mask_sh), \ - HWS_SF(, MMHUBBUB_MEM_PWR_CNTL, VGA_MEM_PWR_FORCE, mask_sh), \ - HWS_SF(, DIO_MEM_PWR_CTRL, I2C_LIGHT_SLEEP_FORCE, mask_sh), \ - HWS_SF(, HPO_TOP_HW_CONTROL, HPO_IO_EN, mask_sh) - -static const struct dce_hwseq_shift hwseq_shift = { - HWSEQ_DCN31_MASK_SH_LIST(__SHIFT) -}; - -static const struct dce_hwseq_mask hwseq_mask = { - HWSEQ_DCN31_MASK_SH_LIST(_MASK) -}; -#define vmid_regs(id)\ -[id] = {\ - DCN20_VMID_REG_LIST(id)\ -} - -static const struct dcn_vmid_registers vmid_regs[] = { - vmid_regs(0), - vmid_regs(1), - vmid_regs(2), - vmid_regs(3), - vmid_regs(4), - vmid_regs(5), - vmid_regs(6), - vmid_regs(7), - vmid_regs(8), - vmid_regs(9), - vmid_regs(10), - vmid_regs(11), - vmid_regs(12), - vmid_regs(13), - vmid_regs(14), - vmid_regs(15) -}; - -static const struct dcn20_vmid_shift vmid_shifts = { - DCN20_VMID_MASK_SH_LIST(__SHIFT) -}; - -static const struct dcn20_vmid_mask vmid_masks = { - DCN20_VMID_MASK_SH_LIST(_MASK) -}; - -static const struct resource_caps res_cap_dcn31 = { - .num_timing_generator = 4, - .num_opp = 4, - .num_video_plane = 4, - .num_audio = 5, - .num_stream_encoder = 5, - .num_dig_link_enc = 5, - .num_hpo_dp_stream_encoder = 4, - .num_hpo_dp_link_encoder = 2, - .num_pll = 5, - .num_dwb = 1, - .num_ddc = 5, - .num_vmid = 16, - .num_mpc_3dlut = 2, - .num_dsc = 3, -}; - -static const struct dc_plane_cap plane_cap = { - .type = DC_PLANE_TYPE_DCN_UNIVERSAL, - .per_pixel_alpha = true, - - .pixel_format_support = { - .argb8888 = true, - .nv12 = true, - .fp16 = true, - .p010 = true, - .ayuv = false, - }, - - .max_upscale_factor = { - .argb8888 = 16000, - .nv12 = 16000, - .fp16 = 16000 - }, - - // 6:1 downscaling ratio: 1000/6 = 166.666 - .max_downscale_factor = { - .argb8888 = 167, - .nv12 = 167, - .fp16 = 167 - }, - 64, - 64 -}; - -static const struct dc_debug_options debug_defaults_drv = { - .disable_dmcu = true, - .force_abm_enable = false, - .timing_trace = false, - .clock_trace = true, - .disable_pplib_clock_request = false, - .pipe_split_policy = MPC_SPLIT_DYNAMIC, - .force_single_disp_pipe_split = false, - .disable_dcc = DCC_ENABLE, - .vsr_support = true, - .performance_trace = false, - .max_downscale_src_width = 4096,/*upto true 4K*/ - .disable_pplib_wm_range = false, - .scl_reset_length10 = true, - .sanity_checks = true, - .underflow_assert_delay_us = 0xFFFFFFFF, - .dwb_fi_phase = -1, // -1 = disable, - .dmub_command_table = true, - .pstate_enabled = true, - .use_max_lb = true, - .enable_mem_low_power = { - .bits = { - .vga = true, - .i2c = true, - .dmcu = false, // This is previously known to cause hang on S3 cycles if enabled - .dscl = true, - .cm = true, - .mpc = true, - .optc = true, - .vpg = true, - .afmt = true, - } - }, - .disable_z10 = true, - .enable_legacy_fast_update = true, - .enable_z9_disable_interface = true, /* Allow support for the PMFW interface for disable Z9*/ - .dml_hostvm_override = DML_HOSTVM_OVERRIDE_FALSE, - .using_dml2 = false, -}; - -static const struct dc_panel_config panel_config_defaults = { - .psr = { - .disable_psr = false, - .disallow_psrsu = false, - .disallow_replay = false, - }, - .ilr = { - .optimize_edp_link_rate = true, - }, -}; - -static void dcn31_dpp_destroy(struct dpp **dpp) -{ - kfree(TO_DCN20_DPP(*dpp)); - *dpp = NULL; -} - -static struct dpp *dcn31_dpp_create( - struct dc_context *ctx, - uint32_t inst) -{ - struct dcn3_dpp *dpp = - kzalloc(sizeof(struct dcn3_dpp), GFP_KERNEL); - - if (!dpp) - return NULL; - - if (dpp3_construct(dpp, ctx, inst, - &dpp_regs[inst], &tf_shift, &tf_mask)) - return &dpp->base; - - BREAK_TO_DEBUGGER(); - kfree(dpp); - return NULL; -} - -static struct output_pixel_processor *dcn31_opp_create( - struct dc_context *ctx, uint32_t inst) -{ - struct dcn20_opp *opp = - kzalloc(sizeof(struct dcn20_opp), GFP_KERNEL); - - if (!opp) { - BREAK_TO_DEBUGGER(); - return NULL; - } - - dcn20_opp_construct(opp, ctx, inst, - &opp_regs[inst], &opp_shift, &opp_mask); - return &opp->base; -} - -static struct dce_aux *dcn31_aux_engine_create( - struct dc_context *ctx, - uint32_t inst) -{ - struct aux_engine_dce110 *aux_engine = - kzalloc(sizeof(struct aux_engine_dce110), GFP_KERNEL); - - if (!aux_engine) - return NULL; - - dce110_aux_engine_construct(aux_engine, ctx, inst, - SW_AUX_TIMEOUT_PERIOD_MULTIPLIER * AUX_TIMEOUT_PERIOD, - &aux_engine_regs[inst], - &aux_mask, - &aux_shift, - ctx->dc->caps.extended_aux_timeout_support); - - return &aux_engine->base; -} -#define i2c_inst_regs(id) { I2C_HW_ENGINE_COMMON_REG_LIST_DCN30(id) } - -static const struct dce_i2c_registers i2c_hw_regs[] = { - i2c_inst_regs(1), - i2c_inst_regs(2), - i2c_inst_regs(3), - i2c_inst_regs(4), - i2c_inst_regs(5), -}; - -static const struct dce_i2c_shift i2c_shifts = { - I2C_COMMON_MASK_SH_LIST_DCN30(__SHIFT) -}; - -static const struct dce_i2c_mask i2c_masks = { - I2C_COMMON_MASK_SH_LIST_DCN30(_MASK) -}; - -static struct dce_i2c_hw *dcn31_i2c_hw_create( - struct dc_context *ctx, - uint32_t inst) -{ - struct dce_i2c_hw *dce_i2c_hw = - kzalloc(sizeof(struct dce_i2c_hw), GFP_KERNEL); - - if (!dce_i2c_hw) - return NULL; - - dcn2_i2c_hw_construct(dce_i2c_hw, ctx, inst, - &i2c_hw_regs[inst], &i2c_shifts, &i2c_masks); - - return dce_i2c_hw; -} -static struct mpc *dcn31_mpc_create( - struct dc_context *ctx, - int num_mpcc, - int num_rmu) -{ - struct dcn30_mpc *mpc30 = kzalloc(sizeof(struct dcn30_mpc), - GFP_KERNEL); - - if (!mpc30) - return NULL; - - dcn30_mpc_construct(mpc30, ctx, - &mpc_regs, - &mpc_shift, - &mpc_mask, - num_mpcc, - num_rmu); - - return &mpc30->base; -} - -static struct hubbub *dcn31_hubbub_create(struct dc_context *ctx) -{ - int i; - - struct dcn20_hubbub *hubbub3 = kzalloc(sizeof(struct dcn20_hubbub), - GFP_KERNEL); - - if (!hubbub3) - return NULL; - - hubbub31_construct(hubbub3, ctx, - &hubbub_reg, - &hubbub_shift, - &hubbub_mask, - dcn3_1_ip.det_buffer_size_kbytes, - dcn3_1_ip.pixel_chunk_size_kbytes, - dcn3_1_ip.config_return_buffer_size_in_kbytes); - - - for (i = 0; i < res_cap_dcn31.num_vmid; i++) { - struct dcn20_vmid *vmid = &hubbub3->vmid[i]; - - vmid->ctx = ctx; - - vmid->regs = &vmid_regs[i]; - vmid->shifts = &vmid_shifts; - vmid->masks = &vmid_masks; - } - - return &hubbub3->base; -} - -static struct timing_generator *dcn31_timing_generator_create( - struct dc_context *ctx, - uint32_t instance) -{ - struct optc *tgn10 = - kzalloc(sizeof(struct optc), GFP_KERNEL); - - if (!tgn10) - return NULL; - - tgn10->base.inst = instance; - tgn10->base.ctx = ctx; - - tgn10->tg_regs = &optc_regs[instance]; - tgn10->tg_shift = &optc_shift; - tgn10->tg_mask = &optc_mask; - - dcn31_timing_generator_init(tgn10); - - return &tgn10->base; -} - -static const struct encoder_feature_support link_enc_feature = { - .max_hdmi_deep_color = COLOR_DEPTH_121212, - .max_hdmi_pixel_clock = 600000, - .hdmi_ycbcr420_supported = true, - .dp_ycbcr420_supported = true, - .fec_supported = true, - .flags.bits.IS_HBR2_CAPABLE = true, - .flags.bits.IS_HBR3_CAPABLE = true, - .flags.bits.IS_TPS3_CAPABLE = true, - .flags.bits.IS_TPS4_CAPABLE = true -}; - -static struct link_encoder *dcn31_link_encoder_create( - struct dc_context *ctx, - const struct encoder_init_data *enc_init_data) -{ - struct dcn20_link_encoder *enc20 = - kzalloc(sizeof(struct dcn20_link_encoder), GFP_KERNEL); - - if (!enc20) - return NULL; - - dcn31_link_encoder_construct(enc20, - enc_init_data, - &link_enc_feature, - &link_enc_regs[enc_init_data->transmitter], - &link_enc_aux_regs[enc_init_data->channel - 1], - &link_enc_hpd_regs[enc_init_data->hpd_source], - &le_shift, - &le_mask); - - return &enc20->enc10.base; -} - -/* Create a minimal link encoder object not associated with a particular - * physical connector. - * resource_funcs.link_enc_create_minimal - */ -static struct link_encoder *dcn31_link_enc_create_minimal( - struct dc_context *ctx, enum engine_id eng_id) -{ - struct dcn20_link_encoder *enc20; - - if ((eng_id - ENGINE_ID_DIGA) > ctx->dc->res_pool->res_cap->num_dig_link_enc) - return NULL; - - enc20 = kzalloc(sizeof(struct dcn20_link_encoder), GFP_KERNEL); - if (!enc20) - return NULL; - - dcn31_link_encoder_construct_minimal( - enc20, - ctx, - &link_enc_feature, - &link_enc_regs[eng_id - ENGINE_ID_DIGA], - eng_id); - - return &enc20->enc10.base; -} - -static struct panel_cntl *dcn31_panel_cntl_create(const struct panel_cntl_init_data *init_data) -{ - struct dcn31_panel_cntl *panel_cntl = - kzalloc(sizeof(struct dcn31_panel_cntl), GFP_KERNEL); - - if (!panel_cntl) - return NULL; - - dcn31_panel_cntl_construct(panel_cntl, init_data); - - return &panel_cntl->base; -} - -static void read_dce_straps( - struct dc_context *ctx, - struct resource_straps *straps) -{ - generic_reg_get(ctx, regDC_PINSTRAPS + BASE(regDC_PINSTRAPS_BASE_IDX), - FN(DC_PINSTRAPS, DC_PINSTRAPS_AUDIO), &straps->dc_pinstraps_audio); - -} - -static struct audio *dcn31_create_audio( - struct dc_context *ctx, unsigned int inst) -{ - return dce_audio_create(ctx, inst, - &audio_regs[inst], &audio_shift, &audio_mask); -} - -static struct vpg *dcn31_vpg_create( - struct dc_context *ctx, - uint32_t inst) -{ - struct dcn31_vpg *vpg31 = kzalloc(sizeof(struct dcn31_vpg), GFP_KERNEL); - - if (!vpg31) - return NULL; - - vpg31_construct(vpg31, ctx, inst, - &vpg_regs[inst], - &vpg_shift, - &vpg_mask); - - return &vpg31->base; -} - -static struct afmt *dcn31_afmt_create( - struct dc_context *ctx, - uint32_t inst) -{ - struct dcn31_afmt *afmt31 = kzalloc(sizeof(struct dcn31_afmt), GFP_KERNEL); - - if (!afmt31) - return NULL; - - afmt31_construct(afmt31, ctx, inst, - &afmt_regs[inst], - &afmt_shift, - &afmt_mask); - - // Light sleep by default, no need to power down here - - return &afmt31->base; -} - -static struct apg *dcn31_apg_create( - struct dc_context *ctx, - uint32_t inst) -{ - struct dcn31_apg *apg31 = kzalloc(sizeof(struct dcn31_apg), GFP_KERNEL); - - if (!apg31) - return NULL; - - apg31_construct(apg31, ctx, inst, - &apg_regs[inst], - &apg_shift, - &apg_mask); - - return &apg31->base; -} - -static struct stream_encoder *dcn31_stream_encoder_create( - enum engine_id eng_id, - struct dc_context *ctx) -{ - struct dcn10_stream_encoder *enc1; - struct vpg *vpg; - struct afmt *afmt; - int vpg_inst; - int afmt_inst; - - /* Mapping of VPG, AFMT, DME register blocks to DIO block instance */ - if (eng_id <= ENGINE_ID_DIGF) { - vpg_inst = eng_id; - afmt_inst = eng_id; - } else - return NULL; - - enc1 = kzalloc(sizeof(struct dcn10_stream_encoder), GFP_KERNEL); - vpg = dcn31_vpg_create(ctx, vpg_inst); - afmt = dcn31_afmt_create(ctx, afmt_inst); - - if (!enc1 || !vpg || !afmt) { - kfree(enc1); - kfree(vpg); - kfree(afmt); - return NULL; - } - - dcn30_dio_stream_encoder_construct(enc1, ctx, ctx->dc_bios, - eng_id, vpg, afmt, - &stream_enc_regs[eng_id], - &se_shift, &se_mask); - - return &enc1->base; -} - -static struct hpo_dp_stream_encoder *dcn31_hpo_dp_stream_encoder_create( - enum engine_id eng_id, - struct dc_context *ctx) -{ - struct dcn31_hpo_dp_stream_encoder *hpo_dp_enc31; - struct vpg *vpg; - struct apg *apg; - uint32_t hpo_dp_inst; - uint32_t vpg_inst; - uint32_t apg_inst; - - ASSERT((eng_id >= ENGINE_ID_HPO_DP_0) && (eng_id <= ENGINE_ID_HPO_DP_3)); - hpo_dp_inst = eng_id - ENGINE_ID_HPO_DP_0; - - /* Mapping of VPG register blocks to HPO DP block instance: - * VPG[6] -> HPO_DP[0] - * VPG[7] -> HPO_DP[1] - * VPG[8] -> HPO_DP[2] - * VPG[9] -> HPO_DP[3] - */ - vpg_inst = hpo_dp_inst + 6; - - /* Mapping of APG register blocks to HPO DP block instance: - * APG[0] -> HPO_DP[0] - * APG[1] -> HPO_DP[1] - * APG[2] -> HPO_DP[2] - * APG[3] -> HPO_DP[3] - */ - apg_inst = hpo_dp_inst; - - /* allocate HPO stream encoder and create VPG sub-block */ - hpo_dp_enc31 = kzalloc(sizeof(struct dcn31_hpo_dp_stream_encoder), GFP_KERNEL); - vpg = dcn31_vpg_create(ctx, vpg_inst); - apg = dcn31_apg_create(ctx, apg_inst); - - if (!hpo_dp_enc31 || !vpg || !apg) { - kfree(hpo_dp_enc31); - kfree(vpg); - kfree(apg); - return NULL; - } - - dcn31_hpo_dp_stream_encoder_construct(hpo_dp_enc31, ctx, ctx->dc_bios, - hpo_dp_inst, eng_id, vpg, apg, - &hpo_dp_stream_enc_regs[hpo_dp_inst], - &hpo_dp_se_shift, &hpo_dp_se_mask); - - return &hpo_dp_enc31->base; -} - -static struct hpo_dp_link_encoder *dcn31_hpo_dp_link_encoder_create( - uint8_t inst, - struct dc_context *ctx) -{ - struct dcn31_hpo_dp_link_encoder *hpo_dp_enc31; - - /* allocate HPO link encoder */ - hpo_dp_enc31 = kzalloc(sizeof(struct dcn31_hpo_dp_link_encoder), GFP_KERNEL); - - hpo_dp_link_encoder31_construct(hpo_dp_enc31, ctx, inst, - &hpo_dp_link_enc_regs[inst], - &hpo_dp_le_shift, &hpo_dp_le_mask); - - return &hpo_dp_enc31->base; -} - -static struct dce_hwseq *dcn31_hwseq_create( - struct dc_context *ctx) -{ - struct dce_hwseq *hws = kzalloc(sizeof(struct dce_hwseq), GFP_KERNEL); - - if (hws) { - hws->ctx = ctx; - hws->regs = &hwseq_reg; - hws->shifts = &hwseq_shift; - hws->masks = &hwseq_mask; - } - return hws; -} -static const struct resource_create_funcs res_create_funcs = { - .read_dce_straps = read_dce_straps, - .create_audio = dcn31_create_audio, - .create_stream_encoder = dcn31_stream_encoder_create, - .create_hpo_dp_stream_encoder = dcn31_hpo_dp_stream_encoder_create, - .create_hpo_dp_link_encoder = dcn31_hpo_dp_link_encoder_create, - .create_hwseq = dcn31_hwseq_create, -}; - -static void dcn31_resource_destruct(struct dcn31_resource_pool *pool) -{ - unsigned int i; - - for (i = 0; i < pool->base.stream_enc_count; i++) { - if (pool->base.stream_enc[i] != NULL) { - if (pool->base.stream_enc[i]->vpg != NULL) { - kfree(DCN30_VPG_FROM_VPG(pool->base.stream_enc[i]->vpg)); - pool->base.stream_enc[i]->vpg = NULL; - } - if (pool->base.stream_enc[i]->afmt != NULL) { - kfree(DCN30_AFMT_FROM_AFMT(pool->base.stream_enc[i]->afmt)); - pool->base.stream_enc[i]->afmt = NULL; - } - kfree(DCN10STRENC_FROM_STRENC(pool->base.stream_enc[i])); - pool->base.stream_enc[i] = NULL; - } - } - - for (i = 0; i < pool->base.hpo_dp_stream_enc_count; i++) { - if (pool->base.hpo_dp_stream_enc[i] != NULL) { - if (pool->base.hpo_dp_stream_enc[i]->vpg != NULL) { - kfree(DCN30_VPG_FROM_VPG(pool->base.hpo_dp_stream_enc[i]->vpg)); - pool->base.hpo_dp_stream_enc[i]->vpg = NULL; - } - if (pool->base.hpo_dp_stream_enc[i]->apg != NULL) { - kfree(DCN31_APG_FROM_APG(pool->base.hpo_dp_stream_enc[i]->apg)); - pool->base.hpo_dp_stream_enc[i]->apg = NULL; - } - kfree(DCN3_1_HPO_DP_STREAM_ENC_FROM_HPO_STREAM_ENC(pool->base.hpo_dp_stream_enc[i])); - pool->base.hpo_dp_stream_enc[i] = NULL; - } - } - - for (i = 0; i < pool->base.hpo_dp_link_enc_count; i++) { - if (pool->base.hpo_dp_link_enc[i] != NULL) { - kfree(DCN3_1_HPO_DP_LINK_ENC_FROM_HPO_LINK_ENC(pool->base.hpo_dp_link_enc[i])); - pool->base.hpo_dp_link_enc[i] = NULL; - } - } - - for (i = 0; i < pool->base.res_cap->num_dsc; i++) { - if (pool->base.dscs[i] != NULL) - dcn20_dsc_destroy(&pool->base.dscs[i]); - } - - if (pool->base.mpc != NULL) { - kfree(TO_DCN20_MPC(pool->base.mpc)); - pool->base.mpc = NULL; - } - if (pool->base.hubbub != NULL) { - kfree(pool->base.hubbub); - pool->base.hubbub = NULL; - } - for (i = 0; i < pool->base.pipe_count; i++) { - if (pool->base.dpps[i] != NULL) - dcn31_dpp_destroy(&pool->base.dpps[i]); - - if (pool->base.ipps[i] != NULL) - pool->base.ipps[i]->funcs->ipp_destroy(&pool->base.ipps[i]); - - if (pool->base.hubps[i] != NULL) { - kfree(TO_DCN20_HUBP(pool->base.hubps[i])); - pool->base.hubps[i] = NULL; - } - - if (pool->base.irqs != NULL) { - dal_irq_service_destroy(&pool->base.irqs); - } - } - - for (i = 0; i < pool->base.res_cap->num_ddc; i++) { - if (pool->base.engines[i] != NULL) - dce110_engine_destroy(&pool->base.engines[i]); - if (pool->base.hw_i2cs[i] != NULL) { - kfree(pool->base.hw_i2cs[i]); - pool->base.hw_i2cs[i] = NULL; - } - if (pool->base.sw_i2cs[i] != NULL) { - kfree(pool->base.sw_i2cs[i]); - pool->base.sw_i2cs[i] = NULL; - } - } - - for (i = 0; i < pool->base.res_cap->num_opp; i++) { - if (pool->base.opps[i] != NULL) - pool->base.opps[i]->funcs->opp_destroy(&pool->base.opps[i]); - } - - for (i = 0; i < pool->base.res_cap->num_timing_generator; i++) { - if (pool->base.timing_generators[i] != NULL) { - kfree(DCN10TG_FROM_TG(pool->base.timing_generators[i])); - pool->base.timing_generators[i] = NULL; - } - } - - for (i = 0; i < pool->base.res_cap->num_dwb; i++) { - if (pool->base.dwbc[i] != NULL) { - kfree(TO_DCN30_DWBC(pool->base.dwbc[i])); - pool->base.dwbc[i] = NULL; - } - if (pool->base.mcif_wb[i] != NULL) { - kfree(TO_DCN30_MMHUBBUB(pool->base.mcif_wb[i])); - pool->base.mcif_wb[i] = NULL; - } - } - - for (i = 0; i < pool->base.audio_count; i++) { - if (pool->base.audios[i]) - dce_aud_destroy(&pool->base.audios[i]); - } - - for (i = 0; i < pool->base.clk_src_count; i++) { - if (pool->base.clock_sources[i] != NULL) { - dcn20_clock_source_destroy(&pool->base.clock_sources[i]); - pool->base.clock_sources[i] = NULL; - } - } - - for (i = 0; i < pool->base.res_cap->num_mpc_3dlut; i++) { - if (pool->base.mpc_lut[i] != NULL) { - dc_3dlut_func_release(pool->base.mpc_lut[i]); - pool->base.mpc_lut[i] = NULL; - } - if (pool->base.mpc_shaper[i] != NULL) { - dc_transfer_func_release(pool->base.mpc_shaper[i]); - pool->base.mpc_shaper[i] = NULL; - } - } - - if (pool->base.dp_clock_source != NULL) { - dcn20_clock_source_destroy(&pool->base.dp_clock_source); - pool->base.dp_clock_source = NULL; - } - - for (i = 0; i < pool->base.res_cap->num_timing_generator; i++) { - if (pool->base.multiple_abms[i] != NULL) - dce_abm_destroy(&pool->base.multiple_abms[i]); - } - - if (pool->base.psr != NULL) - dmub_psr_destroy(&pool->base.psr); - - if (pool->base.replay != NULL) - dmub_replay_destroy(&pool->base.replay); - - if (pool->base.dccg != NULL) - dcn_dccg_destroy(&pool->base.dccg); -} - -static struct hubp *dcn31_hubp_create( - struct dc_context *ctx, - uint32_t inst) -{ - struct dcn20_hubp *hubp2 = - kzalloc(sizeof(struct dcn20_hubp), GFP_KERNEL); - - if (!hubp2) - return NULL; - - if (hubp31_construct(hubp2, ctx, inst, - &hubp_regs[inst], &hubp_shift, &hubp_mask)) - return &hubp2->base; - - BREAK_TO_DEBUGGER(); - kfree(hubp2); - return NULL; -} - -static bool dcn31_dwbc_create(struct dc_context *ctx, struct resource_pool *pool) -{ - int i; - uint32_t pipe_count = pool->res_cap->num_dwb; - - for (i = 0; i < pipe_count; i++) { - struct dcn30_dwbc *dwbc30 = kzalloc(sizeof(struct dcn30_dwbc), - GFP_KERNEL); - - if (!dwbc30) { - dm_error("DC: failed to create dwbc30!\n"); - return false; - } - - dcn30_dwbc_construct(dwbc30, ctx, - &dwbc30_regs[i], - &dwbc30_shift, - &dwbc30_mask, - i); - - pool->dwbc[i] = &dwbc30->base; - } - return true; -} - -static bool dcn31_mmhubbub_create(struct dc_context *ctx, struct resource_pool *pool) -{ - int i; - uint32_t pipe_count = pool->res_cap->num_dwb; - - for (i = 0; i < pipe_count; i++) { - struct dcn30_mmhubbub *mcif_wb30 = kzalloc(sizeof(struct dcn30_mmhubbub), - GFP_KERNEL); - - if (!mcif_wb30) { - dm_error("DC: failed to create mcif_wb30!\n"); - return false; - } - - dcn30_mmhubbub_construct(mcif_wb30, ctx, - &mcif_wb30_regs[i], - &mcif_wb30_shift, - &mcif_wb30_mask, - i); - - pool->mcif_wb[i] = &mcif_wb30->base; - } - return true; -} - -static struct display_stream_compressor *dcn31_dsc_create( - struct dc_context *ctx, uint32_t inst) -{ - struct dcn20_dsc *dsc = - kzalloc(sizeof(struct dcn20_dsc), GFP_KERNEL); - - if (!dsc) { - BREAK_TO_DEBUGGER(); - return NULL; - } - - dsc2_construct(dsc, ctx, inst, &dsc_regs[inst], &dsc_shift, &dsc_mask); - return &dsc->base; -} - -static void dcn31_destroy_resource_pool(struct resource_pool **pool) -{ - struct dcn31_resource_pool *dcn31_pool = TO_DCN31_RES_POOL(*pool); - - dcn31_resource_destruct(dcn31_pool); - kfree(dcn31_pool); - *pool = NULL; -} - -static struct clock_source *dcn31_clock_source_create( - struct dc_context *ctx, - struct dc_bios *bios, - enum clock_source_id id, - const struct dce110_clk_src_regs *regs, - bool dp_clk_src) -{ - struct dce110_clk_src *clk_src = - kzalloc(sizeof(struct dce110_clk_src), GFP_KERNEL); - - if (!clk_src) - return NULL; - - if (dcn3_clk_src_construct(clk_src, ctx, bios, id, - regs, &cs_shift, &cs_mask)) { - clk_src->base.dp_clk_src = dp_clk_src; - return &clk_src->base; - } - - kfree(clk_src); - BREAK_TO_DEBUGGER(); - return NULL; -} - -static bool is_dual_plane(enum surface_pixel_format format) -{ - return format >= SURFACE_PIXEL_FORMAT_VIDEO_BEGIN || format == SURFACE_PIXEL_FORMAT_GRPH_RGBE_ALPHA; -} - -int dcn31x_populate_dml_pipes_from_context(struct dc *dc, - struct dc_state *context, - display_e2e_pipe_params_st *pipes, - bool fast_validate) -{ - uint32_t pipe_cnt; - int i; - - dc_assert_fp_enabled(); - - pipe_cnt = dcn20_populate_dml_pipes_from_context(dc, context, pipes, fast_validate); - - for (i = 0; i < pipe_cnt; i++) { - pipes[i].pipe.src.gpuvm = 1; - if (dc->debug.dml_hostvm_override == DML_HOSTVM_NO_OVERRIDE) { - //pipes[pipe_cnt].pipe.src.hostvm = dc->res_pool->hubbub->riommu_active; - pipes[i].pipe.src.hostvm = dc->vm_pa_config.is_hvm_enabled; - } else if (dc->debug.dml_hostvm_override == DML_HOSTVM_OVERRIDE_FALSE) - pipes[i].pipe.src.hostvm = false; - else if (dc->debug.dml_hostvm_override == DML_HOSTVM_OVERRIDE_TRUE) - pipes[i].pipe.src.hostvm = true; - } - return pipe_cnt; -} - -int dcn31_populate_dml_pipes_from_context( - struct dc *dc, struct dc_state *context, - display_e2e_pipe_params_st *pipes, - bool fast_validate) -{ - int i, pipe_cnt; - struct resource_context *res_ctx = &context->res_ctx; - struct pipe_ctx *pipe; - bool upscaled = false; - - DC_FP_START(); - dcn31x_populate_dml_pipes_from_context(dc, context, pipes, fast_validate); - DC_FP_END(); - - for (i = 0, pipe_cnt = 0; i < dc->res_pool->pipe_count; i++) { - struct dc_crtc_timing *timing; - - if (!res_ctx->pipe_ctx[i].stream) - continue; - pipe = &res_ctx->pipe_ctx[i]; - timing = &pipe->stream->timing; - if (pipe->plane_state && - (pipe->plane_state->src_rect.height < pipe->plane_state->dst_rect.height || - pipe->plane_state->src_rect.width < pipe->plane_state->dst_rect.width)) - upscaled = true; - - /* - * Immediate flip can be set dynamically after enabling the plane. - * We need to require support for immediate flip or underflow can be - * intermittently experienced depending on peak b/w requirements. - */ - pipes[pipe_cnt].pipe.src.immediate_flip = true; - pipes[pipe_cnt].pipe.src.unbounded_req_mode = false; - pipes[pipe_cnt].pipe.src.gpuvm = true; - pipes[pipe_cnt].pipe.dest.vfront_porch = timing->v_front_porch; - pipes[pipe_cnt].pipe.src.dcc_rate = 3; - pipes[pipe_cnt].dout.dsc_input_bpc = 0; - DC_FP_START(); - dcn31_zero_pipe_dcc_fraction(pipes, pipe_cnt); - DC_FP_END(); - - - if (pipes[pipe_cnt].dout.dsc_enable) { - switch (timing->display_color_depth) { - case COLOR_DEPTH_888: - pipes[pipe_cnt].dout.dsc_input_bpc = 8; - break; - case COLOR_DEPTH_101010: - pipes[pipe_cnt].dout.dsc_input_bpc = 10; - break; - case COLOR_DEPTH_121212: - pipes[pipe_cnt].dout.dsc_input_bpc = 12; - break; - default: - ASSERT(0); - break; - } - } - - pipe_cnt++; - } - context->bw_ctx.dml.ip.det_buffer_size_kbytes = DCN3_1_DEFAULT_DET_SIZE; - dc->config.enable_4to1MPC = false; - if (pipe_cnt == 1 && pipe->plane_state && !dc->debug.disable_z9_mpc) { - if (is_dual_plane(pipe->plane_state->format) - && pipe->plane_state->src_rect.width <= 1920 && pipe->plane_state->src_rect.height <= 1080) { - dc->config.enable_4to1MPC = true; - } else if (!is_dual_plane(pipe->plane_state->format) && pipe->plane_state->src_rect.width <= 5120) { - /* Limit to 5k max to avoid forced pipe split when there is not enough detile for swath */ - context->bw_ctx.dml.ip.det_buffer_size_kbytes = 192; - pipes[0].pipe.src.unbounded_req_mode = true; - } - } else if (context->stream_count >= dc->debug.crb_alloc_policy_min_disp_count - && dc->debug.crb_alloc_policy > DET_SIZE_DEFAULT) { - context->bw_ctx.dml.ip.det_buffer_size_kbytes = dc->debug.crb_alloc_policy * 64; - } else if (context->stream_count >= 3 && upscaled) { - context->bw_ctx.dml.ip.det_buffer_size_kbytes = 192; - } - - return pipe_cnt; -} - -void dcn31_calculate_wm_and_dlg( - struct dc *dc, struct dc_state *context, - display_e2e_pipe_params_st *pipes, - int pipe_cnt, - int vlevel) -{ - DC_FP_START(); - dcn31_calculate_wm_and_dlg_fp(dc, context, pipes, pipe_cnt, vlevel); - DC_FP_END(); -} - -void -dcn31_populate_dml_writeback_from_context(struct dc *dc, - struct resource_context *res_ctx, - display_e2e_pipe_params_st *pipes) -{ - DC_FP_START(); - dcn30_populate_dml_writeback_from_context(dc, res_ctx, pipes); - DC_FP_END(); -} - -void -dcn31_set_mcif_arb_params(struct dc *dc, - struct dc_state *context, - display_e2e_pipe_params_st *pipes, - int pipe_cnt) -{ - DC_FP_START(); - dcn30_set_mcif_arb_params(dc, context, pipes, pipe_cnt); - DC_FP_END(); -} - -bool dcn31_validate_bandwidth(struct dc *dc, - struct dc_state *context, - bool fast_validate) -{ - bool out = false; - - BW_VAL_TRACE_SETUP(); - - int vlevel = 0; - int pipe_cnt = 0; - display_e2e_pipe_params_st *pipes = kzalloc(dc->res_pool->pipe_count * sizeof(display_e2e_pipe_params_st), GFP_KERNEL); - DC_LOGGER_INIT(dc->ctx->logger); - - BW_VAL_TRACE_COUNT(); - - DC_FP_START(); - out = dcn30_internal_validate_bw(dc, context, pipes, &pipe_cnt, &vlevel, fast_validate, true); - DC_FP_END(); - - // Disable fast_validate to set min dcfclk in alculate_wm_and_dlg - if (pipe_cnt == 0) - fast_validate = false; - - if (!out) - goto validate_fail; - - BW_VAL_TRACE_END_VOLTAGE_LEVEL(); - - if (fast_validate) { - BW_VAL_TRACE_SKIP(fast); - goto validate_out; - } - if (dc->res_pool->funcs->calculate_wm_and_dlg) - dc->res_pool->funcs->calculate_wm_and_dlg(dc, context, pipes, pipe_cnt, vlevel); - - BW_VAL_TRACE_END_WATERMARKS(); - - goto validate_out; - -validate_fail: - DC_LOG_WARNING("Mode Validation Warning: %s failed validation.\n", - dml_get_status_message(context->bw_ctx.dml.vba.ValidationStatus[context->bw_ctx.dml.vba.soc.num_states])); - - BW_VAL_TRACE_SKIP(fail); - out = false; - -validate_out: - kfree(pipes); - - BW_VAL_TRACE_FINISH(); - - return out; -} - -static void dcn31_get_panel_config_defaults(struct dc_panel_config *panel_config) -{ - *panel_config = panel_config_defaults; -} - -static struct dc_cap_funcs cap_funcs = { - .get_dcc_compression_cap = dcn20_get_dcc_compression_cap -}; - -static struct resource_funcs dcn31_res_pool_funcs = { - .destroy = dcn31_destroy_resource_pool, - .link_enc_create = dcn31_link_encoder_create, - .link_enc_create_minimal = dcn31_link_enc_create_minimal, - .link_encs_assign = link_enc_cfg_link_encs_assign, - .link_enc_unassign = link_enc_cfg_link_enc_unassign, - .panel_cntl_create = dcn31_panel_cntl_create, - .validate_bandwidth = dcn31_validate_bandwidth, - .calculate_wm_and_dlg = dcn31_calculate_wm_and_dlg, - .update_soc_for_wm_a = dcn31_update_soc_for_wm_a, - .populate_dml_pipes = dcn31_populate_dml_pipes_from_context, - .acquire_free_pipe_as_secondary_dpp_pipe = dcn20_acquire_free_pipe_for_layer, - .release_pipe = dcn20_release_pipe, - .add_stream_to_ctx = dcn30_add_stream_to_ctx, - .add_dsc_to_stream_resource = dcn20_add_dsc_to_stream_resource, - .remove_stream_from_ctx = dcn20_remove_stream_from_ctx, - .populate_dml_writeback_from_context = dcn31_populate_dml_writeback_from_context, - .set_mcif_arb_params = dcn31_set_mcif_arb_params, - .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 = dcn31_update_bw_bounding_box, - .patch_unknown_plane_state = dcn20_patch_unknown_plane_state, - .get_panel_config_defaults = dcn31_get_panel_config_defaults, -}; - -static struct clock_source *dcn30_clock_source_create( - struct dc_context *ctx, - struct dc_bios *bios, - enum clock_source_id id, - const struct dce110_clk_src_regs *regs, - bool dp_clk_src) -{ - struct dce110_clk_src *clk_src = - kzalloc(sizeof(struct dce110_clk_src), GFP_KERNEL); - - if (!clk_src) - return NULL; - - if (dcn31_clk_src_construct(clk_src, ctx, bios, id, - regs, &cs_shift, &cs_mask)) { - clk_src->base.dp_clk_src = dp_clk_src; - return &clk_src->base; - } - - BREAK_TO_DEBUGGER(); - return NULL; -} - -static bool dcn31_resource_construct( - uint8_t num_virtual_links, - struct dc *dc, - struct dcn31_resource_pool *pool) -{ - int i; - struct dc_context *ctx = dc->ctx; - struct irq_service_init_data init_data; - - ctx->dc_bios->regs = &bios_regs; - - pool->base.res_cap = &res_cap_dcn31; - - pool->base.funcs = &dcn31_res_pool_funcs; - - /************************************************* - * Resource + asic cap harcoding * - *************************************************/ - pool->base.underlay_pipe_index = NO_UNDERLAY_PIPE; - pool->base.pipe_count = pool->base.res_cap->num_timing_generator; - pool->base.mpcc_count = pool->base.res_cap->num_timing_generator; - dc->caps.max_downscale_ratio = 600; - dc->caps.i2c_speed_in_khz = 100; - dc->caps.i2c_speed_in_khz_hdcp = 5; /*1.4 w/a applied by default*/ - dc->caps.max_cursor_size = 256; - dc->caps.min_horizontal_blanking_period = 80; - dc->caps.dmdata_alloc_size = 2048; - - dc->caps.max_slave_planes = 2; - dc->caps.max_slave_yuv_planes = 2; - dc->caps.max_slave_rgb_planes = 2; - dc->caps.post_blend_color_processing = true; - dc->caps.force_dp_tps4_for_cp2520 = true; - if (dc->config.forceHBR2CP2520) - dc->caps.force_dp_tps4_for_cp2520 = false; - dc->caps.dp_hpo = true; - dc->caps.dp_hdmi21_pcon_support = true; - dc->caps.edp_dsc_support = true; - dc->caps.extended_aux_timeout_support = true; - dc->caps.dmcub_support = true; - dc->caps.is_apu = true; - dc->caps.zstate_support = true; - - /* Color pipeline capabilities */ - dc->caps.color.dpp.dcn_arch = 1; - dc->caps.color.dpp.input_lut_shared = 0; - dc->caps.color.dpp.icsc = 1; - dc->caps.color.dpp.dgam_ram = 0; // must use gamma_corr - dc->caps.color.dpp.dgam_rom_caps.srgb = 1; - dc->caps.color.dpp.dgam_rom_caps.bt2020 = 1; - dc->caps.color.dpp.dgam_rom_caps.gamma2_2 = 1; - dc->caps.color.dpp.dgam_rom_caps.pq = 1; - dc->caps.color.dpp.dgam_rom_caps.hlg = 1; - dc->caps.color.dpp.post_csc = 1; - dc->caps.color.dpp.gamma_corr = 1; - dc->caps.color.dpp.dgam_rom_for_yuv = 0; - - dc->caps.color.dpp.hw_3d_lut = 1; - dc->caps.color.dpp.ogam_ram = 1; - // no OGAM ROM on DCN301 - dc->caps.color.dpp.ogam_rom_caps.srgb = 0; - dc->caps.color.dpp.ogam_rom_caps.bt2020 = 0; - dc->caps.color.dpp.ogam_rom_caps.gamma2_2 = 0; - dc->caps.color.dpp.ogam_rom_caps.pq = 0; - dc->caps.color.dpp.ogam_rom_caps.hlg = 0; - dc->caps.color.dpp.ocsc = 0; - - dc->caps.color.mpc.gamut_remap = 1; - dc->caps.color.mpc.num_3dluts = pool->base.res_cap->num_mpc_3dlut; //2 - dc->caps.color.mpc.ogam_ram = 1; - dc->caps.color.mpc.ogam_rom_caps.srgb = 0; - dc->caps.color.mpc.ogam_rom_caps.bt2020 = 0; - dc->caps.color.mpc.ogam_rom_caps.gamma2_2 = 0; - dc->caps.color.mpc.ogam_rom_caps.pq = 0; - dc->caps.color.mpc.ogam_rom_caps.hlg = 0; - dc->caps.color.mpc.ocsc = 1; - - dc->config.use_old_fixed_vs_sequence = true; - - /* Use pipe context based otg sync logic */ - dc->config.use_pipe_ctx_sync_logic = true; - - /* read VBIOS LTTPR caps */ - { - if (ctx->dc_bios->funcs->get_lttpr_caps) { - enum bp_result bp_query_result; - uint8_t is_vbios_lttpr_enable = 0; - - bp_query_result = ctx->dc_bios->funcs->get_lttpr_caps(ctx->dc_bios, &is_vbios_lttpr_enable); - dc->caps.vbios_lttpr_enable = (bp_query_result == BP_RESULT_OK) && !!is_vbios_lttpr_enable; - } - - /* interop bit is implicit */ - { - dc->caps.vbios_lttpr_aware = true; - } - } - - if (dc->ctx->dce_environment == DCE_ENV_PRODUCTION_DRV) - dc->debug = debug_defaults_drv; - - // Init the vm_helper - if (dc->vm_helper) - vm_helper_init(dc->vm_helper, 16); - - /************************************************* - * Create resources * - *************************************************/ - - /* Clock Sources for Pixel Clock*/ - pool->base.clock_sources[DCN31_CLK_SRC_PLL0] = - dcn30_clock_source_create(ctx, ctx->dc_bios, - CLOCK_SOURCE_COMBO_PHY_PLL0, - &clk_src_regs[0], false); - pool->base.clock_sources[DCN31_CLK_SRC_PLL1] = - dcn30_clock_source_create(ctx, ctx->dc_bios, - CLOCK_SOURCE_COMBO_PHY_PLL1, - &clk_src_regs[1], false); - /*move phypllx_pixclk_resync to dmub next*/ - if (dc->ctx->asic_id.hw_internal_rev == YELLOW_CARP_B0) { - pool->base.clock_sources[DCN31_CLK_SRC_PLL2] = - dcn30_clock_source_create(ctx, ctx->dc_bios, - CLOCK_SOURCE_COMBO_PHY_PLL2, - &clk_src_regs_b0[2], false); - pool->base.clock_sources[DCN31_CLK_SRC_PLL3] = - dcn30_clock_source_create(ctx, ctx->dc_bios, - CLOCK_SOURCE_COMBO_PHY_PLL3, - &clk_src_regs_b0[3], false); - } else { - pool->base.clock_sources[DCN31_CLK_SRC_PLL2] = - dcn30_clock_source_create(ctx, ctx->dc_bios, - CLOCK_SOURCE_COMBO_PHY_PLL2, - &clk_src_regs[2], false); - pool->base.clock_sources[DCN31_CLK_SRC_PLL3] = - dcn30_clock_source_create(ctx, ctx->dc_bios, - CLOCK_SOURCE_COMBO_PHY_PLL3, - &clk_src_regs[3], false); - } - - pool->base.clock_sources[DCN31_CLK_SRC_PLL4] = - dcn30_clock_source_create(ctx, ctx->dc_bios, - CLOCK_SOURCE_COMBO_PHY_PLL4, - &clk_src_regs[4], false); - - pool->base.clk_src_count = DCN30_CLK_SRC_TOTAL; - - /* todo: not reuse phy_pll registers */ - pool->base.dp_clock_source = - dcn31_clock_source_create(ctx, ctx->dc_bios, - CLOCK_SOURCE_ID_DP_DTO, - &clk_src_regs[0], true); - - for (i = 0; i < pool->base.clk_src_count; i++) { - if (pool->base.clock_sources[i] == NULL) { - dm_error("DC: failed to create clock sources!\n"); - BREAK_TO_DEBUGGER(); - goto create_fail; - } - } - - /* TODO: DCCG */ - pool->base.dccg = dccg31_create(ctx, &dccg_regs, &dccg_shift, &dccg_mask); - if (pool->base.dccg == NULL) { - dm_error("DC: failed to create dccg!\n"); - BREAK_TO_DEBUGGER(); - goto create_fail; - } - - /* TODO: IRQ */ - init_data.ctx = dc->ctx; - pool->base.irqs = dal_irq_service_dcn31_create(&init_data); - if (!pool->base.irqs) - goto create_fail; - - /* HUBBUB */ - pool->base.hubbub = dcn31_hubbub_create(ctx); - if (pool->base.hubbub == NULL) { - BREAK_TO_DEBUGGER(); - dm_error("DC: failed to create hubbub!\n"); - goto create_fail; - } - - /* HUBPs, DPPs, OPPs and TGs */ - for (i = 0; i < pool->base.pipe_count; i++) { - pool->base.hubps[i] = dcn31_hubp_create(ctx, i); - if (pool->base.hubps[i] == NULL) { - BREAK_TO_DEBUGGER(); - dm_error( - "DC: failed to create hubps!\n"); - goto create_fail; - } - - pool->base.dpps[i] = dcn31_dpp_create(ctx, i); - if (pool->base.dpps[i] == NULL) { - BREAK_TO_DEBUGGER(); - dm_error( - "DC: failed to create dpps!\n"); - goto create_fail; - } - } - - for (i = 0; i < pool->base.res_cap->num_opp; i++) { - pool->base.opps[i] = dcn31_opp_create(ctx, i); - if (pool->base.opps[i] == NULL) { - BREAK_TO_DEBUGGER(); - dm_error( - "DC: failed to create output pixel processor!\n"); - goto create_fail; - } - } - - for (i = 0; i < pool->base.res_cap->num_timing_generator; i++) { - pool->base.timing_generators[i] = dcn31_timing_generator_create( - ctx, i); - if (pool->base.timing_generators[i] == NULL) { - BREAK_TO_DEBUGGER(); - dm_error("DC: failed to create tg!\n"); - goto create_fail; - } - } - pool->base.timing_generator_count = i; - - /* PSR */ - pool->base.psr = dmub_psr_create(ctx); - if (pool->base.psr == NULL) { - dm_error("DC: failed to create psr obj!\n"); - BREAK_TO_DEBUGGER(); - goto create_fail; - } - - /* Replay */ - pool->base.replay = dmub_replay_create(ctx); - if (pool->base.replay == NULL) { - dm_error("DC: failed to create replay obj!\n"); - BREAK_TO_DEBUGGER(); - goto create_fail; - } - - /* ABM */ - for (i = 0; i < pool->base.res_cap->num_timing_generator; i++) { - pool->base.multiple_abms[i] = dmub_abm_create(ctx, - &abm_regs[i], - &abm_shift, - &abm_mask); - if (pool->base.multiple_abms[i] == NULL) { - dm_error("DC: failed to create abm for pipe %d!\n", i); - BREAK_TO_DEBUGGER(); - goto create_fail; - } - } - - /* MPC and DSC */ - pool->base.mpc = dcn31_mpc_create(ctx, pool->base.mpcc_count, pool->base.res_cap->num_mpc_3dlut); - if (pool->base.mpc == NULL) { - BREAK_TO_DEBUGGER(); - dm_error("DC: failed to create mpc!\n"); - goto create_fail; - } - - for (i = 0; i < pool->base.res_cap->num_dsc; i++) { - pool->base.dscs[i] = dcn31_dsc_create(ctx, i); - if (pool->base.dscs[i] == NULL) { - BREAK_TO_DEBUGGER(); - dm_error("DC: failed to create display stream compressor %d!\n", i); - goto create_fail; - } - } - - /* DWB and MMHUBBUB */ - if (!dcn31_dwbc_create(ctx, &pool->base)) { - BREAK_TO_DEBUGGER(); - dm_error("DC: failed to create dwbc!\n"); - goto create_fail; - } - - if (!dcn31_mmhubbub_create(ctx, &pool->base)) { - BREAK_TO_DEBUGGER(); - dm_error("DC: failed to create mcif_wb!\n"); - goto create_fail; - } - - /* AUX and I2C */ - for (i = 0; i < pool->base.res_cap->num_ddc; i++) { - pool->base.engines[i] = dcn31_aux_engine_create(ctx, i); - if (pool->base.engines[i] == NULL) { - BREAK_TO_DEBUGGER(); - dm_error( - "DC:failed to create aux engine!!\n"); - goto create_fail; - } - pool->base.hw_i2cs[i] = dcn31_i2c_hw_create(ctx, i); - if (pool->base.hw_i2cs[i] == NULL) { - BREAK_TO_DEBUGGER(); - dm_error( - "DC:failed to create hw i2c!!\n"); - goto create_fail; - } - pool->base.sw_i2cs[i] = NULL; - } - - if (dc->ctx->asic_id.chip_family == FAMILY_YELLOW_CARP && - dc->ctx->asic_id.hw_internal_rev == YELLOW_CARP_B0 && - !dc->debug.dpia_debug.bits.disable_dpia) { - /* YELLOW CARP B0 has 4 DPIA's */ - pool->base.usb4_dpia_count = 4; - } - - if (dc->ctx->asic_id.chip_family == AMDGPU_FAMILY_GC_11_0_1) - pool->base.usb4_dpia_count = 4; - - /* Audio, Stream Encoders including HPO and virtual, MPC 3D LUTs */ - if (!resource_construct(num_virtual_links, dc, &pool->base, - &res_create_funcs)) - goto create_fail; - - /* HW Sequencer and Plane caps */ - dcn31_hw_sequencer_construct(dc); - - dc->caps.max_planes = pool->base.pipe_count; - - for (i = 0; i < dc->caps.max_planes; ++i) - dc->caps.planes[i] = plane_cap; - - dc->cap_funcs = cap_funcs; - - dc->dcn_ip->max_num_dpp = dcn3_1_ip.max_num_dpp; - - return true; - -create_fail: - dcn31_resource_destruct(pool); - - return false; -} - -struct resource_pool *dcn31_create_resource_pool( - const struct dc_init_data *init_data, - struct dc *dc) -{ - struct dcn31_resource_pool *pool = - kzalloc(sizeof(struct dcn31_resource_pool), GFP_KERNEL); - - if (!pool) - return NULL; - - if (dcn31_resource_construct(init_data->num_virtual_links, dc, pool)) - return &pool->base; - - BREAK_TO_DEBUGGER(); - kfree(pool); - return NULL; -} diff --git a/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_resource.h b/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_resource.h deleted file mode 100644 index 901436591ed4..000000000000 --- a/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_resource.h +++ /dev/null @@ -1,97 +0,0 @@ -/* - * Copyright 2020 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 _DCN31_RESOURCE_H_ -#define _DCN31_RESOURCE_H_ - -#include "core_types.h" - -#define TO_DCN31_RES_POOL(pool)\ - container_of(pool, struct dcn31_resource_pool, base) - -extern struct _vcs_dpi_ip_params_st dcn3_1_ip; - -struct dcn31_resource_pool { - struct resource_pool base; -}; - -bool dcn31_validate_bandwidth(struct dc *dc, - struct dc_state *context, - bool fast_validate); -void dcn31_calculate_wm_and_dlg( - struct dc *dc, struct dc_state *context, - display_e2e_pipe_params_st *pipes, - int pipe_cnt, - int vlevel); -int dcn31_populate_dml_pipes_from_context( - struct dc *dc, struct dc_state *context, - display_e2e_pipe_params_st *pipes, - bool fast_validate); -void -dcn31_populate_dml_writeback_from_context(struct dc *dc, - struct resource_context *res_ctx, - display_e2e_pipe_params_st *pipes); -void -dcn31_set_mcif_arb_params(struct dc *dc, - struct dc_state *context, - display_e2e_pipe_params_st *pipes, - int pipe_cnt); - -struct resource_pool *dcn31_create_resource_pool( - const struct dc_init_data *init_data, - struct dc *dc); - -/*temp: B0 specific before switch to dcn313 headers*/ -#ifndef regPHYPLLF_PIXCLK_RESYNC_CNTL -#define regPHYPLLF_PIXCLK_RESYNC_CNTL 0x007e -#define regPHYPLLF_PIXCLK_RESYNC_CNTL_BASE_IDX 1 -#define regPHYPLLG_PIXCLK_RESYNC_CNTL 0x005f -#define regPHYPLLG_PIXCLK_RESYNC_CNTL_BASE_IDX 1 - -//PHYPLLF_PIXCLK_RESYNC_CNTL -#define PHYPLLF_PIXCLK_RESYNC_CNTL__PHYPLLF_PIXCLK_RESYNC_ENABLE__SHIFT 0x0 -#define PHYPLLF_PIXCLK_RESYNC_CNTL__PHYPLLF_DEEP_COLOR_DTO_ENABLE_STATUS__SHIFT 0x1 -#define PHYPLLF_PIXCLK_RESYNC_CNTL__PHYPLLF_DCCG_DEEP_COLOR_CNTL__SHIFT 0x4 -#define PHYPLLF_PIXCLK_RESYNC_CNTL__PHYPLLF_PIXCLK_ENABLE__SHIFT 0x8 -#define PHYPLLF_PIXCLK_RESYNC_CNTL__PHYPLLF_PIXCLK_DOUBLE_RATE_ENABLE__SHIFT 0x9 -#define PHYPLLF_PIXCLK_RESYNC_CNTL__PHYPLLF_PIXCLK_RESYNC_ENABLE_MASK 0x00000001L -#define PHYPLLF_PIXCLK_RESYNC_CNTL__PHYPLLF_DEEP_COLOR_DTO_ENABLE_STATUS_MASK 0x00000002L -#define PHYPLLF_PIXCLK_RESYNC_CNTL__PHYPLLF_DCCG_DEEP_COLOR_CNTL_MASK 0x00000030L -#define PHYPLLF_PIXCLK_RESYNC_CNTL__PHYPLLF_PIXCLK_ENABLE_MASK 0x00000100L -#define PHYPLLF_PIXCLK_RESYNC_CNTL__PHYPLLF_PIXCLK_DOUBLE_RATE_ENABLE_MASK 0x00000200L - -//PHYPLLG_PIXCLK_RESYNC_CNTL -#define PHYPLLG_PIXCLK_RESYNC_CNTL__PHYPLLG_PIXCLK_RESYNC_ENABLE__SHIFT 0x0 -#define PHYPLLG_PIXCLK_RESYNC_CNTL__PHYPLLG_DEEP_COLOR_DTO_ENABLE_STATUS__SHIFT 0x1 -#define PHYPLLG_PIXCLK_RESYNC_CNTL__PHYPLLG_DCCG_DEEP_COLOR_CNTL__SHIFT 0x4 -#define PHYPLLG_PIXCLK_RESYNC_CNTL__PHYPLLG_PIXCLK_ENABLE__SHIFT 0x8 -#define PHYPLLG_PIXCLK_RESYNC_CNTL__PHYPLLG_PIXCLK_DOUBLE_RATE_ENABLE__SHIFT 0x9 -#define PHYPLLG_PIXCLK_RESYNC_CNTL__PHYPLLG_PIXCLK_RESYNC_ENABLE_MASK 0x00000001L -#define PHYPLLG_PIXCLK_RESYNC_CNTL__PHYPLLG_DEEP_COLOR_DTO_ENABLE_STATUS_MASK 0x00000002L -#define PHYPLLG_PIXCLK_RESYNC_CNTL__PHYPLLG_DCCG_DEEP_COLOR_CNTL_MASK 0x00000030L -#define PHYPLLG_PIXCLK_RESYNC_CNTL__PHYPLLG_PIXCLK_ENABLE_MASK 0x00000100L -#define PHYPLLG_PIXCLK_RESYNC_CNTL__PHYPLLG_PIXCLK_DOUBLE_RATE_ENABLE_MASK 0x00000200L -#endif -#endif /* _DCN31_RESOURCE_H_ */ diff --git a/drivers/gpu/drm/amd/display/dc/dcn314/Makefile b/drivers/gpu/drm/amd/display/dc/dcn314/Makefile index 72456debb99f..6ea47e00d62d 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn314/Makefile +++ b/drivers/gpu/drm/amd/display/dc/dcn314/Makefile @@ -10,7 +10,7 @@ # # Makefile for dcn314. -DCN314 = dcn314_resource.o dcn314_init.o \ +DCN314 = dcn314_init.o \ dcn314_dio_stream_encoder.o dcn314_dccg.o dcn314_optc.o AMD_DAL_DCN314 = $(addprefix $(AMDDALPATH)/dc/dcn314/,$(DCN314)) diff --git a/drivers/gpu/drm/amd/display/dc/dcn314/dcn314_resource.c b/drivers/gpu/drm/amd/display/dc/dcn314/dcn314_resource.c deleted file mode 100644 index 677361d74a4e..000000000000 --- a/drivers/gpu/drm/amd/display/dc/dcn314/dcn314_resource.c +++ /dev/null @@ -1,2180 +0,0 @@ -// SPDX-License-Identifier: MIT -/* - * Copyright 2022 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 "dm_services.h" -#include "dc.h" - -#include "dcn31/dcn31_init.h" -#include "dcn314/dcn314_init.h" - -#include "resource.h" -#include "include/irq_service_interface.h" -#include "dcn314_resource.h" - -#include "dcn20/dcn20_resource.h" -#include "dcn30/dcn30_resource.h" -#include "dcn31/dcn31_resource.h" - -#include "dcn10/dcn10_ipp.h" -#include "dcn30/dcn30_hubbub.h" -#include "dcn31/dcn31_hubbub.h" -#include "dcn30/dcn30_mpc.h" -#include "dcn31/dcn31_hubp.h" -#include "irq/dcn31/irq_service_dcn31.h" -#include "irq/dcn314/irq_service_dcn314.h" -#include "dcn30/dcn30_dpp.h" -#include "dcn314/dcn314_optc.h" -#include "dcn20/dcn20_hwseq.h" -#include "dcn30/dcn30_hwseq.h" -#include "dce110/dce110_hwseq.h" -#include "dcn30/dcn30_opp.h" -#include "dcn20/dcn20_dsc.h" -#include "dcn30/dcn30_vpg.h" -#include "dcn30/dcn30_afmt.h" -#include "dcn31/dcn31_dio_link_encoder.h" -#include "dcn314/dcn314_dio_stream_encoder.h" -#include "dcn31/dcn31_hpo_dp_stream_encoder.h" -#include "dcn31/dcn31_hpo_dp_link_encoder.h" -#include "dcn31/dcn31_apg.h" -#include "dcn31/dcn31_vpg.h" -#include "dcn31/dcn31_afmt.h" -#include "dce/dce_clock_source.h" -#include "dce/dce_audio.h" -#include "dce/dce_hwseq.h" -#include "clk_mgr.h" -#include "virtual/virtual_stream_encoder.h" -#include "dce110/dce110_resource.h" -#include "dml/display_mode_vba.h" -#include "dml/dcn31/dcn31_fpu.h" -#include "dml/dcn314/dcn314_fpu.h" -#include "dcn314/dcn314_dccg.h" -#include "dcn10/dcn10_resource.h" -#include "dcn31/dcn31_panel_cntl.h" -#include "dcn314/dcn314_hwseq.h" - -#include "dcn30/dcn30_dwb.h" -#include "dcn30/dcn30_mmhubbub.h" - -#include "dcn/dcn_3_1_4_offset.h" -#include "dcn/dcn_3_1_4_sh_mask.h" -#include "dpcs/dpcs_3_1_4_offset.h" -#include "dpcs/dpcs_3_1_4_sh_mask.h" - -#define DCHUBBUB_DEBUG_CTRL_0__DET_DEPTH__SHIFT 0x10 -#define DCHUBBUB_DEBUG_CTRL_0__DET_DEPTH_MASK 0x01FF0000L - -#define DSCC0_DSCC_CONFIG0__ICH_RESET_AT_END_OF_LINE__SHIFT 0x0 -#define DSCC0_DSCC_CONFIG0__ICH_RESET_AT_END_OF_LINE_MASK 0x0000000FL - -#include "reg_helper.h" -#include "dce/dmub_abm.h" -#include "dce/dmub_psr.h" -#include "dce/dmub_replay.h" -#include "dce/dce_aux.h" -#include "dce/dce_i2c.h" -#include "dml/dcn314/display_mode_vba_314.h" -#include "vm_helper.h" -#include "dcn20/dcn20_vmid.h" - -#include "link_enc_cfg.h" - -#define DCN_BASE__INST0_SEG1 0x000000C0 -#define DCN_BASE__INST0_SEG2 0x000034C0 -#define DCN_BASE__INST0_SEG3 0x00009000 - -#define NBIO_BASE__INST0_SEG1 0x00000014 - -#define MAX_INSTANCE 7 -#define MAX_SEGMENT 8 - -#define regBIF_BX2_BIOS_SCRATCH_2 0x003a -#define regBIF_BX2_BIOS_SCRATCH_2_BASE_IDX 1 -#define regBIF_BX2_BIOS_SCRATCH_3 0x003b -#define regBIF_BX2_BIOS_SCRATCH_3_BASE_IDX 1 -#define regBIF_BX2_BIOS_SCRATCH_6 0x003e -#define regBIF_BX2_BIOS_SCRATCH_6_BASE_IDX 1 - -#define DC_LOGGER \ - dc->ctx->logger -#define DC_LOGGER_INIT(logger) - -enum dcn31_clk_src_array_id { - DCN31_CLK_SRC_PLL0, - DCN31_CLK_SRC_PLL1, - DCN31_CLK_SRC_PLL2, - DCN31_CLK_SRC_PLL3, - DCN31_CLK_SRC_PLL4, - DCN30_CLK_SRC_TOTAL -}; - -/* begin ********************* - * macros to expend register list macro defined in HW object header file - */ - -/* DCN */ -/* TODO awful hack. fixup dcn20_dwb.h */ -#undef BASE_INNER -#define BASE_INNER(seg) DCN_BASE__INST0_SEG ## seg - -#define BASE(seg) BASE_INNER(seg) - -#define SR(reg_name)\ - .reg_name = BASE(reg ## reg_name ## _BASE_IDX) + \ - reg ## reg_name - -#define SRI(reg_name, block, id)\ - .reg_name = BASE(reg ## block ## id ## _ ## reg_name ## _BASE_IDX) + \ - reg ## block ## id ## _ ## reg_name - -#define SRI2(reg_name, block, id)\ - .reg_name = BASE(reg ## reg_name ## _BASE_IDX) + \ - reg ## reg_name - -#define SRIR(var_name, reg_name, block, id)\ - .var_name = BASE(reg ## block ## id ## _ ## reg_name ## _BASE_IDX) + \ - reg ## block ## id ## _ ## reg_name - -#define SRII(reg_name, block, id)\ - .reg_name[id] = BASE(reg ## block ## id ## _ ## reg_name ## _BASE_IDX) + \ - reg ## block ## id ## _ ## reg_name - -#define SRII_MPC_RMU(reg_name, block, id)\ - .RMU##_##reg_name[id] = BASE(reg ## block ## id ## _ ## reg_name ## _BASE_IDX) + \ - reg ## block ## id ## _ ## reg_name - -#define SRII_DWB(reg_name, temp_name, block, id)\ - .reg_name[id] = BASE(reg ## block ## id ## _ ## temp_name ## _BASE_IDX) + \ - reg ## block ## id ## _ ## temp_name - -#define SF_DWB2(reg_name, block, id, field_name, post_fix) \ - .field_name = reg_name ## __ ## field_name ## post_fix - -#define DCCG_SRII(reg_name, block, id)\ - .block ## _ ## reg_name[id] = BASE(reg ## block ## id ## _ ## reg_name ## _BASE_IDX) + \ - reg ## block ## id ## _ ## reg_name - -#define VUPDATE_SRII(reg_name, block, id)\ - .reg_name[id] = BASE(reg ## reg_name ## _ ## block ## id ## _BASE_IDX) + \ - reg ## reg_name ## _ ## block ## id - -/* NBIO */ -#define NBIO_BASE_INNER(seg) \ - NBIO_BASE__INST0_SEG ## seg - -#define NBIO_BASE(seg) \ - NBIO_BASE_INNER(seg) - -#define NBIO_SR(reg_name)\ - .reg_name = NBIO_BASE(regBIF_BX2_ ## reg_name ## _BASE_IDX) + \ - regBIF_BX2_ ## reg_name - -/* MMHUB */ -#define MMHUB_BASE_INNER(seg) \ - MMHUB_BASE__INST0_SEG ## seg - -#define MMHUB_BASE(seg) \ - MMHUB_BASE_INNER(seg) - -#define MMHUB_SR(reg_name)\ - .reg_name = MMHUB_BASE(reg ## reg_name ## _BASE_IDX) + \ - reg ## reg_name - -/* CLOCK */ -#define CLK_BASE_INNER(seg) \ - CLK_BASE__INST0_SEG ## seg - -#define CLK_BASE(seg) \ - CLK_BASE_INNER(seg) - -#define CLK_SRI(reg_name, block, inst)\ - .reg_name = CLK_BASE(reg ## block ## _ ## inst ## _ ## reg_name ## _BASE_IDX) + \ - reg ## block ## _ ## inst ## _ ## reg_name - - -static const struct bios_registers bios_regs = { - NBIO_SR(BIOS_SCRATCH_3), - NBIO_SR(BIOS_SCRATCH_6) -}; - -#define clk_src_regs(index, pllid)\ -[index] = {\ - CS_COMMON_REG_LIST_DCN3_0(index, pllid),\ -} - -static const struct dce110_clk_src_regs clk_src_regs[] = { - clk_src_regs(0, A), - clk_src_regs(1, B), - clk_src_regs(2, C), - clk_src_regs(3, D), - clk_src_regs(4, E) -}; - -static const struct dce110_clk_src_shift cs_shift = { - CS_COMMON_MASK_SH_LIST_DCN3_1_4(__SHIFT) -}; - -static const struct dce110_clk_src_mask cs_mask = { - CS_COMMON_MASK_SH_LIST_DCN3_1_4(_MASK) -}; - -#define abm_regs(id)\ -[id] = {\ - ABM_DCN302_REG_LIST(id)\ -} - -static const struct dce_abm_registers abm_regs[] = { - abm_regs(0), - abm_regs(1), - abm_regs(2), - abm_regs(3), -}; - -static const struct dce_abm_shift abm_shift = { - ABM_MASK_SH_LIST_DCN30(__SHIFT) -}; - -static const struct dce_abm_mask abm_mask = { - ABM_MASK_SH_LIST_DCN30(_MASK) -}; - -#define audio_regs(id)\ -[id] = {\ - AUD_COMMON_REG_LIST(id)\ -} - -static const struct dce_audio_registers audio_regs[] = { - audio_regs(0), - audio_regs(1), - audio_regs(2), - audio_regs(3), - audio_regs(4), - audio_regs(5), - audio_regs(6) -}; - -#define DCE120_AUD_COMMON_MASK_SH_LIST(mask_sh)\ - SF(AZF0ENDPOINT0_AZALIA_F0_CODEC_ENDPOINT_INDEX, AZALIA_ENDPOINT_REG_INDEX, mask_sh),\ - SF(AZF0ENDPOINT0_AZALIA_F0_CODEC_ENDPOINT_DATA, AZALIA_ENDPOINT_REG_DATA, mask_sh),\ - AUD_COMMON_MASK_SH_LIST_BASE(mask_sh) - -static const struct dce_audio_shift audio_shift = { - DCE120_AUD_COMMON_MASK_SH_LIST(__SHIFT) -}; - -static const struct dce_audio_mask audio_mask = { - DCE120_AUD_COMMON_MASK_SH_LIST(_MASK) -}; - -#define vpg_regs(id)\ -[id] = {\ - VPG_DCN31_REG_LIST(id)\ -} - -static const struct dcn31_vpg_registers vpg_regs[] = { - vpg_regs(0), - vpg_regs(1), - vpg_regs(2), - vpg_regs(3), - vpg_regs(4), - vpg_regs(5), - vpg_regs(6), - vpg_regs(7), - vpg_regs(8), - vpg_regs(9), -}; - -static const struct dcn31_vpg_shift vpg_shift = { - DCN31_VPG_MASK_SH_LIST(__SHIFT) -}; - -static const struct dcn31_vpg_mask vpg_mask = { - DCN31_VPG_MASK_SH_LIST(_MASK) -}; - -#define afmt_regs(id)\ -[id] = {\ - AFMT_DCN31_REG_LIST(id)\ -} - -static const struct dcn31_afmt_registers afmt_regs[] = { - afmt_regs(0), - afmt_regs(1), - afmt_regs(2), - afmt_regs(3), - afmt_regs(4), - afmt_regs(5) -}; - -static const struct dcn31_afmt_shift afmt_shift = { - DCN31_AFMT_MASK_SH_LIST(__SHIFT) -}; - -static const struct dcn31_afmt_mask afmt_mask = { - DCN31_AFMT_MASK_SH_LIST(_MASK) -}; - -#define apg_regs(id)\ -[id] = {\ - APG_DCN31_REG_LIST(id)\ -} - -static const struct dcn31_apg_registers apg_regs[] = { - apg_regs(0), - apg_regs(1), - apg_regs(2), - apg_regs(3) -}; - -static const struct dcn31_apg_shift apg_shift = { - DCN31_APG_MASK_SH_LIST(__SHIFT) -}; - -static const struct dcn31_apg_mask apg_mask = { - DCN31_APG_MASK_SH_LIST(_MASK) -}; - -#define stream_enc_regs(id)\ -[id] = {\ - SE_DCN314_REG_LIST(id)\ -} - -static const struct dcn10_stream_enc_registers stream_enc_regs[] = { - stream_enc_regs(0), - stream_enc_regs(1), - stream_enc_regs(2), - stream_enc_regs(3), - stream_enc_regs(4) -}; - -static const struct dcn10_stream_encoder_shift se_shift = { - SE_COMMON_MASK_SH_LIST_DCN314(__SHIFT) -}; - -static const struct dcn10_stream_encoder_mask se_mask = { - SE_COMMON_MASK_SH_LIST_DCN314(_MASK) -}; - - -#define aux_regs(id)\ -[id] = {\ - DCN2_AUX_REG_LIST(id)\ -} - -static const struct dcn10_link_enc_aux_registers link_enc_aux_regs[] = { - aux_regs(0), - aux_regs(1), - aux_regs(2), - aux_regs(3), - aux_regs(4) -}; - -#define hpd_regs(id)\ -[id] = {\ - HPD_REG_LIST(id)\ -} - -static const struct dcn10_link_enc_hpd_registers link_enc_hpd_regs[] = { - hpd_regs(0), - hpd_regs(1), - hpd_regs(2), - hpd_regs(3), - hpd_regs(4) -}; - -#define link_regs(id, phyid)\ -[id] = {\ - LE_DCN31_REG_LIST(id), \ - UNIPHY_DCN2_REG_LIST(phyid), \ -} - -static const struct dce110_aux_registers_shift aux_shift = { - DCN_AUX_MASK_SH_LIST(__SHIFT) -}; - -static const struct dce110_aux_registers_mask aux_mask = { - DCN_AUX_MASK_SH_LIST(_MASK) -}; - -static const struct dcn10_link_enc_registers link_enc_regs[] = { - link_regs(0, A), - link_regs(1, B), - link_regs(2, C), - link_regs(3, D), - link_regs(4, E) -}; - -static const struct dcn10_link_enc_shift le_shift = { - LINK_ENCODER_MASK_SH_LIST_DCN31(__SHIFT), - DPCS_DCN31_MASK_SH_LIST(__SHIFT) -}; - -static const struct dcn10_link_enc_mask le_mask = { - LINK_ENCODER_MASK_SH_LIST_DCN31(_MASK), - DPCS_DCN31_MASK_SH_LIST(_MASK) -}; - -#define hpo_dp_stream_encoder_reg_list(id)\ -[id] = {\ - DCN3_1_HPO_DP_STREAM_ENC_REG_LIST(id)\ -} - -static const struct dcn31_hpo_dp_stream_encoder_registers hpo_dp_stream_enc_regs[] = { - hpo_dp_stream_encoder_reg_list(0), - hpo_dp_stream_encoder_reg_list(1), - hpo_dp_stream_encoder_reg_list(2), - hpo_dp_stream_encoder_reg_list(3) -}; - -static const struct dcn31_hpo_dp_stream_encoder_shift hpo_dp_se_shift = { - DCN3_1_HPO_DP_STREAM_ENC_MASK_SH_LIST(__SHIFT) -}; - -static const struct dcn31_hpo_dp_stream_encoder_mask hpo_dp_se_mask = { - DCN3_1_HPO_DP_STREAM_ENC_MASK_SH_LIST(_MASK) -}; - - -#define hpo_dp_link_encoder_reg_list(id)\ -[id] = {\ - DCN3_1_HPO_DP_LINK_ENC_REG_LIST(id),\ - DCN3_1_RDPCSTX_REG_LIST(0),\ - DCN3_1_RDPCSTX_REG_LIST(1),\ - DCN3_1_RDPCSTX_REG_LIST(2),\ -} - -static const struct dcn31_hpo_dp_link_encoder_registers hpo_dp_link_enc_regs[] = { - hpo_dp_link_encoder_reg_list(0), - hpo_dp_link_encoder_reg_list(1), -}; - -static const struct dcn31_hpo_dp_link_encoder_shift hpo_dp_le_shift = { - DCN3_1_HPO_DP_LINK_ENC_MASK_SH_LIST(__SHIFT) -}; - -static const struct dcn31_hpo_dp_link_encoder_mask hpo_dp_le_mask = { - DCN3_1_HPO_DP_LINK_ENC_MASK_SH_LIST(_MASK) -}; - -#define dpp_regs(id)\ -[id] = {\ - DPP_REG_LIST_DCN30(id),\ -} - -static const struct dcn3_dpp_registers dpp_regs[] = { - dpp_regs(0), - dpp_regs(1), - dpp_regs(2), - dpp_regs(3) -}; - -static const struct dcn3_dpp_shift tf_shift = { - DPP_REG_LIST_SH_MASK_DCN30(__SHIFT) -}; - -static const struct dcn3_dpp_mask tf_mask = { - DPP_REG_LIST_SH_MASK_DCN30(_MASK) -}; - -#define opp_regs(id)\ -[id] = {\ - OPP_REG_LIST_DCN30(id),\ -} - -static const struct dcn20_opp_registers opp_regs[] = { - opp_regs(0), - opp_regs(1), - opp_regs(2), - opp_regs(3) -}; - -static const struct dcn20_opp_shift opp_shift = { - OPP_MASK_SH_LIST_DCN20(__SHIFT) -}; - -static const struct dcn20_opp_mask opp_mask = { - OPP_MASK_SH_LIST_DCN20(_MASK) -}; - -#define aux_engine_regs(id)\ -[id] = {\ - AUX_COMMON_REG_LIST0(id), \ - .AUXN_IMPCAL = 0, \ - .AUXP_IMPCAL = 0, \ - .AUX_RESET_MASK = DP_AUX0_AUX_CONTROL__AUX_RESET_MASK, \ -} - -static const struct dce110_aux_registers aux_engine_regs[] = { - aux_engine_regs(0), - aux_engine_regs(1), - aux_engine_regs(2), - aux_engine_regs(3), - aux_engine_regs(4) -}; - -#define dwbc_regs_dcn3(id)\ -[id] = {\ - DWBC_COMMON_REG_LIST_DCN30(id),\ -} - -static const struct dcn30_dwbc_registers dwbc30_regs[] = { - dwbc_regs_dcn3(0), -}; - -static const struct dcn30_dwbc_shift dwbc30_shift = { - DWBC_COMMON_MASK_SH_LIST_DCN30(__SHIFT) -}; - -static const struct dcn30_dwbc_mask dwbc30_mask = { - DWBC_COMMON_MASK_SH_LIST_DCN30(_MASK) -}; - -#define mcif_wb_regs_dcn3(id)\ -[id] = {\ - MCIF_WB_COMMON_REG_LIST_DCN30(id),\ -} - -static const struct dcn30_mmhubbub_registers mcif_wb30_regs[] = { - mcif_wb_regs_dcn3(0) -}; - -static const struct dcn30_mmhubbub_shift mcif_wb30_shift = { - MCIF_WB_COMMON_MASK_SH_LIST_DCN30(__SHIFT) -}; - -static const struct dcn30_mmhubbub_mask mcif_wb30_mask = { - MCIF_WB_COMMON_MASK_SH_LIST_DCN30(_MASK) -}; - -#define dsc_regsDCN314(id)\ -[id] = {\ - DSC_REG_LIST_DCN20(id)\ -} - -static const struct dcn20_dsc_registers dsc_regs[] = { - dsc_regsDCN314(0), - dsc_regsDCN314(1), - dsc_regsDCN314(2), - dsc_regsDCN314(3) -}; - -static const struct dcn20_dsc_shift dsc_shift = { - DSC_REG_LIST_SH_MASK_DCN20(__SHIFT) -}; - -static const struct dcn20_dsc_mask dsc_mask = { - DSC_REG_LIST_SH_MASK_DCN20(_MASK) -}; - -static const struct dcn30_mpc_registers mpc_regs = { - MPC_REG_LIST_DCN3_0(0), - MPC_REG_LIST_DCN3_0(1), - MPC_REG_LIST_DCN3_0(2), - MPC_REG_LIST_DCN3_0(3), - MPC_OUT_MUX_REG_LIST_DCN3_0(0), - MPC_OUT_MUX_REG_LIST_DCN3_0(1), - MPC_OUT_MUX_REG_LIST_DCN3_0(2), - MPC_OUT_MUX_REG_LIST_DCN3_0(3), - MPC_RMU_GLOBAL_REG_LIST_DCN3AG, - MPC_RMU_REG_LIST_DCN3AG(0), - MPC_RMU_REG_LIST_DCN3AG(1), - //MPC_RMU_REG_LIST_DCN3AG(2), - MPC_DWB_MUX_REG_LIST_DCN3_0(0), -}; - -static const struct dcn30_mpc_shift mpc_shift = { - MPC_COMMON_MASK_SH_LIST_DCN30(__SHIFT) -}; - -static const struct dcn30_mpc_mask mpc_mask = { - MPC_COMMON_MASK_SH_LIST_DCN30(_MASK) -}; - -#define optc_regs(id)\ -[id] = {OPTC_COMMON_REG_LIST_DCN3_14(id)} - -static const struct dcn_optc_registers optc_regs[] = { - optc_regs(0), - optc_regs(1), - optc_regs(2), - optc_regs(3) -}; - -static const struct dcn_optc_shift optc_shift = { - OPTC_COMMON_MASK_SH_LIST_DCN3_14(__SHIFT) -}; - -static const struct dcn_optc_mask optc_mask = { - OPTC_COMMON_MASK_SH_LIST_DCN3_14(_MASK) -}; - -#define hubp_regs(id)\ -[id] = {\ - HUBP_REG_LIST_DCN30(id)\ -} - -static const struct dcn_hubp2_registers hubp_regs[] = { - hubp_regs(0), - hubp_regs(1), - hubp_regs(2), - hubp_regs(3) -}; - - -static const struct dcn_hubp2_shift hubp_shift = { - HUBP_MASK_SH_LIST_DCN31(__SHIFT) -}; - -static const struct dcn_hubp2_mask hubp_mask = { - HUBP_MASK_SH_LIST_DCN31(_MASK) -}; -static const struct dcn_hubbub_registers hubbub_reg = { - HUBBUB_REG_LIST_DCN31(0) -}; - -static const struct dcn_hubbub_shift hubbub_shift = { - HUBBUB_MASK_SH_LIST_DCN31(__SHIFT) -}; - -static const struct dcn_hubbub_mask hubbub_mask = { - HUBBUB_MASK_SH_LIST_DCN31(_MASK) -}; - -static const struct dccg_registers dccg_regs = { - DCCG_REG_LIST_DCN314() -}; - -static const struct dccg_shift dccg_shift = { - DCCG_MASK_SH_LIST_DCN314(__SHIFT) -}; - -static const struct dccg_mask dccg_mask = { - DCCG_MASK_SH_LIST_DCN314(_MASK) -}; - - -#define SRII2(reg_name_pre, reg_name_post, id)\ - .reg_name_pre ## _ ## reg_name_post[id] = BASE(reg ## reg_name_pre \ - ## id ## _ ## reg_name_post ## _BASE_IDX) + \ - reg ## reg_name_pre ## id ## _ ## reg_name_post - - -#define HWSEQ_DCN31_REG_LIST()\ - SR(DCHUBBUB_GLOBAL_TIMER_CNTL), \ - SR(DCHUBBUB_ARB_HOSTVM_CNTL), \ - SR(DIO_MEM_PWR_CTRL), \ - SR(ODM_MEM_PWR_CTRL3), \ - SR(DMU_MEM_PWR_CNTL), \ - SR(MMHUBBUB_MEM_PWR_CNTL), \ - SR(DCCG_GATE_DISABLE_CNTL), \ - SR(DCCG_GATE_DISABLE_CNTL2), \ - SR(DCFCLK_CNTL),\ - SR(DC_MEM_GLOBAL_PWR_REQ_CNTL), \ - SRII(PIXEL_RATE_CNTL, OTG, 0), \ - SRII(PIXEL_RATE_CNTL, OTG, 1),\ - SRII(PIXEL_RATE_CNTL, OTG, 2),\ - SRII(PIXEL_RATE_CNTL, OTG, 3),\ - SRII(PHYPLL_PIXEL_RATE_CNTL, OTG, 0),\ - SRII(PHYPLL_PIXEL_RATE_CNTL, OTG, 1),\ - SRII(PHYPLL_PIXEL_RATE_CNTL, OTG, 2),\ - SRII(PHYPLL_PIXEL_RATE_CNTL, OTG, 3),\ - SR(MICROSECOND_TIME_BASE_DIV), \ - SR(MILLISECOND_TIME_BASE_DIV), \ - SR(DISPCLK_FREQ_CHANGE_CNTL), \ - SR(RBBMIF_TIMEOUT_DIS), \ - SR(RBBMIF_TIMEOUT_DIS_2), \ - SR(DCHUBBUB_CRC_CTRL), \ - SR(DPP_TOP0_DPP_CRC_CTRL), \ - SR(DPP_TOP0_DPP_CRC_VAL_B_A), \ - SR(DPP_TOP0_DPP_CRC_VAL_R_G), \ - SR(MPC_CRC_CTRL), \ - SR(MPC_CRC_RESULT_GB), \ - SR(MPC_CRC_RESULT_C), \ - SR(MPC_CRC_RESULT_AR), \ - SR(DOMAIN0_PG_CONFIG), \ - SR(DOMAIN1_PG_CONFIG), \ - SR(DOMAIN2_PG_CONFIG), \ - SR(DOMAIN3_PG_CONFIG), \ - SR(DOMAIN16_PG_CONFIG), \ - SR(DOMAIN17_PG_CONFIG), \ - SR(DOMAIN18_PG_CONFIG), \ - SR(DOMAIN19_PG_CONFIG), \ - SR(DOMAIN0_PG_STATUS), \ - SR(DOMAIN1_PG_STATUS), \ - SR(DOMAIN2_PG_STATUS), \ - SR(DOMAIN3_PG_STATUS), \ - SR(DOMAIN16_PG_STATUS), \ - SR(DOMAIN17_PG_STATUS), \ - SR(DOMAIN18_PG_STATUS), \ - SR(DOMAIN19_PG_STATUS), \ - SR(D1VGA_CONTROL), \ - SR(D2VGA_CONTROL), \ - SR(D3VGA_CONTROL), \ - SR(D4VGA_CONTROL), \ - SR(D5VGA_CONTROL), \ - SR(D6VGA_CONTROL), \ - SR(DC_IP_REQUEST_CNTL), \ - SR(AZALIA_AUDIO_DTO), \ - SR(AZALIA_CONTROLLER_CLOCK_GATING), \ - SR(HPO_TOP_HW_CONTROL) - -static const struct dce_hwseq_registers hwseq_reg = { - HWSEQ_DCN31_REG_LIST() -}; - -#define HWSEQ_DCN31_MASK_SH_LIST(mask_sh)\ - HWSEQ_DCN_MASK_SH_LIST(mask_sh), \ - HWS_SF(, DCHUBBUB_GLOBAL_TIMER_CNTL, DCHUBBUB_GLOBAL_TIMER_REFDIV, mask_sh), \ - HWS_SF(, DCHUBBUB_ARB_HOSTVM_CNTL, DISABLE_HOSTVM_FORCE_ALLOW_PSTATE, mask_sh), \ - HWS_SF(, DOMAIN0_PG_CONFIG, DOMAIN_POWER_FORCEON, mask_sh), \ - HWS_SF(, DOMAIN0_PG_CONFIG, DOMAIN_POWER_GATE, mask_sh), \ - HWS_SF(, DOMAIN1_PG_CONFIG, DOMAIN_POWER_FORCEON, mask_sh), \ - HWS_SF(, DOMAIN1_PG_CONFIG, DOMAIN_POWER_GATE, mask_sh), \ - HWS_SF(, DOMAIN2_PG_CONFIG, DOMAIN_POWER_FORCEON, mask_sh), \ - HWS_SF(, DOMAIN2_PG_CONFIG, DOMAIN_POWER_GATE, mask_sh), \ - HWS_SF(, DOMAIN3_PG_CONFIG, DOMAIN_POWER_FORCEON, mask_sh), \ - HWS_SF(, DOMAIN3_PG_CONFIG, DOMAIN_POWER_GATE, mask_sh), \ - HWS_SF(, DOMAIN16_PG_CONFIG, DOMAIN_POWER_FORCEON, mask_sh), \ - HWS_SF(, DOMAIN16_PG_CONFIG, DOMAIN_POWER_GATE, mask_sh), \ - HWS_SF(, DOMAIN17_PG_CONFIG, DOMAIN_POWER_FORCEON, mask_sh), \ - HWS_SF(, DOMAIN17_PG_CONFIG, DOMAIN_POWER_GATE, mask_sh), \ - HWS_SF(, DOMAIN18_PG_CONFIG, DOMAIN_POWER_FORCEON, mask_sh), \ - HWS_SF(, DOMAIN18_PG_CONFIG, DOMAIN_POWER_GATE, mask_sh), \ - HWS_SF(, DOMAIN19_PG_CONFIG, DOMAIN_POWER_FORCEON, mask_sh), \ - HWS_SF(, DOMAIN19_PG_CONFIG, DOMAIN_POWER_GATE, mask_sh), \ - HWS_SF(, DOMAIN0_PG_STATUS, DOMAIN_PGFSM_PWR_STATUS, mask_sh), \ - HWS_SF(, DOMAIN1_PG_STATUS, DOMAIN_PGFSM_PWR_STATUS, mask_sh), \ - HWS_SF(, DOMAIN2_PG_STATUS, DOMAIN_PGFSM_PWR_STATUS, mask_sh), \ - HWS_SF(, DOMAIN3_PG_STATUS, DOMAIN_PGFSM_PWR_STATUS, mask_sh), \ - HWS_SF(, DOMAIN16_PG_STATUS, DOMAIN_PGFSM_PWR_STATUS, mask_sh), \ - HWS_SF(, DOMAIN17_PG_STATUS, DOMAIN_PGFSM_PWR_STATUS, mask_sh), \ - HWS_SF(, DOMAIN18_PG_STATUS, DOMAIN_PGFSM_PWR_STATUS, mask_sh), \ - HWS_SF(, DOMAIN19_PG_STATUS, DOMAIN_PGFSM_PWR_STATUS, mask_sh), \ - HWS_SF(, DC_IP_REQUEST_CNTL, IP_REQUEST_EN, mask_sh), \ - HWS_SF(, AZALIA_AUDIO_DTO, AZALIA_AUDIO_DTO_MODULE, mask_sh), \ - HWS_SF(, HPO_TOP_CLOCK_CONTROL, HPO_HDMISTREAMCLK_G_GATE_DIS, mask_sh), \ - HWS_SF(, DMU_MEM_PWR_CNTL, DMCU_ERAM_MEM_PWR_FORCE, mask_sh), \ - HWS_SF(, ODM_MEM_PWR_CTRL3, ODM_MEM_UNASSIGNED_PWR_MODE, mask_sh), \ - HWS_SF(, ODM_MEM_PWR_CTRL3, ODM_MEM_VBLANK_PWR_MODE, mask_sh), \ - HWS_SF(, MMHUBBUB_MEM_PWR_CNTL, VGA_MEM_PWR_FORCE, mask_sh), \ - HWS_SF(, DIO_MEM_PWR_CTRL, I2C_LIGHT_SLEEP_FORCE, mask_sh), \ - HWS_SF(, HPO_TOP_HW_CONTROL, HPO_IO_EN, mask_sh) - -static const struct dce_hwseq_shift hwseq_shift = { - HWSEQ_DCN31_MASK_SH_LIST(__SHIFT) -}; - -static const struct dce_hwseq_mask hwseq_mask = { - HWSEQ_DCN31_MASK_SH_LIST(_MASK) -}; -#define vmid_regs(id)\ -[id] = {\ - DCN20_VMID_REG_LIST(id)\ -} - -static const struct dcn_vmid_registers vmid_regs[] = { - vmid_regs(0), - vmid_regs(1), - vmid_regs(2), - vmid_regs(3), - vmid_regs(4), - vmid_regs(5), - vmid_regs(6), - vmid_regs(7), - vmid_regs(8), - vmid_regs(9), - vmid_regs(10), - vmid_regs(11), - vmid_regs(12), - vmid_regs(13), - vmid_regs(14), - vmid_regs(15) -}; - -static const struct dcn20_vmid_shift vmid_shifts = { - DCN20_VMID_MASK_SH_LIST(__SHIFT) -}; - -static const struct dcn20_vmid_mask vmid_masks = { - DCN20_VMID_MASK_SH_LIST(_MASK) -}; - -static const struct resource_caps res_cap_dcn314 = { - .num_timing_generator = 4, - .num_opp = 4, - .num_video_plane = 4, - .num_audio = 5, - .num_stream_encoder = 5, - .num_dig_link_enc = 5, - .num_hpo_dp_stream_encoder = 4, - .num_hpo_dp_link_encoder = 2, - .num_pll = 5, - .num_dwb = 1, - .num_ddc = 5, - .num_vmid = 16, - .num_mpc_3dlut = 2, - .num_dsc = 4, -}; - -static const struct dc_plane_cap plane_cap = { - .type = DC_PLANE_TYPE_DCN_UNIVERSAL, - .per_pixel_alpha = true, - - .pixel_format_support = { - .argb8888 = true, - .nv12 = true, - .fp16 = true, - .p010 = true, - .ayuv = false, - }, - - .max_upscale_factor = { - .argb8888 = 16000, - .nv12 = 16000, - .fp16 = 16000 - }, - - // 6:1 downscaling ratio: 1000/6 = 166.666 - // 4:1 downscaling ratio for ARGB888 to prevent underflow during P010 playback: 1000/4 = 250 - .max_downscale_factor = { - .argb8888 = 250, - .nv12 = 167, - .fp16 = 167 - }, - 64, - 64 -}; - -static const struct dc_debug_options debug_defaults_drv = { - .disable_z10 = false, - .enable_z9_disable_interface = true, - .minimum_z8_residency_time = 2000, - .psr_skip_crtc_disable = true, - .replay_skip_crtc_disabled = true, - .disable_dmcu = true, - .force_abm_enable = false, - .timing_trace = false, - .clock_trace = true, - .disable_dpp_power_gate = false, - .disable_hubp_power_gate = false, - .disable_pplib_clock_request = false, - .pipe_split_policy = MPC_SPLIT_DYNAMIC, - .force_single_disp_pipe_split = false, - .disable_dcc = DCC_ENABLE, - .vsr_support = true, - .performance_trace = false, - .max_downscale_src_width = 4096,/*upto true 4k*/ - .disable_pplib_wm_range = false, - .scl_reset_length10 = true, - .sanity_checks = true, - .underflow_assert_delay_us = 0xFFFFFFFF, - .dwb_fi_phase = -1, // -1 = disable, - .dmub_command_table = true, - .pstate_enabled = true, - .use_max_lb = true, - .enable_mem_low_power = { - .bits = { - .vga = true, - .i2c = true, - .dmcu = false, // This is previously known to cause hang on S3 cycles if enabled - .dscl = true, - .cm = true, - .mpc = true, - .optc = true, - .vpg = true, - .afmt = true, - } - }, - - .root_clock_optimization = { - .bits = { - .dpp = true, - .dsc = true, - .hdmistream = true, - .hdmichar = true, - .dpstream = true, - .symclk32_se = false, - .symclk32_le = true, - .symclk_fe = true, - .physymclk = true, - .dpiasymclk = true, - } - }, - - .seamless_boot_odm_combine = true, - .using_dml2 = false, -}; - -static const struct dc_debug_options debug_defaults_diags = { - .disable_dmcu = true, - .force_abm_enable = false, - .timing_trace = true, - .clock_trace = true, - .disable_dpp_power_gate = true, - .disable_hubp_power_gate = true, - .disable_clock_gate = true, - .disable_pplib_clock_request = true, - .disable_pplib_wm_range = true, - .disable_stutter = false, - .scl_reset_length10 = true, - .dwb_fi_phase = -1, // -1 = disable - .dmub_command_table = true, - .enable_tri_buf = true, - .use_max_lb = true -}; - -static const struct dc_panel_config panel_config_defaults = { - .psr = { - .disable_psr = false, - .disallow_psrsu = false, - .disallow_replay = false, - }, - .ilr = { - .optimize_edp_link_rate = true, - }, -}; - -static void dcn31_dpp_destroy(struct dpp **dpp) -{ - kfree(TO_DCN20_DPP(*dpp)); - *dpp = NULL; -} - -static struct dpp *dcn31_dpp_create( - struct dc_context *ctx, - uint32_t inst) -{ - struct dcn3_dpp *dpp = - kzalloc(sizeof(struct dcn3_dpp), GFP_KERNEL); - - if (!dpp) - return NULL; - - if (dpp3_construct(dpp, ctx, inst, - &dpp_regs[inst], &tf_shift, &tf_mask)) - return &dpp->base; - - BREAK_TO_DEBUGGER(); - kfree(dpp); - return NULL; -} - -static struct output_pixel_processor *dcn31_opp_create( - struct dc_context *ctx, uint32_t inst) -{ - struct dcn20_opp *opp = - kzalloc(sizeof(struct dcn20_opp), GFP_KERNEL); - - if (!opp) { - BREAK_TO_DEBUGGER(); - return NULL; - } - - dcn20_opp_construct(opp, ctx, inst, - &opp_regs[inst], &opp_shift, &opp_mask); - return &opp->base; -} - -static struct dce_aux *dcn31_aux_engine_create( - struct dc_context *ctx, - uint32_t inst) -{ - struct aux_engine_dce110 *aux_engine = - kzalloc(sizeof(struct aux_engine_dce110), GFP_KERNEL); - - if (!aux_engine) - return NULL; - - dce110_aux_engine_construct(aux_engine, ctx, inst, - SW_AUX_TIMEOUT_PERIOD_MULTIPLIER * AUX_TIMEOUT_PERIOD, - &aux_engine_regs[inst], - &aux_mask, - &aux_shift, - ctx->dc->caps.extended_aux_timeout_support); - - return &aux_engine->base; -} -#define i2c_inst_regs(id) { I2C_HW_ENGINE_COMMON_REG_LIST_DCN30(id) } - -static const struct dce_i2c_registers i2c_hw_regs[] = { - i2c_inst_regs(1), - i2c_inst_regs(2), - i2c_inst_regs(3), - i2c_inst_regs(4), - i2c_inst_regs(5), -}; - -static const struct dce_i2c_shift i2c_shifts = { - I2C_COMMON_MASK_SH_LIST_DCN30(__SHIFT) -}; - -static const struct dce_i2c_mask i2c_masks = { - I2C_COMMON_MASK_SH_LIST_DCN30(_MASK) -}; - -/* ========================================================== */ - -/* - * DPIA index | Preferred Encoder | Host Router - * 0 | C | 0 - * 1 | First Available | 0 - * 2 | D | 1 - * 3 | First Available | 1 - */ -/* ========================================================== */ -static const enum engine_id dpia_to_preferred_enc_id_table[] = { - ENGINE_ID_DIGC, - ENGINE_ID_DIGC, - ENGINE_ID_DIGD, - ENGINE_ID_DIGD -}; - -static enum engine_id dcn314_get_preferred_eng_id_dpia(unsigned int dpia_index) -{ - return dpia_to_preferred_enc_id_table[dpia_index]; -} - -static struct dce_i2c_hw *dcn31_i2c_hw_create( - struct dc_context *ctx, - uint32_t inst) -{ - struct dce_i2c_hw *dce_i2c_hw = - kzalloc(sizeof(struct dce_i2c_hw), GFP_KERNEL); - - if (!dce_i2c_hw) - return NULL; - - dcn2_i2c_hw_construct(dce_i2c_hw, ctx, inst, - &i2c_hw_regs[inst], &i2c_shifts, &i2c_masks); - - return dce_i2c_hw; -} -static struct mpc *dcn31_mpc_create( - struct dc_context *ctx, - int num_mpcc, - int num_rmu) -{ - struct dcn30_mpc *mpc30 = kzalloc(sizeof(struct dcn30_mpc), - GFP_KERNEL); - - if (!mpc30) - return NULL; - - dcn30_mpc_construct(mpc30, ctx, - &mpc_regs, - &mpc_shift, - &mpc_mask, - num_mpcc, - num_rmu); - - return &mpc30->base; -} - -static struct hubbub *dcn31_hubbub_create(struct dc_context *ctx) -{ - int i; - - struct dcn20_hubbub *hubbub3 = kzalloc(sizeof(struct dcn20_hubbub), - GFP_KERNEL); - - if (!hubbub3) - return NULL; - - hubbub31_construct(hubbub3, ctx, - &hubbub_reg, - &hubbub_shift, - &hubbub_mask, - dcn3_14_ip.det_buffer_size_kbytes, - dcn3_14_ip.pixel_chunk_size_kbytes, - dcn3_14_ip.config_return_buffer_size_in_kbytes); - - - for (i = 0; i < res_cap_dcn314.num_vmid; i++) { - struct dcn20_vmid *vmid = &hubbub3->vmid[i]; - - vmid->ctx = ctx; - - vmid->regs = &vmid_regs[i]; - vmid->shifts = &vmid_shifts; - vmid->masks = &vmid_masks; - } - - return &hubbub3->base; -} - -static struct timing_generator *dcn31_timing_generator_create( - struct dc_context *ctx, - uint32_t instance) -{ - struct optc *tgn10 = - kzalloc(sizeof(struct optc), GFP_KERNEL); - - if (!tgn10) - return NULL; - - tgn10->base.inst = instance; - tgn10->base.ctx = ctx; - - tgn10->tg_regs = &optc_regs[instance]; - tgn10->tg_shift = &optc_shift; - tgn10->tg_mask = &optc_mask; - - dcn314_timing_generator_init(tgn10); - - return &tgn10->base; -} - -static const struct encoder_feature_support link_enc_feature = { - .max_hdmi_deep_color = COLOR_DEPTH_121212, - .max_hdmi_pixel_clock = 600000, - .hdmi_ycbcr420_supported = true, - .dp_ycbcr420_supported = true, - .fec_supported = true, - .flags.bits.IS_HBR2_CAPABLE = true, - .flags.bits.IS_HBR3_CAPABLE = true, - .flags.bits.IS_TPS3_CAPABLE = true, - .flags.bits.IS_TPS4_CAPABLE = true -}; - -static struct link_encoder *dcn31_link_encoder_create( - struct dc_context *ctx, - const struct encoder_init_data *enc_init_data) -{ - struct dcn20_link_encoder *enc20 = - kzalloc(sizeof(struct dcn20_link_encoder), GFP_KERNEL); - - if (!enc20) - return NULL; - - dcn31_link_encoder_construct(enc20, - enc_init_data, - &link_enc_feature, - &link_enc_regs[enc_init_data->transmitter], - &link_enc_aux_regs[enc_init_data->channel - 1], - &link_enc_hpd_regs[enc_init_data->hpd_source], - &le_shift, - &le_mask); - - return &enc20->enc10.base; -} - -/* Create a minimal link encoder object not associated with a particular - * physical connector. - * resource_funcs.link_enc_create_minimal - */ -static struct link_encoder *dcn31_link_enc_create_minimal( - struct dc_context *ctx, enum engine_id eng_id) -{ - struct dcn20_link_encoder *enc20; - - if ((eng_id - ENGINE_ID_DIGA) > ctx->dc->res_pool->res_cap->num_dig_link_enc) - return NULL; - - enc20 = kzalloc(sizeof(struct dcn20_link_encoder), GFP_KERNEL); - if (!enc20) - return NULL; - - dcn31_link_encoder_construct_minimal( - enc20, - ctx, - &link_enc_feature, - &link_enc_regs[eng_id - ENGINE_ID_DIGA], - eng_id); - - return &enc20->enc10.base; -} - -static struct panel_cntl *dcn31_panel_cntl_create(const struct panel_cntl_init_data *init_data) -{ - struct dcn31_panel_cntl *panel_cntl = - kzalloc(sizeof(struct dcn31_panel_cntl), GFP_KERNEL); - - if (!panel_cntl) - return NULL; - - dcn31_panel_cntl_construct(panel_cntl, init_data); - - return &panel_cntl->base; -} - -static void read_dce_straps( - struct dc_context *ctx, - struct resource_straps *straps) -{ - generic_reg_get(ctx, regDC_PINSTRAPS + BASE(regDC_PINSTRAPS_BASE_IDX), - FN(DC_PINSTRAPS, DC_PINSTRAPS_AUDIO), &straps->dc_pinstraps_audio); - -} - -static struct audio *dcn31_create_audio( - struct dc_context *ctx, unsigned int inst) -{ - return dce_audio_create(ctx, inst, - &audio_regs[inst], &audio_shift, &audio_mask); -} - -static struct vpg *dcn31_vpg_create( - struct dc_context *ctx, - uint32_t inst) -{ - struct dcn31_vpg *vpg31 = kzalloc(sizeof(struct dcn31_vpg), GFP_KERNEL); - - if (!vpg31) - return NULL; - - vpg31_construct(vpg31, ctx, inst, - &vpg_regs[inst], - &vpg_shift, - &vpg_mask); - - return &vpg31->base; -} - -static struct afmt *dcn31_afmt_create( - struct dc_context *ctx, - uint32_t inst) -{ - struct dcn31_afmt *afmt31 = kzalloc(sizeof(struct dcn31_afmt), GFP_KERNEL); - - if (!afmt31) - return NULL; - - afmt31_construct(afmt31, ctx, inst, - &afmt_regs[inst], - &afmt_shift, - &afmt_mask); - - // Light sleep by default, no need to power down here - - return &afmt31->base; -} - -static struct apg *dcn31_apg_create( - struct dc_context *ctx, - uint32_t inst) -{ - struct dcn31_apg *apg31 = kzalloc(sizeof(struct dcn31_apg), GFP_KERNEL); - - if (!apg31) - return NULL; - - apg31_construct(apg31, ctx, inst, - &apg_regs[inst], - &apg_shift, - &apg_mask); - - return &apg31->base; -} - -static struct stream_encoder *dcn314_stream_encoder_create( - enum engine_id eng_id, - struct dc_context *ctx) -{ - struct dcn10_stream_encoder *enc1; - struct vpg *vpg; - struct afmt *afmt; - int vpg_inst; - int afmt_inst; - - /* Mapping of VPG, AFMT, DME register blocks to DIO block instance */ - if (eng_id < ENGINE_ID_DIGF) { - vpg_inst = eng_id; - afmt_inst = eng_id; - } else - return NULL; - - enc1 = kzalloc(sizeof(struct dcn10_stream_encoder), GFP_KERNEL); - vpg = dcn31_vpg_create(ctx, vpg_inst); - afmt = dcn31_afmt_create(ctx, afmt_inst); - - if (!enc1 || !vpg || !afmt) { - kfree(enc1); - kfree(vpg); - kfree(afmt); - return NULL; - } - - dcn314_dio_stream_encoder_construct(enc1, ctx, ctx->dc_bios, - eng_id, vpg, afmt, - &stream_enc_regs[eng_id], - &se_shift, &se_mask); - - return &enc1->base; -} - -static struct hpo_dp_stream_encoder *dcn31_hpo_dp_stream_encoder_create( - enum engine_id eng_id, - struct dc_context *ctx) -{ - struct dcn31_hpo_dp_stream_encoder *hpo_dp_enc31; - struct vpg *vpg; - struct apg *apg; - uint32_t hpo_dp_inst; - uint32_t vpg_inst; - uint32_t apg_inst; - - ASSERT((eng_id >= ENGINE_ID_HPO_DP_0) && (eng_id <= ENGINE_ID_HPO_DP_3)); - hpo_dp_inst = eng_id - ENGINE_ID_HPO_DP_0; - - /* Mapping of VPG register blocks to HPO DP block instance: - * VPG[6] -> HPO_DP[0] - * VPG[7] -> HPO_DP[1] - * VPG[8] -> HPO_DP[2] - * VPG[9] -> HPO_DP[3] - */ - //Uses offset index 5-8, but actually maps to vpg_inst 6-9 - vpg_inst = hpo_dp_inst + 5; - - /* Mapping of APG register blocks to HPO DP block instance: - * APG[0] -> HPO_DP[0] - * APG[1] -> HPO_DP[1] - * APG[2] -> HPO_DP[2] - * APG[3] -> HPO_DP[3] - */ - apg_inst = hpo_dp_inst; - - /* allocate HPO stream encoder and create VPG sub-block */ - hpo_dp_enc31 = kzalloc(sizeof(struct dcn31_hpo_dp_stream_encoder), GFP_KERNEL); - vpg = dcn31_vpg_create(ctx, vpg_inst); - apg = dcn31_apg_create(ctx, apg_inst); - - if (!hpo_dp_enc31 || !vpg || !apg) { - kfree(hpo_dp_enc31); - kfree(vpg); - kfree(apg); - return NULL; - } - - dcn31_hpo_dp_stream_encoder_construct(hpo_dp_enc31, ctx, ctx->dc_bios, - hpo_dp_inst, eng_id, vpg, apg, - &hpo_dp_stream_enc_regs[hpo_dp_inst], - &hpo_dp_se_shift, &hpo_dp_se_mask); - - return &hpo_dp_enc31->base; -} - -static struct hpo_dp_link_encoder *dcn31_hpo_dp_link_encoder_create( - uint8_t inst, - struct dc_context *ctx) -{ - struct dcn31_hpo_dp_link_encoder *hpo_dp_enc31; - - /* allocate HPO link encoder */ - hpo_dp_enc31 = kzalloc(sizeof(struct dcn31_hpo_dp_link_encoder), GFP_KERNEL); - - hpo_dp_link_encoder31_construct(hpo_dp_enc31, ctx, inst, - &hpo_dp_link_enc_regs[inst], - &hpo_dp_le_shift, &hpo_dp_le_mask); - - return &hpo_dp_enc31->base; -} - -static struct dce_hwseq *dcn314_hwseq_create( - struct dc_context *ctx) -{ - struct dce_hwseq *hws = kzalloc(sizeof(struct dce_hwseq), GFP_KERNEL); - - if (hws) { - hws->ctx = ctx; - hws->regs = &hwseq_reg; - hws->shifts = &hwseq_shift; - hws->masks = &hwseq_mask; - } - return hws; -} -static const struct resource_create_funcs res_create_funcs = { - .read_dce_straps = read_dce_straps, - .create_audio = dcn31_create_audio, - .create_stream_encoder = dcn314_stream_encoder_create, - .create_hpo_dp_stream_encoder = dcn31_hpo_dp_stream_encoder_create, - .create_hpo_dp_link_encoder = dcn31_hpo_dp_link_encoder_create, - .create_hwseq = dcn314_hwseq_create, -}; - -static void dcn314_resource_destruct(struct dcn314_resource_pool *pool) -{ - unsigned int i; - - for (i = 0; i < pool->base.stream_enc_count; i++) { - if (pool->base.stream_enc[i] != NULL) { - if (pool->base.stream_enc[i]->vpg != NULL) { - kfree(DCN30_VPG_FROM_VPG(pool->base.stream_enc[i]->vpg)); - pool->base.stream_enc[i]->vpg = NULL; - } - if (pool->base.stream_enc[i]->afmt != NULL) { - kfree(DCN30_AFMT_FROM_AFMT(pool->base.stream_enc[i]->afmt)); - pool->base.stream_enc[i]->afmt = NULL; - } - kfree(DCN10STRENC_FROM_STRENC(pool->base.stream_enc[i])); - pool->base.stream_enc[i] = NULL; - } - } - - for (i = 0; i < pool->base.hpo_dp_stream_enc_count; i++) { - if (pool->base.hpo_dp_stream_enc[i] != NULL) { - if (pool->base.hpo_dp_stream_enc[i]->vpg != NULL) { - kfree(DCN30_VPG_FROM_VPG(pool->base.hpo_dp_stream_enc[i]->vpg)); - pool->base.hpo_dp_stream_enc[i]->vpg = NULL; - } - if (pool->base.hpo_dp_stream_enc[i]->apg != NULL) { - kfree(DCN31_APG_FROM_APG(pool->base.hpo_dp_stream_enc[i]->apg)); - pool->base.hpo_dp_stream_enc[i]->apg = NULL; - } - kfree(DCN3_1_HPO_DP_STREAM_ENC_FROM_HPO_STREAM_ENC(pool->base.hpo_dp_stream_enc[i])); - pool->base.hpo_dp_stream_enc[i] = NULL; - } - } - - for (i = 0; i < pool->base.hpo_dp_link_enc_count; i++) { - if (pool->base.hpo_dp_link_enc[i] != NULL) { - kfree(DCN3_1_HPO_DP_LINK_ENC_FROM_HPO_LINK_ENC(pool->base.hpo_dp_link_enc[i])); - pool->base.hpo_dp_link_enc[i] = NULL; - } - } - - for (i = 0; i < pool->base.res_cap->num_dsc; i++) { - if (pool->base.dscs[i] != NULL) - dcn20_dsc_destroy(&pool->base.dscs[i]); - } - - if (pool->base.mpc != NULL) { - kfree(TO_DCN20_MPC(pool->base.mpc)); - pool->base.mpc = NULL; - } - if (pool->base.hubbub != NULL) { - kfree(pool->base.hubbub); - pool->base.hubbub = NULL; - } - for (i = 0; i < pool->base.pipe_count; i++) { - if (pool->base.dpps[i] != NULL) - dcn31_dpp_destroy(&pool->base.dpps[i]); - - if (pool->base.ipps[i] != NULL) - pool->base.ipps[i]->funcs->ipp_destroy(&pool->base.ipps[i]); - - if (pool->base.hubps[i] != NULL) { - kfree(TO_DCN20_HUBP(pool->base.hubps[i])); - pool->base.hubps[i] = NULL; - } - - if (pool->base.irqs != NULL) - dal_irq_service_destroy(&pool->base.irqs); - } - - for (i = 0; i < pool->base.res_cap->num_ddc; i++) { - if (pool->base.engines[i] != NULL) - dce110_engine_destroy(&pool->base.engines[i]); - if (pool->base.hw_i2cs[i] != NULL) { - kfree(pool->base.hw_i2cs[i]); - pool->base.hw_i2cs[i] = NULL; - } - if (pool->base.sw_i2cs[i] != NULL) { - kfree(pool->base.sw_i2cs[i]); - pool->base.sw_i2cs[i] = NULL; - } - } - - for (i = 0; i < pool->base.res_cap->num_opp; i++) { - if (pool->base.opps[i] != NULL) - pool->base.opps[i]->funcs->opp_destroy(&pool->base.opps[i]); - } - - for (i = 0; i < pool->base.res_cap->num_timing_generator; i++) { - if (pool->base.timing_generators[i] != NULL) { - kfree(DCN10TG_FROM_TG(pool->base.timing_generators[i])); - pool->base.timing_generators[i] = NULL; - } - } - - for (i = 0; i < pool->base.res_cap->num_dwb; i++) { - if (pool->base.dwbc[i] != NULL) { - kfree(TO_DCN30_DWBC(pool->base.dwbc[i])); - pool->base.dwbc[i] = NULL; - } - if (pool->base.mcif_wb[i] != NULL) { - kfree(TO_DCN30_MMHUBBUB(pool->base.mcif_wb[i])); - pool->base.mcif_wb[i] = NULL; - } - } - - for (i = 0; i < pool->base.audio_count; i++) { - if (pool->base.audios[i]) - dce_aud_destroy(&pool->base.audios[i]); - } - - for (i = 0; i < pool->base.clk_src_count; i++) { - if (pool->base.clock_sources[i] != NULL) { - dcn20_clock_source_destroy(&pool->base.clock_sources[i]); - pool->base.clock_sources[i] = NULL; - } - } - - for (i = 0; i < pool->base.res_cap->num_mpc_3dlut; i++) { - if (pool->base.mpc_lut[i] != NULL) { - dc_3dlut_func_release(pool->base.mpc_lut[i]); - pool->base.mpc_lut[i] = NULL; - } - if (pool->base.mpc_shaper[i] != NULL) { - dc_transfer_func_release(pool->base.mpc_shaper[i]); - pool->base.mpc_shaper[i] = NULL; - } - } - - if (pool->base.dp_clock_source != NULL) { - dcn20_clock_source_destroy(&pool->base.dp_clock_source); - pool->base.dp_clock_source = NULL; - } - - for (i = 0; i < pool->base.res_cap->num_timing_generator; i++) { - if (pool->base.multiple_abms[i] != NULL) - dce_abm_destroy(&pool->base.multiple_abms[i]); - } - - if (pool->base.psr != NULL) - dmub_psr_destroy(&pool->base.psr); - - if (pool->base.replay != NULL) - dmub_replay_destroy(&pool->base.replay); - - if (pool->base.dccg != NULL) - dcn_dccg_destroy(&pool->base.dccg); -} - -static struct hubp *dcn31_hubp_create( - struct dc_context *ctx, - uint32_t inst) -{ - struct dcn20_hubp *hubp2 = - kzalloc(sizeof(struct dcn20_hubp), GFP_KERNEL); - - if (!hubp2) - return NULL; - - if (hubp31_construct(hubp2, ctx, inst, - &hubp_regs[inst], &hubp_shift, &hubp_mask)) - return &hubp2->base; - - BREAK_TO_DEBUGGER(); - kfree(hubp2); - return NULL; -} - -static bool dcn31_dwbc_create(struct dc_context *ctx, struct resource_pool *pool) -{ - int i; - uint32_t pipe_count = pool->res_cap->num_dwb; - - for (i = 0; i < pipe_count; i++) { - struct dcn30_dwbc *dwbc30 = kzalloc(sizeof(struct dcn30_dwbc), - GFP_KERNEL); - - if (!dwbc30) { - dm_error("DC: failed to create dwbc30!\n"); - return false; - } - - dcn30_dwbc_construct(dwbc30, ctx, - &dwbc30_regs[i], - &dwbc30_shift, - &dwbc30_mask, - i); - - pool->dwbc[i] = &dwbc30->base; - } - return true; -} - -static bool dcn31_mmhubbub_create(struct dc_context *ctx, struct resource_pool *pool) -{ - int i; - uint32_t pipe_count = pool->res_cap->num_dwb; - - for (i = 0; i < pipe_count; i++) { - struct dcn30_mmhubbub *mcif_wb30 = kzalloc(sizeof(struct dcn30_mmhubbub), - GFP_KERNEL); - - if (!mcif_wb30) { - dm_error("DC: failed to create mcif_wb30!\n"); - return false; - } - - dcn30_mmhubbub_construct(mcif_wb30, ctx, - &mcif_wb30_regs[i], - &mcif_wb30_shift, - &mcif_wb30_mask, - i); - - pool->mcif_wb[i] = &mcif_wb30->base; - } - return true; -} - -static struct display_stream_compressor *dcn314_dsc_create( - struct dc_context *ctx, uint32_t inst) -{ - struct dcn20_dsc *dsc = - kzalloc(sizeof(struct dcn20_dsc), GFP_KERNEL); - - if (!dsc) { - BREAK_TO_DEBUGGER(); - return NULL; - } - - dsc2_construct(dsc, ctx, inst, &dsc_regs[inst], &dsc_shift, &dsc_mask); - return &dsc->base; -} - -static void dcn314_destroy_resource_pool(struct resource_pool **pool) -{ - struct dcn314_resource_pool *dcn314_pool = TO_DCN314_RES_POOL(*pool); - - dcn314_resource_destruct(dcn314_pool); - kfree(dcn314_pool); - *pool = NULL; -} - -static struct clock_source *dcn31_clock_source_create( - struct dc_context *ctx, - struct dc_bios *bios, - enum clock_source_id id, - const struct dce110_clk_src_regs *regs, - bool dp_clk_src) -{ - struct dce110_clk_src *clk_src = - kzalloc(sizeof(struct dce110_clk_src), GFP_KERNEL); - - if (!clk_src) - return NULL; - - if (dcn31_clk_src_construct(clk_src, ctx, bios, id, - regs, &cs_shift, &cs_mask)) { - clk_src->base.dp_clk_src = dp_clk_src; - return &clk_src->base; - } - - BREAK_TO_DEBUGGER(); - kfree(clk_src); - return NULL; -} - -static int dcn314_populate_dml_pipes_from_context( - struct dc *dc, struct dc_state *context, - display_e2e_pipe_params_st *pipes, - bool fast_validate) -{ - int pipe_cnt; - - DC_FP_START(); - pipe_cnt = dcn314_populate_dml_pipes_from_context_fpu(dc, context, pipes, fast_validate); - DC_FP_END(); - - return pipe_cnt; -} - -static struct dc_cap_funcs cap_funcs = { - .get_dcc_compression_cap = dcn20_get_dcc_compression_cap -}; - -static void dcn314_update_bw_bounding_box(struct dc *dc, struct clk_bw_params *bw_params) -{ - DC_FP_START(); - dcn314_update_bw_bounding_box_fpu(dc, bw_params); - DC_FP_END(); -} - -static void dcn314_get_panel_config_defaults(struct dc_panel_config *panel_config) -{ - *panel_config = panel_config_defaults; -} - -static bool filter_modes_for_single_channel_workaround(struct dc *dc, - struct dc_state *context) -{ - // Filter 2K@240Hz+8K@24fps above combination timing if memory only has single dimm LPDDR - if (dc->clk_mgr->bw_params->vram_type == 34 && - dc->clk_mgr->bw_params->num_channels < 2 && - context->stream_count > 1) { - int total_phy_pix_clk = 0; - - for (int i = 0; i < context->stream_count; i++) - if (context->res_ctx.pipe_ctx[i].stream) - total_phy_pix_clk += context->res_ctx.pipe_ctx[i].stream->phy_pix_clk; - - if (total_phy_pix_clk >= (1148928+826260)) //2K@240Hz+8K@24fps - return true; - } - return false; -} - -bool dcn314_validate_bandwidth(struct dc *dc, - struct dc_state *context, - bool fast_validate) -{ - bool out = false; - - BW_VAL_TRACE_SETUP(); - - int vlevel = 0; - int pipe_cnt = 0; - display_e2e_pipe_params_st *pipes = kzalloc(dc->res_pool->pipe_count * sizeof(display_e2e_pipe_params_st), GFP_KERNEL); - DC_LOGGER_INIT(dc->ctx->logger); - - BW_VAL_TRACE_COUNT(); - - if (filter_modes_for_single_channel_workaround(dc, context)) - goto validate_fail; - - DC_FP_START(); - // do not support self refresh only - out = dcn30_internal_validate_bw(dc, context, pipes, &pipe_cnt, &vlevel, fast_validate, false); - DC_FP_END(); - - // Disable fast_validate to set min dcfclk in calculate_wm_and_dlg - if (pipe_cnt == 0) - fast_validate = false; - - if (!out) - goto validate_fail; - - BW_VAL_TRACE_END_VOLTAGE_LEVEL(); - - if (fast_validate) { - BW_VAL_TRACE_SKIP(fast); - goto validate_out; - } - if (dc->res_pool->funcs->calculate_wm_and_dlg) - dc->res_pool->funcs->calculate_wm_and_dlg(dc, context, pipes, pipe_cnt, vlevel); - - BW_VAL_TRACE_END_WATERMARKS(); - - goto validate_out; - -validate_fail: - DC_LOG_WARNING("Mode Validation Warning: %s failed validation.\n", - dml_get_status_message(context->bw_ctx.dml.vba.ValidationStatus[context->bw_ctx.dml.vba.soc.num_states])); - - BW_VAL_TRACE_SKIP(fail); - out = false; - -validate_out: - kfree(pipes); - - BW_VAL_TRACE_FINISH(); - - return out; -} - -static struct resource_funcs dcn314_res_pool_funcs = { - .destroy = dcn314_destroy_resource_pool, - .link_enc_create = dcn31_link_encoder_create, - .link_enc_create_minimal = dcn31_link_enc_create_minimal, - .link_encs_assign = link_enc_cfg_link_encs_assign, - .link_enc_unassign = link_enc_cfg_link_enc_unassign, - .panel_cntl_create = dcn31_panel_cntl_create, - .validate_bandwidth = dcn314_validate_bandwidth, - .calculate_wm_and_dlg = dcn31_calculate_wm_and_dlg, - .update_soc_for_wm_a = dcn31_update_soc_for_wm_a, - .populate_dml_pipes = dcn314_populate_dml_pipes_from_context, - .acquire_free_pipe_as_secondary_dpp_pipe = dcn20_acquire_free_pipe_for_layer, - .release_pipe = dcn20_release_pipe, - .add_stream_to_ctx = dcn30_add_stream_to_ctx, - .add_dsc_to_stream_resource = dcn20_add_dsc_to_stream_resource, - .remove_stream_from_ctx = dcn20_remove_stream_from_ctx, - .populate_dml_writeback_from_context = dcn30_populate_dml_writeback_from_context, - .set_mcif_arb_params = dcn30_set_mcif_arb_params, - .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 = dcn314_update_bw_bounding_box, - .patch_unknown_plane_state = dcn20_patch_unknown_plane_state, - .get_panel_config_defaults = dcn314_get_panel_config_defaults, - .get_preferred_eng_id_dpia = dcn314_get_preferred_eng_id_dpia, -}; - -static struct clock_source *dcn30_clock_source_create( - struct dc_context *ctx, - struct dc_bios *bios, - enum clock_source_id id, - const struct dce110_clk_src_regs *regs, - bool dp_clk_src) -{ - struct dce110_clk_src *clk_src = - kzalloc(sizeof(struct dce110_clk_src), GFP_KERNEL); - - if (!clk_src) - return NULL; - - if (dcn31_clk_src_construct(clk_src, ctx, bios, id, - regs, &cs_shift, &cs_mask)) { - clk_src->base.dp_clk_src = dp_clk_src; - return &clk_src->base; - } - - BREAK_TO_DEBUGGER(); - kfree(clk_src); - return NULL; -} - -static bool dcn314_resource_construct( - uint8_t num_virtual_links, - struct dc *dc, - struct dcn314_resource_pool *pool) -{ - int i; - struct dc_context *ctx = dc->ctx; - struct irq_service_init_data init_data; - - ctx->dc_bios->regs = &bios_regs; - - pool->base.res_cap = &res_cap_dcn314; - pool->base.funcs = &dcn314_res_pool_funcs; - - /************************************************* - * Resource + asic cap harcoding * - *************************************************/ - pool->base.underlay_pipe_index = NO_UNDERLAY_PIPE; - pool->base.pipe_count = pool->base.res_cap->num_timing_generator; - pool->base.mpcc_count = pool->base.res_cap->num_timing_generator; - dc->caps.max_downscale_ratio = 400; - dc->caps.i2c_speed_in_khz = 100; - dc->caps.i2c_speed_in_khz_hdcp = 100; - dc->caps.max_cursor_size = 256; - dc->caps.min_horizontal_blanking_period = 80; - dc->caps.dmdata_alloc_size = 2048; - dc->caps.max_slave_planes = 2; - dc->caps.max_slave_yuv_planes = 2; - dc->caps.max_slave_rgb_planes = 2; - dc->caps.post_blend_color_processing = true; - dc->caps.force_dp_tps4_for_cp2520 = true; - if (dc->config.forceHBR2CP2520) - dc->caps.force_dp_tps4_for_cp2520 = false; - dc->caps.dp_hpo = true; - dc->caps.dp_hdmi21_pcon_support = true; - dc->caps.edp_dsc_support = true; - dc->caps.extended_aux_timeout_support = true; - dc->caps.dmcub_support = true; - dc->caps.is_apu = true; - dc->caps.seamless_odm = true; - - dc->caps.zstate_support = true; - - /* Color pipeline capabilities */ - dc->caps.color.dpp.dcn_arch = 1; - dc->caps.color.dpp.input_lut_shared = 0; - dc->caps.color.dpp.icsc = 1; - dc->caps.color.dpp.dgam_ram = 0; // must use gamma_corr - dc->caps.color.dpp.dgam_rom_caps.srgb = 1; - dc->caps.color.dpp.dgam_rom_caps.bt2020 = 1; - dc->caps.color.dpp.dgam_rom_caps.gamma2_2 = 1; - dc->caps.color.dpp.dgam_rom_caps.pq = 1; - dc->caps.color.dpp.dgam_rom_caps.hlg = 1; - dc->caps.color.dpp.post_csc = 1; - dc->caps.color.dpp.gamma_corr = 1; - dc->caps.color.dpp.dgam_rom_for_yuv = 0; - - dc->caps.color.dpp.hw_3d_lut = 1; - dc->caps.color.dpp.ogam_ram = 1; - // no OGAM ROM on DCN301 - dc->caps.color.dpp.ogam_rom_caps.srgb = 0; - dc->caps.color.dpp.ogam_rom_caps.bt2020 = 0; - dc->caps.color.dpp.ogam_rom_caps.gamma2_2 = 0; - dc->caps.color.dpp.ogam_rom_caps.pq = 0; - dc->caps.color.dpp.ogam_rom_caps.hlg = 0; - dc->caps.color.dpp.ocsc = 0; - - dc->caps.color.mpc.gamut_remap = 1; - dc->caps.color.mpc.num_3dluts = pool->base.res_cap->num_mpc_3dlut; //2 - dc->caps.color.mpc.ogam_ram = 1; - dc->caps.color.mpc.ogam_rom_caps.srgb = 0; - dc->caps.color.mpc.ogam_rom_caps.bt2020 = 0; - dc->caps.color.mpc.ogam_rom_caps.gamma2_2 = 0; - dc->caps.color.mpc.ogam_rom_caps.pq = 0; - dc->caps.color.mpc.ogam_rom_caps.hlg = 0; - dc->caps.color.mpc.ocsc = 1; - - dc->caps.max_disp_clock_khz_at_vmin = 650000; - - /* Use pipe context based otg sync logic */ - dc->config.use_pipe_ctx_sync_logic = true; - - /* read VBIOS LTTPR caps */ - { - if (ctx->dc_bios->funcs->get_lttpr_caps) { - enum bp_result bp_query_result; - uint8_t is_vbios_lttpr_enable = 0; - - bp_query_result = ctx->dc_bios->funcs->get_lttpr_caps(ctx->dc_bios, &is_vbios_lttpr_enable); - dc->caps.vbios_lttpr_enable = (bp_query_result == BP_RESULT_OK) && !!is_vbios_lttpr_enable; - } - - /* interop bit is implicit */ - { - dc->caps.vbios_lttpr_aware = true; - } - } - - if (dc->ctx->dce_environment == DCE_ENV_PRODUCTION_DRV) - dc->debug = debug_defaults_drv; - else - dc->debug = debug_defaults_diags; - - /* Disable pipe power gating */ - dc->debug.disable_dpp_power_gate = true; - dc->debug.disable_hubp_power_gate = true; - - /* Disable root clock optimization */ - dc->debug.root_clock_optimization.u32All = 0; - - // Init the vm_helper - if (dc->vm_helper) - vm_helper_init(dc->vm_helper, 16); - - /************************************************* - * Create resources * - *************************************************/ - - /* Clock Sources for Pixel Clock*/ - pool->base.clock_sources[DCN31_CLK_SRC_PLL0] = - dcn30_clock_source_create(ctx, ctx->dc_bios, - CLOCK_SOURCE_COMBO_PHY_PLL0, - &clk_src_regs[0], false); - pool->base.clock_sources[DCN31_CLK_SRC_PLL1] = - dcn30_clock_source_create(ctx, ctx->dc_bios, - CLOCK_SOURCE_COMBO_PHY_PLL1, - &clk_src_regs[1], false); - pool->base.clock_sources[DCN31_CLK_SRC_PLL2] = - dcn30_clock_source_create(ctx, ctx->dc_bios, - CLOCK_SOURCE_COMBO_PHY_PLL2, - &clk_src_regs[2], false); - pool->base.clock_sources[DCN31_CLK_SRC_PLL3] = - dcn30_clock_source_create(ctx, ctx->dc_bios, - CLOCK_SOURCE_COMBO_PHY_PLL3, - &clk_src_regs[3], false); - pool->base.clock_sources[DCN31_CLK_SRC_PLL4] = - dcn30_clock_source_create(ctx, ctx->dc_bios, - CLOCK_SOURCE_COMBO_PHY_PLL4, - &clk_src_regs[4], false); - - pool->base.clk_src_count = DCN30_CLK_SRC_TOTAL; - - /* todo: not reuse phy_pll registers */ - pool->base.dp_clock_source = - dcn31_clock_source_create(ctx, ctx->dc_bios, - CLOCK_SOURCE_ID_DP_DTO, - &clk_src_regs[0], true); - - for (i = 0; i < pool->base.clk_src_count; i++) { - if (pool->base.clock_sources[i] == NULL) { - dm_error("DC: failed to create clock sources!\n"); - BREAK_TO_DEBUGGER(); - goto create_fail; - } - } - - pool->base.dccg = dccg314_create(ctx, &dccg_regs, &dccg_shift, &dccg_mask); - if (pool->base.dccg == NULL) { - dm_error("DC: failed to create dccg!\n"); - BREAK_TO_DEBUGGER(); - goto create_fail; - } - - init_data.ctx = dc->ctx; - pool->base.irqs = dal_irq_service_dcn314_create(&init_data); - if (!pool->base.irqs) - goto create_fail; - - /* HUBBUB */ - pool->base.hubbub = dcn31_hubbub_create(ctx); - if (pool->base.hubbub == NULL) { - BREAK_TO_DEBUGGER(); - dm_error("DC: failed to create hubbub!\n"); - goto create_fail; - } - - /* HUBPs, DPPs, OPPs and TGs */ - for (i = 0; i < pool->base.pipe_count; i++) { - pool->base.hubps[i] = dcn31_hubp_create(ctx, i); - if (pool->base.hubps[i] == NULL) { - BREAK_TO_DEBUGGER(); - dm_error( - "DC: failed to create hubps!\n"); - goto create_fail; - } - - pool->base.dpps[i] = dcn31_dpp_create(ctx, i); - if (pool->base.dpps[i] == NULL) { - BREAK_TO_DEBUGGER(); - dm_error( - "DC: failed to create dpps!\n"); - goto create_fail; - } - } - - for (i = 0; i < pool->base.res_cap->num_opp; i++) { - pool->base.opps[i] = dcn31_opp_create(ctx, i); - if (pool->base.opps[i] == NULL) { - BREAK_TO_DEBUGGER(); - dm_error( - "DC: failed to create output pixel processor!\n"); - goto create_fail; - } - } - - for (i = 0; i < pool->base.res_cap->num_timing_generator; i++) { - pool->base.timing_generators[i] = dcn31_timing_generator_create( - ctx, i); - if (pool->base.timing_generators[i] == NULL) { - BREAK_TO_DEBUGGER(); - dm_error("DC: failed to create tg!\n"); - goto create_fail; - } - } - pool->base.timing_generator_count = i; - - /* PSR */ - pool->base.psr = dmub_psr_create(ctx); - if (pool->base.psr == NULL) { - dm_error("DC: failed to create psr obj!\n"); - BREAK_TO_DEBUGGER(); - goto create_fail; - } - - /* Replay */ - pool->base.replay = dmub_replay_create(ctx); - if (pool->base.replay == NULL) { - dm_error("DC: failed to create replay obj!\n"); - BREAK_TO_DEBUGGER(); - goto create_fail; - } - - /* ABM */ - for (i = 0; i < pool->base.res_cap->num_timing_generator; i++) { - pool->base.multiple_abms[i] = dmub_abm_create(ctx, - &abm_regs[i], - &abm_shift, - &abm_mask); - if (pool->base.multiple_abms[i] == NULL) { - dm_error("DC: failed to create abm for pipe %d!\n", i); - BREAK_TO_DEBUGGER(); - goto create_fail; - } - } - - /* MPC and DSC */ - pool->base.mpc = dcn31_mpc_create(ctx, pool->base.mpcc_count, pool->base.res_cap->num_mpc_3dlut); - if (pool->base.mpc == NULL) { - BREAK_TO_DEBUGGER(); - dm_error("DC: failed to create mpc!\n"); - goto create_fail; - } - - for (i = 0; i < pool->base.res_cap->num_dsc; i++) { - pool->base.dscs[i] = dcn314_dsc_create(ctx, i); - if (pool->base.dscs[i] == NULL) { - BREAK_TO_DEBUGGER(); - dm_error("DC: failed to create display stream compressor %d!\n", i); - goto create_fail; - } - } - - /* DWB and MMHUBBUB */ - if (!dcn31_dwbc_create(ctx, &pool->base)) { - BREAK_TO_DEBUGGER(); - dm_error("DC: failed to create dwbc!\n"); - goto create_fail; - } - - if (!dcn31_mmhubbub_create(ctx, &pool->base)) { - BREAK_TO_DEBUGGER(); - dm_error("DC: failed to create mcif_wb!\n"); - goto create_fail; - } - - /* AUX and I2C */ - for (i = 0; i < pool->base.res_cap->num_ddc; i++) { - pool->base.engines[i] = dcn31_aux_engine_create(ctx, i); - if (pool->base.engines[i] == NULL) { - BREAK_TO_DEBUGGER(); - dm_error( - "DC:failed to create aux engine!!\n"); - goto create_fail; - } - pool->base.hw_i2cs[i] = dcn31_i2c_hw_create(ctx, i); - if (pool->base.hw_i2cs[i] == NULL) { - BREAK_TO_DEBUGGER(); - dm_error( - "DC:failed to create hw i2c!!\n"); - goto create_fail; - } - pool->base.sw_i2cs[i] = NULL; - } - - /* DCN314 has 4 DPIA */ - pool->base.usb4_dpia_count = 4; - - /* Audio, Stream Encoders including HPO and virtual, MPC 3D LUTs */ - if (!resource_construct(num_virtual_links, dc, &pool->base, - &res_create_funcs)) - goto create_fail; - - /* HW Sequencer and Plane caps */ - dcn314_hw_sequencer_construct(dc); - - dc->caps.max_planes = pool->base.pipe_count; - - for (i = 0; i < dc->caps.max_planes; ++i) - dc->caps.planes[i] = plane_cap; - - dc->cap_funcs = cap_funcs; - - dc->dcn_ip->max_num_dpp = dcn3_14_ip.max_num_dpp; - - return true; - -create_fail: - - dcn314_resource_destruct(pool); - - return false; -} - -struct resource_pool *dcn314_create_resource_pool( - const struct dc_init_data *init_data, - struct dc *dc) -{ - struct dcn314_resource_pool *pool = - kzalloc(sizeof(struct dcn314_resource_pool), GFP_KERNEL); - - if (!pool) - return NULL; - - if (dcn314_resource_construct(init_data->num_virtual_links, dc, pool)) - return &pool->base; - - BREAK_TO_DEBUGGER(); - kfree(pool); - return NULL; -} diff --git a/drivers/gpu/drm/amd/display/dc/dcn314/dcn314_resource.h b/drivers/gpu/drm/amd/display/dc/dcn314/dcn314_resource.h deleted file mode 100644 index 49ffe71018df..000000000000 --- a/drivers/gpu/drm/amd/display/dc/dcn314/dcn314_resource.h +++ /dev/null @@ -1,50 +0,0 @@ -/* SPDX-License-Identifier: MIT */ -/* - * Copyright 2022 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 _DCN314_RESOURCE_H_ -#define _DCN314_RESOURCE_H_ - -#include "core_types.h" - -extern struct _vcs_dpi_ip_params_st dcn3_14_ip; -extern struct _vcs_dpi_soc_bounding_box_st dcn3_14_soc; - -#define TO_DCN314_RES_POOL(pool)\ - container_of(pool, struct dcn314_resource_pool, base) - -struct dcn314_resource_pool { - struct resource_pool base; -}; - -bool dcn314_validate_bandwidth(struct dc *dc, - struct dc_state *context, - bool fast_validate); - -struct resource_pool *dcn314_create_resource_pool( - const struct dc_init_data *init_data, - struct dc *dc); - -#endif /* _DCN314_RESOURCE_H_ */ diff --git a/drivers/gpu/drm/amd/display/dc/dcn315/Makefile b/drivers/gpu/drm/amd/display/dc/dcn315/Makefile deleted file mode 100644 index 59381d24800b..000000000000 --- a/drivers/gpu/drm/amd/display/dc/dcn315/Makefile +++ /dev/null @@ -1,30 +0,0 @@ -# -# 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 -# -# Makefile for dcn315. - -DCN315 = dcn315_resource.o - -AMD_DAL_DCN315 = $(addprefix $(AMDDALPATH)/dc/dcn315/,$(DCN315)) - -AMD_DISPLAY_FILES += $(AMD_DAL_DCN315) diff --git a/drivers/gpu/drm/amd/display/dc/dcn315/dcn315_resource.c b/drivers/gpu/drm/amd/display/dc/dcn315/dcn315_resource.c deleted file mode 100644 index cb8024eee8e4..000000000000 --- a/drivers/gpu/drm/amd/display/dc/dcn315/dcn315_resource.c +++ /dev/null @@ -1,2151 +0,0 @@ -/* - * 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 "dm_services.h" -#include "dc.h" - -#include "dcn31/dcn31_init.h" - -#include "resource.h" -#include "include/irq_service_interface.h" -#include "dcn315_resource.h" - -#include "dcn20/dcn20_resource.h" -#include "dcn30/dcn30_resource.h" -#include "dcn31/dcn31_resource.h" - -#include "dcn10/dcn10_ipp.h" -#include "dcn30/dcn30_hubbub.h" -#include "dcn31/dcn31_hubbub.h" -#include "dcn30/dcn30_mpc.h" -#include "dcn31/dcn31_hubp.h" -#include "irq/dcn315/irq_service_dcn315.h" -#include "dcn30/dcn30_dpp.h" -#include "dcn31/dcn31_optc.h" -#include "dcn20/dcn20_hwseq.h" -#include "dcn30/dcn30_hwseq.h" -#include "dce110/dce110_hwseq.h" -#include "dcn30/dcn30_opp.h" -#include "dcn20/dcn20_dsc.h" -#include "dcn30/dcn30_vpg.h" -#include "dcn30/dcn30_afmt.h" -#include "dcn30/dcn30_dio_stream_encoder.h" -#include "dcn31/dcn31_hpo_dp_stream_encoder.h" -#include "dcn31/dcn31_hpo_dp_link_encoder.h" -#include "dcn31/dcn31_apg.h" -#include "dcn31/dcn31_dio_link_encoder.h" -#include "dcn31/dcn31_vpg.h" -#include "dcn31/dcn31_afmt.h" -#include "dce/dce_clock_source.h" -#include "dce/dce_audio.h" -#include "dce/dce_hwseq.h" -#include "clk_mgr.h" -#include "virtual/virtual_stream_encoder.h" -#include "dce110/dce110_resource.h" -#include "dml/display_mode_vba.h" -#include "dml/dcn31/dcn31_fpu.h" -#include "dcn31/dcn31_dccg.h" -#include "dcn10/dcn10_resource.h" -#include "dcn31/dcn31_panel_cntl.h" - -#include "dcn30/dcn30_dwb.h" -#include "dcn30/dcn30_mmhubbub.h" - -#include "dcn/dcn_3_1_5_offset.h" -#include "dcn/dcn_3_1_5_sh_mask.h" -#include "dpcs/dpcs_4_2_2_offset.h" -#include "dpcs/dpcs_4_2_2_sh_mask.h" - -#define NBIO_BASE__INST0_SEG0 0x00000000 -#define NBIO_BASE__INST0_SEG1 0x00000014 -#define NBIO_BASE__INST0_SEG2 0x00000D20 -#define NBIO_BASE__INST0_SEG3 0x00010400 -#define NBIO_BASE__INST0_SEG4 0x0241B000 -#define NBIO_BASE__INST0_SEG5 0x04040000 - -#define DPCS_BASE__INST0_SEG0 0x00000012 -#define DPCS_BASE__INST0_SEG1 0x000000C0 -#define DPCS_BASE__INST0_SEG2 0x000034C0 -#define DPCS_BASE__INST0_SEG3 0x00009000 -#define DPCS_BASE__INST0_SEG4 0x02403C00 -#define DPCS_BASE__INST0_SEG5 0 - -#define DCN_BASE__INST0_SEG0 0x00000012 -#define DCN_BASE__INST0_SEG1 0x000000C0 -#define DCN_BASE__INST0_SEG2 0x000034C0 -#define DCN_BASE__INST0_SEG3 0x00009000 -#define DCN_BASE__INST0_SEG4 0x02403C00 -#define DCN_BASE__INST0_SEG5 0 - -#define regBIF_BX_PF2_RSMU_INDEX 0x0000 -#define regBIF_BX_PF2_RSMU_INDEX_BASE_IDX 1 -#define regBIF_BX_PF2_RSMU_DATA 0x0001 -#define regBIF_BX_PF2_RSMU_DATA_BASE_IDX 1 -#define regBIF_BX2_BIOS_SCRATCH_6 0x003e -#define regBIF_BX2_BIOS_SCRATCH_6_BASE_IDX 1 -#define BIF_BX2_BIOS_SCRATCH_6__BIOS_SCRATCH_6__SHIFT 0x0 -#define BIF_BX2_BIOS_SCRATCH_6__BIOS_SCRATCH_6_MASK 0xFFFFFFFFL -#define regBIF_BX2_BIOS_SCRATCH_2 0x003a -#define regBIF_BX2_BIOS_SCRATCH_2_BASE_IDX 1 -#define BIF_BX2_BIOS_SCRATCH_2__BIOS_SCRATCH_2__SHIFT 0x0 -#define BIF_BX2_BIOS_SCRATCH_2__BIOS_SCRATCH_2_MASK 0xFFFFFFFFL -#define regBIF_BX2_BIOS_SCRATCH_3 0x003b -#define regBIF_BX2_BIOS_SCRATCH_3_BASE_IDX 1 -#define BIF_BX2_BIOS_SCRATCH_3__BIOS_SCRATCH_3__SHIFT 0x0 -#define BIF_BX2_BIOS_SCRATCH_3__BIOS_SCRATCH_3_MASK 0xFFFFFFFFL - -#define regDCHUBBUB_DEBUG_CTRL_0 0x04d6 -#define regDCHUBBUB_DEBUG_CTRL_0_BASE_IDX 2 -#define DCHUBBUB_DEBUG_CTRL_0__DET_DEPTH__SHIFT 0x10 -#define DCHUBBUB_DEBUG_CTRL_0__DET_DEPTH_MASK 0x01FF0000L - -#include "reg_helper.h" -#include "dce/dmub_abm.h" -#include "dce/dmub_psr.h" -#include "dce/dce_aux.h" -#include "dce/dce_i2c.h" - -#include "dml/dcn30/display_mode_vba_30.h" -#include "vm_helper.h" -#include "dcn20/dcn20_vmid.h" - -#include "link_enc_cfg.h" - -#define DCN3_15_MAX_DET_SIZE 384 -#define DCN3_15_CRB_SEGMENT_SIZE_KB 64 -#define DCN3_15_MAX_DET_SEGS (DCN3_15_MAX_DET_SIZE / DCN3_15_CRB_SEGMENT_SIZE_KB) -/* Minimum 3 extra segments need to be in compbuf and claimable to guarantee seamless mpo transitions */ -#define MIN_RESERVED_DET_SEGS 3 - -enum dcn31_clk_src_array_id { - DCN31_CLK_SRC_PLL0, - DCN31_CLK_SRC_PLL1, - DCN31_CLK_SRC_PLL2, - DCN31_CLK_SRC_PLL3, - DCN31_CLK_SRC_PLL4, - DCN30_CLK_SRC_TOTAL -}; - -/* begin ********************* - * macros to expend register list macro defined in HW object header file - */ - -/* DCN */ -#define BASE_INNER(seg) DCN_BASE__INST0_SEG ## seg - -#define BASE(seg) BASE_INNER(seg) - -#define SR(reg_name)\ - .reg_name = BASE(reg ## reg_name ## _BASE_IDX) + \ - reg ## reg_name - -#define SRI(reg_name, block, id)\ - .reg_name = BASE(reg ## block ## id ## _ ## reg_name ## _BASE_IDX) + \ - reg ## block ## id ## _ ## reg_name - -#define SRI2(reg_name, block, id)\ - .reg_name = BASE(reg ## reg_name ## _BASE_IDX) + \ - reg ## reg_name - -#define SRIR(var_name, reg_name, block, id)\ - .var_name = BASE(reg ## block ## id ## _ ## reg_name ## _BASE_IDX) + \ - reg ## block ## id ## _ ## reg_name - -#define SRII(reg_name, block, id)\ - .reg_name[id] = BASE(reg ## block ## id ## _ ## reg_name ## _BASE_IDX) + \ - reg ## block ## id ## _ ## reg_name - -#define SRII_MPC_RMU(reg_name, block, id)\ - .RMU##_##reg_name[id] = BASE(reg ## block ## id ## _ ## reg_name ## _BASE_IDX) + \ - reg ## block ## id ## _ ## reg_name - -#define SRII_DWB(reg_name, temp_name, block, id)\ - .reg_name[id] = BASE(reg ## block ## id ## _ ## temp_name ## _BASE_IDX) + \ - reg ## block ## id ## _ ## temp_name - -#define SF_DWB2(reg_name, block, id, field_name, post_fix) \ - .field_name = reg_name ## __ ## field_name ## post_fix - -#define DCCG_SRII(reg_name, block, id)\ - .block ## _ ## reg_name[id] = BASE(reg ## block ## id ## _ ## reg_name ## _BASE_IDX) + \ - reg ## block ## id ## _ ## reg_name - -#define VUPDATE_SRII(reg_name, block, id)\ - .reg_name[id] = BASE(reg ## reg_name ## _ ## block ## id ## _BASE_IDX) + \ - reg ## reg_name ## _ ## block ## id - -/* NBIO */ -#define NBIO_BASE_INNER(seg) \ - NBIO_BASE__INST0_SEG ## seg - -#define NBIO_BASE(seg) \ - NBIO_BASE_INNER(seg) - -#define NBIO_SR(reg_name)\ - .reg_name = NBIO_BASE(regBIF_BX2_ ## reg_name ## _BASE_IDX) + \ - regBIF_BX2_ ## reg_name - -static const struct bios_registers bios_regs = { - NBIO_SR(BIOS_SCRATCH_3), - NBIO_SR(BIOS_SCRATCH_6) -}; - -#define clk_src_regs(index, pllid)\ -[index] = {\ - CS_COMMON_REG_LIST_DCN3_0(index, pllid),\ -} - -static const struct dce110_clk_src_regs clk_src_regs[] = { - clk_src_regs(0, A), - clk_src_regs(1, B), - clk_src_regs(2, C), - clk_src_regs(3, D), - clk_src_regs(4, E) -}; - -static const struct dce110_clk_src_shift cs_shift = { - CS_COMMON_MASK_SH_LIST_DCN2_0(__SHIFT) -}; - -static const struct dce110_clk_src_mask cs_mask = { - CS_COMMON_MASK_SH_LIST_DCN2_0(_MASK) -}; - -#define abm_regs(id)\ -[id] = {\ - ABM_DCN302_REG_LIST(id)\ -} - -static const struct dce_abm_registers abm_regs[] = { - abm_regs(0), - abm_regs(1), - abm_regs(2), - abm_regs(3), -}; - -static const struct dce_abm_shift abm_shift = { - ABM_MASK_SH_LIST_DCN30(__SHIFT) -}; - -static const struct dce_abm_mask abm_mask = { - ABM_MASK_SH_LIST_DCN30(_MASK) -}; - -#define audio_regs(id)\ -[id] = {\ - AUD_COMMON_REG_LIST(id)\ -} - -static const struct dce_audio_registers audio_regs[] = { - audio_regs(0), - audio_regs(1), - audio_regs(2), - audio_regs(3), - audio_regs(4), - audio_regs(5), - audio_regs(6) -}; - -#define DCE120_AUD_COMMON_MASK_SH_LIST(mask_sh)\ - SF(AZF0ENDPOINT0_AZALIA_F0_CODEC_ENDPOINT_INDEX, AZALIA_ENDPOINT_REG_INDEX, mask_sh),\ - SF(AZF0ENDPOINT0_AZALIA_F0_CODEC_ENDPOINT_DATA, AZALIA_ENDPOINT_REG_DATA, mask_sh),\ - AUD_COMMON_MASK_SH_LIST_BASE(mask_sh) - -static const struct dce_audio_shift audio_shift = { - DCE120_AUD_COMMON_MASK_SH_LIST(__SHIFT) -}; - -static const struct dce_audio_mask audio_mask = { - DCE120_AUD_COMMON_MASK_SH_LIST(_MASK) -}; - -#define vpg_regs(id)\ -[id] = {\ - VPG_DCN31_REG_LIST(id)\ -} - -static const struct dcn31_vpg_registers vpg_regs[] = { - vpg_regs(0), - vpg_regs(1), - vpg_regs(2), - vpg_regs(3), - vpg_regs(4), - vpg_regs(5), - vpg_regs(6), - vpg_regs(7), - vpg_regs(8), - vpg_regs(9), -}; - -static const struct dcn31_vpg_shift vpg_shift = { - DCN31_VPG_MASK_SH_LIST(__SHIFT) -}; - -static const struct dcn31_vpg_mask vpg_mask = { - DCN31_VPG_MASK_SH_LIST(_MASK) -}; - -#define afmt_regs(id)\ -[id] = {\ - AFMT_DCN31_REG_LIST(id)\ -} - -static const struct dcn31_afmt_registers afmt_regs[] = { - afmt_regs(0), - afmt_regs(1), - afmt_regs(2), - afmt_regs(3), - afmt_regs(4), - afmt_regs(5) -}; - -static const struct dcn31_afmt_shift afmt_shift = { - DCN31_AFMT_MASK_SH_LIST(__SHIFT) -}; - -static const struct dcn31_afmt_mask afmt_mask = { - DCN31_AFMT_MASK_SH_LIST(_MASK) -}; - -#define apg_regs(id)\ -[id] = {\ - APG_DCN31_REG_LIST(id)\ -} - -static const struct dcn31_apg_registers apg_regs[] = { - apg_regs(0), - apg_regs(1), - apg_regs(2), - apg_regs(3) -}; - -static const struct dcn31_apg_shift apg_shift = { - DCN31_APG_MASK_SH_LIST(__SHIFT) -}; - -static const struct dcn31_apg_mask apg_mask = { - DCN31_APG_MASK_SH_LIST(_MASK) -}; - -#define stream_enc_regs(id)\ -[id] = {\ - SE_DCN3_REG_LIST(id)\ -} - -static const struct dcn10_stream_enc_registers stream_enc_regs[] = { - stream_enc_regs(0), - stream_enc_regs(1), - stream_enc_regs(2), - stream_enc_regs(3), - stream_enc_regs(4) -}; - -static const struct dcn10_stream_encoder_shift se_shift = { - SE_COMMON_MASK_SH_LIST_DCN30(__SHIFT) -}; - -static const struct dcn10_stream_encoder_mask se_mask = { - SE_COMMON_MASK_SH_LIST_DCN30(_MASK) -}; - - -#define aux_regs(id)\ -[id] = {\ - DCN2_AUX_REG_LIST(id)\ -} - -static const struct dcn10_link_enc_aux_registers link_enc_aux_regs[] = { - aux_regs(0), - aux_regs(1), - aux_regs(2), - aux_regs(3), - aux_regs(4) -}; - -#define hpd_regs(id)\ -[id] = {\ - HPD_REG_LIST(id)\ -} - -static const struct dcn10_link_enc_hpd_registers link_enc_hpd_regs[] = { - hpd_regs(0), - hpd_regs(1), - hpd_regs(2), - hpd_regs(3), - hpd_regs(4) -}; - -#define link_regs(id, phyid)\ -[id] = {\ - LE_DCN31_REG_LIST(id), \ - UNIPHY_DCN2_REG_LIST(phyid), \ - DPCS_DCN31_REG_LIST(id), \ -} - -static const struct dce110_aux_registers_shift aux_shift = { - DCN_AUX_MASK_SH_LIST(__SHIFT) -}; - -static const struct dce110_aux_registers_mask aux_mask = { - DCN_AUX_MASK_SH_LIST(_MASK) -}; - -static const struct dcn10_link_enc_registers link_enc_regs[] = { - link_regs(0, A), - link_regs(1, B), - link_regs(2, C), - link_regs(3, D), - link_regs(4, E) -}; - -static const struct dcn10_link_enc_shift le_shift = { - LINK_ENCODER_MASK_SH_LIST_DCN31(__SHIFT), \ - DPCS_DCN31_MASK_SH_LIST(__SHIFT) -}; - -static const struct dcn10_link_enc_mask le_mask = { - LINK_ENCODER_MASK_SH_LIST_DCN31(_MASK), \ - DPCS_DCN31_MASK_SH_LIST(_MASK) -}; - -#define hpo_dp_stream_encoder_reg_list(id)\ -[id] = {\ - DCN3_1_HPO_DP_STREAM_ENC_REG_LIST(id)\ -} - -static const struct dcn31_hpo_dp_stream_encoder_registers hpo_dp_stream_enc_regs[] = { - hpo_dp_stream_encoder_reg_list(0), - hpo_dp_stream_encoder_reg_list(1), - hpo_dp_stream_encoder_reg_list(2), - hpo_dp_stream_encoder_reg_list(3), -}; - -static const struct dcn31_hpo_dp_stream_encoder_shift hpo_dp_se_shift = { - DCN3_1_HPO_DP_STREAM_ENC_MASK_SH_LIST(__SHIFT) -}; - -static const struct dcn31_hpo_dp_stream_encoder_mask hpo_dp_se_mask = { - DCN3_1_HPO_DP_STREAM_ENC_MASK_SH_LIST(_MASK) -}; - - -#define hpo_dp_link_encoder_reg_list(id)\ -[id] = {\ - DCN3_1_HPO_DP_LINK_ENC_REG_LIST(id),\ - DCN3_1_RDPCSTX_REG_LIST(0),\ - DCN3_1_RDPCSTX_REG_LIST(1),\ - DCN3_1_RDPCSTX_REG_LIST(2),\ - DCN3_1_RDPCSTX_REG_LIST(3),\ - DCN3_1_RDPCSTX_REG_LIST(4)\ -} - -static const struct dcn31_hpo_dp_link_encoder_registers hpo_dp_link_enc_regs[] = { - hpo_dp_link_encoder_reg_list(0), - hpo_dp_link_encoder_reg_list(1), -}; - -static const struct dcn31_hpo_dp_link_encoder_shift hpo_dp_le_shift = { - DCN3_1_HPO_DP_LINK_ENC_MASK_SH_LIST(__SHIFT) -}; - -static const struct dcn31_hpo_dp_link_encoder_mask hpo_dp_le_mask = { - DCN3_1_HPO_DP_LINK_ENC_MASK_SH_LIST(_MASK) -}; - -#define dpp_regs(id)\ -[id] = {\ - DPP_REG_LIST_DCN30(id),\ -} - -static const struct dcn3_dpp_registers dpp_regs[] = { - dpp_regs(0), - dpp_regs(1), - dpp_regs(2), - dpp_regs(3) -}; - -static const struct dcn3_dpp_shift tf_shift = { - DPP_REG_LIST_SH_MASK_DCN30(__SHIFT) -}; - -static const struct dcn3_dpp_mask tf_mask = { - DPP_REG_LIST_SH_MASK_DCN30(_MASK) -}; - -#define opp_regs(id)\ -[id] = {\ - OPP_REG_LIST_DCN30(id),\ -} - -static const struct dcn20_opp_registers opp_regs[] = { - opp_regs(0), - opp_regs(1), - opp_regs(2), - opp_regs(3) -}; - -static const struct dcn20_opp_shift opp_shift = { - OPP_MASK_SH_LIST_DCN20(__SHIFT) -}; - -static const struct dcn20_opp_mask opp_mask = { - OPP_MASK_SH_LIST_DCN20(_MASK) -}; - -#define aux_engine_regs(id)\ -[id] = {\ - AUX_COMMON_REG_LIST0(id), \ - .AUXN_IMPCAL = 0, \ - .AUXP_IMPCAL = 0, \ - .AUX_RESET_MASK = DP_AUX0_AUX_CONTROL__AUX_RESET_MASK, \ -} - -static const struct dce110_aux_registers aux_engine_regs[] = { - aux_engine_regs(0), - aux_engine_regs(1), - aux_engine_regs(2), - aux_engine_regs(3), - aux_engine_regs(4) -}; - -#define dwbc_regs_dcn3(id)\ -[id] = {\ - DWBC_COMMON_REG_LIST_DCN30(id),\ -} - -static const struct dcn30_dwbc_registers dwbc30_regs[] = { - dwbc_regs_dcn3(0), -}; - -static const struct dcn30_dwbc_shift dwbc30_shift = { - DWBC_COMMON_MASK_SH_LIST_DCN30(__SHIFT) -}; - -static const struct dcn30_dwbc_mask dwbc30_mask = { - DWBC_COMMON_MASK_SH_LIST_DCN30(_MASK) -}; - -#define mcif_wb_regs_dcn3(id)\ -[id] = {\ - MCIF_WB_COMMON_REG_LIST_DCN30(id),\ -} - -static const struct dcn30_mmhubbub_registers mcif_wb30_regs[] = { - mcif_wb_regs_dcn3(0) -}; - -static const struct dcn30_mmhubbub_shift mcif_wb30_shift = { - MCIF_WB_COMMON_MASK_SH_LIST_DCN30(__SHIFT) -}; - -static const struct dcn30_mmhubbub_mask mcif_wb30_mask = { - MCIF_WB_COMMON_MASK_SH_LIST_DCN30(_MASK) -}; - -#define dsc_regsDCN20(id)\ -[id] = {\ - DSC_REG_LIST_DCN20(id)\ -} - -static const struct dcn20_dsc_registers dsc_regs[] = { - dsc_regsDCN20(0), - dsc_regsDCN20(1), - dsc_regsDCN20(2) -}; - -static const struct dcn20_dsc_shift dsc_shift = { - DSC_REG_LIST_SH_MASK_DCN20(__SHIFT) -}; - -static const struct dcn20_dsc_mask dsc_mask = { - DSC_REG_LIST_SH_MASK_DCN20(_MASK) -}; - -static const struct dcn30_mpc_registers mpc_regs = { - MPC_REG_LIST_DCN3_0(0), - MPC_REG_LIST_DCN3_0(1), - MPC_REG_LIST_DCN3_0(2), - MPC_REG_LIST_DCN3_0(3), - MPC_OUT_MUX_REG_LIST_DCN3_0(0), - MPC_OUT_MUX_REG_LIST_DCN3_0(1), - MPC_OUT_MUX_REG_LIST_DCN3_0(2), - MPC_OUT_MUX_REG_LIST_DCN3_0(3), - MPC_DWB_MUX_REG_LIST_DCN3_0(0), -}; - -static const struct dcn30_mpc_shift mpc_shift = { - MPC_COMMON_MASK_SH_LIST_DCN30(__SHIFT) -}; - -static const struct dcn30_mpc_mask mpc_mask = { - MPC_COMMON_MASK_SH_LIST_DCN30(_MASK) -}; - -#define optc_regs(id)\ -[id] = {OPTC_COMMON_REG_LIST_DCN3_1(id)} - -static const struct dcn_optc_registers optc_regs[] = { - optc_regs(0), - optc_regs(1), - optc_regs(2), - optc_regs(3) -}; - -static const struct dcn_optc_shift optc_shift = { - OPTC_COMMON_MASK_SH_LIST_DCN3_1(__SHIFT) -}; - -static const struct dcn_optc_mask optc_mask = { - OPTC_COMMON_MASK_SH_LIST_DCN3_1(_MASK) -}; - -#define hubp_regs(id)\ -[id] = {\ - HUBP_REG_LIST_DCN30(id)\ -} - -static const struct dcn_hubp2_registers hubp_regs[] = { - hubp_regs(0), - hubp_regs(1), - hubp_regs(2), - hubp_regs(3) -}; - - -static const struct dcn_hubp2_shift hubp_shift = { - HUBP_MASK_SH_LIST_DCN31(__SHIFT) -}; - -static const struct dcn_hubp2_mask hubp_mask = { - HUBP_MASK_SH_LIST_DCN31(_MASK) -}; -static const struct dcn_hubbub_registers hubbub_reg = { - HUBBUB_REG_LIST_DCN31(0) -}; - -static const struct dcn_hubbub_shift hubbub_shift = { - HUBBUB_MASK_SH_LIST_DCN31(__SHIFT) -}; - -static const struct dcn_hubbub_mask hubbub_mask = { - HUBBUB_MASK_SH_LIST_DCN31(_MASK) -}; - -static const struct dccg_registers dccg_regs = { - DCCG_REG_LIST_DCN31() -}; - -static const struct dccg_shift dccg_shift = { - DCCG_MASK_SH_LIST_DCN31(__SHIFT) -}; - -static const struct dccg_mask dccg_mask = { - DCCG_MASK_SH_LIST_DCN31(_MASK) -}; - - -#define SRII2(reg_name_pre, reg_name_post, id)\ - .reg_name_pre ## _ ## reg_name_post[id] = BASE(reg ## reg_name_pre \ - ## id ## _ ## reg_name_post ## _BASE_IDX) + \ - reg ## reg_name_pre ## id ## _ ## reg_name_post - - -#define HWSEQ_DCN31_REG_LIST()\ - SR(DCHUBBUB_GLOBAL_TIMER_CNTL), \ - SR(DCHUBBUB_ARB_HOSTVM_CNTL), \ - SR(DIO_MEM_PWR_CTRL), \ - SR(ODM_MEM_PWR_CTRL3), \ - SR(DMU_MEM_PWR_CNTL), \ - SR(MMHUBBUB_MEM_PWR_CNTL), \ - SR(DCCG_GATE_DISABLE_CNTL), \ - SR(DCCG_GATE_DISABLE_CNTL2), \ - SR(DCFCLK_CNTL),\ - SR(DC_MEM_GLOBAL_PWR_REQ_CNTL), \ - SRII(PIXEL_RATE_CNTL, OTG, 0), \ - SRII(PIXEL_RATE_CNTL, OTG, 1),\ - SRII(PIXEL_RATE_CNTL, OTG, 2),\ - SRII(PIXEL_RATE_CNTL, OTG, 3),\ - SRII(PHYPLL_PIXEL_RATE_CNTL, OTG, 0),\ - SRII(PHYPLL_PIXEL_RATE_CNTL, OTG, 1),\ - SRII(PHYPLL_PIXEL_RATE_CNTL, OTG, 2),\ - SRII(PHYPLL_PIXEL_RATE_CNTL, OTG, 3),\ - SR(MICROSECOND_TIME_BASE_DIV), \ - SR(MILLISECOND_TIME_BASE_DIV), \ - SR(DISPCLK_FREQ_CHANGE_CNTL), \ - SR(RBBMIF_TIMEOUT_DIS), \ - SR(RBBMIF_TIMEOUT_DIS_2), \ - SR(DCHUBBUB_CRC_CTRL), \ - SR(DPP_TOP0_DPP_CRC_CTRL), \ - SR(DPP_TOP0_DPP_CRC_VAL_B_A), \ - SR(DPP_TOP0_DPP_CRC_VAL_R_G), \ - SR(MPC_CRC_CTRL), \ - SR(MPC_CRC_RESULT_GB), \ - SR(MPC_CRC_RESULT_C), \ - SR(MPC_CRC_RESULT_AR), \ - SR(DOMAIN0_PG_CONFIG), \ - SR(DOMAIN1_PG_CONFIG), \ - SR(DOMAIN2_PG_CONFIG), \ - SR(DOMAIN3_PG_CONFIG), \ - SR(DOMAIN16_PG_CONFIG), \ - SR(DOMAIN17_PG_CONFIG), \ - SR(DOMAIN18_PG_CONFIG), \ - SR(DOMAIN0_PG_STATUS), \ - SR(DOMAIN1_PG_STATUS), \ - SR(DOMAIN2_PG_STATUS), \ - SR(DOMAIN3_PG_STATUS), \ - SR(DOMAIN16_PG_STATUS), \ - SR(DOMAIN17_PG_STATUS), \ - SR(DOMAIN18_PG_STATUS), \ - SR(D1VGA_CONTROL), \ - SR(D2VGA_CONTROL), \ - SR(D3VGA_CONTROL), \ - SR(D4VGA_CONTROL), \ - SR(D5VGA_CONTROL), \ - SR(D6VGA_CONTROL), \ - SR(DC_IP_REQUEST_CNTL), \ - SR(AZALIA_AUDIO_DTO), \ - SR(AZALIA_CONTROLLER_CLOCK_GATING), \ - SR(HPO_TOP_HW_CONTROL) - -static const struct dce_hwseq_registers hwseq_reg = { - HWSEQ_DCN31_REG_LIST() -}; - -#define HWSEQ_DCN31_MASK_SH_LIST(mask_sh)\ - HWSEQ_DCN_MASK_SH_LIST(mask_sh), \ - HWS_SF(, DCHUBBUB_GLOBAL_TIMER_CNTL, DCHUBBUB_GLOBAL_TIMER_REFDIV, mask_sh), \ - HWS_SF(, DCHUBBUB_ARB_HOSTVM_CNTL, DISABLE_HOSTVM_FORCE_ALLOW_PSTATE, mask_sh), \ - HWS_SF(, DOMAIN0_PG_CONFIG, DOMAIN_POWER_FORCEON, mask_sh), \ - HWS_SF(, DOMAIN0_PG_CONFIG, DOMAIN_POWER_GATE, mask_sh), \ - HWS_SF(, DOMAIN1_PG_CONFIG, DOMAIN_POWER_FORCEON, mask_sh), \ - HWS_SF(, DOMAIN1_PG_CONFIG, DOMAIN_POWER_GATE, mask_sh), \ - HWS_SF(, DOMAIN2_PG_CONFIG, DOMAIN_POWER_FORCEON, mask_sh), \ - HWS_SF(, DOMAIN2_PG_CONFIG, DOMAIN_POWER_GATE, mask_sh), \ - HWS_SF(, DOMAIN3_PG_CONFIG, DOMAIN_POWER_FORCEON, mask_sh), \ - HWS_SF(, DOMAIN3_PG_CONFIG, DOMAIN_POWER_GATE, mask_sh), \ - HWS_SF(, DOMAIN16_PG_CONFIG, DOMAIN_POWER_FORCEON, mask_sh), \ - HWS_SF(, DOMAIN16_PG_CONFIG, DOMAIN_POWER_GATE, mask_sh), \ - HWS_SF(, DOMAIN17_PG_CONFIG, DOMAIN_POWER_FORCEON, mask_sh), \ - HWS_SF(, DOMAIN17_PG_CONFIG, DOMAIN_POWER_GATE, mask_sh), \ - HWS_SF(, DOMAIN18_PG_CONFIG, DOMAIN_POWER_FORCEON, mask_sh), \ - HWS_SF(, DOMAIN18_PG_CONFIG, DOMAIN_POWER_GATE, mask_sh), \ - HWS_SF(, DOMAIN0_PG_STATUS, DOMAIN_PGFSM_PWR_STATUS, mask_sh), \ - HWS_SF(, DOMAIN1_PG_STATUS, DOMAIN_PGFSM_PWR_STATUS, mask_sh), \ - HWS_SF(, DOMAIN2_PG_STATUS, DOMAIN_PGFSM_PWR_STATUS, mask_sh), \ - HWS_SF(, DOMAIN3_PG_STATUS, DOMAIN_PGFSM_PWR_STATUS, mask_sh), \ - HWS_SF(, DOMAIN16_PG_STATUS, DOMAIN_PGFSM_PWR_STATUS, mask_sh), \ - HWS_SF(, DOMAIN17_PG_STATUS, DOMAIN_PGFSM_PWR_STATUS, mask_sh), \ - HWS_SF(, DOMAIN18_PG_STATUS, DOMAIN_PGFSM_PWR_STATUS, mask_sh), \ - HWS_SF(, DC_IP_REQUEST_CNTL, IP_REQUEST_EN, mask_sh), \ - HWS_SF(, AZALIA_AUDIO_DTO, AZALIA_AUDIO_DTO_MODULE, mask_sh), \ - HWS_SF(, HPO_TOP_CLOCK_CONTROL, HPO_HDMISTREAMCLK_G_GATE_DIS, mask_sh), \ - HWS_SF(, DMU_MEM_PWR_CNTL, DMCU_ERAM_MEM_PWR_FORCE, mask_sh), \ - HWS_SF(, ODM_MEM_PWR_CTRL3, ODM_MEM_UNASSIGNED_PWR_MODE, mask_sh), \ - HWS_SF(, ODM_MEM_PWR_CTRL3, ODM_MEM_VBLANK_PWR_MODE, mask_sh), \ - HWS_SF(, MMHUBBUB_MEM_PWR_CNTL, VGA_MEM_PWR_FORCE, mask_sh), \ - HWS_SF(, DIO_MEM_PWR_CTRL, I2C_LIGHT_SLEEP_FORCE, mask_sh), \ - HWS_SF(, HPO_TOP_HW_CONTROL, HPO_IO_EN, mask_sh) - -static const struct dce_hwseq_shift hwseq_shift = { - HWSEQ_DCN31_MASK_SH_LIST(__SHIFT) -}; - -static const struct dce_hwseq_mask hwseq_mask = { - HWSEQ_DCN31_MASK_SH_LIST(_MASK) -}; -#define vmid_regs(id)\ -[id] = {\ - DCN20_VMID_REG_LIST(id)\ -} - -static const struct dcn_vmid_registers vmid_regs[] = { - vmid_regs(0), - vmid_regs(1), - vmid_regs(2), - vmid_regs(3), - vmid_regs(4), - vmid_regs(5), - vmid_regs(6), - vmid_regs(7), - vmid_regs(8), - vmid_regs(9), - vmid_regs(10), - vmid_regs(11), - vmid_regs(12), - vmid_regs(13), - vmid_regs(14), - vmid_regs(15) -}; - -static const struct dcn20_vmid_shift vmid_shifts = { - DCN20_VMID_MASK_SH_LIST(__SHIFT) -}; - -static const struct dcn20_vmid_mask vmid_masks = { - DCN20_VMID_MASK_SH_LIST(_MASK) -}; - -static const struct resource_caps res_cap_dcn31 = { - .num_timing_generator = 4, - .num_opp = 4, - .num_video_plane = 4, - .num_audio = 5, - .num_stream_encoder = 5, - .num_dig_link_enc = 5, - .num_hpo_dp_stream_encoder = 4, - .num_hpo_dp_link_encoder = 2, - .num_pll = 5, - .num_dwb = 1, - .num_ddc = 5, - .num_vmid = 16, - .num_mpc_3dlut = 2, - .num_dsc = 3, -}; - -static const struct dc_plane_cap plane_cap = { - .type = DC_PLANE_TYPE_DCN_UNIVERSAL, - .per_pixel_alpha = true, - - .pixel_format_support = { - .argb8888 = true, - .nv12 = true, - .fp16 = true, - .p010 = true, - .ayuv = false, - }, - - .max_upscale_factor = { - .argb8888 = 16000, - .nv12 = 16000, - .fp16 = 16000 - }, - - // 6:1 downscaling ratio: 1000/6 = 166.666 - .max_downscale_factor = { - .argb8888 = 167, - .nv12 = 167, - .fp16 = 167 - }, - 64, - 64 -}; - -static const struct dc_debug_options debug_defaults_drv = { - .disable_z10 = true, /*hw not support it*/ - .disable_dmcu = true, - .force_abm_enable = false, - .timing_trace = false, - .clock_trace = true, - .disable_pplib_clock_request = false, - .pipe_split_policy = MPC_SPLIT_DYNAMIC, - .force_single_disp_pipe_split = false, - .disable_dcc = DCC_ENABLE, - .vsr_support = true, - .performance_trace = false, - .max_downscale_src_width = 4096,/*upto true 4k*/ - .disable_pplib_wm_range = false, - .scl_reset_length10 = true, - .sanity_checks = false, - .underflow_assert_delay_us = 0xFFFFFFFF, - .dwb_fi_phase = -1, // -1 = disable, - .dmub_command_table = true, - .pstate_enabled = true, - .use_max_lb = true, - .enable_mem_low_power = { - .bits = { - .vga = true, - .i2c = true, - .dmcu = false, // This is previously known to cause hang on S3 cycles if enabled - .dscl = true, - .cm = true, - .mpc = true, - .optc = true, - .vpg = true, - .afmt = true, - } - }, - .enable_legacy_fast_update = true, - .psr_power_use_phy_fsm = 0, - .using_dml2 = false, -}; - -static const struct dc_panel_config panel_config_defaults = { - .psr = { - .disable_psr = false, - .disallow_psrsu = false, - .disallow_replay = false, - }, - .ilr = { - .optimize_edp_link_rate = true, - }, -}; - -static void dcn31_dpp_destroy(struct dpp **dpp) -{ - kfree(TO_DCN20_DPP(*dpp)); - *dpp = NULL; -} - -static struct dpp *dcn31_dpp_create( - struct dc_context *ctx, - uint32_t inst) -{ - struct dcn3_dpp *dpp = - kzalloc(sizeof(struct dcn3_dpp), GFP_KERNEL); - - if (!dpp) - return NULL; - - if (dpp3_construct(dpp, ctx, inst, - &dpp_regs[inst], &tf_shift, &tf_mask)) - return &dpp->base; - - BREAK_TO_DEBUGGER(); - kfree(dpp); - return NULL; -} - -static struct output_pixel_processor *dcn31_opp_create( - struct dc_context *ctx, uint32_t inst) -{ - struct dcn20_opp *opp = - kzalloc(sizeof(struct dcn20_opp), GFP_KERNEL); - - if (!opp) { - BREAK_TO_DEBUGGER(); - return NULL; - } - - dcn20_opp_construct(opp, ctx, inst, - &opp_regs[inst], &opp_shift, &opp_mask); - return &opp->base; -} - -static struct dce_aux *dcn31_aux_engine_create( - struct dc_context *ctx, - uint32_t inst) -{ - struct aux_engine_dce110 *aux_engine = - kzalloc(sizeof(struct aux_engine_dce110), GFP_KERNEL); - - if (!aux_engine) - return NULL; - - dce110_aux_engine_construct(aux_engine, ctx, inst, - SW_AUX_TIMEOUT_PERIOD_MULTIPLIER * AUX_TIMEOUT_PERIOD, - &aux_engine_regs[inst], - &aux_mask, - &aux_shift, - ctx->dc->caps.extended_aux_timeout_support); - - return &aux_engine->base; -} -#define i2c_inst_regs(id) { I2C_HW_ENGINE_COMMON_REG_LIST_DCN30(id) } - -static const struct dce_i2c_registers i2c_hw_regs[] = { - i2c_inst_regs(1), - i2c_inst_regs(2), - i2c_inst_regs(3), - i2c_inst_regs(4), - i2c_inst_regs(5), -}; - -static const struct dce_i2c_shift i2c_shifts = { - I2C_COMMON_MASK_SH_LIST_DCN30(__SHIFT) -}; - -static const struct dce_i2c_mask i2c_masks = { - I2C_COMMON_MASK_SH_LIST_DCN30(_MASK) -}; - -static struct dce_i2c_hw *dcn31_i2c_hw_create( - struct dc_context *ctx, - uint32_t inst) -{ - struct dce_i2c_hw *dce_i2c_hw = - kzalloc(sizeof(struct dce_i2c_hw), GFP_KERNEL); - - if (!dce_i2c_hw) - return NULL; - - dcn2_i2c_hw_construct(dce_i2c_hw, ctx, inst, - &i2c_hw_regs[inst], &i2c_shifts, &i2c_masks); - - return dce_i2c_hw; -} -static struct mpc *dcn31_mpc_create( - struct dc_context *ctx, - int num_mpcc, - int num_rmu) -{ - struct dcn30_mpc *mpc30 = kzalloc(sizeof(struct dcn30_mpc), - GFP_KERNEL); - - if (!mpc30) - return NULL; - - dcn30_mpc_construct(mpc30, ctx, - &mpc_regs, - &mpc_shift, - &mpc_mask, - num_mpcc, - num_rmu); - - return &mpc30->base; -} - -static struct hubbub *dcn31_hubbub_create(struct dc_context *ctx) -{ - int i; - - struct dcn20_hubbub *hubbub3 = kzalloc(sizeof(struct dcn20_hubbub), - GFP_KERNEL); - - if (!hubbub3) - return NULL; - - hubbub31_construct(hubbub3, ctx, - &hubbub_reg, - &hubbub_shift, - &hubbub_mask, - dcn3_15_ip.det_buffer_size_kbytes, - dcn3_15_ip.pixel_chunk_size_kbytes, - dcn3_15_ip.config_return_buffer_size_in_kbytes); - - - for (i = 0; i < res_cap_dcn31.num_vmid; i++) { - struct dcn20_vmid *vmid = &hubbub3->vmid[i]; - - vmid->ctx = ctx; - - vmid->regs = &vmid_regs[i]; - vmid->shifts = &vmid_shifts; - vmid->masks = &vmid_masks; - } - - return &hubbub3->base; -} - -static struct timing_generator *dcn31_timing_generator_create( - struct dc_context *ctx, - uint32_t instance) -{ - struct optc *tgn10 = - kzalloc(sizeof(struct optc), GFP_KERNEL); - - if (!tgn10) - return NULL; - - tgn10->base.inst = instance; - tgn10->base.ctx = ctx; - - tgn10->tg_regs = &optc_regs[instance]; - tgn10->tg_shift = &optc_shift; - tgn10->tg_mask = &optc_mask; - - dcn31_timing_generator_init(tgn10); - - return &tgn10->base; -} - -static const struct encoder_feature_support link_enc_feature = { - .max_hdmi_deep_color = COLOR_DEPTH_121212, - .max_hdmi_pixel_clock = 600000, - .hdmi_ycbcr420_supported = true, - .dp_ycbcr420_supported = true, - .fec_supported = true, - .flags.bits.IS_HBR2_CAPABLE = true, - .flags.bits.IS_HBR3_CAPABLE = true, - .flags.bits.IS_TPS3_CAPABLE = true, - .flags.bits.IS_TPS4_CAPABLE = true -}; - -static struct link_encoder *dcn31_link_encoder_create( - struct dc_context *ctx, - const struct encoder_init_data *enc_init_data) -{ - struct dcn20_link_encoder *enc20 = - kzalloc(sizeof(struct dcn20_link_encoder), GFP_KERNEL); - - if (!enc20) - return NULL; - - dcn31_link_encoder_construct(enc20, - enc_init_data, - &link_enc_feature, - &link_enc_regs[enc_init_data->transmitter], - &link_enc_aux_regs[enc_init_data->channel - 1], - &link_enc_hpd_regs[enc_init_data->hpd_source], - &le_shift, - &le_mask); - - return &enc20->enc10.base; -} - -/* Create a minimal link encoder object not associated with a particular - * physical connector. - * resource_funcs.link_enc_create_minimal - */ -static struct link_encoder *dcn31_link_enc_create_minimal( - struct dc_context *ctx, enum engine_id eng_id) -{ - struct dcn20_link_encoder *enc20; - - if ((eng_id - ENGINE_ID_DIGA) > ctx->dc->res_pool->res_cap->num_dig_link_enc) - return NULL; - - enc20 = kzalloc(sizeof(struct dcn20_link_encoder), GFP_KERNEL); - if (!enc20) - return NULL; - - dcn31_link_encoder_construct_minimal( - enc20, - ctx, - &link_enc_feature, - &link_enc_regs[eng_id - ENGINE_ID_DIGA], - eng_id); - - return &enc20->enc10.base; -} - -static struct panel_cntl *dcn31_panel_cntl_create(const struct panel_cntl_init_data *init_data) -{ - struct dcn31_panel_cntl *panel_cntl = - kzalloc(sizeof(struct dcn31_panel_cntl), GFP_KERNEL); - - if (!panel_cntl) - return NULL; - - dcn31_panel_cntl_construct(panel_cntl, init_data); - - return &panel_cntl->base; -} - -static void read_dce_straps( - struct dc_context *ctx, - struct resource_straps *straps) -{ - generic_reg_get(ctx, regDC_PINSTRAPS + BASE(regDC_PINSTRAPS_BASE_IDX), - FN(DC_PINSTRAPS, DC_PINSTRAPS_AUDIO), &straps->dc_pinstraps_audio); - -} - -static struct audio *dcn31_create_audio( - struct dc_context *ctx, unsigned int inst) -{ - return dce_audio_create(ctx, inst, - &audio_regs[inst], &audio_shift, &audio_mask); -} - -static struct vpg *dcn31_vpg_create( - struct dc_context *ctx, - uint32_t inst) -{ - struct dcn31_vpg *vpg31 = kzalloc(sizeof(struct dcn31_vpg), GFP_KERNEL); - - if (!vpg31) - return NULL; - - vpg31_construct(vpg31, ctx, inst, - &vpg_regs[inst], - &vpg_shift, - &vpg_mask); - - return &vpg31->base; -} - -static struct afmt *dcn31_afmt_create( - struct dc_context *ctx, - uint32_t inst) -{ - struct dcn31_afmt *afmt31 = kzalloc(sizeof(struct dcn31_afmt), GFP_KERNEL); - - if (!afmt31) - return NULL; - - afmt31_construct(afmt31, ctx, inst, - &afmt_regs[inst], - &afmt_shift, - &afmt_mask); - - // Light sleep by default, no need to power down here - - return &afmt31->base; -} - -static struct apg *dcn31_apg_create( - struct dc_context *ctx, - uint32_t inst) -{ - struct dcn31_apg *apg31 = kzalloc(sizeof(struct dcn31_apg), GFP_KERNEL); - - if (!apg31) - return NULL; - - apg31_construct(apg31, ctx, inst, - &apg_regs[inst], - &apg_shift, - &apg_mask); - - return &apg31->base; -} - -static struct stream_encoder *dcn315_stream_encoder_create( - enum engine_id eng_id, - struct dc_context *ctx) -{ - struct dcn10_stream_encoder *enc1; - struct vpg *vpg; - struct afmt *afmt; - int vpg_inst; - int afmt_inst; - - /*PHYB is wired off in HW, allow front end to remapping, otherwise needs more changes*/ - - /* Mapping of VPG, AFMT, DME register blocks to DIO block instance */ - if (eng_id <= ENGINE_ID_DIGF) { - vpg_inst = eng_id; - afmt_inst = eng_id; - } else - return NULL; - - enc1 = kzalloc(sizeof(struct dcn10_stream_encoder), GFP_KERNEL); - vpg = dcn31_vpg_create(ctx, vpg_inst); - afmt = dcn31_afmt_create(ctx, afmt_inst); - - if (!enc1 || !vpg || !afmt) { - kfree(enc1); - kfree(vpg); - kfree(afmt); - return NULL; - } - - dcn30_dio_stream_encoder_construct(enc1, ctx, ctx->dc_bios, - eng_id, vpg, afmt, - &stream_enc_regs[eng_id], - &se_shift, &se_mask); - - return &enc1->base; -} - -static struct hpo_dp_stream_encoder *dcn31_hpo_dp_stream_encoder_create( - enum engine_id eng_id, - struct dc_context *ctx) -{ - struct dcn31_hpo_dp_stream_encoder *hpo_dp_enc31; - struct vpg *vpg; - struct apg *apg; - uint32_t hpo_dp_inst; - uint32_t vpg_inst; - uint32_t apg_inst; - - ASSERT((eng_id >= ENGINE_ID_HPO_DP_0) && (eng_id <= ENGINE_ID_HPO_DP_3)); - hpo_dp_inst = eng_id - ENGINE_ID_HPO_DP_0; - - /* Mapping of VPG register blocks to HPO DP block instance: - * VPG[6] -> HPO_DP[0] - * VPG[7] -> HPO_DP[1] - * VPG[8] -> HPO_DP[2] - * VPG[9] -> HPO_DP[3] - */ - vpg_inst = hpo_dp_inst + 6; - - /* Mapping of APG register blocks to HPO DP block instance: - * APG[0] -> HPO_DP[0] - * APG[1] -> HPO_DP[1] - * APG[2] -> HPO_DP[2] - * APG[3] -> HPO_DP[3] - */ - apg_inst = hpo_dp_inst; - - /* allocate HPO stream encoder and create VPG sub-block */ - hpo_dp_enc31 = kzalloc(sizeof(struct dcn31_hpo_dp_stream_encoder), GFP_KERNEL); - vpg = dcn31_vpg_create(ctx, vpg_inst); - apg = dcn31_apg_create(ctx, apg_inst); - - if (!hpo_dp_enc31 || !vpg || !apg) { - kfree(hpo_dp_enc31); - kfree(vpg); - kfree(apg); - return NULL; - } - - dcn31_hpo_dp_stream_encoder_construct(hpo_dp_enc31, ctx, ctx->dc_bios, - hpo_dp_inst, eng_id, vpg, apg, - &hpo_dp_stream_enc_regs[hpo_dp_inst], - &hpo_dp_se_shift, &hpo_dp_se_mask); - - return &hpo_dp_enc31->base; -} - -static struct hpo_dp_link_encoder *dcn31_hpo_dp_link_encoder_create( - uint8_t inst, - struct dc_context *ctx) -{ - struct dcn31_hpo_dp_link_encoder *hpo_dp_enc31; - - /* allocate HPO link encoder */ - hpo_dp_enc31 = kzalloc(sizeof(struct dcn31_hpo_dp_link_encoder), GFP_KERNEL); - - hpo_dp_link_encoder31_construct(hpo_dp_enc31, ctx, inst, - &hpo_dp_link_enc_regs[inst], - &hpo_dp_le_shift, &hpo_dp_le_mask); - - return &hpo_dp_enc31->base; -} - -static struct dce_hwseq *dcn31_hwseq_create( - struct dc_context *ctx) -{ - struct dce_hwseq *hws = kzalloc(sizeof(struct dce_hwseq), GFP_KERNEL); - - if (hws) { - hws->ctx = ctx; - hws->regs = &hwseq_reg; - hws->shifts = &hwseq_shift; - hws->masks = &hwseq_mask; - } - return hws; -} -static const struct resource_create_funcs res_create_funcs = { - .read_dce_straps = read_dce_straps, - .create_audio = dcn31_create_audio, - .create_stream_encoder = dcn315_stream_encoder_create, - .create_hpo_dp_stream_encoder = dcn31_hpo_dp_stream_encoder_create, - .create_hpo_dp_link_encoder = dcn31_hpo_dp_link_encoder_create, - .create_hwseq = dcn31_hwseq_create, -}; - -static void dcn315_resource_destruct(struct dcn315_resource_pool *pool) -{ - unsigned int i; - - for (i = 0; i < pool->base.stream_enc_count; i++) { - if (pool->base.stream_enc[i] != NULL) { - if (pool->base.stream_enc[i]->vpg != NULL) { - kfree(DCN30_VPG_FROM_VPG(pool->base.stream_enc[i]->vpg)); - pool->base.stream_enc[i]->vpg = NULL; - } - if (pool->base.stream_enc[i]->afmt != NULL) { - kfree(DCN30_AFMT_FROM_AFMT(pool->base.stream_enc[i]->afmt)); - pool->base.stream_enc[i]->afmt = NULL; - } - kfree(DCN10STRENC_FROM_STRENC(pool->base.stream_enc[i])); - pool->base.stream_enc[i] = NULL; - } - } - - for (i = 0; i < pool->base.hpo_dp_stream_enc_count; i++) { - if (pool->base.hpo_dp_stream_enc[i] != NULL) { - if (pool->base.hpo_dp_stream_enc[i]->vpg != NULL) { - kfree(DCN30_VPG_FROM_VPG(pool->base.hpo_dp_stream_enc[i]->vpg)); - pool->base.hpo_dp_stream_enc[i]->vpg = NULL; - } - if (pool->base.hpo_dp_stream_enc[i]->apg != NULL) { - kfree(DCN31_APG_FROM_APG(pool->base.hpo_dp_stream_enc[i]->apg)); - pool->base.hpo_dp_stream_enc[i]->apg = NULL; - } - kfree(DCN3_1_HPO_DP_STREAM_ENC_FROM_HPO_STREAM_ENC(pool->base.hpo_dp_stream_enc[i])); - pool->base.hpo_dp_stream_enc[i] = NULL; - } - } - - for (i = 0; i < pool->base.hpo_dp_link_enc_count; i++) { - if (pool->base.hpo_dp_link_enc[i] != NULL) { - kfree(DCN3_1_HPO_DP_LINK_ENC_FROM_HPO_LINK_ENC(pool->base.hpo_dp_link_enc[i])); - pool->base.hpo_dp_link_enc[i] = NULL; - } - } - - for (i = 0; i < pool->base.res_cap->num_dsc; i++) { - if (pool->base.dscs[i] != NULL) - dcn20_dsc_destroy(&pool->base.dscs[i]); - } - - if (pool->base.mpc != NULL) { - kfree(TO_DCN20_MPC(pool->base.mpc)); - pool->base.mpc = NULL; - } - if (pool->base.hubbub != NULL) { - kfree(pool->base.hubbub); - pool->base.hubbub = NULL; - } - for (i = 0; i < pool->base.pipe_count; i++) { - if (pool->base.dpps[i] != NULL) - dcn31_dpp_destroy(&pool->base.dpps[i]); - - if (pool->base.ipps[i] != NULL) - pool->base.ipps[i]->funcs->ipp_destroy(&pool->base.ipps[i]); - - if (pool->base.hubps[i] != NULL) { - kfree(TO_DCN20_HUBP(pool->base.hubps[i])); - pool->base.hubps[i] = NULL; - } - - if (pool->base.irqs != NULL) { - dal_irq_service_destroy(&pool->base.irqs); - } - } - - for (i = 0; i < pool->base.res_cap->num_ddc; i++) { - if (pool->base.engines[i] != NULL) - dce110_engine_destroy(&pool->base.engines[i]); - if (pool->base.hw_i2cs[i] != NULL) { - kfree(pool->base.hw_i2cs[i]); - pool->base.hw_i2cs[i] = NULL; - } - if (pool->base.sw_i2cs[i] != NULL) { - kfree(pool->base.sw_i2cs[i]); - pool->base.sw_i2cs[i] = NULL; - } - } - - for (i = 0; i < pool->base.res_cap->num_opp; i++) { - if (pool->base.opps[i] != NULL) - pool->base.opps[i]->funcs->opp_destroy(&pool->base.opps[i]); - } - - for (i = 0; i < pool->base.res_cap->num_timing_generator; i++) { - if (pool->base.timing_generators[i] != NULL) { - kfree(DCN10TG_FROM_TG(pool->base.timing_generators[i])); - pool->base.timing_generators[i] = NULL; - } - } - - for (i = 0; i < pool->base.res_cap->num_dwb; i++) { - if (pool->base.dwbc[i] != NULL) { - kfree(TO_DCN30_DWBC(pool->base.dwbc[i])); - pool->base.dwbc[i] = NULL; - } - if (pool->base.mcif_wb[i] != NULL) { - kfree(TO_DCN30_MMHUBBUB(pool->base.mcif_wb[i])); - pool->base.mcif_wb[i] = NULL; - } - } - - for (i = 0; i < pool->base.audio_count; i++) { - if (pool->base.audios[i]) - dce_aud_destroy(&pool->base.audios[i]); - } - - for (i = 0; i < pool->base.clk_src_count; i++) { - if (pool->base.clock_sources[i] != NULL) { - dcn20_clock_source_destroy(&pool->base.clock_sources[i]); - pool->base.clock_sources[i] = NULL; - } - } - - for (i = 0; i < pool->base.res_cap->num_mpc_3dlut; i++) { - if (pool->base.mpc_lut[i] != NULL) { - dc_3dlut_func_release(pool->base.mpc_lut[i]); - pool->base.mpc_lut[i] = NULL; - } - if (pool->base.mpc_shaper[i] != NULL) { - dc_transfer_func_release(pool->base.mpc_shaper[i]); - pool->base.mpc_shaper[i] = NULL; - } - } - - if (pool->base.dp_clock_source != NULL) { - dcn20_clock_source_destroy(&pool->base.dp_clock_source); - pool->base.dp_clock_source = NULL; - } - - for (i = 0; i < pool->base.res_cap->num_timing_generator; i++) { - if (pool->base.multiple_abms[i] != NULL) - dce_abm_destroy(&pool->base.multiple_abms[i]); - } - - if (pool->base.psr != NULL) - dmub_psr_destroy(&pool->base.psr); - - if (pool->base.dccg != NULL) - dcn_dccg_destroy(&pool->base.dccg); -} - -static struct hubp *dcn31_hubp_create( - struct dc_context *ctx, - uint32_t inst) -{ - struct dcn20_hubp *hubp2 = - kzalloc(sizeof(struct dcn20_hubp), GFP_KERNEL); - - if (!hubp2) - return NULL; - - if (hubp31_construct(hubp2, ctx, inst, - &hubp_regs[inst], &hubp_shift, &hubp_mask)) - return &hubp2->base; - - BREAK_TO_DEBUGGER(); - kfree(hubp2); - return NULL; -} - -static bool dcn31_dwbc_create(struct dc_context *ctx, struct resource_pool *pool) -{ - int i; - uint32_t pipe_count = pool->res_cap->num_dwb; - - for (i = 0; i < pipe_count; i++) { - struct dcn30_dwbc *dwbc30 = kzalloc(sizeof(struct dcn30_dwbc), - GFP_KERNEL); - - if (!dwbc30) { - dm_error("DC: failed to create dwbc30!\n"); - return false; - } - - dcn30_dwbc_construct(dwbc30, ctx, - &dwbc30_regs[i], - &dwbc30_shift, - &dwbc30_mask, - i); - - pool->dwbc[i] = &dwbc30->base; - } - return true; -} - -static bool dcn31_mmhubbub_create(struct dc_context *ctx, struct resource_pool *pool) -{ - int i; - uint32_t pipe_count = pool->res_cap->num_dwb; - - for (i = 0; i < pipe_count; i++) { - struct dcn30_mmhubbub *mcif_wb30 = kzalloc(sizeof(struct dcn30_mmhubbub), - GFP_KERNEL); - - if (!mcif_wb30) { - dm_error("DC: failed to create mcif_wb30!\n"); - return false; - } - - dcn30_mmhubbub_construct(mcif_wb30, ctx, - &mcif_wb30_regs[i], - &mcif_wb30_shift, - &mcif_wb30_mask, - i); - - pool->mcif_wb[i] = &mcif_wb30->base; - } - return true; -} - -static struct display_stream_compressor *dcn31_dsc_create( - struct dc_context *ctx, uint32_t inst) -{ - struct dcn20_dsc *dsc = - kzalloc(sizeof(struct dcn20_dsc), GFP_KERNEL); - - if (!dsc) { - BREAK_TO_DEBUGGER(); - return NULL; - } - - dsc2_construct(dsc, ctx, inst, &dsc_regs[inst], &dsc_shift, &dsc_mask); - return &dsc->base; -} - -static void dcn315_destroy_resource_pool(struct resource_pool **pool) -{ - struct dcn315_resource_pool *dcn31_pool = TO_DCN315_RES_POOL(*pool); - - dcn315_resource_destruct(dcn31_pool); - kfree(dcn31_pool); - *pool = NULL; -} - -static struct clock_source *dcn31_clock_source_create( - struct dc_context *ctx, - struct dc_bios *bios, - enum clock_source_id id, - const struct dce110_clk_src_regs *regs, - bool dp_clk_src) -{ - struct dce110_clk_src *clk_src = - kzalloc(sizeof(struct dce110_clk_src), GFP_KERNEL); - - if (!clk_src) - return NULL; - - if (dcn31_clk_src_construct(clk_src, ctx, bios, id, - regs, &cs_shift, &cs_mask)) { - clk_src->base.dp_clk_src = dp_clk_src; - return &clk_src->base; - } - - kfree(clk_src); - BREAK_TO_DEBUGGER(); - return NULL; -} - -static bool is_dual_plane(enum surface_pixel_format format) -{ - return format >= SURFACE_PIXEL_FORMAT_VIDEO_BEGIN || format == SURFACE_PIXEL_FORMAT_GRPH_RGBE_ALPHA; -} - -static int source_format_to_bpp (enum source_format_class SourcePixelFormat) -{ - if (SourcePixelFormat == dm_444_64) - return 8; - else if (SourcePixelFormat == dm_444_16) - return 2; - else if (SourcePixelFormat == dm_444_8) - return 1; - else if (SourcePixelFormat == dm_rgbe_alpha) - return 5; - else if (SourcePixelFormat == dm_420_8) - return 3; - else if (SourcePixelFormat == dm_420_12) - return 6; - else - return 4; -} - -static bool allow_pixel_rate_crb(struct dc *dc, struct dc_state *context) -{ - int i; - struct resource_context *res_ctx = &context->res_ctx; - - /*Don't apply for single stream*/ - if (context->stream_count < 2) - return false; - - for (i = 0; i < dc->res_pool->pipe_count; i++) { - if (!res_ctx->pipe_ctx[i].stream) - continue; - - /*Don't apply if scaling*/ - if (res_ctx->pipe_ctx[i].stream->src.width != res_ctx->pipe_ctx[i].stream->dst.width || - res_ctx->pipe_ctx[i].stream->src.height != res_ctx->pipe_ctx[i].stream->dst.height || - (res_ctx->pipe_ctx[i].plane_state && (res_ctx->pipe_ctx[i].plane_state->src_rect.width - != res_ctx->pipe_ctx[i].plane_state->dst_rect.width || - res_ctx->pipe_ctx[i].plane_state->src_rect.height - != res_ctx->pipe_ctx[i].plane_state->dst_rect.height))) - return false; - /*Don't apply if MPO to avoid transition issues*/ - if (res_ctx->pipe_ctx[i].top_pipe && res_ctx->pipe_ctx[i].top_pipe->plane_state != res_ctx->pipe_ctx[i].plane_state) - return false; - } - return true; -} - -static int dcn315_populate_dml_pipes_from_context( - struct dc *dc, struct dc_state *context, - display_e2e_pipe_params_st *pipes, - bool fast_validate) -{ - int i, pipe_cnt, crb_idx, crb_pipes; - struct resource_context *res_ctx = &context->res_ctx; - struct pipe_ctx *pipe = NULL; - const int max_usable_det = context->bw_ctx.dml.ip.config_return_buffer_size_in_kbytes - DCN3_15_MIN_COMPBUF_SIZE_KB; - int remaining_det_segs = max_usable_det / DCN3_15_CRB_SEGMENT_SIZE_KB; - bool pixel_rate_crb = allow_pixel_rate_crb(dc, context); - - DC_FP_START(); - dcn31x_populate_dml_pipes_from_context(dc, context, pipes, fast_validate); - DC_FP_END(); - - for (i = 0, pipe_cnt = 0, crb_pipes = 0; i < dc->res_pool->pipe_count; i++) { - struct dc_crtc_timing *timing; - - if (!res_ctx->pipe_ctx[i].stream) - continue; - pipe = &res_ctx->pipe_ctx[i]; - timing = &pipe->stream->timing; - - /* - * Immediate flip can be set dynamically after enabling the plane. - * We need to require support for immediate flip or underflow can be - * intermittently experienced depending on peak b/w requirements. - */ - pipes[pipe_cnt].pipe.src.immediate_flip = true; - - pipes[pipe_cnt].pipe.src.unbounded_req_mode = false; - pipes[pipe_cnt].pipe.dest.vfront_porch = timing->v_front_porch; - pipes[pipe_cnt].pipe.src.dcc_rate = 3; - pipes[pipe_cnt].dout.dsc_input_bpc = 0; - DC_FP_START(); - dcn31_zero_pipe_dcc_fraction(pipes, pipe_cnt); - if (pixel_rate_crb && !pipe->top_pipe && !pipe->prev_odm_pipe) { - int bpp = source_format_to_bpp(pipes[pipe_cnt].pipe.src.source_format); - /* Ceil to crb segment size */ - int approx_det_segs_required_for_pstate = dcn_get_approx_det_segs_required_for_pstate( - &context->bw_ctx.dml.soc, timing->pix_clk_100hz, bpp, DCN3_15_CRB_SEGMENT_SIZE_KB); - - if (approx_det_segs_required_for_pstate <= 2 * DCN3_15_MAX_DET_SEGS) { - bool split_required = approx_det_segs_required_for_pstate > DCN3_15_MAX_DET_SEGS; - split_required = split_required || timing->pix_clk_100hz >= dcn_get_max_non_odm_pix_rate_100hz(&dc->dml.soc); - split_required = split_required || (pipe->plane_state && pipe->plane_state->src_rect.width > 5120); - - /* Minimum 2 segments to allow mpc/odm combine if its used later */ - if (approx_det_segs_required_for_pstate < 2) - approx_det_segs_required_for_pstate = 2; - if (split_required) - approx_det_segs_required_for_pstate += approx_det_segs_required_for_pstate % 2; - pipes[pipe_cnt].pipe.src.det_size_override = approx_det_segs_required_for_pstate; - remaining_det_segs -= approx_det_segs_required_for_pstate; - } else - remaining_det_segs = -1; - crb_pipes++; - } - DC_FP_END(); - - if (pipes[pipe_cnt].dout.dsc_enable) { - switch (timing->display_color_depth) { - case COLOR_DEPTH_888: - pipes[pipe_cnt].dout.dsc_input_bpc = 8; - break; - case COLOR_DEPTH_101010: - pipes[pipe_cnt].dout.dsc_input_bpc = 10; - break; - case COLOR_DEPTH_121212: - pipes[pipe_cnt].dout.dsc_input_bpc = 12; - break; - default: - ASSERT(0); - break; - } - } - pipe_cnt++; - } - - /* Spread remaining unreserved crb evenly among all pipes*/ - if (pixel_rate_crb) { - for (i = 0, pipe_cnt = 0, crb_idx = 0; i < dc->res_pool->pipe_count; i++) { - pipe = &res_ctx->pipe_ctx[i]; - if (!pipe->stream) - continue; - - /* Do not use asymetric crb if not enough for pstate support */ - if (remaining_det_segs < 0) { - pipes[pipe_cnt].pipe.src.det_size_override = 0; - pipe_cnt++; - continue; - } - - if (!pipe->top_pipe && !pipe->prev_odm_pipe) { - bool split_required = pipe->stream->timing.pix_clk_100hz >= dcn_get_max_non_odm_pix_rate_100hz(&dc->dml.soc) - || (pipe->plane_state && pipe->plane_state->src_rect.width > 5120); - - if (remaining_det_segs > MIN_RESERVED_DET_SEGS) - pipes[pipe_cnt].pipe.src.det_size_override += (remaining_det_segs - MIN_RESERVED_DET_SEGS) / crb_pipes + - (crb_idx < (remaining_det_segs - MIN_RESERVED_DET_SEGS) % crb_pipes ? 1 : 0); - if (pipes[pipe_cnt].pipe.src.det_size_override > 2 * DCN3_15_MAX_DET_SEGS) { - /* Clamp to 2 pipe split max det segments */ - remaining_det_segs += pipes[pipe_cnt].pipe.src.det_size_override - 2 * (DCN3_15_MAX_DET_SEGS); - pipes[pipe_cnt].pipe.src.det_size_override = 2 * DCN3_15_MAX_DET_SEGS; - } - if (pipes[pipe_cnt].pipe.src.det_size_override > DCN3_15_MAX_DET_SEGS || split_required) { - /* If we are splitting we must have an even number of segments */ - remaining_det_segs += pipes[pipe_cnt].pipe.src.det_size_override % 2; - pipes[pipe_cnt].pipe.src.det_size_override -= pipes[pipe_cnt].pipe.src.det_size_override % 2; - } - /* Convert segments into size for DML use */ - pipes[pipe_cnt].pipe.src.det_size_override *= DCN3_15_CRB_SEGMENT_SIZE_KB; - - crb_idx++; - } - pipe_cnt++; - } - } - - if (pipe_cnt) - context->bw_ctx.dml.ip.det_buffer_size_kbytes = - (max_usable_det / DCN3_15_CRB_SEGMENT_SIZE_KB / pipe_cnt) * DCN3_15_CRB_SEGMENT_SIZE_KB; - if (context->bw_ctx.dml.ip.det_buffer_size_kbytes > DCN3_15_MAX_DET_SIZE) - context->bw_ctx.dml.ip.det_buffer_size_kbytes = DCN3_15_MAX_DET_SIZE; - - dc->config.enable_4to1MPC = false; - if (pipe_cnt == 1 && pipe->plane_state && !dc->debug.disable_z9_mpc) { - if (is_dual_plane(pipe->plane_state->format) - && pipe->plane_state->src_rect.width <= 1920 && pipe->plane_state->src_rect.height <= 1080) { - dc->config.enable_4to1MPC = true; - context->bw_ctx.dml.ip.det_buffer_size_kbytes = - (max_usable_det / DCN3_15_CRB_SEGMENT_SIZE_KB / 4) * DCN3_15_CRB_SEGMENT_SIZE_KB; - } else if (!is_dual_plane(pipe->plane_state->format) - && pipe->plane_state->src_rect.width <= 5120 - && pipe->stream->timing.pix_clk_100hz < dcn_get_max_non_odm_pix_rate_100hz(&dc->dml.soc)) { - /* Limit to 5k max to avoid forced pipe split when there is not enough detile for swath */ - context->bw_ctx.dml.ip.det_buffer_size_kbytes = 192; - pipes[0].pipe.src.unbounded_req_mode = true; - } - } - - return pipe_cnt; -} - -static void dcn315_get_panel_config_defaults(struct dc_panel_config *panel_config) -{ - *panel_config = panel_config_defaults; -} - -static struct dc_cap_funcs cap_funcs = { - .get_dcc_compression_cap = dcn20_get_dcc_compression_cap -}; - -static struct resource_funcs dcn315_res_pool_funcs = { - .destroy = dcn315_destroy_resource_pool, - .link_enc_create = dcn31_link_encoder_create, - .link_enc_create_minimal = dcn31_link_enc_create_minimal, - .link_encs_assign = link_enc_cfg_link_encs_assign, - .link_enc_unassign = link_enc_cfg_link_enc_unassign, - .panel_cntl_create = dcn31_panel_cntl_create, - .validate_bandwidth = dcn31_validate_bandwidth, - .calculate_wm_and_dlg = dcn31_calculate_wm_and_dlg, - .update_soc_for_wm_a = dcn315_update_soc_for_wm_a, - .populate_dml_pipes = dcn315_populate_dml_pipes_from_context, - .acquire_free_pipe_as_secondary_dpp_pipe = dcn20_acquire_free_pipe_for_layer, - .release_pipe = dcn20_release_pipe, - .add_stream_to_ctx = dcn30_add_stream_to_ctx, - .add_dsc_to_stream_resource = dcn20_add_dsc_to_stream_resource, - .remove_stream_from_ctx = dcn20_remove_stream_from_ctx, - .populate_dml_writeback_from_context = dcn31_populate_dml_writeback_from_context, - .set_mcif_arb_params = dcn31_set_mcif_arb_params, - .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 = dcn315_update_bw_bounding_box, - .patch_unknown_plane_state = dcn20_patch_unknown_plane_state, - .get_panel_config_defaults = dcn315_get_panel_config_defaults, -}; - -static bool dcn315_resource_construct( - uint8_t num_virtual_links, - struct dc *dc, - struct dcn315_resource_pool *pool) -{ - int i; - struct dc_context *ctx = dc->ctx; - struct irq_service_init_data init_data; - - ctx->dc_bios->regs = &bios_regs; - - pool->base.res_cap = &res_cap_dcn31; - - pool->base.funcs = &dcn315_res_pool_funcs; - - /************************************************* - * Resource + asic cap harcoding * - *************************************************/ - pool->base.underlay_pipe_index = NO_UNDERLAY_PIPE; - pool->base.pipe_count = pool->base.res_cap->num_timing_generator; - pool->base.mpcc_count = pool->base.res_cap->num_timing_generator; - dc->caps.max_downscale_ratio = 600; - dc->caps.i2c_speed_in_khz = 100; - dc->caps.i2c_speed_in_khz_hdcp = 100; - dc->caps.max_cursor_size = 256; - dc->caps.min_horizontal_blanking_period = 80; - dc->caps.dmdata_alloc_size = 2048; - dc->caps.max_slave_planes = 2; - dc->caps.max_slave_yuv_planes = 2; - dc->caps.max_slave_rgb_planes = 2; - dc->caps.post_blend_color_processing = true; - dc->caps.force_dp_tps4_for_cp2520 = true; - if (dc->config.forceHBR2CP2520) - dc->caps.force_dp_tps4_for_cp2520 = false; - dc->caps.dp_hpo = true; - dc->caps.dp_hdmi21_pcon_support = true; - dc->caps.edp_dsc_support = true; - dc->caps.extended_aux_timeout_support = true; - dc->caps.dmcub_support = true; - dc->caps.is_apu = true; - - /* Color pipeline capabilities */ - dc->caps.color.dpp.dcn_arch = 1; - dc->caps.color.dpp.input_lut_shared = 0; - dc->caps.color.dpp.icsc = 1; - dc->caps.color.dpp.dgam_ram = 0; // must use gamma_corr - dc->caps.color.dpp.dgam_rom_caps.srgb = 1; - dc->caps.color.dpp.dgam_rom_caps.bt2020 = 1; - dc->caps.color.dpp.dgam_rom_caps.gamma2_2 = 1; - dc->caps.color.dpp.dgam_rom_caps.pq = 1; - dc->caps.color.dpp.dgam_rom_caps.hlg = 1; - dc->caps.color.dpp.post_csc = 1; - dc->caps.color.dpp.gamma_corr = 1; - dc->caps.color.dpp.dgam_rom_for_yuv = 0; - - dc->caps.color.dpp.hw_3d_lut = 1; - dc->caps.color.dpp.ogam_ram = 1; - // no OGAM ROM on DCN301 - dc->caps.color.dpp.ogam_rom_caps.srgb = 0; - dc->caps.color.dpp.ogam_rom_caps.bt2020 = 0; - dc->caps.color.dpp.ogam_rom_caps.gamma2_2 = 0; - dc->caps.color.dpp.ogam_rom_caps.pq = 0; - dc->caps.color.dpp.ogam_rom_caps.hlg = 0; - dc->caps.color.dpp.ocsc = 0; - - dc->caps.color.mpc.gamut_remap = 1; - dc->caps.color.mpc.num_3dluts = pool->base.res_cap->num_mpc_3dlut; //2 - dc->caps.color.mpc.ogam_ram = 1; - dc->caps.color.mpc.ogam_rom_caps.srgb = 0; - dc->caps.color.mpc.ogam_rom_caps.bt2020 = 0; - dc->caps.color.mpc.ogam_rom_caps.gamma2_2 = 0; - dc->caps.color.mpc.ogam_rom_caps.pq = 0; - dc->caps.color.mpc.ogam_rom_caps.hlg = 0; - dc->caps.color.mpc.ocsc = 1; - - /* read VBIOS LTTPR caps */ - { - if (ctx->dc_bios->funcs->get_lttpr_caps) { - enum bp_result bp_query_result; - uint8_t is_vbios_lttpr_enable = 0; - - bp_query_result = ctx->dc_bios->funcs->get_lttpr_caps(ctx->dc_bios, &is_vbios_lttpr_enable); - dc->caps.vbios_lttpr_enable = (bp_query_result == BP_RESULT_OK) && !!is_vbios_lttpr_enable; - } - - /* interop bit is implicit */ - { - dc->caps.vbios_lttpr_aware = true; - } - } - - if (dc->ctx->dce_environment == DCE_ENV_PRODUCTION_DRV) - dc->debug = debug_defaults_drv; - - // Init the vm_helper - if (dc->vm_helper) - vm_helper_init(dc->vm_helper, 16); - - /************************************************* - * Create resources * - *************************************************/ - - /* Clock Sources for Pixel Clock*/ - pool->base.clock_sources[DCN31_CLK_SRC_PLL0] = - dcn31_clock_source_create(ctx, ctx->dc_bios, - CLOCK_SOURCE_COMBO_PHY_PLL0, - &clk_src_regs[0], false); - pool->base.clock_sources[DCN31_CLK_SRC_PLL1] = - dcn31_clock_source_create(ctx, ctx->dc_bios, - CLOCK_SOURCE_COMBO_PHY_PLL1, - &clk_src_regs[1], false); - pool->base.clock_sources[DCN31_CLK_SRC_PLL2] = - dcn31_clock_source_create(ctx, ctx->dc_bios, - CLOCK_SOURCE_COMBO_PHY_PLL2, - &clk_src_regs[2], false); - pool->base.clock_sources[DCN31_CLK_SRC_PLL3] = - dcn31_clock_source_create(ctx, ctx->dc_bios, - CLOCK_SOURCE_COMBO_PHY_PLL3, - &clk_src_regs[3], false); - pool->base.clock_sources[DCN31_CLK_SRC_PLL4] = - dcn31_clock_source_create(ctx, ctx->dc_bios, - CLOCK_SOURCE_COMBO_PHY_PLL4, - &clk_src_regs[4], false); - - pool->base.clk_src_count = DCN30_CLK_SRC_TOTAL; - - /* todo: not reuse phy_pll registers */ - pool->base.dp_clock_source = - dcn31_clock_source_create(ctx, ctx->dc_bios, - CLOCK_SOURCE_ID_DP_DTO, - &clk_src_regs[0], true); - - for (i = 0; i < pool->base.clk_src_count; i++) { - if (pool->base.clock_sources[i] == NULL) { - dm_error("DC: failed to create clock sources!\n"); - BREAK_TO_DEBUGGER(); - goto create_fail; - } - } - - /* TODO: DCCG */ - pool->base.dccg = dccg31_create(ctx, &dccg_regs, &dccg_shift, &dccg_mask); - if (pool->base.dccg == NULL) { - dm_error("DC: failed to create dccg!\n"); - BREAK_TO_DEBUGGER(); - goto create_fail; - } - - /* TODO: IRQ */ - init_data.ctx = dc->ctx; - pool->base.irqs = dal_irq_service_dcn315_create(&init_data); - if (!pool->base.irqs) - goto create_fail; - - /* HUBBUB */ - pool->base.hubbub = dcn31_hubbub_create(ctx); - if (pool->base.hubbub == NULL) { - BREAK_TO_DEBUGGER(); - dm_error("DC: failed to create hubbub!\n"); - goto create_fail; - } - - /* HUBPs, DPPs, OPPs and TGs */ - for (i = 0; i < pool->base.pipe_count; i++) { - pool->base.hubps[i] = dcn31_hubp_create(ctx, i); - if (pool->base.hubps[i] == NULL) { - BREAK_TO_DEBUGGER(); - dm_error( - "DC: failed to create hubps!\n"); - goto create_fail; - } - - pool->base.dpps[i] = dcn31_dpp_create(ctx, i); - if (pool->base.dpps[i] == NULL) { - BREAK_TO_DEBUGGER(); - dm_error( - "DC: failed to create dpps!\n"); - goto create_fail; - } - } - - for (i = 0; i < pool->base.res_cap->num_opp; i++) { - pool->base.opps[i] = dcn31_opp_create(ctx, i); - if (pool->base.opps[i] == NULL) { - BREAK_TO_DEBUGGER(); - dm_error( - "DC: failed to create output pixel processor!\n"); - goto create_fail; - } - } - - for (i = 0; i < pool->base.res_cap->num_timing_generator; i++) { - pool->base.timing_generators[i] = dcn31_timing_generator_create( - ctx, i); - if (pool->base.timing_generators[i] == NULL) { - BREAK_TO_DEBUGGER(); - dm_error("DC: failed to create tg!\n"); - goto create_fail; - } - } - pool->base.timing_generator_count = i; - - /* PSR */ - pool->base.psr = dmub_psr_create(ctx); - if (pool->base.psr == NULL) { - dm_error("DC: failed to create psr obj!\n"); - BREAK_TO_DEBUGGER(); - goto create_fail; - } - - /* ABM */ - for (i = 0; i < pool->base.res_cap->num_timing_generator; i++) { - pool->base.multiple_abms[i] = dmub_abm_create(ctx, - &abm_regs[i], - &abm_shift, - &abm_mask); - if (pool->base.multiple_abms[i] == NULL) { - dm_error("DC: failed to create abm for pipe %d!\n", i); - BREAK_TO_DEBUGGER(); - goto create_fail; - } - } - - /* MPC and DSC */ - pool->base.mpc = dcn31_mpc_create(ctx, pool->base.mpcc_count, pool->base.res_cap->num_mpc_3dlut); - if (pool->base.mpc == NULL) { - BREAK_TO_DEBUGGER(); - dm_error("DC: failed to create mpc!\n"); - goto create_fail; - } - - for (i = 0; i < pool->base.res_cap->num_dsc; i++) { - pool->base.dscs[i] = dcn31_dsc_create(ctx, i); - if (pool->base.dscs[i] == NULL) { - BREAK_TO_DEBUGGER(); - dm_error("DC: failed to create display stream compressor %d!\n", i); - goto create_fail; - } - } - - /* DWB and MMHUBBUB */ - if (!dcn31_dwbc_create(ctx, &pool->base)) { - BREAK_TO_DEBUGGER(); - dm_error("DC: failed to create dwbc!\n"); - goto create_fail; - } - - if (!dcn31_mmhubbub_create(ctx, &pool->base)) { - BREAK_TO_DEBUGGER(); - dm_error("DC: failed to create mcif_wb!\n"); - goto create_fail; - } - - /* AUX and I2C */ - for (i = 0; i < pool->base.res_cap->num_ddc; i++) { - pool->base.engines[i] = dcn31_aux_engine_create(ctx, i); - if (pool->base.engines[i] == NULL) { - BREAK_TO_DEBUGGER(); - dm_error( - "DC:failed to create aux engine!!\n"); - goto create_fail; - } - pool->base.hw_i2cs[i] = dcn31_i2c_hw_create(ctx, i); - if (pool->base.hw_i2cs[i] == NULL) { - BREAK_TO_DEBUGGER(); - dm_error( - "DC:failed to create hw i2c!!\n"); - goto create_fail; - } - pool->base.sw_i2cs[i] = NULL; - } - - /* Audio, Stream Encoders including HPO and virtual, MPC 3D LUTs */ - if (!resource_construct(num_virtual_links, dc, &pool->base, - &res_create_funcs)) - goto create_fail; - - /* HW Sequencer and Plane caps */ - dcn31_hw_sequencer_construct(dc); - - dc->caps.max_planes = pool->base.pipe_count; - - for (i = 0; i < dc->caps.max_planes; ++i) - dc->caps.planes[i] = plane_cap; - - dc->cap_funcs = cap_funcs; - - dc->dcn_ip->max_num_dpp = dcn3_15_ip.max_num_dpp; - - return true; - -create_fail: - - dcn315_resource_destruct(pool); - - return false; -} - -struct resource_pool *dcn315_create_resource_pool( - const struct dc_init_data *init_data, - struct dc *dc) -{ - struct dcn315_resource_pool *pool = - kzalloc(sizeof(struct dcn315_resource_pool), GFP_KERNEL); - - if (!pool) - return NULL; - - if (dcn315_resource_construct(init_data->num_virtual_links, dc, pool)) - return &pool->base; - - BREAK_TO_DEBUGGER(); - kfree(pool); - return NULL; -} diff --git a/drivers/gpu/drm/amd/display/dc/dcn315/dcn315_resource.h b/drivers/gpu/drm/amd/display/dc/dcn315/dcn315_resource.h deleted file mode 100644 index 22849eaa6f24..000000000000 --- a/drivers/gpu/drm/amd/display/dc/dcn315/dcn315_resource.h +++ /dev/null @@ -1,44 +0,0 @@ -/* - * 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 _DCN315_RESOURCE_H_ -#define _DCN315_RESOURCE_H_ - -#include "core_types.h" - -#define TO_DCN315_RES_POOL(pool)\ - container_of(pool, struct dcn315_resource_pool, base) - -extern struct _vcs_dpi_ip_params_st dcn3_15_ip; - -struct dcn315_resource_pool { - struct resource_pool base; -}; - -struct resource_pool *dcn315_create_resource_pool( - const struct dc_init_data *init_data, - struct dc *dc); - -#endif /* _DCN315_RESOURCE_H_ */ diff --git a/drivers/gpu/drm/amd/display/dc/dcn316/Makefile b/drivers/gpu/drm/amd/display/dc/dcn316/Makefile deleted file mode 100644 index 819d44a9439b..000000000000 --- a/drivers/gpu/drm/amd/display/dc/dcn316/Makefile +++ /dev/null @@ -1,30 +0,0 @@ -# -# 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 -# -# Makefile for dcn316. - -DCN316 = dcn316_resource.o - -AMD_DAL_DCN316 = $(addprefix $(AMDDALPATH)/dc/dcn316/,$(DCN316)) - -AMD_DISPLAY_FILES += $(AMD_DAL_DCN316) diff --git a/drivers/gpu/drm/amd/display/dc/dcn316/dcn316_resource.c b/drivers/gpu/drm/amd/display/dc/dcn316/dcn316_resource.c deleted file mode 100644 index b9753d4606f8..000000000000 --- a/drivers/gpu/drm/amd/display/dc/dcn316/dcn316_resource.c +++ /dev/null @@ -1,2038 +0,0 @@ -/* - * 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 "dm_services.h" -#include "dc.h" - -#include "dcn31/dcn31_init.h" - -#include "resource.h" -#include "include/irq_service_interface.h" -#include "dcn316_resource.h" - -#include "dcn20/dcn20_resource.h" -#include "dcn30/dcn30_resource.h" -#include "dcn31/dcn31_resource.h" - -#include "dcn10/dcn10_ipp.h" -#include "dcn30/dcn30_hubbub.h" -#include "dcn31/dcn31_hubbub.h" -#include "dcn30/dcn30_mpc.h" -#include "dcn31/dcn31_hubp.h" -#include "irq/dcn31/irq_service_dcn31.h" -#include "dcn30/dcn30_dpp.h" -#include "dcn31/dcn31_optc.h" -#include "dcn20/dcn20_hwseq.h" -#include "dcn30/dcn30_hwseq.h" -#include "dce110/dce110_hwseq.h" -#include "dcn30/dcn30_opp.h" -#include "dcn20/dcn20_dsc.h" -#include "dcn30/dcn30_vpg.h" -#include "dcn30/dcn30_afmt.h" -#include "dcn30/dcn30_dio_stream_encoder.h" -#include "dcn31/dcn31_hpo_dp_stream_encoder.h" -#include "dcn31/dcn31_hpo_dp_link_encoder.h" -#include "dcn31/dcn31_apg.h" -#include "dcn31/dcn31_dio_link_encoder.h" -#include "dcn31/dcn31_vpg.h" -#include "dcn31/dcn31_afmt.h" -#include "dce/dce_clock_source.h" -#include "dce/dce_audio.h" -#include "dce/dce_hwseq.h" -#include "clk_mgr.h" -#include "virtual/virtual_stream_encoder.h" -#include "dce110/dce110_resource.h" -#include "dml/display_mode_vba.h" -#include "dml/dcn31/dcn31_fpu.h" -#include "dcn31/dcn31_dccg.h" -#include "dcn10/dcn10_resource.h" -#include "dcn31/dcn31_panel_cntl.h" - -#include "dcn30/dcn30_dwb.h" -#include "dcn30/dcn30_mmhubbub.h" - -#include "dcn/dcn_3_1_6_offset.h" -#include "dcn/dcn_3_1_6_sh_mask.h" -#include "dpcs/dpcs_4_2_3_offset.h" -#include "dpcs/dpcs_4_2_3_sh_mask.h" - -#define regBIF_BX1_BIOS_SCRATCH_2 0x003a -#define regBIF_BX1_BIOS_SCRATCH_2_BASE_IDX 1 -#define regBIF_BX1_BIOS_SCRATCH_3 0x003b -#define regBIF_BX1_BIOS_SCRATCH_3_BASE_IDX 1 -#define regBIF_BX1_BIOS_SCRATCH_6 0x003e -#define regBIF_BX1_BIOS_SCRATCH_6_BASE_IDX 1 - -#define regDCHUBBUB_DEBUG_CTRL_0 0x04d6 -#define regDCHUBBUB_DEBUG_CTRL_0_BASE_IDX 2 -#define DCHUBBUB_DEBUG_CTRL_0__DET_DEPTH__SHIFT 0x10 -#define DCHUBBUB_DEBUG_CTRL_0__DET_DEPTH_MASK 0x01FF0000L - -#define DCN_BASE__INST0_SEG0 0x00000012 -#define DCN_BASE__INST0_SEG1 0x000000C0 -#define DCN_BASE__INST0_SEG2 0x000034C0 -#define DCN_BASE__INST0_SEG3 0x00009000 -#define DCN_BASE__INST0_SEG4 0x02403C00 -#define DCN_BASE__INST0_SEG5 0 - -#define DPCS_BASE__INST0_SEG0 0x00000012 -#define DPCS_BASE__INST0_SEG1 0x000000C0 -#define DPCS_BASE__INST0_SEG2 0x000034C0 -#define DPCS_BASE__INST0_SEG3 0x00009000 -#define DPCS_BASE__INST0_SEG4 0x02403C00 -#define DPCS_BASE__INST0_SEG5 0 - -#define NBIO_BASE__INST0_SEG0 0x00000000 -#define NBIO_BASE__INST0_SEG1 0x00000014 -#define NBIO_BASE__INST0_SEG2 0x00000D20 -#define NBIO_BASE__INST0_SEG3 0x00010400 -#define NBIO_BASE__INST0_SEG4 0x0241B000 -#define NBIO_BASE__INST0_SEG5 0x04040000 - -#include "reg_helper.h" -#include "dce/dmub_abm.h" -#include "dce/dmub_psr.h" -#include "dce/dce_aux.h" -#include "dce/dce_i2c.h" - -#include "dml/dcn30/display_mode_vba_30.h" -#include "vm_helper.h" -#include "dcn20/dcn20_vmid.h" - -#include "link_enc_cfg.h" - -#define DCN3_16_MAX_DET_SIZE 384 -#define DCN3_16_MIN_COMPBUF_SIZE_KB 128 -#define DCN3_16_CRB_SEGMENT_SIZE_KB 64 - -enum dcn31_clk_src_array_id { - DCN31_CLK_SRC_PLL0, - DCN31_CLK_SRC_PLL1, - DCN31_CLK_SRC_PLL2, - DCN31_CLK_SRC_PLL3, - DCN31_CLK_SRC_PLL4, - DCN30_CLK_SRC_TOTAL -}; - -/* begin ********************* - * macros to expend register list macro defined in HW object header file - */ - -/* DCN */ -#define BASE_INNER(seg) DCN_BASE__INST0_SEG ## seg - -#define BASE(seg) BASE_INNER(seg) - -#define SR(reg_name)\ - .reg_name = BASE(reg ## reg_name ## _BASE_IDX) + \ - reg ## reg_name - -#define SRI(reg_name, block, id)\ - .reg_name = BASE(reg ## block ## id ## _ ## reg_name ## _BASE_IDX) + \ - reg ## block ## id ## _ ## reg_name - -#define SRI2(reg_name, block, id)\ - .reg_name = BASE(reg ## reg_name ## _BASE_IDX) + \ - reg ## reg_name - -#define SRIR(var_name, reg_name, block, id)\ - .var_name = BASE(reg ## block ## id ## _ ## reg_name ## _BASE_IDX) + \ - reg ## block ## id ## _ ## reg_name - -#define SRII(reg_name, block, id)\ - .reg_name[id] = BASE(reg ## block ## id ## _ ## reg_name ## _BASE_IDX) + \ - reg ## block ## id ## _ ## reg_name - -#define SRII_MPC_RMU(reg_name, block, id)\ - .RMU##_##reg_name[id] = BASE(reg ## block ## id ## _ ## reg_name ## _BASE_IDX) + \ - reg ## block ## id ## _ ## reg_name - -#define SRII_DWB(reg_name, temp_name, block, id)\ - .reg_name[id] = BASE(reg ## block ## id ## _ ## temp_name ## _BASE_IDX) + \ - reg ## block ## id ## _ ## temp_name - -#define SF_DWB2(reg_name, block, id, field_name, post_fix) \ - .field_name = reg_name ## __ ## field_name ## post_fix - -#define DCCG_SRII(reg_name, block, id)\ - .block ## _ ## reg_name[id] = BASE(reg ## block ## id ## _ ## reg_name ## _BASE_IDX) + \ - reg ## block ## id ## _ ## reg_name - -#define VUPDATE_SRII(reg_name, block, id)\ - .reg_name[id] = BASE(reg ## reg_name ## _ ## block ## id ## _BASE_IDX) + \ - reg ## reg_name ## _ ## block ## id - -/* NBIO */ -#define NBIO_BASE_INNER(seg) \ - NBIO_BASE__INST0_SEG ## seg - -#define NBIO_BASE(seg) \ - NBIO_BASE_INNER(seg) - -#define NBIO_SR(reg_name)\ - .reg_name = NBIO_BASE(regBIF_BX1_ ## reg_name ## _BASE_IDX) + \ - regBIF_BX1_ ## reg_name - -static const struct bios_registers bios_regs = { - NBIO_SR(BIOS_SCRATCH_3), - NBIO_SR(BIOS_SCRATCH_6) -}; - -#define clk_src_regs(index, pllid)\ -[index] = {\ - CS_COMMON_REG_LIST_DCN3_0(index, pllid),\ -} - -static const struct dce110_clk_src_regs clk_src_regs[] = { - clk_src_regs(0, A), - clk_src_regs(1, B), - clk_src_regs(2, C), - clk_src_regs(3, D), - clk_src_regs(4, E) -}; - -static const struct dce110_clk_src_shift cs_shift = { - CS_COMMON_MASK_SH_LIST_DCN2_0(__SHIFT) -}; - -static const struct dce110_clk_src_mask cs_mask = { - CS_COMMON_MASK_SH_LIST_DCN2_0(_MASK) -}; - -#define abm_regs(id)\ -[id] = {\ - ABM_DCN302_REG_LIST(id)\ -} - -static const struct dce_abm_registers abm_regs[] = { - abm_regs(0), - abm_regs(1), - abm_regs(2), - abm_regs(3), -}; - -static const struct dce_abm_shift abm_shift = { - ABM_MASK_SH_LIST_DCN30(__SHIFT) -}; - -static const struct dce_abm_mask abm_mask = { - ABM_MASK_SH_LIST_DCN30(_MASK) -}; - -#define audio_regs(id)\ -[id] = {\ - AUD_COMMON_REG_LIST(id)\ -} - -static const struct dce_audio_registers audio_regs[] = { - audio_regs(0), - audio_regs(1), - audio_regs(2), - audio_regs(3), - audio_regs(4), - audio_regs(5), - audio_regs(6) -}; - -#define DCE120_AUD_COMMON_MASK_SH_LIST(mask_sh)\ - SF(AZF0ENDPOINT0_AZALIA_F0_CODEC_ENDPOINT_INDEX, AZALIA_ENDPOINT_REG_INDEX, mask_sh),\ - SF(AZF0ENDPOINT0_AZALIA_F0_CODEC_ENDPOINT_DATA, AZALIA_ENDPOINT_REG_DATA, mask_sh),\ - AUD_COMMON_MASK_SH_LIST_BASE(mask_sh) - -static const struct dce_audio_shift audio_shift = { - DCE120_AUD_COMMON_MASK_SH_LIST(__SHIFT) -}; - -static const struct dce_audio_mask audio_mask = { - DCE120_AUD_COMMON_MASK_SH_LIST(_MASK) -}; - -#define vpg_regs(id)\ -[id] = {\ - VPG_DCN31_REG_LIST(id)\ -} - -static const struct dcn31_vpg_registers vpg_regs[] = { - vpg_regs(0), - vpg_regs(1), - vpg_regs(2), - vpg_regs(3), - vpg_regs(4), - vpg_regs(5), - vpg_regs(6), - vpg_regs(7), - vpg_regs(8), - vpg_regs(9), -}; - -static const struct dcn31_vpg_shift vpg_shift = { - DCN31_VPG_MASK_SH_LIST(__SHIFT) -}; - -static const struct dcn31_vpg_mask vpg_mask = { - DCN31_VPG_MASK_SH_LIST(_MASK) -}; - -#define afmt_regs(id)\ -[id] = {\ - AFMT_DCN31_REG_LIST(id)\ -} - -static const struct dcn31_afmt_registers afmt_regs[] = { - afmt_regs(0), - afmt_regs(1), - afmt_regs(2), - afmt_regs(3), - afmt_regs(4), - afmt_regs(5) -}; - -static const struct dcn31_afmt_shift afmt_shift = { - DCN31_AFMT_MASK_SH_LIST(__SHIFT) -}; - -static const struct dcn31_afmt_mask afmt_mask = { - DCN31_AFMT_MASK_SH_LIST(_MASK) -}; - - -#define apg_regs(id)\ -[id] = {\ - APG_DCN31_REG_LIST(id)\ -} - -static const struct dcn31_apg_registers apg_regs[] = { - apg_regs(0), - apg_regs(1), - apg_regs(2), - apg_regs(3) -}; - -static const struct dcn31_apg_shift apg_shift = { - DCN31_APG_MASK_SH_LIST(__SHIFT) -}; - -static const struct dcn31_apg_mask apg_mask = { - DCN31_APG_MASK_SH_LIST(_MASK) -}; - - -#define stream_enc_regs(id)\ -[id] = {\ - SE_DCN3_REG_LIST(id)\ -} - -static const struct dcn10_stream_enc_registers stream_enc_regs[] = { - stream_enc_regs(0), - stream_enc_regs(1), - stream_enc_regs(2), - stream_enc_regs(3), - stream_enc_regs(4) -}; - -static const struct dcn10_stream_encoder_shift se_shift = { - SE_COMMON_MASK_SH_LIST_DCN30(__SHIFT) -}; - -static const struct dcn10_stream_encoder_mask se_mask = { - SE_COMMON_MASK_SH_LIST_DCN30(_MASK) -}; - - -#define aux_regs(id)\ -[id] = {\ - DCN2_AUX_REG_LIST(id)\ -} - -static const struct dcn10_link_enc_aux_registers link_enc_aux_regs[] = { - aux_regs(0), - aux_regs(1), - aux_regs(2), - aux_regs(3), - aux_regs(4) -}; - -#define hpd_regs(id)\ -[id] = {\ - HPD_REG_LIST(id)\ -} - -static const struct dcn10_link_enc_hpd_registers link_enc_hpd_regs[] = { - hpd_regs(0), - hpd_regs(1), - hpd_regs(2), - hpd_regs(3), - hpd_regs(4) -}; - -#define link_regs(id, phyid)\ -[id] = {\ - LE_DCN31_REG_LIST(id), \ - UNIPHY_DCN2_REG_LIST(phyid), \ - DPCS_DCN31_REG_LIST(id), \ -} - -static const struct dce110_aux_registers_shift aux_shift = { - DCN_AUX_MASK_SH_LIST(__SHIFT) -}; - -static const struct dce110_aux_registers_mask aux_mask = { - DCN_AUX_MASK_SH_LIST(_MASK) -}; - -static const struct dcn10_link_enc_registers link_enc_regs[] = { - link_regs(0, A), - link_regs(1, B), - link_regs(2, C), - link_regs(3, D), - link_regs(4, E) -}; - -static const struct dcn10_link_enc_shift le_shift = { - LINK_ENCODER_MASK_SH_LIST_DCN31(__SHIFT), \ - DPCS_DCN31_MASK_SH_LIST(__SHIFT) -}; - -static const struct dcn10_link_enc_mask le_mask = { - LINK_ENCODER_MASK_SH_LIST_DCN31(_MASK), \ - DPCS_DCN31_MASK_SH_LIST(_MASK) -}; - - - -#define hpo_dp_stream_encoder_reg_list(id)\ -[id] = {\ - DCN3_1_HPO_DP_STREAM_ENC_REG_LIST(id)\ -} - -static const struct dcn31_hpo_dp_stream_encoder_registers hpo_dp_stream_enc_regs[] = { - hpo_dp_stream_encoder_reg_list(0), - hpo_dp_stream_encoder_reg_list(1), - hpo_dp_stream_encoder_reg_list(2), - hpo_dp_stream_encoder_reg_list(3), -}; - -static const struct dcn31_hpo_dp_stream_encoder_shift hpo_dp_se_shift = { - DCN3_1_HPO_DP_STREAM_ENC_MASK_SH_LIST(__SHIFT) -}; - -static const struct dcn31_hpo_dp_stream_encoder_mask hpo_dp_se_mask = { - DCN3_1_HPO_DP_STREAM_ENC_MASK_SH_LIST(_MASK) -}; - - -#define hpo_dp_link_encoder_reg_list(id)\ -[id] = {\ - DCN3_1_HPO_DP_LINK_ENC_REG_LIST(id),\ - DCN3_1_RDPCSTX_REG_LIST(0),\ - DCN3_1_RDPCSTX_REG_LIST(1),\ - DCN3_1_RDPCSTX_REG_LIST(2),\ - DCN3_1_RDPCSTX_REG_LIST(3),\ - DCN3_1_RDPCSTX_REG_LIST(4)\ -} - -static const struct dcn31_hpo_dp_link_encoder_registers hpo_dp_link_enc_regs[] = { - hpo_dp_link_encoder_reg_list(0), - hpo_dp_link_encoder_reg_list(1), -}; - -static const struct dcn31_hpo_dp_link_encoder_shift hpo_dp_le_shift = { - DCN3_1_HPO_DP_LINK_ENC_MASK_SH_LIST(__SHIFT) -}; - -static const struct dcn31_hpo_dp_link_encoder_mask hpo_dp_le_mask = { - DCN3_1_HPO_DP_LINK_ENC_MASK_SH_LIST(_MASK) -}; - - -#define dpp_regs(id)\ -[id] = {\ - DPP_REG_LIST_DCN30(id),\ -} - -static const struct dcn3_dpp_registers dpp_regs[] = { - dpp_regs(0), - dpp_regs(1), - dpp_regs(2), - dpp_regs(3) -}; - -static const struct dcn3_dpp_shift tf_shift = { - DPP_REG_LIST_SH_MASK_DCN30(__SHIFT) -}; - -static const struct dcn3_dpp_mask tf_mask = { - DPP_REG_LIST_SH_MASK_DCN30(_MASK) -}; - -#define opp_regs(id)\ -[id] = {\ - OPP_REG_LIST_DCN30(id),\ -} - -static const struct dcn20_opp_registers opp_regs[] = { - opp_regs(0), - opp_regs(1), - opp_regs(2), - opp_regs(3) -}; - -static const struct dcn20_opp_shift opp_shift = { - OPP_MASK_SH_LIST_DCN20(__SHIFT) -}; - -static const struct dcn20_opp_mask opp_mask = { - OPP_MASK_SH_LIST_DCN20(_MASK) -}; - -#define aux_engine_regs(id)\ -[id] = {\ - AUX_COMMON_REG_LIST0(id), \ - .AUXN_IMPCAL = 0, \ - .AUXP_IMPCAL = 0, \ - .AUX_RESET_MASK = DP_AUX0_AUX_CONTROL__AUX_RESET_MASK, \ -} - -static const struct dce110_aux_registers aux_engine_regs[] = { - aux_engine_regs(0), - aux_engine_regs(1), - aux_engine_regs(2), - aux_engine_regs(3), - aux_engine_regs(4) -}; - -#define dwbc_regs_dcn3(id)\ -[id] = {\ - DWBC_COMMON_REG_LIST_DCN30(id),\ -} - -static const struct dcn30_dwbc_registers dwbc30_regs[] = { - dwbc_regs_dcn3(0), -}; - -static const struct dcn30_dwbc_shift dwbc30_shift = { - DWBC_COMMON_MASK_SH_LIST_DCN30(__SHIFT) -}; - -static const struct dcn30_dwbc_mask dwbc30_mask = { - DWBC_COMMON_MASK_SH_LIST_DCN30(_MASK) -}; - -#define mcif_wb_regs_dcn3(id)\ -[id] = {\ - MCIF_WB_COMMON_REG_LIST_DCN30(id),\ -} - -static const struct dcn30_mmhubbub_registers mcif_wb30_regs[] = { - mcif_wb_regs_dcn3(0) -}; - -static const struct dcn30_mmhubbub_shift mcif_wb30_shift = { - MCIF_WB_COMMON_MASK_SH_LIST_DCN30(__SHIFT) -}; - -static const struct dcn30_mmhubbub_mask mcif_wb30_mask = { - MCIF_WB_COMMON_MASK_SH_LIST_DCN30(_MASK) -}; - -#define dsc_regsDCN20(id)\ -[id] = {\ - DSC_REG_LIST_DCN20(id)\ -} - -static const struct dcn20_dsc_registers dsc_regs[] = { - dsc_regsDCN20(0), - dsc_regsDCN20(1), - dsc_regsDCN20(2) -}; - -static const struct dcn20_dsc_shift dsc_shift = { - DSC_REG_LIST_SH_MASK_DCN20(__SHIFT) -}; - -static const struct dcn20_dsc_mask dsc_mask = { - DSC_REG_LIST_SH_MASK_DCN20(_MASK) -}; - -static const struct dcn30_mpc_registers mpc_regs = { - MPC_REG_LIST_DCN3_0(0), - MPC_REG_LIST_DCN3_0(1), - MPC_REG_LIST_DCN3_0(2), - MPC_REG_LIST_DCN3_0(3), - MPC_OUT_MUX_REG_LIST_DCN3_0(0), - MPC_OUT_MUX_REG_LIST_DCN3_0(1), - MPC_OUT_MUX_REG_LIST_DCN3_0(2), - MPC_OUT_MUX_REG_LIST_DCN3_0(3), - MPC_RMU_GLOBAL_REG_LIST_DCN3AG, - MPC_RMU_REG_LIST_DCN3AG(0), - MPC_RMU_REG_LIST_DCN3AG(1), - //MPC_RMU_REG_LIST_DCN3AG(2), - MPC_DWB_MUX_REG_LIST_DCN3_0(0), -}; - -static const struct dcn30_mpc_shift mpc_shift = { - MPC_COMMON_MASK_SH_LIST_DCN30(__SHIFT) -}; - -static const struct dcn30_mpc_mask mpc_mask = { - MPC_COMMON_MASK_SH_LIST_DCN30(_MASK) -}; - -#define optc_regs(id)\ -[id] = {OPTC_COMMON_REG_LIST_DCN3_1(id)} - -static const struct dcn_optc_registers optc_regs[] = { - optc_regs(0), - optc_regs(1), - optc_regs(2), - optc_regs(3) -}; - -static const struct dcn_optc_shift optc_shift = { - OPTC_COMMON_MASK_SH_LIST_DCN3_1(__SHIFT) -}; - -static const struct dcn_optc_mask optc_mask = { - OPTC_COMMON_MASK_SH_LIST_DCN3_1(_MASK) -}; - -#define hubp_regs(id)\ -[id] = {\ - HUBP_REG_LIST_DCN30(id)\ -} - -static const struct dcn_hubp2_registers hubp_regs[] = { - hubp_regs(0), - hubp_regs(1), - hubp_regs(2), - hubp_regs(3) -}; - - -static const struct dcn_hubp2_shift hubp_shift = { - HUBP_MASK_SH_LIST_DCN31(__SHIFT) -}; - -static const struct dcn_hubp2_mask hubp_mask = { - HUBP_MASK_SH_LIST_DCN31(_MASK) -}; -static const struct dcn_hubbub_registers hubbub_reg = { - HUBBUB_REG_LIST_DCN31(0) -}; - -static const struct dcn_hubbub_shift hubbub_shift = { - HUBBUB_MASK_SH_LIST_DCN31(__SHIFT) -}; - -static const struct dcn_hubbub_mask hubbub_mask = { - HUBBUB_MASK_SH_LIST_DCN31(_MASK) -}; - -static const struct dccg_registers dccg_regs = { - DCCG_REG_LIST_DCN31() -}; - -static const struct dccg_shift dccg_shift = { - DCCG_MASK_SH_LIST_DCN31(__SHIFT) -}; - -static const struct dccg_mask dccg_mask = { - DCCG_MASK_SH_LIST_DCN31(_MASK) -}; - - -#define SRII2(reg_name_pre, reg_name_post, id)\ - .reg_name_pre ## _ ## reg_name_post[id] = BASE(reg ## reg_name_pre \ - ## id ## _ ## reg_name_post ## _BASE_IDX) + \ - reg ## reg_name_pre ## id ## _ ## reg_name_post - - -#define HWSEQ_DCN31_REG_LIST()\ - SR(DCHUBBUB_GLOBAL_TIMER_CNTL), \ - SR(DCHUBBUB_ARB_HOSTVM_CNTL), \ - SR(DIO_MEM_PWR_CTRL), \ - SR(ODM_MEM_PWR_CTRL3), \ - SR(DMU_MEM_PWR_CNTL), \ - SR(MMHUBBUB_MEM_PWR_CNTL), \ - SR(DCCG_GATE_DISABLE_CNTL), \ - SR(DCCG_GATE_DISABLE_CNTL2), \ - SR(DCFCLK_CNTL),\ - SR(DC_MEM_GLOBAL_PWR_REQ_CNTL), \ - SRII(PIXEL_RATE_CNTL, OTG, 0), \ - SRII(PIXEL_RATE_CNTL, OTG, 1),\ - SRII(PIXEL_RATE_CNTL, OTG, 2),\ - SRII(PIXEL_RATE_CNTL, OTG, 3),\ - SRII(PHYPLL_PIXEL_RATE_CNTL, OTG, 0),\ - SRII(PHYPLL_PIXEL_RATE_CNTL, OTG, 1),\ - SRII(PHYPLL_PIXEL_RATE_CNTL, OTG, 2),\ - SRII(PHYPLL_PIXEL_RATE_CNTL, OTG, 3),\ - SR(MICROSECOND_TIME_BASE_DIV), \ - SR(MILLISECOND_TIME_BASE_DIV), \ - SR(DISPCLK_FREQ_CHANGE_CNTL), \ - SR(RBBMIF_TIMEOUT_DIS), \ - SR(RBBMIF_TIMEOUT_DIS_2), \ - SR(DCHUBBUB_CRC_CTRL), \ - SR(DPP_TOP0_DPP_CRC_CTRL), \ - SR(DPP_TOP0_DPP_CRC_VAL_B_A), \ - SR(DPP_TOP0_DPP_CRC_VAL_R_G), \ - SR(MPC_CRC_CTRL), \ - SR(MPC_CRC_RESULT_GB), \ - SR(MPC_CRC_RESULT_C), \ - SR(MPC_CRC_RESULT_AR), \ - SR(DOMAIN0_PG_CONFIG), \ - SR(DOMAIN1_PG_CONFIG), \ - SR(DOMAIN2_PG_CONFIG), \ - SR(DOMAIN3_PG_CONFIG), \ - SR(DOMAIN16_PG_CONFIG), \ - SR(DOMAIN17_PG_CONFIG), \ - SR(DOMAIN18_PG_CONFIG), \ - SR(DOMAIN0_PG_STATUS), \ - SR(DOMAIN1_PG_STATUS), \ - SR(DOMAIN2_PG_STATUS), \ - SR(DOMAIN3_PG_STATUS), \ - SR(DOMAIN16_PG_STATUS), \ - SR(DOMAIN17_PG_STATUS), \ - SR(DOMAIN18_PG_STATUS), \ - SR(D1VGA_CONTROL), \ - SR(D2VGA_CONTROL), \ - SR(D3VGA_CONTROL), \ - SR(D4VGA_CONTROL), \ - SR(D5VGA_CONTROL), \ - SR(D6VGA_CONTROL), \ - SR(DC_IP_REQUEST_CNTL), \ - SR(AZALIA_AUDIO_DTO), \ - SR(AZALIA_CONTROLLER_CLOCK_GATING), \ - SR(HPO_TOP_HW_CONTROL) - -static const struct dce_hwseq_registers hwseq_reg = { - HWSEQ_DCN31_REG_LIST() -}; - -#define HWSEQ_DCN31_MASK_SH_LIST(mask_sh)\ - HWSEQ_DCN_MASK_SH_LIST(mask_sh), \ - HWS_SF(, DCHUBBUB_GLOBAL_TIMER_CNTL, DCHUBBUB_GLOBAL_TIMER_REFDIV, mask_sh), \ - HWS_SF(, DCHUBBUB_ARB_HOSTVM_CNTL, DISABLE_HOSTVM_FORCE_ALLOW_PSTATE, mask_sh), \ - HWS_SF(, DOMAIN0_PG_CONFIG, DOMAIN_POWER_FORCEON, mask_sh), \ - HWS_SF(, DOMAIN0_PG_CONFIG, DOMAIN_POWER_GATE, mask_sh), \ - HWS_SF(, DOMAIN1_PG_CONFIG, DOMAIN_POWER_FORCEON, mask_sh), \ - HWS_SF(, DOMAIN1_PG_CONFIG, DOMAIN_POWER_GATE, mask_sh), \ - HWS_SF(, DOMAIN2_PG_CONFIG, DOMAIN_POWER_FORCEON, mask_sh), \ - HWS_SF(, DOMAIN2_PG_CONFIG, DOMAIN_POWER_GATE, mask_sh), \ - HWS_SF(, DOMAIN3_PG_CONFIG, DOMAIN_POWER_FORCEON, mask_sh), \ - HWS_SF(, DOMAIN3_PG_CONFIG, DOMAIN_POWER_GATE, mask_sh), \ - HWS_SF(, DOMAIN16_PG_CONFIG, DOMAIN_POWER_FORCEON, mask_sh), \ - HWS_SF(, DOMAIN16_PG_CONFIG, DOMAIN_POWER_GATE, mask_sh), \ - HWS_SF(, DOMAIN17_PG_CONFIG, DOMAIN_POWER_FORCEON, mask_sh), \ - HWS_SF(, DOMAIN17_PG_CONFIG, DOMAIN_POWER_GATE, mask_sh), \ - HWS_SF(, DOMAIN18_PG_CONFIG, DOMAIN_POWER_FORCEON, mask_sh), \ - HWS_SF(, DOMAIN18_PG_CONFIG, DOMAIN_POWER_GATE, mask_sh), \ - HWS_SF(, DOMAIN0_PG_STATUS, DOMAIN_PGFSM_PWR_STATUS, mask_sh), \ - HWS_SF(, DOMAIN1_PG_STATUS, DOMAIN_PGFSM_PWR_STATUS, mask_sh), \ - HWS_SF(, DOMAIN2_PG_STATUS, DOMAIN_PGFSM_PWR_STATUS, mask_sh), \ - HWS_SF(, DOMAIN3_PG_STATUS, DOMAIN_PGFSM_PWR_STATUS, mask_sh), \ - HWS_SF(, DOMAIN16_PG_STATUS, DOMAIN_PGFSM_PWR_STATUS, mask_sh), \ - HWS_SF(, DOMAIN17_PG_STATUS, DOMAIN_PGFSM_PWR_STATUS, mask_sh), \ - HWS_SF(, DOMAIN18_PG_STATUS, DOMAIN_PGFSM_PWR_STATUS, mask_sh), \ - HWS_SF(, DC_IP_REQUEST_CNTL, IP_REQUEST_EN, mask_sh), \ - HWS_SF(, AZALIA_AUDIO_DTO, AZALIA_AUDIO_DTO_MODULE, mask_sh), \ - HWS_SF(, HPO_TOP_CLOCK_CONTROL, HPO_HDMISTREAMCLK_G_GATE_DIS, mask_sh), \ - HWS_SF(, DMU_MEM_PWR_CNTL, DMCU_ERAM_MEM_PWR_FORCE, mask_sh), \ - HWS_SF(, ODM_MEM_PWR_CTRL3, ODM_MEM_UNASSIGNED_PWR_MODE, mask_sh), \ - HWS_SF(, ODM_MEM_PWR_CTRL3, ODM_MEM_VBLANK_PWR_MODE, mask_sh), \ - HWS_SF(, MMHUBBUB_MEM_PWR_CNTL, VGA_MEM_PWR_FORCE, mask_sh), \ - HWS_SF(, DIO_MEM_PWR_CTRL, I2C_LIGHT_SLEEP_FORCE, mask_sh), \ - HWS_SF(, HPO_TOP_HW_CONTROL, HPO_IO_EN, mask_sh) - -static const struct dce_hwseq_shift hwseq_shift = { - HWSEQ_DCN31_MASK_SH_LIST(__SHIFT) -}; - -static const struct dce_hwseq_mask hwseq_mask = { - HWSEQ_DCN31_MASK_SH_LIST(_MASK) -}; -#define vmid_regs(id)\ -[id] = {\ - DCN20_VMID_REG_LIST(id)\ -} - -static const struct dcn_vmid_registers vmid_regs[] = { - vmid_regs(0), - vmid_regs(1), - vmid_regs(2), - vmid_regs(3), - vmid_regs(4), - vmid_regs(5), - vmid_regs(6), - vmid_regs(7), - vmid_regs(8), - vmid_regs(9), - vmid_regs(10), - vmid_regs(11), - vmid_regs(12), - vmid_regs(13), - vmid_regs(14), - vmid_regs(15) -}; - -static const struct dcn20_vmid_shift vmid_shifts = { - DCN20_VMID_MASK_SH_LIST(__SHIFT) -}; - -static const struct dcn20_vmid_mask vmid_masks = { - DCN20_VMID_MASK_SH_LIST(_MASK) -}; - -static const struct resource_caps res_cap_dcn31 = { - .num_timing_generator = 4, - .num_opp = 4, - .num_video_plane = 4, - .num_audio = 5, - .num_stream_encoder = 5, - .num_dig_link_enc = 5, - .num_hpo_dp_stream_encoder = 4, - .num_hpo_dp_link_encoder = 2, - .num_pll = 5, - .num_dwb = 1, - .num_ddc = 5, - .num_vmid = 16, - .num_mpc_3dlut = 2, - .num_dsc = 3, -}; - -static const struct dc_plane_cap plane_cap = { - .type = DC_PLANE_TYPE_DCN_UNIVERSAL, - .per_pixel_alpha = true, - - .pixel_format_support = { - .argb8888 = true, - .nv12 = true, - .fp16 = true, - .p010 = true, - .ayuv = false, - }, - - .max_upscale_factor = { - .argb8888 = 16000, - .nv12 = 16000, - .fp16 = 16000 - }, - - // 6:1 downscaling ratio: 1000/6 = 166.666 - .max_downscale_factor = { - .argb8888 = 167, - .nv12 = 167, - .fp16 = 167 - }, - 64, - 64 -}; - -static const struct dc_debug_options debug_defaults_drv = { - .disable_z10 = true, /*hw not support it*/ - .disable_dmcu = true, - .force_abm_enable = false, - .timing_trace = false, - .clock_trace = true, - .disable_pplib_clock_request = false, - .pipe_split_policy = MPC_SPLIT_DYNAMIC, - .force_single_disp_pipe_split = false, - .disable_dcc = DCC_ENABLE, - .vsr_support = true, - .performance_trace = false, - .max_downscale_src_width = 4096,/*upto true 4k*/ - .disable_pplib_wm_range = false, - .scl_reset_length10 = true, - .sanity_checks = false, - .underflow_assert_delay_us = 0xFFFFFFFF, - .dwb_fi_phase = -1, // -1 = disable, - .dmub_command_table = true, - .pstate_enabled = true, - .use_max_lb = true, - .enable_mem_low_power = { - .bits = { - .vga = true, - .i2c = true, - .dmcu = false, // This is previously known to cause hang on S3 cycles if enabled - .dscl = true, - .cm = true, - .mpc = true, - .optc = true, - .vpg = true, - .afmt = true, - } - }, - .enable_legacy_fast_update = true, - .using_dml2 = false, -}; - -static const struct dc_panel_config panel_config_defaults = { - .psr = { - .disable_psr = false, - .disallow_psrsu = false, - .disallow_replay = false, - }, - .ilr = { - .optimize_edp_link_rate = true, - }, -}; - -static void dcn31_dpp_destroy(struct dpp **dpp) -{ - kfree(TO_DCN20_DPP(*dpp)); - *dpp = NULL; -} - -static struct dpp *dcn31_dpp_create( - struct dc_context *ctx, - uint32_t inst) -{ - struct dcn3_dpp *dpp = - kzalloc(sizeof(struct dcn3_dpp), GFP_KERNEL); - - if (!dpp) - return NULL; - - if (dpp3_construct(dpp, ctx, inst, - &dpp_regs[inst], &tf_shift, &tf_mask)) - return &dpp->base; - - BREAK_TO_DEBUGGER(); - kfree(dpp); - return NULL; -} - -static struct output_pixel_processor *dcn31_opp_create( - struct dc_context *ctx, uint32_t inst) -{ - struct dcn20_opp *opp = - kzalloc(sizeof(struct dcn20_opp), GFP_KERNEL); - - if (!opp) { - BREAK_TO_DEBUGGER(); - return NULL; - } - - dcn20_opp_construct(opp, ctx, inst, - &opp_regs[inst], &opp_shift, &opp_mask); - return &opp->base; -} - -static struct dce_aux *dcn31_aux_engine_create( - struct dc_context *ctx, - uint32_t inst) -{ - struct aux_engine_dce110 *aux_engine = - kzalloc(sizeof(struct aux_engine_dce110), GFP_KERNEL); - - if (!aux_engine) - return NULL; - - dce110_aux_engine_construct(aux_engine, ctx, inst, - SW_AUX_TIMEOUT_PERIOD_MULTIPLIER * AUX_TIMEOUT_PERIOD, - &aux_engine_regs[inst], - &aux_mask, - &aux_shift, - ctx->dc->caps.extended_aux_timeout_support); - - return &aux_engine->base; -} -#define i2c_inst_regs(id) { I2C_HW_ENGINE_COMMON_REG_LIST_DCN30(id) } - -static const struct dce_i2c_registers i2c_hw_regs[] = { - i2c_inst_regs(1), - i2c_inst_regs(2), - i2c_inst_regs(3), - i2c_inst_regs(4), - i2c_inst_regs(5), -}; - -static const struct dce_i2c_shift i2c_shifts = { - I2C_COMMON_MASK_SH_LIST_DCN30(__SHIFT) -}; - -static const struct dce_i2c_mask i2c_masks = { - I2C_COMMON_MASK_SH_LIST_DCN30(_MASK) -}; - -static struct dce_i2c_hw *dcn31_i2c_hw_create( - struct dc_context *ctx, - uint32_t inst) -{ - struct dce_i2c_hw *dce_i2c_hw = - kzalloc(sizeof(struct dce_i2c_hw), GFP_KERNEL); - - if (!dce_i2c_hw) - return NULL; - - dcn2_i2c_hw_construct(dce_i2c_hw, ctx, inst, - &i2c_hw_regs[inst], &i2c_shifts, &i2c_masks); - - return dce_i2c_hw; -} -static struct mpc *dcn31_mpc_create( - struct dc_context *ctx, - int num_mpcc, - int num_rmu) -{ - struct dcn30_mpc *mpc30 = kzalloc(sizeof(struct dcn30_mpc), - GFP_KERNEL); - - if (!mpc30) - return NULL; - - dcn30_mpc_construct(mpc30, ctx, - &mpc_regs, - &mpc_shift, - &mpc_mask, - num_mpcc, - num_rmu); - - return &mpc30->base; -} - -static struct hubbub *dcn31_hubbub_create(struct dc_context *ctx) -{ - int i; - - struct dcn20_hubbub *hubbub3 = kzalloc(sizeof(struct dcn20_hubbub), - GFP_KERNEL); - - if (!hubbub3) - return NULL; - - hubbub31_construct(hubbub3, ctx, - &hubbub_reg, - &hubbub_shift, - &hubbub_mask, - dcn3_16_ip.det_buffer_size_kbytes, - dcn3_16_ip.pixel_chunk_size_kbytes, - dcn3_16_ip.config_return_buffer_size_in_kbytes); - - - for (i = 0; i < res_cap_dcn31.num_vmid; i++) { - struct dcn20_vmid *vmid = &hubbub3->vmid[i]; - - vmid->ctx = ctx; - - vmid->regs = &vmid_regs[i]; - vmid->shifts = &vmid_shifts; - vmid->masks = &vmid_masks; - } - - return &hubbub3->base; -} - -static struct timing_generator *dcn31_timing_generator_create( - struct dc_context *ctx, - uint32_t instance) -{ - struct optc *tgn10 = - kzalloc(sizeof(struct optc), GFP_KERNEL); - - if (!tgn10) - return NULL; - - tgn10->base.inst = instance; - tgn10->base.ctx = ctx; - - tgn10->tg_regs = &optc_regs[instance]; - tgn10->tg_shift = &optc_shift; - tgn10->tg_mask = &optc_mask; - - dcn31_timing_generator_init(tgn10); - - return &tgn10->base; -} - -static const struct encoder_feature_support link_enc_feature = { - .max_hdmi_deep_color = COLOR_DEPTH_121212, - .max_hdmi_pixel_clock = 600000, - .hdmi_ycbcr420_supported = true, - .dp_ycbcr420_supported = true, - .fec_supported = true, - .flags.bits.IS_HBR2_CAPABLE = true, - .flags.bits.IS_HBR3_CAPABLE = true, - .flags.bits.IS_TPS3_CAPABLE = true, - .flags.bits.IS_TPS4_CAPABLE = true -}; - -static struct link_encoder *dcn31_link_encoder_create( - struct dc_context *ctx, - const struct encoder_init_data *enc_init_data) -{ - struct dcn20_link_encoder *enc20 = - kzalloc(sizeof(struct dcn20_link_encoder), GFP_KERNEL); - - if (!enc20) - return NULL; - - dcn31_link_encoder_construct(enc20, - enc_init_data, - &link_enc_feature, - &link_enc_regs[enc_init_data->transmitter], - &link_enc_aux_regs[enc_init_data->channel - 1], - &link_enc_hpd_regs[enc_init_data->hpd_source], - &le_shift, - &le_mask); - - return &enc20->enc10.base; -} - -/* Create a minimal link encoder object not associated with a particular - * physical connector. - * resource_funcs.link_enc_create_minimal - */ -static struct link_encoder *dcn31_link_enc_create_minimal( - struct dc_context *ctx, enum engine_id eng_id) -{ - struct dcn20_link_encoder *enc20; - - if ((eng_id - ENGINE_ID_DIGA) > ctx->dc->res_pool->res_cap->num_dig_link_enc) - return NULL; - - enc20 = kzalloc(sizeof(struct dcn20_link_encoder), GFP_KERNEL); - if (!enc20) - return NULL; - - dcn31_link_encoder_construct_minimal( - enc20, - ctx, - &link_enc_feature, - &link_enc_regs[eng_id - ENGINE_ID_DIGA], - eng_id); - - return &enc20->enc10.base; -} - -static struct panel_cntl *dcn31_panel_cntl_create(const struct panel_cntl_init_data *init_data) -{ - struct dcn31_panel_cntl *panel_cntl = - kzalloc(sizeof(struct dcn31_panel_cntl), GFP_KERNEL); - - if (!panel_cntl) - return NULL; - - dcn31_panel_cntl_construct(panel_cntl, init_data); - - return &panel_cntl->base; -} - -static void read_dce_straps( - struct dc_context *ctx, - struct resource_straps *straps) -{ - generic_reg_get(ctx, regDC_PINSTRAPS + BASE(regDC_PINSTRAPS_BASE_IDX), - FN(DC_PINSTRAPS, DC_PINSTRAPS_AUDIO), &straps->dc_pinstraps_audio); - -} - -static struct audio *dcn31_create_audio( - struct dc_context *ctx, unsigned int inst) -{ - return dce_audio_create(ctx, inst, - &audio_regs[inst], &audio_shift, &audio_mask); -} - -static struct vpg *dcn31_vpg_create( - struct dc_context *ctx, - uint32_t inst) -{ - struct dcn31_vpg *vpg31 = kzalloc(sizeof(struct dcn31_vpg), GFP_KERNEL); - - if (!vpg31) - return NULL; - - vpg31_construct(vpg31, ctx, inst, - &vpg_regs[inst], - &vpg_shift, - &vpg_mask); - - return &vpg31->base; -} - -static struct afmt *dcn31_afmt_create( - struct dc_context *ctx, - uint32_t inst) -{ - struct dcn31_afmt *afmt31 = kzalloc(sizeof(struct dcn31_afmt), GFP_KERNEL); - - if (!afmt31) - return NULL; - - afmt31_construct(afmt31, ctx, inst, - &afmt_regs[inst], - &afmt_shift, - &afmt_mask); - - // Light sleep by default, no need to power down here - - return &afmt31->base; -} - - -static struct apg *dcn31_apg_create( - struct dc_context *ctx, - uint32_t inst) -{ - struct dcn31_apg *apg31 = kzalloc(sizeof(struct dcn31_apg), GFP_KERNEL); - - if (!apg31) - return NULL; - - apg31_construct(apg31, ctx, inst, - &apg_regs[inst], - &apg_shift, - &apg_mask); - - return &apg31->base; -} - - -static struct stream_encoder *dcn316_stream_encoder_create( - enum engine_id eng_id, - struct dc_context *ctx) -{ - struct dcn10_stream_encoder *enc1; - struct vpg *vpg; - struct afmt *afmt; - int vpg_inst; - int afmt_inst; - - /* Mapping of VPG, AFMT, DME register blocks to DIO block instance */ - if (eng_id <= ENGINE_ID_DIGF) { - vpg_inst = eng_id; - afmt_inst = eng_id; - } else - return NULL; - - enc1 = kzalloc(sizeof(struct dcn10_stream_encoder), GFP_KERNEL); - vpg = dcn31_vpg_create(ctx, vpg_inst); - afmt = dcn31_afmt_create(ctx, afmt_inst); - - if (!enc1 || !vpg || !afmt) { - kfree(enc1); - kfree(vpg); - kfree(afmt); - return NULL; - } - - dcn30_dio_stream_encoder_construct(enc1, ctx, ctx->dc_bios, - eng_id, vpg, afmt, - &stream_enc_regs[eng_id], - &se_shift, &se_mask); - - return &enc1->base; -} - - -static struct hpo_dp_stream_encoder *dcn31_hpo_dp_stream_encoder_create( - enum engine_id eng_id, - struct dc_context *ctx) -{ - struct dcn31_hpo_dp_stream_encoder *hpo_dp_enc31; - struct vpg *vpg; - struct apg *apg; - uint32_t hpo_dp_inst; - uint32_t vpg_inst; - uint32_t apg_inst; - - ASSERT((eng_id >= ENGINE_ID_HPO_DP_0) && (eng_id <= ENGINE_ID_HPO_DP_3)); - hpo_dp_inst = eng_id - ENGINE_ID_HPO_DP_0; - - /* Mapping of VPG register blocks to HPO DP block instance: - * VPG[6] -> HPO_DP[0] - * VPG[7] -> HPO_DP[1] - * VPG[8] -> HPO_DP[2] - * VPG[9] -> HPO_DP[3] - */ - vpg_inst = hpo_dp_inst + 6; - - /* Mapping of APG register blocks to HPO DP block instance: - * APG[0] -> HPO_DP[0] - * APG[1] -> HPO_DP[1] - * APG[2] -> HPO_DP[2] - * APG[3] -> HPO_DP[3] - */ - apg_inst = hpo_dp_inst; - - /* allocate HPO stream encoder and create VPG sub-block */ - hpo_dp_enc31 = kzalloc(sizeof(struct dcn31_hpo_dp_stream_encoder), GFP_KERNEL); - vpg = dcn31_vpg_create(ctx, vpg_inst); - apg = dcn31_apg_create(ctx, apg_inst); - - if (!hpo_dp_enc31 || !vpg || !apg) { - kfree(hpo_dp_enc31); - kfree(vpg); - kfree(apg); - return NULL; - } - - dcn31_hpo_dp_stream_encoder_construct(hpo_dp_enc31, ctx, ctx->dc_bios, - hpo_dp_inst, eng_id, vpg, apg, - &hpo_dp_stream_enc_regs[hpo_dp_inst], - &hpo_dp_se_shift, &hpo_dp_se_mask); - - return &hpo_dp_enc31->base; -} - -static struct hpo_dp_link_encoder *dcn31_hpo_dp_link_encoder_create( - uint8_t inst, - struct dc_context *ctx) -{ - struct dcn31_hpo_dp_link_encoder *hpo_dp_enc31; - - /* allocate HPO link encoder */ - hpo_dp_enc31 = kzalloc(sizeof(struct dcn31_hpo_dp_link_encoder), GFP_KERNEL); - - hpo_dp_link_encoder31_construct(hpo_dp_enc31, ctx, inst, - &hpo_dp_link_enc_regs[inst], - &hpo_dp_le_shift, &hpo_dp_le_mask); - - return &hpo_dp_enc31->base; -} - - -static struct dce_hwseq *dcn31_hwseq_create( - struct dc_context *ctx) -{ - struct dce_hwseq *hws = kzalloc(sizeof(struct dce_hwseq), GFP_KERNEL); - - if (hws) { - hws->ctx = ctx; - hws->regs = &hwseq_reg; - hws->shifts = &hwseq_shift; - hws->masks = &hwseq_mask; - } - return hws; -} -static const struct resource_create_funcs res_create_funcs = { - .read_dce_straps = read_dce_straps, - .create_audio = dcn31_create_audio, - .create_stream_encoder = dcn316_stream_encoder_create, - .create_hpo_dp_stream_encoder = dcn31_hpo_dp_stream_encoder_create, - .create_hpo_dp_link_encoder = dcn31_hpo_dp_link_encoder_create, - .create_hwseq = dcn31_hwseq_create, -}; - -static void dcn316_resource_destruct(struct dcn316_resource_pool *pool) -{ - unsigned int i; - - for (i = 0; i < pool->base.stream_enc_count; i++) { - if (pool->base.stream_enc[i] != NULL) { - if (pool->base.stream_enc[i]->vpg != NULL) { - kfree(DCN30_VPG_FROM_VPG(pool->base.stream_enc[i]->vpg)); - pool->base.stream_enc[i]->vpg = NULL; - } - if (pool->base.stream_enc[i]->afmt != NULL) { - kfree(DCN30_AFMT_FROM_AFMT(pool->base.stream_enc[i]->afmt)); - pool->base.stream_enc[i]->afmt = NULL; - } - kfree(DCN10STRENC_FROM_STRENC(pool->base.stream_enc[i])); - pool->base.stream_enc[i] = NULL; - } - } - - for (i = 0; i < pool->base.hpo_dp_stream_enc_count; i++) { - if (pool->base.hpo_dp_stream_enc[i] != NULL) { - if (pool->base.hpo_dp_stream_enc[i]->vpg != NULL) { - kfree(DCN30_VPG_FROM_VPG(pool->base.hpo_dp_stream_enc[i]->vpg)); - pool->base.hpo_dp_stream_enc[i]->vpg = NULL; - } - if (pool->base.hpo_dp_stream_enc[i]->apg != NULL) { - kfree(DCN31_APG_FROM_APG(pool->base.hpo_dp_stream_enc[i]->apg)); - pool->base.hpo_dp_stream_enc[i]->apg = NULL; - } - kfree(DCN3_1_HPO_DP_STREAM_ENC_FROM_HPO_STREAM_ENC(pool->base.hpo_dp_stream_enc[i])); - pool->base.hpo_dp_stream_enc[i] = NULL; - } - } - - for (i = 0; i < pool->base.hpo_dp_link_enc_count; i++) { - if (pool->base.hpo_dp_link_enc[i] != NULL) { - kfree(DCN3_1_HPO_DP_LINK_ENC_FROM_HPO_LINK_ENC(pool->base.hpo_dp_link_enc[i])); - pool->base.hpo_dp_link_enc[i] = NULL; - } - } - - for (i = 0; i < pool->base.res_cap->num_dsc; i++) { - if (pool->base.dscs[i] != NULL) - dcn20_dsc_destroy(&pool->base.dscs[i]); - } - - if (pool->base.mpc != NULL) { - kfree(TO_DCN20_MPC(pool->base.mpc)); - pool->base.mpc = NULL; - } - if (pool->base.hubbub != NULL) { - kfree(pool->base.hubbub); - pool->base.hubbub = NULL; - } - for (i = 0; i < pool->base.pipe_count; i++) { - if (pool->base.dpps[i] != NULL) - dcn31_dpp_destroy(&pool->base.dpps[i]); - - if (pool->base.ipps[i] != NULL) - pool->base.ipps[i]->funcs->ipp_destroy(&pool->base.ipps[i]); - - if (pool->base.hubps[i] != NULL) { - kfree(TO_DCN20_HUBP(pool->base.hubps[i])); - pool->base.hubps[i] = NULL; - } - - if (pool->base.irqs != NULL) { - dal_irq_service_destroy(&pool->base.irqs); - } - } - - for (i = 0; i < pool->base.res_cap->num_ddc; i++) { - if (pool->base.engines[i] != NULL) - dce110_engine_destroy(&pool->base.engines[i]); - if (pool->base.hw_i2cs[i] != NULL) { - kfree(pool->base.hw_i2cs[i]); - pool->base.hw_i2cs[i] = NULL; - } - if (pool->base.sw_i2cs[i] != NULL) { - kfree(pool->base.sw_i2cs[i]); - pool->base.sw_i2cs[i] = NULL; - } - } - - for (i = 0; i < pool->base.res_cap->num_opp; i++) { - if (pool->base.opps[i] != NULL) - pool->base.opps[i]->funcs->opp_destroy(&pool->base.opps[i]); - } - - for (i = 0; i < pool->base.res_cap->num_timing_generator; i++) { - if (pool->base.timing_generators[i] != NULL) { - kfree(DCN10TG_FROM_TG(pool->base.timing_generators[i])); - pool->base.timing_generators[i] = NULL; - } - } - - for (i = 0; i < pool->base.res_cap->num_dwb; i++) { - if (pool->base.dwbc[i] != NULL) { - kfree(TO_DCN30_DWBC(pool->base.dwbc[i])); - pool->base.dwbc[i] = NULL; - } - if (pool->base.mcif_wb[i] != NULL) { - kfree(TO_DCN30_MMHUBBUB(pool->base.mcif_wb[i])); - pool->base.mcif_wb[i] = NULL; - } - } - - for (i = 0; i < pool->base.audio_count; i++) { - if (pool->base.audios[i]) - dce_aud_destroy(&pool->base.audios[i]); - } - - for (i = 0; i < pool->base.clk_src_count; i++) { - if (pool->base.clock_sources[i] != NULL) { - dcn20_clock_source_destroy(&pool->base.clock_sources[i]); - pool->base.clock_sources[i] = NULL; - } - } - - for (i = 0; i < pool->base.res_cap->num_mpc_3dlut; i++) { - if (pool->base.mpc_lut[i] != NULL) { - dc_3dlut_func_release(pool->base.mpc_lut[i]); - pool->base.mpc_lut[i] = NULL; - } - if (pool->base.mpc_shaper[i] != NULL) { - dc_transfer_func_release(pool->base.mpc_shaper[i]); - pool->base.mpc_shaper[i] = NULL; - } - } - - if (pool->base.dp_clock_source != NULL) { - dcn20_clock_source_destroy(&pool->base.dp_clock_source); - pool->base.dp_clock_source = NULL; - } - - for (i = 0; i < pool->base.res_cap->num_timing_generator; i++) { - if (pool->base.multiple_abms[i] != NULL) - dce_abm_destroy(&pool->base.multiple_abms[i]); - } - - if (pool->base.psr != NULL) - dmub_psr_destroy(&pool->base.psr); - - if (pool->base.dccg != NULL) - dcn_dccg_destroy(&pool->base.dccg); -} - -static struct hubp *dcn31_hubp_create( - struct dc_context *ctx, - uint32_t inst) -{ - struct dcn20_hubp *hubp2 = - kzalloc(sizeof(struct dcn20_hubp), GFP_KERNEL); - - if (!hubp2) - return NULL; - - if (hubp31_construct(hubp2, ctx, inst, - &hubp_regs[inst], &hubp_shift, &hubp_mask)) - return &hubp2->base; - - BREAK_TO_DEBUGGER(); - kfree(hubp2); - return NULL; -} - -static bool dcn31_dwbc_create(struct dc_context *ctx, struct resource_pool *pool) -{ - int i; - uint32_t pipe_count = pool->res_cap->num_dwb; - - for (i = 0; i < pipe_count; i++) { - struct dcn30_dwbc *dwbc30 = kzalloc(sizeof(struct dcn30_dwbc), - GFP_KERNEL); - - if (!dwbc30) { - dm_error("DC: failed to create dwbc30!\n"); - return false; - } - - dcn30_dwbc_construct(dwbc30, ctx, - &dwbc30_regs[i], - &dwbc30_shift, - &dwbc30_mask, - i); - - pool->dwbc[i] = &dwbc30->base; - } - return true; -} - -static bool dcn31_mmhubbub_create(struct dc_context *ctx, struct resource_pool *pool) -{ - int i; - uint32_t pipe_count = pool->res_cap->num_dwb; - - for (i = 0; i < pipe_count; i++) { - struct dcn30_mmhubbub *mcif_wb30 = kzalloc(sizeof(struct dcn30_mmhubbub), - GFP_KERNEL); - - if (!mcif_wb30) { - dm_error("DC: failed to create mcif_wb30!\n"); - return false; - } - - dcn30_mmhubbub_construct(mcif_wb30, ctx, - &mcif_wb30_regs[i], - &mcif_wb30_shift, - &mcif_wb30_mask, - i); - - pool->mcif_wb[i] = &mcif_wb30->base; - } - return true; -} - -static struct display_stream_compressor *dcn31_dsc_create( - struct dc_context *ctx, uint32_t inst) -{ - struct dcn20_dsc *dsc = - kzalloc(sizeof(struct dcn20_dsc), GFP_KERNEL); - - if (!dsc) { - BREAK_TO_DEBUGGER(); - return NULL; - } - - dsc2_construct(dsc, ctx, inst, &dsc_regs[inst], &dsc_shift, &dsc_mask); - return &dsc->base; -} - -static void dcn316_destroy_resource_pool(struct resource_pool **pool) -{ - struct dcn316_resource_pool *dcn31_pool = TO_DCN316_RES_POOL(*pool); - - dcn316_resource_destruct(dcn31_pool); - kfree(dcn31_pool); - *pool = NULL; -} - -static struct clock_source *dcn31_clock_source_create( - struct dc_context *ctx, - struct dc_bios *bios, - enum clock_source_id id, - const struct dce110_clk_src_regs *regs, - bool dp_clk_src) -{ - struct dce110_clk_src *clk_src = - kzalloc(sizeof(struct dce110_clk_src), GFP_KERNEL); - - if (!clk_src) - return NULL; - - if (dcn31_clk_src_construct(clk_src, ctx, bios, id, - regs, &cs_shift, &cs_mask)) { - clk_src->base.dp_clk_src = dp_clk_src; - return &clk_src->base; - } - - kfree(clk_src); - - BREAK_TO_DEBUGGER(); - return NULL; -} - -static bool is_dual_plane(enum surface_pixel_format format) -{ - return format >= SURFACE_PIXEL_FORMAT_VIDEO_BEGIN || format == SURFACE_PIXEL_FORMAT_GRPH_RGBE_ALPHA; -} - -static int dcn316_populate_dml_pipes_from_context( - struct dc *dc, struct dc_state *context, - display_e2e_pipe_params_st *pipes, - bool fast_validate) -{ - int i, pipe_cnt; - struct resource_context *res_ctx = &context->res_ctx; - struct pipe_ctx *pipe; - const int max_usable_det = context->bw_ctx.dml.ip.config_return_buffer_size_in_kbytes - DCN3_16_MIN_COMPBUF_SIZE_KB; - - DC_FP_START(); - dcn31x_populate_dml_pipes_from_context(dc, context, pipes, fast_validate); - DC_FP_END(); - - for (i = 0, pipe_cnt = 0; i < dc->res_pool->pipe_count; i++) { - struct dc_crtc_timing *timing; - - if (!res_ctx->pipe_ctx[i].stream) - continue; - pipe = &res_ctx->pipe_ctx[i]; - timing = &pipe->stream->timing; - - /* - * Immediate flip can be set dynamically after enabling the plane. - * We need to require support for immediate flip or underflow can be - * intermittently experienced depending on peak b/w requirements. - */ - pipes[pipe_cnt].pipe.src.immediate_flip = true; - - pipes[pipe_cnt].pipe.src.unbounded_req_mode = false; - pipes[pipe_cnt].pipe.dest.vfront_porch = timing->v_front_porch; - pipes[pipe_cnt].pipe.src.dcc_rate = 3; - pipes[pipe_cnt].dout.dsc_input_bpc = 0; - DC_FP_START(); - dcn31_zero_pipe_dcc_fraction(pipes, pipe_cnt); - DC_FP_END(); - - if (pipes[pipe_cnt].dout.dsc_enable) { - switch (timing->display_color_depth) { - case COLOR_DEPTH_888: - pipes[pipe_cnt].dout.dsc_input_bpc = 8; - break; - case COLOR_DEPTH_101010: - pipes[pipe_cnt].dout.dsc_input_bpc = 10; - break; - case COLOR_DEPTH_121212: - pipes[pipe_cnt].dout.dsc_input_bpc = 12; - break; - default: - ASSERT(0); - break; - } - } - - pipe_cnt++; - } - - if (pipe_cnt) - context->bw_ctx.dml.ip.det_buffer_size_kbytes = - (max_usable_det / DCN3_16_CRB_SEGMENT_SIZE_KB / pipe_cnt) * DCN3_16_CRB_SEGMENT_SIZE_KB; - if (context->bw_ctx.dml.ip.det_buffer_size_kbytes > DCN3_16_MAX_DET_SIZE) - context->bw_ctx.dml.ip.det_buffer_size_kbytes = DCN3_16_MAX_DET_SIZE; - ASSERT(context->bw_ctx.dml.ip.det_buffer_size_kbytes >= DCN3_16_DEFAULT_DET_SIZE); - dc->config.enable_4to1MPC = false; - if (pipe_cnt == 1 && pipe->plane_state && !dc->debug.disable_z9_mpc) { - if (is_dual_plane(pipe->plane_state->format) - && pipe->plane_state->src_rect.width <= 1920 && pipe->plane_state->src_rect.height <= 1080) { - dc->config.enable_4to1MPC = true; - context->bw_ctx.dml.ip.det_buffer_size_kbytes = - (max_usable_det / DCN3_16_CRB_SEGMENT_SIZE_KB / 4) * DCN3_16_CRB_SEGMENT_SIZE_KB; - } else if (!is_dual_plane(pipe->plane_state->format)) { - context->bw_ctx.dml.ip.det_buffer_size_kbytes = 192; - pipes[0].pipe.src.unbounded_req_mode = true; - } - } - - return pipe_cnt; -} - -static void dcn316_get_panel_config_defaults(struct dc_panel_config *panel_config) -{ - *panel_config = panel_config_defaults; -} - -static struct dc_cap_funcs cap_funcs = { - .get_dcc_compression_cap = dcn20_get_dcc_compression_cap -}; - -static struct resource_funcs dcn316_res_pool_funcs = { - .destroy = dcn316_destroy_resource_pool, - .link_enc_create = dcn31_link_encoder_create, - .link_enc_create_minimal = dcn31_link_enc_create_minimal, - .link_encs_assign = link_enc_cfg_link_encs_assign, - .link_enc_unassign = link_enc_cfg_link_enc_unassign, - .panel_cntl_create = dcn31_panel_cntl_create, - .validate_bandwidth = dcn31_validate_bandwidth, - .calculate_wm_and_dlg = dcn31_calculate_wm_and_dlg, - .update_soc_for_wm_a = dcn31_update_soc_for_wm_a, - .populate_dml_pipes = dcn316_populate_dml_pipes_from_context, - .acquire_free_pipe_as_secondary_dpp_pipe = dcn20_acquire_free_pipe_for_layer, - .release_pipe = dcn20_release_pipe, - .add_stream_to_ctx = dcn30_add_stream_to_ctx, - .add_dsc_to_stream_resource = dcn20_add_dsc_to_stream_resource, - .remove_stream_from_ctx = dcn20_remove_stream_from_ctx, - .populate_dml_writeback_from_context = dcn31_populate_dml_writeback_from_context, - .set_mcif_arb_params = dcn31_set_mcif_arb_params, - .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 = dcn316_update_bw_bounding_box, - .patch_unknown_plane_state = dcn20_patch_unknown_plane_state, - .get_panel_config_defaults = dcn316_get_panel_config_defaults, -}; - -static bool dcn316_resource_construct( - uint8_t num_virtual_links, - struct dc *dc, - struct dcn316_resource_pool *pool) -{ - int i; - struct dc_context *ctx = dc->ctx; - struct irq_service_init_data init_data; - - ctx->dc_bios->regs = &bios_regs; - - pool->base.res_cap = &res_cap_dcn31; - - pool->base.funcs = &dcn316_res_pool_funcs; - - /************************************************* - * Resource + asic cap harcoding * - *************************************************/ - pool->base.underlay_pipe_index = NO_UNDERLAY_PIPE; - pool->base.pipe_count = pool->base.res_cap->num_timing_generator; - pool->base.mpcc_count = pool->base.res_cap->num_timing_generator; - dc->caps.max_downscale_ratio = 600; - dc->caps.i2c_speed_in_khz = 100; - dc->caps.i2c_speed_in_khz_hdcp = 5; /*1.5 w/a applied by default*/ - dc->caps.max_cursor_size = 256; - dc->caps.min_horizontal_blanking_period = 80; - dc->caps.dmdata_alloc_size = 2048; - dc->caps.max_slave_planes = 2; - dc->caps.max_slave_yuv_planes = 2; - dc->caps.max_slave_rgb_planes = 2; - dc->caps.post_blend_color_processing = true; - dc->caps.force_dp_tps4_for_cp2520 = true; - if (dc->config.forceHBR2CP2520) - dc->caps.force_dp_tps4_for_cp2520 = false; - dc->caps.dp_hpo = true; - dc->caps.dp_hdmi21_pcon_support = true; - dc->caps.edp_dsc_support = true; - dc->caps.extended_aux_timeout_support = true; - dc->caps.dmcub_support = true; - dc->caps.is_apu = true; - - /* Color pipeline capabilities */ - dc->caps.color.dpp.dcn_arch = 1; - dc->caps.color.dpp.input_lut_shared = 0; - dc->caps.color.dpp.icsc = 1; - dc->caps.color.dpp.dgam_ram = 0; // must use gamma_corr - dc->caps.color.dpp.dgam_rom_caps.srgb = 1; - dc->caps.color.dpp.dgam_rom_caps.bt2020 = 1; - dc->caps.color.dpp.dgam_rom_caps.gamma2_2 = 1; - dc->caps.color.dpp.dgam_rom_caps.pq = 1; - dc->caps.color.dpp.dgam_rom_caps.hlg = 1; - dc->caps.color.dpp.post_csc = 1; - dc->caps.color.dpp.gamma_corr = 1; - dc->caps.color.dpp.dgam_rom_for_yuv = 0; - - dc->caps.color.dpp.hw_3d_lut = 1; - dc->caps.color.dpp.ogam_ram = 1; - // no OGAM ROM on DCN301 - dc->caps.color.dpp.ogam_rom_caps.srgb = 0; - dc->caps.color.dpp.ogam_rom_caps.bt2020 = 0; - dc->caps.color.dpp.ogam_rom_caps.gamma2_2 = 0; - dc->caps.color.dpp.ogam_rom_caps.pq = 0; - dc->caps.color.dpp.ogam_rom_caps.hlg = 0; - dc->caps.color.dpp.ocsc = 0; - - dc->caps.color.mpc.gamut_remap = 1; - dc->caps.color.mpc.num_3dluts = pool->base.res_cap->num_mpc_3dlut; //2 - dc->caps.color.mpc.ogam_ram = 1; - dc->caps.color.mpc.ogam_rom_caps.srgb = 0; - dc->caps.color.mpc.ogam_rom_caps.bt2020 = 0; - dc->caps.color.mpc.ogam_rom_caps.gamma2_2 = 0; - dc->caps.color.mpc.ogam_rom_caps.pq = 0; - dc->caps.color.mpc.ogam_rom_caps.hlg = 0; - dc->caps.color.mpc.ocsc = 1; - - /* read VBIOS LTTPR caps */ - { - if (ctx->dc_bios->funcs->get_lttpr_caps) { - enum bp_result bp_query_result; - uint8_t is_vbios_lttpr_enable = 0; - - bp_query_result = ctx->dc_bios->funcs->get_lttpr_caps(ctx->dc_bios, &is_vbios_lttpr_enable); - dc->caps.vbios_lttpr_enable = (bp_query_result == BP_RESULT_OK) && !!is_vbios_lttpr_enable; - } - - /* interop bit is implicit */ - { - dc->caps.vbios_lttpr_aware = true; - } - } - - if (dc->ctx->dce_environment == DCE_ENV_PRODUCTION_DRV) - dc->debug = debug_defaults_drv; - - // Init the vm_helper - if (dc->vm_helper) - vm_helper_init(dc->vm_helper, 16); - - /************************************************* - * Create resources * - *************************************************/ - - /* Clock Sources for Pixel Clock*/ - pool->base.clock_sources[DCN31_CLK_SRC_PLL0] = - dcn31_clock_source_create(ctx, ctx->dc_bios, - CLOCK_SOURCE_COMBO_PHY_PLL0, - &clk_src_regs[0], false); - pool->base.clock_sources[DCN31_CLK_SRC_PLL1] = - dcn31_clock_source_create(ctx, ctx->dc_bios, - CLOCK_SOURCE_COMBO_PHY_PLL1, - &clk_src_regs[1], false); - pool->base.clock_sources[DCN31_CLK_SRC_PLL2] = - dcn31_clock_source_create(ctx, ctx->dc_bios, - CLOCK_SOURCE_COMBO_PHY_PLL2, - &clk_src_regs[2], false); - pool->base.clock_sources[DCN31_CLK_SRC_PLL3] = - dcn31_clock_source_create(ctx, ctx->dc_bios, - CLOCK_SOURCE_COMBO_PHY_PLL3, - &clk_src_regs[3], false); - pool->base.clock_sources[DCN31_CLK_SRC_PLL4] = - dcn31_clock_source_create(ctx, ctx->dc_bios, - CLOCK_SOURCE_COMBO_PHY_PLL4, - &clk_src_regs[4], false); - - pool->base.clk_src_count = DCN30_CLK_SRC_TOTAL; - - /* todo: not reuse phy_pll registers */ - pool->base.dp_clock_source = - dcn31_clock_source_create(ctx, ctx->dc_bios, - CLOCK_SOURCE_ID_DP_DTO, - &clk_src_regs[0], true); - - for (i = 0; i < pool->base.clk_src_count; i++) { - if (pool->base.clock_sources[i] == NULL) { - dm_error("DC: failed to create clock sources!\n"); - BREAK_TO_DEBUGGER(); - goto create_fail; - } - } - - /* TODO: DCCG */ - pool->base.dccg = dccg31_create(ctx, &dccg_regs, &dccg_shift, &dccg_mask); - if (pool->base.dccg == NULL) { - dm_error("DC: failed to create dccg!\n"); - BREAK_TO_DEBUGGER(); - goto create_fail; - } - - /* TODO: IRQ */ - init_data.ctx = dc->ctx; - pool->base.irqs = dal_irq_service_dcn31_create(&init_data); - if (!pool->base.irqs) - goto create_fail; - - /* HUBBUB */ - pool->base.hubbub = dcn31_hubbub_create(ctx); - if (pool->base.hubbub == NULL) { - BREAK_TO_DEBUGGER(); - dm_error("DC: failed to create hubbub!\n"); - goto create_fail; - } - - /* HUBPs, DPPs, OPPs and TGs */ - for (i = 0; i < pool->base.pipe_count; i++) { - pool->base.hubps[i] = dcn31_hubp_create(ctx, i); - if (pool->base.hubps[i] == NULL) { - BREAK_TO_DEBUGGER(); - dm_error( - "DC: failed to create hubps!\n"); - goto create_fail; - } - - pool->base.dpps[i] = dcn31_dpp_create(ctx, i); - if (pool->base.dpps[i] == NULL) { - BREAK_TO_DEBUGGER(); - dm_error( - "DC: failed to create dpps!\n"); - goto create_fail; - } - } - - for (i = 0; i < pool->base.res_cap->num_opp; i++) { - pool->base.opps[i] = dcn31_opp_create(ctx, i); - if (pool->base.opps[i] == NULL) { - BREAK_TO_DEBUGGER(); - dm_error( - "DC: failed to create output pixel processor!\n"); - goto create_fail; - } - } - - for (i = 0; i < pool->base.res_cap->num_timing_generator; i++) { - pool->base.timing_generators[i] = dcn31_timing_generator_create( - ctx, i); - if (pool->base.timing_generators[i] == NULL) { - BREAK_TO_DEBUGGER(); - dm_error("DC: failed to create tg!\n"); - goto create_fail; - } - } - pool->base.timing_generator_count = i; - - /* PSR */ - pool->base.psr = dmub_psr_create(ctx); - if (pool->base.psr == NULL) { - dm_error("DC: failed to create psr obj!\n"); - BREAK_TO_DEBUGGER(); - goto create_fail; - } - - /* ABM */ - for (i = 0; i < pool->base.res_cap->num_timing_generator; i++) { - pool->base.multiple_abms[i] = dmub_abm_create(ctx, - &abm_regs[i], - &abm_shift, - &abm_mask); - if (pool->base.multiple_abms[i] == NULL) { - dm_error("DC: failed to create abm for pipe %d!\n", i); - BREAK_TO_DEBUGGER(); - goto create_fail; - } - } - - /* MPC and DSC */ - pool->base.mpc = dcn31_mpc_create(ctx, pool->base.mpcc_count, pool->base.res_cap->num_mpc_3dlut); - if (pool->base.mpc == NULL) { - BREAK_TO_DEBUGGER(); - dm_error("DC: failed to create mpc!\n"); - goto create_fail; - } - - for (i = 0; i < pool->base.res_cap->num_dsc; i++) { - pool->base.dscs[i] = dcn31_dsc_create(ctx, i); - if (pool->base.dscs[i] == NULL) { - BREAK_TO_DEBUGGER(); - dm_error("DC: failed to create display stream compressor %d!\n", i); - goto create_fail; - } - } - - /* DWB and MMHUBBUB */ - if (!dcn31_dwbc_create(ctx, &pool->base)) { - BREAK_TO_DEBUGGER(); - dm_error("DC: failed to create dwbc!\n"); - goto create_fail; - } - - if (!dcn31_mmhubbub_create(ctx, &pool->base)) { - BREAK_TO_DEBUGGER(); - dm_error("DC: failed to create mcif_wb!\n"); - goto create_fail; - } - - /* AUX and I2C */ - for (i = 0; i < pool->base.res_cap->num_ddc; i++) { - pool->base.engines[i] = dcn31_aux_engine_create(ctx, i); - if (pool->base.engines[i] == NULL) { - BREAK_TO_DEBUGGER(); - dm_error( - "DC:failed to create aux engine!!\n"); - goto create_fail; - } - pool->base.hw_i2cs[i] = dcn31_i2c_hw_create(ctx, i); - if (pool->base.hw_i2cs[i] == NULL) { - BREAK_TO_DEBUGGER(); - dm_error( - "DC:failed to create hw i2c!!\n"); - goto create_fail; - } - pool->base.sw_i2cs[i] = NULL; - } - - /* Audio, Stream Encoders including HPO and virtual, MPC 3D LUTs */ - if (!resource_construct(num_virtual_links, dc, &pool->base, - &res_create_funcs)) - goto create_fail; - - /* HW Sequencer and Plane caps */ - dcn31_hw_sequencer_construct(dc); - - dc->caps.max_planes = pool->base.pipe_count; - - for (i = 0; i < dc->caps.max_planes; ++i) - dc->caps.planes[i] = plane_cap; - - dc->cap_funcs = cap_funcs; - - dc->dcn_ip->max_num_dpp = dcn3_16_ip.max_num_dpp; - - return true; - -create_fail: - - dcn316_resource_destruct(pool); - - return false; -} - -struct resource_pool *dcn316_create_resource_pool( - const struct dc_init_data *init_data, - struct dc *dc) -{ - struct dcn316_resource_pool *pool = - kzalloc(sizeof(struct dcn316_resource_pool), GFP_KERNEL); - - if (!pool) - return NULL; - - if (dcn316_resource_construct(init_data->num_virtual_links, dc, pool)) - return &pool->base; - - BREAK_TO_DEBUGGER(); - kfree(pool); - return NULL; -} diff --git a/drivers/gpu/drm/amd/display/dc/dcn316/dcn316_resource.h b/drivers/gpu/drm/amd/display/dc/dcn316/dcn316_resource.h deleted file mode 100644 index aba6d634131b..000000000000 --- a/drivers/gpu/drm/amd/display/dc/dcn316/dcn316_resource.h +++ /dev/null @@ -1,44 +0,0 @@ -/* - * 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 _DCN316_RESOURCE_H_ -#define _DCN316_RESOURCE_H_ - -#include "core_types.h" - -#define TO_DCN316_RES_POOL(pool)\ - container_of(pool, struct dcn316_resource_pool, base) - -extern struct _vcs_dpi_ip_params_st dcn3_16_ip; - -struct dcn316_resource_pool { - struct resource_pool base; -}; - -struct resource_pool *dcn316_create_resource_pool( - const struct dc_init_data *init_data, - struct dc *dc); - -#endif /* _DCN316_RESOURCE_H_ */ diff --git a/drivers/gpu/drm/amd/display/dc/dcn32/Makefile b/drivers/gpu/drm/amd/display/dc/dcn32/Makefile index 8bb251307247..3bb17dd01e4c 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn32/Makefile +++ b/drivers/gpu/drm/amd/display/dc/dcn32/Makefile @@ -10,7 +10,7 @@ # # Makefile for dcn32. -DCN32 = dcn32_resource.o dcn32_hubbub.o dcn32_init.o dcn32_dccg.o \ +DCN32 = dcn32_hubbub.o dcn32_init.o dcn32_dccg.o \ dcn32_dccg.o dcn32_optc.o dcn32_mmhubbub.o dcn32_hubp.o dcn32_dpp.o \ dcn32_dio_stream_encoder.o dcn32_dio_link_encoder.o dcn32_hpo_dp_link_encoder.o \ dcn32_resource_helpers.o dcn32_mpc.o diff --git a/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_resource.c b/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_resource.c deleted file mode 100644 index 89b072447dba..000000000000 --- a/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_resource.c +++ /dev/null @@ -1,2862 +0,0 @@ -// SPDX-License-Identifier: MIT -/* - * Copyright 2022 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 "dm_services.h" -#include "dc.h" - -#include "dcn32_init.h" - -#include "resource.h" -#include "include/irq_service_interface.h" -#include "dcn32_resource.h" - -#include "dcn20/dcn20_resource.h" -#include "dcn30/dcn30_resource.h" - -#include "dcn10/dcn10_ipp.h" -#include "dcn30/dcn30_hubbub.h" -#include "dcn31/dcn31_hubbub.h" -#include "dcn32/dcn32_hubbub.h" -#include "dcn32/dcn32_mpc.h" -#include "dcn32_hubp.h" -#include "irq/dcn32/irq_service_dcn32.h" -#include "dcn32/dcn32_dpp.h" -#include "dcn32/dcn32_optc.h" -#include "dcn20/dcn20_hwseq.h" -#include "dcn30/dcn30_hwseq.h" -#include "dce110/dce110_hwseq.h" -#include "dcn30/dcn30_opp.h" -#include "dcn20/dcn20_dsc.h" -#include "dcn30/dcn30_vpg.h" -#include "dcn30/dcn30_afmt.h" -#include "dcn30/dcn30_dio_stream_encoder.h" -#include "dcn32/dcn32_dio_stream_encoder.h" -#include "dcn31/dcn31_hpo_dp_stream_encoder.h" -#include "dcn31/dcn31_hpo_dp_link_encoder.h" -#include "dcn32/dcn32_hpo_dp_link_encoder.h" -#include "dcn31/dcn31_apg.h" -#include "dcn31/dcn31_dio_link_encoder.h" -#include "dcn32/dcn32_dio_link_encoder.h" -#include "dce/dce_clock_source.h" -#include "dce/dce_audio.h" -#include "dce/dce_hwseq.h" -#include "clk_mgr.h" -#include "virtual/virtual_stream_encoder.h" -#include "dml/display_mode_vba.h" -#include "dcn32/dcn32_dccg.h" -#include "dcn10/dcn10_resource.h" -#include "link.h" -#include "dcn31/dcn31_panel_cntl.h" - -#include "dcn30/dcn30_dwb.h" -#include "dcn32/dcn32_mmhubbub.h" - -#include "dcn/dcn_3_2_0_offset.h" -#include "dcn/dcn_3_2_0_sh_mask.h" -#include "nbio/nbio_4_3_0_offset.h" - -#include "reg_helper.h" -#include "dce/dmub_abm.h" -#include "dce/dmub_psr.h" -#include "dce/dce_aux.h" -#include "dce/dce_i2c.h" - -#include "dml/dcn30/display_mode_vba_30.h" -#include "vm_helper.h" -#include "dcn20/dcn20_vmid.h" -#include "dml/dcn32/dcn32_fpu.h" - -#include "dml2/dml2_wrapper.h" - -#define DC_LOGGER_INIT(logger) - -enum dcn32_clk_src_array_id { - DCN32_CLK_SRC_PLL0, - DCN32_CLK_SRC_PLL1, - DCN32_CLK_SRC_PLL2, - DCN32_CLK_SRC_PLL3, - DCN32_CLK_SRC_PLL4, - DCN32_CLK_SRC_TOTAL -}; - -/* begin ********************* - * macros to expend register list macro defined in HW object header file - */ - -/* DCN */ -#define BASE_INNER(seg) ctx->dcn_reg_offsets[seg] - -#define BASE(seg) BASE_INNER(seg) - -#define SR(reg_name)\ - REG_STRUCT.reg_name = BASE(reg ## reg_name ## _BASE_IDX) + \ - reg ## reg_name -#define SR_ARR(reg_name, id) \ - REG_STRUCT[id].reg_name = BASE(reg##reg_name##_BASE_IDX) + reg##reg_name - -#define SR_ARR_INIT(reg_name, id, value) \ - REG_STRUCT[id].reg_name = value - -#define SRI(reg_name, block, id)\ - REG_STRUCT.reg_name = BASE(reg ## block ## id ## _ ## reg_name ## _BASE_IDX) + \ - reg ## block ## id ## _ ## reg_name - -#define SRI_ARR(reg_name, block, id)\ - REG_STRUCT[id].reg_name = BASE(reg ## block ## id ## _ ## reg_name ## _BASE_IDX) + \ - reg ## block ## id ## _ ## reg_name - -#define SR_ARR_I2C(reg_name, id) \ - REG_STRUCT[id-1].reg_name = BASE(reg##reg_name##_BASE_IDX) + reg##reg_name - -#define SRI_ARR_I2C(reg_name, block, id)\ - REG_STRUCT[id-1].reg_name = BASE(reg ## block ## id ## _ ## reg_name ## _BASE_IDX) + \ - reg ## block ## id ## _ ## reg_name - -#define SRI_ARR_ALPHABET(reg_name, block, index, id)\ - REG_STRUCT[index].reg_name = BASE(reg ## block ## id ## _ ## reg_name ## _BASE_IDX) + \ - reg ## block ## id ## _ ## reg_name - -#define SRI2(reg_name, block, id)\ - .reg_name = BASE(reg ## reg_name ## _BASE_IDX) + \ - reg ## reg_name -#define SRI2_ARR(reg_name, block, id)\ - REG_STRUCT[id].reg_name = BASE(reg ## reg_name ## _BASE_IDX) + \ - reg ## reg_name - -#define SRIR(var_name, reg_name, block, id)\ - .var_name = BASE(reg ## block ## id ## _ ## reg_name ## _BASE_IDX) + \ - reg ## block ## id ## _ ## reg_name - -#define SRII(reg_name, block, id)\ - REG_STRUCT.reg_name[id] = BASE(reg ## block ## id ## _ ## reg_name ## _BASE_IDX) + \ - reg ## block ## id ## _ ## reg_name - -#define SRII_ARR_2(reg_name, block, id, inst)\ - REG_STRUCT[inst].reg_name[id] = BASE(reg ## block ## id ## _ ## reg_name ## _BASE_IDX) + \ - reg ## block ## id ## _ ## reg_name - -#define SRII_MPC_RMU(reg_name, block, id)\ - .RMU##_##reg_name[id] = BASE(reg ## block ## id ## _ ## reg_name ## _BASE_IDX) + \ - reg ## block ## id ## _ ## reg_name - -#define SRII_DWB(reg_name, temp_name, block, id)\ - REG_STRUCT.reg_name[id] = BASE(reg ## block ## id ## _ ## temp_name ## _BASE_IDX) + \ - reg ## block ## id ## _ ## temp_name - -#define SF_DWB2(reg_name, block, id, field_name, post_fix) \ - .field_name = reg_name ## __ ## field_name ## post_fix - -#define DCCG_SRII(reg_name, block, id)\ - REG_STRUCT.block ## _ ## reg_name[id] = BASE(reg ## block ## id ## _ ## reg_name ## _BASE_IDX) + \ - reg ## block ## id ## _ ## reg_name - -#define VUPDATE_SRII(reg_name, block, id)\ - REG_STRUCT.reg_name[id] = BASE(reg ## reg_name ## _ ## block ## id ## _BASE_IDX) + \ - reg ## reg_name ## _ ## block ## id - -/* NBIO */ -#define NBIO_BASE_INNER(seg) ctx->nbio_reg_offsets[seg] - -#define NBIO_BASE(seg) \ - NBIO_BASE_INNER(seg) - -#define NBIO_SR(reg_name)\ - REG_STRUCT.reg_name = NBIO_BASE(regBIF_BX0_ ## reg_name ## _BASE_IDX) + \ - regBIF_BX0_ ## reg_name -#define NBIO_SR_ARR(reg_name, id)\ - REG_STRUCT[id].reg_name = NBIO_BASE(regBIF_BX0_ ## reg_name ## _BASE_IDX) + \ - regBIF_BX0_ ## reg_name - -#undef CTX -#define CTX ctx -#define REG(reg_name) \ - (ctx->dcn_reg_offsets[reg ## reg_name ## _BASE_IDX] + reg ## reg_name) - -static struct bios_registers bios_regs; - -#define bios_regs_init() \ - ( \ - NBIO_SR(BIOS_SCRATCH_3),\ - NBIO_SR(BIOS_SCRATCH_6)\ - ) - -#define clk_src_regs_init(index, pllid)\ - CS_COMMON_REG_LIST_DCN3_0_RI(index, pllid) - -static struct dce110_clk_src_regs clk_src_regs[5]; - -static const struct dce110_clk_src_shift cs_shift = { - CS_COMMON_MASK_SH_LIST_DCN3_2(__SHIFT) -}; - -static const struct dce110_clk_src_mask cs_mask = { - CS_COMMON_MASK_SH_LIST_DCN3_2(_MASK) -}; - -#define abm_regs_init(id)\ - ABM_DCN32_REG_LIST_RI(id) - -static struct dce_abm_registers abm_regs[4]; - -static const struct dce_abm_shift abm_shift = { - ABM_MASK_SH_LIST_DCN32(__SHIFT) -}; - -static const struct dce_abm_mask abm_mask = { - ABM_MASK_SH_LIST_DCN32(_MASK) -}; - -#define audio_regs_init(id)\ - AUD_COMMON_REG_LIST_RI(id) - -static struct dce_audio_registers audio_regs[5]; - -#define DCE120_AUD_COMMON_MASK_SH_LIST(mask_sh)\ - SF(AZF0ENDPOINT0_AZALIA_F0_CODEC_ENDPOINT_INDEX, AZALIA_ENDPOINT_REG_INDEX, mask_sh),\ - SF(AZF0ENDPOINT0_AZALIA_F0_CODEC_ENDPOINT_DATA, AZALIA_ENDPOINT_REG_DATA, mask_sh),\ - AUD_COMMON_MASK_SH_LIST_BASE(mask_sh) - -static const struct dce_audio_shift audio_shift = { - DCE120_AUD_COMMON_MASK_SH_LIST(__SHIFT) -}; - -static const struct dce_audio_mask audio_mask = { - DCE120_AUD_COMMON_MASK_SH_LIST(_MASK) -}; - -#define vpg_regs_init(id)\ - VPG_DCN3_REG_LIST_RI(id) - -static struct dcn30_vpg_registers vpg_regs[10]; - -static const struct dcn30_vpg_shift vpg_shift = { - DCN3_VPG_MASK_SH_LIST(__SHIFT) -}; - -static const struct dcn30_vpg_mask vpg_mask = { - DCN3_VPG_MASK_SH_LIST(_MASK) -}; - -#define afmt_regs_init(id)\ - AFMT_DCN3_REG_LIST_RI(id) - -static struct dcn30_afmt_registers afmt_regs[6]; - -static const struct dcn30_afmt_shift afmt_shift = { - DCN3_AFMT_MASK_SH_LIST(__SHIFT) -}; - -static const struct dcn30_afmt_mask afmt_mask = { - DCN3_AFMT_MASK_SH_LIST(_MASK) -}; - -#define apg_regs_init(id)\ - APG_DCN31_REG_LIST_RI(id) - -static struct dcn31_apg_registers apg_regs[4]; - -static const struct dcn31_apg_shift apg_shift = { - DCN31_APG_MASK_SH_LIST(__SHIFT) -}; - -static const struct dcn31_apg_mask apg_mask = { - DCN31_APG_MASK_SH_LIST(_MASK) -}; - -#define stream_enc_regs_init(id)\ - SE_DCN32_REG_LIST_RI(id) - -static struct dcn10_stream_enc_registers stream_enc_regs[5]; - -static const struct dcn10_stream_encoder_shift se_shift = { - SE_COMMON_MASK_SH_LIST_DCN32(__SHIFT) -}; - -static const struct dcn10_stream_encoder_mask se_mask = { - SE_COMMON_MASK_SH_LIST_DCN32(_MASK) -}; - - -#define aux_regs_init(id)\ - DCN2_AUX_REG_LIST_RI(id) - -static struct dcn10_link_enc_aux_registers link_enc_aux_regs[5]; - -#define hpd_regs_init(id)\ - HPD_REG_LIST_RI(id) - -static struct dcn10_link_enc_hpd_registers link_enc_hpd_regs[5]; - -#define link_regs_init(id, phyid)\ - ( \ - LE_DCN31_REG_LIST_RI(id), \ - UNIPHY_DCN2_REG_LIST_RI(id, phyid)\ - ) - /*DPCS_DCN31_REG_LIST(id),*/ \ - -static struct dcn10_link_enc_registers link_enc_regs[5]; - -static const struct dcn10_link_enc_shift le_shift = { - LINK_ENCODER_MASK_SH_LIST_DCN31(__SHIFT), \ - //DPCS_DCN31_MASK_SH_LIST(__SHIFT) -}; - -static const struct dcn10_link_enc_mask le_mask = { - LINK_ENCODER_MASK_SH_LIST_DCN31(_MASK), \ - //DPCS_DCN31_MASK_SH_LIST(_MASK) -}; - -#define hpo_dp_stream_encoder_reg_init(id)\ - DCN3_1_HPO_DP_STREAM_ENC_REG_LIST_RI(id) - -static struct dcn31_hpo_dp_stream_encoder_registers hpo_dp_stream_enc_regs[4]; - -static const struct dcn31_hpo_dp_stream_encoder_shift hpo_dp_se_shift = { - DCN3_1_HPO_DP_STREAM_ENC_MASK_SH_LIST(__SHIFT) -}; - -static const struct dcn31_hpo_dp_stream_encoder_mask hpo_dp_se_mask = { - DCN3_1_HPO_DP_STREAM_ENC_MASK_SH_LIST(_MASK) -}; - - -#define hpo_dp_link_encoder_reg_init(id)\ - DCN3_1_HPO_DP_LINK_ENC_REG_LIST_RI(id) - /*DCN3_1_RDPCSTX_REG_LIST(0),*/ - /*DCN3_1_RDPCSTX_REG_LIST(1),*/ - /*DCN3_1_RDPCSTX_REG_LIST(2),*/ - /*DCN3_1_RDPCSTX_REG_LIST(3),*/ - -static struct dcn31_hpo_dp_link_encoder_registers hpo_dp_link_enc_regs[2]; - -static const struct dcn31_hpo_dp_link_encoder_shift hpo_dp_le_shift = { - DCN3_2_HPO_DP_LINK_ENC_MASK_SH_LIST(__SHIFT) -}; - -static const struct dcn31_hpo_dp_link_encoder_mask hpo_dp_le_mask = { - DCN3_2_HPO_DP_LINK_ENC_MASK_SH_LIST(_MASK) -}; - -#define dpp_regs_init(id)\ - DPP_REG_LIST_DCN30_COMMON_RI(id) - -static struct dcn3_dpp_registers dpp_regs[4]; - -static const struct dcn3_dpp_shift tf_shift = { - DPP_REG_LIST_SH_MASK_DCN30_COMMON(__SHIFT) -}; - -static const struct dcn3_dpp_mask tf_mask = { - DPP_REG_LIST_SH_MASK_DCN30_COMMON(_MASK) -}; - - -#define opp_regs_init(id)\ - OPP_REG_LIST_DCN30_RI(id) - -static struct dcn20_opp_registers opp_regs[4]; - -static const struct dcn20_opp_shift opp_shift = { - OPP_MASK_SH_LIST_DCN20(__SHIFT) -}; - -static const struct dcn20_opp_mask opp_mask = { - OPP_MASK_SH_LIST_DCN20(_MASK) -}; - -#define aux_engine_regs_init(id)\ - ( \ - AUX_COMMON_REG_LIST0_RI(id), \ - SR_ARR_INIT(AUXN_IMPCAL, id, 0), \ - SR_ARR_INIT(AUXP_IMPCAL, id, 0), \ - SR_ARR_INIT(AUX_RESET_MASK, id, DP_AUX0_AUX_CONTROL__AUX_RESET_MASK), \ - SR_ARR_INIT(AUX_RESET_MASK, id, DP_AUX0_AUX_CONTROL__AUX_RESET_MASK)\ - ) - -static struct dce110_aux_registers aux_engine_regs[5]; - -static const struct dce110_aux_registers_shift aux_shift = { - DCN_AUX_MASK_SH_LIST(__SHIFT) -}; - -static const struct dce110_aux_registers_mask aux_mask = { - DCN_AUX_MASK_SH_LIST(_MASK) -}; - -#define dwbc_regs_dcn3_init(id)\ - DWBC_COMMON_REG_LIST_DCN30_RI(id) - -static struct dcn30_dwbc_registers dwbc30_regs[1]; - -static const struct dcn30_dwbc_shift dwbc30_shift = { - DWBC_COMMON_MASK_SH_LIST_DCN30(__SHIFT) -}; - -static const struct dcn30_dwbc_mask dwbc30_mask = { - DWBC_COMMON_MASK_SH_LIST_DCN30(_MASK) -}; - -#define mcif_wb_regs_dcn3_init(id)\ - MCIF_WB_COMMON_REG_LIST_DCN32_RI(id) - -static struct dcn30_mmhubbub_registers mcif_wb30_regs[1]; - -static const struct dcn30_mmhubbub_shift mcif_wb30_shift = { - MCIF_WB_COMMON_MASK_SH_LIST_DCN32(__SHIFT) -}; - -static const struct dcn30_mmhubbub_mask mcif_wb30_mask = { - MCIF_WB_COMMON_MASK_SH_LIST_DCN32(_MASK) -}; - -#define dsc_regsDCN20_init(id)\ - DSC_REG_LIST_DCN20_RI(id) - -static struct dcn20_dsc_registers dsc_regs[4]; - -static const struct dcn20_dsc_shift dsc_shift = { - DSC_REG_LIST_SH_MASK_DCN20(__SHIFT) -}; - -static const struct dcn20_dsc_mask dsc_mask = { - DSC_REG_LIST_SH_MASK_DCN20(_MASK) -}; - -static struct dcn30_mpc_registers mpc_regs; - -#define dcn_mpc_regs_init() \ - MPC_REG_LIST_DCN3_2_RI(0),\ - MPC_REG_LIST_DCN3_2_RI(1),\ - MPC_REG_LIST_DCN3_2_RI(2),\ - MPC_REG_LIST_DCN3_2_RI(3),\ - MPC_OUT_MUX_REG_LIST_DCN3_0_RI(0),\ - MPC_OUT_MUX_REG_LIST_DCN3_0_RI(1),\ - MPC_OUT_MUX_REG_LIST_DCN3_0_RI(2),\ - MPC_OUT_MUX_REG_LIST_DCN3_0_RI(3),\ - MPC_DWB_MUX_REG_LIST_DCN3_0_RI(0) - -static const struct dcn30_mpc_shift mpc_shift = { - MPC_COMMON_MASK_SH_LIST_DCN32(__SHIFT) -}; - -static const struct dcn30_mpc_mask mpc_mask = { - MPC_COMMON_MASK_SH_LIST_DCN32(_MASK) -}; - -#define optc_regs_init(id)\ - OPTC_COMMON_REG_LIST_DCN3_2_RI(id) - -static struct dcn_optc_registers optc_regs[4]; - -static const struct dcn_optc_shift optc_shift = { - OPTC_COMMON_MASK_SH_LIST_DCN3_2(__SHIFT) -}; - -static const struct dcn_optc_mask optc_mask = { - OPTC_COMMON_MASK_SH_LIST_DCN3_2(_MASK) -}; - -#define hubp_regs_init(id)\ - HUBP_REG_LIST_DCN32_RI(id) - -static struct dcn_hubp2_registers hubp_regs[4]; - - -static const struct dcn_hubp2_shift hubp_shift = { - HUBP_MASK_SH_LIST_DCN32(__SHIFT) -}; - -static const struct dcn_hubp2_mask hubp_mask = { - HUBP_MASK_SH_LIST_DCN32(_MASK) -}; - -static struct dcn_hubbub_registers hubbub_reg; -#define hubbub_reg_init()\ - HUBBUB_REG_LIST_DCN32_RI(0) - -static const struct dcn_hubbub_shift hubbub_shift = { - HUBBUB_MASK_SH_LIST_DCN32(__SHIFT) -}; - -static const struct dcn_hubbub_mask hubbub_mask = { - HUBBUB_MASK_SH_LIST_DCN32(_MASK) -}; - -static struct dccg_registers dccg_regs; - -#define dccg_regs_init()\ - DCCG_REG_LIST_DCN32_RI() - -static const struct dccg_shift dccg_shift = { - DCCG_MASK_SH_LIST_DCN32(__SHIFT) -}; - -static const struct dccg_mask dccg_mask = { - DCCG_MASK_SH_LIST_DCN32(_MASK) -}; - - -#define SRII2(reg_name_pre, reg_name_post, id)\ - .reg_name_pre ## _ ## reg_name_post[id] = BASE(reg ## reg_name_pre \ - ## id ## _ ## reg_name_post ## _BASE_IDX) + \ - reg ## reg_name_pre ## id ## _ ## reg_name_post - - -#define HWSEQ_DCN32_REG_LIST()\ - SR(DCHUBBUB_GLOBAL_TIMER_CNTL), \ - SR(DIO_MEM_PWR_CTRL), \ - SR(ODM_MEM_PWR_CTRL3), \ - SR(MMHUBBUB_MEM_PWR_CNTL), \ - SR(DCCG_GATE_DISABLE_CNTL), \ - SR(DCCG_GATE_DISABLE_CNTL2), \ - SR(DCFCLK_CNTL),\ - SR(DC_MEM_GLOBAL_PWR_REQ_CNTL), \ - SRII(PIXEL_RATE_CNTL, OTG, 0), \ - SRII(PIXEL_RATE_CNTL, OTG, 1),\ - SRII(PIXEL_RATE_CNTL, OTG, 2),\ - SRII(PIXEL_RATE_CNTL, OTG, 3),\ - SRII(PHYPLL_PIXEL_RATE_CNTL, OTG, 0),\ - SRII(PHYPLL_PIXEL_RATE_CNTL, OTG, 1),\ - SRII(PHYPLL_PIXEL_RATE_CNTL, OTG, 2),\ - SRII(PHYPLL_PIXEL_RATE_CNTL, OTG, 3),\ - SR(MICROSECOND_TIME_BASE_DIV), \ - SR(MILLISECOND_TIME_BASE_DIV), \ - SR(DISPCLK_FREQ_CHANGE_CNTL), \ - SR(RBBMIF_TIMEOUT_DIS), \ - SR(RBBMIF_TIMEOUT_DIS_2), \ - SR(DCHUBBUB_CRC_CTRL), \ - SR(DPP_TOP0_DPP_CRC_CTRL), \ - SR(DPP_TOP0_DPP_CRC_VAL_B_A), \ - SR(DPP_TOP0_DPP_CRC_VAL_R_G), \ - SR(MPC_CRC_CTRL), \ - SR(MPC_CRC_RESULT_GB), \ - SR(MPC_CRC_RESULT_C), \ - SR(MPC_CRC_RESULT_AR), \ - SR(DOMAIN0_PG_CONFIG), \ - SR(DOMAIN1_PG_CONFIG), \ - SR(DOMAIN2_PG_CONFIG), \ - SR(DOMAIN3_PG_CONFIG), \ - SR(DOMAIN16_PG_CONFIG), \ - SR(DOMAIN17_PG_CONFIG), \ - SR(DOMAIN18_PG_CONFIG), \ - SR(DOMAIN19_PG_CONFIG), \ - SR(DOMAIN0_PG_STATUS), \ - SR(DOMAIN1_PG_STATUS), \ - SR(DOMAIN2_PG_STATUS), \ - SR(DOMAIN3_PG_STATUS), \ - SR(DOMAIN16_PG_STATUS), \ - SR(DOMAIN17_PG_STATUS), \ - SR(DOMAIN18_PG_STATUS), \ - SR(DOMAIN19_PG_STATUS), \ - SR(D1VGA_CONTROL), \ - SR(D2VGA_CONTROL), \ - SR(D3VGA_CONTROL), \ - SR(D4VGA_CONTROL), \ - SR(D5VGA_CONTROL), \ - SR(D6VGA_CONTROL), \ - SR(DC_IP_REQUEST_CNTL), \ - SR(AZALIA_AUDIO_DTO), \ - SR(AZALIA_CONTROLLER_CLOCK_GATING) - -static struct dce_hwseq_registers hwseq_reg; - -#define hwseq_reg_init()\ - HWSEQ_DCN32_REG_LIST() - -#define HWSEQ_DCN32_MASK_SH_LIST(mask_sh)\ - HWSEQ_DCN_MASK_SH_LIST(mask_sh), \ - HWS_SF(, DCHUBBUB_GLOBAL_TIMER_CNTL, DCHUBBUB_GLOBAL_TIMER_REFDIV, mask_sh), \ - HWS_SF(, DOMAIN0_PG_CONFIG, DOMAIN_POWER_FORCEON, mask_sh), \ - HWS_SF(, DOMAIN0_PG_CONFIG, DOMAIN_POWER_GATE, mask_sh), \ - HWS_SF(, DOMAIN1_PG_CONFIG, DOMAIN_POWER_FORCEON, mask_sh), \ - HWS_SF(, DOMAIN1_PG_CONFIG, DOMAIN_POWER_GATE, mask_sh), \ - HWS_SF(, DOMAIN2_PG_CONFIG, DOMAIN_POWER_FORCEON, mask_sh), \ - HWS_SF(, DOMAIN2_PG_CONFIG, DOMAIN_POWER_GATE, mask_sh), \ - HWS_SF(, DOMAIN3_PG_CONFIG, DOMAIN_POWER_FORCEON, mask_sh), \ - HWS_SF(, DOMAIN3_PG_CONFIG, DOMAIN_POWER_GATE, mask_sh), \ - HWS_SF(, DOMAIN16_PG_CONFIG, DOMAIN_POWER_FORCEON, mask_sh), \ - HWS_SF(, DOMAIN16_PG_CONFIG, DOMAIN_POWER_GATE, mask_sh), \ - HWS_SF(, DOMAIN17_PG_CONFIG, DOMAIN_POWER_FORCEON, mask_sh), \ - HWS_SF(, DOMAIN17_PG_CONFIG, DOMAIN_POWER_GATE, mask_sh), \ - HWS_SF(, DOMAIN18_PG_CONFIG, DOMAIN_POWER_FORCEON, mask_sh), \ - HWS_SF(, DOMAIN18_PG_CONFIG, DOMAIN_POWER_GATE, mask_sh), \ - HWS_SF(, DOMAIN19_PG_CONFIG, DOMAIN_POWER_FORCEON, mask_sh), \ - HWS_SF(, DOMAIN19_PG_CONFIG, DOMAIN_POWER_GATE, mask_sh), \ - HWS_SF(, DOMAIN0_PG_STATUS, DOMAIN_PGFSM_PWR_STATUS, mask_sh), \ - HWS_SF(, DOMAIN1_PG_STATUS, DOMAIN_PGFSM_PWR_STATUS, mask_sh), \ - HWS_SF(, DOMAIN2_PG_STATUS, DOMAIN_PGFSM_PWR_STATUS, mask_sh), \ - HWS_SF(, DOMAIN3_PG_STATUS, DOMAIN_PGFSM_PWR_STATUS, mask_sh), \ - HWS_SF(, DOMAIN16_PG_STATUS, DOMAIN_PGFSM_PWR_STATUS, mask_sh), \ - HWS_SF(, DOMAIN17_PG_STATUS, DOMAIN_PGFSM_PWR_STATUS, mask_sh), \ - HWS_SF(, DOMAIN18_PG_STATUS, DOMAIN_PGFSM_PWR_STATUS, mask_sh), \ - HWS_SF(, DOMAIN19_PG_STATUS, DOMAIN_PGFSM_PWR_STATUS, mask_sh), \ - HWS_SF(, DC_IP_REQUEST_CNTL, IP_REQUEST_EN, mask_sh), \ - HWS_SF(, AZALIA_AUDIO_DTO, AZALIA_AUDIO_DTO_MODULE, mask_sh), \ - HWS_SF(, HPO_TOP_CLOCK_CONTROL, HPO_HDMISTREAMCLK_G_GATE_DIS, mask_sh), \ - HWS_SF(, ODM_MEM_PWR_CTRL3, ODM_MEM_UNASSIGNED_PWR_MODE, mask_sh), \ - HWS_SF(, ODM_MEM_PWR_CTRL3, ODM_MEM_VBLANK_PWR_MODE, mask_sh), \ - HWS_SF(, MMHUBBUB_MEM_PWR_CNTL, VGA_MEM_PWR_FORCE, mask_sh) - -static const struct dce_hwseq_shift hwseq_shift = { - HWSEQ_DCN32_MASK_SH_LIST(__SHIFT) -}; - -static const struct dce_hwseq_mask hwseq_mask = { - HWSEQ_DCN32_MASK_SH_LIST(_MASK) -}; -#define vmid_regs_init(id)\ - DCN20_VMID_REG_LIST_RI(id) - -static struct dcn_vmid_registers vmid_regs[16]; - -static const struct dcn20_vmid_shift vmid_shifts = { - DCN20_VMID_MASK_SH_LIST(__SHIFT) -}; - -static const struct dcn20_vmid_mask vmid_masks = { - DCN20_VMID_MASK_SH_LIST(_MASK) -}; - -static const struct resource_caps res_cap_dcn32 = { - .num_timing_generator = 4, - .num_opp = 4, - .num_video_plane = 4, - .num_audio = 5, - .num_stream_encoder = 5, - .num_hpo_dp_stream_encoder = 4, - .num_hpo_dp_link_encoder = 2, - .num_pll = 5, - .num_dwb = 1, - .num_ddc = 5, - .num_vmid = 16, - .num_mpc_3dlut = 4, - .num_dsc = 4, -}; - -static const struct dc_plane_cap plane_cap = { - .type = DC_PLANE_TYPE_DCN_UNIVERSAL, - .per_pixel_alpha = true, - - .pixel_format_support = { - .argb8888 = true, - .nv12 = true, - .fp16 = true, - .p010 = true, - .ayuv = false, - }, - - .max_upscale_factor = { - .argb8888 = 16000, - .nv12 = 16000, - .fp16 = 16000 - }, - - // 6:1 downscaling ratio: 1000/6 = 166.666 - .max_downscale_factor = { - .argb8888 = 167, - .nv12 = 167, - .fp16 = 167 - }, - 64, - 64 -}; - -static const struct dc_debug_options debug_defaults_drv = { - .disable_dmcu = true, - .force_abm_enable = false, - .timing_trace = false, - .clock_trace = true, - .disable_pplib_clock_request = false, - .pipe_split_policy = MPC_SPLIT_AVOID, // Due to CRB, no need to MPC split anymore - .force_single_disp_pipe_split = false, - .disable_dcc = DCC_ENABLE, - .vsr_support = true, - .performance_trace = false, - .max_downscale_src_width = 7680,/*upto 8K*/ - .disable_pplib_wm_range = false, - .scl_reset_length10 = true, - .sanity_checks = false, - .underflow_assert_delay_us = 0xFFFFFFFF, - .dwb_fi_phase = -1, // -1 = disable, - .dmub_command_table = true, - .enable_mem_low_power = { - .bits = { - .vga = false, - .i2c = false, - .dmcu = false, // This is previously known to cause hang on S3 cycles if enabled - .dscl = false, - .cm = false, - .mpc = false, - .optc = true, - } - }, - .use_max_lb = true, - .force_disable_subvp = false, - .exit_idle_opt_for_cursor_updates = true, - .using_dml2 = false, - .enable_single_display_2to1_odm_policy = true, - - /* Must match enable_single_display_2to1_odm_policy to support dynamic ODM transitions*/ - .enable_double_buffered_dsc_pg_support = true, - .enable_dp_dig_pixel_rate_div_policy = 1, - .allow_sw_cursor_fallback = false, // Linux can't do SW cursor "fallback" - .alloc_extra_way_for_cursor = true, - .min_prefetch_in_strobe_ns = 60000, // 60us - .disable_unbounded_requesting = false, - .override_dispclk_programming = true, - .disable_fpo_optimizations = false, - .fpo_vactive_margin_us = 2000, // 2000us - .disable_fpo_vactive = false, - .disable_boot_optimizations = false, - .disable_subvp_high_refresh = false, - .disable_dp_plus_plus_wa = true, - .fpo_vactive_min_active_margin_us = 200, - .fpo_vactive_max_blank_us = 1000, - .enable_legacy_fast_update = false, -}; - -static struct dce_aux *dcn32_aux_engine_create( - struct dc_context *ctx, - uint32_t inst) -{ - struct aux_engine_dce110 *aux_engine = - kzalloc(sizeof(struct aux_engine_dce110), GFP_KERNEL); - - if (!aux_engine) - return NULL; - -#undef REG_STRUCT -#define REG_STRUCT aux_engine_regs - aux_engine_regs_init(0), - aux_engine_regs_init(1), - aux_engine_regs_init(2), - aux_engine_regs_init(3), - aux_engine_regs_init(4); - - dce110_aux_engine_construct(aux_engine, ctx, inst, - SW_AUX_TIMEOUT_PERIOD_MULTIPLIER * AUX_TIMEOUT_PERIOD, - &aux_engine_regs[inst], - &aux_mask, - &aux_shift, - ctx->dc->caps.extended_aux_timeout_support); - - return &aux_engine->base; -} -#define i2c_inst_regs_init(id)\ - I2C_HW_ENGINE_COMMON_REG_LIST_DCN30_RI(id) - -static struct dce_i2c_registers i2c_hw_regs[5]; - -static const struct dce_i2c_shift i2c_shifts = { - I2C_COMMON_MASK_SH_LIST_DCN30(__SHIFT) -}; - -static const struct dce_i2c_mask i2c_masks = { - I2C_COMMON_MASK_SH_LIST_DCN30(_MASK) -}; - -static struct dce_i2c_hw *dcn32_i2c_hw_create( - struct dc_context *ctx, - uint32_t inst) -{ - struct dce_i2c_hw *dce_i2c_hw = - kzalloc(sizeof(struct dce_i2c_hw), GFP_KERNEL); - - if (!dce_i2c_hw) - return NULL; - -#undef REG_STRUCT -#define REG_STRUCT i2c_hw_regs - i2c_inst_regs_init(1), - i2c_inst_regs_init(2), - i2c_inst_regs_init(3), - i2c_inst_regs_init(4), - i2c_inst_regs_init(5); - - dcn2_i2c_hw_construct(dce_i2c_hw, ctx, inst, - &i2c_hw_regs[inst], &i2c_shifts, &i2c_masks); - - return dce_i2c_hw; -} - -static struct clock_source *dcn32_clock_source_create( - struct dc_context *ctx, - struct dc_bios *bios, - enum clock_source_id id, - const struct dce110_clk_src_regs *regs, - bool dp_clk_src) -{ - struct dce110_clk_src *clk_src = - kzalloc(sizeof(struct dce110_clk_src), GFP_KERNEL); - - if (!clk_src) - return NULL; - - if (dcn31_clk_src_construct(clk_src, ctx, bios, id, - regs, &cs_shift, &cs_mask)) { - clk_src->base.dp_clk_src = dp_clk_src; - return &clk_src->base; - } - - kfree(clk_src); - BREAK_TO_DEBUGGER(); - return NULL; -} - -static struct hubbub *dcn32_hubbub_create(struct dc_context *ctx) -{ - int i; - - struct dcn20_hubbub *hubbub2 = kzalloc(sizeof(struct dcn20_hubbub), - GFP_KERNEL); - - if (!hubbub2) - return NULL; - -#undef REG_STRUCT -#define REG_STRUCT hubbub_reg - hubbub_reg_init(); - -#undef REG_STRUCT -#define REG_STRUCT vmid_regs - vmid_regs_init(0), - vmid_regs_init(1), - vmid_regs_init(2), - vmid_regs_init(3), - vmid_regs_init(4), - vmid_regs_init(5), - vmid_regs_init(6), - vmid_regs_init(7), - vmid_regs_init(8), - vmid_regs_init(9), - vmid_regs_init(10), - vmid_regs_init(11), - vmid_regs_init(12), - vmid_regs_init(13), - vmid_regs_init(14), - vmid_regs_init(15); - - hubbub32_construct(hubbub2, ctx, - &hubbub_reg, - &hubbub_shift, - &hubbub_mask, - ctx->dc->dml.ip.det_buffer_size_kbytes, - ctx->dc->dml.ip.pixel_chunk_size_kbytes, - ctx->dc->dml.ip.config_return_buffer_size_in_kbytes); - - - for (i = 0; i < res_cap_dcn32.num_vmid; i++) { - struct dcn20_vmid *vmid = &hubbub2->vmid[i]; - - vmid->ctx = ctx; - - vmid->regs = &vmid_regs[i]; - vmid->shifts = &vmid_shifts; - vmid->masks = &vmid_masks; - } - - return &hubbub2->base; -} - -static struct hubp *dcn32_hubp_create( - struct dc_context *ctx, - uint32_t inst) -{ - struct dcn20_hubp *hubp2 = - kzalloc(sizeof(struct dcn20_hubp), GFP_KERNEL); - - if (!hubp2) - return NULL; - -#undef REG_STRUCT -#define REG_STRUCT hubp_regs - hubp_regs_init(0), - hubp_regs_init(1), - hubp_regs_init(2), - hubp_regs_init(3); - - if (hubp32_construct(hubp2, ctx, inst, - &hubp_regs[inst], &hubp_shift, &hubp_mask)) - return &hubp2->base; - - BREAK_TO_DEBUGGER(); - kfree(hubp2); - return NULL; -} - -static void dcn32_dpp_destroy(struct dpp **dpp) -{ - kfree(TO_DCN30_DPP(*dpp)); - *dpp = NULL; -} - -static struct dpp *dcn32_dpp_create( - struct dc_context *ctx, - uint32_t inst) -{ - struct dcn3_dpp *dpp3 = - kzalloc(sizeof(struct dcn3_dpp), GFP_KERNEL); - - if (!dpp3) - return NULL; - -#undef REG_STRUCT -#define REG_STRUCT dpp_regs - dpp_regs_init(0), - dpp_regs_init(1), - dpp_regs_init(2), - dpp_regs_init(3); - - if (dpp32_construct(dpp3, ctx, inst, - &dpp_regs[inst], &tf_shift, &tf_mask)) - return &dpp3->base; - - BREAK_TO_DEBUGGER(); - kfree(dpp3); - return NULL; -} - -static struct mpc *dcn32_mpc_create( - struct dc_context *ctx, - int num_mpcc, - int num_rmu) -{ - struct dcn30_mpc *mpc30 = kzalloc(sizeof(struct dcn30_mpc), - GFP_KERNEL); - - if (!mpc30) - return NULL; - -#undef REG_STRUCT -#define REG_STRUCT mpc_regs - dcn_mpc_regs_init(); - - dcn32_mpc_construct(mpc30, ctx, - &mpc_regs, - &mpc_shift, - &mpc_mask, - num_mpcc, - num_rmu); - - return &mpc30->base; -} - -static struct output_pixel_processor *dcn32_opp_create( - struct dc_context *ctx, uint32_t inst) -{ - struct dcn20_opp *opp2 = - kzalloc(sizeof(struct dcn20_opp), GFP_KERNEL); - - if (!opp2) { - BREAK_TO_DEBUGGER(); - return NULL; - } - -#undef REG_STRUCT -#define REG_STRUCT opp_regs - opp_regs_init(0), - opp_regs_init(1), - opp_regs_init(2), - opp_regs_init(3); - - dcn20_opp_construct(opp2, ctx, inst, - &opp_regs[inst], &opp_shift, &opp_mask); - return &opp2->base; -} - - -static struct timing_generator *dcn32_timing_generator_create( - struct dc_context *ctx, - uint32_t instance) -{ - struct optc *tgn10 = - kzalloc(sizeof(struct optc), GFP_KERNEL); - - if (!tgn10) - return NULL; - -#undef REG_STRUCT -#define REG_STRUCT optc_regs - optc_regs_init(0), - optc_regs_init(1), - optc_regs_init(2), - optc_regs_init(3); - - tgn10->base.inst = instance; - tgn10->base.ctx = ctx; - - tgn10->tg_regs = &optc_regs[instance]; - tgn10->tg_shift = &optc_shift; - tgn10->tg_mask = &optc_mask; - - dcn32_timing_generator_init(tgn10); - - return &tgn10->base; -} - -static const struct encoder_feature_support link_enc_feature = { - .max_hdmi_deep_color = COLOR_DEPTH_121212, - .max_hdmi_pixel_clock = 600000, - .hdmi_ycbcr420_supported = true, - .dp_ycbcr420_supported = true, - .fec_supported = true, - .flags.bits.IS_HBR2_CAPABLE = true, - .flags.bits.IS_HBR3_CAPABLE = true, - .flags.bits.IS_TPS3_CAPABLE = true, - .flags.bits.IS_TPS4_CAPABLE = true -}; - -static struct link_encoder *dcn32_link_encoder_create( - struct dc_context *ctx, - const struct encoder_init_data *enc_init_data) -{ - struct dcn20_link_encoder *enc20 = - kzalloc(sizeof(struct dcn20_link_encoder), GFP_KERNEL); - - if (!enc20) - return NULL; - -#undef REG_STRUCT -#define REG_STRUCT link_enc_aux_regs - aux_regs_init(0), - aux_regs_init(1), - aux_regs_init(2), - aux_regs_init(3), - aux_regs_init(4); - -#undef REG_STRUCT -#define REG_STRUCT link_enc_hpd_regs - hpd_regs_init(0), - hpd_regs_init(1), - hpd_regs_init(2), - hpd_regs_init(3), - hpd_regs_init(4); - -#undef REG_STRUCT -#define REG_STRUCT link_enc_regs - link_regs_init(0, A), - link_regs_init(1, B), - link_regs_init(2, C), - link_regs_init(3, D), - link_regs_init(4, E); - - dcn32_link_encoder_construct(enc20, - enc_init_data, - &link_enc_feature, - &link_enc_regs[enc_init_data->transmitter], - &link_enc_aux_regs[enc_init_data->channel - 1], - &link_enc_hpd_regs[enc_init_data->hpd_source], - &le_shift, - &le_mask); - - return &enc20->enc10.base; -} - -struct panel_cntl *dcn32_panel_cntl_create(const struct panel_cntl_init_data *init_data) -{ - struct dcn31_panel_cntl *panel_cntl = - kzalloc(sizeof(struct dcn31_panel_cntl), GFP_KERNEL); - - if (!panel_cntl) - return NULL; - - dcn31_panel_cntl_construct(panel_cntl, init_data); - - return &panel_cntl->base; -} - -static void read_dce_straps( - struct dc_context *ctx, - struct resource_straps *straps) -{ - generic_reg_get(ctx, ctx->dcn_reg_offsets[regDC_PINSTRAPS_BASE_IDX] + regDC_PINSTRAPS, - FN(DC_PINSTRAPS, DC_PINSTRAPS_AUDIO), &straps->dc_pinstraps_audio); - -} - -static struct audio *dcn32_create_audio( - struct dc_context *ctx, unsigned int inst) -{ - -#undef REG_STRUCT -#define REG_STRUCT audio_regs - audio_regs_init(0), - audio_regs_init(1), - audio_regs_init(2), - audio_regs_init(3), - audio_regs_init(4); - - return dce_audio_create(ctx, inst, - &audio_regs[inst], &audio_shift, &audio_mask); -} - -static struct vpg *dcn32_vpg_create( - struct dc_context *ctx, - uint32_t inst) -{ - struct dcn30_vpg *vpg3 = kzalloc(sizeof(struct dcn30_vpg), GFP_KERNEL); - - if (!vpg3) - return NULL; - -#undef REG_STRUCT -#define REG_STRUCT vpg_regs - vpg_regs_init(0), - vpg_regs_init(1), - vpg_regs_init(2), - vpg_regs_init(3), - vpg_regs_init(4), - vpg_regs_init(5), - vpg_regs_init(6), - vpg_regs_init(7), - vpg_regs_init(8), - vpg_regs_init(9); - - vpg3_construct(vpg3, ctx, inst, - &vpg_regs[inst], - &vpg_shift, - &vpg_mask); - - return &vpg3->base; -} - -static struct afmt *dcn32_afmt_create( - struct dc_context *ctx, - uint32_t inst) -{ - struct dcn30_afmt *afmt3 = kzalloc(sizeof(struct dcn30_afmt), GFP_KERNEL); - - if (!afmt3) - return NULL; - -#undef REG_STRUCT -#define REG_STRUCT afmt_regs - afmt_regs_init(0), - afmt_regs_init(1), - afmt_regs_init(2), - afmt_regs_init(3), - afmt_regs_init(4), - afmt_regs_init(5); - - afmt3_construct(afmt3, ctx, inst, - &afmt_regs[inst], - &afmt_shift, - &afmt_mask); - - return &afmt3->base; -} - -static struct apg *dcn31_apg_create( - struct dc_context *ctx, - uint32_t inst) -{ - struct dcn31_apg *apg31 = kzalloc(sizeof(struct dcn31_apg), GFP_KERNEL); - - if (!apg31) - return NULL; - -#undef REG_STRUCT -#define REG_STRUCT apg_regs - apg_regs_init(0), - apg_regs_init(1), - apg_regs_init(2), - apg_regs_init(3); - - apg31_construct(apg31, ctx, inst, - &apg_regs[inst], - &apg_shift, - &apg_mask); - - return &apg31->base; -} - -static struct stream_encoder *dcn32_stream_encoder_create( - enum engine_id eng_id, - struct dc_context *ctx) -{ - struct dcn10_stream_encoder *enc1; - struct vpg *vpg; - struct afmt *afmt; - int vpg_inst; - int afmt_inst; - - /* Mapping of VPG, AFMT, DME register blocks to DIO block instance */ - if (eng_id <= ENGINE_ID_DIGF) { - vpg_inst = eng_id; - afmt_inst = eng_id; - } else - return NULL; - - enc1 = kzalloc(sizeof(struct dcn10_stream_encoder), GFP_KERNEL); - vpg = dcn32_vpg_create(ctx, vpg_inst); - afmt = dcn32_afmt_create(ctx, afmt_inst); - - if (!enc1 || !vpg || !afmt) { - kfree(enc1); - kfree(vpg); - kfree(afmt); - return NULL; - } - -#undef REG_STRUCT -#define REG_STRUCT stream_enc_regs - stream_enc_regs_init(0), - stream_enc_regs_init(1), - stream_enc_regs_init(2), - stream_enc_regs_init(3), - stream_enc_regs_init(4); - - dcn32_dio_stream_encoder_construct(enc1, ctx, ctx->dc_bios, - eng_id, vpg, afmt, - &stream_enc_regs[eng_id], - &se_shift, &se_mask); - - return &enc1->base; -} - -static struct hpo_dp_stream_encoder *dcn32_hpo_dp_stream_encoder_create( - enum engine_id eng_id, - struct dc_context *ctx) -{ - struct dcn31_hpo_dp_stream_encoder *hpo_dp_enc31; - struct vpg *vpg; - struct apg *apg; - uint32_t hpo_dp_inst; - uint32_t vpg_inst; - uint32_t apg_inst; - - ASSERT((eng_id >= ENGINE_ID_HPO_DP_0) && (eng_id <= ENGINE_ID_HPO_DP_3)); - hpo_dp_inst = eng_id - ENGINE_ID_HPO_DP_0; - - /* Mapping of VPG register blocks to HPO DP block instance: - * VPG[6] -> HPO_DP[0] - * VPG[7] -> HPO_DP[1] - * VPG[8] -> HPO_DP[2] - * VPG[9] -> HPO_DP[3] - */ - vpg_inst = hpo_dp_inst + 6; - - /* Mapping of APG register blocks to HPO DP block instance: - * APG[0] -> HPO_DP[0] - * APG[1] -> HPO_DP[1] - * APG[2] -> HPO_DP[2] - * APG[3] -> HPO_DP[3] - */ - apg_inst = hpo_dp_inst; - - /* allocate HPO stream encoder and create VPG sub-block */ - hpo_dp_enc31 = kzalloc(sizeof(struct dcn31_hpo_dp_stream_encoder), GFP_KERNEL); - vpg = dcn32_vpg_create(ctx, vpg_inst); - apg = dcn31_apg_create(ctx, apg_inst); - - if (!hpo_dp_enc31 || !vpg || !apg) { - kfree(hpo_dp_enc31); - kfree(vpg); - kfree(apg); - return NULL; - } - -#undef REG_STRUCT -#define REG_STRUCT hpo_dp_stream_enc_regs - hpo_dp_stream_encoder_reg_init(0), - hpo_dp_stream_encoder_reg_init(1), - hpo_dp_stream_encoder_reg_init(2), - hpo_dp_stream_encoder_reg_init(3); - - dcn31_hpo_dp_stream_encoder_construct(hpo_dp_enc31, ctx, ctx->dc_bios, - hpo_dp_inst, eng_id, vpg, apg, - &hpo_dp_stream_enc_regs[hpo_dp_inst], - &hpo_dp_se_shift, &hpo_dp_se_mask); - - return &hpo_dp_enc31->base; -} - -static struct hpo_dp_link_encoder *dcn32_hpo_dp_link_encoder_create( - uint8_t inst, - struct dc_context *ctx) -{ - struct dcn31_hpo_dp_link_encoder *hpo_dp_enc31; - - /* allocate HPO link encoder */ - hpo_dp_enc31 = kzalloc(sizeof(struct dcn31_hpo_dp_link_encoder), GFP_KERNEL); - -#undef REG_STRUCT -#define REG_STRUCT hpo_dp_link_enc_regs - hpo_dp_link_encoder_reg_init(0), - hpo_dp_link_encoder_reg_init(1); - - hpo_dp_link_encoder32_construct(hpo_dp_enc31, ctx, inst, - &hpo_dp_link_enc_regs[inst], - &hpo_dp_le_shift, &hpo_dp_le_mask); - - return &hpo_dp_enc31->base; -} - -static struct dce_hwseq *dcn32_hwseq_create( - struct dc_context *ctx) -{ - struct dce_hwseq *hws = kzalloc(sizeof(struct dce_hwseq), GFP_KERNEL); - -#undef REG_STRUCT -#define REG_STRUCT hwseq_reg - hwseq_reg_init(); - - if (hws) { - hws->ctx = ctx; - hws->regs = &hwseq_reg; - hws->shifts = &hwseq_shift; - hws->masks = &hwseq_mask; - } - return hws; -} -static const struct resource_create_funcs res_create_funcs = { - .read_dce_straps = read_dce_straps, - .create_audio = dcn32_create_audio, - .create_stream_encoder = dcn32_stream_encoder_create, - .create_hpo_dp_stream_encoder = dcn32_hpo_dp_stream_encoder_create, - .create_hpo_dp_link_encoder = dcn32_hpo_dp_link_encoder_create, - .create_hwseq = dcn32_hwseq_create, -}; - -static void dcn32_resource_destruct(struct dcn32_resource_pool *pool) -{ - unsigned int i; - - for (i = 0; i < pool->base.stream_enc_count; i++) { - if (pool->base.stream_enc[i] != NULL) { - if (pool->base.stream_enc[i]->vpg != NULL) { - kfree(DCN30_VPG_FROM_VPG(pool->base.stream_enc[i]->vpg)); - pool->base.stream_enc[i]->vpg = NULL; - } - if (pool->base.stream_enc[i]->afmt != NULL) { - kfree(DCN30_AFMT_FROM_AFMT(pool->base.stream_enc[i]->afmt)); - pool->base.stream_enc[i]->afmt = NULL; - } - kfree(DCN10STRENC_FROM_STRENC(pool->base.stream_enc[i])); - pool->base.stream_enc[i] = NULL; - } - } - - for (i = 0; i < pool->base.hpo_dp_stream_enc_count; i++) { - if (pool->base.hpo_dp_stream_enc[i] != NULL) { - if (pool->base.hpo_dp_stream_enc[i]->vpg != NULL) { - kfree(DCN30_VPG_FROM_VPG(pool->base.hpo_dp_stream_enc[i]->vpg)); - pool->base.hpo_dp_stream_enc[i]->vpg = NULL; - } - if (pool->base.hpo_dp_stream_enc[i]->apg != NULL) { - kfree(DCN31_APG_FROM_APG(pool->base.hpo_dp_stream_enc[i]->apg)); - pool->base.hpo_dp_stream_enc[i]->apg = NULL; - } - kfree(DCN3_1_HPO_DP_STREAM_ENC_FROM_HPO_STREAM_ENC(pool->base.hpo_dp_stream_enc[i])); - pool->base.hpo_dp_stream_enc[i] = NULL; - } - } - - for (i = 0; i < pool->base.hpo_dp_link_enc_count; i++) { - if (pool->base.hpo_dp_link_enc[i] != NULL) { - kfree(DCN3_1_HPO_DP_LINK_ENC_FROM_HPO_LINK_ENC(pool->base.hpo_dp_link_enc[i])); - pool->base.hpo_dp_link_enc[i] = NULL; - } - } - - for (i = 0; i < pool->base.res_cap->num_dsc; i++) { - if (pool->base.dscs[i] != NULL) - dcn20_dsc_destroy(&pool->base.dscs[i]); - } - - if (pool->base.mpc != NULL) { - kfree(TO_DCN20_MPC(pool->base.mpc)); - pool->base.mpc = NULL; - } - if (pool->base.hubbub != NULL) { - kfree(TO_DCN20_HUBBUB(pool->base.hubbub)); - pool->base.hubbub = NULL; - } - for (i = 0; i < pool->base.pipe_count; i++) { - if (pool->base.dpps[i] != NULL) - dcn32_dpp_destroy(&pool->base.dpps[i]); - - if (pool->base.ipps[i] != NULL) - pool->base.ipps[i]->funcs->ipp_destroy(&pool->base.ipps[i]); - - if (pool->base.hubps[i] != NULL) { - kfree(TO_DCN20_HUBP(pool->base.hubps[i])); - pool->base.hubps[i] = NULL; - } - - if (pool->base.irqs != NULL) { - dal_irq_service_destroy(&pool->base.irqs); - } - } - - for (i = 0; i < pool->base.res_cap->num_ddc; i++) { - if (pool->base.engines[i] != NULL) - dce110_engine_destroy(&pool->base.engines[i]); - if (pool->base.hw_i2cs[i] != NULL) { - kfree(pool->base.hw_i2cs[i]); - pool->base.hw_i2cs[i] = NULL; - } - if (pool->base.sw_i2cs[i] != NULL) { - kfree(pool->base.sw_i2cs[i]); - pool->base.sw_i2cs[i] = NULL; - } - } - - for (i = 0; i < pool->base.res_cap->num_opp; i++) { - if (pool->base.opps[i] != NULL) - pool->base.opps[i]->funcs->opp_destroy(&pool->base.opps[i]); - } - - for (i = 0; i < pool->base.res_cap->num_timing_generator; i++) { - if (pool->base.timing_generators[i] != NULL) { - kfree(DCN10TG_FROM_TG(pool->base.timing_generators[i])); - pool->base.timing_generators[i] = NULL; - } - } - - for (i = 0; i < pool->base.res_cap->num_dwb; i++) { - if (pool->base.dwbc[i] != NULL) { - kfree(TO_DCN30_DWBC(pool->base.dwbc[i])); - pool->base.dwbc[i] = NULL; - } - if (pool->base.mcif_wb[i] != NULL) { - kfree(TO_DCN30_MMHUBBUB(pool->base.mcif_wb[i])); - pool->base.mcif_wb[i] = NULL; - } - } - - for (i = 0; i < pool->base.audio_count; i++) { - if (pool->base.audios[i]) - dce_aud_destroy(&pool->base.audios[i]); - } - - for (i = 0; i < pool->base.clk_src_count; i++) { - if (pool->base.clock_sources[i] != NULL) { - dcn20_clock_source_destroy(&pool->base.clock_sources[i]); - pool->base.clock_sources[i] = NULL; - } - } - - for (i = 0; i < pool->base.res_cap->num_mpc_3dlut; i++) { - if (pool->base.mpc_lut[i] != NULL) { - dc_3dlut_func_release(pool->base.mpc_lut[i]); - pool->base.mpc_lut[i] = NULL; - } - if (pool->base.mpc_shaper[i] != NULL) { - dc_transfer_func_release(pool->base.mpc_shaper[i]); - pool->base.mpc_shaper[i] = NULL; - } - } - - if (pool->base.dp_clock_source != NULL) { - dcn20_clock_source_destroy(&pool->base.dp_clock_source); - pool->base.dp_clock_source = NULL; - } - - for (i = 0; i < pool->base.res_cap->num_timing_generator; i++) { - if (pool->base.multiple_abms[i] != NULL) - dce_abm_destroy(&pool->base.multiple_abms[i]); - } - - if (pool->base.psr != NULL) - dmub_psr_destroy(&pool->base.psr); - - if (pool->base.dccg != NULL) - dcn_dccg_destroy(&pool->base.dccg); - - if (pool->base.oem_device != NULL) { - struct dc *dc = pool->base.oem_device->ctx->dc; - - dc->link_srv->destroy_ddc_service(&pool->base.oem_device); - } -} - - -static bool dcn32_dwbc_create(struct dc_context *ctx, struct resource_pool *pool) -{ - int i; - uint32_t dwb_count = pool->res_cap->num_dwb; - - for (i = 0; i < dwb_count; i++) { - struct dcn30_dwbc *dwbc30 = kzalloc(sizeof(struct dcn30_dwbc), - GFP_KERNEL); - - if (!dwbc30) { - dm_error("DC: failed to create dwbc30!\n"); - return false; - } - -#undef REG_STRUCT -#define REG_STRUCT dwbc30_regs - dwbc_regs_dcn3_init(0); - - dcn30_dwbc_construct(dwbc30, ctx, - &dwbc30_regs[i], - &dwbc30_shift, - &dwbc30_mask, - i); - - pool->dwbc[i] = &dwbc30->base; - } - return true; -} - -static bool dcn32_mmhubbub_create(struct dc_context *ctx, struct resource_pool *pool) -{ - int i; - uint32_t dwb_count = pool->res_cap->num_dwb; - - for (i = 0; i < dwb_count; i++) { - struct dcn30_mmhubbub *mcif_wb30 = kzalloc(sizeof(struct dcn30_mmhubbub), - GFP_KERNEL); - - if (!mcif_wb30) { - dm_error("DC: failed to create mcif_wb30!\n"); - return false; - } - -#undef REG_STRUCT -#define REG_STRUCT mcif_wb30_regs - mcif_wb_regs_dcn3_init(0); - - dcn32_mmhubbub_construct(mcif_wb30, ctx, - &mcif_wb30_regs[i], - &mcif_wb30_shift, - &mcif_wb30_mask, - i); - - pool->mcif_wb[i] = &mcif_wb30->base; - } - return true; -} - -static struct display_stream_compressor *dcn32_dsc_create( - struct dc_context *ctx, uint32_t inst) -{ - struct dcn20_dsc *dsc = - kzalloc(sizeof(struct dcn20_dsc), GFP_KERNEL); - - if (!dsc) { - BREAK_TO_DEBUGGER(); - return NULL; - } - -#undef REG_STRUCT -#define REG_STRUCT dsc_regs - dsc_regsDCN20_init(0), - dsc_regsDCN20_init(1), - dsc_regsDCN20_init(2), - dsc_regsDCN20_init(3); - - dsc2_construct(dsc, ctx, inst, &dsc_regs[inst], &dsc_shift, &dsc_mask); - - dsc->max_image_width = 6016; - - return &dsc->base; -} - -static void dcn32_destroy_resource_pool(struct resource_pool **pool) -{ - struct dcn32_resource_pool *dcn32_pool = TO_DCN32_RES_POOL(*pool); - - dcn32_resource_destruct(dcn32_pool); - kfree(dcn32_pool); - *pool = NULL; -} - -bool dcn32_acquire_post_bldn_3dlut( - struct resource_context *res_ctx, - const struct resource_pool *pool, - int mpcc_id, - struct dc_3dlut **lut, - struct dc_transfer_func **shaper) -{ - bool ret = false; - - ASSERT(*lut == NULL && *shaper == NULL); - *lut = NULL; - *shaper = NULL; - - if (!res_ctx->is_mpc_3dlut_acquired[mpcc_id]) { - *lut = pool->mpc_lut[mpcc_id]; - *shaper = pool->mpc_shaper[mpcc_id]; - res_ctx->is_mpc_3dlut_acquired[mpcc_id] = true; - ret = true; - } - return ret; -} - -bool dcn32_release_post_bldn_3dlut( - struct resource_context *res_ctx, - const struct resource_pool *pool, - struct dc_3dlut **lut, - struct dc_transfer_func **shaper) -{ - int i; - bool ret = false; - - for (i = 0; i < pool->res_cap->num_mpc_3dlut; i++) { - if (pool->mpc_lut[i] == *lut && pool->mpc_shaper[i] == *shaper) { - res_ctx->is_mpc_3dlut_acquired[i] = false; - pool->mpc_lut[i]->state.raw = 0; - *lut = NULL; - *shaper = NULL; - ret = true; - break; - } - } - return ret; -} - -static void dcn32_enable_phantom_plane(struct dc *dc, - struct dc_state *context, - struct dc_stream_state *phantom_stream, - unsigned int dc_pipe_idx) -{ - struct dc_plane_state *phantom_plane = NULL; - struct dc_plane_state *prev_phantom_plane = NULL; - struct pipe_ctx *curr_pipe = &context->res_ctx.pipe_ctx[dc_pipe_idx]; - - while (curr_pipe) { - if (curr_pipe->top_pipe && curr_pipe->top_pipe->plane_state == curr_pipe->plane_state) - phantom_plane = prev_phantom_plane; - else - phantom_plane = dc_create_plane_state(dc); - - memcpy(&phantom_plane->address, &curr_pipe->plane_state->address, sizeof(phantom_plane->address)); - memcpy(&phantom_plane->scaling_quality, &curr_pipe->plane_state->scaling_quality, - sizeof(phantom_plane->scaling_quality)); - memcpy(&phantom_plane->src_rect, &curr_pipe->plane_state->src_rect, sizeof(phantom_plane->src_rect)); - memcpy(&phantom_plane->dst_rect, &curr_pipe->plane_state->dst_rect, sizeof(phantom_plane->dst_rect)); - memcpy(&phantom_plane->clip_rect, &curr_pipe->plane_state->clip_rect, sizeof(phantom_plane->clip_rect)); - memcpy(&phantom_plane->plane_size, &curr_pipe->plane_state->plane_size, - sizeof(phantom_plane->plane_size)); - memcpy(&phantom_plane->tiling_info, &curr_pipe->plane_state->tiling_info, - sizeof(phantom_plane->tiling_info)); - memcpy(&phantom_plane->dcc, &curr_pipe->plane_state->dcc, sizeof(phantom_plane->dcc)); - phantom_plane->format = curr_pipe->plane_state->format; - phantom_plane->rotation = curr_pipe->plane_state->rotation; - phantom_plane->visible = curr_pipe->plane_state->visible; - - /* Shadow pipe has small viewport. */ - phantom_plane->clip_rect.y = 0; - phantom_plane->clip_rect.height = phantom_stream->src.height; - - phantom_plane->is_phantom = true; - - dc_add_plane_to_context(dc, phantom_stream, phantom_plane, context); - - curr_pipe = curr_pipe->bottom_pipe; - prev_phantom_plane = phantom_plane; - } -} - -static struct dc_stream_state *dcn32_enable_phantom_stream(struct dc *dc, - struct dc_state *context, - display_e2e_pipe_params_st *pipes, - unsigned int pipe_cnt, - unsigned int dc_pipe_idx) -{ - struct dc_stream_state *phantom_stream = NULL; - struct pipe_ctx *ref_pipe = &context->res_ctx.pipe_ctx[dc_pipe_idx]; - - phantom_stream = dc_create_stream_for_sink(ref_pipe->stream->sink); - phantom_stream->signal = SIGNAL_TYPE_VIRTUAL; - phantom_stream->dpms_off = true; - phantom_stream->mall_stream_config.type = SUBVP_PHANTOM; - phantom_stream->mall_stream_config.paired_stream = ref_pipe->stream; - ref_pipe->stream->mall_stream_config.type = SUBVP_MAIN; - ref_pipe->stream->mall_stream_config.paired_stream = phantom_stream; - - /* stream has limited viewport and small timing */ - memcpy(&phantom_stream->timing, &ref_pipe->stream->timing, sizeof(phantom_stream->timing)); - memcpy(&phantom_stream->src, &ref_pipe->stream->src, sizeof(phantom_stream->src)); - memcpy(&phantom_stream->dst, &ref_pipe->stream->dst, sizeof(phantom_stream->dst)); - DC_FP_START(); - dcn32_set_phantom_stream_timing(dc, context, ref_pipe, phantom_stream, pipes, pipe_cnt, dc_pipe_idx); - DC_FP_END(); - - dc_add_stream_to_ctx(dc, context, phantom_stream); - return phantom_stream; -} - -void dcn32_retain_phantom_pipes(struct dc *dc, struct dc_state *context) -{ - int i; - struct dc_plane_state *phantom_plane = NULL; - struct dc_stream_state *phantom_stream = NULL; - - for (i = 0; i < dc->res_pool->pipe_count; i++) { - struct pipe_ctx *pipe = &context->res_ctx.pipe_ctx[i]; - - if (resource_is_pipe_type(pipe, OTG_MASTER) && - resource_is_pipe_type(pipe, DPP_PIPE) && - pipe->stream->mall_stream_config.type == SUBVP_PHANTOM) { - phantom_plane = pipe->plane_state; - phantom_stream = pipe->stream; - - dc_plane_state_retain(phantom_plane); - dc_stream_retain(phantom_stream); - } - } -} - -// return true if removed piped from ctx, false otherwise -bool dcn32_remove_phantom_pipes(struct dc *dc, struct dc_state *context, bool fast_update) -{ - int i; - bool removed_pipe = false; - struct dc_plane_state *phantom_plane = NULL; - struct dc_stream_state *phantom_stream = NULL; - - for (i = 0; i < dc->res_pool->pipe_count; i++) { - struct pipe_ctx *pipe = &context->res_ctx.pipe_ctx[i]; - // build scaling params for phantom pipes - if (pipe->plane_state && pipe->stream && pipe->stream->mall_stream_config.type == SUBVP_PHANTOM) { - phantom_plane = pipe->plane_state; - phantom_stream = pipe->stream; - - dc_rem_all_planes_for_stream(dc, pipe->stream, context); - dc_remove_stream_from_ctx(dc, context, pipe->stream); - - /* Ref count is incremented on allocation and also when added to the context. - * Therefore we must call release for the the phantom plane and stream once - * they are removed from the ctx to finally decrement the refcount to 0 to free. - */ - dc_plane_state_release(phantom_plane); - dc_stream_release(phantom_stream); - - removed_pipe = true; - } - - /* For non-full updates, a shallow copy of the current state - * is created. In this case we don't want to erase the current - * state (there can be 2 HIRQL threads, one in flip, and one in - * checkMPO) that can cause a race condition. - * - * This is just a workaround, needs a proper fix. - */ - if (!fast_update) { - // Clear all phantom stream info - if (pipe->stream) { - pipe->stream->mall_stream_config.type = SUBVP_NONE; - pipe->stream->mall_stream_config.paired_stream = NULL; - } - - if (pipe->plane_state) { - pipe->plane_state->is_phantom = false; - } - } - } - return removed_pipe; -} - -/* TODO: Input to this function should indicate which pipe indexes (or streams) - * require a phantom pipe / stream - */ -void dcn32_add_phantom_pipes(struct dc *dc, struct dc_state *context, - display_e2e_pipe_params_st *pipes, - unsigned int pipe_cnt, - unsigned int index) -{ - struct dc_stream_state *phantom_stream = NULL; - unsigned int i; - - // The index of the DC pipe passed into this function is guarenteed to - // be a valid candidate for SubVP (i.e. has a plane, stream, doesn't - // already have phantom pipe assigned, etc.) by previous checks. - phantom_stream = dcn32_enable_phantom_stream(dc, context, pipes, pipe_cnt, index); - dcn32_enable_phantom_plane(dc, context, phantom_stream, index); - - for (i = 0; i < dc->res_pool->pipe_count; i++) { - struct pipe_ctx *pipe = &context->res_ctx.pipe_ctx[i]; - - // Build scaling params for phantom pipes which were newly added. - // We determine which phantom pipes were added by comparing with - // the phantom stream. - if (pipe->plane_state && pipe->stream && pipe->stream == phantom_stream && - pipe->stream->mall_stream_config.type == SUBVP_PHANTOM) { - pipe->stream->use_dynamic_meta = false; - pipe->plane_state->flip_immediate = false; - if (!resource_build_scaling_params(pipe)) { - // Log / remove phantom pipes since failed to build scaling params - } - } - } -} - -static bool dml1_validate(struct dc *dc, struct dc_state *context, bool fast_validate) -{ - bool out = false; - - BW_VAL_TRACE_SETUP(); - - int vlevel = 0; - int pipe_cnt = 0; - display_e2e_pipe_params_st *pipes = kzalloc(dc->res_pool->pipe_count * sizeof(display_e2e_pipe_params_st), GFP_KERNEL); - struct mall_temp_config mall_temp_config; - - /* To handle Freesync properly, setting FreeSync DML parameters - * to its default state for the first stage of validation - */ - context->bw_ctx.bw.dcn.clk.fw_based_mclk_switching = false; - context->bw_ctx.dml.soc.dram_clock_change_requirement_final = true; - - DC_LOGGER_INIT(dc->ctx->logger); - - /* For fast validation, there are situations where a shallow copy of - * of the dc->current_state is created for the validation. In this case - * we want to save and restore the mall config because we always - * teardown subvp at the beginning of validation (and don't attempt - * to add it back if it's fast validation). If we don't restore the - * subvp config in cases of fast validation + shallow copy of the - * dc->current_state, the dc->current_state will have a partially - * removed subvp state when we did not intend to remove it. - */ - if (fast_validate) { - memset(&mall_temp_config, 0, sizeof(mall_temp_config)); - dcn32_save_mall_state(dc, context, &mall_temp_config); - } - - BW_VAL_TRACE_COUNT(); - - DC_FP_START(); - out = dcn32_internal_validate_bw(dc, context, pipes, &pipe_cnt, &vlevel, fast_validate); - DC_FP_END(); - - if (fast_validate) - dcn32_restore_mall_state(dc, context, &mall_temp_config); - - if (pipe_cnt == 0) - goto validate_out; - - if (!out) - goto validate_fail; - - BW_VAL_TRACE_END_VOLTAGE_LEVEL(); - - if (fast_validate) { - BW_VAL_TRACE_SKIP(fast); - goto validate_out; - } - - dc->res_pool->funcs->calculate_wm_and_dlg(dc, context, pipes, pipe_cnt, vlevel); - - dcn32_override_min_req_memclk(dc, context); - - BW_VAL_TRACE_END_WATERMARKS(); - - goto validate_out; - -validate_fail: - DC_LOG_WARNING("Mode Validation Warning: %s failed validation.\n", - dml_get_status_message(context->bw_ctx.dml.vba.ValidationStatus[context->bw_ctx.dml.vba.soc.num_states])); - - BW_VAL_TRACE_SKIP(fail); - out = false; - -validate_out: - kfree(pipes); - - BW_VAL_TRACE_FINISH(); - - return out; -} - -bool dcn32_validate_bandwidth(struct dc *dc, - struct dc_state *context, - bool fast_validate) -{ - bool out = false; - - if (dc->debug.using_dml2) - out = dml2_validate(dc, context, fast_validate); - else - out = dml1_validate(dc, context, fast_validate); - return out; -} - -int dcn32_populate_dml_pipes_from_context( - struct dc *dc, struct dc_state *context, - display_e2e_pipe_params_st *pipes, - bool fast_validate) -{ - int i, pipe_cnt; - struct resource_context *res_ctx = &context->res_ctx; - struct pipe_ctx *pipe = NULL; - bool subvp_in_use = false; - struct dc_crtc_timing *timing; - - dcn20_populate_dml_pipes_from_context(dc, context, pipes, fast_validate); - - for (i = 0, pipe_cnt = 0; i < dc->res_pool->pipe_count; i++) { - - if (!res_ctx->pipe_ctx[i].stream) - continue; - pipe = &res_ctx->pipe_ctx[i]; - timing = &pipe->stream->timing; - - pipes[pipe_cnt].pipe.src.gpuvm = true; - DC_FP_START(); - dcn32_zero_pipe_dcc_fraction(pipes, pipe_cnt); - DC_FP_END(); - pipes[pipe_cnt].pipe.dest.vfront_porch = timing->v_front_porch; - pipes[pipe_cnt].pipe.dest.odm_combine_policy = dm_odm_combine_policy_dal; - pipes[pipe_cnt].pipe.src.gpuvm_min_page_size_kbytes = 256; // according to spreadsheet - pipes[pipe_cnt].pipe.src.unbounded_req_mode = false; - pipes[pipe_cnt].pipe.scale_ratio_depth.lb_depth = dm_lb_19; - - /* Only populate DML input with subvp info for full updates. - * This is just a workaround -- needs a proper fix. - */ - if (!fast_validate) { - switch (pipe->stream->mall_stream_config.type) { - case SUBVP_MAIN: - pipes[pipe_cnt].pipe.src.use_mall_for_pstate_change = dm_use_mall_pstate_change_sub_viewport; - subvp_in_use = true; - break; - case SUBVP_PHANTOM: - pipes[pipe_cnt].pipe.src.use_mall_for_pstate_change = dm_use_mall_pstate_change_phantom_pipe; - pipes[pipe_cnt].pipe.src.use_mall_for_static_screen = dm_use_mall_static_screen_disable; - // Disallow unbounded req for SubVP according to DCHUB programming guide - pipes[pipe_cnt].pipe.src.unbounded_req_mode = false; - break; - case SUBVP_NONE: - pipes[pipe_cnt].pipe.src.use_mall_for_pstate_change = dm_use_mall_pstate_change_disable; - pipes[pipe_cnt].pipe.src.use_mall_for_static_screen = dm_use_mall_static_screen_disable; - break; - default: - break; - } - } - - pipes[pipe_cnt].dout.dsc_input_bpc = 0; - if (pipes[pipe_cnt].dout.dsc_enable) { - switch (timing->display_color_depth) { - case COLOR_DEPTH_888: - pipes[pipe_cnt].dout.dsc_input_bpc = 8; - break; - case COLOR_DEPTH_101010: - pipes[pipe_cnt].dout.dsc_input_bpc = 10; - break; - case COLOR_DEPTH_121212: - pipes[pipe_cnt].dout.dsc_input_bpc = 12; - break; - default: - ASSERT(0); - break; - } - } - - - pipe_cnt++; - } - - /* For DET allocation, we don't want to use DML policy (not optimal for utilizing all - * the DET available for each pipe). Use the DET override input to maintain our driver - * policy. - */ - dcn32_set_det_allocations(dc, context, pipes); - - // In general cases we want to keep the dram clock change requirement - // (prefer configs that support MCLK switch). Only override to false - // for SubVP - if (context->bw_ctx.bw.dcn.clk.fw_based_mclk_switching || subvp_in_use) - context->bw_ctx.dml.soc.dram_clock_change_requirement_final = false; - else - context->bw_ctx.dml.soc.dram_clock_change_requirement_final = true; - - return pipe_cnt; -} - -static struct dc_cap_funcs cap_funcs = { - .get_dcc_compression_cap = dcn20_get_dcc_compression_cap, - .get_subvp_en = dcn32_subvp_in_use, -}; - -void dcn32_calculate_wm_and_dlg(struct dc *dc, struct dc_state *context, - display_e2e_pipe_params_st *pipes, - int pipe_cnt, - int vlevel) -{ - DC_FP_START(); - dcn32_calculate_wm_and_dlg_fpu(dc, context, pipes, pipe_cnt, vlevel); - DC_FP_END(); -} - -static void dcn32_update_bw_bounding_box(struct dc *dc, struct clk_bw_params *bw_params) -{ - DC_FP_START(); - dcn32_update_bw_bounding_box_fpu(dc, bw_params); - DC_FP_END(); -} - -static struct resource_funcs dcn32_res_pool_funcs = { - .destroy = dcn32_destroy_resource_pool, - .link_enc_create = dcn32_link_encoder_create, - .link_enc_create_minimal = NULL, - .panel_cntl_create = dcn32_panel_cntl_create, - .validate_bandwidth = dcn32_validate_bandwidth, - .calculate_wm_and_dlg = dcn32_calculate_wm_and_dlg, - .populate_dml_pipes = dcn32_populate_dml_pipes_from_context, - .acquire_free_pipe_as_secondary_dpp_pipe = dcn32_acquire_free_pipe_as_secondary_dpp_pipe, - .acquire_free_pipe_as_secondary_opp_head = dcn32_acquire_free_pipe_as_secondary_opp_head, - .release_pipe = dcn20_release_pipe, - .add_stream_to_ctx = dcn30_add_stream_to_ctx, - .add_dsc_to_stream_resource = dcn20_add_dsc_to_stream_resource, - .remove_stream_from_ctx = dcn20_remove_stream_from_ctx, - .populate_dml_writeback_from_context = dcn30_populate_dml_writeback_from_context, - .set_mcif_arb_params = dcn30_set_mcif_arb_params, - .find_first_free_match_stream_enc_for_link = dcn10_find_first_free_match_stream_enc_for_link, - .acquire_post_bldn_3dlut = dcn32_acquire_post_bldn_3dlut, - .release_post_bldn_3dlut = dcn32_release_post_bldn_3dlut, - .update_bw_bounding_box = dcn32_update_bw_bounding_box, - .patch_unknown_plane_state = dcn20_patch_unknown_plane_state, - .update_soc_for_wm_a = dcn30_update_soc_for_wm_a, - .add_phantom_pipes = dcn32_add_phantom_pipes, - .remove_phantom_pipes = dcn32_remove_phantom_pipes, - .retain_phantom_pipes = dcn32_retain_phantom_pipes, - .save_mall_state = dcn32_save_mall_state, - .restore_mall_state = dcn32_restore_mall_state, -}; - -static uint32_t read_pipe_fuses(struct dc_context *ctx) -{ - uint32_t value = REG_READ(CC_DC_PIPE_DIS); - /* DCN32 support max 4 pipes */ - value = value & 0xf; - return value; -} - - -static bool dcn32_resource_construct( - uint8_t num_virtual_links, - struct dc *dc, - struct dcn32_resource_pool *pool) -{ - int i, j; - struct dc_context *ctx = dc->ctx; - struct irq_service_init_data init_data; - struct ddc_service_init_data ddc_init_data = {0}; - uint32_t pipe_fuses = 0; - uint32_t num_pipes = 4; - -#undef REG_STRUCT -#define REG_STRUCT bios_regs - bios_regs_init(); - -#undef REG_STRUCT -#define REG_STRUCT clk_src_regs - clk_src_regs_init(0, A), - clk_src_regs_init(1, B), - clk_src_regs_init(2, C), - clk_src_regs_init(3, D), - clk_src_regs_init(4, E); - -#undef REG_STRUCT -#define REG_STRUCT abm_regs - abm_regs_init(0), - abm_regs_init(1), - abm_regs_init(2), - abm_regs_init(3); - -#undef REG_STRUCT -#define REG_STRUCT dccg_regs - dccg_regs_init(); - - DC_FP_START(); - - ctx->dc_bios->regs = &bios_regs; - - pool->base.res_cap = &res_cap_dcn32; - /* max number of pipes for ASIC before checking for pipe fuses */ - num_pipes = pool->base.res_cap->num_timing_generator; - pipe_fuses = read_pipe_fuses(ctx); - - for (i = 0; i < pool->base.res_cap->num_timing_generator; i++) - if (pipe_fuses & 1 << i) - num_pipes--; - - if (pipe_fuses & 1) - ASSERT(0); //Unexpected - Pipe 0 should always be fully functional! - - if (pipe_fuses & CC_DC_PIPE_DIS__DC_FULL_DIS_MASK) - ASSERT(0); //Entire DCN is harvested! - - /* within dml lib, initial value is hard coded, if ASIC pipe is fused, the - * value will be changed, update max_num_dpp and max_num_otg for dml. - */ - dcn3_2_ip.max_num_dpp = num_pipes; - dcn3_2_ip.max_num_otg = num_pipes; - - pool->base.funcs = &dcn32_res_pool_funcs; - - /************************************************* - * Resource + asic cap harcoding * - *************************************************/ - pool->base.underlay_pipe_index = NO_UNDERLAY_PIPE; - pool->base.timing_generator_count = num_pipes; - pool->base.pipe_count = num_pipes; - pool->base.mpcc_count = num_pipes; - dc->caps.max_downscale_ratio = 600; - dc->caps.i2c_speed_in_khz = 100; - dc->caps.i2c_speed_in_khz_hdcp = 100; /*1.4 w/a applied by default*/ - /* TODO: Bring max_cursor_size back to 256 after subvp cursor corruption is fixed*/ - dc->caps.max_cursor_size = 64; - dc->caps.min_horizontal_blanking_period = 80; - dc->caps.dmdata_alloc_size = 2048; - dc->caps.mall_size_per_mem_channel = 4; - dc->caps.mall_size_total = 0; - dc->caps.cursor_cache_size = dc->caps.max_cursor_size * dc->caps.max_cursor_size * 8; - - dc->caps.cache_line_size = 64; - dc->caps.cache_num_ways = 16; - - /* Calculate the available MALL space */ - dc->caps.max_cab_allocation_bytes = dcn32_calc_num_avail_chans_for_mall( - dc, dc->ctx->dc_bios->vram_info.num_chans) * - dc->caps.mall_size_per_mem_channel * 1024 * 1024; - dc->caps.mall_size_total = dc->caps.max_cab_allocation_bytes; - - dc->caps.subvp_fw_processing_delay_us = 15; - dc->caps.subvp_drr_max_vblank_margin_us = 40; - dc->caps.subvp_prefetch_end_to_mall_start_us = 15; - dc->caps.subvp_swath_height_margin_lines = 16; - dc->caps.subvp_pstate_allow_width_us = 20; - dc->caps.subvp_vertical_int_margin_us = 30; - dc->caps.subvp_drr_vblank_start_margin_us = 100; // 100us margin - - dc->caps.max_slave_planes = 2; - dc->caps.max_slave_yuv_planes = 2; - dc->caps.max_slave_rgb_planes = 2; - dc->caps.post_blend_color_processing = true; - dc->caps.force_dp_tps4_for_cp2520 = true; - if (dc->config.forceHBR2CP2520) - dc->caps.force_dp_tps4_for_cp2520 = false; - dc->caps.dp_hpo = true; - dc->caps.dp_hdmi21_pcon_support = true; - dc->caps.edp_dsc_support = true; - dc->caps.extended_aux_timeout_support = true; - dc->caps.dmcub_support = true; - dc->caps.seamless_odm = true; - dc->caps.max_v_total = (1 << 15) - 1; - - /* Color pipeline capabilities */ - dc->caps.color.dpp.dcn_arch = 1; - dc->caps.color.dpp.input_lut_shared = 0; - dc->caps.color.dpp.icsc = 1; - dc->caps.color.dpp.dgam_ram = 0; // must use gamma_corr - dc->caps.color.dpp.dgam_rom_caps.srgb = 1; - dc->caps.color.dpp.dgam_rom_caps.bt2020 = 1; - dc->caps.color.dpp.dgam_rom_caps.gamma2_2 = 1; - dc->caps.color.dpp.dgam_rom_caps.pq = 1; - dc->caps.color.dpp.dgam_rom_caps.hlg = 1; - dc->caps.color.dpp.post_csc = 1; - dc->caps.color.dpp.gamma_corr = 1; - dc->caps.color.dpp.dgam_rom_for_yuv = 0; - - dc->caps.color.dpp.hw_3d_lut = 1; - dc->caps.color.dpp.ogam_ram = 0; // no OGAM in DPP since DCN1 - // no OGAM ROM on DCN2 and later ASICs - dc->caps.color.dpp.ogam_rom_caps.srgb = 0; - dc->caps.color.dpp.ogam_rom_caps.bt2020 = 0; - dc->caps.color.dpp.ogam_rom_caps.gamma2_2 = 0; - dc->caps.color.dpp.ogam_rom_caps.pq = 0; - dc->caps.color.dpp.ogam_rom_caps.hlg = 0; - dc->caps.color.dpp.ocsc = 0; - - dc->caps.color.mpc.gamut_remap = 1; - dc->caps.color.mpc.num_3dluts = pool->base.res_cap->num_mpc_3dlut; //4, configurable to be before or after BLND in MPCC - dc->caps.color.mpc.ogam_ram = 1; - dc->caps.color.mpc.ogam_rom_caps.srgb = 0; - dc->caps.color.mpc.ogam_rom_caps.bt2020 = 0; - dc->caps.color.mpc.ogam_rom_caps.gamma2_2 = 0; - dc->caps.color.mpc.ogam_rom_caps.pq = 0; - dc->caps.color.mpc.ogam_rom_caps.hlg = 0; - dc->caps.color.mpc.ocsc = 1; - - /* Use pipe context based otg sync logic */ - dc->config.use_pipe_ctx_sync_logic = true; - - dc->config.dc_mode_clk_limit_support = true; - /* read VBIOS LTTPR caps */ - { - if (ctx->dc_bios->funcs->get_lttpr_caps) { - enum bp_result bp_query_result; - uint8_t is_vbios_lttpr_enable = 0; - - bp_query_result = ctx->dc_bios->funcs->get_lttpr_caps(ctx->dc_bios, &is_vbios_lttpr_enable); - dc->caps.vbios_lttpr_enable = (bp_query_result == BP_RESULT_OK) && !!is_vbios_lttpr_enable; - } - - /* interop bit is implicit */ - { - dc->caps.vbios_lttpr_aware = true; - } - } - - if (dc->ctx->dce_environment == DCE_ENV_PRODUCTION_DRV) - dc->debug = debug_defaults_drv; - - // Init the vm_helper - if (dc->vm_helper) - vm_helper_init(dc->vm_helper, 16); - - /************************************************* - * Create resources * - *************************************************/ - - /* Clock Sources for Pixel Clock*/ - pool->base.clock_sources[DCN32_CLK_SRC_PLL0] = - dcn32_clock_source_create(ctx, ctx->dc_bios, - CLOCK_SOURCE_COMBO_PHY_PLL0, - &clk_src_regs[0], false); - pool->base.clock_sources[DCN32_CLK_SRC_PLL1] = - dcn32_clock_source_create(ctx, ctx->dc_bios, - CLOCK_SOURCE_COMBO_PHY_PLL1, - &clk_src_regs[1], false); - pool->base.clock_sources[DCN32_CLK_SRC_PLL2] = - dcn32_clock_source_create(ctx, ctx->dc_bios, - CLOCK_SOURCE_COMBO_PHY_PLL2, - &clk_src_regs[2], false); - pool->base.clock_sources[DCN32_CLK_SRC_PLL3] = - dcn32_clock_source_create(ctx, ctx->dc_bios, - CLOCK_SOURCE_COMBO_PHY_PLL3, - &clk_src_regs[3], false); - pool->base.clock_sources[DCN32_CLK_SRC_PLL4] = - dcn32_clock_source_create(ctx, ctx->dc_bios, - CLOCK_SOURCE_COMBO_PHY_PLL4, - &clk_src_regs[4], false); - - pool->base.clk_src_count = DCN32_CLK_SRC_TOTAL; - - /* todo: not reuse phy_pll registers */ - pool->base.dp_clock_source = - dcn32_clock_source_create(ctx, ctx->dc_bios, - CLOCK_SOURCE_ID_DP_DTO, - &clk_src_regs[0], true); - - for (i = 0; i < pool->base.clk_src_count; i++) { - if (pool->base.clock_sources[i] == NULL) { - dm_error("DC: failed to create clock sources!\n"); - BREAK_TO_DEBUGGER(); - goto create_fail; - } - } - - /* DCCG */ - pool->base.dccg = dccg32_create(ctx, &dccg_regs, &dccg_shift, &dccg_mask); - if (pool->base.dccg == NULL) { - dm_error("DC: failed to create dccg!\n"); - BREAK_TO_DEBUGGER(); - goto create_fail; - } - - /* DML */ - dml_init_instance(&dc->dml, &dcn3_2_soc, &dcn3_2_ip, DML_PROJECT_DCN32); - - /* IRQ Service */ - init_data.ctx = dc->ctx; - pool->base.irqs = dal_irq_service_dcn32_create(&init_data); - if (!pool->base.irqs) - goto create_fail; - - /* HUBBUB */ - pool->base.hubbub = dcn32_hubbub_create(ctx); - if (pool->base.hubbub == NULL) { - BREAK_TO_DEBUGGER(); - dm_error("DC: failed to create hubbub!\n"); - goto create_fail; - } - - /* HUBPs, DPPs, OPPs, TGs, ABMs */ - for (i = 0, j = 0; i < pool->base.res_cap->num_timing_generator; i++) { - - /* if pipe is disabled, skip instance of HW pipe, - * i.e, skip ASIC register instance - */ - if (pipe_fuses & 1 << i) - continue; - - /* HUBPs */ - pool->base.hubps[j] = dcn32_hubp_create(ctx, i); - if (pool->base.hubps[j] == NULL) { - BREAK_TO_DEBUGGER(); - dm_error( - "DC: failed to create hubps!\n"); - goto create_fail; - } - - /* DPPs */ - pool->base.dpps[j] = dcn32_dpp_create(ctx, i); - if (pool->base.dpps[j] == NULL) { - BREAK_TO_DEBUGGER(); - dm_error( - "DC: failed to create dpps!\n"); - goto create_fail; - } - - /* OPPs */ - pool->base.opps[j] = dcn32_opp_create(ctx, i); - if (pool->base.opps[j] == NULL) { - BREAK_TO_DEBUGGER(); - dm_error( - "DC: failed to create output pixel processor!\n"); - goto create_fail; - } - - /* TGs */ - pool->base.timing_generators[j] = dcn32_timing_generator_create( - ctx, i); - if (pool->base.timing_generators[j] == NULL) { - BREAK_TO_DEBUGGER(); - dm_error("DC: failed to create tg!\n"); - goto create_fail; - } - - /* ABMs */ - pool->base.multiple_abms[j] = dmub_abm_create(ctx, - &abm_regs[i], - &abm_shift, - &abm_mask); - if (pool->base.multiple_abms[j] == NULL) { - dm_error("DC: failed to create abm for pipe %d!\n", i); - BREAK_TO_DEBUGGER(); - goto create_fail; - } - - /* index for resource pool arrays for next valid pipe */ - j++; - } - - /* PSR */ - pool->base.psr = dmub_psr_create(ctx); - if (pool->base.psr == NULL) { - dm_error("DC: failed to create psr obj!\n"); - BREAK_TO_DEBUGGER(); - goto create_fail; - } - - /* MPCCs */ - pool->base.mpc = dcn32_mpc_create(ctx, pool->base.res_cap->num_timing_generator, pool->base.res_cap->num_mpc_3dlut); - if (pool->base.mpc == NULL) { - BREAK_TO_DEBUGGER(); - dm_error("DC: failed to create mpc!\n"); - goto create_fail; - } - - /* DSCs */ - for (i = 0; i < pool->base.res_cap->num_dsc; i++) { - pool->base.dscs[i] = dcn32_dsc_create(ctx, i); - if (pool->base.dscs[i] == NULL) { - BREAK_TO_DEBUGGER(); - dm_error("DC: failed to create display stream compressor %d!\n", i); - goto create_fail; - } - } - - /* DWB */ - if (!dcn32_dwbc_create(ctx, &pool->base)) { - BREAK_TO_DEBUGGER(); - dm_error("DC: failed to create dwbc!\n"); - goto create_fail; - } - - /* MMHUBBUB */ - if (!dcn32_mmhubbub_create(ctx, &pool->base)) { - BREAK_TO_DEBUGGER(); - dm_error("DC: failed to create mcif_wb!\n"); - goto create_fail; - } - - /* AUX and I2C */ - for (i = 0; i < pool->base.res_cap->num_ddc; i++) { - pool->base.engines[i] = dcn32_aux_engine_create(ctx, i); - if (pool->base.engines[i] == NULL) { - BREAK_TO_DEBUGGER(); - dm_error( - "DC:failed to create aux engine!!\n"); - goto create_fail; - } - pool->base.hw_i2cs[i] = dcn32_i2c_hw_create(ctx, i); - if (pool->base.hw_i2cs[i] == NULL) { - BREAK_TO_DEBUGGER(); - dm_error( - "DC:failed to create hw i2c!!\n"); - goto create_fail; - } - pool->base.sw_i2cs[i] = NULL; - } - - /* Audio, HWSeq, Stream Encoders including HPO and virtual, MPC 3D LUTs */ - if (!resource_construct(num_virtual_links, dc, &pool->base, - &res_create_funcs)) - goto create_fail; - - /* HW Sequencer init functions and Plane caps */ - dcn32_hw_sequencer_init_functions(dc); - - dc->caps.max_planes = pool->base.pipe_count; - - for (i = 0; i < dc->caps.max_planes; ++i) - dc->caps.planes[i] = plane_cap; - - dc->cap_funcs = cap_funcs; - - if (dc->ctx->dc_bios->fw_info.oem_i2c_present) { - ddc_init_data.ctx = dc->ctx; - ddc_init_data.link = NULL; - ddc_init_data.id.id = dc->ctx->dc_bios->fw_info.oem_i2c_obj_id; - ddc_init_data.id.enum_id = 0; - ddc_init_data.id.type = OBJECT_TYPE_GENERIC; - pool->base.oem_device = dc->link_srv->create_ddc_service(&ddc_init_data); - } else { - pool->base.oem_device = NULL; - } - - dc->dml2_options.dcn_pipe_count = pool->base.pipe_count; - dc->dml2_options.use_native_pstate_optimization = false; - dc->dml2_options.use_native_soc_bb_construction = true; - dc->dml2_options.minimize_dispclk_using_odm = true; - - dc->dml2_options.callbacks.dc = dc; - dc->dml2_options.callbacks.build_scaling_params = &resource_build_scaling_params; - dc->dml2_options.callbacks.can_support_mclk_switch_using_fw_based_vblank_stretch = &dcn30_can_support_mclk_switch_using_fw_based_vblank_stretch; - dc->dml2_options.callbacks.acquire_secondary_pipe_for_mpc_odm = &dc_resource_acquire_secondary_pipe_for_mpc_odm_legacy; - dc->dml2_options.callbacks.update_pipes_for_stream_with_slice_count = &resource_update_pipes_for_stream_with_slice_count; - dc->dml2_options.callbacks.update_pipes_for_plane_with_slice_count = &resource_update_pipes_for_plane_with_slice_count; - dc->dml2_options.callbacks.get_mpc_slice_index = &resource_get_mpc_slice_index; - dc->dml2_options.callbacks.get_odm_slice_index = &resource_get_odm_slice_index; - dc->dml2_options.callbacks.get_opp_head = &resource_get_opp_head; - - dc->dml2_options.svp_pstate.callbacks.dc = dc; - dc->dml2_options.svp_pstate.callbacks.add_plane_to_context = &dc_add_plane_to_context; - dc->dml2_options.svp_pstate.callbacks.add_stream_to_ctx = &dc_add_stream_to_ctx; - dc->dml2_options.svp_pstate.callbacks.build_scaling_params = &resource_build_scaling_params; - dc->dml2_options.svp_pstate.callbacks.create_plane = &dc_create_plane_state; - dc->dml2_options.svp_pstate.callbacks.remove_plane_from_context = &dc_remove_plane_from_context; - dc->dml2_options.svp_pstate.callbacks.remove_stream_from_ctx = &dc_remove_stream_from_ctx; - dc->dml2_options.svp_pstate.callbacks.create_stream_for_sink = &dc_create_stream_for_sink; - dc->dml2_options.svp_pstate.callbacks.plane_state_release = &dc_plane_state_release; - dc->dml2_options.svp_pstate.callbacks.stream_release = &dc_stream_release; - dc->dml2_options.svp_pstate.callbacks.release_dsc = &dcn20_release_dsc; - - dc->dml2_options.svp_pstate.subvp_fw_processing_delay_us = dc->caps.subvp_fw_processing_delay_us; - dc->dml2_options.svp_pstate.subvp_prefetch_end_to_mall_start_us = dc->caps.subvp_prefetch_end_to_mall_start_us; - dc->dml2_options.svp_pstate.subvp_pstate_allow_width_us = dc->caps.subvp_pstate_allow_width_us; - dc->dml2_options.svp_pstate.subvp_swath_height_margin_lines = dc->caps.subvp_swath_height_margin_lines; - - dc->dml2_options.svp_pstate.force_disable_subvp = dc->debug.force_disable_subvp; - dc->dml2_options.svp_pstate.force_enable_subvp = dc->debug.force_subvp_mclk_switch; - - dc->dml2_options.mall_cfg.cache_line_size_bytes = dc->caps.cache_line_size; - dc->dml2_options.mall_cfg.cache_num_ways = dc->caps.cache_num_ways; - dc->dml2_options.mall_cfg.max_cab_allocation_bytes = dc->caps.max_cab_allocation_bytes; - dc->dml2_options.mall_cfg.mblk_height_4bpe_pixels = DCN3_2_MBLK_HEIGHT_4BPE; - dc->dml2_options.mall_cfg.mblk_height_8bpe_pixels = DCN3_2_MBLK_HEIGHT_8BPE; - dc->dml2_options.mall_cfg.mblk_size_bytes = DCN3_2_MALL_MBLK_SIZE_BYTES; - dc->dml2_options.mall_cfg.mblk_width_pixels = DCN3_2_MBLK_WIDTH; - - dc->dml2_options.max_segments_per_hubp = 18; - dc->dml2_options.det_segment_size = DCN3_2_DET_SEG_SIZE; - dc->dml2_options.map_dc_pipes_with_callbacks = true; - - if (ASICREV_IS_GC_11_0_3(dc->ctx->asic_id.hw_internal_rev) && (dc->config.sdpif_request_limit_words_per_umc == 0)) - dc->config.sdpif_request_limit_words_per_umc = 16; - - DC_FP_END(); - - return true; - -create_fail: - - DC_FP_END(); - - dcn32_resource_destruct(pool); - - return false; -} - -struct resource_pool *dcn32_create_resource_pool( - const struct dc_init_data *init_data, - struct dc *dc) -{ - struct dcn32_resource_pool *pool = - kzalloc(sizeof(struct dcn32_resource_pool), GFP_KERNEL); - - if (!pool) - return NULL; - - if (dcn32_resource_construct(init_data->num_virtual_links, dc, pool)) - return &pool->base; - - BREAK_TO_DEBUGGER(); - kfree(pool); - return NULL; -} - -/* - * Find the most optimal free pipe from res_ctx, which could be used as a - * secondary dpp pipe for input opp head pipe. - * - * a free pipe - a pipe in input res_ctx not yet used for any streams or - * planes. - * secondary dpp pipe - a pipe gets inserted to a head OPP pipe's MPC blending - * tree. This is typical used for rendering MPO planes or additional offset - * areas in MPCC combine. - * - * Hardware Transition Minimization Algorithm for Finding a Secondary DPP Pipe - * ------------------------------------------------------------------------- - * - * PROBLEM: - * - * 1. There is a hardware limitation that a secondary DPP pipe cannot be - * transferred from one MPC blending tree to the other in a single frame. - * Otherwise it could cause glitches on the screen. - * - * For instance, we cannot transition from state 1 to state 2 in one frame. This - * is because PIPE1 is transferred from PIPE0's MPC blending tree over to - * PIPE2's MPC blending tree, which is not supported by hardware. - * To support this transition we need to first remove PIPE1 from PIPE0's MPC - * blending tree in one frame and then insert PIPE1 to PIPE2's MPC blending tree - * in the next frame. This is not optimal as it will delay the flip for two - * frames. - * - * State 1: - * PIPE0 -- secondary DPP pipe --> (PIPE1) - * PIPE2 -- secondary DPP pipe --> NONE - * - * State 2: - * PIPE0 -- secondary DPP pipe --> NONE - * PIPE2 -- secondary DPP pipe --> (PIPE1) - * - * 2. We want to in general minimize the unnecessary changes in pipe topology. - * If a pipe is already added in current blending tree and there are no changes - * to plane topology, we don't want to swap it with another free pipe - * unnecessarily in every update. Powering up and down a pipe would require a - * full update which delays the flip for 1 frame. If we use the original pipe - * we don't have to toggle its power. So we can flip faster. - */ -static int find_optimal_free_pipe_as_secondary_dpp_pipe( - const struct resource_context *cur_res_ctx, - struct resource_context *new_res_ctx, - const struct resource_pool *pool, - const struct pipe_ctx *new_opp_head) -{ - const struct pipe_ctx *cur_opp_head; - int free_pipe_idx; - - cur_opp_head = &cur_res_ctx->pipe_ctx[new_opp_head->pipe_idx]; - free_pipe_idx = resource_find_free_pipe_used_in_cur_mpc_blending_tree( - cur_res_ctx, new_res_ctx, cur_opp_head); - - /* Up until here if we have not found a free secondary pipe, we will - * need to wait for at least one frame to complete the transition - * sequence. - */ - if (free_pipe_idx == FREE_PIPE_INDEX_NOT_FOUND) - free_pipe_idx = recource_find_free_pipe_not_used_in_cur_res_ctx( - cur_res_ctx, new_res_ctx, pool); - - /* Up until here if we have not found a free secondary pipe, we will - * need to wait for at least two frames to complete the transition - * sequence. It really doesn't matter which pipe we decide take from - * current enabled pipes. It won't save our frame time when we swap only - * one pipe or more pipes. - */ - if (free_pipe_idx == FREE_PIPE_INDEX_NOT_FOUND) - free_pipe_idx = resource_find_free_pipe_used_as_cur_sec_dpp_in_mpcc_combine( - cur_res_ctx, new_res_ctx, pool); - - if (free_pipe_idx == FREE_PIPE_INDEX_NOT_FOUND) - free_pipe_idx = resource_find_any_free_pipe(new_res_ctx, pool); - - return free_pipe_idx; -} - -static struct pipe_ctx *find_idle_secondary_pipe_check_mpo( - struct resource_context *res_ctx, - const struct resource_pool *pool, - const struct pipe_ctx *primary_pipe) -{ - int i; - struct pipe_ctx *secondary_pipe = NULL; - struct pipe_ctx *next_odm_mpo_pipe = NULL; - int primary_index, preferred_pipe_idx; - struct pipe_ctx *old_primary_pipe = NULL; - - /* - * Modified from find_idle_secondary_pipe - * With windowed MPO and ODM, we want to avoid the case where we want a - * free pipe for the left side but the free pipe is being used on the - * right side. - * Add check on current_state if the primary_pipe is the left side, - * to check the right side ( primary_pipe->next_odm_pipe ) to see if - * it is using a pipe for MPO ( primary_pipe->next_odm_pipe->bottom_pipe ) - * - If so, then don't use this pipe - * EXCEPTION - 3 plane ( 2 MPO plane ) case - * - in this case, the primary pipe has already gotten a free pipe for the - * MPO window in the left - * - when it tries to get a free pipe for the MPO window on the right, - * it will see that it is already assigned to the right side - * ( primary_pipe->next_odm_pipe ). But in this case, we want this - * free pipe, since it will be for the right side. So add an - * additional condition, that skipping the free pipe on the right only - * applies if the primary pipe has no bottom pipe currently assigned - */ - if (primary_pipe) { - primary_index = primary_pipe->pipe_idx; - old_primary_pipe = &primary_pipe->stream->ctx->dc->current_state->res_ctx.pipe_ctx[primary_index]; - if ((old_primary_pipe->next_odm_pipe) && (old_primary_pipe->next_odm_pipe->bottom_pipe) - && (!primary_pipe->bottom_pipe)) - next_odm_mpo_pipe = old_primary_pipe->next_odm_pipe->bottom_pipe; - - preferred_pipe_idx = (pool->pipe_count - 1) - primary_pipe->pipe_idx; - if ((res_ctx->pipe_ctx[preferred_pipe_idx].stream == NULL) && - !(next_odm_mpo_pipe && next_odm_mpo_pipe->pipe_idx == preferred_pipe_idx)) { - secondary_pipe = &res_ctx->pipe_ctx[preferred_pipe_idx]; - secondary_pipe->pipe_idx = preferred_pipe_idx; - } - } - - /* - * search backwards for the second pipe to keep pipe - * assignment more consistent - */ - if (!secondary_pipe) - for (i = pool->pipe_count - 1; i >= 0; i--) { - if ((res_ctx->pipe_ctx[i].stream == NULL) && - !(next_odm_mpo_pipe && next_odm_mpo_pipe->pipe_idx == i)) { - secondary_pipe = &res_ctx->pipe_ctx[i]; - secondary_pipe->pipe_idx = i; - break; - } - } - - return secondary_pipe; -} - -static struct pipe_ctx *dcn32_acquire_idle_pipe_for_head_pipe_in_layer( - struct dc_state *state, - const struct resource_pool *pool, - struct dc_stream_state *stream, - const struct pipe_ctx *head_pipe) -{ - struct resource_context *res_ctx = &state->res_ctx; - struct pipe_ctx *idle_pipe, *pipe; - struct resource_context *old_ctx = &stream->ctx->dc->current_state->res_ctx; - int head_index; - - if (!head_pipe) - ASSERT(0); - - /* - * Modified from dcn20_acquire_idle_pipe_for_layer - * Check if head_pipe in old_context already has bottom_pipe allocated. - * - If so, check if that pipe is available in the current context. - * -- If so, reuse pipe from old_context - */ - head_index = head_pipe->pipe_idx; - pipe = &old_ctx->pipe_ctx[head_index]; - if (pipe->bottom_pipe && res_ctx->pipe_ctx[pipe->bottom_pipe->pipe_idx].stream == NULL) { - idle_pipe = &res_ctx->pipe_ctx[pipe->bottom_pipe->pipe_idx]; - idle_pipe->pipe_idx = pipe->bottom_pipe->pipe_idx; - } else { - idle_pipe = find_idle_secondary_pipe_check_mpo(res_ctx, pool, head_pipe); - if (!idle_pipe) - return NULL; - } - - idle_pipe->stream = head_pipe->stream; - idle_pipe->stream_res.tg = head_pipe->stream_res.tg; - idle_pipe->stream_res.opp = head_pipe->stream_res.opp; - - idle_pipe->plane_res.hubp = pool->hubps[idle_pipe->pipe_idx]; - idle_pipe->plane_res.ipp = pool->ipps[idle_pipe->pipe_idx]; - idle_pipe->plane_res.dpp = pool->dpps[idle_pipe->pipe_idx]; - idle_pipe->plane_res.mpcc_inst = pool->dpps[idle_pipe->pipe_idx]->inst; - - return idle_pipe; -} - -static int find_optimal_free_pipe_as_secondary_opp_head( - const struct resource_context *cur_res_ctx, - struct resource_context *new_res_ctx, - const struct resource_pool *pool, - const struct pipe_ctx *new_otg_master) -{ - const struct pipe_ctx *cur_otg_master; - int free_pipe_idx; - - cur_otg_master = &cur_res_ctx->pipe_ctx[new_otg_master->pipe_idx]; - free_pipe_idx = resource_find_free_pipe_used_as_sec_opp_head_by_cur_otg_master( - cur_res_ctx, new_res_ctx, cur_otg_master); - - /* Up until here if we have not found a free secondary pipe, we will - * need to wait for at least one frame to complete the transition - * sequence. - */ - if (free_pipe_idx == FREE_PIPE_INDEX_NOT_FOUND) - free_pipe_idx = recource_find_free_pipe_not_used_in_cur_res_ctx( - cur_res_ctx, new_res_ctx, pool); - - if (free_pipe_idx == FREE_PIPE_INDEX_NOT_FOUND) - free_pipe_idx = resource_find_any_free_pipe(new_res_ctx, pool); - - return free_pipe_idx; -} - -struct pipe_ctx *dcn32_acquire_free_pipe_as_secondary_dpp_pipe( - const struct dc_state *cur_ctx, - struct dc_state *new_ctx, - const struct resource_pool *pool, - const struct pipe_ctx *opp_head_pipe) -{ - - int free_pipe_idx; - struct pipe_ctx *free_pipe; - - if (!opp_head_pipe->stream->ctx->dc->config.enable_windowed_mpo_odm) - return dcn32_acquire_idle_pipe_for_head_pipe_in_layer( - new_ctx, pool, opp_head_pipe->stream, opp_head_pipe); - - free_pipe_idx = find_optimal_free_pipe_as_secondary_dpp_pipe( - &cur_ctx->res_ctx, &new_ctx->res_ctx, - pool, opp_head_pipe); - if (free_pipe_idx >= 0) { - free_pipe = &new_ctx->res_ctx.pipe_ctx[free_pipe_idx]; - free_pipe->pipe_idx = free_pipe_idx; - free_pipe->stream = opp_head_pipe->stream; - free_pipe->stream_res.tg = opp_head_pipe->stream_res.tg; - free_pipe->stream_res.opp = opp_head_pipe->stream_res.opp; - - free_pipe->plane_res.hubp = pool->hubps[free_pipe->pipe_idx]; - free_pipe->plane_res.ipp = pool->ipps[free_pipe->pipe_idx]; - free_pipe->plane_res.dpp = pool->dpps[free_pipe->pipe_idx]; - free_pipe->plane_res.mpcc_inst = - pool->dpps[free_pipe->pipe_idx]->inst; - } else { - ASSERT(opp_head_pipe); - free_pipe = NULL; - } - - return free_pipe; -} - -struct pipe_ctx *dcn32_acquire_free_pipe_as_secondary_opp_head( - const struct dc_state *cur_ctx, - struct dc_state *new_ctx, - const struct resource_pool *pool, - const struct pipe_ctx *otg_master) -{ - int free_pipe_idx = find_optimal_free_pipe_as_secondary_opp_head( - &cur_ctx->res_ctx, &new_ctx->res_ctx, - pool, otg_master); - struct pipe_ctx *free_pipe; - - if (free_pipe_idx >= 0) { - free_pipe = &new_ctx->res_ctx.pipe_ctx[free_pipe_idx]; - free_pipe->pipe_idx = free_pipe_idx; - free_pipe->stream = otg_master->stream; - free_pipe->stream_res.tg = otg_master->stream_res.tg; - free_pipe->stream_res.dsc = NULL; - free_pipe->stream_res.opp = pool->opps[free_pipe_idx]; - free_pipe->plane_res.mi = pool->mis[free_pipe_idx]; - free_pipe->plane_res.hubp = pool->hubps[free_pipe_idx]; - free_pipe->plane_res.ipp = pool->ipps[free_pipe_idx]; - free_pipe->plane_res.xfm = pool->transforms[free_pipe_idx]; - free_pipe->plane_res.dpp = pool->dpps[free_pipe_idx]; - free_pipe->plane_res.mpcc_inst = pool->dpps[free_pipe_idx]->inst; - if (free_pipe->stream->timing.flags.DSC == 1) { - dcn20_acquire_dsc(free_pipe->stream->ctx->dc, - &new_ctx->res_ctx, - &free_pipe->stream_res.dsc, - free_pipe_idx); - ASSERT(free_pipe->stream_res.dsc); - if (free_pipe->stream_res.dsc == NULL) { - memset(free_pipe, 0, sizeof(*free_pipe)); - free_pipe = NULL; - } - } - } else { - ASSERT(otg_master); - free_pipe = NULL; - } - - return free_pipe; -} - -unsigned int dcn32_calc_num_avail_chans_for_mall(struct dc *dc, int num_chans) -{ - /* - * DCN32 and DCN321 SKUs may have different sizes for MALL - * but we may not be able to access all the MALL space. - * If the num_chans is power of 2, then we can access all - * of the available MALL space. Otherwise, we can only - * access: - * - * max_cab_size_in_bytes = total_cache_size_in_bytes * - * ((2^floor(log2(num_chans)))/num_chans) - * - * Calculating the MALL sizes for all available SKUs, we - * have come up with the follow simplified check. - * - we have max_chans which provides the max MALL size. - * Each chans supports 4MB of MALL so: - * - * total_cache_size_in_bytes = max_chans * 4 MB - * - * - we have avail_chans which shows the number of channels - * we can use if we can't access the entire MALL space. - * It is generally half of max_chans - * - so we use the following checks: - * - * if (num_chans == max_chans), return max_chans - * if (num_chans < max_chans), return avail_chans - * - * - exception is GC_11_0_0 where we can't access max_chans, - * so we define max_avail_chans as the maximum available - * MALL space - * - */ - int gc_11_0_0_max_chans = 48; - int gc_11_0_0_max_avail_chans = 32; - int gc_11_0_0_avail_chans = 16; - int gc_11_0_3_max_chans = 16; - int gc_11_0_3_avail_chans = 8; - int gc_11_0_2_max_chans = 8; - int gc_11_0_2_avail_chans = 4; - - if (ASICREV_IS_GC_11_0_0(dc->ctx->asic_id.hw_internal_rev)) { - return (num_chans == gc_11_0_0_max_chans) ? - gc_11_0_0_max_avail_chans : gc_11_0_0_avail_chans; - } else if (ASICREV_IS_GC_11_0_2(dc->ctx->asic_id.hw_internal_rev)) { - return (num_chans == gc_11_0_2_max_chans) ? - gc_11_0_2_max_chans : gc_11_0_2_avail_chans; - } else { // if (ASICREV_IS_GC_11_0_3(dc->ctx->asic_id.hw_internal_rev)) { - return (num_chans == gc_11_0_3_max_chans) ? - gc_11_0_3_max_chans : gc_11_0_3_avail_chans; - } -} diff --git a/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_resource.h b/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_resource.h deleted file mode 100644 index b931008114c9..000000000000 --- a/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_resource.h +++ /dev/null @@ -1,1263 +0,0 @@ -/* - * Copyright 2020 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 _DCN32_RESOURCE_H_ -#define _DCN32_RESOURCE_H_ - -#include "core_types.h" - -#define DCN3_2_DEFAULT_DET_SIZE 256 -#define DCN3_2_MAX_DET_SIZE 1152 -#define DCN3_2_MIN_DET_SIZE 128 -#define DCN3_2_MIN_COMPBUF_SIZE_KB 128 -#define DCN3_2_DET_SEG_SIZE 64 -#define DCN3_2_MALL_MBLK_SIZE_BYTES 65536 // 64 * 1024 -#define DCN3_2_MBLK_WIDTH 128 -#define DCN3_2_MBLK_HEIGHT_4BPE 128 -#define DCN3_2_MBLK_HEIGHT_8BPE 64 -#define DCN3_2_DCFCLK_DS_INIT_KHZ 10000 // Choose 10Mhz for init DCFCLK DS freq -#define SUBVP_HIGH_REFRESH_LIST_LEN 4 -#define DCN3_2_MAX_SUBVP_PIXEL_RATE_MHZ 1800 -#define DCN3_2_VMIN_DISPCLK_HZ 717000000 - -#define TO_DCN32_RES_POOL(pool)\ - container_of(pool, struct dcn32_resource_pool, base) - -extern struct _vcs_dpi_ip_params_st dcn3_2_ip; -extern struct _vcs_dpi_soc_bounding_box_st dcn3_2_soc; - -struct subvp_high_refresh_list { - int min_refresh; - int max_refresh; - struct resolution { - int width; - int height; - } res[SUBVP_HIGH_REFRESH_LIST_LEN]; -}; - -struct dcn32_resource_pool { - struct resource_pool base; -}; - -struct resource_pool *dcn32_create_resource_pool( - const struct dc_init_data *init_data, - struct dc *dc); - -struct panel_cntl *dcn32_panel_cntl_create( - const struct panel_cntl_init_data *init_data); - -bool dcn32_acquire_post_bldn_3dlut( - struct resource_context *res_ctx, - const struct resource_pool *pool, - int mpcc_id, - struct dc_3dlut **lut, - struct dc_transfer_func **shaper); - -bool dcn32_release_post_bldn_3dlut( - struct resource_context *res_ctx, - const struct resource_pool *pool, - struct dc_3dlut **lut, - struct dc_transfer_func **shaper); - -bool dcn32_remove_phantom_pipes(struct dc *dc, - struct dc_state *context, bool fast_update); - -void dcn32_retain_phantom_pipes(struct dc *dc, - struct dc_state *context); - -void dcn32_add_phantom_pipes(struct dc *dc, - struct dc_state *context, - display_e2e_pipe_params_st *pipes, - unsigned int pipe_cnt, - unsigned int index); - -bool dcn32_validate_bandwidth(struct dc *dc, - struct dc_state *context, - bool fast_validate); - -int dcn32_populate_dml_pipes_from_context( - struct dc *dc, struct dc_state *context, - display_e2e_pipe_params_st *pipes, - bool fast_validate); - -void dcn32_calculate_wm_and_dlg( - struct dc *dc, struct dc_state *context, - display_e2e_pipe_params_st *pipes, - int pipe_cnt, - int vlevel); - -uint32_t dcn32_helper_mall_bytes_to_ways( - struct dc *dc, - uint32_t total_size_in_mall_bytes); - -uint32_t dcn32_helper_calculate_mall_bytes_for_cursor( - struct dc *dc, - struct pipe_ctx *pipe_ctx, - bool ignore_cursor_buf); - -uint32_t dcn32_helper_calculate_num_ways_for_subvp( - struct dc *dc, - struct dc_state *context); - -void dcn32_merge_pipes_for_subvp(struct dc *dc, - struct dc_state *context); - -bool dcn32_all_pipes_have_stream_and_plane(struct dc *dc, - struct dc_state *context); - -bool dcn32_subvp_in_use(struct dc *dc, - struct dc_state *context); - -bool dcn32_mpo_in_use(struct dc_state *context); - -bool dcn32_any_surfaces_rotated(struct dc *dc, struct dc_state *context); -bool dcn32_is_center_timing(struct pipe_ctx *pipe); -bool dcn32_is_psr_capable(struct pipe_ctx *pipe); - -struct pipe_ctx *dcn32_acquire_free_pipe_as_secondary_dpp_pipe( - const struct dc_state *cur_ctx, - struct dc_state *new_ctx, - const struct resource_pool *pool, - const struct pipe_ctx *opp_head_pipe); - -struct pipe_ctx *dcn32_acquire_free_pipe_as_secondary_opp_head( - const struct dc_state *cur_ctx, - struct dc_state *new_ctx, - const struct resource_pool *pool, - const struct pipe_ctx *otg_master); - -void dcn32_release_pipe(struct dc_state *context, - struct pipe_ctx *pipe, - const struct resource_pool *pool); - -void dcn32_determine_det_override(struct dc *dc, - struct dc_state *context, - display_e2e_pipe_params_st *pipes); - -void dcn32_set_det_allocations(struct dc *dc, struct dc_state *context, - display_e2e_pipe_params_st *pipes); - -void dcn32_save_mall_state(struct dc *dc, - struct dc_state *context, - struct mall_temp_config *temp_config); - -void dcn32_restore_mall_state(struct dc *dc, - struct dc_state *context, - struct mall_temp_config *temp_config); - -struct dc_stream_state *dcn32_can_support_mclk_switch_using_fw_based_vblank_stretch(struct dc *dc, const struct dc_state *context); - -bool dcn32_allow_subvp_with_active_margin(struct pipe_ctx *pipe); - -bool dcn32_allow_subvp_high_refresh_rate(struct dc *dc, struct dc_state *context, struct pipe_ctx *pipe); - -unsigned int dcn32_calc_num_avail_chans_for_mall(struct dc *dc, int num_chans); - -double dcn32_determine_max_vratio_prefetch(struct dc *dc, struct dc_state *context); - -bool dcn32_check_native_scaling_for_res(struct pipe_ctx *pipe, unsigned int width, unsigned int height); - -bool dcn32_subvp_drr_admissable(struct dc *dc, struct dc_state *context); - -bool dcn32_subvp_vblank_admissable(struct dc *dc, struct dc_state *context, int vlevel); - -/* definitions for run time init of reg offsets */ - -/* CLK SRC */ -#define CS_COMMON_REG_LIST_DCN3_0_RI(index, pllid) \ - SRI_ARR_ALPHABET(PIXCLK_RESYNC_CNTL, PHYPLL, index, pllid), \ - SRII_ARR_2(PHASE, DP_DTO, 0, index), \ - SRII_ARR_2(PHASE, DP_DTO, 1, index), \ - SRII_ARR_2(PHASE, DP_DTO, 2, index), \ - SRII_ARR_2(PHASE, DP_DTO, 3, index), \ - SRII_ARR_2(MODULO, DP_DTO, 0, index), \ - SRII_ARR_2(MODULO, DP_DTO, 1, index), \ - SRII_ARR_2(MODULO, DP_DTO, 2, index), \ - SRII_ARR_2(MODULO, DP_DTO, 3, index), \ - SRII_ARR_2(PIXEL_RATE_CNTL, OTG, 0, index), \ - SRII_ARR_2(PIXEL_RATE_CNTL, OTG, 1, index), \ - SRII_ARR_2(PIXEL_RATE_CNTL, OTG, 2, index), \ - SRII_ARR_2(PIXEL_RATE_CNTL, OTG, 3, index) - -/* ABM */ -#define ABM_DCN32_REG_LIST_RI(id) \ - SRI_ARR(DC_ABM1_HG_SAMPLE_RATE, ABM, id), \ - SRI_ARR(DC_ABM1_LS_SAMPLE_RATE, ABM, id), \ - SRI_ARR(BL1_PWM_BL_UPDATE_SAMPLE_RATE, ABM, id), \ - SRI_ARR(DC_ABM1_HG_MISC_CTRL, ABM, id), \ - SRI_ARR(DC_ABM1_IPCSC_COEFF_SEL, ABM, id), \ - SRI_ARR(BL1_PWM_CURRENT_ABM_LEVEL, ABM, id), \ - SRI_ARR(BL1_PWM_TARGET_ABM_LEVEL, ABM, id), \ - SRI_ARR(BL1_PWM_USER_LEVEL, ABM, id), \ - SRI_ARR(DC_ABM1_LS_MIN_MAX_PIXEL_VALUE_THRES, ABM, id), \ - SRI_ARR(DC_ABM1_HGLS_REG_READ_PROGRESS, ABM, id), \ - SRI_ARR(DC_ABM1_ACE_OFFSET_SLOPE_0, ABM, id), \ - SRI_ARR(DC_ABM1_ACE_THRES_12, ABM, id), NBIO_SR_ARR(BIOS_SCRATCH_2, id) - -/* Audio */ -#define AUD_COMMON_REG_LIST_RI(id) \ - SRI_ARR(AZALIA_F0_CODEC_ENDPOINT_INDEX, AZF0ENDPOINT, id), \ - SRI_ARR(AZALIA_F0_CODEC_ENDPOINT_DATA, AZF0ENDPOINT, id), \ - SR_ARR(AZALIA_F0_CODEC_FUNCTION_PARAMETER_STREAM_FORMATS, id), \ - SR_ARR(AZALIA_F0_CODEC_FUNCTION_PARAMETER_SUPPORTED_SIZE_RATES, id), \ - SR_ARR(AZALIA_F0_CODEC_FUNCTION_PARAMETER_POWER_STATES, id), \ - SR_ARR(DCCG_AUDIO_DTO_SOURCE, id), SR_ARR(DCCG_AUDIO_DTO0_MODULE, id), \ - SR_ARR(DCCG_AUDIO_DTO0_PHASE, id), SR_ARR(DCCG_AUDIO_DTO1_MODULE, id), \ - SR_ARR(DCCG_AUDIO_DTO1_PHASE, id) \ - -/* VPG */ - -#define VPG_DCN3_REG_LIST_RI(id) \ - SRI_ARR(VPG_GENERIC_STATUS, VPG, id), \ - SRI_ARR(VPG_GENERIC_PACKET_ACCESS_CTRL, VPG, id), \ - SRI_ARR(VPG_GENERIC_PACKET_DATA, VPG, id), \ - SRI_ARR(VPG_GSP_FRAME_UPDATE_CTRL, VPG, id), \ - SRI_ARR(VPG_GSP_IMMEDIATE_UPDATE_CTRL, VPG, id) - -/* AFMT */ -#define AFMT_DCN3_REG_LIST_RI(id) \ - SRI_ARR(AFMT_INFOFRAME_CONTROL0, AFMT, id), \ - SRI_ARR(AFMT_VBI_PACKET_CONTROL, AFMT, id), \ - SRI_ARR(AFMT_AUDIO_PACKET_CONTROL, AFMT, id), \ - SRI_ARR(AFMT_AUDIO_PACKET_CONTROL2, AFMT, id), \ - SRI_ARR(AFMT_AUDIO_SRC_CONTROL, AFMT, id), \ - SRI_ARR(AFMT_60958_0, AFMT, id), SRI_ARR(AFMT_60958_1, AFMT, id), \ - SRI_ARR(AFMT_60958_2, AFMT, id), SRI_ARR(AFMT_MEM_PWR, AFMT, id) - -/* APG */ -#define APG_DCN31_REG_LIST_RI(id) \ - SRI_ARR(APG_CONTROL, APG, id), SRI_ARR(APG_CONTROL2, APG, id), \ - SRI_ARR(APG_MEM_PWR, APG, id), SRI_ARR(APG_DBG_GEN_CONTROL, APG, id) - -/* Stream encoder */ -#define SE_DCN32_REG_LIST_RI(id) \ - SRI_ARR(AFMT_CNTL, DIG, id), SRI_ARR(DIG_FE_CNTL, DIG, id), \ - SRI_ARR(HDMI_CONTROL, DIG, id), SRI_ARR(HDMI_DB_CONTROL, DIG, id), \ - SRI_ARR(HDMI_GC, DIG, id), \ - SRI_ARR(HDMI_GENERIC_PACKET_CONTROL0, DIG, id), \ - SRI_ARR(HDMI_GENERIC_PACKET_CONTROL1, DIG, id), \ - SRI_ARR(HDMI_GENERIC_PACKET_CONTROL2, DIG, id), \ - SRI_ARR(HDMI_GENERIC_PACKET_CONTROL3, DIG, id), \ - SRI_ARR(HDMI_GENERIC_PACKET_CONTROL4, DIG, id), \ - SRI_ARR(HDMI_GENERIC_PACKET_CONTROL5, DIG, id), \ - SRI_ARR(HDMI_GENERIC_PACKET_CONTROL6, DIG, id), \ - SRI_ARR(HDMI_GENERIC_PACKET_CONTROL7, DIG, id), \ - SRI_ARR(HDMI_GENERIC_PACKET_CONTROL8, DIG, id), \ - SRI_ARR(HDMI_GENERIC_PACKET_CONTROL9, DIG, id), \ - SRI_ARR(HDMI_GENERIC_PACKET_CONTROL10, DIG, id), \ - SRI_ARR(HDMI_INFOFRAME_CONTROL0, DIG, id), \ - SRI_ARR(HDMI_INFOFRAME_CONTROL1, DIG, id), \ - SRI_ARR(HDMI_VBI_PACKET_CONTROL, DIG, id), \ - SRI_ARR(HDMI_AUDIO_PACKET_CONTROL, DIG, id), \ - SRI_ARR(HDMI_ACR_PACKET_CONTROL, DIG, id), \ - SRI_ARR(HDMI_ACR_32_0, DIG, id), SRI_ARR(HDMI_ACR_32_1, DIG, id), \ - SRI_ARR(HDMI_ACR_44_0, DIG, id), SRI_ARR(HDMI_ACR_44_1, DIG, id), \ - SRI_ARR(HDMI_ACR_48_0, DIG, id), SRI_ARR(HDMI_ACR_48_1, DIG, id), \ - SRI_ARR(DP_DB_CNTL, DP, id), SRI_ARR(DP_MSA_MISC, DP, id), \ - SRI_ARR(DP_MSA_VBID_MISC, DP, id), SRI_ARR(DP_MSA_COLORIMETRY, DP, id), \ - SRI_ARR(DP_MSA_TIMING_PARAM1, DP, id), \ - SRI_ARR(DP_MSA_TIMING_PARAM2, DP, id), \ - SRI_ARR(DP_MSA_TIMING_PARAM3, DP, id), \ - SRI_ARR(DP_MSA_TIMING_PARAM4, DP, id), \ - SRI_ARR(DP_MSE_RATE_CNTL, DP, id), SRI_ARR(DP_MSE_RATE_UPDATE, DP, id), \ - SRI_ARR(DP_PIXEL_FORMAT, DP, id), SRI_ARR(DP_SEC_CNTL, DP, id), \ - SRI_ARR(DP_SEC_CNTL1, DP, id), SRI_ARR(DP_SEC_CNTL2, DP, id), \ - SRI_ARR(DP_SEC_CNTL5, DP, id), SRI_ARR(DP_SEC_CNTL6, DP, id), \ - SRI_ARR(DP_STEER_FIFO, DP, id), SRI_ARR(DP_VID_M, DP, id), \ - SRI_ARR(DP_VID_N, DP, id), SRI_ARR(DP_VID_STREAM_CNTL, DP, id), \ - SRI_ARR(DP_VID_TIMING, DP, id), SRI_ARR(DP_SEC_AUD_N, DP, id), \ - SRI_ARR(DP_SEC_TIMESTAMP, DP, id), SRI_ARR(DP_DSC_CNTL, DP, id), \ - SRI_ARR(DP_SEC_METADATA_TRANSMISSION, DP, id), \ - SRI_ARR(HDMI_METADATA_PACKET_CONTROL, DIG, id), \ - SRI_ARR(DP_SEC_FRAMING4, DP, id), SRI_ARR(DP_GSP11_CNTL, DP, id), \ - SRI_ARR(DME_CONTROL, DME, id), \ - SRI_ARR(DP_SEC_METADATA_TRANSMISSION, DP, id), \ - SRI_ARR(HDMI_METADATA_PACKET_CONTROL, DIG, id), \ - SRI_ARR(DIG_FE_CNTL, DIG, id), SRI_ARR(DIG_CLOCK_PATTERN, DIG, id), \ - SRI_ARR(DIG_FIFO_CTRL0, DIG, id) - -/* Aux regs */ - -#define AUX_REG_LIST_RI(id) \ - SRI_ARR(AUX_CONTROL, DP_AUX, id), SRI_ARR(AUX_DPHY_RX_CONTROL0, DP_AUX, id), \ - SRI_ARR(AUX_DPHY_RX_CONTROL1, DP_AUX, id) - -#define DCN2_AUX_REG_LIST_RI(id) \ - AUX_REG_LIST_RI(id), SRI_ARR(AUX_DPHY_TX_CONTROL, DP_AUX, id) - -/* HDP */ -#define HPD_REG_LIST_RI(id) SRI_ARR(DC_HPD_CONTROL, HPD, id) - -/* Link encoder */ -#define LE_DCN3_REG_LIST_RI(id) \ - SRI_ARR(DIG_BE_CNTL, DIG, id), SRI_ARR(DIG_BE_EN_CNTL, DIG, id), \ - SRI_ARR(TMDS_CTL_BITS, DIG, id), \ - SRI_ARR(TMDS_DCBALANCER_CONTROL, DIG, id), SRI_ARR(DP_CONFIG, DP, id), \ - SRI_ARR(DP_DPHY_CNTL, DP, id), SRI_ARR(DP_DPHY_PRBS_CNTL, DP, id), \ - SRI_ARR(DP_DPHY_SCRAM_CNTL, DP, id), SRI_ARR(DP_DPHY_SYM0, DP, id), \ - SRI_ARR(DP_DPHY_SYM1, DP, id), SRI_ARR(DP_DPHY_SYM2, DP, id), \ - SRI_ARR(DP_DPHY_TRAINING_PATTERN_SEL, DP, id), \ - SRI_ARR(DP_LINK_CNTL, DP, id), SRI_ARR(DP_LINK_FRAMING_CNTL, DP, id), \ - SRI_ARR(DP_MSE_SAT0, DP, id), SRI_ARR(DP_MSE_SAT1, DP, id), \ - SRI_ARR(DP_MSE_SAT2, DP, id), SRI_ARR(DP_MSE_SAT_UPDATE, DP, id), \ - SRI_ARR(DP_SEC_CNTL, DP, id), SRI_ARR(DP_VID_STREAM_CNTL, DP, id), \ - SRI_ARR(DP_DPHY_FAST_TRAINING, DP, id), SRI_ARR(DP_SEC_CNTL1, DP, id), \ - SRI_ARR(DP_DPHY_BS_SR_SWAP_CNTL, DP, id), \ - SRI_ARR(DP_DPHY_HBR2_PATTERN_CONTROL, DP, id) - -#define LE_DCN31_REG_LIST_RI(id) \ - LE_DCN3_REG_LIST_RI(id), SRI_ARR(DP_DPHY_INTERNAL_CTRL, DP, id), \ - SR_ARR(DIO_LINKA_CNTL, id), SR_ARR(DIO_LINKB_CNTL, id), \ - SR_ARR(DIO_LINKC_CNTL, id), SR_ARR(DIO_LINKD_CNTL, id), \ - SR_ARR(DIO_LINKE_CNTL, id), SR_ARR(DIO_LINKF_CNTL, id) - -#define UNIPHY_DCN2_REG_LIST_RI(id, phyid) \ - SRI_ARR_ALPHABET(CLOCK_ENABLE, SYMCLK, id, phyid), \ - SRI_ARR_ALPHABET(CHANNEL_XBAR_CNTL, UNIPHY, id, phyid) - -/* HPO DP stream encoder */ -#define DCN3_1_HPO_DP_STREAM_ENC_REG_LIST_RI(id) \ - SR_ARR(DP_STREAM_MAPPER_CONTROL0, id), \ - SR_ARR(DP_STREAM_MAPPER_CONTROL1, id), \ - SR_ARR(DP_STREAM_MAPPER_CONTROL2, id), \ - SR_ARR(DP_STREAM_MAPPER_CONTROL3, id), \ - SRI_ARR(DP_STREAM_ENC_CLOCK_CONTROL, DP_STREAM_ENC, id), \ - SRI_ARR(DP_STREAM_ENC_INPUT_MUX_CONTROL, DP_STREAM_ENC, id), \ - SRI_ARR(DP_STREAM_ENC_AUDIO_CONTROL, DP_STREAM_ENC, id), \ - SRI_ARR(DP_STREAM_ENC_CLOCK_RAMP_ADJUSTER_FIFO_STATUS_CONTROL0, DP_STREAM_ENC, id), \ - SRI_ARR(DP_SYM32_ENC_CONTROL, DP_SYM32_ENC, id), \ - SRI_ARR(DP_SYM32_ENC_VID_PIXEL_FORMAT, DP_SYM32_ENC, id), \ - SRI_ARR(DP_SYM32_ENC_VID_PIXEL_FORMAT_DOUBLE_BUFFER_CONTROL, DP_SYM32_ENC, id), \ - SRI_ARR(DP_SYM32_ENC_VID_MSA0, DP_SYM32_ENC, id), \ - SRI_ARR(DP_SYM32_ENC_VID_MSA1, DP_SYM32_ENC, id), \ - SRI_ARR(DP_SYM32_ENC_VID_MSA2, DP_SYM32_ENC, id), \ - SRI_ARR(DP_SYM32_ENC_VID_MSA3, DP_SYM32_ENC, id), \ - SRI_ARR(DP_SYM32_ENC_VID_MSA4, DP_SYM32_ENC, id), \ - SRI_ARR(DP_SYM32_ENC_VID_MSA5, DP_SYM32_ENC, id), \ - SRI_ARR(DP_SYM32_ENC_VID_MSA6, DP_SYM32_ENC, id), \ - SRI_ARR(DP_SYM32_ENC_VID_MSA7, DP_SYM32_ENC, id), \ - SRI_ARR(DP_SYM32_ENC_VID_MSA8, DP_SYM32_ENC, id), \ - SRI_ARR(DP_SYM32_ENC_VID_MSA_CONTROL, DP_SYM32_ENC, id), \ - SRI_ARR(DP_SYM32_ENC_VID_MSA_DOUBLE_BUFFER_CONTROL, DP_SYM32_ENC, id), \ - SRI_ARR(DP_SYM32_ENC_VID_FIFO_CONTROL, DP_SYM32_ENC, id), \ - SRI_ARR(DP_SYM32_ENC_VID_STREAM_CONTROL, DP_SYM32_ENC, id), \ - SRI_ARR(DP_SYM32_ENC_VID_VBID_CONTROL, DP_SYM32_ENC, id), \ - SRI_ARR(DP_SYM32_ENC_SDP_CONTROL, DP_SYM32_ENC, id), \ - SRI_ARR(DP_SYM32_ENC_SDP_GSP_CONTROL0, DP_SYM32_ENC, id), \ - SRI_ARR(DP_SYM32_ENC_SDP_GSP_CONTROL2, DP_SYM32_ENC, id), \ - SRI_ARR(DP_SYM32_ENC_SDP_GSP_CONTROL3, DP_SYM32_ENC, id), \ - SRI_ARR(DP_SYM32_ENC_SDP_GSP_CONTROL5, DP_SYM32_ENC, id), \ - SRI_ARR(DP_SYM32_ENC_SDP_GSP_CONTROL11, DP_SYM32_ENC, id), \ - SRI_ARR(DP_SYM32_ENC_SDP_METADATA_PACKET_CONTROL, DP_SYM32_ENC, id), \ - SRI_ARR(DP_SYM32_ENC_SDP_AUDIO_CONTROL0, DP_SYM32_ENC, id), \ - SRI_ARR(DP_SYM32_ENC_VID_CRC_CONTROL, DP_SYM32_ENC, id), \ - SRI_ARR(DP_SYM32_ENC_HBLANK_CONTROL, DP_SYM32_ENC, id) - -/* HPO DP link encoder regs */ -#define DCN3_1_HPO_DP_LINK_ENC_REG_LIST_RI(id) \ - SRI_ARR(DP_LINK_ENC_CLOCK_CONTROL, DP_LINK_ENC, id), \ - SRI_ARR(DP_DPHY_SYM32_CONTROL, DP_DPHY_SYM32, id), \ - SRI_ARR(DP_DPHY_SYM32_STATUS, DP_DPHY_SYM32, id), \ - SRI_ARR(DP_DPHY_SYM32_TP_CONFIG, DP_DPHY_SYM32, id), \ - SRI_ARR(DP_DPHY_SYM32_TP_PRBS_SEED0, DP_DPHY_SYM32, id), \ - SRI_ARR(DP_DPHY_SYM32_TP_PRBS_SEED1, DP_DPHY_SYM32, id), \ - SRI_ARR(DP_DPHY_SYM32_TP_PRBS_SEED2, DP_DPHY_SYM32, id), \ - SRI_ARR(DP_DPHY_SYM32_TP_PRBS_SEED3, DP_DPHY_SYM32, id), \ - SRI_ARR(DP_DPHY_SYM32_TP_SQ_PULSE, DP_DPHY_SYM32, id), \ - SRI_ARR(DP_DPHY_SYM32_TP_CUSTOM0, DP_DPHY_SYM32, id), \ - SRI_ARR(DP_DPHY_SYM32_TP_CUSTOM1, DP_DPHY_SYM32, id), \ - SRI_ARR(DP_DPHY_SYM32_TP_CUSTOM2, DP_DPHY_SYM32, id), \ - SRI_ARR(DP_DPHY_SYM32_TP_CUSTOM3, DP_DPHY_SYM32, id), \ - SRI_ARR(DP_DPHY_SYM32_TP_CUSTOM4, DP_DPHY_SYM32, id), \ - SRI_ARR(DP_DPHY_SYM32_TP_CUSTOM5, DP_DPHY_SYM32, id), \ - SRI_ARR(DP_DPHY_SYM32_TP_CUSTOM6, DP_DPHY_SYM32, id), \ - SRI_ARR(DP_DPHY_SYM32_TP_CUSTOM7, DP_DPHY_SYM32, id), \ - SRI_ARR(DP_DPHY_SYM32_TP_CUSTOM8, DP_DPHY_SYM32, id), \ - SRI_ARR(DP_DPHY_SYM32_TP_CUSTOM9, DP_DPHY_SYM32, id), \ - SRI_ARR(DP_DPHY_SYM32_TP_CUSTOM10, DP_DPHY_SYM32, id), \ - SRI_ARR(DP_DPHY_SYM32_SAT_VC0, DP_DPHY_SYM32, id), \ - SRI_ARR(DP_DPHY_SYM32_SAT_VC1, DP_DPHY_SYM32, id), \ - SRI_ARR(DP_DPHY_SYM32_SAT_VC2, DP_DPHY_SYM32, id), \ - SRI_ARR(DP_DPHY_SYM32_SAT_VC3, DP_DPHY_SYM32, id), \ - SRI_ARR(DP_DPHY_SYM32_VC_RATE_CNTL0, DP_DPHY_SYM32, id), \ - SRI_ARR(DP_DPHY_SYM32_VC_RATE_CNTL1, DP_DPHY_SYM32, id), \ - SRI_ARR(DP_DPHY_SYM32_VC_RATE_CNTL2, DP_DPHY_SYM32, id), \ - SRI_ARR(DP_DPHY_SYM32_VC_RATE_CNTL3, DP_DPHY_SYM32, id), \ - SRI_ARR(DP_DPHY_SYM32_SAT_UPDATE, DP_DPHY_SYM32, id) - -/* DPP */ -#define DPP_REG_LIST_DCN30_COMMON_RI(id) \ - SRI_ARR(CM_DEALPHA, CM, id), SRI_ARR(CM_MEM_PWR_STATUS, CM, id), \ - SRI_ARR(CM_BIAS_CR_R, CM, id), SRI_ARR(CM_BIAS_Y_G_CB_B, CM, id), \ - SRI_ARR(PRE_DEGAM, CNVC_CFG, id), SRI_ARR(CM_GAMCOR_CONTROL, CM, id), \ - SRI_ARR(CM_GAMCOR_LUT_CONTROL, CM, id), \ - SRI_ARR(CM_GAMCOR_LUT_INDEX, CM, id), \ - SRI_ARR(CM_GAMCOR_LUT_INDEX, CM, id), \ - SRI_ARR(CM_GAMCOR_LUT_DATA, CM, id), \ - SRI_ARR(CM_GAMCOR_RAMB_START_CNTL_B, CM, id), \ - SRI_ARR(CM_GAMCOR_RAMB_START_CNTL_G, CM, id), \ - SRI_ARR(CM_GAMCOR_RAMB_START_CNTL_R, CM, id), \ - SRI_ARR(CM_GAMCOR_RAMB_START_SLOPE_CNTL_B, CM, id), \ - SRI_ARR(CM_GAMCOR_RAMB_START_SLOPE_CNTL_G, CM, id), \ - SRI_ARR(CM_GAMCOR_RAMB_START_SLOPE_CNTL_R, CM, id), \ - SRI_ARR(CM_GAMCOR_RAMB_END_CNTL1_B, CM, id), \ - SRI_ARR(CM_GAMCOR_RAMB_END_CNTL2_B, CM, id), \ - SRI_ARR(CM_GAMCOR_RAMB_END_CNTL1_G, CM, id), \ - SRI_ARR(CM_GAMCOR_RAMB_END_CNTL2_G, CM, id), \ - SRI_ARR(CM_GAMCOR_RAMB_END_CNTL1_R, CM, id), \ - SRI_ARR(CM_GAMCOR_RAMB_END_CNTL2_R, CM, id), \ - SRI_ARR(CM_GAMCOR_RAMB_REGION_0_1, CM, id), \ - SRI_ARR(CM_GAMCOR_RAMB_REGION_32_33, CM, id), \ - SRI_ARR(CM_GAMCOR_RAMB_OFFSET_B, CM, id), \ - SRI_ARR(CM_GAMCOR_RAMB_OFFSET_G, CM, id), \ - SRI_ARR(CM_GAMCOR_RAMB_OFFSET_R, CM, id), \ - SRI_ARR(CM_GAMCOR_RAMB_START_BASE_CNTL_B, CM, id), \ - SRI_ARR(CM_GAMCOR_RAMB_START_BASE_CNTL_G, CM, id), \ - SRI_ARR(CM_GAMCOR_RAMB_START_BASE_CNTL_R, CM, id), \ - SRI_ARR(CM_GAMCOR_RAMA_START_CNTL_B, CM, id), \ - SRI_ARR(CM_GAMCOR_RAMA_START_CNTL_G, CM, id), \ - SRI_ARR(CM_GAMCOR_RAMA_START_CNTL_R, CM, id), \ - SRI_ARR(CM_GAMCOR_RAMA_START_SLOPE_CNTL_B, CM, id), \ - SRI_ARR(CM_GAMCOR_RAMA_START_SLOPE_CNTL_G, CM, id), \ - SRI_ARR(CM_GAMCOR_RAMA_START_SLOPE_CNTL_R, CM, id), \ - SRI_ARR(CM_GAMCOR_RAMA_END_CNTL1_B, CM, id), \ - SRI_ARR(CM_GAMCOR_RAMA_END_CNTL2_B, CM, id), \ - SRI_ARR(CM_GAMCOR_RAMA_END_CNTL1_G, CM, id), \ - SRI_ARR(CM_GAMCOR_RAMA_END_CNTL2_G, CM, id), \ - SRI_ARR(CM_GAMCOR_RAMA_END_CNTL1_R, CM, id), \ - SRI_ARR(CM_GAMCOR_RAMA_END_CNTL2_R, CM, id), \ - SRI_ARR(CM_GAMCOR_RAMA_REGION_0_1, CM, id), \ - SRI_ARR(CM_GAMCOR_RAMA_REGION_32_33, CM, id), \ - SRI_ARR(CM_GAMCOR_RAMA_OFFSET_B, CM, id), \ - SRI_ARR(CM_GAMCOR_RAMA_OFFSET_G, CM, id), \ - SRI_ARR(CM_GAMCOR_RAMA_OFFSET_R, CM, id), \ - SRI_ARR(CM_GAMCOR_RAMA_START_BASE_CNTL_B, CM, id), \ - SRI_ARR(CM_GAMCOR_RAMA_START_BASE_CNTL_G, CM, id), \ - SRI_ARR(CM_GAMCOR_RAMA_START_BASE_CNTL_R, CM, id), \ - SRI_ARR(CM_GAMUT_REMAP_CONTROL, CM, id), \ - SRI_ARR(CM_GAMUT_REMAP_C11_C12, CM, id), \ - SRI_ARR(CM_GAMUT_REMAP_C13_C14, CM, id), \ - SRI_ARR(CM_GAMUT_REMAP_C21_C22, CM, id), \ - SRI_ARR(CM_GAMUT_REMAP_C23_C24, CM, id), \ - SRI_ARR(CM_GAMUT_REMAP_C31_C32, CM, id), \ - SRI_ARR(CM_GAMUT_REMAP_C33_C34, CM, id), \ - SRI_ARR(CM_GAMUT_REMAP_B_C11_C12, CM, id), \ - SRI_ARR(CM_GAMUT_REMAP_B_C13_C14, CM, id), \ - SRI_ARR(CM_GAMUT_REMAP_B_C21_C22, CM, id), \ - SRI_ARR(CM_GAMUT_REMAP_B_C23_C24, CM, id), \ - SRI_ARR(CM_GAMUT_REMAP_B_C31_C32, CM, id), \ - SRI_ARR(CM_GAMUT_REMAP_B_C33_C34, CM, id), \ - SRI_ARR(DSCL_EXT_OVERSCAN_LEFT_RIGHT, DSCL, id), \ - SRI_ARR(DSCL_EXT_OVERSCAN_TOP_BOTTOM, DSCL, id), \ - SRI_ARR(OTG_H_BLANK, DSCL, id), SRI_ARR(OTG_V_BLANK, DSCL, id), \ - SRI_ARR(SCL_MODE, DSCL, id), SRI_ARR(LB_DATA_FORMAT, DSCL, id), \ - SRI_ARR(LB_MEMORY_CTRL, DSCL, id), SRI_ARR(DSCL_AUTOCAL, DSCL, id), \ - SRI_ARR(DSCL_CONTROL, DSCL, id), \ - SRI_ARR(SCL_TAP_CONTROL, DSCL, id), \ - SRI_ARR(SCL_COEF_RAM_TAP_SELECT, DSCL, id), \ - SRI_ARR(SCL_COEF_RAM_TAP_DATA, DSCL, id), \ - SRI_ARR(DSCL_2TAP_CONTROL, DSCL, id), SRI_ARR(MPC_SIZE, DSCL, id), \ - SRI_ARR(SCL_HORZ_FILTER_SCALE_RATIO, DSCL, id), \ - SRI_ARR(SCL_VERT_FILTER_SCALE_RATIO, DSCL, id), \ - SRI_ARR(SCL_HORZ_FILTER_SCALE_RATIO_C, DSCL, id), \ - SRI_ARR(SCL_VERT_FILTER_SCALE_RATIO_C, DSCL, id), \ - SRI_ARR(SCL_HORZ_FILTER_INIT, DSCL, id), \ - SRI_ARR(SCL_HORZ_FILTER_INIT_C, DSCL, id), \ - SRI_ARR(SCL_VERT_FILTER_INIT, DSCL, id), \ - SRI_ARR(SCL_VERT_FILTER_INIT_C, DSCL, id), \ - SRI_ARR(RECOUT_START, DSCL, id), SRI_ARR(RECOUT_SIZE, DSCL, id), \ - SRI_ARR(PRE_DEALPHA, CNVC_CFG, id), SRI_ARR(PRE_REALPHA, CNVC_CFG, id), \ - SRI_ARR(PRE_CSC_MODE, CNVC_CFG, id), \ - SRI_ARR(PRE_CSC_C11_C12, CNVC_CFG, id), \ - SRI_ARR(PRE_CSC_C33_C34, CNVC_CFG, id), \ - SRI_ARR(PRE_CSC_B_C11_C12, CNVC_CFG, id), \ - SRI_ARR(PRE_CSC_B_C33_C34, CNVC_CFG, id), \ - SRI_ARR(CM_POST_CSC_CONTROL, CM, id), \ - SRI_ARR(CM_POST_CSC_C11_C12, CM, id), \ - SRI_ARR(CM_POST_CSC_C33_C34, CM, id), \ - SRI_ARR(CM_POST_CSC_B_C11_C12, CM, id), \ - SRI_ARR(CM_POST_CSC_B_C33_C34, CM, id), \ - SRI_ARR(CM_MEM_PWR_CTRL, CM, id), SRI_ARR(CM_CONTROL, CM, id), \ - SRI_ARR(FORMAT_CONTROL, CNVC_CFG, id), \ - SRI_ARR(CNVC_SURFACE_PIXEL_FORMAT, CNVC_CFG, id), \ - SRI_ARR(CURSOR0_CONTROL, CNVC_CUR, id), \ - SRI_ARR(CURSOR0_COLOR0, CNVC_CUR, id), \ - SRI_ARR(CURSOR0_COLOR1, CNVC_CUR, id), \ - SRI_ARR(CURSOR0_FP_SCALE_BIAS, CNVC_CUR, id), \ - SRI_ARR(DPP_CONTROL, DPP_TOP, id), SRI_ARR(CM_HDR_MULT_COEF, CM, id), \ - SRI_ARR(CURSOR_CONTROL, CURSOR0_, id), \ - SRI_ARR(ALPHA_2BIT_LUT, CNVC_CFG, id), \ - SRI_ARR(FCNV_FP_BIAS_R, CNVC_CFG, id), \ - SRI_ARR(FCNV_FP_BIAS_G, CNVC_CFG, id), \ - SRI_ARR(FCNV_FP_BIAS_B, CNVC_CFG, id), \ - SRI_ARR(FCNV_FP_SCALE_R, CNVC_CFG, id), \ - SRI_ARR(FCNV_FP_SCALE_G, CNVC_CFG, id), \ - SRI_ARR(FCNV_FP_SCALE_B, CNVC_CFG, id), \ - SRI_ARR(COLOR_KEYER_CONTROL, CNVC_CFG, id), \ - SRI_ARR(COLOR_KEYER_ALPHA, CNVC_CFG, id), \ - SRI_ARR(COLOR_KEYER_RED, CNVC_CFG, id), \ - SRI_ARR(COLOR_KEYER_GREEN, CNVC_CFG, id), \ - SRI_ARR(COLOR_KEYER_BLUE, CNVC_CFG, id), \ - SRI_ARR(CURSOR_CONTROL, CURSOR0_, id), \ - SRI_ARR(OBUF_MEM_PWR_CTRL, DSCL, id), \ - SRI_ARR(DSCL_MEM_PWR_STATUS, DSCL, id), \ - SRI_ARR(DSCL_MEM_PWR_CTRL, DSCL, id) - -/* OPP */ -#define OPP_REG_LIST_DCN_RI(id) \ - SRI_ARR(FMT_BIT_DEPTH_CONTROL, FMT, id), SRI_ARR(FMT_CONTROL, FMT, id), \ - SRI_ARR(FMT_DITHER_RAND_R_SEED, FMT, id), \ - SRI_ARR(FMT_DITHER_RAND_G_SEED, FMT, id), \ - SRI_ARR(FMT_DITHER_RAND_B_SEED, FMT, id), \ - SRI_ARR(FMT_CLAMP_CNTL, FMT, id), \ - SRI_ARR(FMT_DYNAMIC_EXP_CNTL, FMT, id), \ - SRI_ARR(FMT_MAP420_MEMORY_CONTROL, FMT, id), \ - SRI_ARR(OPPBUF_CONTROL, OPPBUF, id), \ - SRI_ARR(OPPBUF_3D_PARAMETERS_0, OPPBUF, id), \ - SRI_ARR(OPPBUF_3D_PARAMETERS_1, OPPBUF, id), \ - SRI_ARR(OPP_PIPE_CONTROL, OPP_PIPE, id) \ - -#define OPP_REG_LIST_DCN10_RI(id) OPP_REG_LIST_DCN_RI(id) - -#define OPP_DPG_REG_LIST_RI(id) \ - SRI_ARR(DPG_CONTROL, DPG, id), SRI_ARR(DPG_DIMENSIONS, DPG, id), \ - SRI_ARR(DPG_OFFSET_SEGMENT, DPG, id), SRI_ARR(DPG_COLOUR_B_CB, DPG, id), \ - SRI_ARR(DPG_COLOUR_G_Y, DPG, id), SRI_ARR(DPG_COLOUR_R_CR, DPG, id), \ - SRI_ARR(DPG_RAMP_CONTROL, DPG, id), SRI_ARR(DPG_STATUS, DPG, id) - -#define OPP_REG_LIST_DCN30_RI(id) \ - OPP_REG_LIST_DCN10_RI(id), OPP_DPG_REG_LIST_RI(id), \ - SRI_ARR(FMT_422_CONTROL, FMT, id) - -/* Aux engine regs */ -#define AUX_COMMON_REG_LIST0_RI(id) \ - SRI_ARR(AUX_CONTROL, DP_AUX, id), SRI_ARR(AUX_ARB_CONTROL, DP_AUX, id), \ - SRI_ARR(AUX_SW_DATA, DP_AUX, id), SRI_ARR(AUX_SW_CONTROL, DP_AUX, id), \ - SRI_ARR(AUX_INTERRUPT_CONTROL, DP_AUX, id), \ - SRI_ARR(AUX_DPHY_RX_CONTROL1, DP_AUX, id), \ - SRI_ARR(AUX_SW_STATUS, DP_AUX, id) - -/* DWBC */ -#define DWBC_COMMON_REG_LIST_DCN30_RI(id) \ - SR_ARR(DWB_ENABLE_CLK_CTRL, id), SR_ARR(DWB_MEM_PWR_CTRL, id), \ - SR_ARR(FC_MODE_CTRL, id), SR_ARR(FC_FLOW_CTRL, id), \ - SR_ARR(FC_WINDOW_START, id), SR_ARR(FC_WINDOW_SIZE, id), \ - SR_ARR(FC_SOURCE_SIZE, id), SR_ARR(DWB_UPDATE_CTRL, id), \ - SR_ARR(DWB_CRC_CTRL, id), SR_ARR(DWB_CRC_MASK_R_G, id), \ - SR_ARR(DWB_CRC_MASK_B_A, id), SR_ARR(DWB_CRC_VAL_R_G, id), \ - SR_ARR(DWB_CRC_VAL_B_A, id), SR_ARR(DWB_OUT_CTRL, id), \ - SR_ARR(DWB_MMHUBBUB_BACKPRESSURE_CNT_EN, id), \ - SR_ARR(DWB_MMHUBBUB_BACKPRESSURE_CNT, id), \ - SR_ARR(DWB_HOST_READ_CONTROL, id), SR_ARR(DWB_SOFT_RESET, id), \ - SR_ARR(DWB_HDR_MULT_COEF, id), SR_ARR(DWB_GAMUT_REMAP_MODE, id), \ - SR_ARR(DWB_GAMUT_REMAP_COEF_FORMAT, id), \ - SR_ARR(DWB_GAMUT_REMAPA_C11_C12, id), \ - SR_ARR(DWB_GAMUT_REMAPA_C13_C14, id), \ - SR_ARR(DWB_GAMUT_REMAPA_C21_C22, id), \ - SR_ARR(DWB_GAMUT_REMAPA_C23_C24, id), \ - SR_ARR(DWB_GAMUT_REMAPA_C31_C32, id), \ - SR_ARR(DWB_GAMUT_REMAPA_C33_C34, id), \ - SR_ARR(DWB_GAMUT_REMAPB_C11_C12, id), \ - SR_ARR(DWB_GAMUT_REMAPB_C13_C14, id), \ - SR_ARR(DWB_GAMUT_REMAPB_C21_C22, id), \ - SR_ARR(DWB_GAMUT_REMAPB_C23_C24, id), \ - SR_ARR(DWB_GAMUT_REMAPB_C31_C32, id), \ - SR_ARR(DWB_GAMUT_REMAPB_C33_C34, id), SR_ARR(DWB_OGAM_CONTROL, id), \ - SR_ARR(DWB_OGAM_LUT_INDEX, id), SR_ARR(DWB_OGAM_LUT_DATA, id), \ - SR_ARR(DWB_OGAM_LUT_CONTROL, id), \ - SR_ARR(DWB_OGAM_RAMA_START_CNTL_B, id), \ - SR_ARR(DWB_OGAM_RAMA_START_CNTL_G, id), \ - SR_ARR(DWB_OGAM_RAMA_START_CNTL_R, id), \ - SR_ARR(DWB_OGAM_RAMA_START_BASE_CNTL_B, id), \ - SR_ARR(DWB_OGAM_RAMA_START_SLOPE_CNTL_B, id), \ - SR_ARR(DWB_OGAM_RAMA_START_BASE_CNTL_G, id), \ - SR_ARR(DWB_OGAM_RAMA_START_SLOPE_CNTL_G, id), \ - SR_ARR(DWB_OGAM_RAMA_START_BASE_CNTL_R, id), \ - SR_ARR(DWB_OGAM_RAMA_START_SLOPE_CNTL_R, id), \ - SR_ARR(DWB_OGAM_RAMA_END_CNTL1_B, id), \ - SR_ARR(DWB_OGAM_RAMA_END_CNTL2_B, id), \ - SR_ARR(DWB_OGAM_RAMA_END_CNTL1_G, id), \ - SR_ARR(DWB_OGAM_RAMA_END_CNTL2_G, id), \ - SR_ARR(DWB_OGAM_RAMA_END_CNTL1_R, id), \ - SR_ARR(DWB_OGAM_RAMA_END_CNTL2_R, id), \ - SR_ARR(DWB_OGAM_RAMA_OFFSET_B, id), SR_ARR(DWB_OGAM_RAMA_OFFSET_G, id), \ - SR_ARR(DWB_OGAM_RAMA_OFFSET_R, id), \ - SR_ARR(DWB_OGAM_RAMA_REGION_0_1, id), \ - SR_ARR(DWB_OGAM_RAMA_REGION_2_3, id), \ - SR_ARR(DWB_OGAM_RAMA_REGION_4_5, id), \ - SR_ARR(DWB_OGAM_RAMA_REGION_6_7, id), \ - SR_ARR(DWB_OGAM_RAMA_REGION_8_9, id), \ - SR_ARR(DWB_OGAM_RAMA_REGION_10_11, id), \ - SR_ARR(DWB_OGAM_RAMA_REGION_12_13, id), \ - SR_ARR(DWB_OGAM_RAMA_REGION_14_15, id), \ - SR_ARR(DWB_OGAM_RAMA_REGION_16_17, id), \ - SR_ARR(DWB_OGAM_RAMA_REGION_18_19, id), \ - SR_ARR(DWB_OGAM_RAMA_REGION_20_21, id), \ - SR_ARR(DWB_OGAM_RAMA_REGION_22_23, id), \ - SR_ARR(DWB_OGAM_RAMA_REGION_24_25, id), \ - SR_ARR(DWB_OGAM_RAMA_REGION_26_27, id), \ - SR_ARR(DWB_OGAM_RAMA_REGION_28_29, id), \ - SR_ARR(DWB_OGAM_RAMA_REGION_30_31, id), \ - SR_ARR(DWB_OGAM_RAMA_REGION_32_33, id), \ - SR_ARR(DWB_OGAM_RAMB_START_CNTL_B, id), \ - SR_ARR(DWB_OGAM_RAMB_START_CNTL_G, id), \ - SR_ARR(DWB_OGAM_RAMB_START_CNTL_R, id), \ - SR_ARR(DWB_OGAM_RAMB_START_BASE_CNTL_B, id), \ - SR_ARR(DWB_OGAM_RAMB_START_SLOPE_CNTL_B, id), \ - SR_ARR(DWB_OGAM_RAMB_START_BASE_CNTL_G, id), \ - SR_ARR(DWB_OGAM_RAMB_START_SLOPE_CNTL_G, id), \ - SR_ARR(DWB_OGAM_RAMB_START_BASE_CNTL_R, id), \ - SR_ARR(DWB_OGAM_RAMB_START_SLOPE_CNTL_R, id), \ - SR_ARR(DWB_OGAM_RAMB_END_CNTL1_B, id), \ - SR_ARR(DWB_OGAM_RAMB_END_CNTL2_B, id), \ - SR_ARR(DWB_OGAM_RAMB_END_CNTL1_G, id), \ - SR_ARR(DWB_OGAM_RAMB_END_CNTL2_G, id), \ - SR_ARR(DWB_OGAM_RAMB_END_CNTL1_R, id), \ - SR_ARR(DWB_OGAM_RAMB_END_CNTL2_R, id), \ - SR_ARR(DWB_OGAM_RAMB_OFFSET_B, id), SR_ARR(DWB_OGAM_RAMB_OFFSET_G, id), \ - SR_ARR(DWB_OGAM_RAMB_OFFSET_R, id), \ - SR_ARR(DWB_OGAM_RAMB_REGION_0_1, id), \ - SR_ARR(DWB_OGAM_RAMB_REGION_2_3, id), \ - SR_ARR(DWB_OGAM_RAMB_REGION_4_5, id), \ - SR_ARR(DWB_OGAM_RAMB_REGION_6_7, id), \ - SR_ARR(DWB_OGAM_RAMB_REGION_8_9, id), \ - SR_ARR(DWB_OGAM_RAMB_REGION_10_11, id), \ - SR_ARR(DWB_OGAM_RAMB_REGION_12_13, id), \ - SR_ARR(DWB_OGAM_RAMB_REGION_14_15, id), \ - SR_ARR(DWB_OGAM_RAMB_REGION_16_17, id), \ - SR_ARR(DWB_OGAM_RAMB_REGION_18_19, id), \ - SR_ARR(DWB_OGAM_RAMB_REGION_20_21, id), \ - SR_ARR(DWB_OGAM_RAMB_REGION_22_23, id), \ - SR_ARR(DWB_OGAM_RAMB_REGION_24_25, id), \ - SR_ARR(DWB_OGAM_RAMB_REGION_26_27, id), \ - SR_ARR(DWB_OGAM_RAMB_REGION_28_29, id), \ - SR_ARR(DWB_OGAM_RAMB_REGION_30_31, id), \ - SR_ARR(DWB_OGAM_RAMB_REGION_32_33, id) - -/* MCIF */ - -#define MCIF_WB_COMMON_REG_LIST_DCN32_RI(inst) \ - SRI2_ARR(MCIF_WB_BUFMGR_SW_CONTROL, MCIF_WB, inst), \ - SRI2_ARR(MCIF_WB_BUFMGR_STATUS, MCIF_WB, inst), \ - SRI2_ARR(MCIF_WB_BUF_PITCH, MCIF_WB, inst), \ - SRI2_ARR(MCIF_WB_BUF_1_STATUS, MCIF_WB, inst), \ - SRI2_ARR(MCIF_WB_BUF_1_STATUS2, MCIF_WB, inst), \ - SRI2_ARR(MCIF_WB_BUF_2_STATUS, MCIF_WB, inst), \ - SRI2_ARR(MCIF_WB_BUF_2_STATUS2, MCIF_WB, inst), \ - SRI2_ARR(MCIF_WB_BUF_3_STATUS, MCIF_WB, inst), \ - SRI2_ARR(MCIF_WB_BUF_3_STATUS2, MCIF_WB, inst), \ - SRI2_ARR(MCIF_WB_BUF_4_STATUS, MCIF_WB, inst), \ - SRI2_ARR(MCIF_WB_BUF_4_STATUS2, MCIF_WB, inst), \ - SRI2_ARR(MCIF_WB_ARBITRATION_CONTROL, MCIF_WB, inst), \ - SRI2_ARR(MCIF_WB_SCLK_CHANGE, MCIF_WB, inst), \ - SRI2_ARR(MCIF_WB_BUF_1_ADDR_Y, MCIF_WB, inst), \ - SRI2_ARR(MCIF_WB_BUF_1_ADDR_C, MCIF_WB, inst), \ - SRI2_ARR(MCIF_WB_BUF_2_ADDR_Y, MCIF_WB, inst), \ - SRI2_ARR(MCIF_WB_BUF_2_ADDR_C, MCIF_WB, inst), \ - SRI2_ARR(MCIF_WB_BUF_3_ADDR_Y, MCIF_WB, inst), \ - SRI2_ARR(MCIF_WB_BUF_3_ADDR_C, MCIF_WB, inst), \ - SRI2_ARR(MCIF_WB_BUF_4_ADDR_Y, MCIF_WB, inst), \ - SRI2_ARR(MCIF_WB_BUF_4_ADDR_C, MCIF_WB, inst), \ - SRI2_ARR(MCIF_WB_BUFMGR_VCE_CONTROL, MCIF_WB, inst), \ - SRI2_ARR(MCIF_WB_NB_PSTATE_LATENCY_WATERMARK, MMHUBBUB, inst), \ - SRI2_ARR(MCIF_WB_NB_PSTATE_CONTROL, MCIF_WB, inst), \ - SRI2_ARR(MCIF_WB_WATERMARK, MMHUBBUB, inst), \ - SRI2_ARR(MCIF_WB_CLOCK_GATER_CONTROL, MCIF_WB, inst), \ - SRI2_ARR(MCIF_WB_SELF_REFRESH_CONTROL, MCIF_WB, inst), \ - SRI2_ARR(MULTI_LEVEL_QOS_CTRL, MCIF_WB, inst), \ - SRI2_ARR(MCIF_WB_SECURITY_LEVEL, MCIF_WB, inst), \ - SRI2_ARR(MCIF_WB_BUF_LUMA_SIZE, MCIF_WB, inst), \ - SRI2_ARR(MCIF_WB_BUF_CHROMA_SIZE, MCIF_WB, inst), \ - SRI2_ARR(MCIF_WB_BUF_1_ADDR_Y_HIGH, MCIF_WB, inst), \ - SRI2_ARR(MCIF_WB_BUF_1_ADDR_C_HIGH, MCIF_WB, inst), \ - SRI2_ARR(MCIF_WB_BUF_2_ADDR_Y_HIGH, MCIF_WB, inst), \ - SRI2_ARR(MCIF_WB_BUF_2_ADDR_C_HIGH, MCIF_WB, inst), \ - SRI2_ARR(MCIF_WB_BUF_3_ADDR_Y_HIGH, MCIF_WB, inst), \ - SRI2_ARR(MCIF_WB_BUF_3_ADDR_C_HIGH, MCIF_WB, inst), \ - SRI2_ARR(MCIF_WB_BUF_4_ADDR_Y_HIGH, MCIF_WB, inst), \ - SRI2_ARR(MCIF_WB_BUF_4_ADDR_C_HIGH, MCIF_WB, inst), \ - SRI2_ARR(MCIF_WB_BUF_1_RESOLUTION, MCIF_WB, inst), \ - SRI2_ARR(MCIF_WB_BUF_2_RESOLUTION, MCIF_WB, inst), \ - SRI2_ARR(MCIF_WB_BUF_3_RESOLUTION, MCIF_WB, inst), \ - SRI2_ARR(MCIF_WB_BUF_4_RESOLUTION, MCIF_WB, inst), \ - SRI2_ARR(MMHUBBUB_MEM_PWR_CNTL, MMHUBBUB, inst), \ - SRI2_ARR(MMHUBBUB_WARMUP_ADDR_REGION, MMHUBBUB, inst), \ - SRI2_ARR(MMHUBBUB_WARMUP_BASE_ADDR_HIGH, MMHUBBUB, inst), \ - SRI2_ARR(MMHUBBUB_WARMUP_BASE_ADDR_LOW, MMHUBBUB, inst), \ - SRI2_ARR(MMHUBBUB_WARMUP_CONTROL_STATUS, MMHUBBUB, inst) - -/* DSC */ - -#define DSC_REG_LIST_DCN20_RI(id) \ - SRI_ARR(DSC_TOP_CONTROL, DSC_TOP, id), \ - SRI_ARR(DSC_DEBUG_CONTROL, DSC_TOP, id), \ - SRI_ARR(DSCC_CONFIG0, DSCC, id), SRI_ARR(DSCC_CONFIG1, DSCC, id), \ - SRI_ARR(DSCC_STATUS, DSCC, id), \ - SRI_ARR(DSCC_INTERRUPT_CONTROL_STATUS, DSCC, id), \ - SRI_ARR(DSCC_PPS_CONFIG0, DSCC, id), \ - SRI_ARR(DSCC_PPS_CONFIG1, DSCC, id), \ - SRI_ARR(DSCC_PPS_CONFIG2, DSCC, id), \ - SRI_ARR(DSCC_PPS_CONFIG3, DSCC, id), \ - SRI_ARR(DSCC_PPS_CONFIG4, DSCC, id), \ - SRI_ARR(DSCC_PPS_CONFIG5, DSCC, id), \ - SRI_ARR(DSCC_PPS_CONFIG6, DSCC, id), \ - SRI_ARR(DSCC_PPS_CONFIG7, DSCC, id), \ - SRI_ARR(DSCC_PPS_CONFIG8, DSCC, id), \ - SRI_ARR(DSCC_PPS_CONFIG9, DSCC, id), \ - SRI_ARR(DSCC_PPS_CONFIG10, DSCC, id), \ - SRI_ARR(DSCC_PPS_CONFIG11, DSCC, id), \ - SRI_ARR(DSCC_PPS_CONFIG12, DSCC, id), \ - SRI_ARR(DSCC_PPS_CONFIG13, DSCC, id), \ - SRI_ARR(DSCC_PPS_CONFIG14, DSCC, id), \ - SRI_ARR(DSCC_PPS_CONFIG15, DSCC, id), \ - SRI_ARR(DSCC_PPS_CONFIG16, DSCC, id), \ - SRI_ARR(DSCC_PPS_CONFIG17, DSCC, id), \ - SRI_ARR(DSCC_PPS_CONFIG18, DSCC, id), \ - SRI_ARR(DSCC_PPS_CONFIG19, DSCC, id), \ - SRI_ARR(DSCC_PPS_CONFIG20, DSCC, id), \ - SRI_ARR(DSCC_PPS_CONFIG21, DSCC, id), \ - SRI_ARR(DSCC_PPS_CONFIG22, DSCC, id), \ - SRI_ARR(DSCC_MEM_POWER_CONTROL, DSCC, id), \ - SRI_ARR(DSCC_R_Y_SQUARED_ERROR_LOWER, DSCC, id), \ - SRI_ARR(DSCC_R_Y_SQUARED_ERROR_UPPER, DSCC, id), \ - SRI_ARR(DSCC_G_CB_SQUARED_ERROR_LOWER, DSCC, id), \ - SRI_ARR(DSCC_G_CB_SQUARED_ERROR_UPPER, DSCC, id), \ - SRI_ARR(DSCC_B_CR_SQUARED_ERROR_LOWER, DSCC, id), \ - SRI_ARR(DSCC_B_CR_SQUARED_ERROR_UPPER, DSCC, id), \ - SRI_ARR(DSCC_MAX_ABS_ERROR0, DSCC, id), \ - SRI_ARR(DSCC_MAX_ABS_ERROR1, DSCC, id), \ - SRI_ARR(DSCC_RATE_BUFFER0_MAX_FULLNESS_LEVEL, DSCC, id), \ - SRI_ARR(DSCC_RATE_BUFFER1_MAX_FULLNESS_LEVEL, DSCC, id), \ - SRI_ARR(DSCC_RATE_BUFFER2_MAX_FULLNESS_LEVEL, DSCC, id), \ - SRI_ARR(DSCC_RATE_BUFFER3_MAX_FULLNESS_LEVEL, DSCC, id), \ - SRI_ARR(DSCC_RATE_CONTROL_BUFFER0_MAX_FULLNESS_LEVEL, DSCC, id), \ - SRI_ARR(DSCC_RATE_CONTROL_BUFFER1_MAX_FULLNESS_LEVEL, DSCC, id), \ - SRI_ARR(DSCC_RATE_CONTROL_BUFFER2_MAX_FULLNESS_LEVEL, DSCC, id), \ - SRI_ARR(DSCC_RATE_CONTROL_BUFFER3_MAX_FULLNESS_LEVEL, DSCC, id), \ - SRI_ARR(DSCCIF_CONFIG0, DSCCIF, id), \ - SRI_ARR(DSCCIF_CONFIG1, DSCCIF, id), \ - SRI_ARR(DSCRM_DSC_FORWARD_CONFIG, DSCRM, id) - -/* MPC */ - -#define MPC_DWB_MUX_REG_LIST_DCN3_0_RI(inst) \ - SRII_DWB(DWB_MUX, MUX, MPC_DWB, inst) - -#define MPC_OUT_MUX_COMMON_REG_LIST_DCN1_0_RI(inst) \ - SRII(MUX, MPC_OUT, inst), VUPDATE_SRII(CUR, VUPDATE_LOCK_SET, inst) - -#define MPC_OUT_MUX_REG_LIST_DCN3_0_RI(inst) \ - MPC_OUT_MUX_COMMON_REG_LIST_DCN1_0_RI(inst), SRII(CSC_MODE, MPC_OUT, inst), \ - SRII(CSC_C11_C12_A, MPC_OUT, inst), SRII(CSC_C33_C34_A, MPC_OUT, inst), \ - SRII(CSC_C11_C12_B, MPC_OUT, inst), SRII(CSC_C33_C34_B, MPC_OUT, inst), \ - SRII(DENORM_CONTROL, MPC_OUT, inst), \ - SRII(DENORM_CLAMP_G_Y, MPC_OUT, inst), \ - SRII(DENORM_CLAMP_B_CB, MPC_OUT, inst), SR(MPC_OUT_CSC_COEF_FORMAT) - -#define MPC_COMMON_REG_LIST_DCN1_0_RI(inst) \ - SRII(MPCC_TOP_SEL, MPCC, inst), SRII(MPCC_BOT_SEL, MPCC, inst), \ - SRII(MPCC_CONTROL, MPCC, inst), SRII(MPCC_STATUS, MPCC, inst), \ - SRII(MPCC_OPP_ID, MPCC, inst), SRII(MPCC_BG_G_Y, MPCC, inst), \ - SRII(MPCC_BG_R_CR, MPCC, inst), SRII(MPCC_BG_B_CB, MPCC, inst), \ - SRII(MPCC_SM_CONTROL, MPCC, inst), \ - SRII(MPCC_UPDATE_LOCK_SEL, MPCC, inst) - -#define MPC_REG_LIST_DCN3_0_RI(inst) \ - MPC_COMMON_REG_LIST_DCN1_0_RI(inst), SRII(MPCC_TOP_GAIN, MPCC, inst), \ - SRII(MPCC_BOT_GAIN_INSIDE, MPCC, inst), \ - SRII(MPCC_BOT_GAIN_OUTSIDE, MPCC, inst), \ - SRII(MPCC_MEM_PWR_CTRL, MPCC, inst), \ - SRII(MPCC_OGAM_LUT_INDEX, MPCC_OGAM, inst), \ - SRII(MPCC_OGAM_LUT_DATA, MPCC_OGAM, inst), \ - SRII(MPCC_GAMUT_REMAP_COEF_FORMAT, MPCC_OGAM, inst), \ - SRII(MPCC_GAMUT_REMAP_MODE, MPCC_OGAM, inst), \ - SRII(MPC_GAMUT_REMAP_C11_C12_A, MPCC_OGAM, inst), \ - SRII(MPC_GAMUT_REMAP_C33_C34_A, MPCC_OGAM, inst), \ - SRII(MPC_GAMUT_REMAP_C11_C12_B, MPCC_OGAM, inst), \ - SRII(MPC_GAMUT_REMAP_C33_C34_B, MPCC_OGAM, inst), \ - SRII(MPCC_OGAM_RAMA_START_CNTL_B, MPCC_OGAM, inst), \ - SRII(MPCC_OGAM_RAMA_START_CNTL_G, MPCC_OGAM, inst), \ - SRII(MPCC_OGAM_RAMA_START_CNTL_R, MPCC_OGAM, inst), \ - SRII(MPCC_OGAM_RAMA_START_SLOPE_CNTL_B, MPCC_OGAM, inst), \ - SRII(MPCC_OGAM_RAMA_START_SLOPE_CNTL_G, MPCC_OGAM, inst), \ - SRII(MPCC_OGAM_RAMA_START_SLOPE_CNTL_R, MPCC_OGAM, inst), \ - SRII(MPCC_OGAM_RAMA_END_CNTL1_B, MPCC_OGAM, inst), \ - SRII(MPCC_OGAM_RAMA_END_CNTL2_B, MPCC_OGAM, inst), \ - SRII(MPCC_OGAM_RAMA_END_CNTL1_G, MPCC_OGAM, inst), \ - SRII(MPCC_OGAM_RAMA_END_CNTL2_G, MPCC_OGAM, inst), \ - SRII(MPCC_OGAM_RAMA_END_CNTL1_R, MPCC_OGAM, inst), \ - SRII(MPCC_OGAM_RAMA_END_CNTL2_R, MPCC_OGAM, inst), \ - SRII(MPCC_OGAM_RAMA_REGION_0_1, MPCC_OGAM, inst), \ - SRII(MPCC_OGAM_RAMA_REGION_32_33, MPCC_OGAM, inst), \ - SRII(MPCC_OGAM_RAMA_OFFSET_B, MPCC_OGAM, inst), \ - SRII(MPCC_OGAM_RAMA_OFFSET_G, MPCC_OGAM, inst), \ - SRII(MPCC_OGAM_RAMA_OFFSET_R, MPCC_OGAM, inst), \ - SRII(MPCC_OGAM_RAMA_START_BASE_CNTL_B, MPCC_OGAM, inst), \ - SRII(MPCC_OGAM_RAMA_START_BASE_CNTL_G, MPCC_OGAM, inst), \ - SRII(MPCC_OGAM_RAMA_START_BASE_CNTL_R, MPCC_OGAM, inst), \ - SRII(MPCC_OGAM_RAMB_START_CNTL_B, MPCC_OGAM, inst), \ - SRII(MPCC_OGAM_RAMB_START_CNTL_G, MPCC_OGAM, inst), \ - SRII(MPCC_OGAM_RAMB_START_CNTL_R, MPCC_OGAM, inst), \ - SRII(MPCC_OGAM_RAMB_START_SLOPE_CNTL_B, MPCC_OGAM, inst), \ - SRII(MPCC_OGAM_RAMB_START_SLOPE_CNTL_G, MPCC_OGAM, inst), \ - SRII(MPCC_OGAM_RAMB_START_SLOPE_CNTL_R, MPCC_OGAM, inst), \ - SRII(MPCC_OGAM_RAMB_END_CNTL1_B, MPCC_OGAM, inst), \ - SRII(MPCC_OGAM_RAMB_END_CNTL2_B, MPCC_OGAM, inst), \ - SRII(MPCC_OGAM_RAMB_END_CNTL1_G, MPCC_OGAM, inst), \ - SRII(MPCC_OGAM_RAMB_END_CNTL2_G, MPCC_OGAM, inst), \ - SRII(MPCC_OGAM_RAMB_END_CNTL1_R, MPCC_OGAM, inst), \ - SRII(MPCC_OGAM_RAMB_END_CNTL2_R, MPCC_OGAM, inst), \ - SRII(MPCC_OGAM_RAMB_REGION_0_1, MPCC_OGAM, inst), \ - SRII(MPCC_OGAM_RAMB_REGION_32_33, MPCC_OGAM, inst), \ - SRII(MPCC_OGAM_RAMB_OFFSET_B, MPCC_OGAM, inst), \ - SRII(MPCC_OGAM_RAMB_OFFSET_G, MPCC_OGAM, inst), \ - SRII(MPCC_OGAM_RAMB_OFFSET_R, MPCC_OGAM, inst), \ - SRII(MPCC_OGAM_RAMB_START_BASE_CNTL_B, MPCC_OGAM, inst), \ - SRII(MPCC_OGAM_RAMB_START_BASE_CNTL_G, MPCC_OGAM, inst), \ - SRII(MPCC_OGAM_RAMB_START_BASE_CNTL_R, MPCC_OGAM, inst), \ - SRII(MPCC_OGAM_CONTROL, MPCC_OGAM, inst), \ - SRII(MPCC_OGAM_LUT_CONTROL, MPCC_OGAM, inst) - -#define MPC_REG_LIST_DCN3_2_RI(inst) \ - MPC_REG_LIST_DCN3_0_RI(inst),\ - SRII(MPCC_MOVABLE_CM_LOCATION_CONTROL, MPCC, inst),\ - SRII(MPCC_MCM_SHAPER_CONTROL, MPCC_MCM, inst),\ - SRII(MPCC_MCM_SHAPER_OFFSET_R, MPCC_MCM, inst),\ - SRII(MPCC_MCM_SHAPER_OFFSET_G, MPCC_MCM, inst),\ - SRII(MPCC_MCM_SHAPER_OFFSET_B, MPCC_MCM, inst),\ - SRII(MPCC_MCM_SHAPER_SCALE_R, MPCC_MCM, inst),\ - SRII(MPCC_MCM_SHAPER_SCALE_G_B, MPCC_MCM, inst),\ - SRII(MPCC_MCM_SHAPER_LUT_INDEX, MPCC_MCM, inst),\ - SRII(MPCC_MCM_SHAPER_LUT_DATA, MPCC_MCM, inst),\ - SRII(MPCC_MCM_SHAPER_LUT_WRITE_EN_MASK, MPCC_MCM, inst),\ - SRII(MPCC_MCM_SHAPER_RAMA_START_CNTL_B, MPCC_MCM, inst),\ - SRII(MPCC_MCM_SHAPER_RAMA_START_CNTL_G, MPCC_MCM, inst),\ - SRII(MPCC_MCM_SHAPER_RAMA_START_CNTL_R, MPCC_MCM, inst),\ - SRII(MPCC_MCM_SHAPER_RAMA_END_CNTL_B, MPCC_MCM, inst),\ - SRII(MPCC_MCM_SHAPER_RAMA_END_CNTL_G, MPCC_MCM, inst),\ - SRII(MPCC_MCM_SHAPER_RAMA_END_CNTL_R, MPCC_MCM, inst),\ - SRII(MPCC_MCM_SHAPER_RAMA_REGION_0_1, MPCC_MCM, inst),\ - SRII(MPCC_MCM_SHAPER_RAMA_REGION_2_3, MPCC_MCM, inst),\ - SRII(MPCC_MCM_SHAPER_RAMA_REGION_4_5, MPCC_MCM, inst),\ - SRII(MPCC_MCM_SHAPER_RAMA_REGION_6_7, MPCC_MCM, inst),\ - SRII(MPCC_MCM_SHAPER_RAMA_REGION_8_9, MPCC_MCM, inst),\ - SRII(MPCC_MCM_SHAPER_RAMA_REGION_10_11, MPCC_MCM, inst),\ - SRII(MPCC_MCM_SHAPER_RAMA_REGION_12_13, MPCC_MCM, inst),\ - SRII(MPCC_MCM_SHAPER_RAMA_REGION_14_15, MPCC_MCM, inst),\ - SRII(MPCC_MCM_SHAPER_RAMA_REGION_16_17, MPCC_MCM, inst),\ - SRII(MPCC_MCM_SHAPER_RAMA_REGION_18_19, MPCC_MCM, inst),\ - SRII(MPCC_MCM_SHAPER_RAMA_REGION_20_21, MPCC_MCM, inst),\ - SRII(MPCC_MCM_SHAPER_RAMA_REGION_22_23, MPCC_MCM, inst),\ - SRII(MPCC_MCM_SHAPER_RAMA_REGION_24_25, MPCC_MCM, inst),\ - SRII(MPCC_MCM_SHAPER_RAMA_REGION_26_27, MPCC_MCM, inst),\ - SRII(MPCC_MCM_SHAPER_RAMA_REGION_28_29, MPCC_MCM, inst),\ - SRII(MPCC_MCM_SHAPER_RAMA_REGION_30_31, MPCC_MCM, inst),\ - SRII(MPCC_MCM_SHAPER_RAMA_REGION_32_33, MPCC_MCM, inst),\ - SRII(MPCC_MCM_SHAPER_RAMB_START_CNTL_B, MPCC_MCM, inst),\ - SRII(MPCC_MCM_SHAPER_RAMB_START_CNTL_G, MPCC_MCM, inst),\ - SRII(MPCC_MCM_SHAPER_RAMB_START_CNTL_R, MPCC_MCM, inst),\ - SRII(MPCC_MCM_SHAPER_RAMB_END_CNTL_B, MPCC_MCM, inst),\ - SRII(MPCC_MCM_SHAPER_RAMB_END_CNTL_G, MPCC_MCM, inst),\ - SRII(MPCC_MCM_SHAPER_RAMB_END_CNTL_R, MPCC_MCM, inst),\ - SRII(MPCC_MCM_SHAPER_RAMB_REGION_0_1, MPCC_MCM, inst),\ - SRII(MPCC_MCM_SHAPER_RAMB_REGION_2_3, MPCC_MCM, inst),\ - SRII(MPCC_MCM_SHAPER_RAMB_REGION_4_5, MPCC_MCM, inst),\ - SRII(MPCC_MCM_SHAPER_RAMB_REGION_6_7, MPCC_MCM, inst),\ - SRII(MPCC_MCM_SHAPER_RAMB_REGION_8_9, MPCC_MCM, inst),\ - SRII(MPCC_MCM_SHAPER_RAMB_REGION_10_11, MPCC_MCM, inst),\ - SRII(MPCC_MCM_SHAPER_RAMB_REGION_12_13, MPCC_MCM, inst),\ - SRII(MPCC_MCM_SHAPER_RAMB_REGION_14_15, MPCC_MCM, inst),\ - SRII(MPCC_MCM_SHAPER_RAMB_REGION_16_17, MPCC_MCM, inst),\ - SRII(MPCC_MCM_SHAPER_RAMB_REGION_18_19, MPCC_MCM, inst),\ - SRII(MPCC_MCM_SHAPER_RAMB_REGION_20_21, MPCC_MCM, inst),\ - SRII(MPCC_MCM_SHAPER_RAMB_REGION_22_23, MPCC_MCM, inst),\ - SRII(MPCC_MCM_SHAPER_RAMB_REGION_24_25, MPCC_MCM, inst),\ - SRII(MPCC_MCM_SHAPER_RAMB_REGION_26_27, MPCC_MCM, inst),\ - SRII(MPCC_MCM_SHAPER_RAMB_REGION_28_29, MPCC_MCM, inst),\ - SRII(MPCC_MCM_SHAPER_RAMB_REGION_30_31, MPCC_MCM, inst),\ - SRII(MPCC_MCM_SHAPER_RAMB_REGION_32_33, MPCC_MCM, inst),\ - SRII(MPCC_MCM_3DLUT_MODE, MPCC_MCM, inst), /*TODO: may need to add other 3DLUT regs*/\ - SRII(MPCC_MCM_3DLUT_INDEX, MPCC_MCM, inst),\ - SRII(MPCC_MCM_3DLUT_DATA, MPCC_MCM, inst),\ - SRII(MPCC_MCM_3DLUT_DATA_30BIT, MPCC_MCM, inst),\ - SRII(MPCC_MCM_3DLUT_READ_WRITE_CONTROL, MPCC_MCM, inst),\ - SRII(MPCC_MCM_3DLUT_OUT_NORM_FACTOR, MPCC_MCM, inst),\ - SRII(MPCC_MCM_3DLUT_OUT_OFFSET_R, MPCC_MCM, inst),\ - SRII(MPCC_MCM_3DLUT_OUT_OFFSET_G, MPCC_MCM, inst),\ - SRII(MPCC_MCM_3DLUT_OUT_OFFSET_B, MPCC_MCM, inst),\ - SRII(MPCC_MCM_1DLUT_CONTROL, MPCC_MCM, inst),\ - SRII(MPCC_MCM_1DLUT_LUT_INDEX, MPCC_MCM, inst),\ - SRII(MPCC_MCM_1DLUT_LUT_DATA, MPCC_MCM, inst),\ - SRII(MPCC_MCM_1DLUT_LUT_CONTROL, MPCC_MCM, inst),\ - SRII(MPCC_MCM_1DLUT_RAMA_START_CNTL_B, MPCC_MCM, inst),\ - SRII(MPCC_MCM_1DLUT_RAMA_START_CNTL_G, MPCC_MCM, inst),\ - SRII(MPCC_MCM_1DLUT_RAMA_START_CNTL_R, MPCC_MCM, inst),\ - SRII(MPCC_MCM_1DLUT_RAMA_START_SLOPE_CNTL_B, MPCC_MCM, inst),\ - SRII(MPCC_MCM_1DLUT_RAMA_START_SLOPE_CNTL_G, MPCC_MCM, inst),\ - SRII(MPCC_MCM_1DLUT_RAMA_START_SLOPE_CNTL_R, MPCC_MCM, inst),\ - SRII(MPCC_MCM_1DLUT_RAMA_START_BASE_CNTL_B, MPCC_MCM, inst),\ - SRII(MPCC_MCM_1DLUT_RAMA_START_BASE_CNTL_G, MPCC_MCM, inst),\ - SRII(MPCC_MCM_1DLUT_RAMA_START_BASE_CNTL_R, MPCC_MCM, inst),\ - SRII(MPCC_MCM_1DLUT_RAMA_END_CNTL1_B, MPCC_MCM, inst),\ - SRII(MPCC_MCM_1DLUT_RAMA_END_CNTL2_B, MPCC_MCM, inst),\ - SRII(MPCC_MCM_1DLUT_RAMA_END_CNTL1_G, MPCC_MCM, inst),\ - SRII(MPCC_MCM_1DLUT_RAMA_END_CNTL2_G, MPCC_MCM, inst),\ - SRII(MPCC_MCM_1DLUT_RAMA_END_CNTL1_R, MPCC_MCM, inst),\ - SRII(MPCC_MCM_1DLUT_RAMA_END_CNTL2_R, MPCC_MCM, inst),\ - SRII(MPCC_MCM_1DLUT_RAMA_OFFSET_B, MPCC_MCM, inst),\ - SRII(MPCC_MCM_1DLUT_RAMA_OFFSET_G, MPCC_MCM, inst),\ - SRII(MPCC_MCM_1DLUT_RAMA_OFFSET_R, MPCC_MCM, inst),\ - SRII(MPCC_MCM_1DLUT_RAMA_REGION_0_1, MPCC_MCM, inst),\ - SRII(MPCC_MCM_1DLUT_RAMA_REGION_2_3, MPCC_MCM, inst),\ - SRII(MPCC_MCM_1DLUT_RAMA_REGION_4_5, MPCC_MCM, inst),\ - SRII(MPCC_MCM_1DLUT_RAMA_REGION_6_7, MPCC_MCM, inst),\ - SRII(MPCC_MCM_1DLUT_RAMA_REGION_8_9, MPCC_MCM, inst),\ - SRII(MPCC_MCM_1DLUT_RAMA_REGION_10_11, MPCC_MCM, inst),\ - SRII(MPCC_MCM_1DLUT_RAMA_REGION_12_13, MPCC_MCM, inst),\ - SRII(MPCC_MCM_1DLUT_RAMA_REGION_14_15, MPCC_MCM, inst),\ - SRII(MPCC_MCM_1DLUT_RAMA_REGION_16_17, MPCC_MCM, inst),\ - SRII(MPCC_MCM_1DLUT_RAMA_REGION_18_19, MPCC_MCM, inst),\ - SRII(MPCC_MCM_1DLUT_RAMA_REGION_20_21, MPCC_MCM, inst),\ - SRII(MPCC_MCM_1DLUT_RAMA_REGION_22_23, MPCC_MCM, inst),\ - SRII(MPCC_MCM_1DLUT_RAMA_REGION_24_25, MPCC_MCM, inst),\ - SRII(MPCC_MCM_1DLUT_RAMA_REGION_26_27, MPCC_MCM, inst),\ - SRII(MPCC_MCM_1DLUT_RAMA_REGION_28_29, MPCC_MCM, inst),\ - SRII(MPCC_MCM_1DLUT_RAMA_REGION_30_31, MPCC_MCM, inst),\ - SRII(MPCC_MCM_1DLUT_RAMA_REGION_32_33, MPCC_MCM, inst),\ - SRII(MPCC_MCM_1DLUT_RAMB_START_CNTL_B, MPCC_MCM, inst),\ - SRII(MPCC_MCM_1DLUT_RAMB_START_CNTL_G, MPCC_MCM, inst),\ - SRII(MPCC_MCM_1DLUT_RAMB_START_CNTL_R, MPCC_MCM, inst),\ - SRII(MPCC_MCM_1DLUT_RAMB_START_SLOPE_CNTL_B, MPCC_MCM, inst),\ - SRII(MPCC_MCM_1DLUT_RAMB_START_SLOPE_CNTL_G, MPCC_MCM, inst),\ - SRII(MPCC_MCM_1DLUT_RAMB_START_SLOPE_CNTL_R, MPCC_MCM, inst),\ - SRII(MPCC_MCM_1DLUT_RAMB_START_BASE_CNTL_B, MPCC_MCM, inst),\ - SRII(MPCC_MCM_1DLUT_RAMB_START_BASE_CNTL_G, MPCC_MCM, inst),\ - SRII(MPCC_MCM_1DLUT_RAMB_START_BASE_CNTL_R, MPCC_MCM, inst),\ - SRII(MPCC_MCM_1DLUT_RAMB_END_CNTL1_B, MPCC_MCM, inst),\ - SRII(MPCC_MCM_1DLUT_RAMB_END_CNTL2_B, MPCC_MCM, inst),\ - SRII(MPCC_MCM_1DLUT_RAMB_END_CNTL1_G, MPCC_MCM, inst),\ - SRII(MPCC_MCM_1DLUT_RAMB_END_CNTL2_G, MPCC_MCM, inst),\ - SRII(MPCC_MCM_1DLUT_RAMB_END_CNTL1_R, MPCC_MCM, inst),\ - SRII(MPCC_MCM_1DLUT_RAMB_END_CNTL2_R, MPCC_MCM, inst),\ - SRII(MPCC_MCM_1DLUT_RAMB_OFFSET_B, MPCC_MCM, inst),\ - SRII(MPCC_MCM_1DLUT_RAMB_OFFSET_G, MPCC_MCM, inst),\ - SRII(MPCC_MCM_1DLUT_RAMB_OFFSET_R, MPCC_MCM, inst),\ - SRII(MPCC_MCM_1DLUT_RAMB_REGION_0_1, MPCC_MCM, inst),\ - SRII(MPCC_MCM_1DLUT_RAMB_REGION_2_3, MPCC_MCM, inst),\ - SRII(MPCC_MCM_1DLUT_RAMB_REGION_4_5, MPCC_MCM, inst),\ - SRII(MPCC_MCM_1DLUT_RAMB_REGION_6_7, MPCC_MCM, inst),\ - SRII(MPCC_MCM_1DLUT_RAMB_REGION_8_9, MPCC_MCM, inst),\ - SRII(MPCC_MCM_1DLUT_RAMB_REGION_10_11, MPCC_MCM, inst),\ - SRII(MPCC_MCM_1DLUT_RAMB_REGION_12_13, MPCC_MCM, inst),\ - SRII(MPCC_MCM_1DLUT_RAMB_REGION_14_15, MPCC_MCM, inst),\ - SRII(MPCC_MCM_1DLUT_RAMB_REGION_16_17, MPCC_MCM, inst),\ - SRII(MPCC_MCM_1DLUT_RAMB_REGION_18_19, MPCC_MCM, inst),\ - SRII(MPCC_MCM_1DLUT_RAMB_REGION_20_21, MPCC_MCM, inst),\ - SRII(MPCC_MCM_1DLUT_RAMB_REGION_22_23, MPCC_MCM, inst),\ - SRII(MPCC_MCM_1DLUT_RAMB_REGION_24_25, MPCC_MCM, inst),\ - SRII(MPCC_MCM_1DLUT_RAMB_REGION_26_27, MPCC_MCM, inst),\ - SRII(MPCC_MCM_1DLUT_RAMB_REGION_28_29, MPCC_MCM, inst),\ - SRII(MPCC_MCM_1DLUT_RAMB_REGION_30_31, MPCC_MCM, inst),\ - SRII(MPCC_MCM_1DLUT_RAMB_REGION_32_33, MPCC_MCM, inst),\ - SRII(MPCC_MCM_MEM_PWR_CTRL, MPCC_MCM, inst) -/* OPTC */ - -#define OPTC_COMMON_REG_LIST_DCN3_2_RI(inst) \ - SRI_ARR(OTG_VSTARTUP_PARAM, OTG, inst), \ - SRI_ARR(OTG_VUPDATE_PARAM, OTG, inst), \ - SRI_ARR(OTG_VREADY_PARAM, OTG, inst), \ - SRI_ARR(OTG_MASTER_UPDATE_LOCK, OTG, inst), \ - SRI_ARR(OTG_GLOBAL_CONTROL0, OTG, inst), \ - SRI_ARR(OTG_GLOBAL_CONTROL1, OTG, inst), \ - SRI_ARR(OTG_GLOBAL_CONTROL2, OTG, inst), \ - SRI_ARR(OTG_GLOBAL_CONTROL4, OTG, inst), \ - SRI_ARR(OTG_DOUBLE_BUFFER_CONTROL, OTG, inst), \ - SRI_ARR(OTG_H_TOTAL, OTG, inst), \ - SRI_ARR(OTG_H_BLANK_START_END, OTG, inst), \ - SRI_ARR(OTG_H_SYNC_A, OTG, inst), SRI_ARR(OTG_H_SYNC_A_CNTL, OTG, inst), \ - SRI_ARR(OTG_H_TIMING_CNTL, OTG, inst), SRI_ARR(OTG_V_TOTAL, OTG, inst), \ - SRI_ARR(OTG_V_BLANK_START_END, OTG, inst), \ - SRI_ARR(OTG_V_SYNC_A, OTG, inst), SRI_ARR(OTG_V_SYNC_A_CNTL, OTG, inst), \ - SRI_ARR(OTG_CONTROL, OTG, inst), SRI_ARR(OTG_STEREO_CONTROL, OTG, inst), \ - SRI_ARR(OTG_3D_STRUCTURE_CONTROL, OTG, inst), \ - SRI_ARR(OTG_STEREO_STATUS, OTG, inst), \ - SRI_ARR(OTG_V_TOTAL_MAX, OTG, inst), \ - SRI_ARR(OTG_V_TOTAL_MIN, OTG, inst), \ - SRI_ARR(OTG_V_TOTAL_CONTROL, OTG, inst), \ - SRI_ARR(OTG_TRIGA_CNTL, OTG, inst), \ - SRI_ARR(OTG_FORCE_COUNT_NOW_CNTL, OTG, inst), \ - SRI_ARR(OTG_STATIC_SCREEN_CONTROL, OTG, inst), \ - SRI_ARR(OTG_STATUS_FRAME_COUNT, OTG, inst), \ - SRI_ARR(OTG_STATUS, OTG, inst), SRI_ARR(OTG_STATUS_POSITION, OTG, inst), \ - SRI_ARR(OTG_NOM_VERT_POSITION, OTG, inst), \ - SRI_ARR(OTG_M_CONST_DTO0, OTG, inst), \ - SRI_ARR(OTG_M_CONST_DTO1, OTG, inst), \ - SRI_ARR(OTG_CLOCK_CONTROL, OTG, inst), \ - SRI_ARR(OTG_VERTICAL_INTERRUPT0_CONTROL, OTG, inst), \ - SRI_ARR(OTG_VERTICAL_INTERRUPT0_POSITION, OTG, inst), \ - SRI_ARR(OTG_VERTICAL_INTERRUPT1_CONTROL, OTG, inst), \ - SRI_ARR(OTG_VERTICAL_INTERRUPT1_POSITION, OTG, inst), \ - SRI_ARR(OTG_VERTICAL_INTERRUPT2_CONTROL, OTG, inst), \ - SRI_ARR(OTG_VERTICAL_INTERRUPT2_POSITION, OTG, inst), \ - SRI_ARR(OPTC_INPUT_CLOCK_CONTROL, ODM, inst), \ - SRI_ARR(OPTC_DATA_SOURCE_SELECT, ODM, inst), \ - SRI_ARR(OPTC_INPUT_GLOBAL_CONTROL, ODM, inst), \ - SRI_ARR(CONTROL, VTG, inst), SRI_ARR(OTG_VERT_SYNC_CONTROL, OTG, inst), \ - SRI_ARR(OTG_GSL_CONTROL, OTG, inst), SRI_ARR(OTG_CRC_CNTL, OTG, inst), \ - SRI_ARR(OTG_CRC0_DATA_RG, OTG, inst), \ - SRI_ARR(OTG_CRC0_DATA_B, OTG, inst), \ - SRI_ARR(OTG_CRC0_WINDOWA_X_CONTROL, OTG, inst), \ - SRI_ARR(OTG_CRC0_WINDOWA_Y_CONTROL, OTG, inst), \ - SRI_ARR(OTG_CRC0_WINDOWB_X_CONTROL, OTG, inst), \ - SRI_ARR(OTG_CRC0_WINDOWB_Y_CONTROL, OTG, inst), \ - SR_ARR(GSL_SOURCE_SELECT, inst), \ - SRI_ARR(OTG_TRIGA_MANUAL_TRIG, OTG, inst), \ - SRI_ARR(OTG_GLOBAL_CONTROL1, OTG, inst), \ - SRI_ARR(OTG_GLOBAL_CONTROL2, OTG, inst), \ - SRI_ARR(OTG_GSL_WINDOW_X, OTG, inst), \ - SRI_ARR(OTG_GSL_WINDOW_Y, OTG, inst), \ - SRI_ARR(OTG_VUPDATE_KEEPOUT, OTG, inst), \ - SRI_ARR(OTG_DSC_START_POSITION, OTG, inst), \ - SRI_ARR(OTG_DRR_TRIGGER_WINDOW, OTG, inst), \ - SRI_ARR(OTG_DRR_V_TOTAL_CHANGE, OTG, inst), \ - SRI_ARR(OPTC_DATA_FORMAT_CONTROL, ODM, inst), \ - SRI_ARR(OPTC_BYTES_PER_PIXEL, ODM, inst), \ - SRI_ARR(OPTC_WIDTH_CONTROL, ODM, inst), \ - SRI_ARR(OPTC_MEMORY_CONFIG, ODM, inst), \ - SRI_ARR(OTG_DRR_CONTROL, OTG, inst) - -/* HUBP */ - -#define HUBP_REG_LIST_DCN_VM_RI(id) \ - SRI_ARR(NOM_PARAMETERS_0, HUBPREQ, id), \ - SRI_ARR(NOM_PARAMETERS_1, HUBPREQ, id), \ - SRI_ARR(NOM_PARAMETERS_2, HUBPREQ, id), \ - SRI_ARR(NOM_PARAMETERS_3, HUBPREQ, id), \ - SRI_ARR(DCN_VM_MX_L1_TLB_CNTL, HUBPREQ, id) -#define HUBP_REG_LIST_DCN_RI(id) \ - SRI_ARR(DCHUBP_CNTL, HUBP, id), SRI_ARR(HUBPREQ_DEBUG_DB, HUBP, id), \ - SRI_ARR(HUBPREQ_DEBUG, HUBP, id), SRI_ARR(DCSURF_ADDR_CONFIG, HUBP, id), \ - SRI_ARR(DCSURF_TILING_CONFIG, HUBP, id), \ - SRI_ARR(DCSURF_SURFACE_PITCH, HUBPREQ, id), \ - SRI_ARR(DCSURF_SURFACE_PITCH_C, HUBPREQ, id), \ - SRI_ARR(DCSURF_SURFACE_CONFIG, HUBP, id), \ - SRI_ARR(DCSURF_FLIP_CONTROL, HUBPREQ, id), \ - SRI_ARR(DCSURF_PRI_VIEWPORT_DIMENSION, HUBP, id), \ - SRI_ARR(DCSURF_PRI_VIEWPORT_START, HUBP, id), \ - SRI_ARR(DCSURF_SEC_VIEWPORT_DIMENSION, HUBP, id), \ - SRI_ARR(DCSURF_SEC_VIEWPORT_START, HUBP, id), \ - SRI_ARR(DCSURF_PRI_VIEWPORT_DIMENSION_C, HUBP, id), \ - SRI_ARR(DCSURF_PRI_VIEWPORT_START_C, HUBP, id), \ - SRI_ARR(DCSURF_SEC_VIEWPORT_DIMENSION_C, HUBP, id), \ - SRI_ARR(DCSURF_SEC_VIEWPORT_START_C, HUBP, id), \ - SRI_ARR(DCSURF_PRIMARY_SURFACE_ADDRESS_HIGH, HUBPREQ, id), \ - SRI_ARR(DCSURF_PRIMARY_SURFACE_ADDRESS, HUBPREQ, id), \ - SRI_ARR(DCSURF_SECONDARY_SURFACE_ADDRESS_HIGH, HUBPREQ, id), \ - SRI_ARR(DCSURF_SECONDARY_SURFACE_ADDRESS, HUBPREQ, id), \ - SRI_ARR(DCSURF_PRIMARY_META_SURFACE_ADDRESS_HIGH, HUBPREQ, id), \ - SRI_ARR(DCSURF_PRIMARY_META_SURFACE_ADDRESS, HUBPREQ, id), \ - SRI_ARR(DCSURF_SECONDARY_META_SURFACE_ADDRESS_HIGH, HUBPREQ, id), \ - SRI_ARR(DCSURF_SECONDARY_META_SURFACE_ADDRESS, HUBPREQ, id), \ - SRI_ARR(DCSURF_PRIMARY_SURFACE_ADDRESS_HIGH_C, HUBPREQ, id), \ - SRI_ARR(DCSURF_PRIMARY_SURFACE_ADDRESS_C, HUBPREQ, id), \ - SRI_ARR(DCSURF_SECONDARY_SURFACE_ADDRESS_HIGH_C, HUBPREQ, id), \ - SRI_ARR(DCSURF_SECONDARY_SURFACE_ADDRESS_C, HUBPREQ, id), \ - SRI_ARR(DCSURF_PRIMARY_META_SURFACE_ADDRESS_HIGH_C, HUBPREQ, id), \ - SRI_ARR(DCSURF_PRIMARY_META_SURFACE_ADDRESS_C, HUBPREQ, id), \ - SRI_ARR(DCSURF_SECONDARY_META_SURFACE_ADDRESS_HIGH_C, HUBPREQ, id), \ - SRI_ARR(DCSURF_SECONDARY_META_SURFACE_ADDRESS_C, HUBPREQ, id), \ - SRI_ARR(DCSURF_SURFACE_INUSE, HUBPREQ, id), \ - SRI_ARR(DCSURF_SURFACE_INUSE_HIGH, HUBPREQ, id), \ - SRI_ARR(DCSURF_SURFACE_INUSE_C, HUBPREQ, id), \ - SRI_ARR(DCSURF_SURFACE_INUSE_HIGH_C, HUBPREQ, id), \ - SRI_ARR(DCSURF_SURFACE_EARLIEST_INUSE, HUBPREQ, id), \ - SRI_ARR(DCSURF_SURFACE_EARLIEST_INUSE_HIGH, HUBPREQ, id), \ - SRI_ARR(DCSURF_SURFACE_EARLIEST_INUSE_C, HUBPREQ, id), \ - SRI_ARR(DCSURF_SURFACE_EARLIEST_INUSE_HIGH_C, HUBPREQ, id), \ - SRI_ARR(DCSURF_SURFACE_CONTROL, HUBPREQ, id), \ - SRI_ARR(DCSURF_SURFACE_FLIP_INTERRUPT, HUBPREQ, id), \ - SRI_ARR(HUBPRET_CONTROL, HUBPRET, id), \ - SRI_ARR(HUBPRET_READ_LINE_STATUS, HUBPRET, id), \ - SRI_ARR(DCN_EXPANSION_MODE, HUBPREQ, id), \ - SRI_ARR(DCHUBP_REQ_SIZE_CONFIG, HUBP, id), \ - SRI_ARR(DCHUBP_REQ_SIZE_CONFIG_C, HUBP, id), \ - SRI_ARR(BLANK_OFFSET_0, HUBPREQ, id), \ - SRI_ARR(BLANK_OFFSET_1, HUBPREQ, id), \ - SRI_ARR(DST_DIMENSIONS, HUBPREQ, id), \ - SRI_ARR(DST_AFTER_SCALER, HUBPREQ, id), \ - SRI_ARR(VBLANK_PARAMETERS_0, HUBPREQ, id), \ - SRI_ARR(REF_FREQ_TO_PIX_FREQ, HUBPREQ, id), \ - SRI_ARR(VBLANK_PARAMETERS_1, HUBPREQ, id), \ - SRI_ARR(VBLANK_PARAMETERS_3, HUBPREQ, id), \ - SRI_ARR(NOM_PARAMETERS_4, HUBPREQ, id), \ - SRI_ARR(NOM_PARAMETERS_5, HUBPREQ, id), \ - SRI_ARR(PER_LINE_DELIVERY_PRE, HUBPREQ, id), \ - SRI_ARR(PER_LINE_DELIVERY, HUBPREQ, id), \ - SRI_ARR(VBLANK_PARAMETERS_2, HUBPREQ, id), \ - SRI_ARR(VBLANK_PARAMETERS_4, HUBPREQ, id), \ - SRI_ARR(NOM_PARAMETERS_6, HUBPREQ, id), \ - SRI_ARR(NOM_PARAMETERS_7, HUBPREQ, id), \ - SRI_ARR(DCN_TTU_QOS_WM, HUBPREQ, id), \ - SRI_ARR(DCN_GLOBAL_TTU_CNTL, HUBPREQ, id), \ - SRI_ARR(DCN_SURF0_TTU_CNTL0, HUBPREQ, id), \ - SRI_ARR(DCN_SURF0_TTU_CNTL1, HUBPREQ, id), \ - SRI_ARR(DCN_SURF1_TTU_CNTL0, HUBPREQ, id), \ - SRI_ARR(DCN_SURF1_TTU_CNTL1, HUBPREQ, id), \ - SRI_ARR(DCN_CUR0_TTU_CNTL0, HUBPREQ, id), \ - SRI_ARR(DCN_CUR0_TTU_CNTL1, HUBPREQ, id), \ - SRI_ARR(HUBP_CLK_CNTL, HUBP, id) -#define HUBP_REG_LIST_DCN2_COMMON_RI(id) \ - HUBP_REG_LIST_DCN_RI(id), HUBP_REG_LIST_DCN_VM_RI(id), \ - SRI_ARR(PREFETCH_SETTINGS, HUBPREQ, id), \ - SRI_ARR(PREFETCH_SETTINGS_C, HUBPREQ, id), \ - SRI_ARR(DCN_VM_SYSTEM_APERTURE_LOW_ADDR, HUBPREQ, id), \ - SRI_ARR(DCN_VM_SYSTEM_APERTURE_HIGH_ADDR, HUBPREQ, id), \ - SRI_ARR(CURSOR_SETTINGS, HUBPREQ, id), \ - SRI_ARR(CURSOR_SURFACE_ADDRESS_HIGH, CURSOR0_, id), \ - SRI_ARR(CURSOR_SURFACE_ADDRESS, CURSOR0_, id), \ - SRI_ARR(CURSOR_SIZE, CURSOR0_, id), \ - SRI_ARR(CURSOR_CONTROL, CURSOR0_, id), \ - SRI_ARR(CURSOR_POSITION, CURSOR0_, id), \ - SRI_ARR(CURSOR_HOT_SPOT, CURSOR0_, id), \ - SRI_ARR(CURSOR_DST_OFFSET, CURSOR0_, id), \ - SRI_ARR(DMDATA_ADDRESS_HIGH, CURSOR0_, id), \ - SRI_ARR(DMDATA_ADDRESS_LOW, CURSOR0_, id), \ - SRI_ARR(DMDATA_CNTL, CURSOR0_, id), \ - SRI_ARR(DMDATA_SW_CNTL, CURSOR0_, id), \ - SRI_ARR(DMDATA_QOS_CNTL, CURSOR0_, id), \ - SRI_ARR(DMDATA_SW_DATA, CURSOR0_, id), \ - SRI_ARR(DMDATA_STATUS, CURSOR0_, id), \ - SRI_ARR(FLIP_PARAMETERS_0, HUBPREQ, id), \ - SRI_ARR(FLIP_PARAMETERS_1, HUBPREQ, id), \ - SRI_ARR(FLIP_PARAMETERS_2, HUBPREQ, id), \ - SRI_ARR(DCN_CUR1_TTU_CNTL0, HUBPREQ, id), \ - SRI_ARR(DCN_CUR1_TTU_CNTL1, HUBPREQ, id), \ - SRI_ARR(DCSURF_FLIP_CONTROL2, HUBPREQ, id), \ - SRI_ARR(VMID_SETTINGS_0, HUBPREQ, id) -#define HUBP_REG_LIST_DCN21_RI(id) \ - HUBP_REG_LIST_DCN2_COMMON_RI(id), SRI_ARR(FLIP_PARAMETERS_3, HUBPREQ, id), \ - SRI_ARR(FLIP_PARAMETERS_4, HUBPREQ, id), \ - SRI_ARR(FLIP_PARAMETERS_5, HUBPREQ, id), \ - SRI_ARR(FLIP_PARAMETERS_6, HUBPREQ, id), \ - SRI_ARR(VBLANK_PARAMETERS_5, HUBPREQ, id), \ - SRI_ARR(VBLANK_PARAMETERS_6, HUBPREQ, id) -#define HUBP_REG_LIST_DCN30_RI(id) \ - HUBP_REG_LIST_DCN21_RI(id), SRI_ARR(DCN_DMDATA_VM_CNTL, HUBPREQ, id) -#define HUBP_REG_LIST_DCN32_RI(id) \ - HUBP_REG_LIST_DCN30_RI(id), SRI_ARR(DCHUBP_MALL_CONFIG, HUBP, id), \ - SRI_ARR(DCHUBP_VMPG_CONFIG, HUBP, id), \ - SRI_ARR(UCLK_PSTATE_FORCE, HUBPREQ, id) - -/* HUBBUB */ - -#define HUBBUB_REG_LIST_DCN32_RI(id) \ - SR(DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_A), \ - SR(DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_B), \ - SR(DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_C), \ - SR(DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_D), \ - SR(DCHUBBUB_ARB_WATERMARK_CHANGE_CNTL), \ - SR(DCHUBBUB_ARB_DRAM_STATE_CNTL), SR(DCHUBBUB_ARB_SAT_LEVEL), \ - SR(DCHUBBUB_ARB_DF_REQ_OUTSTAND), SR(DCHUBBUB_GLOBAL_TIMER_CNTL), \ - SR(DCHUBBUB_SOFT_RESET), SR(DCHUBBUB_CRC_CTRL), \ - SR(DCN_VM_FB_LOCATION_BASE), SR(DCN_VM_FB_LOCATION_TOP), \ - SR(DCN_VM_FB_OFFSET), SR(DCN_VM_AGP_BOT), SR(DCN_VM_AGP_TOP), \ - SR(DCN_VM_AGP_BASE), HUBBUB_SR_WATERMARK_REG_LIST(), \ - SR(DCHUBBUB_ARB_FRAC_URG_BW_NOM_A), SR(DCHUBBUB_ARB_FRAC_URG_BW_NOM_B), \ - SR(DCHUBBUB_ARB_FRAC_URG_BW_NOM_C), SR(DCHUBBUB_ARB_FRAC_URG_BW_NOM_D), \ - SR(DCHUBBUB_ARB_FRAC_URG_BW_FLIP_A), \ - SR(DCHUBBUB_ARB_FRAC_URG_BW_FLIP_B), \ - SR(DCHUBBUB_ARB_FRAC_URG_BW_FLIP_C), \ - SR(DCHUBBUB_ARB_FRAC_URG_BW_FLIP_D), \ - SR(DCHUBBUB_ARB_REFCYC_PER_TRIP_TO_MEMORY_A), \ - SR(DCHUBBUB_ARB_REFCYC_PER_TRIP_TO_MEMORY_B), \ - SR(DCHUBBUB_ARB_REFCYC_PER_TRIP_TO_MEMORY_C), \ - SR(DCHUBBUB_ARB_REFCYC_PER_TRIP_TO_MEMORY_D), SR(DCHUBBUB_DET0_CTRL), \ - SR(DCHUBBUB_DET1_CTRL), SR(DCHUBBUB_DET2_CTRL), SR(DCHUBBUB_DET3_CTRL), \ - SR(DCHUBBUB_COMPBUF_CTRL), SR(COMPBUF_RESERVED_SPACE), \ - SR(DCHUBBUB_DEBUG_CTRL_0), \ - SR(DCHUBBUB_ARB_USR_RETRAINING_CNTL), \ - SR(DCHUBBUB_ARB_USR_RETRAINING_WATERMARK_A), \ - SR(DCHUBBUB_ARB_USR_RETRAINING_WATERMARK_B), \ - SR(DCHUBBUB_ARB_USR_RETRAINING_WATERMARK_C), \ - SR(DCHUBBUB_ARB_USR_RETRAINING_WATERMARK_D), \ - SR(DCHUBBUB_ARB_UCLK_PSTATE_CHANGE_WATERMARK_A), \ - SR(DCHUBBUB_ARB_UCLK_PSTATE_CHANGE_WATERMARK_B), \ - SR(DCHUBBUB_ARB_UCLK_PSTATE_CHANGE_WATERMARK_C), \ - SR(DCHUBBUB_ARB_UCLK_PSTATE_CHANGE_WATERMARK_D), \ - SR(DCHUBBUB_ARB_FCLK_PSTATE_CHANGE_WATERMARK_A), \ - SR(DCHUBBUB_ARB_FCLK_PSTATE_CHANGE_WATERMARK_B), \ - SR(DCHUBBUB_ARB_FCLK_PSTATE_CHANGE_WATERMARK_C), \ - SR(DCHUBBUB_ARB_FCLK_PSTATE_CHANGE_WATERMARK_D), \ - SR(DCHUBBUB_ARB_MALL_CNTL), \ - SR(DCN_VM_FAULT_ADDR_MSB), SR(DCN_VM_FAULT_ADDR_LSB), \ - SR(DCN_VM_FAULT_CNTL), SR(DCN_VM_FAULT_STATUS), \ - SR(SDPIF_REQUEST_RATE_LIMIT) - -/* DCCG */ - -#define DCCG_REG_LIST_DCN32_RI() \ - SR(DPPCLK_DTO_CTRL), DCCG_SRII(DTO_PARAM, DPPCLK, 0), \ - DCCG_SRII(DTO_PARAM, DPPCLK, 1), DCCG_SRII(DTO_PARAM, DPPCLK, 2), \ - DCCG_SRII(DTO_PARAM, DPPCLK, 3), DCCG_SRII(CLOCK_CNTL, HDMICHARCLK, 0), \ - SR(PHYASYMCLK_CLOCK_CNTL), SR(PHYBSYMCLK_CLOCK_CNTL), \ - SR(PHYCSYMCLK_CLOCK_CNTL), SR(PHYDSYMCLK_CLOCK_CNTL), \ - SR(PHYESYMCLK_CLOCK_CNTL), SR(DPSTREAMCLK_CNTL), SR(HDMISTREAMCLK_CNTL), \ - SR(SYMCLK32_SE_CNTL), SR(SYMCLK32_LE_CNTL), \ - DCCG_SRII(PIXEL_RATE_CNTL, OTG, 0), DCCG_SRII(PIXEL_RATE_CNTL, OTG, 1), \ - DCCG_SRII(PIXEL_RATE_CNTL, OTG, 2), DCCG_SRII(PIXEL_RATE_CNTL, OTG, 3), \ - DCCG_SRII(MODULO, DTBCLK_DTO, 0), DCCG_SRII(MODULO, DTBCLK_DTO, 1), \ - DCCG_SRII(MODULO, DTBCLK_DTO, 2), DCCG_SRII(MODULO, DTBCLK_DTO, 3), \ - DCCG_SRII(PHASE, DTBCLK_DTO, 0), DCCG_SRII(PHASE, DTBCLK_DTO, 1), \ - DCCG_SRII(PHASE, DTBCLK_DTO, 2), DCCG_SRII(PHASE, DTBCLK_DTO, 3), \ - SR(DCCG_AUDIO_DTBCLK_DTO_MODULO), SR(DCCG_AUDIO_DTBCLK_DTO_PHASE), \ - SR(OTG_PIXEL_RATE_DIV), SR(DTBCLK_P_CNTL), \ - SR(DCCG_AUDIO_DTO_SOURCE), SR(DENTIST_DISPCLK_CNTL) - -/* VMID */ -#define DCN20_VMID_REG_LIST_RI(id) \ - SRI_ARR(CNTL, DCN_VM_CONTEXT, id), \ - SRI_ARR(PAGE_TABLE_BASE_ADDR_HI32, DCN_VM_CONTEXT, id), \ - SRI_ARR(PAGE_TABLE_BASE_ADDR_LO32, DCN_VM_CONTEXT, id), \ - SRI_ARR(PAGE_TABLE_START_ADDR_HI32, DCN_VM_CONTEXT, id), \ - SRI_ARR(PAGE_TABLE_START_ADDR_LO32, DCN_VM_CONTEXT, id), \ - SRI_ARR(PAGE_TABLE_END_ADDR_HI32, DCN_VM_CONTEXT, id), \ - SRI_ARR(PAGE_TABLE_END_ADDR_LO32, DCN_VM_CONTEXT, id) - -/* I2C HW */ - -#define I2C_HW_ENGINE_COMMON_REG_LIST_RI(id) \ - SRI_ARR_I2C(SETUP, DC_I2C_DDC, id), SRI_ARR_I2C(SPEED, DC_I2C_DDC, id), \ - SRI_ARR_I2C(HW_STATUS, DC_I2C_DDC, id), \ - SR_ARR_I2C(DC_I2C_ARBITRATION, id), \ - SR_ARR_I2C(DC_I2C_CONTROL, id), SR_ARR_I2C(DC_I2C_SW_STATUS, id), \ - SR_ARR_I2C(DC_I2C_TRANSACTION0, id), SR_ARR_I2C(DC_I2C_TRANSACTION1, id),\ - SR_ARR_I2C(DC_I2C_TRANSACTION2, id), SR_ARR_I2C(DC_I2C_TRANSACTION3, id),\ - SR_ARR_I2C(DC_I2C_DATA, id), SR_ARR_I2C(MICROSECOND_TIME_BASE_DIV, id) - -#define I2C_HW_ENGINE_COMMON_REG_LIST_DCN30_RI(id) \ - I2C_HW_ENGINE_COMMON_REG_LIST_RI(id), SR_ARR_I2C(DIO_MEM_PWR_CTRL, id), \ - SR_ARR_I2C(DIO_MEM_PWR_STATUS, id) - -#endif /* _DCN32_RESOURCE_H_ */ diff --git a/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_resource_helpers.c b/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_resource_helpers.c index bc5f0db23d0c..ef0a2b01734d 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_resource_helpers.c +++ b/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_resource_helpers.c @@ -24,7 +24,7 @@ */ // header file of functions being implemented -#include "dcn32_resource.h" +#include "dcn32/dcn32_resource.h" #include "dcn20/dcn20_resource.h" #include "dml/dcn32/display_mode_vba_util_32.h" #include "dml/dcn32/dcn32_fpu.h" diff --git a/drivers/gpu/drm/amd/display/dc/dcn321/Makefile b/drivers/gpu/drm/amd/display/dc/dcn321/Makefile index 0a199c83bb5b..c195c47f58b4 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn321/Makefile +++ b/drivers/gpu/drm/amd/display/dc/dcn321/Makefile @@ -10,7 +10,7 @@ # # Makefile for dcn321. -DCN321 = dcn321_resource.o dcn321_dio_link_encoder.o +DCN321 = dcn321_dio_link_encoder.o AMD_DAL_DCN321 = $(addprefix $(AMDDALPATH)/dc/dcn321/,$(DCN321)) diff --git a/drivers/gpu/drm/amd/display/dc/dcn321/dcn321_resource.c b/drivers/gpu/drm/amd/display/dc/dcn321/dcn321_resource.c deleted file mode 100644 index f7de3eca1225..000000000000 --- a/drivers/gpu/drm/amd/display/dc/dcn321/dcn321_resource.c +++ /dev/null @@ -1,2065 +0,0 @@ -// SPDX-License-Identifier: MIT -/* - * 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 - * - */ - -#include "dm_services.h" -#include "dc.h" - -#include "dcn32/dcn32_init.h" - -#include "resource.h" -#include "include/irq_service_interface.h" -#include "dcn32/dcn32_resource.h" -#include "dcn321_resource.h" - -#include "dcn20/dcn20_resource.h" -#include "dcn30/dcn30_resource.h" - -#include "dml/dcn321/dcn321_fpu.h" - -#include "dcn10/dcn10_ipp.h" -#include "dcn30/dcn30_hubbub.h" -#include "dcn31/dcn31_hubbub.h" -#include "dcn32/dcn32_hubbub.h" -#include "dcn32/dcn32_mpc.h" -#include "dcn32/dcn32_hubp.h" -#include "irq/dcn32/irq_service_dcn32.h" -#include "dcn32/dcn32_dpp.h" -#include "dcn32/dcn32_optc.h" -#include "dcn20/dcn20_hwseq.h" -#include "dcn30/dcn30_hwseq.h" -#include "dce110/dce110_hwseq.h" -#include "dcn30/dcn30_opp.h" -#include "dcn20/dcn20_dsc.h" -#include "dcn30/dcn30_vpg.h" -#include "dcn30/dcn30_afmt.h" -#include "dcn30/dcn30_dio_stream_encoder.h" -#include "dcn32/dcn32_dio_stream_encoder.h" -#include "dcn31/dcn31_hpo_dp_stream_encoder.h" -#include "dcn31/dcn31_hpo_dp_link_encoder.h" -#include "dcn32/dcn32_hpo_dp_link_encoder.h" -#include "dcn31/dcn31_apg.h" -#include "dcn31/dcn31_dio_link_encoder.h" -#include "dcn32/dcn32_dio_link_encoder.h" -#include "dcn321_dio_link_encoder.h" -#include "dce/dce_clock_source.h" -#include "dce/dce_audio.h" -#include "dce/dce_hwseq.h" -#include "clk_mgr.h" -#include "virtual/virtual_stream_encoder.h" -#include "dml/display_mode_vba.h" -#include "dcn32/dcn32_dccg.h" -#include "dcn10/dcn10_resource.h" -#include "link.h" -#include "dcn31/dcn31_panel_cntl.h" - -#include "dcn30/dcn30_dwb.h" -#include "dcn32/dcn32_mmhubbub.h" - -#include "dcn/dcn_3_2_1_offset.h" -#include "dcn/dcn_3_2_1_sh_mask.h" -#include "nbio/nbio_4_3_0_offset.h" - -#include "reg_helper.h" -#include "dce/dmub_abm.h" -#include "dce/dmub_psr.h" -#include "dce/dce_aux.h" -#include "dce/dce_i2c.h" - -#include "dml/dcn30/display_mode_vba_30.h" -#include "vm_helper.h" -#include "dcn20/dcn20_vmid.h" - -#define DC_LOGGER_INIT(logger) - -enum dcn321_clk_src_array_id { - DCN321_CLK_SRC_PLL0, - DCN321_CLK_SRC_PLL1, - DCN321_CLK_SRC_PLL2, - DCN321_CLK_SRC_PLL3, - DCN321_CLK_SRC_PLL4, - DCN321_CLK_SRC_TOTAL -}; - -/* begin ********************* - * macros to expend register list macro defined in HW object header file - */ - -/* DCN */ -#define BASE_INNER(seg) ctx->dcn_reg_offsets[seg] - -#define BASE(seg) BASE_INNER(seg) - -#define SR(reg_name)\ - REG_STRUCT.reg_name = BASE(reg ## reg_name ## _BASE_IDX) + \ - reg ## reg_name -#define SR_ARR(reg_name, id)\ - REG_STRUCT[id].reg_name = BASE(reg ## reg_name ## _BASE_IDX) + \ - reg ## reg_name -#define SR_ARR_INIT(reg_name, id, value)\ - REG_STRUCT[id].reg_name = value - -#define SRI(reg_name, block, id)\ - REG_STRUCT.reg_name = BASE(reg ## block ## id ## _ ## reg_name ## _BASE_IDX) + \ - reg ## block ## id ## _ ## reg_name - -#define SRI_ARR(reg_name, block, id)\ - REG_STRUCT[id].reg_name = BASE(reg ## block ## id ## _ ## reg_name ## _BASE_IDX) + \ - reg ## block ## id ## _ ## reg_name - -#define SR_ARR_I2C(reg_name, id) \ - REG_STRUCT[id-1].reg_name = BASE(reg##reg_name##_BASE_IDX) + reg##reg_name - -#define SRI_ARR_I2C(reg_name, block, id)\ - REG_STRUCT[id-1].reg_name = BASE(reg ## block ## id ## _ ## reg_name ## _BASE_IDX) + \ - reg ## block ## id ## _ ## reg_name - -#define SRI_ARR_ALPHABET(reg_name, block, index, id)\ - REG_STRUCT[index].reg_name = BASE(reg ## block ## id ## _ ## reg_name ## _BASE_IDX) + \ - reg ## block ## id ## _ ## reg_name - -#define SRI2(reg_name, block, id)\ - .reg_name = BASE(reg ## reg_name ## _BASE_IDX) + \ - reg ## reg_name -#define SRI2_ARR(reg_name, block, id)\ - REG_STRUCT[id].reg_name = BASE(reg ## reg_name ## _BASE_IDX) + \ - reg ## reg_name - -#define SRIR(var_name, reg_name, block, id)\ - .var_name = BASE(reg ## block ## id ## _ ## reg_name ## _BASE_IDX) + \ - reg ## block ## id ## _ ## reg_name - -#define SRII(reg_name, block, id)\ - REG_STRUCT.reg_name[id] = BASE(reg ## block ## id ## _ ## reg_name ## _BASE_IDX) + \ - reg ## block ## id ## _ ## reg_name - -#define SRII_ARR_2(reg_name, block, id, inst)\ - REG_STRUCT[inst].reg_name[id] = BASE(reg ## block ## id ## _ ## reg_name ## _BASE_IDX) + \ - reg ## block ## id ## _ ## reg_name - -#define SRII_MPC_RMU(reg_name, block, id)\ - .RMU##_##reg_name[id] = BASE(reg ## block ## id ## _ ## reg_name ## _BASE_IDX) + \ - reg ## block ## id ## _ ## reg_name - -#define SRII_DWB(reg_name, temp_name, block, id)\ - REG_STRUCT.reg_name[id] = BASE(reg ## block ## id ## _ ## temp_name ## _BASE_IDX) + \ - reg ## block ## id ## _ ## temp_name - -#define DCCG_SRII(reg_name, block, id)\ - REG_STRUCT.block ## _ ## reg_name[id] = BASE(reg ## block ## id ## _ ## reg_name ## _BASE_IDX) + \ - reg ## block ## id ## _ ## reg_name - -#define SF_DWB2(reg_name, block, id, field_name, post_fix) \ - .field_name = reg_name ## __ ## field_name ## post_fix - -#define VUPDATE_SRII(reg_name, block, id)\ - REG_STRUCT.reg_name[id] = BASE(reg ## reg_name ## _ ## block ## id ## _BASE_IDX) + \ - reg ## reg_name ## _ ## block ## id - -/* NBIO */ -#define NBIO_BASE_INNER(seg) ctx->nbio_reg_offsets[seg] - -#define NBIO_BASE(seg) \ - NBIO_BASE_INNER(seg) - -#define NBIO_SR(reg_name)\ - REG_STRUCT.reg_name = NBIO_BASE(regBIF_BX0_ ## reg_name ## _BASE_IDX) + \ - regBIF_BX0_ ## reg_name -#define NBIO_SR_ARR(reg_name, id)\ - REG_STRUCT[id].reg_name = NBIO_BASE(regBIF_BX0_ ## reg_name ## _BASE_IDX) + \ - regBIF_BX0_ ## reg_name - -#define CTX ctx -#define REG(reg_name) \ - (ctx->dcn_reg_offsets[reg ## reg_name ## _BASE_IDX] + reg ## reg_name) - -static struct bios_registers bios_regs; - -#define bios_regs_init() \ - ( \ - NBIO_SR(BIOS_SCRATCH_3),\ - NBIO_SR(BIOS_SCRATCH_6)\ - ) - -#define clk_src_regs_init(index, pllid)\ - CS_COMMON_REG_LIST_DCN3_0_RI(index, pllid) - -static struct dce110_clk_src_regs clk_src_regs[5]; - -static const struct dce110_clk_src_shift cs_shift = { - CS_COMMON_MASK_SH_LIST_DCN3_2(__SHIFT) -}; - -static const struct dce110_clk_src_mask cs_mask = { - CS_COMMON_MASK_SH_LIST_DCN3_2(_MASK) -}; - -#define abm_regs_init(id)\ - ABM_DCN32_REG_LIST_RI(id) - -static struct dce_abm_registers abm_regs[4]; - -static const struct dce_abm_shift abm_shift = { - ABM_MASK_SH_LIST_DCN32(__SHIFT) -}; - -static const struct dce_abm_mask abm_mask = { - ABM_MASK_SH_LIST_DCN32(_MASK) -}; - -#define audio_regs_init(id)\ - AUD_COMMON_REG_LIST_RI(id) - -static struct dce_audio_registers audio_regs[5]; - -#define DCE120_AUD_COMMON_MASK_SH_LIST(mask_sh)\ - SF(AZF0ENDPOINT0_AZALIA_F0_CODEC_ENDPOINT_INDEX, AZALIA_ENDPOINT_REG_INDEX, mask_sh),\ - SF(AZF0ENDPOINT0_AZALIA_F0_CODEC_ENDPOINT_DATA, AZALIA_ENDPOINT_REG_DATA, mask_sh),\ - AUD_COMMON_MASK_SH_LIST_BASE(mask_sh) - -static const struct dce_audio_shift audio_shift = { - DCE120_AUD_COMMON_MASK_SH_LIST(__SHIFT) -}; - -static const struct dce_audio_mask audio_mask = { - DCE120_AUD_COMMON_MASK_SH_LIST(_MASK) -}; - -#define vpg_regs_init(id)\ - VPG_DCN3_REG_LIST_RI(id) - -static struct dcn30_vpg_registers vpg_regs[10]; - -static const struct dcn30_vpg_shift vpg_shift = { - DCN3_VPG_MASK_SH_LIST(__SHIFT) -}; - -static const struct dcn30_vpg_mask vpg_mask = { - DCN3_VPG_MASK_SH_LIST(_MASK) -}; - -#define afmt_regs_init(id)\ - AFMT_DCN3_REG_LIST_RI(id) - -static struct dcn30_afmt_registers afmt_regs[6]; - -static const struct dcn30_afmt_shift afmt_shift = { - DCN3_AFMT_MASK_SH_LIST(__SHIFT) -}; - -static const struct dcn30_afmt_mask afmt_mask = { - DCN3_AFMT_MASK_SH_LIST(_MASK) -}; - -#define apg_regs_init(id)\ - APG_DCN31_REG_LIST_RI(id) - -static struct dcn31_apg_registers apg_regs[4]; - -static const struct dcn31_apg_shift apg_shift = { - DCN31_APG_MASK_SH_LIST(__SHIFT) -}; - -static const struct dcn31_apg_mask apg_mask = { - DCN31_APG_MASK_SH_LIST(_MASK) -}; - -#define stream_enc_regs_init(id)\ - SE_DCN32_REG_LIST_RI(id) - -static struct dcn10_stream_enc_registers stream_enc_regs[5]; - -static const struct dcn10_stream_encoder_shift se_shift = { - SE_COMMON_MASK_SH_LIST_DCN32(__SHIFT) -}; - -static const struct dcn10_stream_encoder_mask se_mask = { - SE_COMMON_MASK_SH_LIST_DCN32(_MASK) -}; - - -#define aux_regs_init(id)\ - DCN2_AUX_REG_LIST_RI(id) - -static struct dcn10_link_enc_aux_registers link_enc_aux_regs[5]; - -#define hpd_regs_init(id)\ - HPD_REG_LIST_RI(id) - -static struct dcn10_link_enc_hpd_registers link_enc_hpd_regs[5]; - -#define link_regs_init(id, phyid)\ - ( \ - LE_DCN31_REG_LIST_RI(id), \ - UNIPHY_DCN2_REG_LIST_RI(id, phyid)\ - ) - /*DPCS_DCN31_REG_LIST(id),*/ \ - -static struct dcn10_link_enc_registers link_enc_regs[5]; - -static const struct dcn10_link_enc_shift le_shift = { - LINK_ENCODER_MASK_SH_LIST_DCN31(__SHIFT), \ -// DPCS_DCN31_MASK_SH_LIST(__SHIFT) -}; - -static const struct dcn10_link_enc_mask le_mask = { - LINK_ENCODER_MASK_SH_LIST_DCN31(_MASK), \ -// DPCS_DCN31_MASK_SH_LIST(_MASK) -}; - -#define hpo_dp_stream_encoder_reg_init(id)\ - DCN3_1_HPO_DP_STREAM_ENC_REG_LIST_RI(id) - -static struct dcn31_hpo_dp_stream_encoder_registers hpo_dp_stream_enc_regs[4]; - -static const struct dcn31_hpo_dp_stream_encoder_shift hpo_dp_se_shift = { - DCN3_1_HPO_DP_STREAM_ENC_MASK_SH_LIST(__SHIFT) -}; - -static const struct dcn31_hpo_dp_stream_encoder_mask hpo_dp_se_mask = { - DCN3_1_HPO_DP_STREAM_ENC_MASK_SH_LIST(_MASK) -}; - - -#define hpo_dp_link_encoder_reg_init(id)\ - DCN3_1_HPO_DP_LINK_ENC_REG_LIST_RI(id) - /*DCN3_1_RDPCSTX_REG_LIST(0),*/ - /*DCN3_1_RDPCSTX_REG_LIST(1),*/ - /*DCN3_1_RDPCSTX_REG_LIST(2),*/ - /*DCN3_1_RDPCSTX_REG_LIST(3),*/ - -static struct dcn31_hpo_dp_link_encoder_registers hpo_dp_link_enc_regs[2]; - -static const struct dcn31_hpo_dp_link_encoder_shift hpo_dp_le_shift = { - DCN3_2_HPO_DP_LINK_ENC_MASK_SH_LIST(__SHIFT) -}; - -static const struct dcn31_hpo_dp_link_encoder_mask hpo_dp_le_mask = { - DCN3_2_HPO_DP_LINK_ENC_MASK_SH_LIST(_MASK) -}; - -#define dpp_regs_init(id)\ - DPP_REG_LIST_DCN30_COMMON_RI(id) - -static struct dcn3_dpp_registers dpp_regs[4]; - -static const struct dcn3_dpp_shift tf_shift = { - DPP_REG_LIST_SH_MASK_DCN30_COMMON(__SHIFT) -}; - -static const struct dcn3_dpp_mask tf_mask = { - DPP_REG_LIST_SH_MASK_DCN30_COMMON(_MASK) -}; - - -#define opp_regs_init(id)\ - OPP_REG_LIST_DCN30_RI(id) - -static struct dcn20_opp_registers opp_regs[4]; - -static const struct dcn20_opp_shift opp_shift = { - OPP_MASK_SH_LIST_DCN20(__SHIFT) -}; - -static const struct dcn20_opp_mask opp_mask = { - OPP_MASK_SH_LIST_DCN20(_MASK) -}; - -#define aux_engine_regs_init(id) \ - ( \ - AUX_COMMON_REG_LIST0_RI(id), SR_ARR_INIT(AUXN_IMPCAL, id, 0), \ - SR_ARR_INIT(AUXP_IMPCAL, id, 0), \ - SR_ARR_INIT(AUX_RESET_MASK, id, DP_AUX0_AUX_CONTROL__AUX_RESET_MASK), \ - SR_ARR_INIT(AUX_RESET_MASK, id, DP_AUX0_AUX_CONTROL__AUX_RESET_MASK)\ - ) - -static struct dce110_aux_registers aux_engine_regs[5]; - -static const struct dce110_aux_registers_shift aux_shift = { - DCN_AUX_MASK_SH_LIST(__SHIFT) -}; - -static const struct dce110_aux_registers_mask aux_mask = { - DCN_AUX_MASK_SH_LIST(_MASK) -}; - -#define dwbc_regs_dcn3_init(id)\ - DWBC_COMMON_REG_LIST_DCN30_RI(id) - -static struct dcn30_dwbc_registers dwbc30_regs[1]; - -static const struct dcn30_dwbc_shift dwbc30_shift = { - DWBC_COMMON_MASK_SH_LIST_DCN30(__SHIFT) -}; - -static const struct dcn30_dwbc_mask dwbc30_mask = { - DWBC_COMMON_MASK_SH_LIST_DCN30(_MASK) -}; - -#define mcif_wb_regs_dcn3_init(id)\ - MCIF_WB_COMMON_REG_LIST_DCN32_RI(id) - -static struct dcn30_mmhubbub_registers mcif_wb30_regs[1]; - -static const struct dcn30_mmhubbub_shift mcif_wb30_shift = { - MCIF_WB_COMMON_MASK_SH_LIST_DCN32(__SHIFT) -}; - -static const struct dcn30_mmhubbub_mask mcif_wb30_mask = { - MCIF_WB_COMMON_MASK_SH_LIST_DCN32(_MASK) -}; - -#define dsc_regsDCN20_init(id)\ - DSC_REG_LIST_DCN20_RI(id) - -static struct dcn20_dsc_registers dsc_regs[4]; - -static const struct dcn20_dsc_shift dsc_shift = { - DSC_REG_LIST_SH_MASK_DCN20(__SHIFT) -}; - -static const struct dcn20_dsc_mask dsc_mask = { - DSC_REG_LIST_SH_MASK_DCN20(_MASK) -}; - -static struct dcn30_mpc_registers mpc_regs; -#define dcn_mpc_regs_init()\ - MPC_REG_LIST_DCN3_2_RI(0),\ - MPC_REG_LIST_DCN3_2_RI(1),\ - MPC_REG_LIST_DCN3_2_RI(2),\ - MPC_REG_LIST_DCN3_2_RI(3),\ - MPC_OUT_MUX_REG_LIST_DCN3_0_RI(0),\ - MPC_OUT_MUX_REG_LIST_DCN3_0_RI(1),\ - MPC_OUT_MUX_REG_LIST_DCN3_0_RI(2),\ - MPC_OUT_MUX_REG_LIST_DCN3_0_RI(3),\ - MPC_DWB_MUX_REG_LIST_DCN3_0_RI(0) - -static const struct dcn30_mpc_shift mpc_shift = { - MPC_COMMON_MASK_SH_LIST_DCN32(__SHIFT) -}; - -static const struct dcn30_mpc_mask mpc_mask = { - MPC_COMMON_MASK_SH_LIST_DCN32(_MASK) -}; - -#define optc_regs_init(id)\ - OPTC_COMMON_REG_LIST_DCN3_2_RI(id) - -static struct dcn_optc_registers optc_regs[4]; - -static const struct dcn_optc_shift optc_shift = { - OPTC_COMMON_MASK_SH_LIST_DCN3_2(__SHIFT) -}; - -static const struct dcn_optc_mask optc_mask = { - OPTC_COMMON_MASK_SH_LIST_DCN3_2(_MASK) -}; - -#define hubp_regs_init(id) \ - HUBP_REG_LIST_DCN32_RI(id) - -static struct dcn_hubp2_registers hubp_regs[4]; - -static const struct dcn_hubp2_shift hubp_shift = { - HUBP_MASK_SH_LIST_DCN32(__SHIFT) -}; - -static const struct dcn_hubp2_mask hubp_mask = { - HUBP_MASK_SH_LIST_DCN32(_MASK) -}; - -static struct dcn_hubbub_registers hubbub_reg; -#define hubbub_reg_init()\ - HUBBUB_REG_LIST_DCN32_RI(0) - -static const struct dcn_hubbub_shift hubbub_shift = { - HUBBUB_MASK_SH_LIST_DCN32(__SHIFT) -}; - -static const struct dcn_hubbub_mask hubbub_mask = { - HUBBUB_MASK_SH_LIST_DCN32(_MASK) -}; - -static struct dccg_registers dccg_regs; - -#define dccg_regs_init()\ - DCCG_REG_LIST_DCN32_RI() - -static const struct dccg_shift dccg_shift = { - DCCG_MASK_SH_LIST_DCN32(__SHIFT) -}; - -static const struct dccg_mask dccg_mask = { - DCCG_MASK_SH_LIST_DCN32(_MASK) -}; - - -#define SRII2(reg_name_pre, reg_name_post, id)\ - .reg_name_pre ## _ ## reg_name_post[id] = BASE(reg ## reg_name_pre \ - ## id ## _ ## reg_name_post ## _BASE_IDX) + \ - reg ## reg_name_pre ## id ## _ ## reg_name_post - - -#define HWSEQ_DCN32_REG_LIST()\ - SR(DCHUBBUB_GLOBAL_TIMER_CNTL), \ - SR(DIO_MEM_PWR_CTRL), \ - SR(ODM_MEM_PWR_CTRL3), \ - SR(MMHUBBUB_MEM_PWR_CNTL), \ - SR(DCCG_GATE_DISABLE_CNTL), \ - SR(DCCG_GATE_DISABLE_CNTL2), \ - SR(DCFCLK_CNTL),\ - SR(DC_MEM_GLOBAL_PWR_REQ_CNTL), \ - SRII(PIXEL_RATE_CNTL, OTG, 0), \ - SRII(PIXEL_RATE_CNTL, OTG, 1),\ - SRII(PIXEL_RATE_CNTL, OTG, 2),\ - SRII(PIXEL_RATE_CNTL, OTG, 3),\ - SRII(PHYPLL_PIXEL_RATE_CNTL, OTG, 0),\ - SRII(PHYPLL_PIXEL_RATE_CNTL, OTG, 1),\ - SRII(PHYPLL_PIXEL_RATE_CNTL, OTG, 2),\ - SRII(PHYPLL_PIXEL_RATE_CNTL, OTG, 3),\ - SR(MICROSECOND_TIME_BASE_DIV), \ - SR(MILLISECOND_TIME_BASE_DIV), \ - SR(DISPCLK_FREQ_CHANGE_CNTL), \ - SR(RBBMIF_TIMEOUT_DIS), \ - SR(RBBMIF_TIMEOUT_DIS_2), \ - SR(DCHUBBUB_CRC_CTRL), \ - SR(DPP_TOP0_DPP_CRC_CTRL), \ - SR(DPP_TOP0_DPP_CRC_VAL_B_A), \ - SR(DPP_TOP0_DPP_CRC_VAL_R_G), \ - SR(MPC_CRC_CTRL), \ - SR(MPC_CRC_RESULT_GB), \ - SR(MPC_CRC_RESULT_C), \ - SR(MPC_CRC_RESULT_AR), \ - SR(DOMAIN0_PG_CONFIG), \ - SR(DOMAIN1_PG_CONFIG), \ - SR(DOMAIN2_PG_CONFIG), \ - SR(DOMAIN3_PG_CONFIG), \ - SR(DOMAIN16_PG_CONFIG), \ - SR(DOMAIN17_PG_CONFIG), \ - SR(DOMAIN18_PG_CONFIG), \ - SR(DOMAIN19_PG_CONFIG), \ - SR(DOMAIN0_PG_STATUS), \ - SR(DOMAIN1_PG_STATUS), \ - SR(DOMAIN2_PG_STATUS), \ - SR(DOMAIN3_PG_STATUS), \ - SR(DOMAIN16_PG_STATUS), \ - SR(DOMAIN17_PG_STATUS), \ - SR(DOMAIN18_PG_STATUS), \ - SR(DOMAIN19_PG_STATUS), \ - SR(D1VGA_CONTROL), \ - SR(D2VGA_CONTROL), \ - SR(D3VGA_CONTROL), \ - SR(D4VGA_CONTROL), \ - SR(D5VGA_CONTROL), \ - SR(D6VGA_CONTROL), \ - SR(DC_IP_REQUEST_CNTL), \ - SR(AZALIA_AUDIO_DTO), \ - SR(AZALIA_CONTROLLER_CLOCK_GATING) - -static struct dce_hwseq_registers hwseq_reg; - -#define hwseq_reg_init()\ - HWSEQ_DCN32_REG_LIST() - -#define HWSEQ_DCN32_MASK_SH_LIST(mask_sh)\ - HWSEQ_DCN_MASK_SH_LIST(mask_sh), \ - HWS_SF(, DCHUBBUB_GLOBAL_TIMER_CNTL, DCHUBBUB_GLOBAL_TIMER_REFDIV, mask_sh), \ - HWS_SF(, DOMAIN0_PG_CONFIG, DOMAIN_POWER_FORCEON, mask_sh), \ - HWS_SF(, DOMAIN0_PG_CONFIG, DOMAIN_POWER_GATE, mask_sh), \ - HWS_SF(, DOMAIN1_PG_CONFIG, DOMAIN_POWER_FORCEON, mask_sh), \ - HWS_SF(, DOMAIN1_PG_CONFIG, DOMAIN_POWER_GATE, mask_sh), \ - HWS_SF(, DOMAIN2_PG_CONFIG, DOMAIN_POWER_FORCEON, mask_sh), \ - HWS_SF(, DOMAIN2_PG_CONFIG, DOMAIN_POWER_GATE, mask_sh), \ - HWS_SF(, DOMAIN3_PG_CONFIG, DOMAIN_POWER_FORCEON, mask_sh), \ - HWS_SF(, DOMAIN3_PG_CONFIG, DOMAIN_POWER_GATE, mask_sh), \ - HWS_SF(, DOMAIN16_PG_CONFIG, DOMAIN_POWER_FORCEON, mask_sh), \ - HWS_SF(, DOMAIN16_PG_CONFIG, DOMAIN_POWER_GATE, mask_sh), \ - HWS_SF(, DOMAIN17_PG_CONFIG, DOMAIN_POWER_FORCEON, mask_sh), \ - HWS_SF(, DOMAIN17_PG_CONFIG, DOMAIN_POWER_GATE, mask_sh), \ - HWS_SF(, DOMAIN18_PG_CONFIG, DOMAIN_POWER_FORCEON, mask_sh), \ - HWS_SF(, DOMAIN18_PG_CONFIG, DOMAIN_POWER_GATE, mask_sh), \ - HWS_SF(, DOMAIN19_PG_CONFIG, DOMAIN_POWER_FORCEON, mask_sh), \ - HWS_SF(, DOMAIN19_PG_CONFIG, DOMAIN_POWER_GATE, mask_sh), \ - HWS_SF(, DOMAIN0_PG_STATUS, DOMAIN_PGFSM_PWR_STATUS, mask_sh), \ - HWS_SF(, DOMAIN1_PG_STATUS, DOMAIN_PGFSM_PWR_STATUS, mask_sh), \ - HWS_SF(, DOMAIN2_PG_STATUS, DOMAIN_PGFSM_PWR_STATUS, mask_sh), \ - HWS_SF(, DOMAIN3_PG_STATUS, DOMAIN_PGFSM_PWR_STATUS, mask_sh), \ - HWS_SF(, DOMAIN16_PG_STATUS, DOMAIN_PGFSM_PWR_STATUS, mask_sh), \ - HWS_SF(, DOMAIN17_PG_STATUS, DOMAIN_PGFSM_PWR_STATUS, mask_sh), \ - HWS_SF(, DOMAIN18_PG_STATUS, DOMAIN_PGFSM_PWR_STATUS, mask_sh), \ - HWS_SF(, DOMAIN19_PG_STATUS, DOMAIN_PGFSM_PWR_STATUS, mask_sh), \ - HWS_SF(, DC_IP_REQUEST_CNTL, IP_REQUEST_EN, mask_sh), \ - HWS_SF(, AZALIA_AUDIO_DTO, AZALIA_AUDIO_DTO_MODULE, mask_sh), \ - HWS_SF(, HPO_TOP_CLOCK_CONTROL, HPO_HDMISTREAMCLK_G_GATE_DIS, mask_sh), \ - HWS_SF(, ODM_MEM_PWR_CTRL3, ODM_MEM_UNASSIGNED_PWR_MODE, mask_sh), \ - HWS_SF(, ODM_MEM_PWR_CTRL3, ODM_MEM_VBLANK_PWR_MODE, mask_sh), \ - HWS_SF(, MMHUBBUB_MEM_PWR_CNTL, VGA_MEM_PWR_FORCE, mask_sh) - -static const struct dce_hwseq_shift hwseq_shift = { - HWSEQ_DCN32_MASK_SH_LIST(__SHIFT) -}; - -static const struct dce_hwseq_mask hwseq_mask = { - HWSEQ_DCN32_MASK_SH_LIST(_MASK) -}; -#define vmid_regs_init(id)\ - DCN20_VMID_REG_LIST_RI(id) - -static struct dcn_vmid_registers vmid_regs[16]; - -static const struct dcn20_vmid_shift vmid_shifts = { - DCN20_VMID_MASK_SH_LIST(__SHIFT) -}; - -static const struct dcn20_vmid_mask vmid_masks = { - DCN20_VMID_MASK_SH_LIST(_MASK) -}; - -static const struct resource_caps res_cap_dcn321 = { - .num_timing_generator = 4, - .num_opp = 4, - .num_video_plane = 4, - .num_audio = 5, - .num_stream_encoder = 5, - .num_hpo_dp_stream_encoder = 4, - .num_hpo_dp_link_encoder = 2, - .num_pll = 5, - .num_dwb = 1, - .num_ddc = 5, - .num_vmid = 16, - .num_mpc_3dlut = 4, - .num_dsc = 4, -}; - -static const struct dc_plane_cap plane_cap = { - .type = DC_PLANE_TYPE_DCN_UNIVERSAL, - .per_pixel_alpha = true, - - .pixel_format_support = { - .argb8888 = true, - .nv12 = true, - .fp16 = true, - .p010 = true, - .ayuv = false, - }, - - .max_upscale_factor = { - .argb8888 = 16000, - .nv12 = 16000, - .fp16 = 16000 - }, - - // 6:1 downscaling ratio: 1000/6 = 166.666 - .max_downscale_factor = { - .argb8888 = 167, - .nv12 = 167, - .fp16 = 167 - }, - 64, - 64 -}; - -static const struct dc_debug_options debug_defaults_drv = { - .disable_dmcu = true, - .force_abm_enable = false, - .timing_trace = false, - .clock_trace = true, - .disable_pplib_clock_request = false, - .pipe_split_policy = MPC_SPLIT_AVOID, - .force_single_disp_pipe_split = false, - .disable_dcc = DCC_ENABLE, - .vsr_support = true, - .performance_trace = false, - .max_downscale_src_width = 7680,/*upto 8K*/ - .disable_pplib_wm_range = false, - .scl_reset_length10 = true, - .sanity_checks = false, - .underflow_assert_delay_us = 0xFFFFFFFF, - .dwb_fi_phase = -1, // -1 = disable, - .dmub_command_table = true, - .enable_mem_low_power = { - .bits = { - .vga = false, - .i2c = false, - .dmcu = false, // This is previously known to cause hang on S3 cycles if enabled - .dscl = false, - .cm = false, - .mpc = false, - .optc = true, - } - }, - .use_max_lb = true, - .force_disable_subvp = false, - .exit_idle_opt_for_cursor_updates = true, - .enable_single_display_2to1_odm_policy = true, - - /*must match enable_single_display_2to1_odm_policy to support dynamic ODM transitions*/ - .enable_double_buffered_dsc_pg_support = true, - .enable_dp_dig_pixel_rate_div_policy = 1, - .allow_sw_cursor_fallback = false, // Linux can't do SW cursor "fallback" - .alloc_extra_way_for_cursor = true, - .min_prefetch_in_strobe_ns = 60000, // 60us - .disable_unbounded_requesting = false, - .override_dispclk_programming = true, - .disable_fpo_optimizations = false, - .fpo_vactive_margin_us = 2000, // 2000us - .disable_fpo_vactive = false, - .disable_boot_optimizations = false, - .disable_subvp_high_refresh = false, - .fpo_vactive_min_active_margin_us = 200, - .fpo_vactive_max_blank_us = 1000, - .enable_legacy_fast_update = false, - .disable_dc_mode_overwrite = true, - .using_dml2 = false, -}; - -static struct dce_aux *dcn321_aux_engine_create( - struct dc_context *ctx, - uint32_t inst) -{ - struct aux_engine_dce110 *aux_engine = - kzalloc(sizeof(struct aux_engine_dce110), GFP_KERNEL); - - if (!aux_engine) - return NULL; - -#undef REG_STRUCT -#define REG_STRUCT aux_engine_regs - aux_engine_regs_init(0), - aux_engine_regs_init(1), - aux_engine_regs_init(2), - aux_engine_regs_init(3), - aux_engine_regs_init(4); - - dce110_aux_engine_construct(aux_engine, ctx, inst, - SW_AUX_TIMEOUT_PERIOD_MULTIPLIER * AUX_TIMEOUT_PERIOD, - &aux_engine_regs[inst], - &aux_mask, - &aux_shift, - ctx->dc->caps.extended_aux_timeout_support); - - return &aux_engine->base; -} -#define i2c_inst_regs_init(id)\ - I2C_HW_ENGINE_COMMON_REG_LIST_DCN30_RI(id) - -static struct dce_i2c_registers i2c_hw_regs[5]; - -static const struct dce_i2c_shift i2c_shifts = { - I2C_COMMON_MASK_SH_LIST_DCN30(__SHIFT) -}; - -static const struct dce_i2c_mask i2c_masks = { - I2C_COMMON_MASK_SH_LIST_DCN30(_MASK) -}; - -static struct dce_i2c_hw *dcn321_i2c_hw_create( - struct dc_context *ctx, - uint32_t inst) -{ - struct dce_i2c_hw *dce_i2c_hw = - kzalloc(sizeof(struct dce_i2c_hw), GFP_KERNEL); - - if (!dce_i2c_hw) - return NULL; - -#undef REG_STRUCT -#define REG_STRUCT i2c_hw_regs - i2c_inst_regs_init(1), - i2c_inst_regs_init(2), - i2c_inst_regs_init(3), - i2c_inst_regs_init(4), - i2c_inst_regs_init(5); - - dcn2_i2c_hw_construct(dce_i2c_hw, ctx, inst, - &i2c_hw_regs[inst], &i2c_shifts, &i2c_masks); - - return dce_i2c_hw; -} - -static struct clock_source *dcn321_clock_source_create( - struct dc_context *ctx, - struct dc_bios *bios, - enum clock_source_id id, - const struct dce110_clk_src_regs *regs, - bool dp_clk_src) -{ - struct dce110_clk_src *clk_src = - kzalloc(sizeof(struct dce110_clk_src), GFP_KERNEL); - - if (!clk_src) - return NULL; - - if (dcn31_clk_src_construct(clk_src, ctx, bios, id, - regs, &cs_shift, &cs_mask)) { - clk_src->base.dp_clk_src = dp_clk_src; - return &clk_src->base; - } - - kfree(clk_src); - BREAK_TO_DEBUGGER(); - return NULL; -} - -static struct hubbub *dcn321_hubbub_create(struct dc_context *ctx) -{ - int i; - - struct dcn20_hubbub *hubbub2 = kzalloc(sizeof(struct dcn20_hubbub), - GFP_KERNEL); - - if (!hubbub2) - return NULL; - -#undef REG_STRUCT -#define REG_STRUCT hubbub_reg - hubbub_reg_init(); - -#undef REG_STRUCT -#define REG_STRUCT vmid_regs - vmid_regs_init(0), - vmid_regs_init(1), - vmid_regs_init(2), - vmid_regs_init(3), - vmid_regs_init(4), - vmid_regs_init(5), - vmid_regs_init(6), - vmid_regs_init(7), - vmid_regs_init(8), - vmid_regs_init(9), - vmid_regs_init(10), - vmid_regs_init(11), - vmid_regs_init(12), - vmid_regs_init(13), - vmid_regs_init(14), - vmid_regs_init(15); - - hubbub32_construct(hubbub2, ctx, - &hubbub_reg, - &hubbub_shift, - &hubbub_mask, - ctx->dc->dml.ip.det_buffer_size_kbytes, - ctx->dc->dml.ip.pixel_chunk_size_kbytes, - ctx->dc->dml.ip.config_return_buffer_size_in_kbytes); - - - for (i = 0; i < res_cap_dcn321.num_vmid; i++) { - struct dcn20_vmid *vmid = &hubbub2->vmid[i]; - - vmid->ctx = ctx; - - vmid->regs = &vmid_regs[i]; - vmid->shifts = &vmid_shifts; - vmid->masks = &vmid_masks; - } - - return &hubbub2->base; -} - -static struct hubp *dcn321_hubp_create( - struct dc_context *ctx, - uint32_t inst) -{ - struct dcn20_hubp *hubp2 = - kzalloc(sizeof(struct dcn20_hubp), GFP_KERNEL); - - if (!hubp2) - return NULL; - -#undef REG_STRUCT -#define REG_STRUCT hubp_regs - hubp_regs_init(0), - hubp_regs_init(1), - hubp_regs_init(2), - hubp_regs_init(3); - - if (hubp32_construct(hubp2, ctx, inst, - &hubp_regs[inst], &hubp_shift, &hubp_mask)) - return &hubp2->base; - - BREAK_TO_DEBUGGER(); - kfree(hubp2); - return NULL; -} - -static void dcn321_dpp_destroy(struct dpp **dpp) -{ - kfree(TO_DCN30_DPP(*dpp)); - *dpp = NULL; -} - -static struct dpp *dcn321_dpp_create( - struct dc_context *ctx, - uint32_t inst) -{ - struct dcn3_dpp *dpp3 = - kzalloc(sizeof(struct dcn3_dpp), GFP_KERNEL); - - if (!dpp3) - return NULL; - -#undef REG_STRUCT -#define REG_STRUCT dpp_regs - dpp_regs_init(0), - dpp_regs_init(1), - dpp_regs_init(2), - dpp_regs_init(3); - - if (dpp32_construct(dpp3, ctx, inst, - &dpp_regs[inst], &tf_shift, &tf_mask)) - return &dpp3->base; - - BREAK_TO_DEBUGGER(); - kfree(dpp3); - return NULL; -} - -static struct mpc *dcn321_mpc_create( - struct dc_context *ctx, - int num_mpcc, - int num_rmu) -{ - struct dcn30_mpc *mpc30 = kzalloc(sizeof(struct dcn30_mpc), - GFP_KERNEL); - - if (!mpc30) - return NULL; - -#undef REG_STRUCT -#define REG_STRUCT mpc_regs - dcn_mpc_regs_init(); - - dcn32_mpc_construct(mpc30, ctx, - &mpc_regs, - &mpc_shift, - &mpc_mask, - num_mpcc, - num_rmu); - - return &mpc30->base; -} - -static struct output_pixel_processor *dcn321_opp_create( - struct dc_context *ctx, uint32_t inst) -{ - struct dcn20_opp *opp2 = - kzalloc(sizeof(struct dcn20_opp), GFP_KERNEL); - - if (!opp2) { - BREAK_TO_DEBUGGER(); - return NULL; - } - -#undef REG_STRUCT -#define REG_STRUCT opp_regs - opp_regs_init(0), - opp_regs_init(1), - opp_regs_init(2), - opp_regs_init(3); - - dcn20_opp_construct(opp2, ctx, inst, - &opp_regs[inst], &opp_shift, &opp_mask); - return &opp2->base; -} - - -static struct timing_generator *dcn321_timing_generator_create( - struct dc_context *ctx, - uint32_t instance) -{ - struct optc *tgn10 = - kzalloc(sizeof(struct optc), GFP_KERNEL); - - if (!tgn10) - return NULL; - -#undef REG_STRUCT -#define REG_STRUCT optc_regs - optc_regs_init(0), - optc_regs_init(1), - optc_regs_init(2), - optc_regs_init(3); - - tgn10->base.inst = instance; - tgn10->base.ctx = ctx; - - tgn10->tg_regs = &optc_regs[instance]; - tgn10->tg_shift = &optc_shift; - tgn10->tg_mask = &optc_mask; - - dcn32_timing_generator_init(tgn10); - - return &tgn10->base; -} - -static const struct encoder_feature_support link_enc_feature = { - .max_hdmi_deep_color = COLOR_DEPTH_121212, - .max_hdmi_pixel_clock = 600000, - .hdmi_ycbcr420_supported = true, - .dp_ycbcr420_supported = true, - .fec_supported = true, - .flags.bits.IS_HBR2_CAPABLE = true, - .flags.bits.IS_HBR3_CAPABLE = true, - .flags.bits.IS_TPS3_CAPABLE = true, - .flags.bits.IS_TPS4_CAPABLE = true -}; - -static struct link_encoder *dcn321_link_encoder_create( - struct dc_context *ctx, - const struct encoder_init_data *enc_init_data) -{ - struct dcn20_link_encoder *enc20 = - kzalloc(sizeof(struct dcn20_link_encoder), GFP_KERNEL); - - if (!enc20) - return NULL; - -#undef REG_STRUCT -#define REG_STRUCT link_enc_aux_regs - aux_regs_init(0), - aux_regs_init(1), - aux_regs_init(2), - aux_regs_init(3), - aux_regs_init(4); - -#undef REG_STRUCT -#define REG_STRUCT link_enc_hpd_regs - hpd_regs_init(0), - hpd_regs_init(1), - hpd_regs_init(2), - hpd_regs_init(3), - hpd_regs_init(4); - -#undef REG_STRUCT -#define REG_STRUCT link_enc_regs - link_regs_init(0, A), - link_regs_init(1, B), - link_regs_init(2, C), - link_regs_init(3, D), - link_regs_init(4, E); - - dcn321_link_encoder_construct(enc20, - enc_init_data, - &link_enc_feature, - &link_enc_regs[enc_init_data->transmitter], - &link_enc_aux_regs[enc_init_data->channel - 1], - &link_enc_hpd_regs[enc_init_data->hpd_source], - &le_shift, - &le_mask); - - return &enc20->enc10.base; -} - -static void read_dce_straps( - struct dc_context *ctx, - struct resource_straps *straps) -{ - generic_reg_get(ctx, ctx->dcn_reg_offsets[regDC_PINSTRAPS_BASE_IDX] + regDC_PINSTRAPS, - FN(DC_PINSTRAPS, DC_PINSTRAPS_AUDIO), &straps->dc_pinstraps_audio); - -} - -static struct audio *dcn321_create_audio( - struct dc_context *ctx, unsigned int inst) -{ - -#undef REG_STRUCT -#define REG_STRUCT audio_regs - audio_regs_init(0), - audio_regs_init(1), - audio_regs_init(2), - audio_regs_init(3), - audio_regs_init(4); - - return dce_audio_create(ctx, inst, - &audio_regs[inst], &audio_shift, &audio_mask); -} - -static struct vpg *dcn321_vpg_create( - struct dc_context *ctx, - uint32_t inst) -{ - struct dcn30_vpg *vpg3 = kzalloc(sizeof(struct dcn30_vpg), GFP_KERNEL); - - if (!vpg3) - return NULL; - -#undef REG_STRUCT -#define REG_STRUCT vpg_regs - vpg_regs_init(0), - vpg_regs_init(1), - vpg_regs_init(2), - vpg_regs_init(3), - vpg_regs_init(4), - vpg_regs_init(5), - vpg_regs_init(6), - vpg_regs_init(7), - vpg_regs_init(8), - vpg_regs_init(9); - - vpg3_construct(vpg3, ctx, inst, - &vpg_regs[inst], - &vpg_shift, - &vpg_mask); - - return &vpg3->base; -} - -static struct afmt *dcn321_afmt_create( - struct dc_context *ctx, - uint32_t inst) -{ - struct dcn30_afmt *afmt3 = kzalloc(sizeof(struct dcn30_afmt), GFP_KERNEL); - - if (!afmt3) - return NULL; - -#undef REG_STRUCT -#define REG_STRUCT afmt_regs - afmt_regs_init(0), - afmt_regs_init(1), - afmt_regs_init(2), - afmt_regs_init(3), - afmt_regs_init(4), - afmt_regs_init(5); - - afmt3_construct(afmt3, ctx, inst, - &afmt_regs[inst], - &afmt_shift, - &afmt_mask); - - return &afmt3->base; -} - -static struct apg *dcn321_apg_create( - struct dc_context *ctx, - uint32_t inst) -{ - struct dcn31_apg *apg31 = kzalloc(sizeof(struct dcn31_apg), GFP_KERNEL); - - if (!apg31) - return NULL; - -#undef REG_STRUCT -#define REG_STRUCT apg_regs - apg_regs_init(0), - apg_regs_init(1), - apg_regs_init(2), - apg_regs_init(3); - - apg31_construct(apg31, ctx, inst, - &apg_regs[inst], - &apg_shift, - &apg_mask); - - return &apg31->base; -} - -static struct stream_encoder *dcn321_stream_encoder_create( - enum engine_id eng_id, - struct dc_context *ctx) -{ - struct dcn10_stream_encoder *enc1; - struct vpg *vpg; - struct afmt *afmt; - int vpg_inst; - int afmt_inst; - - /* Mapping of VPG, AFMT, DME register blocks to DIO block instance */ - if (eng_id <= ENGINE_ID_DIGF) { - vpg_inst = eng_id; - afmt_inst = eng_id; - } else - return NULL; - - enc1 = kzalloc(sizeof(struct dcn10_stream_encoder), GFP_KERNEL); - vpg = dcn321_vpg_create(ctx, vpg_inst); - afmt = dcn321_afmt_create(ctx, afmt_inst); - - if (!enc1 || !vpg || !afmt) { - kfree(enc1); - kfree(vpg); - kfree(afmt); - return NULL; - } - -#undef REG_STRUCT -#define REG_STRUCT stream_enc_regs - stream_enc_regs_init(0), - stream_enc_regs_init(1), - stream_enc_regs_init(2), - stream_enc_regs_init(3), - stream_enc_regs_init(4); - - dcn32_dio_stream_encoder_construct(enc1, ctx, ctx->dc_bios, - eng_id, vpg, afmt, - &stream_enc_regs[eng_id], - &se_shift, &se_mask); - - return &enc1->base; -} - -static struct hpo_dp_stream_encoder *dcn321_hpo_dp_stream_encoder_create( - enum engine_id eng_id, - struct dc_context *ctx) -{ - struct dcn31_hpo_dp_stream_encoder *hpo_dp_enc31; - struct vpg *vpg; - struct apg *apg; - uint32_t hpo_dp_inst; - uint32_t vpg_inst; - uint32_t apg_inst; - - ASSERT((eng_id >= ENGINE_ID_HPO_DP_0) && (eng_id <= ENGINE_ID_HPO_DP_3)); - hpo_dp_inst = eng_id - ENGINE_ID_HPO_DP_0; - - /* Mapping of VPG register blocks to HPO DP block instance: - * VPG[6] -> HPO_DP[0] - * VPG[7] -> HPO_DP[1] - * VPG[8] -> HPO_DP[2] - * VPG[9] -> HPO_DP[3] - */ - vpg_inst = hpo_dp_inst + 6; - - /* Mapping of APG register blocks to HPO DP block instance: - * APG[0] -> HPO_DP[0] - * APG[1] -> HPO_DP[1] - * APG[2] -> HPO_DP[2] - * APG[3] -> HPO_DP[3] - */ - apg_inst = hpo_dp_inst; - - /* allocate HPO stream encoder and create VPG sub-block */ - hpo_dp_enc31 = kzalloc(sizeof(struct dcn31_hpo_dp_stream_encoder), GFP_KERNEL); - vpg = dcn321_vpg_create(ctx, vpg_inst); - apg = dcn321_apg_create(ctx, apg_inst); - - if (!hpo_dp_enc31 || !vpg || !apg) { - kfree(hpo_dp_enc31); - kfree(vpg); - kfree(apg); - return NULL; - } - -#undef REG_STRUCT -#define REG_STRUCT hpo_dp_stream_enc_regs - hpo_dp_stream_encoder_reg_init(0), - hpo_dp_stream_encoder_reg_init(1), - hpo_dp_stream_encoder_reg_init(2), - hpo_dp_stream_encoder_reg_init(3); - - dcn31_hpo_dp_stream_encoder_construct(hpo_dp_enc31, ctx, ctx->dc_bios, - hpo_dp_inst, eng_id, vpg, apg, - &hpo_dp_stream_enc_regs[hpo_dp_inst], - &hpo_dp_se_shift, &hpo_dp_se_mask); - - return &hpo_dp_enc31->base; -} - -static struct hpo_dp_link_encoder *dcn321_hpo_dp_link_encoder_create( - uint8_t inst, - struct dc_context *ctx) -{ - struct dcn31_hpo_dp_link_encoder *hpo_dp_enc31; - - /* allocate HPO link encoder */ - hpo_dp_enc31 = kzalloc(sizeof(struct dcn31_hpo_dp_link_encoder), GFP_KERNEL); - -#undef REG_STRUCT -#define REG_STRUCT hpo_dp_link_enc_regs - hpo_dp_link_encoder_reg_init(0), - hpo_dp_link_encoder_reg_init(1); - - hpo_dp_link_encoder32_construct(hpo_dp_enc31, ctx, inst, - &hpo_dp_link_enc_regs[inst], - &hpo_dp_le_shift, &hpo_dp_le_mask); - - return &hpo_dp_enc31->base; -} - -static struct dce_hwseq *dcn321_hwseq_create( - struct dc_context *ctx) -{ - struct dce_hwseq *hws = kzalloc(sizeof(struct dce_hwseq), GFP_KERNEL); - -#undef REG_STRUCT -#define REG_STRUCT hwseq_reg - hwseq_reg_init(); - - if (hws) { - hws->ctx = ctx; - hws->regs = &hwseq_reg; - hws->shifts = &hwseq_shift; - hws->masks = &hwseq_mask; - } - return hws; -} -static const struct resource_create_funcs res_create_funcs = { - .read_dce_straps = read_dce_straps, - .create_audio = dcn321_create_audio, - .create_stream_encoder = dcn321_stream_encoder_create, - .create_hpo_dp_stream_encoder = dcn321_hpo_dp_stream_encoder_create, - .create_hpo_dp_link_encoder = dcn321_hpo_dp_link_encoder_create, - .create_hwseq = dcn321_hwseq_create, -}; - -static void dcn321_resource_destruct(struct dcn321_resource_pool *pool) -{ - unsigned int i; - - for (i = 0; i < pool->base.stream_enc_count; i++) { - if (pool->base.stream_enc[i] != NULL) { - if (pool->base.stream_enc[i]->vpg != NULL) { - kfree(DCN30_VPG_FROM_VPG(pool->base.stream_enc[i]->vpg)); - pool->base.stream_enc[i]->vpg = NULL; - } - if (pool->base.stream_enc[i]->afmt != NULL) { - kfree(DCN30_AFMT_FROM_AFMT(pool->base.stream_enc[i]->afmt)); - pool->base.stream_enc[i]->afmt = NULL; - } - kfree(DCN10STRENC_FROM_STRENC(pool->base.stream_enc[i])); - pool->base.stream_enc[i] = NULL; - } - } - - for (i = 0; i < pool->base.hpo_dp_stream_enc_count; i++) { - if (pool->base.hpo_dp_stream_enc[i] != NULL) { - if (pool->base.hpo_dp_stream_enc[i]->vpg != NULL) { - kfree(DCN30_VPG_FROM_VPG(pool->base.hpo_dp_stream_enc[i]->vpg)); - pool->base.hpo_dp_stream_enc[i]->vpg = NULL; - } - if (pool->base.hpo_dp_stream_enc[i]->apg != NULL) { - kfree(DCN31_APG_FROM_APG(pool->base.hpo_dp_stream_enc[i]->apg)); - pool->base.hpo_dp_stream_enc[i]->apg = NULL; - } - kfree(DCN3_1_HPO_DP_STREAM_ENC_FROM_HPO_STREAM_ENC(pool->base.hpo_dp_stream_enc[i])); - pool->base.hpo_dp_stream_enc[i] = NULL; - } - } - - for (i = 0; i < pool->base.hpo_dp_link_enc_count; i++) { - if (pool->base.hpo_dp_link_enc[i] != NULL) { - kfree(DCN3_1_HPO_DP_LINK_ENC_FROM_HPO_LINK_ENC(pool->base.hpo_dp_link_enc[i])); - pool->base.hpo_dp_link_enc[i] = NULL; - } - } - - for (i = 0; i < pool->base.res_cap->num_dsc; i++) { - if (pool->base.dscs[i] != NULL) - dcn20_dsc_destroy(&pool->base.dscs[i]); - } - - if (pool->base.mpc != NULL) { - kfree(TO_DCN20_MPC(pool->base.mpc)); - pool->base.mpc = NULL; - } - if (pool->base.hubbub != NULL) { - kfree(TO_DCN20_HUBBUB(pool->base.hubbub)); - pool->base.hubbub = NULL; - } - for (i = 0; i < pool->base.pipe_count; i++) { - if (pool->base.dpps[i] != NULL) - dcn321_dpp_destroy(&pool->base.dpps[i]); - - if (pool->base.ipps[i] != NULL) - pool->base.ipps[i]->funcs->ipp_destroy(&pool->base.ipps[i]); - - if (pool->base.hubps[i] != NULL) { - kfree(TO_DCN20_HUBP(pool->base.hubps[i])); - pool->base.hubps[i] = NULL; - } - - if (pool->base.irqs != NULL) - dal_irq_service_destroy(&pool->base.irqs); - } - - for (i = 0; i < pool->base.res_cap->num_ddc; i++) { - if (pool->base.engines[i] != NULL) - dce110_engine_destroy(&pool->base.engines[i]); - if (pool->base.hw_i2cs[i] != NULL) { - kfree(pool->base.hw_i2cs[i]); - pool->base.hw_i2cs[i] = NULL; - } - if (pool->base.sw_i2cs[i] != NULL) { - kfree(pool->base.sw_i2cs[i]); - pool->base.sw_i2cs[i] = NULL; - } - } - - for (i = 0; i < pool->base.res_cap->num_opp; i++) { - if (pool->base.opps[i] != NULL) - pool->base.opps[i]->funcs->opp_destroy(&pool->base.opps[i]); - } - - for (i = 0; i < pool->base.res_cap->num_timing_generator; i++) { - if (pool->base.timing_generators[i] != NULL) { - kfree(DCN10TG_FROM_TG(pool->base.timing_generators[i])); - pool->base.timing_generators[i] = NULL; - } - } - - for (i = 0; i < pool->base.res_cap->num_dwb; i++) { - if (pool->base.dwbc[i] != NULL) { - kfree(TO_DCN30_DWBC(pool->base.dwbc[i])); - pool->base.dwbc[i] = NULL; - } - if (pool->base.mcif_wb[i] != NULL) { - kfree(TO_DCN30_MMHUBBUB(pool->base.mcif_wb[i])); - pool->base.mcif_wb[i] = NULL; - } - } - - for (i = 0; i < pool->base.audio_count; i++) { - if (pool->base.audios[i]) - dce_aud_destroy(&pool->base.audios[i]); - } - - for (i = 0; i < pool->base.clk_src_count; i++) { - if (pool->base.clock_sources[i] != NULL) { - dcn20_clock_source_destroy(&pool->base.clock_sources[i]); - pool->base.clock_sources[i] = NULL; - } - } - - for (i = 0; i < pool->base.res_cap->num_mpc_3dlut; i++) { - if (pool->base.mpc_lut[i] != NULL) { - dc_3dlut_func_release(pool->base.mpc_lut[i]); - pool->base.mpc_lut[i] = NULL; - } - if (pool->base.mpc_shaper[i] != NULL) { - dc_transfer_func_release(pool->base.mpc_shaper[i]); - pool->base.mpc_shaper[i] = NULL; - } - } - - if (pool->base.dp_clock_source != NULL) { - dcn20_clock_source_destroy(&pool->base.dp_clock_source); - pool->base.dp_clock_source = NULL; - } - - for (i = 0; i < pool->base.res_cap->num_timing_generator; i++) { - if (pool->base.multiple_abms[i] != NULL) - dce_abm_destroy(&pool->base.multiple_abms[i]); - } - - if (pool->base.psr != NULL) - dmub_psr_destroy(&pool->base.psr); - - if (pool->base.dccg != NULL) - dcn_dccg_destroy(&pool->base.dccg); - - if (pool->base.oem_device != NULL) { - struct dc *dc = pool->base.oem_device->ctx->dc; - - dc->link_srv->destroy_ddc_service(&pool->base.oem_device); - } -} - - -static bool dcn321_dwbc_create(struct dc_context *ctx, struct resource_pool *pool) -{ - int i; - uint32_t dwb_count = pool->res_cap->num_dwb; - - for (i = 0; i < dwb_count; i++) { - struct dcn30_dwbc *dwbc30 = kzalloc(sizeof(struct dcn30_dwbc), - GFP_KERNEL); - - if (!dwbc30) { - dm_error("DC: failed to create dwbc30!\n"); - return false; - } - -#undef REG_STRUCT -#define REG_STRUCT dwbc30_regs - dwbc_regs_dcn3_init(0); - - dcn30_dwbc_construct(dwbc30, ctx, - &dwbc30_regs[i], - &dwbc30_shift, - &dwbc30_mask, - i); - - pool->dwbc[i] = &dwbc30->base; - } - return true; -} - -static bool dcn321_mmhubbub_create(struct dc_context *ctx, struct resource_pool *pool) -{ - int i; - uint32_t dwb_count = pool->res_cap->num_dwb; - - for (i = 0; i < dwb_count; i++) { - struct dcn30_mmhubbub *mcif_wb30 = kzalloc(sizeof(struct dcn30_mmhubbub), - GFP_KERNEL); - - if (!mcif_wb30) { - dm_error("DC: failed to create mcif_wb30!\n"); - return false; - } - -#undef REG_STRUCT -#define REG_STRUCT mcif_wb30_regs - mcif_wb_regs_dcn3_init(0); - - dcn32_mmhubbub_construct(mcif_wb30, ctx, - &mcif_wb30_regs[i], - &mcif_wb30_shift, - &mcif_wb30_mask, - i); - - pool->mcif_wb[i] = &mcif_wb30->base; - } - return true; -} - -static struct display_stream_compressor *dcn321_dsc_create( - struct dc_context *ctx, uint32_t inst) -{ - struct dcn20_dsc *dsc = - kzalloc(sizeof(struct dcn20_dsc), GFP_KERNEL); - - if (!dsc) { - BREAK_TO_DEBUGGER(); - return NULL; - } - -#undef REG_STRUCT -#define REG_STRUCT dsc_regs - dsc_regsDCN20_init(0), - dsc_regsDCN20_init(1), - dsc_regsDCN20_init(2), - dsc_regsDCN20_init(3); - - dsc2_construct(dsc, ctx, inst, &dsc_regs[inst], &dsc_shift, &dsc_mask); - - dsc->max_image_width = 6016; - - return &dsc->base; -} - -static void dcn321_destroy_resource_pool(struct resource_pool **pool) -{ - struct dcn321_resource_pool *dcn321_pool = TO_DCN321_RES_POOL(*pool); - - dcn321_resource_destruct(dcn321_pool); - kfree(dcn321_pool); - *pool = NULL; -} - -static struct dc_cap_funcs cap_funcs = { - .get_dcc_compression_cap = dcn20_get_dcc_compression_cap, - .get_subvp_en = dcn32_subvp_in_use, -}; - -static void dcn321_update_bw_bounding_box(struct dc *dc, struct clk_bw_params *bw_params) -{ - DC_FP_START(); - dcn321_update_bw_bounding_box_fpu(dc, bw_params); - DC_FP_END(); -} - -static struct resource_funcs dcn321_res_pool_funcs = { - .destroy = dcn321_destroy_resource_pool, - .link_enc_create = dcn321_link_encoder_create, - .link_enc_create_minimal = NULL, - .panel_cntl_create = dcn32_panel_cntl_create, - .validate_bandwidth = dcn32_validate_bandwidth, - .calculate_wm_and_dlg = dcn32_calculate_wm_and_dlg, - .populate_dml_pipes = dcn32_populate_dml_pipes_from_context, - .acquire_free_pipe_as_secondary_dpp_pipe = dcn32_acquire_free_pipe_as_secondary_dpp_pipe, - .acquire_free_pipe_as_secondary_opp_head = dcn32_acquire_free_pipe_as_secondary_opp_head, - .release_pipe = dcn20_release_pipe, - .add_stream_to_ctx = dcn30_add_stream_to_ctx, - .add_dsc_to_stream_resource = dcn20_add_dsc_to_stream_resource, - .remove_stream_from_ctx = dcn20_remove_stream_from_ctx, - .populate_dml_writeback_from_context = dcn30_populate_dml_writeback_from_context, - .set_mcif_arb_params = dcn30_set_mcif_arb_params, - .find_first_free_match_stream_enc_for_link = dcn10_find_first_free_match_stream_enc_for_link, - .acquire_post_bldn_3dlut = dcn32_acquire_post_bldn_3dlut, - .release_post_bldn_3dlut = dcn32_release_post_bldn_3dlut, - .update_bw_bounding_box = dcn321_update_bw_bounding_box, - .patch_unknown_plane_state = dcn20_patch_unknown_plane_state, - .update_soc_for_wm_a = dcn30_update_soc_for_wm_a, - .add_phantom_pipes = dcn32_add_phantom_pipes, - .remove_phantom_pipes = dcn32_remove_phantom_pipes, - .retain_phantom_pipes = dcn32_retain_phantom_pipes, - .save_mall_state = dcn32_save_mall_state, - .restore_mall_state = dcn32_restore_mall_state, -}; - -static uint32_t read_pipe_fuses(struct dc_context *ctx) -{ - uint32_t value = REG_READ(CC_DC_PIPE_DIS); - /* DCN321 support max 4 pipes */ - value = value & 0xf; - return value; -} - - -static bool dcn321_resource_construct( - uint8_t num_virtual_links, - struct dc *dc, - struct dcn321_resource_pool *pool) -{ - int i, j; - struct dc_context *ctx = dc->ctx; - struct irq_service_init_data init_data; - struct ddc_service_init_data ddc_init_data = {0}; - uint32_t pipe_fuses = 0; - uint32_t num_pipes = 4; - -#undef REG_STRUCT -#define REG_STRUCT bios_regs - bios_regs_init(); - -#undef REG_STRUCT -#define REG_STRUCT clk_src_regs - clk_src_regs_init(0, A), - clk_src_regs_init(1, B), - clk_src_regs_init(2, C), - clk_src_regs_init(3, D), - clk_src_regs_init(4, E); - -#undef REG_STRUCT -#define REG_STRUCT abm_regs - abm_regs_init(0), - abm_regs_init(1), - abm_regs_init(2), - abm_regs_init(3); - -#undef REG_STRUCT -#define REG_STRUCT dccg_regs - dccg_regs_init(); - - - ctx->dc_bios->regs = &bios_regs; - - pool->base.res_cap = &res_cap_dcn321; - /* max number of pipes for ASIC before checking for pipe fuses */ - num_pipes = pool->base.res_cap->num_timing_generator; - pipe_fuses = read_pipe_fuses(ctx); - - for (i = 0; i < pool->base.res_cap->num_timing_generator; i++) - if (pipe_fuses & 1 << i) - num_pipes--; - - if (pipe_fuses & 1) - ASSERT(0); //Unexpected - Pipe 0 should always be fully functional! - - if (pipe_fuses & CC_DC_PIPE_DIS__DC_FULL_DIS_MASK) - ASSERT(0); //Entire DCN is harvested! - - /* within dml lib, initial value is hard coded, if ASIC pipe is fused, the - * value will be changed, update max_num_dpp and max_num_otg for dml. - */ - dcn3_21_ip.max_num_dpp = num_pipes; - dcn3_21_ip.max_num_otg = num_pipes; - - pool->base.funcs = &dcn321_res_pool_funcs; - - /************************************************* - * Resource + asic cap harcoding * - *************************************************/ - pool->base.underlay_pipe_index = NO_UNDERLAY_PIPE; - pool->base.timing_generator_count = num_pipes; - pool->base.pipe_count = num_pipes; - pool->base.mpcc_count = num_pipes; - dc->caps.max_downscale_ratio = 600; - dc->caps.i2c_speed_in_khz = 100; - dc->caps.i2c_speed_in_khz_hdcp = 100; /*1.4 w/a applied by default*/ - /* TODO: Bring max cursor size back to 256 after subvp cursor corruption is fixed*/ - dc->caps.max_cursor_size = 64; - dc->caps.min_horizontal_blanking_period = 80; - dc->caps.dmdata_alloc_size = 2048; - dc->caps.mall_size_per_mem_channel = 4; - dc->caps.mall_size_total = 0; - dc->caps.cursor_cache_size = dc->caps.max_cursor_size * dc->caps.max_cursor_size * 8; - dc->caps.cache_line_size = 64; - dc->caps.cache_num_ways = 16; - - /* Calculate the available MALL space */ - dc->caps.max_cab_allocation_bytes = dcn32_calc_num_avail_chans_for_mall( - dc, dc->ctx->dc_bios->vram_info.num_chans) * - dc->caps.mall_size_per_mem_channel * 1024 * 1024; - dc->caps.mall_size_total = dc->caps.max_cab_allocation_bytes; - - dc->caps.subvp_fw_processing_delay_us = 15; - dc->caps.subvp_drr_max_vblank_margin_us = 40; - dc->caps.subvp_prefetch_end_to_mall_start_us = 15; - dc->caps.subvp_swath_height_margin_lines = 16; - dc->caps.subvp_pstate_allow_width_us = 20; - dc->caps.subvp_vertical_int_margin_us = 30; - dc->caps.subvp_drr_vblank_start_margin_us = 100; // 100us margin - dc->caps.max_slave_planes = 2; - dc->caps.max_slave_yuv_planes = 2; - dc->caps.max_slave_rgb_planes = 2; - dc->caps.post_blend_color_processing = true; - dc->caps.force_dp_tps4_for_cp2520 = true; - dc->caps.dp_hpo = true; - dc->caps.dp_hdmi21_pcon_support = true; - dc->caps.edp_dsc_support = true; - dc->caps.extended_aux_timeout_support = true; - dc->caps.dmcub_support = true; - dc->caps.max_v_total = (1 << 15) - 1; - - /* Color pipeline capabilities */ - dc->caps.color.dpp.dcn_arch = 1; - dc->caps.color.dpp.input_lut_shared = 0; - dc->caps.color.dpp.icsc = 1; - dc->caps.color.dpp.dgam_ram = 0; // must use gamma_corr - dc->caps.color.dpp.dgam_rom_caps.srgb = 1; - dc->caps.color.dpp.dgam_rom_caps.bt2020 = 1; - dc->caps.color.dpp.dgam_rom_caps.gamma2_2 = 1; - dc->caps.color.dpp.dgam_rom_caps.pq = 1; - dc->caps.color.dpp.dgam_rom_caps.hlg = 1; - dc->caps.color.dpp.post_csc = 1; - dc->caps.color.dpp.gamma_corr = 1; - dc->caps.color.dpp.dgam_rom_for_yuv = 0; - - dc->caps.color.dpp.hw_3d_lut = 1; - dc->caps.color.dpp.ogam_ram = 1; - // no OGAM ROM on DCN2 and later ASICs - dc->caps.color.dpp.ogam_rom_caps.srgb = 0; - dc->caps.color.dpp.ogam_rom_caps.bt2020 = 0; - dc->caps.color.dpp.ogam_rom_caps.gamma2_2 = 0; - dc->caps.color.dpp.ogam_rom_caps.pq = 0; - dc->caps.color.dpp.ogam_rom_caps.hlg = 0; - dc->caps.color.dpp.ocsc = 0; - - dc->caps.color.mpc.gamut_remap = 1; - dc->caps.color.mpc.num_3dluts = pool->base.res_cap->num_mpc_3dlut; //4, configurable to be before or after BLND in MPCC - dc->caps.color.mpc.ogam_ram = 1; - dc->caps.color.mpc.ogam_rom_caps.srgb = 0; - dc->caps.color.mpc.ogam_rom_caps.bt2020 = 0; - dc->caps.color.mpc.ogam_rom_caps.gamma2_2 = 0; - dc->caps.color.mpc.ogam_rom_caps.pq = 0; - dc->caps.color.mpc.ogam_rom_caps.hlg = 0; - dc->caps.color.mpc.ocsc = 1; - - dc->config.dc_mode_clk_limit_support = true; - /* read VBIOS LTTPR caps */ - { - if (ctx->dc_bios->funcs->get_lttpr_caps) { - enum bp_result bp_query_result; - uint8_t is_vbios_lttpr_enable = 0; - - bp_query_result = ctx->dc_bios->funcs->get_lttpr_caps(ctx->dc_bios, &is_vbios_lttpr_enable); - dc->caps.vbios_lttpr_enable = (bp_query_result == BP_RESULT_OK) && !!is_vbios_lttpr_enable; - } - - /* interop bit is implicit */ - { - dc->caps.vbios_lttpr_aware = true; - } - } - - if (dc->ctx->dce_environment == DCE_ENV_PRODUCTION_DRV) - dc->debug = debug_defaults_drv; - - // Init the vm_helper - if (dc->vm_helper) - vm_helper_init(dc->vm_helper, 16); - - /************************************************* - * Create resources * - *************************************************/ - - /* Clock Sources for Pixel Clock*/ - pool->base.clock_sources[DCN321_CLK_SRC_PLL0] = - dcn321_clock_source_create(ctx, ctx->dc_bios, - CLOCK_SOURCE_COMBO_PHY_PLL0, - &clk_src_regs[0], false); - pool->base.clock_sources[DCN321_CLK_SRC_PLL1] = - dcn321_clock_source_create(ctx, ctx->dc_bios, - CLOCK_SOURCE_COMBO_PHY_PLL1, - &clk_src_regs[1], false); - pool->base.clock_sources[DCN321_CLK_SRC_PLL2] = - dcn321_clock_source_create(ctx, ctx->dc_bios, - CLOCK_SOURCE_COMBO_PHY_PLL2, - &clk_src_regs[2], false); - pool->base.clock_sources[DCN321_CLK_SRC_PLL3] = - dcn321_clock_source_create(ctx, ctx->dc_bios, - CLOCK_SOURCE_COMBO_PHY_PLL3, - &clk_src_regs[3], false); - pool->base.clock_sources[DCN321_CLK_SRC_PLL4] = - dcn321_clock_source_create(ctx, ctx->dc_bios, - CLOCK_SOURCE_COMBO_PHY_PLL4, - &clk_src_regs[4], false); - - pool->base.clk_src_count = DCN321_CLK_SRC_TOTAL; - - /* todo: not reuse phy_pll registers */ - pool->base.dp_clock_source = - dcn321_clock_source_create(ctx, ctx->dc_bios, - CLOCK_SOURCE_ID_DP_DTO, - &clk_src_regs[0], true); - - for (i = 0; i < pool->base.clk_src_count; i++) { - if (pool->base.clock_sources[i] == NULL) { - dm_error("DC: failed to create clock sources!\n"); - BREAK_TO_DEBUGGER(); - goto create_fail; - } - } - - /* DCCG */ - pool->base.dccg = dccg32_create(ctx, &dccg_regs, &dccg_shift, &dccg_mask); - if (pool->base.dccg == NULL) { - dm_error("DC: failed to create dccg!\n"); - BREAK_TO_DEBUGGER(); - goto create_fail; - } - - /* DML */ - dml_init_instance(&dc->dml, &dcn3_21_soc, &dcn3_21_ip, DML_PROJECT_DCN32); - - /* IRQ Service */ - init_data.ctx = dc->ctx; - pool->base.irqs = dal_irq_service_dcn32_create(&init_data); - if (!pool->base.irqs) - goto create_fail; - - /* HUBBUB */ - pool->base.hubbub = dcn321_hubbub_create(ctx); - if (pool->base.hubbub == NULL) { - BREAK_TO_DEBUGGER(); - dm_error("DC: failed to create hubbub!\n"); - goto create_fail; - } - - /* HUBPs, DPPs, OPPs, TGs, ABMs */ - for (i = 0, j = 0; i < pool->base.res_cap->num_timing_generator; i++) { - - /* if pipe is disabled, skip instance of HW pipe, - * i.e, skip ASIC register instance - */ - if (pipe_fuses & 1 << i) - continue; - - pool->base.hubps[j] = dcn321_hubp_create(ctx, i); - if (pool->base.hubps[j] == NULL) { - BREAK_TO_DEBUGGER(); - dm_error( - "DC: failed to create hubps!\n"); - goto create_fail; - } - - pool->base.dpps[j] = dcn321_dpp_create(ctx, i); - if (pool->base.dpps[j] == NULL) { - BREAK_TO_DEBUGGER(); - dm_error( - "DC: failed to create dpps!\n"); - goto create_fail; - } - - pool->base.opps[j] = dcn321_opp_create(ctx, i); - if (pool->base.opps[j] == NULL) { - BREAK_TO_DEBUGGER(); - dm_error( - "DC: failed to create output pixel processor!\n"); - goto create_fail; - } - - pool->base.timing_generators[j] = dcn321_timing_generator_create( - ctx, i); - if (pool->base.timing_generators[j] == NULL) { - BREAK_TO_DEBUGGER(); - dm_error("DC: failed to create tg!\n"); - goto create_fail; - } - - pool->base.multiple_abms[j] = dmub_abm_create(ctx, - &abm_regs[i], - &abm_shift, - &abm_mask); - if (pool->base.multiple_abms[j] == NULL) { - dm_error("DC: failed to create abm for pipe %d!\n", i); - BREAK_TO_DEBUGGER(); - goto create_fail; - } - - /* index for resource pool arrays for next valid pipe */ - j++; - } - - /* PSR */ - pool->base.psr = dmub_psr_create(ctx); - if (pool->base.psr == NULL) { - dm_error("DC: failed to create psr obj!\n"); - BREAK_TO_DEBUGGER(); - goto create_fail; - } - - /* MPCCs */ - pool->base.mpc = dcn321_mpc_create(ctx, pool->base.res_cap->num_timing_generator, pool->base.res_cap->num_mpc_3dlut); - if (pool->base.mpc == NULL) { - BREAK_TO_DEBUGGER(); - dm_error("DC: failed to create mpc!\n"); - goto create_fail; - } - - /* DSCs */ - for (i = 0; i < pool->base.res_cap->num_dsc; i++) { - pool->base.dscs[i] = dcn321_dsc_create(ctx, i); - if (pool->base.dscs[i] == NULL) { - BREAK_TO_DEBUGGER(); - dm_error("DC: failed to create display stream compressor %d!\n", i); - goto create_fail; - } - } - - /* DWB */ - if (!dcn321_dwbc_create(ctx, &pool->base)) { - BREAK_TO_DEBUGGER(); - dm_error("DC: failed to create dwbc!\n"); - goto create_fail; - } - - /* MMHUBBUB */ - if (!dcn321_mmhubbub_create(ctx, &pool->base)) { - BREAK_TO_DEBUGGER(); - dm_error("DC: failed to create mcif_wb!\n"); - goto create_fail; - } - - /* AUX and I2C */ - for (i = 0; i < pool->base.res_cap->num_ddc; i++) { - pool->base.engines[i] = dcn321_aux_engine_create(ctx, i); - if (pool->base.engines[i] == NULL) { - BREAK_TO_DEBUGGER(); - dm_error( - "DC:failed to create aux engine!!\n"); - goto create_fail; - } - pool->base.hw_i2cs[i] = dcn321_i2c_hw_create(ctx, i); - if (pool->base.hw_i2cs[i] == NULL) { - BREAK_TO_DEBUGGER(); - dm_error( - "DC:failed to create hw i2c!!\n"); - goto create_fail; - } - pool->base.sw_i2cs[i] = NULL; - } - - /* Audio, HWSeq, Stream Encoders including HPO and virtual, MPC 3D LUTs */ - if (!resource_construct(num_virtual_links, dc, &pool->base, - &res_create_funcs)) - goto create_fail; - - /* HW Sequencer init functions and Plane caps */ - dcn32_hw_sequencer_init_functions(dc); - - dc->caps.max_planes = pool->base.pipe_count; - - for (i = 0; i < dc->caps.max_planes; ++i) - dc->caps.planes[i] = plane_cap; - - dc->cap_funcs = cap_funcs; - - if (dc->ctx->dc_bios->fw_info.oem_i2c_present) { - ddc_init_data.ctx = dc->ctx; - ddc_init_data.link = NULL; - ddc_init_data.id.id = dc->ctx->dc_bios->fw_info.oem_i2c_obj_id; - ddc_init_data.id.enum_id = 0; - ddc_init_data.id.type = OBJECT_TYPE_GENERIC; - pool->base.oem_device = dc->link_srv->create_ddc_service(&ddc_init_data); - } else { - pool->base.oem_device = NULL; - } - - dc->dml2_options.dcn_pipe_count = pool->base.pipe_count; - dc->dml2_options.use_native_pstate_optimization = false; - dc->dml2_options.use_native_soc_bb_construction = true; - dc->dml2_options.minimize_dispclk_using_odm = true; - - dc->dml2_options.callbacks.dc = dc; - dc->dml2_options.callbacks.build_scaling_params = &resource_build_scaling_params; - dc->dml2_options.callbacks.can_support_mclk_switch_using_fw_based_vblank_stretch = &dcn30_can_support_mclk_switch_using_fw_based_vblank_stretch; - dc->dml2_options.callbacks.acquire_secondary_pipe_for_mpc_odm = &dc_resource_acquire_secondary_pipe_for_mpc_odm_legacy; - dc->dml2_options.callbacks.update_pipes_for_stream_with_slice_count = &resource_update_pipes_for_stream_with_slice_count; - dc->dml2_options.callbacks.update_pipes_for_plane_with_slice_count = &resource_update_pipes_for_plane_with_slice_count; - dc->dml2_options.callbacks.get_mpc_slice_index = &resource_get_mpc_slice_index; - dc->dml2_options.callbacks.get_odm_slice_index = &resource_get_odm_slice_index; - dc->dml2_options.callbacks.get_opp_head = &resource_get_opp_head; - - dc->dml2_options.svp_pstate.callbacks.dc = dc; - dc->dml2_options.svp_pstate.callbacks.add_plane_to_context = &dc_add_plane_to_context; - dc->dml2_options.svp_pstate.callbacks.add_stream_to_ctx = &dc_add_stream_to_ctx; - dc->dml2_options.svp_pstate.callbacks.build_scaling_params = &resource_build_scaling_params; - dc->dml2_options.svp_pstate.callbacks.create_plane = &dc_create_plane_state; - dc->dml2_options.svp_pstate.callbacks.remove_plane_from_context = &dc_remove_plane_from_context; - dc->dml2_options.svp_pstate.callbacks.remove_stream_from_ctx = &dc_remove_stream_from_ctx; - dc->dml2_options.svp_pstate.callbacks.create_stream_for_sink = &dc_create_stream_for_sink; - dc->dml2_options.svp_pstate.callbacks.plane_state_release = &dc_plane_state_release; - dc->dml2_options.svp_pstate.callbacks.stream_release = &dc_stream_release; - dc->dml2_options.svp_pstate.callbacks.release_dsc = &dcn20_release_dsc; - - dc->dml2_options.svp_pstate.subvp_fw_processing_delay_us = dc->caps.subvp_fw_processing_delay_us; - dc->dml2_options.svp_pstate.subvp_prefetch_end_to_mall_start_us = dc->caps.subvp_prefetch_end_to_mall_start_us; - dc->dml2_options.svp_pstate.subvp_pstate_allow_width_us = dc->caps.subvp_pstate_allow_width_us; - dc->dml2_options.svp_pstate.subvp_swath_height_margin_lines = dc->caps.subvp_swath_height_margin_lines; - - dc->dml2_options.svp_pstate.force_disable_subvp = dc->debug.force_disable_subvp; - dc->dml2_options.svp_pstate.force_enable_subvp = dc->debug.force_subvp_mclk_switch; - - dc->dml2_options.mall_cfg.cache_line_size_bytes = dc->caps.cache_line_size; - dc->dml2_options.mall_cfg.cache_num_ways = dc->caps.cache_num_ways; - dc->dml2_options.mall_cfg.max_cab_allocation_bytes = dc->caps.max_cab_allocation_bytes; - dc->dml2_options.mall_cfg.mblk_height_4bpe_pixels = DCN3_2_MBLK_HEIGHT_4BPE; - dc->dml2_options.mall_cfg.mblk_height_8bpe_pixels = DCN3_2_MBLK_HEIGHT_8BPE; - dc->dml2_options.mall_cfg.mblk_size_bytes = DCN3_2_MALL_MBLK_SIZE_BYTES; - dc->dml2_options.mall_cfg.mblk_width_pixels = DCN3_2_MBLK_WIDTH; - - dc->dml2_options.max_segments_per_hubp = 18; - dc->dml2_options.det_segment_size = DCN3_2_DET_SEG_SIZE; - - return true; - -create_fail: - - dcn321_resource_destruct(pool); - - return false; -} - -struct resource_pool *dcn321_create_resource_pool( - const struct dc_init_data *init_data, - struct dc *dc) -{ - struct dcn321_resource_pool *pool = - kzalloc(sizeof(struct dcn321_resource_pool), GFP_KERNEL); - - if (!pool) - return NULL; - - if (dcn321_resource_construct(init_data->num_virtual_links, dc, pool)) - return &pool->base; - - BREAK_TO_DEBUGGER(); - kfree(pool); - return NULL; -} diff --git a/drivers/gpu/drm/amd/display/dc/dcn321/dcn321_resource.h b/drivers/gpu/drm/amd/display/dc/dcn321/dcn321_resource.h deleted file mode 100644 index 82cbf009f2d3..000000000000 --- a/drivers/gpu/drm/amd/display/dc/dcn321/dcn321_resource.h +++ /dev/null @@ -1,45 +0,0 @@ -/* - * Copyright 2020 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 _DCN321_RESOURCE_H_ -#define _DCN321_RESOURCE_H_ - -#include "core_types.h" - -#define TO_DCN321_RES_POOL(pool)\ - container_of(pool, struct dcn321_resource_pool, base) - -extern struct _vcs_dpi_ip_params_st dcn3_21_ip; -extern struct _vcs_dpi_soc_bounding_box_st dcn3_21_soc; - -struct dcn321_resource_pool { - struct resource_pool base; -}; - -struct resource_pool *dcn321_create_resource_pool( - const struct dc_init_data *init_data, - struct dc *dc); - -#endif /* _DCN321_RESOURCE_H_ */ diff --git a/drivers/gpu/drm/amd/display/dc/dcn35/Makefile b/drivers/gpu/drm/amd/display/dc/dcn35/Makefile index 20d0eef1a13b..719afb5a3b12 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn35/Makefile +++ b/drivers/gpu/drm/amd/display/dc/dcn35/Makefile @@ -10,7 +10,7 @@ # # Makefile for DCN35. -DCN35 = dcn35_resource.o dcn35_init.o dcn35_dio_stream_encoder.o \ +DCN35 = dcn35_init.o dcn35_dio_stream_encoder.o \ dcn35_dio_link_encoder.o dcn35_dccg.o dcn35_optc.o \ dcn35_dsc.o dcn35_hubp.o dcn35_hubbub.o \ dcn35_mmhubbub.o dcn35_opp.o dcn35_dpp.o dcn35_pg_cntl.o dcn35_dwb.o diff --git a/drivers/gpu/drm/amd/display/dc/dcn35/dcn35_resource.c b/drivers/gpu/drm/amd/display/dc/dcn35/dcn35_resource.c deleted file mode 100644 index 7a3faf2b1f06..000000000000 --- a/drivers/gpu/drm/amd/display/dc/dcn35/dcn35_resource.c +++ /dev/null @@ -1,2141 +0,0 @@ -/* SPDX-License-Identifier: MIT */ -/* - * Copyright 2023 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 "dm_services.h" -#include "dc.h" - -#include "dcn31/dcn31_init.h" -#include "dcn35/dcn35_init.h" - -#include "resource.h" -#include "include/irq_service_interface.h" -#include "dcn35_resource.h" -#include "dml2/dml2_wrapper.h" - -#include "dcn20/dcn20_resource.h" -#include "dcn30/dcn30_resource.h" -#include "dcn31/dcn31_resource.h" -#include "dcn32/dcn32_resource.h" - -#include "dcn10/dcn10_ipp.h" -#include "dcn30/dcn30_hubbub.h" -#include "dcn31/dcn31_hubbub.h" -#include "dcn35/dcn35_hubbub.h" -#include "dcn32/dcn32_mpc.h" -#include "dcn35/dcn35_hubp.h" -#include "irq/dcn35/irq_service_dcn35.h" -#include "dcn35/dcn35_dpp.h" -#include "dcn35/dcn35_optc.h" -#include "dcn20/dcn20_hwseq.h" -#include "dcn30/dcn30_hwseq.h" -#include "dce110/dce110_hwseq.h" -#include "dcn35/dcn35_opp.h" -#include "dcn35/dcn35_dsc.h" -#include "dcn30/dcn30_vpg.h" -#include "dcn30/dcn30_afmt.h" -#include "dcn31/dcn31_dio_link_encoder.h" -#include "dcn35/dcn35_dio_stream_encoder.h" -#include "dcn31/dcn31_hpo_dp_stream_encoder.h" -#include "dcn31/dcn31_hpo_dp_link_encoder.h" -#include "dcn32/dcn32_hpo_dp_link_encoder.h" -#include "link.h" -#include "dcn31/dcn31_apg.h" -#include "dcn32/dcn32_dio_link_encoder.h" -#include "dcn31/dcn31_vpg.h" -#include "dcn31/dcn31_afmt.h" -#include "dce/dce_clock_source.h" -#include "dce/dce_audio.h" -#include "dce/dce_hwseq.h" -#include "clk_mgr.h" -#include "virtual/virtual_stream_encoder.h" -#include "dce110/dce110_resource.h" -#include "dml/display_mode_vba.h" -#include "dcn35/dcn35_dccg.h" -#include "dcn35/dcn35_pg_cntl.h" -#include "dcn10/dcn10_resource.h" -#include "dcn31/dcn31_panel_cntl.h" -#include "dcn35/dcn35_hwseq.h" -#include "dcn35_dio_link_encoder.h" -#include "dml/dcn31/dcn31_fpu.h" /*todo*/ -#include "dml/dcn35/dcn35_fpu.h" -#include "dcn35/dcn35_dwb.h" -#include "dcn35/dcn35_mmhubbub.h" - -#include "dcn/dcn_3_5_0_offset.h" -#include "dcn/dcn_3_5_0_sh_mask.h" -#include "nbio/nbio_7_11_0_offset.h" -#include "mmhub/mmhub_3_3_0_offset.h" -#include "mmhub/mmhub_3_3_0_sh_mask.h" - -#define DSCC0_DSCC_CONFIG0__ICH_RESET_AT_END_OF_LINE__SHIFT 0x0 -#define DSCC0_DSCC_CONFIG0__ICH_RESET_AT_END_OF_LINE_MASK 0x0000000FL - -#include "reg_helper.h" -#include "dce/dmub_abm.h" -#include "dce/dmub_psr.h" -#include "dce/dce_aux.h" -#include "dce/dce_i2c.h" -#include "dml/dcn31/display_mode_vba_31.h" /*temp*/ -#include "vm_helper.h" -#include "dcn20/dcn20_vmid.h" - -#include "link_enc_cfg.h" -#define DC_LOGGER_INIT(logger) - -enum dcn35_clk_src_array_id { - DCN35_CLK_SRC_PLL0, - DCN35_CLK_SRC_PLL1, - DCN35_CLK_SRC_PLL2, - DCN35_CLK_SRC_PLL3, - DCN35_CLK_SRC_PLL4, - DCN35_CLK_SRC_TOTAL -}; - -/* begin ********************* - * macros to expend register list macro defined in HW object header file - */ - -/* DCN */ -/* TODO awful hack. fixup dcn20_dwb.h */ -#undef BASE_INNER -#define BASE_INNER(seg) ctx->dcn_reg_offsets[seg] - -#define BASE(seg) BASE_INNER(seg) - -#define SR(reg_name)\ - REG_STRUCT.reg_name = BASE(reg ## reg_name ## _BASE_IDX) + \ - reg ## reg_name - -#define SR_ARR(reg_name, id) \ - REG_STRUCT[id].reg_name = BASE(reg##reg_name##_BASE_IDX) + reg##reg_name - -#define SR_ARR_INIT(reg_name, id, value) \ - REG_STRUCT[id].reg_name = value - -#define SRI(reg_name, block, id)\ - REG_STRUCT.reg_name = BASE(reg ## block ## id ## _ ## reg_name ## _BASE_IDX) + \ - reg ## block ## id ## _ ## reg_name - -#define SRI_ARR(reg_name, block, id)\ - REG_STRUCT[id].reg_name = BASE(reg ## block ## id ## _ ## reg_name ## _BASE_IDX) + \ - reg ## block ## id ## _ ## reg_name - -#define SR_ARR_I2C(reg_name, id) \ - REG_STRUCT[id-1].reg_name = BASE(reg##reg_name##_BASE_IDX) + reg##reg_name - -#define SRI_ARR_I2C(reg_name, block, id)\ - REG_STRUCT[id-1].reg_name = BASE(reg ## block ## id ## _ ## reg_name ## _BASE_IDX) + \ - reg ## block ## id ## _ ## reg_name - -#define SRI_ARR_ALPHABET(reg_name, block, index, id)\ - REG_STRUCT[index].reg_name = BASE(reg ## block ## id ## _ ## reg_name ## _BASE_IDX) + \ - reg ## block ## id ## _ ## reg_name - -#define SRI2(reg_name, block, id)\ - .reg_name = BASE(reg ## reg_name ## _BASE_IDX) + \ - reg ## reg_name - -#define SRI2_ARR(reg_name, block, id)\ - REG_STRUCT[id].reg_name = BASE(reg ## reg_name ## _BASE_IDX) + \ - reg ## reg_name - -#define SRIR(var_name, reg_name, block, id)\ - .var_name = BASE(reg ## block ## id ## _ ## reg_name ## _BASE_IDX) + \ - reg ## block ## id ## _ ## reg_name - -#define SRII(reg_name, block, id)\ - REG_STRUCT.reg_name[id] = BASE(reg ## block ## id ## _ ## reg_name ## _BASE_IDX) + \ - reg ## block ## id ## _ ## reg_name - -#define SRII_ARR_2(reg_name, block, id, inst)\ - REG_STRUCT[inst].reg_name[id] = BASE(reg ## block ## id ## _ ## reg_name ## _BASE_IDX) + \ - reg ## block ## id ## _ ## reg_name - -#define SRII_MPC_RMU(reg_name, block, id)\ - .RMU##_##reg_name[id] = BASE(reg ## block ## id ## _ ## reg_name ## _BASE_IDX) + \ - reg ## block ## id ## _ ## reg_name - -#define SRII_DWB(reg_name, temp_name, block, id)\ - REG_STRUCT.reg_name[id] = BASE(reg ## block ## id ## _ ## temp_name ## _BASE_IDX) + \ - reg ## block ## id ## _ ## temp_name - -#define SF_DWB2(reg_name, block, id, field_name, post_fix) \ - .field_name = reg_name ## __ ## field_name ## post_fix - -#define DCCG_SRII(reg_name, block, id)\ - REG_STRUCT.block ## _ ## reg_name[id] = BASE(reg ## block ## id ## _ ## reg_name ## _BASE_IDX) + \ - reg ## block ## id ## _ ## reg_name - -#define VUPDATE_SRII(reg_name, block, id)\ - REG_STRUCT.reg_name[id] = BASE(reg ## reg_name ## _ ## block ## id ## _BASE_IDX) + \ - reg ## reg_name ## _ ## block ## id - -/* NBIO */ -#define NBIO_BASE_INNER(seg) ctx->nbio_reg_offsets[seg] - -#define NBIO_BASE(seg) \ - NBIO_BASE_INNER(seg) - -#define NBIO_SR(reg_name)\ - REG_STRUCT.reg_name = NBIO_BASE(regBIF_BX2_ ## reg_name ## _BASE_IDX) + \ - regBIF_BX2_ ## reg_name - -#define NBIO_SR_ARR(reg_name, id)\ - REG_STRUCT[id].reg_name = NBIO_BASE(regBIF_BX2_ ## reg_name ## _BASE_IDX) + \ - regBIF_BX2_ ## reg_name - -#define bios_regs_init() \ - ( \ - NBIO_SR(BIOS_SCRATCH_3),\ - NBIO_SR(BIOS_SCRATCH_6)\ - ) - -static struct bios_registers bios_regs; - -#define clk_src_regs_init(index, pllid)\ - CS_COMMON_REG_LIST_DCN3_0_RI(index, pllid) - -static struct dce110_clk_src_regs clk_src_regs[5]; - -static const struct dce110_clk_src_shift cs_shift = { - CS_COMMON_MASK_SH_LIST_DCN3_1_4(__SHIFT) -}; - -static const struct dce110_clk_src_mask cs_mask = { - CS_COMMON_MASK_SH_LIST_DCN3_1_4(_MASK) -}; - -#define abm_regs_init(id)\ - ABM_DCN32_REG_LIST_RI(id) - -static struct dce_abm_registers abm_regs[4]; - -static const struct dce_abm_shift abm_shift = { - ABM_MASK_SH_LIST_DCN35(__SHIFT) -}; - -static const struct dce_abm_mask abm_mask = { - ABM_MASK_SH_LIST_DCN35(_MASK) -}; - -#define audio_regs_init(id)\ - AUD_COMMON_REG_LIST_RI(id) - -static struct dce_audio_registers audio_regs[7]; - - -#define DCE120_AUD_COMMON_MASK_SH_LIST(mask_sh)\ - SF(AZF0ENDPOINT0_AZALIA_F0_CODEC_ENDPOINT_INDEX, AZALIA_ENDPOINT_REG_INDEX, mask_sh),\ - SF(AZF0ENDPOINT0_AZALIA_F0_CODEC_ENDPOINT_DATA, AZALIA_ENDPOINT_REG_DATA, mask_sh),\ - AUD_COMMON_MASK_SH_LIST_BASE(mask_sh) - -static const struct dce_audio_shift audio_shift = { - DCE120_AUD_COMMON_MASK_SH_LIST(__SHIFT) -}; - -static const struct dce_audio_mask audio_mask = { - DCE120_AUD_COMMON_MASK_SH_LIST(_MASK) -}; - -#define vpg_regs_init(id)\ - VPG_DCN31_REG_LIST_RI(id) - -static struct dcn31_vpg_registers vpg_regs[10]; - -static const struct dcn31_vpg_shift vpg_shift = { - DCN31_VPG_MASK_SH_LIST(__SHIFT) -}; - -static const struct dcn31_vpg_mask vpg_mask = { - DCN31_VPG_MASK_SH_LIST(_MASK) -}; - -#define afmt_regs_init(id)\ - AFMT_DCN31_REG_LIST_RI(id) - -static struct dcn31_afmt_registers afmt_regs[6]; - -static const struct dcn31_afmt_shift afmt_shift = { - DCN31_AFMT_MASK_SH_LIST(__SHIFT) -}; - -static const struct dcn31_afmt_mask afmt_mask = { - DCN31_AFMT_MASK_SH_LIST(_MASK) -}; - -#define apg_regs_init(id)\ - APG_DCN31_REG_LIST_RI(id) - -static struct dcn31_apg_registers apg_regs[4]; - -static const struct dcn31_apg_shift apg_shift = { - DCN31_APG_MASK_SH_LIST(__SHIFT) -}; - -static const struct dcn31_apg_mask apg_mask = { - DCN31_APG_MASK_SH_LIST(_MASK) -}; - -#define stream_enc_regs_init(id)\ - SE_DCN35_REG_LIST_RI(id) - -static struct dcn10_stream_enc_registers stream_enc_regs[5]; - -static const struct dcn10_stream_encoder_shift se_shift = { - SE_COMMON_MASK_SH_LIST_DCN35(__SHIFT) -}; - -static const struct dcn10_stream_encoder_mask se_mask = { - SE_COMMON_MASK_SH_LIST_DCN35(_MASK) -}; - -#define aux_regs_init(id)\ - DCN2_AUX_REG_LIST_RI(id) - -static struct dcn10_link_enc_aux_registers link_enc_aux_regs[5]; - -#define hpd_regs_init(id)\ - HPD_REG_LIST_RI(id) - -static struct dcn10_link_enc_hpd_registers link_enc_hpd_regs[5]; - - -static const struct dce110_aux_registers_shift aux_shift = { - DCN_AUX_MASK_SH_LIST(__SHIFT) -}; - -static const struct dce110_aux_registers_mask aux_mask = { - DCN_AUX_MASK_SH_LIST(_MASK) -}; - -#define link_regs_init(id, phyid)\ - ( \ - LE_DCN35_REG_LIST_RI(id), \ - UNIPHY_DCN2_REG_LIST_RI(id, phyid)\ - ) - -static struct dcn10_link_enc_registers link_enc_regs[5]; - -static const struct dcn10_link_enc_shift le_shift = { - LINK_ENCODER_MASK_SH_LIST_DCN35(__SHIFT), \ - //DPCS_DCN31_MASK_SH_LIST(__SHIFT) -}; - -static const struct dcn10_link_enc_mask le_mask = { - LINK_ENCODER_MASK_SH_LIST_DCN35(_MASK), \ - //DPCS_DCN31_MASK_SH_LIST(_MASK) -}; - -#define hpo_dp_stream_encoder_reg_init(id)\ - DCN3_1_HPO_DP_STREAM_ENC_REG_LIST_RI(id) - -static struct dcn31_hpo_dp_stream_encoder_registers hpo_dp_stream_enc_regs[4]; - -static const struct dcn31_hpo_dp_stream_encoder_shift hpo_dp_se_shift = { - DCN3_1_HPO_DP_STREAM_ENC_MASK_SH_LIST(__SHIFT) -}; - -static const struct dcn31_hpo_dp_stream_encoder_mask hpo_dp_se_mask = { - DCN3_1_HPO_DP_STREAM_ENC_MASK_SH_LIST(_MASK) -}; - -#define hpo_dp_link_encoder_reg_init(id)\ - DCN3_1_HPO_DP_LINK_ENC_REG_LIST_RI(id) - /*DCN3_1_RDPCSTX_REG_LIST(0),*/ - /*DCN3_1_RDPCSTX_REG_LIST(1),*/ - /*DCN3_1_RDPCSTX_REG_LIST(2),*/ - /*DCN3_1_RDPCSTX_REG_LIST(3),*/ - -static struct dcn31_hpo_dp_link_encoder_registers hpo_dp_link_enc_regs[2]; - -static const struct dcn31_hpo_dp_link_encoder_shift hpo_dp_le_shift = { - DCN3_1_HPO_DP_LINK_ENC_COMMON_MASK_SH_LIST(__SHIFT) -}; - -static const struct dcn31_hpo_dp_link_encoder_mask hpo_dp_le_mask = { - DCN3_1_HPO_DP_LINK_ENC_COMMON_MASK_SH_LIST(_MASK) -}; - -#define dpp_regs_init(id)\ - DPP_REG_LIST_DCN35_RI(id) - -static struct dcn3_dpp_registers dpp_regs[4]; - -static const struct dcn35_dpp_shift tf_shift = { - DPP_REG_LIST_SH_MASK_DCN35(__SHIFT) -}; - -static const struct dcn35_dpp_mask tf_mask = { - DPP_REG_LIST_SH_MASK_DCN35(_MASK) -}; - -#define opp_regs_init(id)\ - OPP_REG_LIST_DCN35_RI(id) - -static struct dcn35_opp_registers opp_regs[4]; - -static const struct dcn35_opp_shift opp_shift = { - OPP_MASK_SH_LIST_DCN35(__SHIFT) -}; - -static const struct dcn35_opp_mask opp_mask = { - OPP_MASK_SH_LIST_DCN35(_MASK) -}; - -#define aux_engine_regs_init(id)\ - ( \ - AUX_COMMON_REG_LIST0_RI(id), \ - SR_ARR_INIT(AUXN_IMPCAL, id, 0), \ - SR_ARR_INIT(AUXP_IMPCAL, id, 0), \ - SR_ARR_INIT(AUX_RESET_MASK, id, DP_AUX0_AUX_CONTROL__AUX_RESET_MASK) \ - ) - -static struct dce110_aux_registers aux_engine_regs[5]; - -#define dwbc_regs_dcn3_init(id)\ - DWBC_COMMON_REG_LIST_DCN30_RI(id) - -static struct dcn30_dwbc_registers dwbc35_regs[1]; - -static const struct dcn35_dwbc_shift dwbc35_shift = { - DWBC_COMMON_MASK_SH_LIST_DCN35(__SHIFT) -}; - -static const struct dcn35_dwbc_mask dwbc35_mask = { - DWBC_COMMON_MASK_SH_LIST_DCN35(_MASK) -}; - -#define mcif_wb_regs_dcn3_init(id)\ - MCIF_WB_COMMON_REG_LIST_DCN3_5_RI(id) - -static struct dcn35_mmhubbub_registers mcif_wb35_regs[1]; - -static const struct dcn35_mmhubbub_shift mcif_wb35_shift = { - MCIF_WB_COMMON_MASK_SH_LIST_DCN3_5(__SHIFT) -}; - -static const struct dcn35_mmhubbub_mask mcif_wb35_mask = { - MCIF_WB_COMMON_MASK_SH_LIST_DCN3_5(_MASK) -}; - -#define dsc_regsDCN35_init(id)\ - DSC_REG_LIST_DCN20_RI(id) - -static struct dcn20_dsc_registers dsc_regs[4]; - -static const struct dcn35_dsc_shift dsc_shift = { - DSC_REG_LIST_SH_MASK_DCN35(__SHIFT) -}; - -static const struct dcn35_dsc_mask dsc_mask = { - DSC_REG_LIST_SH_MASK_DCN35(_MASK) -}; - -static struct dcn30_mpc_registers mpc_regs; - -#define dcn_mpc_regs_init() \ - MPC_REG_LIST_DCN3_2_RI(0),\ - MPC_REG_LIST_DCN3_2_RI(1),\ - MPC_REG_LIST_DCN3_2_RI(2),\ - MPC_REG_LIST_DCN3_2_RI(3),\ - MPC_OUT_MUX_REG_LIST_DCN3_0_RI(0),\ - MPC_OUT_MUX_REG_LIST_DCN3_0_RI(1),\ - MPC_OUT_MUX_REG_LIST_DCN3_0_RI(2),\ - MPC_OUT_MUX_REG_LIST_DCN3_0_RI(3),\ - MPC_DWB_MUX_REG_LIST_DCN3_0_RI(0) - -static const struct dcn30_mpc_shift mpc_shift = { - MPC_COMMON_MASK_SH_LIST_DCN32(__SHIFT) -}; - -static const struct dcn30_mpc_mask mpc_mask = { - MPC_COMMON_MASK_SH_LIST_DCN32(_MASK) -}; - -#define optc_regs_init(id)\ - OPTC_COMMON_REG_LIST_DCN3_5_RI(id) - -static struct dcn_optc_registers optc_regs[4]; - -static const struct dcn_optc_shift optc_shift = { - OPTC_COMMON_MASK_SH_LIST_DCN3_5(__SHIFT) -}; - -static const struct dcn_optc_mask optc_mask = { - OPTC_COMMON_MASK_SH_LIST_DCN3_5(_MASK) -}; - -#define hubp_regs_init(id)\ - HUBP_REG_LIST_DCN30_RI(id) - -static struct dcn_hubp2_registers hubp_regs[4]; - - -static const struct dcn35_hubp2_shift hubp_shift = { - HUBP_MASK_SH_LIST_DCN35(__SHIFT) -}; - -static const struct dcn35_hubp2_mask hubp_mask = { - HUBP_MASK_SH_LIST_DCN35(_MASK) -}; - -static struct dcn_hubbub_registers hubbub_reg; - -#define hubbub_reg_init()\ - HUBBUB_REG_LIST_DCN35(0) - -static const struct dcn_hubbub_shift hubbub_shift = { - HUBBUB_MASK_SH_LIST_DCN35(__SHIFT) -}; - -static const struct dcn_hubbub_mask hubbub_mask = { - HUBBUB_MASK_SH_LIST_DCN35(_MASK) -}; - -static struct dccg_registers dccg_regs; - -#define dccg_regs_init()\ - DCCG_REG_LIST_DCN35() - -static const struct dccg_shift dccg_shift = { - DCCG_MASK_SH_LIST_DCN35(__SHIFT) -}; - -static const struct dccg_mask dccg_mask = { - DCCG_MASK_SH_LIST_DCN35(_MASK) -}; - -static struct pg_cntl_registers pg_cntl_regs; - -#define pg_cntl_dcn35_regs_init() \ - PG_CNTL_REG_LIST_DCN35() - -static const struct pg_cntl_shift pg_cntl_shift = { - PG_CNTL_MASK_SH_LIST_DCN35(__SHIFT) -}; - -static const struct pg_cntl_mask pg_cntl_mask = { - PG_CNTL_MASK_SH_LIST_DCN35(_MASK) -}; - -#define SRII2(reg_name_pre, reg_name_post, id)\ - .reg_name_pre ## _ ## reg_name_post[id] = BASE(reg ## reg_name_pre \ - ## id ## _ ## reg_name_post ## _BASE_IDX) + \ - reg ## reg_name_pre ## id ## _ ## reg_name_post - -static struct dce_hwseq_registers hwseq_reg; - -#define hwseq_reg_init()\ - HWSEQ_DCN35_REG_LIST() - -#define HWSEQ_DCN35_MASK_SH_LIST(mask_sh)\ - HWSEQ_DCN_MASK_SH_LIST(mask_sh), \ - HWS_SF(, DCHUBBUB_GLOBAL_TIMER_CNTL, DCHUBBUB_GLOBAL_TIMER_REFDIV, mask_sh), \ - HWS_SF(, DCHUBBUB_ARB_HOSTVM_CNTL, DISABLE_HOSTVM_FORCE_ALLOW_PSTATE, mask_sh), \ - HWS_SF(, DOMAIN0_PG_CONFIG, DOMAIN_POWER_FORCEON, mask_sh), \ - HWS_SF(, DOMAIN0_PG_CONFIG, DOMAIN_POWER_GATE, mask_sh), \ - HWS_SF(, DOMAIN1_PG_CONFIG, DOMAIN_POWER_FORCEON, mask_sh), \ - HWS_SF(, DOMAIN1_PG_CONFIG, DOMAIN_POWER_GATE, mask_sh), \ - HWS_SF(, DOMAIN2_PG_CONFIG, DOMAIN_POWER_FORCEON, mask_sh), \ - HWS_SF(, DOMAIN2_PG_CONFIG, DOMAIN_POWER_GATE, mask_sh), \ - HWS_SF(, DOMAIN3_PG_CONFIG, DOMAIN_POWER_FORCEON, mask_sh), \ - HWS_SF(, DOMAIN3_PG_CONFIG, DOMAIN_POWER_GATE, mask_sh), \ - HWS_SF(, DOMAIN16_PG_CONFIG, DOMAIN_POWER_FORCEON, mask_sh), \ - HWS_SF(, DOMAIN16_PG_CONFIG, DOMAIN_POWER_GATE, mask_sh), \ - HWS_SF(, DOMAIN17_PG_CONFIG, DOMAIN_POWER_FORCEON, mask_sh), \ - HWS_SF(, DOMAIN17_PG_CONFIG, DOMAIN_POWER_GATE, mask_sh), \ - HWS_SF(, DOMAIN18_PG_CONFIG, DOMAIN_POWER_FORCEON, mask_sh), \ - HWS_SF(, DOMAIN18_PG_CONFIG, DOMAIN_POWER_GATE, mask_sh), \ - HWS_SF(, DOMAIN19_PG_CONFIG, DOMAIN_POWER_FORCEON, mask_sh), \ - HWS_SF(, DOMAIN19_PG_CONFIG, DOMAIN_POWER_GATE, mask_sh), \ - HWS_SF(, DOMAIN22_PG_CONFIG, DOMAIN_POWER_FORCEON, mask_sh), \ - HWS_SF(, DOMAIN22_PG_CONFIG, DOMAIN_POWER_GATE, mask_sh), \ - HWS_SF(, DOMAIN23_PG_CONFIG, DOMAIN_POWER_FORCEON, mask_sh), \ - HWS_SF(, DOMAIN23_PG_CONFIG, DOMAIN_POWER_GATE, mask_sh), \ - HWS_SF(, DOMAIN24_PG_CONFIG, DOMAIN_POWER_FORCEON, mask_sh), \ - HWS_SF(, DOMAIN24_PG_CONFIG, DOMAIN_POWER_GATE, mask_sh), \ - HWS_SF(, DOMAIN25_PG_CONFIG, DOMAIN_POWER_FORCEON, mask_sh), \ - HWS_SF(, DOMAIN25_PG_CONFIG, DOMAIN_POWER_GATE, mask_sh), \ - HWS_SF(, DOMAIN0_PG_STATUS, DOMAIN_PGFSM_PWR_STATUS, mask_sh), \ - HWS_SF(, DOMAIN1_PG_STATUS, DOMAIN_PGFSM_PWR_STATUS, mask_sh), \ - HWS_SF(, DOMAIN2_PG_STATUS, DOMAIN_PGFSM_PWR_STATUS, mask_sh), \ - HWS_SF(, DOMAIN3_PG_STATUS, DOMAIN_PGFSM_PWR_STATUS, mask_sh), \ - HWS_SF(, DOMAIN16_PG_STATUS, DOMAIN_PGFSM_PWR_STATUS, mask_sh), \ - HWS_SF(, DOMAIN17_PG_STATUS, DOMAIN_PGFSM_PWR_STATUS, mask_sh), \ - HWS_SF(, DOMAIN18_PG_STATUS, DOMAIN_PGFSM_PWR_STATUS, mask_sh), \ - HWS_SF(, DOMAIN19_PG_STATUS, DOMAIN_PGFSM_PWR_STATUS, mask_sh), \ - HWS_SF(, DOMAIN22_PG_STATUS, DOMAIN_PGFSM_PWR_STATUS, mask_sh), \ - HWS_SF(, DOMAIN23_PG_STATUS, DOMAIN_PGFSM_PWR_STATUS, mask_sh), \ - HWS_SF(, DOMAIN24_PG_STATUS, DOMAIN_PGFSM_PWR_STATUS, mask_sh), \ - HWS_SF(, DOMAIN25_PG_STATUS, DOMAIN_PGFSM_PWR_STATUS, mask_sh), \ - HWS_SF(, DC_IP_REQUEST_CNTL, IP_REQUEST_EN, mask_sh), \ - HWS_SF(, AZALIA_AUDIO_DTO, AZALIA_AUDIO_DTO_MODULE, mask_sh), \ - HWS_SF(, HPO_TOP_CLOCK_CONTROL, HPO_HDMISTREAMCLK_G_GATE_DIS, mask_sh), \ - HWS_SF(, ODM_MEM_PWR_CTRL3, ODM_MEM_UNASSIGNED_PWR_MODE, mask_sh), \ - HWS_SF(, ODM_MEM_PWR_CTRL3, ODM_MEM_VBLANK_PWR_MODE, mask_sh), \ - HWS_SF(, DIO_MEM_PWR_CTRL, I2C_LIGHT_SLEEP_FORCE, mask_sh), \ - HWS_SF(, HPO_TOP_HW_CONTROL, HPO_IO_EN, mask_sh),\ - HWS_SF(, DMU_CLK_CNTL, DISPCLK_R_DMU_GATE_DIS, mask_sh),\ - HWS_SF(, DMU_CLK_CNTL, DISPCLK_G_RBBMIF_GATE_DIS, mask_sh),\ - HWS_SF(, DMU_CLK_CNTL, RBBMIF_FGCG_REP_DIS, mask_sh),\ - HWS_SF(, DMU_CLK_CNTL, DPREFCLK_ALLOW_DS_CLKSTOP, mask_sh),\ - HWS_SF(, DMU_CLK_CNTL, DISPCLK_ALLOW_DS_CLKSTOP, mask_sh),\ - HWS_SF(, DMU_CLK_CNTL, DPPCLK_ALLOW_DS_CLKSTOP, mask_sh),\ - HWS_SF(, DMU_CLK_CNTL, DTBCLK_ALLOW_DS_CLKSTOP, mask_sh),\ - HWS_SF(, DMU_CLK_CNTL, DCFCLK_ALLOW_DS_CLKSTOP, mask_sh),\ - HWS_SF(, DMU_CLK_CNTL, DPIACLK_ALLOW_DS_CLKSTOP, mask_sh),\ - HWS_SF(, DMU_CLK_CNTL, LONO_FGCG_REP_DIS, mask_sh),\ - HWS_SF(, DMU_CLK_CNTL, LONO_DISPCLK_GATE_DISABLE, mask_sh),\ - HWS_SF(, DMU_CLK_CNTL, LONO_SOCCLK_GATE_DISABLE, mask_sh),\ - HWS_SF(, DMU_CLK_CNTL, LONO_DMCUBCLK_GATE_DISABLE, mask_sh),\ - HWS_SF(, DCCG_GATE_DISABLE_CNTL2, SYMCLKA_FE_GATE_DISABLE, mask_sh), \ - HWS_SF(, DCCG_GATE_DISABLE_CNTL2, SYMCLKB_FE_GATE_DISABLE, mask_sh), \ - HWS_SF(, DCCG_GATE_DISABLE_CNTL2, SYMCLKC_FE_GATE_DISABLE, mask_sh), \ - HWS_SF(, DCCG_GATE_DISABLE_CNTL2, SYMCLKD_FE_GATE_DISABLE, mask_sh), \ - HWS_SF(, DCCG_GATE_DISABLE_CNTL2, SYMCLKE_FE_GATE_DISABLE, mask_sh), \ - HWS_SF(, DCCG_GATE_DISABLE_CNTL2, HDMICHARCLK0_GATE_DISABLE, mask_sh), \ - HWS_SF(, DCCG_GATE_DISABLE_CNTL2, SYMCLKA_GATE_DISABLE, mask_sh), \ - HWS_SF(, DCCG_GATE_DISABLE_CNTL2, SYMCLKB_GATE_DISABLE, mask_sh), \ - HWS_SF(, DCCG_GATE_DISABLE_CNTL2, SYMCLKC_GATE_DISABLE, mask_sh), \ - HWS_SF(, DCCG_GATE_DISABLE_CNTL2, SYMCLKD_GATE_DISABLE, mask_sh), \ - HWS_SF(, DCCG_GATE_DISABLE_CNTL2, SYMCLKE_GATE_DISABLE, mask_sh), \ - HWS_SF(, DCCG_GATE_DISABLE_CNTL2, PHYASYMCLK_ROOT_GATE_DISABLE, mask_sh), \ - HWS_SF(, DCCG_GATE_DISABLE_CNTL2, PHYBSYMCLK_ROOT_GATE_DISABLE, mask_sh), \ - HWS_SF(, DCCG_GATE_DISABLE_CNTL2, PHYCSYMCLK_ROOT_GATE_DISABLE, mask_sh), \ - HWS_SF(, DCCG_GATE_DISABLE_CNTL2, PHYDSYMCLK_ROOT_GATE_DISABLE, mask_sh), \ - HWS_SF(, DCCG_GATE_DISABLE_CNTL2, PHYESYMCLK_ROOT_GATE_DISABLE, mask_sh) - -static const struct dce_hwseq_shift hwseq_shift = { - HWSEQ_DCN35_MASK_SH_LIST(__SHIFT) -}; - -static const struct dce_hwseq_mask hwseq_mask = { - HWSEQ_DCN35_MASK_SH_LIST(_MASK) -}; - -#define vmid_regs_init(id)\ - DCN20_VMID_REG_LIST_RI(id) - -static struct dcn_vmid_registers vmid_regs[16]; - -static const struct dcn20_vmid_shift vmid_shifts = { - DCN20_VMID_MASK_SH_LIST(__SHIFT) -}; - -static const struct dcn20_vmid_mask vmid_masks = { - DCN20_VMID_MASK_SH_LIST(_MASK) -}; - -static const struct resource_caps res_cap_dcn35 = { - .num_timing_generator = 4, - .num_opp = 4, - .num_video_plane = 4, - .num_audio = 5, - .num_stream_encoder = 5, - .num_dig_link_enc = 5, - .num_hpo_dp_stream_encoder = 4, - .num_hpo_dp_link_encoder = 2, - .num_pll = 4,/*1 c10 edp, 3xc20 combo PHY*/ - .num_dwb = 1, - .num_ddc = 5, - .num_vmid = 16, - .num_mpc_3dlut = 2, - .num_dsc = 4, -}; - -static const struct dc_plane_cap plane_cap = { - .type = DC_PLANE_TYPE_DCN_UNIVERSAL, - .per_pixel_alpha = true, - - .pixel_format_support = { - .argb8888 = true, - .nv12 = true, - .fp16 = true, - .p010 = true, - .ayuv = false, - }, - - .max_upscale_factor = { - .argb8888 = 16000, - .nv12 = 16000, - .fp16 = 16000 - }, - - // 6:1 downscaling ratio: 1000/6 = 166.666 - .max_downscale_factor = { - .argb8888 = 167, - .nv12 = 167, - .fp16 = 167 - }, - 64, - 64 -}; - -static const struct dc_debug_options debug_defaults_drv = { - .disable_dmcu = true, - .force_abm_enable = false, - .timing_trace = false, - .clock_trace = true, - .disable_pplib_clock_request = false, - .pipe_split_policy = MPC_SPLIT_AVOID, - .force_single_disp_pipe_split = false, - .disable_dcc = DCC_ENABLE, - .disable_dpp_power_gate = true, - .disable_hubp_power_gate = true, - .disable_clock_gate = true, - .disable_dsc_power_gate = true, - .vsr_support = true, - .performance_trace = false, - .max_downscale_src_width = 4096,/*upto true 4k*/ - .disable_pplib_wm_range = false, - .scl_reset_length10 = true, - .sanity_checks = false, - .underflow_assert_delay_us = 0xFFFFFFFF, - .dwb_fi_phase = -1, // -1 = disable, - .dmub_command_table = true, - .pstate_enabled = true, - .use_max_lb = true, - .enable_mem_low_power = { - .bits = { - .vga = false, - .i2c = true, - .dmcu = false, // This is previously known to cause hang on S3 cycles if enabled - .dscl = true, - .cm = true, - .mpc = true, - .optc = true, - .vpg = true, - .afmt = true, - } - }, - .root_clock_optimization = { - .bits = { - .dpp = true, - .dsc = true,/*dscclk and dsc pg*/ - .hdmistream = true, - .hdmichar = true, - .dpstream = true, - .symclk32_se = true, - .symclk32_le = true, - .symclk_fe = true, - .physymclk = true, - .dpiasymclk = true, - } - }, - .seamless_boot_odm_combine = DML_FAIL_SOURCE_PIXEL_FORMAT, - .enable_z9_disable_interface = true, /* Allow support for the PMFW interface for disable Z9*/ - .using_dml2 = true, - .support_eDP1_5 = true, - .enable_hpo_pg_support = false, - .enable_legacy_fast_update = true, - .enable_single_display_2to1_odm_policy = false, - .disable_idle_power_optimizations = true, - .dmcub_emulation = false, - .disable_boot_optimizations = false, - .disable_unbounded_requesting = false, - .disable_mem_low_power = false, - //must match enable_single_display_2to1_odm_policy to support dynamic ODM transitions - .enable_double_buffered_dsc_pg_support = true, - .enable_dp_dig_pixel_rate_div_policy = 1, - .disable_z10 = false, - .ignore_pg = true, - .psp_disabled_wa = true, - .ips2_eval_delay_us = 200, - .ips2_entry_delay_us = 400 -}; - -static const struct dc_panel_config panel_config_defaults = { - .psr = { - .disable_psr = false, - .disallow_psrsu = false, - }, - .ilr = { - .optimize_edp_link_rate = true, - }, -}; - -static void dcn35_dpp_destroy(struct dpp **dpp) -{ - kfree(TO_DCN20_DPP(*dpp)); - *dpp = NULL; -} - -static struct dpp *dcn35_dpp_create(struct dc_context *ctx, uint32_t inst) -{ - struct dcn3_dpp *dpp = kzalloc(sizeof(struct dcn3_dpp), GFP_KERNEL); - bool success = (dpp != NULL); - - if (!success) - return NULL; - -#undef REG_STRUCT -#define REG_STRUCT dpp_regs - dpp_regs_init(0), - dpp_regs_init(1), - dpp_regs_init(2), - dpp_regs_init(3); - - success = dpp35_construct(dpp, ctx, inst, &dpp_regs[inst], &tf_shift, - &tf_mask); - if (success) { - dpp35_set_fgcg( - dpp, - ctx->dc->debug.enable_fine_grain_clock_gating.bits.dpp); - return &dpp->base; - } - - BREAK_TO_DEBUGGER(); - kfree(dpp); - return NULL; -} - -static struct output_pixel_processor *dcn35_opp_create( - struct dc_context *ctx, uint32_t inst) -{ - struct dcn20_opp *opp = - kzalloc(sizeof(struct dcn20_opp), GFP_KERNEL); - - if (!opp) { - BREAK_TO_DEBUGGER(); - return NULL; - } - -#undef REG_STRUCT -#define REG_STRUCT opp_regs - opp_regs_init(0), - opp_regs_init(1), - opp_regs_init(2), - opp_regs_init(3); - - dcn35_opp_construct(opp, ctx, inst, - &opp_regs[inst], &opp_shift, &opp_mask); - - dcn35_opp_set_fgcg(opp, ctx->dc->debug.enable_fine_grain_clock_gating.bits.opp); - - return &opp->base; -} - -static struct dce_aux *dcn31_aux_engine_create( - struct dc_context *ctx, - uint32_t inst) -{ - struct aux_engine_dce110 *aux_engine = - kzalloc(sizeof(struct aux_engine_dce110), GFP_KERNEL); - - if (!aux_engine) - return NULL; - -#undef REG_STRUCT -#define REG_STRUCT aux_engine_regs - aux_engine_regs_init(0), - aux_engine_regs_init(1), - aux_engine_regs_init(2), - aux_engine_regs_init(3), - aux_engine_regs_init(4); - - dce110_aux_engine_construct(aux_engine, ctx, inst, - SW_AUX_TIMEOUT_PERIOD_MULTIPLIER * AUX_TIMEOUT_PERIOD, - &aux_engine_regs[inst], - &aux_mask, - &aux_shift, - ctx->dc->caps.extended_aux_timeout_support); - - return &aux_engine->base; -} - -#define i2c_inst_regs_init(id)\ - I2C_HW_ENGINE_COMMON_REG_LIST_DCN30_RI(id) - -static struct dce_i2c_registers i2c_hw_regs[5]; - -static const struct dce_i2c_shift i2c_shifts = { - I2C_COMMON_MASK_SH_LIST_DCN35(__SHIFT) -}; - -static const struct dce_i2c_mask i2c_masks = { - I2C_COMMON_MASK_SH_LIST_DCN35(_MASK) -}; - -/* ========================================================== */ - -/* - * DPIA index | Preferred Encoder | Host Router - * 0 | C | 0 - * 1 | First Available | 0 - * 2 | D | 1 - * 3 | First Available | 1 - */ -/* ========================================================== */ -static const enum engine_id dpia_to_preferred_enc_id_table[] = { - ENGINE_ID_DIGC, - ENGINE_ID_DIGC, - ENGINE_ID_DIGD, - ENGINE_ID_DIGD -}; - -static enum engine_id dcn35_get_preferred_eng_id_dpia(unsigned int dpia_index) -{ - return dpia_to_preferred_enc_id_table[dpia_index]; -} - -static struct dce_i2c_hw *dcn31_i2c_hw_create( - struct dc_context *ctx, - uint32_t inst) -{ - struct dce_i2c_hw *dce_i2c_hw = - kzalloc(sizeof(struct dce_i2c_hw), GFP_KERNEL); - - if (!dce_i2c_hw) - return NULL; - -#undef REG_STRUCT -#define REG_STRUCT i2c_hw_regs - i2c_inst_regs_init(1), - i2c_inst_regs_init(2), - i2c_inst_regs_init(3), - i2c_inst_regs_init(4), - i2c_inst_regs_init(5); - - dcn2_i2c_hw_construct(dce_i2c_hw, ctx, inst, - &i2c_hw_regs[inst], &i2c_shifts, &i2c_masks); - - return dce_i2c_hw; -} -static struct mpc *dcn35_mpc_create( - struct dc_context *ctx, - int num_mpcc, - int num_rmu) -{ - struct dcn30_mpc *mpc30 = kzalloc(sizeof(struct dcn30_mpc), GFP_KERNEL); - - if (!mpc30) - return NULL; - -#undef REG_STRUCT -#define REG_STRUCT mpc_regs - dcn_mpc_regs_init(); - - dcn32_mpc_construct(mpc30, ctx, - &mpc_regs, - &mpc_shift, - &mpc_mask, - num_mpcc, - num_rmu); - - return &mpc30->base; -} - -static struct hubbub *dcn35_hubbub_create(struct dc_context *ctx) -{ - int i; - - struct dcn20_hubbub *hubbub3 = kzalloc(sizeof(struct dcn20_hubbub), - GFP_KERNEL); - - if (!hubbub3) - return NULL; - -#undef REG_STRUCT -#define REG_STRUCT hubbub_reg - hubbub_reg_init(); - -#undef REG_STRUCT -#define REG_STRUCT vmid_regs - vmid_regs_init(0), - vmid_regs_init(1), - vmid_regs_init(2), - vmid_regs_init(3), - vmid_regs_init(4), - vmid_regs_init(5), - vmid_regs_init(6), - vmid_regs_init(7), - vmid_regs_init(8), - vmid_regs_init(9), - vmid_regs_init(10), - vmid_regs_init(11), - vmid_regs_init(12), - vmid_regs_init(13), - vmid_regs_init(14), - vmid_regs_init(15); - - hubbub35_construct(hubbub3, ctx, - &hubbub_reg, - &hubbub_shift, - &hubbub_mask, - 384,/*ctx->dc->dml.ip.det_buffer_size_kbytes,*/ - 8, /*ctx->dc->dml.ip.pixel_chunk_size_kbytes,*/ - 1792 /*ctx->dc->dml.ip.config_return_buffer_size_in_kbytes*/); - - - for (i = 0; i < res_cap_dcn35.num_vmid; i++) { - struct dcn20_vmid *vmid = &hubbub3->vmid[i]; - - vmid->ctx = ctx; - - vmid->regs = &vmid_regs[i]; - vmid->shifts = &vmid_shifts; - vmid->masks = &vmid_masks; - } - - return &hubbub3->base; -} - -static struct timing_generator *dcn35_timing_generator_create( - struct dc_context *ctx, - uint32_t instance) -{ - struct optc *tgn10 = - kzalloc(sizeof(struct optc), GFP_KERNEL); - - if (!tgn10) - return NULL; - -#undef REG_STRUCT -#define REG_STRUCT optc_regs - optc_regs_init(0), - optc_regs_init(1), - optc_regs_init(2), - optc_regs_init(3); - - tgn10->base.inst = instance; - tgn10->base.ctx = ctx; - - tgn10->tg_regs = &optc_regs[instance]; - tgn10->tg_shift = &optc_shift; - tgn10->tg_mask = &optc_mask; - - dcn35_timing_generator_init(tgn10); - - return &tgn10->base; -} - -static const struct encoder_feature_support link_enc_feature = { - .max_hdmi_deep_color = COLOR_DEPTH_121212, - .max_hdmi_pixel_clock = 600000, - .hdmi_ycbcr420_supported = true, - .dp_ycbcr420_supported = true, - .fec_supported = true, - .flags.bits.IS_HBR2_CAPABLE = true, - .flags.bits.IS_HBR3_CAPABLE = true, - .flags.bits.IS_TPS3_CAPABLE = true, - .flags.bits.IS_TPS4_CAPABLE = true -}; - -static struct link_encoder *dcn35_link_encoder_create( - struct dc_context *ctx, - const struct encoder_init_data *enc_init_data) -{ - struct dcn20_link_encoder *enc20 = - kzalloc(sizeof(struct dcn20_link_encoder), GFP_KERNEL); - - if (!enc20) - return NULL; - -#undef REG_STRUCT -#define REG_STRUCT link_enc_aux_regs - aux_regs_init(0), - aux_regs_init(1), - aux_regs_init(2), - aux_regs_init(3), - aux_regs_init(4); - -#undef REG_STRUCT -#define REG_STRUCT link_enc_hpd_regs - hpd_regs_init(0), - hpd_regs_init(1), - hpd_regs_init(2), - hpd_regs_init(3), - hpd_regs_init(4); - -#undef REG_STRUCT -#define REG_STRUCT link_enc_regs - link_regs_init(0, A), - link_regs_init(1, B), - link_regs_init(2, C), - link_regs_init(3, D), - link_regs_init(4, E); - - dcn35_link_encoder_construct(enc20, - enc_init_data, - &link_enc_feature, - &link_enc_regs[enc_init_data->transmitter], - &link_enc_aux_regs[enc_init_data->channel - 1], - &link_enc_hpd_regs[enc_init_data->hpd_source], - &le_shift, - &le_mask); - - return &enc20->enc10.base; -} - -/* Create a minimal link encoder object not associated with a particular - * physical connector. - * resource_funcs.link_enc_create_minimal - */ -static struct link_encoder *dcn31_link_enc_create_minimal( - struct dc_context *ctx, enum engine_id eng_id) -{ - struct dcn20_link_encoder *enc20; - - if ((eng_id - ENGINE_ID_DIGA) > ctx->dc->res_pool->res_cap->num_dig_link_enc) - return NULL; - - enc20 = kzalloc(sizeof(struct dcn20_link_encoder), GFP_KERNEL); - if (!enc20) - return NULL; - - dcn31_link_encoder_construct_minimal( - enc20, - ctx, - &link_enc_feature, - &link_enc_regs[eng_id - ENGINE_ID_DIGA], - eng_id); - - return &enc20->enc10.base; -} - -static struct panel_cntl *dcn31_panel_cntl_create(const struct panel_cntl_init_data *init_data) -{ - struct dcn31_panel_cntl *panel_cntl = - kzalloc(sizeof(struct dcn31_panel_cntl), GFP_KERNEL); - - if (!panel_cntl) - return NULL; - - dcn31_panel_cntl_construct(panel_cntl, init_data); - - return &panel_cntl->base; -} - -static void read_dce_straps( - struct dc_context *ctx, - struct resource_straps *straps) -{ - generic_reg_get(ctx, regDC_PINSTRAPS + BASE(regDC_PINSTRAPS_BASE_IDX), - FN(DC_PINSTRAPS, DC_PINSTRAPS_AUDIO), &straps->dc_pinstraps_audio); - -} - -static struct audio *dcn31_create_audio( - struct dc_context *ctx, unsigned int inst) -{ - -#undef REG_STRUCT -#define REG_STRUCT audio_regs - audio_regs_init(0), - audio_regs_init(1), - audio_regs_init(2), - audio_regs_init(3), - audio_regs_init(4); - audio_regs_init(5); - audio_regs_init(6); - - return dce_audio_create(ctx, inst, - &audio_regs[inst], &audio_shift, &audio_mask); -} - -static struct vpg *dcn31_vpg_create( - struct dc_context *ctx, - uint32_t inst) -{ - struct dcn31_vpg *vpg31 = kzalloc(sizeof(struct dcn31_vpg), GFP_KERNEL); - - if (!vpg31) - return NULL; - -#undef REG_STRUCT -#define REG_STRUCT vpg_regs - vpg_regs_init(0), - vpg_regs_init(1), - vpg_regs_init(2), - vpg_regs_init(3), - vpg_regs_init(4), - vpg_regs_init(5), - vpg_regs_init(6), - vpg_regs_init(7), - vpg_regs_init(8), - vpg_regs_init(9); - - vpg31_construct(vpg31, ctx, inst, - &vpg_regs[inst], - &vpg_shift, - &vpg_mask); - - return &vpg31->base; -} - -static struct afmt *dcn31_afmt_create( - struct dc_context *ctx, - uint32_t inst) -{ - struct dcn31_afmt *afmt31 = kzalloc(sizeof(struct dcn31_afmt), GFP_KERNEL); - - if (!afmt31) - return NULL; - -#undef REG_STRUCT -#define REG_STRUCT afmt_regs - afmt_regs_init(0), - afmt_regs_init(1), - afmt_regs_init(2), - afmt_regs_init(3), - afmt_regs_init(4), - afmt_regs_init(5); - - afmt31_construct(afmt31, ctx, inst, - &afmt_regs[inst], - &afmt_shift, - &afmt_mask); - - // Light sleep by default, no need to power down here - - return &afmt31->base; -} - -static struct apg *dcn31_apg_create( - struct dc_context *ctx, - uint32_t inst) -{ - struct dcn31_apg *apg31 = kzalloc(sizeof(struct dcn31_apg), GFP_KERNEL); - - if (!apg31) - return NULL; - -#undef REG_STRUCT -#define REG_STRUCT apg_regs - apg_regs_init(0), - apg_regs_init(1), - apg_regs_init(2), - apg_regs_init(3); - - apg31_construct(apg31, ctx, inst, - &apg_regs[inst], - &apg_shift, - &apg_mask); - - return &apg31->base; -} - -static struct stream_encoder *dcn35_stream_encoder_create( - enum engine_id eng_id, - struct dc_context *ctx) -{ - struct dcn10_stream_encoder *enc1; - struct vpg *vpg; - struct afmt *afmt; - int vpg_inst; - int afmt_inst; - - /* Mapping of VPG, AFMT, DME register blocks to DIO block instance */ - if (eng_id <= ENGINE_ID_DIGF) { - vpg_inst = eng_id; - afmt_inst = eng_id; - } else - return NULL; - - enc1 = kzalloc(sizeof(struct dcn10_stream_encoder), GFP_KERNEL); - vpg = dcn31_vpg_create(ctx, vpg_inst); - afmt = dcn31_afmt_create(ctx, afmt_inst); - - if (!enc1 || !vpg || !afmt) { - kfree(enc1); - kfree(vpg); - kfree(afmt); - return NULL; - } - -#undef REG_STRUCT -#define REG_STRUCT stream_enc_regs - stream_enc_regs_init(0), - stream_enc_regs_init(1), - stream_enc_regs_init(2), - stream_enc_regs_init(3), - stream_enc_regs_init(4); - - dcn35_dio_stream_encoder_construct(enc1, ctx, ctx->dc_bios, - eng_id, vpg, afmt, - &stream_enc_regs[eng_id], - &se_shift, &se_mask); - - return &enc1->base; -} - -static struct hpo_dp_stream_encoder *dcn31_hpo_dp_stream_encoder_create( - enum engine_id eng_id, - struct dc_context *ctx) -{ - struct dcn31_hpo_dp_stream_encoder *hpo_dp_enc31; - struct vpg *vpg; - struct apg *apg; - uint32_t hpo_dp_inst; - uint32_t vpg_inst; - uint32_t apg_inst; - - ASSERT((eng_id >= ENGINE_ID_HPO_DP_0) && (eng_id <= ENGINE_ID_HPO_DP_3)); - hpo_dp_inst = eng_id - ENGINE_ID_HPO_DP_0; - - /* Mapping of VPG register blocks to HPO DP block instance: - * VPG[6] -> HPO_DP[0] - * VPG[7] -> HPO_DP[1] - * VPG[8] -> HPO_DP[2] - * VPG[9] -> HPO_DP[3] - */ - vpg_inst = hpo_dp_inst + 6; - - /* Mapping of APG register blocks to HPO DP block instance: - * APG[0] -> HPO_DP[0] - * APG[1] -> HPO_DP[1] - * APG[2] -> HPO_DP[2] - * APG[3] -> HPO_DP[3] - */ - apg_inst = hpo_dp_inst; - - /* allocate HPO stream encoder and create VPG sub-block */ - hpo_dp_enc31 = kzalloc(sizeof(struct dcn31_hpo_dp_stream_encoder), GFP_KERNEL); - vpg = dcn31_vpg_create(ctx, vpg_inst); - apg = dcn31_apg_create(ctx, apg_inst); - - if (!hpo_dp_enc31 || !vpg || !apg) { - kfree(hpo_dp_enc31); - kfree(vpg); - kfree(apg); - return NULL; - } - -#undef REG_STRUCT -#define REG_STRUCT hpo_dp_stream_enc_regs - hpo_dp_stream_encoder_reg_init(0), - hpo_dp_stream_encoder_reg_init(1), - hpo_dp_stream_encoder_reg_init(2), - hpo_dp_stream_encoder_reg_init(3); - - dcn31_hpo_dp_stream_encoder_construct(hpo_dp_enc31, ctx, ctx->dc_bios, - hpo_dp_inst, eng_id, vpg, apg, - &hpo_dp_stream_enc_regs[hpo_dp_inst], - &hpo_dp_se_shift, &hpo_dp_se_mask); - - return &hpo_dp_enc31->base; -} - -static struct hpo_dp_link_encoder *dcn31_hpo_dp_link_encoder_create( - uint8_t inst, - struct dc_context *ctx) -{ - struct dcn31_hpo_dp_link_encoder *hpo_dp_enc31; - - /* allocate HPO link encoder */ - hpo_dp_enc31 = kzalloc(sizeof(struct dcn31_hpo_dp_link_encoder), GFP_KERNEL); - -#undef REG_STRUCT -#define REG_STRUCT hpo_dp_link_enc_regs - hpo_dp_link_encoder_reg_init(0), - hpo_dp_link_encoder_reg_init(1); - - hpo_dp_link_encoder31_construct(hpo_dp_enc31, ctx, inst, - &hpo_dp_link_enc_regs[inst], - &hpo_dp_le_shift, &hpo_dp_le_mask); - - return &hpo_dp_enc31->base; -} - -static struct dce_hwseq *dcn35_hwseq_create( - struct dc_context *ctx) -{ - struct dce_hwseq *hws = kzalloc(sizeof(struct dce_hwseq), GFP_KERNEL); - -#undef REG_STRUCT -#define REG_STRUCT hwseq_reg - hwseq_reg_init(); - - if (hws) { - hws->ctx = ctx; - hws->regs = &hwseq_reg; - hws->shifts = &hwseq_shift; - hws->masks = &hwseq_mask; - } - return hws; -} -static const struct resource_create_funcs res_create_funcs = { - .read_dce_straps = read_dce_straps, - .create_audio = dcn31_create_audio, - .create_stream_encoder = dcn35_stream_encoder_create, - .create_hpo_dp_stream_encoder = dcn31_hpo_dp_stream_encoder_create, - .create_hpo_dp_link_encoder = dcn31_hpo_dp_link_encoder_create, - .create_hwseq = dcn35_hwseq_create, -}; - -static void dcn35_resource_destruct(struct dcn35_resource_pool *pool) -{ - unsigned int i; - - for (i = 0; i < pool->base.stream_enc_count; i++) { - if (pool->base.stream_enc[i] != NULL) { - if (pool->base.stream_enc[i]->vpg != NULL) { - kfree(DCN30_VPG_FROM_VPG(pool->base.stream_enc[i]->vpg)); - pool->base.stream_enc[i]->vpg = NULL; - } - if (pool->base.stream_enc[i]->afmt != NULL) { - kfree(DCN30_AFMT_FROM_AFMT(pool->base.stream_enc[i]->afmt)); - pool->base.stream_enc[i]->afmt = NULL; - } - kfree(DCN10STRENC_FROM_STRENC(pool->base.stream_enc[i])); - pool->base.stream_enc[i] = NULL; - } - } - - for (i = 0; i < pool->base.hpo_dp_stream_enc_count; i++) { - if (pool->base.hpo_dp_stream_enc[i] != NULL) { - if (pool->base.hpo_dp_stream_enc[i]->vpg != NULL) { - kfree(DCN30_VPG_FROM_VPG(pool->base.hpo_dp_stream_enc[i]->vpg)); - pool->base.hpo_dp_stream_enc[i]->vpg = NULL; - } - if (pool->base.hpo_dp_stream_enc[i]->apg != NULL) { - kfree(DCN31_APG_FROM_APG(pool->base.hpo_dp_stream_enc[i]->apg)); - pool->base.hpo_dp_stream_enc[i]->apg = NULL; - } - kfree(DCN3_1_HPO_DP_STREAM_ENC_FROM_HPO_STREAM_ENC(pool->base.hpo_dp_stream_enc[i])); - pool->base.hpo_dp_stream_enc[i] = NULL; - } - } - - for (i = 0; i < pool->base.hpo_dp_link_enc_count; i++) { - if (pool->base.hpo_dp_link_enc[i] != NULL) { - kfree(DCN3_1_HPO_DP_LINK_ENC_FROM_HPO_LINK_ENC(pool->base.hpo_dp_link_enc[i])); - pool->base.hpo_dp_link_enc[i] = NULL; - } - } - - for (i = 0; i < pool->base.res_cap->num_dsc; i++) { - if (pool->base.dscs[i] != NULL) - dcn20_dsc_destroy(&pool->base.dscs[i]); - } - - if (pool->base.mpc != NULL) { - kfree(TO_DCN20_MPC(pool->base.mpc)); - pool->base.mpc = NULL; - } - if (pool->base.hubbub != NULL) { - kfree(pool->base.hubbub); - pool->base.hubbub = NULL; - } - for (i = 0; i < pool->base.pipe_count; i++) { - if (pool->base.dpps[i] != NULL) - dcn35_dpp_destroy(&pool->base.dpps[i]); - - if (pool->base.ipps[i] != NULL) - pool->base.ipps[i]->funcs->ipp_destroy(&pool->base.ipps[i]); - - if (pool->base.hubps[i] != NULL) { - kfree(TO_DCN20_HUBP(pool->base.hubps[i])); - pool->base.hubps[i] = NULL; - } - - if (pool->base.irqs != NULL) { - dal_irq_service_destroy(&pool->base.irqs); - } - } - - for (i = 0; i < pool->base.res_cap->num_ddc; i++) { - if (pool->base.engines[i] != NULL) - dce110_engine_destroy(&pool->base.engines[i]); - if (pool->base.hw_i2cs[i] != NULL) { - kfree(pool->base.hw_i2cs[i]); - pool->base.hw_i2cs[i] = NULL; - } - if (pool->base.sw_i2cs[i] != NULL) { - kfree(pool->base.sw_i2cs[i]); - pool->base.sw_i2cs[i] = NULL; - } - } - - for (i = 0; i < pool->base.res_cap->num_opp; i++) { - if (pool->base.opps[i] != NULL) - pool->base.opps[i]->funcs->opp_destroy(&pool->base.opps[i]); - } - - for (i = 0; i < pool->base.res_cap->num_timing_generator; i++) { - if (pool->base.timing_generators[i] != NULL) { - kfree(DCN10TG_FROM_TG(pool->base.timing_generators[i])); - pool->base.timing_generators[i] = NULL; - } - } - - for (i = 0; i < pool->base.res_cap->num_dwb; i++) { - if (pool->base.dwbc[i] != NULL) { - kfree(TO_DCN30_DWBC(pool->base.dwbc[i])); - pool->base.dwbc[i] = NULL; - } - if (pool->base.mcif_wb[i] != NULL) { - kfree(TO_DCN30_MMHUBBUB(pool->base.mcif_wb[i])); - pool->base.mcif_wb[i] = NULL; - } - } - - for (i = 0; i < pool->base.audio_count; i++) { - if (pool->base.audios[i]) - dce_aud_destroy(&pool->base.audios[i]); - } - - for (i = 0; i < pool->base.clk_src_count; i++) { - if (pool->base.clock_sources[i] != NULL) { - dcn20_clock_source_destroy(&pool->base.clock_sources[i]); - pool->base.clock_sources[i] = NULL; - } - } - - for (i = 0; i < pool->base.res_cap->num_mpc_3dlut; i++) { - if (pool->base.mpc_lut[i] != NULL) { - dc_3dlut_func_release(pool->base.mpc_lut[i]); - pool->base.mpc_lut[i] = NULL; - } - if (pool->base.mpc_shaper[i] != NULL) { - dc_transfer_func_release(pool->base.mpc_shaper[i]); - pool->base.mpc_shaper[i] = NULL; - } - } - - if (pool->base.dp_clock_source != NULL) { - dcn20_clock_source_destroy(&pool->base.dp_clock_source); - pool->base.dp_clock_source = NULL; - } - - for (i = 0; i < pool->base.res_cap->num_timing_generator; i++) { - if (pool->base.multiple_abms[i] != NULL) - dce_abm_destroy(&pool->base.multiple_abms[i]); - } - - if (pool->base.psr != NULL) - dmub_psr_destroy(&pool->base.psr); - - if (pool->base.pg_cntl != NULL) - dcn_pg_cntl_destroy(&pool->base.pg_cntl); - - if (pool->base.dccg != NULL) - dcn_dccg_destroy(&pool->base.dccg); -} - -static struct hubp *dcn35_hubp_create( - struct dc_context *ctx, - uint32_t inst) -{ - struct dcn20_hubp *hubp2 = - kzalloc(sizeof(struct dcn20_hubp), GFP_KERNEL); - - if (!hubp2) - return NULL; - -#undef REG_STRUCT -#define REG_STRUCT hubp_regs - hubp_regs_init(0), - hubp_regs_init(1), - hubp_regs_init(2), - hubp_regs_init(3); - - if (hubp35_construct(hubp2, ctx, inst, - &hubp_regs[inst], &hubp_shift, &hubp_mask)) - return &hubp2->base; - - BREAK_TO_DEBUGGER(); - kfree(hubp2); - return NULL; -} - -static void dcn35_dwbc_init(struct dcn30_dwbc *dwbc30, struct dc_context *ctx) -{ - dcn35_dwbc_set_fgcg( - dwbc30, ctx->dc->debug.enable_fine_grain_clock_gating.bits.dwb); -} - -static bool dcn35_dwbc_create(struct dc_context *ctx, struct resource_pool *pool) -{ - int i; - uint32_t pipe_count = pool->res_cap->num_dwb; - - for (i = 0; i < pipe_count; i++) { - struct dcn30_dwbc *dwbc30 = kzalloc(sizeof(struct dcn30_dwbc), - GFP_KERNEL); - - if (!dwbc30) { - dm_error("DC: failed to create dwbc30!\n"); - return false; - } - -#undef REG_STRUCT -#define REG_STRUCT dwbc35_regs - dwbc_regs_dcn3_init(0); - - dcn35_dwbc_construct(dwbc30, ctx, - &dwbc35_regs[i], - &dwbc35_shift, - &dwbc35_mask, - i); - - pool->dwbc[i] = &dwbc30->base; - - dcn35_dwbc_init(dwbc30, ctx); - } - return true; -} - -static void dcn35_mmhubbub_init(struct dcn30_mmhubbub *mcif_wb30, - struct dc_context *ctx) -{ - dcn35_mmhubbub_set_fgcg( - mcif_wb30, - ctx->dc->debug.enable_fine_grain_clock_gating.bits.mmhubbub); -} - -static bool dcn35_mmhubbub_create(struct dc_context *ctx, struct resource_pool *pool) -{ - int i; - uint32_t pipe_count = pool->res_cap->num_dwb; - - for (i = 0; i < pipe_count; i++) { - struct dcn30_mmhubbub *mcif_wb30 = kzalloc(sizeof(struct dcn30_mmhubbub), - GFP_KERNEL); - - if (!mcif_wb30) { - dm_error("DC: failed to create mcif_wb30!\n"); - return false; - } - -#undef REG_STRUCT -#define REG_STRUCT mcif_wb35_regs - mcif_wb_regs_dcn3_init(0); - - dcn35_mmhubbub_construct(mcif_wb30, ctx, - &mcif_wb35_regs[i], - &mcif_wb35_shift, - &mcif_wb35_mask, - i); - - dcn35_mmhubbub_init(mcif_wb30, ctx); - - pool->mcif_wb[i] = &mcif_wb30->base; - } - return true; -} - -static struct display_stream_compressor *dcn35_dsc_create( - struct dc_context *ctx, uint32_t inst) -{ - struct dcn20_dsc *dsc = - kzalloc(sizeof(struct dcn20_dsc), GFP_KERNEL); - - if (!dsc) { - BREAK_TO_DEBUGGER(); - return NULL; - } - -#undef REG_STRUCT -#define REG_STRUCT dsc_regs - dsc_regsDCN35_init(0), - dsc_regsDCN35_init(1), - dsc_regsDCN35_init(2), - dsc_regsDCN35_init(3); - - dsc35_construct(dsc, ctx, inst, &dsc_regs[inst], &dsc_shift, &dsc_mask); - dsc35_set_fgcg(dsc, - ctx->dc->debug.enable_fine_grain_clock_gating.bits.dsc); - return &dsc->base; -} - -static void dcn35_destroy_resource_pool(struct resource_pool **pool) -{ - struct dcn35_resource_pool *dcn35_pool = TO_DCN35_RES_POOL(*pool); - - dcn35_resource_destruct(dcn35_pool); - kfree(dcn35_pool); - *pool = NULL; -} - -static struct clock_source *dcn35_clock_source_create( - struct dc_context *ctx, - struct dc_bios *bios, - enum clock_source_id id, - const struct dce110_clk_src_regs *regs, - bool dp_clk_src) -{ - struct dce110_clk_src *clk_src = - kzalloc(sizeof(struct dce110_clk_src), GFP_KERNEL); - - if (!clk_src) - return NULL; - - if (dcn31_clk_src_construct(clk_src, ctx, bios, id, - regs, &cs_shift, &cs_mask)) { - clk_src->base.dp_clk_src = dp_clk_src; - return &clk_src->base; - } - - BREAK_TO_DEBUGGER(); - return NULL; -} - -static struct dc_cap_funcs cap_funcs = { - .get_dcc_compression_cap = dcn20_get_dcc_compression_cap -}; - -static void dcn35_get_panel_config_defaults(struct dc_panel_config *panel_config) -{ - *panel_config = panel_config_defaults; -} - - -static bool dcn35_validate_bandwidth(struct dc *dc, - struct dc_state *context, - bool fast_validate) -{ - bool out = false; - - out = dml2_validate(dc, context, fast_validate); - - return out; -} - - -static struct resource_funcs dcn35_res_pool_funcs = { - .destroy = dcn35_destroy_resource_pool, - .link_enc_create = dcn35_link_encoder_create, - .link_enc_create_minimal = dcn31_link_enc_create_minimal, - .link_encs_assign = link_enc_cfg_link_encs_assign, - .link_enc_unassign = link_enc_cfg_link_enc_unassign, - .panel_cntl_create = dcn31_panel_cntl_create, - .validate_bandwidth = dcn35_validate_bandwidth, - .calculate_wm_and_dlg = NULL, - .update_soc_for_wm_a = dcn31_update_soc_for_wm_a, - .populate_dml_pipes = dcn35_populate_dml_pipes_from_context_fpu, - .acquire_free_pipe_as_secondary_dpp_pipe = dcn20_acquire_free_pipe_for_layer, - .release_pipe = dcn20_release_pipe, - .add_stream_to_ctx = dcn30_add_stream_to_ctx, - .add_dsc_to_stream_resource = dcn20_add_dsc_to_stream_resource, - .remove_stream_from_ctx = dcn20_remove_stream_from_ctx, - .populate_dml_writeback_from_context = dcn30_populate_dml_writeback_from_context, - .set_mcif_arb_params = dcn30_set_mcif_arb_params, - .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 = dcn35_update_bw_bounding_box_fpu, - .patch_unknown_plane_state = dcn20_patch_unknown_plane_state, - .get_panel_config_defaults = dcn35_get_panel_config_defaults, - .get_preferred_eng_id_dpia = dcn35_get_preferred_eng_id_dpia, -}; - -static bool dcn35_resource_construct( - uint8_t num_virtual_links, - struct dc *dc, - struct dcn35_resource_pool *pool) -{ - int i; - struct dc_context *ctx = dc->ctx; - struct irq_service_init_data init_data; - -#undef REG_STRUCT -#define REG_STRUCT bios_regs - bios_regs_init(); - -#undef REG_STRUCT -#define REG_STRUCT clk_src_regs - clk_src_regs_init(0, A), - clk_src_regs_init(1, B), - clk_src_regs_init(2, C), - clk_src_regs_init(3, D), - clk_src_regs_init(4, E); - -#undef REG_STRUCT -#define REG_STRUCT abm_regs - abm_regs_init(0), - abm_regs_init(1), - abm_regs_init(2), - abm_regs_init(3); - -#undef REG_STRUCT -#define REG_STRUCT dccg_regs - dccg_regs_init(); - - ctx->dc_bios->regs = &bios_regs; - - pool->base.res_cap = &res_cap_dcn35; - - pool->base.funcs = &dcn35_res_pool_funcs; - - /************************************************* - * Resource + asic cap harcoding * - *************************************************/ - pool->base.underlay_pipe_index = NO_UNDERLAY_PIPE; - pool->base.pipe_count = pool->base.res_cap->num_timing_generator; - pool->base.mpcc_count = pool->base.res_cap->num_timing_generator; - dc->caps.max_downscale_ratio = 600; - dc->caps.i2c_speed_in_khz = 100; - dc->caps.i2c_speed_in_khz_hdcp = 100; - dc->caps.max_cursor_size = 256; - dc->caps.min_horizontal_blanking_period = 80; - dc->caps.dmdata_alloc_size = 2048; - dc->caps.max_slave_planes = 2; - dc->caps.max_slave_yuv_planes = 2; - dc->caps.max_slave_rgb_planes = 2; - dc->caps.post_blend_color_processing = true; - dc->caps.force_dp_tps4_for_cp2520 = true; - if (dc->config.forceHBR2CP2520) - dc->caps.force_dp_tps4_for_cp2520 = false; - dc->caps.dp_hpo = true; - dc->caps.dp_hdmi21_pcon_support = true; - - dc->caps.edp_dsc_support = true; - dc->caps.extended_aux_timeout_support = true; - dc->caps.dmcub_support = true; - dc->caps.is_apu = true; - dc->caps.seamless_odm = true; - - dc->caps.zstate_support = true; - dc->caps.ips_support = true; - dc->caps.max_v_total = (1 << 15) - 1; - - /* Color pipeline capabilities */ - dc->caps.color.dpp.dcn_arch = 1; - dc->caps.color.dpp.input_lut_shared = 0; - dc->caps.color.dpp.icsc = 1; - dc->caps.color.dpp.dgam_ram = 0; // must use gamma_corr - dc->caps.color.dpp.dgam_rom_caps.srgb = 1; - dc->caps.color.dpp.dgam_rom_caps.bt2020 = 1; - dc->caps.color.dpp.dgam_rom_caps.gamma2_2 = 1; - dc->caps.color.dpp.dgam_rom_caps.pq = 1; - dc->caps.color.dpp.dgam_rom_caps.hlg = 1; - dc->caps.color.dpp.post_csc = 1; - dc->caps.color.dpp.gamma_corr = 1; - dc->caps.color.dpp.dgam_rom_for_yuv = 0; - - dc->caps.color.dpp.hw_3d_lut = 1; - dc->caps.color.dpp.ogam_ram = 0; // no OGAM in DPP since DCN1 - // no OGAM ROM on DCN301 - dc->caps.color.dpp.ogam_rom_caps.srgb = 0; - dc->caps.color.dpp.ogam_rom_caps.bt2020 = 0; - dc->caps.color.dpp.ogam_rom_caps.gamma2_2 = 0; - dc->caps.color.dpp.ogam_rom_caps.pq = 0; - dc->caps.color.dpp.ogam_rom_caps.hlg = 0; - dc->caps.color.dpp.ocsc = 0; - - dc->caps.color.mpc.gamut_remap = 1; - dc->caps.color.mpc.num_3dluts = pool->base.res_cap->num_mpc_3dlut; //2 - dc->caps.color.mpc.ogam_ram = 1; - dc->caps.color.mpc.ogam_rom_caps.srgb = 0; - dc->caps.color.mpc.ogam_rom_caps.bt2020 = 0; - dc->caps.color.mpc.ogam_rom_caps.gamma2_2 = 0; - dc->caps.color.mpc.ogam_rom_caps.pq = 0; - dc->caps.color.mpc.ogam_rom_caps.hlg = 0; - dc->caps.color.mpc.ocsc = 1; - - /* max_disp_clock_khz_at_vmin is slightly lower than the STA value in order - * to provide some margin. - * It's expected for furture ASIC to have equal or higher value, in order to - * have determinstic power improvement from generate to genration. - * (i.e., we should not expect new ASIC generation with lower vmin rate) - */ - dc->caps.max_disp_clock_khz_at_vmin = 650000; - - /* Use pipe context based otg sync logic */ - dc->config.use_pipe_ctx_sync_logic = true; - dc->config.use_default_clock_table = false; - /* read VBIOS LTTPR caps */ - { - if (ctx->dc_bios->funcs->get_lttpr_caps) { - enum bp_result bp_query_result; - uint8_t is_vbios_lttpr_enable = 0; - - bp_query_result = ctx->dc_bios->funcs->get_lttpr_caps(ctx->dc_bios, &is_vbios_lttpr_enable); - dc->caps.vbios_lttpr_enable = (bp_query_result == BP_RESULT_OK) && !!is_vbios_lttpr_enable; - } - - /* interop bit is implicit */ - { - dc->caps.vbios_lttpr_aware = true; - } - } - - if (dc->ctx->dce_environment == DCE_ENV_PRODUCTION_DRV) - dc->debug = debug_defaults_drv; - - // Init the vm_helper - if (dc->vm_helper) - vm_helper_init(dc->vm_helper, 16); - - /************************************************* - * Create resources * - *************************************************/ - - /* Clock Sources for Pixel Clock*/ - pool->base.clock_sources[DCN35_CLK_SRC_PLL0] = - dcn35_clock_source_create(ctx, ctx->dc_bios, - CLOCK_SOURCE_COMBO_PHY_PLL0, - &clk_src_regs[0], false); - pool->base.clock_sources[DCN35_CLK_SRC_PLL1] = - dcn35_clock_source_create(ctx, ctx->dc_bios, - CLOCK_SOURCE_COMBO_PHY_PLL1, - &clk_src_regs[1], false); - pool->base.clock_sources[DCN35_CLK_SRC_PLL2] = - dcn35_clock_source_create(ctx, ctx->dc_bios, - CLOCK_SOURCE_COMBO_PHY_PLL2, - &clk_src_regs[2], false); - pool->base.clock_sources[DCN35_CLK_SRC_PLL3] = - dcn35_clock_source_create(ctx, ctx->dc_bios, - CLOCK_SOURCE_COMBO_PHY_PLL3, - &clk_src_regs[3], false); - pool->base.clock_sources[DCN35_CLK_SRC_PLL4] = - dcn35_clock_source_create(ctx, ctx->dc_bios, - CLOCK_SOURCE_COMBO_PHY_PLL4, - &clk_src_regs[4], false); - - pool->base.clk_src_count = DCN35_CLK_SRC_TOTAL; - - /* todo: not reuse phy_pll registers */ - pool->base.dp_clock_source = - dcn35_clock_source_create(ctx, ctx->dc_bios, - CLOCK_SOURCE_ID_DP_DTO, - &clk_src_regs[0], true); - - for (i = 0; i < pool->base.clk_src_count; i++) { - if (pool->base.clock_sources[i] == NULL) { - dm_error("DC: failed to create clock sources!\n"); - BREAK_TO_DEBUGGER(); - goto create_fail; - } - } - /*temp till dml2 fully work without dml1*/ - dml_init_instance(&dc->dml, &dcn3_5_soc, &dcn3_5_ip, DML_PROJECT_DCN31); - - /* TODO: DCCG */ - pool->base.dccg = dccg35_create(ctx, &dccg_regs, &dccg_shift, &dccg_mask); - if (pool->base.dccg == NULL) { - dm_error("DC: failed to create dccg!\n"); - BREAK_TO_DEBUGGER(); - goto create_fail; - } - -#undef REG_STRUCT -#define REG_STRUCT pg_cntl_regs - pg_cntl_dcn35_regs_init(); - - pool->base.pg_cntl = pg_cntl35_create(ctx, &pg_cntl_regs, &pg_cntl_shift, &pg_cntl_mask); - if (pool->base.pg_cntl == NULL) { - dm_error("DC: failed to create power gate control!\n"); - BREAK_TO_DEBUGGER(); - goto create_fail; - } - - /* TODO: IRQ */ - init_data.ctx = dc->ctx; - pool->base.irqs = dal_irq_service_dcn35_create(&init_data); - if (!pool->base.irqs) - goto create_fail; - - /* HUBBUB */ - pool->base.hubbub = dcn35_hubbub_create(ctx); - if (pool->base.hubbub == NULL) { - BREAK_TO_DEBUGGER(); - dm_error("DC: failed to create hubbub!\n"); - goto create_fail; - } - - /* HUBPs, DPPs, OPPs and TGs */ - for (i = 0; i < pool->base.pipe_count; i++) { - pool->base.hubps[i] = dcn35_hubp_create(ctx, i); - if (pool->base.hubps[i] == NULL) { - BREAK_TO_DEBUGGER(); - dm_error( - "DC: failed to create hubps!\n"); - goto create_fail; - } - - pool->base.dpps[i] = dcn35_dpp_create(ctx, i); - if (pool->base.dpps[i] == NULL) { - BREAK_TO_DEBUGGER(); - dm_error( - "DC: failed to create dpps!\n"); - goto create_fail; - } - } - - for (i = 0; i < pool->base.res_cap->num_opp; i++) { - pool->base.opps[i] = dcn35_opp_create(ctx, i); - if (pool->base.opps[i] == NULL) { - BREAK_TO_DEBUGGER(); - dm_error( - "DC: failed to create output pixel processor!\n"); - goto create_fail; - } - } - - for (i = 0; i < pool->base.res_cap->num_timing_generator; i++) { - pool->base.timing_generators[i] = dcn35_timing_generator_create( - ctx, i); - if (pool->base.timing_generators[i] == NULL) { - BREAK_TO_DEBUGGER(); - dm_error("DC: failed to create tg!\n"); - goto create_fail; - } - } - pool->base.timing_generator_count = i; - - /* PSR */ - pool->base.psr = dmub_psr_create(ctx); - if (pool->base.psr == NULL) { - dm_error("DC: failed to create psr obj!\n"); - BREAK_TO_DEBUGGER(); - goto create_fail; - } - - /* ABM */ - for (i = 0; i < pool->base.res_cap->num_timing_generator; i++) { - pool->base.multiple_abms[i] = dmub_abm_create(ctx, - &abm_regs[i], - &abm_shift, - &abm_mask); - if (pool->base.multiple_abms[i] == NULL) { - dm_error("DC: failed to create abm for pipe %d!\n", i); - BREAK_TO_DEBUGGER(); - goto create_fail; - } - } - - /* MPC and DSC */ - pool->base.mpc = dcn35_mpc_create(ctx, pool->base.mpcc_count, pool->base.res_cap->num_mpc_3dlut); - if (pool->base.mpc == NULL) { - BREAK_TO_DEBUGGER(); - dm_error("DC: failed to create mpc!\n"); - goto create_fail; - } - - for (i = 0; i < pool->base.res_cap->num_dsc; i++) { - pool->base.dscs[i] = dcn35_dsc_create(ctx, i); - if (pool->base.dscs[i] == NULL) { - BREAK_TO_DEBUGGER(); - dm_error("DC: failed to create display stream compressor %d!\n", i); - goto create_fail; - } - } - - /* DWB and MMHUBBUB */ - if (!dcn35_dwbc_create(ctx, &pool->base)) { - BREAK_TO_DEBUGGER(); - dm_error("DC: failed to create dwbc!\n"); - goto create_fail; - } - - if (!dcn35_mmhubbub_create(ctx, &pool->base)) { - BREAK_TO_DEBUGGER(); - dm_error("DC: failed to create mcif_wb!\n"); - goto create_fail; - } - - /* AUX and I2C */ - for (i = 0; i < pool->base.res_cap->num_ddc; i++) { - pool->base.engines[i] = dcn31_aux_engine_create(ctx, i); - if (pool->base.engines[i] == NULL) { - BREAK_TO_DEBUGGER(); - dm_error( - "DC:failed to create aux engine!!\n"); - goto create_fail; - } - pool->base.hw_i2cs[i] = dcn31_i2c_hw_create(ctx, i); - if (pool->base.hw_i2cs[i] == NULL) { - BREAK_TO_DEBUGGER(); - dm_error( - "DC:failed to create hw i2c!!\n"); - goto create_fail; - } - pool->base.sw_i2cs[i] = NULL; - } - - /* DCN3.5 has 6 DPIA */ - pool->base.usb4_dpia_count = 4; - if (dc->debug.dpia_debug.bits.disable_dpia) - pool->base.usb4_dpia_count = 0; - - /* Audio, Stream Encoders including HPO and virtual, MPC 3D LUTs */ - if (!resource_construct(num_virtual_links, dc, &pool->base, - &res_create_funcs)) - goto create_fail; - - /* HW Sequencer and Plane caps */ - dcn35_hw_sequencer_construct(dc); - - dc->caps.max_planes = pool->base.pipe_count; - - for (i = 0; i < dc->caps.max_planes; ++i) - dc->caps.planes[i] = plane_cap; - - dc->cap_funcs = cap_funcs; - - dc->dcn_ip->max_num_dpp = pool->base.pipe_count; - - dc->dml2_options.dcn_pipe_count = pool->base.pipe_count; - dc->dml2_options.use_native_pstate_optimization = true; - dc->dml2_options.use_native_soc_bb_construction = true; - if (dc->config.EnableMinDispClkODM) - dc->dml2_options.minimize_dispclk_using_odm = true; - dc->dml2_options.enable_windowed_mpo_odm = dc->config.enable_windowed_mpo_odm; - - dc->dml2_options.callbacks.dc = dc; - dc->dml2_options.callbacks.build_scaling_params = &resource_build_scaling_params; - dc->dml2_options.callbacks.can_support_mclk_switch_using_fw_based_vblank_stretch = &dcn30_can_support_mclk_switch_using_fw_based_vblank_stretch; - dc->dml2_options.callbacks.acquire_secondary_pipe_for_mpc_odm = &dc_resource_acquire_secondary_pipe_for_mpc_odm_legacy; - dc->dml2_options.callbacks.update_pipes_for_stream_with_slice_count = &resource_update_pipes_for_stream_with_slice_count; - dc->dml2_options.callbacks.update_pipes_for_plane_with_slice_count = &resource_update_pipes_for_plane_with_slice_count; - dc->dml2_options.callbacks.get_mpc_slice_index = &resource_get_mpc_slice_index; - dc->dml2_options.callbacks.get_odm_slice_index = &resource_get_odm_slice_index; - dc->dml2_options.callbacks.get_opp_head = &resource_get_opp_head; - dc->dml2_options.max_segments_per_hubp = 24; - - dc->dml2_options.det_segment_size = DCN3_2_DET_SEG_SIZE;/*todo*/ - - if (dc->config.sdpif_request_limit_words_per_umc == 0) - dc->config.sdpif_request_limit_words_per_umc = 16;/*todo*/ - - return true; - -create_fail: - - dcn35_resource_destruct(pool); - - return false; -} - -struct resource_pool *dcn35_create_resource_pool( - const struct dc_init_data *init_data, - struct dc *dc) -{ - struct dcn35_resource_pool *pool = - kzalloc(sizeof(struct dcn35_resource_pool), GFP_KERNEL); - - if (!pool) - return NULL; - - if (dcn35_resource_construct(init_data->num_virtual_links, dc, pool)) - return &pool->base; - - BREAK_TO_DEBUGGER(); - kfree(pool); - return NULL; -} diff --git a/drivers/gpu/drm/amd/display/dc/dcn35/dcn35_resource.h b/drivers/gpu/drm/amd/display/dc/dcn35/dcn35_resource.h deleted file mode 100644 index 99aea102e3f7..000000000000 --- a/drivers/gpu/drm/amd/display/dc/dcn35/dcn35_resource.h +++ /dev/null @@ -1,310 +0,0 @@ -/* SPDX-License-Identifier: MIT */ -/* - * Copyright 2023 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 _DCN35_RESOURCE_H_ -#define _DCN35_RESOURCE_H_ - -#include "core_types.h" - -#define DCN3_5_VMIN_DISPCLK_HZ 717000000 -#define TO_DCN35_RES_POOL(pool)\ - container_of(pool, struct dcn35_resource_pool, base) - -extern struct _vcs_dpi_ip_params_st dcn3_5_ip; -extern struct _vcs_dpi_soc_bounding_box_st dcn3_5_soc; - -struct dcn35_resource_pool { - struct resource_pool base; -}; - -struct resource_pool *dcn35_create_resource_pool( - const struct dc_init_data *init_data, - struct dc *dc); - -/* Defs for runtime init of registers */ - -#define OPP_REG_LIST_DCN20_RI(id) \ - OPP_REG_LIST_DCN10_RI(id), \ - OPP_DPG_REG_LIST_RI(id), \ - SRI_ARR(FMT_422_CONTROL, FMT, id), \ - SRI_ARR(OPPBUF_CONTROL1, OPPBUF, id) - -#define OPP_REG_LIST_DCN35_RI(id) \ - OPP_REG_LIST_DCN20_RI(id), \ - SRI2_ARR(OPP_TOP_CLK_CONTROL, OPP, id) - -#define VPG_DCN31_REG_LIST_RI(id) \ - SRI_ARR(VPG_GENERIC_STATUS, VPG, id), \ - SRI_ARR(VPG_GENERIC_PACKET_ACCESS_CTRL, VPG, id), \ - SRI_ARR(VPG_GENERIC_PACKET_DATA, VPG, id), \ - SRI_ARR(VPG_GSP_FRAME_UPDATE_CTRL, VPG, id), \ - SRI_ARR(VPG_GSP_IMMEDIATE_UPDATE_CTRL, VPG, id), \ - SRI_ARR(VPG_MEM_PWR, VPG, id) - -#define AFMT_DCN31_REG_LIST_RI(id) \ - SRI_ARR(AFMT_INFOFRAME_CONTROL0, AFMT, id), \ - SRI_ARR(AFMT_VBI_PACKET_CONTROL, AFMT, id), \ - SRI_ARR(AFMT_AUDIO_PACKET_CONTROL, AFMT, id), \ - SRI_ARR(AFMT_AUDIO_PACKET_CONTROL2, AFMT, id), \ - SRI_ARR(AFMT_AUDIO_SRC_CONTROL, AFMT, id), \ - SRI_ARR(AFMT_60958_0, AFMT, id), \ - SRI_ARR(AFMT_60958_1, AFMT, id), \ - SRI_ARR(AFMT_60958_2, AFMT, id), \ - SRI_ARR(AFMT_MEM_PWR, AFMT, id) - -/* Stream encoder */ -#define SE_DCN35_REG_LIST_RI(id) \ - SRI_ARR(AFMT_CNTL, DIG, id), \ - SRI_ARR(DIG_FE_CNTL, DIG, id), \ - SRI_ARR(HDMI_CONTROL, DIG, id), \ - SRI_ARR(HDMI_DB_CONTROL, DIG, id), \ - SRI_ARR(HDMI_GC, DIG, id), \ - SRI_ARR(HDMI_GENERIC_PACKET_CONTROL0, DIG, id), \ - SRI_ARR(HDMI_GENERIC_PACKET_CONTROL1, DIG, id), \ - SRI_ARR(HDMI_GENERIC_PACKET_CONTROL2, DIG, id), \ - SRI_ARR(HDMI_GENERIC_PACKET_CONTROL3, DIG, id), \ - SRI_ARR(HDMI_GENERIC_PACKET_CONTROL4, DIG, id), \ - SRI_ARR(HDMI_GENERIC_PACKET_CONTROL5, DIG, id), \ - SRI_ARR(HDMI_GENERIC_PACKET_CONTROL6, DIG, id), \ - SRI_ARR(HDMI_GENERIC_PACKET_CONTROL7, DIG, id), \ - SRI_ARR(HDMI_GENERIC_PACKET_CONTROL8, DIG, id), \ - SRI_ARR(HDMI_GENERIC_PACKET_CONTROL9, DIG, id), \ - SRI_ARR(HDMI_GENERIC_PACKET_CONTROL10, DIG, id), \ - SRI_ARR(HDMI_INFOFRAME_CONTROL0, DIG, id), \ - SRI_ARR(HDMI_INFOFRAME_CONTROL1, DIG, id), \ - SRI_ARR(HDMI_VBI_PACKET_CONTROL, DIG, id), \ - SRI_ARR(HDMI_AUDIO_PACKET_CONTROL, DIG, id),\ - SRI_ARR(HDMI_ACR_PACKET_CONTROL, DIG, id),\ - SRI_ARR(HDMI_ACR_32_0, DIG, id),\ - SRI_ARR(HDMI_ACR_32_1, DIG, id),\ - SRI_ARR(HDMI_ACR_44_0, DIG, id),\ - SRI_ARR(HDMI_ACR_44_1, DIG, id),\ - SRI_ARR(HDMI_ACR_48_0, DIG, id),\ - SRI_ARR(HDMI_ACR_48_1, DIG, id),\ - SRI_ARR(DP_DB_CNTL, DP, id), \ - SRI_ARR(DP_MSA_MISC, DP, id), \ - SRI_ARR(DP_MSA_VBID_MISC, DP, id), \ - SRI_ARR(DP_MSA_COLORIMETRY, DP, id), \ - SRI_ARR(DP_MSA_TIMING_PARAM1, DP, id), \ - SRI_ARR(DP_MSA_TIMING_PARAM2, DP, id), \ - SRI_ARR(DP_MSA_TIMING_PARAM3, DP, id), \ - SRI_ARR(DP_MSA_TIMING_PARAM4, DP, id), \ - SRI_ARR(DP_MSE_RATE_CNTL, DP, id), \ - SRI_ARR(DP_MSE_RATE_UPDATE, DP, id), \ - SRI_ARR(DP_PIXEL_FORMAT, DP, id), \ - SRI_ARR(DP_SEC_CNTL, DP, id), \ - SRI_ARR(DP_SEC_CNTL1, DP, id), \ - SRI_ARR(DP_SEC_CNTL2, DP, id), \ - SRI_ARR(DP_SEC_CNTL5, DP, id), \ - SRI_ARR(DP_SEC_CNTL6, DP, id), \ - SRI_ARR(DP_STEER_FIFO, DP, id), \ - SRI_ARR(DP_VID_M, DP, id), \ - SRI_ARR(DP_VID_N, DP, id), \ - SRI_ARR(DP_VID_STREAM_CNTL, DP, id), \ - SRI_ARR(DP_VID_TIMING, DP, id), \ - SRI_ARR(DP_SEC_AUD_N, DP, id), \ - SRI_ARR(DP_SEC_TIMESTAMP, DP, id), \ - SRI_ARR(DP_DSC_CNTL, DP, id), \ - SRI_ARR(DP_SEC_METADATA_TRANSMISSION, DP, id), \ - SRI_ARR(HDMI_METADATA_PACKET_CONTROL, DIG, id), \ - SRI_ARR(DP_SEC_FRAMING4, DP, id), \ - SRI_ARR(DP_GSP11_CNTL, DP, id), \ - SRI_ARR(DME_CONTROL, DME, id),\ - SRI_ARR(DP_SEC_METADATA_TRANSMISSION, DP, id), \ - SRI_ARR(HDMI_METADATA_PACKET_CONTROL, DIG, id), \ - SRI_ARR(DIG_FE_CNTL, DIG, id), \ - SRI_ARR(DIG_FE_EN_CNTL, DIG, id), \ - SRI_ARR(DIG_FE_CLK_CNTL, DIG, id), \ - SRI_ARR(DIG_CLOCK_PATTERN, DIG, id), \ - SRI_ARR(DIG_FIFO_CTRL0, DIG, id), \ - SRI_ARR(STREAM_MAPPER_CONTROL, DIG, id) - -#define LE_DCN35_REG_LIST_RI(id)\ - LE_DCN3_REG_LIST_RI(id),\ - SRI_ARR(DP_DPHY_INTERNAL_CTRL, DP, id), \ - SR_ARR(DIO_LINKA_CNTL, id), \ - SR_ARR(DIO_LINKB_CNTL, id), \ - SR_ARR(DIO_LINKC_CNTL, id), \ - SR_ARR(DIO_LINKD_CNTL, id), \ - SR_ARR(DIO_LINKE_CNTL, id), \ - SR_ARR(DIO_LINKF_CNTL, id),\ - SRI_ARR(DIG_BE_CLK_CNTL, DIG, id),\ - SR_ARR(DIO_CLK_CNTL, id) - -#define MCIF_WB_COMMON_REG_LIST_DCN3_5_RI(inst) \ - MCIF_WB_COMMON_REG_LIST_DCN32_RI(inst), \ - SRI2_ARR(MMHUBBUB_CLOCK_CNTL, MMHUBBUB, inst) - -#define HWSEQ_DCN35_REG_LIST()\ - SR(DCHUBBUB_GLOBAL_TIMER_CNTL), \ - SR(DCHUBBUB_ARB_HOSTVM_CNTL), \ - SR(DIO_MEM_PWR_CTRL), \ - SR(ODM_MEM_PWR_CTRL3), \ - SR(MMHUBBUB_MEM_PWR_CNTL), \ - SR(DCCG_GATE_DISABLE_CNTL), \ - SR(DCCG_GATE_DISABLE_CNTL2), \ - SR(DCCG_GATE_DISABLE_CNTL5), \ - SR(DCFCLK_CNTL),\ - SR(DC_MEM_GLOBAL_PWR_REQ_CNTL), \ - SRII(PIXEL_RATE_CNTL, OTG, 0), \ - SRII(PIXEL_RATE_CNTL, OTG, 1),\ - SRII(PIXEL_RATE_CNTL, OTG, 2),\ - SRII(PIXEL_RATE_CNTL, OTG, 3),\ - SRII(PHYPLL_PIXEL_RATE_CNTL, OTG, 0),\ - SRII(PHYPLL_PIXEL_RATE_CNTL, OTG, 1),\ - SRII(PHYPLL_PIXEL_RATE_CNTL, OTG, 2),\ - SRII(PHYPLL_PIXEL_RATE_CNTL, OTG, 3),\ - SR(MICROSECOND_TIME_BASE_DIV), \ - SR(MILLISECOND_TIME_BASE_DIV), \ - SR(DISPCLK_FREQ_CHANGE_CNTL), \ - SR(RBBMIF_TIMEOUT_DIS), \ - SR(RBBMIF_TIMEOUT_DIS_2), \ - SR(DCHUBBUB_CRC_CTRL), \ - SR(DPP_TOP0_DPP_CRC_CTRL), \ - SR(DPP_TOP0_DPP_CRC_VAL_B_A), \ - SR(DPP_TOP0_DPP_CRC_VAL_R_G), \ - SR(MPC_CRC_CTRL), \ - SR(MPC_CRC_RESULT_GB), \ - SR(MPC_CRC_RESULT_C), \ - SR(MPC_CRC_RESULT_AR), \ - SR(DOMAIN0_PG_CONFIG), \ - SR(DOMAIN1_PG_CONFIG), \ - SR(DOMAIN2_PG_CONFIG), \ - SR(DOMAIN3_PG_CONFIG), \ - SR(DOMAIN16_PG_CONFIG), \ - SR(DOMAIN17_PG_CONFIG), \ - SR(DOMAIN18_PG_CONFIG), \ - SR(DOMAIN19_PG_CONFIG), \ - SR(DOMAIN0_PG_STATUS), \ - SR(DOMAIN1_PG_STATUS), \ - SR(DOMAIN2_PG_STATUS), \ - SR(DOMAIN3_PG_STATUS), \ - SR(DOMAIN16_PG_STATUS), \ - SR(DOMAIN17_PG_STATUS), \ - SR(DOMAIN18_PG_STATUS), \ - SR(DOMAIN19_PG_STATUS), \ - SR(DC_IP_REQUEST_CNTL), \ - SR(AZALIA_AUDIO_DTO), \ - SR(AZALIA_CONTROLLER_CLOCK_GATING), \ - SR(HPO_TOP_HW_CONTROL),\ - SR(DMU_CLK_CNTL) - -/* OPTC */ -#define OPTC_COMMON_REG_LIST_DCN3_5_RI(inst) \ - SRI_ARR(OTG_VSTARTUP_PARAM, OTG, inst),\ - SRI_ARR(OTG_VUPDATE_PARAM, OTG, inst),\ - SRI_ARR(OTG_VREADY_PARAM, OTG, inst),\ - SRI_ARR(OTG_MASTER_UPDATE_LOCK, OTG, inst),\ - SRI_ARR(OTG_GLOBAL_CONTROL0, OTG, inst),\ - SRI_ARR(OTG_GLOBAL_CONTROL1, OTG, inst),\ - SRI_ARR(OTG_GLOBAL_CONTROL2, OTG, inst),\ - SRI_ARR(OTG_GLOBAL_CONTROL4, OTG, inst),\ - SRI_ARR(OTG_DOUBLE_BUFFER_CONTROL, OTG, inst),\ - SRI_ARR(OTG_H_TOTAL, OTG, inst),\ - SRI_ARR(OTG_H_BLANK_START_END, OTG, inst),\ - SRI_ARR(OTG_H_SYNC_A, OTG, inst),\ - SRI_ARR(OTG_H_SYNC_A_CNTL, OTG, inst),\ - SRI_ARR(OTG_H_TIMING_CNTL, OTG, inst),\ - SRI_ARR(OTG_V_TOTAL, OTG, inst),\ - SRI_ARR(OTG_V_BLANK_START_END, OTG, inst),\ - SRI_ARR(OTG_V_SYNC_A, OTG, inst),\ - SRI_ARR(OTG_V_SYNC_A_CNTL, OTG, inst),\ - SRI_ARR(OTG_CONTROL, OTG, inst),\ - SRI_ARR(OTG_STEREO_CONTROL, OTG, inst),\ - SRI_ARR(OTG_3D_STRUCTURE_CONTROL, OTG, inst),\ - SRI_ARR(OTG_STEREO_STATUS, OTG, inst),\ - SRI_ARR(OTG_V_TOTAL_MAX, OTG, inst),\ - SRI_ARR(OTG_V_TOTAL_MIN, OTG, inst),\ - SRI_ARR(OTG_V_TOTAL_CONTROL, OTG, inst),\ - SRI_ARR(OTG_TRIGA_CNTL, OTG, inst),\ - SRI_ARR(OTG_FORCE_COUNT_NOW_CNTL, OTG, inst),\ - SRI_ARR(OTG_STATIC_SCREEN_CONTROL, OTG, inst),\ - SRI_ARR(OTG_STATUS_FRAME_COUNT, OTG, inst),\ - SRI_ARR(OTG_STATUS, OTG, inst),\ - SRI_ARR(OTG_STATUS_POSITION, OTG, inst),\ - SRI_ARR(OTG_NOM_VERT_POSITION, OTG, inst),\ - SRI_ARR(OTG_M_CONST_DTO0, OTG, inst),\ - SRI_ARR(OTG_M_CONST_DTO1, OTG, inst),\ - SRI_ARR(OTG_CLOCK_CONTROL, OTG, inst),\ - SRI_ARR(OTG_VERTICAL_INTERRUPT0_CONTROL, OTG, inst),\ - SRI_ARR(OTG_VERTICAL_INTERRUPT0_POSITION, OTG, inst),\ - SRI_ARR(OTG_VERTICAL_INTERRUPT1_CONTROL, OTG, inst),\ - SRI_ARR(OTG_VERTICAL_INTERRUPT1_POSITION, OTG, inst),\ - SRI_ARR(OTG_VERTICAL_INTERRUPT2_CONTROL, OTG, inst),\ - SRI_ARR(OTG_VERTICAL_INTERRUPT2_POSITION, OTG, inst),\ - SRI_ARR(OPTC_INPUT_CLOCK_CONTROL, ODM, inst),\ - SRI_ARR(OPTC_DATA_SOURCE_SELECT, ODM, inst),\ - SRI_ARR(OPTC_INPUT_GLOBAL_CONTROL, ODM, inst),\ - SRI_ARR(CONTROL, VTG, inst),\ - SRI_ARR(OTG_VERT_SYNC_CONTROL, OTG, inst),\ - SRI_ARR(OTG_GSL_CONTROL, OTG, inst),\ - SRI_ARR(OTG_CRC_CNTL, OTG, inst),\ - SRI_ARR(OTG_CRC0_DATA_RG, OTG, inst),\ - SRI_ARR(OTG_CRC0_DATA_B, OTG, inst),\ - SRI_ARR(OTG_CRC1_DATA_RG, OTG, inst),\ - SRI_ARR(OTG_CRC1_DATA_B, OTG, inst),\ - SRI_ARR(OTG_CRC2_DATA_RG, OTG, inst),\ - SRI_ARR(OTG_CRC2_DATA_B, OTG, inst),\ - SRI_ARR(OTG_CRC3_DATA_RG, OTG, inst),\ - SRI_ARR(OTG_CRC3_DATA_B, OTG, inst),\ - SRI_ARR(OTG_CRC0_WINDOWA_X_CONTROL, OTG, inst),\ - SRI_ARR(OTG_CRC0_WINDOWA_Y_CONTROL, OTG, inst),\ - SRI_ARR(OTG_CRC0_WINDOWB_X_CONTROL, OTG, inst),\ - SRI_ARR(OTG_CRC0_WINDOWB_Y_CONTROL, OTG, inst),\ - SRI_ARR(OTG_CRC1_WINDOWA_X_CONTROL, OTG, inst),\ - SRI_ARR(OTG_CRC1_WINDOWA_Y_CONTROL, OTG, inst),\ - SRI_ARR(OTG_CRC1_WINDOWB_X_CONTROL, OTG, inst),\ - SRI_ARR(OTG_CRC1_WINDOWB_Y_CONTROL, OTG, inst),\ - SRI_ARR(OTG_CRC0_WINDOWA_X_CONTROL_READBACK, OTG, inst),\ - SRI_ARR(OTG_CRC0_WINDOWA_Y_CONTROL_READBACK, OTG, inst),\ - SRI_ARR(OTG_CRC0_WINDOWB_X_CONTROL_READBACK, OTG, inst),\ - SRI_ARR(OTG_CRC0_WINDOWB_Y_CONTROL_READBACK, OTG, inst),\ - SRI_ARR(OTG_CRC1_WINDOWA_X_CONTROL_READBACK, OTG, inst),\ - SRI_ARR(OTG_CRC1_WINDOWA_Y_CONTROL_READBACK, OTG, inst),\ - SRI_ARR(OTG_CRC1_WINDOWB_X_CONTROL_READBACK, OTG, inst),\ - SRI_ARR(OTG_CRC1_WINDOWB_Y_CONTROL_READBACK, OTG, inst),\ - SR_ARR(GSL_SOURCE_SELECT, inst),\ - SRI_ARR(OTG_TRIGA_MANUAL_TRIG, OTG, inst),\ - SRI_ARR(OTG_GLOBAL_CONTROL1, OTG, inst),\ - SRI_ARR(OTG_GLOBAL_CONTROL2, OTG, inst),\ - SRI_ARR(OTG_GSL_WINDOW_X, OTG, inst),\ - SRI_ARR(OTG_GSL_WINDOW_Y, OTG, inst),\ - SRI_ARR(OTG_VUPDATE_KEEPOUT, OTG, inst),\ - SRI_ARR(OTG_DSC_START_POSITION, OTG, inst),\ - SRI_ARR(OTG_DRR_TRIGGER_WINDOW, OTG, inst),\ - SRI_ARR(OTG_DRR_V_TOTAL_CHANGE, OTG, inst),\ - SRI_ARR(OPTC_DATA_FORMAT_CONTROL, ODM, inst),\ - SRI_ARR(OPTC_BYTES_PER_PIXEL, ODM, inst),\ - SRI_ARR(OPTC_WIDTH_CONTROL, ODM, inst),\ - SRI_ARR(OPTC_MEMORY_CONFIG, ODM, inst),\ - SRI_ARR(OTG_DRR_CONTROL, OTG, inst),\ - SRI2_ARR(OPTC_CLOCK_CONTROL, OPTC, inst) - -/* DPP */ -#define DPP_REG_LIST_DCN35_RI(id)\ - DPP_REG_LIST_DCN30_COMMON_RI(id) - -#endif /* _DCN35_RESOURCE_H_ */ diff --git a/drivers/gpu/drm/amd/display/dc/dml/calcs/dcn_calcs.c b/drivers/gpu/drm/amd/display/dc/dml/calcs/dcn_calcs.c index 50b0434354f8..0c4a8fe8e5ca 100644 --- a/drivers/gpu/drm/amd/display/dc/dml/calcs/dcn_calcs.c +++ b/drivers/gpu/drm/amd/display/dc/dml/calcs/dcn_calcs.c @@ -30,7 +30,7 @@ #include "dcn_calc_auto.h" #include "dal_asic_id.h" #include "resource.h" -#include "dcn10/dcn10_resource.h" +#include "resource/dcn10/dcn10_resource.h" #include "dcn10/dcn10_hubbub.h" #include "dml/dml1_display_rq_dlg_calc.h" diff --git a/drivers/gpu/drm/amd/display/dc/resource/Makefile b/drivers/gpu/drm/amd/display/dc/resource/Makefile new file mode 100644 index 000000000000..0a75ed8962a5 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/resource/Makefile @@ -0,0 +1,199 @@ + +# Copyright 2022 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. +# +# Makefile for the 'resource' sub-component of DAL. +# + + +############################################################################### +# DCE +############################################################################### + +RESOURCE_DCE100 = dce100_resource.o + +AMD_DAL_RESOURCE_DCE100 = $(addprefix $(AMDDALPATH)/dc/resource/dce100/,$(RESOURCE_DCE100)) + +AMD_DISPLAY_FILES += $(AMD_DAL_RESOURCE_DCE100) + +############################################################################### + +RESOURCE_DCE110 = dce110_resource.o + +AMD_DAL_RESOURCE_DCE110 = $(addprefix $(AMDDALPATH)/dc/resource/dce110/,$(RESOURCE_DCE110)) + +AMD_DISPLAY_FILES += $(AMD_DAL_RESOURCE_DCE110) + +############################################################################### + +RESOURCE_DCE112 = dce112_resource.o + +AMD_DAL_RESOURCE_DCE112 = $(addprefix $(AMDDALPATH)/dc/resource/dce112/,$(RESOURCE_DCE112)) + +AMD_DISPLAY_FILES += $(AMD_DAL_RESOURCE_DCE112) + +############################################################################### + +RESOURCE_DCE120 = dce120_resource.o + +AMD_DAL_RESOURCE_DCE120 = $(addprefix $(AMDDALPATH)/dc/resource/dce120/,$(RESOURCE_DCE120)) + +AMD_DISPLAY_FILES += $(AMD_DAL_RESOURCE_DCE120) + +############################################################################### + +RESOURCE_DCE80 = dce80_resource.o + +AMD_DAL_RESOURCE_DCE80 = $(addprefix $(AMDDALPATH)/dc/resource/dce80/,$(RESOURCE_DCE80)) + +AMD_DISPLAY_FILES += $(AMD_DAL_RESOURCE_DCE80) + +ifdef CONFIG_DRM_AMD_DC_FP +############################################################################### +# DCN +############################################################################### + +RESOURCE_DCN10 = dcn10_resource.o + +AMD_DAL_RESOURCE_DCN10 = $(addprefix $(AMDDALPATH)/dc/resource/dcn10/,$(RESOURCE_DCN10)) + +AMD_DISPLAY_FILES += $(AMD_DAL_RESOURCE_DCN10) + +############################################################################### + +RESOURCE_DCN20 = dcn20_resource.o + +AMD_DAL_RESOURCE_DCN20 = $(addprefix $(AMDDALPATH)/dc/resource/dcn20/,$(RESOURCE_DCN20)) + +AMD_DISPLAY_FILES += $(AMD_DAL_RESOURCE_DCN20) + +############################################################################### + +RESOURCE_DCN201 = dcn201_resource.o + +AMD_DAL_RESOURCE_DCN201 = $(addprefix $(AMDDALPATH)/dc/resource/dcn201/,$(RESOURCE_DCN201)) + +AMD_DISPLAY_FILES += $(AMD_DAL_RESOURCE_DCN201) + +############################################################################### + +RESOURCE_DCN21 = dcn21_resource.o + +AMD_DAL_RESOURCE_DCN21 = $(addprefix $(AMDDALPATH)/dc/resource/dcn21/,$(RESOURCE_DCN21)) + +AMD_DISPLAY_FILES += $(AMD_DAL_RESOURCE_DCN21) + +############################################################################### + +############################################################################### + +############################################################################### + +RESOURCE_DCN30 = dcn30_resource.o + +AMD_DAL_RESOURCE_DCN30 = $(addprefix $(AMDDALPATH)/dc/resource/dcn30/,$(RESOURCE_DCN30)) + +AMD_DISPLAY_FILES += $(AMD_DAL_RESOURCE_DCN30) + +############################################################################### + +RESOURCE_DCN301 = dcn301_resource.o + +AMD_DAL_RESOURCE_DCN301 = $(addprefix $(AMDDALPATH)/dc/resource/dcn301/,$(RESOURCE_DCN301)) + +AMD_DISPLAY_FILES += $(AMD_DAL_RESOURCE_DCN301) + +############################################################################### + +RESOURCE_DCN302 = dcn302_resource.o + +AMD_DAL_RESOURCE_DCN302 = $(addprefix $(AMDDALPATH)/dc/resource/dcn302/,$(RESOURCE_DCN302)) + +AMD_DISPLAY_FILES += $(AMD_DAL_RESOURCE_DCN302) + +############################################################################### + +RESOURCE_DCN303 = dcn303_resource.o + +AMD_DAL_RESOURCE_DCN303 = $(addprefix $(AMDDALPATH)/dc/resource/dcn303/,$(RESOURCE_DCN303)) + +AMD_DISPLAY_FILES += $(AMD_DAL_RESOURCE_DCN303) + +############################################################################### + +RESOURCE_DCN31 = dcn31_resource.o + +AMD_DAL_RESOURCE_DCN31 = $(addprefix $(AMDDALPATH)/dc/resource/dcn31/,$(RESOURCE_DCN31)) + +AMD_DISPLAY_FILES += $(AMD_DAL_RESOURCE_DCN31) + +############################################################################### + +RESOURCE_DCN314 = dcn314_resource.o + +AMD_DAL_RESOURCE_DCN314 = $(addprefix $(AMDDALPATH)/dc/resource/dcn314/,$(RESOURCE_DCN314)) + +AMD_DISPLAY_FILES += $(AMD_DAL_RESOURCE_DCN314) + +############################################################################### + +RESOURCE_DCN315 = dcn315_resource.o + +AMD_DAL_RESOURCE_DCN315 = $(addprefix $(AMDDALPATH)/dc/resource/dcn315/,$(RESOURCE_DCN315)) + +AMD_DISPLAY_FILES += $(AMD_DAL_RESOURCE_DCN315) + +############################################################################### + +RESOURCE_DCN316 = dcn316_resource.o + +AMD_DAL_RESOURCE_DCN316 = $(addprefix $(AMDDALPATH)/dc/resource/dcn316/,$(RESOURCE_DCN316)) + +AMD_DISPLAY_FILES += $(AMD_DAL_RESOURCE_DCN316) + +############################################################################### + +RESOURCE_DCN32 = dcn32_resource.o + +AMD_DAL_RESOURCE_DCN32 = $(addprefix $(AMDDALPATH)/dc/resource/dcn32/,$(RESOURCE_DCN32)) + +AMD_DISPLAY_FILES += $(AMD_DAL_RESOURCE_DCN32) + +############################################################################### + +RESOURCE_DCN321 = dcn321_resource.o + +AMD_DAL_RESOURCE_DCN321 = $(addprefix $(AMDDALPATH)/dc/resource/dcn321/,$(RESOURCE_DCN321)) + +AMD_DISPLAY_FILES += $(AMD_DAL_RESOURCE_DCN321) + +############################################################################### + +RESOURCE_DCN35 = dcn35_resource.o + +AMD_DAL_RESOURCE_DCN35 = $(addprefix $(AMDDALPATH)/dc/resource/dcn35/,$(RESOURCE_DCN35)) + +AMD_DISPLAY_FILES += $(AMD_DAL_RESOURCE_DCN35) + +############################################################################### + +############################################################################### + +endif diff --git a/drivers/gpu/drm/amd/display/dc/resource/dce100/dce100_resource.c b/drivers/gpu/drm/amd/display/dc/resource/dce100/dce100_resource.c new file mode 100644 index 000000000000..53a5f4cb648c --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/resource/dce100/dce100_resource.c @@ -0,0 +1,1179 @@ +/* + * Copyright 2012-15 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 "dm_services.h" + +#include "link_encoder.h" +#include "stream_encoder.h" + +#include "resource.h" +#include "include/irq_service_interface.h" +#include "virtual/virtual_stream_encoder.h" +#include "dce110/dce110_resource.h" +#include "dce110/dce110_timing_generator.h" +#include "irq/dce110/irq_service_dce110.h" +#include "dce/dce_link_encoder.h" +#include "dce/dce_stream_encoder.h" +#include "dce/dce_mem_input.h" +#include "dce/dce_ipp.h" +#include "dce/dce_transform.h" +#include "dce/dce_opp.h" +#include "dce/dce_clock_source.h" +#include "dce/dce_audio.h" +#include "dce/dce_hwseq.h" +#include "dce100/dce100_hwseq.h" +#include "dce/dce_panel_cntl.h" + +#include "reg_helper.h" + +#include "dce/dce_10_0_d.h" +#include "dce/dce_10_0_sh_mask.h" + +#include "dce/dce_dmcu.h" +#include "dce/dce_aux.h" +#include "dce/dce_abm.h" +#include "dce/dce_i2c.h" + +#include "dce100_resource.h" + +#ifndef mmMC_HUB_RDREQ_DMIF_LIMIT +#include "gmc/gmc_8_2_d.h" +#include "gmc/gmc_8_2_sh_mask.h" +#endif + +#ifndef mmDP_DPHY_INTERNAL_CTRL + #define mmDP_DPHY_INTERNAL_CTRL 0x4aa7 + #define mmDP0_DP_DPHY_INTERNAL_CTRL 0x4aa7 + #define mmDP1_DP_DPHY_INTERNAL_CTRL 0x4ba7 + #define mmDP2_DP_DPHY_INTERNAL_CTRL 0x4ca7 + #define mmDP3_DP_DPHY_INTERNAL_CTRL 0x4da7 + #define mmDP4_DP_DPHY_INTERNAL_CTRL 0x4ea7 + #define mmDP5_DP_DPHY_INTERNAL_CTRL 0x4fa7 + #define mmDP6_DP_DPHY_INTERNAL_CTRL 0x54a7 + #define mmDP7_DP_DPHY_INTERNAL_CTRL 0x56a7 + #define mmDP8_DP_DPHY_INTERNAL_CTRL 0x57a7 +#endif + +#ifndef mmBIOS_SCRATCH_2 + #define mmBIOS_SCRATCH_2 0x05CB + #define mmBIOS_SCRATCH_3 0x05CC + #define mmBIOS_SCRATCH_6 0x05CF +#endif + +#ifndef mmDP_DPHY_BS_SR_SWAP_CNTL + #define mmDP_DPHY_BS_SR_SWAP_CNTL 0x4ADC + #define mmDP0_DP_DPHY_BS_SR_SWAP_CNTL 0x4ADC + #define mmDP1_DP_DPHY_BS_SR_SWAP_CNTL 0x4BDC + #define mmDP2_DP_DPHY_BS_SR_SWAP_CNTL 0x4CDC + #define mmDP3_DP_DPHY_BS_SR_SWAP_CNTL 0x4DDC + #define mmDP4_DP_DPHY_BS_SR_SWAP_CNTL 0x4EDC + #define mmDP5_DP_DPHY_BS_SR_SWAP_CNTL 0x4FDC + #define mmDP6_DP_DPHY_BS_SR_SWAP_CNTL 0x54DC +#endif + +#ifndef mmDP_DPHY_FAST_TRAINING + #define mmDP_DPHY_FAST_TRAINING 0x4ABC + #define mmDP0_DP_DPHY_FAST_TRAINING 0x4ABC + #define mmDP1_DP_DPHY_FAST_TRAINING 0x4BBC + #define mmDP2_DP_DPHY_FAST_TRAINING 0x4CBC + #define mmDP3_DP_DPHY_FAST_TRAINING 0x4DBC + #define mmDP4_DP_DPHY_FAST_TRAINING 0x4EBC + #define mmDP5_DP_DPHY_FAST_TRAINING 0x4FBC + #define mmDP6_DP_DPHY_FAST_TRAINING 0x54BC +#endif + +static const struct dce110_timing_generator_offsets dce100_tg_offsets[] = { + { + .crtc = (mmCRTC0_CRTC_CONTROL - mmCRTC_CONTROL), + .dcp = (mmDCP0_GRPH_CONTROL - mmGRPH_CONTROL), + }, + { + .crtc = (mmCRTC1_CRTC_CONTROL - mmCRTC_CONTROL), + .dcp = (mmDCP1_GRPH_CONTROL - mmGRPH_CONTROL), + }, + { + .crtc = (mmCRTC2_CRTC_CONTROL - mmCRTC_CONTROL), + .dcp = (mmDCP2_GRPH_CONTROL - mmGRPH_CONTROL), + }, + { + .crtc = (mmCRTC3_CRTC_CONTROL - mmCRTC_CONTROL), + .dcp = (mmDCP3_GRPH_CONTROL - mmGRPH_CONTROL), + }, + { + .crtc = (mmCRTC4_CRTC_CONTROL - mmCRTC_CONTROL), + .dcp = (mmDCP4_GRPH_CONTROL - mmGRPH_CONTROL), + }, + { + .crtc = (mmCRTC5_CRTC_CONTROL - mmCRTC_CONTROL), + .dcp = (mmDCP5_GRPH_CONTROL - mmGRPH_CONTROL), + } +}; + +/* set register offset */ +#define SR(reg_name)\ + .reg_name = mm ## reg_name + +/* set register offset with instance */ +#define SRI(reg_name, block, id)\ + .reg_name = mm ## block ## id ## _ ## reg_name + +#define ipp_regs(id)\ +[id] = {\ + IPP_DCE100_REG_LIST_DCE_BASE(id)\ +} + +static const struct dce_ipp_registers ipp_regs[] = { + ipp_regs(0), + ipp_regs(1), + ipp_regs(2), + ipp_regs(3), + ipp_regs(4), + ipp_regs(5) +}; + +static const struct dce_ipp_shift ipp_shift = { + IPP_DCE100_MASK_SH_LIST_DCE_COMMON_BASE(__SHIFT) +}; + +static const struct dce_ipp_mask ipp_mask = { + IPP_DCE100_MASK_SH_LIST_DCE_COMMON_BASE(_MASK) +}; + +#define transform_regs(id)\ +[id] = {\ + XFM_COMMON_REG_LIST_DCE100(id)\ +} + +static const struct dce_transform_registers xfm_regs[] = { + transform_regs(0), + transform_regs(1), + transform_regs(2), + transform_regs(3), + transform_regs(4), + transform_regs(5) +}; + +static const struct dce_transform_shift xfm_shift = { + XFM_COMMON_MASK_SH_LIST_DCE110(__SHIFT) +}; + +static const struct dce_transform_mask xfm_mask = { + XFM_COMMON_MASK_SH_LIST_DCE110(_MASK) +}; + +#define aux_regs(id)\ +[id] = {\ + AUX_REG_LIST(id)\ +} + +static const struct dce110_link_enc_aux_registers link_enc_aux_regs[] = { + aux_regs(0), + aux_regs(1), + aux_regs(2), + aux_regs(3), + aux_regs(4), + aux_regs(5) +}; + +#define hpd_regs(id)\ +[id] = {\ + HPD_REG_LIST(id)\ +} + +static const struct dce110_link_enc_hpd_registers link_enc_hpd_regs[] = { + hpd_regs(0), + hpd_regs(1), + hpd_regs(2), + hpd_regs(3), + hpd_regs(4), + hpd_regs(5) +}; + +#define link_regs(id)\ +[id] = {\ + LE_DCE100_REG_LIST(id)\ +} + +static const struct dce110_link_enc_registers link_enc_regs[] = { + link_regs(0), + link_regs(1), + link_regs(2), + link_regs(3), + link_regs(4), + link_regs(5), + link_regs(6), +}; + +#define stream_enc_regs(id)\ +[id] = {\ + SE_COMMON_REG_LIST_DCE_BASE(id),\ + .AFMT_CNTL = 0,\ +} + +static const struct dce110_stream_enc_registers stream_enc_regs[] = { + stream_enc_regs(0), + stream_enc_regs(1), + stream_enc_regs(2), + stream_enc_regs(3), + stream_enc_regs(4), + stream_enc_regs(5), + stream_enc_regs(6) +}; + +static const struct dce_stream_encoder_shift se_shift = { + SE_COMMON_MASK_SH_LIST_DCE80_100(__SHIFT) +}; + +static const struct dce_stream_encoder_mask se_mask = { + SE_COMMON_MASK_SH_LIST_DCE80_100(_MASK) +}; + +static const struct dce_panel_cntl_registers panel_cntl_regs[] = { + { DCE_PANEL_CNTL_REG_LIST() } +}; + +static const struct dce_panel_cntl_shift panel_cntl_shift = { + DCE_PANEL_CNTL_MASK_SH_LIST(__SHIFT) +}; + +static const struct dce_panel_cntl_mask panel_cntl_mask = { + DCE_PANEL_CNTL_MASK_SH_LIST(_MASK) +}; + +#define opp_regs(id)\ +[id] = {\ + OPP_DCE_100_REG_LIST(id),\ +} + +static const struct dce_opp_registers opp_regs[] = { + opp_regs(0), + opp_regs(1), + opp_regs(2), + opp_regs(3), + opp_regs(4), + opp_regs(5) +}; + +static const struct dce_opp_shift opp_shift = { + OPP_COMMON_MASK_SH_LIST_DCE_100(__SHIFT) +}; + +static const struct dce_opp_mask opp_mask = { + OPP_COMMON_MASK_SH_LIST_DCE_100(_MASK) +}; +#define aux_engine_regs(id)\ +[id] = {\ + AUX_COMMON_REG_LIST(id), \ + .AUX_RESET_MASK = 0 \ +} + +static const struct dce110_aux_registers aux_engine_regs[] = { + aux_engine_regs(0), + aux_engine_regs(1), + aux_engine_regs(2), + aux_engine_regs(3), + aux_engine_regs(4), + aux_engine_regs(5) +}; + +#define audio_regs(id)\ +[id] = {\ + AUD_COMMON_REG_LIST(id)\ +} + +static const struct dce_audio_registers audio_regs[] = { + audio_regs(0), + audio_regs(1), + audio_regs(2), + audio_regs(3), + audio_regs(4), + audio_regs(5), + audio_regs(6), +}; + +static const struct dce_audio_shift audio_shift = { + AUD_COMMON_MASK_SH_LIST(__SHIFT) +}; + +static const struct dce_audio_mask audio_mask = { + AUD_COMMON_MASK_SH_LIST(_MASK) +}; + +#define clk_src_regs(id)\ +[id] = {\ + CS_COMMON_REG_LIST_DCE_100_110(id),\ +} + +static const struct dce110_clk_src_regs clk_src_regs[] = { + clk_src_regs(0), + clk_src_regs(1), + clk_src_regs(2) +}; + +static const struct dce110_clk_src_shift cs_shift = { + CS_COMMON_MASK_SH_LIST_DCE_COMMON_BASE(__SHIFT) +}; + +static const struct dce110_clk_src_mask cs_mask = { + CS_COMMON_MASK_SH_LIST_DCE_COMMON_BASE(_MASK) +}; + +static const struct dce_dmcu_registers dmcu_regs = { + DMCU_DCE110_COMMON_REG_LIST() +}; + +static const struct dce_dmcu_shift dmcu_shift = { + DMCU_MASK_SH_LIST_DCE110(__SHIFT) +}; + +static const struct dce_dmcu_mask dmcu_mask = { + DMCU_MASK_SH_LIST_DCE110(_MASK) +}; + +static const struct dce_abm_registers abm_regs = { + ABM_DCE110_COMMON_REG_LIST() +}; + +static const struct dce_abm_shift abm_shift = { + ABM_MASK_SH_LIST_DCE110(__SHIFT) +}; + +static const struct dce_abm_mask abm_mask = { + ABM_MASK_SH_LIST_DCE110(_MASK) +}; + +#define DCFE_MEM_PWR_CTRL_REG_BASE 0x1b03 + +static const struct bios_registers bios_regs = { + .BIOS_SCRATCH_3 = mmBIOS_SCRATCH_3, + .BIOS_SCRATCH_6 = mmBIOS_SCRATCH_6 +}; + +static const struct resource_caps res_cap = { + .num_timing_generator = 6, + .num_audio = 6, + .num_stream_encoder = 6, + .num_pll = 3, + .num_ddc = 6, +}; + +static const struct dc_plane_cap plane_cap = { + .type = DC_PLANE_TYPE_DCE_RGB, + + .pixel_format_support = { + .argb8888 = true, + .nv12 = false, + .fp16 = true + }, + + .max_upscale_factor = { + .argb8888 = 16000, + .nv12 = 1, + .fp16 = 1 + }, + + .max_downscale_factor = { + .argb8888 = 250, + .nv12 = 1, + .fp16 = 1 + } +}; + +static const struct dc_debug_options debug_defaults = { + .enable_legacy_fast_update = true, +}; + +#define CTX ctx +#define REG(reg) mm ## reg + +#ifndef mmCC_DC_HDMI_STRAPS +#define mmCC_DC_HDMI_STRAPS 0x1918 +#define CC_DC_HDMI_STRAPS__HDMI_DISABLE_MASK 0x40 +#define CC_DC_HDMI_STRAPS__HDMI_DISABLE__SHIFT 0x6 +#define CC_DC_HDMI_STRAPS__AUDIO_STREAM_NUMBER_MASK 0x700 +#define CC_DC_HDMI_STRAPS__AUDIO_STREAM_NUMBER__SHIFT 0x8 +#endif + +static int map_transmitter_id_to_phy_instance( + enum transmitter transmitter) +{ + switch (transmitter) { + case TRANSMITTER_UNIPHY_A: + return 0; + case TRANSMITTER_UNIPHY_B: + return 1; + case TRANSMITTER_UNIPHY_C: + return 2; + case TRANSMITTER_UNIPHY_D: + return 3; + case TRANSMITTER_UNIPHY_E: + return 4; + case TRANSMITTER_UNIPHY_F: + return 5; + case TRANSMITTER_UNIPHY_G: + return 6; + default: + ASSERT(0); + return 0; + } +} + +static void read_dce_straps( + struct dc_context *ctx, + struct resource_straps *straps) +{ + REG_GET_2(CC_DC_HDMI_STRAPS, + HDMI_DISABLE, &straps->hdmi_disable, + AUDIO_STREAM_NUMBER, &straps->audio_stream_number); + + REG_GET(DC_PINSTRAPS, DC_PINSTRAPS_AUDIO, &straps->dc_pinstraps_audio); +} + +static struct audio *create_audio( + struct dc_context *ctx, unsigned int inst) +{ + return dce_audio_create(ctx, inst, + &audio_regs[inst], &audio_shift, &audio_mask); +} + +static struct timing_generator *dce100_timing_generator_create( + struct dc_context *ctx, + uint32_t instance, + const struct dce110_timing_generator_offsets *offsets) +{ + struct dce110_timing_generator *tg110 = + kzalloc(sizeof(struct dce110_timing_generator), GFP_KERNEL); + + if (!tg110) + return NULL; + + dce110_timing_generator_construct(tg110, ctx, instance, offsets); + return &tg110->base; +} + +static struct stream_encoder *dce100_stream_encoder_create( + enum engine_id eng_id, + struct dc_context *ctx) +{ + struct dce110_stream_encoder *enc110 = + kzalloc(sizeof(struct dce110_stream_encoder), GFP_KERNEL); + + if (!enc110) + return NULL; + + dce110_stream_encoder_construct(enc110, ctx, ctx->dc_bios, eng_id, + &stream_enc_regs[eng_id], &se_shift, &se_mask); + return &enc110->base; +} + +#define SRII(reg_name, block, id)\ + .reg_name[id] = mm ## block ## id ## _ ## reg_name + +static const struct dce_hwseq_registers hwseq_reg = { + HWSEQ_DCE10_REG_LIST() +}; + +static const struct dce_hwseq_shift hwseq_shift = { + HWSEQ_DCE10_MASK_SH_LIST(__SHIFT) +}; + +static const struct dce_hwseq_mask hwseq_mask = { + HWSEQ_DCE10_MASK_SH_LIST(_MASK) +}; + +static struct dce_hwseq *dce100_hwseq_create( + struct dc_context *ctx) +{ + struct dce_hwseq *hws = kzalloc(sizeof(struct dce_hwseq), GFP_KERNEL); + + if (hws) { + hws->ctx = ctx; + hws->regs = &hwseq_reg; + hws->shifts = &hwseq_shift; + hws->masks = &hwseq_mask; + } + return hws; +} + +static const struct resource_create_funcs res_create_funcs = { + .read_dce_straps = read_dce_straps, + .create_audio = create_audio, + .create_stream_encoder = dce100_stream_encoder_create, + .create_hwseq = dce100_hwseq_create, +}; + +#define mi_inst_regs(id) { \ + MI_DCE8_REG_LIST(id), \ + .MC_HUB_RDREQ_DMIF_LIMIT = mmMC_HUB_RDREQ_DMIF_LIMIT \ +} +static const struct dce_mem_input_registers mi_regs[] = { + mi_inst_regs(0), + mi_inst_regs(1), + mi_inst_regs(2), + mi_inst_regs(3), + mi_inst_regs(4), + mi_inst_regs(5), +}; + +static const struct dce_mem_input_shift mi_shifts = { + MI_DCE8_MASK_SH_LIST(__SHIFT), + .ENABLE = MC_HUB_RDREQ_DMIF_LIMIT__ENABLE__SHIFT +}; + +static const struct dce_mem_input_mask mi_masks = { + MI_DCE8_MASK_SH_LIST(_MASK), + .ENABLE = MC_HUB_RDREQ_DMIF_LIMIT__ENABLE_MASK +}; + +static const struct dce110_aux_registers_shift aux_shift = { + DCE10_AUX_MASK_SH_LIST(__SHIFT) +}; + +static const struct dce110_aux_registers_mask aux_mask = { + DCE10_AUX_MASK_SH_LIST(_MASK) +}; + +static struct mem_input *dce100_mem_input_create( + struct dc_context *ctx, + uint32_t inst) +{ + struct dce_mem_input *dce_mi = kzalloc(sizeof(struct dce_mem_input), + GFP_KERNEL); + + if (!dce_mi) { + BREAK_TO_DEBUGGER(); + return NULL; + } + + dce_mem_input_construct(dce_mi, ctx, inst, &mi_regs[inst], &mi_shifts, &mi_masks); + dce_mi->wa.single_head_rdreq_dmif_limit = 2; + return &dce_mi->base; +} + +static void dce100_transform_destroy(struct transform **xfm) +{ + kfree(TO_DCE_TRANSFORM(*xfm)); + *xfm = NULL; +} + +static struct transform *dce100_transform_create( + struct dc_context *ctx, + uint32_t inst) +{ + struct dce_transform *transform = + kzalloc(sizeof(struct dce_transform), GFP_KERNEL); + + if (!transform) + return NULL; + + dce_transform_construct(transform, ctx, inst, + &xfm_regs[inst], &xfm_shift, &xfm_mask); + return &transform->base; +} + +static struct input_pixel_processor *dce100_ipp_create( + struct dc_context *ctx, uint32_t inst) +{ + struct dce_ipp *ipp = kzalloc(sizeof(struct dce_ipp), GFP_KERNEL); + + if (!ipp) { + BREAK_TO_DEBUGGER(); + return NULL; + } + + dce_ipp_construct(ipp, ctx, inst, + &ipp_regs[inst], &ipp_shift, &ipp_mask); + return &ipp->base; +} + +static const struct encoder_feature_support link_enc_feature = { + .max_hdmi_deep_color = COLOR_DEPTH_121212, + .max_hdmi_pixel_clock = 300000, + .flags.bits.IS_HBR2_CAPABLE = true, + .flags.bits.IS_TPS3_CAPABLE = true +}; + +static struct link_encoder *dce100_link_encoder_create( + struct dc_context *ctx, + const struct encoder_init_data *enc_init_data) +{ + struct dce110_link_encoder *enc110 = + kzalloc(sizeof(struct dce110_link_encoder), GFP_KERNEL); + int link_regs_id; + + if (!enc110) + return NULL; + + link_regs_id = + map_transmitter_id_to_phy_instance(enc_init_data->transmitter); + + dce110_link_encoder_construct(enc110, + enc_init_data, + &link_enc_feature, + &link_enc_regs[link_regs_id], + &link_enc_aux_regs[enc_init_data->channel - 1], + &link_enc_hpd_regs[enc_init_data->hpd_source]); + return &enc110->base; +} + +static struct panel_cntl *dce100_panel_cntl_create(const struct panel_cntl_init_data *init_data) +{ + struct dce_panel_cntl *panel_cntl = + kzalloc(sizeof(struct dce_panel_cntl), GFP_KERNEL); + + if (!panel_cntl) + return NULL; + + dce_panel_cntl_construct(panel_cntl, + init_data, + &panel_cntl_regs[init_data->inst], + &panel_cntl_shift, + &panel_cntl_mask); + + return &panel_cntl->base; +} + +static struct output_pixel_processor *dce100_opp_create( + struct dc_context *ctx, + uint32_t inst) +{ + struct dce110_opp *opp = + kzalloc(sizeof(struct dce110_opp), GFP_KERNEL); + + if (!opp) + return NULL; + + dce110_opp_construct(opp, + ctx, inst, &opp_regs[inst], &opp_shift, &opp_mask); + return &opp->base; +} + +static struct dce_aux *dce100_aux_engine_create( + struct dc_context *ctx, + uint32_t inst) +{ + struct aux_engine_dce110 *aux_engine = + kzalloc(sizeof(struct aux_engine_dce110), GFP_KERNEL); + + if (!aux_engine) + return NULL; + + dce110_aux_engine_construct(aux_engine, ctx, inst, + SW_AUX_TIMEOUT_PERIOD_MULTIPLIER * AUX_TIMEOUT_PERIOD, + &aux_engine_regs[inst], + &aux_mask, + &aux_shift, + ctx->dc->caps.extended_aux_timeout_support); + + return &aux_engine->base; +} +#define i2c_inst_regs(id) { I2C_HW_ENGINE_COMMON_REG_LIST(id) } + +static const struct dce_i2c_registers i2c_hw_regs[] = { + i2c_inst_regs(1), + i2c_inst_regs(2), + i2c_inst_regs(3), + i2c_inst_regs(4), + i2c_inst_regs(5), + i2c_inst_regs(6), +}; + +static const struct dce_i2c_shift i2c_shifts = { + I2C_COMMON_MASK_SH_LIST_DCE_COMMON_BASE(__SHIFT) +}; + +static const struct dce_i2c_mask i2c_masks = { + I2C_COMMON_MASK_SH_LIST_DCE_COMMON_BASE(_MASK) +}; + +static struct dce_i2c_hw *dce100_i2c_hw_create( + struct dc_context *ctx, + uint32_t inst) +{ + struct dce_i2c_hw *dce_i2c_hw = + kzalloc(sizeof(struct dce_i2c_hw), GFP_KERNEL); + + if (!dce_i2c_hw) + return NULL; + + dce100_i2c_hw_construct(dce_i2c_hw, ctx, inst, + &i2c_hw_regs[inst], &i2c_shifts, &i2c_masks); + + return dce_i2c_hw; +} +static struct clock_source *dce100_clock_source_create( + struct dc_context *ctx, + struct dc_bios *bios, + enum clock_source_id id, + const struct dce110_clk_src_regs *regs, + bool dp_clk_src) +{ + struct dce110_clk_src *clk_src = + kzalloc(sizeof(struct dce110_clk_src), GFP_KERNEL); + + if (!clk_src) + return NULL; + + if (dce110_clk_src_construct(clk_src, ctx, bios, id, + regs, &cs_shift, &cs_mask)) { + clk_src->base.dp_clk_src = dp_clk_src; + return &clk_src->base; + } + + kfree(clk_src); + BREAK_TO_DEBUGGER(); + return NULL; +} + +static void dce100_clock_source_destroy(struct clock_source **clk_src) +{ + kfree(TO_DCE110_CLK_SRC(*clk_src)); + *clk_src = NULL; +} + +static void dce100_resource_destruct(struct dce110_resource_pool *pool) +{ + unsigned int i; + + for (i = 0; i < pool->base.pipe_count; i++) { + if (pool->base.opps[i] != NULL) + dce110_opp_destroy(&pool->base.opps[i]); + + if (pool->base.transforms[i] != NULL) + dce100_transform_destroy(&pool->base.transforms[i]); + + if (pool->base.ipps[i] != NULL) + dce_ipp_destroy(&pool->base.ipps[i]); + + if (pool->base.mis[i] != NULL) { + kfree(TO_DCE_MEM_INPUT(pool->base.mis[i])); + pool->base.mis[i] = NULL; + } + + if (pool->base.timing_generators[i] != NULL) { + kfree(DCE110TG_FROM_TG(pool->base.timing_generators[i])); + pool->base.timing_generators[i] = NULL; + } + } + + for (i = 0; i < pool->base.res_cap->num_ddc; i++) { + if (pool->base.engines[i] != NULL) + dce110_engine_destroy(&pool->base.engines[i]); + if (pool->base.hw_i2cs[i] != NULL) { + kfree(pool->base.hw_i2cs[i]); + pool->base.hw_i2cs[i] = NULL; + } + if (pool->base.sw_i2cs[i] != NULL) { + kfree(pool->base.sw_i2cs[i]); + pool->base.sw_i2cs[i] = NULL; + } + } + + for (i = 0; i < pool->base.stream_enc_count; i++) { + if (pool->base.stream_enc[i] != NULL) + kfree(DCE110STRENC_FROM_STRENC(pool->base.stream_enc[i])); + } + + for (i = 0; i < pool->base.clk_src_count; i++) { + if (pool->base.clock_sources[i] != NULL) + dce100_clock_source_destroy(&pool->base.clock_sources[i]); + } + + if (pool->base.dp_clock_source != NULL) + dce100_clock_source_destroy(&pool->base.dp_clock_source); + + for (i = 0; i < pool->base.audio_count; i++) { + if (pool->base.audios[i] != NULL) + dce_aud_destroy(&pool->base.audios[i]); + } + + if (pool->base.abm != NULL) + dce_abm_destroy(&pool->base.abm); + + if (pool->base.dmcu != NULL) + dce_dmcu_destroy(&pool->base.dmcu); + + if (pool->base.irqs != NULL) + dal_irq_service_destroy(&pool->base.irqs); +} + +static enum dc_status build_mapped_resource( + const struct dc *dc, + struct dc_state *context, + struct dc_stream_state *stream) +{ + struct pipe_ctx *pipe_ctx = resource_get_otg_master_for_stream(&context->res_ctx, stream); + + if (!pipe_ctx) + return DC_ERROR_UNEXPECTED; + + dce110_resource_build_pipe_hw_param(pipe_ctx); + + resource_build_info_frame(pipe_ctx); + + return DC_OK; +} + +static bool dce100_validate_bandwidth( + struct dc *dc, + struct dc_state *context, + bool fast_validate) +{ + int i; + bool at_least_one_pipe = false; + + for (i = 0; i < dc->res_pool->pipe_count; i++) { + if (context->res_ctx.pipe_ctx[i].stream) + at_least_one_pipe = true; + } + + if (at_least_one_pipe) { + /* TODO implement when needed but for now hardcode max value*/ + context->bw_ctx.bw.dce.dispclk_khz = 681000; + context->bw_ctx.bw.dce.yclk_khz = 250000 * MEMORY_TYPE_MULTIPLIER_CZ; + } else { + context->bw_ctx.bw.dce.dispclk_khz = 0; + context->bw_ctx.bw.dce.yclk_khz = 0; + } + + return true; +} + +static bool dce100_validate_surface_sets( + struct dc_state *context) +{ + int i; + + for (i = 0; i < context->stream_count; i++) { + if (context->stream_status[i].plane_count == 0) + continue; + + if (context->stream_status[i].plane_count > 1) + return false; + + if (context->stream_status[i].plane_states[0]->format + >= SURFACE_PIXEL_FORMAT_VIDEO_BEGIN) + return false; + } + + return true; +} + +static enum dc_status dce100_validate_global( + struct dc *dc, + struct dc_state *context) +{ + if (!dce100_validate_surface_sets(context)) + return DC_FAIL_SURFACE_VALIDATE; + + return DC_OK; +} + +enum dc_status dce100_add_stream_to_ctx( + struct dc *dc, + struct dc_state *new_ctx, + struct dc_stream_state *dc_stream) +{ + enum dc_status result = DC_ERROR_UNEXPECTED; + + result = resource_map_pool_resources(dc, new_ctx, dc_stream); + + if (result == DC_OK) + result = resource_map_clock_resources(dc, new_ctx, dc_stream); + + if (result == DC_OK) + result = build_mapped_resource(dc, new_ctx, dc_stream); + + return result; +} + +static void dce100_destroy_resource_pool(struct resource_pool **pool) +{ + struct dce110_resource_pool *dce110_pool = TO_DCE110_RES_POOL(*pool); + + dce100_resource_destruct(dce110_pool); + kfree(dce110_pool); + *pool = NULL; +} + +enum dc_status dce100_validate_plane(const struct dc_plane_state *plane_state, struct dc_caps *caps) +{ + + if (plane_state->format < SURFACE_PIXEL_FORMAT_VIDEO_BEGIN) + return DC_OK; + + return DC_FAIL_SURFACE_VALIDATE; +} + +struct stream_encoder *dce100_find_first_free_match_stream_enc_for_link( + struct resource_context *res_ctx, + const struct resource_pool *pool, + struct dc_stream_state *stream) +{ + int i; + int j = -1; + struct dc_link *link = stream->link; + + for (i = 0; i < pool->stream_enc_count; i++) { + if (!res_ctx->is_stream_enc_acquired[i] && + pool->stream_enc[i]) { + /* Store first available for MST second display + * in daisy chain use case + */ + j = i; + if (pool->stream_enc[i]->id == + link->link_enc->preferred_engine) + return pool->stream_enc[i]; + } + } + + /* + * below can happen in cases when stream encoder is acquired: + * 1) for second MST display in chain, so preferred engine already + * acquired; + * 2) for another link, which preferred engine already acquired by any + * MST configuration. + * + * If signal is of DP type and preferred engine not found, return last available + * + * TODO - This is just a patch up and a generic solution is + * required for non DP connectors. + */ + + if (j >= 0 && link->connector_signal == SIGNAL_TYPE_DISPLAY_PORT) + return pool->stream_enc[j]; + + return NULL; +} + +static const struct resource_funcs dce100_res_pool_funcs = { + .destroy = dce100_destroy_resource_pool, + .link_enc_create = dce100_link_encoder_create, + .panel_cntl_create = dce100_panel_cntl_create, + .validate_bandwidth = dce100_validate_bandwidth, + .validate_plane = dce100_validate_plane, + .add_stream_to_ctx = dce100_add_stream_to_ctx, + .validate_global = dce100_validate_global, + .find_first_free_match_stream_enc_for_link = dce100_find_first_free_match_stream_enc_for_link +}; + +static bool dce100_resource_construct( + uint8_t num_virtual_links, + struct dc *dc, + struct dce110_resource_pool *pool) +{ + unsigned int i; + struct dc_context *ctx = dc->ctx; + struct dc_bios *bp; + + ctx->dc_bios->regs = &bios_regs; + + pool->base.res_cap = &res_cap; + pool->base.funcs = &dce100_res_pool_funcs; + pool->base.underlay_pipe_index = NO_UNDERLAY_PIPE; + + bp = ctx->dc_bios; + + if (bp->fw_info_valid && bp->fw_info.external_clock_source_frequency_for_dp != 0) { + pool->base.dp_clock_source = + dce100_clock_source_create(ctx, bp, CLOCK_SOURCE_ID_EXTERNAL, NULL, true); + + pool->base.clock_sources[0] = + dce100_clock_source_create(ctx, bp, CLOCK_SOURCE_ID_PLL0, &clk_src_regs[0], false); + pool->base.clock_sources[1] = + dce100_clock_source_create(ctx, bp, CLOCK_SOURCE_ID_PLL1, &clk_src_regs[1], false); + pool->base.clock_sources[2] = + dce100_clock_source_create(ctx, bp, CLOCK_SOURCE_ID_PLL2, &clk_src_regs[2], false); + pool->base.clk_src_count = 3; + + } else { + pool->base.dp_clock_source = + dce100_clock_source_create(ctx, bp, CLOCK_SOURCE_ID_PLL0, &clk_src_regs[0], true); + + pool->base.clock_sources[0] = + dce100_clock_source_create(ctx, bp, CLOCK_SOURCE_ID_PLL1, &clk_src_regs[1], false); + pool->base.clock_sources[1] = + dce100_clock_source_create(ctx, bp, CLOCK_SOURCE_ID_PLL2, &clk_src_regs[2], false); + pool->base.clk_src_count = 2; + } + + if (pool->base.dp_clock_source == NULL) { + dm_error("DC: failed to create dp clock source!\n"); + BREAK_TO_DEBUGGER(); + goto res_create_fail; + } + + for (i = 0; i < pool->base.clk_src_count; i++) { + if (pool->base.clock_sources[i] == NULL) { + dm_error("DC: failed to create clock sources!\n"); + BREAK_TO_DEBUGGER(); + goto res_create_fail; + } + } + + pool->base.dmcu = dce_dmcu_create(ctx, + &dmcu_regs, + &dmcu_shift, + &dmcu_mask); + if (pool->base.dmcu == NULL) { + dm_error("DC: failed to create dmcu!\n"); + BREAK_TO_DEBUGGER(); + goto res_create_fail; + } + + pool->base.abm = dce_abm_create(ctx, + &abm_regs, + &abm_shift, + &abm_mask); + if (pool->base.abm == NULL) { + dm_error("DC: failed to create abm!\n"); + BREAK_TO_DEBUGGER(); + goto res_create_fail; + } + + { + struct irq_service_init_data init_data; + init_data.ctx = dc->ctx; + pool->base.irqs = dal_irq_service_dce110_create(&init_data); + if (!pool->base.irqs) + goto res_create_fail; + } + + /************************************************* + * Resource + asic cap harcoding * + *************************************************/ + pool->base.underlay_pipe_index = NO_UNDERLAY_PIPE; + pool->base.pipe_count = res_cap.num_timing_generator; + pool->base.timing_generator_count = pool->base.res_cap->num_timing_generator; + dc->caps.max_downscale_ratio = 200; + dc->caps.i2c_speed_in_khz = 40; + dc->caps.i2c_speed_in_khz = 40; + dc->caps.max_cursor_size = 128; + dc->caps.min_horizontal_blanking_period = 80; + dc->caps.dual_link_dvi = true; + dc->caps.disable_dp_clk_share = true; + dc->caps.extended_aux_timeout_support = false; + dc->debug = debug_defaults; + + for (i = 0; i < pool->base.pipe_count; i++) { + pool->base.timing_generators[i] = + dce100_timing_generator_create( + ctx, + i, + &dce100_tg_offsets[i]); + if (pool->base.timing_generators[i] == NULL) { + BREAK_TO_DEBUGGER(); + dm_error("DC: failed to create tg!\n"); + goto res_create_fail; + } + + pool->base.mis[i] = dce100_mem_input_create(ctx, i); + if (pool->base.mis[i] == NULL) { + BREAK_TO_DEBUGGER(); + dm_error( + "DC: failed to create memory input!\n"); + goto res_create_fail; + } + + pool->base.ipps[i] = dce100_ipp_create(ctx, i); + if (pool->base.ipps[i] == NULL) { + BREAK_TO_DEBUGGER(); + dm_error( + "DC: failed to create input pixel processor!\n"); + goto res_create_fail; + } + + pool->base.transforms[i] = dce100_transform_create(ctx, i); + if (pool->base.transforms[i] == NULL) { + BREAK_TO_DEBUGGER(); + dm_error( + "DC: failed to create transform!\n"); + goto res_create_fail; + } + + pool->base.opps[i] = dce100_opp_create(ctx, i); + if (pool->base.opps[i] == NULL) { + BREAK_TO_DEBUGGER(); + dm_error( + "DC: failed to create output pixel processor!\n"); + goto res_create_fail; + } + } + + for (i = 0; i < pool->base.res_cap->num_ddc; i++) { + pool->base.engines[i] = dce100_aux_engine_create(ctx, i); + if (pool->base.engines[i] == NULL) { + BREAK_TO_DEBUGGER(); + dm_error( + "DC:failed to create aux engine!!\n"); + goto res_create_fail; + } + pool->base.hw_i2cs[i] = dce100_i2c_hw_create(ctx, i); + if (pool->base.hw_i2cs[i] == NULL) { + BREAK_TO_DEBUGGER(); + dm_error( + "DC:failed to create i2c engine!!\n"); + goto res_create_fail; + } + pool->base.sw_i2cs[i] = NULL; + } + + dc->caps.max_planes = pool->base.pipe_count; + + for (i = 0; i < dc->caps.max_planes; ++i) + dc->caps.planes[i] = plane_cap; + + if (!resource_construct(num_virtual_links, dc, &pool->base, + &res_create_funcs)) + goto res_create_fail; + + /* Create hardware sequencer */ + dce100_hw_sequencer_construct(dc); + return true; + +res_create_fail: + dce100_resource_destruct(pool); + + return false; +} + +struct resource_pool *dce100_create_resource_pool( + uint8_t num_virtual_links, + struct dc *dc) +{ + struct dce110_resource_pool *pool = + kzalloc(sizeof(struct dce110_resource_pool), GFP_KERNEL); + + if (!pool) + return NULL; + + if (dce100_resource_construct(num_virtual_links, dc, pool)) + return &pool->base; + + kfree(pool); + BREAK_TO_DEBUGGER(); + return NULL; +} + diff --git a/drivers/gpu/drm/amd/display/dc/resource/dce100/dce100_resource.h b/drivers/gpu/drm/amd/display/dc/resource/dce100/dce100_resource.h new file mode 100644 index 000000000000..fecab7c560f5 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/resource/dce100/dce100_resource.h @@ -0,0 +1,54 @@ +/* + * Copyright 2017 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. + * + * + */ +/* + * dce100_resource.h + * + * Created on: 2016-01-20 + * Author: qyang + */ + +#ifndef DCE100_RESOURCE_H_ +#define DCE100_RESOURCE_H_ + +struct dc; +struct resource_pool; +struct dc_validation_set; + +struct resource_pool *dce100_create_resource_pool( + uint8_t num_virtual_links, + struct dc *dc); + +enum dc_status dce100_validate_plane(const struct dc_plane_state *plane_state, struct dc_caps *caps); + +enum dc_status dce100_add_stream_to_ctx( + struct dc *dc, + struct dc_state *new_ctx, + struct dc_stream_state *dc_stream); + +struct stream_encoder *dce100_find_first_free_match_stream_enc_for_link( + struct resource_context *res_ctx, + const struct resource_pool *pool, + struct dc_stream_state *stream); + +#endif /* DCE100_RESOURCE_H_ */ diff --git a/drivers/gpu/drm/amd/display/dc/resource/dce110/dce110_resource.c b/drivers/gpu/drm/amd/display/dc/resource/dce110/dce110_resource.c new file mode 100644 index 000000000000..fe518fd27b08 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/resource/dce110/dce110_resource.c @@ -0,0 +1,1551 @@ +/* + * Copyright 2012-15 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 "dm_services.h" + +#include "link_encoder.h" +#include "stream_encoder.h" + +#include "resource.h" +#include "dce110/dce110_resource.h" +#include "include/irq_service_interface.h" +#include "dce/dce_audio.h" +#include "dce110/dce110_timing_generator.h" +#include "irq/dce110/irq_service_dce110.h" +#include "dce110/dce110_timing_generator_v.h" +#include "dce/dce_link_encoder.h" +#include "dce/dce_stream_encoder.h" +#include "dce/dce_mem_input.h" +#include "dce110/dce110_mem_input_v.h" +#include "dce/dce_ipp.h" +#include "dce/dce_transform.h" +#include "dce110/dce110_transform_v.h" +#include "dce/dce_opp.h" +#include "dce110/dce110_opp_v.h" +#include "dce/dce_clock_source.h" +#include "dce/dce_hwseq.h" +#include "dce110/dce110_hwseq.h" +#include "dce/dce_aux.h" +#include "dce/dce_abm.h" +#include "dce/dce_dmcu.h" +#include "dce/dce_i2c.h" +#include "dce/dce_panel_cntl.h" + +#define DC_LOGGER \ + dc->ctx->logger + +#include "dce110/dce110_compressor.h" + +#include "reg_helper.h" + +#include "dce/dce_11_0_d.h" +#include "dce/dce_11_0_sh_mask.h" + +#ifndef mmMC_HUB_RDREQ_DMIF_LIMIT +#include "gmc/gmc_8_2_d.h" +#include "gmc/gmc_8_2_sh_mask.h" +#endif + +#ifndef mmDP_DPHY_INTERNAL_CTRL + #define mmDP_DPHY_INTERNAL_CTRL 0x4aa7 + #define mmDP0_DP_DPHY_INTERNAL_CTRL 0x4aa7 + #define mmDP1_DP_DPHY_INTERNAL_CTRL 0x4ba7 + #define mmDP2_DP_DPHY_INTERNAL_CTRL 0x4ca7 + #define mmDP3_DP_DPHY_INTERNAL_CTRL 0x4da7 + #define mmDP4_DP_DPHY_INTERNAL_CTRL 0x4ea7 + #define mmDP5_DP_DPHY_INTERNAL_CTRL 0x4fa7 + #define mmDP6_DP_DPHY_INTERNAL_CTRL 0x54a7 + #define mmDP7_DP_DPHY_INTERNAL_CTRL 0x56a7 + #define mmDP8_DP_DPHY_INTERNAL_CTRL 0x57a7 +#endif + +#ifndef mmBIOS_SCRATCH_2 + #define mmBIOS_SCRATCH_2 0x05CB + #define mmBIOS_SCRATCH_3 0x05CC + #define mmBIOS_SCRATCH_6 0x05CF +#endif + +#ifndef mmDP_DPHY_BS_SR_SWAP_CNTL + #define mmDP_DPHY_BS_SR_SWAP_CNTL 0x4ADC + #define mmDP0_DP_DPHY_BS_SR_SWAP_CNTL 0x4ADC + #define mmDP1_DP_DPHY_BS_SR_SWAP_CNTL 0x4BDC + #define mmDP2_DP_DPHY_BS_SR_SWAP_CNTL 0x4CDC + #define mmDP3_DP_DPHY_BS_SR_SWAP_CNTL 0x4DDC + #define mmDP4_DP_DPHY_BS_SR_SWAP_CNTL 0x4EDC + #define mmDP5_DP_DPHY_BS_SR_SWAP_CNTL 0x4FDC + #define mmDP6_DP_DPHY_BS_SR_SWAP_CNTL 0x54DC +#endif + +#ifndef mmDP_DPHY_FAST_TRAINING + #define mmDP_DPHY_FAST_TRAINING 0x4ABC + #define mmDP0_DP_DPHY_FAST_TRAINING 0x4ABC + #define mmDP1_DP_DPHY_FAST_TRAINING 0x4BBC + #define mmDP2_DP_DPHY_FAST_TRAINING 0x4CBC + #define mmDP3_DP_DPHY_FAST_TRAINING 0x4DBC + #define mmDP4_DP_DPHY_FAST_TRAINING 0x4EBC + #define mmDP5_DP_DPHY_FAST_TRAINING 0x4FBC + #define mmDP6_DP_DPHY_FAST_TRAINING 0x54BC +#endif + +#ifndef DPHY_RX_FAST_TRAINING_CAPABLE + #define DPHY_RX_FAST_TRAINING_CAPABLE 0x1 +#endif + +static const struct dce110_timing_generator_offsets dce110_tg_offsets[] = { + { + .crtc = (mmCRTC0_CRTC_CONTROL - mmCRTC_CONTROL), + .dcp = (mmDCP0_GRPH_CONTROL - mmGRPH_CONTROL), + }, + { + .crtc = (mmCRTC1_CRTC_CONTROL - mmCRTC_CONTROL), + .dcp = (mmDCP1_GRPH_CONTROL - mmGRPH_CONTROL), + }, + { + .crtc = (mmCRTC2_CRTC_CONTROL - mmCRTC_CONTROL), + .dcp = (mmDCP2_GRPH_CONTROL - mmGRPH_CONTROL), + }, + { + .crtc = (mmCRTC3_CRTC_CONTROL - mmCRTC_CONTROL), + .dcp = (mmDCP3_GRPH_CONTROL - mmGRPH_CONTROL), + }, + { + .crtc = (mmCRTC4_CRTC_CONTROL - mmCRTC_CONTROL), + .dcp = (mmDCP4_GRPH_CONTROL - mmGRPH_CONTROL), + }, + { + .crtc = (mmCRTC5_CRTC_CONTROL - mmCRTC_CONTROL), + .dcp = (mmDCP5_GRPH_CONTROL - mmGRPH_CONTROL), + } +}; + +/* set register offset */ +#define SR(reg_name)\ + .reg_name = mm ## reg_name + +/* set register offset with instance */ +#define SRI(reg_name, block, id)\ + .reg_name = mm ## block ## id ## _ ## reg_name + +static const struct dce_dmcu_registers dmcu_regs = { + DMCU_DCE110_COMMON_REG_LIST() +}; + +static const struct dce_dmcu_shift dmcu_shift = { + DMCU_MASK_SH_LIST_DCE110(__SHIFT) +}; + +static const struct dce_dmcu_mask dmcu_mask = { + DMCU_MASK_SH_LIST_DCE110(_MASK) +}; + +static const struct dce_abm_registers abm_regs = { + ABM_DCE110_COMMON_REG_LIST() +}; + +static const struct dce_abm_shift abm_shift = { + ABM_MASK_SH_LIST_DCE110(__SHIFT) +}; + +static const struct dce_abm_mask abm_mask = { + ABM_MASK_SH_LIST_DCE110(_MASK) +}; + +#define ipp_regs(id)\ +[id] = {\ + IPP_DCE110_REG_LIST_DCE_BASE(id)\ +} + +static const struct dce_ipp_registers ipp_regs[] = { + ipp_regs(0), + ipp_regs(1), + ipp_regs(2) +}; + +static const struct dce_ipp_shift ipp_shift = { + IPP_DCE100_MASK_SH_LIST_DCE_COMMON_BASE(__SHIFT) +}; + +static const struct dce_ipp_mask ipp_mask = { + IPP_DCE100_MASK_SH_LIST_DCE_COMMON_BASE(_MASK) +}; + +#define transform_regs(id)\ +[id] = {\ + XFM_COMMON_REG_LIST_DCE110(id)\ +} + +static const struct dce_transform_registers xfm_regs[] = { + transform_regs(0), + transform_regs(1), + transform_regs(2) +}; + +static const struct dce_transform_shift xfm_shift = { + XFM_COMMON_MASK_SH_LIST_DCE110(__SHIFT) +}; + +static const struct dce_transform_mask xfm_mask = { + XFM_COMMON_MASK_SH_LIST_DCE110(_MASK) +}; + +#define aux_regs(id)\ +[id] = {\ + AUX_REG_LIST(id)\ +} + +static const struct dce110_link_enc_aux_registers link_enc_aux_regs[] = { + aux_regs(0), + aux_regs(1), + aux_regs(2), + aux_regs(3), + aux_regs(4), + aux_regs(5) +}; + +#define hpd_regs(id)\ +[id] = {\ + HPD_REG_LIST(id)\ +} + +static const struct dce110_link_enc_hpd_registers link_enc_hpd_regs[] = { + hpd_regs(0), + hpd_regs(1), + hpd_regs(2), + hpd_regs(3), + hpd_regs(4), + hpd_regs(5) +}; + + +#define link_regs(id)\ +[id] = {\ + LE_DCE110_REG_LIST(id)\ +} + +static const struct dce110_link_enc_registers link_enc_regs[] = { + link_regs(0), + link_regs(1), + link_regs(2), + link_regs(3), + link_regs(4), + link_regs(5), + link_regs(6), +}; + +#define stream_enc_regs(id)\ +[id] = {\ + SE_COMMON_REG_LIST(id),\ + .TMDS_CNTL = 0,\ +} + +static const struct dce110_stream_enc_registers stream_enc_regs[] = { + stream_enc_regs(0), + stream_enc_regs(1), + stream_enc_regs(2) +}; + +static const struct dce_stream_encoder_shift se_shift = { + SE_COMMON_MASK_SH_LIST_DCE110(__SHIFT) +}; + +static const struct dce_stream_encoder_mask se_mask = { + SE_COMMON_MASK_SH_LIST_DCE110(_MASK) +}; + +static const struct dce_panel_cntl_registers panel_cntl_regs[] = { + { DCE_PANEL_CNTL_REG_LIST() } +}; + +static const struct dce_panel_cntl_shift panel_cntl_shift = { + DCE_PANEL_CNTL_MASK_SH_LIST(__SHIFT) +}; + +static const struct dce_panel_cntl_mask panel_cntl_mask = { + DCE_PANEL_CNTL_MASK_SH_LIST(_MASK) +}; + +static const struct dce110_aux_registers_shift aux_shift = { + DCE_AUX_MASK_SH_LIST(__SHIFT) +}; + +static const struct dce110_aux_registers_mask aux_mask = { + DCE_AUX_MASK_SH_LIST(_MASK) +}; + +#define opp_regs(id)\ +[id] = {\ + OPP_DCE_110_REG_LIST(id),\ +} + +static const struct dce_opp_registers opp_regs[] = { + opp_regs(0), + opp_regs(1), + opp_regs(2), + opp_regs(3), + opp_regs(4), + opp_regs(5) +}; + +static const struct dce_opp_shift opp_shift = { + OPP_COMMON_MASK_SH_LIST_DCE_110(__SHIFT) +}; + +static const struct dce_opp_mask opp_mask = { + OPP_COMMON_MASK_SH_LIST_DCE_110(_MASK) +}; + +#define aux_engine_regs(id)\ +[id] = {\ + AUX_COMMON_REG_LIST(id), \ + .AUX_RESET_MASK = 0 \ +} + +static const struct dce110_aux_registers aux_engine_regs[] = { + aux_engine_regs(0), + aux_engine_regs(1), + aux_engine_regs(2), + aux_engine_regs(3), + aux_engine_regs(4), + aux_engine_regs(5) +}; + +#define audio_regs(id)\ +[id] = {\ + AUD_COMMON_REG_LIST(id)\ +} + +static const struct dce_audio_registers audio_regs[] = { + audio_regs(0), + audio_regs(1), + audio_regs(2), + audio_regs(3), + audio_regs(4), + audio_regs(5), + audio_regs(6), +}; + +static const struct dce_audio_shift audio_shift = { + AUD_COMMON_MASK_SH_LIST(__SHIFT) +}; + +static const struct dce_audio_mask audio_mask = { + AUD_COMMON_MASK_SH_LIST(_MASK) +}; + +/* AG TBD Needs to be reduced back to 3 pipes once dce10 hw sequencer implemented. */ + + +#define clk_src_regs(id)\ +[id] = {\ + CS_COMMON_REG_LIST_DCE_100_110(id),\ +} + +static const struct dce110_clk_src_regs clk_src_regs[] = { + clk_src_regs(0), + clk_src_regs(1), + clk_src_regs(2) +}; + +static const struct dce110_clk_src_shift cs_shift = { + CS_COMMON_MASK_SH_LIST_DCE_COMMON_BASE(__SHIFT) +}; + +static const struct dce110_clk_src_mask cs_mask = { + CS_COMMON_MASK_SH_LIST_DCE_COMMON_BASE(_MASK) +}; + +static const struct bios_registers bios_regs = { + .BIOS_SCRATCH_3 = mmBIOS_SCRATCH_3, + .BIOS_SCRATCH_6 = mmBIOS_SCRATCH_6 +}; + +static const struct resource_caps carrizo_resource_cap = { + .num_timing_generator = 3, + .num_video_plane = 1, + .num_audio = 3, + .num_stream_encoder = 3, + .num_pll = 2, + .num_ddc = 3, +}; + +static const struct resource_caps stoney_resource_cap = { + .num_timing_generator = 2, + .num_video_plane = 1, + .num_audio = 3, + .num_stream_encoder = 3, + .num_pll = 2, + .num_ddc = 3, +}; + +static const struct dc_plane_cap plane_cap = { + .type = DC_PLANE_TYPE_DCE_RGB, + .per_pixel_alpha = 1, + + .pixel_format_support = { + .argb8888 = true, + .nv12 = false, + .fp16 = true + }, + + .max_upscale_factor = { + .argb8888 = 16000, + .nv12 = 1, + .fp16 = 1 + }, + + .max_downscale_factor = { + .argb8888 = 250, + .nv12 = 1, + .fp16 = 1 + }, + 64, + 64 +}; + +static const struct dc_debug_options debug_defaults = { + .enable_legacy_fast_update = true, +}; + +static const struct dc_plane_cap underlay_plane_cap = { + .type = DC_PLANE_TYPE_DCE_UNDERLAY, + .per_pixel_alpha = 1, + + .pixel_format_support = { + .argb8888 = false, + .nv12 = true, + .fp16 = false + }, + + .max_upscale_factor = { + .argb8888 = 1, + .nv12 = 16000, + .fp16 = 1 + }, + + .max_downscale_factor = { + .argb8888 = 1, + .nv12 = 250, + .fp16 = 1 + }, + 64, + 64 +}; + +#define CTX ctx +#define REG(reg) mm ## reg + +#ifndef mmCC_DC_HDMI_STRAPS +#define mmCC_DC_HDMI_STRAPS 0x4819 +#define CC_DC_HDMI_STRAPS__HDMI_DISABLE_MASK 0x40 +#define CC_DC_HDMI_STRAPS__HDMI_DISABLE__SHIFT 0x6 +#define CC_DC_HDMI_STRAPS__AUDIO_STREAM_NUMBER_MASK 0x700 +#define CC_DC_HDMI_STRAPS__AUDIO_STREAM_NUMBER__SHIFT 0x8 +#endif + +static int map_transmitter_id_to_phy_instance( + enum transmitter transmitter) +{ + switch (transmitter) { + case TRANSMITTER_UNIPHY_A: + return 0; + case TRANSMITTER_UNIPHY_B: + return 1; + case TRANSMITTER_UNIPHY_C: + return 2; + case TRANSMITTER_UNIPHY_D: + return 3; + case TRANSMITTER_UNIPHY_E: + return 4; + case TRANSMITTER_UNIPHY_F: + return 5; + case TRANSMITTER_UNIPHY_G: + return 6; + default: + ASSERT(0); + return 0; + } +} + +static void read_dce_straps( + struct dc_context *ctx, + struct resource_straps *straps) +{ + REG_GET_2(CC_DC_HDMI_STRAPS, + HDMI_DISABLE, &straps->hdmi_disable, + AUDIO_STREAM_NUMBER, &straps->audio_stream_number); + + REG_GET(DC_PINSTRAPS, DC_PINSTRAPS_AUDIO, &straps->dc_pinstraps_audio); +} + +static struct audio *create_audio( + struct dc_context *ctx, unsigned int inst) +{ + return dce_audio_create(ctx, inst, + &audio_regs[inst], &audio_shift, &audio_mask); +} + +static struct timing_generator *dce110_timing_generator_create( + struct dc_context *ctx, + uint32_t instance, + const struct dce110_timing_generator_offsets *offsets) +{ + struct dce110_timing_generator *tg110 = + kzalloc(sizeof(struct dce110_timing_generator), GFP_KERNEL); + + if (!tg110) + return NULL; + + dce110_timing_generator_construct(tg110, ctx, instance, offsets); + return &tg110->base; +} + +static struct stream_encoder *dce110_stream_encoder_create( + enum engine_id eng_id, + struct dc_context *ctx) +{ + struct dce110_stream_encoder *enc110 = + kzalloc(sizeof(struct dce110_stream_encoder), GFP_KERNEL); + + if (!enc110) + return NULL; + + dce110_stream_encoder_construct(enc110, ctx, ctx->dc_bios, eng_id, + &stream_enc_regs[eng_id], + &se_shift, &se_mask); + return &enc110->base; +} + +#define SRII(reg_name, block, id)\ + .reg_name[id] = mm ## block ## id ## _ ## reg_name + +static const struct dce_hwseq_registers hwseq_stoney_reg = { + HWSEQ_ST_REG_LIST() +}; + +static const struct dce_hwseq_registers hwseq_cz_reg = { + HWSEQ_CZ_REG_LIST() +}; + +static const struct dce_hwseq_shift hwseq_shift = { + HWSEQ_DCE11_MASK_SH_LIST(__SHIFT), +}; + +static const struct dce_hwseq_mask hwseq_mask = { + HWSEQ_DCE11_MASK_SH_LIST(_MASK), +}; + +static struct dce_hwseq *dce110_hwseq_create( + struct dc_context *ctx) +{ + struct dce_hwseq *hws = kzalloc(sizeof(struct dce_hwseq), GFP_KERNEL); + + if (hws) { + hws->ctx = ctx; + hws->regs = ASIC_REV_IS_STONEY(ctx->asic_id.hw_internal_rev) ? + &hwseq_stoney_reg : &hwseq_cz_reg; + hws->shifts = &hwseq_shift; + hws->masks = &hwseq_mask; + hws->wa.blnd_crtc_trigger = true; + } + return hws; +} + +static const struct resource_create_funcs res_create_funcs = { + .read_dce_straps = read_dce_straps, + .create_audio = create_audio, + .create_stream_encoder = dce110_stream_encoder_create, + .create_hwseq = dce110_hwseq_create, +}; + +#define mi_inst_regs(id) { \ + MI_DCE11_REG_LIST(id), \ + .MC_HUB_RDREQ_DMIF_LIMIT = mmMC_HUB_RDREQ_DMIF_LIMIT \ +} +static const struct dce_mem_input_registers mi_regs[] = { + mi_inst_regs(0), + mi_inst_regs(1), + mi_inst_regs(2), +}; + +static const struct dce_mem_input_shift mi_shifts = { + MI_DCE11_MASK_SH_LIST(__SHIFT), + .ENABLE = MC_HUB_RDREQ_DMIF_LIMIT__ENABLE__SHIFT +}; + +static const struct dce_mem_input_mask mi_masks = { + MI_DCE11_MASK_SH_LIST(_MASK), + .ENABLE = MC_HUB_RDREQ_DMIF_LIMIT__ENABLE_MASK +}; + + +static struct mem_input *dce110_mem_input_create( + struct dc_context *ctx, + uint32_t inst) +{ + struct dce_mem_input *dce_mi = kzalloc(sizeof(struct dce_mem_input), + GFP_KERNEL); + + if (!dce_mi) { + BREAK_TO_DEBUGGER(); + return NULL; + } + + dce_mem_input_construct(dce_mi, ctx, inst, &mi_regs[inst], &mi_shifts, &mi_masks); + dce_mi->wa.single_head_rdreq_dmif_limit = 3; + return &dce_mi->base; +} + +static void dce110_transform_destroy(struct transform **xfm) +{ + kfree(TO_DCE_TRANSFORM(*xfm)); + *xfm = NULL; +} + +static struct transform *dce110_transform_create( + struct dc_context *ctx, + uint32_t inst) +{ + struct dce_transform *transform = + kzalloc(sizeof(struct dce_transform), GFP_KERNEL); + + if (!transform) + return NULL; + + dce_transform_construct(transform, ctx, inst, + &xfm_regs[inst], &xfm_shift, &xfm_mask); + return &transform->base; +} + +static struct input_pixel_processor *dce110_ipp_create( + struct dc_context *ctx, uint32_t inst) +{ + struct dce_ipp *ipp = kzalloc(sizeof(struct dce_ipp), GFP_KERNEL); + + if (!ipp) { + BREAK_TO_DEBUGGER(); + return NULL; + } + + dce_ipp_construct(ipp, ctx, inst, + &ipp_regs[inst], &ipp_shift, &ipp_mask); + return &ipp->base; +} + +static const struct encoder_feature_support link_enc_feature = { + .max_hdmi_deep_color = COLOR_DEPTH_121212, + .max_hdmi_pixel_clock = 300000, + .flags.bits.IS_HBR2_CAPABLE = true, + .flags.bits.IS_TPS3_CAPABLE = true +}; + +static struct link_encoder *dce110_link_encoder_create( + struct dc_context *ctx, + const struct encoder_init_data *enc_init_data) +{ + struct dce110_link_encoder *enc110 = + kzalloc(sizeof(struct dce110_link_encoder), GFP_KERNEL); + int link_regs_id; + + if (!enc110) + return NULL; + + link_regs_id = + map_transmitter_id_to_phy_instance(enc_init_data->transmitter); + + dce110_link_encoder_construct(enc110, + enc_init_data, + &link_enc_feature, + &link_enc_regs[link_regs_id], + &link_enc_aux_regs[enc_init_data->channel - 1], + &link_enc_hpd_regs[enc_init_data->hpd_source]); + return &enc110->base; +} + +static struct panel_cntl *dce110_panel_cntl_create(const struct panel_cntl_init_data *init_data) +{ + struct dce_panel_cntl *panel_cntl = + kzalloc(sizeof(struct dce_panel_cntl), GFP_KERNEL); + + if (!panel_cntl) + return NULL; + + dce_panel_cntl_construct(panel_cntl, + init_data, + &panel_cntl_regs[init_data->inst], + &panel_cntl_shift, + &panel_cntl_mask); + + return &panel_cntl->base; +} + +static struct output_pixel_processor *dce110_opp_create( + struct dc_context *ctx, + uint32_t inst) +{ + struct dce110_opp *opp = + kzalloc(sizeof(struct dce110_opp), GFP_KERNEL); + + if (!opp) + return NULL; + + dce110_opp_construct(opp, + ctx, inst, &opp_regs[inst], &opp_shift, &opp_mask); + return &opp->base; +} + +static struct dce_aux *dce110_aux_engine_create( + struct dc_context *ctx, + uint32_t inst) +{ + struct aux_engine_dce110 *aux_engine = + kzalloc(sizeof(struct aux_engine_dce110), GFP_KERNEL); + + if (!aux_engine) + return NULL; + + dce110_aux_engine_construct(aux_engine, ctx, inst, + SW_AUX_TIMEOUT_PERIOD_MULTIPLIER * AUX_TIMEOUT_PERIOD, + &aux_engine_regs[inst], + &aux_mask, + &aux_shift, + ctx->dc->caps.extended_aux_timeout_support); + + return &aux_engine->base; +} +#define i2c_inst_regs(id) { I2C_HW_ENGINE_COMMON_REG_LIST(id) } + +static const struct dce_i2c_registers i2c_hw_regs[] = { + i2c_inst_regs(1), + i2c_inst_regs(2), + i2c_inst_regs(3), + i2c_inst_regs(4), + i2c_inst_regs(5), + i2c_inst_regs(6), +}; + +static const struct dce_i2c_shift i2c_shifts = { + I2C_COMMON_MASK_SH_LIST_DCE110(__SHIFT) +}; + +static const struct dce_i2c_mask i2c_masks = { + I2C_COMMON_MASK_SH_LIST_DCE110(_MASK) +}; + +static struct dce_i2c_hw *dce110_i2c_hw_create( + struct dc_context *ctx, + uint32_t inst) +{ + struct dce_i2c_hw *dce_i2c_hw = + kzalloc(sizeof(struct dce_i2c_hw), GFP_KERNEL); + + if (!dce_i2c_hw) + return NULL; + + dce100_i2c_hw_construct(dce_i2c_hw, ctx, inst, + &i2c_hw_regs[inst], &i2c_shifts, &i2c_masks); + + return dce_i2c_hw; +} +static struct clock_source *dce110_clock_source_create( + struct dc_context *ctx, + struct dc_bios *bios, + enum clock_source_id id, + const struct dce110_clk_src_regs *regs, + bool dp_clk_src) +{ + struct dce110_clk_src *clk_src = + kzalloc(sizeof(struct dce110_clk_src), GFP_KERNEL); + + if (!clk_src) + return NULL; + + if (dce110_clk_src_construct(clk_src, ctx, bios, id, + regs, &cs_shift, &cs_mask)) { + clk_src->base.dp_clk_src = dp_clk_src; + return &clk_src->base; + } + + kfree(clk_src); + BREAK_TO_DEBUGGER(); + return NULL; +} + +static void dce110_clock_source_destroy(struct clock_source **clk_src) +{ + struct dce110_clk_src *dce110_clk_src; + + if (!clk_src) + return; + + dce110_clk_src = TO_DCE110_CLK_SRC(*clk_src); + + kfree(dce110_clk_src->dp_ss_params); + kfree(dce110_clk_src->hdmi_ss_params); + kfree(dce110_clk_src->dvi_ss_params); + + kfree(dce110_clk_src); + *clk_src = NULL; +} + +static void dce110_resource_destruct(struct dce110_resource_pool *pool) +{ + unsigned int i; + + for (i = 0; i < pool->base.pipe_count; i++) { + if (pool->base.opps[i] != NULL) + dce110_opp_destroy(&pool->base.opps[i]); + + if (pool->base.transforms[i] != NULL) + dce110_transform_destroy(&pool->base.transforms[i]); + + if (pool->base.ipps[i] != NULL) + dce_ipp_destroy(&pool->base.ipps[i]); + + if (pool->base.mis[i] != NULL) { + kfree(TO_DCE_MEM_INPUT(pool->base.mis[i])); + pool->base.mis[i] = NULL; + } + + if (pool->base.timing_generators[i] != NULL) { + kfree(DCE110TG_FROM_TG(pool->base.timing_generators[i])); + pool->base.timing_generators[i] = NULL; + } + } + + for (i = 0; i < pool->base.res_cap->num_ddc; i++) { + if (pool->base.engines[i] != NULL) + dce110_engine_destroy(&pool->base.engines[i]); + if (pool->base.hw_i2cs[i] != NULL) { + kfree(pool->base.hw_i2cs[i]); + pool->base.hw_i2cs[i] = NULL; + } + if (pool->base.sw_i2cs[i] != NULL) { + kfree(pool->base.sw_i2cs[i]); + pool->base.sw_i2cs[i] = NULL; + } + } + + for (i = 0; i < pool->base.stream_enc_count; i++) { + if (pool->base.stream_enc[i] != NULL) + kfree(DCE110STRENC_FROM_STRENC(pool->base.stream_enc[i])); + } + + for (i = 0; i < pool->base.clk_src_count; i++) { + if (pool->base.clock_sources[i] != NULL) { + dce110_clock_source_destroy(&pool->base.clock_sources[i]); + } + } + + if (pool->base.dp_clock_source != NULL) + dce110_clock_source_destroy(&pool->base.dp_clock_source); + + for (i = 0; i < pool->base.audio_count; i++) { + if (pool->base.audios[i] != NULL) { + dce_aud_destroy(&pool->base.audios[i]); + } + } + + if (pool->base.abm != NULL) + dce_abm_destroy(&pool->base.abm); + + if (pool->base.dmcu != NULL) + dce_dmcu_destroy(&pool->base.dmcu); + + if (pool->base.irqs != NULL) { + dal_irq_service_destroy(&pool->base.irqs); + } +} + + +static void get_pixel_clock_parameters( + const struct pipe_ctx *pipe_ctx, + struct pixel_clk_params *pixel_clk_params) +{ + const struct dc_stream_state *stream = pipe_ctx->stream; + + /*TODO: is this halved for YCbCr 420? in that case we might want to move + * the pixel clock normalization for hdmi up to here instead of doing it + * in pll_adjust_pix_clk + */ + pixel_clk_params->requested_pix_clk_100hz = stream->timing.pix_clk_100hz; + pixel_clk_params->encoder_object_id = stream->link->link_enc->id; + pixel_clk_params->signal_type = pipe_ctx->stream->signal; + pixel_clk_params->controller_id = pipe_ctx->stream_res.tg->inst + 1; + /* TODO: un-hardcode*/ + pixel_clk_params->requested_sym_clk = LINK_RATE_LOW * + LINK_RATE_REF_FREQ_IN_KHZ; + pixel_clk_params->flags.ENABLE_SS = 0; + pixel_clk_params->color_depth = + stream->timing.display_color_depth; + pixel_clk_params->flags.DISPLAY_BLANKED = 1; + pixel_clk_params->flags.SUPPORT_YCBCR420 = (stream->timing.pixel_encoding == + PIXEL_ENCODING_YCBCR420); + pixel_clk_params->pixel_encoding = stream->timing.pixel_encoding; + if (stream->timing.pixel_encoding == PIXEL_ENCODING_YCBCR422) { + pixel_clk_params->color_depth = COLOR_DEPTH_888; + } + if (stream->timing.pixel_encoding == PIXEL_ENCODING_YCBCR420) { + pixel_clk_params->requested_pix_clk_100hz = pixel_clk_params->requested_pix_clk_100hz / 2; + } + if (stream->timing.timing_3d_format == TIMING_3D_FORMAT_HW_FRAME_PACKING) + pixel_clk_params->requested_pix_clk_100hz *= 2; + +} + +void dce110_resource_build_pipe_hw_param(struct pipe_ctx *pipe_ctx) +{ + get_pixel_clock_parameters(pipe_ctx, &pipe_ctx->stream_res.pix_clk_params); + pipe_ctx->clock_source->funcs->get_pix_clk_dividers( + pipe_ctx->clock_source, + &pipe_ctx->stream_res.pix_clk_params, + &pipe_ctx->pll_settings); + resource_build_bit_depth_reduction_params(pipe_ctx->stream, + &pipe_ctx->stream->bit_depth_params); + pipe_ctx->stream->clamping.pixel_encoding = pipe_ctx->stream->timing.pixel_encoding; +} + +static bool is_surface_pixel_format_supported(struct pipe_ctx *pipe_ctx, unsigned int underlay_idx) +{ + if (pipe_ctx->pipe_idx != underlay_idx) + return true; + if (!pipe_ctx->plane_state) + return false; + if (pipe_ctx->plane_state->format < SURFACE_PIXEL_FORMAT_VIDEO_BEGIN) + return false; + return true; +} + +static enum dc_status build_mapped_resource( + const struct dc *dc, + struct dc_state *context, + struct dc_stream_state *stream) +{ + struct pipe_ctx *pipe_ctx = resource_get_otg_master_for_stream(&context->res_ctx, stream); + + if (!pipe_ctx) + return DC_ERROR_UNEXPECTED; + + if (!is_surface_pixel_format_supported(pipe_ctx, + dc->res_pool->underlay_pipe_index)) + return DC_SURFACE_PIXEL_FORMAT_UNSUPPORTED; + + dce110_resource_build_pipe_hw_param(pipe_ctx); + + /* TODO: validate audio ASIC caps, encoder */ + + resource_build_info_frame(pipe_ctx); + + return DC_OK; +} + +static bool dce110_validate_bandwidth( + struct dc *dc, + struct dc_state *context, + bool fast_validate) +{ + bool result = false; + + DC_LOG_BANDWIDTH_CALCS( + "%s: start", + __func__); + + if (bw_calcs( + dc->ctx, + dc->bw_dceip, + dc->bw_vbios, + context->res_ctx.pipe_ctx, + dc->res_pool->pipe_count, + &context->bw_ctx.bw.dce)) + result = true; + + if (!result) + DC_LOG_BANDWIDTH_VALIDATION("%s: %dx%d@%d Bandwidth validation failed!\n", + __func__, + context->streams[0]->timing.h_addressable, + context->streams[0]->timing.v_addressable, + context->streams[0]->timing.pix_clk_100hz / 10); + + if (memcmp(&dc->current_state->bw_ctx.bw.dce, + &context->bw_ctx.bw.dce, sizeof(context->bw_ctx.bw.dce))) { + + DC_LOG_BANDWIDTH_CALCS( + "%s: finish,\n" + "nbpMark_b: %d nbpMark_a: %d urgentMark_b: %d urgentMark_a: %d\n" + "stutMark_b: %d stutMark_a: %d\n" + "nbpMark_b: %d nbpMark_a: %d urgentMark_b: %d urgentMark_a: %d\n" + "stutMark_b: %d stutMark_a: %d\n" + "nbpMark_b: %d nbpMark_a: %d urgentMark_b: %d urgentMark_a: %d\n" + "stutMark_b: %d stutMark_a: %d stutter_mode_enable: %d\n" + "cstate: %d pstate: %d nbpstate: %d sync: %d dispclk: %d\n" + "sclk: %d sclk_sleep: %d yclk: %d blackout_recovery_time_us: %d\n" + , + __func__, + context->bw_ctx.bw.dce.nbp_state_change_wm_ns[0].b_mark, + context->bw_ctx.bw.dce.nbp_state_change_wm_ns[0].a_mark, + context->bw_ctx.bw.dce.urgent_wm_ns[0].b_mark, + context->bw_ctx.bw.dce.urgent_wm_ns[0].a_mark, + context->bw_ctx.bw.dce.stutter_exit_wm_ns[0].b_mark, + context->bw_ctx.bw.dce.stutter_exit_wm_ns[0].a_mark, + context->bw_ctx.bw.dce.nbp_state_change_wm_ns[1].b_mark, + context->bw_ctx.bw.dce.nbp_state_change_wm_ns[1].a_mark, + context->bw_ctx.bw.dce.urgent_wm_ns[1].b_mark, + context->bw_ctx.bw.dce.urgent_wm_ns[1].a_mark, + context->bw_ctx.bw.dce.stutter_exit_wm_ns[1].b_mark, + context->bw_ctx.bw.dce.stutter_exit_wm_ns[1].a_mark, + context->bw_ctx.bw.dce.nbp_state_change_wm_ns[2].b_mark, + context->bw_ctx.bw.dce.nbp_state_change_wm_ns[2].a_mark, + context->bw_ctx.bw.dce.urgent_wm_ns[2].b_mark, + context->bw_ctx.bw.dce.urgent_wm_ns[2].a_mark, + context->bw_ctx.bw.dce.stutter_exit_wm_ns[2].b_mark, + context->bw_ctx.bw.dce.stutter_exit_wm_ns[2].a_mark, + context->bw_ctx.bw.dce.stutter_mode_enable, + context->bw_ctx.bw.dce.cpuc_state_change_enable, + context->bw_ctx.bw.dce.cpup_state_change_enable, + context->bw_ctx.bw.dce.nbp_state_change_enable, + context->bw_ctx.bw.dce.all_displays_in_sync, + context->bw_ctx.bw.dce.dispclk_khz, + context->bw_ctx.bw.dce.sclk_khz, + context->bw_ctx.bw.dce.sclk_deep_sleep_khz, + context->bw_ctx.bw.dce.yclk_khz, + context->bw_ctx.bw.dce.blackout_recovery_time_us); + } + return result; +} + +static enum dc_status dce110_validate_plane(const struct dc_plane_state *plane_state, + struct dc_caps *caps) +{ + if (((plane_state->dst_rect.width * 2) < plane_state->src_rect.width) || + ((plane_state->dst_rect.height * 2) < plane_state->src_rect.height)) + return DC_FAIL_SURFACE_VALIDATE; + + return DC_OK; +} + +static bool dce110_validate_surface_sets( + struct dc_state *context) +{ + int i, j; + + for (i = 0; i < context->stream_count; i++) { + if (context->stream_status[i].plane_count == 0) + continue; + + if (context->stream_status[i].plane_count > 2) + return false; + + for (j = 0; j < context->stream_status[i].plane_count; j++) { + struct dc_plane_state *plane = + context->stream_status[i].plane_states[j]; + + /* underlay validation */ + if (plane->format >= SURFACE_PIXEL_FORMAT_VIDEO_BEGIN) { + + if ((plane->src_rect.width > 1920 || + plane->src_rect.height > 1080)) + return false; + + /* we don't have the logic to support underlay + * only yet so block the use case where we get + * NV12 plane as top layer + */ + if (j == 0) + return false; + + /* irrespective of plane format, + * stream should be RGB encoded + */ + if (context->streams[i]->timing.pixel_encoding + != PIXEL_ENCODING_RGB) + return false; + + } + + } + } + + return true; +} + +static enum dc_status dce110_validate_global( + struct dc *dc, + struct dc_state *context) +{ + if (!dce110_validate_surface_sets(context)) + return DC_FAIL_SURFACE_VALIDATE; + + return DC_OK; +} + +static enum dc_status dce110_add_stream_to_ctx( + struct dc *dc, + struct dc_state *new_ctx, + struct dc_stream_state *dc_stream) +{ + enum dc_status result = DC_ERROR_UNEXPECTED; + + result = resource_map_pool_resources(dc, new_ctx, dc_stream); + + if (result == DC_OK) + result = resource_map_clock_resources(dc, new_ctx, dc_stream); + + + if (result == DC_OK) + result = build_mapped_resource(dc, new_ctx, dc_stream); + + return result; +} + +static struct pipe_ctx *dce110_acquire_underlay( + const struct dc_state *cur_ctx, + struct dc_state *new_ctx, + const struct resource_pool *pool, + const struct pipe_ctx *opp_head_pipe) +{ + struct dc_stream_state *stream = opp_head_pipe->stream; + struct dc *dc = stream->ctx->dc; + struct dce_hwseq *hws = dc->hwseq; + struct resource_context *res_ctx = &new_ctx->res_ctx; + unsigned int underlay_idx = pool->underlay_pipe_index; + struct pipe_ctx *pipe_ctx = &res_ctx->pipe_ctx[underlay_idx]; + + if (res_ctx->pipe_ctx[underlay_idx].stream) + return NULL; + + pipe_ctx->stream_res.tg = pool->timing_generators[underlay_idx]; + pipe_ctx->plane_res.mi = pool->mis[underlay_idx]; + /*pipe_ctx->plane_res.ipp = res_ctx->pool->ipps[underlay_idx];*/ + pipe_ctx->plane_res.xfm = pool->transforms[underlay_idx]; + pipe_ctx->stream_res.opp = pool->opps[underlay_idx]; + pipe_ctx->pipe_idx = underlay_idx; + + pipe_ctx->stream = stream; + + if (!dc->current_state->res_ctx.pipe_ctx[underlay_idx].stream) { + struct tg_color black_color = {0}; + struct dc_bios *dcb = dc->ctx->dc_bios; + + hws->funcs.enable_display_power_gating( + dc, + pipe_ctx->stream_res.tg->inst, + dcb, PIPE_GATING_CONTROL_DISABLE); + + /* + * This is for powering on underlay, so crtc does not + * need to be enabled + */ + + pipe_ctx->stream_res.tg->funcs->program_timing(pipe_ctx->stream_res.tg, + &stream->timing, + 0, + 0, + 0, + 0, + pipe_ctx->stream->signal, + false); + + pipe_ctx->stream_res.tg->funcs->enable_advanced_request( + pipe_ctx->stream_res.tg, + true, + &stream->timing); + + pipe_ctx->plane_res.mi->funcs->allocate_mem_input(pipe_ctx->plane_res.mi, + stream->timing.h_total, + stream->timing.v_total, + stream->timing.pix_clk_100hz / 10, + new_ctx->stream_count); + + color_space_to_black_color(dc, + COLOR_SPACE_YCBCR601, &black_color); + pipe_ctx->stream_res.tg->funcs->set_blank_color( + pipe_ctx->stream_res.tg, + &black_color); + } + + return pipe_ctx; +} + +static void dce110_destroy_resource_pool(struct resource_pool **pool) +{ + struct dce110_resource_pool *dce110_pool = TO_DCE110_RES_POOL(*pool); + + dce110_resource_destruct(dce110_pool); + kfree(dce110_pool); + *pool = NULL; +} + +struct stream_encoder *dce110_find_first_free_match_stream_enc_for_link( + struct resource_context *res_ctx, + const struct resource_pool *pool, + struct dc_stream_state *stream) +{ + int i; + int j = -1; + struct dc_link *link = stream->link; + + for (i = 0; i < pool->stream_enc_count; i++) { + if (!res_ctx->is_stream_enc_acquired[i] && + pool->stream_enc[i]) { + /* Store first available for MST second display + * in daisy chain use case + */ + j = i; + if (pool->stream_enc[i]->id == + link->link_enc->preferred_engine) + return pool->stream_enc[i]; + } + } + + /* + * For CZ and later, we can allow DIG FE and BE to differ for all display types + */ + + if (j >= 0) + return pool->stream_enc[j]; + + return NULL; +} + + +static const struct resource_funcs dce110_res_pool_funcs = { + .destroy = dce110_destroy_resource_pool, + .link_enc_create = dce110_link_encoder_create, + .panel_cntl_create = dce110_panel_cntl_create, + .validate_bandwidth = dce110_validate_bandwidth, + .validate_plane = dce110_validate_plane, + .acquire_free_pipe_as_secondary_dpp_pipe = dce110_acquire_underlay, + .add_stream_to_ctx = dce110_add_stream_to_ctx, + .validate_global = dce110_validate_global, + .find_first_free_match_stream_enc_for_link = dce110_find_first_free_match_stream_enc_for_link +}; + +static bool underlay_create(struct dc_context *ctx, struct resource_pool *pool) +{ + struct dce110_timing_generator *dce110_tgv = kzalloc(sizeof(*dce110_tgv), + GFP_KERNEL); + struct dce_transform *dce110_xfmv = kzalloc(sizeof(*dce110_xfmv), + GFP_KERNEL); + struct dce_mem_input *dce110_miv = kzalloc(sizeof(*dce110_miv), + GFP_KERNEL); + struct dce110_opp *dce110_oppv = kzalloc(sizeof(*dce110_oppv), + GFP_KERNEL); + + if (!dce110_tgv || !dce110_xfmv || !dce110_miv || !dce110_oppv) { + kfree(dce110_tgv); + kfree(dce110_xfmv); + kfree(dce110_miv); + kfree(dce110_oppv); + return false; + } + + dce110_opp_v_construct(dce110_oppv, ctx); + + dce110_timing_generator_v_construct(dce110_tgv, ctx); + dce110_mem_input_v_construct(dce110_miv, ctx); + dce110_transform_v_construct(dce110_xfmv, ctx); + + pool->opps[pool->pipe_count] = &dce110_oppv->base; + pool->timing_generators[pool->pipe_count] = &dce110_tgv->base; + pool->mis[pool->pipe_count] = &dce110_miv->base; + pool->transforms[pool->pipe_count] = &dce110_xfmv->base; + pool->pipe_count++; + + /* update the public caps to indicate an underlay is available */ + ctx->dc->caps.max_slave_planes = 1; + ctx->dc->caps.max_slave_yuv_planes = 1; + ctx->dc->caps.max_slave_rgb_planes = 0; + + return true; +} + +static void bw_calcs_data_update_from_pplib(struct dc *dc) +{ + struct dm_pp_clock_levels clks = {0}; + + /*do system clock*/ + dm_pp_get_clock_levels_by_type( + dc->ctx, + DM_PP_CLOCK_TYPE_ENGINE_CLK, + &clks); + /* convert all the clock fro kHz to fix point mHz */ + dc->bw_vbios->high_sclk = bw_frc_to_fixed( + clks.clocks_in_khz[clks.num_levels-1], 1000); + dc->bw_vbios->mid1_sclk = bw_frc_to_fixed( + clks.clocks_in_khz[clks.num_levels/8], 1000); + dc->bw_vbios->mid2_sclk = bw_frc_to_fixed( + clks.clocks_in_khz[clks.num_levels*2/8], 1000); + dc->bw_vbios->mid3_sclk = bw_frc_to_fixed( + clks.clocks_in_khz[clks.num_levels*3/8], 1000); + dc->bw_vbios->mid4_sclk = bw_frc_to_fixed( + clks.clocks_in_khz[clks.num_levels*4/8], 1000); + dc->bw_vbios->mid5_sclk = bw_frc_to_fixed( + clks.clocks_in_khz[clks.num_levels*5/8], 1000); + dc->bw_vbios->mid6_sclk = bw_frc_to_fixed( + clks.clocks_in_khz[clks.num_levels*6/8], 1000); + dc->bw_vbios->low_sclk = bw_frc_to_fixed( + clks.clocks_in_khz[0], 1000); + dc->sclk_lvls = clks; + + /*do display clock*/ + dm_pp_get_clock_levels_by_type( + dc->ctx, + DM_PP_CLOCK_TYPE_DISPLAY_CLK, + &clks); + dc->bw_vbios->high_voltage_max_dispclk = bw_frc_to_fixed( + clks.clocks_in_khz[clks.num_levels-1], 1000); + dc->bw_vbios->mid_voltage_max_dispclk = bw_frc_to_fixed( + clks.clocks_in_khz[clks.num_levels>>1], 1000); + dc->bw_vbios->low_voltage_max_dispclk = bw_frc_to_fixed( + clks.clocks_in_khz[0], 1000); + + /*do memory clock*/ + dm_pp_get_clock_levels_by_type( + dc->ctx, + DM_PP_CLOCK_TYPE_MEMORY_CLK, + &clks); + + dc->bw_vbios->low_yclk = bw_frc_to_fixed( + clks.clocks_in_khz[0] * MEMORY_TYPE_MULTIPLIER_CZ, 1000); + dc->bw_vbios->mid_yclk = bw_frc_to_fixed( + clks.clocks_in_khz[clks.num_levels>>1] * MEMORY_TYPE_MULTIPLIER_CZ, + 1000); + dc->bw_vbios->high_yclk = bw_frc_to_fixed( + clks.clocks_in_khz[clks.num_levels-1] * MEMORY_TYPE_MULTIPLIER_CZ, + 1000); +} + +static const struct resource_caps *dce110_resource_cap( + struct hw_asic_id *asic_id) +{ + if (ASIC_REV_IS_STONEY(asic_id->hw_internal_rev)) + return &stoney_resource_cap; + else + return &carrizo_resource_cap; +} + +static bool dce110_resource_construct( + uint8_t num_virtual_links, + struct dc *dc, + struct dce110_resource_pool *pool, + struct hw_asic_id asic_id) +{ + unsigned int i; + struct dc_context *ctx = dc->ctx; + struct dc_bios *bp; + + ctx->dc_bios->regs = &bios_regs; + + pool->base.res_cap = dce110_resource_cap(&ctx->asic_id); + pool->base.funcs = &dce110_res_pool_funcs; + + /************************************************* + * Resource + asic cap harcoding * + *************************************************/ + + pool->base.pipe_count = pool->base.res_cap->num_timing_generator; + pool->base.underlay_pipe_index = pool->base.pipe_count; + pool->base.timing_generator_count = pool->base.res_cap->num_timing_generator; + dc->caps.max_downscale_ratio = 150; + dc->caps.i2c_speed_in_khz = 40; + dc->caps.i2c_speed_in_khz_hdcp = 40; + dc->caps.max_cursor_size = 128; + dc->caps.min_horizontal_blanking_period = 80; + dc->caps.is_apu = true; + dc->caps.extended_aux_timeout_support = false; + dc->debug = debug_defaults; + + /************************************************* + * Create resources * + *************************************************/ + + bp = ctx->dc_bios; + + if (bp->fw_info_valid && bp->fw_info.external_clock_source_frequency_for_dp != 0) { + pool->base.dp_clock_source = + dce110_clock_source_create(ctx, bp, CLOCK_SOURCE_ID_EXTERNAL, NULL, true); + + pool->base.clock_sources[0] = + dce110_clock_source_create(ctx, bp, CLOCK_SOURCE_ID_PLL0, + &clk_src_regs[0], false); + pool->base.clock_sources[1] = + dce110_clock_source_create(ctx, bp, CLOCK_SOURCE_ID_PLL1, + &clk_src_regs[1], false); + + pool->base.clk_src_count = 2; + + /* TODO: find out if CZ support 3 PLLs */ + } + + if (pool->base.dp_clock_source == NULL) { + dm_error("DC: failed to create dp clock source!\n"); + BREAK_TO_DEBUGGER(); + goto res_create_fail; + } + + for (i = 0; i < pool->base.clk_src_count; i++) { + if (pool->base.clock_sources[i] == NULL) { + dm_error("DC: failed to create clock sources!\n"); + BREAK_TO_DEBUGGER(); + goto res_create_fail; + } + } + + pool->base.dmcu = dce_dmcu_create(ctx, + &dmcu_regs, + &dmcu_shift, + &dmcu_mask); + if (pool->base.dmcu == NULL) { + dm_error("DC: failed to create dmcu!\n"); + BREAK_TO_DEBUGGER(); + goto res_create_fail; + } + + pool->base.abm = dce_abm_create(ctx, + &abm_regs, + &abm_shift, + &abm_mask); + if (pool->base.abm == NULL) { + dm_error("DC: failed to create abm!\n"); + BREAK_TO_DEBUGGER(); + goto res_create_fail; + } + + { + struct irq_service_init_data init_data; + init_data.ctx = dc->ctx; + pool->base.irqs = dal_irq_service_dce110_create(&init_data); + if (!pool->base.irqs) + goto res_create_fail; + } + + for (i = 0; i < pool->base.pipe_count; i++) { + pool->base.timing_generators[i] = dce110_timing_generator_create( + ctx, i, &dce110_tg_offsets[i]); + if (pool->base.timing_generators[i] == NULL) { + BREAK_TO_DEBUGGER(); + dm_error("DC: failed to create tg!\n"); + goto res_create_fail; + } + + pool->base.mis[i] = dce110_mem_input_create(ctx, i); + if (pool->base.mis[i] == NULL) { + BREAK_TO_DEBUGGER(); + dm_error( + "DC: failed to create memory input!\n"); + goto res_create_fail; + } + + pool->base.ipps[i] = dce110_ipp_create(ctx, i); + if (pool->base.ipps[i] == NULL) { + BREAK_TO_DEBUGGER(); + dm_error( + "DC: failed to create input pixel processor!\n"); + goto res_create_fail; + } + + pool->base.transforms[i] = dce110_transform_create(ctx, i); + if (pool->base.transforms[i] == NULL) { + BREAK_TO_DEBUGGER(); + dm_error( + "DC: failed to create transform!\n"); + goto res_create_fail; + } + + pool->base.opps[i] = dce110_opp_create(ctx, i); + if (pool->base.opps[i] == NULL) { + BREAK_TO_DEBUGGER(); + dm_error( + "DC: failed to create output pixel processor!\n"); + goto res_create_fail; + } + } + + for (i = 0; i < pool->base.res_cap->num_ddc; i++) { + pool->base.engines[i] = dce110_aux_engine_create(ctx, i); + if (pool->base.engines[i] == NULL) { + BREAK_TO_DEBUGGER(); + dm_error( + "DC:failed to create aux engine!!\n"); + goto res_create_fail; + } + pool->base.hw_i2cs[i] = dce110_i2c_hw_create(ctx, i); + if (pool->base.hw_i2cs[i] == NULL) { + BREAK_TO_DEBUGGER(); + dm_error( + "DC:failed to create i2c engine!!\n"); + goto res_create_fail; + } + pool->base.sw_i2cs[i] = NULL; + } + + if (dc->config.fbc_support) + dc->fbc_compressor = dce110_compressor_create(ctx); + + if (!underlay_create(ctx, &pool->base)) + goto res_create_fail; + + if (!resource_construct(num_virtual_links, dc, &pool->base, + &res_create_funcs)) + goto res_create_fail; + + /* Create hardware sequencer */ + dce110_hw_sequencer_construct(dc); + + dc->caps.max_planes = pool->base.pipe_count; + + for (i = 0; i < pool->base.underlay_pipe_index; ++i) + dc->caps.planes[i] = plane_cap; + + dc->caps.planes[pool->base.underlay_pipe_index] = underlay_plane_cap; + + bw_calcs_init(dc->bw_dceip, dc->bw_vbios, dc->ctx->asic_id); + + bw_calcs_data_update_from_pplib(dc); + + return true; + +res_create_fail: + dce110_resource_destruct(pool); + return false; +} + +struct resource_pool *dce110_create_resource_pool( + uint8_t num_virtual_links, + struct dc *dc, + struct hw_asic_id asic_id) +{ + struct dce110_resource_pool *pool = + kzalloc(sizeof(struct dce110_resource_pool), GFP_KERNEL); + + if (!pool) + return NULL; + + if (dce110_resource_construct(num_virtual_links, dc, pool, asic_id)) + return &pool->base; + + kfree(pool); + BREAK_TO_DEBUGGER(); + return NULL; +} diff --git a/drivers/gpu/drm/amd/display/dc/resource/dce110/dce110_resource.h b/drivers/gpu/drm/amd/display/dc/resource/dce110/dce110_resource.h new file mode 100644 index 000000000000..aa4531e0800e --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/resource/dce110/dce110_resource.h @@ -0,0 +1,54 @@ +/* +* Copyright 2012-15 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_RESOURCE_DCE110_H__ +#define __DC_RESOURCE_DCE110_H__ + +#include "core_types.h" + +struct dc; +struct resource_pool; + +#define TO_DCE110_RES_POOL(pool)\ + container_of(pool, struct dce110_resource_pool, base) + +struct dce110_resource_pool { + struct resource_pool base; +}; + +void dce110_resource_build_pipe_hw_param(struct pipe_ctx *pipe_ctx); + +struct resource_pool *dce110_create_resource_pool( + uint8_t num_virtual_links, + struct dc *dc, + struct hw_asic_id asic_id); + +struct stream_encoder *dce110_find_first_free_match_stream_enc_for_link( + struct resource_context *res_ctx, + const struct resource_pool *pool, + struct dc_stream_state *stream); + +#endif /* __DC_RESOURCE_DCE110_H__ */ + diff --git a/drivers/gpu/drm/amd/display/dc/resource/dce112/dce112_resource.c b/drivers/gpu/drm/amd/display/dc/resource/dce112/dce112_resource.c new file mode 100644 index 000000000000..d1edac46c9a0 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/resource/dce112/dce112_resource.c @@ -0,0 +1,1431 @@ +/* +* Copyright 2012-15 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 "dm_services.h" + +#include "link_encoder.h" +#include "stream_encoder.h" + +#include "resource.h" +#include "include/irq_service_interface.h" +#include "dce110/dce110_resource.h" +#include "dce110/dce110_timing_generator.h" + +#include "irq/dce110/irq_service_dce110.h" +#include "dce/dce_mem_input.h" +#include "dce/dce_transform.h" +#include "dce/dce_link_encoder.h" +#include "dce/dce_stream_encoder.h" +#include "dce/dce_audio.h" +#include "dce/dce_opp.h" +#include "dce/dce_ipp.h" +#include "dce/dce_clock_source.h" + +#include "dce/dce_hwseq.h" +#include "dce112/dce112_hwseq.h" +#include "dce/dce_abm.h" +#include "dce/dce_dmcu.h" +#include "dce/dce_aux.h" +#include "dce/dce_i2c.h" +#include "dce/dce_panel_cntl.h" + +#include "reg_helper.h" + +#include "dce/dce_11_2_d.h" +#include "dce/dce_11_2_sh_mask.h" + +#include "dce100/dce100_resource.h" +#include "dce112_resource.h" + +#define DC_LOGGER \ + dc->ctx->logger + +#ifndef mmDP_DPHY_INTERNAL_CTRL + #define mmDP_DPHY_INTERNAL_CTRL 0x4aa7 + #define mmDP0_DP_DPHY_INTERNAL_CTRL 0x4aa7 + #define mmDP1_DP_DPHY_INTERNAL_CTRL 0x4ba7 + #define mmDP2_DP_DPHY_INTERNAL_CTRL 0x4ca7 + #define mmDP3_DP_DPHY_INTERNAL_CTRL 0x4da7 + #define mmDP4_DP_DPHY_INTERNAL_CTRL 0x4ea7 + #define mmDP5_DP_DPHY_INTERNAL_CTRL 0x4fa7 + #define mmDP6_DP_DPHY_INTERNAL_CTRL 0x54a7 + #define mmDP7_DP_DPHY_INTERNAL_CTRL 0x56a7 + #define mmDP8_DP_DPHY_INTERNAL_CTRL 0x57a7 +#endif + +#ifndef mmBIOS_SCRATCH_2 + #define mmBIOS_SCRATCH_2 0x05CB + #define mmBIOS_SCRATCH_3 0x05CC + #define mmBIOS_SCRATCH_6 0x05CF +#endif + +#ifndef mmDP_DPHY_BS_SR_SWAP_CNTL + #define mmDP_DPHY_BS_SR_SWAP_CNTL 0x4ADC + #define mmDP0_DP_DPHY_BS_SR_SWAP_CNTL 0x4ADC + #define mmDP1_DP_DPHY_BS_SR_SWAP_CNTL 0x4BDC + #define mmDP2_DP_DPHY_BS_SR_SWAP_CNTL 0x4CDC + #define mmDP3_DP_DPHY_BS_SR_SWAP_CNTL 0x4DDC + #define mmDP4_DP_DPHY_BS_SR_SWAP_CNTL 0x4EDC + #define mmDP5_DP_DPHY_BS_SR_SWAP_CNTL 0x4FDC + #define mmDP6_DP_DPHY_BS_SR_SWAP_CNTL 0x54DC +#endif + +#ifndef mmDP_DPHY_FAST_TRAINING + #define mmDP_DPHY_FAST_TRAINING 0x4ABC + #define mmDP0_DP_DPHY_FAST_TRAINING 0x4ABC + #define mmDP1_DP_DPHY_FAST_TRAINING 0x4BBC + #define mmDP2_DP_DPHY_FAST_TRAINING 0x4CBC + #define mmDP3_DP_DPHY_FAST_TRAINING 0x4DBC + #define mmDP4_DP_DPHY_FAST_TRAINING 0x4EBC + #define mmDP5_DP_DPHY_FAST_TRAINING 0x4FBC + #define mmDP6_DP_DPHY_FAST_TRAINING 0x54BC +#endif + +enum dce112_clk_src_array_id { + DCE112_CLK_SRC_PLL0, + DCE112_CLK_SRC_PLL1, + DCE112_CLK_SRC_PLL2, + DCE112_CLK_SRC_PLL3, + DCE112_CLK_SRC_PLL4, + DCE112_CLK_SRC_PLL5, + + DCE112_CLK_SRC_TOTAL +}; + +static const struct dce110_timing_generator_offsets dce112_tg_offsets[] = { + { + .crtc = (mmCRTC0_CRTC_CONTROL - mmCRTC_CONTROL), + .dcp = (mmDCP0_GRPH_CONTROL - mmGRPH_CONTROL), + }, + { + .crtc = (mmCRTC1_CRTC_CONTROL - mmCRTC_CONTROL), + .dcp = (mmDCP1_GRPH_CONTROL - mmGRPH_CONTROL), + }, + { + .crtc = (mmCRTC2_CRTC_CONTROL - mmCRTC_CONTROL), + .dcp = (mmDCP2_GRPH_CONTROL - mmGRPH_CONTROL), + }, + { + .crtc = (mmCRTC3_CRTC_CONTROL - mmCRTC_CONTROL), + .dcp = (mmDCP3_GRPH_CONTROL - mmGRPH_CONTROL), + }, + { + .crtc = (mmCRTC4_CRTC_CONTROL - mmCRTC_CONTROL), + .dcp = (mmDCP4_GRPH_CONTROL - mmGRPH_CONTROL), + }, + { + .crtc = (mmCRTC5_CRTC_CONTROL - mmCRTC_CONTROL), + .dcp = (mmDCP5_GRPH_CONTROL - mmGRPH_CONTROL), + } +}; + +/* set register offset */ +#define SR(reg_name)\ + .reg_name = mm ## reg_name + +/* set register offset with instance */ +#define SRI(reg_name, block, id)\ + .reg_name = mm ## block ## id ## _ ## reg_name + +static const struct dce_dmcu_registers dmcu_regs = { + DMCU_DCE110_COMMON_REG_LIST() +}; + +static const struct dce_dmcu_shift dmcu_shift = { + DMCU_MASK_SH_LIST_DCE110(__SHIFT) +}; + +static const struct dce_dmcu_mask dmcu_mask = { + DMCU_MASK_SH_LIST_DCE110(_MASK) +}; + +static const struct dce_abm_registers abm_regs = { + ABM_DCE110_COMMON_REG_LIST() +}; + +static const struct dce_abm_shift abm_shift = { + ABM_MASK_SH_LIST_DCE110(__SHIFT) +}; + +static const struct dce_abm_mask abm_mask = { + ABM_MASK_SH_LIST_DCE110(_MASK) +}; + +static const struct dce110_aux_registers_shift aux_shift = { + DCE_AUX_MASK_SH_LIST(__SHIFT) +}; + +static const struct dce110_aux_registers_mask aux_mask = { + DCE_AUX_MASK_SH_LIST(_MASK) +}; + +#define ipp_regs(id)\ +[id] = {\ + IPP_DCE110_REG_LIST_DCE_BASE(id)\ +} + +static const struct dce_ipp_registers ipp_regs[] = { + ipp_regs(0), + ipp_regs(1), + ipp_regs(2), + ipp_regs(3), + ipp_regs(4), + ipp_regs(5) +}; + +static const struct dce_ipp_shift ipp_shift = { + IPP_DCE100_MASK_SH_LIST_DCE_COMMON_BASE(__SHIFT) +}; + +static const struct dce_ipp_mask ipp_mask = { + IPP_DCE100_MASK_SH_LIST_DCE_COMMON_BASE(_MASK) +}; + +#define transform_regs(id)\ +[id] = {\ + XFM_COMMON_REG_LIST_DCE110(id)\ +} + +static const struct dce_transform_registers xfm_regs[] = { + transform_regs(0), + transform_regs(1), + transform_regs(2), + transform_regs(3), + transform_regs(4), + transform_regs(5) +}; + +static const struct dce_transform_shift xfm_shift = { + XFM_COMMON_MASK_SH_LIST_DCE110(__SHIFT) +}; + +static const struct dce_transform_mask xfm_mask = { + XFM_COMMON_MASK_SH_LIST_DCE110(_MASK) +}; + +#define aux_regs(id)\ +[id] = {\ + AUX_REG_LIST(id)\ +} + +static const struct dce110_link_enc_aux_registers link_enc_aux_regs[] = { + aux_regs(0), + aux_regs(1), + aux_regs(2), + aux_regs(3), + aux_regs(4), + aux_regs(5) +}; + +static const struct dce_panel_cntl_registers panel_cntl_regs[] = { + { DCE_PANEL_CNTL_REG_LIST() } +}; + +static const struct dce_panel_cntl_shift panel_cntl_shift = { + DCE_PANEL_CNTL_MASK_SH_LIST(__SHIFT) +}; + +static const struct dce_panel_cntl_mask panel_cntl_mask = { + DCE_PANEL_CNTL_MASK_SH_LIST(_MASK) +}; + +#define hpd_regs(id)\ +[id] = {\ + HPD_REG_LIST(id)\ +} + +static const struct dce110_link_enc_hpd_registers link_enc_hpd_regs[] = { + hpd_regs(0), + hpd_regs(1), + hpd_regs(2), + hpd_regs(3), + hpd_regs(4), + hpd_regs(5) +}; + +#define link_regs(id)\ +[id] = {\ + LE_DCE110_REG_LIST(id)\ +} + +static const struct dce110_link_enc_registers link_enc_regs[] = { + link_regs(0), + link_regs(1), + link_regs(2), + link_regs(3), + link_regs(4), + link_regs(5), + link_regs(6), +}; + +#define stream_enc_regs(id)\ +[id] = {\ + SE_COMMON_REG_LIST(id),\ + .TMDS_CNTL = 0,\ +} + +static const struct dce110_stream_enc_registers stream_enc_regs[] = { + stream_enc_regs(0), + stream_enc_regs(1), + stream_enc_regs(2), + stream_enc_regs(3), + stream_enc_regs(4), + stream_enc_regs(5) +}; + +static const struct dce_stream_encoder_shift se_shift = { + SE_COMMON_MASK_SH_LIST_DCE112(__SHIFT) +}; + +static const struct dce_stream_encoder_mask se_mask = { + SE_COMMON_MASK_SH_LIST_DCE112(_MASK) +}; + +#define opp_regs(id)\ +[id] = {\ + OPP_DCE_112_REG_LIST(id),\ +} + +static const struct dce_opp_registers opp_regs[] = { + opp_regs(0), + opp_regs(1), + opp_regs(2), + opp_regs(3), + opp_regs(4), + opp_regs(5) +}; + +static const struct dce_opp_shift opp_shift = { + OPP_COMMON_MASK_SH_LIST_DCE_112(__SHIFT) +}; + +static const struct dce_opp_mask opp_mask = { + OPP_COMMON_MASK_SH_LIST_DCE_112(_MASK) +}; + +#define aux_engine_regs(id)\ +[id] = {\ + AUX_COMMON_REG_LIST(id), \ + .AUX_RESET_MASK = 0 \ +} + +static const struct dce110_aux_registers aux_engine_regs[] = { + aux_engine_regs(0), + aux_engine_regs(1), + aux_engine_regs(2), + aux_engine_regs(3), + aux_engine_regs(4), + aux_engine_regs(5) +}; + +#define audio_regs(id)\ +[id] = {\ + AUD_COMMON_REG_LIST(id)\ +} + +static const struct dce_audio_registers audio_regs[] = { + audio_regs(0), + audio_regs(1), + audio_regs(2), + audio_regs(3), + audio_regs(4), + audio_regs(5) +}; + +static const struct dce_audio_shift audio_shift = { + AUD_COMMON_MASK_SH_LIST(__SHIFT) +}; + +static const struct dce_audio_mask audio_mask = { + AUD_COMMON_MASK_SH_LIST(_MASK) +}; + +#define clk_src_regs(index, id)\ +[index] = {\ + CS_COMMON_REG_LIST_DCE_112(id),\ +} + +static const struct dce110_clk_src_regs clk_src_regs[] = { + clk_src_regs(0, A), + clk_src_regs(1, B), + clk_src_regs(2, C), + clk_src_regs(3, D), + clk_src_regs(4, E), + clk_src_regs(5, F) +}; + +static const struct dce110_clk_src_shift cs_shift = { + CS_COMMON_MASK_SH_LIST_DCE_112(__SHIFT) +}; + +static const struct dce110_clk_src_mask cs_mask = { + CS_COMMON_MASK_SH_LIST_DCE_112(_MASK) +}; + +static const struct bios_registers bios_regs = { + .BIOS_SCRATCH_3 = mmBIOS_SCRATCH_3, + .BIOS_SCRATCH_6 = mmBIOS_SCRATCH_6 +}; + +static const struct resource_caps polaris_10_resource_cap = { + .num_timing_generator = 6, + .num_audio = 6, + .num_stream_encoder = 6, + .num_pll = 8, /* why 8? 6 combo PHY PLL + 2 regular PLLs? */ + .num_ddc = 6, +}; + +static const struct resource_caps polaris_11_resource_cap = { + .num_timing_generator = 5, + .num_audio = 5, + .num_stream_encoder = 5, + .num_pll = 8, /* why 8? 6 combo PHY PLL + 2 regular PLLs? */ + .num_ddc = 5, +}; + +static const struct dc_plane_cap plane_cap = { + .type = DC_PLANE_TYPE_DCE_RGB, + + .pixel_format_support = { + .argb8888 = true, + .nv12 = false, + .fp16 = true + }, + + .max_upscale_factor = { + .argb8888 = 16000, + .nv12 = 1, + .fp16 = 1 + }, + + .max_downscale_factor = { + .argb8888 = 250, + .nv12 = 1, + .fp16 = 1 + }, + 64, + 64 +}; + +static const struct dc_debug_options debug_defaults = { + .enable_legacy_fast_update = true, +}; + +#define CTX ctx +#define REG(reg) mm ## reg + +#ifndef mmCC_DC_HDMI_STRAPS +#define mmCC_DC_HDMI_STRAPS 0x4819 +#define CC_DC_HDMI_STRAPS__HDMI_DISABLE_MASK 0x40 +#define CC_DC_HDMI_STRAPS__HDMI_DISABLE__SHIFT 0x6 +#define CC_DC_HDMI_STRAPS__AUDIO_STREAM_NUMBER_MASK 0x700 +#define CC_DC_HDMI_STRAPS__AUDIO_STREAM_NUMBER__SHIFT 0x8 +#endif + +static int map_transmitter_id_to_phy_instance( + enum transmitter transmitter) +{ + switch (transmitter) { + case TRANSMITTER_UNIPHY_A: + return 0; + case TRANSMITTER_UNIPHY_B: + return 1; + case TRANSMITTER_UNIPHY_C: + return 2; + case TRANSMITTER_UNIPHY_D: + return 3; + case TRANSMITTER_UNIPHY_E: + return 4; + case TRANSMITTER_UNIPHY_F: + return 5; + case TRANSMITTER_UNIPHY_G: + return 6; + default: + ASSERT(0); + return 0; + } +} + +static void read_dce_straps( + struct dc_context *ctx, + struct resource_straps *straps) +{ + REG_GET_2(CC_DC_HDMI_STRAPS, + HDMI_DISABLE, &straps->hdmi_disable, + AUDIO_STREAM_NUMBER, &straps->audio_stream_number); + + REG_GET(DC_PINSTRAPS, DC_PINSTRAPS_AUDIO, &straps->dc_pinstraps_audio); +} + +static struct audio *create_audio( + struct dc_context *ctx, unsigned int inst) +{ + return dce_audio_create(ctx, inst, + &audio_regs[inst], &audio_shift, &audio_mask); +} + + +static struct timing_generator *dce112_timing_generator_create( + struct dc_context *ctx, + uint32_t instance, + const struct dce110_timing_generator_offsets *offsets) +{ + struct dce110_timing_generator *tg110 = + kzalloc(sizeof(struct dce110_timing_generator), GFP_KERNEL); + + if (!tg110) + return NULL; + + dce110_timing_generator_construct(tg110, ctx, instance, offsets); + return &tg110->base; +} + +static struct stream_encoder *dce112_stream_encoder_create( + enum engine_id eng_id, + struct dc_context *ctx) +{ + struct dce110_stream_encoder *enc110 = + kzalloc(sizeof(struct dce110_stream_encoder), GFP_KERNEL); + + if (!enc110) + return NULL; + + dce110_stream_encoder_construct(enc110, ctx, ctx->dc_bios, eng_id, + &stream_enc_regs[eng_id], + &se_shift, &se_mask); + return &enc110->base; +} + +#define SRII(reg_name, block, id)\ + .reg_name[id] = mm ## block ## id ## _ ## reg_name + +static const struct dce_hwseq_registers hwseq_reg = { + HWSEQ_DCE112_REG_LIST() +}; + +static const struct dce_hwseq_shift hwseq_shift = { + HWSEQ_DCE112_MASK_SH_LIST(__SHIFT) +}; + +static const struct dce_hwseq_mask hwseq_mask = { + HWSEQ_DCE112_MASK_SH_LIST(_MASK) +}; + +static struct dce_hwseq *dce112_hwseq_create( + struct dc_context *ctx) +{ + struct dce_hwseq *hws = kzalloc(sizeof(struct dce_hwseq), GFP_KERNEL); + + if (hws) { + hws->ctx = ctx; + hws->regs = &hwseq_reg; + hws->shifts = &hwseq_shift; + hws->masks = &hwseq_mask; + } + return hws; +} + +static const struct resource_create_funcs res_create_funcs = { + .read_dce_straps = read_dce_straps, + .create_audio = create_audio, + .create_stream_encoder = dce112_stream_encoder_create, + .create_hwseq = dce112_hwseq_create, +}; + +#define mi_inst_regs(id) { MI_DCE11_2_REG_LIST(id) } +static const struct dce_mem_input_registers mi_regs[] = { + mi_inst_regs(0), + mi_inst_regs(1), + mi_inst_regs(2), + mi_inst_regs(3), + mi_inst_regs(4), + mi_inst_regs(5), +}; + +static const struct dce_mem_input_shift mi_shifts = { + MI_DCE11_2_MASK_SH_LIST(__SHIFT) +}; + +static const struct dce_mem_input_mask mi_masks = { + MI_DCE11_2_MASK_SH_LIST(_MASK) +}; + +static struct mem_input *dce112_mem_input_create( + struct dc_context *ctx, + uint32_t inst) +{ + struct dce_mem_input *dce_mi = kzalloc(sizeof(struct dce_mem_input), + GFP_KERNEL); + + if (!dce_mi) { + BREAK_TO_DEBUGGER(); + return NULL; + } + + dce112_mem_input_construct(dce_mi, ctx, inst, &mi_regs[inst], &mi_shifts, &mi_masks); + return &dce_mi->base; +} + +static void dce112_transform_destroy(struct transform **xfm) +{ + kfree(TO_DCE_TRANSFORM(*xfm)); + *xfm = NULL; +} + +static struct transform *dce112_transform_create( + struct dc_context *ctx, + uint32_t inst) +{ + struct dce_transform *transform = + kzalloc(sizeof(struct dce_transform), GFP_KERNEL); + + if (!transform) + return NULL; + + dce_transform_construct(transform, ctx, inst, + &xfm_regs[inst], &xfm_shift, &xfm_mask); + transform->lb_memory_size = 0x1404; /*5124*/ + return &transform->base; +} + +static const struct encoder_feature_support link_enc_feature = { + .max_hdmi_deep_color = COLOR_DEPTH_121212, + .max_hdmi_pixel_clock = 600000, + .hdmi_ycbcr420_supported = true, + .dp_ycbcr420_supported = false, + .flags.bits.IS_HBR2_CAPABLE = true, + .flags.bits.IS_HBR3_CAPABLE = true, + .flags.bits.IS_TPS3_CAPABLE = true, + .flags.bits.IS_TPS4_CAPABLE = true +}; + +static struct link_encoder *dce112_link_encoder_create( + struct dc_context *ctx, + const struct encoder_init_data *enc_init_data) +{ + struct dce110_link_encoder *enc110 = + kzalloc(sizeof(struct dce110_link_encoder), GFP_KERNEL); + int link_regs_id; + + if (!enc110) + return NULL; + + link_regs_id = + map_transmitter_id_to_phy_instance(enc_init_data->transmitter); + + dce110_link_encoder_construct(enc110, + enc_init_data, + &link_enc_feature, + &link_enc_regs[link_regs_id], + &link_enc_aux_regs[enc_init_data->channel - 1], + &link_enc_hpd_regs[enc_init_data->hpd_source]); + return &enc110->base; +} + +static struct panel_cntl *dce112_panel_cntl_create(const struct panel_cntl_init_data *init_data) +{ + struct dce_panel_cntl *panel_cntl = + kzalloc(sizeof(struct dce_panel_cntl), GFP_KERNEL); + + if (!panel_cntl) + return NULL; + + dce_panel_cntl_construct(panel_cntl, + init_data, + &panel_cntl_regs[init_data->inst], + &panel_cntl_shift, + &panel_cntl_mask); + + return &panel_cntl->base; +} + +static struct input_pixel_processor *dce112_ipp_create( + struct dc_context *ctx, uint32_t inst) +{ + struct dce_ipp *ipp = kzalloc(sizeof(struct dce_ipp), GFP_KERNEL); + + if (!ipp) { + BREAK_TO_DEBUGGER(); + return NULL; + } + + dce_ipp_construct(ipp, ctx, inst, + &ipp_regs[inst], &ipp_shift, &ipp_mask); + return &ipp->base; +} + +static struct output_pixel_processor *dce112_opp_create( + struct dc_context *ctx, + uint32_t inst) +{ + struct dce110_opp *opp = + kzalloc(sizeof(struct dce110_opp), GFP_KERNEL); + + if (!opp) + return NULL; + + dce110_opp_construct(opp, + ctx, inst, &opp_regs[inst], &opp_shift, &opp_mask); + return &opp->base; +} + +static struct dce_aux *dce112_aux_engine_create( + struct dc_context *ctx, + uint32_t inst) +{ + struct aux_engine_dce110 *aux_engine = + kzalloc(sizeof(struct aux_engine_dce110), GFP_KERNEL); + + if (!aux_engine) + return NULL; + + dce110_aux_engine_construct(aux_engine, ctx, inst, + SW_AUX_TIMEOUT_PERIOD_MULTIPLIER * AUX_TIMEOUT_PERIOD, + &aux_engine_regs[inst], + &aux_mask, + &aux_shift, + ctx->dc->caps.extended_aux_timeout_support); + + return &aux_engine->base; +} +#define i2c_inst_regs(id) { I2C_HW_ENGINE_COMMON_REG_LIST(id) } + +static const struct dce_i2c_registers i2c_hw_regs[] = { + i2c_inst_regs(1), + i2c_inst_regs(2), + i2c_inst_regs(3), + i2c_inst_regs(4), + i2c_inst_regs(5), + i2c_inst_regs(6), +}; + +static const struct dce_i2c_shift i2c_shifts = { + I2C_COMMON_MASK_SH_LIST_DCE110(__SHIFT) +}; + +static const struct dce_i2c_mask i2c_masks = { + I2C_COMMON_MASK_SH_LIST_DCE110(_MASK) +}; + +static struct dce_i2c_hw *dce112_i2c_hw_create( + struct dc_context *ctx, + uint32_t inst) +{ + struct dce_i2c_hw *dce_i2c_hw = + kzalloc(sizeof(struct dce_i2c_hw), GFP_KERNEL); + + if (!dce_i2c_hw) + return NULL; + + dce112_i2c_hw_construct(dce_i2c_hw, ctx, inst, + &i2c_hw_regs[inst], &i2c_shifts, &i2c_masks); + + return dce_i2c_hw; +} +static struct clock_source *dce112_clock_source_create( + struct dc_context *ctx, + struct dc_bios *bios, + enum clock_source_id id, + const struct dce110_clk_src_regs *regs, + bool dp_clk_src) +{ + struct dce110_clk_src *clk_src = + kzalloc(sizeof(struct dce110_clk_src), GFP_KERNEL); + + if (!clk_src) + return NULL; + + if (dce112_clk_src_construct(clk_src, ctx, bios, id, + regs, &cs_shift, &cs_mask)) { + clk_src->base.dp_clk_src = dp_clk_src; + return &clk_src->base; + } + + kfree(clk_src); + BREAK_TO_DEBUGGER(); + return NULL; +} + +static void dce112_clock_source_destroy(struct clock_source **clk_src) +{ + kfree(TO_DCE110_CLK_SRC(*clk_src)); + *clk_src = NULL; +} + +static void dce112_resource_destruct(struct dce110_resource_pool *pool) +{ + unsigned int i; + + for (i = 0; i < pool->base.pipe_count; i++) { + if (pool->base.opps[i] != NULL) + dce110_opp_destroy(&pool->base.opps[i]); + + if (pool->base.transforms[i] != NULL) + dce112_transform_destroy(&pool->base.transforms[i]); + + if (pool->base.ipps[i] != NULL) + dce_ipp_destroy(&pool->base.ipps[i]); + + if (pool->base.mis[i] != NULL) { + kfree(TO_DCE_MEM_INPUT(pool->base.mis[i])); + pool->base.mis[i] = NULL; + } + + if (pool->base.timing_generators[i] != NULL) { + kfree(DCE110TG_FROM_TG(pool->base.timing_generators[i])); + pool->base.timing_generators[i] = NULL; + } + } + + for (i = 0; i < pool->base.res_cap->num_ddc; i++) { + if (pool->base.engines[i] != NULL) + dce110_engine_destroy(&pool->base.engines[i]); + if (pool->base.hw_i2cs[i] != NULL) { + kfree(pool->base.hw_i2cs[i]); + pool->base.hw_i2cs[i] = NULL; + } + if (pool->base.sw_i2cs[i] != NULL) { + kfree(pool->base.sw_i2cs[i]); + pool->base.sw_i2cs[i] = NULL; + } + } + + for (i = 0; i < pool->base.stream_enc_count; i++) { + if (pool->base.stream_enc[i] != NULL) + kfree(DCE110STRENC_FROM_STRENC(pool->base.stream_enc[i])); + } + + for (i = 0; i < pool->base.clk_src_count; i++) { + if (pool->base.clock_sources[i] != NULL) { + dce112_clock_source_destroy(&pool->base.clock_sources[i]); + } + } + + if (pool->base.dp_clock_source != NULL) + dce112_clock_source_destroy(&pool->base.dp_clock_source); + + for (i = 0; i < pool->base.audio_count; i++) { + if (pool->base.audios[i] != NULL) { + dce_aud_destroy(&pool->base.audios[i]); + } + } + + if (pool->base.abm != NULL) + dce_abm_destroy(&pool->base.abm); + + if (pool->base.dmcu != NULL) + dce_dmcu_destroy(&pool->base.dmcu); + + if (pool->base.irqs != NULL) { + dal_irq_service_destroy(&pool->base.irqs); + } +} + +static struct clock_source *find_matching_pll( + struct resource_context *res_ctx, + const struct resource_pool *pool, + const struct dc_stream_state *const stream) +{ + switch (stream->link->link_enc->transmitter) { + case TRANSMITTER_UNIPHY_A: + return pool->clock_sources[DCE112_CLK_SRC_PLL0]; + case TRANSMITTER_UNIPHY_B: + return pool->clock_sources[DCE112_CLK_SRC_PLL1]; + case TRANSMITTER_UNIPHY_C: + return pool->clock_sources[DCE112_CLK_SRC_PLL2]; + case TRANSMITTER_UNIPHY_D: + return pool->clock_sources[DCE112_CLK_SRC_PLL3]; + case TRANSMITTER_UNIPHY_E: + return pool->clock_sources[DCE112_CLK_SRC_PLL4]; + case TRANSMITTER_UNIPHY_F: + return pool->clock_sources[DCE112_CLK_SRC_PLL5]; + default: + return NULL; + } + + return NULL; +} + +static enum dc_status build_mapped_resource( + const struct dc *dc, + struct dc_state *context, + struct dc_stream_state *stream) +{ + struct pipe_ctx *pipe_ctx = resource_get_otg_master_for_stream(&context->res_ctx, stream); + + if (!pipe_ctx) + return DC_ERROR_UNEXPECTED; + + dce110_resource_build_pipe_hw_param(pipe_ctx); + + resource_build_info_frame(pipe_ctx); + + return DC_OK; +} + +bool dce112_validate_bandwidth( + struct dc *dc, + struct dc_state *context, + bool fast_validate) +{ + bool result = false; + + DC_LOG_BANDWIDTH_CALCS( + "%s: start", + __func__); + + if (bw_calcs( + dc->ctx, + dc->bw_dceip, + dc->bw_vbios, + context->res_ctx.pipe_ctx, + dc->res_pool->pipe_count, + &context->bw_ctx.bw.dce)) + result = true; + + if (!result) + DC_LOG_BANDWIDTH_VALIDATION( + "%s: Bandwidth validation failed!", + __func__); + + if (memcmp(&dc->current_state->bw_ctx.bw.dce, + &context->bw_ctx.bw.dce, sizeof(context->bw_ctx.bw.dce))) { + + DC_LOG_BANDWIDTH_CALCS( + "%s: finish,\n" + "nbpMark_b: %d nbpMark_a: %d urgentMark_b: %d urgentMark_a: %d\n" + "stutMark_b: %d stutMark_a: %d\n" + "nbpMark_b: %d nbpMark_a: %d urgentMark_b: %d urgentMark_a: %d\n" + "stutMark_b: %d stutMark_a: %d\n" + "nbpMark_b: %d nbpMark_a: %d urgentMark_b: %d urgentMark_a: %d\n" + "stutMark_b: %d stutMark_a: %d stutter_mode_enable: %d\n" + "cstate: %d pstate: %d nbpstate: %d sync: %d dispclk: %d\n" + "sclk: %d sclk_sleep: %d yclk: %d blackout_recovery_time_us: %d\n" + , + __func__, + context->bw_ctx.bw.dce.nbp_state_change_wm_ns[0].b_mark, + context->bw_ctx.bw.dce.nbp_state_change_wm_ns[0].a_mark, + context->bw_ctx.bw.dce.urgent_wm_ns[0].b_mark, + context->bw_ctx.bw.dce.urgent_wm_ns[0].a_mark, + context->bw_ctx.bw.dce.stutter_exit_wm_ns[0].b_mark, + context->bw_ctx.bw.dce.stutter_exit_wm_ns[0].a_mark, + context->bw_ctx.bw.dce.nbp_state_change_wm_ns[1].b_mark, + context->bw_ctx.bw.dce.nbp_state_change_wm_ns[1].a_mark, + context->bw_ctx.bw.dce.urgent_wm_ns[1].b_mark, + context->bw_ctx.bw.dce.urgent_wm_ns[1].a_mark, + context->bw_ctx.bw.dce.stutter_exit_wm_ns[1].b_mark, + context->bw_ctx.bw.dce.stutter_exit_wm_ns[1].a_mark, + context->bw_ctx.bw.dce.nbp_state_change_wm_ns[2].b_mark, + context->bw_ctx.bw.dce.nbp_state_change_wm_ns[2].a_mark, + context->bw_ctx.bw.dce.urgent_wm_ns[2].b_mark, + context->bw_ctx.bw.dce.urgent_wm_ns[2].a_mark, + context->bw_ctx.bw.dce.stutter_exit_wm_ns[2].b_mark, + context->bw_ctx.bw.dce.stutter_exit_wm_ns[2].a_mark, + context->bw_ctx.bw.dce.stutter_mode_enable, + context->bw_ctx.bw.dce.cpuc_state_change_enable, + context->bw_ctx.bw.dce.cpup_state_change_enable, + context->bw_ctx.bw.dce.nbp_state_change_enable, + context->bw_ctx.bw.dce.all_displays_in_sync, + context->bw_ctx.bw.dce.dispclk_khz, + context->bw_ctx.bw.dce.sclk_khz, + context->bw_ctx.bw.dce.sclk_deep_sleep_khz, + context->bw_ctx.bw.dce.yclk_khz, + context->bw_ctx.bw.dce.blackout_recovery_time_us); + } + return result; +} + +enum dc_status resource_map_phy_clock_resources( + const struct dc *dc, + struct dc_state *context, + struct dc_stream_state *stream) +{ + + /* acquire new resources */ + struct pipe_ctx *pipe_ctx = resource_get_otg_master_for_stream( + &context->res_ctx, stream); + + if (!pipe_ctx) + return DC_ERROR_UNEXPECTED; + + if (dc_is_dp_signal(pipe_ctx->stream->signal) + || dc_is_virtual_signal(pipe_ctx->stream->signal)) + pipe_ctx->clock_source = + dc->res_pool->dp_clock_source; + else { + if (stream && stream->link && stream->link->link_enc) + pipe_ctx->clock_source = find_matching_pll( + &context->res_ctx, dc->res_pool, + stream); + } + + if (pipe_ctx->clock_source == NULL) + return DC_NO_CLOCK_SOURCE_RESOURCE; + + resource_reference_clock_source( + &context->res_ctx, + dc->res_pool, + pipe_ctx->clock_source); + + return DC_OK; +} + +static bool dce112_validate_surface_sets( + struct dc_state *context) +{ + int i; + + for (i = 0; i < context->stream_count; i++) { + if (context->stream_status[i].plane_count == 0) + continue; + + if (context->stream_status[i].plane_count > 1) + return false; + + if (context->stream_status[i].plane_states[0]->format + >= SURFACE_PIXEL_FORMAT_VIDEO_BEGIN) + return false; + } + + return true; +} + +enum dc_status dce112_add_stream_to_ctx( + struct dc *dc, + struct dc_state *new_ctx, + struct dc_stream_state *dc_stream) +{ + enum dc_status result; + + result = resource_map_pool_resources(dc, new_ctx, dc_stream); + + if (result == DC_OK) + result = resource_map_phy_clock_resources(dc, new_ctx, dc_stream); + + + if (result == DC_OK) + result = build_mapped_resource(dc, new_ctx, dc_stream); + + return result; +} + +static enum dc_status dce112_validate_global( + struct dc *dc, + struct dc_state *context) +{ + if (!dce112_validate_surface_sets(context)) + return DC_FAIL_SURFACE_VALIDATE; + + return DC_OK; +} + +static void dce112_destroy_resource_pool(struct resource_pool **pool) +{ + struct dce110_resource_pool *dce110_pool = TO_DCE110_RES_POOL(*pool); + + dce112_resource_destruct(dce110_pool); + kfree(dce110_pool); + *pool = NULL; +} + +static const struct resource_funcs dce112_res_pool_funcs = { + .destroy = dce112_destroy_resource_pool, + .link_enc_create = dce112_link_encoder_create, + .panel_cntl_create = dce112_panel_cntl_create, + .validate_bandwidth = dce112_validate_bandwidth, + .validate_plane = dce100_validate_plane, + .add_stream_to_ctx = dce112_add_stream_to_ctx, + .validate_global = dce112_validate_global, + .find_first_free_match_stream_enc_for_link = dce110_find_first_free_match_stream_enc_for_link +}; + +static void bw_calcs_data_update_from_pplib(struct dc *dc) +{ + struct dm_pp_clock_levels_with_latency eng_clks = {0}; + struct dm_pp_clock_levels_with_latency mem_clks = {0}; + struct dm_pp_wm_sets_with_clock_ranges clk_ranges = {0}; + struct dm_pp_clock_levels clks = {0}; + int memory_type_multiplier = MEMORY_TYPE_MULTIPLIER_CZ; + + if (dc->bw_vbios && dc->bw_vbios->memory_type == bw_def_hbm) + memory_type_multiplier = MEMORY_TYPE_HBM; + + /*do system clock TODO PPLIB: after PPLIB implement, + * then remove old way + */ + if (!dm_pp_get_clock_levels_by_type_with_latency( + dc->ctx, + DM_PP_CLOCK_TYPE_ENGINE_CLK, + &eng_clks)) { + + /* This is only for temporary */ + dm_pp_get_clock_levels_by_type( + dc->ctx, + DM_PP_CLOCK_TYPE_ENGINE_CLK, + &clks); + /* convert all the clock fro kHz to fix point mHz */ + dc->bw_vbios->high_sclk = bw_frc_to_fixed( + clks.clocks_in_khz[clks.num_levels-1], 1000); + dc->bw_vbios->mid1_sclk = bw_frc_to_fixed( + clks.clocks_in_khz[clks.num_levels/8], 1000); + dc->bw_vbios->mid2_sclk = bw_frc_to_fixed( + clks.clocks_in_khz[clks.num_levels*2/8], 1000); + dc->bw_vbios->mid3_sclk = bw_frc_to_fixed( + clks.clocks_in_khz[clks.num_levels*3/8], 1000); + dc->bw_vbios->mid4_sclk = bw_frc_to_fixed( + clks.clocks_in_khz[clks.num_levels*4/8], 1000); + dc->bw_vbios->mid5_sclk = bw_frc_to_fixed( + clks.clocks_in_khz[clks.num_levels*5/8], 1000); + dc->bw_vbios->mid6_sclk = bw_frc_to_fixed( + clks.clocks_in_khz[clks.num_levels*6/8], 1000); + dc->bw_vbios->low_sclk = bw_frc_to_fixed( + clks.clocks_in_khz[0], 1000); + + /*do memory clock*/ + dm_pp_get_clock_levels_by_type( + dc->ctx, + DM_PP_CLOCK_TYPE_MEMORY_CLK, + &clks); + + dc->bw_vbios->low_yclk = bw_frc_to_fixed( + clks.clocks_in_khz[0] * memory_type_multiplier, 1000); + dc->bw_vbios->mid_yclk = bw_frc_to_fixed( + clks.clocks_in_khz[clks.num_levels>>1] * memory_type_multiplier, + 1000); + dc->bw_vbios->high_yclk = bw_frc_to_fixed( + clks.clocks_in_khz[clks.num_levels-1] * memory_type_multiplier, + 1000); + + return; + } + + /* convert all the clock fro kHz to fix point mHz TODO: wloop data */ + dc->bw_vbios->high_sclk = bw_frc_to_fixed( + eng_clks.data[eng_clks.num_levels-1].clocks_in_khz, 1000); + dc->bw_vbios->mid1_sclk = bw_frc_to_fixed( + eng_clks.data[eng_clks.num_levels/8].clocks_in_khz, 1000); + dc->bw_vbios->mid2_sclk = bw_frc_to_fixed( + eng_clks.data[eng_clks.num_levels*2/8].clocks_in_khz, 1000); + dc->bw_vbios->mid3_sclk = bw_frc_to_fixed( + eng_clks.data[eng_clks.num_levels*3/8].clocks_in_khz, 1000); + dc->bw_vbios->mid4_sclk = bw_frc_to_fixed( + eng_clks.data[eng_clks.num_levels*4/8].clocks_in_khz, 1000); + dc->bw_vbios->mid5_sclk = bw_frc_to_fixed( + eng_clks.data[eng_clks.num_levels*5/8].clocks_in_khz, 1000); + dc->bw_vbios->mid6_sclk = bw_frc_to_fixed( + eng_clks.data[eng_clks.num_levels*6/8].clocks_in_khz, 1000); + dc->bw_vbios->low_sclk = bw_frc_to_fixed( + eng_clks.data[0].clocks_in_khz, 1000); + + /*do memory clock*/ + dm_pp_get_clock_levels_by_type_with_latency( + dc->ctx, + DM_PP_CLOCK_TYPE_MEMORY_CLK, + &mem_clks); + + /* we don't need to call PPLIB for validation clock since they + * also give us the highest sclk and highest mclk (UMA clock). + * ALSO always convert UMA clock (from PPLIB) to YCLK (HW formula): + * YCLK = UMACLK*m_memoryTypeMultiplier + */ + dc->bw_vbios->low_yclk = bw_frc_to_fixed( + mem_clks.data[0].clocks_in_khz * memory_type_multiplier, 1000); + dc->bw_vbios->mid_yclk = bw_frc_to_fixed( + mem_clks.data[mem_clks.num_levels>>1].clocks_in_khz * memory_type_multiplier, + 1000); + dc->bw_vbios->high_yclk = bw_frc_to_fixed( + mem_clks.data[mem_clks.num_levels-1].clocks_in_khz * memory_type_multiplier, + 1000); + + /* Now notify PPLib/SMU about which Watermarks sets they should select + * depending on DPM state they are in. And update BW MGR GFX Engine and + * Memory clock member variables for Watermarks calculations for each + * Watermark Set + */ + clk_ranges.num_wm_sets = 4; + clk_ranges.wm_clk_ranges[0].wm_set_id = WM_SET_A; + clk_ranges.wm_clk_ranges[0].wm_min_eng_clk_in_khz = + eng_clks.data[0].clocks_in_khz; + clk_ranges.wm_clk_ranges[0].wm_max_eng_clk_in_khz = + eng_clks.data[eng_clks.num_levels*3/8].clocks_in_khz - 1; + clk_ranges.wm_clk_ranges[0].wm_min_mem_clk_in_khz = + mem_clks.data[0].clocks_in_khz; + clk_ranges.wm_clk_ranges[0].wm_max_mem_clk_in_khz = + mem_clks.data[mem_clks.num_levels>>1].clocks_in_khz - 1; + + clk_ranges.wm_clk_ranges[1].wm_set_id = WM_SET_B; + clk_ranges.wm_clk_ranges[1].wm_min_eng_clk_in_khz = + eng_clks.data[eng_clks.num_levels*3/8].clocks_in_khz; + /* 5 GHz instead of data[7].clockInKHz to cover Overdrive */ + clk_ranges.wm_clk_ranges[1].wm_max_eng_clk_in_khz = 5000000; + clk_ranges.wm_clk_ranges[1].wm_min_mem_clk_in_khz = + mem_clks.data[0].clocks_in_khz; + clk_ranges.wm_clk_ranges[1].wm_max_mem_clk_in_khz = + mem_clks.data[mem_clks.num_levels>>1].clocks_in_khz - 1; + + clk_ranges.wm_clk_ranges[2].wm_set_id = WM_SET_C; + clk_ranges.wm_clk_ranges[2].wm_min_eng_clk_in_khz = + eng_clks.data[0].clocks_in_khz; + clk_ranges.wm_clk_ranges[2].wm_max_eng_clk_in_khz = + eng_clks.data[eng_clks.num_levels*3/8].clocks_in_khz - 1; + clk_ranges.wm_clk_ranges[2].wm_min_mem_clk_in_khz = + mem_clks.data[mem_clks.num_levels>>1].clocks_in_khz; + /* 5 GHz instead of data[2].clockInKHz to cover Overdrive */ + clk_ranges.wm_clk_ranges[2].wm_max_mem_clk_in_khz = 5000000; + + clk_ranges.wm_clk_ranges[3].wm_set_id = WM_SET_D; + clk_ranges.wm_clk_ranges[3].wm_min_eng_clk_in_khz = + eng_clks.data[eng_clks.num_levels*3/8].clocks_in_khz; + /* 5 GHz instead of data[7].clockInKHz to cover Overdrive */ + clk_ranges.wm_clk_ranges[3].wm_max_eng_clk_in_khz = 5000000; + clk_ranges.wm_clk_ranges[3].wm_min_mem_clk_in_khz = + mem_clks.data[mem_clks.num_levels>>1].clocks_in_khz; + /* 5 GHz instead of data[2].clockInKHz to cover Overdrive */ + clk_ranges.wm_clk_ranges[3].wm_max_mem_clk_in_khz = 5000000; + + /* Notify PP Lib/SMU which Watermarks to use for which clock ranges */ + dm_pp_notify_wm_clock_changes(dc->ctx, &clk_ranges); +} + +static const struct resource_caps *dce112_resource_cap( + struct hw_asic_id *asic_id) +{ + if (ASIC_REV_IS_POLARIS11_M(asic_id->hw_internal_rev) || + ASIC_REV_IS_POLARIS12_V(asic_id->hw_internal_rev)) + return &polaris_11_resource_cap; + else + return &polaris_10_resource_cap; +} + +static bool dce112_resource_construct( + uint8_t num_virtual_links, + struct dc *dc, + struct dce110_resource_pool *pool) +{ + unsigned int i; + struct dc_context *ctx = dc->ctx; + + ctx->dc_bios->regs = &bios_regs; + + pool->base.res_cap = dce112_resource_cap(&ctx->asic_id); + pool->base.funcs = &dce112_res_pool_funcs; + + /************************************************* + * Resource + asic cap harcoding * + *************************************************/ + pool->base.underlay_pipe_index = NO_UNDERLAY_PIPE; + pool->base.pipe_count = pool->base.res_cap->num_timing_generator; + pool->base.timing_generator_count = pool->base.res_cap->num_timing_generator; + dc->caps.max_downscale_ratio = 200; + dc->caps.i2c_speed_in_khz = 100; + dc->caps.i2c_speed_in_khz_hdcp = 100; /*1.4 w/a not applied by default*/ + dc->caps.max_cursor_size = 128; + dc->caps.min_horizontal_blanking_period = 80; + dc->caps.dual_link_dvi = true; + dc->caps.extended_aux_timeout_support = false; + dc->debug = debug_defaults; + + /************************************************* + * Create resources * + *************************************************/ + + pool->base.clock_sources[DCE112_CLK_SRC_PLL0] = + dce112_clock_source_create( + ctx, ctx->dc_bios, + CLOCK_SOURCE_COMBO_PHY_PLL0, + &clk_src_regs[0], false); + pool->base.clock_sources[DCE112_CLK_SRC_PLL1] = + dce112_clock_source_create( + ctx, ctx->dc_bios, + CLOCK_SOURCE_COMBO_PHY_PLL1, + &clk_src_regs[1], false); + pool->base.clock_sources[DCE112_CLK_SRC_PLL2] = + dce112_clock_source_create( + ctx, ctx->dc_bios, + CLOCK_SOURCE_COMBO_PHY_PLL2, + &clk_src_regs[2], false); + pool->base.clock_sources[DCE112_CLK_SRC_PLL3] = + dce112_clock_source_create( + ctx, ctx->dc_bios, + CLOCK_SOURCE_COMBO_PHY_PLL3, + &clk_src_regs[3], false); + pool->base.clock_sources[DCE112_CLK_SRC_PLL4] = + dce112_clock_source_create( + ctx, ctx->dc_bios, + CLOCK_SOURCE_COMBO_PHY_PLL4, + &clk_src_regs[4], false); + pool->base.clock_sources[DCE112_CLK_SRC_PLL5] = + dce112_clock_source_create( + ctx, ctx->dc_bios, + CLOCK_SOURCE_COMBO_PHY_PLL5, + &clk_src_regs[5], false); + pool->base.clk_src_count = DCE112_CLK_SRC_TOTAL; + + pool->base.dp_clock_source = dce112_clock_source_create( + ctx, ctx->dc_bios, + CLOCK_SOURCE_ID_DP_DTO, &clk_src_regs[0], true); + + + for (i = 0; i < pool->base.clk_src_count; i++) { + if (pool->base.clock_sources[i] == NULL) { + dm_error("DC: failed to create clock sources!\n"); + BREAK_TO_DEBUGGER(); + goto res_create_fail; + } + } + + pool->base.dmcu = dce_dmcu_create(ctx, + &dmcu_regs, + &dmcu_shift, + &dmcu_mask); + if (pool->base.dmcu == NULL) { + dm_error("DC: failed to create dmcu!\n"); + BREAK_TO_DEBUGGER(); + goto res_create_fail; + } + + pool->base.abm = dce_abm_create(ctx, + &abm_regs, + &abm_shift, + &abm_mask); + if (pool->base.abm == NULL) { + dm_error("DC: failed to create abm!\n"); + BREAK_TO_DEBUGGER(); + goto res_create_fail; + } + + { + struct irq_service_init_data init_data; + init_data.ctx = dc->ctx; + pool->base.irqs = dal_irq_service_dce110_create(&init_data); + if (!pool->base.irqs) + goto res_create_fail; + } + + for (i = 0; i < pool->base.pipe_count; i++) { + pool->base.timing_generators[i] = + dce112_timing_generator_create( + ctx, + i, + &dce112_tg_offsets[i]); + if (pool->base.timing_generators[i] == NULL) { + BREAK_TO_DEBUGGER(); + dm_error("DC: failed to create tg!\n"); + goto res_create_fail; + } + + pool->base.mis[i] = dce112_mem_input_create(ctx, i); + if (pool->base.mis[i] == NULL) { + BREAK_TO_DEBUGGER(); + dm_error( + "DC: failed to create memory input!\n"); + goto res_create_fail; + } + + pool->base.ipps[i] = dce112_ipp_create(ctx, i); + if (pool->base.ipps[i] == NULL) { + BREAK_TO_DEBUGGER(); + dm_error( + "DC:failed to create input pixel processor!\n"); + goto res_create_fail; + } + + pool->base.transforms[i] = dce112_transform_create(ctx, i); + if (pool->base.transforms[i] == NULL) { + BREAK_TO_DEBUGGER(); + dm_error( + "DC: failed to create transform!\n"); + goto res_create_fail; + } + + pool->base.opps[i] = dce112_opp_create( + ctx, + i); + if (pool->base.opps[i] == NULL) { + BREAK_TO_DEBUGGER(); + dm_error( + "DC:failed to create output pixel processor!\n"); + goto res_create_fail; + } + } + + for (i = 0; i < pool->base.res_cap->num_ddc; i++) { + pool->base.engines[i] = dce112_aux_engine_create(ctx, i); + if (pool->base.engines[i] == NULL) { + BREAK_TO_DEBUGGER(); + dm_error( + "DC:failed to create aux engine!!\n"); + goto res_create_fail; + } + pool->base.hw_i2cs[i] = dce112_i2c_hw_create(ctx, i); + if (pool->base.hw_i2cs[i] == NULL) { + BREAK_TO_DEBUGGER(); + dm_error( + "DC:failed to create i2c engine!!\n"); + goto res_create_fail; + } + pool->base.sw_i2cs[i] = NULL; + } + + if (!resource_construct(num_virtual_links, dc, &pool->base, + &res_create_funcs)) + goto res_create_fail; + + dc->caps.max_planes = pool->base.pipe_count; + + for (i = 0; i < dc->caps.max_planes; ++i) + dc->caps.planes[i] = plane_cap; + + /* Create hardware sequencer */ + dce112_hw_sequencer_construct(dc); + + bw_calcs_init(dc->bw_dceip, dc->bw_vbios, dc->ctx->asic_id); + + bw_calcs_data_update_from_pplib(dc); + + return true; + +res_create_fail: + dce112_resource_destruct(pool); + return false; +} + +struct resource_pool *dce112_create_resource_pool( + uint8_t num_virtual_links, + struct dc *dc) +{ + struct dce110_resource_pool *pool = + kzalloc(sizeof(struct dce110_resource_pool), GFP_KERNEL); + + if (!pool) + return NULL; + + if (dce112_resource_construct(num_virtual_links, dc, pool)) + return &pool->base; + + kfree(pool); + BREAK_TO_DEBUGGER(); + return NULL; +} diff --git a/drivers/gpu/drm/amd/display/dc/resource/dce112/dce112_resource.h b/drivers/gpu/drm/amd/display/dc/resource/dce112/dce112_resource.h new file mode 100644 index 000000000000..1f57ebc6f9b4 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/resource/dce112/dce112_resource.h @@ -0,0 +1,57 @@ +/* +* Copyright 2012-15 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_RESOURCE_DCE112_H__ +#define __DC_RESOURCE_DCE112_H__ + +#include "core_types.h" + +struct dc; +struct resource_pool; + +struct resource_pool *dce112_create_resource_pool( + uint8_t num_virtual_links, + struct dc *dc); + +enum dc_status dce112_validate_with_context( + struct dc *dc, + const struct dc_validation_set set[], + int set_count, + struct dc_state *context, + struct dc_state *old_context); + +bool dce112_validate_bandwidth( + struct dc *dc, + struct dc_state *context, + bool fast_validate); + +enum dc_status dce112_add_stream_to_ctx( + struct dc *dc, + struct dc_state *new_ctx, + struct dc_stream_state *dc_stream); + + +#endif /* __DC_RESOURCE_DCE112_H__ */ + diff --git a/drivers/gpu/drm/amd/display/dc/resource/dce120/dce120_resource.c b/drivers/gpu/drm/amd/display/dc/resource/dce120/dce120_resource.c new file mode 100644 index 000000000000..20662edd0ae4 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/resource/dce120/dce120_resource.c @@ -0,0 +1,1288 @@ +/* +* Copyright 2012-15 Advanced Micro Devices, Inc.cls +* + * + * 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 "dm_services.h" + + +#include "stream_encoder.h" +#include "resource.h" +#include "include/irq_service_interface.h" +#include "dce120_resource.h" + +#include "dce112/dce112_resource.h" + +#include "dce110/dce110_resource.h" +#include "virtual/virtual_stream_encoder.h" +#include "dce120/dce120_timing_generator.h" +#include "irq/dce120/irq_service_dce120.h" +#include "dce/dce_opp.h" +#include "dce/dce_clock_source.h" +#include "dce/dce_ipp.h" +#include "dce/dce_mem_input.h" +#include "dce/dce_panel_cntl.h" + +#include "dce110/dce110_hwseq.h" +#include "dce120/dce120_hwseq.h" +#include "dce/dce_transform.h" +#include "clk_mgr.h" +#include "dce/dce_audio.h" +#include "dce/dce_link_encoder.h" +#include "dce/dce_stream_encoder.h" +#include "dce/dce_hwseq.h" +#include "dce/dce_abm.h" +#include "dce/dce_dmcu.h" +#include "dce/dce_aux.h" +#include "dce/dce_i2c.h" + +#include "dce/dce_12_0_offset.h" +#include "dce/dce_12_0_sh_mask.h" +#include "soc15_hw_ip.h" +#include "vega10_ip_offset.h" +#include "nbio/nbio_6_1_offset.h" +#include "mmhub/mmhub_1_0_offset.h" +#include "mmhub/mmhub_1_0_sh_mask.h" +#include "reg_helper.h" + +#include "dce100/dce100_resource.h" + +#ifndef mmDP0_DP_DPHY_INTERNAL_CTRL + #define mmDP0_DP_DPHY_INTERNAL_CTRL 0x210f + #define mmDP0_DP_DPHY_INTERNAL_CTRL_BASE_IDX 2 + #define mmDP1_DP_DPHY_INTERNAL_CTRL 0x220f + #define mmDP1_DP_DPHY_INTERNAL_CTRL_BASE_IDX 2 + #define mmDP2_DP_DPHY_INTERNAL_CTRL 0x230f + #define mmDP2_DP_DPHY_INTERNAL_CTRL_BASE_IDX 2 + #define mmDP3_DP_DPHY_INTERNAL_CTRL 0x240f + #define mmDP3_DP_DPHY_INTERNAL_CTRL_BASE_IDX 2 + #define mmDP4_DP_DPHY_INTERNAL_CTRL 0x250f + #define mmDP4_DP_DPHY_INTERNAL_CTRL_BASE_IDX 2 + #define mmDP5_DP_DPHY_INTERNAL_CTRL 0x260f + #define mmDP5_DP_DPHY_INTERNAL_CTRL_BASE_IDX 2 + #define mmDP6_DP_DPHY_INTERNAL_CTRL 0x270f + #define mmDP6_DP_DPHY_INTERNAL_CTRL_BASE_IDX 2 +#endif + +enum dce120_clk_src_array_id { + DCE120_CLK_SRC_PLL0, + DCE120_CLK_SRC_PLL1, + DCE120_CLK_SRC_PLL2, + DCE120_CLK_SRC_PLL3, + DCE120_CLK_SRC_PLL4, + DCE120_CLK_SRC_PLL5, + + DCE120_CLK_SRC_TOTAL +}; + +static const struct dce110_timing_generator_offsets dce120_tg_offsets[] = { + { + .crtc = (mmCRTC0_CRTC_CONTROL - mmCRTC0_CRTC_CONTROL), + }, + { + .crtc = (mmCRTC1_CRTC_CONTROL - mmCRTC0_CRTC_CONTROL), + }, + { + .crtc = (mmCRTC2_CRTC_CONTROL - mmCRTC0_CRTC_CONTROL), + }, + { + .crtc = (mmCRTC3_CRTC_CONTROL - mmCRTC0_CRTC_CONTROL), + }, + { + .crtc = (mmCRTC4_CRTC_CONTROL - mmCRTC0_CRTC_CONTROL), + }, + { + .crtc = (mmCRTC5_CRTC_CONTROL - mmCRTC0_CRTC_CONTROL), + } +}; + +/* begin ********************* + * macros to expend register list macro defined in HW object header file */ + +#define BASE_INNER(seg) \ + DCE_BASE__INST0_SEG ## seg + +#define NBIO_BASE_INNER(seg) \ + NBIF_BASE__INST0_SEG ## seg + +#define NBIO_BASE(seg) \ + NBIO_BASE_INNER(seg) + +/* compile time expand base address. */ +#define BASE(seg) \ + BASE_INNER(seg) + +#define SR(reg_name)\ + .reg_name = BASE(mm ## reg_name ## _BASE_IDX) + \ + mm ## reg_name + +#define SRI(reg_name, block, id)\ + .reg_name = BASE(mm ## block ## id ## _ ## reg_name ## _BASE_IDX) + \ + mm ## block ## id ## _ ## reg_name + +/* MMHUB */ +#define MMHUB_BASE_INNER(seg) \ + MMHUB_BASE__INST0_SEG ## seg + +#define MMHUB_BASE(seg) \ + MMHUB_BASE_INNER(seg) + +#define MMHUB_SR(reg_name)\ + .reg_name = MMHUB_BASE(mm ## reg_name ## _BASE_IDX) + \ + mm ## reg_name + +/* macros to expend register list macro defined in HW object header file + * end *********************/ + + +static const struct dce_dmcu_registers dmcu_regs = { + DMCU_DCE110_COMMON_REG_LIST() +}; + +static const struct dce_dmcu_shift dmcu_shift = { + DMCU_MASK_SH_LIST_DCE110(__SHIFT) +}; + +static const struct dce_dmcu_mask dmcu_mask = { + DMCU_MASK_SH_LIST_DCE110(_MASK) +}; + +static const struct dce_abm_registers abm_regs = { + ABM_DCE110_COMMON_REG_LIST() +}; + +static const struct dce_abm_shift abm_shift = { + ABM_MASK_SH_LIST_DCE110(__SHIFT) +}; + +static const struct dce_abm_mask abm_mask = { + ABM_MASK_SH_LIST_DCE110(_MASK) +}; + +#define ipp_regs(id)\ +[id] = {\ + IPP_DCE110_REG_LIST_DCE_BASE(id)\ +} + +static const struct dce_ipp_registers ipp_regs[] = { + ipp_regs(0), + ipp_regs(1), + ipp_regs(2), + ipp_regs(3), + ipp_regs(4), + ipp_regs(5) +}; + +static const struct dce_ipp_shift ipp_shift = { + IPP_DCE120_MASK_SH_LIST_SOC_BASE(__SHIFT) +}; + +static const struct dce_ipp_mask ipp_mask = { + IPP_DCE120_MASK_SH_LIST_SOC_BASE(_MASK) +}; + +#define transform_regs(id)\ +[id] = {\ + XFM_COMMON_REG_LIST_DCE110(id)\ +} + +static const struct dce_transform_registers xfm_regs[] = { + transform_regs(0), + transform_regs(1), + transform_regs(2), + transform_regs(3), + transform_regs(4), + transform_regs(5) +}; + +static const struct dce_transform_shift xfm_shift = { + XFM_COMMON_MASK_SH_LIST_SOC_BASE(__SHIFT) +}; + +static const struct dce_transform_mask xfm_mask = { + XFM_COMMON_MASK_SH_LIST_SOC_BASE(_MASK) +}; + +#define aux_regs(id)\ +[id] = {\ + AUX_REG_LIST(id)\ +} + +static const struct dce110_link_enc_aux_registers link_enc_aux_regs[] = { + aux_regs(0), + aux_regs(1), + aux_regs(2), + aux_regs(3), + aux_regs(4), + aux_regs(5) +}; + +#define hpd_regs(id)\ +[id] = {\ + HPD_REG_LIST(id)\ +} + +static const struct dce110_link_enc_hpd_registers link_enc_hpd_regs[] = { + hpd_regs(0), + hpd_regs(1), + hpd_regs(2), + hpd_regs(3), + hpd_regs(4), + hpd_regs(5) +}; + +#define link_regs(id)\ +[id] = {\ + LE_DCE120_REG_LIST(id), \ + SRI(DP_DPHY_INTERNAL_CTRL, DP, id) \ +} + +static const struct dce110_link_enc_registers link_enc_regs[] = { + link_regs(0), + link_regs(1), + link_regs(2), + link_regs(3), + link_regs(4), + link_regs(5), + link_regs(6), +}; + + +#define stream_enc_regs(id)\ +[id] = {\ + SE_COMMON_REG_LIST(id),\ + .TMDS_CNTL = 0,\ +} + +static const struct dce110_stream_enc_registers stream_enc_regs[] = { + stream_enc_regs(0), + stream_enc_regs(1), + stream_enc_regs(2), + stream_enc_regs(3), + stream_enc_regs(4), + stream_enc_regs(5) +}; + +static const struct dce_stream_encoder_shift se_shift = { + SE_COMMON_MASK_SH_LIST_DCE120(__SHIFT) +}; + +static const struct dce_stream_encoder_mask se_mask = { + SE_COMMON_MASK_SH_LIST_DCE120(_MASK) +}; + +static const struct dce_panel_cntl_registers panel_cntl_regs[] = { + { DCE_PANEL_CNTL_REG_LIST() } +}; + +static const struct dce_panel_cntl_shift panel_cntl_shift = { + DCE_PANEL_CNTL_MASK_SH_LIST(__SHIFT) +}; + +static const struct dce_panel_cntl_mask panel_cntl_mask = { + DCE_PANEL_CNTL_MASK_SH_LIST(_MASK) +}; + +static const struct dce110_aux_registers_shift aux_shift = { + DCE12_AUX_MASK_SH_LIST(__SHIFT) +}; + +static const struct dce110_aux_registers_mask aux_mask = { + DCE12_AUX_MASK_SH_LIST(_MASK) +}; + +#define opp_regs(id)\ +[id] = {\ + OPP_DCE_120_REG_LIST(id),\ +} + +static const struct dce_opp_registers opp_regs[] = { + opp_regs(0), + opp_regs(1), + opp_regs(2), + opp_regs(3), + opp_regs(4), + opp_regs(5) +}; + +static const struct dce_opp_shift opp_shift = { + OPP_COMMON_MASK_SH_LIST_DCE_120(__SHIFT) +}; + +static const struct dce_opp_mask opp_mask = { + OPP_COMMON_MASK_SH_LIST_DCE_120(_MASK) +}; + #define aux_engine_regs(id)\ +[id] = {\ + AUX_COMMON_REG_LIST(id), \ + .AUX_RESET_MASK = 0 \ +} + +static const struct dce110_aux_registers aux_engine_regs[] = { + aux_engine_regs(0), + aux_engine_regs(1), + aux_engine_regs(2), + aux_engine_regs(3), + aux_engine_regs(4), + aux_engine_regs(5) +}; + +#define audio_regs(id)\ +[id] = {\ + AUD_COMMON_REG_LIST(id)\ +} + +static const struct dce_audio_registers audio_regs[] = { + audio_regs(0), + audio_regs(1), + audio_regs(2), + audio_regs(3), + audio_regs(4), + audio_regs(5), + audio_regs(6), +}; + +#define DCE120_AUD_COMMON_MASK_SH_LIST(mask_sh)\ + SF(AZF0ENDPOINT0_AZALIA_F0_CODEC_ENDPOINT_INDEX, AZALIA_ENDPOINT_REG_INDEX, mask_sh),\ + SF(AZF0ENDPOINT0_AZALIA_F0_CODEC_ENDPOINT_DATA, AZALIA_ENDPOINT_REG_DATA, mask_sh),\ + AUD_COMMON_MASK_SH_LIST_BASE(mask_sh) + +static const struct dce_audio_shift audio_shift = { + DCE120_AUD_COMMON_MASK_SH_LIST(__SHIFT) +}; + +static const struct dce_audio_mask audio_mask = { + DCE120_AUD_COMMON_MASK_SH_LIST(_MASK) +}; + +static int map_transmitter_id_to_phy_instance( + enum transmitter transmitter) +{ + switch (transmitter) { + case TRANSMITTER_UNIPHY_A: + return 0; + case TRANSMITTER_UNIPHY_B: + return 1; + case TRANSMITTER_UNIPHY_C: + return 2; + case TRANSMITTER_UNIPHY_D: + return 3; + case TRANSMITTER_UNIPHY_E: + return 4; + case TRANSMITTER_UNIPHY_F: + return 5; + case TRANSMITTER_UNIPHY_G: + return 6; + default: + ASSERT(0); + return 0; + } +} + +#define clk_src_regs(index, id)\ +[index] = {\ + CS_COMMON_REG_LIST_DCE_112(id),\ +} + +static const struct dce110_clk_src_regs clk_src_regs[] = { + clk_src_regs(0, A), + clk_src_regs(1, B), + clk_src_regs(2, C), + clk_src_regs(3, D), + clk_src_regs(4, E), + clk_src_regs(5, F) +}; + +static const struct dce110_clk_src_shift cs_shift = { + CS_COMMON_MASK_SH_LIST_DCE_112(__SHIFT) +}; + +static const struct dce110_clk_src_mask cs_mask = { + CS_COMMON_MASK_SH_LIST_DCE_112(_MASK) +}; + +static struct output_pixel_processor *dce120_opp_create( + struct dc_context *ctx, + uint32_t inst) +{ + struct dce110_opp *opp = + kzalloc(sizeof(struct dce110_opp), GFP_KERNEL); + + if (!opp) + return NULL; + + dce110_opp_construct(opp, + ctx, inst, &opp_regs[inst], &opp_shift, &opp_mask); + return &opp->base; +} +static struct dce_aux *dce120_aux_engine_create( + struct dc_context *ctx, + uint32_t inst) +{ + struct aux_engine_dce110 *aux_engine = + kzalloc(sizeof(struct aux_engine_dce110), GFP_KERNEL); + + if (!aux_engine) + return NULL; + + dce110_aux_engine_construct(aux_engine, ctx, inst, + SW_AUX_TIMEOUT_PERIOD_MULTIPLIER * AUX_TIMEOUT_PERIOD, + &aux_engine_regs[inst], + &aux_mask, + &aux_shift, + ctx->dc->caps.extended_aux_timeout_support); + + return &aux_engine->base; +} +#define i2c_inst_regs(id) { I2C_HW_ENGINE_COMMON_REG_LIST(id) } + +static const struct dce_i2c_registers i2c_hw_regs[] = { + i2c_inst_regs(1), + i2c_inst_regs(2), + i2c_inst_regs(3), + i2c_inst_regs(4), + i2c_inst_regs(5), + i2c_inst_regs(6), +}; + +static const struct dce_i2c_shift i2c_shifts = { + I2C_COMMON_MASK_SH_LIST_DCE110(__SHIFT) +}; + +static const struct dce_i2c_mask i2c_masks = { + I2C_COMMON_MASK_SH_LIST_DCE110(_MASK) +}; + +static struct dce_i2c_hw *dce120_i2c_hw_create( + struct dc_context *ctx, + uint32_t inst) +{ + struct dce_i2c_hw *dce_i2c_hw = + kzalloc(sizeof(struct dce_i2c_hw), GFP_KERNEL); + + if (!dce_i2c_hw) + return NULL; + + dce112_i2c_hw_construct(dce_i2c_hw, ctx, inst, + &i2c_hw_regs[inst], &i2c_shifts, &i2c_masks); + + return dce_i2c_hw; +} +static const struct bios_registers bios_regs = { + .BIOS_SCRATCH_3 = mmBIOS_SCRATCH_3 + NBIO_BASE(mmBIOS_SCRATCH_3_BASE_IDX), + .BIOS_SCRATCH_6 = mmBIOS_SCRATCH_6 + NBIO_BASE(mmBIOS_SCRATCH_6_BASE_IDX) +}; + +static const struct resource_caps res_cap = { + .num_timing_generator = 6, + .num_audio = 7, + .num_stream_encoder = 6, + .num_pll = 6, + .num_ddc = 6, +}; + +static const struct dc_plane_cap plane_cap = { + .type = DC_PLANE_TYPE_DCE_RGB, + + .pixel_format_support = { + .argb8888 = true, + .nv12 = false, + .fp16 = true + }, + + .max_upscale_factor = { + .argb8888 = 16000, + .nv12 = 1, + .fp16 = 1 + }, + + .max_downscale_factor = { + .argb8888 = 250, + .nv12 = 1, + .fp16 = 1 + } +}; + +static const struct dc_debug_options debug_defaults = { + .disable_clock_gate = true, + .enable_legacy_fast_update = true, +}; + +static struct clock_source *dce120_clock_source_create( + struct dc_context *ctx, + struct dc_bios *bios, + enum clock_source_id id, + const struct dce110_clk_src_regs *regs, + bool dp_clk_src) +{ + struct dce110_clk_src *clk_src = + kzalloc(sizeof(*clk_src), GFP_KERNEL); + + if (!clk_src) + return NULL; + + if (dce112_clk_src_construct(clk_src, ctx, bios, id, + regs, &cs_shift, &cs_mask)) { + clk_src->base.dp_clk_src = dp_clk_src; + return &clk_src->base; + } + + kfree(clk_src); + BREAK_TO_DEBUGGER(); + return NULL; +} + +static void dce120_clock_source_destroy(struct clock_source **clk_src) +{ + kfree(TO_DCE110_CLK_SRC(*clk_src)); + *clk_src = NULL; +} + + +static bool dce120_hw_sequencer_create(struct dc *dc) +{ + /* All registers used by dce11.2 match those in dce11 in offset and + * structure + */ + dce120_hw_sequencer_construct(dc); + + /*TODO Move to separate file and Override what is needed */ + + return true; +} + +static struct timing_generator *dce120_timing_generator_create( + struct dc_context *ctx, + uint32_t instance, + const struct dce110_timing_generator_offsets *offsets) +{ + struct dce110_timing_generator *tg110 = + kzalloc(sizeof(struct dce110_timing_generator), GFP_KERNEL); + + if (!tg110) + return NULL; + + dce120_timing_generator_construct(tg110, ctx, instance, offsets); + return &tg110->base; +} + +static void dce120_transform_destroy(struct transform **xfm) +{ + kfree(TO_DCE_TRANSFORM(*xfm)); + *xfm = NULL; +} + +static void dce120_resource_destruct(struct dce110_resource_pool *pool) +{ + unsigned int i; + + for (i = 0; i < pool->base.pipe_count; i++) { + if (pool->base.opps[i] != NULL) + dce110_opp_destroy(&pool->base.opps[i]); + + if (pool->base.transforms[i] != NULL) + dce120_transform_destroy(&pool->base.transforms[i]); + + if (pool->base.ipps[i] != NULL) + dce_ipp_destroy(&pool->base.ipps[i]); + + if (pool->base.mis[i] != NULL) { + kfree(TO_DCE_MEM_INPUT(pool->base.mis[i])); + pool->base.mis[i] = NULL; + } + + if (pool->base.irqs != NULL) { + dal_irq_service_destroy(&pool->base.irqs); + } + + if (pool->base.timing_generators[i] != NULL) { + kfree(DCE110TG_FROM_TG(pool->base.timing_generators[i])); + pool->base.timing_generators[i] = NULL; + } + } + + for (i = 0; i < pool->base.res_cap->num_ddc; i++) { + if (pool->base.engines[i] != NULL) + dce110_engine_destroy(&pool->base.engines[i]); + if (pool->base.hw_i2cs[i] != NULL) { + kfree(pool->base.hw_i2cs[i]); + pool->base.hw_i2cs[i] = NULL; + } + if (pool->base.sw_i2cs[i] != NULL) { + kfree(pool->base.sw_i2cs[i]); + pool->base.sw_i2cs[i] = NULL; + } + } + + for (i = 0; i < pool->base.audio_count; i++) { + if (pool->base.audios[i]) + dce_aud_destroy(&pool->base.audios[i]); + } + + for (i = 0; i < pool->base.stream_enc_count; i++) { + if (pool->base.stream_enc[i] != NULL) + kfree(DCE110STRENC_FROM_STRENC(pool->base.stream_enc[i])); + } + + for (i = 0; i < pool->base.clk_src_count; i++) { + if (pool->base.clock_sources[i] != NULL) + dce120_clock_source_destroy( + &pool->base.clock_sources[i]); + } + + if (pool->base.dp_clock_source != NULL) + dce120_clock_source_destroy(&pool->base.dp_clock_source); + + if (pool->base.abm != NULL) + dce_abm_destroy(&pool->base.abm); + + if (pool->base.dmcu != NULL) + dce_dmcu_destroy(&pool->base.dmcu); +} + +static void read_dce_straps( + struct dc_context *ctx, + struct resource_straps *straps) +{ + uint32_t reg_val = dm_read_reg_soc15(ctx, mmCC_DC_MISC_STRAPS, 0); + + straps->audio_stream_number = get_reg_field_value(reg_val, + CC_DC_MISC_STRAPS, + AUDIO_STREAM_NUMBER); + straps->hdmi_disable = get_reg_field_value(reg_val, + CC_DC_MISC_STRAPS, + HDMI_DISABLE); + + reg_val = dm_read_reg_soc15(ctx, mmDC_PINSTRAPS, 0); + straps->dc_pinstraps_audio = get_reg_field_value(reg_val, + DC_PINSTRAPS, + DC_PINSTRAPS_AUDIO); +} + +static struct audio *create_audio( + struct dc_context *ctx, unsigned int inst) +{ + return dce_audio_create(ctx, inst, + &audio_regs[inst], &audio_shift, &audio_mask); +} + +static const struct encoder_feature_support link_enc_feature = { + .max_hdmi_deep_color = COLOR_DEPTH_121212, + .max_hdmi_pixel_clock = 600000, + .hdmi_ycbcr420_supported = true, + .dp_ycbcr420_supported = false, + .flags.bits.IS_HBR2_CAPABLE = true, + .flags.bits.IS_HBR3_CAPABLE = true, + .flags.bits.IS_TPS3_CAPABLE = true, + .flags.bits.IS_TPS4_CAPABLE = true, +}; + +static struct link_encoder *dce120_link_encoder_create( + struct dc_context *ctx, + const struct encoder_init_data *enc_init_data) +{ + struct dce110_link_encoder *enc110 = + kzalloc(sizeof(struct dce110_link_encoder), GFP_KERNEL); + int link_regs_id; + + if (!enc110) + return NULL; + + link_regs_id = + map_transmitter_id_to_phy_instance(enc_init_data->transmitter); + + dce110_link_encoder_construct(enc110, + enc_init_data, + &link_enc_feature, + &link_enc_regs[link_regs_id], + &link_enc_aux_regs[enc_init_data->channel - 1], + &link_enc_hpd_regs[enc_init_data->hpd_source]); + + return &enc110->base; +} + +static struct panel_cntl *dce120_panel_cntl_create(const struct panel_cntl_init_data *init_data) +{ + struct dce_panel_cntl *panel_cntl = + kzalloc(sizeof(struct dce_panel_cntl), GFP_KERNEL); + + if (!panel_cntl) + return NULL; + + dce_panel_cntl_construct(panel_cntl, + init_data, + &panel_cntl_regs[init_data->inst], + &panel_cntl_shift, + &panel_cntl_mask); + + return &panel_cntl->base; +} + +static struct input_pixel_processor *dce120_ipp_create( + struct dc_context *ctx, uint32_t inst) +{ + struct dce_ipp *ipp = kzalloc(sizeof(struct dce_ipp), GFP_KERNEL); + + if (!ipp) { + BREAK_TO_DEBUGGER(); + return NULL; + } + + dce_ipp_construct(ipp, ctx, inst, + &ipp_regs[inst], &ipp_shift, &ipp_mask); + return &ipp->base; +} + +static struct stream_encoder *dce120_stream_encoder_create( + enum engine_id eng_id, + struct dc_context *ctx) +{ + struct dce110_stream_encoder *enc110 = + kzalloc(sizeof(struct dce110_stream_encoder), GFP_KERNEL); + + if (!enc110) + return NULL; + + dce110_stream_encoder_construct(enc110, ctx, ctx->dc_bios, eng_id, + &stream_enc_regs[eng_id], + &se_shift, &se_mask); + return &enc110->base; +} + +#define SRII(reg_name, block, id)\ + .reg_name[id] = BASE(mm ## block ## id ## _ ## reg_name ## _BASE_IDX) + \ + mm ## block ## id ## _ ## reg_name + +static const struct dce_hwseq_registers hwseq_reg = { + HWSEQ_DCE120_REG_LIST() +}; + +static const struct dce_hwseq_shift hwseq_shift = { + HWSEQ_DCE12_MASK_SH_LIST(__SHIFT) +}; + +static const struct dce_hwseq_mask hwseq_mask = { + HWSEQ_DCE12_MASK_SH_LIST(_MASK) +}; + +/* HWSEQ regs for VG20 */ +static const struct dce_hwseq_registers dce121_hwseq_reg = { + HWSEQ_VG20_REG_LIST() +}; + +static const struct dce_hwseq_shift dce121_hwseq_shift = { + HWSEQ_VG20_MASK_SH_LIST(__SHIFT) +}; + +static const struct dce_hwseq_mask dce121_hwseq_mask = { + HWSEQ_VG20_MASK_SH_LIST(_MASK) +}; + +static struct dce_hwseq *dce120_hwseq_create( + struct dc_context *ctx) +{ + struct dce_hwseq *hws = kzalloc(sizeof(struct dce_hwseq), GFP_KERNEL); + + if (hws) { + hws->ctx = ctx; + hws->regs = &hwseq_reg; + hws->shifts = &hwseq_shift; + hws->masks = &hwseq_mask; + } + return hws; +} + +static struct dce_hwseq *dce121_hwseq_create( + struct dc_context *ctx) +{ + struct dce_hwseq *hws = kzalloc(sizeof(struct dce_hwseq), GFP_KERNEL); + + if (hws) { + hws->ctx = ctx; + hws->regs = &dce121_hwseq_reg; + hws->shifts = &dce121_hwseq_shift; + hws->masks = &dce121_hwseq_mask; + } + return hws; +} + +static const struct resource_create_funcs res_create_funcs = { + .read_dce_straps = read_dce_straps, + .create_audio = create_audio, + .create_stream_encoder = dce120_stream_encoder_create, + .create_hwseq = dce120_hwseq_create, +}; + +static const struct resource_create_funcs dce121_res_create_funcs = { + .read_dce_straps = read_dce_straps, + .create_audio = create_audio, + .create_stream_encoder = dce120_stream_encoder_create, + .create_hwseq = dce121_hwseq_create, +}; + + +#define mi_inst_regs(id) { MI_DCE12_REG_LIST(id) } +static const struct dce_mem_input_registers mi_regs[] = { + mi_inst_regs(0), + mi_inst_regs(1), + mi_inst_regs(2), + mi_inst_regs(3), + mi_inst_regs(4), + mi_inst_regs(5), +}; + +static const struct dce_mem_input_shift mi_shifts = { + MI_DCE12_MASK_SH_LIST(__SHIFT) +}; + +static const struct dce_mem_input_mask mi_masks = { + MI_DCE12_MASK_SH_LIST(_MASK) +}; + +static struct mem_input *dce120_mem_input_create( + struct dc_context *ctx, + uint32_t inst) +{ + struct dce_mem_input *dce_mi = kzalloc(sizeof(struct dce_mem_input), + GFP_KERNEL); + + if (!dce_mi) { + BREAK_TO_DEBUGGER(); + return NULL; + } + + dce120_mem_input_construct(dce_mi, ctx, inst, &mi_regs[inst], &mi_shifts, &mi_masks); + return &dce_mi->base; +} + +static struct transform *dce120_transform_create( + struct dc_context *ctx, + uint32_t inst) +{ + struct dce_transform *transform = + kzalloc(sizeof(struct dce_transform), GFP_KERNEL); + + if (!transform) + return NULL; + + dce_transform_construct(transform, ctx, inst, + &xfm_regs[inst], &xfm_shift, &xfm_mask); + transform->lb_memory_size = 0x1404; /*5124*/ + return &transform->base; +} + +static void dce120_destroy_resource_pool(struct resource_pool **pool) +{ + struct dce110_resource_pool *dce110_pool = TO_DCE110_RES_POOL(*pool); + + dce120_resource_destruct(dce110_pool); + kfree(dce110_pool); + *pool = NULL; +} + +static const struct resource_funcs dce120_res_pool_funcs = { + .destroy = dce120_destroy_resource_pool, + .link_enc_create = dce120_link_encoder_create, + .panel_cntl_create = dce120_panel_cntl_create, + .validate_bandwidth = dce112_validate_bandwidth, + .validate_plane = dce100_validate_plane, + .add_stream_to_ctx = dce112_add_stream_to_ctx, + .find_first_free_match_stream_enc_for_link = dce110_find_first_free_match_stream_enc_for_link +}; + +static void bw_calcs_data_update_from_pplib(struct dc *dc) +{ + struct dm_pp_clock_levels_with_latency eng_clks = {0}; + struct dm_pp_clock_levels_with_latency mem_clks = {0}; + struct dm_pp_wm_sets_with_clock_ranges clk_ranges = {0}; + int i; + unsigned int clk; + unsigned int latency; + /*original logic in dal3*/ + int memory_type_multiplier = MEMORY_TYPE_MULTIPLIER_CZ; + + /*do system clock*/ + if (!dm_pp_get_clock_levels_by_type_with_latency( + dc->ctx, + DM_PP_CLOCK_TYPE_ENGINE_CLK, + &eng_clks) || eng_clks.num_levels == 0) { + + eng_clks.num_levels = 8; + clk = 300000; + + for (i = 0; i < eng_clks.num_levels; i++) { + eng_clks.data[i].clocks_in_khz = clk; + clk += 100000; + } + } + + /* convert all the clock fro kHz to fix point mHz TODO: wloop data */ + dc->bw_vbios->high_sclk = bw_frc_to_fixed( + eng_clks.data[eng_clks.num_levels-1].clocks_in_khz, 1000); + dc->bw_vbios->mid1_sclk = bw_frc_to_fixed( + eng_clks.data[eng_clks.num_levels/8].clocks_in_khz, 1000); + dc->bw_vbios->mid2_sclk = bw_frc_to_fixed( + eng_clks.data[eng_clks.num_levels*2/8].clocks_in_khz, 1000); + dc->bw_vbios->mid3_sclk = bw_frc_to_fixed( + eng_clks.data[eng_clks.num_levels*3/8].clocks_in_khz, 1000); + dc->bw_vbios->mid4_sclk = bw_frc_to_fixed( + eng_clks.data[eng_clks.num_levels*4/8].clocks_in_khz, 1000); + dc->bw_vbios->mid5_sclk = bw_frc_to_fixed( + eng_clks.data[eng_clks.num_levels*5/8].clocks_in_khz, 1000); + dc->bw_vbios->mid6_sclk = bw_frc_to_fixed( + eng_clks.data[eng_clks.num_levels*6/8].clocks_in_khz, 1000); + dc->bw_vbios->low_sclk = bw_frc_to_fixed( + eng_clks.data[0].clocks_in_khz, 1000); + + /*do memory clock*/ + if (!dm_pp_get_clock_levels_by_type_with_latency( + dc->ctx, + DM_PP_CLOCK_TYPE_MEMORY_CLK, + &mem_clks) || mem_clks.num_levels == 0) { + + mem_clks.num_levels = 3; + clk = 250000; + latency = 45; + + for (i = 0; i < eng_clks.num_levels; i++) { + mem_clks.data[i].clocks_in_khz = clk; + mem_clks.data[i].latency_in_us = latency; + clk += 500000; + latency -= 5; + } + + } + + /* we don't need to call PPLIB for validation clock since they + * also give us the highest sclk and highest mclk (UMA clock). + * ALSO always convert UMA clock (from PPLIB) to YCLK (HW formula): + * YCLK = UMACLK*m_memoryTypeMultiplier + */ + if (dc->bw_vbios->memory_type == bw_def_hbm) + memory_type_multiplier = MEMORY_TYPE_HBM; + + dc->bw_vbios->low_yclk = bw_frc_to_fixed( + mem_clks.data[0].clocks_in_khz * memory_type_multiplier, 1000); + dc->bw_vbios->mid_yclk = bw_frc_to_fixed( + mem_clks.data[mem_clks.num_levels>>1].clocks_in_khz * memory_type_multiplier, + 1000); + dc->bw_vbios->high_yclk = bw_frc_to_fixed( + mem_clks.data[mem_clks.num_levels-1].clocks_in_khz * memory_type_multiplier, + 1000); + + /* Now notify PPLib/SMU about which Watermarks sets they should select + * depending on DPM state they are in. And update BW MGR GFX Engine and + * Memory clock member variables for Watermarks calculations for each + * Watermark Set + */ + clk_ranges.num_wm_sets = 4; + clk_ranges.wm_clk_ranges[0].wm_set_id = WM_SET_A; + clk_ranges.wm_clk_ranges[0].wm_min_eng_clk_in_khz = + eng_clks.data[0].clocks_in_khz; + clk_ranges.wm_clk_ranges[0].wm_max_eng_clk_in_khz = + eng_clks.data[eng_clks.num_levels*3/8].clocks_in_khz - 1; + clk_ranges.wm_clk_ranges[0].wm_min_mem_clk_in_khz = + mem_clks.data[0].clocks_in_khz; + clk_ranges.wm_clk_ranges[0].wm_max_mem_clk_in_khz = + mem_clks.data[mem_clks.num_levels>>1].clocks_in_khz - 1; + + clk_ranges.wm_clk_ranges[1].wm_set_id = WM_SET_B; + clk_ranges.wm_clk_ranges[1].wm_min_eng_clk_in_khz = + eng_clks.data[eng_clks.num_levels*3/8].clocks_in_khz; + /* 5 GHz instead of data[7].clockInKHz to cover Overdrive */ + clk_ranges.wm_clk_ranges[1].wm_max_eng_clk_in_khz = 5000000; + clk_ranges.wm_clk_ranges[1].wm_min_mem_clk_in_khz = + mem_clks.data[0].clocks_in_khz; + clk_ranges.wm_clk_ranges[1].wm_max_mem_clk_in_khz = + mem_clks.data[mem_clks.num_levels>>1].clocks_in_khz - 1; + + clk_ranges.wm_clk_ranges[2].wm_set_id = WM_SET_C; + clk_ranges.wm_clk_ranges[2].wm_min_eng_clk_in_khz = + eng_clks.data[0].clocks_in_khz; + clk_ranges.wm_clk_ranges[2].wm_max_eng_clk_in_khz = + eng_clks.data[eng_clks.num_levels*3/8].clocks_in_khz - 1; + clk_ranges.wm_clk_ranges[2].wm_min_mem_clk_in_khz = + mem_clks.data[mem_clks.num_levels>>1].clocks_in_khz; + /* 5 GHz instead of data[2].clockInKHz to cover Overdrive */ + clk_ranges.wm_clk_ranges[2].wm_max_mem_clk_in_khz = 5000000; + + clk_ranges.wm_clk_ranges[3].wm_set_id = WM_SET_D; + clk_ranges.wm_clk_ranges[3].wm_min_eng_clk_in_khz = + eng_clks.data[eng_clks.num_levels*3/8].clocks_in_khz; + /* 5 GHz instead of data[7].clockInKHz to cover Overdrive */ + clk_ranges.wm_clk_ranges[3].wm_max_eng_clk_in_khz = 5000000; + clk_ranges.wm_clk_ranges[3].wm_min_mem_clk_in_khz = + mem_clks.data[mem_clks.num_levels>>1].clocks_in_khz; + /* 5 GHz instead of data[2].clockInKHz to cover Overdrive */ + clk_ranges.wm_clk_ranges[3].wm_max_mem_clk_in_khz = 5000000; + + /* Notify PP Lib/SMU which Watermarks to use for which clock ranges */ + dm_pp_notify_wm_clock_changes(dc->ctx, &clk_ranges); +} + +static uint32_t read_pipe_fuses(struct dc_context *ctx) +{ + uint32_t value = dm_read_reg_soc15(ctx, mmCC_DC_PIPE_DIS, 0); + /* VG20 support max 6 pipes */ + value = value & 0x3f; + return value; +} + +static bool dce120_resource_construct( + uint8_t num_virtual_links, + struct dc *dc, + struct dce110_resource_pool *pool) +{ + unsigned int i; + int j; + struct dc_context *ctx = dc->ctx; + struct irq_service_init_data irq_init_data; + static const struct resource_create_funcs *res_funcs; + bool is_vg20 = ASICREV_IS_VEGA20_P(ctx->asic_id.hw_internal_rev); + uint32_t pipe_fuses; + + ctx->dc_bios->regs = &bios_regs; + + pool->base.res_cap = &res_cap; + pool->base.funcs = &dce120_res_pool_funcs; + + /* TODO: Fill more data from GreenlandAsicCapability.cpp */ + pool->base.pipe_count = res_cap.num_timing_generator; + pool->base.timing_generator_count = pool->base.res_cap->num_timing_generator; + pool->base.underlay_pipe_index = NO_UNDERLAY_PIPE; + + dc->caps.max_downscale_ratio = 200; + dc->caps.i2c_speed_in_khz = 100; + dc->caps.i2c_speed_in_khz_hdcp = 100; /*1.4 w/a not applied by default*/ + dc->caps.max_cursor_size = 128; + dc->caps.min_horizontal_blanking_period = 80; + dc->caps.dual_link_dvi = true; + dc->caps.psp_setup_panel_mode = true; + dc->caps.extended_aux_timeout_support = false; + dc->debug = debug_defaults; + + /************************************************* + * Create resources * + *************************************************/ + + pool->base.clock_sources[DCE120_CLK_SRC_PLL0] = + dce120_clock_source_create(ctx, ctx->dc_bios, + CLOCK_SOURCE_COMBO_PHY_PLL0, + &clk_src_regs[0], false); + pool->base.clock_sources[DCE120_CLK_SRC_PLL1] = + dce120_clock_source_create(ctx, ctx->dc_bios, + CLOCK_SOURCE_COMBO_PHY_PLL1, + &clk_src_regs[1], false); + pool->base.clock_sources[DCE120_CLK_SRC_PLL2] = + dce120_clock_source_create(ctx, ctx->dc_bios, + CLOCK_SOURCE_COMBO_PHY_PLL2, + &clk_src_regs[2], false); + pool->base.clock_sources[DCE120_CLK_SRC_PLL3] = + dce120_clock_source_create(ctx, ctx->dc_bios, + CLOCK_SOURCE_COMBO_PHY_PLL3, + &clk_src_regs[3], false); + pool->base.clock_sources[DCE120_CLK_SRC_PLL4] = + dce120_clock_source_create(ctx, ctx->dc_bios, + CLOCK_SOURCE_COMBO_PHY_PLL4, + &clk_src_regs[4], false); + pool->base.clock_sources[DCE120_CLK_SRC_PLL5] = + dce120_clock_source_create(ctx, ctx->dc_bios, + CLOCK_SOURCE_COMBO_PHY_PLL5, + &clk_src_regs[5], false); + pool->base.clk_src_count = DCE120_CLK_SRC_TOTAL; + + pool->base.dp_clock_source = + dce120_clock_source_create(ctx, ctx->dc_bios, + CLOCK_SOURCE_ID_DP_DTO, + &clk_src_regs[0], true); + + for (i = 0; i < pool->base.clk_src_count; i++) { + if (pool->base.clock_sources[i] == NULL) { + dm_error("DC: failed to create clock sources!\n"); + BREAK_TO_DEBUGGER(); + goto clk_src_create_fail; + } + } + + pool->base.dmcu = dce_dmcu_create(ctx, + &dmcu_regs, + &dmcu_shift, + &dmcu_mask); + if (pool->base.dmcu == NULL) { + dm_error("DC: failed to create dmcu!\n"); + BREAK_TO_DEBUGGER(); + goto res_create_fail; + } + + pool->base.abm = dce_abm_create(ctx, + &abm_regs, + &abm_shift, + &abm_mask); + if (pool->base.abm == NULL) { + dm_error("DC: failed to create abm!\n"); + BREAK_TO_DEBUGGER(); + goto res_create_fail; + } + + + irq_init_data.ctx = dc->ctx; + pool->base.irqs = dal_irq_service_dce120_create(&irq_init_data); + if (!pool->base.irqs) + goto irqs_create_fail; + + /* VG20: Pipe harvesting enabled, retrieve valid pipe fuses */ + if (is_vg20) + pipe_fuses = read_pipe_fuses(ctx); + + /* index to valid pipe resource */ + j = 0; + for (i = 0; i < pool->base.pipe_count; i++) { + if (is_vg20) { + if ((pipe_fuses & (1 << i)) != 0) { + dm_error("DC: skip invalid pipe %d!\n", i); + continue; + } + } + + pool->base.timing_generators[j] = + dce120_timing_generator_create( + ctx, + i, + &dce120_tg_offsets[i]); + if (pool->base.timing_generators[j] == NULL) { + BREAK_TO_DEBUGGER(); + dm_error("DC: failed to create tg!\n"); + goto controller_create_fail; + } + + pool->base.mis[j] = dce120_mem_input_create(ctx, i); + + if (pool->base.mis[j] == NULL) { + BREAK_TO_DEBUGGER(); + dm_error( + "DC: failed to create memory input!\n"); + goto controller_create_fail; + } + + pool->base.ipps[j] = dce120_ipp_create(ctx, i); + if (pool->base.ipps[i] == NULL) { + BREAK_TO_DEBUGGER(); + dm_error( + "DC: failed to create input pixel processor!\n"); + goto controller_create_fail; + } + + pool->base.transforms[j] = dce120_transform_create(ctx, i); + if (pool->base.transforms[i] == NULL) { + BREAK_TO_DEBUGGER(); + dm_error( + "DC: failed to create transform!\n"); + goto res_create_fail; + } + + pool->base.opps[j] = dce120_opp_create( + ctx, + i); + if (pool->base.opps[j] == NULL) { + BREAK_TO_DEBUGGER(); + dm_error( + "DC: failed to create output pixel processor!\n"); + } + + /* check next valid pipe */ + j++; + } + + for (i = 0; i < pool->base.res_cap->num_ddc; i++) { + pool->base.engines[i] = dce120_aux_engine_create(ctx, i); + if (pool->base.engines[i] == NULL) { + BREAK_TO_DEBUGGER(); + dm_error( + "DC:failed to create aux engine!!\n"); + goto res_create_fail; + } + pool->base.hw_i2cs[i] = dce120_i2c_hw_create(ctx, i); + if (pool->base.hw_i2cs[i] == NULL) { + BREAK_TO_DEBUGGER(); + dm_error( + "DC:failed to create i2c engine!!\n"); + goto res_create_fail; + } + pool->base.sw_i2cs[i] = NULL; + } + + /* valid pipe num */ + pool->base.pipe_count = j; + pool->base.timing_generator_count = j; + + if (is_vg20) + res_funcs = &dce121_res_create_funcs; + else + res_funcs = &res_create_funcs; + + if (!resource_construct(num_virtual_links, dc, &pool->base, res_funcs)) + goto res_create_fail; + + /* Create hardware sequencer */ + if (!dce120_hw_sequencer_create(dc)) + goto controller_create_fail; + + dc->caps.max_planes = pool->base.pipe_count; + + for (i = 0; i < dc->caps.max_planes; ++i) + dc->caps.planes[i] = plane_cap; + + bw_calcs_init(dc->bw_dceip, dc->bw_vbios, dc->ctx->asic_id); + + bw_calcs_data_update_from_pplib(dc); + + return true; + +irqs_create_fail: +controller_create_fail: +clk_src_create_fail: +res_create_fail: + + dce120_resource_destruct(pool); + + return false; +} + +struct resource_pool *dce120_create_resource_pool( + uint8_t num_virtual_links, + struct dc *dc) +{ + struct dce110_resource_pool *pool = + kzalloc(sizeof(struct dce110_resource_pool), GFP_KERNEL); + + if (!pool) + return NULL; + + if (dce120_resource_construct(num_virtual_links, dc, pool)) + return &pool->base; + + kfree(pool); + BREAK_TO_DEBUGGER(); + return NULL; +} diff --git a/drivers/gpu/drm/amd/display/dc/resource/dce120/dce120_resource.h b/drivers/gpu/drm/amd/display/dc/resource/dce120/dce120_resource.h new file mode 100644 index 000000000000..3d1f3cf012f4 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/resource/dce120/dce120_resource.h @@ -0,0 +1,39 @@ +/* +* Copyright 2012-15 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_RESOURCE_DCE120_H__ +#define __DC_RESOURCE_DCE120_H__ + +#include "core_types.h" + +struct dc; +struct resource_pool; + +struct resource_pool *dce120_create_resource_pool( + uint8_t num_virtual_links, + struct dc *dc); + +#endif /* __DC_RESOURCE_DCE120_H__ */ + diff --git a/drivers/gpu/drm/amd/display/dc/resource/dce80/CMakeLists.txt b/drivers/gpu/drm/amd/display/dc/resource/dce80/CMakeLists.txt new file mode 100644 index 000000000000..19dd73bc9ab0 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/resource/dce80/CMakeLists.txt @@ -0,0 +1,4 @@ +dal3_subdirectory_sources( + dce80_resource.c + dce80_resource.h + ) \ No newline at end of file diff --git a/drivers/gpu/drm/amd/display/dc/resource/dce80/dce80_resource.c b/drivers/gpu/drm/amd/display/dc/resource/dce80/dce80_resource.c new file mode 100644 index 000000000000..35a2cce0c2b8 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/resource/dce80/dce80_resource.c @@ -0,0 +1,1544 @@ +/* + * Copyright 2012-15 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_8_0_d.h" +#include "dce/dce_8_0_sh_mask.h" + +#include "dm_services.h" + +#include "link_encoder.h" +#include "stream_encoder.h" + +#include "resource.h" +#include "include/irq_service_interface.h" +#include "irq/dce80/irq_service_dce80.h" +#include "dce110/dce110_timing_generator.h" +#include "dce110/dce110_resource.h" +#include "dce80/dce80_timing_generator.h" +#include "dce/dce_mem_input.h" +#include "dce/dce_link_encoder.h" +#include "dce/dce_stream_encoder.h" +#include "dce/dce_ipp.h" +#include "dce/dce_transform.h" +#include "dce/dce_opp.h" +#include "dce/dce_clock_source.h" +#include "dce/dce_audio.h" +#include "dce/dce_hwseq.h" +#include "dce80/dce80_hwseq.h" +#include "dce100/dce100_resource.h" +#include "dce/dce_panel_cntl.h" + +#include "reg_helper.h" + +#include "dce/dce_dmcu.h" +#include "dce/dce_aux.h" +#include "dce/dce_abm.h" +#include "dce/dce_i2c.h" +/* TODO remove this include */ + +#ifndef mmMC_HUB_RDREQ_DMIF_LIMIT +#include "gmc/gmc_7_1_d.h" +#include "gmc/gmc_7_1_sh_mask.h" +#endif + +#include "dce80/dce80_resource.h" + +#ifndef mmDP_DPHY_INTERNAL_CTRL +#define mmDP_DPHY_INTERNAL_CTRL 0x1CDE +#define mmDP0_DP_DPHY_INTERNAL_CTRL 0x1CDE +#define mmDP1_DP_DPHY_INTERNAL_CTRL 0x1FDE +#define mmDP2_DP_DPHY_INTERNAL_CTRL 0x42DE +#define mmDP3_DP_DPHY_INTERNAL_CTRL 0x45DE +#define mmDP4_DP_DPHY_INTERNAL_CTRL 0x48DE +#define mmDP5_DP_DPHY_INTERNAL_CTRL 0x4BDE +#define mmDP6_DP_DPHY_INTERNAL_CTRL 0x4EDE +#endif + + +#ifndef mmBIOS_SCRATCH_2 + #define mmBIOS_SCRATCH_2 0x05CB + #define mmBIOS_SCRATCH_3 0x05CC + #define mmBIOS_SCRATCH_6 0x05CF +#endif + +#ifndef mmDP_DPHY_FAST_TRAINING + #define mmDP_DPHY_FAST_TRAINING 0x1CCE + #define mmDP0_DP_DPHY_FAST_TRAINING 0x1CCE + #define mmDP1_DP_DPHY_FAST_TRAINING 0x1FCE + #define mmDP2_DP_DPHY_FAST_TRAINING 0x42CE + #define mmDP3_DP_DPHY_FAST_TRAINING 0x45CE + #define mmDP4_DP_DPHY_FAST_TRAINING 0x48CE + #define mmDP5_DP_DPHY_FAST_TRAINING 0x4BCE + #define mmDP6_DP_DPHY_FAST_TRAINING 0x4ECE +#endif + + +#ifndef mmHPD_DC_HPD_CONTROL + #define mmHPD_DC_HPD_CONTROL 0x189A + #define mmHPD0_DC_HPD_CONTROL 0x189A + #define mmHPD1_DC_HPD_CONTROL 0x18A2 + #define mmHPD2_DC_HPD_CONTROL 0x18AA + #define mmHPD3_DC_HPD_CONTROL 0x18B2 + #define mmHPD4_DC_HPD_CONTROL 0x18BA + #define mmHPD5_DC_HPD_CONTROL 0x18C2 +#endif + +#define DCE11_DIG_FE_CNTL 0x4a00 +#define DCE11_DIG_BE_CNTL 0x4a47 +#define DCE11_DP_SEC 0x4ac3 + +static const struct dce110_timing_generator_offsets dce80_tg_offsets[] = { + { + .crtc = (mmCRTC0_CRTC_CONTROL - mmCRTC_CONTROL), + .dcp = (mmGRPH_CONTROL - mmGRPH_CONTROL), + .dmif = (mmDMIF_PG0_DPG_WATERMARK_MASK_CONTROL + - mmDPG_WATERMARK_MASK_CONTROL), + }, + { + .crtc = (mmCRTC1_CRTC_CONTROL - mmCRTC_CONTROL), + .dcp = (mmDCP1_GRPH_CONTROL - mmGRPH_CONTROL), + .dmif = (mmDMIF_PG1_DPG_WATERMARK_MASK_CONTROL + - mmDPG_WATERMARK_MASK_CONTROL), + }, + { + .crtc = (mmCRTC2_CRTC_CONTROL - mmCRTC_CONTROL), + .dcp = (mmDCP2_GRPH_CONTROL - mmGRPH_CONTROL), + .dmif = (mmDMIF_PG2_DPG_WATERMARK_MASK_CONTROL + - mmDPG_WATERMARK_MASK_CONTROL), + }, + { + .crtc = (mmCRTC3_CRTC_CONTROL - mmCRTC_CONTROL), + .dcp = (mmDCP3_GRPH_CONTROL - mmGRPH_CONTROL), + .dmif = (mmDMIF_PG3_DPG_WATERMARK_MASK_CONTROL + - mmDPG_WATERMARK_MASK_CONTROL), + }, + { + .crtc = (mmCRTC4_CRTC_CONTROL - mmCRTC_CONTROL), + .dcp = (mmDCP4_GRPH_CONTROL - mmGRPH_CONTROL), + .dmif = (mmDMIF_PG4_DPG_WATERMARK_MASK_CONTROL + - mmDPG_WATERMARK_MASK_CONTROL), + }, + { + .crtc = (mmCRTC5_CRTC_CONTROL - mmCRTC_CONTROL), + .dcp = (mmDCP5_GRPH_CONTROL - mmGRPH_CONTROL), + .dmif = (mmDMIF_PG5_DPG_WATERMARK_MASK_CONTROL + - mmDPG_WATERMARK_MASK_CONTROL), + } +}; + +/* set register offset */ +#define SR(reg_name)\ + .reg_name = mm ## reg_name + +/* set register offset with instance */ +#define SRI(reg_name, block, id)\ + .reg_name = mm ## block ## id ## _ ## reg_name + +#define ipp_regs(id)\ +[id] = {\ + IPP_COMMON_REG_LIST_DCE_BASE(id)\ +} + +static const struct dce_ipp_registers ipp_regs[] = { + ipp_regs(0), + ipp_regs(1), + ipp_regs(2), + ipp_regs(3), + ipp_regs(4), + ipp_regs(5) +}; + +static const struct dce_ipp_shift ipp_shift = { + IPP_COMMON_MASK_SH_LIST_DCE_COMMON_BASE(__SHIFT) +}; + +static const struct dce_ipp_mask ipp_mask = { + IPP_COMMON_MASK_SH_LIST_DCE_COMMON_BASE(_MASK) +}; + +#define transform_regs(id)\ +[id] = {\ + XFM_COMMON_REG_LIST_DCE80(id)\ +} + +static const struct dce_transform_registers xfm_regs[] = { + transform_regs(0), + transform_regs(1), + transform_regs(2), + transform_regs(3), + transform_regs(4), + transform_regs(5) +}; + +static const struct dce_transform_shift xfm_shift = { + XFM_COMMON_MASK_SH_LIST_DCE80(__SHIFT) +}; + +static const struct dce_transform_mask xfm_mask = { + XFM_COMMON_MASK_SH_LIST_DCE80(_MASK) +}; + +#define aux_regs(id)\ +[id] = {\ + AUX_REG_LIST(id)\ +} + +static const struct dce110_link_enc_aux_registers link_enc_aux_regs[] = { + aux_regs(0), + aux_regs(1), + aux_regs(2), + aux_regs(3), + aux_regs(4), + aux_regs(5) +}; + +#define hpd_regs(id)\ +[id] = {\ + HPD_REG_LIST(id)\ +} + +static const struct dce110_link_enc_hpd_registers link_enc_hpd_regs[] = { + hpd_regs(0), + hpd_regs(1), + hpd_regs(2), + hpd_regs(3), + hpd_regs(4), + hpd_regs(5) +}; + +#define link_regs(id)\ +[id] = {\ + LE_DCE80_REG_LIST(id)\ +} + +static const struct dce110_link_enc_registers link_enc_regs[] = { + link_regs(0), + link_regs(1), + link_regs(2), + link_regs(3), + link_regs(4), + link_regs(5), + link_regs(6), +}; + +#define stream_enc_regs(id)\ +[id] = {\ + SE_COMMON_REG_LIST_DCE_BASE(id),\ + .AFMT_CNTL = 0,\ +} + +static const struct dce110_stream_enc_registers stream_enc_regs[] = { + stream_enc_regs(0), + stream_enc_regs(1), + stream_enc_regs(2), + stream_enc_regs(3), + stream_enc_regs(4), + stream_enc_regs(5), + stream_enc_regs(6) +}; + +static const struct dce_stream_encoder_shift se_shift = { + SE_COMMON_MASK_SH_LIST_DCE80_100(__SHIFT) +}; + +static const struct dce_stream_encoder_mask se_mask = { + SE_COMMON_MASK_SH_LIST_DCE80_100(_MASK) +}; + +static const struct dce_panel_cntl_registers panel_cntl_regs[] = { + { DCE_PANEL_CNTL_REG_LIST() } +}; + +static const struct dce_panel_cntl_shift panel_cntl_shift = { + DCE_PANEL_CNTL_MASK_SH_LIST(__SHIFT) +}; + +static const struct dce_panel_cntl_mask panel_cntl_mask = { + DCE_PANEL_CNTL_MASK_SH_LIST(_MASK) +}; + +#define opp_regs(id)\ +[id] = {\ + OPP_DCE_80_REG_LIST(id),\ +} + +static const struct dce_opp_registers opp_regs[] = { + opp_regs(0), + opp_regs(1), + opp_regs(2), + opp_regs(3), + opp_regs(4), + opp_regs(5) +}; + +static const struct dce_opp_shift opp_shift = { + OPP_COMMON_MASK_SH_LIST_DCE_80(__SHIFT) +}; + +static const struct dce_opp_mask opp_mask = { + OPP_COMMON_MASK_SH_LIST_DCE_80(_MASK) +}; + +static const struct dce110_aux_registers_shift aux_shift = { + DCE10_AUX_MASK_SH_LIST(__SHIFT) +}; + +static const struct dce110_aux_registers_mask aux_mask = { + DCE10_AUX_MASK_SH_LIST(_MASK) +}; + +#define aux_engine_regs(id)\ +[id] = {\ + AUX_COMMON_REG_LIST(id), \ + .AUX_RESET_MASK = 0 \ +} + +static const struct dce110_aux_registers aux_engine_regs[] = { + aux_engine_regs(0), + aux_engine_regs(1), + aux_engine_regs(2), + aux_engine_regs(3), + aux_engine_regs(4), + aux_engine_regs(5) +}; + +#define audio_regs(id)\ +[id] = {\ + AUD_COMMON_REG_LIST(id)\ +} + +static const struct dce_audio_registers audio_regs[] = { + audio_regs(0), + audio_regs(1), + audio_regs(2), + audio_regs(3), + audio_regs(4), + audio_regs(5), + audio_regs(6), +}; + +static const struct dce_audio_shift audio_shift = { + AUD_COMMON_MASK_SH_LIST(__SHIFT) +}; + +static const struct dce_audio_mask audio_mask = { + AUD_COMMON_MASK_SH_LIST(_MASK) +}; + +#define clk_src_regs(id)\ +[id] = {\ + CS_COMMON_REG_LIST_DCE_80(id),\ +} + + +static const struct dce110_clk_src_regs clk_src_regs[] = { + clk_src_regs(0), + clk_src_regs(1), + clk_src_regs(2) +}; + +static const struct dce110_clk_src_shift cs_shift = { + CS_COMMON_MASK_SH_LIST_DCE_COMMON_BASE(__SHIFT) +}; + +static const struct dce110_clk_src_mask cs_mask = { + CS_COMMON_MASK_SH_LIST_DCE_COMMON_BASE(_MASK) +}; + +static const struct bios_registers bios_regs = { + .BIOS_SCRATCH_3 = mmBIOS_SCRATCH_3, + .BIOS_SCRATCH_6 = mmBIOS_SCRATCH_6 +}; + +static const struct resource_caps res_cap = { + .num_timing_generator = 6, + .num_audio = 6, + .num_stream_encoder = 6, + .num_pll = 3, + .num_ddc = 6, +}; + +static const struct resource_caps res_cap_81 = { + .num_timing_generator = 4, + .num_audio = 7, + .num_stream_encoder = 7, + .num_pll = 3, + .num_ddc = 6, +}; + +static const struct resource_caps res_cap_83 = { + .num_timing_generator = 2, + .num_audio = 6, + .num_stream_encoder = 6, + .num_pll = 2, + .num_ddc = 2, +}; + +static const struct dc_plane_cap plane_cap = { + .type = DC_PLANE_TYPE_DCE_RGB, + + .pixel_format_support = { + .argb8888 = true, + .nv12 = false, + .fp16 = true + }, + + .max_upscale_factor = { + .argb8888 = 16000, + .nv12 = 1, + .fp16 = 1 + }, + + .max_downscale_factor = { + .argb8888 = 250, + .nv12 = 1, + .fp16 = 1 + } +}; + +static const struct dc_debug_options debug_defaults = { + .enable_legacy_fast_update = true, +}; + +static const struct dce_dmcu_registers dmcu_regs = { + DMCU_DCE80_REG_LIST() +}; + +static const struct dce_dmcu_shift dmcu_shift = { + DMCU_MASK_SH_LIST_DCE80(__SHIFT) +}; + +static const struct dce_dmcu_mask dmcu_mask = { + DMCU_MASK_SH_LIST_DCE80(_MASK) +}; +static const struct dce_abm_registers abm_regs = { + ABM_DCE110_COMMON_REG_LIST() +}; + +static const struct dce_abm_shift abm_shift = { + ABM_MASK_SH_LIST_DCE110(__SHIFT) +}; + +static const struct dce_abm_mask abm_mask = { + ABM_MASK_SH_LIST_DCE110(_MASK) +}; + +#define CTX ctx +#define REG(reg) mm ## reg + +#ifndef mmCC_DC_HDMI_STRAPS +#define mmCC_DC_HDMI_STRAPS 0x1918 +#define CC_DC_HDMI_STRAPS__HDMI_DISABLE_MASK 0x40 +#define CC_DC_HDMI_STRAPS__HDMI_DISABLE__SHIFT 0x6 +#define CC_DC_HDMI_STRAPS__AUDIO_STREAM_NUMBER_MASK 0x700 +#define CC_DC_HDMI_STRAPS__AUDIO_STREAM_NUMBER__SHIFT 0x8 +#endif + +static int map_transmitter_id_to_phy_instance( + enum transmitter transmitter) +{ + switch (transmitter) { + case TRANSMITTER_UNIPHY_A: + return 0; + case TRANSMITTER_UNIPHY_B: + return 1; + case TRANSMITTER_UNIPHY_C: + return 2; + case TRANSMITTER_UNIPHY_D: + return 3; + case TRANSMITTER_UNIPHY_E: + return 4; + case TRANSMITTER_UNIPHY_F: + return 5; + case TRANSMITTER_UNIPHY_G: + return 6; + default: + ASSERT(0); + return 0; + } +} + +static void read_dce_straps( + struct dc_context *ctx, + struct resource_straps *straps) +{ + REG_GET_2(CC_DC_HDMI_STRAPS, + HDMI_DISABLE, &straps->hdmi_disable, + AUDIO_STREAM_NUMBER, &straps->audio_stream_number); + + REG_GET(DC_PINSTRAPS, DC_PINSTRAPS_AUDIO, &straps->dc_pinstraps_audio); +} + +static struct audio *create_audio( + struct dc_context *ctx, unsigned int inst) +{ + return dce_audio_create(ctx, inst, + &audio_regs[inst], &audio_shift, &audio_mask); +} + +static struct timing_generator *dce80_timing_generator_create( + struct dc_context *ctx, + uint32_t instance, + const struct dce110_timing_generator_offsets *offsets) +{ + struct dce110_timing_generator *tg110 = + kzalloc(sizeof(struct dce110_timing_generator), GFP_KERNEL); + + if (!tg110) + return NULL; + + dce80_timing_generator_construct(tg110, ctx, instance, offsets); + return &tg110->base; +} + +static struct output_pixel_processor *dce80_opp_create( + struct dc_context *ctx, + uint32_t inst) +{ + struct dce110_opp *opp = + kzalloc(sizeof(struct dce110_opp), GFP_KERNEL); + + if (!opp) + return NULL; + + dce110_opp_construct(opp, + ctx, inst, &opp_regs[inst], &opp_shift, &opp_mask); + return &opp->base; +} + +static struct dce_aux *dce80_aux_engine_create( + struct dc_context *ctx, + uint32_t inst) +{ + struct aux_engine_dce110 *aux_engine = + kzalloc(sizeof(struct aux_engine_dce110), GFP_KERNEL); + + if (!aux_engine) + return NULL; + + dce110_aux_engine_construct(aux_engine, ctx, inst, + SW_AUX_TIMEOUT_PERIOD_MULTIPLIER * AUX_TIMEOUT_PERIOD, + &aux_engine_regs[inst], + &aux_mask, + &aux_shift, + ctx->dc->caps.extended_aux_timeout_support); + + return &aux_engine->base; +} +#define i2c_inst_regs(id) { I2C_HW_ENGINE_COMMON_REG_LIST(id) } + +static const struct dce_i2c_registers i2c_hw_regs[] = { + i2c_inst_regs(1), + i2c_inst_regs(2), + i2c_inst_regs(3), + i2c_inst_regs(4), + i2c_inst_regs(5), + i2c_inst_regs(6), +}; + +static const struct dce_i2c_shift i2c_shifts = { + I2C_COMMON_MASK_SH_LIST_DCE_COMMON_BASE(__SHIFT) +}; + +static const struct dce_i2c_mask i2c_masks = { + I2C_COMMON_MASK_SH_LIST_DCE_COMMON_BASE(_MASK) +}; + +static struct dce_i2c_hw *dce80_i2c_hw_create( + struct dc_context *ctx, + uint32_t inst) +{ + struct dce_i2c_hw *dce_i2c_hw = + kzalloc(sizeof(struct dce_i2c_hw), GFP_KERNEL); + + if (!dce_i2c_hw) + return NULL; + + dce_i2c_hw_construct(dce_i2c_hw, ctx, inst, + &i2c_hw_regs[inst], &i2c_shifts, &i2c_masks); + + return dce_i2c_hw; +} + +static struct dce_i2c_sw *dce80_i2c_sw_create( + struct dc_context *ctx) +{ + struct dce_i2c_sw *dce_i2c_sw = + kzalloc(sizeof(struct dce_i2c_sw), GFP_KERNEL); + + if (!dce_i2c_sw) + return NULL; + + dce_i2c_sw_construct(dce_i2c_sw, ctx); + + return dce_i2c_sw; +} +static struct stream_encoder *dce80_stream_encoder_create( + enum engine_id eng_id, + struct dc_context *ctx) +{ + struct dce110_stream_encoder *enc110 = + kzalloc(sizeof(struct dce110_stream_encoder), GFP_KERNEL); + + if (!enc110) + return NULL; + + dce110_stream_encoder_construct(enc110, ctx, ctx->dc_bios, eng_id, + &stream_enc_regs[eng_id], + &se_shift, &se_mask); + return &enc110->base; +} + +#define SRII(reg_name, block, id)\ + .reg_name[id] = mm ## block ## id ## _ ## reg_name + +static const struct dce_hwseq_registers hwseq_reg = { + HWSEQ_DCE8_REG_LIST() +}; + +static const struct dce_hwseq_shift hwseq_shift = { + HWSEQ_DCE8_MASK_SH_LIST(__SHIFT) +}; + +static const struct dce_hwseq_mask hwseq_mask = { + HWSEQ_DCE8_MASK_SH_LIST(_MASK) +}; + +static struct dce_hwseq *dce80_hwseq_create( + struct dc_context *ctx) +{ + struct dce_hwseq *hws = kzalloc(sizeof(struct dce_hwseq), GFP_KERNEL); + + if (hws) { + hws->ctx = ctx; + hws->regs = &hwseq_reg; + hws->shifts = &hwseq_shift; + hws->masks = &hwseq_mask; + } + return hws; +} + +static const struct resource_create_funcs res_create_funcs = { + .read_dce_straps = read_dce_straps, + .create_audio = create_audio, + .create_stream_encoder = dce80_stream_encoder_create, + .create_hwseq = dce80_hwseq_create, +}; + +#define mi_inst_regs(id) { \ + MI_DCE8_REG_LIST(id), \ + .MC_HUB_RDREQ_DMIF_LIMIT = mmMC_HUB_RDREQ_DMIF_LIMIT \ +} +static const struct dce_mem_input_registers mi_regs[] = { + mi_inst_regs(0), + mi_inst_regs(1), + mi_inst_regs(2), + mi_inst_regs(3), + mi_inst_regs(4), + mi_inst_regs(5), +}; + +static const struct dce_mem_input_shift mi_shifts = { + MI_DCE8_MASK_SH_LIST(__SHIFT), + .ENABLE = MC_HUB_RDREQ_DMIF_LIMIT__ENABLE__SHIFT +}; + +static const struct dce_mem_input_mask mi_masks = { + MI_DCE8_MASK_SH_LIST(_MASK), + .ENABLE = MC_HUB_RDREQ_DMIF_LIMIT__ENABLE_MASK +}; + +static struct mem_input *dce80_mem_input_create( + struct dc_context *ctx, + uint32_t inst) +{ + struct dce_mem_input *dce_mi = kzalloc(sizeof(struct dce_mem_input), + GFP_KERNEL); + + if (!dce_mi) { + BREAK_TO_DEBUGGER(); + return NULL; + } + + dce_mem_input_construct(dce_mi, ctx, inst, &mi_regs[inst], &mi_shifts, &mi_masks); + dce_mi->wa.single_head_rdreq_dmif_limit = 2; + return &dce_mi->base; +} + +static void dce80_transform_destroy(struct transform **xfm) +{ + kfree(TO_DCE_TRANSFORM(*xfm)); + *xfm = NULL; +} + +static struct transform *dce80_transform_create( + struct dc_context *ctx, + uint32_t inst) +{ + struct dce_transform *transform = + kzalloc(sizeof(struct dce_transform), GFP_KERNEL); + + if (!transform) + return NULL; + + dce_transform_construct(transform, ctx, inst, + &xfm_regs[inst], &xfm_shift, &xfm_mask); + transform->prescaler_on = false; + return &transform->base; +} + +static const struct encoder_feature_support link_enc_feature = { + .max_hdmi_deep_color = COLOR_DEPTH_121212, + .max_hdmi_pixel_clock = 297000, + .flags.bits.IS_HBR2_CAPABLE = true, + .flags.bits.IS_TPS3_CAPABLE = true +}; + +static struct link_encoder *dce80_link_encoder_create( + struct dc_context *ctx, + const struct encoder_init_data *enc_init_data) +{ + struct dce110_link_encoder *enc110 = + kzalloc(sizeof(struct dce110_link_encoder), GFP_KERNEL); + int link_regs_id; + + if (!enc110) + return NULL; + + link_regs_id = + map_transmitter_id_to_phy_instance(enc_init_data->transmitter); + + dce110_link_encoder_construct(enc110, + enc_init_data, + &link_enc_feature, + &link_enc_regs[link_regs_id], + &link_enc_aux_regs[enc_init_data->channel - 1], + &link_enc_hpd_regs[enc_init_data->hpd_source]); + return &enc110->base; +} + +static struct panel_cntl *dce80_panel_cntl_create(const struct panel_cntl_init_data *init_data) +{ + struct dce_panel_cntl *panel_cntl = + kzalloc(sizeof(struct dce_panel_cntl), GFP_KERNEL); + + if (!panel_cntl) + return NULL; + + dce_panel_cntl_construct(panel_cntl, + init_data, + &panel_cntl_regs[init_data->inst], + &panel_cntl_shift, + &panel_cntl_mask); + + return &panel_cntl->base; +} + +static struct clock_source *dce80_clock_source_create( + struct dc_context *ctx, + struct dc_bios *bios, + enum clock_source_id id, + const struct dce110_clk_src_regs *regs, + bool dp_clk_src) +{ + struct dce110_clk_src *clk_src = + kzalloc(sizeof(struct dce110_clk_src), GFP_KERNEL); + + if (!clk_src) + return NULL; + + if (dce110_clk_src_construct(clk_src, ctx, bios, id, + regs, &cs_shift, &cs_mask)) { + clk_src->base.dp_clk_src = dp_clk_src; + return &clk_src->base; + } + + kfree(clk_src); + BREAK_TO_DEBUGGER(); + return NULL; +} + +static void dce80_clock_source_destroy(struct clock_source **clk_src) +{ + kfree(TO_DCE110_CLK_SRC(*clk_src)); + *clk_src = NULL; +} + +static struct input_pixel_processor *dce80_ipp_create( + struct dc_context *ctx, uint32_t inst) +{ + struct dce_ipp *ipp = kzalloc(sizeof(struct dce_ipp), GFP_KERNEL); + + if (!ipp) { + BREAK_TO_DEBUGGER(); + return NULL; + } + + dce_ipp_construct(ipp, ctx, inst, + &ipp_regs[inst], &ipp_shift, &ipp_mask); + return &ipp->base; +} + +static void dce80_resource_destruct(struct dce110_resource_pool *pool) +{ + unsigned int i; + + for (i = 0; i < pool->base.pipe_count; i++) { + if (pool->base.opps[i] != NULL) + dce110_opp_destroy(&pool->base.opps[i]); + + if (pool->base.transforms[i] != NULL) + dce80_transform_destroy(&pool->base.transforms[i]); + + if (pool->base.ipps[i] != NULL) + dce_ipp_destroy(&pool->base.ipps[i]); + + if (pool->base.mis[i] != NULL) { + kfree(TO_DCE_MEM_INPUT(pool->base.mis[i])); + pool->base.mis[i] = NULL; + } + + if (pool->base.timing_generators[i] != NULL) { + kfree(DCE110TG_FROM_TG(pool->base.timing_generators[i])); + pool->base.timing_generators[i] = NULL; + } + } + + for (i = 0; i < pool->base.res_cap->num_ddc; i++) { + if (pool->base.engines[i] != NULL) + dce110_engine_destroy(&pool->base.engines[i]); + if (pool->base.hw_i2cs[i] != NULL) { + kfree(pool->base.hw_i2cs[i]); + pool->base.hw_i2cs[i] = NULL; + } + if (pool->base.sw_i2cs[i] != NULL) { + kfree(pool->base.sw_i2cs[i]); + pool->base.sw_i2cs[i] = NULL; + } + } + + for (i = 0; i < pool->base.stream_enc_count; i++) { + if (pool->base.stream_enc[i] != NULL) + kfree(DCE110STRENC_FROM_STRENC(pool->base.stream_enc[i])); + } + + for (i = 0; i < pool->base.clk_src_count; i++) { + if (pool->base.clock_sources[i] != NULL) { + dce80_clock_source_destroy(&pool->base.clock_sources[i]); + } + } + + if (pool->base.abm != NULL) + dce_abm_destroy(&pool->base.abm); + + if (pool->base.dmcu != NULL) + dce_dmcu_destroy(&pool->base.dmcu); + + if (pool->base.dp_clock_source != NULL) + dce80_clock_source_destroy(&pool->base.dp_clock_source); + + for (i = 0; i < pool->base.audio_count; i++) { + if (pool->base.audios[i] != NULL) { + dce_aud_destroy(&pool->base.audios[i]); + } + } + + if (pool->base.irqs != NULL) { + dal_irq_service_destroy(&pool->base.irqs); + } +} + +static bool dce80_validate_bandwidth( + struct dc *dc, + struct dc_state *context, + bool fast_validate) +{ + int i; + bool at_least_one_pipe = false; + + for (i = 0; i < dc->res_pool->pipe_count; i++) { + if (context->res_ctx.pipe_ctx[i].stream) + at_least_one_pipe = true; + } + + if (at_least_one_pipe) { + /* TODO implement when needed but for now hardcode max value*/ + context->bw_ctx.bw.dce.dispclk_khz = 681000; + context->bw_ctx.bw.dce.yclk_khz = 250000 * MEMORY_TYPE_MULTIPLIER_CZ; + } else { + context->bw_ctx.bw.dce.dispclk_khz = 0; + context->bw_ctx.bw.dce.yclk_khz = 0; + } + + return true; +} + +static bool dce80_validate_surface_sets( + struct dc_state *context) +{ + int i; + + for (i = 0; i < context->stream_count; i++) { + if (context->stream_status[i].plane_count == 0) + continue; + + if (context->stream_status[i].plane_count > 1) + return false; + + if (context->stream_status[i].plane_states[0]->format + >= SURFACE_PIXEL_FORMAT_VIDEO_BEGIN) + return false; + } + + return true; +} + +static enum dc_status dce80_validate_global( + struct dc *dc, + struct dc_state *context) +{ + if (!dce80_validate_surface_sets(context)) + return DC_FAIL_SURFACE_VALIDATE; + + return DC_OK; +} + +static void dce80_destroy_resource_pool(struct resource_pool **pool) +{ + struct dce110_resource_pool *dce110_pool = TO_DCE110_RES_POOL(*pool); + + dce80_resource_destruct(dce110_pool); + kfree(dce110_pool); + *pool = NULL; +} + +static const struct resource_funcs dce80_res_pool_funcs = { + .destroy = dce80_destroy_resource_pool, + .link_enc_create = dce80_link_encoder_create, + .panel_cntl_create = dce80_panel_cntl_create, + .validate_bandwidth = dce80_validate_bandwidth, + .validate_plane = dce100_validate_plane, + .add_stream_to_ctx = dce100_add_stream_to_ctx, + .validate_global = dce80_validate_global, + .find_first_free_match_stream_enc_for_link = dce100_find_first_free_match_stream_enc_for_link +}; + +static bool dce80_construct( + uint8_t num_virtual_links, + struct dc *dc, + struct dce110_resource_pool *pool) +{ + unsigned int i; + struct dc_context *ctx = dc->ctx; + struct dc_bios *bp; + + ctx->dc_bios->regs = &bios_regs; + + pool->base.res_cap = &res_cap; + pool->base.funcs = &dce80_res_pool_funcs; + + + /************************************************* + * Resource + asic cap harcoding * + *************************************************/ + pool->base.underlay_pipe_index = NO_UNDERLAY_PIPE; + pool->base.pipe_count = res_cap.num_timing_generator; + pool->base.timing_generator_count = res_cap.num_timing_generator; + dc->caps.max_downscale_ratio = 200; + dc->caps.i2c_speed_in_khz = 40; + dc->caps.i2c_speed_in_khz_hdcp = 40; + dc->caps.max_cursor_size = 128; + dc->caps.min_horizontal_blanking_period = 80; + dc->caps.dual_link_dvi = true; + dc->caps.extended_aux_timeout_support = false; + dc->debug = debug_defaults; + + /************************************************* + * Create resources * + *************************************************/ + + bp = ctx->dc_bios; + + if (bp->fw_info_valid && bp->fw_info.external_clock_source_frequency_for_dp != 0) { + pool->base.dp_clock_source = + dce80_clock_source_create(ctx, bp, CLOCK_SOURCE_ID_EXTERNAL, NULL, true); + + pool->base.clock_sources[0] = + dce80_clock_source_create(ctx, bp, CLOCK_SOURCE_ID_PLL0, &clk_src_regs[0], false); + pool->base.clock_sources[1] = + dce80_clock_source_create(ctx, bp, CLOCK_SOURCE_ID_PLL1, &clk_src_regs[1], false); + pool->base.clock_sources[2] = + dce80_clock_source_create(ctx, bp, CLOCK_SOURCE_ID_PLL2, &clk_src_regs[2], false); + pool->base.clk_src_count = 3; + + } else { + pool->base.dp_clock_source = + dce80_clock_source_create(ctx, bp, CLOCK_SOURCE_ID_PLL0, &clk_src_regs[0], true); + + pool->base.clock_sources[0] = + dce80_clock_source_create(ctx, bp, CLOCK_SOURCE_ID_PLL1, &clk_src_regs[1], false); + pool->base.clock_sources[1] = + dce80_clock_source_create(ctx, bp, CLOCK_SOURCE_ID_PLL2, &clk_src_regs[2], false); + pool->base.clk_src_count = 2; + } + + if (pool->base.dp_clock_source == NULL) { + dm_error("DC: failed to create dp clock source!\n"); + BREAK_TO_DEBUGGER(); + goto res_create_fail; + } + + for (i = 0; i < pool->base.clk_src_count; i++) { + if (pool->base.clock_sources[i] == NULL) { + dm_error("DC: failed to create clock sources!\n"); + BREAK_TO_DEBUGGER(); + goto res_create_fail; + } + } + + pool->base.dmcu = dce_dmcu_create(ctx, + &dmcu_regs, + &dmcu_shift, + &dmcu_mask); + if (pool->base.dmcu == NULL) { + dm_error("DC: failed to create dmcu!\n"); + BREAK_TO_DEBUGGER(); + goto res_create_fail; + } + + pool->base.abm = dce_abm_create(ctx, + &abm_regs, + &abm_shift, + &abm_mask); + if (pool->base.abm == NULL) { + dm_error("DC: failed to create abm!\n"); + BREAK_TO_DEBUGGER(); + goto res_create_fail; + } + + { + struct irq_service_init_data init_data; + init_data.ctx = dc->ctx; + pool->base.irqs = dal_irq_service_dce80_create(&init_data); + if (!pool->base.irqs) + goto res_create_fail; + } + + for (i = 0; i < pool->base.pipe_count; i++) { + pool->base.timing_generators[i] = dce80_timing_generator_create( + ctx, i, &dce80_tg_offsets[i]); + if (pool->base.timing_generators[i] == NULL) { + BREAK_TO_DEBUGGER(); + dm_error("DC: failed to create tg!\n"); + goto res_create_fail; + } + + pool->base.mis[i] = dce80_mem_input_create(ctx, i); + if (pool->base.mis[i] == NULL) { + BREAK_TO_DEBUGGER(); + dm_error("DC: failed to create memory input!\n"); + goto res_create_fail; + } + + pool->base.ipps[i] = dce80_ipp_create(ctx, i); + if (pool->base.ipps[i] == NULL) { + BREAK_TO_DEBUGGER(); + dm_error("DC: failed to create input pixel processor!\n"); + goto res_create_fail; + } + + pool->base.transforms[i] = dce80_transform_create(ctx, i); + if (pool->base.transforms[i] == NULL) { + BREAK_TO_DEBUGGER(); + dm_error("DC: failed to create transform!\n"); + goto res_create_fail; + } + + pool->base.opps[i] = dce80_opp_create(ctx, i); + if (pool->base.opps[i] == NULL) { + BREAK_TO_DEBUGGER(); + dm_error("DC: failed to create output pixel processor!\n"); + goto res_create_fail; + } + } + + for (i = 0; i < pool->base.res_cap->num_ddc; i++) { + pool->base.engines[i] = dce80_aux_engine_create(ctx, i); + if (pool->base.engines[i] == NULL) { + BREAK_TO_DEBUGGER(); + dm_error( + "DC:failed to create aux engine!!\n"); + goto res_create_fail; + } + pool->base.hw_i2cs[i] = dce80_i2c_hw_create(ctx, i); + if (pool->base.hw_i2cs[i] == NULL) { + BREAK_TO_DEBUGGER(); + dm_error( + "DC:failed to create i2c engine!!\n"); + goto res_create_fail; + } + pool->base.sw_i2cs[i] = dce80_i2c_sw_create(ctx); + if (pool->base.sw_i2cs[i] == NULL) { + BREAK_TO_DEBUGGER(); + dm_error( + "DC:failed to create sw i2c!!\n"); + goto res_create_fail; + } + } + + dc->caps.max_planes = pool->base.pipe_count; + + for (i = 0; i < dc->caps.max_planes; ++i) + dc->caps.planes[i] = plane_cap; + + dc->caps.disable_dp_clk_share = true; + + if (!resource_construct(num_virtual_links, dc, &pool->base, + &res_create_funcs)) + goto res_create_fail; + + /* Create hardware sequencer */ + dce80_hw_sequencer_construct(dc); + + return true; + +res_create_fail: + dce80_resource_destruct(pool); + return false; +} + +struct resource_pool *dce80_create_resource_pool( + uint8_t num_virtual_links, + struct dc *dc) +{ + struct dce110_resource_pool *pool = + kzalloc(sizeof(struct dce110_resource_pool), GFP_KERNEL); + + if (!pool) + return NULL; + + if (dce80_construct(num_virtual_links, dc, pool)) + return &pool->base; + + kfree(pool); + BREAK_TO_DEBUGGER(); + return NULL; +} + +static bool dce81_construct( + uint8_t num_virtual_links, + struct dc *dc, + struct dce110_resource_pool *pool) +{ + unsigned int i; + struct dc_context *ctx = dc->ctx; + struct dc_bios *bp; + + ctx->dc_bios->regs = &bios_regs; + + pool->base.res_cap = &res_cap_81; + pool->base.funcs = &dce80_res_pool_funcs; + + + /************************************************* + * Resource + asic cap harcoding * + *************************************************/ + pool->base.underlay_pipe_index = NO_UNDERLAY_PIPE; + pool->base.pipe_count = res_cap_81.num_timing_generator; + pool->base.timing_generator_count = res_cap_81.num_timing_generator; + dc->caps.max_downscale_ratio = 200; + dc->caps.i2c_speed_in_khz = 40; + dc->caps.i2c_speed_in_khz_hdcp = 40; + dc->caps.max_cursor_size = 128; + dc->caps.min_horizontal_blanking_period = 80; + dc->caps.is_apu = true; + + /************************************************* + * Create resources * + *************************************************/ + + bp = ctx->dc_bios; + + if (bp->fw_info_valid && bp->fw_info.external_clock_source_frequency_for_dp != 0) { + pool->base.dp_clock_source = + dce80_clock_source_create(ctx, bp, CLOCK_SOURCE_ID_EXTERNAL, NULL, true); + + pool->base.clock_sources[0] = + dce80_clock_source_create(ctx, bp, CLOCK_SOURCE_ID_PLL0, &clk_src_regs[0], false); + pool->base.clock_sources[1] = + dce80_clock_source_create(ctx, bp, CLOCK_SOURCE_ID_PLL1, &clk_src_regs[1], false); + pool->base.clock_sources[2] = + dce80_clock_source_create(ctx, bp, CLOCK_SOURCE_ID_PLL2, &clk_src_regs[2], false); + pool->base.clk_src_count = 3; + + } else { + pool->base.dp_clock_source = + dce80_clock_source_create(ctx, bp, CLOCK_SOURCE_ID_PLL0, &clk_src_regs[0], true); + + pool->base.clock_sources[0] = + dce80_clock_source_create(ctx, bp, CLOCK_SOURCE_ID_PLL1, &clk_src_regs[1], false); + pool->base.clock_sources[1] = + dce80_clock_source_create(ctx, bp, CLOCK_SOURCE_ID_PLL2, &clk_src_regs[2], false); + pool->base.clk_src_count = 2; + } + + if (pool->base.dp_clock_source == NULL) { + dm_error("DC: failed to create dp clock source!\n"); + BREAK_TO_DEBUGGER(); + goto res_create_fail; + } + + for (i = 0; i < pool->base.clk_src_count; i++) { + if (pool->base.clock_sources[i] == NULL) { + dm_error("DC: failed to create clock sources!\n"); + BREAK_TO_DEBUGGER(); + goto res_create_fail; + } + } + + pool->base.dmcu = dce_dmcu_create(ctx, + &dmcu_regs, + &dmcu_shift, + &dmcu_mask); + if (pool->base.dmcu == NULL) { + dm_error("DC: failed to create dmcu!\n"); + BREAK_TO_DEBUGGER(); + goto res_create_fail; + } + + pool->base.abm = dce_abm_create(ctx, + &abm_regs, + &abm_shift, + &abm_mask); + if (pool->base.abm == NULL) { + dm_error("DC: failed to create abm!\n"); + BREAK_TO_DEBUGGER(); + goto res_create_fail; + } + + { + struct irq_service_init_data init_data; + init_data.ctx = dc->ctx; + pool->base.irqs = dal_irq_service_dce80_create(&init_data); + if (!pool->base.irqs) + goto res_create_fail; + } + + for (i = 0; i < pool->base.pipe_count; i++) { + pool->base.timing_generators[i] = dce80_timing_generator_create( + ctx, i, &dce80_tg_offsets[i]); + if (pool->base.timing_generators[i] == NULL) { + BREAK_TO_DEBUGGER(); + dm_error("DC: failed to create tg!\n"); + goto res_create_fail; + } + + pool->base.mis[i] = dce80_mem_input_create(ctx, i); + if (pool->base.mis[i] == NULL) { + BREAK_TO_DEBUGGER(); + dm_error("DC: failed to create memory input!\n"); + goto res_create_fail; + } + + pool->base.ipps[i] = dce80_ipp_create(ctx, i); + if (pool->base.ipps[i] == NULL) { + BREAK_TO_DEBUGGER(); + dm_error("DC: failed to create input pixel processor!\n"); + goto res_create_fail; + } + + pool->base.transforms[i] = dce80_transform_create(ctx, i); + if (pool->base.transforms[i] == NULL) { + BREAK_TO_DEBUGGER(); + dm_error("DC: failed to create transform!\n"); + goto res_create_fail; + } + + pool->base.opps[i] = dce80_opp_create(ctx, i); + if (pool->base.opps[i] == NULL) { + BREAK_TO_DEBUGGER(); + dm_error("DC: failed to create output pixel processor!\n"); + goto res_create_fail; + } + } + + for (i = 0; i < pool->base.res_cap->num_ddc; i++) { + pool->base.engines[i] = dce80_aux_engine_create(ctx, i); + if (pool->base.engines[i] == NULL) { + BREAK_TO_DEBUGGER(); + dm_error( + "DC:failed to create aux engine!!\n"); + goto res_create_fail; + } + pool->base.hw_i2cs[i] = dce80_i2c_hw_create(ctx, i); + if (pool->base.hw_i2cs[i] == NULL) { + BREAK_TO_DEBUGGER(); + dm_error( + "DC:failed to create i2c engine!!\n"); + goto res_create_fail; + } + pool->base.sw_i2cs[i] = dce80_i2c_sw_create(ctx); + if (pool->base.sw_i2cs[i] == NULL) { + BREAK_TO_DEBUGGER(); + dm_error( + "DC:failed to create sw i2c!!\n"); + goto res_create_fail; + } + } + + dc->caps.max_planes = pool->base.pipe_count; + + for (i = 0; i < dc->caps.max_planes; ++i) + dc->caps.planes[i] = plane_cap; + + dc->caps.disable_dp_clk_share = true; + + if (!resource_construct(num_virtual_links, dc, &pool->base, + &res_create_funcs)) + goto res_create_fail; + + /* Create hardware sequencer */ + dce80_hw_sequencer_construct(dc); + + return true; + +res_create_fail: + dce80_resource_destruct(pool); + return false; +} + +struct resource_pool *dce81_create_resource_pool( + uint8_t num_virtual_links, + struct dc *dc) +{ + struct dce110_resource_pool *pool = + kzalloc(sizeof(struct dce110_resource_pool), GFP_KERNEL); + + if (!pool) + return NULL; + + if (dce81_construct(num_virtual_links, dc, pool)) + return &pool->base; + + kfree(pool); + BREAK_TO_DEBUGGER(); + return NULL; +} + +static bool dce83_construct( + uint8_t num_virtual_links, + struct dc *dc, + struct dce110_resource_pool *pool) +{ + unsigned int i; + struct dc_context *ctx = dc->ctx; + struct dc_bios *bp; + + ctx->dc_bios->regs = &bios_regs; + + pool->base.res_cap = &res_cap_83; + pool->base.funcs = &dce80_res_pool_funcs; + + + /************************************************* + * Resource + asic cap harcoding * + *************************************************/ + pool->base.underlay_pipe_index = NO_UNDERLAY_PIPE; + pool->base.pipe_count = res_cap_83.num_timing_generator; + pool->base.timing_generator_count = res_cap_83.num_timing_generator; + dc->caps.max_downscale_ratio = 200; + dc->caps.i2c_speed_in_khz = 40; + dc->caps.i2c_speed_in_khz_hdcp = 40; + dc->caps.max_cursor_size = 128; + dc->caps.min_horizontal_blanking_period = 80; + dc->caps.is_apu = true; + dc->debug = debug_defaults; + + /************************************************* + * Create resources * + *************************************************/ + + bp = ctx->dc_bios; + + if (bp->fw_info_valid && bp->fw_info.external_clock_source_frequency_for_dp != 0) { + pool->base.dp_clock_source = + dce80_clock_source_create(ctx, bp, CLOCK_SOURCE_ID_EXTERNAL, NULL, true); + + pool->base.clock_sources[0] = + dce80_clock_source_create(ctx, bp, CLOCK_SOURCE_ID_PLL1, &clk_src_regs[0], false); + pool->base.clock_sources[1] = + dce80_clock_source_create(ctx, bp, CLOCK_SOURCE_ID_PLL2, &clk_src_regs[1], false); + pool->base.clk_src_count = 2; + + } else { + pool->base.dp_clock_source = + dce80_clock_source_create(ctx, bp, CLOCK_SOURCE_ID_PLL1, &clk_src_regs[0], true); + + pool->base.clock_sources[0] = + dce80_clock_source_create(ctx, bp, CLOCK_SOURCE_ID_PLL2, &clk_src_regs[1], false); + pool->base.clk_src_count = 1; + } + + if (pool->base.dp_clock_source == NULL) { + dm_error("DC: failed to create dp clock source!\n"); + BREAK_TO_DEBUGGER(); + goto res_create_fail; + } + + for (i = 0; i < pool->base.clk_src_count; i++) { + if (pool->base.clock_sources[i] == NULL) { + dm_error("DC: failed to create clock sources!\n"); + BREAK_TO_DEBUGGER(); + goto res_create_fail; + } + } + + pool->base.dmcu = dce_dmcu_create(ctx, + &dmcu_regs, + &dmcu_shift, + &dmcu_mask); + if (pool->base.dmcu == NULL) { + dm_error("DC: failed to create dmcu!\n"); + BREAK_TO_DEBUGGER(); + goto res_create_fail; + } + + pool->base.abm = dce_abm_create(ctx, + &abm_regs, + &abm_shift, + &abm_mask); + if (pool->base.abm == NULL) { + dm_error("DC: failed to create abm!\n"); + BREAK_TO_DEBUGGER(); + goto res_create_fail; + } + + { + struct irq_service_init_data init_data; + init_data.ctx = dc->ctx; + pool->base.irqs = dal_irq_service_dce80_create(&init_data); + if (!pool->base.irqs) + goto res_create_fail; + } + + for (i = 0; i < pool->base.pipe_count; i++) { + pool->base.timing_generators[i] = dce80_timing_generator_create( + ctx, i, &dce80_tg_offsets[i]); + if (pool->base.timing_generators[i] == NULL) { + BREAK_TO_DEBUGGER(); + dm_error("DC: failed to create tg!\n"); + goto res_create_fail; + } + + pool->base.mis[i] = dce80_mem_input_create(ctx, i); + if (pool->base.mis[i] == NULL) { + BREAK_TO_DEBUGGER(); + dm_error("DC: failed to create memory input!\n"); + goto res_create_fail; + } + + pool->base.ipps[i] = dce80_ipp_create(ctx, i); + if (pool->base.ipps[i] == NULL) { + BREAK_TO_DEBUGGER(); + dm_error("DC: failed to create input pixel processor!\n"); + goto res_create_fail; + } + + pool->base.transforms[i] = dce80_transform_create(ctx, i); + if (pool->base.transforms[i] == NULL) { + BREAK_TO_DEBUGGER(); + dm_error("DC: failed to create transform!\n"); + goto res_create_fail; + } + + pool->base.opps[i] = dce80_opp_create(ctx, i); + if (pool->base.opps[i] == NULL) { + BREAK_TO_DEBUGGER(); + dm_error("DC: failed to create output pixel processor!\n"); + goto res_create_fail; + } + } + + for (i = 0; i < pool->base.res_cap->num_ddc; i++) { + pool->base.engines[i] = dce80_aux_engine_create(ctx, i); + if (pool->base.engines[i] == NULL) { + BREAK_TO_DEBUGGER(); + dm_error( + "DC:failed to create aux engine!!\n"); + goto res_create_fail; + } + pool->base.hw_i2cs[i] = dce80_i2c_hw_create(ctx, i); + if (pool->base.hw_i2cs[i] == NULL) { + BREAK_TO_DEBUGGER(); + dm_error( + "DC:failed to create i2c engine!!\n"); + goto res_create_fail; + } + pool->base.sw_i2cs[i] = dce80_i2c_sw_create(ctx); + if (pool->base.sw_i2cs[i] == NULL) { + BREAK_TO_DEBUGGER(); + dm_error( + "DC:failed to create sw i2c!!\n"); + goto res_create_fail; + } + } + + dc->caps.max_planes = pool->base.pipe_count; + + for (i = 0; i < dc->caps.max_planes; ++i) + dc->caps.planes[i] = plane_cap; + + dc->caps.disable_dp_clk_share = true; + + if (!resource_construct(num_virtual_links, dc, &pool->base, + &res_create_funcs)) + goto res_create_fail; + + /* Create hardware sequencer */ + dce80_hw_sequencer_construct(dc); + + return true; + +res_create_fail: + dce80_resource_destruct(pool); + return false; +} + +struct resource_pool *dce83_create_resource_pool( + uint8_t num_virtual_links, + struct dc *dc) +{ + struct dce110_resource_pool *pool = + kzalloc(sizeof(struct dce110_resource_pool), GFP_KERNEL); + + if (!pool) + return NULL; + + if (dce83_construct(num_virtual_links, dc, pool)) + return &pool->base; + + BREAK_TO_DEBUGGER(); + return NULL; +} diff --git a/drivers/gpu/drm/amd/display/dc/resource/dce80/dce80_resource.h b/drivers/gpu/drm/amd/display/dc/resource/dce80/dce80_resource.h new file mode 100644 index 000000000000..eff31ab83a39 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/resource/dce80/dce80_resource.h @@ -0,0 +1,47 @@ +/* +* Copyright 2012-15 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_RESOURCE_DCE80_H__ +#define __DC_RESOURCE_DCE80_H__ + +#include "core_types.h" + +struct dc; +struct resource_pool; + +struct resource_pool *dce80_create_resource_pool( + uint8_t num_virtual_links, + struct dc *dc); + +struct resource_pool *dce81_create_resource_pool( + uint8_t num_virtual_links, + struct dc *dc); + +struct resource_pool *dce83_create_resource_pool( + uint8_t num_virtual_links, + struct dc *dc); + +#endif /* __DC_RESOURCE_DCE80_H__ */ + diff --git a/drivers/gpu/drm/amd/display/dc/resource/dcn10/dcn10_resource.c b/drivers/gpu/drm/amd/display/dc/resource/dcn10/dcn10_resource.c new file mode 100644 index 000000000000..af1b31f4e69a --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/resource/dcn10/dcn10_resource.c @@ -0,0 +1,1689 @@ +/* +* Copyright 2016 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 "dm_services.h" +#include "dc.h" + +#include "dcn10/dcn10_init.h" + +#include "resource.h" +#include "include/irq_service_interface.h" +#include "dcn10/dcn10_resource.h" +#include "dcn10/dcn10_ipp.h" +#include "dcn10/dcn10_mpc.h" + +#include "dcn10/dcn10_dwb.h" + +#include "irq/dcn10/irq_service_dcn10.h" +#include "dcn10/dcn10_dpp.h" +#include "dcn10/dcn10_optc.h" +#include "dcn10/dcn10_hwseq.h" +#include "dce110/dce110_hwseq.h" +#include "dcn10/dcn10_opp.h" +#include "dcn10/dcn10_link_encoder.h" +#include "dcn10/dcn10_stream_encoder.h" +#include "dce/dce_clock_source.h" +#include "dce/dce_audio.h" +#include "dce/dce_hwseq.h" +#include "virtual/virtual_stream_encoder.h" +#include "dce110/dce110_resource.h" +#include "dce112/dce112_resource.h" +#include "dcn10/dcn10_hubp.h" +#include "dcn10/dcn10_hubbub.h" +#include "dce/dce_panel_cntl.h" + +#include "soc15_hw_ip.h" +#include "vega10_ip_offset.h" + +#include "dcn/dcn_1_0_offset.h" +#include "dcn/dcn_1_0_sh_mask.h" + +#include "nbio/nbio_7_0_offset.h" + +#include "mmhub/mmhub_9_1_offset.h" +#include "mmhub/mmhub_9_1_sh_mask.h" + +#include "reg_helper.h" +#include "dce/dce_abm.h" +#include "dce/dce_dmcu.h" +#include "dce/dce_aux.h" +#include "dce/dce_i2c.h" + +#ifndef mmDP0_DP_DPHY_INTERNAL_CTRL + #define mmDP0_DP_DPHY_INTERNAL_CTRL 0x210f + #define mmDP0_DP_DPHY_INTERNAL_CTRL_BASE_IDX 2 + #define mmDP1_DP_DPHY_INTERNAL_CTRL 0x220f + #define mmDP1_DP_DPHY_INTERNAL_CTRL_BASE_IDX 2 + #define mmDP2_DP_DPHY_INTERNAL_CTRL 0x230f + #define mmDP2_DP_DPHY_INTERNAL_CTRL_BASE_IDX 2 + #define mmDP3_DP_DPHY_INTERNAL_CTRL 0x240f + #define mmDP3_DP_DPHY_INTERNAL_CTRL_BASE_IDX 2 + #define mmDP4_DP_DPHY_INTERNAL_CTRL 0x250f + #define mmDP4_DP_DPHY_INTERNAL_CTRL_BASE_IDX 2 + #define mmDP5_DP_DPHY_INTERNAL_CTRL 0x260f + #define mmDP5_DP_DPHY_INTERNAL_CTRL_BASE_IDX 2 + #define mmDP6_DP_DPHY_INTERNAL_CTRL 0x270f + #define mmDP6_DP_DPHY_INTERNAL_CTRL_BASE_IDX 2 +#endif + + +enum dcn10_clk_src_array_id { + DCN10_CLK_SRC_PLL0, + DCN10_CLK_SRC_PLL1, + DCN10_CLK_SRC_PLL2, + DCN10_CLK_SRC_PLL3, + DCN10_CLK_SRC_TOTAL, + DCN101_CLK_SRC_TOTAL = DCN10_CLK_SRC_PLL3 +}; + +/* begin ********************* + * macros to expend register list macro defined in HW object header file */ + +/* DCN */ +#define BASE_INNER(seg) \ + DCE_BASE__INST0_SEG ## seg + +#define BASE(seg) \ + BASE_INNER(seg) + +#define SR(reg_name)\ + .reg_name = BASE(mm ## reg_name ## _BASE_IDX) + \ + mm ## reg_name + +#define SRI(reg_name, block, id)\ + .reg_name = BASE(mm ## block ## id ## _ ## reg_name ## _BASE_IDX) + \ + mm ## block ## id ## _ ## reg_name + + +#define SRII(reg_name, block, id)\ + .reg_name[id] = BASE(mm ## block ## id ## _ ## reg_name ## _BASE_IDX) + \ + mm ## block ## id ## _ ## reg_name + +#define VUPDATE_SRII(reg_name, block, id)\ + .reg_name[id] = BASE(mm ## reg_name ## 0 ## _ ## block ## id ## _BASE_IDX) + \ + mm ## reg_name ## 0 ## _ ## block ## id + +/* set field/register/bitfield name */ +#define SFRB(field_name, reg_name, bitfield, post_fix)\ + .field_name = reg_name ## __ ## bitfield ## post_fix + +/* NBIO */ +#define NBIO_BASE_INNER(seg) \ + NBIF_BASE__INST0_SEG ## seg + +#define NBIO_BASE(seg) \ + NBIO_BASE_INNER(seg) + +#define NBIO_SR(reg_name)\ + .reg_name = NBIO_BASE(mm ## reg_name ## _BASE_IDX) + \ + mm ## reg_name + +/* MMHUB */ +#define MMHUB_BASE_INNER(seg) \ + MMHUB_BASE__INST0_SEG ## seg + +#define MMHUB_BASE(seg) \ + MMHUB_BASE_INNER(seg) + +#define MMHUB_SR(reg_name)\ + .reg_name = MMHUB_BASE(mm ## reg_name ## _BASE_IDX) + \ + mm ## reg_name + +/* macros to expend register list macro defined in HW object header file + * end *********************/ + + +static const struct dce_dmcu_registers dmcu_regs = { + DMCU_DCN10_REG_LIST() +}; + +static const struct dce_dmcu_shift dmcu_shift = { + DMCU_MASK_SH_LIST_DCN10(__SHIFT) +}; + +static const struct dce_dmcu_mask dmcu_mask = { + DMCU_MASK_SH_LIST_DCN10(_MASK) +}; + +static const struct dce_abm_registers abm_regs = { + ABM_DCN10_REG_LIST(0) +}; + +static const struct dce_abm_shift abm_shift = { + ABM_MASK_SH_LIST_DCN10(__SHIFT) +}; + +static const struct dce_abm_mask abm_mask = { + ABM_MASK_SH_LIST_DCN10(_MASK) +}; + +#define stream_enc_regs(id)\ +[id] = {\ + SE_DCN_REG_LIST(id)\ +} + +static const struct dcn10_stream_enc_registers stream_enc_regs[] = { + stream_enc_regs(0), + stream_enc_regs(1), + stream_enc_regs(2), + stream_enc_regs(3), +}; + +static const struct dcn10_stream_encoder_shift se_shift = { + SE_COMMON_MASK_SH_LIST_DCN10(__SHIFT) +}; + +static const struct dcn10_stream_encoder_mask se_mask = { + SE_COMMON_MASK_SH_LIST_DCN10(_MASK) +}; + +#define audio_regs(id)\ +[id] = {\ + AUD_COMMON_REG_LIST(id)\ +} + +static const struct dce_audio_registers audio_regs[] = { + audio_regs(0), + audio_regs(1), + audio_regs(2), + audio_regs(3), +}; + +#define DCE120_AUD_COMMON_MASK_SH_LIST(mask_sh)\ + SF(AZF0ENDPOINT0_AZALIA_F0_CODEC_ENDPOINT_INDEX, AZALIA_ENDPOINT_REG_INDEX, mask_sh),\ + SF(AZF0ENDPOINT0_AZALIA_F0_CODEC_ENDPOINT_DATA, AZALIA_ENDPOINT_REG_DATA, mask_sh),\ + AUD_COMMON_MASK_SH_LIST_BASE(mask_sh) + +static const struct dce_audio_shift audio_shift = { + DCE120_AUD_COMMON_MASK_SH_LIST(__SHIFT) +}; + +static const struct dce_audio_mask audio_mask = { + DCE120_AUD_COMMON_MASK_SH_LIST(_MASK) +}; + +#define aux_regs(id)\ +[id] = {\ + AUX_REG_LIST(id)\ +} + +static const struct dcn10_link_enc_aux_registers link_enc_aux_regs[] = { + aux_regs(0), + aux_regs(1), + aux_regs(2), + aux_regs(3) +}; + +#define hpd_regs(id)\ +[id] = {\ + HPD_REG_LIST(id)\ +} + +static const struct dcn10_link_enc_hpd_registers link_enc_hpd_regs[] = { + hpd_regs(0), + hpd_regs(1), + hpd_regs(2), + hpd_regs(3) +}; + +#define link_regs(id)\ +[id] = {\ + LE_DCN10_REG_LIST(id), \ + SRI(DP_DPHY_INTERNAL_CTRL, DP, id) \ +} + +static const struct dcn10_link_enc_registers link_enc_regs[] = { + link_regs(0), + link_regs(1), + link_regs(2), + link_regs(3) +}; + +static const struct dcn10_link_enc_shift le_shift = { + LINK_ENCODER_MASK_SH_LIST_DCN10(__SHIFT) +}; + +static const struct dcn10_link_enc_mask le_mask = { + LINK_ENCODER_MASK_SH_LIST_DCN10(_MASK) +}; + +static const struct dce_panel_cntl_registers panel_cntl_regs[] = { + { DCN_PANEL_CNTL_REG_LIST() } +}; + +static const struct dce_panel_cntl_shift panel_cntl_shift = { + DCE_PANEL_CNTL_MASK_SH_LIST(__SHIFT) +}; + +static const struct dce_panel_cntl_mask panel_cntl_mask = { + DCE_PANEL_CNTL_MASK_SH_LIST(_MASK) +}; + +static const struct dce110_aux_registers_shift aux_shift = { + DCN10_AUX_MASK_SH_LIST(__SHIFT) +}; + +static const struct dce110_aux_registers_mask aux_mask = { + DCN10_AUX_MASK_SH_LIST(_MASK) +}; + +#define ipp_regs(id)\ +[id] = {\ + IPP_REG_LIST_DCN10(id),\ +} + +static const struct dcn10_ipp_registers ipp_regs[] = { + ipp_regs(0), + ipp_regs(1), + ipp_regs(2), + ipp_regs(3), +}; + +static const struct dcn10_ipp_shift ipp_shift = { + IPP_MASK_SH_LIST_DCN10(__SHIFT) +}; + +static const struct dcn10_ipp_mask ipp_mask = { + IPP_MASK_SH_LIST_DCN10(_MASK), +}; + +#define opp_regs(id)\ +[id] = {\ + OPP_REG_LIST_DCN10(id),\ +} + +static const struct dcn10_opp_registers opp_regs[] = { + opp_regs(0), + opp_regs(1), + opp_regs(2), + opp_regs(3), +}; + +static const struct dcn10_opp_shift opp_shift = { + OPP_MASK_SH_LIST_DCN10(__SHIFT) +}; + +static const struct dcn10_opp_mask opp_mask = { + OPP_MASK_SH_LIST_DCN10(_MASK), +}; + +#define aux_engine_regs(id)\ +[id] = {\ + AUX_COMMON_REG_LIST(id), \ + .AUX_RESET_MASK = 0 \ +} + +static const struct dce110_aux_registers aux_engine_regs[] = { + aux_engine_regs(0), + aux_engine_regs(1), + aux_engine_regs(2), + aux_engine_regs(3), + aux_engine_regs(4), + aux_engine_regs(5) +}; + +#define tf_regs(id)\ +[id] = {\ + TF_REG_LIST_DCN10(id),\ +} + +static const struct dcn_dpp_registers tf_regs[] = { + tf_regs(0), + tf_regs(1), + tf_regs(2), + tf_regs(3), +}; + +static const struct dcn_dpp_shift tf_shift = { + TF_REG_LIST_SH_MASK_DCN10(__SHIFT), + TF_DEBUG_REG_LIST_SH_DCN10 + +}; + +static const struct dcn_dpp_mask tf_mask = { + TF_REG_LIST_SH_MASK_DCN10(_MASK), + TF_DEBUG_REG_LIST_MASK_DCN10 +}; + +static const struct dcn_mpc_registers mpc_regs = { + MPC_COMMON_REG_LIST_DCN1_0(0), + MPC_COMMON_REG_LIST_DCN1_0(1), + MPC_COMMON_REG_LIST_DCN1_0(2), + MPC_COMMON_REG_LIST_DCN1_0(3), + MPC_OUT_MUX_COMMON_REG_LIST_DCN1_0(0), + MPC_OUT_MUX_COMMON_REG_LIST_DCN1_0(1), + MPC_OUT_MUX_COMMON_REG_LIST_DCN1_0(2), + MPC_OUT_MUX_COMMON_REG_LIST_DCN1_0(3) +}; + +static const struct dcn_mpc_shift mpc_shift = { + MPC_COMMON_MASK_SH_LIST_DCN1_0(__SHIFT),\ + SFRB(CUR_VUPDATE_LOCK_SET, CUR0_VUPDATE_LOCK_SET0, CUR0_VUPDATE_LOCK_SET, __SHIFT) +}; + +static const struct dcn_mpc_mask mpc_mask = { + MPC_COMMON_MASK_SH_LIST_DCN1_0(_MASK),\ + SFRB(CUR_VUPDATE_LOCK_SET, CUR0_VUPDATE_LOCK_SET0, CUR0_VUPDATE_LOCK_SET, _MASK) +}; + +#define tg_regs(id)\ +[id] = {TG_COMMON_REG_LIST_DCN1_0(id)} + +static const struct dcn_optc_registers tg_regs[] = { + tg_regs(0), + tg_regs(1), + tg_regs(2), + tg_regs(3), +}; + +static const struct dcn_optc_shift tg_shift = { + TG_COMMON_MASK_SH_LIST_DCN1_0(__SHIFT) +}; + +static const struct dcn_optc_mask tg_mask = { + TG_COMMON_MASK_SH_LIST_DCN1_0(_MASK) +}; + +static const struct bios_registers bios_regs = { + NBIO_SR(BIOS_SCRATCH_3), + NBIO_SR(BIOS_SCRATCH_6) +}; + +#define hubp_regs(id)\ +[id] = {\ + HUBP_REG_LIST_DCN10(id)\ +} + +static const struct dcn_mi_registers hubp_regs[] = { + hubp_regs(0), + hubp_regs(1), + hubp_regs(2), + hubp_regs(3), +}; + +static const struct dcn_mi_shift hubp_shift = { + HUBP_MASK_SH_LIST_DCN10(__SHIFT) +}; + +static const struct dcn_mi_mask hubp_mask = { + HUBP_MASK_SH_LIST_DCN10(_MASK) +}; + +static const struct dcn_hubbub_registers hubbub_reg = { + HUBBUB_REG_LIST_DCN10(0) +}; + +static const struct dcn_hubbub_shift hubbub_shift = { + HUBBUB_MASK_SH_LIST_DCN10(__SHIFT) +}; + +static const struct dcn_hubbub_mask hubbub_mask = { + HUBBUB_MASK_SH_LIST_DCN10(_MASK) +}; + +static int map_transmitter_id_to_phy_instance( + enum transmitter transmitter) +{ + switch (transmitter) { + case TRANSMITTER_UNIPHY_A: + return 0; + break; + case TRANSMITTER_UNIPHY_B: + return 1; + break; + case TRANSMITTER_UNIPHY_C: + return 2; + break; + case TRANSMITTER_UNIPHY_D: + return 3; + break; + default: + ASSERT(0); + return 0; + } +} + +#define clk_src_regs(index, pllid)\ +[index] = {\ + CS_COMMON_REG_LIST_DCN1_0(index, pllid),\ +} + +static const struct dce110_clk_src_regs clk_src_regs[] = { + clk_src_regs(0, A), + clk_src_regs(1, B), + clk_src_regs(2, C), + clk_src_regs(3, D) +}; + +static const struct dce110_clk_src_shift cs_shift = { + CS_COMMON_MASK_SH_LIST_DCN1_0(__SHIFT) +}; + +static const struct dce110_clk_src_mask cs_mask = { + CS_COMMON_MASK_SH_LIST_DCN1_0(_MASK) +}; + +static const struct resource_caps res_cap = { + .num_timing_generator = 4, + .num_opp = 4, + .num_video_plane = 4, + .num_audio = 4, + .num_stream_encoder = 4, + .num_pll = 4, + .num_ddc = 4, +}; + +static const struct resource_caps rv2_res_cap = { + .num_timing_generator = 3, + .num_opp = 3, + .num_video_plane = 3, + .num_audio = 3, + .num_stream_encoder = 3, + .num_pll = 3, + .num_ddc = 4, +}; + +static const struct dc_plane_cap plane_cap = { + .type = DC_PLANE_TYPE_DCN_UNIVERSAL, + .per_pixel_alpha = true, + + .pixel_format_support = { + .argb8888 = true, + .nv12 = true, + .fp16 = true, + .p010 = true + }, + + .max_upscale_factor = { + .argb8888 = 16000, + .nv12 = 16000, + .fp16 = 1 + }, + + .max_downscale_factor = { + .argb8888 = 250, + .nv12 = 250, + .fp16 = 1 + } +}; + +static const struct dc_debug_options debug_defaults_drv = { + .sanity_checks = true, + .disable_dmcu = false, + .force_abm_enable = false, + .timing_trace = false, + .clock_trace = true, + + /* raven smu dones't allow 0 disp clk, + * smu min disp clk limit is 50Mhz + * keep min disp clk 100Mhz avoid smu hang + */ + .min_disp_clk_khz = 100000, + + .disable_pplib_clock_request = false, + .disable_pplib_wm_range = false, + .pplib_wm_report_mode = WM_REPORT_DEFAULT, + .pipe_split_policy = MPC_SPLIT_DYNAMIC, + .force_single_disp_pipe_split = true, + .disable_dcc = DCC_ENABLE, + .voltage_align_fclk = true, + .disable_stereo_support = true, + .vsr_support = true, + .performance_trace = false, + .az_endpoint_mute_only = true, + .recovery_enabled = false, /*enable this by default after testing.*/ + .max_downscale_src_width = 3840, + .underflow_assert_delay_us = 0xFFFFFFFF, + .enable_legacy_fast_update = true, + .using_dml2 = false, +}; + +static const struct dc_debug_options debug_defaults_diags = { + .disable_dmcu = false, + .force_abm_enable = false, + .timing_trace = true, + .clock_trace = true, + .disable_stutter = true, + .disable_pplib_clock_request = true, + .disable_pplib_wm_range = true, + .underflow_assert_delay_us = 0xFFFFFFFF, +}; + +static void dcn10_dpp_destroy(struct dpp **dpp) +{ + kfree(TO_DCN10_DPP(*dpp)); + *dpp = NULL; +} + +static struct dpp *dcn10_dpp_create( + struct dc_context *ctx, + uint32_t inst) +{ + struct dcn10_dpp *dpp = + kzalloc(sizeof(struct dcn10_dpp), GFP_KERNEL); + + if (!dpp) + return NULL; + + dpp1_construct(dpp, ctx, inst, + &tf_regs[inst], &tf_shift, &tf_mask); + return &dpp->base; +} + +static struct input_pixel_processor *dcn10_ipp_create( + struct dc_context *ctx, uint32_t inst) +{ + struct dcn10_ipp *ipp = + kzalloc(sizeof(struct dcn10_ipp), GFP_KERNEL); + + if (!ipp) { + BREAK_TO_DEBUGGER(); + return NULL; + } + + dcn10_ipp_construct(ipp, ctx, inst, + &ipp_regs[inst], &ipp_shift, &ipp_mask); + return &ipp->base; +} + + +static struct output_pixel_processor *dcn10_opp_create( + struct dc_context *ctx, uint32_t inst) +{ + struct dcn10_opp *opp = + kzalloc(sizeof(struct dcn10_opp), GFP_KERNEL); + + if (!opp) { + BREAK_TO_DEBUGGER(); + return NULL; + } + + dcn10_opp_construct(opp, ctx, inst, + &opp_regs[inst], &opp_shift, &opp_mask); + return &opp->base; +} + +static struct dce_aux *dcn10_aux_engine_create(struct dc_context *ctx, + uint32_t inst) +{ + struct aux_engine_dce110 *aux_engine = + kzalloc(sizeof(struct aux_engine_dce110), GFP_KERNEL); + + if (!aux_engine) + return NULL; + + dce110_aux_engine_construct(aux_engine, ctx, inst, + SW_AUX_TIMEOUT_PERIOD_MULTIPLIER * AUX_TIMEOUT_PERIOD, + &aux_engine_regs[inst], + &aux_mask, + &aux_shift, + ctx->dc->caps.extended_aux_timeout_support); + + return &aux_engine->base; +} +#define i2c_inst_regs(id) { I2C_HW_ENGINE_COMMON_REG_LIST(id) } + +static const struct dce_i2c_registers i2c_hw_regs[] = { + i2c_inst_regs(1), + i2c_inst_regs(2), + i2c_inst_regs(3), + i2c_inst_regs(4), + i2c_inst_regs(5), + i2c_inst_regs(6), +}; + +static const struct dce_i2c_shift i2c_shifts = { + I2C_COMMON_MASK_SH_LIST_DCE110(__SHIFT) +}; + +static const struct dce_i2c_mask i2c_masks = { + I2C_COMMON_MASK_SH_LIST_DCE110(_MASK) +}; + +static struct dce_i2c_hw *dcn10_i2c_hw_create(struct dc_context *ctx, + uint32_t inst) +{ + struct dce_i2c_hw *dce_i2c_hw = + kzalloc(sizeof(struct dce_i2c_hw), GFP_KERNEL); + + if (!dce_i2c_hw) + return NULL; + + dcn1_i2c_hw_construct(dce_i2c_hw, ctx, inst, + &i2c_hw_regs[inst], &i2c_shifts, &i2c_masks); + + return dce_i2c_hw; +} +static struct mpc *dcn10_mpc_create(struct dc_context *ctx) +{ + struct dcn10_mpc *mpc10 = kzalloc(sizeof(struct dcn10_mpc), + GFP_KERNEL); + + if (!mpc10) + return NULL; + + dcn10_mpc_construct(mpc10, ctx, + &mpc_regs, + &mpc_shift, + &mpc_mask, + 4); + + return &mpc10->base; +} + +static struct hubbub *dcn10_hubbub_create(struct dc_context *ctx) +{ + struct dcn10_hubbub *dcn10_hubbub = kzalloc(sizeof(struct dcn10_hubbub), + GFP_KERNEL); + + if (!dcn10_hubbub) + return NULL; + + hubbub1_construct(&dcn10_hubbub->base, ctx, + &hubbub_reg, + &hubbub_shift, + &hubbub_mask); + + return &dcn10_hubbub->base; +} + +static struct timing_generator *dcn10_timing_generator_create( + struct dc_context *ctx, + uint32_t instance) +{ + struct optc *tgn10 = + kzalloc(sizeof(struct optc), GFP_KERNEL); + + if (!tgn10) + return NULL; + + tgn10->base.inst = instance; + tgn10->base.ctx = ctx; + + tgn10->tg_regs = &tg_regs[instance]; + tgn10->tg_shift = &tg_shift; + tgn10->tg_mask = &tg_mask; + + dcn10_timing_generator_init(tgn10); + + return &tgn10->base; +} + +static const struct encoder_feature_support link_enc_feature = { + .max_hdmi_deep_color = COLOR_DEPTH_121212, + .max_hdmi_pixel_clock = 600000, + .hdmi_ycbcr420_supported = true, + .dp_ycbcr420_supported = true, + .flags.bits.IS_HBR2_CAPABLE = true, + .flags.bits.IS_HBR3_CAPABLE = true, + .flags.bits.IS_TPS3_CAPABLE = true, + .flags.bits.IS_TPS4_CAPABLE = true +}; + +static struct link_encoder *dcn10_link_encoder_create( + struct dc_context *ctx, + const struct encoder_init_data *enc_init_data) +{ + struct dcn10_link_encoder *enc10 = + kzalloc(sizeof(struct dcn10_link_encoder), GFP_KERNEL); + int link_regs_id; + + if (!enc10) + return NULL; + + link_regs_id = + map_transmitter_id_to_phy_instance(enc_init_data->transmitter); + + dcn10_link_encoder_construct(enc10, + enc_init_data, + &link_enc_feature, + &link_enc_regs[link_regs_id], + &link_enc_aux_regs[enc_init_data->channel - 1], + &link_enc_hpd_regs[enc_init_data->hpd_source], + &le_shift, + &le_mask); + + return &enc10->base; +} + +static struct panel_cntl *dcn10_panel_cntl_create(const struct panel_cntl_init_data *init_data) +{ + struct dce_panel_cntl *panel_cntl = + kzalloc(sizeof(struct dce_panel_cntl), GFP_KERNEL); + + if (!panel_cntl) + return NULL; + + dce_panel_cntl_construct(panel_cntl, + init_data, + &panel_cntl_regs[init_data->inst], + &panel_cntl_shift, + &panel_cntl_mask); + + return &panel_cntl->base; +} + +static struct clock_source *dcn10_clock_source_create( + struct dc_context *ctx, + struct dc_bios *bios, + enum clock_source_id id, + const struct dce110_clk_src_regs *regs, + bool dp_clk_src) +{ + struct dce110_clk_src *clk_src = + kzalloc(sizeof(struct dce110_clk_src), GFP_KERNEL); + + if (!clk_src) + return NULL; + + if (dce112_clk_src_construct(clk_src, ctx, bios, id, + regs, &cs_shift, &cs_mask)) { + clk_src->base.dp_clk_src = dp_clk_src; + return &clk_src->base; + } + + kfree(clk_src); + BREAK_TO_DEBUGGER(); + return NULL; +} + +static void read_dce_straps( + struct dc_context *ctx, + struct resource_straps *straps) +{ + generic_reg_get(ctx, mmDC_PINSTRAPS + BASE(mmDC_PINSTRAPS_BASE_IDX), + FN(DC_PINSTRAPS, DC_PINSTRAPS_AUDIO), &straps->dc_pinstraps_audio); +} + +static struct audio *create_audio( + struct dc_context *ctx, unsigned int inst) +{ + return dce_audio_create(ctx, inst, + &audio_regs[inst], &audio_shift, &audio_mask); +} + +static struct stream_encoder *dcn10_stream_encoder_create( + enum engine_id eng_id, + struct dc_context *ctx) +{ + struct dcn10_stream_encoder *enc1 = + kzalloc(sizeof(struct dcn10_stream_encoder), GFP_KERNEL); + + if (!enc1) + return NULL; + + dcn10_stream_encoder_construct(enc1, ctx, ctx->dc_bios, eng_id, + &stream_enc_regs[eng_id], + &se_shift, &se_mask); + return &enc1->base; +} + +static const struct dce_hwseq_registers hwseq_reg = { + HWSEQ_DCN1_REG_LIST() +}; + +static const struct dce_hwseq_shift hwseq_shift = { + HWSEQ_DCN1_MASK_SH_LIST(__SHIFT) +}; + +static const struct dce_hwseq_mask hwseq_mask = { + HWSEQ_DCN1_MASK_SH_LIST(_MASK) +}; + +static struct dce_hwseq *dcn10_hwseq_create( + struct dc_context *ctx) +{ + struct dce_hwseq *hws = kzalloc(sizeof(struct dce_hwseq), GFP_KERNEL); + + if (hws) { + hws->ctx = ctx; + hws->regs = &hwseq_reg; + hws->shifts = &hwseq_shift; + hws->masks = &hwseq_mask; + hws->wa.DEGVIDCN10_253 = true; + hws->wa.false_optc_underflow = true; + hws->wa.DEGVIDCN10_254 = true; + + if ((ctx->asic_id.chip_family == FAMILY_RV) && + ASICREV_IS_RAVEN2(ctx->asic_id.hw_internal_rev)) + switch (ctx->asic_id.pci_revision_id) { + case PRID_POLLOCK_94: + case PRID_POLLOCK_95: + case PRID_POLLOCK_E9: + case PRID_POLLOCK_EA: + case PRID_POLLOCK_EB: + hws->wa.wait_hubpret_read_start_during_mpo_transition = true; + break; + default: + hws->wa.wait_hubpret_read_start_during_mpo_transition = false; + break; + } + } + return hws; +} + +static const struct resource_create_funcs res_create_funcs = { + .read_dce_straps = read_dce_straps, + .create_audio = create_audio, + .create_stream_encoder = dcn10_stream_encoder_create, + .create_hwseq = dcn10_hwseq_create, +}; + +static void dcn10_clock_source_destroy(struct clock_source **clk_src) +{ + kfree(TO_DCE110_CLK_SRC(*clk_src)); + *clk_src = NULL; +} + +static struct pp_smu_funcs *dcn10_pp_smu_create(struct dc_context *ctx) +{ + struct pp_smu_funcs *pp_smu = kzalloc(sizeof(*pp_smu), GFP_KERNEL); + + if (!pp_smu) + return pp_smu; + + dm_pp_get_funcs(ctx, pp_smu); + return pp_smu; +} + +static void dcn10_resource_destruct(struct dcn10_resource_pool *pool) +{ + unsigned int i; + + for (i = 0; i < pool->base.stream_enc_count; i++) { + if (pool->base.stream_enc[i] != NULL) { + kfree(DCN10STRENC_FROM_STRENC(pool->base.stream_enc[i])); + pool->base.stream_enc[i] = NULL; + } + } + + if (pool->base.mpc != NULL) { + kfree(TO_DCN10_MPC(pool->base.mpc)); + pool->base.mpc = NULL; + } + + kfree(pool->base.hubbub); + pool->base.hubbub = NULL; + + for (i = 0; i < pool->base.pipe_count; i++) { + if (pool->base.opps[i] != NULL) + pool->base.opps[i]->funcs->opp_destroy(&pool->base.opps[i]); + + if (pool->base.dpps[i] != NULL) + dcn10_dpp_destroy(&pool->base.dpps[i]); + + if (pool->base.ipps[i] != NULL) + pool->base.ipps[i]->funcs->ipp_destroy(&pool->base.ipps[i]); + + if (pool->base.hubps[i] != NULL) { + kfree(TO_DCN10_HUBP(pool->base.hubps[i])); + pool->base.hubps[i] = NULL; + } + + if (pool->base.irqs != NULL) { + dal_irq_service_destroy(&pool->base.irqs); + } + + if (pool->base.timing_generators[i] != NULL) { + kfree(DCN10TG_FROM_TG(pool->base.timing_generators[i])); + pool->base.timing_generators[i] = NULL; + } + } + + for (i = 0; i < pool->base.res_cap->num_ddc; i++) { + if (pool->base.engines[i] != NULL) + dce110_engine_destroy(&pool->base.engines[i]); + kfree(pool->base.hw_i2cs[i]); + pool->base.hw_i2cs[i] = NULL; + kfree(pool->base.sw_i2cs[i]); + pool->base.sw_i2cs[i] = NULL; + } + + for (i = 0; i < pool->base.audio_count; i++) { + if (pool->base.audios[i]) + dce_aud_destroy(&pool->base.audios[i]); + } + + for (i = 0; i < pool->base.clk_src_count; i++) { + if (pool->base.clock_sources[i] != NULL) { + dcn10_clock_source_destroy(&pool->base.clock_sources[i]); + pool->base.clock_sources[i] = NULL; + } + } + + if (pool->base.dp_clock_source != NULL) { + dcn10_clock_source_destroy(&pool->base.dp_clock_source); + pool->base.dp_clock_source = NULL; + } + + if (pool->base.abm != NULL) + dce_abm_destroy(&pool->base.abm); + + if (pool->base.dmcu != NULL) + dce_dmcu_destroy(&pool->base.dmcu); + + kfree(pool->base.pp_smu); +} + +static struct hubp *dcn10_hubp_create( + struct dc_context *ctx, + uint32_t inst) +{ + struct dcn10_hubp *hubp1 = + kzalloc(sizeof(struct dcn10_hubp), GFP_KERNEL); + + if (!hubp1) + return NULL; + + dcn10_hubp_construct(hubp1, ctx, inst, + &hubp_regs[inst], &hubp_shift, &hubp_mask); + return &hubp1->base; +} + +static void get_pixel_clock_parameters( + const struct pipe_ctx *pipe_ctx, + struct pixel_clk_params *pixel_clk_params) +{ + const struct dc_stream_state *stream = pipe_ctx->stream; + pixel_clk_params->requested_pix_clk_100hz = stream->timing.pix_clk_100hz; + pixel_clk_params->encoder_object_id = stream->link->link_enc->id; + pixel_clk_params->signal_type = pipe_ctx->stream->signal; + pixel_clk_params->controller_id = pipe_ctx->stream_res.tg->inst + 1; + /* TODO: un-hardcode*/ + pixel_clk_params->requested_sym_clk = LINK_RATE_LOW * + LINK_RATE_REF_FREQ_IN_KHZ; + pixel_clk_params->flags.ENABLE_SS = 0; + pixel_clk_params->color_depth = + stream->timing.display_color_depth; + pixel_clk_params->flags.DISPLAY_BLANKED = 1; + pixel_clk_params->pixel_encoding = stream->timing.pixel_encoding; + + if (stream->timing.pixel_encoding == PIXEL_ENCODING_YCBCR422) + pixel_clk_params->color_depth = COLOR_DEPTH_888; + + if (stream->timing.pixel_encoding == PIXEL_ENCODING_YCBCR420) + pixel_clk_params->requested_pix_clk_100hz /= 2; + if (stream->timing.timing_3d_format == TIMING_3D_FORMAT_HW_FRAME_PACKING) + pixel_clk_params->requested_pix_clk_100hz *= 2; + +} + +static void build_clamping_params(struct dc_stream_state *stream) +{ + stream->clamping.clamping_level = CLAMPING_FULL_RANGE; + stream->clamping.c_depth = stream->timing.display_color_depth; + stream->clamping.pixel_encoding = stream->timing.pixel_encoding; +} + +static void build_pipe_hw_param(struct pipe_ctx *pipe_ctx) +{ + + get_pixel_clock_parameters(pipe_ctx, &pipe_ctx->stream_res.pix_clk_params); + + pipe_ctx->clock_source->funcs->get_pix_clk_dividers( + pipe_ctx->clock_source, + &pipe_ctx->stream_res.pix_clk_params, + &pipe_ctx->pll_settings); + + pipe_ctx->stream->clamping.pixel_encoding = pipe_ctx->stream->timing.pixel_encoding; + + resource_build_bit_depth_reduction_params(pipe_ctx->stream, + &pipe_ctx->stream->bit_depth_params); + build_clamping_params(pipe_ctx->stream); +} + +static enum dc_status build_mapped_resource( + const struct dc *dc, + struct dc_state *context, + struct dc_stream_state *stream) +{ + struct pipe_ctx *pipe_ctx = resource_get_otg_master_for_stream(&context->res_ctx, stream); + + if (!pipe_ctx) + return DC_ERROR_UNEXPECTED; + + build_pipe_hw_param(pipe_ctx); + return DC_OK; +} + +static enum dc_status dcn10_add_stream_to_ctx( + struct dc *dc, + struct dc_state *new_ctx, + struct dc_stream_state *dc_stream) +{ + enum dc_status result = DC_ERROR_UNEXPECTED; + + result = resource_map_pool_resources(dc, new_ctx, dc_stream); + + if (result == DC_OK) + result = resource_map_phy_clock_resources(dc, new_ctx, dc_stream); + + + if (result == DC_OK) + result = build_mapped_resource(dc, new_ctx, dc_stream); + + return result; +} + +static struct pipe_ctx *dcn10_acquire_free_pipe_for_layer( + const struct dc_state *cur_ctx, + struct dc_state *new_ctx, + const struct resource_pool *pool, + const struct pipe_ctx *opp_head_pipe) +{ + struct resource_context *res_ctx = &new_ctx->res_ctx; + struct pipe_ctx *head_pipe = resource_get_otg_master_for_stream(res_ctx, opp_head_pipe->stream); + struct pipe_ctx *idle_pipe = resource_find_free_secondary_pipe_legacy(res_ctx, pool, head_pipe); + + if (!head_pipe) { + ASSERT(0); + return NULL; + } + + if (!idle_pipe) + return NULL; + + idle_pipe->stream = head_pipe->stream; + idle_pipe->stream_res.tg = head_pipe->stream_res.tg; + idle_pipe->stream_res.abm = head_pipe->stream_res.abm; + idle_pipe->stream_res.opp = head_pipe->stream_res.opp; + + idle_pipe->plane_res.hubp = pool->hubps[idle_pipe->pipe_idx]; + idle_pipe->plane_res.ipp = pool->ipps[idle_pipe->pipe_idx]; + idle_pipe->plane_res.dpp = pool->dpps[idle_pipe->pipe_idx]; + idle_pipe->plane_res.mpcc_inst = pool->dpps[idle_pipe->pipe_idx]->inst; + + return idle_pipe; +} + +static bool dcn10_get_dcc_compression_cap(const struct dc *dc, + const struct dc_dcc_surface_param *input, + struct dc_surface_dcc_cap *output) +{ + return dc->res_pool->hubbub->funcs->get_dcc_compression_cap( + dc->res_pool->hubbub, + input, + output); +} + +static void dcn10_destroy_resource_pool(struct resource_pool **pool) +{ + struct dcn10_resource_pool *dcn10_pool = TO_DCN10_RES_POOL(*pool); + + dcn10_resource_destruct(dcn10_pool); + kfree(dcn10_pool); + *pool = NULL; +} + +static bool dcn10_validate_bandwidth( + struct dc *dc, + struct dc_state *context, + bool fast_validate) +{ + bool voltage_supported; + + DC_FP_START(); + voltage_supported = dcn_validate_bandwidth(dc, context, fast_validate); + DC_FP_END(); + + return voltage_supported; +} + +static enum dc_status dcn10_validate_plane(const struct dc_plane_state *plane_state, struct dc_caps *caps) +{ + if (plane_state->format >= SURFACE_PIXEL_FORMAT_VIDEO_BEGIN + && caps->max_video_width != 0 + && plane_state->src_rect.width > caps->max_video_width) + return DC_FAIL_SURFACE_VALIDATE; + + return DC_OK; +} + +static enum dc_status dcn10_validate_global(struct dc *dc, struct dc_state *context) +{ + int i, j; + bool video_down_scaled = false; + bool video_large = false; + bool desktop_large = false; + bool dcc_disabled = false; + bool mpo_enabled = false; + + for (i = 0; i < context->stream_count; i++) { + if (context->stream_status[i].plane_count == 0) + continue; + + if (context->stream_status[i].plane_count > 2) + return DC_FAIL_UNSUPPORTED_1; + + if (context->stream_status[i].plane_count > 1) + mpo_enabled = true; + + for (j = 0; j < context->stream_status[i].plane_count; j++) { + struct dc_plane_state *plane = + context->stream_status[i].plane_states[j]; + + + if (plane->format >= SURFACE_PIXEL_FORMAT_VIDEO_BEGIN) { + + if (plane->src_rect.width > plane->dst_rect.width || + plane->src_rect.height > plane->dst_rect.height) + video_down_scaled = true; + + if (plane->src_rect.width >= 3840) + video_large = true; + + } else { + if (plane->src_rect.width >= 3840) + desktop_large = true; + if (!plane->dcc.enable) + dcc_disabled = true; + } + } + } + + /* Disable MPO in multi-display configurations. */ + if (context->stream_count > 1 && mpo_enabled) + return DC_FAIL_UNSUPPORTED_1; + + /* + * Workaround: On DCN10 there is UMC issue that causes underflow when + * playing 4k video on 4k desktop with video downscaled and single channel + * memory + */ + if (video_large && desktop_large && video_down_scaled && dcc_disabled && + dc->dcn_soc->number_of_channels == 1) + return DC_FAIL_SURFACE_VALIDATE; + + return DC_OK; +} + +static enum dc_status dcn10_patch_unknown_plane_state(struct dc_plane_state *plane_state) +{ + enum surface_pixel_format surf_pix_format = plane_state->format; + unsigned int bpp = resource_pixel_format_to_bpp(surf_pix_format); + + enum swizzle_mode_values swizzle = DC_SW_LINEAR; + + if (bpp == 64) + swizzle = DC_SW_64KB_D; + else + swizzle = DC_SW_64KB_S; + + plane_state->tiling_info.gfx9.swizzle = swizzle; + return DC_OK; +} + +struct stream_encoder *dcn10_find_first_free_match_stream_enc_for_link( + struct resource_context *res_ctx, + const struct resource_pool *pool, + struct dc_stream_state *stream) +{ + int i; + int j = -1; + struct dc_link *link = stream->link; + + for (i = 0; i < pool->stream_enc_count; i++) { + if (!res_ctx->is_stream_enc_acquired[i] && + pool->stream_enc[i]) { + /* Store first available for MST second display + * in daisy chain use case + */ + j = i; + if (link->ep_type == DISPLAY_ENDPOINT_PHY && pool->stream_enc[i]->id == + link->link_enc->preferred_engine) + return pool->stream_enc[i]; + } + } + + /* + * For CZ and later, we can allow DIG FE and BE to differ for all display types + */ + + if (j >= 0) + return pool->stream_enc[j]; + + return NULL; +} + +static const struct dc_cap_funcs cap_funcs = { + .get_dcc_compression_cap = dcn10_get_dcc_compression_cap +}; + +static const struct resource_funcs dcn10_res_pool_funcs = { + .destroy = dcn10_destroy_resource_pool, + .link_enc_create = dcn10_link_encoder_create, + .panel_cntl_create = dcn10_panel_cntl_create, + .validate_bandwidth = dcn10_validate_bandwidth, + .acquire_free_pipe_as_secondary_dpp_pipe = dcn10_acquire_free_pipe_for_layer, + .validate_plane = dcn10_validate_plane, + .validate_global = dcn10_validate_global, + .add_stream_to_ctx = dcn10_add_stream_to_ctx, + .patch_unknown_plane_state = dcn10_patch_unknown_plane_state, + .find_first_free_match_stream_enc_for_link = dcn10_find_first_free_match_stream_enc_for_link +}; + +static uint32_t read_pipe_fuses(struct dc_context *ctx) +{ + uint32_t value = dm_read_reg_soc15(ctx, mmCC_DC_PIPE_DIS, 0); + /* RV1 support max 4 pipes */ + value = value & 0xf; + return value; +} + +static bool verify_clock_values(struct dm_pp_clock_levels_with_voltage *clks) +{ + int i; + + if (clks->num_levels == 0) + return false; + + for (i = 0; i < clks->num_levels; i++) + /* Ensure that the result is sane */ + if (clks->data[i].clocks_in_khz == 0) + return false; + + return true; +} + +static bool dcn10_resource_construct( + uint8_t num_virtual_links, + struct dc *dc, + struct dcn10_resource_pool *pool) +{ + int i; + int j; + struct dc_context *ctx = dc->ctx; + uint32_t pipe_fuses = read_pipe_fuses(ctx); + struct dm_pp_clock_levels_with_voltage fclks = {0}, dcfclks = {0}; + int min_fclk_khz, min_dcfclk_khz, socclk_khz; + bool res; + + ctx->dc_bios->regs = &bios_regs; + + if (ctx->dce_version == DCN_VERSION_1_01) + pool->base.res_cap = &rv2_res_cap; + else + pool->base.res_cap = &res_cap; + pool->base.funcs = &dcn10_res_pool_funcs; + + /* + * TODO fill in from actual raven resource when we create + * more than virtual encoder + */ + + /************************************************* + * Resource + asic cap harcoding * + *************************************************/ + pool->base.underlay_pipe_index = NO_UNDERLAY_PIPE; + + /* max pipe num for ASIC before check pipe fuses */ + pool->base.pipe_count = pool->base.res_cap->num_timing_generator; + + if (dc->ctx->dce_version == DCN_VERSION_1_01) + pool->base.pipe_count = 3; + dc->caps.max_video_width = 3840; + dc->caps.max_downscale_ratio = 200; + dc->caps.i2c_speed_in_khz = 100; + dc->caps.i2c_speed_in_khz_hdcp = 100; /*1.4 w/a not applied by default*/ + dc->caps.max_cursor_size = 256; + dc->caps.min_horizontal_blanking_period = 80; + dc->caps.max_slave_planes = 1; + dc->caps.max_slave_yuv_planes = 1; + dc->caps.max_slave_rgb_planes = 0; + dc->caps.is_apu = true; + dc->caps.post_blend_color_processing = false; + dc->caps.extended_aux_timeout_support = false; + + /* Raven DP PHY HBR2 eye diagram pattern is not stable. Use TP4 */ + dc->caps.force_dp_tps4_for_cp2520 = true; + + /* Color pipeline capabilities */ + dc->caps.color.dpp.dcn_arch = 1; + dc->caps.color.dpp.input_lut_shared = 1; + dc->caps.color.dpp.icsc = 1; + dc->caps.color.dpp.dgam_ram = 1; + dc->caps.color.dpp.dgam_rom_caps.srgb = 1; + dc->caps.color.dpp.dgam_rom_caps.bt2020 = 1; + dc->caps.color.dpp.dgam_rom_caps.gamma2_2 = 0; + dc->caps.color.dpp.dgam_rom_caps.pq = 0; + dc->caps.color.dpp.dgam_rom_caps.hlg = 0; + dc->caps.color.dpp.post_csc = 0; + dc->caps.color.dpp.gamma_corr = 0; + dc->caps.color.dpp.dgam_rom_for_yuv = 1; + + dc->caps.color.dpp.hw_3d_lut = 0; + dc->caps.color.dpp.ogam_ram = 1; // RGAM on DCN1 + dc->caps.color.dpp.ogam_rom_caps.srgb = 1; + dc->caps.color.dpp.ogam_rom_caps.bt2020 = 1; + dc->caps.color.dpp.ogam_rom_caps.gamma2_2 = 0; + dc->caps.color.dpp.ogam_rom_caps.pq = 0; + dc->caps.color.dpp.ogam_rom_caps.hlg = 0; + dc->caps.color.dpp.ocsc = 1; + + /* no post-blend color operations */ + dc->caps.color.mpc.gamut_remap = 0; + dc->caps.color.mpc.num_3dluts = 0; + dc->caps.color.mpc.shared_3d_lut = 0; + dc->caps.color.mpc.ogam_ram = 0; + dc->caps.color.mpc.ogam_rom_caps.srgb = 0; + dc->caps.color.mpc.ogam_rom_caps.bt2020 = 0; + dc->caps.color.mpc.ogam_rom_caps.gamma2_2 = 0; + dc->caps.color.mpc.ogam_rom_caps.pq = 0; + dc->caps.color.mpc.ogam_rom_caps.hlg = 0; + dc->caps.color.mpc.ocsc = 0; + + if (dc->ctx->dce_environment == DCE_ENV_PRODUCTION_DRV) + dc->debug = debug_defaults_drv; + else + dc->debug = debug_defaults_diags; + + /************************************************* + * Create resources * + *************************************************/ + + pool->base.clock_sources[DCN10_CLK_SRC_PLL0] = + dcn10_clock_source_create(ctx, ctx->dc_bios, + CLOCK_SOURCE_COMBO_PHY_PLL0, + &clk_src_regs[0], false); + pool->base.clock_sources[DCN10_CLK_SRC_PLL1] = + dcn10_clock_source_create(ctx, ctx->dc_bios, + CLOCK_SOURCE_COMBO_PHY_PLL1, + &clk_src_regs[1], false); + pool->base.clock_sources[DCN10_CLK_SRC_PLL2] = + dcn10_clock_source_create(ctx, ctx->dc_bios, + CLOCK_SOURCE_COMBO_PHY_PLL2, + &clk_src_regs[2], false); + + if (dc->ctx->dce_version == DCN_VERSION_1_0) { + pool->base.clock_sources[DCN10_CLK_SRC_PLL3] = + dcn10_clock_source_create(ctx, ctx->dc_bios, + CLOCK_SOURCE_COMBO_PHY_PLL3, + &clk_src_regs[3], false); + } + + pool->base.clk_src_count = DCN10_CLK_SRC_TOTAL; + + if (dc->ctx->dce_version == DCN_VERSION_1_01) + pool->base.clk_src_count = DCN101_CLK_SRC_TOTAL; + + pool->base.dp_clock_source = + dcn10_clock_source_create(ctx, ctx->dc_bios, + CLOCK_SOURCE_ID_DP_DTO, + /* todo: not reuse phy_pll registers */ + &clk_src_regs[0], true); + + for (i = 0; i < pool->base.clk_src_count; i++) { + if (pool->base.clock_sources[i] == NULL) { + dm_error("DC: failed to create clock sources!\n"); + BREAK_TO_DEBUGGER(); + goto fail; + } + } + + pool->base.dmcu = dcn10_dmcu_create(ctx, + &dmcu_regs, + &dmcu_shift, + &dmcu_mask); + if (pool->base.dmcu == NULL) { + dm_error("DC: failed to create dmcu!\n"); + BREAK_TO_DEBUGGER(); + goto fail; + } + + pool->base.abm = dce_abm_create(ctx, + &abm_regs, + &abm_shift, + &abm_mask); + if (pool->base.abm == NULL) { + dm_error("DC: failed to create abm!\n"); + BREAK_TO_DEBUGGER(); + goto fail; + } + + dml_init_instance(&dc->dml, &dcn1_0_soc, &dcn1_0_ip, DML_PROJECT_RAVEN1); + memcpy(dc->dcn_ip, &dcn10_ip_defaults, sizeof(dcn10_ip_defaults)); + memcpy(dc->dcn_soc, &dcn10_soc_defaults, sizeof(dcn10_soc_defaults)); + + DC_FP_START(); + dcn10_resource_construct_fp(dc); + DC_FP_END(); + + if (!dc->config.is_vmin_only_asic) + if (ASICREV_IS_RAVEN2(dc->ctx->asic_id.hw_internal_rev)) + switch (dc->ctx->asic_id.pci_revision_id) { + case PRID_DALI_DE: + case PRID_DALI_DF: + case PRID_DALI_E3: + case PRID_DALI_E4: + case PRID_POLLOCK_94: + case PRID_POLLOCK_95: + case PRID_POLLOCK_E9: + case PRID_POLLOCK_EA: + case PRID_POLLOCK_EB: + dc->config.is_vmin_only_asic = true; + break; + default: + break; + } + + pool->base.pp_smu = dcn10_pp_smu_create(ctx); + + /* + * Right now SMU/PPLIB and DAL all have the AZ D3 force PME notification * + * implemented. So AZ D3 should work.For issue 197007. * + */ + if (pool->base.pp_smu != NULL + && pool->base.pp_smu->rv_funcs.set_pme_wa_enable != NULL) + dc->debug.az_endpoint_mute_only = false; + + + if (!dc->debug.disable_pplib_clock_request) { + /* + * TODO: This is not the proper way to obtain + * fabric_and_dram_bandwidth, should be min(fclk, memclk). + */ + res = dm_pp_get_clock_levels_by_type_with_voltage( + ctx, DM_PP_CLOCK_TYPE_FCLK, &fclks); + + DC_FP_START(); + + if (res) + res = verify_clock_values(&fclks); + + if (res) + dcn_bw_update_from_pplib_fclks(dc, &fclks); + else + BREAK_TO_DEBUGGER(); + + DC_FP_END(); + + res = dm_pp_get_clock_levels_by_type_with_voltage( + ctx, DM_PP_CLOCK_TYPE_DCFCLK, &dcfclks); + + DC_FP_START(); + + if (res) + res = verify_clock_values(&dcfclks); + + if (res) + dcn_bw_update_from_pplib_dcfclks(dc, &dcfclks); + else + BREAK_TO_DEBUGGER(); + + DC_FP_END(); + } + + dcn_bw_sync_calcs_and_dml(dc); + if (!dc->debug.disable_pplib_wm_range) { + dc->res_pool = &pool->base; + DC_FP_START(); + dcn_get_soc_clks( + dc, &min_fclk_khz, &min_dcfclk_khz, &socclk_khz); + DC_FP_END(); + dcn_bw_notify_pplib_of_wm_ranges( + dc, min_fclk_khz, min_dcfclk_khz, socclk_khz); + } + + { + struct irq_service_init_data init_data; + init_data.ctx = dc->ctx; + pool->base.irqs = dal_irq_service_dcn10_create(&init_data); + if (!pool->base.irqs) + goto fail; + } + + /* index to valid pipe resource */ + j = 0; + /* mem input -> ipp -> dpp -> opp -> TG */ + for (i = 0; i < pool->base.pipe_count; i++) { + /* if pipe is disabled, skip instance of HW pipe, + * i.e, skip ASIC register instance + */ + if ((pipe_fuses & (1 << i)) != 0) + continue; + + pool->base.hubps[j] = dcn10_hubp_create(ctx, i); + if (pool->base.hubps[j] == NULL) { + BREAK_TO_DEBUGGER(); + dm_error( + "DC: failed to create memory input!\n"); + goto fail; + } + + pool->base.ipps[j] = dcn10_ipp_create(ctx, i); + if (pool->base.ipps[j] == NULL) { + BREAK_TO_DEBUGGER(); + dm_error( + "DC: failed to create input pixel processor!\n"); + goto fail; + } + + pool->base.dpps[j] = dcn10_dpp_create(ctx, i); + if (pool->base.dpps[j] == NULL) { + BREAK_TO_DEBUGGER(); + dm_error( + "DC: failed to create dpp!\n"); + goto fail; + } + + pool->base.opps[j] = dcn10_opp_create(ctx, i); + if (pool->base.opps[j] == NULL) { + BREAK_TO_DEBUGGER(); + dm_error( + "DC: failed to create output pixel processor!\n"); + goto fail; + } + + pool->base.timing_generators[j] = dcn10_timing_generator_create( + ctx, i); + if (pool->base.timing_generators[j] == NULL) { + BREAK_TO_DEBUGGER(); + dm_error("DC: failed to create tg!\n"); + goto fail; + } + /* check next valid pipe */ + j++; + } + + for (i = 0; i < pool->base.res_cap->num_ddc; i++) { + pool->base.engines[i] = dcn10_aux_engine_create(ctx, i); + if (pool->base.engines[i] == NULL) { + BREAK_TO_DEBUGGER(); + dm_error( + "DC:failed to create aux engine!!\n"); + goto fail; + } + pool->base.hw_i2cs[i] = dcn10_i2c_hw_create(ctx, i); + if (pool->base.hw_i2cs[i] == NULL) { + BREAK_TO_DEBUGGER(); + dm_error( + "DC:failed to create hw i2c!!\n"); + goto fail; + } + pool->base.sw_i2cs[i] = NULL; + } + + /* valid pipe num */ + pool->base.pipe_count = j; + pool->base.timing_generator_count = j; + + /* within dml lib, it is hard code to 4. If ASIC pipe is fused, + * the value may be changed + */ + dc->dml.ip.max_num_dpp = pool->base.pipe_count; + dc->dcn_ip->max_num_dpp = pool->base.pipe_count; + + pool->base.mpc = dcn10_mpc_create(ctx); + if (pool->base.mpc == NULL) { + BREAK_TO_DEBUGGER(); + dm_error("DC: failed to create mpc!\n"); + goto fail; + } + + pool->base.hubbub = dcn10_hubbub_create(ctx); + if (pool->base.hubbub == NULL) { + BREAK_TO_DEBUGGER(); + dm_error("DC: failed to create hubbub!\n"); + goto fail; + } + + if (!resource_construct(num_virtual_links, dc, &pool->base, + &res_create_funcs)) + goto fail; + + dcn10_hw_sequencer_construct(dc); + dc->caps.max_planes = pool->base.pipe_count; + + for (i = 0; i < dc->caps.max_planes; ++i) + dc->caps.planes[i] = plane_cap; + + dc->cap_funcs = cap_funcs; + + return true; + +fail: + + dcn10_resource_destruct(pool); + + return false; +} + +struct resource_pool *dcn10_create_resource_pool( + const struct dc_init_data *init_data, + struct dc *dc) +{ + struct dcn10_resource_pool *pool = + kzalloc(sizeof(struct dcn10_resource_pool), GFP_KERNEL); + + if (!pool) + return NULL; + + if (dcn10_resource_construct(init_data->num_virtual_links, dc, pool)) + return &pool->base; + + kfree(pool); + BREAK_TO_DEBUGGER(); + return NULL; +} diff --git a/drivers/gpu/drm/amd/display/dc/resource/dcn10/dcn10_resource.h b/drivers/gpu/drm/amd/display/dc/resource/dcn10/dcn10_resource.h new file mode 100644 index 000000000000..bf8e33cd8147 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/resource/dcn10/dcn10_resource.h @@ -0,0 +1,56 @@ +/* +* Copyright 2016 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_RESOURCE_DCN10_H__ +#define __DC_RESOURCE_DCN10_H__ + +#include "core_types.h" +#include "dml/dcn10/dcn10_fpu.h" + +#define TO_DCN10_RES_POOL(pool)\ + container_of(pool, struct dcn10_resource_pool, base) + +struct dc; +struct resource_pool; +struct _vcs_dpi_display_pipe_params_st; + +extern struct _vcs_dpi_ip_params_st dcn1_0_ip; +extern struct _vcs_dpi_soc_bounding_box_st dcn1_0_soc; + +struct dcn10_resource_pool { + struct resource_pool base; +}; +struct resource_pool *dcn10_create_resource_pool( + const struct dc_init_data *init_data, + struct dc *dc); + +struct stream_encoder *dcn10_find_first_free_match_stream_enc_for_link( + struct resource_context *res_ctx, + const struct resource_pool *pool, + struct dc_stream_state *stream); + + +#endif /* __DC_RESOURCE_DCN10_H__ */ + diff --git a/drivers/gpu/drm/amd/display/dc/resource/dcn20/dcn20_resource.c b/drivers/gpu/drm/amd/display/dc/resource/dcn20/dcn20_resource.c new file mode 100644 index 000000000000..f04bb5b1471d --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/resource/dcn20/dcn20_resource.c @@ -0,0 +1,2789 @@ +/* +* Copyright 2016 Advanced Micro Devices, Inc. + * Copyright 2019 Raptor Engineering, LLC + * + * 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 + +#include "dm_services.h" +#include "dc.h" + +#include "dcn20/dcn20_init.h" + +#include "resource.h" +#include "include/irq_service_interface.h" +#include "dcn20/dcn20_resource.h" + +#include "dml/dcn20/dcn20_fpu.h" + +#include "dcn10/dcn10_hubp.h" +#include "dcn10/dcn10_ipp.h" +#include "dcn20/dcn20_hubbub.h" +#include "dcn20/dcn20_mpc.h" +#include "dcn20/dcn20_hubp.h" +#include "irq/dcn20/irq_service_dcn20.h" +#include "dcn20/dcn20_dpp.h" +#include "dcn20/dcn20_optc.h" +#include "dcn20/dcn20_hwseq.h" +#include "dce110/dce110_hwseq.h" +#include "dcn10/dcn10_resource.h" +#include "dcn20/dcn20_opp.h" + +#include "dcn20/dcn20_dsc.h" + +#include "dcn20/dcn20_link_encoder.h" +#include "dcn20/dcn20_stream_encoder.h" +#include "dce/dce_clock_source.h" +#include "dce/dce_audio.h" +#include "dce/dce_hwseq.h" +#include "virtual/virtual_stream_encoder.h" +#include "dce110/dce110_resource.h" +#include "dml/display_mode_vba.h" +#include "dcn20/dcn20_dccg.h" +#include "dcn20/dcn20_vmid.h" +#include "dce/dce_panel_cntl.h" + +#include "navi10_ip_offset.h" + +#include "dcn/dcn_2_0_0_offset.h" +#include "dcn/dcn_2_0_0_sh_mask.h" +#include "dpcs/dpcs_2_0_0_offset.h" +#include "dpcs/dpcs_2_0_0_sh_mask.h" + +#include "nbio/nbio_2_3_offset.h" + +#include "dcn20/dcn20_dwb.h" +#include "dcn20/dcn20_mmhubbub.h" + +#include "mmhub/mmhub_2_0_0_offset.h" +#include "mmhub/mmhub_2_0_0_sh_mask.h" + +#include "reg_helper.h" +#include "dce/dce_abm.h" +#include "dce/dce_dmcu.h" +#include "dce/dce_aux.h" +#include "dce/dce_i2c.h" +#include "vm_helper.h" +#include "link_enc_cfg.h" + +#include "amdgpu_socbb.h" + +#include "link.h" +#define DC_LOGGER_INIT(logger) + +#ifndef mmDP0_DP_DPHY_INTERNAL_CTRL + #define mmDP0_DP_DPHY_INTERNAL_CTRL 0x210f + #define mmDP0_DP_DPHY_INTERNAL_CTRL_BASE_IDX 2 + #define mmDP1_DP_DPHY_INTERNAL_CTRL 0x220f + #define mmDP1_DP_DPHY_INTERNAL_CTRL_BASE_IDX 2 + #define mmDP2_DP_DPHY_INTERNAL_CTRL 0x230f + #define mmDP2_DP_DPHY_INTERNAL_CTRL_BASE_IDX 2 + #define mmDP3_DP_DPHY_INTERNAL_CTRL 0x240f + #define mmDP3_DP_DPHY_INTERNAL_CTRL_BASE_IDX 2 + #define mmDP4_DP_DPHY_INTERNAL_CTRL 0x250f + #define mmDP4_DP_DPHY_INTERNAL_CTRL_BASE_IDX 2 + #define mmDP5_DP_DPHY_INTERNAL_CTRL 0x260f + #define mmDP5_DP_DPHY_INTERNAL_CTRL_BASE_IDX 2 + #define mmDP6_DP_DPHY_INTERNAL_CTRL 0x270f + #define mmDP6_DP_DPHY_INTERNAL_CTRL_BASE_IDX 2 +#endif + + +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_PLL5, + DCN20_CLK_SRC_TOTAL +}; + +/* begin ********************* + * macros to expend register list macro defined in HW object header file */ + +/* DCN */ +#define BASE_INNER(seg) DCN_BASE__INST0_SEG ## seg + +#define BASE(seg) BASE_INNER(seg) + +#define SR(reg_name)\ + .reg_name = BASE(mm ## reg_name ## _BASE_IDX) + \ + mm ## reg_name + +#define SRI(reg_name, block, id)\ + .reg_name = BASE(mm ## block ## id ## _ ## reg_name ## _BASE_IDX) + \ + mm ## block ## id ## _ ## reg_name + +#define SRI2_DWB(reg_name, block, id)\ + .reg_name = BASE(mm ## reg_name ## _BASE_IDX) + \ + mm ## reg_name +#define SF_DWB(reg_name, field_name, post_fix)\ + .field_name = reg_name ## __ ## field_name ## post_fix + +#define SF_DWB2(reg_name, block, id, field_name, post_fix) \ + .field_name = reg_name ## __ ## field_name ## post_fix + +#define SRIR(var_name, reg_name, block, id)\ + .var_name = BASE(mm ## block ## id ## _ ## reg_name ## _BASE_IDX) + \ + mm ## block ## id ## _ ## reg_name + +#define SRII(reg_name, block, id)\ + .reg_name[id] = BASE(mm ## block ## id ## _ ## reg_name ## _BASE_IDX) + \ + mm ## block ## id ## _ ## reg_name + +#define DCCG_SRII(reg_name, block, id)\ + .block ## _ ## reg_name[id] = BASE(mm ## block ## id ## _ ## reg_name ## _BASE_IDX) + \ + mm ## block ## id ## _ ## reg_name + +#define VUPDATE_SRII(reg_name, block, id)\ + .reg_name[id] = BASE(mm ## reg_name ## _ ## block ## id ## _BASE_IDX) + \ + mm ## reg_name ## _ ## block ## id + +/* NBIO */ +#define NBIO_BASE_INNER(seg) \ + NBIO_BASE__INST0_SEG ## seg + +#define NBIO_BASE(seg) \ + NBIO_BASE_INNER(seg) + +#define NBIO_SR(reg_name)\ + .reg_name = NBIO_BASE(mm ## reg_name ## _BASE_IDX) + \ + mm ## reg_name + +/* MMHUB */ +#define MMHUB_BASE_INNER(seg) \ + MMHUB_BASE__INST0_SEG ## seg + +#define MMHUB_BASE(seg) \ + MMHUB_BASE_INNER(seg) + +#define MMHUB_SR(reg_name)\ + .reg_name = MMHUB_BASE(mmMM ## reg_name ## _BASE_IDX) + \ + mmMM ## reg_name + +static const struct bios_registers bios_regs = { + NBIO_SR(BIOS_SCRATCH_3), + NBIO_SR(BIOS_SCRATCH_6) +}; + +#define clk_src_regs(index, pllid)\ +[index] = {\ + CS_COMMON_REG_LIST_DCN2_0(index, pllid),\ +} + +static const struct dce110_clk_src_regs clk_src_regs[] = { + clk_src_regs(0, A), + clk_src_regs(1, B), + clk_src_regs(2, C), + clk_src_regs(3, D), + clk_src_regs(4, E), + clk_src_regs(5, F) +}; + +static const struct dce110_clk_src_shift cs_shift = { + CS_COMMON_MASK_SH_LIST_DCN2_0(__SHIFT) +}; + +static const struct dce110_clk_src_mask cs_mask = { + CS_COMMON_MASK_SH_LIST_DCN2_0(_MASK) +}; + +static const struct dce_dmcu_registers dmcu_regs = { + DMCU_DCN10_REG_LIST() +}; + +static const struct dce_dmcu_shift dmcu_shift = { + DMCU_MASK_SH_LIST_DCN10(__SHIFT) +}; + +static const struct dce_dmcu_mask dmcu_mask = { + DMCU_MASK_SH_LIST_DCN10(_MASK) +}; + +static const struct dce_abm_registers abm_regs = { + ABM_DCN20_REG_LIST() +}; + +static const struct dce_abm_shift abm_shift = { + ABM_MASK_SH_LIST_DCN20(__SHIFT) +}; + +static const struct dce_abm_mask abm_mask = { + ABM_MASK_SH_LIST_DCN20(_MASK) +}; + +#define audio_regs(id)\ +[id] = {\ + AUD_COMMON_REG_LIST(id)\ +} + +static const struct dce_audio_registers audio_regs[] = { + audio_regs(0), + audio_regs(1), + audio_regs(2), + audio_regs(3), + audio_regs(4), + audio_regs(5), + audio_regs(6), +}; + +#define DCE120_AUD_COMMON_MASK_SH_LIST(mask_sh)\ + SF(AZF0ENDPOINT0_AZALIA_F0_CODEC_ENDPOINT_INDEX, AZALIA_ENDPOINT_REG_INDEX, mask_sh),\ + SF(AZF0ENDPOINT0_AZALIA_F0_CODEC_ENDPOINT_DATA, AZALIA_ENDPOINT_REG_DATA, mask_sh),\ + AUD_COMMON_MASK_SH_LIST_BASE(mask_sh) + +static const struct dce_audio_shift audio_shift = { + DCE120_AUD_COMMON_MASK_SH_LIST(__SHIFT) +}; + +static const struct dce_audio_mask audio_mask = { + DCE120_AUD_COMMON_MASK_SH_LIST(_MASK) +}; + +#define stream_enc_regs(id)\ +[id] = {\ + SE_DCN2_REG_LIST(id)\ +} + +static const struct dcn10_stream_enc_registers stream_enc_regs[] = { + stream_enc_regs(0), + stream_enc_regs(1), + stream_enc_regs(2), + stream_enc_regs(3), + stream_enc_regs(4), + stream_enc_regs(5), +}; + +static const struct dcn10_stream_encoder_shift se_shift = { + SE_COMMON_MASK_SH_LIST_DCN20(__SHIFT) +}; + +static const struct dcn10_stream_encoder_mask se_mask = { + SE_COMMON_MASK_SH_LIST_DCN20(_MASK) +}; + + +#define aux_regs(id)\ +[id] = {\ + DCN2_AUX_REG_LIST(id)\ +} + +static const struct dcn10_link_enc_aux_registers link_enc_aux_regs[] = { + aux_regs(0), + aux_regs(1), + aux_regs(2), + aux_regs(3), + aux_regs(4), + aux_regs(5) +}; + +#define hpd_regs(id)\ +[id] = {\ + HPD_REG_LIST(id)\ +} + +static const struct dcn10_link_enc_hpd_registers link_enc_hpd_regs[] = { + hpd_regs(0), + hpd_regs(1), + hpd_regs(2), + hpd_regs(3), + hpd_regs(4), + hpd_regs(5) +}; + +#define link_regs(id, phyid)\ +[id] = {\ + LE_DCN10_REG_LIST(id), \ + UNIPHY_DCN2_REG_LIST(phyid), \ + DPCS_DCN2_REG_LIST(id), \ + SRI(DP_DPHY_INTERNAL_CTRL, DP, id) \ +} + +static const struct dcn10_link_enc_registers link_enc_regs[] = { + link_regs(0, A), + link_regs(1, B), + link_regs(2, C), + link_regs(3, D), + link_regs(4, E), + link_regs(5, F) +}; + +static const struct dcn10_link_enc_shift le_shift = { + LINK_ENCODER_MASK_SH_LIST_DCN20(__SHIFT),\ + DPCS_DCN2_MASK_SH_LIST(__SHIFT) +}; + +static const struct dcn10_link_enc_mask le_mask = { + LINK_ENCODER_MASK_SH_LIST_DCN20(_MASK),\ + DPCS_DCN2_MASK_SH_LIST(_MASK) +}; + +static const struct dce_panel_cntl_registers panel_cntl_regs[] = { + { DCN_PANEL_CNTL_REG_LIST() } +}; + +static const struct dce_panel_cntl_shift panel_cntl_shift = { + DCE_PANEL_CNTL_MASK_SH_LIST(__SHIFT) +}; + +static const struct dce_panel_cntl_mask panel_cntl_mask = { + DCE_PANEL_CNTL_MASK_SH_LIST(_MASK) +}; + +#define ipp_regs(id)\ +[id] = {\ + IPP_REG_LIST_DCN20(id),\ +} + +static const struct dcn10_ipp_registers ipp_regs[] = { + ipp_regs(0), + ipp_regs(1), + ipp_regs(2), + ipp_regs(3), + ipp_regs(4), + ipp_regs(5), +}; + +static const struct dcn10_ipp_shift ipp_shift = { + IPP_MASK_SH_LIST_DCN20(__SHIFT) +}; + +static const struct dcn10_ipp_mask ipp_mask = { + IPP_MASK_SH_LIST_DCN20(_MASK), +}; + +#define opp_regs(id)\ +[id] = {\ + OPP_REG_LIST_DCN20(id),\ +} + +static const struct dcn20_opp_registers opp_regs[] = { + opp_regs(0), + opp_regs(1), + opp_regs(2), + opp_regs(3), + opp_regs(4), + opp_regs(5), +}; + +static const struct dcn20_opp_shift opp_shift = { + OPP_MASK_SH_LIST_DCN20(__SHIFT) +}; + +static const struct dcn20_opp_mask opp_mask = { + OPP_MASK_SH_LIST_DCN20(_MASK) +}; + +#define aux_engine_regs(id)\ +[id] = {\ + AUX_COMMON_REG_LIST0(id), \ + .AUXN_IMPCAL = 0, \ + .AUXP_IMPCAL = 0, \ + .AUX_RESET_MASK = DP_AUX0_AUX_CONTROL__AUX_RESET_MASK, \ +} + +static const struct dce110_aux_registers aux_engine_regs[] = { + aux_engine_regs(0), + aux_engine_regs(1), + aux_engine_regs(2), + aux_engine_regs(3), + aux_engine_regs(4), + aux_engine_regs(5) +}; + +#define tf_regs(id)\ +[id] = {\ + TF_REG_LIST_DCN20(id),\ + TF_REG_LIST_DCN20_COMMON_APPEND(id),\ +} + +static const struct dcn2_dpp_registers tf_regs[] = { + tf_regs(0), + tf_regs(1), + tf_regs(2), + tf_regs(3), + tf_regs(4), + tf_regs(5), +}; + +static const struct dcn2_dpp_shift tf_shift = { + TF_REG_LIST_SH_MASK_DCN20(__SHIFT), + TF_DEBUG_REG_LIST_SH_DCN20 +}; + +static const struct dcn2_dpp_mask tf_mask = { + TF_REG_LIST_SH_MASK_DCN20(_MASK), + TF_DEBUG_REG_LIST_MASK_DCN20 +}; + +#define dwbc_regs_dcn2(id)\ +[id] = {\ + DWBC_COMMON_REG_LIST_DCN2_0(id),\ + } + +static const struct dcn20_dwbc_registers dwbc20_regs[] = { + dwbc_regs_dcn2(0), +}; + +static const struct dcn20_dwbc_shift dwbc20_shift = { + DWBC_COMMON_MASK_SH_LIST_DCN2_0(__SHIFT) +}; + +static const struct dcn20_dwbc_mask dwbc20_mask = { + DWBC_COMMON_MASK_SH_LIST_DCN2_0(_MASK) +}; + +#define mcif_wb_regs_dcn2(id)\ +[id] = {\ + MCIF_WB_COMMON_REG_LIST_DCN2_0(id),\ + } + +static const struct dcn20_mmhubbub_registers mcif_wb20_regs[] = { + mcif_wb_regs_dcn2(0), +}; + +static const struct dcn20_mmhubbub_shift mcif_wb20_shift = { + MCIF_WB_COMMON_MASK_SH_LIST_DCN2_0(__SHIFT) +}; + +static const struct dcn20_mmhubbub_mask mcif_wb20_mask = { + MCIF_WB_COMMON_MASK_SH_LIST_DCN2_0(_MASK) +}; + +static const struct dcn20_mpc_registers mpc_regs = { + MPC_REG_LIST_DCN2_0(0), + MPC_REG_LIST_DCN2_0(1), + MPC_REG_LIST_DCN2_0(2), + MPC_REG_LIST_DCN2_0(3), + MPC_REG_LIST_DCN2_0(4), + MPC_REG_LIST_DCN2_0(5), + MPC_OUT_MUX_REG_LIST_DCN2_0(0), + MPC_OUT_MUX_REG_LIST_DCN2_0(1), + MPC_OUT_MUX_REG_LIST_DCN2_0(2), + MPC_OUT_MUX_REG_LIST_DCN2_0(3), + MPC_OUT_MUX_REG_LIST_DCN2_0(4), + MPC_OUT_MUX_REG_LIST_DCN2_0(5), + MPC_DBG_REG_LIST_DCN2_0() +}; + +static const struct dcn20_mpc_shift mpc_shift = { + MPC_COMMON_MASK_SH_LIST_DCN2_0(__SHIFT), + MPC_DEBUG_REG_LIST_SH_DCN20 +}; + +static const struct dcn20_mpc_mask mpc_mask = { + MPC_COMMON_MASK_SH_LIST_DCN2_0(_MASK), + MPC_DEBUG_REG_LIST_MASK_DCN20 +}; + +#define tg_regs(id)\ +[id] = {TG_COMMON_REG_LIST_DCN2_0(id)} + + +static const struct dcn_optc_registers tg_regs[] = { + tg_regs(0), + tg_regs(1), + tg_regs(2), + tg_regs(3), + tg_regs(4), + tg_regs(5) +}; + +static const struct dcn_optc_shift tg_shift = { + TG_COMMON_MASK_SH_LIST_DCN2_0(__SHIFT) +}; + +static const struct dcn_optc_mask tg_mask = { + TG_COMMON_MASK_SH_LIST_DCN2_0(_MASK) +}; + +#define hubp_regs(id)\ +[id] = {\ + HUBP_REG_LIST_DCN20(id)\ +} + +static const struct dcn_hubp2_registers hubp_regs[] = { + hubp_regs(0), + hubp_regs(1), + hubp_regs(2), + hubp_regs(3), + hubp_regs(4), + hubp_regs(5) +}; + +static const struct dcn_hubp2_shift hubp_shift = { + HUBP_MASK_SH_LIST_DCN20(__SHIFT) +}; + +static const struct dcn_hubp2_mask hubp_mask = { + HUBP_MASK_SH_LIST_DCN20(_MASK) +}; + +static const struct dcn_hubbub_registers hubbub_reg = { + HUBBUB_REG_LIST_DCN20(0) +}; + +static const struct dcn_hubbub_shift hubbub_shift = { + HUBBUB_MASK_SH_LIST_DCN20(__SHIFT) +}; + +static const struct dcn_hubbub_mask hubbub_mask = { + HUBBUB_MASK_SH_LIST_DCN20(_MASK) +}; + +#define vmid_regs(id)\ +[id] = {\ + DCN20_VMID_REG_LIST(id)\ +} + +static const struct dcn_vmid_registers vmid_regs[] = { + vmid_regs(0), + vmid_regs(1), + vmid_regs(2), + vmid_regs(3), + vmid_regs(4), + vmid_regs(5), + vmid_regs(6), + vmid_regs(7), + vmid_regs(8), + vmid_regs(9), + vmid_regs(10), + vmid_regs(11), + vmid_regs(12), + vmid_regs(13), + vmid_regs(14), + vmid_regs(15) +}; + +static const struct dcn20_vmid_shift vmid_shifts = { + DCN20_VMID_MASK_SH_LIST(__SHIFT) +}; + +static const struct dcn20_vmid_mask vmid_masks = { + DCN20_VMID_MASK_SH_LIST(_MASK) +}; + +static const struct dce110_aux_registers_shift aux_shift = { + DCN_AUX_MASK_SH_LIST(__SHIFT) +}; + +static const struct dce110_aux_registers_mask aux_mask = { + DCN_AUX_MASK_SH_LIST(_MASK) +}; + +static int map_transmitter_id_to_phy_instance( + enum transmitter transmitter) +{ + switch (transmitter) { + case TRANSMITTER_UNIPHY_A: + return 0; + break; + case TRANSMITTER_UNIPHY_B: + return 1; + break; + case TRANSMITTER_UNIPHY_C: + return 2; + break; + case TRANSMITTER_UNIPHY_D: + return 3; + break; + case TRANSMITTER_UNIPHY_E: + return 4; + break; + case TRANSMITTER_UNIPHY_F: + return 5; + break; + default: + ASSERT(0); + return 0; + } +} + +#define dsc_regsDCN20(id)\ +[id] = {\ + DSC_REG_LIST_DCN20(id)\ +} + +static const struct dcn20_dsc_registers dsc_regs[] = { + dsc_regsDCN20(0), + dsc_regsDCN20(1), + dsc_regsDCN20(2), + dsc_regsDCN20(3), + dsc_regsDCN20(4), + dsc_regsDCN20(5) +}; + +static const struct dcn20_dsc_shift dsc_shift = { + DSC_REG_LIST_SH_MASK_DCN20(__SHIFT) +}; + +static const struct dcn20_dsc_mask dsc_mask = { + DSC_REG_LIST_SH_MASK_DCN20(_MASK) +}; + +static const struct dccg_registers dccg_regs = { + DCCG_REG_LIST_DCN2() +}; + +static const struct dccg_shift dccg_shift = { + DCCG_MASK_SH_LIST_DCN2(__SHIFT) +}; + +static const struct dccg_mask dccg_mask = { + DCCG_MASK_SH_LIST_DCN2(_MASK) +}; + +static const struct resource_caps res_cap_nv10 = { + .num_timing_generator = 6, + .num_opp = 6, + .num_video_plane = 6, + .num_audio = 7, + .num_stream_encoder = 6, + .num_pll = 6, + .num_dwb = 1, + .num_ddc = 6, + .num_vmid = 16, + .num_dsc = 6, +}; + +static const struct dc_plane_cap plane_cap = { + .type = DC_PLANE_TYPE_DCN_UNIVERSAL, + .per_pixel_alpha = true, + + .pixel_format_support = { + .argb8888 = true, + .nv12 = true, + .fp16 = true, + .p010 = true + }, + + .max_upscale_factor = { + .argb8888 = 16000, + .nv12 = 16000, + .fp16 = 1 + }, + + .max_downscale_factor = { + .argb8888 = 250, + .nv12 = 250, + .fp16 = 1 + }, + 16, + 16 +}; +static const struct resource_caps res_cap_nv14 = { + .num_timing_generator = 5, + .num_opp = 5, + .num_video_plane = 5, + .num_audio = 6, + .num_stream_encoder = 5, + .num_pll = 5, + .num_dwb = 1, + .num_ddc = 5, + .num_vmid = 16, + .num_dsc = 5, +}; + +static const struct dc_debug_options debug_defaults_drv = { + .disable_dmcu = false, + .force_abm_enable = false, + .timing_trace = false, + .clock_trace = true, + .disable_pplib_clock_request = true, + .pipe_split_policy = MPC_SPLIT_AVOID_MULT_DISP, + .force_single_disp_pipe_split = false, + .disable_dcc = DCC_ENABLE, + .vsr_support = true, + .performance_trace = false, + .max_downscale_src_width = 5120,/*upto 5K*/ + .disable_pplib_wm_range = false, + .scl_reset_length10 = true, + .sanity_checks = false, + .underflow_assert_delay_us = 0xFFFFFFFF, + .enable_legacy_fast_update = true, + .using_dml2 = false, +}; + +void dcn20_dpp_destroy(struct dpp **dpp) +{ + kfree(TO_DCN20_DPP(*dpp)); + *dpp = NULL; +} + +struct dpp *dcn20_dpp_create( + struct dc_context *ctx, + uint32_t inst) +{ + struct dcn20_dpp *dpp = + kzalloc(sizeof(struct dcn20_dpp), GFP_ATOMIC); + + if (!dpp) + return NULL; + + if (dpp2_construct(dpp, ctx, inst, + &tf_regs[inst], &tf_shift, &tf_mask)) + return &dpp->base; + + BREAK_TO_DEBUGGER(); + kfree(dpp); + return NULL; +} + +struct input_pixel_processor *dcn20_ipp_create( + struct dc_context *ctx, uint32_t inst) +{ + struct dcn10_ipp *ipp = + kzalloc(sizeof(struct dcn10_ipp), GFP_ATOMIC); + + if (!ipp) { + BREAK_TO_DEBUGGER(); + return NULL; + } + + dcn20_ipp_construct(ipp, ctx, inst, + &ipp_regs[inst], &ipp_shift, &ipp_mask); + return &ipp->base; +} + + +struct output_pixel_processor *dcn20_opp_create( + struct dc_context *ctx, uint32_t inst) +{ + struct dcn20_opp *opp = + kzalloc(sizeof(struct dcn20_opp), GFP_ATOMIC); + + if (!opp) { + BREAK_TO_DEBUGGER(); + return NULL; + } + + dcn20_opp_construct(opp, ctx, inst, + &opp_regs[inst], &opp_shift, &opp_mask); + return &opp->base; +} + +struct dce_aux *dcn20_aux_engine_create( + struct dc_context *ctx, + uint32_t inst) +{ + struct aux_engine_dce110 *aux_engine = + kzalloc(sizeof(struct aux_engine_dce110), GFP_ATOMIC); + + if (!aux_engine) + return NULL; + + dce110_aux_engine_construct(aux_engine, ctx, inst, + SW_AUX_TIMEOUT_PERIOD_MULTIPLIER * AUX_TIMEOUT_PERIOD, + &aux_engine_regs[inst], + &aux_mask, + &aux_shift, + ctx->dc->caps.extended_aux_timeout_support); + + return &aux_engine->base; +} +#define i2c_inst_regs(id) { I2C_HW_ENGINE_COMMON_REG_LIST(id) } + +static const struct dce_i2c_registers i2c_hw_regs[] = { + i2c_inst_regs(1), + i2c_inst_regs(2), + i2c_inst_regs(3), + i2c_inst_regs(4), + i2c_inst_regs(5), + i2c_inst_regs(6), +}; + +static const struct dce_i2c_shift i2c_shifts = { + I2C_COMMON_MASK_SH_LIST_DCN2(__SHIFT) +}; + +static const struct dce_i2c_mask i2c_masks = { + I2C_COMMON_MASK_SH_LIST_DCN2(_MASK) +}; + +struct dce_i2c_hw *dcn20_i2c_hw_create( + struct dc_context *ctx, + uint32_t inst) +{ + struct dce_i2c_hw *dce_i2c_hw = + kzalloc(sizeof(struct dce_i2c_hw), GFP_ATOMIC); + + if (!dce_i2c_hw) + return NULL; + + dcn2_i2c_hw_construct(dce_i2c_hw, ctx, inst, + &i2c_hw_regs[inst], &i2c_shifts, &i2c_masks); + + return dce_i2c_hw; +} +struct mpc *dcn20_mpc_create(struct dc_context *ctx) +{ + struct dcn20_mpc *mpc20 = kzalloc(sizeof(struct dcn20_mpc), + GFP_ATOMIC); + + if (!mpc20) + return NULL; + + dcn20_mpc_construct(mpc20, ctx, + &mpc_regs, + &mpc_shift, + &mpc_mask, + 6); + + return &mpc20->base; +} + +struct hubbub *dcn20_hubbub_create(struct dc_context *ctx) +{ + int i; + struct dcn20_hubbub *hubbub = kzalloc(sizeof(struct dcn20_hubbub), + GFP_ATOMIC); + + if (!hubbub) + return NULL; + + hubbub2_construct(hubbub, ctx, + &hubbub_reg, + &hubbub_shift, + &hubbub_mask); + + for (i = 0; i < res_cap_nv10.num_vmid; i++) { + struct dcn20_vmid *vmid = &hubbub->vmid[i]; + + vmid->ctx = ctx; + + vmid->regs = &vmid_regs[i]; + vmid->shifts = &vmid_shifts; + vmid->masks = &vmid_masks; + } + + return &hubbub->base; +} + +struct timing_generator *dcn20_timing_generator_create( + struct dc_context *ctx, + uint32_t instance) +{ + struct optc *tgn10 = + kzalloc(sizeof(struct optc), GFP_ATOMIC); + + if (!tgn10) + return NULL; + + tgn10->base.inst = instance; + tgn10->base.ctx = ctx; + + tgn10->tg_regs = &tg_regs[instance]; + tgn10->tg_shift = &tg_shift; + tgn10->tg_mask = &tg_mask; + + dcn20_timing_generator_init(tgn10); + + return &tgn10->base; +} + +static const struct encoder_feature_support link_enc_feature = { + .max_hdmi_deep_color = COLOR_DEPTH_121212, + .max_hdmi_pixel_clock = 600000, + .hdmi_ycbcr420_supported = true, + .dp_ycbcr420_supported = true, + .fec_supported = true, + .flags.bits.IS_HBR2_CAPABLE = true, + .flags.bits.IS_HBR3_CAPABLE = true, + .flags.bits.IS_TPS3_CAPABLE = true, + .flags.bits.IS_TPS4_CAPABLE = true +}; + +struct link_encoder *dcn20_link_encoder_create( + struct dc_context *ctx, + const struct encoder_init_data *enc_init_data) +{ + struct dcn20_link_encoder *enc20 = + kzalloc(sizeof(struct dcn20_link_encoder), GFP_KERNEL); + int link_regs_id; + + if (!enc20) + return NULL; + + link_regs_id = + map_transmitter_id_to_phy_instance(enc_init_data->transmitter); + + dcn20_link_encoder_construct(enc20, + enc_init_data, + &link_enc_feature, + &link_enc_regs[link_regs_id], + &link_enc_aux_regs[enc_init_data->channel - 1], + &link_enc_hpd_regs[enc_init_data->hpd_source], + &le_shift, + &le_mask); + + return &enc20->enc10.base; +} + +static struct panel_cntl *dcn20_panel_cntl_create(const struct panel_cntl_init_data *init_data) +{ + struct dce_panel_cntl *panel_cntl = + kzalloc(sizeof(struct dce_panel_cntl), GFP_KERNEL); + + if (!panel_cntl) + return NULL; + + dce_panel_cntl_construct(panel_cntl, + init_data, + &panel_cntl_regs[init_data->inst], + &panel_cntl_shift, + &panel_cntl_mask); + + return &panel_cntl->base; +} + +static struct clock_source *dcn20_clock_source_create( + struct dc_context *ctx, + struct dc_bios *bios, + enum clock_source_id id, + const struct dce110_clk_src_regs *regs, + bool dp_clk_src) +{ + struct dce110_clk_src *clk_src = + kzalloc(sizeof(struct dce110_clk_src), GFP_ATOMIC); + + if (!clk_src) + return NULL; + + if (dcn20_clk_src_construct(clk_src, ctx, bios, id, + regs, &cs_shift, &cs_mask)) { + clk_src->base.dp_clk_src = dp_clk_src; + return &clk_src->base; + } + + kfree(clk_src); + BREAK_TO_DEBUGGER(); + return NULL; +} + +static void read_dce_straps( + struct dc_context *ctx, + struct resource_straps *straps) +{ + generic_reg_get(ctx, mmDC_PINSTRAPS + BASE(mmDC_PINSTRAPS_BASE_IDX), + FN(DC_PINSTRAPS, DC_PINSTRAPS_AUDIO), &straps->dc_pinstraps_audio); +} + +static struct audio *dcn20_create_audio( + struct dc_context *ctx, unsigned int inst) +{ + return dce_audio_create(ctx, inst, + &audio_regs[inst], &audio_shift, &audio_mask); +} + +struct stream_encoder *dcn20_stream_encoder_create( + enum engine_id eng_id, + struct dc_context *ctx) +{ + struct dcn10_stream_encoder *enc1 = + kzalloc(sizeof(struct dcn10_stream_encoder), GFP_KERNEL); + + if (!enc1) + return NULL; + + if (ASICREV_IS_NAVI14_M(ctx->asic_id.hw_internal_rev)) { + if (eng_id >= ENGINE_ID_DIGD) + eng_id++; + } + + dcn20_stream_encoder_construct(enc1, ctx, ctx->dc_bios, eng_id, + &stream_enc_regs[eng_id], + &se_shift, &se_mask); + + return &enc1->base; +} + +static const struct dce_hwseq_registers hwseq_reg = { + HWSEQ_DCN2_REG_LIST() +}; + +static const struct dce_hwseq_shift hwseq_shift = { + HWSEQ_DCN2_MASK_SH_LIST(__SHIFT) +}; + +static const struct dce_hwseq_mask hwseq_mask = { + HWSEQ_DCN2_MASK_SH_LIST(_MASK) +}; + +struct dce_hwseq *dcn20_hwseq_create( + struct dc_context *ctx) +{ + struct dce_hwseq *hws = kzalloc(sizeof(struct dce_hwseq), GFP_KERNEL); + + if (hws) { + hws->ctx = ctx; + hws->regs = &hwseq_reg; + hws->shifts = &hwseq_shift; + hws->masks = &hwseq_mask; + } + return hws; +} + +static const struct resource_create_funcs res_create_funcs = { + .read_dce_straps = read_dce_straps, + .create_audio = dcn20_create_audio, + .create_stream_encoder = dcn20_stream_encoder_create, + .create_hwseq = dcn20_hwseq_create, +}; + +static void dcn20_pp_smu_destroy(struct pp_smu_funcs **pp_smu); + +void dcn20_clock_source_destroy(struct clock_source **clk_src) +{ + kfree(TO_DCE110_CLK_SRC(*clk_src)); + *clk_src = NULL; +} + + +struct display_stream_compressor *dcn20_dsc_create( + struct dc_context *ctx, uint32_t inst) +{ + struct dcn20_dsc *dsc = + kzalloc(sizeof(struct dcn20_dsc), GFP_ATOMIC); + + if (!dsc) { + BREAK_TO_DEBUGGER(); + return NULL; + } + + dsc2_construct(dsc, ctx, inst, &dsc_regs[inst], &dsc_shift, &dsc_mask); + return &dsc->base; +} + +void dcn20_dsc_destroy(struct display_stream_compressor **dsc) +{ + kfree(container_of(*dsc, struct dcn20_dsc, base)); + *dsc = NULL; +} + + +static void dcn20_resource_destruct(struct dcn20_resource_pool *pool) +{ + unsigned int i; + + for (i = 0; i < pool->base.stream_enc_count; i++) { + if (pool->base.stream_enc[i] != NULL) { + kfree(DCN10STRENC_FROM_STRENC(pool->base.stream_enc[i])); + pool->base.stream_enc[i] = NULL; + } + } + + for (i = 0; i < pool->base.res_cap->num_dsc; i++) { + if (pool->base.dscs[i] != NULL) + dcn20_dsc_destroy(&pool->base.dscs[i]); + } + + if (pool->base.mpc != NULL) { + kfree(TO_DCN20_MPC(pool->base.mpc)); + pool->base.mpc = NULL; + } + if (pool->base.hubbub != NULL) { + kfree(pool->base.hubbub); + pool->base.hubbub = NULL; + } + for (i = 0; i < pool->base.pipe_count; i++) { + if (pool->base.dpps[i] != NULL) + dcn20_dpp_destroy(&pool->base.dpps[i]); + + if (pool->base.ipps[i] != NULL) + pool->base.ipps[i]->funcs->ipp_destroy(&pool->base.ipps[i]); + + if (pool->base.hubps[i] != NULL) { + kfree(TO_DCN20_HUBP(pool->base.hubps[i])); + pool->base.hubps[i] = NULL; + } + + if (pool->base.irqs != NULL) { + dal_irq_service_destroy(&pool->base.irqs); + } + } + + for (i = 0; i < pool->base.res_cap->num_ddc; i++) { + if (pool->base.engines[i] != NULL) + dce110_engine_destroy(&pool->base.engines[i]); + if (pool->base.hw_i2cs[i] != NULL) { + kfree(pool->base.hw_i2cs[i]); + pool->base.hw_i2cs[i] = NULL; + } + if (pool->base.sw_i2cs[i] != NULL) { + kfree(pool->base.sw_i2cs[i]); + pool->base.sw_i2cs[i] = NULL; + } + } + + for (i = 0; i < pool->base.res_cap->num_opp; i++) { + if (pool->base.opps[i] != NULL) + pool->base.opps[i]->funcs->opp_destroy(&pool->base.opps[i]); + } + + for (i = 0; i < pool->base.res_cap->num_timing_generator; i++) { + if (pool->base.timing_generators[i] != NULL) { + kfree(DCN10TG_FROM_TG(pool->base.timing_generators[i])); + pool->base.timing_generators[i] = NULL; + } + } + + for (i = 0; i < pool->base.res_cap->num_dwb; i++) { + if (pool->base.dwbc[i] != NULL) { + kfree(TO_DCN20_DWBC(pool->base.dwbc[i])); + pool->base.dwbc[i] = NULL; + } + if (pool->base.mcif_wb[i] != NULL) { + kfree(TO_DCN20_MMHUBBUB(pool->base.mcif_wb[i])); + pool->base.mcif_wb[i] = NULL; + } + } + + for (i = 0; i < pool->base.audio_count; i++) { + if (pool->base.audios[i]) + dce_aud_destroy(&pool->base.audios[i]); + } + + for (i = 0; i < pool->base.clk_src_count; i++) { + if (pool->base.clock_sources[i] != NULL) { + dcn20_clock_source_destroy(&pool->base.clock_sources[i]); + pool->base.clock_sources[i] = NULL; + } + } + + if (pool->base.dp_clock_source != NULL) { + dcn20_clock_source_destroy(&pool->base.dp_clock_source); + pool->base.dp_clock_source = NULL; + } + + + if (pool->base.abm != NULL) + dce_abm_destroy(&pool->base.abm); + + if (pool->base.dmcu != NULL) + dce_dmcu_destroy(&pool->base.dmcu); + + if (pool->base.dccg != NULL) + dcn_dccg_destroy(&pool->base.dccg); + + if (pool->base.pp_smu != NULL) + dcn20_pp_smu_destroy(&pool->base.pp_smu); + + if (pool->base.oem_device != NULL) { + struct dc *dc = pool->base.oem_device->ctx->dc; + + dc->link_srv->destroy_ddc_service(&pool->base.oem_device); + } +} + +struct hubp *dcn20_hubp_create( + struct dc_context *ctx, + uint32_t inst) +{ + struct dcn20_hubp *hubp2 = + kzalloc(sizeof(struct dcn20_hubp), GFP_ATOMIC); + + if (!hubp2) + return NULL; + + if (hubp2_construct(hubp2, ctx, inst, + &hubp_regs[inst], &hubp_shift, &hubp_mask)) + return &hubp2->base; + + BREAK_TO_DEBUGGER(); + kfree(hubp2); + return NULL; +} + +static void get_pixel_clock_parameters( + struct pipe_ctx *pipe_ctx, + struct pixel_clk_params *pixel_clk_params) +{ + const struct dc_stream_state *stream = pipe_ctx->stream; + struct pipe_ctx *odm_pipe; + int opp_cnt = 1; + struct dc_link *link = stream->link; + struct link_encoder *link_enc = NULL; + struct dc *dc = pipe_ctx->stream->ctx->dc; + struct dce_hwseq *hws = dc->hwseq; + + for (odm_pipe = pipe_ctx->next_odm_pipe; odm_pipe; odm_pipe = odm_pipe->next_odm_pipe) + opp_cnt++; + + pixel_clk_params->requested_pix_clk_100hz = stream->timing.pix_clk_100hz; + + link_enc = link_enc_cfg_get_link_enc(link); + if (link_enc) + pixel_clk_params->encoder_object_id = link_enc->id; + + pixel_clk_params->signal_type = pipe_ctx->stream->signal; + pixel_clk_params->controller_id = pipe_ctx->stream_res.tg->inst + 1; + /* TODO: un-hardcode*/ + /* TODO - DP2.0 HW: calculate requested_sym_clk for UHBR rates */ + pixel_clk_params->requested_sym_clk = LINK_RATE_LOW * + LINK_RATE_REF_FREQ_IN_KHZ; + pixel_clk_params->flags.ENABLE_SS = 0; + pixel_clk_params->color_depth = + stream->timing.display_color_depth; + pixel_clk_params->flags.DISPLAY_BLANKED = 1; + pixel_clk_params->pixel_encoding = stream->timing.pixel_encoding; + + if (stream->timing.pixel_encoding == PIXEL_ENCODING_YCBCR422) + pixel_clk_params->color_depth = COLOR_DEPTH_888; + + if (opp_cnt == 4) + pixel_clk_params->requested_pix_clk_100hz /= 4; + else if (optc2_is_two_pixels_per_containter(&stream->timing) || opp_cnt == 2) + pixel_clk_params->requested_pix_clk_100hz /= 2; + else if (hws->funcs.is_dp_dig_pixel_rate_div_policy) { + if (hws->funcs.is_dp_dig_pixel_rate_div_policy(pipe_ctx)) + pixel_clk_params->requested_pix_clk_100hz /= 2; + } + + if (stream->timing.timing_3d_format == TIMING_3D_FORMAT_HW_FRAME_PACKING) + pixel_clk_params->requested_pix_clk_100hz *= 2; + +} + +static void build_clamping_params(struct dc_stream_state *stream) +{ + stream->clamping.clamping_level = CLAMPING_FULL_RANGE; + stream->clamping.c_depth = stream->timing.display_color_depth; + stream->clamping.pixel_encoding = stream->timing.pixel_encoding; +} + +static enum dc_status build_pipe_hw_param(struct pipe_ctx *pipe_ctx) +{ + + get_pixel_clock_parameters(pipe_ctx, &pipe_ctx->stream_res.pix_clk_params); + + pipe_ctx->clock_source->funcs->get_pix_clk_dividers( + pipe_ctx->clock_source, + &pipe_ctx->stream_res.pix_clk_params, + &pipe_ctx->pll_settings); + + pipe_ctx->stream->clamping.pixel_encoding = pipe_ctx->stream->timing.pixel_encoding; + + resource_build_bit_depth_reduction_params(pipe_ctx->stream, + &pipe_ctx->stream->bit_depth_params); + build_clamping_params(pipe_ctx->stream); + + return DC_OK; +} + +enum dc_status dcn20_build_mapped_resource(const struct dc *dc, struct dc_state *context, struct dc_stream_state *stream) +{ + enum dc_status status = DC_OK; + struct pipe_ctx *pipe_ctx = resource_get_otg_master_for_stream(&context->res_ctx, stream); + + if (!pipe_ctx) + return DC_ERROR_UNEXPECTED; + + + status = build_pipe_hw_param(pipe_ctx); + + return status; +} + + +void dcn20_acquire_dsc(const struct dc *dc, + struct resource_context *res_ctx, + struct display_stream_compressor **dsc, + int pipe_idx) +{ + int i; + const struct resource_pool *pool = dc->res_pool; + struct display_stream_compressor *dsc_old = dc->current_state->res_ctx.pipe_ctx[pipe_idx].stream_res.dsc; + + ASSERT(*dsc == NULL); /* If this ASSERT fails, dsc was not released properly */ + *dsc = NULL; + + /* Always do 1-to-1 mapping when number of DSCs is same as number of pipes */ + if (pool->res_cap->num_dsc == pool->res_cap->num_opp) { + *dsc = pool->dscs[pipe_idx]; + res_ctx->is_dsc_acquired[pipe_idx] = true; + return; + } + + /* Return old DSC to avoid the need for re-programming */ + if (dsc_old && !res_ctx->is_dsc_acquired[dsc_old->inst]) { + *dsc = dsc_old; + res_ctx->is_dsc_acquired[dsc_old->inst] = true; + return ; + } + + /* Find first free DSC */ + for (i = 0; i < pool->res_cap->num_dsc; i++) + if (!res_ctx->is_dsc_acquired[i]) { + *dsc = pool->dscs[i]; + res_ctx->is_dsc_acquired[i] = true; + break; + } +} + +void dcn20_release_dsc(struct resource_context *res_ctx, + const struct resource_pool *pool, + struct display_stream_compressor **dsc) +{ + int i; + + for (i = 0; i < pool->res_cap->num_dsc; i++) + if (pool->dscs[i] == *dsc) { + res_ctx->is_dsc_acquired[i] = false; + *dsc = NULL; + break; + } +} + + + +enum dc_status dcn20_add_dsc_to_stream_resource(struct dc *dc, + struct dc_state *dc_ctx, + struct dc_stream_state *dc_stream) +{ + enum dc_status result = DC_OK; + int i; + + /* Get a DSC if required and available */ + for (i = 0; i < dc->res_pool->pipe_count; i++) { + struct pipe_ctx *pipe_ctx = &dc_ctx->res_ctx.pipe_ctx[i]; + + if (pipe_ctx->top_pipe) + continue; + + if (pipe_ctx->stream != dc_stream) + continue; + + if (pipe_ctx->stream_res.dsc) + continue; + + dcn20_acquire_dsc(dc, &dc_ctx->res_ctx, &pipe_ctx->stream_res.dsc, i); + + /* The number of DSCs can be less than the number of pipes */ + if (!pipe_ctx->stream_res.dsc) { + result = DC_NO_DSC_RESOURCE; + } + + break; + } + + return result; +} + + +static enum dc_status remove_dsc_from_stream_resource(struct dc *dc, + struct dc_state *new_ctx, + struct dc_stream_state *dc_stream) +{ + struct pipe_ctx *pipe_ctx = NULL; + int i; + + for (i = 0; i < MAX_PIPES; i++) { + if (new_ctx->res_ctx.pipe_ctx[i].stream == dc_stream && !new_ctx->res_ctx.pipe_ctx[i].top_pipe) { + pipe_ctx = &new_ctx->res_ctx.pipe_ctx[i]; + + if (pipe_ctx->stream_res.dsc) + dcn20_release_dsc(&new_ctx->res_ctx, dc->res_pool, &pipe_ctx->stream_res.dsc); + } + } + + if (!pipe_ctx) + return DC_ERROR_UNEXPECTED; + else + return DC_OK; +} + + +enum dc_status dcn20_add_stream_to_ctx(struct dc *dc, struct dc_state *new_ctx, struct dc_stream_state *dc_stream) +{ + enum dc_status result = DC_ERROR_UNEXPECTED; + + result = resource_map_pool_resources(dc, new_ctx, dc_stream); + + if (result == DC_OK) + result = resource_map_phy_clock_resources(dc, new_ctx, dc_stream); + + /* Get a DSC if required and available */ + if (result == DC_OK && dc_stream->timing.flags.DSC) + result = dcn20_add_dsc_to_stream_resource(dc, new_ctx, dc_stream); + + if (result == DC_OK) + result = dcn20_build_mapped_resource(dc, new_ctx, dc_stream); + + return result; +} + + +enum dc_status dcn20_remove_stream_from_ctx(struct dc *dc, struct dc_state *new_ctx, struct dc_stream_state *dc_stream) +{ + enum dc_status result = DC_OK; + + result = remove_dsc_from_stream_resource(dc, new_ctx, dc_stream); + + return result; +} + +/** + * dcn20_split_stream_for_odm - Check if stream can be splited for ODM + * + * @dc: DC object with resource pool info required for pipe split + * @res_ctx: Persistent state of resources + * @prev_odm_pipe: Reference to the previous ODM pipe + * @next_odm_pipe: Reference to the next ODM pipe + * + * This function takes a logically active pipe and a logically free pipe and + * halves all the scaling parameters that need to be halved while populating + * the free pipe with the required resources and configuring the next/previous + * ODM pipe pointers. + * + * Return: + * Return true if split stream for ODM is possible, otherwise, return false. + */ +bool dcn20_split_stream_for_odm( + const struct dc *dc, + struct resource_context *res_ctx, + struct pipe_ctx *prev_odm_pipe, + struct pipe_ctx *next_odm_pipe) +{ + int pipe_idx = next_odm_pipe->pipe_idx; + const struct resource_pool *pool = dc->res_pool; + + *next_odm_pipe = *prev_odm_pipe; + + next_odm_pipe->pipe_idx = pipe_idx; + next_odm_pipe->plane_res.mi = pool->mis[next_odm_pipe->pipe_idx]; + next_odm_pipe->plane_res.hubp = pool->hubps[next_odm_pipe->pipe_idx]; + next_odm_pipe->plane_res.ipp = pool->ipps[next_odm_pipe->pipe_idx]; + next_odm_pipe->plane_res.xfm = pool->transforms[next_odm_pipe->pipe_idx]; + next_odm_pipe->plane_res.dpp = pool->dpps[next_odm_pipe->pipe_idx]; + next_odm_pipe->plane_res.mpcc_inst = pool->dpps[next_odm_pipe->pipe_idx]->inst; + next_odm_pipe->stream_res.dsc = NULL; + if (prev_odm_pipe->next_odm_pipe && prev_odm_pipe->next_odm_pipe != next_odm_pipe) { + next_odm_pipe->next_odm_pipe = prev_odm_pipe->next_odm_pipe; + next_odm_pipe->next_odm_pipe->prev_odm_pipe = next_odm_pipe; + } + if (prev_odm_pipe->top_pipe && prev_odm_pipe->top_pipe->next_odm_pipe) { + prev_odm_pipe->top_pipe->next_odm_pipe->bottom_pipe = next_odm_pipe; + next_odm_pipe->top_pipe = prev_odm_pipe->top_pipe->next_odm_pipe; + } + if (prev_odm_pipe->bottom_pipe && prev_odm_pipe->bottom_pipe->next_odm_pipe) { + prev_odm_pipe->bottom_pipe->next_odm_pipe->top_pipe = next_odm_pipe; + next_odm_pipe->bottom_pipe = prev_odm_pipe->bottom_pipe->next_odm_pipe; + } + prev_odm_pipe->next_odm_pipe = next_odm_pipe; + next_odm_pipe->prev_odm_pipe = prev_odm_pipe; + + if (prev_odm_pipe->plane_state) { + struct scaler_data *sd = &prev_odm_pipe->plane_res.scl_data; + int new_width; + + /* HACTIVE halved for odm combine */ + sd->h_active /= 2; + /* Calculate new vp and recout for left pipe */ + /* Need at least 16 pixels width per side */ + if (sd->recout.x + 16 >= sd->h_active) + return false; + new_width = sd->h_active - sd->recout.x; + sd->viewport.width -= dc_fixpt_floor(dc_fixpt_mul_int( + sd->ratios.horz, sd->recout.width - new_width)); + sd->viewport_c.width -= dc_fixpt_floor(dc_fixpt_mul_int( + sd->ratios.horz_c, sd->recout.width - new_width)); + sd->recout.width = new_width; + + /* Calculate new vp and recout for right pipe */ + sd = &next_odm_pipe->plane_res.scl_data; + /* HACTIVE halved for odm combine */ + sd->h_active /= 2; + /* Need at least 16 pixels width per side */ + if (new_width <= 16) + return false; + new_width = sd->recout.width + sd->recout.x - sd->h_active; + sd->viewport.width -= dc_fixpt_floor(dc_fixpt_mul_int( + sd->ratios.horz, sd->recout.width - new_width)); + sd->viewport_c.width -= dc_fixpt_floor(dc_fixpt_mul_int( + sd->ratios.horz_c, sd->recout.width - new_width)); + sd->recout.width = new_width; + sd->viewport.x += dc_fixpt_floor(dc_fixpt_mul_int( + sd->ratios.horz, sd->h_active - sd->recout.x)); + sd->viewport_c.x += dc_fixpt_floor(dc_fixpt_mul_int( + sd->ratios.horz_c, sd->h_active - sd->recout.x)); + sd->recout.x = 0; + } + if (!next_odm_pipe->top_pipe) + next_odm_pipe->stream_res.opp = pool->opps[next_odm_pipe->pipe_idx]; + else + next_odm_pipe->stream_res.opp = next_odm_pipe->top_pipe->stream_res.opp; + if (next_odm_pipe->stream->timing.flags.DSC == 1 && !next_odm_pipe->top_pipe) { + dcn20_acquire_dsc(dc, res_ctx, &next_odm_pipe->stream_res.dsc, next_odm_pipe->pipe_idx); + ASSERT(next_odm_pipe->stream_res.dsc); + if (next_odm_pipe->stream_res.dsc == NULL) + return false; + } + + return true; +} + +void dcn20_split_stream_for_mpc( + struct resource_context *res_ctx, + const struct resource_pool *pool, + struct pipe_ctx *primary_pipe, + struct pipe_ctx *secondary_pipe) +{ + int pipe_idx = secondary_pipe->pipe_idx; + struct pipe_ctx *sec_bot_pipe = secondary_pipe->bottom_pipe; + + *secondary_pipe = *primary_pipe; + secondary_pipe->bottom_pipe = sec_bot_pipe; + + secondary_pipe->pipe_idx = pipe_idx; + secondary_pipe->plane_res.mi = pool->mis[secondary_pipe->pipe_idx]; + secondary_pipe->plane_res.hubp = pool->hubps[secondary_pipe->pipe_idx]; + secondary_pipe->plane_res.ipp = pool->ipps[secondary_pipe->pipe_idx]; + secondary_pipe->plane_res.xfm = pool->transforms[secondary_pipe->pipe_idx]; + secondary_pipe->plane_res.dpp = pool->dpps[secondary_pipe->pipe_idx]; + secondary_pipe->plane_res.mpcc_inst = pool->dpps[secondary_pipe->pipe_idx]->inst; + secondary_pipe->stream_res.dsc = NULL; + if (primary_pipe->bottom_pipe && primary_pipe->bottom_pipe != secondary_pipe) { + ASSERT(!secondary_pipe->bottom_pipe); + secondary_pipe->bottom_pipe = primary_pipe->bottom_pipe; + secondary_pipe->bottom_pipe->top_pipe = secondary_pipe; + } + primary_pipe->bottom_pipe = secondary_pipe; + secondary_pipe->top_pipe = primary_pipe; + + ASSERT(primary_pipe->plane_state); +} + +unsigned int dcn20_calc_max_scaled_time( + unsigned int time_per_pixel, + enum mmhubbub_wbif_mode mode, + unsigned int urgent_watermark) +{ + unsigned int time_per_byte = 0; + unsigned int total_y_free_entry = 0x200; /* two memory piece for luma */ + unsigned int total_c_free_entry = 0x140; /* two memory piece for chroma */ + unsigned int small_free_entry, max_free_entry; + unsigned int buf_lh_capability; + unsigned int max_scaled_time; + + if (mode == PACKED_444) /* packed mode */ + time_per_byte = time_per_pixel/4; + else if (mode == PLANAR_420_8BPC) + time_per_byte = time_per_pixel; + else if (mode == PLANAR_420_10BPC) /* p010 */ + time_per_byte = time_per_pixel * 819/1024; + + if (time_per_byte == 0) + time_per_byte = 1; + + small_free_entry = (total_y_free_entry > total_c_free_entry) ? total_c_free_entry : total_y_free_entry; + max_free_entry = (mode == PACKED_444) ? total_y_free_entry + total_c_free_entry : small_free_entry; + buf_lh_capability = max_free_entry*time_per_byte*32/16; /* there is 4bit fraction */ + max_scaled_time = buf_lh_capability - urgent_watermark; + return max_scaled_time; +} + +void dcn20_set_mcif_arb_params( + struct dc *dc, + struct dc_state *context, + display_e2e_pipe_params_st *pipes, + int pipe_cnt) +{ + enum mmhubbub_wbif_mode wbif_mode; + struct mcif_arb_params *wb_arb_params; + int i, j, dwb_pipe; + + /* Writeback MCIF_WB arbitration parameters */ + dwb_pipe = 0; + for (i = 0; i < dc->res_pool->pipe_count; i++) { + + if (!context->res_ctx.pipe_ctx[i].stream) + continue; + + for (j = 0; j < MAX_DWB_PIPES; j++) { + if (context->res_ctx.pipe_ctx[i].stream->writeback_info[j].wb_enabled == false) + continue; + + //wb_arb_params = &context->res_ctx.pipe_ctx[i].stream->writeback_info[j].mcif_arb_params; + wb_arb_params = &context->bw_ctx.bw.dcn.bw_writeback.mcif_wb_arb[dwb_pipe]; + + if (context->res_ctx.pipe_ctx[i].stream->writeback_info[j].dwb_params.out_format == dwb_scaler_mode_yuv420) { + if (context->res_ctx.pipe_ctx[i].stream->writeback_info[j].dwb_params.output_depth == DWB_OUTPUT_PIXEL_DEPTH_8BPC) + wbif_mode = PLANAR_420_8BPC; + else + wbif_mode = PLANAR_420_10BPC; + } else + wbif_mode = PACKED_444; + + DC_FP_START(); + dcn20_fpu_set_wb_arb_params(wb_arb_params, context, pipes, pipe_cnt, i); + DC_FP_END(); + + wb_arb_params->slice_lines = 32; + wb_arb_params->arbitration_slice = 2; + wb_arb_params->max_scaled_time = dcn20_calc_max_scaled_time(wb_arb_params->time_per_pixel, + wbif_mode, + wb_arb_params->cli_watermark[0]); /* assume 4 watermark sets have the same value */ + + dwb_pipe++; + + if (dwb_pipe >= MAX_DWB_PIPES) + return; + } + if (dwb_pipe >= MAX_DWB_PIPES) + return; + } +} + +bool dcn20_validate_dsc(struct dc *dc, struct dc_state *new_ctx) +{ + int i; + + /* Validate DSC config, dsc count validation is already done */ + for (i = 0; i < dc->res_pool->pipe_count; i++) { + struct pipe_ctx *pipe_ctx = &new_ctx->res_ctx.pipe_ctx[i]; + struct dc_stream_state *stream = pipe_ctx->stream; + struct dsc_config dsc_cfg; + struct pipe_ctx *odm_pipe; + int opp_cnt = 1; + + for (odm_pipe = pipe_ctx->next_odm_pipe; odm_pipe; odm_pipe = odm_pipe->next_odm_pipe) + opp_cnt++; + + /* Only need to validate top pipe */ + if (pipe_ctx->top_pipe || pipe_ctx->prev_odm_pipe || !stream || !stream->timing.flags.DSC) + continue; + + dsc_cfg.pic_width = (stream->timing.h_addressable + stream->timing.h_border_left + + stream->timing.h_border_right) / opp_cnt; + dsc_cfg.pic_height = stream->timing.v_addressable + stream->timing.v_border_top + + stream->timing.v_border_bottom; + dsc_cfg.pixel_encoding = stream->timing.pixel_encoding; + dsc_cfg.color_depth = stream->timing.display_color_depth; + dsc_cfg.is_odm = pipe_ctx->next_odm_pipe ? true : false; + dsc_cfg.dc_dsc_cfg = stream->timing.dsc_cfg; + dsc_cfg.dc_dsc_cfg.num_slices_h /= opp_cnt; + + if (!pipe_ctx->stream_res.dsc->funcs->dsc_validate_stream(pipe_ctx->stream_res.dsc, &dsc_cfg)) + return false; + } + return true; +} + +struct pipe_ctx *dcn20_find_secondary_pipe(struct dc *dc, + struct resource_context *res_ctx, + const struct resource_pool *pool, + const struct pipe_ctx *primary_pipe) +{ + struct pipe_ctx *secondary_pipe = NULL; + + if (dc && primary_pipe) { + int j; + int preferred_pipe_idx = 0; + + /* first check the prev dc state: + * if this primary pipe has a bottom pipe in prev. state + * and if the bottom pipe is still available (which it should be), + * pick that pipe as secondary + * Same logic applies for ODM pipes + */ + if (dc->current_state->res_ctx.pipe_ctx[primary_pipe->pipe_idx].next_odm_pipe) { + preferred_pipe_idx = dc->current_state->res_ctx.pipe_ctx[primary_pipe->pipe_idx].next_odm_pipe->pipe_idx; + if (res_ctx->pipe_ctx[preferred_pipe_idx].stream == NULL) { + secondary_pipe = &res_ctx->pipe_ctx[preferred_pipe_idx]; + secondary_pipe->pipe_idx = preferred_pipe_idx; + } + } + if (secondary_pipe == NULL && + dc->current_state->res_ctx.pipe_ctx[primary_pipe->pipe_idx].bottom_pipe) { + preferred_pipe_idx = dc->current_state->res_ctx.pipe_ctx[primary_pipe->pipe_idx].bottom_pipe->pipe_idx; + if (res_ctx->pipe_ctx[preferred_pipe_idx].stream == NULL) { + secondary_pipe = &res_ctx->pipe_ctx[preferred_pipe_idx]; + secondary_pipe->pipe_idx = preferred_pipe_idx; + } + } + + /* + * if this primary pipe does not have a bottom pipe in prev. state + * start backward and find a pipe that did not used to be a bottom pipe in + * prev. dc state. This way we make sure we keep the same assignment as + * last state and will not have to reprogram every pipe + */ + if (secondary_pipe == NULL) { + for (j = dc->res_pool->pipe_count - 1; j >= 0; j--) { + if (dc->current_state->res_ctx.pipe_ctx[j].top_pipe == NULL + && dc->current_state->res_ctx.pipe_ctx[j].prev_odm_pipe == NULL) { + preferred_pipe_idx = j; + + if (res_ctx->pipe_ctx[preferred_pipe_idx].stream == NULL) { + secondary_pipe = &res_ctx->pipe_ctx[preferred_pipe_idx]; + secondary_pipe->pipe_idx = preferred_pipe_idx; + break; + } + } + } + } + /* + * We should never hit this assert unless assignments are shuffled around + * if this happens we will prob. hit a vsync tdr + */ + ASSERT(secondary_pipe); + /* + * search backwards for the second pipe to keep pipe + * assignment more consistent + */ + if (secondary_pipe == NULL) { + for (j = dc->res_pool->pipe_count - 1; j >= 0; j--) { + preferred_pipe_idx = j; + + if (res_ctx->pipe_ctx[preferred_pipe_idx].stream == NULL) { + secondary_pipe = &res_ctx->pipe_ctx[preferred_pipe_idx]; + secondary_pipe->pipe_idx = preferred_pipe_idx; + break; + } + } + } + } + + return secondary_pipe; +} + +void dcn20_merge_pipes_for_validate( + struct dc *dc, + struct dc_state *context) +{ + int i; + + /* merge previously split odm pipes since mode support needs to make the decision */ + for (i = 0; i < dc->res_pool->pipe_count; i++) { + struct pipe_ctx *pipe = &context->res_ctx.pipe_ctx[i]; + struct pipe_ctx *odm_pipe = pipe->next_odm_pipe; + + if (pipe->prev_odm_pipe) + continue; + + pipe->next_odm_pipe = NULL; + while (odm_pipe) { + struct pipe_ctx *next_odm_pipe = odm_pipe->next_odm_pipe; + + odm_pipe->plane_state = NULL; + odm_pipe->stream = NULL; + odm_pipe->top_pipe = NULL; + odm_pipe->bottom_pipe = NULL; + odm_pipe->prev_odm_pipe = NULL; + odm_pipe->next_odm_pipe = NULL; + if (odm_pipe->stream_res.dsc) + dcn20_release_dsc(&context->res_ctx, dc->res_pool, &odm_pipe->stream_res.dsc); + /* Clear plane_res and stream_res */ + memset(&odm_pipe->plane_res, 0, sizeof(odm_pipe->plane_res)); + memset(&odm_pipe->stream_res, 0, sizeof(odm_pipe->stream_res)); + odm_pipe = next_odm_pipe; + } + if (pipe->plane_state) + resource_build_scaling_params(pipe); + } + + /* merge previously mpc split pipes since mode support needs to make the decision */ + for (i = 0; i < dc->res_pool->pipe_count; i++) { + struct pipe_ctx *pipe = &context->res_ctx.pipe_ctx[i]; + struct pipe_ctx *hsplit_pipe = pipe->bottom_pipe; + + if (!hsplit_pipe || hsplit_pipe->plane_state != pipe->plane_state) + continue; + + pipe->bottom_pipe = hsplit_pipe->bottom_pipe; + if (hsplit_pipe->bottom_pipe) + hsplit_pipe->bottom_pipe->top_pipe = pipe; + hsplit_pipe->plane_state = NULL; + hsplit_pipe->stream = NULL; + hsplit_pipe->top_pipe = NULL; + hsplit_pipe->bottom_pipe = NULL; + + /* Clear plane_res and stream_res */ + memset(&hsplit_pipe->plane_res, 0, sizeof(hsplit_pipe->plane_res)); + memset(&hsplit_pipe->stream_res, 0, sizeof(hsplit_pipe->stream_res)); + if (pipe->plane_state) + resource_build_scaling_params(pipe); + } +} + +int dcn20_validate_apply_pipe_split_flags( + struct dc *dc, + struct dc_state *context, + int vlevel, + int *split, + bool *merge) +{ + int i, pipe_idx, vlevel_split; + int plane_count = 0; + bool force_split = false; + bool avoid_split = dc->debug.pipe_split_policy == MPC_SPLIT_AVOID; + struct vba_vars_st *v = &context->bw_ctx.dml.vba; + int max_mpc_comb = v->maxMpcComb; + + if (context->stream_count > 1) { + if (dc->debug.pipe_split_policy == MPC_SPLIT_AVOID_MULT_DISP) + avoid_split = true; + } else if (dc->debug.force_single_disp_pipe_split) + force_split = true; + + for (i = 0; i < dc->res_pool->pipe_count; i++) { + struct pipe_ctx *pipe = &context->res_ctx.pipe_ctx[i]; + + /** + * Workaround for avoiding pipe-split in cases where we'd split + * planes that are too small, resulting in splits that aren't + * valid for the scaler. + */ + if (pipe->plane_state && + (pipe->plane_state->dst_rect.width <= 16 || + pipe->plane_state->dst_rect.height <= 16 || + pipe->plane_state->src_rect.width <= 16 || + pipe->plane_state->src_rect.height <= 16)) + avoid_split = true; + + /* TODO: fix dc bugs and remove this split threshold thing */ + if (pipe->stream && !pipe->prev_odm_pipe && + (!pipe->top_pipe || pipe->top_pipe->plane_state != pipe->plane_state)) + ++plane_count; + } + if (plane_count > dc->res_pool->pipe_count / 2) + avoid_split = true; + + /* W/A: Mode timing with borders may not work well with pipe split, avoid for this corner case */ + for (i = 0; i < dc->res_pool->pipe_count; i++) { + struct pipe_ctx *pipe = &context->res_ctx.pipe_ctx[i]; + struct dc_crtc_timing timing; + + if (!pipe->stream) + continue; + else { + timing = pipe->stream->timing; + if (timing.h_border_left + timing.h_border_right + + timing.v_border_top + timing.v_border_bottom > 0) { + avoid_split = true; + break; + } + } + } + + /* Avoid split loop looks for lowest voltage level that allows most unsplit pipes possible */ + if (avoid_split) { + for (i = 0, pipe_idx = 0; i < dc->res_pool->pipe_count; i++) { + if (!context->res_ctx.pipe_ctx[i].stream) + continue; + + for (vlevel_split = vlevel; vlevel <= context->bw_ctx.dml.soc.num_states; vlevel++) + if (v->NoOfDPP[vlevel][0][pipe_idx] == 1 && + v->ModeSupport[vlevel][0]) + break; + /* Impossible to not split this pipe */ + if (vlevel > context->bw_ctx.dml.soc.num_states) + vlevel = vlevel_split; + else + max_mpc_comb = 0; + pipe_idx++; + } + v->maxMpcComb = max_mpc_comb; + } + + /* Split loop sets which pipe should be split based on dml outputs and dc flags */ + for (i = 0, pipe_idx = 0; i < dc->res_pool->pipe_count; i++) { + struct pipe_ctx *pipe = &context->res_ctx.pipe_ctx[i]; + int pipe_plane = v->pipe_plane[pipe_idx]; + bool split4mpc = context->stream_count == 1 && plane_count == 1 + && dc->config.enable_4to1MPC && dc->res_pool->pipe_count >= 4; + + if (!context->res_ctx.pipe_ctx[i].stream) + continue; + + if (split4mpc || v->NoOfDPP[vlevel][max_mpc_comb][pipe_plane] == 4) + split[i] = 4; + else if (force_split || v->NoOfDPP[vlevel][max_mpc_comb][pipe_plane] == 2) + split[i] = 2; + + if ((pipe->stream->view_format == + VIEW_3D_FORMAT_SIDE_BY_SIDE || + pipe->stream->view_format == + VIEW_3D_FORMAT_TOP_AND_BOTTOM) && + (pipe->stream->timing.timing_3d_format == + TIMING_3D_FORMAT_TOP_AND_BOTTOM || + pipe->stream->timing.timing_3d_format == + TIMING_3D_FORMAT_SIDE_BY_SIDE)) + split[i] = 2; + if (dc->debug.force_odm_combine & (1 << pipe->stream_res.tg->inst)) { + split[i] = 2; + v->ODMCombineEnablePerState[vlevel][pipe_plane] = dm_odm_combine_mode_2to1; + } + if (dc->debug.force_odm_combine_4to1 & (1 << pipe->stream_res.tg->inst)) { + split[i] = 4; + v->ODMCombineEnablePerState[vlevel][pipe_plane] = dm_odm_combine_mode_4to1; + } + /*420 format workaround*/ + if (pipe->stream->timing.h_addressable > 7680 && + pipe->stream->timing.pixel_encoding == PIXEL_ENCODING_YCBCR420) { + split[i] = 4; + } + v->ODMCombineEnabled[pipe_plane] = + v->ODMCombineEnablePerState[vlevel][pipe_plane]; + + if (v->ODMCombineEnabled[pipe_plane] == dm_odm_combine_mode_disabled) { + if (resource_get_mpc_slice_count(pipe) == 2) { + /*If need split for mpc but 2 way split already*/ + if (split[i] == 4) + split[i] = 2; /* 2 -> 4 MPC */ + else if (split[i] == 2) + split[i] = 0; /* 2 -> 2 MPC */ + else if (pipe->top_pipe && pipe->top_pipe->plane_state == pipe->plane_state) + merge[i] = true; /* 2 -> 1 MPC */ + } else if (resource_get_mpc_slice_count(pipe) == 4) { + /*If need split for mpc but 4 way split already*/ + if (split[i] == 2 && ((pipe->top_pipe && !pipe->top_pipe->top_pipe) + || !pipe->bottom_pipe)) { + merge[i] = true; /* 4 -> 2 MPC */ + } else if (split[i] == 0 && pipe->top_pipe && + pipe->top_pipe->plane_state == pipe->plane_state) + merge[i] = true; /* 4 -> 1 MPC */ + split[i] = 0; + } else if (resource_get_odm_slice_count(pipe) > 1) { + /* ODM -> MPC transition */ + if (pipe->prev_odm_pipe) { + split[i] = 0; + merge[i] = true; + } + } + } else { + if (resource_get_odm_slice_count(pipe) == 2) { + /*If need split for odm but 2 way split already*/ + if (split[i] == 4) + split[i] = 2; /* 2 -> 4 ODM */ + else if (split[i] == 2) + split[i] = 0; /* 2 -> 2 ODM */ + else if (pipe->prev_odm_pipe) { + ASSERT(0); /* NOT expected yet */ + merge[i] = true; /* exit ODM */ + } + } else if (resource_get_odm_slice_count(pipe) == 4) { + /*If need split for odm but 4 way split already*/ + if (split[i] == 2 && ((pipe->prev_odm_pipe && !pipe->prev_odm_pipe->prev_odm_pipe) + || !pipe->next_odm_pipe)) { + merge[i] = true; /* 4 -> 2 ODM */ + } else if (split[i] == 0 && pipe->prev_odm_pipe) { + ASSERT(0); /* NOT expected yet */ + merge[i] = true; /* exit ODM */ + } + split[i] = 0; + } else if (resource_get_mpc_slice_count(pipe) > 1) { + /* MPC -> ODM transition */ + ASSERT(0); /* NOT expected yet */ + if (pipe->top_pipe && pipe->top_pipe->plane_state == pipe->plane_state) { + split[i] = 0; + merge[i] = true; + } + } + } + + /* Adjust dppclk when split is forced, do not bother with dispclk */ + if (split[i] != 0 && v->NoOfDPP[vlevel][max_mpc_comb][pipe_idx] == 1) { + DC_FP_START(); + dcn20_fpu_adjust_dppclk(v, vlevel, max_mpc_comb, pipe_idx, false); + DC_FP_END(); + } + pipe_idx++; + } + + return vlevel; +} + +bool dcn20_fast_validate_bw( + struct dc *dc, + struct dc_state *context, + display_e2e_pipe_params_st *pipes, + int *pipe_cnt_out, + int *pipe_split_from, + int *vlevel_out, + bool fast_validate) +{ + bool out = false; + int split[MAX_PIPES] = { 0 }; + int pipe_cnt, i, pipe_idx, vlevel; + + ASSERT(pipes); + if (!pipes) + return false; + + dcn20_merge_pipes_for_validate(dc, context); + + DC_FP_START(); + pipe_cnt = dc->res_pool->funcs->populate_dml_pipes(dc, context, pipes, fast_validate); + DC_FP_END(); + + *pipe_cnt_out = pipe_cnt; + + if (!pipe_cnt) { + out = true; + goto validate_out; + } + + vlevel = dml_get_voltage_level(&context->bw_ctx.dml, pipes, pipe_cnt); + + if (vlevel > context->bw_ctx.dml.soc.num_states) + goto validate_fail; + + vlevel = dcn20_validate_apply_pipe_split_flags(dc, context, vlevel, split, NULL); + + /*initialize pipe_just_split_from to invalid idx*/ + for (i = 0; i < MAX_PIPES; i++) + pipe_split_from[i] = -1; + + for (i = 0, pipe_idx = -1; i < dc->res_pool->pipe_count; i++) { + struct pipe_ctx *pipe = &context->res_ctx.pipe_ctx[i]; + struct pipe_ctx *hsplit_pipe = pipe->bottom_pipe; + + if (!pipe->stream || pipe_split_from[i] >= 0) + continue; + + pipe_idx++; + + if (!pipe->top_pipe && !pipe->plane_state && context->bw_ctx.dml.vba.ODMCombineEnabled[pipe_idx]) { + hsplit_pipe = dcn20_find_secondary_pipe(dc, &context->res_ctx, dc->res_pool, pipe); + ASSERT(hsplit_pipe); + if (!dcn20_split_stream_for_odm( + dc, &context->res_ctx, + pipe, hsplit_pipe)) + goto validate_fail; + pipe_split_from[hsplit_pipe->pipe_idx] = pipe_idx; + dcn20_build_mapped_resource(dc, context, pipe->stream); + } + + if (!pipe->plane_state) + continue; + /* Skip 2nd half of already split pipe */ + if (pipe->top_pipe && pipe->plane_state == pipe->top_pipe->plane_state) + continue; + + /* We do not support mpo + odm at the moment */ + if (hsplit_pipe && hsplit_pipe->plane_state != pipe->plane_state + && context->bw_ctx.dml.vba.ODMCombineEnabled[pipe_idx]) + goto validate_fail; + + if (split[i] == 2) { + if (!hsplit_pipe || hsplit_pipe->plane_state != pipe->plane_state) { + /* pipe not split previously needs split */ + hsplit_pipe = dcn20_find_secondary_pipe(dc, &context->res_ctx, dc->res_pool, pipe); + ASSERT(hsplit_pipe); + if (!hsplit_pipe) { + DC_FP_START(); + dcn20_fpu_adjust_dppclk(&context->bw_ctx.dml.vba, vlevel, context->bw_ctx.dml.vba.maxMpcComb, pipe_idx, true); + DC_FP_END(); + continue; + } + if (context->bw_ctx.dml.vba.ODMCombineEnabled[pipe_idx]) { + if (!dcn20_split_stream_for_odm( + dc, &context->res_ctx, + pipe, hsplit_pipe)) + goto validate_fail; + dcn20_build_mapped_resource(dc, context, pipe->stream); + } else { + dcn20_split_stream_for_mpc( + &context->res_ctx, dc->res_pool, + pipe, hsplit_pipe); + resource_build_scaling_params(pipe); + resource_build_scaling_params(hsplit_pipe); + } + pipe_split_from[hsplit_pipe->pipe_idx] = pipe_idx; + } + } else if (hsplit_pipe && hsplit_pipe->plane_state == pipe->plane_state) { + /* merge should already have been done */ + ASSERT(0); + } + } + /* Actual dsc count per stream dsc validation*/ + if (!dcn20_validate_dsc(dc, context)) { + context->bw_ctx.dml.vba.ValidationStatus[context->bw_ctx.dml.vba.soc.num_states] = + DML_FAIL_DSC_VALIDATION_FAILURE; + goto validate_fail; + } + + *vlevel_out = vlevel; + + out = true; + goto validate_out; + +validate_fail: + out = false; + +validate_out: + return out; +} + +bool dcn20_validate_bandwidth(struct dc *dc, struct dc_state *context, + bool fast_validate) +{ + bool voltage_supported; + display_e2e_pipe_params_st *pipes; + + pipes = kcalloc(dc->res_pool->pipe_count, sizeof(display_e2e_pipe_params_st), GFP_KERNEL); + if (!pipes) + return false; + + DC_FP_START(); + voltage_supported = dcn20_validate_bandwidth_fp(dc, context, fast_validate, pipes); + DC_FP_END(); + + kfree(pipes); + return voltage_supported; +} + +struct pipe_ctx *dcn20_acquire_free_pipe_for_layer( + const struct dc_state *cur_ctx, + struct dc_state *new_ctx, + const struct resource_pool *pool, + const struct pipe_ctx *opp_head) +{ + struct resource_context *res_ctx = &new_ctx->res_ctx; + struct pipe_ctx *otg_master = resource_get_otg_master_for_stream(res_ctx, opp_head->stream); + struct pipe_ctx *sec_dpp_pipe = resource_find_free_secondary_pipe_legacy(res_ctx, pool, otg_master); + + ASSERT(otg_master); + + if (!sec_dpp_pipe) + return NULL; + + sec_dpp_pipe->stream = opp_head->stream; + sec_dpp_pipe->stream_res.tg = opp_head->stream_res.tg; + sec_dpp_pipe->stream_res.opp = opp_head->stream_res.opp; + + sec_dpp_pipe->plane_res.hubp = pool->hubps[sec_dpp_pipe->pipe_idx]; + sec_dpp_pipe->plane_res.ipp = pool->ipps[sec_dpp_pipe->pipe_idx]; + sec_dpp_pipe->plane_res.dpp = pool->dpps[sec_dpp_pipe->pipe_idx]; + sec_dpp_pipe->plane_res.mpcc_inst = pool->dpps[sec_dpp_pipe->pipe_idx]->inst; + + return sec_dpp_pipe; +} + +bool dcn20_get_dcc_compression_cap(const struct dc *dc, + const struct dc_dcc_surface_param *input, + struct dc_surface_dcc_cap *output) +{ + return dc->res_pool->hubbub->funcs->get_dcc_compression_cap( + dc->res_pool->hubbub, + input, + output); +} + +static void dcn20_destroy_resource_pool(struct resource_pool **pool) +{ + struct dcn20_resource_pool *dcn20_pool = TO_DCN20_RES_POOL(*pool); + + dcn20_resource_destruct(dcn20_pool); + kfree(dcn20_pool); + *pool = NULL; +} + + +static struct dc_cap_funcs cap_funcs = { + .get_dcc_compression_cap = dcn20_get_dcc_compression_cap +}; + + +enum dc_status dcn20_patch_unknown_plane_state(struct dc_plane_state *plane_state) +{ + enum surface_pixel_format surf_pix_format = plane_state->format; + unsigned int bpp = resource_pixel_format_to_bpp(surf_pix_format); + + plane_state->tiling_info.gfx9.swizzle = DC_SW_64KB_S; + if (bpp == 64) + plane_state->tiling_info.gfx9.swizzle = DC_SW_64KB_D; + + return DC_OK; +} + +void dcn20_release_pipe(struct dc_state *context, + struct pipe_ctx *pipe, + const struct resource_pool *pool) +{ + if (resource_is_pipe_type(pipe, OPP_HEAD) && pipe->stream_res.dsc) + dcn20_release_dsc(&context->res_ctx, pool, &pipe->stream_res.dsc); + memset(pipe, 0, sizeof(*pipe)); +} + +static const struct resource_funcs dcn20_res_pool_funcs = { + .destroy = dcn20_destroy_resource_pool, + .link_enc_create = dcn20_link_encoder_create, + .panel_cntl_create = dcn20_panel_cntl_create, + .validate_bandwidth = dcn20_validate_bandwidth, + .acquire_free_pipe_as_secondary_dpp_pipe = dcn20_acquire_free_pipe_for_layer, + .release_pipe = dcn20_release_pipe, + .add_stream_to_ctx = dcn20_add_stream_to_ctx, + .add_dsc_to_stream_resource = dcn20_add_dsc_to_stream_resource, + .remove_stream_from_ctx = dcn20_remove_stream_from_ctx, + .populate_dml_writeback_from_context = dcn20_populate_dml_writeback_from_context, + .patch_unknown_plane_state = dcn20_patch_unknown_plane_state, + .set_mcif_arb_params = dcn20_set_mcif_arb_params, + .populate_dml_pipes = dcn20_populate_dml_pipes_from_context, + .find_first_free_match_stream_enc_for_link = dcn10_find_first_free_match_stream_enc_for_link +}; + +bool dcn20_dwbc_create(struct dc_context *ctx, struct resource_pool *pool) +{ + int i; + uint32_t pipe_count = pool->res_cap->num_dwb; + + for (i = 0; i < pipe_count; i++) { + struct dcn20_dwbc *dwbc20 = kzalloc(sizeof(struct dcn20_dwbc), + GFP_KERNEL); + + if (!dwbc20) { + dm_error("DC: failed to create dwbc20!\n"); + return false; + } + dcn20_dwbc_construct(dwbc20, ctx, + &dwbc20_regs[i], + &dwbc20_shift, + &dwbc20_mask, + i); + pool->dwbc[i] = &dwbc20->base; + } + return true; +} + +bool dcn20_mmhubbub_create(struct dc_context *ctx, struct resource_pool *pool) +{ + int i; + uint32_t pipe_count = pool->res_cap->num_dwb; + + ASSERT(pipe_count > 0); + + for (i = 0; i < pipe_count; i++) { + struct dcn20_mmhubbub *mcif_wb20 = kzalloc(sizeof(struct dcn20_mmhubbub), + GFP_KERNEL); + + if (!mcif_wb20) { + dm_error("DC: failed to create mcif_wb20!\n"); + return false; + } + + dcn20_mmhubbub_construct(mcif_wb20, ctx, + &mcif_wb20_regs[i], + &mcif_wb20_shift, + &mcif_wb20_mask, + i); + + pool->mcif_wb[i] = &mcif_wb20->base; + } + return true; +} + +static struct pp_smu_funcs *dcn20_pp_smu_create(struct dc_context *ctx) +{ + struct pp_smu_funcs *pp_smu = kzalloc(sizeof(*pp_smu), GFP_ATOMIC); + + if (!pp_smu) + return pp_smu; + + dm_pp_get_funcs(ctx, pp_smu); + + if (pp_smu->ctx.ver != PP_SMU_VER_NV) + pp_smu = memset(pp_smu, 0, sizeof(struct pp_smu_funcs)); + + return pp_smu; +} + +static void dcn20_pp_smu_destroy(struct pp_smu_funcs **pp_smu) +{ + if (pp_smu && *pp_smu) { + kfree(*pp_smu); + *pp_smu = NULL; + } +} + +static struct _vcs_dpi_soc_bounding_box_st *get_asic_rev_soc_bb( + uint32_t hw_internal_rev) +{ + if (ASICREV_IS_NAVI14_M(hw_internal_rev)) + return &dcn2_0_nv14_soc; + + if (ASICREV_IS_NAVI12_P(hw_internal_rev)) + return &dcn2_0_nv12_soc; + + return &dcn2_0_soc; +} + +static struct _vcs_dpi_ip_params_st *get_asic_rev_ip_params( + uint32_t hw_internal_rev) +{ + /* NV14 */ + if (ASICREV_IS_NAVI14_M(hw_internal_rev)) + return &dcn2_0_nv14_ip; + + /* NV12 and NV10 */ + return &dcn2_0_ip; +} + +static enum dml_project get_dml_project_version(uint32_t hw_internal_rev) +{ + return DML_PROJECT_NAVI10v2; +} + +static bool init_soc_bounding_box(struct dc *dc, + struct dcn20_resource_pool *pool) +{ + 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 = + get_asic_rev_ip_params(dc->ctx->asic_id.hw_internal_rev); + + DC_LOGGER_INIT(dc->ctx->logger); + + if (pool->base.pp_smu) { + struct pp_smu_nv_clock_table max_clocks = {0}; + unsigned int uclk_states[8] = {0}; + unsigned int num_states = 0; + enum pp_smu_status status; + bool clock_limits_available = false; + bool uclk_states_available = false; + + if (pool->base.pp_smu->nv_funcs.get_uclk_dpm_states) { + status = (pool->base.pp_smu->nv_funcs.get_uclk_dpm_states) + (&pool->base.pp_smu->nv_funcs.pp_smu, uclk_states, &num_states); + + uclk_states_available = (status == PP_SMU_RESULT_OK); + } + + if (pool->base.pp_smu->nv_funcs.get_maximum_sustainable_clocks) { + status = (*pool->base.pp_smu->nv_funcs.get_maximum_sustainable_clocks) + (&pool->base.pp_smu->nv_funcs.pp_smu, &max_clocks); + /* SMU cannot set DCF clock to anything equal to or higher than SOC clock + */ + if (max_clocks.dcfClockInKhz >= max_clocks.socClockInKhz) + max_clocks.dcfClockInKhz = max_clocks.socClockInKhz - 1000; + clock_limits_available = (status == PP_SMU_RESULT_OK); + } + + if (clock_limits_available && uclk_states_available && num_states) { + DC_FP_START(); + dcn20_update_bounding_box(dc, loaded_bb, &max_clocks, uclk_states, num_states); + DC_FP_END(); + } else if (clock_limits_available) { + DC_FP_START(); + dcn20_cap_soc_clocks(loaded_bb, max_clocks); + DC_FP_END(); + } + } + + loaded_ip->max_num_otg = pool->base.res_cap->num_timing_generator; + loaded_ip->max_num_dpp = pool->base.pipe_count; + DC_FP_START(); + dcn20_patch_bounding_box(dc, loaded_bb); + DC_FP_END(); + return true; +} + +static bool dcn20_resource_construct( + uint8_t num_virtual_links, + struct dc *dc, + struct dcn20_resource_pool *pool) +{ + int i; + struct dc_context *ctx = dc->ctx; + struct irq_service_init_data init_data; + struct ddc_service_init_data ddc_init_data = {0}; + struct _vcs_dpi_soc_bounding_box_st *loaded_bb = + get_asic_rev_soc_bb(ctx->asic_id.hw_internal_rev); + struct _vcs_dpi_ip_params_st *loaded_ip = + get_asic_rev_ip_params(ctx->asic_id.hw_internal_rev); + enum dml_project dml_project_version = + get_dml_project_version(ctx->asic_id.hw_internal_rev); + + ctx->dc_bios->regs = &bios_regs; + pool->base.funcs = &dcn20_res_pool_funcs; + + if (ASICREV_IS_NAVI14_M(ctx->asic_id.hw_internal_rev)) { + pool->base.res_cap = &res_cap_nv14; + pool->base.pipe_count = 5; + pool->base.mpcc_count = 5; + } else { + pool->base.res_cap = &res_cap_nv10; + pool->base.pipe_count = 6; + pool->base.mpcc_count = 6; + } + /************************************************* + * Resource + asic cap harcoding * + *************************************************/ + pool->base.underlay_pipe_index = NO_UNDERLAY_PIPE; + + dc->caps.max_downscale_ratio = 200; + dc->caps.i2c_speed_in_khz = 100; + dc->caps.i2c_speed_in_khz_hdcp = 100; /*1.4 w/a not applied by default*/ + dc->caps.max_cursor_size = 256; + dc->caps.min_horizontal_blanking_period = 80; + dc->caps.dmdata_alloc_size = 2048; + + dc->caps.max_slave_planes = 1; + dc->caps.max_slave_yuv_planes = 1; + dc->caps.max_slave_rgb_planes = 1; + dc->caps.post_blend_color_processing = true; + dc->caps.force_dp_tps4_for_cp2520 = true; + dc->caps.extended_aux_timeout_support = true; + + /* Color pipeline capabilities */ + dc->caps.color.dpp.dcn_arch = 1; + dc->caps.color.dpp.input_lut_shared = 0; + dc->caps.color.dpp.icsc = 1; + dc->caps.color.dpp.dgam_ram = 1; + dc->caps.color.dpp.dgam_rom_caps.srgb = 1; + dc->caps.color.dpp.dgam_rom_caps.bt2020 = 1; + dc->caps.color.dpp.dgam_rom_caps.gamma2_2 = 0; + dc->caps.color.dpp.dgam_rom_caps.pq = 0; + dc->caps.color.dpp.dgam_rom_caps.hlg = 0; + dc->caps.color.dpp.post_csc = 0; + dc->caps.color.dpp.gamma_corr = 0; + dc->caps.color.dpp.dgam_rom_for_yuv = 1; + + dc->caps.color.dpp.hw_3d_lut = 1; + dc->caps.color.dpp.ogam_ram = 1; + // no OGAM ROM on DCN2, only MPC ROM + dc->caps.color.dpp.ogam_rom_caps.srgb = 0; + dc->caps.color.dpp.ogam_rom_caps.bt2020 = 0; + dc->caps.color.dpp.ogam_rom_caps.gamma2_2 = 0; + dc->caps.color.dpp.ogam_rom_caps.pq = 0; + dc->caps.color.dpp.ogam_rom_caps.hlg = 0; + dc->caps.color.dpp.ocsc = 0; + + dc->caps.color.mpc.gamut_remap = 0; + dc->caps.color.mpc.num_3dluts = 0; + dc->caps.color.mpc.shared_3d_lut = 0; + dc->caps.color.mpc.ogam_ram = 1; + dc->caps.color.mpc.ogam_rom_caps.srgb = 0; + dc->caps.color.mpc.ogam_rom_caps.bt2020 = 0; + dc->caps.color.mpc.ogam_rom_caps.gamma2_2 = 0; + dc->caps.color.mpc.ogam_rom_caps.pq = 0; + dc->caps.color.mpc.ogam_rom_caps.hlg = 0; + dc->caps.color.mpc.ocsc = 1; + + dc->caps.dp_hdmi21_pcon_support = true; + + if (dc->ctx->dce_environment == DCE_ENV_PRODUCTION_DRV) + dc->debug = debug_defaults_drv; + + //dcn2.0x + dc->work_arounds.dedcn20_305_wa = true; + + // Init the vm_helper + if (dc->vm_helper) + vm_helper_init(dc->vm_helper, 16); + + /************************************************* + * Create resources * + *************************************************/ + + pool->base.clock_sources[DCN20_CLK_SRC_PLL0] = + dcn20_clock_source_create(ctx, ctx->dc_bios, + CLOCK_SOURCE_COMBO_PHY_PLL0, + &clk_src_regs[0], false); + pool->base.clock_sources[DCN20_CLK_SRC_PLL1] = + dcn20_clock_source_create(ctx, ctx->dc_bios, + CLOCK_SOURCE_COMBO_PHY_PLL1, + &clk_src_regs[1], false); + pool->base.clock_sources[DCN20_CLK_SRC_PLL2] = + dcn20_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] = + dcn20_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] = + dcn20_clock_source_create(ctx, ctx->dc_bios, + CLOCK_SOURCE_COMBO_PHY_PLL4, + &clk_src_regs[4], false); + pool->base.clock_sources[DCN20_CLK_SRC_PLL5] = + dcn20_clock_source_create(ctx, ctx->dc_bios, + CLOCK_SOURCE_COMBO_PHY_PLL5, + &clk_src_regs[5], false); + pool->base.clk_src_count = DCN20_CLK_SRC_TOTAL; + /* todo: not reuse phy_pll registers */ + pool->base.dp_clock_source = + dcn20_clock_source_create(ctx, ctx->dc_bios, + CLOCK_SOURCE_ID_DP_DTO, + &clk_src_regs[0], true); + + for (i = 0; i < pool->base.clk_src_count; i++) { + if (pool->base.clock_sources[i] == NULL) { + dm_error("DC: failed to create clock sources!\n"); + BREAK_TO_DEBUGGER(); + goto create_fail; + } + } + + pool->base.dccg = dccg2_create(ctx, &dccg_regs, &dccg_shift, &dccg_mask); + if (pool->base.dccg == NULL) { + dm_error("DC: failed to create dccg!\n"); + BREAK_TO_DEBUGGER(); + goto create_fail; + } + + pool->base.dmcu = dcn20_dmcu_create(ctx, + &dmcu_regs, + &dmcu_shift, + &dmcu_mask); + if (pool->base.dmcu == NULL) { + dm_error("DC: failed to create dmcu!\n"); + BREAK_TO_DEBUGGER(); + goto create_fail; + } + + pool->base.abm = dce_abm_create(ctx, + &abm_regs, + &abm_shift, + &abm_mask); + if (pool->base.abm == NULL) { + dm_error("DC: failed to create abm!\n"); + BREAK_TO_DEBUGGER(); + goto create_fail; + } + + pool->base.pp_smu = dcn20_pp_smu_create(ctx); + + + if (!init_soc_bounding_box(dc, pool)) { + dm_error("DC: failed to initialize soc bounding box!\n"); + BREAK_TO_DEBUGGER(); + goto create_fail; + } + + dml_init_instance(&dc->dml, loaded_bb, loaded_ip, dml_project_version); + + if (!dc->debug.disable_pplib_wm_range) { + struct pp_smu_wm_range_sets ranges = {0}; + int i = 0; + + ranges.num_reader_wm_sets = 0; + + if (loaded_bb->num_states == 1) { + ranges.reader_wm_sets[0].wm_inst = i; + ranges.reader_wm_sets[0].min_drain_clk_mhz = PP_SMU_WM_SET_RANGE_CLK_UNCONSTRAINED_MIN; + ranges.reader_wm_sets[0].max_drain_clk_mhz = PP_SMU_WM_SET_RANGE_CLK_UNCONSTRAINED_MAX; + ranges.reader_wm_sets[0].min_fill_clk_mhz = PP_SMU_WM_SET_RANGE_CLK_UNCONSTRAINED_MIN; + ranges.reader_wm_sets[0].max_fill_clk_mhz = PP_SMU_WM_SET_RANGE_CLK_UNCONSTRAINED_MAX; + + ranges.num_reader_wm_sets = 1; + } else if (loaded_bb->num_states > 1) { + for (i = 0; i < 4 && i < loaded_bb->num_states; i++) { + ranges.reader_wm_sets[i].wm_inst = i; + ranges.reader_wm_sets[i].min_drain_clk_mhz = PP_SMU_WM_SET_RANGE_CLK_UNCONSTRAINED_MIN; + ranges.reader_wm_sets[i].max_drain_clk_mhz = PP_SMU_WM_SET_RANGE_CLK_UNCONSTRAINED_MAX; + DC_FP_START(); + dcn20_fpu_set_wm_ranges(i, &ranges, loaded_bb); + DC_FP_END(); + + ranges.num_reader_wm_sets = i + 1; + } + + ranges.reader_wm_sets[0].min_fill_clk_mhz = PP_SMU_WM_SET_RANGE_CLK_UNCONSTRAINED_MIN; + ranges.reader_wm_sets[ranges.num_reader_wm_sets - 1].max_fill_clk_mhz = PP_SMU_WM_SET_RANGE_CLK_UNCONSTRAINED_MAX; + } + + ranges.num_writer_wm_sets = 1; + + ranges.writer_wm_sets[0].wm_inst = 0; + ranges.writer_wm_sets[0].min_fill_clk_mhz = PP_SMU_WM_SET_RANGE_CLK_UNCONSTRAINED_MIN; + ranges.writer_wm_sets[0].max_fill_clk_mhz = PP_SMU_WM_SET_RANGE_CLK_UNCONSTRAINED_MAX; + ranges.writer_wm_sets[0].min_drain_clk_mhz = PP_SMU_WM_SET_RANGE_CLK_UNCONSTRAINED_MIN; + ranges.writer_wm_sets[0].max_drain_clk_mhz = PP_SMU_WM_SET_RANGE_CLK_UNCONSTRAINED_MAX; + + /* Notify PP Lib/SMU which Watermarks to use for which clock ranges */ + if (pool->base.pp_smu->nv_funcs.set_wm_ranges) + pool->base.pp_smu->nv_funcs.set_wm_ranges(&pool->base.pp_smu->nv_funcs.pp_smu, &ranges); + } + + init_data.ctx = dc->ctx; + pool->base.irqs = dal_irq_service_dcn20_create(&init_data); + if (!pool->base.irqs) + goto create_fail; + + /* mem input -> ipp -> dpp -> opp -> TG */ + for (i = 0; i < pool->base.pipe_count; i++) { + pool->base.hubps[i] = dcn20_hubp_create(ctx, i); + if (pool->base.hubps[i] == NULL) { + BREAK_TO_DEBUGGER(); + dm_error( + "DC: failed to create memory input!\n"); + goto create_fail; + } + + pool->base.ipps[i] = dcn20_ipp_create(ctx, i); + if (pool->base.ipps[i] == NULL) { + BREAK_TO_DEBUGGER(); + dm_error( + "DC: failed to create input pixel processor!\n"); + goto create_fail; + } + + pool->base.dpps[i] = dcn20_dpp_create(ctx, i); + if (pool->base.dpps[i] == NULL) { + BREAK_TO_DEBUGGER(); + dm_error( + "DC: failed to create dpps!\n"); + goto create_fail; + } + } + for (i = 0; i < pool->base.res_cap->num_ddc; i++) { + pool->base.engines[i] = dcn20_aux_engine_create(ctx, i); + if (pool->base.engines[i] == NULL) { + BREAK_TO_DEBUGGER(); + dm_error( + "DC:failed to create aux engine!!\n"); + goto create_fail; + } + pool->base.hw_i2cs[i] = dcn20_i2c_hw_create(ctx, i); + if (pool->base.hw_i2cs[i] == NULL) { + BREAK_TO_DEBUGGER(); + dm_error( + "DC:failed to create hw i2c!!\n"); + goto create_fail; + } + pool->base.sw_i2cs[i] = NULL; + } + + for (i = 0; i < pool->base.res_cap->num_opp; i++) { + pool->base.opps[i] = dcn20_opp_create(ctx, i); + if (pool->base.opps[i] == NULL) { + BREAK_TO_DEBUGGER(); + dm_error( + "DC: failed to create output pixel processor!\n"); + goto create_fail; + } + } + + for (i = 0; i < pool->base.res_cap->num_timing_generator; i++) { + pool->base.timing_generators[i] = dcn20_timing_generator_create( + ctx, i); + if (pool->base.timing_generators[i] == NULL) { + BREAK_TO_DEBUGGER(); + dm_error("DC: failed to create tg!\n"); + goto create_fail; + } + } + + pool->base.timing_generator_count = i; + + pool->base.mpc = dcn20_mpc_create(ctx); + if (pool->base.mpc == NULL) { + BREAK_TO_DEBUGGER(); + dm_error("DC: failed to create mpc!\n"); + goto create_fail; + } + + pool->base.hubbub = dcn20_hubbub_create(ctx); + if (pool->base.hubbub == NULL) { + BREAK_TO_DEBUGGER(); + dm_error("DC: failed to create hubbub!\n"); + goto create_fail; + } + + for (i = 0; i < pool->base.res_cap->num_dsc; i++) { + pool->base.dscs[i] = dcn20_dsc_create(ctx, i); + if (pool->base.dscs[i] == NULL) { + BREAK_TO_DEBUGGER(); + dm_error("DC: failed to create display stream compressor %d!\n", i); + goto create_fail; + } + } + + if (!dcn20_dwbc_create(ctx, &pool->base)) { + BREAK_TO_DEBUGGER(); + dm_error("DC: failed to create dwbc!\n"); + goto create_fail; + } + if (!dcn20_mmhubbub_create(ctx, &pool->base)) { + BREAK_TO_DEBUGGER(); + dm_error("DC: failed to create mcif_wb!\n"); + goto create_fail; + } + + if (!resource_construct(num_virtual_links, dc, &pool->base, + &res_create_funcs)) + goto create_fail; + + dcn20_hw_sequencer_construct(dc); + + // IF NV12, set PG function pointer to NULL. It's not that + // PG isn't supported for NV12, it's that we don't want to + // program the registers because that will cause more power + // to be consumed. We could have created dcn20_init_hw to get + // the same effect by checking ASIC rev, but there was a + // request at some point to not check ASIC rev on hw sequencer. + if (ASICREV_IS_NAVI12_P(dc->ctx->asic_id.hw_internal_rev)) { + dc->hwseq->funcs.enable_power_gating_plane = NULL; + dc->debug.disable_dpp_power_gate = true; + dc->debug.disable_hubp_power_gate = true; + } + + + dc->caps.max_planes = pool->base.pipe_count; + + for (i = 0; i < dc->caps.max_planes; ++i) + dc->caps.planes[i] = plane_cap; + + dc->cap_funcs = cap_funcs; + + if (dc->ctx->dc_bios->fw_info.oem_i2c_present) { + ddc_init_data.ctx = dc->ctx; + ddc_init_data.link = NULL; + ddc_init_data.id.id = dc->ctx->dc_bios->fw_info.oem_i2c_obj_id; + ddc_init_data.id.enum_id = 0; + ddc_init_data.id.type = OBJECT_TYPE_GENERIC; + pool->base.oem_device = dc->link_srv->create_ddc_service(&ddc_init_data); + } else { + pool->base.oem_device = NULL; + } + + return true; + +create_fail: + + dcn20_resource_destruct(pool); + + return false; +} + +struct resource_pool *dcn20_create_resource_pool( + const struct dc_init_data *init_data, + struct dc *dc) +{ + struct dcn20_resource_pool *pool = + kzalloc(sizeof(struct dcn20_resource_pool), GFP_ATOMIC); + + if (!pool) + return NULL; + + if (dcn20_resource_construct(init_data->num_virtual_links, dc, pool)) + return &pool->base; + + BREAK_TO_DEBUGGER(); + kfree(pool); + return NULL; +} diff --git a/drivers/gpu/drm/amd/display/dc/resource/dcn20/dcn20_resource.h b/drivers/gpu/drm/amd/display/dc/resource/dcn20/dcn20_resource.h new file mode 100644 index 000000000000..37ecaccc5d12 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/resource/dcn20/dcn20_resource.h @@ -0,0 +1,170 @@ +/* +* Copyright 2017 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_RESOURCE_DCN20_H__ +#define __DC_RESOURCE_DCN20_H__ + +#include "core_types.h" +#include "dml/dcn20/dcn20_fpu.h" + +#define TO_DCN20_RES_POOL(pool)\ + container_of(pool, struct dcn20_resource_pool, base) + +struct dc; +struct resource_pool; +struct _vcs_dpi_display_pipe_params_st; + +extern struct _vcs_dpi_ip_params_st dcn2_0_ip; +extern struct _vcs_dpi_ip_params_st dcn2_0_nv14_ip; +extern struct _vcs_dpi_soc_bounding_box_st dcn2_0_soc; +extern struct _vcs_dpi_soc_bounding_box_st dcn2_0_nv14_soc; +extern struct _vcs_dpi_soc_bounding_box_st dcn2_0_nv12_soc; + +struct dcn20_resource_pool { + struct resource_pool base; +}; +struct resource_pool *dcn20_create_resource_pool( + const struct dc_init_data *init_data, + struct dc *dc); + +struct link_encoder *dcn20_link_encoder_create( + struct dc_context *ctx, + const struct encoder_init_data *enc_init_data); + +unsigned int dcn20_calc_max_scaled_time( + unsigned int time_per_pixel, + enum mmhubbub_wbif_mode mode, + unsigned int urgent_watermark); + +struct pipe_ctx *dcn20_acquire_free_pipe_for_layer( + const struct dc_state *cur_ctx, + struct dc_state *new_ctx, + const struct resource_pool *pool, + const struct pipe_ctx *opp_head_pipe); +void dcn20_release_pipe(struct dc_state *context, + struct pipe_ctx *pipe, + const struct resource_pool *pool); +struct stream_encoder *dcn20_stream_encoder_create( + enum engine_id eng_id, + struct dc_context *ctx); + +struct dce_hwseq *dcn20_hwseq_create( + struct dc_context *ctx); + +bool dcn20_get_dcc_compression_cap(const struct dc *dc, + const struct dc_dcc_surface_param *input, + struct dc_surface_dcc_cap *output); + +void dcn20_dpp_destroy(struct dpp **dpp); + +struct dpp *dcn20_dpp_create( + struct dc_context *ctx, + uint32_t inst); + +struct input_pixel_processor *dcn20_ipp_create( + struct dc_context *ctx, uint32_t inst); + +struct output_pixel_processor *dcn20_opp_create( + struct dc_context *ctx, uint32_t inst); + +struct dce_aux *dcn20_aux_engine_create( + struct dc_context *ctx, uint32_t inst); + +struct dce_i2c_hw *dcn20_i2c_hw_create( + struct dc_context *ctx, + uint32_t inst); + +void dcn20_clock_source_destroy(struct clock_source **clk_src); + +struct display_stream_compressor *dcn20_dsc_create( + struct dc_context *ctx, uint32_t inst); +void dcn20_dsc_destroy(struct display_stream_compressor **dsc); + +struct hubp *dcn20_hubp_create( + struct dc_context *ctx, + uint32_t inst); +struct timing_generator *dcn20_timing_generator_create( + struct dc_context *ctx, + uint32_t instance); +struct mpc *dcn20_mpc_create(struct dc_context *ctx); +struct hubbub *dcn20_hubbub_create(struct dc_context *ctx); + +bool dcn20_dwbc_create(struct dc_context *ctx, struct resource_pool *pool); +bool dcn20_mmhubbub_create(struct dc_context *ctx, struct resource_pool *pool); + +void dcn20_set_mcif_arb_params( + struct dc *dc, + struct dc_state *context, + display_e2e_pipe_params_st *pipes, + int pipe_cnt); +bool dcn20_validate_bandwidth(struct dc *dc, struct dc_state *context, bool fast_validate); +void dcn20_merge_pipes_for_validate( + struct dc *dc, + struct dc_state *context); +int dcn20_validate_apply_pipe_split_flags( + struct dc *dc, + struct dc_state *context, + int vlevel, + int *split, + bool *merge); +void dcn20_release_dsc(struct resource_context *res_ctx, + const struct resource_pool *pool, + struct display_stream_compressor **dsc); +bool dcn20_validate_dsc(struct dc *dc, struct dc_state *new_ctx); +void dcn20_split_stream_for_mpc( + struct resource_context *res_ctx, + const struct resource_pool *pool, + struct pipe_ctx *primary_pipe, + struct pipe_ctx *secondary_pipe); +bool dcn20_split_stream_for_odm( + const struct dc *dc, + struct resource_context *res_ctx, + struct pipe_ctx *prev_odm_pipe, + struct pipe_ctx *next_odm_pipe); +void dcn20_acquire_dsc(const struct dc *dc, + struct resource_context *res_ctx, + struct display_stream_compressor **dsc, + int pipe_idx); +struct pipe_ctx *dcn20_find_secondary_pipe(struct dc *dc, + struct resource_context *res_ctx, + const struct resource_pool *pool, + const struct pipe_ctx *primary_pipe); +bool dcn20_fast_validate_bw( + struct dc *dc, + struct dc_state *context, + display_e2e_pipe_params_st *pipes, + int *pipe_cnt_out, + int *pipe_split_from, + int *vlevel_out, + bool fast_validate); + +enum dc_status dcn20_build_mapped_resource(const struct dc *dc, struct dc_state *context, struct dc_stream_state *stream); +enum dc_status dcn20_add_stream_to_ctx(struct dc *dc, struct dc_state *new_ctx, struct dc_stream_state *dc_stream); +enum dc_status dcn20_add_dsc_to_stream_resource(struct dc *dc, struct dc_state *dc_ctx, struct dc_stream_state *dc_stream); +enum dc_status dcn20_remove_stream_from_ctx(struct dc *dc, struct dc_state *new_ctx, struct dc_stream_state *dc_stream); +enum dc_status dcn20_patch_unknown_plane_state(struct dc_plane_state *plane_state); + +#endif /* __DC_RESOURCE_DCN20_H__ */ + diff --git a/drivers/gpu/drm/amd/display/dc/resource/dcn201/dcn201_resource.c b/drivers/gpu/drm/amd/display/dc/resource/dcn201/dcn201_resource.c new file mode 100644 index 000000000000..914b234d7f6b --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/resource/dcn201/dcn201_resource.c @@ -0,0 +1,1308 @@ +/* +* Copyright 2016 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 "dm_services.h" +#include "dc.h" + +#include "dcn201/dcn201_init.h" +#include "dml/dcn20/dcn20_fpu.h" +#include "resource.h" +#include "include/irq_service_interface.h" +#include "dcn201_resource.h" + +#include "dcn20/dcn20_resource.h" + +#include "dcn10/dcn10_hubp.h" +#include "dcn10/dcn10_ipp.h" +#include "dcn201/dcn201_mpc.h" +#include "dcn201/dcn201_hubp.h" +#include "irq/dcn201/irq_service_dcn201.h" +#include "dcn201/dcn201_dpp.h" +#include "dcn201/dcn201_hubbub.h" +#include "dcn201/dcn201_dccg.h" +#include "dcn201/dcn201_optc.h" +#include "dcn201/dcn201_hwseq.h" +#include "dce110/dce110_hwseq.h" +#include "dcn201/dcn201_opp.h" +#include "dcn201/dcn201_link_encoder.h" +#include "dcn20/dcn20_stream_encoder.h" +#include "dce/dce_clock_source.h" +#include "dce/dce_audio.h" +#include "dce/dce_hwseq.h" +#include "virtual/virtual_stream_encoder.h" +#include "dce110/dce110_resource.h" +#include "dce/dce_aux.h" +#include "dce/dce_i2c.h" +#include "dcn201/dcn201_hubbub.h" +#include "dcn10/dcn10_resource.h" + +#include "cyan_skillfish_ip_offset.h" + +#include "dcn/dcn_2_0_3_offset.h" +#include "dcn/dcn_2_0_3_sh_mask.h" +#include "dpcs/dpcs_2_0_3_offset.h" +#include "dpcs/dpcs_2_0_3_sh_mask.h" + +#include "mmhub/mmhub_2_0_0_offset.h" +#include "mmhub/mmhub_2_0_0_sh_mask.h" +#include "nbio/nbio_7_4_offset.h" + +#include "reg_helper.h" + +#define MIN_DISP_CLK_KHZ 100000 +#define MIN_DPP_CLK_KHZ 100000 + +static struct _vcs_dpi_ip_params_st dcn201_ip = { + .gpuvm_enable = 0, + .hostvm_enable = 0, + .gpuvm_max_page_table_levels = 4, + .hostvm_max_page_table_levels = 4, + .hostvm_cached_page_table_levels = 0, + .pte_group_size_bytes = 2048, + .rob_buffer_size_kbytes = 168, + .det_buffer_size_kbytes = 164, + .dpte_buffer_size_in_pte_reqs_luma = 84, + .pde_proc_buffer_size_64k_reqs = 48, + .dpp_output_buffer_pixels = 2560, + .opp_output_buffer_lines = 1, + .pixel_chunk_size_kbytes = 8, + .pte_chunk_size_kbytes = 2, + .meta_chunk_size_kbytes = 2, + .writeback_chunk_size_kbytes = 2, + .line_buffer_size_bits = 789504, + .is_line_buffer_bpp_fixed = 0, + .line_buffer_fixed_bpp = 0, + .dcc_supported = true, + .max_line_buffer_lines = 12, + .writeback_luma_buffer_size_kbytes = 12, + .writeback_chroma_buffer_size_kbytes = 8, + .writeback_chroma_line_buffer_width_pixels = 4, + .writeback_max_hscl_ratio = 1, + .writeback_max_vscl_ratio = 1, + .writeback_min_hscl_ratio = 1, + .writeback_min_vscl_ratio = 1, + .writeback_max_hscl_taps = 12, + .writeback_max_vscl_taps = 12, + .writeback_line_buffer_luma_buffer_size = 0, + .writeback_line_buffer_chroma_buffer_size = 9600, + .cursor_buffer_size = 8, + .cursor_chunk_size = 2, + .max_num_otg = 2, + .max_num_dpp = 4, + .max_num_wb = 0, + .max_dchub_pscl_bw_pix_per_clk = 4, + .max_pscl_lb_bw_pix_per_clk = 2, + .max_lb_vscl_bw_pix_per_clk = 4, + .max_vscl_hscl_bw_pix_per_clk = 4, + .max_hscl_ratio = 8, + .max_vscl_ratio = 8, + .hscl_mults = 4, + .vscl_mults = 4, + .max_hscl_taps = 8, + .max_vscl_taps = 8, + .dispclk_ramp_margin_percent = 1, + .underscan_factor = 1.10, + .min_vblank_lines = 30, + .dppclk_delay_subtotal = 77, + .dppclk_delay_scl_lb_only = 16, + .dppclk_delay_scl = 50, + .dppclk_delay_cnvc_formatter = 8, + .dppclk_delay_cnvc_cursor = 6, + .dispclk_delay_subtotal = 87, + .dcfclk_cstate_latency = 10, + .max_inter_dcn_tile_repeaters = 8, + .number_of_cursors = 1, +}; + +static struct _vcs_dpi_soc_bounding_box_st dcn201_soc = { + .clock_limits = { + { + .state = 0, + .dscclk_mhz = 400.0, + .dcfclk_mhz = 1000.0, + .fabricclk_mhz = 200.0, + .dispclk_mhz = 300.0, + .dppclk_mhz = 300.0, + .phyclk_mhz = 810.0, + .socclk_mhz = 1254.0, + .dram_speed_mts = 2000.0, + }, + { + .state = 1, + .dscclk_mhz = 400.0, + .dcfclk_mhz = 1000.0, + .fabricclk_mhz = 250.0, + .dispclk_mhz = 1200.0, + .dppclk_mhz = 1200.0, + .phyclk_mhz = 810.0, + .socclk_mhz = 1254.0, + .dram_speed_mts = 3600.0, + }, + { + .state = 2, + .dscclk_mhz = 400.0, + .dcfclk_mhz = 1000.0, + .fabricclk_mhz = 750.0, + .dispclk_mhz = 1200.0, + .dppclk_mhz = 1200.0, + .phyclk_mhz = 810.0, + .socclk_mhz = 1254.0, + .dram_speed_mts = 6800.0, + }, + { + .state = 3, + .dscclk_mhz = 400.0, + .dcfclk_mhz = 1000.0, + .fabricclk_mhz = 250.0, + .dispclk_mhz = 1200.0, + .dppclk_mhz = 1200.0, + .phyclk_mhz = 810.0, + .socclk_mhz = 1254.0, + .dram_speed_mts = 14000.0, + }, + { + .state = 4, + .dscclk_mhz = 400.0, + .dcfclk_mhz = 1000.0, + .fabricclk_mhz = 750.0, + .dispclk_mhz = 1200.0, + .dppclk_mhz = 1200.0, + .phyclk_mhz = 810.0, + .socclk_mhz = 1254.0, + .dram_speed_mts = 14000.0, + } + }, + .num_states = 4, + .sr_exit_time_us = 9.0, + .sr_enter_plus_exit_time_us = 11.0, + .urgent_latency_us = 4.0, + .urgent_latency_pixel_data_only_us = 4.0, + .urgent_latency_pixel_mixed_with_vm_data_us = 4.0, + .urgent_latency_vm_data_only_us = 4.0, + .urgent_out_of_order_return_per_channel_pixel_only_bytes = 256, + .urgent_out_of_order_return_per_channel_pixel_and_vm_bytes = 256, + .urgent_out_of_order_return_per_channel_vm_only_bytes = 256, + .pct_ideal_dram_sdp_bw_after_urgent_pixel_only = 80.0, + .pct_ideal_dram_sdp_bw_after_urgent_pixel_and_vm = 80.0, + .pct_ideal_dram_sdp_bw_after_urgent_vm_only = 80.0, + .max_avg_sdp_bw_use_normal_percent = 80.0, + .max_avg_dram_bw_use_normal_percent = 69.0, + .writeback_latency_us = 12.0, + .ideal_dram_bw_after_urgent_percent = 80.0, + .max_request_size_bytes = 256, + .dram_channel_width_bytes = 2, + .fabric_datapath_to_dcn_data_return_bytes = 64, + .dcn_downspread_percent = 0.3, + .downspread_percent = 0.3, + .dram_page_open_time_ns = 50.0, + .dram_rw_turnaround_time_ns = 17.5, + .dram_return_buffer_per_channel_bytes = 8192, + .round_trip_ping_latency_dcfclk_cycles = 128, + .urgent_out_of_order_return_per_channel_bytes = 256, + .channel_interleave_bytes = 256, + .num_banks = 8, + .num_chans = 16, + .vmm_page_size_bytes = 4096, + .dram_clock_change_latency_us = 250.0, + .writeback_dram_clock_change_latency_us = 23.0, + .return_bus_width_bytes = 64, + .dispclk_dppclk_vco_speed_mhz = 3000, + .use_urgent_burst_bw = 0, +}; + +enum dcn20_clk_src_array_id { + DCN20_CLK_SRC_PLL0, + DCN20_CLK_SRC_PLL1, + DCN20_CLK_SRC_TOTAL_DCN201 +}; + +/* begin ********************* + * macros to expend register list macro defined in HW object header file */ + +/* DCN */ + +#undef BASE_INNER +#define BASE_INNER(seg) DMU_BASE__INST0_SEG ## seg + +#define BASE(seg) BASE_INNER(seg) + +#define SR(reg_name)\ + .reg_name = BASE(mm ## reg_name ## _BASE_IDX) + \ + mm ## reg_name + +#define SRI(reg_name, block, id)\ + .reg_name = BASE(mm ## block ## id ## _ ## reg_name ## _BASE_IDX) + \ + mm ## block ## id ## _ ## reg_name + +#define SRIR(var_name, reg_name, block, id)\ + .var_name = BASE(mm ## block ## id ## _ ## reg_name ## _BASE_IDX) + \ + mm ## block ## id ## _ ## reg_name + +#define SRII(reg_name, block, id)\ + .reg_name[id] = BASE(mm ## block ## id ## _ ## reg_name ## _BASE_IDX) + \ + mm ## block ## id ## _ ## reg_name + +#define SRI_IX(reg_name, block, id)\ + .reg_name = ix ## block ## id ## _ ## reg_name + +#define DCCG_SRII(reg_name, block, id)\ + .block ## _ ## reg_name[id] = BASE(mm ## block ## id ## _ ## reg_name ## _BASE_IDX) + \ + mm ## block ## id ## _ ## reg_name + +#define VUPDATE_SRII(reg_name, block, id)\ + .reg_name[id] = BASE(mm ## reg_name ## _ ## block ## id ## _BASE_IDX) + \ + mm ## reg_name ## _ ## block ## id + +/* NBIO */ +#define NBIO_BASE_INNER(seg) \ + NBIO_BASE__INST0_SEG ## seg + +#define NBIO_BASE(seg) \ + NBIO_BASE_INNER(seg) + +#define NBIO_SR(reg_name)\ + .reg_name = NBIO_BASE(mm ## reg_name ## _BASE_IDX) + \ + mm ## reg_name + +/* MMHUB */ +#define MMHUB_BASE_INNER(seg) \ + MMHUB_BASE__INST0_SEG ## seg + +#define MMHUB_BASE(seg) \ + MMHUB_BASE_INNER(seg) + +#define MMHUB_SR(reg_name)\ + .reg_name = MMHUB_BASE(mmMM ## reg_name ## _BASE_IDX) + \ + mmMM ## reg_name + +static const struct bios_registers bios_regs = { + NBIO_SR(BIOS_SCRATCH_3), + NBIO_SR(BIOS_SCRATCH_6) +}; + +#define clk_src_regs(index, pllid)\ +[index] = {\ + CS_COMMON_REG_LIST_DCN201(index, pllid),\ +} + +static const struct dce110_clk_src_regs clk_src_regs[] = { + clk_src_regs(0, A), + clk_src_regs(1, B) +}; + +static const struct dce110_clk_src_shift cs_shift = { + CS_COMMON_MASK_SH_LIST_DCN2_0(__SHIFT) +}; + +static const struct dce110_clk_src_mask cs_mask = { + CS_COMMON_MASK_SH_LIST_DCN2_0(_MASK) +}; + +#define audio_regs(id)\ +[id] = {\ + AUD_COMMON_REG_LIST(id)\ +} + +static const struct dce_audio_registers audio_regs[] = { + audio_regs(0), + audio_regs(1), +}; + +#define DCE120_AUD_COMMON_MASK_SH_LIST(mask_sh)\ + SF(AZF0ENDPOINT0_AZALIA_F0_CODEC_ENDPOINT_INDEX, AZALIA_ENDPOINT_REG_INDEX, mask_sh),\ + SF(AZF0ENDPOINT0_AZALIA_F0_CODEC_ENDPOINT_DATA, AZALIA_ENDPOINT_REG_DATA, mask_sh),\ + AUD_COMMON_MASK_SH_LIST_BASE(mask_sh) + +static const struct dce_audio_shift audio_shift = { + DCE120_AUD_COMMON_MASK_SH_LIST(__SHIFT) +}; + +static const struct dce_audio_mask audio_mask = { + DCE120_AUD_COMMON_MASK_SH_LIST(_MASK) +}; + +#define stream_enc_regs(id)\ +[id] = {\ + SE_DCN2_REG_LIST(id)\ +} + +static const struct dcn10_stream_enc_registers stream_enc_regs[] = { + stream_enc_regs(0), + stream_enc_regs(1) +}; + +static const struct dcn10_stream_encoder_shift se_shift = { + SE_COMMON_MASK_SH_LIST_DCN20(__SHIFT) +}; + +static const struct dcn10_stream_encoder_mask se_mask = { + SE_COMMON_MASK_SH_LIST_DCN20(_MASK) +}; + +static const struct dce110_aux_registers_shift aux_shift = { + DCN_AUX_MASK_SH_LIST(__SHIFT) +}; + +static const struct dce110_aux_registers_mask aux_mask = { + DCN_AUX_MASK_SH_LIST(_MASK) +}; + +#define aux_regs(id)\ +[id] = {\ + DCN2_AUX_REG_LIST(id)\ +} + +static const struct dcn10_link_enc_aux_registers link_enc_aux_regs[] = { + aux_regs(0), + aux_regs(1), +}; + +#define hpd_regs(id)\ +[id] = {\ + HPD_REG_LIST(id)\ +} + +static const struct dcn10_link_enc_hpd_registers link_enc_hpd_regs[] = { + hpd_regs(0), + hpd_regs(1), +}; + +#define link_regs(id, phyid)\ +[id] = {\ + LE_DCN_COMMON_REG_LIST(id), \ + UNIPHY_DCN2_REG_LIST(phyid) \ +} + +static const struct dcn10_link_enc_registers link_enc_regs[] = { + link_regs(0, A), + link_regs(1, B), +}; + +#define LINK_ENCODER_MASK_SH_LIST_DCN201(mask_sh)\ + LINK_ENCODER_MASK_SH_LIST_DCN20(mask_sh) + +static const struct dcn10_link_enc_shift le_shift = { + LINK_ENCODER_MASK_SH_LIST_DCN201(__SHIFT) +}; + +static const struct dcn10_link_enc_mask le_mask = { + LINK_ENCODER_MASK_SH_LIST_DCN201(_MASK) +}; + +#define ipp_regs(id)\ +[id] = {\ + IPP_REG_LIST_DCN201(id),\ +} + +static const struct dcn10_ipp_registers ipp_regs[] = { + ipp_regs(0), + ipp_regs(1), + ipp_regs(2), + ipp_regs(3), +}; + +static const struct dcn10_ipp_shift ipp_shift = { + IPP_MASK_SH_LIST_DCN201(__SHIFT) +}; + +static const struct dcn10_ipp_mask ipp_mask = { + IPP_MASK_SH_LIST_DCN201(_MASK) +}; + +#define opp_regs(id)\ +[id] = {\ + OPP_REG_LIST_DCN201(id),\ +} + +static const struct dcn201_opp_registers opp_regs[] = { + opp_regs(0), + opp_regs(1), +}; + +static const struct dcn201_opp_shift opp_shift = { + OPP_MASK_SH_LIST_DCN201(__SHIFT) +}; + +static const struct dcn201_opp_mask opp_mask = { + OPP_MASK_SH_LIST_DCN201(_MASK) +}; + +#define aux_engine_regs(id)\ +[id] = {\ + AUX_COMMON_REG_LIST0(id), \ + .AUX_RESET_MASK = 0 \ +} + +static const struct dce110_aux_registers aux_engine_regs[] = { + aux_engine_regs(0), + aux_engine_regs(1) +}; + +#define tf_regs(id)\ +[id] = {\ + TF_REG_LIST_DCN201(id),\ +} + +static const struct dcn201_dpp_registers tf_regs[] = { + tf_regs(0), + tf_regs(1), + tf_regs(2), + tf_regs(3), +}; + +static const struct dcn201_dpp_shift tf_shift = { + TF_REG_LIST_SH_MASK_DCN201(__SHIFT) +}; + +static const struct dcn201_dpp_mask tf_mask = { + TF_REG_LIST_SH_MASK_DCN201(_MASK) +}; + +static const struct dcn201_mpc_registers mpc_regs = { + MPC_REG_LIST_DCN201(0), + MPC_REG_LIST_DCN201(1), + MPC_REG_LIST_DCN201(2), + MPC_REG_LIST_DCN201(3), + MPC_REG_LIST_DCN201(4), + MPC_OUT_MUX_REG_LIST_DCN201(0), + MPC_OUT_MUX_REG_LIST_DCN201(1), +}; + +static const struct dcn201_mpc_shift mpc_shift = { + MPC_COMMON_MASK_SH_LIST_DCN201(__SHIFT) +}; + +static const struct dcn201_mpc_mask mpc_mask = { + MPC_COMMON_MASK_SH_LIST_DCN201(_MASK) +}; + +#define tg_regs_dcn201(id)\ +[id] = {TG_COMMON_REG_LIST_DCN201(id)} + +static const struct dcn_optc_registers tg_regs[] = { + tg_regs_dcn201(0), + tg_regs_dcn201(1) +}; + +static const struct dcn_optc_shift tg_shift = { + TG_COMMON_MASK_SH_LIST_DCN201(__SHIFT) +}; + +static const struct dcn_optc_mask tg_mask = { + TG_COMMON_MASK_SH_LIST_DCN201(_MASK) +}; + +#define hubp_regsDCN201(id)\ +[id] = {\ + HUBP_REG_LIST_DCN201(id)\ +} + +static const struct dcn201_hubp_registers hubp_regs[] = { + hubp_regsDCN201(0), + hubp_regsDCN201(1), + hubp_regsDCN201(2), + hubp_regsDCN201(3) +}; + +static const struct dcn201_hubp_shift hubp_shift = { + HUBP_MASK_SH_LIST_DCN201(__SHIFT) +}; + +static const struct dcn201_hubp_mask hubp_mask = { + HUBP_MASK_SH_LIST_DCN201(_MASK) +}; + +static const struct dcn_hubbub_registers hubbub_reg = { + HUBBUB_REG_LIST_DCN201(0) +}; + +static const struct dcn_hubbub_shift hubbub_shift = { + HUBBUB_MASK_SH_LIST_DCN201(__SHIFT) +}; + +static const struct dcn_hubbub_mask hubbub_mask = { + HUBBUB_MASK_SH_LIST_DCN201(_MASK) +}; + + +static const struct dccg_registers dccg_regs = { + DCCG_COMMON_REG_LIST_DCN_BASE() +}; + +static const struct dccg_shift dccg_shift = { + DCCG_COMMON_MASK_SH_LIST_DCN_COMMON_BASE(__SHIFT) +}; + +static const struct dccg_mask dccg_mask = { + DCCG_COMMON_MASK_SH_LIST_DCN_COMMON_BASE(_MASK) +}; + +static const struct resource_caps res_cap_dnc201 = { + .num_timing_generator = 2, + .num_opp = 2, + .num_video_plane = 4, + .num_audio = 2, + .num_stream_encoder = 2, + .num_pll = 2, + .num_ddc = 2, +}; + +static const struct dc_plane_cap plane_cap = { + .type = DC_PLANE_TYPE_DCN_UNIVERSAL, + .per_pixel_alpha = true, + + .pixel_format_support = { + .argb8888 = true, + .nv12 = false, + .fp16 = true, + .p010 = false, + }, + + .max_upscale_factor = { + .argb8888 = 16000, + .nv12 = 16000, + .fp16 = 1 + }, + + .max_downscale_factor = { + .argb8888 = 250, + .nv12 = 250, + .fp16 = 250 + }, + 64, + 64 +}; + +static const struct dc_debug_options debug_defaults_drv = { + .disable_dmcu = true, + .force_abm_enable = false, + .timing_trace = false, + .clock_trace = true, + .disable_pplib_clock_request = true, + .pipe_split_policy = MPC_SPLIT_DYNAMIC, + .force_single_disp_pipe_split = false, + .disable_dcc = DCC_ENABLE, + .vsr_support = true, + .performance_trace = false, + .az_endpoint_mute_only = true, + .max_downscale_src_width = 3840, + .disable_pplib_wm_range = true, + .scl_reset_length10 = true, + .sanity_checks = false, + .underflow_assert_delay_us = 0xFFFFFFFF, + .enable_tri_buf = false, + .enable_legacy_fast_update = true, + .using_dml2 = false, +}; + +static void dcn201_dpp_destroy(struct dpp **dpp) +{ + kfree(TO_DCN201_DPP(*dpp)); + *dpp = NULL; +} + +static struct dpp *dcn201_dpp_create( + struct dc_context *ctx, + uint32_t inst) +{ + struct dcn201_dpp *dpp = + kzalloc(sizeof(struct dcn201_dpp), GFP_ATOMIC); + + if (!dpp) + return NULL; + + if (dpp201_construct(dpp, ctx, inst, + &tf_regs[inst], &tf_shift, &tf_mask)) + return &dpp->base; + + kfree(dpp); + return NULL; +} + +static struct input_pixel_processor *dcn201_ipp_create( + struct dc_context *ctx, uint32_t inst) +{ + struct dcn10_ipp *ipp = + kzalloc(sizeof(struct dcn10_ipp), GFP_ATOMIC); + + if (!ipp) { + return NULL; + } + + dcn20_ipp_construct(ipp, ctx, inst, + &ipp_regs[inst], &ipp_shift, &ipp_mask); + return &ipp->base; +} + + +static struct output_pixel_processor *dcn201_opp_create( + struct dc_context *ctx, uint32_t inst) +{ + struct dcn201_opp *opp = + kzalloc(sizeof(struct dcn201_opp), GFP_ATOMIC); + + if (!opp) { + return NULL; + } + + dcn201_opp_construct(opp, ctx, inst, + &opp_regs[inst], &opp_shift, &opp_mask); + return &opp->base; +} + +static struct dce_aux *dcn201_aux_engine_create(struct dc_context *ctx, + uint32_t inst) +{ + struct aux_engine_dce110 *aux_engine = + kzalloc(sizeof(struct aux_engine_dce110), GFP_ATOMIC); + + if (!aux_engine) + return NULL; + + dce110_aux_engine_construct(aux_engine, ctx, inst, + SW_AUX_TIMEOUT_PERIOD_MULTIPLIER * AUX_TIMEOUT_PERIOD, + &aux_engine_regs[inst], + &aux_mask, + &aux_shift, + ctx->dc->caps.extended_aux_timeout_support); + + return &aux_engine->base; +} +#define i2c_inst_regs(id) { I2C_HW_ENGINE_COMMON_REG_LIST(id) } + +static const struct dce_i2c_registers i2c_hw_regs[] = { + i2c_inst_regs(1), + i2c_inst_regs(2), +}; + +static const struct dce_i2c_shift i2c_shifts = { + I2C_COMMON_MASK_SH_LIST_DCN2(__SHIFT) +}; + +static const struct dce_i2c_mask i2c_masks = { + I2C_COMMON_MASK_SH_LIST_DCN2(_MASK) +}; + +static struct dce_i2c_hw *dcn201_i2c_hw_create(struct dc_context *ctx, + uint32_t inst) +{ + struct dce_i2c_hw *dce_i2c_hw = + kzalloc(sizeof(struct dce_i2c_hw), GFP_ATOMIC); + + if (!dce_i2c_hw) + return NULL; + + dcn2_i2c_hw_construct(dce_i2c_hw, ctx, inst, + &i2c_hw_regs[inst], &i2c_shifts, &i2c_masks); + + return dce_i2c_hw; +} + +static struct mpc *dcn201_mpc_create(struct dc_context *ctx, uint32_t num_mpcc) +{ + struct dcn201_mpc *mpc201 = kzalloc(sizeof(struct dcn201_mpc), + GFP_ATOMIC); + + if (!mpc201) + return NULL; + + dcn201_mpc_construct(mpc201, ctx, + &mpc_regs, + &mpc_shift, + &mpc_mask, + num_mpcc); + + return &mpc201->base; +} + +static struct hubbub *dcn201_hubbub_create(struct dc_context *ctx) +{ + struct dcn20_hubbub *hubbub = kzalloc(sizeof(struct dcn20_hubbub), + GFP_ATOMIC); + + if (!hubbub) + return NULL; + + hubbub201_construct(hubbub, ctx, + &hubbub_reg, + &hubbub_shift, + &hubbub_mask); + + return &hubbub->base; +} + +static struct timing_generator *dcn201_timing_generator_create( + struct dc_context *ctx, + uint32_t instance) +{ + struct optc *tgn10 = + kzalloc(sizeof(struct optc), GFP_ATOMIC); + + if (!tgn10) + return NULL; + + tgn10->base.inst = instance; + tgn10->base.ctx = ctx; + + tgn10->tg_regs = &tg_regs[instance]; + tgn10->tg_shift = &tg_shift; + tgn10->tg_mask = &tg_mask; + + dcn201_timing_generator_init(tgn10); + + return &tgn10->base; +} + +static const struct encoder_feature_support link_enc_feature = { + .max_hdmi_deep_color = COLOR_DEPTH_121212, + .max_hdmi_pixel_clock = 600000, + .hdmi_ycbcr420_supported = true, + .dp_ycbcr420_supported = true, + .fec_supported = true, + .flags.bits.IS_HBR2_CAPABLE = true, + .flags.bits.IS_HBR3_CAPABLE = true, + .flags.bits.IS_TPS3_CAPABLE = true, + .flags.bits.IS_TPS4_CAPABLE = true +}; + +static struct link_encoder *dcn201_link_encoder_create( + struct dc_context *ctx, + const struct encoder_init_data *enc_init_data) +{ + struct dcn20_link_encoder *enc20 = + kzalloc(sizeof(struct dcn20_link_encoder), GFP_ATOMIC); + struct dcn10_link_encoder *enc10 = &enc20->enc10; + + if (!enc20) + return NULL; + + dcn201_link_encoder_construct(enc20, + enc_init_data, + &link_enc_feature, + &link_enc_regs[enc_init_data->transmitter], + &link_enc_aux_regs[enc_init_data->channel - 1], + &link_enc_hpd_regs[enc_init_data->hpd_source], + &le_shift, + &le_mask); + + return &enc10->base; +} + +static struct clock_source *dcn201_clock_source_create( + struct dc_context *ctx, + struct dc_bios *bios, + enum clock_source_id id, + const struct dce110_clk_src_regs *regs, + bool dp_clk_src) +{ + struct dce110_clk_src *clk_src = + kzalloc(sizeof(struct dce110_clk_src), GFP_ATOMIC); + + if (!clk_src) + return NULL; + + if (dce112_clk_src_construct(clk_src, ctx, bios, id, + regs, &cs_shift, &cs_mask)) { + clk_src->base.dp_clk_src = dp_clk_src; + return &clk_src->base; + } + kfree(clk_src); + return NULL; +} + +static void read_dce_straps( + struct dc_context *ctx, + struct resource_straps *straps) +{ + generic_reg_get(ctx, mmDC_PINSTRAPS + BASE(mmDC_PINSTRAPS_BASE_IDX), + + FN(DC_PINSTRAPS, DC_PINSTRAPS_AUDIO), &straps->dc_pinstraps_audio); +} + +static struct audio *dcn201_create_audio( + struct dc_context *ctx, unsigned int inst) +{ + return dce_audio_create(ctx, inst, + &audio_regs[inst], &audio_shift, &audio_mask); +} + +static struct stream_encoder *dcn201_stream_encoder_create( + enum engine_id eng_id, + struct dc_context *ctx) +{ + struct dcn10_stream_encoder *enc1 = + kzalloc(sizeof(struct dcn10_stream_encoder), GFP_ATOMIC); + + if (!enc1) + return NULL; + + dcn20_stream_encoder_construct(enc1, ctx, ctx->dc_bios, eng_id, + &stream_enc_regs[eng_id], + &se_shift, &se_mask); + + return &enc1->base; +} + +static const struct dce_hwseq_registers hwseq_reg = { + HWSEQ_DCN201_REG_LIST() +}; + +static const struct dce_hwseq_shift hwseq_shift = { + HWSEQ_DCN201_MASK_SH_LIST(__SHIFT) +}; + +static const struct dce_hwseq_mask hwseq_mask = { + HWSEQ_DCN201_MASK_SH_LIST(_MASK) +}; + +static struct dce_hwseq *dcn201_hwseq_create( + struct dc_context *ctx) +{ + struct dce_hwseq *hws = kzalloc(sizeof(struct dce_hwseq), GFP_ATOMIC); + + if (hws) { + hws->ctx = ctx; + hws->regs = &hwseq_reg; + hws->shifts = &hwseq_shift; + hws->masks = &hwseq_mask; + } + return hws; +} + +static const struct resource_create_funcs res_create_funcs = { + .read_dce_straps = read_dce_straps, + .create_audio = dcn201_create_audio, + .create_stream_encoder = dcn201_stream_encoder_create, + .create_hwseq = dcn201_hwseq_create, +}; + +static void dcn201_clock_source_destroy(struct clock_source **clk_src) +{ + kfree(TO_DCE110_CLK_SRC(*clk_src)); + *clk_src = NULL; +} + +static void dcn201_resource_destruct(struct dcn201_resource_pool *pool) +{ + unsigned int i; + + for (i = 0; i < pool->base.stream_enc_count; i++) { + if (pool->base.stream_enc[i] != NULL) { + kfree(DCN10STRENC_FROM_STRENC(pool->base.stream_enc[i])); + pool->base.stream_enc[i] = NULL; + } + } + + + if (pool->base.mpc != NULL) { + kfree(TO_DCN201_MPC(pool->base.mpc)); + pool->base.mpc = NULL; + } + + if (pool->base.hubbub != NULL) { + kfree(pool->base.hubbub); + pool->base.hubbub = NULL; + } + + for (i = 0; i < pool->base.pipe_count; i++) { + if (pool->base.dpps[i] != NULL) + dcn201_dpp_destroy(&pool->base.dpps[i]); + + if (pool->base.ipps[i] != NULL) + pool->base.ipps[i]->funcs->ipp_destroy(&pool->base.ipps[i]); + + if (pool->base.hubps[i] != NULL) { + kfree(TO_DCN10_HUBP(pool->base.hubps[i])); + pool->base.hubps[i] = NULL; + } + + if (pool->base.irqs != NULL) { + dal_irq_service_destroy(&pool->base.irqs); + } + } + + for (i = 0; i < pool->base.res_cap->num_opp; i++) { + if (pool->base.opps[i] != NULL) + pool->base.opps[i]->funcs->opp_destroy(&pool->base.opps[i]); + } + + for (i = 0; i < pool->base.res_cap->num_timing_generator; i++) { + if (pool->base.timing_generators[i] != NULL) { + kfree(DCN10TG_FROM_TG(pool->base.timing_generators[i])); + pool->base.timing_generators[i] = NULL; + } + } + for (i = 0; i < pool->base.audio_count; i++) { + if (pool->base.audios[i]) + dce_aud_destroy(&pool->base.audios[i]); + } + + for (i = 0; i < pool->base.clk_src_count; i++) { + if (pool->base.clock_sources[i] != NULL) { + dcn201_clock_source_destroy(&pool->base.clock_sources[i]); + pool->base.clock_sources[i] = NULL; + } + } + + if (pool->base.dp_clock_source != NULL) { + dcn201_clock_source_destroy(&pool->base.dp_clock_source); + pool->base.dp_clock_source = NULL; + } + + if (pool->base.dccg != NULL) + dcn_dccg_destroy(&pool->base.dccg); +} + +static struct hubp *dcn201_hubp_create( + struct dc_context *ctx, + uint32_t inst) +{ + struct dcn201_hubp *hubp201 = + kzalloc(sizeof(struct dcn201_hubp), GFP_ATOMIC); + + if (!hubp201) + return NULL; + + if (dcn201_hubp_construct(hubp201, ctx, inst, + &hubp_regs[inst], &hubp_shift, &hubp_mask)) + return &hubp201->base; + + kfree(hubp201); + return NULL; +} + +static struct pipe_ctx *dcn201_acquire_free_pipe_for_layer( + const struct dc_state *cur_ctx, + struct dc_state *new_ctx, + const struct resource_pool *pool, + const struct pipe_ctx *opp_head_pipe) +{ + struct resource_context *res_ctx = &new_ctx->res_ctx; + struct pipe_ctx *head_pipe = resource_get_otg_master_for_stream(res_ctx, opp_head_pipe->stream); + struct pipe_ctx *idle_pipe = resource_find_free_secondary_pipe_legacy(res_ctx, pool, head_pipe); + + if (!head_pipe) + ASSERT(0); + + if (!idle_pipe) + return NULL; + + idle_pipe->stream = head_pipe->stream; + idle_pipe->stream_res.tg = head_pipe->stream_res.tg; + idle_pipe->stream_res.opp = head_pipe->stream_res.opp; + + idle_pipe->plane_res.hubp = pool->hubps[idle_pipe->pipe_idx]; + idle_pipe->plane_res.ipp = pool->ipps[idle_pipe->pipe_idx]; + idle_pipe->plane_res.dpp = pool->dpps[idle_pipe->pipe_idx]; + idle_pipe->plane_res.mpcc_inst = pool->dpps[idle_pipe->pipe_idx]->inst; + + return idle_pipe; +} + +static bool dcn201_get_dcc_compression_cap(const struct dc *dc, + const struct dc_dcc_surface_param *input, + struct dc_surface_dcc_cap *output) +{ + return dc->res_pool->hubbub->funcs->get_dcc_compression_cap( + dc->res_pool->hubbub, + input, + output); +} + +static void dcn201_populate_dml_writeback_from_context(struct dc *dc, + struct resource_context *res_ctx, + display_e2e_pipe_params_st *pipes) +{ + DC_FP_START(); + dcn201_populate_dml_writeback_from_context_fpu(dc, res_ctx, pipes); + DC_FP_END(); +} + +static void dcn201_destroy_resource_pool(struct resource_pool **pool) +{ + struct dcn201_resource_pool *dcn201_pool = TO_DCN201_RES_POOL(*pool); + + dcn201_resource_destruct(dcn201_pool); + kfree(dcn201_pool); + *pool = NULL; +} + +static void dcn201_link_init(struct dc_link *link) +{ + if (link->ctx->dc_bios->integrated_info) + link->dp_ss_off = !link->ctx->dc_bios->integrated_info->dp_ss_control; +} + +static struct dc_cap_funcs cap_funcs = { + .get_dcc_compression_cap = dcn201_get_dcc_compression_cap, +}; + +static struct resource_funcs dcn201_res_pool_funcs = { + .link_init = dcn201_link_init, + .destroy = dcn201_destroy_resource_pool, + .link_enc_create = dcn201_link_encoder_create, + .panel_cntl_create = NULL, + .validate_bandwidth = dcn20_validate_bandwidth, + .populate_dml_pipes = dcn20_populate_dml_pipes_from_context, + .add_stream_to_ctx = dcn20_add_stream_to_ctx, + .add_dsc_to_stream_resource = NULL, + .remove_stream_from_ctx = dcn20_remove_stream_from_ctx, + .acquire_free_pipe_as_secondary_dpp_pipe = dcn201_acquire_free_pipe_for_layer, + .release_pipe = dcn20_release_pipe, + .populate_dml_writeback_from_context = dcn201_populate_dml_writeback_from_context, + .patch_unknown_plane_state = dcn20_patch_unknown_plane_state, + .set_mcif_arb_params = dcn20_set_mcif_arb_params, + .find_first_free_match_stream_enc_for_link = dcn10_find_first_free_match_stream_enc_for_link +}; + +static bool dcn201_resource_construct( + uint8_t num_virtual_links, + struct dc *dc, + struct dcn201_resource_pool *pool) +{ + int i; + struct dc_context *ctx = dc->ctx; + + ctx->dc_bios->regs = &bios_regs; + + pool->base.res_cap = &res_cap_dnc201; + pool->base.funcs = &dcn201_res_pool_funcs; + + /************************************************* + * Resource + asic cap harcoding * + *************************************************/ + pool->base.underlay_pipe_index = NO_UNDERLAY_PIPE; + + pool->base.pipe_count = 4; + pool->base.mpcc_count = 5; + dc->caps.max_downscale_ratio = 200; + dc->caps.i2c_speed_in_khz = 100; + dc->caps.i2c_speed_in_khz_hdcp = 5; /*1.5 w/a applied by default*/ + dc->caps.max_cursor_size = 256; + dc->caps.min_horizontal_blanking_period = 80; + dc->caps.dmdata_alloc_size = 2048; + + dc->caps.max_slave_planes = 1; + dc->caps.max_slave_yuv_planes = 1; + dc->caps.max_slave_rgb_planes = 1; + dc->caps.post_blend_color_processing = true; + dc->caps.force_dp_tps4_for_cp2520 = true; + dc->caps.extended_aux_timeout_support = true; + + /* Color pipeline capabilities */ + dc->caps.color.dpp.dcn_arch = 1; + dc->caps.color.dpp.input_lut_shared = 0; + dc->caps.color.dpp.icsc = 1; + dc->caps.color.dpp.dgam_ram = 1; + dc->caps.color.dpp.dgam_rom_caps.srgb = 1; + dc->caps.color.dpp.dgam_rom_caps.bt2020 = 1; + dc->caps.color.dpp.dgam_rom_caps.gamma2_2 = 0; + dc->caps.color.dpp.dgam_rom_caps.pq = 0; + dc->caps.color.dpp.dgam_rom_caps.hlg = 0; + dc->caps.color.dpp.post_csc = 0; + dc->caps.color.dpp.gamma_corr = 0; + dc->caps.color.dpp.dgam_rom_for_yuv = 1; + + dc->caps.color.dpp.hw_3d_lut = 1; + dc->caps.color.dpp.ogam_ram = 1; + // no OGAM ROM on DCN2 + dc->caps.color.dpp.ogam_rom_caps.srgb = 0; + dc->caps.color.dpp.ogam_rom_caps.bt2020 = 0; + dc->caps.color.dpp.ogam_rom_caps.gamma2_2 = 0; + dc->caps.color.dpp.ogam_rom_caps.pq = 0; + dc->caps.color.dpp.ogam_rom_caps.hlg = 0; + dc->caps.color.dpp.ocsc = 0; + + dc->caps.color.mpc.gamut_remap = 0; + dc->caps.color.mpc.num_3dluts = 0; + dc->caps.color.mpc.shared_3d_lut = 0; + dc->caps.color.mpc.ogam_ram = 1; + dc->caps.color.mpc.ogam_rom_caps.srgb = 0; + dc->caps.color.mpc.ogam_rom_caps.bt2020 = 0; + dc->caps.color.mpc.ogam_rom_caps.gamma2_2 = 0; + dc->caps.color.mpc.ogam_rom_caps.pq = 0; + dc->caps.color.mpc.ogam_rom_caps.hlg = 0; + dc->caps.color.mpc.ocsc = 1; + + dc->debug = debug_defaults_drv; + + /*a0 only, remove later*/ + dc->work_arounds.no_connect_phy_config = true; + dc->work_arounds.dedcn20_305_wa = true; + /************************************************* + * Create resources * + *************************************************/ + + pool->base.clock_sources[DCN20_CLK_SRC_PLL0] = + dcn201_clock_source_create(ctx, ctx->dc_bios, + CLOCK_SOURCE_COMBO_PHY_PLL0, + &clk_src_regs[0], false); + pool->base.clock_sources[DCN20_CLK_SRC_PLL1] = + dcn201_clock_source_create(ctx, ctx->dc_bios, + CLOCK_SOURCE_COMBO_PHY_PLL1, + &clk_src_regs[1], false); + + pool->base.clk_src_count = DCN20_CLK_SRC_TOTAL_DCN201; + + /* todo: not reuse phy_pll registers */ + pool->base.dp_clock_source = + dcn201_clock_source_create(ctx, ctx->dc_bios, + CLOCK_SOURCE_ID_DP_DTO, + &clk_src_regs[0], true); + + for (i = 0; i < pool->base.clk_src_count; i++) { + if (pool->base.clock_sources[i] == NULL) { + dm_error("DC: failed to create clock sources!\n"); + goto create_fail; + } + } + + pool->base.dccg = dccg201_create(ctx, &dccg_regs, &dccg_shift, &dccg_mask); + if (pool->base.dccg == NULL) { + dm_error("DC: failed to create dccg!\n"); + goto create_fail; + } + + dcn201_ip.max_num_otg = pool->base.res_cap->num_timing_generator; + dcn201_ip.max_num_dpp = pool->base.pipe_count; + dml_init_instance(&dc->dml, &dcn201_soc, &dcn201_ip, DML_PROJECT_DCN201); + { + struct irq_service_init_data init_data; + init_data.ctx = dc->ctx; + pool->base.irqs = dal_irq_service_dcn201_create(&init_data); + if (!pool->base.irqs) + goto create_fail; + } + + /* mem input -> ipp -> dpp -> opp -> TG */ + for (i = 0; i < pool->base.pipe_count; i++) { + pool->base.hubps[i] = dcn201_hubp_create(ctx, i); + if (pool->base.hubps[i] == NULL) { + dm_error( + "DC: failed to create memory input!\n"); + goto create_fail; + } + + pool->base.ipps[i] = dcn201_ipp_create(ctx, i); + if (pool->base.ipps[i] == NULL) { + dm_error( + "DC: failed to create input pixel processor!\n"); + goto create_fail; + } + + pool->base.dpps[i] = dcn201_dpp_create(ctx, i); + if (pool->base.dpps[i] == NULL) { + dm_error( + "DC: failed to create dpps!\n"); + goto create_fail; + } + } + + for (i = 0; i < pool->base.res_cap->num_opp; i++) { + pool->base.opps[i] = dcn201_opp_create(ctx, i); + if (pool->base.opps[i] == NULL) { + dm_error( + "DC: failed to create output pixel processor!\n"); + goto create_fail; + } + } + + for (i = 0; i < pool->base.res_cap->num_ddc; i++) { + pool->base.engines[i] = dcn201_aux_engine_create(ctx, i); + if (pool->base.engines[i] == NULL) { + dm_error( + "DC:failed to create aux engine!!\n"); + goto create_fail; + } + pool->base.hw_i2cs[i] = dcn201_i2c_hw_create(ctx, i); + if (pool->base.hw_i2cs[i] == NULL) { + dm_error( + "DC:failed to create hw i2c!!\n"); + goto create_fail; + } + pool->base.sw_i2cs[i] = NULL; + } + + for (i = 0; i < pool->base.res_cap->num_timing_generator; i++) { + pool->base.timing_generators[i] = dcn201_timing_generator_create( + ctx, i); + if (pool->base.timing_generators[i] == NULL) { + dm_error("DC: failed to create tg!\n"); + goto create_fail; + } + } + + pool->base.timing_generator_count = i; + + pool->base.mpc = dcn201_mpc_create(ctx, pool->base.mpcc_count); + if (pool->base.mpc == NULL) { + dm_error("DC: failed to create mpc!\n"); + goto create_fail; + } + + pool->base.hubbub = dcn201_hubbub_create(ctx); + if (pool->base.hubbub == NULL) { + dm_error("DC: failed to create hubbub!\n"); + goto create_fail; + } + + if (!resource_construct(num_virtual_links, dc, &pool->base, + &res_create_funcs)) + goto create_fail; + + dcn201_hw_sequencer_construct(dc); + + dc->caps.max_planes = pool->base.pipe_count; + + for (i = 0; i < dc->caps.max_planes; ++i) + dc->caps.planes[i] = plane_cap; + + dc->cap_funcs = cap_funcs; + + return true; + +create_fail: + + dcn201_resource_destruct(pool); + + return false; +} + +struct resource_pool *dcn201_create_resource_pool( + const struct dc_init_data *init_data, + struct dc *dc) +{ + struct dcn201_resource_pool *pool = + kzalloc(sizeof(struct dcn201_resource_pool), GFP_ATOMIC); + + if (!pool) + return NULL; + + if (dcn201_resource_construct(init_data->num_virtual_links, dc, pool)) + return &pool->base; + + kfree(pool); + return NULL; +} diff --git a/drivers/gpu/drm/amd/display/dc/resource/dcn201/dcn201_resource.h b/drivers/gpu/drm/amd/display/dc/resource/dcn201/dcn201_resource.h new file mode 100644 index 000000000000..e0467d17d4ae --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/resource/dcn201/dcn201_resource.h @@ -0,0 +1,50 @@ +/* +* Copyright 2017 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_RESOURCE_DCN201_H__ +#define __DC_RESOURCE_DCN201_H__ + +#include "core_types.h" + +#define RRDPCS_PHY_DP_TX_PSTATE_POWER_UP 0x00000000 +#define RRDPCS_PHY_DP_TX_PSTATE_HOLD 0x00000001 +#define RRDPCS_PHY_DP_TX_PSTATE_HOLD_OFF 0x00000002 +#define RRDPCS_PHY_DP_TX_PSTATE_POWER_DOWN 0x00000003 + +#define TO_DCN201_RES_POOL(pool)\ + container_of(pool, struct dcn201_resource_pool, base) + +struct dc; +struct resource_pool; +struct _vcs_dpi_display_pipe_params_st; + +struct dcn201_resource_pool { + struct resource_pool base; +}; +struct resource_pool *dcn201_create_resource_pool( + const struct dc_init_data *init_data, + struct dc *dc); + +#endif /* __DC_RESOURCE_DCN201_H__ */ diff --git a/drivers/gpu/drm/amd/display/dc/resource/dcn21/dcn21_resource.c b/drivers/gpu/drm/amd/display/dc/resource/dcn21/dcn21_resource.c new file mode 100644 index 000000000000..c07da45e1e2c --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/resource/dcn21/dcn21_resource.c @@ -0,0 +1,1745 @@ +/* +* Copyright 2018 Advanced Micro Devices, Inc. + * Copyright 2019 Raptor Engineering, LLC + * + * 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 + +#include "dm_services.h" +#include "dc.h" + +#include "dcn21/dcn21_init.h" + +#include "resource.h" +#include "include/irq_service_interface.h" +#include "dcn20/dcn20_resource.h" +#include "dcn21/dcn21_resource.h" + +#include "dml/dcn20/dcn20_fpu.h" + +#include "clk_mgr.h" +#include "dcn10/dcn10_hubp.h" +#include "dcn10/dcn10_ipp.h" +#include "dcn20/dcn20_hubbub.h" +#include "dcn20/dcn20_mpc.h" +#include "dcn20/dcn20_hubp.h" +#include "dcn21/dcn21_hubp.h" +#include "irq/dcn21/irq_service_dcn21.h" +#include "dcn20/dcn20_dpp.h" +#include "dcn20/dcn20_optc.h" +#include "dcn21/dcn21_hwseq.h" +#include "dce110/dce110_hwseq.h" +#include "dcn20/dcn20_opp.h" +#include "dcn20/dcn20_dsc.h" +#include "dcn21/dcn21_link_encoder.h" +#include "dcn20/dcn20_stream_encoder.h" +#include "dce/dce_clock_source.h" +#include "dce/dce_audio.h" +#include "dce/dce_hwseq.h" +#include "virtual/virtual_stream_encoder.h" +#include "dml/display_mode_vba.h" +#include "dcn20/dcn20_dccg.h" +#include "dcn21/dcn21_dccg.h" +#include "dcn21/dcn21_hubbub.h" +#include "dcn10/dcn10_resource.h" +#include "dce/dce_panel_cntl.h" + +#include "dcn20/dcn20_dwb.h" +#include "dcn20/dcn20_mmhubbub.h" +#include "dpcs/dpcs_2_1_0_offset.h" +#include "dpcs/dpcs_2_1_0_sh_mask.h" + +#include "renoir_ip_offset.h" +#include "dcn/dcn_2_1_0_offset.h" +#include "dcn/dcn_2_1_0_sh_mask.h" + +#include "nbio/nbio_7_0_offset.h" + +#include "mmhub/mmhub_2_0_0_offset.h" +#include "mmhub/mmhub_2_0_0_sh_mask.h" + +#include "reg_helper.h" +#include "dce/dce_abm.h" +#include "dce/dce_dmcu.h" +#include "dce/dce_aux.h" +#include "dce/dce_i2c.h" +#include "dcn21_resource.h" +#include "vm_helper.h" +#include "dcn20/dcn20_vmid.h" +#include "dce/dmub_psr.h" +#include "dce/dmub_abm.h" + +/* begin ********************* + * macros to expend register list macro defined in HW object header file */ + +/* DCN */ +#define BASE_INNER(seg) DMU_BASE__INST0_SEG ## seg + +#define BASE(seg) BASE_INNER(seg) + +#define SR(reg_name)\ + .reg_name = BASE(mm ## reg_name ## _BASE_IDX) + \ + mm ## reg_name + +#define SRI(reg_name, block, id)\ + .reg_name = BASE(mm ## block ## id ## _ ## reg_name ## _BASE_IDX) + \ + mm ## block ## id ## _ ## reg_name + +#define SRIR(var_name, reg_name, block, id)\ + .var_name = BASE(mm ## block ## id ## _ ## reg_name ## _BASE_IDX) + \ + mm ## block ## id ## _ ## reg_name + +#define SRII(reg_name, block, id)\ + .reg_name[id] = BASE(mm ## block ## id ## _ ## reg_name ## _BASE_IDX) + \ + mm ## block ## id ## _ ## reg_name + +#define DCCG_SRII(reg_name, block, id)\ + .block ## _ ## reg_name[id] = BASE(mm ## block ## id ## _ ## reg_name ## _BASE_IDX) + \ + mm ## block ## id ## _ ## reg_name + +#define VUPDATE_SRII(reg_name, block, id)\ + .reg_name[id] = BASE(mm ## reg_name ## _ ## block ## id ## _BASE_IDX) + \ + mm ## reg_name ## _ ## block ## id + +/* NBIO */ +#define NBIO_BASE_INNER(seg) \ + NBIF0_BASE__INST0_SEG ## seg + +#define NBIO_BASE(seg) \ + NBIO_BASE_INNER(seg) + +#define NBIO_SR(reg_name)\ + .reg_name = NBIO_BASE(mm ## reg_name ## _BASE_IDX) + \ + mm ## reg_name + +/* MMHUB */ +#define MMHUB_BASE_INNER(seg) \ + MMHUB_BASE__INST0_SEG ## seg + +#define MMHUB_BASE(seg) \ + MMHUB_BASE_INNER(seg) + +#define MMHUB_SR(reg_name)\ + .reg_name = MMHUB_BASE(mmMM ## reg_name ## _BASE_IDX) + \ + mmMM ## reg_name + +#define clk_src_regs(index, pllid)\ +[index] = {\ + CS_COMMON_REG_LIST_DCN2_1(index, pllid),\ +} + +static const struct dce110_clk_src_regs clk_src_regs[] = { + clk_src_regs(0, A), + clk_src_regs(1, B), + clk_src_regs(2, C), + clk_src_regs(3, D), + clk_src_regs(4, E), +}; + +static const struct dce110_clk_src_shift cs_shift = { + CS_COMMON_MASK_SH_LIST_DCN2_0(__SHIFT) +}; + +static const struct dce110_clk_src_mask cs_mask = { + CS_COMMON_MASK_SH_LIST_DCN2_0(_MASK) +}; + +static const struct bios_registers bios_regs = { + NBIO_SR(BIOS_SCRATCH_3), + NBIO_SR(BIOS_SCRATCH_6) +}; + +static const struct dce_dmcu_registers dmcu_regs = { + DMCU_DCN20_REG_LIST() +}; + +static const struct dce_dmcu_shift dmcu_shift = { + DMCU_MASK_SH_LIST_DCN10(__SHIFT) +}; + +static const struct dce_dmcu_mask dmcu_mask = { + DMCU_MASK_SH_LIST_DCN10(_MASK) +}; + +static const struct dce_abm_registers abm_regs = { + ABM_DCN20_REG_LIST() +}; + +static const struct dce_abm_shift abm_shift = { + ABM_MASK_SH_LIST_DCN20(__SHIFT) +}; + +static const struct dce_abm_mask abm_mask = { + ABM_MASK_SH_LIST_DCN20(_MASK) +}; + +#define audio_regs(id)\ +[id] = {\ + AUD_COMMON_REG_LIST(id)\ +} + +static const struct dce_audio_registers audio_regs[] = { + audio_regs(0), + audio_regs(1), + audio_regs(2), + audio_regs(3), + audio_regs(4), + audio_regs(5), +}; + +#define DCE120_AUD_COMMON_MASK_SH_LIST(mask_sh)\ + SF(AZF0ENDPOINT0_AZALIA_F0_CODEC_ENDPOINT_INDEX, AZALIA_ENDPOINT_REG_INDEX, mask_sh),\ + SF(AZF0ENDPOINT0_AZALIA_F0_CODEC_ENDPOINT_DATA, AZALIA_ENDPOINT_REG_DATA, mask_sh),\ + AUD_COMMON_MASK_SH_LIST_BASE(mask_sh) + +static const struct dce_audio_shift audio_shift = { + DCE120_AUD_COMMON_MASK_SH_LIST(__SHIFT) +}; + +static const struct dce_audio_mask audio_mask = { + DCE120_AUD_COMMON_MASK_SH_LIST(_MASK) +}; + +static const struct dccg_registers dccg_regs = { + DCCG_COMMON_REG_LIST_DCN_BASE() +}; + +static const struct dccg_shift dccg_shift = { + DCCG_MASK_SH_LIST_DCN2_1(__SHIFT) +}; + +static const struct dccg_mask dccg_mask = { + DCCG_MASK_SH_LIST_DCN2_1(_MASK) +}; + +#define opp_regs(id)\ +[id] = {\ + OPP_REG_LIST_DCN20(id),\ +} + +static const struct dcn20_opp_registers opp_regs[] = { + opp_regs(0), + opp_regs(1), + opp_regs(2), + opp_regs(3), + opp_regs(4), + opp_regs(5), +}; + +static const struct dcn20_opp_shift opp_shift = { + OPP_MASK_SH_LIST_DCN20(__SHIFT) +}; + +static const struct dcn20_opp_mask opp_mask = { + OPP_MASK_SH_LIST_DCN20(_MASK) +}; + +#define tg_regs(id)\ +[id] = {TG_COMMON_REG_LIST_DCN2_0(id)} + +static const struct dcn_optc_registers tg_regs[] = { + tg_regs(0), + tg_regs(1), + tg_regs(2), + tg_regs(3) +}; + +static const struct dcn_optc_shift tg_shift = { + TG_COMMON_MASK_SH_LIST_DCN2_0(__SHIFT) +}; + +static const struct dcn_optc_mask tg_mask = { + TG_COMMON_MASK_SH_LIST_DCN2_0(_MASK) +}; + +static const struct dcn20_mpc_registers mpc_regs = { + MPC_REG_LIST_DCN2_0(0), + MPC_REG_LIST_DCN2_0(1), + MPC_REG_LIST_DCN2_0(2), + MPC_REG_LIST_DCN2_0(3), + MPC_REG_LIST_DCN2_0(4), + MPC_REG_LIST_DCN2_0(5), + MPC_OUT_MUX_REG_LIST_DCN2_0(0), + MPC_OUT_MUX_REG_LIST_DCN2_0(1), + MPC_OUT_MUX_REG_LIST_DCN2_0(2), + MPC_OUT_MUX_REG_LIST_DCN2_0(3), + MPC_DBG_REG_LIST_DCN2_0() +}; + +static const struct dcn20_mpc_shift mpc_shift = { + MPC_COMMON_MASK_SH_LIST_DCN2_0(__SHIFT), + MPC_DEBUG_REG_LIST_SH_DCN20 +}; + +static const struct dcn20_mpc_mask mpc_mask = { + MPC_COMMON_MASK_SH_LIST_DCN2_0(_MASK), + MPC_DEBUG_REG_LIST_MASK_DCN20 +}; + +#define hubp_regs(id)\ +[id] = {\ + HUBP_REG_LIST_DCN21(id)\ +} + +static const struct dcn_hubp2_registers hubp_regs[] = { + hubp_regs(0), + hubp_regs(1), + hubp_regs(2), + hubp_regs(3) +}; + +static const struct dcn_hubp2_shift hubp_shift = { + HUBP_MASK_SH_LIST_DCN21(__SHIFT) +}; + +static const struct dcn_hubp2_mask hubp_mask = { + HUBP_MASK_SH_LIST_DCN21(_MASK) +}; + +static const struct dcn_hubbub_registers hubbub_reg = { + HUBBUB_REG_LIST_DCN21() +}; + +static const struct dcn_hubbub_shift hubbub_shift = { + HUBBUB_MASK_SH_LIST_DCN21(__SHIFT) +}; + +static const struct dcn_hubbub_mask hubbub_mask = { + HUBBUB_MASK_SH_LIST_DCN21(_MASK) +}; + + +#define vmid_regs(id)\ +[id] = {\ + DCN20_VMID_REG_LIST(id)\ +} + +static const struct dcn_vmid_registers vmid_regs[] = { + vmid_regs(0), + vmid_regs(1), + vmid_regs(2), + vmid_regs(3), + vmid_regs(4), + vmid_regs(5), + vmid_regs(6), + vmid_regs(7), + vmid_regs(8), + vmid_regs(9), + vmid_regs(10), + vmid_regs(11), + vmid_regs(12), + vmid_regs(13), + vmid_regs(14), + vmid_regs(15) +}; + +static const struct dcn20_vmid_shift vmid_shifts = { + DCN20_VMID_MASK_SH_LIST(__SHIFT) +}; + +static const struct dcn20_vmid_mask vmid_masks = { + DCN20_VMID_MASK_SH_LIST(_MASK) +}; + +#define dsc_regsDCN20(id)\ +[id] = {\ + DSC_REG_LIST_DCN20(id)\ +} + +static const struct dcn20_dsc_registers dsc_regs[] = { + dsc_regsDCN20(0), + dsc_regsDCN20(1), + dsc_regsDCN20(2), + dsc_regsDCN20(3), + dsc_regsDCN20(4), + dsc_regsDCN20(5) +}; + +static const struct dcn20_dsc_shift dsc_shift = { + DSC_REG_LIST_SH_MASK_DCN20(__SHIFT) +}; + +static const struct dcn20_dsc_mask dsc_mask = { + DSC_REG_LIST_SH_MASK_DCN20(_MASK) +}; + +#define ipp_regs(id)\ +[id] = {\ + IPP_REG_LIST_DCN20(id),\ +} + +static const struct dcn10_ipp_registers ipp_regs[] = { + ipp_regs(0), + ipp_regs(1), + ipp_regs(2), + ipp_regs(3), +}; + +static const struct dcn10_ipp_shift ipp_shift = { + IPP_MASK_SH_LIST_DCN20(__SHIFT) +}; + +static const struct dcn10_ipp_mask ipp_mask = { + IPP_MASK_SH_LIST_DCN20(_MASK), +}; + +#define opp_regs(id)\ +[id] = {\ + OPP_REG_LIST_DCN20(id),\ +} + + +#define aux_engine_regs(id)\ +[id] = {\ + AUX_COMMON_REG_LIST0(id), \ + .AUXN_IMPCAL = 0, \ + .AUXP_IMPCAL = 0, \ + .AUX_RESET_MASK = DP_AUX0_AUX_CONTROL__AUX_RESET_MASK, \ +} + +static const struct dce110_aux_registers aux_engine_regs[] = { + aux_engine_regs(0), + aux_engine_regs(1), + aux_engine_regs(2), + aux_engine_regs(3), + aux_engine_regs(4), +}; + +#define tf_regs(id)\ +[id] = {\ + TF_REG_LIST_DCN20(id),\ + TF_REG_LIST_DCN20_COMMON_APPEND(id),\ +} + +static const struct dcn2_dpp_registers tf_regs[] = { + tf_regs(0), + tf_regs(1), + tf_regs(2), + tf_regs(3), +}; + +static const struct dcn2_dpp_shift tf_shift = { + TF_REG_LIST_SH_MASK_DCN20(__SHIFT), + TF_DEBUG_REG_LIST_SH_DCN20 +}; + +static const struct dcn2_dpp_mask tf_mask = { + TF_REG_LIST_SH_MASK_DCN20(_MASK), + TF_DEBUG_REG_LIST_MASK_DCN20 +}; + +#define stream_enc_regs(id)\ +[id] = {\ + SE_DCN2_REG_LIST(id)\ +} + +static const struct dcn10_stream_enc_registers stream_enc_regs[] = { + stream_enc_regs(0), + stream_enc_regs(1), + stream_enc_regs(2), + stream_enc_regs(3), + stream_enc_regs(4), +}; + +static const struct dce110_aux_registers_shift aux_shift = { + DCN_AUX_MASK_SH_LIST(__SHIFT) +}; + +static const struct dce110_aux_registers_mask aux_mask = { + DCN_AUX_MASK_SH_LIST(_MASK) +}; + +static const struct dcn10_stream_encoder_shift se_shift = { + SE_COMMON_MASK_SH_LIST_DCN20(__SHIFT) +}; + +static const struct dcn10_stream_encoder_mask se_mask = { + SE_COMMON_MASK_SH_LIST_DCN20(_MASK) +}; + +static void dcn21_pp_smu_destroy(struct pp_smu_funcs **pp_smu); + +static struct input_pixel_processor *dcn21_ipp_create( + struct dc_context *ctx, uint32_t inst) +{ + struct dcn10_ipp *ipp = + kzalloc(sizeof(struct dcn10_ipp), GFP_KERNEL); + + if (!ipp) { + BREAK_TO_DEBUGGER(); + return NULL; + } + + dcn20_ipp_construct(ipp, ctx, inst, + &ipp_regs[inst], &ipp_shift, &ipp_mask); + return &ipp->base; +} + +static struct dpp *dcn21_dpp_create( + struct dc_context *ctx, + uint32_t inst) +{ + struct dcn20_dpp *dpp = + kzalloc(sizeof(struct dcn20_dpp), GFP_KERNEL); + + if (!dpp) + return NULL; + + if (dpp2_construct(dpp, ctx, inst, + &tf_regs[inst], &tf_shift, &tf_mask)) + return &dpp->base; + + BREAK_TO_DEBUGGER(); + kfree(dpp); + return NULL; +} + +static struct dce_aux *dcn21_aux_engine_create( + struct dc_context *ctx, + uint32_t inst) +{ + struct aux_engine_dce110 *aux_engine = + kzalloc(sizeof(struct aux_engine_dce110), GFP_KERNEL); + + if (!aux_engine) + return NULL; + + dce110_aux_engine_construct(aux_engine, ctx, inst, + SW_AUX_TIMEOUT_PERIOD_MULTIPLIER * AUX_TIMEOUT_PERIOD, + &aux_engine_regs[inst], + &aux_mask, + &aux_shift, + ctx->dc->caps.extended_aux_timeout_support); + + return &aux_engine->base; +} + +#define i2c_inst_regs(id) { I2C_HW_ENGINE_COMMON_REG_LIST(id) } + +static const struct dce_i2c_registers i2c_hw_regs[] = { + i2c_inst_regs(1), + i2c_inst_regs(2), + i2c_inst_regs(3), + i2c_inst_regs(4), + i2c_inst_regs(5), +}; + +static const struct dce_i2c_shift i2c_shifts = { + I2C_COMMON_MASK_SH_LIST_DCN2(__SHIFT) +}; + +static const struct dce_i2c_mask i2c_masks = { + I2C_COMMON_MASK_SH_LIST_DCN2(_MASK) +}; + +static struct dce_i2c_hw *dcn21_i2c_hw_create(struct dc_context *ctx, + uint32_t inst) +{ + struct dce_i2c_hw *dce_i2c_hw = + kzalloc(sizeof(struct dce_i2c_hw), GFP_KERNEL); + + if (!dce_i2c_hw) + return NULL; + + dcn2_i2c_hw_construct(dce_i2c_hw, ctx, inst, + &i2c_hw_regs[inst], &i2c_shifts, &i2c_masks); + + return dce_i2c_hw; +} + +static const struct resource_caps res_cap_rn = { + .num_timing_generator = 4, + .num_opp = 4, + .num_video_plane = 4, + .num_audio = 4, // 4 audio endpoints. 4 audio streams + .num_stream_encoder = 5, + .num_pll = 5, // maybe 3 because the last two used for USB-c + .num_dwb = 1, + .num_ddc = 5, + .num_vmid = 16, + .num_dsc = 3, +}; + +#ifdef DIAGS_BUILD +static const struct resource_caps res_cap_rn_FPGA_4pipe = { + .num_timing_generator = 4, + .num_opp = 4, + .num_video_plane = 4, + .num_audio = 7, + .num_stream_encoder = 4, + .num_pll = 4, + .num_dwb = 1, + .num_ddc = 4, + .num_dsc = 0, +}; + +static const struct resource_caps res_cap_rn_FPGA_2pipe_dsc = { + .num_timing_generator = 2, + .num_opp = 2, + .num_video_plane = 2, + .num_audio = 7, + .num_stream_encoder = 2, + .num_pll = 4, + .num_dwb = 1, + .num_ddc = 4, + .num_dsc = 2, +}; +#endif + +static const struct dc_plane_cap plane_cap = { + .type = DC_PLANE_TYPE_DCN_UNIVERSAL, + .per_pixel_alpha = true, + + .pixel_format_support = { + .argb8888 = true, + .nv12 = true, + .fp16 = true, + .p010 = true + }, + + .max_upscale_factor = { + .argb8888 = 16000, + .nv12 = 16000, + .fp16 = 16000 + }, + + .max_downscale_factor = { + .argb8888 = 250, + .nv12 = 250, + .fp16 = 250 + }, + 64, + 64 +}; + +static const struct dc_debug_options debug_defaults_drv = { + .disable_dmcu = false, + .force_abm_enable = false, + .timing_trace = false, + .clock_trace = true, + .disable_pplib_clock_request = true, + .min_disp_clk_khz = 100000, + .pipe_split_policy = MPC_SPLIT_DYNAMIC, + .force_single_disp_pipe_split = false, + .disable_dcc = DCC_ENABLE, + .vsr_support = true, + .performance_trace = false, + .max_downscale_src_width = 4096, + .disable_pplib_wm_range = false, + .scl_reset_length10 = true, + .sanity_checks = true, + .disable_48mhz_pwrdwn = false, + .usbc_combo_phy_reset_wa = true, + .dmub_command_table = true, + .use_max_lb = true, + .enable_legacy_fast_update = true, + .using_dml2 = false, +}; + +static const struct dc_panel_config panel_config_defaults = { + .psr = { + .disable_psr = false, + .disallow_psrsu = false, + .disallow_replay = false, + }, + .ilr = { + .optimize_edp_link_rate = true, + }, +}; + +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 +}; + +static void dcn21_resource_destruct(struct dcn21_resource_pool *pool) +{ + unsigned int i; + + for (i = 0; i < pool->base.stream_enc_count; i++) { + if (pool->base.stream_enc[i] != NULL) { + kfree(DCN10STRENC_FROM_STRENC(pool->base.stream_enc[i])); + pool->base.stream_enc[i] = NULL; + } + } + + for (i = 0; i < pool->base.res_cap->num_dsc; i++) { + if (pool->base.dscs[i] != NULL) + dcn20_dsc_destroy(&pool->base.dscs[i]); + } + + if (pool->base.mpc != NULL) { + kfree(TO_DCN20_MPC(pool->base.mpc)); + pool->base.mpc = NULL; + } + if (pool->base.hubbub != NULL) { + kfree(pool->base.hubbub); + pool->base.hubbub = NULL; + } + for (i = 0; i < pool->base.pipe_count; i++) { + if (pool->base.dpps[i] != NULL) + dcn20_dpp_destroy(&pool->base.dpps[i]); + + if (pool->base.ipps[i] != NULL) + pool->base.ipps[i]->funcs->ipp_destroy(&pool->base.ipps[i]); + + if (pool->base.hubps[i] != NULL) { + kfree(TO_DCN20_HUBP(pool->base.hubps[i])); + pool->base.hubps[i] = NULL; + } + + if (pool->base.irqs != NULL) { + dal_irq_service_destroy(&pool->base.irqs); + } + } + + for (i = 0; i < pool->base.res_cap->num_ddc; i++) { + if (pool->base.engines[i] != NULL) + dce110_engine_destroy(&pool->base.engines[i]); + if (pool->base.hw_i2cs[i] != NULL) { + kfree(pool->base.hw_i2cs[i]); + pool->base.hw_i2cs[i] = NULL; + } + if (pool->base.sw_i2cs[i] != NULL) { + kfree(pool->base.sw_i2cs[i]); + pool->base.sw_i2cs[i] = NULL; + } + } + + for (i = 0; i < pool->base.res_cap->num_opp; i++) { + if (pool->base.opps[i] != NULL) + pool->base.opps[i]->funcs->opp_destroy(&pool->base.opps[i]); + } + + for (i = 0; i < pool->base.res_cap->num_timing_generator; i++) { + if (pool->base.timing_generators[i] != NULL) { + kfree(DCN10TG_FROM_TG(pool->base.timing_generators[i])); + pool->base.timing_generators[i] = NULL; + } + } + + for (i = 0; i < pool->base.res_cap->num_dwb; i++) { + if (pool->base.dwbc[i] != NULL) { + kfree(TO_DCN20_DWBC(pool->base.dwbc[i])); + pool->base.dwbc[i] = NULL; + } + if (pool->base.mcif_wb[i] != NULL) { + kfree(TO_DCN20_MMHUBBUB(pool->base.mcif_wb[i])); + pool->base.mcif_wb[i] = NULL; + } + } + + for (i = 0; i < pool->base.audio_count; i++) { + if (pool->base.audios[i]) + dce_aud_destroy(&pool->base.audios[i]); + } + + for (i = 0; i < pool->base.clk_src_count; i++) { + if (pool->base.clock_sources[i] != NULL) { + dcn20_clock_source_destroy(&pool->base.clock_sources[i]); + pool->base.clock_sources[i] = NULL; + } + } + + if (pool->base.dp_clock_source != NULL) { + dcn20_clock_source_destroy(&pool->base.dp_clock_source); + pool->base.dp_clock_source = NULL; + } + + if (pool->base.abm != NULL) { + if (pool->base.abm->ctx->dc->config.disable_dmcu) + dmub_abm_destroy(&pool->base.abm); + else + dce_abm_destroy(&pool->base.abm); + } + + if (pool->base.dmcu != NULL) + dce_dmcu_destroy(&pool->base.dmcu); + + if (pool->base.psr != NULL) + dmub_psr_destroy(&pool->base.psr); + + if (pool->base.dccg != NULL) + dcn_dccg_destroy(&pool->base.dccg); + + if (pool->base.pp_smu != NULL) + dcn21_pp_smu_destroy(&pool->base.pp_smu); +} + +bool dcn21_fast_validate_bw(struct dc *dc, + struct dc_state *context, + display_e2e_pipe_params_st *pipes, + int *pipe_cnt_out, + int *pipe_split_from, + int *vlevel_out, + bool fast_validate) +{ + bool out = false; + int split[MAX_PIPES] = { 0 }; + int pipe_cnt, i, pipe_idx, vlevel; + + ASSERT(pipes); + if (!pipes) + return false; + + dcn20_merge_pipes_for_validate(dc, context); + + DC_FP_START(); + pipe_cnt = dc->res_pool->funcs->populate_dml_pipes(dc, context, pipes, fast_validate); + DC_FP_END(); + + *pipe_cnt_out = pipe_cnt; + + if (!pipe_cnt) { + out = true; + goto validate_out; + } + /* + * DML favors voltage over p-state, but we're more interested in + * supporting p-state over voltage. We can't support p-state in + * prefetch mode > 0 so try capping the prefetch mode to start. + */ + context->bw_ctx.dml.soc.allow_dram_self_refresh_or_dram_clock_change_in_vblank = + dm_allow_self_refresh_and_mclk_switch; + vlevel = dml_get_voltage_level(&context->bw_ctx.dml, pipes, pipe_cnt); + + if (vlevel > context->bw_ctx.dml.soc.num_states) { + /* + * If mode is unsupported or there's still no p-state support then + * fall back to favoring voltage. + * + * We don't actually support prefetch mode 2, so require that we + * at least support prefetch mode 1. + */ + context->bw_ctx.dml.soc.allow_dram_self_refresh_or_dram_clock_change_in_vblank = + dm_allow_self_refresh; + vlevel = dml_get_voltage_level(&context->bw_ctx.dml, pipes, pipe_cnt); + if (vlevel > context->bw_ctx.dml.soc.num_states) + goto validate_fail; + } + + vlevel = dcn20_validate_apply_pipe_split_flags(dc, context, vlevel, split, NULL); + + for (i = 0, pipe_idx = 0; i < dc->res_pool->pipe_count; i++) { + struct pipe_ctx *pipe = &context->res_ctx.pipe_ctx[i]; + struct pipe_ctx *mpo_pipe = pipe->bottom_pipe; + struct vba_vars_st *vba = &context->bw_ctx.dml.vba; + + if (!pipe->stream) + continue; + + /* We only support full screen mpo with ODM */ + if (vba->ODMCombineEnabled[vba->pipe_plane[pipe_idx]] != dm_odm_combine_mode_disabled + && pipe->plane_state && mpo_pipe + && memcmp(&mpo_pipe->plane_state->clip_rect, + &pipe->stream->src, + sizeof(struct rect)) != 0) { + ASSERT(mpo_pipe->plane_state != pipe->plane_state); + goto validate_fail; + } + pipe_idx++; + } + + /*initialize pipe_just_split_from to invalid idx*/ + for (i = 0; i < MAX_PIPES; i++) + pipe_split_from[i] = -1; + + for (i = 0, pipe_idx = -1; i < dc->res_pool->pipe_count; i++) { + struct pipe_ctx *pipe = &context->res_ctx.pipe_ctx[i]; + struct pipe_ctx *hsplit_pipe = pipe->bottom_pipe; + + if (!pipe->stream || pipe_split_from[i] >= 0) + continue; + + pipe_idx++; + + if (!pipe->top_pipe && !pipe->plane_state && context->bw_ctx.dml.vba.ODMCombineEnabled[pipe_idx]) { + hsplit_pipe = dcn20_find_secondary_pipe(dc, &context->res_ctx, dc->res_pool, pipe); + ASSERT(hsplit_pipe); + if (!dcn20_split_stream_for_odm( + dc, &context->res_ctx, + pipe, hsplit_pipe)) + goto validate_fail; + pipe_split_from[hsplit_pipe->pipe_idx] = pipe_idx; + dcn20_build_mapped_resource(dc, context, pipe->stream); + } + + if (!pipe->plane_state) + continue; + /* Skip 2nd half of already split pipe */ + if (pipe->top_pipe && pipe->plane_state == pipe->top_pipe->plane_state) + continue; + + if (split[i] == 2) { + if (!hsplit_pipe || hsplit_pipe->plane_state != pipe->plane_state) { + /* pipe not split previously needs split */ + hsplit_pipe = dcn20_find_secondary_pipe(dc, &context->res_ctx, dc->res_pool, pipe); + ASSERT(hsplit_pipe); + if (!hsplit_pipe) { + DC_FP_START(); + dcn20_fpu_adjust_dppclk(&context->bw_ctx.dml.vba, vlevel, context->bw_ctx.dml.vba.maxMpcComb, pipe_idx, true); + DC_FP_END(); + continue; + } + if (context->bw_ctx.dml.vba.ODMCombineEnabled[pipe_idx]) { + if (!dcn20_split_stream_for_odm( + dc, &context->res_ctx, + pipe, hsplit_pipe)) + goto validate_fail; + dcn20_build_mapped_resource(dc, context, pipe->stream); + } else { + dcn20_split_stream_for_mpc( + &context->res_ctx, dc->res_pool, + pipe, hsplit_pipe); + resource_build_scaling_params(pipe); + resource_build_scaling_params(hsplit_pipe); + } + pipe_split_from[hsplit_pipe->pipe_idx] = pipe_idx; + } + } else if (hsplit_pipe && hsplit_pipe->plane_state == pipe->plane_state) { + /* merge should already have been done */ + ASSERT(0); + } + } + /* Actual dsc count per stream dsc validation*/ + if (!dcn20_validate_dsc(dc, context)) { + context->bw_ctx.dml.vba.ValidationStatus[context->bw_ctx.dml.vba.soc.num_states] = + DML_FAIL_DSC_VALIDATION_FAILURE; + goto validate_fail; + } + + *vlevel_out = vlevel; + + out = true; + goto validate_out; + +validate_fail: + out = false; + +validate_out: + return out; +} + +/* + * Some of the functions further below use the FPU, so we need to wrap this + * with DC_FP_START()/DC_FP_END(). Use the same approach as for + * dcn20_validate_bandwidth in dcn20_resource.c. + */ +static bool dcn21_validate_bandwidth(struct dc *dc, struct dc_state *context, + bool fast_validate) +{ + bool voltage_supported; + display_e2e_pipe_params_st *pipes; + + pipes = kcalloc(dc->res_pool->pipe_count, sizeof(display_e2e_pipe_params_st), GFP_KERNEL); + if (!pipes) + return false; + + DC_FP_START(); + voltage_supported = dcn21_validate_bandwidth_fp(dc, context, fast_validate, pipes); + DC_FP_END(); + + kfree(pipes); + return voltage_supported; +} + +static void dcn21_destroy_resource_pool(struct resource_pool **pool) +{ + struct dcn21_resource_pool *dcn21_pool = TO_DCN21_RES_POOL(*pool); + + dcn21_resource_destruct(dcn21_pool); + kfree(dcn21_pool); + *pool = NULL; +} + +static struct clock_source *dcn21_clock_source_create( + struct dc_context *ctx, + struct dc_bios *bios, + enum clock_source_id id, + const struct dce110_clk_src_regs *regs, + bool dp_clk_src) +{ + struct dce110_clk_src *clk_src = + kzalloc(sizeof(struct dce110_clk_src), GFP_KERNEL); + + if (!clk_src) + return NULL; + + if (dcn20_clk_src_construct(clk_src, ctx, bios, id, + regs, &cs_shift, &cs_mask)) { + clk_src->base.dp_clk_src = dp_clk_src; + return &clk_src->base; + } + + kfree(clk_src); + BREAK_TO_DEBUGGER(); + return NULL; +} + +static struct hubp *dcn21_hubp_create( + struct dc_context *ctx, + uint32_t inst) +{ + struct dcn21_hubp *hubp21 = + kzalloc(sizeof(struct dcn21_hubp), GFP_KERNEL); + + if (!hubp21) + return NULL; + + if (hubp21_construct(hubp21, ctx, inst, + &hubp_regs[inst], &hubp_shift, &hubp_mask)) + return &hubp21->base; + + BREAK_TO_DEBUGGER(); + kfree(hubp21); + return NULL; +} + +static struct hubbub *dcn21_hubbub_create(struct dc_context *ctx) +{ + int i; + + struct dcn20_hubbub *hubbub = kzalloc(sizeof(struct dcn20_hubbub), + GFP_KERNEL); + + if (!hubbub) + return NULL; + + hubbub21_construct(hubbub, ctx, + &hubbub_reg, + &hubbub_shift, + &hubbub_mask); + + for (i = 0; i < res_cap_rn.num_vmid; i++) { + struct dcn20_vmid *vmid = &hubbub->vmid[i]; + + vmid->ctx = ctx; + + vmid->regs = &vmid_regs[i]; + vmid->shifts = &vmid_shifts; + vmid->masks = &vmid_masks; + } + hubbub->num_vmid = res_cap_rn.num_vmid; + + return &hubbub->base; +} + +static struct output_pixel_processor *dcn21_opp_create(struct dc_context *ctx, + uint32_t inst) +{ + struct dcn20_opp *opp = + kzalloc(sizeof(struct dcn20_opp), GFP_KERNEL); + + if (!opp) { + BREAK_TO_DEBUGGER(); + return NULL; + } + + dcn20_opp_construct(opp, ctx, inst, + &opp_regs[inst], &opp_shift, &opp_mask); + return &opp->base; +} + +static struct timing_generator *dcn21_timing_generator_create(struct dc_context *ctx, + uint32_t instance) +{ + struct optc *tgn10 = + kzalloc(sizeof(struct optc), GFP_KERNEL); + + if (!tgn10) + return NULL; + + tgn10->base.inst = instance; + tgn10->base.ctx = ctx; + + tgn10->tg_regs = &tg_regs[instance]; + tgn10->tg_shift = &tg_shift; + tgn10->tg_mask = &tg_mask; + + dcn20_timing_generator_init(tgn10); + + return &tgn10->base; +} + +static struct mpc *dcn21_mpc_create(struct dc_context *ctx) +{ + struct dcn20_mpc *mpc20 = kzalloc(sizeof(struct dcn20_mpc), + GFP_KERNEL); + + if (!mpc20) + return NULL; + + dcn20_mpc_construct(mpc20, ctx, + &mpc_regs, + &mpc_shift, + &mpc_mask, + 6); + + return &mpc20->base; +} + +static void read_dce_straps( + struct dc_context *ctx, + struct resource_straps *straps) +{ + generic_reg_get(ctx, mmDC_PINSTRAPS + BASE(mmDC_PINSTRAPS_BASE_IDX), + FN(DC_PINSTRAPS, DC_PINSTRAPS_AUDIO), &straps->dc_pinstraps_audio); + +} + + +static struct display_stream_compressor *dcn21_dsc_create(struct dc_context *ctx, + uint32_t inst) +{ + struct dcn20_dsc *dsc = + kzalloc(sizeof(struct dcn20_dsc), GFP_KERNEL); + + if (!dsc) { + BREAK_TO_DEBUGGER(); + return NULL; + } + + dsc2_construct(dsc, ctx, inst, &dsc_regs[inst], &dsc_shift, &dsc_mask); + return &dsc->base; +} + +static struct pp_smu_funcs *dcn21_pp_smu_create(struct dc_context *ctx) +{ + struct pp_smu_funcs *pp_smu = kzalloc(sizeof(*pp_smu), GFP_KERNEL); + + if (!pp_smu) + return pp_smu; + + dm_pp_get_funcs(ctx, pp_smu); + + if (pp_smu->ctx.ver != PP_SMU_VER_RN) + pp_smu = memset(pp_smu, 0, sizeof(struct pp_smu_funcs)); + + + return pp_smu; +} + +static void dcn21_pp_smu_destroy(struct pp_smu_funcs **pp_smu) +{ + if (pp_smu && *pp_smu) { + kfree(*pp_smu); + *pp_smu = NULL; + } +} + +static struct audio *dcn21_create_audio( + struct dc_context *ctx, unsigned int inst) +{ + return dce_audio_create(ctx, inst, + &audio_regs[inst], &audio_shift, &audio_mask); +} + +static struct dc_cap_funcs cap_funcs = { + .get_dcc_compression_cap = dcn20_get_dcc_compression_cap +}; + +static struct stream_encoder *dcn21_stream_encoder_create(enum engine_id eng_id, + struct dc_context *ctx) +{ + struct dcn10_stream_encoder *enc1 = + kzalloc(sizeof(struct dcn10_stream_encoder), GFP_KERNEL); + + if (!enc1) + return NULL; + + dcn20_stream_encoder_construct(enc1, ctx, ctx->dc_bios, eng_id, + &stream_enc_regs[eng_id], + &se_shift, &se_mask); + + return &enc1->base; +} + +static const struct dce_hwseq_registers hwseq_reg = { + HWSEQ_DCN21_REG_LIST() +}; + +static const struct dce_hwseq_shift hwseq_shift = { + HWSEQ_DCN21_MASK_SH_LIST(__SHIFT) +}; + +static const struct dce_hwseq_mask hwseq_mask = { + HWSEQ_DCN21_MASK_SH_LIST(_MASK) +}; + +static struct dce_hwseq *dcn21_hwseq_create( + struct dc_context *ctx) +{ + struct dce_hwseq *hws = kzalloc(sizeof(struct dce_hwseq), GFP_KERNEL); + + if (hws) { + hws->ctx = ctx; + hws->regs = &hwseq_reg; + hws->shifts = &hwseq_shift; + hws->masks = &hwseq_mask; + hws->wa.DEGVIDCN21 = true; + hws->wa.disallow_self_refresh_during_multi_plane_transition = true; + } + return hws; +} + +static const struct resource_create_funcs res_create_funcs = { + .read_dce_straps = read_dce_straps, + .create_audio = dcn21_create_audio, + .create_stream_encoder = dcn21_stream_encoder_create, + .create_hwseq = dcn21_hwseq_create, +}; + +static const struct encoder_feature_support link_enc_feature = { + .max_hdmi_deep_color = COLOR_DEPTH_121212, + .max_hdmi_pixel_clock = 600000, + .hdmi_ycbcr420_supported = true, + .dp_ycbcr420_supported = true, + .fec_supported = true, + .flags.bits.IS_HBR2_CAPABLE = true, + .flags.bits.IS_HBR3_CAPABLE = true, + .flags.bits.IS_TPS3_CAPABLE = true, + .flags.bits.IS_TPS4_CAPABLE = true +}; + + +#define link_regs(id, phyid)\ +[id] = {\ + LE_DCN2_REG_LIST(id), \ + UNIPHY_DCN2_REG_LIST(phyid), \ + DPCS_DCN21_REG_LIST(id), \ + SRI(DP_DPHY_INTERNAL_CTRL, DP, id) \ +} + +static const struct dcn10_link_enc_registers link_enc_regs[] = { + link_regs(0, A), + link_regs(1, B), + link_regs(2, C), + link_regs(3, D), + link_regs(4, E), +}; + +static const struct dce_panel_cntl_registers panel_cntl_regs[] = { + { DCN_PANEL_CNTL_REG_LIST() } +}; + +static const struct dce_panel_cntl_shift panel_cntl_shift = { + DCE_PANEL_CNTL_MASK_SH_LIST(__SHIFT) +}; + +static const struct dce_panel_cntl_mask panel_cntl_mask = { + DCE_PANEL_CNTL_MASK_SH_LIST(_MASK) +}; + +#define aux_regs(id)\ +[id] = {\ + DCN2_AUX_REG_LIST(id)\ +} + +static const struct dcn10_link_enc_aux_registers link_enc_aux_regs[] = { + aux_regs(0), + aux_regs(1), + aux_regs(2), + aux_regs(3), + aux_regs(4) +}; + +#define hpd_regs(id)\ +[id] = {\ + HPD_REG_LIST(id)\ +} + +static const struct dcn10_link_enc_hpd_registers link_enc_hpd_regs[] = { + hpd_regs(0), + hpd_regs(1), + hpd_regs(2), + hpd_regs(3), + hpd_regs(4) +}; + +static const struct dcn10_link_enc_shift le_shift = { + LINK_ENCODER_MASK_SH_LIST_DCN20(__SHIFT),\ + DPCS_DCN21_MASK_SH_LIST(__SHIFT) +}; + +static const struct dcn10_link_enc_mask le_mask = { + LINK_ENCODER_MASK_SH_LIST_DCN20(_MASK),\ + DPCS_DCN21_MASK_SH_LIST(_MASK) +}; + +static int map_transmitter_id_to_phy_instance( + enum transmitter transmitter) +{ + switch (transmitter) { + case TRANSMITTER_UNIPHY_A: + return 0; + break; + case TRANSMITTER_UNIPHY_B: + return 1; + break; + case TRANSMITTER_UNIPHY_C: + return 2; + break; + case TRANSMITTER_UNIPHY_D: + return 3; + break; + case TRANSMITTER_UNIPHY_E: + return 4; + break; + default: + ASSERT(0); + return 0; + } +} + +static struct link_encoder *dcn21_link_encoder_create( + struct dc_context *ctx, + const struct encoder_init_data *enc_init_data) +{ + struct dcn21_link_encoder *enc21 = + kzalloc(sizeof(struct dcn21_link_encoder), GFP_KERNEL); + int link_regs_id; + + if (!enc21) + return NULL; + + link_regs_id = + map_transmitter_id_to_phy_instance(enc_init_data->transmitter); + + dcn21_link_encoder_construct(enc21, + enc_init_data, + &link_enc_feature, + &link_enc_regs[link_regs_id], + &link_enc_aux_regs[enc_init_data->channel - 1], + &link_enc_hpd_regs[enc_init_data->hpd_source], + &le_shift, + &le_mask); + + return &enc21->enc10.base; +} + +static struct panel_cntl *dcn21_panel_cntl_create(const struct panel_cntl_init_data *init_data) +{ + struct dce_panel_cntl *panel_cntl = + kzalloc(sizeof(struct dce_panel_cntl), GFP_KERNEL); + + if (!panel_cntl) + return NULL; + + dce_panel_cntl_construct(panel_cntl, + init_data, + &panel_cntl_regs[init_data->inst], + &panel_cntl_shift, + &panel_cntl_mask); + + return &panel_cntl->base; +} + +static void dcn21_get_panel_config_defaults(struct dc_panel_config *panel_config) +{ + *panel_config = panel_config_defaults; +} + +#define CTX ctx + +#define REG(reg_name) \ + (DCN_BASE.instance[0].segment[mm ## reg_name ## _BASE_IDX] + mm ## reg_name) + +static uint32_t read_pipe_fuses(struct dc_context *ctx) +{ + uint32_t value = REG_READ(CC_DC_PIPE_DIS); + /* RV1 support max 4 pipes */ + value = value & 0xf; + return value; +} + +static enum dc_status dcn21_patch_unknown_plane_state(struct dc_plane_state *plane_state) +{ + if (plane_state->ctx->dc->debug.disable_dcc == DCC_ENABLE) { + plane_state->dcc.enable = 1; + /* align to our worst case block width */ + plane_state->dcc.meta_pitch = ((plane_state->src_rect.width + 1023) / 1024) * 1024; + } + + return dcn20_patch_unknown_plane_state(plane_state); +} + +static const struct resource_funcs dcn21_res_pool_funcs = { + .destroy = dcn21_destroy_resource_pool, + .link_enc_create = dcn21_link_encoder_create, + .panel_cntl_create = dcn21_panel_cntl_create, + .validate_bandwidth = dcn21_validate_bandwidth, + .populate_dml_pipes = dcn21_populate_dml_pipes_from_context, + .add_stream_to_ctx = dcn20_add_stream_to_ctx, + .add_dsc_to_stream_resource = dcn20_add_dsc_to_stream_resource, + .remove_stream_from_ctx = dcn20_remove_stream_from_ctx, + .acquire_free_pipe_as_secondary_dpp_pipe = dcn20_acquire_free_pipe_for_layer, + .release_pipe = dcn20_release_pipe, + .populate_dml_writeback_from_context = dcn20_populate_dml_writeback_from_context, + .patch_unknown_plane_state = dcn21_patch_unknown_plane_state, + .set_mcif_arb_params = dcn20_set_mcif_arb_params, + .find_first_free_match_stream_enc_for_link = dcn10_find_first_free_match_stream_enc_for_link, + .update_bw_bounding_box = dcn21_update_bw_bounding_box, + .get_panel_config_defaults = dcn21_get_panel_config_defaults, +}; + +static bool dcn21_resource_construct( + uint8_t num_virtual_links, + struct dc *dc, + struct dcn21_resource_pool *pool) +{ + int i, j; + struct dc_context *ctx = dc->ctx; + struct irq_service_init_data init_data; + uint32_t pipe_fuses = read_pipe_fuses(ctx); + uint32_t num_pipes; + + ctx->dc_bios->regs = &bios_regs; + + pool->base.res_cap = &res_cap_rn; +#ifdef DIAGS_BUILD + if (IS_FPGA_MAXIMUS_DC(dc->ctx->dce_environment)) + //pool->base.res_cap = &res_cap_nv10_FPGA_2pipe_dsc; + pool->base.res_cap = &res_cap_rn_FPGA_4pipe; +#endif + + pool->base.funcs = &dcn21_res_pool_funcs; + + /************************************************* + * Resource + asic cap harcoding * + *************************************************/ + pool->base.underlay_pipe_index = NO_UNDERLAY_PIPE; + + /* max pipe num for ASIC before check pipe fuses */ + pool->base.pipe_count = pool->base.res_cap->num_timing_generator; + + dc->caps.max_downscale_ratio = 200; + dc->caps.i2c_speed_in_khz = 100; + dc->caps.i2c_speed_in_khz_hdcp = 5; /*1.4 w/a applied by default*/ + dc->caps.max_cursor_size = 256; + dc->caps.min_horizontal_blanking_period = 80; + dc->caps.dmdata_alloc_size = 2048; + + dc->caps.max_slave_planes = 1; + dc->caps.max_slave_yuv_planes = 1; + dc->caps.max_slave_rgb_planes = 1; + dc->caps.post_blend_color_processing = true; + dc->caps.force_dp_tps4_for_cp2520 = true; + dc->caps.extended_aux_timeout_support = true; + dc->caps.dmcub_support = true; + dc->caps.is_apu = true; + + /* Color pipeline capabilities */ + dc->caps.color.dpp.dcn_arch = 1; + dc->caps.color.dpp.input_lut_shared = 0; + dc->caps.color.dpp.icsc = 1; + dc->caps.color.dpp.dgam_ram = 1; + dc->caps.color.dpp.dgam_rom_caps.srgb = 1; + dc->caps.color.dpp.dgam_rom_caps.bt2020 = 1; + dc->caps.color.dpp.dgam_rom_caps.gamma2_2 = 0; + dc->caps.color.dpp.dgam_rom_caps.pq = 0; + dc->caps.color.dpp.dgam_rom_caps.hlg = 0; + dc->caps.color.dpp.post_csc = 0; + dc->caps.color.dpp.gamma_corr = 0; + dc->caps.color.dpp.dgam_rom_for_yuv = 1; + + dc->caps.color.dpp.hw_3d_lut = 1; + dc->caps.color.dpp.ogam_ram = 1; + // no OGAM ROM on DCN2 + dc->caps.color.dpp.ogam_rom_caps.srgb = 0; + dc->caps.color.dpp.ogam_rom_caps.bt2020 = 0; + dc->caps.color.dpp.ogam_rom_caps.gamma2_2 = 0; + dc->caps.color.dpp.ogam_rom_caps.pq = 0; + dc->caps.color.dpp.ogam_rom_caps.hlg = 0; + dc->caps.color.dpp.ocsc = 0; + + dc->caps.color.mpc.gamut_remap = 0; + dc->caps.color.mpc.num_3dluts = 0; + dc->caps.color.mpc.shared_3d_lut = 0; + dc->caps.color.mpc.ogam_ram = 1; + dc->caps.color.mpc.ogam_rom_caps.srgb = 0; + dc->caps.color.mpc.ogam_rom_caps.bt2020 = 0; + dc->caps.color.mpc.ogam_rom_caps.gamma2_2 = 0; + dc->caps.color.mpc.ogam_rom_caps.pq = 0; + dc->caps.color.mpc.ogam_rom_caps.hlg = 0; + dc->caps.color.mpc.ocsc = 1; + + dc->caps.dp_hdmi21_pcon_support = true; + + if (dc->ctx->dce_environment == DCE_ENV_PRODUCTION_DRV) + dc->debug = debug_defaults_drv; + + // Init the vm_helper + if (dc->vm_helper) + vm_helper_init(dc->vm_helper, 16); + + /************************************************* + * Create resources * + *************************************************/ + + pool->base.clock_sources[DCN20_CLK_SRC_PLL0] = + dcn21_clock_source_create(ctx, ctx->dc_bios, + CLOCK_SOURCE_COMBO_PHY_PLL0, + &clk_src_regs[0], false); + pool->base.clock_sources[DCN20_CLK_SRC_PLL1] = + dcn21_clock_source_create(ctx, ctx->dc_bios, + CLOCK_SOURCE_COMBO_PHY_PLL1, + &clk_src_regs[1], false); + pool->base.clock_sources[DCN20_CLK_SRC_PLL2] = + 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; + + /* todo: not reuse phy_pll registers */ + pool->base.dp_clock_source = + dcn21_clock_source_create(ctx, ctx->dc_bios, + CLOCK_SOURCE_ID_DP_DTO, + &clk_src_regs[0], true); + + for (i = 0; i < pool->base.clk_src_count; i++) { + if (pool->base.clock_sources[i] == NULL) { + dm_error("DC: failed to create clock sources!\n"); + BREAK_TO_DEBUGGER(); + goto create_fail; + } + } + + pool->base.dccg = dccg21_create(ctx, &dccg_regs, &dccg_shift, &dccg_mask); + if (pool->base.dccg == NULL) { + dm_error("DC: failed to create dccg!\n"); + BREAK_TO_DEBUGGER(); + goto create_fail; + } + + if (!dc->config.disable_dmcu) { + pool->base.dmcu = dcn21_dmcu_create(ctx, + &dmcu_regs, + &dmcu_shift, + &dmcu_mask); + if (pool->base.dmcu == NULL) { + dm_error("DC: failed to create dmcu!\n"); + BREAK_TO_DEBUGGER(); + goto create_fail; + } + + dc->debug.dmub_command_table = false; + } + + if (dc->config.disable_dmcu) { + pool->base.psr = dmub_psr_create(ctx); + + if (pool->base.psr == NULL) { + dm_error("DC: failed to create psr obj!\n"); + BREAK_TO_DEBUGGER(); + goto create_fail; + } + } + + if (dc->config.disable_dmcu) + pool->base.abm = dmub_abm_create(ctx, + &abm_regs, + &abm_shift, + &abm_mask); + else + pool->base.abm = dce_abm_create(ctx, + &abm_regs, + &abm_shift, + &abm_mask); + + pool->base.pp_smu = dcn21_pp_smu_create(ctx); + + num_pipes = dcn2_1_ip.max_num_dpp; + + for (i = 0; i < dcn2_1_ip.max_num_dpp; i++) + if (pipe_fuses & 1 << i) + num_pipes--; + dcn2_1_ip.max_num_dpp = num_pipes; + dcn2_1_ip.max_num_otg = num_pipes; + + dml_init_instance(&dc->dml, &dcn2_1_soc, &dcn2_1_ip, DML_PROJECT_DCN21); + + init_data.ctx = dc->ctx; + pool->base.irqs = dal_irq_service_dcn21_create(&init_data); + if (!pool->base.irqs) + goto create_fail; + + j = 0; + /* mem input -> ipp -> dpp -> opp -> TG */ + for (i = 0; i < pool->base.pipe_count; i++) { + /* if pipe is disabled, skip instance of HW pipe, + * i.e, skip ASIC register instance + */ + if ((pipe_fuses & (1 << i)) != 0) + continue; + + pool->base.hubps[j] = dcn21_hubp_create(ctx, i); + if (pool->base.hubps[j] == NULL) { + BREAK_TO_DEBUGGER(); + dm_error( + "DC: failed to create memory input!\n"); + goto create_fail; + } + + pool->base.ipps[j] = dcn21_ipp_create(ctx, i); + if (pool->base.ipps[j] == NULL) { + BREAK_TO_DEBUGGER(); + dm_error( + "DC: failed to create input pixel processor!\n"); + goto create_fail; + } + + pool->base.dpps[j] = dcn21_dpp_create(ctx, i); + if (pool->base.dpps[j] == NULL) { + BREAK_TO_DEBUGGER(); + dm_error( + "DC: failed to create dpps!\n"); + goto create_fail; + } + + pool->base.opps[j] = dcn21_opp_create(ctx, i); + if (pool->base.opps[j] == NULL) { + BREAK_TO_DEBUGGER(); + dm_error( + "DC: failed to create output pixel processor!\n"); + goto create_fail; + } + + pool->base.timing_generators[j] = dcn21_timing_generator_create( + ctx, i); + if (pool->base.timing_generators[j] == NULL) { + BREAK_TO_DEBUGGER(); + dm_error("DC: failed to create tg!\n"); + goto create_fail; + } + j++; + } + + for (i = 0; i < pool->base.res_cap->num_ddc; i++) { + pool->base.engines[i] = dcn21_aux_engine_create(ctx, i); + if (pool->base.engines[i] == NULL) { + BREAK_TO_DEBUGGER(); + dm_error( + "DC:failed to create aux engine!!\n"); + goto create_fail; + } + pool->base.hw_i2cs[i] = dcn21_i2c_hw_create(ctx, i); + if (pool->base.hw_i2cs[i] == NULL) { + BREAK_TO_DEBUGGER(); + dm_error( + "DC:failed to create hw i2c!!\n"); + goto create_fail; + } + pool->base.sw_i2cs[i] = NULL; + } + + pool->base.timing_generator_count = j; + pool->base.pipe_count = j; + pool->base.mpcc_count = j; + + pool->base.mpc = dcn21_mpc_create(ctx); + if (pool->base.mpc == NULL) { + BREAK_TO_DEBUGGER(); + dm_error("DC: failed to create mpc!\n"); + goto create_fail; + } + + pool->base.hubbub = dcn21_hubbub_create(ctx); + if (pool->base.hubbub == NULL) { + BREAK_TO_DEBUGGER(); + dm_error("DC: failed to create hubbub!\n"); + goto create_fail; + } + + for (i = 0; i < pool->base.res_cap->num_dsc; i++) { + pool->base.dscs[i] = dcn21_dsc_create(ctx, i); + if (pool->base.dscs[i] == NULL) { + BREAK_TO_DEBUGGER(); + dm_error("DC: failed to create display stream compressor %d!\n", i); + goto create_fail; + } + } + + if (!dcn20_dwbc_create(ctx, &pool->base)) { + BREAK_TO_DEBUGGER(); + dm_error("DC: failed to create dwbc!\n"); + goto create_fail; + } + if (!dcn20_mmhubbub_create(ctx, &pool->base)) { + BREAK_TO_DEBUGGER(); + dm_error("DC: failed to create mcif_wb!\n"); + goto create_fail; + } + + if (!resource_construct(num_virtual_links, dc, &pool->base, + &res_create_funcs)) + goto create_fail; + + dcn21_hw_sequencer_construct(dc); + + dc->caps.max_planes = pool->base.pipe_count; + + for (i = 0; i < dc->caps.max_planes; ++i) + dc->caps.planes[i] = plane_cap; + + dc->cap_funcs = cap_funcs; + + return true; + +create_fail: + + dcn21_resource_destruct(pool); + + return false; +} + +struct resource_pool *dcn21_create_resource_pool( + const struct dc_init_data *init_data, + struct dc *dc) +{ + struct dcn21_resource_pool *pool = + kzalloc(sizeof(struct dcn21_resource_pool), GFP_KERNEL); + + if (!pool) + return NULL; + + if (dcn21_resource_construct(init_data->num_virtual_links, dc, pool)) + return &pool->base; + + BREAK_TO_DEBUGGER(); + kfree(pool); + return NULL; +} diff --git a/drivers/gpu/drm/amd/display/dc/resource/dcn21/dcn21_resource.h b/drivers/gpu/drm/amd/display/dc/resource/dcn21/dcn21_resource.h new file mode 100644 index 000000000000..f7ecc002c2f7 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/resource/dcn21/dcn21_resource.h @@ -0,0 +1,56 @@ +/* + * Copyright 2018 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 _DCN21_RESOURCE_H_ +#define _DCN21_RESOURCE_H_ + +#include "core_types.h" + +#define TO_DCN21_RES_POOL(pool)\ + container_of(pool, struct dcn21_resource_pool, base) + +struct dc; +struct resource_pool; +struct _vcs_dpi_display_pipe_params_st; + +extern struct _vcs_dpi_ip_params_st dcn2_1_ip; +extern struct _vcs_dpi_soc_bounding_box_st dcn2_1_soc; + +struct dcn21_resource_pool { + struct resource_pool base; +}; +struct resource_pool *dcn21_create_resource_pool( + const struct dc_init_data *init_data, + struct dc *dc); +bool dcn21_fast_validate_bw( + struct dc *dc, + struct dc_state *context, + display_e2e_pipe_params_st *pipes, + int *pipe_cnt_out, + int *pipe_split_from, + int *vlevel_out, + bool fast_validate); + +#endif /* _DCN21_RESOURCE_H_ */ diff --git a/drivers/gpu/drm/amd/display/dc/resource/dcn30/dcn30_resource.c b/drivers/gpu/drm/amd/display/dc/resource/dcn30/dcn30_resource.c new file mode 100644 index 000000000000..2b6dcb489b90 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/resource/dcn30/dcn30_resource.c @@ -0,0 +1,2611 @@ +/* + * Copyright 2020 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 "dm_services.h" +#include "dc.h" + +#include "dcn30/dcn30_init.h" + +#include "resource.h" +#include "include/irq_service_interface.h" +#include "dcn20/dcn20_resource.h" + +#include "dcn30_resource.h" + +#include "dcn10/dcn10_ipp.h" +#include "dcn30/dcn30_hubbub.h" +#include "dcn30/dcn30_mpc.h" +#include "dcn30/dcn30_hubp.h" +#include "irq/dcn30/irq_service_dcn30.h" +#include "dcn30/dcn30_dpp.h" +#include "dcn30/dcn30_optc.h" +#include "dcn20/dcn20_hwseq.h" +#include "dcn30/dcn30_hwseq.h" +#include "dce110/dce110_hwseq.h" +#include "dcn30/dcn30_opp.h" +#include "dcn20/dcn20_dsc.h" +#include "dcn30/dcn30_vpg.h" +#include "dcn30/dcn30_afmt.h" +#include "dcn30/dcn30_dio_stream_encoder.h" +#include "dcn30/dcn30_dio_link_encoder.h" +#include "dce/dce_clock_source.h" +#include "dce/dce_audio.h" +#include "dce/dce_hwseq.h" +#include "clk_mgr.h" +#include "virtual/virtual_stream_encoder.h" +#include "dce110/dce110_resource.h" +#include "dml/display_mode_vba.h" +#include "dcn30/dcn30_dccg.h" +#include "dcn10/dcn10_resource.h" +#include "link.h" +#include "dce/dce_panel_cntl.h" + +#include "dcn30/dcn30_dwb.h" +#include "dcn30/dcn30_mmhubbub.h" + +#include "sienna_cichlid_ip_offset.h" +#include "dcn/dcn_3_0_0_offset.h" +#include "dcn/dcn_3_0_0_sh_mask.h" + +#include "nbio/nbio_7_4_offset.h" + +#include "dpcs/dpcs_3_0_0_offset.h" +#include "dpcs/dpcs_3_0_0_sh_mask.h" + +#include "mmhub/mmhub_2_0_0_offset.h" +#include "mmhub/mmhub_2_0_0_sh_mask.h" + +#include "reg_helper.h" +#include "dce/dmub_abm.h" +#include "dce/dmub_psr.h" +#include "dce/dce_aux.h" +#include "dce/dce_i2c.h" + +#include "dml/dcn30/dcn30_fpu.h" +#include "dml/dcn30/display_mode_vba_30.h" +#include "vm_helper.h" +#include "dcn20/dcn20_vmid.h" +#include "amdgpu_socbb.h" +#include "dc_dmub_srv.h" + +#define DC_LOGGER \ + dc->ctx->logger +#define DC_LOGGER_INIT(logger) + +enum dcn30_clk_src_array_id { + DCN30_CLK_SRC_PLL0, + DCN30_CLK_SRC_PLL1, + DCN30_CLK_SRC_PLL2, + DCN30_CLK_SRC_PLL3, + DCN30_CLK_SRC_PLL4, + DCN30_CLK_SRC_PLL5, + DCN30_CLK_SRC_TOTAL +}; + +/* begin ********************* + * macros to expend register list macro defined in HW object header file + */ + +/* DCN */ +#define BASE_INNER(seg) DCN_BASE__INST0_SEG ## seg + +#define BASE(seg) BASE_INNER(seg) + +#define SR(reg_name)\ + .reg_name = BASE(mm ## reg_name ## _BASE_IDX) + \ + mm ## reg_name + +#define SRI(reg_name, block, id)\ + .reg_name = BASE(mm ## block ## id ## _ ## reg_name ## _BASE_IDX) + \ + mm ## block ## id ## _ ## reg_name + +#define SRI2(reg_name, block, id)\ + .reg_name = BASE(mm ## reg_name ## _BASE_IDX) + \ + mm ## reg_name + +#define SRIR(var_name, reg_name, block, id)\ + .var_name = BASE(mm ## block ## id ## _ ## reg_name ## _BASE_IDX) + \ + mm ## block ## id ## _ ## reg_name + +#define SRII(reg_name, block, id)\ + .reg_name[id] = BASE(mm ## block ## id ## _ ## reg_name ## _BASE_IDX) + \ + mm ## block ## id ## _ ## reg_name + +#define SRII_MPC_RMU(reg_name, block, id)\ + .RMU##_##reg_name[id] = BASE(mm ## block ## id ## _ ## reg_name ## _BASE_IDX) + \ + mm ## block ## id ## _ ## reg_name + +#define SRII_DWB(reg_name, temp_name, block, id)\ + .reg_name[id] = BASE(mm ## block ## id ## _ ## temp_name ## _BASE_IDX) + \ + mm ## block ## id ## _ ## temp_name + +#define SF_DWB2(reg_name, block, id, field_name, post_fix) \ + .field_name = reg_name ## __ ## field_name ## post_fix + +#define DCCG_SRII(reg_name, block, id)\ + .block ## _ ## reg_name[id] = BASE(mm ## block ## id ## _ ## reg_name ## _BASE_IDX) + \ + mm ## block ## id ## _ ## reg_name + +#define VUPDATE_SRII(reg_name, block, id)\ + .reg_name[id] = BASE(mm ## reg_name ## _ ## block ## id ## _BASE_IDX) + \ + mm ## reg_name ## _ ## block ## id + +/* NBIO */ +#define NBIO_BASE_INNER(seg) \ + NBIO_BASE__INST0_SEG ## seg + +#define NBIO_BASE(seg) \ + NBIO_BASE_INNER(seg) + +#define NBIO_SR(reg_name)\ + .reg_name = NBIO_BASE(mm ## reg_name ## _BASE_IDX) + \ + mm ## reg_name + +/* MMHUB */ +#define MMHUB_BASE_INNER(seg) \ + MMHUB_BASE__INST0_SEG ## seg + +#define MMHUB_BASE(seg) \ + MMHUB_BASE_INNER(seg) + +#define MMHUB_SR(reg_name)\ + .reg_name = MMHUB_BASE(mmMM ## reg_name ## _BASE_IDX) + \ + mmMM ## reg_name + +/* CLOCK */ +#define CLK_BASE_INNER(seg) \ + CLK_BASE__INST0_SEG ## seg + +#define CLK_BASE(seg) \ + CLK_BASE_INNER(seg) + +#define CLK_SRI(reg_name, block, inst)\ + .reg_name = CLK_BASE(mm ## block ## _ ## inst ## _ ## reg_name ## _BASE_IDX) + \ + mm ## block ## _ ## inst ## _ ## reg_name + + +static const struct bios_registers bios_regs = { + NBIO_SR(BIOS_SCRATCH_3), + NBIO_SR(BIOS_SCRATCH_6) +}; + +#define clk_src_regs(index, pllid)\ +[index] = {\ + CS_COMMON_REG_LIST_DCN2_0(index, pllid),\ +} + +static const struct dce110_clk_src_regs clk_src_regs[] = { + clk_src_regs(0, A), + clk_src_regs(1, B), + clk_src_regs(2, C), + clk_src_regs(3, D), + clk_src_regs(4, E), + clk_src_regs(5, F) +}; + +static const struct dce110_clk_src_shift cs_shift = { + CS_COMMON_MASK_SH_LIST_DCN2_0(__SHIFT) +}; + +static const struct dce110_clk_src_mask cs_mask = { + CS_COMMON_MASK_SH_LIST_DCN2_0(_MASK) +}; + +#define abm_regs(id)\ +[id] = {\ + ABM_DCN30_REG_LIST(id)\ +} + +static const struct dce_abm_registers abm_regs[] = { + abm_regs(0), + abm_regs(1), + abm_regs(2), + abm_regs(3), + abm_regs(4), + abm_regs(5), +}; + +static const struct dce_abm_shift abm_shift = { + ABM_MASK_SH_LIST_DCN30(__SHIFT) +}; + +static const struct dce_abm_mask abm_mask = { + ABM_MASK_SH_LIST_DCN30(_MASK) +}; + + + +#define audio_regs(id)\ +[id] = {\ + AUD_COMMON_REG_LIST(id)\ +} + +static const struct dce_audio_registers audio_regs[] = { + audio_regs(0), + audio_regs(1), + audio_regs(2), + audio_regs(3), + audio_regs(4), + audio_regs(5), + audio_regs(6) +}; + +#define DCE120_AUD_COMMON_MASK_SH_LIST(mask_sh)\ + SF(AZF0ENDPOINT0_AZALIA_F0_CODEC_ENDPOINT_INDEX, AZALIA_ENDPOINT_REG_INDEX, mask_sh),\ + SF(AZF0ENDPOINT0_AZALIA_F0_CODEC_ENDPOINT_DATA, AZALIA_ENDPOINT_REG_DATA, mask_sh),\ + AUD_COMMON_MASK_SH_LIST_BASE(mask_sh) + +static const struct dce_audio_shift audio_shift = { + DCE120_AUD_COMMON_MASK_SH_LIST(__SHIFT) +}; + +static const struct dce_audio_mask audio_mask = { + DCE120_AUD_COMMON_MASK_SH_LIST(_MASK) +}; + +#define vpg_regs(id)\ +[id] = {\ + VPG_DCN3_REG_LIST(id)\ +} + +static const struct dcn30_vpg_registers vpg_regs[] = { + vpg_regs(0), + vpg_regs(1), + vpg_regs(2), + vpg_regs(3), + vpg_regs(4), + vpg_regs(5), + vpg_regs(6), +}; + +static const struct dcn30_vpg_shift vpg_shift = { + DCN3_VPG_MASK_SH_LIST(__SHIFT) +}; + +static const struct dcn30_vpg_mask vpg_mask = { + DCN3_VPG_MASK_SH_LIST(_MASK) +}; + +#define afmt_regs(id)\ +[id] = {\ + AFMT_DCN3_REG_LIST(id)\ +} + +static const struct dcn30_afmt_registers afmt_regs[] = { + afmt_regs(0), + afmt_regs(1), + afmt_regs(2), + afmt_regs(3), + afmt_regs(4), + afmt_regs(5), + afmt_regs(6), +}; + +static const struct dcn30_afmt_shift afmt_shift = { + DCN3_AFMT_MASK_SH_LIST(__SHIFT) +}; + +static const struct dcn30_afmt_mask afmt_mask = { + DCN3_AFMT_MASK_SH_LIST(_MASK) +}; + +#define stream_enc_regs(id)\ +[id] = {\ + SE_DCN3_REG_LIST(id)\ +} + +static const struct dcn10_stream_enc_registers stream_enc_regs[] = { + stream_enc_regs(0), + stream_enc_regs(1), + stream_enc_regs(2), + stream_enc_regs(3), + stream_enc_regs(4), + stream_enc_regs(5) +}; + +static const struct dcn10_stream_encoder_shift se_shift = { + SE_COMMON_MASK_SH_LIST_DCN30(__SHIFT) +}; + +static const struct dcn10_stream_encoder_mask se_mask = { + SE_COMMON_MASK_SH_LIST_DCN30(_MASK) +}; + + +#define aux_regs(id)\ +[id] = {\ + DCN2_AUX_REG_LIST(id)\ +} + +static const struct dcn10_link_enc_aux_registers link_enc_aux_regs[] = { + aux_regs(0), + aux_regs(1), + aux_regs(2), + aux_regs(3), + aux_regs(4), + aux_regs(5) +}; + +#define hpd_regs(id)\ +[id] = {\ + HPD_REG_LIST(id)\ +} + +static const struct dcn10_link_enc_hpd_registers link_enc_hpd_regs[] = { + hpd_regs(0), + hpd_regs(1), + hpd_regs(2), + hpd_regs(3), + hpd_regs(4), + hpd_regs(5) +}; + +#define link_regs(id, phyid)\ +[id] = {\ + LE_DCN3_REG_LIST(id), \ + UNIPHY_DCN2_REG_LIST(phyid), \ + DPCS_DCN2_REG_LIST(id), \ + SRI(DP_DPHY_INTERNAL_CTRL, DP, id) \ +} + +static const struct dce110_aux_registers_shift aux_shift = { + DCN_AUX_MASK_SH_LIST(__SHIFT) +}; + +static const struct dce110_aux_registers_mask aux_mask = { + DCN_AUX_MASK_SH_LIST(_MASK) +}; + +static const struct dcn10_link_enc_registers link_enc_regs[] = { + link_regs(0, A), + link_regs(1, B), + link_regs(2, C), + link_regs(3, D), + link_regs(4, E), + link_regs(5, F) +}; + +static const struct dcn10_link_enc_shift le_shift = { + LINK_ENCODER_MASK_SH_LIST_DCN30(__SHIFT),\ + DPCS_DCN2_MASK_SH_LIST(__SHIFT) +}; + +static const struct dcn10_link_enc_mask le_mask = { + LINK_ENCODER_MASK_SH_LIST_DCN30(_MASK),\ + DPCS_DCN2_MASK_SH_LIST(_MASK) +}; + + +static const struct dce_panel_cntl_registers panel_cntl_regs[] = { + { DCN_PANEL_CNTL_REG_LIST() } +}; + +static const struct dce_panel_cntl_shift panel_cntl_shift = { + DCE_PANEL_CNTL_MASK_SH_LIST(__SHIFT) +}; + +static const struct dce_panel_cntl_mask panel_cntl_mask = { + DCE_PANEL_CNTL_MASK_SH_LIST(_MASK) +}; + +#define dpp_regs(id)\ +[id] = {\ + DPP_REG_LIST_DCN30(id),\ +} + +static const struct dcn3_dpp_registers dpp_regs[] = { + dpp_regs(0), + dpp_regs(1), + dpp_regs(2), + dpp_regs(3), + dpp_regs(4), + dpp_regs(5), +}; + +static const struct dcn3_dpp_shift tf_shift = { + DPP_REG_LIST_SH_MASK_DCN30(__SHIFT) +}; + +static const struct dcn3_dpp_mask tf_mask = { + DPP_REG_LIST_SH_MASK_DCN30(_MASK) +}; + +#define opp_regs(id)\ +[id] = {\ + OPP_REG_LIST_DCN30(id),\ +} + +static const struct dcn20_opp_registers opp_regs[] = { + opp_regs(0), + opp_regs(1), + opp_regs(2), + opp_regs(3), + opp_regs(4), + opp_regs(5) +}; + +static const struct dcn20_opp_shift opp_shift = { + OPP_MASK_SH_LIST_DCN20(__SHIFT) +}; + +static const struct dcn20_opp_mask opp_mask = { + OPP_MASK_SH_LIST_DCN20(_MASK) +}; + +#define aux_engine_regs(id)\ +[id] = {\ + AUX_COMMON_REG_LIST0(id), \ + .AUXN_IMPCAL = 0, \ + .AUXP_IMPCAL = 0, \ + .AUX_RESET_MASK = DP_AUX0_AUX_CONTROL__AUX_RESET_MASK, \ +} + +static const struct dce110_aux_registers aux_engine_regs[] = { + aux_engine_regs(0), + aux_engine_regs(1), + aux_engine_regs(2), + aux_engine_regs(3), + aux_engine_regs(4), + aux_engine_regs(5) +}; + +#define dwbc_regs_dcn3(id)\ +[id] = {\ + DWBC_COMMON_REG_LIST_DCN30(id),\ +} + +static const struct dcn30_dwbc_registers dwbc30_regs[] = { + dwbc_regs_dcn3(0), +}; + +static const struct dcn30_dwbc_shift dwbc30_shift = { + DWBC_COMMON_MASK_SH_LIST_DCN30(__SHIFT) +}; + +static const struct dcn30_dwbc_mask dwbc30_mask = { + DWBC_COMMON_MASK_SH_LIST_DCN30(_MASK) +}; + +#define mcif_wb_regs_dcn3(id)\ +[id] = {\ + MCIF_WB_COMMON_REG_LIST_DCN30(id),\ +} + +static const struct dcn30_mmhubbub_registers mcif_wb30_regs[] = { + mcif_wb_regs_dcn3(0) +}; + +static const struct dcn30_mmhubbub_shift mcif_wb30_shift = { + MCIF_WB_COMMON_MASK_SH_LIST_DCN30(__SHIFT) +}; + +static const struct dcn30_mmhubbub_mask mcif_wb30_mask = { + MCIF_WB_COMMON_MASK_SH_LIST_DCN30(_MASK) +}; + +#define dsc_regsDCN20(id)\ +[id] = {\ + DSC_REG_LIST_DCN20(id)\ +} + +static const struct dcn20_dsc_registers dsc_regs[] = { + dsc_regsDCN20(0), + dsc_regsDCN20(1), + dsc_regsDCN20(2), + dsc_regsDCN20(3), + dsc_regsDCN20(4), + dsc_regsDCN20(5) +}; + +static const struct dcn20_dsc_shift dsc_shift = { + DSC_REG_LIST_SH_MASK_DCN20(__SHIFT) +}; + +static const struct dcn20_dsc_mask dsc_mask = { + DSC_REG_LIST_SH_MASK_DCN20(_MASK) +}; + +static const struct dcn30_mpc_registers mpc_regs = { + MPC_REG_LIST_DCN3_0(0), + MPC_REG_LIST_DCN3_0(1), + MPC_REG_LIST_DCN3_0(2), + MPC_REG_LIST_DCN3_0(3), + MPC_REG_LIST_DCN3_0(4), + MPC_REG_LIST_DCN3_0(5), + MPC_OUT_MUX_REG_LIST_DCN3_0(0), + MPC_OUT_MUX_REG_LIST_DCN3_0(1), + MPC_OUT_MUX_REG_LIST_DCN3_0(2), + MPC_OUT_MUX_REG_LIST_DCN3_0(3), + MPC_OUT_MUX_REG_LIST_DCN3_0(4), + MPC_OUT_MUX_REG_LIST_DCN3_0(5), + MPC_RMU_GLOBAL_REG_LIST_DCN3AG, + MPC_RMU_REG_LIST_DCN3AG(0), + MPC_RMU_REG_LIST_DCN3AG(1), + MPC_RMU_REG_LIST_DCN3AG(2), + MPC_DWB_MUX_REG_LIST_DCN3_0(0), +}; + +static const struct dcn30_mpc_shift mpc_shift = { + MPC_COMMON_MASK_SH_LIST_DCN30(__SHIFT) +}; + +static const struct dcn30_mpc_mask mpc_mask = { + MPC_COMMON_MASK_SH_LIST_DCN30(_MASK) +}; + +#define optc_regs(id)\ +[id] = {OPTC_COMMON_REG_LIST_DCN3_0(id)} + + +static const struct dcn_optc_registers optc_regs[] = { + optc_regs(0), + optc_regs(1), + optc_regs(2), + optc_regs(3), + optc_regs(4), + optc_regs(5) +}; + +static const struct dcn_optc_shift optc_shift = { + OPTC_COMMON_MASK_SH_LIST_DCN30(__SHIFT) +}; + +static const struct dcn_optc_mask optc_mask = { + OPTC_COMMON_MASK_SH_LIST_DCN30(_MASK) +}; + +#define hubp_regs(id)\ +[id] = {\ + HUBP_REG_LIST_DCN30(id)\ +} + +static const struct dcn_hubp2_registers hubp_regs[] = { + hubp_regs(0), + hubp_regs(1), + hubp_regs(2), + hubp_regs(3), + hubp_regs(4), + hubp_regs(5) +}; + +static const struct dcn_hubp2_shift hubp_shift = { + HUBP_MASK_SH_LIST_DCN30(__SHIFT) +}; + +static const struct dcn_hubp2_mask hubp_mask = { + HUBP_MASK_SH_LIST_DCN30(_MASK) +}; + +static const struct dcn_hubbub_registers hubbub_reg = { + HUBBUB_REG_LIST_DCN30(0) +}; + +static const struct dcn_hubbub_shift hubbub_shift = { + HUBBUB_MASK_SH_LIST_DCN30(__SHIFT) +}; + +static const struct dcn_hubbub_mask hubbub_mask = { + HUBBUB_MASK_SH_LIST_DCN30(_MASK) +}; + +static const struct dccg_registers dccg_regs = { + DCCG_REG_LIST_DCN30() +}; + +static const struct dccg_shift dccg_shift = { + DCCG_MASK_SH_LIST_DCN3(__SHIFT) +}; + +static const struct dccg_mask dccg_mask = { + DCCG_MASK_SH_LIST_DCN3(_MASK) +}; + +static const struct dce_hwseq_registers hwseq_reg = { + HWSEQ_DCN30_REG_LIST() +}; + +static const struct dce_hwseq_shift hwseq_shift = { + HWSEQ_DCN30_MASK_SH_LIST(__SHIFT) +}; + +static const struct dce_hwseq_mask hwseq_mask = { + HWSEQ_DCN30_MASK_SH_LIST(_MASK) +}; +#define vmid_regs(id)\ +[id] = {\ + DCN20_VMID_REG_LIST(id)\ +} + +static const struct dcn_vmid_registers vmid_regs[] = { + vmid_regs(0), + vmid_regs(1), + vmid_regs(2), + vmid_regs(3), + vmid_regs(4), + vmid_regs(5), + vmid_regs(6), + vmid_regs(7), + vmid_regs(8), + vmid_regs(9), + vmid_regs(10), + vmid_regs(11), + vmid_regs(12), + vmid_regs(13), + vmid_regs(14), + vmid_regs(15) +}; + +static const struct dcn20_vmid_shift vmid_shifts = { + DCN20_VMID_MASK_SH_LIST(__SHIFT) +}; + +static const struct dcn20_vmid_mask vmid_masks = { + DCN20_VMID_MASK_SH_LIST(_MASK) +}; + +static const struct resource_caps res_cap_dcn3 = { + .num_timing_generator = 6, + .num_opp = 6, + .num_video_plane = 6, + .num_audio = 6, + .num_stream_encoder = 6, + .num_pll = 6, + .num_dwb = 1, + .num_ddc = 6, + .num_vmid = 16, + .num_mpc_3dlut = 3, + .num_dsc = 6, +}; + +static const struct dc_plane_cap plane_cap = { + .type = DC_PLANE_TYPE_DCN_UNIVERSAL, + .per_pixel_alpha = true, + + .pixel_format_support = { + .argb8888 = true, + .nv12 = true, + .fp16 = true, + .p010 = true, + .ayuv = false, + }, + + .max_upscale_factor = { + .argb8888 = 16000, + .nv12 = 16000, + .fp16 = 16000 + }, + + /* 6:1 downscaling ratio: 1000/6 = 166.666 */ + .max_downscale_factor = { + .argb8888 = 167, + .nv12 = 167, + .fp16 = 167 + }, + 16, + 16 +}; + +static const struct dc_debug_options debug_defaults_drv = { + .disable_dmcu = true, //No DMCU on DCN30 + .force_abm_enable = false, + .timing_trace = false, + .clock_trace = true, + .disable_pplib_clock_request = true, + .pipe_split_policy = MPC_SPLIT_DYNAMIC, + .force_single_disp_pipe_split = false, + .disable_dcc = DCC_ENABLE, + .vsr_support = true, + .performance_trace = false, + .max_downscale_src_width = 7680,/*upto 8K*/ + .disable_pplib_wm_range = false, + .scl_reset_length10 = true, + .sanity_checks = false, + .underflow_assert_delay_us = 0xFFFFFFFF, + .dwb_fi_phase = -1, // -1 = disable, + .dmub_command_table = true, + .use_max_lb = true, + .exit_idle_opt_for_cursor_updates = true, + .enable_legacy_fast_update = false, + .using_dml2 = false, +}; + +static const struct dc_panel_config panel_config_defaults = { + .psr = { + .disable_psr = false, + .disallow_psrsu = false, + .disallow_replay = false, + }, +}; + +static void dcn30_dpp_destroy(struct dpp **dpp) +{ + kfree(TO_DCN20_DPP(*dpp)); + *dpp = NULL; +} + +static struct dpp *dcn30_dpp_create( + struct dc_context *ctx, + uint32_t inst) +{ + struct dcn3_dpp *dpp = + kzalloc(sizeof(struct dcn3_dpp), GFP_KERNEL); + + if (!dpp) + return NULL; + + if (dpp3_construct(dpp, ctx, inst, + &dpp_regs[inst], &tf_shift, &tf_mask)) + return &dpp->base; + + BREAK_TO_DEBUGGER(); + kfree(dpp); + return NULL; +} + +static struct output_pixel_processor *dcn30_opp_create( + struct dc_context *ctx, uint32_t inst) +{ + struct dcn20_opp *opp = + kzalloc(sizeof(struct dcn20_opp), GFP_KERNEL); + + if (!opp) { + BREAK_TO_DEBUGGER(); + return NULL; + } + + dcn20_opp_construct(opp, ctx, inst, + &opp_regs[inst], &opp_shift, &opp_mask); + return &opp->base; +} + +static struct dce_aux *dcn30_aux_engine_create( + struct dc_context *ctx, + uint32_t inst) +{ + struct aux_engine_dce110 *aux_engine = + kzalloc(sizeof(struct aux_engine_dce110), GFP_KERNEL); + + if (!aux_engine) + return NULL; + + dce110_aux_engine_construct(aux_engine, ctx, inst, + SW_AUX_TIMEOUT_PERIOD_MULTIPLIER * AUX_TIMEOUT_PERIOD, + &aux_engine_regs[inst], + &aux_mask, + &aux_shift, + ctx->dc->caps.extended_aux_timeout_support); + + return &aux_engine->base; +} + +#define i2c_inst_regs(id) { I2C_HW_ENGINE_COMMON_REG_LIST_DCN30(id) } + +static const struct dce_i2c_registers i2c_hw_regs[] = { + i2c_inst_regs(1), + i2c_inst_regs(2), + i2c_inst_regs(3), + i2c_inst_regs(4), + i2c_inst_regs(5), + i2c_inst_regs(6), +}; + +static const struct dce_i2c_shift i2c_shifts = { + I2C_COMMON_MASK_SH_LIST_DCN30(__SHIFT) +}; + +static const struct dce_i2c_mask i2c_masks = { + I2C_COMMON_MASK_SH_LIST_DCN30(_MASK) +}; + +static struct dce_i2c_hw *dcn30_i2c_hw_create( + struct dc_context *ctx, + uint32_t inst) +{ + struct dce_i2c_hw *dce_i2c_hw = + kzalloc(sizeof(struct dce_i2c_hw), GFP_KERNEL); + + if (!dce_i2c_hw) + return NULL; + + dcn2_i2c_hw_construct(dce_i2c_hw, ctx, inst, + &i2c_hw_regs[inst], &i2c_shifts, &i2c_masks); + + return dce_i2c_hw; +} + +static struct mpc *dcn30_mpc_create( + struct dc_context *ctx, + int num_mpcc, + int num_rmu) +{ + struct dcn30_mpc *mpc30 = kzalloc(sizeof(struct dcn30_mpc), + GFP_KERNEL); + + if (!mpc30) + return NULL; + + dcn30_mpc_construct(mpc30, ctx, + &mpc_regs, + &mpc_shift, + &mpc_mask, + num_mpcc, + num_rmu); + + return &mpc30->base; +} + +static struct hubbub *dcn30_hubbub_create(struct dc_context *ctx) +{ + int i; + + struct dcn20_hubbub *hubbub3 = kzalloc(sizeof(struct dcn20_hubbub), + GFP_KERNEL); + + if (!hubbub3) + return NULL; + + hubbub3_construct(hubbub3, ctx, + &hubbub_reg, + &hubbub_shift, + &hubbub_mask); + + + for (i = 0; i < res_cap_dcn3.num_vmid; i++) { + struct dcn20_vmid *vmid = &hubbub3->vmid[i]; + + vmid->ctx = ctx; + + vmid->regs = &vmid_regs[i]; + vmid->shifts = &vmid_shifts; + vmid->masks = &vmid_masks; + } + + return &hubbub3->base; +} + +static struct timing_generator *dcn30_timing_generator_create( + struct dc_context *ctx, + uint32_t instance) +{ + struct optc *tgn10 = + kzalloc(sizeof(struct optc), GFP_KERNEL); + + if (!tgn10) + return NULL; + + tgn10->base.inst = instance; + tgn10->base.ctx = ctx; + + tgn10->tg_regs = &optc_regs[instance]; + tgn10->tg_shift = &optc_shift; + tgn10->tg_mask = &optc_mask; + + dcn30_timing_generator_init(tgn10); + + return &tgn10->base; +} + +static const struct encoder_feature_support link_enc_feature = { + .max_hdmi_deep_color = COLOR_DEPTH_121212, + .max_hdmi_pixel_clock = 600000, + .hdmi_ycbcr420_supported = true, + .dp_ycbcr420_supported = true, + .fec_supported = true, + .flags.bits.IS_HBR2_CAPABLE = true, + .flags.bits.IS_HBR3_CAPABLE = true, + .flags.bits.IS_TPS3_CAPABLE = true, + .flags.bits.IS_TPS4_CAPABLE = true +}; + +static struct link_encoder *dcn30_link_encoder_create( + struct dc_context *ctx, + const struct encoder_init_data *enc_init_data) +{ + struct dcn20_link_encoder *enc20 = + kzalloc(sizeof(struct dcn20_link_encoder), GFP_KERNEL); + + if (!enc20) + return NULL; + + dcn30_link_encoder_construct(enc20, + enc_init_data, + &link_enc_feature, + &link_enc_regs[enc_init_data->transmitter], + &link_enc_aux_regs[enc_init_data->channel - 1], + &link_enc_hpd_regs[enc_init_data->hpd_source], + &le_shift, + &le_mask); + + return &enc20->enc10.base; +} + +static struct panel_cntl *dcn30_panel_cntl_create(const struct panel_cntl_init_data *init_data) +{ + struct dce_panel_cntl *panel_cntl = + kzalloc(sizeof(struct dce_panel_cntl), GFP_KERNEL); + + if (!panel_cntl) + return NULL; + + dce_panel_cntl_construct(panel_cntl, + init_data, + &panel_cntl_regs[init_data->inst], + &panel_cntl_shift, + &panel_cntl_mask); + + return &panel_cntl->base; +} + +static void read_dce_straps( + struct dc_context *ctx, + struct resource_straps *straps) +{ + generic_reg_get(ctx, mmDC_PINSTRAPS + BASE(mmDC_PINSTRAPS_BASE_IDX), + FN(DC_PINSTRAPS, DC_PINSTRAPS_AUDIO), &straps->dc_pinstraps_audio); + +} + +static struct audio *dcn30_create_audio( + struct dc_context *ctx, unsigned int inst) +{ + return dce_audio_create(ctx, inst, + &audio_regs[inst], &audio_shift, &audio_mask); +} + +static struct vpg *dcn30_vpg_create( + struct dc_context *ctx, + uint32_t inst) +{ + struct dcn30_vpg *vpg3 = kzalloc(sizeof(struct dcn30_vpg), GFP_KERNEL); + + if (!vpg3) + return NULL; + + vpg3_construct(vpg3, ctx, inst, + &vpg_regs[inst], + &vpg_shift, + &vpg_mask); + + return &vpg3->base; +} + +static struct afmt *dcn30_afmt_create( + struct dc_context *ctx, + uint32_t inst) +{ + struct dcn30_afmt *afmt3 = kzalloc(sizeof(struct dcn30_afmt), GFP_KERNEL); + + if (!afmt3) + return NULL; + + afmt3_construct(afmt3, ctx, inst, + &afmt_regs[inst], + &afmt_shift, + &afmt_mask); + + return &afmt3->base; +} + +static struct stream_encoder *dcn30_stream_encoder_create(enum engine_id eng_id, + struct dc_context *ctx) +{ + struct dcn10_stream_encoder *enc1; + struct vpg *vpg; + struct afmt *afmt; + int vpg_inst; + int afmt_inst; + + /* Mapping of VPG, AFMT, DME register blocks to DIO block instance */ + if (eng_id <= ENGINE_ID_DIGF) { + vpg_inst = eng_id; + afmt_inst = eng_id; + } else + return NULL; + + enc1 = kzalloc(sizeof(struct dcn10_stream_encoder), GFP_KERNEL); + vpg = dcn30_vpg_create(ctx, vpg_inst); + afmt = dcn30_afmt_create(ctx, afmt_inst); + + if (!enc1 || !vpg || !afmt) { + kfree(enc1); + kfree(vpg); + kfree(afmt); + return NULL; + } + + dcn30_dio_stream_encoder_construct(enc1, ctx, ctx->dc_bios, + eng_id, vpg, afmt, + &stream_enc_regs[eng_id], + &se_shift, &se_mask); + + return &enc1->base; +} + +static struct dce_hwseq *dcn30_hwseq_create(struct dc_context *ctx) +{ + struct dce_hwseq *hws = kzalloc(sizeof(struct dce_hwseq), GFP_KERNEL); + + if (hws) { + hws->ctx = ctx; + hws->regs = &hwseq_reg; + hws->shifts = &hwseq_shift; + hws->masks = &hwseq_mask; + } + return hws; +} +static const struct resource_create_funcs res_create_funcs = { + .read_dce_straps = read_dce_straps, + .create_audio = dcn30_create_audio, + .create_stream_encoder = dcn30_stream_encoder_create, + .create_hwseq = dcn30_hwseq_create, +}; + +static void dcn30_resource_destruct(struct dcn30_resource_pool *pool) +{ + unsigned int i; + + for (i = 0; i < pool->base.stream_enc_count; i++) { + if (pool->base.stream_enc[i] != NULL) { + if (pool->base.stream_enc[i]->vpg != NULL) { + kfree(DCN30_VPG_FROM_VPG(pool->base.stream_enc[i]->vpg)); + pool->base.stream_enc[i]->vpg = NULL; + } + if (pool->base.stream_enc[i]->afmt != NULL) { + kfree(DCN30_AFMT_FROM_AFMT(pool->base.stream_enc[i]->afmt)); + pool->base.stream_enc[i]->afmt = NULL; + } + kfree(DCN10STRENC_FROM_STRENC(pool->base.stream_enc[i])); + pool->base.stream_enc[i] = NULL; + } + } + + for (i = 0; i < pool->base.res_cap->num_dsc; i++) { + if (pool->base.dscs[i] != NULL) + dcn20_dsc_destroy(&pool->base.dscs[i]); + } + + if (pool->base.mpc != NULL) { + kfree(TO_DCN20_MPC(pool->base.mpc)); + pool->base.mpc = NULL; + } + if (pool->base.hubbub != NULL) { + kfree(pool->base.hubbub); + pool->base.hubbub = NULL; + } + for (i = 0; i < pool->base.pipe_count; i++) { + if (pool->base.dpps[i] != NULL) + dcn30_dpp_destroy(&pool->base.dpps[i]); + + if (pool->base.ipps[i] != NULL) + pool->base.ipps[i]->funcs->ipp_destroy(&pool->base.ipps[i]); + + if (pool->base.hubps[i] != NULL) { + kfree(TO_DCN20_HUBP(pool->base.hubps[i])); + pool->base.hubps[i] = NULL; + } + + if (pool->base.irqs != NULL) { + dal_irq_service_destroy(&pool->base.irqs); + } + } + + for (i = 0; i < pool->base.res_cap->num_ddc; i++) { + if (pool->base.engines[i] != NULL) + dce110_engine_destroy(&pool->base.engines[i]); + if (pool->base.hw_i2cs[i] != NULL) { + kfree(pool->base.hw_i2cs[i]); + pool->base.hw_i2cs[i] = NULL; + } + if (pool->base.sw_i2cs[i] != NULL) { + kfree(pool->base.sw_i2cs[i]); + pool->base.sw_i2cs[i] = NULL; + } + } + + for (i = 0; i < pool->base.res_cap->num_opp; i++) { + if (pool->base.opps[i] != NULL) + pool->base.opps[i]->funcs->opp_destroy(&pool->base.opps[i]); + } + + for (i = 0; i < pool->base.res_cap->num_timing_generator; i++) { + if (pool->base.timing_generators[i] != NULL) { + kfree(DCN10TG_FROM_TG(pool->base.timing_generators[i])); + pool->base.timing_generators[i] = NULL; + } + } + + for (i = 0; i < pool->base.res_cap->num_dwb; i++) { + if (pool->base.dwbc[i] != NULL) { + kfree(TO_DCN30_DWBC(pool->base.dwbc[i])); + pool->base.dwbc[i] = NULL; + } + if (pool->base.mcif_wb[i] != NULL) { + kfree(TO_DCN30_MMHUBBUB(pool->base.mcif_wb[i])); + pool->base.mcif_wb[i] = NULL; + } + } + + for (i = 0; i < pool->base.audio_count; i++) { + if (pool->base.audios[i]) + dce_aud_destroy(&pool->base.audios[i]); + } + + for (i = 0; i < pool->base.clk_src_count; i++) { + if (pool->base.clock_sources[i] != NULL) { + dcn20_clock_source_destroy(&pool->base.clock_sources[i]); + pool->base.clock_sources[i] = NULL; + } + } + + for (i = 0; i < pool->base.res_cap->num_mpc_3dlut; i++) { + if (pool->base.mpc_lut[i] != NULL) { + dc_3dlut_func_release(pool->base.mpc_lut[i]); + pool->base.mpc_lut[i] = NULL; + } + if (pool->base.mpc_shaper[i] != NULL) { + dc_transfer_func_release(pool->base.mpc_shaper[i]); + pool->base.mpc_shaper[i] = NULL; + } + } + + if (pool->base.dp_clock_source != NULL) { + dcn20_clock_source_destroy(&pool->base.dp_clock_source); + pool->base.dp_clock_source = NULL; + } + + for (i = 0; i < pool->base.pipe_count; i++) { + if (pool->base.multiple_abms[i] != NULL) + dce_abm_destroy(&pool->base.multiple_abms[i]); + } + + if (pool->base.psr != NULL) + dmub_psr_destroy(&pool->base.psr); + + if (pool->base.dccg != NULL) + dcn_dccg_destroy(&pool->base.dccg); + + if (pool->base.oem_device != NULL) { + struct dc *dc = pool->base.oem_device->ctx->dc; + + dc->link_srv->destroy_ddc_service(&pool->base.oem_device); + } +} + +static struct hubp *dcn30_hubp_create( + struct dc_context *ctx, + uint32_t inst) +{ + struct dcn20_hubp *hubp2 = + kzalloc(sizeof(struct dcn20_hubp), GFP_KERNEL); + + if (!hubp2) + return NULL; + + if (hubp3_construct(hubp2, ctx, inst, + &hubp_regs[inst], &hubp_shift, &hubp_mask)) + return &hubp2->base; + + BREAK_TO_DEBUGGER(); + kfree(hubp2); + return NULL; +} + +static bool dcn30_dwbc_create(struct dc_context *ctx, struct resource_pool *pool) +{ + int i; + uint32_t pipe_count = pool->res_cap->num_dwb; + + for (i = 0; i < pipe_count; i++) { + struct dcn30_dwbc *dwbc30 = kzalloc(sizeof(struct dcn30_dwbc), + GFP_KERNEL); + + if (!dwbc30) { + dm_error("DC: failed to create dwbc30!\n"); + return false; + } + + dcn30_dwbc_construct(dwbc30, ctx, + &dwbc30_regs[i], + &dwbc30_shift, + &dwbc30_mask, + i); + + pool->dwbc[i] = &dwbc30->base; + } + return true; +} + +static bool dcn30_mmhubbub_create(struct dc_context *ctx, struct resource_pool *pool) +{ + int i; + uint32_t pipe_count = pool->res_cap->num_dwb; + + for (i = 0; i < pipe_count; i++) { + struct dcn30_mmhubbub *mcif_wb30 = kzalloc(sizeof(struct dcn30_mmhubbub), + GFP_KERNEL); + + if (!mcif_wb30) { + dm_error("DC: failed to create mcif_wb30!\n"); + return false; + } + + dcn30_mmhubbub_construct(mcif_wb30, ctx, + &mcif_wb30_regs[i], + &mcif_wb30_shift, + &mcif_wb30_mask, + i); + + pool->mcif_wb[i] = &mcif_wb30->base; + } + return true; +} + +static struct display_stream_compressor *dcn30_dsc_create( + struct dc_context *ctx, uint32_t inst) +{ + struct dcn20_dsc *dsc = + kzalloc(sizeof(struct dcn20_dsc), GFP_KERNEL); + + if (!dsc) { + BREAK_TO_DEBUGGER(); + return NULL; + } + + dsc2_construct(dsc, ctx, inst, &dsc_regs[inst], &dsc_shift, &dsc_mask); + return &dsc->base; +} + +enum dc_status dcn30_add_stream_to_ctx(struct dc *dc, struct dc_state *new_ctx, struct dc_stream_state *dc_stream) +{ + + return dcn20_add_stream_to_ctx(dc, new_ctx, dc_stream); +} + +static void dcn30_destroy_resource_pool(struct resource_pool **pool) +{ + struct dcn30_resource_pool *dcn30_pool = TO_DCN30_RES_POOL(*pool); + + dcn30_resource_destruct(dcn30_pool); + kfree(dcn30_pool); + *pool = NULL; +} + +static struct clock_source *dcn30_clock_source_create( + struct dc_context *ctx, + struct dc_bios *bios, + enum clock_source_id id, + const struct dce110_clk_src_regs *regs, + bool dp_clk_src) +{ + struct dce110_clk_src *clk_src = + kzalloc(sizeof(struct dce110_clk_src), GFP_KERNEL); + + if (!clk_src) + return NULL; + + if (dcn3_clk_src_construct(clk_src, ctx, bios, id, + regs, &cs_shift, &cs_mask)) { + clk_src->base.dp_clk_src = dp_clk_src; + return &clk_src->base; + } + + kfree(clk_src); + BREAK_TO_DEBUGGER(); + return NULL; +} + +int dcn30_populate_dml_pipes_from_context( + struct dc *dc, struct dc_state *context, + display_e2e_pipe_params_st *pipes, + bool fast_validate) +{ + int i, pipe_cnt; + struct resource_context *res_ctx = &context->res_ctx; + + DC_FP_START(); + dcn20_populate_dml_pipes_from_context(dc, context, pipes, fast_validate); + DC_FP_END(); + + for (i = 0, pipe_cnt = 0; i < dc->res_pool->pipe_count; i++) { + if (!res_ctx->pipe_ctx[i].stream) + continue; + + pipes[pipe_cnt++].pipe.scale_ratio_depth.lb_depth = + dm_lb_16; + } + + return pipe_cnt; +} + +void dcn30_populate_dml_writeback_from_context( + struct dc *dc, struct resource_context *res_ctx, display_e2e_pipe_params_st *pipes) +{ + DC_FP_START(); + dcn30_fpu_populate_dml_writeback_from_context(dc, res_ctx, pipes); + DC_FP_END(); +} + +unsigned int dcn30_calc_max_scaled_time( + unsigned int time_per_pixel, + enum mmhubbub_wbif_mode mode, + unsigned int urgent_watermark) +{ + unsigned int time_per_byte = 0; + unsigned int total_free_entry = 0xb40; + unsigned int buf_lh_capability; + unsigned int max_scaled_time; + + if (mode == PACKED_444) /* packed mode 32 bpp */ + time_per_byte = time_per_pixel/4; + else if (mode == PACKED_444_FP16) /* packed mode 64 bpp */ + time_per_byte = time_per_pixel/8; + + if (time_per_byte == 0) + time_per_byte = 1; + + buf_lh_capability = (total_free_entry*time_per_byte*32) >> 6; /* time_per_byte is in u6.6*/ + max_scaled_time = buf_lh_capability - urgent_watermark; + return max_scaled_time; +} + +void dcn30_set_mcif_arb_params( + struct dc *dc, + struct dc_state *context, + display_e2e_pipe_params_st *pipes, + int pipe_cnt) +{ + enum mmhubbub_wbif_mode wbif_mode; + struct display_mode_lib *dml = &context->bw_ctx.dml; + struct mcif_arb_params *wb_arb_params; + int i, j, dwb_pipe; + + /* Writeback MCIF_WB arbitration parameters */ + dwb_pipe = 0; + for (i = 0; i < dc->res_pool->pipe_count; i++) { + + if (!context->res_ctx.pipe_ctx[i].stream) + continue; + + for (j = 0; j < MAX_DWB_PIPES; j++) { + struct dc_writeback_info *writeback_info = &context->res_ctx.pipe_ctx[i].stream->writeback_info[j]; + + if (writeback_info->wb_enabled == false) + continue; + + //wb_arb_params = &context->res_ctx.pipe_ctx[i].stream->writeback_info[j].mcif_arb_params; + wb_arb_params = &context->bw_ctx.bw.dcn.bw_writeback.mcif_wb_arb[dwb_pipe]; + + if (writeback_info->dwb_params.cnv_params.fc_out_format == DWB_OUT_FORMAT_64BPP_ARGB || + writeback_info->dwb_params.cnv_params.fc_out_format == DWB_OUT_FORMAT_64BPP_RGBA) + wbif_mode = PACKED_444_FP16; + else + wbif_mode = PACKED_444; + + DC_FP_START(); + dcn30_fpu_set_mcif_arb_params(wb_arb_params, dml, pipes, pipe_cnt, j); + DC_FP_END(); + wb_arb_params->time_per_pixel = (1000000 << 6) / context->res_ctx.pipe_ctx[i].stream->phy_pix_clk; /* time_per_pixel should be in u6.6 format */ + wb_arb_params->slice_lines = 32; + wb_arb_params->arbitration_slice = 2; /* irrelevant since there is no YUV output */ + wb_arb_params->max_scaled_time = dcn30_calc_max_scaled_time(wb_arb_params->time_per_pixel, + wbif_mode, + wb_arb_params->cli_watermark[0]); /* assume 4 watermark sets have the same value */ + + dwb_pipe++; + + if (dwb_pipe >= MAX_DWB_PIPES) + return; + } + if (dwb_pipe >= MAX_DWB_PIPES) + return; + } + +} + +static struct dc_cap_funcs cap_funcs = { + .get_dcc_compression_cap = dcn20_get_dcc_compression_cap +}; + +bool dcn30_acquire_post_bldn_3dlut( + struct resource_context *res_ctx, + const struct resource_pool *pool, + int mpcc_id, + struct dc_3dlut **lut, + struct dc_transfer_func **shaper) +{ + int i; + bool ret = false; + union dc_3dlut_state *state; + + ASSERT(*lut == NULL && *shaper == NULL); + *lut = NULL; + *shaper = NULL; + + for (i = 0; i < pool->res_cap->num_mpc_3dlut; i++) { + if (!res_ctx->is_mpc_3dlut_acquired[i]) { + *lut = pool->mpc_lut[i]; + *shaper = pool->mpc_shaper[i]; + state = &pool->mpc_lut[i]->state; + res_ctx->is_mpc_3dlut_acquired[i] = true; + state->bits.rmu_idx_valid = 1; + state->bits.rmu_mux_num = i; + if (state->bits.rmu_mux_num == 0) + state->bits.mpc_rmu0_mux = mpcc_id; + else if (state->bits.rmu_mux_num == 1) + state->bits.mpc_rmu1_mux = mpcc_id; + else if (state->bits.rmu_mux_num == 2) + state->bits.mpc_rmu2_mux = mpcc_id; + ret = true; + break; + } + } + return ret; +} + +bool dcn30_release_post_bldn_3dlut( + struct resource_context *res_ctx, + const struct resource_pool *pool, + struct dc_3dlut **lut, + struct dc_transfer_func **shaper) +{ + int i; + bool ret = false; + + for (i = 0; i < pool->res_cap->num_mpc_3dlut; i++) { + if (pool->mpc_lut[i] == *lut && pool->mpc_shaper[i] == *shaper) { + res_ctx->is_mpc_3dlut_acquired[i] = false; + pool->mpc_lut[i]->state.raw = 0; + *lut = NULL; + *shaper = NULL; + ret = true; + break; + } + } + return ret; +} + +static bool is_soc_bounding_box_valid(struct dc *dc) +{ + uint32_t hw_internal_rev = dc->ctx->asic_id.hw_internal_rev; + + if (ASICREV_IS_SIENNA_CICHLID_P(hw_internal_rev)) + return true; + + return false; +} + +static bool init_soc_bounding_box(struct dc *dc, + struct dcn30_resource_pool *pool) +{ + 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 (!is_soc_bounding_box_valid(dc)) { + DC_LOG_ERROR("%s: not valid soc bounding box\n", __func__); + return false; + } + + 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); + DC_FP_START(); + patch_dcn30_soc_bounding_box(dc, &dcn3_0_soc); + DC_FP_END(); + + return true; +} + +static bool dcn30_split_stream_for_mpc_or_odm( + const struct dc *dc, + struct resource_context *res_ctx, + struct pipe_ctx *pri_pipe, + struct pipe_ctx *sec_pipe, + bool odm) +{ + int pipe_idx = sec_pipe->pipe_idx; + const struct resource_pool *pool = dc->res_pool; + + *sec_pipe = *pri_pipe; + + sec_pipe->pipe_idx = pipe_idx; + sec_pipe->plane_res.mi = pool->mis[pipe_idx]; + sec_pipe->plane_res.hubp = pool->hubps[pipe_idx]; + sec_pipe->plane_res.ipp = pool->ipps[pipe_idx]; + sec_pipe->plane_res.xfm = pool->transforms[pipe_idx]; + sec_pipe->plane_res.dpp = pool->dpps[pipe_idx]; + sec_pipe->plane_res.mpcc_inst = pool->dpps[pipe_idx]->inst; + sec_pipe->stream_res.dsc = NULL; + if (odm) { + if (pri_pipe->next_odm_pipe) { + ASSERT(pri_pipe->next_odm_pipe != sec_pipe); + sec_pipe->next_odm_pipe = pri_pipe->next_odm_pipe; + sec_pipe->next_odm_pipe->prev_odm_pipe = sec_pipe; + } + if (pri_pipe->top_pipe && pri_pipe->top_pipe->next_odm_pipe) { + pri_pipe->top_pipe->next_odm_pipe->bottom_pipe = sec_pipe; + sec_pipe->top_pipe = pri_pipe->top_pipe->next_odm_pipe; + } + if (pri_pipe->bottom_pipe && pri_pipe->bottom_pipe->next_odm_pipe) { + pri_pipe->bottom_pipe->next_odm_pipe->top_pipe = sec_pipe; + sec_pipe->bottom_pipe = pri_pipe->bottom_pipe->next_odm_pipe; + } + pri_pipe->next_odm_pipe = sec_pipe; + sec_pipe->prev_odm_pipe = pri_pipe; + + if (!sec_pipe->top_pipe) + sec_pipe->stream_res.opp = pool->opps[pipe_idx]; + else + sec_pipe->stream_res.opp = sec_pipe->top_pipe->stream_res.opp; + if (sec_pipe->stream->timing.flags.DSC == 1) { + dcn20_acquire_dsc(dc, res_ctx, &sec_pipe->stream_res.dsc, pipe_idx); + ASSERT(sec_pipe->stream_res.dsc); + if (sec_pipe->stream_res.dsc == NULL) + return false; + } + } else { + if (pri_pipe->bottom_pipe) { + ASSERT(pri_pipe->bottom_pipe != sec_pipe); + sec_pipe->bottom_pipe = pri_pipe->bottom_pipe; + sec_pipe->bottom_pipe->top_pipe = sec_pipe; + } + pri_pipe->bottom_pipe = sec_pipe; + sec_pipe->top_pipe = pri_pipe; + + ASSERT(pri_pipe->plane_state); + } + + return true; +} + +static struct pipe_ctx *dcn30_find_split_pipe( + struct dc *dc, + struct dc_state *context, + int old_index) +{ + struct pipe_ctx *pipe = NULL; + int i; + + if (old_index >= 0 && context->res_ctx.pipe_ctx[old_index].stream == NULL) { + pipe = &context->res_ctx.pipe_ctx[old_index]; + pipe->pipe_idx = old_index; + } + + if (!pipe) + for (i = dc->res_pool->pipe_count - 1; i >= 0; i--) { + if (dc->current_state->res_ctx.pipe_ctx[i].top_pipe == NULL + && dc->current_state->res_ctx.pipe_ctx[i].prev_odm_pipe == NULL) { + if (context->res_ctx.pipe_ctx[i].stream == NULL) { + pipe = &context->res_ctx.pipe_ctx[i]; + pipe->pipe_idx = i; + break; + } + } + } + + /* + * May need to fix pipes getting tossed from 1 opp to another on flip + * Add for debugging transient underflow during topology updates: + * ASSERT(pipe); + */ + if (!pipe) + for (i = dc->res_pool->pipe_count - 1; i >= 0; i--) { + if (context->res_ctx.pipe_ctx[i].stream == NULL) { + pipe = &context->res_ctx.pipe_ctx[i]; + pipe->pipe_idx = i; + break; + } + } + + return pipe; +} + +noinline bool dcn30_internal_validate_bw( + struct dc *dc, + struct dc_state *context, + display_e2e_pipe_params_st *pipes, + int *pipe_cnt_out, + int *vlevel_out, + bool fast_validate, + bool allow_self_refresh_only) +{ + bool out = false; + bool repopulate_pipes = false; + int split[MAX_PIPES] = { 0 }; + bool merge[MAX_PIPES] = { false }; + bool newly_split[MAX_PIPES] = { false }; + int pipe_cnt, i, pipe_idx, vlevel; + struct vba_vars_st *vba = &context->bw_ctx.dml.vba; + + ASSERT(pipes); + if (!pipes) + return false; + + context->bw_ctx.dml.vba.maxMpcComb = 0; + context->bw_ctx.dml.vba.VoltageLevel = 0; + context->bw_ctx.dml.vba.DRAMClockChangeSupport[0][0] = dm_dram_clock_change_vactive; + dc->res_pool->funcs->update_soc_for_wm_a(dc, context); + pipe_cnt = dc->res_pool->funcs->populate_dml_pipes(dc, context, pipes, fast_validate); + + if (!pipe_cnt) { + out = true; + goto validate_out; + } + + dml_log_pipe_params(&context->bw_ctx.dml, pipes, pipe_cnt); + + if (!fast_validate || !allow_self_refresh_only) { + /* + * DML favors voltage over p-state, but we're more interested in + * supporting p-state over voltage. We can't support p-state in + * prefetch mode > 0 so try capping the prefetch mode to start. + */ + context->bw_ctx.dml.soc.allow_dram_self_refresh_or_dram_clock_change_in_vblank = + dm_allow_self_refresh_and_mclk_switch; + vlevel = dml_get_voltage_level(&context->bw_ctx.dml, pipes, pipe_cnt); + /* This may adjust vlevel and maxMpcComb */ + if (vlevel < context->bw_ctx.dml.soc.num_states) + vlevel = dcn20_validate_apply_pipe_split_flags(dc, context, vlevel, split, merge); + } + if (allow_self_refresh_only && + (fast_validate || vlevel == context->bw_ctx.dml.soc.num_states || + vba->DRAMClockChangeSupport[vlevel][vba->maxMpcComb] == dm_dram_clock_change_unsupported)) { + /* + * If mode is unsupported or there's still no p-state support + * then fall back to favoring voltage. + * + * We don't actually support prefetch mode 2, so require that we + * at least support prefetch mode 1. + */ + context->bw_ctx.dml.soc.allow_dram_self_refresh_or_dram_clock_change_in_vblank = + dm_allow_self_refresh; + + vlevel = dml_get_voltage_level(&context->bw_ctx.dml, pipes, pipe_cnt); + if (vlevel < context->bw_ctx.dml.soc.num_states) { + memset(split, 0, sizeof(split)); + memset(merge, 0, sizeof(merge)); + vlevel = dcn20_validate_apply_pipe_split_flags(dc, context, vlevel, split, merge); + } + } + + dml_log_mode_support_params(&context->bw_ctx.dml); + + if (vlevel == context->bw_ctx.dml.soc.num_states) + goto validate_fail; + + if (!dc->config.enable_windowed_mpo_odm) { + for (i = 0, pipe_idx = 0; i < dc->res_pool->pipe_count; i++) { + struct pipe_ctx *pipe = &context->res_ctx.pipe_ctx[i]; + struct pipe_ctx *mpo_pipe = pipe->bottom_pipe; + + if (!pipe->stream) + continue; + + /* We only support full screen mpo with ODM */ + if (vba->ODMCombineEnabled[vba->pipe_plane[pipe_idx]] != dm_odm_combine_mode_disabled + && pipe->plane_state && mpo_pipe + && memcmp(&mpo_pipe->plane_state->clip_rect, + &pipe->stream->src, + sizeof(struct rect)) != 0) { + ASSERT(mpo_pipe->plane_state != pipe->plane_state); + goto validate_fail; + } + pipe_idx++; + } + } + + /* merge pipes if necessary */ + for (i = 0; i < dc->res_pool->pipe_count; i++) { + struct pipe_ctx *pipe = &context->res_ctx.pipe_ctx[i]; + + /*skip pipes that don't need merging*/ + if (!merge[i]) + continue; + + /* if ODM merge we ignore mpc tree, mpo pipes will have their own flags */ + if (pipe->prev_odm_pipe) { + /*split off odm pipe*/ + pipe->prev_odm_pipe->next_odm_pipe = pipe->next_odm_pipe; + if (pipe->next_odm_pipe) + pipe->next_odm_pipe->prev_odm_pipe = pipe->prev_odm_pipe; + + pipe->bottom_pipe = NULL; + pipe->next_odm_pipe = NULL; + pipe->plane_state = NULL; + pipe->stream = NULL; + pipe->top_pipe = NULL; + pipe->prev_odm_pipe = NULL; + if (pipe->stream_res.dsc) + dcn20_release_dsc(&context->res_ctx, dc->res_pool, &pipe->stream_res.dsc); + memset(&pipe->plane_res, 0, sizeof(pipe->plane_res)); + memset(&pipe->stream_res, 0, sizeof(pipe->stream_res)); + repopulate_pipes = true; + } else if (pipe->top_pipe && pipe->top_pipe->plane_state == pipe->plane_state) { + struct pipe_ctx *top_pipe = pipe->top_pipe; + struct pipe_ctx *bottom_pipe = pipe->bottom_pipe; + + top_pipe->bottom_pipe = bottom_pipe; + if (bottom_pipe) + bottom_pipe->top_pipe = top_pipe; + + pipe->top_pipe = NULL; + pipe->bottom_pipe = NULL; + pipe->plane_state = NULL; + pipe->stream = NULL; + memset(&pipe->plane_res, 0, sizeof(pipe->plane_res)); + memset(&pipe->stream_res, 0, sizeof(pipe->stream_res)); + repopulate_pipes = true; + } else + ASSERT(0); /* Should never try to merge master pipe */ + + } + + for (i = 0, pipe_idx = -1; i < dc->res_pool->pipe_count; i++) { + struct pipe_ctx *pipe = &context->res_ctx.pipe_ctx[i]; + struct pipe_ctx *old_pipe = &dc->current_state->res_ctx.pipe_ctx[i]; + struct pipe_ctx *hsplit_pipe = NULL; + bool odm; + int old_index = -1; + + if (!pipe->stream || newly_split[i]) + continue; + + pipe_idx++; + odm = vba->ODMCombineEnabled[vba->pipe_plane[pipe_idx]] != dm_odm_combine_mode_disabled; + + if (!pipe->plane_state && !odm) + continue; + + if (split[i]) { + if (odm) { + if (split[i] == 4 && old_pipe->next_odm_pipe && old_pipe->next_odm_pipe->next_odm_pipe) + old_index = old_pipe->next_odm_pipe->next_odm_pipe->pipe_idx; + else if (old_pipe->next_odm_pipe) + old_index = old_pipe->next_odm_pipe->pipe_idx; + } else { + if (split[i] == 4 && old_pipe->bottom_pipe && old_pipe->bottom_pipe->bottom_pipe && + old_pipe->bottom_pipe->bottom_pipe->plane_state == old_pipe->plane_state) + old_index = old_pipe->bottom_pipe->bottom_pipe->pipe_idx; + else if (old_pipe->bottom_pipe && + old_pipe->bottom_pipe->plane_state == old_pipe->plane_state) + old_index = old_pipe->bottom_pipe->pipe_idx; + } + hsplit_pipe = dcn30_find_split_pipe(dc, context, old_index); + ASSERT(hsplit_pipe); + if (!hsplit_pipe) + goto validate_fail; + + if (!dcn30_split_stream_for_mpc_or_odm( + dc, &context->res_ctx, + pipe, hsplit_pipe, odm)) + goto validate_fail; + + newly_split[hsplit_pipe->pipe_idx] = true; + repopulate_pipes = true; + } + if (split[i] == 4) { + struct pipe_ctx *pipe_4to1; + + if (odm && old_pipe->next_odm_pipe) + old_index = old_pipe->next_odm_pipe->pipe_idx; + else if (!odm && old_pipe->bottom_pipe && + old_pipe->bottom_pipe->plane_state == old_pipe->plane_state) + old_index = old_pipe->bottom_pipe->pipe_idx; + else + old_index = -1; + pipe_4to1 = dcn30_find_split_pipe(dc, context, old_index); + ASSERT(pipe_4to1); + if (!pipe_4to1) + goto validate_fail; + if (!dcn30_split_stream_for_mpc_or_odm( + dc, &context->res_ctx, + pipe, pipe_4to1, odm)) + goto validate_fail; + newly_split[pipe_4to1->pipe_idx] = true; + + if (odm && old_pipe->next_odm_pipe && old_pipe->next_odm_pipe->next_odm_pipe + && old_pipe->next_odm_pipe->next_odm_pipe->next_odm_pipe) + old_index = old_pipe->next_odm_pipe->next_odm_pipe->next_odm_pipe->pipe_idx; + else if (!odm && old_pipe->bottom_pipe && old_pipe->bottom_pipe->bottom_pipe && + old_pipe->bottom_pipe->bottom_pipe->bottom_pipe && + old_pipe->bottom_pipe->bottom_pipe->bottom_pipe->plane_state == old_pipe->plane_state) + old_index = old_pipe->bottom_pipe->bottom_pipe->bottom_pipe->pipe_idx; + else + old_index = -1; + pipe_4to1 = dcn30_find_split_pipe(dc, context, old_index); + ASSERT(pipe_4to1); + if (!pipe_4to1) + goto validate_fail; + if (!dcn30_split_stream_for_mpc_or_odm( + dc, &context->res_ctx, + hsplit_pipe, pipe_4to1, odm)) + goto validate_fail; + newly_split[pipe_4to1->pipe_idx] = true; + } + if (odm) + dcn20_build_mapped_resource(dc, context, pipe->stream); + } + + for (i = 0; i < dc->res_pool->pipe_count; i++) { + struct pipe_ctx *pipe = &context->res_ctx.pipe_ctx[i]; + + if (pipe->plane_state) { + if (!resource_build_scaling_params(pipe)) + goto validate_fail; + } + } + + /* Actual dsc count per stream dsc validation*/ + if (!dcn20_validate_dsc(dc, context)) { + vba->ValidationStatus[vba->soc.num_states] = DML_FAIL_DSC_VALIDATION_FAILURE; + goto validate_fail; + } + + if (repopulate_pipes) + pipe_cnt = dc->res_pool->funcs->populate_dml_pipes(dc, context, pipes, fast_validate); + context->bw_ctx.dml.vba.VoltageLevel = vlevel; + *vlevel_out = vlevel; + *pipe_cnt_out = pipe_cnt; + + out = true; + goto validate_out; + +validate_fail: + out = false; + +validate_out: + return out; +} + +static int get_refresh_rate(struct dc_state *context) +{ + int refresh_rate = 0; + int h_v_total = 0; + struct dc_crtc_timing *timing = NULL; + + if (context == NULL || context->streams[0] == NULL) + return 0; + + /* check if refresh rate at least 120hz */ + timing = &context->streams[0]->timing; + if (timing == NULL) + return 0; + + h_v_total = timing->h_total * timing->v_total; + if (h_v_total == 0) + return 0; + + refresh_rate = ((timing->pix_clk_100hz * 100) / (h_v_total)) + 1; + return refresh_rate; +} + +#define MAX_STRETCHED_V_BLANK 500 // in micro-seconds +/* + * Scaling factor for v_blank stretch calculations considering timing in + * micro-seconds and pixel clock in 100hz. + * Note: the parenthesis are necessary to ensure the correct order of + * operation where V_SCALE is used. + */ +#define V_SCALE (10000 / MAX_STRETCHED_V_BLANK) + +static int get_frame_rate_at_max_stretch_100hz(struct dc_state *context) +{ + struct dc_crtc_timing *timing = NULL; + uint32_t sec_per_100_lines; + uint32_t max_v_blank; + uint32_t curr_v_blank; + uint32_t v_stretch_max; + uint32_t stretched_frame_pix_cnt; + uint32_t scaled_stretched_frame_pix_cnt; + uint32_t scaled_refresh_rate; + + if (context == NULL || context->streams[0] == NULL) + return 0; + + /* check if refresh rate at least 120hz */ + timing = &context->streams[0]->timing; + if (timing == NULL) + return 0; + + sec_per_100_lines = timing->pix_clk_100hz / timing->h_total + 1; + max_v_blank = sec_per_100_lines / V_SCALE + 1; + curr_v_blank = timing->v_total - timing->v_addressable; + v_stretch_max = (max_v_blank > curr_v_blank) ? (max_v_blank - curr_v_blank) : (0); + stretched_frame_pix_cnt = (v_stretch_max + timing->v_total) * timing->h_total; + scaled_stretched_frame_pix_cnt = stretched_frame_pix_cnt / 10000; + scaled_refresh_rate = (timing->pix_clk_100hz) / scaled_stretched_frame_pix_cnt + 1; + + return scaled_refresh_rate; +} + +static bool is_refresh_rate_support_mclk_switch_using_fw_based_vblank_stretch(struct dc_state *context) +{ + int refresh_rate_max_stretch_100hz; + int min_refresh_100hz; + + if (context == NULL || context->streams[0] == NULL) + return false; + + refresh_rate_max_stretch_100hz = get_frame_rate_at_max_stretch_100hz(context); + min_refresh_100hz = context->streams[0]->timing.min_refresh_in_uhz / 10000; + + if (refresh_rate_max_stretch_100hz < min_refresh_100hz) + return false; + + return true; +} + +bool dcn30_can_support_mclk_switch_using_fw_based_vblank_stretch(struct dc *dc, struct dc_state *context) +{ + int refresh_rate = 0; + const int minimum_refreshrate_supported = 120; + + if (context == NULL || context->streams[0] == NULL) + return false; + + if (context->streams[0]->sink->edid_caps.panel_patch.disable_fams) + return false; + + if (dc->debug.disable_fams) + return false; + + if (!dc->caps.dmub_caps.mclk_sw) + return false; + + if (context->bw_ctx.bw.dcn.clk.fw_based_mclk_switching_shut_down) + return false; + + /* more then 1 monitor connected */ + if (context->stream_count != 1) + return false; + + refresh_rate = get_refresh_rate(context); + if (refresh_rate < minimum_refreshrate_supported) + return false; + + if (!is_refresh_rate_support_mclk_switch_using_fw_based_vblank_stretch(context)) + return false; + + if (!context->streams[0]->allow_freesync) + return false; + + if (context->streams[0]->vrr_active_variable && dc->debug.disable_fams_gaming) + return false; + + context->streams[0]->fpo_in_use = true; + + return true; +} + +/* + * set up FPO watermarks, pstate, dram latency + */ +void dcn30_setup_mclk_switch_using_fw_based_vblank_stretch(struct dc *dc, struct dc_state *context) +{ + ASSERT(dc != NULL && context != NULL); + if (dc == NULL || context == NULL) + return; + + /* Set wm_a.pstate so high natural MCLK switches are impossible: 4 seconds */ + context->bw_ctx.bw.dcn.watermarks.a.cstate_pstate.pstate_change_ns = 4U * 1000U * 1000U * 1000U; +} + +void dcn30_update_soc_for_wm_a(struct dc *dc, struct dc_state *context) +{ + DC_FP_START(); + dcn30_fpu_update_soc_for_wm_a(dc, context); + DC_FP_END(); +} + +void dcn30_calculate_wm_and_dlg( + struct dc *dc, struct dc_state *context, + display_e2e_pipe_params_st *pipes, + int pipe_cnt, + int vlevel) +{ + DC_FP_START(); + dcn30_fpu_calculate_wm_and_dlg(dc, context, pipes, pipe_cnt, vlevel); + DC_FP_END(); +} + +bool dcn30_validate_bandwidth(struct dc *dc, + struct dc_state *context, + bool fast_validate) +{ + bool out = false; + + BW_VAL_TRACE_SETUP(); + + int vlevel = 0; + int pipe_cnt = 0; + display_e2e_pipe_params_st *pipes = kzalloc(dc->res_pool->pipe_count * sizeof(display_e2e_pipe_params_st), GFP_KERNEL); + DC_LOGGER_INIT(dc->ctx->logger); + + BW_VAL_TRACE_COUNT(); + + DC_FP_START(); + out = dcn30_internal_validate_bw(dc, context, pipes, &pipe_cnt, &vlevel, fast_validate, true); + DC_FP_END(); + + if (pipe_cnt == 0) + goto validate_out; + + if (!out) + goto validate_fail; + + BW_VAL_TRACE_END_VOLTAGE_LEVEL(); + + if (fast_validate) { + BW_VAL_TRACE_SKIP(fast); + goto validate_out; + } + + DC_FP_START(); + if (dc->res_pool->funcs->calculate_wm_and_dlg) + dc->res_pool->funcs->calculate_wm_and_dlg(dc, context, pipes, pipe_cnt, vlevel); + DC_FP_END(); + + BW_VAL_TRACE_END_WATERMARKS(); + + goto validate_out; + +validate_fail: + DC_LOG_WARNING("Mode Validation Warning: %s failed validation.\n", + dml_get_status_message(context->bw_ctx.dml.vba.ValidationStatus[context->bw_ctx.dml.vba.soc.num_states])); + + BW_VAL_TRACE_SKIP(fail); + out = false; + +validate_out: + kfree(pipes); + + BW_VAL_TRACE_FINISH(); + + return out; +} + +void dcn30_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; + + struct dc_bounding_box_max_clk dcn30_bb_max_clk; + + memset(&dcn30_bb_max_clk, 0, sizeof(dcn30_bb_max_clk)); + + if (dc->ctx->dc_bios->vram_info.num_chans) + dcn3_0_soc.num_chans = dc->ctx->dc_bios->vram_info.num_chans; + + DC_FP_START(); + dcn30_fpu_update_dram_channel_width_bytes(dc); + DC_FP_END(); + + if (bw_params->clk_table.entries[0].memclk_mhz) { + + for (i = 0; i < MAX_NUM_DPM_LVL; i++) { + if (bw_params->clk_table.entries[i].dcfclk_mhz > dcn30_bb_max_clk.max_dcfclk_mhz) + dcn30_bb_max_clk.max_dcfclk_mhz = bw_params->clk_table.entries[i].dcfclk_mhz; + if (bw_params->clk_table.entries[i].dispclk_mhz > dcn30_bb_max_clk.max_dispclk_mhz) + dcn30_bb_max_clk.max_dispclk_mhz = bw_params->clk_table.entries[i].dispclk_mhz; + if (bw_params->clk_table.entries[i].dppclk_mhz > dcn30_bb_max_clk.max_dppclk_mhz) + dcn30_bb_max_clk.max_dppclk_mhz = bw_params->clk_table.entries[i].dppclk_mhz; + if (bw_params->clk_table.entries[i].phyclk_mhz > dcn30_bb_max_clk.max_phyclk_mhz) + dcn30_bb_max_clk.max_phyclk_mhz = bw_params->clk_table.entries[i].phyclk_mhz; + } + + DC_FP_START(); + dcn30_fpu_update_max_clk(&dcn30_bb_max_clk); + DC_FP_END(); + + if (dcn30_bb_max_clk.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] = dcn30_bb_max_clk.max_dcfclk_mhz; + num_dcfclk_sta_targets++; + } else if (dcn30_bb_max_clk.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] > dcn30_bb_max_clk.max_dcfclk_mhz) { + dcfclk_sta_targets[i] = dcn30_bb_max_clk.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++) { + DC_FP_START(); + dcn30_fpu_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) { + 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] <= dcn30_bb_max_clk.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] <= dcn30_bb_max_clk.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_0_soc.num_states = num_states; + DC_FP_START(); + dcn30_fpu_update_bw_bounding_box(dc, bw_params, &dcn30_bb_max_clk, dcfclk_mhz, dram_speed_mts); + DC_FP_END(); + } +} + +static void dcn30_get_panel_config_defaults(struct dc_panel_config *panel_config) +{ + *panel_config = panel_config_defaults; +} + +static const struct resource_funcs dcn30_res_pool_funcs = { + .destroy = dcn30_destroy_resource_pool, + .link_enc_create = dcn30_link_encoder_create, + .panel_cntl_create = dcn30_panel_cntl_create, + .validate_bandwidth = dcn30_validate_bandwidth, + .calculate_wm_and_dlg = dcn30_calculate_wm_and_dlg, + .update_soc_for_wm_a = dcn30_update_soc_for_wm_a, + .populate_dml_pipes = dcn30_populate_dml_pipes_from_context, + .acquire_free_pipe_as_secondary_dpp_pipe = dcn20_acquire_free_pipe_for_layer, + .release_pipe = dcn20_release_pipe, + .add_stream_to_ctx = dcn30_add_stream_to_ctx, + .add_dsc_to_stream_resource = dcn20_add_dsc_to_stream_resource, + .remove_stream_from_ctx = dcn20_remove_stream_from_ctx, + .populate_dml_writeback_from_context = dcn30_populate_dml_writeback_from_context, + .set_mcif_arb_params = dcn30_set_mcif_arb_params, + .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, + .patch_unknown_plane_state = dcn20_patch_unknown_plane_state, + .get_panel_config_defaults = dcn30_get_panel_config_defaults, +}; + +#define CTX ctx + +#define REG(reg_name) \ + (DCN_BASE.instance[0].segment[mm ## reg_name ## _BASE_IDX] + mm ## reg_name) + +static uint32_t read_pipe_fuses(struct dc_context *ctx) +{ + uint32_t value = REG_READ(CC_DC_PIPE_DIS); + /* Support for max 6 pipes */ + value = value & 0x3f; + return value; +} + +static bool dcn30_resource_construct( + uint8_t num_virtual_links, + struct dc *dc, + struct dcn30_resource_pool *pool) +{ + int i; + struct dc_context *ctx = dc->ctx; + struct irq_service_init_data init_data; + struct ddc_service_init_data ddc_init_data = {0}; + uint32_t pipe_fuses = read_pipe_fuses(ctx); + uint32_t num_pipes = 0; + + if (!(pipe_fuses == 0 || pipe_fuses == 0x3e)) { + BREAK_TO_DEBUGGER(); + dm_error("DC: Unexpected fuse recipe for navi2x !\n"); + /* fault to single pipe */ + pipe_fuses = 0x3e; + } + + DC_FP_START(); + + ctx->dc_bios->regs = &bios_regs; + + pool->base.res_cap = &res_cap_dcn3; + + pool->base.funcs = &dcn30_res_pool_funcs; + + /************************************************* + * Resource + asic cap harcoding * + *************************************************/ + pool->base.underlay_pipe_index = NO_UNDERLAY_PIPE; + pool->base.pipe_count = pool->base.res_cap->num_timing_generator; + pool->base.mpcc_count = pool->base.res_cap->num_timing_generator; + dc->caps.max_downscale_ratio = 600; + dc->caps.i2c_speed_in_khz = 100; + dc->caps.i2c_speed_in_khz_hdcp = 100; /*1.4 w/a not applied by default*/ + 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 = 8; + /* 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 = 2; + dc->caps.max_slave_yuv_planes = 2; + dc->caps.max_slave_rgb_planes = 2; + dc->caps.post_blend_color_processing = true; + dc->caps.force_dp_tps4_for_cp2520 = true; + dc->caps.extended_aux_timeout_support = true; + dc->caps.dmcub_support = true; + + /* Color pipeline capabilities */ + dc->caps.color.dpp.dcn_arch = 1; + dc->caps.color.dpp.input_lut_shared = 0; + dc->caps.color.dpp.icsc = 1; + dc->caps.color.dpp.dgam_ram = 0; // must use gamma_corr + dc->caps.color.dpp.dgam_rom_caps.srgb = 1; + dc->caps.color.dpp.dgam_rom_caps.bt2020 = 1; + dc->caps.color.dpp.dgam_rom_caps.gamma2_2 = 1; + dc->caps.color.dpp.dgam_rom_caps.pq = 1; + dc->caps.color.dpp.dgam_rom_caps.hlg = 1; + dc->caps.color.dpp.post_csc = 1; + dc->caps.color.dpp.gamma_corr = 1; + dc->caps.color.dpp.dgam_rom_for_yuv = 0; + + dc->caps.color.dpp.hw_3d_lut = 1; + dc->caps.color.dpp.ogam_ram = 1; + // no OGAM ROM on DCN3 + dc->caps.color.dpp.ogam_rom_caps.srgb = 0; + dc->caps.color.dpp.ogam_rom_caps.bt2020 = 0; + dc->caps.color.dpp.ogam_rom_caps.gamma2_2 = 0; + dc->caps.color.dpp.ogam_rom_caps.pq = 0; + dc->caps.color.dpp.ogam_rom_caps.hlg = 0; + dc->caps.color.dpp.ocsc = 0; + + dc->caps.color.mpc.gamut_remap = 1; + dc->caps.color.mpc.num_3dluts = pool->base.res_cap->num_mpc_3dlut; //3 + dc->caps.color.mpc.ogam_ram = 1; + dc->caps.color.mpc.ogam_rom_caps.srgb = 0; + dc->caps.color.mpc.ogam_rom_caps.bt2020 = 0; + dc->caps.color.mpc.ogam_rom_caps.gamma2_2 = 0; + dc->caps.color.mpc.ogam_rom_caps.pq = 0; + dc->caps.color.mpc.ogam_rom_caps.hlg = 0; + dc->caps.color.mpc.ocsc = 1; + + dc->caps.dp_hdmi21_pcon_support = true; + dc->caps.max_v_total = (1 << 15) - 1; + + /* read VBIOS LTTPR caps */ + { + if (ctx->dc_bios->funcs->get_lttpr_caps) { + enum bp_result bp_query_result; + uint8_t is_vbios_lttpr_enable = 0; + + bp_query_result = ctx->dc_bios->funcs->get_lttpr_caps(ctx->dc_bios, &is_vbios_lttpr_enable); + dc->caps.vbios_lttpr_enable = (bp_query_result == BP_RESULT_OK) && !!is_vbios_lttpr_enable; + } + + if (ctx->dc_bios->funcs->get_lttpr_interop) { + enum bp_result bp_query_result; + uint8_t is_vbios_interop_enabled = 0; + + bp_query_result = ctx->dc_bios->funcs->get_lttpr_interop(ctx->dc_bios, + &is_vbios_interop_enabled); + dc->caps.vbios_lttpr_aware = (bp_query_result == BP_RESULT_OK) && !!is_vbios_interop_enabled; + } + } + + if (dc->ctx->dce_environment == DCE_ENV_PRODUCTION_DRV) + dc->debug = debug_defaults_drv; + + // Init the vm_helper + if (dc->vm_helper) + vm_helper_init(dc->vm_helper, 16); + + /************************************************* + * Create resources * + *************************************************/ + + /* Clock Sources for Pixel Clock*/ + pool->base.clock_sources[DCN30_CLK_SRC_PLL0] = + dcn30_clock_source_create(ctx, ctx->dc_bios, + CLOCK_SOURCE_COMBO_PHY_PLL0, + &clk_src_regs[0], false); + pool->base.clock_sources[DCN30_CLK_SRC_PLL1] = + dcn30_clock_source_create(ctx, ctx->dc_bios, + CLOCK_SOURCE_COMBO_PHY_PLL1, + &clk_src_regs[1], false); + pool->base.clock_sources[DCN30_CLK_SRC_PLL2] = + dcn30_clock_source_create(ctx, ctx->dc_bios, + CLOCK_SOURCE_COMBO_PHY_PLL2, + &clk_src_regs[2], false); + pool->base.clock_sources[DCN30_CLK_SRC_PLL3] = + dcn30_clock_source_create(ctx, ctx->dc_bios, + CLOCK_SOURCE_COMBO_PHY_PLL3, + &clk_src_regs[3], false); + pool->base.clock_sources[DCN30_CLK_SRC_PLL4] = + dcn30_clock_source_create(ctx, ctx->dc_bios, + CLOCK_SOURCE_COMBO_PHY_PLL4, + &clk_src_regs[4], false); + pool->base.clock_sources[DCN30_CLK_SRC_PLL5] = + dcn30_clock_source_create(ctx, ctx->dc_bios, + CLOCK_SOURCE_COMBO_PHY_PLL5, + &clk_src_regs[5], false); + + pool->base.clk_src_count = DCN30_CLK_SRC_TOTAL; + + /* todo: not reuse phy_pll registers */ + pool->base.dp_clock_source = + dcn30_clock_source_create(ctx, ctx->dc_bios, + CLOCK_SOURCE_ID_DP_DTO, + &clk_src_regs[0], true); + + for (i = 0; i < pool->base.clk_src_count; i++) { + if (pool->base.clock_sources[i] == NULL) { + dm_error("DC: failed to create clock sources!\n"); + BREAK_TO_DEBUGGER(); + goto create_fail; + } + } + + /* DCCG */ + pool->base.dccg = dccg30_create(ctx, &dccg_regs, &dccg_shift, &dccg_mask); + if (pool->base.dccg == NULL) { + dm_error("DC: failed to create dccg!\n"); + BREAK_TO_DEBUGGER(); + goto create_fail; + } + + /* PP Lib and SMU interfaces */ + init_soc_bounding_box(dc, pool); + + num_pipes = dcn3_0_ip.max_num_dpp; + + for (i = 0; i < dcn3_0_ip.max_num_dpp; i++) + if (pipe_fuses & 1 << i) + num_pipes--; + + dcn3_0_ip.max_num_dpp = num_pipes; + dcn3_0_ip.max_num_otg = num_pipes; + + dml_init_instance(&dc->dml, &dcn3_0_soc, &dcn3_0_ip, DML_PROJECT_DCN30); + + /* IRQ */ + init_data.ctx = dc->ctx; + pool->base.irqs = dal_irq_service_dcn30_create(&init_data); + if (!pool->base.irqs) + goto create_fail; + + /* HUBBUB */ + pool->base.hubbub = dcn30_hubbub_create(ctx); + if (pool->base.hubbub == NULL) { + BREAK_TO_DEBUGGER(); + dm_error("DC: failed to create hubbub!\n"); + goto create_fail; + } + + /* HUBPs, DPPs, OPPs and TGs */ + for (i = 0; i < pool->base.pipe_count; i++) { + pool->base.hubps[i] = dcn30_hubp_create(ctx, i); + if (pool->base.hubps[i] == NULL) { + BREAK_TO_DEBUGGER(); + dm_error( + "DC: failed to create hubps!\n"); + goto create_fail; + } + + pool->base.dpps[i] = dcn30_dpp_create(ctx, i); + if (pool->base.dpps[i] == NULL) { + BREAK_TO_DEBUGGER(); + dm_error( + "DC: failed to create dpps!\n"); + goto create_fail; + } + } + + for (i = 0; i < pool->base.res_cap->num_opp; i++) { + pool->base.opps[i] = dcn30_opp_create(ctx, i); + if (pool->base.opps[i] == NULL) { + BREAK_TO_DEBUGGER(); + dm_error( + "DC: failed to create output pixel processor!\n"); + goto create_fail; + } + } + + for (i = 0; i < pool->base.res_cap->num_timing_generator; i++) { + pool->base.timing_generators[i] = dcn30_timing_generator_create( + ctx, i); + if (pool->base.timing_generators[i] == NULL) { + BREAK_TO_DEBUGGER(); + dm_error("DC: failed to create tg!\n"); + goto create_fail; + } + } + pool->base.timing_generator_count = i; + /* PSR */ + pool->base.psr = dmub_psr_create(ctx); + + if (pool->base.psr == NULL) { + dm_error("DC: failed to create PSR obj!\n"); + BREAK_TO_DEBUGGER(); + goto create_fail; + } + + /* ABM */ + for (i = 0; i < pool->base.res_cap->num_timing_generator; i++) { + pool->base.multiple_abms[i] = dmub_abm_create(ctx, + &abm_regs[i], + &abm_shift, + &abm_mask); + if (pool->base.multiple_abms[i] == NULL) { + dm_error("DC: failed to create abm for pipe %d!\n", i); + BREAK_TO_DEBUGGER(); + goto create_fail; + } + } + /* MPC and DSC */ + pool->base.mpc = dcn30_mpc_create(ctx, pool->base.mpcc_count, pool->base.res_cap->num_mpc_3dlut); + if (pool->base.mpc == NULL) { + BREAK_TO_DEBUGGER(); + dm_error("DC: failed to create mpc!\n"); + goto create_fail; + } + + for (i = 0; i < pool->base.res_cap->num_dsc; i++) { + pool->base.dscs[i] = dcn30_dsc_create(ctx, i); + if (pool->base.dscs[i] == NULL) { + BREAK_TO_DEBUGGER(); + dm_error("DC: failed to create display stream compressor %d!\n", i); + goto create_fail; + } + } + + /* DWB and MMHUBBUB */ + if (!dcn30_dwbc_create(ctx, &pool->base)) { + BREAK_TO_DEBUGGER(); + dm_error("DC: failed to create dwbc!\n"); + goto create_fail; + } + + if (!dcn30_mmhubbub_create(ctx, &pool->base)) { + BREAK_TO_DEBUGGER(); + dm_error("DC: failed to create mcif_wb!\n"); + goto create_fail; + } + + /* AUX and I2C */ + for (i = 0; i < pool->base.res_cap->num_ddc; i++) { + pool->base.engines[i] = dcn30_aux_engine_create(ctx, i); + if (pool->base.engines[i] == NULL) { + BREAK_TO_DEBUGGER(); + dm_error( + "DC:failed to create aux engine!!\n"); + goto create_fail; + } + pool->base.hw_i2cs[i] = dcn30_i2c_hw_create(ctx, i); + if (pool->base.hw_i2cs[i] == NULL) { + BREAK_TO_DEBUGGER(); + dm_error( + "DC:failed to create hw i2c!!\n"); + goto create_fail; + } + pool->base.sw_i2cs[i] = NULL; + } + + /* Audio, Stream Encoders including DIG and virtual, MPC 3D LUTs */ + if (!resource_construct(num_virtual_links, dc, &pool->base, + &res_create_funcs)) + goto create_fail; + + /* HW Sequencer and Plane caps */ + dcn30_hw_sequencer_construct(dc); + + dc->caps.max_planes = pool->base.pipe_count; + + for (i = 0; i < dc->caps.max_planes; ++i) + dc->caps.planes[i] = plane_cap; + + dc->cap_funcs = cap_funcs; + + if (dc->ctx->dc_bios->fw_info.oem_i2c_present) { + ddc_init_data.ctx = dc->ctx; + ddc_init_data.link = NULL; + ddc_init_data.id.id = dc->ctx->dc_bios->fw_info.oem_i2c_obj_id; + ddc_init_data.id.enum_id = 0; + ddc_init_data.id.type = OBJECT_TYPE_GENERIC; + pool->base.oem_device = dc->link_srv->create_ddc_service(&ddc_init_data); + } else { + pool->base.oem_device = NULL; + } + + DC_FP_END(); + + return true; + +create_fail: + + DC_FP_END(); + dcn30_resource_destruct(pool); + + return false; +} + +struct resource_pool *dcn30_create_resource_pool( + const struct dc_init_data *init_data, + struct dc *dc) +{ + struct dcn30_resource_pool *pool = + kzalloc(sizeof(struct dcn30_resource_pool), GFP_KERNEL); + + if (!pool) + return NULL; + + if (dcn30_resource_construct(init_data->num_virtual_links, dc, pool)) + return &pool->base; + + BREAK_TO_DEBUGGER(); + kfree(pool); + return NULL; +} diff --git a/drivers/gpu/drm/amd/display/dc/resource/dcn30/dcn30_resource.h b/drivers/gpu/drm/amd/display/dc/resource/dcn30/dcn30_resource.h new file mode 100644 index 000000000000..8e6b8b7368fd --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/resource/dcn30/dcn30_resource.h @@ -0,0 +1,108 @@ +/* + * Copyright 2020 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 _DCN30_RESOURCE_H_ +#define _DCN30_RESOURCE_H_ + +#include "core_types.h" + +#define TO_DCN30_RES_POOL(pool)\ + container_of(pool, struct dcn30_resource_pool, base) + +struct dc; +struct resource_pool; +struct _vcs_dpi_display_pipe_params_st; + +extern struct _vcs_dpi_ip_params_st dcn3_0_ip; +extern struct _vcs_dpi_soc_bounding_box_st dcn3_0_soc; + +struct dcn30_resource_pool { + struct resource_pool base; +}; +struct resource_pool *dcn30_create_resource_pool( + const struct dc_init_data *init_data, + struct dc *dc); + +void dcn30_set_mcif_arb_params( + struct dc *dc, + struct dc_state *context, + display_e2e_pipe_params_st *pipes, + int pipe_cnt); + +unsigned int dcn30_calc_max_scaled_time( + unsigned int time_per_pixel, + enum mmhubbub_wbif_mode mode, + unsigned int urgent_watermark); + +bool dcn30_validate_bandwidth(struct dc *dc, struct dc_state *context, + bool fast_validate); +bool dcn30_internal_validate_bw( + struct dc *dc, + struct dc_state *context, + display_e2e_pipe_params_st *pipes, + int *pipe_cnt_out, + int *vlevel_out, + bool fast_validate, + bool allow_self_refresh_only); +void dcn30_calculate_wm_and_dlg( + struct dc *dc, struct dc_state *context, + display_e2e_pipe_params_st *pipes, + int pipe_cnt, + int vlevel); +void dcn30_update_soc_for_wm_a(struct dc *dc, struct dc_state *context); +void dcn30_populate_dml_writeback_from_context( + struct dc *dc, struct resource_context *res_ctx, display_e2e_pipe_params_st *pipes); + +int dcn30_populate_dml_pipes_from_context( + struct dc *dc, struct dc_state *context, + display_e2e_pipe_params_st *pipes, + bool fast_validate); + +bool dcn30_acquire_post_bldn_3dlut( + struct resource_context *res_ctx, + const struct resource_pool *pool, + int mpcc_id, + struct dc_3dlut **lut, + struct dc_transfer_func **shaper); + +bool dcn30_release_post_bldn_3dlut( + struct resource_context *res_ctx, + const struct resource_pool *pool, + struct dc_3dlut **lut, + struct dc_transfer_func **shaper); + +enum dc_status dcn30_add_stream_to_ctx( + struct dc *dc, + struct dc_state *new_ctx, + struct dc_stream_state *dc_stream); + +void dcn30_update_bw_bounding_box(struct dc *dc, struct clk_bw_params *bw_params); + +bool dcn30_can_support_mclk_switch_using_fw_based_vblank_stretch(struct dc *dc, struct dc_state *context); +void dcn30_setup_mclk_switch_using_fw_based_vblank_stretch(struct dc *dc, struct dc_state *context); +int dcn30_find_dummy_latency_index_for_fw_based_mclk_switch(struct dc *dc, struct dc_state *context, + display_e2e_pipe_params_st *pipes, int pipe_cnt, int vlevel); + +#endif /* _DCN30_RESOURCE_H_ */ diff --git a/drivers/gpu/drm/amd/display/dc/resource/dcn301/dcn301_resource.c b/drivers/gpu/drm/amd/display/dc/resource/dcn301/dcn301_resource.c new file mode 100644 index 000000000000..511ff6b5b985 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/resource/dcn301/dcn301_resource.c @@ -0,0 +1,1728 @@ +/* + * Copyright 2019-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 "dm_services.h" +#include "dc.h" + +#include "dcn301/dcn301_init.h" + +#include "resource.h" +#include "include/irq_service_interface.h" +#include "dcn30/dcn30_resource.h" +#include "dcn301_resource.h" + +#include "dcn20/dcn20_resource.h" + +#include "dcn10/dcn10_ipp.h" +#include "dcn301/dcn301_hubbub.h" +#include "dcn30/dcn30_mpc.h" +#include "dcn30/dcn30_hubp.h" +#include "irq/dcn30/irq_service_dcn30.h" +#include "dcn30/dcn30_dpp.h" +#include "dcn301/dcn301_optc.h" +#include "dcn20/dcn20_hwseq.h" +#include "dcn30/dcn30_hwseq.h" +#include "dce110/dce110_hwseq.h" +#include "dcn30/dcn30_opp.h" +#include "dcn20/dcn20_dsc.h" +#include "dcn30/dcn30_vpg.h" +#include "dcn30/dcn30_afmt.h" +#include "dce/dce_clock_source.h" +#include "dce/dce_audio.h" +#include "dce/dce_hwseq.h" +#include "clk_mgr.h" +#include "virtual/virtual_stream_encoder.h" +#include "dce110/dce110_resource.h" +#include "dml/display_mode_vba.h" +#include "dcn301/dcn301_dccg.h" +#include "dcn10/dcn10_resource.h" +#include "dcn30/dcn30_dio_stream_encoder.h" +#include "dcn301/dcn301_dio_link_encoder.h" +#include "dcn301/dcn301_panel_cntl.h" + +#include "vangogh_ip_offset.h" + +#include "dcn30/dcn30_dwb.h" +#include "dcn30/dcn30_mmhubbub.h" + +#include "dcn/dcn_3_0_1_offset.h" +#include "dcn/dcn_3_0_1_sh_mask.h" + +#include "nbio/nbio_7_2_0_offset.h" + +#include "dpcs/dpcs_3_0_0_offset.h" +#include "dpcs/dpcs_3_0_0_sh_mask.h" + +#include "reg_helper.h" +#include "dce/dmub_abm.h" +#include "dce/dce_aux.h" +#include "dce/dce_i2c.h" + +#include "dml/dcn30/dcn30_fpu.h" + +#include "dml/dcn30/display_mode_vba_30.h" +#include "dml/dcn301/dcn301_fpu.h" +#include "vm_helper.h" +#include "dcn20/dcn20_vmid.h" +#include "amdgpu_socbb.h" + +#define TO_DCN301_RES_POOL(pool)\ + container_of(pool, struct dcn301_resource_pool, base) + +#define DC_LOGGER \ + dc->ctx->logger +#define DC_LOGGER_INIT(logger) + +enum dcn301_clk_src_array_id { + DCN301_CLK_SRC_PLL0, + DCN301_CLK_SRC_PLL1, + DCN301_CLK_SRC_PLL2, + DCN301_CLK_SRC_PLL3, + DCN301_CLK_SRC_TOTAL +}; + +/* begin ********************* + * macros to expend register list macro defined in HW object header file + */ + +/* DCN */ +#define BASE_INNER(seg) DCN_BASE__INST0_SEG ## seg + +#define BASE(seg) BASE_INNER(seg) + +#define SR(reg_name)\ + .reg_name = BASE(mm ## reg_name ## _BASE_IDX) + \ + mm ## reg_name + +#define SRI(reg_name, block, id)\ + .reg_name = BASE(mm ## block ## id ## _ ## reg_name ## _BASE_IDX) + \ + mm ## block ## id ## _ ## reg_name + +#define SRI2(reg_name, block, id)\ + .reg_name = BASE(mm ## reg_name ## _BASE_IDX) + \ + mm ## reg_name + +#define SRIR(var_name, reg_name, block, id)\ + .var_name = BASE(mm ## block ## id ## _ ## reg_name ## _BASE_IDX) + \ + mm ## block ## id ## _ ## reg_name + +#define SRII(reg_name, block, id)\ + .reg_name[id] = BASE(mm ## block ## id ## _ ## reg_name ## _BASE_IDX) + \ + mm ## block ## id ## _ ## reg_name + +#define SRII2(reg_name_pre, reg_name_post, id)\ + .reg_name_pre ## _ ## reg_name_post[id] = BASE(mm ## reg_name_pre \ + ## id ## _ ## reg_name_post ## _BASE_IDX) + \ + mm ## reg_name_pre ## id ## _ ## reg_name_post + +#define SRII_MPC_RMU(reg_name, block, id)\ + .RMU##_##reg_name[id] = BASE(mm ## block ## id ## _ ## reg_name ## _BASE_IDX) + \ + mm ## block ## id ## _ ## reg_name + +#define SRII_DWB(reg_name, temp_name, block, id)\ + .reg_name[id] = BASE(mm ## block ## id ## _ ## temp_name ## _BASE_IDX) + \ + mm ## block ## id ## _ ## temp_name + +#define SF_DWB2(reg_name, block, id, field_name, post_fix) \ + .field_name = reg_name ## __ ## field_name ## post_fix + +#define DCCG_SRII(reg_name, block, id)\ + .block ## _ ## reg_name[id] = BASE(mm ## block ## id ## _ ## reg_name ## _BASE_IDX) + \ + mm ## block ## id ## _ ## reg_name + +#define VUPDATE_SRII(reg_name, block, id)\ + .reg_name[id] = BASE(mm ## reg_name ## _ ## block ## id ## _BASE_IDX) + \ + mm ## reg_name ## _ ## block ## id + +/* NBIO */ +#define NBIO_BASE_INNER(seg) \ + NBIO_BASE__INST0_SEG ## seg + +#define NBIO_BASE(seg) \ + NBIO_BASE_INNER(seg) + +#define NBIO_SR(reg_name)\ + .reg_name = NBIO_BASE(regBIF_BX0_ ## reg_name ## _BASE_IDX) + \ + regBIF_BX0_ ## reg_name + +/* MMHUB */ +#define MMHUB_BASE_INNER(seg) \ + MMHUB_BASE__INST0_SEG ## seg + +#define MMHUB_BASE(seg) \ + MMHUB_BASE_INNER(seg) + +#define MMHUB_SR(reg_name)\ + .reg_name = MMHUB_BASE(regMM ## reg_name ## _BASE_IDX) + \ + regMM ## reg_name + +/* CLOCK */ +#define CLK_BASE_INNER(seg) \ + CLK_BASE__INST0_SEG ## seg + +#define CLK_BASE(seg) \ + CLK_BASE_INNER(seg) + +#define CLK_SRI(reg_name, block, inst)\ + .reg_name = CLK_BASE(mm ## block ## _ ## inst ## _ ## reg_name ## _BASE_IDX) + \ + mm ## block ## _ ## inst ## _ ## reg_name + +static const struct bios_registers bios_regs = { + NBIO_SR(BIOS_SCRATCH_3), + NBIO_SR(BIOS_SCRATCH_6) +}; + +#define clk_src_regs(index, pllid)\ +[index] = {\ + CS_COMMON_REG_LIST_DCN3_01(index, pllid),\ +} + +static const struct dce110_clk_src_regs clk_src_regs[] = { + clk_src_regs(0, A), + clk_src_regs(1, B), + clk_src_regs(2, C), + clk_src_regs(3, D) +}; + +static const struct dce110_clk_src_shift cs_shift = { + CS_COMMON_MASK_SH_LIST_DCN2_0(__SHIFT) +}; + +static const struct dce110_clk_src_mask cs_mask = { + CS_COMMON_MASK_SH_LIST_DCN2_0(_MASK) +}; + +#define abm_regs(id)\ +[id] = {\ + ABM_DCN301_REG_LIST(id)\ +} + +static const struct dce_abm_registers abm_regs[] = { + abm_regs(0), + abm_regs(1), + abm_regs(2), + abm_regs(3), +}; + +static const struct dce_abm_shift abm_shift = { + ABM_MASK_SH_LIST_DCN30(__SHIFT) +}; + +static const struct dce_abm_mask abm_mask = { + ABM_MASK_SH_LIST_DCN30(_MASK) +}; + +#define audio_regs(id)\ +[id] = {\ + AUD_COMMON_REG_LIST(id)\ +} + +static const struct dce_audio_registers audio_regs[] = { + audio_regs(0), + audio_regs(1), + audio_regs(2), + audio_regs(3), + audio_regs(4), + audio_regs(5), + audio_regs(6) +}; + +#define DCE120_AUD_COMMON_MASK_SH_LIST(mask_sh)\ + SF(AZF0ENDPOINT0_AZALIA_F0_CODEC_ENDPOINT_INDEX, AZALIA_ENDPOINT_REG_INDEX, mask_sh),\ + SF(AZF0ENDPOINT0_AZALIA_F0_CODEC_ENDPOINT_DATA, AZALIA_ENDPOINT_REG_DATA, mask_sh),\ + AUD_COMMON_MASK_SH_LIST_BASE(mask_sh) + +static const struct dce_audio_shift audio_shift = { + DCE120_AUD_COMMON_MASK_SH_LIST(__SHIFT) +}; + +static const struct dce_audio_mask audio_mask = { + DCE120_AUD_COMMON_MASK_SH_LIST(_MASK) +}; + +#define vpg_regs(id)\ +[id] = {\ + VPG_DCN3_REG_LIST(id)\ +} + +static const struct dcn30_vpg_registers vpg_regs[] = { + vpg_regs(0), + vpg_regs(1), + vpg_regs(2), + vpg_regs(3), +}; + +static const struct dcn30_vpg_shift vpg_shift = { + DCN3_VPG_MASK_SH_LIST(__SHIFT) +}; + +static const struct dcn30_vpg_mask vpg_mask = { + DCN3_VPG_MASK_SH_LIST(_MASK) +}; + +#define afmt_regs(id)\ +[id] = {\ + AFMT_DCN3_REG_LIST(id)\ +} + +static const struct dcn30_afmt_registers afmt_regs[] = { + afmt_regs(0), + afmt_regs(1), + afmt_regs(2), + afmt_regs(3), +}; + +static const struct dcn30_afmt_shift afmt_shift = { + DCN3_AFMT_MASK_SH_LIST(__SHIFT) +}; + +static const struct dcn30_afmt_mask afmt_mask = { + DCN3_AFMT_MASK_SH_LIST(_MASK) +}; + +#define stream_enc_regs(id)\ +[id] = {\ + SE_DCN3_REG_LIST(id)\ +} + +static const struct dcn10_stream_enc_registers stream_enc_regs[] = { + stream_enc_regs(0), + stream_enc_regs(1), + stream_enc_regs(2), + stream_enc_regs(3), +}; + +static const struct dcn10_stream_encoder_shift se_shift = { + SE_COMMON_MASK_SH_LIST_DCN30(__SHIFT) +}; + +static const struct dcn10_stream_encoder_mask se_mask = { + SE_COMMON_MASK_SH_LIST_DCN30(_MASK) +}; + + +#define aux_regs(id)\ +[id] = {\ + DCN2_AUX_REG_LIST(id)\ +} + +static const struct dcn10_link_enc_aux_registers link_enc_aux_regs[] = { + aux_regs(0), + aux_regs(1), + aux_regs(2), + aux_regs(3), +}; + +#define hpd_regs(id)\ +[id] = {\ + HPD_REG_LIST(id)\ +} + +static const struct dcn10_link_enc_hpd_registers link_enc_hpd_regs[] = { + hpd_regs(0), + hpd_regs(1), + hpd_regs(2), + hpd_regs(3), +}; + + +#define link_regs(id, phyid)\ +[id] = {\ + LE_DCN301_REG_LIST(id), \ + UNIPHY_DCN2_REG_LIST(phyid), \ + DPCS_DCN2_REG_LIST(id), \ + SRI(DP_DPHY_INTERNAL_CTRL, DP, id) \ +} + +static const struct dce110_aux_registers_shift aux_shift = { + DCN_AUX_MASK_SH_LIST(__SHIFT) +}; + +static const struct dce110_aux_registers_mask aux_mask = { + DCN_AUX_MASK_SH_LIST(_MASK) +}; + +static const struct dcn10_link_enc_registers link_enc_regs[] = { + link_regs(0, A), + link_regs(1, B), + link_regs(2, C), + link_regs(3, D), +}; + +static const struct dcn10_link_enc_shift le_shift = { + LINK_ENCODER_MASK_SH_LIST_DCN301(__SHIFT),\ + DPCS_DCN2_MASK_SH_LIST(__SHIFT) +}; + +static const struct dcn10_link_enc_mask le_mask = { + LINK_ENCODER_MASK_SH_LIST_DCN301(_MASK),\ + DPCS_DCN2_MASK_SH_LIST(_MASK) +}; + +#define panel_cntl_regs(id)\ +[id] = {\ + DCN301_PANEL_CNTL_REG_LIST(id),\ +} + +static const struct dce_panel_cntl_registers panel_cntl_regs[] = { + panel_cntl_regs(0), + panel_cntl_regs(1), +}; + +static const struct dcn301_panel_cntl_shift panel_cntl_shift = { + DCN301_PANEL_CNTL_MASK_SH_LIST(__SHIFT) +}; + +static const struct dcn301_panel_cntl_mask panel_cntl_mask = { + DCN301_PANEL_CNTL_MASK_SH_LIST(_MASK) +}; + +#define dpp_regs(id)\ +[id] = {\ + DPP_REG_LIST_DCN30(id),\ +} + +static const struct dcn3_dpp_registers dpp_regs[] = { + dpp_regs(0), + dpp_regs(1), + dpp_regs(2), + dpp_regs(3), +}; + +static const struct dcn3_dpp_shift tf_shift = { + DPP_REG_LIST_SH_MASK_DCN30(__SHIFT) +}; + +static const struct dcn3_dpp_mask tf_mask = { + DPP_REG_LIST_SH_MASK_DCN30(_MASK) +}; + +#define opp_regs(id)\ +[id] = {\ + OPP_REG_LIST_DCN30(id),\ +} + +static const struct dcn20_opp_registers opp_regs[] = { + opp_regs(0), + opp_regs(1), + opp_regs(2), + opp_regs(3), +}; + +static const struct dcn20_opp_shift opp_shift = { + OPP_MASK_SH_LIST_DCN20(__SHIFT) +}; + +static const struct dcn20_opp_mask opp_mask = { + OPP_MASK_SH_LIST_DCN20(_MASK) +}; + +#define aux_engine_regs(id)\ +[id] = {\ + AUX_COMMON_REG_LIST0(id), \ + .AUXN_IMPCAL = 0, \ + .AUXP_IMPCAL = 0, \ + .AUX_RESET_MASK = DP_AUX0_AUX_CONTROL__AUX_RESET_MASK, \ +} + +static const struct dce110_aux_registers aux_engine_regs[] = { + aux_engine_regs(0), + aux_engine_regs(1), + aux_engine_regs(2), + aux_engine_regs(3), +}; + +#define dwbc_regs_dcn3(id)\ +[id] = {\ + DWBC_COMMON_REG_LIST_DCN30(id),\ +} + +static const struct dcn30_dwbc_registers dwbc30_regs[] = { + dwbc_regs_dcn3(0), +}; + +static const struct dcn30_dwbc_shift dwbc30_shift = { + DWBC_COMMON_MASK_SH_LIST_DCN30(__SHIFT) +}; + +static const struct dcn30_dwbc_mask dwbc30_mask = { + DWBC_COMMON_MASK_SH_LIST_DCN30(_MASK) +}; + +#define mcif_wb_regs_dcn3(id)\ +[id] = {\ + MCIF_WB_COMMON_REG_LIST_DCN30(id),\ +} + +static const struct dcn30_mmhubbub_registers mcif_wb30_regs[] = { + mcif_wb_regs_dcn3(0) +}; + +static const struct dcn30_mmhubbub_shift mcif_wb30_shift = { + MCIF_WB_COMMON_MASK_SH_LIST_DCN30(__SHIFT) +}; + +static const struct dcn30_mmhubbub_mask mcif_wb30_mask = { + MCIF_WB_COMMON_MASK_SH_LIST_DCN30(_MASK) +}; + +#define dsc_regsDCN20(id)\ +[id] = {\ + DSC_REG_LIST_DCN20(id)\ +} + +static const struct dcn20_dsc_registers dsc_regs[] = { + dsc_regsDCN20(0), + dsc_regsDCN20(1), + dsc_regsDCN20(2), +}; + +static const struct dcn20_dsc_shift dsc_shift = { + DSC_REG_LIST_SH_MASK_DCN20(__SHIFT) +}; + +static const struct dcn20_dsc_mask dsc_mask = { + DSC_REG_LIST_SH_MASK_DCN20(_MASK) +}; + +static const struct dcn30_mpc_registers mpc_regs = { + MPC_REG_LIST_DCN3_0(0), + MPC_REG_LIST_DCN3_0(1), + MPC_REG_LIST_DCN3_0(2), + MPC_REG_LIST_DCN3_0(3), + MPC_OUT_MUX_REG_LIST_DCN3_0(0), + MPC_OUT_MUX_REG_LIST_DCN3_0(1), + MPC_OUT_MUX_REG_LIST_DCN3_0(2), + MPC_OUT_MUX_REG_LIST_DCN3_0(3), + MPC_RMU_GLOBAL_REG_LIST_DCN3AG, + MPC_RMU_REG_LIST_DCN3AG(0), + MPC_RMU_REG_LIST_DCN3AG(1), + MPC_DWB_MUX_REG_LIST_DCN3_0(0), +}; + +static const struct dcn30_mpc_shift mpc_shift = { + MPC_COMMON_MASK_SH_LIST_DCN30(__SHIFT) +}; + +static const struct dcn30_mpc_mask mpc_mask = { + MPC_COMMON_MASK_SH_LIST_DCN30(_MASK) +}; + +#define optc_regs(id)\ +[id] = {OPTC_COMMON_REG_LIST_DCN3_0(id)} + + +static const struct dcn_optc_registers optc_regs[] = { + optc_regs(0), + optc_regs(1), + optc_regs(2), + optc_regs(3), +}; + +static const struct dcn_optc_shift optc_shift = { + OPTC_COMMON_MASK_SH_LIST_DCN30(__SHIFT) +}; + +static const struct dcn_optc_mask optc_mask = { + OPTC_COMMON_MASK_SH_LIST_DCN30(_MASK) +}; + +#define hubp_regs(id)\ +[id] = {\ + HUBP_REG_LIST_DCN30(id)\ +} + +static const struct dcn_hubp2_registers hubp_regs[] = { + hubp_regs(0), + hubp_regs(1), + hubp_regs(2), + hubp_regs(3), +}; + +static const struct dcn_hubp2_shift hubp_shift = { + HUBP_MASK_SH_LIST_DCN30(__SHIFT) +}; + +static const struct dcn_hubp2_mask hubp_mask = { + HUBP_MASK_SH_LIST_DCN30(_MASK) +}; + +static const struct dcn_hubbub_registers hubbub_reg = { + HUBBUB_REG_LIST_DCN301(0) +}; + +static const struct dcn_hubbub_shift hubbub_shift = { + HUBBUB_MASK_SH_LIST_DCN301(__SHIFT) +}; + +static const struct dcn_hubbub_mask hubbub_mask = { + HUBBUB_MASK_SH_LIST_DCN301(_MASK) +}; + +static const struct dccg_registers dccg_regs = { + DCCG_REG_LIST_DCN301() +}; + +static const struct dccg_shift dccg_shift = { + DCCG_MASK_SH_LIST_DCN301(__SHIFT) +}; + +static const struct dccg_mask dccg_mask = { + DCCG_MASK_SH_LIST_DCN301(_MASK) +}; + +static const struct dce_hwseq_registers hwseq_reg = { + HWSEQ_DCN301_REG_LIST() +}; + +static const struct dce_hwseq_shift hwseq_shift = { + HWSEQ_DCN301_MASK_SH_LIST(__SHIFT) +}; + +static const struct dce_hwseq_mask hwseq_mask = { + HWSEQ_DCN301_MASK_SH_LIST(_MASK) +}; +#define vmid_regs(id)\ +[id] = {\ + DCN20_VMID_REG_LIST(id)\ +} + +static const struct dcn_vmid_registers vmid_regs[] = { + vmid_regs(0), + vmid_regs(1), + vmid_regs(2), + vmid_regs(3), + vmid_regs(4), + vmid_regs(5), + vmid_regs(6), + vmid_regs(7), + vmid_regs(8), + vmid_regs(9), + vmid_regs(10), + vmid_regs(11), + vmid_regs(12), + vmid_regs(13), + vmid_regs(14), + vmid_regs(15) +}; + +static const struct dcn20_vmid_shift vmid_shifts = { + DCN20_VMID_MASK_SH_LIST(__SHIFT) +}; + +static const struct dcn20_vmid_mask vmid_masks = { + DCN20_VMID_MASK_SH_LIST(_MASK) +}; + +static struct resource_caps res_cap_dcn301 = { + .num_timing_generator = 4, + .num_opp = 4, + .num_video_plane = 4, + .num_audio = 4, + .num_stream_encoder = 4, + .num_pll = 4, + .num_dwb = 1, + .num_ddc = 4, + .num_vmid = 16, + .num_mpc_3dlut = 2, + .num_dsc = 3, +}; + +static const struct dc_plane_cap plane_cap = { + .type = DC_PLANE_TYPE_DCN_UNIVERSAL, + .per_pixel_alpha = true, + + .pixel_format_support = { + .argb8888 = true, + .nv12 = true, + .fp16 = true, + .p010 = true, + .ayuv = false, + }, + + .max_upscale_factor = { + .argb8888 = 16000, + .nv12 = 16000, + .fp16 = 16000 + }, + + /* 6:1 downscaling ratio: 1000/6 = 166.666 */ + .max_downscale_factor = { + .argb8888 = 167, + .nv12 = 167, + .fp16 = 167 + }, + 64, + 64 +}; + +static const struct dc_debug_options debug_defaults_drv = { + .disable_dmcu = true, + .force_abm_enable = false, + .timing_trace = false, + .clock_trace = true, + .disable_dpp_power_gate = false, + .disable_hubp_power_gate = false, + .disable_clock_gate = true, + .disable_pplib_clock_request = true, + .disable_pplib_wm_range = true, + .pipe_split_policy = MPC_SPLIT_DYNAMIC, + .force_single_disp_pipe_split = false, + .disable_dcc = DCC_ENABLE, + .vsr_support = true, + .performance_trace = false, + .max_downscale_src_width = 7680,/*upto 8K*/ + .scl_reset_length10 = true, + .sanity_checks = false, + .underflow_assert_delay_us = 0xFFFFFFFF, + .dwb_fi_phase = -1, // -1 = disable + .dmub_command_table = true, + .use_max_lb = false, + .exit_idle_opt_for_cursor_updates = true, + .using_dml2 = false, +}; + +static void dcn301_dpp_destroy(struct dpp **dpp) +{ + kfree(TO_DCN20_DPP(*dpp)); + *dpp = NULL; +} + +static struct dpp *dcn301_dpp_create(struct dc_context *ctx, uint32_t inst) +{ + struct dcn3_dpp *dpp = + kzalloc(sizeof(struct dcn3_dpp), GFP_KERNEL); + + if (!dpp) + return NULL; + + if (dpp3_construct(dpp, ctx, inst, + &dpp_regs[inst], &tf_shift, &tf_mask)) + return &dpp->base; + + BREAK_TO_DEBUGGER(); + kfree(dpp); + return NULL; +} +static struct output_pixel_processor *dcn301_opp_create(struct dc_context *ctx, + uint32_t inst) +{ + struct dcn20_opp *opp = + kzalloc(sizeof(struct dcn20_opp), GFP_KERNEL); + + if (!opp) { + BREAK_TO_DEBUGGER(); + return NULL; + } + + dcn20_opp_construct(opp, ctx, inst, + &opp_regs[inst], &opp_shift, &opp_mask); + return &opp->base; +} + +static struct dce_aux *dcn301_aux_engine_create(struct dc_context *ctx, uint32_t inst) +{ + struct aux_engine_dce110 *aux_engine = + kzalloc(sizeof(struct aux_engine_dce110), GFP_KERNEL); + + if (!aux_engine) + return NULL; + + dce110_aux_engine_construct(aux_engine, ctx, inst, + SW_AUX_TIMEOUT_PERIOD_MULTIPLIER * AUX_TIMEOUT_PERIOD, + &aux_engine_regs[inst], + &aux_mask, + &aux_shift, + ctx->dc->caps.extended_aux_timeout_support); + + return &aux_engine->base; +} +#define i2c_inst_regs(id) { I2C_HW_ENGINE_COMMON_REG_LIST(id) } + +static const struct dce_i2c_registers i2c_hw_regs[] = { + i2c_inst_regs(1), + i2c_inst_regs(2), + i2c_inst_regs(3), + i2c_inst_regs(4), +}; + +static const struct dce_i2c_shift i2c_shifts = { + I2C_COMMON_MASK_SH_LIST_DCN2(__SHIFT) +}; + +static const struct dce_i2c_mask i2c_masks = { + I2C_COMMON_MASK_SH_LIST_DCN2(_MASK) +}; + +static struct dce_i2c_hw *dcn301_i2c_hw_create(struct dc_context *ctx, uint32_t inst) +{ + struct dce_i2c_hw *dce_i2c_hw = + kzalloc(sizeof(struct dce_i2c_hw), GFP_KERNEL); + + if (!dce_i2c_hw) + return NULL; + + dcn2_i2c_hw_construct(dce_i2c_hw, ctx, inst, + &i2c_hw_regs[inst], &i2c_shifts, &i2c_masks); + + return dce_i2c_hw; +} +static struct mpc *dcn301_mpc_create( + struct dc_context *ctx, + int num_mpcc, + int num_rmu) +{ + struct dcn30_mpc *mpc30 = kzalloc(sizeof(struct dcn30_mpc), + GFP_KERNEL); + + if (!mpc30) + return NULL; + + dcn30_mpc_construct(mpc30, ctx, + &mpc_regs, + &mpc_shift, + &mpc_mask, + num_mpcc, + num_rmu); + + return &mpc30->base; +} + +static struct hubbub *dcn301_hubbub_create(struct dc_context *ctx) +{ + int i; + + struct dcn20_hubbub *hubbub3 = kzalloc(sizeof(struct dcn20_hubbub), + GFP_KERNEL); + + if (!hubbub3) + return NULL; + + hubbub301_construct(hubbub3, ctx, + &hubbub_reg, + &hubbub_shift, + &hubbub_mask); + + + for (i = 0; i < res_cap_dcn301.num_vmid; i++) { + struct dcn20_vmid *vmid = &hubbub3->vmid[i]; + + vmid->ctx = ctx; + + vmid->regs = &vmid_regs[i]; + vmid->shifts = &vmid_shifts; + vmid->masks = &vmid_masks; + } + + hubbub3->num_vmid = res_cap_dcn301.num_vmid; + + return &hubbub3->base; +} + +static struct timing_generator *dcn301_timing_generator_create( + struct dc_context *ctx, uint32_t instance) +{ + struct optc *tgn10 = + kzalloc(sizeof(struct optc), GFP_KERNEL); + + if (!tgn10) + return NULL; + + tgn10->base.inst = instance; + tgn10->base.ctx = ctx; + + tgn10->tg_regs = &optc_regs[instance]; + tgn10->tg_shift = &optc_shift; + tgn10->tg_mask = &optc_mask; + + dcn301_timing_generator_init(tgn10); + + return &tgn10->base; +} + +static const struct encoder_feature_support link_enc_feature = { + .max_hdmi_deep_color = COLOR_DEPTH_121212, + .max_hdmi_pixel_clock = 600000, + .hdmi_ycbcr420_supported = true, + .dp_ycbcr420_supported = true, + .fec_supported = true, + .flags.bits.IS_HBR2_CAPABLE = true, + .flags.bits.IS_HBR3_CAPABLE = true, + .flags.bits.IS_TPS3_CAPABLE = true, + .flags.bits.IS_TPS4_CAPABLE = true +}; + +static struct link_encoder *dcn301_link_encoder_create( + struct dc_context *ctx, + const struct encoder_init_data *enc_init_data) +{ + struct dcn20_link_encoder *enc20 = + kzalloc(sizeof(struct dcn20_link_encoder), GFP_KERNEL); + + if (!enc20) + return NULL; + + dcn301_link_encoder_construct(enc20, + enc_init_data, + &link_enc_feature, + &link_enc_regs[enc_init_data->transmitter], + &link_enc_aux_regs[enc_init_data->channel - 1], + &link_enc_hpd_regs[enc_init_data->hpd_source], + &le_shift, + &le_mask); + + return &enc20->enc10.base; +} + +static struct panel_cntl *dcn301_panel_cntl_create(const struct panel_cntl_init_data *init_data) +{ + struct dcn301_panel_cntl *panel_cntl = + kzalloc(sizeof(struct dcn301_panel_cntl), GFP_KERNEL); + + if (!panel_cntl) + return NULL; + + dcn301_panel_cntl_construct(panel_cntl, + init_data, + &panel_cntl_regs[init_data->inst], + &panel_cntl_shift, + &panel_cntl_mask); + + return &panel_cntl->base; +} + + +#define CTX ctx + +#define REG(reg_name) \ + (DCN_BASE.instance[0].segment[mm ## reg_name ## _BASE_IDX] + mm ## reg_name) + +static uint32_t read_pipe_fuses(struct dc_context *ctx) +{ + uint32_t value = REG_READ(CC_DC_PIPE_DIS); + /* RV1 support max 4 pipes */ + value = value & 0xf; + return value; +} + + +static void read_dce_straps( + struct dc_context *ctx, + struct resource_straps *straps) +{ + generic_reg_get(ctx, mmDC_PINSTRAPS + BASE(mmDC_PINSTRAPS_BASE_IDX), + FN(DC_PINSTRAPS, DC_PINSTRAPS_AUDIO), &straps->dc_pinstraps_audio); + +} + +static struct audio *dcn301_create_audio( + struct dc_context *ctx, unsigned int inst) +{ + return dce_audio_create(ctx, inst, + &audio_regs[inst], &audio_shift, &audio_mask); +} + +static struct vpg *dcn301_vpg_create( + struct dc_context *ctx, + uint32_t inst) +{ + struct dcn30_vpg *vpg3 = kzalloc(sizeof(struct dcn30_vpg), GFP_KERNEL); + + if (!vpg3) + return NULL; + + vpg3_construct(vpg3, ctx, inst, + &vpg_regs[inst], + &vpg_shift, + &vpg_mask); + + return &vpg3->base; +} + +static struct afmt *dcn301_afmt_create( + struct dc_context *ctx, + uint32_t inst) +{ + struct dcn30_afmt *afmt3 = kzalloc(sizeof(struct dcn30_afmt), GFP_KERNEL); + + if (!afmt3) + return NULL; + + afmt3_construct(afmt3, ctx, inst, + &afmt_regs[inst], + &afmt_shift, + &afmt_mask); + + return &afmt3->base; +} + +static struct stream_encoder *dcn301_stream_encoder_create(enum engine_id eng_id, + struct dc_context *ctx) +{ + struct dcn10_stream_encoder *enc1; + struct vpg *vpg; + struct afmt *afmt; + int vpg_inst; + int afmt_inst; + + /* Mapping of VPG, AFMT, DME register blocks to DIO block instance */ + if (eng_id <= ENGINE_ID_DIGF) { + vpg_inst = eng_id; + afmt_inst = eng_id; + } else + return NULL; + + enc1 = kzalloc(sizeof(struct dcn10_stream_encoder), GFP_KERNEL); + vpg = dcn301_vpg_create(ctx, vpg_inst); + afmt = dcn301_afmt_create(ctx, afmt_inst); + + if (!enc1 || !vpg || !afmt) { + kfree(enc1); + kfree(vpg); + kfree(afmt); + return NULL; + } + + dcn30_dio_stream_encoder_construct(enc1, ctx, ctx->dc_bios, + eng_id, vpg, afmt, + &stream_enc_regs[eng_id], + &se_shift, &se_mask); + + return &enc1->base; +} + +static struct dce_hwseq *dcn301_hwseq_create(struct dc_context *ctx) +{ + struct dce_hwseq *hws = kzalloc(sizeof(struct dce_hwseq), GFP_KERNEL); + + if (hws) { + hws->ctx = ctx; + hws->regs = &hwseq_reg; + hws->shifts = &hwseq_shift; + hws->masks = &hwseq_mask; + } + return hws; +} +static const struct resource_create_funcs res_create_funcs = { + .read_dce_straps = read_dce_straps, + .create_audio = dcn301_create_audio, + .create_stream_encoder = dcn301_stream_encoder_create, + .create_hwseq = dcn301_hwseq_create, +}; + +static void dcn301_destruct(struct dcn301_resource_pool *pool) +{ + unsigned int i; + + for (i = 0; i < pool->base.stream_enc_count; i++) { + if (pool->base.stream_enc[i] != NULL) { + if (pool->base.stream_enc[i]->vpg != NULL) { + kfree(DCN30_VPG_FROM_VPG(pool->base.stream_enc[i]->vpg)); + pool->base.stream_enc[i]->vpg = NULL; + } + if (pool->base.stream_enc[i]->afmt != NULL) { + kfree(DCN30_AFMT_FROM_AFMT(pool->base.stream_enc[i]->afmt)); + pool->base.stream_enc[i]->afmt = NULL; + } + kfree(DCN10STRENC_FROM_STRENC(pool->base.stream_enc[i])); + pool->base.stream_enc[i] = NULL; + } + } + + for (i = 0; i < pool->base.res_cap->num_dsc; i++) { + if (pool->base.dscs[i] != NULL) + dcn20_dsc_destroy(&pool->base.dscs[i]); + } + + if (pool->base.mpc != NULL) { + kfree(TO_DCN20_MPC(pool->base.mpc)); + pool->base.mpc = NULL; + } + if (pool->base.hubbub != NULL) { + kfree(pool->base.hubbub); + pool->base.hubbub = NULL; + } + for (i = 0; i < pool->base.pipe_count; i++) { + if (pool->base.dpps[i] != NULL) + dcn301_dpp_destroy(&pool->base.dpps[i]); + + if (pool->base.ipps[i] != NULL) + pool->base.ipps[i]->funcs->ipp_destroy(&pool->base.ipps[i]); + + if (pool->base.hubps[i] != NULL) { + kfree(TO_DCN20_HUBP(pool->base.hubps[i])); + pool->base.hubps[i] = NULL; + } + + if (pool->base.irqs != NULL) { + dal_irq_service_destroy(&pool->base.irqs); + } + } + + for (i = 0; i < pool->base.res_cap->num_ddc; i++) { + if (pool->base.engines[i] != NULL) + dce110_engine_destroy(&pool->base.engines[i]); + if (pool->base.hw_i2cs[i] != NULL) { + kfree(pool->base.hw_i2cs[i]); + pool->base.hw_i2cs[i] = NULL; + } + if (pool->base.sw_i2cs[i] != NULL) { + kfree(pool->base.sw_i2cs[i]); + pool->base.sw_i2cs[i] = NULL; + } + } + + for (i = 0; i < pool->base.res_cap->num_opp; i++) { + if (pool->base.opps[i] != NULL) + pool->base.opps[i]->funcs->opp_destroy(&pool->base.opps[i]); + } + + for (i = 0; i < pool->base.res_cap->num_timing_generator; i++) { + if (pool->base.timing_generators[i] != NULL) { + kfree(DCN10TG_FROM_TG(pool->base.timing_generators[i])); + pool->base.timing_generators[i] = NULL; + } + } + + for (i = 0; i < pool->base.res_cap->num_dwb; i++) { + if (pool->base.dwbc[i] != NULL) { + kfree(TO_DCN30_DWBC(pool->base.dwbc[i])); + pool->base.dwbc[i] = NULL; + } + if (pool->base.mcif_wb[i] != NULL) { + kfree(TO_DCN30_MMHUBBUB(pool->base.mcif_wb[i])); + pool->base.mcif_wb[i] = NULL; + } + } + + for (i = 0; i < pool->base.audio_count; i++) { + if (pool->base.audios[i]) + dce_aud_destroy(&pool->base.audios[i]); + } + + for (i = 0; i < pool->base.clk_src_count; i++) { + if (pool->base.clock_sources[i] != NULL) { + dcn20_clock_source_destroy(&pool->base.clock_sources[i]); + pool->base.clock_sources[i] = NULL; + } + } + + for (i = 0; i < pool->base.res_cap->num_mpc_3dlut; i++) { + if (pool->base.mpc_lut[i] != NULL) { + dc_3dlut_func_release(pool->base.mpc_lut[i]); + pool->base.mpc_lut[i] = NULL; + } + if (pool->base.mpc_shaper[i] != NULL) { + dc_transfer_func_release(pool->base.mpc_shaper[i]); + pool->base.mpc_shaper[i] = NULL; + } + } + + if (pool->base.dp_clock_source != NULL) { + dcn20_clock_source_destroy(&pool->base.dp_clock_source); + pool->base.dp_clock_source = NULL; + } + + for (i = 0; i < pool->base.res_cap->num_timing_generator; i++) { + if (pool->base.multiple_abms[i] != NULL) + dce_abm_destroy(&pool->base.multiple_abms[i]); + } + + if (pool->base.dccg != NULL) + dcn_dccg_destroy(&pool->base.dccg); +} + +static struct hubp *dcn301_hubp_create(struct dc_context *ctx, uint32_t inst) +{ + struct dcn20_hubp *hubp2 = + kzalloc(sizeof(struct dcn20_hubp), GFP_KERNEL); + + if (!hubp2) + return NULL; + + if (hubp3_construct(hubp2, ctx, inst, + &hubp_regs[inst], &hubp_shift, &hubp_mask)) + return &hubp2->base; + + BREAK_TO_DEBUGGER(); + kfree(hubp2); + return NULL; +} + +static bool dcn301_dwbc_create(struct dc_context *ctx, struct resource_pool *pool) +{ + int i; + uint32_t pipe_count = pool->res_cap->num_dwb; + + for (i = 0; i < pipe_count; i++) { + struct dcn30_dwbc *dwbc30 = kzalloc(sizeof(struct dcn30_dwbc), + GFP_KERNEL); + + if (!dwbc30) { + dm_error("DC: failed to create dwbc30!\n"); + return false; + } + + dcn30_dwbc_construct(dwbc30, ctx, + &dwbc30_regs[i], + &dwbc30_shift, + &dwbc30_mask, + i); + + pool->dwbc[i] = &dwbc30->base; + } + return true; +} + +static bool dcn301_mmhubbub_create(struct dc_context *ctx, struct resource_pool *pool) +{ + int i; + uint32_t pipe_count = pool->res_cap->num_dwb; + + for (i = 0; i < pipe_count; i++) { + struct dcn30_mmhubbub *mcif_wb30 = kzalloc(sizeof(struct dcn30_mmhubbub), + GFP_KERNEL); + + if (!mcif_wb30) { + dm_error("DC: failed to create mcif_wb30!\n"); + return false; + } + + dcn30_mmhubbub_construct(mcif_wb30, ctx, + &mcif_wb30_regs[i], + &mcif_wb30_shift, + &mcif_wb30_mask, + i); + + pool->mcif_wb[i] = &mcif_wb30->base; + } + return true; +} + +static struct display_stream_compressor *dcn301_dsc_create( + struct dc_context *ctx, uint32_t inst) +{ + struct dcn20_dsc *dsc = + kzalloc(sizeof(struct dcn20_dsc), GFP_KERNEL); + + if (!dsc) { + BREAK_TO_DEBUGGER(); + return NULL; + } + + dsc2_construct(dsc, ctx, inst, &dsc_regs[inst], &dsc_shift, &dsc_mask); + return &dsc->base; +} + + +static void dcn301_destroy_resource_pool(struct resource_pool **pool) +{ + struct dcn301_resource_pool *dcn301_pool = TO_DCN301_RES_POOL(*pool); + + dcn301_destruct(dcn301_pool); + kfree(dcn301_pool); + *pool = NULL; +} + +static struct clock_source *dcn301_clock_source_create( + struct dc_context *ctx, + struct dc_bios *bios, + enum clock_source_id id, + const struct dce110_clk_src_regs *regs, + bool dp_clk_src) +{ + struct dce110_clk_src *clk_src = + kzalloc(sizeof(struct dce110_clk_src), GFP_KERNEL); + + if (!clk_src) + return NULL; + + if (dcn301_clk_src_construct(clk_src, ctx, bios, id, + regs, &cs_shift, &cs_mask)) { + clk_src->base.dp_clk_src = dp_clk_src; + return &clk_src->base; + } + + kfree(clk_src); + BREAK_TO_DEBUGGER(); + return NULL; +} + +static struct dc_cap_funcs cap_funcs = { + .get_dcc_compression_cap = dcn20_get_dcc_compression_cap +}; + + +static bool is_soc_bounding_box_valid(struct dc *dc) +{ + uint32_t hw_internal_rev = dc->ctx->asic_id.hw_internal_rev; + + if (ASICREV_IS_VANGOGH(hw_internal_rev)) + return true; + + return false; +} + +static bool init_soc_bounding_box(struct dc *dc, + struct dcn301_resource_pool *pool) +{ + 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 (!is_soc_bounding_box_valid(dc)) { + DC_LOG_ERROR("%s: not valid soc bounding box\n", __func__); + return false; + } + + loaded_ip->max_num_otg = pool->base.res_cap->num_timing_generator; + loaded_ip->max_num_dpp = pool->base.pipe_count; + DC_FP_START(); + dcn20_patch_bounding_box(dc, loaded_bb); + DC_FP_END(); + + 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) { + DC_FP_START(); + dcn301_fpu_init_soc_bounding_box(bb_info); + DC_FP_END(); + } + } + + return true; +} + + +static void set_wm_ranges( + struct pp_smu_funcs *pp_smu, + struct _vcs_dpi_soc_bounding_box_st *loaded_bb) +{ + struct pp_smu_wm_range_sets ranges = {0}; + int i; + + ranges.num_reader_wm_sets = 0; + + if (loaded_bb->num_states == 1) { + ranges.reader_wm_sets[0].wm_inst = 0; + ranges.reader_wm_sets[0].min_drain_clk_mhz = PP_SMU_WM_SET_RANGE_CLK_UNCONSTRAINED_MIN; + ranges.reader_wm_sets[0].max_drain_clk_mhz = PP_SMU_WM_SET_RANGE_CLK_UNCONSTRAINED_MAX; + ranges.reader_wm_sets[0].min_fill_clk_mhz = PP_SMU_WM_SET_RANGE_CLK_UNCONSTRAINED_MIN; + ranges.reader_wm_sets[0].max_fill_clk_mhz = PP_SMU_WM_SET_RANGE_CLK_UNCONSTRAINED_MAX; + + ranges.num_reader_wm_sets = 1; + } else if (loaded_bb->num_states > 1) { + for (i = 0; i < 4 && i < loaded_bb->num_states; i++) { + ranges.reader_wm_sets[i].wm_inst = i; + ranges.reader_wm_sets[i].min_drain_clk_mhz = PP_SMU_WM_SET_RANGE_CLK_UNCONSTRAINED_MIN; + ranges.reader_wm_sets[i].max_drain_clk_mhz = PP_SMU_WM_SET_RANGE_CLK_UNCONSTRAINED_MAX; + DC_FP_START(); + dcn301_fpu_set_wm_ranges(i, &ranges, loaded_bb); + DC_FP_END(); + ranges.num_reader_wm_sets = i + 1; + } + + ranges.reader_wm_sets[0].min_fill_clk_mhz = PP_SMU_WM_SET_RANGE_CLK_UNCONSTRAINED_MIN; + ranges.reader_wm_sets[ranges.num_reader_wm_sets - 1].max_fill_clk_mhz = PP_SMU_WM_SET_RANGE_CLK_UNCONSTRAINED_MAX; + } + + ranges.num_writer_wm_sets = 1; + + ranges.writer_wm_sets[0].wm_inst = 0; + ranges.writer_wm_sets[0].min_fill_clk_mhz = PP_SMU_WM_SET_RANGE_CLK_UNCONSTRAINED_MIN; + ranges.writer_wm_sets[0].max_fill_clk_mhz = PP_SMU_WM_SET_RANGE_CLK_UNCONSTRAINED_MAX; + ranges.writer_wm_sets[0].min_drain_clk_mhz = PP_SMU_WM_SET_RANGE_CLK_UNCONSTRAINED_MIN; + ranges.writer_wm_sets[0].max_drain_clk_mhz = PP_SMU_WM_SET_RANGE_CLK_UNCONSTRAINED_MAX; + + /* Notify PP Lib/SMU which Watermarks to use for which clock ranges */ + pp_smu->nv_funcs.set_wm_ranges(&pp_smu->nv_funcs.pp_smu, &ranges); +} + +static void dcn301_calculate_wm_and_dlg( + struct dc *dc, struct dc_state *context, + display_e2e_pipe_params_st *pipes, + int pipe_cnt, + int vlevel) +{ + DC_FP_START(); + dcn301_calculate_wm_and_dlg_fp(dc, context, pipes, pipe_cnt, vlevel); + DC_FP_END(); +} + +static struct resource_funcs dcn301_res_pool_funcs = { + .destroy = dcn301_destroy_resource_pool, + .link_enc_create = dcn301_link_encoder_create, + .panel_cntl_create = dcn301_panel_cntl_create, + .validate_bandwidth = dcn30_validate_bandwidth, + .calculate_wm_and_dlg = dcn301_calculate_wm_and_dlg, + .update_soc_for_wm_a = dcn30_update_soc_for_wm_a, + .populate_dml_pipes = dcn30_populate_dml_pipes_from_context, + .acquire_free_pipe_as_secondary_dpp_pipe = dcn20_acquire_free_pipe_for_layer, + .release_pipe = dcn20_release_pipe, + .add_stream_to_ctx = dcn30_add_stream_to_ctx, + .add_dsc_to_stream_resource = dcn20_add_dsc_to_stream_resource, + .remove_stream_from_ctx = dcn20_remove_stream_from_ctx, + .populate_dml_writeback_from_context = dcn30_populate_dml_writeback_from_context, + .set_mcif_arb_params = dcn30_set_mcif_arb_params, + .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 = dcn301_update_bw_bounding_box, + .patch_unknown_plane_state = dcn20_patch_unknown_plane_state +}; + +static bool dcn301_resource_construct( + uint8_t num_virtual_links, + struct dc *dc, + struct dcn301_resource_pool *pool) +{ + int i, j; + struct dc_context *ctx = dc->ctx; + struct irq_service_init_data init_data; + uint32_t pipe_fuses = read_pipe_fuses(ctx); + uint32_t num_pipes = 0; + + DC_LOGGER_INIT(dc->ctx->logger); + + ctx->dc_bios->regs = &bios_regs; + + if (dc->ctx->asic_id.chip_id == DEVICE_ID_VGH_1435) + res_cap_dcn301.num_pll = 2; + pool->base.res_cap = &res_cap_dcn301; + + pool->base.funcs = &dcn301_res_pool_funcs; + + /************************************************* + * Resource + asic cap harcoding * + *************************************************/ + pool->base.underlay_pipe_index = NO_UNDERLAY_PIPE; + pool->base.pipe_count = pool->base.res_cap->num_timing_generator; + pool->base.mpcc_count = pool->base.res_cap->num_timing_generator; + dc->caps.max_downscale_ratio = 600; + dc->caps.i2c_speed_in_khz = 100; + dc->caps.i2c_speed_in_khz_hdcp = 5; /*1.4 w/a enabled by default*/ + dc->caps.max_cursor_size = 256; + dc->caps.min_horizontal_blanking_period = 80; + dc->caps.dmdata_alloc_size = 2048; + dc->caps.max_slave_planes = 2; + dc->caps.max_slave_yuv_planes = 2; + dc->caps.max_slave_rgb_planes = 2; + dc->caps.is_apu = true; + dc->caps.post_blend_color_processing = true; + dc->caps.force_dp_tps4_for_cp2520 = true; + dc->caps.extended_aux_timeout_support = true; + dc->caps.dmcub_support = true; + + /* Color pipeline capabilities */ + dc->caps.color.dpp.dcn_arch = 1; + dc->caps.color.dpp.input_lut_shared = 0; + dc->caps.color.dpp.icsc = 1; + dc->caps.color.dpp.dgam_ram = 0; // must use gamma_corr + dc->caps.color.dpp.dgam_rom_caps.srgb = 1; + dc->caps.color.dpp.dgam_rom_caps.bt2020 = 1; + dc->caps.color.dpp.dgam_rom_caps.gamma2_2 = 1; + dc->caps.color.dpp.dgam_rom_caps.pq = 1; + dc->caps.color.dpp.dgam_rom_caps.hlg = 1; + dc->caps.color.dpp.post_csc = 1; + dc->caps.color.dpp.gamma_corr = 1; + dc->caps.color.dpp.dgam_rom_for_yuv = 0; + + dc->caps.color.dpp.hw_3d_lut = 1; + dc->caps.color.dpp.ogam_ram = 1; + // no OGAM ROM on DCN301 + dc->caps.color.dpp.ogam_rom_caps.srgb = 0; + dc->caps.color.dpp.ogam_rom_caps.bt2020 = 0; + dc->caps.color.dpp.ogam_rom_caps.gamma2_2 = 0; + dc->caps.color.dpp.ogam_rom_caps.pq = 0; + dc->caps.color.dpp.ogam_rom_caps.hlg = 0; + dc->caps.color.dpp.ocsc = 0; + + dc->caps.color.mpc.gamut_remap = 1; + dc->caps.color.mpc.num_3dluts = pool->base.res_cap->num_mpc_3dlut; //2 + dc->caps.color.mpc.ogam_ram = 1; + dc->caps.color.mpc.ogam_rom_caps.srgb = 0; + dc->caps.color.mpc.ogam_rom_caps.bt2020 = 0; + dc->caps.color.mpc.ogam_rom_caps.gamma2_2 = 0; + dc->caps.color.mpc.ogam_rom_caps.pq = 0; + dc->caps.color.mpc.ogam_rom_caps.hlg = 0; + dc->caps.color.mpc.ocsc = 1; + + dc->caps.dp_hdmi21_pcon_support = true; + + /* read VBIOS LTTPR caps */ + if (ctx->dc_bios->funcs->get_lttpr_caps) { + enum bp_result bp_query_result; + uint8_t is_vbios_lttpr_enable = 0; + + bp_query_result = ctx->dc_bios->funcs->get_lttpr_caps(ctx->dc_bios, &is_vbios_lttpr_enable); + dc->caps.vbios_lttpr_enable = (bp_query_result == BP_RESULT_OK) && !!is_vbios_lttpr_enable; + } + + if (ctx->dc_bios->funcs->get_lttpr_interop) { + enum bp_result bp_query_result; + uint8_t is_vbios_interop_enabled = 0; + + bp_query_result = ctx->dc_bios->funcs->get_lttpr_interop(ctx->dc_bios, &is_vbios_interop_enabled); + dc->caps.vbios_lttpr_aware = (bp_query_result == BP_RESULT_OK) && !!is_vbios_interop_enabled; + } + + if (dc->ctx->dce_environment == DCE_ENV_PRODUCTION_DRV) + dc->debug = debug_defaults_drv; + + // Init the vm_helper + if (dc->vm_helper) + vm_helper_init(dc->vm_helper, 16); + + /************************************************* + * Create resources * + *************************************************/ + + /* Clock Sources for Pixel Clock*/ + pool->base.clock_sources[DCN301_CLK_SRC_PLL0] = + dcn301_clock_source_create(ctx, ctx->dc_bios, + CLOCK_SOURCE_COMBO_PHY_PLL0, + &clk_src_regs[0], false); + pool->base.clock_sources[DCN301_CLK_SRC_PLL1] = + dcn301_clock_source_create(ctx, ctx->dc_bios, + CLOCK_SOURCE_COMBO_PHY_PLL1, + &clk_src_regs[1], false); + pool->base.clock_sources[DCN301_CLK_SRC_PLL2] = + dcn301_clock_source_create(ctx, ctx->dc_bios, + CLOCK_SOURCE_COMBO_PHY_PLL2, + &clk_src_regs[2], false); + pool->base.clock_sources[DCN301_CLK_SRC_PLL3] = + dcn301_clock_source_create(ctx, ctx->dc_bios, + CLOCK_SOURCE_COMBO_PHY_PLL3, + &clk_src_regs[3], false); + + pool->base.clk_src_count = DCN301_CLK_SRC_TOTAL; + + /* todo: not reuse phy_pll registers */ + pool->base.dp_clock_source = + dcn301_clock_source_create(ctx, ctx->dc_bios, + CLOCK_SOURCE_ID_DP_DTO, + &clk_src_regs[0], true); + + for (i = 0; i < pool->base.clk_src_count; i++) { + if (pool->base.clock_sources[i] == NULL) { + dm_error("DC: failed to create clock sources!\n"); + BREAK_TO_DEBUGGER(); + goto create_fail; + } + } + + /* DCCG */ + pool->base.dccg = dccg301_create(ctx, &dccg_regs, &dccg_shift, &dccg_mask); + if (pool->base.dccg == NULL) { + dm_error("DC: failed to create dccg!\n"); + BREAK_TO_DEBUGGER(); + goto create_fail; + } + + init_soc_bounding_box(dc, pool); + + if (!dc->debug.disable_pplib_wm_range && pool->base.pp_smu->nv_funcs.set_wm_ranges) + set_wm_ranges(pool->base.pp_smu, &dcn3_01_soc); + + num_pipes = dcn3_01_ip.max_num_dpp; + + for (i = 0; i < dcn3_01_ip.max_num_dpp; i++) + if (pipe_fuses & 1 << i) + num_pipes--; + dcn3_01_ip.max_num_dpp = num_pipes; + dcn3_01_ip.max_num_otg = num_pipes; + + + dml_init_instance(&dc->dml, &dcn3_01_soc, &dcn3_01_ip, DML_PROJECT_DCN30); + + /* IRQ */ + init_data.ctx = dc->ctx; + pool->base.irqs = dal_irq_service_dcn30_create(&init_data); + if (!pool->base.irqs) + goto create_fail; + + /* HUBBUB */ + pool->base.hubbub = dcn301_hubbub_create(ctx); + if (pool->base.hubbub == NULL) { + BREAK_TO_DEBUGGER(); + dm_error("DC: failed to create hubbub!\n"); + goto create_fail; + } + + j = 0; + /* HUBPs, DPPs, OPPs and TGs */ + for (i = 0; i < pool->base.pipe_count; i++) { + + /* if pipe is disabled, skip instance of HW pipe, + * i.e, skip ASIC register instance + */ + if ((pipe_fuses & (1 << i)) != 0) { + DC_LOG_DEBUG("%s: fusing pipe %d\n", __func__, i); + continue; + } + + pool->base.hubps[j] = dcn301_hubp_create(ctx, i); + if (pool->base.hubps[j] == NULL) { + BREAK_TO_DEBUGGER(); + dm_error( + "DC: failed to create hubps!\n"); + goto create_fail; + } + + pool->base.dpps[j] = dcn301_dpp_create(ctx, i); + if (pool->base.dpps[j] == NULL) { + BREAK_TO_DEBUGGER(); + dm_error( + "DC: failed to create dpps!\n"); + goto create_fail; + } + + pool->base.opps[j] = dcn301_opp_create(ctx, i); + if (pool->base.opps[j] == NULL) { + BREAK_TO_DEBUGGER(); + dm_error( + "DC: failed to create output pixel processor!\n"); + goto create_fail; + } + + pool->base.timing_generators[j] = dcn301_timing_generator_create(ctx, i); + if (pool->base.timing_generators[j] == NULL) { + BREAK_TO_DEBUGGER(); + dm_error("DC: failed to create tg!\n"); + goto create_fail; + } + j++; + } + pool->base.timing_generator_count = j; + pool->base.pipe_count = j; + pool->base.mpcc_count = j; + + /* ABM (or ABMs for NV2x) */ + /* TODO: */ + for (i = 0; i < pool->base.res_cap->num_timing_generator; i++) { + pool->base.multiple_abms[i] = dmub_abm_create(ctx, + &abm_regs[i], + &abm_shift, + &abm_mask); + if (pool->base.multiple_abms[i] == NULL) { + dm_error("DC: failed to create abm for pipe %d!\n", i); + BREAK_TO_DEBUGGER(); + goto create_fail; + } + } + + /* MPC and DSC */ + pool->base.mpc = dcn301_mpc_create(ctx, pool->base.mpcc_count, pool->base.res_cap->num_mpc_3dlut); + if (pool->base.mpc == NULL) { + BREAK_TO_DEBUGGER(); + dm_error("DC: failed to create mpc!\n"); + goto create_fail; + } + + for (i = 0; i < pool->base.res_cap->num_dsc; i++) { + pool->base.dscs[i] = dcn301_dsc_create(ctx, i); + if (pool->base.dscs[i] == NULL) { + BREAK_TO_DEBUGGER(); + dm_error("DC: failed to create display stream compressor %d!\n", i); + goto create_fail; + } + } + + /* DWB and MMHUBBUB */ + if (!dcn301_dwbc_create(ctx, &pool->base)) { + BREAK_TO_DEBUGGER(); + dm_error("DC: failed to create dwbc!\n"); + goto create_fail; + } + + if (!dcn301_mmhubbub_create(ctx, &pool->base)) { + BREAK_TO_DEBUGGER(); + dm_error("DC: failed to create mcif_wb!\n"); + goto create_fail; + } + + /* AUX and I2C */ + for (i = 0; i < pool->base.res_cap->num_ddc; i++) { + pool->base.engines[i] = dcn301_aux_engine_create(ctx, i); + if (pool->base.engines[i] == NULL) { + BREAK_TO_DEBUGGER(); + dm_error( + "DC:failed to create aux engine!!\n"); + goto create_fail; + } + pool->base.hw_i2cs[i] = dcn301_i2c_hw_create(ctx, i); + if (pool->base.hw_i2cs[i] == NULL) { + BREAK_TO_DEBUGGER(); + dm_error( + "DC:failed to create hw i2c!!\n"); + goto create_fail; + } + pool->base.sw_i2cs[i] = NULL; + } + + /* Audio, Stream Encoders including HPO and virtual, MPC 3D LUTs */ + if (!resource_construct(num_virtual_links, dc, &pool->base, + &res_create_funcs)) + goto create_fail; + + /* HW Sequencer and Plane caps */ + dcn301_hw_sequencer_construct(dc); + + dc->caps.max_planes = pool->base.pipe_count; + + for (i = 0; i < dc->caps.max_planes; ++i) + dc->caps.planes[i] = plane_cap; + + dc->cap_funcs = cap_funcs; + + return true; + +create_fail: + + dcn301_destruct(pool); + + return false; +} + +struct resource_pool *dcn301_create_resource_pool( + const struct dc_init_data *init_data, + struct dc *dc) +{ + struct dcn301_resource_pool *pool = + kzalloc(sizeof(struct dcn301_resource_pool), GFP_KERNEL); + + if (!pool) + return NULL; + + if (dcn301_resource_construct(init_data->num_virtual_links, dc, pool)) + return &pool->base; + + BREAK_TO_DEBUGGER(); + kfree(pool); + return NULL; +} diff --git a/drivers/gpu/drm/amd/display/dc/resource/dcn301/dcn301_resource.h b/drivers/gpu/drm/amd/display/dc/resource/dcn301/dcn301_resource.h new file mode 100644 index 000000000000..ae8672680cdd --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/resource/dcn301/dcn301_resource.h @@ -0,0 +1,45 @@ +/* + * Copyright 2020 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 _DCN301_RESOURCE_H_ +#define _DCN301_RESOURCE_H_ + +#include "core_types.h" + +struct dc; +struct resource_pool; +struct _vcs_dpi_display_pipe_params_st; + +extern struct _vcs_dpi_ip_params_st dcn3_01_ip; +extern struct _vcs_dpi_soc_bounding_box_st dcn3_01_soc; + +struct dcn301_resource_pool { + struct resource_pool base; +}; +struct resource_pool *dcn301_create_resource_pool( + const struct dc_init_data *init_data, + struct dc *dc); + +#endif /* _DCN301_RESOURCE_H_ */ diff --git a/drivers/gpu/drm/amd/display/dc/resource/dcn302/dcn302_resource.c b/drivers/gpu/drm/amd/display/dc/resource/dcn302/dcn302_resource.c new file mode 100644 index 000000000000..5791b5cc2875 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/resource/dcn302/dcn302_resource.c @@ -0,0 +1,1518 @@ +/* + * Copyright 2020 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 "dcn302/dcn302_init.h" +#include "dcn302_resource.h" +#include "dcn302/dcn302_dccg.h" +#include "irq/dcn302/irq_service_dcn302.h" + +#include "dcn30/dcn30_dio_link_encoder.h" +#include "dcn30/dcn30_dio_stream_encoder.h" +#include "dcn30/dcn30_dwb.h" +#include "dcn30/dcn30_dpp.h" +#include "dcn30/dcn30_hubbub.h" +#include "dcn30/dcn30_hubp.h" +#include "dcn30/dcn30_mmhubbub.h" +#include "dcn30/dcn30_mpc.h" +#include "dcn30/dcn30_opp.h" +#include "dcn30/dcn30_optc.h" +#include "dcn30/dcn30_resource.h" + +#include "dcn20/dcn20_dsc.h" +#include "dcn20/dcn20_resource.h" + +#include "dml/dcn30/dcn30_fpu.h" + +#include "dcn10/dcn10_resource.h" + +#include "link.h" +#include "dce/dce_abm.h" +#include "dce/dce_audio.h" +#include "dce/dce_aux.h" +#include "dce/dce_clock_source.h" +#include "dce/dce_hwseq.h" +#include "dce/dce_i2c_hw.h" +#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" +#include "resource.h" +#include "vm_helper.h" + +#include "dml/dcn302/dcn302_fpu.h" + +#include "dimgrey_cavefish_ip_offset.h" +#include "dcn/dcn_3_0_2_offset.h" +#include "dcn/dcn_3_0_2_sh_mask.h" +#include "dpcs/dpcs_3_0_0_offset.h" +#include "dpcs/dpcs_3_0_0_sh_mask.h" +#include "nbio/nbio_7_4_offset.h" +#include "amdgpu_socbb.h" + +#define DC_LOGGER \ + dc->ctx->logger +#define DC_LOGGER_INIT(logger) + +static const struct dc_debug_options debug_defaults_drv = { + .disable_dmcu = true, + .force_abm_enable = false, + .timing_trace = false, + .clock_trace = true, + .disable_pplib_clock_request = true, + .pipe_split_policy = MPC_SPLIT_DYNAMIC, + .force_single_disp_pipe_split = false, + .disable_dcc = DCC_ENABLE, + .vsr_support = true, + .performance_trace = false, + .max_downscale_src_width = 7680,/*upto 8K*/ + .disable_pplib_wm_range = false, + .scl_reset_length10 = true, + .sanity_checks = false, + .underflow_assert_delay_us = 0xFFFFFFFF, + .dwb_fi_phase = -1, // -1 = disable, + .dmub_command_table = true, + .use_max_lb = true, + .exit_idle_opt_for_cursor_updates = true, + .enable_legacy_fast_update = false, + .using_dml2 = false, +}; + +static const struct dc_panel_config panel_config_defaults = { + .psr = { + .disable_psr = false, + .disallow_psrsu = false, + .disallow_replay = false, + }, +}; + +enum dcn302_clk_src_array_id { + DCN302_CLK_SRC_PLL0, + DCN302_CLK_SRC_PLL1, + DCN302_CLK_SRC_PLL2, + DCN302_CLK_SRC_PLL3, + DCN302_CLK_SRC_PLL4, + DCN302_CLK_SRC_TOTAL +}; + +static const struct resource_caps res_cap_dcn302 = { + .num_timing_generator = 5, + .num_opp = 5, + .num_video_plane = 5, + .num_audio = 5, + .num_stream_encoder = 5, + .num_dwb = 1, + .num_ddc = 5, + .num_vmid = 16, + .num_mpc_3dlut = 2, + .num_dsc = 5, +}; + +static const struct dc_plane_cap plane_cap = { + .type = DC_PLANE_TYPE_DCN_UNIVERSAL, + .per_pixel_alpha = true, + .pixel_format_support = { + .argb8888 = true, + .nv12 = true, + .fp16 = true, + .p010 = true, + .ayuv = false, + }, + .max_upscale_factor = { + .argb8888 = 16000, + .nv12 = 16000, + .fp16 = 16000 + }, + /* 6:1 downscaling ratio: 1000/6 = 166.666 */ + .max_downscale_factor = { + .argb8888 = 167, + .nv12 = 167, + .fp16 = 167 + }, + 16, + 16 +}; + +/* NBIO */ +#define NBIO_BASE_INNER(seg) \ + NBIO_BASE__INST0_SEG ## seg + +#define NBIO_BASE(seg) \ + NBIO_BASE_INNER(seg) + +#define NBIO_SR(reg_name)\ + .reg_name = NBIO_BASE(mm ## reg_name ## _BASE_IDX) + \ + mm ## reg_name + +/* DCN */ +#define BASE_INNER(seg) DCN_BASE__INST0_SEG ## seg + +#define BASE(seg) BASE_INNER(seg) + +#define SR(reg_name)\ + .reg_name = BASE(mm ## reg_name ## _BASE_IDX) + mm ## reg_name + +#define SF(reg_name, field_name, post_fix)\ + .field_name = reg_name ## __ ## field_name ## post_fix + +#define SRI(reg_name, block, id)\ + .reg_name = BASE(mm ## block ## id ## _ ## reg_name ## _BASE_IDX) + mm ## block ## id ## _ ## reg_name + +#define SRI2(reg_name, block, id)\ + .reg_name = BASE(mm ## reg_name ## _BASE_IDX) + mm ## reg_name + +#define SRII(reg_name, block, id)\ + .reg_name[id] = BASE(mm ## block ## id ## _ ## reg_name ## _BASE_IDX) + \ + mm ## block ## id ## _ ## reg_name + +#define DCCG_SRII(reg_name, block, id)\ + .block ## _ ## reg_name[id] = BASE(mm ## block ## id ## _ ## reg_name ## _BASE_IDX) + \ + mm ## block ## id ## _ ## reg_name + +#define VUPDATE_SRII(reg_name, block, id)\ + .reg_name[id] = BASE(mm ## reg_name ## _ ## block ## id ## _BASE_IDX) + \ + mm ## reg_name ## _ ## block ## id + +#define SRII_DWB(reg_name, temp_name, block, id)\ + .reg_name[id] = BASE(mm ## block ## id ## _ ## temp_name ## _BASE_IDX) + \ + mm ## block ## id ## _ ## temp_name + +#define SF_DWB2(reg_name, block, id, field_name, post_fix) \ + .field_name = reg_name ## __ ## field_name ## post_fix + +#define SRII_MPC_RMU(reg_name, block, id)\ + .RMU##_##reg_name[id] = BASE(mm ## block ## id ## _ ## reg_name ## _BASE_IDX) + \ + mm ## block ## id ## _ ## reg_name + +static const struct dcn_hubbub_registers hubbub_reg = { + HUBBUB_REG_LIST_DCN30(0) +}; + +static const struct dcn_hubbub_shift hubbub_shift = { + HUBBUB_MASK_SH_LIST_DCN30(__SHIFT) +}; + +static const struct dcn_hubbub_mask hubbub_mask = { + HUBBUB_MASK_SH_LIST_DCN30(_MASK) +}; + +#define vmid_regs(id)\ + [id] = { DCN20_VMID_REG_LIST(id) } + +static const struct dcn_vmid_registers vmid_regs[] = { + vmid_regs(0), + vmid_regs(1), + vmid_regs(2), + vmid_regs(3), + vmid_regs(4), + vmid_regs(5), + vmid_regs(6), + vmid_regs(7), + vmid_regs(8), + vmid_regs(9), + vmid_regs(10), + vmid_regs(11), + vmid_regs(12), + vmid_regs(13), + vmid_regs(14), + vmid_regs(15) +}; + +static const struct dcn20_vmid_shift vmid_shifts = { + DCN20_VMID_MASK_SH_LIST(__SHIFT) +}; + +static const struct dcn20_vmid_mask vmid_masks = { + DCN20_VMID_MASK_SH_LIST(_MASK) +}; + +static struct hubbub *dcn302_hubbub_create(struct dc_context *ctx) +{ + int i; + + struct dcn20_hubbub *hubbub3 = kzalloc(sizeof(struct dcn20_hubbub), GFP_KERNEL); + + if (!hubbub3) + return NULL; + + hubbub3_construct(hubbub3, ctx, &hubbub_reg, &hubbub_shift, &hubbub_mask); + + for (i = 0; i < res_cap_dcn302.num_vmid; i++) { + struct dcn20_vmid *vmid = &hubbub3->vmid[i]; + + vmid->ctx = ctx; + + vmid->regs = &vmid_regs[i]; + vmid->shifts = &vmid_shifts; + vmid->masks = &vmid_masks; + } + + return &hubbub3->base; +} + +#define vpg_regs(id)\ + [id] = { VPG_DCN3_REG_LIST(id) } + +static const struct dcn30_vpg_registers vpg_regs[] = { + vpg_regs(0), + vpg_regs(1), + vpg_regs(2), + vpg_regs(3), + vpg_regs(4), + vpg_regs(5) +}; + +static const struct dcn30_vpg_shift vpg_shift = { + DCN3_VPG_MASK_SH_LIST(__SHIFT) +}; + +static const struct dcn30_vpg_mask vpg_mask = { + DCN3_VPG_MASK_SH_LIST(_MASK) +}; + +static struct vpg *dcn302_vpg_create(struct dc_context *ctx, uint32_t inst) +{ + struct dcn30_vpg *vpg3 = kzalloc(sizeof(struct dcn30_vpg), GFP_KERNEL); + + if (!vpg3) + return NULL; + + vpg3_construct(vpg3, ctx, inst, &vpg_regs[inst], &vpg_shift, &vpg_mask); + + return &vpg3->base; +} + +#define afmt_regs(id)\ + [id] = { AFMT_DCN3_REG_LIST(id) } + +static const struct dcn30_afmt_registers afmt_regs[] = { + afmt_regs(0), + afmt_regs(1), + afmt_regs(2), + afmt_regs(3), + afmt_regs(4), + afmt_regs(5) +}; + +static const struct dcn30_afmt_shift afmt_shift = { + DCN3_AFMT_MASK_SH_LIST(__SHIFT) +}; + +static const struct dcn30_afmt_mask afmt_mask = { + DCN3_AFMT_MASK_SH_LIST(_MASK) +}; + +static struct afmt *dcn302_afmt_create(struct dc_context *ctx, uint32_t inst) +{ + struct dcn30_afmt *afmt3 = kzalloc(sizeof(struct dcn30_afmt), GFP_KERNEL); + + if (!afmt3) + return NULL; + + afmt3_construct(afmt3, ctx, inst, &afmt_regs[inst], &afmt_shift, &afmt_mask); + + return &afmt3->base; +} + +#define audio_regs(id)\ + [id] = { AUD_COMMON_REG_LIST(id) } + +static const struct dce_audio_registers audio_regs[] = { + audio_regs(0), + audio_regs(1), + audio_regs(2), + audio_regs(3), + audio_regs(4), + audio_regs(5), + audio_regs(6) +}; + +#define DCE120_AUD_COMMON_MASK_SH_LIST(mask_sh)\ + SF(AZF0ENDPOINT0_AZALIA_F0_CODEC_ENDPOINT_INDEX, AZALIA_ENDPOINT_REG_INDEX, mask_sh),\ + SF(AZF0ENDPOINT0_AZALIA_F0_CODEC_ENDPOINT_DATA, AZALIA_ENDPOINT_REG_DATA, mask_sh),\ + AUD_COMMON_MASK_SH_LIST_BASE(mask_sh) + +static const struct dce_audio_shift audio_shift = { + DCE120_AUD_COMMON_MASK_SH_LIST(__SHIFT) +}; + +static const struct dce_audio_mask audio_mask = { + DCE120_AUD_COMMON_MASK_SH_LIST(_MASK) +}; + +static struct audio *dcn302_create_audio(struct dc_context *ctx, unsigned int inst) +{ + return dce_audio_create(ctx, inst, &audio_regs[inst], &audio_shift, &audio_mask); +} + +#define stream_enc_regs(id)\ + [id] = { SE_DCN3_REG_LIST(id) } + +static const struct dcn10_stream_enc_registers stream_enc_regs[] = { + stream_enc_regs(0), + stream_enc_regs(1), + stream_enc_regs(2), + stream_enc_regs(3), + stream_enc_regs(4) +}; + +static const struct dcn10_stream_encoder_shift se_shift = { + SE_COMMON_MASK_SH_LIST_DCN30(__SHIFT) +}; + +static const struct dcn10_stream_encoder_mask se_mask = { + SE_COMMON_MASK_SH_LIST_DCN30(_MASK) +}; + +static struct stream_encoder *dcn302_stream_encoder_create(enum engine_id eng_id, struct dc_context *ctx) +{ + struct dcn10_stream_encoder *enc1; + struct vpg *vpg; + struct afmt *afmt; + int vpg_inst; + int afmt_inst; + + /* Mapping of VPG, AFMT, DME register blocks to DIO block instance */ + if (eng_id <= ENGINE_ID_DIGE) { + vpg_inst = eng_id; + afmt_inst = eng_id; + } else + return NULL; + + enc1 = kzalloc(sizeof(struct dcn10_stream_encoder), GFP_KERNEL); + vpg = dcn302_vpg_create(ctx, vpg_inst); + afmt = dcn302_afmt_create(ctx, afmt_inst); + + if (!enc1 || !vpg || !afmt) { + kfree(enc1); + kfree(vpg); + kfree(afmt); + return NULL; + } + + dcn30_dio_stream_encoder_construct(enc1, ctx, ctx->dc_bios, eng_id, vpg, afmt, &stream_enc_regs[eng_id], + &se_shift, &se_mask); + + return &enc1->base; +} + +#define clk_src_regs(index, pllid)\ + [index] = { CS_COMMON_REG_LIST_DCN3_02(index, pllid) } + +static const struct dce110_clk_src_regs clk_src_regs[] = { + clk_src_regs(0, A), + clk_src_regs(1, B), + clk_src_regs(2, C), + clk_src_regs(3, D), + clk_src_regs(4, E) +}; + +static const struct dce110_clk_src_shift cs_shift = { + CS_COMMON_MASK_SH_LIST_DCN2_0(__SHIFT) +}; + +static const struct dce110_clk_src_mask cs_mask = { + CS_COMMON_MASK_SH_LIST_DCN2_0(_MASK) +}; + +static struct clock_source *dcn302_clock_source_create(struct dc_context *ctx, struct dc_bios *bios, + enum clock_source_id id, const struct dce110_clk_src_regs *regs, bool dp_clk_src) +{ + struct dce110_clk_src *clk_src = kzalloc(sizeof(struct dce110_clk_src), GFP_KERNEL); + + if (!clk_src) + return NULL; + + if (dcn3_clk_src_construct(clk_src, ctx, bios, id, regs, &cs_shift, &cs_mask)) { + clk_src->base.dp_clk_src = dp_clk_src; + return &clk_src->base; + } + + kfree(clk_src); + BREAK_TO_DEBUGGER(); + return NULL; +} + +static const struct dce_hwseq_registers hwseq_reg = { + HWSEQ_DCN302_REG_LIST() +}; + +static const struct dce_hwseq_shift hwseq_shift = { + HWSEQ_DCN302_MASK_SH_LIST(__SHIFT) +}; + +static const struct dce_hwseq_mask hwseq_mask = { + HWSEQ_DCN302_MASK_SH_LIST(_MASK) +}; + +static struct dce_hwseq *dcn302_hwseq_create(struct dc_context *ctx) +{ + struct dce_hwseq *hws = kzalloc(sizeof(struct dce_hwseq), GFP_KERNEL); + + if (hws) { + hws->ctx = ctx; + hws->regs = &hwseq_reg; + hws->shifts = &hwseq_shift; + hws->masks = &hwseq_mask; + } + return hws; +} + +#define hubp_regs(id)\ + [id] = { HUBP_REG_LIST_DCN30(id) } + +static const struct dcn_hubp2_registers hubp_regs[] = { + hubp_regs(0), + hubp_regs(1), + hubp_regs(2), + hubp_regs(3), + hubp_regs(4) +}; + +static const struct dcn_hubp2_shift hubp_shift = { + HUBP_MASK_SH_LIST_DCN30(__SHIFT) +}; + +static const struct dcn_hubp2_mask hubp_mask = { + HUBP_MASK_SH_LIST_DCN30(_MASK) +}; + +static struct hubp *dcn302_hubp_create(struct dc_context *ctx, uint32_t inst) +{ + struct dcn20_hubp *hubp2 = kzalloc(sizeof(struct dcn20_hubp), GFP_KERNEL); + + if (!hubp2) + return NULL; + + if (hubp3_construct(hubp2, ctx, inst, &hubp_regs[inst], &hubp_shift, &hubp_mask)) + return &hubp2->base; + + BREAK_TO_DEBUGGER(); + kfree(hubp2); + return NULL; +} + +#define dpp_regs(id)\ + [id] = { DPP_REG_LIST_DCN30(id) } + +static const struct dcn3_dpp_registers dpp_regs[] = { + dpp_regs(0), + dpp_regs(1), + dpp_regs(2), + dpp_regs(3), + dpp_regs(4) +}; + +static const struct dcn3_dpp_shift tf_shift = { + DPP_REG_LIST_SH_MASK_DCN30(__SHIFT) +}; + +static const struct dcn3_dpp_mask tf_mask = { + DPP_REG_LIST_SH_MASK_DCN30(_MASK) +}; + +static struct dpp *dcn302_dpp_create(struct dc_context *ctx, uint32_t inst) +{ + struct dcn3_dpp *dpp = kzalloc(sizeof(struct dcn3_dpp), GFP_KERNEL); + + if (!dpp) + return NULL; + + if (dpp3_construct(dpp, ctx, inst, &dpp_regs[inst], &tf_shift, &tf_mask)) + return &dpp->base; + + BREAK_TO_DEBUGGER(); + kfree(dpp); + return NULL; +} + +#define opp_regs(id)\ + [id] = { OPP_REG_LIST_DCN30(id) } + +static const struct dcn20_opp_registers opp_regs[] = { + opp_regs(0), + opp_regs(1), + opp_regs(2), + opp_regs(3), + opp_regs(4) +}; + +static const struct dcn20_opp_shift opp_shift = { + OPP_MASK_SH_LIST_DCN20(__SHIFT) +}; + +static const struct dcn20_opp_mask opp_mask = { + OPP_MASK_SH_LIST_DCN20(_MASK) +}; + +static struct output_pixel_processor *dcn302_opp_create(struct dc_context *ctx, uint32_t inst) +{ + struct dcn20_opp *opp = kzalloc(sizeof(struct dcn20_opp), GFP_KERNEL); + + if (!opp) { + BREAK_TO_DEBUGGER(); + return NULL; + } + + dcn20_opp_construct(opp, ctx, inst, &opp_regs[inst], &opp_shift, &opp_mask); + return &opp->base; +} + +#define optc_regs(id)\ + [id] = { OPTC_COMMON_REG_LIST_DCN3_0(id) } + +static const struct dcn_optc_registers optc_regs[] = { + optc_regs(0), + optc_regs(1), + optc_regs(2), + optc_regs(3), + optc_regs(4) +}; + +static const struct dcn_optc_shift optc_shift = { + OPTC_COMMON_MASK_SH_LIST_DCN30(__SHIFT) +}; + +static const struct dcn_optc_mask optc_mask = { + OPTC_COMMON_MASK_SH_LIST_DCN30(_MASK) +}; + +static struct timing_generator *dcn302_timing_generator_create(struct dc_context *ctx, uint32_t instance) +{ + struct optc *tgn10 = kzalloc(sizeof(struct optc), GFP_KERNEL); + + if (!tgn10) + return NULL; + + tgn10->base.inst = instance; + tgn10->base.ctx = ctx; + + tgn10->tg_regs = &optc_regs[instance]; + tgn10->tg_shift = &optc_shift; + tgn10->tg_mask = &optc_mask; + + dcn30_timing_generator_init(tgn10); + + return &tgn10->base; +} + +static const struct dcn30_mpc_registers mpc_regs = { + MPC_REG_LIST_DCN3_0(0), + MPC_REG_LIST_DCN3_0(1), + MPC_REG_LIST_DCN3_0(2), + MPC_REG_LIST_DCN3_0(3), + MPC_REG_LIST_DCN3_0(4), + MPC_OUT_MUX_REG_LIST_DCN3_0(0), + MPC_OUT_MUX_REG_LIST_DCN3_0(1), + MPC_OUT_MUX_REG_LIST_DCN3_0(2), + MPC_OUT_MUX_REG_LIST_DCN3_0(3), + MPC_OUT_MUX_REG_LIST_DCN3_0(4), + MPC_RMU_GLOBAL_REG_LIST_DCN3AG, + MPC_RMU_REG_LIST_DCN3AG(0), + MPC_RMU_REG_LIST_DCN3AG(1), + MPC_RMU_REG_LIST_DCN3AG(2), + MPC_DWB_MUX_REG_LIST_DCN3_0(0), +}; + +static const struct dcn30_mpc_shift mpc_shift = { + MPC_COMMON_MASK_SH_LIST_DCN30(__SHIFT) +}; + +static const struct dcn30_mpc_mask mpc_mask = { + MPC_COMMON_MASK_SH_LIST_DCN30(_MASK) +}; + +static struct mpc *dcn302_mpc_create(struct dc_context *ctx, int num_mpcc, int num_rmu) +{ + struct dcn30_mpc *mpc30 = kzalloc(sizeof(struct dcn30_mpc), GFP_KERNEL); + + if (!mpc30) + return NULL; + + dcn30_mpc_construct(mpc30, ctx, &mpc_regs, &mpc_shift, &mpc_mask, num_mpcc, num_rmu); + + return &mpc30->base; +} + +#define dsc_regsDCN20(id)\ +[id] = { DSC_REG_LIST_DCN20(id) } + +static const struct dcn20_dsc_registers dsc_regs[] = { + dsc_regsDCN20(0), + dsc_regsDCN20(1), + dsc_regsDCN20(2), + dsc_regsDCN20(3), + dsc_regsDCN20(4) +}; + +static const struct dcn20_dsc_shift dsc_shift = { + DSC_REG_LIST_SH_MASK_DCN20(__SHIFT) +}; + +static const struct dcn20_dsc_mask dsc_mask = { + DSC_REG_LIST_SH_MASK_DCN20(_MASK) +}; + +static struct display_stream_compressor *dcn302_dsc_create(struct dc_context *ctx, uint32_t inst) +{ + struct dcn20_dsc *dsc = kzalloc(sizeof(struct dcn20_dsc), GFP_KERNEL); + + if (!dsc) { + BREAK_TO_DEBUGGER(); + return NULL; + } + + dsc2_construct(dsc, ctx, inst, &dsc_regs[inst], &dsc_shift, &dsc_mask); + return &dsc->base; +} + +#define dwbc_regs_dcn3(id)\ +[id] = { DWBC_COMMON_REG_LIST_DCN30(id) } + +static const struct dcn30_dwbc_registers dwbc30_regs[] = { + dwbc_regs_dcn3(0) +}; + +static const struct dcn30_dwbc_shift dwbc30_shift = { + DWBC_COMMON_MASK_SH_LIST_DCN30(__SHIFT) +}; + +static const struct dcn30_dwbc_mask dwbc30_mask = { + DWBC_COMMON_MASK_SH_LIST_DCN30(_MASK) +}; + +static bool dcn302_dwbc_create(struct dc_context *ctx, struct resource_pool *pool) +{ + int i; + uint32_t pipe_count = pool->res_cap->num_dwb; + + for (i = 0; i < pipe_count; i++) { + struct dcn30_dwbc *dwbc30 = kzalloc(sizeof(struct dcn30_dwbc), GFP_KERNEL); + + if (!dwbc30) { + dm_error("DC: failed to create dwbc30!\n"); + return false; + } + + dcn30_dwbc_construct(dwbc30, ctx, &dwbc30_regs[i], &dwbc30_shift, &dwbc30_mask, i); + + pool->dwbc[i] = &dwbc30->base; + } + return true; +} + +#define mcif_wb_regs_dcn3(id)\ +[id] = { MCIF_WB_COMMON_REG_LIST_DCN30(id) } + +static const struct dcn30_mmhubbub_registers mcif_wb30_regs[] = { + mcif_wb_regs_dcn3(0) +}; + +static const struct dcn30_mmhubbub_shift mcif_wb30_shift = { + MCIF_WB_COMMON_MASK_SH_LIST_DCN30(__SHIFT) +}; + +static const struct dcn30_mmhubbub_mask mcif_wb30_mask = { + MCIF_WB_COMMON_MASK_SH_LIST_DCN30(_MASK) +}; + +static bool dcn302_mmhubbub_create(struct dc_context *ctx, struct resource_pool *pool) +{ + int i; + uint32_t pipe_count = pool->res_cap->num_dwb; + + for (i = 0; i < pipe_count; i++) { + struct dcn30_mmhubbub *mcif_wb30 = kzalloc(sizeof(struct dcn30_mmhubbub), GFP_KERNEL); + + if (!mcif_wb30) { + dm_error("DC: failed to create mcif_wb30!\n"); + return false; + } + + dcn30_mmhubbub_construct(mcif_wb30, ctx, &mcif_wb30_regs[i], &mcif_wb30_shift, &mcif_wb30_mask, i); + + pool->mcif_wb[i] = &mcif_wb30->base; + } + return true; +} + +#define aux_engine_regs(id)\ +[id] = {\ + AUX_COMMON_REG_LIST0(id), \ + .AUXN_IMPCAL = 0, \ + .AUXP_IMPCAL = 0, \ + .AUX_RESET_MASK = DP_AUX0_AUX_CONTROL__AUX_RESET_MASK, \ +} + +static const struct dce110_aux_registers aux_engine_regs[] = { + aux_engine_regs(0), + aux_engine_regs(1), + aux_engine_regs(2), + aux_engine_regs(3), + aux_engine_regs(4) +}; + +static const struct dce110_aux_registers_shift aux_shift = { + DCN_AUX_MASK_SH_LIST(__SHIFT) +}; + +static const struct dce110_aux_registers_mask aux_mask = { + DCN_AUX_MASK_SH_LIST(_MASK) +}; + +static struct dce_aux *dcn302_aux_engine_create(struct dc_context *ctx, uint32_t inst) +{ + struct aux_engine_dce110 *aux_engine = kzalloc(sizeof(struct aux_engine_dce110), GFP_KERNEL); + + if (!aux_engine) + return NULL; + + dce110_aux_engine_construct(aux_engine, ctx, inst, SW_AUX_TIMEOUT_PERIOD_MULTIPLIER * AUX_TIMEOUT_PERIOD, + &aux_engine_regs[inst], &aux_mask, &aux_shift, ctx->dc->caps.extended_aux_timeout_support); + + return &aux_engine->base; +} + +#define i2c_inst_regs(id) { I2C_HW_ENGINE_COMMON_REG_LIST(id) } + +static const struct dce_i2c_registers i2c_hw_regs[] = { + i2c_inst_regs(1), + i2c_inst_regs(2), + i2c_inst_regs(3), + i2c_inst_regs(4), + i2c_inst_regs(5) +}; + +static const struct dce_i2c_shift i2c_shifts = { + I2C_COMMON_MASK_SH_LIST_DCN2(__SHIFT) +}; + +static const struct dce_i2c_mask i2c_masks = { + I2C_COMMON_MASK_SH_LIST_DCN2(_MASK) +}; + +static struct dce_i2c_hw *dcn302_i2c_hw_create(struct dc_context *ctx, uint32_t inst) +{ + struct dce_i2c_hw *dce_i2c_hw = kzalloc(sizeof(struct dce_i2c_hw), GFP_KERNEL); + + if (!dce_i2c_hw) + return NULL; + + dcn2_i2c_hw_construct(dce_i2c_hw, ctx, inst, &i2c_hw_regs[inst], &i2c_shifts, &i2c_masks); + + return dce_i2c_hw; +} + +static const struct encoder_feature_support link_enc_feature = { + .max_hdmi_deep_color = COLOR_DEPTH_121212, + .max_hdmi_pixel_clock = 600000, + .hdmi_ycbcr420_supported = true, + .dp_ycbcr420_supported = true, + .fec_supported = true, + .flags.bits.IS_HBR2_CAPABLE = true, + .flags.bits.IS_HBR3_CAPABLE = true, + .flags.bits.IS_TPS3_CAPABLE = true, + .flags.bits.IS_TPS4_CAPABLE = true +}; + +#define link_regs(id, phyid)\ + [id] = {\ + LE_DCN3_REG_LIST(id), \ + UNIPHY_DCN2_REG_LIST(phyid), \ + DPCS_DCN2_REG_LIST(id), \ + SRI(DP_DPHY_INTERNAL_CTRL, DP, id) \ + } + +static const struct dcn10_link_enc_registers link_enc_regs[] = { + link_regs(0, A), + link_regs(1, B), + link_regs(2, C), + link_regs(3, D), + link_regs(4, E) +}; + +static const struct dcn10_link_enc_shift le_shift = { + LINK_ENCODER_MASK_SH_LIST_DCN30(__SHIFT), + DPCS_DCN2_MASK_SH_LIST(__SHIFT) +}; + +static const struct dcn10_link_enc_mask le_mask = { + LINK_ENCODER_MASK_SH_LIST_DCN30(_MASK), + DPCS_DCN2_MASK_SH_LIST(_MASK) +}; + +#define aux_regs(id)\ + [id] = { DCN2_AUX_REG_LIST(id) } + +static const struct dcn10_link_enc_aux_registers link_enc_aux_regs[] = { + aux_regs(0), + aux_regs(1), + aux_regs(2), + aux_regs(3), + aux_regs(4) +}; + +#define hpd_regs(id)\ + [id] = { HPD_REG_LIST(id) } + +static const struct dcn10_link_enc_hpd_registers link_enc_hpd_regs[] = { + hpd_regs(0), + hpd_regs(1), + hpd_regs(2), + hpd_regs(3), + hpd_regs(4) +}; + +static struct link_encoder *dcn302_link_encoder_create( + struct dc_context *ctx, + const struct encoder_init_data *enc_init_data) +{ + struct dcn20_link_encoder *enc20 = kzalloc(sizeof(struct dcn20_link_encoder), GFP_KERNEL); + + if (!enc20) + return NULL; + + dcn30_link_encoder_construct(enc20, enc_init_data, &link_enc_feature, + &link_enc_regs[enc_init_data->transmitter], &link_enc_aux_regs[enc_init_data->channel - 1], + &link_enc_hpd_regs[enc_init_data->hpd_source], &le_shift, &le_mask); + + return &enc20->enc10.base; +} + +static const struct dce_panel_cntl_registers panel_cntl_regs[] = { + { DCN_PANEL_CNTL_REG_LIST() } +}; + +static const struct dce_panel_cntl_shift panel_cntl_shift = { + DCE_PANEL_CNTL_MASK_SH_LIST(__SHIFT) +}; + +static const struct dce_panel_cntl_mask panel_cntl_mask = { + DCE_PANEL_CNTL_MASK_SH_LIST(_MASK) +}; + +static struct panel_cntl *dcn302_panel_cntl_create(const struct panel_cntl_init_data *init_data) +{ + struct dce_panel_cntl *panel_cntl = kzalloc(sizeof(struct dce_panel_cntl), GFP_KERNEL); + + if (!panel_cntl) + return NULL; + + dce_panel_cntl_construct(panel_cntl, init_data, &panel_cntl_regs[init_data->inst], + &panel_cntl_shift, &panel_cntl_mask); + + return &panel_cntl->base; +} + +static void read_dce_straps(struct dc_context *ctx, struct resource_straps *straps) +{ + generic_reg_get(ctx, mmDC_PINSTRAPS + BASE(mmDC_PINSTRAPS_BASE_IDX), + FN(DC_PINSTRAPS, DC_PINSTRAPS_AUDIO), &straps->dc_pinstraps_audio); +} + +static const struct resource_create_funcs res_create_funcs = { + .read_dce_straps = read_dce_straps, + .create_audio = dcn302_create_audio, + .create_stream_encoder = dcn302_stream_encoder_create, + .create_hwseq = dcn302_hwseq_create, +}; + +static bool is_soc_bounding_box_valid(struct dc *dc) +{ + uint32_t hw_internal_rev = dc->ctx->asic_id.hw_internal_rev; + + if (ASICREV_IS_DIMGREY_CAVEFISH_P(hw_internal_rev)) + return true; + + return false; +} + +static bool init_soc_bounding_box(struct dc *dc, struct resource_pool *pool) +{ + struct _vcs_dpi_soc_bounding_box_st *loaded_bb = &dcn3_02_soc; + struct _vcs_dpi_ip_params_st *loaded_ip = &dcn3_02_ip; + + DC_LOGGER_INIT(dc->ctx->logger); + + if (!is_soc_bounding_box_valid(dc)) { + DC_LOG_ERROR("%s: not valid soc bounding box\n", __func__); + return false; + } + + loaded_ip->max_num_otg = pool->pipe_count; + loaded_ip->max_num_dpp = pool->pipe_count; + loaded_ip->clamp_min_dcfclk = dc->config.clamp_min_dcfclk; + DC_FP_START(); + dcn20_patch_bounding_box(dc, loaded_bb); + DC_FP_END(); + + 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) { + + DC_FP_START(); + dcn302_fpu_init_soc_bounding_box(bb_info); + DC_FP_END(); + } + } + + return true; +} + +static void dcn302_resource_destruct(struct resource_pool *pool) +{ + unsigned int i; + + for (i = 0; i < pool->stream_enc_count; i++) { + if (pool->stream_enc[i] != NULL) { + if (pool->stream_enc[i]->vpg != NULL) { + kfree(DCN30_VPG_FROM_VPG(pool->stream_enc[i]->vpg)); + pool->stream_enc[i]->vpg = NULL; + } + if (pool->stream_enc[i]->afmt != NULL) { + kfree(DCN30_AFMT_FROM_AFMT(pool->stream_enc[i]->afmt)); + pool->stream_enc[i]->afmt = NULL; + } + kfree(DCN10STRENC_FROM_STRENC(pool->stream_enc[i])); + pool->stream_enc[i] = NULL; + } + } + + for (i = 0; i < pool->res_cap->num_dsc; i++) { + if (pool->dscs[i] != NULL) + dcn20_dsc_destroy(&pool->dscs[i]); + } + + if (pool->mpc != NULL) { + kfree(TO_DCN20_MPC(pool->mpc)); + pool->mpc = NULL; + } + + if (pool->hubbub != NULL) { + kfree(pool->hubbub); + pool->hubbub = NULL; + } + + for (i = 0; i < pool->pipe_count; i++) { + if (pool->dpps[i] != NULL) { + kfree(TO_DCN20_DPP(pool->dpps[i])); + pool->dpps[i] = NULL; + } + + if (pool->hubps[i] != NULL) { + kfree(TO_DCN20_HUBP(pool->hubps[i])); + pool->hubps[i] = NULL; + } + + if (pool->irqs != NULL) + dal_irq_service_destroy(&pool->irqs); + } + + for (i = 0; i < pool->res_cap->num_ddc; i++) { + if (pool->engines[i] != NULL) + dce110_engine_destroy(&pool->engines[i]); + if (pool->hw_i2cs[i] != NULL) { + kfree(pool->hw_i2cs[i]); + pool->hw_i2cs[i] = NULL; + } + if (pool->sw_i2cs[i] != NULL) { + kfree(pool->sw_i2cs[i]); + pool->sw_i2cs[i] = NULL; + } + } + + for (i = 0; i < pool->res_cap->num_opp; i++) { + if (pool->opps[i] != NULL) + pool->opps[i]->funcs->opp_destroy(&pool->opps[i]); + } + + for (i = 0; i < pool->res_cap->num_timing_generator; i++) { + if (pool->timing_generators[i] != NULL) { + kfree(DCN10TG_FROM_TG(pool->timing_generators[i])); + pool->timing_generators[i] = NULL; + } + } + + for (i = 0; i < pool->res_cap->num_dwb; i++) { + if (pool->dwbc[i] != NULL) { + kfree(TO_DCN30_DWBC(pool->dwbc[i])); + pool->dwbc[i] = NULL; + } + if (pool->mcif_wb[i] != NULL) { + kfree(TO_DCN30_MMHUBBUB(pool->mcif_wb[i])); + pool->mcif_wb[i] = NULL; + } + } + + for (i = 0; i < pool->audio_count; i++) { + if (pool->audios[i]) + dce_aud_destroy(&pool->audios[i]); + } + + for (i = 0; i < pool->clk_src_count; i++) { + if (pool->clock_sources[i] != NULL) + dcn20_clock_source_destroy(&pool->clock_sources[i]); + } + + if (pool->dp_clock_source != NULL) + dcn20_clock_source_destroy(&pool->dp_clock_source); + + for (i = 0; i < pool->res_cap->num_mpc_3dlut; i++) { + if (pool->mpc_lut[i] != NULL) { + dc_3dlut_func_release(pool->mpc_lut[i]); + pool->mpc_lut[i] = NULL; + } + if (pool->mpc_shaper[i] != NULL) { + dc_transfer_func_release(pool->mpc_shaper[i]); + pool->mpc_shaper[i] = NULL; + } + } + + for (i = 0; i < pool->pipe_count; i++) { + if (pool->multiple_abms[i] != NULL) + dce_abm_destroy(&pool->multiple_abms[i]); + } + + if (pool->psr != NULL) + dmub_psr_destroy(&pool->psr); + + if (pool->dccg != NULL) + dcn_dccg_destroy(&pool->dccg); + + if (pool->oem_device != NULL) { + struct dc *dc = pool->oem_device->ctx->dc; + + dc->link_srv->destroy_ddc_service(&pool->oem_device); + } +} + +static void dcn302_destroy_resource_pool(struct resource_pool **pool) +{ + dcn302_resource_destruct(*pool); + kfree(*pool); + *pool = NULL; +} + +void dcn302_update_bw_bounding_box(struct dc *dc, struct clk_bw_params *bw_params) +{ + DC_FP_START(); + dcn302_fpu_update_bw_bounding_box(dc, bw_params); + DC_FP_END(); +} + +static void dcn302_get_panel_config_defaults(struct dc_panel_config *panel_config) +{ + *panel_config = panel_config_defaults; +} + +static struct resource_funcs dcn302_res_pool_funcs = { + .destroy = dcn302_destroy_resource_pool, + .link_enc_create = dcn302_link_encoder_create, + .panel_cntl_create = dcn302_panel_cntl_create, + .validate_bandwidth = dcn30_validate_bandwidth, + .calculate_wm_and_dlg = dcn30_calculate_wm_and_dlg, + .update_soc_for_wm_a = dcn30_update_soc_for_wm_a, + .populate_dml_pipes = dcn30_populate_dml_pipes_from_context, + .acquire_free_pipe_as_secondary_dpp_pipe = dcn20_acquire_free_pipe_for_layer, + .release_pipe = dcn20_release_pipe, + .add_stream_to_ctx = dcn30_add_stream_to_ctx, + .add_dsc_to_stream_resource = dcn20_add_dsc_to_stream_resource, + .remove_stream_from_ctx = dcn20_remove_stream_from_ctx, + .populate_dml_writeback_from_context = dcn30_populate_dml_writeback_from_context, + .set_mcif_arb_params = dcn30_set_mcif_arb_params, + .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 = dcn302_update_bw_bounding_box, + .patch_unknown_plane_state = dcn20_patch_unknown_plane_state, + .get_panel_config_defaults = dcn302_get_panel_config_defaults, +}; + +static struct dc_cap_funcs cap_funcs = { + .get_dcc_compression_cap = dcn20_get_dcc_compression_cap +}; + +static const struct bios_registers bios_regs = { + NBIO_SR(BIOS_SCRATCH_3), + NBIO_SR(BIOS_SCRATCH_6) +}; + +static const struct dccg_registers dccg_regs = { + DCCG_REG_LIST_DCN3_02() +}; + +static const struct dccg_shift dccg_shift = { + DCCG_MASK_SH_LIST_DCN3_02(__SHIFT) +}; + +static const struct dccg_mask dccg_mask = { + DCCG_MASK_SH_LIST_DCN3_02(_MASK) +}; + +#define abm_regs(id)\ + [id] = { ABM_DCN302_REG_LIST(id) } + +static const struct dce_abm_registers abm_regs[] = { + abm_regs(0), + abm_regs(1), + abm_regs(2), + abm_regs(3), + abm_regs(4) +}; + +static const struct dce_abm_shift abm_shift = { + ABM_MASK_SH_LIST_DCN30(__SHIFT) +}; + +static const struct dce_abm_mask abm_mask = { + ABM_MASK_SH_LIST_DCN30(_MASK) +}; + +static bool dcn302_resource_construct( + uint8_t num_virtual_links, + struct dc *dc, + struct resource_pool *pool) +{ + int i; + struct dc_context *ctx = dc->ctx; + struct irq_service_init_data init_data; + struct ddc_service_init_data ddc_init_data = {0}; + + ctx->dc_bios->regs = &bios_regs; + + pool->res_cap = &res_cap_dcn302; + + pool->funcs = &dcn302_res_pool_funcs; + + /************************************************* + * Resource + asic cap harcoding * + *************************************************/ + pool->underlay_pipe_index = NO_UNDERLAY_PIPE; + pool->pipe_count = pool->res_cap->num_timing_generator; + pool->mpcc_count = pool->res_cap->num_timing_generator; + dc->caps.max_downscale_ratio = 600; + dc->caps.i2c_speed_in_khz = 100; + dc->caps.i2c_speed_in_khz_hdcp = 5; /*1.4 w/a applied by derfault*/ + 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 = 2; + dc->caps.max_slave_yuv_planes = 2; + dc->caps.max_slave_rgb_planes = 2; + dc->caps.post_blend_color_processing = true; + dc->caps.force_dp_tps4_for_cp2520 = true; + dc->caps.extended_aux_timeout_support = true; + dc->caps.dmcub_support = true; + dc->caps.max_v_total = (1 << 15) - 1; + + /* Color pipeline capabilities */ + dc->caps.color.dpp.dcn_arch = 1; + dc->caps.color.dpp.input_lut_shared = 0; + dc->caps.color.dpp.icsc = 1; + dc->caps.color.dpp.dgam_ram = 0; // must use gamma_corr + dc->caps.color.dpp.dgam_rom_caps.srgb = 1; + dc->caps.color.dpp.dgam_rom_caps.bt2020 = 1; + dc->caps.color.dpp.dgam_rom_caps.gamma2_2 = 1; + dc->caps.color.dpp.dgam_rom_caps.pq = 1; + dc->caps.color.dpp.dgam_rom_caps.hlg = 1; + dc->caps.color.dpp.post_csc = 1; + dc->caps.color.dpp.gamma_corr = 1; + dc->caps.color.dpp.dgam_rom_for_yuv = 0; + + dc->caps.color.dpp.hw_3d_lut = 1; + dc->caps.color.dpp.ogam_ram = 1; + // no OGAM ROM on DCN3 + dc->caps.color.dpp.ogam_rom_caps.srgb = 0; + dc->caps.color.dpp.ogam_rom_caps.bt2020 = 0; + dc->caps.color.dpp.ogam_rom_caps.gamma2_2 = 0; + dc->caps.color.dpp.ogam_rom_caps.pq = 0; + dc->caps.color.dpp.ogam_rom_caps.hlg = 0; + dc->caps.color.dpp.ocsc = 0; + + dc->caps.color.mpc.gamut_remap = 1; + dc->caps.color.mpc.num_3dluts = pool->res_cap->num_mpc_3dlut; //3 + dc->caps.color.mpc.ogam_ram = 1; + dc->caps.color.mpc.ogam_rom_caps.srgb = 0; + dc->caps.color.mpc.ogam_rom_caps.bt2020 = 0; + dc->caps.color.mpc.ogam_rom_caps.gamma2_2 = 0; + dc->caps.color.mpc.ogam_rom_caps.pq = 0; + dc->caps.color.mpc.ogam_rom_caps.hlg = 0; + dc->caps.color.mpc.ocsc = 1; + + dc->caps.dp_hdmi21_pcon_support = true; + + /* read VBIOS LTTPR caps */ + if (ctx->dc_bios->funcs->get_lttpr_caps) { + enum bp_result bp_query_result; + uint8_t is_vbios_lttpr_enable = 0; + + bp_query_result = ctx->dc_bios->funcs->get_lttpr_caps(ctx->dc_bios, &is_vbios_lttpr_enable); + dc->caps.vbios_lttpr_enable = (bp_query_result == BP_RESULT_OK) && !!is_vbios_lttpr_enable; + } + + if (ctx->dc_bios->funcs->get_lttpr_interop) { + enum bp_result bp_query_result; + uint8_t is_vbios_interop_enabled = 0; + + bp_query_result = ctx->dc_bios->funcs->get_lttpr_interop(ctx->dc_bios, + &is_vbios_interop_enabled); + dc->caps.vbios_lttpr_aware = (bp_query_result == BP_RESULT_OK) && !!is_vbios_interop_enabled; + } + + if (dc->ctx->dce_environment == DCE_ENV_PRODUCTION_DRV) + dc->debug = debug_defaults_drv; + + // Init the vm_helper + if (dc->vm_helper) + vm_helper_init(dc->vm_helper, 16); + + /************************************************* + * Create resources * + *************************************************/ + + /* Clock Sources for Pixel Clock*/ + pool->clock_sources[DCN302_CLK_SRC_PLL0] = + dcn302_clock_source_create(ctx, ctx->dc_bios, + CLOCK_SOURCE_COMBO_PHY_PLL0, + &clk_src_regs[0], false); + pool->clock_sources[DCN302_CLK_SRC_PLL1] = + dcn302_clock_source_create(ctx, ctx->dc_bios, + CLOCK_SOURCE_COMBO_PHY_PLL1, + &clk_src_regs[1], false); + pool->clock_sources[DCN302_CLK_SRC_PLL2] = + dcn302_clock_source_create(ctx, ctx->dc_bios, + CLOCK_SOURCE_COMBO_PHY_PLL2, + &clk_src_regs[2], false); + pool->clock_sources[DCN302_CLK_SRC_PLL3] = + dcn302_clock_source_create(ctx, ctx->dc_bios, + CLOCK_SOURCE_COMBO_PHY_PLL3, + &clk_src_regs[3], false); + pool->clock_sources[DCN302_CLK_SRC_PLL4] = + dcn302_clock_source_create(ctx, ctx->dc_bios, + CLOCK_SOURCE_COMBO_PHY_PLL4, + &clk_src_regs[4], false); + + pool->clk_src_count = DCN302_CLK_SRC_TOTAL; + + /* todo: not reuse phy_pll registers */ + pool->dp_clock_source = + dcn302_clock_source_create(ctx, ctx->dc_bios, + CLOCK_SOURCE_ID_DP_DTO, + &clk_src_regs[0], true); + + for (i = 0; i < pool->clk_src_count; i++) { + if (pool->clock_sources[i] == NULL) { + dm_error("DC: failed to create clock sources!\n"); + BREAK_TO_DEBUGGER(); + goto create_fail; + } + } + + /* DCCG */ + pool->dccg = dccg30_create(ctx, &dccg_regs, &dccg_shift, &dccg_mask); + if (pool->dccg == NULL) { + dm_error("DC: failed to create dccg!\n"); + BREAK_TO_DEBUGGER(); + goto create_fail; + } + + /* PP Lib and SMU interfaces */ + init_soc_bounding_box(dc, pool); + + /* DML */ + dml_init_instance(&dc->dml, &dcn3_02_soc, &dcn3_02_ip, DML_PROJECT_DCN30); + + /* IRQ */ + init_data.ctx = dc->ctx; + pool->irqs = dal_irq_service_dcn302_create(&init_data); + if (!pool->irqs) + goto create_fail; + + /* HUBBUB */ + pool->hubbub = dcn302_hubbub_create(ctx); + if (pool->hubbub == NULL) { + BREAK_TO_DEBUGGER(); + dm_error("DC: failed to create hubbub!\n"); + goto create_fail; + } + + /* HUBPs, DPPs, OPPs and TGs */ + for (i = 0; i < pool->pipe_count; i++) { + pool->hubps[i] = dcn302_hubp_create(ctx, i); + if (pool->hubps[i] == NULL) { + BREAK_TO_DEBUGGER(); + dm_error("DC: failed to create hubps!\n"); + goto create_fail; + } + + pool->dpps[i] = dcn302_dpp_create(ctx, i); + if (pool->dpps[i] == NULL) { + BREAK_TO_DEBUGGER(); + dm_error("DC: failed to create dpps!\n"); + goto create_fail; + } + } + + for (i = 0; i < pool->res_cap->num_opp; i++) { + pool->opps[i] = dcn302_opp_create(ctx, i); + if (pool->opps[i] == NULL) { + BREAK_TO_DEBUGGER(); + dm_error("DC: failed to create output pixel processor!\n"); + goto create_fail; + } + } + + for (i = 0; i < pool->res_cap->num_timing_generator; i++) { + pool->timing_generators[i] = dcn302_timing_generator_create(ctx, i); + if (pool->timing_generators[i] == NULL) { + BREAK_TO_DEBUGGER(); + dm_error("DC: failed to create tg!\n"); + goto create_fail; + } + } + pool->timing_generator_count = i; + + /* PSR */ + pool->psr = dmub_psr_create(ctx); + if (pool->psr == NULL) { + dm_error("DC: failed to create psr!\n"); + BREAK_TO_DEBUGGER(); + goto create_fail; + } + + /* ABMs */ + for (i = 0; i < pool->res_cap->num_timing_generator; i++) { + pool->multiple_abms[i] = dmub_abm_create(ctx, &abm_regs[i], &abm_shift, &abm_mask); + if (pool->multiple_abms[i] == NULL) { + dm_error("DC: failed to create abm for pipe %d!\n", i); + BREAK_TO_DEBUGGER(); + goto create_fail; + } + } + + /* MPC and DSC */ + pool->mpc = dcn302_mpc_create(ctx, pool->mpcc_count, pool->res_cap->num_mpc_3dlut); + if (pool->mpc == NULL) { + BREAK_TO_DEBUGGER(); + dm_error("DC: failed to create mpc!\n"); + goto create_fail; + } + + for (i = 0; i < pool->res_cap->num_dsc; i++) { + pool->dscs[i] = dcn302_dsc_create(ctx, i); + if (pool->dscs[i] == NULL) { + BREAK_TO_DEBUGGER(); + dm_error("DC: failed to create display stream compressor %d!\n", i); + goto create_fail; + } + } + + /* DWB and MMHUBBUB */ + if (!dcn302_dwbc_create(ctx, pool)) { + BREAK_TO_DEBUGGER(); + dm_error("DC: failed to create dwbc!\n"); + goto create_fail; + } + + if (!dcn302_mmhubbub_create(ctx, pool)) { + BREAK_TO_DEBUGGER(); + dm_error("DC: failed to create mcif_wb!\n"); + goto create_fail; + } + + /* AUX and I2C */ + for (i = 0; i < pool->res_cap->num_ddc; i++) { + pool->engines[i] = dcn302_aux_engine_create(ctx, i); + if (pool->engines[i] == NULL) { + BREAK_TO_DEBUGGER(); + dm_error("DC:failed to create aux engine!!\n"); + goto create_fail; + } + pool->hw_i2cs[i] = dcn302_i2c_hw_create(ctx, i); + if (pool->hw_i2cs[i] == NULL) { + BREAK_TO_DEBUGGER(); + dm_error("DC:failed to create hw i2c!!\n"); + goto create_fail; + } + pool->sw_i2cs[i] = NULL; + } + + /* Audio, Stream Encoders including HPO and virtual, MPC 3D LUTs */ + if (!resource_construct(num_virtual_links, dc, pool, + &res_create_funcs)) + goto create_fail; + + /* HW Sequencer and Plane caps */ + dcn302_hw_sequencer_construct(dc); + + dc->caps.max_planes = pool->pipe_count; + + for (i = 0; i < dc->caps.max_planes; ++i) + dc->caps.planes[i] = plane_cap; + + dc->cap_funcs = cap_funcs; + + if (dc->ctx->dc_bios->fw_info.oem_i2c_present) { + ddc_init_data.ctx = dc->ctx; + ddc_init_data.link = NULL; + ddc_init_data.id.id = dc->ctx->dc_bios->fw_info.oem_i2c_obj_id; + ddc_init_data.id.enum_id = 0; + ddc_init_data.id.type = OBJECT_TYPE_GENERIC; + pool->oem_device = dc->link_srv->create_ddc_service(&ddc_init_data); + } else { + pool->oem_device = NULL; + } + + return true; + +create_fail: + + dcn302_resource_destruct(pool); + + return false; +} + +struct resource_pool *dcn302_create_resource_pool(const struct dc_init_data *init_data, struct dc *dc) +{ + struct resource_pool *pool = kzalloc(sizeof(struct resource_pool), GFP_KERNEL); + + if (!pool) + return NULL; + + if (dcn302_resource_construct(init_data->num_virtual_links, dc, pool)) + return pool; + + BREAK_TO_DEBUGGER(); + kfree(pool); + return NULL; +} diff --git a/drivers/gpu/drm/amd/display/dc/resource/dcn302/dcn302_resource.h b/drivers/gpu/drm/amd/display/dc/resource/dcn302/dcn302_resource.h new file mode 100644 index 000000000000..9f24e73b92b3 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/resource/dcn302/dcn302_resource.h @@ -0,0 +1,38 @@ +/* + * Copyright 2020 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 _DCN302_RESOURCE_H_ +#define _DCN302_RESOURCE_H_ + +#include "core_types.h" + +extern struct _vcs_dpi_ip_params_st dcn3_02_ip; +extern struct _vcs_dpi_soc_bounding_box_st dcn3_02_soc; + +struct resource_pool *dcn302_create_resource_pool(const struct dc_init_data *init_data, struct dc *dc); + +void dcn302_update_bw_bounding_box(struct dc *dc, struct clk_bw_params *bw_params); + +#endif /* _DCN302_RESOURCE_H_ */ diff --git a/drivers/gpu/drm/amd/display/dc/resource/dcn303/dcn303_resource.c b/drivers/gpu/drm/amd/display/dc/resource/dcn303/dcn303_resource.c new file mode 100644 index 000000000000..25cd6236b054 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/resource/dcn303/dcn303_resource.c @@ -0,0 +1,1448 @@ +// SPDX-License-Identifier: MIT +/* + * Copyright (C) 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 "dcn303/dcn303_init.h" +#include "dcn303_resource.h" +#include "dcn303/dcn303_dccg.h" +#include "irq/dcn303/irq_service_dcn303.h" + +#include "dcn30/dcn30_dio_link_encoder.h" +#include "dcn30/dcn30_dio_stream_encoder.h" +#include "dcn30/dcn30_dpp.h" +#include "dcn30/dcn30_dwb.h" +#include "dcn30/dcn30_hubbub.h" +#include "dcn30/dcn30_hubp.h" +#include "dcn30/dcn30_mmhubbub.h" +#include "dcn30/dcn30_mpc.h" +#include "dcn30/dcn30_opp.h" +#include "dcn30/dcn30_optc.h" +#include "dcn30/dcn30_resource.h" + +#include "dcn20/dcn20_dsc.h" +#include "dcn20/dcn20_resource.h" + +#include "dml/dcn30/dcn30_fpu.h" + +#include "dcn10/dcn10_resource.h" + +#include "link.h" + +#include "dce/dce_abm.h" +#include "dce/dce_audio.h" +#include "dce/dce_aux.h" +#include "dce/dce_clock_source.h" +#include "dce/dce_hwseq.h" +#include "dce/dce_i2c_hw.h" +#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" +#include "resource.h" +#include "vm_helper.h" + +#include "sienna_cichlid_ip_offset.h" +#include "dcn/dcn_3_0_3_offset.h" +#include "dcn/dcn_3_0_3_sh_mask.h" +#include "dpcs/dpcs_3_0_3_offset.h" +#include "dpcs/dpcs_3_0_3_sh_mask.h" +#include "nbio/nbio_2_3_offset.h" + +#include "dml/dcn303/dcn303_fpu.h" + +#define DC_LOGGER \ + dc->ctx->logger +#define DC_LOGGER_INIT(logger) + + +static const struct dc_debug_options debug_defaults_drv = { + .disable_dmcu = true, + .force_abm_enable = false, + .timing_trace = false, + .clock_trace = true, + .disable_pplib_clock_request = true, + .pipe_split_policy = MPC_SPLIT_AVOID, + .force_single_disp_pipe_split = false, + .disable_dcc = DCC_ENABLE, + .vsr_support = true, + .performance_trace = false, + .max_downscale_src_width = 7680,/*upto 8K*/ + .disable_pplib_wm_range = false, + .scl_reset_length10 = true, + .sanity_checks = false, + .underflow_assert_delay_us = 0xFFFFFFFF, + .dwb_fi_phase = -1, // -1 = disable, + .dmub_command_table = true, + .exit_idle_opt_for_cursor_updates = true, + .disable_idle_power_optimizations = false, + .using_dml2 = false, +}; + +static const struct dc_panel_config panel_config_defaults = { + .psr = { + .disable_psr = false, + .disallow_psrsu = false, + .disallow_replay = false, + }, +}; + +enum dcn303_clk_src_array_id { + DCN303_CLK_SRC_PLL0, + DCN303_CLK_SRC_PLL1, + DCN303_CLK_SRC_TOTAL +}; + +static const struct resource_caps res_cap_dcn303 = { + .num_timing_generator = 2, + .num_opp = 2, + .num_video_plane = 2, + .num_audio = 2, + .num_stream_encoder = 2, + .num_dwb = 1, + .num_ddc = 2, + .num_vmid = 16, + .num_mpc_3dlut = 1, + .num_dsc = 2, +}; + +static const struct dc_plane_cap plane_cap = { + .type = DC_PLANE_TYPE_DCN_UNIVERSAL, + .per_pixel_alpha = true, + .pixel_format_support = { + .argb8888 = true, + .nv12 = true, + .fp16 = true, + .p010 = true, + .ayuv = false, + }, + .max_upscale_factor = { + .argb8888 = 16000, + .nv12 = 16000, + .fp16 = 16000 + }, + .max_downscale_factor = { + .argb8888 = 600, + .nv12 = 600, + .fp16 = 600 + }, + 16, + 16 +}; + +/* NBIO */ +#define NBIO_BASE_INNER(seg) \ + NBIO_BASE__INST0_SEG ## seg + +#define NBIO_BASE(seg) \ + NBIO_BASE_INNER(seg) + +#define NBIO_SR(reg_name)\ + .reg_name = NBIO_BASE(mm ## reg_name ## _BASE_IDX) + \ + mm ## reg_name + +/* DCN */ +#define BASE_INNER(seg) DCN_BASE__INST0_SEG ## seg + +#define BASE(seg) BASE_INNER(seg) + +#define SR(reg_name)\ + .reg_name = BASE(mm ## reg_name ## _BASE_IDX) + mm ## reg_name + +#define SF(reg_name, field_name, post_fix)\ + .field_name = reg_name ## __ ## field_name ## post_fix + +#define SRI(reg_name, block, id)\ + .reg_name = BASE(mm ## block ## id ## _ ## reg_name ## _BASE_IDX) + mm ## block ## id ## _ ## reg_name + +#define SRI2(reg_name, block, id)\ + .reg_name = BASE(mm ## reg_name ## _BASE_IDX) + mm ## reg_name + +#define SRII(reg_name, block, id)\ + .reg_name[id] = BASE(mm ## block ## id ## _ ## reg_name ## _BASE_IDX) + \ + mm ## block ## id ## _ ## reg_name + +#define DCCG_SRII(reg_name, block, id)\ + .block ## _ ## reg_name[id] = BASE(mm ## block ## id ## _ ## reg_name ## _BASE_IDX) + \ + mm ## block ## id ## _ ## reg_name + +#define VUPDATE_SRII(reg_name, block, id)\ + .reg_name[id] = BASE(mm ## reg_name ## _ ## block ## id ## _BASE_IDX) + \ + mm ## reg_name ## _ ## block ## id + +#define SRII_DWB(reg_name, temp_name, block, id)\ + .reg_name[id] = BASE(mm ## block ## id ## _ ## temp_name ## _BASE_IDX) + \ + mm ## block ## id ## _ ## temp_name + +#define SF_DWB2(reg_name, block, id, field_name, post_fix) \ + .field_name = reg_name ## __ ## field_name ## post_fix + +#define SRII_MPC_RMU(reg_name, block, id)\ + .RMU##_##reg_name[id] = BASE(mm ## block ## id ## _ ## reg_name ## _BASE_IDX) + \ + mm ## block ## id ## _ ## reg_name + +static const struct dcn_hubbub_registers hubbub_reg = { + HUBBUB_REG_LIST_DCN30(0) +}; + +static const struct dcn_hubbub_shift hubbub_shift = { + HUBBUB_MASK_SH_LIST_DCN30(__SHIFT) +}; + +static const struct dcn_hubbub_mask hubbub_mask = { + HUBBUB_MASK_SH_LIST_DCN30(_MASK) +}; + +#define vmid_regs(id)\ + [id] = { DCN20_VMID_REG_LIST(id) } + +static const struct dcn_vmid_registers vmid_regs[] = { + vmid_regs(0), + vmid_regs(1), + vmid_regs(2), + vmid_regs(3), + vmid_regs(4), + vmid_regs(5), + vmid_regs(6), + vmid_regs(7), + vmid_regs(8), + vmid_regs(9), + vmid_regs(10), + vmid_regs(11), + vmid_regs(12), + vmid_regs(13), + vmid_regs(14), + vmid_regs(15) +}; + +static const struct dcn20_vmid_shift vmid_shifts = { + DCN20_VMID_MASK_SH_LIST(__SHIFT) +}; + +static const struct dcn20_vmid_mask vmid_masks = { + DCN20_VMID_MASK_SH_LIST(_MASK) +}; + +static struct hubbub *dcn303_hubbub_create(struct dc_context *ctx) +{ + int i; + + struct dcn20_hubbub *hubbub3 = kzalloc(sizeof(struct dcn20_hubbub), GFP_KERNEL); + + if (!hubbub3) + return NULL; + + hubbub3_construct(hubbub3, ctx, &hubbub_reg, &hubbub_shift, &hubbub_mask); + + for (i = 0; i < res_cap_dcn303.num_vmid; i++) { + struct dcn20_vmid *vmid = &hubbub3->vmid[i]; + + vmid->ctx = ctx; + + vmid->regs = &vmid_regs[i]; + vmid->shifts = &vmid_shifts; + vmid->masks = &vmid_masks; + } + + return &hubbub3->base; +} + +#define vpg_regs(id)\ + [id] = { VPG_DCN3_REG_LIST(id) } + +static const struct dcn30_vpg_registers vpg_regs[] = { + vpg_regs(0), + vpg_regs(1), + vpg_regs(2) +}; + +static const struct dcn30_vpg_shift vpg_shift = { + DCN3_VPG_MASK_SH_LIST(__SHIFT) +}; + +static const struct dcn30_vpg_mask vpg_mask = { + DCN3_VPG_MASK_SH_LIST(_MASK) +}; + +static struct vpg *dcn303_vpg_create(struct dc_context *ctx, uint32_t inst) +{ + struct dcn30_vpg *vpg3 = kzalloc(sizeof(struct dcn30_vpg), GFP_KERNEL); + + if (!vpg3) + return NULL; + + vpg3_construct(vpg3, ctx, inst, &vpg_regs[inst], &vpg_shift, &vpg_mask); + + return &vpg3->base; +} + +#define afmt_regs(id)\ + [id] = { AFMT_DCN3_REG_LIST(id) } + +static const struct dcn30_afmt_registers afmt_regs[] = { + afmt_regs(0), + afmt_regs(1), + afmt_regs(2) +}; + +static const struct dcn30_afmt_shift afmt_shift = { + DCN3_AFMT_MASK_SH_LIST(__SHIFT) +}; + +static const struct dcn30_afmt_mask afmt_mask = { + DCN3_AFMT_MASK_SH_LIST(_MASK) +}; + +static struct afmt *dcn303_afmt_create(struct dc_context *ctx, uint32_t inst) +{ + struct dcn30_afmt *afmt3 = kzalloc(sizeof(struct dcn30_afmt), GFP_KERNEL); + + if (!afmt3) + return NULL; + + afmt3_construct(afmt3, ctx, inst, &afmt_regs[inst], &afmt_shift, &afmt_mask); + + return &afmt3->base; +} + +#define audio_regs(id)\ + [id] = { AUD_COMMON_REG_LIST(id) } + +static const struct dce_audio_registers audio_regs[] = { + audio_regs(0), + audio_regs(1), + audio_regs(2), + audio_regs(3), + audio_regs(4), + audio_regs(5), + audio_regs(6) +}; + +#define DCE120_AUD_COMMON_MASK_SH_LIST(mask_sh)\ + SF(AZF0ENDPOINT0_AZALIA_F0_CODEC_ENDPOINT_INDEX, AZALIA_ENDPOINT_REG_INDEX, mask_sh),\ + SF(AZF0ENDPOINT0_AZALIA_F0_CODEC_ENDPOINT_DATA, AZALIA_ENDPOINT_REG_DATA, mask_sh),\ + AUD_COMMON_MASK_SH_LIST_BASE(mask_sh) + +static const struct dce_audio_shift audio_shift = { + DCE120_AUD_COMMON_MASK_SH_LIST(__SHIFT) +}; + +static const struct dce_audio_mask audio_mask = { + DCE120_AUD_COMMON_MASK_SH_LIST(_MASK) +}; + +static struct audio *dcn303_create_audio(struct dc_context *ctx, unsigned int inst) +{ + return dce_audio_create(ctx, inst, &audio_regs[inst], &audio_shift, &audio_mask); +} + +#define stream_enc_regs(id)\ + [id] = { SE_DCN3_REG_LIST(id) } + +static const struct dcn10_stream_enc_registers stream_enc_regs[] = { + stream_enc_regs(0), + stream_enc_regs(1) +}; + +static const struct dcn10_stream_encoder_shift se_shift = { + SE_COMMON_MASK_SH_LIST_DCN30(__SHIFT) +}; + +static const struct dcn10_stream_encoder_mask se_mask = { + SE_COMMON_MASK_SH_LIST_DCN30(_MASK) +}; + +static struct stream_encoder *dcn303_stream_encoder_create(enum engine_id eng_id, struct dc_context *ctx) +{ + struct dcn10_stream_encoder *enc1; + struct vpg *vpg; + struct afmt *afmt; + int vpg_inst; + int afmt_inst; + + /* Mapping of VPG, AFMT, DME register blocks to DIO block instance */ + if (eng_id <= ENGINE_ID_DIGB) { + vpg_inst = eng_id; + afmt_inst = eng_id; + } else + return NULL; + + enc1 = kzalloc(sizeof(struct dcn10_stream_encoder), GFP_KERNEL); + vpg = dcn303_vpg_create(ctx, vpg_inst); + afmt = dcn303_afmt_create(ctx, afmt_inst); + + if (!enc1 || !vpg || !afmt) { + kfree(enc1); + kfree(vpg); + kfree(afmt); + return NULL; + } + + dcn30_dio_stream_encoder_construct(enc1, ctx, ctx->dc_bios, eng_id, vpg, afmt, &stream_enc_regs[eng_id], + &se_shift, &se_mask); + + return &enc1->base; +} + +#define clk_src_regs(index, pllid)\ + [index] = { CS_COMMON_REG_LIST_DCN3_03(index, pllid) } + +static const struct dce110_clk_src_regs clk_src_regs[] = { + clk_src_regs(0, A), + clk_src_regs(1, B) +}; + +static const struct dce110_clk_src_shift cs_shift = { + CS_COMMON_MASK_SH_LIST_DCN2_0(__SHIFT) +}; + +static const struct dce110_clk_src_mask cs_mask = { + CS_COMMON_MASK_SH_LIST_DCN2_0(_MASK) +}; + +static struct clock_source *dcn303_clock_source_create(struct dc_context *ctx, struct dc_bios *bios, + enum clock_source_id id, const struct dce110_clk_src_regs *regs, bool dp_clk_src) +{ + struct dce110_clk_src *clk_src = kzalloc(sizeof(struct dce110_clk_src), GFP_KERNEL); + + if (!clk_src) + return NULL; + + if (dcn3_clk_src_construct(clk_src, ctx, bios, id, regs, &cs_shift, &cs_mask)) { + clk_src->base.dp_clk_src = dp_clk_src; + return &clk_src->base; + } + + kfree(clk_src); + BREAK_TO_DEBUGGER(); + return NULL; +} + +static const struct dce_hwseq_registers hwseq_reg = { + HWSEQ_DCN303_REG_LIST() +}; + +static const struct dce_hwseq_shift hwseq_shift = { + HWSEQ_DCN303_MASK_SH_LIST(__SHIFT) +}; + +static const struct dce_hwseq_mask hwseq_mask = { + HWSEQ_DCN303_MASK_SH_LIST(_MASK) +}; + +static struct dce_hwseq *dcn303_hwseq_create(struct dc_context *ctx) +{ + struct dce_hwseq *hws = kzalloc(sizeof(struct dce_hwseq), GFP_KERNEL); + + if (hws) { + hws->ctx = ctx; + hws->regs = &hwseq_reg; + hws->shifts = &hwseq_shift; + hws->masks = &hwseq_mask; + } + return hws; +} + +#define hubp_regs(id)\ + [id] = { HUBP_REG_LIST_DCN30(id) } + +static const struct dcn_hubp2_registers hubp_regs[] = { + hubp_regs(0), + hubp_regs(1) +}; + +static const struct dcn_hubp2_shift hubp_shift = { + HUBP_MASK_SH_LIST_DCN30(__SHIFT) +}; + +static const struct dcn_hubp2_mask hubp_mask = { + HUBP_MASK_SH_LIST_DCN30(_MASK) +}; + +static struct hubp *dcn303_hubp_create(struct dc_context *ctx, uint32_t inst) +{ + struct dcn20_hubp *hubp2 = kzalloc(sizeof(struct dcn20_hubp), GFP_KERNEL); + + if (!hubp2) + return NULL; + + if (hubp3_construct(hubp2, ctx, inst, &hubp_regs[inst], &hubp_shift, &hubp_mask)) + return &hubp2->base; + + BREAK_TO_DEBUGGER(); + kfree(hubp2); + return NULL; +} + +#define dpp_regs(id)\ + [id] = { DPP_REG_LIST_DCN30(id) } + +static const struct dcn3_dpp_registers dpp_regs[] = { + dpp_regs(0), + dpp_regs(1) +}; + +static const struct dcn3_dpp_shift tf_shift = { + DPP_REG_LIST_SH_MASK_DCN30(__SHIFT) +}; + +static const struct dcn3_dpp_mask tf_mask = { + DPP_REG_LIST_SH_MASK_DCN30(_MASK) +}; + +static struct dpp *dcn303_dpp_create(struct dc_context *ctx, uint32_t inst) +{ + struct dcn3_dpp *dpp = kzalloc(sizeof(struct dcn3_dpp), GFP_KERNEL); + + if (!dpp) + return NULL; + + if (dpp3_construct(dpp, ctx, inst, &dpp_regs[inst], &tf_shift, &tf_mask)) + return &dpp->base; + + BREAK_TO_DEBUGGER(); + kfree(dpp); + return NULL; +} + +#define opp_regs(id)\ + [id] = { OPP_REG_LIST_DCN30(id) } + +static const struct dcn20_opp_registers opp_regs[] = { + opp_regs(0), + opp_regs(1) +}; + +static const struct dcn20_opp_shift opp_shift = { + OPP_MASK_SH_LIST_DCN20(__SHIFT) +}; + +static const struct dcn20_opp_mask opp_mask = { + OPP_MASK_SH_LIST_DCN20(_MASK) +}; + +static struct output_pixel_processor *dcn303_opp_create(struct dc_context *ctx, uint32_t inst) +{ + struct dcn20_opp *opp = kzalloc(sizeof(struct dcn20_opp), GFP_KERNEL); + + if (!opp) { + BREAK_TO_DEBUGGER(); + return NULL; + } + + dcn20_opp_construct(opp, ctx, inst, &opp_regs[inst], &opp_shift, &opp_mask); + return &opp->base; +} + +#define optc_regs(id)\ + [id] = { OPTC_COMMON_REG_LIST_DCN3_0(id) } + +static const struct dcn_optc_registers optc_regs[] = { + optc_regs(0), + optc_regs(1) +}; + +static const struct dcn_optc_shift optc_shift = { + OPTC_COMMON_MASK_SH_LIST_DCN30(__SHIFT) +}; + +static const struct dcn_optc_mask optc_mask = { + OPTC_COMMON_MASK_SH_LIST_DCN30(_MASK) +}; + +static struct timing_generator *dcn303_timing_generator_create(struct dc_context *ctx, uint32_t instance) +{ + struct optc *tgn10 = kzalloc(sizeof(struct optc), GFP_KERNEL); + + if (!tgn10) + return NULL; + + tgn10->base.inst = instance; + tgn10->base.ctx = ctx; + + tgn10->tg_regs = &optc_regs[instance]; + tgn10->tg_shift = &optc_shift; + tgn10->tg_mask = &optc_mask; + + dcn30_timing_generator_init(tgn10); + + return &tgn10->base; +} + +static const struct dcn30_mpc_registers mpc_regs = { + MPC_REG_LIST_DCN3_0(0), + MPC_REG_LIST_DCN3_0(1), + MPC_OUT_MUX_REG_LIST_DCN3_0(0), + MPC_OUT_MUX_REG_LIST_DCN3_0(1), + MPC_RMU_GLOBAL_REG_LIST_DCN3AG, + MPC_RMU_REG_LIST_DCN3AG(0), + MPC_DWB_MUX_REG_LIST_DCN3_0(0), +}; + +static const struct dcn30_mpc_shift mpc_shift = { + MPC_COMMON_MASK_SH_LIST_DCN303(__SHIFT) +}; + +static const struct dcn30_mpc_mask mpc_mask = { + MPC_COMMON_MASK_SH_LIST_DCN303(_MASK) +}; + +static struct mpc *dcn303_mpc_create(struct dc_context *ctx, int num_mpcc, int num_rmu) +{ + struct dcn30_mpc *mpc30 = kzalloc(sizeof(struct dcn30_mpc), GFP_KERNEL); + + if (!mpc30) + return NULL; + + dcn30_mpc_construct(mpc30, ctx, &mpc_regs, &mpc_shift, &mpc_mask, num_mpcc, num_rmu); + + return &mpc30->base; +} + +#define dsc_regsDCN20(id)\ +[id] = { DSC_REG_LIST_DCN20(id) } + +static const struct dcn20_dsc_registers dsc_regs[] = { + dsc_regsDCN20(0), + dsc_regsDCN20(1) +}; + +static const struct dcn20_dsc_shift dsc_shift = { + DSC_REG_LIST_SH_MASK_DCN20(__SHIFT) +}; + +static const struct dcn20_dsc_mask dsc_mask = { + DSC_REG_LIST_SH_MASK_DCN20(_MASK) +}; + +static struct display_stream_compressor *dcn303_dsc_create(struct dc_context *ctx, uint32_t inst) +{ + struct dcn20_dsc *dsc = kzalloc(sizeof(struct dcn20_dsc), GFP_KERNEL); + + if (!dsc) { + BREAK_TO_DEBUGGER(); + return NULL; + } + + dsc2_construct(dsc, ctx, inst, &dsc_regs[inst], &dsc_shift, &dsc_mask); + return &dsc->base; +} + +#define dwbc_regs_dcn3(id)\ +[id] = { DWBC_COMMON_REG_LIST_DCN30(id) } + +static const struct dcn30_dwbc_registers dwbc30_regs[] = { + dwbc_regs_dcn3(0) +}; + +static const struct dcn30_dwbc_shift dwbc30_shift = { + DWBC_COMMON_MASK_SH_LIST_DCN30(__SHIFT) +}; + +static const struct dcn30_dwbc_mask dwbc30_mask = { + DWBC_COMMON_MASK_SH_LIST_DCN30(_MASK) +}; + +static bool dcn303_dwbc_create(struct dc_context *ctx, struct resource_pool *pool) +{ + int i; + uint32_t pipe_count = pool->res_cap->num_dwb; + + for (i = 0; i < pipe_count; i++) { + struct dcn30_dwbc *dwbc30 = kzalloc(sizeof(struct dcn30_dwbc), GFP_KERNEL); + + if (!dwbc30) { + dm_error("DC: failed to create dwbc30!\n"); + return false; + } + + dcn30_dwbc_construct(dwbc30, ctx, &dwbc30_regs[i], &dwbc30_shift, &dwbc30_mask, i); + + pool->dwbc[i] = &dwbc30->base; + } + return true; +} + +#define mcif_wb_regs_dcn3(id)\ +[id] = { MCIF_WB_COMMON_REG_LIST_DCN30(id) } + +static const struct dcn30_mmhubbub_registers mcif_wb30_regs[] = { + mcif_wb_regs_dcn3(0) +}; + +static const struct dcn30_mmhubbub_shift mcif_wb30_shift = { + MCIF_WB_COMMON_MASK_SH_LIST_DCN30(__SHIFT) +}; + +static const struct dcn30_mmhubbub_mask mcif_wb30_mask = { + MCIF_WB_COMMON_MASK_SH_LIST_DCN30(_MASK) +}; + +static bool dcn303_mmhubbub_create(struct dc_context *ctx, struct resource_pool *pool) +{ + int i; + uint32_t pipe_count = pool->res_cap->num_dwb; + + for (i = 0; i < pipe_count; i++) { + struct dcn30_mmhubbub *mcif_wb30 = kzalloc(sizeof(struct dcn30_mmhubbub), GFP_KERNEL); + + if (!mcif_wb30) { + dm_error("DC: failed to create mcif_wb30!\n"); + return false; + } + + dcn30_mmhubbub_construct(mcif_wb30, ctx, &mcif_wb30_regs[i], &mcif_wb30_shift, &mcif_wb30_mask, i); + + pool->mcif_wb[i] = &mcif_wb30->base; + } + return true; +} + +#define aux_engine_regs(id)\ +[id] = {\ + AUX_COMMON_REG_LIST0(id), \ + .AUXN_IMPCAL = 0, \ + .AUXP_IMPCAL = 0, \ + .AUX_RESET_MASK = DP_AUX0_AUX_CONTROL__AUX_RESET_MASK, \ +} + +static const struct dce110_aux_registers aux_engine_regs[] = { + aux_engine_regs(0), + aux_engine_regs(1) +}; + +static const struct dce110_aux_registers_shift aux_shift = { + DCN_AUX_MASK_SH_LIST(__SHIFT) +}; + +static const struct dce110_aux_registers_mask aux_mask = { + DCN_AUX_MASK_SH_LIST(_MASK) +}; + +static struct dce_aux *dcn303_aux_engine_create(struct dc_context *ctx, uint32_t inst) +{ + struct aux_engine_dce110 *aux_engine = kzalloc(sizeof(struct aux_engine_dce110), GFP_KERNEL); + + if (!aux_engine) + return NULL; + + dce110_aux_engine_construct(aux_engine, ctx, inst, SW_AUX_TIMEOUT_PERIOD_MULTIPLIER * AUX_TIMEOUT_PERIOD, + &aux_engine_regs[inst], &aux_mask, &aux_shift, ctx->dc->caps.extended_aux_timeout_support); + + return &aux_engine->base; +} + +#define i2c_inst_regs(id) { I2C_HW_ENGINE_COMMON_REG_LIST(id) } + +static const struct dce_i2c_registers i2c_hw_regs[] = { + i2c_inst_regs(1), + i2c_inst_regs(2) +}; + +static const struct dce_i2c_shift i2c_shifts = { + I2C_COMMON_MASK_SH_LIST_DCN2(__SHIFT) +}; + +static const struct dce_i2c_mask i2c_masks = { + I2C_COMMON_MASK_SH_LIST_DCN2(_MASK) +}; + +static struct dce_i2c_hw *dcn303_i2c_hw_create(struct dc_context *ctx, uint32_t inst) +{ + struct dce_i2c_hw *dce_i2c_hw = kzalloc(sizeof(struct dce_i2c_hw), GFP_KERNEL); + + if (!dce_i2c_hw) + return NULL; + + dcn2_i2c_hw_construct(dce_i2c_hw, ctx, inst, &i2c_hw_regs[inst], &i2c_shifts, &i2c_masks); + + return dce_i2c_hw; +} + +static const struct encoder_feature_support link_enc_feature = { + .max_hdmi_deep_color = COLOR_DEPTH_121212, + .max_hdmi_pixel_clock = 600000, + .hdmi_ycbcr420_supported = true, + .dp_ycbcr420_supported = true, + .fec_supported = true, + .flags.bits.IS_HBR2_CAPABLE = true, + .flags.bits.IS_HBR3_CAPABLE = true, + .flags.bits.IS_TPS3_CAPABLE = true, + .flags.bits.IS_TPS4_CAPABLE = true +}; + +#define link_regs(id, phyid)\ + [id] = {\ + LE_DCN3_REG_LIST(id), \ + UNIPHY_DCN2_REG_LIST(phyid), \ + SRI(DP_DPHY_INTERNAL_CTRL, DP, id) \ + } + +static const struct dcn10_link_enc_registers link_enc_regs[] = { + link_regs(0, A), + link_regs(1, B) +}; + +static const struct dcn10_link_enc_shift le_shift = { + LINK_ENCODER_MASK_SH_LIST_DCN30(__SHIFT), + DPCS_DCN2_MASK_SH_LIST(__SHIFT) +}; + +static const struct dcn10_link_enc_mask le_mask = { + LINK_ENCODER_MASK_SH_LIST_DCN30(_MASK), + DPCS_DCN2_MASK_SH_LIST(_MASK) +}; + +#define aux_regs(id)\ + [id] = { DCN2_AUX_REG_LIST(id) } + +static const struct dcn10_link_enc_aux_registers link_enc_aux_regs[] = { + aux_regs(0), + aux_regs(1) +}; + +#define hpd_regs(id)\ + [id] = { HPD_REG_LIST(id) } + +static const struct dcn10_link_enc_hpd_registers link_enc_hpd_regs[] = { + hpd_regs(0), + hpd_regs(1) +}; + +static struct link_encoder *dcn303_link_encoder_create( + struct dc_context *ctx, + const struct encoder_init_data *enc_init_data) +{ + struct dcn20_link_encoder *enc20 = kzalloc(sizeof(struct dcn20_link_encoder), GFP_KERNEL); + + if (!enc20) + return NULL; + + dcn30_link_encoder_construct(enc20, enc_init_data, &link_enc_feature, + &link_enc_regs[enc_init_data->transmitter], &link_enc_aux_regs[enc_init_data->channel - 1], + &link_enc_hpd_regs[enc_init_data->hpd_source], &le_shift, &le_mask); + + return &enc20->enc10.base; +} + +static const struct dce_panel_cntl_registers panel_cntl_regs[] = { + { DCN_PANEL_CNTL_REG_LIST() } +}; + +static const struct dce_panel_cntl_shift panel_cntl_shift = { + DCE_PANEL_CNTL_MASK_SH_LIST(__SHIFT) +}; + +static const struct dce_panel_cntl_mask panel_cntl_mask = { + DCE_PANEL_CNTL_MASK_SH_LIST(_MASK) +}; + +static struct panel_cntl *dcn303_panel_cntl_create(const struct panel_cntl_init_data *init_data) +{ + struct dce_panel_cntl *panel_cntl = kzalloc(sizeof(struct dce_panel_cntl), GFP_KERNEL); + + if (!panel_cntl) + return NULL; + + dce_panel_cntl_construct(panel_cntl, init_data, &panel_cntl_regs[init_data->inst], + &panel_cntl_shift, &panel_cntl_mask); + + return &panel_cntl->base; +} + +static void read_dce_straps(struct dc_context *ctx, struct resource_straps *straps) +{ + generic_reg_get(ctx, mmDC_PINSTRAPS + BASE(mmDC_PINSTRAPS_BASE_IDX), + FN(DC_PINSTRAPS, DC_PINSTRAPS_AUDIO), &straps->dc_pinstraps_audio); +} + +static const struct resource_create_funcs res_create_funcs = { + .read_dce_straps = read_dce_straps, + .create_audio = dcn303_create_audio, + .create_stream_encoder = dcn303_stream_encoder_create, + .create_hwseq = dcn303_hwseq_create, +}; + +static bool is_soc_bounding_box_valid(struct dc *dc) +{ + uint32_t hw_internal_rev = dc->ctx->asic_id.hw_internal_rev; + + if (ASICREV_IS_BEIGE_GOBY_P(hw_internal_rev)) + return true; + + return false; +} + +static bool init_soc_bounding_box(struct dc *dc, struct resource_pool *pool) +{ + struct _vcs_dpi_soc_bounding_box_st *loaded_bb = &dcn3_03_soc; + struct _vcs_dpi_ip_params_st *loaded_ip = &dcn3_03_ip; + + DC_LOGGER_INIT(dc->ctx->logger); + + if (!is_soc_bounding_box_valid(dc)) { + DC_LOG_ERROR("%s: not valid soc bounding box/n", __func__); + return false; + } + + loaded_ip->max_num_otg = pool->pipe_count; + loaded_ip->max_num_dpp = pool->pipe_count; + loaded_ip->clamp_min_dcfclk = dc->config.clamp_min_dcfclk; + DC_FP_START(); + dcn20_patch_bounding_box(dc, loaded_bb); + DC_FP_END(); + + 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) { + DC_FP_START(); + dcn303_fpu_init_soc_bounding_box(bb_info); + DC_FP_END(); + } + } + + return true; +} + +static void dcn303_resource_destruct(struct resource_pool *pool) +{ + unsigned int i; + + for (i = 0; i < pool->stream_enc_count; i++) { + if (pool->stream_enc[i] != NULL) { + if (pool->stream_enc[i]->vpg != NULL) { + kfree(DCN30_VPG_FROM_VPG(pool->stream_enc[i]->vpg)); + pool->stream_enc[i]->vpg = NULL; + } + if (pool->stream_enc[i]->afmt != NULL) { + kfree(DCN30_AFMT_FROM_AFMT(pool->stream_enc[i]->afmt)); + pool->stream_enc[i]->afmt = NULL; + } + kfree(DCN10STRENC_FROM_STRENC(pool->stream_enc[i])); + pool->stream_enc[i] = NULL; + } + } + + for (i = 0; i < pool->res_cap->num_dsc; i++) { + if (pool->dscs[i] != NULL) + dcn20_dsc_destroy(&pool->dscs[i]); + } + + if (pool->mpc != NULL) { + kfree(TO_DCN20_MPC(pool->mpc)); + pool->mpc = NULL; + } + + if (pool->hubbub != NULL) { + kfree(pool->hubbub); + pool->hubbub = NULL; + } + + for (i = 0; i < pool->pipe_count; i++) { + if (pool->dpps[i] != NULL) { + kfree(TO_DCN20_DPP(pool->dpps[i])); + pool->dpps[i] = NULL; + } + + if (pool->hubps[i] != NULL) { + kfree(TO_DCN20_HUBP(pool->hubps[i])); + pool->hubps[i] = NULL; + } + + if (pool->irqs != NULL) + dal_irq_service_destroy(&pool->irqs); + } + + for (i = 0; i < pool->res_cap->num_ddc; i++) { + if (pool->engines[i] != NULL) + dce110_engine_destroy(&pool->engines[i]); + if (pool->hw_i2cs[i] != NULL) { + kfree(pool->hw_i2cs[i]); + pool->hw_i2cs[i] = NULL; + } + if (pool->sw_i2cs[i] != NULL) { + kfree(pool->sw_i2cs[i]); + pool->sw_i2cs[i] = NULL; + } + } + + for (i = 0; i < pool->res_cap->num_opp; i++) { + if (pool->opps[i] != NULL) + pool->opps[i]->funcs->opp_destroy(&pool->opps[i]); + } + + for (i = 0; i < pool->res_cap->num_timing_generator; i++) { + if (pool->timing_generators[i] != NULL) { + kfree(DCN10TG_FROM_TG(pool->timing_generators[i])); + pool->timing_generators[i] = NULL; + } + } + + for (i = 0; i < pool->res_cap->num_dwb; i++) { + if (pool->dwbc[i] != NULL) { + kfree(TO_DCN30_DWBC(pool->dwbc[i])); + pool->dwbc[i] = NULL; + } + if (pool->mcif_wb[i] != NULL) { + kfree(TO_DCN30_MMHUBBUB(pool->mcif_wb[i])); + pool->mcif_wb[i] = NULL; + } + } + + for (i = 0; i < pool->audio_count; i++) { + if (pool->audios[i]) + dce_aud_destroy(&pool->audios[i]); + } + + for (i = 0; i < pool->clk_src_count; i++) { + if (pool->clock_sources[i] != NULL) + dcn20_clock_source_destroy(&pool->clock_sources[i]); + } + + if (pool->dp_clock_source != NULL) + dcn20_clock_source_destroy(&pool->dp_clock_source); + + for (i = 0; i < pool->res_cap->num_mpc_3dlut; i++) { + if (pool->mpc_lut[i] != NULL) { + dc_3dlut_func_release(pool->mpc_lut[i]); + pool->mpc_lut[i] = NULL; + } + if (pool->mpc_shaper[i] != NULL) { + dc_transfer_func_release(pool->mpc_shaper[i]); + pool->mpc_shaper[i] = NULL; + } + } + + for (i = 0; i < pool->pipe_count; i++) { + if (pool->multiple_abms[i] != NULL) + dce_abm_destroy(&pool->multiple_abms[i]); + } + + if (pool->psr != NULL) + dmub_psr_destroy(&pool->psr); + + if (pool->dccg != NULL) + dcn_dccg_destroy(&pool->dccg); + + if (pool->oem_device != NULL) { + struct dc *dc = pool->oem_device->ctx->dc; + + dc->link_srv->destroy_ddc_service(&pool->oem_device); + } +} + +static void dcn303_destroy_resource_pool(struct resource_pool **pool) +{ + dcn303_resource_destruct(*pool); + kfree(*pool); + *pool = NULL; +} + +static void dcn303_get_panel_config_defaults(struct dc_panel_config *panel_config) +{ + *panel_config = panel_config_defaults; +} + +void dcn303_update_bw_bounding_box(struct dc *dc, struct clk_bw_params *bw_params) +{ + DC_FP_START(); + dcn303_fpu_update_bw_bounding_box(dc, bw_params); + DC_FP_END(); +} + +static struct resource_funcs dcn303_res_pool_funcs = { + .destroy = dcn303_destroy_resource_pool, + .link_enc_create = dcn303_link_encoder_create, + .panel_cntl_create = dcn303_panel_cntl_create, + .validate_bandwidth = dcn30_validate_bandwidth, + .calculate_wm_and_dlg = dcn30_calculate_wm_and_dlg, + .update_soc_for_wm_a = dcn30_update_soc_for_wm_a, + .populate_dml_pipes = dcn30_populate_dml_pipes_from_context, + .acquire_free_pipe_as_secondary_dpp_pipe = dcn20_acquire_free_pipe_for_layer, + .release_pipe = dcn20_release_pipe, + .add_stream_to_ctx = dcn30_add_stream_to_ctx, + .add_dsc_to_stream_resource = dcn20_add_dsc_to_stream_resource, + .remove_stream_from_ctx = dcn20_remove_stream_from_ctx, + .populate_dml_writeback_from_context = dcn30_populate_dml_writeback_from_context, + .set_mcif_arb_params = dcn30_set_mcif_arb_params, + .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 = dcn303_update_bw_bounding_box, + .patch_unknown_plane_state = dcn20_patch_unknown_plane_state, + .get_panel_config_defaults = dcn303_get_panel_config_defaults, +}; + +static struct dc_cap_funcs cap_funcs = { + .get_dcc_compression_cap = dcn20_get_dcc_compression_cap +}; + +static const struct bios_registers bios_regs = { + NBIO_SR(BIOS_SCRATCH_3), + NBIO_SR(BIOS_SCRATCH_6) +}; + +static const struct dccg_registers dccg_regs = { + DCCG_REG_LIST_DCN3_03() +}; + +static const struct dccg_shift dccg_shift = { + DCCG_MASK_SH_LIST_DCN3_03(__SHIFT) +}; + +static const struct dccg_mask dccg_mask = { + DCCG_MASK_SH_LIST_DCN3_03(_MASK) +}; + +#define abm_regs(id)\ + [id] = { ABM_DCN302_REG_LIST(id) } + +static const struct dce_abm_registers abm_regs[] = { + abm_regs(0), + abm_regs(1) +}; + +static const struct dce_abm_shift abm_shift = { + ABM_MASK_SH_LIST_DCN30(__SHIFT) +}; + +static const struct dce_abm_mask abm_mask = { + ABM_MASK_SH_LIST_DCN30(_MASK) +}; + +static bool dcn303_resource_construct( + uint8_t num_virtual_links, + struct dc *dc, + struct resource_pool *pool) +{ + int i; + struct dc_context *ctx = dc->ctx; + struct irq_service_init_data init_data; + struct ddc_service_init_data ddc_init_data; + + ctx->dc_bios->regs = &bios_regs; + + pool->res_cap = &res_cap_dcn303; + + pool->funcs = &dcn303_res_pool_funcs; + + /************************************************* + * Resource + asic cap harcoding * + *************************************************/ + pool->underlay_pipe_index = NO_UNDERLAY_PIPE; + pool->pipe_count = pool->res_cap->num_timing_generator; + pool->mpcc_count = pool->res_cap->num_timing_generator; + dc->caps.max_downscale_ratio = 600; + dc->caps.i2c_speed_in_khz = 100; + dc->caps.i2c_speed_in_khz_hdcp = 5; /*1.4 w/a applied by derfault*/ + 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 * + 1024 * 1024; + 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; + dc->caps.extended_aux_timeout_support = true; + dc->caps.dmcub_support = true; + dc->caps.max_v_total = (1 << 15) - 1; + + /* Color pipeline capabilities */ + dc->caps.color.dpp.dcn_arch = 1; + dc->caps.color.dpp.input_lut_shared = 0; + dc->caps.color.dpp.icsc = 1; + dc->caps.color.dpp.dgam_ram = 0; // must use gamma_corr + dc->caps.color.dpp.dgam_rom_caps.srgb = 1; + dc->caps.color.dpp.dgam_rom_caps.bt2020 = 1; + dc->caps.color.dpp.dgam_rom_caps.gamma2_2 = 1; + dc->caps.color.dpp.dgam_rom_caps.pq = 1; + dc->caps.color.dpp.dgam_rom_caps.hlg = 1; + dc->caps.color.dpp.post_csc = 1; + dc->caps.color.dpp.gamma_corr = 1; + dc->caps.color.dpp.dgam_rom_for_yuv = 0; + + dc->caps.color.dpp.hw_3d_lut = 1; + dc->caps.color.dpp.ogam_ram = 1; + // no OGAM ROM on DCN3 + dc->caps.color.dpp.ogam_rom_caps.srgb = 0; + dc->caps.color.dpp.ogam_rom_caps.bt2020 = 0; + dc->caps.color.dpp.ogam_rom_caps.gamma2_2 = 0; + dc->caps.color.dpp.ogam_rom_caps.pq = 0; + dc->caps.color.dpp.ogam_rom_caps.hlg = 0; + dc->caps.color.dpp.ocsc = 0; + + dc->caps.color.mpc.gamut_remap = 1; + dc->caps.color.mpc.num_3dluts = pool->res_cap->num_mpc_3dlut; //3 + dc->caps.color.mpc.ogam_ram = 1; + dc->caps.color.mpc.ogam_rom_caps.srgb = 0; + dc->caps.color.mpc.ogam_rom_caps.bt2020 = 0; + dc->caps.color.mpc.ogam_rom_caps.gamma2_2 = 0; + dc->caps.color.mpc.ogam_rom_caps.pq = 0; + dc->caps.color.mpc.ogam_rom_caps.hlg = 0; + dc->caps.color.mpc.ocsc = 1; + + dc->caps.dp_hdmi21_pcon_support = true; + + dc->config.dc_mode_clk_limit_support = true; + /* read VBIOS LTTPR caps */ + if (ctx->dc_bios->funcs->get_lttpr_caps) { + enum bp_result bp_query_result; + uint8_t is_vbios_lttpr_enable = 0; + + bp_query_result = ctx->dc_bios->funcs->get_lttpr_caps(ctx->dc_bios, &is_vbios_lttpr_enable); + dc->caps.vbios_lttpr_enable = (bp_query_result == BP_RESULT_OK) && !!is_vbios_lttpr_enable; + } + + if (ctx->dc_bios->funcs->get_lttpr_interop) { + enum bp_result bp_query_result; + uint8_t is_vbios_interop_enabled = 0; + + bp_query_result = ctx->dc_bios->funcs->get_lttpr_interop(ctx->dc_bios, &is_vbios_interop_enabled); + dc->caps.vbios_lttpr_aware = (bp_query_result == BP_RESULT_OK) && !!is_vbios_interop_enabled; + } + + if (dc->ctx->dce_environment == DCE_ENV_PRODUCTION_DRV) + dc->debug = debug_defaults_drv; + + // Init the vm_helper + if (dc->vm_helper) + vm_helper_init(dc->vm_helper, 16); + + /************************************************* + * Create resources * + *************************************************/ + + /* Clock Sources for Pixel Clock*/ + pool->clock_sources[DCN303_CLK_SRC_PLL0] = + dcn303_clock_source_create(ctx, ctx->dc_bios, + CLOCK_SOURCE_COMBO_PHY_PLL0, + &clk_src_regs[0], false); + pool->clock_sources[DCN303_CLK_SRC_PLL1] = + dcn303_clock_source_create(ctx, ctx->dc_bios, + CLOCK_SOURCE_COMBO_PHY_PLL1, + &clk_src_regs[1], false); + + pool->clk_src_count = DCN303_CLK_SRC_TOTAL; + + /* todo: not reuse phy_pll registers */ + pool->dp_clock_source = + dcn303_clock_source_create(ctx, ctx->dc_bios, + CLOCK_SOURCE_ID_DP_DTO, + &clk_src_regs[0], true); + + for (i = 0; i < pool->clk_src_count; i++) { + if (pool->clock_sources[i] == NULL) { + dm_error("DC: failed to create clock sources!\n"); + BREAK_TO_DEBUGGER(); + goto create_fail; + } + } + + /* DCCG */ + pool->dccg = dccg30_create(ctx, &dccg_regs, &dccg_shift, &dccg_mask); + if (pool->dccg == NULL) { + dm_error("DC: failed to create dccg!\n"); + BREAK_TO_DEBUGGER(); + goto create_fail; + } + + /* PP Lib and SMU interfaces */ + init_soc_bounding_box(dc, pool); + + /* DML */ + dml_init_instance(&dc->dml, &dcn3_03_soc, &dcn3_03_ip, DML_PROJECT_DCN30); + + /* IRQ */ + init_data.ctx = dc->ctx; + pool->irqs = dal_irq_service_dcn303_create(&init_data); + if (!pool->irqs) + goto create_fail; + + /* HUBBUB */ + pool->hubbub = dcn303_hubbub_create(ctx); + if (pool->hubbub == NULL) { + BREAK_TO_DEBUGGER(); + dm_error("DC: failed to create hubbub!\n"); + goto create_fail; + } + + /* HUBPs, DPPs, OPPs and TGs */ + for (i = 0; i < pool->pipe_count; i++) { + pool->hubps[i] = dcn303_hubp_create(ctx, i); + if (pool->hubps[i] == NULL) { + BREAK_TO_DEBUGGER(); + dm_error("DC: failed to create hubps!\n"); + goto create_fail; + } + + pool->dpps[i] = dcn303_dpp_create(ctx, i); + if (pool->dpps[i] == NULL) { + BREAK_TO_DEBUGGER(); + dm_error("DC: failed to create dpps!\n"); + goto create_fail; + } + } + + for (i = 0; i < pool->res_cap->num_opp; i++) { + pool->opps[i] = dcn303_opp_create(ctx, i); + if (pool->opps[i] == NULL) { + BREAK_TO_DEBUGGER(); + dm_error("DC: failed to create output pixel processor!\n"); + goto create_fail; + } + } + + for (i = 0; i < pool->res_cap->num_timing_generator; i++) { + pool->timing_generators[i] = dcn303_timing_generator_create(ctx, i); + if (pool->timing_generators[i] == NULL) { + BREAK_TO_DEBUGGER(); + dm_error("DC: failed to create tg!\n"); + goto create_fail; + } + } + pool->timing_generator_count = i; + + /* PSR */ + pool->psr = dmub_psr_create(ctx); + if (pool->psr == NULL) { + dm_error("DC: failed to create psr!\n"); + BREAK_TO_DEBUGGER(); + goto create_fail; + } + + /* ABM */ + for (i = 0; i < pool->res_cap->num_timing_generator; i++) { + pool->multiple_abms[i] = dmub_abm_create(ctx, &abm_regs[i], &abm_shift, &abm_mask); + if (pool->multiple_abms[i] == NULL) { + dm_error("DC: failed to create abm for pipe %d!\n", i); + BREAK_TO_DEBUGGER(); + goto create_fail; + } + } + + /* MPC and DSC */ + pool->mpc = dcn303_mpc_create(ctx, pool->mpcc_count, pool->res_cap->num_mpc_3dlut); + if (pool->mpc == NULL) { + BREAK_TO_DEBUGGER(); + dm_error("DC: failed to create mpc!\n"); + goto create_fail; + } + + for (i = 0; i < pool->res_cap->num_dsc; i++) { + pool->dscs[i] = dcn303_dsc_create(ctx, i); + if (pool->dscs[i] == NULL) { + BREAK_TO_DEBUGGER(); + dm_error("DC: failed to create display stream compressor %d!\n", i); + goto create_fail; + } + } + + /* DWB and MMHUBBUB */ + if (!dcn303_dwbc_create(ctx, pool)) { + BREAK_TO_DEBUGGER(); + dm_error("DC: failed to create dwbc!\n"); + goto create_fail; + } + + if (!dcn303_mmhubbub_create(ctx, pool)) { + BREAK_TO_DEBUGGER(); + dm_error("DC: failed to create mcif_wb!\n"); + goto create_fail; + } + + /* AUX and I2C */ + for (i = 0; i < pool->res_cap->num_ddc; i++) { + pool->engines[i] = dcn303_aux_engine_create(ctx, i); + if (pool->engines[i] == NULL) { + BREAK_TO_DEBUGGER(); + dm_error("DC:failed to create aux engine!!\n"); + goto create_fail; + } + pool->hw_i2cs[i] = dcn303_i2c_hw_create(ctx, i); + if (pool->hw_i2cs[i] == NULL) { + BREAK_TO_DEBUGGER(); + dm_error("DC:failed to create hw i2c!!\n"); + goto create_fail; + } + pool->sw_i2cs[i] = NULL; + } + + /* Audio, Stream Encoders including HPO and virtual, MPC 3D LUTs */ + if (!resource_construct(num_virtual_links, dc, pool, + &res_create_funcs)) + goto create_fail; + + /* HW Sequencer and Plane caps */ + dcn303_hw_sequencer_construct(dc); + + dc->caps.max_planes = pool->pipe_count; + + for (i = 0; i < dc->caps.max_planes; ++i) + dc->caps.planes[i] = plane_cap; + + dc->cap_funcs = cap_funcs; + + if (dc->ctx->dc_bios->fw_info.oem_i2c_present) { + ddc_init_data.ctx = dc->ctx; + ddc_init_data.link = NULL; + ddc_init_data.id.id = dc->ctx->dc_bios->fw_info.oem_i2c_obj_id; + ddc_init_data.id.enum_id = 0; + ddc_init_data.id.type = OBJECT_TYPE_GENERIC; + pool->oem_device = dc->link_srv->create_ddc_service(&ddc_init_data); + } else { + pool->oem_device = NULL; + } + + return true; + +create_fail: + + dcn303_resource_destruct(pool); + + return false; +} + +struct resource_pool *dcn303_create_resource_pool(const struct dc_init_data *init_data, struct dc *dc) +{ + struct resource_pool *pool = kzalloc(sizeof(struct resource_pool), GFP_KERNEL); + + if (!pool) + return NULL; + + if (dcn303_resource_construct(init_data->num_virtual_links, dc, pool)) + return pool; + + BREAK_TO_DEBUGGER(); + kfree(pool); + return NULL; +} diff --git a/drivers/gpu/drm/amd/display/dc/resource/dcn303/dcn303_resource.h b/drivers/gpu/drm/amd/display/dc/resource/dcn303/dcn303_resource.h new file mode 100644 index 000000000000..37cf1525820b --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/resource/dcn303/dcn303_resource.h @@ -0,0 +1,38 @@ +// SPDX-License-Identifier: MIT +/* + * Copyright (C) 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 _DCN303_RESOURCE_H_ +#define _DCN303_RESOURCE_H_ + +#include "core_types.h" + +extern struct _vcs_dpi_ip_params_st dcn3_03_ip; +extern struct _vcs_dpi_soc_bounding_box_st dcn3_03_soc; + +struct resource_pool *dcn303_create_resource_pool(const struct dc_init_data *init_data, struct dc *dc); + +void dcn303_update_bw_bounding_box(struct dc *dc, struct clk_bw_params *bw_params); + +#endif /* _DCN303_RESOURCE_H_ */ diff --git a/drivers/gpu/drm/amd/display/dc/resource/dcn31/dcn31_resource.c b/drivers/gpu/drm/amd/display/dc/resource/dcn31/dcn31_resource.c new file mode 100644 index 000000000000..31035fc3d868 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/resource/dcn31/dcn31_resource.c @@ -0,0 +1,2218 @@ +/* + * 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 + * + */ + + +#include "dm_services.h" +#include "dc.h" + +#include "dcn31/dcn31_init.h" + +#include "resource.h" +#include "include/irq_service_interface.h" +#include "dcn31_resource.h" + +#include "dcn20/dcn20_resource.h" +#include "dcn30/dcn30_resource.h" + +#include "dml/dcn30/dcn30_fpu.h" + +#include "dcn10/dcn10_ipp.h" +#include "dcn30/dcn30_hubbub.h" +#include "dcn31/dcn31_hubbub.h" +#include "dcn30/dcn30_mpc.h" +#include "dcn31/dcn31_hubp.h" +#include "irq/dcn31/irq_service_dcn31.h" +#include "dcn30/dcn30_dpp.h" +#include "dcn31/dcn31_optc.h" +#include "dcn20/dcn20_hwseq.h" +#include "dcn30/dcn30_hwseq.h" +#include "dce110/dce110_hwseq.h" +#include "dcn30/dcn30_opp.h" +#include "dcn20/dcn20_dsc.h" +#include "dcn30/dcn30_vpg.h" +#include "dcn30/dcn30_afmt.h" +#include "dcn30/dcn30_dio_stream_encoder.h" +#include "dcn31/dcn31_hpo_dp_stream_encoder.h" +#include "dcn31/dcn31_hpo_dp_link_encoder.h" +#include "dcn31/dcn31_apg.h" +#include "dcn31/dcn31_dio_link_encoder.h" +#include "dcn31/dcn31_vpg.h" +#include "dcn31/dcn31_afmt.h" +#include "dce/dce_clock_source.h" +#include "dce/dce_audio.h" +#include "dce/dce_hwseq.h" +#include "clk_mgr.h" +#include "virtual/virtual_stream_encoder.h" +#include "dce110/dce110_resource.h" +#include "dml/display_mode_vba.h" +#include "dml/dcn31/dcn31_fpu.h" +#include "dcn31/dcn31_dccg.h" +#include "dcn10/dcn10_resource.h" +#include "dcn31/dcn31_panel_cntl.h" + +#include "dcn30/dcn30_dwb.h" +#include "dcn30/dcn30_mmhubbub.h" + +// TODO: change include headers /amd/include/asic_reg after upstream +#include "yellow_carp_offset.h" +#include "dcn/dcn_3_1_2_offset.h" +#include "dcn/dcn_3_1_2_sh_mask.h" +#include "nbio/nbio_7_2_0_offset.h" +#include "dpcs/dpcs_4_2_0_offset.h" +#include "dpcs/dpcs_4_2_0_sh_mask.h" +#include "mmhub/mmhub_2_3_0_offset.h" +#include "mmhub/mmhub_2_3_0_sh_mask.h" + + +#define regDCHUBBUB_DEBUG_CTRL_0 0x04d6 +#define regDCHUBBUB_DEBUG_CTRL_0_BASE_IDX 2 +#define DCHUBBUB_DEBUG_CTRL_0__DET_DEPTH__SHIFT 0x10 +#define DCHUBBUB_DEBUG_CTRL_0__DET_DEPTH_MASK 0x01FF0000L + +#include "reg_helper.h" +#include "dce/dmub_abm.h" +#include "dce/dmub_psr.h" +#include "dce/dce_aux.h" +#include "dce/dce_i2c.h" +#include "dce/dmub_replay.h" + +#include "dml/dcn30/display_mode_vba_30.h" +#include "vm_helper.h" +#include "dcn20/dcn20_vmid.h" + +#include "link_enc_cfg.h" + +#define DC_LOGGER \ + dc->ctx->logger +#define DC_LOGGER_INIT(logger) + +enum dcn31_clk_src_array_id { + DCN31_CLK_SRC_PLL0, + DCN31_CLK_SRC_PLL1, + DCN31_CLK_SRC_PLL2, + DCN31_CLK_SRC_PLL3, + DCN31_CLK_SRC_PLL4, + DCN30_CLK_SRC_TOTAL +}; + +/* begin ********************* + * macros to expend register list macro defined in HW object header file + */ + +/* DCN */ +#define BASE_INNER(seg) DCN_BASE__INST0_SEG ## seg + +#define BASE(seg) BASE_INNER(seg) + +#define SR(reg_name)\ + .reg_name = BASE(reg ## reg_name ## _BASE_IDX) + \ + reg ## reg_name + +#define SRI(reg_name, block, id)\ + .reg_name = BASE(reg ## block ## id ## _ ## reg_name ## _BASE_IDX) + \ + reg ## block ## id ## _ ## reg_name + +#define SRI2(reg_name, block, id)\ + .reg_name = BASE(reg ## reg_name ## _BASE_IDX) + \ + reg ## reg_name + +#define SRIR(var_name, reg_name, block, id)\ + .var_name = BASE(reg ## block ## id ## _ ## reg_name ## _BASE_IDX) + \ + reg ## block ## id ## _ ## reg_name + +#define SRII(reg_name, block, id)\ + .reg_name[id] = BASE(reg ## block ## id ## _ ## reg_name ## _BASE_IDX) + \ + reg ## block ## id ## _ ## reg_name + +#define SRII_MPC_RMU(reg_name, block, id)\ + .RMU##_##reg_name[id] = BASE(reg ## block ## id ## _ ## reg_name ## _BASE_IDX) + \ + reg ## block ## id ## _ ## reg_name + +#define SRII_DWB(reg_name, temp_name, block, id)\ + .reg_name[id] = BASE(reg ## block ## id ## _ ## temp_name ## _BASE_IDX) + \ + reg ## block ## id ## _ ## temp_name + +#define SF_DWB2(reg_name, block, id, field_name, post_fix) \ + .field_name = reg_name ## __ ## field_name ## post_fix + +#define DCCG_SRII(reg_name, block, id)\ + .block ## _ ## reg_name[id] = BASE(reg ## block ## id ## _ ## reg_name ## _BASE_IDX) + \ + reg ## block ## id ## _ ## reg_name + +#define VUPDATE_SRII(reg_name, block, id)\ + .reg_name[id] = BASE(reg ## reg_name ## _ ## block ## id ## _BASE_IDX) + \ + reg ## reg_name ## _ ## block ## id + +/* NBIO */ +#define NBIO_BASE_INNER(seg) \ + NBIO_BASE__INST0_SEG ## seg + +#define NBIO_BASE(seg) \ + NBIO_BASE_INNER(seg) + +#define NBIO_SR(reg_name)\ + .reg_name = NBIO_BASE(regBIF_BX1_ ## reg_name ## _BASE_IDX) + \ + regBIF_BX1_ ## reg_name + +/* MMHUB */ +#define MMHUB_BASE_INNER(seg) \ + MMHUB_BASE__INST0_SEG ## seg + +#define MMHUB_BASE(seg) \ + MMHUB_BASE_INNER(seg) + +#define MMHUB_SR(reg_name)\ + .reg_name = MMHUB_BASE(mm ## reg_name ## _BASE_IDX) + \ + mm ## reg_name + +/* CLOCK */ +#define CLK_BASE_INNER(seg) \ + CLK_BASE__INST0_SEG ## seg + +#define CLK_BASE(seg) \ + CLK_BASE_INNER(seg) + +#define CLK_SRI(reg_name, block, inst)\ + .reg_name = CLK_BASE(reg ## block ## _ ## inst ## _ ## reg_name ## _BASE_IDX) + \ + reg ## block ## _ ## inst ## _ ## reg_name + + +static const struct bios_registers bios_regs = { + NBIO_SR(BIOS_SCRATCH_3), + NBIO_SR(BIOS_SCRATCH_6) +}; + +#define clk_src_regs(index, pllid)\ +[index] = {\ + CS_COMMON_REG_LIST_DCN3_0(index, pllid),\ +} + +static const struct dce110_clk_src_regs clk_src_regs[] = { + clk_src_regs(0, A), + clk_src_regs(1, B), + clk_src_regs(2, C), + clk_src_regs(3, D), + clk_src_regs(4, E) +}; +/*pll_id being rempped in dmub, in driver it is logical instance*/ +static const struct dce110_clk_src_regs clk_src_regs_b0[] = { + clk_src_regs(0, A), + clk_src_regs(1, B), + clk_src_regs(2, F), + clk_src_regs(3, G), + clk_src_regs(4, E) +}; + +static const struct dce110_clk_src_shift cs_shift = { + CS_COMMON_MASK_SH_LIST_DCN2_0(__SHIFT) +}; + +static const struct dce110_clk_src_mask cs_mask = { + CS_COMMON_MASK_SH_LIST_DCN2_0(_MASK) +}; + +#define abm_regs(id)\ +[id] = {\ + ABM_DCN302_REG_LIST(id)\ +} + +static const struct dce_abm_registers abm_regs[] = { + abm_regs(0), + abm_regs(1), + abm_regs(2), + abm_regs(3), +}; + +static const struct dce_abm_shift abm_shift = { + ABM_MASK_SH_LIST_DCN30(__SHIFT) +}; + +static const struct dce_abm_mask abm_mask = { + ABM_MASK_SH_LIST_DCN30(_MASK) +}; + +#define audio_regs(id)\ +[id] = {\ + AUD_COMMON_REG_LIST(id)\ +} + +static const struct dce_audio_registers audio_regs[] = { + audio_regs(0), + audio_regs(1), + audio_regs(2), + audio_regs(3), + audio_regs(4), + audio_regs(5), + audio_regs(6) +}; + +#define DCE120_AUD_COMMON_MASK_SH_LIST(mask_sh)\ + SF(AZF0ENDPOINT0_AZALIA_F0_CODEC_ENDPOINT_INDEX, AZALIA_ENDPOINT_REG_INDEX, mask_sh),\ + SF(AZF0ENDPOINT0_AZALIA_F0_CODEC_ENDPOINT_DATA, AZALIA_ENDPOINT_REG_DATA, mask_sh),\ + AUD_COMMON_MASK_SH_LIST_BASE(mask_sh) + +static const struct dce_audio_shift audio_shift = { + DCE120_AUD_COMMON_MASK_SH_LIST(__SHIFT) +}; + +static const struct dce_audio_mask audio_mask = { + DCE120_AUD_COMMON_MASK_SH_LIST(_MASK) +}; + +#define vpg_regs(id)\ +[id] = {\ + VPG_DCN31_REG_LIST(id)\ +} + +static const struct dcn31_vpg_registers vpg_regs[] = { + vpg_regs(0), + vpg_regs(1), + vpg_regs(2), + vpg_regs(3), + vpg_regs(4), + vpg_regs(5), + vpg_regs(6), + vpg_regs(7), + vpg_regs(8), + vpg_regs(9), +}; + +static const struct dcn31_vpg_shift vpg_shift = { + DCN31_VPG_MASK_SH_LIST(__SHIFT) +}; + +static const struct dcn31_vpg_mask vpg_mask = { + DCN31_VPG_MASK_SH_LIST(_MASK) +}; + +#define afmt_regs(id)\ +[id] = {\ + AFMT_DCN31_REG_LIST(id)\ +} + +static const struct dcn31_afmt_registers afmt_regs[] = { + afmt_regs(0), + afmt_regs(1), + afmt_regs(2), + afmt_regs(3), + afmt_regs(4), + afmt_regs(5) +}; + +static const struct dcn31_afmt_shift afmt_shift = { + DCN31_AFMT_MASK_SH_LIST(__SHIFT) +}; + +static const struct dcn31_afmt_mask afmt_mask = { + DCN31_AFMT_MASK_SH_LIST(_MASK) +}; + +#define apg_regs(id)\ +[id] = {\ + APG_DCN31_REG_LIST(id)\ +} + +static const struct dcn31_apg_registers apg_regs[] = { + apg_regs(0), + apg_regs(1), + apg_regs(2), + apg_regs(3) +}; + +static const struct dcn31_apg_shift apg_shift = { + DCN31_APG_MASK_SH_LIST(__SHIFT) +}; + +static const struct dcn31_apg_mask apg_mask = { + DCN31_APG_MASK_SH_LIST(_MASK) +}; + +#define stream_enc_regs(id)\ +[id] = {\ + SE_DCN3_REG_LIST(id)\ +} + +/* Some encoders won't be initialized here - but they're logical, not physical. */ +static const struct dcn10_stream_enc_registers stream_enc_regs[ENGINE_ID_COUNT] = { + stream_enc_regs(0), + stream_enc_regs(1), + stream_enc_regs(2), + stream_enc_regs(3), + stream_enc_regs(4) +}; + +static const struct dcn10_stream_encoder_shift se_shift = { + SE_COMMON_MASK_SH_LIST_DCN30(__SHIFT) +}; + +static const struct dcn10_stream_encoder_mask se_mask = { + SE_COMMON_MASK_SH_LIST_DCN30(_MASK) +}; + + +#define aux_regs(id)\ +[id] = {\ + DCN2_AUX_REG_LIST(id)\ +} + +static const struct dcn10_link_enc_aux_registers link_enc_aux_regs[] = { + aux_regs(0), + aux_regs(1), + aux_regs(2), + aux_regs(3), + aux_regs(4) +}; + +#define hpd_regs(id)\ +[id] = {\ + HPD_REG_LIST(id)\ +} + +static const struct dcn10_link_enc_hpd_registers link_enc_hpd_regs[] = { + hpd_regs(0), + hpd_regs(1), + hpd_regs(2), + hpd_regs(3), + hpd_regs(4) +}; + +#define link_regs(id, phyid)\ +[id] = {\ + LE_DCN31_REG_LIST(id), \ + UNIPHY_DCN2_REG_LIST(phyid), \ + DPCS_DCN31_REG_LIST(id), \ +} + +static const struct dce110_aux_registers_shift aux_shift = { + DCN_AUX_MASK_SH_LIST(__SHIFT) +}; + +static const struct dce110_aux_registers_mask aux_mask = { + DCN_AUX_MASK_SH_LIST(_MASK) +}; + +static const struct dcn10_link_enc_registers link_enc_regs[] = { + link_regs(0, A), + link_regs(1, B), + link_regs(2, C), + link_regs(3, D), + link_regs(4, E) +}; + +static const struct dcn10_link_enc_shift le_shift = { + LINK_ENCODER_MASK_SH_LIST_DCN31(__SHIFT), \ + DPCS_DCN31_MASK_SH_LIST(__SHIFT) +}; + +static const struct dcn10_link_enc_mask le_mask = { + LINK_ENCODER_MASK_SH_LIST_DCN31(_MASK), \ + DPCS_DCN31_MASK_SH_LIST(_MASK) +}; + +#define hpo_dp_stream_encoder_reg_list(id)\ +[id] = {\ + DCN3_1_HPO_DP_STREAM_ENC_REG_LIST(id)\ +} + +static const struct dcn31_hpo_dp_stream_encoder_registers hpo_dp_stream_enc_regs[] = { + hpo_dp_stream_encoder_reg_list(0), + hpo_dp_stream_encoder_reg_list(1), + hpo_dp_stream_encoder_reg_list(2), + hpo_dp_stream_encoder_reg_list(3), +}; + +static const struct dcn31_hpo_dp_stream_encoder_shift hpo_dp_se_shift = { + DCN3_1_HPO_DP_STREAM_ENC_MASK_SH_LIST(__SHIFT) +}; + +static const struct dcn31_hpo_dp_stream_encoder_mask hpo_dp_se_mask = { + DCN3_1_HPO_DP_STREAM_ENC_MASK_SH_LIST(_MASK) +}; + +#define hpo_dp_link_encoder_reg_list(id)\ +[id] = {\ + DCN3_1_HPO_DP_LINK_ENC_REG_LIST(id),\ + DCN3_1_RDPCSTX_REG_LIST(0),\ + DCN3_1_RDPCSTX_REG_LIST(1),\ + DCN3_1_RDPCSTX_REG_LIST(2),\ + DCN3_1_RDPCSTX_REG_LIST(3),\ + DCN3_1_RDPCSTX_REG_LIST(4)\ +} + +static const struct dcn31_hpo_dp_link_encoder_registers hpo_dp_link_enc_regs[] = { + hpo_dp_link_encoder_reg_list(0), + hpo_dp_link_encoder_reg_list(1), +}; + +static const struct dcn31_hpo_dp_link_encoder_shift hpo_dp_le_shift = { + DCN3_1_HPO_DP_LINK_ENC_MASK_SH_LIST(__SHIFT) +}; + +static const struct dcn31_hpo_dp_link_encoder_mask hpo_dp_le_mask = { + DCN3_1_HPO_DP_LINK_ENC_MASK_SH_LIST(_MASK) +}; + +#define dpp_regs(id)\ +[id] = {\ + DPP_REG_LIST_DCN30(id),\ +} + +static const struct dcn3_dpp_registers dpp_regs[] = { + dpp_regs(0), + dpp_regs(1), + dpp_regs(2), + dpp_regs(3) +}; + +static const struct dcn3_dpp_shift tf_shift = { + DPP_REG_LIST_SH_MASK_DCN30(__SHIFT) +}; + +static const struct dcn3_dpp_mask tf_mask = { + DPP_REG_LIST_SH_MASK_DCN30(_MASK) +}; + +#define opp_regs(id)\ +[id] = {\ + OPP_REG_LIST_DCN30(id),\ +} + +static const struct dcn20_opp_registers opp_regs[] = { + opp_regs(0), + opp_regs(1), + opp_regs(2), + opp_regs(3) +}; + +static const struct dcn20_opp_shift opp_shift = { + OPP_MASK_SH_LIST_DCN20(__SHIFT) +}; + +static const struct dcn20_opp_mask opp_mask = { + OPP_MASK_SH_LIST_DCN20(_MASK) +}; + +#define aux_engine_regs(id)\ +[id] = {\ + AUX_COMMON_REG_LIST0(id), \ + .AUXN_IMPCAL = 0, \ + .AUXP_IMPCAL = 0, \ + .AUX_RESET_MASK = DP_AUX0_AUX_CONTROL__AUX_RESET_MASK, \ +} + +static const struct dce110_aux_registers aux_engine_regs[] = { + aux_engine_regs(0), + aux_engine_regs(1), + aux_engine_regs(2), + aux_engine_regs(3), + aux_engine_regs(4) +}; + +#define dwbc_regs_dcn3(id)\ +[id] = {\ + DWBC_COMMON_REG_LIST_DCN30(id),\ +} + +static const struct dcn30_dwbc_registers dwbc30_regs[] = { + dwbc_regs_dcn3(0), +}; + +static const struct dcn30_dwbc_shift dwbc30_shift = { + DWBC_COMMON_MASK_SH_LIST_DCN30(__SHIFT) +}; + +static const struct dcn30_dwbc_mask dwbc30_mask = { + DWBC_COMMON_MASK_SH_LIST_DCN30(_MASK) +}; + +#define mcif_wb_regs_dcn3(id)\ +[id] = {\ + MCIF_WB_COMMON_REG_LIST_DCN30(id),\ +} + +static const struct dcn30_mmhubbub_registers mcif_wb30_regs[] = { + mcif_wb_regs_dcn3(0) +}; + +static const struct dcn30_mmhubbub_shift mcif_wb30_shift = { + MCIF_WB_COMMON_MASK_SH_LIST_DCN30(__SHIFT) +}; + +static const struct dcn30_mmhubbub_mask mcif_wb30_mask = { + MCIF_WB_COMMON_MASK_SH_LIST_DCN30(_MASK) +}; + +#define dsc_regsDCN20(id)\ +[id] = {\ + DSC_REG_LIST_DCN20(id)\ +} + +static const struct dcn20_dsc_registers dsc_regs[] = { + dsc_regsDCN20(0), + dsc_regsDCN20(1), + dsc_regsDCN20(2) +}; + +static const struct dcn20_dsc_shift dsc_shift = { + DSC_REG_LIST_SH_MASK_DCN20(__SHIFT) +}; + +static const struct dcn20_dsc_mask dsc_mask = { + DSC_REG_LIST_SH_MASK_DCN20(_MASK) +}; + +static const struct dcn30_mpc_registers mpc_regs = { + MPC_REG_LIST_DCN3_0(0), + MPC_REG_LIST_DCN3_0(1), + MPC_REG_LIST_DCN3_0(2), + MPC_REG_LIST_DCN3_0(3), + MPC_OUT_MUX_REG_LIST_DCN3_0(0), + MPC_OUT_MUX_REG_LIST_DCN3_0(1), + MPC_OUT_MUX_REG_LIST_DCN3_0(2), + MPC_OUT_MUX_REG_LIST_DCN3_0(3), + MPC_RMU_GLOBAL_REG_LIST_DCN3AG, + MPC_RMU_REG_LIST_DCN3AG(0), + MPC_RMU_REG_LIST_DCN3AG(1), + //MPC_RMU_REG_LIST_DCN3AG(2), + MPC_DWB_MUX_REG_LIST_DCN3_0(0), +}; + +static const struct dcn30_mpc_shift mpc_shift = { + MPC_COMMON_MASK_SH_LIST_DCN30(__SHIFT) +}; + +static const struct dcn30_mpc_mask mpc_mask = { + MPC_COMMON_MASK_SH_LIST_DCN30(_MASK) +}; + +#define optc_regs(id)\ +[id] = {OPTC_COMMON_REG_LIST_DCN3_1(id)} + +static const struct dcn_optc_registers optc_regs[] = { + optc_regs(0), + optc_regs(1), + optc_regs(2), + optc_regs(3) +}; + +static const struct dcn_optc_shift optc_shift = { + OPTC_COMMON_MASK_SH_LIST_DCN3_1(__SHIFT) +}; + +static const struct dcn_optc_mask optc_mask = { + OPTC_COMMON_MASK_SH_LIST_DCN3_1(_MASK) +}; + +#define hubp_regs(id)\ +[id] = {\ + HUBP_REG_LIST_DCN30(id)\ +} + +static const struct dcn_hubp2_registers hubp_regs[] = { + hubp_regs(0), + hubp_regs(1), + hubp_regs(2), + hubp_regs(3) +}; + + +static const struct dcn_hubp2_shift hubp_shift = { + HUBP_MASK_SH_LIST_DCN31(__SHIFT) +}; + +static const struct dcn_hubp2_mask hubp_mask = { + HUBP_MASK_SH_LIST_DCN31(_MASK) +}; +static const struct dcn_hubbub_registers hubbub_reg = { + HUBBUB_REG_LIST_DCN31(0) +}; + +static const struct dcn_hubbub_shift hubbub_shift = { + HUBBUB_MASK_SH_LIST_DCN31(__SHIFT) +}; + +static const struct dcn_hubbub_mask hubbub_mask = { + HUBBUB_MASK_SH_LIST_DCN31(_MASK) +}; + +static const struct dccg_registers dccg_regs = { + DCCG_REG_LIST_DCN31() +}; + +static const struct dccg_shift dccg_shift = { + DCCG_MASK_SH_LIST_DCN31(__SHIFT) +}; + +static const struct dccg_mask dccg_mask = { + DCCG_MASK_SH_LIST_DCN31(_MASK) +}; + + +#define SRII2(reg_name_pre, reg_name_post, id)\ + .reg_name_pre ## _ ## reg_name_post[id] = BASE(reg ## reg_name_pre \ + ## id ## _ ## reg_name_post ## _BASE_IDX) + \ + reg ## reg_name_pre ## id ## _ ## reg_name_post + + +#define HWSEQ_DCN31_REG_LIST()\ + SR(DCHUBBUB_GLOBAL_TIMER_CNTL), \ + SR(DCHUBBUB_ARB_HOSTVM_CNTL), \ + SR(DIO_MEM_PWR_CTRL), \ + SR(ODM_MEM_PWR_CTRL3), \ + SR(DMU_MEM_PWR_CNTL), \ + SR(MMHUBBUB_MEM_PWR_CNTL), \ + SR(DCCG_GATE_DISABLE_CNTL), \ + SR(DCCG_GATE_DISABLE_CNTL2), \ + SR(DCFCLK_CNTL),\ + SR(DC_MEM_GLOBAL_PWR_REQ_CNTL), \ + SRII(PIXEL_RATE_CNTL, OTG, 0), \ + SRII(PIXEL_RATE_CNTL, OTG, 1),\ + SRII(PIXEL_RATE_CNTL, OTG, 2),\ + SRII(PIXEL_RATE_CNTL, OTG, 3),\ + SRII(PHYPLL_PIXEL_RATE_CNTL, OTG, 0),\ + SRII(PHYPLL_PIXEL_RATE_CNTL, OTG, 1),\ + SRII(PHYPLL_PIXEL_RATE_CNTL, OTG, 2),\ + SRII(PHYPLL_PIXEL_RATE_CNTL, OTG, 3),\ + SR(MICROSECOND_TIME_BASE_DIV), \ + SR(MILLISECOND_TIME_BASE_DIV), \ + SR(DISPCLK_FREQ_CHANGE_CNTL), \ + SR(RBBMIF_TIMEOUT_DIS), \ + SR(RBBMIF_TIMEOUT_DIS_2), \ + SR(DCHUBBUB_CRC_CTRL), \ + SR(DPP_TOP0_DPP_CRC_CTRL), \ + SR(DPP_TOP0_DPP_CRC_VAL_B_A), \ + SR(DPP_TOP0_DPP_CRC_VAL_R_G), \ + SR(MPC_CRC_CTRL), \ + SR(MPC_CRC_RESULT_GB), \ + SR(MPC_CRC_RESULT_C), \ + SR(MPC_CRC_RESULT_AR), \ + SR(DOMAIN0_PG_CONFIG), \ + SR(DOMAIN1_PG_CONFIG), \ + SR(DOMAIN2_PG_CONFIG), \ + SR(DOMAIN3_PG_CONFIG), \ + SR(DOMAIN16_PG_CONFIG), \ + SR(DOMAIN17_PG_CONFIG), \ + SR(DOMAIN18_PG_CONFIG), \ + SR(DOMAIN0_PG_STATUS), \ + SR(DOMAIN1_PG_STATUS), \ + SR(DOMAIN2_PG_STATUS), \ + SR(DOMAIN3_PG_STATUS), \ + SR(DOMAIN16_PG_STATUS), \ + SR(DOMAIN17_PG_STATUS), \ + SR(DOMAIN18_PG_STATUS), \ + SR(D1VGA_CONTROL), \ + SR(D2VGA_CONTROL), \ + SR(D3VGA_CONTROL), \ + SR(D4VGA_CONTROL), \ + SR(D5VGA_CONTROL), \ + SR(D6VGA_CONTROL), \ + SR(DC_IP_REQUEST_CNTL), \ + SR(AZALIA_AUDIO_DTO), \ + SR(AZALIA_CONTROLLER_CLOCK_GATING), \ + SR(HPO_TOP_HW_CONTROL) + +static const struct dce_hwseq_registers hwseq_reg = { + HWSEQ_DCN31_REG_LIST() +}; + +#define HWSEQ_DCN31_MASK_SH_LIST(mask_sh)\ + HWSEQ_DCN_MASK_SH_LIST(mask_sh), \ + HWS_SF(, DCHUBBUB_GLOBAL_TIMER_CNTL, DCHUBBUB_GLOBAL_TIMER_REFDIV, mask_sh), \ + HWS_SF(, DCHUBBUB_ARB_HOSTVM_CNTL, DISABLE_HOSTVM_FORCE_ALLOW_PSTATE, mask_sh), \ + HWS_SF(, DOMAIN0_PG_CONFIG, DOMAIN_POWER_FORCEON, mask_sh), \ + HWS_SF(, DOMAIN0_PG_CONFIG, DOMAIN_POWER_GATE, mask_sh), \ + HWS_SF(, DOMAIN1_PG_CONFIG, DOMAIN_POWER_FORCEON, mask_sh), \ + HWS_SF(, DOMAIN1_PG_CONFIG, DOMAIN_POWER_GATE, mask_sh), \ + HWS_SF(, DOMAIN2_PG_CONFIG, DOMAIN_POWER_FORCEON, mask_sh), \ + HWS_SF(, DOMAIN2_PG_CONFIG, DOMAIN_POWER_GATE, mask_sh), \ + HWS_SF(, DOMAIN3_PG_CONFIG, DOMAIN_POWER_FORCEON, mask_sh), \ + HWS_SF(, DOMAIN3_PG_CONFIG, DOMAIN_POWER_GATE, mask_sh), \ + HWS_SF(, DOMAIN16_PG_CONFIG, DOMAIN_POWER_FORCEON, mask_sh), \ + HWS_SF(, DOMAIN16_PG_CONFIG, DOMAIN_POWER_GATE, mask_sh), \ + HWS_SF(, DOMAIN17_PG_CONFIG, DOMAIN_POWER_FORCEON, mask_sh), \ + HWS_SF(, DOMAIN17_PG_CONFIG, DOMAIN_POWER_GATE, mask_sh), \ + HWS_SF(, DOMAIN18_PG_CONFIG, DOMAIN_POWER_FORCEON, mask_sh), \ + HWS_SF(, DOMAIN18_PG_CONFIG, DOMAIN_POWER_GATE, mask_sh), \ + HWS_SF(, DOMAIN0_PG_STATUS, DOMAIN_PGFSM_PWR_STATUS, mask_sh), \ + HWS_SF(, DOMAIN1_PG_STATUS, DOMAIN_PGFSM_PWR_STATUS, mask_sh), \ + HWS_SF(, DOMAIN2_PG_STATUS, DOMAIN_PGFSM_PWR_STATUS, mask_sh), \ + HWS_SF(, DOMAIN3_PG_STATUS, DOMAIN_PGFSM_PWR_STATUS, mask_sh), \ + HWS_SF(, DOMAIN16_PG_STATUS, DOMAIN_PGFSM_PWR_STATUS, mask_sh), \ + HWS_SF(, DOMAIN17_PG_STATUS, DOMAIN_PGFSM_PWR_STATUS, mask_sh), \ + HWS_SF(, DOMAIN18_PG_STATUS, DOMAIN_PGFSM_PWR_STATUS, mask_sh), \ + HWS_SF(, DC_IP_REQUEST_CNTL, IP_REQUEST_EN, mask_sh), \ + HWS_SF(, AZALIA_AUDIO_DTO, AZALIA_AUDIO_DTO_MODULE, mask_sh), \ + HWS_SF(, HPO_TOP_CLOCK_CONTROL, HPO_HDMISTREAMCLK_G_GATE_DIS, mask_sh), \ + HWS_SF(, DMU_MEM_PWR_CNTL, DMCU_ERAM_MEM_PWR_FORCE, mask_sh), \ + HWS_SF(, ODM_MEM_PWR_CTRL3, ODM_MEM_UNASSIGNED_PWR_MODE, mask_sh), \ + HWS_SF(, ODM_MEM_PWR_CTRL3, ODM_MEM_VBLANK_PWR_MODE, mask_sh), \ + HWS_SF(, MMHUBBUB_MEM_PWR_CNTL, VGA_MEM_PWR_FORCE, mask_sh), \ + HWS_SF(, DIO_MEM_PWR_CTRL, I2C_LIGHT_SLEEP_FORCE, mask_sh), \ + HWS_SF(, HPO_TOP_HW_CONTROL, HPO_IO_EN, mask_sh) + +static const struct dce_hwseq_shift hwseq_shift = { + HWSEQ_DCN31_MASK_SH_LIST(__SHIFT) +}; + +static const struct dce_hwseq_mask hwseq_mask = { + HWSEQ_DCN31_MASK_SH_LIST(_MASK) +}; +#define vmid_regs(id)\ +[id] = {\ + DCN20_VMID_REG_LIST(id)\ +} + +static const struct dcn_vmid_registers vmid_regs[] = { + vmid_regs(0), + vmid_regs(1), + vmid_regs(2), + vmid_regs(3), + vmid_regs(4), + vmid_regs(5), + vmid_regs(6), + vmid_regs(7), + vmid_regs(8), + vmid_regs(9), + vmid_regs(10), + vmid_regs(11), + vmid_regs(12), + vmid_regs(13), + vmid_regs(14), + vmid_regs(15) +}; + +static const struct dcn20_vmid_shift vmid_shifts = { + DCN20_VMID_MASK_SH_LIST(__SHIFT) +}; + +static const struct dcn20_vmid_mask vmid_masks = { + DCN20_VMID_MASK_SH_LIST(_MASK) +}; + +static const struct resource_caps res_cap_dcn31 = { + .num_timing_generator = 4, + .num_opp = 4, + .num_video_plane = 4, + .num_audio = 5, + .num_stream_encoder = 5, + .num_dig_link_enc = 5, + .num_hpo_dp_stream_encoder = 4, + .num_hpo_dp_link_encoder = 2, + .num_pll = 5, + .num_dwb = 1, + .num_ddc = 5, + .num_vmid = 16, + .num_mpc_3dlut = 2, + .num_dsc = 3, +}; + +static const struct dc_plane_cap plane_cap = { + .type = DC_PLANE_TYPE_DCN_UNIVERSAL, + .per_pixel_alpha = true, + + .pixel_format_support = { + .argb8888 = true, + .nv12 = true, + .fp16 = true, + .p010 = true, + .ayuv = false, + }, + + .max_upscale_factor = { + .argb8888 = 16000, + .nv12 = 16000, + .fp16 = 16000 + }, + + // 6:1 downscaling ratio: 1000/6 = 166.666 + .max_downscale_factor = { + .argb8888 = 167, + .nv12 = 167, + .fp16 = 167 + }, + 64, + 64 +}; + +static const struct dc_debug_options debug_defaults_drv = { + .disable_dmcu = true, + .force_abm_enable = false, + .timing_trace = false, + .clock_trace = true, + .disable_pplib_clock_request = false, + .pipe_split_policy = MPC_SPLIT_DYNAMIC, + .force_single_disp_pipe_split = false, + .disable_dcc = DCC_ENABLE, + .vsr_support = true, + .performance_trace = false, + .max_downscale_src_width = 4096,/*upto true 4K*/ + .disable_pplib_wm_range = false, + .scl_reset_length10 = true, + .sanity_checks = true, + .underflow_assert_delay_us = 0xFFFFFFFF, + .dwb_fi_phase = -1, // -1 = disable, + .dmub_command_table = true, + .pstate_enabled = true, + .use_max_lb = true, + .enable_mem_low_power = { + .bits = { + .vga = true, + .i2c = true, + .dmcu = false, // This is previously known to cause hang on S3 cycles if enabled + .dscl = true, + .cm = true, + .mpc = true, + .optc = true, + .vpg = true, + .afmt = true, + } + }, + .disable_z10 = true, + .enable_legacy_fast_update = true, + .enable_z9_disable_interface = true, /* Allow support for the PMFW interface for disable Z9*/ + .dml_hostvm_override = DML_HOSTVM_OVERRIDE_FALSE, + .using_dml2 = false, +}; + +static const struct dc_panel_config panel_config_defaults = { + .psr = { + .disable_psr = false, + .disallow_psrsu = false, + .disallow_replay = false, + }, + .ilr = { + .optimize_edp_link_rate = true, + }, +}; + +static void dcn31_dpp_destroy(struct dpp **dpp) +{ + kfree(TO_DCN20_DPP(*dpp)); + *dpp = NULL; +} + +static struct dpp *dcn31_dpp_create( + struct dc_context *ctx, + uint32_t inst) +{ + struct dcn3_dpp *dpp = + kzalloc(sizeof(struct dcn3_dpp), GFP_KERNEL); + + if (!dpp) + return NULL; + + if (dpp3_construct(dpp, ctx, inst, + &dpp_regs[inst], &tf_shift, &tf_mask)) + return &dpp->base; + + BREAK_TO_DEBUGGER(); + kfree(dpp); + return NULL; +} + +static struct output_pixel_processor *dcn31_opp_create( + struct dc_context *ctx, uint32_t inst) +{ + struct dcn20_opp *opp = + kzalloc(sizeof(struct dcn20_opp), GFP_KERNEL); + + if (!opp) { + BREAK_TO_DEBUGGER(); + return NULL; + } + + dcn20_opp_construct(opp, ctx, inst, + &opp_regs[inst], &opp_shift, &opp_mask); + return &opp->base; +} + +static struct dce_aux *dcn31_aux_engine_create( + struct dc_context *ctx, + uint32_t inst) +{ + struct aux_engine_dce110 *aux_engine = + kzalloc(sizeof(struct aux_engine_dce110), GFP_KERNEL); + + if (!aux_engine) + return NULL; + + dce110_aux_engine_construct(aux_engine, ctx, inst, + SW_AUX_TIMEOUT_PERIOD_MULTIPLIER * AUX_TIMEOUT_PERIOD, + &aux_engine_regs[inst], + &aux_mask, + &aux_shift, + ctx->dc->caps.extended_aux_timeout_support); + + return &aux_engine->base; +} +#define i2c_inst_regs(id) { I2C_HW_ENGINE_COMMON_REG_LIST_DCN30(id) } + +static const struct dce_i2c_registers i2c_hw_regs[] = { + i2c_inst_regs(1), + i2c_inst_regs(2), + i2c_inst_regs(3), + i2c_inst_regs(4), + i2c_inst_regs(5), +}; + +static const struct dce_i2c_shift i2c_shifts = { + I2C_COMMON_MASK_SH_LIST_DCN30(__SHIFT) +}; + +static const struct dce_i2c_mask i2c_masks = { + I2C_COMMON_MASK_SH_LIST_DCN30(_MASK) +}; + +static struct dce_i2c_hw *dcn31_i2c_hw_create( + struct dc_context *ctx, + uint32_t inst) +{ + struct dce_i2c_hw *dce_i2c_hw = + kzalloc(sizeof(struct dce_i2c_hw), GFP_KERNEL); + + if (!dce_i2c_hw) + return NULL; + + dcn2_i2c_hw_construct(dce_i2c_hw, ctx, inst, + &i2c_hw_regs[inst], &i2c_shifts, &i2c_masks); + + return dce_i2c_hw; +} +static struct mpc *dcn31_mpc_create( + struct dc_context *ctx, + int num_mpcc, + int num_rmu) +{ + struct dcn30_mpc *mpc30 = kzalloc(sizeof(struct dcn30_mpc), + GFP_KERNEL); + + if (!mpc30) + return NULL; + + dcn30_mpc_construct(mpc30, ctx, + &mpc_regs, + &mpc_shift, + &mpc_mask, + num_mpcc, + num_rmu); + + return &mpc30->base; +} + +static struct hubbub *dcn31_hubbub_create(struct dc_context *ctx) +{ + int i; + + struct dcn20_hubbub *hubbub3 = kzalloc(sizeof(struct dcn20_hubbub), + GFP_KERNEL); + + if (!hubbub3) + return NULL; + + hubbub31_construct(hubbub3, ctx, + &hubbub_reg, + &hubbub_shift, + &hubbub_mask, + dcn3_1_ip.det_buffer_size_kbytes, + dcn3_1_ip.pixel_chunk_size_kbytes, + dcn3_1_ip.config_return_buffer_size_in_kbytes); + + + for (i = 0; i < res_cap_dcn31.num_vmid; i++) { + struct dcn20_vmid *vmid = &hubbub3->vmid[i]; + + vmid->ctx = ctx; + + vmid->regs = &vmid_regs[i]; + vmid->shifts = &vmid_shifts; + vmid->masks = &vmid_masks; + } + + return &hubbub3->base; +} + +static struct timing_generator *dcn31_timing_generator_create( + struct dc_context *ctx, + uint32_t instance) +{ + struct optc *tgn10 = + kzalloc(sizeof(struct optc), GFP_KERNEL); + + if (!tgn10) + return NULL; + + tgn10->base.inst = instance; + tgn10->base.ctx = ctx; + + tgn10->tg_regs = &optc_regs[instance]; + tgn10->tg_shift = &optc_shift; + tgn10->tg_mask = &optc_mask; + + dcn31_timing_generator_init(tgn10); + + return &tgn10->base; +} + +static const struct encoder_feature_support link_enc_feature = { + .max_hdmi_deep_color = COLOR_DEPTH_121212, + .max_hdmi_pixel_clock = 600000, + .hdmi_ycbcr420_supported = true, + .dp_ycbcr420_supported = true, + .fec_supported = true, + .flags.bits.IS_HBR2_CAPABLE = true, + .flags.bits.IS_HBR3_CAPABLE = true, + .flags.bits.IS_TPS3_CAPABLE = true, + .flags.bits.IS_TPS4_CAPABLE = true +}; + +static struct link_encoder *dcn31_link_encoder_create( + struct dc_context *ctx, + const struct encoder_init_data *enc_init_data) +{ + struct dcn20_link_encoder *enc20 = + kzalloc(sizeof(struct dcn20_link_encoder), GFP_KERNEL); + + if (!enc20) + return NULL; + + dcn31_link_encoder_construct(enc20, + enc_init_data, + &link_enc_feature, + &link_enc_regs[enc_init_data->transmitter], + &link_enc_aux_regs[enc_init_data->channel - 1], + &link_enc_hpd_regs[enc_init_data->hpd_source], + &le_shift, + &le_mask); + + return &enc20->enc10.base; +} + +/* Create a minimal link encoder object not associated with a particular + * physical connector. + * resource_funcs.link_enc_create_minimal + */ +static struct link_encoder *dcn31_link_enc_create_minimal( + struct dc_context *ctx, enum engine_id eng_id) +{ + struct dcn20_link_encoder *enc20; + + if ((eng_id - ENGINE_ID_DIGA) > ctx->dc->res_pool->res_cap->num_dig_link_enc) + return NULL; + + enc20 = kzalloc(sizeof(struct dcn20_link_encoder), GFP_KERNEL); + if (!enc20) + return NULL; + + dcn31_link_encoder_construct_minimal( + enc20, + ctx, + &link_enc_feature, + &link_enc_regs[eng_id - ENGINE_ID_DIGA], + eng_id); + + return &enc20->enc10.base; +} + +static struct panel_cntl *dcn31_panel_cntl_create(const struct panel_cntl_init_data *init_data) +{ + struct dcn31_panel_cntl *panel_cntl = + kzalloc(sizeof(struct dcn31_panel_cntl), GFP_KERNEL); + + if (!panel_cntl) + return NULL; + + dcn31_panel_cntl_construct(panel_cntl, init_data); + + return &panel_cntl->base; +} + +static void read_dce_straps( + struct dc_context *ctx, + struct resource_straps *straps) +{ + generic_reg_get(ctx, regDC_PINSTRAPS + BASE(regDC_PINSTRAPS_BASE_IDX), + FN(DC_PINSTRAPS, DC_PINSTRAPS_AUDIO), &straps->dc_pinstraps_audio); + +} + +static struct audio *dcn31_create_audio( + struct dc_context *ctx, unsigned int inst) +{ + return dce_audio_create(ctx, inst, + &audio_regs[inst], &audio_shift, &audio_mask); +} + +static struct vpg *dcn31_vpg_create( + struct dc_context *ctx, + uint32_t inst) +{ + struct dcn31_vpg *vpg31 = kzalloc(sizeof(struct dcn31_vpg), GFP_KERNEL); + + if (!vpg31) + return NULL; + + vpg31_construct(vpg31, ctx, inst, + &vpg_regs[inst], + &vpg_shift, + &vpg_mask); + + return &vpg31->base; +} + +static struct afmt *dcn31_afmt_create( + struct dc_context *ctx, + uint32_t inst) +{ + struct dcn31_afmt *afmt31 = kzalloc(sizeof(struct dcn31_afmt), GFP_KERNEL); + + if (!afmt31) + return NULL; + + afmt31_construct(afmt31, ctx, inst, + &afmt_regs[inst], + &afmt_shift, + &afmt_mask); + + // Light sleep by default, no need to power down here + + return &afmt31->base; +} + +static struct apg *dcn31_apg_create( + struct dc_context *ctx, + uint32_t inst) +{ + struct dcn31_apg *apg31 = kzalloc(sizeof(struct dcn31_apg), GFP_KERNEL); + + if (!apg31) + return NULL; + + apg31_construct(apg31, ctx, inst, + &apg_regs[inst], + &apg_shift, + &apg_mask); + + return &apg31->base; +} + +static struct stream_encoder *dcn31_stream_encoder_create( + enum engine_id eng_id, + struct dc_context *ctx) +{ + struct dcn10_stream_encoder *enc1; + struct vpg *vpg; + struct afmt *afmt; + int vpg_inst; + int afmt_inst; + + /* Mapping of VPG, AFMT, DME register blocks to DIO block instance */ + if (eng_id <= ENGINE_ID_DIGF) { + vpg_inst = eng_id; + afmt_inst = eng_id; + } else + return NULL; + + enc1 = kzalloc(sizeof(struct dcn10_stream_encoder), GFP_KERNEL); + vpg = dcn31_vpg_create(ctx, vpg_inst); + afmt = dcn31_afmt_create(ctx, afmt_inst); + + if (!enc1 || !vpg || !afmt) { + kfree(enc1); + kfree(vpg); + kfree(afmt); + return NULL; + } + + dcn30_dio_stream_encoder_construct(enc1, ctx, ctx->dc_bios, + eng_id, vpg, afmt, + &stream_enc_regs[eng_id], + &se_shift, &se_mask); + + return &enc1->base; +} + +static struct hpo_dp_stream_encoder *dcn31_hpo_dp_stream_encoder_create( + enum engine_id eng_id, + struct dc_context *ctx) +{ + struct dcn31_hpo_dp_stream_encoder *hpo_dp_enc31; + struct vpg *vpg; + struct apg *apg; + uint32_t hpo_dp_inst; + uint32_t vpg_inst; + uint32_t apg_inst; + + ASSERT((eng_id >= ENGINE_ID_HPO_DP_0) && (eng_id <= ENGINE_ID_HPO_DP_3)); + hpo_dp_inst = eng_id - ENGINE_ID_HPO_DP_0; + + /* Mapping of VPG register blocks to HPO DP block instance: + * VPG[6] -> HPO_DP[0] + * VPG[7] -> HPO_DP[1] + * VPG[8] -> HPO_DP[2] + * VPG[9] -> HPO_DP[3] + */ + vpg_inst = hpo_dp_inst + 6; + + /* Mapping of APG register blocks to HPO DP block instance: + * APG[0] -> HPO_DP[0] + * APG[1] -> HPO_DP[1] + * APG[2] -> HPO_DP[2] + * APG[3] -> HPO_DP[3] + */ + apg_inst = hpo_dp_inst; + + /* allocate HPO stream encoder and create VPG sub-block */ + hpo_dp_enc31 = kzalloc(sizeof(struct dcn31_hpo_dp_stream_encoder), GFP_KERNEL); + vpg = dcn31_vpg_create(ctx, vpg_inst); + apg = dcn31_apg_create(ctx, apg_inst); + + if (!hpo_dp_enc31 || !vpg || !apg) { + kfree(hpo_dp_enc31); + kfree(vpg); + kfree(apg); + return NULL; + } + + dcn31_hpo_dp_stream_encoder_construct(hpo_dp_enc31, ctx, ctx->dc_bios, + hpo_dp_inst, eng_id, vpg, apg, + &hpo_dp_stream_enc_regs[hpo_dp_inst], + &hpo_dp_se_shift, &hpo_dp_se_mask); + + return &hpo_dp_enc31->base; +} + +static struct hpo_dp_link_encoder *dcn31_hpo_dp_link_encoder_create( + uint8_t inst, + struct dc_context *ctx) +{ + struct dcn31_hpo_dp_link_encoder *hpo_dp_enc31; + + /* allocate HPO link encoder */ + hpo_dp_enc31 = kzalloc(sizeof(struct dcn31_hpo_dp_link_encoder), GFP_KERNEL); + + hpo_dp_link_encoder31_construct(hpo_dp_enc31, ctx, inst, + &hpo_dp_link_enc_regs[inst], + &hpo_dp_le_shift, &hpo_dp_le_mask); + + return &hpo_dp_enc31->base; +} + +static struct dce_hwseq *dcn31_hwseq_create( + struct dc_context *ctx) +{ + struct dce_hwseq *hws = kzalloc(sizeof(struct dce_hwseq), GFP_KERNEL); + + if (hws) { + hws->ctx = ctx; + hws->regs = &hwseq_reg; + hws->shifts = &hwseq_shift; + hws->masks = &hwseq_mask; + } + return hws; +} +static const struct resource_create_funcs res_create_funcs = { + .read_dce_straps = read_dce_straps, + .create_audio = dcn31_create_audio, + .create_stream_encoder = dcn31_stream_encoder_create, + .create_hpo_dp_stream_encoder = dcn31_hpo_dp_stream_encoder_create, + .create_hpo_dp_link_encoder = dcn31_hpo_dp_link_encoder_create, + .create_hwseq = dcn31_hwseq_create, +}; + +static void dcn31_resource_destruct(struct dcn31_resource_pool *pool) +{ + unsigned int i; + + for (i = 0; i < pool->base.stream_enc_count; i++) { + if (pool->base.stream_enc[i] != NULL) { + if (pool->base.stream_enc[i]->vpg != NULL) { + kfree(DCN30_VPG_FROM_VPG(pool->base.stream_enc[i]->vpg)); + pool->base.stream_enc[i]->vpg = NULL; + } + if (pool->base.stream_enc[i]->afmt != NULL) { + kfree(DCN30_AFMT_FROM_AFMT(pool->base.stream_enc[i]->afmt)); + pool->base.stream_enc[i]->afmt = NULL; + } + kfree(DCN10STRENC_FROM_STRENC(pool->base.stream_enc[i])); + pool->base.stream_enc[i] = NULL; + } + } + + for (i = 0; i < pool->base.hpo_dp_stream_enc_count; i++) { + if (pool->base.hpo_dp_stream_enc[i] != NULL) { + if (pool->base.hpo_dp_stream_enc[i]->vpg != NULL) { + kfree(DCN30_VPG_FROM_VPG(pool->base.hpo_dp_stream_enc[i]->vpg)); + pool->base.hpo_dp_stream_enc[i]->vpg = NULL; + } + if (pool->base.hpo_dp_stream_enc[i]->apg != NULL) { + kfree(DCN31_APG_FROM_APG(pool->base.hpo_dp_stream_enc[i]->apg)); + pool->base.hpo_dp_stream_enc[i]->apg = NULL; + } + kfree(DCN3_1_HPO_DP_STREAM_ENC_FROM_HPO_STREAM_ENC(pool->base.hpo_dp_stream_enc[i])); + pool->base.hpo_dp_stream_enc[i] = NULL; + } + } + + for (i = 0; i < pool->base.hpo_dp_link_enc_count; i++) { + if (pool->base.hpo_dp_link_enc[i] != NULL) { + kfree(DCN3_1_HPO_DP_LINK_ENC_FROM_HPO_LINK_ENC(pool->base.hpo_dp_link_enc[i])); + pool->base.hpo_dp_link_enc[i] = NULL; + } + } + + for (i = 0; i < pool->base.res_cap->num_dsc; i++) { + if (pool->base.dscs[i] != NULL) + dcn20_dsc_destroy(&pool->base.dscs[i]); + } + + if (pool->base.mpc != NULL) { + kfree(TO_DCN20_MPC(pool->base.mpc)); + pool->base.mpc = NULL; + } + if (pool->base.hubbub != NULL) { + kfree(pool->base.hubbub); + pool->base.hubbub = NULL; + } + for (i = 0; i < pool->base.pipe_count; i++) { + if (pool->base.dpps[i] != NULL) + dcn31_dpp_destroy(&pool->base.dpps[i]); + + if (pool->base.ipps[i] != NULL) + pool->base.ipps[i]->funcs->ipp_destroy(&pool->base.ipps[i]); + + if (pool->base.hubps[i] != NULL) { + kfree(TO_DCN20_HUBP(pool->base.hubps[i])); + pool->base.hubps[i] = NULL; + } + + if (pool->base.irqs != NULL) { + dal_irq_service_destroy(&pool->base.irqs); + } + } + + for (i = 0; i < pool->base.res_cap->num_ddc; i++) { + if (pool->base.engines[i] != NULL) + dce110_engine_destroy(&pool->base.engines[i]); + if (pool->base.hw_i2cs[i] != NULL) { + kfree(pool->base.hw_i2cs[i]); + pool->base.hw_i2cs[i] = NULL; + } + if (pool->base.sw_i2cs[i] != NULL) { + kfree(pool->base.sw_i2cs[i]); + pool->base.sw_i2cs[i] = NULL; + } + } + + for (i = 0; i < pool->base.res_cap->num_opp; i++) { + if (pool->base.opps[i] != NULL) + pool->base.opps[i]->funcs->opp_destroy(&pool->base.opps[i]); + } + + for (i = 0; i < pool->base.res_cap->num_timing_generator; i++) { + if (pool->base.timing_generators[i] != NULL) { + kfree(DCN10TG_FROM_TG(pool->base.timing_generators[i])); + pool->base.timing_generators[i] = NULL; + } + } + + for (i = 0; i < pool->base.res_cap->num_dwb; i++) { + if (pool->base.dwbc[i] != NULL) { + kfree(TO_DCN30_DWBC(pool->base.dwbc[i])); + pool->base.dwbc[i] = NULL; + } + if (pool->base.mcif_wb[i] != NULL) { + kfree(TO_DCN30_MMHUBBUB(pool->base.mcif_wb[i])); + pool->base.mcif_wb[i] = NULL; + } + } + + for (i = 0; i < pool->base.audio_count; i++) { + if (pool->base.audios[i]) + dce_aud_destroy(&pool->base.audios[i]); + } + + for (i = 0; i < pool->base.clk_src_count; i++) { + if (pool->base.clock_sources[i] != NULL) { + dcn20_clock_source_destroy(&pool->base.clock_sources[i]); + pool->base.clock_sources[i] = NULL; + } + } + + for (i = 0; i < pool->base.res_cap->num_mpc_3dlut; i++) { + if (pool->base.mpc_lut[i] != NULL) { + dc_3dlut_func_release(pool->base.mpc_lut[i]); + pool->base.mpc_lut[i] = NULL; + } + if (pool->base.mpc_shaper[i] != NULL) { + dc_transfer_func_release(pool->base.mpc_shaper[i]); + pool->base.mpc_shaper[i] = NULL; + } + } + + if (pool->base.dp_clock_source != NULL) { + dcn20_clock_source_destroy(&pool->base.dp_clock_source); + pool->base.dp_clock_source = NULL; + } + + for (i = 0; i < pool->base.res_cap->num_timing_generator; i++) { + if (pool->base.multiple_abms[i] != NULL) + dce_abm_destroy(&pool->base.multiple_abms[i]); + } + + if (pool->base.psr != NULL) + dmub_psr_destroy(&pool->base.psr); + + if (pool->base.replay != NULL) + dmub_replay_destroy(&pool->base.replay); + + if (pool->base.dccg != NULL) + dcn_dccg_destroy(&pool->base.dccg); +} + +static struct hubp *dcn31_hubp_create( + struct dc_context *ctx, + uint32_t inst) +{ + struct dcn20_hubp *hubp2 = + kzalloc(sizeof(struct dcn20_hubp), GFP_KERNEL); + + if (!hubp2) + return NULL; + + if (hubp31_construct(hubp2, ctx, inst, + &hubp_regs[inst], &hubp_shift, &hubp_mask)) + return &hubp2->base; + + BREAK_TO_DEBUGGER(); + kfree(hubp2); + return NULL; +} + +static bool dcn31_dwbc_create(struct dc_context *ctx, struct resource_pool *pool) +{ + int i; + uint32_t pipe_count = pool->res_cap->num_dwb; + + for (i = 0; i < pipe_count; i++) { + struct dcn30_dwbc *dwbc30 = kzalloc(sizeof(struct dcn30_dwbc), + GFP_KERNEL); + + if (!dwbc30) { + dm_error("DC: failed to create dwbc30!\n"); + return false; + } + + dcn30_dwbc_construct(dwbc30, ctx, + &dwbc30_regs[i], + &dwbc30_shift, + &dwbc30_mask, + i); + + pool->dwbc[i] = &dwbc30->base; + } + return true; +} + +static bool dcn31_mmhubbub_create(struct dc_context *ctx, struct resource_pool *pool) +{ + int i; + uint32_t pipe_count = pool->res_cap->num_dwb; + + for (i = 0; i < pipe_count; i++) { + struct dcn30_mmhubbub *mcif_wb30 = kzalloc(sizeof(struct dcn30_mmhubbub), + GFP_KERNEL); + + if (!mcif_wb30) { + dm_error("DC: failed to create mcif_wb30!\n"); + return false; + } + + dcn30_mmhubbub_construct(mcif_wb30, ctx, + &mcif_wb30_regs[i], + &mcif_wb30_shift, + &mcif_wb30_mask, + i); + + pool->mcif_wb[i] = &mcif_wb30->base; + } + return true; +} + +static struct display_stream_compressor *dcn31_dsc_create( + struct dc_context *ctx, uint32_t inst) +{ + struct dcn20_dsc *dsc = + kzalloc(sizeof(struct dcn20_dsc), GFP_KERNEL); + + if (!dsc) { + BREAK_TO_DEBUGGER(); + return NULL; + } + + dsc2_construct(dsc, ctx, inst, &dsc_regs[inst], &dsc_shift, &dsc_mask); + return &dsc->base; +} + +static void dcn31_destroy_resource_pool(struct resource_pool **pool) +{ + struct dcn31_resource_pool *dcn31_pool = TO_DCN31_RES_POOL(*pool); + + dcn31_resource_destruct(dcn31_pool); + kfree(dcn31_pool); + *pool = NULL; +} + +static struct clock_source *dcn31_clock_source_create( + struct dc_context *ctx, + struct dc_bios *bios, + enum clock_source_id id, + const struct dce110_clk_src_regs *regs, + bool dp_clk_src) +{ + struct dce110_clk_src *clk_src = + kzalloc(sizeof(struct dce110_clk_src), GFP_KERNEL); + + if (!clk_src) + return NULL; + + if (dcn3_clk_src_construct(clk_src, ctx, bios, id, + regs, &cs_shift, &cs_mask)) { + clk_src->base.dp_clk_src = dp_clk_src; + return &clk_src->base; + } + + kfree(clk_src); + BREAK_TO_DEBUGGER(); + return NULL; +} + +static bool is_dual_plane(enum surface_pixel_format format) +{ + return format >= SURFACE_PIXEL_FORMAT_VIDEO_BEGIN || format == SURFACE_PIXEL_FORMAT_GRPH_RGBE_ALPHA; +} + +int dcn31x_populate_dml_pipes_from_context(struct dc *dc, + struct dc_state *context, + display_e2e_pipe_params_st *pipes, + bool fast_validate) +{ + uint32_t pipe_cnt; + int i; + + dc_assert_fp_enabled(); + + pipe_cnt = dcn20_populate_dml_pipes_from_context(dc, context, pipes, fast_validate); + + for (i = 0; i < pipe_cnt; i++) { + pipes[i].pipe.src.gpuvm = 1; + if (dc->debug.dml_hostvm_override == DML_HOSTVM_NO_OVERRIDE) { + //pipes[pipe_cnt].pipe.src.hostvm = dc->res_pool->hubbub->riommu_active; + pipes[i].pipe.src.hostvm = dc->vm_pa_config.is_hvm_enabled; + } else if (dc->debug.dml_hostvm_override == DML_HOSTVM_OVERRIDE_FALSE) + pipes[i].pipe.src.hostvm = false; + else if (dc->debug.dml_hostvm_override == DML_HOSTVM_OVERRIDE_TRUE) + pipes[i].pipe.src.hostvm = true; + } + return pipe_cnt; +} + +int dcn31_populate_dml_pipes_from_context( + struct dc *dc, struct dc_state *context, + display_e2e_pipe_params_st *pipes, + bool fast_validate) +{ + int i, pipe_cnt; + struct resource_context *res_ctx = &context->res_ctx; + struct pipe_ctx *pipe; + bool upscaled = false; + + DC_FP_START(); + dcn31x_populate_dml_pipes_from_context(dc, context, pipes, fast_validate); + DC_FP_END(); + + for (i = 0, pipe_cnt = 0; i < dc->res_pool->pipe_count; i++) { + struct dc_crtc_timing *timing; + + if (!res_ctx->pipe_ctx[i].stream) + continue; + pipe = &res_ctx->pipe_ctx[i]; + timing = &pipe->stream->timing; + if (pipe->plane_state && + (pipe->plane_state->src_rect.height < pipe->plane_state->dst_rect.height || + pipe->plane_state->src_rect.width < pipe->plane_state->dst_rect.width)) + upscaled = true; + + /* + * Immediate flip can be set dynamically after enabling the plane. + * We need to require support for immediate flip or underflow can be + * intermittently experienced depending on peak b/w requirements. + */ + pipes[pipe_cnt].pipe.src.immediate_flip = true; + pipes[pipe_cnt].pipe.src.unbounded_req_mode = false; + pipes[pipe_cnt].pipe.src.gpuvm = true; + pipes[pipe_cnt].pipe.dest.vfront_porch = timing->v_front_porch; + pipes[pipe_cnt].pipe.src.dcc_rate = 3; + pipes[pipe_cnt].dout.dsc_input_bpc = 0; + DC_FP_START(); + dcn31_zero_pipe_dcc_fraction(pipes, pipe_cnt); + DC_FP_END(); + + + if (pipes[pipe_cnt].dout.dsc_enable) { + switch (timing->display_color_depth) { + case COLOR_DEPTH_888: + pipes[pipe_cnt].dout.dsc_input_bpc = 8; + break; + case COLOR_DEPTH_101010: + pipes[pipe_cnt].dout.dsc_input_bpc = 10; + break; + case COLOR_DEPTH_121212: + pipes[pipe_cnt].dout.dsc_input_bpc = 12; + break; + default: + ASSERT(0); + break; + } + } + + pipe_cnt++; + } + context->bw_ctx.dml.ip.det_buffer_size_kbytes = DCN3_1_DEFAULT_DET_SIZE; + dc->config.enable_4to1MPC = false; + if (pipe_cnt == 1 && pipe->plane_state && !dc->debug.disable_z9_mpc) { + if (is_dual_plane(pipe->plane_state->format) + && pipe->plane_state->src_rect.width <= 1920 && pipe->plane_state->src_rect.height <= 1080) { + dc->config.enable_4to1MPC = true; + } else if (!is_dual_plane(pipe->plane_state->format) && pipe->plane_state->src_rect.width <= 5120) { + /* Limit to 5k max to avoid forced pipe split when there is not enough detile for swath */ + context->bw_ctx.dml.ip.det_buffer_size_kbytes = 192; + pipes[0].pipe.src.unbounded_req_mode = true; + } + } else if (context->stream_count >= dc->debug.crb_alloc_policy_min_disp_count + && dc->debug.crb_alloc_policy > DET_SIZE_DEFAULT) { + context->bw_ctx.dml.ip.det_buffer_size_kbytes = dc->debug.crb_alloc_policy * 64; + } else if (context->stream_count >= 3 && upscaled) { + context->bw_ctx.dml.ip.det_buffer_size_kbytes = 192; + } + + return pipe_cnt; +} + +void dcn31_calculate_wm_and_dlg( + struct dc *dc, struct dc_state *context, + display_e2e_pipe_params_st *pipes, + int pipe_cnt, + int vlevel) +{ + DC_FP_START(); + dcn31_calculate_wm_and_dlg_fp(dc, context, pipes, pipe_cnt, vlevel); + DC_FP_END(); +} + +void +dcn31_populate_dml_writeback_from_context(struct dc *dc, + struct resource_context *res_ctx, + display_e2e_pipe_params_st *pipes) +{ + DC_FP_START(); + dcn30_populate_dml_writeback_from_context(dc, res_ctx, pipes); + DC_FP_END(); +} + +void +dcn31_set_mcif_arb_params(struct dc *dc, + struct dc_state *context, + display_e2e_pipe_params_st *pipes, + int pipe_cnt) +{ + DC_FP_START(); + dcn30_set_mcif_arb_params(dc, context, pipes, pipe_cnt); + DC_FP_END(); +} + +bool dcn31_validate_bandwidth(struct dc *dc, + struct dc_state *context, + bool fast_validate) +{ + bool out = false; + + BW_VAL_TRACE_SETUP(); + + int vlevel = 0; + int pipe_cnt = 0; + display_e2e_pipe_params_st *pipes = kzalloc(dc->res_pool->pipe_count * sizeof(display_e2e_pipe_params_st), GFP_KERNEL); + DC_LOGGER_INIT(dc->ctx->logger); + + BW_VAL_TRACE_COUNT(); + + DC_FP_START(); + out = dcn30_internal_validate_bw(dc, context, pipes, &pipe_cnt, &vlevel, fast_validate, true); + DC_FP_END(); + + // Disable fast_validate to set min dcfclk in alculate_wm_and_dlg + if (pipe_cnt == 0) + fast_validate = false; + + if (!out) + goto validate_fail; + + BW_VAL_TRACE_END_VOLTAGE_LEVEL(); + + if (fast_validate) { + BW_VAL_TRACE_SKIP(fast); + goto validate_out; + } + if (dc->res_pool->funcs->calculate_wm_and_dlg) + dc->res_pool->funcs->calculate_wm_and_dlg(dc, context, pipes, pipe_cnt, vlevel); + + BW_VAL_TRACE_END_WATERMARKS(); + + goto validate_out; + +validate_fail: + DC_LOG_WARNING("Mode Validation Warning: %s failed validation.\n", + dml_get_status_message(context->bw_ctx.dml.vba.ValidationStatus[context->bw_ctx.dml.vba.soc.num_states])); + + BW_VAL_TRACE_SKIP(fail); + out = false; + +validate_out: + kfree(pipes); + + BW_VAL_TRACE_FINISH(); + + return out; +} + +static void dcn31_get_panel_config_defaults(struct dc_panel_config *panel_config) +{ + *panel_config = panel_config_defaults; +} + +static struct dc_cap_funcs cap_funcs = { + .get_dcc_compression_cap = dcn20_get_dcc_compression_cap +}; + +static struct resource_funcs dcn31_res_pool_funcs = { + .destroy = dcn31_destroy_resource_pool, + .link_enc_create = dcn31_link_encoder_create, + .link_enc_create_minimal = dcn31_link_enc_create_minimal, + .link_encs_assign = link_enc_cfg_link_encs_assign, + .link_enc_unassign = link_enc_cfg_link_enc_unassign, + .panel_cntl_create = dcn31_panel_cntl_create, + .validate_bandwidth = dcn31_validate_bandwidth, + .calculate_wm_and_dlg = dcn31_calculate_wm_and_dlg, + .update_soc_for_wm_a = dcn31_update_soc_for_wm_a, + .populate_dml_pipes = dcn31_populate_dml_pipes_from_context, + .acquire_free_pipe_as_secondary_dpp_pipe = dcn20_acquire_free_pipe_for_layer, + .release_pipe = dcn20_release_pipe, + .add_stream_to_ctx = dcn30_add_stream_to_ctx, + .add_dsc_to_stream_resource = dcn20_add_dsc_to_stream_resource, + .remove_stream_from_ctx = dcn20_remove_stream_from_ctx, + .populate_dml_writeback_from_context = dcn31_populate_dml_writeback_from_context, + .set_mcif_arb_params = dcn31_set_mcif_arb_params, + .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 = dcn31_update_bw_bounding_box, + .patch_unknown_plane_state = dcn20_patch_unknown_plane_state, + .get_panel_config_defaults = dcn31_get_panel_config_defaults, +}; + +static struct clock_source *dcn30_clock_source_create( + struct dc_context *ctx, + struct dc_bios *bios, + enum clock_source_id id, + const struct dce110_clk_src_regs *regs, + bool dp_clk_src) +{ + struct dce110_clk_src *clk_src = + kzalloc(sizeof(struct dce110_clk_src), GFP_KERNEL); + + if (!clk_src) + return NULL; + + if (dcn31_clk_src_construct(clk_src, ctx, bios, id, + regs, &cs_shift, &cs_mask)) { + clk_src->base.dp_clk_src = dp_clk_src; + return &clk_src->base; + } + + BREAK_TO_DEBUGGER(); + return NULL; +} + +static bool dcn31_resource_construct( + uint8_t num_virtual_links, + struct dc *dc, + struct dcn31_resource_pool *pool) +{ + int i; + struct dc_context *ctx = dc->ctx; + struct irq_service_init_data init_data; + + ctx->dc_bios->regs = &bios_regs; + + pool->base.res_cap = &res_cap_dcn31; + + pool->base.funcs = &dcn31_res_pool_funcs; + + /************************************************* + * Resource + asic cap harcoding * + *************************************************/ + pool->base.underlay_pipe_index = NO_UNDERLAY_PIPE; + pool->base.pipe_count = pool->base.res_cap->num_timing_generator; + pool->base.mpcc_count = pool->base.res_cap->num_timing_generator; + dc->caps.max_downscale_ratio = 600; + dc->caps.i2c_speed_in_khz = 100; + dc->caps.i2c_speed_in_khz_hdcp = 5; /*1.4 w/a applied by default*/ + dc->caps.max_cursor_size = 256; + dc->caps.min_horizontal_blanking_period = 80; + dc->caps.dmdata_alloc_size = 2048; + + dc->caps.max_slave_planes = 2; + dc->caps.max_slave_yuv_planes = 2; + dc->caps.max_slave_rgb_planes = 2; + dc->caps.post_blend_color_processing = true; + dc->caps.force_dp_tps4_for_cp2520 = true; + if (dc->config.forceHBR2CP2520) + dc->caps.force_dp_tps4_for_cp2520 = false; + dc->caps.dp_hpo = true; + dc->caps.dp_hdmi21_pcon_support = true; + dc->caps.edp_dsc_support = true; + dc->caps.extended_aux_timeout_support = true; + dc->caps.dmcub_support = true; + dc->caps.is_apu = true; + dc->caps.zstate_support = true; + + /* Color pipeline capabilities */ + dc->caps.color.dpp.dcn_arch = 1; + dc->caps.color.dpp.input_lut_shared = 0; + dc->caps.color.dpp.icsc = 1; + dc->caps.color.dpp.dgam_ram = 0; // must use gamma_corr + dc->caps.color.dpp.dgam_rom_caps.srgb = 1; + dc->caps.color.dpp.dgam_rom_caps.bt2020 = 1; + dc->caps.color.dpp.dgam_rom_caps.gamma2_2 = 1; + dc->caps.color.dpp.dgam_rom_caps.pq = 1; + dc->caps.color.dpp.dgam_rom_caps.hlg = 1; + dc->caps.color.dpp.post_csc = 1; + dc->caps.color.dpp.gamma_corr = 1; + dc->caps.color.dpp.dgam_rom_for_yuv = 0; + + dc->caps.color.dpp.hw_3d_lut = 1; + dc->caps.color.dpp.ogam_ram = 1; + // no OGAM ROM on DCN301 + dc->caps.color.dpp.ogam_rom_caps.srgb = 0; + dc->caps.color.dpp.ogam_rom_caps.bt2020 = 0; + dc->caps.color.dpp.ogam_rom_caps.gamma2_2 = 0; + dc->caps.color.dpp.ogam_rom_caps.pq = 0; + dc->caps.color.dpp.ogam_rom_caps.hlg = 0; + dc->caps.color.dpp.ocsc = 0; + + dc->caps.color.mpc.gamut_remap = 1; + dc->caps.color.mpc.num_3dluts = pool->base.res_cap->num_mpc_3dlut; //2 + dc->caps.color.mpc.ogam_ram = 1; + dc->caps.color.mpc.ogam_rom_caps.srgb = 0; + dc->caps.color.mpc.ogam_rom_caps.bt2020 = 0; + dc->caps.color.mpc.ogam_rom_caps.gamma2_2 = 0; + dc->caps.color.mpc.ogam_rom_caps.pq = 0; + dc->caps.color.mpc.ogam_rom_caps.hlg = 0; + dc->caps.color.mpc.ocsc = 1; + + dc->config.use_old_fixed_vs_sequence = true; + + /* Use pipe context based otg sync logic */ + dc->config.use_pipe_ctx_sync_logic = true; + + /* read VBIOS LTTPR caps */ + { + if (ctx->dc_bios->funcs->get_lttpr_caps) { + enum bp_result bp_query_result; + uint8_t is_vbios_lttpr_enable = 0; + + bp_query_result = ctx->dc_bios->funcs->get_lttpr_caps(ctx->dc_bios, &is_vbios_lttpr_enable); + dc->caps.vbios_lttpr_enable = (bp_query_result == BP_RESULT_OK) && !!is_vbios_lttpr_enable; + } + + /* interop bit is implicit */ + { + dc->caps.vbios_lttpr_aware = true; + } + } + + if (dc->ctx->dce_environment == DCE_ENV_PRODUCTION_DRV) + dc->debug = debug_defaults_drv; + + // Init the vm_helper + if (dc->vm_helper) + vm_helper_init(dc->vm_helper, 16); + + /************************************************* + * Create resources * + *************************************************/ + + /* Clock Sources for Pixel Clock*/ + pool->base.clock_sources[DCN31_CLK_SRC_PLL0] = + dcn30_clock_source_create(ctx, ctx->dc_bios, + CLOCK_SOURCE_COMBO_PHY_PLL0, + &clk_src_regs[0], false); + pool->base.clock_sources[DCN31_CLK_SRC_PLL1] = + dcn30_clock_source_create(ctx, ctx->dc_bios, + CLOCK_SOURCE_COMBO_PHY_PLL1, + &clk_src_regs[1], false); + /*move phypllx_pixclk_resync to dmub next*/ + if (dc->ctx->asic_id.hw_internal_rev == YELLOW_CARP_B0) { + pool->base.clock_sources[DCN31_CLK_SRC_PLL2] = + dcn30_clock_source_create(ctx, ctx->dc_bios, + CLOCK_SOURCE_COMBO_PHY_PLL2, + &clk_src_regs_b0[2], false); + pool->base.clock_sources[DCN31_CLK_SRC_PLL3] = + dcn30_clock_source_create(ctx, ctx->dc_bios, + CLOCK_SOURCE_COMBO_PHY_PLL3, + &clk_src_regs_b0[3], false); + } else { + pool->base.clock_sources[DCN31_CLK_SRC_PLL2] = + dcn30_clock_source_create(ctx, ctx->dc_bios, + CLOCK_SOURCE_COMBO_PHY_PLL2, + &clk_src_regs[2], false); + pool->base.clock_sources[DCN31_CLK_SRC_PLL3] = + dcn30_clock_source_create(ctx, ctx->dc_bios, + CLOCK_SOURCE_COMBO_PHY_PLL3, + &clk_src_regs[3], false); + } + + pool->base.clock_sources[DCN31_CLK_SRC_PLL4] = + dcn30_clock_source_create(ctx, ctx->dc_bios, + CLOCK_SOURCE_COMBO_PHY_PLL4, + &clk_src_regs[4], false); + + pool->base.clk_src_count = DCN30_CLK_SRC_TOTAL; + + /* todo: not reuse phy_pll registers */ + pool->base.dp_clock_source = + dcn31_clock_source_create(ctx, ctx->dc_bios, + CLOCK_SOURCE_ID_DP_DTO, + &clk_src_regs[0], true); + + for (i = 0; i < pool->base.clk_src_count; i++) { + if (pool->base.clock_sources[i] == NULL) { + dm_error("DC: failed to create clock sources!\n"); + BREAK_TO_DEBUGGER(); + goto create_fail; + } + } + + /* TODO: DCCG */ + pool->base.dccg = dccg31_create(ctx, &dccg_regs, &dccg_shift, &dccg_mask); + if (pool->base.dccg == NULL) { + dm_error("DC: failed to create dccg!\n"); + BREAK_TO_DEBUGGER(); + goto create_fail; + } + + /* TODO: IRQ */ + init_data.ctx = dc->ctx; + pool->base.irqs = dal_irq_service_dcn31_create(&init_data); + if (!pool->base.irqs) + goto create_fail; + + /* HUBBUB */ + pool->base.hubbub = dcn31_hubbub_create(ctx); + if (pool->base.hubbub == NULL) { + BREAK_TO_DEBUGGER(); + dm_error("DC: failed to create hubbub!\n"); + goto create_fail; + } + + /* HUBPs, DPPs, OPPs and TGs */ + for (i = 0; i < pool->base.pipe_count; i++) { + pool->base.hubps[i] = dcn31_hubp_create(ctx, i); + if (pool->base.hubps[i] == NULL) { + BREAK_TO_DEBUGGER(); + dm_error( + "DC: failed to create hubps!\n"); + goto create_fail; + } + + pool->base.dpps[i] = dcn31_dpp_create(ctx, i); + if (pool->base.dpps[i] == NULL) { + BREAK_TO_DEBUGGER(); + dm_error( + "DC: failed to create dpps!\n"); + goto create_fail; + } + } + + for (i = 0; i < pool->base.res_cap->num_opp; i++) { + pool->base.opps[i] = dcn31_opp_create(ctx, i); + if (pool->base.opps[i] == NULL) { + BREAK_TO_DEBUGGER(); + dm_error( + "DC: failed to create output pixel processor!\n"); + goto create_fail; + } + } + + for (i = 0; i < pool->base.res_cap->num_timing_generator; i++) { + pool->base.timing_generators[i] = dcn31_timing_generator_create( + ctx, i); + if (pool->base.timing_generators[i] == NULL) { + BREAK_TO_DEBUGGER(); + dm_error("DC: failed to create tg!\n"); + goto create_fail; + } + } + pool->base.timing_generator_count = i; + + /* PSR */ + pool->base.psr = dmub_psr_create(ctx); + if (pool->base.psr == NULL) { + dm_error("DC: failed to create psr obj!\n"); + BREAK_TO_DEBUGGER(); + goto create_fail; + } + + /* Replay */ + pool->base.replay = dmub_replay_create(ctx); + if (pool->base.replay == NULL) { + dm_error("DC: failed to create replay obj!\n"); + BREAK_TO_DEBUGGER(); + goto create_fail; + } + + /* ABM */ + for (i = 0; i < pool->base.res_cap->num_timing_generator; i++) { + pool->base.multiple_abms[i] = dmub_abm_create(ctx, + &abm_regs[i], + &abm_shift, + &abm_mask); + if (pool->base.multiple_abms[i] == NULL) { + dm_error("DC: failed to create abm for pipe %d!\n", i); + BREAK_TO_DEBUGGER(); + goto create_fail; + } + } + + /* MPC and DSC */ + pool->base.mpc = dcn31_mpc_create(ctx, pool->base.mpcc_count, pool->base.res_cap->num_mpc_3dlut); + if (pool->base.mpc == NULL) { + BREAK_TO_DEBUGGER(); + dm_error("DC: failed to create mpc!\n"); + goto create_fail; + } + + for (i = 0; i < pool->base.res_cap->num_dsc; i++) { + pool->base.dscs[i] = dcn31_dsc_create(ctx, i); + if (pool->base.dscs[i] == NULL) { + BREAK_TO_DEBUGGER(); + dm_error("DC: failed to create display stream compressor %d!\n", i); + goto create_fail; + } + } + + /* DWB and MMHUBBUB */ + if (!dcn31_dwbc_create(ctx, &pool->base)) { + BREAK_TO_DEBUGGER(); + dm_error("DC: failed to create dwbc!\n"); + goto create_fail; + } + + if (!dcn31_mmhubbub_create(ctx, &pool->base)) { + BREAK_TO_DEBUGGER(); + dm_error("DC: failed to create mcif_wb!\n"); + goto create_fail; + } + + /* AUX and I2C */ + for (i = 0; i < pool->base.res_cap->num_ddc; i++) { + pool->base.engines[i] = dcn31_aux_engine_create(ctx, i); + if (pool->base.engines[i] == NULL) { + BREAK_TO_DEBUGGER(); + dm_error( + "DC:failed to create aux engine!!\n"); + goto create_fail; + } + pool->base.hw_i2cs[i] = dcn31_i2c_hw_create(ctx, i); + if (pool->base.hw_i2cs[i] == NULL) { + BREAK_TO_DEBUGGER(); + dm_error( + "DC:failed to create hw i2c!!\n"); + goto create_fail; + } + pool->base.sw_i2cs[i] = NULL; + } + + if (dc->ctx->asic_id.chip_family == FAMILY_YELLOW_CARP && + dc->ctx->asic_id.hw_internal_rev == YELLOW_CARP_B0 && + !dc->debug.dpia_debug.bits.disable_dpia) { + /* YELLOW CARP B0 has 4 DPIA's */ + pool->base.usb4_dpia_count = 4; + } + + if (dc->ctx->asic_id.chip_family == AMDGPU_FAMILY_GC_11_0_1) + pool->base.usb4_dpia_count = 4; + + /* Audio, Stream Encoders including HPO and virtual, MPC 3D LUTs */ + if (!resource_construct(num_virtual_links, dc, &pool->base, + &res_create_funcs)) + goto create_fail; + + /* HW Sequencer and Plane caps */ + dcn31_hw_sequencer_construct(dc); + + dc->caps.max_planes = pool->base.pipe_count; + + for (i = 0; i < dc->caps.max_planes; ++i) + dc->caps.planes[i] = plane_cap; + + dc->cap_funcs = cap_funcs; + + dc->dcn_ip->max_num_dpp = dcn3_1_ip.max_num_dpp; + + return true; + +create_fail: + dcn31_resource_destruct(pool); + + return false; +} + +struct resource_pool *dcn31_create_resource_pool( + const struct dc_init_data *init_data, + struct dc *dc) +{ + struct dcn31_resource_pool *pool = + kzalloc(sizeof(struct dcn31_resource_pool), GFP_KERNEL); + + if (!pool) + return NULL; + + if (dcn31_resource_construct(init_data->num_virtual_links, dc, pool)) + return &pool->base; + + BREAK_TO_DEBUGGER(); + kfree(pool); + return NULL; +} diff --git a/drivers/gpu/drm/amd/display/dc/resource/dcn31/dcn31_resource.h b/drivers/gpu/drm/amd/display/dc/resource/dcn31/dcn31_resource.h new file mode 100644 index 000000000000..901436591ed4 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/resource/dcn31/dcn31_resource.h @@ -0,0 +1,97 @@ +/* + * Copyright 2020 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 _DCN31_RESOURCE_H_ +#define _DCN31_RESOURCE_H_ + +#include "core_types.h" + +#define TO_DCN31_RES_POOL(pool)\ + container_of(pool, struct dcn31_resource_pool, base) + +extern struct _vcs_dpi_ip_params_st dcn3_1_ip; + +struct dcn31_resource_pool { + struct resource_pool base; +}; + +bool dcn31_validate_bandwidth(struct dc *dc, + struct dc_state *context, + bool fast_validate); +void dcn31_calculate_wm_and_dlg( + struct dc *dc, struct dc_state *context, + display_e2e_pipe_params_st *pipes, + int pipe_cnt, + int vlevel); +int dcn31_populate_dml_pipes_from_context( + struct dc *dc, struct dc_state *context, + display_e2e_pipe_params_st *pipes, + bool fast_validate); +void +dcn31_populate_dml_writeback_from_context(struct dc *dc, + struct resource_context *res_ctx, + display_e2e_pipe_params_st *pipes); +void +dcn31_set_mcif_arb_params(struct dc *dc, + struct dc_state *context, + display_e2e_pipe_params_st *pipes, + int pipe_cnt); + +struct resource_pool *dcn31_create_resource_pool( + const struct dc_init_data *init_data, + struct dc *dc); + +/*temp: B0 specific before switch to dcn313 headers*/ +#ifndef regPHYPLLF_PIXCLK_RESYNC_CNTL +#define regPHYPLLF_PIXCLK_RESYNC_CNTL 0x007e +#define regPHYPLLF_PIXCLK_RESYNC_CNTL_BASE_IDX 1 +#define regPHYPLLG_PIXCLK_RESYNC_CNTL 0x005f +#define regPHYPLLG_PIXCLK_RESYNC_CNTL_BASE_IDX 1 + +//PHYPLLF_PIXCLK_RESYNC_CNTL +#define PHYPLLF_PIXCLK_RESYNC_CNTL__PHYPLLF_PIXCLK_RESYNC_ENABLE__SHIFT 0x0 +#define PHYPLLF_PIXCLK_RESYNC_CNTL__PHYPLLF_DEEP_COLOR_DTO_ENABLE_STATUS__SHIFT 0x1 +#define PHYPLLF_PIXCLK_RESYNC_CNTL__PHYPLLF_DCCG_DEEP_COLOR_CNTL__SHIFT 0x4 +#define PHYPLLF_PIXCLK_RESYNC_CNTL__PHYPLLF_PIXCLK_ENABLE__SHIFT 0x8 +#define PHYPLLF_PIXCLK_RESYNC_CNTL__PHYPLLF_PIXCLK_DOUBLE_RATE_ENABLE__SHIFT 0x9 +#define PHYPLLF_PIXCLK_RESYNC_CNTL__PHYPLLF_PIXCLK_RESYNC_ENABLE_MASK 0x00000001L +#define PHYPLLF_PIXCLK_RESYNC_CNTL__PHYPLLF_DEEP_COLOR_DTO_ENABLE_STATUS_MASK 0x00000002L +#define PHYPLLF_PIXCLK_RESYNC_CNTL__PHYPLLF_DCCG_DEEP_COLOR_CNTL_MASK 0x00000030L +#define PHYPLLF_PIXCLK_RESYNC_CNTL__PHYPLLF_PIXCLK_ENABLE_MASK 0x00000100L +#define PHYPLLF_PIXCLK_RESYNC_CNTL__PHYPLLF_PIXCLK_DOUBLE_RATE_ENABLE_MASK 0x00000200L + +//PHYPLLG_PIXCLK_RESYNC_CNTL +#define PHYPLLG_PIXCLK_RESYNC_CNTL__PHYPLLG_PIXCLK_RESYNC_ENABLE__SHIFT 0x0 +#define PHYPLLG_PIXCLK_RESYNC_CNTL__PHYPLLG_DEEP_COLOR_DTO_ENABLE_STATUS__SHIFT 0x1 +#define PHYPLLG_PIXCLK_RESYNC_CNTL__PHYPLLG_DCCG_DEEP_COLOR_CNTL__SHIFT 0x4 +#define PHYPLLG_PIXCLK_RESYNC_CNTL__PHYPLLG_PIXCLK_ENABLE__SHIFT 0x8 +#define PHYPLLG_PIXCLK_RESYNC_CNTL__PHYPLLG_PIXCLK_DOUBLE_RATE_ENABLE__SHIFT 0x9 +#define PHYPLLG_PIXCLK_RESYNC_CNTL__PHYPLLG_PIXCLK_RESYNC_ENABLE_MASK 0x00000001L +#define PHYPLLG_PIXCLK_RESYNC_CNTL__PHYPLLG_DEEP_COLOR_DTO_ENABLE_STATUS_MASK 0x00000002L +#define PHYPLLG_PIXCLK_RESYNC_CNTL__PHYPLLG_DCCG_DEEP_COLOR_CNTL_MASK 0x00000030L +#define PHYPLLG_PIXCLK_RESYNC_CNTL__PHYPLLG_PIXCLK_ENABLE_MASK 0x00000100L +#define PHYPLLG_PIXCLK_RESYNC_CNTL__PHYPLLG_PIXCLK_DOUBLE_RATE_ENABLE_MASK 0x00000200L +#endif +#endif /* _DCN31_RESOURCE_H_ */ diff --git a/drivers/gpu/drm/amd/display/dc/resource/dcn314/dcn314_resource.c b/drivers/gpu/drm/amd/display/dc/resource/dcn314/dcn314_resource.c new file mode 100644 index 000000000000..677361d74a4e --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/resource/dcn314/dcn314_resource.c @@ -0,0 +1,2180 @@ +// SPDX-License-Identifier: MIT +/* + * Copyright 2022 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 "dm_services.h" +#include "dc.h" + +#include "dcn31/dcn31_init.h" +#include "dcn314/dcn314_init.h" + +#include "resource.h" +#include "include/irq_service_interface.h" +#include "dcn314_resource.h" + +#include "dcn20/dcn20_resource.h" +#include "dcn30/dcn30_resource.h" +#include "dcn31/dcn31_resource.h" + +#include "dcn10/dcn10_ipp.h" +#include "dcn30/dcn30_hubbub.h" +#include "dcn31/dcn31_hubbub.h" +#include "dcn30/dcn30_mpc.h" +#include "dcn31/dcn31_hubp.h" +#include "irq/dcn31/irq_service_dcn31.h" +#include "irq/dcn314/irq_service_dcn314.h" +#include "dcn30/dcn30_dpp.h" +#include "dcn314/dcn314_optc.h" +#include "dcn20/dcn20_hwseq.h" +#include "dcn30/dcn30_hwseq.h" +#include "dce110/dce110_hwseq.h" +#include "dcn30/dcn30_opp.h" +#include "dcn20/dcn20_dsc.h" +#include "dcn30/dcn30_vpg.h" +#include "dcn30/dcn30_afmt.h" +#include "dcn31/dcn31_dio_link_encoder.h" +#include "dcn314/dcn314_dio_stream_encoder.h" +#include "dcn31/dcn31_hpo_dp_stream_encoder.h" +#include "dcn31/dcn31_hpo_dp_link_encoder.h" +#include "dcn31/dcn31_apg.h" +#include "dcn31/dcn31_vpg.h" +#include "dcn31/dcn31_afmt.h" +#include "dce/dce_clock_source.h" +#include "dce/dce_audio.h" +#include "dce/dce_hwseq.h" +#include "clk_mgr.h" +#include "virtual/virtual_stream_encoder.h" +#include "dce110/dce110_resource.h" +#include "dml/display_mode_vba.h" +#include "dml/dcn31/dcn31_fpu.h" +#include "dml/dcn314/dcn314_fpu.h" +#include "dcn314/dcn314_dccg.h" +#include "dcn10/dcn10_resource.h" +#include "dcn31/dcn31_panel_cntl.h" +#include "dcn314/dcn314_hwseq.h" + +#include "dcn30/dcn30_dwb.h" +#include "dcn30/dcn30_mmhubbub.h" + +#include "dcn/dcn_3_1_4_offset.h" +#include "dcn/dcn_3_1_4_sh_mask.h" +#include "dpcs/dpcs_3_1_4_offset.h" +#include "dpcs/dpcs_3_1_4_sh_mask.h" + +#define DCHUBBUB_DEBUG_CTRL_0__DET_DEPTH__SHIFT 0x10 +#define DCHUBBUB_DEBUG_CTRL_0__DET_DEPTH_MASK 0x01FF0000L + +#define DSCC0_DSCC_CONFIG0__ICH_RESET_AT_END_OF_LINE__SHIFT 0x0 +#define DSCC0_DSCC_CONFIG0__ICH_RESET_AT_END_OF_LINE_MASK 0x0000000FL + +#include "reg_helper.h" +#include "dce/dmub_abm.h" +#include "dce/dmub_psr.h" +#include "dce/dmub_replay.h" +#include "dce/dce_aux.h" +#include "dce/dce_i2c.h" +#include "dml/dcn314/display_mode_vba_314.h" +#include "vm_helper.h" +#include "dcn20/dcn20_vmid.h" + +#include "link_enc_cfg.h" + +#define DCN_BASE__INST0_SEG1 0x000000C0 +#define DCN_BASE__INST0_SEG2 0x000034C0 +#define DCN_BASE__INST0_SEG3 0x00009000 + +#define NBIO_BASE__INST0_SEG1 0x00000014 + +#define MAX_INSTANCE 7 +#define MAX_SEGMENT 8 + +#define regBIF_BX2_BIOS_SCRATCH_2 0x003a +#define regBIF_BX2_BIOS_SCRATCH_2_BASE_IDX 1 +#define regBIF_BX2_BIOS_SCRATCH_3 0x003b +#define regBIF_BX2_BIOS_SCRATCH_3_BASE_IDX 1 +#define regBIF_BX2_BIOS_SCRATCH_6 0x003e +#define regBIF_BX2_BIOS_SCRATCH_6_BASE_IDX 1 + +#define DC_LOGGER \ + dc->ctx->logger +#define DC_LOGGER_INIT(logger) + +enum dcn31_clk_src_array_id { + DCN31_CLK_SRC_PLL0, + DCN31_CLK_SRC_PLL1, + DCN31_CLK_SRC_PLL2, + DCN31_CLK_SRC_PLL3, + DCN31_CLK_SRC_PLL4, + DCN30_CLK_SRC_TOTAL +}; + +/* begin ********************* + * macros to expend register list macro defined in HW object header file + */ + +/* DCN */ +/* TODO awful hack. fixup dcn20_dwb.h */ +#undef BASE_INNER +#define BASE_INNER(seg) DCN_BASE__INST0_SEG ## seg + +#define BASE(seg) BASE_INNER(seg) + +#define SR(reg_name)\ + .reg_name = BASE(reg ## reg_name ## _BASE_IDX) + \ + reg ## reg_name + +#define SRI(reg_name, block, id)\ + .reg_name = BASE(reg ## block ## id ## _ ## reg_name ## _BASE_IDX) + \ + reg ## block ## id ## _ ## reg_name + +#define SRI2(reg_name, block, id)\ + .reg_name = BASE(reg ## reg_name ## _BASE_IDX) + \ + reg ## reg_name + +#define SRIR(var_name, reg_name, block, id)\ + .var_name = BASE(reg ## block ## id ## _ ## reg_name ## _BASE_IDX) + \ + reg ## block ## id ## _ ## reg_name + +#define SRII(reg_name, block, id)\ + .reg_name[id] = BASE(reg ## block ## id ## _ ## reg_name ## _BASE_IDX) + \ + reg ## block ## id ## _ ## reg_name + +#define SRII_MPC_RMU(reg_name, block, id)\ + .RMU##_##reg_name[id] = BASE(reg ## block ## id ## _ ## reg_name ## _BASE_IDX) + \ + reg ## block ## id ## _ ## reg_name + +#define SRII_DWB(reg_name, temp_name, block, id)\ + .reg_name[id] = BASE(reg ## block ## id ## _ ## temp_name ## _BASE_IDX) + \ + reg ## block ## id ## _ ## temp_name + +#define SF_DWB2(reg_name, block, id, field_name, post_fix) \ + .field_name = reg_name ## __ ## field_name ## post_fix + +#define DCCG_SRII(reg_name, block, id)\ + .block ## _ ## reg_name[id] = BASE(reg ## block ## id ## _ ## reg_name ## _BASE_IDX) + \ + reg ## block ## id ## _ ## reg_name + +#define VUPDATE_SRII(reg_name, block, id)\ + .reg_name[id] = BASE(reg ## reg_name ## _ ## block ## id ## _BASE_IDX) + \ + reg ## reg_name ## _ ## block ## id + +/* NBIO */ +#define NBIO_BASE_INNER(seg) \ + NBIO_BASE__INST0_SEG ## seg + +#define NBIO_BASE(seg) \ + NBIO_BASE_INNER(seg) + +#define NBIO_SR(reg_name)\ + .reg_name = NBIO_BASE(regBIF_BX2_ ## reg_name ## _BASE_IDX) + \ + regBIF_BX2_ ## reg_name + +/* MMHUB */ +#define MMHUB_BASE_INNER(seg) \ + MMHUB_BASE__INST0_SEG ## seg + +#define MMHUB_BASE(seg) \ + MMHUB_BASE_INNER(seg) + +#define MMHUB_SR(reg_name)\ + .reg_name = MMHUB_BASE(reg ## reg_name ## _BASE_IDX) + \ + reg ## reg_name + +/* CLOCK */ +#define CLK_BASE_INNER(seg) \ + CLK_BASE__INST0_SEG ## seg + +#define CLK_BASE(seg) \ + CLK_BASE_INNER(seg) + +#define CLK_SRI(reg_name, block, inst)\ + .reg_name = CLK_BASE(reg ## block ## _ ## inst ## _ ## reg_name ## _BASE_IDX) + \ + reg ## block ## _ ## inst ## _ ## reg_name + + +static const struct bios_registers bios_regs = { + NBIO_SR(BIOS_SCRATCH_3), + NBIO_SR(BIOS_SCRATCH_6) +}; + +#define clk_src_regs(index, pllid)\ +[index] = {\ + CS_COMMON_REG_LIST_DCN3_0(index, pllid),\ +} + +static const struct dce110_clk_src_regs clk_src_regs[] = { + clk_src_regs(0, A), + clk_src_regs(1, B), + clk_src_regs(2, C), + clk_src_regs(3, D), + clk_src_regs(4, E) +}; + +static const struct dce110_clk_src_shift cs_shift = { + CS_COMMON_MASK_SH_LIST_DCN3_1_4(__SHIFT) +}; + +static const struct dce110_clk_src_mask cs_mask = { + CS_COMMON_MASK_SH_LIST_DCN3_1_4(_MASK) +}; + +#define abm_regs(id)\ +[id] = {\ + ABM_DCN302_REG_LIST(id)\ +} + +static const struct dce_abm_registers abm_regs[] = { + abm_regs(0), + abm_regs(1), + abm_regs(2), + abm_regs(3), +}; + +static const struct dce_abm_shift abm_shift = { + ABM_MASK_SH_LIST_DCN30(__SHIFT) +}; + +static const struct dce_abm_mask abm_mask = { + ABM_MASK_SH_LIST_DCN30(_MASK) +}; + +#define audio_regs(id)\ +[id] = {\ + AUD_COMMON_REG_LIST(id)\ +} + +static const struct dce_audio_registers audio_regs[] = { + audio_regs(0), + audio_regs(1), + audio_regs(2), + audio_regs(3), + audio_regs(4), + audio_regs(5), + audio_regs(6) +}; + +#define DCE120_AUD_COMMON_MASK_SH_LIST(mask_sh)\ + SF(AZF0ENDPOINT0_AZALIA_F0_CODEC_ENDPOINT_INDEX, AZALIA_ENDPOINT_REG_INDEX, mask_sh),\ + SF(AZF0ENDPOINT0_AZALIA_F0_CODEC_ENDPOINT_DATA, AZALIA_ENDPOINT_REG_DATA, mask_sh),\ + AUD_COMMON_MASK_SH_LIST_BASE(mask_sh) + +static const struct dce_audio_shift audio_shift = { + DCE120_AUD_COMMON_MASK_SH_LIST(__SHIFT) +}; + +static const struct dce_audio_mask audio_mask = { + DCE120_AUD_COMMON_MASK_SH_LIST(_MASK) +}; + +#define vpg_regs(id)\ +[id] = {\ + VPG_DCN31_REG_LIST(id)\ +} + +static const struct dcn31_vpg_registers vpg_regs[] = { + vpg_regs(0), + vpg_regs(1), + vpg_regs(2), + vpg_regs(3), + vpg_regs(4), + vpg_regs(5), + vpg_regs(6), + vpg_regs(7), + vpg_regs(8), + vpg_regs(9), +}; + +static const struct dcn31_vpg_shift vpg_shift = { + DCN31_VPG_MASK_SH_LIST(__SHIFT) +}; + +static const struct dcn31_vpg_mask vpg_mask = { + DCN31_VPG_MASK_SH_LIST(_MASK) +}; + +#define afmt_regs(id)\ +[id] = {\ + AFMT_DCN31_REG_LIST(id)\ +} + +static const struct dcn31_afmt_registers afmt_regs[] = { + afmt_regs(0), + afmt_regs(1), + afmt_regs(2), + afmt_regs(3), + afmt_regs(4), + afmt_regs(5) +}; + +static const struct dcn31_afmt_shift afmt_shift = { + DCN31_AFMT_MASK_SH_LIST(__SHIFT) +}; + +static const struct dcn31_afmt_mask afmt_mask = { + DCN31_AFMT_MASK_SH_LIST(_MASK) +}; + +#define apg_regs(id)\ +[id] = {\ + APG_DCN31_REG_LIST(id)\ +} + +static const struct dcn31_apg_registers apg_regs[] = { + apg_regs(0), + apg_regs(1), + apg_regs(2), + apg_regs(3) +}; + +static const struct dcn31_apg_shift apg_shift = { + DCN31_APG_MASK_SH_LIST(__SHIFT) +}; + +static const struct dcn31_apg_mask apg_mask = { + DCN31_APG_MASK_SH_LIST(_MASK) +}; + +#define stream_enc_regs(id)\ +[id] = {\ + SE_DCN314_REG_LIST(id)\ +} + +static const struct dcn10_stream_enc_registers stream_enc_regs[] = { + stream_enc_regs(0), + stream_enc_regs(1), + stream_enc_regs(2), + stream_enc_regs(3), + stream_enc_regs(4) +}; + +static const struct dcn10_stream_encoder_shift se_shift = { + SE_COMMON_MASK_SH_LIST_DCN314(__SHIFT) +}; + +static const struct dcn10_stream_encoder_mask se_mask = { + SE_COMMON_MASK_SH_LIST_DCN314(_MASK) +}; + + +#define aux_regs(id)\ +[id] = {\ + DCN2_AUX_REG_LIST(id)\ +} + +static const struct dcn10_link_enc_aux_registers link_enc_aux_regs[] = { + aux_regs(0), + aux_regs(1), + aux_regs(2), + aux_regs(3), + aux_regs(4) +}; + +#define hpd_regs(id)\ +[id] = {\ + HPD_REG_LIST(id)\ +} + +static const struct dcn10_link_enc_hpd_registers link_enc_hpd_regs[] = { + hpd_regs(0), + hpd_regs(1), + hpd_regs(2), + hpd_regs(3), + hpd_regs(4) +}; + +#define link_regs(id, phyid)\ +[id] = {\ + LE_DCN31_REG_LIST(id), \ + UNIPHY_DCN2_REG_LIST(phyid), \ +} + +static const struct dce110_aux_registers_shift aux_shift = { + DCN_AUX_MASK_SH_LIST(__SHIFT) +}; + +static const struct dce110_aux_registers_mask aux_mask = { + DCN_AUX_MASK_SH_LIST(_MASK) +}; + +static const struct dcn10_link_enc_registers link_enc_regs[] = { + link_regs(0, A), + link_regs(1, B), + link_regs(2, C), + link_regs(3, D), + link_regs(4, E) +}; + +static const struct dcn10_link_enc_shift le_shift = { + LINK_ENCODER_MASK_SH_LIST_DCN31(__SHIFT), + DPCS_DCN31_MASK_SH_LIST(__SHIFT) +}; + +static const struct dcn10_link_enc_mask le_mask = { + LINK_ENCODER_MASK_SH_LIST_DCN31(_MASK), + DPCS_DCN31_MASK_SH_LIST(_MASK) +}; + +#define hpo_dp_stream_encoder_reg_list(id)\ +[id] = {\ + DCN3_1_HPO_DP_STREAM_ENC_REG_LIST(id)\ +} + +static const struct dcn31_hpo_dp_stream_encoder_registers hpo_dp_stream_enc_regs[] = { + hpo_dp_stream_encoder_reg_list(0), + hpo_dp_stream_encoder_reg_list(1), + hpo_dp_stream_encoder_reg_list(2), + hpo_dp_stream_encoder_reg_list(3) +}; + +static const struct dcn31_hpo_dp_stream_encoder_shift hpo_dp_se_shift = { + DCN3_1_HPO_DP_STREAM_ENC_MASK_SH_LIST(__SHIFT) +}; + +static const struct dcn31_hpo_dp_stream_encoder_mask hpo_dp_se_mask = { + DCN3_1_HPO_DP_STREAM_ENC_MASK_SH_LIST(_MASK) +}; + + +#define hpo_dp_link_encoder_reg_list(id)\ +[id] = {\ + DCN3_1_HPO_DP_LINK_ENC_REG_LIST(id),\ + DCN3_1_RDPCSTX_REG_LIST(0),\ + DCN3_1_RDPCSTX_REG_LIST(1),\ + DCN3_1_RDPCSTX_REG_LIST(2),\ +} + +static const struct dcn31_hpo_dp_link_encoder_registers hpo_dp_link_enc_regs[] = { + hpo_dp_link_encoder_reg_list(0), + hpo_dp_link_encoder_reg_list(1), +}; + +static const struct dcn31_hpo_dp_link_encoder_shift hpo_dp_le_shift = { + DCN3_1_HPO_DP_LINK_ENC_MASK_SH_LIST(__SHIFT) +}; + +static const struct dcn31_hpo_dp_link_encoder_mask hpo_dp_le_mask = { + DCN3_1_HPO_DP_LINK_ENC_MASK_SH_LIST(_MASK) +}; + +#define dpp_regs(id)\ +[id] = {\ + DPP_REG_LIST_DCN30(id),\ +} + +static const struct dcn3_dpp_registers dpp_regs[] = { + dpp_regs(0), + dpp_regs(1), + dpp_regs(2), + dpp_regs(3) +}; + +static const struct dcn3_dpp_shift tf_shift = { + DPP_REG_LIST_SH_MASK_DCN30(__SHIFT) +}; + +static const struct dcn3_dpp_mask tf_mask = { + DPP_REG_LIST_SH_MASK_DCN30(_MASK) +}; + +#define opp_regs(id)\ +[id] = {\ + OPP_REG_LIST_DCN30(id),\ +} + +static const struct dcn20_opp_registers opp_regs[] = { + opp_regs(0), + opp_regs(1), + opp_regs(2), + opp_regs(3) +}; + +static const struct dcn20_opp_shift opp_shift = { + OPP_MASK_SH_LIST_DCN20(__SHIFT) +}; + +static const struct dcn20_opp_mask opp_mask = { + OPP_MASK_SH_LIST_DCN20(_MASK) +}; + +#define aux_engine_regs(id)\ +[id] = {\ + AUX_COMMON_REG_LIST0(id), \ + .AUXN_IMPCAL = 0, \ + .AUXP_IMPCAL = 0, \ + .AUX_RESET_MASK = DP_AUX0_AUX_CONTROL__AUX_RESET_MASK, \ +} + +static const struct dce110_aux_registers aux_engine_regs[] = { + aux_engine_regs(0), + aux_engine_regs(1), + aux_engine_regs(2), + aux_engine_regs(3), + aux_engine_regs(4) +}; + +#define dwbc_regs_dcn3(id)\ +[id] = {\ + DWBC_COMMON_REG_LIST_DCN30(id),\ +} + +static const struct dcn30_dwbc_registers dwbc30_regs[] = { + dwbc_regs_dcn3(0), +}; + +static const struct dcn30_dwbc_shift dwbc30_shift = { + DWBC_COMMON_MASK_SH_LIST_DCN30(__SHIFT) +}; + +static const struct dcn30_dwbc_mask dwbc30_mask = { + DWBC_COMMON_MASK_SH_LIST_DCN30(_MASK) +}; + +#define mcif_wb_regs_dcn3(id)\ +[id] = {\ + MCIF_WB_COMMON_REG_LIST_DCN30(id),\ +} + +static const struct dcn30_mmhubbub_registers mcif_wb30_regs[] = { + mcif_wb_regs_dcn3(0) +}; + +static const struct dcn30_mmhubbub_shift mcif_wb30_shift = { + MCIF_WB_COMMON_MASK_SH_LIST_DCN30(__SHIFT) +}; + +static const struct dcn30_mmhubbub_mask mcif_wb30_mask = { + MCIF_WB_COMMON_MASK_SH_LIST_DCN30(_MASK) +}; + +#define dsc_regsDCN314(id)\ +[id] = {\ + DSC_REG_LIST_DCN20(id)\ +} + +static const struct dcn20_dsc_registers dsc_regs[] = { + dsc_regsDCN314(0), + dsc_regsDCN314(1), + dsc_regsDCN314(2), + dsc_regsDCN314(3) +}; + +static const struct dcn20_dsc_shift dsc_shift = { + DSC_REG_LIST_SH_MASK_DCN20(__SHIFT) +}; + +static const struct dcn20_dsc_mask dsc_mask = { + DSC_REG_LIST_SH_MASK_DCN20(_MASK) +}; + +static const struct dcn30_mpc_registers mpc_regs = { + MPC_REG_LIST_DCN3_0(0), + MPC_REG_LIST_DCN3_0(1), + MPC_REG_LIST_DCN3_0(2), + MPC_REG_LIST_DCN3_0(3), + MPC_OUT_MUX_REG_LIST_DCN3_0(0), + MPC_OUT_MUX_REG_LIST_DCN3_0(1), + MPC_OUT_MUX_REG_LIST_DCN3_0(2), + MPC_OUT_MUX_REG_LIST_DCN3_0(3), + MPC_RMU_GLOBAL_REG_LIST_DCN3AG, + MPC_RMU_REG_LIST_DCN3AG(0), + MPC_RMU_REG_LIST_DCN3AG(1), + //MPC_RMU_REG_LIST_DCN3AG(2), + MPC_DWB_MUX_REG_LIST_DCN3_0(0), +}; + +static const struct dcn30_mpc_shift mpc_shift = { + MPC_COMMON_MASK_SH_LIST_DCN30(__SHIFT) +}; + +static const struct dcn30_mpc_mask mpc_mask = { + MPC_COMMON_MASK_SH_LIST_DCN30(_MASK) +}; + +#define optc_regs(id)\ +[id] = {OPTC_COMMON_REG_LIST_DCN3_14(id)} + +static const struct dcn_optc_registers optc_regs[] = { + optc_regs(0), + optc_regs(1), + optc_regs(2), + optc_regs(3) +}; + +static const struct dcn_optc_shift optc_shift = { + OPTC_COMMON_MASK_SH_LIST_DCN3_14(__SHIFT) +}; + +static const struct dcn_optc_mask optc_mask = { + OPTC_COMMON_MASK_SH_LIST_DCN3_14(_MASK) +}; + +#define hubp_regs(id)\ +[id] = {\ + HUBP_REG_LIST_DCN30(id)\ +} + +static const struct dcn_hubp2_registers hubp_regs[] = { + hubp_regs(0), + hubp_regs(1), + hubp_regs(2), + hubp_regs(3) +}; + + +static const struct dcn_hubp2_shift hubp_shift = { + HUBP_MASK_SH_LIST_DCN31(__SHIFT) +}; + +static const struct dcn_hubp2_mask hubp_mask = { + HUBP_MASK_SH_LIST_DCN31(_MASK) +}; +static const struct dcn_hubbub_registers hubbub_reg = { + HUBBUB_REG_LIST_DCN31(0) +}; + +static const struct dcn_hubbub_shift hubbub_shift = { + HUBBUB_MASK_SH_LIST_DCN31(__SHIFT) +}; + +static const struct dcn_hubbub_mask hubbub_mask = { + HUBBUB_MASK_SH_LIST_DCN31(_MASK) +}; + +static const struct dccg_registers dccg_regs = { + DCCG_REG_LIST_DCN314() +}; + +static const struct dccg_shift dccg_shift = { + DCCG_MASK_SH_LIST_DCN314(__SHIFT) +}; + +static const struct dccg_mask dccg_mask = { + DCCG_MASK_SH_LIST_DCN314(_MASK) +}; + + +#define SRII2(reg_name_pre, reg_name_post, id)\ + .reg_name_pre ## _ ## reg_name_post[id] = BASE(reg ## reg_name_pre \ + ## id ## _ ## reg_name_post ## _BASE_IDX) + \ + reg ## reg_name_pre ## id ## _ ## reg_name_post + + +#define HWSEQ_DCN31_REG_LIST()\ + SR(DCHUBBUB_GLOBAL_TIMER_CNTL), \ + SR(DCHUBBUB_ARB_HOSTVM_CNTL), \ + SR(DIO_MEM_PWR_CTRL), \ + SR(ODM_MEM_PWR_CTRL3), \ + SR(DMU_MEM_PWR_CNTL), \ + SR(MMHUBBUB_MEM_PWR_CNTL), \ + SR(DCCG_GATE_DISABLE_CNTL), \ + SR(DCCG_GATE_DISABLE_CNTL2), \ + SR(DCFCLK_CNTL),\ + SR(DC_MEM_GLOBAL_PWR_REQ_CNTL), \ + SRII(PIXEL_RATE_CNTL, OTG, 0), \ + SRII(PIXEL_RATE_CNTL, OTG, 1),\ + SRII(PIXEL_RATE_CNTL, OTG, 2),\ + SRII(PIXEL_RATE_CNTL, OTG, 3),\ + SRII(PHYPLL_PIXEL_RATE_CNTL, OTG, 0),\ + SRII(PHYPLL_PIXEL_RATE_CNTL, OTG, 1),\ + SRII(PHYPLL_PIXEL_RATE_CNTL, OTG, 2),\ + SRII(PHYPLL_PIXEL_RATE_CNTL, OTG, 3),\ + SR(MICROSECOND_TIME_BASE_DIV), \ + SR(MILLISECOND_TIME_BASE_DIV), \ + SR(DISPCLK_FREQ_CHANGE_CNTL), \ + SR(RBBMIF_TIMEOUT_DIS), \ + SR(RBBMIF_TIMEOUT_DIS_2), \ + SR(DCHUBBUB_CRC_CTRL), \ + SR(DPP_TOP0_DPP_CRC_CTRL), \ + SR(DPP_TOP0_DPP_CRC_VAL_B_A), \ + SR(DPP_TOP0_DPP_CRC_VAL_R_G), \ + SR(MPC_CRC_CTRL), \ + SR(MPC_CRC_RESULT_GB), \ + SR(MPC_CRC_RESULT_C), \ + SR(MPC_CRC_RESULT_AR), \ + SR(DOMAIN0_PG_CONFIG), \ + SR(DOMAIN1_PG_CONFIG), \ + SR(DOMAIN2_PG_CONFIG), \ + SR(DOMAIN3_PG_CONFIG), \ + SR(DOMAIN16_PG_CONFIG), \ + SR(DOMAIN17_PG_CONFIG), \ + SR(DOMAIN18_PG_CONFIG), \ + SR(DOMAIN19_PG_CONFIG), \ + SR(DOMAIN0_PG_STATUS), \ + SR(DOMAIN1_PG_STATUS), \ + SR(DOMAIN2_PG_STATUS), \ + SR(DOMAIN3_PG_STATUS), \ + SR(DOMAIN16_PG_STATUS), \ + SR(DOMAIN17_PG_STATUS), \ + SR(DOMAIN18_PG_STATUS), \ + SR(DOMAIN19_PG_STATUS), \ + SR(D1VGA_CONTROL), \ + SR(D2VGA_CONTROL), \ + SR(D3VGA_CONTROL), \ + SR(D4VGA_CONTROL), \ + SR(D5VGA_CONTROL), \ + SR(D6VGA_CONTROL), \ + SR(DC_IP_REQUEST_CNTL), \ + SR(AZALIA_AUDIO_DTO), \ + SR(AZALIA_CONTROLLER_CLOCK_GATING), \ + SR(HPO_TOP_HW_CONTROL) + +static const struct dce_hwseq_registers hwseq_reg = { + HWSEQ_DCN31_REG_LIST() +}; + +#define HWSEQ_DCN31_MASK_SH_LIST(mask_sh)\ + HWSEQ_DCN_MASK_SH_LIST(mask_sh), \ + HWS_SF(, DCHUBBUB_GLOBAL_TIMER_CNTL, DCHUBBUB_GLOBAL_TIMER_REFDIV, mask_sh), \ + HWS_SF(, DCHUBBUB_ARB_HOSTVM_CNTL, DISABLE_HOSTVM_FORCE_ALLOW_PSTATE, mask_sh), \ + HWS_SF(, DOMAIN0_PG_CONFIG, DOMAIN_POWER_FORCEON, mask_sh), \ + HWS_SF(, DOMAIN0_PG_CONFIG, DOMAIN_POWER_GATE, mask_sh), \ + HWS_SF(, DOMAIN1_PG_CONFIG, DOMAIN_POWER_FORCEON, mask_sh), \ + HWS_SF(, DOMAIN1_PG_CONFIG, DOMAIN_POWER_GATE, mask_sh), \ + HWS_SF(, DOMAIN2_PG_CONFIG, DOMAIN_POWER_FORCEON, mask_sh), \ + HWS_SF(, DOMAIN2_PG_CONFIG, DOMAIN_POWER_GATE, mask_sh), \ + HWS_SF(, DOMAIN3_PG_CONFIG, DOMAIN_POWER_FORCEON, mask_sh), \ + HWS_SF(, DOMAIN3_PG_CONFIG, DOMAIN_POWER_GATE, mask_sh), \ + HWS_SF(, DOMAIN16_PG_CONFIG, DOMAIN_POWER_FORCEON, mask_sh), \ + HWS_SF(, DOMAIN16_PG_CONFIG, DOMAIN_POWER_GATE, mask_sh), \ + HWS_SF(, DOMAIN17_PG_CONFIG, DOMAIN_POWER_FORCEON, mask_sh), \ + HWS_SF(, DOMAIN17_PG_CONFIG, DOMAIN_POWER_GATE, mask_sh), \ + HWS_SF(, DOMAIN18_PG_CONFIG, DOMAIN_POWER_FORCEON, mask_sh), \ + HWS_SF(, DOMAIN18_PG_CONFIG, DOMAIN_POWER_GATE, mask_sh), \ + HWS_SF(, DOMAIN19_PG_CONFIG, DOMAIN_POWER_FORCEON, mask_sh), \ + HWS_SF(, DOMAIN19_PG_CONFIG, DOMAIN_POWER_GATE, mask_sh), \ + HWS_SF(, DOMAIN0_PG_STATUS, DOMAIN_PGFSM_PWR_STATUS, mask_sh), \ + HWS_SF(, DOMAIN1_PG_STATUS, DOMAIN_PGFSM_PWR_STATUS, mask_sh), \ + HWS_SF(, DOMAIN2_PG_STATUS, DOMAIN_PGFSM_PWR_STATUS, mask_sh), \ + HWS_SF(, DOMAIN3_PG_STATUS, DOMAIN_PGFSM_PWR_STATUS, mask_sh), \ + HWS_SF(, DOMAIN16_PG_STATUS, DOMAIN_PGFSM_PWR_STATUS, mask_sh), \ + HWS_SF(, DOMAIN17_PG_STATUS, DOMAIN_PGFSM_PWR_STATUS, mask_sh), \ + HWS_SF(, DOMAIN18_PG_STATUS, DOMAIN_PGFSM_PWR_STATUS, mask_sh), \ + HWS_SF(, DOMAIN19_PG_STATUS, DOMAIN_PGFSM_PWR_STATUS, mask_sh), \ + HWS_SF(, DC_IP_REQUEST_CNTL, IP_REQUEST_EN, mask_sh), \ + HWS_SF(, AZALIA_AUDIO_DTO, AZALIA_AUDIO_DTO_MODULE, mask_sh), \ + HWS_SF(, HPO_TOP_CLOCK_CONTROL, HPO_HDMISTREAMCLK_G_GATE_DIS, mask_sh), \ + HWS_SF(, DMU_MEM_PWR_CNTL, DMCU_ERAM_MEM_PWR_FORCE, mask_sh), \ + HWS_SF(, ODM_MEM_PWR_CTRL3, ODM_MEM_UNASSIGNED_PWR_MODE, mask_sh), \ + HWS_SF(, ODM_MEM_PWR_CTRL3, ODM_MEM_VBLANK_PWR_MODE, mask_sh), \ + HWS_SF(, MMHUBBUB_MEM_PWR_CNTL, VGA_MEM_PWR_FORCE, mask_sh), \ + HWS_SF(, DIO_MEM_PWR_CTRL, I2C_LIGHT_SLEEP_FORCE, mask_sh), \ + HWS_SF(, HPO_TOP_HW_CONTROL, HPO_IO_EN, mask_sh) + +static const struct dce_hwseq_shift hwseq_shift = { + HWSEQ_DCN31_MASK_SH_LIST(__SHIFT) +}; + +static const struct dce_hwseq_mask hwseq_mask = { + HWSEQ_DCN31_MASK_SH_LIST(_MASK) +}; +#define vmid_regs(id)\ +[id] = {\ + DCN20_VMID_REG_LIST(id)\ +} + +static const struct dcn_vmid_registers vmid_regs[] = { + vmid_regs(0), + vmid_regs(1), + vmid_regs(2), + vmid_regs(3), + vmid_regs(4), + vmid_regs(5), + vmid_regs(6), + vmid_regs(7), + vmid_regs(8), + vmid_regs(9), + vmid_regs(10), + vmid_regs(11), + vmid_regs(12), + vmid_regs(13), + vmid_regs(14), + vmid_regs(15) +}; + +static const struct dcn20_vmid_shift vmid_shifts = { + DCN20_VMID_MASK_SH_LIST(__SHIFT) +}; + +static const struct dcn20_vmid_mask vmid_masks = { + DCN20_VMID_MASK_SH_LIST(_MASK) +}; + +static const struct resource_caps res_cap_dcn314 = { + .num_timing_generator = 4, + .num_opp = 4, + .num_video_plane = 4, + .num_audio = 5, + .num_stream_encoder = 5, + .num_dig_link_enc = 5, + .num_hpo_dp_stream_encoder = 4, + .num_hpo_dp_link_encoder = 2, + .num_pll = 5, + .num_dwb = 1, + .num_ddc = 5, + .num_vmid = 16, + .num_mpc_3dlut = 2, + .num_dsc = 4, +}; + +static const struct dc_plane_cap plane_cap = { + .type = DC_PLANE_TYPE_DCN_UNIVERSAL, + .per_pixel_alpha = true, + + .pixel_format_support = { + .argb8888 = true, + .nv12 = true, + .fp16 = true, + .p010 = true, + .ayuv = false, + }, + + .max_upscale_factor = { + .argb8888 = 16000, + .nv12 = 16000, + .fp16 = 16000 + }, + + // 6:1 downscaling ratio: 1000/6 = 166.666 + // 4:1 downscaling ratio for ARGB888 to prevent underflow during P010 playback: 1000/4 = 250 + .max_downscale_factor = { + .argb8888 = 250, + .nv12 = 167, + .fp16 = 167 + }, + 64, + 64 +}; + +static const struct dc_debug_options debug_defaults_drv = { + .disable_z10 = false, + .enable_z9_disable_interface = true, + .minimum_z8_residency_time = 2000, + .psr_skip_crtc_disable = true, + .replay_skip_crtc_disabled = true, + .disable_dmcu = true, + .force_abm_enable = false, + .timing_trace = false, + .clock_trace = true, + .disable_dpp_power_gate = false, + .disable_hubp_power_gate = false, + .disable_pplib_clock_request = false, + .pipe_split_policy = MPC_SPLIT_DYNAMIC, + .force_single_disp_pipe_split = false, + .disable_dcc = DCC_ENABLE, + .vsr_support = true, + .performance_trace = false, + .max_downscale_src_width = 4096,/*upto true 4k*/ + .disable_pplib_wm_range = false, + .scl_reset_length10 = true, + .sanity_checks = true, + .underflow_assert_delay_us = 0xFFFFFFFF, + .dwb_fi_phase = -1, // -1 = disable, + .dmub_command_table = true, + .pstate_enabled = true, + .use_max_lb = true, + .enable_mem_low_power = { + .bits = { + .vga = true, + .i2c = true, + .dmcu = false, // This is previously known to cause hang on S3 cycles if enabled + .dscl = true, + .cm = true, + .mpc = true, + .optc = true, + .vpg = true, + .afmt = true, + } + }, + + .root_clock_optimization = { + .bits = { + .dpp = true, + .dsc = true, + .hdmistream = true, + .hdmichar = true, + .dpstream = true, + .symclk32_se = false, + .symclk32_le = true, + .symclk_fe = true, + .physymclk = true, + .dpiasymclk = true, + } + }, + + .seamless_boot_odm_combine = true, + .using_dml2 = false, +}; + +static const struct dc_debug_options debug_defaults_diags = { + .disable_dmcu = true, + .force_abm_enable = false, + .timing_trace = true, + .clock_trace = true, + .disable_dpp_power_gate = true, + .disable_hubp_power_gate = true, + .disable_clock_gate = true, + .disable_pplib_clock_request = true, + .disable_pplib_wm_range = true, + .disable_stutter = false, + .scl_reset_length10 = true, + .dwb_fi_phase = -1, // -1 = disable + .dmub_command_table = true, + .enable_tri_buf = true, + .use_max_lb = true +}; + +static const struct dc_panel_config panel_config_defaults = { + .psr = { + .disable_psr = false, + .disallow_psrsu = false, + .disallow_replay = false, + }, + .ilr = { + .optimize_edp_link_rate = true, + }, +}; + +static void dcn31_dpp_destroy(struct dpp **dpp) +{ + kfree(TO_DCN20_DPP(*dpp)); + *dpp = NULL; +} + +static struct dpp *dcn31_dpp_create( + struct dc_context *ctx, + uint32_t inst) +{ + struct dcn3_dpp *dpp = + kzalloc(sizeof(struct dcn3_dpp), GFP_KERNEL); + + if (!dpp) + return NULL; + + if (dpp3_construct(dpp, ctx, inst, + &dpp_regs[inst], &tf_shift, &tf_mask)) + return &dpp->base; + + BREAK_TO_DEBUGGER(); + kfree(dpp); + return NULL; +} + +static struct output_pixel_processor *dcn31_opp_create( + struct dc_context *ctx, uint32_t inst) +{ + struct dcn20_opp *opp = + kzalloc(sizeof(struct dcn20_opp), GFP_KERNEL); + + if (!opp) { + BREAK_TO_DEBUGGER(); + return NULL; + } + + dcn20_opp_construct(opp, ctx, inst, + &opp_regs[inst], &opp_shift, &opp_mask); + return &opp->base; +} + +static struct dce_aux *dcn31_aux_engine_create( + struct dc_context *ctx, + uint32_t inst) +{ + struct aux_engine_dce110 *aux_engine = + kzalloc(sizeof(struct aux_engine_dce110), GFP_KERNEL); + + if (!aux_engine) + return NULL; + + dce110_aux_engine_construct(aux_engine, ctx, inst, + SW_AUX_TIMEOUT_PERIOD_MULTIPLIER * AUX_TIMEOUT_PERIOD, + &aux_engine_regs[inst], + &aux_mask, + &aux_shift, + ctx->dc->caps.extended_aux_timeout_support); + + return &aux_engine->base; +} +#define i2c_inst_regs(id) { I2C_HW_ENGINE_COMMON_REG_LIST_DCN30(id) } + +static const struct dce_i2c_registers i2c_hw_regs[] = { + i2c_inst_regs(1), + i2c_inst_regs(2), + i2c_inst_regs(3), + i2c_inst_regs(4), + i2c_inst_regs(5), +}; + +static const struct dce_i2c_shift i2c_shifts = { + I2C_COMMON_MASK_SH_LIST_DCN30(__SHIFT) +}; + +static const struct dce_i2c_mask i2c_masks = { + I2C_COMMON_MASK_SH_LIST_DCN30(_MASK) +}; + +/* ========================================================== */ + +/* + * DPIA index | Preferred Encoder | Host Router + * 0 | C | 0 + * 1 | First Available | 0 + * 2 | D | 1 + * 3 | First Available | 1 + */ +/* ========================================================== */ +static const enum engine_id dpia_to_preferred_enc_id_table[] = { + ENGINE_ID_DIGC, + ENGINE_ID_DIGC, + ENGINE_ID_DIGD, + ENGINE_ID_DIGD +}; + +static enum engine_id dcn314_get_preferred_eng_id_dpia(unsigned int dpia_index) +{ + return dpia_to_preferred_enc_id_table[dpia_index]; +} + +static struct dce_i2c_hw *dcn31_i2c_hw_create( + struct dc_context *ctx, + uint32_t inst) +{ + struct dce_i2c_hw *dce_i2c_hw = + kzalloc(sizeof(struct dce_i2c_hw), GFP_KERNEL); + + if (!dce_i2c_hw) + return NULL; + + dcn2_i2c_hw_construct(dce_i2c_hw, ctx, inst, + &i2c_hw_regs[inst], &i2c_shifts, &i2c_masks); + + return dce_i2c_hw; +} +static struct mpc *dcn31_mpc_create( + struct dc_context *ctx, + int num_mpcc, + int num_rmu) +{ + struct dcn30_mpc *mpc30 = kzalloc(sizeof(struct dcn30_mpc), + GFP_KERNEL); + + if (!mpc30) + return NULL; + + dcn30_mpc_construct(mpc30, ctx, + &mpc_regs, + &mpc_shift, + &mpc_mask, + num_mpcc, + num_rmu); + + return &mpc30->base; +} + +static struct hubbub *dcn31_hubbub_create(struct dc_context *ctx) +{ + int i; + + struct dcn20_hubbub *hubbub3 = kzalloc(sizeof(struct dcn20_hubbub), + GFP_KERNEL); + + if (!hubbub3) + return NULL; + + hubbub31_construct(hubbub3, ctx, + &hubbub_reg, + &hubbub_shift, + &hubbub_mask, + dcn3_14_ip.det_buffer_size_kbytes, + dcn3_14_ip.pixel_chunk_size_kbytes, + dcn3_14_ip.config_return_buffer_size_in_kbytes); + + + for (i = 0; i < res_cap_dcn314.num_vmid; i++) { + struct dcn20_vmid *vmid = &hubbub3->vmid[i]; + + vmid->ctx = ctx; + + vmid->regs = &vmid_regs[i]; + vmid->shifts = &vmid_shifts; + vmid->masks = &vmid_masks; + } + + return &hubbub3->base; +} + +static struct timing_generator *dcn31_timing_generator_create( + struct dc_context *ctx, + uint32_t instance) +{ + struct optc *tgn10 = + kzalloc(sizeof(struct optc), GFP_KERNEL); + + if (!tgn10) + return NULL; + + tgn10->base.inst = instance; + tgn10->base.ctx = ctx; + + tgn10->tg_regs = &optc_regs[instance]; + tgn10->tg_shift = &optc_shift; + tgn10->tg_mask = &optc_mask; + + dcn314_timing_generator_init(tgn10); + + return &tgn10->base; +} + +static const struct encoder_feature_support link_enc_feature = { + .max_hdmi_deep_color = COLOR_DEPTH_121212, + .max_hdmi_pixel_clock = 600000, + .hdmi_ycbcr420_supported = true, + .dp_ycbcr420_supported = true, + .fec_supported = true, + .flags.bits.IS_HBR2_CAPABLE = true, + .flags.bits.IS_HBR3_CAPABLE = true, + .flags.bits.IS_TPS3_CAPABLE = true, + .flags.bits.IS_TPS4_CAPABLE = true +}; + +static struct link_encoder *dcn31_link_encoder_create( + struct dc_context *ctx, + const struct encoder_init_data *enc_init_data) +{ + struct dcn20_link_encoder *enc20 = + kzalloc(sizeof(struct dcn20_link_encoder), GFP_KERNEL); + + if (!enc20) + return NULL; + + dcn31_link_encoder_construct(enc20, + enc_init_data, + &link_enc_feature, + &link_enc_regs[enc_init_data->transmitter], + &link_enc_aux_regs[enc_init_data->channel - 1], + &link_enc_hpd_regs[enc_init_data->hpd_source], + &le_shift, + &le_mask); + + return &enc20->enc10.base; +} + +/* Create a minimal link encoder object not associated with a particular + * physical connector. + * resource_funcs.link_enc_create_minimal + */ +static struct link_encoder *dcn31_link_enc_create_minimal( + struct dc_context *ctx, enum engine_id eng_id) +{ + struct dcn20_link_encoder *enc20; + + if ((eng_id - ENGINE_ID_DIGA) > ctx->dc->res_pool->res_cap->num_dig_link_enc) + return NULL; + + enc20 = kzalloc(sizeof(struct dcn20_link_encoder), GFP_KERNEL); + if (!enc20) + return NULL; + + dcn31_link_encoder_construct_minimal( + enc20, + ctx, + &link_enc_feature, + &link_enc_regs[eng_id - ENGINE_ID_DIGA], + eng_id); + + return &enc20->enc10.base; +} + +static struct panel_cntl *dcn31_panel_cntl_create(const struct panel_cntl_init_data *init_data) +{ + struct dcn31_panel_cntl *panel_cntl = + kzalloc(sizeof(struct dcn31_panel_cntl), GFP_KERNEL); + + if (!panel_cntl) + return NULL; + + dcn31_panel_cntl_construct(panel_cntl, init_data); + + return &panel_cntl->base; +} + +static void read_dce_straps( + struct dc_context *ctx, + struct resource_straps *straps) +{ + generic_reg_get(ctx, regDC_PINSTRAPS + BASE(regDC_PINSTRAPS_BASE_IDX), + FN(DC_PINSTRAPS, DC_PINSTRAPS_AUDIO), &straps->dc_pinstraps_audio); + +} + +static struct audio *dcn31_create_audio( + struct dc_context *ctx, unsigned int inst) +{ + return dce_audio_create(ctx, inst, + &audio_regs[inst], &audio_shift, &audio_mask); +} + +static struct vpg *dcn31_vpg_create( + struct dc_context *ctx, + uint32_t inst) +{ + struct dcn31_vpg *vpg31 = kzalloc(sizeof(struct dcn31_vpg), GFP_KERNEL); + + if (!vpg31) + return NULL; + + vpg31_construct(vpg31, ctx, inst, + &vpg_regs[inst], + &vpg_shift, + &vpg_mask); + + return &vpg31->base; +} + +static struct afmt *dcn31_afmt_create( + struct dc_context *ctx, + uint32_t inst) +{ + struct dcn31_afmt *afmt31 = kzalloc(sizeof(struct dcn31_afmt), GFP_KERNEL); + + if (!afmt31) + return NULL; + + afmt31_construct(afmt31, ctx, inst, + &afmt_regs[inst], + &afmt_shift, + &afmt_mask); + + // Light sleep by default, no need to power down here + + return &afmt31->base; +} + +static struct apg *dcn31_apg_create( + struct dc_context *ctx, + uint32_t inst) +{ + struct dcn31_apg *apg31 = kzalloc(sizeof(struct dcn31_apg), GFP_KERNEL); + + if (!apg31) + return NULL; + + apg31_construct(apg31, ctx, inst, + &apg_regs[inst], + &apg_shift, + &apg_mask); + + return &apg31->base; +} + +static struct stream_encoder *dcn314_stream_encoder_create( + enum engine_id eng_id, + struct dc_context *ctx) +{ + struct dcn10_stream_encoder *enc1; + struct vpg *vpg; + struct afmt *afmt; + int vpg_inst; + int afmt_inst; + + /* Mapping of VPG, AFMT, DME register blocks to DIO block instance */ + if (eng_id < ENGINE_ID_DIGF) { + vpg_inst = eng_id; + afmt_inst = eng_id; + } else + return NULL; + + enc1 = kzalloc(sizeof(struct dcn10_stream_encoder), GFP_KERNEL); + vpg = dcn31_vpg_create(ctx, vpg_inst); + afmt = dcn31_afmt_create(ctx, afmt_inst); + + if (!enc1 || !vpg || !afmt) { + kfree(enc1); + kfree(vpg); + kfree(afmt); + return NULL; + } + + dcn314_dio_stream_encoder_construct(enc1, ctx, ctx->dc_bios, + eng_id, vpg, afmt, + &stream_enc_regs[eng_id], + &se_shift, &se_mask); + + return &enc1->base; +} + +static struct hpo_dp_stream_encoder *dcn31_hpo_dp_stream_encoder_create( + enum engine_id eng_id, + struct dc_context *ctx) +{ + struct dcn31_hpo_dp_stream_encoder *hpo_dp_enc31; + struct vpg *vpg; + struct apg *apg; + uint32_t hpo_dp_inst; + uint32_t vpg_inst; + uint32_t apg_inst; + + ASSERT((eng_id >= ENGINE_ID_HPO_DP_0) && (eng_id <= ENGINE_ID_HPO_DP_3)); + hpo_dp_inst = eng_id - ENGINE_ID_HPO_DP_0; + + /* Mapping of VPG register blocks to HPO DP block instance: + * VPG[6] -> HPO_DP[0] + * VPG[7] -> HPO_DP[1] + * VPG[8] -> HPO_DP[2] + * VPG[9] -> HPO_DP[3] + */ + //Uses offset index 5-8, but actually maps to vpg_inst 6-9 + vpg_inst = hpo_dp_inst + 5; + + /* Mapping of APG register blocks to HPO DP block instance: + * APG[0] -> HPO_DP[0] + * APG[1] -> HPO_DP[1] + * APG[2] -> HPO_DP[2] + * APG[3] -> HPO_DP[3] + */ + apg_inst = hpo_dp_inst; + + /* allocate HPO stream encoder and create VPG sub-block */ + hpo_dp_enc31 = kzalloc(sizeof(struct dcn31_hpo_dp_stream_encoder), GFP_KERNEL); + vpg = dcn31_vpg_create(ctx, vpg_inst); + apg = dcn31_apg_create(ctx, apg_inst); + + if (!hpo_dp_enc31 || !vpg || !apg) { + kfree(hpo_dp_enc31); + kfree(vpg); + kfree(apg); + return NULL; + } + + dcn31_hpo_dp_stream_encoder_construct(hpo_dp_enc31, ctx, ctx->dc_bios, + hpo_dp_inst, eng_id, vpg, apg, + &hpo_dp_stream_enc_regs[hpo_dp_inst], + &hpo_dp_se_shift, &hpo_dp_se_mask); + + return &hpo_dp_enc31->base; +} + +static struct hpo_dp_link_encoder *dcn31_hpo_dp_link_encoder_create( + uint8_t inst, + struct dc_context *ctx) +{ + struct dcn31_hpo_dp_link_encoder *hpo_dp_enc31; + + /* allocate HPO link encoder */ + hpo_dp_enc31 = kzalloc(sizeof(struct dcn31_hpo_dp_link_encoder), GFP_KERNEL); + + hpo_dp_link_encoder31_construct(hpo_dp_enc31, ctx, inst, + &hpo_dp_link_enc_regs[inst], + &hpo_dp_le_shift, &hpo_dp_le_mask); + + return &hpo_dp_enc31->base; +} + +static struct dce_hwseq *dcn314_hwseq_create( + struct dc_context *ctx) +{ + struct dce_hwseq *hws = kzalloc(sizeof(struct dce_hwseq), GFP_KERNEL); + + if (hws) { + hws->ctx = ctx; + hws->regs = &hwseq_reg; + hws->shifts = &hwseq_shift; + hws->masks = &hwseq_mask; + } + return hws; +} +static const struct resource_create_funcs res_create_funcs = { + .read_dce_straps = read_dce_straps, + .create_audio = dcn31_create_audio, + .create_stream_encoder = dcn314_stream_encoder_create, + .create_hpo_dp_stream_encoder = dcn31_hpo_dp_stream_encoder_create, + .create_hpo_dp_link_encoder = dcn31_hpo_dp_link_encoder_create, + .create_hwseq = dcn314_hwseq_create, +}; + +static void dcn314_resource_destruct(struct dcn314_resource_pool *pool) +{ + unsigned int i; + + for (i = 0; i < pool->base.stream_enc_count; i++) { + if (pool->base.stream_enc[i] != NULL) { + if (pool->base.stream_enc[i]->vpg != NULL) { + kfree(DCN30_VPG_FROM_VPG(pool->base.stream_enc[i]->vpg)); + pool->base.stream_enc[i]->vpg = NULL; + } + if (pool->base.stream_enc[i]->afmt != NULL) { + kfree(DCN30_AFMT_FROM_AFMT(pool->base.stream_enc[i]->afmt)); + pool->base.stream_enc[i]->afmt = NULL; + } + kfree(DCN10STRENC_FROM_STRENC(pool->base.stream_enc[i])); + pool->base.stream_enc[i] = NULL; + } + } + + for (i = 0; i < pool->base.hpo_dp_stream_enc_count; i++) { + if (pool->base.hpo_dp_stream_enc[i] != NULL) { + if (pool->base.hpo_dp_stream_enc[i]->vpg != NULL) { + kfree(DCN30_VPG_FROM_VPG(pool->base.hpo_dp_stream_enc[i]->vpg)); + pool->base.hpo_dp_stream_enc[i]->vpg = NULL; + } + if (pool->base.hpo_dp_stream_enc[i]->apg != NULL) { + kfree(DCN31_APG_FROM_APG(pool->base.hpo_dp_stream_enc[i]->apg)); + pool->base.hpo_dp_stream_enc[i]->apg = NULL; + } + kfree(DCN3_1_HPO_DP_STREAM_ENC_FROM_HPO_STREAM_ENC(pool->base.hpo_dp_stream_enc[i])); + pool->base.hpo_dp_stream_enc[i] = NULL; + } + } + + for (i = 0; i < pool->base.hpo_dp_link_enc_count; i++) { + if (pool->base.hpo_dp_link_enc[i] != NULL) { + kfree(DCN3_1_HPO_DP_LINK_ENC_FROM_HPO_LINK_ENC(pool->base.hpo_dp_link_enc[i])); + pool->base.hpo_dp_link_enc[i] = NULL; + } + } + + for (i = 0; i < pool->base.res_cap->num_dsc; i++) { + if (pool->base.dscs[i] != NULL) + dcn20_dsc_destroy(&pool->base.dscs[i]); + } + + if (pool->base.mpc != NULL) { + kfree(TO_DCN20_MPC(pool->base.mpc)); + pool->base.mpc = NULL; + } + if (pool->base.hubbub != NULL) { + kfree(pool->base.hubbub); + pool->base.hubbub = NULL; + } + for (i = 0; i < pool->base.pipe_count; i++) { + if (pool->base.dpps[i] != NULL) + dcn31_dpp_destroy(&pool->base.dpps[i]); + + if (pool->base.ipps[i] != NULL) + pool->base.ipps[i]->funcs->ipp_destroy(&pool->base.ipps[i]); + + if (pool->base.hubps[i] != NULL) { + kfree(TO_DCN20_HUBP(pool->base.hubps[i])); + pool->base.hubps[i] = NULL; + } + + if (pool->base.irqs != NULL) + dal_irq_service_destroy(&pool->base.irqs); + } + + for (i = 0; i < pool->base.res_cap->num_ddc; i++) { + if (pool->base.engines[i] != NULL) + dce110_engine_destroy(&pool->base.engines[i]); + if (pool->base.hw_i2cs[i] != NULL) { + kfree(pool->base.hw_i2cs[i]); + pool->base.hw_i2cs[i] = NULL; + } + if (pool->base.sw_i2cs[i] != NULL) { + kfree(pool->base.sw_i2cs[i]); + pool->base.sw_i2cs[i] = NULL; + } + } + + for (i = 0; i < pool->base.res_cap->num_opp; i++) { + if (pool->base.opps[i] != NULL) + pool->base.opps[i]->funcs->opp_destroy(&pool->base.opps[i]); + } + + for (i = 0; i < pool->base.res_cap->num_timing_generator; i++) { + if (pool->base.timing_generators[i] != NULL) { + kfree(DCN10TG_FROM_TG(pool->base.timing_generators[i])); + pool->base.timing_generators[i] = NULL; + } + } + + for (i = 0; i < pool->base.res_cap->num_dwb; i++) { + if (pool->base.dwbc[i] != NULL) { + kfree(TO_DCN30_DWBC(pool->base.dwbc[i])); + pool->base.dwbc[i] = NULL; + } + if (pool->base.mcif_wb[i] != NULL) { + kfree(TO_DCN30_MMHUBBUB(pool->base.mcif_wb[i])); + pool->base.mcif_wb[i] = NULL; + } + } + + for (i = 0; i < pool->base.audio_count; i++) { + if (pool->base.audios[i]) + dce_aud_destroy(&pool->base.audios[i]); + } + + for (i = 0; i < pool->base.clk_src_count; i++) { + if (pool->base.clock_sources[i] != NULL) { + dcn20_clock_source_destroy(&pool->base.clock_sources[i]); + pool->base.clock_sources[i] = NULL; + } + } + + for (i = 0; i < pool->base.res_cap->num_mpc_3dlut; i++) { + if (pool->base.mpc_lut[i] != NULL) { + dc_3dlut_func_release(pool->base.mpc_lut[i]); + pool->base.mpc_lut[i] = NULL; + } + if (pool->base.mpc_shaper[i] != NULL) { + dc_transfer_func_release(pool->base.mpc_shaper[i]); + pool->base.mpc_shaper[i] = NULL; + } + } + + if (pool->base.dp_clock_source != NULL) { + dcn20_clock_source_destroy(&pool->base.dp_clock_source); + pool->base.dp_clock_source = NULL; + } + + for (i = 0; i < pool->base.res_cap->num_timing_generator; i++) { + if (pool->base.multiple_abms[i] != NULL) + dce_abm_destroy(&pool->base.multiple_abms[i]); + } + + if (pool->base.psr != NULL) + dmub_psr_destroy(&pool->base.psr); + + if (pool->base.replay != NULL) + dmub_replay_destroy(&pool->base.replay); + + if (pool->base.dccg != NULL) + dcn_dccg_destroy(&pool->base.dccg); +} + +static struct hubp *dcn31_hubp_create( + struct dc_context *ctx, + uint32_t inst) +{ + struct dcn20_hubp *hubp2 = + kzalloc(sizeof(struct dcn20_hubp), GFP_KERNEL); + + if (!hubp2) + return NULL; + + if (hubp31_construct(hubp2, ctx, inst, + &hubp_regs[inst], &hubp_shift, &hubp_mask)) + return &hubp2->base; + + BREAK_TO_DEBUGGER(); + kfree(hubp2); + return NULL; +} + +static bool dcn31_dwbc_create(struct dc_context *ctx, struct resource_pool *pool) +{ + int i; + uint32_t pipe_count = pool->res_cap->num_dwb; + + for (i = 0; i < pipe_count; i++) { + struct dcn30_dwbc *dwbc30 = kzalloc(sizeof(struct dcn30_dwbc), + GFP_KERNEL); + + if (!dwbc30) { + dm_error("DC: failed to create dwbc30!\n"); + return false; + } + + dcn30_dwbc_construct(dwbc30, ctx, + &dwbc30_regs[i], + &dwbc30_shift, + &dwbc30_mask, + i); + + pool->dwbc[i] = &dwbc30->base; + } + return true; +} + +static bool dcn31_mmhubbub_create(struct dc_context *ctx, struct resource_pool *pool) +{ + int i; + uint32_t pipe_count = pool->res_cap->num_dwb; + + for (i = 0; i < pipe_count; i++) { + struct dcn30_mmhubbub *mcif_wb30 = kzalloc(sizeof(struct dcn30_mmhubbub), + GFP_KERNEL); + + if (!mcif_wb30) { + dm_error("DC: failed to create mcif_wb30!\n"); + return false; + } + + dcn30_mmhubbub_construct(mcif_wb30, ctx, + &mcif_wb30_regs[i], + &mcif_wb30_shift, + &mcif_wb30_mask, + i); + + pool->mcif_wb[i] = &mcif_wb30->base; + } + return true; +} + +static struct display_stream_compressor *dcn314_dsc_create( + struct dc_context *ctx, uint32_t inst) +{ + struct dcn20_dsc *dsc = + kzalloc(sizeof(struct dcn20_dsc), GFP_KERNEL); + + if (!dsc) { + BREAK_TO_DEBUGGER(); + return NULL; + } + + dsc2_construct(dsc, ctx, inst, &dsc_regs[inst], &dsc_shift, &dsc_mask); + return &dsc->base; +} + +static void dcn314_destroy_resource_pool(struct resource_pool **pool) +{ + struct dcn314_resource_pool *dcn314_pool = TO_DCN314_RES_POOL(*pool); + + dcn314_resource_destruct(dcn314_pool); + kfree(dcn314_pool); + *pool = NULL; +} + +static struct clock_source *dcn31_clock_source_create( + struct dc_context *ctx, + struct dc_bios *bios, + enum clock_source_id id, + const struct dce110_clk_src_regs *regs, + bool dp_clk_src) +{ + struct dce110_clk_src *clk_src = + kzalloc(sizeof(struct dce110_clk_src), GFP_KERNEL); + + if (!clk_src) + return NULL; + + if (dcn31_clk_src_construct(clk_src, ctx, bios, id, + regs, &cs_shift, &cs_mask)) { + clk_src->base.dp_clk_src = dp_clk_src; + return &clk_src->base; + } + + BREAK_TO_DEBUGGER(); + kfree(clk_src); + return NULL; +} + +static int dcn314_populate_dml_pipes_from_context( + struct dc *dc, struct dc_state *context, + display_e2e_pipe_params_st *pipes, + bool fast_validate) +{ + int pipe_cnt; + + DC_FP_START(); + pipe_cnt = dcn314_populate_dml_pipes_from_context_fpu(dc, context, pipes, fast_validate); + DC_FP_END(); + + return pipe_cnt; +} + +static struct dc_cap_funcs cap_funcs = { + .get_dcc_compression_cap = dcn20_get_dcc_compression_cap +}; + +static void dcn314_update_bw_bounding_box(struct dc *dc, struct clk_bw_params *bw_params) +{ + DC_FP_START(); + dcn314_update_bw_bounding_box_fpu(dc, bw_params); + DC_FP_END(); +} + +static void dcn314_get_panel_config_defaults(struct dc_panel_config *panel_config) +{ + *panel_config = panel_config_defaults; +} + +static bool filter_modes_for_single_channel_workaround(struct dc *dc, + struct dc_state *context) +{ + // Filter 2K@240Hz+8K@24fps above combination timing if memory only has single dimm LPDDR + if (dc->clk_mgr->bw_params->vram_type == 34 && + dc->clk_mgr->bw_params->num_channels < 2 && + context->stream_count > 1) { + int total_phy_pix_clk = 0; + + for (int i = 0; i < context->stream_count; i++) + if (context->res_ctx.pipe_ctx[i].stream) + total_phy_pix_clk += context->res_ctx.pipe_ctx[i].stream->phy_pix_clk; + + if (total_phy_pix_clk >= (1148928+826260)) //2K@240Hz+8K@24fps + return true; + } + return false; +} + +bool dcn314_validate_bandwidth(struct dc *dc, + struct dc_state *context, + bool fast_validate) +{ + bool out = false; + + BW_VAL_TRACE_SETUP(); + + int vlevel = 0; + int pipe_cnt = 0; + display_e2e_pipe_params_st *pipes = kzalloc(dc->res_pool->pipe_count * sizeof(display_e2e_pipe_params_st), GFP_KERNEL); + DC_LOGGER_INIT(dc->ctx->logger); + + BW_VAL_TRACE_COUNT(); + + if (filter_modes_for_single_channel_workaround(dc, context)) + goto validate_fail; + + DC_FP_START(); + // do not support self refresh only + out = dcn30_internal_validate_bw(dc, context, pipes, &pipe_cnt, &vlevel, fast_validate, false); + DC_FP_END(); + + // Disable fast_validate to set min dcfclk in calculate_wm_and_dlg + if (pipe_cnt == 0) + fast_validate = false; + + if (!out) + goto validate_fail; + + BW_VAL_TRACE_END_VOLTAGE_LEVEL(); + + if (fast_validate) { + BW_VAL_TRACE_SKIP(fast); + goto validate_out; + } + if (dc->res_pool->funcs->calculate_wm_and_dlg) + dc->res_pool->funcs->calculate_wm_and_dlg(dc, context, pipes, pipe_cnt, vlevel); + + BW_VAL_TRACE_END_WATERMARKS(); + + goto validate_out; + +validate_fail: + DC_LOG_WARNING("Mode Validation Warning: %s failed validation.\n", + dml_get_status_message(context->bw_ctx.dml.vba.ValidationStatus[context->bw_ctx.dml.vba.soc.num_states])); + + BW_VAL_TRACE_SKIP(fail); + out = false; + +validate_out: + kfree(pipes); + + BW_VAL_TRACE_FINISH(); + + return out; +} + +static struct resource_funcs dcn314_res_pool_funcs = { + .destroy = dcn314_destroy_resource_pool, + .link_enc_create = dcn31_link_encoder_create, + .link_enc_create_minimal = dcn31_link_enc_create_minimal, + .link_encs_assign = link_enc_cfg_link_encs_assign, + .link_enc_unassign = link_enc_cfg_link_enc_unassign, + .panel_cntl_create = dcn31_panel_cntl_create, + .validate_bandwidth = dcn314_validate_bandwidth, + .calculate_wm_and_dlg = dcn31_calculate_wm_and_dlg, + .update_soc_for_wm_a = dcn31_update_soc_for_wm_a, + .populate_dml_pipes = dcn314_populate_dml_pipes_from_context, + .acquire_free_pipe_as_secondary_dpp_pipe = dcn20_acquire_free_pipe_for_layer, + .release_pipe = dcn20_release_pipe, + .add_stream_to_ctx = dcn30_add_stream_to_ctx, + .add_dsc_to_stream_resource = dcn20_add_dsc_to_stream_resource, + .remove_stream_from_ctx = dcn20_remove_stream_from_ctx, + .populate_dml_writeback_from_context = dcn30_populate_dml_writeback_from_context, + .set_mcif_arb_params = dcn30_set_mcif_arb_params, + .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 = dcn314_update_bw_bounding_box, + .patch_unknown_plane_state = dcn20_patch_unknown_plane_state, + .get_panel_config_defaults = dcn314_get_panel_config_defaults, + .get_preferred_eng_id_dpia = dcn314_get_preferred_eng_id_dpia, +}; + +static struct clock_source *dcn30_clock_source_create( + struct dc_context *ctx, + struct dc_bios *bios, + enum clock_source_id id, + const struct dce110_clk_src_regs *regs, + bool dp_clk_src) +{ + struct dce110_clk_src *clk_src = + kzalloc(sizeof(struct dce110_clk_src), GFP_KERNEL); + + if (!clk_src) + return NULL; + + if (dcn31_clk_src_construct(clk_src, ctx, bios, id, + regs, &cs_shift, &cs_mask)) { + clk_src->base.dp_clk_src = dp_clk_src; + return &clk_src->base; + } + + BREAK_TO_DEBUGGER(); + kfree(clk_src); + return NULL; +} + +static bool dcn314_resource_construct( + uint8_t num_virtual_links, + struct dc *dc, + struct dcn314_resource_pool *pool) +{ + int i; + struct dc_context *ctx = dc->ctx; + struct irq_service_init_data init_data; + + ctx->dc_bios->regs = &bios_regs; + + pool->base.res_cap = &res_cap_dcn314; + pool->base.funcs = &dcn314_res_pool_funcs; + + /************************************************* + * Resource + asic cap harcoding * + *************************************************/ + pool->base.underlay_pipe_index = NO_UNDERLAY_PIPE; + pool->base.pipe_count = pool->base.res_cap->num_timing_generator; + pool->base.mpcc_count = pool->base.res_cap->num_timing_generator; + dc->caps.max_downscale_ratio = 400; + dc->caps.i2c_speed_in_khz = 100; + dc->caps.i2c_speed_in_khz_hdcp = 100; + dc->caps.max_cursor_size = 256; + dc->caps.min_horizontal_blanking_period = 80; + dc->caps.dmdata_alloc_size = 2048; + dc->caps.max_slave_planes = 2; + dc->caps.max_slave_yuv_planes = 2; + dc->caps.max_slave_rgb_planes = 2; + dc->caps.post_blend_color_processing = true; + dc->caps.force_dp_tps4_for_cp2520 = true; + if (dc->config.forceHBR2CP2520) + dc->caps.force_dp_tps4_for_cp2520 = false; + dc->caps.dp_hpo = true; + dc->caps.dp_hdmi21_pcon_support = true; + dc->caps.edp_dsc_support = true; + dc->caps.extended_aux_timeout_support = true; + dc->caps.dmcub_support = true; + dc->caps.is_apu = true; + dc->caps.seamless_odm = true; + + dc->caps.zstate_support = true; + + /* Color pipeline capabilities */ + dc->caps.color.dpp.dcn_arch = 1; + dc->caps.color.dpp.input_lut_shared = 0; + dc->caps.color.dpp.icsc = 1; + dc->caps.color.dpp.dgam_ram = 0; // must use gamma_corr + dc->caps.color.dpp.dgam_rom_caps.srgb = 1; + dc->caps.color.dpp.dgam_rom_caps.bt2020 = 1; + dc->caps.color.dpp.dgam_rom_caps.gamma2_2 = 1; + dc->caps.color.dpp.dgam_rom_caps.pq = 1; + dc->caps.color.dpp.dgam_rom_caps.hlg = 1; + dc->caps.color.dpp.post_csc = 1; + dc->caps.color.dpp.gamma_corr = 1; + dc->caps.color.dpp.dgam_rom_for_yuv = 0; + + dc->caps.color.dpp.hw_3d_lut = 1; + dc->caps.color.dpp.ogam_ram = 1; + // no OGAM ROM on DCN301 + dc->caps.color.dpp.ogam_rom_caps.srgb = 0; + dc->caps.color.dpp.ogam_rom_caps.bt2020 = 0; + dc->caps.color.dpp.ogam_rom_caps.gamma2_2 = 0; + dc->caps.color.dpp.ogam_rom_caps.pq = 0; + dc->caps.color.dpp.ogam_rom_caps.hlg = 0; + dc->caps.color.dpp.ocsc = 0; + + dc->caps.color.mpc.gamut_remap = 1; + dc->caps.color.mpc.num_3dluts = pool->base.res_cap->num_mpc_3dlut; //2 + dc->caps.color.mpc.ogam_ram = 1; + dc->caps.color.mpc.ogam_rom_caps.srgb = 0; + dc->caps.color.mpc.ogam_rom_caps.bt2020 = 0; + dc->caps.color.mpc.ogam_rom_caps.gamma2_2 = 0; + dc->caps.color.mpc.ogam_rom_caps.pq = 0; + dc->caps.color.mpc.ogam_rom_caps.hlg = 0; + dc->caps.color.mpc.ocsc = 1; + + dc->caps.max_disp_clock_khz_at_vmin = 650000; + + /* Use pipe context based otg sync logic */ + dc->config.use_pipe_ctx_sync_logic = true; + + /* read VBIOS LTTPR caps */ + { + if (ctx->dc_bios->funcs->get_lttpr_caps) { + enum bp_result bp_query_result; + uint8_t is_vbios_lttpr_enable = 0; + + bp_query_result = ctx->dc_bios->funcs->get_lttpr_caps(ctx->dc_bios, &is_vbios_lttpr_enable); + dc->caps.vbios_lttpr_enable = (bp_query_result == BP_RESULT_OK) && !!is_vbios_lttpr_enable; + } + + /* interop bit is implicit */ + { + dc->caps.vbios_lttpr_aware = true; + } + } + + if (dc->ctx->dce_environment == DCE_ENV_PRODUCTION_DRV) + dc->debug = debug_defaults_drv; + else + dc->debug = debug_defaults_diags; + + /* Disable pipe power gating */ + dc->debug.disable_dpp_power_gate = true; + dc->debug.disable_hubp_power_gate = true; + + /* Disable root clock optimization */ + dc->debug.root_clock_optimization.u32All = 0; + + // Init the vm_helper + if (dc->vm_helper) + vm_helper_init(dc->vm_helper, 16); + + /************************************************* + * Create resources * + *************************************************/ + + /* Clock Sources for Pixel Clock*/ + pool->base.clock_sources[DCN31_CLK_SRC_PLL0] = + dcn30_clock_source_create(ctx, ctx->dc_bios, + CLOCK_SOURCE_COMBO_PHY_PLL0, + &clk_src_regs[0], false); + pool->base.clock_sources[DCN31_CLK_SRC_PLL1] = + dcn30_clock_source_create(ctx, ctx->dc_bios, + CLOCK_SOURCE_COMBO_PHY_PLL1, + &clk_src_regs[1], false); + pool->base.clock_sources[DCN31_CLK_SRC_PLL2] = + dcn30_clock_source_create(ctx, ctx->dc_bios, + CLOCK_SOURCE_COMBO_PHY_PLL2, + &clk_src_regs[2], false); + pool->base.clock_sources[DCN31_CLK_SRC_PLL3] = + dcn30_clock_source_create(ctx, ctx->dc_bios, + CLOCK_SOURCE_COMBO_PHY_PLL3, + &clk_src_regs[3], false); + pool->base.clock_sources[DCN31_CLK_SRC_PLL4] = + dcn30_clock_source_create(ctx, ctx->dc_bios, + CLOCK_SOURCE_COMBO_PHY_PLL4, + &clk_src_regs[4], false); + + pool->base.clk_src_count = DCN30_CLK_SRC_TOTAL; + + /* todo: not reuse phy_pll registers */ + pool->base.dp_clock_source = + dcn31_clock_source_create(ctx, ctx->dc_bios, + CLOCK_SOURCE_ID_DP_DTO, + &clk_src_regs[0], true); + + for (i = 0; i < pool->base.clk_src_count; i++) { + if (pool->base.clock_sources[i] == NULL) { + dm_error("DC: failed to create clock sources!\n"); + BREAK_TO_DEBUGGER(); + goto create_fail; + } + } + + pool->base.dccg = dccg314_create(ctx, &dccg_regs, &dccg_shift, &dccg_mask); + if (pool->base.dccg == NULL) { + dm_error("DC: failed to create dccg!\n"); + BREAK_TO_DEBUGGER(); + goto create_fail; + } + + init_data.ctx = dc->ctx; + pool->base.irqs = dal_irq_service_dcn314_create(&init_data); + if (!pool->base.irqs) + goto create_fail; + + /* HUBBUB */ + pool->base.hubbub = dcn31_hubbub_create(ctx); + if (pool->base.hubbub == NULL) { + BREAK_TO_DEBUGGER(); + dm_error("DC: failed to create hubbub!\n"); + goto create_fail; + } + + /* HUBPs, DPPs, OPPs and TGs */ + for (i = 0; i < pool->base.pipe_count; i++) { + pool->base.hubps[i] = dcn31_hubp_create(ctx, i); + if (pool->base.hubps[i] == NULL) { + BREAK_TO_DEBUGGER(); + dm_error( + "DC: failed to create hubps!\n"); + goto create_fail; + } + + pool->base.dpps[i] = dcn31_dpp_create(ctx, i); + if (pool->base.dpps[i] == NULL) { + BREAK_TO_DEBUGGER(); + dm_error( + "DC: failed to create dpps!\n"); + goto create_fail; + } + } + + for (i = 0; i < pool->base.res_cap->num_opp; i++) { + pool->base.opps[i] = dcn31_opp_create(ctx, i); + if (pool->base.opps[i] == NULL) { + BREAK_TO_DEBUGGER(); + dm_error( + "DC: failed to create output pixel processor!\n"); + goto create_fail; + } + } + + for (i = 0; i < pool->base.res_cap->num_timing_generator; i++) { + pool->base.timing_generators[i] = dcn31_timing_generator_create( + ctx, i); + if (pool->base.timing_generators[i] == NULL) { + BREAK_TO_DEBUGGER(); + dm_error("DC: failed to create tg!\n"); + goto create_fail; + } + } + pool->base.timing_generator_count = i; + + /* PSR */ + pool->base.psr = dmub_psr_create(ctx); + if (pool->base.psr == NULL) { + dm_error("DC: failed to create psr obj!\n"); + BREAK_TO_DEBUGGER(); + goto create_fail; + } + + /* Replay */ + pool->base.replay = dmub_replay_create(ctx); + if (pool->base.replay == NULL) { + dm_error("DC: failed to create replay obj!\n"); + BREAK_TO_DEBUGGER(); + goto create_fail; + } + + /* ABM */ + for (i = 0; i < pool->base.res_cap->num_timing_generator; i++) { + pool->base.multiple_abms[i] = dmub_abm_create(ctx, + &abm_regs[i], + &abm_shift, + &abm_mask); + if (pool->base.multiple_abms[i] == NULL) { + dm_error("DC: failed to create abm for pipe %d!\n", i); + BREAK_TO_DEBUGGER(); + goto create_fail; + } + } + + /* MPC and DSC */ + pool->base.mpc = dcn31_mpc_create(ctx, pool->base.mpcc_count, pool->base.res_cap->num_mpc_3dlut); + if (pool->base.mpc == NULL) { + BREAK_TO_DEBUGGER(); + dm_error("DC: failed to create mpc!\n"); + goto create_fail; + } + + for (i = 0; i < pool->base.res_cap->num_dsc; i++) { + pool->base.dscs[i] = dcn314_dsc_create(ctx, i); + if (pool->base.dscs[i] == NULL) { + BREAK_TO_DEBUGGER(); + dm_error("DC: failed to create display stream compressor %d!\n", i); + goto create_fail; + } + } + + /* DWB and MMHUBBUB */ + if (!dcn31_dwbc_create(ctx, &pool->base)) { + BREAK_TO_DEBUGGER(); + dm_error("DC: failed to create dwbc!\n"); + goto create_fail; + } + + if (!dcn31_mmhubbub_create(ctx, &pool->base)) { + BREAK_TO_DEBUGGER(); + dm_error("DC: failed to create mcif_wb!\n"); + goto create_fail; + } + + /* AUX and I2C */ + for (i = 0; i < pool->base.res_cap->num_ddc; i++) { + pool->base.engines[i] = dcn31_aux_engine_create(ctx, i); + if (pool->base.engines[i] == NULL) { + BREAK_TO_DEBUGGER(); + dm_error( + "DC:failed to create aux engine!!\n"); + goto create_fail; + } + pool->base.hw_i2cs[i] = dcn31_i2c_hw_create(ctx, i); + if (pool->base.hw_i2cs[i] == NULL) { + BREAK_TO_DEBUGGER(); + dm_error( + "DC:failed to create hw i2c!!\n"); + goto create_fail; + } + pool->base.sw_i2cs[i] = NULL; + } + + /* DCN314 has 4 DPIA */ + pool->base.usb4_dpia_count = 4; + + /* Audio, Stream Encoders including HPO and virtual, MPC 3D LUTs */ + if (!resource_construct(num_virtual_links, dc, &pool->base, + &res_create_funcs)) + goto create_fail; + + /* HW Sequencer and Plane caps */ + dcn314_hw_sequencer_construct(dc); + + dc->caps.max_planes = pool->base.pipe_count; + + for (i = 0; i < dc->caps.max_planes; ++i) + dc->caps.planes[i] = plane_cap; + + dc->cap_funcs = cap_funcs; + + dc->dcn_ip->max_num_dpp = dcn3_14_ip.max_num_dpp; + + return true; + +create_fail: + + dcn314_resource_destruct(pool); + + return false; +} + +struct resource_pool *dcn314_create_resource_pool( + const struct dc_init_data *init_data, + struct dc *dc) +{ + struct dcn314_resource_pool *pool = + kzalloc(sizeof(struct dcn314_resource_pool), GFP_KERNEL); + + if (!pool) + return NULL; + + if (dcn314_resource_construct(init_data->num_virtual_links, dc, pool)) + return &pool->base; + + BREAK_TO_DEBUGGER(); + kfree(pool); + return NULL; +} diff --git a/drivers/gpu/drm/amd/display/dc/resource/dcn314/dcn314_resource.h b/drivers/gpu/drm/amd/display/dc/resource/dcn314/dcn314_resource.h new file mode 100644 index 000000000000..49ffe71018df --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/resource/dcn314/dcn314_resource.h @@ -0,0 +1,50 @@ +/* SPDX-License-Identifier: MIT */ +/* + * Copyright 2022 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 _DCN314_RESOURCE_H_ +#define _DCN314_RESOURCE_H_ + +#include "core_types.h" + +extern struct _vcs_dpi_ip_params_st dcn3_14_ip; +extern struct _vcs_dpi_soc_bounding_box_st dcn3_14_soc; + +#define TO_DCN314_RES_POOL(pool)\ + container_of(pool, struct dcn314_resource_pool, base) + +struct dcn314_resource_pool { + struct resource_pool base; +}; + +bool dcn314_validate_bandwidth(struct dc *dc, + struct dc_state *context, + bool fast_validate); + +struct resource_pool *dcn314_create_resource_pool( + const struct dc_init_data *init_data, + struct dc *dc); + +#endif /* _DCN314_RESOURCE_H_ */ diff --git a/drivers/gpu/drm/amd/display/dc/resource/dcn315/dcn315_resource.c b/drivers/gpu/drm/amd/display/dc/resource/dcn315/dcn315_resource.c new file mode 100644 index 000000000000..cb8024eee8e4 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/resource/dcn315/dcn315_resource.c @@ -0,0 +1,2151 @@ +/* + * 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 "dm_services.h" +#include "dc.h" + +#include "dcn31/dcn31_init.h" + +#include "resource.h" +#include "include/irq_service_interface.h" +#include "dcn315_resource.h" + +#include "dcn20/dcn20_resource.h" +#include "dcn30/dcn30_resource.h" +#include "dcn31/dcn31_resource.h" + +#include "dcn10/dcn10_ipp.h" +#include "dcn30/dcn30_hubbub.h" +#include "dcn31/dcn31_hubbub.h" +#include "dcn30/dcn30_mpc.h" +#include "dcn31/dcn31_hubp.h" +#include "irq/dcn315/irq_service_dcn315.h" +#include "dcn30/dcn30_dpp.h" +#include "dcn31/dcn31_optc.h" +#include "dcn20/dcn20_hwseq.h" +#include "dcn30/dcn30_hwseq.h" +#include "dce110/dce110_hwseq.h" +#include "dcn30/dcn30_opp.h" +#include "dcn20/dcn20_dsc.h" +#include "dcn30/dcn30_vpg.h" +#include "dcn30/dcn30_afmt.h" +#include "dcn30/dcn30_dio_stream_encoder.h" +#include "dcn31/dcn31_hpo_dp_stream_encoder.h" +#include "dcn31/dcn31_hpo_dp_link_encoder.h" +#include "dcn31/dcn31_apg.h" +#include "dcn31/dcn31_dio_link_encoder.h" +#include "dcn31/dcn31_vpg.h" +#include "dcn31/dcn31_afmt.h" +#include "dce/dce_clock_source.h" +#include "dce/dce_audio.h" +#include "dce/dce_hwseq.h" +#include "clk_mgr.h" +#include "virtual/virtual_stream_encoder.h" +#include "dce110/dce110_resource.h" +#include "dml/display_mode_vba.h" +#include "dml/dcn31/dcn31_fpu.h" +#include "dcn31/dcn31_dccg.h" +#include "dcn10/dcn10_resource.h" +#include "dcn31/dcn31_panel_cntl.h" + +#include "dcn30/dcn30_dwb.h" +#include "dcn30/dcn30_mmhubbub.h" + +#include "dcn/dcn_3_1_5_offset.h" +#include "dcn/dcn_3_1_5_sh_mask.h" +#include "dpcs/dpcs_4_2_2_offset.h" +#include "dpcs/dpcs_4_2_2_sh_mask.h" + +#define NBIO_BASE__INST0_SEG0 0x00000000 +#define NBIO_BASE__INST0_SEG1 0x00000014 +#define NBIO_BASE__INST0_SEG2 0x00000D20 +#define NBIO_BASE__INST0_SEG3 0x00010400 +#define NBIO_BASE__INST0_SEG4 0x0241B000 +#define NBIO_BASE__INST0_SEG5 0x04040000 + +#define DPCS_BASE__INST0_SEG0 0x00000012 +#define DPCS_BASE__INST0_SEG1 0x000000C0 +#define DPCS_BASE__INST0_SEG2 0x000034C0 +#define DPCS_BASE__INST0_SEG3 0x00009000 +#define DPCS_BASE__INST0_SEG4 0x02403C00 +#define DPCS_BASE__INST0_SEG5 0 + +#define DCN_BASE__INST0_SEG0 0x00000012 +#define DCN_BASE__INST0_SEG1 0x000000C0 +#define DCN_BASE__INST0_SEG2 0x000034C0 +#define DCN_BASE__INST0_SEG3 0x00009000 +#define DCN_BASE__INST0_SEG4 0x02403C00 +#define DCN_BASE__INST0_SEG5 0 + +#define regBIF_BX_PF2_RSMU_INDEX 0x0000 +#define regBIF_BX_PF2_RSMU_INDEX_BASE_IDX 1 +#define regBIF_BX_PF2_RSMU_DATA 0x0001 +#define regBIF_BX_PF2_RSMU_DATA_BASE_IDX 1 +#define regBIF_BX2_BIOS_SCRATCH_6 0x003e +#define regBIF_BX2_BIOS_SCRATCH_6_BASE_IDX 1 +#define BIF_BX2_BIOS_SCRATCH_6__BIOS_SCRATCH_6__SHIFT 0x0 +#define BIF_BX2_BIOS_SCRATCH_6__BIOS_SCRATCH_6_MASK 0xFFFFFFFFL +#define regBIF_BX2_BIOS_SCRATCH_2 0x003a +#define regBIF_BX2_BIOS_SCRATCH_2_BASE_IDX 1 +#define BIF_BX2_BIOS_SCRATCH_2__BIOS_SCRATCH_2__SHIFT 0x0 +#define BIF_BX2_BIOS_SCRATCH_2__BIOS_SCRATCH_2_MASK 0xFFFFFFFFL +#define regBIF_BX2_BIOS_SCRATCH_3 0x003b +#define regBIF_BX2_BIOS_SCRATCH_3_BASE_IDX 1 +#define BIF_BX2_BIOS_SCRATCH_3__BIOS_SCRATCH_3__SHIFT 0x0 +#define BIF_BX2_BIOS_SCRATCH_3__BIOS_SCRATCH_3_MASK 0xFFFFFFFFL + +#define regDCHUBBUB_DEBUG_CTRL_0 0x04d6 +#define regDCHUBBUB_DEBUG_CTRL_0_BASE_IDX 2 +#define DCHUBBUB_DEBUG_CTRL_0__DET_DEPTH__SHIFT 0x10 +#define DCHUBBUB_DEBUG_CTRL_0__DET_DEPTH_MASK 0x01FF0000L + +#include "reg_helper.h" +#include "dce/dmub_abm.h" +#include "dce/dmub_psr.h" +#include "dce/dce_aux.h" +#include "dce/dce_i2c.h" + +#include "dml/dcn30/display_mode_vba_30.h" +#include "vm_helper.h" +#include "dcn20/dcn20_vmid.h" + +#include "link_enc_cfg.h" + +#define DCN3_15_MAX_DET_SIZE 384 +#define DCN3_15_CRB_SEGMENT_SIZE_KB 64 +#define DCN3_15_MAX_DET_SEGS (DCN3_15_MAX_DET_SIZE / DCN3_15_CRB_SEGMENT_SIZE_KB) +/* Minimum 3 extra segments need to be in compbuf and claimable to guarantee seamless mpo transitions */ +#define MIN_RESERVED_DET_SEGS 3 + +enum dcn31_clk_src_array_id { + DCN31_CLK_SRC_PLL0, + DCN31_CLK_SRC_PLL1, + DCN31_CLK_SRC_PLL2, + DCN31_CLK_SRC_PLL3, + DCN31_CLK_SRC_PLL4, + DCN30_CLK_SRC_TOTAL +}; + +/* begin ********************* + * macros to expend register list macro defined in HW object header file + */ + +/* DCN */ +#define BASE_INNER(seg) DCN_BASE__INST0_SEG ## seg + +#define BASE(seg) BASE_INNER(seg) + +#define SR(reg_name)\ + .reg_name = BASE(reg ## reg_name ## _BASE_IDX) + \ + reg ## reg_name + +#define SRI(reg_name, block, id)\ + .reg_name = BASE(reg ## block ## id ## _ ## reg_name ## _BASE_IDX) + \ + reg ## block ## id ## _ ## reg_name + +#define SRI2(reg_name, block, id)\ + .reg_name = BASE(reg ## reg_name ## _BASE_IDX) + \ + reg ## reg_name + +#define SRIR(var_name, reg_name, block, id)\ + .var_name = BASE(reg ## block ## id ## _ ## reg_name ## _BASE_IDX) + \ + reg ## block ## id ## _ ## reg_name + +#define SRII(reg_name, block, id)\ + .reg_name[id] = BASE(reg ## block ## id ## _ ## reg_name ## _BASE_IDX) + \ + reg ## block ## id ## _ ## reg_name + +#define SRII_MPC_RMU(reg_name, block, id)\ + .RMU##_##reg_name[id] = BASE(reg ## block ## id ## _ ## reg_name ## _BASE_IDX) + \ + reg ## block ## id ## _ ## reg_name + +#define SRII_DWB(reg_name, temp_name, block, id)\ + .reg_name[id] = BASE(reg ## block ## id ## _ ## temp_name ## _BASE_IDX) + \ + reg ## block ## id ## _ ## temp_name + +#define SF_DWB2(reg_name, block, id, field_name, post_fix) \ + .field_name = reg_name ## __ ## field_name ## post_fix + +#define DCCG_SRII(reg_name, block, id)\ + .block ## _ ## reg_name[id] = BASE(reg ## block ## id ## _ ## reg_name ## _BASE_IDX) + \ + reg ## block ## id ## _ ## reg_name + +#define VUPDATE_SRII(reg_name, block, id)\ + .reg_name[id] = BASE(reg ## reg_name ## _ ## block ## id ## _BASE_IDX) + \ + reg ## reg_name ## _ ## block ## id + +/* NBIO */ +#define NBIO_BASE_INNER(seg) \ + NBIO_BASE__INST0_SEG ## seg + +#define NBIO_BASE(seg) \ + NBIO_BASE_INNER(seg) + +#define NBIO_SR(reg_name)\ + .reg_name = NBIO_BASE(regBIF_BX2_ ## reg_name ## _BASE_IDX) + \ + regBIF_BX2_ ## reg_name + +static const struct bios_registers bios_regs = { + NBIO_SR(BIOS_SCRATCH_3), + NBIO_SR(BIOS_SCRATCH_6) +}; + +#define clk_src_regs(index, pllid)\ +[index] = {\ + CS_COMMON_REG_LIST_DCN3_0(index, pllid),\ +} + +static const struct dce110_clk_src_regs clk_src_regs[] = { + clk_src_regs(0, A), + clk_src_regs(1, B), + clk_src_regs(2, C), + clk_src_regs(3, D), + clk_src_regs(4, E) +}; + +static const struct dce110_clk_src_shift cs_shift = { + CS_COMMON_MASK_SH_LIST_DCN2_0(__SHIFT) +}; + +static const struct dce110_clk_src_mask cs_mask = { + CS_COMMON_MASK_SH_LIST_DCN2_0(_MASK) +}; + +#define abm_regs(id)\ +[id] = {\ + ABM_DCN302_REG_LIST(id)\ +} + +static const struct dce_abm_registers abm_regs[] = { + abm_regs(0), + abm_regs(1), + abm_regs(2), + abm_regs(3), +}; + +static const struct dce_abm_shift abm_shift = { + ABM_MASK_SH_LIST_DCN30(__SHIFT) +}; + +static const struct dce_abm_mask abm_mask = { + ABM_MASK_SH_LIST_DCN30(_MASK) +}; + +#define audio_regs(id)\ +[id] = {\ + AUD_COMMON_REG_LIST(id)\ +} + +static const struct dce_audio_registers audio_regs[] = { + audio_regs(0), + audio_regs(1), + audio_regs(2), + audio_regs(3), + audio_regs(4), + audio_regs(5), + audio_regs(6) +}; + +#define DCE120_AUD_COMMON_MASK_SH_LIST(mask_sh)\ + SF(AZF0ENDPOINT0_AZALIA_F0_CODEC_ENDPOINT_INDEX, AZALIA_ENDPOINT_REG_INDEX, mask_sh),\ + SF(AZF0ENDPOINT0_AZALIA_F0_CODEC_ENDPOINT_DATA, AZALIA_ENDPOINT_REG_DATA, mask_sh),\ + AUD_COMMON_MASK_SH_LIST_BASE(mask_sh) + +static const struct dce_audio_shift audio_shift = { + DCE120_AUD_COMMON_MASK_SH_LIST(__SHIFT) +}; + +static const struct dce_audio_mask audio_mask = { + DCE120_AUD_COMMON_MASK_SH_LIST(_MASK) +}; + +#define vpg_regs(id)\ +[id] = {\ + VPG_DCN31_REG_LIST(id)\ +} + +static const struct dcn31_vpg_registers vpg_regs[] = { + vpg_regs(0), + vpg_regs(1), + vpg_regs(2), + vpg_regs(3), + vpg_regs(4), + vpg_regs(5), + vpg_regs(6), + vpg_regs(7), + vpg_regs(8), + vpg_regs(9), +}; + +static const struct dcn31_vpg_shift vpg_shift = { + DCN31_VPG_MASK_SH_LIST(__SHIFT) +}; + +static const struct dcn31_vpg_mask vpg_mask = { + DCN31_VPG_MASK_SH_LIST(_MASK) +}; + +#define afmt_regs(id)\ +[id] = {\ + AFMT_DCN31_REG_LIST(id)\ +} + +static const struct dcn31_afmt_registers afmt_regs[] = { + afmt_regs(0), + afmt_regs(1), + afmt_regs(2), + afmt_regs(3), + afmt_regs(4), + afmt_regs(5) +}; + +static const struct dcn31_afmt_shift afmt_shift = { + DCN31_AFMT_MASK_SH_LIST(__SHIFT) +}; + +static const struct dcn31_afmt_mask afmt_mask = { + DCN31_AFMT_MASK_SH_LIST(_MASK) +}; + +#define apg_regs(id)\ +[id] = {\ + APG_DCN31_REG_LIST(id)\ +} + +static const struct dcn31_apg_registers apg_regs[] = { + apg_regs(0), + apg_regs(1), + apg_regs(2), + apg_regs(3) +}; + +static const struct dcn31_apg_shift apg_shift = { + DCN31_APG_MASK_SH_LIST(__SHIFT) +}; + +static const struct dcn31_apg_mask apg_mask = { + DCN31_APG_MASK_SH_LIST(_MASK) +}; + +#define stream_enc_regs(id)\ +[id] = {\ + SE_DCN3_REG_LIST(id)\ +} + +static const struct dcn10_stream_enc_registers stream_enc_regs[] = { + stream_enc_regs(0), + stream_enc_regs(1), + stream_enc_regs(2), + stream_enc_regs(3), + stream_enc_regs(4) +}; + +static const struct dcn10_stream_encoder_shift se_shift = { + SE_COMMON_MASK_SH_LIST_DCN30(__SHIFT) +}; + +static const struct dcn10_stream_encoder_mask se_mask = { + SE_COMMON_MASK_SH_LIST_DCN30(_MASK) +}; + + +#define aux_regs(id)\ +[id] = {\ + DCN2_AUX_REG_LIST(id)\ +} + +static const struct dcn10_link_enc_aux_registers link_enc_aux_regs[] = { + aux_regs(0), + aux_regs(1), + aux_regs(2), + aux_regs(3), + aux_regs(4) +}; + +#define hpd_regs(id)\ +[id] = {\ + HPD_REG_LIST(id)\ +} + +static const struct dcn10_link_enc_hpd_registers link_enc_hpd_regs[] = { + hpd_regs(0), + hpd_regs(1), + hpd_regs(2), + hpd_regs(3), + hpd_regs(4) +}; + +#define link_regs(id, phyid)\ +[id] = {\ + LE_DCN31_REG_LIST(id), \ + UNIPHY_DCN2_REG_LIST(phyid), \ + DPCS_DCN31_REG_LIST(id), \ +} + +static const struct dce110_aux_registers_shift aux_shift = { + DCN_AUX_MASK_SH_LIST(__SHIFT) +}; + +static const struct dce110_aux_registers_mask aux_mask = { + DCN_AUX_MASK_SH_LIST(_MASK) +}; + +static const struct dcn10_link_enc_registers link_enc_regs[] = { + link_regs(0, A), + link_regs(1, B), + link_regs(2, C), + link_regs(3, D), + link_regs(4, E) +}; + +static const struct dcn10_link_enc_shift le_shift = { + LINK_ENCODER_MASK_SH_LIST_DCN31(__SHIFT), \ + DPCS_DCN31_MASK_SH_LIST(__SHIFT) +}; + +static const struct dcn10_link_enc_mask le_mask = { + LINK_ENCODER_MASK_SH_LIST_DCN31(_MASK), \ + DPCS_DCN31_MASK_SH_LIST(_MASK) +}; + +#define hpo_dp_stream_encoder_reg_list(id)\ +[id] = {\ + DCN3_1_HPO_DP_STREAM_ENC_REG_LIST(id)\ +} + +static const struct dcn31_hpo_dp_stream_encoder_registers hpo_dp_stream_enc_regs[] = { + hpo_dp_stream_encoder_reg_list(0), + hpo_dp_stream_encoder_reg_list(1), + hpo_dp_stream_encoder_reg_list(2), + hpo_dp_stream_encoder_reg_list(3), +}; + +static const struct dcn31_hpo_dp_stream_encoder_shift hpo_dp_se_shift = { + DCN3_1_HPO_DP_STREAM_ENC_MASK_SH_LIST(__SHIFT) +}; + +static const struct dcn31_hpo_dp_stream_encoder_mask hpo_dp_se_mask = { + DCN3_1_HPO_DP_STREAM_ENC_MASK_SH_LIST(_MASK) +}; + + +#define hpo_dp_link_encoder_reg_list(id)\ +[id] = {\ + DCN3_1_HPO_DP_LINK_ENC_REG_LIST(id),\ + DCN3_1_RDPCSTX_REG_LIST(0),\ + DCN3_1_RDPCSTX_REG_LIST(1),\ + DCN3_1_RDPCSTX_REG_LIST(2),\ + DCN3_1_RDPCSTX_REG_LIST(3),\ + DCN3_1_RDPCSTX_REG_LIST(4)\ +} + +static const struct dcn31_hpo_dp_link_encoder_registers hpo_dp_link_enc_regs[] = { + hpo_dp_link_encoder_reg_list(0), + hpo_dp_link_encoder_reg_list(1), +}; + +static const struct dcn31_hpo_dp_link_encoder_shift hpo_dp_le_shift = { + DCN3_1_HPO_DP_LINK_ENC_MASK_SH_LIST(__SHIFT) +}; + +static const struct dcn31_hpo_dp_link_encoder_mask hpo_dp_le_mask = { + DCN3_1_HPO_DP_LINK_ENC_MASK_SH_LIST(_MASK) +}; + +#define dpp_regs(id)\ +[id] = {\ + DPP_REG_LIST_DCN30(id),\ +} + +static const struct dcn3_dpp_registers dpp_regs[] = { + dpp_regs(0), + dpp_regs(1), + dpp_regs(2), + dpp_regs(3) +}; + +static const struct dcn3_dpp_shift tf_shift = { + DPP_REG_LIST_SH_MASK_DCN30(__SHIFT) +}; + +static const struct dcn3_dpp_mask tf_mask = { + DPP_REG_LIST_SH_MASK_DCN30(_MASK) +}; + +#define opp_regs(id)\ +[id] = {\ + OPP_REG_LIST_DCN30(id),\ +} + +static const struct dcn20_opp_registers opp_regs[] = { + opp_regs(0), + opp_regs(1), + opp_regs(2), + opp_regs(3) +}; + +static const struct dcn20_opp_shift opp_shift = { + OPP_MASK_SH_LIST_DCN20(__SHIFT) +}; + +static const struct dcn20_opp_mask opp_mask = { + OPP_MASK_SH_LIST_DCN20(_MASK) +}; + +#define aux_engine_regs(id)\ +[id] = {\ + AUX_COMMON_REG_LIST0(id), \ + .AUXN_IMPCAL = 0, \ + .AUXP_IMPCAL = 0, \ + .AUX_RESET_MASK = DP_AUX0_AUX_CONTROL__AUX_RESET_MASK, \ +} + +static const struct dce110_aux_registers aux_engine_regs[] = { + aux_engine_regs(0), + aux_engine_regs(1), + aux_engine_regs(2), + aux_engine_regs(3), + aux_engine_regs(4) +}; + +#define dwbc_regs_dcn3(id)\ +[id] = {\ + DWBC_COMMON_REG_LIST_DCN30(id),\ +} + +static const struct dcn30_dwbc_registers dwbc30_regs[] = { + dwbc_regs_dcn3(0), +}; + +static const struct dcn30_dwbc_shift dwbc30_shift = { + DWBC_COMMON_MASK_SH_LIST_DCN30(__SHIFT) +}; + +static const struct dcn30_dwbc_mask dwbc30_mask = { + DWBC_COMMON_MASK_SH_LIST_DCN30(_MASK) +}; + +#define mcif_wb_regs_dcn3(id)\ +[id] = {\ + MCIF_WB_COMMON_REG_LIST_DCN30(id),\ +} + +static const struct dcn30_mmhubbub_registers mcif_wb30_regs[] = { + mcif_wb_regs_dcn3(0) +}; + +static const struct dcn30_mmhubbub_shift mcif_wb30_shift = { + MCIF_WB_COMMON_MASK_SH_LIST_DCN30(__SHIFT) +}; + +static const struct dcn30_mmhubbub_mask mcif_wb30_mask = { + MCIF_WB_COMMON_MASK_SH_LIST_DCN30(_MASK) +}; + +#define dsc_regsDCN20(id)\ +[id] = {\ + DSC_REG_LIST_DCN20(id)\ +} + +static const struct dcn20_dsc_registers dsc_regs[] = { + dsc_regsDCN20(0), + dsc_regsDCN20(1), + dsc_regsDCN20(2) +}; + +static const struct dcn20_dsc_shift dsc_shift = { + DSC_REG_LIST_SH_MASK_DCN20(__SHIFT) +}; + +static const struct dcn20_dsc_mask dsc_mask = { + DSC_REG_LIST_SH_MASK_DCN20(_MASK) +}; + +static const struct dcn30_mpc_registers mpc_regs = { + MPC_REG_LIST_DCN3_0(0), + MPC_REG_LIST_DCN3_0(1), + MPC_REG_LIST_DCN3_0(2), + MPC_REG_LIST_DCN3_0(3), + MPC_OUT_MUX_REG_LIST_DCN3_0(0), + MPC_OUT_MUX_REG_LIST_DCN3_0(1), + MPC_OUT_MUX_REG_LIST_DCN3_0(2), + MPC_OUT_MUX_REG_LIST_DCN3_0(3), + MPC_DWB_MUX_REG_LIST_DCN3_0(0), +}; + +static const struct dcn30_mpc_shift mpc_shift = { + MPC_COMMON_MASK_SH_LIST_DCN30(__SHIFT) +}; + +static const struct dcn30_mpc_mask mpc_mask = { + MPC_COMMON_MASK_SH_LIST_DCN30(_MASK) +}; + +#define optc_regs(id)\ +[id] = {OPTC_COMMON_REG_LIST_DCN3_1(id)} + +static const struct dcn_optc_registers optc_regs[] = { + optc_regs(0), + optc_regs(1), + optc_regs(2), + optc_regs(3) +}; + +static const struct dcn_optc_shift optc_shift = { + OPTC_COMMON_MASK_SH_LIST_DCN3_1(__SHIFT) +}; + +static const struct dcn_optc_mask optc_mask = { + OPTC_COMMON_MASK_SH_LIST_DCN3_1(_MASK) +}; + +#define hubp_regs(id)\ +[id] = {\ + HUBP_REG_LIST_DCN30(id)\ +} + +static const struct dcn_hubp2_registers hubp_regs[] = { + hubp_regs(0), + hubp_regs(1), + hubp_regs(2), + hubp_regs(3) +}; + + +static const struct dcn_hubp2_shift hubp_shift = { + HUBP_MASK_SH_LIST_DCN31(__SHIFT) +}; + +static const struct dcn_hubp2_mask hubp_mask = { + HUBP_MASK_SH_LIST_DCN31(_MASK) +}; +static const struct dcn_hubbub_registers hubbub_reg = { + HUBBUB_REG_LIST_DCN31(0) +}; + +static const struct dcn_hubbub_shift hubbub_shift = { + HUBBUB_MASK_SH_LIST_DCN31(__SHIFT) +}; + +static const struct dcn_hubbub_mask hubbub_mask = { + HUBBUB_MASK_SH_LIST_DCN31(_MASK) +}; + +static const struct dccg_registers dccg_regs = { + DCCG_REG_LIST_DCN31() +}; + +static const struct dccg_shift dccg_shift = { + DCCG_MASK_SH_LIST_DCN31(__SHIFT) +}; + +static const struct dccg_mask dccg_mask = { + DCCG_MASK_SH_LIST_DCN31(_MASK) +}; + + +#define SRII2(reg_name_pre, reg_name_post, id)\ + .reg_name_pre ## _ ## reg_name_post[id] = BASE(reg ## reg_name_pre \ + ## id ## _ ## reg_name_post ## _BASE_IDX) + \ + reg ## reg_name_pre ## id ## _ ## reg_name_post + + +#define HWSEQ_DCN31_REG_LIST()\ + SR(DCHUBBUB_GLOBAL_TIMER_CNTL), \ + SR(DCHUBBUB_ARB_HOSTVM_CNTL), \ + SR(DIO_MEM_PWR_CTRL), \ + SR(ODM_MEM_PWR_CTRL3), \ + SR(DMU_MEM_PWR_CNTL), \ + SR(MMHUBBUB_MEM_PWR_CNTL), \ + SR(DCCG_GATE_DISABLE_CNTL), \ + SR(DCCG_GATE_DISABLE_CNTL2), \ + SR(DCFCLK_CNTL),\ + SR(DC_MEM_GLOBAL_PWR_REQ_CNTL), \ + SRII(PIXEL_RATE_CNTL, OTG, 0), \ + SRII(PIXEL_RATE_CNTL, OTG, 1),\ + SRII(PIXEL_RATE_CNTL, OTG, 2),\ + SRII(PIXEL_RATE_CNTL, OTG, 3),\ + SRII(PHYPLL_PIXEL_RATE_CNTL, OTG, 0),\ + SRII(PHYPLL_PIXEL_RATE_CNTL, OTG, 1),\ + SRII(PHYPLL_PIXEL_RATE_CNTL, OTG, 2),\ + SRII(PHYPLL_PIXEL_RATE_CNTL, OTG, 3),\ + SR(MICROSECOND_TIME_BASE_DIV), \ + SR(MILLISECOND_TIME_BASE_DIV), \ + SR(DISPCLK_FREQ_CHANGE_CNTL), \ + SR(RBBMIF_TIMEOUT_DIS), \ + SR(RBBMIF_TIMEOUT_DIS_2), \ + SR(DCHUBBUB_CRC_CTRL), \ + SR(DPP_TOP0_DPP_CRC_CTRL), \ + SR(DPP_TOP0_DPP_CRC_VAL_B_A), \ + SR(DPP_TOP0_DPP_CRC_VAL_R_G), \ + SR(MPC_CRC_CTRL), \ + SR(MPC_CRC_RESULT_GB), \ + SR(MPC_CRC_RESULT_C), \ + SR(MPC_CRC_RESULT_AR), \ + SR(DOMAIN0_PG_CONFIG), \ + SR(DOMAIN1_PG_CONFIG), \ + SR(DOMAIN2_PG_CONFIG), \ + SR(DOMAIN3_PG_CONFIG), \ + SR(DOMAIN16_PG_CONFIG), \ + SR(DOMAIN17_PG_CONFIG), \ + SR(DOMAIN18_PG_CONFIG), \ + SR(DOMAIN0_PG_STATUS), \ + SR(DOMAIN1_PG_STATUS), \ + SR(DOMAIN2_PG_STATUS), \ + SR(DOMAIN3_PG_STATUS), \ + SR(DOMAIN16_PG_STATUS), \ + SR(DOMAIN17_PG_STATUS), \ + SR(DOMAIN18_PG_STATUS), \ + SR(D1VGA_CONTROL), \ + SR(D2VGA_CONTROL), \ + SR(D3VGA_CONTROL), \ + SR(D4VGA_CONTROL), \ + SR(D5VGA_CONTROL), \ + SR(D6VGA_CONTROL), \ + SR(DC_IP_REQUEST_CNTL), \ + SR(AZALIA_AUDIO_DTO), \ + SR(AZALIA_CONTROLLER_CLOCK_GATING), \ + SR(HPO_TOP_HW_CONTROL) + +static const struct dce_hwseq_registers hwseq_reg = { + HWSEQ_DCN31_REG_LIST() +}; + +#define HWSEQ_DCN31_MASK_SH_LIST(mask_sh)\ + HWSEQ_DCN_MASK_SH_LIST(mask_sh), \ + HWS_SF(, DCHUBBUB_GLOBAL_TIMER_CNTL, DCHUBBUB_GLOBAL_TIMER_REFDIV, mask_sh), \ + HWS_SF(, DCHUBBUB_ARB_HOSTVM_CNTL, DISABLE_HOSTVM_FORCE_ALLOW_PSTATE, mask_sh), \ + HWS_SF(, DOMAIN0_PG_CONFIG, DOMAIN_POWER_FORCEON, mask_sh), \ + HWS_SF(, DOMAIN0_PG_CONFIG, DOMAIN_POWER_GATE, mask_sh), \ + HWS_SF(, DOMAIN1_PG_CONFIG, DOMAIN_POWER_FORCEON, mask_sh), \ + HWS_SF(, DOMAIN1_PG_CONFIG, DOMAIN_POWER_GATE, mask_sh), \ + HWS_SF(, DOMAIN2_PG_CONFIG, DOMAIN_POWER_FORCEON, mask_sh), \ + HWS_SF(, DOMAIN2_PG_CONFIG, DOMAIN_POWER_GATE, mask_sh), \ + HWS_SF(, DOMAIN3_PG_CONFIG, DOMAIN_POWER_FORCEON, mask_sh), \ + HWS_SF(, DOMAIN3_PG_CONFIG, DOMAIN_POWER_GATE, mask_sh), \ + HWS_SF(, DOMAIN16_PG_CONFIG, DOMAIN_POWER_FORCEON, mask_sh), \ + HWS_SF(, DOMAIN16_PG_CONFIG, DOMAIN_POWER_GATE, mask_sh), \ + HWS_SF(, DOMAIN17_PG_CONFIG, DOMAIN_POWER_FORCEON, mask_sh), \ + HWS_SF(, DOMAIN17_PG_CONFIG, DOMAIN_POWER_GATE, mask_sh), \ + HWS_SF(, DOMAIN18_PG_CONFIG, DOMAIN_POWER_FORCEON, mask_sh), \ + HWS_SF(, DOMAIN18_PG_CONFIG, DOMAIN_POWER_GATE, mask_sh), \ + HWS_SF(, DOMAIN0_PG_STATUS, DOMAIN_PGFSM_PWR_STATUS, mask_sh), \ + HWS_SF(, DOMAIN1_PG_STATUS, DOMAIN_PGFSM_PWR_STATUS, mask_sh), \ + HWS_SF(, DOMAIN2_PG_STATUS, DOMAIN_PGFSM_PWR_STATUS, mask_sh), \ + HWS_SF(, DOMAIN3_PG_STATUS, DOMAIN_PGFSM_PWR_STATUS, mask_sh), \ + HWS_SF(, DOMAIN16_PG_STATUS, DOMAIN_PGFSM_PWR_STATUS, mask_sh), \ + HWS_SF(, DOMAIN17_PG_STATUS, DOMAIN_PGFSM_PWR_STATUS, mask_sh), \ + HWS_SF(, DOMAIN18_PG_STATUS, DOMAIN_PGFSM_PWR_STATUS, mask_sh), \ + HWS_SF(, DC_IP_REQUEST_CNTL, IP_REQUEST_EN, mask_sh), \ + HWS_SF(, AZALIA_AUDIO_DTO, AZALIA_AUDIO_DTO_MODULE, mask_sh), \ + HWS_SF(, HPO_TOP_CLOCK_CONTROL, HPO_HDMISTREAMCLK_G_GATE_DIS, mask_sh), \ + HWS_SF(, DMU_MEM_PWR_CNTL, DMCU_ERAM_MEM_PWR_FORCE, mask_sh), \ + HWS_SF(, ODM_MEM_PWR_CTRL3, ODM_MEM_UNASSIGNED_PWR_MODE, mask_sh), \ + HWS_SF(, ODM_MEM_PWR_CTRL3, ODM_MEM_VBLANK_PWR_MODE, mask_sh), \ + HWS_SF(, MMHUBBUB_MEM_PWR_CNTL, VGA_MEM_PWR_FORCE, mask_sh), \ + HWS_SF(, DIO_MEM_PWR_CTRL, I2C_LIGHT_SLEEP_FORCE, mask_sh), \ + HWS_SF(, HPO_TOP_HW_CONTROL, HPO_IO_EN, mask_sh) + +static const struct dce_hwseq_shift hwseq_shift = { + HWSEQ_DCN31_MASK_SH_LIST(__SHIFT) +}; + +static const struct dce_hwseq_mask hwseq_mask = { + HWSEQ_DCN31_MASK_SH_LIST(_MASK) +}; +#define vmid_regs(id)\ +[id] = {\ + DCN20_VMID_REG_LIST(id)\ +} + +static const struct dcn_vmid_registers vmid_regs[] = { + vmid_regs(0), + vmid_regs(1), + vmid_regs(2), + vmid_regs(3), + vmid_regs(4), + vmid_regs(5), + vmid_regs(6), + vmid_regs(7), + vmid_regs(8), + vmid_regs(9), + vmid_regs(10), + vmid_regs(11), + vmid_regs(12), + vmid_regs(13), + vmid_regs(14), + vmid_regs(15) +}; + +static const struct dcn20_vmid_shift vmid_shifts = { + DCN20_VMID_MASK_SH_LIST(__SHIFT) +}; + +static const struct dcn20_vmid_mask vmid_masks = { + DCN20_VMID_MASK_SH_LIST(_MASK) +}; + +static const struct resource_caps res_cap_dcn31 = { + .num_timing_generator = 4, + .num_opp = 4, + .num_video_plane = 4, + .num_audio = 5, + .num_stream_encoder = 5, + .num_dig_link_enc = 5, + .num_hpo_dp_stream_encoder = 4, + .num_hpo_dp_link_encoder = 2, + .num_pll = 5, + .num_dwb = 1, + .num_ddc = 5, + .num_vmid = 16, + .num_mpc_3dlut = 2, + .num_dsc = 3, +}; + +static const struct dc_plane_cap plane_cap = { + .type = DC_PLANE_TYPE_DCN_UNIVERSAL, + .per_pixel_alpha = true, + + .pixel_format_support = { + .argb8888 = true, + .nv12 = true, + .fp16 = true, + .p010 = true, + .ayuv = false, + }, + + .max_upscale_factor = { + .argb8888 = 16000, + .nv12 = 16000, + .fp16 = 16000 + }, + + // 6:1 downscaling ratio: 1000/6 = 166.666 + .max_downscale_factor = { + .argb8888 = 167, + .nv12 = 167, + .fp16 = 167 + }, + 64, + 64 +}; + +static const struct dc_debug_options debug_defaults_drv = { + .disable_z10 = true, /*hw not support it*/ + .disable_dmcu = true, + .force_abm_enable = false, + .timing_trace = false, + .clock_trace = true, + .disable_pplib_clock_request = false, + .pipe_split_policy = MPC_SPLIT_DYNAMIC, + .force_single_disp_pipe_split = false, + .disable_dcc = DCC_ENABLE, + .vsr_support = true, + .performance_trace = false, + .max_downscale_src_width = 4096,/*upto true 4k*/ + .disable_pplib_wm_range = false, + .scl_reset_length10 = true, + .sanity_checks = false, + .underflow_assert_delay_us = 0xFFFFFFFF, + .dwb_fi_phase = -1, // -1 = disable, + .dmub_command_table = true, + .pstate_enabled = true, + .use_max_lb = true, + .enable_mem_low_power = { + .bits = { + .vga = true, + .i2c = true, + .dmcu = false, // This is previously known to cause hang on S3 cycles if enabled + .dscl = true, + .cm = true, + .mpc = true, + .optc = true, + .vpg = true, + .afmt = true, + } + }, + .enable_legacy_fast_update = true, + .psr_power_use_phy_fsm = 0, + .using_dml2 = false, +}; + +static const struct dc_panel_config panel_config_defaults = { + .psr = { + .disable_psr = false, + .disallow_psrsu = false, + .disallow_replay = false, + }, + .ilr = { + .optimize_edp_link_rate = true, + }, +}; + +static void dcn31_dpp_destroy(struct dpp **dpp) +{ + kfree(TO_DCN20_DPP(*dpp)); + *dpp = NULL; +} + +static struct dpp *dcn31_dpp_create( + struct dc_context *ctx, + uint32_t inst) +{ + struct dcn3_dpp *dpp = + kzalloc(sizeof(struct dcn3_dpp), GFP_KERNEL); + + if (!dpp) + return NULL; + + if (dpp3_construct(dpp, ctx, inst, + &dpp_regs[inst], &tf_shift, &tf_mask)) + return &dpp->base; + + BREAK_TO_DEBUGGER(); + kfree(dpp); + return NULL; +} + +static struct output_pixel_processor *dcn31_opp_create( + struct dc_context *ctx, uint32_t inst) +{ + struct dcn20_opp *opp = + kzalloc(sizeof(struct dcn20_opp), GFP_KERNEL); + + if (!opp) { + BREAK_TO_DEBUGGER(); + return NULL; + } + + dcn20_opp_construct(opp, ctx, inst, + &opp_regs[inst], &opp_shift, &opp_mask); + return &opp->base; +} + +static struct dce_aux *dcn31_aux_engine_create( + struct dc_context *ctx, + uint32_t inst) +{ + struct aux_engine_dce110 *aux_engine = + kzalloc(sizeof(struct aux_engine_dce110), GFP_KERNEL); + + if (!aux_engine) + return NULL; + + dce110_aux_engine_construct(aux_engine, ctx, inst, + SW_AUX_TIMEOUT_PERIOD_MULTIPLIER * AUX_TIMEOUT_PERIOD, + &aux_engine_regs[inst], + &aux_mask, + &aux_shift, + ctx->dc->caps.extended_aux_timeout_support); + + return &aux_engine->base; +} +#define i2c_inst_regs(id) { I2C_HW_ENGINE_COMMON_REG_LIST_DCN30(id) } + +static const struct dce_i2c_registers i2c_hw_regs[] = { + i2c_inst_regs(1), + i2c_inst_regs(2), + i2c_inst_regs(3), + i2c_inst_regs(4), + i2c_inst_regs(5), +}; + +static const struct dce_i2c_shift i2c_shifts = { + I2C_COMMON_MASK_SH_LIST_DCN30(__SHIFT) +}; + +static const struct dce_i2c_mask i2c_masks = { + I2C_COMMON_MASK_SH_LIST_DCN30(_MASK) +}; + +static struct dce_i2c_hw *dcn31_i2c_hw_create( + struct dc_context *ctx, + uint32_t inst) +{ + struct dce_i2c_hw *dce_i2c_hw = + kzalloc(sizeof(struct dce_i2c_hw), GFP_KERNEL); + + if (!dce_i2c_hw) + return NULL; + + dcn2_i2c_hw_construct(dce_i2c_hw, ctx, inst, + &i2c_hw_regs[inst], &i2c_shifts, &i2c_masks); + + return dce_i2c_hw; +} +static struct mpc *dcn31_mpc_create( + struct dc_context *ctx, + int num_mpcc, + int num_rmu) +{ + struct dcn30_mpc *mpc30 = kzalloc(sizeof(struct dcn30_mpc), + GFP_KERNEL); + + if (!mpc30) + return NULL; + + dcn30_mpc_construct(mpc30, ctx, + &mpc_regs, + &mpc_shift, + &mpc_mask, + num_mpcc, + num_rmu); + + return &mpc30->base; +} + +static struct hubbub *dcn31_hubbub_create(struct dc_context *ctx) +{ + int i; + + struct dcn20_hubbub *hubbub3 = kzalloc(sizeof(struct dcn20_hubbub), + GFP_KERNEL); + + if (!hubbub3) + return NULL; + + hubbub31_construct(hubbub3, ctx, + &hubbub_reg, + &hubbub_shift, + &hubbub_mask, + dcn3_15_ip.det_buffer_size_kbytes, + dcn3_15_ip.pixel_chunk_size_kbytes, + dcn3_15_ip.config_return_buffer_size_in_kbytes); + + + for (i = 0; i < res_cap_dcn31.num_vmid; i++) { + struct dcn20_vmid *vmid = &hubbub3->vmid[i]; + + vmid->ctx = ctx; + + vmid->regs = &vmid_regs[i]; + vmid->shifts = &vmid_shifts; + vmid->masks = &vmid_masks; + } + + return &hubbub3->base; +} + +static struct timing_generator *dcn31_timing_generator_create( + struct dc_context *ctx, + uint32_t instance) +{ + struct optc *tgn10 = + kzalloc(sizeof(struct optc), GFP_KERNEL); + + if (!tgn10) + return NULL; + + tgn10->base.inst = instance; + tgn10->base.ctx = ctx; + + tgn10->tg_regs = &optc_regs[instance]; + tgn10->tg_shift = &optc_shift; + tgn10->tg_mask = &optc_mask; + + dcn31_timing_generator_init(tgn10); + + return &tgn10->base; +} + +static const struct encoder_feature_support link_enc_feature = { + .max_hdmi_deep_color = COLOR_DEPTH_121212, + .max_hdmi_pixel_clock = 600000, + .hdmi_ycbcr420_supported = true, + .dp_ycbcr420_supported = true, + .fec_supported = true, + .flags.bits.IS_HBR2_CAPABLE = true, + .flags.bits.IS_HBR3_CAPABLE = true, + .flags.bits.IS_TPS3_CAPABLE = true, + .flags.bits.IS_TPS4_CAPABLE = true +}; + +static struct link_encoder *dcn31_link_encoder_create( + struct dc_context *ctx, + const struct encoder_init_data *enc_init_data) +{ + struct dcn20_link_encoder *enc20 = + kzalloc(sizeof(struct dcn20_link_encoder), GFP_KERNEL); + + if (!enc20) + return NULL; + + dcn31_link_encoder_construct(enc20, + enc_init_data, + &link_enc_feature, + &link_enc_regs[enc_init_data->transmitter], + &link_enc_aux_regs[enc_init_data->channel - 1], + &link_enc_hpd_regs[enc_init_data->hpd_source], + &le_shift, + &le_mask); + + return &enc20->enc10.base; +} + +/* Create a minimal link encoder object not associated with a particular + * physical connector. + * resource_funcs.link_enc_create_minimal + */ +static struct link_encoder *dcn31_link_enc_create_minimal( + struct dc_context *ctx, enum engine_id eng_id) +{ + struct dcn20_link_encoder *enc20; + + if ((eng_id - ENGINE_ID_DIGA) > ctx->dc->res_pool->res_cap->num_dig_link_enc) + return NULL; + + enc20 = kzalloc(sizeof(struct dcn20_link_encoder), GFP_KERNEL); + if (!enc20) + return NULL; + + dcn31_link_encoder_construct_minimal( + enc20, + ctx, + &link_enc_feature, + &link_enc_regs[eng_id - ENGINE_ID_DIGA], + eng_id); + + return &enc20->enc10.base; +} + +static struct panel_cntl *dcn31_panel_cntl_create(const struct panel_cntl_init_data *init_data) +{ + struct dcn31_panel_cntl *panel_cntl = + kzalloc(sizeof(struct dcn31_panel_cntl), GFP_KERNEL); + + if (!panel_cntl) + return NULL; + + dcn31_panel_cntl_construct(panel_cntl, init_data); + + return &panel_cntl->base; +} + +static void read_dce_straps( + struct dc_context *ctx, + struct resource_straps *straps) +{ + generic_reg_get(ctx, regDC_PINSTRAPS + BASE(regDC_PINSTRAPS_BASE_IDX), + FN(DC_PINSTRAPS, DC_PINSTRAPS_AUDIO), &straps->dc_pinstraps_audio); + +} + +static struct audio *dcn31_create_audio( + struct dc_context *ctx, unsigned int inst) +{ + return dce_audio_create(ctx, inst, + &audio_regs[inst], &audio_shift, &audio_mask); +} + +static struct vpg *dcn31_vpg_create( + struct dc_context *ctx, + uint32_t inst) +{ + struct dcn31_vpg *vpg31 = kzalloc(sizeof(struct dcn31_vpg), GFP_KERNEL); + + if (!vpg31) + return NULL; + + vpg31_construct(vpg31, ctx, inst, + &vpg_regs[inst], + &vpg_shift, + &vpg_mask); + + return &vpg31->base; +} + +static struct afmt *dcn31_afmt_create( + struct dc_context *ctx, + uint32_t inst) +{ + struct dcn31_afmt *afmt31 = kzalloc(sizeof(struct dcn31_afmt), GFP_KERNEL); + + if (!afmt31) + return NULL; + + afmt31_construct(afmt31, ctx, inst, + &afmt_regs[inst], + &afmt_shift, + &afmt_mask); + + // Light sleep by default, no need to power down here + + return &afmt31->base; +} + +static struct apg *dcn31_apg_create( + struct dc_context *ctx, + uint32_t inst) +{ + struct dcn31_apg *apg31 = kzalloc(sizeof(struct dcn31_apg), GFP_KERNEL); + + if (!apg31) + return NULL; + + apg31_construct(apg31, ctx, inst, + &apg_regs[inst], + &apg_shift, + &apg_mask); + + return &apg31->base; +} + +static struct stream_encoder *dcn315_stream_encoder_create( + enum engine_id eng_id, + struct dc_context *ctx) +{ + struct dcn10_stream_encoder *enc1; + struct vpg *vpg; + struct afmt *afmt; + int vpg_inst; + int afmt_inst; + + /*PHYB is wired off in HW, allow front end to remapping, otherwise needs more changes*/ + + /* Mapping of VPG, AFMT, DME register blocks to DIO block instance */ + if (eng_id <= ENGINE_ID_DIGF) { + vpg_inst = eng_id; + afmt_inst = eng_id; + } else + return NULL; + + enc1 = kzalloc(sizeof(struct dcn10_stream_encoder), GFP_KERNEL); + vpg = dcn31_vpg_create(ctx, vpg_inst); + afmt = dcn31_afmt_create(ctx, afmt_inst); + + if (!enc1 || !vpg || !afmt) { + kfree(enc1); + kfree(vpg); + kfree(afmt); + return NULL; + } + + dcn30_dio_stream_encoder_construct(enc1, ctx, ctx->dc_bios, + eng_id, vpg, afmt, + &stream_enc_regs[eng_id], + &se_shift, &se_mask); + + return &enc1->base; +} + +static struct hpo_dp_stream_encoder *dcn31_hpo_dp_stream_encoder_create( + enum engine_id eng_id, + struct dc_context *ctx) +{ + struct dcn31_hpo_dp_stream_encoder *hpo_dp_enc31; + struct vpg *vpg; + struct apg *apg; + uint32_t hpo_dp_inst; + uint32_t vpg_inst; + uint32_t apg_inst; + + ASSERT((eng_id >= ENGINE_ID_HPO_DP_0) && (eng_id <= ENGINE_ID_HPO_DP_3)); + hpo_dp_inst = eng_id - ENGINE_ID_HPO_DP_0; + + /* Mapping of VPG register blocks to HPO DP block instance: + * VPG[6] -> HPO_DP[0] + * VPG[7] -> HPO_DP[1] + * VPG[8] -> HPO_DP[2] + * VPG[9] -> HPO_DP[3] + */ + vpg_inst = hpo_dp_inst + 6; + + /* Mapping of APG register blocks to HPO DP block instance: + * APG[0] -> HPO_DP[0] + * APG[1] -> HPO_DP[1] + * APG[2] -> HPO_DP[2] + * APG[3] -> HPO_DP[3] + */ + apg_inst = hpo_dp_inst; + + /* allocate HPO stream encoder and create VPG sub-block */ + hpo_dp_enc31 = kzalloc(sizeof(struct dcn31_hpo_dp_stream_encoder), GFP_KERNEL); + vpg = dcn31_vpg_create(ctx, vpg_inst); + apg = dcn31_apg_create(ctx, apg_inst); + + if (!hpo_dp_enc31 || !vpg || !apg) { + kfree(hpo_dp_enc31); + kfree(vpg); + kfree(apg); + return NULL; + } + + dcn31_hpo_dp_stream_encoder_construct(hpo_dp_enc31, ctx, ctx->dc_bios, + hpo_dp_inst, eng_id, vpg, apg, + &hpo_dp_stream_enc_regs[hpo_dp_inst], + &hpo_dp_se_shift, &hpo_dp_se_mask); + + return &hpo_dp_enc31->base; +} + +static struct hpo_dp_link_encoder *dcn31_hpo_dp_link_encoder_create( + uint8_t inst, + struct dc_context *ctx) +{ + struct dcn31_hpo_dp_link_encoder *hpo_dp_enc31; + + /* allocate HPO link encoder */ + hpo_dp_enc31 = kzalloc(sizeof(struct dcn31_hpo_dp_link_encoder), GFP_KERNEL); + + hpo_dp_link_encoder31_construct(hpo_dp_enc31, ctx, inst, + &hpo_dp_link_enc_regs[inst], + &hpo_dp_le_shift, &hpo_dp_le_mask); + + return &hpo_dp_enc31->base; +} + +static struct dce_hwseq *dcn31_hwseq_create( + struct dc_context *ctx) +{ + struct dce_hwseq *hws = kzalloc(sizeof(struct dce_hwseq), GFP_KERNEL); + + if (hws) { + hws->ctx = ctx; + hws->regs = &hwseq_reg; + hws->shifts = &hwseq_shift; + hws->masks = &hwseq_mask; + } + return hws; +} +static const struct resource_create_funcs res_create_funcs = { + .read_dce_straps = read_dce_straps, + .create_audio = dcn31_create_audio, + .create_stream_encoder = dcn315_stream_encoder_create, + .create_hpo_dp_stream_encoder = dcn31_hpo_dp_stream_encoder_create, + .create_hpo_dp_link_encoder = dcn31_hpo_dp_link_encoder_create, + .create_hwseq = dcn31_hwseq_create, +}; + +static void dcn315_resource_destruct(struct dcn315_resource_pool *pool) +{ + unsigned int i; + + for (i = 0; i < pool->base.stream_enc_count; i++) { + if (pool->base.stream_enc[i] != NULL) { + if (pool->base.stream_enc[i]->vpg != NULL) { + kfree(DCN30_VPG_FROM_VPG(pool->base.stream_enc[i]->vpg)); + pool->base.stream_enc[i]->vpg = NULL; + } + if (pool->base.stream_enc[i]->afmt != NULL) { + kfree(DCN30_AFMT_FROM_AFMT(pool->base.stream_enc[i]->afmt)); + pool->base.stream_enc[i]->afmt = NULL; + } + kfree(DCN10STRENC_FROM_STRENC(pool->base.stream_enc[i])); + pool->base.stream_enc[i] = NULL; + } + } + + for (i = 0; i < pool->base.hpo_dp_stream_enc_count; i++) { + if (pool->base.hpo_dp_stream_enc[i] != NULL) { + if (pool->base.hpo_dp_stream_enc[i]->vpg != NULL) { + kfree(DCN30_VPG_FROM_VPG(pool->base.hpo_dp_stream_enc[i]->vpg)); + pool->base.hpo_dp_stream_enc[i]->vpg = NULL; + } + if (pool->base.hpo_dp_stream_enc[i]->apg != NULL) { + kfree(DCN31_APG_FROM_APG(pool->base.hpo_dp_stream_enc[i]->apg)); + pool->base.hpo_dp_stream_enc[i]->apg = NULL; + } + kfree(DCN3_1_HPO_DP_STREAM_ENC_FROM_HPO_STREAM_ENC(pool->base.hpo_dp_stream_enc[i])); + pool->base.hpo_dp_stream_enc[i] = NULL; + } + } + + for (i = 0; i < pool->base.hpo_dp_link_enc_count; i++) { + if (pool->base.hpo_dp_link_enc[i] != NULL) { + kfree(DCN3_1_HPO_DP_LINK_ENC_FROM_HPO_LINK_ENC(pool->base.hpo_dp_link_enc[i])); + pool->base.hpo_dp_link_enc[i] = NULL; + } + } + + for (i = 0; i < pool->base.res_cap->num_dsc; i++) { + if (pool->base.dscs[i] != NULL) + dcn20_dsc_destroy(&pool->base.dscs[i]); + } + + if (pool->base.mpc != NULL) { + kfree(TO_DCN20_MPC(pool->base.mpc)); + pool->base.mpc = NULL; + } + if (pool->base.hubbub != NULL) { + kfree(pool->base.hubbub); + pool->base.hubbub = NULL; + } + for (i = 0; i < pool->base.pipe_count; i++) { + if (pool->base.dpps[i] != NULL) + dcn31_dpp_destroy(&pool->base.dpps[i]); + + if (pool->base.ipps[i] != NULL) + pool->base.ipps[i]->funcs->ipp_destroy(&pool->base.ipps[i]); + + if (pool->base.hubps[i] != NULL) { + kfree(TO_DCN20_HUBP(pool->base.hubps[i])); + pool->base.hubps[i] = NULL; + } + + if (pool->base.irqs != NULL) { + dal_irq_service_destroy(&pool->base.irqs); + } + } + + for (i = 0; i < pool->base.res_cap->num_ddc; i++) { + if (pool->base.engines[i] != NULL) + dce110_engine_destroy(&pool->base.engines[i]); + if (pool->base.hw_i2cs[i] != NULL) { + kfree(pool->base.hw_i2cs[i]); + pool->base.hw_i2cs[i] = NULL; + } + if (pool->base.sw_i2cs[i] != NULL) { + kfree(pool->base.sw_i2cs[i]); + pool->base.sw_i2cs[i] = NULL; + } + } + + for (i = 0; i < pool->base.res_cap->num_opp; i++) { + if (pool->base.opps[i] != NULL) + pool->base.opps[i]->funcs->opp_destroy(&pool->base.opps[i]); + } + + for (i = 0; i < pool->base.res_cap->num_timing_generator; i++) { + if (pool->base.timing_generators[i] != NULL) { + kfree(DCN10TG_FROM_TG(pool->base.timing_generators[i])); + pool->base.timing_generators[i] = NULL; + } + } + + for (i = 0; i < pool->base.res_cap->num_dwb; i++) { + if (pool->base.dwbc[i] != NULL) { + kfree(TO_DCN30_DWBC(pool->base.dwbc[i])); + pool->base.dwbc[i] = NULL; + } + if (pool->base.mcif_wb[i] != NULL) { + kfree(TO_DCN30_MMHUBBUB(pool->base.mcif_wb[i])); + pool->base.mcif_wb[i] = NULL; + } + } + + for (i = 0; i < pool->base.audio_count; i++) { + if (pool->base.audios[i]) + dce_aud_destroy(&pool->base.audios[i]); + } + + for (i = 0; i < pool->base.clk_src_count; i++) { + if (pool->base.clock_sources[i] != NULL) { + dcn20_clock_source_destroy(&pool->base.clock_sources[i]); + pool->base.clock_sources[i] = NULL; + } + } + + for (i = 0; i < pool->base.res_cap->num_mpc_3dlut; i++) { + if (pool->base.mpc_lut[i] != NULL) { + dc_3dlut_func_release(pool->base.mpc_lut[i]); + pool->base.mpc_lut[i] = NULL; + } + if (pool->base.mpc_shaper[i] != NULL) { + dc_transfer_func_release(pool->base.mpc_shaper[i]); + pool->base.mpc_shaper[i] = NULL; + } + } + + if (pool->base.dp_clock_source != NULL) { + dcn20_clock_source_destroy(&pool->base.dp_clock_source); + pool->base.dp_clock_source = NULL; + } + + for (i = 0; i < pool->base.res_cap->num_timing_generator; i++) { + if (pool->base.multiple_abms[i] != NULL) + dce_abm_destroy(&pool->base.multiple_abms[i]); + } + + if (pool->base.psr != NULL) + dmub_psr_destroy(&pool->base.psr); + + if (pool->base.dccg != NULL) + dcn_dccg_destroy(&pool->base.dccg); +} + +static struct hubp *dcn31_hubp_create( + struct dc_context *ctx, + uint32_t inst) +{ + struct dcn20_hubp *hubp2 = + kzalloc(sizeof(struct dcn20_hubp), GFP_KERNEL); + + if (!hubp2) + return NULL; + + if (hubp31_construct(hubp2, ctx, inst, + &hubp_regs[inst], &hubp_shift, &hubp_mask)) + return &hubp2->base; + + BREAK_TO_DEBUGGER(); + kfree(hubp2); + return NULL; +} + +static bool dcn31_dwbc_create(struct dc_context *ctx, struct resource_pool *pool) +{ + int i; + uint32_t pipe_count = pool->res_cap->num_dwb; + + for (i = 0; i < pipe_count; i++) { + struct dcn30_dwbc *dwbc30 = kzalloc(sizeof(struct dcn30_dwbc), + GFP_KERNEL); + + if (!dwbc30) { + dm_error("DC: failed to create dwbc30!\n"); + return false; + } + + dcn30_dwbc_construct(dwbc30, ctx, + &dwbc30_regs[i], + &dwbc30_shift, + &dwbc30_mask, + i); + + pool->dwbc[i] = &dwbc30->base; + } + return true; +} + +static bool dcn31_mmhubbub_create(struct dc_context *ctx, struct resource_pool *pool) +{ + int i; + uint32_t pipe_count = pool->res_cap->num_dwb; + + for (i = 0; i < pipe_count; i++) { + struct dcn30_mmhubbub *mcif_wb30 = kzalloc(sizeof(struct dcn30_mmhubbub), + GFP_KERNEL); + + if (!mcif_wb30) { + dm_error("DC: failed to create mcif_wb30!\n"); + return false; + } + + dcn30_mmhubbub_construct(mcif_wb30, ctx, + &mcif_wb30_regs[i], + &mcif_wb30_shift, + &mcif_wb30_mask, + i); + + pool->mcif_wb[i] = &mcif_wb30->base; + } + return true; +} + +static struct display_stream_compressor *dcn31_dsc_create( + struct dc_context *ctx, uint32_t inst) +{ + struct dcn20_dsc *dsc = + kzalloc(sizeof(struct dcn20_dsc), GFP_KERNEL); + + if (!dsc) { + BREAK_TO_DEBUGGER(); + return NULL; + } + + dsc2_construct(dsc, ctx, inst, &dsc_regs[inst], &dsc_shift, &dsc_mask); + return &dsc->base; +} + +static void dcn315_destroy_resource_pool(struct resource_pool **pool) +{ + struct dcn315_resource_pool *dcn31_pool = TO_DCN315_RES_POOL(*pool); + + dcn315_resource_destruct(dcn31_pool); + kfree(dcn31_pool); + *pool = NULL; +} + +static struct clock_source *dcn31_clock_source_create( + struct dc_context *ctx, + struct dc_bios *bios, + enum clock_source_id id, + const struct dce110_clk_src_regs *regs, + bool dp_clk_src) +{ + struct dce110_clk_src *clk_src = + kzalloc(sizeof(struct dce110_clk_src), GFP_KERNEL); + + if (!clk_src) + return NULL; + + if (dcn31_clk_src_construct(clk_src, ctx, bios, id, + regs, &cs_shift, &cs_mask)) { + clk_src->base.dp_clk_src = dp_clk_src; + return &clk_src->base; + } + + kfree(clk_src); + BREAK_TO_DEBUGGER(); + return NULL; +} + +static bool is_dual_plane(enum surface_pixel_format format) +{ + return format >= SURFACE_PIXEL_FORMAT_VIDEO_BEGIN || format == SURFACE_PIXEL_FORMAT_GRPH_RGBE_ALPHA; +} + +static int source_format_to_bpp (enum source_format_class SourcePixelFormat) +{ + if (SourcePixelFormat == dm_444_64) + return 8; + else if (SourcePixelFormat == dm_444_16) + return 2; + else if (SourcePixelFormat == dm_444_8) + return 1; + else if (SourcePixelFormat == dm_rgbe_alpha) + return 5; + else if (SourcePixelFormat == dm_420_8) + return 3; + else if (SourcePixelFormat == dm_420_12) + return 6; + else + return 4; +} + +static bool allow_pixel_rate_crb(struct dc *dc, struct dc_state *context) +{ + int i; + struct resource_context *res_ctx = &context->res_ctx; + + /*Don't apply for single stream*/ + if (context->stream_count < 2) + return false; + + for (i = 0; i < dc->res_pool->pipe_count; i++) { + if (!res_ctx->pipe_ctx[i].stream) + continue; + + /*Don't apply if scaling*/ + if (res_ctx->pipe_ctx[i].stream->src.width != res_ctx->pipe_ctx[i].stream->dst.width || + res_ctx->pipe_ctx[i].stream->src.height != res_ctx->pipe_ctx[i].stream->dst.height || + (res_ctx->pipe_ctx[i].plane_state && (res_ctx->pipe_ctx[i].plane_state->src_rect.width + != res_ctx->pipe_ctx[i].plane_state->dst_rect.width || + res_ctx->pipe_ctx[i].plane_state->src_rect.height + != res_ctx->pipe_ctx[i].plane_state->dst_rect.height))) + return false; + /*Don't apply if MPO to avoid transition issues*/ + if (res_ctx->pipe_ctx[i].top_pipe && res_ctx->pipe_ctx[i].top_pipe->plane_state != res_ctx->pipe_ctx[i].plane_state) + return false; + } + return true; +} + +static int dcn315_populate_dml_pipes_from_context( + struct dc *dc, struct dc_state *context, + display_e2e_pipe_params_st *pipes, + bool fast_validate) +{ + int i, pipe_cnt, crb_idx, crb_pipes; + struct resource_context *res_ctx = &context->res_ctx; + struct pipe_ctx *pipe = NULL; + const int max_usable_det = context->bw_ctx.dml.ip.config_return_buffer_size_in_kbytes - DCN3_15_MIN_COMPBUF_SIZE_KB; + int remaining_det_segs = max_usable_det / DCN3_15_CRB_SEGMENT_SIZE_KB; + bool pixel_rate_crb = allow_pixel_rate_crb(dc, context); + + DC_FP_START(); + dcn31x_populate_dml_pipes_from_context(dc, context, pipes, fast_validate); + DC_FP_END(); + + for (i = 0, pipe_cnt = 0, crb_pipes = 0; i < dc->res_pool->pipe_count; i++) { + struct dc_crtc_timing *timing; + + if (!res_ctx->pipe_ctx[i].stream) + continue; + pipe = &res_ctx->pipe_ctx[i]; + timing = &pipe->stream->timing; + + /* + * Immediate flip can be set dynamically after enabling the plane. + * We need to require support for immediate flip or underflow can be + * intermittently experienced depending on peak b/w requirements. + */ + pipes[pipe_cnt].pipe.src.immediate_flip = true; + + pipes[pipe_cnt].pipe.src.unbounded_req_mode = false; + pipes[pipe_cnt].pipe.dest.vfront_porch = timing->v_front_porch; + pipes[pipe_cnt].pipe.src.dcc_rate = 3; + pipes[pipe_cnt].dout.dsc_input_bpc = 0; + DC_FP_START(); + dcn31_zero_pipe_dcc_fraction(pipes, pipe_cnt); + if (pixel_rate_crb && !pipe->top_pipe && !pipe->prev_odm_pipe) { + int bpp = source_format_to_bpp(pipes[pipe_cnt].pipe.src.source_format); + /* Ceil to crb segment size */ + int approx_det_segs_required_for_pstate = dcn_get_approx_det_segs_required_for_pstate( + &context->bw_ctx.dml.soc, timing->pix_clk_100hz, bpp, DCN3_15_CRB_SEGMENT_SIZE_KB); + + if (approx_det_segs_required_for_pstate <= 2 * DCN3_15_MAX_DET_SEGS) { + bool split_required = approx_det_segs_required_for_pstate > DCN3_15_MAX_DET_SEGS; + split_required = split_required || timing->pix_clk_100hz >= dcn_get_max_non_odm_pix_rate_100hz(&dc->dml.soc); + split_required = split_required || (pipe->plane_state && pipe->plane_state->src_rect.width > 5120); + + /* Minimum 2 segments to allow mpc/odm combine if its used later */ + if (approx_det_segs_required_for_pstate < 2) + approx_det_segs_required_for_pstate = 2; + if (split_required) + approx_det_segs_required_for_pstate += approx_det_segs_required_for_pstate % 2; + pipes[pipe_cnt].pipe.src.det_size_override = approx_det_segs_required_for_pstate; + remaining_det_segs -= approx_det_segs_required_for_pstate; + } else + remaining_det_segs = -1; + crb_pipes++; + } + DC_FP_END(); + + if (pipes[pipe_cnt].dout.dsc_enable) { + switch (timing->display_color_depth) { + case COLOR_DEPTH_888: + pipes[pipe_cnt].dout.dsc_input_bpc = 8; + break; + case COLOR_DEPTH_101010: + pipes[pipe_cnt].dout.dsc_input_bpc = 10; + break; + case COLOR_DEPTH_121212: + pipes[pipe_cnt].dout.dsc_input_bpc = 12; + break; + default: + ASSERT(0); + break; + } + } + pipe_cnt++; + } + + /* Spread remaining unreserved crb evenly among all pipes*/ + if (pixel_rate_crb) { + for (i = 0, pipe_cnt = 0, crb_idx = 0; i < dc->res_pool->pipe_count; i++) { + pipe = &res_ctx->pipe_ctx[i]; + if (!pipe->stream) + continue; + + /* Do not use asymetric crb if not enough for pstate support */ + if (remaining_det_segs < 0) { + pipes[pipe_cnt].pipe.src.det_size_override = 0; + pipe_cnt++; + continue; + } + + if (!pipe->top_pipe && !pipe->prev_odm_pipe) { + bool split_required = pipe->stream->timing.pix_clk_100hz >= dcn_get_max_non_odm_pix_rate_100hz(&dc->dml.soc) + || (pipe->plane_state && pipe->plane_state->src_rect.width > 5120); + + if (remaining_det_segs > MIN_RESERVED_DET_SEGS) + pipes[pipe_cnt].pipe.src.det_size_override += (remaining_det_segs - MIN_RESERVED_DET_SEGS) / crb_pipes + + (crb_idx < (remaining_det_segs - MIN_RESERVED_DET_SEGS) % crb_pipes ? 1 : 0); + if (pipes[pipe_cnt].pipe.src.det_size_override > 2 * DCN3_15_MAX_DET_SEGS) { + /* Clamp to 2 pipe split max det segments */ + remaining_det_segs += pipes[pipe_cnt].pipe.src.det_size_override - 2 * (DCN3_15_MAX_DET_SEGS); + pipes[pipe_cnt].pipe.src.det_size_override = 2 * DCN3_15_MAX_DET_SEGS; + } + if (pipes[pipe_cnt].pipe.src.det_size_override > DCN3_15_MAX_DET_SEGS || split_required) { + /* If we are splitting we must have an even number of segments */ + remaining_det_segs += pipes[pipe_cnt].pipe.src.det_size_override % 2; + pipes[pipe_cnt].pipe.src.det_size_override -= pipes[pipe_cnt].pipe.src.det_size_override % 2; + } + /* Convert segments into size for DML use */ + pipes[pipe_cnt].pipe.src.det_size_override *= DCN3_15_CRB_SEGMENT_SIZE_KB; + + crb_idx++; + } + pipe_cnt++; + } + } + + if (pipe_cnt) + context->bw_ctx.dml.ip.det_buffer_size_kbytes = + (max_usable_det / DCN3_15_CRB_SEGMENT_SIZE_KB / pipe_cnt) * DCN3_15_CRB_SEGMENT_SIZE_KB; + if (context->bw_ctx.dml.ip.det_buffer_size_kbytes > DCN3_15_MAX_DET_SIZE) + context->bw_ctx.dml.ip.det_buffer_size_kbytes = DCN3_15_MAX_DET_SIZE; + + dc->config.enable_4to1MPC = false; + if (pipe_cnt == 1 && pipe->plane_state && !dc->debug.disable_z9_mpc) { + if (is_dual_plane(pipe->plane_state->format) + && pipe->plane_state->src_rect.width <= 1920 && pipe->plane_state->src_rect.height <= 1080) { + dc->config.enable_4to1MPC = true; + context->bw_ctx.dml.ip.det_buffer_size_kbytes = + (max_usable_det / DCN3_15_CRB_SEGMENT_SIZE_KB / 4) * DCN3_15_CRB_SEGMENT_SIZE_KB; + } else if (!is_dual_plane(pipe->plane_state->format) + && pipe->plane_state->src_rect.width <= 5120 + && pipe->stream->timing.pix_clk_100hz < dcn_get_max_non_odm_pix_rate_100hz(&dc->dml.soc)) { + /* Limit to 5k max to avoid forced pipe split when there is not enough detile for swath */ + context->bw_ctx.dml.ip.det_buffer_size_kbytes = 192; + pipes[0].pipe.src.unbounded_req_mode = true; + } + } + + return pipe_cnt; +} + +static void dcn315_get_panel_config_defaults(struct dc_panel_config *panel_config) +{ + *panel_config = panel_config_defaults; +} + +static struct dc_cap_funcs cap_funcs = { + .get_dcc_compression_cap = dcn20_get_dcc_compression_cap +}; + +static struct resource_funcs dcn315_res_pool_funcs = { + .destroy = dcn315_destroy_resource_pool, + .link_enc_create = dcn31_link_encoder_create, + .link_enc_create_minimal = dcn31_link_enc_create_minimal, + .link_encs_assign = link_enc_cfg_link_encs_assign, + .link_enc_unassign = link_enc_cfg_link_enc_unassign, + .panel_cntl_create = dcn31_panel_cntl_create, + .validate_bandwidth = dcn31_validate_bandwidth, + .calculate_wm_and_dlg = dcn31_calculate_wm_and_dlg, + .update_soc_for_wm_a = dcn315_update_soc_for_wm_a, + .populate_dml_pipes = dcn315_populate_dml_pipes_from_context, + .acquire_free_pipe_as_secondary_dpp_pipe = dcn20_acquire_free_pipe_for_layer, + .release_pipe = dcn20_release_pipe, + .add_stream_to_ctx = dcn30_add_stream_to_ctx, + .add_dsc_to_stream_resource = dcn20_add_dsc_to_stream_resource, + .remove_stream_from_ctx = dcn20_remove_stream_from_ctx, + .populate_dml_writeback_from_context = dcn31_populate_dml_writeback_from_context, + .set_mcif_arb_params = dcn31_set_mcif_arb_params, + .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 = dcn315_update_bw_bounding_box, + .patch_unknown_plane_state = dcn20_patch_unknown_plane_state, + .get_panel_config_defaults = dcn315_get_panel_config_defaults, +}; + +static bool dcn315_resource_construct( + uint8_t num_virtual_links, + struct dc *dc, + struct dcn315_resource_pool *pool) +{ + int i; + struct dc_context *ctx = dc->ctx; + struct irq_service_init_data init_data; + + ctx->dc_bios->regs = &bios_regs; + + pool->base.res_cap = &res_cap_dcn31; + + pool->base.funcs = &dcn315_res_pool_funcs; + + /************************************************* + * Resource + asic cap harcoding * + *************************************************/ + pool->base.underlay_pipe_index = NO_UNDERLAY_PIPE; + pool->base.pipe_count = pool->base.res_cap->num_timing_generator; + pool->base.mpcc_count = pool->base.res_cap->num_timing_generator; + dc->caps.max_downscale_ratio = 600; + dc->caps.i2c_speed_in_khz = 100; + dc->caps.i2c_speed_in_khz_hdcp = 100; + dc->caps.max_cursor_size = 256; + dc->caps.min_horizontal_blanking_period = 80; + dc->caps.dmdata_alloc_size = 2048; + dc->caps.max_slave_planes = 2; + dc->caps.max_slave_yuv_planes = 2; + dc->caps.max_slave_rgb_planes = 2; + dc->caps.post_blend_color_processing = true; + dc->caps.force_dp_tps4_for_cp2520 = true; + if (dc->config.forceHBR2CP2520) + dc->caps.force_dp_tps4_for_cp2520 = false; + dc->caps.dp_hpo = true; + dc->caps.dp_hdmi21_pcon_support = true; + dc->caps.edp_dsc_support = true; + dc->caps.extended_aux_timeout_support = true; + dc->caps.dmcub_support = true; + dc->caps.is_apu = true; + + /* Color pipeline capabilities */ + dc->caps.color.dpp.dcn_arch = 1; + dc->caps.color.dpp.input_lut_shared = 0; + dc->caps.color.dpp.icsc = 1; + dc->caps.color.dpp.dgam_ram = 0; // must use gamma_corr + dc->caps.color.dpp.dgam_rom_caps.srgb = 1; + dc->caps.color.dpp.dgam_rom_caps.bt2020 = 1; + dc->caps.color.dpp.dgam_rom_caps.gamma2_2 = 1; + dc->caps.color.dpp.dgam_rom_caps.pq = 1; + dc->caps.color.dpp.dgam_rom_caps.hlg = 1; + dc->caps.color.dpp.post_csc = 1; + dc->caps.color.dpp.gamma_corr = 1; + dc->caps.color.dpp.dgam_rom_for_yuv = 0; + + dc->caps.color.dpp.hw_3d_lut = 1; + dc->caps.color.dpp.ogam_ram = 1; + // no OGAM ROM on DCN301 + dc->caps.color.dpp.ogam_rom_caps.srgb = 0; + dc->caps.color.dpp.ogam_rom_caps.bt2020 = 0; + dc->caps.color.dpp.ogam_rom_caps.gamma2_2 = 0; + dc->caps.color.dpp.ogam_rom_caps.pq = 0; + dc->caps.color.dpp.ogam_rom_caps.hlg = 0; + dc->caps.color.dpp.ocsc = 0; + + dc->caps.color.mpc.gamut_remap = 1; + dc->caps.color.mpc.num_3dluts = pool->base.res_cap->num_mpc_3dlut; //2 + dc->caps.color.mpc.ogam_ram = 1; + dc->caps.color.mpc.ogam_rom_caps.srgb = 0; + dc->caps.color.mpc.ogam_rom_caps.bt2020 = 0; + dc->caps.color.mpc.ogam_rom_caps.gamma2_2 = 0; + dc->caps.color.mpc.ogam_rom_caps.pq = 0; + dc->caps.color.mpc.ogam_rom_caps.hlg = 0; + dc->caps.color.mpc.ocsc = 1; + + /* read VBIOS LTTPR caps */ + { + if (ctx->dc_bios->funcs->get_lttpr_caps) { + enum bp_result bp_query_result; + uint8_t is_vbios_lttpr_enable = 0; + + bp_query_result = ctx->dc_bios->funcs->get_lttpr_caps(ctx->dc_bios, &is_vbios_lttpr_enable); + dc->caps.vbios_lttpr_enable = (bp_query_result == BP_RESULT_OK) && !!is_vbios_lttpr_enable; + } + + /* interop bit is implicit */ + { + dc->caps.vbios_lttpr_aware = true; + } + } + + if (dc->ctx->dce_environment == DCE_ENV_PRODUCTION_DRV) + dc->debug = debug_defaults_drv; + + // Init the vm_helper + if (dc->vm_helper) + vm_helper_init(dc->vm_helper, 16); + + /************************************************* + * Create resources * + *************************************************/ + + /* Clock Sources for Pixel Clock*/ + pool->base.clock_sources[DCN31_CLK_SRC_PLL0] = + dcn31_clock_source_create(ctx, ctx->dc_bios, + CLOCK_SOURCE_COMBO_PHY_PLL0, + &clk_src_regs[0], false); + pool->base.clock_sources[DCN31_CLK_SRC_PLL1] = + dcn31_clock_source_create(ctx, ctx->dc_bios, + CLOCK_SOURCE_COMBO_PHY_PLL1, + &clk_src_regs[1], false); + pool->base.clock_sources[DCN31_CLK_SRC_PLL2] = + dcn31_clock_source_create(ctx, ctx->dc_bios, + CLOCK_SOURCE_COMBO_PHY_PLL2, + &clk_src_regs[2], false); + pool->base.clock_sources[DCN31_CLK_SRC_PLL3] = + dcn31_clock_source_create(ctx, ctx->dc_bios, + CLOCK_SOURCE_COMBO_PHY_PLL3, + &clk_src_regs[3], false); + pool->base.clock_sources[DCN31_CLK_SRC_PLL4] = + dcn31_clock_source_create(ctx, ctx->dc_bios, + CLOCK_SOURCE_COMBO_PHY_PLL4, + &clk_src_regs[4], false); + + pool->base.clk_src_count = DCN30_CLK_SRC_TOTAL; + + /* todo: not reuse phy_pll registers */ + pool->base.dp_clock_source = + dcn31_clock_source_create(ctx, ctx->dc_bios, + CLOCK_SOURCE_ID_DP_DTO, + &clk_src_regs[0], true); + + for (i = 0; i < pool->base.clk_src_count; i++) { + if (pool->base.clock_sources[i] == NULL) { + dm_error("DC: failed to create clock sources!\n"); + BREAK_TO_DEBUGGER(); + goto create_fail; + } + } + + /* TODO: DCCG */ + pool->base.dccg = dccg31_create(ctx, &dccg_regs, &dccg_shift, &dccg_mask); + if (pool->base.dccg == NULL) { + dm_error("DC: failed to create dccg!\n"); + BREAK_TO_DEBUGGER(); + goto create_fail; + } + + /* TODO: IRQ */ + init_data.ctx = dc->ctx; + pool->base.irqs = dal_irq_service_dcn315_create(&init_data); + if (!pool->base.irqs) + goto create_fail; + + /* HUBBUB */ + pool->base.hubbub = dcn31_hubbub_create(ctx); + if (pool->base.hubbub == NULL) { + BREAK_TO_DEBUGGER(); + dm_error("DC: failed to create hubbub!\n"); + goto create_fail; + } + + /* HUBPs, DPPs, OPPs and TGs */ + for (i = 0; i < pool->base.pipe_count; i++) { + pool->base.hubps[i] = dcn31_hubp_create(ctx, i); + if (pool->base.hubps[i] == NULL) { + BREAK_TO_DEBUGGER(); + dm_error( + "DC: failed to create hubps!\n"); + goto create_fail; + } + + pool->base.dpps[i] = dcn31_dpp_create(ctx, i); + if (pool->base.dpps[i] == NULL) { + BREAK_TO_DEBUGGER(); + dm_error( + "DC: failed to create dpps!\n"); + goto create_fail; + } + } + + for (i = 0; i < pool->base.res_cap->num_opp; i++) { + pool->base.opps[i] = dcn31_opp_create(ctx, i); + if (pool->base.opps[i] == NULL) { + BREAK_TO_DEBUGGER(); + dm_error( + "DC: failed to create output pixel processor!\n"); + goto create_fail; + } + } + + for (i = 0; i < pool->base.res_cap->num_timing_generator; i++) { + pool->base.timing_generators[i] = dcn31_timing_generator_create( + ctx, i); + if (pool->base.timing_generators[i] == NULL) { + BREAK_TO_DEBUGGER(); + dm_error("DC: failed to create tg!\n"); + goto create_fail; + } + } + pool->base.timing_generator_count = i; + + /* PSR */ + pool->base.psr = dmub_psr_create(ctx); + if (pool->base.psr == NULL) { + dm_error("DC: failed to create psr obj!\n"); + BREAK_TO_DEBUGGER(); + goto create_fail; + } + + /* ABM */ + for (i = 0; i < pool->base.res_cap->num_timing_generator; i++) { + pool->base.multiple_abms[i] = dmub_abm_create(ctx, + &abm_regs[i], + &abm_shift, + &abm_mask); + if (pool->base.multiple_abms[i] == NULL) { + dm_error("DC: failed to create abm for pipe %d!\n", i); + BREAK_TO_DEBUGGER(); + goto create_fail; + } + } + + /* MPC and DSC */ + pool->base.mpc = dcn31_mpc_create(ctx, pool->base.mpcc_count, pool->base.res_cap->num_mpc_3dlut); + if (pool->base.mpc == NULL) { + BREAK_TO_DEBUGGER(); + dm_error("DC: failed to create mpc!\n"); + goto create_fail; + } + + for (i = 0; i < pool->base.res_cap->num_dsc; i++) { + pool->base.dscs[i] = dcn31_dsc_create(ctx, i); + if (pool->base.dscs[i] == NULL) { + BREAK_TO_DEBUGGER(); + dm_error("DC: failed to create display stream compressor %d!\n", i); + goto create_fail; + } + } + + /* DWB and MMHUBBUB */ + if (!dcn31_dwbc_create(ctx, &pool->base)) { + BREAK_TO_DEBUGGER(); + dm_error("DC: failed to create dwbc!\n"); + goto create_fail; + } + + if (!dcn31_mmhubbub_create(ctx, &pool->base)) { + BREAK_TO_DEBUGGER(); + dm_error("DC: failed to create mcif_wb!\n"); + goto create_fail; + } + + /* AUX and I2C */ + for (i = 0; i < pool->base.res_cap->num_ddc; i++) { + pool->base.engines[i] = dcn31_aux_engine_create(ctx, i); + if (pool->base.engines[i] == NULL) { + BREAK_TO_DEBUGGER(); + dm_error( + "DC:failed to create aux engine!!\n"); + goto create_fail; + } + pool->base.hw_i2cs[i] = dcn31_i2c_hw_create(ctx, i); + if (pool->base.hw_i2cs[i] == NULL) { + BREAK_TO_DEBUGGER(); + dm_error( + "DC:failed to create hw i2c!!\n"); + goto create_fail; + } + pool->base.sw_i2cs[i] = NULL; + } + + /* Audio, Stream Encoders including HPO and virtual, MPC 3D LUTs */ + if (!resource_construct(num_virtual_links, dc, &pool->base, + &res_create_funcs)) + goto create_fail; + + /* HW Sequencer and Plane caps */ + dcn31_hw_sequencer_construct(dc); + + dc->caps.max_planes = pool->base.pipe_count; + + for (i = 0; i < dc->caps.max_planes; ++i) + dc->caps.planes[i] = plane_cap; + + dc->cap_funcs = cap_funcs; + + dc->dcn_ip->max_num_dpp = dcn3_15_ip.max_num_dpp; + + return true; + +create_fail: + + dcn315_resource_destruct(pool); + + return false; +} + +struct resource_pool *dcn315_create_resource_pool( + const struct dc_init_data *init_data, + struct dc *dc) +{ + struct dcn315_resource_pool *pool = + kzalloc(sizeof(struct dcn315_resource_pool), GFP_KERNEL); + + if (!pool) + return NULL; + + if (dcn315_resource_construct(init_data->num_virtual_links, dc, pool)) + return &pool->base; + + BREAK_TO_DEBUGGER(); + kfree(pool); + return NULL; +} diff --git a/drivers/gpu/drm/amd/display/dc/resource/dcn315/dcn315_resource.h b/drivers/gpu/drm/amd/display/dc/resource/dcn315/dcn315_resource.h new file mode 100644 index 000000000000..22849eaa6f24 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/resource/dcn315/dcn315_resource.h @@ -0,0 +1,44 @@ +/* + * Copyright 2021 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#ifndef _DCN315_RESOURCE_H_ +#define _DCN315_RESOURCE_H_ + +#include "core_types.h" + +#define TO_DCN315_RES_POOL(pool)\ + container_of(pool, struct dcn315_resource_pool, base) + +extern struct _vcs_dpi_ip_params_st dcn3_15_ip; + +struct dcn315_resource_pool { + struct resource_pool base; +}; + +struct resource_pool *dcn315_create_resource_pool( + const struct dc_init_data *init_data, + struct dc *dc); + +#endif /* _DCN315_RESOURCE_H_ */ diff --git a/drivers/gpu/drm/amd/display/dc/resource/dcn316/dcn316_resource.c b/drivers/gpu/drm/amd/display/dc/resource/dcn316/dcn316_resource.c new file mode 100644 index 000000000000..b9753d4606f8 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/resource/dcn316/dcn316_resource.c @@ -0,0 +1,2038 @@ +/* + * 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 "dm_services.h" +#include "dc.h" + +#include "dcn31/dcn31_init.h" + +#include "resource.h" +#include "include/irq_service_interface.h" +#include "dcn316_resource.h" + +#include "dcn20/dcn20_resource.h" +#include "dcn30/dcn30_resource.h" +#include "dcn31/dcn31_resource.h" + +#include "dcn10/dcn10_ipp.h" +#include "dcn30/dcn30_hubbub.h" +#include "dcn31/dcn31_hubbub.h" +#include "dcn30/dcn30_mpc.h" +#include "dcn31/dcn31_hubp.h" +#include "irq/dcn31/irq_service_dcn31.h" +#include "dcn30/dcn30_dpp.h" +#include "dcn31/dcn31_optc.h" +#include "dcn20/dcn20_hwseq.h" +#include "dcn30/dcn30_hwseq.h" +#include "dce110/dce110_hwseq.h" +#include "dcn30/dcn30_opp.h" +#include "dcn20/dcn20_dsc.h" +#include "dcn30/dcn30_vpg.h" +#include "dcn30/dcn30_afmt.h" +#include "dcn30/dcn30_dio_stream_encoder.h" +#include "dcn31/dcn31_hpo_dp_stream_encoder.h" +#include "dcn31/dcn31_hpo_dp_link_encoder.h" +#include "dcn31/dcn31_apg.h" +#include "dcn31/dcn31_dio_link_encoder.h" +#include "dcn31/dcn31_vpg.h" +#include "dcn31/dcn31_afmt.h" +#include "dce/dce_clock_source.h" +#include "dce/dce_audio.h" +#include "dce/dce_hwseq.h" +#include "clk_mgr.h" +#include "virtual/virtual_stream_encoder.h" +#include "dce110/dce110_resource.h" +#include "dml/display_mode_vba.h" +#include "dml/dcn31/dcn31_fpu.h" +#include "dcn31/dcn31_dccg.h" +#include "dcn10/dcn10_resource.h" +#include "dcn31/dcn31_panel_cntl.h" + +#include "dcn30/dcn30_dwb.h" +#include "dcn30/dcn30_mmhubbub.h" + +#include "dcn/dcn_3_1_6_offset.h" +#include "dcn/dcn_3_1_6_sh_mask.h" +#include "dpcs/dpcs_4_2_3_offset.h" +#include "dpcs/dpcs_4_2_3_sh_mask.h" + +#define regBIF_BX1_BIOS_SCRATCH_2 0x003a +#define regBIF_BX1_BIOS_SCRATCH_2_BASE_IDX 1 +#define regBIF_BX1_BIOS_SCRATCH_3 0x003b +#define regBIF_BX1_BIOS_SCRATCH_3_BASE_IDX 1 +#define regBIF_BX1_BIOS_SCRATCH_6 0x003e +#define regBIF_BX1_BIOS_SCRATCH_6_BASE_IDX 1 + +#define regDCHUBBUB_DEBUG_CTRL_0 0x04d6 +#define regDCHUBBUB_DEBUG_CTRL_0_BASE_IDX 2 +#define DCHUBBUB_DEBUG_CTRL_0__DET_DEPTH__SHIFT 0x10 +#define DCHUBBUB_DEBUG_CTRL_0__DET_DEPTH_MASK 0x01FF0000L + +#define DCN_BASE__INST0_SEG0 0x00000012 +#define DCN_BASE__INST0_SEG1 0x000000C0 +#define DCN_BASE__INST0_SEG2 0x000034C0 +#define DCN_BASE__INST0_SEG3 0x00009000 +#define DCN_BASE__INST0_SEG4 0x02403C00 +#define DCN_BASE__INST0_SEG5 0 + +#define DPCS_BASE__INST0_SEG0 0x00000012 +#define DPCS_BASE__INST0_SEG1 0x000000C0 +#define DPCS_BASE__INST0_SEG2 0x000034C0 +#define DPCS_BASE__INST0_SEG3 0x00009000 +#define DPCS_BASE__INST0_SEG4 0x02403C00 +#define DPCS_BASE__INST0_SEG5 0 + +#define NBIO_BASE__INST0_SEG0 0x00000000 +#define NBIO_BASE__INST0_SEG1 0x00000014 +#define NBIO_BASE__INST0_SEG2 0x00000D20 +#define NBIO_BASE__INST0_SEG3 0x00010400 +#define NBIO_BASE__INST0_SEG4 0x0241B000 +#define NBIO_BASE__INST0_SEG5 0x04040000 + +#include "reg_helper.h" +#include "dce/dmub_abm.h" +#include "dce/dmub_psr.h" +#include "dce/dce_aux.h" +#include "dce/dce_i2c.h" + +#include "dml/dcn30/display_mode_vba_30.h" +#include "vm_helper.h" +#include "dcn20/dcn20_vmid.h" + +#include "link_enc_cfg.h" + +#define DCN3_16_MAX_DET_SIZE 384 +#define DCN3_16_MIN_COMPBUF_SIZE_KB 128 +#define DCN3_16_CRB_SEGMENT_SIZE_KB 64 + +enum dcn31_clk_src_array_id { + DCN31_CLK_SRC_PLL0, + DCN31_CLK_SRC_PLL1, + DCN31_CLK_SRC_PLL2, + DCN31_CLK_SRC_PLL3, + DCN31_CLK_SRC_PLL4, + DCN30_CLK_SRC_TOTAL +}; + +/* begin ********************* + * macros to expend register list macro defined in HW object header file + */ + +/* DCN */ +#define BASE_INNER(seg) DCN_BASE__INST0_SEG ## seg + +#define BASE(seg) BASE_INNER(seg) + +#define SR(reg_name)\ + .reg_name = BASE(reg ## reg_name ## _BASE_IDX) + \ + reg ## reg_name + +#define SRI(reg_name, block, id)\ + .reg_name = BASE(reg ## block ## id ## _ ## reg_name ## _BASE_IDX) + \ + reg ## block ## id ## _ ## reg_name + +#define SRI2(reg_name, block, id)\ + .reg_name = BASE(reg ## reg_name ## _BASE_IDX) + \ + reg ## reg_name + +#define SRIR(var_name, reg_name, block, id)\ + .var_name = BASE(reg ## block ## id ## _ ## reg_name ## _BASE_IDX) + \ + reg ## block ## id ## _ ## reg_name + +#define SRII(reg_name, block, id)\ + .reg_name[id] = BASE(reg ## block ## id ## _ ## reg_name ## _BASE_IDX) + \ + reg ## block ## id ## _ ## reg_name + +#define SRII_MPC_RMU(reg_name, block, id)\ + .RMU##_##reg_name[id] = BASE(reg ## block ## id ## _ ## reg_name ## _BASE_IDX) + \ + reg ## block ## id ## _ ## reg_name + +#define SRII_DWB(reg_name, temp_name, block, id)\ + .reg_name[id] = BASE(reg ## block ## id ## _ ## temp_name ## _BASE_IDX) + \ + reg ## block ## id ## _ ## temp_name + +#define SF_DWB2(reg_name, block, id, field_name, post_fix) \ + .field_name = reg_name ## __ ## field_name ## post_fix + +#define DCCG_SRII(reg_name, block, id)\ + .block ## _ ## reg_name[id] = BASE(reg ## block ## id ## _ ## reg_name ## _BASE_IDX) + \ + reg ## block ## id ## _ ## reg_name + +#define VUPDATE_SRII(reg_name, block, id)\ + .reg_name[id] = BASE(reg ## reg_name ## _ ## block ## id ## _BASE_IDX) + \ + reg ## reg_name ## _ ## block ## id + +/* NBIO */ +#define NBIO_BASE_INNER(seg) \ + NBIO_BASE__INST0_SEG ## seg + +#define NBIO_BASE(seg) \ + NBIO_BASE_INNER(seg) + +#define NBIO_SR(reg_name)\ + .reg_name = NBIO_BASE(regBIF_BX1_ ## reg_name ## _BASE_IDX) + \ + regBIF_BX1_ ## reg_name + +static const struct bios_registers bios_regs = { + NBIO_SR(BIOS_SCRATCH_3), + NBIO_SR(BIOS_SCRATCH_6) +}; + +#define clk_src_regs(index, pllid)\ +[index] = {\ + CS_COMMON_REG_LIST_DCN3_0(index, pllid),\ +} + +static const struct dce110_clk_src_regs clk_src_regs[] = { + clk_src_regs(0, A), + clk_src_regs(1, B), + clk_src_regs(2, C), + clk_src_regs(3, D), + clk_src_regs(4, E) +}; + +static const struct dce110_clk_src_shift cs_shift = { + CS_COMMON_MASK_SH_LIST_DCN2_0(__SHIFT) +}; + +static const struct dce110_clk_src_mask cs_mask = { + CS_COMMON_MASK_SH_LIST_DCN2_0(_MASK) +}; + +#define abm_regs(id)\ +[id] = {\ + ABM_DCN302_REG_LIST(id)\ +} + +static const struct dce_abm_registers abm_regs[] = { + abm_regs(0), + abm_regs(1), + abm_regs(2), + abm_regs(3), +}; + +static const struct dce_abm_shift abm_shift = { + ABM_MASK_SH_LIST_DCN30(__SHIFT) +}; + +static const struct dce_abm_mask abm_mask = { + ABM_MASK_SH_LIST_DCN30(_MASK) +}; + +#define audio_regs(id)\ +[id] = {\ + AUD_COMMON_REG_LIST(id)\ +} + +static const struct dce_audio_registers audio_regs[] = { + audio_regs(0), + audio_regs(1), + audio_regs(2), + audio_regs(3), + audio_regs(4), + audio_regs(5), + audio_regs(6) +}; + +#define DCE120_AUD_COMMON_MASK_SH_LIST(mask_sh)\ + SF(AZF0ENDPOINT0_AZALIA_F0_CODEC_ENDPOINT_INDEX, AZALIA_ENDPOINT_REG_INDEX, mask_sh),\ + SF(AZF0ENDPOINT0_AZALIA_F0_CODEC_ENDPOINT_DATA, AZALIA_ENDPOINT_REG_DATA, mask_sh),\ + AUD_COMMON_MASK_SH_LIST_BASE(mask_sh) + +static const struct dce_audio_shift audio_shift = { + DCE120_AUD_COMMON_MASK_SH_LIST(__SHIFT) +}; + +static const struct dce_audio_mask audio_mask = { + DCE120_AUD_COMMON_MASK_SH_LIST(_MASK) +}; + +#define vpg_regs(id)\ +[id] = {\ + VPG_DCN31_REG_LIST(id)\ +} + +static const struct dcn31_vpg_registers vpg_regs[] = { + vpg_regs(0), + vpg_regs(1), + vpg_regs(2), + vpg_regs(3), + vpg_regs(4), + vpg_regs(5), + vpg_regs(6), + vpg_regs(7), + vpg_regs(8), + vpg_regs(9), +}; + +static const struct dcn31_vpg_shift vpg_shift = { + DCN31_VPG_MASK_SH_LIST(__SHIFT) +}; + +static const struct dcn31_vpg_mask vpg_mask = { + DCN31_VPG_MASK_SH_LIST(_MASK) +}; + +#define afmt_regs(id)\ +[id] = {\ + AFMT_DCN31_REG_LIST(id)\ +} + +static const struct dcn31_afmt_registers afmt_regs[] = { + afmt_regs(0), + afmt_regs(1), + afmt_regs(2), + afmt_regs(3), + afmt_regs(4), + afmt_regs(5) +}; + +static const struct dcn31_afmt_shift afmt_shift = { + DCN31_AFMT_MASK_SH_LIST(__SHIFT) +}; + +static const struct dcn31_afmt_mask afmt_mask = { + DCN31_AFMT_MASK_SH_LIST(_MASK) +}; + + +#define apg_regs(id)\ +[id] = {\ + APG_DCN31_REG_LIST(id)\ +} + +static const struct dcn31_apg_registers apg_regs[] = { + apg_regs(0), + apg_regs(1), + apg_regs(2), + apg_regs(3) +}; + +static const struct dcn31_apg_shift apg_shift = { + DCN31_APG_MASK_SH_LIST(__SHIFT) +}; + +static const struct dcn31_apg_mask apg_mask = { + DCN31_APG_MASK_SH_LIST(_MASK) +}; + + +#define stream_enc_regs(id)\ +[id] = {\ + SE_DCN3_REG_LIST(id)\ +} + +static const struct dcn10_stream_enc_registers stream_enc_regs[] = { + stream_enc_regs(0), + stream_enc_regs(1), + stream_enc_regs(2), + stream_enc_regs(3), + stream_enc_regs(4) +}; + +static const struct dcn10_stream_encoder_shift se_shift = { + SE_COMMON_MASK_SH_LIST_DCN30(__SHIFT) +}; + +static const struct dcn10_stream_encoder_mask se_mask = { + SE_COMMON_MASK_SH_LIST_DCN30(_MASK) +}; + + +#define aux_regs(id)\ +[id] = {\ + DCN2_AUX_REG_LIST(id)\ +} + +static const struct dcn10_link_enc_aux_registers link_enc_aux_regs[] = { + aux_regs(0), + aux_regs(1), + aux_regs(2), + aux_regs(3), + aux_regs(4) +}; + +#define hpd_regs(id)\ +[id] = {\ + HPD_REG_LIST(id)\ +} + +static const struct dcn10_link_enc_hpd_registers link_enc_hpd_regs[] = { + hpd_regs(0), + hpd_regs(1), + hpd_regs(2), + hpd_regs(3), + hpd_regs(4) +}; + +#define link_regs(id, phyid)\ +[id] = {\ + LE_DCN31_REG_LIST(id), \ + UNIPHY_DCN2_REG_LIST(phyid), \ + DPCS_DCN31_REG_LIST(id), \ +} + +static const struct dce110_aux_registers_shift aux_shift = { + DCN_AUX_MASK_SH_LIST(__SHIFT) +}; + +static const struct dce110_aux_registers_mask aux_mask = { + DCN_AUX_MASK_SH_LIST(_MASK) +}; + +static const struct dcn10_link_enc_registers link_enc_regs[] = { + link_regs(0, A), + link_regs(1, B), + link_regs(2, C), + link_regs(3, D), + link_regs(4, E) +}; + +static const struct dcn10_link_enc_shift le_shift = { + LINK_ENCODER_MASK_SH_LIST_DCN31(__SHIFT), \ + DPCS_DCN31_MASK_SH_LIST(__SHIFT) +}; + +static const struct dcn10_link_enc_mask le_mask = { + LINK_ENCODER_MASK_SH_LIST_DCN31(_MASK), \ + DPCS_DCN31_MASK_SH_LIST(_MASK) +}; + + + +#define hpo_dp_stream_encoder_reg_list(id)\ +[id] = {\ + DCN3_1_HPO_DP_STREAM_ENC_REG_LIST(id)\ +} + +static const struct dcn31_hpo_dp_stream_encoder_registers hpo_dp_stream_enc_regs[] = { + hpo_dp_stream_encoder_reg_list(0), + hpo_dp_stream_encoder_reg_list(1), + hpo_dp_stream_encoder_reg_list(2), + hpo_dp_stream_encoder_reg_list(3), +}; + +static const struct dcn31_hpo_dp_stream_encoder_shift hpo_dp_se_shift = { + DCN3_1_HPO_DP_STREAM_ENC_MASK_SH_LIST(__SHIFT) +}; + +static const struct dcn31_hpo_dp_stream_encoder_mask hpo_dp_se_mask = { + DCN3_1_HPO_DP_STREAM_ENC_MASK_SH_LIST(_MASK) +}; + + +#define hpo_dp_link_encoder_reg_list(id)\ +[id] = {\ + DCN3_1_HPO_DP_LINK_ENC_REG_LIST(id),\ + DCN3_1_RDPCSTX_REG_LIST(0),\ + DCN3_1_RDPCSTX_REG_LIST(1),\ + DCN3_1_RDPCSTX_REG_LIST(2),\ + DCN3_1_RDPCSTX_REG_LIST(3),\ + DCN3_1_RDPCSTX_REG_LIST(4)\ +} + +static const struct dcn31_hpo_dp_link_encoder_registers hpo_dp_link_enc_regs[] = { + hpo_dp_link_encoder_reg_list(0), + hpo_dp_link_encoder_reg_list(1), +}; + +static const struct dcn31_hpo_dp_link_encoder_shift hpo_dp_le_shift = { + DCN3_1_HPO_DP_LINK_ENC_MASK_SH_LIST(__SHIFT) +}; + +static const struct dcn31_hpo_dp_link_encoder_mask hpo_dp_le_mask = { + DCN3_1_HPO_DP_LINK_ENC_MASK_SH_LIST(_MASK) +}; + + +#define dpp_regs(id)\ +[id] = {\ + DPP_REG_LIST_DCN30(id),\ +} + +static const struct dcn3_dpp_registers dpp_regs[] = { + dpp_regs(0), + dpp_regs(1), + dpp_regs(2), + dpp_regs(3) +}; + +static const struct dcn3_dpp_shift tf_shift = { + DPP_REG_LIST_SH_MASK_DCN30(__SHIFT) +}; + +static const struct dcn3_dpp_mask tf_mask = { + DPP_REG_LIST_SH_MASK_DCN30(_MASK) +}; + +#define opp_regs(id)\ +[id] = {\ + OPP_REG_LIST_DCN30(id),\ +} + +static const struct dcn20_opp_registers opp_regs[] = { + opp_regs(0), + opp_regs(1), + opp_regs(2), + opp_regs(3) +}; + +static const struct dcn20_opp_shift opp_shift = { + OPP_MASK_SH_LIST_DCN20(__SHIFT) +}; + +static const struct dcn20_opp_mask opp_mask = { + OPP_MASK_SH_LIST_DCN20(_MASK) +}; + +#define aux_engine_regs(id)\ +[id] = {\ + AUX_COMMON_REG_LIST0(id), \ + .AUXN_IMPCAL = 0, \ + .AUXP_IMPCAL = 0, \ + .AUX_RESET_MASK = DP_AUX0_AUX_CONTROL__AUX_RESET_MASK, \ +} + +static const struct dce110_aux_registers aux_engine_regs[] = { + aux_engine_regs(0), + aux_engine_regs(1), + aux_engine_regs(2), + aux_engine_regs(3), + aux_engine_regs(4) +}; + +#define dwbc_regs_dcn3(id)\ +[id] = {\ + DWBC_COMMON_REG_LIST_DCN30(id),\ +} + +static const struct dcn30_dwbc_registers dwbc30_regs[] = { + dwbc_regs_dcn3(0), +}; + +static const struct dcn30_dwbc_shift dwbc30_shift = { + DWBC_COMMON_MASK_SH_LIST_DCN30(__SHIFT) +}; + +static const struct dcn30_dwbc_mask dwbc30_mask = { + DWBC_COMMON_MASK_SH_LIST_DCN30(_MASK) +}; + +#define mcif_wb_regs_dcn3(id)\ +[id] = {\ + MCIF_WB_COMMON_REG_LIST_DCN30(id),\ +} + +static const struct dcn30_mmhubbub_registers mcif_wb30_regs[] = { + mcif_wb_regs_dcn3(0) +}; + +static const struct dcn30_mmhubbub_shift mcif_wb30_shift = { + MCIF_WB_COMMON_MASK_SH_LIST_DCN30(__SHIFT) +}; + +static const struct dcn30_mmhubbub_mask mcif_wb30_mask = { + MCIF_WB_COMMON_MASK_SH_LIST_DCN30(_MASK) +}; + +#define dsc_regsDCN20(id)\ +[id] = {\ + DSC_REG_LIST_DCN20(id)\ +} + +static const struct dcn20_dsc_registers dsc_regs[] = { + dsc_regsDCN20(0), + dsc_regsDCN20(1), + dsc_regsDCN20(2) +}; + +static const struct dcn20_dsc_shift dsc_shift = { + DSC_REG_LIST_SH_MASK_DCN20(__SHIFT) +}; + +static const struct dcn20_dsc_mask dsc_mask = { + DSC_REG_LIST_SH_MASK_DCN20(_MASK) +}; + +static const struct dcn30_mpc_registers mpc_regs = { + MPC_REG_LIST_DCN3_0(0), + MPC_REG_LIST_DCN3_0(1), + MPC_REG_LIST_DCN3_0(2), + MPC_REG_LIST_DCN3_0(3), + MPC_OUT_MUX_REG_LIST_DCN3_0(0), + MPC_OUT_MUX_REG_LIST_DCN3_0(1), + MPC_OUT_MUX_REG_LIST_DCN3_0(2), + MPC_OUT_MUX_REG_LIST_DCN3_0(3), + MPC_RMU_GLOBAL_REG_LIST_DCN3AG, + MPC_RMU_REG_LIST_DCN3AG(0), + MPC_RMU_REG_LIST_DCN3AG(1), + //MPC_RMU_REG_LIST_DCN3AG(2), + MPC_DWB_MUX_REG_LIST_DCN3_0(0), +}; + +static const struct dcn30_mpc_shift mpc_shift = { + MPC_COMMON_MASK_SH_LIST_DCN30(__SHIFT) +}; + +static const struct dcn30_mpc_mask mpc_mask = { + MPC_COMMON_MASK_SH_LIST_DCN30(_MASK) +}; + +#define optc_regs(id)\ +[id] = {OPTC_COMMON_REG_LIST_DCN3_1(id)} + +static const struct dcn_optc_registers optc_regs[] = { + optc_regs(0), + optc_regs(1), + optc_regs(2), + optc_regs(3) +}; + +static const struct dcn_optc_shift optc_shift = { + OPTC_COMMON_MASK_SH_LIST_DCN3_1(__SHIFT) +}; + +static const struct dcn_optc_mask optc_mask = { + OPTC_COMMON_MASK_SH_LIST_DCN3_1(_MASK) +}; + +#define hubp_regs(id)\ +[id] = {\ + HUBP_REG_LIST_DCN30(id)\ +} + +static const struct dcn_hubp2_registers hubp_regs[] = { + hubp_regs(0), + hubp_regs(1), + hubp_regs(2), + hubp_regs(3) +}; + + +static const struct dcn_hubp2_shift hubp_shift = { + HUBP_MASK_SH_LIST_DCN31(__SHIFT) +}; + +static const struct dcn_hubp2_mask hubp_mask = { + HUBP_MASK_SH_LIST_DCN31(_MASK) +}; +static const struct dcn_hubbub_registers hubbub_reg = { + HUBBUB_REG_LIST_DCN31(0) +}; + +static const struct dcn_hubbub_shift hubbub_shift = { + HUBBUB_MASK_SH_LIST_DCN31(__SHIFT) +}; + +static const struct dcn_hubbub_mask hubbub_mask = { + HUBBUB_MASK_SH_LIST_DCN31(_MASK) +}; + +static const struct dccg_registers dccg_regs = { + DCCG_REG_LIST_DCN31() +}; + +static const struct dccg_shift dccg_shift = { + DCCG_MASK_SH_LIST_DCN31(__SHIFT) +}; + +static const struct dccg_mask dccg_mask = { + DCCG_MASK_SH_LIST_DCN31(_MASK) +}; + + +#define SRII2(reg_name_pre, reg_name_post, id)\ + .reg_name_pre ## _ ## reg_name_post[id] = BASE(reg ## reg_name_pre \ + ## id ## _ ## reg_name_post ## _BASE_IDX) + \ + reg ## reg_name_pre ## id ## _ ## reg_name_post + + +#define HWSEQ_DCN31_REG_LIST()\ + SR(DCHUBBUB_GLOBAL_TIMER_CNTL), \ + SR(DCHUBBUB_ARB_HOSTVM_CNTL), \ + SR(DIO_MEM_PWR_CTRL), \ + SR(ODM_MEM_PWR_CTRL3), \ + SR(DMU_MEM_PWR_CNTL), \ + SR(MMHUBBUB_MEM_PWR_CNTL), \ + SR(DCCG_GATE_DISABLE_CNTL), \ + SR(DCCG_GATE_DISABLE_CNTL2), \ + SR(DCFCLK_CNTL),\ + SR(DC_MEM_GLOBAL_PWR_REQ_CNTL), \ + SRII(PIXEL_RATE_CNTL, OTG, 0), \ + SRII(PIXEL_RATE_CNTL, OTG, 1),\ + SRII(PIXEL_RATE_CNTL, OTG, 2),\ + SRII(PIXEL_RATE_CNTL, OTG, 3),\ + SRII(PHYPLL_PIXEL_RATE_CNTL, OTG, 0),\ + SRII(PHYPLL_PIXEL_RATE_CNTL, OTG, 1),\ + SRII(PHYPLL_PIXEL_RATE_CNTL, OTG, 2),\ + SRII(PHYPLL_PIXEL_RATE_CNTL, OTG, 3),\ + SR(MICROSECOND_TIME_BASE_DIV), \ + SR(MILLISECOND_TIME_BASE_DIV), \ + SR(DISPCLK_FREQ_CHANGE_CNTL), \ + SR(RBBMIF_TIMEOUT_DIS), \ + SR(RBBMIF_TIMEOUT_DIS_2), \ + SR(DCHUBBUB_CRC_CTRL), \ + SR(DPP_TOP0_DPP_CRC_CTRL), \ + SR(DPP_TOP0_DPP_CRC_VAL_B_A), \ + SR(DPP_TOP0_DPP_CRC_VAL_R_G), \ + SR(MPC_CRC_CTRL), \ + SR(MPC_CRC_RESULT_GB), \ + SR(MPC_CRC_RESULT_C), \ + SR(MPC_CRC_RESULT_AR), \ + SR(DOMAIN0_PG_CONFIG), \ + SR(DOMAIN1_PG_CONFIG), \ + SR(DOMAIN2_PG_CONFIG), \ + SR(DOMAIN3_PG_CONFIG), \ + SR(DOMAIN16_PG_CONFIG), \ + SR(DOMAIN17_PG_CONFIG), \ + SR(DOMAIN18_PG_CONFIG), \ + SR(DOMAIN0_PG_STATUS), \ + SR(DOMAIN1_PG_STATUS), \ + SR(DOMAIN2_PG_STATUS), \ + SR(DOMAIN3_PG_STATUS), \ + SR(DOMAIN16_PG_STATUS), \ + SR(DOMAIN17_PG_STATUS), \ + SR(DOMAIN18_PG_STATUS), \ + SR(D1VGA_CONTROL), \ + SR(D2VGA_CONTROL), \ + SR(D3VGA_CONTROL), \ + SR(D4VGA_CONTROL), \ + SR(D5VGA_CONTROL), \ + SR(D6VGA_CONTROL), \ + SR(DC_IP_REQUEST_CNTL), \ + SR(AZALIA_AUDIO_DTO), \ + SR(AZALIA_CONTROLLER_CLOCK_GATING), \ + SR(HPO_TOP_HW_CONTROL) + +static const struct dce_hwseq_registers hwseq_reg = { + HWSEQ_DCN31_REG_LIST() +}; + +#define HWSEQ_DCN31_MASK_SH_LIST(mask_sh)\ + HWSEQ_DCN_MASK_SH_LIST(mask_sh), \ + HWS_SF(, DCHUBBUB_GLOBAL_TIMER_CNTL, DCHUBBUB_GLOBAL_TIMER_REFDIV, mask_sh), \ + HWS_SF(, DCHUBBUB_ARB_HOSTVM_CNTL, DISABLE_HOSTVM_FORCE_ALLOW_PSTATE, mask_sh), \ + HWS_SF(, DOMAIN0_PG_CONFIG, DOMAIN_POWER_FORCEON, mask_sh), \ + HWS_SF(, DOMAIN0_PG_CONFIG, DOMAIN_POWER_GATE, mask_sh), \ + HWS_SF(, DOMAIN1_PG_CONFIG, DOMAIN_POWER_FORCEON, mask_sh), \ + HWS_SF(, DOMAIN1_PG_CONFIG, DOMAIN_POWER_GATE, mask_sh), \ + HWS_SF(, DOMAIN2_PG_CONFIG, DOMAIN_POWER_FORCEON, mask_sh), \ + HWS_SF(, DOMAIN2_PG_CONFIG, DOMAIN_POWER_GATE, mask_sh), \ + HWS_SF(, DOMAIN3_PG_CONFIG, DOMAIN_POWER_FORCEON, mask_sh), \ + HWS_SF(, DOMAIN3_PG_CONFIG, DOMAIN_POWER_GATE, mask_sh), \ + HWS_SF(, DOMAIN16_PG_CONFIG, DOMAIN_POWER_FORCEON, mask_sh), \ + HWS_SF(, DOMAIN16_PG_CONFIG, DOMAIN_POWER_GATE, mask_sh), \ + HWS_SF(, DOMAIN17_PG_CONFIG, DOMAIN_POWER_FORCEON, mask_sh), \ + HWS_SF(, DOMAIN17_PG_CONFIG, DOMAIN_POWER_GATE, mask_sh), \ + HWS_SF(, DOMAIN18_PG_CONFIG, DOMAIN_POWER_FORCEON, mask_sh), \ + HWS_SF(, DOMAIN18_PG_CONFIG, DOMAIN_POWER_GATE, mask_sh), \ + HWS_SF(, DOMAIN0_PG_STATUS, DOMAIN_PGFSM_PWR_STATUS, mask_sh), \ + HWS_SF(, DOMAIN1_PG_STATUS, DOMAIN_PGFSM_PWR_STATUS, mask_sh), \ + HWS_SF(, DOMAIN2_PG_STATUS, DOMAIN_PGFSM_PWR_STATUS, mask_sh), \ + HWS_SF(, DOMAIN3_PG_STATUS, DOMAIN_PGFSM_PWR_STATUS, mask_sh), \ + HWS_SF(, DOMAIN16_PG_STATUS, DOMAIN_PGFSM_PWR_STATUS, mask_sh), \ + HWS_SF(, DOMAIN17_PG_STATUS, DOMAIN_PGFSM_PWR_STATUS, mask_sh), \ + HWS_SF(, DOMAIN18_PG_STATUS, DOMAIN_PGFSM_PWR_STATUS, mask_sh), \ + HWS_SF(, DC_IP_REQUEST_CNTL, IP_REQUEST_EN, mask_sh), \ + HWS_SF(, AZALIA_AUDIO_DTO, AZALIA_AUDIO_DTO_MODULE, mask_sh), \ + HWS_SF(, HPO_TOP_CLOCK_CONTROL, HPO_HDMISTREAMCLK_G_GATE_DIS, mask_sh), \ + HWS_SF(, DMU_MEM_PWR_CNTL, DMCU_ERAM_MEM_PWR_FORCE, mask_sh), \ + HWS_SF(, ODM_MEM_PWR_CTRL3, ODM_MEM_UNASSIGNED_PWR_MODE, mask_sh), \ + HWS_SF(, ODM_MEM_PWR_CTRL3, ODM_MEM_VBLANK_PWR_MODE, mask_sh), \ + HWS_SF(, MMHUBBUB_MEM_PWR_CNTL, VGA_MEM_PWR_FORCE, mask_sh), \ + HWS_SF(, DIO_MEM_PWR_CTRL, I2C_LIGHT_SLEEP_FORCE, mask_sh), \ + HWS_SF(, HPO_TOP_HW_CONTROL, HPO_IO_EN, mask_sh) + +static const struct dce_hwseq_shift hwseq_shift = { + HWSEQ_DCN31_MASK_SH_LIST(__SHIFT) +}; + +static const struct dce_hwseq_mask hwseq_mask = { + HWSEQ_DCN31_MASK_SH_LIST(_MASK) +}; +#define vmid_regs(id)\ +[id] = {\ + DCN20_VMID_REG_LIST(id)\ +} + +static const struct dcn_vmid_registers vmid_regs[] = { + vmid_regs(0), + vmid_regs(1), + vmid_regs(2), + vmid_regs(3), + vmid_regs(4), + vmid_regs(5), + vmid_regs(6), + vmid_regs(7), + vmid_regs(8), + vmid_regs(9), + vmid_regs(10), + vmid_regs(11), + vmid_regs(12), + vmid_regs(13), + vmid_regs(14), + vmid_regs(15) +}; + +static const struct dcn20_vmid_shift vmid_shifts = { + DCN20_VMID_MASK_SH_LIST(__SHIFT) +}; + +static const struct dcn20_vmid_mask vmid_masks = { + DCN20_VMID_MASK_SH_LIST(_MASK) +}; + +static const struct resource_caps res_cap_dcn31 = { + .num_timing_generator = 4, + .num_opp = 4, + .num_video_plane = 4, + .num_audio = 5, + .num_stream_encoder = 5, + .num_dig_link_enc = 5, + .num_hpo_dp_stream_encoder = 4, + .num_hpo_dp_link_encoder = 2, + .num_pll = 5, + .num_dwb = 1, + .num_ddc = 5, + .num_vmid = 16, + .num_mpc_3dlut = 2, + .num_dsc = 3, +}; + +static const struct dc_plane_cap plane_cap = { + .type = DC_PLANE_TYPE_DCN_UNIVERSAL, + .per_pixel_alpha = true, + + .pixel_format_support = { + .argb8888 = true, + .nv12 = true, + .fp16 = true, + .p010 = true, + .ayuv = false, + }, + + .max_upscale_factor = { + .argb8888 = 16000, + .nv12 = 16000, + .fp16 = 16000 + }, + + // 6:1 downscaling ratio: 1000/6 = 166.666 + .max_downscale_factor = { + .argb8888 = 167, + .nv12 = 167, + .fp16 = 167 + }, + 64, + 64 +}; + +static const struct dc_debug_options debug_defaults_drv = { + .disable_z10 = true, /*hw not support it*/ + .disable_dmcu = true, + .force_abm_enable = false, + .timing_trace = false, + .clock_trace = true, + .disable_pplib_clock_request = false, + .pipe_split_policy = MPC_SPLIT_DYNAMIC, + .force_single_disp_pipe_split = false, + .disable_dcc = DCC_ENABLE, + .vsr_support = true, + .performance_trace = false, + .max_downscale_src_width = 4096,/*upto true 4k*/ + .disable_pplib_wm_range = false, + .scl_reset_length10 = true, + .sanity_checks = false, + .underflow_assert_delay_us = 0xFFFFFFFF, + .dwb_fi_phase = -1, // -1 = disable, + .dmub_command_table = true, + .pstate_enabled = true, + .use_max_lb = true, + .enable_mem_low_power = { + .bits = { + .vga = true, + .i2c = true, + .dmcu = false, // This is previously known to cause hang on S3 cycles if enabled + .dscl = true, + .cm = true, + .mpc = true, + .optc = true, + .vpg = true, + .afmt = true, + } + }, + .enable_legacy_fast_update = true, + .using_dml2 = false, +}; + +static const struct dc_panel_config panel_config_defaults = { + .psr = { + .disable_psr = false, + .disallow_psrsu = false, + .disallow_replay = false, + }, + .ilr = { + .optimize_edp_link_rate = true, + }, +}; + +static void dcn31_dpp_destroy(struct dpp **dpp) +{ + kfree(TO_DCN20_DPP(*dpp)); + *dpp = NULL; +} + +static struct dpp *dcn31_dpp_create( + struct dc_context *ctx, + uint32_t inst) +{ + struct dcn3_dpp *dpp = + kzalloc(sizeof(struct dcn3_dpp), GFP_KERNEL); + + if (!dpp) + return NULL; + + if (dpp3_construct(dpp, ctx, inst, + &dpp_regs[inst], &tf_shift, &tf_mask)) + return &dpp->base; + + BREAK_TO_DEBUGGER(); + kfree(dpp); + return NULL; +} + +static struct output_pixel_processor *dcn31_opp_create( + struct dc_context *ctx, uint32_t inst) +{ + struct dcn20_opp *opp = + kzalloc(sizeof(struct dcn20_opp), GFP_KERNEL); + + if (!opp) { + BREAK_TO_DEBUGGER(); + return NULL; + } + + dcn20_opp_construct(opp, ctx, inst, + &opp_regs[inst], &opp_shift, &opp_mask); + return &opp->base; +} + +static struct dce_aux *dcn31_aux_engine_create( + struct dc_context *ctx, + uint32_t inst) +{ + struct aux_engine_dce110 *aux_engine = + kzalloc(sizeof(struct aux_engine_dce110), GFP_KERNEL); + + if (!aux_engine) + return NULL; + + dce110_aux_engine_construct(aux_engine, ctx, inst, + SW_AUX_TIMEOUT_PERIOD_MULTIPLIER * AUX_TIMEOUT_PERIOD, + &aux_engine_regs[inst], + &aux_mask, + &aux_shift, + ctx->dc->caps.extended_aux_timeout_support); + + return &aux_engine->base; +} +#define i2c_inst_regs(id) { I2C_HW_ENGINE_COMMON_REG_LIST_DCN30(id) } + +static const struct dce_i2c_registers i2c_hw_regs[] = { + i2c_inst_regs(1), + i2c_inst_regs(2), + i2c_inst_regs(3), + i2c_inst_regs(4), + i2c_inst_regs(5), +}; + +static const struct dce_i2c_shift i2c_shifts = { + I2C_COMMON_MASK_SH_LIST_DCN30(__SHIFT) +}; + +static const struct dce_i2c_mask i2c_masks = { + I2C_COMMON_MASK_SH_LIST_DCN30(_MASK) +}; + +static struct dce_i2c_hw *dcn31_i2c_hw_create( + struct dc_context *ctx, + uint32_t inst) +{ + struct dce_i2c_hw *dce_i2c_hw = + kzalloc(sizeof(struct dce_i2c_hw), GFP_KERNEL); + + if (!dce_i2c_hw) + return NULL; + + dcn2_i2c_hw_construct(dce_i2c_hw, ctx, inst, + &i2c_hw_regs[inst], &i2c_shifts, &i2c_masks); + + return dce_i2c_hw; +} +static struct mpc *dcn31_mpc_create( + struct dc_context *ctx, + int num_mpcc, + int num_rmu) +{ + struct dcn30_mpc *mpc30 = kzalloc(sizeof(struct dcn30_mpc), + GFP_KERNEL); + + if (!mpc30) + return NULL; + + dcn30_mpc_construct(mpc30, ctx, + &mpc_regs, + &mpc_shift, + &mpc_mask, + num_mpcc, + num_rmu); + + return &mpc30->base; +} + +static struct hubbub *dcn31_hubbub_create(struct dc_context *ctx) +{ + int i; + + struct dcn20_hubbub *hubbub3 = kzalloc(sizeof(struct dcn20_hubbub), + GFP_KERNEL); + + if (!hubbub3) + return NULL; + + hubbub31_construct(hubbub3, ctx, + &hubbub_reg, + &hubbub_shift, + &hubbub_mask, + dcn3_16_ip.det_buffer_size_kbytes, + dcn3_16_ip.pixel_chunk_size_kbytes, + dcn3_16_ip.config_return_buffer_size_in_kbytes); + + + for (i = 0; i < res_cap_dcn31.num_vmid; i++) { + struct dcn20_vmid *vmid = &hubbub3->vmid[i]; + + vmid->ctx = ctx; + + vmid->regs = &vmid_regs[i]; + vmid->shifts = &vmid_shifts; + vmid->masks = &vmid_masks; + } + + return &hubbub3->base; +} + +static struct timing_generator *dcn31_timing_generator_create( + struct dc_context *ctx, + uint32_t instance) +{ + struct optc *tgn10 = + kzalloc(sizeof(struct optc), GFP_KERNEL); + + if (!tgn10) + return NULL; + + tgn10->base.inst = instance; + tgn10->base.ctx = ctx; + + tgn10->tg_regs = &optc_regs[instance]; + tgn10->tg_shift = &optc_shift; + tgn10->tg_mask = &optc_mask; + + dcn31_timing_generator_init(tgn10); + + return &tgn10->base; +} + +static const struct encoder_feature_support link_enc_feature = { + .max_hdmi_deep_color = COLOR_DEPTH_121212, + .max_hdmi_pixel_clock = 600000, + .hdmi_ycbcr420_supported = true, + .dp_ycbcr420_supported = true, + .fec_supported = true, + .flags.bits.IS_HBR2_CAPABLE = true, + .flags.bits.IS_HBR3_CAPABLE = true, + .flags.bits.IS_TPS3_CAPABLE = true, + .flags.bits.IS_TPS4_CAPABLE = true +}; + +static struct link_encoder *dcn31_link_encoder_create( + struct dc_context *ctx, + const struct encoder_init_data *enc_init_data) +{ + struct dcn20_link_encoder *enc20 = + kzalloc(sizeof(struct dcn20_link_encoder), GFP_KERNEL); + + if (!enc20) + return NULL; + + dcn31_link_encoder_construct(enc20, + enc_init_data, + &link_enc_feature, + &link_enc_regs[enc_init_data->transmitter], + &link_enc_aux_regs[enc_init_data->channel - 1], + &link_enc_hpd_regs[enc_init_data->hpd_source], + &le_shift, + &le_mask); + + return &enc20->enc10.base; +} + +/* Create a minimal link encoder object not associated with a particular + * physical connector. + * resource_funcs.link_enc_create_minimal + */ +static struct link_encoder *dcn31_link_enc_create_minimal( + struct dc_context *ctx, enum engine_id eng_id) +{ + struct dcn20_link_encoder *enc20; + + if ((eng_id - ENGINE_ID_DIGA) > ctx->dc->res_pool->res_cap->num_dig_link_enc) + return NULL; + + enc20 = kzalloc(sizeof(struct dcn20_link_encoder), GFP_KERNEL); + if (!enc20) + return NULL; + + dcn31_link_encoder_construct_minimal( + enc20, + ctx, + &link_enc_feature, + &link_enc_regs[eng_id - ENGINE_ID_DIGA], + eng_id); + + return &enc20->enc10.base; +} + +static struct panel_cntl *dcn31_panel_cntl_create(const struct panel_cntl_init_data *init_data) +{ + struct dcn31_panel_cntl *panel_cntl = + kzalloc(sizeof(struct dcn31_panel_cntl), GFP_KERNEL); + + if (!panel_cntl) + return NULL; + + dcn31_panel_cntl_construct(panel_cntl, init_data); + + return &panel_cntl->base; +} + +static void read_dce_straps( + struct dc_context *ctx, + struct resource_straps *straps) +{ + generic_reg_get(ctx, regDC_PINSTRAPS + BASE(regDC_PINSTRAPS_BASE_IDX), + FN(DC_PINSTRAPS, DC_PINSTRAPS_AUDIO), &straps->dc_pinstraps_audio); + +} + +static struct audio *dcn31_create_audio( + struct dc_context *ctx, unsigned int inst) +{ + return dce_audio_create(ctx, inst, + &audio_regs[inst], &audio_shift, &audio_mask); +} + +static struct vpg *dcn31_vpg_create( + struct dc_context *ctx, + uint32_t inst) +{ + struct dcn31_vpg *vpg31 = kzalloc(sizeof(struct dcn31_vpg), GFP_KERNEL); + + if (!vpg31) + return NULL; + + vpg31_construct(vpg31, ctx, inst, + &vpg_regs[inst], + &vpg_shift, + &vpg_mask); + + return &vpg31->base; +} + +static struct afmt *dcn31_afmt_create( + struct dc_context *ctx, + uint32_t inst) +{ + struct dcn31_afmt *afmt31 = kzalloc(sizeof(struct dcn31_afmt), GFP_KERNEL); + + if (!afmt31) + return NULL; + + afmt31_construct(afmt31, ctx, inst, + &afmt_regs[inst], + &afmt_shift, + &afmt_mask); + + // Light sleep by default, no need to power down here + + return &afmt31->base; +} + + +static struct apg *dcn31_apg_create( + struct dc_context *ctx, + uint32_t inst) +{ + struct dcn31_apg *apg31 = kzalloc(sizeof(struct dcn31_apg), GFP_KERNEL); + + if (!apg31) + return NULL; + + apg31_construct(apg31, ctx, inst, + &apg_regs[inst], + &apg_shift, + &apg_mask); + + return &apg31->base; +} + + +static struct stream_encoder *dcn316_stream_encoder_create( + enum engine_id eng_id, + struct dc_context *ctx) +{ + struct dcn10_stream_encoder *enc1; + struct vpg *vpg; + struct afmt *afmt; + int vpg_inst; + int afmt_inst; + + /* Mapping of VPG, AFMT, DME register blocks to DIO block instance */ + if (eng_id <= ENGINE_ID_DIGF) { + vpg_inst = eng_id; + afmt_inst = eng_id; + } else + return NULL; + + enc1 = kzalloc(sizeof(struct dcn10_stream_encoder), GFP_KERNEL); + vpg = dcn31_vpg_create(ctx, vpg_inst); + afmt = dcn31_afmt_create(ctx, afmt_inst); + + if (!enc1 || !vpg || !afmt) { + kfree(enc1); + kfree(vpg); + kfree(afmt); + return NULL; + } + + dcn30_dio_stream_encoder_construct(enc1, ctx, ctx->dc_bios, + eng_id, vpg, afmt, + &stream_enc_regs[eng_id], + &se_shift, &se_mask); + + return &enc1->base; +} + + +static struct hpo_dp_stream_encoder *dcn31_hpo_dp_stream_encoder_create( + enum engine_id eng_id, + struct dc_context *ctx) +{ + struct dcn31_hpo_dp_stream_encoder *hpo_dp_enc31; + struct vpg *vpg; + struct apg *apg; + uint32_t hpo_dp_inst; + uint32_t vpg_inst; + uint32_t apg_inst; + + ASSERT((eng_id >= ENGINE_ID_HPO_DP_0) && (eng_id <= ENGINE_ID_HPO_DP_3)); + hpo_dp_inst = eng_id - ENGINE_ID_HPO_DP_0; + + /* Mapping of VPG register blocks to HPO DP block instance: + * VPG[6] -> HPO_DP[0] + * VPG[7] -> HPO_DP[1] + * VPG[8] -> HPO_DP[2] + * VPG[9] -> HPO_DP[3] + */ + vpg_inst = hpo_dp_inst + 6; + + /* Mapping of APG register blocks to HPO DP block instance: + * APG[0] -> HPO_DP[0] + * APG[1] -> HPO_DP[1] + * APG[2] -> HPO_DP[2] + * APG[3] -> HPO_DP[3] + */ + apg_inst = hpo_dp_inst; + + /* allocate HPO stream encoder and create VPG sub-block */ + hpo_dp_enc31 = kzalloc(sizeof(struct dcn31_hpo_dp_stream_encoder), GFP_KERNEL); + vpg = dcn31_vpg_create(ctx, vpg_inst); + apg = dcn31_apg_create(ctx, apg_inst); + + if (!hpo_dp_enc31 || !vpg || !apg) { + kfree(hpo_dp_enc31); + kfree(vpg); + kfree(apg); + return NULL; + } + + dcn31_hpo_dp_stream_encoder_construct(hpo_dp_enc31, ctx, ctx->dc_bios, + hpo_dp_inst, eng_id, vpg, apg, + &hpo_dp_stream_enc_regs[hpo_dp_inst], + &hpo_dp_se_shift, &hpo_dp_se_mask); + + return &hpo_dp_enc31->base; +} + +static struct hpo_dp_link_encoder *dcn31_hpo_dp_link_encoder_create( + uint8_t inst, + struct dc_context *ctx) +{ + struct dcn31_hpo_dp_link_encoder *hpo_dp_enc31; + + /* allocate HPO link encoder */ + hpo_dp_enc31 = kzalloc(sizeof(struct dcn31_hpo_dp_link_encoder), GFP_KERNEL); + + hpo_dp_link_encoder31_construct(hpo_dp_enc31, ctx, inst, + &hpo_dp_link_enc_regs[inst], + &hpo_dp_le_shift, &hpo_dp_le_mask); + + return &hpo_dp_enc31->base; +} + + +static struct dce_hwseq *dcn31_hwseq_create( + struct dc_context *ctx) +{ + struct dce_hwseq *hws = kzalloc(sizeof(struct dce_hwseq), GFP_KERNEL); + + if (hws) { + hws->ctx = ctx; + hws->regs = &hwseq_reg; + hws->shifts = &hwseq_shift; + hws->masks = &hwseq_mask; + } + return hws; +} +static const struct resource_create_funcs res_create_funcs = { + .read_dce_straps = read_dce_straps, + .create_audio = dcn31_create_audio, + .create_stream_encoder = dcn316_stream_encoder_create, + .create_hpo_dp_stream_encoder = dcn31_hpo_dp_stream_encoder_create, + .create_hpo_dp_link_encoder = dcn31_hpo_dp_link_encoder_create, + .create_hwseq = dcn31_hwseq_create, +}; + +static void dcn316_resource_destruct(struct dcn316_resource_pool *pool) +{ + unsigned int i; + + for (i = 0; i < pool->base.stream_enc_count; i++) { + if (pool->base.stream_enc[i] != NULL) { + if (pool->base.stream_enc[i]->vpg != NULL) { + kfree(DCN30_VPG_FROM_VPG(pool->base.stream_enc[i]->vpg)); + pool->base.stream_enc[i]->vpg = NULL; + } + if (pool->base.stream_enc[i]->afmt != NULL) { + kfree(DCN30_AFMT_FROM_AFMT(pool->base.stream_enc[i]->afmt)); + pool->base.stream_enc[i]->afmt = NULL; + } + kfree(DCN10STRENC_FROM_STRENC(pool->base.stream_enc[i])); + pool->base.stream_enc[i] = NULL; + } + } + + for (i = 0; i < pool->base.hpo_dp_stream_enc_count; i++) { + if (pool->base.hpo_dp_stream_enc[i] != NULL) { + if (pool->base.hpo_dp_stream_enc[i]->vpg != NULL) { + kfree(DCN30_VPG_FROM_VPG(pool->base.hpo_dp_stream_enc[i]->vpg)); + pool->base.hpo_dp_stream_enc[i]->vpg = NULL; + } + if (pool->base.hpo_dp_stream_enc[i]->apg != NULL) { + kfree(DCN31_APG_FROM_APG(pool->base.hpo_dp_stream_enc[i]->apg)); + pool->base.hpo_dp_stream_enc[i]->apg = NULL; + } + kfree(DCN3_1_HPO_DP_STREAM_ENC_FROM_HPO_STREAM_ENC(pool->base.hpo_dp_stream_enc[i])); + pool->base.hpo_dp_stream_enc[i] = NULL; + } + } + + for (i = 0; i < pool->base.hpo_dp_link_enc_count; i++) { + if (pool->base.hpo_dp_link_enc[i] != NULL) { + kfree(DCN3_1_HPO_DP_LINK_ENC_FROM_HPO_LINK_ENC(pool->base.hpo_dp_link_enc[i])); + pool->base.hpo_dp_link_enc[i] = NULL; + } + } + + for (i = 0; i < pool->base.res_cap->num_dsc; i++) { + if (pool->base.dscs[i] != NULL) + dcn20_dsc_destroy(&pool->base.dscs[i]); + } + + if (pool->base.mpc != NULL) { + kfree(TO_DCN20_MPC(pool->base.mpc)); + pool->base.mpc = NULL; + } + if (pool->base.hubbub != NULL) { + kfree(pool->base.hubbub); + pool->base.hubbub = NULL; + } + for (i = 0; i < pool->base.pipe_count; i++) { + if (pool->base.dpps[i] != NULL) + dcn31_dpp_destroy(&pool->base.dpps[i]); + + if (pool->base.ipps[i] != NULL) + pool->base.ipps[i]->funcs->ipp_destroy(&pool->base.ipps[i]); + + if (pool->base.hubps[i] != NULL) { + kfree(TO_DCN20_HUBP(pool->base.hubps[i])); + pool->base.hubps[i] = NULL; + } + + if (pool->base.irqs != NULL) { + dal_irq_service_destroy(&pool->base.irqs); + } + } + + for (i = 0; i < pool->base.res_cap->num_ddc; i++) { + if (pool->base.engines[i] != NULL) + dce110_engine_destroy(&pool->base.engines[i]); + if (pool->base.hw_i2cs[i] != NULL) { + kfree(pool->base.hw_i2cs[i]); + pool->base.hw_i2cs[i] = NULL; + } + if (pool->base.sw_i2cs[i] != NULL) { + kfree(pool->base.sw_i2cs[i]); + pool->base.sw_i2cs[i] = NULL; + } + } + + for (i = 0; i < pool->base.res_cap->num_opp; i++) { + if (pool->base.opps[i] != NULL) + pool->base.opps[i]->funcs->opp_destroy(&pool->base.opps[i]); + } + + for (i = 0; i < pool->base.res_cap->num_timing_generator; i++) { + if (pool->base.timing_generators[i] != NULL) { + kfree(DCN10TG_FROM_TG(pool->base.timing_generators[i])); + pool->base.timing_generators[i] = NULL; + } + } + + for (i = 0; i < pool->base.res_cap->num_dwb; i++) { + if (pool->base.dwbc[i] != NULL) { + kfree(TO_DCN30_DWBC(pool->base.dwbc[i])); + pool->base.dwbc[i] = NULL; + } + if (pool->base.mcif_wb[i] != NULL) { + kfree(TO_DCN30_MMHUBBUB(pool->base.mcif_wb[i])); + pool->base.mcif_wb[i] = NULL; + } + } + + for (i = 0; i < pool->base.audio_count; i++) { + if (pool->base.audios[i]) + dce_aud_destroy(&pool->base.audios[i]); + } + + for (i = 0; i < pool->base.clk_src_count; i++) { + if (pool->base.clock_sources[i] != NULL) { + dcn20_clock_source_destroy(&pool->base.clock_sources[i]); + pool->base.clock_sources[i] = NULL; + } + } + + for (i = 0; i < pool->base.res_cap->num_mpc_3dlut; i++) { + if (pool->base.mpc_lut[i] != NULL) { + dc_3dlut_func_release(pool->base.mpc_lut[i]); + pool->base.mpc_lut[i] = NULL; + } + if (pool->base.mpc_shaper[i] != NULL) { + dc_transfer_func_release(pool->base.mpc_shaper[i]); + pool->base.mpc_shaper[i] = NULL; + } + } + + if (pool->base.dp_clock_source != NULL) { + dcn20_clock_source_destroy(&pool->base.dp_clock_source); + pool->base.dp_clock_source = NULL; + } + + for (i = 0; i < pool->base.res_cap->num_timing_generator; i++) { + if (pool->base.multiple_abms[i] != NULL) + dce_abm_destroy(&pool->base.multiple_abms[i]); + } + + if (pool->base.psr != NULL) + dmub_psr_destroy(&pool->base.psr); + + if (pool->base.dccg != NULL) + dcn_dccg_destroy(&pool->base.dccg); +} + +static struct hubp *dcn31_hubp_create( + struct dc_context *ctx, + uint32_t inst) +{ + struct dcn20_hubp *hubp2 = + kzalloc(sizeof(struct dcn20_hubp), GFP_KERNEL); + + if (!hubp2) + return NULL; + + if (hubp31_construct(hubp2, ctx, inst, + &hubp_regs[inst], &hubp_shift, &hubp_mask)) + return &hubp2->base; + + BREAK_TO_DEBUGGER(); + kfree(hubp2); + return NULL; +} + +static bool dcn31_dwbc_create(struct dc_context *ctx, struct resource_pool *pool) +{ + int i; + uint32_t pipe_count = pool->res_cap->num_dwb; + + for (i = 0; i < pipe_count; i++) { + struct dcn30_dwbc *dwbc30 = kzalloc(sizeof(struct dcn30_dwbc), + GFP_KERNEL); + + if (!dwbc30) { + dm_error("DC: failed to create dwbc30!\n"); + return false; + } + + dcn30_dwbc_construct(dwbc30, ctx, + &dwbc30_regs[i], + &dwbc30_shift, + &dwbc30_mask, + i); + + pool->dwbc[i] = &dwbc30->base; + } + return true; +} + +static bool dcn31_mmhubbub_create(struct dc_context *ctx, struct resource_pool *pool) +{ + int i; + uint32_t pipe_count = pool->res_cap->num_dwb; + + for (i = 0; i < pipe_count; i++) { + struct dcn30_mmhubbub *mcif_wb30 = kzalloc(sizeof(struct dcn30_mmhubbub), + GFP_KERNEL); + + if (!mcif_wb30) { + dm_error("DC: failed to create mcif_wb30!\n"); + return false; + } + + dcn30_mmhubbub_construct(mcif_wb30, ctx, + &mcif_wb30_regs[i], + &mcif_wb30_shift, + &mcif_wb30_mask, + i); + + pool->mcif_wb[i] = &mcif_wb30->base; + } + return true; +} + +static struct display_stream_compressor *dcn31_dsc_create( + struct dc_context *ctx, uint32_t inst) +{ + struct dcn20_dsc *dsc = + kzalloc(sizeof(struct dcn20_dsc), GFP_KERNEL); + + if (!dsc) { + BREAK_TO_DEBUGGER(); + return NULL; + } + + dsc2_construct(dsc, ctx, inst, &dsc_regs[inst], &dsc_shift, &dsc_mask); + return &dsc->base; +} + +static void dcn316_destroy_resource_pool(struct resource_pool **pool) +{ + struct dcn316_resource_pool *dcn31_pool = TO_DCN316_RES_POOL(*pool); + + dcn316_resource_destruct(dcn31_pool); + kfree(dcn31_pool); + *pool = NULL; +} + +static struct clock_source *dcn31_clock_source_create( + struct dc_context *ctx, + struct dc_bios *bios, + enum clock_source_id id, + const struct dce110_clk_src_regs *regs, + bool dp_clk_src) +{ + struct dce110_clk_src *clk_src = + kzalloc(sizeof(struct dce110_clk_src), GFP_KERNEL); + + if (!clk_src) + return NULL; + + if (dcn31_clk_src_construct(clk_src, ctx, bios, id, + regs, &cs_shift, &cs_mask)) { + clk_src->base.dp_clk_src = dp_clk_src; + return &clk_src->base; + } + + kfree(clk_src); + + BREAK_TO_DEBUGGER(); + return NULL; +} + +static bool is_dual_plane(enum surface_pixel_format format) +{ + return format >= SURFACE_PIXEL_FORMAT_VIDEO_BEGIN || format == SURFACE_PIXEL_FORMAT_GRPH_RGBE_ALPHA; +} + +static int dcn316_populate_dml_pipes_from_context( + struct dc *dc, struct dc_state *context, + display_e2e_pipe_params_st *pipes, + bool fast_validate) +{ + int i, pipe_cnt; + struct resource_context *res_ctx = &context->res_ctx; + struct pipe_ctx *pipe; + const int max_usable_det = context->bw_ctx.dml.ip.config_return_buffer_size_in_kbytes - DCN3_16_MIN_COMPBUF_SIZE_KB; + + DC_FP_START(); + dcn31x_populate_dml_pipes_from_context(dc, context, pipes, fast_validate); + DC_FP_END(); + + for (i = 0, pipe_cnt = 0; i < dc->res_pool->pipe_count; i++) { + struct dc_crtc_timing *timing; + + if (!res_ctx->pipe_ctx[i].stream) + continue; + pipe = &res_ctx->pipe_ctx[i]; + timing = &pipe->stream->timing; + + /* + * Immediate flip can be set dynamically after enabling the plane. + * We need to require support for immediate flip or underflow can be + * intermittently experienced depending on peak b/w requirements. + */ + pipes[pipe_cnt].pipe.src.immediate_flip = true; + + pipes[pipe_cnt].pipe.src.unbounded_req_mode = false; + pipes[pipe_cnt].pipe.dest.vfront_porch = timing->v_front_porch; + pipes[pipe_cnt].pipe.src.dcc_rate = 3; + pipes[pipe_cnt].dout.dsc_input_bpc = 0; + DC_FP_START(); + dcn31_zero_pipe_dcc_fraction(pipes, pipe_cnt); + DC_FP_END(); + + if (pipes[pipe_cnt].dout.dsc_enable) { + switch (timing->display_color_depth) { + case COLOR_DEPTH_888: + pipes[pipe_cnt].dout.dsc_input_bpc = 8; + break; + case COLOR_DEPTH_101010: + pipes[pipe_cnt].dout.dsc_input_bpc = 10; + break; + case COLOR_DEPTH_121212: + pipes[pipe_cnt].dout.dsc_input_bpc = 12; + break; + default: + ASSERT(0); + break; + } + } + + pipe_cnt++; + } + + if (pipe_cnt) + context->bw_ctx.dml.ip.det_buffer_size_kbytes = + (max_usable_det / DCN3_16_CRB_SEGMENT_SIZE_KB / pipe_cnt) * DCN3_16_CRB_SEGMENT_SIZE_KB; + if (context->bw_ctx.dml.ip.det_buffer_size_kbytes > DCN3_16_MAX_DET_SIZE) + context->bw_ctx.dml.ip.det_buffer_size_kbytes = DCN3_16_MAX_DET_SIZE; + ASSERT(context->bw_ctx.dml.ip.det_buffer_size_kbytes >= DCN3_16_DEFAULT_DET_SIZE); + dc->config.enable_4to1MPC = false; + if (pipe_cnt == 1 && pipe->plane_state && !dc->debug.disable_z9_mpc) { + if (is_dual_plane(pipe->plane_state->format) + && pipe->plane_state->src_rect.width <= 1920 && pipe->plane_state->src_rect.height <= 1080) { + dc->config.enable_4to1MPC = true; + context->bw_ctx.dml.ip.det_buffer_size_kbytes = + (max_usable_det / DCN3_16_CRB_SEGMENT_SIZE_KB / 4) * DCN3_16_CRB_SEGMENT_SIZE_KB; + } else if (!is_dual_plane(pipe->plane_state->format)) { + context->bw_ctx.dml.ip.det_buffer_size_kbytes = 192; + pipes[0].pipe.src.unbounded_req_mode = true; + } + } + + return pipe_cnt; +} + +static void dcn316_get_panel_config_defaults(struct dc_panel_config *panel_config) +{ + *panel_config = panel_config_defaults; +} + +static struct dc_cap_funcs cap_funcs = { + .get_dcc_compression_cap = dcn20_get_dcc_compression_cap +}; + +static struct resource_funcs dcn316_res_pool_funcs = { + .destroy = dcn316_destroy_resource_pool, + .link_enc_create = dcn31_link_encoder_create, + .link_enc_create_minimal = dcn31_link_enc_create_minimal, + .link_encs_assign = link_enc_cfg_link_encs_assign, + .link_enc_unassign = link_enc_cfg_link_enc_unassign, + .panel_cntl_create = dcn31_panel_cntl_create, + .validate_bandwidth = dcn31_validate_bandwidth, + .calculate_wm_and_dlg = dcn31_calculate_wm_and_dlg, + .update_soc_for_wm_a = dcn31_update_soc_for_wm_a, + .populate_dml_pipes = dcn316_populate_dml_pipes_from_context, + .acquire_free_pipe_as_secondary_dpp_pipe = dcn20_acquire_free_pipe_for_layer, + .release_pipe = dcn20_release_pipe, + .add_stream_to_ctx = dcn30_add_stream_to_ctx, + .add_dsc_to_stream_resource = dcn20_add_dsc_to_stream_resource, + .remove_stream_from_ctx = dcn20_remove_stream_from_ctx, + .populate_dml_writeback_from_context = dcn31_populate_dml_writeback_from_context, + .set_mcif_arb_params = dcn31_set_mcif_arb_params, + .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 = dcn316_update_bw_bounding_box, + .patch_unknown_plane_state = dcn20_patch_unknown_plane_state, + .get_panel_config_defaults = dcn316_get_panel_config_defaults, +}; + +static bool dcn316_resource_construct( + uint8_t num_virtual_links, + struct dc *dc, + struct dcn316_resource_pool *pool) +{ + int i; + struct dc_context *ctx = dc->ctx; + struct irq_service_init_data init_data; + + ctx->dc_bios->regs = &bios_regs; + + pool->base.res_cap = &res_cap_dcn31; + + pool->base.funcs = &dcn316_res_pool_funcs; + + /************************************************* + * Resource + asic cap harcoding * + *************************************************/ + pool->base.underlay_pipe_index = NO_UNDERLAY_PIPE; + pool->base.pipe_count = pool->base.res_cap->num_timing_generator; + pool->base.mpcc_count = pool->base.res_cap->num_timing_generator; + dc->caps.max_downscale_ratio = 600; + dc->caps.i2c_speed_in_khz = 100; + dc->caps.i2c_speed_in_khz_hdcp = 5; /*1.5 w/a applied by default*/ + dc->caps.max_cursor_size = 256; + dc->caps.min_horizontal_blanking_period = 80; + dc->caps.dmdata_alloc_size = 2048; + dc->caps.max_slave_planes = 2; + dc->caps.max_slave_yuv_planes = 2; + dc->caps.max_slave_rgb_planes = 2; + dc->caps.post_blend_color_processing = true; + dc->caps.force_dp_tps4_for_cp2520 = true; + if (dc->config.forceHBR2CP2520) + dc->caps.force_dp_tps4_for_cp2520 = false; + dc->caps.dp_hpo = true; + dc->caps.dp_hdmi21_pcon_support = true; + dc->caps.edp_dsc_support = true; + dc->caps.extended_aux_timeout_support = true; + dc->caps.dmcub_support = true; + dc->caps.is_apu = true; + + /* Color pipeline capabilities */ + dc->caps.color.dpp.dcn_arch = 1; + dc->caps.color.dpp.input_lut_shared = 0; + dc->caps.color.dpp.icsc = 1; + dc->caps.color.dpp.dgam_ram = 0; // must use gamma_corr + dc->caps.color.dpp.dgam_rom_caps.srgb = 1; + dc->caps.color.dpp.dgam_rom_caps.bt2020 = 1; + dc->caps.color.dpp.dgam_rom_caps.gamma2_2 = 1; + dc->caps.color.dpp.dgam_rom_caps.pq = 1; + dc->caps.color.dpp.dgam_rom_caps.hlg = 1; + dc->caps.color.dpp.post_csc = 1; + dc->caps.color.dpp.gamma_corr = 1; + dc->caps.color.dpp.dgam_rom_for_yuv = 0; + + dc->caps.color.dpp.hw_3d_lut = 1; + dc->caps.color.dpp.ogam_ram = 1; + // no OGAM ROM on DCN301 + dc->caps.color.dpp.ogam_rom_caps.srgb = 0; + dc->caps.color.dpp.ogam_rom_caps.bt2020 = 0; + dc->caps.color.dpp.ogam_rom_caps.gamma2_2 = 0; + dc->caps.color.dpp.ogam_rom_caps.pq = 0; + dc->caps.color.dpp.ogam_rom_caps.hlg = 0; + dc->caps.color.dpp.ocsc = 0; + + dc->caps.color.mpc.gamut_remap = 1; + dc->caps.color.mpc.num_3dluts = pool->base.res_cap->num_mpc_3dlut; //2 + dc->caps.color.mpc.ogam_ram = 1; + dc->caps.color.mpc.ogam_rom_caps.srgb = 0; + dc->caps.color.mpc.ogam_rom_caps.bt2020 = 0; + dc->caps.color.mpc.ogam_rom_caps.gamma2_2 = 0; + dc->caps.color.mpc.ogam_rom_caps.pq = 0; + dc->caps.color.mpc.ogam_rom_caps.hlg = 0; + dc->caps.color.mpc.ocsc = 1; + + /* read VBIOS LTTPR caps */ + { + if (ctx->dc_bios->funcs->get_lttpr_caps) { + enum bp_result bp_query_result; + uint8_t is_vbios_lttpr_enable = 0; + + bp_query_result = ctx->dc_bios->funcs->get_lttpr_caps(ctx->dc_bios, &is_vbios_lttpr_enable); + dc->caps.vbios_lttpr_enable = (bp_query_result == BP_RESULT_OK) && !!is_vbios_lttpr_enable; + } + + /* interop bit is implicit */ + { + dc->caps.vbios_lttpr_aware = true; + } + } + + if (dc->ctx->dce_environment == DCE_ENV_PRODUCTION_DRV) + dc->debug = debug_defaults_drv; + + // Init the vm_helper + if (dc->vm_helper) + vm_helper_init(dc->vm_helper, 16); + + /************************************************* + * Create resources * + *************************************************/ + + /* Clock Sources for Pixel Clock*/ + pool->base.clock_sources[DCN31_CLK_SRC_PLL0] = + dcn31_clock_source_create(ctx, ctx->dc_bios, + CLOCK_SOURCE_COMBO_PHY_PLL0, + &clk_src_regs[0], false); + pool->base.clock_sources[DCN31_CLK_SRC_PLL1] = + dcn31_clock_source_create(ctx, ctx->dc_bios, + CLOCK_SOURCE_COMBO_PHY_PLL1, + &clk_src_regs[1], false); + pool->base.clock_sources[DCN31_CLK_SRC_PLL2] = + dcn31_clock_source_create(ctx, ctx->dc_bios, + CLOCK_SOURCE_COMBO_PHY_PLL2, + &clk_src_regs[2], false); + pool->base.clock_sources[DCN31_CLK_SRC_PLL3] = + dcn31_clock_source_create(ctx, ctx->dc_bios, + CLOCK_SOURCE_COMBO_PHY_PLL3, + &clk_src_regs[3], false); + pool->base.clock_sources[DCN31_CLK_SRC_PLL4] = + dcn31_clock_source_create(ctx, ctx->dc_bios, + CLOCK_SOURCE_COMBO_PHY_PLL4, + &clk_src_regs[4], false); + + pool->base.clk_src_count = DCN30_CLK_SRC_TOTAL; + + /* todo: not reuse phy_pll registers */ + pool->base.dp_clock_source = + dcn31_clock_source_create(ctx, ctx->dc_bios, + CLOCK_SOURCE_ID_DP_DTO, + &clk_src_regs[0], true); + + for (i = 0; i < pool->base.clk_src_count; i++) { + if (pool->base.clock_sources[i] == NULL) { + dm_error("DC: failed to create clock sources!\n"); + BREAK_TO_DEBUGGER(); + goto create_fail; + } + } + + /* TODO: DCCG */ + pool->base.dccg = dccg31_create(ctx, &dccg_regs, &dccg_shift, &dccg_mask); + if (pool->base.dccg == NULL) { + dm_error("DC: failed to create dccg!\n"); + BREAK_TO_DEBUGGER(); + goto create_fail; + } + + /* TODO: IRQ */ + init_data.ctx = dc->ctx; + pool->base.irqs = dal_irq_service_dcn31_create(&init_data); + if (!pool->base.irqs) + goto create_fail; + + /* HUBBUB */ + pool->base.hubbub = dcn31_hubbub_create(ctx); + if (pool->base.hubbub == NULL) { + BREAK_TO_DEBUGGER(); + dm_error("DC: failed to create hubbub!\n"); + goto create_fail; + } + + /* HUBPs, DPPs, OPPs and TGs */ + for (i = 0; i < pool->base.pipe_count; i++) { + pool->base.hubps[i] = dcn31_hubp_create(ctx, i); + if (pool->base.hubps[i] == NULL) { + BREAK_TO_DEBUGGER(); + dm_error( + "DC: failed to create hubps!\n"); + goto create_fail; + } + + pool->base.dpps[i] = dcn31_dpp_create(ctx, i); + if (pool->base.dpps[i] == NULL) { + BREAK_TO_DEBUGGER(); + dm_error( + "DC: failed to create dpps!\n"); + goto create_fail; + } + } + + for (i = 0; i < pool->base.res_cap->num_opp; i++) { + pool->base.opps[i] = dcn31_opp_create(ctx, i); + if (pool->base.opps[i] == NULL) { + BREAK_TO_DEBUGGER(); + dm_error( + "DC: failed to create output pixel processor!\n"); + goto create_fail; + } + } + + for (i = 0; i < pool->base.res_cap->num_timing_generator; i++) { + pool->base.timing_generators[i] = dcn31_timing_generator_create( + ctx, i); + if (pool->base.timing_generators[i] == NULL) { + BREAK_TO_DEBUGGER(); + dm_error("DC: failed to create tg!\n"); + goto create_fail; + } + } + pool->base.timing_generator_count = i; + + /* PSR */ + pool->base.psr = dmub_psr_create(ctx); + if (pool->base.psr == NULL) { + dm_error("DC: failed to create psr obj!\n"); + BREAK_TO_DEBUGGER(); + goto create_fail; + } + + /* ABM */ + for (i = 0; i < pool->base.res_cap->num_timing_generator; i++) { + pool->base.multiple_abms[i] = dmub_abm_create(ctx, + &abm_regs[i], + &abm_shift, + &abm_mask); + if (pool->base.multiple_abms[i] == NULL) { + dm_error("DC: failed to create abm for pipe %d!\n", i); + BREAK_TO_DEBUGGER(); + goto create_fail; + } + } + + /* MPC and DSC */ + pool->base.mpc = dcn31_mpc_create(ctx, pool->base.mpcc_count, pool->base.res_cap->num_mpc_3dlut); + if (pool->base.mpc == NULL) { + BREAK_TO_DEBUGGER(); + dm_error("DC: failed to create mpc!\n"); + goto create_fail; + } + + for (i = 0; i < pool->base.res_cap->num_dsc; i++) { + pool->base.dscs[i] = dcn31_dsc_create(ctx, i); + if (pool->base.dscs[i] == NULL) { + BREAK_TO_DEBUGGER(); + dm_error("DC: failed to create display stream compressor %d!\n", i); + goto create_fail; + } + } + + /* DWB and MMHUBBUB */ + if (!dcn31_dwbc_create(ctx, &pool->base)) { + BREAK_TO_DEBUGGER(); + dm_error("DC: failed to create dwbc!\n"); + goto create_fail; + } + + if (!dcn31_mmhubbub_create(ctx, &pool->base)) { + BREAK_TO_DEBUGGER(); + dm_error("DC: failed to create mcif_wb!\n"); + goto create_fail; + } + + /* AUX and I2C */ + for (i = 0; i < pool->base.res_cap->num_ddc; i++) { + pool->base.engines[i] = dcn31_aux_engine_create(ctx, i); + if (pool->base.engines[i] == NULL) { + BREAK_TO_DEBUGGER(); + dm_error( + "DC:failed to create aux engine!!\n"); + goto create_fail; + } + pool->base.hw_i2cs[i] = dcn31_i2c_hw_create(ctx, i); + if (pool->base.hw_i2cs[i] == NULL) { + BREAK_TO_DEBUGGER(); + dm_error( + "DC:failed to create hw i2c!!\n"); + goto create_fail; + } + pool->base.sw_i2cs[i] = NULL; + } + + /* Audio, Stream Encoders including HPO and virtual, MPC 3D LUTs */ + if (!resource_construct(num_virtual_links, dc, &pool->base, + &res_create_funcs)) + goto create_fail; + + /* HW Sequencer and Plane caps */ + dcn31_hw_sequencer_construct(dc); + + dc->caps.max_planes = pool->base.pipe_count; + + for (i = 0; i < dc->caps.max_planes; ++i) + dc->caps.planes[i] = plane_cap; + + dc->cap_funcs = cap_funcs; + + dc->dcn_ip->max_num_dpp = dcn3_16_ip.max_num_dpp; + + return true; + +create_fail: + + dcn316_resource_destruct(pool); + + return false; +} + +struct resource_pool *dcn316_create_resource_pool( + const struct dc_init_data *init_data, + struct dc *dc) +{ + struct dcn316_resource_pool *pool = + kzalloc(sizeof(struct dcn316_resource_pool), GFP_KERNEL); + + if (!pool) + return NULL; + + if (dcn316_resource_construct(init_data->num_virtual_links, dc, pool)) + return &pool->base; + + BREAK_TO_DEBUGGER(); + kfree(pool); + return NULL; +} diff --git a/drivers/gpu/drm/amd/display/dc/resource/dcn316/dcn316_resource.h b/drivers/gpu/drm/amd/display/dc/resource/dcn316/dcn316_resource.h new file mode 100644 index 000000000000..aba6d634131b --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/resource/dcn316/dcn316_resource.h @@ -0,0 +1,44 @@ +/* + * Copyright 2021 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#ifndef _DCN316_RESOURCE_H_ +#define _DCN316_RESOURCE_H_ + +#include "core_types.h" + +#define TO_DCN316_RES_POOL(pool)\ + container_of(pool, struct dcn316_resource_pool, base) + +extern struct _vcs_dpi_ip_params_st dcn3_16_ip; + +struct dcn316_resource_pool { + struct resource_pool base; +}; + +struct resource_pool *dcn316_create_resource_pool( + const struct dc_init_data *init_data, + struct dc *dc); + +#endif /* _DCN316_RESOURCE_H_ */ diff --git a/drivers/gpu/drm/amd/display/dc/resource/dcn32/dcn32_resource.c b/drivers/gpu/drm/amd/display/dc/resource/dcn32/dcn32_resource.c new file mode 100644 index 000000000000..36e4c7bef403 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/resource/dcn32/dcn32_resource.c @@ -0,0 +1,2862 @@ +// SPDX-License-Identifier: MIT +/* + * Copyright 2022 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 "dm_services.h" +#include "dc.h" + +#include "dcn32/dcn32_init.h" + +#include "resource.h" +#include "include/irq_service_interface.h" +#include "dcn32_resource.h" + +#include "dcn20/dcn20_resource.h" +#include "dcn30/dcn30_resource.h" + +#include "dcn10/dcn10_ipp.h" +#include "dcn30/dcn30_hubbub.h" +#include "dcn31/dcn31_hubbub.h" +#include "dcn32/dcn32_hubbub.h" +#include "dcn32/dcn32_mpc.h" +#include "dcn32/dcn32_hubp.h" +#include "irq/dcn32/irq_service_dcn32.h" +#include "dcn32/dcn32_dpp.h" +#include "dcn32/dcn32_optc.h" +#include "dcn20/dcn20_hwseq.h" +#include "dcn30/dcn30_hwseq.h" +#include "dce110/dce110_hwseq.h" +#include "dcn30/dcn30_opp.h" +#include "dcn20/dcn20_dsc.h" +#include "dcn30/dcn30_vpg.h" +#include "dcn30/dcn30_afmt.h" +#include "dcn30/dcn30_dio_stream_encoder.h" +#include "dcn32/dcn32_dio_stream_encoder.h" +#include "dcn31/dcn31_hpo_dp_stream_encoder.h" +#include "dcn31/dcn31_hpo_dp_link_encoder.h" +#include "dcn32/dcn32_hpo_dp_link_encoder.h" +#include "dcn31/dcn31_apg.h" +#include "dcn31/dcn31_dio_link_encoder.h" +#include "dcn32/dcn32_dio_link_encoder.h" +#include "dce/dce_clock_source.h" +#include "dce/dce_audio.h" +#include "dce/dce_hwseq.h" +#include "clk_mgr.h" +#include "virtual/virtual_stream_encoder.h" +#include "dml/display_mode_vba.h" +#include "dcn32/dcn32_dccg.h" +#include "dcn10/dcn10_resource.h" +#include "link.h" +#include "dcn31/dcn31_panel_cntl.h" + +#include "dcn30/dcn30_dwb.h" +#include "dcn32/dcn32_mmhubbub.h" + +#include "dcn/dcn_3_2_0_offset.h" +#include "dcn/dcn_3_2_0_sh_mask.h" +#include "nbio/nbio_4_3_0_offset.h" + +#include "reg_helper.h" +#include "dce/dmub_abm.h" +#include "dce/dmub_psr.h" +#include "dce/dce_aux.h" +#include "dce/dce_i2c.h" + +#include "dml/dcn30/display_mode_vba_30.h" +#include "vm_helper.h" +#include "dcn20/dcn20_vmid.h" +#include "dml/dcn32/dcn32_fpu.h" + +#include "dml2/dml2_wrapper.h" + +#define DC_LOGGER_INIT(logger) + +enum dcn32_clk_src_array_id { + DCN32_CLK_SRC_PLL0, + DCN32_CLK_SRC_PLL1, + DCN32_CLK_SRC_PLL2, + DCN32_CLK_SRC_PLL3, + DCN32_CLK_SRC_PLL4, + DCN32_CLK_SRC_TOTAL +}; + +/* begin ********************* + * macros to expend register list macro defined in HW object header file + */ + +/* DCN */ +#define BASE_INNER(seg) ctx->dcn_reg_offsets[seg] + +#define BASE(seg) BASE_INNER(seg) + +#define SR(reg_name)\ + REG_STRUCT.reg_name = BASE(reg ## reg_name ## _BASE_IDX) + \ + reg ## reg_name +#define SR_ARR(reg_name, id) \ + REG_STRUCT[id].reg_name = BASE(reg##reg_name##_BASE_IDX) + reg##reg_name + +#define SR_ARR_INIT(reg_name, id, value) \ + REG_STRUCT[id].reg_name = value + +#define SRI(reg_name, block, id)\ + REG_STRUCT.reg_name = BASE(reg ## block ## id ## _ ## reg_name ## _BASE_IDX) + \ + reg ## block ## id ## _ ## reg_name + +#define SRI_ARR(reg_name, block, id)\ + REG_STRUCT[id].reg_name = BASE(reg ## block ## id ## _ ## reg_name ## _BASE_IDX) + \ + reg ## block ## id ## _ ## reg_name + +#define SR_ARR_I2C(reg_name, id) \ + REG_STRUCT[id-1].reg_name = BASE(reg##reg_name##_BASE_IDX) + reg##reg_name + +#define SRI_ARR_I2C(reg_name, block, id)\ + REG_STRUCT[id-1].reg_name = BASE(reg ## block ## id ## _ ## reg_name ## _BASE_IDX) + \ + reg ## block ## id ## _ ## reg_name + +#define SRI_ARR_ALPHABET(reg_name, block, index, id)\ + REG_STRUCT[index].reg_name = BASE(reg ## block ## id ## _ ## reg_name ## _BASE_IDX) + \ + reg ## block ## id ## _ ## reg_name + +#define SRI2(reg_name, block, id)\ + .reg_name = BASE(reg ## reg_name ## _BASE_IDX) + \ + reg ## reg_name +#define SRI2_ARR(reg_name, block, id)\ + REG_STRUCT[id].reg_name = BASE(reg ## reg_name ## _BASE_IDX) + \ + reg ## reg_name + +#define SRIR(var_name, reg_name, block, id)\ + .var_name = BASE(reg ## block ## id ## _ ## reg_name ## _BASE_IDX) + \ + reg ## block ## id ## _ ## reg_name + +#define SRII(reg_name, block, id)\ + REG_STRUCT.reg_name[id] = BASE(reg ## block ## id ## _ ## reg_name ## _BASE_IDX) + \ + reg ## block ## id ## _ ## reg_name + +#define SRII_ARR_2(reg_name, block, id, inst)\ + REG_STRUCT[inst].reg_name[id] = BASE(reg ## block ## id ## _ ## reg_name ## _BASE_IDX) + \ + reg ## block ## id ## _ ## reg_name + +#define SRII_MPC_RMU(reg_name, block, id)\ + .RMU##_##reg_name[id] = BASE(reg ## block ## id ## _ ## reg_name ## _BASE_IDX) + \ + reg ## block ## id ## _ ## reg_name + +#define SRII_DWB(reg_name, temp_name, block, id)\ + REG_STRUCT.reg_name[id] = BASE(reg ## block ## id ## _ ## temp_name ## _BASE_IDX) + \ + reg ## block ## id ## _ ## temp_name + +#define SF_DWB2(reg_name, block, id, field_name, post_fix) \ + .field_name = reg_name ## __ ## field_name ## post_fix + +#define DCCG_SRII(reg_name, block, id)\ + REG_STRUCT.block ## _ ## reg_name[id] = BASE(reg ## block ## id ## _ ## reg_name ## _BASE_IDX) + \ + reg ## block ## id ## _ ## reg_name + +#define VUPDATE_SRII(reg_name, block, id)\ + REG_STRUCT.reg_name[id] = BASE(reg ## reg_name ## _ ## block ## id ## _BASE_IDX) + \ + reg ## reg_name ## _ ## block ## id + +/* NBIO */ +#define NBIO_BASE_INNER(seg) ctx->nbio_reg_offsets[seg] + +#define NBIO_BASE(seg) \ + NBIO_BASE_INNER(seg) + +#define NBIO_SR(reg_name)\ + REG_STRUCT.reg_name = NBIO_BASE(regBIF_BX0_ ## reg_name ## _BASE_IDX) + \ + regBIF_BX0_ ## reg_name +#define NBIO_SR_ARR(reg_name, id)\ + REG_STRUCT[id].reg_name = NBIO_BASE(regBIF_BX0_ ## reg_name ## _BASE_IDX) + \ + regBIF_BX0_ ## reg_name + +#undef CTX +#define CTX ctx +#define REG(reg_name) \ + (ctx->dcn_reg_offsets[reg ## reg_name ## _BASE_IDX] + reg ## reg_name) + +static struct bios_registers bios_regs; + +#define bios_regs_init() \ + ( \ + NBIO_SR(BIOS_SCRATCH_3),\ + NBIO_SR(BIOS_SCRATCH_6)\ + ) + +#define clk_src_regs_init(index, pllid)\ + CS_COMMON_REG_LIST_DCN3_0_RI(index, pllid) + +static struct dce110_clk_src_regs clk_src_regs[5]; + +static const struct dce110_clk_src_shift cs_shift = { + CS_COMMON_MASK_SH_LIST_DCN3_2(__SHIFT) +}; + +static const struct dce110_clk_src_mask cs_mask = { + CS_COMMON_MASK_SH_LIST_DCN3_2(_MASK) +}; + +#define abm_regs_init(id)\ + ABM_DCN32_REG_LIST_RI(id) + +static struct dce_abm_registers abm_regs[4]; + +static const struct dce_abm_shift abm_shift = { + ABM_MASK_SH_LIST_DCN32(__SHIFT) +}; + +static const struct dce_abm_mask abm_mask = { + ABM_MASK_SH_LIST_DCN32(_MASK) +}; + +#define audio_regs_init(id)\ + AUD_COMMON_REG_LIST_RI(id) + +static struct dce_audio_registers audio_regs[5]; + +#define DCE120_AUD_COMMON_MASK_SH_LIST(mask_sh)\ + SF(AZF0ENDPOINT0_AZALIA_F0_CODEC_ENDPOINT_INDEX, AZALIA_ENDPOINT_REG_INDEX, mask_sh),\ + SF(AZF0ENDPOINT0_AZALIA_F0_CODEC_ENDPOINT_DATA, AZALIA_ENDPOINT_REG_DATA, mask_sh),\ + AUD_COMMON_MASK_SH_LIST_BASE(mask_sh) + +static const struct dce_audio_shift audio_shift = { + DCE120_AUD_COMMON_MASK_SH_LIST(__SHIFT) +}; + +static const struct dce_audio_mask audio_mask = { + DCE120_AUD_COMMON_MASK_SH_LIST(_MASK) +}; + +#define vpg_regs_init(id)\ + VPG_DCN3_REG_LIST_RI(id) + +static struct dcn30_vpg_registers vpg_regs[10]; + +static const struct dcn30_vpg_shift vpg_shift = { + DCN3_VPG_MASK_SH_LIST(__SHIFT) +}; + +static const struct dcn30_vpg_mask vpg_mask = { + DCN3_VPG_MASK_SH_LIST(_MASK) +}; + +#define afmt_regs_init(id)\ + AFMT_DCN3_REG_LIST_RI(id) + +static struct dcn30_afmt_registers afmt_regs[6]; + +static const struct dcn30_afmt_shift afmt_shift = { + DCN3_AFMT_MASK_SH_LIST(__SHIFT) +}; + +static const struct dcn30_afmt_mask afmt_mask = { + DCN3_AFMT_MASK_SH_LIST(_MASK) +}; + +#define apg_regs_init(id)\ + APG_DCN31_REG_LIST_RI(id) + +static struct dcn31_apg_registers apg_regs[4]; + +static const struct dcn31_apg_shift apg_shift = { + DCN31_APG_MASK_SH_LIST(__SHIFT) +}; + +static const struct dcn31_apg_mask apg_mask = { + DCN31_APG_MASK_SH_LIST(_MASK) +}; + +#define stream_enc_regs_init(id)\ + SE_DCN32_REG_LIST_RI(id) + +static struct dcn10_stream_enc_registers stream_enc_regs[5]; + +static const struct dcn10_stream_encoder_shift se_shift = { + SE_COMMON_MASK_SH_LIST_DCN32(__SHIFT) +}; + +static const struct dcn10_stream_encoder_mask se_mask = { + SE_COMMON_MASK_SH_LIST_DCN32(_MASK) +}; + + +#define aux_regs_init(id)\ + DCN2_AUX_REG_LIST_RI(id) + +static struct dcn10_link_enc_aux_registers link_enc_aux_regs[5]; + +#define hpd_regs_init(id)\ + HPD_REG_LIST_RI(id) + +static struct dcn10_link_enc_hpd_registers link_enc_hpd_regs[5]; + +#define link_regs_init(id, phyid)\ + ( \ + LE_DCN31_REG_LIST_RI(id), \ + UNIPHY_DCN2_REG_LIST_RI(id, phyid)\ + ) + /*DPCS_DCN31_REG_LIST(id),*/ \ + +static struct dcn10_link_enc_registers link_enc_regs[5]; + +static const struct dcn10_link_enc_shift le_shift = { + LINK_ENCODER_MASK_SH_LIST_DCN31(__SHIFT), \ + //DPCS_DCN31_MASK_SH_LIST(__SHIFT) +}; + +static const struct dcn10_link_enc_mask le_mask = { + LINK_ENCODER_MASK_SH_LIST_DCN31(_MASK), \ + //DPCS_DCN31_MASK_SH_LIST(_MASK) +}; + +#define hpo_dp_stream_encoder_reg_init(id)\ + DCN3_1_HPO_DP_STREAM_ENC_REG_LIST_RI(id) + +static struct dcn31_hpo_dp_stream_encoder_registers hpo_dp_stream_enc_regs[4]; + +static const struct dcn31_hpo_dp_stream_encoder_shift hpo_dp_se_shift = { + DCN3_1_HPO_DP_STREAM_ENC_MASK_SH_LIST(__SHIFT) +}; + +static const struct dcn31_hpo_dp_stream_encoder_mask hpo_dp_se_mask = { + DCN3_1_HPO_DP_STREAM_ENC_MASK_SH_LIST(_MASK) +}; + + +#define hpo_dp_link_encoder_reg_init(id)\ + DCN3_1_HPO_DP_LINK_ENC_REG_LIST_RI(id) + /*DCN3_1_RDPCSTX_REG_LIST(0),*/ + /*DCN3_1_RDPCSTX_REG_LIST(1),*/ + /*DCN3_1_RDPCSTX_REG_LIST(2),*/ + /*DCN3_1_RDPCSTX_REG_LIST(3),*/ + +static struct dcn31_hpo_dp_link_encoder_registers hpo_dp_link_enc_regs[2]; + +static const struct dcn31_hpo_dp_link_encoder_shift hpo_dp_le_shift = { + DCN3_2_HPO_DP_LINK_ENC_MASK_SH_LIST(__SHIFT) +}; + +static const struct dcn31_hpo_dp_link_encoder_mask hpo_dp_le_mask = { + DCN3_2_HPO_DP_LINK_ENC_MASK_SH_LIST(_MASK) +}; + +#define dpp_regs_init(id)\ + DPP_REG_LIST_DCN30_COMMON_RI(id) + +static struct dcn3_dpp_registers dpp_regs[4]; + +static const struct dcn3_dpp_shift tf_shift = { + DPP_REG_LIST_SH_MASK_DCN30_COMMON(__SHIFT) +}; + +static const struct dcn3_dpp_mask tf_mask = { + DPP_REG_LIST_SH_MASK_DCN30_COMMON(_MASK) +}; + + +#define opp_regs_init(id)\ + OPP_REG_LIST_DCN30_RI(id) + +static struct dcn20_opp_registers opp_regs[4]; + +static const struct dcn20_opp_shift opp_shift = { + OPP_MASK_SH_LIST_DCN20(__SHIFT) +}; + +static const struct dcn20_opp_mask opp_mask = { + OPP_MASK_SH_LIST_DCN20(_MASK) +}; + +#define aux_engine_regs_init(id)\ + ( \ + AUX_COMMON_REG_LIST0_RI(id), \ + SR_ARR_INIT(AUXN_IMPCAL, id, 0), \ + SR_ARR_INIT(AUXP_IMPCAL, id, 0), \ + SR_ARR_INIT(AUX_RESET_MASK, id, DP_AUX0_AUX_CONTROL__AUX_RESET_MASK), \ + SR_ARR_INIT(AUX_RESET_MASK, id, DP_AUX0_AUX_CONTROL__AUX_RESET_MASK)\ + ) + +static struct dce110_aux_registers aux_engine_regs[5]; + +static const struct dce110_aux_registers_shift aux_shift = { + DCN_AUX_MASK_SH_LIST(__SHIFT) +}; + +static const struct dce110_aux_registers_mask aux_mask = { + DCN_AUX_MASK_SH_LIST(_MASK) +}; + +#define dwbc_regs_dcn3_init(id)\ + DWBC_COMMON_REG_LIST_DCN30_RI(id) + +static struct dcn30_dwbc_registers dwbc30_regs[1]; + +static const struct dcn30_dwbc_shift dwbc30_shift = { + DWBC_COMMON_MASK_SH_LIST_DCN30(__SHIFT) +}; + +static const struct dcn30_dwbc_mask dwbc30_mask = { + DWBC_COMMON_MASK_SH_LIST_DCN30(_MASK) +}; + +#define mcif_wb_regs_dcn3_init(id)\ + MCIF_WB_COMMON_REG_LIST_DCN32_RI(id) + +static struct dcn30_mmhubbub_registers mcif_wb30_regs[1]; + +static const struct dcn30_mmhubbub_shift mcif_wb30_shift = { + MCIF_WB_COMMON_MASK_SH_LIST_DCN32(__SHIFT) +}; + +static const struct dcn30_mmhubbub_mask mcif_wb30_mask = { + MCIF_WB_COMMON_MASK_SH_LIST_DCN32(_MASK) +}; + +#define dsc_regsDCN20_init(id)\ + DSC_REG_LIST_DCN20_RI(id) + +static struct dcn20_dsc_registers dsc_regs[4]; + +static const struct dcn20_dsc_shift dsc_shift = { + DSC_REG_LIST_SH_MASK_DCN20(__SHIFT) +}; + +static const struct dcn20_dsc_mask dsc_mask = { + DSC_REG_LIST_SH_MASK_DCN20(_MASK) +}; + +static struct dcn30_mpc_registers mpc_regs; + +#define dcn_mpc_regs_init() \ + MPC_REG_LIST_DCN3_2_RI(0),\ + MPC_REG_LIST_DCN3_2_RI(1),\ + MPC_REG_LIST_DCN3_2_RI(2),\ + MPC_REG_LIST_DCN3_2_RI(3),\ + MPC_OUT_MUX_REG_LIST_DCN3_0_RI(0),\ + MPC_OUT_MUX_REG_LIST_DCN3_0_RI(1),\ + MPC_OUT_MUX_REG_LIST_DCN3_0_RI(2),\ + MPC_OUT_MUX_REG_LIST_DCN3_0_RI(3),\ + MPC_DWB_MUX_REG_LIST_DCN3_0_RI(0) + +static const struct dcn30_mpc_shift mpc_shift = { + MPC_COMMON_MASK_SH_LIST_DCN32(__SHIFT) +}; + +static const struct dcn30_mpc_mask mpc_mask = { + MPC_COMMON_MASK_SH_LIST_DCN32(_MASK) +}; + +#define optc_regs_init(id)\ + OPTC_COMMON_REG_LIST_DCN3_2_RI(id) + +static struct dcn_optc_registers optc_regs[4]; + +static const struct dcn_optc_shift optc_shift = { + OPTC_COMMON_MASK_SH_LIST_DCN3_2(__SHIFT) +}; + +static const struct dcn_optc_mask optc_mask = { + OPTC_COMMON_MASK_SH_LIST_DCN3_2(_MASK) +}; + +#define hubp_regs_init(id)\ + HUBP_REG_LIST_DCN32_RI(id) + +static struct dcn_hubp2_registers hubp_regs[4]; + + +static const struct dcn_hubp2_shift hubp_shift = { + HUBP_MASK_SH_LIST_DCN32(__SHIFT) +}; + +static const struct dcn_hubp2_mask hubp_mask = { + HUBP_MASK_SH_LIST_DCN32(_MASK) +}; + +static struct dcn_hubbub_registers hubbub_reg; +#define hubbub_reg_init()\ + HUBBUB_REG_LIST_DCN32_RI(0) + +static const struct dcn_hubbub_shift hubbub_shift = { + HUBBUB_MASK_SH_LIST_DCN32(__SHIFT) +}; + +static const struct dcn_hubbub_mask hubbub_mask = { + HUBBUB_MASK_SH_LIST_DCN32(_MASK) +}; + +static struct dccg_registers dccg_regs; + +#define dccg_regs_init()\ + DCCG_REG_LIST_DCN32_RI() + +static const struct dccg_shift dccg_shift = { + DCCG_MASK_SH_LIST_DCN32(__SHIFT) +}; + +static const struct dccg_mask dccg_mask = { + DCCG_MASK_SH_LIST_DCN32(_MASK) +}; + + +#define SRII2(reg_name_pre, reg_name_post, id)\ + .reg_name_pre ## _ ## reg_name_post[id] = BASE(reg ## reg_name_pre \ + ## id ## _ ## reg_name_post ## _BASE_IDX) + \ + reg ## reg_name_pre ## id ## _ ## reg_name_post + + +#define HWSEQ_DCN32_REG_LIST()\ + SR(DCHUBBUB_GLOBAL_TIMER_CNTL), \ + SR(DIO_MEM_PWR_CTRL), \ + SR(ODM_MEM_PWR_CTRL3), \ + SR(MMHUBBUB_MEM_PWR_CNTL), \ + SR(DCCG_GATE_DISABLE_CNTL), \ + SR(DCCG_GATE_DISABLE_CNTL2), \ + SR(DCFCLK_CNTL),\ + SR(DC_MEM_GLOBAL_PWR_REQ_CNTL), \ + SRII(PIXEL_RATE_CNTL, OTG, 0), \ + SRII(PIXEL_RATE_CNTL, OTG, 1),\ + SRII(PIXEL_RATE_CNTL, OTG, 2),\ + SRII(PIXEL_RATE_CNTL, OTG, 3),\ + SRII(PHYPLL_PIXEL_RATE_CNTL, OTG, 0),\ + SRII(PHYPLL_PIXEL_RATE_CNTL, OTG, 1),\ + SRII(PHYPLL_PIXEL_RATE_CNTL, OTG, 2),\ + SRII(PHYPLL_PIXEL_RATE_CNTL, OTG, 3),\ + SR(MICROSECOND_TIME_BASE_DIV), \ + SR(MILLISECOND_TIME_BASE_DIV), \ + SR(DISPCLK_FREQ_CHANGE_CNTL), \ + SR(RBBMIF_TIMEOUT_DIS), \ + SR(RBBMIF_TIMEOUT_DIS_2), \ + SR(DCHUBBUB_CRC_CTRL), \ + SR(DPP_TOP0_DPP_CRC_CTRL), \ + SR(DPP_TOP0_DPP_CRC_VAL_B_A), \ + SR(DPP_TOP0_DPP_CRC_VAL_R_G), \ + SR(MPC_CRC_CTRL), \ + SR(MPC_CRC_RESULT_GB), \ + SR(MPC_CRC_RESULT_C), \ + SR(MPC_CRC_RESULT_AR), \ + SR(DOMAIN0_PG_CONFIG), \ + SR(DOMAIN1_PG_CONFIG), \ + SR(DOMAIN2_PG_CONFIG), \ + SR(DOMAIN3_PG_CONFIG), \ + SR(DOMAIN16_PG_CONFIG), \ + SR(DOMAIN17_PG_CONFIG), \ + SR(DOMAIN18_PG_CONFIG), \ + SR(DOMAIN19_PG_CONFIG), \ + SR(DOMAIN0_PG_STATUS), \ + SR(DOMAIN1_PG_STATUS), \ + SR(DOMAIN2_PG_STATUS), \ + SR(DOMAIN3_PG_STATUS), \ + SR(DOMAIN16_PG_STATUS), \ + SR(DOMAIN17_PG_STATUS), \ + SR(DOMAIN18_PG_STATUS), \ + SR(DOMAIN19_PG_STATUS), \ + SR(D1VGA_CONTROL), \ + SR(D2VGA_CONTROL), \ + SR(D3VGA_CONTROL), \ + SR(D4VGA_CONTROL), \ + SR(D5VGA_CONTROL), \ + SR(D6VGA_CONTROL), \ + SR(DC_IP_REQUEST_CNTL), \ + SR(AZALIA_AUDIO_DTO), \ + SR(AZALIA_CONTROLLER_CLOCK_GATING) + +static struct dce_hwseq_registers hwseq_reg; + +#define hwseq_reg_init()\ + HWSEQ_DCN32_REG_LIST() + +#define HWSEQ_DCN32_MASK_SH_LIST(mask_sh)\ + HWSEQ_DCN_MASK_SH_LIST(mask_sh), \ + HWS_SF(, DCHUBBUB_GLOBAL_TIMER_CNTL, DCHUBBUB_GLOBAL_TIMER_REFDIV, mask_sh), \ + HWS_SF(, DOMAIN0_PG_CONFIG, DOMAIN_POWER_FORCEON, mask_sh), \ + HWS_SF(, DOMAIN0_PG_CONFIG, DOMAIN_POWER_GATE, mask_sh), \ + HWS_SF(, DOMAIN1_PG_CONFIG, DOMAIN_POWER_FORCEON, mask_sh), \ + HWS_SF(, DOMAIN1_PG_CONFIG, DOMAIN_POWER_GATE, mask_sh), \ + HWS_SF(, DOMAIN2_PG_CONFIG, DOMAIN_POWER_FORCEON, mask_sh), \ + HWS_SF(, DOMAIN2_PG_CONFIG, DOMAIN_POWER_GATE, mask_sh), \ + HWS_SF(, DOMAIN3_PG_CONFIG, DOMAIN_POWER_FORCEON, mask_sh), \ + HWS_SF(, DOMAIN3_PG_CONFIG, DOMAIN_POWER_GATE, mask_sh), \ + HWS_SF(, DOMAIN16_PG_CONFIG, DOMAIN_POWER_FORCEON, mask_sh), \ + HWS_SF(, DOMAIN16_PG_CONFIG, DOMAIN_POWER_GATE, mask_sh), \ + HWS_SF(, DOMAIN17_PG_CONFIG, DOMAIN_POWER_FORCEON, mask_sh), \ + HWS_SF(, DOMAIN17_PG_CONFIG, DOMAIN_POWER_GATE, mask_sh), \ + HWS_SF(, DOMAIN18_PG_CONFIG, DOMAIN_POWER_FORCEON, mask_sh), \ + HWS_SF(, DOMAIN18_PG_CONFIG, DOMAIN_POWER_GATE, mask_sh), \ + HWS_SF(, DOMAIN19_PG_CONFIG, DOMAIN_POWER_FORCEON, mask_sh), \ + HWS_SF(, DOMAIN19_PG_CONFIG, DOMAIN_POWER_GATE, mask_sh), \ + HWS_SF(, DOMAIN0_PG_STATUS, DOMAIN_PGFSM_PWR_STATUS, mask_sh), \ + HWS_SF(, DOMAIN1_PG_STATUS, DOMAIN_PGFSM_PWR_STATUS, mask_sh), \ + HWS_SF(, DOMAIN2_PG_STATUS, DOMAIN_PGFSM_PWR_STATUS, mask_sh), \ + HWS_SF(, DOMAIN3_PG_STATUS, DOMAIN_PGFSM_PWR_STATUS, mask_sh), \ + HWS_SF(, DOMAIN16_PG_STATUS, DOMAIN_PGFSM_PWR_STATUS, mask_sh), \ + HWS_SF(, DOMAIN17_PG_STATUS, DOMAIN_PGFSM_PWR_STATUS, mask_sh), \ + HWS_SF(, DOMAIN18_PG_STATUS, DOMAIN_PGFSM_PWR_STATUS, mask_sh), \ + HWS_SF(, DOMAIN19_PG_STATUS, DOMAIN_PGFSM_PWR_STATUS, mask_sh), \ + HWS_SF(, DC_IP_REQUEST_CNTL, IP_REQUEST_EN, mask_sh), \ + HWS_SF(, AZALIA_AUDIO_DTO, AZALIA_AUDIO_DTO_MODULE, mask_sh), \ + HWS_SF(, HPO_TOP_CLOCK_CONTROL, HPO_HDMISTREAMCLK_G_GATE_DIS, mask_sh), \ + HWS_SF(, ODM_MEM_PWR_CTRL3, ODM_MEM_UNASSIGNED_PWR_MODE, mask_sh), \ + HWS_SF(, ODM_MEM_PWR_CTRL3, ODM_MEM_VBLANK_PWR_MODE, mask_sh), \ + HWS_SF(, MMHUBBUB_MEM_PWR_CNTL, VGA_MEM_PWR_FORCE, mask_sh) + +static const struct dce_hwseq_shift hwseq_shift = { + HWSEQ_DCN32_MASK_SH_LIST(__SHIFT) +}; + +static const struct dce_hwseq_mask hwseq_mask = { + HWSEQ_DCN32_MASK_SH_LIST(_MASK) +}; +#define vmid_regs_init(id)\ + DCN20_VMID_REG_LIST_RI(id) + +static struct dcn_vmid_registers vmid_regs[16]; + +static const struct dcn20_vmid_shift vmid_shifts = { + DCN20_VMID_MASK_SH_LIST(__SHIFT) +}; + +static const struct dcn20_vmid_mask vmid_masks = { + DCN20_VMID_MASK_SH_LIST(_MASK) +}; + +static const struct resource_caps res_cap_dcn32 = { + .num_timing_generator = 4, + .num_opp = 4, + .num_video_plane = 4, + .num_audio = 5, + .num_stream_encoder = 5, + .num_hpo_dp_stream_encoder = 4, + .num_hpo_dp_link_encoder = 2, + .num_pll = 5, + .num_dwb = 1, + .num_ddc = 5, + .num_vmid = 16, + .num_mpc_3dlut = 4, + .num_dsc = 4, +}; + +static const struct dc_plane_cap plane_cap = { + .type = DC_PLANE_TYPE_DCN_UNIVERSAL, + .per_pixel_alpha = true, + + .pixel_format_support = { + .argb8888 = true, + .nv12 = true, + .fp16 = true, + .p010 = true, + .ayuv = false, + }, + + .max_upscale_factor = { + .argb8888 = 16000, + .nv12 = 16000, + .fp16 = 16000 + }, + + // 6:1 downscaling ratio: 1000/6 = 166.666 + .max_downscale_factor = { + .argb8888 = 167, + .nv12 = 167, + .fp16 = 167 + }, + 64, + 64 +}; + +static const struct dc_debug_options debug_defaults_drv = { + .disable_dmcu = true, + .force_abm_enable = false, + .timing_trace = false, + .clock_trace = true, + .disable_pplib_clock_request = false, + .pipe_split_policy = MPC_SPLIT_AVOID, // Due to CRB, no need to MPC split anymore + .force_single_disp_pipe_split = false, + .disable_dcc = DCC_ENABLE, + .vsr_support = true, + .performance_trace = false, + .max_downscale_src_width = 7680,/*upto 8K*/ + .disable_pplib_wm_range = false, + .scl_reset_length10 = true, + .sanity_checks = false, + .underflow_assert_delay_us = 0xFFFFFFFF, + .dwb_fi_phase = -1, // -1 = disable, + .dmub_command_table = true, + .enable_mem_low_power = { + .bits = { + .vga = false, + .i2c = false, + .dmcu = false, // This is previously known to cause hang on S3 cycles if enabled + .dscl = false, + .cm = false, + .mpc = false, + .optc = true, + } + }, + .use_max_lb = true, + .force_disable_subvp = false, + .exit_idle_opt_for_cursor_updates = true, + .using_dml2 = false, + .enable_single_display_2to1_odm_policy = true, + + /* Must match enable_single_display_2to1_odm_policy to support dynamic ODM transitions*/ + .enable_double_buffered_dsc_pg_support = true, + .enable_dp_dig_pixel_rate_div_policy = 1, + .allow_sw_cursor_fallback = false, // Linux can't do SW cursor "fallback" + .alloc_extra_way_for_cursor = true, + .min_prefetch_in_strobe_ns = 60000, // 60us + .disable_unbounded_requesting = false, + .override_dispclk_programming = true, + .disable_fpo_optimizations = false, + .fpo_vactive_margin_us = 2000, // 2000us + .disable_fpo_vactive = false, + .disable_boot_optimizations = false, + .disable_subvp_high_refresh = false, + .disable_dp_plus_plus_wa = true, + .fpo_vactive_min_active_margin_us = 200, + .fpo_vactive_max_blank_us = 1000, + .enable_legacy_fast_update = false, +}; + +static struct dce_aux *dcn32_aux_engine_create( + struct dc_context *ctx, + uint32_t inst) +{ + struct aux_engine_dce110 *aux_engine = + kzalloc(sizeof(struct aux_engine_dce110), GFP_KERNEL); + + if (!aux_engine) + return NULL; + +#undef REG_STRUCT +#define REG_STRUCT aux_engine_regs + aux_engine_regs_init(0), + aux_engine_regs_init(1), + aux_engine_regs_init(2), + aux_engine_regs_init(3), + aux_engine_regs_init(4); + + dce110_aux_engine_construct(aux_engine, ctx, inst, + SW_AUX_TIMEOUT_PERIOD_MULTIPLIER * AUX_TIMEOUT_PERIOD, + &aux_engine_regs[inst], + &aux_mask, + &aux_shift, + ctx->dc->caps.extended_aux_timeout_support); + + return &aux_engine->base; +} +#define i2c_inst_regs_init(id)\ + I2C_HW_ENGINE_COMMON_REG_LIST_DCN30_RI(id) + +static struct dce_i2c_registers i2c_hw_regs[5]; + +static const struct dce_i2c_shift i2c_shifts = { + I2C_COMMON_MASK_SH_LIST_DCN30(__SHIFT) +}; + +static const struct dce_i2c_mask i2c_masks = { + I2C_COMMON_MASK_SH_LIST_DCN30(_MASK) +}; + +static struct dce_i2c_hw *dcn32_i2c_hw_create( + struct dc_context *ctx, + uint32_t inst) +{ + struct dce_i2c_hw *dce_i2c_hw = + kzalloc(sizeof(struct dce_i2c_hw), GFP_KERNEL); + + if (!dce_i2c_hw) + return NULL; + +#undef REG_STRUCT +#define REG_STRUCT i2c_hw_regs + i2c_inst_regs_init(1), + i2c_inst_regs_init(2), + i2c_inst_regs_init(3), + i2c_inst_regs_init(4), + i2c_inst_regs_init(5); + + dcn2_i2c_hw_construct(dce_i2c_hw, ctx, inst, + &i2c_hw_regs[inst], &i2c_shifts, &i2c_masks); + + return dce_i2c_hw; +} + +static struct clock_source *dcn32_clock_source_create( + struct dc_context *ctx, + struct dc_bios *bios, + enum clock_source_id id, + const struct dce110_clk_src_regs *regs, + bool dp_clk_src) +{ + struct dce110_clk_src *clk_src = + kzalloc(sizeof(struct dce110_clk_src), GFP_KERNEL); + + if (!clk_src) + return NULL; + + if (dcn31_clk_src_construct(clk_src, ctx, bios, id, + regs, &cs_shift, &cs_mask)) { + clk_src->base.dp_clk_src = dp_clk_src; + return &clk_src->base; + } + + kfree(clk_src); + BREAK_TO_DEBUGGER(); + return NULL; +} + +static struct hubbub *dcn32_hubbub_create(struct dc_context *ctx) +{ + int i; + + struct dcn20_hubbub *hubbub2 = kzalloc(sizeof(struct dcn20_hubbub), + GFP_KERNEL); + + if (!hubbub2) + return NULL; + +#undef REG_STRUCT +#define REG_STRUCT hubbub_reg + hubbub_reg_init(); + +#undef REG_STRUCT +#define REG_STRUCT vmid_regs + vmid_regs_init(0), + vmid_regs_init(1), + vmid_regs_init(2), + vmid_regs_init(3), + vmid_regs_init(4), + vmid_regs_init(5), + vmid_regs_init(6), + vmid_regs_init(7), + vmid_regs_init(8), + vmid_regs_init(9), + vmid_regs_init(10), + vmid_regs_init(11), + vmid_regs_init(12), + vmid_regs_init(13), + vmid_regs_init(14), + vmid_regs_init(15); + + hubbub32_construct(hubbub2, ctx, + &hubbub_reg, + &hubbub_shift, + &hubbub_mask, + ctx->dc->dml.ip.det_buffer_size_kbytes, + ctx->dc->dml.ip.pixel_chunk_size_kbytes, + ctx->dc->dml.ip.config_return_buffer_size_in_kbytes); + + + for (i = 0; i < res_cap_dcn32.num_vmid; i++) { + struct dcn20_vmid *vmid = &hubbub2->vmid[i]; + + vmid->ctx = ctx; + + vmid->regs = &vmid_regs[i]; + vmid->shifts = &vmid_shifts; + vmid->masks = &vmid_masks; + } + + return &hubbub2->base; +} + +static struct hubp *dcn32_hubp_create( + struct dc_context *ctx, + uint32_t inst) +{ + struct dcn20_hubp *hubp2 = + kzalloc(sizeof(struct dcn20_hubp), GFP_KERNEL); + + if (!hubp2) + return NULL; + +#undef REG_STRUCT +#define REG_STRUCT hubp_regs + hubp_regs_init(0), + hubp_regs_init(1), + hubp_regs_init(2), + hubp_regs_init(3); + + if (hubp32_construct(hubp2, ctx, inst, + &hubp_regs[inst], &hubp_shift, &hubp_mask)) + return &hubp2->base; + + BREAK_TO_DEBUGGER(); + kfree(hubp2); + return NULL; +} + +static void dcn32_dpp_destroy(struct dpp **dpp) +{ + kfree(TO_DCN30_DPP(*dpp)); + *dpp = NULL; +} + +static struct dpp *dcn32_dpp_create( + struct dc_context *ctx, + uint32_t inst) +{ + struct dcn3_dpp *dpp3 = + kzalloc(sizeof(struct dcn3_dpp), GFP_KERNEL); + + if (!dpp3) + return NULL; + +#undef REG_STRUCT +#define REG_STRUCT dpp_regs + dpp_regs_init(0), + dpp_regs_init(1), + dpp_regs_init(2), + dpp_regs_init(3); + + if (dpp32_construct(dpp3, ctx, inst, + &dpp_regs[inst], &tf_shift, &tf_mask)) + return &dpp3->base; + + BREAK_TO_DEBUGGER(); + kfree(dpp3); + return NULL; +} + +static struct mpc *dcn32_mpc_create( + struct dc_context *ctx, + int num_mpcc, + int num_rmu) +{ + struct dcn30_mpc *mpc30 = kzalloc(sizeof(struct dcn30_mpc), + GFP_KERNEL); + + if (!mpc30) + return NULL; + +#undef REG_STRUCT +#define REG_STRUCT mpc_regs + dcn_mpc_regs_init(); + + dcn32_mpc_construct(mpc30, ctx, + &mpc_regs, + &mpc_shift, + &mpc_mask, + num_mpcc, + num_rmu); + + return &mpc30->base; +} + +static struct output_pixel_processor *dcn32_opp_create( + struct dc_context *ctx, uint32_t inst) +{ + struct dcn20_opp *opp2 = + kzalloc(sizeof(struct dcn20_opp), GFP_KERNEL); + + if (!opp2) { + BREAK_TO_DEBUGGER(); + return NULL; + } + +#undef REG_STRUCT +#define REG_STRUCT opp_regs + opp_regs_init(0), + opp_regs_init(1), + opp_regs_init(2), + opp_regs_init(3); + + dcn20_opp_construct(opp2, ctx, inst, + &opp_regs[inst], &opp_shift, &opp_mask); + return &opp2->base; +} + + +static struct timing_generator *dcn32_timing_generator_create( + struct dc_context *ctx, + uint32_t instance) +{ + struct optc *tgn10 = + kzalloc(sizeof(struct optc), GFP_KERNEL); + + if (!tgn10) + return NULL; + +#undef REG_STRUCT +#define REG_STRUCT optc_regs + optc_regs_init(0), + optc_regs_init(1), + optc_regs_init(2), + optc_regs_init(3); + + tgn10->base.inst = instance; + tgn10->base.ctx = ctx; + + tgn10->tg_regs = &optc_regs[instance]; + tgn10->tg_shift = &optc_shift; + tgn10->tg_mask = &optc_mask; + + dcn32_timing_generator_init(tgn10); + + return &tgn10->base; +} + +static const struct encoder_feature_support link_enc_feature = { + .max_hdmi_deep_color = COLOR_DEPTH_121212, + .max_hdmi_pixel_clock = 600000, + .hdmi_ycbcr420_supported = true, + .dp_ycbcr420_supported = true, + .fec_supported = true, + .flags.bits.IS_HBR2_CAPABLE = true, + .flags.bits.IS_HBR3_CAPABLE = true, + .flags.bits.IS_TPS3_CAPABLE = true, + .flags.bits.IS_TPS4_CAPABLE = true +}; + +static struct link_encoder *dcn32_link_encoder_create( + struct dc_context *ctx, + const struct encoder_init_data *enc_init_data) +{ + struct dcn20_link_encoder *enc20 = + kzalloc(sizeof(struct dcn20_link_encoder), GFP_KERNEL); + + if (!enc20) + return NULL; + +#undef REG_STRUCT +#define REG_STRUCT link_enc_aux_regs + aux_regs_init(0), + aux_regs_init(1), + aux_regs_init(2), + aux_regs_init(3), + aux_regs_init(4); + +#undef REG_STRUCT +#define REG_STRUCT link_enc_hpd_regs + hpd_regs_init(0), + hpd_regs_init(1), + hpd_regs_init(2), + hpd_regs_init(3), + hpd_regs_init(4); + +#undef REG_STRUCT +#define REG_STRUCT link_enc_regs + link_regs_init(0, A), + link_regs_init(1, B), + link_regs_init(2, C), + link_regs_init(3, D), + link_regs_init(4, E); + + dcn32_link_encoder_construct(enc20, + enc_init_data, + &link_enc_feature, + &link_enc_regs[enc_init_data->transmitter], + &link_enc_aux_regs[enc_init_data->channel - 1], + &link_enc_hpd_regs[enc_init_data->hpd_source], + &le_shift, + &le_mask); + + return &enc20->enc10.base; +} + +struct panel_cntl *dcn32_panel_cntl_create(const struct panel_cntl_init_data *init_data) +{ + struct dcn31_panel_cntl *panel_cntl = + kzalloc(sizeof(struct dcn31_panel_cntl), GFP_KERNEL); + + if (!panel_cntl) + return NULL; + + dcn31_panel_cntl_construct(panel_cntl, init_data); + + return &panel_cntl->base; +} + +static void read_dce_straps( + struct dc_context *ctx, + struct resource_straps *straps) +{ + generic_reg_get(ctx, ctx->dcn_reg_offsets[regDC_PINSTRAPS_BASE_IDX] + regDC_PINSTRAPS, + FN(DC_PINSTRAPS, DC_PINSTRAPS_AUDIO), &straps->dc_pinstraps_audio); + +} + +static struct audio *dcn32_create_audio( + struct dc_context *ctx, unsigned int inst) +{ + +#undef REG_STRUCT +#define REG_STRUCT audio_regs + audio_regs_init(0), + audio_regs_init(1), + audio_regs_init(2), + audio_regs_init(3), + audio_regs_init(4); + + return dce_audio_create(ctx, inst, + &audio_regs[inst], &audio_shift, &audio_mask); +} + +static struct vpg *dcn32_vpg_create( + struct dc_context *ctx, + uint32_t inst) +{ + struct dcn30_vpg *vpg3 = kzalloc(sizeof(struct dcn30_vpg), GFP_KERNEL); + + if (!vpg3) + return NULL; + +#undef REG_STRUCT +#define REG_STRUCT vpg_regs + vpg_regs_init(0), + vpg_regs_init(1), + vpg_regs_init(2), + vpg_regs_init(3), + vpg_regs_init(4), + vpg_regs_init(5), + vpg_regs_init(6), + vpg_regs_init(7), + vpg_regs_init(8), + vpg_regs_init(9); + + vpg3_construct(vpg3, ctx, inst, + &vpg_regs[inst], + &vpg_shift, + &vpg_mask); + + return &vpg3->base; +} + +static struct afmt *dcn32_afmt_create( + struct dc_context *ctx, + uint32_t inst) +{ + struct dcn30_afmt *afmt3 = kzalloc(sizeof(struct dcn30_afmt), GFP_KERNEL); + + if (!afmt3) + return NULL; + +#undef REG_STRUCT +#define REG_STRUCT afmt_regs + afmt_regs_init(0), + afmt_regs_init(1), + afmt_regs_init(2), + afmt_regs_init(3), + afmt_regs_init(4), + afmt_regs_init(5); + + afmt3_construct(afmt3, ctx, inst, + &afmt_regs[inst], + &afmt_shift, + &afmt_mask); + + return &afmt3->base; +} + +static struct apg *dcn31_apg_create( + struct dc_context *ctx, + uint32_t inst) +{ + struct dcn31_apg *apg31 = kzalloc(sizeof(struct dcn31_apg), GFP_KERNEL); + + if (!apg31) + return NULL; + +#undef REG_STRUCT +#define REG_STRUCT apg_regs + apg_regs_init(0), + apg_regs_init(1), + apg_regs_init(2), + apg_regs_init(3); + + apg31_construct(apg31, ctx, inst, + &apg_regs[inst], + &apg_shift, + &apg_mask); + + return &apg31->base; +} + +static struct stream_encoder *dcn32_stream_encoder_create( + enum engine_id eng_id, + struct dc_context *ctx) +{ + struct dcn10_stream_encoder *enc1; + struct vpg *vpg; + struct afmt *afmt; + int vpg_inst; + int afmt_inst; + + /* Mapping of VPG, AFMT, DME register blocks to DIO block instance */ + if (eng_id <= ENGINE_ID_DIGF) { + vpg_inst = eng_id; + afmt_inst = eng_id; + } else + return NULL; + + enc1 = kzalloc(sizeof(struct dcn10_stream_encoder), GFP_KERNEL); + vpg = dcn32_vpg_create(ctx, vpg_inst); + afmt = dcn32_afmt_create(ctx, afmt_inst); + + if (!enc1 || !vpg || !afmt) { + kfree(enc1); + kfree(vpg); + kfree(afmt); + return NULL; + } + +#undef REG_STRUCT +#define REG_STRUCT stream_enc_regs + stream_enc_regs_init(0), + stream_enc_regs_init(1), + stream_enc_regs_init(2), + stream_enc_regs_init(3), + stream_enc_regs_init(4); + + dcn32_dio_stream_encoder_construct(enc1, ctx, ctx->dc_bios, + eng_id, vpg, afmt, + &stream_enc_regs[eng_id], + &se_shift, &se_mask); + + return &enc1->base; +} + +static struct hpo_dp_stream_encoder *dcn32_hpo_dp_stream_encoder_create( + enum engine_id eng_id, + struct dc_context *ctx) +{ + struct dcn31_hpo_dp_stream_encoder *hpo_dp_enc31; + struct vpg *vpg; + struct apg *apg; + uint32_t hpo_dp_inst; + uint32_t vpg_inst; + uint32_t apg_inst; + + ASSERT((eng_id >= ENGINE_ID_HPO_DP_0) && (eng_id <= ENGINE_ID_HPO_DP_3)); + hpo_dp_inst = eng_id - ENGINE_ID_HPO_DP_0; + + /* Mapping of VPG register blocks to HPO DP block instance: + * VPG[6] -> HPO_DP[0] + * VPG[7] -> HPO_DP[1] + * VPG[8] -> HPO_DP[2] + * VPG[9] -> HPO_DP[3] + */ + vpg_inst = hpo_dp_inst + 6; + + /* Mapping of APG register blocks to HPO DP block instance: + * APG[0] -> HPO_DP[0] + * APG[1] -> HPO_DP[1] + * APG[2] -> HPO_DP[2] + * APG[3] -> HPO_DP[3] + */ + apg_inst = hpo_dp_inst; + + /* allocate HPO stream encoder and create VPG sub-block */ + hpo_dp_enc31 = kzalloc(sizeof(struct dcn31_hpo_dp_stream_encoder), GFP_KERNEL); + vpg = dcn32_vpg_create(ctx, vpg_inst); + apg = dcn31_apg_create(ctx, apg_inst); + + if (!hpo_dp_enc31 || !vpg || !apg) { + kfree(hpo_dp_enc31); + kfree(vpg); + kfree(apg); + return NULL; + } + +#undef REG_STRUCT +#define REG_STRUCT hpo_dp_stream_enc_regs + hpo_dp_stream_encoder_reg_init(0), + hpo_dp_stream_encoder_reg_init(1), + hpo_dp_stream_encoder_reg_init(2), + hpo_dp_stream_encoder_reg_init(3); + + dcn31_hpo_dp_stream_encoder_construct(hpo_dp_enc31, ctx, ctx->dc_bios, + hpo_dp_inst, eng_id, vpg, apg, + &hpo_dp_stream_enc_regs[hpo_dp_inst], + &hpo_dp_se_shift, &hpo_dp_se_mask); + + return &hpo_dp_enc31->base; +} + +static struct hpo_dp_link_encoder *dcn32_hpo_dp_link_encoder_create( + uint8_t inst, + struct dc_context *ctx) +{ + struct dcn31_hpo_dp_link_encoder *hpo_dp_enc31; + + /* allocate HPO link encoder */ + hpo_dp_enc31 = kzalloc(sizeof(struct dcn31_hpo_dp_link_encoder), GFP_KERNEL); + +#undef REG_STRUCT +#define REG_STRUCT hpo_dp_link_enc_regs + hpo_dp_link_encoder_reg_init(0), + hpo_dp_link_encoder_reg_init(1); + + hpo_dp_link_encoder32_construct(hpo_dp_enc31, ctx, inst, + &hpo_dp_link_enc_regs[inst], + &hpo_dp_le_shift, &hpo_dp_le_mask); + + return &hpo_dp_enc31->base; +} + +static struct dce_hwseq *dcn32_hwseq_create( + struct dc_context *ctx) +{ + struct dce_hwseq *hws = kzalloc(sizeof(struct dce_hwseq), GFP_KERNEL); + +#undef REG_STRUCT +#define REG_STRUCT hwseq_reg + hwseq_reg_init(); + + if (hws) { + hws->ctx = ctx; + hws->regs = &hwseq_reg; + hws->shifts = &hwseq_shift; + hws->masks = &hwseq_mask; + } + return hws; +} +static const struct resource_create_funcs res_create_funcs = { + .read_dce_straps = read_dce_straps, + .create_audio = dcn32_create_audio, + .create_stream_encoder = dcn32_stream_encoder_create, + .create_hpo_dp_stream_encoder = dcn32_hpo_dp_stream_encoder_create, + .create_hpo_dp_link_encoder = dcn32_hpo_dp_link_encoder_create, + .create_hwseq = dcn32_hwseq_create, +}; + +static void dcn32_resource_destruct(struct dcn32_resource_pool *pool) +{ + unsigned int i; + + for (i = 0; i < pool->base.stream_enc_count; i++) { + if (pool->base.stream_enc[i] != NULL) { + if (pool->base.stream_enc[i]->vpg != NULL) { + kfree(DCN30_VPG_FROM_VPG(pool->base.stream_enc[i]->vpg)); + pool->base.stream_enc[i]->vpg = NULL; + } + if (pool->base.stream_enc[i]->afmt != NULL) { + kfree(DCN30_AFMT_FROM_AFMT(pool->base.stream_enc[i]->afmt)); + pool->base.stream_enc[i]->afmt = NULL; + } + kfree(DCN10STRENC_FROM_STRENC(pool->base.stream_enc[i])); + pool->base.stream_enc[i] = NULL; + } + } + + for (i = 0; i < pool->base.hpo_dp_stream_enc_count; i++) { + if (pool->base.hpo_dp_stream_enc[i] != NULL) { + if (pool->base.hpo_dp_stream_enc[i]->vpg != NULL) { + kfree(DCN30_VPG_FROM_VPG(pool->base.hpo_dp_stream_enc[i]->vpg)); + pool->base.hpo_dp_stream_enc[i]->vpg = NULL; + } + if (pool->base.hpo_dp_stream_enc[i]->apg != NULL) { + kfree(DCN31_APG_FROM_APG(pool->base.hpo_dp_stream_enc[i]->apg)); + pool->base.hpo_dp_stream_enc[i]->apg = NULL; + } + kfree(DCN3_1_HPO_DP_STREAM_ENC_FROM_HPO_STREAM_ENC(pool->base.hpo_dp_stream_enc[i])); + pool->base.hpo_dp_stream_enc[i] = NULL; + } + } + + for (i = 0; i < pool->base.hpo_dp_link_enc_count; i++) { + if (pool->base.hpo_dp_link_enc[i] != NULL) { + kfree(DCN3_1_HPO_DP_LINK_ENC_FROM_HPO_LINK_ENC(pool->base.hpo_dp_link_enc[i])); + pool->base.hpo_dp_link_enc[i] = NULL; + } + } + + for (i = 0; i < pool->base.res_cap->num_dsc; i++) { + if (pool->base.dscs[i] != NULL) + dcn20_dsc_destroy(&pool->base.dscs[i]); + } + + if (pool->base.mpc != NULL) { + kfree(TO_DCN20_MPC(pool->base.mpc)); + pool->base.mpc = NULL; + } + if (pool->base.hubbub != NULL) { + kfree(TO_DCN20_HUBBUB(pool->base.hubbub)); + pool->base.hubbub = NULL; + } + for (i = 0; i < pool->base.pipe_count; i++) { + if (pool->base.dpps[i] != NULL) + dcn32_dpp_destroy(&pool->base.dpps[i]); + + if (pool->base.ipps[i] != NULL) + pool->base.ipps[i]->funcs->ipp_destroy(&pool->base.ipps[i]); + + if (pool->base.hubps[i] != NULL) { + kfree(TO_DCN20_HUBP(pool->base.hubps[i])); + pool->base.hubps[i] = NULL; + } + + if (pool->base.irqs != NULL) { + dal_irq_service_destroy(&pool->base.irqs); + } + } + + for (i = 0; i < pool->base.res_cap->num_ddc; i++) { + if (pool->base.engines[i] != NULL) + dce110_engine_destroy(&pool->base.engines[i]); + if (pool->base.hw_i2cs[i] != NULL) { + kfree(pool->base.hw_i2cs[i]); + pool->base.hw_i2cs[i] = NULL; + } + if (pool->base.sw_i2cs[i] != NULL) { + kfree(pool->base.sw_i2cs[i]); + pool->base.sw_i2cs[i] = NULL; + } + } + + for (i = 0; i < pool->base.res_cap->num_opp; i++) { + if (pool->base.opps[i] != NULL) + pool->base.opps[i]->funcs->opp_destroy(&pool->base.opps[i]); + } + + for (i = 0; i < pool->base.res_cap->num_timing_generator; i++) { + if (pool->base.timing_generators[i] != NULL) { + kfree(DCN10TG_FROM_TG(pool->base.timing_generators[i])); + pool->base.timing_generators[i] = NULL; + } + } + + for (i = 0; i < pool->base.res_cap->num_dwb; i++) { + if (pool->base.dwbc[i] != NULL) { + kfree(TO_DCN30_DWBC(pool->base.dwbc[i])); + pool->base.dwbc[i] = NULL; + } + if (pool->base.mcif_wb[i] != NULL) { + kfree(TO_DCN30_MMHUBBUB(pool->base.mcif_wb[i])); + pool->base.mcif_wb[i] = NULL; + } + } + + for (i = 0; i < pool->base.audio_count; i++) { + if (pool->base.audios[i]) + dce_aud_destroy(&pool->base.audios[i]); + } + + for (i = 0; i < pool->base.clk_src_count; i++) { + if (pool->base.clock_sources[i] != NULL) { + dcn20_clock_source_destroy(&pool->base.clock_sources[i]); + pool->base.clock_sources[i] = NULL; + } + } + + for (i = 0; i < pool->base.res_cap->num_mpc_3dlut; i++) { + if (pool->base.mpc_lut[i] != NULL) { + dc_3dlut_func_release(pool->base.mpc_lut[i]); + pool->base.mpc_lut[i] = NULL; + } + if (pool->base.mpc_shaper[i] != NULL) { + dc_transfer_func_release(pool->base.mpc_shaper[i]); + pool->base.mpc_shaper[i] = NULL; + } + } + + if (pool->base.dp_clock_source != NULL) { + dcn20_clock_source_destroy(&pool->base.dp_clock_source); + pool->base.dp_clock_source = NULL; + } + + for (i = 0; i < pool->base.res_cap->num_timing_generator; i++) { + if (pool->base.multiple_abms[i] != NULL) + dce_abm_destroy(&pool->base.multiple_abms[i]); + } + + if (pool->base.psr != NULL) + dmub_psr_destroy(&pool->base.psr); + + if (pool->base.dccg != NULL) + dcn_dccg_destroy(&pool->base.dccg); + + if (pool->base.oem_device != NULL) { + struct dc *dc = pool->base.oem_device->ctx->dc; + + dc->link_srv->destroy_ddc_service(&pool->base.oem_device); + } +} + + +static bool dcn32_dwbc_create(struct dc_context *ctx, struct resource_pool *pool) +{ + int i; + uint32_t dwb_count = pool->res_cap->num_dwb; + + for (i = 0; i < dwb_count; i++) { + struct dcn30_dwbc *dwbc30 = kzalloc(sizeof(struct dcn30_dwbc), + GFP_KERNEL); + + if (!dwbc30) { + dm_error("DC: failed to create dwbc30!\n"); + return false; + } + +#undef REG_STRUCT +#define REG_STRUCT dwbc30_regs + dwbc_regs_dcn3_init(0); + + dcn30_dwbc_construct(dwbc30, ctx, + &dwbc30_regs[i], + &dwbc30_shift, + &dwbc30_mask, + i); + + pool->dwbc[i] = &dwbc30->base; + } + return true; +} + +static bool dcn32_mmhubbub_create(struct dc_context *ctx, struct resource_pool *pool) +{ + int i; + uint32_t dwb_count = pool->res_cap->num_dwb; + + for (i = 0; i < dwb_count; i++) { + struct dcn30_mmhubbub *mcif_wb30 = kzalloc(sizeof(struct dcn30_mmhubbub), + GFP_KERNEL); + + if (!mcif_wb30) { + dm_error("DC: failed to create mcif_wb30!\n"); + return false; + } + +#undef REG_STRUCT +#define REG_STRUCT mcif_wb30_regs + mcif_wb_regs_dcn3_init(0); + + dcn32_mmhubbub_construct(mcif_wb30, ctx, + &mcif_wb30_regs[i], + &mcif_wb30_shift, + &mcif_wb30_mask, + i); + + pool->mcif_wb[i] = &mcif_wb30->base; + } + return true; +} + +static struct display_stream_compressor *dcn32_dsc_create( + struct dc_context *ctx, uint32_t inst) +{ + struct dcn20_dsc *dsc = + kzalloc(sizeof(struct dcn20_dsc), GFP_KERNEL); + + if (!dsc) { + BREAK_TO_DEBUGGER(); + return NULL; + } + +#undef REG_STRUCT +#define REG_STRUCT dsc_regs + dsc_regsDCN20_init(0), + dsc_regsDCN20_init(1), + dsc_regsDCN20_init(2), + dsc_regsDCN20_init(3); + + dsc2_construct(dsc, ctx, inst, &dsc_regs[inst], &dsc_shift, &dsc_mask); + + dsc->max_image_width = 6016; + + return &dsc->base; +} + +static void dcn32_destroy_resource_pool(struct resource_pool **pool) +{ + struct dcn32_resource_pool *dcn32_pool = TO_DCN32_RES_POOL(*pool); + + dcn32_resource_destruct(dcn32_pool); + kfree(dcn32_pool); + *pool = NULL; +} + +bool dcn32_acquire_post_bldn_3dlut( + struct resource_context *res_ctx, + const struct resource_pool *pool, + int mpcc_id, + struct dc_3dlut **lut, + struct dc_transfer_func **shaper) +{ + bool ret = false; + + ASSERT(*lut == NULL && *shaper == NULL); + *lut = NULL; + *shaper = NULL; + + if (!res_ctx->is_mpc_3dlut_acquired[mpcc_id]) { + *lut = pool->mpc_lut[mpcc_id]; + *shaper = pool->mpc_shaper[mpcc_id]; + res_ctx->is_mpc_3dlut_acquired[mpcc_id] = true; + ret = true; + } + return ret; +} + +bool dcn32_release_post_bldn_3dlut( + struct resource_context *res_ctx, + const struct resource_pool *pool, + struct dc_3dlut **lut, + struct dc_transfer_func **shaper) +{ + int i; + bool ret = false; + + for (i = 0; i < pool->res_cap->num_mpc_3dlut; i++) { + if (pool->mpc_lut[i] == *lut && pool->mpc_shaper[i] == *shaper) { + res_ctx->is_mpc_3dlut_acquired[i] = false; + pool->mpc_lut[i]->state.raw = 0; + *lut = NULL; + *shaper = NULL; + ret = true; + break; + } + } + return ret; +} + +static void dcn32_enable_phantom_plane(struct dc *dc, + struct dc_state *context, + struct dc_stream_state *phantom_stream, + unsigned int dc_pipe_idx) +{ + struct dc_plane_state *phantom_plane = NULL; + struct dc_plane_state *prev_phantom_plane = NULL; + struct pipe_ctx *curr_pipe = &context->res_ctx.pipe_ctx[dc_pipe_idx]; + + while (curr_pipe) { + if (curr_pipe->top_pipe && curr_pipe->top_pipe->plane_state == curr_pipe->plane_state) + phantom_plane = prev_phantom_plane; + else + phantom_plane = dc_create_plane_state(dc); + + memcpy(&phantom_plane->address, &curr_pipe->plane_state->address, sizeof(phantom_plane->address)); + memcpy(&phantom_plane->scaling_quality, &curr_pipe->plane_state->scaling_quality, + sizeof(phantom_plane->scaling_quality)); + memcpy(&phantom_plane->src_rect, &curr_pipe->plane_state->src_rect, sizeof(phantom_plane->src_rect)); + memcpy(&phantom_plane->dst_rect, &curr_pipe->plane_state->dst_rect, sizeof(phantom_plane->dst_rect)); + memcpy(&phantom_plane->clip_rect, &curr_pipe->plane_state->clip_rect, sizeof(phantom_plane->clip_rect)); + memcpy(&phantom_plane->plane_size, &curr_pipe->plane_state->plane_size, + sizeof(phantom_plane->plane_size)); + memcpy(&phantom_plane->tiling_info, &curr_pipe->plane_state->tiling_info, + sizeof(phantom_plane->tiling_info)); + memcpy(&phantom_plane->dcc, &curr_pipe->plane_state->dcc, sizeof(phantom_plane->dcc)); + phantom_plane->format = curr_pipe->plane_state->format; + phantom_plane->rotation = curr_pipe->plane_state->rotation; + phantom_plane->visible = curr_pipe->plane_state->visible; + + /* Shadow pipe has small viewport. */ + phantom_plane->clip_rect.y = 0; + phantom_plane->clip_rect.height = phantom_stream->src.height; + + phantom_plane->is_phantom = true; + + dc_add_plane_to_context(dc, phantom_stream, phantom_plane, context); + + curr_pipe = curr_pipe->bottom_pipe; + prev_phantom_plane = phantom_plane; + } +} + +static struct dc_stream_state *dcn32_enable_phantom_stream(struct dc *dc, + struct dc_state *context, + display_e2e_pipe_params_st *pipes, + unsigned int pipe_cnt, + unsigned int dc_pipe_idx) +{ + struct dc_stream_state *phantom_stream = NULL; + struct pipe_ctx *ref_pipe = &context->res_ctx.pipe_ctx[dc_pipe_idx]; + + phantom_stream = dc_create_stream_for_sink(ref_pipe->stream->sink); + phantom_stream->signal = SIGNAL_TYPE_VIRTUAL; + phantom_stream->dpms_off = true; + phantom_stream->mall_stream_config.type = SUBVP_PHANTOM; + phantom_stream->mall_stream_config.paired_stream = ref_pipe->stream; + ref_pipe->stream->mall_stream_config.type = SUBVP_MAIN; + ref_pipe->stream->mall_stream_config.paired_stream = phantom_stream; + + /* stream has limited viewport and small timing */ + memcpy(&phantom_stream->timing, &ref_pipe->stream->timing, sizeof(phantom_stream->timing)); + memcpy(&phantom_stream->src, &ref_pipe->stream->src, sizeof(phantom_stream->src)); + memcpy(&phantom_stream->dst, &ref_pipe->stream->dst, sizeof(phantom_stream->dst)); + DC_FP_START(); + dcn32_set_phantom_stream_timing(dc, context, ref_pipe, phantom_stream, pipes, pipe_cnt, dc_pipe_idx); + DC_FP_END(); + + dc_add_stream_to_ctx(dc, context, phantom_stream); + return phantom_stream; +} + +void dcn32_retain_phantom_pipes(struct dc *dc, struct dc_state *context) +{ + int i; + struct dc_plane_state *phantom_plane = NULL; + struct dc_stream_state *phantom_stream = NULL; + + for (i = 0; i < dc->res_pool->pipe_count; i++) { + struct pipe_ctx *pipe = &context->res_ctx.pipe_ctx[i]; + + if (resource_is_pipe_type(pipe, OTG_MASTER) && + resource_is_pipe_type(pipe, DPP_PIPE) && + pipe->stream->mall_stream_config.type == SUBVP_PHANTOM) { + phantom_plane = pipe->plane_state; + phantom_stream = pipe->stream; + + dc_plane_state_retain(phantom_plane); + dc_stream_retain(phantom_stream); + } + } +} + +// return true if removed piped from ctx, false otherwise +bool dcn32_remove_phantom_pipes(struct dc *dc, struct dc_state *context, bool fast_update) +{ + int i; + bool removed_pipe = false; + struct dc_plane_state *phantom_plane = NULL; + struct dc_stream_state *phantom_stream = NULL; + + for (i = 0; i < dc->res_pool->pipe_count; i++) { + struct pipe_ctx *pipe = &context->res_ctx.pipe_ctx[i]; + // build scaling params for phantom pipes + if (pipe->plane_state && pipe->stream && pipe->stream->mall_stream_config.type == SUBVP_PHANTOM) { + phantom_plane = pipe->plane_state; + phantom_stream = pipe->stream; + + dc_rem_all_planes_for_stream(dc, pipe->stream, context); + dc_remove_stream_from_ctx(dc, context, pipe->stream); + + /* Ref count is incremented on allocation and also when added to the context. + * Therefore we must call release for the the phantom plane and stream once + * they are removed from the ctx to finally decrement the refcount to 0 to free. + */ + dc_plane_state_release(phantom_plane); + dc_stream_release(phantom_stream); + + removed_pipe = true; + } + + /* For non-full updates, a shallow copy of the current state + * is created. In this case we don't want to erase the current + * state (there can be 2 HIRQL threads, one in flip, and one in + * checkMPO) that can cause a race condition. + * + * This is just a workaround, needs a proper fix. + */ + if (!fast_update) { + // Clear all phantom stream info + if (pipe->stream) { + pipe->stream->mall_stream_config.type = SUBVP_NONE; + pipe->stream->mall_stream_config.paired_stream = NULL; + } + + if (pipe->plane_state) { + pipe->plane_state->is_phantom = false; + } + } + } + return removed_pipe; +} + +/* TODO: Input to this function should indicate which pipe indexes (or streams) + * require a phantom pipe / stream + */ +void dcn32_add_phantom_pipes(struct dc *dc, struct dc_state *context, + display_e2e_pipe_params_st *pipes, + unsigned int pipe_cnt, + unsigned int index) +{ + struct dc_stream_state *phantom_stream = NULL; + unsigned int i; + + // The index of the DC pipe passed into this function is guarenteed to + // be a valid candidate for SubVP (i.e. has a plane, stream, doesn't + // already have phantom pipe assigned, etc.) by previous checks. + phantom_stream = dcn32_enable_phantom_stream(dc, context, pipes, pipe_cnt, index); + dcn32_enable_phantom_plane(dc, context, phantom_stream, index); + + for (i = 0; i < dc->res_pool->pipe_count; i++) { + struct pipe_ctx *pipe = &context->res_ctx.pipe_ctx[i]; + + // Build scaling params for phantom pipes which were newly added. + // We determine which phantom pipes were added by comparing with + // the phantom stream. + if (pipe->plane_state && pipe->stream && pipe->stream == phantom_stream && + pipe->stream->mall_stream_config.type == SUBVP_PHANTOM) { + pipe->stream->use_dynamic_meta = false; + pipe->plane_state->flip_immediate = false; + if (!resource_build_scaling_params(pipe)) { + // Log / remove phantom pipes since failed to build scaling params + } + } + } +} + +static bool dml1_validate(struct dc *dc, struct dc_state *context, bool fast_validate) +{ + bool out = false; + + BW_VAL_TRACE_SETUP(); + + int vlevel = 0; + int pipe_cnt = 0; + display_e2e_pipe_params_st *pipes = kzalloc(dc->res_pool->pipe_count * sizeof(display_e2e_pipe_params_st), GFP_KERNEL); + struct mall_temp_config mall_temp_config; + + /* To handle Freesync properly, setting FreeSync DML parameters + * to its default state for the first stage of validation + */ + context->bw_ctx.bw.dcn.clk.fw_based_mclk_switching = false; + context->bw_ctx.dml.soc.dram_clock_change_requirement_final = true; + + DC_LOGGER_INIT(dc->ctx->logger); + + /* For fast validation, there are situations where a shallow copy of + * of the dc->current_state is created for the validation. In this case + * we want to save and restore the mall config because we always + * teardown subvp at the beginning of validation (and don't attempt + * to add it back if it's fast validation). If we don't restore the + * subvp config in cases of fast validation + shallow copy of the + * dc->current_state, the dc->current_state will have a partially + * removed subvp state when we did not intend to remove it. + */ + if (fast_validate) { + memset(&mall_temp_config, 0, sizeof(mall_temp_config)); + dcn32_save_mall_state(dc, context, &mall_temp_config); + } + + BW_VAL_TRACE_COUNT(); + + DC_FP_START(); + out = dcn32_internal_validate_bw(dc, context, pipes, &pipe_cnt, &vlevel, fast_validate); + DC_FP_END(); + + if (fast_validate) + dcn32_restore_mall_state(dc, context, &mall_temp_config); + + if (pipe_cnt == 0) + goto validate_out; + + if (!out) + goto validate_fail; + + BW_VAL_TRACE_END_VOLTAGE_LEVEL(); + + if (fast_validate) { + BW_VAL_TRACE_SKIP(fast); + goto validate_out; + } + + dc->res_pool->funcs->calculate_wm_and_dlg(dc, context, pipes, pipe_cnt, vlevel); + + dcn32_override_min_req_memclk(dc, context); + + BW_VAL_TRACE_END_WATERMARKS(); + + goto validate_out; + +validate_fail: + DC_LOG_WARNING("Mode Validation Warning: %s failed validation.\n", + dml_get_status_message(context->bw_ctx.dml.vba.ValidationStatus[context->bw_ctx.dml.vba.soc.num_states])); + + BW_VAL_TRACE_SKIP(fail); + out = false; + +validate_out: + kfree(pipes); + + BW_VAL_TRACE_FINISH(); + + return out; +} + +bool dcn32_validate_bandwidth(struct dc *dc, + struct dc_state *context, + bool fast_validate) +{ + bool out = false; + + if (dc->debug.using_dml2) + out = dml2_validate(dc, context, fast_validate); + else + out = dml1_validate(dc, context, fast_validate); + return out; +} + +int dcn32_populate_dml_pipes_from_context( + struct dc *dc, struct dc_state *context, + display_e2e_pipe_params_st *pipes, + bool fast_validate) +{ + int i, pipe_cnt; + struct resource_context *res_ctx = &context->res_ctx; + struct pipe_ctx *pipe = NULL; + bool subvp_in_use = false; + struct dc_crtc_timing *timing; + + dcn20_populate_dml_pipes_from_context(dc, context, pipes, fast_validate); + + for (i = 0, pipe_cnt = 0; i < dc->res_pool->pipe_count; i++) { + + if (!res_ctx->pipe_ctx[i].stream) + continue; + pipe = &res_ctx->pipe_ctx[i]; + timing = &pipe->stream->timing; + + pipes[pipe_cnt].pipe.src.gpuvm = true; + DC_FP_START(); + dcn32_zero_pipe_dcc_fraction(pipes, pipe_cnt); + DC_FP_END(); + pipes[pipe_cnt].pipe.dest.vfront_porch = timing->v_front_porch; + pipes[pipe_cnt].pipe.dest.odm_combine_policy = dm_odm_combine_policy_dal; + pipes[pipe_cnt].pipe.src.gpuvm_min_page_size_kbytes = 256; // according to spreadsheet + pipes[pipe_cnt].pipe.src.unbounded_req_mode = false; + pipes[pipe_cnt].pipe.scale_ratio_depth.lb_depth = dm_lb_19; + + /* Only populate DML input with subvp info for full updates. + * This is just a workaround -- needs a proper fix. + */ + if (!fast_validate) { + switch (pipe->stream->mall_stream_config.type) { + case SUBVP_MAIN: + pipes[pipe_cnt].pipe.src.use_mall_for_pstate_change = dm_use_mall_pstate_change_sub_viewport; + subvp_in_use = true; + break; + case SUBVP_PHANTOM: + pipes[pipe_cnt].pipe.src.use_mall_for_pstate_change = dm_use_mall_pstate_change_phantom_pipe; + pipes[pipe_cnt].pipe.src.use_mall_for_static_screen = dm_use_mall_static_screen_disable; + // Disallow unbounded req for SubVP according to DCHUB programming guide + pipes[pipe_cnt].pipe.src.unbounded_req_mode = false; + break; + case SUBVP_NONE: + pipes[pipe_cnt].pipe.src.use_mall_for_pstate_change = dm_use_mall_pstate_change_disable; + pipes[pipe_cnt].pipe.src.use_mall_for_static_screen = dm_use_mall_static_screen_disable; + break; + default: + break; + } + } + + pipes[pipe_cnt].dout.dsc_input_bpc = 0; + if (pipes[pipe_cnt].dout.dsc_enable) { + switch (timing->display_color_depth) { + case COLOR_DEPTH_888: + pipes[pipe_cnt].dout.dsc_input_bpc = 8; + break; + case COLOR_DEPTH_101010: + pipes[pipe_cnt].dout.dsc_input_bpc = 10; + break; + case COLOR_DEPTH_121212: + pipes[pipe_cnt].dout.dsc_input_bpc = 12; + break; + default: + ASSERT(0); + break; + } + } + + + pipe_cnt++; + } + + /* For DET allocation, we don't want to use DML policy (not optimal for utilizing all + * the DET available for each pipe). Use the DET override input to maintain our driver + * policy. + */ + dcn32_set_det_allocations(dc, context, pipes); + + // In general cases we want to keep the dram clock change requirement + // (prefer configs that support MCLK switch). Only override to false + // for SubVP + if (context->bw_ctx.bw.dcn.clk.fw_based_mclk_switching || subvp_in_use) + context->bw_ctx.dml.soc.dram_clock_change_requirement_final = false; + else + context->bw_ctx.dml.soc.dram_clock_change_requirement_final = true; + + return pipe_cnt; +} + +static struct dc_cap_funcs cap_funcs = { + .get_dcc_compression_cap = dcn20_get_dcc_compression_cap, + .get_subvp_en = dcn32_subvp_in_use, +}; + +void dcn32_calculate_wm_and_dlg(struct dc *dc, struct dc_state *context, + display_e2e_pipe_params_st *pipes, + int pipe_cnt, + int vlevel) +{ + DC_FP_START(); + dcn32_calculate_wm_and_dlg_fpu(dc, context, pipes, pipe_cnt, vlevel); + DC_FP_END(); +} + +static void dcn32_update_bw_bounding_box(struct dc *dc, struct clk_bw_params *bw_params) +{ + DC_FP_START(); + dcn32_update_bw_bounding_box_fpu(dc, bw_params); + DC_FP_END(); +} + +static struct resource_funcs dcn32_res_pool_funcs = { + .destroy = dcn32_destroy_resource_pool, + .link_enc_create = dcn32_link_encoder_create, + .link_enc_create_minimal = NULL, + .panel_cntl_create = dcn32_panel_cntl_create, + .validate_bandwidth = dcn32_validate_bandwidth, + .calculate_wm_and_dlg = dcn32_calculate_wm_and_dlg, + .populate_dml_pipes = dcn32_populate_dml_pipes_from_context, + .acquire_free_pipe_as_secondary_dpp_pipe = dcn32_acquire_free_pipe_as_secondary_dpp_pipe, + .acquire_free_pipe_as_secondary_opp_head = dcn32_acquire_free_pipe_as_secondary_opp_head, + .release_pipe = dcn20_release_pipe, + .add_stream_to_ctx = dcn30_add_stream_to_ctx, + .add_dsc_to_stream_resource = dcn20_add_dsc_to_stream_resource, + .remove_stream_from_ctx = dcn20_remove_stream_from_ctx, + .populate_dml_writeback_from_context = dcn30_populate_dml_writeback_from_context, + .set_mcif_arb_params = dcn30_set_mcif_arb_params, + .find_first_free_match_stream_enc_for_link = dcn10_find_first_free_match_stream_enc_for_link, + .acquire_post_bldn_3dlut = dcn32_acquire_post_bldn_3dlut, + .release_post_bldn_3dlut = dcn32_release_post_bldn_3dlut, + .update_bw_bounding_box = dcn32_update_bw_bounding_box, + .patch_unknown_plane_state = dcn20_patch_unknown_plane_state, + .update_soc_for_wm_a = dcn30_update_soc_for_wm_a, + .add_phantom_pipes = dcn32_add_phantom_pipes, + .remove_phantom_pipes = dcn32_remove_phantom_pipes, + .retain_phantom_pipes = dcn32_retain_phantom_pipes, + .save_mall_state = dcn32_save_mall_state, + .restore_mall_state = dcn32_restore_mall_state, +}; + +static uint32_t read_pipe_fuses(struct dc_context *ctx) +{ + uint32_t value = REG_READ(CC_DC_PIPE_DIS); + /* DCN32 support max 4 pipes */ + value = value & 0xf; + return value; +} + + +static bool dcn32_resource_construct( + uint8_t num_virtual_links, + struct dc *dc, + struct dcn32_resource_pool *pool) +{ + int i, j; + struct dc_context *ctx = dc->ctx; + struct irq_service_init_data init_data; + struct ddc_service_init_data ddc_init_data = {0}; + uint32_t pipe_fuses = 0; + uint32_t num_pipes = 4; + +#undef REG_STRUCT +#define REG_STRUCT bios_regs + bios_regs_init(); + +#undef REG_STRUCT +#define REG_STRUCT clk_src_regs + clk_src_regs_init(0, A), + clk_src_regs_init(1, B), + clk_src_regs_init(2, C), + clk_src_regs_init(3, D), + clk_src_regs_init(4, E); + +#undef REG_STRUCT +#define REG_STRUCT abm_regs + abm_regs_init(0), + abm_regs_init(1), + abm_regs_init(2), + abm_regs_init(3); + +#undef REG_STRUCT +#define REG_STRUCT dccg_regs + dccg_regs_init(); + + DC_FP_START(); + + ctx->dc_bios->regs = &bios_regs; + + pool->base.res_cap = &res_cap_dcn32; + /* max number of pipes for ASIC before checking for pipe fuses */ + num_pipes = pool->base.res_cap->num_timing_generator; + pipe_fuses = read_pipe_fuses(ctx); + + for (i = 0; i < pool->base.res_cap->num_timing_generator; i++) + if (pipe_fuses & 1 << i) + num_pipes--; + + if (pipe_fuses & 1) + ASSERT(0); //Unexpected - Pipe 0 should always be fully functional! + + if (pipe_fuses & CC_DC_PIPE_DIS__DC_FULL_DIS_MASK) + ASSERT(0); //Entire DCN is harvested! + + /* within dml lib, initial value is hard coded, if ASIC pipe is fused, the + * value will be changed, update max_num_dpp and max_num_otg for dml. + */ + dcn3_2_ip.max_num_dpp = num_pipes; + dcn3_2_ip.max_num_otg = num_pipes; + + pool->base.funcs = &dcn32_res_pool_funcs; + + /************************************************* + * Resource + asic cap harcoding * + *************************************************/ + pool->base.underlay_pipe_index = NO_UNDERLAY_PIPE; + pool->base.timing_generator_count = num_pipes; + pool->base.pipe_count = num_pipes; + pool->base.mpcc_count = num_pipes; + dc->caps.max_downscale_ratio = 600; + dc->caps.i2c_speed_in_khz = 100; + dc->caps.i2c_speed_in_khz_hdcp = 100; /*1.4 w/a applied by default*/ + /* TODO: Bring max_cursor_size back to 256 after subvp cursor corruption is fixed*/ + dc->caps.max_cursor_size = 64; + dc->caps.min_horizontal_blanking_period = 80; + dc->caps.dmdata_alloc_size = 2048; + dc->caps.mall_size_per_mem_channel = 4; + dc->caps.mall_size_total = 0; + dc->caps.cursor_cache_size = dc->caps.max_cursor_size * dc->caps.max_cursor_size * 8; + + dc->caps.cache_line_size = 64; + dc->caps.cache_num_ways = 16; + + /* Calculate the available MALL space */ + dc->caps.max_cab_allocation_bytes = dcn32_calc_num_avail_chans_for_mall( + dc, dc->ctx->dc_bios->vram_info.num_chans) * + dc->caps.mall_size_per_mem_channel * 1024 * 1024; + dc->caps.mall_size_total = dc->caps.max_cab_allocation_bytes; + + dc->caps.subvp_fw_processing_delay_us = 15; + dc->caps.subvp_drr_max_vblank_margin_us = 40; + dc->caps.subvp_prefetch_end_to_mall_start_us = 15; + dc->caps.subvp_swath_height_margin_lines = 16; + dc->caps.subvp_pstate_allow_width_us = 20; + dc->caps.subvp_vertical_int_margin_us = 30; + dc->caps.subvp_drr_vblank_start_margin_us = 100; // 100us margin + + dc->caps.max_slave_planes = 2; + dc->caps.max_slave_yuv_planes = 2; + dc->caps.max_slave_rgb_planes = 2; + dc->caps.post_blend_color_processing = true; + dc->caps.force_dp_tps4_for_cp2520 = true; + if (dc->config.forceHBR2CP2520) + dc->caps.force_dp_tps4_for_cp2520 = false; + dc->caps.dp_hpo = true; + dc->caps.dp_hdmi21_pcon_support = true; + dc->caps.edp_dsc_support = true; + dc->caps.extended_aux_timeout_support = true; + dc->caps.dmcub_support = true; + dc->caps.seamless_odm = true; + dc->caps.max_v_total = (1 << 15) - 1; + + /* Color pipeline capabilities */ + dc->caps.color.dpp.dcn_arch = 1; + dc->caps.color.dpp.input_lut_shared = 0; + dc->caps.color.dpp.icsc = 1; + dc->caps.color.dpp.dgam_ram = 0; // must use gamma_corr + dc->caps.color.dpp.dgam_rom_caps.srgb = 1; + dc->caps.color.dpp.dgam_rom_caps.bt2020 = 1; + dc->caps.color.dpp.dgam_rom_caps.gamma2_2 = 1; + dc->caps.color.dpp.dgam_rom_caps.pq = 1; + dc->caps.color.dpp.dgam_rom_caps.hlg = 1; + dc->caps.color.dpp.post_csc = 1; + dc->caps.color.dpp.gamma_corr = 1; + dc->caps.color.dpp.dgam_rom_for_yuv = 0; + + dc->caps.color.dpp.hw_3d_lut = 1; + dc->caps.color.dpp.ogam_ram = 0; // no OGAM in DPP since DCN1 + // no OGAM ROM on DCN2 and later ASICs + dc->caps.color.dpp.ogam_rom_caps.srgb = 0; + dc->caps.color.dpp.ogam_rom_caps.bt2020 = 0; + dc->caps.color.dpp.ogam_rom_caps.gamma2_2 = 0; + dc->caps.color.dpp.ogam_rom_caps.pq = 0; + dc->caps.color.dpp.ogam_rom_caps.hlg = 0; + dc->caps.color.dpp.ocsc = 0; + + dc->caps.color.mpc.gamut_remap = 1; + dc->caps.color.mpc.num_3dluts = pool->base.res_cap->num_mpc_3dlut; //4, configurable to be before or after BLND in MPCC + dc->caps.color.mpc.ogam_ram = 1; + dc->caps.color.mpc.ogam_rom_caps.srgb = 0; + dc->caps.color.mpc.ogam_rom_caps.bt2020 = 0; + dc->caps.color.mpc.ogam_rom_caps.gamma2_2 = 0; + dc->caps.color.mpc.ogam_rom_caps.pq = 0; + dc->caps.color.mpc.ogam_rom_caps.hlg = 0; + dc->caps.color.mpc.ocsc = 1; + + /* Use pipe context based otg sync logic */ + dc->config.use_pipe_ctx_sync_logic = true; + + dc->config.dc_mode_clk_limit_support = true; + /* read VBIOS LTTPR caps */ + { + if (ctx->dc_bios->funcs->get_lttpr_caps) { + enum bp_result bp_query_result; + uint8_t is_vbios_lttpr_enable = 0; + + bp_query_result = ctx->dc_bios->funcs->get_lttpr_caps(ctx->dc_bios, &is_vbios_lttpr_enable); + dc->caps.vbios_lttpr_enable = (bp_query_result == BP_RESULT_OK) && !!is_vbios_lttpr_enable; + } + + /* interop bit is implicit */ + { + dc->caps.vbios_lttpr_aware = true; + } + } + + if (dc->ctx->dce_environment == DCE_ENV_PRODUCTION_DRV) + dc->debug = debug_defaults_drv; + + // Init the vm_helper + if (dc->vm_helper) + vm_helper_init(dc->vm_helper, 16); + + /************************************************* + * Create resources * + *************************************************/ + + /* Clock Sources for Pixel Clock*/ + pool->base.clock_sources[DCN32_CLK_SRC_PLL0] = + dcn32_clock_source_create(ctx, ctx->dc_bios, + CLOCK_SOURCE_COMBO_PHY_PLL0, + &clk_src_regs[0], false); + pool->base.clock_sources[DCN32_CLK_SRC_PLL1] = + dcn32_clock_source_create(ctx, ctx->dc_bios, + CLOCK_SOURCE_COMBO_PHY_PLL1, + &clk_src_regs[1], false); + pool->base.clock_sources[DCN32_CLK_SRC_PLL2] = + dcn32_clock_source_create(ctx, ctx->dc_bios, + CLOCK_SOURCE_COMBO_PHY_PLL2, + &clk_src_regs[2], false); + pool->base.clock_sources[DCN32_CLK_SRC_PLL3] = + dcn32_clock_source_create(ctx, ctx->dc_bios, + CLOCK_SOURCE_COMBO_PHY_PLL3, + &clk_src_regs[3], false); + pool->base.clock_sources[DCN32_CLK_SRC_PLL4] = + dcn32_clock_source_create(ctx, ctx->dc_bios, + CLOCK_SOURCE_COMBO_PHY_PLL4, + &clk_src_regs[4], false); + + pool->base.clk_src_count = DCN32_CLK_SRC_TOTAL; + + /* todo: not reuse phy_pll registers */ + pool->base.dp_clock_source = + dcn32_clock_source_create(ctx, ctx->dc_bios, + CLOCK_SOURCE_ID_DP_DTO, + &clk_src_regs[0], true); + + for (i = 0; i < pool->base.clk_src_count; i++) { + if (pool->base.clock_sources[i] == NULL) { + dm_error("DC: failed to create clock sources!\n"); + BREAK_TO_DEBUGGER(); + goto create_fail; + } + } + + /* DCCG */ + pool->base.dccg = dccg32_create(ctx, &dccg_regs, &dccg_shift, &dccg_mask); + if (pool->base.dccg == NULL) { + dm_error("DC: failed to create dccg!\n"); + BREAK_TO_DEBUGGER(); + goto create_fail; + } + + /* DML */ + dml_init_instance(&dc->dml, &dcn3_2_soc, &dcn3_2_ip, DML_PROJECT_DCN32); + + /* IRQ Service */ + init_data.ctx = dc->ctx; + pool->base.irqs = dal_irq_service_dcn32_create(&init_data); + if (!pool->base.irqs) + goto create_fail; + + /* HUBBUB */ + pool->base.hubbub = dcn32_hubbub_create(ctx); + if (pool->base.hubbub == NULL) { + BREAK_TO_DEBUGGER(); + dm_error("DC: failed to create hubbub!\n"); + goto create_fail; + } + + /* HUBPs, DPPs, OPPs, TGs, ABMs */ + for (i = 0, j = 0; i < pool->base.res_cap->num_timing_generator; i++) { + + /* if pipe is disabled, skip instance of HW pipe, + * i.e, skip ASIC register instance + */ + if (pipe_fuses & 1 << i) + continue; + + /* HUBPs */ + pool->base.hubps[j] = dcn32_hubp_create(ctx, i); + if (pool->base.hubps[j] == NULL) { + BREAK_TO_DEBUGGER(); + dm_error( + "DC: failed to create hubps!\n"); + goto create_fail; + } + + /* DPPs */ + pool->base.dpps[j] = dcn32_dpp_create(ctx, i); + if (pool->base.dpps[j] == NULL) { + BREAK_TO_DEBUGGER(); + dm_error( + "DC: failed to create dpps!\n"); + goto create_fail; + } + + /* OPPs */ + pool->base.opps[j] = dcn32_opp_create(ctx, i); + if (pool->base.opps[j] == NULL) { + BREAK_TO_DEBUGGER(); + dm_error( + "DC: failed to create output pixel processor!\n"); + goto create_fail; + } + + /* TGs */ + pool->base.timing_generators[j] = dcn32_timing_generator_create( + ctx, i); + if (pool->base.timing_generators[j] == NULL) { + BREAK_TO_DEBUGGER(); + dm_error("DC: failed to create tg!\n"); + goto create_fail; + } + + /* ABMs */ + pool->base.multiple_abms[j] = dmub_abm_create(ctx, + &abm_regs[i], + &abm_shift, + &abm_mask); + if (pool->base.multiple_abms[j] == NULL) { + dm_error("DC: failed to create abm for pipe %d!\n", i); + BREAK_TO_DEBUGGER(); + goto create_fail; + } + + /* index for resource pool arrays for next valid pipe */ + j++; + } + + /* PSR */ + pool->base.psr = dmub_psr_create(ctx); + if (pool->base.psr == NULL) { + dm_error("DC: failed to create psr obj!\n"); + BREAK_TO_DEBUGGER(); + goto create_fail; + } + + /* MPCCs */ + pool->base.mpc = dcn32_mpc_create(ctx, pool->base.res_cap->num_timing_generator, pool->base.res_cap->num_mpc_3dlut); + if (pool->base.mpc == NULL) { + BREAK_TO_DEBUGGER(); + dm_error("DC: failed to create mpc!\n"); + goto create_fail; + } + + /* DSCs */ + for (i = 0; i < pool->base.res_cap->num_dsc; i++) { + pool->base.dscs[i] = dcn32_dsc_create(ctx, i); + if (pool->base.dscs[i] == NULL) { + BREAK_TO_DEBUGGER(); + dm_error("DC: failed to create display stream compressor %d!\n", i); + goto create_fail; + } + } + + /* DWB */ + if (!dcn32_dwbc_create(ctx, &pool->base)) { + BREAK_TO_DEBUGGER(); + dm_error("DC: failed to create dwbc!\n"); + goto create_fail; + } + + /* MMHUBBUB */ + if (!dcn32_mmhubbub_create(ctx, &pool->base)) { + BREAK_TO_DEBUGGER(); + dm_error("DC: failed to create mcif_wb!\n"); + goto create_fail; + } + + /* AUX and I2C */ + for (i = 0; i < pool->base.res_cap->num_ddc; i++) { + pool->base.engines[i] = dcn32_aux_engine_create(ctx, i); + if (pool->base.engines[i] == NULL) { + BREAK_TO_DEBUGGER(); + dm_error( + "DC:failed to create aux engine!!\n"); + goto create_fail; + } + pool->base.hw_i2cs[i] = dcn32_i2c_hw_create(ctx, i); + if (pool->base.hw_i2cs[i] == NULL) { + BREAK_TO_DEBUGGER(); + dm_error( + "DC:failed to create hw i2c!!\n"); + goto create_fail; + } + pool->base.sw_i2cs[i] = NULL; + } + + /* Audio, HWSeq, Stream Encoders including HPO and virtual, MPC 3D LUTs */ + if (!resource_construct(num_virtual_links, dc, &pool->base, + &res_create_funcs)) + goto create_fail; + + /* HW Sequencer init functions and Plane caps */ + dcn32_hw_sequencer_init_functions(dc); + + dc->caps.max_planes = pool->base.pipe_count; + + for (i = 0; i < dc->caps.max_planes; ++i) + dc->caps.planes[i] = plane_cap; + + dc->cap_funcs = cap_funcs; + + if (dc->ctx->dc_bios->fw_info.oem_i2c_present) { + ddc_init_data.ctx = dc->ctx; + ddc_init_data.link = NULL; + ddc_init_data.id.id = dc->ctx->dc_bios->fw_info.oem_i2c_obj_id; + ddc_init_data.id.enum_id = 0; + ddc_init_data.id.type = OBJECT_TYPE_GENERIC; + pool->base.oem_device = dc->link_srv->create_ddc_service(&ddc_init_data); + } else { + pool->base.oem_device = NULL; + } + + dc->dml2_options.dcn_pipe_count = pool->base.pipe_count; + dc->dml2_options.use_native_pstate_optimization = false; + dc->dml2_options.use_native_soc_bb_construction = true; + dc->dml2_options.minimize_dispclk_using_odm = true; + + dc->dml2_options.callbacks.dc = dc; + dc->dml2_options.callbacks.build_scaling_params = &resource_build_scaling_params; + dc->dml2_options.callbacks.can_support_mclk_switch_using_fw_based_vblank_stretch = &dcn30_can_support_mclk_switch_using_fw_based_vblank_stretch; + dc->dml2_options.callbacks.acquire_secondary_pipe_for_mpc_odm = &dc_resource_acquire_secondary_pipe_for_mpc_odm_legacy; + dc->dml2_options.callbacks.update_pipes_for_stream_with_slice_count = &resource_update_pipes_for_stream_with_slice_count; + dc->dml2_options.callbacks.update_pipes_for_plane_with_slice_count = &resource_update_pipes_for_plane_with_slice_count; + dc->dml2_options.callbacks.get_mpc_slice_index = &resource_get_mpc_slice_index; + dc->dml2_options.callbacks.get_odm_slice_index = &resource_get_odm_slice_index; + dc->dml2_options.callbacks.get_opp_head = &resource_get_opp_head; + + dc->dml2_options.svp_pstate.callbacks.dc = dc; + dc->dml2_options.svp_pstate.callbacks.add_plane_to_context = &dc_add_plane_to_context; + dc->dml2_options.svp_pstate.callbacks.add_stream_to_ctx = &dc_add_stream_to_ctx; + dc->dml2_options.svp_pstate.callbacks.build_scaling_params = &resource_build_scaling_params; + dc->dml2_options.svp_pstate.callbacks.create_plane = &dc_create_plane_state; + dc->dml2_options.svp_pstate.callbacks.remove_plane_from_context = &dc_remove_plane_from_context; + dc->dml2_options.svp_pstate.callbacks.remove_stream_from_ctx = &dc_remove_stream_from_ctx; + dc->dml2_options.svp_pstate.callbacks.create_stream_for_sink = &dc_create_stream_for_sink; + dc->dml2_options.svp_pstate.callbacks.plane_state_release = &dc_plane_state_release; + dc->dml2_options.svp_pstate.callbacks.stream_release = &dc_stream_release; + dc->dml2_options.svp_pstate.callbacks.release_dsc = &dcn20_release_dsc; + + dc->dml2_options.svp_pstate.subvp_fw_processing_delay_us = dc->caps.subvp_fw_processing_delay_us; + dc->dml2_options.svp_pstate.subvp_prefetch_end_to_mall_start_us = dc->caps.subvp_prefetch_end_to_mall_start_us; + dc->dml2_options.svp_pstate.subvp_pstate_allow_width_us = dc->caps.subvp_pstate_allow_width_us; + dc->dml2_options.svp_pstate.subvp_swath_height_margin_lines = dc->caps.subvp_swath_height_margin_lines; + + dc->dml2_options.svp_pstate.force_disable_subvp = dc->debug.force_disable_subvp; + dc->dml2_options.svp_pstate.force_enable_subvp = dc->debug.force_subvp_mclk_switch; + + dc->dml2_options.mall_cfg.cache_line_size_bytes = dc->caps.cache_line_size; + dc->dml2_options.mall_cfg.cache_num_ways = dc->caps.cache_num_ways; + dc->dml2_options.mall_cfg.max_cab_allocation_bytes = dc->caps.max_cab_allocation_bytes; + dc->dml2_options.mall_cfg.mblk_height_4bpe_pixels = DCN3_2_MBLK_HEIGHT_4BPE; + dc->dml2_options.mall_cfg.mblk_height_8bpe_pixels = DCN3_2_MBLK_HEIGHT_8BPE; + dc->dml2_options.mall_cfg.mblk_size_bytes = DCN3_2_MALL_MBLK_SIZE_BYTES; + dc->dml2_options.mall_cfg.mblk_width_pixels = DCN3_2_MBLK_WIDTH; + + dc->dml2_options.max_segments_per_hubp = 18; + dc->dml2_options.det_segment_size = DCN3_2_DET_SEG_SIZE; + dc->dml2_options.map_dc_pipes_with_callbacks = true; + + if (ASICREV_IS_GC_11_0_3(dc->ctx->asic_id.hw_internal_rev) && (dc->config.sdpif_request_limit_words_per_umc == 0)) + dc->config.sdpif_request_limit_words_per_umc = 16; + + DC_FP_END(); + + return true; + +create_fail: + + DC_FP_END(); + + dcn32_resource_destruct(pool); + + return false; +} + +struct resource_pool *dcn32_create_resource_pool( + const struct dc_init_data *init_data, + struct dc *dc) +{ + struct dcn32_resource_pool *pool = + kzalloc(sizeof(struct dcn32_resource_pool), GFP_KERNEL); + + if (!pool) + return NULL; + + if (dcn32_resource_construct(init_data->num_virtual_links, dc, pool)) + return &pool->base; + + BREAK_TO_DEBUGGER(); + kfree(pool); + return NULL; +} + +/* + * Find the most optimal free pipe from res_ctx, which could be used as a + * secondary dpp pipe for input opp head pipe. + * + * a free pipe - a pipe in input res_ctx not yet used for any streams or + * planes. + * secondary dpp pipe - a pipe gets inserted to a head OPP pipe's MPC blending + * tree. This is typical used for rendering MPO planes or additional offset + * areas in MPCC combine. + * + * Hardware Transition Minimization Algorithm for Finding a Secondary DPP Pipe + * ------------------------------------------------------------------------- + * + * PROBLEM: + * + * 1. There is a hardware limitation that a secondary DPP pipe cannot be + * transferred from one MPC blending tree to the other in a single frame. + * Otherwise it could cause glitches on the screen. + * + * For instance, we cannot transition from state 1 to state 2 in one frame. This + * is because PIPE1 is transferred from PIPE0's MPC blending tree over to + * PIPE2's MPC blending tree, which is not supported by hardware. + * To support this transition we need to first remove PIPE1 from PIPE0's MPC + * blending tree in one frame and then insert PIPE1 to PIPE2's MPC blending tree + * in the next frame. This is not optimal as it will delay the flip for two + * frames. + * + * State 1: + * PIPE0 -- secondary DPP pipe --> (PIPE1) + * PIPE2 -- secondary DPP pipe --> NONE + * + * State 2: + * PIPE0 -- secondary DPP pipe --> NONE + * PIPE2 -- secondary DPP pipe --> (PIPE1) + * + * 2. We want to in general minimize the unnecessary changes in pipe topology. + * If a pipe is already added in current blending tree and there are no changes + * to plane topology, we don't want to swap it with another free pipe + * unnecessarily in every update. Powering up and down a pipe would require a + * full update which delays the flip for 1 frame. If we use the original pipe + * we don't have to toggle its power. So we can flip faster. + */ +static int find_optimal_free_pipe_as_secondary_dpp_pipe( + const struct resource_context *cur_res_ctx, + struct resource_context *new_res_ctx, + const struct resource_pool *pool, + const struct pipe_ctx *new_opp_head) +{ + const struct pipe_ctx *cur_opp_head; + int free_pipe_idx; + + cur_opp_head = &cur_res_ctx->pipe_ctx[new_opp_head->pipe_idx]; + free_pipe_idx = resource_find_free_pipe_used_in_cur_mpc_blending_tree( + cur_res_ctx, new_res_ctx, cur_opp_head); + + /* Up until here if we have not found a free secondary pipe, we will + * need to wait for at least one frame to complete the transition + * sequence. + */ + if (free_pipe_idx == FREE_PIPE_INDEX_NOT_FOUND) + free_pipe_idx = recource_find_free_pipe_not_used_in_cur_res_ctx( + cur_res_ctx, new_res_ctx, pool); + + /* Up until here if we have not found a free secondary pipe, we will + * need to wait for at least two frames to complete the transition + * sequence. It really doesn't matter which pipe we decide take from + * current enabled pipes. It won't save our frame time when we swap only + * one pipe or more pipes. + */ + if (free_pipe_idx == FREE_PIPE_INDEX_NOT_FOUND) + free_pipe_idx = resource_find_free_pipe_used_as_cur_sec_dpp_in_mpcc_combine( + cur_res_ctx, new_res_ctx, pool); + + if (free_pipe_idx == FREE_PIPE_INDEX_NOT_FOUND) + free_pipe_idx = resource_find_any_free_pipe(new_res_ctx, pool); + + return free_pipe_idx; +} + +static struct pipe_ctx *find_idle_secondary_pipe_check_mpo( + struct resource_context *res_ctx, + const struct resource_pool *pool, + const struct pipe_ctx *primary_pipe) +{ + int i; + struct pipe_ctx *secondary_pipe = NULL; + struct pipe_ctx *next_odm_mpo_pipe = NULL; + int primary_index, preferred_pipe_idx; + struct pipe_ctx *old_primary_pipe = NULL; + + /* + * Modified from find_idle_secondary_pipe + * With windowed MPO and ODM, we want to avoid the case where we want a + * free pipe for the left side but the free pipe is being used on the + * right side. + * Add check on current_state if the primary_pipe is the left side, + * to check the right side ( primary_pipe->next_odm_pipe ) to see if + * it is using a pipe for MPO ( primary_pipe->next_odm_pipe->bottom_pipe ) + * - If so, then don't use this pipe + * EXCEPTION - 3 plane ( 2 MPO plane ) case + * - in this case, the primary pipe has already gotten a free pipe for the + * MPO window in the left + * - when it tries to get a free pipe for the MPO window on the right, + * it will see that it is already assigned to the right side + * ( primary_pipe->next_odm_pipe ). But in this case, we want this + * free pipe, since it will be for the right side. So add an + * additional condition, that skipping the free pipe on the right only + * applies if the primary pipe has no bottom pipe currently assigned + */ + if (primary_pipe) { + primary_index = primary_pipe->pipe_idx; + old_primary_pipe = &primary_pipe->stream->ctx->dc->current_state->res_ctx.pipe_ctx[primary_index]; + if ((old_primary_pipe->next_odm_pipe) && (old_primary_pipe->next_odm_pipe->bottom_pipe) + && (!primary_pipe->bottom_pipe)) + next_odm_mpo_pipe = old_primary_pipe->next_odm_pipe->bottom_pipe; + + preferred_pipe_idx = (pool->pipe_count - 1) - primary_pipe->pipe_idx; + if ((res_ctx->pipe_ctx[preferred_pipe_idx].stream == NULL) && + !(next_odm_mpo_pipe && next_odm_mpo_pipe->pipe_idx == preferred_pipe_idx)) { + secondary_pipe = &res_ctx->pipe_ctx[preferred_pipe_idx]; + secondary_pipe->pipe_idx = preferred_pipe_idx; + } + } + + /* + * search backwards for the second pipe to keep pipe + * assignment more consistent + */ + if (!secondary_pipe) + for (i = pool->pipe_count - 1; i >= 0; i--) { + if ((res_ctx->pipe_ctx[i].stream == NULL) && + !(next_odm_mpo_pipe && next_odm_mpo_pipe->pipe_idx == i)) { + secondary_pipe = &res_ctx->pipe_ctx[i]; + secondary_pipe->pipe_idx = i; + break; + } + } + + return secondary_pipe; +} + +static struct pipe_ctx *dcn32_acquire_idle_pipe_for_head_pipe_in_layer( + struct dc_state *state, + const struct resource_pool *pool, + struct dc_stream_state *stream, + const struct pipe_ctx *head_pipe) +{ + struct resource_context *res_ctx = &state->res_ctx; + struct pipe_ctx *idle_pipe, *pipe; + struct resource_context *old_ctx = &stream->ctx->dc->current_state->res_ctx; + int head_index; + + if (!head_pipe) + ASSERT(0); + + /* + * Modified from dcn20_acquire_idle_pipe_for_layer + * Check if head_pipe in old_context already has bottom_pipe allocated. + * - If so, check if that pipe is available in the current context. + * -- If so, reuse pipe from old_context + */ + head_index = head_pipe->pipe_idx; + pipe = &old_ctx->pipe_ctx[head_index]; + if (pipe->bottom_pipe && res_ctx->pipe_ctx[pipe->bottom_pipe->pipe_idx].stream == NULL) { + idle_pipe = &res_ctx->pipe_ctx[pipe->bottom_pipe->pipe_idx]; + idle_pipe->pipe_idx = pipe->bottom_pipe->pipe_idx; + } else { + idle_pipe = find_idle_secondary_pipe_check_mpo(res_ctx, pool, head_pipe); + if (!idle_pipe) + return NULL; + } + + idle_pipe->stream = head_pipe->stream; + idle_pipe->stream_res.tg = head_pipe->stream_res.tg; + idle_pipe->stream_res.opp = head_pipe->stream_res.opp; + + idle_pipe->plane_res.hubp = pool->hubps[idle_pipe->pipe_idx]; + idle_pipe->plane_res.ipp = pool->ipps[idle_pipe->pipe_idx]; + idle_pipe->plane_res.dpp = pool->dpps[idle_pipe->pipe_idx]; + idle_pipe->plane_res.mpcc_inst = pool->dpps[idle_pipe->pipe_idx]->inst; + + return idle_pipe; +} + +static int find_optimal_free_pipe_as_secondary_opp_head( + const struct resource_context *cur_res_ctx, + struct resource_context *new_res_ctx, + const struct resource_pool *pool, + const struct pipe_ctx *new_otg_master) +{ + const struct pipe_ctx *cur_otg_master; + int free_pipe_idx; + + cur_otg_master = &cur_res_ctx->pipe_ctx[new_otg_master->pipe_idx]; + free_pipe_idx = resource_find_free_pipe_used_as_sec_opp_head_by_cur_otg_master( + cur_res_ctx, new_res_ctx, cur_otg_master); + + /* Up until here if we have not found a free secondary pipe, we will + * need to wait for at least one frame to complete the transition + * sequence. + */ + if (free_pipe_idx == FREE_PIPE_INDEX_NOT_FOUND) + free_pipe_idx = recource_find_free_pipe_not_used_in_cur_res_ctx( + cur_res_ctx, new_res_ctx, pool); + + if (free_pipe_idx == FREE_PIPE_INDEX_NOT_FOUND) + free_pipe_idx = resource_find_any_free_pipe(new_res_ctx, pool); + + return free_pipe_idx; +} + +struct pipe_ctx *dcn32_acquire_free_pipe_as_secondary_dpp_pipe( + const struct dc_state *cur_ctx, + struct dc_state *new_ctx, + const struct resource_pool *pool, + const struct pipe_ctx *opp_head_pipe) +{ + + int free_pipe_idx; + struct pipe_ctx *free_pipe; + + if (!opp_head_pipe->stream->ctx->dc->config.enable_windowed_mpo_odm) + return dcn32_acquire_idle_pipe_for_head_pipe_in_layer( + new_ctx, pool, opp_head_pipe->stream, opp_head_pipe); + + free_pipe_idx = find_optimal_free_pipe_as_secondary_dpp_pipe( + &cur_ctx->res_ctx, &new_ctx->res_ctx, + pool, opp_head_pipe); + if (free_pipe_idx >= 0) { + free_pipe = &new_ctx->res_ctx.pipe_ctx[free_pipe_idx]; + free_pipe->pipe_idx = free_pipe_idx; + free_pipe->stream = opp_head_pipe->stream; + free_pipe->stream_res.tg = opp_head_pipe->stream_res.tg; + free_pipe->stream_res.opp = opp_head_pipe->stream_res.opp; + + free_pipe->plane_res.hubp = pool->hubps[free_pipe->pipe_idx]; + free_pipe->plane_res.ipp = pool->ipps[free_pipe->pipe_idx]; + free_pipe->plane_res.dpp = pool->dpps[free_pipe->pipe_idx]; + free_pipe->plane_res.mpcc_inst = + pool->dpps[free_pipe->pipe_idx]->inst; + } else { + ASSERT(opp_head_pipe); + free_pipe = NULL; + } + + return free_pipe; +} + +struct pipe_ctx *dcn32_acquire_free_pipe_as_secondary_opp_head( + const struct dc_state *cur_ctx, + struct dc_state *new_ctx, + const struct resource_pool *pool, + const struct pipe_ctx *otg_master) +{ + int free_pipe_idx = find_optimal_free_pipe_as_secondary_opp_head( + &cur_ctx->res_ctx, &new_ctx->res_ctx, + pool, otg_master); + struct pipe_ctx *free_pipe; + + if (free_pipe_idx >= 0) { + free_pipe = &new_ctx->res_ctx.pipe_ctx[free_pipe_idx]; + free_pipe->pipe_idx = free_pipe_idx; + free_pipe->stream = otg_master->stream; + free_pipe->stream_res.tg = otg_master->stream_res.tg; + free_pipe->stream_res.dsc = NULL; + free_pipe->stream_res.opp = pool->opps[free_pipe_idx]; + free_pipe->plane_res.mi = pool->mis[free_pipe_idx]; + free_pipe->plane_res.hubp = pool->hubps[free_pipe_idx]; + free_pipe->plane_res.ipp = pool->ipps[free_pipe_idx]; + free_pipe->plane_res.xfm = pool->transforms[free_pipe_idx]; + free_pipe->plane_res.dpp = pool->dpps[free_pipe_idx]; + free_pipe->plane_res.mpcc_inst = pool->dpps[free_pipe_idx]->inst; + if (free_pipe->stream->timing.flags.DSC == 1) { + dcn20_acquire_dsc(free_pipe->stream->ctx->dc, + &new_ctx->res_ctx, + &free_pipe->stream_res.dsc, + free_pipe_idx); + ASSERT(free_pipe->stream_res.dsc); + if (free_pipe->stream_res.dsc == NULL) { + memset(free_pipe, 0, sizeof(*free_pipe)); + free_pipe = NULL; + } + } + } else { + ASSERT(otg_master); + free_pipe = NULL; + } + + return free_pipe; +} + +unsigned int dcn32_calc_num_avail_chans_for_mall(struct dc *dc, int num_chans) +{ + /* + * DCN32 and DCN321 SKUs may have different sizes for MALL + * but we may not be able to access all the MALL space. + * If the num_chans is power of 2, then we can access all + * of the available MALL space. Otherwise, we can only + * access: + * + * max_cab_size_in_bytes = total_cache_size_in_bytes * + * ((2^floor(log2(num_chans)))/num_chans) + * + * Calculating the MALL sizes for all available SKUs, we + * have come up with the follow simplified check. + * - we have max_chans which provides the max MALL size. + * Each chans supports 4MB of MALL so: + * + * total_cache_size_in_bytes = max_chans * 4 MB + * + * - we have avail_chans which shows the number of channels + * we can use if we can't access the entire MALL space. + * It is generally half of max_chans + * - so we use the following checks: + * + * if (num_chans == max_chans), return max_chans + * if (num_chans < max_chans), return avail_chans + * + * - exception is GC_11_0_0 where we can't access max_chans, + * so we define max_avail_chans as the maximum available + * MALL space + * + */ + int gc_11_0_0_max_chans = 48; + int gc_11_0_0_max_avail_chans = 32; + int gc_11_0_0_avail_chans = 16; + int gc_11_0_3_max_chans = 16; + int gc_11_0_3_avail_chans = 8; + int gc_11_0_2_max_chans = 8; + int gc_11_0_2_avail_chans = 4; + + if (ASICREV_IS_GC_11_0_0(dc->ctx->asic_id.hw_internal_rev)) { + return (num_chans == gc_11_0_0_max_chans) ? + gc_11_0_0_max_avail_chans : gc_11_0_0_avail_chans; + } else if (ASICREV_IS_GC_11_0_2(dc->ctx->asic_id.hw_internal_rev)) { + return (num_chans == gc_11_0_2_max_chans) ? + gc_11_0_2_max_chans : gc_11_0_2_avail_chans; + } else { // if (ASICREV_IS_GC_11_0_3(dc->ctx->asic_id.hw_internal_rev)) { + return (num_chans == gc_11_0_3_max_chans) ? + gc_11_0_3_max_chans : gc_11_0_3_avail_chans; + } +} diff --git a/drivers/gpu/drm/amd/display/dc/resource/dcn32/dcn32_resource.h b/drivers/gpu/drm/amd/display/dc/resource/dcn32/dcn32_resource.h new file mode 100644 index 000000000000..b931008114c9 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/resource/dcn32/dcn32_resource.h @@ -0,0 +1,1263 @@ +/* + * Copyright 2020 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 _DCN32_RESOURCE_H_ +#define _DCN32_RESOURCE_H_ + +#include "core_types.h" + +#define DCN3_2_DEFAULT_DET_SIZE 256 +#define DCN3_2_MAX_DET_SIZE 1152 +#define DCN3_2_MIN_DET_SIZE 128 +#define DCN3_2_MIN_COMPBUF_SIZE_KB 128 +#define DCN3_2_DET_SEG_SIZE 64 +#define DCN3_2_MALL_MBLK_SIZE_BYTES 65536 // 64 * 1024 +#define DCN3_2_MBLK_WIDTH 128 +#define DCN3_2_MBLK_HEIGHT_4BPE 128 +#define DCN3_2_MBLK_HEIGHT_8BPE 64 +#define DCN3_2_DCFCLK_DS_INIT_KHZ 10000 // Choose 10Mhz for init DCFCLK DS freq +#define SUBVP_HIGH_REFRESH_LIST_LEN 4 +#define DCN3_2_MAX_SUBVP_PIXEL_RATE_MHZ 1800 +#define DCN3_2_VMIN_DISPCLK_HZ 717000000 + +#define TO_DCN32_RES_POOL(pool)\ + container_of(pool, struct dcn32_resource_pool, base) + +extern struct _vcs_dpi_ip_params_st dcn3_2_ip; +extern struct _vcs_dpi_soc_bounding_box_st dcn3_2_soc; + +struct subvp_high_refresh_list { + int min_refresh; + int max_refresh; + struct resolution { + int width; + int height; + } res[SUBVP_HIGH_REFRESH_LIST_LEN]; +}; + +struct dcn32_resource_pool { + struct resource_pool base; +}; + +struct resource_pool *dcn32_create_resource_pool( + const struct dc_init_data *init_data, + struct dc *dc); + +struct panel_cntl *dcn32_panel_cntl_create( + const struct panel_cntl_init_data *init_data); + +bool dcn32_acquire_post_bldn_3dlut( + struct resource_context *res_ctx, + const struct resource_pool *pool, + int mpcc_id, + struct dc_3dlut **lut, + struct dc_transfer_func **shaper); + +bool dcn32_release_post_bldn_3dlut( + struct resource_context *res_ctx, + const struct resource_pool *pool, + struct dc_3dlut **lut, + struct dc_transfer_func **shaper); + +bool dcn32_remove_phantom_pipes(struct dc *dc, + struct dc_state *context, bool fast_update); + +void dcn32_retain_phantom_pipes(struct dc *dc, + struct dc_state *context); + +void dcn32_add_phantom_pipes(struct dc *dc, + struct dc_state *context, + display_e2e_pipe_params_st *pipes, + unsigned int pipe_cnt, + unsigned int index); + +bool dcn32_validate_bandwidth(struct dc *dc, + struct dc_state *context, + bool fast_validate); + +int dcn32_populate_dml_pipes_from_context( + struct dc *dc, struct dc_state *context, + display_e2e_pipe_params_st *pipes, + bool fast_validate); + +void dcn32_calculate_wm_and_dlg( + struct dc *dc, struct dc_state *context, + display_e2e_pipe_params_st *pipes, + int pipe_cnt, + int vlevel); + +uint32_t dcn32_helper_mall_bytes_to_ways( + struct dc *dc, + uint32_t total_size_in_mall_bytes); + +uint32_t dcn32_helper_calculate_mall_bytes_for_cursor( + struct dc *dc, + struct pipe_ctx *pipe_ctx, + bool ignore_cursor_buf); + +uint32_t dcn32_helper_calculate_num_ways_for_subvp( + struct dc *dc, + struct dc_state *context); + +void dcn32_merge_pipes_for_subvp(struct dc *dc, + struct dc_state *context); + +bool dcn32_all_pipes_have_stream_and_plane(struct dc *dc, + struct dc_state *context); + +bool dcn32_subvp_in_use(struct dc *dc, + struct dc_state *context); + +bool dcn32_mpo_in_use(struct dc_state *context); + +bool dcn32_any_surfaces_rotated(struct dc *dc, struct dc_state *context); +bool dcn32_is_center_timing(struct pipe_ctx *pipe); +bool dcn32_is_psr_capable(struct pipe_ctx *pipe); + +struct pipe_ctx *dcn32_acquire_free_pipe_as_secondary_dpp_pipe( + const struct dc_state *cur_ctx, + struct dc_state *new_ctx, + const struct resource_pool *pool, + const struct pipe_ctx *opp_head_pipe); + +struct pipe_ctx *dcn32_acquire_free_pipe_as_secondary_opp_head( + const struct dc_state *cur_ctx, + struct dc_state *new_ctx, + const struct resource_pool *pool, + const struct pipe_ctx *otg_master); + +void dcn32_release_pipe(struct dc_state *context, + struct pipe_ctx *pipe, + const struct resource_pool *pool); + +void dcn32_determine_det_override(struct dc *dc, + struct dc_state *context, + display_e2e_pipe_params_st *pipes); + +void dcn32_set_det_allocations(struct dc *dc, struct dc_state *context, + display_e2e_pipe_params_st *pipes); + +void dcn32_save_mall_state(struct dc *dc, + struct dc_state *context, + struct mall_temp_config *temp_config); + +void dcn32_restore_mall_state(struct dc *dc, + struct dc_state *context, + struct mall_temp_config *temp_config); + +struct dc_stream_state *dcn32_can_support_mclk_switch_using_fw_based_vblank_stretch(struct dc *dc, const struct dc_state *context); + +bool dcn32_allow_subvp_with_active_margin(struct pipe_ctx *pipe); + +bool dcn32_allow_subvp_high_refresh_rate(struct dc *dc, struct dc_state *context, struct pipe_ctx *pipe); + +unsigned int dcn32_calc_num_avail_chans_for_mall(struct dc *dc, int num_chans); + +double dcn32_determine_max_vratio_prefetch(struct dc *dc, struct dc_state *context); + +bool dcn32_check_native_scaling_for_res(struct pipe_ctx *pipe, unsigned int width, unsigned int height); + +bool dcn32_subvp_drr_admissable(struct dc *dc, struct dc_state *context); + +bool dcn32_subvp_vblank_admissable(struct dc *dc, struct dc_state *context, int vlevel); + +/* definitions for run time init of reg offsets */ + +/* CLK SRC */ +#define CS_COMMON_REG_LIST_DCN3_0_RI(index, pllid) \ + SRI_ARR_ALPHABET(PIXCLK_RESYNC_CNTL, PHYPLL, index, pllid), \ + SRII_ARR_2(PHASE, DP_DTO, 0, index), \ + SRII_ARR_2(PHASE, DP_DTO, 1, index), \ + SRII_ARR_2(PHASE, DP_DTO, 2, index), \ + SRII_ARR_2(PHASE, DP_DTO, 3, index), \ + SRII_ARR_2(MODULO, DP_DTO, 0, index), \ + SRII_ARR_2(MODULO, DP_DTO, 1, index), \ + SRII_ARR_2(MODULO, DP_DTO, 2, index), \ + SRII_ARR_2(MODULO, DP_DTO, 3, index), \ + SRII_ARR_2(PIXEL_RATE_CNTL, OTG, 0, index), \ + SRII_ARR_2(PIXEL_RATE_CNTL, OTG, 1, index), \ + SRII_ARR_2(PIXEL_RATE_CNTL, OTG, 2, index), \ + SRII_ARR_2(PIXEL_RATE_CNTL, OTG, 3, index) + +/* ABM */ +#define ABM_DCN32_REG_LIST_RI(id) \ + SRI_ARR(DC_ABM1_HG_SAMPLE_RATE, ABM, id), \ + SRI_ARR(DC_ABM1_LS_SAMPLE_RATE, ABM, id), \ + SRI_ARR(BL1_PWM_BL_UPDATE_SAMPLE_RATE, ABM, id), \ + SRI_ARR(DC_ABM1_HG_MISC_CTRL, ABM, id), \ + SRI_ARR(DC_ABM1_IPCSC_COEFF_SEL, ABM, id), \ + SRI_ARR(BL1_PWM_CURRENT_ABM_LEVEL, ABM, id), \ + SRI_ARR(BL1_PWM_TARGET_ABM_LEVEL, ABM, id), \ + SRI_ARR(BL1_PWM_USER_LEVEL, ABM, id), \ + SRI_ARR(DC_ABM1_LS_MIN_MAX_PIXEL_VALUE_THRES, ABM, id), \ + SRI_ARR(DC_ABM1_HGLS_REG_READ_PROGRESS, ABM, id), \ + SRI_ARR(DC_ABM1_ACE_OFFSET_SLOPE_0, ABM, id), \ + SRI_ARR(DC_ABM1_ACE_THRES_12, ABM, id), NBIO_SR_ARR(BIOS_SCRATCH_2, id) + +/* Audio */ +#define AUD_COMMON_REG_LIST_RI(id) \ + SRI_ARR(AZALIA_F0_CODEC_ENDPOINT_INDEX, AZF0ENDPOINT, id), \ + SRI_ARR(AZALIA_F0_CODEC_ENDPOINT_DATA, AZF0ENDPOINT, id), \ + SR_ARR(AZALIA_F0_CODEC_FUNCTION_PARAMETER_STREAM_FORMATS, id), \ + SR_ARR(AZALIA_F0_CODEC_FUNCTION_PARAMETER_SUPPORTED_SIZE_RATES, id), \ + SR_ARR(AZALIA_F0_CODEC_FUNCTION_PARAMETER_POWER_STATES, id), \ + SR_ARR(DCCG_AUDIO_DTO_SOURCE, id), SR_ARR(DCCG_AUDIO_DTO0_MODULE, id), \ + SR_ARR(DCCG_AUDIO_DTO0_PHASE, id), SR_ARR(DCCG_AUDIO_DTO1_MODULE, id), \ + SR_ARR(DCCG_AUDIO_DTO1_PHASE, id) \ + +/* VPG */ + +#define VPG_DCN3_REG_LIST_RI(id) \ + SRI_ARR(VPG_GENERIC_STATUS, VPG, id), \ + SRI_ARR(VPG_GENERIC_PACKET_ACCESS_CTRL, VPG, id), \ + SRI_ARR(VPG_GENERIC_PACKET_DATA, VPG, id), \ + SRI_ARR(VPG_GSP_FRAME_UPDATE_CTRL, VPG, id), \ + SRI_ARR(VPG_GSP_IMMEDIATE_UPDATE_CTRL, VPG, id) + +/* AFMT */ +#define AFMT_DCN3_REG_LIST_RI(id) \ + SRI_ARR(AFMT_INFOFRAME_CONTROL0, AFMT, id), \ + SRI_ARR(AFMT_VBI_PACKET_CONTROL, AFMT, id), \ + SRI_ARR(AFMT_AUDIO_PACKET_CONTROL, AFMT, id), \ + SRI_ARR(AFMT_AUDIO_PACKET_CONTROL2, AFMT, id), \ + SRI_ARR(AFMT_AUDIO_SRC_CONTROL, AFMT, id), \ + SRI_ARR(AFMT_60958_0, AFMT, id), SRI_ARR(AFMT_60958_1, AFMT, id), \ + SRI_ARR(AFMT_60958_2, AFMT, id), SRI_ARR(AFMT_MEM_PWR, AFMT, id) + +/* APG */ +#define APG_DCN31_REG_LIST_RI(id) \ + SRI_ARR(APG_CONTROL, APG, id), SRI_ARR(APG_CONTROL2, APG, id), \ + SRI_ARR(APG_MEM_PWR, APG, id), SRI_ARR(APG_DBG_GEN_CONTROL, APG, id) + +/* Stream encoder */ +#define SE_DCN32_REG_LIST_RI(id) \ + SRI_ARR(AFMT_CNTL, DIG, id), SRI_ARR(DIG_FE_CNTL, DIG, id), \ + SRI_ARR(HDMI_CONTROL, DIG, id), SRI_ARR(HDMI_DB_CONTROL, DIG, id), \ + SRI_ARR(HDMI_GC, DIG, id), \ + SRI_ARR(HDMI_GENERIC_PACKET_CONTROL0, DIG, id), \ + SRI_ARR(HDMI_GENERIC_PACKET_CONTROL1, DIG, id), \ + SRI_ARR(HDMI_GENERIC_PACKET_CONTROL2, DIG, id), \ + SRI_ARR(HDMI_GENERIC_PACKET_CONTROL3, DIG, id), \ + SRI_ARR(HDMI_GENERIC_PACKET_CONTROL4, DIG, id), \ + SRI_ARR(HDMI_GENERIC_PACKET_CONTROL5, DIG, id), \ + SRI_ARR(HDMI_GENERIC_PACKET_CONTROL6, DIG, id), \ + SRI_ARR(HDMI_GENERIC_PACKET_CONTROL7, DIG, id), \ + SRI_ARR(HDMI_GENERIC_PACKET_CONTROL8, DIG, id), \ + SRI_ARR(HDMI_GENERIC_PACKET_CONTROL9, DIG, id), \ + SRI_ARR(HDMI_GENERIC_PACKET_CONTROL10, DIG, id), \ + SRI_ARR(HDMI_INFOFRAME_CONTROL0, DIG, id), \ + SRI_ARR(HDMI_INFOFRAME_CONTROL1, DIG, id), \ + SRI_ARR(HDMI_VBI_PACKET_CONTROL, DIG, id), \ + SRI_ARR(HDMI_AUDIO_PACKET_CONTROL, DIG, id), \ + SRI_ARR(HDMI_ACR_PACKET_CONTROL, DIG, id), \ + SRI_ARR(HDMI_ACR_32_0, DIG, id), SRI_ARR(HDMI_ACR_32_1, DIG, id), \ + SRI_ARR(HDMI_ACR_44_0, DIG, id), SRI_ARR(HDMI_ACR_44_1, DIG, id), \ + SRI_ARR(HDMI_ACR_48_0, DIG, id), SRI_ARR(HDMI_ACR_48_1, DIG, id), \ + SRI_ARR(DP_DB_CNTL, DP, id), SRI_ARR(DP_MSA_MISC, DP, id), \ + SRI_ARR(DP_MSA_VBID_MISC, DP, id), SRI_ARR(DP_MSA_COLORIMETRY, DP, id), \ + SRI_ARR(DP_MSA_TIMING_PARAM1, DP, id), \ + SRI_ARR(DP_MSA_TIMING_PARAM2, DP, id), \ + SRI_ARR(DP_MSA_TIMING_PARAM3, DP, id), \ + SRI_ARR(DP_MSA_TIMING_PARAM4, DP, id), \ + SRI_ARR(DP_MSE_RATE_CNTL, DP, id), SRI_ARR(DP_MSE_RATE_UPDATE, DP, id), \ + SRI_ARR(DP_PIXEL_FORMAT, DP, id), SRI_ARR(DP_SEC_CNTL, DP, id), \ + SRI_ARR(DP_SEC_CNTL1, DP, id), SRI_ARR(DP_SEC_CNTL2, DP, id), \ + SRI_ARR(DP_SEC_CNTL5, DP, id), SRI_ARR(DP_SEC_CNTL6, DP, id), \ + SRI_ARR(DP_STEER_FIFO, DP, id), SRI_ARR(DP_VID_M, DP, id), \ + SRI_ARR(DP_VID_N, DP, id), SRI_ARR(DP_VID_STREAM_CNTL, DP, id), \ + SRI_ARR(DP_VID_TIMING, DP, id), SRI_ARR(DP_SEC_AUD_N, DP, id), \ + SRI_ARR(DP_SEC_TIMESTAMP, DP, id), SRI_ARR(DP_DSC_CNTL, DP, id), \ + SRI_ARR(DP_SEC_METADATA_TRANSMISSION, DP, id), \ + SRI_ARR(HDMI_METADATA_PACKET_CONTROL, DIG, id), \ + SRI_ARR(DP_SEC_FRAMING4, DP, id), SRI_ARR(DP_GSP11_CNTL, DP, id), \ + SRI_ARR(DME_CONTROL, DME, id), \ + SRI_ARR(DP_SEC_METADATA_TRANSMISSION, DP, id), \ + SRI_ARR(HDMI_METADATA_PACKET_CONTROL, DIG, id), \ + SRI_ARR(DIG_FE_CNTL, DIG, id), SRI_ARR(DIG_CLOCK_PATTERN, DIG, id), \ + SRI_ARR(DIG_FIFO_CTRL0, DIG, id) + +/* Aux regs */ + +#define AUX_REG_LIST_RI(id) \ + SRI_ARR(AUX_CONTROL, DP_AUX, id), SRI_ARR(AUX_DPHY_RX_CONTROL0, DP_AUX, id), \ + SRI_ARR(AUX_DPHY_RX_CONTROL1, DP_AUX, id) + +#define DCN2_AUX_REG_LIST_RI(id) \ + AUX_REG_LIST_RI(id), SRI_ARR(AUX_DPHY_TX_CONTROL, DP_AUX, id) + +/* HDP */ +#define HPD_REG_LIST_RI(id) SRI_ARR(DC_HPD_CONTROL, HPD, id) + +/* Link encoder */ +#define LE_DCN3_REG_LIST_RI(id) \ + SRI_ARR(DIG_BE_CNTL, DIG, id), SRI_ARR(DIG_BE_EN_CNTL, DIG, id), \ + SRI_ARR(TMDS_CTL_BITS, DIG, id), \ + SRI_ARR(TMDS_DCBALANCER_CONTROL, DIG, id), SRI_ARR(DP_CONFIG, DP, id), \ + SRI_ARR(DP_DPHY_CNTL, DP, id), SRI_ARR(DP_DPHY_PRBS_CNTL, DP, id), \ + SRI_ARR(DP_DPHY_SCRAM_CNTL, DP, id), SRI_ARR(DP_DPHY_SYM0, DP, id), \ + SRI_ARR(DP_DPHY_SYM1, DP, id), SRI_ARR(DP_DPHY_SYM2, DP, id), \ + SRI_ARR(DP_DPHY_TRAINING_PATTERN_SEL, DP, id), \ + SRI_ARR(DP_LINK_CNTL, DP, id), SRI_ARR(DP_LINK_FRAMING_CNTL, DP, id), \ + SRI_ARR(DP_MSE_SAT0, DP, id), SRI_ARR(DP_MSE_SAT1, DP, id), \ + SRI_ARR(DP_MSE_SAT2, DP, id), SRI_ARR(DP_MSE_SAT_UPDATE, DP, id), \ + SRI_ARR(DP_SEC_CNTL, DP, id), SRI_ARR(DP_VID_STREAM_CNTL, DP, id), \ + SRI_ARR(DP_DPHY_FAST_TRAINING, DP, id), SRI_ARR(DP_SEC_CNTL1, DP, id), \ + SRI_ARR(DP_DPHY_BS_SR_SWAP_CNTL, DP, id), \ + SRI_ARR(DP_DPHY_HBR2_PATTERN_CONTROL, DP, id) + +#define LE_DCN31_REG_LIST_RI(id) \ + LE_DCN3_REG_LIST_RI(id), SRI_ARR(DP_DPHY_INTERNAL_CTRL, DP, id), \ + SR_ARR(DIO_LINKA_CNTL, id), SR_ARR(DIO_LINKB_CNTL, id), \ + SR_ARR(DIO_LINKC_CNTL, id), SR_ARR(DIO_LINKD_CNTL, id), \ + SR_ARR(DIO_LINKE_CNTL, id), SR_ARR(DIO_LINKF_CNTL, id) + +#define UNIPHY_DCN2_REG_LIST_RI(id, phyid) \ + SRI_ARR_ALPHABET(CLOCK_ENABLE, SYMCLK, id, phyid), \ + SRI_ARR_ALPHABET(CHANNEL_XBAR_CNTL, UNIPHY, id, phyid) + +/* HPO DP stream encoder */ +#define DCN3_1_HPO_DP_STREAM_ENC_REG_LIST_RI(id) \ + SR_ARR(DP_STREAM_MAPPER_CONTROL0, id), \ + SR_ARR(DP_STREAM_MAPPER_CONTROL1, id), \ + SR_ARR(DP_STREAM_MAPPER_CONTROL2, id), \ + SR_ARR(DP_STREAM_MAPPER_CONTROL3, id), \ + SRI_ARR(DP_STREAM_ENC_CLOCK_CONTROL, DP_STREAM_ENC, id), \ + SRI_ARR(DP_STREAM_ENC_INPUT_MUX_CONTROL, DP_STREAM_ENC, id), \ + SRI_ARR(DP_STREAM_ENC_AUDIO_CONTROL, DP_STREAM_ENC, id), \ + SRI_ARR(DP_STREAM_ENC_CLOCK_RAMP_ADJUSTER_FIFO_STATUS_CONTROL0, DP_STREAM_ENC, id), \ + SRI_ARR(DP_SYM32_ENC_CONTROL, DP_SYM32_ENC, id), \ + SRI_ARR(DP_SYM32_ENC_VID_PIXEL_FORMAT, DP_SYM32_ENC, id), \ + SRI_ARR(DP_SYM32_ENC_VID_PIXEL_FORMAT_DOUBLE_BUFFER_CONTROL, DP_SYM32_ENC, id), \ + SRI_ARR(DP_SYM32_ENC_VID_MSA0, DP_SYM32_ENC, id), \ + SRI_ARR(DP_SYM32_ENC_VID_MSA1, DP_SYM32_ENC, id), \ + SRI_ARR(DP_SYM32_ENC_VID_MSA2, DP_SYM32_ENC, id), \ + SRI_ARR(DP_SYM32_ENC_VID_MSA3, DP_SYM32_ENC, id), \ + SRI_ARR(DP_SYM32_ENC_VID_MSA4, DP_SYM32_ENC, id), \ + SRI_ARR(DP_SYM32_ENC_VID_MSA5, DP_SYM32_ENC, id), \ + SRI_ARR(DP_SYM32_ENC_VID_MSA6, DP_SYM32_ENC, id), \ + SRI_ARR(DP_SYM32_ENC_VID_MSA7, DP_SYM32_ENC, id), \ + SRI_ARR(DP_SYM32_ENC_VID_MSA8, DP_SYM32_ENC, id), \ + SRI_ARR(DP_SYM32_ENC_VID_MSA_CONTROL, DP_SYM32_ENC, id), \ + SRI_ARR(DP_SYM32_ENC_VID_MSA_DOUBLE_BUFFER_CONTROL, DP_SYM32_ENC, id), \ + SRI_ARR(DP_SYM32_ENC_VID_FIFO_CONTROL, DP_SYM32_ENC, id), \ + SRI_ARR(DP_SYM32_ENC_VID_STREAM_CONTROL, DP_SYM32_ENC, id), \ + SRI_ARR(DP_SYM32_ENC_VID_VBID_CONTROL, DP_SYM32_ENC, id), \ + SRI_ARR(DP_SYM32_ENC_SDP_CONTROL, DP_SYM32_ENC, id), \ + SRI_ARR(DP_SYM32_ENC_SDP_GSP_CONTROL0, DP_SYM32_ENC, id), \ + SRI_ARR(DP_SYM32_ENC_SDP_GSP_CONTROL2, DP_SYM32_ENC, id), \ + SRI_ARR(DP_SYM32_ENC_SDP_GSP_CONTROL3, DP_SYM32_ENC, id), \ + SRI_ARR(DP_SYM32_ENC_SDP_GSP_CONTROL5, DP_SYM32_ENC, id), \ + SRI_ARR(DP_SYM32_ENC_SDP_GSP_CONTROL11, DP_SYM32_ENC, id), \ + SRI_ARR(DP_SYM32_ENC_SDP_METADATA_PACKET_CONTROL, DP_SYM32_ENC, id), \ + SRI_ARR(DP_SYM32_ENC_SDP_AUDIO_CONTROL0, DP_SYM32_ENC, id), \ + SRI_ARR(DP_SYM32_ENC_VID_CRC_CONTROL, DP_SYM32_ENC, id), \ + SRI_ARR(DP_SYM32_ENC_HBLANK_CONTROL, DP_SYM32_ENC, id) + +/* HPO DP link encoder regs */ +#define DCN3_1_HPO_DP_LINK_ENC_REG_LIST_RI(id) \ + SRI_ARR(DP_LINK_ENC_CLOCK_CONTROL, DP_LINK_ENC, id), \ + SRI_ARR(DP_DPHY_SYM32_CONTROL, DP_DPHY_SYM32, id), \ + SRI_ARR(DP_DPHY_SYM32_STATUS, DP_DPHY_SYM32, id), \ + SRI_ARR(DP_DPHY_SYM32_TP_CONFIG, DP_DPHY_SYM32, id), \ + SRI_ARR(DP_DPHY_SYM32_TP_PRBS_SEED0, DP_DPHY_SYM32, id), \ + SRI_ARR(DP_DPHY_SYM32_TP_PRBS_SEED1, DP_DPHY_SYM32, id), \ + SRI_ARR(DP_DPHY_SYM32_TP_PRBS_SEED2, DP_DPHY_SYM32, id), \ + SRI_ARR(DP_DPHY_SYM32_TP_PRBS_SEED3, DP_DPHY_SYM32, id), \ + SRI_ARR(DP_DPHY_SYM32_TP_SQ_PULSE, DP_DPHY_SYM32, id), \ + SRI_ARR(DP_DPHY_SYM32_TP_CUSTOM0, DP_DPHY_SYM32, id), \ + SRI_ARR(DP_DPHY_SYM32_TP_CUSTOM1, DP_DPHY_SYM32, id), \ + SRI_ARR(DP_DPHY_SYM32_TP_CUSTOM2, DP_DPHY_SYM32, id), \ + SRI_ARR(DP_DPHY_SYM32_TP_CUSTOM3, DP_DPHY_SYM32, id), \ + SRI_ARR(DP_DPHY_SYM32_TP_CUSTOM4, DP_DPHY_SYM32, id), \ + SRI_ARR(DP_DPHY_SYM32_TP_CUSTOM5, DP_DPHY_SYM32, id), \ + SRI_ARR(DP_DPHY_SYM32_TP_CUSTOM6, DP_DPHY_SYM32, id), \ + SRI_ARR(DP_DPHY_SYM32_TP_CUSTOM7, DP_DPHY_SYM32, id), \ + SRI_ARR(DP_DPHY_SYM32_TP_CUSTOM8, DP_DPHY_SYM32, id), \ + SRI_ARR(DP_DPHY_SYM32_TP_CUSTOM9, DP_DPHY_SYM32, id), \ + SRI_ARR(DP_DPHY_SYM32_TP_CUSTOM10, DP_DPHY_SYM32, id), \ + SRI_ARR(DP_DPHY_SYM32_SAT_VC0, DP_DPHY_SYM32, id), \ + SRI_ARR(DP_DPHY_SYM32_SAT_VC1, DP_DPHY_SYM32, id), \ + SRI_ARR(DP_DPHY_SYM32_SAT_VC2, DP_DPHY_SYM32, id), \ + SRI_ARR(DP_DPHY_SYM32_SAT_VC3, DP_DPHY_SYM32, id), \ + SRI_ARR(DP_DPHY_SYM32_VC_RATE_CNTL0, DP_DPHY_SYM32, id), \ + SRI_ARR(DP_DPHY_SYM32_VC_RATE_CNTL1, DP_DPHY_SYM32, id), \ + SRI_ARR(DP_DPHY_SYM32_VC_RATE_CNTL2, DP_DPHY_SYM32, id), \ + SRI_ARR(DP_DPHY_SYM32_VC_RATE_CNTL3, DP_DPHY_SYM32, id), \ + SRI_ARR(DP_DPHY_SYM32_SAT_UPDATE, DP_DPHY_SYM32, id) + +/* DPP */ +#define DPP_REG_LIST_DCN30_COMMON_RI(id) \ + SRI_ARR(CM_DEALPHA, CM, id), SRI_ARR(CM_MEM_PWR_STATUS, CM, id), \ + SRI_ARR(CM_BIAS_CR_R, CM, id), SRI_ARR(CM_BIAS_Y_G_CB_B, CM, id), \ + SRI_ARR(PRE_DEGAM, CNVC_CFG, id), SRI_ARR(CM_GAMCOR_CONTROL, CM, id), \ + SRI_ARR(CM_GAMCOR_LUT_CONTROL, CM, id), \ + SRI_ARR(CM_GAMCOR_LUT_INDEX, CM, id), \ + SRI_ARR(CM_GAMCOR_LUT_INDEX, CM, id), \ + SRI_ARR(CM_GAMCOR_LUT_DATA, CM, id), \ + SRI_ARR(CM_GAMCOR_RAMB_START_CNTL_B, CM, id), \ + SRI_ARR(CM_GAMCOR_RAMB_START_CNTL_G, CM, id), \ + SRI_ARR(CM_GAMCOR_RAMB_START_CNTL_R, CM, id), \ + SRI_ARR(CM_GAMCOR_RAMB_START_SLOPE_CNTL_B, CM, id), \ + SRI_ARR(CM_GAMCOR_RAMB_START_SLOPE_CNTL_G, CM, id), \ + SRI_ARR(CM_GAMCOR_RAMB_START_SLOPE_CNTL_R, CM, id), \ + SRI_ARR(CM_GAMCOR_RAMB_END_CNTL1_B, CM, id), \ + SRI_ARR(CM_GAMCOR_RAMB_END_CNTL2_B, CM, id), \ + SRI_ARR(CM_GAMCOR_RAMB_END_CNTL1_G, CM, id), \ + SRI_ARR(CM_GAMCOR_RAMB_END_CNTL2_G, CM, id), \ + SRI_ARR(CM_GAMCOR_RAMB_END_CNTL1_R, CM, id), \ + SRI_ARR(CM_GAMCOR_RAMB_END_CNTL2_R, CM, id), \ + SRI_ARR(CM_GAMCOR_RAMB_REGION_0_1, CM, id), \ + SRI_ARR(CM_GAMCOR_RAMB_REGION_32_33, CM, id), \ + SRI_ARR(CM_GAMCOR_RAMB_OFFSET_B, CM, id), \ + SRI_ARR(CM_GAMCOR_RAMB_OFFSET_G, CM, id), \ + SRI_ARR(CM_GAMCOR_RAMB_OFFSET_R, CM, id), \ + SRI_ARR(CM_GAMCOR_RAMB_START_BASE_CNTL_B, CM, id), \ + SRI_ARR(CM_GAMCOR_RAMB_START_BASE_CNTL_G, CM, id), \ + SRI_ARR(CM_GAMCOR_RAMB_START_BASE_CNTL_R, CM, id), \ + SRI_ARR(CM_GAMCOR_RAMA_START_CNTL_B, CM, id), \ + SRI_ARR(CM_GAMCOR_RAMA_START_CNTL_G, CM, id), \ + SRI_ARR(CM_GAMCOR_RAMA_START_CNTL_R, CM, id), \ + SRI_ARR(CM_GAMCOR_RAMA_START_SLOPE_CNTL_B, CM, id), \ + SRI_ARR(CM_GAMCOR_RAMA_START_SLOPE_CNTL_G, CM, id), \ + SRI_ARR(CM_GAMCOR_RAMA_START_SLOPE_CNTL_R, CM, id), \ + SRI_ARR(CM_GAMCOR_RAMA_END_CNTL1_B, CM, id), \ + SRI_ARR(CM_GAMCOR_RAMA_END_CNTL2_B, CM, id), \ + SRI_ARR(CM_GAMCOR_RAMA_END_CNTL1_G, CM, id), \ + SRI_ARR(CM_GAMCOR_RAMA_END_CNTL2_G, CM, id), \ + SRI_ARR(CM_GAMCOR_RAMA_END_CNTL1_R, CM, id), \ + SRI_ARR(CM_GAMCOR_RAMA_END_CNTL2_R, CM, id), \ + SRI_ARR(CM_GAMCOR_RAMA_REGION_0_1, CM, id), \ + SRI_ARR(CM_GAMCOR_RAMA_REGION_32_33, CM, id), \ + SRI_ARR(CM_GAMCOR_RAMA_OFFSET_B, CM, id), \ + SRI_ARR(CM_GAMCOR_RAMA_OFFSET_G, CM, id), \ + SRI_ARR(CM_GAMCOR_RAMA_OFFSET_R, CM, id), \ + SRI_ARR(CM_GAMCOR_RAMA_START_BASE_CNTL_B, CM, id), \ + SRI_ARR(CM_GAMCOR_RAMA_START_BASE_CNTL_G, CM, id), \ + SRI_ARR(CM_GAMCOR_RAMA_START_BASE_CNTL_R, CM, id), \ + SRI_ARR(CM_GAMUT_REMAP_CONTROL, CM, id), \ + SRI_ARR(CM_GAMUT_REMAP_C11_C12, CM, id), \ + SRI_ARR(CM_GAMUT_REMAP_C13_C14, CM, id), \ + SRI_ARR(CM_GAMUT_REMAP_C21_C22, CM, id), \ + SRI_ARR(CM_GAMUT_REMAP_C23_C24, CM, id), \ + SRI_ARR(CM_GAMUT_REMAP_C31_C32, CM, id), \ + SRI_ARR(CM_GAMUT_REMAP_C33_C34, CM, id), \ + SRI_ARR(CM_GAMUT_REMAP_B_C11_C12, CM, id), \ + SRI_ARR(CM_GAMUT_REMAP_B_C13_C14, CM, id), \ + SRI_ARR(CM_GAMUT_REMAP_B_C21_C22, CM, id), \ + SRI_ARR(CM_GAMUT_REMAP_B_C23_C24, CM, id), \ + SRI_ARR(CM_GAMUT_REMAP_B_C31_C32, CM, id), \ + SRI_ARR(CM_GAMUT_REMAP_B_C33_C34, CM, id), \ + SRI_ARR(DSCL_EXT_OVERSCAN_LEFT_RIGHT, DSCL, id), \ + SRI_ARR(DSCL_EXT_OVERSCAN_TOP_BOTTOM, DSCL, id), \ + SRI_ARR(OTG_H_BLANK, DSCL, id), SRI_ARR(OTG_V_BLANK, DSCL, id), \ + SRI_ARR(SCL_MODE, DSCL, id), SRI_ARR(LB_DATA_FORMAT, DSCL, id), \ + SRI_ARR(LB_MEMORY_CTRL, DSCL, id), SRI_ARR(DSCL_AUTOCAL, DSCL, id), \ + SRI_ARR(DSCL_CONTROL, DSCL, id), \ + SRI_ARR(SCL_TAP_CONTROL, DSCL, id), \ + SRI_ARR(SCL_COEF_RAM_TAP_SELECT, DSCL, id), \ + SRI_ARR(SCL_COEF_RAM_TAP_DATA, DSCL, id), \ + SRI_ARR(DSCL_2TAP_CONTROL, DSCL, id), SRI_ARR(MPC_SIZE, DSCL, id), \ + SRI_ARR(SCL_HORZ_FILTER_SCALE_RATIO, DSCL, id), \ + SRI_ARR(SCL_VERT_FILTER_SCALE_RATIO, DSCL, id), \ + SRI_ARR(SCL_HORZ_FILTER_SCALE_RATIO_C, DSCL, id), \ + SRI_ARR(SCL_VERT_FILTER_SCALE_RATIO_C, DSCL, id), \ + SRI_ARR(SCL_HORZ_FILTER_INIT, DSCL, id), \ + SRI_ARR(SCL_HORZ_FILTER_INIT_C, DSCL, id), \ + SRI_ARR(SCL_VERT_FILTER_INIT, DSCL, id), \ + SRI_ARR(SCL_VERT_FILTER_INIT_C, DSCL, id), \ + SRI_ARR(RECOUT_START, DSCL, id), SRI_ARR(RECOUT_SIZE, DSCL, id), \ + SRI_ARR(PRE_DEALPHA, CNVC_CFG, id), SRI_ARR(PRE_REALPHA, CNVC_CFG, id), \ + SRI_ARR(PRE_CSC_MODE, CNVC_CFG, id), \ + SRI_ARR(PRE_CSC_C11_C12, CNVC_CFG, id), \ + SRI_ARR(PRE_CSC_C33_C34, CNVC_CFG, id), \ + SRI_ARR(PRE_CSC_B_C11_C12, CNVC_CFG, id), \ + SRI_ARR(PRE_CSC_B_C33_C34, CNVC_CFG, id), \ + SRI_ARR(CM_POST_CSC_CONTROL, CM, id), \ + SRI_ARR(CM_POST_CSC_C11_C12, CM, id), \ + SRI_ARR(CM_POST_CSC_C33_C34, CM, id), \ + SRI_ARR(CM_POST_CSC_B_C11_C12, CM, id), \ + SRI_ARR(CM_POST_CSC_B_C33_C34, CM, id), \ + SRI_ARR(CM_MEM_PWR_CTRL, CM, id), SRI_ARR(CM_CONTROL, CM, id), \ + SRI_ARR(FORMAT_CONTROL, CNVC_CFG, id), \ + SRI_ARR(CNVC_SURFACE_PIXEL_FORMAT, CNVC_CFG, id), \ + SRI_ARR(CURSOR0_CONTROL, CNVC_CUR, id), \ + SRI_ARR(CURSOR0_COLOR0, CNVC_CUR, id), \ + SRI_ARR(CURSOR0_COLOR1, CNVC_CUR, id), \ + SRI_ARR(CURSOR0_FP_SCALE_BIAS, CNVC_CUR, id), \ + SRI_ARR(DPP_CONTROL, DPP_TOP, id), SRI_ARR(CM_HDR_MULT_COEF, CM, id), \ + SRI_ARR(CURSOR_CONTROL, CURSOR0_, id), \ + SRI_ARR(ALPHA_2BIT_LUT, CNVC_CFG, id), \ + SRI_ARR(FCNV_FP_BIAS_R, CNVC_CFG, id), \ + SRI_ARR(FCNV_FP_BIAS_G, CNVC_CFG, id), \ + SRI_ARR(FCNV_FP_BIAS_B, CNVC_CFG, id), \ + SRI_ARR(FCNV_FP_SCALE_R, CNVC_CFG, id), \ + SRI_ARR(FCNV_FP_SCALE_G, CNVC_CFG, id), \ + SRI_ARR(FCNV_FP_SCALE_B, CNVC_CFG, id), \ + SRI_ARR(COLOR_KEYER_CONTROL, CNVC_CFG, id), \ + SRI_ARR(COLOR_KEYER_ALPHA, CNVC_CFG, id), \ + SRI_ARR(COLOR_KEYER_RED, CNVC_CFG, id), \ + SRI_ARR(COLOR_KEYER_GREEN, CNVC_CFG, id), \ + SRI_ARR(COLOR_KEYER_BLUE, CNVC_CFG, id), \ + SRI_ARR(CURSOR_CONTROL, CURSOR0_, id), \ + SRI_ARR(OBUF_MEM_PWR_CTRL, DSCL, id), \ + SRI_ARR(DSCL_MEM_PWR_STATUS, DSCL, id), \ + SRI_ARR(DSCL_MEM_PWR_CTRL, DSCL, id) + +/* OPP */ +#define OPP_REG_LIST_DCN_RI(id) \ + SRI_ARR(FMT_BIT_DEPTH_CONTROL, FMT, id), SRI_ARR(FMT_CONTROL, FMT, id), \ + SRI_ARR(FMT_DITHER_RAND_R_SEED, FMT, id), \ + SRI_ARR(FMT_DITHER_RAND_G_SEED, FMT, id), \ + SRI_ARR(FMT_DITHER_RAND_B_SEED, FMT, id), \ + SRI_ARR(FMT_CLAMP_CNTL, FMT, id), \ + SRI_ARR(FMT_DYNAMIC_EXP_CNTL, FMT, id), \ + SRI_ARR(FMT_MAP420_MEMORY_CONTROL, FMT, id), \ + SRI_ARR(OPPBUF_CONTROL, OPPBUF, id), \ + SRI_ARR(OPPBUF_3D_PARAMETERS_0, OPPBUF, id), \ + SRI_ARR(OPPBUF_3D_PARAMETERS_1, OPPBUF, id), \ + SRI_ARR(OPP_PIPE_CONTROL, OPP_PIPE, id) \ + +#define OPP_REG_LIST_DCN10_RI(id) OPP_REG_LIST_DCN_RI(id) + +#define OPP_DPG_REG_LIST_RI(id) \ + SRI_ARR(DPG_CONTROL, DPG, id), SRI_ARR(DPG_DIMENSIONS, DPG, id), \ + SRI_ARR(DPG_OFFSET_SEGMENT, DPG, id), SRI_ARR(DPG_COLOUR_B_CB, DPG, id), \ + SRI_ARR(DPG_COLOUR_G_Y, DPG, id), SRI_ARR(DPG_COLOUR_R_CR, DPG, id), \ + SRI_ARR(DPG_RAMP_CONTROL, DPG, id), SRI_ARR(DPG_STATUS, DPG, id) + +#define OPP_REG_LIST_DCN30_RI(id) \ + OPP_REG_LIST_DCN10_RI(id), OPP_DPG_REG_LIST_RI(id), \ + SRI_ARR(FMT_422_CONTROL, FMT, id) + +/* Aux engine regs */ +#define AUX_COMMON_REG_LIST0_RI(id) \ + SRI_ARR(AUX_CONTROL, DP_AUX, id), SRI_ARR(AUX_ARB_CONTROL, DP_AUX, id), \ + SRI_ARR(AUX_SW_DATA, DP_AUX, id), SRI_ARR(AUX_SW_CONTROL, DP_AUX, id), \ + SRI_ARR(AUX_INTERRUPT_CONTROL, DP_AUX, id), \ + SRI_ARR(AUX_DPHY_RX_CONTROL1, DP_AUX, id), \ + SRI_ARR(AUX_SW_STATUS, DP_AUX, id) + +/* DWBC */ +#define DWBC_COMMON_REG_LIST_DCN30_RI(id) \ + SR_ARR(DWB_ENABLE_CLK_CTRL, id), SR_ARR(DWB_MEM_PWR_CTRL, id), \ + SR_ARR(FC_MODE_CTRL, id), SR_ARR(FC_FLOW_CTRL, id), \ + SR_ARR(FC_WINDOW_START, id), SR_ARR(FC_WINDOW_SIZE, id), \ + SR_ARR(FC_SOURCE_SIZE, id), SR_ARR(DWB_UPDATE_CTRL, id), \ + SR_ARR(DWB_CRC_CTRL, id), SR_ARR(DWB_CRC_MASK_R_G, id), \ + SR_ARR(DWB_CRC_MASK_B_A, id), SR_ARR(DWB_CRC_VAL_R_G, id), \ + SR_ARR(DWB_CRC_VAL_B_A, id), SR_ARR(DWB_OUT_CTRL, id), \ + SR_ARR(DWB_MMHUBBUB_BACKPRESSURE_CNT_EN, id), \ + SR_ARR(DWB_MMHUBBUB_BACKPRESSURE_CNT, id), \ + SR_ARR(DWB_HOST_READ_CONTROL, id), SR_ARR(DWB_SOFT_RESET, id), \ + SR_ARR(DWB_HDR_MULT_COEF, id), SR_ARR(DWB_GAMUT_REMAP_MODE, id), \ + SR_ARR(DWB_GAMUT_REMAP_COEF_FORMAT, id), \ + SR_ARR(DWB_GAMUT_REMAPA_C11_C12, id), \ + SR_ARR(DWB_GAMUT_REMAPA_C13_C14, id), \ + SR_ARR(DWB_GAMUT_REMAPA_C21_C22, id), \ + SR_ARR(DWB_GAMUT_REMAPA_C23_C24, id), \ + SR_ARR(DWB_GAMUT_REMAPA_C31_C32, id), \ + SR_ARR(DWB_GAMUT_REMAPA_C33_C34, id), \ + SR_ARR(DWB_GAMUT_REMAPB_C11_C12, id), \ + SR_ARR(DWB_GAMUT_REMAPB_C13_C14, id), \ + SR_ARR(DWB_GAMUT_REMAPB_C21_C22, id), \ + SR_ARR(DWB_GAMUT_REMAPB_C23_C24, id), \ + SR_ARR(DWB_GAMUT_REMAPB_C31_C32, id), \ + SR_ARR(DWB_GAMUT_REMAPB_C33_C34, id), SR_ARR(DWB_OGAM_CONTROL, id), \ + SR_ARR(DWB_OGAM_LUT_INDEX, id), SR_ARR(DWB_OGAM_LUT_DATA, id), \ + SR_ARR(DWB_OGAM_LUT_CONTROL, id), \ + SR_ARR(DWB_OGAM_RAMA_START_CNTL_B, id), \ + SR_ARR(DWB_OGAM_RAMA_START_CNTL_G, id), \ + SR_ARR(DWB_OGAM_RAMA_START_CNTL_R, id), \ + SR_ARR(DWB_OGAM_RAMA_START_BASE_CNTL_B, id), \ + SR_ARR(DWB_OGAM_RAMA_START_SLOPE_CNTL_B, id), \ + SR_ARR(DWB_OGAM_RAMA_START_BASE_CNTL_G, id), \ + SR_ARR(DWB_OGAM_RAMA_START_SLOPE_CNTL_G, id), \ + SR_ARR(DWB_OGAM_RAMA_START_BASE_CNTL_R, id), \ + SR_ARR(DWB_OGAM_RAMA_START_SLOPE_CNTL_R, id), \ + SR_ARR(DWB_OGAM_RAMA_END_CNTL1_B, id), \ + SR_ARR(DWB_OGAM_RAMA_END_CNTL2_B, id), \ + SR_ARR(DWB_OGAM_RAMA_END_CNTL1_G, id), \ + SR_ARR(DWB_OGAM_RAMA_END_CNTL2_G, id), \ + SR_ARR(DWB_OGAM_RAMA_END_CNTL1_R, id), \ + SR_ARR(DWB_OGAM_RAMA_END_CNTL2_R, id), \ + SR_ARR(DWB_OGAM_RAMA_OFFSET_B, id), SR_ARR(DWB_OGAM_RAMA_OFFSET_G, id), \ + SR_ARR(DWB_OGAM_RAMA_OFFSET_R, id), \ + SR_ARR(DWB_OGAM_RAMA_REGION_0_1, id), \ + SR_ARR(DWB_OGAM_RAMA_REGION_2_3, id), \ + SR_ARR(DWB_OGAM_RAMA_REGION_4_5, id), \ + SR_ARR(DWB_OGAM_RAMA_REGION_6_7, id), \ + SR_ARR(DWB_OGAM_RAMA_REGION_8_9, id), \ + SR_ARR(DWB_OGAM_RAMA_REGION_10_11, id), \ + SR_ARR(DWB_OGAM_RAMA_REGION_12_13, id), \ + SR_ARR(DWB_OGAM_RAMA_REGION_14_15, id), \ + SR_ARR(DWB_OGAM_RAMA_REGION_16_17, id), \ + SR_ARR(DWB_OGAM_RAMA_REGION_18_19, id), \ + SR_ARR(DWB_OGAM_RAMA_REGION_20_21, id), \ + SR_ARR(DWB_OGAM_RAMA_REGION_22_23, id), \ + SR_ARR(DWB_OGAM_RAMA_REGION_24_25, id), \ + SR_ARR(DWB_OGAM_RAMA_REGION_26_27, id), \ + SR_ARR(DWB_OGAM_RAMA_REGION_28_29, id), \ + SR_ARR(DWB_OGAM_RAMA_REGION_30_31, id), \ + SR_ARR(DWB_OGAM_RAMA_REGION_32_33, id), \ + SR_ARR(DWB_OGAM_RAMB_START_CNTL_B, id), \ + SR_ARR(DWB_OGAM_RAMB_START_CNTL_G, id), \ + SR_ARR(DWB_OGAM_RAMB_START_CNTL_R, id), \ + SR_ARR(DWB_OGAM_RAMB_START_BASE_CNTL_B, id), \ + SR_ARR(DWB_OGAM_RAMB_START_SLOPE_CNTL_B, id), \ + SR_ARR(DWB_OGAM_RAMB_START_BASE_CNTL_G, id), \ + SR_ARR(DWB_OGAM_RAMB_START_SLOPE_CNTL_G, id), \ + SR_ARR(DWB_OGAM_RAMB_START_BASE_CNTL_R, id), \ + SR_ARR(DWB_OGAM_RAMB_START_SLOPE_CNTL_R, id), \ + SR_ARR(DWB_OGAM_RAMB_END_CNTL1_B, id), \ + SR_ARR(DWB_OGAM_RAMB_END_CNTL2_B, id), \ + SR_ARR(DWB_OGAM_RAMB_END_CNTL1_G, id), \ + SR_ARR(DWB_OGAM_RAMB_END_CNTL2_G, id), \ + SR_ARR(DWB_OGAM_RAMB_END_CNTL1_R, id), \ + SR_ARR(DWB_OGAM_RAMB_END_CNTL2_R, id), \ + SR_ARR(DWB_OGAM_RAMB_OFFSET_B, id), SR_ARR(DWB_OGAM_RAMB_OFFSET_G, id), \ + SR_ARR(DWB_OGAM_RAMB_OFFSET_R, id), \ + SR_ARR(DWB_OGAM_RAMB_REGION_0_1, id), \ + SR_ARR(DWB_OGAM_RAMB_REGION_2_3, id), \ + SR_ARR(DWB_OGAM_RAMB_REGION_4_5, id), \ + SR_ARR(DWB_OGAM_RAMB_REGION_6_7, id), \ + SR_ARR(DWB_OGAM_RAMB_REGION_8_9, id), \ + SR_ARR(DWB_OGAM_RAMB_REGION_10_11, id), \ + SR_ARR(DWB_OGAM_RAMB_REGION_12_13, id), \ + SR_ARR(DWB_OGAM_RAMB_REGION_14_15, id), \ + SR_ARR(DWB_OGAM_RAMB_REGION_16_17, id), \ + SR_ARR(DWB_OGAM_RAMB_REGION_18_19, id), \ + SR_ARR(DWB_OGAM_RAMB_REGION_20_21, id), \ + SR_ARR(DWB_OGAM_RAMB_REGION_22_23, id), \ + SR_ARR(DWB_OGAM_RAMB_REGION_24_25, id), \ + SR_ARR(DWB_OGAM_RAMB_REGION_26_27, id), \ + SR_ARR(DWB_OGAM_RAMB_REGION_28_29, id), \ + SR_ARR(DWB_OGAM_RAMB_REGION_30_31, id), \ + SR_ARR(DWB_OGAM_RAMB_REGION_32_33, id) + +/* MCIF */ + +#define MCIF_WB_COMMON_REG_LIST_DCN32_RI(inst) \ + SRI2_ARR(MCIF_WB_BUFMGR_SW_CONTROL, MCIF_WB, inst), \ + SRI2_ARR(MCIF_WB_BUFMGR_STATUS, MCIF_WB, inst), \ + SRI2_ARR(MCIF_WB_BUF_PITCH, MCIF_WB, inst), \ + SRI2_ARR(MCIF_WB_BUF_1_STATUS, MCIF_WB, inst), \ + SRI2_ARR(MCIF_WB_BUF_1_STATUS2, MCIF_WB, inst), \ + SRI2_ARR(MCIF_WB_BUF_2_STATUS, MCIF_WB, inst), \ + SRI2_ARR(MCIF_WB_BUF_2_STATUS2, MCIF_WB, inst), \ + SRI2_ARR(MCIF_WB_BUF_3_STATUS, MCIF_WB, inst), \ + SRI2_ARR(MCIF_WB_BUF_3_STATUS2, MCIF_WB, inst), \ + SRI2_ARR(MCIF_WB_BUF_4_STATUS, MCIF_WB, inst), \ + SRI2_ARR(MCIF_WB_BUF_4_STATUS2, MCIF_WB, inst), \ + SRI2_ARR(MCIF_WB_ARBITRATION_CONTROL, MCIF_WB, inst), \ + SRI2_ARR(MCIF_WB_SCLK_CHANGE, MCIF_WB, inst), \ + SRI2_ARR(MCIF_WB_BUF_1_ADDR_Y, MCIF_WB, inst), \ + SRI2_ARR(MCIF_WB_BUF_1_ADDR_C, MCIF_WB, inst), \ + SRI2_ARR(MCIF_WB_BUF_2_ADDR_Y, MCIF_WB, inst), \ + SRI2_ARR(MCIF_WB_BUF_2_ADDR_C, MCIF_WB, inst), \ + SRI2_ARR(MCIF_WB_BUF_3_ADDR_Y, MCIF_WB, inst), \ + SRI2_ARR(MCIF_WB_BUF_3_ADDR_C, MCIF_WB, inst), \ + SRI2_ARR(MCIF_WB_BUF_4_ADDR_Y, MCIF_WB, inst), \ + SRI2_ARR(MCIF_WB_BUF_4_ADDR_C, MCIF_WB, inst), \ + SRI2_ARR(MCIF_WB_BUFMGR_VCE_CONTROL, MCIF_WB, inst), \ + SRI2_ARR(MCIF_WB_NB_PSTATE_LATENCY_WATERMARK, MMHUBBUB, inst), \ + SRI2_ARR(MCIF_WB_NB_PSTATE_CONTROL, MCIF_WB, inst), \ + SRI2_ARR(MCIF_WB_WATERMARK, MMHUBBUB, inst), \ + SRI2_ARR(MCIF_WB_CLOCK_GATER_CONTROL, MCIF_WB, inst), \ + SRI2_ARR(MCIF_WB_SELF_REFRESH_CONTROL, MCIF_WB, inst), \ + SRI2_ARR(MULTI_LEVEL_QOS_CTRL, MCIF_WB, inst), \ + SRI2_ARR(MCIF_WB_SECURITY_LEVEL, MCIF_WB, inst), \ + SRI2_ARR(MCIF_WB_BUF_LUMA_SIZE, MCIF_WB, inst), \ + SRI2_ARR(MCIF_WB_BUF_CHROMA_SIZE, MCIF_WB, inst), \ + SRI2_ARR(MCIF_WB_BUF_1_ADDR_Y_HIGH, MCIF_WB, inst), \ + SRI2_ARR(MCIF_WB_BUF_1_ADDR_C_HIGH, MCIF_WB, inst), \ + SRI2_ARR(MCIF_WB_BUF_2_ADDR_Y_HIGH, MCIF_WB, inst), \ + SRI2_ARR(MCIF_WB_BUF_2_ADDR_C_HIGH, MCIF_WB, inst), \ + SRI2_ARR(MCIF_WB_BUF_3_ADDR_Y_HIGH, MCIF_WB, inst), \ + SRI2_ARR(MCIF_WB_BUF_3_ADDR_C_HIGH, MCIF_WB, inst), \ + SRI2_ARR(MCIF_WB_BUF_4_ADDR_Y_HIGH, MCIF_WB, inst), \ + SRI2_ARR(MCIF_WB_BUF_4_ADDR_C_HIGH, MCIF_WB, inst), \ + SRI2_ARR(MCIF_WB_BUF_1_RESOLUTION, MCIF_WB, inst), \ + SRI2_ARR(MCIF_WB_BUF_2_RESOLUTION, MCIF_WB, inst), \ + SRI2_ARR(MCIF_WB_BUF_3_RESOLUTION, MCIF_WB, inst), \ + SRI2_ARR(MCIF_WB_BUF_4_RESOLUTION, MCIF_WB, inst), \ + SRI2_ARR(MMHUBBUB_MEM_PWR_CNTL, MMHUBBUB, inst), \ + SRI2_ARR(MMHUBBUB_WARMUP_ADDR_REGION, MMHUBBUB, inst), \ + SRI2_ARR(MMHUBBUB_WARMUP_BASE_ADDR_HIGH, MMHUBBUB, inst), \ + SRI2_ARR(MMHUBBUB_WARMUP_BASE_ADDR_LOW, MMHUBBUB, inst), \ + SRI2_ARR(MMHUBBUB_WARMUP_CONTROL_STATUS, MMHUBBUB, inst) + +/* DSC */ + +#define DSC_REG_LIST_DCN20_RI(id) \ + SRI_ARR(DSC_TOP_CONTROL, DSC_TOP, id), \ + SRI_ARR(DSC_DEBUG_CONTROL, DSC_TOP, id), \ + SRI_ARR(DSCC_CONFIG0, DSCC, id), SRI_ARR(DSCC_CONFIG1, DSCC, id), \ + SRI_ARR(DSCC_STATUS, DSCC, id), \ + SRI_ARR(DSCC_INTERRUPT_CONTROL_STATUS, DSCC, id), \ + SRI_ARR(DSCC_PPS_CONFIG0, DSCC, id), \ + SRI_ARR(DSCC_PPS_CONFIG1, DSCC, id), \ + SRI_ARR(DSCC_PPS_CONFIG2, DSCC, id), \ + SRI_ARR(DSCC_PPS_CONFIG3, DSCC, id), \ + SRI_ARR(DSCC_PPS_CONFIG4, DSCC, id), \ + SRI_ARR(DSCC_PPS_CONFIG5, DSCC, id), \ + SRI_ARR(DSCC_PPS_CONFIG6, DSCC, id), \ + SRI_ARR(DSCC_PPS_CONFIG7, DSCC, id), \ + SRI_ARR(DSCC_PPS_CONFIG8, DSCC, id), \ + SRI_ARR(DSCC_PPS_CONFIG9, DSCC, id), \ + SRI_ARR(DSCC_PPS_CONFIG10, DSCC, id), \ + SRI_ARR(DSCC_PPS_CONFIG11, DSCC, id), \ + SRI_ARR(DSCC_PPS_CONFIG12, DSCC, id), \ + SRI_ARR(DSCC_PPS_CONFIG13, DSCC, id), \ + SRI_ARR(DSCC_PPS_CONFIG14, DSCC, id), \ + SRI_ARR(DSCC_PPS_CONFIG15, DSCC, id), \ + SRI_ARR(DSCC_PPS_CONFIG16, DSCC, id), \ + SRI_ARR(DSCC_PPS_CONFIG17, DSCC, id), \ + SRI_ARR(DSCC_PPS_CONFIG18, DSCC, id), \ + SRI_ARR(DSCC_PPS_CONFIG19, DSCC, id), \ + SRI_ARR(DSCC_PPS_CONFIG20, DSCC, id), \ + SRI_ARR(DSCC_PPS_CONFIG21, DSCC, id), \ + SRI_ARR(DSCC_PPS_CONFIG22, DSCC, id), \ + SRI_ARR(DSCC_MEM_POWER_CONTROL, DSCC, id), \ + SRI_ARR(DSCC_R_Y_SQUARED_ERROR_LOWER, DSCC, id), \ + SRI_ARR(DSCC_R_Y_SQUARED_ERROR_UPPER, DSCC, id), \ + SRI_ARR(DSCC_G_CB_SQUARED_ERROR_LOWER, DSCC, id), \ + SRI_ARR(DSCC_G_CB_SQUARED_ERROR_UPPER, DSCC, id), \ + SRI_ARR(DSCC_B_CR_SQUARED_ERROR_LOWER, DSCC, id), \ + SRI_ARR(DSCC_B_CR_SQUARED_ERROR_UPPER, DSCC, id), \ + SRI_ARR(DSCC_MAX_ABS_ERROR0, DSCC, id), \ + SRI_ARR(DSCC_MAX_ABS_ERROR1, DSCC, id), \ + SRI_ARR(DSCC_RATE_BUFFER0_MAX_FULLNESS_LEVEL, DSCC, id), \ + SRI_ARR(DSCC_RATE_BUFFER1_MAX_FULLNESS_LEVEL, DSCC, id), \ + SRI_ARR(DSCC_RATE_BUFFER2_MAX_FULLNESS_LEVEL, DSCC, id), \ + SRI_ARR(DSCC_RATE_BUFFER3_MAX_FULLNESS_LEVEL, DSCC, id), \ + SRI_ARR(DSCC_RATE_CONTROL_BUFFER0_MAX_FULLNESS_LEVEL, DSCC, id), \ + SRI_ARR(DSCC_RATE_CONTROL_BUFFER1_MAX_FULLNESS_LEVEL, DSCC, id), \ + SRI_ARR(DSCC_RATE_CONTROL_BUFFER2_MAX_FULLNESS_LEVEL, DSCC, id), \ + SRI_ARR(DSCC_RATE_CONTROL_BUFFER3_MAX_FULLNESS_LEVEL, DSCC, id), \ + SRI_ARR(DSCCIF_CONFIG0, DSCCIF, id), \ + SRI_ARR(DSCCIF_CONFIG1, DSCCIF, id), \ + SRI_ARR(DSCRM_DSC_FORWARD_CONFIG, DSCRM, id) + +/* MPC */ + +#define MPC_DWB_MUX_REG_LIST_DCN3_0_RI(inst) \ + SRII_DWB(DWB_MUX, MUX, MPC_DWB, inst) + +#define MPC_OUT_MUX_COMMON_REG_LIST_DCN1_0_RI(inst) \ + SRII(MUX, MPC_OUT, inst), VUPDATE_SRII(CUR, VUPDATE_LOCK_SET, inst) + +#define MPC_OUT_MUX_REG_LIST_DCN3_0_RI(inst) \ + MPC_OUT_MUX_COMMON_REG_LIST_DCN1_0_RI(inst), SRII(CSC_MODE, MPC_OUT, inst), \ + SRII(CSC_C11_C12_A, MPC_OUT, inst), SRII(CSC_C33_C34_A, MPC_OUT, inst), \ + SRII(CSC_C11_C12_B, MPC_OUT, inst), SRII(CSC_C33_C34_B, MPC_OUT, inst), \ + SRII(DENORM_CONTROL, MPC_OUT, inst), \ + SRII(DENORM_CLAMP_G_Y, MPC_OUT, inst), \ + SRII(DENORM_CLAMP_B_CB, MPC_OUT, inst), SR(MPC_OUT_CSC_COEF_FORMAT) + +#define MPC_COMMON_REG_LIST_DCN1_0_RI(inst) \ + SRII(MPCC_TOP_SEL, MPCC, inst), SRII(MPCC_BOT_SEL, MPCC, inst), \ + SRII(MPCC_CONTROL, MPCC, inst), SRII(MPCC_STATUS, MPCC, inst), \ + SRII(MPCC_OPP_ID, MPCC, inst), SRII(MPCC_BG_G_Y, MPCC, inst), \ + SRII(MPCC_BG_R_CR, MPCC, inst), SRII(MPCC_BG_B_CB, MPCC, inst), \ + SRII(MPCC_SM_CONTROL, MPCC, inst), \ + SRII(MPCC_UPDATE_LOCK_SEL, MPCC, inst) + +#define MPC_REG_LIST_DCN3_0_RI(inst) \ + MPC_COMMON_REG_LIST_DCN1_0_RI(inst), SRII(MPCC_TOP_GAIN, MPCC, inst), \ + SRII(MPCC_BOT_GAIN_INSIDE, MPCC, inst), \ + SRII(MPCC_BOT_GAIN_OUTSIDE, MPCC, inst), \ + SRII(MPCC_MEM_PWR_CTRL, MPCC, inst), \ + SRII(MPCC_OGAM_LUT_INDEX, MPCC_OGAM, inst), \ + SRII(MPCC_OGAM_LUT_DATA, MPCC_OGAM, inst), \ + SRII(MPCC_GAMUT_REMAP_COEF_FORMAT, MPCC_OGAM, inst), \ + SRII(MPCC_GAMUT_REMAP_MODE, MPCC_OGAM, inst), \ + SRII(MPC_GAMUT_REMAP_C11_C12_A, MPCC_OGAM, inst), \ + SRII(MPC_GAMUT_REMAP_C33_C34_A, MPCC_OGAM, inst), \ + SRII(MPC_GAMUT_REMAP_C11_C12_B, MPCC_OGAM, inst), \ + SRII(MPC_GAMUT_REMAP_C33_C34_B, MPCC_OGAM, inst), \ + SRII(MPCC_OGAM_RAMA_START_CNTL_B, MPCC_OGAM, inst), \ + SRII(MPCC_OGAM_RAMA_START_CNTL_G, MPCC_OGAM, inst), \ + SRII(MPCC_OGAM_RAMA_START_CNTL_R, MPCC_OGAM, inst), \ + SRII(MPCC_OGAM_RAMA_START_SLOPE_CNTL_B, MPCC_OGAM, inst), \ + SRII(MPCC_OGAM_RAMA_START_SLOPE_CNTL_G, MPCC_OGAM, inst), \ + SRII(MPCC_OGAM_RAMA_START_SLOPE_CNTL_R, MPCC_OGAM, inst), \ + SRII(MPCC_OGAM_RAMA_END_CNTL1_B, MPCC_OGAM, inst), \ + SRII(MPCC_OGAM_RAMA_END_CNTL2_B, MPCC_OGAM, inst), \ + SRII(MPCC_OGAM_RAMA_END_CNTL1_G, MPCC_OGAM, inst), \ + SRII(MPCC_OGAM_RAMA_END_CNTL2_G, MPCC_OGAM, inst), \ + SRII(MPCC_OGAM_RAMA_END_CNTL1_R, MPCC_OGAM, inst), \ + SRII(MPCC_OGAM_RAMA_END_CNTL2_R, MPCC_OGAM, inst), \ + SRII(MPCC_OGAM_RAMA_REGION_0_1, MPCC_OGAM, inst), \ + SRII(MPCC_OGAM_RAMA_REGION_32_33, MPCC_OGAM, inst), \ + SRII(MPCC_OGAM_RAMA_OFFSET_B, MPCC_OGAM, inst), \ + SRII(MPCC_OGAM_RAMA_OFFSET_G, MPCC_OGAM, inst), \ + SRII(MPCC_OGAM_RAMA_OFFSET_R, MPCC_OGAM, inst), \ + SRII(MPCC_OGAM_RAMA_START_BASE_CNTL_B, MPCC_OGAM, inst), \ + SRII(MPCC_OGAM_RAMA_START_BASE_CNTL_G, MPCC_OGAM, inst), \ + SRII(MPCC_OGAM_RAMA_START_BASE_CNTL_R, MPCC_OGAM, inst), \ + SRII(MPCC_OGAM_RAMB_START_CNTL_B, MPCC_OGAM, inst), \ + SRII(MPCC_OGAM_RAMB_START_CNTL_G, MPCC_OGAM, inst), \ + SRII(MPCC_OGAM_RAMB_START_CNTL_R, MPCC_OGAM, inst), \ + SRII(MPCC_OGAM_RAMB_START_SLOPE_CNTL_B, MPCC_OGAM, inst), \ + SRII(MPCC_OGAM_RAMB_START_SLOPE_CNTL_G, MPCC_OGAM, inst), \ + SRII(MPCC_OGAM_RAMB_START_SLOPE_CNTL_R, MPCC_OGAM, inst), \ + SRII(MPCC_OGAM_RAMB_END_CNTL1_B, MPCC_OGAM, inst), \ + SRII(MPCC_OGAM_RAMB_END_CNTL2_B, MPCC_OGAM, inst), \ + SRII(MPCC_OGAM_RAMB_END_CNTL1_G, MPCC_OGAM, inst), \ + SRII(MPCC_OGAM_RAMB_END_CNTL2_G, MPCC_OGAM, inst), \ + SRII(MPCC_OGAM_RAMB_END_CNTL1_R, MPCC_OGAM, inst), \ + SRII(MPCC_OGAM_RAMB_END_CNTL2_R, MPCC_OGAM, inst), \ + SRII(MPCC_OGAM_RAMB_REGION_0_1, MPCC_OGAM, inst), \ + SRII(MPCC_OGAM_RAMB_REGION_32_33, MPCC_OGAM, inst), \ + SRII(MPCC_OGAM_RAMB_OFFSET_B, MPCC_OGAM, inst), \ + SRII(MPCC_OGAM_RAMB_OFFSET_G, MPCC_OGAM, inst), \ + SRII(MPCC_OGAM_RAMB_OFFSET_R, MPCC_OGAM, inst), \ + SRII(MPCC_OGAM_RAMB_START_BASE_CNTL_B, MPCC_OGAM, inst), \ + SRII(MPCC_OGAM_RAMB_START_BASE_CNTL_G, MPCC_OGAM, inst), \ + SRII(MPCC_OGAM_RAMB_START_BASE_CNTL_R, MPCC_OGAM, inst), \ + SRII(MPCC_OGAM_CONTROL, MPCC_OGAM, inst), \ + SRII(MPCC_OGAM_LUT_CONTROL, MPCC_OGAM, inst) + +#define MPC_REG_LIST_DCN3_2_RI(inst) \ + MPC_REG_LIST_DCN3_0_RI(inst),\ + SRII(MPCC_MOVABLE_CM_LOCATION_CONTROL, MPCC, inst),\ + SRII(MPCC_MCM_SHAPER_CONTROL, MPCC_MCM, inst),\ + SRII(MPCC_MCM_SHAPER_OFFSET_R, MPCC_MCM, inst),\ + SRII(MPCC_MCM_SHAPER_OFFSET_G, MPCC_MCM, inst),\ + SRII(MPCC_MCM_SHAPER_OFFSET_B, MPCC_MCM, inst),\ + SRII(MPCC_MCM_SHAPER_SCALE_R, MPCC_MCM, inst),\ + SRII(MPCC_MCM_SHAPER_SCALE_G_B, MPCC_MCM, inst),\ + SRII(MPCC_MCM_SHAPER_LUT_INDEX, MPCC_MCM, inst),\ + SRII(MPCC_MCM_SHAPER_LUT_DATA, MPCC_MCM, inst),\ + SRII(MPCC_MCM_SHAPER_LUT_WRITE_EN_MASK, MPCC_MCM, inst),\ + SRII(MPCC_MCM_SHAPER_RAMA_START_CNTL_B, MPCC_MCM, inst),\ + SRII(MPCC_MCM_SHAPER_RAMA_START_CNTL_G, MPCC_MCM, inst),\ + SRII(MPCC_MCM_SHAPER_RAMA_START_CNTL_R, MPCC_MCM, inst),\ + SRII(MPCC_MCM_SHAPER_RAMA_END_CNTL_B, MPCC_MCM, inst),\ + SRII(MPCC_MCM_SHAPER_RAMA_END_CNTL_G, MPCC_MCM, inst),\ + SRII(MPCC_MCM_SHAPER_RAMA_END_CNTL_R, MPCC_MCM, inst),\ + SRII(MPCC_MCM_SHAPER_RAMA_REGION_0_1, MPCC_MCM, inst),\ + SRII(MPCC_MCM_SHAPER_RAMA_REGION_2_3, MPCC_MCM, inst),\ + SRII(MPCC_MCM_SHAPER_RAMA_REGION_4_5, MPCC_MCM, inst),\ + SRII(MPCC_MCM_SHAPER_RAMA_REGION_6_7, MPCC_MCM, inst),\ + SRII(MPCC_MCM_SHAPER_RAMA_REGION_8_9, MPCC_MCM, inst),\ + SRII(MPCC_MCM_SHAPER_RAMA_REGION_10_11, MPCC_MCM, inst),\ + SRII(MPCC_MCM_SHAPER_RAMA_REGION_12_13, MPCC_MCM, inst),\ + SRII(MPCC_MCM_SHAPER_RAMA_REGION_14_15, MPCC_MCM, inst),\ + SRII(MPCC_MCM_SHAPER_RAMA_REGION_16_17, MPCC_MCM, inst),\ + SRII(MPCC_MCM_SHAPER_RAMA_REGION_18_19, MPCC_MCM, inst),\ + SRII(MPCC_MCM_SHAPER_RAMA_REGION_20_21, MPCC_MCM, inst),\ + SRII(MPCC_MCM_SHAPER_RAMA_REGION_22_23, MPCC_MCM, inst),\ + SRII(MPCC_MCM_SHAPER_RAMA_REGION_24_25, MPCC_MCM, inst),\ + SRII(MPCC_MCM_SHAPER_RAMA_REGION_26_27, MPCC_MCM, inst),\ + SRII(MPCC_MCM_SHAPER_RAMA_REGION_28_29, MPCC_MCM, inst),\ + SRII(MPCC_MCM_SHAPER_RAMA_REGION_30_31, MPCC_MCM, inst),\ + SRII(MPCC_MCM_SHAPER_RAMA_REGION_32_33, MPCC_MCM, inst),\ + SRII(MPCC_MCM_SHAPER_RAMB_START_CNTL_B, MPCC_MCM, inst),\ + SRII(MPCC_MCM_SHAPER_RAMB_START_CNTL_G, MPCC_MCM, inst),\ + SRII(MPCC_MCM_SHAPER_RAMB_START_CNTL_R, MPCC_MCM, inst),\ + SRII(MPCC_MCM_SHAPER_RAMB_END_CNTL_B, MPCC_MCM, inst),\ + SRII(MPCC_MCM_SHAPER_RAMB_END_CNTL_G, MPCC_MCM, inst),\ + SRII(MPCC_MCM_SHAPER_RAMB_END_CNTL_R, MPCC_MCM, inst),\ + SRII(MPCC_MCM_SHAPER_RAMB_REGION_0_1, MPCC_MCM, inst),\ + SRII(MPCC_MCM_SHAPER_RAMB_REGION_2_3, MPCC_MCM, inst),\ + SRII(MPCC_MCM_SHAPER_RAMB_REGION_4_5, MPCC_MCM, inst),\ + SRII(MPCC_MCM_SHAPER_RAMB_REGION_6_7, MPCC_MCM, inst),\ + SRII(MPCC_MCM_SHAPER_RAMB_REGION_8_9, MPCC_MCM, inst),\ + SRII(MPCC_MCM_SHAPER_RAMB_REGION_10_11, MPCC_MCM, inst),\ + SRII(MPCC_MCM_SHAPER_RAMB_REGION_12_13, MPCC_MCM, inst),\ + SRII(MPCC_MCM_SHAPER_RAMB_REGION_14_15, MPCC_MCM, inst),\ + SRII(MPCC_MCM_SHAPER_RAMB_REGION_16_17, MPCC_MCM, inst),\ + SRII(MPCC_MCM_SHAPER_RAMB_REGION_18_19, MPCC_MCM, inst),\ + SRII(MPCC_MCM_SHAPER_RAMB_REGION_20_21, MPCC_MCM, inst),\ + SRII(MPCC_MCM_SHAPER_RAMB_REGION_22_23, MPCC_MCM, inst),\ + SRII(MPCC_MCM_SHAPER_RAMB_REGION_24_25, MPCC_MCM, inst),\ + SRII(MPCC_MCM_SHAPER_RAMB_REGION_26_27, MPCC_MCM, inst),\ + SRII(MPCC_MCM_SHAPER_RAMB_REGION_28_29, MPCC_MCM, inst),\ + SRII(MPCC_MCM_SHAPER_RAMB_REGION_30_31, MPCC_MCM, inst),\ + SRII(MPCC_MCM_SHAPER_RAMB_REGION_32_33, MPCC_MCM, inst),\ + SRII(MPCC_MCM_3DLUT_MODE, MPCC_MCM, inst), /*TODO: may need to add other 3DLUT regs*/\ + SRII(MPCC_MCM_3DLUT_INDEX, MPCC_MCM, inst),\ + SRII(MPCC_MCM_3DLUT_DATA, MPCC_MCM, inst),\ + SRII(MPCC_MCM_3DLUT_DATA_30BIT, MPCC_MCM, inst),\ + SRII(MPCC_MCM_3DLUT_READ_WRITE_CONTROL, MPCC_MCM, inst),\ + SRII(MPCC_MCM_3DLUT_OUT_NORM_FACTOR, MPCC_MCM, inst),\ + SRII(MPCC_MCM_3DLUT_OUT_OFFSET_R, MPCC_MCM, inst),\ + SRII(MPCC_MCM_3DLUT_OUT_OFFSET_G, MPCC_MCM, inst),\ + SRII(MPCC_MCM_3DLUT_OUT_OFFSET_B, MPCC_MCM, inst),\ + SRII(MPCC_MCM_1DLUT_CONTROL, MPCC_MCM, inst),\ + SRII(MPCC_MCM_1DLUT_LUT_INDEX, MPCC_MCM, inst),\ + SRII(MPCC_MCM_1DLUT_LUT_DATA, MPCC_MCM, inst),\ + SRII(MPCC_MCM_1DLUT_LUT_CONTROL, MPCC_MCM, inst),\ + SRII(MPCC_MCM_1DLUT_RAMA_START_CNTL_B, MPCC_MCM, inst),\ + SRII(MPCC_MCM_1DLUT_RAMA_START_CNTL_G, MPCC_MCM, inst),\ + SRII(MPCC_MCM_1DLUT_RAMA_START_CNTL_R, MPCC_MCM, inst),\ + SRII(MPCC_MCM_1DLUT_RAMA_START_SLOPE_CNTL_B, MPCC_MCM, inst),\ + SRII(MPCC_MCM_1DLUT_RAMA_START_SLOPE_CNTL_G, MPCC_MCM, inst),\ + SRII(MPCC_MCM_1DLUT_RAMA_START_SLOPE_CNTL_R, MPCC_MCM, inst),\ + SRII(MPCC_MCM_1DLUT_RAMA_START_BASE_CNTL_B, MPCC_MCM, inst),\ + SRII(MPCC_MCM_1DLUT_RAMA_START_BASE_CNTL_G, MPCC_MCM, inst),\ + SRII(MPCC_MCM_1DLUT_RAMA_START_BASE_CNTL_R, MPCC_MCM, inst),\ + SRII(MPCC_MCM_1DLUT_RAMA_END_CNTL1_B, MPCC_MCM, inst),\ + SRII(MPCC_MCM_1DLUT_RAMA_END_CNTL2_B, MPCC_MCM, inst),\ + SRII(MPCC_MCM_1DLUT_RAMA_END_CNTL1_G, MPCC_MCM, inst),\ + SRII(MPCC_MCM_1DLUT_RAMA_END_CNTL2_G, MPCC_MCM, inst),\ + SRII(MPCC_MCM_1DLUT_RAMA_END_CNTL1_R, MPCC_MCM, inst),\ + SRII(MPCC_MCM_1DLUT_RAMA_END_CNTL2_R, MPCC_MCM, inst),\ + SRII(MPCC_MCM_1DLUT_RAMA_OFFSET_B, MPCC_MCM, inst),\ + SRII(MPCC_MCM_1DLUT_RAMA_OFFSET_G, MPCC_MCM, inst),\ + SRII(MPCC_MCM_1DLUT_RAMA_OFFSET_R, MPCC_MCM, inst),\ + SRII(MPCC_MCM_1DLUT_RAMA_REGION_0_1, MPCC_MCM, inst),\ + SRII(MPCC_MCM_1DLUT_RAMA_REGION_2_3, MPCC_MCM, inst),\ + SRII(MPCC_MCM_1DLUT_RAMA_REGION_4_5, MPCC_MCM, inst),\ + SRII(MPCC_MCM_1DLUT_RAMA_REGION_6_7, MPCC_MCM, inst),\ + SRII(MPCC_MCM_1DLUT_RAMA_REGION_8_9, MPCC_MCM, inst),\ + SRII(MPCC_MCM_1DLUT_RAMA_REGION_10_11, MPCC_MCM, inst),\ + SRII(MPCC_MCM_1DLUT_RAMA_REGION_12_13, MPCC_MCM, inst),\ + SRII(MPCC_MCM_1DLUT_RAMA_REGION_14_15, MPCC_MCM, inst),\ + SRII(MPCC_MCM_1DLUT_RAMA_REGION_16_17, MPCC_MCM, inst),\ + SRII(MPCC_MCM_1DLUT_RAMA_REGION_18_19, MPCC_MCM, inst),\ + SRII(MPCC_MCM_1DLUT_RAMA_REGION_20_21, MPCC_MCM, inst),\ + SRII(MPCC_MCM_1DLUT_RAMA_REGION_22_23, MPCC_MCM, inst),\ + SRII(MPCC_MCM_1DLUT_RAMA_REGION_24_25, MPCC_MCM, inst),\ + SRII(MPCC_MCM_1DLUT_RAMA_REGION_26_27, MPCC_MCM, inst),\ + SRII(MPCC_MCM_1DLUT_RAMA_REGION_28_29, MPCC_MCM, inst),\ + SRII(MPCC_MCM_1DLUT_RAMA_REGION_30_31, MPCC_MCM, inst),\ + SRII(MPCC_MCM_1DLUT_RAMA_REGION_32_33, MPCC_MCM, inst),\ + SRII(MPCC_MCM_1DLUT_RAMB_START_CNTL_B, MPCC_MCM, inst),\ + SRII(MPCC_MCM_1DLUT_RAMB_START_CNTL_G, MPCC_MCM, inst),\ + SRII(MPCC_MCM_1DLUT_RAMB_START_CNTL_R, MPCC_MCM, inst),\ + SRII(MPCC_MCM_1DLUT_RAMB_START_SLOPE_CNTL_B, MPCC_MCM, inst),\ + SRII(MPCC_MCM_1DLUT_RAMB_START_SLOPE_CNTL_G, MPCC_MCM, inst),\ + SRII(MPCC_MCM_1DLUT_RAMB_START_SLOPE_CNTL_R, MPCC_MCM, inst),\ + SRII(MPCC_MCM_1DLUT_RAMB_START_BASE_CNTL_B, MPCC_MCM, inst),\ + SRII(MPCC_MCM_1DLUT_RAMB_START_BASE_CNTL_G, MPCC_MCM, inst),\ + SRII(MPCC_MCM_1DLUT_RAMB_START_BASE_CNTL_R, MPCC_MCM, inst),\ + SRII(MPCC_MCM_1DLUT_RAMB_END_CNTL1_B, MPCC_MCM, inst),\ + SRII(MPCC_MCM_1DLUT_RAMB_END_CNTL2_B, MPCC_MCM, inst),\ + SRII(MPCC_MCM_1DLUT_RAMB_END_CNTL1_G, MPCC_MCM, inst),\ + SRII(MPCC_MCM_1DLUT_RAMB_END_CNTL2_G, MPCC_MCM, inst),\ + SRII(MPCC_MCM_1DLUT_RAMB_END_CNTL1_R, MPCC_MCM, inst),\ + SRII(MPCC_MCM_1DLUT_RAMB_END_CNTL2_R, MPCC_MCM, inst),\ + SRII(MPCC_MCM_1DLUT_RAMB_OFFSET_B, MPCC_MCM, inst),\ + SRII(MPCC_MCM_1DLUT_RAMB_OFFSET_G, MPCC_MCM, inst),\ + SRII(MPCC_MCM_1DLUT_RAMB_OFFSET_R, MPCC_MCM, inst),\ + SRII(MPCC_MCM_1DLUT_RAMB_REGION_0_1, MPCC_MCM, inst),\ + SRII(MPCC_MCM_1DLUT_RAMB_REGION_2_3, MPCC_MCM, inst),\ + SRII(MPCC_MCM_1DLUT_RAMB_REGION_4_5, MPCC_MCM, inst),\ + SRII(MPCC_MCM_1DLUT_RAMB_REGION_6_7, MPCC_MCM, inst),\ + SRII(MPCC_MCM_1DLUT_RAMB_REGION_8_9, MPCC_MCM, inst),\ + SRII(MPCC_MCM_1DLUT_RAMB_REGION_10_11, MPCC_MCM, inst),\ + SRII(MPCC_MCM_1DLUT_RAMB_REGION_12_13, MPCC_MCM, inst),\ + SRII(MPCC_MCM_1DLUT_RAMB_REGION_14_15, MPCC_MCM, inst),\ + SRII(MPCC_MCM_1DLUT_RAMB_REGION_16_17, MPCC_MCM, inst),\ + SRII(MPCC_MCM_1DLUT_RAMB_REGION_18_19, MPCC_MCM, inst),\ + SRII(MPCC_MCM_1DLUT_RAMB_REGION_20_21, MPCC_MCM, inst),\ + SRII(MPCC_MCM_1DLUT_RAMB_REGION_22_23, MPCC_MCM, inst),\ + SRII(MPCC_MCM_1DLUT_RAMB_REGION_24_25, MPCC_MCM, inst),\ + SRII(MPCC_MCM_1DLUT_RAMB_REGION_26_27, MPCC_MCM, inst),\ + SRII(MPCC_MCM_1DLUT_RAMB_REGION_28_29, MPCC_MCM, inst),\ + SRII(MPCC_MCM_1DLUT_RAMB_REGION_30_31, MPCC_MCM, inst),\ + SRII(MPCC_MCM_1DLUT_RAMB_REGION_32_33, MPCC_MCM, inst),\ + SRII(MPCC_MCM_MEM_PWR_CTRL, MPCC_MCM, inst) +/* OPTC */ + +#define OPTC_COMMON_REG_LIST_DCN3_2_RI(inst) \ + SRI_ARR(OTG_VSTARTUP_PARAM, OTG, inst), \ + SRI_ARR(OTG_VUPDATE_PARAM, OTG, inst), \ + SRI_ARR(OTG_VREADY_PARAM, OTG, inst), \ + SRI_ARR(OTG_MASTER_UPDATE_LOCK, OTG, inst), \ + SRI_ARR(OTG_GLOBAL_CONTROL0, OTG, inst), \ + SRI_ARR(OTG_GLOBAL_CONTROL1, OTG, inst), \ + SRI_ARR(OTG_GLOBAL_CONTROL2, OTG, inst), \ + SRI_ARR(OTG_GLOBAL_CONTROL4, OTG, inst), \ + SRI_ARR(OTG_DOUBLE_BUFFER_CONTROL, OTG, inst), \ + SRI_ARR(OTG_H_TOTAL, OTG, inst), \ + SRI_ARR(OTG_H_BLANK_START_END, OTG, inst), \ + SRI_ARR(OTG_H_SYNC_A, OTG, inst), SRI_ARR(OTG_H_SYNC_A_CNTL, OTG, inst), \ + SRI_ARR(OTG_H_TIMING_CNTL, OTG, inst), SRI_ARR(OTG_V_TOTAL, OTG, inst), \ + SRI_ARR(OTG_V_BLANK_START_END, OTG, inst), \ + SRI_ARR(OTG_V_SYNC_A, OTG, inst), SRI_ARR(OTG_V_SYNC_A_CNTL, OTG, inst), \ + SRI_ARR(OTG_CONTROL, OTG, inst), SRI_ARR(OTG_STEREO_CONTROL, OTG, inst), \ + SRI_ARR(OTG_3D_STRUCTURE_CONTROL, OTG, inst), \ + SRI_ARR(OTG_STEREO_STATUS, OTG, inst), \ + SRI_ARR(OTG_V_TOTAL_MAX, OTG, inst), \ + SRI_ARR(OTG_V_TOTAL_MIN, OTG, inst), \ + SRI_ARR(OTG_V_TOTAL_CONTROL, OTG, inst), \ + SRI_ARR(OTG_TRIGA_CNTL, OTG, inst), \ + SRI_ARR(OTG_FORCE_COUNT_NOW_CNTL, OTG, inst), \ + SRI_ARR(OTG_STATIC_SCREEN_CONTROL, OTG, inst), \ + SRI_ARR(OTG_STATUS_FRAME_COUNT, OTG, inst), \ + SRI_ARR(OTG_STATUS, OTG, inst), SRI_ARR(OTG_STATUS_POSITION, OTG, inst), \ + SRI_ARR(OTG_NOM_VERT_POSITION, OTG, inst), \ + SRI_ARR(OTG_M_CONST_DTO0, OTG, inst), \ + SRI_ARR(OTG_M_CONST_DTO1, OTG, inst), \ + SRI_ARR(OTG_CLOCK_CONTROL, OTG, inst), \ + SRI_ARR(OTG_VERTICAL_INTERRUPT0_CONTROL, OTG, inst), \ + SRI_ARR(OTG_VERTICAL_INTERRUPT0_POSITION, OTG, inst), \ + SRI_ARR(OTG_VERTICAL_INTERRUPT1_CONTROL, OTG, inst), \ + SRI_ARR(OTG_VERTICAL_INTERRUPT1_POSITION, OTG, inst), \ + SRI_ARR(OTG_VERTICAL_INTERRUPT2_CONTROL, OTG, inst), \ + SRI_ARR(OTG_VERTICAL_INTERRUPT2_POSITION, OTG, inst), \ + SRI_ARR(OPTC_INPUT_CLOCK_CONTROL, ODM, inst), \ + SRI_ARR(OPTC_DATA_SOURCE_SELECT, ODM, inst), \ + SRI_ARR(OPTC_INPUT_GLOBAL_CONTROL, ODM, inst), \ + SRI_ARR(CONTROL, VTG, inst), SRI_ARR(OTG_VERT_SYNC_CONTROL, OTG, inst), \ + SRI_ARR(OTG_GSL_CONTROL, OTG, inst), SRI_ARR(OTG_CRC_CNTL, OTG, inst), \ + SRI_ARR(OTG_CRC0_DATA_RG, OTG, inst), \ + SRI_ARR(OTG_CRC0_DATA_B, OTG, inst), \ + SRI_ARR(OTG_CRC0_WINDOWA_X_CONTROL, OTG, inst), \ + SRI_ARR(OTG_CRC0_WINDOWA_Y_CONTROL, OTG, inst), \ + SRI_ARR(OTG_CRC0_WINDOWB_X_CONTROL, OTG, inst), \ + SRI_ARR(OTG_CRC0_WINDOWB_Y_CONTROL, OTG, inst), \ + SR_ARR(GSL_SOURCE_SELECT, inst), \ + SRI_ARR(OTG_TRIGA_MANUAL_TRIG, OTG, inst), \ + SRI_ARR(OTG_GLOBAL_CONTROL1, OTG, inst), \ + SRI_ARR(OTG_GLOBAL_CONTROL2, OTG, inst), \ + SRI_ARR(OTG_GSL_WINDOW_X, OTG, inst), \ + SRI_ARR(OTG_GSL_WINDOW_Y, OTG, inst), \ + SRI_ARR(OTG_VUPDATE_KEEPOUT, OTG, inst), \ + SRI_ARR(OTG_DSC_START_POSITION, OTG, inst), \ + SRI_ARR(OTG_DRR_TRIGGER_WINDOW, OTG, inst), \ + SRI_ARR(OTG_DRR_V_TOTAL_CHANGE, OTG, inst), \ + SRI_ARR(OPTC_DATA_FORMAT_CONTROL, ODM, inst), \ + SRI_ARR(OPTC_BYTES_PER_PIXEL, ODM, inst), \ + SRI_ARR(OPTC_WIDTH_CONTROL, ODM, inst), \ + SRI_ARR(OPTC_MEMORY_CONFIG, ODM, inst), \ + SRI_ARR(OTG_DRR_CONTROL, OTG, inst) + +/* HUBP */ + +#define HUBP_REG_LIST_DCN_VM_RI(id) \ + SRI_ARR(NOM_PARAMETERS_0, HUBPREQ, id), \ + SRI_ARR(NOM_PARAMETERS_1, HUBPREQ, id), \ + SRI_ARR(NOM_PARAMETERS_2, HUBPREQ, id), \ + SRI_ARR(NOM_PARAMETERS_3, HUBPREQ, id), \ + SRI_ARR(DCN_VM_MX_L1_TLB_CNTL, HUBPREQ, id) +#define HUBP_REG_LIST_DCN_RI(id) \ + SRI_ARR(DCHUBP_CNTL, HUBP, id), SRI_ARR(HUBPREQ_DEBUG_DB, HUBP, id), \ + SRI_ARR(HUBPREQ_DEBUG, HUBP, id), SRI_ARR(DCSURF_ADDR_CONFIG, HUBP, id), \ + SRI_ARR(DCSURF_TILING_CONFIG, HUBP, id), \ + SRI_ARR(DCSURF_SURFACE_PITCH, HUBPREQ, id), \ + SRI_ARR(DCSURF_SURFACE_PITCH_C, HUBPREQ, id), \ + SRI_ARR(DCSURF_SURFACE_CONFIG, HUBP, id), \ + SRI_ARR(DCSURF_FLIP_CONTROL, HUBPREQ, id), \ + SRI_ARR(DCSURF_PRI_VIEWPORT_DIMENSION, HUBP, id), \ + SRI_ARR(DCSURF_PRI_VIEWPORT_START, HUBP, id), \ + SRI_ARR(DCSURF_SEC_VIEWPORT_DIMENSION, HUBP, id), \ + SRI_ARR(DCSURF_SEC_VIEWPORT_START, HUBP, id), \ + SRI_ARR(DCSURF_PRI_VIEWPORT_DIMENSION_C, HUBP, id), \ + SRI_ARR(DCSURF_PRI_VIEWPORT_START_C, HUBP, id), \ + SRI_ARR(DCSURF_SEC_VIEWPORT_DIMENSION_C, HUBP, id), \ + SRI_ARR(DCSURF_SEC_VIEWPORT_START_C, HUBP, id), \ + SRI_ARR(DCSURF_PRIMARY_SURFACE_ADDRESS_HIGH, HUBPREQ, id), \ + SRI_ARR(DCSURF_PRIMARY_SURFACE_ADDRESS, HUBPREQ, id), \ + SRI_ARR(DCSURF_SECONDARY_SURFACE_ADDRESS_HIGH, HUBPREQ, id), \ + SRI_ARR(DCSURF_SECONDARY_SURFACE_ADDRESS, HUBPREQ, id), \ + SRI_ARR(DCSURF_PRIMARY_META_SURFACE_ADDRESS_HIGH, HUBPREQ, id), \ + SRI_ARR(DCSURF_PRIMARY_META_SURFACE_ADDRESS, HUBPREQ, id), \ + SRI_ARR(DCSURF_SECONDARY_META_SURFACE_ADDRESS_HIGH, HUBPREQ, id), \ + SRI_ARR(DCSURF_SECONDARY_META_SURFACE_ADDRESS, HUBPREQ, id), \ + SRI_ARR(DCSURF_PRIMARY_SURFACE_ADDRESS_HIGH_C, HUBPREQ, id), \ + SRI_ARR(DCSURF_PRIMARY_SURFACE_ADDRESS_C, HUBPREQ, id), \ + SRI_ARR(DCSURF_SECONDARY_SURFACE_ADDRESS_HIGH_C, HUBPREQ, id), \ + SRI_ARR(DCSURF_SECONDARY_SURFACE_ADDRESS_C, HUBPREQ, id), \ + SRI_ARR(DCSURF_PRIMARY_META_SURFACE_ADDRESS_HIGH_C, HUBPREQ, id), \ + SRI_ARR(DCSURF_PRIMARY_META_SURFACE_ADDRESS_C, HUBPREQ, id), \ + SRI_ARR(DCSURF_SECONDARY_META_SURFACE_ADDRESS_HIGH_C, HUBPREQ, id), \ + SRI_ARR(DCSURF_SECONDARY_META_SURFACE_ADDRESS_C, HUBPREQ, id), \ + SRI_ARR(DCSURF_SURFACE_INUSE, HUBPREQ, id), \ + SRI_ARR(DCSURF_SURFACE_INUSE_HIGH, HUBPREQ, id), \ + SRI_ARR(DCSURF_SURFACE_INUSE_C, HUBPREQ, id), \ + SRI_ARR(DCSURF_SURFACE_INUSE_HIGH_C, HUBPREQ, id), \ + SRI_ARR(DCSURF_SURFACE_EARLIEST_INUSE, HUBPREQ, id), \ + SRI_ARR(DCSURF_SURFACE_EARLIEST_INUSE_HIGH, HUBPREQ, id), \ + SRI_ARR(DCSURF_SURFACE_EARLIEST_INUSE_C, HUBPREQ, id), \ + SRI_ARR(DCSURF_SURFACE_EARLIEST_INUSE_HIGH_C, HUBPREQ, id), \ + SRI_ARR(DCSURF_SURFACE_CONTROL, HUBPREQ, id), \ + SRI_ARR(DCSURF_SURFACE_FLIP_INTERRUPT, HUBPREQ, id), \ + SRI_ARR(HUBPRET_CONTROL, HUBPRET, id), \ + SRI_ARR(HUBPRET_READ_LINE_STATUS, HUBPRET, id), \ + SRI_ARR(DCN_EXPANSION_MODE, HUBPREQ, id), \ + SRI_ARR(DCHUBP_REQ_SIZE_CONFIG, HUBP, id), \ + SRI_ARR(DCHUBP_REQ_SIZE_CONFIG_C, HUBP, id), \ + SRI_ARR(BLANK_OFFSET_0, HUBPREQ, id), \ + SRI_ARR(BLANK_OFFSET_1, HUBPREQ, id), \ + SRI_ARR(DST_DIMENSIONS, HUBPREQ, id), \ + SRI_ARR(DST_AFTER_SCALER, HUBPREQ, id), \ + SRI_ARR(VBLANK_PARAMETERS_0, HUBPREQ, id), \ + SRI_ARR(REF_FREQ_TO_PIX_FREQ, HUBPREQ, id), \ + SRI_ARR(VBLANK_PARAMETERS_1, HUBPREQ, id), \ + SRI_ARR(VBLANK_PARAMETERS_3, HUBPREQ, id), \ + SRI_ARR(NOM_PARAMETERS_4, HUBPREQ, id), \ + SRI_ARR(NOM_PARAMETERS_5, HUBPREQ, id), \ + SRI_ARR(PER_LINE_DELIVERY_PRE, HUBPREQ, id), \ + SRI_ARR(PER_LINE_DELIVERY, HUBPREQ, id), \ + SRI_ARR(VBLANK_PARAMETERS_2, HUBPREQ, id), \ + SRI_ARR(VBLANK_PARAMETERS_4, HUBPREQ, id), \ + SRI_ARR(NOM_PARAMETERS_6, HUBPREQ, id), \ + SRI_ARR(NOM_PARAMETERS_7, HUBPREQ, id), \ + SRI_ARR(DCN_TTU_QOS_WM, HUBPREQ, id), \ + SRI_ARR(DCN_GLOBAL_TTU_CNTL, HUBPREQ, id), \ + SRI_ARR(DCN_SURF0_TTU_CNTL0, HUBPREQ, id), \ + SRI_ARR(DCN_SURF0_TTU_CNTL1, HUBPREQ, id), \ + SRI_ARR(DCN_SURF1_TTU_CNTL0, HUBPREQ, id), \ + SRI_ARR(DCN_SURF1_TTU_CNTL1, HUBPREQ, id), \ + SRI_ARR(DCN_CUR0_TTU_CNTL0, HUBPREQ, id), \ + SRI_ARR(DCN_CUR0_TTU_CNTL1, HUBPREQ, id), \ + SRI_ARR(HUBP_CLK_CNTL, HUBP, id) +#define HUBP_REG_LIST_DCN2_COMMON_RI(id) \ + HUBP_REG_LIST_DCN_RI(id), HUBP_REG_LIST_DCN_VM_RI(id), \ + SRI_ARR(PREFETCH_SETTINGS, HUBPREQ, id), \ + SRI_ARR(PREFETCH_SETTINGS_C, HUBPREQ, id), \ + SRI_ARR(DCN_VM_SYSTEM_APERTURE_LOW_ADDR, HUBPREQ, id), \ + SRI_ARR(DCN_VM_SYSTEM_APERTURE_HIGH_ADDR, HUBPREQ, id), \ + SRI_ARR(CURSOR_SETTINGS, HUBPREQ, id), \ + SRI_ARR(CURSOR_SURFACE_ADDRESS_HIGH, CURSOR0_, id), \ + SRI_ARR(CURSOR_SURFACE_ADDRESS, CURSOR0_, id), \ + SRI_ARR(CURSOR_SIZE, CURSOR0_, id), \ + SRI_ARR(CURSOR_CONTROL, CURSOR0_, id), \ + SRI_ARR(CURSOR_POSITION, CURSOR0_, id), \ + SRI_ARR(CURSOR_HOT_SPOT, CURSOR0_, id), \ + SRI_ARR(CURSOR_DST_OFFSET, CURSOR0_, id), \ + SRI_ARR(DMDATA_ADDRESS_HIGH, CURSOR0_, id), \ + SRI_ARR(DMDATA_ADDRESS_LOW, CURSOR0_, id), \ + SRI_ARR(DMDATA_CNTL, CURSOR0_, id), \ + SRI_ARR(DMDATA_SW_CNTL, CURSOR0_, id), \ + SRI_ARR(DMDATA_QOS_CNTL, CURSOR0_, id), \ + SRI_ARR(DMDATA_SW_DATA, CURSOR0_, id), \ + SRI_ARR(DMDATA_STATUS, CURSOR0_, id), \ + SRI_ARR(FLIP_PARAMETERS_0, HUBPREQ, id), \ + SRI_ARR(FLIP_PARAMETERS_1, HUBPREQ, id), \ + SRI_ARR(FLIP_PARAMETERS_2, HUBPREQ, id), \ + SRI_ARR(DCN_CUR1_TTU_CNTL0, HUBPREQ, id), \ + SRI_ARR(DCN_CUR1_TTU_CNTL1, HUBPREQ, id), \ + SRI_ARR(DCSURF_FLIP_CONTROL2, HUBPREQ, id), \ + SRI_ARR(VMID_SETTINGS_0, HUBPREQ, id) +#define HUBP_REG_LIST_DCN21_RI(id) \ + HUBP_REG_LIST_DCN2_COMMON_RI(id), SRI_ARR(FLIP_PARAMETERS_3, HUBPREQ, id), \ + SRI_ARR(FLIP_PARAMETERS_4, HUBPREQ, id), \ + SRI_ARR(FLIP_PARAMETERS_5, HUBPREQ, id), \ + SRI_ARR(FLIP_PARAMETERS_6, HUBPREQ, id), \ + SRI_ARR(VBLANK_PARAMETERS_5, HUBPREQ, id), \ + SRI_ARR(VBLANK_PARAMETERS_6, HUBPREQ, id) +#define HUBP_REG_LIST_DCN30_RI(id) \ + HUBP_REG_LIST_DCN21_RI(id), SRI_ARR(DCN_DMDATA_VM_CNTL, HUBPREQ, id) +#define HUBP_REG_LIST_DCN32_RI(id) \ + HUBP_REG_LIST_DCN30_RI(id), SRI_ARR(DCHUBP_MALL_CONFIG, HUBP, id), \ + SRI_ARR(DCHUBP_VMPG_CONFIG, HUBP, id), \ + SRI_ARR(UCLK_PSTATE_FORCE, HUBPREQ, id) + +/* HUBBUB */ + +#define HUBBUB_REG_LIST_DCN32_RI(id) \ + SR(DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_A), \ + SR(DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_B), \ + SR(DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_C), \ + SR(DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_D), \ + SR(DCHUBBUB_ARB_WATERMARK_CHANGE_CNTL), \ + SR(DCHUBBUB_ARB_DRAM_STATE_CNTL), SR(DCHUBBUB_ARB_SAT_LEVEL), \ + SR(DCHUBBUB_ARB_DF_REQ_OUTSTAND), SR(DCHUBBUB_GLOBAL_TIMER_CNTL), \ + SR(DCHUBBUB_SOFT_RESET), SR(DCHUBBUB_CRC_CTRL), \ + SR(DCN_VM_FB_LOCATION_BASE), SR(DCN_VM_FB_LOCATION_TOP), \ + SR(DCN_VM_FB_OFFSET), SR(DCN_VM_AGP_BOT), SR(DCN_VM_AGP_TOP), \ + SR(DCN_VM_AGP_BASE), HUBBUB_SR_WATERMARK_REG_LIST(), \ + SR(DCHUBBUB_ARB_FRAC_URG_BW_NOM_A), SR(DCHUBBUB_ARB_FRAC_URG_BW_NOM_B), \ + SR(DCHUBBUB_ARB_FRAC_URG_BW_NOM_C), SR(DCHUBBUB_ARB_FRAC_URG_BW_NOM_D), \ + SR(DCHUBBUB_ARB_FRAC_URG_BW_FLIP_A), \ + SR(DCHUBBUB_ARB_FRAC_URG_BW_FLIP_B), \ + SR(DCHUBBUB_ARB_FRAC_URG_BW_FLIP_C), \ + SR(DCHUBBUB_ARB_FRAC_URG_BW_FLIP_D), \ + SR(DCHUBBUB_ARB_REFCYC_PER_TRIP_TO_MEMORY_A), \ + SR(DCHUBBUB_ARB_REFCYC_PER_TRIP_TO_MEMORY_B), \ + SR(DCHUBBUB_ARB_REFCYC_PER_TRIP_TO_MEMORY_C), \ + SR(DCHUBBUB_ARB_REFCYC_PER_TRIP_TO_MEMORY_D), SR(DCHUBBUB_DET0_CTRL), \ + SR(DCHUBBUB_DET1_CTRL), SR(DCHUBBUB_DET2_CTRL), SR(DCHUBBUB_DET3_CTRL), \ + SR(DCHUBBUB_COMPBUF_CTRL), SR(COMPBUF_RESERVED_SPACE), \ + SR(DCHUBBUB_DEBUG_CTRL_0), \ + SR(DCHUBBUB_ARB_USR_RETRAINING_CNTL), \ + SR(DCHUBBUB_ARB_USR_RETRAINING_WATERMARK_A), \ + SR(DCHUBBUB_ARB_USR_RETRAINING_WATERMARK_B), \ + SR(DCHUBBUB_ARB_USR_RETRAINING_WATERMARK_C), \ + SR(DCHUBBUB_ARB_USR_RETRAINING_WATERMARK_D), \ + SR(DCHUBBUB_ARB_UCLK_PSTATE_CHANGE_WATERMARK_A), \ + SR(DCHUBBUB_ARB_UCLK_PSTATE_CHANGE_WATERMARK_B), \ + SR(DCHUBBUB_ARB_UCLK_PSTATE_CHANGE_WATERMARK_C), \ + SR(DCHUBBUB_ARB_UCLK_PSTATE_CHANGE_WATERMARK_D), \ + SR(DCHUBBUB_ARB_FCLK_PSTATE_CHANGE_WATERMARK_A), \ + SR(DCHUBBUB_ARB_FCLK_PSTATE_CHANGE_WATERMARK_B), \ + SR(DCHUBBUB_ARB_FCLK_PSTATE_CHANGE_WATERMARK_C), \ + SR(DCHUBBUB_ARB_FCLK_PSTATE_CHANGE_WATERMARK_D), \ + SR(DCHUBBUB_ARB_MALL_CNTL), \ + SR(DCN_VM_FAULT_ADDR_MSB), SR(DCN_VM_FAULT_ADDR_LSB), \ + SR(DCN_VM_FAULT_CNTL), SR(DCN_VM_FAULT_STATUS), \ + SR(SDPIF_REQUEST_RATE_LIMIT) + +/* DCCG */ + +#define DCCG_REG_LIST_DCN32_RI() \ + SR(DPPCLK_DTO_CTRL), DCCG_SRII(DTO_PARAM, DPPCLK, 0), \ + DCCG_SRII(DTO_PARAM, DPPCLK, 1), DCCG_SRII(DTO_PARAM, DPPCLK, 2), \ + DCCG_SRII(DTO_PARAM, DPPCLK, 3), DCCG_SRII(CLOCK_CNTL, HDMICHARCLK, 0), \ + SR(PHYASYMCLK_CLOCK_CNTL), SR(PHYBSYMCLK_CLOCK_CNTL), \ + SR(PHYCSYMCLK_CLOCK_CNTL), SR(PHYDSYMCLK_CLOCK_CNTL), \ + SR(PHYESYMCLK_CLOCK_CNTL), SR(DPSTREAMCLK_CNTL), SR(HDMISTREAMCLK_CNTL), \ + SR(SYMCLK32_SE_CNTL), SR(SYMCLK32_LE_CNTL), \ + DCCG_SRII(PIXEL_RATE_CNTL, OTG, 0), DCCG_SRII(PIXEL_RATE_CNTL, OTG, 1), \ + DCCG_SRII(PIXEL_RATE_CNTL, OTG, 2), DCCG_SRII(PIXEL_RATE_CNTL, OTG, 3), \ + DCCG_SRII(MODULO, DTBCLK_DTO, 0), DCCG_SRII(MODULO, DTBCLK_DTO, 1), \ + DCCG_SRII(MODULO, DTBCLK_DTO, 2), DCCG_SRII(MODULO, DTBCLK_DTO, 3), \ + DCCG_SRII(PHASE, DTBCLK_DTO, 0), DCCG_SRII(PHASE, DTBCLK_DTO, 1), \ + DCCG_SRII(PHASE, DTBCLK_DTO, 2), DCCG_SRII(PHASE, DTBCLK_DTO, 3), \ + SR(DCCG_AUDIO_DTBCLK_DTO_MODULO), SR(DCCG_AUDIO_DTBCLK_DTO_PHASE), \ + SR(OTG_PIXEL_RATE_DIV), SR(DTBCLK_P_CNTL), \ + SR(DCCG_AUDIO_DTO_SOURCE), SR(DENTIST_DISPCLK_CNTL) + +/* VMID */ +#define DCN20_VMID_REG_LIST_RI(id) \ + SRI_ARR(CNTL, DCN_VM_CONTEXT, id), \ + SRI_ARR(PAGE_TABLE_BASE_ADDR_HI32, DCN_VM_CONTEXT, id), \ + SRI_ARR(PAGE_TABLE_BASE_ADDR_LO32, DCN_VM_CONTEXT, id), \ + SRI_ARR(PAGE_TABLE_START_ADDR_HI32, DCN_VM_CONTEXT, id), \ + SRI_ARR(PAGE_TABLE_START_ADDR_LO32, DCN_VM_CONTEXT, id), \ + SRI_ARR(PAGE_TABLE_END_ADDR_HI32, DCN_VM_CONTEXT, id), \ + SRI_ARR(PAGE_TABLE_END_ADDR_LO32, DCN_VM_CONTEXT, id) + +/* I2C HW */ + +#define I2C_HW_ENGINE_COMMON_REG_LIST_RI(id) \ + SRI_ARR_I2C(SETUP, DC_I2C_DDC, id), SRI_ARR_I2C(SPEED, DC_I2C_DDC, id), \ + SRI_ARR_I2C(HW_STATUS, DC_I2C_DDC, id), \ + SR_ARR_I2C(DC_I2C_ARBITRATION, id), \ + SR_ARR_I2C(DC_I2C_CONTROL, id), SR_ARR_I2C(DC_I2C_SW_STATUS, id), \ + SR_ARR_I2C(DC_I2C_TRANSACTION0, id), SR_ARR_I2C(DC_I2C_TRANSACTION1, id),\ + SR_ARR_I2C(DC_I2C_TRANSACTION2, id), SR_ARR_I2C(DC_I2C_TRANSACTION3, id),\ + SR_ARR_I2C(DC_I2C_DATA, id), SR_ARR_I2C(MICROSECOND_TIME_BASE_DIV, id) + +#define I2C_HW_ENGINE_COMMON_REG_LIST_DCN30_RI(id) \ + I2C_HW_ENGINE_COMMON_REG_LIST_RI(id), SR_ARR_I2C(DIO_MEM_PWR_CTRL, id), \ + SR_ARR_I2C(DIO_MEM_PWR_STATUS, id) + +#endif /* _DCN32_RESOURCE_H_ */ diff --git a/drivers/gpu/drm/amd/display/dc/resource/dcn321/dcn321_resource.c b/drivers/gpu/drm/amd/display/dc/resource/dcn321/dcn321_resource.c new file mode 100644 index 000000000000..bedb70b98162 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/resource/dcn321/dcn321_resource.c @@ -0,0 +1,2065 @@ +// SPDX-License-Identifier: MIT +/* + * 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 + * + */ + +#include "dm_services.h" +#include "dc.h" + +#include "dcn32/dcn32_init.h" + +#include "resource.h" +#include "include/irq_service_interface.h" +#include "dcn32/dcn32_resource.h" +#include "dcn321_resource.h" + +#include "dcn20/dcn20_resource.h" +#include "dcn30/dcn30_resource.h" + +#include "dml/dcn321/dcn321_fpu.h" + +#include "dcn10/dcn10_ipp.h" +#include "dcn30/dcn30_hubbub.h" +#include "dcn31/dcn31_hubbub.h" +#include "dcn32/dcn32_hubbub.h" +#include "dcn32/dcn32_mpc.h" +#include "dcn32/dcn32_hubp.h" +#include "irq/dcn32/irq_service_dcn32.h" +#include "dcn32/dcn32_dpp.h" +#include "dcn32/dcn32_optc.h" +#include "dcn20/dcn20_hwseq.h" +#include "dcn30/dcn30_hwseq.h" +#include "dce110/dce110_hwseq.h" +#include "dcn30/dcn30_opp.h" +#include "dcn20/dcn20_dsc.h" +#include "dcn30/dcn30_vpg.h" +#include "dcn30/dcn30_afmt.h" +#include "dcn30/dcn30_dio_stream_encoder.h" +#include "dcn32/dcn32_dio_stream_encoder.h" +#include "dcn31/dcn31_hpo_dp_stream_encoder.h" +#include "dcn31/dcn31_hpo_dp_link_encoder.h" +#include "dcn32/dcn32_hpo_dp_link_encoder.h" +#include "dcn31/dcn31_apg.h" +#include "dcn31/dcn31_dio_link_encoder.h" +#include "dcn32/dcn32_dio_link_encoder.h" +#include "dcn321/dcn321_dio_link_encoder.h" +#include "dce/dce_clock_source.h" +#include "dce/dce_audio.h" +#include "dce/dce_hwseq.h" +#include "clk_mgr.h" +#include "virtual/virtual_stream_encoder.h" +#include "dml/display_mode_vba.h" +#include "dcn32/dcn32_dccg.h" +#include "dcn10/dcn10_resource.h" +#include "link.h" +#include "dcn31/dcn31_panel_cntl.h" + +#include "dcn30/dcn30_dwb.h" +#include "dcn32/dcn32_mmhubbub.h" + +#include "dcn/dcn_3_2_1_offset.h" +#include "dcn/dcn_3_2_1_sh_mask.h" +#include "nbio/nbio_4_3_0_offset.h" + +#include "reg_helper.h" +#include "dce/dmub_abm.h" +#include "dce/dmub_psr.h" +#include "dce/dce_aux.h" +#include "dce/dce_i2c.h" + +#include "dml/dcn30/display_mode_vba_30.h" +#include "vm_helper.h" +#include "dcn20/dcn20_vmid.h" + +#define DC_LOGGER_INIT(logger) + +enum dcn321_clk_src_array_id { + DCN321_CLK_SRC_PLL0, + DCN321_CLK_SRC_PLL1, + DCN321_CLK_SRC_PLL2, + DCN321_CLK_SRC_PLL3, + DCN321_CLK_SRC_PLL4, + DCN321_CLK_SRC_TOTAL +}; + +/* begin ********************* + * macros to expend register list macro defined in HW object header file + */ + +/* DCN */ +#define BASE_INNER(seg) ctx->dcn_reg_offsets[seg] + +#define BASE(seg) BASE_INNER(seg) + +#define SR(reg_name)\ + REG_STRUCT.reg_name = BASE(reg ## reg_name ## _BASE_IDX) + \ + reg ## reg_name +#define SR_ARR(reg_name, id)\ + REG_STRUCT[id].reg_name = BASE(reg ## reg_name ## _BASE_IDX) + \ + reg ## reg_name +#define SR_ARR_INIT(reg_name, id, value)\ + REG_STRUCT[id].reg_name = value + +#define SRI(reg_name, block, id)\ + REG_STRUCT.reg_name = BASE(reg ## block ## id ## _ ## reg_name ## _BASE_IDX) + \ + reg ## block ## id ## _ ## reg_name + +#define SRI_ARR(reg_name, block, id)\ + REG_STRUCT[id].reg_name = BASE(reg ## block ## id ## _ ## reg_name ## _BASE_IDX) + \ + reg ## block ## id ## _ ## reg_name + +#define SR_ARR_I2C(reg_name, id) \ + REG_STRUCT[id-1].reg_name = BASE(reg##reg_name##_BASE_IDX) + reg##reg_name + +#define SRI_ARR_I2C(reg_name, block, id)\ + REG_STRUCT[id-1].reg_name = BASE(reg ## block ## id ## _ ## reg_name ## _BASE_IDX) + \ + reg ## block ## id ## _ ## reg_name + +#define SRI_ARR_ALPHABET(reg_name, block, index, id)\ + REG_STRUCT[index].reg_name = BASE(reg ## block ## id ## _ ## reg_name ## _BASE_IDX) + \ + reg ## block ## id ## _ ## reg_name + +#define SRI2(reg_name, block, id)\ + .reg_name = BASE(reg ## reg_name ## _BASE_IDX) + \ + reg ## reg_name +#define SRI2_ARR(reg_name, block, id)\ + REG_STRUCT[id].reg_name = BASE(reg ## reg_name ## _BASE_IDX) + \ + reg ## reg_name + +#define SRIR(var_name, reg_name, block, id)\ + .var_name = BASE(reg ## block ## id ## _ ## reg_name ## _BASE_IDX) + \ + reg ## block ## id ## _ ## reg_name + +#define SRII(reg_name, block, id)\ + REG_STRUCT.reg_name[id] = BASE(reg ## block ## id ## _ ## reg_name ## _BASE_IDX) + \ + reg ## block ## id ## _ ## reg_name + +#define SRII_ARR_2(reg_name, block, id, inst)\ + REG_STRUCT[inst].reg_name[id] = BASE(reg ## block ## id ## _ ## reg_name ## _BASE_IDX) + \ + reg ## block ## id ## _ ## reg_name + +#define SRII_MPC_RMU(reg_name, block, id)\ + .RMU##_##reg_name[id] = BASE(reg ## block ## id ## _ ## reg_name ## _BASE_IDX) + \ + reg ## block ## id ## _ ## reg_name + +#define SRII_DWB(reg_name, temp_name, block, id)\ + REG_STRUCT.reg_name[id] = BASE(reg ## block ## id ## _ ## temp_name ## _BASE_IDX) + \ + reg ## block ## id ## _ ## temp_name + +#define DCCG_SRII(reg_name, block, id)\ + REG_STRUCT.block ## _ ## reg_name[id] = BASE(reg ## block ## id ## _ ## reg_name ## _BASE_IDX) + \ + reg ## block ## id ## _ ## reg_name + +#define SF_DWB2(reg_name, block, id, field_name, post_fix) \ + .field_name = reg_name ## __ ## field_name ## post_fix + +#define VUPDATE_SRII(reg_name, block, id)\ + REG_STRUCT.reg_name[id] = BASE(reg ## reg_name ## _ ## block ## id ## _BASE_IDX) + \ + reg ## reg_name ## _ ## block ## id + +/* NBIO */ +#define NBIO_BASE_INNER(seg) ctx->nbio_reg_offsets[seg] + +#define NBIO_BASE(seg) \ + NBIO_BASE_INNER(seg) + +#define NBIO_SR(reg_name)\ + REG_STRUCT.reg_name = NBIO_BASE(regBIF_BX0_ ## reg_name ## _BASE_IDX) + \ + regBIF_BX0_ ## reg_name +#define NBIO_SR_ARR(reg_name, id)\ + REG_STRUCT[id].reg_name = NBIO_BASE(regBIF_BX0_ ## reg_name ## _BASE_IDX) + \ + regBIF_BX0_ ## reg_name + +#define CTX ctx +#define REG(reg_name) \ + (ctx->dcn_reg_offsets[reg ## reg_name ## _BASE_IDX] + reg ## reg_name) + +static struct bios_registers bios_regs; + +#define bios_regs_init() \ + ( \ + NBIO_SR(BIOS_SCRATCH_3),\ + NBIO_SR(BIOS_SCRATCH_6)\ + ) + +#define clk_src_regs_init(index, pllid)\ + CS_COMMON_REG_LIST_DCN3_0_RI(index, pllid) + +static struct dce110_clk_src_regs clk_src_regs[5]; + +static const struct dce110_clk_src_shift cs_shift = { + CS_COMMON_MASK_SH_LIST_DCN3_2(__SHIFT) +}; + +static const struct dce110_clk_src_mask cs_mask = { + CS_COMMON_MASK_SH_LIST_DCN3_2(_MASK) +}; + +#define abm_regs_init(id)\ + ABM_DCN32_REG_LIST_RI(id) + +static struct dce_abm_registers abm_regs[4]; + +static const struct dce_abm_shift abm_shift = { + ABM_MASK_SH_LIST_DCN32(__SHIFT) +}; + +static const struct dce_abm_mask abm_mask = { + ABM_MASK_SH_LIST_DCN32(_MASK) +}; + +#define audio_regs_init(id)\ + AUD_COMMON_REG_LIST_RI(id) + +static struct dce_audio_registers audio_regs[5]; + +#define DCE120_AUD_COMMON_MASK_SH_LIST(mask_sh)\ + SF(AZF0ENDPOINT0_AZALIA_F0_CODEC_ENDPOINT_INDEX, AZALIA_ENDPOINT_REG_INDEX, mask_sh),\ + SF(AZF0ENDPOINT0_AZALIA_F0_CODEC_ENDPOINT_DATA, AZALIA_ENDPOINT_REG_DATA, mask_sh),\ + AUD_COMMON_MASK_SH_LIST_BASE(mask_sh) + +static const struct dce_audio_shift audio_shift = { + DCE120_AUD_COMMON_MASK_SH_LIST(__SHIFT) +}; + +static const struct dce_audio_mask audio_mask = { + DCE120_AUD_COMMON_MASK_SH_LIST(_MASK) +}; + +#define vpg_regs_init(id)\ + VPG_DCN3_REG_LIST_RI(id) + +static struct dcn30_vpg_registers vpg_regs[10]; + +static const struct dcn30_vpg_shift vpg_shift = { + DCN3_VPG_MASK_SH_LIST(__SHIFT) +}; + +static const struct dcn30_vpg_mask vpg_mask = { + DCN3_VPG_MASK_SH_LIST(_MASK) +}; + +#define afmt_regs_init(id)\ + AFMT_DCN3_REG_LIST_RI(id) + +static struct dcn30_afmt_registers afmt_regs[6]; + +static const struct dcn30_afmt_shift afmt_shift = { + DCN3_AFMT_MASK_SH_LIST(__SHIFT) +}; + +static const struct dcn30_afmt_mask afmt_mask = { + DCN3_AFMT_MASK_SH_LIST(_MASK) +}; + +#define apg_regs_init(id)\ + APG_DCN31_REG_LIST_RI(id) + +static struct dcn31_apg_registers apg_regs[4]; + +static const struct dcn31_apg_shift apg_shift = { + DCN31_APG_MASK_SH_LIST(__SHIFT) +}; + +static const struct dcn31_apg_mask apg_mask = { + DCN31_APG_MASK_SH_LIST(_MASK) +}; + +#define stream_enc_regs_init(id)\ + SE_DCN32_REG_LIST_RI(id) + +static struct dcn10_stream_enc_registers stream_enc_regs[5]; + +static const struct dcn10_stream_encoder_shift se_shift = { + SE_COMMON_MASK_SH_LIST_DCN32(__SHIFT) +}; + +static const struct dcn10_stream_encoder_mask se_mask = { + SE_COMMON_MASK_SH_LIST_DCN32(_MASK) +}; + + +#define aux_regs_init(id)\ + DCN2_AUX_REG_LIST_RI(id) + +static struct dcn10_link_enc_aux_registers link_enc_aux_regs[5]; + +#define hpd_regs_init(id)\ + HPD_REG_LIST_RI(id) + +static struct dcn10_link_enc_hpd_registers link_enc_hpd_regs[5]; + +#define link_regs_init(id, phyid)\ + ( \ + LE_DCN31_REG_LIST_RI(id), \ + UNIPHY_DCN2_REG_LIST_RI(id, phyid)\ + ) + /*DPCS_DCN31_REG_LIST(id),*/ \ + +static struct dcn10_link_enc_registers link_enc_regs[5]; + +static const struct dcn10_link_enc_shift le_shift = { + LINK_ENCODER_MASK_SH_LIST_DCN31(__SHIFT), \ +// DPCS_DCN31_MASK_SH_LIST(__SHIFT) +}; + +static const struct dcn10_link_enc_mask le_mask = { + LINK_ENCODER_MASK_SH_LIST_DCN31(_MASK), \ +// DPCS_DCN31_MASK_SH_LIST(_MASK) +}; + +#define hpo_dp_stream_encoder_reg_init(id)\ + DCN3_1_HPO_DP_STREAM_ENC_REG_LIST_RI(id) + +static struct dcn31_hpo_dp_stream_encoder_registers hpo_dp_stream_enc_regs[4]; + +static const struct dcn31_hpo_dp_stream_encoder_shift hpo_dp_se_shift = { + DCN3_1_HPO_DP_STREAM_ENC_MASK_SH_LIST(__SHIFT) +}; + +static const struct dcn31_hpo_dp_stream_encoder_mask hpo_dp_se_mask = { + DCN3_1_HPO_DP_STREAM_ENC_MASK_SH_LIST(_MASK) +}; + + +#define hpo_dp_link_encoder_reg_init(id)\ + DCN3_1_HPO_DP_LINK_ENC_REG_LIST_RI(id) + /*DCN3_1_RDPCSTX_REG_LIST(0),*/ + /*DCN3_1_RDPCSTX_REG_LIST(1),*/ + /*DCN3_1_RDPCSTX_REG_LIST(2),*/ + /*DCN3_1_RDPCSTX_REG_LIST(3),*/ + +static struct dcn31_hpo_dp_link_encoder_registers hpo_dp_link_enc_regs[2]; + +static const struct dcn31_hpo_dp_link_encoder_shift hpo_dp_le_shift = { + DCN3_2_HPO_DP_LINK_ENC_MASK_SH_LIST(__SHIFT) +}; + +static const struct dcn31_hpo_dp_link_encoder_mask hpo_dp_le_mask = { + DCN3_2_HPO_DP_LINK_ENC_MASK_SH_LIST(_MASK) +}; + +#define dpp_regs_init(id)\ + DPP_REG_LIST_DCN30_COMMON_RI(id) + +static struct dcn3_dpp_registers dpp_regs[4]; + +static const struct dcn3_dpp_shift tf_shift = { + DPP_REG_LIST_SH_MASK_DCN30_COMMON(__SHIFT) +}; + +static const struct dcn3_dpp_mask tf_mask = { + DPP_REG_LIST_SH_MASK_DCN30_COMMON(_MASK) +}; + + +#define opp_regs_init(id)\ + OPP_REG_LIST_DCN30_RI(id) + +static struct dcn20_opp_registers opp_regs[4]; + +static const struct dcn20_opp_shift opp_shift = { + OPP_MASK_SH_LIST_DCN20(__SHIFT) +}; + +static const struct dcn20_opp_mask opp_mask = { + OPP_MASK_SH_LIST_DCN20(_MASK) +}; + +#define aux_engine_regs_init(id) \ + ( \ + AUX_COMMON_REG_LIST0_RI(id), SR_ARR_INIT(AUXN_IMPCAL, id, 0), \ + SR_ARR_INIT(AUXP_IMPCAL, id, 0), \ + SR_ARR_INIT(AUX_RESET_MASK, id, DP_AUX0_AUX_CONTROL__AUX_RESET_MASK), \ + SR_ARR_INIT(AUX_RESET_MASK, id, DP_AUX0_AUX_CONTROL__AUX_RESET_MASK)\ + ) + +static struct dce110_aux_registers aux_engine_regs[5]; + +static const struct dce110_aux_registers_shift aux_shift = { + DCN_AUX_MASK_SH_LIST(__SHIFT) +}; + +static const struct dce110_aux_registers_mask aux_mask = { + DCN_AUX_MASK_SH_LIST(_MASK) +}; + +#define dwbc_regs_dcn3_init(id)\ + DWBC_COMMON_REG_LIST_DCN30_RI(id) + +static struct dcn30_dwbc_registers dwbc30_regs[1]; + +static const struct dcn30_dwbc_shift dwbc30_shift = { + DWBC_COMMON_MASK_SH_LIST_DCN30(__SHIFT) +}; + +static const struct dcn30_dwbc_mask dwbc30_mask = { + DWBC_COMMON_MASK_SH_LIST_DCN30(_MASK) +}; + +#define mcif_wb_regs_dcn3_init(id)\ + MCIF_WB_COMMON_REG_LIST_DCN32_RI(id) + +static struct dcn30_mmhubbub_registers mcif_wb30_regs[1]; + +static const struct dcn30_mmhubbub_shift mcif_wb30_shift = { + MCIF_WB_COMMON_MASK_SH_LIST_DCN32(__SHIFT) +}; + +static const struct dcn30_mmhubbub_mask mcif_wb30_mask = { + MCIF_WB_COMMON_MASK_SH_LIST_DCN32(_MASK) +}; + +#define dsc_regsDCN20_init(id)\ + DSC_REG_LIST_DCN20_RI(id) + +static struct dcn20_dsc_registers dsc_regs[4]; + +static const struct dcn20_dsc_shift dsc_shift = { + DSC_REG_LIST_SH_MASK_DCN20(__SHIFT) +}; + +static const struct dcn20_dsc_mask dsc_mask = { + DSC_REG_LIST_SH_MASK_DCN20(_MASK) +}; + +static struct dcn30_mpc_registers mpc_regs; +#define dcn_mpc_regs_init()\ + MPC_REG_LIST_DCN3_2_RI(0),\ + MPC_REG_LIST_DCN3_2_RI(1),\ + MPC_REG_LIST_DCN3_2_RI(2),\ + MPC_REG_LIST_DCN3_2_RI(3),\ + MPC_OUT_MUX_REG_LIST_DCN3_0_RI(0),\ + MPC_OUT_MUX_REG_LIST_DCN3_0_RI(1),\ + MPC_OUT_MUX_REG_LIST_DCN3_0_RI(2),\ + MPC_OUT_MUX_REG_LIST_DCN3_0_RI(3),\ + MPC_DWB_MUX_REG_LIST_DCN3_0_RI(0) + +static const struct dcn30_mpc_shift mpc_shift = { + MPC_COMMON_MASK_SH_LIST_DCN32(__SHIFT) +}; + +static const struct dcn30_mpc_mask mpc_mask = { + MPC_COMMON_MASK_SH_LIST_DCN32(_MASK) +}; + +#define optc_regs_init(id)\ + OPTC_COMMON_REG_LIST_DCN3_2_RI(id) + +static struct dcn_optc_registers optc_regs[4]; + +static const struct dcn_optc_shift optc_shift = { + OPTC_COMMON_MASK_SH_LIST_DCN3_2(__SHIFT) +}; + +static const struct dcn_optc_mask optc_mask = { + OPTC_COMMON_MASK_SH_LIST_DCN3_2(_MASK) +}; + +#define hubp_regs_init(id) \ + HUBP_REG_LIST_DCN32_RI(id) + +static struct dcn_hubp2_registers hubp_regs[4]; + +static const struct dcn_hubp2_shift hubp_shift = { + HUBP_MASK_SH_LIST_DCN32(__SHIFT) +}; + +static const struct dcn_hubp2_mask hubp_mask = { + HUBP_MASK_SH_LIST_DCN32(_MASK) +}; + +static struct dcn_hubbub_registers hubbub_reg; +#define hubbub_reg_init()\ + HUBBUB_REG_LIST_DCN32_RI(0) + +static const struct dcn_hubbub_shift hubbub_shift = { + HUBBUB_MASK_SH_LIST_DCN32(__SHIFT) +}; + +static const struct dcn_hubbub_mask hubbub_mask = { + HUBBUB_MASK_SH_LIST_DCN32(_MASK) +}; + +static struct dccg_registers dccg_regs; + +#define dccg_regs_init()\ + DCCG_REG_LIST_DCN32_RI() + +static const struct dccg_shift dccg_shift = { + DCCG_MASK_SH_LIST_DCN32(__SHIFT) +}; + +static const struct dccg_mask dccg_mask = { + DCCG_MASK_SH_LIST_DCN32(_MASK) +}; + + +#define SRII2(reg_name_pre, reg_name_post, id)\ + .reg_name_pre ## _ ## reg_name_post[id] = BASE(reg ## reg_name_pre \ + ## id ## _ ## reg_name_post ## _BASE_IDX) + \ + reg ## reg_name_pre ## id ## _ ## reg_name_post + + +#define HWSEQ_DCN32_REG_LIST()\ + SR(DCHUBBUB_GLOBAL_TIMER_CNTL), \ + SR(DIO_MEM_PWR_CTRL), \ + SR(ODM_MEM_PWR_CTRL3), \ + SR(MMHUBBUB_MEM_PWR_CNTL), \ + SR(DCCG_GATE_DISABLE_CNTL), \ + SR(DCCG_GATE_DISABLE_CNTL2), \ + SR(DCFCLK_CNTL),\ + SR(DC_MEM_GLOBAL_PWR_REQ_CNTL), \ + SRII(PIXEL_RATE_CNTL, OTG, 0), \ + SRII(PIXEL_RATE_CNTL, OTG, 1),\ + SRII(PIXEL_RATE_CNTL, OTG, 2),\ + SRII(PIXEL_RATE_CNTL, OTG, 3),\ + SRII(PHYPLL_PIXEL_RATE_CNTL, OTG, 0),\ + SRII(PHYPLL_PIXEL_RATE_CNTL, OTG, 1),\ + SRII(PHYPLL_PIXEL_RATE_CNTL, OTG, 2),\ + SRII(PHYPLL_PIXEL_RATE_CNTL, OTG, 3),\ + SR(MICROSECOND_TIME_BASE_DIV), \ + SR(MILLISECOND_TIME_BASE_DIV), \ + SR(DISPCLK_FREQ_CHANGE_CNTL), \ + SR(RBBMIF_TIMEOUT_DIS), \ + SR(RBBMIF_TIMEOUT_DIS_2), \ + SR(DCHUBBUB_CRC_CTRL), \ + SR(DPP_TOP0_DPP_CRC_CTRL), \ + SR(DPP_TOP0_DPP_CRC_VAL_B_A), \ + SR(DPP_TOP0_DPP_CRC_VAL_R_G), \ + SR(MPC_CRC_CTRL), \ + SR(MPC_CRC_RESULT_GB), \ + SR(MPC_CRC_RESULT_C), \ + SR(MPC_CRC_RESULT_AR), \ + SR(DOMAIN0_PG_CONFIG), \ + SR(DOMAIN1_PG_CONFIG), \ + SR(DOMAIN2_PG_CONFIG), \ + SR(DOMAIN3_PG_CONFIG), \ + SR(DOMAIN16_PG_CONFIG), \ + SR(DOMAIN17_PG_CONFIG), \ + SR(DOMAIN18_PG_CONFIG), \ + SR(DOMAIN19_PG_CONFIG), \ + SR(DOMAIN0_PG_STATUS), \ + SR(DOMAIN1_PG_STATUS), \ + SR(DOMAIN2_PG_STATUS), \ + SR(DOMAIN3_PG_STATUS), \ + SR(DOMAIN16_PG_STATUS), \ + SR(DOMAIN17_PG_STATUS), \ + SR(DOMAIN18_PG_STATUS), \ + SR(DOMAIN19_PG_STATUS), \ + SR(D1VGA_CONTROL), \ + SR(D2VGA_CONTROL), \ + SR(D3VGA_CONTROL), \ + SR(D4VGA_CONTROL), \ + SR(D5VGA_CONTROL), \ + SR(D6VGA_CONTROL), \ + SR(DC_IP_REQUEST_CNTL), \ + SR(AZALIA_AUDIO_DTO), \ + SR(AZALIA_CONTROLLER_CLOCK_GATING) + +static struct dce_hwseq_registers hwseq_reg; + +#define hwseq_reg_init()\ + HWSEQ_DCN32_REG_LIST() + +#define HWSEQ_DCN32_MASK_SH_LIST(mask_sh)\ + HWSEQ_DCN_MASK_SH_LIST(mask_sh), \ + HWS_SF(, DCHUBBUB_GLOBAL_TIMER_CNTL, DCHUBBUB_GLOBAL_TIMER_REFDIV, mask_sh), \ + HWS_SF(, DOMAIN0_PG_CONFIG, DOMAIN_POWER_FORCEON, mask_sh), \ + HWS_SF(, DOMAIN0_PG_CONFIG, DOMAIN_POWER_GATE, mask_sh), \ + HWS_SF(, DOMAIN1_PG_CONFIG, DOMAIN_POWER_FORCEON, mask_sh), \ + HWS_SF(, DOMAIN1_PG_CONFIG, DOMAIN_POWER_GATE, mask_sh), \ + HWS_SF(, DOMAIN2_PG_CONFIG, DOMAIN_POWER_FORCEON, mask_sh), \ + HWS_SF(, DOMAIN2_PG_CONFIG, DOMAIN_POWER_GATE, mask_sh), \ + HWS_SF(, DOMAIN3_PG_CONFIG, DOMAIN_POWER_FORCEON, mask_sh), \ + HWS_SF(, DOMAIN3_PG_CONFIG, DOMAIN_POWER_GATE, mask_sh), \ + HWS_SF(, DOMAIN16_PG_CONFIG, DOMAIN_POWER_FORCEON, mask_sh), \ + HWS_SF(, DOMAIN16_PG_CONFIG, DOMAIN_POWER_GATE, mask_sh), \ + HWS_SF(, DOMAIN17_PG_CONFIG, DOMAIN_POWER_FORCEON, mask_sh), \ + HWS_SF(, DOMAIN17_PG_CONFIG, DOMAIN_POWER_GATE, mask_sh), \ + HWS_SF(, DOMAIN18_PG_CONFIG, DOMAIN_POWER_FORCEON, mask_sh), \ + HWS_SF(, DOMAIN18_PG_CONFIG, DOMAIN_POWER_GATE, mask_sh), \ + HWS_SF(, DOMAIN19_PG_CONFIG, DOMAIN_POWER_FORCEON, mask_sh), \ + HWS_SF(, DOMAIN19_PG_CONFIG, DOMAIN_POWER_GATE, mask_sh), \ + HWS_SF(, DOMAIN0_PG_STATUS, DOMAIN_PGFSM_PWR_STATUS, mask_sh), \ + HWS_SF(, DOMAIN1_PG_STATUS, DOMAIN_PGFSM_PWR_STATUS, mask_sh), \ + HWS_SF(, DOMAIN2_PG_STATUS, DOMAIN_PGFSM_PWR_STATUS, mask_sh), \ + HWS_SF(, DOMAIN3_PG_STATUS, DOMAIN_PGFSM_PWR_STATUS, mask_sh), \ + HWS_SF(, DOMAIN16_PG_STATUS, DOMAIN_PGFSM_PWR_STATUS, mask_sh), \ + HWS_SF(, DOMAIN17_PG_STATUS, DOMAIN_PGFSM_PWR_STATUS, mask_sh), \ + HWS_SF(, DOMAIN18_PG_STATUS, DOMAIN_PGFSM_PWR_STATUS, mask_sh), \ + HWS_SF(, DOMAIN19_PG_STATUS, DOMAIN_PGFSM_PWR_STATUS, mask_sh), \ + HWS_SF(, DC_IP_REQUEST_CNTL, IP_REQUEST_EN, mask_sh), \ + HWS_SF(, AZALIA_AUDIO_DTO, AZALIA_AUDIO_DTO_MODULE, mask_sh), \ + HWS_SF(, HPO_TOP_CLOCK_CONTROL, HPO_HDMISTREAMCLK_G_GATE_DIS, mask_sh), \ + HWS_SF(, ODM_MEM_PWR_CTRL3, ODM_MEM_UNASSIGNED_PWR_MODE, mask_sh), \ + HWS_SF(, ODM_MEM_PWR_CTRL3, ODM_MEM_VBLANK_PWR_MODE, mask_sh), \ + HWS_SF(, MMHUBBUB_MEM_PWR_CNTL, VGA_MEM_PWR_FORCE, mask_sh) + +static const struct dce_hwseq_shift hwseq_shift = { + HWSEQ_DCN32_MASK_SH_LIST(__SHIFT) +}; + +static const struct dce_hwseq_mask hwseq_mask = { + HWSEQ_DCN32_MASK_SH_LIST(_MASK) +}; +#define vmid_regs_init(id)\ + DCN20_VMID_REG_LIST_RI(id) + +static struct dcn_vmid_registers vmid_regs[16]; + +static const struct dcn20_vmid_shift vmid_shifts = { + DCN20_VMID_MASK_SH_LIST(__SHIFT) +}; + +static const struct dcn20_vmid_mask vmid_masks = { + DCN20_VMID_MASK_SH_LIST(_MASK) +}; + +static const struct resource_caps res_cap_dcn321 = { + .num_timing_generator = 4, + .num_opp = 4, + .num_video_plane = 4, + .num_audio = 5, + .num_stream_encoder = 5, + .num_hpo_dp_stream_encoder = 4, + .num_hpo_dp_link_encoder = 2, + .num_pll = 5, + .num_dwb = 1, + .num_ddc = 5, + .num_vmid = 16, + .num_mpc_3dlut = 4, + .num_dsc = 4, +}; + +static const struct dc_plane_cap plane_cap = { + .type = DC_PLANE_TYPE_DCN_UNIVERSAL, + .per_pixel_alpha = true, + + .pixel_format_support = { + .argb8888 = true, + .nv12 = true, + .fp16 = true, + .p010 = true, + .ayuv = false, + }, + + .max_upscale_factor = { + .argb8888 = 16000, + .nv12 = 16000, + .fp16 = 16000 + }, + + // 6:1 downscaling ratio: 1000/6 = 166.666 + .max_downscale_factor = { + .argb8888 = 167, + .nv12 = 167, + .fp16 = 167 + }, + 64, + 64 +}; + +static const struct dc_debug_options debug_defaults_drv = { + .disable_dmcu = true, + .force_abm_enable = false, + .timing_trace = false, + .clock_trace = true, + .disable_pplib_clock_request = false, + .pipe_split_policy = MPC_SPLIT_AVOID, + .force_single_disp_pipe_split = false, + .disable_dcc = DCC_ENABLE, + .vsr_support = true, + .performance_trace = false, + .max_downscale_src_width = 7680,/*upto 8K*/ + .disable_pplib_wm_range = false, + .scl_reset_length10 = true, + .sanity_checks = false, + .underflow_assert_delay_us = 0xFFFFFFFF, + .dwb_fi_phase = -1, // -1 = disable, + .dmub_command_table = true, + .enable_mem_low_power = { + .bits = { + .vga = false, + .i2c = false, + .dmcu = false, // This is previously known to cause hang on S3 cycles if enabled + .dscl = false, + .cm = false, + .mpc = false, + .optc = true, + } + }, + .use_max_lb = true, + .force_disable_subvp = false, + .exit_idle_opt_for_cursor_updates = true, + .enable_single_display_2to1_odm_policy = true, + + /*must match enable_single_display_2to1_odm_policy to support dynamic ODM transitions*/ + .enable_double_buffered_dsc_pg_support = true, + .enable_dp_dig_pixel_rate_div_policy = 1, + .allow_sw_cursor_fallback = false, // Linux can't do SW cursor "fallback" + .alloc_extra_way_for_cursor = true, + .min_prefetch_in_strobe_ns = 60000, // 60us + .disable_unbounded_requesting = false, + .override_dispclk_programming = true, + .disable_fpo_optimizations = false, + .fpo_vactive_margin_us = 2000, // 2000us + .disable_fpo_vactive = false, + .disable_boot_optimizations = false, + .disable_subvp_high_refresh = false, + .fpo_vactive_min_active_margin_us = 200, + .fpo_vactive_max_blank_us = 1000, + .enable_legacy_fast_update = false, + .disable_dc_mode_overwrite = true, + .using_dml2 = false, +}; + +static struct dce_aux *dcn321_aux_engine_create( + struct dc_context *ctx, + uint32_t inst) +{ + struct aux_engine_dce110 *aux_engine = + kzalloc(sizeof(struct aux_engine_dce110), GFP_KERNEL); + + if (!aux_engine) + return NULL; + +#undef REG_STRUCT +#define REG_STRUCT aux_engine_regs + aux_engine_regs_init(0), + aux_engine_regs_init(1), + aux_engine_regs_init(2), + aux_engine_regs_init(3), + aux_engine_regs_init(4); + + dce110_aux_engine_construct(aux_engine, ctx, inst, + SW_AUX_TIMEOUT_PERIOD_MULTIPLIER * AUX_TIMEOUT_PERIOD, + &aux_engine_regs[inst], + &aux_mask, + &aux_shift, + ctx->dc->caps.extended_aux_timeout_support); + + return &aux_engine->base; +} +#define i2c_inst_regs_init(id)\ + I2C_HW_ENGINE_COMMON_REG_LIST_DCN30_RI(id) + +static struct dce_i2c_registers i2c_hw_regs[5]; + +static const struct dce_i2c_shift i2c_shifts = { + I2C_COMMON_MASK_SH_LIST_DCN30(__SHIFT) +}; + +static const struct dce_i2c_mask i2c_masks = { + I2C_COMMON_MASK_SH_LIST_DCN30(_MASK) +}; + +static struct dce_i2c_hw *dcn321_i2c_hw_create( + struct dc_context *ctx, + uint32_t inst) +{ + struct dce_i2c_hw *dce_i2c_hw = + kzalloc(sizeof(struct dce_i2c_hw), GFP_KERNEL); + + if (!dce_i2c_hw) + return NULL; + +#undef REG_STRUCT +#define REG_STRUCT i2c_hw_regs + i2c_inst_regs_init(1), + i2c_inst_regs_init(2), + i2c_inst_regs_init(3), + i2c_inst_regs_init(4), + i2c_inst_regs_init(5); + + dcn2_i2c_hw_construct(dce_i2c_hw, ctx, inst, + &i2c_hw_regs[inst], &i2c_shifts, &i2c_masks); + + return dce_i2c_hw; +} + +static struct clock_source *dcn321_clock_source_create( + struct dc_context *ctx, + struct dc_bios *bios, + enum clock_source_id id, + const struct dce110_clk_src_regs *regs, + bool dp_clk_src) +{ + struct dce110_clk_src *clk_src = + kzalloc(sizeof(struct dce110_clk_src), GFP_KERNEL); + + if (!clk_src) + return NULL; + + if (dcn31_clk_src_construct(clk_src, ctx, bios, id, + regs, &cs_shift, &cs_mask)) { + clk_src->base.dp_clk_src = dp_clk_src; + return &clk_src->base; + } + + kfree(clk_src); + BREAK_TO_DEBUGGER(); + return NULL; +} + +static struct hubbub *dcn321_hubbub_create(struct dc_context *ctx) +{ + int i; + + struct dcn20_hubbub *hubbub2 = kzalloc(sizeof(struct dcn20_hubbub), + GFP_KERNEL); + + if (!hubbub2) + return NULL; + +#undef REG_STRUCT +#define REG_STRUCT hubbub_reg + hubbub_reg_init(); + +#undef REG_STRUCT +#define REG_STRUCT vmid_regs + vmid_regs_init(0), + vmid_regs_init(1), + vmid_regs_init(2), + vmid_regs_init(3), + vmid_regs_init(4), + vmid_regs_init(5), + vmid_regs_init(6), + vmid_regs_init(7), + vmid_regs_init(8), + vmid_regs_init(9), + vmid_regs_init(10), + vmid_regs_init(11), + vmid_regs_init(12), + vmid_regs_init(13), + vmid_regs_init(14), + vmid_regs_init(15); + + hubbub32_construct(hubbub2, ctx, + &hubbub_reg, + &hubbub_shift, + &hubbub_mask, + ctx->dc->dml.ip.det_buffer_size_kbytes, + ctx->dc->dml.ip.pixel_chunk_size_kbytes, + ctx->dc->dml.ip.config_return_buffer_size_in_kbytes); + + + for (i = 0; i < res_cap_dcn321.num_vmid; i++) { + struct dcn20_vmid *vmid = &hubbub2->vmid[i]; + + vmid->ctx = ctx; + + vmid->regs = &vmid_regs[i]; + vmid->shifts = &vmid_shifts; + vmid->masks = &vmid_masks; + } + + return &hubbub2->base; +} + +static struct hubp *dcn321_hubp_create( + struct dc_context *ctx, + uint32_t inst) +{ + struct dcn20_hubp *hubp2 = + kzalloc(sizeof(struct dcn20_hubp), GFP_KERNEL); + + if (!hubp2) + return NULL; + +#undef REG_STRUCT +#define REG_STRUCT hubp_regs + hubp_regs_init(0), + hubp_regs_init(1), + hubp_regs_init(2), + hubp_regs_init(3); + + if (hubp32_construct(hubp2, ctx, inst, + &hubp_regs[inst], &hubp_shift, &hubp_mask)) + return &hubp2->base; + + BREAK_TO_DEBUGGER(); + kfree(hubp2); + return NULL; +} + +static void dcn321_dpp_destroy(struct dpp **dpp) +{ + kfree(TO_DCN30_DPP(*dpp)); + *dpp = NULL; +} + +static struct dpp *dcn321_dpp_create( + struct dc_context *ctx, + uint32_t inst) +{ + struct dcn3_dpp *dpp3 = + kzalloc(sizeof(struct dcn3_dpp), GFP_KERNEL); + + if (!dpp3) + return NULL; + +#undef REG_STRUCT +#define REG_STRUCT dpp_regs + dpp_regs_init(0), + dpp_regs_init(1), + dpp_regs_init(2), + dpp_regs_init(3); + + if (dpp32_construct(dpp3, ctx, inst, + &dpp_regs[inst], &tf_shift, &tf_mask)) + return &dpp3->base; + + BREAK_TO_DEBUGGER(); + kfree(dpp3); + return NULL; +} + +static struct mpc *dcn321_mpc_create( + struct dc_context *ctx, + int num_mpcc, + int num_rmu) +{ + struct dcn30_mpc *mpc30 = kzalloc(sizeof(struct dcn30_mpc), + GFP_KERNEL); + + if (!mpc30) + return NULL; + +#undef REG_STRUCT +#define REG_STRUCT mpc_regs + dcn_mpc_regs_init(); + + dcn32_mpc_construct(mpc30, ctx, + &mpc_regs, + &mpc_shift, + &mpc_mask, + num_mpcc, + num_rmu); + + return &mpc30->base; +} + +static struct output_pixel_processor *dcn321_opp_create( + struct dc_context *ctx, uint32_t inst) +{ + struct dcn20_opp *opp2 = + kzalloc(sizeof(struct dcn20_opp), GFP_KERNEL); + + if (!opp2) { + BREAK_TO_DEBUGGER(); + return NULL; + } + +#undef REG_STRUCT +#define REG_STRUCT opp_regs + opp_regs_init(0), + opp_regs_init(1), + opp_regs_init(2), + opp_regs_init(3); + + dcn20_opp_construct(opp2, ctx, inst, + &opp_regs[inst], &opp_shift, &opp_mask); + return &opp2->base; +} + + +static struct timing_generator *dcn321_timing_generator_create( + struct dc_context *ctx, + uint32_t instance) +{ + struct optc *tgn10 = + kzalloc(sizeof(struct optc), GFP_KERNEL); + + if (!tgn10) + return NULL; + +#undef REG_STRUCT +#define REG_STRUCT optc_regs + optc_regs_init(0), + optc_regs_init(1), + optc_regs_init(2), + optc_regs_init(3); + + tgn10->base.inst = instance; + tgn10->base.ctx = ctx; + + tgn10->tg_regs = &optc_regs[instance]; + tgn10->tg_shift = &optc_shift; + tgn10->tg_mask = &optc_mask; + + dcn32_timing_generator_init(tgn10); + + return &tgn10->base; +} + +static const struct encoder_feature_support link_enc_feature = { + .max_hdmi_deep_color = COLOR_DEPTH_121212, + .max_hdmi_pixel_clock = 600000, + .hdmi_ycbcr420_supported = true, + .dp_ycbcr420_supported = true, + .fec_supported = true, + .flags.bits.IS_HBR2_CAPABLE = true, + .flags.bits.IS_HBR3_CAPABLE = true, + .flags.bits.IS_TPS3_CAPABLE = true, + .flags.bits.IS_TPS4_CAPABLE = true +}; + +static struct link_encoder *dcn321_link_encoder_create( + struct dc_context *ctx, + const struct encoder_init_data *enc_init_data) +{ + struct dcn20_link_encoder *enc20 = + kzalloc(sizeof(struct dcn20_link_encoder), GFP_KERNEL); + + if (!enc20) + return NULL; + +#undef REG_STRUCT +#define REG_STRUCT link_enc_aux_regs + aux_regs_init(0), + aux_regs_init(1), + aux_regs_init(2), + aux_regs_init(3), + aux_regs_init(4); + +#undef REG_STRUCT +#define REG_STRUCT link_enc_hpd_regs + hpd_regs_init(0), + hpd_regs_init(1), + hpd_regs_init(2), + hpd_regs_init(3), + hpd_regs_init(4); + +#undef REG_STRUCT +#define REG_STRUCT link_enc_regs + link_regs_init(0, A), + link_regs_init(1, B), + link_regs_init(2, C), + link_regs_init(3, D), + link_regs_init(4, E); + + dcn321_link_encoder_construct(enc20, + enc_init_data, + &link_enc_feature, + &link_enc_regs[enc_init_data->transmitter], + &link_enc_aux_regs[enc_init_data->channel - 1], + &link_enc_hpd_regs[enc_init_data->hpd_source], + &le_shift, + &le_mask); + + return &enc20->enc10.base; +} + +static void read_dce_straps( + struct dc_context *ctx, + struct resource_straps *straps) +{ + generic_reg_get(ctx, ctx->dcn_reg_offsets[regDC_PINSTRAPS_BASE_IDX] + regDC_PINSTRAPS, + FN(DC_PINSTRAPS, DC_PINSTRAPS_AUDIO), &straps->dc_pinstraps_audio); + +} + +static struct audio *dcn321_create_audio( + struct dc_context *ctx, unsigned int inst) +{ + +#undef REG_STRUCT +#define REG_STRUCT audio_regs + audio_regs_init(0), + audio_regs_init(1), + audio_regs_init(2), + audio_regs_init(3), + audio_regs_init(4); + + return dce_audio_create(ctx, inst, + &audio_regs[inst], &audio_shift, &audio_mask); +} + +static struct vpg *dcn321_vpg_create( + struct dc_context *ctx, + uint32_t inst) +{ + struct dcn30_vpg *vpg3 = kzalloc(sizeof(struct dcn30_vpg), GFP_KERNEL); + + if (!vpg3) + return NULL; + +#undef REG_STRUCT +#define REG_STRUCT vpg_regs + vpg_regs_init(0), + vpg_regs_init(1), + vpg_regs_init(2), + vpg_regs_init(3), + vpg_regs_init(4), + vpg_regs_init(5), + vpg_regs_init(6), + vpg_regs_init(7), + vpg_regs_init(8), + vpg_regs_init(9); + + vpg3_construct(vpg3, ctx, inst, + &vpg_regs[inst], + &vpg_shift, + &vpg_mask); + + return &vpg3->base; +} + +static struct afmt *dcn321_afmt_create( + struct dc_context *ctx, + uint32_t inst) +{ + struct dcn30_afmt *afmt3 = kzalloc(sizeof(struct dcn30_afmt), GFP_KERNEL); + + if (!afmt3) + return NULL; + +#undef REG_STRUCT +#define REG_STRUCT afmt_regs + afmt_regs_init(0), + afmt_regs_init(1), + afmt_regs_init(2), + afmt_regs_init(3), + afmt_regs_init(4), + afmt_regs_init(5); + + afmt3_construct(afmt3, ctx, inst, + &afmt_regs[inst], + &afmt_shift, + &afmt_mask); + + return &afmt3->base; +} + +static struct apg *dcn321_apg_create( + struct dc_context *ctx, + uint32_t inst) +{ + struct dcn31_apg *apg31 = kzalloc(sizeof(struct dcn31_apg), GFP_KERNEL); + + if (!apg31) + return NULL; + +#undef REG_STRUCT +#define REG_STRUCT apg_regs + apg_regs_init(0), + apg_regs_init(1), + apg_regs_init(2), + apg_regs_init(3); + + apg31_construct(apg31, ctx, inst, + &apg_regs[inst], + &apg_shift, + &apg_mask); + + return &apg31->base; +} + +static struct stream_encoder *dcn321_stream_encoder_create( + enum engine_id eng_id, + struct dc_context *ctx) +{ + struct dcn10_stream_encoder *enc1; + struct vpg *vpg; + struct afmt *afmt; + int vpg_inst; + int afmt_inst; + + /* Mapping of VPG, AFMT, DME register blocks to DIO block instance */ + if (eng_id <= ENGINE_ID_DIGF) { + vpg_inst = eng_id; + afmt_inst = eng_id; + } else + return NULL; + + enc1 = kzalloc(sizeof(struct dcn10_stream_encoder), GFP_KERNEL); + vpg = dcn321_vpg_create(ctx, vpg_inst); + afmt = dcn321_afmt_create(ctx, afmt_inst); + + if (!enc1 || !vpg || !afmt) { + kfree(enc1); + kfree(vpg); + kfree(afmt); + return NULL; + } + +#undef REG_STRUCT +#define REG_STRUCT stream_enc_regs + stream_enc_regs_init(0), + stream_enc_regs_init(1), + stream_enc_regs_init(2), + stream_enc_regs_init(3), + stream_enc_regs_init(4); + + dcn32_dio_stream_encoder_construct(enc1, ctx, ctx->dc_bios, + eng_id, vpg, afmt, + &stream_enc_regs[eng_id], + &se_shift, &se_mask); + + return &enc1->base; +} + +static struct hpo_dp_stream_encoder *dcn321_hpo_dp_stream_encoder_create( + enum engine_id eng_id, + struct dc_context *ctx) +{ + struct dcn31_hpo_dp_stream_encoder *hpo_dp_enc31; + struct vpg *vpg; + struct apg *apg; + uint32_t hpo_dp_inst; + uint32_t vpg_inst; + uint32_t apg_inst; + + ASSERT((eng_id >= ENGINE_ID_HPO_DP_0) && (eng_id <= ENGINE_ID_HPO_DP_3)); + hpo_dp_inst = eng_id - ENGINE_ID_HPO_DP_0; + + /* Mapping of VPG register blocks to HPO DP block instance: + * VPG[6] -> HPO_DP[0] + * VPG[7] -> HPO_DP[1] + * VPG[8] -> HPO_DP[2] + * VPG[9] -> HPO_DP[3] + */ + vpg_inst = hpo_dp_inst + 6; + + /* Mapping of APG register blocks to HPO DP block instance: + * APG[0] -> HPO_DP[0] + * APG[1] -> HPO_DP[1] + * APG[2] -> HPO_DP[2] + * APG[3] -> HPO_DP[3] + */ + apg_inst = hpo_dp_inst; + + /* allocate HPO stream encoder and create VPG sub-block */ + hpo_dp_enc31 = kzalloc(sizeof(struct dcn31_hpo_dp_stream_encoder), GFP_KERNEL); + vpg = dcn321_vpg_create(ctx, vpg_inst); + apg = dcn321_apg_create(ctx, apg_inst); + + if (!hpo_dp_enc31 || !vpg || !apg) { + kfree(hpo_dp_enc31); + kfree(vpg); + kfree(apg); + return NULL; + } + +#undef REG_STRUCT +#define REG_STRUCT hpo_dp_stream_enc_regs + hpo_dp_stream_encoder_reg_init(0), + hpo_dp_stream_encoder_reg_init(1), + hpo_dp_stream_encoder_reg_init(2), + hpo_dp_stream_encoder_reg_init(3); + + dcn31_hpo_dp_stream_encoder_construct(hpo_dp_enc31, ctx, ctx->dc_bios, + hpo_dp_inst, eng_id, vpg, apg, + &hpo_dp_stream_enc_regs[hpo_dp_inst], + &hpo_dp_se_shift, &hpo_dp_se_mask); + + return &hpo_dp_enc31->base; +} + +static struct hpo_dp_link_encoder *dcn321_hpo_dp_link_encoder_create( + uint8_t inst, + struct dc_context *ctx) +{ + struct dcn31_hpo_dp_link_encoder *hpo_dp_enc31; + + /* allocate HPO link encoder */ + hpo_dp_enc31 = kzalloc(sizeof(struct dcn31_hpo_dp_link_encoder), GFP_KERNEL); + +#undef REG_STRUCT +#define REG_STRUCT hpo_dp_link_enc_regs + hpo_dp_link_encoder_reg_init(0), + hpo_dp_link_encoder_reg_init(1); + + hpo_dp_link_encoder32_construct(hpo_dp_enc31, ctx, inst, + &hpo_dp_link_enc_regs[inst], + &hpo_dp_le_shift, &hpo_dp_le_mask); + + return &hpo_dp_enc31->base; +} + +static struct dce_hwseq *dcn321_hwseq_create( + struct dc_context *ctx) +{ + struct dce_hwseq *hws = kzalloc(sizeof(struct dce_hwseq), GFP_KERNEL); + +#undef REG_STRUCT +#define REG_STRUCT hwseq_reg + hwseq_reg_init(); + + if (hws) { + hws->ctx = ctx; + hws->regs = &hwseq_reg; + hws->shifts = &hwseq_shift; + hws->masks = &hwseq_mask; + } + return hws; +} +static const struct resource_create_funcs res_create_funcs = { + .read_dce_straps = read_dce_straps, + .create_audio = dcn321_create_audio, + .create_stream_encoder = dcn321_stream_encoder_create, + .create_hpo_dp_stream_encoder = dcn321_hpo_dp_stream_encoder_create, + .create_hpo_dp_link_encoder = dcn321_hpo_dp_link_encoder_create, + .create_hwseq = dcn321_hwseq_create, +}; + +static void dcn321_resource_destruct(struct dcn321_resource_pool *pool) +{ + unsigned int i; + + for (i = 0; i < pool->base.stream_enc_count; i++) { + if (pool->base.stream_enc[i] != NULL) { + if (pool->base.stream_enc[i]->vpg != NULL) { + kfree(DCN30_VPG_FROM_VPG(pool->base.stream_enc[i]->vpg)); + pool->base.stream_enc[i]->vpg = NULL; + } + if (pool->base.stream_enc[i]->afmt != NULL) { + kfree(DCN30_AFMT_FROM_AFMT(pool->base.stream_enc[i]->afmt)); + pool->base.stream_enc[i]->afmt = NULL; + } + kfree(DCN10STRENC_FROM_STRENC(pool->base.stream_enc[i])); + pool->base.stream_enc[i] = NULL; + } + } + + for (i = 0; i < pool->base.hpo_dp_stream_enc_count; i++) { + if (pool->base.hpo_dp_stream_enc[i] != NULL) { + if (pool->base.hpo_dp_stream_enc[i]->vpg != NULL) { + kfree(DCN30_VPG_FROM_VPG(pool->base.hpo_dp_stream_enc[i]->vpg)); + pool->base.hpo_dp_stream_enc[i]->vpg = NULL; + } + if (pool->base.hpo_dp_stream_enc[i]->apg != NULL) { + kfree(DCN31_APG_FROM_APG(pool->base.hpo_dp_stream_enc[i]->apg)); + pool->base.hpo_dp_stream_enc[i]->apg = NULL; + } + kfree(DCN3_1_HPO_DP_STREAM_ENC_FROM_HPO_STREAM_ENC(pool->base.hpo_dp_stream_enc[i])); + pool->base.hpo_dp_stream_enc[i] = NULL; + } + } + + for (i = 0; i < pool->base.hpo_dp_link_enc_count; i++) { + if (pool->base.hpo_dp_link_enc[i] != NULL) { + kfree(DCN3_1_HPO_DP_LINK_ENC_FROM_HPO_LINK_ENC(pool->base.hpo_dp_link_enc[i])); + pool->base.hpo_dp_link_enc[i] = NULL; + } + } + + for (i = 0; i < pool->base.res_cap->num_dsc; i++) { + if (pool->base.dscs[i] != NULL) + dcn20_dsc_destroy(&pool->base.dscs[i]); + } + + if (pool->base.mpc != NULL) { + kfree(TO_DCN20_MPC(pool->base.mpc)); + pool->base.mpc = NULL; + } + if (pool->base.hubbub != NULL) { + kfree(TO_DCN20_HUBBUB(pool->base.hubbub)); + pool->base.hubbub = NULL; + } + for (i = 0; i < pool->base.pipe_count; i++) { + if (pool->base.dpps[i] != NULL) + dcn321_dpp_destroy(&pool->base.dpps[i]); + + if (pool->base.ipps[i] != NULL) + pool->base.ipps[i]->funcs->ipp_destroy(&pool->base.ipps[i]); + + if (pool->base.hubps[i] != NULL) { + kfree(TO_DCN20_HUBP(pool->base.hubps[i])); + pool->base.hubps[i] = NULL; + } + + if (pool->base.irqs != NULL) + dal_irq_service_destroy(&pool->base.irqs); + } + + for (i = 0; i < pool->base.res_cap->num_ddc; i++) { + if (pool->base.engines[i] != NULL) + dce110_engine_destroy(&pool->base.engines[i]); + if (pool->base.hw_i2cs[i] != NULL) { + kfree(pool->base.hw_i2cs[i]); + pool->base.hw_i2cs[i] = NULL; + } + if (pool->base.sw_i2cs[i] != NULL) { + kfree(pool->base.sw_i2cs[i]); + pool->base.sw_i2cs[i] = NULL; + } + } + + for (i = 0; i < pool->base.res_cap->num_opp; i++) { + if (pool->base.opps[i] != NULL) + pool->base.opps[i]->funcs->opp_destroy(&pool->base.opps[i]); + } + + for (i = 0; i < pool->base.res_cap->num_timing_generator; i++) { + if (pool->base.timing_generators[i] != NULL) { + kfree(DCN10TG_FROM_TG(pool->base.timing_generators[i])); + pool->base.timing_generators[i] = NULL; + } + } + + for (i = 0; i < pool->base.res_cap->num_dwb; i++) { + if (pool->base.dwbc[i] != NULL) { + kfree(TO_DCN30_DWBC(pool->base.dwbc[i])); + pool->base.dwbc[i] = NULL; + } + if (pool->base.mcif_wb[i] != NULL) { + kfree(TO_DCN30_MMHUBBUB(pool->base.mcif_wb[i])); + pool->base.mcif_wb[i] = NULL; + } + } + + for (i = 0; i < pool->base.audio_count; i++) { + if (pool->base.audios[i]) + dce_aud_destroy(&pool->base.audios[i]); + } + + for (i = 0; i < pool->base.clk_src_count; i++) { + if (pool->base.clock_sources[i] != NULL) { + dcn20_clock_source_destroy(&pool->base.clock_sources[i]); + pool->base.clock_sources[i] = NULL; + } + } + + for (i = 0; i < pool->base.res_cap->num_mpc_3dlut; i++) { + if (pool->base.mpc_lut[i] != NULL) { + dc_3dlut_func_release(pool->base.mpc_lut[i]); + pool->base.mpc_lut[i] = NULL; + } + if (pool->base.mpc_shaper[i] != NULL) { + dc_transfer_func_release(pool->base.mpc_shaper[i]); + pool->base.mpc_shaper[i] = NULL; + } + } + + if (pool->base.dp_clock_source != NULL) { + dcn20_clock_source_destroy(&pool->base.dp_clock_source); + pool->base.dp_clock_source = NULL; + } + + for (i = 0; i < pool->base.res_cap->num_timing_generator; i++) { + if (pool->base.multiple_abms[i] != NULL) + dce_abm_destroy(&pool->base.multiple_abms[i]); + } + + if (pool->base.psr != NULL) + dmub_psr_destroy(&pool->base.psr); + + if (pool->base.dccg != NULL) + dcn_dccg_destroy(&pool->base.dccg); + + if (pool->base.oem_device != NULL) { + struct dc *dc = pool->base.oem_device->ctx->dc; + + dc->link_srv->destroy_ddc_service(&pool->base.oem_device); + } +} + + +static bool dcn321_dwbc_create(struct dc_context *ctx, struct resource_pool *pool) +{ + int i; + uint32_t dwb_count = pool->res_cap->num_dwb; + + for (i = 0; i < dwb_count; i++) { + struct dcn30_dwbc *dwbc30 = kzalloc(sizeof(struct dcn30_dwbc), + GFP_KERNEL); + + if (!dwbc30) { + dm_error("DC: failed to create dwbc30!\n"); + return false; + } + +#undef REG_STRUCT +#define REG_STRUCT dwbc30_regs + dwbc_regs_dcn3_init(0); + + dcn30_dwbc_construct(dwbc30, ctx, + &dwbc30_regs[i], + &dwbc30_shift, + &dwbc30_mask, + i); + + pool->dwbc[i] = &dwbc30->base; + } + return true; +} + +static bool dcn321_mmhubbub_create(struct dc_context *ctx, struct resource_pool *pool) +{ + int i; + uint32_t dwb_count = pool->res_cap->num_dwb; + + for (i = 0; i < dwb_count; i++) { + struct dcn30_mmhubbub *mcif_wb30 = kzalloc(sizeof(struct dcn30_mmhubbub), + GFP_KERNEL); + + if (!mcif_wb30) { + dm_error("DC: failed to create mcif_wb30!\n"); + return false; + } + +#undef REG_STRUCT +#define REG_STRUCT mcif_wb30_regs + mcif_wb_regs_dcn3_init(0); + + dcn32_mmhubbub_construct(mcif_wb30, ctx, + &mcif_wb30_regs[i], + &mcif_wb30_shift, + &mcif_wb30_mask, + i); + + pool->mcif_wb[i] = &mcif_wb30->base; + } + return true; +} + +static struct display_stream_compressor *dcn321_dsc_create( + struct dc_context *ctx, uint32_t inst) +{ + struct dcn20_dsc *dsc = + kzalloc(sizeof(struct dcn20_dsc), GFP_KERNEL); + + if (!dsc) { + BREAK_TO_DEBUGGER(); + return NULL; + } + +#undef REG_STRUCT +#define REG_STRUCT dsc_regs + dsc_regsDCN20_init(0), + dsc_regsDCN20_init(1), + dsc_regsDCN20_init(2), + dsc_regsDCN20_init(3); + + dsc2_construct(dsc, ctx, inst, &dsc_regs[inst], &dsc_shift, &dsc_mask); + + dsc->max_image_width = 6016; + + return &dsc->base; +} + +static void dcn321_destroy_resource_pool(struct resource_pool **pool) +{ + struct dcn321_resource_pool *dcn321_pool = TO_DCN321_RES_POOL(*pool); + + dcn321_resource_destruct(dcn321_pool); + kfree(dcn321_pool); + *pool = NULL; +} + +static struct dc_cap_funcs cap_funcs = { + .get_dcc_compression_cap = dcn20_get_dcc_compression_cap, + .get_subvp_en = dcn32_subvp_in_use, +}; + +static void dcn321_update_bw_bounding_box(struct dc *dc, struct clk_bw_params *bw_params) +{ + DC_FP_START(); + dcn321_update_bw_bounding_box_fpu(dc, bw_params); + DC_FP_END(); +} + +static struct resource_funcs dcn321_res_pool_funcs = { + .destroy = dcn321_destroy_resource_pool, + .link_enc_create = dcn321_link_encoder_create, + .link_enc_create_minimal = NULL, + .panel_cntl_create = dcn32_panel_cntl_create, + .validate_bandwidth = dcn32_validate_bandwidth, + .calculate_wm_and_dlg = dcn32_calculate_wm_and_dlg, + .populate_dml_pipes = dcn32_populate_dml_pipes_from_context, + .acquire_free_pipe_as_secondary_dpp_pipe = dcn32_acquire_free_pipe_as_secondary_dpp_pipe, + .acquire_free_pipe_as_secondary_opp_head = dcn32_acquire_free_pipe_as_secondary_opp_head, + .release_pipe = dcn20_release_pipe, + .add_stream_to_ctx = dcn30_add_stream_to_ctx, + .add_dsc_to_stream_resource = dcn20_add_dsc_to_stream_resource, + .remove_stream_from_ctx = dcn20_remove_stream_from_ctx, + .populate_dml_writeback_from_context = dcn30_populate_dml_writeback_from_context, + .set_mcif_arb_params = dcn30_set_mcif_arb_params, + .find_first_free_match_stream_enc_for_link = dcn10_find_first_free_match_stream_enc_for_link, + .acquire_post_bldn_3dlut = dcn32_acquire_post_bldn_3dlut, + .release_post_bldn_3dlut = dcn32_release_post_bldn_3dlut, + .update_bw_bounding_box = dcn321_update_bw_bounding_box, + .patch_unknown_plane_state = dcn20_patch_unknown_plane_state, + .update_soc_for_wm_a = dcn30_update_soc_for_wm_a, + .add_phantom_pipes = dcn32_add_phantom_pipes, + .remove_phantom_pipes = dcn32_remove_phantom_pipes, + .retain_phantom_pipes = dcn32_retain_phantom_pipes, + .save_mall_state = dcn32_save_mall_state, + .restore_mall_state = dcn32_restore_mall_state, +}; + +static uint32_t read_pipe_fuses(struct dc_context *ctx) +{ + uint32_t value = REG_READ(CC_DC_PIPE_DIS); + /* DCN321 support max 4 pipes */ + value = value & 0xf; + return value; +} + + +static bool dcn321_resource_construct( + uint8_t num_virtual_links, + struct dc *dc, + struct dcn321_resource_pool *pool) +{ + int i, j; + struct dc_context *ctx = dc->ctx; + struct irq_service_init_data init_data; + struct ddc_service_init_data ddc_init_data = {0}; + uint32_t pipe_fuses = 0; + uint32_t num_pipes = 4; + +#undef REG_STRUCT +#define REG_STRUCT bios_regs + bios_regs_init(); + +#undef REG_STRUCT +#define REG_STRUCT clk_src_regs + clk_src_regs_init(0, A), + clk_src_regs_init(1, B), + clk_src_regs_init(2, C), + clk_src_regs_init(3, D), + clk_src_regs_init(4, E); + +#undef REG_STRUCT +#define REG_STRUCT abm_regs + abm_regs_init(0), + abm_regs_init(1), + abm_regs_init(2), + abm_regs_init(3); + +#undef REG_STRUCT +#define REG_STRUCT dccg_regs + dccg_regs_init(); + + + ctx->dc_bios->regs = &bios_regs; + + pool->base.res_cap = &res_cap_dcn321; + /* max number of pipes for ASIC before checking for pipe fuses */ + num_pipes = pool->base.res_cap->num_timing_generator; + pipe_fuses = read_pipe_fuses(ctx); + + for (i = 0; i < pool->base.res_cap->num_timing_generator; i++) + if (pipe_fuses & 1 << i) + num_pipes--; + + if (pipe_fuses & 1) + ASSERT(0); //Unexpected - Pipe 0 should always be fully functional! + + if (pipe_fuses & CC_DC_PIPE_DIS__DC_FULL_DIS_MASK) + ASSERT(0); //Entire DCN is harvested! + + /* within dml lib, initial value is hard coded, if ASIC pipe is fused, the + * value will be changed, update max_num_dpp and max_num_otg for dml. + */ + dcn3_21_ip.max_num_dpp = num_pipes; + dcn3_21_ip.max_num_otg = num_pipes; + + pool->base.funcs = &dcn321_res_pool_funcs; + + /************************************************* + * Resource + asic cap harcoding * + *************************************************/ + pool->base.underlay_pipe_index = NO_UNDERLAY_PIPE; + pool->base.timing_generator_count = num_pipes; + pool->base.pipe_count = num_pipes; + pool->base.mpcc_count = num_pipes; + dc->caps.max_downscale_ratio = 600; + dc->caps.i2c_speed_in_khz = 100; + dc->caps.i2c_speed_in_khz_hdcp = 100; /*1.4 w/a applied by default*/ + /* TODO: Bring max cursor size back to 256 after subvp cursor corruption is fixed*/ + dc->caps.max_cursor_size = 64; + dc->caps.min_horizontal_blanking_period = 80; + dc->caps.dmdata_alloc_size = 2048; + dc->caps.mall_size_per_mem_channel = 4; + dc->caps.mall_size_total = 0; + dc->caps.cursor_cache_size = dc->caps.max_cursor_size * dc->caps.max_cursor_size * 8; + dc->caps.cache_line_size = 64; + dc->caps.cache_num_ways = 16; + + /* Calculate the available MALL space */ + dc->caps.max_cab_allocation_bytes = dcn32_calc_num_avail_chans_for_mall( + dc, dc->ctx->dc_bios->vram_info.num_chans) * + dc->caps.mall_size_per_mem_channel * 1024 * 1024; + dc->caps.mall_size_total = dc->caps.max_cab_allocation_bytes; + + dc->caps.subvp_fw_processing_delay_us = 15; + dc->caps.subvp_drr_max_vblank_margin_us = 40; + dc->caps.subvp_prefetch_end_to_mall_start_us = 15; + dc->caps.subvp_swath_height_margin_lines = 16; + dc->caps.subvp_pstate_allow_width_us = 20; + dc->caps.subvp_vertical_int_margin_us = 30; + dc->caps.subvp_drr_vblank_start_margin_us = 100; // 100us margin + dc->caps.max_slave_planes = 2; + dc->caps.max_slave_yuv_planes = 2; + dc->caps.max_slave_rgb_planes = 2; + dc->caps.post_blend_color_processing = true; + dc->caps.force_dp_tps4_for_cp2520 = true; + dc->caps.dp_hpo = true; + dc->caps.dp_hdmi21_pcon_support = true; + dc->caps.edp_dsc_support = true; + dc->caps.extended_aux_timeout_support = true; + dc->caps.dmcub_support = true; + dc->caps.max_v_total = (1 << 15) - 1; + + /* Color pipeline capabilities */ + dc->caps.color.dpp.dcn_arch = 1; + dc->caps.color.dpp.input_lut_shared = 0; + dc->caps.color.dpp.icsc = 1; + dc->caps.color.dpp.dgam_ram = 0; // must use gamma_corr + dc->caps.color.dpp.dgam_rom_caps.srgb = 1; + dc->caps.color.dpp.dgam_rom_caps.bt2020 = 1; + dc->caps.color.dpp.dgam_rom_caps.gamma2_2 = 1; + dc->caps.color.dpp.dgam_rom_caps.pq = 1; + dc->caps.color.dpp.dgam_rom_caps.hlg = 1; + dc->caps.color.dpp.post_csc = 1; + dc->caps.color.dpp.gamma_corr = 1; + dc->caps.color.dpp.dgam_rom_for_yuv = 0; + + dc->caps.color.dpp.hw_3d_lut = 1; + dc->caps.color.dpp.ogam_ram = 1; + // no OGAM ROM on DCN2 and later ASICs + dc->caps.color.dpp.ogam_rom_caps.srgb = 0; + dc->caps.color.dpp.ogam_rom_caps.bt2020 = 0; + dc->caps.color.dpp.ogam_rom_caps.gamma2_2 = 0; + dc->caps.color.dpp.ogam_rom_caps.pq = 0; + dc->caps.color.dpp.ogam_rom_caps.hlg = 0; + dc->caps.color.dpp.ocsc = 0; + + dc->caps.color.mpc.gamut_remap = 1; + dc->caps.color.mpc.num_3dluts = pool->base.res_cap->num_mpc_3dlut; //4, configurable to be before or after BLND in MPCC + dc->caps.color.mpc.ogam_ram = 1; + dc->caps.color.mpc.ogam_rom_caps.srgb = 0; + dc->caps.color.mpc.ogam_rom_caps.bt2020 = 0; + dc->caps.color.mpc.ogam_rom_caps.gamma2_2 = 0; + dc->caps.color.mpc.ogam_rom_caps.pq = 0; + dc->caps.color.mpc.ogam_rom_caps.hlg = 0; + dc->caps.color.mpc.ocsc = 1; + + dc->config.dc_mode_clk_limit_support = true; + /* read VBIOS LTTPR caps */ + { + if (ctx->dc_bios->funcs->get_lttpr_caps) { + enum bp_result bp_query_result; + uint8_t is_vbios_lttpr_enable = 0; + + bp_query_result = ctx->dc_bios->funcs->get_lttpr_caps(ctx->dc_bios, &is_vbios_lttpr_enable); + dc->caps.vbios_lttpr_enable = (bp_query_result == BP_RESULT_OK) && !!is_vbios_lttpr_enable; + } + + /* interop bit is implicit */ + { + dc->caps.vbios_lttpr_aware = true; + } + } + + if (dc->ctx->dce_environment == DCE_ENV_PRODUCTION_DRV) + dc->debug = debug_defaults_drv; + + // Init the vm_helper + if (dc->vm_helper) + vm_helper_init(dc->vm_helper, 16); + + /************************************************* + * Create resources * + *************************************************/ + + /* Clock Sources for Pixel Clock*/ + pool->base.clock_sources[DCN321_CLK_SRC_PLL0] = + dcn321_clock_source_create(ctx, ctx->dc_bios, + CLOCK_SOURCE_COMBO_PHY_PLL0, + &clk_src_regs[0], false); + pool->base.clock_sources[DCN321_CLK_SRC_PLL1] = + dcn321_clock_source_create(ctx, ctx->dc_bios, + CLOCK_SOURCE_COMBO_PHY_PLL1, + &clk_src_regs[1], false); + pool->base.clock_sources[DCN321_CLK_SRC_PLL2] = + dcn321_clock_source_create(ctx, ctx->dc_bios, + CLOCK_SOURCE_COMBO_PHY_PLL2, + &clk_src_regs[2], false); + pool->base.clock_sources[DCN321_CLK_SRC_PLL3] = + dcn321_clock_source_create(ctx, ctx->dc_bios, + CLOCK_SOURCE_COMBO_PHY_PLL3, + &clk_src_regs[3], false); + pool->base.clock_sources[DCN321_CLK_SRC_PLL4] = + dcn321_clock_source_create(ctx, ctx->dc_bios, + CLOCK_SOURCE_COMBO_PHY_PLL4, + &clk_src_regs[4], false); + + pool->base.clk_src_count = DCN321_CLK_SRC_TOTAL; + + /* todo: not reuse phy_pll registers */ + pool->base.dp_clock_source = + dcn321_clock_source_create(ctx, ctx->dc_bios, + CLOCK_SOURCE_ID_DP_DTO, + &clk_src_regs[0], true); + + for (i = 0; i < pool->base.clk_src_count; i++) { + if (pool->base.clock_sources[i] == NULL) { + dm_error("DC: failed to create clock sources!\n"); + BREAK_TO_DEBUGGER(); + goto create_fail; + } + } + + /* DCCG */ + pool->base.dccg = dccg32_create(ctx, &dccg_regs, &dccg_shift, &dccg_mask); + if (pool->base.dccg == NULL) { + dm_error("DC: failed to create dccg!\n"); + BREAK_TO_DEBUGGER(); + goto create_fail; + } + + /* DML */ + dml_init_instance(&dc->dml, &dcn3_21_soc, &dcn3_21_ip, DML_PROJECT_DCN32); + + /* IRQ Service */ + init_data.ctx = dc->ctx; + pool->base.irqs = dal_irq_service_dcn32_create(&init_data); + if (!pool->base.irqs) + goto create_fail; + + /* HUBBUB */ + pool->base.hubbub = dcn321_hubbub_create(ctx); + if (pool->base.hubbub == NULL) { + BREAK_TO_DEBUGGER(); + dm_error("DC: failed to create hubbub!\n"); + goto create_fail; + } + + /* HUBPs, DPPs, OPPs, TGs, ABMs */ + for (i = 0, j = 0; i < pool->base.res_cap->num_timing_generator; i++) { + + /* if pipe is disabled, skip instance of HW pipe, + * i.e, skip ASIC register instance + */ + if (pipe_fuses & 1 << i) + continue; + + pool->base.hubps[j] = dcn321_hubp_create(ctx, i); + if (pool->base.hubps[j] == NULL) { + BREAK_TO_DEBUGGER(); + dm_error( + "DC: failed to create hubps!\n"); + goto create_fail; + } + + pool->base.dpps[j] = dcn321_dpp_create(ctx, i); + if (pool->base.dpps[j] == NULL) { + BREAK_TO_DEBUGGER(); + dm_error( + "DC: failed to create dpps!\n"); + goto create_fail; + } + + pool->base.opps[j] = dcn321_opp_create(ctx, i); + if (pool->base.opps[j] == NULL) { + BREAK_TO_DEBUGGER(); + dm_error( + "DC: failed to create output pixel processor!\n"); + goto create_fail; + } + + pool->base.timing_generators[j] = dcn321_timing_generator_create( + ctx, i); + if (pool->base.timing_generators[j] == NULL) { + BREAK_TO_DEBUGGER(); + dm_error("DC: failed to create tg!\n"); + goto create_fail; + } + + pool->base.multiple_abms[j] = dmub_abm_create(ctx, + &abm_regs[i], + &abm_shift, + &abm_mask); + if (pool->base.multiple_abms[j] == NULL) { + dm_error("DC: failed to create abm for pipe %d!\n", i); + BREAK_TO_DEBUGGER(); + goto create_fail; + } + + /* index for resource pool arrays for next valid pipe */ + j++; + } + + /* PSR */ + pool->base.psr = dmub_psr_create(ctx); + if (pool->base.psr == NULL) { + dm_error("DC: failed to create psr obj!\n"); + BREAK_TO_DEBUGGER(); + goto create_fail; + } + + /* MPCCs */ + pool->base.mpc = dcn321_mpc_create(ctx, pool->base.res_cap->num_timing_generator, pool->base.res_cap->num_mpc_3dlut); + if (pool->base.mpc == NULL) { + BREAK_TO_DEBUGGER(); + dm_error("DC: failed to create mpc!\n"); + goto create_fail; + } + + /* DSCs */ + for (i = 0; i < pool->base.res_cap->num_dsc; i++) { + pool->base.dscs[i] = dcn321_dsc_create(ctx, i); + if (pool->base.dscs[i] == NULL) { + BREAK_TO_DEBUGGER(); + dm_error("DC: failed to create display stream compressor %d!\n", i); + goto create_fail; + } + } + + /* DWB */ + if (!dcn321_dwbc_create(ctx, &pool->base)) { + BREAK_TO_DEBUGGER(); + dm_error("DC: failed to create dwbc!\n"); + goto create_fail; + } + + /* MMHUBBUB */ + if (!dcn321_mmhubbub_create(ctx, &pool->base)) { + BREAK_TO_DEBUGGER(); + dm_error("DC: failed to create mcif_wb!\n"); + goto create_fail; + } + + /* AUX and I2C */ + for (i = 0; i < pool->base.res_cap->num_ddc; i++) { + pool->base.engines[i] = dcn321_aux_engine_create(ctx, i); + if (pool->base.engines[i] == NULL) { + BREAK_TO_DEBUGGER(); + dm_error( + "DC:failed to create aux engine!!\n"); + goto create_fail; + } + pool->base.hw_i2cs[i] = dcn321_i2c_hw_create(ctx, i); + if (pool->base.hw_i2cs[i] == NULL) { + BREAK_TO_DEBUGGER(); + dm_error( + "DC:failed to create hw i2c!!\n"); + goto create_fail; + } + pool->base.sw_i2cs[i] = NULL; + } + + /* Audio, HWSeq, Stream Encoders including HPO and virtual, MPC 3D LUTs */ + if (!resource_construct(num_virtual_links, dc, &pool->base, + &res_create_funcs)) + goto create_fail; + + /* HW Sequencer init functions and Plane caps */ + dcn32_hw_sequencer_init_functions(dc); + + dc->caps.max_planes = pool->base.pipe_count; + + for (i = 0; i < dc->caps.max_planes; ++i) + dc->caps.planes[i] = plane_cap; + + dc->cap_funcs = cap_funcs; + + if (dc->ctx->dc_bios->fw_info.oem_i2c_present) { + ddc_init_data.ctx = dc->ctx; + ddc_init_data.link = NULL; + ddc_init_data.id.id = dc->ctx->dc_bios->fw_info.oem_i2c_obj_id; + ddc_init_data.id.enum_id = 0; + ddc_init_data.id.type = OBJECT_TYPE_GENERIC; + pool->base.oem_device = dc->link_srv->create_ddc_service(&ddc_init_data); + } else { + pool->base.oem_device = NULL; + } + + dc->dml2_options.dcn_pipe_count = pool->base.pipe_count; + dc->dml2_options.use_native_pstate_optimization = false; + dc->dml2_options.use_native_soc_bb_construction = true; + dc->dml2_options.minimize_dispclk_using_odm = true; + + dc->dml2_options.callbacks.dc = dc; + dc->dml2_options.callbacks.build_scaling_params = &resource_build_scaling_params; + dc->dml2_options.callbacks.can_support_mclk_switch_using_fw_based_vblank_stretch = &dcn30_can_support_mclk_switch_using_fw_based_vblank_stretch; + dc->dml2_options.callbacks.acquire_secondary_pipe_for_mpc_odm = &dc_resource_acquire_secondary_pipe_for_mpc_odm_legacy; + dc->dml2_options.callbacks.update_pipes_for_stream_with_slice_count = &resource_update_pipes_for_stream_with_slice_count; + dc->dml2_options.callbacks.update_pipes_for_plane_with_slice_count = &resource_update_pipes_for_plane_with_slice_count; + dc->dml2_options.callbacks.get_mpc_slice_index = &resource_get_mpc_slice_index; + dc->dml2_options.callbacks.get_odm_slice_index = &resource_get_odm_slice_index; + dc->dml2_options.callbacks.get_opp_head = &resource_get_opp_head; + + dc->dml2_options.svp_pstate.callbacks.dc = dc; + dc->dml2_options.svp_pstate.callbacks.add_plane_to_context = &dc_add_plane_to_context; + dc->dml2_options.svp_pstate.callbacks.add_stream_to_ctx = &dc_add_stream_to_ctx; + dc->dml2_options.svp_pstate.callbacks.build_scaling_params = &resource_build_scaling_params; + dc->dml2_options.svp_pstate.callbacks.create_plane = &dc_create_plane_state; + dc->dml2_options.svp_pstate.callbacks.remove_plane_from_context = &dc_remove_plane_from_context; + dc->dml2_options.svp_pstate.callbacks.remove_stream_from_ctx = &dc_remove_stream_from_ctx; + dc->dml2_options.svp_pstate.callbacks.create_stream_for_sink = &dc_create_stream_for_sink; + dc->dml2_options.svp_pstate.callbacks.plane_state_release = &dc_plane_state_release; + dc->dml2_options.svp_pstate.callbacks.stream_release = &dc_stream_release; + dc->dml2_options.svp_pstate.callbacks.release_dsc = &dcn20_release_dsc; + + dc->dml2_options.svp_pstate.subvp_fw_processing_delay_us = dc->caps.subvp_fw_processing_delay_us; + dc->dml2_options.svp_pstate.subvp_prefetch_end_to_mall_start_us = dc->caps.subvp_prefetch_end_to_mall_start_us; + dc->dml2_options.svp_pstate.subvp_pstate_allow_width_us = dc->caps.subvp_pstate_allow_width_us; + dc->dml2_options.svp_pstate.subvp_swath_height_margin_lines = dc->caps.subvp_swath_height_margin_lines; + + dc->dml2_options.svp_pstate.force_disable_subvp = dc->debug.force_disable_subvp; + dc->dml2_options.svp_pstate.force_enable_subvp = dc->debug.force_subvp_mclk_switch; + + dc->dml2_options.mall_cfg.cache_line_size_bytes = dc->caps.cache_line_size; + dc->dml2_options.mall_cfg.cache_num_ways = dc->caps.cache_num_ways; + dc->dml2_options.mall_cfg.max_cab_allocation_bytes = dc->caps.max_cab_allocation_bytes; + dc->dml2_options.mall_cfg.mblk_height_4bpe_pixels = DCN3_2_MBLK_HEIGHT_4BPE; + dc->dml2_options.mall_cfg.mblk_height_8bpe_pixels = DCN3_2_MBLK_HEIGHT_8BPE; + dc->dml2_options.mall_cfg.mblk_size_bytes = DCN3_2_MALL_MBLK_SIZE_BYTES; + dc->dml2_options.mall_cfg.mblk_width_pixels = DCN3_2_MBLK_WIDTH; + + dc->dml2_options.max_segments_per_hubp = 18; + dc->dml2_options.det_segment_size = DCN3_2_DET_SEG_SIZE; + + return true; + +create_fail: + + dcn321_resource_destruct(pool); + + return false; +} + +struct resource_pool *dcn321_create_resource_pool( + const struct dc_init_data *init_data, + struct dc *dc) +{ + struct dcn321_resource_pool *pool = + kzalloc(sizeof(struct dcn321_resource_pool), GFP_KERNEL); + + if (!pool) + return NULL; + + if (dcn321_resource_construct(init_data->num_virtual_links, dc, pool)) + return &pool->base; + + BREAK_TO_DEBUGGER(); + kfree(pool); + return NULL; +} diff --git a/drivers/gpu/drm/amd/display/dc/resource/dcn321/dcn321_resource.h b/drivers/gpu/drm/amd/display/dc/resource/dcn321/dcn321_resource.h new file mode 100644 index 000000000000..82cbf009f2d3 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/resource/dcn321/dcn321_resource.h @@ -0,0 +1,45 @@ +/* + * Copyright 2020 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 _DCN321_RESOURCE_H_ +#define _DCN321_RESOURCE_H_ + +#include "core_types.h" + +#define TO_DCN321_RES_POOL(pool)\ + container_of(pool, struct dcn321_resource_pool, base) + +extern struct _vcs_dpi_ip_params_st dcn3_21_ip; +extern struct _vcs_dpi_soc_bounding_box_st dcn3_21_soc; + +struct dcn321_resource_pool { + struct resource_pool base; +}; + +struct resource_pool *dcn321_create_resource_pool( + const struct dc_init_data *init_data, + struct dc *dc); + +#endif /* _DCN321_RESOURCE_H_ */ diff --git a/drivers/gpu/drm/amd/display/dc/resource/dcn35/dcn35_resource.c b/drivers/gpu/drm/amd/display/dc/resource/dcn35/dcn35_resource.c new file mode 100644 index 000000000000..a4027bf053c5 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/resource/dcn35/dcn35_resource.c @@ -0,0 +1,2141 @@ +/* SPDX-License-Identifier: MIT */ +/* + * Copyright 2023 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 "dm_services.h" +#include "dc.h" + +#include "dcn31/dcn31_init.h" +#include "dcn35/dcn35_init.h" + +#include "resource.h" +#include "include/irq_service_interface.h" +#include "dcn35_resource.h" +#include "dml2/dml2_wrapper.h" + +#include "dcn20/dcn20_resource.h" +#include "dcn30/dcn30_resource.h" +#include "dcn31/dcn31_resource.h" +#include "dcn32/dcn32_resource.h" + +#include "dcn10/dcn10_ipp.h" +#include "dcn30/dcn30_hubbub.h" +#include "dcn31/dcn31_hubbub.h" +#include "dcn35/dcn35_hubbub.h" +#include "dcn32/dcn32_mpc.h" +#include "dcn35/dcn35_hubp.h" +#include "irq/dcn35/irq_service_dcn35.h" +#include "dcn35/dcn35_dpp.h" +#include "dcn35/dcn35_optc.h" +#include "dcn20/dcn20_hwseq.h" +#include "dcn30/dcn30_hwseq.h" +#include "dce110/dce110_hwseq.h" +#include "dcn35/dcn35_opp.h" +#include "dcn35/dcn35_dsc.h" +#include "dcn30/dcn30_vpg.h" +#include "dcn30/dcn30_afmt.h" +#include "dcn31/dcn31_dio_link_encoder.h" +#include "dcn35/dcn35_dio_stream_encoder.h" +#include "dcn31/dcn31_hpo_dp_stream_encoder.h" +#include "dcn31/dcn31_hpo_dp_link_encoder.h" +#include "dcn32/dcn32_hpo_dp_link_encoder.h" +#include "link.h" +#include "dcn31/dcn31_apg.h" +#include "dcn32/dcn32_dio_link_encoder.h" +#include "dcn31/dcn31_vpg.h" +#include "dcn31/dcn31_afmt.h" +#include "dce/dce_clock_source.h" +#include "dce/dce_audio.h" +#include "dce/dce_hwseq.h" +#include "clk_mgr.h" +#include "virtual/virtual_stream_encoder.h" +#include "dce110/dce110_resource.h" +#include "dml/display_mode_vba.h" +#include "dcn35/dcn35_dccg.h" +#include "dcn35/dcn35_pg_cntl.h" +#include "dcn10/dcn10_resource.h" +#include "dcn31/dcn31_panel_cntl.h" +#include "dcn35/dcn35_hwseq.h" +#include "dcn35/dcn35_dio_link_encoder.h" +#include "dml/dcn31/dcn31_fpu.h" /*todo*/ +#include "dml/dcn35/dcn35_fpu.h" +#include "dcn35/dcn35_dwb.h" +#include "dcn35/dcn35_mmhubbub.h" + +#include "dcn/dcn_3_5_0_offset.h" +#include "dcn/dcn_3_5_0_sh_mask.h" +#include "nbio/nbio_7_11_0_offset.h" +#include "mmhub/mmhub_3_3_0_offset.h" +#include "mmhub/mmhub_3_3_0_sh_mask.h" + +#define DSCC0_DSCC_CONFIG0__ICH_RESET_AT_END_OF_LINE__SHIFT 0x0 +#define DSCC0_DSCC_CONFIG0__ICH_RESET_AT_END_OF_LINE_MASK 0x0000000FL + +#include "reg_helper.h" +#include "dce/dmub_abm.h" +#include "dce/dmub_psr.h" +#include "dce/dce_aux.h" +#include "dce/dce_i2c.h" +#include "dml/dcn31/display_mode_vba_31.h" /*temp*/ +#include "vm_helper.h" +#include "dcn20/dcn20_vmid.h" + +#include "link_enc_cfg.h" +#define DC_LOGGER_INIT(logger) + +enum dcn35_clk_src_array_id { + DCN35_CLK_SRC_PLL0, + DCN35_CLK_SRC_PLL1, + DCN35_CLK_SRC_PLL2, + DCN35_CLK_SRC_PLL3, + DCN35_CLK_SRC_PLL4, + DCN35_CLK_SRC_TOTAL +}; + +/* begin ********************* + * macros to expend register list macro defined in HW object header file + */ + +/* DCN */ +/* TODO awful hack. fixup dcn20_dwb.h */ +#undef BASE_INNER +#define BASE_INNER(seg) ctx->dcn_reg_offsets[seg] + +#define BASE(seg) BASE_INNER(seg) + +#define SR(reg_name)\ + REG_STRUCT.reg_name = BASE(reg ## reg_name ## _BASE_IDX) + \ + reg ## reg_name + +#define SR_ARR(reg_name, id) \ + REG_STRUCT[id].reg_name = BASE(reg##reg_name##_BASE_IDX) + reg##reg_name + +#define SR_ARR_INIT(reg_name, id, value) \ + REG_STRUCT[id].reg_name = value + +#define SRI(reg_name, block, id)\ + REG_STRUCT.reg_name = BASE(reg ## block ## id ## _ ## reg_name ## _BASE_IDX) + \ + reg ## block ## id ## _ ## reg_name + +#define SRI_ARR(reg_name, block, id)\ + REG_STRUCT[id].reg_name = BASE(reg ## block ## id ## _ ## reg_name ## _BASE_IDX) + \ + reg ## block ## id ## _ ## reg_name + +#define SR_ARR_I2C(reg_name, id) \ + REG_STRUCT[id-1].reg_name = BASE(reg##reg_name##_BASE_IDX) + reg##reg_name + +#define SRI_ARR_I2C(reg_name, block, id)\ + REG_STRUCT[id-1].reg_name = BASE(reg ## block ## id ## _ ## reg_name ## _BASE_IDX) + \ + reg ## block ## id ## _ ## reg_name + +#define SRI_ARR_ALPHABET(reg_name, block, index, id)\ + REG_STRUCT[index].reg_name = BASE(reg ## block ## id ## _ ## reg_name ## _BASE_IDX) + \ + reg ## block ## id ## _ ## reg_name + +#define SRI2(reg_name, block, id)\ + .reg_name = BASE(reg ## reg_name ## _BASE_IDX) + \ + reg ## reg_name + +#define SRI2_ARR(reg_name, block, id)\ + REG_STRUCT[id].reg_name = BASE(reg ## reg_name ## _BASE_IDX) + \ + reg ## reg_name + +#define SRIR(var_name, reg_name, block, id)\ + .var_name = BASE(reg ## block ## id ## _ ## reg_name ## _BASE_IDX) + \ + reg ## block ## id ## _ ## reg_name + +#define SRII(reg_name, block, id)\ + REG_STRUCT.reg_name[id] = BASE(reg ## block ## id ## _ ## reg_name ## _BASE_IDX) + \ + reg ## block ## id ## _ ## reg_name + +#define SRII_ARR_2(reg_name, block, id, inst)\ + REG_STRUCT[inst].reg_name[id] = BASE(reg ## block ## id ## _ ## reg_name ## _BASE_IDX) + \ + reg ## block ## id ## _ ## reg_name + +#define SRII_MPC_RMU(reg_name, block, id)\ + .RMU##_##reg_name[id] = BASE(reg ## block ## id ## _ ## reg_name ## _BASE_IDX) + \ + reg ## block ## id ## _ ## reg_name + +#define SRII_DWB(reg_name, temp_name, block, id)\ + REG_STRUCT.reg_name[id] = BASE(reg ## block ## id ## _ ## temp_name ## _BASE_IDX) + \ + reg ## block ## id ## _ ## temp_name + +#define SF_DWB2(reg_name, block, id, field_name, post_fix) \ + .field_name = reg_name ## __ ## field_name ## post_fix + +#define DCCG_SRII(reg_name, block, id)\ + REG_STRUCT.block ## _ ## reg_name[id] = BASE(reg ## block ## id ## _ ## reg_name ## _BASE_IDX) + \ + reg ## block ## id ## _ ## reg_name + +#define VUPDATE_SRII(reg_name, block, id)\ + REG_STRUCT.reg_name[id] = BASE(reg ## reg_name ## _ ## block ## id ## _BASE_IDX) + \ + reg ## reg_name ## _ ## block ## id + +/* NBIO */ +#define NBIO_BASE_INNER(seg) ctx->nbio_reg_offsets[seg] + +#define NBIO_BASE(seg) \ + NBIO_BASE_INNER(seg) + +#define NBIO_SR(reg_name)\ + REG_STRUCT.reg_name = NBIO_BASE(regBIF_BX2_ ## reg_name ## _BASE_IDX) + \ + regBIF_BX2_ ## reg_name + +#define NBIO_SR_ARR(reg_name, id)\ + REG_STRUCT[id].reg_name = NBIO_BASE(regBIF_BX2_ ## reg_name ## _BASE_IDX) + \ + regBIF_BX2_ ## reg_name + +#define bios_regs_init() \ + ( \ + NBIO_SR(BIOS_SCRATCH_3),\ + NBIO_SR(BIOS_SCRATCH_6)\ + ) + +static struct bios_registers bios_regs; + +#define clk_src_regs_init(index, pllid)\ + CS_COMMON_REG_LIST_DCN3_0_RI(index, pllid) + +static struct dce110_clk_src_regs clk_src_regs[5]; + +static const struct dce110_clk_src_shift cs_shift = { + CS_COMMON_MASK_SH_LIST_DCN3_1_4(__SHIFT) +}; + +static const struct dce110_clk_src_mask cs_mask = { + CS_COMMON_MASK_SH_LIST_DCN3_1_4(_MASK) +}; + +#define abm_regs_init(id)\ + ABM_DCN32_REG_LIST_RI(id) + +static struct dce_abm_registers abm_regs[4]; + +static const struct dce_abm_shift abm_shift = { + ABM_MASK_SH_LIST_DCN35(__SHIFT) +}; + +static const struct dce_abm_mask abm_mask = { + ABM_MASK_SH_LIST_DCN35(_MASK) +}; + +#define audio_regs_init(id)\ + AUD_COMMON_REG_LIST_RI(id) + +static struct dce_audio_registers audio_regs[7]; + + +#define DCE120_AUD_COMMON_MASK_SH_LIST(mask_sh)\ + SF(AZF0ENDPOINT0_AZALIA_F0_CODEC_ENDPOINT_INDEX, AZALIA_ENDPOINT_REG_INDEX, mask_sh),\ + SF(AZF0ENDPOINT0_AZALIA_F0_CODEC_ENDPOINT_DATA, AZALIA_ENDPOINT_REG_DATA, mask_sh),\ + AUD_COMMON_MASK_SH_LIST_BASE(mask_sh) + +static const struct dce_audio_shift audio_shift = { + DCE120_AUD_COMMON_MASK_SH_LIST(__SHIFT) +}; + +static const struct dce_audio_mask audio_mask = { + DCE120_AUD_COMMON_MASK_SH_LIST(_MASK) +}; + +#define vpg_regs_init(id)\ + VPG_DCN31_REG_LIST_RI(id) + +static struct dcn31_vpg_registers vpg_regs[10]; + +static const struct dcn31_vpg_shift vpg_shift = { + DCN31_VPG_MASK_SH_LIST(__SHIFT) +}; + +static const struct dcn31_vpg_mask vpg_mask = { + DCN31_VPG_MASK_SH_LIST(_MASK) +}; + +#define afmt_regs_init(id)\ + AFMT_DCN31_REG_LIST_RI(id) + +static struct dcn31_afmt_registers afmt_regs[6]; + +static const struct dcn31_afmt_shift afmt_shift = { + DCN31_AFMT_MASK_SH_LIST(__SHIFT) +}; + +static const struct dcn31_afmt_mask afmt_mask = { + DCN31_AFMT_MASK_SH_LIST(_MASK) +}; + +#define apg_regs_init(id)\ + APG_DCN31_REG_LIST_RI(id) + +static struct dcn31_apg_registers apg_regs[4]; + +static const struct dcn31_apg_shift apg_shift = { + DCN31_APG_MASK_SH_LIST(__SHIFT) +}; + +static const struct dcn31_apg_mask apg_mask = { + DCN31_APG_MASK_SH_LIST(_MASK) +}; + +#define stream_enc_regs_init(id)\ + SE_DCN35_REG_LIST_RI(id) + +static struct dcn10_stream_enc_registers stream_enc_regs[5]; + +static const struct dcn10_stream_encoder_shift se_shift = { + SE_COMMON_MASK_SH_LIST_DCN35(__SHIFT) +}; + +static const struct dcn10_stream_encoder_mask se_mask = { + SE_COMMON_MASK_SH_LIST_DCN35(_MASK) +}; + +#define aux_regs_init(id)\ + DCN2_AUX_REG_LIST_RI(id) + +static struct dcn10_link_enc_aux_registers link_enc_aux_regs[5]; + +#define hpd_regs_init(id)\ + HPD_REG_LIST_RI(id) + +static struct dcn10_link_enc_hpd_registers link_enc_hpd_regs[5]; + + +static const struct dce110_aux_registers_shift aux_shift = { + DCN_AUX_MASK_SH_LIST(__SHIFT) +}; + +static const struct dce110_aux_registers_mask aux_mask = { + DCN_AUX_MASK_SH_LIST(_MASK) +}; + +#define link_regs_init(id, phyid)\ + ( \ + LE_DCN35_REG_LIST_RI(id), \ + UNIPHY_DCN2_REG_LIST_RI(id, phyid)\ + ) + +static struct dcn10_link_enc_registers link_enc_regs[5]; + +static const struct dcn10_link_enc_shift le_shift = { + LINK_ENCODER_MASK_SH_LIST_DCN35(__SHIFT), \ + //DPCS_DCN31_MASK_SH_LIST(__SHIFT) +}; + +static const struct dcn10_link_enc_mask le_mask = { + LINK_ENCODER_MASK_SH_LIST_DCN35(_MASK), \ + //DPCS_DCN31_MASK_SH_LIST(_MASK) +}; + +#define hpo_dp_stream_encoder_reg_init(id)\ + DCN3_1_HPO_DP_STREAM_ENC_REG_LIST_RI(id) + +static struct dcn31_hpo_dp_stream_encoder_registers hpo_dp_stream_enc_regs[4]; + +static const struct dcn31_hpo_dp_stream_encoder_shift hpo_dp_se_shift = { + DCN3_1_HPO_DP_STREAM_ENC_MASK_SH_LIST(__SHIFT) +}; + +static const struct dcn31_hpo_dp_stream_encoder_mask hpo_dp_se_mask = { + DCN3_1_HPO_DP_STREAM_ENC_MASK_SH_LIST(_MASK) +}; + +#define hpo_dp_link_encoder_reg_init(id)\ + DCN3_1_HPO_DP_LINK_ENC_REG_LIST_RI(id) + /*DCN3_1_RDPCSTX_REG_LIST(0),*/ + /*DCN3_1_RDPCSTX_REG_LIST(1),*/ + /*DCN3_1_RDPCSTX_REG_LIST(2),*/ + /*DCN3_1_RDPCSTX_REG_LIST(3),*/ + +static struct dcn31_hpo_dp_link_encoder_registers hpo_dp_link_enc_regs[2]; + +static const struct dcn31_hpo_dp_link_encoder_shift hpo_dp_le_shift = { + DCN3_1_HPO_DP_LINK_ENC_COMMON_MASK_SH_LIST(__SHIFT) +}; + +static const struct dcn31_hpo_dp_link_encoder_mask hpo_dp_le_mask = { + DCN3_1_HPO_DP_LINK_ENC_COMMON_MASK_SH_LIST(_MASK) +}; + +#define dpp_regs_init(id)\ + DPP_REG_LIST_DCN35_RI(id) + +static struct dcn3_dpp_registers dpp_regs[4]; + +static const struct dcn35_dpp_shift tf_shift = { + DPP_REG_LIST_SH_MASK_DCN35(__SHIFT) +}; + +static const struct dcn35_dpp_mask tf_mask = { + DPP_REG_LIST_SH_MASK_DCN35(_MASK) +}; + +#define opp_regs_init(id)\ + OPP_REG_LIST_DCN35_RI(id) + +static struct dcn35_opp_registers opp_regs[4]; + +static const struct dcn35_opp_shift opp_shift = { + OPP_MASK_SH_LIST_DCN35(__SHIFT) +}; + +static const struct dcn35_opp_mask opp_mask = { + OPP_MASK_SH_LIST_DCN35(_MASK) +}; + +#define aux_engine_regs_init(id)\ + ( \ + AUX_COMMON_REG_LIST0_RI(id), \ + SR_ARR_INIT(AUXN_IMPCAL, id, 0), \ + SR_ARR_INIT(AUXP_IMPCAL, id, 0), \ + SR_ARR_INIT(AUX_RESET_MASK, id, DP_AUX0_AUX_CONTROL__AUX_RESET_MASK) \ + ) + +static struct dce110_aux_registers aux_engine_regs[5]; + +#define dwbc_regs_dcn3_init(id)\ + DWBC_COMMON_REG_LIST_DCN30_RI(id) + +static struct dcn30_dwbc_registers dwbc35_regs[1]; + +static const struct dcn35_dwbc_shift dwbc35_shift = { + DWBC_COMMON_MASK_SH_LIST_DCN35(__SHIFT) +}; + +static const struct dcn35_dwbc_mask dwbc35_mask = { + DWBC_COMMON_MASK_SH_LIST_DCN35(_MASK) +}; + +#define mcif_wb_regs_dcn3_init(id)\ + MCIF_WB_COMMON_REG_LIST_DCN3_5_RI(id) + +static struct dcn35_mmhubbub_registers mcif_wb35_regs[1]; + +static const struct dcn35_mmhubbub_shift mcif_wb35_shift = { + MCIF_WB_COMMON_MASK_SH_LIST_DCN3_5(__SHIFT) +}; + +static const struct dcn35_mmhubbub_mask mcif_wb35_mask = { + MCIF_WB_COMMON_MASK_SH_LIST_DCN3_5(_MASK) +}; + +#define dsc_regsDCN35_init(id)\ + DSC_REG_LIST_DCN20_RI(id) + +static struct dcn20_dsc_registers dsc_regs[4]; + +static const struct dcn35_dsc_shift dsc_shift = { + DSC_REG_LIST_SH_MASK_DCN35(__SHIFT) +}; + +static const struct dcn35_dsc_mask dsc_mask = { + DSC_REG_LIST_SH_MASK_DCN35(_MASK) +}; + +static struct dcn30_mpc_registers mpc_regs; + +#define dcn_mpc_regs_init() \ + MPC_REG_LIST_DCN3_2_RI(0),\ + MPC_REG_LIST_DCN3_2_RI(1),\ + MPC_REG_LIST_DCN3_2_RI(2),\ + MPC_REG_LIST_DCN3_2_RI(3),\ + MPC_OUT_MUX_REG_LIST_DCN3_0_RI(0),\ + MPC_OUT_MUX_REG_LIST_DCN3_0_RI(1),\ + MPC_OUT_MUX_REG_LIST_DCN3_0_RI(2),\ + MPC_OUT_MUX_REG_LIST_DCN3_0_RI(3),\ + MPC_DWB_MUX_REG_LIST_DCN3_0_RI(0) + +static const struct dcn30_mpc_shift mpc_shift = { + MPC_COMMON_MASK_SH_LIST_DCN32(__SHIFT) +}; + +static const struct dcn30_mpc_mask mpc_mask = { + MPC_COMMON_MASK_SH_LIST_DCN32(_MASK) +}; + +#define optc_regs_init(id)\ + OPTC_COMMON_REG_LIST_DCN3_5_RI(id) + +static struct dcn_optc_registers optc_regs[4]; + +static const struct dcn_optc_shift optc_shift = { + OPTC_COMMON_MASK_SH_LIST_DCN3_5(__SHIFT) +}; + +static const struct dcn_optc_mask optc_mask = { + OPTC_COMMON_MASK_SH_LIST_DCN3_5(_MASK) +}; + +#define hubp_regs_init(id)\ + HUBP_REG_LIST_DCN30_RI(id) + +static struct dcn_hubp2_registers hubp_regs[4]; + + +static const struct dcn35_hubp2_shift hubp_shift = { + HUBP_MASK_SH_LIST_DCN35(__SHIFT) +}; + +static const struct dcn35_hubp2_mask hubp_mask = { + HUBP_MASK_SH_LIST_DCN35(_MASK) +}; + +static struct dcn_hubbub_registers hubbub_reg; + +#define hubbub_reg_init()\ + HUBBUB_REG_LIST_DCN35(0) + +static const struct dcn_hubbub_shift hubbub_shift = { + HUBBUB_MASK_SH_LIST_DCN35(__SHIFT) +}; + +static const struct dcn_hubbub_mask hubbub_mask = { + HUBBUB_MASK_SH_LIST_DCN35(_MASK) +}; + +static struct dccg_registers dccg_regs; + +#define dccg_regs_init()\ + DCCG_REG_LIST_DCN35() + +static const struct dccg_shift dccg_shift = { + DCCG_MASK_SH_LIST_DCN35(__SHIFT) +}; + +static const struct dccg_mask dccg_mask = { + DCCG_MASK_SH_LIST_DCN35(_MASK) +}; + +static struct pg_cntl_registers pg_cntl_regs; + +#define pg_cntl_dcn35_regs_init() \ + PG_CNTL_REG_LIST_DCN35() + +static const struct pg_cntl_shift pg_cntl_shift = { + PG_CNTL_MASK_SH_LIST_DCN35(__SHIFT) +}; + +static const struct pg_cntl_mask pg_cntl_mask = { + PG_CNTL_MASK_SH_LIST_DCN35(_MASK) +}; + +#define SRII2(reg_name_pre, reg_name_post, id)\ + .reg_name_pre ## _ ## reg_name_post[id] = BASE(reg ## reg_name_pre \ + ## id ## _ ## reg_name_post ## _BASE_IDX) + \ + reg ## reg_name_pre ## id ## _ ## reg_name_post + +static struct dce_hwseq_registers hwseq_reg; + +#define hwseq_reg_init()\ + HWSEQ_DCN35_REG_LIST() + +#define HWSEQ_DCN35_MASK_SH_LIST(mask_sh)\ + HWSEQ_DCN_MASK_SH_LIST(mask_sh), \ + HWS_SF(, DCHUBBUB_GLOBAL_TIMER_CNTL, DCHUBBUB_GLOBAL_TIMER_REFDIV, mask_sh), \ + HWS_SF(, DCHUBBUB_ARB_HOSTVM_CNTL, DISABLE_HOSTVM_FORCE_ALLOW_PSTATE, mask_sh), \ + HWS_SF(, DOMAIN0_PG_CONFIG, DOMAIN_POWER_FORCEON, mask_sh), \ + HWS_SF(, DOMAIN0_PG_CONFIG, DOMAIN_POWER_GATE, mask_sh), \ + HWS_SF(, DOMAIN1_PG_CONFIG, DOMAIN_POWER_FORCEON, mask_sh), \ + HWS_SF(, DOMAIN1_PG_CONFIG, DOMAIN_POWER_GATE, mask_sh), \ + HWS_SF(, DOMAIN2_PG_CONFIG, DOMAIN_POWER_FORCEON, mask_sh), \ + HWS_SF(, DOMAIN2_PG_CONFIG, DOMAIN_POWER_GATE, mask_sh), \ + HWS_SF(, DOMAIN3_PG_CONFIG, DOMAIN_POWER_FORCEON, mask_sh), \ + HWS_SF(, DOMAIN3_PG_CONFIG, DOMAIN_POWER_GATE, mask_sh), \ + HWS_SF(, DOMAIN16_PG_CONFIG, DOMAIN_POWER_FORCEON, mask_sh), \ + HWS_SF(, DOMAIN16_PG_CONFIG, DOMAIN_POWER_GATE, mask_sh), \ + HWS_SF(, DOMAIN17_PG_CONFIG, DOMAIN_POWER_FORCEON, mask_sh), \ + HWS_SF(, DOMAIN17_PG_CONFIG, DOMAIN_POWER_GATE, mask_sh), \ + HWS_SF(, DOMAIN18_PG_CONFIG, DOMAIN_POWER_FORCEON, mask_sh), \ + HWS_SF(, DOMAIN18_PG_CONFIG, DOMAIN_POWER_GATE, mask_sh), \ + HWS_SF(, DOMAIN19_PG_CONFIG, DOMAIN_POWER_FORCEON, mask_sh), \ + HWS_SF(, DOMAIN19_PG_CONFIG, DOMAIN_POWER_GATE, mask_sh), \ + HWS_SF(, DOMAIN22_PG_CONFIG, DOMAIN_POWER_FORCEON, mask_sh), \ + HWS_SF(, DOMAIN22_PG_CONFIG, DOMAIN_POWER_GATE, mask_sh), \ + HWS_SF(, DOMAIN23_PG_CONFIG, DOMAIN_POWER_FORCEON, mask_sh), \ + HWS_SF(, DOMAIN23_PG_CONFIG, DOMAIN_POWER_GATE, mask_sh), \ + HWS_SF(, DOMAIN24_PG_CONFIG, DOMAIN_POWER_FORCEON, mask_sh), \ + HWS_SF(, DOMAIN24_PG_CONFIG, DOMAIN_POWER_GATE, mask_sh), \ + HWS_SF(, DOMAIN25_PG_CONFIG, DOMAIN_POWER_FORCEON, mask_sh), \ + HWS_SF(, DOMAIN25_PG_CONFIG, DOMAIN_POWER_GATE, mask_sh), \ + HWS_SF(, DOMAIN0_PG_STATUS, DOMAIN_PGFSM_PWR_STATUS, mask_sh), \ + HWS_SF(, DOMAIN1_PG_STATUS, DOMAIN_PGFSM_PWR_STATUS, mask_sh), \ + HWS_SF(, DOMAIN2_PG_STATUS, DOMAIN_PGFSM_PWR_STATUS, mask_sh), \ + HWS_SF(, DOMAIN3_PG_STATUS, DOMAIN_PGFSM_PWR_STATUS, mask_sh), \ + HWS_SF(, DOMAIN16_PG_STATUS, DOMAIN_PGFSM_PWR_STATUS, mask_sh), \ + HWS_SF(, DOMAIN17_PG_STATUS, DOMAIN_PGFSM_PWR_STATUS, mask_sh), \ + HWS_SF(, DOMAIN18_PG_STATUS, DOMAIN_PGFSM_PWR_STATUS, mask_sh), \ + HWS_SF(, DOMAIN19_PG_STATUS, DOMAIN_PGFSM_PWR_STATUS, mask_sh), \ + HWS_SF(, DOMAIN22_PG_STATUS, DOMAIN_PGFSM_PWR_STATUS, mask_sh), \ + HWS_SF(, DOMAIN23_PG_STATUS, DOMAIN_PGFSM_PWR_STATUS, mask_sh), \ + HWS_SF(, DOMAIN24_PG_STATUS, DOMAIN_PGFSM_PWR_STATUS, mask_sh), \ + HWS_SF(, DOMAIN25_PG_STATUS, DOMAIN_PGFSM_PWR_STATUS, mask_sh), \ + HWS_SF(, DC_IP_REQUEST_CNTL, IP_REQUEST_EN, mask_sh), \ + HWS_SF(, AZALIA_AUDIO_DTO, AZALIA_AUDIO_DTO_MODULE, mask_sh), \ + HWS_SF(, HPO_TOP_CLOCK_CONTROL, HPO_HDMISTREAMCLK_G_GATE_DIS, mask_sh), \ + HWS_SF(, ODM_MEM_PWR_CTRL3, ODM_MEM_UNASSIGNED_PWR_MODE, mask_sh), \ + HWS_SF(, ODM_MEM_PWR_CTRL3, ODM_MEM_VBLANK_PWR_MODE, mask_sh), \ + HWS_SF(, DIO_MEM_PWR_CTRL, I2C_LIGHT_SLEEP_FORCE, mask_sh), \ + HWS_SF(, HPO_TOP_HW_CONTROL, HPO_IO_EN, mask_sh),\ + HWS_SF(, DMU_CLK_CNTL, DISPCLK_R_DMU_GATE_DIS, mask_sh),\ + HWS_SF(, DMU_CLK_CNTL, DISPCLK_G_RBBMIF_GATE_DIS, mask_sh),\ + HWS_SF(, DMU_CLK_CNTL, RBBMIF_FGCG_REP_DIS, mask_sh),\ + HWS_SF(, DMU_CLK_CNTL, DPREFCLK_ALLOW_DS_CLKSTOP, mask_sh),\ + HWS_SF(, DMU_CLK_CNTL, DISPCLK_ALLOW_DS_CLKSTOP, mask_sh),\ + HWS_SF(, DMU_CLK_CNTL, DPPCLK_ALLOW_DS_CLKSTOP, mask_sh),\ + HWS_SF(, DMU_CLK_CNTL, DTBCLK_ALLOW_DS_CLKSTOP, mask_sh),\ + HWS_SF(, DMU_CLK_CNTL, DCFCLK_ALLOW_DS_CLKSTOP, mask_sh),\ + HWS_SF(, DMU_CLK_CNTL, DPIACLK_ALLOW_DS_CLKSTOP, mask_sh),\ + HWS_SF(, DMU_CLK_CNTL, LONO_FGCG_REP_DIS, mask_sh),\ + HWS_SF(, DMU_CLK_CNTL, LONO_DISPCLK_GATE_DISABLE, mask_sh),\ + HWS_SF(, DMU_CLK_CNTL, LONO_SOCCLK_GATE_DISABLE, mask_sh),\ + HWS_SF(, DMU_CLK_CNTL, LONO_DMCUBCLK_GATE_DISABLE, mask_sh),\ + HWS_SF(, DCCG_GATE_DISABLE_CNTL2, SYMCLKA_FE_GATE_DISABLE, mask_sh), \ + HWS_SF(, DCCG_GATE_DISABLE_CNTL2, SYMCLKB_FE_GATE_DISABLE, mask_sh), \ + HWS_SF(, DCCG_GATE_DISABLE_CNTL2, SYMCLKC_FE_GATE_DISABLE, mask_sh), \ + HWS_SF(, DCCG_GATE_DISABLE_CNTL2, SYMCLKD_FE_GATE_DISABLE, mask_sh), \ + HWS_SF(, DCCG_GATE_DISABLE_CNTL2, SYMCLKE_FE_GATE_DISABLE, mask_sh), \ + HWS_SF(, DCCG_GATE_DISABLE_CNTL2, HDMICHARCLK0_GATE_DISABLE, mask_sh), \ + HWS_SF(, DCCG_GATE_DISABLE_CNTL2, SYMCLKA_GATE_DISABLE, mask_sh), \ + HWS_SF(, DCCG_GATE_DISABLE_CNTL2, SYMCLKB_GATE_DISABLE, mask_sh), \ + HWS_SF(, DCCG_GATE_DISABLE_CNTL2, SYMCLKC_GATE_DISABLE, mask_sh), \ + HWS_SF(, DCCG_GATE_DISABLE_CNTL2, SYMCLKD_GATE_DISABLE, mask_sh), \ + HWS_SF(, DCCG_GATE_DISABLE_CNTL2, SYMCLKE_GATE_DISABLE, mask_sh), \ + HWS_SF(, DCCG_GATE_DISABLE_CNTL2, PHYASYMCLK_ROOT_GATE_DISABLE, mask_sh), \ + HWS_SF(, DCCG_GATE_DISABLE_CNTL2, PHYBSYMCLK_ROOT_GATE_DISABLE, mask_sh), \ + HWS_SF(, DCCG_GATE_DISABLE_CNTL2, PHYCSYMCLK_ROOT_GATE_DISABLE, mask_sh), \ + HWS_SF(, DCCG_GATE_DISABLE_CNTL2, PHYDSYMCLK_ROOT_GATE_DISABLE, mask_sh), \ + HWS_SF(, DCCG_GATE_DISABLE_CNTL2, PHYESYMCLK_ROOT_GATE_DISABLE, mask_sh) + +static const struct dce_hwseq_shift hwseq_shift = { + HWSEQ_DCN35_MASK_SH_LIST(__SHIFT) +}; + +static const struct dce_hwseq_mask hwseq_mask = { + HWSEQ_DCN35_MASK_SH_LIST(_MASK) +}; + +#define vmid_regs_init(id)\ + DCN20_VMID_REG_LIST_RI(id) + +static struct dcn_vmid_registers vmid_regs[16]; + +static const struct dcn20_vmid_shift vmid_shifts = { + DCN20_VMID_MASK_SH_LIST(__SHIFT) +}; + +static const struct dcn20_vmid_mask vmid_masks = { + DCN20_VMID_MASK_SH_LIST(_MASK) +}; + +static const struct resource_caps res_cap_dcn35 = { + .num_timing_generator = 4, + .num_opp = 4, + .num_video_plane = 4, + .num_audio = 5, + .num_stream_encoder = 5, + .num_dig_link_enc = 5, + .num_hpo_dp_stream_encoder = 4, + .num_hpo_dp_link_encoder = 2, + .num_pll = 4,/*1 c10 edp, 3xc20 combo PHY*/ + .num_dwb = 1, + .num_ddc = 5, + .num_vmid = 16, + .num_mpc_3dlut = 2, + .num_dsc = 4, +}; + +static const struct dc_plane_cap plane_cap = { + .type = DC_PLANE_TYPE_DCN_UNIVERSAL, + .per_pixel_alpha = true, + + .pixel_format_support = { + .argb8888 = true, + .nv12 = true, + .fp16 = true, + .p010 = true, + .ayuv = false, + }, + + .max_upscale_factor = { + .argb8888 = 16000, + .nv12 = 16000, + .fp16 = 16000 + }, + + // 6:1 downscaling ratio: 1000/6 = 166.666 + .max_downscale_factor = { + .argb8888 = 167, + .nv12 = 167, + .fp16 = 167 + }, + 64, + 64 +}; + +static const struct dc_debug_options debug_defaults_drv = { + .disable_dmcu = true, + .force_abm_enable = false, + .timing_trace = false, + .clock_trace = true, + .disable_pplib_clock_request = false, + .pipe_split_policy = MPC_SPLIT_AVOID, + .force_single_disp_pipe_split = false, + .disable_dcc = DCC_ENABLE, + .disable_dpp_power_gate = true, + .disable_hubp_power_gate = true, + .disable_clock_gate = true, + .disable_dsc_power_gate = true, + .vsr_support = true, + .performance_trace = false, + .max_downscale_src_width = 4096,/*upto true 4k*/ + .disable_pplib_wm_range = false, + .scl_reset_length10 = true, + .sanity_checks = false, + .underflow_assert_delay_us = 0xFFFFFFFF, + .dwb_fi_phase = -1, // -1 = disable, + .dmub_command_table = true, + .pstate_enabled = true, + .use_max_lb = true, + .enable_mem_low_power = { + .bits = { + .vga = false, + .i2c = true, + .dmcu = false, // This is previously known to cause hang on S3 cycles if enabled + .dscl = true, + .cm = true, + .mpc = true, + .optc = true, + .vpg = true, + .afmt = true, + } + }, + .root_clock_optimization = { + .bits = { + .dpp = true, + .dsc = true,/*dscclk and dsc pg*/ + .hdmistream = true, + .hdmichar = true, + .dpstream = true, + .symclk32_se = true, + .symclk32_le = true, + .symclk_fe = true, + .physymclk = true, + .dpiasymclk = true, + } + }, + .seamless_boot_odm_combine = DML_FAIL_SOURCE_PIXEL_FORMAT, + .enable_z9_disable_interface = true, /* Allow support for the PMFW interface for disable Z9*/ + .using_dml2 = true, + .support_eDP1_5 = true, + .enable_hpo_pg_support = false, + .enable_legacy_fast_update = true, + .enable_single_display_2to1_odm_policy = false, + .disable_idle_power_optimizations = true, + .dmcub_emulation = false, + .disable_boot_optimizations = false, + .disable_unbounded_requesting = false, + .disable_mem_low_power = false, + //must match enable_single_display_2to1_odm_policy to support dynamic ODM transitions + .enable_double_buffered_dsc_pg_support = true, + .enable_dp_dig_pixel_rate_div_policy = 1, + .disable_z10 = false, + .ignore_pg = true, + .psp_disabled_wa = true, + .ips2_eval_delay_us = 200, + .ips2_entry_delay_us = 400 +}; + +static const struct dc_panel_config panel_config_defaults = { + .psr = { + .disable_psr = false, + .disallow_psrsu = false, + }, + .ilr = { + .optimize_edp_link_rate = true, + }, +}; + +static void dcn35_dpp_destroy(struct dpp **dpp) +{ + kfree(TO_DCN20_DPP(*dpp)); + *dpp = NULL; +} + +static struct dpp *dcn35_dpp_create(struct dc_context *ctx, uint32_t inst) +{ + struct dcn3_dpp *dpp = kzalloc(sizeof(struct dcn3_dpp), GFP_KERNEL); + bool success = (dpp != NULL); + + if (!success) + return NULL; + +#undef REG_STRUCT +#define REG_STRUCT dpp_regs + dpp_regs_init(0), + dpp_regs_init(1), + dpp_regs_init(2), + dpp_regs_init(3); + + success = dpp35_construct(dpp, ctx, inst, &dpp_regs[inst], &tf_shift, + &tf_mask); + if (success) { + dpp35_set_fgcg( + dpp, + ctx->dc->debug.enable_fine_grain_clock_gating.bits.dpp); + return &dpp->base; + } + + BREAK_TO_DEBUGGER(); + kfree(dpp); + return NULL; +} + +static struct output_pixel_processor *dcn35_opp_create( + struct dc_context *ctx, uint32_t inst) +{ + struct dcn20_opp *opp = + kzalloc(sizeof(struct dcn20_opp), GFP_KERNEL); + + if (!opp) { + BREAK_TO_DEBUGGER(); + return NULL; + } + +#undef REG_STRUCT +#define REG_STRUCT opp_regs + opp_regs_init(0), + opp_regs_init(1), + opp_regs_init(2), + opp_regs_init(3); + + dcn35_opp_construct(opp, ctx, inst, + &opp_regs[inst], &opp_shift, &opp_mask); + + dcn35_opp_set_fgcg(opp, ctx->dc->debug.enable_fine_grain_clock_gating.bits.opp); + + return &opp->base; +} + +static struct dce_aux *dcn31_aux_engine_create( + struct dc_context *ctx, + uint32_t inst) +{ + struct aux_engine_dce110 *aux_engine = + kzalloc(sizeof(struct aux_engine_dce110), GFP_KERNEL); + + if (!aux_engine) + return NULL; + +#undef REG_STRUCT +#define REG_STRUCT aux_engine_regs + aux_engine_regs_init(0), + aux_engine_regs_init(1), + aux_engine_regs_init(2), + aux_engine_regs_init(3), + aux_engine_regs_init(4); + + dce110_aux_engine_construct(aux_engine, ctx, inst, + SW_AUX_TIMEOUT_PERIOD_MULTIPLIER * AUX_TIMEOUT_PERIOD, + &aux_engine_regs[inst], + &aux_mask, + &aux_shift, + ctx->dc->caps.extended_aux_timeout_support); + + return &aux_engine->base; +} + +#define i2c_inst_regs_init(id)\ + I2C_HW_ENGINE_COMMON_REG_LIST_DCN30_RI(id) + +static struct dce_i2c_registers i2c_hw_regs[5]; + +static const struct dce_i2c_shift i2c_shifts = { + I2C_COMMON_MASK_SH_LIST_DCN35(__SHIFT) +}; + +static const struct dce_i2c_mask i2c_masks = { + I2C_COMMON_MASK_SH_LIST_DCN35(_MASK) +}; + +/* ========================================================== */ + +/* + * DPIA index | Preferred Encoder | Host Router + * 0 | C | 0 + * 1 | First Available | 0 + * 2 | D | 1 + * 3 | First Available | 1 + */ +/* ========================================================== */ +static const enum engine_id dpia_to_preferred_enc_id_table[] = { + ENGINE_ID_DIGC, + ENGINE_ID_DIGC, + ENGINE_ID_DIGD, + ENGINE_ID_DIGD +}; + +static enum engine_id dcn35_get_preferred_eng_id_dpia(unsigned int dpia_index) +{ + return dpia_to_preferred_enc_id_table[dpia_index]; +} + +static struct dce_i2c_hw *dcn31_i2c_hw_create( + struct dc_context *ctx, + uint32_t inst) +{ + struct dce_i2c_hw *dce_i2c_hw = + kzalloc(sizeof(struct dce_i2c_hw), GFP_KERNEL); + + if (!dce_i2c_hw) + return NULL; + +#undef REG_STRUCT +#define REG_STRUCT i2c_hw_regs + i2c_inst_regs_init(1), + i2c_inst_regs_init(2), + i2c_inst_regs_init(3), + i2c_inst_regs_init(4), + i2c_inst_regs_init(5); + + dcn2_i2c_hw_construct(dce_i2c_hw, ctx, inst, + &i2c_hw_regs[inst], &i2c_shifts, &i2c_masks); + + return dce_i2c_hw; +} +static struct mpc *dcn35_mpc_create( + struct dc_context *ctx, + int num_mpcc, + int num_rmu) +{ + struct dcn30_mpc *mpc30 = kzalloc(sizeof(struct dcn30_mpc), GFP_KERNEL); + + if (!mpc30) + return NULL; + +#undef REG_STRUCT +#define REG_STRUCT mpc_regs + dcn_mpc_regs_init(); + + dcn32_mpc_construct(mpc30, ctx, + &mpc_regs, + &mpc_shift, + &mpc_mask, + num_mpcc, + num_rmu); + + return &mpc30->base; +} + +static struct hubbub *dcn35_hubbub_create(struct dc_context *ctx) +{ + int i; + + struct dcn20_hubbub *hubbub3 = kzalloc(sizeof(struct dcn20_hubbub), + GFP_KERNEL); + + if (!hubbub3) + return NULL; + +#undef REG_STRUCT +#define REG_STRUCT hubbub_reg + hubbub_reg_init(); + +#undef REG_STRUCT +#define REG_STRUCT vmid_regs + vmid_regs_init(0), + vmid_regs_init(1), + vmid_regs_init(2), + vmid_regs_init(3), + vmid_regs_init(4), + vmid_regs_init(5), + vmid_regs_init(6), + vmid_regs_init(7), + vmid_regs_init(8), + vmid_regs_init(9), + vmid_regs_init(10), + vmid_regs_init(11), + vmid_regs_init(12), + vmid_regs_init(13), + vmid_regs_init(14), + vmid_regs_init(15); + + hubbub35_construct(hubbub3, ctx, + &hubbub_reg, + &hubbub_shift, + &hubbub_mask, + 384,/*ctx->dc->dml.ip.det_buffer_size_kbytes,*/ + 8, /*ctx->dc->dml.ip.pixel_chunk_size_kbytes,*/ + 1792 /*ctx->dc->dml.ip.config_return_buffer_size_in_kbytes*/); + + + for (i = 0; i < res_cap_dcn35.num_vmid; i++) { + struct dcn20_vmid *vmid = &hubbub3->vmid[i]; + + vmid->ctx = ctx; + + vmid->regs = &vmid_regs[i]; + vmid->shifts = &vmid_shifts; + vmid->masks = &vmid_masks; + } + + return &hubbub3->base; +} + +static struct timing_generator *dcn35_timing_generator_create( + struct dc_context *ctx, + uint32_t instance) +{ + struct optc *tgn10 = + kzalloc(sizeof(struct optc), GFP_KERNEL); + + if (!tgn10) + return NULL; + +#undef REG_STRUCT +#define REG_STRUCT optc_regs + optc_regs_init(0), + optc_regs_init(1), + optc_regs_init(2), + optc_regs_init(3); + + tgn10->base.inst = instance; + tgn10->base.ctx = ctx; + + tgn10->tg_regs = &optc_regs[instance]; + tgn10->tg_shift = &optc_shift; + tgn10->tg_mask = &optc_mask; + + dcn35_timing_generator_init(tgn10); + + return &tgn10->base; +} + +static const struct encoder_feature_support link_enc_feature = { + .max_hdmi_deep_color = COLOR_DEPTH_121212, + .max_hdmi_pixel_clock = 600000, + .hdmi_ycbcr420_supported = true, + .dp_ycbcr420_supported = true, + .fec_supported = true, + .flags.bits.IS_HBR2_CAPABLE = true, + .flags.bits.IS_HBR3_CAPABLE = true, + .flags.bits.IS_TPS3_CAPABLE = true, + .flags.bits.IS_TPS4_CAPABLE = true +}; + +static struct link_encoder *dcn35_link_encoder_create( + struct dc_context *ctx, + const struct encoder_init_data *enc_init_data) +{ + struct dcn20_link_encoder *enc20 = + kzalloc(sizeof(struct dcn20_link_encoder), GFP_KERNEL); + + if (!enc20) + return NULL; + +#undef REG_STRUCT +#define REG_STRUCT link_enc_aux_regs + aux_regs_init(0), + aux_regs_init(1), + aux_regs_init(2), + aux_regs_init(3), + aux_regs_init(4); + +#undef REG_STRUCT +#define REG_STRUCT link_enc_hpd_regs + hpd_regs_init(0), + hpd_regs_init(1), + hpd_regs_init(2), + hpd_regs_init(3), + hpd_regs_init(4); + +#undef REG_STRUCT +#define REG_STRUCT link_enc_regs + link_regs_init(0, A), + link_regs_init(1, B), + link_regs_init(2, C), + link_regs_init(3, D), + link_regs_init(4, E); + + dcn35_link_encoder_construct(enc20, + enc_init_data, + &link_enc_feature, + &link_enc_regs[enc_init_data->transmitter], + &link_enc_aux_regs[enc_init_data->channel - 1], + &link_enc_hpd_regs[enc_init_data->hpd_source], + &le_shift, + &le_mask); + + return &enc20->enc10.base; +} + +/* Create a minimal link encoder object not associated with a particular + * physical connector. + * resource_funcs.link_enc_create_minimal + */ +static struct link_encoder *dcn31_link_enc_create_minimal( + struct dc_context *ctx, enum engine_id eng_id) +{ + struct dcn20_link_encoder *enc20; + + if ((eng_id - ENGINE_ID_DIGA) > ctx->dc->res_pool->res_cap->num_dig_link_enc) + return NULL; + + enc20 = kzalloc(sizeof(struct dcn20_link_encoder), GFP_KERNEL); + if (!enc20) + return NULL; + + dcn31_link_encoder_construct_minimal( + enc20, + ctx, + &link_enc_feature, + &link_enc_regs[eng_id - ENGINE_ID_DIGA], + eng_id); + + return &enc20->enc10.base; +} + +static struct panel_cntl *dcn31_panel_cntl_create(const struct panel_cntl_init_data *init_data) +{ + struct dcn31_panel_cntl *panel_cntl = + kzalloc(sizeof(struct dcn31_panel_cntl), GFP_KERNEL); + + if (!panel_cntl) + return NULL; + + dcn31_panel_cntl_construct(panel_cntl, init_data); + + return &panel_cntl->base; +} + +static void read_dce_straps( + struct dc_context *ctx, + struct resource_straps *straps) +{ + generic_reg_get(ctx, regDC_PINSTRAPS + BASE(regDC_PINSTRAPS_BASE_IDX), + FN(DC_PINSTRAPS, DC_PINSTRAPS_AUDIO), &straps->dc_pinstraps_audio); + +} + +static struct audio *dcn31_create_audio( + struct dc_context *ctx, unsigned int inst) +{ + +#undef REG_STRUCT +#define REG_STRUCT audio_regs + audio_regs_init(0), + audio_regs_init(1), + audio_regs_init(2), + audio_regs_init(3), + audio_regs_init(4); + audio_regs_init(5); + audio_regs_init(6); + + return dce_audio_create(ctx, inst, + &audio_regs[inst], &audio_shift, &audio_mask); +} + +static struct vpg *dcn31_vpg_create( + struct dc_context *ctx, + uint32_t inst) +{ + struct dcn31_vpg *vpg31 = kzalloc(sizeof(struct dcn31_vpg), GFP_KERNEL); + + if (!vpg31) + return NULL; + +#undef REG_STRUCT +#define REG_STRUCT vpg_regs + vpg_regs_init(0), + vpg_regs_init(1), + vpg_regs_init(2), + vpg_regs_init(3), + vpg_regs_init(4), + vpg_regs_init(5), + vpg_regs_init(6), + vpg_regs_init(7), + vpg_regs_init(8), + vpg_regs_init(9); + + vpg31_construct(vpg31, ctx, inst, + &vpg_regs[inst], + &vpg_shift, + &vpg_mask); + + return &vpg31->base; +} + +static struct afmt *dcn31_afmt_create( + struct dc_context *ctx, + uint32_t inst) +{ + struct dcn31_afmt *afmt31 = kzalloc(sizeof(struct dcn31_afmt), GFP_KERNEL); + + if (!afmt31) + return NULL; + +#undef REG_STRUCT +#define REG_STRUCT afmt_regs + afmt_regs_init(0), + afmt_regs_init(1), + afmt_regs_init(2), + afmt_regs_init(3), + afmt_regs_init(4), + afmt_regs_init(5); + + afmt31_construct(afmt31, ctx, inst, + &afmt_regs[inst], + &afmt_shift, + &afmt_mask); + + // Light sleep by default, no need to power down here + + return &afmt31->base; +} + +static struct apg *dcn31_apg_create( + struct dc_context *ctx, + uint32_t inst) +{ + struct dcn31_apg *apg31 = kzalloc(sizeof(struct dcn31_apg), GFP_KERNEL); + + if (!apg31) + return NULL; + +#undef REG_STRUCT +#define REG_STRUCT apg_regs + apg_regs_init(0), + apg_regs_init(1), + apg_regs_init(2), + apg_regs_init(3); + + apg31_construct(apg31, ctx, inst, + &apg_regs[inst], + &apg_shift, + &apg_mask); + + return &apg31->base; +} + +static struct stream_encoder *dcn35_stream_encoder_create( + enum engine_id eng_id, + struct dc_context *ctx) +{ + struct dcn10_stream_encoder *enc1; + struct vpg *vpg; + struct afmt *afmt; + int vpg_inst; + int afmt_inst; + + /* Mapping of VPG, AFMT, DME register blocks to DIO block instance */ + if (eng_id <= ENGINE_ID_DIGF) { + vpg_inst = eng_id; + afmt_inst = eng_id; + } else + return NULL; + + enc1 = kzalloc(sizeof(struct dcn10_stream_encoder), GFP_KERNEL); + vpg = dcn31_vpg_create(ctx, vpg_inst); + afmt = dcn31_afmt_create(ctx, afmt_inst); + + if (!enc1 || !vpg || !afmt) { + kfree(enc1); + kfree(vpg); + kfree(afmt); + return NULL; + } + +#undef REG_STRUCT +#define REG_STRUCT stream_enc_regs + stream_enc_regs_init(0), + stream_enc_regs_init(1), + stream_enc_regs_init(2), + stream_enc_regs_init(3), + stream_enc_regs_init(4); + + dcn35_dio_stream_encoder_construct(enc1, ctx, ctx->dc_bios, + eng_id, vpg, afmt, + &stream_enc_regs[eng_id], + &se_shift, &se_mask); + + return &enc1->base; +} + +static struct hpo_dp_stream_encoder *dcn31_hpo_dp_stream_encoder_create( + enum engine_id eng_id, + struct dc_context *ctx) +{ + struct dcn31_hpo_dp_stream_encoder *hpo_dp_enc31; + struct vpg *vpg; + struct apg *apg; + uint32_t hpo_dp_inst; + uint32_t vpg_inst; + uint32_t apg_inst; + + ASSERT((eng_id >= ENGINE_ID_HPO_DP_0) && (eng_id <= ENGINE_ID_HPO_DP_3)); + hpo_dp_inst = eng_id - ENGINE_ID_HPO_DP_0; + + /* Mapping of VPG register blocks to HPO DP block instance: + * VPG[6] -> HPO_DP[0] + * VPG[7] -> HPO_DP[1] + * VPG[8] -> HPO_DP[2] + * VPG[9] -> HPO_DP[3] + */ + vpg_inst = hpo_dp_inst + 6; + + /* Mapping of APG register blocks to HPO DP block instance: + * APG[0] -> HPO_DP[0] + * APG[1] -> HPO_DP[1] + * APG[2] -> HPO_DP[2] + * APG[3] -> HPO_DP[3] + */ + apg_inst = hpo_dp_inst; + + /* allocate HPO stream encoder and create VPG sub-block */ + hpo_dp_enc31 = kzalloc(sizeof(struct dcn31_hpo_dp_stream_encoder), GFP_KERNEL); + vpg = dcn31_vpg_create(ctx, vpg_inst); + apg = dcn31_apg_create(ctx, apg_inst); + + if (!hpo_dp_enc31 || !vpg || !apg) { + kfree(hpo_dp_enc31); + kfree(vpg); + kfree(apg); + return NULL; + } + +#undef REG_STRUCT +#define REG_STRUCT hpo_dp_stream_enc_regs + hpo_dp_stream_encoder_reg_init(0), + hpo_dp_stream_encoder_reg_init(1), + hpo_dp_stream_encoder_reg_init(2), + hpo_dp_stream_encoder_reg_init(3); + + dcn31_hpo_dp_stream_encoder_construct(hpo_dp_enc31, ctx, ctx->dc_bios, + hpo_dp_inst, eng_id, vpg, apg, + &hpo_dp_stream_enc_regs[hpo_dp_inst], + &hpo_dp_se_shift, &hpo_dp_se_mask); + + return &hpo_dp_enc31->base; +} + +static struct hpo_dp_link_encoder *dcn31_hpo_dp_link_encoder_create( + uint8_t inst, + struct dc_context *ctx) +{ + struct dcn31_hpo_dp_link_encoder *hpo_dp_enc31; + + /* allocate HPO link encoder */ + hpo_dp_enc31 = kzalloc(sizeof(struct dcn31_hpo_dp_link_encoder), GFP_KERNEL); + +#undef REG_STRUCT +#define REG_STRUCT hpo_dp_link_enc_regs + hpo_dp_link_encoder_reg_init(0), + hpo_dp_link_encoder_reg_init(1); + + hpo_dp_link_encoder31_construct(hpo_dp_enc31, ctx, inst, + &hpo_dp_link_enc_regs[inst], + &hpo_dp_le_shift, &hpo_dp_le_mask); + + return &hpo_dp_enc31->base; +} + +static struct dce_hwseq *dcn35_hwseq_create( + struct dc_context *ctx) +{ + struct dce_hwseq *hws = kzalloc(sizeof(struct dce_hwseq), GFP_KERNEL); + +#undef REG_STRUCT +#define REG_STRUCT hwseq_reg + hwseq_reg_init(); + + if (hws) { + hws->ctx = ctx; + hws->regs = &hwseq_reg; + hws->shifts = &hwseq_shift; + hws->masks = &hwseq_mask; + } + return hws; +} +static const struct resource_create_funcs res_create_funcs = { + .read_dce_straps = read_dce_straps, + .create_audio = dcn31_create_audio, + .create_stream_encoder = dcn35_stream_encoder_create, + .create_hpo_dp_stream_encoder = dcn31_hpo_dp_stream_encoder_create, + .create_hpo_dp_link_encoder = dcn31_hpo_dp_link_encoder_create, + .create_hwseq = dcn35_hwseq_create, +}; + +static void dcn35_resource_destruct(struct dcn35_resource_pool *pool) +{ + unsigned int i; + + for (i = 0; i < pool->base.stream_enc_count; i++) { + if (pool->base.stream_enc[i] != NULL) { + if (pool->base.stream_enc[i]->vpg != NULL) { + kfree(DCN30_VPG_FROM_VPG(pool->base.stream_enc[i]->vpg)); + pool->base.stream_enc[i]->vpg = NULL; + } + if (pool->base.stream_enc[i]->afmt != NULL) { + kfree(DCN30_AFMT_FROM_AFMT(pool->base.stream_enc[i]->afmt)); + pool->base.stream_enc[i]->afmt = NULL; + } + kfree(DCN10STRENC_FROM_STRENC(pool->base.stream_enc[i])); + pool->base.stream_enc[i] = NULL; + } + } + + for (i = 0; i < pool->base.hpo_dp_stream_enc_count; i++) { + if (pool->base.hpo_dp_stream_enc[i] != NULL) { + if (pool->base.hpo_dp_stream_enc[i]->vpg != NULL) { + kfree(DCN30_VPG_FROM_VPG(pool->base.hpo_dp_stream_enc[i]->vpg)); + pool->base.hpo_dp_stream_enc[i]->vpg = NULL; + } + if (pool->base.hpo_dp_stream_enc[i]->apg != NULL) { + kfree(DCN31_APG_FROM_APG(pool->base.hpo_dp_stream_enc[i]->apg)); + pool->base.hpo_dp_stream_enc[i]->apg = NULL; + } + kfree(DCN3_1_HPO_DP_STREAM_ENC_FROM_HPO_STREAM_ENC(pool->base.hpo_dp_stream_enc[i])); + pool->base.hpo_dp_stream_enc[i] = NULL; + } + } + + for (i = 0; i < pool->base.hpo_dp_link_enc_count; i++) { + if (pool->base.hpo_dp_link_enc[i] != NULL) { + kfree(DCN3_1_HPO_DP_LINK_ENC_FROM_HPO_LINK_ENC(pool->base.hpo_dp_link_enc[i])); + pool->base.hpo_dp_link_enc[i] = NULL; + } + } + + for (i = 0; i < pool->base.res_cap->num_dsc; i++) { + if (pool->base.dscs[i] != NULL) + dcn20_dsc_destroy(&pool->base.dscs[i]); + } + + if (pool->base.mpc != NULL) { + kfree(TO_DCN20_MPC(pool->base.mpc)); + pool->base.mpc = NULL; + } + if (pool->base.hubbub != NULL) { + kfree(pool->base.hubbub); + pool->base.hubbub = NULL; + } + for (i = 0; i < pool->base.pipe_count; i++) { + if (pool->base.dpps[i] != NULL) + dcn35_dpp_destroy(&pool->base.dpps[i]); + + if (pool->base.ipps[i] != NULL) + pool->base.ipps[i]->funcs->ipp_destroy(&pool->base.ipps[i]); + + if (pool->base.hubps[i] != NULL) { + kfree(TO_DCN20_HUBP(pool->base.hubps[i])); + pool->base.hubps[i] = NULL; + } + + if (pool->base.irqs != NULL) { + dal_irq_service_destroy(&pool->base.irqs); + } + } + + for (i = 0; i < pool->base.res_cap->num_ddc; i++) { + if (pool->base.engines[i] != NULL) + dce110_engine_destroy(&pool->base.engines[i]); + if (pool->base.hw_i2cs[i] != NULL) { + kfree(pool->base.hw_i2cs[i]); + pool->base.hw_i2cs[i] = NULL; + } + if (pool->base.sw_i2cs[i] != NULL) { + kfree(pool->base.sw_i2cs[i]); + pool->base.sw_i2cs[i] = NULL; + } + } + + for (i = 0; i < pool->base.res_cap->num_opp; i++) { + if (pool->base.opps[i] != NULL) + pool->base.opps[i]->funcs->opp_destroy(&pool->base.opps[i]); + } + + for (i = 0; i < pool->base.res_cap->num_timing_generator; i++) { + if (pool->base.timing_generators[i] != NULL) { + kfree(DCN10TG_FROM_TG(pool->base.timing_generators[i])); + pool->base.timing_generators[i] = NULL; + } + } + + for (i = 0; i < pool->base.res_cap->num_dwb; i++) { + if (pool->base.dwbc[i] != NULL) { + kfree(TO_DCN30_DWBC(pool->base.dwbc[i])); + pool->base.dwbc[i] = NULL; + } + if (pool->base.mcif_wb[i] != NULL) { + kfree(TO_DCN30_MMHUBBUB(pool->base.mcif_wb[i])); + pool->base.mcif_wb[i] = NULL; + } + } + + for (i = 0; i < pool->base.audio_count; i++) { + if (pool->base.audios[i]) + dce_aud_destroy(&pool->base.audios[i]); + } + + for (i = 0; i < pool->base.clk_src_count; i++) { + if (pool->base.clock_sources[i] != NULL) { + dcn20_clock_source_destroy(&pool->base.clock_sources[i]); + pool->base.clock_sources[i] = NULL; + } + } + + for (i = 0; i < pool->base.res_cap->num_mpc_3dlut; i++) { + if (pool->base.mpc_lut[i] != NULL) { + dc_3dlut_func_release(pool->base.mpc_lut[i]); + pool->base.mpc_lut[i] = NULL; + } + if (pool->base.mpc_shaper[i] != NULL) { + dc_transfer_func_release(pool->base.mpc_shaper[i]); + pool->base.mpc_shaper[i] = NULL; + } + } + + if (pool->base.dp_clock_source != NULL) { + dcn20_clock_source_destroy(&pool->base.dp_clock_source); + pool->base.dp_clock_source = NULL; + } + + for (i = 0; i < pool->base.res_cap->num_timing_generator; i++) { + if (pool->base.multiple_abms[i] != NULL) + dce_abm_destroy(&pool->base.multiple_abms[i]); + } + + if (pool->base.psr != NULL) + dmub_psr_destroy(&pool->base.psr); + + if (pool->base.pg_cntl != NULL) + dcn_pg_cntl_destroy(&pool->base.pg_cntl); + + if (pool->base.dccg != NULL) + dcn_dccg_destroy(&pool->base.dccg); +} + +static struct hubp *dcn35_hubp_create( + struct dc_context *ctx, + uint32_t inst) +{ + struct dcn20_hubp *hubp2 = + kzalloc(sizeof(struct dcn20_hubp), GFP_KERNEL); + + if (!hubp2) + return NULL; + +#undef REG_STRUCT +#define REG_STRUCT hubp_regs + hubp_regs_init(0), + hubp_regs_init(1), + hubp_regs_init(2), + hubp_regs_init(3); + + if (hubp35_construct(hubp2, ctx, inst, + &hubp_regs[inst], &hubp_shift, &hubp_mask)) + return &hubp2->base; + + BREAK_TO_DEBUGGER(); + kfree(hubp2); + return NULL; +} + +static void dcn35_dwbc_init(struct dcn30_dwbc *dwbc30, struct dc_context *ctx) +{ + dcn35_dwbc_set_fgcg( + dwbc30, ctx->dc->debug.enable_fine_grain_clock_gating.bits.dwb); +} + +static bool dcn35_dwbc_create(struct dc_context *ctx, struct resource_pool *pool) +{ + int i; + uint32_t pipe_count = pool->res_cap->num_dwb; + + for (i = 0; i < pipe_count; i++) { + struct dcn30_dwbc *dwbc30 = kzalloc(sizeof(struct dcn30_dwbc), + GFP_KERNEL); + + if (!dwbc30) { + dm_error("DC: failed to create dwbc30!\n"); + return false; + } + +#undef REG_STRUCT +#define REG_STRUCT dwbc35_regs + dwbc_regs_dcn3_init(0); + + dcn35_dwbc_construct(dwbc30, ctx, + &dwbc35_regs[i], + &dwbc35_shift, + &dwbc35_mask, + i); + + pool->dwbc[i] = &dwbc30->base; + + dcn35_dwbc_init(dwbc30, ctx); + } + return true; +} + +static void dcn35_mmhubbub_init(struct dcn30_mmhubbub *mcif_wb30, + struct dc_context *ctx) +{ + dcn35_mmhubbub_set_fgcg( + mcif_wb30, + ctx->dc->debug.enable_fine_grain_clock_gating.bits.mmhubbub); +} + +static bool dcn35_mmhubbub_create(struct dc_context *ctx, struct resource_pool *pool) +{ + int i; + uint32_t pipe_count = pool->res_cap->num_dwb; + + for (i = 0; i < pipe_count; i++) { + struct dcn30_mmhubbub *mcif_wb30 = kzalloc(sizeof(struct dcn30_mmhubbub), + GFP_KERNEL); + + if (!mcif_wb30) { + dm_error("DC: failed to create mcif_wb30!\n"); + return false; + } + +#undef REG_STRUCT +#define REG_STRUCT mcif_wb35_regs + mcif_wb_regs_dcn3_init(0); + + dcn35_mmhubbub_construct(mcif_wb30, ctx, + &mcif_wb35_regs[i], + &mcif_wb35_shift, + &mcif_wb35_mask, + i); + + dcn35_mmhubbub_init(mcif_wb30, ctx); + + pool->mcif_wb[i] = &mcif_wb30->base; + } + return true; +} + +static struct display_stream_compressor *dcn35_dsc_create( + struct dc_context *ctx, uint32_t inst) +{ + struct dcn20_dsc *dsc = + kzalloc(sizeof(struct dcn20_dsc), GFP_KERNEL); + + if (!dsc) { + BREAK_TO_DEBUGGER(); + return NULL; + } + +#undef REG_STRUCT +#define REG_STRUCT dsc_regs + dsc_regsDCN35_init(0), + dsc_regsDCN35_init(1), + dsc_regsDCN35_init(2), + dsc_regsDCN35_init(3); + + dsc35_construct(dsc, ctx, inst, &dsc_regs[inst], &dsc_shift, &dsc_mask); + dsc35_set_fgcg(dsc, + ctx->dc->debug.enable_fine_grain_clock_gating.bits.dsc); + return &dsc->base; +} + +static void dcn35_destroy_resource_pool(struct resource_pool **pool) +{ + struct dcn35_resource_pool *dcn35_pool = TO_DCN35_RES_POOL(*pool); + + dcn35_resource_destruct(dcn35_pool); + kfree(dcn35_pool); + *pool = NULL; +} + +static struct clock_source *dcn35_clock_source_create( + struct dc_context *ctx, + struct dc_bios *bios, + enum clock_source_id id, + const struct dce110_clk_src_regs *regs, + bool dp_clk_src) +{ + struct dce110_clk_src *clk_src = + kzalloc(sizeof(struct dce110_clk_src), GFP_KERNEL); + + if (!clk_src) + return NULL; + + if (dcn31_clk_src_construct(clk_src, ctx, bios, id, + regs, &cs_shift, &cs_mask)) { + clk_src->base.dp_clk_src = dp_clk_src; + return &clk_src->base; + } + + BREAK_TO_DEBUGGER(); + return NULL; +} + +static struct dc_cap_funcs cap_funcs = { + .get_dcc_compression_cap = dcn20_get_dcc_compression_cap +}; + +static void dcn35_get_panel_config_defaults(struct dc_panel_config *panel_config) +{ + *panel_config = panel_config_defaults; +} + + +static bool dcn35_validate_bandwidth(struct dc *dc, + struct dc_state *context, + bool fast_validate) +{ + bool out = false; + + out = dml2_validate(dc, context, fast_validate); + + return out; +} + + +static struct resource_funcs dcn35_res_pool_funcs = { + .destroy = dcn35_destroy_resource_pool, + .link_enc_create = dcn35_link_encoder_create, + .link_enc_create_minimal = dcn31_link_enc_create_minimal, + .link_encs_assign = link_enc_cfg_link_encs_assign, + .link_enc_unassign = link_enc_cfg_link_enc_unassign, + .panel_cntl_create = dcn31_panel_cntl_create, + .validate_bandwidth = dcn35_validate_bandwidth, + .calculate_wm_and_dlg = NULL, + .update_soc_for_wm_a = dcn31_update_soc_for_wm_a, + .populate_dml_pipes = dcn35_populate_dml_pipes_from_context_fpu, + .acquire_free_pipe_as_secondary_dpp_pipe = dcn20_acquire_free_pipe_for_layer, + .release_pipe = dcn20_release_pipe, + .add_stream_to_ctx = dcn30_add_stream_to_ctx, + .add_dsc_to_stream_resource = dcn20_add_dsc_to_stream_resource, + .remove_stream_from_ctx = dcn20_remove_stream_from_ctx, + .populate_dml_writeback_from_context = dcn30_populate_dml_writeback_from_context, + .set_mcif_arb_params = dcn30_set_mcif_arb_params, + .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 = dcn35_update_bw_bounding_box_fpu, + .patch_unknown_plane_state = dcn20_patch_unknown_plane_state, + .get_panel_config_defaults = dcn35_get_panel_config_defaults, + .get_preferred_eng_id_dpia = dcn35_get_preferred_eng_id_dpia, +}; + +static bool dcn35_resource_construct( + uint8_t num_virtual_links, + struct dc *dc, + struct dcn35_resource_pool *pool) +{ + int i; + struct dc_context *ctx = dc->ctx; + struct irq_service_init_data init_data; + +#undef REG_STRUCT +#define REG_STRUCT bios_regs + bios_regs_init(); + +#undef REG_STRUCT +#define REG_STRUCT clk_src_regs + clk_src_regs_init(0, A), + clk_src_regs_init(1, B), + clk_src_regs_init(2, C), + clk_src_regs_init(3, D), + clk_src_regs_init(4, E); + +#undef REG_STRUCT +#define REG_STRUCT abm_regs + abm_regs_init(0), + abm_regs_init(1), + abm_regs_init(2), + abm_regs_init(3); + +#undef REG_STRUCT +#define REG_STRUCT dccg_regs + dccg_regs_init(); + + ctx->dc_bios->regs = &bios_regs; + + pool->base.res_cap = &res_cap_dcn35; + + pool->base.funcs = &dcn35_res_pool_funcs; + + /************************************************* + * Resource + asic cap harcoding * + *************************************************/ + pool->base.underlay_pipe_index = NO_UNDERLAY_PIPE; + pool->base.pipe_count = pool->base.res_cap->num_timing_generator; + pool->base.mpcc_count = pool->base.res_cap->num_timing_generator; + dc->caps.max_downscale_ratio = 600; + dc->caps.i2c_speed_in_khz = 100; + dc->caps.i2c_speed_in_khz_hdcp = 100; + dc->caps.max_cursor_size = 256; + dc->caps.min_horizontal_blanking_period = 80; + dc->caps.dmdata_alloc_size = 2048; + dc->caps.max_slave_planes = 2; + dc->caps.max_slave_yuv_planes = 2; + dc->caps.max_slave_rgb_planes = 2; + dc->caps.post_blend_color_processing = true; + dc->caps.force_dp_tps4_for_cp2520 = true; + if (dc->config.forceHBR2CP2520) + dc->caps.force_dp_tps4_for_cp2520 = false; + dc->caps.dp_hpo = true; + dc->caps.dp_hdmi21_pcon_support = true; + + dc->caps.edp_dsc_support = true; + dc->caps.extended_aux_timeout_support = true; + dc->caps.dmcub_support = true; + dc->caps.is_apu = true; + dc->caps.seamless_odm = true; + + dc->caps.zstate_support = true; + dc->caps.ips_support = true; + dc->caps.max_v_total = (1 << 15) - 1; + + /* Color pipeline capabilities */ + dc->caps.color.dpp.dcn_arch = 1; + dc->caps.color.dpp.input_lut_shared = 0; + dc->caps.color.dpp.icsc = 1; + dc->caps.color.dpp.dgam_ram = 0; // must use gamma_corr + dc->caps.color.dpp.dgam_rom_caps.srgb = 1; + dc->caps.color.dpp.dgam_rom_caps.bt2020 = 1; + dc->caps.color.dpp.dgam_rom_caps.gamma2_2 = 1; + dc->caps.color.dpp.dgam_rom_caps.pq = 1; + dc->caps.color.dpp.dgam_rom_caps.hlg = 1; + dc->caps.color.dpp.post_csc = 1; + dc->caps.color.dpp.gamma_corr = 1; + dc->caps.color.dpp.dgam_rom_for_yuv = 0; + + dc->caps.color.dpp.hw_3d_lut = 1; + dc->caps.color.dpp.ogam_ram = 0; // no OGAM in DPP since DCN1 + // no OGAM ROM on DCN301 + dc->caps.color.dpp.ogam_rom_caps.srgb = 0; + dc->caps.color.dpp.ogam_rom_caps.bt2020 = 0; + dc->caps.color.dpp.ogam_rom_caps.gamma2_2 = 0; + dc->caps.color.dpp.ogam_rom_caps.pq = 0; + dc->caps.color.dpp.ogam_rom_caps.hlg = 0; + dc->caps.color.dpp.ocsc = 0; + + dc->caps.color.mpc.gamut_remap = 1; + dc->caps.color.mpc.num_3dluts = pool->base.res_cap->num_mpc_3dlut; //2 + dc->caps.color.mpc.ogam_ram = 1; + dc->caps.color.mpc.ogam_rom_caps.srgb = 0; + dc->caps.color.mpc.ogam_rom_caps.bt2020 = 0; + dc->caps.color.mpc.ogam_rom_caps.gamma2_2 = 0; + dc->caps.color.mpc.ogam_rom_caps.pq = 0; + dc->caps.color.mpc.ogam_rom_caps.hlg = 0; + dc->caps.color.mpc.ocsc = 1; + + /* max_disp_clock_khz_at_vmin is slightly lower than the STA value in order + * to provide some margin. + * It's expected for furture ASIC to have equal or higher value, in order to + * have determinstic power improvement from generate to genration. + * (i.e., we should not expect new ASIC generation with lower vmin rate) + */ + dc->caps.max_disp_clock_khz_at_vmin = 650000; + + /* Use pipe context based otg sync logic */ + dc->config.use_pipe_ctx_sync_logic = true; + dc->config.use_default_clock_table = false; + /* read VBIOS LTTPR caps */ + { + if (ctx->dc_bios->funcs->get_lttpr_caps) { + enum bp_result bp_query_result; + uint8_t is_vbios_lttpr_enable = 0; + + bp_query_result = ctx->dc_bios->funcs->get_lttpr_caps(ctx->dc_bios, &is_vbios_lttpr_enable); + dc->caps.vbios_lttpr_enable = (bp_query_result == BP_RESULT_OK) && !!is_vbios_lttpr_enable; + } + + /* interop bit is implicit */ + { + dc->caps.vbios_lttpr_aware = true; + } + } + + if (dc->ctx->dce_environment == DCE_ENV_PRODUCTION_DRV) + dc->debug = debug_defaults_drv; + + // Init the vm_helper + if (dc->vm_helper) + vm_helper_init(dc->vm_helper, 16); + + /************************************************* + * Create resources * + *************************************************/ + + /* Clock Sources for Pixel Clock*/ + pool->base.clock_sources[DCN35_CLK_SRC_PLL0] = + dcn35_clock_source_create(ctx, ctx->dc_bios, + CLOCK_SOURCE_COMBO_PHY_PLL0, + &clk_src_regs[0], false); + pool->base.clock_sources[DCN35_CLK_SRC_PLL1] = + dcn35_clock_source_create(ctx, ctx->dc_bios, + CLOCK_SOURCE_COMBO_PHY_PLL1, + &clk_src_regs[1], false); + pool->base.clock_sources[DCN35_CLK_SRC_PLL2] = + dcn35_clock_source_create(ctx, ctx->dc_bios, + CLOCK_SOURCE_COMBO_PHY_PLL2, + &clk_src_regs[2], false); + pool->base.clock_sources[DCN35_CLK_SRC_PLL3] = + dcn35_clock_source_create(ctx, ctx->dc_bios, + CLOCK_SOURCE_COMBO_PHY_PLL3, + &clk_src_regs[3], false); + pool->base.clock_sources[DCN35_CLK_SRC_PLL4] = + dcn35_clock_source_create(ctx, ctx->dc_bios, + CLOCK_SOURCE_COMBO_PHY_PLL4, + &clk_src_regs[4], false); + + pool->base.clk_src_count = DCN35_CLK_SRC_TOTAL; + + /* todo: not reuse phy_pll registers */ + pool->base.dp_clock_source = + dcn35_clock_source_create(ctx, ctx->dc_bios, + CLOCK_SOURCE_ID_DP_DTO, + &clk_src_regs[0], true); + + for (i = 0; i < pool->base.clk_src_count; i++) { + if (pool->base.clock_sources[i] == NULL) { + dm_error("DC: failed to create clock sources!\n"); + BREAK_TO_DEBUGGER(); + goto create_fail; + } + } + /*temp till dml2 fully work without dml1*/ + dml_init_instance(&dc->dml, &dcn3_5_soc, &dcn3_5_ip, DML_PROJECT_DCN31); + + /* TODO: DCCG */ + pool->base.dccg = dccg35_create(ctx, &dccg_regs, &dccg_shift, &dccg_mask); + if (pool->base.dccg == NULL) { + dm_error("DC: failed to create dccg!\n"); + BREAK_TO_DEBUGGER(); + goto create_fail; + } + +#undef REG_STRUCT +#define REG_STRUCT pg_cntl_regs + pg_cntl_dcn35_regs_init(); + + pool->base.pg_cntl = pg_cntl35_create(ctx, &pg_cntl_regs, &pg_cntl_shift, &pg_cntl_mask); + if (pool->base.pg_cntl == NULL) { + dm_error("DC: failed to create power gate control!\n"); + BREAK_TO_DEBUGGER(); + goto create_fail; + } + + /* TODO: IRQ */ + init_data.ctx = dc->ctx; + pool->base.irqs = dal_irq_service_dcn35_create(&init_data); + if (!pool->base.irqs) + goto create_fail; + + /* HUBBUB */ + pool->base.hubbub = dcn35_hubbub_create(ctx); + if (pool->base.hubbub == NULL) { + BREAK_TO_DEBUGGER(); + dm_error("DC: failed to create hubbub!\n"); + goto create_fail; + } + + /* HUBPs, DPPs, OPPs and TGs */ + for (i = 0; i < pool->base.pipe_count; i++) { + pool->base.hubps[i] = dcn35_hubp_create(ctx, i); + if (pool->base.hubps[i] == NULL) { + BREAK_TO_DEBUGGER(); + dm_error( + "DC: failed to create hubps!\n"); + goto create_fail; + } + + pool->base.dpps[i] = dcn35_dpp_create(ctx, i); + if (pool->base.dpps[i] == NULL) { + BREAK_TO_DEBUGGER(); + dm_error( + "DC: failed to create dpps!\n"); + goto create_fail; + } + } + + for (i = 0; i < pool->base.res_cap->num_opp; i++) { + pool->base.opps[i] = dcn35_opp_create(ctx, i); + if (pool->base.opps[i] == NULL) { + BREAK_TO_DEBUGGER(); + dm_error( + "DC: failed to create output pixel processor!\n"); + goto create_fail; + } + } + + for (i = 0; i < pool->base.res_cap->num_timing_generator; i++) { + pool->base.timing_generators[i] = dcn35_timing_generator_create( + ctx, i); + if (pool->base.timing_generators[i] == NULL) { + BREAK_TO_DEBUGGER(); + dm_error("DC: failed to create tg!\n"); + goto create_fail; + } + } + pool->base.timing_generator_count = i; + + /* PSR */ + pool->base.psr = dmub_psr_create(ctx); + if (pool->base.psr == NULL) { + dm_error("DC: failed to create psr obj!\n"); + BREAK_TO_DEBUGGER(); + goto create_fail; + } + + /* ABM */ + for (i = 0; i < pool->base.res_cap->num_timing_generator; i++) { + pool->base.multiple_abms[i] = dmub_abm_create(ctx, + &abm_regs[i], + &abm_shift, + &abm_mask); + if (pool->base.multiple_abms[i] == NULL) { + dm_error("DC: failed to create abm for pipe %d!\n", i); + BREAK_TO_DEBUGGER(); + goto create_fail; + } + } + + /* MPC and DSC */ + pool->base.mpc = dcn35_mpc_create(ctx, pool->base.mpcc_count, pool->base.res_cap->num_mpc_3dlut); + if (pool->base.mpc == NULL) { + BREAK_TO_DEBUGGER(); + dm_error("DC: failed to create mpc!\n"); + goto create_fail; + } + + for (i = 0; i < pool->base.res_cap->num_dsc; i++) { + pool->base.dscs[i] = dcn35_dsc_create(ctx, i); + if (pool->base.dscs[i] == NULL) { + BREAK_TO_DEBUGGER(); + dm_error("DC: failed to create display stream compressor %d!\n", i); + goto create_fail; + } + } + + /* DWB and MMHUBBUB */ + if (!dcn35_dwbc_create(ctx, &pool->base)) { + BREAK_TO_DEBUGGER(); + dm_error("DC: failed to create dwbc!\n"); + goto create_fail; + } + + if (!dcn35_mmhubbub_create(ctx, &pool->base)) { + BREAK_TO_DEBUGGER(); + dm_error("DC: failed to create mcif_wb!\n"); + goto create_fail; + } + + /* AUX and I2C */ + for (i = 0; i < pool->base.res_cap->num_ddc; i++) { + pool->base.engines[i] = dcn31_aux_engine_create(ctx, i); + if (pool->base.engines[i] == NULL) { + BREAK_TO_DEBUGGER(); + dm_error( + "DC:failed to create aux engine!!\n"); + goto create_fail; + } + pool->base.hw_i2cs[i] = dcn31_i2c_hw_create(ctx, i); + if (pool->base.hw_i2cs[i] == NULL) { + BREAK_TO_DEBUGGER(); + dm_error( + "DC:failed to create hw i2c!!\n"); + goto create_fail; + } + pool->base.sw_i2cs[i] = NULL; + } + + /* DCN3.5 has 6 DPIA */ + pool->base.usb4_dpia_count = 4; + if (dc->debug.dpia_debug.bits.disable_dpia) + pool->base.usb4_dpia_count = 0; + + /* Audio, Stream Encoders including HPO and virtual, MPC 3D LUTs */ + if (!resource_construct(num_virtual_links, dc, &pool->base, + &res_create_funcs)) + goto create_fail; + + /* HW Sequencer and Plane caps */ + dcn35_hw_sequencer_construct(dc); + + dc->caps.max_planes = pool->base.pipe_count; + + for (i = 0; i < dc->caps.max_planes; ++i) + dc->caps.planes[i] = plane_cap; + + dc->cap_funcs = cap_funcs; + + dc->dcn_ip->max_num_dpp = pool->base.pipe_count; + + dc->dml2_options.dcn_pipe_count = pool->base.pipe_count; + dc->dml2_options.use_native_pstate_optimization = true; + dc->dml2_options.use_native_soc_bb_construction = true; + if (dc->config.EnableMinDispClkODM) + dc->dml2_options.minimize_dispclk_using_odm = true; + dc->dml2_options.enable_windowed_mpo_odm = dc->config.enable_windowed_mpo_odm; + + dc->dml2_options.callbacks.dc = dc; + dc->dml2_options.callbacks.build_scaling_params = &resource_build_scaling_params; + dc->dml2_options.callbacks.can_support_mclk_switch_using_fw_based_vblank_stretch = &dcn30_can_support_mclk_switch_using_fw_based_vblank_stretch; + dc->dml2_options.callbacks.acquire_secondary_pipe_for_mpc_odm = &dc_resource_acquire_secondary_pipe_for_mpc_odm_legacy; + dc->dml2_options.callbacks.update_pipes_for_stream_with_slice_count = &resource_update_pipes_for_stream_with_slice_count; + dc->dml2_options.callbacks.update_pipes_for_plane_with_slice_count = &resource_update_pipes_for_plane_with_slice_count; + dc->dml2_options.callbacks.get_mpc_slice_index = &resource_get_mpc_slice_index; + dc->dml2_options.callbacks.get_odm_slice_index = &resource_get_odm_slice_index; + dc->dml2_options.callbacks.get_opp_head = &resource_get_opp_head; + dc->dml2_options.max_segments_per_hubp = 24; + + dc->dml2_options.det_segment_size = DCN3_2_DET_SEG_SIZE;/*todo*/ + + if (dc->config.sdpif_request_limit_words_per_umc == 0) + dc->config.sdpif_request_limit_words_per_umc = 16;/*todo*/ + + return true; + +create_fail: + + dcn35_resource_destruct(pool); + + return false; +} + +struct resource_pool *dcn35_create_resource_pool( + const struct dc_init_data *init_data, + struct dc *dc) +{ + struct dcn35_resource_pool *pool = + kzalloc(sizeof(struct dcn35_resource_pool), GFP_KERNEL); + + if (!pool) + return NULL; + + if (dcn35_resource_construct(init_data->num_virtual_links, dc, pool)) + return &pool->base; + + BREAK_TO_DEBUGGER(); + kfree(pool); + return NULL; +} diff --git a/drivers/gpu/drm/amd/display/dc/resource/dcn35/dcn35_resource.h b/drivers/gpu/drm/amd/display/dc/resource/dcn35/dcn35_resource.h new file mode 100644 index 000000000000..99aea102e3f7 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/resource/dcn35/dcn35_resource.h @@ -0,0 +1,310 @@ +/* SPDX-License-Identifier: MIT */ +/* + * Copyright 2023 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 _DCN35_RESOURCE_H_ +#define _DCN35_RESOURCE_H_ + +#include "core_types.h" + +#define DCN3_5_VMIN_DISPCLK_HZ 717000000 +#define TO_DCN35_RES_POOL(pool)\ + container_of(pool, struct dcn35_resource_pool, base) + +extern struct _vcs_dpi_ip_params_st dcn3_5_ip; +extern struct _vcs_dpi_soc_bounding_box_st dcn3_5_soc; + +struct dcn35_resource_pool { + struct resource_pool base; +}; + +struct resource_pool *dcn35_create_resource_pool( + const struct dc_init_data *init_data, + struct dc *dc); + +/* Defs for runtime init of registers */ + +#define OPP_REG_LIST_DCN20_RI(id) \ + OPP_REG_LIST_DCN10_RI(id), \ + OPP_DPG_REG_LIST_RI(id), \ + SRI_ARR(FMT_422_CONTROL, FMT, id), \ + SRI_ARR(OPPBUF_CONTROL1, OPPBUF, id) + +#define OPP_REG_LIST_DCN35_RI(id) \ + OPP_REG_LIST_DCN20_RI(id), \ + SRI2_ARR(OPP_TOP_CLK_CONTROL, OPP, id) + +#define VPG_DCN31_REG_LIST_RI(id) \ + SRI_ARR(VPG_GENERIC_STATUS, VPG, id), \ + SRI_ARR(VPG_GENERIC_PACKET_ACCESS_CTRL, VPG, id), \ + SRI_ARR(VPG_GENERIC_PACKET_DATA, VPG, id), \ + SRI_ARR(VPG_GSP_FRAME_UPDATE_CTRL, VPG, id), \ + SRI_ARR(VPG_GSP_IMMEDIATE_UPDATE_CTRL, VPG, id), \ + SRI_ARR(VPG_MEM_PWR, VPG, id) + +#define AFMT_DCN31_REG_LIST_RI(id) \ + SRI_ARR(AFMT_INFOFRAME_CONTROL0, AFMT, id), \ + SRI_ARR(AFMT_VBI_PACKET_CONTROL, AFMT, id), \ + SRI_ARR(AFMT_AUDIO_PACKET_CONTROL, AFMT, id), \ + SRI_ARR(AFMT_AUDIO_PACKET_CONTROL2, AFMT, id), \ + SRI_ARR(AFMT_AUDIO_SRC_CONTROL, AFMT, id), \ + SRI_ARR(AFMT_60958_0, AFMT, id), \ + SRI_ARR(AFMT_60958_1, AFMT, id), \ + SRI_ARR(AFMT_60958_2, AFMT, id), \ + SRI_ARR(AFMT_MEM_PWR, AFMT, id) + +/* Stream encoder */ +#define SE_DCN35_REG_LIST_RI(id) \ + SRI_ARR(AFMT_CNTL, DIG, id), \ + SRI_ARR(DIG_FE_CNTL, DIG, id), \ + SRI_ARR(HDMI_CONTROL, DIG, id), \ + SRI_ARR(HDMI_DB_CONTROL, DIG, id), \ + SRI_ARR(HDMI_GC, DIG, id), \ + SRI_ARR(HDMI_GENERIC_PACKET_CONTROL0, DIG, id), \ + SRI_ARR(HDMI_GENERIC_PACKET_CONTROL1, DIG, id), \ + SRI_ARR(HDMI_GENERIC_PACKET_CONTROL2, DIG, id), \ + SRI_ARR(HDMI_GENERIC_PACKET_CONTROL3, DIG, id), \ + SRI_ARR(HDMI_GENERIC_PACKET_CONTROL4, DIG, id), \ + SRI_ARR(HDMI_GENERIC_PACKET_CONTROL5, DIG, id), \ + SRI_ARR(HDMI_GENERIC_PACKET_CONTROL6, DIG, id), \ + SRI_ARR(HDMI_GENERIC_PACKET_CONTROL7, DIG, id), \ + SRI_ARR(HDMI_GENERIC_PACKET_CONTROL8, DIG, id), \ + SRI_ARR(HDMI_GENERIC_PACKET_CONTROL9, DIG, id), \ + SRI_ARR(HDMI_GENERIC_PACKET_CONTROL10, DIG, id), \ + SRI_ARR(HDMI_INFOFRAME_CONTROL0, DIG, id), \ + SRI_ARR(HDMI_INFOFRAME_CONTROL1, DIG, id), \ + SRI_ARR(HDMI_VBI_PACKET_CONTROL, DIG, id), \ + SRI_ARR(HDMI_AUDIO_PACKET_CONTROL, DIG, id),\ + SRI_ARR(HDMI_ACR_PACKET_CONTROL, DIG, id),\ + SRI_ARR(HDMI_ACR_32_0, DIG, id),\ + SRI_ARR(HDMI_ACR_32_1, DIG, id),\ + SRI_ARR(HDMI_ACR_44_0, DIG, id),\ + SRI_ARR(HDMI_ACR_44_1, DIG, id),\ + SRI_ARR(HDMI_ACR_48_0, DIG, id),\ + SRI_ARR(HDMI_ACR_48_1, DIG, id),\ + SRI_ARR(DP_DB_CNTL, DP, id), \ + SRI_ARR(DP_MSA_MISC, DP, id), \ + SRI_ARR(DP_MSA_VBID_MISC, DP, id), \ + SRI_ARR(DP_MSA_COLORIMETRY, DP, id), \ + SRI_ARR(DP_MSA_TIMING_PARAM1, DP, id), \ + SRI_ARR(DP_MSA_TIMING_PARAM2, DP, id), \ + SRI_ARR(DP_MSA_TIMING_PARAM3, DP, id), \ + SRI_ARR(DP_MSA_TIMING_PARAM4, DP, id), \ + SRI_ARR(DP_MSE_RATE_CNTL, DP, id), \ + SRI_ARR(DP_MSE_RATE_UPDATE, DP, id), \ + SRI_ARR(DP_PIXEL_FORMAT, DP, id), \ + SRI_ARR(DP_SEC_CNTL, DP, id), \ + SRI_ARR(DP_SEC_CNTL1, DP, id), \ + SRI_ARR(DP_SEC_CNTL2, DP, id), \ + SRI_ARR(DP_SEC_CNTL5, DP, id), \ + SRI_ARR(DP_SEC_CNTL6, DP, id), \ + SRI_ARR(DP_STEER_FIFO, DP, id), \ + SRI_ARR(DP_VID_M, DP, id), \ + SRI_ARR(DP_VID_N, DP, id), \ + SRI_ARR(DP_VID_STREAM_CNTL, DP, id), \ + SRI_ARR(DP_VID_TIMING, DP, id), \ + SRI_ARR(DP_SEC_AUD_N, DP, id), \ + SRI_ARR(DP_SEC_TIMESTAMP, DP, id), \ + SRI_ARR(DP_DSC_CNTL, DP, id), \ + SRI_ARR(DP_SEC_METADATA_TRANSMISSION, DP, id), \ + SRI_ARR(HDMI_METADATA_PACKET_CONTROL, DIG, id), \ + SRI_ARR(DP_SEC_FRAMING4, DP, id), \ + SRI_ARR(DP_GSP11_CNTL, DP, id), \ + SRI_ARR(DME_CONTROL, DME, id),\ + SRI_ARR(DP_SEC_METADATA_TRANSMISSION, DP, id), \ + SRI_ARR(HDMI_METADATA_PACKET_CONTROL, DIG, id), \ + SRI_ARR(DIG_FE_CNTL, DIG, id), \ + SRI_ARR(DIG_FE_EN_CNTL, DIG, id), \ + SRI_ARR(DIG_FE_CLK_CNTL, DIG, id), \ + SRI_ARR(DIG_CLOCK_PATTERN, DIG, id), \ + SRI_ARR(DIG_FIFO_CTRL0, DIG, id), \ + SRI_ARR(STREAM_MAPPER_CONTROL, DIG, id) + +#define LE_DCN35_REG_LIST_RI(id)\ + LE_DCN3_REG_LIST_RI(id),\ + SRI_ARR(DP_DPHY_INTERNAL_CTRL, DP, id), \ + SR_ARR(DIO_LINKA_CNTL, id), \ + SR_ARR(DIO_LINKB_CNTL, id), \ + SR_ARR(DIO_LINKC_CNTL, id), \ + SR_ARR(DIO_LINKD_CNTL, id), \ + SR_ARR(DIO_LINKE_CNTL, id), \ + SR_ARR(DIO_LINKF_CNTL, id),\ + SRI_ARR(DIG_BE_CLK_CNTL, DIG, id),\ + SR_ARR(DIO_CLK_CNTL, id) + +#define MCIF_WB_COMMON_REG_LIST_DCN3_5_RI(inst) \ + MCIF_WB_COMMON_REG_LIST_DCN32_RI(inst), \ + SRI2_ARR(MMHUBBUB_CLOCK_CNTL, MMHUBBUB, inst) + +#define HWSEQ_DCN35_REG_LIST()\ + SR(DCHUBBUB_GLOBAL_TIMER_CNTL), \ + SR(DCHUBBUB_ARB_HOSTVM_CNTL), \ + SR(DIO_MEM_PWR_CTRL), \ + SR(ODM_MEM_PWR_CTRL3), \ + SR(MMHUBBUB_MEM_PWR_CNTL), \ + SR(DCCG_GATE_DISABLE_CNTL), \ + SR(DCCG_GATE_DISABLE_CNTL2), \ + SR(DCCG_GATE_DISABLE_CNTL5), \ + SR(DCFCLK_CNTL),\ + SR(DC_MEM_GLOBAL_PWR_REQ_CNTL), \ + SRII(PIXEL_RATE_CNTL, OTG, 0), \ + SRII(PIXEL_RATE_CNTL, OTG, 1),\ + SRII(PIXEL_RATE_CNTL, OTG, 2),\ + SRII(PIXEL_RATE_CNTL, OTG, 3),\ + SRII(PHYPLL_PIXEL_RATE_CNTL, OTG, 0),\ + SRII(PHYPLL_PIXEL_RATE_CNTL, OTG, 1),\ + SRII(PHYPLL_PIXEL_RATE_CNTL, OTG, 2),\ + SRII(PHYPLL_PIXEL_RATE_CNTL, OTG, 3),\ + SR(MICROSECOND_TIME_BASE_DIV), \ + SR(MILLISECOND_TIME_BASE_DIV), \ + SR(DISPCLK_FREQ_CHANGE_CNTL), \ + SR(RBBMIF_TIMEOUT_DIS), \ + SR(RBBMIF_TIMEOUT_DIS_2), \ + SR(DCHUBBUB_CRC_CTRL), \ + SR(DPP_TOP0_DPP_CRC_CTRL), \ + SR(DPP_TOP0_DPP_CRC_VAL_B_A), \ + SR(DPP_TOP0_DPP_CRC_VAL_R_G), \ + SR(MPC_CRC_CTRL), \ + SR(MPC_CRC_RESULT_GB), \ + SR(MPC_CRC_RESULT_C), \ + SR(MPC_CRC_RESULT_AR), \ + SR(DOMAIN0_PG_CONFIG), \ + SR(DOMAIN1_PG_CONFIG), \ + SR(DOMAIN2_PG_CONFIG), \ + SR(DOMAIN3_PG_CONFIG), \ + SR(DOMAIN16_PG_CONFIG), \ + SR(DOMAIN17_PG_CONFIG), \ + SR(DOMAIN18_PG_CONFIG), \ + SR(DOMAIN19_PG_CONFIG), \ + SR(DOMAIN0_PG_STATUS), \ + SR(DOMAIN1_PG_STATUS), \ + SR(DOMAIN2_PG_STATUS), \ + SR(DOMAIN3_PG_STATUS), \ + SR(DOMAIN16_PG_STATUS), \ + SR(DOMAIN17_PG_STATUS), \ + SR(DOMAIN18_PG_STATUS), \ + SR(DOMAIN19_PG_STATUS), \ + SR(DC_IP_REQUEST_CNTL), \ + SR(AZALIA_AUDIO_DTO), \ + SR(AZALIA_CONTROLLER_CLOCK_GATING), \ + SR(HPO_TOP_HW_CONTROL),\ + SR(DMU_CLK_CNTL) + +/* OPTC */ +#define OPTC_COMMON_REG_LIST_DCN3_5_RI(inst) \ + SRI_ARR(OTG_VSTARTUP_PARAM, OTG, inst),\ + SRI_ARR(OTG_VUPDATE_PARAM, OTG, inst),\ + SRI_ARR(OTG_VREADY_PARAM, OTG, inst),\ + SRI_ARR(OTG_MASTER_UPDATE_LOCK, OTG, inst),\ + SRI_ARR(OTG_GLOBAL_CONTROL0, OTG, inst),\ + SRI_ARR(OTG_GLOBAL_CONTROL1, OTG, inst),\ + SRI_ARR(OTG_GLOBAL_CONTROL2, OTG, inst),\ + SRI_ARR(OTG_GLOBAL_CONTROL4, OTG, inst),\ + SRI_ARR(OTG_DOUBLE_BUFFER_CONTROL, OTG, inst),\ + SRI_ARR(OTG_H_TOTAL, OTG, inst),\ + SRI_ARR(OTG_H_BLANK_START_END, OTG, inst),\ + SRI_ARR(OTG_H_SYNC_A, OTG, inst),\ + SRI_ARR(OTG_H_SYNC_A_CNTL, OTG, inst),\ + SRI_ARR(OTG_H_TIMING_CNTL, OTG, inst),\ + SRI_ARR(OTG_V_TOTAL, OTG, inst),\ + SRI_ARR(OTG_V_BLANK_START_END, OTG, inst),\ + SRI_ARR(OTG_V_SYNC_A, OTG, inst),\ + SRI_ARR(OTG_V_SYNC_A_CNTL, OTG, inst),\ + SRI_ARR(OTG_CONTROL, OTG, inst),\ + SRI_ARR(OTG_STEREO_CONTROL, OTG, inst),\ + SRI_ARR(OTG_3D_STRUCTURE_CONTROL, OTG, inst),\ + SRI_ARR(OTG_STEREO_STATUS, OTG, inst),\ + SRI_ARR(OTG_V_TOTAL_MAX, OTG, inst),\ + SRI_ARR(OTG_V_TOTAL_MIN, OTG, inst),\ + SRI_ARR(OTG_V_TOTAL_CONTROL, OTG, inst),\ + SRI_ARR(OTG_TRIGA_CNTL, OTG, inst),\ + SRI_ARR(OTG_FORCE_COUNT_NOW_CNTL, OTG, inst),\ + SRI_ARR(OTG_STATIC_SCREEN_CONTROL, OTG, inst),\ + SRI_ARR(OTG_STATUS_FRAME_COUNT, OTG, inst),\ + SRI_ARR(OTG_STATUS, OTG, inst),\ + SRI_ARR(OTG_STATUS_POSITION, OTG, inst),\ + SRI_ARR(OTG_NOM_VERT_POSITION, OTG, inst),\ + SRI_ARR(OTG_M_CONST_DTO0, OTG, inst),\ + SRI_ARR(OTG_M_CONST_DTO1, OTG, inst),\ + SRI_ARR(OTG_CLOCK_CONTROL, OTG, inst),\ + SRI_ARR(OTG_VERTICAL_INTERRUPT0_CONTROL, OTG, inst),\ + SRI_ARR(OTG_VERTICAL_INTERRUPT0_POSITION, OTG, inst),\ + SRI_ARR(OTG_VERTICAL_INTERRUPT1_CONTROL, OTG, inst),\ + SRI_ARR(OTG_VERTICAL_INTERRUPT1_POSITION, OTG, inst),\ + SRI_ARR(OTG_VERTICAL_INTERRUPT2_CONTROL, OTG, inst),\ + SRI_ARR(OTG_VERTICAL_INTERRUPT2_POSITION, OTG, inst),\ + SRI_ARR(OPTC_INPUT_CLOCK_CONTROL, ODM, inst),\ + SRI_ARR(OPTC_DATA_SOURCE_SELECT, ODM, inst),\ + SRI_ARR(OPTC_INPUT_GLOBAL_CONTROL, ODM, inst),\ + SRI_ARR(CONTROL, VTG, inst),\ + SRI_ARR(OTG_VERT_SYNC_CONTROL, OTG, inst),\ + SRI_ARR(OTG_GSL_CONTROL, OTG, inst),\ + SRI_ARR(OTG_CRC_CNTL, OTG, inst),\ + SRI_ARR(OTG_CRC0_DATA_RG, OTG, inst),\ + SRI_ARR(OTG_CRC0_DATA_B, OTG, inst),\ + SRI_ARR(OTG_CRC1_DATA_RG, OTG, inst),\ + SRI_ARR(OTG_CRC1_DATA_B, OTG, inst),\ + SRI_ARR(OTG_CRC2_DATA_RG, OTG, inst),\ + SRI_ARR(OTG_CRC2_DATA_B, OTG, inst),\ + SRI_ARR(OTG_CRC3_DATA_RG, OTG, inst),\ + SRI_ARR(OTG_CRC3_DATA_B, OTG, inst),\ + SRI_ARR(OTG_CRC0_WINDOWA_X_CONTROL, OTG, inst),\ + SRI_ARR(OTG_CRC0_WINDOWA_Y_CONTROL, OTG, inst),\ + SRI_ARR(OTG_CRC0_WINDOWB_X_CONTROL, OTG, inst),\ + SRI_ARR(OTG_CRC0_WINDOWB_Y_CONTROL, OTG, inst),\ + SRI_ARR(OTG_CRC1_WINDOWA_X_CONTROL, OTG, inst),\ + SRI_ARR(OTG_CRC1_WINDOWA_Y_CONTROL, OTG, inst),\ + SRI_ARR(OTG_CRC1_WINDOWB_X_CONTROL, OTG, inst),\ + SRI_ARR(OTG_CRC1_WINDOWB_Y_CONTROL, OTG, inst),\ + SRI_ARR(OTG_CRC0_WINDOWA_X_CONTROL_READBACK, OTG, inst),\ + SRI_ARR(OTG_CRC0_WINDOWA_Y_CONTROL_READBACK, OTG, inst),\ + SRI_ARR(OTG_CRC0_WINDOWB_X_CONTROL_READBACK, OTG, inst),\ + SRI_ARR(OTG_CRC0_WINDOWB_Y_CONTROL_READBACK, OTG, inst),\ + SRI_ARR(OTG_CRC1_WINDOWA_X_CONTROL_READBACK, OTG, inst),\ + SRI_ARR(OTG_CRC1_WINDOWA_Y_CONTROL_READBACK, OTG, inst),\ + SRI_ARR(OTG_CRC1_WINDOWB_X_CONTROL_READBACK, OTG, inst),\ + SRI_ARR(OTG_CRC1_WINDOWB_Y_CONTROL_READBACK, OTG, inst),\ + SR_ARR(GSL_SOURCE_SELECT, inst),\ + SRI_ARR(OTG_TRIGA_MANUAL_TRIG, OTG, inst),\ + SRI_ARR(OTG_GLOBAL_CONTROL1, OTG, inst),\ + SRI_ARR(OTG_GLOBAL_CONTROL2, OTG, inst),\ + SRI_ARR(OTG_GSL_WINDOW_X, OTG, inst),\ + SRI_ARR(OTG_GSL_WINDOW_Y, OTG, inst),\ + SRI_ARR(OTG_VUPDATE_KEEPOUT, OTG, inst),\ + SRI_ARR(OTG_DSC_START_POSITION, OTG, inst),\ + SRI_ARR(OTG_DRR_TRIGGER_WINDOW, OTG, inst),\ + SRI_ARR(OTG_DRR_V_TOTAL_CHANGE, OTG, inst),\ + SRI_ARR(OPTC_DATA_FORMAT_CONTROL, ODM, inst),\ + SRI_ARR(OPTC_BYTES_PER_PIXEL, ODM, inst),\ + SRI_ARR(OPTC_WIDTH_CONTROL, ODM, inst),\ + SRI_ARR(OPTC_MEMORY_CONFIG, ODM, inst),\ + SRI_ARR(OTG_DRR_CONTROL, OTG, inst),\ + SRI2_ARR(OPTC_CLOCK_CONTROL, OPTC, inst) + +/* DPP */ +#define DPP_REG_LIST_DCN35_RI(id)\ + DPP_REG_LIST_DCN30_COMMON_RI(id) + +#endif /* _DCN35_RESOURCE_H_ */ -- cgit From 68cfc5d8e459f50e5f46dca3b0f3c97a75f39975 Mon Sep 17 00:00:00 2001 From: Wenjing Liu Date: Fri, 20 Oct 2023 16:26:19 -0400 Subject: drm/amd/display: Try to acquire a free OTG master not used in cur ctx first [WHY & HOW] The current otg master pipe allocation logic is not optimized based current resource context. We should try to acquire a free OTG master not used in cur cts first to avoid unnecessary pipe switch from current state. Acked-by: Alex Hung Signed-off-by: Wenjing Liu Tested-by: Daniel Wheeler Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc_resource.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c index 6159d819c5c5..49f8c90f0d2b 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c @@ -3586,6 +3586,7 @@ static void mark_seamless_boot_stream( * |________|_______________|___________|_____________| */ static bool acquire_otg_master_pipe_for_stream( + const struct dc_state *cur_ctx, struct dc_state *new_ctx, const struct resource_pool *pool, struct dc_stream_state *stream) @@ -3599,7 +3600,10 @@ static bool acquire_otg_master_pipe_for_stream( int pipe_idx; struct pipe_ctx *pipe_ctx = NULL; - pipe_idx = resource_find_any_free_pipe(&new_ctx->res_ctx, pool); + pipe_idx = recource_find_free_pipe_not_used_in_cur_res_ctx( + &cur_ctx->res_ctx, &new_ctx->res_ctx, pool); + if (pipe_idx == FREE_PIPE_INDEX_NOT_FOUND) + pipe_idx = resource_find_any_free_pipe(&new_ctx->res_ctx, pool); if (pipe_idx != FREE_PIPE_INDEX_NOT_FOUND) { pipe_ctx = &new_ctx->res_ctx.pipe_ctx[pipe_idx]; memset(pipe_ctx, 0, sizeof(*pipe_ctx)); @@ -3659,7 +3663,7 @@ enum dc_status resource_map_pool_resources( if (!acquired) /* acquire new resources */ - acquired = acquire_otg_master_pipe_for_stream( + acquired = acquire_otg_master_pipe_for_stream(dc->current_state, context, pool, stream); pipe_ctx = resource_get_otg_master_for_stream(&context->res_ctx, stream); -- cgit From 673d6d73eba79a1205ac403b68ef63da1c823da2 Mon Sep 17 00:00:00 2001 From: Wenjing Liu Date: Mon, 30 Oct 2023 15:21:12 -0400 Subject: drm/amd/display: Prefer currently used OTG master when acquiring free pipe [WHY & HOW] When acquiring an OTG master pipe we should prefer currently enabled OTG master pipes first. If there are no free pipes used as current OTG master pipe then we will try to acquire a currently unused free pipe as new OTG master instead of tearing down current secondary pipes from ODM or MPC combine. Reviewed-by: Alvin Lee Reviewed-by: Dillon Varone Acked-by: Alex Hung Signed-off-by: Wenjing Liu Tested-by: Daniel Wheeler Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc_resource.c | 37 ++++++++++++++++++++++- drivers/gpu/drm/amd/display/dc/inc/resource.h | 12 ++++++++ 2 files changed, 48 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c index 49f8c90f0d2b..42a927710743 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c @@ -1764,6 +1764,29 @@ int recource_find_free_pipe_not_used_in_cur_res_ctx( return free_pipe_idx; } +int recource_find_free_pipe_used_as_otg_master_in_cur_res_ctx( + const struct resource_context *cur_res_ctx, + struct resource_context *new_res_ctx, + const struct resource_pool *pool) +{ + int free_pipe_idx = FREE_PIPE_INDEX_NOT_FOUND; + const struct pipe_ctx *new_pipe, *cur_pipe; + int i; + + for (i = 0; i < pool->pipe_count; i++) { + cur_pipe = &cur_res_ctx->pipe_ctx[i]; + new_pipe = &new_res_ctx->pipe_ctx[i]; + + if (resource_is_pipe_type(cur_pipe, OTG_MASTER) && + resource_is_pipe_type(new_pipe, FREE_PIPE)) { + free_pipe_idx = i; + break; + } + } + + return free_pipe_idx; +} + int resource_find_free_pipe_used_as_cur_sec_dpp_in_mpcc_combine( const struct resource_context *cur_res_ctx, struct resource_context *new_res_ctx, @@ -3600,8 +3623,20 @@ static bool acquire_otg_master_pipe_for_stream( int pipe_idx; struct pipe_ctx *pipe_ctx = NULL; - pipe_idx = recource_find_free_pipe_not_used_in_cur_res_ctx( + /* + * Upper level code is responsible to optimize unnecessary addition and + * removal for unchanged streams. So unchanged stream will keep the same + * OTG master instance allocated. When current stream is removed and a + * new stream is added, we want to reuse the OTG instance made available + * by the removed stream first. If not found, we try to avoid of using + * any free pipes already used in current context as this could tear + * down exiting ODM/MPC/MPO configuration unnecessarily. + */ + pipe_idx = recource_find_free_pipe_used_as_otg_master_in_cur_res_ctx( &cur_ctx->res_ctx, &new_ctx->res_ctx, pool); + if (pipe_idx == FREE_PIPE_INDEX_NOT_FOUND) + pipe_idx = recource_find_free_pipe_not_used_in_cur_res_ctx( + &cur_ctx->res_ctx, &new_ctx->res_ctx, pool); if (pipe_idx == FREE_PIPE_INDEX_NOT_FOUND) pipe_idx = resource_find_any_free_pipe(&new_ctx->res_ctx, pool); if (pipe_idx != FREE_PIPE_INDEX_NOT_FOUND) { diff --git a/drivers/gpu/drm/amd/display/dc/inc/resource.h b/drivers/gpu/drm/amd/display/dc/inc/resource.h index 06ca8bfb91e7..0458d2d749f4 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/resource.h +++ b/drivers/gpu/drm/amd/display/dc/inc/resource.h @@ -500,6 +500,18 @@ int recource_find_free_pipe_not_used_in_cur_res_ctx( struct resource_context *new_res_ctx, const struct resource_pool *pool); +/* + * Look for a free pipe in new resource context that is used in current resource + * context as an OTG master pipe. + * + * return - FREE_PIPE_INDEX_NOT_FOUND if free pipe is not found, otherwise + * pipe idx of the free pipe + */ +int recource_find_free_pipe_used_as_otg_master_in_cur_res_ctx( + const struct resource_context *cur_res_ctx, + struct resource_context *new_res_ctx, + const struct resource_pool *pool); + /* * Look for a free pipe in new resource context that is used as a secondary DPP * pipe in any MPCC combine in current resource context. -- cgit From 5f70d4ff8095a2ad362d2a00eb8d9f7e20f3daa1 Mon Sep 17 00:00:00 2001 From: Daniel Miess Date: Thu, 12 Oct 2023 12:55:47 -0400 Subject: drm/amd/display: Enable DCN clock gating for DCN35 [WHY & HOW] Enable DCN clock gating for DCN35. Disable DTBCLK gate before link training and re-enable afterwards Reviewed-by: Nicholas Kazlauskas Acked-by: Alex Hung Signed-off-by: Daniel Miess Tested-by: Daniel Wheeler Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dcn20/dcn20_dccg.h | 6 +++- drivers/gpu/drm/amd/display/dc/dcn35/dcn35_dccg.c | 30 ++++++++++++++++ drivers/gpu/drm/amd/display/dc/dcn35/dcn35_dccg.h | 7 +++- .../gpu/drm/amd/display/dc/dcn35/dcn35_pg_cntl.c | 10 +----- .../gpu/drm/amd/display/dc/dcn35/dcn35_pg_cntl.h | 1 - .../gpu/drm/amd/display/dc/hwss/dce/dce_hwseq.h | 15 +++++++- .../drm/amd/display/dc/hwss/dcn35/dcn35_hwseq.c | 42 +++++++++++++++------- drivers/gpu/drm/amd/display/dc/inc/hw/pg_cntl.h | 2 -- .../amd/display/dc/resource/dcn35/dcn35_resource.c | 16 +++++++-- .../amd/display/dc/resource/dcn35/dcn35_resource.h | 1 + .../amd/include/asic_reg/dcn/dcn_3_5_0_sh_mask.h | 8 +++++ 11 files changed, 108 insertions(+), 30 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_dccg.h b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_dccg.h index ab6d09c6fe34..76da59d8caaf 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_dccg.h +++ b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_dccg.h @@ -291,7 +291,11 @@ type SYMCLKB_FE_SRC_SEL;\ type SYMCLKC_FE_SRC_SEL;\ type SYMCLKD_FE_SRC_SEL;\ - type SYMCLKE_FE_SRC_SEL; + type SYMCLKE_FE_SRC_SEL;\ + type DTBCLK_P0_GATE_DISABLE;\ + type DTBCLK_P1_GATE_DISABLE;\ + type DTBCLK_P2_GATE_DISABLE;\ + type DTBCLK_P3_GATE_DISABLE;\ struct dccg_shift { DCCG_REG_FIELD_LIST(uint8_t) diff --git a/drivers/gpu/drm/amd/display/dc/dcn35/dcn35_dccg.c b/drivers/gpu/drm/amd/display/dc/dcn35/dcn35_dccg.c index 479f3683c0b7..142efd390d86 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn35/dcn35_dccg.c +++ b/drivers/gpu/drm/amd/display/dc/dcn35/dcn35_dccg.c @@ -256,6 +256,21 @@ static void dccg35_set_dtbclk_dto( if (params->ref_dtbclk_khz && req_dtbclk_khz) { uint32_t modulo, phase; + switch (params->otg_inst) { + case 0: + REG_UPDATE(DCCG_GATE_DISABLE_CNTL5, DTBCLK_P0_GATE_DISABLE, 1); + break; + case 1: + REG_UPDATE(DCCG_GATE_DISABLE_CNTL5, DTBCLK_P1_GATE_DISABLE, 1); + break; + case 2: + REG_UPDATE(DCCG_GATE_DISABLE_CNTL5, DTBCLK_P2_GATE_DISABLE, 1); + break; + case 3: + REG_UPDATE(DCCG_GATE_DISABLE_CNTL5, DTBCLK_P3_GATE_DISABLE, 1); + break; + } + // phase / modulo = dtbclk / dtbclk ref modulo = params->ref_dtbclk_khz * 1000; phase = req_dtbclk_khz * 1000; @@ -280,6 +295,21 @@ static void dccg35_set_dtbclk_dto( REG_UPDATE(OTG_PIXEL_RATE_CNTL[params->otg_inst], PIPE_DTO_SRC_SEL[params->otg_inst], 2); } else { + switch (params->otg_inst) { + case 0: + REG_UPDATE(DCCG_GATE_DISABLE_CNTL5, DTBCLK_P0_GATE_DISABLE, 0); + break; + case 1: + REG_UPDATE(DCCG_GATE_DISABLE_CNTL5, DTBCLK_P1_GATE_DISABLE, 0); + break; + case 2: + REG_UPDATE(DCCG_GATE_DISABLE_CNTL5, DTBCLK_P2_GATE_DISABLE, 0); + break; + case 3: + REG_UPDATE(DCCG_GATE_DISABLE_CNTL5, DTBCLK_P3_GATE_DISABLE, 0); + break; + } + REG_UPDATE_2(OTG_PIXEL_RATE_CNTL[params->otg_inst], DTBCLK_DTO_ENABLE[params->otg_inst], 0, PIPE_DTO_SRC_SEL[params->otg_inst], params->is_hdmi ? 0 : 1); diff --git a/drivers/gpu/drm/amd/display/dc/dcn35/dcn35_dccg.h b/drivers/gpu/drm/amd/display/dc/dcn35/dcn35_dccg.h index 423feb4c2f3f..bde48bee0119 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn35/dcn35_dccg.h +++ b/drivers/gpu/drm/amd/display/dc/dcn35/dcn35_dccg.h @@ -34,6 +34,7 @@ #define DCCG_REG_LIST_DCN35() \ DCCG_REG_LIST_DCN314(),\ SR(DPPCLK_CTRL),\ + SR(DCCG_GATE_DISABLE_CNTL5),\ SR(DCCG_GATE_DISABLE_CNTL6),\ SR(DCCG_GLOBAL_FGCG_REP_CNTL),\ SR(SYMCLKA_CLOCK_ENABLE),\ @@ -174,7 +175,11 @@ DCCG_SF(SYMCLKB_CLOCK_ENABLE, SYMCLKB_FE_SRC_SEL, mask_sh),\ DCCG_SF(SYMCLKC_CLOCK_ENABLE, SYMCLKC_FE_SRC_SEL, mask_sh),\ DCCG_SF(SYMCLKD_CLOCK_ENABLE, SYMCLKD_FE_SRC_SEL, mask_sh),\ - DCCG_SF(SYMCLKE_CLOCK_ENABLE, SYMCLKE_FE_SRC_SEL, mask_sh) + DCCG_SF(SYMCLKE_CLOCK_ENABLE, SYMCLKE_FE_SRC_SEL, mask_sh),\ + DCCG_SF(DCCG_GATE_DISABLE_CNTL5, DTBCLK_P0_GATE_DISABLE, mask_sh),\ + DCCG_SF(DCCG_GATE_DISABLE_CNTL5, DTBCLK_P1_GATE_DISABLE, mask_sh),\ + DCCG_SF(DCCG_GATE_DISABLE_CNTL5, DTBCLK_P2_GATE_DISABLE, mask_sh),\ + DCCG_SF(DCCG_GATE_DISABLE_CNTL5, DTBCLK_P3_GATE_DISABLE, mask_sh),\ struct dccg *dccg35_create( struct dc_context *ctx, diff --git a/drivers/gpu/drm/amd/display/dc/dcn35/dcn35_pg_cntl.c b/drivers/gpu/drm/amd/display/dc/dcn35/dcn35_pg_cntl.c index 46f71ff08fd1..0f60c40e1fc5 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn35/dcn35_pg_cntl.c +++ b/drivers/gpu/drm/amd/display/dc/dcn35/dcn35_pg_cntl.c @@ -332,13 +332,6 @@ void pg_cntl35_io_clk_pg_control(struct pg_cntl *pg_cntl, bool power_on) pg_cntl->pg_res_enable[PG_DCIO] = power_on; } -void pg_cntl35_set_force_poweron_domain22(struct pg_cntl *pg_cntl, bool power_on) -{ - struct dcn_pg_cntl *pg_cntl_dcn = TO_DCN_PG_CNTL(pg_cntl); - - REG_UPDATE(DOMAIN22_PG_CONFIG, DOMAIN_POWER_FORCEON, power_on ? 1 : 0); -} - static bool pg_cntl35_plane_otg_status(struct pg_cntl *pg_cntl) { struct dcn_pg_cntl *pg_cntl_dcn = TO_DCN_PG_CNTL(pg_cntl); @@ -508,8 +501,7 @@ static const struct pg_cntl_funcs pg_cntl35_funcs = { .mpcc_pg_control = pg_cntl35_mpcc_pg_control, .opp_pg_control = pg_cntl35_opp_pg_control, .optc_pg_control = pg_cntl35_optc_pg_control, - .dwb_pg_control = pg_cntl35_dwb_pg_control, - .set_force_poweron_domain22 = pg_cntl35_set_force_poweron_domain22 + .dwb_pg_control = pg_cntl35_dwb_pg_control }; struct pg_cntl *pg_cntl35_create( diff --git a/drivers/gpu/drm/amd/display/dc/dcn35/dcn35_pg_cntl.h b/drivers/gpu/drm/amd/display/dc/dcn35/dcn35_pg_cntl.h index 069dae08e222..3de240884d22 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn35/dcn35_pg_cntl.h +++ b/drivers/gpu/drm/amd/display/dc/dcn35/dcn35_pg_cntl.h @@ -183,7 +183,6 @@ void pg_cntl35_optc_pg_control(struct pg_cntl *pg_cntl, unsigned int optc_inst, bool power_on); void pg_cntl35_dwb_pg_control(struct pg_cntl *pg_cntl, bool power_on); void pg_cntl35_init_pg_status(struct pg_cntl *pg_cntl); -void pg_cntl35_set_force_poweron_domain22(struct pg_cntl *pg_cntl, bool power_on); struct pg_cntl *pg_cntl35_create( struct dc_context *ctx, diff --git a/drivers/gpu/drm/amd/display/dc/hwss/dce/dce_hwseq.h b/drivers/gpu/drm/amd/display/dc/hwss/dce/dce_hwseq.h index 44b4df6469d1..52f045cfd52a 100644 --- a/drivers/gpu/drm/amd/display/dc/hwss/dce/dce_hwseq.h +++ b/drivers/gpu/drm/amd/display/dc/hwss/dce/dce_hwseq.h @@ -682,6 +682,7 @@ struct dce_hwseq_registers { uint32_t DCHUBBUB_ARB_HOSTVM_CNTL; uint32_t HPO_TOP_HW_CONTROL; uint32_t DMU_CLK_CNTL; + uint32_t DCCG_GATE_DISABLE_CNTL4; uint32_t DCCG_GATE_DISABLE_CNTL5; }; /* set field name */ @@ -1199,7 +1200,19 @@ struct dce_hwseq_registers { type PHYBSYMCLK_ROOT_GATE_DISABLE;\ type PHYCSYMCLK_ROOT_GATE_DISABLE;\ type PHYDSYMCLK_ROOT_GATE_DISABLE;\ - type PHYESYMCLK_ROOT_GATE_DISABLE; + type PHYESYMCLK_ROOT_GATE_DISABLE;\ + type DTBCLK_P0_GATE_DISABLE;\ + type DTBCLK_P1_GATE_DISABLE;\ + type DTBCLK_P2_GATE_DISABLE;\ + type DTBCLK_P3_GATE_DISABLE;\ + type DPSTREAMCLK0_GATE_DISABLE;\ + type DPSTREAMCLK1_GATE_DISABLE;\ + type DPSTREAMCLK2_GATE_DISABLE;\ + type DPSTREAMCLK3_GATE_DISABLE;\ + type DPIASYMCLK0_GATE_DISABLE;\ + type DPIASYMCLK1_GATE_DISABLE;\ + type DPIASYMCLK2_GATE_DISABLE;\ + type DPIASYMCLK3_GATE_DISABLE; struct dce_hwseq_shift { HWSEQ_REG_FIELD_LIST(uint8_t) diff --git a/drivers/gpu/drm/amd/display/dc/hwss/dcn35/dcn35_hwseq.c b/drivers/gpu/drm/amd/display/dc/hwss/dcn35/dcn35_hwseq.c index 5a8258287438..39260371beb9 100644 --- a/drivers/gpu/drm/amd/display/dc/hwss/dcn35/dcn35_hwseq.c +++ b/drivers/gpu/drm/amd/display/dc/hwss/dcn35/dcn35_hwseq.c @@ -145,17 +145,36 @@ void dcn35_init_hw(struct dc *dc) hws->funcs.bios_golden_init(dc); } - REG_WRITE(DCCG_GATE_DISABLE_CNTL, 0); - REG_WRITE(DCCG_GATE_DISABLE_CNTL2, 0); - - /* Disable gating for PHYASYMCLK. This will be enabled in dccg if needed */ - REG_UPDATE_5(DCCG_GATE_DISABLE_CNTL2, PHYASYMCLK_ROOT_GATE_DISABLE, 1, - PHYBSYMCLK_ROOT_GATE_DISABLE, 1, - PHYCSYMCLK_ROOT_GATE_DISABLE, 1, - PHYDSYMCLK_ROOT_GATE_DISABLE, 1, - PHYESYMCLK_ROOT_GATE_DISABLE, 1); + if (!dc->debug.disable_clock_gate) { + REG_WRITE(DCCG_GATE_DISABLE_CNTL, 0); + REG_WRITE(DCCG_GATE_DISABLE_CNTL2, 0); + + /* Disable gating for PHYASYMCLK. This will be enabled in dccg if needed */ + REG_UPDATE_5(DCCG_GATE_DISABLE_CNTL2, PHYASYMCLK_ROOT_GATE_DISABLE, 1, + PHYBSYMCLK_ROOT_GATE_DISABLE, 1, + PHYCSYMCLK_ROOT_GATE_DISABLE, 1, + PHYDSYMCLK_ROOT_GATE_DISABLE, 1, + PHYESYMCLK_ROOT_GATE_DISABLE, 1); + + REG_UPDATE_4(DCCG_GATE_DISABLE_CNTL4, + DPIASYMCLK0_GATE_DISABLE, 0, + DPIASYMCLK1_GATE_DISABLE, 0, + DPIASYMCLK2_GATE_DISABLE, 0, + DPIASYMCLK3_GATE_DISABLE, 0); + + REG_WRITE(DCCG_GATE_DISABLE_CNTL5, 0xFFFFFFFF); + REG_UPDATE_4(DCCG_GATE_DISABLE_CNTL5, + DTBCLK_P0_GATE_DISABLE, 0, + DTBCLK_P1_GATE_DISABLE, 0, + DTBCLK_P2_GATE_DISABLE, 0, + DTBCLK_P3_GATE_DISABLE, 0); + REG_UPDATE_4(DCCG_GATE_DISABLE_CNTL5, + DPSTREAMCLK0_GATE_DISABLE, 0, + DPSTREAMCLK1_GATE_DISABLE, 0, + DPSTREAMCLK2_GATE_DISABLE, 0, + DPSTREAMCLK3_GATE_DISABLE, 0); - REG_WRITE(DCCG_GATE_DISABLE_CNTL5, 0x1f7c3fcf); + } // Initialize the dccg if (res_pool->dccg->funcs->dccg_init) @@ -332,9 +351,6 @@ void dcn35_init_hw(struct dc *dc) if (dc->res_pool->pg_cntl) { if (dc->res_pool->pg_cntl->funcs->init_pg_status) dc->res_pool->pg_cntl->funcs->init_pg_status(dc->res_pool->pg_cntl); - - if (dc->res_pool->pg_cntl->funcs->set_force_poweron_domain22) - dc->res_pool->pg_cntl->funcs->set_force_poweron_domain22(dc->res_pool->pg_cntl, false); } } diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/pg_cntl.h b/drivers/gpu/drm/amd/display/dc/inc/hw/pg_cntl.h index b9812afb886b..00ea3864dd4d 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/hw/pg_cntl.h +++ b/drivers/gpu/drm/amd/display/dc/inc/hw/pg_cntl.h @@ -47,8 +47,6 @@ struct pg_cntl_funcs { void (*optc_pg_control)(struct pg_cntl *pg_cntl, unsigned int optc_inst, bool power_on); void (*dwb_pg_control)(struct pg_cntl *pg_cntl, bool power_on); void (*init_pg_status)(struct pg_cntl *pg_cntl); - - void (*set_force_poweron_domain22)(struct pg_cntl *pg_cntl, bool power_on); }; #endif //__DC_PG_CNTL_H__ diff --git a/drivers/gpu/drm/amd/display/dc/resource/dcn35/dcn35_resource.c b/drivers/gpu/drm/amd/display/dc/resource/dcn35/dcn35_resource.c index a4027bf053c5..5c935d94a95c 100644 --- a/drivers/gpu/drm/amd/display/dc/resource/dcn35/dcn35_resource.c +++ b/drivers/gpu/drm/amd/display/dc/resource/dcn35/dcn35_resource.c @@ -626,7 +626,19 @@ static struct dce_hwseq_registers hwseq_reg; HWS_SF(, DCCG_GATE_DISABLE_CNTL2, PHYBSYMCLK_ROOT_GATE_DISABLE, mask_sh), \ HWS_SF(, DCCG_GATE_DISABLE_CNTL2, PHYCSYMCLK_ROOT_GATE_DISABLE, mask_sh), \ HWS_SF(, DCCG_GATE_DISABLE_CNTL2, PHYDSYMCLK_ROOT_GATE_DISABLE, mask_sh), \ - HWS_SF(, DCCG_GATE_DISABLE_CNTL2, PHYESYMCLK_ROOT_GATE_DISABLE, mask_sh) + HWS_SF(, DCCG_GATE_DISABLE_CNTL2, PHYESYMCLK_ROOT_GATE_DISABLE, mask_sh),\ + HWS_SF(, DCCG_GATE_DISABLE_CNTL5, DTBCLK_P0_GATE_DISABLE, mask_sh),\ + HWS_SF(, DCCG_GATE_DISABLE_CNTL5, DTBCLK_P1_GATE_DISABLE, mask_sh),\ + HWS_SF(, DCCG_GATE_DISABLE_CNTL5, DTBCLK_P2_GATE_DISABLE, mask_sh),\ + HWS_SF(, DCCG_GATE_DISABLE_CNTL5, DTBCLK_P3_GATE_DISABLE, mask_sh),\ + HWS_SF(, DCCG_GATE_DISABLE_CNTL5, DPSTREAMCLK0_GATE_DISABLE, mask_sh),\ + HWS_SF(, DCCG_GATE_DISABLE_CNTL5, DPSTREAMCLK1_GATE_DISABLE, mask_sh),\ + HWS_SF(, DCCG_GATE_DISABLE_CNTL5, DPSTREAMCLK2_GATE_DISABLE, mask_sh),\ + HWS_SF(, DCCG_GATE_DISABLE_CNTL5, DPSTREAMCLK3_GATE_DISABLE, mask_sh),\ + HWS_SF(, DCCG_GATE_DISABLE_CNTL4, DPIASYMCLK0_GATE_DISABLE, mask_sh),\ + HWS_SF(, DCCG_GATE_DISABLE_CNTL4, DPIASYMCLK1_GATE_DISABLE, mask_sh),\ + HWS_SF(, DCCG_GATE_DISABLE_CNTL4, DPIASYMCLK2_GATE_DISABLE, mask_sh),\ + HWS_SF(, DCCG_GATE_DISABLE_CNTL4, DPIASYMCLK3_GATE_DISABLE, mask_sh) static const struct dce_hwseq_shift hwseq_shift = { HWSEQ_DCN35_MASK_SH_LIST(__SHIFT) @@ -705,7 +717,7 @@ static const struct dc_debug_options debug_defaults_drv = { .disable_dcc = DCC_ENABLE, .disable_dpp_power_gate = true, .disable_hubp_power_gate = true, - .disable_clock_gate = true, + .disable_clock_gate = false, .disable_dsc_power_gate = true, .vsr_support = true, .performance_trace = false, diff --git a/drivers/gpu/drm/amd/display/dc/resource/dcn35/dcn35_resource.h b/drivers/gpu/drm/amd/display/dc/resource/dcn35/dcn35_resource.h index 99aea102e3f7..a51c4a9eaafe 100644 --- a/drivers/gpu/drm/amd/display/dc/resource/dcn35/dcn35_resource.h +++ b/drivers/gpu/drm/amd/display/dc/resource/dcn35/dcn35_resource.h @@ -166,6 +166,7 @@ struct resource_pool *dcn35_create_resource_pool( SR(MMHUBBUB_MEM_PWR_CNTL), \ SR(DCCG_GATE_DISABLE_CNTL), \ SR(DCCG_GATE_DISABLE_CNTL2), \ + SR(DCCG_GATE_DISABLE_CNTL4), \ SR(DCCG_GATE_DISABLE_CNTL5), \ SR(DCFCLK_CNTL),\ SR(DC_MEM_GLOBAL_PWR_REQ_CNTL), \ diff --git a/drivers/gpu/drm/amd/include/asic_reg/dcn/dcn_3_5_0_sh_mask.h b/drivers/gpu/drm/amd/include/asic_reg/dcn/dcn_3_5_0_sh_mask.h index b64664879211..fca72e2ec929 100644 --- a/drivers/gpu/drm/amd/include/asic_reg/dcn/dcn_3_5_0_sh_mask.h +++ b/drivers/gpu/drm/amd/include/asic_reg/dcn/dcn_3_5_0_sh_mask.h @@ -6220,12 +6220,20 @@ #define DCCG_GATE_DISABLE_CNTL4__PHYD_REFCLK_ROOT_GATE_DISABLE__SHIFT 0x3 #define DCCG_GATE_DISABLE_CNTL4__PHYE_REFCLK_ROOT_GATE_DISABLE__SHIFT 0x4 #define DCCG_GATE_DISABLE_CNTL4__HDMICHARCLK0_ROOT_GATE_DISABLE__SHIFT 0x11 +#define DCCG_GATE_DISABLE_CNTL4__DPIASYMCLK0_GATE_DISABLE__SHIFT 0x17 +#define DCCG_GATE_DISABLE_CNTL4__DPIASYMCLK1_GATE_DISABLE__SHIFT 0x18 +#define DCCG_GATE_DISABLE_CNTL4__DPIASYMCLK2_GATE_DISABLE__SHIFT 0x19 +#define DCCG_GATE_DISABLE_CNTL4__DPIASYMCLK3_GATE_DISABLE__SHIFT 0x1a #define DCCG_GATE_DISABLE_CNTL4__PHYA_REFCLK_ROOT_GATE_DISABLE_MASK 0x00000001L #define DCCG_GATE_DISABLE_CNTL4__PHYB_REFCLK_ROOT_GATE_DISABLE_MASK 0x00000002L #define DCCG_GATE_DISABLE_CNTL4__PHYC_REFCLK_ROOT_GATE_DISABLE_MASK 0x00000004L #define DCCG_GATE_DISABLE_CNTL4__PHYD_REFCLK_ROOT_GATE_DISABLE_MASK 0x00000008L #define DCCG_GATE_DISABLE_CNTL4__PHYE_REFCLK_ROOT_GATE_DISABLE_MASK 0x00000010L #define DCCG_GATE_DISABLE_CNTL4__HDMICHARCLK0_ROOT_GATE_DISABLE_MASK 0x00020000L +#define DCCG_GATE_DISABLE_CNTL4__DPIASYMCLK0_GATE_DISABLE_MASK 0x00800000L +#define DCCG_GATE_DISABLE_CNTL4__DPIASYMCLK1_GATE_DISABLE_MASK 0x01000000L +#define DCCG_GATE_DISABLE_CNTL4__DPIASYMCLK2_GATE_DISABLE_MASK 0x02000000L +#define DCCG_GATE_DISABLE_CNTL4__DPIASYMCLK3_GATE_DISABLE_MASK 0x04000000L #define DPSTREAMCLK_CNTL__DPSTREAMCLK0_SRC_SEL__SHIFT 0x0 #define DPSTREAMCLK_CNTL__DPSTREAMCLK0_EN__SHIFT 0x3 #define DPSTREAMCLK_CNTL__DPSTREAMCLK1_SRC_SEL__SHIFT 0x4 -- cgit From cc6201b773f12388c234aa10145322ccc429959e Mon Sep 17 00:00:00 2001 From: Duncan Ma Date: Tue, 31 Oct 2023 16:57:36 -0400 Subject: drm/amd/display: Add disable timeout option [WHY] Driver continues running whenever there is is timeout from smu or dmcub. It is difficult to track failure state when dcn, dc or dmcub changes on root failure. [HOW] Add disable_timeout option to halt driver whenever there is a failure in response. Reviewed-by: Charlene Liu Acked-by: Alex Hung Signed-off-by: Duncan Ma Tested-by: Daniel Wheeler Signed-off-by: Alex Deucher --- .../drm/amd/display/dc/clk_mgr/dcn35/dcn35_smu.c | 3 +++ drivers/gpu/drm/amd/display/dc/dc.h | 1 + drivers/gpu/drm/amd/display/dc/dc_dmub_srv.c | 29 +++++++++++++++++----- 3 files changed, 27 insertions(+), 6 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn35/dcn35_smu.c b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn35/dcn35_smu.c index b6b8c3ca1572..af0a0f292595 100644 --- a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn35/dcn35_smu.c +++ b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn35/dcn35_smu.c @@ -116,6 +116,9 @@ static uint32_t dcn35_smu_wait_for_response(struct clk_mgr_internal *clk_mgr, un msleep(delay_us/1000); else if (delay_us > 0) udelay(delay_us); + + if (clk_mgr->base.ctx->dc->debug.disable_timeout) + max_retries++; } while (max_retries--); return res_val; diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h index 9316b737a8ba..ae54ef6837f9 100644 --- a/drivers/gpu/drm/amd/display/dc/dc.h +++ b/drivers/gpu/drm/amd/display/dc/dc.h @@ -978,6 +978,7 @@ struct dc_debug_options { bool psp_disabled_wa; unsigned int ips2_eval_delay_us; unsigned int ips2_entry_delay_us; + bool disable_timeout; }; struct gpu_info_soc_bounding_box_v1_0; diff --git a/drivers/gpu/drm/amd/display/dc/dc_dmub_srv.c b/drivers/gpu/drm/amd/display/dc/dc_dmub_srv.c index 0e07699c1e83..53400cc05b5b 100644 --- a/drivers/gpu/drm/amd/display/dc/dc_dmub_srv.c +++ b/drivers/gpu/drm/amd/display/dc/dc_dmub_srv.c @@ -241,7 +241,12 @@ bool dc_dmub_srv_cmd_run_list(struct dc_dmub_srv *dc_dmub_srv, unsigned int coun // Wait for DMUB to process command if (wait_type != DM_DMUB_WAIT_TYPE_NO_WAIT) { - status = dmub_srv_wait_for_idle(dmub, 100000); + if (dc_dmub_srv->ctx->dc->debug.disable_timeout) { + do { + status = dmub_srv_wait_for_idle(dmub, 100000); + } while (status != DMUB_STATUS_OK); + } else + status = dmub_srv_wait_for_idle(dmub, 100000); if (status != DMUB_STATUS_OK) { DC_LOG_DEBUG("No reply for DMUB command: status=%d\n", status); @@ -1147,10 +1152,16 @@ bool dc_dmub_srv_is_hw_pwr_up(struct dc_dmub_srv *dc_dmub_srv, bool wait) return true; if (wait) { - status = dmub_srv_wait_for_hw_pwr_up(dc_dmub_srv->dmub, 500000); - if (status != DMUB_STATUS_OK) { - DC_ERROR("Error querying DMUB hw power up status: error=%d\n", status); - return false; + if (dc_dmub_srv->ctx->dc->debug.disable_timeout) { + do { + status = dmub_srv_wait_for_hw_pwr_up(dc_dmub_srv->dmub, 500000); + } while (status != DMUB_STATUS_OK); + } else { + status = dmub_srv_wait_for_hw_pwr_up(dc_dmub_srv->dmub, 500000); + if (status != DMUB_STATUS_OK) { + DC_ERROR("Error querying DMUB hw power up status: error=%d\n", status); + return false; + } } } else return dmub_srv_is_hw_pwr_up(dc_dmub_srv->dmub); @@ -1187,7 +1198,7 @@ void dc_dmub_srv_exit_low_power_state(const struct dc *dc) const uint32_t max_num_polls = 10000; uint32_t allow_state = 0; uint32_t commit_state = 0; - uint32_t i; + int i; if (dc->debug.dmcub_emulation) return; @@ -1220,6 +1231,9 @@ void dc_dmub_srv_exit_low_power_state(const struct dc *dc) break; udelay(1); + + if (dc->debug.disable_timeout) + i--; } ASSERT(i < max_num_polls); @@ -1242,6 +1256,9 @@ void dc_dmub_srv_exit_low_power_state(const struct dc *dc) break; udelay(1); + + if (dc->debug.disable_timeout) + i--; } ASSERT(i < max_num_polls); } -- cgit From c21a764a98cb59d673cad3da64f35f4dec951951 Mon Sep 17 00:00:00 2001 From: Krunoslav Kovac Date: Wed, 1 Nov 2023 15:59:56 -0400 Subject: drm/amd/display: Send PQ bit in AMD VSIF [WHY & HOW] PB9 bit 5 was added to signal PQ EOTF in AMD vendor specific infoframe. This change sets it when appropriate. Reviewed-by: Aric Cyr Acked-by: Alex Hung Signed-off-by: Krunoslav Kovac Tested-by: Daniel Wheeler Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/modules/freesync/freesync.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/amd/display/modules/freesync/freesync.c b/drivers/gpu/drm/amd/display/modules/freesync/freesync.c index ccecddafeb05..47296d155c3a 100644 --- a/drivers/gpu/drm/amd/display/modules/freesync/freesync.c +++ b/drivers/gpu/drm/amd/display/modules/freesync/freesync.c @@ -693,10 +693,12 @@ static void build_vrr_infopacket_fs2_data(enum color_transfer_func app_tf, if (app_tf != TRANSFER_FUNC_UNKNOWN) { infopacket->valid = true; - if (app_tf != TRANSFER_FUNC_PQ2084) { + if (app_tf == TRANSFER_FUNC_PQ2084) + infopacket->sb[9] |= 0x20; // PB9 = [Bit 5 = PQ EOTF Active] + else { infopacket->sb[6] |= 0x08; // PB6 = [Bit 3 = Native Color Active] if (app_tf == TRANSFER_FUNC_GAMMA_22) - infopacket->sb[9] |= 0x04; // PB6 = [Bit 2 = Gamma 2.2 EOTF Active] + infopacket->sb[9] |= 0x04; // PB9 = [Bit 2 = Gamma 2.2 EOTF Active] } } } -- cgit From c29085d29562990559163302d9e28d1e88223d90 Mon Sep 17 00:00:00 2001 From: Fangzhi Zuo Date: Mon, 30 Oct 2023 16:23:08 -0400 Subject: drm/amd/display: Enable DSC Flag in MST Mode Validation [WHY & HOW] When dsc is possible, MST mode validation includes: 1. if maximum dsc compression cannot fit into end to end bw, mode pruned 2. if native bw cannot fit into end to end bw, try to enabled dsc to see whether a feasible dsc config can be found 3. if native bw can fit into end to end bw, mode supported Reviewed-by: Wayne Lin Acked-by: Alex Hung Signed-off-by: Fangzhi Zuo Tested-by: Daniel Wheeler Signed-off-by: Alex Deucher --- .../amd/display/amdgpu_dm/amdgpu_dm_mst_types.c | 44 +++++++++++++--------- 1 file changed, 26 insertions(+), 18 deletions(-) diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c index ec87e31c6fe8..8d7d4024f285 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c @@ -1602,9 +1602,8 @@ enum dc_status dm_dp_mst_is_port_support_mode( struct dc_link_settings cur_link_settings; unsigned int end_to_end_bw_in_kbps = 0; unsigned int upper_link_bw_in_kbps = 0, down_link_bw_in_kbps = 0; - unsigned int max_compressed_bw_in_kbps = 0; struct dc_dsc_bw_range bw_range = {0}; - uint16_t full_pbn = aconnector->mst_output_port->full_pbn; + struct dc_dsc_config_options dsc_options = {0}; /* * Consider the case with the depth of the mst topology tree is equal or less than 2 @@ -1620,30 +1619,39 @@ enum dc_status dm_dp_mst_is_port_support_mode( (aconnector->mst_output_port->passthrough_aux || aconnector->dsc_aux == &aconnector->mst_output_port->aux)) { cur_link_settings = stream->link->verified_link_cap; + upper_link_bw_in_kbps = dc_link_bandwidth_kbps(aconnector->dc_link, &cur_link_settings); + down_link_bw_in_kbps = kbps_from_pbn(aconnector->mst_output_port->full_pbn); - upper_link_bw_in_kbps = dc_link_bandwidth_kbps(aconnector->dc_link, - &cur_link_settings); - down_link_bw_in_kbps = kbps_from_pbn(full_pbn); - - /* pick the bottleneck */ - end_to_end_bw_in_kbps = min(upper_link_bw_in_kbps, - down_link_bw_in_kbps); - - /* - * use the maximum dsc compression bandwidth as the required - * bandwidth for the mode - */ - max_compressed_bw_in_kbps = bw_range.min_kbps; + /* pick the end to end bw bottleneck */ + end_to_end_bw_in_kbps = min(upper_link_bw_in_kbps, down_link_bw_in_kbps); - if (end_to_end_bw_in_kbps < max_compressed_bw_in_kbps) { - DRM_DEBUG_DRIVER("Mode does not fit into DSC pass-through bandwidth validation\n"); + if (end_to_end_bw_in_kbps < bw_range.min_kbps) { + DRM_DEBUG_DRIVER("maximum dsc compression cannot fit into end-to-end bandwidth\n"); return DC_FAIL_BANDWIDTH_VALIDATE; } + + if (end_to_end_bw_in_kbps < bw_range.stream_kbps) { + dc_dsc_get_default_config_option(stream->link->dc, &dsc_options); + dsc_options.max_target_bpp_limit_override_x16 = aconnector->base.display_info.max_dsc_bpp * 16; + if (dc_dsc_compute_config(stream->sink->ctx->dc->res_pool->dscs[0], + &stream->sink->dsc_caps.dsc_dec_caps, + &dsc_options, + end_to_end_bw_in_kbps, + &stream->timing, + dc_link_get_highest_encoding_format(stream->link), + &stream->timing.dsc_cfg)) { + stream->timing.flags.DSC = 1; + DRM_DEBUG_DRIVER("end-to-end bandwidth require dsc and dsc config found\n"); + } else { + DRM_DEBUG_DRIVER("end-to-end bandwidth require dsc but dsc config not found\n"); + return DC_FAIL_BANDWIDTH_VALIDATE; + } + } } else { /* check if mode could be supported within full_pbn */ bpp = convert_dc_color_depth_into_bpc(stream->timing.display_color_depth) * 3; pbn = drm_dp_calc_pbn_mode(stream->timing.pix_clk_100hz / 10, bpp, false); - if (pbn > full_pbn) + if (pbn > aconnector->mst_output_port->full_pbn) return DC_FAIL_BANDWIDTH_VALIDATE; } -- cgit From ed4ae8f77f2c4ff05244db99330d1eff828d9f7d Mon Sep 17 00:00:00 2001 From: Anthony Koo Date: Sat, 4 Nov 2023 01:53:13 -0400 Subject: drm/amd/display: Add new command to disable replay timing resync [WHY & HOW] Add new command to disable replay timing resync Acked-by: Alex Hung Signed-off-by: Anthony Koo Tested-by: Daniel Wheeler Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dmub/inc/dmub_cmd.h | 41 +++++++++++++++++++++++++ 1 file changed, 41 insertions(+) diff --git a/drivers/gpu/drm/amd/display/dmub/inc/dmub_cmd.h b/drivers/gpu/drm/amd/display/dmub/inc/dmub_cmd.h index aa6e6923afed..55573083bc31 100644 --- a/drivers/gpu/drm/amd/display/dmub/inc/dmub_cmd.h +++ b/drivers/gpu/drm/amd/display/dmub/inc/dmub_cmd.h @@ -2876,6 +2876,10 @@ enum dmub_cmd_replay_type { * Set power opt and coasting vtotal. */ DMUB_CMD__REPLAY_SET_POWER_OPT_AND_COASTING_VTOTAL = 4, + /** + * Set disabled iiming sync. + */ + DMUB_CMD__REPLAY_SET_TIMING_SYNC_SUPPORTED = 5, }; /** @@ -3038,6 +3042,27 @@ struct dmub_cmd_replay_set_power_opt_data { uint32_t power_opt; }; +/** + * Data passed from driver to FW in a DMUB_CMD__REPLAY_SET_TIMING_SYNC_SUPPORTED command. + */ +struct dmub_cmd_replay_set_timing_sync_data { + /** + * Panel Instance. + * Panel isntance to identify which replay_state to use + * Currently the support is only for 0 or 1 + */ + uint8_t panel_inst; + + /** + * Explicit padding to 4 byte boundary. + */ + uint8_t pad[3]; + /** + * REPLAY set_timing_sync + */ + bool timing_sync_supported; +}; + /** * Definition of a DMUB_CMD__SET_REPLAY_POWER_OPT command. */ @@ -3104,6 +3129,20 @@ struct dmub_rb_cmd_replay_set_power_opt_and_coasting_vtotal { struct dmub_cmd_replay_set_coasting_vtotal_data replay_set_coasting_vtotal_data; }; +/** + * Definition of a DMUB_CMD__REPLAY_SET_TIMING_SYNC_SUPPORTED command. + */ +struct dmub_rb_cmd_replay_set_timing_sync { + /** + * Command header. + */ + struct dmub_cmd_header header; + /** + * Definition of DMUB_CMD__REPLAY_SET_TIMING_SYNC_SUPPORTED command. + */ + struct dmub_cmd_replay_set_timing_sync_data replay_set_timing_sync_data; +}; + /** * Set of HW components that can be locked. * @@ -4237,6 +4276,8 @@ union dmub_rb_cmd { * Definition of a DMUB_CMD__REPLAY_SET_POWER_OPT_AND_COASTING_VTOTAL command. */ struct dmub_rb_cmd_replay_set_power_opt_and_coasting_vtotal replay_set_power_opt_and_coasting_vtotal; + + struct dmub_rb_cmd_replay_set_timing_sync replay_set_timing_sync; }; /** -- cgit From 8a2553d5c7ade00d1b508bbd418d5c4803c12fdd Mon Sep 17 00:00:00 2001 From: Rodrigo Siqueira Date: Mon, 6 Nov 2023 19:30:51 -0700 Subject: drm/amd/display: Add missing chips for HDCP [WHAT] Add missing HDCP ID in the message id enum. Acked-by: Alex Hung Signed-off-by: Rodrigo Siqueira Tested-by: Daniel Wheeler Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/include/hdcp_msg_types.h | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/drivers/gpu/drm/amd/display/include/hdcp_msg_types.h b/drivers/gpu/drm/amd/display/include/hdcp_msg_types.h index 42229b4effdc..eced9ad91f1d 100644 --- a/drivers/gpu/drm/amd/display/include/hdcp_msg_types.h +++ b/drivers/gpu/drm/amd/display/include/hdcp_msg_types.h @@ -69,6 +69,11 @@ enum hdcp_message_id { HDCP_MESSAGE_ID_READ_RXSTATUS, HDCP_MESSAGE_ID_WRITE_CONTENT_STREAM_TYPE, + /* PS175 chip */ + + HDCP_MESSAGE_ID_WRITE_PS175_CMD, + HDCP_MESSAGE_ID_READ_PS175_RSP, + HDCP_MESSAGE_ID_MAX }; -- cgit From 466a7d115326ece682c2b60d1c77d1d0b9010b4f Mon Sep 17 00:00:00 2001 From: Mario Limonciello Date: Fri, 10 Nov 2023 16:34:51 -0600 Subject: drm/amd: Use the first non-dGPU PCI device for BW limits When bandwidth limits are looked up using pcie_bandwidth_available() virtual links such as USB4 are analyzed which might not represent the real speed. Furthermore devices may change speeds autonomously which may introduce conditional variation to the results reported in the status registers. Instead look at the capabilities of first PCI device outside of dGPU to decide upper limits that the dGPU will work at. For eGPU this effectively means that it will use the speed of the link partner. Link: https://gitlab.freedesktop.org/drm/amd/-/issues/2925#note_2145860 Link: https://www.usb.org/document-library/usb4r-specification-v20 USB4 V2 with Errata and ECN through June 2023 Section 11.2.1 Reviewed-by: Lijo Lazar Signed-off-by: Mario Limonciello Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_device.c | 37 ++++++++++++++++++++++++++++-- 1 file changed, 35 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c index 151f8b950b72..ec3bf949ee2f 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c @@ -5737,6 +5737,39 @@ recover_end: return r; } +/** + * amdgpu_device_partner_bandwidth - find the bandwidth of appropriate partner + * + * @adev: amdgpu_device pointer + * @speed: pointer to the speed of the link + * @width: pointer to the width of the link + * + * Evaluate the hierarchy to find the speed and bandwidth capabilities of the + * first physical partner to an AMD dGPU. + * This will exclude any virtual switches and links. + */ +static void amdgpu_device_partner_bandwidth(struct amdgpu_device *adev, + enum pci_bus_speed *speed, + enum pcie_link_width *width) +{ + struct pci_dev *parent = adev->pdev; + + if (!speed || !width) + return; + + *speed = PCI_SPEED_UNKNOWN; + *width = PCIE_LNK_WIDTH_UNKNOWN; + + while ((parent = pci_upstream_bridge(parent))) { + /* skip upstream/downstream switches internal to dGPU*/ + if (parent->vendor == PCI_VENDOR_ID_ATI) + continue; + *speed = pcie_get_speed_cap(parent); + *width = pcie_get_width_cap(parent); + break; + } +} + /** * amdgpu_device_get_pcie_info - fence pcie info about the PCIE slot * @@ -5770,8 +5803,8 @@ static void amdgpu_device_get_pcie_info(struct amdgpu_device *adev) if (adev->pm.pcie_gen_mask && adev->pm.pcie_mlw_mask) return; - pcie_bandwidth_available(adev->pdev, NULL, - &platform_speed_cap, &platform_link_width); + amdgpu_device_partner_bandwidth(adev, &platform_speed_cap, + &platform_link_width); if (adev->pm.pcie_gen_mask == 0) { /* asic caps */ -- cgit From d9b3a066dfcd3fe50b4dc561d8510c43c0ad8863 Mon Sep 17 00:00:00 2001 From: Mario Limonciello Date: Fri, 10 Nov 2023 16:34:52 -0600 Subject: drm/amd: Exclude dGPUs in eGPU enclosures from DPM quirks The PCIe speed capabilities advertised by a USB4 or TBT3 link are limited to PCIe gen 1 per the USB4 spec. In reality the speed will change dynamically based on fabric conditions and other traffic. DPM is disabled when dGPUs are connected directly to Intel hosts since the PCIe root port isn't able to handle dynamic speed switching. As this limitation is specifically for PCIe root ports in the SoC, don't apply it when connected to an eGPU enclosure connected to an Intel host. Link: https://gitlab.freedesktop.org/drm/amd/-/issues/2885 Reviewed-by: Lijo Lazar Signed-off-by: Mario Limonciello Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_device.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c index ec3bf949ee2f..b5edf40b5d03 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c @@ -1551,11 +1551,15 @@ bool amdgpu_device_seamless_boot_supported(struct amdgpu_device *adev) * https://edc.intel.com/content/www/us/en/design/products/platforms/details/raptor-lake-s/13th-generation-core-processors-datasheet-volume-1-of-2/005/pci-express-support/ * https://gitlab.freedesktop.org/drm/amd/-/issues/2663 */ -static bool amdgpu_device_pcie_dynamic_switching_supported(void) +static bool amdgpu_device_pcie_dynamic_switching_supported(struct amdgpu_device *adev) { #if IS_ENABLED(CONFIG_X86) struct cpuinfo_x86 *c = &cpu_data(0); + /* eGPU change speeds based on USB4 fabric conditions */ + if (dev_is_removable(adev->dev)) + return true; + if (c->x86_vendor == X86_VENDOR_INTEL) return false; #endif @@ -2395,7 +2399,7 @@ static int amdgpu_device_ip_early_init(struct amdgpu_device *adev) adev->pm.pp_feature &= ~PP_GFXOFF_MASK; if (amdgpu_sriov_vf(adev) && adev->asic_type == CHIP_SIENNA_CICHLID) adev->pm.pp_feature &= ~PP_OVERDRIVE_MASK; - if (!amdgpu_device_pcie_dynamic_switching_supported()) + if (!amdgpu_device_pcie_dynamic_switching_supported(adev)) adev->pm.pp_feature &= ~PP_PCIE_DPM_MASK; total = true; -- cgit From 59e4db5375f587954eb779ac9c7888a6c81c306b Mon Sep 17 00:00:00 2001 From: Aric Cyr Date: Sun, 5 Nov 2023 20:22:06 -0500 Subject: drm/amd/display: Promote DC to 3.2.260 - Add missing chips for HDCP - Add new command to disable replay timing resync - Fix encoder disable logic - Enable DSC Flag in MST Mode Validation - Change the DMCUB mailbox memory location from FB to inbox - Add disable timeout option - Negate IPS allow and commit bits - Enable DCN clock gating for DCN35 - Prefer currently used OTG master when acquiring free pipe - Try to acquire a free OTG master not used in cur ctx first - Clear dpcd_sink_ext_caps if not set - Enable fast plane updates on DCN3.2 and above - Add null checks for 8K60 lightup - Refactor resource into component directory - Fix DSC not Enabled on Direct MST Sink - Guard against invalid RPTR/WPTR being set - Enable CM low mem power optimization - Fix a debugfs null pointer error Acked-by: Alex Hung Signed-off-by: Aric Cyr Tested-by: Daniel Wheeler Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dc.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h index ae54ef6837f9..541e781267b9 100644 --- a/drivers/gpu/drm/amd/display/dc/dc.h +++ b/drivers/gpu/drm/amd/display/dc/dc.h @@ -49,7 +49,7 @@ struct aux_payload; struct set_config_cmd_payload; struct dmub_notification; -#define DC_VER "3.2.259" +#define DC_VER "3.2.260" #define MAX_SURFACES 3 #define MAX_PLANES 6 -- cgit From 75fb313c55fa102f973c440f55dc63ffc61f3b54 Mon Sep 17 00:00:00 2001 From: Shiwu Zhang Date: Tue, 31 Oct 2023 12:32:54 +0800 Subject: drm/amdgpu: expose the connected port num info through sysfs By catting the xgmi_port_num sysfs node, it prints out the info in the format of : -> : for one xgmi link. For example, in case of 4 sockets fully and evenly connected setup, it would be like as below for the first node in the hive. 01:02 -> 02:03 01:03 -> 02:02 01:07 -> 03:04 01:04 -> 03:07 01:06 -> 04:05 01:05 -> 04:06 Based on the fact that there is two xgmi links between each socket pair, "01:02 -> 02:03" means that the current socket in question use the port 2 to connect with port 3 of the second node in the hive and so on. v2: print out the src/dst node id for each xgmi link (lijo) v3: replace the current_node++ with +1 to align with dst node (le) and use the dev_err instead of pr_err (lijo) v4: fix checkpatch warning (alex) Signed-off-by: Shiwu Zhang Acked-by: Lijo Lazar Reviewed-by: Le Ma Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_xgmi.c | 44 ++++++++++++++++++++++++++++++++ 1 file changed, 44 insertions(+) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_xgmi.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_xgmi.c index bd20cb3b9819..44d8c1a11e1b 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_xgmi.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_xgmi.c @@ -413,6 +413,38 @@ static ssize_t amdgpu_xgmi_show_num_links(struct device *dev, return sysfs_emit(buf, "%s\n", buf); } +static ssize_t amdgpu_xgmi_show_connected_port_num(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct drm_device *ddev = dev_get_drvdata(dev); + struct amdgpu_device *adev = drm_to_adev(ddev); + struct psp_xgmi_topology_info *top = &adev->psp.xgmi_context.top_info; + int i, j, size = 0; + int current_node; + /* + * get the node id in the sysfs for the current socket and show + * it in the port num info output in the sysfs for easy reading. + * it is NOT the one retrieved from xgmi ta. + */ + for (i = 0; i < top->num_nodes; i++) { + if (top->nodes[i].node_id == adev->gmc.xgmi.node_id) { + current_node = i; + break; + } + } + + for (i = 0; i < top->num_nodes; i++) { + for (j = 0; j < top->nodes[i].num_links; j++) + /* node id in sysfs starts from 1 rather than 0 so +1 here */ + size += sysfs_emit_at(buf, size, "%02x:%02x -> %02x:%02x\n", current_node + 1, + top->nodes[i].port_num[j].src_xgmi_port_num, i + 1, + top->nodes[i].port_num[j].dst_xgmi_port_num); + } + + return size; +} + #define AMDGPU_XGMI_SET_FICAA(o) ((o) | 0x456801) static ssize_t amdgpu_xgmi_show_error(struct device *dev, struct device_attribute *attr, @@ -452,6 +484,7 @@ static DEVICE_ATTR(xgmi_physical_id, 0444, amdgpu_xgmi_show_physical_id, NULL); static DEVICE_ATTR(xgmi_error, S_IRUGO, amdgpu_xgmi_show_error, NULL); static DEVICE_ATTR(xgmi_num_hops, S_IRUGO, amdgpu_xgmi_show_num_hops, NULL); static DEVICE_ATTR(xgmi_num_links, S_IRUGO, amdgpu_xgmi_show_num_links, NULL); +static DEVICE_ATTR(xgmi_port_num, S_IRUGO, amdgpu_xgmi_show_connected_port_num, NULL); static int amdgpu_xgmi_sysfs_add_dev_info(struct amdgpu_device *adev, struct amdgpu_hive_info *hive) @@ -487,6 +520,13 @@ static int amdgpu_xgmi_sysfs_add_dev_info(struct amdgpu_device *adev, if (ret) pr_err("failed to create xgmi_num_links\n"); + /* Create xgmi port num file if supported */ + if (adev->psp.xgmi_context.xgmi_ta_caps & EXTEND_PEER_LINK_INFO_CMD_FLAG) { + ret = device_create_file(adev->dev, &dev_attr_xgmi_port_num); + if (ret) + dev_err(adev->dev, "failed to create xgmi_port_num\n"); + } + /* Create sysfs link to hive info folder on the first device */ if (hive->kobj.parent != (&adev->dev->kobj)) { ret = sysfs_create_link(&adev->dev->kobj, &hive->kobj, @@ -517,6 +557,8 @@ remove_file: device_remove_file(adev->dev, &dev_attr_xgmi_error); device_remove_file(adev->dev, &dev_attr_xgmi_num_hops); device_remove_file(adev->dev, &dev_attr_xgmi_num_links); + if (adev->psp.xgmi_context.xgmi_ta_caps & EXTEND_PEER_LINK_INFO_CMD_FLAG) + device_remove_file(adev->dev, &dev_attr_xgmi_port_num); success: return ret; @@ -533,6 +575,8 @@ static void amdgpu_xgmi_sysfs_rem_dev_info(struct amdgpu_device *adev, device_remove_file(adev->dev, &dev_attr_xgmi_error); device_remove_file(adev->dev, &dev_attr_xgmi_num_hops); device_remove_file(adev->dev, &dev_attr_xgmi_num_links); + if (adev->psp.xgmi_context.xgmi_ta_caps & EXTEND_PEER_LINK_INFO_CMD_FLAG) + device_remove_file(adev->dev, &dev_attr_xgmi_port_num); if (hive->kobj.parent != (&adev->dev->kobj)) sysfs_remove_link(&adev->dev->kobj,"xgmi_hive_info"); -- cgit From a3cc7dbe9957f856b84a504687a85e22e02a49db Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Thu, 28 Sep 2023 15:18:16 +0530 Subject: drm/amdgpu: add pm metrics structure definition Define the pm metrics structures to be exposed via sysfs. Signed-off-by: Alex Deucher Signed-off-by: Lijo Lazar Reviewed-by: Hawking Zhang Reviewed-by: Yang Wang --- drivers/gpu/drm/amd/include/kgd_pp_interface.h | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/drivers/gpu/drm/amd/include/kgd_pp_interface.h b/drivers/gpu/drm/amd/include/kgd_pp_interface.h index b14231f470dc..f9c438d16c56 100644 --- a/drivers/gpu/drm/amd/include/kgd_pp_interface.h +++ b/drivers/gpu/drm/amd/include/kgd_pp_interface.h @@ -1127,4 +1127,19 @@ struct gpu_metrics_v3_0 { /* Metrics table alpha filter time constant [us] */ uint32_t time_filter_alphavalue; }; + +struct amdgpu_pmmetrics_header { + uint16_t structure_size; + uint16_t pad; + uint32_t mp1_ip_discovery_version; + uint32_t pmfw_version; + uint32_t pmmetrics_version; +}; + +struct amdgpu_pm_metrics { + struct amdgpu_pmmetrics_header common_header; + + uint8_t data[]; +}; + #endif -- cgit From 425285d39afddaf4a9dab36045b816af0cc3e400 Mon Sep 17 00:00:00 2001 From: Prike Liang Date: Thu, 9 Nov 2023 11:37:18 +0800 Subject: drm/amdgpu: add amdgpu runpm usage trace for separate funcs Add trace for amdgpu runpm separate funcs usage and this will help debugging on the case of runpm usage missed to dereference. In the normal case the runpm usage count referred by one kind of functionality pairwise and usage should be changed from 1 to 0, otherwise there will be an issue in the amdgpu runpm usage dereference. Signed-off-by: Prike Liang Acked-by: Alex Deucher Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_dma_buf.c | 4 ++++ drivers/gpu/drm/amd/amdgpu/amdgpu_fence.c | 2 ++ drivers/gpu/drm/amd/amdgpu/amdgpu_trace.h | 15 +++++++++++++++ 3 files changed, 21 insertions(+) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_dma_buf.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_dma_buf.c index e7e87a3b2601..decbbe3d4f06 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_dma_buf.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_dma_buf.c @@ -42,6 +42,7 @@ #include #include #include +#include "amdgpu_trace.h" /** * amdgpu_dma_buf_attach - &dma_buf_ops.attach implementation @@ -63,6 +64,7 @@ static int amdgpu_dma_buf_attach(struct dma_buf *dmabuf, attach->peer2peer = false; r = pm_runtime_get_sync(adev_to_drm(adev)->dev); + trace_amdgpu_runpm_reference_dumps(1, __func__); if (r < 0) goto out; @@ -70,6 +72,7 @@ static int amdgpu_dma_buf_attach(struct dma_buf *dmabuf, out: pm_runtime_put_autosuspend(adev_to_drm(adev)->dev); + trace_amdgpu_runpm_reference_dumps(0, __func__); return r; } @@ -90,6 +93,7 @@ static void amdgpu_dma_buf_detach(struct dma_buf *dmabuf, pm_runtime_mark_last_busy(adev_to_drm(adev)->dev); pm_runtime_put_autosuspend(adev_to_drm(adev)->dev); + trace_amdgpu_runpm_reference_dumps(0, __func__); } /** diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_fence.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_fence.c index dc230212746a..70bff8cecfda 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_fence.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_fence.c @@ -183,6 +183,7 @@ int amdgpu_fence_emit(struct amdgpu_ring *ring, struct dma_fence **f, struct amd amdgpu_ring_emit_fence(ring, ring->fence_drv.gpu_addr, seq, flags | AMDGPU_FENCE_FLAG_INT); pm_runtime_get_noresume(adev_to_drm(adev)->dev); + trace_amdgpu_runpm_reference_dumps(1, __func__); ptr = &ring->fence_drv.fences[seq & ring->fence_drv.num_fences_mask]; if (unlikely(rcu_dereference_protected(*ptr, 1))) { struct dma_fence *old; @@ -310,6 +311,7 @@ bool amdgpu_fence_process(struct amdgpu_ring *ring) dma_fence_put(fence); pm_runtime_mark_last_busy(adev_to_drm(adev)->dev); pm_runtime_put_autosuspend(adev_to_drm(adev)->dev); + trace_amdgpu_runpm_reference_dumps(0, __func__); } while (last_seq != seq); return true; diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_trace.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_trace.h index 2fd1bfb35916..f539b1d00234 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_trace.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_trace.h @@ -554,6 +554,21 @@ TRACE_EVENT(amdgpu_reset_reg_dumps, __entry->value) ); +TRACE_EVENT(amdgpu_runpm_reference_dumps, + TP_PROTO(uint32_t index, const char *func), + TP_ARGS(index, func), + TP_STRUCT__entry( + __field(uint32_t, index) + __string(func, func) + ), + TP_fast_assign( + __entry->index = index; + __assign_str(func, func); + ), + TP_printk("amdgpu runpm reference dump 0x%x: 0x%s\n", + __entry->index, + __get_str(func)) +); #undef AMDGPU_JOB_GET_TIMELINE_NAME #endif -- cgit From 699d392903c3cebb7d2a2a3505ec9047c419dcd7 Mon Sep 17 00:00:00 2001 From: Srinivasan Shanmugam Date: Sun, 12 Nov 2023 10:09:44 +0530 Subject: drm/amdgpu: Add function parameter 'xcc_mask' not described in 'amdgpu_vm_flush_compute_tlb' MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fixes the below: drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c:1373: warning: Function parameter or member 'xcc_mask' not described in 'amdgpu_vm_flush_compute_tlb' Cc: Felix Kuehling Cc: Christian König Cc: Alex Deucher Cc: "Pan, Xinhui" Signed-off-by: Srinivasan Shanmugam Reviewed-by: Christian König Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c index d59154ddaaed..7da71b6a9dc6 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c @@ -1443,6 +1443,7 @@ int amdgpu_vm_handle_moved(struct amdgpu_device *adev, * @adev: amdgpu_device pointer * @vm: requested vm * @flush_type: flush type + * @xcc_mask: mask of XCCs that belong to the compute partition in need of a TLB flush. * * Flush TLB if needed for a compute VM. * -- cgit From 613ecd6563d2716192e69624105fe1939d104663 Mon Sep 17 00:00:00 2001 From: André Almeida Date: Fri, 10 Nov 2023 12:23:28 -0500 Subject: drm/amd: Document device reset methods MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Document what each amdgpu driver reset method does. Signed-off-by: André Almeida Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu.h | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu.h b/drivers/gpu/drm/amd/amdgpu/amdgpu.h index 4d100f8d75bf..ea2656bd714f 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu.h @@ -508,6 +508,31 @@ struct amdgpu_allowed_register_entry { bool grbm_indexed; }; +/** + * enum amd_reset_method - Methods for resetting AMD GPU devices + * + * @AMD_RESET_METHOD_NONE: The device will not be reset. + * @AMD_RESET_LEGACY: Method reserved for SI, CIK and VI ASICs. + * @AMD_RESET_MODE0: Reset the entire ASIC. Not currently available for the + * any device. + * @AMD_RESET_MODE1: Resets all IP blocks on the ASIC (SDMA, GFX, VCN, etc.) + * individually. Suitable only for some discrete GPU, not + * available for all ASICs. + * @AMD_RESET_MODE2: Resets a lesser level of IPs compared to MODE1. Which IPs + * are reset depends on the ASIC. Notably doesn't reset IPs + * shared with the CPU on APUs or the memory controllers (so + * VRAM is not lost). Not available on all ASICs. + * @AMD_RESET_BACO: BACO (Bus Alive, Chip Off) method powers off and on the card + * but without powering off the PCI bus. Suitable only for + * discrete GPUs. + * @AMD_RESET_PCI: Does a full bus reset using core Linux subsystem PCI reset + * and does a secondary bus reset or FLR, depending on what the + * underlying hardware supports. + * + * Methods available for AMD GPU driver for resetting the device. Not all + * methods are suitable for every device. User can override the method using + * module parameter `reset_method`. + */ enum amd_reset_method { AMD_RESET_METHOD_NONE = -1, AMD_RESET_METHOD_LEGACY = 0, -- cgit From 534eee82356c220649dc9c2ea90099f39fb1cb62 Mon Sep 17 00:00:00 2001 From: Srinivasan Shanmugam Date: Sun, 12 Nov 2023 09:30:51 +0530 Subject: drm/amd/display: Remove redundant DRM device struct in amdgpu_dm_, mst_types.c Declaration of 'struct drm_device *dev' is redundant, as 'connector->dev' & 'dev_get_drvdata(kdev)' can be directly passed to 'drm_to_adev', without any intermediate DRM device 'dev' variable Cc: Roman Li Cc: Hamza Mahfooz Cc: Harry Wentland Cc: Rodrigo Siqueira Cc: Aurabindo Pillai Cc: Alex Deucher Signed-off-by: Srinivasan Shanmugam Reviewed-by: Roman Li Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 9 +++------ drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c | 3 +-- 2 files changed, 4 insertions(+), 8 deletions(-) diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c index ee97814ebd99..ba3f7b232a16 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -894,8 +894,7 @@ static int dm_early_init(void *handle); /* Allocate memory for FBC compressed data */ static void amdgpu_dm_fbc_init(struct drm_connector *connector) { - struct drm_device *dev = connector->dev; - struct amdgpu_device *adev = drm_to_adev(dev); + struct amdgpu_device *adev = drm_to_adev(connector->dev); struct dm_compressor_info *compressor = &adev->dm.compressor; struct amdgpu_dm_connector *aconn = to_amdgpu_dm_connector(connector); struct drm_display_mode *mode; @@ -989,8 +988,7 @@ static int amdgpu_dm_audio_component_bind(struct device *kdev, static void amdgpu_dm_audio_component_unbind(struct device *kdev, struct device *hda_kdev, void *data) { - struct drm_device *dev = dev_get_drvdata(kdev); - struct amdgpu_device *adev = drm_to_adev(dev); + struct amdgpu_device *adev = drm_to_adev(dev_get_drvdata(kdev)); struct drm_audio_component *acomp = data; acomp->ops = NULL; @@ -10788,8 +10786,7 @@ void amdgpu_dm_update_freesync_caps(struct drm_connector *connector, struct dm_connector_state *dm_con_state = NULL; struct dc_sink *sink; - struct drm_device *dev = connector->dev; - struct amdgpu_device *adev = drm_to_adev(dev); + struct amdgpu_device *adev = drm_to_adev(connector->dev); struct amdgpu_hdmi_vsdb_info vsdb_info = {0}; bool freesync_capable = false; enum adaptive_sync_type as_type = ADAPTIVE_SYNC_TYPE_NONE; diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c index 8d7d4024f285..a6995688d7ad 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c @@ -424,8 +424,7 @@ dm_mst_atomic_best_encoder(struct drm_connector *connector, { struct drm_connector_state *connector_state = drm_atomic_get_new_connector_state(state, connector); - struct drm_device *dev = connector->dev; - struct amdgpu_device *adev = drm_to_adev(dev); + struct amdgpu_device *adev = drm_to_adev(connector->dev); struct amdgpu_crtc *acrtc = to_amdgpu_crtc(connector_state->crtc); return &adev->dm.mst_encoders[acrtc->crtc_id].base; -- cgit From 12c2d3b5f5bc4ecb470a4bc06424914c145e8c03 Mon Sep 17 00:00:00 2001 From: Lijo Lazar Date: Fri, 29 Sep 2023 10:51:02 +0530 Subject: drm/amd/pm: Add support to fetch pm metrics sample Add API support to fetch a snapshot of power management metrics from PMFW. Signed-off-by: Lijo Lazar Reviewed-by: Hawking Zhang Reviewed-by: Yang Wang Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/include/kgd_pp_interface.h | 1 + drivers/gpu/drm/amd/pm/amdgpu_dpm.c | 17 +++++++++++++++++ drivers/gpu/drm/amd/pm/inc/amdgpu_dpm.h | 12 ++++++++++++ drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c | 15 +++++++++++++++ drivers/gpu/drm/amd/pm/swsmu/inc/amdgpu_smu.h | 10 ++++++++++ drivers/gpu/drm/amd/pm/swsmu/inc/smu_types.h | 3 ++- 6 files changed, 57 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/include/kgd_pp_interface.h b/drivers/gpu/drm/amd/include/kgd_pp_interface.h index f9c438d16c56..6a1d31e8fdd1 100644 --- a/drivers/gpu/drm/amd/include/kgd_pp_interface.h +++ b/drivers/gpu/drm/amd/include/kgd_pp_interface.h @@ -431,6 +431,7 @@ struct amd_pm_funcs { int (*set_df_cstate)(void *handle, enum pp_df_cstate state); int (*set_xgmi_pstate)(void *handle, uint32_t pstate); ssize_t (*get_gpu_metrics)(void *handle, void **table); + ssize_t (*get_pm_metrics)(void *handle, void *pmmetrics, size_t size); int (*set_watermarks_for_clock_ranges)(void *handle, struct pp_smu_wm_range_sets *ranges); int (*display_disable_memory_clock_switch)(void *handle, diff --git a/drivers/gpu/drm/amd/pm/amdgpu_dpm.c b/drivers/gpu/drm/amd/pm/amdgpu_dpm.c index 1ae3b81548fa..4717884a2bc4 100644 --- a/drivers/gpu/drm/amd/pm/amdgpu_dpm.c +++ b/drivers/gpu/drm/amd/pm/amdgpu_dpm.c @@ -1299,6 +1299,23 @@ int amdgpu_dpm_get_gpu_metrics(struct amdgpu_device *adev, void **table) return ret; } +ssize_t amdgpu_dpm_get_pm_metrics(struct amdgpu_device *adev, void *pm_metrics, + size_t size) +{ + const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs; + int ret = 0; + + if (!pp_funcs->get_pm_metrics) + return -EOPNOTSUPP; + + mutex_lock(&adev->pm.mutex); + ret = pp_funcs->get_pm_metrics(adev->powerplay.pp_handle, pm_metrics, + size); + mutex_unlock(&adev->pm.mutex); + + return ret; +} + int amdgpu_dpm_get_fan_control_mode(struct amdgpu_device *adev, uint32_t *fan_mode) { diff --git a/drivers/gpu/drm/amd/pm/inc/amdgpu_dpm.h b/drivers/gpu/drm/amd/pm/inc/amdgpu_dpm.h index feccd2a7120d..9b3fef5474b1 100644 --- a/drivers/gpu/drm/amd/pm/inc/amdgpu_dpm.h +++ b/drivers/gpu/drm/amd/pm/inc/amdgpu_dpm.h @@ -511,6 +511,18 @@ int amdgpu_dpm_get_power_profile_mode(struct amdgpu_device *adev, int amdgpu_dpm_set_power_profile_mode(struct amdgpu_device *adev, long *input, uint32_t size); int amdgpu_dpm_get_gpu_metrics(struct amdgpu_device *adev, void **table); + +/** + * @get_pm_metrics: Get one snapshot of power management metrics from PMFW. The + * sample is copied to pm_metrics buffer. It's expected to be allocated by the + * caller and size of the allocated buffer is passed. Max size expected for a + * metrics sample is 4096 bytes. + * + * Return: Actual size of the metrics sample + */ +ssize_t amdgpu_dpm_get_pm_metrics(struct amdgpu_device *adev, void *pm_metrics, + size_t size); + int amdgpu_dpm_get_fan_control_mode(struct amdgpu_device *adev, uint32_t *fan_mode); int amdgpu_dpm_set_fan_speed_pwm(struct amdgpu_device *adev, diff --git a/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c b/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c index 37c2605f9b35..930e7e3532ad 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c +++ b/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c @@ -3189,6 +3189,20 @@ static ssize_t smu_sys_get_gpu_metrics(void *handle, void **table) return smu->ppt_funcs->get_gpu_metrics(smu, table); } +static ssize_t smu_sys_get_pm_metrics(void *handle, void *pm_metrics, + size_t size) +{ + struct smu_context *smu = handle; + + if (!smu->pm_enabled || !smu->adev->pm.dpm_enabled) + return -EOPNOTSUPP; + + if (!smu->ppt_funcs->get_pm_metrics) + return -EOPNOTSUPP; + + return smu->ppt_funcs->get_pm_metrics(smu, pm_metrics, size); +} + static int smu_enable_mgpu_fan_boost(void *handle) { struct smu_context *smu = handle; @@ -3330,6 +3344,7 @@ static const struct amd_pm_funcs swsmu_pm_funcs = { .set_df_cstate = smu_set_df_cstate, .set_xgmi_pstate = smu_set_xgmi_pstate, .get_gpu_metrics = smu_sys_get_gpu_metrics, + .get_pm_metrics = smu_sys_get_pm_metrics, .set_watermarks_for_clock_ranges = smu_set_watermarks_for_clock_ranges, .display_disable_memory_clock_switch = smu_display_disable_memory_clock_switch, .get_max_sustainable_clocks_by_dc = smu_get_max_sustainable_clocks_by_dc, diff --git a/drivers/gpu/drm/amd/pm/swsmu/inc/amdgpu_smu.h b/drivers/gpu/drm/amd/pm/swsmu/inc/amdgpu_smu.h index 8def291b18bc..32600ba74bf1 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/inc/amdgpu_smu.h +++ b/drivers/gpu/drm/amd/pm/swsmu/inc/amdgpu_smu.h @@ -253,6 +253,7 @@ struct smu_table { uint64_t mc_address; void *cpu_addr; struct amdgpu_bo *bo; + uint32_t version; }; enum smu_perf_level_designation { @@ -1252,6 +1253,15 @@ struct pptable_funcs { */ ssize_t (*get_gpu_metrics)(struct smu_context *smu, void **table); + /** + * @get_pm_metrics: Get one snapshot of power management metrics from + * PMFW. + * + * Return: Size of the metrics sample + */ + ssize_t (*get_pm_metrics)(struct smu_context *smu, void *pm_metrics, + size_t size); + /** * @enable_mgpu_fan_boost: Enable multi-GPU fan boost. */ diff --git a/drivers/gpu/drm/amd/pm/swsmu/inc/smu_types.h b/drivers/gpu/drm/amd/pm/swsmu/inc/smu_types.h index 9dd47d91093e..ea8ea99b7436 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/inc/smu_types.h +++ b/drivers/gpu/drm/amd/pm/swsmu/inc/smu_types.h @@ -259,7 +259,8 @@ __SMU_DUMMY_MAP(PowerUpUmsch), \ __SMU_DUMMY_MAP(PowerDownUmsch), \ __SMU_DUMMY_MAP(SetSoftMaxVpe), \ - __SMU_DUMMY_MAP(SetSoftMinVpe), + __SMU_DUMMY_MAP(SetSoftMinVpe), \ + __SMU_DUMMY_MAP(GetMetricsVersion), #undef __SMU_DUMMY_MAP #define __SMU_DUMMY_MAP(type) SMU_MSG_##type -- cgit From f9a45b76a1883b081fbe15466b11d0264e85d372 Mon Sep 17 00:00:00 2001 From: Lijo Lazar Date: Fri, 29 Sep 2023 11:35:19 +0530 Subject: drm/amd/pm: Add pm metrics support to SMU v13.0.6 Add support to fetch PM metrics sample from SMU v13.0.6 Signed-off-by: Lijo Lazar Reviewed-by: Hawking Zhang Reviewed-by: Yang Wang Signed-off-by: Alex Deucher --- .../gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_6_ppt.c | 47 ++++++++++++++++++++++ 1 file changed, 47 insertions(+) diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_6_ppt.c b/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_6_ppt.c index f723a4190ee5..8ccb8354bb49 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_6_ppt.c +++ b/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_6_ppt.c @@ -120,6 +120,7 @@ struct mca_ras_info { #define P2S_TABLE_ID_A 0x50325341 #define P2S_TABLE_ID_X 0x50325358 +// clang-format off static const struct cmn2asic_msg_mapping smu_v13_0_6_message_map[SMU_MSG_MAX_COUNT] = { MSG_MAP(TestMessage, PPSMC_MSG_TestMessage, 0), MSG_MAP(GetSmuVersion, PPSMC_MSG_GetSmuVersion, 1), @@ -128,6 +129,7 @@ static const struct cmn2asic_msg_mapping smu_v13_0_6_message_map[SMU_MSG_MAX_COU MSG_MAP(DisableAllSmuFeatures, PPSMC_MSG_DisableAllSmuFeatures, 0), MSG_MAP(RequestI2cTransaction, PPSMC_MSG_RequestI2cTransaction, 0), MSG_MAP(GetMetricsTable, PPSMC_MSG_GetMetricsTable, 1), + MSG_MAP(GetMetricsVersion, PPSMC_MSG_GetMetricsVersion, 1), MSG_MAP(GetEnabledSmuFeaturesHigh, PPSMC_MSG_GetEnabledSmuFeaturesHigh, 1), MSG_MAP(GetEnabledSmuFeaturesLow, PPSMC_MSG_GetEnabledSmuFeaturesLow, 1), MSG_MAP(SetDriverDramAddrHigh, PPSMC_MSG_SetDriverDramAddrHigh, 1), @@ -171,6 +173,7 @@ static const struct cmn2asic_msg_mapping smu_v13_0_6_message_map[SMU_MSG_MAX_COU MSG_MAP(SelectPLPDMode, PPSMC_MSG_SelectPLPDMode, 0), }; +// clang-format on static const struct cmn2asic_mapping smu_v13_0_6_clk_map[SMU_CLK_COUNT] = { CLK_MAP(SOCCLK, PPCLK_SOCCLK), CLK_MAP(FCLK, PPCLK_FCLK), @@ -428,6 +431,41 @@ static int smu_v13_0_6_get_metrics_table(struct smu_context *smu, return 0; } +static ssize_t smu_v13_0_6_get_pm_metrics(struct smu_context *smu, + void *metrics, size_t max_size) +{ + struct smu_table_context *smu_tbl_ctxt = &smu->smu_table; + uint32_t table_version = smu_tbl_ctxt->tables[SMU_TABLE_SMU_METRICS].version; + uint32_t table_size = smu_tbl_ctxt->tables[SMU_TABLE_SMU_METRICS].size; + struct amdgpu_pm_metrics *pm_metrics = metrics; + uint32_t pmfw_version; + int ret; + + if (!pm_metrics || !max_size) + return -EINVAL; + + if (max_size < (table_size + sizeof(pm_metrics->common_header))) + return -EOVERFLOW; + + /* Don't use cached metrics data */ + ret = smu_v13_0_6_get_metrics_table(smu, pm_metrics->data, true); + if (ret) + return ret; + + smu_cmn_get_smc_version(smu, NULL, &pmfw_version); + + memset(&pm_metrics->common_header, 0, + sizeof(pm_metrics->common_header)); + pm_metrics->common_header.mp1_ip_discovery_version = + IP_VERSION(13, 0, 6); + pm_metrics->common_header.pmfw_version = pmfw_version; + pm_metrics->common_header.pmmetrics_version = table_version; + pm_metrics->common_header.structure_size = + sizeof(pm_metrics->common_header) + table_size; + + return pm_metrics->common_header.structure_size; +} + static int smu_v13_0_6_setup_driver_pptable(struct smu_context *smu) { struct smu_table_context *smu_table = &smu->smu_table; @@ -435,6 +473,7 @@ static int smu_v13_0_6_setup_driver_pptable(struct smu_context *smu) struct PPTable_t *pptable = (struct PPTable_t *)smu_table->driver_pptable; int ret, i, retry = 100; + uint32_t table_version; /* Store one-time values in driver PPTable */ if (!pptable->Init) { @@ -453,6 +492,13 @@ static int smu_v13_0_6_setup_driver_pptable(struct smu_context *smu) if (!retry) return -ETIME; + ret = smu_cmn_send_smc_msg(smu, SMU_MSG_GetMetricsVersion, + &table_version); + if (ret) + return ret; + smu_table->tables[SMU_TABLE_SMU_METRICS].version = + table_version; + pptable->MaxSocketPowerLimit = SMUQ10_ROUND(metrics->MaxSocketPowerLimit); pptable->MaxGfxclkFrequency = @@ -2864,6 +2910,7 @@ static const struct pptable_funcs smu_v13_0_6_ppt_funcs = { .log_thermal_throttling_event = smu_v13_0_6_log_thermal_throttling_event, .get_pp_feature_mask = smu_cmn_get_pp_feature_mask, .get_gpu_metrics = smu_v13_0_6_get_gpu_metrics, + .get_pm_metrics = smu_v13_0_6_get_pm_metrics, .get_thermal_temperature_range = smu_v13_0_6_get_thermal_temperature_range, .mode1_reset_is_support = smu_v13_0_6_is_mode1_reset_supported, .mode2_reset_is_support = smu_v13_0_6_is_mode2_reset_supported, -- cgit From 223aad1be34e1169ee7210bce05726cc5ef1fd66 Mon Sep 17 00:00:00 2001 From: Lijo Lazar Date: Fri, 29 Sep 2023 11:56:49 +0530 Subject: drm/amd/pm: Add sysfs attribute to get pm metrics Add sysfs attribute to read power management metrics. A snapshot is captured to the buffer when the attribute is read. Signed-off-by: Lijo Lazar Reviewed-by: Hawking Zhang Reviewed-by: Yang Wang Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/pm/amdgpu_pm.c | 40 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 40 insertions(+) diff --git a/drivers/gpu/drm/amd/pm/amdgpu_pm.c b/drivers/gpu/drm/amd/pm/amdgpu_pm.c index ca2ece24e1e0..e1497296afee 100644 --- a/drivers/gpu/drm/amd/pm/amdgpu_pm.c +++ b/drivers/gpu/drm/amd/pm/amdgpu_pm.c @@ -1799,6 +1799,44 @@ static ssize_t amdgpu_set_apu_thermal_cap(struct device *dev, return count; } +static int amdgpu_pm_metrics_attr_update(struct amdgpu_device *adev, + struct amdgpu_device_attr *attr, + uint32_t mask, + enum amdgpu_device_attr_states *states) +{ + if (amdgpu_dpm_get_pm_metrics(adev, NULL, 0) == -EOPNOTSUPP) + *states = ATTR_STATE_UNSUPPORTED; + + return 0; +} + +static ssize_t amdgpu_get_pm_metrics(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct drm_device *ddev = dev_get_drvdata(dev); + struct amdgpu_device *adev = drm_to_adev(ddev); + ssize_t size = 0; + int ret; + + if (amdgpu_in_reset(adev)) + return -EPERM; + if (adev->in_suspend && !adev->in_runpm) + return -EPERM; + + ret = pm_runtime_get_sync(ddev->dev); + if (ret < 0) { + pm_runtime_put_autosuspend(ddev->dev); + return ret; + } + + size = amdgpu_dpm_get_pm_metrics(adev, buf, PAGE_SIZE); + + pm_runtime_mark_last_busy(ddev->dev); + pm_runtime_put_autosuspend(ddev->dev); + + return size; +} + /** * DOC: gpu_metrics * @@ -2096,6 +2134,8 @@ static struct amdgpu_device_attr amdgpu_device_attrs[] = { AMDGPU_DEVICE_ATTR_RW(smartshift_bias, ATTR_FLAG_BASIC, .attr_update = ss_bias_attr_update), AMDGPU_DEVICE_ATTR_RW(xgmi_plpd_policy, ATTR_FLAG_BASIC), + AMDGPU_DEVICE_ATTR_RO(pm_metrics, ATTR_FLAG_BASIC, + .attr_update = amdgpu_pm_metrics_attr_update), }; static int default_attr_update(struct amdgpu_device *adev, struct amdgpu_device_attr *attr, -- cgit From cee6de122461de699aaa7932b33466c6d259eabb Mon Sep 17 00:00:00 2001 From: Dennis Chan Date: Fri, 27 Oct 2023 11:00:36 +0800 Subject: drm/amd/display: Add new Replay command and Disabled Replay Timing Resync [why] To support dynamic switching for Replay timing sync mechanism. Reviewed-by: ChunTao Tso Acked-by: Hamza Mahfooz Signed-off-by: Dennis Chan Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dc_types.h | 10 +++++++++ drivers/gpu/drm/amd/display/dc/dce/dmub_replay.h | 3 +++ drivers/gpu/drm/amd/display/dc/inc/link.h | 3 +++ drivers/gpu/drm/amd/display/dc/link/link_factory.c | 1 + .../dc/link/protocols/link_edp_panel_control.c | 24 ++++++++++++++++++++++ .../dc/link/protocols/link_edp_panel_control.h | 3 +++ 6 files changed, 44 insertions(+) diff --git a/drivers/gpu/drm/amd/display/dc/dc_types.h b/drivers/gpu/drm/amd/display/dc/dc_types.h index fcb825e4f1bb..edf60c4f318c 100644 --- a/drivers/gpu/drm/amd/display/dc/dc_types.h +++ b/drivers/gpu/drm/amd/display/dc/dc_types.h @@ -1022,6 +1022,16 @@ enum replay_coasting_vtotal_type { PR_COASTING_TYPE_NUM, }; +/* + * This is general Interface for Replay to + * set an 32 bit variable to dmub + * The Message_type indicates which variable + * passed to DMUB. + */ +enum replay_FW_Message_type { + Replay_Set_Timing_Sync_Supported, +}; + union replay_error_status { struct { unsigned char STATE_TRANSITION_ERROR :1; diff --git a/drivers/gpu/drm/amd/display/dc/dce/dmub_replay.h b/drivers/gpu/drm/amd/display/dc/dce/dmub_replay.h index e8385bbf51fc..427bc47a676e 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dmub_replay.h +++ b/drivers/gpu/drm/amd/display/dc/dce/dmub_replay.h @@ -45,6 +45,9 @@ struct dmub_replay_funcs { struct replay_context *replay_context, uint8_t panel_inst); void (*replay_set_power_opt)(struct dmub_replay *dmub, unsigned int power_opt, uint8_t panel_inst); + void (*replay_send_cmd)(struct dmub_replay *dmub, + enum replay_FW_Message_type msg, unsigned int panel_inst, + uint32_t cmd_data); void (*replay_set_coasting_vtotal)(struct dmub_replay *dmub, uint16_t coasting_vtotal, uint8_t panel_inst); void (*replay_residency)(struct dmub_replay *dmub, diff --git a/drivers/gpu/drm/amd/display/dc/inc/link.h b/drivers/gpu/drm/amd/display/dc/inc/link.h index d7685368140a..dd3f53151d8b 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/link.h +++ b/drivers/gpu/drm/amd/display/dc/inc/link.h @@ -281,6 +281,9 @@ struct link_service { const unsigned int *power_opts); bool (*edp_setup_replay)(struct dc_link *link, const struct dc_stream_state *stream); + bool (*edp_send_replay_cmd)(struct dc_link *link, + enum replay_FW_Message_type msg, + uint32_t params); bool (*edp_set_coasting_vtotal)( struct dc_link *link, uint16_t coasting_vtotal); bool (*edp_replay_residency)(const struct dc_link *link, diff --git a/drivers/gpu/drm/amd/display/dc/link/link_factory.c b/drivers/gpu/drm/amd/display/dc/link/link_factory.c index 7abfc67d10a6..6b306ea58b9b 100644 --- a/drivers/gpu/drm/amd/display/dc/link/link_factory.c +++ b/drivers/gpu/drm/amd/display/dc/link/link_factory.c @@ -213,6 +213,7 @@ static void construct_link_service_edp_panel_control(struct link_service *link_s link_srv->edp_get_replay_state = edp_get_replay_state; link_srv->edp_set_replay_allow_active = edp_set_replay_allow_active; link_srv->edp_setup_replay = edp_setup_replay; + link_srv->edp_send_replay_cmd = edp_send_replay_cmd; link_srv->edp_set_coasting_vtotal = edp_set_coasting_vtotal; link_srv->edp_replay_residency = edp_replay_residency; diff --git a/drivers/gpu/drm/amd/display/dc/link/protocols/link_edp_panel_control.c b/drivers/gpu/drm/amd/display/dc/link/protocols/link_edp_panel_control.c index e32a7974a4bc..c52b51b2b4b3 100644 --- a/drivers/gpu/drm/amd/display/dc/link/protocols/link_edp_panel_control.c +++ b/drivers/gpu/drm/amd/display/dc/link/protocols/link_edp_panel_control.c @@ -1007,6 +1007,30 @@ bool edp_setup_replay(struct dc_link *link, const struct dc_stream_state *stream return true; } +/* + * This is general Interface for Replay to set an 32 bit variable to dmub + * replay_FW_Message_type: Indicates which instruction or variable pass to DMUB + * cmd_data: Value of the config. + */ +bool edp_send_replay_cmd(struct dc_link *link, + enum replay_FW_Message_type msg, + uint32_t cmd_data) +{ + struct dc *dc = link->ctx->dc; + struct dmub_replay *replay = dc->res_pool->replay; + unsigned int panel_inst; + + if (!replay) + return false; + + if (!dc_get_edp_link_panel_inst(dc, link, &panel_inst)) + return false; + + replay->funcs->replay_send_cmd(replay, msg, cmd_data, panel_inst); + + return true; +} + bool edp_set_coasting_vtotal(struct dc_link *link, uint16_t coasting_vtotal) { struct dc *dc = link->ctx->dc; diff --git a/drivers/gpu/drm/amd/display/dc/link/protocols/link_edp_panel_control.h b/drivers/gpu/drm/amd/display/dc/link/protocols/link_edp_panel_control.h index ebf7deb63d13..6b223580ac8a 100644 --- a/drivers/gpu/drm/amd/display/dc/link/protocols/link_edp_panel_control.h +++ b/drivers/gpu/drm/amd/display/dc/link/protocols/link_edp_panel_control.h @@ -57,6 +57,9 @@ bool edp_set_replay_allow_active(struct dc_link *dc_link, const bool *enable, bool wait, bool force_static, const unsigned int *power_opts); bool edp_setup_replay(struct dc_link *link, const struct dc_stream_state *stream); +bool edp_send_replay_cmd(struct dc_link *link, + enum replay_FW_Message_type msg, + uint32_t params); bool edp_set_coasting_vtotal(struct dc_link *link, uint16_t coasting_vtotal); bool edp_replay_residency(const struct dc_link *link, unsigned int *residency, const bool is_start, const bool is_alpm); -- cgit From 1c22d6ce53280763bcb4cb24d4f71111fff4a526 Mon Sep 17 00:00:00 2001 From: Alvin Lee Date: Mon, 6 Nov 2023 11:20:15 -0500 Subject: drm/amd/display: Include udelay when waiting for INBOX0 ACK When waiting for the ACK for INBOX0 message, we have to ensure to include the udelay for proper wait time Cc: stable@vger.kernel.org # 6.1+ Reviewed-by: Samson Tam Acked-by: Hamza Mahfooz Signed-off-by: Alvin Lee Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dmub/src/dmub_srv.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/gpu/drm/amd/display/dmub/src/dmub_srv.c b/drivers/gpu/drm/amd/display/dmub/src/dmub_srv.c index 22fc4ba96def..38360adc53d9 100644 --- a/drivers/gpu/drm/amd/display/dmub/src/dmub_srv.c +++ b/drivers/gpu/drm/amd/display/dmub/src/dmub_srv.c @@ -1077,6 +1077,7 @@ enum dmub_status dmub_srv_wait_for_inbox0_ack(struct dmub_srv *dmub, uint32_t ti ack = dmub->hw_funcs.read_inbox0_ack_register(dmub); if (ack) return DMUB_STATUS_OK; + udelay(1); } return DMUB_STATUS_TIMEOUT; } -- cgit From 3f3b08be58834339b00f28d19c20d684cdec704f Mon Sep 17 00:00:00 2001 From: Nicholas Kazlauskas Date: Fri, 3 Nov 2023 10:01:01 -0400 Subject: drm/amd/display: Add z-state support policy for dcn35 [Why] DML2 means that the dcn3x policy for calculating z-state support no longer runs from validate_bandwidth. This means we are unconditionally allowing Z8, the hardware default. [How] Port the policy over to DCN35, but with a few modifications: - Don't use min_dst_y_next_start as a check for Z8/Z10 allow - Add support for overriding the Z10 stutter period per ASIC - Cleanup the code to make the policy assignment more clear Reviewed-by: Charlene Liu Acked-by: Hamza Mahfooz Signed-off-by: Nicholas Kazlauskas Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dc.h | 1 + .../gpu/drm/amd/display/dc/dml/dcn35/dcn35_fpu.c | 34 ++++++++++++++++++++++ .../gpu/drm/amd/display/dc/dml/dcn35/dcn35_fpu.h | 2 ++ .../amd/display/dc/resource/dcn35/dcn35_resource.c | 7 +++++ 4 files changed, 44 insertions(+) diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h index 541e781267b9..349629858205 100644 --- a/drivers/gpu/drm/amd/display/dc/dc.h +++ b/drivers/gpu/drm/amd/display/dc/dc.h @@ -874,6 +874,7 @@ struct dc_debug_options { unsigned int seamless_boot_odm_combine; unsigned int force_odm_combine_4to1; //bit vector based on otg inst int minimum_z8_residency_time; + int minimum_z10_residency_time; bool disable_z9_mpc; unsigned int force_fclk_khz; bool enable_tri_buf; diff --git a/drivers/gpu/drm/amd/display/dc/dml/dcn35/dcn35_fpu.c b/drivers/gpu/drm/amd/display/dc/dml/dcn35/dcn35_fpu.c index a5fe523668e9..dee80429fc4c 100644 --- a/drivers/gpu/drm/amd/display/dc/dml/dcn35/dcn35_fpu.c +++ b/drivers/gpu/drm/amd/display/dc/dml/dcn35/dcn35_fpu.c @@ -507,3 +507,37 @@ int dcn35_populate_dml_pipes_from_context_fpu(struct dc *dc, return pipe_cnt; } + +void dcn35_decide_zstate_support(struct dc *dc, struct dc_state *context) +{ + enum dcn_zstate_support_state support = DCN_ZSTATE_SUPPORT_DISALLOW; + unsigned int i, plane_count = 0; + + for (i = 0; i < dc->res_pool->pipe_count; i++) { + if (context->res_ctx.pipe_ctx[i].plane_state) + plane_count++; + } + + if (plane_count == 0) { + support = DCN_ZSTATE_SUPPORT_ALLOW; + } else if (plane_count == 1 && context->stream_count == 1 && context->streams[0]->signal == SIGNAL_TYPE_EDP) { + struct dc_link *link = context->streams[0]->sink->link; + bool is_pwrseq0 = link && link->link_index == 0; + bool is_psr1 = link && link->psr_settings.psr_version == DC_PSR_VERSION_1 && !link->panel_config.psr.disable_psr; + int minmum_z8_residency = + dc->debug.minimum_z8_residency_time > 0 ? dc->debug.minimum_z8_residency_time : 1000; + bool allow_z8 = context->bw_ctx.dml.vba.StutterPeriod > (double)minmum_z8_residency; + int minmum_z10_residency = + dc->debug.minimum_z10_residency_time > 0 ? dc->debug.minimum_z10_residency_time : 5000; + bool allow_z10 = context->bw_ctx.dml.vba.StutterPeriod > (double)minmum_z10_residency; + + if (is_pwrseq0 && allow_z10) + support = DCN_ZSTATE_SUPPORT_ALLOW; + else if (is_pwrseq0 && is_psr1) + support = allow_z8 ? DCN_ZSTATE_SUPPORT_ALLOW_Z8_Z10_ONLY : DCN_ZSTATE_SUPPORT_ALLOW_Z10_ONLY; + else if (allow_z8) + support = DCN_ZSTATE_SUPPORT_ALLOW_Z8_ONLY; + } + + context->bw_ctx.bw.dcn.clk.zstate_support = support; +} diff --git a/drivers/gpu/drm/amd/display/dc/dml/dcn35/dcn35_fpu.h b/drivers/gpu/drm/amd/display/dc/dml/dcn35/dcn35_fpu.h index e8d5a170893e..067480fc3691 100644 --- a/drivers/gpu/drm/amd/display/dc/dml/dcn35/dcn35_fpu.h +++ b/drivers/gpu/drm/amd/display/dc/dml/dcn35/dcn35_fpu.h @@ -39,4 +39,6 @@ int dcn35_populate_dml_pipes_from_context_fpu(struct dc *dc, display_e2e_pipe_params_st *pipes, bool fast_validate); +void dcn35_decide_zstate_support(struct dc *dc, struct dc_state *context); + #endif diff --git a/drivers/gpu/drm/amd/display/dc/resource/dcn35/dcn35_resource.c b/drivers/gpu/drm/amd/display/dc/resource/dcn35/dcn35_resource.c index 5c935d94a95c..0d5a03c6d812 100644 --- a/drivers/gpu/drm/amd/display/dc/resource/dcn35/dcn35_resource.c +++ b/drivers/gpu/drm/amd/display/dc/resource/dcn35/dcn35_resource.c @@ -1724,6 +1724,13 @@ static bool dcn35_validate_bandwidth(struct dc *dc, out = dml2_validate(dc, context, fast_validate); + if (fast_validate) + return out; + + DC_FP_START(); + dcn35_decide_zstate_support(dc, context); + DC_FP_END(); + return out; } -- cgit From a2d3c69261178df7d4c1350d5ef67375d399acd3 Mon Sep 17 00:00:00 2001 From: David Yat Sin Date: Fri, 17 Nov 2023 05:16:59 +0000 Subject: drm/amdkfd: Copy HW exception data to user event Fixes issue where user events of type KFD_EVENT_TYPE_HW_EXCEPTION do not have valid data Signed-off-by: David Yat Sin Reviewed-by: Lijo Lazar Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdkfd/kfd_events.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_events.c b/drivers/gpu/drm/amd/amdkfd/kfd_events.c index 0f58be65132f..739721254a5d 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_events.c +++ b/drivers/gpu/drm/amd/amdkfd/kfd_events.c @@ -880,6 +880,10 @@ static int copy_signaled_event_data(uint32_t num_events, dst = &data[i].memory_exception_data; src = &event->memory_exception_data; size = sizeof(struct kfd_hsa_memory_exception_data); + } else if (event->type == KFD_EVENT_TYPE_HW_EXCEPTION) { + dst = &data[i].memory_exception_data; + src = &event->hw_exception_data; + size = sizeof(struct kfd_hsa_hw_exception_data); } else if (event->type == KFD_EVENT_TYPE_SIGNAL && waiter->event_age_enabled) { dst = &data[i].signal_event_data.last_event_age; -- cgit From 35c425f5cc251417ad681475dc9901ab6d3244ea Mon Sep 17 00:00:00 2001 From: Jonathan Kim Date: Thu, 16 Nov 2023 13:57:07 -0500 Subject: drm/amdgpu: update xgmi num links info post gc9.4.2 GC IP 9.4.2 and up support TA reporting of the number of xGMI links between peers. Tested-by: Vignesh Chander Signed-off-by: Jonathan Kim Reviewed-by: Mukul Joshi Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.c index 6ab17330a6ed..2d22f7d45512 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.c @@ -547,7 +547,7 @@ int amdgpu_amdkfd_get_xgmi_bandwidth_mbytes(struct amdgpu_device *dst, struct amdgpu_device *adev = dst, *peer_adev; int num_links; - if (adev->asic_type != CHIP_ALDEBARAN) + if (amdgpu_ip_version(adev, GC_HWIP, 0) < IP_VERSION(9, 4, 2)) return 0; if (src) -- cgit From 76c5d6900908439386b0045a6130150150079300 Mon Sep 17 00:00:00 2001 From: Nicholas Kazlauskas Date: Mon, 6 Nov 2023 17:29:33 -0500 Subject: drm/amd/display: Update DCN35 watermarks [Why & How] Update to the new values per HW team request. Affects both stutter and z8. Reviewed-by: Charlene Liu Acked-by: Hamza Mahfooz Signed-off-by: Nicholas Kazlauskas Signed-off-by: Alex Deucher --- .../amd/display/dc/clk_mgr/dcn35/dcn35_clk_mgr.c | 32 +++++++++++----------- .../gpu/drm/amd/display/dc/dml/dcn35/dcn35_fpu.c | 8 +++--- 2 files changed, 20 insertions(+), 20 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn35/dcn35_clk_mgr.c b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn35/dcn35_clk_mgr.c index 507a7cf56711..3469f692d6ea 100644 --- a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn35/dcn35_clk_mgr.c +++ b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn35/dcn35_clk_mgr.c @@ -443,32 +443,32 @@ static struct wm_table ddr5_wm_table = { .wm_inst = WM_A, .wm_type = WM_TYPE_PSTATE_CHG, .pstate_latency_us = 11.72, - .sr_exit_time_us = 9, - .sr_enter_plus_exit_time_us = 11, + .sr_exit_time_us = 14.0, + .sr_enter_plus_exit_time_us = 16.0, .valid = true, }, { .wm_inst = WM_B, .wm_type = WM_TYPE_PSTATE_CHG, .pstate_latency_us = 11.72, - .sr_exit_time_us = 9, - .sr_enter_plus_exit_time_us = 11, + .sr_exit_time_us = 14.0, + .sr_enter_plus_exit_time_us = 16.0, .valid = true, }, { .wm_inst = WM_C, .wm_type = WM_TYPE_PSTATE_CHG, .pstate_latency_us = 11.72, - .sr_exit_time_us = 9, - .sr_enter_plus_exit_time_us = 11, + .sr_exit_time_us = 14.0, + .sr_enter_plus_exit_time_us = 16.0, .valid = true, }, { .wm_inst = WM_D, .wm_type = WM_TYPE_PSTATE_CHG, .pstate_latency_us = 11.72, - .sr_exit_time_us = 9, - .sr_enter_plus_exit_time_us = 11, + .sr_exit_time_us = 14.0, + .sr_enter_plus_exit_time_us = 16.0, .valid = true, }, } @@ -480,32 +480,32 @@ static struct wm_table lpddr5_wm_table = { .wm_inst = WM_A, .wm_type = WM_TYPE_PSTATE_CHG, .pstate_latency_us = 11.65333, - .sr_exit_time_us = 11.5, - .sr_enter_plus_exit_time_us = 14.5, + .sr_exit_time_us = 14.0, + .sr_enter_plus_exit_time_us = 16.0, .valid = true, }, { .wm_inst = WM_B, .wm_type = WM_TYPE_PSTATE_CHG, .pstate_latency_us = 11.65333, - .sr_exit_time_us = 11.5, - .sr_enter_plus_exit_time_us = 14.5, + .sr_exit_time_us = 14.0, + .sr_enter_plus_exit_time_us = 16.0, .valid = true, }, { .wm_inst = WM_C, .wm_type = WM_TYPE_PSTATE_CHG, .pstate_latency_us = 11.65333, - .sr_exit_time_us = 11.5, - .sr_enter_plus_exit_time_us = 14.5, + .sr_exit_time_us = 14.0, + .sr_enter_plus_exit_time_us = 16.0, .valid = true, }, { .wm_inst = WM_D, .wm_type = WM_TYPE_PSTATE_CHG, .pstate_latency_us = 11.65333, - .sr_exit_time_us = 11.5, - .sr_enter_plus_exit_time_us = 14.5, + .sr_exit_time_us = 14.0, + .sr_enter_plus_exit_time_us = 16.0, .valid = true, }, } diff --git a/drivers/gpu/drm/amd/display/dc/dml/dcn35/dcn35_fpu.c b/drivers/gpu/drm/amd/display/dc/dml/dcn35/dcn35_fpu.c index dee80429fc4c..30d78ad91b9c 100644 --- a/drivers/gpu/drm/amd/display/dc/dml/dcn35/dcn35_fpu.c +++ b/drivers/gpu/drm/amd/display/dc/dml/dcn35/dcn35_fpu.c @@ -164,10 +164,10 @@ struct _vcs_dpi_soc_bounding_box_st dcn3_5_soc = { }, }, .num_states = 5, - .sr_exit_time_us = 9.0, - .sr_enter_plus_exit_time_us = 11.0, - .sr_exit_z8_time_us = 50.0, /*changed from 442.0*/ - .sr_enter_plus_exit_z8_time_us = 50.0,/*changed from 560.0*/ + .sr_exit_time_us = 14.0, + .sr_enter_plus_exit_time_us = 16.0, + .sr_exit_z8_time_us = 525.0, + .sr_enter_plus_exit_z8_time_us = 715.0, .fclk_change_latency_us = 20.0, .usr_retraining_latency_us = 2, .writeback_latency_us = 12.0, -- cgit From c4290449f8fbecc55013c6125b50908b5359a8fd Mon Sep 17 00:00:00 2001 From: Ian Chen Date: Mon, 6 Nov 2023 15:46:19 +0800 Subject: drm/amd/display: add skip_implict_edp_power_control flag for dce110 If the link requests to skip implicit eDP power control, we should honor that request. Reviewed-by: Robin Chen Acked-by: Hamza Mahfooz Signed-off-by: Ian Chen Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/hwss/dce110/dce110_hwseq.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/display/dc/hwss/dce110/dce110_hwseq.c b/drivers/gpu/drm/amd/display/dc/hwss/dce110/dce110_hwseq.c index 960a55e06375..0a331d17ee92 100644 --- a/drivers/gpu/drm/amd/display/dc/hwss/dce110/dce110_hwseq.c +++ b/drivers/gpu/drm/amd/display/dc/hwss/dce110/dce110_hwseq.c @@ -3115,7 +3115,8 @@ void dce110_disable_link_output(struct dc_link *link, struct dmcu *dmcu = dc->res_pool->dmcu; if (signal == SIGNAL_TYPE_EDP && - link->dc->hwss.edp_backlight_control) + link->dc->hwss.edp_backlight_control && + !link->skip_implict_edp_power_control) link->dc->hwss.edp_backlight_control(link, false); else if (dmcu != NULL && dmcu->funcs->lock_phy) dmcu->funcs->lock_phy(dmcu); -- cgit From 613a81995575889753ca44d70d33e84a1d21bae5 Mon Sep 17 00:00:00 2001 From: Wenjing Liu Date: Mon, 6 Nov 2023 16:47:19 -0500 Subject: drm/amd/display: fix a pipe mapping error in dcn32_fpu [why] In dcn32 DML pipes are ordered the same as dc pipes but only for used pipes. For example, if dc pipe 1 and 2 are used, their dml pipe indices would be 0 and 1 respectively. However update_pipe_slice_table_with_split_flags doesn't skip indices for free pipes. This causes us to not reference correct dml pipe output when building pipe topology. [how] Use two variables to iterate dc and dml pipes respectively and only increment dml pipe index when current dc pipe is not free. Cc: stable@vger.kernel.org # 6.1+ Reviewed-by: Chaitanya Dhere Acked-by: Hamza Mahfooz Signed-off-by: Wenjing Liu Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dml/dcn32/dcn32_fpu.c | 20 ++++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/dml/dcn32/dcn32_fpu.c b/drivers/gpu/drm/amd/display/dc/dml/dcn32/dcn32_fpu.c index 9ec4172d1c2d..44b0666e53b0 100644 --- a/drivers/gpu/drm/amd/display/dc/dml/dcn32/dcn32_fpu.c +++ b/drivers/gpu/drm/amd/display/dc/dml/dcn32/dcn32_fpu.c @@ -1192,13 +1192,16 @@ static bool update_pipe_slice_table_with_split_flags( */ struct pipe_ctx *pipe; bool odm; - int i; + int dc_pipe_idx, dml_pipe_idx = 0; bool updated = false; - for (i = 0; i < dc->res_pool->pipe_count; i++) { - pipe = &context->res_ctx.pipe_ctx[i]; + for (dc_pipe_idx = 0; + dc_pipe_idx < dc->res_pool->pipe_count; dc_pipe_idx++) { + pipe = &context->res_ctx.pipe_ctx[dc_pipe_idx]; + if (resource_is_pipe_type(pipe, FREE_PIPE)) + continue; - if (merge[i]) { + if (merge[dc_pipe_idx]) { if (resource_is_pipe_type(pipe, OPP_HEAD)) /* merging OPP head means reducing ODM slice * count by 1 @@ -1213,17 +1216,18 @@ static bool update_pipe_slice_table_with_split_flags( updated = true; } - if (split[i]) { - odm = vba->ODMCombineEnabled[vba->pipe_plane[i]] != + if (split[dc_pipe_idx]) { + odm = vba->ODMCombineEnabled[vba->pipe_plane[dml_pipe_idx]] != dm_odm_combine_mode_disabled; if (odm && resource_is_pipe_type(pipe, OPP_HEAD)) update_slice_table_for_stream( - table, pipe->stream, split[i] - 1); + table, pipe->stream, split[dc_pipe_idx] - 1); else if (!odm && resource_is_pipe_type(pipe, DPP_PIPE)) update_slice_table_for_plane(table, pipe, - pipe->plane_state, split[i] - 1); + pipe->plane_state, split[dc_pipe_idx] - 1); updated = true; } + dml_pipe_idx++; } return updated; } -- cgit From 702e2fb579e000382c219c58dacef4f733511a36 Mon Sep 17 00:00:00 2001 From: Hawking Zhang Date: Mon, 20 Nov 2023 11:04:45 +0800 Subject: drm/amdgpu: Retire query/reset_ras_err_status from gfx_v9_4_3 Not needed anymore. Signed-off-by: Hawking Zhang Reviewed-by: Stanley Yang Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/gfx_v9_4_3.c | 156 -------------------------------- 1 file changed, 156 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v9_4_3.c b/drivers/gpu/drm/amd/amdgpu/gfx_v9_4_3.c index 40d06d32bb74..21865668b787 100644 --- a/drivers/gpu/drm/amd/amdgpu/gfx_v9_4_3.c +++ b/drivers/gpu/drm/amd/amdgpu/gfx_v9_4_3.c @@ -3882,150 +3882,6 @@ static void gfx_v9_4_3_inst_reset_ras_err_count(struct amdgpu_device *adev, mutex_unlock(&adev->grbm_idx_mutex); } -static void gfx_v9_4_3_inst_query_utc_err_status(struct amdgpu_device *adev, - int xcc_id) -{ - uint32_t data; - - data = RREG32_SOC15(GC, GET_INST(GC, xcc_id), regUTCL2_MEM_ECC_STATUS); - if (data) { - dev_warn(adev->dev, "GFX UTCL2 Mem Ecc Status: 0x%x!\n", data); - WREG32_SOC15(GC, GET_INST(GC, xcc_id), regUTCL2_MEM_ECC_STATUS, 0x3); - } - - data = RREG32_SOC15(GC, GET_INST(GC, xcc_id), regVML2_MEM_ECC_STATUS); - if (data) { - dev_warn(adev->dev, "GFX VML2 Mem Ecc Status: 0x%x!\n", data); - WREG32_SOC15(GC, GET_INST(GC, xcc_id), regVML2_MEM_ECC_STATUS, 0x3); - } - - data = RREG32_SOC15(GC, GET_INST(GC, xcc_id), - regVML2_WALKER_MEM_ECC_STATUS); - if (data) { - dev_warn(adev->dev, "GFX VML2 Walker Mem Ecc Status: 0x%x!\n", data); - WREG32_SOC15(GC, GET_INST(GC, xcc_id), regVML2_WALKER_MEM_ECC_STATUS, - 0x3); - } -} - -static void gfx_v9_4_3_log_cu_timeout_status(struct amdgpu_device *adev, - uint32_t status, int xcc_id) -{ - struct amdgpu_cu_info *cu_info = &adev->gfx.cu_info; - uint32_t i, simd, wave; - uint32_t wave_status; - uint32_t wave_pc_lo, wave_pc_hi; - uint32_t wave_exec_lo, wave_exec_hi; - uint32_t wave_inst_dw0, wave_inst_dw1; - uint32_t wave_ib_sts; - - for (i = 0; i < 32; i++) { - if (!((i << 1) & status)) - continue; - - simd = i / cu_info->max_waves_per_simd; - wave = i % cu_info->max_waves_per_simd; - - wave_status = wave_read_ind(adev, xcc_id, simd, wave, ixSQ_WAVE_STATUS); - wave_pc_lo = wave_read_ind(adev, xcc_id, simd, wave, ixSQ_WAVE_PC_LO); - wave_pc_hi = wave_read_ind(adev, xcc_id, simd, wave, ixSQ_WAVE_PC_HI); - wave_exec_lo = - wave_read_ind(adev, xcc_id, simd, wave, ixSQ_WAVE_EXEC_LO); - wave_exec_hi = - wave_read_ind(adev, xcc_id, simd, wave, ixSQ_WAVE_EXEC_HI); - wave_inst_dw0 = - wave_read_ind(adev, xcc_id, simd, wave, ixSQ_WAVE_INST_DW0); - wave_inst_dw1 = - wave_read_ind(adev, xcc_id, simd, wave, ixSQ_WAVE_INST_DW1); - wave_ib_sts = wave_read_ind(adev, xcc_id, simd, wave, ixSQ_WAVE_IB_STS); - - dev_info( - adev->dev, - "\t SIMD %d, Wave %d: status 0x%x, pc 0x%llx, exec 0x%llx, inst 0x%llx, ib_sts 0x%x\n", - simd, wave, wave_status, - ((uint64_t)wave_pc_hi << 32 | wave_pc_lo), - ((uint64_t)wave_exec_hi << 32 | wave_exec_lo), - ((uint64_t)wave_inst_dw1 << 32 | wave_inst_dw0), - wave_ib_sts); - } -} - -static void gfx_v9_4_3_inst_query_sq_timeout_status(struct amdgpu_device *adev, - int xcc_id) -{ - uint32_t se_idx, sh_idx, cu_idx; - uint32_t status; - - mutex_lock(&adev->grbm_idx_mutex); - for (se_idx = 0; se_idx < adev->gfx.config.max_shader_engines; se_idx++) { - for (sh_idx = 0; sh_idx < adev->gfx.config.max_sh_per_se; sh_idx++) { - for (cu_idx = 0; cu_idx < adev->gfx.config.max_cu_per_sh; cu_idx++) { - gfx_v9_4_3_xcc_select_se_sh(adev, se_idx, sh_idx, - cu_idx, xcc_id); - status = RREG32_SOC15(GC, GET_INST(GC, xcc_id), - regSQ_TIMEOUT_STATUS); - if (status != 0) { - dev_info( - adev->dev, - "GFX Watchdog Timeout: SE %d, SH %d, CU %d\n", - se_idx, sh_idx, cu_idx); - gfx_v9_4_3_log_cu_timeout_status( - adev, status, xcc_id); - } - /* clear old status */ - WREG32_SOC15(GC, GET_INST(GC, xcc_id), - regSQ_TIMEOUT_STATUS, 0); - } - } - } - gfx_v9_4_3_xcc_select_se_sh(adev, 0xffffffff, 0xffffffff, 0xffffffff, - xcc_id); - mutex_unlock(&adev->grbm_idx_mutex); -} - -static void gfx_v9_4_3_inst_query_ras_err_status(struct amdgpu_device *adev, - void *ras_error_status, int xcc_id) -{ - gfx_v9_4_3_inst_query_utc_err_status(adev, xcc_id); - gfx_v9_4_3_inst_query_sq_timeout_status(adev, xcc_id); -} - -static void gfx_v9_4_3_inst_reset_utc_err_status(struct amdgpu_device *adev, - int xcc_id) -{ - WREG32_SOC15(GC, GET_INST(GC, xcc_id), regUTCL2_MEM_ECC_STATUS, 0x3); - WREG32_SOC15(GC, GET_INST(GC, xcc_id), regVML2_MEM_ECC_STATUS, 0x3); - WREG32_SOC15(GC, GET_INST(GC, xcc_id), regVML2_WALKER_MEM_ECC_STATUS, 0x3); -} - -static void gfx_v9_4_3_inst_reset_sq_timeout_status(struct amdgpu_device *adev, - int xcc_id) -{ - uint32_t se_idx, sh_idx, cu_idx; - - mutex_lock(&adev->grbm_idx_mutex); - for (se_idx = 0; se_idx < adev->gfx.config.max_shader_engines; se_idx++) { - for (sh_idx = 0; sh_idx < adev->gfx.config.max_sh_per_se; sh_idx++) { - for (cu_idx = 0; cu_idx < adev->gfx.config.max_cu_per_sh; cu_idx++) { - gfx_v9_4_3_xcc_select_se_sh(adev, se_idx, sh_idx, - cu_idx, xcc_id); - WREG32_SOC15(GC, GET_INST(GC, xcc_id), - regSQ_TIMEOUT_STATUS, 0); - } - } - } - gfx_v9_4_3_xcc_select_se_sh(adev, 0xffffffff, 0xffffffff, 0xffffffff, - xcc_id); - mutex_unlock(&adev->grbm_idx_mutex); -} - -static void gfx_v9_4_3_inst_reset_ras_err_status(struct amdgpu_device *adev, - void *ras_error_status, int xcc_id) -{ - gfx_v9_4_3_inst_reset_utc_err_status(adev, xcc_id); - gfx_v9_4_3_inst_reset_sq_timeout_status(adev, xcc_id); -} - static void gfx_v9_4_3_inst_enable_watchdog_timer(struct amdgpu_device *adev, void *ras_error_status, int xcc_id) { @@ -4067,16 +3923,6 @@ static void gfx_v9_4_3_reset_ras_error_count(struct amdgpu_device *adev) amdgpu_gfx_ras_error_func(adev, NULL, gfx_v9_4_3_inst_reset_ras_err_count); } -static void gfx_v9_4_3_query_ras_error_status(struct amdgpu_device *adev) -{ - amdgpu_gfx_ras_error_func(adev, NULL, gfx_v9_4_3_inst_query_ras_err_status); -} - -static void gfx_v9_4_3_reset_ras_error_status(struct amdgpu_device *adev) -{ - amdgpu_gfx_ras_error_func(adev, NULL, gfx_v9_4_3_inst_reset_ras_err_status); -} - static void gfx_v9_4_3_enable_watchdog_timer(struct amdgpu_device *adev) { amdgpu_gfx_ras_error_func(adev, NULL, gfx_v9_4_3_inst_enable_watchdog_timer); @@ -4394,8 +4240,6 @@ struct amdgpu_xcp_ip_funcs gfx_v9_4_3_xcp_funcs = { struct amdgpu_ras_block_hw_ops gfx_v9_4_3_ras_ops = { .query_ras_error_count = &gfx_v9_4_3_query_ras_error_count, .reset_ras_error_count = &gfx_v9_4_3_reset_ras_error_count, - .query_ras_error_status = &gfx_v9_4_3_query_ras_error_status, - .reset_ras_error_status = &gfx_v9_4_3_reset_ras_error_status, }; struct amdgpu_gfx_ras gfx_v9_4_3_ras = { -- cgit From 2e9b152325f649923b9324fa8ea5f1a5289145bb Mon Sep 17 00:00:00 2001 From: Perry Yuan Date: Tue, 1 Aug 2023 10:37:41 -0400 Subject: drm/amdgpu: optimize RLC powerdown notification on Vangogh The smu needs to get the rlc power down message to sync the rlc state with smu, the rlc state updating message need to be sent at while smu begin suspend sequence , otherwise SMU will crash while RLC state is not notified by driver, and rlc state probally changed after that notification, so it needs to notify rlc state to smu at the end of the suspend sequence in amdgpu_device_suspend() that can make sure the rlc state is correctly set to SMU. [ 101.000590] amdgpu 0000:03:00.0: amdgpu: SMU: I'm not done with your previous command: SMN_C2PMSG_66:0x0000001E SMN_C2PMSG_82:0x00000000 [ 101.000598] amdgpu 0000:03:00.0: amdgpu: Failed to disable gfxoff! [ 110.838026] amdgpu 0000:03:00.0: amdgpu: SMU: I'm not done with your previous command: SMN_C2PMSG_66:0x0000001E SMN_C2PMSG_82:0x00000000 [ 110.838035] amdgpu 0000:03:00.0: amdgpu: Failed to disable smu features. [ 110.838039] amdgpu 0000:03:00.0: amdgpu: Fail to disable dpm features! [ 110.838040] [drm:amdgpu_device_ip_suspend_phase2 [amdgpu]] *ERROR* suspend of IP block failed -62 [ 110.884394] PM: suspend of devices aborted after 21213.620 msecs [ 110.884402] PM: start suspend of devices aborted after 21213.882 msecs [ 110.884405] PM: Some devices failed to suspend, or early wake event detected Reviewed-by: Yifan Zhang Signed-off-by: Perry Yuan Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_device.c | 4 ++++ drivers/gpu/drm/amd/include/kgd_pp_interface.h | 1 + drivers/gpu/drm/amd/pm/amdgpu_dpm.c | 18 ++++++++++++++++++ drivers/gpu/drm/amd/pm/inc/amdgpu_dpm.h | 2 ++ drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c | 10 ++++++++++ drivers/gpu/drm/amd/pm/swsmu/inc/amdgpu_smu.h | 5 +++++ drivers/gpu/drm/amd/pm/swsmu/smu11/vangogh_ppt.c | 5 ++--- drivers/gpu/drm/amd/pm/swsmu/smu_internal.h | 1 + 8 files changed, 43 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c index b5edf40b5d03..5d3a83193115 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c @@ -4549,6 +4549,10 @@ int amdgpu_device_suspend(struct drm_device *dev, bool fbcon) if (amdgpu_sriov_vf(adev)) amdgpu_virt_release_full_gpu(adev, false); + r = amdgpu_dpm_notify_rlc_state(adev, false); + if (r) + return r; + return 0; } diff --git a/drivers/gpu/drm/amd/include/kgd_pp_interface.h b/drivers/gpu/drm/amd/include/kgd_pp_interface.h index 6a1d31e8fdd1..8ebba87f4289 100644 --- a/drivers/gpu/drm/amd/include/kgd_pp_interface.h +++ b/drivers/gpu/drm/amd/include/kgd_pp_interface.h @@ -445,6 +445,7 @@ struct amd_pm_funcs { struct dpm_clocks *clock_table); int (*get_smu_prv_buf_details)(void *handle, void **addr, size_t *size); void (*pm_compute_clocks)(void *handle); + int (*notify_rlc_state)(void *handle, bool en); }; struct metrics_table_header { diff --git a/drivers/gpu/drm/amd/pm/amdgpu_dpm.c b/drivers/gpu/drm/amd/pm/amdgpu_dpm.c index 4717884a2bc4..97b40c5fa1ff 100644 --- a/drivers/gpu/drm/amd/pm/amdgpu_dpm.c +++ b/drivers/gpu/drm/amd/pm/amdgpu_dpm.c @@ -181,6 +181,24 @@ int amdgpu_dpm_set_mp1_state(struct amdgpu_device *adev, return ret; } +int amdgpu_dpm_notify_rlc_state(struct amdgpu_device *adev, bool en) +{ + int ret = 0; + const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs; + + if (pp_funcs && pp_funcs->notify_rlc_state) { + mutex_lock(&adev->pm.mutex); + + ret = pp_funcs->notify_rlc_state( + adev->powerplay.pp_handle, + en); + + mutex_unlock(&adev->pm.mutex); + } + + return ret; +} + bool amdgpu_dpm_is_baco_supported(struct amdgpu_device *adev) { const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs; diff --git a/drivers/gpu/drm/amd/pm/inc/amdgpu_dpm.h b/drivers/gpu/drm/amd/pm/inc/amdgpu_dpm.h index 9b3fef5474b1..d76b0a60db44 100644 --- a/drivers/gpu/drm/amd/pm/inc/amdgpu_dpm.h +++ b/drivers/gpu/drm/amd/pm/inc/amdgpu_dpm.h @@ -415,6 +415,8 @@ int amdgpu_dpm_mode1_reset(struct amdgpu_device *adev); int amdgpu_dpm_set_mp1_state(struct amdgpu_device *adev, enum pp_mp1_state mp1_state); +int amdgpu_dpm_notify_rlc_state(struct amdgpu_device *adev, bool en); + int amdgpu_dpm_set_gfx_power_up_by_imu(struct amdgpu_device *adev); int amdgpu_dpm_baco_exit(struct amdgpu_device *adev); diff --git a/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c b/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c index 930e7e3532ad..f464610a959f 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c +++ b/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c @@ -1710,6 +1710,16 @@ static int smu_disable_dpms(struct smu_context *smu) } } + /* Notify SMU RLC is going to be off, stop RLC and SMU interaction. + * otherwise SMU will hang while interacting with RLC if RLC is halted + * this is a WA for Vangogh asic which fix the SMU hang issue. + */ + ret = smu_notify_rlc_state(smu, false); + if (ret) { + dev_err(adev->dev, "Fail to notify rlc status!\n"); + return ret; + } + if (amdgpu_ip_version(adev, GC_HWIP, 0) >= IP_VERSION(9, 4, 2) && !((adev->flags & AMD_IS_APU) && adev->gfx.imu.funcs) && !amdgpu_sriov_vf(adev) && adev->gfx.rlc.funcs->stop) diff --git a/drivers/gpu/drm/amd/pm/swsmu/inc/amdgpu_smu.h b/drivers/gpu/drm/amd/pm/swsmu/inc/amdgpu_smu.h index 32600ba74bf1..c125253df20b 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/inc/amdgpu_smu.h +++ b/drivers/gpu/drm/amd/pm/swsmu/inc/amdgpu_smu.h @@ -1370,6 +1370,11 @@ struct pptable_funcs { * management. */ int (*dpm_set_umsch_mm_enable)(struct smu_context *smu, bool enable); + + /** + * @notify_rlc_state: Notify RLC power state to SMU. + */ + int (*notify_rlc_state)(struct smu_context *smu, bool en); }; typedef enum { diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu11/vangogh_ppt.c b/drivers/gpu/drm/amd/pm/swsmu/smu11/vangogh_ppt.c index 762b31455a0b..2ff6deedef95 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/smu11/vangogh_ppt.c +++ b/drivers/gpu/drm/amd/pm/swsmu/smu11/vangogh_ppt.c @@ -2193,8 +2193,7 @@ static int vangogh_get_dpm_clock_table(struct smu_context *smu, struct dpm_clock return 0; } - -static int vangogh_system_features_control(struct smu_context *smu, bool en) +static int vangogh_notify_rlc_state(struct smu_context *smu, bool en) { struct amdgpu_device *adev = smu->adev; int ret = 0; @@ -2523,7 +2522,7 @@ static const struct pptable_funcs vangogh_ppt_funcs = { .print_clk_levels = vangogh_common_print_clk_levels, .set_default_dpm_table = vangogh_set_default_dpm_tables, .set_fine_grain_gfx_freq_parameters = vangogh_set_fine_grain_gfx_freq_parameters, - .system_features_control = vangogh_system_features_control, + .notify_rlc_state = vangogh_notify_rlc_state, .feature_is_enabled = smu_cmn_feature_is_enabled, .set_power_profile_mode = vangogh_set_power_profile_mode, .get_power_profile_mode = vangogh_get_power_profile_mode, diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu_internal.h b/drivers/gpu/drm/amd/pm/swsmu/smu_internal.h index 80b3c3efc006..64766ac69c53 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/smu_internal.h +++ b/drivers/gpu/drm/amd/pm/swsmu/smu_internal.h @@ -97,6 +97,7 @@ #define smu_get_default_config_table_settings(smu, config_table) smu_ppt_funcs(get_default_config_table_settings, -EOPNOTSUPP, smu, config_table) #define smu_set_config_table(smu, config_table) smu_ppt_funcs(set_config_table, -EOPNOTSUPP, smu, config_table) #define smu_init_pptable_microcode(smu) smu_ppt_funcs(init_pptable_microcode, 0, smu) +#define smu_notify_rlc_state(smu, en) smu_ppt_funcs(notify_rlc_state, 0, smu, en) #endif #endif -- cgit From cfab803884f426b36b58dbe1f86f99742767c208 Mon Sep 17 00:00:00 2001 From: Wenjing Liu Date: Thu, 2 Nov 2023 14:59:13 -0400 Subject: drm/amd/display: update pixel clock params after stream slice count change in context [why] When ODM slice count is changed, otg master pipe's pixel clock params is no longer valid as the value is dependent on ODM slice count. Reviewed-by: Chaitanya Dhere Acked-by: Hamza Mahfooz Signed-off-by: Wenjing Liu Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc_resource.c | 9 ++++++--- drivers/gpu/drm/amd/display/dc/dml/dcn32/dcn32_fpu.c | 6 +----- drivers/gpu/drm/amd/display/dc/inc/core_types.h | 1 + .../drm/amd/display/dc/resource/dcn20/dcn20_resource.c | 16 ++++++++++------ .../drm/amd/display/dc/resource/dcn20/dcn20_resource.h | 1 + .../drm/amd/display/dc/resource/dcn32/dcn32_resource.c | 1 + .../drm/amd/display/dc/resource/dcn321/dcn321_resource.c | 1 + 7 files changed, 21 insertions(+), 14 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c index 42a927710743..84d632700949 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c @@ -2256,7 +2256,7 @@ static struct pipe_ctx *get_last_dpp_pipe_in_mpcc_combine( } static bool update_pipe_params_after_odm_slice_count_change( - const struct dc_stream_state *stream, + struct pipe_ctx *otg_master, struct dc_state *context, const struct resource_pool *pool) { @@ -2266,9 +2266,12 @@ static bool update_pipe_params_after_odm_slice_count_change( for (i = 0; i < pool->pipe_count && result; i++) { pipe = &context->res_ctx.pipe_ctx[i]; - if (pipe->stream == stream && pipe->plane_state) + if (pipe->stream == otg_master->stream && pipe->plane_state) result = resource_build_scaling_params(pipe); } + + if (pool->funcs->build_pipe_pix_clk_params) + pool->funcs->build_pipe_pix_clk_params(otg_master); return result; } @@ -2951,7 +2954,7 @@ bool resource_update_pipes_for_stream_with_slice_count( otg_master, new_ctx, pool); if (result) result = update_pipe_params_after_odm_slice_count_change( - otg_master->stream, new_ctx, pool); + otg_master, new_ctx, pool); return result; } diff --git a/drivers/gpu/drm/amd/display/dc/dml/dcn32/dcn32_fpu.c b/drivers/gpu/drm/amd/display/dc/dml/dcn32/dcn32_fpu.c index 44b0666e53b0..e7f13e28caa3 100644 --- a/drivers/gpu/drm/amd/display/dc/dml/dcn32/dcn32_fpu.c +++ b/drivers/gpu/drm/amd/display/dc/dml/dcn32/dcn32_fpu.c @@ -1237,15 +1237,11 @@ static void update_pipes_with_slice_table(struct dc *dc, struct dc_state *contex { int i; - for (i = 0; i < table->odm_combine_count; i++) { + for (i = 0; i < table->odm_combine_count; i++) resource_update_pipes_for_stream_with_slice_count(context, dc->current_state, dc->res_pool, table->odm_combines[i].stream, table->odm_combines[i].slice_count); - /* TODO: move this into the function above */ - dcn20_build_mapped_resource(dc, context, - table->odm_combines[i].stream); - } for (i = 0; i < table->mpc_combine_count; i++) resource_update_pipes_for_plane_with_slice_count(context, diff --git a/drivers/gpu/drm/amd/display/dc/inc/core_types.h b/drivers/gpu/drm/amd/display/dc/inc/core_types.h index bac1420b1de8..10397d4dfb07 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/core_types.h +++ b/drivers/gpu/drm/amd/display/dc/inc/core_types.h @@ -205,6 +205,7 @@ struct resource_funcs { void (*get_panel_config_defaults)(struct dc_panel_config *panel_config); void (*save_mall_state)(struct dc *dc, struct dc_state *context, struct mall_temp_config *temp_config); void (*restore_mall_state)(struct dc *dc, struct dc_state *context, struct mall_temp_config *temp_config); + void (*build_pipe_pix_clk_params)(struct pipe_ctx *pipe_ctx); }; struct audio_support{ diff --git a/drivers/gpu/drm/amd/display/dc/resource/dcn20/dcn20_resource.c b/drivers/gpu/drm/amd/display/dc/resource/dcn20/dcn20_resource.c index f04bb5b1471d..f9c5bc624be3 100644 --- a/drivers/gpu/drm/amd/display/dc/resource/dcn20/dcn20_resource.c +++ b/drivers/gpu/drm/amd/display/dc/resource/dcn20/dcn20_resource.c @@ -1273,15 +1273,19 @@ static void build_clamping_params(struct dc_stream_state *stream) stream->clamping.pixel_encoding = stream->timing.pixel_encoding; } -static enum dc_status build_pipe_hw_param(struct pipe_ctx *pipe_ctx) +void dcn20_build_pipe_pix_clk_params(struct pipe_ctx *pipe_ctx) { - get_pixel_clock_parameters(pipe_ctx, &pipe_ctx->stream_res.pix_clk_params); - pipe_ctx->clock_source->funcs->get_pix_clk_dividers( - pipe_ctx->clock_source, - &pipe_ctx->stream_res.pix_clk_params, - &pipe_ctx->pll_settings); + pipe_ctx->clock_source, + &pipe_ctx->stream_res.pix_clk_params, + &pipe_ctx->pll_settings); +} + +static enum dc_status build_pipe_hw_param(struct pipe_ctx *pipe_ctx) +{ + + dcn20_build_pipe_pix_clk_params(pipe_ctx); pipe_ctx->stream->clamping.pixel_encoding = pipe_ctx->stream->timing.pixel_encoding; diff --git a/drivers/gpu/drm/amd/display/dc/resource/dcn20/dcn20_resource.h b/drivers/gpu/drm/amd/display/dc/resource/dcn20/dcn20_resource.h index 37ecaccc5d12..4cee3fa11a7f 100644 --- a/drivers/gpu/drm/amd/display/dc/resource/dcn20/dcn20_resource.h +++ b/drivers/gpu/drm/amd/display/dc/resource/dcn20/dcn20_resource.h @@ -165,6 +165,7 @@ enum dc_status dcn20_add_stream_to_ctx(struct dc *dc, struct dc_state *new_ctx, enum dc_status dcn20_add_dsc_to_stream_resource(struct dc *dc, struct dc_state *dc_ctx, struct dc_stream_state *dc_stream); enum dc_status dcn20_remove_stream_from_ctx(struct dc *dc, struct dc_state *new_ctx, struct dc_stream_state *dc_stream); enum dc_status dcn20_patch_unknown_plane_state(struct dc_plane_state *plane_state); +void dcn20_build_pipe_pix_clk_params(struct pipe_ctx *pipe_ctx); #endif /* __DC_RESOURCE_DCN20_H__ */ diff --git a/drivers/gpu/drm/amd/display/dc/resource/dcn32/dcn32_resource.c b/drivers/gpu/drm/amd/display/dc/resource/dcn32/dcn32_resource.c index 36e4c7bef403..f6cbcc9b4006 100644 --- a/drivers/gpu/drm/amd/display/dc/resource/dcn32/dcn32_resource.c +++ b/drivers/gpu/drm/amd/display/dc/resource/dcn32/dcn32_resource.c @@ -2041,6 +2041,7 @@ static struct resource_funcs dcn32_res_pool_funcs = { .retain_phantom_pipes = dcn32_retain_phantom_pipes, .save_mall_state = dcn32_save_mall_state, .restore_mall_state = dcn32_restore_mall_state, + .build_pipe_pix_clk_params = dcn20_build_pipe_pix_clk_params, }; static uint32_t read_pipe_fuses(struct dc_context *ctx) diff --git a/drivers/gpu/drm/amd/display/dc/resource/dcn321/dcn321_resource.c b/drivers/gpu/drm/amd/display/dc/resource/dcn321/dcn321_resource.c index bedb70b98162..12986fe0b289 100644 --- a/drivers/gpu/drm/amd/display/dc/resource/dcn321/dcn321_resource.c +++ b/drivers/gpu/drm/amd/display/dc/resource/dcn321/dcn321_resource.c @@ -1609,6 +1609,7 @@ static struct resource_funcs dcn321_res_pool_funcs = { .retain_phantom_pipes = dcn32_retain_phantom_pipes, .save_mall_state = dcn32_save_mall_state, .restore_mall_state = dcn32_restore_mall_state, + .build_pipe_pix_clk_params = dcn20_build_pipe_pix_clk_params, }; static uint32_t read_pipe_fuses(struct dc_context *ctx) -- cgit From 1290183db494641772c18d063c34e9c8f720c61c Mon Sep 17 00:00:00 2001 From: Wenjing Liu Date: Thu, 2 Nov 2023 15:02:42 -0400 Subject: drm/amd/display: always use mpc factor of 2 for stereo timings [why] In the new pipe resource management logic, the special handling for stereo timings is missing. This commit implements the same stereo timings handling as old pipe resource management code. Reviewed-by: Chaitanya Dhere Acked-by: Hamza Mahfooz Signed-off-by: Wenjing Liu Signed-off-by: Alex Deucher --- .../amd/display/dc/dml2/dml2_dc_resource_mgmt.c | 26 +++++++++++++++------- drivers/gpu/drm/amd/display/dc/dml2/dml2_utils.c | 2 +- drivers/gpu/drm/amd/display/dc/dml2/dml2_utils.h | 2 +- 3 files changed, 20 insertions(+), 10 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/dml2/dml2_dc_resource_mgmt.c b/drivers/gpu/drm/amd/display/dc/dml2/dml2_dc_resource_mgmt.c index 1a2b24cc6b61..0baf39d64a2d 100644 --- a/drivers/gpu/drm/amd/display/dc/dml2/dml2_dc_resource_mgmt.c +++ b/drivers/gpu/drm/amd/display/dc/dml2/dml2_dc_resource_mgmt.c @@ -772,18 +772,29 @@ static unsigned int get_mpc_factor(struct dml2_context *ctx, const struct dc_state *state, const struct dml_display_cfg_st *disp_cfg, struct dml2_dml_to_dc_pipe_mapping *mapping, - const struct dc_stream_status *status, unsigned int stream_id, + const struct dc_stream_status *status, + const struct dc_stream_state *stream, int plane_idx) { unsigned int plane_id; unsigned int cfg_idx; + unsigned int mpc_factor; - get_plane_id(ctx, state, status->plane_states[plane_idx], stream_id, plane_idx, &plane_id); + get_plane_id(ctx, state, status->plane_states[plane_idx], + stream->stream_id, plane_idx, &plane_id); cfg_idx = find_disp_cfg_idx_by_plane_id(mapping, plane_id); - if (ctx->architecture == dml2_architecture_20) - return (unsigned int)disp_cfg->hw.DPPPerSurface[cfg_idx]; - ASSERT(false); - return 1; + if (ctx->architecture == dml2_architecture_20) { + mpc_factor = (unsigned int)disp_cfg->hw.DPPPerSurface[cfg_idx]; + } else { + mpc_factor = 1; + ASSERT(false); + } + + /* For stereo timings, we need to pipe split */ + if (dml2_is_stereo_timing(stream)) + mpc_factor = 2; + + return mpc_factor; } static unsigned int get_odm_factor( @@ -820,14 +831,13 @@ static void populate_mpc_factors_for_stream( unsigned int mpc_factors[MAX_PIPES]) { const struct dc_stream_status *status = &state->stream_status[stream_idx]; - unsigned int stream_id = state->streams[stream_idx]->stream_id; int i; for (i = 0; i < status->plane_count; i++) if (odm_factor == 1) mpc_factors[i] = get_mpc_factor( ctx, state, disp_cfg, mapping, status, - stream_id, i); + state->streams[stream_idx], i); else mpc_factors[i] = 1; } diff --git a/drivers/gpu/drm/amd/display/dc/dml2/dml2_utils.c b/drivers/gpu/drm/amd/display/dc/dml2/dml2_utils.c index 2498b8341199..33eab80e89a8 100644 --- a/drivers/gpu/drm/amd/display/dc/dml2/dml2_utils.c +++ b/drivers/gpu/drm/amd/display/dc/dml2/dml2_utils.c @@ -468,7 +468,7 @@ bool dml2_verify_det_buffer_configuration(struct dml2_context *in_ctx, struct dc return need_recalculation; } -bool dml2_is_stereo_timing(struct dc_stream_state *stream) +bool dml2_is_stereo_timing(const struct dc_stream_state *stream) { bool is_stereo = false; diff --git a/drivers/gpu/drm/amd/display/dc/dml2/dml2_utils.h b/drivers/gpu/drm/amd/display/dc/dml2/dml2_utils.h index 23b9028337d4..5842d6d3c4b6 100644 --- a/drivers/gpu/drm/amd/display/dc/dml2/dml2_utils.h +++ b/drivers/gpu/drm/amd/display/dc/dml2/dml2_utils.h @@ -42,7 +42,7 @@ void dml2_copy_clocks_to_dc_state(struct dml2_dcn_clocks *out_clks, struct dc_st void dml2_extract_watermark_set(struct dcn_watermarks *watermark, struct display_mode_lib_st *dml_core_ctx); int dml2_helper_find_dml_pipe_idx_by_stream_id(struct dml2_context *ctx, unsigned int stream_id); bool is_dtbclk_required(const struct dc *dc, struct dc_state *context); -bool dml2_is_stereo_timing(struct dc_stream_state *stream); +bool dml2_is_stereo_timing(const struct dc_stream_state *stream); /* * dml2_dc_construct_pipes - This function will determine if we need additional pipes based -- cgit From 80061d6b58a99f1fffb97a7f3592234a5fe0a3fe Mon Sep 17 00:00:00 2001 From: Nicholas Kazlauskas Date: Tue, 7 Nov 2023 11:12:45 -0500 Subject: drm/amd/display: Add Z8 watermarks for DML2 bbox overrides [Why] We can override SR watermarks but not Z8 ones. [How] Add new parameters for Z8 matching the SR ones and feed them into the states. These also weren't being applied to every state, so make sure that we loop over and update all SOC states if given an override. Reviewed-by: Jun Lei Acked-by: Hamza Mahfooz Signed-off-by: Nicholas Kazlauskas Signed-off-by: Alex Deucher --- .../amd/display/dc/dml2/dml2_translation_helper.c | 47 +++++++++++++++------- drivers/gpu/drm/amd/display/dc/dml2/dml2_wrapper.h | 2 + 2 files changed, 34 insertions(+), 15 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/dml2/dml2_translation_helper.c b/drivers/gpu/drm/amd/display/dc/dml2/dml2_translation_helper.c index 75171bee6f71..2b9638c6d9b0 100644 --- a/drivers/gpu/drm/amd/display/dc/dml2/dml2_translation_helper.c +++ b/drivers/gpu/drm/amd/display/dc/dml2/dml2_translation_helper.c @@ -341,25 +341,42 @@ void dml2_init_soc_states(struct dml2_context *dml2, const struct dc *in_dc, break; } - /* Override from passed values, mainly for debugging purposes, if available */ - if (dml2->config.bbox_overrides.sr_exit_latency_us) { - p->in_states->state_array[0].sr_exit_time_us = dml2->config.bbox_overrides.sr_exit_latency_us; - } + /* Override from passed values, if available */ + for (i = 0; i < p->in_states->num_states; i++) { + if (dml2->config.bbox_overrides.sr_exit_latency_us) { + p->in_states->state_array[i].sr_exit_time_us = + dml2->config.bbox_overrides.sr_exit_latency_us; + } - if (dml2->config.bbox_overrides.sr_enter_plus_exit_latency_us) { - p->in_states->state_array[0].sr_enter_plus_exit_time_us = dml2->config.bbox_overrides.sr_enter_plus_exit_latency_us; - } + if (dml2->config.bbox_overrides.sr_enter_plus_exit_latency_us) { + p->in_states->state_array[i].sr_enter_plus_exit_time_us = + dml2->config.bbox_overrides.sr_enter_plus_exit_latency_us; + } - if (dml2->config.bbox_overrides.urgent_latency_us) { - p->in_states->state_array[0].urgent_latency_pixel_data_only_us = dml2->config.bbox_overrides.urgent_latency_us; - } + if (dml2->config.bbox_overrides.sr_exit_z8_time_us) { + p->in_states->state_array[i].sr_exit_z8_time_us = + dml2->config.bbox_overrides.sr_exit_z8_time_us; + } - if (dml2->config.bbox_overrides.dram_clock_change_latency_us) { - p->in_states->state_array[0].dram_clock_change_latency_us = dml2->config.bbox_overrides.dram_clock_change_latency_us; - } + if (dml2->config.bbox_overrides.sr_enter_plus_exit_z8_time_us) { + p->in_states->state_array[i].sr_enter_plus_exit_z8_time_us = + dml2->config.bbox_overrides.sr_enter_plus_exit_z8_time_us; + } + + if (dml2->config.bbox_overrides.urgent_latency_us) { + p->in_states->state_array[i].urgent_latency_pixel_data_only_us = + dml2->config.bbox_overrides.urgent_latency_us; + } - if (dml2->config.bbox_overrides.fclk_change_latency_us) { - p->in_states->state_array[0].fclk_change_latency_us = dml2->config.bbox_overrides.fclk_change_latency_us; + if (dml2->config.bbox_overrides.dram_clock_change_latency_us) { + p->in_states->state_array[i].dram_clock_change_latency_us = + dml2->config.bbox_overrides.dram_clock_change_latency_us; + } + + if (dml2->config.bbox_overrides.fclk_change_latency_us) { + p->in_states->state_array[i].fclk_change_latency_us = + dml2->config.bbox_overrides.fclk_change_latency_us; + } } /* DCFCLK stas values are project specific */ diff --git a/drivers/gpu/drm/amd/display/dc/dml2/dml2_wrapper.h b/drivers/gpu/drm/amd/display/dc/dml2/dml2_wrapper.h index 317f90776d97..fe15baa4bf09 100644 --- a/drivers/gpu/drm/amd/display/dc/dml2/dml2_wrapper.h +++ b/drivers/gpu/drm/amd/display/dc/dml2/dml2_wrapper.h @@ -139,6 +139,8 @@ struct dml2_soc_bbox_overrides { double urgent_latency_us; double sr_exit_latency_us; double sr_enter_plus_exit_latency_us; + double sr_exit_z8_time_us; + double sr_enter_plus_exit_z8_time_us; double dram_clock_change_latency_us; double fclk_change_latency_us; unsigned int dram_num_chan; -- cgit From 4b8251e019ea17037667e6d61aa5e66d5b4f51d2 Mon Sep 17 00:00:00 2001 From: Hawking Zhang Date: Mon, 20 Nov 2023 10:14:21 +0800 Subject: drm/amdgpu: Do not issue gpu reset from nbio v7_9 bif interrupt In nbio v7_9, host driver should not issu gpu reset Signed-off-by: Hawking Zhang Reviewed-by: Stanley Yang Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/nbio_v7_9.c | 5 ----- 1 file changed, 5 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/nbio_v7_9.c b/drivers/gpu/drm/amd/amdgpu/nbio_v7_9.c index 23f26f8caad4..25a3da83e0fb 100644 --- a/drivers/gpu/drm/amd/amdgpu/nbio_v7_9.c +++ b/drivers/gpu/drm/amd/amdgpu/nbio_v7_9.c @@ -611,11 +611,6 @@ static void nbio_v7_9_handle_ras_controller_intr_no_bifring(struct amdgpu_device dev_info(adev->dev, "RAS controller interrupt triggered " "by NBIF error\n"); - - /* ras_controller_int is dedicated for nbif ras error, - * not the global interrupt for sync flood - */ - amdgpu_ras_reset_gpu(adev); } amdgpu_ras_error_data_fini(&err_data); -- cgit From 20b07b0cb3a0a2fb3a6daf00f645925be77ec80c Mon Sep 17 00:00:00 2001 From: Alex Sierra Date: Mon, 20 Nov 2023 11:31:32 -0600 Subject: drm/amdgpu: Force order between a read and write to the same address Setting register to force ordering to prevent read/write or write/read hazards for un-cached modes. Signed-off-by: Alex Sierra Acked-by: Alex Deucher Reviewed-by: Felix Kuehling Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c | 8 ++++++++ drivers/gpu/drm/amd/include/asic_reg/gc/gc_11_0_0_offset.h | 2 ++ 2 files changed, 10 insertions(+) diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c b/drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c index 0c6133cc5e57..40ce12323164 100644 --- a/drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c @@ -89,6 +89,10 @@ MODULE_FIRMWARE("amdgpu/gc_11_5_0_me.bin"); MODULE_FIRMWARE("amdgpu/gc_11_5_0_mec.bin"); MODULE_FIRMWARE("amdgpu/gc_11_5_0_rlc.bin"); +static const struct soc15_reg_golden golden_settings_gc_11_0[] = { + SOC15_REG_GOLDEN_VALUE(GC, 0, regTCP_CNTL, 0x20000000, 0x20000000) +}; + static const struct soc15_reg_golden golden_settings_gc_11_0_1[] = { SOC15_REG_GOLDEN_VALUE(GC, 0, regCGTT_GS_NGG_CLK_CTRL, 0x9fff8fff, 0x00000010), @@ -304,6 +308,10 @@ static void gfx_v11_0_init_golden_registers(struct amdgpu_device *adev) default: break; } + soc15_program_register_sequence(adev, + golden_settings_gc_11_0, + (const u32)ARRAY_SIZE(golden_settings_gc_11_0)); + } static void gfx_v11_0_write_data_to_reg(struct amdgpu_ring *ring, int eng_sel, diff --git a/drivers/gpu/drm/amd/include/asic_reg/gc/gc_11_0_0_offset.h b/drivers/gpu/drm/amd/include/asic_reg/gc/gc_11_0_0_offset.h index c92c4b83253f..4bff1ef8a9a6 100644 --- a/drivers/gpu/drm/amd/include/asic_reg/gc/gc_11_0_0_offset.h +++ b/drivers/gpu/drm/amd/include/asic_reg/gc/gc_11_0_0_offset.h @@ -6369,6 +6369,8 @@ #define regTCP_INVALIDATE_BASE_IDX 1 #define regTCP_STATUS 0x19a1 #define regTCP_STATUS_BASE_IDX 1 +#define regTCP_CNTL 0x19a2 +#define regTCP_CNTL_BASE_IDX 1 #define regTCP_CNTL2 0x19a3 #define regTCP_CNTL2_BASE_IDX 1 #define regTCP_DEBUG_INDEX 0x19a5 -- cgit From 251027968a7230f18c353e25634cc7e25d9ab953 Mon Sep 17 00:00:00 2001 From: Nicholas Kazlauskas Date: Tue, 7 Nov 2023 11:15:16 -0500 Subject: drm/amd/display: Feed SR and Z8 watermarks into DML2 for DCN35 [Why] We've updated the table but the values aren't being reflected in DML2 calculation. [How] Pass them into the bbox overrides. Reviewed-by: Jun Lei Acked-by: Hamza Mahfooz Signed-off-by: Nicholas Kazlauskas Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dml/dcn35/dcn35_fpu.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/drivers/gpu/drm/amd/display/dc/dml/dcn35/dcn35_fpu.c b/drivers/gpu/drm/amd/display/dc/dml/dcn35/dcn35_fpu.c index 30d78ad91b9c..21c17d3296a3 100644 --- a/drivers/gpu/drm/amd/display/dc/dml/dcn35/dcn35_fpu.c +++ b/drivers/gpu/drm/amd/display/dc/dml/dcn35/dcn35_fpu.c @@ -329,6 +329,15 @@ void dcn35_update_bw_bounding_box_fpu(struct dc *dc, /*temp till dml2 fully work without dml1*/ dml_init_instance(&dc->dml, &dcn3_5_soc, &dcn3_5_ip, DML_PROJECT_DCN31); + + /* Update latency values */ + dc->dml2_options.bbox_overrides.dram_clock_change_latency_us = dcn3_5_soc.dram_clock_change_latency_us; + + dc->dml2_options.bbox_overrides.sr_exit_latency_us = dcn3_5_soc.sr_exit_time_us; + dc->dml2_options.bbox_overrides.sr_enter_plus_exit_latency_us = dcn3_5_soc.sr_enter_plus_exit_time_us; + + dc->dml2_options.bbox_overrides.sr_exit_z8_time_us = dcn3_5_soc.sr_exit_z8_time_us; + dc->dml2_options.bbox_overrides.sr_enter_plus_exit_z8_time_us = dcn3_5_soc.sr_enter_plus_exit_z8_time_us; } static bool is_dual_plane(enum surface_pixel_format format) -- cgit From a953cd8cac6be69fba0b66e6fb46d1324d797af4 Mon Sep 17 00:00:00 2001 From: Ilya Bakoulin Date: Tue, 7 Nov 2023 15:07:56 -0500 Subject: drm/amd/display: Fix MPCC 1DLUT programming [Why] Wrong function is used to translate LUT values to HW format, leading to visible artifacting in some cases. [How] Use the correct cm3_helper function. Cc: stable@vger.kernel.org # 6.1+ Reviewed-by: Krunoslav Kovac Acked-by: Hamza Mahfooz Signed-off-by: Ilya Bakoulin Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/hwss/dcn32/dcn32_hwseq.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/hwss/dcn32/dcn32_hwseq.c b/drivers/gpu/drm/amd/display/dc/hwss/dcn32/dcn32_hwseq.c index 6a65af8c36b9..5f7f474ef51c 100644 --- a/drivers/gpu/drm/amd/display/dc/hwss/dcn32/dcn32_hwseq.c +++ b/drivers/gpu/drm/amd/display/dc/hwss/dcn32/dcn32_hwseq.c @@ -487,8 +487,7 @@ bool dcn32_set_mcm_luts( if (plane_state->blend_tf->type == TF_TYPE_HWPWL) lut_params = &plane_state->blend_tf->pwl; else if (plane_state->blend_tf->type == TF_TYPE_DISTRIBUTED_POINTS) { - cm_helper_translate_curve_to_hw_format(plane_state->ctx, - plane_state->blend_tf, + cm3_helper_translate_curve_to_hw_format(plane_state->blend_tf, &dpp_base->regamma_params, false); lut_params = &dpp_base->regamma_params; } @@ -503,8 +502,7 @@ bool dcn32_set_mcm_luts( else if (plane_state->in_shaper_func->type == TF_TYPE_DISTRIBUTED_POINTS) { // TODO: dpp_base replace ASSERT(false); - cm_helper_translate_curve_to_hw_format(plane_state->ctx, - plane_state->in_shaper_func, + cm3_helper_translate_curve_to_hw_format(plane_state->in_shaper_func, &dpp_base->shaper_params, true); lut_params = &dpp_base->shaper_params; } -- cgit From 40436ce7ccfec5c616e2e48d0ec2c905637c7397 Mon Sep 17 00:00:00 2001 From: Alvin Lee Date: Tue, 7 Nov 2023 17:01:49 -0500 Subject: drm/amd/display: Use DRAM speed from validation for dummy p-state [Description] When choosing which dummy p-state latency to use, we need to use the DRAM speed from validation. The DRAMSpeed DML variable can change because we use different input params to DML when populating watermarks set B. Cc: stable@vger.kernel.org # 6.1+ Reviewed-by: Samson Tam Acked-by: Hamza Mahfooz Signed-off-by: Alvin Lee Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dml/dcn32/dcn32_fpu.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/display/dc/dml/dcn32/dcn32_fpu.c b/drivers/gpu/drm/amd/display/dc/dml/dcn32/dcn32_fpu.c index e7f13e28caa3..92e2ddc9ab7e 100644 --- a/drivers/gpu/drm/amd/display/dc/dml/dcn32/dcn32_fpu.c +++ b/drivers/gpu/drm/amd/display/dc/dml/dcn32/dcn32_fpu.c @@ -2231,6 +2231,7 @@ void dcn32_calculate_wm_and_dlg_fpu(struct dc *dc, struct dc_state *context, int i, pipe_idx, vlevel_temp = 0; double dcfclk = dcn3_2_soc.clock_limits[0].dcfclk_mhz; double dcfclk_from_validation = context->bw_ctx.dml.vba.DCFCLKState[vlevel][context->bw_ctx.dml.vba.maxMpcComb]; + double dram_speed_from_validation = context->bw_ctx.dml.vba.DRAMSpeed; double dcfclk_from_fw_based_mclk_switching = dcfclk_from_validation; bool pstate_en = context->bw_ctx.dml.vba.DRAMClockChangeSupport[vlevel][context->bw_ctx.dml.vba.maxMpcComb] != dm_dram_clock_change_unsupported; @@ -2418,7 +2419,7 @@ void dcn32_calculate_wm_and_dlg_fpu(struct dc *dc, struct dc_state *context, } if (dc->clk_mgr->bw_params->wm_table.nv_entries[WM_C].valid) { - min_dram_speed_mts = context->bw_ctx.dml.vba.DRAMSpeed; + min_dram_speed_mts = dram_speed_from_validation; min_dram_speed_mts_margin = 160; context->bw_ctx.dml.soc.dram_clock_change_latency_us = -- cgit From 6c22fb07e0c2935d97a86509f16f755ab895f2c8 Mon Sep 17 00:00:00 2001 From: Bhuvana Chandra Pinninti Date: Wed, 18 Oct 2023 19:16:17 +0530 Subject: drm/amd/display: Refactor DSC into component folder [why] To refactor DSC and make DSC files unit testable. [how] moved the dcnxx_dsc.c and .h files into corresponding dcn folders inside the dsc and cleared the linkage errors. Reviewed-by: Wenjing Liu Acked-by: Hamza Mahfooz Signed-off-by: Bhuvana Chandra Pinninti Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/Makefile | 1 + drivers/gpu/drm/amd/display/dc/dcn20/Makefile | 2 - drivers/gpu/drm/amd/display/dc/dcn20/dcn20_dsc.c | 780 --------------------- drivers/gpu/drm/amd/display/dc/dcn20/dcn20_dsc.h | 589 ---------------- drivers/gpu/drm/amd/display/dc/dcn35/Makefile | 2 +- drivers/gpu/drm/amd/display/dc/dcn35/dcn35_dsc.c | 60 -- drivers/gpu/drm/amd/display/dc/dcn35/dcn35_dsc.h | 59 -- drivers/gpu/drm/amd/display/dc/dsc/Makefile | 26 + .../gpu/drm/amd/display/dc/dsc/dcn20/dcn20_dsc.c | 780 +++++++++++++++++++++ .../gpu/drm/amd/display/dc/dsc/dcn20/dcn20_dsc.h | 589 ++++++++++++++++ .../gpu/drm/amd/display/dc/dsc/dcn35/dcn35_dsc.c | 60 ++ .../gpu/drm/amd/display/dc/dsc/dcn35/dcn35_dsc.h | 59 ++ drivers/gpu/drm/amd/display/dc/dsc/dsc.h | 112 +++ drivers/gpu/drm/amd/display/dc/inc/hw/dsc.h | 112 --- 14 files changed, 1628 insertions(+), 1603 deletions(-) delete mode 100644 drivers/gpu/drm/amd/display/dc/dcn20/dcn20_dsc.c delete mode 100644 drivers/gpu/drm/amd/display/dc/dcn20/dcn20_dsc.h delete mode 100644 drivers/gpu/drm/amd/display/dc/dcn35/dcn35_dsc.c delete mode 100644 drivers/gpu/drm/amd/display/dc/dcn35/dcn35_dsc.h create mode 100644 drivers/gpu/drm/amd/display/dc/dsc/dcn20/dcn20_dsc.c create mode 100644 drivers/gpu/drm/amd/display/dc/dsc/dcn20/dcn20_dsc.h create mode 100644 drivers/gpu/drm/amd/display/dc/dsc/dcn35/dcn35_dsc.c create mode 100644 drivers/gpu/drm/amd/display/dc/dsc/dcn35/dcn35_dsc.h create mode 100644 drivers/gpu/drm/amd/display/dc/dsc/dsc.h delete mode 100644 drivers/gpu/drm/amd/display/dc/inc/hw/dsc.h diff --git a/drivers/gpu/drm/amd/display/Makefile b/drivers/gpu/drm/amd/display/Makefile index 71192fc81a20..7b0959da2cac 100644 --- a/drivers/gpu/drm/amd/display/Makefile +++ b/drivers/gpu/drm/amd/display/Makefile @@ -31,6 +31,7 @@ subdir-ccflags-y += -I$(FULL_AMD_DISPLAY_PATH)/dc/inc/hw subdir-ccflags-y += -I$(FULL_AMD_DISPLAY_PATH)/dc/clk_mgr subdir-ccflags-y += -I$(FULL_AMD_DISPLAY_PATH)/dc/hwss subdir-ccflags-y += -I$(FULL_AMD_DISPLAY_PATH)/dc/resource +subdir-ccflags-y += -I$(FULL_AMD_DISPLAY_PATH)/dc/dsc subdir-ccflags-y += -I$(FULL_AMD_DISPLAY_PATH)/modules/inc subdir-ccflags-y += -I$(FULL_AMD_DISPLAY_PATH)/modules/freesync subdir-ccflags-y += -I$(FULL_AMD_DISPLAY_PATH)/modules/color diff --git a/drivers/gpu/drm/amd/display/dc/dcn20/Makefile b/drivers/gpu/drm/amd/display/dc/dcn20/Makefile index 1cac1eca8111..93ac45802e44 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn20/Makefile +++ b/drivers/gpu/drm/amd/display/dc/dcn20/Makefile @@ -7,8 +7,6 @@ DCN20 = dcn20_init.o dcn20_dpp.o dcn20_dpp_cm.o dcn20_hubp.o \ dcn20_stream_encoder.o dcn20_link_encoder.o dcn20_dccg.o \ dcn20_vmid.o dcn20_dwb.o dcn20_dwb_scl.o -DCN20 += dcn20_dsc.o - AMD_DAL_DCN20 = $(addprefix $(AMDDALPATH)/dc/dcn20/,$(DCN20)) AMD_DISPLAY_FILES += $(AMD_DAL_DCN20) diff --git a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_dsc.c b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_dsc.c deleted file mode 100644 index c9ae2d8f0096..000000000000 --- a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_dsc.c +++ /dev/null @@ -1,780 +0,0 @@ -/* - * Copyright 2017 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 - -#include "reg_helper.h" -#include "dcn20_dsc.h" -#include "dsc/dscc_types.h" -#include "dsc/rc_calc.h" - -static void dsc_write_to_registers(struct display_stream_compressor *dsc, const struct dsc_reg_values *reg_vals); - -/* Object I/F functions */ -static void dsc2_read_state(struct display_stream_compressor *dsc, struct dcn_dsc_state *s); -static bool dsc2_validate_stream(struct display_stream_compressor *dsc, const struct dsc_config *dsc_cfg); -static void dsc2_set_config(struct display_stream_compressor *dsc, const struct dsc_config *dsc_cfg, - struct dsc_optc_config *dsc_optc_cfg); -static void dsc2_enable(struct display_stream_compressor *dsc, int opp_pipe); -static void dsc2_disable(struct display_stream_compressor *dsc); -static void dsc2_disconnect(struct display_stream_compressor *dsc); - -static const struct dsc_funcs dcn20_dsc_funcs = { - .dsc_get_enc_caps = dsc2_get_enc_caps, - .dsc_read_state = dsc2_read_state, - .dsc_validate_stream = dsc2_validate_stream, - .dsc_set_config = dsc2_set_config, - .dsc_get_packed_pps = dsc2_get_packed_pps, - .dsc_enable = dsc2_enable, - .dsc_disable = dsc2_disable, - .dsc_disconnect = dsc2_disconnect, -}; - -/* Macro definitios for REG_SET macros*/ -#define CTX \ - dsc20->base.ctx - -#define REG(reg)\ - dsc20->dsc_regs->reg - -#undef FN -#define FN(reg_name, field_name) \ - dsc20->dsc_shift->field_name, dsc20->dsc_mask->field_name -#define DC_LOGGER \ - dsc->ctx->logger - -enum dsc_bits_per_comp { - DSC_BPC_8 = 8, - DSC_BPC_10 = 10, - DSC_BPC_12 = 12, - DSC_BPC_UNKNOWN -}; - -/* API functions (external or via structure->function_pointer) */ - -void dsc2_construct(struct dcn20_dsc *dsc, - struct dc_context *ctx, - int inst, - const struct dcn20_dsc_registers *dsc_regs, - const struct dcn20_dsc_shift *dsc_shift, - const struct dcn20_dsc_mask *dsc_mask) -{ - dsc->base.ctx = ctx; - dsc->base.inst = inst; - dsc->base.funcs = &dcn20_dsc_funcs; - - dsc->dsc_regs = dsc_regs; - dsc->dsc_shift = dsc_shift; - dsc->dsc_mask = dsc_mask; - - dsc->max_image_width = 5184; -} - - -#define DCN20_MAX_PIXEL_CLOCK_Mhz 1188 -#define DCN20_MAX_DISPLAY_CLOCK_Mhz 1200 - -/* This returns the capabilities for a single DSC encoder engine. Number of slices and total throughput - * can be doubled, tripled etc. by using additional DSC engines. - */ -void dsc2_get_enc_caps(struct dsc_enc_caps *dsc_enc_caps, int pixel_clock_100Hz) -{ - dsc_enc_caps->dsc_version = 0x21; /* v1.2 - DP spec defined it in reverse order and we kept it */ - - dsc_enc_caps->slice_caps.bits.NUM_SLICES_1 = 1; - dsc_enc_caps->slice_caps.bits.NUM_SLICES_2 = 1; - dsc_enc_caps->slice_caps.bits.NUM_SLICES_3 = 1; - dsc_enc_caps->slice_caps.bits.NUM_SLICES_4 = 1; - - dsc_enc_caps->lb_bit_depth = 13; - dsc_enc_caps->is_block_pred_supported = true; - - dsc_enc_caps->color_formats.bits.RGB = 1; - dsc_enc_caps->color_formats.bits.YCBCR_444 = 1; - dsc_enc_caps->color_formats.bits.YCBCR_SIMPLE_422 = 1; - dsc_enc_caps->color_formats.bits.YCBCR_NATIVE_422 = 0; - dsc_enc_caps->color_formats.bits.YCBCR_NATIVE_420 = 1; - - dsc_enc_caps->color_depth.bits.COLOR_DEPTH_8_BPC = 1; - dsc_enc_caps->color_depth.bits.COLOR_DEPTH_10_BPC = 1; - dsc_enc_caps->color_depth.bits.COLOR_DEPTH_12_BPC = 1; - - /* Maximum total throughput with all the slices combined. This is different from how DP spec specifies it. - * Our decoder's total throughput in Pix/s is equal to DISPCLK. This is then shared between slices. - * The value below is the absolute maximum value. The actual throughput may be lower, but it'll always - * be sufficient to process the input pixel rate fed into a single DSC engine. - */ - dsc_enc_caps->max_total_throughput_mps = DCN20_MAX_DISPLAY_CLOCK_Mhz; - - /* For pixel clock bigger than a single-pipe limit we'll need two engines, which then doubles our - * throughput and number of slices, but also introduces a lower limit of 2 slices - */ - if (pixel_clock_100Hz >= DCN20_MAX_PIXEL_CLOCK_Mhz*10000) { - dsc_enc_caps->slice_caps.bits.NUM_SLICES_1 = 0; - dsc_enc_caps->slice_caps.bits.NUM_SLICES_8 = 1; - dsc_enc_caps->max_total_throughput_mps = DCN20_MAX_DISPLAY_CLOCK_Mhz * 2; - } - - /* For pixel clock bigger than a single-pipe limit needing four engines ODM 4:1, which then quardruples our - * throughput and number of slices - */ - if (pixel_clock_100Hz > DCN20_MAX_PIXEL_CLOCK_Mhz*10000*2) { - dsc_enc_caps->slice_caps.bits.NUM_SLICES_12 = 1; - dsc_enc_caps->slice_caps.bits.NUM_SLICES_16 = 1; - dsc_enc_caps->max_total_throughput_mps = DCN20_MAX_DISPLAY_CLOCK_Mhz * 4; - } - - dsc_enc_caps->max_slice_width = 5184; /* (including 64 overlap pixels for eDP MSO mode) */ - dsc_enc_caps->bpp_increment_div = 16; /* 1/16th of a bit */ -} - - -/* this function read dsc related register fields to be logged later in dcn10_log_hw_state - * into a dcn_dsc_state struct. - */ -static void dsc2_read_state(struct display_stream_compressor *dsc, struct dcn_dsc_state *s) -{ - struct dcn20_dsc *dsc20 = TO_DCN20_DSC(dsc); - - REG_GET(DSC_TOP_CONTROL, DSC_CLOCK_EN, &s->dsc_clock_en); - REG_GET(DSCC_PPS_CONFIG3, SLICE_WIDTH, &s->dsc_slice_width); - REG_GET(DSCC_PPS_CONFIG1, BITS_PER_PIXEL, &s->dsc_bits_per_pixel); - REG_GET(DSCC_PPS_CONFIG3, SLICE_HEIGHT, &s->dsc_slice_height); - REG_GET(DSCC_PPS_CONFIG1, CHUNK_SIZE, &s->dsc_chunk_size); - REG_GET(DSCC_PPS_CONFIG2, PIC_WIDTH, &s->dsc_pic_width); - REG_GET(DSCC_PPS_CONFIG2, PIC_HEIGHT, &s->dsc_pic_height); - REG_GET(DSCC_PPS_CONFIG7, SLICE_BPG_OFFSET, &s->dsc_slice_bpg_offset); - REG_GET_2(DSCRM_DSC_FORWARD_CONFIG, DSCRM_DSC_FORWARD_EN, &s->dsc_fw_en, - DSCRM_DSC_OPP_PIPE_SOURCE, &s->dsc_opp_source); -} - - -static bool dsc2_validate_stream(struct display_stream_compressor *dsc, const struct dsc_config *dsc_cfg) -{ - struct dsc_optc_config dsc_optc_cfg; - struct dcn20_dsc *dsc20 = TO_DCN20_DSC(dsc); - - if (dsc_cfg->pic_width > dsc20->max_image_width) - return false; - - return dsc_prepare_config(dsc_cfg, &dsc20->reg_vals, &dsc_optc_cfg); -} - - -void dsc_config_log(struct display_stream_compressor *dsc, const struct dsc_config *config) -{ - DC_LOG_DSC("\tnum_slices_h %d", config->dc_dsc_cfg.num_slices_h); - DC_LOG_DSC("\tnum_slices_v %d", config->dc_dsc_cfg.num_slices_v); - DC_LOG_DSC("\tbits_per_pixel %d (%d.%04d)", - config->dc_dsc_cfg.bits_per_pixel, - config->dc_dsc_cfg.bits_per_pixel / 16, - ((config->dc_dsc_cfg.bits_per_pixel % 16) * 10000) / 16); - DC_LOG_DSC("\tcolor_depth %d", config->color_depth); -} - -static void dsc2_set_config(struct display_stream_compressor *dsc, const struct dsc_config *dsc_cfg, - struct dsc_optc_config *dsc_optc_cfg) -{ - bool is_config_ok; - struct dcn20_dsc *dsc20 = TO_DCN20_DSC(dsc); - - DC_LOG_DSC("Setting DSC Config at DSC inst %d", dsc->inst); - dsc_config_log(dsc, dsc_cfg); - is_config_ok = dsc_prepare_config(dsc_cfg, &dsc20->reg_vals, dsc_optc_cfg); - ASSERT(is_config_ok); - DC_LOG_DSC("programming DSC Picture Parameter Set (PPS):"); - dsc_log_pps(dsc, &dsc20->reg_vals.pps); - dsc_write_to_registers(dsc, &dsc20->reg_vals); -} - - -bool dsc2_get_packed_pps(struct display_stream_compressor *dsc, const struct dsc_config *dsc_cfg, uint8_t *dsc_packed_pps) -{ - bool is_config_ok; - struct dsc_reg_values dsc_reg_vals; - struct dsc_optc_config dsc_optc_cfg; - - memset(&dsc_reg_vals, 0, sizeof(dsc_reg_vals)); - memset(&dsc_optc_cfg, 0, sizeof(dsc_optc_cfg)); - - DC_LOG_DSC("Getting packed DSC PPS for DSC Config:"); - dsc_config_log(dsc, dsc_cfg); - DC_LOG_DSC("DSC Picture Parameter Set (PPS):"); - is_config_ok = dsc_prepare_config(dsc_cfg, &dsc_reg_vals, &dsc_optc_cfg); - ASSERT(is_config_ok); - drm_dsc_pps_payload_pack((struct drm_dsc_picture_parameter_set *)dsc_packed_pps, &dsc_reg_vals.pps); - dsc_log_pps(dsc, &dsc_reg_vals.pps); - - return is_config_ok; -} - - -static void dsc2_enable(struct display_stream_compressor *dsc, int opp_pipe) -{ - struct dcn20_dsc *dsc20 = TO_DCN20_DSC(dsc); - int dsc_clock_en; - int dsc_fw_config; - int enabled_opp_pipe; - - DC_LOG_DSC("enable DSC %d at opp pipe %d", dsc->inst, opp_pipe); - - REG_GET(DSC_TOP_CONTROL, DSC_CLOCK_EN, &dsc_clock_en); - REG_GET_2(DSCRM_DSC_FORWARD_CONFIG, DSCRM_DSC_FORWARD_EN, &dsc_fw_config, DSCRM_DSC_OPP_PIPE_SOURCE, &enabled_opp_pipe); - if ((dsc_clock_en || dsc_fw_config) && enabled_opp_pipe != opp_pipe) { - DC_LOG_DSC("ERROR: DSC %d at opp pipe %d already enabled!", dsc->inst, enabled_opp_pipe); - ASSERT(0); - } - - REG_UPDATE(DSC_TOP_CONTROL, - DSC_CLOCK_EN, 1); - - REG_UPDATE_2(DSCRM_DSC_FORWARD_CONFIG, - DSCRM_DSC_FORWARD_EN, 1, - DSCRM_DSC_OPP_PIPE_SOURCE, opp_pipe); -} - - -static void dsc2_disable(struct display_stream_compressor *dsc) -{ - struct dcn20_dsc *dsc20 = TO_DCN20_DSC(dsc); - int dsc_clock_en; - int dsc_fw_config; - int enabled_opp_pipe; - - DC_LOG_DSC("disable DSC %d", dsc->inst); - - REG_GET(DSC_TOP_CONTROL, DSC_CLOCK_EN, &dsc_clock_en); - REG_GET_2(DSCRM_DSC_FORWARD_CONFIG, DSCRM_DSC_FORWARD_EN, &dsc_fw_config, DSCRM_DSC_OPP_PIPE_SOURCE, &enabled_opp_pipe); - if (!dsc_clock_en || !dsc_fw_config) { - DC_LOG_DSC("ERROR: DSC %d at opp pipe %d already disabled!", dsc->inst, enabled_opp_pipe); - ASSERT(0); - } - - REG_UPDATE(DSCRM_DSC_FORWARD_CONFIG, - DSCRM_DSC_FORWARD_EN, 0); - - REG_UPDATE(DSC_TOP_CONTROL, - DSC_CLOCK_EN, 0); -} - -static void dsc2_disconnect(struct display_stream_compressor *dsc) -{ - struct dcn20_dsc *dsc20 = TO_DCN20_DSC(dsc); - - DC_LOG_DSC("disconnect DSC %d", dsc->inst); - - REG_UPDATE(DSCRM_DSC_FORWARD_CONFIG, - DSCRM_DSC_FORWARD_EN, 0); -} - -/* This module's internal functions */ -void dsc_log_pps(struct display_stream_compressor *dsc, struct drm_dsc_config *pps) -{ - int i; - int bits_per_pixel = pps->bits_per_pixel; - - DC_LOG_DSC("\tdsc_version_major %d", pps->dsc_version_major); - DC_LOG_DSC("\tdsc_version_minor %d", pps->dsc_version_minor); - DC_LOG_DSC("\tbits_per_component %d", pps->bits_per_component); - DC_LOG_DSC("\tline_buf_depth %d", pps->line_buf_depth); - DC_LOG_DSC("\tblock_pred_enable %d", pps->block_pred_enable); - DC_LOG_DSC("\tconvert_rgb %d", pps->convert_rgb); - DC_LOG_DSC("\tsimple_422 %d", pps->simple_422); - DC_LOG_DSC("\tvbr_enable %d", pps->vbr_enable); - DC_LOG_DSC("\tbits_per_pixel %d (%d.%04d)", bits_per_pixel, bits_per_pixel / 16, ((bits_per_pixel % 16) * 10000) / 16); - DC_LOG_DSC("\tpic_height %d", pps->pic_height); - DC_LOG_DSC("\tpic_width %d", pps->pic_width); - DC_LOG_DSC("\tslice_height %d", pps->slice_height); - DC_LOG_DSC("\tslice_width %d", pps->slice_width); - DC_LOG_DSC("\tslice_chunk_size %d", pps->slice_chunk_size); - DC_LOG_DSC("\tinitial_xmit_delay %d", pps->initial_xmit_delay); - DC_LOG_DSC("\tinitial_dec_delay %d", pps->initial_dec_delay); - DC_LOG_DSC("\tinitial_scale_value %d", pps->initial_scale_value); - DC_LOG_DSC("\tscale_increment_interval %d", pps->scale_increment_interval); - DC_LOG_DSC("\tscale_decrement_interval %d", pps->scale_decrement_interval); - DC_LOG_DSC("\tfirst_line_bpg_offset %d", pps->first_line_bpg_offset); - DC_LOG_DSC("\tnfl_bpg_offset %d", pps->nfl_bpg_offset); - DC_LOG_DSC("\tslice_bpg_offset %d", pps->slice_bpg_offset); - DC_LOG_DSC("\tinitial_offset %d", pps->initial_offset); - DC_LOG_DSC("\tfinal_offset %d", pps->final_offset); - DC_LOG_DSC("\tflatness_min_qp %d", pps->flatness_min_qp); - DC_LOG_DSC("\tflatness_max_qp %d", pps->flatness_max_qp); - /* DC_LOG_DSC("\trc_parameter_set %d", pps->rc_parameter_set); */ - DC_LOG_DSC("\tnative_420 %d", pps->native_420); - DC_LOG_DSC("\tnative_422 %d", pps->native_422); - DC_LOG_DSC("\tsecond_line_bpg_offset %d", pps->second_line_bpg_offset); - DC_LOG_DSC("\tnsl_bpg_offset %d", pps->nsl_bpg_offset); - DC_LOG_DSC("\tsecond_line_offset_adj %d", pps->second_line_offset_adj); - DC_LOG_DSC("\trc_model_size %d", pps->rc_model_size); - DC_LOG_DSC("\trc_edge_factor %d", pps->rc_edge_factor); - DC_LOG_DSC("\trc_quant_incr_limit0 %d", pps->rc_quant_incr_limit0); - DC_LOG_DSC("\trc_quant_incr_limit1 %d", pps->rc_quant_incr_limit1); - DC_LOG_DSC("\trc_tgt_offset_high %d", pps->rc_tgt_offset_high); - DC_LOG_DSC("\trc_tgt_offset_low %d", pps->rc_tgt_offset_low); - - for (i = 0; i < NUM_BUF_RANGES - 1; i++) - DC_LOG_DSC("\trc_buf_thresh[%d] %d", i, pps->rc_buf_thresh[i]); - - for (i = 0; i < NUM_BUF_RANGES; i++) { - DC_LOG_DSC("\trc_range_parameters[%d].range_min_qp %d", i, pps->rc_range_params[i].range_min_qp); - DC_LOG_DSC("\trc_range_parameters[%d].range_max_qp %d", i, pps->rc_range_params[i].range_max_qp); - DC_LOG_DSC("\trc_range_parameters[%d].range_bpg_offset %d", i, pps->rc_range_params[i].range_bpg_offset); - } -} - -void dsc_override_rc_params(struct rc_params *rc, const struct dc_dsc_rc_params_override *override) -{ - uint8_t i; - - rc->rc_model_size = override->rc_model_size; - for (i = 0; i < DC_DSC_RC_BUF_THRESH_SIZE; i++) - rc->rc_buf_thresh[i] = override->rc_buf_thresh[i]; - for (i = 0; i < DC_DSC_QP_SET_SIZE; i++) { - rc->qp_min[i] = override->rc_minqp[i]; - rc->qp_max[i] = override->rc_maxqp[i]; - rc->ofs[i] = override->rc_offset[i]; - } - - rc->rc_tgt_offset_hi = override->rc_tgt_offset_hi; - rc->rc_tgt_offset_lo = override->rc_tgt_offset_lo; - rc->rc_edge_factor = override->rc_edge_factor; - rc->rc_quant_incr_limit0 = override->rc_quant_incr_limit0; - rc->rc_quant_incr_limit1 = override->rc_quant_incr_limit1; - - rc->initial_fullness_offset = override->initial_fullness_offset; - rc->initial_xmit_delay = override->initial_delay; - - rc->flatness_min_qp = override->flatness_min_qp; - rc->flatness_max_qp = override->flatness_max_qp; - rc->flatness_det_thresh = override->flatness_det_thresh; -} - -bool dsc_prepare_config(const struct dsc_config *dsc_cfg, struct dsc_reg_values *dsc_reg_vals, - struct dsc_optc_config *dsc_optc_cfg) -{ - struct dsc_parameters dsc_params; - struct rc_params rc; - - /* Validate input parameters */ - ASSERT(dsc_cfg->dc_dsc_cfg.num_slices_h); - ASSERT(dsc_cfg->dc_dsc_cfg.num_slices_v); - ASSERT(dsc_cfg->dc_dsc_cfg.version_minor == 1 || dsc_cfg->dc_dsc_cfg.version_minor == 2); - ASSERT(dsc_cfg->pic_width); - ASSERT(dsc_cfg->pic_height); - ASSERT((dsc_cfg->dc_dsc_cfg.version_minor == 1 && - (8 <= dsc_cfg->dc_dsc_cfg.linebuf_depth && dsc_cfg->dc_dsc_cfg.linebuf_depth <= 13)) || - (dsc_cfg->dc_dsc_cfg.version_minor == 2 && - ((8 <= dsc_cfg->dc_dsc_cfg.linebuf_depth && dsc_cfg->dc_dsc_cfg.linebuf_depth <= 15) || - dsc_cfg->dc_dsc_cfg.linebuf_depth == 0))); - ASSERT(96 <= dsc_cfg->dc_dsc_cfg.bits_per_pixel && dsc_cfg->dc_dsc_cfg.bits_per_pixel <= 0x3ff); // 6.0 <= bits_per_pixel <= 63.9375 - - if (!dsc_cfg->dc_dsc_cfg.num_slices_v || !dsc_cfg->dc_dsc_cfg.num_slices_h || - !(dsc_cfg->dc_dsc_cfg.version_minor == 1 || dsc_cfg->dc_dsc_cfg.version_minor == 2) || - !dsc_cfg->pic_width || !dsc_cfg->pic_height || - !((dsc_cfg->dc_dsc_cfg.version_minor == 1 && // v1.1 line buffer depth range: - 8 <= dsc_cfg->dc_dsc_cfg.linebuf_depth && dsc_cfg->dc_dsc_cfg.linebuf_depth <= 13) || - (dsc_cfg->dc_dsc_cfg.version_minor == 2 && // v1.2 line buffer depth range: - ((8 <= dsc_cfg->dc_dsc_cfg.linebuf_depth && dsc_cfg->dc_dsc_cfg.linebuf_depth <= 15) || - dsc_cfg->dc_dsc_cfg.linebuf_depth == 0))) || - !(96 <= dsc_cfg->dc_dsc_cfg.bits_per_pixel && dsc_cfg->dc_dsc_cfg.bits_per_pixel <= 0x3ff)) { - dm_output_to_console("%s: Invalid parameters\n", __func__); - return false; - } - - dsc_init_reg_values(dsc_reg_vals); - - /* Copy input config */ - dsc_reg_vals->pixel_format = dsc_dc_pixel_encoding_to_dsc_pixel_format(dsc_cfg->pixel_encoding, dsc_cfg->dc_dsc_cfg.ycbcr422_simple); - dsc_reg_vals->num_slices_h = dsc_cfg->dc_dsc_cfg.num_slices_h; - dsc_reg_vals->num_slices_v = dsc_cfg->dc_dsc_cfg.num_slices_v; - dsc_reg_vals->pps.dsc_version_minor = dsc_cfg->dc_dsc_cfg.version_minor; - dsc_reg_vals->pps.pic_width = dsc_cfg->pic_width; - dsc_reg_vals->pps.pic_height = dsc_cfg->pic_height; - dsc_reg_vals->pps.bits_per_component = dsc_dc_color_depth_to_dsc_bits_per_comp(dsc_cfg->color_depth); - dsc_reg_vals->pps.block_pred_enable = dsc_cfg->dc_dsc_cfg.block_pred_enable; - dsc_reg_vals->pps.line_buf_depth = dsc_cfg->dc_dsc_cfg.linebuf_depth; - dsc_reg_vals->alternate_ich_encoding_en = dsc_reg_vals->pps.dsc_version_minor == 1 ? 0 : 1; - dsc_reg_vals->ich_reset_at_eol = (dsc_cfg->is_odm || dsc_reg_vals->num_slices_h > 1) ? 0xF : 0; - - // TODO: in addition to validating slice height (pic height must be divisible by slice height), - // see what happens when the same condition doesn't apply for slice_width/pic_width. - dsc_reg_vals->pps.slice_width = dsc_cfg->pic_width / dsc_cfg->dc_dsc_cfg.num_slices_h; - dsc_reg_vals->pps.slice_height = dsc_cfg->pic_height / dsc_cfg->dc_dsc_cfg.num_slices_v; - - ASSERT(dsc_reg_vals->pps.slice_height * dsc_cfg->dc_dsc_cfg.num_slices_v == dsc_cfg->pic_height); - if (!(dsc_reg_vals->pps.slice_height * dsc_cfg->dc_dsc_cfg.num_slices_v == dsc_cfg->pic_height)) { - dm_output_to_console("%s: pix height %d not divisible by num_slices_v %d\n\n", __func__, dsc_cfg->pic_height, dsc_cfg->dc_dsc_cfg.num_slices_v); - return false; - } - - dsc_reg_vals->bpp_x32 = dsc_cfg->dc_dsc_cfg.bits_per_pixel << 1; - if (dsc_reg_vals->pixel_format == DSC_PIXFMT_NATIVE_YCBCR420 || dsc_reg_vals->pixel_format == DSC_PIXFMT_NATIVE_YCBCR422) - dsc_reg_vals->pps.bits_per_pixel = dsc_reg_vals->bpp_x32; - else - dsc_reg_vals->pps.bits_per_pixel = dsc_reg_vals->bpp_x32 >> 1; - - dsc_reg_vals->pps.convert_rgb = dsc_reg_vals->pixel_format == DSC_PIXFMT_RGB ? 1 : 0; - dsc_reg_vals->pps.native_422 = (dsc_reg_vals->pixel_format == DSC_PIXFMT_NATIVE_YCBCR422); - dsc_reg_vals->pps.native_420 = (dsc_reg_vals->pixel_format == DSC_PIXFMT_NATIVE_YCBCR420); - dsc_reg_vals->pps.simple_422 = (dsc_reg_vals->pixel_format == DSC_PIXFMT_SIMPLE_YCBCR422); - - calc_rc_params(&rc, &dsc_reg_vals->pps); - - if (dsc_cfg->dc_dsc_cfg.rc_params_ovrd) - dsc_override_rc_params(&rc, dsc_cfg->dc_dsc_cfg.rc_params_ovrd); - - if (dscc_compute_dsc_parameters(&dsc_reg_vals->pps, &rc, &dsc_params)) { - dm_output_to_console("%s: DSC config failed\n", __func__); - return false; - } - - dsc_update_from_dsc_parameters(dsc_reg_vals, &dsc_params); - - dsc_optc_cfg->bytes_per_pixel = dsc_params.bytes_per_pixel; - dsc_optc_cfg->slice_width = dsc_reg_vals->pps.slice_width; - dsc_optc_cfg->is_pixel_format_444 = dsc_reg_vals->pixel_format == DSC_PIXFMT_RGB || - dsc_reg_vals->pixel_format == DSC_PIXFMT_YCBCR444 || - dsc_reg_vals->pixel_format == DSC_PIXFMT_SIMPLE_YCBCR422; - - return true; -} - - -enum dsc_pixel_format dsc_dc_pixel_encoding_to_dsc_pixel_format(enum dc_pixel_encoding dc_pix_enc, bool is_ycbcr422_simple) -{ - enum dsc_pixel_format dsc_pix_fmt = DSC_PIXFMT_UNKNOWN; - - /* NOTE: We don't support DSC_PIXFMT_SIMPLE_YCBCR422 */ - - switch (dc_pix_enc) { - case PIXEL_ENCODING_RGB: - dsc_pix_fmt = DSC_PIXFMT_RGB; - break; - case PIXEL_ENCODING_YCBCR422: - if (is_ycbcr422_simple) - dsc_pix_fmt = DSC_PIXFMT_SIMPLE_YCBCR422; - else - dsc_pix_fmt = DSC_PIXFMT_NATIVE_YCBCR422; - break; - case PIXEL_ENCODING_YCBCR444: - dsc_pix_fmt = DSC_PIXFMT_YCBCR444; - break; - case PIXEL_ENCODING_YCBCR420: - dsc_pix_fmt = DSC_PIXFMT_NATIVE_YCBCR420; - break; - default: - dsc_pix_fmt = DSC_PIXFMT_UNKNOWN; - break; - } - - ASSERT(dsc_pix_fmt != DSC_PIXFMT_UNKNOWN); - return dsc_pix_fmt; -} - - -enum dsc_bits_per_comp dsc_dc_color_depth_to_dsc_bits_per_comp(enum dc_color_depth dc_color_depth) -{ - enum dsc_bits_per_comp bpc = DSC_BPC_UNKNOWN; - - switch (dc_color_depth) { - case COLOR_DEPTH_888: - bpc = DSC_BPC_8; - break; - case COLOR_DEPTH_101010: - bpc = DSC_BPC_10; - break; - case COLOR_DEPTH_121212: - bpc = DSC_BPC_12; - break; - default: - bpc = DSC_BPC_UNKNOWN; - break; - } - - return bpc; -} - - -void dsc_init_reg_values(struct dsc_reg_values *reg_vals) -{ - int i; - - memset(reg_vals, 0, sizeof(struct dsc_reg_values)); - - /* Non-PPS values */ - reg_vals->dsc_clock_enable = 1; - reg_vals->dsc_clock_gating_disable = 0; - reg_vals->underflow_recovery_en = 0; - reg_vals->underflow_occurred_int_en = 0; - reg_vals->underflow_occurred_status = 0; - reg_vals->ich_reset_at_eol = 0; - reg_vals->alternate_ich_encoding_en = 0; - reg_vals->rc_buffer_model_size = 0; - /*reg_vals->disable_ich = 0;*/ - reg_vals->dsc_dbg_en = 0; - - for (i = 0; i < 4; i++) - reg_vals->rc_buffer_model_overflow_int_en[i] = 0; - - /* PPS values */ - reg_vals->pps.dsc_version_minor = 2; - reg_vals->pps.dsc_version_major = 1; - reg_vals->pps.line_buf_depth = 9; - reg_vals->pps.bits_per_component = 8; - reg_vals->pps.block_pred_enable = 1; - reg_vals->pps.slice_chunk_size = 0; - reg_vals->pps.pic_width = 0; - reg_vals->pps.pic_height = 0; - reg_vals->pps.slice_width = 0; - reg_vals->pps.slice_height = 0; - reg_vals->pps.initial_xmit_delay = 170; - reg_vals->pps.initial_dec_delay = 0; - reg_vals->pps.initial_scale_value = 0; - reg_vals->pps.scale_increment_interval = 0; - reg_vals->pps.scale_decrement_interval = 0; - reg_vals->pps.nfl_bpg_offset = 0; - reg_vals->pps.slice_bpg_offset = 0; - reg_vals->pps.nsl_bpg_offset = 0; - reg_vals->pps.initial_offset = 6144; - reg_vals->pps.final_offset = 0; - reg_vals->pps.flatness_min_qp = 3; - reg_vals->pps.flatness_max_qp = 12; - reg_vals->pps.rc_model_size = 8192; - reg_vals->pps.rc_edge_factor = 6; - reg_vals->pps.rc_quant_incr_limit0 = 11; - reg_vals->pps.rc_quant_incr_limit1 = 11; - reg_vals->pps.rc_tgt_offset_low = 3; - reg_vals->pps.rc_tgt_offset_high = 3; -} - -/* Updates dsc_reg_values::reg_vals::xxx fields based on the values from computed params. - * This is required because dscc_compute_dsc_parameters returns a modified PPS, which in turn - * affects non-PPS register values. - */ -void dsc_update_from_dsc_parameters(struct dsc_reg_values *reg_vals, const struct dsc_parameters *dsc_params) -{ - int i; - - reg_vals->pps = dsc_params->pps; - - // pps_computed will have the "expanded" values; need to shift them to make them fit for regs. - for (i = 0; i < NUM_BUF_RANGES - 1; i++) - reg_vals->pps.rc_buf_thresh[i] = reg_vals->pps.rc_buf_thresh[i] >> 6; - - reg_vals->rc_buffer_model_size = dsc_params->rc_buffer_model_size; -} - -static void dsc_write_to_registers(struct display_stream_compressor *dsc, const struct dsc_reg_values *reg_vals) -{ - uint32_t temp_int; - struct dcn20_dsc *dsc20 = TO_DCN20_DSC(dsc); - - REG_SET(DSC_DEBUG_CONTROL, 0, - DSC_DBG_EN, reg_vals->dsc_dbg_en); - - // dsccif registers - REG_SET_5(DSCCIF_CONFIG0, 0, - INPUT_INTERFACE_UNDERFLOW_RECOVERY_EN, reg_vals->underflow_recovery_en, - INPUT_INTERFACE_UNDERFLOW_OCCURRED_INT_EN, reg_vals->underflow_occurred_int_en, - INPUT_INTERFACE_UNDERFLOW_OCCURRED_STATUS, reg_vals->underflow_occurred_status, - INPUT_PIXEL_FORMAT, reg_vals->pixel_format, - DSCCIF_CONFIG0__BITS_PER_COMPONENT, reg_vals->pps.bits_per_component); - - REG_SET_2(DSCCIF_CONFIG1, 0, - PIC_WIDTH, reg_vals->pps.pic_width, - PIC_HEIGHT, reg_vals->pps.pic_height); - - // dscc registers - if (dsc20->dsc_mask->ICH_RESET_AT_END_OF_LINE == 0) { - REG_SET_3(DSCC_CONFIG0, 0, - NUMBER_OF_SLICES_PER_LINE, reg_vals->num_slices_h - 1, - ALTERNATE_ICH_ENCODING_EN, reg_vals->alternate_ich_encoding_en, - NUMBER_OF_SLICES_IN_VERTICAL_DIRECTION, reg_vals->num_slices_v - 1); - } else { - REG_SET_4(DSCC_CONFIG0, 0, ICH_RESET_AT_END_OF_LINE, - reg_vals->ich_reset_at_eol, NUMBER_OF_SLICES_PER_LINE, - reg_vals->num_slices_h - 1, ALTERNATE_ICH_ENCODING_EN, - reg_vals->alternate_ich_encoding_en, NUMBER_OF_SLICES_IN_VERTICAL_DIRECTION, - reg_vals->num_slices_v - 1); - } - - REG_SET(DSCC_CONFIG1, 0, - DSCC_RATE_CONTROL_BUFFER_MODEL_SIZE, reg_vals->rc_buffer_model_size); - /*REG_SET_2(DSCC_CONFIG1, 0, - DSCC_RATE_CONTROL_BUFFER_MODEL_SIZE, reg_vals->rc_buffer_model_size, - DSCC_DISABLE_ICH, reg_vals->disable_ich);*/ - - REG_SET_4(DSCC_INTERRUPT_CONTROL_STATUS, 0, - DSCC_RATE_CONTROL_BUFFER_MODEL0_OVERFLOW_OCCURRED_INT_EN, reg_vals->rc_buffer_model_overflow_int_en[0], - DSCC_RATE_CONTROL_BUFFER_MODEL1_OVERFLOW_OCCURRED_INT_EN, reg_vals->rc_buffer_model_overflow_int_en[1], - DSCC_RATE_CONTROL_BUFFER_MODEL2_OVERFLOW_OCCURRED_INT_EN, reg_vals->rc_buffer_model_overflow_int_en[2], - DSCC_RATE_CONTROL_BUFFER_MODEL3_OVERFLOW_OCCURRED_INT_EN, reg_vals->rc_buffer_model_overflow_int_en[3]); - - REG_SET_3(DSCC_PPS_CONFIG0, 0, - DSC_VERSION_MINOR, reg_vals->pps.dsc_version_minor, - LINEBUF_DEPTH, reg_vals->pps.line_buf_depth, - DSCC_PPS_CONFIG0__BITS_PER_COMPONENT, reg_vals->pps.bits_per_component); - - if (reg_vals->pixel_format == DSC_PIXFMT_NATIVE_YCBCR420 || reg_vals->pixel_format == DSC_PIXFMT_NATIVE_YCBCR422) - temp_int = reg_vals->bpp_x32; - else - temp_int = reg_vals->bpp_x32 >> 1; - - REG_SET_7(DSCC_PPS_CONFIG1, 0, - BITS_PER_PIXEL, temp_int, - SIMPLE_422, reg_vals->pixel_format == DSC_PIXFMT_SIMPLE_YCBCR422, - CONVERT_RGB, reg_vals->pixel_format == DSC_PIXFMT_RGB, - BLOCK_PRED_ENABLE, reg_vals->pps.block_pred_enable, - NATIVE_422, reg_vals->pixel_format == DSC_PIXFMT_NATIVE_YCBCR422, - NATIVE_420, reg_vals->pixel_format == DSC_PIXFMT_NATIVE_YCBCR420, - CHUNK_SIZE, reg_vals->pps.slice_chunk_size); - - REG_SET_2(DSCC_PPS_CONFIG2, 0, - PIC_WIDTH, reg_vals->pps.pic_width, - PIC_HEIGHT, reg_vals->pps.pic_height); - - REG_SET_2(DSCC_PPS_CONFIG3, 0, - SLICE_WIDTH, reg_vals->pps.slice_width, - SLICE_HEIGHT, reg_vals->pps.slice_height); - - REG_SET(DSCC_PPS_CONFIG4, 0, - INITIAL_XMIT_DELAY, reg_vals->pps.initial_xmit_delay); - - REG_SET_2(DSCC_PPS_CONFIG5, 0, - INITIAL_SCALE_VALUE, reg_vals->pps.initial_scale_value, - SCALE_INCREMENT_INTERVAL, reg_vals->pps.scale_increment_interval); - - REG_SET_3(DSCC_PPS_CONFIG6, 0, - SCALE_DECREMENT_INTERVAL, reg_vals->pps.scale_decrement_interval, - FIRST_LINE_BPG_OFFSET, reg_vals->pps.first_line_bpg_offset, - SECOND_LINE_BPG_OFFSET, reg_vals->pps.second_line_bpg_offset); - - REG_SET_2(DSCC_PPS_CONFIG7, 0, - NFL_BPG_OFFSET, reg_vals->pps.nfl_bpg_offset, - SLICE_BPG_OFFSET, reg_vals->pps.slice_bpg_offset); - - REG_SET_2(DSCC_PPS_CONFIG8, 0, - NSL_BPG_OFFSET, reg_vals->pps.nsl_bpg_offset, - SECOND_LINE_OFFSET_ADJ, reg_vals->pps.second_line_offset_adj); - - REG_SET_2(DSCC_PPS_CONFIG9, 0, - INITIAL_OFFSET, reg_vals->pps.initial_offset, - FINAL_OFFSET, reg_vals->pps.final_offset); - - REG_SET_3(DSCC_PPS_CONFIG10, 0, - FLATNESS_MIN_QP, reg_vals->pps.flatness_min_qp, - FLATNESS_MAX_QP, reg_vals->pps.flatness_max_qp, - RC_MODEL_SIZE, reg_vals->pps.rc_model_size); - - REG_SET_5(DSCC_PPS_CONFIG11, 0, - RC_EDGE_FACTOR, reg_vals->pps.rc_edge_factor, - RC_QUANT_INCR_LIMIT0, reg_vals->pps.rc_quant_incr_limit0, - RC_QUANT_INCR_LIMIT1, reg_vals->pps.rc_quant_incr_limit1, - RC_TGT_OFFSET_LO, reg_vals->pps.rc_tgt_offset_low, - RC_TGT_OFFSET_HI, reg_vals->pps.rc_tgt_offset_high); - - REG_SET_4(DSCC_PPS_CONFIG12, 0, - RC_BUF_THRESH0, reg_vals->pps.rc_buf_thresh[0], - RC_BUF_THRESH1, reg_vals->pps.rc_buf_thresh[1], - RC_BUF_THRESH2, reg_vals->pps.rc_buf_thresh[2], - RC_BUF_THRESH3, reg_vals->pps.rc_buf_thresh[3]); - - REG_SET_4(DSCC_PPS_CONFIG13, 0, - RC_BUF_THRESH4, reg_vals->pps.rc_buf_thresh[4], - RC_BUF_THRESH5, reg_vals->pps.rc_buf_thresh[5], - RC_BUF_THRESH6, reg_vals->pps.rc_buf_thresh[6], - RC_BUF_THRESH7, reg_vals->pps.rc_buf_thresh[7]); - - REG_SET_4(DSCC_PPS_CONFIG14, 0, - RC_BUF_THRESH8, reg_vals->pps.rc_buf_thresh[8], - RC_BUF_THRESH9, reg_vals->pps.rc_buf_thresh[9], - RC_BUF_THRESH10, reg_vals->pps.rc_buf_thresh[10], - RC_BUF_THRESH11, reg_vals->pps.rc_buf_thresh[11]); - - REG_SET_5(DSCC_PPS_CONFIG15, 0, - RC_BUF_THRESH12, reg_vals->pps.rc_buf_thresh[12], - RC_BUF_THRESH13, reg_vals->pps.rc_buf_thresh[13], - RANGE_MIN_QP0, reg_vals->pps.rc_range_params[0].range_min_qp, - RANGE_MAX_QP0, reg_vals->pps.rc_range_params[0].range_max_qp, - RANGE_BPG_OFFSET0, reg_vals->pps.rc_range_params[0].range_bpg_offset); - - REG_SET_6(DSCC_PPS_CONFIG16, 0, - RANGE_MIN_QP1, reg_vals->pps.rc_range_params[1].range_min_qp, - RANGE_MAX_QP1, reg_vals->pps.rc_range_params[1].range_max_qp, - RANGE_BPG_OFFSET1, reg_vals->pps.rc_range_params[1].range_bpg_offset, - RANGE_MIN_QP2, reg_vals->pps.rc_range_params[2].range_min_qp, - RANGE_MAX_QP2, reg_vals->pps.rc_range_params[2].range_max_qp, - RANGE_BPG_OFFSET2, reg_vals->pps.rc_range_params[2].range_bpg_offset); - - REG_SET_6(DSCC_PPS_CONFIG17, 0, - RANGE_MIN_QP3, reg_vals->pps.rc_range_params[3].range_min_qp, - RANGE_MAX_QP3, reg_vals->pps.rc_range_params[3].range_max_qp, - RANGE_BPG_OFFSET3, reg_vals->pps.rc_range_params[3].range_bpg_offset, - RANGE_MIN_QP4, reg_vals->pps.rc_range_params[4].range_min_qp, - RANGE_MAX_QP4, reg_vals->pps.rc_range_params[4].range_max_qp, - RANGE_BPG_OFFSET4, reg_vals->pps.rc_range_params[4].range_bpg_offset); - - REG_SET_6(DSCC_PPS_CONFIG18, 0, - RANGE_MIN_QP5, reg_vals->pps.rc_range_params[5].range_min_qp, - RANGE_MAX_QP5, reg_vals->pps.rc_range_params[5].range_max_qp, - RANGE_BPG_OFFSET5, reg_vals->pps.rc_range_params[5].range_bpg_offset, - RANGE_MIN_QP6, reg_vals->pps.rc_range_params[6].range_min_qp, - RANGE_MAX_QP6, reg_vals->pps.rc_range_params[6].range_max_qp, - RANGE_BPG_OFFSET6, reg_vals->pps.rc_range_params[6].range_bpg_offset); - - REG_SET_6(DSCC_PPS_CONFIG19, 0, - RANGE_MIN_QP7, reg_vals->pps.rc_range_params[7].range_min_qp, - RANGE_MAX_QP7, reg_vals->pps.rc_range_params[7].range_max_qp, - RANGE_BPG_OFFSET7, reg_vals->pps.rc_range_params[7].range_bpg_offset, - RANGE_MIN_QP8, reg_vals->pps.rc_range_params[8].range_min_qp, - RANGE_MAX_QP8, reg_vals->pps.rc_range_params[8].range_max_qp, - RANGE_BPG_OFFSET8, reg_vals->pps.rc_range_params[8].range_bpg_offset); - - REG_SET_6(DSCC_PPS_CONFIG20, 0, - RANGE_MIN_QP9, reg_vals->pps.rc_range_params[9].range_min_qp, - RANGE_MAX_QP9, reg_vals->pps.rc_range_params[9].range_max_qp, - RANGE_BPG_OFFSET9, reg_vals->pps.rc_range_params[9].range_bpg_offset, - RANGE_MIN_QP10, reg_vals->pps.rc_range_params[10].range_min_qp, - RANGE_MAX_QP10, reg_vals->pps.rc_range_params[10].range_max_qp, - RANGE_BPG_OFFSET10, reg_vals->pps.rc_range_params[10].range_bpg_offset); - - REG_SET_6(DSCC_PPS_CONFIG21, 0, - RANGE_MIN_QP11, reg_vals->pps.rc_range_params[11].range_min_qp, - RANGE_MAX_QP11, reg_vals->pps.rc_range_params[11].range_max_qp, - RANGE_BPG_OFFSET11, reg_vals->pps.rc_range_params[11].range_bpg_offset, - RANGE_MIN_QP12, reg_vals->pps.rc_range_params[12].range_min_qp, - RANGE_MAX_QP12, reg_vals->pps.rc_range_params[12].range_max_qp, - RANGE_BPG_OFFSET12, reg_vals->pps.rc_range_params[12].range_bpg_offset); - - REG_SET_6(DSCC_PPS_CONFIG22, 0, - RANGE_MIN_QP13, reg_vals->pps.rc_range_params[13].range_min_qp, - RANGE_MAX_QP13, reg_vals->pps.rc_range_params[13].range_max_qp, - RANGE_BPG_OFFSET13, reg_vals->pps.rc_range_params[13].range_bpg_offset, - RANGE_MIN_QP14, reg_vals->pps.rc_range_params[14].range_min_qp, - RANGE_MAX_QP14, reg_vals->pps.rc_range_params[14].range_max_qp, - RANGE_BPG_OFFSET14, reg_vals->pps.rc_range_params[14].range_bpg_offset); - -} - diff --git a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_dsc.h b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_dsc.h deleted file mode 100644 index ba869387c3c5..000000000000 --- a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_dsc.h +++ /dev/null @@ -1,589 +0,0 @@ -/* Copyright 2017 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 __DCN20_DSC_H__ -#define __DCN20_DSC_H__ - -#include "dsc.h" -#include "dsc/dscc_types.h" -#include - -#define TO_DCN20_DSC(dsc)\ - container_of(dsc, struct dcn20_dsc, base) - -#define DSC_REG_LIST_DCN20(id) \ - SRI(DSC_TOP_CONTROL, DSC_TOP, id),\ - SRI(DSC_DEBUG_CONTROL, DSC_TOP, id),\ - SRI(DSCC_CONFIG0, DSCC, id),\ - SRI(DSCC_CONFIG1, DSCC, id),\ - SRI(DSCC_STATUS, DSCC, id),\ - SRI(DSCC_INTERRUPT_CONTROL_STATUS, DSCC, id),\ - SRI(DSCC_PPS_CONFIG0, DSCC, id),\ - SRI(DSCC_PPS_CONFIG1, DSCC, id),\ - SRI(DSCC_PPS_CONFIG2, DSCC, id),\ - SRI(DSCC_PPS_CONFIG3, DSCC, id),\ - SRI(DSCC_PPS_CONFIG4, DSCC, id),\ - SRI(DSCC_PPS_CONFIG5, DSCC, id),\ - SRI(DSCC_PPS_CONFIG6, DSCC, id),\ - SRI(DSCC_PPS_CONFIG7, DSCC, id),\ - SRI(DSCC_PPS_CONFIG8, DSCC, id),\ - SRI(DSCC_PPS_CONFIG9, DSCC, id),\ - SRI(DSCC_PPS_CONFIG10, DSCC, id),\ - SRI(DSCC_PPS_CONFIG11, DSCC, id),\ - SRI(DSCC_PPS_CONFIG12, DSCC, id),\ - SRI(DSCC_PPS_CONFIG13, DSCC, id),\ - SRI(DSCC_PPS_CONFIG14, DSCC, id),\ - SRI(DSCC_PPS_CONFIG15, DSCC, id),\ - SRI(DSCC_PPS_CONFIG16, DSCC, id),\ - SRI(DSCC_PPS_CONFIG17, DSCC, id),\ - SRI(DSCC_PPS_CONFIG18, DSCC, id),\ - SRI(DSCC_PPS_CONFIG19, DSCC, id),\ - SRI(DSCC_PPS_CONFIG20, DSCC, id),\ - SRI(DSCC_PPS_CONFIG21, DSCC, id),\ - SRI(DSCC_PPS_CONFIG22, DSCC, id),\ - SRI(DSCC_MEM_POWER_CONTROL, DSCC, id),\ - SRI(DSCC_R_Y_SQUARED_ERROR_LOWER, DSCC, id),\ - SRI(DSCC_R_Y_SQUARED_ERROR_UPPER, DSCC, id),\ - SRI(DSCC_G_CB_SQUARED_ERROR_LOWER, DSCC, id),\ - SRI(DSCC_G_CB_SQUARED_ERROR_UPPER, DSCC, id),\ - SRI(DSCC_B_CR_SQUARED_ERROR_LOWER, DSCC, id),\ - SRI(DSCC_B_CR_SQUARED_ERROR_UPPER, DSCC, id),\ - SRI(DSCC_MAX_ABS_ERROR0, DSCC, id),\ - SRI(DSCC_MAX_ABS_ERROR1, DSCC, id),\ - SRI(DSCC_RATE_BUFFER0_MAX_FULLNESS_LEVEL, DSCC, id),\ - SRI(DSCC_RATE_BUFFER1_MAX_FULLNESS_LEVEL, DSCC, id),\ - SRI(DSCC_RATE_BUFFER2_MAX_FULLNESS_LEVEL, DSCC, id),\ - SRI(DSCC_RATE_BUFFER3_MAX_FULLNESS_LEVEL, DSCC, id),\ - SRI(DSCC_RATE_CONTROL_BUFFER0_MAX_FULLNESS_LEVEL, DSCC, id),\ - SRI(DSCC_RATE_CONTROL_BUFFER1_MAX_FULLNESS_LEVEL, DSCC, id),\ - SRI(DSCC_RATE_CONTROL_BUFFER2_MAX_FULLNESS_LEVEL, DSCC, id),\ - SRI(DSCC_RATE_CONTROL_BUFFER3_MAX_FULLNESS_LEVEL, DSCC, id),\ - SRI(DSCCIF_CONFIG0, DSCCIF, id),\ - SRI(DSCCIF_CONFIG1, DSCCIF, id),\ - SRI(DSCRM_DSC_FORWARD_CONFIG, DSCRM, id) - - -#define DSC_SF(reg_name, field_name, post_fix)\ - .field_name = reg_name ## __ ## field_name ## post_fix - -//Used in resolving the corner case with duplicate field name -#define DSC2_SF(reg_name, field_name, post_fix)\ - .field_name = reg_name ## _ ## field_name ## post_fix - -#define DSC_REG_LIST_SH_MASK_DCN20(mask_sh)\ - DSC_SF(DSC_TOP0_DSC_TOP_CONTROL, DSC_CLOCK_EN, mask_sh), \ - DSC_SF(DSC_TOP0_DSC_TOP_CONTROL, DSC_DISPCLK_R_GATE_DIS, mask_sh), \ - DSC_SF(DSC_TOP0_DSC_TOP_CONTROL, DSC_DSCCLK_R_GATE_DIS, mask_sh), \ - DSC_SF(DSC_TOP0_DSC_DEBUG_CONTROL, DSC_DBG_EN, mask_sh), \ - DSC_SF(DSCC0_DSCC_CONFIG0, ICH_RESET_AT_END_OF_LINE, mask_sh), \ - DSC_SF(DSCC0_DSCC_CONFIG0, NUMBER_OF_SLICES_PER_LINE, mask_sh), \ - DSC_SF(DSCC0_DSCC_CONFIG0, ALTERNATE_ICH_ENCODING_EN, mask_sh), \ - DSC_SF(DSCC0_DSCC_CONFIG0, NUMBER_OF_SLICES_IN_VERTICAL_DIRECTION, mask_sh), \ - DSC_SF(DSCC0_DSCC_CONFIG1, DSCC_RATE_CONTROL_BUFFER_MODEL_SIZE, mask_sh), \ - /*DSC_SF(DSCC0_DSCC_CONFIG1, DSCC_DISABLE_ICH, mask_sh),*/ \ - DSC_SF(DSCC0_DSCC_STATUS, DSCC_DOUBLE_BUFFER_REG_UPDATE_PENDING, mask_sh), \ - DSC_SF(DSCC0_DSCC_INTERRUPT_CONTROL_STATUS, DSCC_RATE_BUFFER0_OVERFLOW_OCCURRED, mask_sh), \ - DSC_SF(DSCC0_DSCC_INTERRUPT_CONTROL_STATUS, DSCC_RATE_BUFFER1_OVERFLOW_OCCURRED, mask_sh), \ - DSC_SF(DSCC0_DSCC_INTERRUPT_CONTROL_STATUS, DSCC_RATE_BUFFER2_OVERFLOW_OCCURRED, mask_sh), \ - DSC_SF(DSCC0_DSCC_INTERRUPT_CONTROL_STATUS, DSCC_RATE_BUFFER3_OVERFLOW_OCCURRED, mask_sh), \ - DSC_SF(DSCC0_DSCC_INTERRUPT_CONTROL_STATUS, DSCC_RATE_BUFFER0_UNDERFLOW_OCCURRED, mask_sh), \ - DSC_SF(DSCC0_DSCC_INTERRUPT_CONTROL_STATUS, DSCC_RATE_BUFFER1_UNDERFLOW_OCCURRED, mask_sh), \ - DSC_SF(DSCC0_DSCC_INTERRUPT_CONTROL_STATUS, DSCC_RATE_BUFFER2_UNDERFLOW_OCCURRED, mask_sh), \ - DSC_SF(DSCC0_DSCC_INTERRUPT_CONTROL_STATUS, DSCC_RATE_BUFFER3_UNDERFLOW_OCCURRED, mask_sh), \ - DSC_SF(DSCC0_DSCC_INTERRUPT_CONTROL_STATUS, DSCC_RATE_CONTROL_BUFFER_MODEL0_OVERFLOW_OCCURRED, mask_sh), \ - DSC_SF(DSCC0_DSCC_INTERRUPT_CONTROL_STATUS, DSCC_RATE_CONTROL_BUFFER_MODEL1_OVERFLOW_OCCURRED, mask_sh), \ - DSC_SF(DSCC0_DSCC_INTERRUPT_CONTROL_STATUS, DSCC_RATE_CONTROL_BUFFER_MODEL2_OVERFLOW_OCCURRED, mask_sh), \ - DSC_SF(DSCC0_DSCC_INTERRUPT_CONTROL_STATUS, DSCC_RATE_CONTROL_BUFFER_MODEL3_OVERFLOW_OCCURRED, mask_sh), \ - DSC_SF(DSCC0_DSCC_INTERRUPT_CONTROL_STATUS, DSCC_RATE_BUFFER0_OVERFLOW_OCCURRED_INT_EN, mask_sh), \ - DSC_SF(DSCC0_DSCC_INTERRUPT_CONTROL_STATUS, DSCC_RATE_BUFFER1_OVERFLOW_OCCURRED_INT_EN, mask_sh), \ - DSC_SF(DSCC0_DSCC_INTERRUPT_CONTROL_STATUS, DSCC_RATE_BUFFER2_OVERFLOW_OCCURRED_INT_EN, mask_sh), \ - DSC_SF(DSCC0_DSCC_INTERRUPT_CONTROL_STATUS, DSCC_RATE_BUFFER3_OVERFLOW_OCCURRED_INT_EN, mask_sh), \ - DSC_SF(DSCC0_DSCC_INTERRUPT_CONTROL_STATUS, DSCC_RATE_BUFFER0_UNDERFLOW_OCCURRED_INT_EN, mask_sh), \ - DSC_SF(DSCC0_DSCC_INTERRUPT_CONTROL_STATUS, DSCC_RATE_BUFFER1_UNDERFLOW_OCCURRED_INT_EN, mask_sh), \ - DSC_SF(DSCC0_DSCC_INTERRUPT_CONTROL_STATUS, DSCC_RATE_BUFFER2_UNDERFLOW_OCCURRED_INT_EN, mask_sh), \ - DSC_SF(DSCC0_DSCC_INTERRUPT_CONTROL_STATUS, DSCC_RATE_BUFFER3_UNDERFLOW_OCCURRED_INT_EN, mask_sh), \ - DSC_SF(DSCC0_DSCC_INTERRUPT_CONTROL_STATUS, DSCC_RATE_CONTROL_BUFFER_MODEL0_OVERFLOW_OCCURRED_INT_EN, mask_sh), \ - DSC_SF(DSCC0_DSCC_INTERRUPT_CONTROL_STATUS, DSCC_RATE_CONTROL_BUFFER_MODEL1_OVERFLOW_OCCURRED_INT_EN, mask_sh), \ - DSC_SF(DSCC0_DSCC_INTERRUPT_CONTROL_STATUS, DSCC_RATE_CONTROL_BUFFER_MODEL2_OVERFLOW_OCCURRED_INT_EN, mask_sh), \ - DSC_SF(DSCC0_DSCC_INTERRUPT_CONTROL_STATUS, DSCC_RATE_CONTROL_BUFFER_MODEL3_OVERFLOW_OCCURRED_INT_EN, mask_sh), \ - DSC_SF(DSCC0_DSCC_PPS_CONFIG0, DSC_VERSION_MINOR, mask_sh), \ - DSC_SF(DSCC0_DSCC_PPS_CONFIG0, DSC_VERSION_MAJOR, mask_sh), \ - DSC_SF(DSCC0_DSCC_PPS_CONFIG0, PPS_IDENTIFIER, mask_sh), \ - DSC_SF(DSCC0_DSCC_PPS_CONFIG0, LINEBUF_DEPTH, mask_sh), \ - DSC2_SF(DSCC0, DSCC_PPS_CONFIG0__BITS_PER_COMPONENT, mask_sh), \ - DSC_SF(DSCC0_DSCC_PPS_CONFIG1, BITS_PER_PIXEL, mask_sh), \ - DSC_SF(DSCC0_DSCC_PPS_CONFIG1, VBR_ENABLE, mask_sh), \ - DSC_SF(DSCC0_DSCC_PPS_CONFIG1, SIMPLE_422, mask_sh), \ - DSC_SF(DSCC0_DSCC_PPS_CONFIG1, CONVERT_RGB, mask_sh), \ - DSC_SF(DSCC0_DSCC_PPS_CONFIG1, BLOCK_PRED_ENABLE, mask_sh), \ - DSC_SF(DSCC0_DSCC_PPS_CONFIG1, NATIVE_422, mask_sh), \ - DSC_SF(DSCC0_DSCC_PPS_CONFIG1, NATIVE_420, mask_sh), \ - DSC_SF(DSCC0_DSCC_PPS_CONFIG1, CHUNK_SIZE, mask_sh), \ - DSC_SF(DSCC0_DSCC_PPS_CONFIG2, PIC_WIDTH, mask_sh), \ - DSC_SF(DSCC0_DSCC_PPS_CONFIG2, PIC_HEIGHT, mask_sh), \ - DSC_SF(DSCC0_DSCC_PPS_CONFIG3, SLICE_WIDTH, mask_sh), \ - DSC_SF(DSCC0_DSCC_PPS_CONFIG3, SLICE_HEIGHT, mask_sh), \ - DSC_SF(DSCC0_DSCC_PPS_CONFIG4, INITIAL_XMIT_DELAY, mask_sh), \ - DSC_SF(DSCC0_DSCC_PPS_CONFIG4, INITIAL_DEC_DELAY, mask_sh), \ - DSC_SF(DSCC0_DSCC_PPS_CONFIG5, INITIAL_SCALE_VALUE, mask_sh), \ - DSC_SF(DSCC0_DSCC_PPS_CONFIG5, SCALE_INCREMENT_INTERVAL, mask_sh), \ - DSC_SF(DSCC0_DSCC_PPS_CONFIG6, SCALE_DECREMENT_INTERVAL, mask_sh), \ - DSC_SF(DSCC0_DSCC_PPS_CONFIG6, FIRST_LINE_BPG_OFFSET, mask_sh), \ - DSC_SF(DSCC0_DSCC_PPS_CONFIG6, SECOND_LINE_BPG_OFFSET, mask_sh), \ - DSC_SF(DSCC0_DSCC_PPS_CONFIG7, NFL_BPG_OFFSET, mask_sh), \ - DSC_SF(DSCC0_DSCC_PPS_CONFIG7, SLICE_BPG_OFFSET, mask_sh), \ - DSC_SF(DSCC0_DSCC_PPS_CONFIG8, NSL_BPG_OFFSET, mask_sh), \ - DSC_SF(DSCC0_DSCC_PPS_CONFIG8, SECOND_LINE_OFFSET_ADJ, mask_sh), \ - DSC_SF(DSCC0_DSCC_PPS_CONFIG9, INITIAL_OFFSET, mask_sh), \ - DSC_SF(DSCC0_DSCC_PPS_CONFIG9, FINAL_OFFSET, mask_sh), \ - DSC_SF(DSCC0_DSCC_PPS_CONFIG10, FLATNESS_MIN_QP, mask_sh), \ - DSC_SF(DSCC0_DSCC_PPS_CONFIG10, FLATNESS_MAX_QP, mask_sh), \ - DSC_SF(DSCC0_DSCC_PPS_CONFIG10, RC_MODEL_SIZE, mask_sh), \ - DSC_SF(DSCC0_DSCC_PPS_CONFIG11, RC_EDGE_FACTOR, mask_sh), \ - DSC_SF(DSCC0_DSCC_PPS_CONFIG11, RC_QUANT_INCR_LIMIT0, mask_sh), \ - DSC_SF(DSCC0_DSCC_PPS_CONFIG11, RC_QUANT_INCR_LIMIT1, mask_sh), \ - DSC_SF(DSCC0_DSCC_PPS_CONFIG11, RC_TGT_OFFSET_LO, mask_sh), \ - DSC_SF(DSCC0_DSCC_PPS_CONFIG11, RC_TGT_OFFSET_HI, mask_sh), \ - DSC_SF(DSCC0_DSCC_PPS_CONFIG12, RC_BUF_THRESH0, mask_sh), \ - DSC_SF(DSCC0_DSCC_PPS_CONFIG12, RC_BUF_THRESH1, mask_sh), \ - DSC_SF(DSCC0_DSCC_PPS_CONFIG12, RC_BUF_THRESH2, mask_sh), \ - DSC_SF(DSCC0_DSCC_PPS_CONFIG12, RC_BUF_THRESH3, mask_sh), \ - DSC_SF(DSCC0_DSCC_PPS_CONFIG13, RC_BUF_THRESH4, mask_sh), \ - DSC_SF(DSCC0_DSCC_PPS_CONFIG13, RC_BUF_THRESH5, mask_sh), \ - DSC_SF(DSCC0_DSCC_PPS_CONFIG13, RC_BUF_THRESH6, mask_sh), \ - DSC_SF(DSCC0_DSCC_PPS_CONFIG13, RC_BUF_THRESH7, mask_sh), \ - DSC_SF(DSCC0_DSCC_PPS_CONFIG14, RC_BUF_THRESH8, mask_sh), \ - DSC_SF(DSCC0_DSCC_PPS_CONFIG14, RC_BUF_THRESH9, mask_sh), \ - DSC_SF(DSCC0_DSCC_PPS_CONFIG14, RC_BUF_THRESH10, mask_sh), \ - DSC_SF(DSCC0_DSCC_PPS_CONFIG14, RC_BUF_THRESH11, mask_sh), \ - DSC_SF(DSCC0_DSCC_PPS_CONFIG15, RC_BUF_THRESH12, mask_sh), \ - DSC_SF(DSCC0_DSCC_PPS_CONFIG15, RC_BUF_THRESH13, mask_sh), \ - DSC_SF(DSCC0_DSCC_PPS_CONFIG15, RANGE_MIN_QP0, mask_sh), \ - DSC_SF(DSCC0_DSCC_PPS_CONFIG15, RANGE_MAX_QP0, mask_sh), \ - DSC_SF(DSCC0_DSCC_PPS_CONFIG15, RANGE_BPG_OFFSET0, mask_sh), \ - DSC_SF(DSCC0_DSCC_PPS_CONFIG16, RANGE_MIN_QP1, mask_sh), \ - DSC_SF(DSCC0_DSCC_PPS_CONFIG16, RANGE_MAX_QP1, mask_sh), \ - DSC_SF(DSCC0_DSCC_PPS_CONFIG16, RANGE_BPG_OFFSET1, mask_sh), \ - DSC_SF(DSCC0_DSCC_PPS_CONFIG16, RANGE_MIN_QP2, mask_sh), \ - DSC_SF(DSCC0_DSCC_PPS_CONFIG16, RANGE_MAX_QP2, mask_sh), \ - DSC_SF(DSCC0_DSCC_PPS_CONFIG16, RANGE_BPG_OFFSET2, mask_sh), \ - DSC_SF(DSCC0_DSCC_PPS_CONFIG17, RANGE_MIN_QP3, mask_sh), \ - DSC_SF(DSCC0_DSCC_PPS_CONFIG17, RANGE_MAX_QP3, mask_sh), \ - DSC_SF(DSCC0_DSCC_PPS_CONFIG17, RANGE_BPG_OFFSET3, mask_sh), \ - DSC_SF(DSCC0_DSCC_PPS_CONFIG17, RANGE_MIN_QP4, mask_sh), \ - DSC_SF(DSCC0_DSCC_PPS_CONFIG17, RANGE_MAX_QP4, mask_sh), \ - DSC_SF(DSCC0_DSCC_PPS_CONFIG17, RANGE_BPG_OFFSET4, mask_sh), \ - DSC_SF(DSCC0_DSCC_PPS_CONFIG18, RANGE_MIN_QP5, mask_sh), \ - DSC_SF(DSCC0_DSCC_PPS_CONFIG18, RANGE_MAX_QP5, mask_sh), \ - DSC_SF(DSCC0_DSCC_PPS_CONFIG18, RANGE_BPG_OFFSET5, mask_sh), \ - DSC_SF(DSCC0_DSCC_PPS_CONFIG18, RANGE_MIN_QP6, mask_sh), \ - DSC_SF(DSCC0_DSCC_PPS_CONFIG18, RANGE_MAX_QP6, mask_sh), \ - DSC_SF(DSCC0_DSCC_PPS_CONFIG18, RANGE_BPG_OFFSET6, mask_sh), \ - DSC_SF(DSCC0_DSCC_PPS_CONFIG19, RANGE_MIN_QP7, mask_sh), \ - DSC_SF(DSCC0_DSCC_PPS_CONFIG19, RANGE_MAX_QP7, mask_sh), \ - DSC_SF(DSCC0_DSCC_PPS_CONFIG19, RANGE_BPG_OFFSET7, mask_sh), \ - DSC_SF(DSCC0_DSCC_PPS_CONFIG19, RANGE_MIN_QP8, mask_sh), \ - DSC_SF(DSCC0_DSCC_PPS_CONFIG19, RANGE_MAX_QP8, mask_sh), \ - DSC_SF(DSCC0_DSCC_PPS_CONFIG19, RANGE_BPG_OFFSET8, mask_sh), \ - DSC_SF(DSCC0_DSCC_PPS_CONFIG20, RANGE_MIN_QP9, mask_sh), \ - DSC_SF(DSCC0_DSCC_PPS_CONFIG20, RANGE_MAX_QP9, mask_sh), \ - DSC_SF(DSCC0_DSCC_PPS_CONFIG20, RANGE_BPG_OFFSET9, mask_sh), \ - DSC_SF(DSCC0_DSCC_PPS_CONFIG20, RANGE_MIN_QP10, mask_sh), \ - DSC_SF(DSCC0_DSCC_PPS_CONFIG20, RANGE_MAX_QP10, mask_sh), \ - DSC_SF(DSCC0_DSCC_PPS_CONFIG20, RANGE_BPG_OFFSET10, mask_sh), \ - DSC_SF(DSCC0_DSCC_PPS_CONFIG21, RANGE_MIN_QP11, mask_sh), \ - DSC_SF(DSCC0_DSCC_PPS_CONFIG21, RANGE_MAX_QP11, mask_sh), \ - DSC_SF(DSCC0_DSCC_PPS_CONFIG21, RANGE_BPG_OFFSET11, mask_sh), \ - DSC_SF(DSCC0_DSCC_PPS_CONFIG21, RANGE_MIN_QP12, mask_sh), \ - DSC_SF(DSCC0_DSCC_PPS_CONFIG21, RANGE_MAX_QP12, mask_sh), \ - DSC_SF(DSCC0_DSCC_PPS_CONFIG21, RANGE_BPG_OFFSET12, mask_sh), \ - DSC_SF(DSCC0_DSCC_PPS_CONFIG22, RANGE_MIN_QP13, mask_sh), \ - DSC_SF(DSCC0_DSCC_PPS_CONFIG22, RANGE_MAX_QP13, mask_sh), \ - DSC_SF(DSCC0_DSCC_PPS_CONFIG22, RANGE_BPG_OFFSET13, mask_sh), \ - DSC_SF(DSCC0_DSCC_PPS_CONFIG22, RANGE_MIN_QP14, mask_sh), \ - DSC_SF(DSCC0_DSCC_PPS_CONFIG22, RANGE_MAX_QP14, mask_sh), \ - DSC_SF(DSCC0_DSCC_PPS_CONFIG22, RANGE_BPG_OFFSET14, mask_sh), \ - DSC_SF(DSCC0_DSCC_MEM_POWER_CONTROL, DSCC_DEFAULT_MEM_LOW_POWER_STATE, mask_sh), \ - DSC_SF(DSCC0_DSCC_MEM_POWER_CONTROL, DSCC_MEM_PWR_FORCE, mask_sh), \ - DSC_SF(DSCC0_DSCC_MEM_POWER_CONTROL, DSCC_MEM_PWR_DIS, mask_sh), \ - DSC_SF(DSCC0_DSCC_MEM_POWER_CONTROL, DSCC_MEM_PWR_STATE, mask_sh), \ - DSC_SF(DSCC0_DSCC_MEM_POWER_CONTROL, DSCC_NATIVE_422_MEM_PWR_FORCE, mask_sh), \ - DSC_SF(DSCC0_DSCC_MEM_POWER_CONTROL, DSCC_NATIVE_422_MEM_PWR_DIS, mask_sh), \ - DSC_SF(DSCC0_DSCC_MEM_POWER_CONTROL, DSCC_NATIVE_422_MEM_PWR_STATE, mask_sh), \ - DSC_SF(DSCC0_DSCC_R_Y_SQUARED_ERROR_LOWER, DSCC_R_Y_SQUARED_ERROR_LOWER, mask_sh), \ - DSC_SF(DSCC0_DSCC_R_Y_SQUARED_ERROR_UPPER, DSCC_R_Y_SQUARED_ERROR_UPPER, mask_sh), \ - DSC_SF(DSCC0_DSCC_G_CB_SQUARED_ERROR_LOWER, DSCC_G_CB_SQUARED_ERROR_LOWER, mask_sh), \ - DSC_SF(DSCC0_DSCC_G_CB_SQUARED_ERROR_UPPER, DSCC_G_CB_SQUARED_ERROR_UPPER, mask_sh), \ - DSC_SF(DSCC0_DSCC_B_CR_SQUARED_ERROR_LOWER, DSCC_B_CR_SQUARED_ERROR_LOWER, mask_sh), \ - DSC_SF(DSCC0_DSCC_B_CR_SQUARED_ERROR_UPPER, DSCC_B_CR_SQUARED_ERROR_UPPER, mask_sh), \ - DSC_SF(DSCC0_DSCC_MAX_ABS_ERROR0, DSCC_R_Y_MAX_ABS_ERROR, mask_sh), \ - DSC_SF(DSCC0_DSCC_MAX_ABS_ERROR0, DSCC_G_CB_MAX_ABS_ERROR, mask_sh), \ - DSC_SF(DSCC0_DSCC_MAX_ABS_ERROR1, DSCC_B_CR_MAX_ABS_ERROR, mask_sh), \ - DSC_SF(DSCC0_DSCC_RATE_BUFFER0_MAX_FULLNESS_LEVEL, DSCC_RATE_BUFFER0_MAX_FULLNESS_LEVEL, mask_sh), \ - DSC_SF(DSCC0_DSCC_RATE_BUFFER1_MAX_FULLNESS_LEVEL, DSCC_RATE_BUFFER1_MAX_FULLNESS_LEVEL, mask_sh), \ - DSC_SF(DSCC0_DSCC_RATE_BUFFER2_MAX_FULLNESS_LEVEL, DSCC_RATE_BUFFER2_MAX_FULLNESS_LEVEL, mask_sh), \ - DSC_SF(DSCC0_DSCC_RATE_BUFFER3_MAX_FULLNESS_LEVEL, DSCC_RATE_BUFFER3_MAX_FULLNESS_LEVEL, mask_sh), \ - DSC_SF(DSCC0_DSCC_RATE_CONTROL_BUFFER0_MAX_FULLNESS_LEVEL, DSCC_RATE_CONTROL_BUFFER0_MAX_FULLNESS_LEVEL, mask_sh), \ - DSC_SF(DSCC0_DSCC_RATE_CONTROL_BUFFER1_MAX_FULLNESS_LEVEL, DSCC_RATE_CONTROL_BUFFER1_MAX_FULLNESS_LEVEL, mask_sh), \ - DSC_SF(DSCC0_DSCC_RATE_CONTROL_BUFFER2_MAX_FULLNESS_LEVEL, DSCC_RATE_CONTROL_BUFFER2_MAX_FULLNESS_LEVEL, mask_sh), \ - DSC_SF(DSCC0_DSCC_RATE_CONTROL_BUFFER3_MAX_FULLNESS_LEVEL, DSCC_RATE_CONTROL_BUFFER3_MAX_FULLNESS_LEVEL, mask_sh), \ - DSC_SF(DSCCIF0_DSCCIF_CONFIG0, INPUT_INTERFACE_UNDERFLOW_RECOVERY_EN, mask_sh), \ - DSC_SF(DSCCIF0_DSCCIF_CONFIG0, INPUT_INTERFACE_UNDERFLOW_OCCURRED_INT_EN, mask_sh), \ - DSC_SF(DSCCIF0_DSCCIF_CONFIG0, INPUT_INTERFACE_UNDERFLOW_OCCURRED_STATUS, mask_sh), \ - DSC_SF(DSCCIF0_DSCCIF_CONFIG0, INPUT_PIXEL_FORMAT, mask_sh), \ - DSC2_SF(DSCCIF0, DSCCIF_CONFIG0__BITS_PER_COMPONENT, mask_sh), \ - DSC_SF(DSCCIF0_DSCCIF_CONFIG0, DOUBLE_BUFFER_REG_UPDATE_PENDING, mask_sh), \ - DSC_SF(DSCCIF0_DSCCIF_CONFIG1, PIC_WIDTH, mask_sh), \ - DSC_SF(DSCCIF0_DSCCIF_CONFIG1, PIC_HEIGHT, mask_sh), \ - DSC_SF(DSCRM0_DSCRM_DSC_FORWARD_CONFIG, DSCRM_DSC_FORWARD_EN, mask_sh), \ - DSC_SF(DSCRM0_DSCRM_DSC_FORWARD_CONFIG, DSCRM_DSC_OPP_PIPE_SOURCE, mask_sh) - - - -#define DSC_FIELD_LIST_DCN20(type)\ - type DSC_CLOCK_EN; \ - type DSC_DISPCLK_R_GATE_DIS; \ - type DSC_DSCCLK_R_GATE_DIS; \ - type DSC_DBG_EN; \ - type DSC_TEST_CLOCK_MUX_SEL; \ - type ICH_RESET_AT_END_OF_LINE; \ - type NUMBER_OF_SLICES_PER_LINE; \ - type ALTERNATE_ICH_ENCODING_EN; \ - type NUMBER_OF_SLICES_IN_VERTICAL_DIRECTION; \ - type DSCC_RATE_CONTROL_BUFFER_MODEL_SIZE; \ - /*type DSCC_DISABLE_ICH;*/ \ - type DSCC_DOUBLE_BUFFER_REG_UPDATE_PENDING; \ - type DSCC_RATE_BUFFER0_OVERFLOW_OCCURRED; \ - type DSCC_RATE_BUFFER1_OVERFLOW_OCCURRED; \ - type DSCC_RATE_BUFFER2_OVERFLOW_OCCURRED; \ - type DSCC_RATE_BUFFER3_OVERFLOW_OCCURRED; \ - type DSCC_RATE_BUFFER0_UNDERFLOW_OCCURRED; \ - type DSCC_RATE_BUFFER1_UNDERFLOW_OCCURRED; \ - type DSCC_RATE_BUFFER2_UNDERFLOW_OCCURRED; \ - type DSCC_RATE_BUFFER3_UNDERFLOW_OCCURRED; \ - type DSCC_RATE_CONTROL_BUFFER_MODEL0_OVERFLOW_OCCURRED; \ - type DSCC_RATE_CONTROL_BUFFER_MODEL1_OVERFLOW_OCCURRED; \ - type DSCC_RATE_CONTROL_BUFFER_MODEL2_OVERFLOW_OCCURRED; \ - type DSCC_RATE_CONTROL_BUFFER_MODEL3_OVERFLOW_OCCURRED; \ - type DSCC_RATE_BUFFER0_OVERFLOW_OCCURRED_INT_EN; \ - type DSCC_RATE_BUFFER1_OVERFLOW_OCCURRED_INT_EN; \ - type DSCC_RATE_BUFFER2_OVERFLOW_OCCURRED_INT_EN; \ - type DSCC_RATE_BUFFER3_OVERFLOW_OCCURRED_INT_EN; \ - type DSCC_RATE_BUFFER0_UNDERFLOW_OCCURRED_INT_EN; \ - type DSCC_RATE_BUFFER1_UNDERFLOW_OCCURRED_INT_EN; \ - type DSCC_RATE_BUFFER2_UNDERFLOW_OCCURRED_INT_EN; \ - type DSCC_RATE_BUFFER3_UNDERFLOW_OCCURRED_INT_EN; \ - type DSCC_RATE_CONTROL_BUFFER_MODEL0_OVERFLOW_OCCURRED_INT_EN; \ - type DSCC_RATE_CONTROL_BUFFER_MODEL1_OVERFLOW_OCCURRED_INT_EN; \ - type DSCC_RATE_CONTROL_BUFFER_MODEL2_OVERFLOW_OCCURRED_INT_EN; \ - type DSCC_RATE_CONTROL_BUFFER_MODEL3_OVERFLOW_OCCURRED_INT_EN; \ - type DSC_VERSION_MINOR; \ - type DSC_VERSION_MAJOR; \ - type PPS_IDENTIFIER; \ - type LINEBUF_DEPTH; \ - type DSCC_PPS_CONFIG0__BITS_PER_COMPONENT; \ - type BITS_PER_PIXEL; \ - type VBR_ENABLE; \ - type SIMPLE_422; \ - type CONVERT_RGB; \ - type BLOCK_PRED_ENABLE; \ - type NATIVE_422; \ - type NATIVE_420; \ - type CHUNK_SIZE; \ - type PIC_WIDTH; \ - type PIC_HEIGHT; \ - type SLICE_WIDTH; \ - type SLICE_HEIGHT; \ - type INITIAL_XMIT_DELAY; \ - type INITIAL_DEC_DELAY; \ - type INITIAL_SCALE_VALUE; \ - type SCALE_INCREMENT_INTERVAL; \ - type SCALE_DECREMENT_INTERVAL; \ - type FIRST_LINE_BPG_OFFSET; \ - type SECOND_LINE_BPG_OFFSET; \ - type NFL_BPG_OFFSET; \ - type SLICE_BPG_OFFSET; \ - type NSL_BPG_OFFSET; \ - type SECOND_LINE_OFFSET_ADJ; \ - type INITIAL_OFFSET; \ - type FINAL_OFFSET; \ - type FLATNESS_MIN_QP; \ - type FLATNESS_MAX_QP; \ - type RC_MODEL_SIZE; \ - type RC_EDGE_FACTOR; \ - type RC_QUANT_INCR_LIMIT0; \ - type RC_QUANT_INCR_LIMIT1; \ - type RC_TGT_OFFSET_LO; \ - type RC_TGT_OFFSET_HI; \ - type RC_BUF_THRESH0; \ - type RC_BUF_THRESH1; \ - type RC_BUF_THRESH2; \ - type RC_BUF_THRESH3; \ - type RC_BUF_THRESH4; \ - type RC_BUF_THRESH5; \ - type RC_BUF_THRESH6; \ - type RC_BUF_THRESH7; \ - type RC_BUF_THRESH8; \ - type RC_BUF_THRESH9; \ - type RC_BUF_THRESH10; \ - type RC_BUF_THRESH11; \ - type RC_BUF_THRESH12; \ - type RC_BUF_THRESH13; \ - type RANGE_MIN_QP0; \ - type RANGE_MAX_QP0; \ - type RANGE_BPG_OFFSET0; \ - type RANGE_MIN_QP1; \ - type RANGE_MAX_QP1; \ - type RANGE_BPG_OFFSET1; \ - type RANGE_MIN_QP2; \ - type RANGE_MAX_QP2; \ - type RANGE_BPG_OFFSET2; \ - type RANGE_MIN_QP3; \ - type RANGE_MAX_QP3; \ - type RANGE_BPG_OFFSET3; \ - type RANGE_MIN_QP4; \ - type RANGE_MAX_QP4; \ - type RANGE_BPG_OFFSET4; \ - type RANGE_MIN_QP5; \ - type RANGE_MAX_QP5; \ - type RANGE_BPG_OFFSET5; \ - type RANGE_MIN_QP6; \ - type RANGE_MAX_QP6; \ - type RANGE_BPG_OFFSET6; \ - type RANGE_MIN_QP7; \ - type RANGE_MAX_QP7; \ - type RANGE_BPG_OFFSET7; \ - type RANGE_MIN_QP8; \ - type RANGE_MAX_QP8; \ - type RANGE_BPG_OFFSET8; \ - type RANGE_MIN_QP9; \ - type RANGE_MAX_QP9; \ - type RANGE_BPG_OFFSET9; \ - type RANGE_MIN_QP10; \ - type RANGE_MAX_QP10; \ - type RANGE_BPG_OFFSET10; \ - type RANGE_MIN_QP11; \ - type RANGE_MAX_QP11; \ - type RANGE_BPG_OFFSET11; \ - type RANGE_MIN_QP12; \ - type RANGE_MAX_QP12; \ - type RANGE_BPG_OFFSET12; \ - type RANGE_MIN_QP13; \ - type RANGE_MAX_QP13; \ - type RANGE_BPG_OFFSET13; \ - type RANGE_MIN_QP14; \ - type RANGE_MAX_QP14; \ - type RANGE_BPG_OFFSET14; \ - type DSCC_DEFAULT_MEM_LOW_POWER_STATE; \ - type DSCC_MEM_PWR_FORCE; \ - type DSCC_MEM_PWR_DIS; \ - type DSCC_MEM_PWR_STATE; \ - type DSCC_NATIVE_422_MEM_PWR_FORCE; \ - type DSCC_NATIVE_422_MEM_PWR_DIS; \ - type DSCC_NATIVE_422_MEM_PWR_STATE; \ - type DSCC_R_Y_SQUARED_ERROR_LOWER; \ - type DSCC_R_Y_SQUARED_ERROR_UPPER; \ - type DSCC_G_CB_SQUARED_ERROR_LOWER; \ - type DSCC_G_CB_SQUARED_ERROR_UPPER; \ - type DSCC_B_CR_SQUARED_ERROR_LOWER; \ - type DSCC_B_CR_SQUARED_ERROR_UPPER; \ - type DSCC_R_Y_MAX_ABS_ERROR; \ - type DSCC_G_CB_MAX_ABS_ERROR; \ - type DSCC_B_CR_MAX_ABS_ERROR; \ - type DSCC_RATE_BUFFER0_MAX_FULLNESS_LEVEL; \ - type DSCC_RATE_BUFFER1_MAX_FULLNESS_LEVEL; \ - type DSCC_RATE_BUFFER2_MAX_FULLNESS_LEVEL; \ - type DSCC_RATE_BUFFER3_MAX_FULLNESS_LEVEL; \ - type DSCC_RATE_CONTROL_BUFFER0_MAX_FULLNESS_LEVEL; \ - type DSCC_RATE_CONTROL_BUFFER1_MAX_FULLNESS_LEVEL; \ - type DSCC_RATE_CONTROL_BUFFER2_MAX_FULLNESS_LEVEL; \ - type DSCC_RATE_CONTROL_BUFFER3_MAX_FULLNESS_LEVEL; \ - type DSCC_UPDATE_PENDING_STATUS; \ - type DSCC_UPDATE_TAKEN_STATUS; \ - type DSCC_UPDATE_TAKEN_ACK; \ - type DSCC_RATE_BUFFER0_FULLNESS_LEVEL; \ - type DSCC_RATE_BUFFER1_FULLNESS_LEVEL; \ - type DSCC_RATE_BUFFER2_FULLNESS_LEVEL; \ - type DSCC_RATE_BUFFER3_FULLNESS_LEVEL; \ - type DSCC_RATE_CONTROL_BUFFER0_FULLNESS_LEVEL; \ - type DSCC_RATE_CONTROL_BUFFER1_FULLNESS_LEVEL; \ - type DSCC_RATE_CONTROL_BUFFER2_FULLNESS_LEVEL; \ - type DSCC_RATE_CONTROL_BUFFER3_FULLNESS_LEVEL; \ - type DSCC_RATE_BUFFER0_INITIAL_XMIT_DELAY_REACHED; \ - type DSCC_RATE_BUFFER1_INITIAL_XMIT_DELAY_REACHED; \ - type DSCC_RATE_BUFFER2_INITIAL_XMIT_DELAY_REACHED; \ - type DSCC_RATE_BUFFER3_INITIAL_XMIT_DELAY_REACHED; \ - type INPUT_INTERFACE_UNDERFLOW_RECOVERY_EN; \ - type INPUT_INTERFACE_UNDERFLOW_OCCURRED_INT_EN; \ - type INPUT_INTERFACE_UNDERFLOW_OCCURRED_STATUS; \ - type INPUT_PIXEL_FORMAT; \ - type DSCCIF_CONFIG0__BITS_PER_COMPONENT; \ - type DOUBLE_BUFFER_REG_UPDATE_PENDING; \ - type DSCCIF_UPDATE_PENDING_STATUS; \ - type DSCCIF_UPDATE_TAKEN_STATUS; \ - type DSCCIF_UPDATE_TAKEN_ACK; \ - type DSCRM_DSC_FORWARD_EN; \ - type DSCRM_DSC_OPP_PIPE_SOURCE - -struct dcn20_dsc_registers { - uint32_t DSC_TOP_CONTROL; - uint32_t DSC_DEBUG_CONTROL; - uint32_t DSCC_CONFIG0; - uint32_t DSCC_CONFIG1; - uint32_t DSCC_STATUS; - uint32_t DSCC_INTERRUPT_CONTROL_STATUS; - uint32_t DSCC_PPS_CONFIG0; - uint32_t DSCC_PPS_CONFIG1; - uint32_t DSCC_PPS_CONFIG2; - uint32_t DSCC_PPS_CONFIG3; - uint32_t DSCC_PPS_CONFIG4; - uint32_t DSCC_PPS_CONFIG5; - uint32_t DSCC_PPS_CONFIG6; - uint32_t DSCC_PPS_CONFIG7; - uint32_t DSCC_PPS_CONFIG8; - uint32_t DSCC_PPS_CONFIG9; - uint32_t DSCC_PPS_CONFIG10; - uint32_t DSCC_PPS_CONFIG11; - uint32_t DSCC_PPS_CONFIG12; - uint32_t DSCC_PPS_CONFIG13; - uint32_t DSCC_PPS_CONFIG14; - uint32_t DSCC_PPS_CONFIG15; - uint32_t DSCC_PPS_CONFIG16; - uint32_t DSCC_PPS_CONFIG17; - uint32_t DSCC_PPS_CONFIG18; - uint32_t DSCC_PPS_CONFIG19; - uint32_t DSCC_PPS_CONFIG20; - uint32_t DSCC_PPS_CONFIG21; - uint32_t DSCC_PPS_CONFIG22; - uint32_t DSCC_MEM_POWER_CONTROL; - uint32_t DSCC_R_Y_SQUARED_ERROR_LOWER; - uint32_t DSCC_R_Y_SQUARED_ERROR_UPPER; - uint32_t DSCC_G_CB_SQUARED_ERROR_LOWER; - uint32_t DSCC_G_CB_SQUARED_ERROR_UPPER; - uint32_t DSCC_B_CR_SQUARED_ERROR_LOWER; - uint32_t DSCC_B_CR_SQUARED_ERROR_UPPER; - uint32_t DSCC_MAX_ABS_ERROR0; - uint32_t DSCC_MAX_ABS_ERROR1; - uint32_t DSCC_RATE_BUFFER0_MAX_FULLNESS_LEVEL; - uint32_t DSCC_RATE_BUFFER1_MAX_FULLNESS_LEVEL; - uint32_t DSCC_RATE_BUFFER2_MAX_FULLNESS_LEVEL; - uint32_t DSCC_RATE_BUFFER3_MAX_FULLNESS_LEVEL; - uint32_t DSCC_RATE_CONTROL_BUFFER0_MAX_FULLNESS_LEVEL; - uint32_t DSCC_RATE_CONTROL_BUFFER1_MAX_FULLNESS_LEVEL; - uint32_t DSCC_RATE_CONTROL_BUFFER2_MAX_FULLNESS_LEVEL; - uint32_t DSCC_RATE_CONTROL_BUFFER3_MAX_FULLNESS_LEVEL; - uint32_t DSCCIF_CONFIG0; - uint32_t DSCCIF_CONFIG1; - uint32_t DSCRM_DSC_FORWARD_CONFIG; -}; - - -struct dcn20_dsc_shift { - DSC_FIELD_LIST_DCN20(uint8_t); -}; - -struct dcn20_dsc_mask { - DSC_FIELD_LIST_DCN20(uint32_t); -}; - -/* DSCCIF_CONFIG.INPUT_PIXEL_FORMAT values */ -enum dsc_pixel_format { - DSC_PIXFMT_RGB, - DSC_PIXFMT_YCBCR444, - DSC_PIXFMT_SIMPLE_YCBCR422, - DSC_PIXFMT_NATIVE_YCBCR422, - DSC_PIXFMT_NATIVE_YCBCR420, - DSC_PIXFMT_UNKNOWN -}; - -struct dsc_reg_values { - /* PPS registers */ - struct drm_dsc_config pps; - - /* Additional registers */ - uint32_t dsc_clock_enable; - uint32_t dsc_clock_gating_disable; - uint32_t underflow_recovery_en; - uint32_t underflow_occurred_int_en; - uint32_t underflow_occurred_status; - enum dsc_pixel_format pixel_format; - uint32_t ich_reset_at_eol; - uint32_t alternate_ich_encoding_en; - uint32_t num_slices_h; - uint32_t num_slices_v; - uint32_t rc_buffer_model_size; - uint32_t disable_ich; - uint32_t bpp_x32; - uint32_t dsc_dbg_en; - uint32_t rc_buffer_model_overflow_int_en[4]; -}; - -struct dcn20_dsc { - struct display_stream_compressor base; - const struct dcn20_dsc_registers *dsc_regs; - const struct dcn20_dsc_shift *dsc_shift; - const struct dcn20_dsc_mask *dsc_mask; - - struct dsc_reg_values reg_vals; - - int max_image_width; -}; - -void dsc_config_log(struct display_stream_compressor *dsc, - const struct dsc_config *config); - -void dsc_log_pps(struct display_stream_compressor *dsc, - struct drm_dsc_config *pps); - -void dsc_override_rc_params(struct rc_params *rc, - const struct dc_dsc_rc_params_override *override); - -bool dsc_prepare_config(const struct dsc_config *dsc_cfg, - struct dsc_reg_values *dsc_reg_vals, - struct dsc_optc_config *dsc_optc_cfg); - -enum dsc_pixel_format dsc_dc_pixel_encoding_to_dsc_pixel_format(enum dc_pixel_encoding dc_pix_enc, - bool is_ycbcr422_simple); - -enum dsc_bits_per_comp dsc_dc_color_depth_to_dsc_bits_per_comp(enum dc_color_depth dc_color_depth); - -void dsc_init_reg_values(struct dsc_reg_values *reg_vals); - -void dsc_update_from_dsc_parameters(struct dsc_reg_values *reg_vals, const struct dsc_parameters *dsc_params); - -void dsc2_construct(struct dcn20_dsc *dsc, - struct dc_context *ctx, - int inst, - const struct dcn20_dsc_registers *dsc_regs, - const struct dcn20_dsc_shift *dsc_shift, - const struct dcn20_dsc_mask *dsc_mask); - -void dsc2_get_enc_caps(struct dsc_enc_caps *dsc_enc_caps, - int pixel_clock_100Hz); - -bool dsc2_get_packed_pps(struct display_stream_compressor *dsc, - const struct dsc_config *dsc_cfg, - uint8_t *dsc_packed_pps); - -#endif - diff --git a/drivers/gpu/drm/amd/display/dc/dcn35/Makefile b/drivers/gpu/drm/amd/display/dc/dcn35/Makefile index 719afb5a3b12..85a307babab9 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn35/Makefile +++ b/drivers/gpu/drm/amd/display/dc/dcn35/Makefile @@ -12,7 +12,7 @@ DCN35 = dcn35_init.o dcn35_dio_stream_encoder.o \ dcn35_dio_link_encoder.o dcn35_dccg.o dcn35_optc.o \ - dcn35_dsc.o dcn35_hubp.o dcn35_hubbub.o \ + dcn35_hubp.o dcn35_hubbub.o \ dcn35_mmhubbub.o dcn35_opp.o dcn35_dpp.o dcn35_pg_cntl.o dcn35_dwb.o AMD_DAL_DCN35 = $(addprefix $(AMDDALPATH)/dc/dcn35/,$(DCN35)) diff --git a/drivers/gpu/drm/amd/display/dc/dcn35/dcn35_dsc.c b/drivers/gpu/drm/amd/display/dc/dcn35/dcn35_dsc.c deleted file mode 100644 index 71d2dff9986d..000000000000 --- a/drivers/gpu/drm/amd/display/dc/dcn35/dcn35_dsc.c +++ /dev/null @@ -1,60 +0,0 @@ -/* SPDX-License-Identifier: MIT */ -/* - * Copyright 2023 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 "dcn35_dsc.h" -#include "reg_helper.h" - -/* Macro definitios for REG_SET macros*/ -#define CTX \ - dsc20->base.ctx - -#define REG(reg)\ - dsc20->dsc_regs->reg - -#undef FN -#define FN(reg_name, field_name) \ - ((const struct dcn35_dsc_shift *)(dsc20->dsc_shift))->field_name, \ - ((const struct dcn35_dsc_mask *)(dsc20->dsc_mask))->field_name - -#define DC_LOGGER \ - dsc->ctx->logger - -void dsc35_construct(struct dcn20_dsc *dsc, - struct dc_context *ctx, - int inst, - const struct dcn20_dsc_registers *dsc_regs, - const struct dcn35_dsc_shift *dsc_shift, - const struct dcn35_dsc_mask *dsc_mask) -{ - dsc2_construct(dsc, ctx, inst, dsc_regs, - (const struct dcn20_dsc_shift *)(dsc_shift), - (const struct dcn20_dsc_mask *)(dsc_mask)); -} - -void dsc35_set_fgcg(struct dcn20_dsc *dsc20, bool enable) -{ - REG_UPDATE(DSC_TOP_CONTROL, DSC_FGCG_REP_DIS, !enable); -} diff --git a/drivers/gpu/drm/amd/display/dc/dcn35/dcn35_dsc.h b/drivers/gpu/drm/amd/display/dc/dcn35/dcn35_dsc.h deleted file mode 100644 index 133ad38842cc..000000000000 --- a/drivers/gpu/drm/amd/display/dc/dcn35/dcn35_dsc.h +++ /dev/null @@ -1,59 +0,0 @@ -/* SPDX-License-Identifier: MIT */ -/* - * Copyright 2023 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 __DCN35_DSC_H__ -#define __DCN35_DSC_H__ - -#include "dcn20/dcn20_dsc.h" - -#define DSC_REG_LIST_SH_MASK_DCN35(mask_sh) \ - DSC_REG_LIST_SH_MASK_DCN20(mask_sh), \ - DSC_SF(DSC_TOP0_DSC_TOP_CONTROL, DSC_FGCG_REP_DIS, mask_sh) - -#define DSC_FIELD_LIST_DCN35(type) \ - struct { \ - DSC_FIELD_LIST_DCN20(type); \ - type DSC_FGCG_REP_DIS; \ - } - -struct dcn35_dsc_shift { - DSC_FIELD_LIST_DCN35(uint8_t); -}; - -struct dcn35_dsc_mask { - DSC_FIELD_LIST_DCN35(uint32_t); -}; - -void dsc35_construct(struct dcn20_dsc *dsc, - struct dc_context *ctx, - int inst, - const struct dcn20_dsc_registers *dsc_regs, - const struct dcn35_dsc_shift *dsc_shift, - const struct dcn35_dsc_mask *dsc_mask); - -void dsc35_set_fgcg(struct dcn20_dsc *dsc20, bool enable); - -#endif /* __DCN35_DSC_H__ */ diff --git a/drivers/gpu/drm/amd/display/dc/dsc/Makefile b/drivers/gpu/drm/amd/display/dc/dsc/Makefile index a2537229ee88..b183ba5a692e 100644 --- a/drivers/gpu/drm/amd/display/dc/dsc/Makefile +++ b/drivers/gpu/drm/amd/display/dc/dsc/Makefile @@ -1,8 +1,34 @@ # SPDX-License-Identifier: MIT # # Makefile for the 'dsc' sub-component of DAL. + +ifdef CONFIG_DRM_AMD_DC_FP + +############################################################################### +# DCN20 +############################################################################### +DSC_DCN20 = dcn20_dsc.o + +AMD_DISPLAY_FILES += $(addprefix $(AMDDALPATH)/dc/dsc/dcn20/,$(DSC_DCN20)) + + + + +############################################################################### +# DCN35 +############################################################################### + +DSC_DCN35 = dcn35_dsc.o + +AMD_DISPLAY_FILES += $(addprefix $(AMDDALPATH)/dc/dsc/dcn35/,$(DSC_DCN35)) + + + +endif + DSC = dc_dsc.o rc_calc.o rc_calc_dpi.o AMD_DAL_DSC = $(addprefix $(AMDDALPATH)/dc/dsc/,$(DSC)) AMD_DISPLAY_FILES += $(AMD_DAL_DSC) + diff --git a/drivers/gpu/drm/amd/display/dc/dsc/dcn20/dcn20_dsc.c b/drivers/gpu/drm/amd/display/dc/dsc/dcn20/dcn20_dsc.c new file mode 100644 index 000000000000..c9ae2d8f0096 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/dsc/dcn20/dcn20_dsc.c @@ -0,0 +1,780 @@ +/* + * Copyright 2017 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 + +#include "reg_helper.h" +#include "dcn20_dsc.h" +#include "dsc/dscc_types.h" +#include "dsc/rc_calc.h" + +static void dsc_write_to_registers(struct display_stream_compressor *dsc, const struct dsc_reg_values *reg_vals); + +/* Object I/F functions */ +static void dsc2_read_state(struct display_stream_compressor *dsc, struct dcn_dsc_state *s); +static bool dsc2_validate_stream(struct display_stream_compressor *dsc, const struct dsc_config *dsc_cfg); +static void dsc2_set_config(struct display_stream_compressor *dsc, const struct dsc_config *dsc_cfg, + struct dsc_optc_config *dsc_optc_cfg); +static void dsc2_enable(struct display_stream_compressor *dsc, int opp_pipe); +static void dsc2_disable(struct display_stream_compressor *dsc); +static void dsc2_disconnect(struct display_stream_compressor *dsc); + +static const struct dsc_funcs dcn20_dsc_funcs = { + .dsc_get_enc_caps = dsc2_get_enc_caps, + .dsc_read_state = dsc2_read_state, + .dsc_validate_stream = dsc2_validate_stream, + .dsc_set_config = dsc2_set_config, + .dsc_get_packed_pps = dsc2_get_packed_pps, + .dsc_enable = dsc2_enable, + .dsc_disable = dsc2_disable, + .dsc_disconnect = dsc2_disconnect, +}; + +/* Macro definitios for REG_SET macros*/ +#define CTX \ + dsc20->base.ctx + +#define REG(reg)\ + dsc20->dsc_regs->reg + +#undef FN +#define FN(reg_name, field_name) \ + dsc20->dsc_shift->field_name, dsc20->dsc_mask->field_name +#define DC_LOGGER \ + dsc->ctx->logger + +enum dsc_bits_per_comp { + DSC_BPC_8 = 8, + DSC_BPC_10 = 10, + DSC_BPC_12 = 12, + DSC_BPC_UNKNOWN +}; + +/* API functions (external or via structure->function_pointer) */ + +void dsc2_construct(struct dcn20_dsc *dsc, + struct dc_context *ctx, + int inst, + const struct dcn20_dsc_registers *dsc_regs, + const struct dcn20_dsc_shift *dsc_shift, + const struct dcn20_dsc_mask *dsc_mask) +{ + dsc->base.ctx = ctx; + dsc->base.inst = inst; + dsc->base.funcs = &dcn20_dsc_funcs; + + dsc->dsc_regs = dsc_regs; + dsc->dsc_shift = dsc_shift; + dsc->dsc_mask = dsc_mask; + + dsc->max_image_width = 5184; +} + + +#define DCN20_MAX_PIXEL_CLOCK_Mhz 1188 +#define DCN20_MAX_DISPLAY_CLOCK_Mhz 1200 + +/* This returns the capabilities for a single DSC encoder engine. Number of slices and total throughput + * can be doubled, tripled etc. by using additional DSC engines. + */ +void dsc2_get_enc_caps(struct dsc_enc_caps *dsc_enc_caps, int pixel_clock_100Hz) +{ + dsc_enc_caps->dsc_version = 0x21; /* v1.2 - DP spec defined it in reverse order and we kept it */ + + dsc_enc_caps->slice_caps.bits.NUM_SLICES_1 = 1; + dsc_enc_caps->slice_caps.bits.NUM_SLICES_2 = 1; + dsc_enc_caps->slice_caps.bits.NUM_SLICES_3 = 1; + dsc_enc_caps->slice_caps.bits.NUM_SLICES_4 = 1; + + dsc_enc_caps->lb_bit_depth = 13; + dsc_enc_caps->is_block_pred_supported = true; + + dsc_enc_caps->color_formats.bits.RGB = 1; + dsc_enc_caps->color_formats.bits.YCBCR_444 = 1; + dsc_enc_caps->color_formats.bits.YCBCR_SIMPLE_422 = 1; + dsc_enc_caps->color_formats.bits.YCBCR_NATIVE_422 = 0; + dsc_enc_caps->color_formats.bits.YCBCR_NATIVE_420 = 1; + + dsc_enc_caps->color_depth.bits.COLOR_DEPTH_8_BPC = 1; + dsc_enc_caps->color_depth.bits.COLOR_DEPTH_10_BPC = 1; + dsc_enc_caps->color_depth.bits.COLOR_DEPTH_12_BPC = 1; + + /* Maximum total throughput with all the slices combined. This is different from how DP spec specifies it. + * Our decoder's total throughput in Pix/s is equal to DISPCLK. This is then shared between slices. + * The value below is the absolute maximum value. The actual throughput may be lower, but it'll always + * be sufficient to process the input pixel rate fed into a single DSC engine. + */ + dsc_enc_caps->max_total_throughput_mps = DCN20_MAX_DISPLAY_CLOCK_Mhz; + + /* For pixel clock bigger than a single-pipe limit we'll need two engines, which then doubles our + * throughput and number of slices, but also introduces a lower limit of 2 slices + */ + if (pixel_clock_100Hz >= DCN20_MAX_PIXEL_CLOCK_Mhz*10000) { + dsc_enc_caps->slice_caps.bits.NUM_SLICES_1 = 0; + dsc_enc_caps->slice_caps.bits.NUM_SLICES_8 = 1; + dsc_enc_caps->max_total_throughput_mps = DCN20_MAX_DISPLAY_CLOCK_Mhz * 2; + } + + /* For pixel clock bigger than a single-pipe limit needing four engines ODM 4:1, which then quardruples our + * throughput and number of slices + */ + if (pixel_clock_100Hz > DCN20_MAX_PIXEL_CLOCK_Mhz*10000*2) { + dsc_enc_caps->slice_caps.bits.NUM_SLICES_12 = 1; + dsc_enc_caps->slice_caps.bits.NUM_SLICES_16 = 1; + dsc_enc_caps->max_total_throughput_mps = DCN20_MAX_DISPLAY_CLOCK_Mhz * 4; + } + + dsc_enc_caps->max_slice_width = 5184; /* (including 64 overlap pixels for eDP MSO mode) */ + dsc_enc_caps->bpp_increment_div = 16; /* 1/16th of a bit */ +} + + +/* this function read dsc related register fields to be logged later in dcn10_log_hw_state + * into a dcn_dsc_state struct. + */ +static void dsc2_read_state(struct display_stream_compressor *dsc, struct dcn_dsc_state *s) +{ + struct dcn20_dsc *dsc20 = TO_DCN20_DSC(dsc); + + REG_GET(DSC_TOP_CONTROL, DSC_CLOCK_EN, &s->dsc_clock_en); + REG_GET(DSCC_PPS_CONFIG3, SLICE_WIDTH, &s->dsc_slice_width); + REG_GET(DSCC_PPS_CONFIG1, BITS_PER_PIXEL, &s->dsc_bits_per_pixel); + REG_GET(DSCC_PPS_CONFIG3, SLICE_HEIGHT, &s->dsc_slice_height); + REG_GET(DSCC_PPS_CONFIG1, CHUNK_SIZE, &s->dsc_chunk_size); + REG_GET(DSCC_PPS_CONFIG2, PIC_WIDTH, &s->dsc_pic_width); + REG_GET(DSCC_PPS_CONFIG2, PIC_HEIGHT, &s->dsc_pic_height); + REG_GET(DSCC_PPS_CONFIG7, SLICE_BPG_OFFSET, &s->dsc_slice_bpg_offset); + REG_GET_2(DSCRM_DSC_FORWARD_CONFIG, DSCRM_DSC_FORWARD_EN, &s->dsc_fw_en, + DSCRM_DSC_OPP_PIPE_SOURCE, &s->dsc_opp_source); +} + + +static bool dsc2_validate_stream(struct display_stream_compressor *dsc, const struct dsc_config *dsc_cfg) +{ + struct dsc_optc_config dsc_optc_cfg; + struct dcn20_dsc *dsc20 = TO_DCN20_DSC(dsc); + + if (dsc_cfg->pic_width > dsc20->max_image_width) + return false; + + return dsc_prepare_config(dsc_cfg, &dsc20->reg_vals, &dsc_optc_cfg); +} + + +void dsc_config_log(struct display_stream_compressor *dsc, const struct dsc_config *config) +{ + DC_LOG_DSC("\tnum_slices_h %d", config->dc_dsc_cfg.num_slices_h); + DC_LOG_DSC("\tnum_slices_v %d", config->dc_dsc_cfg.num_slices_v); + DC_LOG_DSC("\tbits_per_pixel %d (%d.%04d)", + config->dc_dsc_cfg.bits_per_pixel, + config->dc_dsc_cfg.bits_per_pixel / 16, + ((config->dc_dsc_cfg.bits_per_pixel % 16) * 10000) / 16); + DC_LOG_DSC("\tcolor_depth %d", config->color_depth); +} + +static void dsc2_set_config(struct display_stream_compressor *dsc, const struct dsc_config *dsc_cfg, + struct dsc_optc_config *dsc_optc_cfg) +{ + bool is_config_ok; + struct dcn20_dsc *dsc20 = TO_DCN20_DSC(dsc); + + DC_LOG_DSC("Setting DSC Config at DSC inst %d", dsc->inst); + dsc_config_log(dsc, dsc_cfg); + is_config_ok = dsc_prepare_config(dsc_cfg, &dsc20->reg_vals, dsc_optc_cfg); + ASSERT(is_config_ok); + DC_LOG_DSC("programming DSC Picture Parameter Set (PPS):"); + dsc_log_pps(dsc, &dsc20->reg_vals.pps); + dsc_write_to_registers(dsc, &dsc20->reg_vals); +} + + +bool dsc2_get_packed_pps(struct display_stream_compressor *dsc, const struct dsc_config *dsc_cfg, uint8_t *dsc_packed_pps) +{ + bool is_config_ok; + struct dsc_reg_values dsc_reg_vals; + struct dsc_optc_config dsc_optc_cfg; + + memset(&dsc_reg_vals, 0, sizeof(dsc_reg_vals)); + memset(&dsc_optc_cfg, 0, sizeof(dsc_optc_cfg)); + + DC_LOG_DSC("Getting packed DSC PPS for DSC Config:"); + dsc_config_log(dsc, dsc_cfg); + DC_LOG_DSC("DSC Picture Parameter Set (PPS):"); + is_config_ok = dsc_prepare_config(dsc_cfg, &dsc_reg_vals, &dsc_optc_cfg); + ASSERT(is_config_ok); + drm_dsc_pps_payload_pack((struct drm_dsc_picture_parameter_set *)dsc_packed_pps, &dsc_reg_vals.pps); + dsc_log_pps(dsc, &dsc_reg_vals.pps); + + return is_config_ok; +} + + +static void dsc2_enable(struct display_stream_compressor *dsc, int opp_pipe) +{ + struct dcn20_dsc *dsc20 = TO_DCN20_DSC(dsc); + int dsc_clock_en; + int dsc_fw_config; + int enabled_opp_pipe; + + DC_LOG_DSC("enable DSC %d at opp pipe %d", dsc->inst, opp_pipe); + + REG_GET(DSC_TOP_CONTROL, DSC_CLOCK_EN, &dsc_clock_en); + REG_GET_2(DSCRM_DSC_FORWARD_CONFIG, DSCRM_DSC_FORWARD_EN, &dsc_fw_config, DSCRM_DSC_OPP_PIPE_SOURCE, &enabled_opp_pipe); + if ((dsc_clock_en || dsc_fw_config) && enabled_opp_pipe != opp_pipe) { + DC_LOG_DSC("ERROR: DSC %d at opp pipe %d already enabled!", dsc->inst, enabled_opp_pipe); + ASSERT(0); + } + + REG_UPDATE(DSC_TOP_CONTROL, + DSC_CLOCK_EN, 1); + + REG_UPDATE_2(DSCRM_DSC_FORWARD_CONFIG, + DSCRM_DSC_FORWARD_EN, 1, + DSCRM_DSC_OPP_PIPE_SOURCE, opp_pipe); +} + + +static void dsc2_disable(struct display_stream_compressor *dsc) +{ + struct dcn20_dsc *dsc20 = TO_DCN20_DSC(dsc); + int dsc_clock_en; + int dsc_fw_config; + int enabled_opp_pipe; + + DC_LOG_DSC("disable DSC %d", dsc->inst); + + REG_GET(DSC_TOP_CONTROL, DSC_CLOCK_EN, &dsc_clock_en); + REG_GET_2(DSCRM_DSC_FORWARD_CONFIG, DSCRM_DSC_FORWARD_EN, &dsc_fw_config, DSCRM_DSC_OPP_PIPE_SOURCE, &enabled_opp_pipe); + if (!dsc_clock_en || !dsc_fw_config) { + DC_LOG_DSC("ERROR: DSC %d at opp pipe %d already disabled!", dsc->inst, enabled_opp_pipe); + ASSERT(0); + } + + REG_UPDATE(DSCRM_DSC_FORWARD_CONFIG, + DSCRM_DSC_FORWARD_EN, 0); + + REG_UPDATE(DSC_TOP_CONTROL, + DSC_CLOCK_EN, 0); +} + +static void dsc2_disconnect(struct display_stream_compressor *dsc) +{ + struct dcn20_dsc *dsc20 = TO_DCN20_DSC(dsc); + + DC_LOG_DSC("disconnect DSC %d", dsc->inst); + + REG_UPDATE(DSCRM_DSC_FORWARD_CONFIG, + DSCRM_DSC_FORWARD_EN, 0); +} + +/* This module's internal functions */ +void dsc_log_pps(struct display_stream_compressor *dsc, struct drm_dsc_config *pps) +{ + int i; + int bits_per_pixel = pps->bits_per_pixel; + + DC_LOG_DSC("\tdsc_version_major %d", pps->dsc_version_major); + DC_LOG_DSC("\tdsc_version_minor %d", pps->dsc_version_minor); + DC_LOG_DSC("\tbits_per_component %d", pps->bits_per_component); + DC_LOG_DSC("\tline_buf_depth %d", pps->line_buf_depth); + DC_LOG_DSC("\tblock_pred_enable %d", pps->block_pred_enable); + DC_LOG_DSC("\tconvert_rgb %d", pps->convert_rgb); + DC_LOG_DSC("\tsimple_422 %d", pps->simple_422); + DC_LOG_DSC("\tvbr_enable %d", pps->vbr_enable); + DC_LOG_DSC("\tbits_per_pixel %d (%d.%04d)", bits_per_pixel, bits_per_pixel / 16, ((bits_per_pixel % 16) * 10000) / 16); + DC_LOG_DSC("\tpic_height %d", pps->pic_height); + DC_LOG_DSC("\tpic_width %d", pps->pic_width); + DC_LOG_DSC("\tslice_height %d", pps->slice_height); + DC_LOG_DSC("\tslice_width %d", pps->slice_width); + DC_LOG_DSC("\tslice_chunk_size %d", pps->slice_chunk_size); + DC_LOG_DSC("\tinitial_xmit_delay %d", pps->initial_xmit_delay); + DC_LOG_DSC("\tinitial_dec_delay %d", pps->initial_dec_delay); + DC_LOG_DSC("\tinitial_scale_value %d", pps->initial_scale_value); + DC_LOG_DSC("\tscale_increment_interval %d", pps->scale_increment_interval); + DC_LOG_DSC("\tscale_decrement_interval %d", pps->scale_decrement_interval); + DC_LOG_DSC("\tfirst_line_bpg_offset %d", pps->first_line_bpg_offset); + DC_LOG_DSC("\tnfl_bpg_offset %d", pps->nfl_bpg_offset); + DC_LOG_DSC("\tslice_bpg_offset %d", pps->slice_bpg_offset); + DC_LOG_DSC("\tinitial_offset %d", pps->initial_offset); + DC_LOG_DSC("\tfinal_offset %d", pps->final_offset); + DC_LOG_DSC("\tflatness_min_qp %d", pps->flatness_min_qp); + DC_LOG_DSC("\tflatness_max_qp %d", pps->flatness_max_qp); + /* DC_LOG_DSC("\trc_parameter_set %d", pps->rc_parameter_set); */ + DC_LOG_DSC("\tnative_420 %d", pps->native_420); + DC_LOG_DSC("\tnative_422 %d", pps->native_422); + DC_LOG_DSC("\tsecond_line_bpg_offset %d", pps->second_line_bpg_offset); + DC_LOG_DSC("\tnsl_bpg_offset %d", pps->nsl_bpg_offset); + DC_LOG_DSC("\tsecond_line_offset_adj %d", pps->second_line_offset_adj); + DC_LOG_DSC("\trc_model_size %d", pps->rc_model_size); + DC_LOG_DSC("\trc_edge_factor %d", pps->rc_edge_factor); + DC_LOG_DSC("\trc_quant_incr_limit0 %d", pps->rc_quant_incr_limit0); + DC_LOG_DSC("\trc_quant_incr_limit1 %d", pps->rc_quant_incr_limit1); + DC_LOG_DSC("\trc_tgt_offset_high %d", pps->rc_tgt_offset_high); + DC_LOG_DSC("\trc_tgt_offset_low %d", pps->rc_tgt_offset_low); + + for (i = 0; i < NUM_BUF_RANGES - 1; i++) + DC_LOG_DSC("\trc_buf_thresh[%d] %d", i, pps->rc_buf_thresh[i]); + + for (i = 0; i < NUM_BUF_RANGES; i++) { + DC_LOG_DSC("\trc_range_parameters[%d].range_min_qp %d", i, pps->rc_range_params[i].range_min_qp); + DC_LOG_DSC("\trc_range_parameters[%d].range_max_qp %d", i, pps->rc_range_params[i].range_max_qp); + DC_LOG_DSC("\trc_range_parameters[%d].range_bpg_offset %d", i, pps->rc_range_params[i].range_bpg_offset); + } +} + +void dsc_override_rc_params(struct rc_params *rc, const struct dc_dsc_rc_params_override *override) +{ + uint8_t i; + + rc->rc_model_size = override->rc_model_size; + for (i = 0; i < DC_DSC_RC_BUF_THRESH_SIZE; i++) + rc->rc_buf_thresh[i] = override->rc_buf_thresh[i]; + for (i = 0; i < DC_DSC_QP_SET_SIZE; i++) { + rc->qp_min[i] = override->rc_minqp[i]; + rc->qp_max[i] = override->rc_maxqp[i]; + rc->ofs[i] = override->rc_offset[i]; + } + + rc->rc_tgt_offset_hi = override->rc_tgt_offset_hi; + rc->rc_tgt_offset_lo = override->rc_tgt_offset_lo; + rc->rc_edge_factor = override->rc_edge_factor; + rc->rc_quant_incr_limit0 = override->rc_quant_incr_limit0; + rc->rc_quant_incr_limit1 = override->rc_quant_incr_limit1; + + rc->initial_fullness_offset = override->initial_fullness_offset; + rc->initial_xmit_delay = override->initial_delay; + + rc->flatness_min_qp = override->flatness_min_qp; + rc->flatness_max_qp = override->flatness_max_qp; + rc->flatness_det_thresh = override->flatness_det_thresh; +} + +bool dsc_prepare_config(const struct dsc_config *dsc_cfg, struct dsc_reg_values *dsc_reg_vals, + struct dsc_optc_config *dsc_optc_cfg) +{ + struct dsc_parameters dsc_params; + struct rc_params rc; + + /* Validate input parameters */ + ASSERT(dsc_cfg->dc_dsc_cfg.num_slices_h); + ASSERT(dsc_cfg->dc_dsc_cfg.num_slices_v); + ASSERT(dsc_cfg->dc_dsc_cfg.version_minor == 1 || dsc_cfg->dc_dsc_cfg.version_minor == 2); + ASSERT(dsc_cfg->pic_width); + ASSERT(dsc_cfg->pic_height); + ASSERT((dsc_cfg->dc_dsc_cfg.version_minor == 1 && + (8 <= dsc_cfg->dc_dsc_cfg.linebuf_depth && dsc_cfg->dc_dsc_cfg.linebuf_depth <= 13)) || + (dsc_cfg->dc_dsc_cfg.version_minor == 2 && + ((8 <= dsc_cfg->dc_dsc_cfg.linebuf_depth && dsc_cfg->dc_dsc_cfg.linebuf_depth <= 15) || + dsc_cfg->dc_dsc_cfg.linebuf_depth == 0))); + ASSERT(96 <= dsc_cfg->dc_dsc_cfg.bits_per_pixel && dsc_cfg->dc_dsc_cfg.bits_per_pixel <= 0x3ff); // 6.0 <= bits_per_pixel <= 63.9375 + + if (!dsc_cfg->dc_dsc_cfg.num_slices_v || !dsc_cfg->dc_dsc_cfg.num_slices_h || + !(dsc_cfg->dc_dsc_cfg.version_minor == 1 || dsc_cfg->dc_dsc_cfg.version_minor == 2) || + !dsc_cfg->pic_width || !dsc_cfg->pic_height || + !((dsc_cfg->dc_dsc_cfg.version_minor == 1 && // v1.1 line buffer depth range: + 8 <= dsc_cfg->dc_dsc_cfg.linebuf_depth && dsc_cfg->dc_dsc_cfg.linebuf_depth <= 13) || + (dsc_cfg->dc_dsc_cfg.version_minor == 2 && // v1.2 line buffer depth range: + ((8 <= dsc_cfg->dc_dsc_cfg.linebuf_depth && dsc_cfg->dc_dsc_cfg.linebuf_depth <= 15) || + dsc_cfg->dc_dsc_cfg.linebuf_depth == 0))) || + !(96 <= dsc_cfg->dc_dsc_cfg.bits_per_pixel && dsc_cfg->dc_dsc_cfg.bits_per_pixel <= 0x3ff)) { + dm_output_to_console("%s: Invalid parameters\n", __func__); + return false; + } + + dsc_init_reg_values(dsc_reg_vals); + + /* Copy input config */ + dsc_reg_vals->pixel_format = dsc_dc_pixel_encoding_to_dsc_pixel_format(dsc_cfg->pixel_encoding, dsc_cfg->dc_dsc_cfg.ycbcr422_simple); + dsc_reg_vals->num_slices_h = dsc_cfg->dc_dsc_cfg.num_slices_h; + dsc_reg_vals->num_slices_v = dsc_cfg->dc_dsc_cfg.num_slices_v; + dsc_reg_vals->pps.dsc_version_minor = dsc_cfg->dc_dsc_cfg.version_minor; + dsc_reg_vals->pps.pic_width = dsc_cfg->pic_width; + dsc_reg_vals->pps.pic_height = dsc_cfg->pic_height; + dsc_reg_vals->pps.bits_per_component = dsc_dc_color_depth_to_dsc_bits_per_comp(dsc_cfg->color_depth); + dsc_reg_vals->pps.block_pred_enable = dsc_cfg->dc_dsc_cfg.block_pred_enable; + dsc_reg_vals->pps.line_buf_depth = dsc_cfg->dc_dsc_cfg.linebuf_depth; + dsc_reg_vals->alternate_ich_encoding_en = dsc_reg_vals->pps.dsc_version_minor == 1 ? 0 : 1; + dsc_reg_vals->ich_reset_at_eol = (dsc_cfg->is_odm || dsc_reg_vals->num_slices_h > 1) ? 0xF : 0; + + // TODO: in addition to validating slice height (pic height must be divisible by slice height), + // see what happens when the same condition doesn't apply for slice_width/pic_width. + dsc_reg_vals->pps.slice_width = dsc_cfg->pic_width / dsc_cfg->dc_dsc_cfg.num_slices_h; + dsc_reg_vals->pps.slice_height = dsc_cfg->pic_height / dsc_cfg->dc_dsc_cfg.num_slices_v; + + ASSERT(dsc_reg_vals->pps.slice_height * dsc_cfg->dc_dsc_cfg.num_slices_v == dsc_cfg->pic_height); + if (!(dsc_reg_vals->pps.slice_height * dsc_cfg->dc_dsc_cfg.num_slices_v == dsc_cfg->pic_height)) { + dm_output_to_console("%s: pix height %d not divisible by num_slices_v %d\n\n", __func__, dsc_cfg->pic_height, dsc_cfg->dc_dsc_cfg.num_slices_v); + return false; + } + + dsc_reg_vals->bpp_x32 = dsc_cfg->dc_dsc_cfg.bits_per_pixel << 1; + if (dsc_reg_vals->pixel_format == DSC_PIXFMT_NATIVE_YCBCR420 || dsc_reg_vals->pixel_format == DSC_PIXFMT_NATIVE_YCBCR422) + dsc_reg_vals->pps.bits_per_pixel = dsc_reg_vals->bpp_x32; + else + dsc_reg_vals->pps.bits_per_pixel = dsc_reg_vals->bpp_x32 >> 1; + + dsc_reg_vals->pps.convert_rgb = dsc_reg_vals->pixel_format == DSC_PIXFMT_RGB ? 1 : 0; + dsc_reg_vals->pps.native_422 = (dsc_reg_vals->pixel_format == DSC_PIXFMT_NATIVE_YCBCR422); + dsc_reg_vals->pps.native_420 = (dsc_reg_vals->pixel_format == DSC_PIXFMT_NATIVE_YCBCR420); + dsc_reg_vals->pps.simple_422 = (dsc_reg_vals->pixel_format == DSC_PIXFMT_SIMPLE_YCBCR422); + + calc_rc_params(&rc, &dsc_reg_vals->pps); + + if (dsc_cfg->dc_dsc_cfg.rc_params_ovrd) + dsc_override_rc_params(&rc, dsc_cfg->dc_dsc_cfg.rc_params_ovrd); + + if (dscc_compute_dsc_parameters(&dsc_reg_vals->pps, &rc, &dsc_params)) { + dm_output_to_console("%s: DSC config failed\n", __func__); + return false; + } + + dsc_update_from_dsc_parameters(dsc_reg_vals, &dsc_params); + + dsc_optc_cfg->bytes_per_pixel = dsc_params.bytes_per_pixel; + dsc_optc_cfg->slice_width = dsc_reg_vals->pps.slice_width; + dsc_optc_cfg->is_pixel_format_444 = dsc_reg_vals->pixel_format == DSC_PIXFMT_RGB || + dsc_reg_vals->pixel_format == DSC_PIXFMT_YCBCR444 || + dsc_reg_vals->pixel_format == DSC_PIXFMT_SIMPLE_YCBCR422; + + return true; +} + + +enum dsc_pixel_format dsc_dc_pixel_encoding_to_dsc_pixel_format(enum dc_pixel_encoding dc_pix_enc, bool is_ycbcr422_simple) +{ + enum dsc_pixel_format dsc_pix_fmt = DSC_PIXFMT_UNKNOWN; + + /* NOTE: We don't support DSC_PIXFMT_SIMPLE_YCBCR422 */ + + switch (dc_pix_enc) { + case PIXEL_ENCODING_RGB: + dsc_pix_fmt = DSC_PIXFMT_RGB; + break; + case PIXEL_ENCODING_YCBCR422: + if (is_ycbcr422_simple) + dsc_pix_fmt = DSC_PIXFMT_SIMPLE_YCBCR422; + else + dsc_pix_fmt = DSC_PIXFMT_NATIVE_YCBCR422; + break; + case PIXEL_ENCODING_YCBCR444: + dsc_pix_fmt = DSC_PIXFMT_YCBCR444; + break; + case PIXEL_ENCODING_YCBCR420: + dsc_pix_fmt = DSC_PIXFMT_NATIVE_YCBCR420; + break; + default: + dsc_pix_fmt = DSC_PIXFMT_UNKNOWN; + break; + } + + ASSERT(dsc_pix_fmt != DSC_PIXFMT_UNKNOWN); + return dsc_pix_fmt; +} + + +enum dsc_bits_per_comp dsc_dc_color_depth_to_dsc_bits_per_comp(enum dc_color_depth dc_color_depth) +{ + enum dsc_bits_per_comp bpc = DSC_BPC_UNKNOWN; + + switch (dc_color_depth) { + case COLOR_DEPTH_888: + bpc = DSC_BPC_8; + break; + case COLOR_DEPTH_101010: + bpc = DSC_BPC_10; + break; + case COLOR_DEPTH_121212: + bpc = DSC_BPC_12; + break; + default: + bpc = DSC_BPC_UNKNOWN; + break; + } + + return bpc; +} + + +void dsc_init_reg_values(struct dsc_reg_values *reg_vals) +{ + int i; + + memset(reg_vals, 0, sizeof(struct dsc_reg_values)); + + /* Non-PPS values */ + reg_vals->dsc_clock_enable = 1; + reg_vals->dsc_clock_gating_disable = 0; + reg_vals->underflow_recovery_en = 0; + reg_vals->underflow_occurred_int_en = 0; + reg_vals->underflow_occurred_status = 0; + reg_vals->ich_reset_at_eol = 0; + reg_vals->alternate_ich_encoding_en = 0; + reg_vals->rc_buffer_model_size = 0; + /*reg_vals->disable_ich = 0;*/ + reg_vals->dsc_dbg_en = 0; + + for (i = 0; i < 4; i++) + reg_vals->rc_buffer_model_overflow_int_en[i] = 0; + + /* PPS values */ + reg_vals->pps.dsc_version_minor = 2; + reg_vals->pps.dsc_version_major = 1; + reg_vals->pps.line_buf_depth = 9; + reg_vals->pps.bits_per_component = 8; + reg_vals->pps.block_pred_enable = 1; + reg_vals->pps.slice_chunk_size = 0; + reg_vals->pps.pic_width = 0; + reg_vals->pps.pic_height = 0; + reg_vals->pps.slice_width = 0; + reg_vals->pps.slice_height = 0; + reg_vals->pps.initial_xmit_delay = 170; + reg_vals->pps.initial_dec_delay = 0; + reg_vals->pps.initial_scale_value = 0; + reg_vals->pps.scale_increment_interval = 0; + reg_vals->pps.scale_decrement_interval = 0; + reg_vals->pps.nfl_bpg_offset = 0; + reg_vals->pps.slice_bpg_offset = 0; + reg_vals->pps.nsl_bpg_offset = 0; + reg_vals->pps.initial_offset = 6144; + reg_vals->pps.final_offset = 0; + reg_vals->pps.flatness_min_qp = 3; + reg_vals->pps.flatness_max_qp = 12; + reg_vals->pps.rc_model_size = 8192; + reg_vals->pps.rc_edge_factor = 6; + reg_vals->pps.rc_quant_incr_limit0 = 11; + reg_vals->pps.rc_quant_incr_limit1 = 11; + reg_vals->pps.rc_tgt_offset_low = 3; + reg_vals->pps.rc_tgt_offset_high = 3; +} + +/* Updates dsc_reg_values::reg_vals::xxx fields based on the values from computed params. + * This is required because dscc_compute_dsc_parameters returns a modified PPS, which in turn + * affects non-PPS register values. + */ +void dsc_update_from_dsc_parameters(struct dsc_reg_values *reg_vals, const struct dsc_parameters *dsc_params) +{ + int i; + + reg_vals->pps = dsc_params->pps; + + // pps_computed will have the "expanded" values; need to shift them to make them fit for regs. + for (i = 0; i < NUM_BUF_RANGES - 1; i++) + reg_vals->pps.rc_buf_thresh[i] = reg_vals->pps.rc_buf_thresh[i] >> 6; + + reg_vals->rc_buffer_model_size = dsc_params->rc_buffer_model_size; +} + +static void dsc_write_to_registers(struct display_stream_compressor *dsc, const struct dsc_reg_values *reg_vals) +{ + uint32_t temp_int; + struct dcn20_dsc *dsc20 = TO_DCN20_DSC(dsc); + + REG_SET(DSC_DEBUG_CONTROL, 0, + DSC_DBG_EN, reg_vals->dsc_dbg_en); + + // dsccif registers + REG_SET_5(DSCCIF_CONFIG0, 0, + INPUT_INTERFACE_UNDERFLOW_RECOVERY_EN, reg_vals->underflow_recovery_en, + INPUT_INTERFACE_UNDERFLOW_OCCURRED_INT_EN, reg_vals->underflow_occurred_int_en, + INPUT_INTERFACE_UNDERFLOW_OCCURRED_STATUS, reg_vals->underflow_occurred_status, + INPUT_PIXEL_FORMAT, reg_vals->pixel_format, + DSCCIF_CONFIG0__BITS_PER_COMPONENT, reg_vals->pps.bits_per_component); + + REG_SET_2(DSCCIF_CONFIG1, 0, + PIC_WIDTH, reg_vals->pps.pic_width, + PIC_HEIGHT, reg_vals->pps.pic_height); + + // dscc registers + if (dsc20->dsc_mask->ICH_RESET_AT_END_OF_LINE == 0) { + REG_SET_3(DSCC_CONFIG0, 0, + NUMBER_OF_SLICES_PER_LINE, reg_vals->num_slices_h - 1, + ALTERNATE_ICH_ENCODING_EN, reg_vals->alternate_ich_encoding_en, + NUMBER_OF_SLICES_IN_VERTICAL_DIRECTION, reg_vals->num_slices_v - 1); + } else { + REG_SET_4(DSCC_CONFIG0, 0, ICH_RESET_AT_END_OF_LINE, + reg_vals->ich_reset_at_eol, NUMBER_OF_SLICES_PER_LINE, + reg_vals->num_slices_h - 1, ALTERNATE_ICH_ENCODING_EN, + reg_vals->alternate_ich_encoding_en, NUMBER_OF_SLICES_IN_VERTICAL_DIRECTION, + reg_vals->num_slices_v - 1); + } + + REG_SET(DSCC_CONFIG1, 0, + DSCC_RATE_CONTROL_BUFFER_MODEL_SIZE, reg_vals->rc_buffer_model_size); + /*REG_SET_2(DSCC_CONFIG1, 0, + DSCC_RATE_CONTROL_BUFFER_MODEL_SIZE, reg_vals->rc_buffer_model_size, + DSCC_DISABLE_ICH, reg_vals->disable_ich);*/ + + REG_SET_4(DSCC_INTERRUPT_CONTROL_STATUS, 0, + DSCC_RATE_CONTROL_BUFFER_MODEL0_OVERFLOW_OCCURRED_INT_EN, reg_vals->rc_buffer_model_overflow_int_en[0], + DSCC_RATE_CONTROL_BUFFER_MODEL1_OVERFLOW_OCCURRED_INT_EN, reg_vals->rc_buffer_model_overflow_int_en[1], + DSCC_RATE_CONTROL_BUFFER_MODEL2_OVERFLOW_OCCURRED_INT_EN, reg_vals->rc_buffer_model_overflow_int_en[2], + DSCC_RATE_CONTROL_BUFFER_MODEL3_OVERFLOW_OCCURRED_INT_EN, reg_vals->rc_buffer_model_overflow_int_en[3]); + + REG_SET_3(DSCC_PPS_CONFIG0, 0, + DSC_VERSION_MINOR, reg_vals->pps.dsc_version_minor, + LINEBUF_DEPTH, reg_vals->pps.line_buf_depth, + DSCC_PPS_CONFIG0__BITS_PER_COMPONENT, reg_vals->pps.bits_per_component); + + if (reg_vals->pixel_format == DSC_PIXFMT_NATIVE_YCBCR420 || reg_vals->pixel_format == DSC_PIXFMT_NATIVE_YCBCR422) + temp_int = reg_vals->bpp_x32; + else + temp_int = reg_vals->bpp_x32 >> 1; + + REG_SET_7(DSCC_PPS_CONFIG1, 0, + BITS_PER_PIXEL, temp_int, + SIMPLE_422, reg_vals->pixel_format == DSC_PIXFMT_SIMPLE_YCBCR422, + CONVERT_RGB, reg_vals->pixel_format == DSC_PIXFMT_RGB, + BLOCK_PRED_ENABLE, reg_vals->pps.block_pred_enable, + NATIVE_422, reg_vals->pixel_format == DSC_PIXFMT_NATIVE_YCBCR422, + NATIVE_420, reg_vals->pixel_format == DSC_PIXFMT_NATIVE_YCBCR420, + CHUNK_SIZE, reg_vals->pps.slice_chunk_size); + + REG_SET_2(DSCC_PPS_CONFIG2, 0, + PIC_WIDTH, reg_vals->pps.pic_width, + PIC_HEIGHT, reg_vals->pps.pic_height); + + REG_SET_2(DSCC_PPS_CONFIG3, 0, + SLICE_WIDTH, reg_vals->pps.slice_width, + SLICE_HEIGHT, reg_vals->pps.slice_height); + + REG_SET(DSCC_PPS_CONFIG4, 0, + INITIAL_XMIT_DELAY, reg_vals->pps.initial_xmit_delay); + + REG_SET_2(DSCC_PPS_CONFIG5, 0, + INITIAL_SCALE_VALUE, reg_vals->pps.initial_scale_value, + SCALE_INCREMENT_INTERVAL, reg_vals->pps.scale_increment_interval); + + REG_SET_3(DSCC_PPS_CONFIG6, 0, + SCALE_DECREMENT_INTERVAL, reg_vals->pps.scale_decrement_interval, + FIRST_LINE_BPG_OFFSET, reg_vals->pps.first_line_bpg_offset, + SECOND_LINE_BPG_OFFSET, reg_vals->pps.second_line_bpg_offset); + + REG_SET_2(DSCC_PPS_CONFIG7, 0, + NFL_BPG_OFFSET, reg_vals->pps.nfl_bpg_offset, + SLICE_BPG_OFFSET, reg_vals->pps.slice_bpg_offset); + + REG_SET_2(DSCC_PPS_CONFIG8, 0, + NSL_BPG_OFFSET, reg_vals->pps.nsl_bpg_offset, + SECOND_LINE_OFFSET_ADJ, reg_vals->pps.second_line_offset_adj); + + REG_SET_2(DSCC_PPS_CONFIG9, 0, + INITIAL_OFFSET, reg_vals->pps.initial_offset, + FINAL_OFFSET, reg_vals->pps.final_offset); + + REG_SET_3(DSCC_PPS_CONFIG10, 0, + FLATNESS_MIN_QP, reg_vals->pps.flatness_min_qp, + FLATNESS_MAX_QP, reg_vals->pps.flatness_max_qp, + RC_MODEL_SIZE, reg_vals->pps.rc_model_size); + + REG_SET_5(DSCC_PPS_CONFIG11, 0, + RC_EDGE_FACTOR, reg_vals->pps.rc_edge_factor, + RC_QUANT_INCR_LIMIT0, reg_vals->pps.rc_quant_incr_limit0, + RC_QUANT_INCR_LIMIT1, reg_vals->pps.rc_quant_incr_limit1, + RC_TGT_OFFSET_LO, reg_vals->pps.rc_tgt_offset_low, + RC_TGT_OFFSET_HI, reg_vals->pps.rc_tgt_offset_high); + + REG_SET_4(DSCC_PPS_CONFIG12, 0, + RC_BUF_THRESH0, reg_vals->pps.rc_buf_thresh[0], + RC_BUF_THRESH1, reg_vals->pps.rc_buf_thresh[1], + RC_BUF_THRESH2, reg_vals->pps.rc_buf_thresh[2], + RC_BUF_THRESH3, reg_vals->pps.rc_buf_thresh[3]); + + REG_SET_4(DSCC_PPS_CONFIG13, 0, + RC_BUF_THRESH4, reg_vals->pps.rc_buf_thresh[4], + RC_BUF_THRESH5, reg_vals->pps.rc_buf_thresh[5], + RC_BUF_THRESH6, reg_vals->pps.rc_buf_thresh[6], + RC_BUF_THRESH7, reg_vals->pps.rc_buf_thresh[7]); + + REG_SET_4(DSCC_PPS_CONFIG14, 0, + RC_BUF_THRESH8, reg_vals->pps.rc_buf_thresh[8], + RC_BUF_THRESH9, reg_vals->pps.rc_buf_thresh[9], + RC_BUF_THRESH10, reg_vals->pps.rc_buf_thresh[10], + RC_BUF_THRESH11, reg_vals->pps.rc_buf_thresh[11]); + + REG_SET_5(DSCC_PPS_CONFIG15, 0, + RC_BUF_THRESH12, reg_vals->pps.rc_buf_thresh[12], + RC_BUF_THRESH13, reg_vals->pps.rc_buf_thresh[13], + RANGE_MIN_QP0, reg_vals->pps.rc_range_params[0].range_min_qp, + RANGE_MAX_QP0, reg_vals->pps.rc_range_params[0].range_max_qp, + RANGE_BPG_OFFSET0, reg_vals->pps.rc_range_params[0].range_bpg_offset); + + REG_SET_6(DSCC_PPS_CONFIG16, 0, + RANGE_MIN_QP1, reg_vals->pps.rc_range_params[1].range_min_qp, + RANGE_MAX_QP1, reg_vals->pps.rc_range_params[1].range_max_qp, + RANGE_BPG_OFFSET1, reg_vals->pps.rc_range_params[1].range_bpg_offset, + RANGE_MIN_QP2, reg_vals->pps.rc_range_params[2].range_min_qp, + RANGE_MAX_QP2, reg_vals->pps.rc_range_params[2].range_max_qp, + RANGE_BPG_OFFSET2, reg_vals->pps.rc_range_params[2].range_bpg_offset); + + REG_SET_6(DSCC_PPS_CONFIG17, 0, + RANGE_MIN_QP3, reg_vals->pps.rc_range_params[3].range_min_qp, + RANGE_MAX_QP3, reg_vals->pps.rc_range_params[3].range_max_qp, + RANGE_BPG_OFFSET3, reg_vals->pps.rc_range_params[3].range_bpg_offset, + RANGE_MIN_QP4, reg_vals->pps.rc_range_params[4].range_min_qp, + RANGE_MAX_QP4, reg_vals->pps.rc_range_params[4].range_max_qp, + RANGE_BPG_OFFSET4, reg_vals->pps.rc_range_params[4].range_bpg_offset); + + REG_SET_6(DSCC_PPS_CONFIG18, 0, + RANGE_MIN_QP5, reg_vals->pps.rc_range_params[5].range_min_qp, + RANGE_MAX_QP5, reg_vals->pps.rc_range_params[5].range_max_qp, + RANGE_BPG_OFFSET5, reg_vals->pps.rc_range_params[5].range_bpg_offset, + RANGE_MIN_QP6, reg_vals->pps.rc_range_params[6].range_min_qp, + RANGE_MAX_QP6, reg_vals->pps.rc_range_params[6].range_max_qp, + RANGE_BPG_OFFSET6, reg_vals->pps.rc_range_params[6].range_bpg_offset); + + REG_SET_6(DSCC_PPS_CONFIG19, 0, + RANGE_MIN_QP7, reg_vals->pps.rc_range_params[7].range_min_qp, + RANGE_MAX_QP7, reg_vals->pps.rc_range_params[7].range_max_qp, + RANGE_BPG_OFFSET7, reg_vals->pps.rc_range_params[7].range_bpg_offset, + RANGE_MIN_QP8, reg_vals->pps.rc_range_params[8].range_min_qp, + RANGE_MAX_QP8, reg_vals->pps.rc_range_params[8].range_max_qp, + RANGE_BPG_OFFSET8, reg_vals->pps.rc_range_params[8].range_bpg_offset); + + REG_SET_6(DSCC_PPS_CONFIG20, 0, + RANGE_MIN_QP9, reg_vals->pps.rc_range_params[9].range_min_qp, + RANGE_MAX_QP9, reg_vals->pps.rc_range_params[9].range_max_qp, + RANGE_BPG_OFFSET9, reg_vals->pps.rc_range_params[9].range_bpg_offset, + RANGE_MIN_QP10, reg_vals->pps.rc_range_params[10].range_min_qp, + RANGE_MAX_QP10, reg_vals->pps.rc_range_params[10].range_max_qp, + RANGE_BPG_OFFSET10, reg_vals->pps.rc_range_params[10].range_bpg_offset); + + REG_SET_6(DSCC_PPS_CONFIG21, 0, + RANGE_MIN_QP11, reg_vals->pps.rc_range_params[11].range_min_qp, + RANGE_MAX_QP11, reg_vals->pps.rc_range_params[11].range_max_qp, + RANGE_BPG_OFFSET11, reg_vals->pps.rc_range_params[11].range_bpg_offset, + RANGE_MIN_QP12, reg_vals->pps.rc_range_params[12].range_min_qp, + RANGE_MAX_QP12, reg_vals->pps.rc_range_params[12].range_max_qp, + RANGE_BPG_OFFSET12, reg_vals->pps.rc_range_params[12].range_bpg_offset); + + REG_SET_6(DSCC_PPS_CONFIG22, 0, + RANGE_MIN_QP13, reg_vals->pps.rc_range_params[13].range_min_qp, + RANGE_MAX_QP13, reg_vals->pps.rc_range_params[13].range_max_qp, + RANGE_BPG_OFFSET13, reg_vals->pps.rc_range_params[13].range_bpg_offset, + RANGE_MIN_QP14, reg_vals->pps.rc_range_params[14].range_min_qp, + RANGE_MAX_QP14, reg_vals->pps.rc_range_params[14].range_max_qp, + RANGE_BPG_OFFSET14, reg_vals->pps.rc_range_params[14].range_bpg_offset); + +} + diff --git a/drivers/gpu/drm/amd/display/dc/dsc/dcn20/dcn20_dsc.h b/drivers/gpu/drm/amd/display/dc/dsc/dcn20/dcn20_dsc.h new file mode 100644 index 000000000000..ba869387c3c5 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/dsc/dcn20/dcn20_dsc.h @@ -0,0 +1,589 @@ +/* Copyright 2017 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 __DCN20_DSC_H__ +#define __DCN20_DSC_H__ + +#include "dsc.h" +#include "dsc/dscc_types.h" +#include + +#define TO_DCN20_DSC(dsc)\ + container_of(dsc, struct dcn20_dsc, base) + +#define DSC_REG_LIST_DCN20(id) \ + SRI(DSC_TOP_CONTROL, DSC_TOP, id),\ + SRI(DSC_DEBUG_CONTROL, DSC_TOP, id),\ + SRI(DSCC_CONFIG0, DSCC, id),\ + SRI(DSCC_CONFIG1, DSCC, id),\ + SRI(DSCC_STATUS, DSCC, id),\ + SRI(DSCC_INTERRUPT_CONTROL_STATUS, DSCC, id),\ + SRI(DSCC_PPS_CONFIG0, DSCC, id),\ + SRI(DSCC_PPS_CONFIG1, DSCC, id),\ + SRI(DSCC_PPS_CONFIG2, DSCC, id),\ + SRI(DSCC_PPS_CONFIG3, DSCC, id),\ + SRI(DSCC_PPS_CONFIG4, DSCC, id),\ + SRI(DSCC_PPS_CONFIG5, DSCC, id),\ + SRI(DSCC_PPS_CONFIG6, DSCC, id),\ + SRI(DSCC_PPS_CONFIG7, DSCC, id),\ + SRI(DSCC_PPS_CONFIG8, DSCC, id),\ + SRI(DSCC_PPS_CONFIG9, DSCC, id),\ + SRI(DSCC_PPS_CONFIG10, DSCC, id),\ + SRI(DSCC_PPS_CONFIG11, DSCC, id),\ + SRI(DSCC_PPS_CONFIG12, DSCC, id),\ + SRI(DSCC_PPS_CONFIG13, DSCC, id),\ + SRI(DSCC_PPS_CONFIG14, DSCC, id),\ + SRI(DSCC_PPS_CONFIG15, DSCC, id),\ + SRI(DSCC_PPS_CONFIG16, DSCC, id),\ + SRI(DSCC_PPS_CONFIG17, DSCC, id),\ + SRI(DSCC_PPS_CONFIG18, DSCC, id),\ + SRI(DSCC_PPS_CONFIG19, DSCC, id),\ + SRI(DSCC_PPS_CONFIG20, DSCC, id),\ + SRI(DSCC_PPS_CONFIG21, DSCC, id),\ + SRI(DSCC_PPS_CONFIG22, DSCC, id),\ + SRI(DSCC_MEM_POWER_CONTROL, DSCC, id),\ + SRI(DSCC_R_Y_SQUARED_ERROR_LOWER, DSCC, id),\ + SRI(DSCC_R_Y_SQUARED_ERROR_UPPER, DSCC, id),\ + SRI(DSCC_G_CB_SQUARED_ERROR_LOWER, DSCC, id),\ + SRI(DSCC_G_CB_SQUARED_ERROR_UPPER, DSCC, id),\ + SRI(DSCC_B_CR_SQUARED_ERROR_LOWER, DSCC, id),\ + SRI(DSCC_B_CR_SQUARED_ERROR_UPPER, DSCC, id),\ + SRI(DSCC_MAX_ABS_ERROR0, DSCC, id),\ + SRI(DSCC_MAX_ABS_ERROR1, DSCC, id),\ + SRI(DSCC_RATE_BUFFER0_MAX_FULLNESS_LEVEL, DSCC, id),\ + SRI(DSCC_RATE_BUFFER1_MAX_FULLNESS_LEVEL, DSCC, id),\ + SRI(DSCC_RATE_BUFFER2_MAX_FULLNESS_LEVEL, DSCC, id),\ + SRI(DSCC_RATE_BUFFER3_MAX_FULLNESS_LEVEL, DSCC, id),\ + SRI(DSCC_RATE_CONTROL_BUFFER0_MAX_FULLNESS_LEVEL, DSCC, id),\ + SRI(DSCC_RATE_CONTROL_BUFFER1_MAX_FULLNESS_LEVEL, DSCC, id),\ + SRI(DSCC_RATE_CONTROL_BUFFER2_MAX_FULLNESS_LEVEL, DSCC, id),\ + SRI(DSCC_RATE_CONTROL_BUFFER3_MAX_FULLNESS_LEVEL, DSCC, id),\ + SRI(DSCCIF_CONFIG0, DSCCIF, id),\ + SRI(DSCCIF_CONFIG1, DSCCIF, id),\ + SRI(DSCRM_DSC_FORWARD_CONFIG, DSCRM, id) + + +#define DSC_SF(reg_name, field_name, post_fix)\ + .field_name = reg_name ## __ ## field_name ## post_fix + +//Used in resolving the corner case with duplicate field name +#define DSC2_SF(reg_name, field_name, post_fix)\ + .field_name = reg_name ## _ ## field_name ## post_fix + +#define DSC_REG_LIST_SH_MASK_DCN20(mask_sh)\ + DSC_SF(DSC_TOP0_DSC_TOP_CONTROL, DSC_CLOCK_EN, mask_sh), \ + DSC_SF(DSC_TOP0_DSC_TOP_CONTROL, DSC_DISPCLK_R_GATE_DIS, mask_sh), \ + DSC_SF(DSC_TOP0_DSC_TOP_CONTROL, DSC_DSCCLK_R_GATE_DIS, mask_sh), \ + DSC_SF(DSC_TOP0_DSC_DEBUG_CONTROL, DSC_DBG_EN, mask_sh), \ + DSC_SF(DSCC0_DSCC_CONFIG0, ICH_RESET_AT_END_OF_LINE, mask_sh), \ + DSC_SF(DSCC0_DSCC_CONFIG0, NUMBER_OF_SLICES_PER_LINE, mask_sh), \ + DSC_SF(DSCC0_DSCC_CONFIG0, ALTERNATE_ICH_ENCODING_EN, mask_sh), \ + DSC_SF(DSCC0_DSCC_CONFIG0, NUMBER_OF_SLICES_IN_VERTICAL_DIRECTION, mask_sh), \ + DSC_SF(DSCC0_DSCC_CONFIG1, DSCC_RATE_CONTROL_BUFFER_MODEL_SIZE, mask_sh), \ + /*DSC_SF(DSCC0_DSCC_CONFIG1, DSCC_DISABLE_ICH, mask_sh),*/ \ + DSC_SF(DSCC0_DSCC_STATUS, DSCC_DOUBLE_BUFFER_REG_UPDATE_PENDING, mask_sh), \ + DSC_SF(DSCC0_DSCC_INTERRUPT_CONTROL_STATUS, DSCC_RATE_BUFFER0_OVERFLOW_OCCURRED, mask_sh), \ + DSC_SF(DSCC0_DSCC_INTERRUPT_CONTROL_STATUS, DSCC_RATE_BUFFER1_OVERFLOW_OCCURRED, mask_sh), \ + DSC_SF(DSCC0_DSCC_INTERRUPT_CONTROL_STATUS, DSCC_RATE_BUFFER2_OVERFLOW_OCCURRED, mask_sh), \ + DSC_SF(DSCC0_DSCC_INTERRUPT_CONTROL_STATUS, DSCC_RATE_BUFFER3_OVERFLOW_OCCURRED, mask_sh), \ + DSC_SF(DSCC0_DSCC_INTERRUPT_CONTROL_STATUS, DSCC_RATE_BUFFER0_UNDERFLOW_OCCURRED, mask_sh), \ + DSC_SF(DSCC0_DSCC_INTERRUPT_CONTROL_STATUS, DSCC_RATE_BUFFER1_UNDERFLOW_OCCURRED, mask_sh), \ + DSC_SF(DSCC0_DSCC_INTERRUPT_CONTROL_STATUS, DSCC_RATE_BUFFER2_UNDERFLOW_OCCURRED, mask_sh), \ + DSC_SF(DSCC0_DSCC_INTERRUPT_CONTROL_STATUS, DSCC_RATE_BUFFER3_UNDERFLOW_OCCURRED, mask_sh), \ + DSC_SF(DSCC0_DSCC_INTERRUPT_CONTROL_STATUS, DSCC_RATE_CONTROL_BUFFER_MODEL0_OVERFLOW_OCCURRED, mask_sh), \ + DSC_SF(DSCC0_DSCC_INTERRUPT_CONTROL_STATUS, DSCC_RATE_CONTROL_BUFFER_MODEL1_OVERFLOW_OCCURRED, mask_sh), \ + DSC_SF(DSCC0_DSCC_INTERRUPT_CONTROL_STATUS, DSCC_RATE_CONTROL_BUFFER_MODEL2_OVERFLOW_OCCURRED, mask_sh), \ + DSC_SF(DSCC0_DSCC_INTERRUPT_CONTROL_STATUS, DSCC_RATE_CONTROL_BUFFER_MODEL3_OVERFLOW_OCCURRED, mask_sh), \ + DSC_SF(DSCC0_DSCC_INTERRUPT_CONTROL_STATUS, DSCC_RATE_BUFFER0_OVERFLOW_OCCURRED_INT_EN, mask_sh), \ + DSC_SF(DSCC0_DSCC_INTERRUPT_CONTROL_STATUS, DSCC_RATE_BUFFER1_OVERFLOW_OCCURRED_INT_EN, mask_sh), \ + DSC_SF(DSCC0_DSCC_INTERRUPT_CONTROL_STATUS, DSCC_RATE_BUFFER2_OVERFLOW_OCCURRED_INT_EN, mask_sh), \ + DSC_SF(DSCC0_DSCC_INTERRUPT_CONTROL_STATUS, DSCC_RATE_BUFFER3_OVERFLOW_OCCURRED_INT_EN, mask_sh), \ + DSC_SF(DSCC0_DSCC_INTERRUPT_CONTROL_STATUS, DSCC_RATE_BUFFER0_UNDERFLOW_OCCURRED_INT_EN, mask_sh), \ + DSC_SF(DSCC0_DSCC_INTERRUPT_CONTROL_STATUS, DSCC_RATE_BUFFER1_UNDERFLOW_OCCURRED_INT_EN, mask_sh), \ + DSC_SF(DSCC0_DSCC_INTERRUPT_CONTROL_STATUS, DSCC_RATE_BUFFER2_UNDERFLOW_OCCURRED_INT_EN, mask_sh), \ + DSC_SF(DSCC0_DSCC_INTERRUPT_CONTROL_STATUS, DSCC_RATE_BUFFER3_UNDERFLOW_OCCURRED_INT_EN, mask_sh), \ + DSC_SF(DSCC0_DSCC_INTERRUPT_CONTROL_STATUS, DSCC_RATE_CONTROL_BUFFER_MODEL0_OVERFLOW_OCCURRED_INT_EN, mask_sh), \ + DSC_SF(DSCC0_DSCC_INTERRUPT_CONTROL_STATUS, DSCC_RATE_CONTROL_BUFFER_MODEL1_OVERFLOW_OCCURRED_INT_EN, mask_sh), \ + DSC_SF(DSCC0_DSCC_INTERRUPT_CONTROL_STATUS, DSCC_RATE_CONTROL_BUFFER_MODEL2_OVERFLOW_OCCURRED_INT_EN, mask_sh), \ + DSC_SF(DSCC0_DSCC_INTERRUPT_CONTROL_STATUS, DSCC_RATE_CONTROL_BUFFER_MODEL3_OVERFLOW_OCCURRED_INT_EN, mask_sh), \ + DSC_SF(DSCC0_DSCC_PPS_CONFIG0, DSC_VERSION_MINOR, mask_sh), \ + DSC_SF(DSCC0_DSCC_PPS_CONFIG0, DSC_VERSION_MAJOR, mask_sh), \ + DSC_SF(DSCC0_DSCC_PPS_CONFIG0, PPS_IDENTIFIER, mask_sh), \ + DSC_SF(DSCC0_DSCC_PPS_CONFIG0, LINEBUF_DEPTH, mask_sh), \ + DSC2_SF(DSCC0, DSCC_PPS_CONFIG0__BITS_PER_COMPONENT, mask_sh), \ + DSC_SF(DSCC0_DSCC_PPS_CONFIG1, BITS_PER_PIXEL, mask_sh), \ + DSC_SF(DSCC0_DSCC_PPS_CONFIG1, VBR_ENABLE, mask_sh), \ + DSC_SF(DSCC0_DSCC_PPS_CONFIG1, SIMPLE_422, mask_sh), \ + DSC_SF(DSCC0_DSCC_PPS_CONFIG1, CONVERT_RGB, mask_sh), \ + DSC_SF(DSCC0_DSCC_PPS_CONFIG1, BLOCK_PRED_ENABLE, mask_sh), \ + DSC_SF(DSCC0_DSCC_PPS_CONFIG1, NATIVE_422, mask_sh), \ + DSC_SF(DSCC0_DSCC_PPS_CONFIG1, NATIVE_420, mask_sh), \ + DSC_SF(DSCC0_DSCC_PPS_CONFIG1, CHUNK_SIZE, mask_sh), \ + DSC_SF(DSCC0_DSCC_PPS_CONFIG2, PIC_WIDTH, mask_sh), \ + DSC_SF(DSCC0_DSCC_PPS_CONFIG2, PIC_HEIGHT, mask_sh), \ + DSC_SF(DSCC0_DSCC_PPS_CONFIG3, SLICE_WIDTH, mask_sh), \ + DSC_SF(DSCC0_DSCC_PPS_CONFIG3, SLICE_HEIGHT, mask_sh), \ + DSC_SF(DSCC0_DSCC_PPS_CONFIG4, INITIAL_XMIT_DELAY, mask_sh), \ + DSC_SF(DSCC0_DSCC_PPS_CONFIG4, INITIAL_DEC_DELAY, mask_sh), \ + DSC_SF(DSCC0_DSCC_PPS_CONFIG5, INITIAL_SCALE_VALUE, mask_sh), \ + DSC_SF(DSCC0_DSCC_PPS_CONFIG5, SCALE_INCREMENT_INTERVAL, mask_sh), \ + DSC_SF(DSCC0_DSCC_PPS_CONFIG6, SCALE_DECREMENT_INTERVAL, mask_sh), \ + DSC_SF(DSCC0_DSCC_PPS_CONFIG6, FIRST_LINE_BPG_OFFSET, mask_sh), \ + DSC_SF(DSCC0_DSCC_PPS_CONFIG6, SECOND_LINE_BPG_OFFSET, mask_sh), \ + DSC_SF(DSCC0_DSCC_PPS_CONFIG7, NFL_BPG_OFFSET, mask_sh), \ + DSC_SF(DSCC0_DSCC_PPS_CONFIG7, SLICE_BPG_OFFSET, mask_sh), \ + DSC_SF(DSCC0_DSCC_PPS_CONFIG8, NSL_BPG_OFFSET, mask_sh), \ + DSC_SF(DSCC0_DSCC_PPS_CONFIG8, SECOND_LINE_OFFSET_ADJ, mask_sh), \ + DSC_SF(DSCC0_DSCC_PPS_CONFIG9, INITIAL_OFFSET, mask_sh), \ + DSC_SF(DSCC0_DSCC_PPS_CONFIG9, FINAL_OFFSET, mask_sh), \ + DSC_SF(DSCC0_DSCC_PPS_CONFIG10, FLATNESS_MIN_QP, mask_sh), \ + DSC_SF(DSCC0_DSCC_PPS_CONFIG10, FLATNESS_MAX_QP, mask_sh), \ + DSC_SF(DSCC0_DSCC_PPS_CONFIG10, RC_MODEL_SIZE, mask_sh), \ + DSC_SF(DSCC0_DSCC_PPS_CONFIG11, RC_EDGE_FACTOR, mask_sh), \ + DSC_SF(DSCC0_DSCC_PPS_CONFIG11, RC_QUANT_INCR_LIMIT0, mask_sh), \ + DSC_SF(DSCC0_DSCC_PPS_CONFIG11, RC_QUANT_INCR_LIMIT1, mask_sh), \ + DSC_SF(DSCC0_DSCC_PPS_CONFIG11, RC_TGT_OFFSET_LO, mask_sh), \ + DSC_SF(DSCC0_DSCC_PPS_CONFIG11, RC_TGT_OFFSET_HI, mask_sh), \ + DSC_SF(DSCC0_DSCC_PPS_CONFIG12, RC_BUF_THRESH0, mask_sh), \ + DSC_SF(DSCC0_DSCC_PPS_CONFIG12, RC_BUF_THRESH1, mask_sh), \ + DSC_SF(DSCC0_DSCC_PPS_CONFIG12, RC_BUF_THRESH2, mask_sh), \ + DSC_SF(DSCC0_DSCC_PPS_CONFIG12, RC_BUF_THRESH3, mask_sh), \ + DSC_SF(DSCC0_DSCC_PPS_CONFIG13, RC_BUF_THRESH4, mask_sh), \ + DSC_SF(DSCC0_DSCC_PPS_CONFIG13, RC_BUF_THRESH5, mask_sh), \ + DSC_SF(DSCC0_DSCC_PPS_CONFIG13, RC_BUF_THRESH6, mask_sh), \ + DSC_SF(DSCC0_DSCC_PPS_CONFIG13, RC_BUF_THRESH7, mask_sh), \ + DSC_SF(DSCC0_DSCC_PPS_CONFIG14, RC_BUF_THRESH8, mask_sh), \ + DSC_SF(DSCC0_DSCC_PPS_CONFIG14, RC_BUF_THRESH9, mask_sh), \ + DSC_SF(DSCC0_DSCC_PPS_CONFIG14, RC_BUF_THRESH10, mask_sh), \ + DSC_SF(DSCC0_DSCC_PPS_CONFIG14, RC_BUF_THRESH11, mask_sh), \ + DSC_SF(DSCC0_DSCC_PPS_CONFIG15, RC_BUF_THRESH12, mask_sh), \ + DSC_SF(DSCC0_DSCC_PPS_CONFIG15, RC_BUF_THRESH13, mask_sh), \ + DSC_SF(DSCC0_DSCC_PPS_CONFIG15, RANGE_MIN_QP0, mask_sh), \ + DSC_SF(DSCC0_DSCC_PPS_CONFIG15, RANGE_MAX_QP0, mask_sh), \ + DSC_SF(DSCC0_DSCC_PPS_CONFIG15, RANGE_BPG_OFFSET0, mask_sh), \ + DSC_SF(DSCC0_DSCC_PPS_CONFIG16, RANGE_MIN_QP1, mask_sh), \ + DSC_SF(DSCC0_DSCC_PPS_CONFIG16, RANGE_MAX_QP1, mask_sh), \ + DSC_SF(DSCC0_DSCC_PPS_CONFIG16, RANGE_BPG_OFFSET1, mask_sh), \ + DSC_SF(DSCC0_DSCC_PPS_CONFIG16, RANGE_MIN_QP2, mask_sh), \ + DSC_SF(DSCC0_DSCC_PPS_CONFIG16, RANGE_MAX_QP2, mask_sh), \ + DSC_SF(DSCC0_DSCC_PPS_CONFIG16, RANGE_BPG_OFFSET2, mask_sh), \ + DSC_SF(DSCC0_DSCC_PPS_CONFIG17, RANGE_MIN_QP3, mask_sh), \ + DSC_SF(DSCC0_DSCC_PPS_CONFIG17, RANGE_MAX_QP3, mask_sh), \ + DSC_SF(DSCC0_DSCC_PPS_CONFIG17, RANGE_BPG_OFFSET3, mask_sh), \ + DSC_SF(DSCC0_DSCC_PPS_CONFIG17, RANGE_MIN_QP4, mask_sh), \ + DSC_SF(DSCC0_DSCC_PPS_CONFIG17, RANGE_MAX_QP4, mask_sh), \ + DSC_SF(DSCC0_DSCC_PPS_CONFIG17, RANGE_BPG_OFFSET4, mask_sh), \ + DSC_SF(DSCC0_DSCC_PPS_CONFIG18, RANGE_MIN_QP5, mask_sh), \ + DSC_SF(DSCC0_DSCC_PPS_CONFIG18, RANGE_MAX_QP5, mask_sh), \ + DSC_SF(DSCC0_DSCC_PPS_CONFIG18, RANGE_BPG_OFFSET5, mask_sh), \ + DSC_SF(DSCC0_DSCC_PPS_CONFIG18, RANGE_MIN_QP6, mask_sh), \ + DSC_SF(DSCC0_DSCC_PPS_CONFIG18, RANGE_MAX_QP6, mask_sh), \ + DSC_SF(DSCC0_DSCC_PPS_CONFIG18, RANGE_BPG_OFFSET6, mask_sh), \ + DSC_SF(DSCC0_DSCC_PPS_CONFIG19, RANGE_MIN_QP7, mask_sh), \ + DSC_SF(DSCC0_DSCC_PPS_CONFIG19, RANGE_MAX_QP7, mask_sh), \ + DSC_SF(DSCC0_DSCC_PPS_CONFIG19, RANGE_BPG_OFFSET7, mask_sh), \ + DSC_SF(DSCC0_DSCC_PPS_CONFIG19, RANGE_MIN_QP8, mask_sh), \ + DSC_SF(DSCC0_DSCC_PPS_CONFIG19, RANGE_MAX_QP8, mask_sh), \ + DSC_SF(DSCC0_DSCC_PPS_CONFIG19, RANGE_BPG_OFFSET8, mask_sh), \ + DSC_SF(DSCC0_DSCC_PPS_CONFIG20, RANGE_MIN_QP9, mask_sh), \ + DSC_SF(DSCC0_DSCC_PPS_CONFIG20, RANGE_MAX_QP9, mask_sh), \ + DSC_SF(DSCC0_DSCC_PPS_CONFIG20, RANGE_BPG_OFFSET9, mask_sh), \ + DSC_SF(DSCC0_DSCC_PPS_CONFIG20, RANGE_MIN_QP10, mask_sh), \ + DSC_SF(DSCC0_DSCC_PPS_CONFIG20, RANGE_MAX_QP10, mask_sh), \ + DSC_SF(DSCC0_DSCC_PPS_CONFIG20, RANGE_BPG_OFFSET10, mask_sh), \ + DSC_SF(DSCC0_DSCC_PPS_CONFIG21, RANGE_MIN_QP11, mask_sh), \ + DSC_SF(DSCC0_DSCC_PPS_CONFIG21, RANGE_MAX_QP11, mask_sh), \ + DSC_SF(DSCC0_DSCC_PPS_CONFIG21, RANGE_BPG_OFFSET11, mask_sh), \ + DSC_SF(DSCC0_DSCC_PPS_CONFIG21, RANGE_MIN_QP12, mask_sh), \ + DSC_SF(DSCC0_DSCC_PPS_CONFIG21, RANGE_MAX_QP12, mask_sh), \ + DSC_SF(DSCC0_DSCC_PPS_CONFIG21, RANGE_BPG_OFFSET12, mask_sh), \ + DSC_SF(DSCC0_DSCC_PPS_CONFIG22, RANGE_MIN_QP13, mask_sh), \ + DSC_SF(DSCC0_DSCC_PPS_CONFIG22, RANGE_MAX_QP13, mask_sh), \ + DSC_SF(DSCC0_DSCC_PPS_CONFIG22, RANGE_BPG_OFFSET13, mask_sh), \ + DSC_SF(DSCC0_DSCC_PPS_CONFIG22, RANGE_MIN_QP14, mask_sh), \ + DSC_SF(DSCC0_DSCC_PPS_CONFIG22, RANGE_MAX_QP14, mask_sh), \ + DSC_SF(DSCC0_DSCC_PPS_CONFIG22, RANGE_BPG_OFFSET14, mask_sh), \ + DSC_SF(DSCC0_DSCC_MEM_POWER_CONTROL, DSCC_DEFAULT_MEM_LOW_POWER_STATE, mask_sh), \ + DSC_SF(DSCC0_DSCC_MEM_POWER_CONTROL, DSCC_MEM_PWR_FORCE, mask_sh), \ + DSC_SF(DSCC0_DSCC_MEM_POWER_CONTROL, DSCC_MEM_PWR_DIS, mask_sh), \ + DSC_SF(DSCC0_DSCC_MEM_POWER_CONTROL, DSCC_MEM_PWR_STATE, mask_sh), \ + DSC_SF(DSCC0_DSCC_MEM_POWER_CONTROL, DSCC_NATIVE_422_MEM_PWR_FORCE, mask_sh), \ + DSC_SF(DSCC0_DSCC_MEM_POWER_CONTROL, DSCC_NATIVE_422_MEM_PWR_DIS, mask_sh), \ + DSC_SF(DSCC0_DSCC_MEM_POWER_CONTROL, DSCC_NATIVE_422_MEM_PWR_STATE, mask_sh), \ + DSC_SF(DSCC0_DSCC_R_Y_SQUARED_ERROR_LOWER, DSCC_R_Y_SQUARED_ERROR_LOWER, mask_sh), \ + DSC_SF(DSCC0_DSCC_R_Y_SQUARED_ERROR_UPPER, DSCC_R_Y_SQUARED_ERROR_UPPER, mask_sh), \ + DSC_SF(DSCC0_DSCC_G_CB_SQUARED_ERROR_LOWER, DSCC_G_CB_SQUARED_ERROR_LOWER, mask_sh), \ + DSC_SF(DSCC0_DSCC_G_CB_SQUARED_ERROR_UPPER, DSCC_G_CB_SQUARED_ERROR_UPPER, mask_sh), \ + DSC_SF(DSCC0_DSCC_B_CR_SQUARED_ERROR_LOWER, DSCC_B_CR_SQUARED_ERROR_LOWER, mask_sh), \ + DSC_SF(DSCC0_DSCC_B_CR_SQUARED_ERROR_UPPER, DSCC_B_CR_SQUARED_ERROR_UPPER, mask_sh), \ + DSC_SF(DSCC0_DSCC_MAX_ABS_ERROR0, DSCC_R_Y_MAX_ABS_ERROR, mask_sh), \ + DSC_SF(DSCC0_DSCC_MAX_ABS_ERROR0, DSCC_G_CB_MAX_ABS_ERROR, mask_sh), \ + DSC_SF(DSCC0_DSCC_MAX_ABS_ERROR1, DSCC_B_CR_MAX_ABS_ERROR, mask_sh), \ + DSC_SF(DSCC0_DSCC_RATE_BUFFER0_MAX_FULLNESS_LEVEL, DSCC_RATE_BUFFER0_MAX_FULLNESS_LEVEL, mask_sh), \ + DSC_SF(DSCC0_DSCC_RATE_BUFFER1_MAX_FULLNESS_LEVEL, DSCC_RATE_BUFFER1_MAX_FULLNESS_LEVEL, mask_sh), \ + DSC_SF(DSCC0_DSCC_RATE_BUFFER2_MAX_FULLNESS_LEVEL, DSCC_RATE_BUFFER2_MAX_FULLNESS_LEVEL, mask_sh), \ + DSC_SF(DSCC0_DSCC_RATE_BUFFER3_MAX_FULLNESS_LEVEL, DSCC_RATE_BUFFER3_MAX_FULLNESS_LEVEL, mask_sh), \ + DSC_SF(DSCC0_DSCC_RATE_CONTROL_BUFFER0_MAX_FULLNESS_LEVEL, DSCC_RATE_CONTROL_BUFFER0_MAX_FULLNESS_LEVEL, mask_sh), \ + DSC_SF(DSCC0_DSCC_RATE_CONTROL_BUFFER1_MAX_FULLNESS_LEVEL, DSCC_RATE_CONTROL_BUFFER1_MAX_FULLNESS_LEVEL, mask_sh), \ + DSC_SF(DSCC0_DSCC_RATE_CONTROL_BUFFER2_MAX_FULLNESS_LEVEL, DSCC_RATE_CONTROL_BUFFER2_MAX_FULLNESS_LEVEL, mask_sh), \ + DSC_SF(DSCC0_DSCC_RATE_CONTROL_BUFFER3_MAX_FULLNESS_LEVEL, DSCC_RATE_CONTROL_BUFFER3_MAX_FULLNESS_LEVEL, mask_sh), \ + DSC_SF(DSCCIF0_DSCCIF_CONFIG0, INPUT_INTERFACE_UNDERFLOW_RECOVERY_EN, mask_sh), \ + DSC_SF(DSCCIF0_DSCCIF_CONFIG0, INPUT_INTERFACE_UNDERFLOW_OCCURRED_INT_EN, mask_sh), \ + DSC_SF(DSCCIF0_DSCCIF_CONFIG0, INPUT_INTERFACE_UNDERFLOW_OCCURRED_STATUS, mask_sh), \ + DSC_SF(DSCCIF0_DSCCIF_CONFIG0, INPUT_PIXEL_FORMAT, mask_sh), \ + DSC2_SF(DSCCIF0, DSCCIF_CONFIG0__BITS_PER_COMPONENT, mask_sh), \ + DSC_SF(DSCCIF0_DSCCIF_CONFIG0, DOUBLE_BUFFER_REG_UPDATE_PENDING, mask_sh), \ + DSC_SF(DSCCIF0_DSCCIF_CONFIG1, PIC_WIDTH, mask_sh), \ + DSC_SF(DSCCIF0_DSCCIF_CONFIG1, PIC_HEIGHT, mask_sh), \ + DSC_SF(DSCRM0_DSCRM_DSC_FORWARD_CONFIG, DSCRM_DSC_FORWARD_EN, mask_sh), \ + DSC_SF(DSCRM0_DSCRM_DSC_FORWARD_CONFIG, DSCRM_DSC_OPP_PIPE_SOURCE, mask_sh) + + + +#define DSC_FIELD_LIST_DCN20(type)\ + type DSC_CLOCK_EN; \ + type DSC_DISPCLK_R_GATE_DIS; \ + type DSC_DSCCLK_R_GATE_DIS; \ + type DSC_DBG_EN; \ + type DSC_TEST_CLOCK_MUX_SEL; \ + type ICH_RESET_AT_END_OF_LINE; \ + type NUMBER_OF_SLICES_PER_LINE; \ + type ALTERNATE_ICH_ENCODING_EN; \ + type NUMBER_OF_SLICES_IN_VERTICAL_DIRECTION; \ + type DSCC_RATE_CONTROL_BUFFER_MODEL_SIZE; \ + /*type DSCC_DISABLE_ICH;*/ \ + type DSCC_DOUBLE_BUFFER_REG_UPDATE_PENDING; \ + type DSCC_RATE_BUFFER0_OVERFLOW_OCCURRED; \ + type DSCC_RATE_BUFFER1_OVERFLOW_OCCURRED; \ + type DSCC_RATE_BUFFER2_OVERFLOW_OCCURRED; \ + type DSCC_RATE_BUFFER3_OVERFLOW_OCCURRED; \ + type DSCC_RATE_BUFFER0_UNDERFLOW_OCCURRED; \ + type DSCC_RATE_BUFFER1_UNDERFLOW_OCCURRED; \ + type DSCC_RATE_BUFFER2_UNDERFLOW_OCCURRED; \ + type DSCC_RATE_BUFFER3_UNDERFLOW_OCCURRED; \ + type DSCC_RATE_CONTROL_BUFFER_MODEL0_OVERFLOW_OCCURRED; \ + type DSCC_RATE_CONTROL_BUFFER_MODEL1_OVERFLOW_OCCURRED; \ + type DSCC_RATE_CONTROL_BUFFER_MODEL2_OVERFLOW_OCCURRED; \ + type DSCC_RATE_CONTROL_BUFFER_MODEL3_OVERFLOW_OCCURRED; \ + type DSCC_RATE_BUFFER0_OVERFLOW_OCCURRED_INT_EN; \ + type DSCC_RATE_BUFFER1_OVERFLOW_OCCURRED_INT_EN; \ + type DSCC_RATE_BUFFER2_OVERFLOW_OCCURRED_INT_EN; \ + type DSCC_RATE_BUFFER3_OVERFLOW_OCCURRED_INT_EN; \ + type DSCC_RATE_BUFFER0_UNDERFLOW_OCCURRED_INT_EN; \ + type DSCC_RATE_BUFFER1_UNDERFLOW_OCCURRED_INT_EN; \ + type DSCC_RATE_BUFFER2_UNDERFLOW_OCCURRED_INT_EN; \ + type DSCC_RATE_BUFFER3_UNDERFLOW_OCCURRED_INT_EN; \ + type DSCC_RATE_CONTROL_BUFFER_MODEL0_OVERFLOW_OCCURRED_INT_EN; \ + type DSCC_RATE_CONTROL_BUFFER_MODEL1_OVERFLOW_OCCURRED_INT_EN; \ + type DSCC_RATE_CONTROL_BUFFER_MODEL2_OVERFLOW_OCCURRED_INT_EN; \ + type DSCC_RATE_CONTROL_BUFFER_MODEL3_OVERFLOW_OCCURRED_INT_EN; \ + type DSC_VERSION_MINOR; \ + type DSC_VERSION_MAJOR; \ + type PPS_IDENTIFIER; \ + type LINEBUF_DEPTH; \ + type DSCC_PPS_CONFIG0__BITS_PER_COMPONENT; \ + type BITS_PER_PIXEL; \ + type VBR_ENABLE; \ + type SIMPLE_422; \ + type CONVERT_RGB; \ + type BLOCK_PRED_ENABLE; \ + type NATIVE_422; \ + type NATIVE_420; \ + type CHUNK_SIZE; \ + type PIC_WIDTH; \ + type PIC_HEIGHT; \ + type SLICE_WIDTH; \ + type SLICE_HEIGHT; \ + type INITIAL_XMIT_DELAY; \ + type INITIAL_DEC_DELAY; \ + type INITIAL_SCALE_VALUE; \ + type SCALE_INCREMENT_INTERVAL; \ + type SCALE_DECREMENT_INTERVAL; \ + type FIRST_LINE_BPG_OFFSET; \ + type SECOND_LINE_BPG_OFFSET; \ + type NFL_BPG_OFFSET; \ + type SLICE_BPG_OFFSET; \ + type NSL_BPG_OFFSET; \ + type SECOND_LINE_OFFSET_ADJ; \ + type INITIAL_OFFSET; \ + type FINAL_OFFSET; \ + type FLATNESS_MIN_QP; \ + type FLATNESS_MAX_QP; \ + type RC_MODEL_SIZE; \ + type RC_EDGE_FACTOR; \ + type RC_QUANT_INCR_LIMIT0; \ + type RC_QUANT_INCR_LIMIT1; \ + type RC_TGT_OFFSET_LO; \ + type RC_TGT_OFFSET_HI; \ + type RC_BUF_THRESH0; \ + type RC_BUF_THRESH1; \ + type RC_BUF_THRESH2; \ + type RC_BUF_THRESH3; \ + type RC_BUF_THRESH4; \ + type RC_BUF_THRESH5; \ + type RC_BUF_THRESH6; \ + type RC_BUF_THRESH7; \ + type RC_BUF_THRESH8; \ + type RC_BUF_THRESH9; \ + type RC_BUF_THRESH10; \ + type RC_BUF_THRESH11; \ + type RC_BUF_THRESH12; \ + type RC_BUF_THRESH13; \ + type RANGE_MIN_QP0; \ + type RANGE_MAX_QP0; \ + type RANGE_BPG_OFFSET0; \ + type RANGE_MIN_QP1; \ + type RANGE_MAX_QP1; \ + type RANGE_BPG_OFFSET1; \ + type RANGE_MIN_QP2; \ + type RANGE_MAX_QP2; \ + type RANGE_BPG_OFFSET2; \ + type RANGE_MIN_QP3; \ + type RANGE_MAX_QP3; \ + type RANGE_BPG_OFFSET3; \ + type RANGE_MIN_QP4; \ + type RANGE_MAX_QP4; \ + type RANGE_BPG_OFFSET4; \ + type RANGE_MIN_QP5; \ + type RANGE_MAX_QP5; \ + type RANGE_BPG_OFFSET5; \ + type RANGE_MIN_QP6; \ + type RANGE_MAX_QP6; \ + type RANGE_BPG_OFFSET6; \ + type RANGE_MIN_QP7; \ + type RANGE_MAX_QP7; \ + type RANGE_BPG_OFFSET7; \ + type RANGE_MIN_QP8; \ + type RANGE_MAX_QP8; \ + type RANGE_BPG_OFFSET8; \ + type RANGE_MIN_QP9; \ + type RANGE_MAX_QP9; \ + type RANGE_BPG_OFFSET9; \ + type RANGE_MIN_QP10; \ + type RANGE_MAX_QP10; \ + type RANGE_BPG_OFFSET10; \ + type RANGE_MIN_QP11; \ + type RANGE_MAX_QP11; \ + type RANGE_BPG_OFFSET11; \ + type RANGE_MIN_QP12; \ + type RANGE_MAX_QP12; \ + type RANGE_BPG_OFFSET12; \ + type RANGE_MIN_QP13; \ + type RANGE_MAX_QP13; \ + type RANGE_BPG_OFFSET13; \ + type RANGE_MIN_QP14; \ + type RANGE_MAX_QP14; \ + type RANGE_BPG_OFFSET14; \ + type DSCC_DEFAULT_MEM_LOW_POWER_STATE; \ + type DSCC_MEM_PWR_FORCE; \ + type DSCC_MEM_PWR_DIS; \ + type DSCC_MEM_PWR_STATE; \ + type DSCC_NATIVE_422_MEM_PWR_FORCE; \ + type DSCC_NATIVE_422_MEM_PWR_DIS; \ + type DSCC_NATIVE_422_MEM_PWR_STATE; \ + type DSCC_R_Y_SQUARED_ERROR_LOWER; \ + type DSCC_R_Y_SQUARED_ERROR_UPPER; \ + type DSCC_G_CB_SQUARED_ERROR_LOWER; \ + type DSCC_G_CB_SQUARED_ERROR_UPPER; \ + type DSCC_B_CR_SQUARED_ERROR_LOWER; \ + type DSCC_B_CR_SQUARED_ERROR_UPPER; \ + type DSCC_R_Y_MAX_ABS_ERROR; \ + type DSCC_G_CB_MAX_ABS_ERROR; \ + type DSCC_B_CR_MAX_ABS_ERROR; \ + type DSCC_RATE_BUFFER0_MAX_FULLNESS_LEVEL; \ + type DSCC_RATE_BUFFER1_MAX_FULLNESS_LEVEL; \ + type DSCC_RATE_BUFFER2_MAX_FULLNESS_LEVEL; \ + type DSCC_RATE_BUFFER3_MAX_FULLNESS_LEVEL; \ + type DSCC_RATE_CONTROL_BUFFER0_MAX_FULLNESS_LEVEL; \ + type DSCC_RATE_CONTROL_BUFFER1_MAX_FULLNESS_LEVEL; \ + type DSCC_RATE_CONTROL_BUFFER2_MAX_FULLNESS_LEVEL; \ + type DSCC_RATE_CONTROL_BUFFER3_MAX_FULLNESS_LEVEL; \ + type DSCC_UPDATE_PENDING_STATUS; \ + type DSCC_UPDATE_TAKEN_STATUS; \ + type DSCC_UPDATE_TAKEN_ACK; \ + type DSCC_RATE_BUFFER0_FULLNESS_LEVEL; \ + type DSCC_RATE_BUFFER1_FULLNESS_LEVEL; \ + type DSCC_RATE_BUFFER2_FULLNESS_LEVEL; \ + type DSCC_RATE_BUFFER3_FULLNESS_LEVEL; \ + type DSCC_RATE_CONTROL_BUFFER0_FULLNESS_LEVEL; \ + type DSCC_RATE_CONTROL_BUFFER1_FULLNESS_LEVEL; \ + type DSCC_RATE_CONTROL_BUFFER2_FULLNESS_LEVEL; \ + type DSCC_RATE_CONTROL_BUFFER3_FULLNESS_LEVEL; \ + type DSCC_RATE_BUFFER0_INITIAL_XMIT_DELAY_REACHED; \ + type DSCC_RATE_BUFFER1_INITIAL_XMIT_DELAY_REACHED; \ + type DSCC_RATE_BUFFER2_INITIAL_XMIT_DELAY_REACHED; \ + type DSCC_RATE_BUFFER3_INITIAL_XMIT_DELAY_REACHED; \ + type INPUT_INTERFACE_UNDERFLOW_RECOVERY_EN; \ + type INPUT_INTERFACE_UNDERFLOW_OCCURRED_INT_EN; \ + type INPUT_INTERFACE_UNDERFLOW_OCCURRED_STATUS; \ + type INPUT_PIXEL_FORMAT; \ + type DSCCIF_CONFIG0__BITS_PER_COMPONENT; \ + type DOUBLE_BUFFER_REG_UPDATE_PENDING; \ + type DSCCIF_UPDATE_PENDING_STATUS; \ + type DSCCIF_UPDATE_TAKEN_STATUS; \ + type DSCCIF_UPDATE_TAKEN_ACK; \ + type DSCRM_DSC_FORWARD_EN; \ + type DSCRM_DSC_OPP_PIPE_SOURCE + +struct dcn20_dsc_registers { + uint32_t DSC_TOP_CONTROL; + uint32_t DSC_DEBUG_CONTROL; + uint32_t DSCC_CONFIG0; + uint32_t DSCC_CONFIG1; + uint32_t DSCC_STATUS; + uint32_t DSCC_INTERRUPT_CONTROL_STATUS; + uint32_t DSCC_PPS_CONFIG0; + uint32_t DSCC_PPS_CONFIG1; + uint32_t DSCC_PPS_CONFIG2; + uint32_t DSCC_PPS_CONFIG3; + uint32_t DSCC_PPS_CONFIG4; + uint32_t DSCC_PPS_CONFIG5; + uint32_t DSCC_PPS_CONFIG6; + uint32_t DSCC_PPS_CONFIG7; + uint32_t DSCC_PPS_CONFIG8; + uint32_t DSCC_PPS_CONFIG9; + uint32_t DSCC_PPS_CONFIG10; + uint32_t DSCC_PPS_CONFIG11; + uint32_t DSCC_PPS_CONFIG12; + uint32_t DSCC_PPS_CONFIG13; + uint32_t DSCC_PPS_CONFIG14; + uint32_t DSCC_PPS_CONFIG15; + uint32_t DSCC_PPS_CONFIG16; + uint32_t DSCC_PPS_CONFIG17; + uint32_t DSCC_PPS_CONFIG18; + uint32_t DSCC_PPS_CONFIG19; + uint32_t DSCC_PPS_CONFIG20; + uint32_t DSCC_PPS_CONFIG21; + uint32_t DSCC_PPS_CONFIG22; + uint32_t DSCC_MEM_POWER_CONTROL; + uint32_t DSCC_R_Y_SQUARED_ERROR_LOWER; + uint32_t DSCC_R_Y_SQUARED_ERROR_UPPER; + uint32_t DSCC_G_CB_SQUARED_ERROR_LOWER; + uint32_t DSCC_G_CB_SQUARED_ERROR_UPPER; + uint32_t DSCC_B_CR_SQUARED_ERROR_LOWER; + uint32_t DSCC_B_CR_SQUARED_ERROR_UPPER; + uint32_t DSCC_MAX_ABS_ERROR0; + uint32_t DSCC_MAX_ABS_ERROR1; + uint32_t DSCC_RATE_BUFFER0_MAX_FULLNESS_LEVEL; + uint32_t DSCC_RATE_BUFFER1_MAX_FULLNESS_LEVEL; + uint32_t DSCC_RATE_BUFFER2_MAX_FULLNESS_LEVEL; + uint32_t DSCC_RATE_BUFFER3_MAX_FULLNESS_LEVEL; + uint32_t DSCC_RATE_CONTROL_BUFFER0_MAX_FULLNESS_LEVEL; + uint32_t DSCC_RATE_CONTROL_BUFFER1_MAX_FULLNESS_LEVEL; + uint32_t DSCC_RATE_CONTROL_BUFFER2_MAX_FULLNESS_LEVEL; + uint32_t DSCC_RATE_CONTROL_BUFFER3_MAX_FULLNESS_LEVEL; + uint32_t DSCCIF_CONFIG0; + uint32_t DSCCIF_CONFIG1; + uint32_t DSCRM_DSC_FORWARD_CONFIG; +}; + + +struct dcn20_dsc_shift { + DSC_FIELD_LIST_DCN20(uint8_t); +}; + +struct dcn20_dsc_mask { + DSC_FIELD_LIST_DCN20(uint32_t); +}; + +/* DSCCIF_CONFIG.INPUT_PIXEL_FORMAT values */ +enum dsc_pixel_format { + DSC_PIXFMT_RGB, + DSC_PIXFMT_YCBCR444, + DSC_PIXFMT_SIMPLE_YCBCR422, + DSC_PIXFMT_NATIVE_YCBCR422, + DSC_PIXFMT_NATIVE_YCBCR420, + DSC_PIXFMT_UNKNOWN +}; + +struct dsc_reg_values { + /* PPS registers */ + struct drm_dsc_config pps; + + /* Additional registers */ + uint32_t dsc_clock_enable; + uint32_t dsc_clock_gating_disable; + uint32_t underflow_recovery_en; + uint32_t underflow_occurred_int_en; + uint32_t underflow_occurred_status; + enum dsc_pixel_format pixel_format; + uint32_t ich_reset_at_eol; + uint32_t alternate_ich_encoding_en; + uint32_t num_slices_h; + uint32_t num_slices_v; + uint32_t rc_buffer_model_size; + uint32_t disable_ich; + uint32_t bpp_x32; + uint32_t dsc_dbg_en; + uint32_t rc_buffer_model_overflow_int_en[4]; +}; + +struct dcn20_dsc { + struct display_stream_compressor base; + const struct dcn20_dsc_registers *dsc_regs; + const struct dcn20_dsc_shift *dsc_shift; + const struct dcn20_dsc_mask *dsc_mask; + + struct dsc_reg_values reg_vals; + + int max_image_width; +}; + +void dsc_config_log(struct display_stream_compressor *dsc, + const struct dsc_config *config); + +void dsc_log_pps(struct display_stream_compressor *dsc, + struct drm_dsc_config *pps); + +void dsc_override_rc_params(struct rc_params *rc, + const struct dc_dsc_rc_params_override *override); + +bool dsc_prepare_config(const struct dsc_config *dsc_cfg, + struct dsc_reg_values *dsc_reg_vals, + struct dsc_optc_config *dsc_optc_cfg); + +enum dsc_pixel_format dsc_dc_pixel_encoding_to_dsc_pixel_format(enum dc_pixel_encoding dc_pix_enc, + bool is_ycbcr422_simple); + +enum dsc_bits_per_comp dsc_dc_color_depth_to_dsc_bits_per_comp(enum dc_color_depth dc_color_depth); + +void dsc_init_reg_values(struct dsc_reg_values *reg_vals); + +void dsc_update_from_dsc_parameters(struct dsc_reg_values *reg_vals, const struct dsc_parameters *dsc_params); + +void dsc2_construct(struct dcn20_dsc *dsc, + struct dc_context *ctx, + int inst, + const struct dcn20_dsc_registers *dsc_regs, + const struct dcn20_dsc_shift *dsc_shift, + const struct dcn20_dsc_mask *dsc_mask); + +void dsc2_get_enc_caps(struct dsc_enc_caps *dsc_enc_caps, + int pixel_clock_100Hz); + +bool dsc2_get_packed_pps(struct display_stream_compressor *dsc, + const struct dsc_config *dsc_cfg, + uint8_t *dsc_packed_pps); + +#endif + diff --git a/drivers/gpu/drm/amd/display/dc/dsc/dcn35/dcn35_dsc.c b/drivers/gpu/drm/amd/display/dc/dsc/dcn35/dcn35_dsc.c new file mode 100644 index 000000000000..71d2dff9986d --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/dsc/dcn35/dcn35_dsc.c @@ -0,0 +1,60 @@ +/* SPDX-License-Identifier: MIT */ +/* + * Copyright 2023 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 "dcn35_dsc.h" +#include "reg_helper.h" + +/* Macro definitios for REG_SET macros*/ +#define CTX \ + dsc20->base.ctx + +#define REG(reg)\ + dsc20->dsc_regs->reg + +#undef FN +#define FN(reg_name, field_name) \ + ((const struct dcn35_dsc_shift *)(dsc20->dsc_shift))->field_name, \ + ((const struct dcn35_dsc_mask *)(dsc20->dsc_mask))->field_name + +#define DC_LOGGER \ + dsc->ctx->logger + +void dsc35_construct(struct dcn20_dsc *dsc, + struct dc_context *ctx, + int inst, + const struct dcn20_dsc_registers *dsc_regs, + const struct dcn35_dsc_shift *dsc_shift, + const struct dcn35_dsc_mask *dsc_mask) +{ + dsc2_construct(dsc, ctx, inst, dsc_regs, + (const struct dcn20_dsc_shift *)(dsc_shift), + (const struct dcn20_dsc_mask *)(dsc_mask)); +} + +void dsc35_set_fgcg(struct dcn20_dsc *dsc20, bool enable) +{ + REG_UPDATE(DSC_TOP_CONTROL, DSC_FGCG_REP_DIS, !enable); +} diff --git a/drivers/gpu/drm/amd/display/dc/dsc/dcn35/dcn35_dsc.h b/drivers/gpu/drm/amd/display/dc/dsc/dcn35/dcn35_dsc.h new file mode 100644 index 000000000000..133ad38842cc --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/dsc/dcn35/dcn35_dsc.h @@ -0,0 +1,59 @@ +/* SPDX-License-Identifier: MIT */ +/* + * Copyright 2023 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 __DCN35_DSC_H__ +#define __DCN35_DSC_H__ + +#include "dcn20/dcn20_dsc.h" + +#define DSC_REG_LIST_SH_MASK_DCN35(mask_sh) \ + DSC_REG_LIST_SH_MASK_DCN20(mask_sh), \ + DSC_SF(DSC_TOP0_DSC_TOP_CONTROL, DSC_FGCG_REP_DIS, mask_sh) + +#define DSC_FIELD_LIST_DCN35(type) \ + struct { \ + DSC_FIELD_LIST_DCN20(type); \ + type DSC_FGCG_REP_DIS; \ + } + +struct dcn35_dsc_shift { + DSC_FIELD_LIST_DCN35(uint8_t); +}; + +struct dcn35_dsc_mask { + DSC_FIELD_LIST_DCN35(uint32_t); +}; + +void dsc35_construct(struct dcn20_dsc *dsc, + struct dc_context *ctx, + int inst, + const struct dcn20_dsc_registers *dsc_regs, + const struct dcn35_dsc_shift *dsc_shift, + const struct dcn35_dsc_mask *dsc_mask); + +void dsc35_set_fgcg(struct dcn20_dsc *dsc20, bool enable); + +#endif /* __DCN35_DSC_H__ */ diff --git a/drivers/gpu/drm/amd/display/dc/dsc/dsc.h b/drivers/gpu/drm/amd/display/dc/dsc/dsc.h new file mode 100644 index 000000000000..4b27f29d0d80 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/dsc/dsc.h @@ -0,0 +1,112 @@ +/* + * Copyright 2017 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 __DAL_DSC_H__ +#define __DAL_DSC_H__ + +#include "dc_dsc.h" +#include "dc_hw_types.h" +#include "dc_types.h" +/* do not include any other headers + * or else it might break Edid Utility functionality. + */ + + +/* Input parameters for configuring DSC from the outside of DSC */ +struct dsc_config { + uint32_t pic_width; + uint32_t pic_height; + enum dc_pixel_encoding pixel_encoding; + enum dc_color_depth color_depth; /* Bits per component */ + bool is_odm; + struct dc_dsc_config dc_dsc_cfg; +}; + + +/* Output parameters for configuring DSC-related part of OPTC */ +struct dsc_optc_config { + uint32_t slice_width; /* Slice width in pixels */ + uint32_t bytes_per_pixel; /* Bytes per pixel in u3.28 format */ + bool is_pixel_format_444; /* 'true' if pixel format is 'RGB 444' or 'Simple YCbCr 4:2:2' (4:2:2 upsampled to 4:4:4)' */ +}; + + +struct dcn_dsc_state { + uint32_t dsc_clock_en; + uint32_t dsc_slice_width; + uint32_t dsc_bits_per_pixel; + uint32_t dsc_slice_height; + uint32_t dsc_pic_width; + uint32_t dsc_pic_height; + uint32_t dsc_slice_bpg_offset; + uint32_t dsc_chunk_size; + uint32_t dsc_fw_en; + uint32_t dsc_opp_source; +}; + + +/* DSC encoder capabilities + * They differ from the DPCD DSC caps because they are based on AMD DSC encoder caps. + */ +union dsc_enc_slice_caps { + struct { + uint8_t NUM_SLICES_1 : 1; + uint8_t NUM_SLICES_2 : 1; + uint8_t NUM_SLICES_3 : 1; /* This one is not per DSC spec, but our encoder supports it */ + uint8_t NUM_SLICES_4 : 1; + uint8_t NUM_SLICES_8 : 1; + uint8_t NUM_SLICES_12 : 1; + uint8_t NUM_SLICES_16 : 1; + } bits; + uint8_t raw; +}; + +struct dsc_enc_caps { + uint8_t dsc_version; + union dsc_enc_slice_caps slice_caps; + int32_t lb_bit_depth; + bool is_block_pred_supported; + union dsc_color_formats color_formats; + union dsc_color_depth color_depth; + int32_t max_total_throughput_mps; /* Maximum total throughput with all the slices combined */ + int32_t max_slice_width; + uint32_t bpp_increment_div; /* bpp increment divisor, e.g. if 16, it's 1/16th of a bit */ + uint32_t edp_sink_max_bits_per_pixel; + bool is_dp; +}; + +struct dsc_funcs { + void (*dsc_get_enc_caps)(struct dsc_enc_caps *dsc_enc_caps, int pixel_clock_100Hz); + void (*dsc_read_state)(struct display_stream_compressor *dsc, struct dcn_dsc_state *s); + bool (*dsc_validate_stream)(struct display_stream_compressor *dsc, const struct dsc_config *dsc_cfg); + void (*dsc_set_config)(struct display_stream_compressor *dsc, const struct dsc_config *dsc_cfg, + struct dsc_optc_config *dsc_optc_cfg); + bool (*dsc_get_packed_pps)(struct display_stream_compressor *dsc, const struct dsc_config *dsc_cfg, + uint8_t *dsc_packed_pps); + void (*dsc_enable)(struct display_stream_compressor *dsc, int opp_pipe); + void (*dsc_disable)(struct display_stream_compressor *dsc); + void (*dsc_disconnect)(struct display_stream_compressor *dsc); +}; + +#endif diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/dsc.h b/drivers/gpu/drm/amd/display/dc/inc/hw/dsc.h deleted file mode 100644 index 4b27f29d0d80..000000000000 --- a/drivers/gpu/drm/amd/display/dc/inc/hw/dsc.h +++ /dev/null @@ -1,112 +0,0 @@ -/* - * Copyright 2017 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 __DAL_DSC_H__ -#define __DAL_DSC_H__ - -#include "dc_dsc.h" -#include "dc_hw_types.h" -#include "dc_types.h" -/* do not include any other headers - * or else it might break Edid Utility functionality. - */ - - -/* Input parameters for configuring DSC from the outside of DSC */ -struct dsc_config { - uint32_t pic_width; - uint32_t pic_height; - enum dc_pixel_encoding pixel_encoding; - enum dc_color_depth color_depth; /* Bits per component */ - bool is_odm; - struct dc_dsc_config dc_dsc_cfg; -}; - - -/* Output parameters for configuring DSC-related part of OPTC */ -struct dsc_optc_config { - uint32_t slice_width; /* Slice width in pixels */ - uint32_t bytes_per_pixel; /* Bytes per pixel in u3.28 format */ - bool is_pixel_format_444; /* 'true' if pixel format is 'RGB 444' or 'Simple YCbCr 4:2:2' (4:2:2 upsampled to 4:4:4)' */ -}; - - -struct dcn_dsc_state { - uint32_t dsc_clock_en; - uint32_t dsc_slice_width; - uint32_t dsc_bits_per_pixel; - uint32_t dsc_slice_height; - uint32_t dsc_pic_width; - uint32_t dsc_pic_height; - uint32_t dsc_slice_bpg_offset; - uint32_t dsc_chunk_size; - uint32_t dsc_fw_en; - uint32_t dsc_opp_source; -}; - - -/* DSC encoder capabilities - * They differ from the DPCD DSC caps because they are based on AMD DSC encoder caps. - */ -union dsc_enc_slice_caps { - struct { - uint8_t NUM_SLICES_1 : 1; - uint8_t NUM_SLICES_2 : 1; - uint8_t NUM_SLICES_3 : 1; /* This one is not per DSC spec, but our encoder supports it */ - uint8_t NUM_SLICES_4 : 1; - uint8_t NUM_SLICES_8 : 1; - uint8_t NUM_SLICES_12 : 1; - uint8_t NUM_SLICES_16 : 1; - } bits; - uint8_t raw; -}; - -struct dsc_enc_caps { - uint8_t dsc_version; - union dsc_enc_slice_caps slice_caps; - int32_t lb_bit_depth; - bool is_block_pred_supported; - union dsc_color_formats color_formats; - union dsc_color_depth color_depth; - int32_t max_total_throughput_mps; /* Maximum total throughput with all the slices combined */ - int32_t max_slice_width; - uint32_t bpp_increment_div; /* bpp increment divisor, e.g. if 16, it's 1/16th of a bit */ - uint32_t edp_sink_max_bits_per_pixel; - bool is_dp; -}; - -struct dsc_funcs { - void (*dsc_get_enc_caps)(struct dsc_enc_caps *dsc_enc_caps, int pixel_clock_100Hz); - void (*dsc_read_state)(struct display_stream_compressor *dsc, struct dcn_dsc_state *s); - bool (*dsc_validate_stream)(struct display_stream_compressor *dsc, const struct dsc_config *dsc_cfg); - void (*dsc_set_config)(struct display_stream_compressor *dsc, const struct dsc_config *dsc_cfg, - struct dsc_optc_config *dsc_optc_cfg); - bool (*dsc_get_packed_pps)(struct display_stream_compressor *dsc, const struct dsc_config *dsc_cfg, - uint8_t *dsc_packed_pps); - void (*dsc_enable)(struct display_stream_compressor *dsc, int opp_pipe); - void (*dsc_disable)(struct display_stream_compressor *dsc); - void (*dsc_disconnect)(struct display_stream_compressor *dsc); -}; - -#endif -- cgit From c77b0008591094d454c1f340d1e82b5ebe2d918d Mon Sep 17 00:00:00 2001 From: Max Tseng Date: Tue, 7 Nov 2023 15:00:03 +0800 Subject: drm/amd/display: replay: generalize the send command function usage Augment the function to allow send different format data in different use case. Reviewed-by: Dennis Chan Acked-by: Hamza Mahfooz Signed-off-by: Max Tseng Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dc_types.h | 1 + drivers/gpu/drm/amd/display/dc/dce/dmub_replay.h | 3 +-- drivers/gpu/drm/amd/display/dc/inc/link.h | 2 +- .../drm/amd/display/dc/link/protocols/link_edp_panel_control.c | 4 ++-- .../drm/amd/display/dc/link/protocols/link_edp_panel_control.h | 2 +- drivers/gpu/drm/amd/display/dmub/inc/dmub_cmd.h | 10 ++++++++++ 6 files changed, 16 insertions(+), 6 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/dc_types.h b/drivers/gpu/drm/amd/display/dc/dc_types.h index edf60c4f318c..6f5da510e8de 100644 --- a/drivers/gpu/drm/amd/display/dc/dc_types.h +++ b/drivers/gpu/drm/amd/display/dc/dc_types.h @@ -1029,6 +1029,7 @@ enum replay_coasting_vtotal_type { * passed to DMUB. */ enum replay_FW_Message_type { + Replay_Msg_Not_Support = -1, Replay_Set_Timing_Sync_Supported, }; diff --git a/drivers/gpu/drm/amd/display/dc/dce/dmub_replay.h b/drivers/gpu/drm/amd/display/dc/dce/dmub_replay.h index 427bc47a676e..368711f76335 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dmub_replay.h +++ b/drivers/gpu/drm/amd/display/dc/dce/dmub_replay.h @@ -46,8 +46,7 @@ struct dmub_replay_funcs { void (*replay_set_power_opt)(struct dmub_replay *dmub, unsigned int power_opt, uint8_t panel_inst); void (*replay_send_cmd)(struct dmub_replay *dmub, - enum replay_FW_Message_type msg, unsigned int panel_inst, - uint32_t cmd_data); + enum replay_FW_Message_type msg, unsigned int panel_inst, union dmub_replay_cmd_set *cmd_element); void (*replay_set_coasting_vtotal)(struct dmub_replay *dmub, uint16_t coasting_vtotal, uint8_t panel_inst); void (*replay_residency)(struct dmub_replay *dmub, diff --git a/drivers/gpu/drm/amd/display/dc/inc/link.h b/drivers/gpu/drm/amd/display/dc/inc/link.h index dd3f53151d8b..7439865d1b50 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/link.h +++ b/drivers/gpu/drm/amd/display/dc/inc/link.h @@ -283,7 +283,7 @@ struct link_service { const struct dc_stream_state *stream); bool (*edp_send_replay_cmd)(struct dc_link *link, enum replay_FW_Message_type msg, - uint32_t params); + union dmub_replay_cmd_set *cmd_data); bool (*edp_set_coasting_vtotal)( struct dc_link *link, uint16_t coasting_vtotal); bool (*edp_replay_residency)(const struct dc_link *link, diff --git a/drivers/gpu/drm/amd/display/dc/link/protocols/link_edp_panel_control.c b/drivers/gpu/drm/amd/display/dc/link/protocols/link_edp_panel_control.c index c52b51b2b4b3..6bc8ec47e267 100644 --- a/drivers/gpu/drm/amd/display/dc/link/protocols/link_edp_panel_control.c +++ b/drivers/gpu/drm/amd/display/dc/link/protocols/link_edp_panel_control.c @@ -1014,7 +1014,7 @@ bool edp_setup_replay(struct dc_link *link, const struct dc_stream_state *stream */ bool edp_send_replay_cmd(struct dc_link *link, enum replay_FW_Message_type msg, - uint32_t cmd_data) + union dmub_replay_cmd_set *cmd_data) { struct dc *dc = link->ctx->dc; struct dmub_replay *replay = dc->res_pool->replay; @@ -1026,7 +1026,7 @@ bool edp_send_replay_cmd(struct dc_link *link, if (!dc_get_edp_link_panel_inst(dc, link, &panel_inst)) return false; - replay->funcs->replay_send_cmd(replay, msg, cmd_data, panel_inst); + replay->funcs->replay_send_cmd(replay, msg, panel_inst, cmd_data); return true; } diff --git a/drivers/gpu/drm/amd/display/dc/link/protocols/link_edp_panel_control.h b/drivers/gpu/drm/amd/display/dc/link/protocols/link_edp_panel_control.h index 6b223580ac8a..39526bd40178 100644 --- a/drivers/gpu/drm/amd/display/dc/link/protocols/link_edp_panel_control.h +++ b/drivers/gpu/drm/amd/display/dc/link/protocols/link_edp_panel_control.h @@ -59,7 +59,7 @@ bool edp_setup_replay(struct dc_link *link, const struct dc_stream_state *stream); bool edp_send_replay_cmd(struct dc_link *link, enum replay_FW_Message_type msg, - uint32_t params); + union dmub_replay_cmd_set *cmd_data); bool edp_set_coasting_vtotal(struct dc_link *link, uint16_t coasting_vtotal); bool edp_replay_residency(const struct dc_link *link, unsigned int *residency, const bool is_start, const bool is_alpm); diff --git a/drivers/gpu/drm/amd/display/dmub/inc/dmub_cmd.h b/drivers/gpu/drm/amd/display/dmub/inc/dmub_cmd.h index 55573083bc31..5f06cf4c663f 100644 --- a/drivers/gpu/drm/amd/display/dmub/inc/dmub_cmd.h +++ b/drivers/gpu/drm/amd/display/dmub/inc/dmub_cmd.h @@ -3143,6 +3143,16 @@ struct dmub_rb_cmd_replay_set_timing_sync { struct dmub_cmd_replay_set_timing_sync_data replay_set_timing_sync_data; }; +/** + * Definition union of replay command set + */ +union dmub_replay_cmd_set { + /** + * Definition of DMUB_CMD__REPLAY_SET_TIMING_SYNC_SUPPORTED command data. + */ + struct dmub_cmd_replay_set_timing_sync_data sync_data; +}; + /** * Set of HW components that can be locked. * -- cgit From 220db802cb505e6ec3b3e0018ac0233205632a72 Mon Sep 17 00:00:00 2001 From: Michael Strauss Date: Fri, 27 Oct 2023 14:12:51 -0400 Subject: drm/amd/display: Do not read DPREFCLK spread info from LUT on DCN35 [WHY] Currently DCN35 does not spread DPREFCLK [HOW] Remove hardcoded table with nonzero caps Reviewed-by: Nicholas Kazlauskas Acked-by: Hamza Mahfooz Signed-off-by: Michael Strauss Signed-off-by: Alex Deucher --- .../amd/display/dc/clk_mgr/dcn35/dcn35_clk_mgr.c | 22 ---------------------- 1 file changed, 22 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn35/dcn35_clk_mgr.c b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn35/dcn35_clk_mgr.c index 3469f692d6ea..0f3f6a9d5144 100644 --- a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn35/dcn35_clk_mgr.c +++ b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn35/dcn35_clk_mgr.c @@ -515,11 +515,6 @@ static DpmClocks_t_dcn35 dummy_clocks; static struct dcn35_watermarks dummy_wms = { 0 }; -static struct dcn35_ss_info_table ss_info_table = { - .ss_divider = 1000, - .ss_percentage = {0, 0, 375, 375, 375} -}; - static void dcn35_build_watermark_ranges(struct clk_bw_params *bw_params, struct dcn35_watermarks *table) { int i, num_valid_sets; @@ -965,21 +960,6 @@ struct clk_mgr_funcs dcn35_fpga_funcs = { .get_dtb_ref_clk_frequency = dcn31_get_dtb_ref_freq_khz, }; -static void dcn35_read_ss_info_from_lut(struct clk_mgr_internal *clk_mgr) -{ - uint32_t clock_source; - struct dc_context *ctx = clk_mgr->base.ctx; - - REG_GET(CLK1_CLK2_BYPASS_CNTL, CLK2_BYPASS_SEL, &clock_source); - - clk_mgr->dprefclk_ss_percentage = ss_info_table.ss_percentage[clock_source]; - - if (clk_mgr->dprefclk_ss_percentage != 0) { - clk_mgr->ss_on_dprefclk = true; - clk_mgr->dprefclk_ss_divider = ss_info_table.ss_divider; - } -} - void dcn35_clk_mgr_construct( struct dc_context *ctx, struct clk_mgr_dcn35 *clk_mgr, @@ -1052,8 +1032,6 @@ void dcn35_clk_mgr_construct( dce_clock_read_ss_info(&clk_mgr->base); /*when clk src is from FCH, it could have ss, same clock src as DPREF clk*/ - dcn35_read_ss_info_from_lut(&clk_mgr->base); - clk_mgr->base.base.bw_params = &dcn35_bw_params; if (clk_mgr->base.base.ctx->dc->debug.pstate_enabled) { -- cgit From 75a3371e8ffdab2e504f4326daab60f8fb15fdf1 Mon Sep 17 00:00:00 2001 From: Alvin Lee Date: Wed, 8 Nov 2023 17:16:28 -0500 Subject: drm/amd/display: Increase num voltage states to 40 [Description] If during driver init stage there are greater than 20 intermediary voltage states while constructing the SOC BB we could hit issues because we will index outside of the clock_limits array and start overwriting data. Increase the total number of states to 40 to avoid this issue. Cc: stable@vger.kernel.org # 6.1+ Reviewed-by: Samson Tam Acked-by: Hamza Mahfooz Signed-off-by: Alvin Lee Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dml/dc_features.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/display/dc/dml/dc_features.h b/drivers/gpu/drm/amd/display/dc/dml/dc_features.h index 2cbdd75429ff..6e669a2c5b2d 100644 --- a/drivers/gpu/drm/amd/display/dc/dml/dc_features.h +++ b/drivers/gpu/drm/amd/display/dc/dml/dc_features.h @@ -36,7 +36,7 @@ * Define the maximum amount of states supported by the ASIC. Every ASIC has a * specific number of states; this macro defines the maximum number of states. */ -#define DC__VOLTAGE_STATES 20 +#define DC__VOLTAGE_STATES 40 #define DC__NUM_DPP__4 1 #define DC__NUM_DPP__0_PRESENT 1 #define DC__NUM_DPP__1_PRESENT 1 -- cgit From 37f4382b64a2b01109a0ed5c05f58d3f86385e10 Mon Sep 17 00:00:00 2001 From: Max Tseng Date: Wed, 8 Nov 2023 11:31:50 +0800 Subject: drm/amd/display: replay: Augment Frameupdate Command [Why] Sending certain Frameupdate number for Replay Power Evaluation Reviewed-by: Dennis Chan Acked-by: Hamza Mahfooz Signed-off-by: Max Tseng Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dc_types.h | 1 + drivers/gpu/drm/amd/display/dc/dce/dmub_replay.h | 2 +- .../dc/link/protocols/link_edp_panel_control.c | 10 ++++- drivers/gpu/drm/amd/display/dmub/inc/dmub_cmd.h | 51 ++++++++++++++++++++++ 4 files changed, 61 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/dc_types.h b/drivers/gpu/drm/amd/display/dc/dc_types.h index 6f5da510e8de..4a60d2c47686 100644 --- a/drivers/gpu/drm/amd/display/dc/dc_types.h +++ b/drivers/gpu/drm/amd/display/dc/dc_types.h @@ -1031,6 +1031,7 @@ enum replay_coasting_vtotal_type { enum replay_FW_Message_type { Replay_Msg_Not_Support = -1, Replay_Set_Timing_Sync_Supported, + Replay_Set_Residency_Frameupdate_Timer, }; union replay_error_status { diff --git a/drivers/gpu/drm/amd/display/dc/dce/dmub_replay.h b/drivers/gpu/drm/amd/display/dc/dce/dmub_replay.h index 368711f76335..b3ee90a0b8b3 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dmub_replay.h +++ b/drivers/gpu/drm/amd/display/dc/dce/dmub_replay.h @@ -46,7 +46,7 @@ struct dmub_replay_funcs { void (*replay_set_power_opt)(struct dmub_replay *dmub, unsigned int power_opt, uint8_t panel_inst); void (*replay_send_cmd)(struct dmub_replay *dmub, - enum replay_FW_Message_type msg, unsigned int panel_inst, union dmub_replay_cmd_set *cmd_element); + enum replay_FW_Message_type msg, union dmub_replay_cmd_set *cmd_element); void (*replay_set_coasting_vtotal)(struct dmub_replay *dmub, uint16_t coasting_vtotal, uint8_t panel_inst); void (*replay_residency)(struct dmub_replay *dmub, diff --git a/drivers/gpu/drm/amd/display/dc/link/protocols/link_edp_panel_control.c b/drivers/gpu/drm/amd/display/dc/link/protocols/link_edp_panel_control.c index 6bc8ec47e267..fdeb8dff5485 100644 --- a/drivers/gpu/drm/amd/display/dc/link/protocols/link_edp_panel_control.c +++ b/drivers/gpu/drm/amd/display/dc/link/protocols/link_edp_panel_control.c @@ -1023,10 +1023,16 @@ bool edp_send_replay_cmd(struct dc_link *link, if (!replay) return false; - if (!dc_get_edp_link_panel_inst(dc, link, &panel_inst)) + DC_LOGGER_INIT(link->ctx->logger); + + if (dc_get_edp_link_panel_inst(dc, link, &panel_inst)) + cmd_data->panel_inst = panel_inst; + else { + DC_LOG_DC("%s(): get edp panel inst fail ", __func__); return false; + } - replay->funcs->replay_send_cmd(replay, msg, panel_inst, cmd_data); + replay->funcs->replay_send_cmd(replay, msg, cmd_data); return true; } diff --git a/drivers/gpu/drm/amd/display/dmub/inc/dmub_cmd.h b/drivers/gpu/drm/amd/display/dmub/inc/dmub_cmd.h index 5f06cf4c663f..d1becbb5aa29 100644 --- a/drivers/gpu/drm/amd/display/dmub/inc/dmub_cmd.h +++ b/drivers/gpu/drm/amd/display/dmub/inc/dmub_cmd.h @@ -2880,6 +2880,10 @@ enum dmub_cmd_replay_type { * Set disabled iiming sync. */ DMUB_CMD__REPLAY_SET_TIMING_SYNC_SUPPORTED = 5, + /** + * Set Residency Frameupdate Timer. + */ + DMUB_CMD__REPLAY_SET_RESIDENCY_FRAMEUPDATE_TIMER = 6, }; /** @@ -3143,14 +3147,57 @@ struct dmub_rb_cmd_replay_set_timing_sync { struct dmub_cmd_replay_set_timing_sync_data replay_set_timing_sync_data; }; +/** + * Data passed from driver to FW in DMUB_CMD__REPLAY_SET_RESIDENCY_FRAMEUPDATE_TIMER command. + */ +struct dmub_cmd_replay_frameupdate_timer_data { + /** + * Panel Instance. + * Panel isntance to identify which replay_state to use + * Currently the support is only for 0 or 1 + */ + uint8_t panel_inst; + /** + * Replay Frameupdate Timer Enable or not + */ + uint8_t enable; + /** + * REPLAY force reflash frame update number + */ + uint16_t frameupdate_count; +}; +/** + * Definition of DMUB_CMD__REPLAY_SET_RESIDENCY_FRAMEUPDATE_TIMER + */ +struct dmub_rb_cmd_replay_set_frameupdate_timer { + /** + * Command header. + */ + struct dmub_cmd_header header; + /** + * Definition of a DMUB_CMD__SET_REPLAY_POWER_OPT command. + */ + struct dmub_cmd_replay_frameupdate_timer_data data; +}; + /** * Definition union of replay command set */ union dmub_replay_cmd_set { + /** + * Panel Instance. + * Panel isntance to identify which replay_state to use + * Currently the support is only for 0 or 1 + */ + uint8_t panel_inst; /** * Definition of DMUB_CMD__REPLAY_SET_TIMING_SYNC_SUPPORTED command data. */ struct dmub_cmd_replay_set_timing_sync_data sync_data; + /** + * Definition of DMUB_CMD__REPLAY_SET_RESIDENCY_FRAMEUPDATE_TIMER command data. + */ + struct dmub_cmd_replay_frameupdate_timer_data timer_data; }; /** @@ -4288,6 +4335,10 @@ union dmub_rb_cmd { struct dmub_rb_cmd_replay_set_power_opt_and_coasting_vtotal replay_set_power_opt_and_coasting_vtotal; struct dmub_rb_cmd_replay_set_timing_sync replay_set_timing_sync; + /** + * Definition of a DMUB_CMD__REPLAY_SET_RESIDENCY_FRAMEUPDATE_TIMER command. + */ + struct dmub_rb_cmd_replay_set_frameupdate_timer replay_set_frameupdate_timer; }; /** -- cgit From 43b8ac4b34ec239bccf4a692c1227ef51a95a4d2 Mon Sep 17 00:00:00 2001 From: Camille Cho Date: Fri, 3 Nov 2023 12:08:42 +0800 Subject: drm/amd/display: Simplify brightness initialization [Why] Remove the brightness cache in DC. It uses a single value to represent the brightness for both SDR and HDR mode. This leads to flash in HDR on/off. It also unconditionally programs brightness as in HDR mode. This may introduce garbage on SDR mode in miniLED panel. [How] Simplify the initialization flow by removing the DC cache and taking what panel has as default. Expand the mechanism for PWM to DPCD Aux to restore cached brightness value generally. Cc: stable@vger.kernel.org # 6.1+ Reviewed-by: Krunoslav Kovac Acked-by: Hamza Mahfooz Signed-off-by: Camille Cho Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dc.h | 1 - drivers/gpu/drm/amd/display/dc/dc_types.h | 4 ---- drivers/gpu/drm/amd/display/dc/link/link_detection.c | 2 +- drivers/gpu/drm/amd/display/dc/link/link_dpms.c | 3 +-- .../display/dc/link/protocols/link_edp_panel_control.c | 16 +++------------- .../display/dc/link/protocols/link_edp_panel_control.h | 1 - 6 files changed, 5 insertions(+), 22 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h index 349629858205..18b8d7f3f738 100644 --- a/drivers/gpu/drm/amd/display/dc/dc.h +++ b/drivers/gpu/drm/amd/display/dc/dc.h @@ -1610,7 +1610,6 @@ struct dc_link { enum edp_revision edp_revision; union dpcd_sink_ext_caps dpcd_sink_ext_caps; - struct backlight_settings backlight_settings; struct psr_settings psr_settings; struct replay_settings replay_settings; diff --git a/drivers/gpu/drm/amd/display/dc/dc_types.h b/drivers/gpu/drm/amd/display/dc/dc_types.h index 4a60d2c47686..a2f6c994a2a9 100644 --- a/drivers/gpu/drm/amd/display/dc/dc_types.h +++ b/drivers/gpu/drm/amd/display/dc/dc_types.h @@ -991,10 +991,6 @@ struct link_mst_stream_allocation_table { struct link_mst_stream_allocation stream_allocations[MAX_CONTROLLER_NUM]; }; -struct backlight_settings { - uint32_t backlight_millinits; -}; - /* PSR feature flags */ struct psr_settings { bool psr_feature_enabled; // PSR is supported by sink diff --git a/drivers/gpu/drm/amd/display/dc/link/link_detection.c b/drivers/gpu/drm/amd/display/dc/link/link_detection.c index f2fe523f914f..24153b0df503 100644 --- a/drivers/gpu/drm/amd/display/dc/link/link_detection.c +++ b/drivers/gpu/drm/amd/display/dc/link/link_detection.c @@ -879,7 +879,7 @@ static bool detect_link_and_local_sink(struct dc_link *link, (link->dpcd_sink_ext_caps.bits.oled == 1)) { dpcd_set_source_specific_data(link); msleep(post_oui_delay); - set_cached_brightness_aux(link); + set_default_brightness_aux(link); } return true; diff --git a/drivers/gpu/drm/amd/display/dc/link/link_dpms.c b/drivers/gpu/drm/amd/display/dc/link/link_dpms.c index 34a4a8c0e18c..f8e01ca09d96 100644 --- a/drivers/gpu/drm/amd/display/dc/link/link_dpms.c +++ b/drivers/gpu/drm/amd/display/dc/link/link_dpms.c @@ -2142,8 +2142,7 @@ static enum dc_status enable_link_dp(struct dc_state *state, if (link->dpcd_sink_ext_caps.bits.oled == 1 || link->dpcd_sink_ext_caps.bits.sdr_aux_backlight_control == 1 || link->dpcd_sink_ext_caps.bits.hdr_aux_backlight_control == 1) { - set_cached_brightness_aux(link); - + set_default_brightness_aux(link); if (link->dpcd_sink_ext_caps.bits.oled == 1) msleep(bl_oled_enable_delay); edp_backlight_enable_aux(link, true); diff --git a/drivers/gpu/drm/amd/display/dc/link/protocols/link_edp_panel_control.c b/drivers/gpu/drm/amd/display/dc/link/protocols/link_edp_panel_control.c index fdeb8dff5485..ac0fa88b52a0 100644 --- a/drivers/gpu/drm/amd/display/dc/link/protocols/link_edp_panel_control.c +++ b/drivers/gpu/drm/amd/display/dc/link/protocols/link_edp_panel_control.c @@ -170,7 +170,6 @@ bool edp_set_backlight_level_nits(struct dc_link *link, *(uint32_t *)&dpcd_backlight_set.backlight_level_millinits = backlight_millinits; *(uint16_t *)&dpcd_backlight_set.backlight_transition_time_ms = (uint16_t)transition_time_in_ms; - link->backlight_settings.backlight_millinits = backlight_millinits; if (!link->dpcd_caps.panel_luminance_control) { if (core_link_write_dpcd(link, DP_SOURCE_BACKLIGHT_LEVEL, @@ -288,9 +287,9 @@ bool set_default_brightness_aux(struct dc_link *link) if (link && link->dpcd_sink_ext_caps.bits.oled == 1) { if (!read_default_bl_aux(link, &default_backlight)) default_backlight = 150000; - // if < 1 nits or > 5000, it might be wrong readback - if (default_backlight < 1000 || default_backlight > 5000000) - default_backlight = 150000; // + // if > 5000, it might be wrong readback + if (default_backlight > 5000000) + default_backlight = 150000; return edp_set_backlight_level_nits(link, true, default_backlight, 0); @@ -298,15 +297,6 @@ bool set_default_brightness_aux(struct dc_link *link) return false; } -bool set_cached_brightness_aux(struct dc_link *link) -{ - if (link->backlight_settings.backlight_millinits) - return edp_set_backlight_level_nits(link, true, - link->backlight_settings.backlight_millinits, 0); - else - return set_default_brightness_aux(link); - return false; -} bool edp_is_ilr_optimization_enabled(struct dc_link *link) { if (link->dpcd_caps.edp_supported_link_rates_count == 0 || !link->panel_config.ilr.optimize_edp_link_rate) diff --git a/drivers/gpu/drm/amd/display/dc/link/protocols/link_edp_panel_control.h b/drivers/gpu/drm/amd/display/dc/link/protocols/link_edp_panel_control.h index 39526bd40178..b7493ff4fcee 100644 --- a/drivers/gpu/drm/amd/display/dc/link/protocols/link_edp_panel_control.h +++ b/drivers/gpu/drm/amd/display/dc/link/protocols/link_edp_panel_control.h @@ -30,7 +30,6 @@ enum dp_panel_mode dp_get_panel_mode(struct dc_link *link); void dp_set_panel_mode(struct dc_link *link, enum dp_panel_mode panel_mode); bool set_default_brightness_aux(struct dc_link *link); -bool set_cached_brightness_aux(struct dc_link *link); void edp_panel_backlight_power_on(struct dc_link *link, bool wait_for_hpd); int edp_get_backlight_level(const struct dc_link *link); bool edp_get_backlight_level_nits(struct dc_link *link, -- cgit From 83a79dd6f4fb54c8cfe3ecbd378817047687a9b2 Mon Sep 17 00:00:00 2001 From: Wayne Lin Date: Mon, 7 Aug 2023 15:34:39 +0800 Subject: drm/amd/display: adjust flow for deallocation mst payload MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [Why] MST relevant variables are maintained at drm side. As the result, we still have to call drm_dp_remove_payload_part2() to update the relevant values regardless the link is under mst mode or not. We used to have a workaround patch to tackle this: commit 3d8fcc6740c9 ("drm/amd/display: Extract temp drm mst deallocation wa into its own function") Now it's time to remove the workaround and adjust the flow. [How] During deallocate_mst_payload(), source actually doesn't send out ALLOCATE_PAYLOAD at the end as like the flow in allocate_mst_payload(). Call function dm_helpers_dp_mst_send_payload_allocation() at the end of deallocate_mst_payload() is a bit confusing. Separate dm_helpers_dp_mst_send_payload_allocation() into 2 functions. Have a new function dm_helpers_dp_mst_update_mst_mgr_for_deallocation() to replace dm_helpers_dp_mst_send_payload_allocation() for payload deallocation. Cc: Ville Syrjälä Reviewed-by: Wenjing Liu Acked-by: Hamza Mahfooz Signed-off-by: Wayne Lin Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 17 ---- .../drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c | 53 +++++++---- drivers/gpu/drm/amd/display/dc/dc.h | 1 - drivers/gpu/drm/amd/display/dc/dm_helpers.h | 12 ++- drivers/gpu/drm/amd/display/dc/link/link_dpms.c | 105 ++------------------- 5 files changed, 50 insertions(+), 138 deletions(-) diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c index ba3f7b232a16..2be64c593c87 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -1715,23 +1715,6 @@ static int amdgpu_dm_init(struct amdgpu_device *adev) /* TODO: Remove after DP2 receiver gets proper support of Cable ID feature */ adev->dm.dc->debug.ignore_cable_id = true; - /* TODO: There is a new drm mst change where the freedom of - * vc_next_start_slot update is revoked/moved into drm, instead of in - * driver. This forces us to make sure to get vc_next_start_slot updated - * in drm function each time without considering if mst_state is active - * or not. Otherwise, next time hotplug will give wrong start_slot - * number. We are implementing a temporary solution to even notify drm - * mst deallocation when link is no longer of MST type when uncommitting - * the stream so we will have more time to work on a proper solution. - * Ideally when dm_helpers_dp_mst_stop_top_mgr message is triggered, we - * should notify drm to do a complete "reset" of its states and stop - * calling further drm mst functions when link is no longer of an MST - * type. This could happen when we unplug an MST hubs/displays. When - * uncommit stream comes later after unplug, we should just reset - * hardware states only. - */ - adev->dm.dc->debug.temp_mst_deallocation_sequence = true; - if (adev->dm.dc->caps.dp_hdmi21_pcon_support) DRM_INFO("DP-HDMI FRL PCON supported\n"); diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c index c7a29bb737e2..e44ba5c1c48e 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c @@ -333,15 +333,14 @@ enum act_return_status dm_helpers_dp_mst_poll_for_allocation_change_trigger( return ACT_SUCCESS; } -bool dm_helpers_dp_mst_send_payload_allocation( +void dm_helpers_dp_mst_send_payload_allocation( struct dc_context *ctx, - const struct dc_stream_state *stream, - bool enable) + const struct dc_stream_state *stream) { struct amdgpu_dm_connector *aconnector; struct drm_dp_mst_topology_state *mst_state; struct drm_dp_mst_topology_mgr *mst_mgr; - struct drm_dp_mst_atomic_payload *new_payload, old_payload; + struct drm_dp_mst_atomic_payload *new_payload; enum mst_progress_status set_flag = MST_ALLOCATE_NEW_PAYLOAD; enum mst_progress_status clr_flag = MST_CLEAR_ALLOCATED_PAYLOAD; int ret = 0; @@ -349,25 +348,13 @@ bool dm_helpers_dp_mst_send_payload_allocation( aconnector = (struct amdgpu_dm_connector *)stream->dm_stream_context; if (!aconnector || !aconnector->mst_root) - return false; + return; mst_mgr = &aconnector->mst_root->mst_mgr; mst_state = to_drm_dp_mst_topology_state(mst_mgr->base.state); - new_payload = drm_atomic_get_mst_payload_state(mst_state, aconnector->mst_output_port); - if (!enable) { - set_flag = MST_CLEAR_ALLOCATED_PAYLOAD; - clr_flag = MST_ALLOCATE_NEW_PAYLOAD; - } - - if (enable) { - ret = drm_dp_add_payload_part2(mst_mgr, mst_state->base.state, new_payload); - } else { - dm_helpers_construct_old_payload(mst_mgr, mst_state, - new_payload, &old_payload); - drm_dp_remove_payload_part2(mst_mgr, mst_state, &old_payload, new_payload); - } + ret = drm_dp_add_payload_part2(mst_mgr, mst_state->base.state, new_payload); if (ret) { amdgpu_dm_set_mst_status(&aconnector->mst_status, @@ -378,10 +365,36 @@ bool dm_helpers_dp_mst_send_payload_allocation( amdgpu_dm_set_mst_status(&aconnector->mst_status, clr_flag, false); } - - return true; } +void dm_helpers_dp_mst_update_mst_mgr_for_deallocation( + struct dc_context *ctx, + const struct dc_stream_state *stream) +{ + struct amdgpu_dm_connector *aconnector; + struct drm_dp_mst_topology_state *mst_state; + struct drm_dp_mst_topology_mgr *mst_mgr; + struct drm_dp_mst_atomic_payload *new_payload, old_payload; + enum mst_progress_status set_flag = MST_CLEAR_ALLOCATED_PAYLOAD; + enum mst_progress_status clr_flag = MST_ALLOCATE_NEW_PAYLOAD; + + aconnector = (struct amdgpu_dm_connector *)stream->dm_stream_context; + + if (!aconnector || !aconnector->mst_root) + return; + + mst_mgr = &aconnector->mst_root->mst_mgr; + mst_state = to_drm_dp_mst_topology_state(mst_mgr->base.state); + new_payload = drm_atomic_get_mst_payload_state(mst_state, aconnector->mst_output_port); + dm_helpers_construct_old_payload(mst_mgr, mst_state, + new_payload, &old_payload); + + drm_dp_remove_payload_part2(mst_mgr, mst_state, &old_payload, new_payload); + + amdgpu_dm_set_mst_status(&aconnector->mst_status, set_flag, true); + amdgpu_dm_set_mst_status(&aconnector->mst_status, clr_flag, false); + } + void dm_dtn_log_begin(struct dc_context *ctx, struct dc_log_buffer_ctx *log_ctx) { diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h index 18b8d7f3f738..85771ef98cd7 100644 --- a/drivers/gpu/drm/amd/display/dc/dc.h +++ b/drivers/gpu/drm/amd/display/dc/dc.h @@ -956,7 +956,6 @@ struct dc_debug_options { unsigned int min_prefetch_in_strobe_ns; bool disable_unbounded_requesting; bool dig_fifo_off_in_blank; - bool temp_mst_deallocation_sequence; bool override_dispclk_programming; bool otg_crc_db; bool disallow_dispclk_dppclk_ds; diff --git a/drivers/gpu/drm/amd/display/dc/dm_helpers.h b/drivers/gpu/drm/amd/display/dc/dm_helpers.h index 7ce9a5b6c33b..6d7a15dcf8a7 100644 --- a/drivers/gpu/drm/amd/display/dc/dm_helpers.h +++ b/drivers/gpu/drm/amd/display/dc/dm_helpers.h @@ -103,10 +103,16 @@ enum act_return_status dm_helpers_dp_mst_poll_for_allocation_change_trigger( /* * Sends ALLOCATE_PAYLOAD message. */ -bool dm_helpers_dp_mst_send_payload_allocation( +void dm_helpers_dp_mst_send_payload_allocation( struct dc_context *ctx, - const struct dc_stream_state *stream, - bool enable); + const struct dc_stream_state *stream); + +/* + * Update mst manager relevant variables + */ +void dm_helpers_dp_mst_update_mst_mgr_for_deallocation( + struct dc_context *ctx, + const struct dc_stream_state *stream); bool dm_helpers_dp_mst_start_top_mgr( struct dc_context *ctx, diff --git a/drivers/gpu/drm/amd/display/dc/link/link_dpms.c b/drivers/gpu/drm/amd/display/dc/link/link_dpms.c index f8e01ca09d96..aa0a086aa7fc 100644 --- a/drivers/gpu/drm/amd/display/dc/link/link_dpms.c +++ b/drivers/gpu/drm/amd/display/dc/link/link_dpms.c @@ -1247,86 +1247,6 @@ static void remove_stream_from_alloc_table( } } -static enum dc_status deallocate_mst_payload_with_temp_drm_wa( - struct pipe_ctx *pipe_ctx) -{ - struct dc_stream_state *stream = pipe_ctx->stream; - struct dc_link *link = stream->link; - struct dc_dp_mst_stream_allocation_table proposed_table = {0}; - struct fixed31_32 avg_time_slots_per_mtp = dc_fixpt_from_int(0); - int i; - bool mst_mode = (link->type == dc_connection_mst_branch); - /* adjust for drm changes*/ - const struct link_hwss *link_hwss = get_link_hwss(link, &pipe_ctx->link_res); - const struct dc_link_settings empty_link_settings = {0}; - DC_LOGGER_INIT(link->ctx->logger); - - if (link_hwss->ext.set_throttled_vcp_size) - link_hwss->ext.set_throttled_vcp_size(pipe_ctx, avg_time_slots_per_mtp); - if (link_hwss->ext.set_hblank_min_symbol_width) - link_hwss->ext.set_hblank_min_symbol_width(pipe_ctx, - &empty_link_settings, - avg_time_slots_per_mtp); - - if (dm_helpers_dp_mst_write_payload_allocation_table( - stream->ctx, - stream, - &proposed_table, - false)) - update_mst_stream_alloc_table( - link, - pipe_ctx->stream_res.stream_enc, - pipe_ctx->stream_res.hpo_dp_stream_enc, - &proposed_table); - else - DC_LOG_WARNING("Failed to update" - "MST allocation table for" - "pipe idx:%d\n", - pipe_ctx->pipe_idx); - - DC_LOG_MST("%s" - "stream_count: %d: ", - __func__, - link->mst_stream_alloc_table.stream_count); - - for (i = 0; i < MAX_CONTROLLER_NUM; i++) { - DC_LOG_MST("stream_enc[%d]: %p " - "stream[%d].hpo_dp_stream_enc: %p " - "stream[%d].vcp_id: %d " - "stream[%d].slot_count: %d\n", - i, - (void *) link->mst_stream_alloc_table.stream_allocations[i].stream_enc, - i, - (void *) link->mst_stream_alloc_table.stream_allocations[i].hpo_dp_stream_enc, - i, - link->mst_stream_alloc_table.stream_allocations[i].vcp_id, - i, - link->mst_stream_alloc_table.stream_allocations[i].slot_count); - } - - if (link_hwss->ext.update_stream_allocation_table == NULL || - link_dp_get_encoding_format(&link->cur_link_settings) == DP_UNKNOWN_ENCODING) { - DC_LOG_DEBUG("Unknown encoding format\n"); - return DC_ERROR_UNEXPECTED; - } - - link_hwss->ext.update_stream_allocation_table(link, &pipe_ctx->link_res, - &link->mst_stream_alloc_table); - - if (mst_mode) { - dm_helpers_dp_mst_poll_for_allocation_change_trigger( - stream->ctx, - stream); - } - - dm_helpers_dp_mst_send_payload_allocation( - stream->ctx, - stream, - false); - - return DC_OK; -} - static enum dc_status deallocate_mst_payload(struct pipe_ctx *pipe_ctx) { struct dc_stream_state *stream = pipe_ctx->stream; @@ -1339,9 +1259,6 @@ static enum dc_status deallocate_mst_payload(struct pipe_ctx *pipe_ctx) const struct dc_link_settings empty_link_settings = {0}; DC_LOGGER_INIT(link->ctx->logger); - if (link->dc->debug.temp_mst_deallocation_sequence) - return deallocate_mst_payload_with_temp_drm_wa(pipe_ctx); - /* deallocate_mst_payload is called before disable link. When mode or * disable/enable monitor, new stream is created which is not in link * stream[] yet. For this, payload is not allocated yet, so de-alloc @@ -1414,16 +1331,14 @@ static enum dc_status deallocate_mst_payload(struct pipe_ctx *pipe_ctx) link_hwss->ext.update_stream_allocation_table(link, &pipe_ctx->link_res, &link->mst_stream_alloc_table); - if (mst_mode) { + if (mst_mode) dm_helpers_dp_mst_poll_for_allocation_change_trigger( stream->ctx, stream); - dm_helpers_dp_mst_send_payload_allocation( - stream->ctx, - stream, - false); - } + dm_helpers_dp_mst_update_mst_mgr_for_deallocation( + stream->ctx, + stream); return DC_OK; } @@ -1504,12 +1419,10 @@ static enum dc_status allocate_mst_payload(struct pipe_ctx *pipe_ctx) stream->ctx, stream); - if (ret != ACT_LINK_LOST) { + if (ret != ACT_LINK_LOST) dm_helpers_dp_mst_send_payload_allocation( stream->ctx, - stream, - true); - } + stream); /* slot X.Y for only current stream */ pbn_per_slot = get_pbn_per_slot(stream); @@ -1769,8 +1682,7 @@ enum dc_status link_reduce_mst_payload(struct pipe_ctx *pipe_ctx, uint32_t bw_in /* send ALLOCATE_PAYLOAD sideband message with updated pbn */ dm_helpers_dp_mst_send_payload_allocation( stream->ctx, - stream, - true); + stream); /* notify immediate branch device table update */ if (dm_helpers_dp_mst_write_payload_allocation_table( @@ -1899,8 +1811,7 @@ enum dc_status link_increase_mst_payload(struct pipe_ctx *pipe_ctx, uint32_t bw_ /* send ALLOCATE_PAYLOAD sideband message with updated pbn */ dm_helpers_dp_mst_send_payload_allocation( stream->ctx, - stream, - true); + stream); } /* increase throttled vcp size */ -- cgit From 5f2a404cbccec0c8d6635f0997cea2ac226d25d4 Mon Sep 17 00:00:00 2001 From: Dennis Chan Date: Tue, 31 Oct 2023 10:09:02 +0800 Subject: drm/amd/display: Disable Timing sync check in Full-Screen Video Case [why] If Panel max link off frame count is low, it will cause low residency for Replay, then Disabled timing sync check in Full screen Video Case. Reviewed-by: Robin Chen Acked-by: Hamza Mahfooz Signed-off-by: Dennis Chan Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dc_types.h | 66 ++++++++++++++++++------- drivers/gpu/drm/amd/display/dmub/inc/dmub_cmd.h | 9 ++-- 2 files changed, 51 insertions(+), 24 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/dc_types.h b/drivers/gpu/drm/amd/display/dc/dc_types.h index a2f6c994a2a9..7313cfe69498 100644 --- a/drivers/gpu/drm/amd/display/dc/dc_types.h +++ b/drivers/gpu/drm/amd/display/dc/dc_types.h @@ -1018,6 +1018,12 @@ enum replay_coasting_vtotal_type { PR_COASTING_TYPE_NUM, }; +enum replay_link_off_frame_count_level { + PR_LINK_OFF_FRAME_COUNT_FAIL = 0x0, + PR_LINK_OFF_FRAME_COUNT_GOOD = 0x2, + PR_LINK_OFF_FRAME_COUNT_BEST = 0x6, +}; + /* * This is general Interface for Replay to * set an 32 bit variable to dmub @@ -1041,26 +1047,48 @@ union replay_error_status { }; struct replay_config { - bool replay_supported; // Replay feature is supported - unsigned int replay_power_opt_supported; // Power opt flags that are supported - bool replay_smu_opt_supported; // SMU optimization is supported - unsigned int replay_enable_option; // Replay enablement option - uint32_t debug_flags; // Replay debug flags - bool replay_timing_sync_supported; // Replay desync is supported - bool force_disable_desync_error_check; // Replay desync is supported - bool received_desync_error_hpd; //Replay Received Desync Error HPD. - union replay_error_status replay_error_status; // Replay error status -}; - -/* Replay feature flags */ + /* Replay feature is supported */ + bool replay_supported; + /* Power opt flags that are supported */ + unsigned int replay_power_opt_supported; + /* SMU optimization is supported */ + bool replay_smu_opt_supported; + /* Replay enablement option */ + unsigned int replay_enable_option; + /* Replay debug flags */ + uint32_t debug_flags; + /* Replay sync is supported */ + bool replay_timing_sync_supported; + /* Replay Disable desync error check. */ + bool force_disable_desync_error_check; + /* Replay Received Desync Error HPD. */ + bool received_desync_error_hpd; + /* Replay feature is supported long vblank */ + bool replay_support_fast_resync_in_ultra_sleep_mode; + /* Replay error status */ + union replay_error_status replay_error_status; +}; + +/* Replay feature flags*/ struct replay_settings { - struct replay_config config; // Replay configuration - bool replay_feature_enabled; // Replay feature is ready for activating - bool replay_allow_active; // Replay is currently active - unsigned int replay_power_opt_active; // Power opt flags that are activated currently - bool replay_smu_opt_enable; // SMU optimization is enabled - uint16_t coasting_vtotal; // Current Coasting vtotal - uint16_t coasting_vtotal_table[PR_COASTING_TYPE_NUM]; // Coasting vtotal table + /* Replay configuration */ + struct replay_config config; + /* Replay feature is ready for activating */ + bool replay_feature_enabled; + /* Replay is currently active */ + bool replay_allow_active; + /* Replay is currently active */ + bool replay_allow_long_vblank; + /* Power opt flags that are activated currently */ + unsigned int replay_power_opt_active; + /* SMU optimization is enabled */ + bool replay_smu_opt_enable; + /* Current Coasting vtotal */ + uint16_t coasting_vtotal; + /* Coasting vtotal table */ + uint16_t coasting_vtotal_table[PR_COASTING_TYPE_NUM]; + /* Maximum link off frame count */ + enum replay_link_off_frame_count_level link_off_frame_count_level; }; /* To split out "global" and "per-panel" config settings. diff --git a/drivers/gpu/drm/amd/display/dmub/inc/dmub_cmd.h b/drivers/gpu/drm/amd/display/dmub/inc/dmub_cmd.h index d1becbb5aa29..a08073fc92ae 100644 --- a/drivers/gpu/drm/amd/display/dmub/inc/dmub_cmd.h +++ b/drivers/gpu/drm/amd/display/dmub/inc/dmub_cmd.h @@ -3056,15 +3056,14 @@ struct dmub_cmd_replay_set_timing_sync_data { * Currently the support is only for 0 or 1 */ uint8_t panel_inst; - /** - * Explicit padding to 4 byte boundary. + * REPLAY set_timing_sync */ - uint8_t pad[3]; + uint8_t timing_sync_supported; /** - * REPLAY set_timing_sync + * Explicit padding to 4 byte boundary. */ - bool timing_sync_supported; + uint8_t pad[2]; }; /** -- cgit From 8f3656ce65d6d550247a85fdb5c54a5b65cc2252 Mon Sep 17 00:00:00 2001 From: Alvin Lee Date: Thu, 9 Nov 2023 10:50:30 -0500 Subject: drm/amd/display: Enable SubVP on 1080p60 displays [Description] - Previously SubVP would never be selected on 1080p60 displays because it has too much vactive margin. However, implement a change to allow it like how 1440p60 is allowed. - Add a new struct such that we have a list of allowed modes for enabling subvp with vactive margin (currently 1080p60 and 1440p60) - Also ensure to block drr + vblank cases to prevent unexpected enablement of new display configs - Update SW cursor fallback for these new potential cases as well Reviewed-by: Samson Tam Acked-by: Hamza Mahfooz Signed-off-by: Alvin Lee Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc_resource.c | 2 +- .../amd/display/dc/dcn32/dcn32_resource_helpers.c | 32 +++++++++++++++-- .../gpu/drm/amd/display/dc/dml/dcn32/dcn32_fpu.c | 41 +++++++++++++--------- .../amd/display/dc/resource/dcn32/dcn32_resource.h | 10 ++++++ 4 files changed, 65 insertions(+), 20 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c index 84d632700949..f3a9fdd2340d 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c @@ -5316,7 +5316,7 @@ bool check_subvp_sw_cursor_fallback_req(const struct dc *dc, struct dc_stream_st if (dc->current_state->stream_count == 1 && stream->timing.v_addressable >= 2880 && ((stream->timing.pix_clk_100hz * 100) / stream->timing.v_total / stream->timing.h_total) < 120) return true; - else if (dc->current_state->stream_count > 1 && stream->timing.v_addressable >= 2160 && + else if (dc->current_state->stream_count > 1 && stream->timing.v_addressable >= 1080 && ((stream->timing.pix_clk_100hz * 100) / stream->timing.v_total / stream->timing.h_total) < 120) return true; diff --git a/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_resource_helpers.c b/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_resource_helpers.c index ef0a2b01734d..389ac7ae1154 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_resource_helpers.c +++ b/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_resource_helpers.c @@ -665,6 +665,30 @@ bool dcn32_check_native_scaling_for_res(struct pipe_ctx *pipe, unsigned int widt return is_native_scaling; } +/** + * disallow_subvp_in_active_plus_blank() - Function to determine disallowed subvp + drr/vblank configs + * + * @pipe: subvp pipe to be used for the subvp + drr/vblank config + * + * Since subvp is being enabled on more configs (such as 1080p60), we want + * to explicitly block any configs that we don't want to enable. We do not + * want to enable any 1080p60 (SubVP) + drr / vblank configs since these + * are already convered by FPO. + * + * Return: True if disallowed, false otherwise + */ +static bool disallow_subvp_in_active_plus_blank(struct pipe_ctx *pipe) +{ + bool disallow = false; + + if (resource_is_pipe_type(pipe, OPP_HEAD) && + resource_is_pipe_type(pipe, DPP_PIPE)) { + if (pipe->stream->timing.v_addressable == 1080 && pipe->stream->timing.h_addressable == 1920) + disallow = true; + } + return disallow; +} + /** * dcn32_subvp_drr_admissable() - Determine if SubVP + DRR config is admissible * @@ -688,6 +712,7 @@ bool dcn32_subvp_drr_admissable(struct dc *dc, struct dc_state *context) bool drr_pipe_found = false; bool drr_psr_capable = false; uint64_t refresh_rate = 0; + bool subvp_disallow = false; for (i = 0; i < dc->res_pool->pipe_count; i++) { struct pipe_ctx *pipe = &context->res_ctx.pipe_ctx[i]; @@ -697,6 +722,7 @@ bool dcn32_subvp_drr_admissable(struct dc *dc, struct dc_state *context) if (pipe->stream->mall_stream_config.type == SUBVP_MAIN) { subvp_count++; + subvp_disallow |= disallow_subvp_in_active_plus_blank(pipe); refresh_rate = (pipe->stream->timing.pix_clk_100hz * (uint64_t)100 + pipe->stream->timing.v_total * pipe->stream->timing.h_total - (uint64_t)1); refresh_rate = div_u64(refresh_rate, pipe->stream->timing.v_total); @@ -713,7 +739,7 @@ bool dcn32_subvp_drr_admissable(struct dc *dc, struct dc_state *context) } } - if (subvp_count == 1 && non_subvp_pipes == 1 && drr_pipe_found && !drr_psr_capable && + if (subvp_count == 1 && !subvp_disallow && non_subvp_pipes == 1 && drr_pipe_found && !drr_psr_capable && ((uint32_t)refresh_rate < 120)) result = true; @@ -746,6 +772,7 @@ bool dcn32_subvp_vblank_admissable(struct dc *dc, struct dc_state *context, int struct vba_vars_st *vba = &context->bw_ctx.dml.vba; bool vblank_psr_capable = false; uint64_t refresh_rate = 0; + bool subvp_disallow = false; for (i = 0; i < dc->res_pool->pipe_count; i++) { struct pipe_ctx *pipe = &context->res_ctx.pipe_ctx[i]; @@ -755,6 +782,7 @@ bool dcn32_subvp_vblank_admissable(struct dc *dc, struct dc_state *context, int if (pipe->stream->mall_stream_config.type == SUBVP_MAIN) { subvp_count++; + subvp_disallow |= disallow_subvp_in_active_plus_blank(pipe); refresh_rate = (pipe->stream->timing.pix_clk_100hz * (uint64_t)100 + pipe->stream->timing.v_total * pipe->stream->timing.h_total - (uint64_t)1); refresh_rate = div_u64(refresh_rate, pipe->stream->timing.v_total); @@ -772,7 +800,7 @@ bool dcn32_subvp_vblank_admissable(struct dc *dc, struct dc_state *context, int } if (subvp_count == 1 && non_subvp_pipes == 1 && !drr_pipe_found && !vblank_psr_capable && - ((uint32_t)refresh_rate < 120) && + ((uint32_t)refresh_rate < 120) && !subvp_disallow && vba->DRAMClockChangeSupport[vlevel][vba->maxMpcComb] == dm_dram_clock_change_vblank_w_mall_sub_vp) result = true; diff --git a/drivers/gpu/drm/amd/display/dc/dml/dcn32/dcn32_fpu.c b/drivers/gpu/drm/amd/display/dc/dml/dcn32/dcn32_fpu.c index 92e2ddc9ab7e..c4ffb4b92b56 100644 --- a/drivers/gpu/drm/amd/display/dc/dml/dcn32/dcn32_fpu.c +++ b/drivers/gpu/drm/amd/display/dc/dml/dcn32/dcn32_fpu.c @@ -45,6 +45,14 @@ static const struct subvp_high_refresh_list subvp_high_refresh_list = { {.width = 1920, .height = 1080, }}, }; +static const struct subvp_active_margin_list subvp_active_margin_list = { + .min_refresh = 55, + .max_refresh = 65, + .res = { + {.width = 2560, .height = 1440, }, + {.width = 1920, .height = 1080, }}, +}; + struct _vcs_dpi_ip_params_st dcn3_2_ip = { .gpuvm_enable = 0, .gpuvm_max_page_table_levels = 4, @@ -3295,25 +3303,24 @@ bool dcn32_allow_subvp_with_active_margin(struct pipe_ctx *pipe) { bool allow = false; uint32_t refresh_rate = 0; + uint32_t min_refresh = subvp_active_margin_list.min_refresh; + uint32_t max_refresh = subvp_active_margin_list.max_refresh; + uint32_t i; - /* Allow subvp on displays that have active margin for 2560x1440@60hz displays - * only for now. There must be no scaling as well. - * - * For now we only enable on 2560x1440@60hz displays to enable 4K60 + 1440p60 configs - * for p-state switching. - */ - if (pipe->stream && pipe->plane_state) { - refresh_rate = (pipe->stream->timing.pix_clk_100hz * 100 + - pipe->stream->timing.v_total * pipe->stream->timing.h_total - 1) - / (double)(pipe->stream->timing.v_total * pipe->stream->timing.h_total); - if (pipe->stream->timing.v_addressable == 1440 && - pipe->stream->timing.h_addressable == 2560 && - refresh_rate >= 55 && refresh_rate <= 65 && - pipe->plane_state->src_rect.height == 1440 && - pipe->plane_state->src_rect.width == 2560 && - pipe->plane_state->dst_rect.height == 1440 && - pipe->plane_state->dst_rect.width == 2560) + for (i = 0; i < SUBVP_ACTIVE_MARGIN_LIST_LEN; i++) { + uint32_t width = subvp_active_margin_list.res[i].width; + uint32_t height = subvp_active_margin_list.res[i].height; + + refresh_rate = (pipe->stream->timing.pix_clk_100hz * (uint64_t)100 + + pipe->stream->timing.v_total * pipe->stream->timing.h_total - (uint64_t)1); + refresh_rate = div_u64(refresh_rate, pipe->stream->timing.v_total); + refresh_rate = div_u64(refresh_rate, pipe->stream->timing.h_total); + + if (refresh_rate >= min_refresh && refresh_rate <= max_refresh && + dcn32_check_native_scaling_for_res(pipe, width, height)) { allow = true; + break; + } } return allow; } diff --git a/drivers/gpu/drm/amd/display/dc/resource/dcn32/dcn32_resource.h b/drivers/gpu/drm/amd/display/dc/resource/dcn32/dcn32_resource.h index b931008114c9..b2f20e6cfb38 100644 --- a/drivers/gpu/drm/amd/display/dc/resource/dcn32/dcn32_resource.h +++ b/drivers/gpu/drm/amd/display/dc/resource/dcn32/dcn32_resource.h @@ -39,6 +39,7 @@ #define DCN3_2_MBLK_HEIGHT_8BPE 64 #define DCN3_2_DCFCLK_DS_INIT_KHZ 10000 // Choose 10Mhz for init DCFCLK DS freq #define SUBVP_HIGH_REFRESH_LIST_LEN 4 +#define SUBVP_ACTIVE_MARGIN_LIST_LEN 2 #define DCN3_2_MAX_SUBVP_PIXEL_RATE_MHZ 1800 #define DCN3_2_VMIN_DISPCLK_HZ 717000000 @@ -57,6 +58,15 @@ struct subvp_high_refresh_list { } res[SUBVP_HIGH_REFRESH_LIST_LEN]; }; +struct subvp_active_margin_list { + int min_refresh; + int max_refresh; + struct { + int width; + int height; + } res[SUBVP_ACTIVE_MARGIN_LIST_LEN]; +}; + struct dcn32_resource_pool { struct resource_pool base; }; -- cgit From ee95135bfeecf67b313b5573054b03aa6dbc76f8 Mon Sep 17 00:00:00 2001 From: Li Ma Date: Tue, 21 Nov 2023 16:54:59 +0800 Subject: drm/amdgpu: add init_registers for nbio v7.11 enable init_registers callback func for nbio v7.11. Signed-off-by: Li Ma Reviewed-by: Yifan Zhang Acked-by: Alex Deucher Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/nbio_v7_11.c | 18 +++++++------- .../amd/include/asic_reg/nbio/nbio_7_11_0_offset.h | 2 ++ .../include/asic_reg/nbio/nbio_7_11_0_sh_mask.h | 29 ++++++++++++++++++++++ 3 files changed, 40 insertions(+), 9 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/nbio_v7_11.c b/drivers/gpu/drm/amd/amdgpu/nbio_v7_11.c index 676ab1d20d2f..1f52b4b1db03 100644 --- a/drivers/gpu/drm/amd/amdgpu/nbio_v7_11.c +++ b/drivers/gpu/drm/amd/amdgpu/nbio_v7_11.c @@ -259,17 +259,17 @@ const struct nbio_hdp_flush_reg nbio_v7_11_hdp_flush_reg = { static void nbio_v7_11_init_registers(struct amdgpu_device *adev) { -/* uint32_t def, data; + uint32_t def, data; + + def = data = RREG32_SOC15(NBIO, 0, regBIF_BIF256_CI256_RC3X4_USB4_PCIE_MST_CTRL_3); + data = REG_SET_FIELD(data, BIF_BIF256_CI256_RC3X4_USB4_PCIE_MST_CTRL_3, + CI_SWUS_MAX_READ_REQUEST_SIZE_MODE, 1); + data = REG_SET_FIELD(data, BIF_BIF256_CI256_RC3X4_USB4_PCIE_MST_CTRL_3, + CI_SWUS_MAX_READ_REQUEST_SIZE_PRIV, 1); - def = data = RREG32_SOC15(NBIO, 0, regBIF_BIF256_CI256_RC3X4_USB4_PCIE_MST_CTRL_3); - data = REG_SET_FIELD(data, BIF_BIF256_CI256_RC3X4_USB4_PCIE_MST_CTRL_3, - CI_SWUS_MAX_READ_REQUEST_SIZE_MODE, 1); - data = REG_SET_FIELD(data, BIF_BIF256_CI256_RC3X4_USB4_PCIE_MST_CTRL_3, - CI_SWUS_MAX_READ_REQUEST_SIZE_PRIV, 1); + if (def != data) + WREG32_SOC15(NBIO, 0, regBIF_BIF256_CI256_RC3X4_USB4_PCIE_MST_CTRL_3, data); - if (def != data) - WREG32_SOC15(NBIO, 0, regBIF_BIF256_CI256_RC3X4_USB4_PCIE_MST_CTRL_3, data); -*/ } static void nbio_v7_11_update_medium_grain_clock_gating(struct amdgpu_device *adev, diff --git a/drivers/gpu/drm/amd/include/asic_reg/nbio/nbio_7_11_0_offset.h b/drivers/gpu/drm/amd/include/asic_reg/nbio/nbio_7_11_0_offset.h index ff30f04be591..7ee3d291120d 100644 --- a/drivers/gpu/drm/amd/include/asic_reg/nbio/nbio_7_11_0_offset.h +++ b/drivers/gpu/drm/amd/include/asic_reg/nbio/nbio_7_11_0_offset.h @@ -781,6 +781,8 @@ #define regBIF_BIF256_CI256_RC3X4_USB4_PCIE_CNTL2_BASE_IDX 5 #define regBIF_BIF256_CI256_RC3X4_USB4_PCIE_TX_POWER_CTRL_1 0x420187 #define regBIF_BIF256_CI256_RC3X4_USB4_PCIE_TX_POWER_CTRL_1_BASE_IDX 5 +#define regBIF_BIF256_CI256_RC3X4_USB4_PCIE_MST_CTRL_3 0x4201c6 +#define regBIF_BIF256_CI256_RC3X4_USB4_PCIE_MST_CTRL_3_BASE_IDX 5 // addressBlock: nbio_nbif0_bif_cfg_dev0_rc_bifcfgdecp diff --git a/drivers/gpu/drm/amd/include/asic_reg/nbio/nbio_7_11_0_sh_mask.h b/drivers/gpu/drm/amd/include/asic_reg/nbio/nbio_7_11_0_sh_mask.h index 7f131999a263..eb8c556d9c93 100644 --- a/drivers/gpu/drm/amd/include/asic_reg/nbio/nbio_7_11_0_sh_mask.h +++ b/drivers/gpu/drm/amd/include/asic_reg/nbio/nbio_7_11_0_sh_mask.h @@ -24646,6 +24646,35 @@ //BIF_BIF256_CI256_RC3X4_USB4_PCIE_TX_POWER_CTRL_1 #define BIF_BIF256_CI256_RC3X4_USB4_PCIE_TX_POWER_CTRL_1__MST_MEM_LS_EN_MASK 0x00000001L #define BIF_BIF256_CI256_RC3X4_USB4_PCIE_TX_POWER_CTRL_1__REPLAY_MEM_LS_EN_MASK 0x00000008L +//BIF_BIF256_CI256_RC3X4_USB4_PCIE_MST_CTRL_3 +#define BIF_BIF256_CI256_RC3X4_USB4_PCIE_MST_CTRL_3__CI_SWUS_MAX_PAYLOAD_SIZE_MODE__SHIFT 0x8 +#define BIF_BIF256_CI256_RC3X4_USB4_PCIE_MST_CTRL_3__CI_SWUS_PRIV_MAX_PAYLOAD_SIZE__SHIFT 0x9 +#define BIF_BIF256_CI256_RC3X4_USB4_PCIE_MST_CTRL_3__CI_10BIT_TAG_EN_OVERRIDE__SHIFT 0xb +#define BIF_BIF256_CI256_RC3X4_USB4_PCIE_MST_CTRL_3__CI_SWUS_10BIT_TAG_EN_OVERRIDE__SHIFT 0xd +#define BIF_BIF256_CI256_RC3X4_USB4_PCIE_MST_CTRL_3__MST_DROP_SYNC_FLOOD_EN__SHIFT 0xf +#define BIF_BIF256_CI256_RC3X4_USB4_PCIE_MST_CTRL_3__CI_MAX_PAYLOAD_SIZE_MODE__SHIFT 0x10 +#define BIF_BIF256_CI256_RC3X4_USB4_PCIE_MST_CTRL_3__CI_PRIV_MAX_PAYLOAD_SIZE__SHIFT 0x11 +#define BIF_BIF256_CI256_RC3X4_USB4_PCIE_MST_CTRL_3__CI_MAX_READ_REQUEST_SIZE_MODE__SHIFT 0x14 +#define BIF_BIF256_CI256_RC3X4_USB4_PCIE_MST_CTRL_3__CI_PRIV_MAX_READ_REQUEST_SIZE__SHIFT 0x15 +#define BIF_BIF256_CI256_RC3X4_USB4_PCIE_MST_CTRL_3__CI_MAX_READ_SAFE_MODE__SHIFT 0x18 +#define BIF_BIF256_CI256_RC3X4_USB4_PCIE_MST_CTRL_3__CI_EXTENDED_TAG_EN_OVERRIDE__SHIFT 0x19 +#define BIF_BIF256_CI256_RC3X4_USB4_PCIE_MST_CTRL_3__CI_SWUS_MAX_READ_REQUEST_SIZE_MODE__SHIFT 0x1b +#define BIF_BIF256_CI256_RC3X4_USB4_PCIE_MST_CTRL_3__CI_SWUS_MAX_READ_REQUEST_SIZE_PRIV__SHIFT 0x1c +#define BIF_BIF256_CI256_RC3X4_USB4_PCIE_MST_CTRL_3__CI_SWUS_EXTENDED_TAG_EN_OVERRIDE__SHIFT 0x1e +#define BIF_BIF256_CI256_RC3X4_USB4_PCIE_MST_CTRL_3__CI_SWUS_MAX_PAYLOAD_SIZE_MODE_MASK 0x00000100L +#define BIF_BIF256_CI256_RC3X4_USB4_PCIE_MST_CTRL_3__CI_SWUS_PRIV_MAX_PAYLOAD_SIZE_MASK 0x00000600L +#define BIF_BIF256_CI256_RC3X4_USB4_PCIE_MST_CTRL_3__CI_10BIT_TAG_EN_OVERRIDE_MASK 0x00001800L +#define BIF_BIF256_CI256_RC3X4_USB4_PCIE_MST_CTRL_3__CI_SWUS_10BIT_TAG_EN_OVERRIDE_MASK 0x00006000L +#define BIF_BIF256_CI256_RC3X4_USB4_PCIE_MST_CTRL_3__MST_DROP_SYNC_FLOOD_EN_MASK 0x00008000L +#define BIF_BIF256_CI256_RC3X4_USB4_PCIE_MST_CTRL_3__CI_MAX_PAYLOAD_SIZE_MODE_MASK 0x00010000L +#define BIF_BIF256_CI256_RC3X4_USB4_PCIE_MST_CTRL_3__CI_PRIV_MAX_PAYLOAD_SIZE_MASK 0x000E0000L +#define BIF_BIF256_CI256_RC3X4_USB4_PCIE_MST_CTRL_3__CI_MAX_READ_REQUEST_SIZE_MODE_MASK 0x00100000L +#define BIF_BIF256_CI256_RC3X4_USB4_PCIE_MST_CTRL_3__CI_PRIV_MAX_READ_REQUEST_SIZE_MASK 0x00E00000L +#define BIF_BIF256_CI256_RC3X4_USB4_PCIE_MST_CTRL_3__CI_MAX_READ_SAFE_MODE_MASK 0x01000000L +#define BIF_BIF256_CI256_RC3X4_USB4_PCIE_MST_CTRL_3__CI_EXTENDED_TAG_EN_OVERRIDE_MASK 0x06000000L +#define BIF_BIF256_CI256_RC3X4_USB4_PCIE_MST_CTRL_3__CI_SWUS_MAX_READ_REQUEST_SIZE_MODE_MASK 0x08000000L +#define BIF_BIF256_CI256_RC3X4_USB4_PCIE_MST_CTRL_3__CI_SWUS_MAX_READ_REQUEST_SIZE_PRIV_MASK 0x30000000L +#define BIF_BIF256_CI256_RC3X4_USB4_PCIE_MST_CTRL_3__CI_SWUS_EXTENDED_TAG_EN_OVERRIDE_MASK 0xC0000000L // addressBlock: nbio_nbif0_bif_cfg_dev0_rc_bifcfgdecp //BIF_CFG_DEV0_RC0_VENDOR_ID -- cgit From 88f4b10a793262c4d6cf2566b1d210ec76f87867 Mon Sep 17 00:00:00 2001 From: Tim Huang Date: Tue, 21 Nov 2023 11:06:51 +0800 Subject: drm/amdgpu: fix memory overflow in the IB test MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fix a memory overflow issue in the gfx IB test for some ASICs. At least 20 bytes are needed for the IB test packet. v2: correct code indentation errors. (Christian) Signed-off-by: Tim Huang Reviewed-by: Yifan Zhang Reviewed-by: Christian König Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c | 2 +- drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c | 4 ++-- drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c | 4 ++-- drivers/gpu/drm/amd/amdgpu/gfx_v9_4_3.c | 4 ++-- 4 files changed, 7 insertions(+), 7 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c b/drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c index 40ce12323164..8ed4a6fb147a 100644 --- a/drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c @@ -427,7 +427,7 @@ static int gfx_v11_0_ring_test_ib(struct amdgpu_ring *ring, long timeout) adev->wb.wb[index] = cpu_to_le32(0xCAFEDEAD); cpu_ptr = &adev->wb.wb[index]; - r = amdgpu_ib_get(adev, NULL, 16, AMDGPU_IB_POOL_DIRECT, &ib); + r = amdgpu_ib_get(adev, NULL, 20, AMDGPU_IB_POOL_DIRECT, &ib); if (r) { DRM_ERROR("amdgpu: failed to get ib (%ld).\n", r); goto err1; diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c b/drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c index 885ebd703260..1943beb135c4 100644 --- a/drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c @@ -883,8 +883,8 @@ static int gfx_v8_0_ring_test_ib(struct amdgpu_ring *ring, long timeout) gpu_addr = adev->wb.gpu_addr + (index * 4); adev->wb.wb[index] = cpu_to_le32(0xCAFEDEAD); memset(&ib, 0, sizeof(ib)); - r = amdgpu_ib_get(adev, NULL, 16, - AMDGPU_IB_POOL_DIRECT, &ib); + + r = amdgpu_ib_get(adev, NULL, 20, AMDGPU_IB_POOL_DIRECT, &ib); if (r) goto err1; diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c b/drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c index e3ff6e46f3f7..69c500910746 100644 --- a/drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c @@ -1039,8 +1039,8 @@ static int gfx_v9_0_ring_test_ib(struct amdgpu_ring *ring, long timeout) gpu_addr = adev->wb.gpu_addr + (index * 4); adev->wb.wb[index] = cpu_to_le32(0xCAFEDEAD); memset(&ib, 0, sizeof(ib)); - r = amdgpu_ib_get(adev, NULL, 16, - AMDGPU_IB_POOL_DIRECT, &ib); + + r = amdgpu_ib_get(adev, NULL, 20, AMDGPU_IB_POOL_DIRECT, &ib); if (r) goto err1; diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v9_4_3.c b/drivers/gpu/drm/amd/amdgpu/gfx_v9_4_3.c index 21865668b787..00b21ece081f 100644 --- a/drivers/gpu/drm/amd/amdgpu/gfx_v9_4_3.c +++ b/drivers/gpu/drm/amd/amdgpu/gfx_v9_4_3.c @@ -297,8 +297,8 @@ static int gfx_v9_4_3_ring_test_ib(struct amdgpu_ring *ring, long timeout) gpu_addr = adev->wb.gpu_addr + (index * 4); adev->wb.wb[index] = cpu_to_le32(0xCAFEDEAD); memset(&ib, 0, sizeof(ib)); - r = amdgpu_ib_get(adev, NULL, 16, - AMDGPU_IB_POOL_DIRECT, &ib); + + r = amdgpu_ib_get(adev, NULL, 20, AMDGPU_IB_POOL_DIRECT, &ib); if (r) goto err1; -- cgit From c4b8394e76adba4f50a3c2696c75b214a291e24a Mon Sep 17 00:00:00 2001 From: Meenakshikumar Somasundaram Date: Thu, 9 Nov 2023 00:04:36 -0500 Subject: drm/amd/display: Fix tiled display misalignment [Why] When otg workaround is applied during clock update, otgs of tiled display went out of sync. [How] To call dc_trigger_sync() after clock update to sync otgs again. Reviewed-by: Nicholas Kazlauskas Acked-by: Hamza Mahfooz Signed-off-by: Meenakshikumar Somasundaram Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c index 76b47f178127..eab713c0da0d 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc.c @@ -1964,6 +1964,10 @@ static enum dc_status dc_commit_state_no_check(struct dc *dc, struct dc_state *c wait_for_no_pipes_pending(dc, context); /* pplib is notified if disp_num changed */ dc->hwss.optimize_bandwidth(dc, context); + /* Need to do otg sync again as otg could be out of sync due to otg + * workaround applied during clock update + */ + dc_trigger_sync(dc, context); } if (dc->hwss.update_dsc_pg) -- cgit From fcd94ef1b3e78f7dc76309c9611915018d2d62a3 Mon Sep 17 00:00:00 2001 From: Nicholas Kazlauskas Date: Wed, 8 Nov 2023 10:55:53 -0500 Subject: drm/amd/display: Remove min_dst_y_next_start check for Z8 [Why] Flickering occurs on DRR supported panels when engaged in DRR due to min_dst_y_next becoming larger than the frame size itself. [How] In general, we should be able to enter Z8 when this is engaged but it might be a net power loss even if the calculation wasn't bugged. Don't support enabling Z8 during the DRR region. Cc: stable@vger.kernel.org # 6.1+ Reviewed-by: Syed Hassan Acked-by: Hamza Mahfooz Signed-off-by: Nicholas Kazlauskas Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dml/dcn20/dcn20_fpu.c | 15 +-------------- 1 file changed, 1 insertion(+), 14 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/dml/dcn20/dcn20_fpu.c b/drivers/gpu/drm/amd/display/dc/dml/dcn20/dcn20_fpu.c index 7fc8b18096ba..ec77b2b41ba3 100644 --- a/drivers/gpu/drm/amd/display/dc/dml/dcn20/dcn20_fpu.c +++ b/drivers/gpu/drm/amd/display/dc/dml/dcn20/dcn20_fpu.c @@ -950,10 +950,8 @@ static enum dcn_zstate_support_state decide_zstate_support(struct dc *dc, struc { int plane_count; int i; - unsigned int min_dst_y_next_start_us; plane_count = 0; - min_dst_y_next_start_us = 0; for (i = 0; i < dc->res_pool->pipe_count; i++) { if (context->res_ctx.pipe_ctx[i].plane_state) plane_count++; @@ -975,26 +973,15 @@ static enum dcn_zstate_support_state decide_zstate_support(struct dc *dc, struc else if (context->stream_count == 1 && context->streams[0]->signal == SIGNAL_TYPE_EDP) { struct dc_link *link = context->streams[0]->sink->link; struct dc_stream_status *stream_status = &context->stream_status[0]; - struct dc_stream_state *current_stream = context->streams[0]; int minmum_z8_residency = dc->debug.minimum_z8_residency_time > 0 ? dc->debug.minimum_z8_residency_time : 1000; bool allow_z8 = context->bw_ctx.dml.vba.StutterPeriod > (double)minmum_z8_residency; bool is_pwrseq0 = link->link_index == 0; - bool isFreesyncVideo; - - isFreesyncVideo = current_stream->adjust.v_total_min == current_stream->adjust.v_total_max; - isFreesyncVideo = isFreesyncVideo && current_stream->timing.v_total < current_stream->adjust.v_total_min; - for (i = 0; i < dc->res_pool->pipe_count; i++) { - if (context->res_ctx.pipe_ctx[i].stream == current_stream && isFreesyncVideo) { - min_dst_y_next_start_us = context->res_ctx.pipe_ctx[i].dlg_regs.min_dst_y_next_start_us; - break; - } - } /* Don't support multi-plane configurations */ if (stream_status->plane_count > 1) return DCN_ZSTATE_SUPPORT_DISALLOW; - if (is_pwrseq0 && (context->bw_ctx.dml.vba.StutterPeriod > 5000.0 || min_dst_y_next_start_us > 5000)) + if (is_pwrseq0 && context->bw_ctx.dml.vba.StutterPeriod > 5000.0) return DCN_ZSTATE_SUPPORT_ALLOW; else if (is_pwrseq0 && link->psr_settings.psr_version == DC_PSR_VERSION_1 && !link->panel_config.psr.disable_psr) return allow_z8 ? DCN_ZSTATE_SUPPORT_ALLOW_Z8_Z10_ONLY : DCN_ZSTATE_SUPPORT_ALLOW_Z10_ONLY; -- cgit From d642b0100bf8c95e88e8396b7191b35807dabb4c Mon Sep 17 00:00:00 2001 From: Nicholas Kazlauskas Date: Wed, 8 Nov 2023 10:59:00 -0500 Subject: drm/amd/display: Update min Z8 residency time to 2100 for DCN314 [Why] Some panels with residency period of 2054 exhibit flickering with Z8 at the end of the frame. [How] As a workaround, increase the limit to block these panels. Cc: stable@vger.kernel.org # 6.1+ Reviewed-by: Syed Hassan Acked-by: Hamza Mahfooz Signed-off-by: Nicholas Kazlauskas Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/resource/dcn314/dcn314_resource.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/display/dc/resource/dcn314/dcn314_resource.c b/drivers/gpu/drm/amd/display/dc/resource/dcn314/dcn314_resource.c index 677361d74a4e..c97391edb5ff 100644 --- a/drivers/gpu/drm/amd/display/dc/resource/dcn314/dcn314_resource.c +++ b/drivers/gpu/drm/amd/display/dc/resource/dcn314/dcn314_resource.c @@ -871,7 +871,7 @@ static const struct dc_plane_cap plane_cap = { static const struct dc_debug_options debug_defaults_drv = { .disable_z10 = false, .enable_z9_disable_interface = true, - .minimum_z8_residency_time = 2000, + .minimum_z8_residency_time = 2100, .psr_skip_crtc_disable = true, .replay_skip_crtc_disabled = true, .disable_dmcu = true, -- cgit From a5e90392fdda05ce842810bb749f3d210c3ffc65 Mon Sep 17 00:00:00 2001 From: Gabe Teeger Date: Thu, 9 Nov 2023 17:53:49 -0500 Subject: Revert "drm/amd/display: Enable CM low mem power optimization" This reverts commit fcfc6ceec3ebb725a0d6381a1120e7cd546e1df4. [why] Flickering observed. Regression search pointed to this being the offending commit. Reviewed-by: Charlene Liu Reviewed-by: Yihan Zhu Acked-by: Hamza Mahfooz Signed-off-by: Gabe Teeger Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dcn32/dcn32_mpc.c | 13 +++++-------- .../gpu/drm/amd/display/dc/resource/dcn35/dcn35_resource.c | 2 +- 2 files changed, 6 insertions(+), 9 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_mpc.c b/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_mpc.c index 1a2adb354718..994b21ed272f 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_mpc.c +++ b/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_mpc.c @@ -71,24 +71,21 @@ void mpc32_power_on_blnd_lut( { struct dcn30_mpc *mpc30 = TO_DCN30_MPC(mpc); -/* if (mpc->ctx->dc->debug.enable_mem_low_power.bits.cm) { if (power_on) { REG_UPDATE(MPCC_MCM_MEM_PWR_CTRL[mpcc_id], MPCC_MCM_1DLUT_MEM_PWR_FORCE, 0); REG_WAIT(MPCC_MCM_MEM_PWR_CTRL[mpcc_id], MPCC_MCM_1DLUT_MEM_PWR_STATE, 0, 1, 5); } else if (!mpc->ctx->dc->debug.disable_mem_low_power) { - //TODO: change to mpc - dpp_base->ctx->dc->optimized_required = true; - dpp_base->deferred_reg_writes.bits.disable_blnd_lut = true; + ASSERT(false); + /* TODO: change to mpc + * dpp_base->ctx->dc->optimized_required = true; + * dpp_base->deferred_reg_writes.bits.disable_blnd_lut = true; + */ } } else { REG_SET(MPCC_MCM_MEM_PWR_CTRL[mpcc_id], 0, MPCC_MCM_1DLUT_MEM_PWR_FORCE, power_on == true ? 0 : 1); } -*/ - - REG_SET(MPCC_MCM_MEM_PWR_CTRL[mpcc_id], 0, - MPCC_MCM_1DLUT_MEM_PWR_FORCE, power_on == true ? 0 : 1); } static enum dc_lut_mode mpc32_get_post1dlut_current(struct mpc *mpc, uint32_t mpcc_id) diff --git a/drivers/gpu/drm/amd/display/dc/resource/dcn35/dcn35_resource.c b/drivers/gpu/drm/amd/display/dc/resource/dcn35/dcn35_resource.c index 0d5a03c6d812..53eefba0b9dc 100644 --- a/drivers/gpu/drm/amd/display/dc/resource/dcn35/dcn35_resource.c +++ b/drivers/gpu/drm/amd/display/dc/resource/dcn35/dcn35_resource.c @@ -736,7 +736,7 @@ static const struct dc_debug_options debug_defaults_drv = { .i2c = true, .dmcu = false, // This is previously known to cause hang on S3 cycles if enabled .dscl = true, - .cm = true, + .cm = false, .mpc = true, .optc = true, .vpg = true, -- cgit From 0e6a12884ca72520b195d95f1fa1bf790678cd6c Mon Sep 17 00:00:00 2001 From: Prike Liang Date: Wed, 8 Nov 2023 14:38:29 +0800 Subject: drm/amdgpu: correct the amdgpu runtime dereference usage count Fix the amdgpu runpm dereference usage count. Signed-off-by: Prike Liang Reviewed-by: Alex Deucher Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_display.c | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_display.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_display.c index 0cacd0b9f8be..b8fbe97efe1d 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_display.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_display.c @@ -340,14 +340,11 @@ int amdgpu_display_crtc_set_config(struct drm_mode_set *set, adev->have_disp_power_ref = true; return ret; } - /* if we have no active crtcs, then drop the power ref - * we got before + /* if we have no active crtcs, then go to + * drop the power ref we got before */ - if (!active && adev->have_disp_power_ref) { - pm_runtime_put_autosuspend(dev->dev); + if (!active && adev->have_disp_power_ref) adev->have_disp_power_ref = false; - } - out: /* drop the power reference we got coming in here */ pm_runtime_put_autosuspend(dev->dev); -- cgit From f4233efedf75572e49efd08202b1a07196949b4a Mon Sep 17 00:00:00 2001 From: Alvin Lee Date: Thu, 9 Nov 2023 18:08:17 -0500 Subject: drm/amd/display: If P-State is supported try SubVP for smaller vlevel [Description] - To reduce vlevel further, we can try to apply subvp on configs that already support p-state since the natural p-state support may not allow for DPM0. - Add code to try subvp to reduce UCLK DPM level further if already supported, but don't use subvp if it does not optimize the DPM level even lower Reviewed-by: Samson Tam Acked-by: Hamza Mahfooz Signed-off-by: Alvin Lee Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dml/dcn32/dcn32_fpu.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/display/dc/dml/dcn32/dcn32_fpu.c b/drivers/gpu/drm/amd/display/dc/dml/dcn32/dcn32_fpu.c index c4ffb4b92b56..26411d4e9730 100644 --- a/drivers/gpu/drm/amd/display/dc/dml/dcn32/dcn32_fpu.c +++ b/drivers/gpu/drm/amd/display/dc/dml/dcn32/dcn32_fpu.c @@ -1416,6 +1416,7 @@ static void dcn32_full_validate_bw_helper(struct dc *dc, unsigned int dc_pipe_idx = 0; int i = 0; bool found_supported_config = false; + int vlevel_temp = 0; dc_assert_fp_enabled(); @@ -1448,13 +1449,15 @@ static void dcn32_full_validate_bw_helper(struct dc *dc, */ if (!dc->debug.force_disable_subvp && !dc->caps.dmub_caps.gecc_enable && dcn32_all_pipes_have_stream_and_plane(dc, context) && !dcn32_mpo_in_use(context) && !dcn32_any_surfaces_rotated(dc, context) && !is_test_pattern_enabled(context) && - (*vlevel == context->bw_ctx.dml.soc.num_states || + (*vlevel == context->bw_ctx.dml.soc.num_states || (vba->DRAMSpeedPerState[*vlevel] != vba->DRAMSpeedPerState[0] && + vba->DRAMClockChangeSupport[*vlevel][vba->maxMpcComb] != dm_dram_clock_change_unsupported) || vba->DRAMClockChangeSupport[*vlevel][vba->maxMpcComb] == dm_dram_clock_change_unsupported || dc->debug.force_subvp_mclk_switch)) { dcn32_merge_pipes_for_subvp(dc, context); memset(merge, 0, MAX_PIPES * sizeof(bool)); + vlevel_temp = *vlevel; /* to re-initialize viewport after the pipe merge */ for (i = 0; i < dc->res_pool->pipe_count; i++) { struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i]; @@ -1523,6 +1526,9 @@ static void dcn32_full_validate_bw_helper(struct dc *dc, } } + if (vba->DRAMSpeedPerState[*vlevel] >= vba->DRAMSpeedPerState[vlevel_temp]) + found_supported_config = false; + // If SubVP pipe config is unsupported (or cannot be used for UCLK switching) // remove phantom pipes and repopulate dml pipes if (!found_supported_config) { -- cgit From 5a9a2cc8ae1889c4002850b00fd4fd9691dfac4e Mon Sep 17 00:00:00 2001 From: Zhongwei Date: Wed, 8 Nov 2023 16:34:36 +0800 Subject: drm/amd/display: force toggle rate wa for first link training for a retimer [WHY] Handover from DMUB to driver does not perform link rate toggle. It might cause link training failure for boot up. [HOW] Force toggle rate wa for first link train. link->vendor_specific_lttpr_link_rate_wa should be zero then. Cc: stable@vger.kernel.org # 6.1+ Reviewed-by: Michael Strauss Acked-by: Hamza Mahfooz Signed-off-by: Zhongwei Signed-off-by: Alex Deucher --- .../dc/link/protocols/link_dp_training_fixed_vs_pe_retimer.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_training_fixed_vs_pe_retimer.c b/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_training_fixed_vs_pe_retimer.c index fd8f6f198146..68096d12f52f 100644 --- a/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_training_fixed_vs_pe_retimer.c +++ b/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_training_fixed_vs_pe_retimer.c @@ -115,7 +115,7 @@ static enum link_training_result perform_fixed_vs_pe_nontransparent_training_seq lt_settings->cr_pattern_time = 16000; /* Fixed VS/PE specific: Toggle link rate */ - apply_toggle_rate_wa = (link->vendor_specific_lttpr_link_rate_wa == target_rate); + apply_toggle_rate_wa = ((link->vendor_specific_lttpr_link_rate_wa == target_rate) || (link->vendor_specific_lttpr_link_rate_wa == 0)); target_rate = get_dpcd_link_rate(<_settings->link_settings); toggle_rate = (target_rate == 0x6) ? 0xA : 0x6; @@ -271,7 +271,7 @@ enum link_training_result dp_perform_fixed_vs_pe_training_sequence_legacy( /* Vendor specific: Toggle link rate */ toggle_rate = (rate == 0x6) ? 0xA : 0x6; - if (link->vendor_specific_lttpr_link_rate_wa == rate) { + if (link->vendor_specific_lttpr_link_rate_wa == rate || link->vendor_specific_lttpr_link_rate_wa == 0) { core_link_write_dpcd( link, DP_LINK_BW_SET, @@ -617,7 +617,7 @@ enum link_training_result dp_perform_fixed_vs_pe_training_sequence( /* Vendor specific: Toggle link rate */ toggle_rate = (rate == 0x6) ? 0xA : 0x6; - if (link->vendor_specific_lttpr_link_rate_wa == rate) { + if (link->vendor_specific_lttpr_link_rate_wa == rate || link->vendor_specific_lttpr_link_rate_wa == 0) { core_link_write_dpcd( link, DP_LINK_BW_SET, -- cgit From 3d0fe49454652117522f60bfbefb978ba0e5300b Mon Sep 17 00:00:00 2001 From: Parandhaman K Date: Thu, 9 Nov 2023 15:52:17 +0530 Subject: drm/amd/display: Refactor OPTC into component folder [why] Move all optc files to unique folder optc. [how] creating optc repo in dc, and moved the dcnxx_optc.c and .h files into corresponding new folders inside the optc and cleared the linkage errors by adding relative paths in the Makefile.template. Reviewed-by: Martin Leung Acked-by: Hamza Mahfooz Signed-off-by: Parandhaman K Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/Makefile | 1 + drivers/gpu/drm/amd/display/dc/Makefile | 2 +- drivers/gpu/drm/amd/display/dc/dcn10/Makefile | 2 +- .../display/dc/dcn10/dcn10_hw_sequencer_debug.c | 2 +- drivers/gpu/drm/amd/display/dc/dcn10/dcn10_optc.c | 1621 -------------------- drivers/gpu/drm/amd/display/dc/dcn10/dcn10_optc.h | 599 -------- drivers/gpu/drm/amd/display/dc/dcn20/Makefile | 2 +- drivers/gpu/drm/amd/display/dc/dcn20/dcn20_optc.c | 587 ------- drivers/gpu/drm/amd/display/dc/dcn20/dcn20_optc.h | 124 -- drivers/gpu/drm/amd/display/dc/dcn201/Makefile | 2 +- .../gpu/drm/amd/display/dc/dcn201/dcn201_optc.c | 202 --- .../gpu/drm/amd/display/dc/dcn201/dcn201_optc.h | 74 - drivers/gpu/drm/amd/display/dc/dcn30/Makefile | 1 - drivers/gpu/drm/amd/display/dc/dcn30/dcn30_optc.c | 393 ----- drivers/gpu/drm/amd/display/dc/dcn30/dcn30_optc.h | 359 ----- drivers/gpu/drm/amd/display/dc/dcn301/Makefile | 3 +- .../gpu/drm/amd/display/dc/dcn301/dcn301_optc.c | 185 --- .../gpu/drm/amd/display/dc/dcn301/dcn301_optc.h | 36 - drivers/gpu/drm/amd/display/dc/dcn31/Makefile | 2 +- drivers/gpu/drm/amd/display/dc/dcn31/dcn31_optc.c | 310 ---- drivers/gpu/drm/amd/display/dc/dcn31/dcn31_optc.h | 267 ---- drivers/gpu/drm/amd/display/dc/dcn314/Makefile | 2 +- .../gpu/drm/amd/display/dc/dcn314/dcn314_optc.c | 273 ---- .../gpu/drm/amd/display/dc/dcn314/dcn314_optc.h | 255 --- drivers/gpu/drm/amd/display/dc/dcn32/Makefile | 6 +- drivers/gpu/drm/amd/display/dc/dcn32/dcn32_optc.c | 357 ----- drivers/gpu/drm/amd/display/dc/dcn32/dcn32_optc.h | 187 --- drivers/gpu/drm/amd/display/dc/dcn35/Makefile | 2 +- drivers/gpu/drm/amd/display/dc/dcn35/dcn35_optc.c | 290 ---- drivers/gpu/drm/amd/display/dc/dcn35/dcn35_optc.h | 74 - drivers/gpu/drm/amd/display/dc/optc/Makefile | 108 ++ .../gpu/drm/amd/display/dc/optc/dcn10/dcn10_optc.c | 1621 ++++++++++++++++++++ .../gpu/drm/amd/display/dc/optc/dcn10/dcn10_optc.h | 599 ++++++++ .../gpu/drm/amd/display/dc/optc/dcn20/dcn20_optc.c | 587 +++++++ .../gpu/drm/amd/display/dc/optc/dcn20/dcn20_optc.h | 124 ++ .../drm/amd/display/dc/optc/dcn201/dcn201_optc.c | 202 +++ .../drm/amd/display/dc/optc/dcn201/dcn201_optc.h | 74 + .../gpu/drm/amd/display/dc/optc/dcn30/dcn30_optc.c | 393 +++++ .../gpu/drm/amd/display/dc/optc/dcn30/dcn30_optc.h | 359 +++++ .../drm/amd/display/dc/optc/dcn301/dcn301_optc.c | 185 +++ .../drm/amd/display/dc/optc/dcn301/dcn301_optc.h | 36 + .../gpu/drm/amd/display/dc/optc/dcn31/dcn31_optc.c | 310 ++++ .../gpu/drm/amd/display/dc/optc/dcn31/dcn31_optc.h | 267 ++++ .../drm/amd/display/dc/optc/dcn314/dcn314_optc.c | 273 ++++ .../drm/amd/display/dc/optc/dcn314/dcn314_optc.h | 255 +++ .../gpu/drm/amd/display/dc/optc/dcn32/dcn32_optc.c | 357 +++++ .../gpu/drm/amd/display/dc/optc/dcn32/dcn32_optc.h | 187 +++ .../gpu/drm/amd/display/dc/optc/dcn35/dcn35_optc.c | 290 ++++ .../gpu/drm/amd/display/dc/optc/dcn35/dcn35_optc.h | 74 + 49 files changed, 6314 insertions(+), 6207 deletions(-) delete mode 100644 drivers/gpu/drm/amd/display/dc/dcn10/dcn10_optc.c delete mode 100644 drivers/gpu/drm/amd/display/dc/dcn10/dcn10_optc.h delete mode 100644 drivers/gpu/drm/amd/display/dc/dcn20/dcn20_optc.c delete mode 100644 drivers/gpu/drm/amd/display/dc/dcn20/dcn20_optc.h delete mode 100644 drivers/gpu/drm/amd/display/dc/dcn201/dcn201_optc.c delete mode 100644 drivers/gpu/drm/amd/display/dc/dcn201/dcn201_optc.h delete mode 100644 drivers/gpu/drm/amd/display/dc/dcn30/dcn30_optc.c delete mode 100644 drivers/gpu/drm/amd/display/dc/dcn30/dcn30_optc.h delete mode 100644 drivers/gpu/drm/amd/display/dc/dcn301/dcn301_optc.c delete mode 100644 drivers/gpu/drm/amd/display/dc/dcn301/dcn301_optc.h delete mode 100644 drivers/gpu/drm/amd/display/dc/dcn31/dcn31_optc.c delete mode 100644 drivers/gpu/drm/amd/display/dc/dcn31/dcn31_optc.h delete mode 100644 drivers/gpu/drm/amd/display/dc/dcn314/dcn314_optc.c delete mode 100644 drivers/gpu/drm/amd/display/dc/dcn314/dcn314_optc.h delete mode 100644 drivers/gpu/drm/amd/display/dc/dcn32/dcn32_optc.c delete mode 100644 drivers/gpu/drm/amd/display/dc/dcn32/dcn32_optc.h delete mode 100644 drivers/gpu/drm/amd/display/dc/dcn35/dcn35_optc.c delete mode 100644 drivers/gpu/drm/amd/display/dc/dcn35/dcn35_optc.h create mode 100644 drivers/gpu/drm/amd/display/dc/optc/Makefile create mode 100644 drivers/gpu/drm/amd/display/dc/optc/dcn10/dcn10_optc.c create mode 100644 drivers/gpu/drm/amd/display/dc/optc/dcn10/dcn10_optc.h create mode 100644 drivers/gpu/drm/amd/display/dc/optc/dcn20/dcn20_optc.c create mode 100644 drivers/gpu/drm/amd/display/dc/optc/dcn20/dcn20_optc.h create mode 100644 drivers/gpu/drm/amd/display/dc/optc/dcn201/dcn201_optc.c create mode 100644 drivers/gpu/drm/amd/display/dc/optc/dcn201/dcn201_optc.h create mode 100644 drivers/gpu/drm/amd/display/dc/optc/dcn30/dcn30_optc.c create mode 100644 drivers/gpu/drm/amd/display/dc/optc/dcn30/dcn30_optc.h create mode 100644 drivers/gpu/drm/amd/display/dc/optc/dcn301/dcn301_optc.c create mode 100644 drivers/gpu/drm/amd/display/dc/optc/dcn301/dcn301_optc.h create mode 100644 drivers/gpu/drm/amd/display/dc/optc/dcn31/dcn31_optc.c create mode 100644 drivers/gpu/drm/amd/display/dc/optc/dcn31/dcn31_optc.h create mode 100644 drivers/gpu/drm/amd/display/dc/optc/dcn314/dcn314_optc.c create mode 100644 drivers/gpu/drm/amd/display/dc/optc/dcn314/dcn314_optc.h create mode 100644 drivers/gpu/drm/amd/display/dc/optc/dcn32/dcn32_optc.c create mode 100644 drivers/gpu/drm/amd/display/dc/optc/dcn32/dcn32_optc.h create mode 100644 drivers/gpu/drm/amd/display/dc/optc/dcn35/dcn35_optc.c create mode 100644 drivers/gpu/drm/amd/display/dc/optc/dcn35/dcn35_optc.h diff --git a/drivers/gpu/drm/amd/display/Makefile b/drivers/gpu/drm/amd/display/Makefile index 7b0959da2cac..92a5c5efcf92 100644 --- a/drivers/gpu/drm/amd/display/Makefile +++ b/drivers/gpu/drm/amd/display/Makefile @@ -32,6 +32,7 @@ subdir-ccflags-y += -I$(FULL_AMD_DISPLAY_PATH)/dc/clk_mgr subdir-ccflags-y += -I$(FULL_AMD_DISPLAY_PATH)/dc/hwss subdir-ccflags-y += -I$(FULL_AMD_DISPLAY_PATH)/dc/resource subdir-ccflags-y += -I$(FULL_AMD_DISPLAY_PATH)/dc/dsc +subdir-ccflags-y += -I$(FULL_AMD_DISPLAY_PATH)/dc/optc subdir-ccflags-y += -I$(FULL_AMD_DISPLAY_PATH)/modules/inc subdir-ccflags-y += -I$(FULL_AMD_DISPLAY_PATH)/modules/freesync subdir-ccflags-y += -I$(FULL_AMD_DISPLAY_PATH)/modules/color diff --git a/drivers/gpu/drm/amd/display/dc/Makefile b/drivers/gpu/drm/amd/display/dc/Makefile index ab51a065cf0e..390e7a99be54 100644 --- a/drivers/gpu/drm/amd/display/dc/Makefile +++ b/drivers/gpu/drm/amd/display/dc/Makefile @@ -22,7 +22,7 @@ # # Makefile for Display Core (dc) component. -DC_LIBS = basics bios dml clk_mgr dce gpio hwss irq link virtual dsc resource +DC_LIBS = basics bios dml clk_mgr dce gpio hwss irq link virtual dsc resource optc ifdef CONFIG_DRM_AMD_DC_FP diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/Makefile b/drivers/gpu/drm/amd/display/dc/dcn10/Makefile index 1eb7418ced3a..0dd62934a18c 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/Makefile +++ b/drivers/gpu/drm/amd/display/dc/dcn10/Makefile @@ -24,7 +24,7 @@ DCN10 = dcn10_init.o dcn10_ipp.o \ dcn10_hw_sequencer_debug.o \ - dcn10_dpp.o dcn10_opp.o dcn10_optc.o \ + dcn10_dpp.o dcn10_opp.o \ dcn10_hubp.o dcn10_mpc.o \ dcn10_dpp_dscl.o dcn10_dpp_cm.o dcn10_cm_common.o \ dcn10_hubbub.o dcn10_stream_encoder.o dcn10_link_encoder.o diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer_debug.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer_debug.c index 92fdab731f4a..9033b39e0e0c 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer_debug.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer_debug.c @@ -32,7 +32,7 @@ #include "dce/dce_hwseq.h" #include "abm.h" #include "dmcu.h" -#include "dcn10_optc.h" +#include "dcn10/dcn10_optc.h" #include "dcn10/dcn10_dpp.h" #include "dcn10/dcn10_mpc.h" #include "timing_generator.h" diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_optc.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_optc.c deleted file mode 100644 index 0e8f4f36c87c..000000000000 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_optc.c +++ /dev/null @@ -1,1621 +0,0 @@ -/* - * Copyright 2012-15 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 "reg_helper.h" -#include "dcn10_optc.h" -#include "dc.h" -#include "dc_trace.h" - -#define REG(reg)\ - optc1->tg_regs->reg - -#define CTX \ - optc1->base.ctx - -#undef FN -#define FN(reg_name, field_name) \ - optc1->tg_shift->field_name, optc1->tg_mask->field_name - -#define STATIC_SCREEN_EVENT_MASK_RANGETIMING_DOUBLE_BUFFER_UPDATE_EN 0x100 - -/** - * apply_front_porch_workaround() - This is a workaround for a bug that has - * existed since R5xx and has not been fixed - * keep Front porch at minimum 2 for Interlaced - * mode or 1 for progressive. - * - * @timing: Timing parameters used to configure DCN blocks. - */ -static void apply_front_porch_workaround(struct dc_crtc_timing *timing) -{ - if (timing->flags.INTERLACE == 1) { - if (timing->v_front_porch < 2) - timing->v_front_porch = 2; - } else { - if (timing->v_front_porch < 1) - timing->v_front_porch = 1; - } -} - -void optc1_program_global_sync( - struct timing_generator *optc, - int vready_offset, - int vstartup_start, - int vupdate_offset, - int vupdate_width) -{ - struct optc *optc1 = DCN10TG_FROM_TG(optc); - - optc1->vready_offset = vready_offset; - optc1->vstartup_start = vstartup_start; - optc1->vupdate_offset = vupdate_offset; - optc1->vupdate_width = vupdate_width; - - if (optc1->vstartup_start == 0) { - BREAK_TO_DEBUGGER(); - return; - } - - REG_SET(OTG_VSTARTUP_PARAM, 0, - VSTARTUP_START, optc1->vstartup_start); - - REG_SET_2(OTG_VUPDATE_PARAM, 0, - VUPDATE_OFFSET, optc1->vupdate_offset, - VUPDATE_WIDTH, optc1->vupdate_width); - - REG_SET(OTG_VREADY_PARAM, 0, - VREADY_OFFSET, optc1->vready_offset); -} - -static void optc1_disable_stereo(struct timing_generator *optc) -{ - struct optc *optc1 = DCN10TG_FROM_TG(optc); - - REG_SET(OTG_STEREO_CONTROL, 0, - OTG_STEREO_EN, 0); - - REG_SET_2(OTG_3D_STRUCTURE_CONTROL, 0, - OTG_3D_STRUCTURE_EN, 0, - OTG_3D_STRUCTURE_STEREO_SEL_OVR, 0); -} - -void optc1_setup_vertical_interrupt0( - struct timing_generator *optc, - uint32_t start_line, - uint32_t end_line) -{ - struct optc *optc1 = DCN10TG_FROM_TG(optc); - - REG_SET_2(OTG_VERTICAL_INTERRUPT0_POSITION, 0, - OTG_VERTICAL_INTERRUPT0_LINE_START, start_line, - OTG_VERTICAL_INTERRUPT0_LINE_END, end_line); -} - -void optc1_setup_vertical_interrupt1( - struct timing_generator *optc, - uint32_t start_line) -{ - struct optc *optc1 = DCN10TG_FROM_TG(optc); - - REG_SET(OTG_VERTICAL_INTERRUPT1_POSITION, 0, - OTG_VERTICAL_INTERRUPT1_LINE_START, start_line); -} - -void optc1_setup_vertical_interrupt2( - struct timing_generator *optc, - uint32_t start_line) -{ - struct optc *optc1 = DCN10TG_FROM_TG(optc); - - REG_SET(OTG_VERTICAL_INTERRUPT2_POSITION, 0, - OTG_VERTICAL_INTERRUPT2_LINE_START, start_line); -} - -/** - * optc1_program_timing() - used by mode timing set Program - * CRTC Timing Registers - OTG_H_*, - * OTG_V_*, Pixel repetition. - * Including SYNC. Call BIOS command table to program Timings. - * - * @optc: timing_generator instance. - * @dc_crtc_timing: Timing parameters used to configure DCN blocks. - * @vready_offset: Vready's starting position. - * @vstartup_start: Vstartup period. - * @vupdate_offset: Vupdate starting position. - * @vupdate_width: Vupdate duration. - * @signal: DC signal types. - * @use_vbios: to program timings from BIOS command table. - * - */ -void optc1_program_timing( - struct timing_generator *optc, - const struct dc_crtc_timing *dc_crtc_timing, - int vready_offset, - int vstartup_start, - int vupdate_offset, - int vupdate_width, - const enum signal_type signal, - bool use_vbios) -{ - struct dc_crtc_timing patched_crtc_timing; - uint32_t asic_blank_end; - uint32_t asic_blank_start; - uint32_t v_total; - uint32_t v_sync_end; - uint32_t h_sync_polarity, v_sync_polarity; - uint32_t start_point = 0; - uint32_t field_num = 0; - enum h_timing_div_mode h_div = H_TIMING_NO_DIV; - - struct optc *optc1 = DCN10TG_FROM_TG(optc); - - optc1->signal = signal; - optc1->vready_offset = vready_offset; - optc1->vstartup_start = vstartup_start; - optc1->vupdate_offset = vupdate_offset; - optc1->vupdate_width = vupdate_width; - patched_crtc_timing = *dc_crtc_timing; - apply_front_porch_workaround(&patched_crtc_timing); - optc1->orginal_patched_timing = patched_crtc_timing; - - /* Load horizontal timing */ - - /* CRTC_H_TOTAL = vesa.h_total - 1 */ - REG_SET(OTG_H_TOTAL, 0, - OTG_H_TOTAL, patched_crtc_timing.h_total - 1); - - /* h_sync_start = 0, h_sync_end = vesa.h_sync_width */ - REG_UPDATE_2(OTG_H_SYNC_A, - OTG_H_SYNC_A_START, 0, - OTG_H_SYNC_A_END, patched_crtc_timing.h_sync_width); - - /* blank_start = line end - front porch */ - asic_blank_start = patched_crtc_timing.h_total - - patched_crtc_timing.h_front_porch; - - /* blank_end = blank_start - active */ - asic_blank_end = asic_blank_start - - patched_crtc_timing.h_border_right - - patched_crtc_timing.h_addressable - - patched_crtc_timing.h_border_left; - - REG_UPDATE_2(OTG_H_BLANK_START_END, - OTG_H_BLANK_START, asic_blank_start, - OTG_H_BLANK_END, asic_blank_end); - - /* h_sync polarity */ - h_sync_polarity = patched_crtc_timing.flags.HSYNC_POSITIVE_POLARITY ? - 0 : 1; - - REG_UPDATE(OTG_H_SYNC_A_CNTL, - OTG_H_SYNC_A_POL, h_sync_polarity); - - v_total = patched_crtc_timing.v_total - 1; - - REG_SET(OTG_V_TOTAL, 0, - OTG_V_TOTAL, v_total); - - /* In case of V_TOTAL_CONTROL is on, make sure OTG_V_TOTAL_MAX and - * OTG_V_TOTAL_MIN are equal to V_TOTAL. - */ - optc->funcs->set_vtotal_min_max(optc, v_total, v_total); - - /* v_sync_start = 0, v_sync_end = v_sync_width */ - v_sync_end = patched_crtc_timing.v_sync_width; - - REG_UPDATE_2(OTG_V_SYNC_A, - OTG_V_SYNC_A_START, 0, - OTG_V_SYNC_A_END, v_sync_end); - - /* blank_start = frame end - front porch */ - asic_blank_start = patched_crtc_timing.v_total - - patched_crtc_timing.v_front_porch; - - /* blank_end = blank_start - active */ - asic_blank_end = asic_blank_start - - patched_crtc_timing.v_border_bottom - - patched_crtc_timing.v_addressable - - patched_crtc_timing.v_border_top; - - REG_UPDATE_2(OTG_V_BLANK_START_END, - OTG_V_BLANK_START, asic_blank_start, - OTG_V_BLANK_END, asic_blank_end); - - /* v_sync polarity */ - v_sync_polarity = patched_crtc_timing.flags.VSYNC_POSITIVE_POLARITY ? - 0 : 1; - - REG_UPDATE(OTG_V_SYNC_A_CNTL, - OTG_V_SYNC_A_POL, v_sync_polarity); - - if (optc1->signal == SIGNAL_TYPE_DISPLAY_PORT || - optc1->signal == SIGNAL_TYPE_DISPLAY_PORT_MST || - optc1->signal == SIGNAL_TYPE_EDP) { - start_point = 1; - if (patched_crtc_timing.flags.INTERLACE == 1) - field_num = 1; - } - - /* Interlace */ - if (REG(OTG_INTERLACE_CONTROL)) { - if (patched_crtc_timing.flags.INTERLACE == 1) - REG_UPDATE(OTG_INTERLACE_CONTROL, - OTG_INTERLACE_ENABLE, 1); - else - REG_UPDATE(OTG_INTERLACE_CONTROL, - OTG_INTERLACE_ENABLE, 0); - } - - /* VTG enable set to 0 first VInit */ - REG_UPDATE(CONTROL, - VTG0_ENABLE, 0); - - /* original code is using VTG offset to address OTG reg, seems wrong */ - REG_UPDATE_2(OTG_CONTROL, - OTG_START_POINT_CNTL, start_point, - OTG_FIELD_NUMBER_CNTL, field_num); - - optc->funcs->program_global_sync(optc, - vready_offset, - vstartup_start, - vupdate_offset, - vupdate_width); - - optc->funcs->set_vtg_params(optc, dc_crtc_timing, true); - - /* TODO - * patched_crtc_timing.flags.HORZ_COUNT_BY_TWO == 1 - * program_horz_count_by_2 - * for DVI 30bpp mode, 0 otherwise - * program_horz_count_by_2(optc, &patched_crtc_timing); - */ - - /* Enable stereo - only when we need to pack 3D frame. Other types - * of stereo handled in explicit call - */ - - if (optc1_is_two_pixels_per_containter(&patched_crtc_timing) || optc1->opp_count == 2) - h_div = H_TIMING_DIV_BY2; - - if (REG(OPTC_DATA_FORMAT_CONTROL) && optc1->tg_mask->OPTC_DATA_FORMAT != 0) { - uint32_t data_fmt = 0; - - if (patched_crtc_timing.pixel_encoding == PIXEL_ENCODING_YCBCR422) - data_fmt = 1; - else if (patched_crtc_timing.pixel_encoding == PIXEL_ENCODING_YCBCR420) - data_fmt = 2; - - REG_UPDATE(OPTC_DATA_FORMAT_CONTROL, OPTC_DATA_FORMAT, data_fmt); - } - - if (optc1->tg_mask->OTG_H_TIMING_DIV_MODE != 0) { - if (optc1->opp_count == 4) - h_div = H_TIMING_DIV_BY4; - - REG_UPDATE(OTG_H_TIMING_CNTL, - OTG_H_TIMING_DIV_MODE, h_div); - } else { - REG_UPDATE(OTG_H_TIMING_CNTL, - OTG_H_TIMING_DIV_BY2, h_div); - } -} - -/** - * optc1_set_vtg_params - Set Vertical Timing Generator (VTG) parameters - * - * @optc: timing_generator struct used to extract the optc parameters - * @dc_crtc_timing: Timing parameters configured - * @program_fp2: Boolean value indicating if FP2 will be programmed or not - * - * OTG is responsible for generating the global sync signals, including - * vertical timing information for each HUBP in the dcfclk domain. Each VTG is - * associated with one OTG that provides HUBP with vertical timing information - * (i.e., there is 1:1 correspondence between OTG and VTG). This function is - * responsible for setting the OTG parameters to the VTG during the pipe - * programming. - */ -void optc1_set_vtg_params(struct timing_generator *optc, - const struct dc_crtc_timing *dc_crtc_timing, bool program_fp2) -{ - struct dc_crtc_timing patched_crtc_timing; - uint32_t asic_blank_end; - uint32_t v_init; - uint32_t v_fp2 = 0; - int32_t vertical_line_start; - - struct optc *optc1 = DCN10TG_FROM_TG(optc); - - patched_crtc_timing = *dc_crtc_timing; - apply_front_porch_workaround(&patched_crtc_timing); - - /* VCOUNT_INIT is the start of blank */ - v_init = patched_crtc_timing.v_total - patched_crtc_timing.v_front_porch; - - /* end of blank = v_init - active */ - asic_blank_end = v_init - - patched_crtc_timing.v_border_bottom - - patched_crtc_timing.v_addressable - - patched_crtc_timing.v_border_top; - - /* if VSTARTUP is before VSYNC, FP2 is the offset, otherwise 0 */ - vertical_line_start = asic_blank_end - optc1->vstartup_start + 1; - if (vertical_line_start < 0) - v_fp2 = -vertical_line_start; - - /* Interlace */ - if (REG(OTG_INTERLACE_CONTROL)) { - if (patched_crtc_timing.flags.INTERLACE == 1) { - v_init = v_init / 2; - if ((optc1->vstartup_start/2)*2 > asic_blank_end) - v_fp2 = v_fp2 / 2; - } - } - - if (program_fp2) - REG_UPDATE_2(CONTROL, - VTG0_FP2, v_fp2, - VTG0_VCOUNT_INIT, v_init); - else - REG_UPDATE(CONTROL, VTG0_VCOUNT_INIT, v_init); -} - -void optc1_set_blank_data_double_buffer(struct timing_generator *optc, bool enable) -{ - struct optc *optc1 = DCN10TG_FROM_TG(optc); - - uint32_t blank_data_double_buffer_enable = enable ? 1 : 0; - - REG_UPDATE(OTG_DOUBLE_BUFFER_CONTROL, - OTG_BLANK_DATA_DOUBLE_BUFFER_EN, blank_data_double_buffer_enable); -} - -/** - * optc1_set_timing_double_buffer() - DRR double buffering control - * - * Sets double buffer point for V_TOTAL, H_TOTAL, VTOTAL_MIN, - * VTOTAL_MAX, VTOTAL_MIN_SEL and VTOTAL_MAX_SEL registers. - * - * @optc: timing_generator instance. - * @enable: Enable DRR double buffering control if true, disable otherwise. - * - * Options: any time, start of frame, dp start of frame (range timing) - */ -void optc1_set_timing_double_buffer(struct timing_generator *optc, bool enable) -{ - struct optc *optc1 = DCN10TG_FROM_TG(optc); - uint32_t mode = enable ? 2 : 0; - - REG_UPDATE(OTG_DOUBLE_BUFFER_CONTROL, - OTG_RANGE_TIMING_DBUF_UPDATE_MODE, mode); -} - -/** - * optc1_unblank_crtc() - Call ASIC Control Object to UnBlank CRTC. - * - * @optc: timing_generator instance. - */ -static void optc1_unblank_crtc(struct timing_generator *optc) -{ - struct optc *optc1 = DCN10TG_FROM_TG(optc); - - REG_UPDATE_2(OTG_BLANK_CONTROL, - OTG_BLANK_DATA_EN, 0, - OTG_BLANK_DE_MODE, 0); - - /* W/A for automated testing - * Automated testing will fail underflow test as there - * sporadic underflows which occur during the optc blank - * sequence. As a w/a, clear underflow on unblank. - * This prevents the failure, but will not mask actual - * underflow that affect real use cases. - */ - optc1_clear_optc_underflow(optc); -} - -/** - * optc1_blank_crtc() - Call ASIC Control Object to Blank CRTC. - * - * @optc: timing_generator instance. - */ - -static void optc1_blank_crtc(struct timing_generator *optc) -{ - struct optc *optc1 = DCN10TG_FROM_TG(optc); - - REG_UPDATE_2(OTG_BLANK_CONTROL, - OTG_BLANK_DATA_EN, 1, - OTG_BLANK_DE_MODE, 0); - - optc1_set_blank_data_double_buffer(optc, false); -} - -void optc1_set_blank(struct timing_generator *optc, - bool enable_blanking) -{ - if (enable_blanking) - optc1_blank_crtc(optc); - else - optc1_unblank_crtc(optc); -} - -bool optc1_is_blanked(struct timing_generator *optc) -{ - struct optc *optc1 = DCN10TG_FROM_TG(optc); - uint32_t blank_en; - uint32_t blank_state; - - REG_GET_2(OTG_BLANK_CONTROL, - OTG_BLANK_DATA_EN, &blank_en, - OTG_CURRENT_BLANK_STATE, &blank_state); - - return blank_en && blank_state; -} - -void optc1_enable_optc_clock(struct timing_generator *optc, bool enable) -{ - struct optc *optc1 = DCN10TG_FROM_TG(optc); - - if (enable) { - REG_UPDATE_2(OPTC_INPUT_CLOCK_CONTROL, - OPTC_INPUT_CLK_EN, 1, - OPTC_INPUT_CLK_GATE_DIS, 1); - - REG_WAIT(OPTC_INPUT_CLOCK_CONTROL, - OPTC_INPUT_CLK_ON, 1, - 1, 1000); - - /* Enable clock */ - REG_UPDATE_2(OTG_CLOCK_CONTROL, - OTG_CLOCK_EN, 1, - OTG_CLOCK_GATE_DIS, 1); - REG_WAIT(OTG_CLOCK_CONTROL, - OTG_CLOCK_ON, 1, - 1, 1000); - } else { - - //last chance to clear underflow, otherwise, it will always there due to clock is off. - if (optc->funcs->is_optc_underflow_occurred(optc) == true) - optc->funcs->clear_optc_underflow(optc); - - REG_UPDATE_2(OTG_CLOCK_CONTROL, - OTG_CLOCK_GATE_DIS, 0, - OTG_CLOCK_EN, 0); - - REG_UPDATE_2(OPTC_INPUT_CLOCK_CONTROL, - OPTC_INPUT_CLK_GATE_DIS, 0, - OPTC_INPUT_CLK_EN, 0); - } -} - -/** - * optc1_enable_crtc() - Enable CRTC - call ASIC Control Object to enable Timing generator. - * - * @optc: timing_generator instance. - */ -static bool optc1_enable_crtc(struct timing_generator *optc) -{ - /* TODO FPGA wait for answer - * OTG_MASTER_UPDATE_MODE != CRTC_MASTER_UPDATE_MODE - * OTG_MASTER_UPDATE_LOCK != CRTC_MASTER_UPDATE_LOCK - */ - struct optc *optc1 = DCN10TG_FROM_TG(optc); - - /* opp instance for OTG. For DCN1.0, ODM is remoed. - * OPP and OPTC should 1:1 mapping - */ - REG_UPDATE(OPTC_DATA_SOURCE_SELECT, - OPTC_SRC_SEL, optc->inst); - - /* VTG enable first is for HW workaround */ - REG_UPDATE(CONTROL, - VTG0_ENABLE, 1); - - REG_SEQ_START(); - - /* Enable CRTC */ - REG_UPDATE_2(OTG_CONTROL, - OTG_DISABLE_POINT_CNTL, 3, - OTG_MASTER_EN, 1); - - REG_SEQ_SUBMIT(); - REG_SEQ_WAIT_DONE(); - - return true; -} - -/* disable_crtc - call ASIC Control Object to disable Timing generator. */ -bool optc1_disable_crtc(struct timing_generator *optc) -{ - struct optc *optc1 = DCN10TG_FROM_TG(optc); - - /* disable otg request until end of the first line - * in the vertical blank region - */ - REG_UPDATE_2(OTG_CONTROL, - OTG_DISABLE_POINT_CNTL, 3, - OTG_MASTER_EN, 0); - - REG_UPDATE(CONTROL, - VTG0_ENABLE, 0); - - /* CRTC disabled, so disable clock. */ - REG_WAIT(OTG_CLOCK_CONTROL, - OTG_BUSY, 0, - 1, 100000); - - return true; -} - - -void optc1_program_blank_color( - struct timing_generator *optc, - const struct tg_color *black_color) -{ - struct optc *optc1 = DCN10TG_FROM_TG(optc); - - REG_SET_3(OTG_BLACK_COLOR, 0, - OTG_BLACK_COLOR_B_CB, black_color->color_b_cb, - OTG_BLACK_COLOR_G_Y, black_color->color_g_y, - OTG_BLACK_COLOR_R_CR, black_color->color_r_cr); -} - -bool optc1_validate_timing( - struct timing_generator *optc, - const struct dc_crtc_timing *timing) -{ - uint32_t v_blank; - uint32_t h_blank; - uint32_t min_v_blank; - struct optc *optc1 = DCN10TG_FROM_TG(optc); - - ASSERT(timing != NULL); - - v_blank = (timing->v_total - timing->v_addressable - - timing->v_border_top - timing->v_border_bottom); - - h_blank = (timing->h_total - timing->h_addressable - - timing->h_border_right - - timing->h_border_left); - - if (timing->timing_3d_format != TIMING_3D_FORMAT_NONE && - timing->timing_3d_format != TIMING_3D_FORMAT_HW_FRAME_PACKING && - timing->timing_3d_format != TIMING_3D_FORMAT_TOP_AND_BOTTOM && - timing->timing_3d_format != TIMING_3D_FORMAT_SIDE_BY_SIDE && - timing->timing_3d_format != TIMING_3D_FORMAT_FRAME_ALTERNATE && - timing->timing_3d_format != TIMING_3D_FORMAT_INBAND_FA) - return false; - - /* Temporarily blocking interlacing mode until it's supported */ - if (timing->flags.INTERLACE == 1) - return false; - - /* Check maximum number of pixels supported by Timing Generator - * (Currently will never fail, in order to fail needs display which - * needs more than 8192 horizontal and - * more than 8192 vertical total pixels) - */ - if (timing->h_total > optc1->max_h_total || - timing->v_total > optc1->max_v_total) - return false; - - - if (h_blank < optc1->min_h_blank) - return false; - - if (timing->h_sync_width < optc1->min_h_sync_width || - timing->v_sync_width < optc1->min_v_sync_width) - return false; - - min_v_blank = timing->flags.INTERLACE?optc1->min_v_blank_interlace:optc1->min_v_blank; - - if (v_blank < min_v_blank) - return false; - - return true; - -} - -/* - * get_vblank_counter - * - * @brief - * Get counter for vertical blanks. use register CRTC_STATUS_FRAME_COUNT which - * holds the counter of frames. - * - * @param - * struct timing_generator *optc - [in] timing generator which controls the - * desired CRTC - * - * @return - * Counter of frames, which should equal to number of vblanks. - */ -uint32_t optc1_get_vblank_counter(struct timing_generator *optc) -{ - struct optc *optc1 = DCN10TG_FROM_TG(optc); - uint32_t frame_count; - - REG_GET(OTG_STATUS_FRAME_COUNT, - OTG_FRAME_COUNT, &frame_count); - - return frame_count; -} - -void optc1_lock(struct timing_generator *optc) -{ - struct optc *optc1 = DCN10TG_FROM_TG(optc); - - REG_SET(OTG_GLOBAL_CONTROL0, 0, - OTG_MASTER_UPDATE_LOCK_SEL, optc->inst); - REG_SET(OTG_MASTER_UPDATE_LOCK, 0, - OTG_MASTER_UPDATE_LOCK, 1); - - REG_WAIT(OTG_MASTER_UPDATE_LOCK, - UPDATE_LOCK_STATUS, 1, - 1, 10); - - TRACE_OPTC_LOCK_UNLOCK_STATE(optc1, optc->inst, true); -} - -void optc1_unlock(struct timing_generator *optc) -{ - struct optc *optc1 = DCN10TG_FROM_TG(optc); - - REG_SET(OTG_MASTER_UPDATE_LOCK, 0, - OTG_MASTER_UPDATE_LOCK, 0); - - TRACE_OPTC_LOCK_UNLOCK_STATE(optc1, optc->inst, false); -} - -void optc1_get_position(struct timing_generator *optc, - struct crtc_position *position) -{ - struct optc *optc1 = DCN10TG_FROM_TG(optc); - - REG_GET_2(OTG_STATUS_POSITION, - OTG_HORZ_COUNT, &position->horizontal_count, - OTG_VERT_COUNT, &position->vertical_count); - - REG_GET(OTG_NOM_VERT_POSITION, - OTG_VERT_COUNT_NOM, &position->nominal_vcount); -} - -bool optc1_is_counter_moving(struct timing_generator *optc) -{ - struct crtc_position position1, position2; - - optc->funcs->get_position(optc, &position1); - optc->funcs->get_position(optc, &position2); - - if (position1.horizontal_count == position2.horizontal_count && - position1.vertical_count == position2.vertical_count) - return false; - else - return true; -} - -bool optc1_did_triggered_reset_occur( - struct timing_generator *optc) -{ - struct optc *optc1 = DCN10TG_FROM_TG(optc); - uint32_t occurred_force, occurred_vsync; - - REG_GET(OTG_FORCE_COUNT_NOW_CNTL, - OTG_FORCE_COUNT_NOW_OCCURRED, &occurred_force); - - REG_GET(OTG_VERT_SYNC_CONTROL, - OTG_FORCE_VSYNC_NEXT_LINE_OCCURRED, &occurred_vsync); - - return occurred_vsync != 0 || occurred_force != 0; -} - -void optc1_disable_reset_trigger(struct timing_generator *optc) -{ - struct optc *optc1 = DCN10TG_FROM_TG(optc); - - REG_WRITE(OTG_TRIGA_CNTL, 0); - - REG_SET(OTG_FORCE_COUNT_NOW_CNTL, 0, - OTG_FORCE_COUNT_NOW_CLEAR, 1); - - REG_SET(OTG_VERT_SYNC_CONTROL, 0, - OTG_FORCE_VSYNC_NEXT_LINE_CLEAR, 1); -} - -void optc1_enable_reset_trigger(struct timing_generator *optc, int source_tg_inst) -{ - struct optc *optc1 = DCN10TG_FROM_TG(optc); - uint32_t falling_edge; - - REG_GET(OTG_V_SYNC_A_CNTL, - OTG_V_SYNC_A_POL, &falling_edge); - - if (falling_edge) - REG_SET_3(OTG_TRIGA_CNTL, 0, - /* vsync signal from selected OTG pipe based - * on OTG_TRIG_SOURCE_PIPE_SELECT setting - */ - OTG_TRIGA_SOURCE_SELECT, 20, - OTG_TRIGA_SOURCE_PIPE_SELECT, source_tg_inst, - /* always detect falling edge */ - OTG_TRIGA_FALLING_EDGE_DETECT_CNTL, 1); - else - REG_SET_3(OTG_TRIGA_CNTL, 0, - /* vsync signal from selected OTG pipe based - * on OTG_TRIG_SOURCE_PIPE_SELECT setting - */ - OTG_TRIGA_SOURCE_SELECT, 20, - OTG_TRIGA_SOURCE_PIPE_SELECT, source_tg_inst, - /* always detect rising edge */ - OTG_TRIGA_RISING_EDGE_DETECT_CNTL, 1); - - REG_SET(OTG_FORCE_COUNT_NOW_CNTL, 0, - /* force H count to H_TOTAL and V count to V_TOTAL in - * progressive mode and V_TOTAL-1 in interlaced mode - */ - OTG_FORCE_COUNT_NOW_MODE, 2); -} - -void optc1_enable_crtc_reset( - struct timing_generator *optc, - int source_tg_inst, - struct crtc_trigger_info *crtc_tp) -{ - struct optc *optc1 = DCN10TG_FROM_TG(optc); - uint32_t falling_edge = 0; - uint32_t rising_edge = 0; - - switch (crtc_tp->event) { - - case CRTC_EVENT_VSYNC_RISING: - rising_edge = 1; - break; - - case CRTC_EVENT_VSYNC_FALLING: - falling_edge = 1; - break; - } - - REG_SET_4(OTG_TRIGA_CNTL, 0, - /* vsync signal from selected OTG pipe based - * on OTG_TRIG_SOURCE_PIPE_SELECT setting - */ - OTG_TRIGA_SOURCE_SELECT, 20, - OTG_TRIGA_SOURCE_PIPE_SELECT, source_tg_inst, - /* always detect falling edge */ - OTG_TRIGA_RISING_EDGE_DETECT_CNTL, rising_edge, - OTG_TRIGA_FALLING_EDGE_DETECT_CNTL, falling_edge); - - switch (crtc_tp->delay) { - case TRIGGER_DELAY_NEXT_LINE: - REG_SET(OTG_VERT_SYNC_CONTROL, 0, - OTG_AUTO_FORCE_VSYNC_MODE, 1); - break; - case TRIGGER_DELAY_NEXT_PIXEL: - REG_SET(OTG_FORCE_COUNT_NOW_CNTL, 0, - /* force H count to H_TOTAL and V count to V_TOTAL in - * progressive mode and V_TOTAL-1 in interlaced mode - */ - OTG_FORCE_COUNT_NOW_MODE, 2); - break; - } -} - -void optc1_wait_for_state(struct timing_generator *optc, - enum crtc_state state) -{ - struct optc *optc1 = DCN10TG_FROM_TG(optc); - - switch (state) { - case CRTC_STATE_VBLANK: - REG_WAIT(OTG_STATUS, - OTG_V_BLANK, 1, - 1, 100000); /* 1 vupdate at 10hz */ - break; - - case CRTC_STATE_VACTIVE: - REG_WAIT(OTG_STATUS, - OTG_V_ACTIVE_DISP, 1, - 1, 100000); /* 1 vupdate at 10hz */ - break; - - default: - break; - } -} - -void optc1_set_early_control( - struct timing_generator *optc, - uint32_t early_cntl) -{ - /* asic design change, do not need this control - * empty for share caller logic - */ -} - - -void optc1_set_static_screen_control( - struct timing_generator *optc, - uint32_t event_triggers, - uint32_t num_frames) -{ - struct optc *optc1 = DCN10TG_FROM_TG(optc); - - // By register spec, it only takes 8 bit value - if (num_frames > 0xFF) - num_frames = 0xFF; - - /* Bit 8 is no longer applicable in RV for PSR case, - * set bit 8 to 0 if given - */ - if ((event_triggers & STATIC_SCREEN_EVENT_MASK_RANGETIMING_DOUBLE_BUFFER_UPDATE_EN) - != 0) - event_triggers = event_triggers & - ~STATIC_SCREEN_EVENT_MASK_RANGETIMING_DOUBLE_BUFFER_UPDATE_EN; - - REG_SET_2(OTG_STATIC_SCREEN_CONTROL, 0, - OTG_STATIC_SCREEN_EVENT_MASK, event_triggers, - OTG_STATIC_SCREEN_FRAME_COUNT, num_frames); -} - -static void optc1_setup_manual_trigger(struct timing_generator *optc) -{ - struct optc *optc1 = DCN10TG_FROM_TG(optc); - - REG_SET(OTG_GLOBAL_CONTROL2, 0, - MANUAL_FLOW_CONTROL_SEL, optc->inst); - - REG_SET_8(OTG_TRIGA_CNTL, 0, - OTG_TRIGA_SOURCE_SELECT, 22, - OTG_TRIGA_SOURCE_PIPE_SELECT, optc->inst, - OTG_TRIGA_RISING_EDGE_DETECT_CNTL, 1, - OTG_TRIGA_FALLING_EDGE_DETECT_CNTL, 0, - OTG_TRIGA_POLARITY_SELECT, 0, - OTG_TRIGA_FREQUENCY_SELECT, 0, - OTG_TRIGA_DELAY, 0, - OTG_TRIGA_CLEAR, 1); -} - -static void optc1_program_manual_trigger(struct timing_generator *optc) -{ - struct optc *optc1 = DCN10TG_FROM_TG(optc); - - REG_SET(OTG_MANUAL_FLOW_CONTROL, 0, - MANUAL_FLOW_CONTROL, 1); - - REG_SET(OTG_MANUAL_FLOW_CONTROL, 0, - MANUAL_FLOW_CONTROL, 0); -} - -/** - * optc1_set_drr() - Program dynamic refresh rate registers m_OTGx_OTG_V_TOTAL_*. - * - * @optc: timing_generator instance. - * @params: parameters used for Dynamic Refresh Rate. - */ -void optc1_set_drr( - struct timing_generator *optc, - const struct drr_params *params) -{ - struct optc *optc1 = DCN10TG_FROM_TG(optc); - - if (params != NULL && - params->vertical_total_max > 0 && - params->vertical_total_min > 0) { - - if (params->vertical_total_mid != 0) { - - REG_SET(OTG_V_TOTAL_MID, 0, - OTG_V_TOTAL_MID, params->vertical_total_mid - 1); - - REG_UPDATE_2(OTG_V_TOTAL_CONTROL, - OTG_VTOTAL_MID_REPLACING_MAX_EN, 1, - OTG_VTOTAL_MID_FRAME_NUM, - (uint8_t)params->vertical_total_mid_frame_num); - - } - - optc->funcs->set_vtotal_min_max(optc, params->vertical_total_min - 1, params->vertical_total_max - 1); - - REG_UPDATE_5(OTG_V_TOTAL_CONTROL, - OTG_V_TOTAL_MIN_SEL, 1, - OTG_V_TOTAL_MAX_SEL, 1, - OTG_FORCE_LOCK_ON_EVENT, 0, - OTG_SET_V_TOTAL_MIN_MASK_EN, 0, - OTG_SET_V_TOTAL_MIN_MASK, 0); - } - - // Setup manual flow control for EOF via TRIG_A - optc->funcs->setup_manual_trigger(optc); -} - -void optc1_set_vtotal_min_max(struct timing_generator *optc, int vtotal_min, int vtotal_max) -{ - struct optc *optc1 = DCN10TG_FROM_TG(optc); - - REG_SET(OTG_V_TOTAL_MAX, 0, - OTG_V_TOTAL_MAX, vtotal_max); - - REG_SET(OTG_V_TOTAL_MIN, 0, - OTG_V_TOTAL_MIN, vtotal_min); -} - -static void optc1_set_test_pattern( - struct timing_generator *optc, - /* TODO: replace 'controller_dp_test_pattern' by 'test_pattern_mode' - * because this is not DP-specific (which is probably somewhere in DP - * encoder) */ - enum controller_dp_test_pattern test_pattern, - enum dc_color_depth color_depth) -{ - struct optc *optc1 = DCN10TG_FROM_TG(optc); - enum test_pattern_color_format bit_depth; - enum test_pattern_dyn_range dyn_range; - enum test_pattern_mode mode; - uint32_t pattern_mask; - uint32_t pattern_data; - /* color ramp generator mixes 16-bits color */ - uint32_t src_bpc = 16; - /* requested bpc */ - uint32_t dst_bpc; - uint32_t index; - /* RGB values of the color bars. - * Produce two RGB colors: RGB0 - white (all Fs) - * and RGB1 - black (all 0s) - * (three RGB components for two colors) - */ - uint16_t src_color[6] = {0xFFFF, 0xFFFF, 0xFFFF, 0x0000, - 0x0000, 0x0000}; - /* dest color (converted to the specified color format) */ - uint16_t dst_color[6]; - uint32_t inc_base; - - /* translate to bit depth */ - switch (color_depth) { - case COLOR_DEPTH_666: - bit_depth = TEST_PATTERN_COLOR_FORMAT_BPC_6; - break; - case COLOR_DEPTH_888: - bit_depth = TEST_PATTERN_COLOR_FORMAT_BPC_8; - break; - case COLOR_DEPTH_101010: - bit_depth = TEST_PATTERN_COLOR_FORMAT_BPC_10; - break; - case COLOR_DEPTH_121212: - bit_depth = TEST_PATTERN_COLOR_FORMAT_BPC_12; - break; - default: - bit_depth = TEST_PATTERN_COLOR_FORMAT_BPC_8; - break; - } - - switch (test_pattern) { - case CONTROLLER_DP_TEST_PATTERN_COLORSQUARES: - case CONTROLLER_DP_TEST_PATTERN_COLORSQUARES_CEA: - { - dyn_range = (test_pattern == - CONTROLLER_DP_TEST_PATTERN_COLORSQUARES_CEA ? - TEST_PATTERN_DYN_RANGE_CEA : - TEST_PATTERN_DYN_RANGE_VESA); - mode = TEST_PATTERN_MODE_COLORSQUARES_RGB; - - REG_UPDATE_2(OTG_TEST_PATTERN_PARAMETERS, - OTG_TEST_PATTERN_VRES, 6, - OTG_TEST_PATTERN_HRES, 6); - - REG_UPDATE_4(OTG_TEST_PATTERN_CONTROL, - OTG_TEST_PATTERN_EN, 1, - OTG_TEST_PATTERN_MODE, mode, - OTG_TEST_PATTERN_DYNAMIC_RANGE, dyn_range, - OTG_TEST_PATTERN_COLOR_FORMAT, bit_depth); - } - break; - - case CONTROLLER_DP_TEST_PATTERN_VERTICALBARS: - case CONTROLLER_DP_TEST_PATTERN_HORIZONTALBARS: - { - mode = (test_pattern == - CONTROLLER_DP_TEST_PATTERN_VERTICALBARS ? - TEST_PATTERN_MODE_VERTICALBARS : - TEST_PATTERN_MODE_HORIZONTALBARS); - - switch (bit_depth) { - case TEST_PATTERN_COLOR_FORMAT_BPC_6: - dst_bpc = 6; - break; - case TEST_PATTERN_COLOR_FORMAT_BPC_8: - dst_bpc = 8; - break; - case TEST_PATTERN_COLOR_FORMAT_BPC_10: - dst_bpc = 10; - break; - default: - dst_bpc = 8; - break; - } - - /* adjust color to the required colorFormat */ - for (index = 0; index < 6; index++) { - /* dst = 2^dstBpc * src / 2^srcBpc = src >> - * (srcBpc - dstBpc); - */ - dst_color[index] = - src_color[index] >> (src_bpc - dst_bpc); - /* CRTC_TEST_PATTERN_DATA has 16 bits, - * lowest 6 are hardwired to ZERO - * color bits should be left aligned to MSB - * XXXXXXXXXX000000 for 10 bit, - * XXXXXXXX00000000 for 8 bit and XXXXXX0000000000 for 6 - */ - dst_color[index] <<= (16 - dst_bpc); - } - - REG_WRITE(OTG_TEST_PATTERN_PARAMETERS, 0); - - /* We have to write the mask before data, similar to pipeline. - * For example, for 8 bpc, if we want RGB0 to be magenta, - * and RGB1 to be cyan, - * we need to make 7 writes: - * MASK DATA - * 000001 00000000 00000000 set mask to R0 - * 000010 11111111 00000000 R0 255, 0xFF00, set mask to G0 - * 000100 00000000 00000000 G0 0, 0x0000, set mask to B0 - * 001000 11111111 00000000 B0 255, 0xFF00, set mask to R1 - * 010000 00000000 00000000 R1 0, 0x0000, set mask to G1 - * 100000 11111111 00000000 G1 255, 0xFF00, set mask to B1 - * 100000 11111111 00000000 B1 255, 0xFF00 - * - * we will make a loop of 6 in which we prepare the mask, - * then write, then prepare the color for next write. - * first iteration will write mask only, - * but each next iteration color prepared in - * previous iteration will be written within new mask, - * the last component will written separately, - * mask is not changing between 6th and 7th write - * and color will be prepared by last iteration - */ - - /* write color, color values mask in CRTC_TEST_PATTERN_MASK - * is B1, G1, R1, B0, G0, R0 - */ - pattern_data = 0; - for (index = 0; index < 6; index++) { - /* prepare color mask, first write PATTERN_DATA - * will have all zeros - */ - pattern_mask = (1 << index); - - /* write color component */ - REG_SET_2(OTG_TEST_PATTERN_COLOR, 0, - OTG_TEST_PATTERN_MASK, pattern_mask, - OTG_TEST_PATTERN_DATA, pattern_data); - - /* prepare next color component, - * will be written in the next iteration - */ - pattern_data = dst_color[index]; - } - /* write last color component, - * it's been already prepared in the loop - */ - REG_SET_2(OTG_TEST_PATTERN_COLOR, 0, - OTG_TEST_PATTERN_MASK, pattern_mask, - OTG_TEST_PATTERN_DATA, pattern_data); - - /* enable test pattern */ - REG_UPDATE_4(OTG_TEST_PATTERN_CONTROL, - OTG_TEST_PATTERN_EN, 1, - OTG_TEST_PATTERN_MODE, mode, - OTG_TEST_PATTERN_DYNAMIC_RANGE, 0, - OTG_TEST_PATTERN_COLOR_FORMAT, bit_depth); - } - break; - - case CONTROLLER_DP_TEST_PATTERN_COLORRAMP: - { - mode = (bit_depth == - TEST_PATTERN_COLOR_FORMAT_BPC_10 ? - TEST_PATTERN_MODE_DUALRAMP_RGB : - TEST_PATTERN_MODE_SINGLERAMP_RGB); - - switch (bit_depth) { - case TEST_PATTERN_COLOR_FORMAT_BPC_6: - dst_bpc = 6; - break; - case TEST_PATTERN_COLOR_FORMAT_BPC_8: - dst_bpc = 8; - break; - case TEST_PATTERN_COLOR_FORMAT_BPC_10: - dst_bpc = 10; - break; - default: - dst_bpc = 8; - break; - } - - /* increment for the first ramp for one color gradation - * 1 gradation for 6-bit color is 2^10 - * gradations in 16-bit color - */ - inc_base = (src_bpc - dst_bpc); - - switch (bit_depth) { - case TEST_PATTERN_COLOR_FORMAT_BPC_6: - { - REG_UPDATE_5(OTG_TEST_PATTERN_PARAMETERS, - OTG_TEST_PATTERN_INC0, inc_base, - OTG_TEST_PATTERN_INC1, 0, - OTG_TEST_PATTERN_HRES, 6, - OTG_TEST_PATTERN_VRES, 6, - OTG_TEST_PATTERN_RAMP0_OFFSET, 0); - } - break; - case TEST_PATTERN_COLOR_FORMAT_BPC_8: - { - REG_UPDATE_5(OTG_TEST_PATTERN_PARAMETERS, - OTG_TEST_PATTERN_INC0, inc_base, - OTG_TEST_PATTERN_INC1, 0, - OTG_TEST_PATTERN_HRES, 8, - OTG_TEST_PATTERN_VRES, 6, - OTG_TEST_PATTERN_RAMP0_OFFSET, 0); - } - break; - case TEST_PATTERN_COLOR_FORMAT_BPC_10: - { - REG_UPDATE_5(OTG_TEST_PATTERN_PARAMETERS, - OTG_TEST_PATTERN_INC0, inc_base, - OTG_TEST_PATTERN_INC1, inc_base + 2, - OTG_TEST_PATTERN_HRES, 8, - OTG_TEST_PATTERN_VRES, 5, - OTG_TEST_PATTERN_RAMP0_OFFSET, 384 << 6); - } - break; - default: - break; - } - - REG_WRITE(OTG_TEST_PATTERN_COLOR, 0); - - /* enable test pattern */ - REG_WRITE(OTG_TEST_PATTERN_CONTROL, 0); - - REG_SET_4(OTG_TEST_PATTERN_CONTROL, 0, - OTG_TEST_PATTERN_EN, 1, - OTG_TEST_PATTERN_MODE, mode, - OTG_TEST_PATTERN_DYNAMIC_RANGE, 0, - OTG_TEST_PATTERN_COLOR_FORMAT, bit_depth); - } - break; - case CONTROLLER_DP_TEST_PATTERN_VIDEOMODE: - { - REG_WRITE(OTG_TEST_PATTERN_CONTROL, 0); - REG_WRITE(OTG_TEST_PATTERN_COLOR, 0); - REG_WRITE(OTG_TEST_PATTERN_PARAMETERS, 0); - } - break; - default: - break; - - } -} - -void optc1_get_crtc_scanoutpos( - struct timing_generator *optc, - uint32_t *v_blank_start, - uint32_t *v_blank_end, - uint32_t *h_position, - uint32_t *v_position) -{ - struct optc *optc1 = DCN10TG_FROM_TG(optc); - struct crtc_position position; - - REG_GET_2(OTG_V_BLANK_START_END, - OTG_V_BLANK_START, v_blank_start, - OTG_V_BLANK_END, v_blank_end); - - optc1_get_position(optc, &position); - - *h_position = position.horizontal_count; - *v_position = position.vertical_count; -} - -static void optc1_enable_stereo(struct timing_generator *optc, - const struct dc_crtc_timing *timing, struct crtc_stereo_flags *flags) -{ - struct optc *optc1 = DCN10TG_FROM_TG(optc); - - if (flags) { - uint32_t stereo_en; - stereo_en = flags->FRAME_PACKED == 0 ? 1 : 0; - - if (flags->PROGRAM_STEREO) - REG_UPDATE_3(OTG_STEREO_CONTROL, - OTG_STEREO_EN, stereo_en, - OTG_STEREO_SYNC_OUTPUT_LINE_NUM, 0, - OTG_STEREO_SYNC_OUTPUT_POLARITY, flags->RIGHT_EYE_POLARITY == 0 ? 0 : 1); - - if (flags->PROGRAM_POLARITY) - REG_UPDATE(OTG_STEREO_CONTROL, - OTG_STEREO_EYE_FLAG_POLARITY, - flags->RIGHT_EYE_POLARITY == 0 ? 0 : 1); - - if (flags->DISABLE_STEREO_DP_SYNC) - REG_UPDATE(OTG_STEREO_CONTROL, - OTG_DISABLE_STEREOSYNC_OUTPUT_FOR_DP, 1); - - if (flags->PROGRAM_STEREO) - REG_UPDATE_2(OTG_3D_STRUCTURE_CONTROL, - OTG_3D_STRUCTURE_EN, flags->FRAME_PACKED, - OTG_3D_STRUCTURE_STEREO_SEL_OVR, flags->FRAME_PACKED); - - } -} - -void optc1_program_stereo(struct timing_generator *optc, - const struct dc_crtc_timing *timing, struct crtc_stereo_flags *flags) -{ - if (flags->PROGRAM_STEREO) - optc1_enable_stereo(optc, timing, flags); - else - optc1_disable_stereo(optc); -} - - -bool optc1_is_stereo_left_eye(struct timing_generator *optc) -{ - bool ret = false; - uint32_t left_eye = 0; - struct optc *optc1 = DCN10TG_FROM_TG(optc); - - REG_GET(OTG_STEREO_STATUS, - OTG_STEREO_CURRENT_EYE, &left_eye); - if (left_eye == 1) - ret = true; - else - ret = false; - - return ret; -} - -bool optc1_get_hw_timing(struct timing_generator *tg, - struct dc_crtc_timing *hw_crtc_timing) -{ - struct dcn_otg_state s = {0}; - - if (tg == NULL || hw_crtc_timing == NULL) - return false; - - optc1_read_otg_state(DCN10TG_FROM_TG(tg), &s); - - hw_crtc_timing->h_total = s.h_total + 1; - hw_crtc_timing->h_addressable = s.h_total - ((s.h_total - s.h_blank_start) + s.h_blank_end); - hw_crtc_timing->h_front_porch = s.h_total + 1 - s.h_blank_start; - hw_crtc_timing->h_sync_width = s.h_sync_a_end - s.h_sync_a_start; - - hw_crtc_timing->v_total = s.v_total + 1; - hw_crtc_timing->v_addressable = s.v_total - ((s.v_total - s.v_blank_start) + s.v_blank_end); - hw_crtc_timing->v_front_porch = s.v_total + 1 - s.v_blank_start; - hw_crtc_timing->v_sync_width = s.v_sync_a_end - s.v_sync_a_start; - - return true; -} - - -void optc1_read_otg_state(struct optc *optc1, - struct dcn_otg_state *s) -{ - REG_GET(OTG_CONTROL, - OTG_MASTER_EN, &s->otg_enabled); - - REG_GET_2(OTG_V_BLANK_START_END, - OTG_V_BLANK_START, &s->v_blank_start, - OTG_V_BLANK_END, &s->v_blank_end); - - REG_GET(OTG_V_SYNC_A_CNTL, - OTG_V_SYNC_A_POL, &s->v_sync_a_pol); - - REG_GET(OTG_V_TOTAL, - OTG_V_TOTAL, &s->v_total); - - REG_GET(OTG_V_TOTAL_MAX, - OTG_V_TOTAL_MAX, &s->v_total_max); - - REG_GET(OTG_V_TOTAL_MIN, - OTG_V_TOTAL_MIN, &s->v_total_min); - - REG_GET(OTG_V_TOTAL_CONTROL, - OTG_V_TOTAL_MAX_SEL, &s->v_total_max_sel); - - REG_GET(OTG_V_TOTAL_CONTROL, - OTG_V_TOTAL_MIN_SEL, &s->v_total_min_sel); - - REG_GET_2(OTG_V_SYNC_A, - OTG_V_SYNC_A_START, &s->v_sync_a_start, - OTG_V_SYNC_A_END, &s->v_sync_a_end); - - REG_GET_2(OTG_H_BLANK_START_END, - OTG_H_BLANK_START, &s->h_blank_start, - OTG_H_BLANK_END, &s->h_blank_end); - - REG_GET_2(OTG_H_SYNC_A, - OTG_H_SYNC_A_START, &s->h_sync_a_start, - OTG_H_SYNC_A_END, &s->h_sync_a_end); - - REG_GET(OTG_H_SYNC_A_CNTL, - OTG_H_SYNC_A_POL, &s->h_sync_a_pol); - - REG_GET(OTG_H_TOTAL, - OTG_H_TOTAL, &s->h_total); - - REG_GET(OPTC_INPUT_GLOBAL_CONTROL, - OPTC_UNDERFLOW_OCCURRED_STATUS, &s->underflow_occurred_status); - - REG_GET(OTG_VERTICAL_INTERRUPT1_CONTROL, - OTG_VERTICAL_INTERRUPT1_INT_ENABLE, &s->vertical_interrupt1_en); - - REG_GET(OTG_VERTICAL_INTERRUPT1_POSITION, - OTG_VERTICAL_INTERRUPT1_LINE_START, &s->vertical_interrupt1_line); - - REG_GET(OTG_VERTICAL_INTERRUPT2_CONTROL, - OTG_VERTICAL_INTERRUPT2_INT_ENABLE, &s->vertical_interrupt2_en); - - REG_GET(OTG_VERTICAL_INTERRUPT2_POSITION, - OTG_VERTICAL_INTERRUPT2_LINE_START, &s->vertical_interrupt2_line); -} - -bool optc1_get_otg_active_size(struct timing_generator *optc, - uint32_t *otg_active_width, - uint32_t *otg_active_height) -{ - uint32_t otg_enabled; - uint32_t v_blank_start; - uint32_t v_blank_end; - uint32_t h_blank_start; - uint32_t h_blank_end; - struct optc *optc1 = DCN10TG_FROM_TG(optc); - - - REG_GET(OTG_CONTROL, - OTG_MASTER_EN, &otg_enabled); - - if (otg_enabled == 0) - return false; - - REG_GET_2(OTG_V_BLANK_START_END, - OTG_V_BLANK_START, &v_blank_start, - OTG_V_BLANK_END, &v_blank_end); - - REG_GET_2(OTG_H_BLANK_START_END, - OTG_H_BLANK_START, &h_blank_start, - OTG_H_BLANK_END, &h_blank_end); - - *otg_active_width = v_blank_start - v_blank_end; - *otg_active_height = h_blank_start - h_blank_end; - return true; -} - -void optc1_clear_optc_underflow(struct timing_generator *optc) -{ - struct optc *optc1 = DCN10TG_FROM_TG(optc); - - REG_UPDATE(OPTC_INPUT_GLOBAL_CONTROL, OPTC_UNDERFLOW_CLEAR, 1); -} - -void optc1_tg_init(struct timing_generator *optc) -{ - optc1_set_blank_data_double_buffer(optc, true); - optc1_set_timing_double_buffer(optc, true); - optc1_clear_optc_underflow(optc); -} - -bool optc1_is_tg_enabled(struct timing_generator *optc) -{ - struct optc *optc1 = DCN10TG_FROM_TG(optc); - uint32_t otg_enabled = 0; - - REG_GET(OTG_CONTROL, OTG_MASTER_EN, &otg_enabled); - - return (otg_enabled != 0); - -} - -bool optc1_is_optc_underflow_occurred(struct timing_generator *optc) -{ - struct optc *optc1 = DCN10TG_FROM_TG(optc); - uint32_t underflow_occurred = 0; - - REG_GET(OPTC_INPUT_GLOBAL_CONTROL, - OPTC_UNDERFLOW_OCCURRED_STATUS, - &underflow_occurred); - - return (underflow_occurred == 1); -} - -bool optc1_configure_crc(struct timing_generator *optc, - const struct crc_params *params) -{ - struct optc *optc1 = DCN10TG_FROM_TG(optc); - - /* Cannot configure crc on a CRTC that is disabled */ - if (!optc1_is_tg_enabled(optc)) - return false; - - REG_WRITE(OTG_CRC_CNTL, 0); - - if (!params->enable) - return true; - - /* Program frame boundaries */ - /* Window A x axis start and end. */ - REG_UPDATE_2(OTG_CRC0_WINDOWA_X_CONTROL, - OTG_CRC0_WINDOWA_X_START, params->windowa_x_start, - OTG_CRC0_WINDOWA_X_END, params->windowa_x_end); - - /* Window A y axis start and end. */ - REG_UPDATE_2(OTG_CRC0_WINDOWA_Y_CONTROL, - OTG_CRC0_WINDOWA_Y_START, params->windowa_y_start, - OTG_CRC0_WINDOWA_Y_END, params->windowa_y_end); - - /* Window B x axis start and end. */ - REG_UPDATE_2(OTG_CRC0_WINDOWB_X_CONTROL, - OTG_CRC0_WINDOWB_X_START, params->windowb_x_start, - OTG_CRC0_WINDOWB_X_END, params->windowb_x_end); - - /* Window B y axis start and end. */ - REG_UPDATE_2(OTG_CRC0_WINDOWB_Y_CONTROL, - OTG_CRC0_WINDOWB_Y_START, params->windowb_y_start, - OTG_CRC0_WINDOWB_Y_END, params->windowb_y_end); - - /* Set crc mode and selection, and enable. Only using CRC0*/ - REG_UPDATE_3(OTG_CRC_CNTL, - OTG_CRC_CONT_EN, params->continuous_mode ? 1 : 0, - OTG_CRC0_SELECT, params->selection, - OTG_CRC_EN, 1); - - return true; -} - -/** - * optc1_get_crc - Capture CRC result per component - * - * @optc: timing_generator instance. - * @r_cr: 16-bit primary CRC signature for red data. - * @g_y: 16-bit primary CRC signature for green data. - * @b_cb: 16-bit primary CRC signature for blue data. - * - * This function reads the CRC signature from the OPTC registers. Notice that - * we have three registers to keep the CRC result per color component (RGB). - * - * Returns: - * If CRC is disabled, return false; otherwise, return true, and the CRC - * results in the parameters. - */ -bool optc1_get_crc(struct timing_generator *optc, - uint32_t *r_cr, uint32_t *g_y, uint32_t *b_cb) -{ - uint32_t field = 0; - struct optc *optc1 = DCN10TG_FROM_TG(optc); - - REG_GET(OTG_CRC_CNTL, OTG_CRC_EN, &field); - - /* Early return if CRC is not enabled for this CRTC */ - if (!field) - return false; - - /* OTG_CRC0_DATA_RG has the CRC16 results for the red and green component */ - REG_GET_2(OTG_CRC0_DATA_RG, - CRC0_R_CR, r_cr, - CRC0_G_Y, g_y); - - /* OTG_CRC0_DATA_B has the CRC16 results for the blue component */ - REG_GET(OTG_CRC0_DATA_B, - CRC0_B_CB, b_cb); - - return true; -} - -static const struct timing_generator_funcs dcn10_tg_funcs = { - .validate_timing = optc1_validate_timing, - .program_timing = optc1_program_timing, - .setup_vertical_interrupt0 = optc1_setup_vertical_interrupt0, - .setup_vertical_interrupt1 = optc1_setup_vertical_interrupt1, - .setup_vertical_interrupt2 = optc1_setup_vertical_interrupt2, - .program_global_sync = optc1_program_global_sync, - .enable_crtc = optc1_enable_crtc, - .disable_crtc = optc1_disable_crtc, - /* used by enable_timing_synchronization. Not need for FPGA */ - .is_counter_moving = optc1_is_counter_moving, - .get_position = optc1_get_position, - .get_frame_count = optc1_get_vblank_counter, - .get_scanoutpos = optc1_get_crtc_scanoutpos, - .get_otg_active_size = optc1_get_otg_active_size, - .set_early_control = optc1_set_early_control, - /* used by enable_timing_synchronization. Not need for FPGA */ - .wait_for_state = optc1_wait_for_state, - .set_blank = optc1_set_blank, - .is_blanked = optc1_is_blanked, - .set_blank_color = optc1_program_blank_color, - .did_triggered_reset_occur = optc1_did_triggered_reset_occur, - .enable_reset_trigger = optc1_enable_reset_trigger, - .enable_crtc_reset = optc1_enable_crtc_reset, - .disable_reset_trigger = optc1_disable_reset_trigger, - .lock = optc1_lock, - .unlock = optc1_unlock, - .enable_optc_clock = optc1_enable_optc_clock, - .set_drr = optc1_set_drr, - .get_last_used_drr_vtotal = NULL, - .set_vtotal_min_max = optc1_set_vtotal_min_max, - .set_static_screen_control = optc1_set_static_screen_control, - .set_test_pattern = optc1_set_test_pattern, - .program_stereo = optc1_program_stereo, - .is_stereo_left_eye = optc1_is_stereo_left_eye, - .set_blank_data_double_buffer = optc1_set_blank_data_double_buffer, - .tg_init = optc1_tg_init, - .is_tg_enabled = optc1_is_tg_enabled, - .is_optc_underflow_occurred = optc1_is_optc_underflow_occurred, - .clear_optc_underflow = optc1_clear_optc_underflow, - .get_crc = optc1_get_crc, - .configure_crc = optc1_configure_crc, - .set_vtg_params = optc1_set_vtg_params, - .program_manual_trigger = optc1_program_manual_trigger, - .setup_manual_trigger = optc1_setup_manual_trigger, - .get_hw_timing = optc1_get_hw_timing, -}; - -void dcn10_timing_generator_init(struct optc *optc1) -{ - optc1->base.funcs = &dcn10_tg_funcs; - - optc1->max_h_total = optc1->tg_mask->OTG_H_TOTAL + 1; - optc1->max_v_total = optc1->tg_mask->OTG_V_TOTAL + 1; - - optc1->min_h_blank = 32; - optc1->min_v_blank = 3; - optc1->min_v_blank_interlace = 5; - optc1->min_h_sync_width = 4; - optc1->min_v_sync_width = 1; -} - -/* "Containter" vs. "pixel" is a concept within HW blocks, mostly those closer to the back-end. It works like this: - * - * - In most of the formats (RGB or YCbCr 4:4:4, 4:2:2 uncompressed and DSC 4:2:2 Simple) pixel rate is the same as - * containter rate. - * - * - In 4:2:0 (DSC or uncompressed) there are two pixels per container, hence the target container rate has to be - * halved to maintain the correct pixel rate. - * - * - Unlike 4:2:2 uncompressed, DSC 4:2:2 Native also has two pixels per container (this happens when DSC is applied - * to it) and has to be treated the same as 4:2:0, i.e. target containter rate has to be halved in this case as well. - * - */ -bool optc1_is_two_pixels_per_containter(const struct dc_crtc_timing *timing) -{ - bool two_pix = timing->pixel_encoding == PIXEL_ENCODING_YCBCR420; - - two_pix = two_pix || (timing->flags.DSC && timing->pixel_encoding == PIXEL_ENCODING_YCBCR422 - && !timing->dsc_cfg.ycbcr422_simple); - return two_pix; -} - diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_optc.h b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_optc.h deleted file mode 100644 index ab81594a7fad..000000000000 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_optc.h +++ /dev/null @@ -1,599 +0,0 @@ -/* - * Copyright 2012-15 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_TIMING_GENERATOR_DCN10_H__ -#define __DC_TIMING_GENERATOR_DCN10_H__ - -#include "optc.h" - -#define DCN10TG_FROM_TG(tg)\ - container_of(tg, struct optc, base) - -#define TG_COMMON_REG_LIST_DCN(inst) \ - SRI(OTG_VSTARTUP_PARAM, OTG, inst),\ - SRI(OTG_VUPDATE_PARAM, OTG, inst),\ - SRI(OTG_VREADY_PARAM, OTG, inst),\ - SRI(OTG_BLANK_CONTROL, OTG, inst),\ - SRI(OTG_MASTER_UPDATE_LOCK, OTG, inst),\ - SRI(OTG_GLOBAL_CONTROL0, OTG, inst),\ - SRI(OTG_DOUBLE_BUFFER_CONTROL, OTG, inst),\ - SRI(OTG_H_TOTAL, OTG, inst),\ - SRI(OTG_H_BLANK_START_END, OTG, inst),\ - SRI(OTG_H_SYNC_A, OTG, inst),\ - SRI(OTG_H_SYNC_A_CNTL, OTG, inst),\ - SRI(OTG_H_TIMING_CNTL, OTG, inst),\ - SRI(OTG_V_TOTAL, OTG, inst),\ - SRI(OTG_V_BLANK_START_END, OTG, inst),\ - SRI(OTG_V_SYNC_A, OTG, inst),\ - SRI(OTG_V_SYNC_A_CNTL, OTG, inst),\ - SRI(OTG_INTERLACE_CONTROL, OTG, inst),\ - SRI(OTG_CONTROL, OTG, inst),\ - SRI(OTG_STEREO_CONTROL, OTG, inst),\ - SRI(OTG_3D_STRUCTURE_CONTROL, OTG, inst),\ - SRI(OTG_STEREO_STATUS, OTG, inst),\ - SRI(OTG_V_TOTAL_MAX, OTG, inst),\ - SRI(OTG_V_TOTAL_MID, OTG, inst),\ - SRI(OTG_V_TOTAL_MIN, OTG, inst),\ - SRI(OTG_V_TOTAL_CONTROL, OTG, inst),\ - SRI(OTG_TRIGA_CNTL, OTG, inst),\ - SRI(OTG_FORCE_COUNT_NOW_CNTL, OTG, inst),\ - SRI(OTG_STATIC_SCREEN_CONTROL, OTG, inst),\ - SRI(OTG_STATUS_FRAME_COUNT, OTG, inst),\ - SRI(OTG_STATUS, OTG, inst),\ - SRI(OTG_STATUS_POSITION, OTG, inst),\ - SRI(OTG_NOM_VERT_POSITION, OTG, inst),\ - SRI(OTG_BLACK_COLOR, OTG, inst),\ - SRI(OTG_CLOCK_CONTROL, OTG, inst),\ - SRI(OTG_VERTICAL_INTERRUPT0_CONTROL, OTG, inst),\ - SRI(OTG_VERTICAL_INTERRUPT0_POSITION, OTG, inst),\ - SRI(OTG_VERTICAL_INTERRUPT1_CONTROL, OTG, inst),\ - SRI(OTG_VERTICAL_INTERRUPT1_POSITION, OTG, inst),\ - SRI(OTG_VERTICAL_INTERRUPT2_CONTROL, OTG, inst),\ - SRI(OTG_VERTICAL_INTERRUPT2_POSITION, OTG, inst),\ - SRI(OPTC_INPUT_CLOCK_CONTROL, ODM, inst),\ - SRI(OPTC_DATA_SOURCE_SELECT, ODM, inst),\ - SRI(OPTC_INPUT_GLOBAL_CONTROL, ODM, inst),\ - SRI(CONTROL, VTG, inst),\ - SRI(OTG_VERT_SYNC_CONTROL, OTG, inst),\ - SRI(OTG_MASTER_UPDATE_MODE, OTG, inst),\ - SRI(OTG_GSL_CONTROL, OTG, inst),\ - SRI(OTG_CRC_CNTL, OTG, inst),\ - SRI(OTG_CRC0_DATA_RG, OTG, inst),\ - SRI(OTG_CRC0_DATA_B, OTG, inst),\ - SRI(OTG_CRC0_WINDOWA_X_CONTROL, OTG, inst),\ - SRI(OTG_CRC0_WINDOWA_Y_CONTROL, OTG, inst),\ - SRI(OTG_CRC0_WINDOWB_X_CONTROL, OTG, inst),\ - SRI(OTG_CRC0_WINDOWB_Y_CONTROL, OTG, inst),\ - SR(GSL_SOURCE_SELECT),\ - SRI(OTG_GLOBAL_CONTROL2, OTG, inst),\ - SRI(OTG_TRIGA_MANUAL_TRIG, OTG, inst) - -#define TG_COMMON_REG_LIST_DCN1_0(inst) \ - TG_COMMON_REG_LIST_DCN(inst),\ - SRI(OTG_TEST_PATTERN_PARAMETERS, OTG, inst),\ - SRI(OTG_TEST_PATTERN_CONTROL, OTG, inst),\ - SRI(OTG_TEST_PATTERN_COLOR, OTG, inst),\ - SRI(OTG_MANUAL_FLOW_CONTROL, OTG, inst) - - -struct dcn_optc_registers { - uint32_t OTG_GLOBAL_CONTROL1; - uint32_t OTG_GLOBAL_CONTROL2; - uint32_t OTG_VERT_SYNC_CONTROL; - uint32_t OTG_MASTER_UPDATE_MODE; - uint32_t OTG_GSL_CONTROL; - uint32_t OTG_VSTARTUP_PARAM; - uint32_t OTG_VUPDATE_PARAM; - uint32_t OTG_VREADY_PARAM; - uint32_t OTG_BLANK_CONTROL; - uint32_t OTG_MASTER_UPDATE_LOCK; - uint32_t OTG_GLOBAL_CONTROL0; - uint32_t OTG_DOUBLE_BUFFER_CONTROL; - uint32_t OTG_H_TOTAL; - uint32_t OTG_H_BLANK_START_END; - uint32_t OTG_H_SYNC_A; - uint32_t OTG_H_SYNC_A_CNTL; - uint32_t OTG_H_TIMING_CNTL; - uint32_t OTG_V_TOTAL; - uint32_t OTG_V_BLANK_START_END; - uint32_t OTG_V_SYNC_A; - uint32_t OTG_V_SYNC_A_CNTL; - uint32_t OTG_INTERLACE_CONTROL; - uint32_t OTG_CONTROL; - uint32_t OTG_STEREO_CONTROL; - uint32_t OTG_3D_STRUCTURE_CONTROL; - uint32_t OTG_STEREO_STATUS; - uint32_t OTG_V_TOTAL_MAX; - uint32_t OTG_V_TOTAL_MID; - uint32_t OTG_V_TOTAL_MIN; - uint32_t OTG_V_TOTAL_CONTROL; - uint32_t OTG_TRIGA_CNTL; - uint32_t OTG_TRIGA_MANUAL_TRIG; - uint32_t OTG_MANUAL_FLOW_CONTROL; - uint32_t OTG_FORCE_COUNT_NOW_CNTL; - uint32_t OTG_STATIC_SCREEN_CONTROL; - uint32_t OTG_STATUS_FRAME_COUNT; - uint32_t OTG_STATUS; - uint32_t OTG_STATUS_POSITION; - uint32_t OTG_NOM_VERT_POSITION; - uint32_t OTG_BLACK_COLOR; - uint32_t OTG_TEST_PATTERN_PARAMETERS; - uint32_t OTG_TEST_PATTERN_CONTROL; - uint32_t OTG_TEST_PATTERN_COLOR; - uint32_t OTG_CLOCK_CONTROL; - uint32_t OTG_VERTICAL_INTERRUPT0_CONTROL; - uint32_t OTG_VERTICAL_INTERRUPT0_POSITION; - uint32_t OTG_VERTICAL_INTERRUPT1_CONTROL; - uint32_t OTG_VERTICAL_INTERRUPT1_POSITION; - uint32_t OTG_VERTICAL_INTERRUPT2_CONTROL; - uint32_t OTG_VERTICAL_INTERRUPT2_POSITION; - uint32_t OPTC_INPUT_CLOCK_CONTROL; - uint32_t OPTC_DATA_SOURCE_SELECT; - uint32_t OPTC_MEMORY_CONFIG; - uint32_t OPTC_INPUT_GLOBAL_CONTROL; - uint32_t CONTROL; - uint32_t OTG_GSL_WINDOW_X; - uint32_t OTG_GSL_WINDOW_Y; - uint32_t OTG_VUPDATE_KEEPOUT; - uint32_t OTG_CRC_CNTL; - uint32_t OTG_CRC_CNTL2; - uint32_t OTG_CRC0_DATA_RG; - uint32_t OTG_CRC0_DATA_B; - uint32_t OTG_CRC1_DATA_B; - uint32_t OTG_CRC2_DATA_B; - uint32_t OTG_CRC3_DATA_B; - uint32_t OTG_CRC1_DATA_RG; - uint32_t OTG_CRC2_DATA_RG; - uint32_t OTG_CRC3_DATA_RG; - uint32_t OTG_CRC0_WINDOWA_X_CONTROL; - uint32_t OTG_CRC0_WINDOWA_Y_CONTROL; - uint32_t OTG_CRC0_WINDOWB_X_CONTROL; - uint32_t OTG_CRC0_WINDOWB_Y_CONTROL; - uint32_t OTG_CRC1_WINDOWA_X_CONTROL; - uint32_t OTG_CRC1_WINDOWA_Y_CONTROL; - uint32_t OTG_CRC1_WINDOWB_X_CONTROL; - uint32_t OTG_CRC1_WINDOWB_Y_CONTROL; - uint32_t GSL_SOURCE_SELECT; - uint32_t DWB_SOURCE_SELECT; - uint32_t OTG_DSC_START_POSITION; - uint32_t OPTC_DATA_FORMAT_CONTROL; - uint32_t OPTC_BYTES_PER_PIXEL; - uint32_t OPTC_WIDTH_CONTROL; - uint32_t OTG_DRR_CONTROL; - uint32_t OTG_BLANK_DATA_COLOR; - uint32_t OTG_BLANK_DATA_COLOR_EXT; - uint32_t OTG_DRR_TRIGGER_WINDOW; - uint32_t OTG_M_CONST_DTO0; - uint32_t OTG_M_CONST_DTO1; - uint32_t OTG_DRR_V_TOTAL_CHANGE; - uint32_t OTG_GLOBAL_CONTROL4; - uint32_t OTG_CRC0_WINDOWA_X_CONTROL_READBACK; - uint32_t OTG_CRC0_WINDOWA_Y_CONTROL_READBACK; - uint32_t OTG_CRC0_WINDOWB_X_CONTROL_READBACK; - uint32_t OTG_CRC0_WINDOWB_Y_CONTROL_READBACK; - uint32_t OTG_CRC1_WINDOWA_X_CONTROL_READBACK; - uint32_t OTG_CRC1_WINDOWA_Y_CONTROL_READBACK; - uint32_t OTG_CRC1_WINDOWB_X_CONTROL_READBACK; - uint32_t OTG_CRC1_WINDOWB_Y_CONTROL_READBACK; - uint32_t OPTC_CLOCK_CONTROL; -}; - -#define TG_COMMON_MASK_SH_LIST_DCN(mask_sh)\ - SF(OTG0_OTG_VSTARTUP_PARAM, VSTARTUP_START, mask_sh),\ - SF(OTG0_OTG_VUPDATE_PARAM, VUPDATE_OFFSET, mask_sh),\ - SF(OTG0_OTG_VUPDATE_PARAM, VUPDATE_WIDTH, mask_sh),\ - SF(OTG0_OTG_VREADY_PARAM, VREADY_OFFSET, mask_sh),\ - SF(OTG0_OTG_BLANK_CONTROL, OTG_BLANK_DATA_EN, mask_sh),\ - SF(OTG0_OTG_BLANK_CONTROL, OTG_BLANK_DE_MODE, mask_sh),\ - SF(OTG0_OTG_BLANK_CONTROL, OTG_CURRENT_BLANK_STATE, mask_sh),\ - SF(OTG0_OTG_MASTER_UPDATE_LOCK, OTG_MASTER_UPDATE_LOCK, mask_sh),\ - SF(OTG0_OTG_MASTER_UPDATE_LOCK, UPDATE_LOCK_STATUS, mask_sh),\ - SF(OTG0_OTG_GLOBAL_CONTROL0, OTG_MASTER_UPDATE_LOCK_SEL, mask_sh),\ - SF(OTG0_OTG_DOUBLE_BUFFER_CONTROL, OTG_UPDATE_PENDING, mask_sh),\ - SF(OTG0_OTG_DOUBLE_BUFFER_CONTROL, OTG_BLANK_DATA_DOUBLE_BUFFER_EN, mask_sh),\ - SF(OTG0_OTG_DOUBLE_BUFFER_CONTROL, OTG_RANGE_TIMING_DBUF_UPDATE_MODE, mask_sh),\ - SF(OTG0_OTG_VUPDATE_KEEPOUT, OTG_MASTER_UPDATE_LOCK_VUPDATE_KEEPOUT_EN, mask_sh), \ - SF(OTG0_OTG_VUPDATE_KEEPOUT, MASTER_UPDATE_LOCK_VUPDATE_KEEPOUT_START_OFFSET, mask_sh), \ - SF(OTG0_OTG_VUPDATE_KEEPOUT, MASTER_UPDATE_LOCK_VUPDATE_KEEPOUT_END_OFFSET, mask_sh), \ - SF(OTG0_OTG_H_TOTAL, OTG_H_TOTAL, mask_sh),\ - SF(OTG0_OTG_H_BLANK_START_END, OTG_H_BLANK_START, mask_sh),\ - SF(OTG0_OTG_H_BLANK_START_END, OTG_H_BLANK_END, mask_sh),\ - SF(OTG0_OTG_H_SYNC_A, OTG_H_SYNC_A_START, mask_sh),\ - SF(OTG0_OTG_H_SYNC_A, OTG_H_SYNC_A_END, mask_sh),\ - SF(OTG0_OTG_H_SYNC_A_CNTL, OTG_H_SYNC_A_POL, mask_sh),\ - SF(OTG0_OTG_H_TIMING_CNTL, OTG_H_TIMING_DIV_BY2, mask_sh),\ - SF(OTG0_OTG_V_TOTAL, OTG_V_TOTAL, mask_sh),\ - SF(OTG0_OTG_V_BLANK_START_END, OTG_V_BLANK_START, mask_sh),\ - SF(OTG0_OTG_V_BLANK_START_END, OTG_V_BLANK_END, mask_sh),\ - SF(OTG0_OTG_V_SYNC_A, OTG_V_SYNC_A_START, mask_sh),\ - SF(OTG0_OTG_V_SYNC_A, OTG_V_SYNC_A_END, mask_sh),\ - SF(OTG0_OTG_V_SYNC_A_CNTL, OTG_V_SYNC_A_POL, mask_sh),\ - SF(OTG0_OTG_INTERLACE_CONTROL, OTG_INTERLACE_ENABLE, mask_sh),\ - SF(OTG0_OTG_CONTROL, OTG_MASTER_EN, mask_sh),\ - SF(OTG0_OTG_CONTROL, OTG_START_POINT_CNTL, mask_sh),\ - SF(OTG0_OTG_CONTROL, OTG_DISABLE_POINT_CNTL, mask_sh),\ - SF(OTG0_OTG_CONTROL, OTG_FIELD_NUMBER_CNTL, mask_sh),\ - SF(OTG0_OTG_CONTROL, OTG_CURRENT_MASTER_EN_STATE, mask_sh),\ - SF(OTG0_OTG_STEREO_CONTROL, OTG_STEREO_EN, mask_sh),\ - SF(OTG0_OTG_STEREO_CONTROL, OTG_STEREO_SYNC_OUTPUT_LINE_NUM, mask_sh),\ - SF(OTG0_OTG_STEREO_CONTROL, OTG_STEREO_SYNC_OUTPUT_POLARITY, mask_sh),\ - SF(OTG0_OTG_STEREO_CONTROL, OTG_STEREO_EYE_FLAG_POLARITY, mask_sh),\ - SF(OTG0_OTG_STEREO_CONTROL, OTG_DISABLE_STEREOSYNC_OUTPUT_FOR_DP, mask_sh),\ - SF(OTG0_OTG_STEREO_CONTROL, OTG_DISABLE_STEREOSYNC_OUTPUT_FOR_DP, mask_sh),\ - SF(OTG0_OTG_STEREO_STATUS, OTG_STEREO_CURRENT_EYE, mask_sh),\ - SF(OTG0_OTG_3D_STRUCTURE_CONTROL, OTG_3D_STRUCTURE_EN, mask_sh),\ - SF(OTG0_OTG_3D_STRUCTURE_CONTROL, OTG_3D_STRUCTURE_V_UPDATE_MODE, mask_sh),\ - SF(OTG0_OTG_3D_STRUCTURE_CONTROL, OTG_3D_STRUCTURE_STEREO_SEL_OVR, mask_sh),\ - SF(OTG0_OTG_V_TOTAL_MAX, OTG_V_TOTAL_MAX, mask_sh),\ - SF(OTG0_OTG_V_TOTAL_MID, OTG_V_TOTAL_MID, mask_sh),\ - SF(OTG0_OTG_V_TOTAL_MIN, OTG_V_TOTAL_MIN, mask_sh),\ - SF(OTG0_OTG_V_TOTAL_CONTROL, OTG_V_TOTAL_MIN_SEL, mask_sh),\ - SF(OTG0_OTG_V_TOTAL_CONTROL, OTG_V_TOTAL_MAX_SEL, mask_sh),\ - SF(OTG0_OTG_V_TOTAL_CONTROL, OTG_FORCE_LOCK_ON_EVENT, mask_sh),\ - SF(OTG0_OTG_V_TOTAL_CONTROL, OTG_SET_V_TOTAL_MIN_MASK_EN, mask_sh),\ - SF(OTG0_OTG_V_TOTAL_CONTROL, OTG_SET_V_TOTAL_MIN_MASK, mask_sh),\ - SF(OTG0_OTG_V_TOTAL_CONTROL, OTG_VTOTAL_MID_REPLACING_MAX_EN, mask_sh),\ - SF(OTG0_OTG_V_TOTAL_CONTROL, OTG_VTOTAL_MID_FRAME_NUM, mask_sh),\ - SF(OTG0_OTG_FORCE_COUNT_NOW_CNTL, OTG_FORCE_COUNT_NOW_CLEAR, mask_sh),\ - SF(OTG0_OTG_FORCE_COUNT_NOW_CNTL, OTG_FORCE_COUNT_NOW_MODE, mask_sh),\ - SF(OTG0_OTG_FORCE_COUNT_NOW_CNTL, OTG_FORCE_COUNT_NOW_OCCURRED, mask_sh),\ - SF(OTG0_OTG_TRIGA_CNTL, OTG_TRIGA_SOURCE_SELECT, mask_sh),\ - SF(OTG0_OTG_TRIGA_CNTL, OTG_TRIGA_SOURCE_PIPE_SELECT, mask_sh),\ - SF(OTG0_OTG_TRIGA_CNTL, OTG_TRIGA_RISING_EDGE_DETECT_CNTL, mask_sh),\ - SF(OTG0_OTG_TRIGA_CNTL, OTG_TRIGA_FALLING_EDGE_DETECT_CNTL, mask_sh),\ - SF(OTG0_OTG_TRIGA_CNTL, OTG_TRIGA_POLARITY_SELECT, mask_sh),\ - SF(OTG0_OTG_TRIGA_CNTL, OTG_TRIGA_FREQUENCY_SELECT, mask_sh),\ - SF(OTG0_OTG_TRIGA_CNTL, OTG_TRIGA_DELAY, mask_sh),\ - SF(OTG0_OTG_TRIGA_CNTL, OTG_TRIGA_CLEAR, mask_sh),\ - SF(OTG0_OTG_TRIGA_MANUAL_TRIG, OTG_TRIGA_MANUAL_TRIG, mask_sh),\ - SF(OTG0_OTG_STATIC_SCREEN_CONTROL, OTG_STATIC_SCREEN_EVENT_MASK, mask_sh),\ - SF(OTG0_OTG_STATIC_SCREEN_CONTROL, OTG_STATIC_SCREEN_FRAME_COUNT, mask_sh),\ - SF(OTG0_OTG_STATUS_FRAME_COUNT, OTG_FRAME_COUNT, mask_sh),\ - SF(OTG0_OTG_STATUS, OTG_V_BLANK, mask_sh),\ - SF(OTG0_OTG_STATUS, OTG_V_ACTIVE_DISP, mask_sh),\ - SF(OTG0_OTG_STATUS_POSITION, OTG_HORZ_COUNT, mask_sh),\ - SF(OTG0_OTG_STATUS_POSITION, OTG_VERT_COUNT, mask_sh),\ - SF(OTG0_OTG_NOM_VERT_POSITION, OTG_VERT_COUNT_NOM, mask_sh),\ - SF(OTG0_OTG_BLACK_COLOR, OTG_BLACK_COLOR_B_CB, mask_sh),\ - SF(OTG0_OTG_BLACK_COLOR, OTG_BLACK_COLOR_G_Y, mask_sh),\ - SF(OTG0_OTG_BLACK_COLOR, OTG_BLACK_COLOR_R_CR, mask_sh),\ - SF(OTG0_OTG_CLOCK_CONTROL, OTG_BUSY, mask_sh),\ - SF(OTG0_OTG_CLOCK_CONTROL, OTG_CLOCK_EN, mask_sh),\ - SF(OTG0_OTG_CLOCK_CONTROL, OTG_CLOCK_ON, mask_sh),\ - SF(OTG0_OTG_CLOCK_CONTROL, OTG_CLOCK_GATE_DIS, mask_sh),\ - SF(OTG0_OTG_VERTICAL_INTERRUPT0_CONTROL, OTG_VERTICAL_INTERRUPT0_INT_ENABLE, mask_sh),\ - SF(OTG0_OTG_VERTICAL_INTERRUPT0_POSITION, OTG_VERTICAL_INTERRUPT0_LINE_START, mask_sh),\ - SF(OTG0_OTG_VERTICAL_INTERRUPT0_POSITION, OTG_VERTICAL_INTERRUPT0_LINE_END, mask_sh),\ - SF(OTG0_OTG_VERTICAL_INTERRUPT1_CONTROL, OTG_VERTICAL_INTERRUPT1_INT_ENABLE, mask_sh),\ - SF(OTG0_OTG_VERTICAL_INTERRUPT1_POSITION, OTG_VERTICAL_INTERRUPT1_LINE_START, mask_sh),\ - SF(OTG0_OTG_VERTICAL_INTERRUPT2_CONTROL, OTG_VERTICAL_INTERRUPT2_INT_ENABLE, mask_sh),\ - SF(OTG0_OTG_VERTICAL_INTERRUPT2_POSITION, OTG_VERTICAL_INTERRUPT2_LINE_START, mask_sh),\ - SF(ODM0_OPTC_INPUT_CLOCK_CONTROL, OPTC_INPUT_CLK_EN, mask_sh),\ - SF(ODM0_OPTC_INPUT_CLOCK_CONTROL, OPTC_INPUT_CLK_ON, mask_sh),\ - SF(ODM0_OPTC_INPUT_CLOCK_CONTROL, OPTC_INPUT_CLK_GATE_DIS, mask_sh),\ - SF(ODM0_OPTC_INPUT_GLOBAL_CONTROL, OPTC_UNDERFLOW_OCCURRED_STATUS, mask_sh),\ - SF(ODM0_OPTC_INPUT_GLOBAL_CONTROL, OPTC_UNDERFLOW_CLEAR, mask_sh),\ - SF(VTG0_CONTROL, VTG0_ENABLE, mask_sh),\ - SF(VTG0_CONTROL, VTG0_FP2, mask_sh),\ - SF(VTG0_CONTROL, VTG0_VCOUNT_INIT, mask_sh),\ - SF(OTG0_OTG_VERT_SYNC_CONTROL, OTG_FORCE_VSYNC_NEXT_LINE_OCCURRED, mask_sh),\ - SF(OTG0_OTG_VERT_SYNC_CONTROL, OTG_FORCE_VSYNC_NEXT_LINE_CLEAR, mask_sh),\ - SF(OTG0_OTG_VERT_SYNC_CONTROL, OTG_AUTO_FORCE_VSYNC_MODE, mask_sh),\ - SF(OTG0_OTG_MASTER_UPDATE_MODE, MASTER_UPDATE_INTERLACED_MODE, mask_sh),\ - SF(OTG0_OTG_GSL_CONTROL, OTG_GSL0_EN, mask_sh),\ - SF(OTG0_OTG_GSL_CONTROL, OTG_GSL1_EN, mask_sh),\ - SF(OTG0_OTG_GSL_CONTROL, OTG_GSL2_EN, mask_sh),\ - SF(OTG0_OTG_GSL_CONTROL, OTG_GSL_MASTER_EN, mask_sh),\ - SF(OTG0_OTG_GSL_CONTROL, OTG_GSL_FORCE_DELAY, mask_sh),\ - SF(OTG0_OTG_GSL_CONTROL, OTG_GSL_CHECK_ALL_FIELDS, mask_sh),\ - SF(OTG0_OTG_CRC_CNTL, OTG_CRC_CONT_EN, mask_sh),\ - SF(OTG0_OTG_CRC_CNTL, OTG_CRC0_SELECT, mask_sh),\ - SF(OTG0_OTG_CRC_CNTL, OTG_CRC_EN, mask_sh),\ - SF(OTG0_OTG_CRC0_DATA_RG, CRC0_R_CR, mask_sh),\ - SF(OTG0_OTG_CRC0_DATA_RG, CRC0_G_Y, mask_sh),\ - SF(OTG0_OTG_CRC0_DATA_B, CRC0_B_CB, mask_sh),\ - SF(OTG0_OTG_CRC0_WINDOWA_X_CONTROL, OTG_CRC0_WINDOWA_X_START, mask_sh),\ - SF(OTG0_OTG_CRC0_WINDOWA_X_CONTROL, OTG_CRC0_WINDOWA_X_END, mask_sh),\ - SF(OTG0_OTG_CRC0_WINDOWA_Y_CONTROL, OTG_CRC0_WINDOWA_Y_START, mask_sh),\ - SF(OTG0_OTG_CRC0_WINDOWA_Y_CONTROL, OTG_CRC0_WINDOWA_Y_END, mask_sh),\ - SF(OTG0_OTG_CRC0_WINDOWB_X_CONTROL, OTG_CRC0_WINDOWB_X_START, mask_sh),\ - SF(OTG0_OTG_CRC0_WINDOWB_X_CONTROL, OTG_CRC0_WINDOWB_X_END, mask_sh),\ - SF(OTG0_OTG_CRC0_WINDOWB_Y_CONTROL, OTG_CRC0_WINDOWB_Y_START, mask_sh),\ - SF(OTG0_OTG_CRC0_WINDOWB_Y_CONTROL, OTG_CRC0_WINDOWB_Y_END, mask_sh),\ - SF(GSL_SOURCE_SELECT, GSL0_READY_SOURCE_SEL, mask_sh),\ - SF(GSL_SOURCE_SELECT, GSL1_READY_SOURCE_SEL, mask_sh),\ - SF(GSL_SOURCE_SELECT, GSL2_READY_SOURCE_SEL, mask_sh),\ - SF(OTG0_OTG_GLOBAL_CONTROL2, MANUAL_FLOW_CONTROL_SEL, mask_sh) - - - -#define TG_COMMON_MASK_SH_LIST_DCN1_0(mask_sh)\ - TG_COMMON_MASK_SH_LIST_DCN(mask_sh),\ - SF(OTG0_OTG_TEST_PATTERN_PARAMETERS, OTG_TEST_PATTERN_INC0, mask_sh),\ - SF(OTG0_OTG_TEST_PATTERN_PARAMETERS, OTG_TEST_PATTERN_INC1, mask_sh),\ - SF(OTG0_OTG_TEST_PATTERN_PARAMETERS, OTG_TEST_PATTERN_VRES, mask_sh),\ - SF(OTG0_OTG_TEST_PATTERN_PARAMETERS, OTG_TEST_PATTERN_HRES, mask_sh),\ - SF(OTG0_OTG_TEST_PATTERN_PARAMETERS, OTG_TEST_PATTERN_RAMP0_OFFSET, mask_sh),\ - SF(OTG0_OTG_TEST_PATTERN_CONTROL, OTG_TEST_PATTERN_EN, mask_sh),\ - SF(OTG0_OTG_TEST_PATTERN_CONTROL, OTG_TEST_PATTERN_MODE, mask_sh),\ - SF(OTG0_OTG_TEST_PATTERN_CONTROL, OTG_TEST_PATTERN_DYNAMIC_RANGE, mask_sh),\ - SF(OTG0_OTG_TEST_PATTERN_CONTROL, OTG_TEST_PATTERN_COLOR_FORMAT, mask_sh),\ - SF(OTG0_OTG_TEST_PATTERN_COLOR, OTG_TEST_PATTERN_MASK, mask_sh),\ - SF(OTG0_OTG_TEST_PATTERN_COLOR, OTG_TEST_PATTERN_DATA, mask_sh),\ - SF(ODM0_OPTC_DATA_SOURCE_SELECT, OPTC_SRC_SEL, mask_sh),\ - SF(OTG0_OTG_MANUAL_FLOW_CONTROL, MANUAL_FLOW_CONTROL, mask_sh),\ - -#define TG_REG_FIELD_LIST_DCN1_0(type) \ - type VSTARTUP_START;\ - type VUPDATE_OFFSET;\ - type VUPDATE_WIDTH;\ - type VREADY_OFFSET;\ - type OTG_BLANK_DATA_EN;\ - type OTG_BLANK_DE_MODE;\ - type OTG_CURRENT_BLANK_STATE;\ - type OTG_MASTER_UPDATE_LOCK;\ - type UPDATE_LOCK_STATUS;\ - type OTG_UPDATE_PENDING;\ - type OTG_MASTER_UPDATE_LOCK_SEL;\ - type OTG_BLANK_DATA_DOUBLE_BUFFER_EN;\ - type OTG_H_TOTAL;\ - type OTG_H_BLANK_START;\ - type OTG_H_BLANK_END;\ - type OTG_H_SYNC_A_START;\ - type OTG_H_SYNC_A_END;\ - type OTG_H_SYNC_A_POL;\ - type OTG_H_TIMING_DIV_BY2;\ - type OTG_V_TOTAL;\ - type OTG_V_BLANK_START;\ - type OTG_V_BLANK_END;\ - type OTG_V_SYNC_A_START;\ - type OTG_V_SYNC_A_END;\ - type OTG_V_SYNC_A_POL;\ - type OTG_INTERLACE_ENABLE;\ - type OTG_MASTER_EN;\ - type OTG_START_POINT_CNTL;\ - type OTG_DISABLE_POINT_CNTL;\ - type OTG_FIELD_NUMBER_CNTL;\ - type OTG_CURRENT_MASTER_EN_STATE;\ - type OTG_STEREO_EN;\ - type OTG_STEREO_SYNC_OUTPUT_LINE_NUM;\ - type OTG_STEREO_SYNC_OUTPUT_POLARITY;\ - type OTG_STEREO_EYE_FLAG_POLARITY;\ - type OTG_STEREO_CURRENT_EYE;\ - type OTG_DISABLE_STEREOSYNC_OUTPUT_FOR_DP;\ - type OTG_3D_STRUCTURE_EN;\ - type OTG_3D_STRUCTURE_V_UPDATE_MODE;\ - type OTG_3D_STRUCTURE_STEREO_SEL_OVR;\ - type OTG_V_TOTAL_MAX;\ - type OTG_V_TOTAL_MID;\ - type OTG_V_TOTAL_MIN;\ - type OTG_V_TOTAL_MIN_SEL;\ - type OTG_V_TOTAL_MAX_SEL;\ - type OTG_VTOTAL_MID_REPLACING_MAX_EN;\ - type OTG_VTOTAL_MID_FRAME_NUM;\ - type OTG_FORCE_LOCK_ON_EVENT;\ - type OTG_SET_V_TOTAL_MIN_MASK_EN;\ - type OTG_SET_V_TOTAL_MIN_MASK;\ - type OTG_FORCE_COUNT_NOW_CLEAR;\ - type OTG_FORCE_COUNT_NOW_MODE;\ - type OTG_FORCE_COUNT_NOW_OCCURRED;\ - type OTG_TRIGA_SOURCE_SELECT;\ - type OTG_TRIGA_SOURCE_PIPE_SELECT;\ - type OTG_TRIGA_RISING_EDGE_DETECT_CNTL;\ - type OTG_TRIGA_FALLING_EDGE_DETECT_CNTL;\ - type OTG_TRIGA_POLARITY_SELECT;\ - type OTG_TRIGA_FREQUENCY_SELECT;\ - type OTG_TRIGA_DELAY;\ - type OTG_TRIGA_CLEAR;\ - type OTG_TRIGA_MANUAL_TRIG;\ - type OTG_STATIC_SCREEN_EVENT_MASK;\ - type OTG_STATIC_SCREEN_FRAME_COUNT;\ - type OTG_FRAME_COUNT;\ - type OTG_V_BLANK;\ - type OTG_V_ACTIVE_DISP;\ - type OTG_HORZ_COUNT;\ - type OTG_VERT_COUNT;\ - type OTG_VERT_COUNT_NOM;\ - type OTG_BLACK_COLOR_B_CB;\ - type OTG_BLACK_COLOR_G_Y;\ - type OTG_BLACK_COLOR_R_CR;\ - type OTG_BLANK_DATA_COLOR_BLUE_CB;\ - type OTG_BLANK_DATA_COLOR_GREEN_Y;\ - type OTG_BLANK_DATA_COLOR_RED_CR;\ - type OTG_BLANK_DATA_COLOR_BLUE_CB_EXT;\ - type OTG_BLANK_DATA_COLOR_GREEN_Y_EXT;\ - type OTG_BLANK_DATA_COLOR_RED_CR_EXT;\ - type OTG_VTOTAL_MID_REPLACING_MIN_EN;\ - type OTG_TEST_PATTERN_INC0;\ - type OTG_TEST_PATTERN_INC1;\ - type OTG_TEST_PATTERN_VRES;\ - type OTG_TEST_PATTERN_HRES;\ - type OTG_TEST_PATTERN_RAMP0_OFFSET;\ - type OTG_TEST_PATTERN_EN;\ - type OTG_TEST_PATTERN_MODE;\ - type OTG_TEST_PATTERN_DYNAMIC_RANGE;\ - type OTG_TEST_PATTERN_COLOR_FORMAT;\ - type OTG_TEST_PATTERN_MASK;\ - type OTG_TEST_PATTERN_DATA;\ - type OTG_BUSY;\ - type OTG_CLOCK_EN;\ - type OTG_CLOCK_ON;\ - type OTG_CLOCK_GATE_DIS;\ - type OTG_VERTICAL_INTERRUPT0_INT_ENABLE;\ - type OTG_VERTICAL_INTERRUPT0_LINE_START;\ - type OTG_VERTICAL_INTERRUPT0_LINE_END;\ - type OTG_VERTICAL_INTERRUPT1_INT_ENABLE;\ - type OTG_VERTICAL_INTERRUPT1_LINE_START;\ - type OTG_VERTICAL_INTERRUPT2_INT_ENABLE;\ - type OTG_VERTICAL_INTERRUPT2_LINE_START;\ - type OPTC_INPUT_CLK_EN;\ - type OPTC_INPUT_CLK_ON;\ - type OPTC_INPUT_CLK_GATE_DIS;\ - type OPTC_UNDERFLOW_OCCURRED_STATUS;\ - type OPTC_UNDERFLOW_CLEAR;\ - type OPTC_SRC_SEL;\ - type VTG0_ENABLE;\ - type VTG0_FP2;\ - type VTG0_VCOUNT_INIT;\ - type OTG_FORCE_VSYNC_NEXT_LINE_OCCURRED;\ - type OTG_FORCE_VSYNC_NEXT_LINE_CLEAR;\ - type OTG_AUTO_FORCE_VSYNC_MODE;\ - type MASTER_UPDATE_INTERLACED_MODE;\ - type OTG_GSL0_EN;\ - type OTG_GSL1_EN;\ - type OTG_GSL2_EN;\ - type OTG_GSL_MASTER_EN;\ - type OTG_GSL_FORCE_DELAY;\ - type OTG_GSL_CHECK_ALL_FIELDS;\ - type OTG_GSL_WINDOW_START_X;\ - type OTG_GSL_WINDOW_END_X;\ - type OTG_GSL_WINDOW_START_Y;\ - type OTG_GSL_WINDOW_END_Y;\ - type OTG_RANGE_TIMING_DBUF_UPDATE_MODE;\ - type OTG_GSL_MASTER_MODE;\ - type OTG_MASTER_UPDATE_LOCK_GSL_EN;\ - type MASTER_UPDATE_LOCK_VUPDATE_KEEPOUT_START_OFFSET;\ - type MASTER_UPDATE_LOCK_VUPDATE_KEEPOUT_END_OFFSET;\ - type OTG_MASTER_UPDATE_LOCK_VUPDATE_KEEPOUT_EN;\ - type OTG_CRC_CONT_EN;\ - type OTG_CRC0_SELECT;\ - type OTG_CRC_EN;\ - type CRC0_R_CR;\ - type CRC0_G_Y;\ - type CRC0_B_CB;\ - type CRC1_R_CR;\ - type CRC1_G_Y;\ - type CRC1_B_CB;\ - type CRC2_R_CR;\ - type CRC2_G_Y;\ - type CRC2_B_CB;\ - type CRC3_R_CR;\ - type CRC3_G_Y;\ - type CRC3_B_CB;\ - type OTG_CRC0_WINDOWA_X_START;\ - type OTG_CRC0_WINDOWA_X_END;\ - type OTG_CRC0_WINDOWA_Y_START;\ - type OTG_CRC0_WINDOWA_Y_END;\ - type OTG_CRC0_WINDOWB_X_START;\ - type OTG_CRC0_WINDOWB_X_END;\ - type OTG_CRC0_WINDOWB_Y_START;\ - type OTG_CRC0_WINDOWB_Y_END;\ - type OTG_CRC_WINDOW_DB_EN;\ - type OTG_CRC1_WINDOWA_X_START;\ - type OTG_CRC1_WINDOWA_X_END;\ - type OTG_CRC1_WINDOWA_Y_START;\ - type OTG_CRC1_WINDOWA_Y_END;\ - type OTG_CRC1_WINDOWB_X_START;\ - type OTG_CRC1_WINDOWB_X_END;\ - type OTG_CRC1_WINDOWB_Y_START;\ - type OTG_CRC1_WINDOWB_Y_END;\ - type GSL0_READY_SOURCE_SEL;\ - type GSL1_READY_SOURCE_SEL;\ - type GSL2_READY_SOURCE_SEL;\ - type MANUAL_FLOW_CONTROL;\ - type MANUAL_FLOW_CONTROL_SEL; - -#define TG_REG_FIELD_LIST(type) \ - TG_REG_FIELD_LIST_DCN1_0(type)\ - type OTG_V_SYNC_MODE;\ - type OTG_DRR_TRIGGER_WINDOW_START_X;\ - type OTG_DRR_TRIGGER_WINDOW_END_X;\ - type OTG_DRR_V_TOTAL_CHANGE_LIMIT;\ - type OTG_OUT_MUX;\ - type OTG_M_CONST_DTO_PHASE;\ - type OTG_M_CONST_DTO_MODULO;\ - type MASTER_UPDATE_LOCK_DB_X;\ - type MASTER_UPDATE_LOCK_DB_Y;\ - type MASTER_UPDATE_LOCK_DB_EN;\ - type GLOBAL_UPDATE_LOCK_EN;\ - type DIG_UPDATE_LOCATION;\ - type OTG_DSC_START_POSITION_X;\ - type OTG_DSC_START_POSITION_LINE_NUM;\ - type OPTC_NUM_OF_INPUT_SEGMENT;\ - type OPTC_SEG0_SRC_SEL;\ - type OPTC_SEG1_SRC_SEL;\ - type OPTC_SEG2_SRC_SEL;\ - type OPTC_SEG3_SRC_SEL;\ - type OPTC_MEM_SEL;\ - type OPTC_DATA_FORMAT;\ - type OPTC_DSC_MODE;\ - type OPTC_DSC_BYTES_PER_PIXEL;\ - type OPTC_DSC_SLICE_WIDTH;\ - type OPTC_SEGMENT_WIDTH;\ - type OPTC_DWB0_SOURCE_SELECT;\ - type OPTC_DWB1_SOURCE_SELECT;\ - type MASTER_UPDATE_LOCK_DB_START_X;\ - type MASTER_UPDATE_LOCK_DB_END_X;\ - type MASTER_UPDATE_LOCK_DB_START_Y;\ - type MASTER_UPDATE_LOCK_DB_END_Y;\ - type DIG_UPDATE_POSITION_X;\ - type DIG_UPDATE_POSITION_Y;\ - type OTG_H_TIMING_DIV_MODE;\ - type OTG_DRR_TIMING_DBUF_UPDATE_MODE;\ - type OTG_CRC_DSC_MODE;\ - type OTG_CRC_DATA_STREAM_COMBINE_MODE;\ - type OTG_CRC_DATA_STREAM_SPLIT_MODE;\ - type OTG_CRC_DATA_FORMAT;\ - type OTG_V_TOTAL_LAST_USED_BY_DRR;\ - type OTG_DRR_TIMING_DBUF_UPDATE_PENDING; - -#define TG_REG_FIELD_LIST_DCN3_2(type) \ - type OTG_H_TIMING_DIV_MODE_MANUAL; - - -#define TG_REG_FIELD_LIST_DCN3_5(type) \ - type OTG_CRC0_WINDOWA_X_START_READBACK;\ - type OTG_CRC0_WINDOWA_X_END_READBACK;\ - type OTG_CRC0_WINDOWA_Y_START_READBACK;\ - type OTG_CRC0_WINDOWA_Y_END_READBACK;\ - type OTG_CRC0_WINDOWB_X_START_READBACK;\ - type OTG_CRC0_WINDOWB_X_END_READBACK;\ - type OTG_CRC0_WINDOWB_Y_START_READBACK;\ - type OTG_CRC0_WINDOWB_Y_END_READBACK; \ - type OTG_CRC1_WINDOWA_X_START_READBACK;\ - type OTG_CRC1_WINDOWA_X_END_READBACK;\ - type OTG_CRC1_WINDOWA_Y_START_READBACK;\ - type OTG_CRC1_WINDOWA_Y_END_READBACK;\ - type OTG_CRC1_WINDOWB_X_START_READBACK;\ - type OTG_CRC1_WINDOWB_X_END_READBACK;\ - type OTG_CRC1_WINDOWB_Y_START_READBACK;\ - type OTG_CRC1_WINDOWB_Y_END_READBACK;\ - type OPTC_FGCG_REP_DIS; - -struct dcn_optc_shift { - TG_REG_FIELD_LIST(uint8_t) - TG_REG_FIELD_LIST_DCN3_2(uint8_t) - TG_REG_FIELD_LIST_DCN3_5(uint8_t) -}; - -struct dcn_optc_mask { - TG_REG_FIELD_LIST(uint32_t) - TG_REG_FIELD_LIST_DCN3_2(uint32_t) - TG_REG_FIELD_LIST_DCN3_5(uint32_t) -}; - -void dcn10_timing_generator_init(struct optc *optc); - -#endif /* __DC_TIMING_GENERATOR_DCN10_H__ */ diff --git a/drivers/gpu/drm/amd/display/dc/dcn20/Makefile b/drivers/gpu/drm/amd/display/dc/dcn20/Makefile index 93ac45802e44..bd760442ff89 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn20/Makefile +++ b/drivers/gpu/drm/amd/display/dc/dcn20/Makefile @@ -3,7 +3,7 @@ # Makefile for DCN. DCN20 = dcn20_init.o dcn20_dpp.o dcn20_dpp_cm.o dcn20_hubp.o \ - dcn20_mpc.o dcn20_opp.o dcn20_hubbub.o dcn20_optc.o dcn20_mmhubbub.o \ + dcn20_mpc.o dcn20_opp.o dcn20_hubbub.o dcn20_mmhubbub.o \ dcn20_stream_encoder.o dcn20_link_encoder.o dcn20_dccg.o \ dcn20_vmid.o dcn20_dwb.o dcn20_dwb_scl.o diff --git a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_optc.c b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_optc.c deleted file mode 100644 index 58bdbd859bf9..000000000000 --- a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_optc.c +++ /dev/null @@ -1,587 +0,0 @@ -/* - * Copyright 2012-15 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 "reg_helper.h" -#include "dcn20_optc.h" -#include "dc.h" - -#define REG(reg)\ - optc1->tg_regs->reg - -#define CTX \ - optc1->base.ctx - -#undef FN -#define FN(reg_name, field_name) \ - optc1->tg_shift->field_name, optc1->tg_mask->field_name - -/** - * optc2_enable_crtc() - Enable CRTC - call ASIC Control Object to enable Timing generator. - * - * @optc: timing_generator instance. - * - * Return: If CRTC is enabled, return true. - * - */ -bool optc2_enable_crtc(struct timing_generator *optc) -{ - /* TODO FPGA wait for answer - * OTG_MASTER_UPDATE_MODE != CRTC_MASTER_UPDATE_MODE - * OTG_MASTER_UPDATE_LOCK != CRTC_MASTER_UPDATE_LOCK - */ - struct optc *optc1 = DCN10TG_FROM_TG(optc); - - /* opp instance for OTG. For DCN1.0, ODM is remoed. - * OPP and OPTC should 1:1 mapping - */ - REG_UPDATE(OPTC_DATA_SOURCE_SELECT, - OPTC_SEG0_SRC_SEL, optc->inst); - - /* VTG enable first is for HW workaround */ - REG_UPDATE(CONTROL, - VTG0_ENABLE, 1); - - REG_SEQ_START(); - - /* Enable CRTC */ - REG_UPDATE_2(OTG_CONTROL, - OTG_DISABLE_POINT_CNTL, 3, - OTG_MASTER_EN, 1); - - REG_SEQ_SUBMIT(); - REG_SEQ_WAIT_DONE(); - - return true; -} - -/** - * optc2_set_gsl() - Assign OTG to GSL groups, - * set one of the OTGs to be master & rest are slaves - * - * @optc: timing_generator instance. - * @params: pointer to gsl_params - */ -void optc2_set_gsl(struct timing_generator *optc, - const struct gsl_params *params) -{ - struct optc *optc1 = DCN10TG_FROM_TG(optc); - -/* - * There are (MAX_OPTC+1)/2 gsl groups available for use. - * In each group (assign an OTG to a group by setting OTG_GSLX_EN = 1, - * set one of the OTGs to be the master (OTG_GSL_MASTER_EN = 1) and the rest are slaves. - */ - REG_UPDATE_5(OTG_GSL_CONTROL, - OTG_GSL0_EN, params->gsl0_en, - OTG_GSL1_EN, params->gsl1_en, - OTG_GSL2_EN, params->gsl2_en, - OTG_GSL_MASTER_EN, params->gsl_master_en, - OTG_GSL_MASTER_MODE, params->gsl_master_mode); -} - - -void optc2_set_gsl_source_select( - struct timing_generator *optc, - int group_idx, - uint32_t gsl_ready_signal) -{ - struct optc *optc1 = DCN10TG_FROM_TG(optc); - - switch (group_idx) { - case 1: - REG_UPDATE(GSL_SOURCE_SELECT, GSL0_READY_SOURCE_SEL, gsl_ready_signal); - break; - case 2: - REG_UPDATE(GSL_SOURCE_SELECT, GSL1_READY_SOURCE_SEL, gsl_ready_signal); - break; - case 3: - REG_UPDATE(GSL_SOURCE_SELECT, GSL2_READY_SOURCE_SEL, gsl_ready_signal); - break; - default: - break; - } -} - -/* Set DSC-related configuration. - * dsc_mode: 0 disables DSC, other values enable DSC in specified format - * sc_bytes_per_pixel: Bytes per pixel in u3.28 format - * dsc_slice_width: Slice width in pixels - */ -void optc2_set_dsc_config(struct timing_generator *optc, - enum optc_dsc_mode dsc_mode, - uint32_t dsc_bytes_per_pixel, - uint32_t dsc_slice_width) -{ - struct optc *optc1 = DCN10TG_FROM_TG(optc); - - REG_UPDATE(OPTC_DATA_FORMAT_CONTROL, - OPTC_DSC_MODE, dsc_mode); - - REG_SET(OPTC_BYTES_PER_PIXEL, 0, - OPTC_DSC_BYTES_PER_PIXEL, dsc_bytes_per_pixel); - - REG_UPDATE(OPTC_WIDTH_CONTROL, - OPTC_DSC_SLICE_WIDTH, dsc_slice_width); -} - -/* Get DSC-related configuration. - * dsc_mode: 0 disables DSC, other values enable DSC in specified format - */ -void optc2_get_dsc_status(struct timing_generator *optc, - uint32_t *dsc_mode) -{ - struct optc *optc1 = DCN10TG_FROM_TG(optc); - - REG_GET(OPTC_DATA_FORMAT_CONTROL, - OPTC_DSC_MODE, dsc_mode); -} - - -/*TEMP: Need to figure out inheritance model here.*/ -bool optc2_is_two_pixels_per_containter(const struct dc_crtc_timing *timing) -{ - return optc1_is_two_pixels_per_containter(timing); -} - -void optc2_set_odm_bypass(struct timing_generator *optc, - const struct dc_crtc_timing *dc_crtc_timing) -{ - struct optc *optc1 = DCN10TG_FROM_TG(optc); - uint32_t h_div_2 = 0; - - REG_SET_3(OPTC_DATA_SOURCE_SELECT, 0, - OPTC_NUM_OF_INPUT_SEGMENT, 0, - OPTC_SEG0_SRC_SEL, optc->inst, - OPTC_SEG1_SRC_SEL, 0xf); - REG_WRITE(OTG_H_TIMING_CNTL, 0); - - h_div_2 = optc2_is_two_pixels_per_containter(dc_crtc_timing); - REG_UPDATE(OTG_H_TIMING_CNTL, - OTG_H_TIMING_DIV_BY2, h_div_2); - REG_SET(OPTC_MEMORY_CONFIG, 0, - OPTC_MEM_SEL, 0); - optc1->opp_count = 1; -} - -void optc2_set_odm_combine(struct timing_generator *optc, int *opp_id, int opp_cnt, - struct dc_crtc_timing *timing) -{ - struct optc *optc1 = DCN10TG_FROM_TG(optc); - int mpcc_hactive = (timing->h_addressable + timing->h_border_left + timing->h_border_right) - / opp_cnt; - uint32_t memory_mask; - - ASSERT(opp_cnt == 2); - - /* TODO: In pseudocode but does not affect maximus, delete comment if we dont need on asic - * REG_SET(OTG_GLOBAL_CONTROL2, 0, GLOBAL_UPDATE_LOCK_EN, 1); - * Program OTG register MASTER_UPDATE_LOCK_DB_X/Y to the position before DP frame start - * REG_SET_2(OTG_GLOBAL_CONTROL1, 0, - * MASTER_UPDATE_LOCK_DB_X, 160, - * MASTER_UPDATE_LOCK_DB_Y, 240); - */ - - /* 2 pieces of memory required for up to 5120 displays, 4 for up to 8192, - * however, for ODM combine we can simplify by always using 4. - * To make sure there's no overlap, each instance "reserves" 2 memories and - * they are uniquely combined here. - */ - memory_mask = 0x3 << (opp_id[0] * 2) | 0x3 << (opp_id[1] * 2); - - if (REG(OPTC_MEMORY_CONFIG)) - REG_SET(OPTC_MEMORY_CONFIG, 0, - OPTC_MEM_SEL, memory_mask); - - REG_SET_3(OPTC_DATA_SOURCE_SELECT, 0, - OPTC_NUM_OF_INPUT_SEGMENT, 1, - OPTC_SEG0_SRC_SEL, opp_id[0], - OPTC_SEG1_SRC_SEL, opp_id[1]); - - REG_UPDATE(OPTC_WIDTH_CONTROL, - OPTC_SEGMENT_WIDTH, mpcc_hactive); - - REG_SET(OTG_H_TIMING_CNTL, 0, OTG_H_TIMING_DIV_BY2, 1); - optc1->opp_count = opp_cnt; -} - -void optc2_get_optc_source(struct timing_generator *optc, - uint32_t *num_of_src_opp, - uint32_t *src_opp_id_0, - uint32_t *src_opp_id_1) -{ - uint32_t num_of_input_segments; - struct optc *optc1 = DCN10TG_FROM_TG(optc); - - REG_GET_3(OPTC_DATA_SOURCE_SELECT, - OPTC_NUM_OF_INPUT_SEGMENT, &num_of_input_segments, - OPTC_SEG0_SRC_SEL, src_opp_id_0, - OPTC_SEG1_SRC_SEL, src_opp_id_1); - - if (num_of_input_segments == 1) - *num_of_src_opp = 2; - else - *num_of_src_opp = 1; - - /* Work around VBIOS not updating OPTC_NUM_OF_INPUT_SEGMENT */ - if (*src_opp_id_1 == 0xf) - *num_of_src_opp = 1; -} - -static void optc2_set_dwb_source(struct timing_generator *optc, - uint32_t dwb_pipe_inst) -{ - struct optc *optc1 = DCN10TG_FROM_TG(optc); - - if (dwb_pipe_inst == 0) - REG_UPDATE(DWB_SOURCE_SELECT, - OPTC_DWB0_SOURCE_SELECT, optc->inst); - else if (dwb_pipe_inst == 1) - REG_UPDATE(DWB_SOURCE_SELECT, - OPTC_DWB1_SOURCE_SELECT, optc->inst); -} - -static void optc2_align_vblanks( - struct timing_generator *optc_master, - struct timing_generator *optc_slave, - uint32_t master_pixel_clock_100Hz, - uint32_t slave_pixel_clock_100Hz, - uint8_t master_clock_divider, - uint8_t slave_clock_divider) -{ - /* accessing slave OTG registers */ - struct optc *optc1 = DCN10TG_FROM_TG(optc_slave); - - uint32_t master_v_active = 0; - uint32_t master_h_total = 0; - uint32_t slave_h_total = 0; - uint64_t L, XY; - uint32_t X, Y, p = 10000; - uint32_t master_update_lock; - - /* disable slave OTG */ - REG_UPDATE(OTG_CONTROL, OTG_MASTER_EN, 0); - /* wait until disabled */ - REG_WAIT(OTG_CONTROL, - OTG_CURRENT_MASTER_EN_STATE, - 0, 10, 5000); - - REG_GET(OTG_H_TOTAL, OTG_H_TOTAL, &slave_h_total); - - /* assign slave OTG to be controlled by master update lock */ - REG_SET(OTG_GLOBAL_CONTROL0, 0, - OTG_MASTER_UPDATE_LOCK_SEL, optc_master->inst); - - /* accessing master OTG registers */ - optc1 = DCN10TG_FROM_TG(optc_master); - - /* saving update lock state, not sure if it's needed */ - REG_GET(OTG_MASTER_UPDATE_LOCK, - OTG_MASTER_UPDATE_LOCK, &master_update_lock); - /* unlocking master OTG */ - REG_SET(OTG_MASTER_UPDATE_LOCK, 0, - OTG_MASTER_UPDATE_LOCK, 0); - - REG_GET(OTG_V_BLANK_START_END, - OTG_V_BLANK_START, &master_v_active); - REG_GET(OTG_H_TOTAL, OTG_H_TOTAL, &master_h_total); - - /* calculate when to enable slave OTG */ - L = (uint64_t)p * slave_h_total * master_pixel_clock_100Hz; - L = div_u64(L, master_h_total); - L = div_u64(L, slave_pixel_clock_100Hz); - XY = div_u64(L, p); - Y = master_v_active - XY - 1; - X = div_u64(((XY + 1) * p - L) * master_h_total, p * master_clock_divider); - - /* - * set master OTG to unlock when V/H - * counters reach calculated values - */ - REG_UPDATE(OTG_GLOBAL_CONTROL1, - MASTER_UPDATE_LOCK_DB_EN, 1); - REG_UPDATE_2(OTG_GLOBAL_CONTROL1, - MASTER_UPDATE_LOCK_DB_X, - X, - MASTER_UPDATE_LOCK_DB_Y, - Y); - - /* lock master OTG */ - REG_SET(OTG_MASTER_UPDATE_LOCK, 0, - OTG_MASTER_UPDATE_LOCK, 1); - REG_WAIT(OTG_MASTER_UPDATE_LOCK, - UPDATE_LOCK_STATUS, 1, 1, 10); - - /* accessing slave OTG registers */ - optc1 = DCN10TG_FROM_TG(optc_slave); - - /* - * enable slave OTG, the OTG is locked with - * master's update lock, so it will not run - */ - REG_UPDATE(OTG_CONTROL, - OTG_MASTER_EN, 1); - - /* accessing master OTG registers */ - optc1 = DCN10TG_FROM_TG(optc_master); - - /* - * unlock master OTG. When master H/V counters reach - * DB_XY point, slave OTG will start - */ - REG_SET(OTG_MASTER_UPDATE_LOCK, 0, - OTG_MASTER_UPDATE_LOCK, 0); - - /* accessing slave OTG registers */ - optc1 = DCN10TG_FROM_TG(optc_slave); - - /* wait for slave OTG to start running*/ - REG_WAIT(OTG_CONTROL, - OTG_CURRENT_MASTER_EN_STATE, - 1, 10, 5000); - - /* accessing master OTG registers */ - optc1 = DCN10TG_FROM_TG(optc_master); - - /* disable the XY point*/ - REG_UPDATE(OTG_GLOBAL_CONTROL1, - MASTER_UPDATE_LOCK_DB_EN, 0); - REG_UPDATE_2(OTG_GLOBAL_CONTROL1, - MASTER_UPDATE_LOCK_DB_X, - 0, - MASTER_UPDATE_LOCK_DB_Y, - 0); - - /*restore master update lock*/ - REG_SET(OTG_MASTER_UPDATE_LOCK, 0, - OTG_MASTER_UPDATE_LOCK, master_update_lock); - - /* accessing slave OTG registers */ - optc1 = DCN10TG_FROM_TG(optc_slave); - /* restore slave to be controlled by it's own */ - REG_SET(OTG_GLOBAL_CONTROL0, 0, - OTG_MASTER_UPDATE_LOCK_SEL, optc_slave->inst); - -} - -void optc2_triplebuffer_lock(struct timing_generator *optc) -{ - struct optc *optc1 = DCN10TG_FROM_TG(optc); - - REG_SET(OTG_GLOBAL_CONTROL0, 0, - OTG_MASTER_UPDATE_LOCK_SEL, optc->inst); - - REG_SET(OTG_VUPDATE_KEEPOUT, 0, - OTG_MASTER_UPDATE_LOCK_VUPDATE_KEEPOUT_EN, 1); - - REG_SET(OTG_MASTER_UPDATE_LOCK, 0, - OTG_MASTER_UPDATE_LOCK, 1); - - REG_WAIT(OTG_MASTER_UPDATE_LOCK, - UPDATE_LOCK_STATUS, 1, - 1, 10); -} - -void optc2_triplebuffer_unlock(struct timing_generator *optc) -{ - struct optc *optc1 = DCN10TG_FROM_TG(optc); - - REG_SET(OTG_MASTER_UPDATE_LOCK, 0, - OTG_MASTER_UPDATE_LOCK, 0); - - REG_SET(OTG_VUPDATE_KEEPOUT, 0, - OTG_MASTER_UPDATE_LOCK_VUPDATE_KEEPOUT_EN, 0); - -} - -void optc2_lock_doublebuffer_enable(struct timing_generator *optc) -{ - struct optc *optc1 = DCN10TG_FROM_TG(optc); - uint32_t v_blank_start = 0; - uint32_t h_blank_start = 0; - - REG_UPDATE(OTG_GLOBAL_CONTROL1, MASTER_UPDATE_LOCK_DB_EN, 1); - - REG_UPDATE_2(OTG_GLOBAL_CONTROL2, GLOBAL_UPDATE_LOCK_EN, 1, - DIG_UPDATE_LOCATION, 20); - - REG_GET(OTG_V_BLANK_START_END, OTG_V_BLANK_START, &v_blank_start); - - REG_GET(OTG_H_BLANK_START_END, OTG_H_BLANK_START, &h_blank_start); - - REG_UPDATE_2(OTG_GLOBAL_CONTROL1, - MASTER_UPDATE_LOCK_DB_X, - (h_blank_start - 200 - 1) / optc1->opp_count, - MASTER_UPDATE_LOCK_DB_Y, - v_blank_start - 1); - - REG_SET_3(OTG_VUPDATE_KEEPOUT, 0, - MASTER_UPDATE_LOCK_VUPDATE_KEEPOUT_START_OFFSET, 0, - MASTER_UPDATE_LOCK_VUPDATE_KEEPOUT_END_OFFSET, 100, - OTG_MASTER_UPDATE_LOCK_VUPDATE_KEEPOUT_EN, 1); -} - -void optc2_lock_doublebuffer_disable(struct timing_generator *optc) -{ - struct optc *optc1 = DCN10TG_FROM_TG(optc); - - REG_UPDATE_2(OTG_GLOBAL_CONTROL1, - MASTER_UPDATE_LOCK_DB_X, - 0, - MASTER_UPDATE_LOCK_DB_Y, - 0); - - REG_UPDATE_2(OTG_GLOBAL_CONTROL2, GLOBAL_UPDATE_LOCK_EN, 0, - DIG_UPDATE_LOCATION, 0); - - REG_UPDATE(OTG_GLOBAL_CONTROL1, MASTER_UPDATE_LOCK_DB_EN, 0); -} - -void optc2_setup_manual_trigger(struct timing_generator *optc) -{ - struct optc *optc1 = DCN10TG_FROM_TG(optc); - - /* Set the min/max selectors unconditionally so that - * DMCUB fw may change OTG timings when necessary - * TODO: Remove the w/a after fixing the issue in DMCUB firmware - */ - REG_UPDATE_4(OTG_V_TOTAL_CONTROL, - OTG_V_TOTAL_MIN_SEL, 1, - OTG_V_TOTAL_MAX_SEL, 1, - OTG_FORCE_LOCK_ON_EVENT, 0, - OTG_SET_V_TOTAL_MIN_MASK, (1 << 1)); /* TRIGA */ - - REG_SET_8(OTG_TRIGA_CNTL, 0, - OTG_TRIGA_SOURCE_SELECT, 21, - OTG_TRIGA_SOURCE_PIPE_SELECT, optc->inst, - OTG_TRIGA_RISING_EDGE_DETECT_CNTL, 1, - OTG_TRIGA_FALLING_EDGE_DETECT_CNTL, 0, - OTG_TRIGA_POLARITY_SELECT, 0, - OTG_TRIGA_FREQUENCY_SELECT, 0, - OTG_TRIGA_DELAY, 0, - OTG_TRIGA_CLEAR, 1); -} - -void optc2_program_manual_trigger(struct timing_generator *optc) -{ - struct optc *optc1 = DCN10TG_FROM_TG(optc); - - REG_SET(OTG_TRIGA_MANUAL_TRIG, 0, - OTG_TRIGA_MANUAL_TRIG, 1); -} - -bool optc2_configure_crc(struct timing_generator *optc, - const struct crc_params *params) -{ - struct optc *optc1 = DCN10TG_FROM_TG(optc); - - REG_SET_2(OTG_CRC_CNTL2, 0, - OTG_CRC_DSC_MODE, params->dsc_mode, - OTG_CRC_DATA_STREAM_COMBINE_MODE, params->odm_mode); - - return optc1_configure_crc(optc, params); -} - - -void optc2_get_last_used_drr_vtotal(struct timing_generator *optc, uint32_t *refresh_rate) -{ - struct optc *optc1 = DCN10TG_FROM_TG(optc); - - REG_GET(OTG_DRR_CONTROL, OTG_V_TOTAL_LAST_USED_BY_DRR, refresh_rate); -} - -static struct timing_generator_funcs dcn20_tg_funcs = { - .validate_timing = optc1_validate_timing, - .program_timing = optc1_program_timing, - .setup_vertical_interrupt0 = optc1_setup_vertical_interrupt0, - .setup_vertical_interrupt1 = optc1_setup_vertical_interrupt1, - .setup_vertical_interrupt2 = optc1_setup_vertical_interrupt2, - .program_global_sync = optc1_program_global_sync, - .enable_crtc = optc2_enable_crtc, - .disable_crtc = optc1_disable_crtc, - /* used by enable_timing_synchronization. Not need for FPGA */ - .is_counter_moving = optc1_is_counter_moving, - .get_position = optc1_get_position, - .get_frame_count = optc1_get_vblank_counter, - .get_scanoutpos = optc1_get_crtc_scanoutpos, - .get_otg_active_size = optc1_get_otg_active_size, - .set_early_control = optc1_set_early_control, - /* used by enable_timing_synchronization. Not need for FPGA */ - .wait_for_state = optc1_wait_for_state, - .set_blank = optc1_set_blank, - .is_blanked = optc1_is_blanked, - .set_blank_color = optc1_program_blank_color, - .enable_reset_trigger = optc1_enable_reset_trigger, - .enable_crtc_reset = optc1_enable_crtc_reset, - .did_triggered_reset_occur = optc1_did_triggered_reset_occur, - .triplebuffer_lock = optc2_triplebuffer_lock, - .triplebuffer_unlock = optc2_triplebuffer_unlock, - .disable_reset_trigger = optc1_disable_reset_trigger, - .lock = optc1_lock, - .unlock = optc1_unlock, - .lock_doublebuffer_enable = optc2_lock_doublebuffer_enable, - .lock_doublebuffer_disable = optc2_lock_doublebuffer_disable, - .enable_optc_clock = optc1_enable_optc_clock, - .set_drr = optc1_set_drr, - .get_last_used_drr_vtotal = optc2_get_last_used_drr_vtotal, - .set_vtotal_min_max = optc1_set_vtotal_min_max, - .set_static_screen_control = optc1_set_static_screen_control, - .program_stereo = optc1_program_stereo, - .is_stereo_left_eye = optc1_is_stereo_left_eye, - .set_blank_data_double_buffer = optc1_set_blank_data_double_buffer, - .tg_init = optc1_tg_init, - .is_tg_enabled = optc1_is_tg_enabled, - .is_optc_underflow_occurred = optc1_is_optc_underflow_occurred, - .clear_optc_underflow = optc1_clear_optc_underflow, - .setup_global_swap_lock = NULL, - .get_crc = optc1_get_crc, - .configure_crc = optc2_configure_crc, - .set_dsc_config = optc2_set_dsc_config, - .get_dsc_status = optc2_get_dsc_status, - .set_dwb_source = optc2_set_dwb_source, - .set_odm_bypass = optc2_set_odm_bypass, - .set_odm_combine = optc2_set_odm_combine, - .get_optc_source = optc2_get_optc_source, - .set_gsl = optc2_set_gsl, - .set_gsl_source_select = optc2_set_gsl_source_select, - .set_vtg_params = optc1_set_vtg_params, - .program_manual_trigger = optc2_program_manual_trigger, - .setup_manual_trigger = optc2_setup_manual_trigger, - .get_hw_timing = optc1_get_hw_timing, - .align_vblanks = optc2_align_vblanks, -}; - -void dcn20_timing_generator_init(struct optc *optc1) -{ - optc1->base.funcs = &dcn20_tg_funcs; - - optc1->max_h_total = optc1->tg_mask->OTG_H_TOTAL + 1; - optc1->max_v_total = optc1->tg_mask->OTG_V_TOTAL + 1; - - optc1->min_h_blank = 32; - optc1->min_v_blank = 3; - optc1->min_v_blank_interlace = 5; - optc1->min_h_sync_width = 4;// Minimum HSYNC = 8 pixels asked By HW in the first place for no actual reason. Oculus Rift S will not light up with 8 as it's hsyncWidth is 6. Changing it to 4 to fix that issue. - optc1->min_v_sync_width = 1; -} diff --git a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_optc.h b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_optc.h deleted file mode 100644 index f7968b9ca16e..000000000000 --- a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_optc.h +++ /dev/null @@ -1,124 +0,0 @@ -/* - * Copyright 2012-15 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_OPTC_DCN20_H__ -#define __DC_OPTC_DCN20_H__ - -#include "../dcn10/dcn10_optc.h" - -#define TG_COMMON_REG_LIST_DCN2_0(inst) \ - TG_COMMON_REG_LIST_DCN(inst),\ - SRI(OTG_GLOBAL_CONTROL1, OTG, inst),\ - SRI(OTG_GLOBAL_CONTROL2, OTG, inst),\ - SRI(OTG_GSL_WINDOW_X, OTG, inst),\ - SRI(OTG_GSL_WINDOW_Y, OTG, inst),\ - SRI(OTG_VUPDATE_KEEPOUT, OTG, inst),\ - SRI(OTG_DSC_START_POSITION, OTG, inst),\ - SRI(OTG_CRC_CNTL2, OTG, inst),\ - SRI(OPTC_DATA_FORMAT_CONTROL, ODM, inst),\ - SRI(OPTC_BYTES_PER_PIXEL, ODM, inst),\ - SRI(OPTC_WIDTH_CONTROL, ODM, inst),\ - SRI(OPTC_MEMORY_CONFIG, ODM, inst),\ - SR(DWB_SOURCE_SELECT),\ - SRI(OTG_MANUAL_FLOW_CONTROL, OTG, inst), \ - SRI(OTG_DRR_CONTROL, OTG, inst) - -#define TG_COMMON_MASK_SH_LIST_DCN2_0(mask_sh)\ - TG_COMMON_MASK_SH_LIST_DCN(mask_sh),\ - SF(OTG0_OTG_GLOBAL_CONTROL1, MASTER_UPDATE_LOCK_DB_X, mask_sh),\ - SF(OTG0_OTG_GLOBAL_CONTROL1, MASTER_UPDATE_LOCK_DB_Y, mask_sh),\ - SF(OTG0_OTG_GLOBAL_CONTROL1, MASTER_UPDATE_LOCK_DB_EN, mask_sh),\ - SF(OTG0_OTG_GLOBAL_CONTROL2, GLOBAL_UPDATE_LOCK_EN, mask_sh),\ - SF(OTG0_OTG_GLOBAL_CONTROL2, DIG_UPDATE_LOCATION, mask_sh),\ - SF(OTG0_OTG_DOUBLE_BUFFER_CONTROL, OTG_RANGE_TIMING_DBUF_UPDATE_MODE, mask_sh),\ - SF(OTG0_OTG_GSL_WINDOW_X, OTG_GSL_WINDOW_START_X, mask_sh),\ - SF(OTG0_OTG_GSL_WINDOW_X, OTG_GSL_WINDOW_END_X, mask_sh), \ - SF(OTG0_OTG_GSL_WINDOW_Y, OTG_GSL_WINDOW_START_Y, mask_sh),\ - SF(OTG0_OTG_GSL_WINDOW_Y, OTG_GSL_WINDOW_END_Y, mask_sh),\ - SF(OTG0_OTG_GSL_CONTROL, OTG_GSL_MASTER_MODE, mask_sh), \ - SF(OTG0_OTG_GSL_CONTROL, OTG_MASTER_UPDATE_LOCK_GSL_EN, mask_sh), \ - SF(OTG0_OTG_DSC_START_POSITION, OTG_DSC_START_POSITION_X, mask_sh), \ - SF(OTG0_OTG_DSC_START_POSITION, OTG_DSC_START_POSITION_LINE_NUM, mask_sh),\ - SF(OTG0_OTG_CRC_CNTL2, OTG_CRC_DSC_MODE, mask_sh),\ - SF(OTG0_OTG_CRC_CNTL2, OTG_CRC_DATA_STREAM_COMBINE_MODE, mask_sh),\ - SF(OTG0_OTG_CRC_CNTL2, OTG_CRC_DATA_STREAM_SPLIT_MODE, mask_sh),\ - SF(OTG0_OTG_CRC_CNTL2, OTG_CRC_DATA_FORMAT, mask_sh),\ - SF(ODM0_OPTC_DATA_SOURCE_SELECT, OPTC_SEG0_SRC_SEL, mask_sh),\ - SF(ODM0_OPTC_DATA_SOURCE_SELECT, OPTC_SEG1_SRC_SEL, mask_sh),\ - SF(ODM0_OPTC_DATA_SOURCE_SELECT, OPTC_NUM_OF_INPUT_SEGMENT, mask_sh),\ - SF(ODM0_OPTC_MEMORY_CONFIG, OPTC_MEM_SEL, mask_sh),\ - SF(ODM0_OPTC_DATA_FORMAT_CONTROL, OPTC_DATA_FORMAT, mask_sh),\ - SF(ODM0_OPTC_DATA_FORMAT_CONTROL, OPTC_DSC_MODE, mask_sh),\ - SF(ODM0_OPTC_BYTES_PER_PIXEL, OPTC_DSC_BYTES_PER_PIXEL, mask_sh),\ - SF(ODM0_OPTC_WIDTH_CONTROL, OPTC_DSC_SLICE_WIDTH, mask_sh),\ - SF(ODM0_OPTC_WIDTH_CONTROL, OPTC_SEGMENT_WIDTH, mask_sh),\ - SF(DWB_SOURCE_SELECT, OPTC_DWB0_SOURCE_SELECT, mask_sh),\ - SF(DWB_SOURCE_SELECT, OPTC_DWB1_SOURCE_SELECT, mask_sh),\ - SF(OTG0_OTG_MANUAL_FLOW_CONTROL, MANUAL_FLOW_CONTROL, mask_sh), \ - SF(OTG0_OTG_DRR_CONTROL, OTG_V_TOTAL_LAST_USED_BY_DRR, mask_sh) - -void dcn20_timing_generator_init(struct optc *optc); - -void optc2_get_last_used_drr_vtotal(struct timing_generator *optc, - uint32_t *refresh_rate); - -bool optc2_enable_crtc(struct timing_generator *optc); - -void optc2_set_gsl(struct timing_generator *optc, - const struct gsl_params *params); - -void optc2_set_gsl_source_select(struct timing_generator *optc, - int group_idx, - uint32_t gsl_ready_signal); - -void optc2_set_dsc_config(struct timing_generator *optc, - enum optc_dsc_mode dsc_mode, - uint32_t dsc_bytes_per_pixel, - uint32_t dsc_slice_width); - -void optc2_get_dsc_status(struct timing_generator *optc, - uint32_t *dsc_mode); - -void optc2_set_odm_bypass(struct timing_generator *optc, - const struct dc_crtc_timing *dc_crtc_timing); - -void optc2_set_odm_combine(struct timing_generator *optc, int *opp_id, int opp_cnt, - struct dc_crtc_timing *timing); - -void optc2_get_optc_source(struct timing_generator *optc, - uint32_t *num_of_src_opp, - uint32_t *src_opp_id_0, - uint32_t *src_opp_id_1); - -void optc2_triplebuffer_lock(struct timing_generator *optc); -void optc2_triplebuffer_unlock(struct timing_generator *optc); -void optc2_lock_doublebuffer_disable(struct timing_generator *optc); -void optc2_lock_doublebuffer_enable(struct timing_generator *optc); -void optc2_setup_manual_trigger(struct timing_generator *optc); -void optc2_program_manual_trigger(struct timing_generator *optc); -bool optc2_is_two_pixels_per_containter(const struct dc_crtc_timing *timing); -bool optc2_configure_crc(struct timing_generator *optc, - const struct crc_params *params); -#endif /* __DC_OPTC_DCN20_H__ */ diff --git a/drivers/gpu/drm/amd/display/dc/dcn201/Makefile b/drivers/gpu/drm/amd/display/dc/dcn201/Makefile index c069a894db92..a101e6511555 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn201/Makefile +++ b/drivers/gpu/drm/amd/display/dc/dcn201/Makefile @@ -3,7 +3,7 @@ # Makefile for DCN. DCN201 = dcn201_init.o \ dcn201_hubbub.o\ - dcn201_mpc.o dcn201_hubp.o dcn201_opp.o dcn201_optc.o dcn201_dpp.o \ + dcn201_mpc.o dcn201_hubp.o dcn201_opp.o dcn201_dpp.o \ dcn201_dccg.o dcn201_link_encoder.o AMD_DAL_DCN201 = $(addprefix $(AMDDALPATH)/dc/dcn201/,$(DCN201)) diff --git a/drivers/gpu/drm/amd/display/dc/dcn201/dcn201_optc.c b/drivers/gpu/drm/amd/display/dc/dcn201/dcn201_optc.c deleted file mode 100644 index 70fcbec03fb6..000000000000 --- a/drivers/gpu/drm/amd/display/dc/dcn201/dcn201_optc.c +++ /dev/null @@ -1,202 +0,0 @@ -/* - * Copyright 2012-15 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 "reg_helper.h" -#include "dcn201_optc.h" -#include "dcn10/dcn10_optc.h" -#include "dc.h" - -#define REG(reg)\ - optc1->tg_regs->reg - -#define CTX \ - optc1->base.ctx - -#undef FN -#define FN(reg_name, field_name) \ - optc1->tg_shift->field_name, optc1->tg_mask->field_name - -/*TEMP: Need to figure out inheritance model here.*/ -bool optc201_is_two_pixels_per_containter(const struct dc_crtc_timing *timing) -{ - return optc1_is_two_pixels_per_containter(timing); -} - -static void optc201_triplebuffer_lock(struct timing_generator *optc) -{ - struct optc *optc1 = DCN10TG_FROM_TG(optc); - - REG_SET(OTG_GLOBAL_CONTROL0, 0, - OTG_MASTER_UPDATE_LOCK_SEL, optc->inst); - REG_SET(OTG_VUPDATE_KEEPOUT, 0, - OTG_MASTER_UPDATE_LOCK_VUPDATE_KEEPOUT_EN, 1); - REG_SET(OTG_MASTER_UPDATE_LOCK, 0, - OTG_MASTER_UPDATE_LOCK, 1); - - REG_WAIT(OTG_MASTER_UPDATE_LOCK, - UPDATE_LOCK_STATUS, 1, - 1, 10); -} - -static void optc201_triplebuffer_unlock(struct timing_generator *optc) -{ - struct optc *optc1 = DCN10TG_FROM_TG(optc); - - REG_SET(OTG_MASTER_UPDATE_LOCK, 0, - OTG_MASTER_UPDATE_LOCK, 0); - REG_SET(OTG_VUPDATE_KEEPOUT, 0, - OTG_MASTER_UPDATE_LOCK_VUPDATE_KEEPOUT_EN, 0); - -} - -static bool optc201_validate_timing( - struct timing_generator *optc, - const struct dc_crtc_timing *timing) -{ - uint32_t v_blank; - uint32_t h_blank; - uint32_t min_v_blank; - struct optc *optc1 = DCN10TG_FROM_TG(optc); - - ASSERT(timing != NULL); - - v_blank = (timing->v_total - timing->v_addressable - - timing->v_border_top - timing->v_border_bottom); - - h_blank = (timing->h_total - timing->h_addressable - - timing->h_border_right - - timing->h_border_left); - - if (timing->timing_3d_format != TIMING_3D_FORMAT_NONE && - timing->timing_3d_format != TIMING_3D_FORMAT_HW_FRAME_PACKING && - timing->timing_3d_format != TIMING_3D_FORMAT_TOP_AND_BOTTOM && - timing->timing_3d_format != TIMING_3D_FORMAT_SIDE_BY_SIDE && - timing->timing_3d_format != TIMING_3D_FORMAT_FRAME_ALTERNATE && - timing->timing_3d_format != TIMING_3D_FORMAT_INBAND_FA) - return false; - - /* Check maximum number of pixels supported by Timing Generator - * (Currently will never fail, in order to fail needs display which - * needs more than 8192 horizontal and - * more than 8192 vertical total pixels) - */ - if (timing->h_total > optc1->max_h_total || - timing->v_total > optc1->max_v_total) - return false; - - if (h_blank < optc1->min_h_blank) - return false; - - if (timing->h_sync_width < optc1->min_h_sync_width || - timing->v_sync_width < optc1->min_v_sync_width) - return false; - - min_v_blank = timing->flags.INTERLACE?optc1->min_v_blank_interlace:optc1->min_v_blank; - - if (v_blank < min_v_blank) - return false; - - return true; - -} - -static void optc201_get_optc_source(struct timing_generator *optc, - uint32_t *num_of_src_opp, - uint32_t *src_opp_id_0, - uint32_t *src_opp_id_1) -{ - struct optc *optc1 = DCN10TG_FROM_TG(optc); - - REG_GET(OPTC_DATA_SOURCE_SELECT, - OPTC_SEG0_SRC_SEL, src_opp_id_0); - - *num_of_src_opp = 1; -} - -static struct timing_generator_funcs dcn201_tg_funcs = { - .validate_timing = optc201_validate_timing, - .program_timing = optc1_program_timing, - .setup_vertical_interrupt0 = optc1_setup_vertical_interrupt0, - .setup_vertical_interrupt1 = optc1_setup_vertical_interrupt1, - .setup_vertical_interrupt2 = optc1_setup_vertical_interrupt2, - .program_global_sync = optc1_program_global_sync, - .enable_crtc = optc2_enable_crtc, - .disable_crtc = optc1_disable_crtc, - /* used by enable_timing_synchronization. Not need for FPGA */ - .is_counter_moving = optc1_is_counter_moving, - .get_position = optc1_get_position, - .get_frame_count = optc1_get_vblank_counter, - .get_scanoutpos = optc1_get_crtc_scanoutpos, - .get_otg_active_size = optc1_get_otg_active_size, - .set_early_control = optc1_set_early_control, - /* used by enable_timing_synchronization. Not need for FPGA */ - .wait_for_state = optc1_wait_for_state, - .set_blank = optc1_set_blank, - .is_blanked = optc1_is_blanked, - .set_blank_color = optc1_program_blank_color, - .did_triggered_reset_occur = optc1_did_triggered_reset_occur, - .enable_reset_trigger = optc1_enable_reset_trigger, - .enable_crtc_reset = optc1_enable_crtc_reset, - .disable_reset_trigger = optc1_disable_reset_trigger, - .triplebuffer_lock = optc201_triplebuffer_lock, - .triplebuffer_unlock = optc201_triplebuffer_unlock, - .lock = optc1_lock, - .unlock = optc1_unlock, - .enable_optc_clock = optc1_enable_optc_clock, - .set_drr = optc1_set_drr, - .get_last_used_drr_vtotal = NULL, - .set_vtotal_min_max = optc1_set_vtotal_min_max, - .set_static_screen_control = optc1_set_static_screen_control, - .program_stereo = optc1_program_stereo, - .is_stereo_left_eye = optc1_is_stereo_left_eye, - .set_blank_data_double_buffer = optc1_set_blank_data_double_buffer, - .tg_init = optc1_tg_init, - .is_tg_enabled = optc1_is_tg_enabled, - .is_optc_underflow_occurred = optc1_is_optc_underflow_occurred, - .clear_optc_underflow = optc1_clear_optc_underflow, - .get_crc = optc1_get_crc, - .configure_crc = optc2_configure_crc, - .set_dsc_config = optc2_set_dsc_config, - .set_dwb_source = NULL, - .get_optc_source = optc201_get_optc_source, - .set_vtg_params = optc1_set_vtg_params, - .program_manual_trigger = optc2_program_manual_trigger, - .setup_manual_trigger = optc2_setup_manual_trigger, - .get_hw_timing = optc1_get_hw_timing, -}; - -void dcn201_timing_generator_init(struct optc *optc1) -{ - optc1->base.funcs = &dcn201_tg_funcs; - - optc1->max_h_total = optc1->tg_mask->OTG_H_TOTAL + 1; - optc1->max_v_total = optc1->tg_mask->OTG_V_TOTAL + 1; - - optc1->min_h_blank = 32; - optc1->min_v_blank = 3; - optc1->min_v_blank_interlace = 5; - optc1->min_h_sync_width = 8; - optc1->min_v_sync_width = 1; -} diff --git a/drivers/gpu/drm/amd/display/dc/dcn201/dcn201_optc.h b/drivers/gpu/drm/amd/display/dc/dcn201/dcn201_optc.h deleted file mode 100644 index e9545b73513a..000000000000 --- a/drivers/gpu/drm/amd/display/dc/dcn201/dcn201_optc.h +++ /dev/null @@ -1,74 +0,0 @@ -/* - * Copyright 2012-15 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_OPTC_DCN201_H__ -#define __DC_OPTC_DCN201_H__ - -#include "dcn20/dcn20_optc.h" - -#define TG_COMMON_REG_LIST_DCN201(inst) \ - TG_COMMON_REG_LIST_DCN(inst),\ - SRI(OTG_GLOBAL_CONTROL1, OTG, inst),\ - SRI(OTG_GLOBAL_CONTROL2, OTG, inst),\ - SRI(OTG_GSL_WINDOW_X, OTG, inst),\ - SRI(OTG_GSL_WINDOW_Y, OTG, inst),\ - SRI(OTG_VUPDATE_KEEPOUT, OTG, inst),\ - SRI(OTG_DSC_START_POSITION, OTG, inst),\ - SRI(OPTC_DATA_FORMAT_CONTROL, ODM, inst),\ - SRI(OPTC_BYTES_PER_PIXEL, ODM, inst),\ - SRI(OPTC_WIDTH_CONTROL, ODM, inst),\ - SR(DWB_SOURCE_SELECT) - -#define TG_COMMON_MASK_SH_LIST_DCN201(mask_sh)\ - TG_COMMON_MASK_SH_LIST_DCN(mask_sh),\ - SF(OTG0_OTG_GLOBAL_CONTROL1, MASTER_UPDATE_LOCK_DB_X, mask_sh),\ - SF(OTG0_OTG_GLOBAL_CONTROL1, MASTER_UPDATE_LOCK_DB_Y, mask_sh),\ - SF(OTG0_OTG_GLOBAL_CONTROL1, MASTER_UPDATE_LOCK_DB_EN, mask_sh),\ - SF(OTG0_OTG_GLOBAL_CONTROL2, GLOBAL_UPDATE_LOCK_EN, mask_sh),\ - SF(OTG0_OTG_DOUBLE_BUFFER_CONTROL, OTG_RANGE_TIMING_DBUF_UPDATE_MODE, mask_sh),\ - SF(OTG0_OTG_GSL_WINDOW_X, OTG_GSL_WINDOW_START_X, mask_sh),\ - SF(OTG0_OTG_GSL_WINDOW_X, OTG_GSL_WINDOW_END_X, mask_sh), \ - SF(OTG0_OTG_GSL_WINDOW_Y, OTG_GSL_WINDOW_START_Y, mask_sh),\ - SF(OTG0_OTG_GSL_WINDOW_Y, OTG_GSL_WINDOW_END_Y, mask_sh),\ - SF(OTG0_OTG_VUPDATE_KEEPOUT, OTG_MASTER_UPDATE_LOCK_VUPDATE_KEEPOUT_EN, mask_sh), \ - SF(OTG0_OTG_VUPDATE_KEEPOUT, MASTER_UPDATE_LOCK_VUPDATE_KEEPOUT_START_OFFSET, mask_sh), \ - SF(OTG0_OTG_VUPDATE_KEEPOUT, MASTER_UPDATE_LOCK_VUPDATE_KEEPOUT_END_OFFSET, mask_sh), \ - SF(OTG0_OTG_GSL_CONTROL, OTG_GSL_MASTER_MODE, mask_sh), \ - SF(OTG0_OTG_GSL_CONTROL, OTG_MASTER_UPDATE_LOCK_GSL_EN, mask_sh), \ - SF(OTG0_OTG_DSC_START_POSITION, OTG_DSC_START_POSITION_X, mask_sh), \ - SF(OTG0_OTG_DSC_START_POSITION, OTG_DSC_START_POSITION_LINE_NUM, mask_sh),\ - SF(ODM0_OPTC_DATA_SOURCE_SELECT, OPTC_SEG0_SRC_SEL, mask_sh),\ - SF(ODM0_OPTC_DATA_FORMAT_CONTROL, OPTC_DSC_MODE, mask_sh),\ - SF(ODM0_OPTC_BYTES_PER_PIXEL, OPTC_DSC_BYTES_PER_PIXEL, mask_sh),\ - SF(ODM0_OPTC_WIDTH_CONTROL, OPTC_DSC_SLICE_WIDTH, mask_sh),\ - SF(DWB_SOURCE_SELECT, OPTC_DWB0_SOURCE_SELECT, mask_sh),\ - SF(DWB_SOURCE_SELECT, OPTC_DWB1_SOURCE_SELECT, mask_sh),\ - SF(DWB_SOURCE_SELECT, OPTC_DWB1_SOURCE_SELECT, mask_sh) - -void dcn201_timing_generator_init(struct optc *optc); - -bool optc201_is_two_pixels_per_containter(const struct dc_crtc_timing *timing); - -#endif diff --git a/drivers/gpu/drm/amd/display/dc/dcn30/Makefile b/drivers/gpu/drm/amd/display/dc/dcn30/Makefile index 9dcf06c0954d..cd95f322235e 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn30/Makefile +++ b/drivers/gpu/drm/amd/display/dc/dcn30/Makefile @@ -28,7 +28,6 @@ DCN30 := \ dcn30_hubbub.o \ dcn30_hubp.o \ dcn30_dpp.o \ - dcn30_optc.o \ dcn30_dccg.o \ dcn30_mpc.o dcn30_vpg.o \ dcn30_afmt.o \ diff --git a/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_optc.c b/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_optc.c deleted file mode 100644 index b97bdb868a0e..000000000000 --- a/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_optc.c +++ /dev/null @@ -1,393 +0,0 @@ -/* - * Copyright 2020 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 "reg_helper.h" -#include "dcn30_optc.h" -#include "dc.h" -#include "dcn_calc_math.h" -#include "dc_dmub_srv.h" - -#include "dml/dcn30/dcn30_fpu.h" -#include "dc_trace.h" - -#define REG(reg)\ - optc1->tg_regs->reg - -#define CTX \ - optc1->base.ctx - -#undef FN -#define FN(reg_name, field_name) \ - optc1->tg_shift->field_name, optc1->tg_mask->field_name - -void optc3_triplebuffer_lock(struct timing_generator *optc) -{ - struct optc *optc1 = DCN10TG_FROM_TG(optc); - - REG_UPDATE(OTG_GLOBAL_CONTROL2, - OTG_MASTER_UPDATE_LOCK_SEL, optc->inst); - - REG_SET(OTG_VUPDATE_KEEPOUT, 0, - OTG_MASTER_UPDATE_LOCK_VUPDATE_KEEPOUT_EN, 1); - - REG_SET(OTG_MASTER_UPDATE_LOCK, 0, - OTG_MASTER_UPDATE_LOCK, 1); - - REG_WAIT(OTG_MASTER_UPDATE_LOCK, - UPDATE_LOCK_STATUS, 1, - 1, 10); - - TRACE_OPTC_LOCK_UNLOCK_STATE(optc1, optc->inst, true); -} - -void optc3_lock_doublebuffer_enable(struct timing_generator *optc) -{ - struct optc *optc1 = DCN10TG_FROM_TG(optc); - uint32_t v_blank_start = 0; - uint32_t v_blank_end = 0; - uint32_t h_blank_start = 0; - uint32_t h_blank_end = 0; - - REG_GET_2(OTG_V_BLANK_START_END, - OTG_V_BLANK_START, &v_blank_start, - OTG_V_BLANK_END, &v_blank_end); - REG_GET_2(OTG_H_BLANK_START_END, - OTG_H_BLANK_START, &h_blank_start, - OTG_H_BLANK_END, &h_blank_end); - - REG_UPDATE_2(OTG_GLOBAL_CONTROL1, - MASTER_UPDATE_LOCK_DB_START_Y, v_blank_start - 1, - MASTER_UPDATE_LOCK_DB_END_Y, v_blank_start); - REG_UPDATE_2(OTG_GLOBAL_CONTROL4, - DIG_UPDATE_POSITION_X, h_blank_start - 180 - 1, - DIG_UPDATE_POSITION_Y, v_blank_start - 1); - // there is a DIG_UPDATE_VCOUNT_MODE and it is 0. - - REG_UPDATE_3(OTG_GLOBAL_CONTROL0, - MASTER_UPDATE_LOCK_DB_START_X, h_blank_start - 200 - 1, - MASTER_UPDATE_LOCK_DB_END_X, h_blank_start - 180, - MASTER_UPDATE_LOCK_DB_EN, 1); - REG_UPDATE(OTG_GLOBAL_CONTROL2, GLOBAL_UPDATE_LOCK_EN, 1); - - REG_SET_3(OTG_VUPDATE_KEEPOUT, 0, - MASTER_UPDATE_LOCK_VUPDATE_KEEPOUT_START_OFFSET, 0, - MASTER_UPDATE_LOCK_VUPDATE_KEEPOUT_END_OFFSET, 100, - OTG_MASTER_UPDATE_LOCK_VUPDATE_KEEPOUT_EN, 1); - - TRACE_OPTC_LOCK_UNLOCK_STATE(optc1, optc->inst, true); -} - -void optc3_lock_doublebuffer_disable(struct timing_generator *optc) -{ - struct optc *optc1 = DCN10TG_FROM_TG(optc); - - REG_UPDATE_2(OTG_GLOBAL_CONTROL0, - MASTER_UPDATE_LOCK_DB_START_X, 0, - MASTER_UPDATE_LOCK_DB_END_X, 0); - REG_UPDATE_2(OTG_GLOBAL_CONTROL1, - MASTER_UPDATE_LOCK_DB_START_Y, 0, - MASTER_UPDATE_LOCK_DB_END_Y, 0); - - REG_UPDATE(OTG_GLOBAL_CONTROL2, GLOBAL_UPDATE_LOCK_EN, 0); - REG_UPDATE(OTG_GLOBAL_CONTROL0, MASTER_UPDATE_LOCK_DB_EN, 0); - - TRACE_OPTC_LOCK_UNLOCK_STATE(optc1, optc->inst, true); -} - -void optc3_lock(struct timing_generator *optc) -{ - struct optc *optc1 = DCN10TG_FROM_TG(optc); - - REG_UPDATE(OTG_GLOBAL_CONTROL2, - OTG_MASTER_UPDATE_LOCK_SEL, optc->inst); - REG_SET(OTG_MASTER_UPDATE_LOCK, 0, - OTG_MASTER_UPDATE_LOCK, 1); - - REG_WAIT(OTG_MASTER_UPDATE_LOCK, - UPDATE_LOCK_STATUS, 1, - 1, 10); - - TRACE_OPTC_LOCK_UNLOCK_STATE(optc1, optc->inst, true); -} - -void optc3_set_out_mux(struct timing_generator *optc, enum otg_out_mux_dest dest) -{ - struct optc *optc1 = DCN10TG_FROM_TG(optc); - - REG_UPDATE(OTG_CONTROL, OTG_OUT_MUX, dest); -} - -void optc3_program_blank_color(struct timing_generator *optc, - const struct tg_color *blank_color) -{ - struct optc *optc1 = DCN10TG_FROM_TG(optc); - - REG_SET_3(OTG_BLANK_DATA_COLOR, 0, - OTG_BLANK_DATA_COLOR_BLUE_CB, blank_color->color_b_cb, - OTG_BLANK_DATA_COLOR_GREEN_Y, blank_color->color_g_y, - OTG_BLANK_DATA_COLOR_RED_CR, blank_color->color_r_cr); - - REG_SET_3(OTG_BLANK_DATA_COLOR_EXT, 0, - OTG_BLANK_DATA_COLOR_BLUE_CB_EXT, blank_color->color_b_cb >> 10, - OTG_BLANK_DATA_COLOR_GREEN_Y_EXT, blank_color->color_g_y >> 10, - OTG_BLANK_DATA_COLOR_RED_CR_EXT, blank_color->color_r_cr >> 10); -} - -void optc3_set_drr_trigger_window(struct timing_generator *optc, - uint32_t window_start, uint32_t window_end) -{ - struct optc *optc1 = DCN10TG_FROM_TG(optc); - - REG_SET_2(OTG_DRR_TRIGGER_WINDOW, 0, - OTG_DRR_TRIGGER_WINDOW_START_X, window_start, - OTG_DRR_TRIGGER_WINDOW_END_X, window_end); -} - -void optc3_set_vtotal_change_limit(struct timing_generator *optc, - uint32_t limit) -{ - struct optc *optc1 = DCN10TG_FROM_TG(optc); - - - REG_SET(OTG_DRR_V_TOTAL_CHANGE, 0, - OTG_DRR_V_TOTAL_CHANGE_LIMIT, limit); -} - - -/* Set DSC-related configuration. - * dsc_mode: 0 disables DSC, other values enable DSC in specified format - * sc_bytes_per_pixel: Bytes per pixel in u3.28 format - * dsc_slice_width: Slice width in pixels - */ -void optc3_set_dsc_config(struct timing_generator *optc, - enum optc_dsc_mode dsc_mode, - uint32_t dsc_bytes_per_pixel, - uint32_t dsc_slice_width) -{ - struct optc *optc1 = DCN10TG_FROM_TG(optc); - - optc2_set_dsc_config(optc, dsc_mode, dsc_bytes_per_pixel, dsc_slice_width); - REG_UPDATE(OTG_V_SYNC_A_CNTL, OTG_V_SYNC_MODE, 0); -} - -void optc3_set_odm_bypass(struct timing_generator *optc, - const struct dc_crtc_timing *dc_crtc_timing) -{ - struct optc *optc1 = DCN10TG_FROM_TG(optc); - enum h_timing_div_mode h_div = H_TIMING_NO_DIV; - - REG_SET_5(OPTC_DATA_SOURCE_SELECT, 0, - OPTC_NUM_OF_INPUT_SEGMENT, 0, - OPTC_SEG0_SRC_SEL, optc->inst, - OPTC_SEG1_SRC_SEL, 0xf, - OPTC_SEG2_SRC_SEL, 0xf, - OPTC_SEG3_SRC_SEL, 0xf - ); - - h_div = optc1_is_two_pixels_per_containter(dc_crtc_timing); - REG_UPDATE(OTG_H_TIMING_CNTL, - OTG_H_TIMING_DIV_MODE, h_div); - - REG_SET(OPTC_MEMORY_CONFIG, 0, - OPTC_MEM_SEL, 0); - optc1->opp_count = 1; -} - -void optc3_set_odm_combine(struct timing_generator *optc, int *opp_id, int opp_cnt, - struct dc_crtc_timing *timing) -{ - struct optc *optc1 = DCN10TG_FROM_TG(optc); - int mpcc_hactive = (timing->h_addressable + timing->h_border_left + timing->h_border_right) - / opp_cnt; - uint32_t memory_mask = 0; - - /* TODO: In pseudocode but does not affect maximus, delete comment if we dont need on asic - * REG_SET(OTG_GLOBAL_CONTROL2, 0, GLOBAL_UPDATE_LOCK_EN, 1); - * Program OTG register MASTER_UPDATE_LOCK_DB_X/Y to the position before DP frame start - * REG_SET_2(OTG_GLOBAL_CONTROL1, 0, - * MASTER_UPDATE_LOCK_DB_X, 160, - * MASTER_UPDATE_LOCK_DB_Y, 240); - */ - - ASSERT(opp_cnt == 2 || opp_cnt == 4); - - /* 2 pieces of memory required for up to 5120 displays, 4 for up to 8192, - * however, for ODM combine we can simplify by always using 4. - */ - if (opp_cnt == 2) { - /* To make sure there's no memory overlap, each instance "reserves" 2 - * memories and they are uniquely combined here. - */ - memory_mask = 0x3 << (opp_id[0] * 2) | 0x3 << (opp_id[1] * 2); - } else if (opp_cnt == 4) { - /* To make sure there's no memory overlap, each instance "reserves" 1 - * memory and they are uniquely combined here. - */ - memory_mask = 0x1 << (opp_id[0] * 2) | 0x1 << (opp_id[1] * 2) | 0x1 << (opp_id[2] * 2) | 0x1 << (opp_id[3] * 2); - } - - if (REG(OPTC_MEMORY_CONFIG)) - REG_SET(OPTC_MEMORY_CONFIG, 0, - OPTC_MEM_SEL, memory_mask); - - if (opp_cnt == 2) { - REG_SET_3(OPTC_DATA_SOURCE_SELECT, 0, - OPTC_NUM_OF_INPUT_SEGMENT, 1, - OPTC_SEG0_SRC_SEL, opp_id[0], - OPTC_SEG1_SRC_SEL, opp_id[1]); - } else if (opp_cnt == 4) { - REG_SET_5(OPTC_DATA_SOURCE_SELECT, 0, - OPTC_NUM_OF_INPUT_SEGMENT, 3, - OPTC_SEG0_SRC_SEL, opp_id[0], - OPTC_SEG1_SRC_SEL, opp_id[1], - OPTC_SEG2_SRC_SEL, opp_id[2], - OPTC_SEG3_SRC_SEL, opp_id[3]); - } - - REG_UPDATE(OPTC_WIDTH_CONTROL, - OPTC_SEGMENT_WIDTH, mpcc_hactive); - - REG_SET(OTG_H_TIMING_CNTL, 0, OTG_H_TIMING_DIV_MODE, opp_cnt - 1); - optc1->opp_count = opp_cnt; -} - -/** - * optc3_set_timing_double_buffer() - DRR double buffering control - * - * Sets double buffer point for V_TOTAL, H_TOTAL, VTOTAL_MIN, - * VTOTAL_MAX, VTOTAL_MIN_SEL and VTOTAL_MAX_SEL registers. - * - * @optc: timing_generator instance. - * @enable: Enable DRR double buffering control if true, disable otherwise. - * - * Options: any time, start of frame, dp start of frame (range timing) - */ -static void optc3_set_timing_double_buffer(struct timing_generator *optc, bool enable) -{ - struct optc *optc1 = DCN10TG_FROM_TG(optc); - uint32_t mode = enable ? 2 : 0; - - REG_UPDATE(OTG_DOUBLE_BUFFER_CONTROL, - OTG_DRR_TIMING_DBUF_UPDATE_MODE, mode); -} - -void optc3_wait_drr_doublebuffer_pending_clear(struct timing_generator *optc) -{ - struct optc *optc1 = DCN10TG_FROM_TG(optc); - - REG_WAIT(OTG_DOUBLE_BUFFER_CONTROL, OTG_DRR_TIMING_DBUF_UPDATE_PENDING, 0, 2, 100000); /* 1 vupdate at 5hz */ - -} - -void optc3_set_vtotal_min_max(struct timing_generator *optc, int vtotal_min, int vtotal_max) -{ - struct dc *dc = optc->ctx->dc; - - if (dc->caps.dmub_caps.mclk_sw && !dc->debug.disable_fams) - dc_dmub_srv_drr_update_cmd(dc, optc->inst, vtotal_min, vtotal_max); - else - optc1_set_vtotal_min_max(optc, vtotal_min, vtotal_max); -} - -void optc3_tg_init(struct timing_generator *optc) -{ - optc3_set_timing_double_buffer(optc, true); - optc1_clear_optc_underflow(optc); -} - -static struct timing_generator_funcs dcn30_tg_funcs = { - .validate_timing = optc1_validate_timing, - .program_timing = optc1_program_timing, - .setup_vertical_interrupt0 = optc1_setup_vertical_interrupt0, - .setup_vertical_interrupt1 = optc1_setup_vertical_interrupt1, - .setup_vertical_interrupt2 = optc1_setup_vertical_interrupt2, - .program_global_sync = optc1_program_global_sync, - .enable_crtc = optc2_enable_crtc, - .disable_crtc = optc1_disable_crtc, - /* used by enable_timing_synchronization. Not need for FPGA */ - .is_counter_moving = optc1_is_counter_moving, - .get_position = optc1_get_position, - .get_frame_count = optc1_get_vblank_counter, - .get_scanoutpos = optc1_get_crtc_scanoutpos, - .get_otg_active_size = optc1_get_otg_active_size, - .set_early_control = optc1_set_early_control, - /* used by enable_timing_synchronization. Not need for FPGA */ - .wait_for_state = optc1_wait_for_state, - .set_blank_color = optc3_program_blank_color, - .did_triggered_reset_occur = optc1_did_triggered_reset_occur, - .triplebuffer_lock = optc3_triplebuffer_lock, - .triplebuffer_unlock = optc2_triplebuffer_unlock, - .enable_reset_trigger = optc1_enable_reset_trigger, - .enable_crtc_reset = optc1_enable_crtc_reset, - .disable_reset_trigger = optc1_disable_reset_trigger, - .lock = optc3_lock, - .unlock = optc1_unlock, - .lock_doublebuffer_enable = optc3_lock_doublebuffer_enable, - .lock_doublebuffer_disable = optc3_lock_doublebuffer_disable, - .enable_optc_clock = optc1_enable_optc_clock, - .set_drr = optc1_set_drr, - .get_last_used_drr_vtotal = optc2_get_last_used_drr_vtotal, - .set_vtotal_min_max = optc3_set_vtotal_min_max, - .set_static_screen_control = optc1_set_static_screen_control, - .program_stereo = optc1_program_stereo, - .is_stereo_left_eye = optc1_is_stereo_left_eye, - .tg_init = optc3_tg_init, - .is_tg_enabled = optc1_is_tg_enabled, - .is_optc_underflow_occurred = optc1_is_optc_underflow_occurred, - .clear_optc_underflow = optc1_clear_optc_underflow, - .setup_global_swap_lock = NULL, - .get_crc = optc1_get_crc, - .configure_crc = optc2_configure_crc, - .set_dsc_config = optc3_set_dsc_config, - .get_dsc_status = optc2_get_dsc_status, - .set_dwb_source = NULL, - .set_odm_bypass = optc3_set_odm_bypass, - .set_odm_combine = optc3_set_odm_combine, - .get_optc_source = optc2_get_optc_source, - .set_out_mux = optc3_set_out_mux, - .set_drr_trigger_window = optc3_set_drr_trigger_window, - .set_vtotal_change_limit = optc3_set_vtotal_change_limit, - .set_gsl = optc2_set_gsl, - .set_gsl_source_select = optc2_set_gsl_source_select, - .set_vtg_params = optc1_set_vtg_params, - .program_manual_trigger = optc2_program_manual_trigger, - .setup_manual_trigger = optc2_setup_manual_trigger, - .get_hw_timing = optc1_get_hw_timing, - .wait_drr_doublebuffer_pending_clear = optc3_wait_drr_doublebuffer_pending_clear, -}; - -void dcn30_timing_generator_init(struct optc *optc1) -{ - optc1->base.funcs = &dcn30_tg_funcs; - - optc1->max_h_total = optc1->tg_mask->OTG_H_TOTAL + 1; - optc1->max_v_total = optc1->tg_mask->OTG_V_TOTAL + 1; - - optc1->min_h_blank = 32; - optc1->min_v_blank = 3; - optc1->min_v_blank_interlace = 5; - optc1->min_h_sync_width = 4; - optc1->min_v_sync_width = 1; -} diff --git a/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_optc.h b/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_optc.h deleted file mode 100644 index d3a056c12b0d..000000000000 --- a/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_optc.h +++ /dev/null @@ -1,359 +0,0 @@ -/* - * Copyright 2020 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_OPTC_DCN30_H__ -#define __DC_OPTC_DCN30_H__ - -#include "dcn20/dcn20_optc.h" - -#define V_TOTAL_REGS_DCN30_SRI(inst) - -#define OPTC_COMMON_REG_LIST_DCN3_BASE(inst) \ - SRI(OTG_VSTARTUP_PARAM, OTG, inst),\ - SRI(OTG_VUPDATE_PARAM, OTG, inst),\ - SRI(OTG_VREADY_PARAM, OTG, inst),\ - SRI(OTG_MASTER_UPDATE_LOCK, OTG, inst),\ - SRI(OTG_GLOBAL_CONTROL0, OTG, inst),\ - SRI(OTG_GLOBAL_CONTROL1, OTG, inst),\ - SRI(OTG_GLOBAL_CONTROL2, OTG, inst),\ - SRI(OTG_GLOBAL_CONTROL4, OTG, inst),\ - SRI(OTG_DOUBLE_BUFFER_CONTROL, OTG, inst),\ - SRI(OTG_H_TOTAL, OTG, inst),\ - SRI(OTG_H_BLANK_START_END, OTG, inst),\ - SRI(OTG_H_SYNC_A, OTG, inst),\ - SRI(OTG_H_SYNC_A_CNTL, OTG, inst),\ - SRI(OTG_H_TIMING_CNTL, OTG, inst),\ - SRI(OTG_V_TOTAL, OTG, inst),\ - SRI(OTG_V_BLANK_START_END, OTG, inst),\ - SRI(OTG_V_SYNC_A, OTG, inst),\ - SRI(OTG_V_SYNC_A_CNTL, OTG, inst),\ - SRI(OTG_CONTROL, OTG, inst),\ - SRI(OTG_STEREO_CONTROL, OTG, inst),\ - SRI(OTG_3D_STRUCTURE_CONTROL, OTG, inst),\ - SRI(OTG_STEREO_STATUS, OTG, inst),\ - SRI(OTG_V_TOTAL_MAX, OTG, inst),\ - SRI(OTG_V_TOTAL_MIN, OTG, inst),\ - SRI(OTG_V_TOTAL_CONTROL, OTG, inst),\ - V_TOTAL_REGS_DCN30_SRI(inst)\ - SRI(OTG_TRIGA_CNTL, OTG, inst),\ - SRI(OTG_FORCE_COUNT_NOW_CNTL, OTG, inst),\ - SRI(OTG_STATIC_SCREEN_CONTROL, OTG, inst),\ - SRI(OTG_STATUS_FRAME_COUNT, OTG, inst),\ - SRI(OTG_STATUS, OTG, inst),\ - SRI(OTG_STATUS_POSITION, OTG, inst),\ - SRI(OTG_NOM_VERT_POSITION, OTG, inst),\ - SRI(OTG_BLANK_DATA_COLOR, OTG, inst),\ - SRI(OTG_BLANK_DATA_COLOR_EXT, OTG, inst),\ - SRI(OTG_M_CONST_DTO0, OTG, inst),\ - SRI(OTG_M_CONST_DTO1, OTG, inst),\ - SRI(OTG_CLOCK_CONTROL, OTG, inst),\ - SRI(OTG_VERTICAL_INTERRUPT0_CONTROL, OTG, inst),\ - SRI(OTG_VERTICAL_INTERRUPT0_POSITION, OTG, inst),\ - SRI(OTG_VERTICAL_INTERRUPT1_CONTROL, OTG, inst),\ - SRI(OTG_VERTICAL_INTERRUPT1_POSITION, OTG, inst),\ - SRI(OTG_VERTICAL_INTERRUPT2_CONTROL, OTG, inst),\ - SRI(OTG_VERTICAL_INTERRUPT2_POSITION, OTG, inst),\ - SRI(OPTC_INPUT_CLOCK_CONTROL, ODM, inst),\ - SRI(OPTC_DATA_SOURCE_SELECT, ODM, inst),\ - SRI(OPTC_INPUT_GLOBAL_CONTROL, ODM, inst),\ - SRI(CONTROL, VTG, inst),\ - SRI(OTG_VERT_SYNC_CONTROL, OTG, inst),\ - SRI(OTG_GSL_CONTROL, OTG, inst),\ - SRI(OTG_CRC_CNTL, OTG, inst),\ - SRI(OTG_CRC_CNTL2, OTG, inst),\ - SRI(OTG_CRC0_DATA_RG, OTG, inst),\ - SRI(OTG_CRC0_DATA_B, OTG, inst),\ - SRI(OTG_CRC0_WINDOWA_X_CONTROL, OTG, inst),\ - SRI(OTG_CRC0_WINDOWA_Y_CONTROL, OTG, inst),\ - SRI(OTG_CRC0_WINDOWB_X_CONTROL, OTG, inst),\ - SRI(OTG_CRC0_WINDOWB_Y_CONTROL, OTG, inst),\ - SR(GSL_SOURCE_SELECT),\ - SRI(OTG_TRIGA_MANUAL_TRIG, OTG, inst),\ - SRI(OTG_DRR_CONTROL, OTG, inst) - - -#define OPTC_COMMON_REG_LIST_DCN3_0(inst) \ - OPTC_COMMON_REG_LIST_DCN3_BASE(inst),\ - SRI(OTG_GLOBAL_CONTROL1, OTG, inst),\ - SRI(OTG_GLOBAL_CONTROL2, OTG, inst),\ - SRI(OTG_GSL_WINDOW_X, OTG, inst),\ - SRI(OTG_GSL_WINDOW_Y, OTG, inst),\ - SRI(OTG_VUPDATE_KEEPOUT, OTG, inst),\ - SRI(OTG_DSC_START_POSITION, OTG, inst),\ - SRI(OTG_CRC_CNTL2, OTG, inst),\ - SRI(OTG_DRR_TRIGGER_WINDOW, OTG, inst),\ - SRI(OTG_DRR_V_TOTAL_CHANGE, OTG, inst),\ - SRI(OPTC_DATA_FORMAT_CONTROL, ODM, inst),\ - SRI(OPTC_BYTES_PER_PIXEL, ODM, inst),\ - SRI(OPTC_WIDTH_CONTROL, ODM, inst),\ - SRI(OPTC_MEMORY_CONFIG, ODM, inst),\ - SR(DWB_SOURCE_SELECT) - -#define DCN30_VTOTAL_REGS_SF(mask_sh) - -#define OPTC_COMMON_MASK_SH_LIST_DCN3_BASE(mask_sh)\ - SF(OTG0_OTG_VSTARTUP_PARAM, VSTARTUP_START, mask_sh),\ - SF(OTG0_OTG_VUPDATE_PARAM, VUPDATE_OFFSET, mask_sh),\ - SF(OTG0_OTG_VUPDATE_PARAM, VUPDATE_WIDTH, mask_sh),\ - SF(OTG0_OTG_VREADY_PARAM, VREADY_OFFSET, mask_sh),\ - SF(OTG0_OTG_MASTER_UPDATE_LOCK, OTG_MASTER_UPDATE_LOCK, mask_sh),\ - SF(OTG0_OTG_MASTER_UPDATE_LOCK, UPDATE_LOCK_STATUS, mask_sh),\ - SF(OTG0_OTG_GLOBAL_CONTROL0, MASTER_UPDATE_LOCK_DB_START_X, mask_sh),\ - SF(OTG0_OTG_GLOBAL_CONTROL0, MASTER_UPDATE_LOCK_DB_END_X, mask_sh),\ - SF(OTG0_OTG_GLOBAL_CONTROL0, MASTER_UPDATE_LOCK_DB_EN, mask_sh),\ - SF(OTG0_OTG_GLOBAL_CONTROL1, MASTER_UPDATE_LOCK_DB_START_Y, mask_sh),\ - SF(OTG0_OTG_GLOBAL_CONTROL1, MASTER_UPDATE_LOCK_DB_END_Y, mask_sh),\ - SF(OTG0_OTG_GLOBAL_CONTROL2, OTG_MASTER_UPDATE_LOCK_SEL, mask_sh),\ - SF(OTG0_OTG_GLOBAL_CONTROL4, DIG_UPDATE_POSITION_X, mask_sh),\ - SF(OTG0_OTG_GLOBAL_CONTROL4, DIG_UPDATE_POSITION_Y, mask_sh),\ - SF(OTG0_OTG_DOUBLE_BUFFER_CONTROL, OTG_UPDATE_PENDING, mask_sh),\ - SF(OTG0_OTG_H_TOTAL, OTG_H_TOTAL, mask_sh),\ - SF(OTG0_OTG_H_BLANK_START_END, OTG_H_BLANK_START, mask_sh),\ - SF(OTG0_OTG_H_BLANK_START_END, OTG_H_BLANK_END, mask_sh),\ - SF(OTG0_OTG_H_SYNC_A, OTG_H_SYNC_A_START, mask_sh),\ - SF(OTG0_OTG_H_SYNC_A, OTG_H_SYNC_A_END, mask_sh),\ - SF(OTG0_OTG_H_SYNC_A_CNTL, OTG_H_SYNC_A_POL, mask_sh),\ - SF(OTG0_OTG_V_TOTAL, OTG_V_TOTAL, mask_sh),\ - SF(OTG0_OTG_V_BLANK_START_END, OTG_V_BLANK_START, mask_sh),\ - SF(OTG0_OTG_V_BLANK_START_END, OTG_V_BLANK_END, mask_sh),\ - SF(OTG0_OTG_V_SYNC_A, OTG_V_SYNC_A_START, mask_sh),\ - SF(OTG0_OTG_V_SYNC_A, OTG_V_SYNC_A_END, mask_sh),\ - SF(OTG0_OTG_V_SYNC_A_CNTL, OTG_V_SYNC_A_POL, mask_sh),\ - SF(OTG0_OTG_V_SYNC_A_CNTL, OTG_V_SYNC_MODE, mask_sh),\ - SF(OTG0_OTG_CONTROL, OTG_MASTER_EN, mask_sh),\ - SF(OTG0_OTG_CONTROL, OTG_START_POINT_CNTL, mask_sh),\ - SF(OTG0_OTG_CONTROL, OTG_DISABLE_POINT_CNTL, mask_sh),\ - SF(OTG0_OTG_CONTROL, OTG_FIELD_NUMBER_CNTL, mask_sh),\ - SF(OTG0_OTG_CONTROL, OTG_OUT_MUX, mask_sh),\ - SF(OTG0_OTG_STEREO_CONTROL, OTG_STEREO_EN, mask_sh),\ - SF(OTG0_OTG_STEREO_CONTROL, OTG_STEREO_SYNC_OUTPUT_LINE_NUM, mask_sh),\ - SF(OTG0_OTG_STEREO_CONTROL, OTG_STEREO_SYNC_OUTPUT_POLARITY, mask_sh),\ - SF(OTG0_OTG_STEREO_CONTROL, OTG_STEREO_EYE_FLAG_POLARITY, mask_sh),\ - SF(OTG0_OTG_STEREO_CONTROL, OTG_DISABLE_STEREOSYNC_OUTPUT_FOR_DP, mask_sh),\ - SF(OTG0_OTG_STEREO_STATUS, OTG_STEREO_CURRENT_EYE, mask_sh),\ - SF(OTG0_OTG_3D_STRUCTURE_CONTROL, OTG_3D_STRUCTURE_EN, mask_sh),\ - SF(OTG0_OTG_3D_STRUCTURE_CONTROL, OTG_3D_STRUCTURE_V_UPDATE_MODE, mask_sh),\ - SF(OTG0_OTG_3D_STRUCTURE_CONTROL, OTG_3D_STRUCTURE_STEREO_SEL_OVR, mask_sh),\ - SF(OTG0_OTG_V_TOTAL_MAX, OTG_V_TOTAL_MAX, mask_sh),\ - SF(OTG0_OTG_V_TOTAL_MIN, OTG_V_TOTAL_MIN, mask_sh),\ - SF(OTG0_OTG_V_TOTAL_CONTROL, OTG_V_TOTAL_MIN_SEL, mask_sh),\ - SF(OTG0_OTG_V_TOTAL_CONTROL, OTG_V_TOTAL_MAX_SEL, mask_sh),\ - SF(OTG0_OTG_V_TOTAL_CONTROL, OTG_FORCE_LOCK_ON_EVENT, mask_sh),\ - SF(OTG0_OTG_V_TOTAL_CONTROL, OTG_SET_V_TOTAL_MIN_MASK_EN, mask_sh),\ - SF(OTG0_OTG_V_TOTAL_CONTROL, OTG_SET_V_TOTAL_MIN_MASK, mask_sh),\ - SF(OTG0_OTG_V_TOTAL_CONTROL, OTG_VTOTAL_MID_REPLACING_MIN_EN, mask_sh),\ - SF(OTG0_OTG_V_TOTAL_CONTROL, OTG_VTOTAL_MID_REPLACING_MAX_EN, mask_sh),\ - DCN30_VTOTAL_REGS_SF(mask_sh)\ - SF(OTG0_OTG_FORCE_COUNT_NOW_CNTL, OTG_FORCE_COUNT_NOW_CLEAR, mask_sh),\ - SF(OTG0_OTG_FORCE_COUNT_NOW_CNTL, OTG_FORCE_COUNT_NOW_MODE, mask_sh),\ - SF(OTG0_OTG_FORCE_COUNT_NOW_CNTL, OTG_FORCE_COUNT_NOW_OCCURRED, mask_sh),\ - SF(OTG0_OTG_TRIGA_CNTL, OTG_TRIGA_SOURCE_SELECT, mask_sh),\ - SF(OTG0_OTG_TRIGA_CNTL, OTG_TRIGA_SOURCE_PIPE_SELECT, mask_sh),\ - SF(OTG0_OTG_TRIGA_CNTL, OTG_TRIGA_RISING_EDGE_DETECT_CNTL, mask_sh),\ - SF(OTG0_OTG_TRIGA_CNTL, OTG_TRIGA_FALLING_EDGE_DETECT_CNTL, mask_sh),\ - SF(OTG0_OTG_TRIGA_CNTL, OTG_TRIGA_POLARITY_SELECT, mask_sh),\ - SF(OTG0_OTG_TRIGA_CNTL, OTG_TRIGA_FREQUENCY_SELECT, mask_sh),\ - SF(OTG0_OTG_TRIGA_CNTL, OTG_TRIGA_DELAY, mask_sh),\ - SF(OTG0_OTG_TRIGA_CNTL, OTG_TRIGA_CLEAR, mask_sh),\ - SF(OTG0_OTG_STATIC_SCREEN_CONTROL, OTG_STATIC_SCREEN_EVENT_MASK, mask_sh),\ - SF(OTG0_OTG_STATIC_SCREEN_CONTROL, OTG_STATIC_SCREEN_FRAME_COUNT, mask_sh),\ - SF(OTG0_OTG_STATUS_FRAME_COUNT, OTG_FRAME_COUNT, mask_sh),\ - SF(OTG0_OTG_STATUS, OTG_V_BLANK, mask_sh),\ - SF(OTG0_OTG_STATUS, OTG_V_ACTIVE_DISP, mask_sh),\ - SF(OTG0_OTG_STATUS_POSITION, OTG_HORZ_COUNT, mask_sh),\ - SF(OTG0_OTG_STATUS_POSITION, OTG_VERT_COUNT, mask_sh),\ - SF(OTG0_OTG_NOM_VERT_POSITION, OTG_VERT_COUNT_NOM, mask_sh),\ - SF(OTG0_OTG_BLANK_DATA_COLOR, OTG_BLANK_DATA_COLOR_BLUE_CB, mask_sh),\ - SF(OTG0_OTG_BLANK_DATA_COLOR, OTG_BLANK_DATA_COLOR_GREEN_Y, mask_sh),\ - SF(OTG0_OTG_BLANK_DATA_COLOR, OTG_BLANK_DATA_COLOR_RED_CR, mask_sh),\ - SF(OTG0_OTG_BLANK_DATA_COLOR_EXT, OTG_BLANK_DATA_COLOR_BLUE_CB_EXT, mask_sh),\ - SF(OTG0_OTG_BLANK_DATA_COLOR_EXT, OTG_BLANK_DATA_COLOR_GREEN_Y_EXT, mask_sh),\ - SF(OTG0_OTG_BLANK_DATA_COLOR_EXT, OTG_BLANK_DATA_COLOR_RED_CR_EXT, mask_sh),\ - SF(OTG0_OTG_M_CONST_DTO0, OTG_M_CONST_DTO_PHASE, mask_sh),\ - SF(OTG0_OTG_M_CONST_DTO1, OTG_M_CONST_DTO_MODULO, mask_sh),\ - SF(OTG0_OTG_CLOCK_CONTROL, OTG_BUSY, mask_sh),\ - SF(OTG0_OTG_CLOCK_CONTROL, OTG_CLOCK_EN, mask_sh),\ - SF(OTG0_OTG_CLOCK_CONTROL, OTG_CLOCK_ON, mask_sh),\ - SF(OTG0_OTG_CLOCK_CONTROL, OTG_CLOCK_GATE_DIS, mask_sh),\ - SF(OTG0_OTG_VERTICAL_INTERRUPT0_CONTROL, OTG_VERTICAL_INTERRUPT0_INT_ENABLE, mask_sh),\ - SF(OTG0_OTG_VERTICAL_INTERRUPT0_POSITION, OTG_VERTICAL_INTERRUPT0_LINE_START, mask_sh),\ - SF(OTG0_OTG_VERTICAL_INTERRUPT0_POSITION, OTG_VERTICAL_INTERRUPT0_LINE_END, mask_sh),\ - SF(OTG0_OTG_VERTICAL_INTERRUPT1_CONTROL, OTG_VERTICAL_INTERRUPT1_INT_ENABLE, mask_sh),\ - SF(OTG0_OTG_VERTICAL_INTERRUPT1_POSITION, OTG_VERTICAL_INTERRUPT1_LINE_START, mask_sh),\ - SF(OTG0_OTG_VERTICAL_INTERRUPT2_CONTROL, OTG_VERTICAL_INTERRUPT2_INT_ENABLE, mask_sh),\ - SF(OTG0_OTG_VERTICAL_INTERRUPT2_POSITION, OTG_VERTICAL_INTERRUPT2_LINE_START, mask_sh),\ - SF(ODM0_OPTC_INPUT_CLOCK_CONTROL, OPTC_INPUT_CLK_EN, mask_sh),\ - SF(ODM0_OPTC_INPUT_CLOCK_CONTROL, OPTC_INPUT_CLK_ON, mask_sh),\ - SF(ODM0_OPTC_INPUT_CLOCK_CONTROL, OPTC_INPUT_CLK_GATE_DIS, mask_sh),\ - SF(ODM0_OPTC_INPUT_GLOBAL_CONTROL, OPTC_UNDERFLOW_OCCURRED_STATUS, mask_sh),\ - SF(ODM0_OPTC_INPUT_GLOBAL_CONTROL, OPTC_UNDERFLOW_CLEAR, mask_sh),\ - SF(VTG0_CONTROL, VTG0_ENABLE, mask_sh),\ - SF(VTG0_CONTROL, VTG0_FP2, mask_sh),\ - SF(VTG0_CONTROL, VTG0_VCOUNT_INIT, mask_sh),\ - SF(OTG0_OTG_VERT_SYNC_CONTROL, OTG_FORCE_VSYNC_NEXT_LINE_OCCURRED, mask_sh),\ - SF(OTG0_OTG_VERT_SYNC_CONTROL, OTG_FORCE_VSYNC_NEXT_LINE_CLEAR, mask_sh),\ - SF(OTG0_OTG_VERT_SYNC_CONTROL, OTG_AUTO_FORCE_VSYNC_MODE, mask_sh),\ - SF(OTG0_OTG_GSL_CONTROL, OTG_GSL0_EN, mask_sh),\ - SF(OTG0_OTG_GSL_CONTROL, OTG_GSL1_EN, mask_sh),\ - SF(OTG0_OTG_GSL_CONTROL, OTG_GSL2_EN, mask_sh),\ - SF(OTG0_OTG_GSL_CONTROL, OTG_GSL_MASTER_EN, mask_sh),\ - SF(OTG0_OTG_GSL_CONTROL, OTG_GSL_FORCE_DELAY, mask_sh),\ - SF(OTG0_OTG_GSL_CONTROL, OTG_GSL_CHECK_ALL_FIELDS, mask_sh),\ - SF(OTG0_OTG_CRC_CNTL, OTG_CRC_CONT_EN, mask_sh),\ - SF(OTG0_OTG_CRC_CNTL, OTG_CRC0_SELECT, mask_sh),\ - SF(OTG0_OTG_CRC_CNTL, OTG_CRC_EN, mask_sh),\ - SF(OTG0_OTG_CRC_CNTL2, OTG_CRC_DSC_MODE, mask_sh),\ - SF(OTG0_OTG_CRC_CNTL2, OTG_CRC_DATA_STREAM_COMBINE_MODE, mask_sh),\ - SF(OTG0_OTG_CRC_CNTL2, OTG_CRC_DATA_STREAM_SPLIT_MODE, mask_sh),\ - SF(OTG0_OTG_CRC_CNTL2, OTG_CRC_DATA_FORMAT, mask_sh),\ - SF(OTG0_OTG_CRC0_DATA_RG, CRC0_R_CR, mask_sh),\ - SF(OTG0_OTG_CRC0_DATA_RG, CRC0_G_Y, mask_sh),\ - SF(OTG0_OTG_CRC0_DATA_B, CRC0_B_CB, mask_sh),\ - SF(OTG0_OTG_CRC0_WINDOWA_X_CONTROL, OTG_CRC0_WINDOWA_X_START, mask_sh),\ - SF(OTG0_OTG_CRC0_WINDOWA_X_CONTROL, OTG_CRC0_WINDOWA_X_END, mask_sh),\ - SF(OTG0_OTG_CRC0_WINDOWA_Y_CONTROL, OTG_CRC0_WINDOWA_Y_START, mask_sh),\ - SF(OTG0_OTG_CRC0_WINDOWA_Y_CONTROL, OTG_CRC0_WINDOWA_Y_END, mask_sh),\ - SF(OTG0_OTG_CRC0_WINDOWB_X_CONTROL, OTG_CRC0_WINDOWB_X_START, mask_sh),\ - SF(OTG0_OTG_CRC0_WINDOWB_X_CONTROL, OTG_CRC0_WINDOWB_X_END, mask_sh),\ - SF(OTG0_OTG_CRC0_WINDOWB_Y_CONTROL, OTG_CRC0_WINDOWB_Y_START, mask_sh),\ - SF(OTG0_OTG_CRC0_WINDOWB_Y_CONTROL, OTG_CRC0_WINDOWB_Y_END, mask_sh),\ - SF(OTG0_OTG_TRIGA_MANUAL_TRIG, OTG_TRIGA_MANUAL_TRIG, mask_sh),\ - SF(GSL_SOURCE_SELECT, GSL0_READY_SOURCE_SEL, mask_sh),\ - SF(GSL_SOURCE_SELECT, GSL1_READY_SOURCE_SEL, mask_sh),\ - SF(GSL_SOURCE_SELECT, GSL2_READY_SOURCE_SEL, mask_sh),\ - SF(OTG0_OTG_GLOBAL_CONTROL2, MANUAL_FLOW_CONTROL_SEL, mask_sh),\ - SF(OTG0_OTG_DRR_CONTROL, OTG_V_TOTAL_LAST_USED_BY_DRR, mask_sh) - -#define OPTC_COMMON_MASK_SH_LIST_DCN3_0(mask_sh)\ - OPTC_COMMON_MASK_SH_LIST_DCN3_BASE(mask_sh),\ - SF(OTG0_OTG_GLOBAL_CONTROL2, GLOBAL_UPDATE_LOCK_EN, mask_sh),\ - SF(OTG0_OTG_GSL_WINDOW_X, OTG_GSL_WINDOW_START_X, mask_sh),\ - SF(OTG0_OTG_GSL_WINDOW_X, OTG_GSL_WINDOW_END_X, mask_sh), \ - SF(OTG0_OTG_GSL_WINDOW_Y, OTG_GSL_WINDOW_START_Y, mask_sh),\ - SF(OTG0_OTG_GSL_WINDOW_Y, OTG_GSL_WINDOW_END_Y, mask_sh),\ - SF(OTG0_OTG_VUPDATE_KEEPOUT, OTG_MASTER_UPDATE_LOCK_VUPDATE_KEEPOUT_EN, mask_sh), \ - SF(OTG0_OTG_VUPDATE_KEEPOUT, MASTER_UPDATE_LOCK_VUPDATE_KEEPOUT_START_OFFSET, mask_sh), \ - SF(OTG0_OTG_VUPDATE_KEEPOUT, MASTER_UPDATE_LOCK_VUPDATE_KEEPOUT_END_OFFSET, mask_sh), \ - SF(OTG0_OTG_GSL_CONTROL, OTG_GSL_MASTER_MODE, mask_sh), \ - SF(OTG0_OTG_GSL_CONTROL, OTG_MASTER_UPDATE_LOCK_GSL_EN, mask_sh), \ - SF(OTG0_OTG_DSC_START_POSITION, OTG_DSC_START_POSITION_X, mask_sh), \ - SF(OTG0_OTG_DSC_START_POSITION, OTG_DSC_START_POSITION_LINE_NUM, mask_sh),\ - SF(OTG0_OTG_CRC_CNTL2, OTG_CRC_DSC_MODE, mask_sh),\ - SF(OTG0_OTG_CRC_CNTL2, OTG_CRC_DATA_STREAM_COMBINE_MODE, mask_sh),\ - SF(OTG0_OTG_CRC_CNTL2, OTG_CRC_DATA_STREAM_SPLIT_MODE, mask_sh),\ - SF(OTG0_OTG_CRC_CNTL2, OTG_CRC_DATA_FORMAT, mask_sh),\ - SF(ODM0_OPTC_DATA_SOURCE_SELECT, OPTC_SEG0_SRC_SEL, mask_sh),\ - SF(ODM0_OPTC_DATA_SOURCE_SELECT, OPTC_SEG1_SRC_SEL, mask_sh),\ - SF(ODM0_OPTC_DATA_SOURCE_SELECT, OPTC_NUM_OF_INPUT_SEGMENT, mask_sh),\ - SF(ODM0_OPTC_MEMORY_CONFIG, OPTC_MEM_SEL, mask_sh),\ - SF(ODM0_OPTC_DATA_FORMAT_CONTROL, OPTC_DATA_FORMAT, mask_sh),\ - SF(ODM0_OPTC_DATA_FORMAT_CONTROL, OPTC_DSC_MODE, mask_sh),\ - SF(ODM0_OPTC_BYTES_PER_PIXEL, OPTC_DSC_BYTES_PER_PIXEL, mask_sh),\ - SF(ODM0_OPTC_WIDTH_CONTROL, OPTC_DSC_SLICE_WIDTH, mask_sh),\ - SF(ODM0_OPTC_WIDTH_CONTROL, OPTC_SEGMENT_WIDTH, mask_sh),\ - SF(DWB_SOURCE_SELECT, OPTC_DWB0_SOURCE_SELECT, mask_sh),\ - SF(DWB_SOURCE_SELECT, OPTC_DWB1_SOURCE_SELECT, mask_sh),\ - SF(OTG0_OTG_DRR_TRIGGER_WINDOW, OTG_DRR_TRIGGER_WINDOW_START_X, mask_sh),\ - SF(OTG0_OTG_DRR_TRIGGER_WINDOW, OTG_DRR_TRIGGER_WINDOW_END_X, mask_sh),\ - SF(OTG0_OTG_DRR_V_TOTAL_CHANGE, OTG_DRR_V_TOTAL_CHANGE_LIMIT, mask_sh),\ - SF(OTG0_OTG_H_TIMING_CNTL, OTG_H_TIMING_DIV_BY2, mask_sh),\ - SF(OTG0_OTG_DOUBLE_BUFFER_CONTROL, OTG_DRR_TIMING_DBUF_UPDATE_PENDING, mask_sh),\ - SF(OTG0_OTG_DOUBLE_BUFFER_CONTROL, OTG_DRR_TIMING_DBUF_UPDATE_MODE, mask_sh),\ - SF(OTG0_OTG_DOUBLE_BUFFER_CONTROL, OTG_BLANK_DATA_DOUBLE_BUFFER_EN, mask_sh) - -#define OPTC_COMMON_MASK_SH_LIST_DCN30(mask_sh)\ - OPTC_COMMON_MASK_SH_LIST_DCN3_BASE(mask_sh),\ - SF(OTG0_OTG_GLOBAL_CONTROL2, GLOBAL_UPDATE_LOCK_EN, mask_sh),\ - SF(OTG0_OTG_GSL_WINDOW_X, OTG_GSL_WINDOW_START_X, mask_sh),\ - SF(OTG0_OTG_GSL_WINDOW_X, OTG_GSL_WINDOW_END_X, mask_sh), \ - SF(OTG0_OTG_GSL_WINDOW_Y, OTG_GSL_WINDOW_START_Y, mask_sh),\ - SF(OTG0_OTG_GSL_WINDOW_Y, OTG_GSL_WINDOW_END_Y, mask_sh),\ - SF(OTG0_OTG_VUPDATE_KEEPOUT, OTG_MASTER_UPDATE_LOCK_VUPDATE_KEEPOUT_EN, mask_sh), \ - SF(OTG0_OTG_VUPDATE_KEEPOUT, MASTER_UPDATE_LOCK_VUPDATE_KEEPOUT_START_OFFSET, mask_sh), \ - SF(OTG0_OTG_VUPDATE_KEEPOUT, MASTER_UPDATE_LOCK_VUPDATE_KEEPOUT_END_OFFSET, mask_sh), \ - SF(OTG0_OTG_GSL_CONTROL, OTG_GSL_MASTER_MODE, mask_sh), \ - SF(OTG0_OTG_GSL_CONTROL, OTG_MASTER_UPDATE_LOCK_GSL_EN, mask_sh), \ - SF(OTG0_OTG_DSC_START_POSITION, OTG_DSC_START_POSITION_X, mask_sh), \ - SF(OTG0_OTG_DSC_START_POSITION, OTG_DSC_START_POSITION_LINE_NUM, mask_sh),\ - SF(OTG0_OTG_CRC_CNTL2, OTG_CRC_DSC_MODE, mask_sh),\ - SF(OTG0_OTG_CRC_CNTL2, OTG_CRC_DATA_STREAM_COMBINE_MODE, mask_sh),\ - SF(OTG0_OTG_CRC_CNTL2, OTG_CRC_DATA_STREAM_SPLIT_MODE, mask_sh),\ - SF(OTG0_OTG_CRC_CNTL2, OTG_CRC_DATA_FORMAT, mask_sh),\ - SF(ODM0_OPTC_DATA_SOURCE_SELECT, OPTC_SEG0_SRC_SEL, mask_sh),\ - SF(ODM0_OPTC_DATA_SOURCE_SELECT, OPTC_SEG1_SRC_SEL, mask_sh),\ - SF(ODM0_OPTC_DATA_SOURCE_SELECT, OPTC_SEG2_SRC_SEL, mask_sh),\ - SF(ODM0_OPTC_DATA_SOURCE_SELECT, OPTC_SEG3_SRC_SEL, mask_sh),\ - SF(ODM0_OPTC_DATA_SOURCE_SELECT, OPTC_NUM_OF_INPUT_SEGMENT, mask_sh),\ - SF(ODM0_OPTC_MEMORY_CONFIG, OPTC_MEM_SEL, mask_sh),\ - SF(ODM0_OPTC_DATA_FORMAT_CONTROL, OPTC_DATA_FORMAT, mask_sh),\ - SF(ODM0_OPTC_DATA_FORMAT_CONTROL, OPTC_DSC_MODE, mask_sh),\ - SF(ODM0_OPTC_BYTES_PER_PIXEL, OPTC_DSC_BYTES_PER_PIXEL, mask_sh),\ - SF(ODM0_OPTC_WIDTH_CONTROL, OPTC_DSC_SLICE_WIDTH, mask_sh),\ - SF(ODM0_OPTC_WIDTH_CONTROL, OPTC_SEGMENT_WIDTH, mask_sh),\ - SF(DWB_SOURCE_SELECT, OPTC_DWB0_SOURCE_SELECT, mask_sh),\ - SF(DWB_SOURCE_SELECT, OPTC_DWB1_SOURCE_SELECT, mask_sh),\ - SF(OTG0_OTG_DRR_TRIGGER_WINDOW, OTG_DRR_TRIGGER_WINDOW_START_X, mask_sh),\ - SF(OTG0_OTG_DRR_TRIGGER_WINDOW, OTG_DRR_TRIGGER_WINDOW_END_X, mask_sh),\ - SF(OTG0_OTG_DRR_V_TOTAL_CHANGE, OTG_DRR_V_TOTAL_CHANGE_LIMIT, mask_sh),\ - SF(OTG0_OTG_H_TIMING_CNTL, OTG_H_TIMING_DIV_MODE, mask_sh),\ - SF(OTG0_OTG_DOUBLE_BUFFER_CONTROL, OTG_DRR_TIMING_DBUF_UPDATE_PENDING, mask_sh),\ - SF(OTG0_OTG_DOUBLE_BUFFER_CONTROL, OTG_DRR_TIMING_DBUF_UPDATE_MODE, mask_sh) - -void dcn30_timing_generator_init(struct optc *optc1); - -void optc3_set_out_mux(struct timing_generator *optc, enum otg_out_mux_dest dest); - -void optc3_lock(struct timing_generator *optc); - -void optc3_lock_doublebuffer_enable(struct timing_generator *optc); - -void optc3_lock_doublebuffer_disable(struct timing_generator *optc); - -void optc3_set_drr_trigger_window(struct timing_generator *optc, - uint32_t window_start, uint32_t window_end); - -void optc3_triplebuffer_lock(struct timing_generator *optc); - -void optc3_program_blank_color(struct timing_generator *optc, - const struct tg_color *blank_color); - -void optc3_set_vtotal_change_limit(struct timing_generator *optc, - uint32_t limit); - -void optc3_set_dsc_config(struct timing_generator *optc, - enum optc_dsc_mode dsc_mode, - uint32_t dsc_bytes_per_pixel, - uint32_t dsc_slice_width); - -void optc3_set_timing_db_mode(struct timing_generator *optc, bool enable); - -void optc3_set_odm_bypass(struct timing_generator *optc, - const struct dc_crtc_timing *dc_crtc_timing); -void optc3_set_odm_combine(struct timing_generator *optc, int *opp_id, int opp_cnt, - struct dc_crtc_timing *timing); -void optc3_wait_drr_doublebuffer_pending_clear(struct timing_generator *optc); -void optc3_tg_init(struct timing_generator *optc); -void optc3_set_vtotal_min_max(struct timing_generator *optc, int vtotal_min, int vtotal_max); -#endif /* __DC_OPTC_DCN30_H__ */ diff --git a/drivers/gpu/drm/amd/display/dc/dcn301/Makefile b/drivers/gpu/drm/amd/display/dc/dcn301/Makefile index cbf59d7e78c4..090011300dcd 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn301/Makefile +++ b/drivers/gpu/drm/amd/display/dc/dcn301/Makefile @@ -11,8 +11,7 @@ # Makefile for dcn30. DCN301 = dcn301_init.o dcn301_dccg.o \ - dcn301_dio_link_encoder.o dcn301_panel_cntl.o dcn301_hubbub.o \ - dcn301_optc.o + dcn301_dio_link_encoder.o dcn301_panel_cntl.o dcn301_hubbub.o AMD_DAL_DCN301 = $(addprefix $(AMDDALPATH)/dc/dcn301/,$(DCN301)) diff --git a/drivers/gpu/drm/amd/display/dc/dcn301/dcn301_optc.c b/drivers/gpu/drm/amd/display/dc/dcn301/dcn301_optc.c deleted file mode 100644 index b3cfcb887905..000000000000 --- a/drivers/gpu/drm/amd/display/dc/dcn301/dcn301_optc.c +++ /dev/null @@ -1,185 +0,0 @@ -/* - * Copyright 2020 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 "reg_helper.h" -#include "dcn301_optc.h" -#include "dc.h" -#include "dcn_calc_math.h" -#include "dc_dmub_srv.h" - -#include "dml/dcn30/dcn30_fpu.h" -#include "dc_trace.h" - -#define REG(reg)\ - optc1->tg_regs->reg - -#define CTX \ - optc1->base.ctx - -#undef FN -#define FN(reg_name, field_name) \ - optc1->tg_shift->field_name, optc1->tg_mask->field_name - - -/** - * optc301_set_drr() - Program dynamic refresh rate registers m_OTGx_OTG_V_TOTAL_*. - * - * @optc: timing_generator instance. - * @params: parameters used for Dynamic Refresh Rate. - */ -void optc301_set_drr( - struct timing_generator *optc, - const struct drr_params *params) -{ - struct optc *optc1 = DCN10TG_FROM_TG(optc); - - if (params != NULL && - params->vertical_total_max > 0 && - params->vertical_total_min > 0) { - - if (params->vertical_total_mid != 0) { - - REG_SET(OTG_V_TOTAL_MID, 0, - OTG_V_TOTAL_MID, params->vertical_total_mid - 1); - - REG_UPDATE_2(OTG_V_TOTAL_CONTROL, - OTG_VTOTAL_MID_REPLACING_MAX_EN, 1, - OTG_VTOTAL_MID_FRAME_NUM, - (uint8_t)params->vertical_total_mid_frame_num); - - } - - optc->funcs->set_vtotal_min_max(optc, params->vertical_total_min - 1, params->vertical_total_max - 1); - - REG_UPDATE_5(OTG_V_TOTAL_CONTROL, - OTG_V_TOTAL_MIN_SEL, 1, - OTG_V_TOTAL_MAX_SEL, 1, - OTG_FORCE_LOCK_ON_EVENT, 0, - OTG_SET_V_TOTAL_MIN_MASK_EN, 0, - OTG_SET_V_TOTAL_MIN_MASK, 0); - // Setup manual flow control for EOF via TRIG_A - optc->funcs->setup_manual_trigger(optc); - - } else { - REG_UPDATE_4(OTG_V_TOTAL_CONTROL, - OTG_SET_V_TOTAL_MIN_MASK, 0, - OTG_V_TOTAL_MIN_SEL, 0, - OTG_V_TOTAL_MAX_SEL, 0, - OTG_FORCE_LOCK_ON_EVENT, 0); - - optc->funcs->set_vtotal_min_max(optc, 0, 0); - } -} - - -void optc301_setup_manual_trigger(struct timing_generator *optc) -{ - struct optc *optc1 = DCN10TG_FROM_TG(optc); - - REG_SET_8(OTG_TRIGA_CNTL, 0, - OTG_TRIGA_SOURCE_SELECT, 21, - OTG_TRIGA_SOURCE_PIPE_SELECT, optc->inst, - OTG_TRIGA_RISING_EDGE_DETECT_CNTL, 1, - OTG_TRIGA_FALLING_EDGE_DETECT_CNTL, 0, - OTG_TRIGA_POLARITY_SELECT, 0, - OTG_TRIGA_FREQUENCY_SELECT, 0, - OTG_TRIGA_DELAY, 0, - OTG_TRIGA_CLEAR, 1); -} - -static struct timing_generator_funcs dcn30_tg_funcs = { - .validate_timing = optc1_validate_timing, - .program_timing = optc1_program_timing, - .setup_vertical_interrupt0 = optc1_setup_vertical_interrupt0, - .setup_vertical_interrupt1 = optc1_setup_vertical_interrupt1, - .setup_vertical_interrupt2 = optc1_setup_vertical_interrupt2, - .program_global_sync = optc1_program_global_sync, - .enable_crtc = optc2_enable_crtc, - .disable_crtc = optc1_disable_crtc, - /* used by enable_timing_synchronization. Not need for FPGA */ - .is_counter_moving = optc1_is_counter_moving, - .get_position = optc1_get_position, - .get_frame_count = optc1_get_vblank_counter, - .get_scanoutpos = optc1_get_crtc_scanoutpos, - .get_otg_active_size = optc1_get_otg_active_size, - .set_early_control = optc1_set_early_control, - /* used by enable_timing_synchronization. Not need for FPGA */ - .wait_for_state = optc1_wait_for_state, - .set_blank_color = optc3_program_blank_color, - .did_triggered_reset_occur = optc1_did_triggered_reset_occur, - .triplebuffer_lock = optc3_triplebuffer_lock, - .triplebuffer_unlock = optc2_triplebuffer_unlock, - .enable_reset_trigger = optc1_enable_reset_trigger, - .enable_crtc_reset = optc1_enable_crtc_reset, - .disable_reset_trigger = optc1_disable_reset_trigger, - .lock = optc3_lock, - .unlock = optc1_unlock, - .lock_doublebuffer_enable = optc3_lock_doublebuffer_enable, - .lock_doublebuffer_disable = optc3_lock_doublebuffer_disable, - .enable_optc_clock = optc1_enable_optc_clock, - .set_drr = optc301_set_drr, - .get_last_used_drr_vtotal = optc2_get_last_used_drr_vtotal, - .set_vtotal_min_max = optc3_set_vtotal_min_max, - .set_static_screen_control = optc1_set_static_screen_control, - .program_stereo = optc1_program_stereo, - .is_stereo_left_eye = optc1_is_stereo_left_eye, - .tg_init = optc3_tg_init, - .is_tg_enabled = optc1_is_tg_enabled, - .is_optc_underflow_occurred = optc1_is_optc_underflow_occurred, - .clear_optc_underflow = optc1_clear_optc_underflow, - .setup_global_swap_lock = NULL, - .get_crc = optc1_get_crc, - .configure_crc = optc2_configure_crc, - .set_dsc_config = optc3_set_dsc_config, - .get_dsc_status = optc2_get_dsc_status, - .set_dwb_source = NULL, - .set_odm_bypass = optc3_set_odm_bypass, - .set_odm_combine = optc3_set_odm_combine, - .get_optc_source = optc2_get_optc_source, - .set_out_mux = optc3_set_out_mux, - .set_drr_trigger_window = optc3_set_drr_trigger_window, - .set_vtotal_change_limit = optc3_set_vtotal_change_limit, - .set_gsl = optc2_set_gsl, - .set_gsl_source_select = optc2_set_gsl_source_select, - .set_vtg_params = optc1_set_vtg_params, - .program_manual_trigger = optc2_program_manual_trigger, - .setup_manual_trigger = optc301_setup_manual_trigger, - .get_hw_timing = optc1_get_hw_timing, - .wait_drr_doublebuffer_pending_clear = optc3_wait_drr_doublebuffer_pending_clear, -}; - -void dcn301_timing_generator_init(struct optc *optc1) -{ - optc1->base.funcs = &dcn30_tg_funcs; - - optc1->max_h_total = optc1->tg_mask->OTG_H_TOTAL + 1; - optc1->max_v_total = optc1->tg_mask->OTG_V_TOTAL + 1; - - optc1->min_h_blank = 32; - optc1->min_v_blank = 3; - optc1->min_v_blank_interlace = 5; - optc1->min_h_sync_width = 4; - optc1->min_v_sync_width = 1; -} diff --git a/drivers/gpu/drm/amd/display/dc/dcn301/dcn301_optc.h b/drivers/gpu/drm/amd/display/dc/dcn301/dcn301_optc.h deleted file mode 100644 index b49585682a15..000000000000 --- a/drivers/gpu/drm/amd/display/dc/dcn301/dcn301_optc.h +++ /dev/null @@ -1,36 +0,0 @@ -/* - * Copyright 2020 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_OPTC_DCN301_H__ -#define __DC_OPTC_DCN301_H__ - -#include "dcn20/dcn20_optc.h" -#include "dcn30/dcn30_optc.h" - -void dcn301_timing_generator_init(struct optc *optc1); -void optc301_setup_manual_trigger(struct timing_generator *optc); -void optc301_set_drr(struct timing_generator *optc, const struct drr_params *params); - -#endif /* __DC_OPTC_DCN301_H__ */ diff --git a/drivers/gpu/drm/amd/display/dc/dcn31/Makefile b/drivers/gpu/drm/amd/display/dc/dcn31/Makefile index 212287008c0a..11a2662e58ef 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn31/Makefile +++ b/drivers/gpu/drm/amd/display/dc/dcn31/Makefile @@ -11,7 +11,7 @@ # Makefile for dcn31. DCN31 = dcn31_hubbub.o dcn31_init.o dcn31_hubp.o \ - dcn31_dccg.o dcn31_optc.o dcn31_dio_link_encoder.o dcn31_panel_cntl.o \ + dcn31_dccg.o dcn31_dio_link_encoder.o dcn31_panel_cntl.o \ dcn31_apg.o dcn31_hpo_dp_stream_encoder.o dcn31_hpo_dp_link_encoder.o \ dcn31_afmt.o dcn31_vpg.o diff --git a/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_optc.c b/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_optc.c deleted file mode 100644 index 63a677c8ee27..000000000000 --- a/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_optc.c +++ /dev/null @@ -1,310 +0,0 @@ -/* - * Copyright 2012-15 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 "dcn31_optc.h" - -#include "dcn30/dcn30_optc.h" -#include "reg_helper.h" -#include "dc.h" -#include "dcn_calc_math.h" - -#define REG(reg)\ - optc1->tg_regs->reg - -#define CTX \ - optc1->base.ctx - -#undef FN -#define FN(reg_name, field_name) \ - optc1->tg_shift->field_name, optc1->tg_mask->field_name - -static void optc31_set_odm_combine(struct timing_generator *optc, int *opp_id, int opp_cnt, - struct dc_crtc_timing *timing) -{ - struct optc *optc1 = DCN10TG_FROM_TG(optc); - int mpcc_hactive = (timing->h_addressable + timing->h_border_left + timing->h_border_right) - / opp_cnt; - uint32_t memory_mask = 0; - int mem_count_per_opp = (mpcc_hactive + 2559) / 2560; - - /* Assume less than 6 pipes */ - if (opp_cnt == 4) { - if (mem_count_per_opp == 1) - memory_mask = 0xf; - else { - ASSERT(mem_count_per_opp == 2); - memory_mask = 0xff; - } - } else if (mem_count_per_opp == 1) - memory_mask = 0x1 << (opp_id[0] * 2) | 0x1 << (opp_id[1] * 2); - else if (mem_count_per_opp == 2) - memory_mask = 0x3 << (opp_id[0] * 2) | 0x3 << (opp_id[1] * 2); - else if (mem_count_per_opp == 3) - memory_mask = 0x77; - else if (mem_count_per_opp == 4) - memory_mask = 0xff; - - if (REG(OPTC_MEMORY_CONFIG)) - REG_SET(OPTC_MEMORY_CONFIG, 0, - OPTC_MEM_SEL, memory_mask); - - if (opp_cnt == 2) { - REG_SET_3(OPTC_DATA_SOURCE_SELECT, 0, - OPTC_NUM_OF_INPUT_SEGMENT, 1, - OPTC_SEG0_SRC_SEL, opp_id[0], - OPTC_SEG1_SRC_SEL, opp_id[1]); - } else if (opp_cnt == 4) { - REG_SET_5(OPTC_DATA_SOURCE_SELECT, 0, - OPTC_NUM_OF_INPUT_SEGMENT, 3, - OPTC_SEG0_SRC_SEL, opp_id[0], - OPTC_SEG1_SRC_SEL, opp_id[1], - OPTC_SEG2_SRC_SEL, opp_id[2], - OPTC_SEG3_SRC_SEL, opp_id[3]); - } - - REG_UPDATE(OPTC_WIDTH_CONTROL, - OPTC_SEGMENT_WIDTH, mpcc_hactive); - - REG_SET(OTG_H_TIMING_CNTL, 0, OTG_H_TIMING_DIV_MODE, opp_cnt - 1); - optc1->opp_count = opp_cnt; -} - -/* - * Enable CRTC - call ASIC Control Object to enable Timing generator. - */ -static bool optc31_enable_crtc(struct timing_generator *optc) -{ - struct optc *optc1 = DCN10TG_FROM_TG(optc); - - /* opp instance for OTG, 1 to 1 mapping and odm will adjust */ - REG_UPDATE(OPTC_DATA_SOURCE_SELECT, - OPTC_SEG0_SRC_SEL, optc->inst); - - /* VTG enable first is for HW workaround */ - REG_UPDATE(CONTROL, - VTG0_ENABLE, 1); - - REG_SEQ_START(); - - /* Enable CRTC */ - REG_UPDATE_2(OTG_CONTROL, - OTG_DISABLE_POINT_CNTL, 2, - OTG_MASTER_EN, 1); - - REG_SEQ_SUBMIT(); - REG_SEQ_WAIT_DONE(); - - return true; -} - -/* disable_crtc - call ASIC Control Object to disable Timing generator. */ -static bool optc31_disable_crtc(struct timing_generator *optc) -{ - struct optc *optc1 = DCN10TG_FROM_TG(optc); - /* disable otg request until end of the first line - * in the vertical blank region - */ - REG_UPDATE(OTG_CONTROL, - OTG_MASTER_EN, 0); - - REG_UPDATE(CONTROL, - VTG0_ENABLE, 0); - - /* CRTC disabled, so disable clock. */ - REG_WAIT(OTG_CLOCK_CONTROL, - OTG_BUSY, 0, - 1, 100000); - optc1_clear_optc_underflow(optc); - - return true; -} - -bool optc31_immediate_disable_crtc(struct timing_generator *optc) -{ - struct optc *optc1 = DCN10TG_FROM_TG(optc); - - REG_UPDATE_2(OTG_CONTROL, - OTG_DISABLE_POINT_CNTL, 0, - OTG_MASTER_EN, 0); - - REG_UPDATE(CONTROL, - VTG0_ENABLE, 0); - - /* CRTC disabled, so disable clock. */ - REG_WAIT(OTG_CLOCK_CONTROL, - OTG_BUSY, 0, - 1, 100000); - - /* clear the false state */ - optc1_clear_optc_underflow(optc); - - return true; -} - -void optc31_set_drr( - struct timing_generator *optc, - const struct drr_params *params) -{ - struct optc *optc1 = DCN10TG_FROM_TG(optc); - - if (params != NULL && - params->vertical_total_max > 0 && - params->vertical_total_min > 0) { - - if (params->vertical_total_mid != 0) { - - REG_SET(OTG_V_TOTAL_MID, 0, - OTG_V_TOTAL_MID, params->vertical_total_mid - 1); - - REG_UPDATE_2(OTG_V_TOTAL_CONTROL, - OTG_VTOTAL_MID_REPLACING_MAX_EN, 1, - OTG_VTOTAL_MID_FRAME_NUM, - (uint8_t)params->vertical_total_mid_frame_num); - - } - - optc->funcs->set_vtotal_min_max(optc, params->vertical_total_min - 1, params->vertical_total_max - 1); - - /* - * MIN_MASK_EN is gone and MASK is now always enabled. - * - * To get it to it work with manual trigger we need to make sure - * we program the correct bit. - */ - REG_UPDATE_4(OTG_V_TOTAL_CONTROL, - OTG_V_TOTAL_MIN_SEL, 1, - OTG_V_TOTAL_MAX_SEL, 1, - OTG_FORCE_LOCK_ON_EVENT, 0, - OTG_SET_V_TOTAL_MIN_MASK, (1 << 1)); /* TRIGA */ - - // Setup manual flow control for EOF via TRIG_A - optc->funcs->setup_manual_trigger(optc); - } else { - REG_UPDATE_4(OTG_V_TOTAL_CONTROL, - OTG_SET_V_TOTAL_MIN_MASK, 0, - OTG_V_TOTAL_MIN_SEL, 0, - OTG_V_TOTAL_MAX_SEL, 0, - OTG_FORCE_LOCK_ON_EVENT, 0); - - optc->funcs->set_vtotal_min_max(optc, 0, 0); - } -} - -void optc3_init_odm(struct timing_generator *optc) -{ - struct optc *optc1 = DCN10TG_FROM_TG(optc); - - REG_SET_5(OPTC_DATA_SOURCE_SELECT, 0, - OPTC_NUM_OF_INPUT_SEGMENT, 0, - OPTC_SEG0_SRC_SEL, optc->inst, - OPTC_SEG1_SRC_SEL, 0xf, - OPTC_SEG2_SRC_SEL, 0xf, - OPTC_SEG3_SRC_SEL, 0xf - ); - - REG_SET(OTG_H_TIMING_CNTL, 0, - OTG_H_TIMING_DIV_MODE, 0); - - REG_SET(OPTC_MEMORY_CONFIG, 0, - OPTC_MEM_SEL, 0); - optc1->opp_count = 1; -} - -static struct timing_generator_funcs dcn31_tg_funcs = { - .validate_timing = optc1_validate_timing, - .program_timing = optc1_program_timing, - .setup_vertical_interrupt0 = optc1_setup_vertical_interrupt0, - .setup_vertical_interrupt1 = optc1_setup_vertical_interrupt1, - .setup_vertical_interrupt2 = optc1_setup_vertical_interrupt2, - .program_global_sync = optc1_program_global_sync, - .enable_crtc = optc31_enable_crtc, - .disable_crtc = optc31_disable_crtc, - .immediate_disable_crtc = optc31_immediate_disable_crtc, - /* used by enable_timing_synchronization. Not need for FPGA */ - .is_counter_moving = optc1_is_counter_moving, - .get_position = optc1_get_position, - .get_frame_count = optc1_get_vblank_counter, - .get_scanoutpos = optc1_get_crtc_scanoutpos, - .get_otg_active_size = optc1_get_otg_active_size, - .set_early_control = optc1_set_early_control, - /* used by enable_timing_synchronization. Not need for FPGA */ - .wait_for_state = optc1_wait_for_state, - .set_blank_color = optc3_program_blank_color, - .did_triggered_reset_occur = optc1_did_triggered_reset_occur, - .triplebuffer_lock = optc3_triplebuffer_lock, - .triplebuffer_unlock = optc2_triplebuffer_unlock, - .enable_reset_trigger = optc1_enable_reset_trigger, - .enable_crtc_reset = optc1_enable_crtc_reset, - .disable_reset_trigger = optc1_disable_reset_trigger, - .lock = optc3_lock, - .unlock = optc1_unlock, - .lock_doublebuffer_enable = optc3_lock_doublebuffer_enable, - .lock_doublebuffer_disable = optc3_lock_doublebuffer_disable, - .enable_optc_clock = optc1_enable_optc_clock, - .set_drr = optc31_set_drr, - .get_last_used_drr_vtotal = optc2_get_last_used_drr_vtotal, - .set_vtotal_min_max = optc1_set_vtotal_min_max, - .set_static_screen_control = optc1_set_static_screen_control, - .program_stereo = optc1_program_stereo, - .is_stereo_left_eye = optc1_is_stereo_left_eye, - .tg_init = optc3_tg_init, - .is_tg_enabled = optc1_is_tg_enabled, - .is_optc_underflow_occurred = optc1_is_optc_underflow_occurred, - .clear_optc_underflow = optc1_clear_optc_underflow, - .setup_global_swap_lock = NULL, - .get_crc = optc1_get_crc, - .configure_crc = optc2_configure_crc, - .set_dsc_config = optc3_set_dsc_config, - .get_dsc_status = optc2_get_dsc_status, - .set_dwb_source = NULL, - .set_odm_bypass = optc3_set_odm_bypass, - .set_odm_combine = optc31_set_odm_combine, - .get_optc_source = optc2_get_optc_source, - .set_out_mux = optc3_set_out_mux, - .set_drr_trigger_window = optc3_set_drr_trigger_window, - .set_vtotal_change_limit = optc3_set_vtotal_change_limit, - .set_gsl = optc2_set_gsl, - .set_gsl_source_select = optc2_set_gsl_source_select, - .set_vtg_params = optc1_set_vtg_params, - .program_manual_trigger = optc2_program_manual_trigger, - .setup_manual_trigger = optc2_setup_manual_trigger, - .get_hw_timing = optc1_get_hw_timing, - .init_odm = optc3_init_odm, -}; - -void dcn31_timing_generator_init(struct optc *optc1) -{ - optc1->base.funcs = &dcn31_tg_funcs; - - optc1->max_h_total = optc1->tg_mask->OTG_H_TOTAL + 1; - optc1->max_v_total = optc1->tg_mask->OTG_V_TOTAL + 1; - - optc1->min_h_blank = 32; - optc1->min_v_blank = 3; - optc1->min_v_blank_interlace = 5; - optc1->min_h_sync_width = 4; - optc1->min_v_sync_width = 1; -} - diff --git a/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_optc.h b/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_optc.h deleted file mode 100644 index 30b81a448ce2..000000000000 --- a/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_optc.h +++ /dev/null @@ -1,267 +0,0 @@ -/* - * Copyright 2012-15 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_OPTC_DCN31_H__ -#define __DC_OPTC_DCN31_H__ - -#include "dcn10/dcn10_optc.h" - -#define OPTC_COMMON_REG_LIST_DCN3_1(inst) \ - SRI(OTG_VSTARTUP_PARAM, OTG, inst),\ - SRI(OTG_VUPDATE_PARAM, OTG, inst),\ - SRI(OTG_VREADY_PARAM, OTG, inst),\ - SRI(OTG_MASTER_UPDATE_LOCK, OTG, inst),\ - SRI(OTG_GLOBAL_CONTROL0, OTG, inst),\ - SRI(OTG_GLOBAL_CONTROL1, OTG, inst),\ - SRI(OTG_GLOBAL_CONTROL2, OTG, inst),\ - SRI(OTG_GLOBAL_CONTROL4, OTG, inst),\ - SRI(OTG_DOUBLE_BUFFER_CONTROL, OTG, inst),\ - SRI(OTG_H_TOTAL, OTG, inst),\ - SRI(OTG_H_BLANK_START_END, OTG, inst),\ - SRI(OTG_H_SYNC_A, OTG, inst),\ - SRI(OTG_H_SYNC_A_CNTL, OTG, inst),\ - SRI(OTG_H_TIMING_CNTL, OTG, inst),\ - SRI(OTG_V_TOTAL, OTG, inst),\ - SRI(OTG_V_BLANK_START_END, OTG, inst),\ - SRI(OTG_V_SYNC_A, OTG, inst),\ - SRI(OTG_V_SYNC_A_CNTL, OTG, inst),\ - SRI(OTG_CONTROL, OTG, inst),\ - SRI(OTG_STEREO_CONTROL, OTG, inst),\ - SRI(OTG_3D_STRUCTURE_CONTROL, OTG, inst),\ - SRI(OTG_STEREO_STATUS, OTG, inst),\ - SRI(OTG_V_TOTAL_MAX, OTG, inst),\ - SRI(OTG_V_TOTAL_MIN, OTG, inst),\ - SRI(OTG_V_TOTAL_CONTROL, OTG, inst),\ - SRI(OTG_TRIGA_CNTL, OTG, inst),\ - SRI(OTG_FORCE_COUNT_NOW_CNTL, OTG, inst),\ - SRI(OTG_STATIC_SCREEN_CONTROL, OTG, inst),\ - SRI(OTG_STATUS_FRAME_COUNT, OTG, inst),\ - SRI(OTG_STATUS, OTG, inst),\ - SRI(OTG_STATUS_POSITION, OTG, inst),\ - SRI(OTG_NOM_VERT_POSITION, OTG, inst),\ - SRI(OTG_M_CONST_DTO0, OTG, inst),\ - SRI(OTG_M_CONST_DTO1, OTG, inst),\ - SRI(OTG_CLOCK_CONTROL, OTG, inst),\ - SRI(OTG_VERTICAL_INTERRUPT0_CONTROL, OTG, inst),\ - SRI(OTG_VERTICAL_INTERRUPT0_POSITION, OTG, inst),\ - SRI(OTG_VERTICAL_INTERRUPT1_CONTROL, OTG, inst),\ - SRI(OTG_VERTICAL_INTERRUPT1_POSITION, OTG, inst),\ - SRI(OTG_VERTICAL_INTERRUPT2_CONTROL, OTG, inst),\ - SRI(OTG_VERTICAL_INTERRUPT2_POSITION, OTG, inst),\ - SRI(OPTC_INPUT_CLOCK_CONTROL, ODM, inst),\ - SRI(OPTC_DATA_SOURCE_SELECT, ODM, inst),\ - SRI(OPTC_INPUT_GLOBAL_CONTROL, ODM, inst),\ - SRI(CONTROL, VTG, inst),\ - SRI(OTG_VERT_SYNC_CONTROL, OTG, inst),\ - SRI(OTG_GSL_CONTROL, OTG, inst),\ - SRI(OTG_CRC_CNTL, OTG, inst),\ - SRI(OTG_CRC0_DATA_RG, OTG, inst),\ - SRI(OTG_CRC0_DATA_B, OTG, inst),\ - SRI(OTG_CRC0_WINDOWA_X_CONTROL, OTG, inst),\ - SRI(OTG_CRC0_WINDOWA_Y_CONTROL, OTG, inst),\ - SRI(OTG_CRC0_WINDOWB_X_CONTROL, OTG, inst),\ - SRI(OTG_CRC0_WINDOWB_Y_CONTROL, OTG, inst),\ - SR(GSL_SOURCE_SELECT),\ - SRI(OTG_TRIGA_MANUAL_TRIG, OTG, inst),\ - SRI(OTG_GLOBAL_CONTROL1, OTG, inst),\ - SRI(OTG_GLOBAL_CONTROL2, OTG, inst),\ - SRI(OTG_GSL_WINDOW_X, OTG, inst),\ - SRI(OTG_GSL_WINDOW_Y, OTG, inst),\ - SRI(OTG_VUPDATE_KEEPOUT, OTG, inst),\ - SRI(OTG_DSC_START_POSITION, OTG, inst),\ - SRI(OTG_DRR_TRIGGER_WINDOW, OTG, inst),\ - SRI(OTG_DRR_V_TOTAL_CHANGE, OTG, inst),\ - SRI(OPTC_DATA_FORMAT_CONTROL, ODM, inst),\ - SRI(OPTC_BYTES_PER_PIXEL, ODM, inst),\ - SRI(OPTC_WIDTH_CONTROL, ODM, inst),\ - SRI(OPTC_MEMORY_CONFIG, ODM, inst),\ - SRI(OTG_CRC_CNTL2, OTG, inst),\ - SR(DWB_SOURCE_SELECT),\ - SRI(OTG_DRR_CONTROL, OTG, inst) - -#define OPTC_COMMON_MASK_SH_LIST_DCN3_1(mask_sh)\ - SF(OTG0_OTG_VSTARTUP_PARAM, VSTARTUP_START, mask_sh),\ - SF(OTG0_OTG_VUPDATE_PARAM, VUPDATE_OFFSET, mask_sh),\ - SF(OTG0_OTG_VUPDATE_PARAM, VUPDATE_WIDTH, mask_sh),\ - SF(OTG0_OTG_VREADY_PARAM, VREADY_OFFSET, mask_sh),\ - SF(OTG0_OTG_MASTER_UPDATE_LOCK, OTG_MASTER_UPDATE_LOCK, mask_sh),\ - SF(OTG0_OTG_MASTER_UPDATE_LOCK, UPDATE_LOCK_STATUS, mask_sh),\ - SF(OTG0_OTG_GLOBAL_CONTROL0, MASTER_UPDATE_LOCK_DB_START_X, mask_sh),\ - SF(OTG0_OTG_GLOBAL_CONTROL0, MASTER_UPDATE_LOCK_DB_END_X, mask_sh),\ - SF(OTG0_OTG_GLOBAL_CONTROL0, MASTER_UPDATE_LOCK_DB_EN, mask_sh),\ - SF(OTG0_OTG_GLOBAL_CONTROL1, MASTER_UPDATE_LOCK_DB_START_Y, mask_sh),\ - SF(OTG0_OTG_GLOBAL_CONTROL1, MASTER_UPDATE_LOCK_DB_END_Y, mask_sh),\ - SF(OTG0_OTG_GLOBAL_CONTROL2, OTG_MASTER_UPDATE_LOCK_SEL, mask_sh),\ - SF(OTG0_OTG_GLOBAL_CONTROL4, DIG_UPDATE_POSITION_X, mask_sh),\ - SF(OTG0_OTG_GLOBAL_CONTROL4, DIG_UPDATE_POSITION_Y, mask_sh),\ - SF(OTG0_OTG_DOUBLE_BUFFER_CONTROL, OTG_UPDATE_PENDING, mask_sh),\ - SF(OTG0_OTG_H_TOTAL, OTG_H_TOTAL, mask_sh),\ - SF(OTG0_OTG_H_BLANK_START_END, OTG_H_BLANK_START, mask_sh),\ - SF(OTG0_OTG_H_BLANK_START_END, OTG_H_BLANK_END, mask_sh),\ - SF(OTG0_OTG_H_SYNC_A, OTG_H_SYNC_A_START, mask_sh),\ - SF(OTG0_OTG_H_SYNC_A, OTG_H_SYNC_A_END, mask_sh),\ - SF(OTG0_OTG_H_SYNC_A_CNTL, OTG_H_SYNC_A_POL, mask_sh),\ - SF(OTG0_OTG_V_TOTAL, OTG_V_TOTAL, mask_sh),\ - SF(OTG0_OTG_V_BLANK_START_END, OTG_V_BLANK_START, mask_sh),\ - SF(OTG0_OTG_V_BLANK_START_END, OTG_V_BLANK_END, mask_sh),\ - SF(OTG0_OTG_V_SYNC_A, OTG_V_SYNC_A_START, mask_sh),\ - SF(OTG0_OTG_V_SYNC_A, OTG_V_SYNC_A_END, mask_sh),\ - SF(OTG0_OTG_V_SYNC_A_CNTL, OTG_V_SYNC_A_POL, mask_sh),\ - SF(OTG0_OTG_V_SYNC_A_CNTL, OTG_V_SYNC_MODE, mask_sh),\ - SF(OTG0_OTG_CONTROL, OTG_MASTER_EN, mask_sh),\ - SF(OTG0_OTG_CONTROL, OTG_START_POINT_CNTL, mask_sh),\ - SF(OTG0_OTG_CONTROL, OTG_DISABLE_POINT_CNTL, mask_sh),\ - SF(OTG0_OTG_CONTROL, OTG_FIELD_NUMBER_CNTL, mask_sh),\ - SF(OTG0_OTG_CONTROL, OTG_OUT_MUX, mask_sh),\ - SF(OTG0_OTG_STEREO_CONTROL, OTG_STEREO_EN, mask_sh),\ - SF(OTG0_OTG_STEREO_CONTROL, OTG_STEREO_SYNC_OUTPUT_LINE_NUM, mask_sh),\ - SF(OTG0_OTG_STEREO_CONTROL, OTG_STEREO_SYNC_OUTPUT_POLARITY, mask_sh),\ - SF(OTG0_OTG_STEREO_CONTROL, OTG_STEREO_EYE_FLAG_POLARITY, mask_sh),\ - SF(OTG0_OTG_STEREO_CONTROL, OTG_DISABLE_STEREOSYNC_OUTPUT_FOR_DP, mask_sh),\ - SF(OTG0_OTG_STEREO_STATUS, OTG_STEREO_CURRENT_EYE, mask_sh),\ - SF(OTG0_OTG_3D_STRUCTURE_CONTROL, OTG_3D_STRUCTURE_EN, mask_sh),\ - SF(OTG0_OTG_3D_STRUCTURE_CONTROL, OTG_3D_STRUCTURE_V_UPDATE_MODE, mask_sh),\ - SF(OTG0_OTG_3D_STRUCTURE_CONTROL, OTG_3D_STRUCTURE_STEREO_SEL_OVR, mask_sh),\ - SF(OTG0_OTG_V_TOTAL_MAX, OTG_V_TOTAL_MAX, mask_sh),\ - SF(OTG0_OTG_V_TOTAL_MIN, OTG_V_TOTAL_MIN, mask_sh),\ - SF(OTG0_OTG_V_TOTAL_CONTROL, OTG_V_TOTAL_MIN_SEL, mask_sh),\ - SF(OTG0_OTG_V_TOTAL_CONTROL, OTG_V_TOTAL_MAX_SEL, mask_sh),\ - SF(OTG0_OTG_V_TOTAL_CONTROL, OTG_FORCE_LOCK_ON_EVENT, mask_sh),\ - SF(OTG0_OTG_V_TOTAL_CONTROL, OTG_SET_V_TOTAL_MIN_MASK, mask_sh),\ - SF(OTG0_OTG_V_TOTAL_CONTROL, OTG_VTOTAL_MID_REPLACING_MIN_EN, mask_sh),\ - SF(OTG0_OTG_V_TOTAL_CONTROL, OTG_VTOTAL_MID_REPLACING_MAX_EN, mask_sh),\ - SF(OTG0_OTG_FORCE_COUNT_NOW_CNTL, OTG_FORCE_COUNT_NOW_CLEAR, mask_sh),\ - SF(OTG0_OTG_FORCE_COUNT_NOW_CNTL, OTG_FORCE_COUNT_NOW_MODE, mask_sh),\ - SF(OTG0_OTG_FORCE_COUNT_NOW_CNTL, OTG_FORCE_COUNT_NOW_OCCURRED, mask_sh),\ - SF(OTG0_OTG_TRIGA_CNTL, OTG_TRIGA_SOURCE_SELECT, mask_sh),\ - SF(OTG0_OTG_TRIGA_CNTL, OTG_TRIGA_SOURCE_PIPE_SELECT, mask_sh),\ - SF(OTG0_OTG_TRIGA_CNTL, OTG_TRIGA_RISING_EDGE_DETECT_CNTL, mask_sh),\ - SF(OTG0_OTG_TRIGA_CNTL, OTG_TRIGA_FALLING_EDGE_DETECT_CNTL, mask_sh),\ - SF(OTG0_OTG_TRIGA_CNTL, OTG_TRIGA_POLARITY_SELECT, mask_sh),\ - SF(OTG0_OTG_TRIGA_CNTL, OTG_TRIGA_FREQUENCY_SELECT, mask_sh),\ - SF(OTG0_OTG_TRIGA_CNTL, OTG_TRIGA_DELAY, mask_sh),\ - SF(OTG0_OTG_TRIGA_CNTL, OTG_TRIGA_CLEAR, mask_sh),\ - SF(OTG0_OTG_STATIC_SCREEN_CONTROL, OTG_STATIC_SCREEN_EVENT_MASK, mask_sh),\ - SF(OTG0_OTG_STATIC_SCREEN_CONTROL, OTG_STATIC_SCREEN_FRAME_COUNT, mask_sh),\ - SF(OTG0_OTG_STATUS_FRAME_COUNT, OTG_FRAME_COUNT, mask_sh),\ - SF(OTG0_OTG_STATUS, OTG_V_BLANK, mask_sh),\ - SF(OTG0_OTG_STATUS, OTG_V_ACTIVE_DISP, mask_sh),\ - SF(OTG0_OTG_STATUS_POSITION, OTG_HORZ_COUNT, mask_sh),\ - SF(OTG0_OTG_STATUS_POSITION, OTG_VERT_COUNT, mask_sh),\ - SF(OTG0_OTG_NOM_VERT_POSITION, OTG_VERT_COUNT_NOM, mask_sh),\ - SF(OTG0_OTG_M_CONST_DTO0, OTG_M_CONST_DTO_PHASE, mask_sh),\ - SF(OTG0_OTG_M_CONST_DTO1, OTG_M_CONST_DTO_MODULO, mask_sh),\ - SF(OTG0_OTG_CLOCK_CONTROL, OTG_BUSY, mask_sh),\ - SF(OTG0_OTG_CLOCK_CONTROL, OTG_CLOCK_EN, mask_sh),\ - SF(OTG0_OTG_CLOCK_CONTROL, OTG_CLOCK_ON, mask_sh),\ - SF(OTG0_OTG_CLOCK_CONTROL, OTG_CLOCK_GATE_DIS, mask_sh),\ - SF(OTG0_OTG_VERTICAL_INTERRUPT0_CONTROL, OTG_VERTICAL_INTERRUPT0_INT_ENABLE, mask_sh),\ - SF(OTG0_OTG_VERTICAL_INTERRUPT0_POSITION, OTG_VERTICAL_INTERRUPT0_LINE_START, mask_sh),\ - SF(OTG0_OTG_VERTICAL_INTERRUPT0_POSITION, OTG_VERTICAL_INTERRUPT0_LINE_END, mask_sh),\ - SF(OTG0_OTG_VERTICAL_INTERRUPT1_CONTROL, OTG_VERTICAL_INTERRUPT1_INT_ENABLE, mask_sh),\ - SF(OTG0_OTG_VERTICAL_INTERRUPT1_POSITION, OTG_VERTICAL_INTERRUPT1_LINE_START, mask_sh),\ - SF(OTG0_OTG_VERTICAL_INTERRUPT2_CONTROL, OTG_VERTICAL_INTERRUPT2_INT_ENABLE, mask_sh),\ - SF(OTG0_OTG_VERTICAL_INTERRUPT2_POSITION, OTG_VERTICAL_INTERRUPT2_LINE_START, mask_sh),\ - SF(ODM0_OPTC_INPUT_CLOCK_CONTROL, OPTC_INPUT_CLK_EN, mask_sh),\ - SF(ODM0_OPTC_INPUT_CLOCK_CONTROL, OPTC_INPUT_CLK_ON, mask_sh),\ - SF(ODM0_OPTC_INPUT_CLOCK_CONTROL, OPTC_INPUT_CLK_GATE_DIS, mask_sh),\ - SF(ODM0_OPTC_INPUT_GLOBAL_CONTROL, OPTC_UNDERFLOW_OCCURRED_STATUS, mask_sh),\ - SF(ODM0_OPTC_INPUT_GLOBAL_CONTROL, OPTC_UNDERFLOW_CLEAR, mask_sh),\ - SF(VTG0_CONTROL, VTG0_ENABLE, mask_sh),\ - SF(VTG0_CONTROL, VTG0_FP2, mask_sh),\ - SF(VTG0_CONTROL, VTG0_VCOUNT_INIT, mask_sh),\ - SF(OTG0_OTG_VERT_SYNC_CONTROL, OTG_FORCE_VSYNC_NEXT_LINE_OCCURRED, mask_sh),\ - SF(OTG0_OTG_VERT_SYNC_CONTROL, OTG_FORCE_VSYNC_NEXT_LINE_CLEAR, mask_sh),\ - SF(OTG0_OTG_VERT_SYNC_CONTROL, OTG_AUTO_FORCE_VSYNC_MODE, mask_sh),\ - SF(OTG0_OTG_GSL_CONTROL, OTG_GSL0_EN, mask_sh),\ - SF(OTG0_OTG_GSL_CONTROL, OTG_GSL1_EN, mask_sh),\ - SF(OTG0_OTG_GSL_CONTROL, OTG_GSL2_EN, mask_sh),\ - SF(OTG0_OTG_GSL_CONTROL, OTG_GSL_MASTER_EN, mask_sh),\ - SF(OTG0_OTG_GSL_CONTROL, OTG_GSL_FORCE_DELAY, mask_sh),\ - SF(OTG0_OTG_GSL_CONTROL, OTG_GSL_CHECK_ALL_FIELDS, mask_sh),\ - SF(OTG0_OTG_CRC_CNTL, OTG_CRC_CONT_EN, mask_sh),\ - SF(OTG0_OTG_CRC_CNTL, OTG_CRC0_SELECT, mask_sh),\ - SF(OTG0_OTG_CRC_CNTL, OTG_CRC_EN, mask_sh),\ - SF(OTG0_OTG_CRC0_DATA_RG, CRC0_R_CR, mask_sh),\ - SF(OTG0_OTG_CRC0_DATA_RG, CRC0_G_Y, mask_sh),\ - SF(OTG0_OTG_CRC0_DATA_B, CRC0_B_CB, mask_sh),\ - SF(OTG0_OTG_CRC0_WINDOWA_X_CONTROL, OTG_CRC0_WINDOWA_X_START, mask_sh),\ - SF(OTG0_OTG_CRC0_WINDOWA_X_CONTROL, OTG_CRC0_WINDOWA_X_END, mask_sh),\ - SF(OTG0_OTG_CRC0_WINDOWA_Y_CONTROL, OTG_CRC0_WINDOWA_Y_START, mask_sh),\ - SF(OTG0_OTG_CRC0_WINDOWA_Y_CONTROL, OTG_CRC0_WINDOWA_Y_END, mask_sh),\ - SF(OTG0_OTG_CRC0_WINDOWB_X_CONTROL, OTG_CRC0_WINDOWB_X_START, mask_sh),\ - SF(OTG0_OTG_CRC0_WINDOWB_X_CONTROL, OTG_CRC0_WINDOWB_X_END, mask_sh),\ - SF(OTG0_OTG_CRC0_WINDOWB_Y_CONTROL, OTG_CRC0_WINDOWB_Y_START, mask_sh),\ - SF(OTG0_OTG_CRC0_WINDOWB_Y_CONTROL, OTG_CRC0_WINDOWB_Y_END, mask_sh),\ - SF(OTG0_OTG_TRIGA_MANUAL_TRIG, OTG_TRIGA_MANUAL_TRIG, mask_sh),\ - SF(GSL_SOURCE_SELECT, GSL0_READY_SOURCE_SEL, mask_sh),\ - SF(GSL_SOURCE_SELECT, GSL1_READY_SOURCE_SEL, mask_sh),\ - SF(GSL_SOURCE_SELECT, GSL2_READY_SOURCE_SEL, mask_sh),\ - SF(OTG0_OTG_GLOBAL_CONTROL2, MANUAL_FLOW_CONTROL_SEL, mask_sh),\ - SF(OTG0_OTG_GLOBAL_CONTROL2, GLOBAL_UPDATE_LOCK_EN, mask_sh),\ - SF(OTG0_OTG_GSL_WINDOW_X, OTG_GSL_WINDOW_START_X, mask_sh),\ - SF(OTG0_OTG_GSL_WINDOW_X, OTG_GSL_WINDOW_END_X, mask_sh), \ - SF(OTG0_OTG_GSL_WINDOW_Y, OTG_GSL_WINDOW_START_Y, mask_sh),\ - SF(OTG0_OTG_GSL_WINDOW_Y, OTG_GSL_WINDOW_END_Y, mask_sh),\ - SF(OTG0_OTG_VUPDATE_KEEPOUT, OTG_MASTER_UPDATE_LOCK_VUPDATE_KEEPOUT_EN, mask_sh), \ - SF(OTG0_OTG_VUPDATE_KEEPOUT, MASTER_UPDATE_LOCK_VUPDATE_KEEPOUT_START_OFFSET, mask_sh), \ - SF(OTG0_OTG_VUPDATE_KEEPOUT, MASTER_UPDATE_LOCK_VUPDATE_KEEPOUT_END_OFFSET, mask_sh), \ - SF(OTG0_OTG_GSL_CONTROL, OTG_GSL_MASTER_MODE, mask_sh), \ - SF(OTG0_OTG_GSL_CONTROL, OTG_MASTER_UPDATE_LOCK_GSL_EN, mask_sh), \ - SF(OTG0_OTG_DSC_START_POSITION, OTG_DSC_START_POSITION_X, mask_sh), \ - SF(OTG0_OTG_DSC_START_POSITION, OTG_DSC_START_POSITION_LINE_NUM, mask_sh),\ - SF(ODM0_OPTC_DATA_SOURCE_SELECT, OPTC_SEG0_SRC_SEL, mask_sh),\ - SF(ODM0_OPTC_DATA_SOURCE_SELECT, OPTC_SEG1_SRC_SEL, mask_sh),\ - SF(ODM0_OPTC_DATA_SOURCE_SELECT, OPTC_SEG2_SRC_SEL, mask_sh),\ - SF(ODM0_OPTC_DATA_SOURCE_SELECT, OPTC_SEG3_SRC_SEL, mask_sh),\ - SF(ODM0_OPTC_DATA_SOURCE_SELECT, OPTC_NUM_OF_INPUT_SEGMENT, mask_sh),\ - SF(ODM0_OPTC_MEMORY_CONFIG, OPTC_MEM_SEL, mask_sh),\ - SF(ODM0_OPTC_DATA_FORMAT_CONTROL, OPTC_DATA_FORMAT, mask_sh),\ - SF(ODM0_OPTC_DATA_FORMAT_CONTROL, OPTC_DSC_MODE, mask_sh),\ - SF(ODM0_OPTC_BYTES_PER_PIXEL, OPTC_DSC_BYTES_PER_PIXEL, mask_sh),\ - SF(ODM0_OPTC_WIDTH_CONTROL, OPTC_DSC_SLICE_WIDTH, mask_sh),\ - SF(ODM0_OPTC_WIDTH_CONTROL, OPTC_SEGMENT_WIDTH, mask_sh),\ - SF(DWB_SOURCE_SELECT, OPTC_DWB0_SOURCE_SELECT, mask_sh),\ - SF(DWB_SOURCE_SELECT, OPTC_DWB1_SOURCE_SELECT, mask_sh),\ - SF(OTG0_OTG_DRR_TRIGGER_WINDOW, OTG_DRR_TRIGGER_WINDOW_START_X, mask_sh),\ - SF(OTG0_OTG_DRR_TRIGGER_WINDOW, OTG_DRR_TRIGGER_WINDOW_END_X, mask_sh),\ - SF(OTG0_OTG_DRR_V_TOTAL_CHANGE, OTG_DRR_V_TOTAL_CHANGE_LIMIT, mask_sh),\ - SF(OTG0_OTG_H_TIMING_CNTL, OTG_H_TIMING_DIV_MODE, mask_sh),\ - SF(OTG0_OTG_DOUBLE_BUFFER_CONTROL, OTG_DRR_TIMING_DBUF_UPDATE_MODE, mask_sh),\ - SF(OTG0_OTG_CRC_CNTL2, OTG_CRC_DSC_MODE, mask_sh),\ - SF(OTG0_OTG_CRC_CNTL2, OTG_CRC_DATA_STREAM_COMBINE_MODE, mask_sh),\ - SF(OTG0_OTG_CRC_CNTL2, OTG_CRC_DATA_STREAM_SPLIT_MODE, mask_sh),\ - SF(OTG0_OTG_CRC_CNTL2, OTG_CRC_DATA_FORMAT, mask_sh),\ - SF(OTG0_OTG_DRR_CONTROL, OTG_V_TOTAL_LAST_USED_BY_DRR, mask_sh) - -void dcn31_timing_generator_init(struct optc *optc1); - -bool optc31_immediate_disable_crtc(struct timing_generator *optc); - -void optc31_set_drr(struct timing_generator *optc, const struct drr_params *params); - -void optc3_init_odm(struct timing_generator *optc); - -#endif /* __DC_OPTC_DCN31_H__ */ diff --git a/drivers/gpu/drm/amd/display/dc/dcn314/Makefile b/drivers/gpu/drm/amd/display/dc/dcn314/Makefile index 6ea47e00d62d..d5c177346a3b 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn314/Makefile +++ b/drivers/gpu/drm/amd/display/dc/dcn314/Makefile @@ -11,7 +11,7 @@ # Makefile for dcn314. DCN314 = dcn314_init.o \ - dcn314_dio_stream_encoder.o dcn314_dccg.o dcn314_optc.o + dcn314_dio_stream_encoder.o dcn314_dccg.o AMD_DAL_DCN314 = $(addprefix $(AMDDALPATH)/dc/dcn314/,$(DCN314)) diff --git a/drivers/gpu/drm/amd/display/dc/dcn314/dcn314_optc.c b/drivers/gpu/drm/amd/display/dc/dcn314/dcn314_optc.c deleted file mode 100644 index 0086cafb0f7a..000000000000 --- a/drivers/gpu/drm/amd/display/dc/dcn314/dcn314_optc.c +++ /dev/null @@ -1,273 +0,0 @@ -// SPDX-License-Identifier: MIT -/* - * Copyright 2022 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 "dcn314_optc.h" - -#include "dcn30/dcn30_optc.h" -#include "dcn31/dcn31_optc.h" -#include "reg_helper.h" -#include "dc.h" -#include "dcn_calc_math.h" - -#define REG(reg)\ - optc1->tg_regs->reg - -#define CTX \ - optc1->base.ctx - -#undef FN -#define FN(reg_name, field_name) \ - optc1->tg_shift->field_name, optc1->tg_mask->field_name - -/* - * Enable CRTC - * Enable CRTC - call ASIC Control Object to enable Timing generator. - */ - -static void optc314_set_odm_combine(struct timing_generator *optc, int *opp_id, int opp_cnt, - struct dc_crtc_timing *timing) -{ - struct optc *optc1 = DCN10TG_FROM_TG(optc); - uint32_t memory_mask = 0; - int h_active = timing->h_addressable + timing->h_border_left + timing->h_border_right; - int mpcc_hactive = h_active / opp_cnt; - /* Each memory instance is 2048x(314x2) bits to support half line of 4096 */ - int odm_mem_count = (h_active + 2047) / 2048; - - /* - * display <= 4k : 2 memories + 2 pipes - * 4k < display <= 8k : 4 memories + 2 pipes - * 8k < display <= 12k : 6 memories + 4 pipes - */ - if (opp_cnt == 4) { - if (odm_mem_count <= 2) - memory_mask = 0x3; - else if (odm_mem_count <= 4) - memory_mask = 0xf; - else - memory_mask = 0x3f; - } else { - if (odm_mem_count <= 2) - memory_mask = 0x1 << (opp_id[0] * 2) | 0x1 << (opp_id[1] * 2); - else if (odm_mem_count <= 4) - memory_mask = 0x3 << (opp_id[0] * 2) | 0x3 << (opp_id[1] * 2); - else - memory_mask = 0x77; - } - - REG_SET(OPTC_MEMORY_CONFIG, 0, - OPTC_MEM_SEL, memory_mask); - - if (opp_cnt == 2) { - REG_SET_3(OPTC_DATA_SOURCE_SELECT, 0, - OPTC_NUM_OF_INPUT_SEGMENT, 1, - OPTC_SEG0_SRC_SEL, opp_id[0], - OPTC_SEG1_SRC_SEL, opp_id[1]); - } else if (opp_cnt == 4) { - REG_SET_5(OPTC_DATA_SOURCE_SELECT, 0, - OPTC_NUM_OF_INPUT_SEGMENT, 3, - OPTC_SEG0_SRC_SEL, opp_id[0], - OPTC_SEG1_SRC_SEL, opp_id[1], - OPTC_SEG2_SRC_SEL, opp_id[2], - OPTC_SEG3_SRC_SEL, opp_id[3]); - } - - REG_UPDATE(OPTC_WIDTH_CONTROL, - OPTC_SEGMENT_WIDTH, mpcc_hactive); - - REG_UPDATE(OTG_H_TIMING_CNTL, - OTG_H_TIMING_DIV_MODE, opp_cnt - 1); - optc1->opp_count = opp_cnt; -} - -static bool optc314_enable_crtc(struct timing_generator *optc) -{ - struct optc *optc1 = DCN10TG_FROM_TG(optc); - - /* opp instance for OTG, 1 to 1 mapping and odm will adjust */ - REG_UPDATE(OPTC_DATA_SOURCE_SELECT, - OPTC_SEG0_SRC_SEL, optc->inst); - - /* VTG enable first is for HW workaround */ - REG_UPDATE(CONTROL, - VTG0_ENABLE, 1); - - REG_SEQ_START(); - - /* Enable CRTC */ - REG_UPDATE_2(OTG_CONTROL, - OTG_DISABLE_POINT_CNTL, 2, - OTG_MASTER_EN, 1); - - REG_SEQ_SUBMIT(); - REG_SEQ_WAIT_DONE(); - - return true; -} - -/* disable_crtc */ -static bool optc314_disable_crtc(struct timing_generator *optc) -{ - struct optc *optc1 = DCN10TG_FROM_TG(optc); - - /* disable otg request until end of the first line - * in the vertical blank region - */ - REG_UPDATE(OTG_CONTROL, - OTG_MASTER_EN, 0); - - REG_UPDATE(CONTROL, - VTG0_ENABLE, 0); - - /* CRTC disabled, so disable clock. */ - REG_WAIT(OTG_CLOCK_CONTROL, - OTG_BUSY, 0, - 1, 100000); - - return true; -} - -static void optc314_phantom_crtc_post_enable(struct timing_generator *optc) -{ - struct optc *optc1 = DCN10TG_FROM_TG(optc); - - /* Disable immediately. */ - REG_UPDATE_2(OTG_CONTROL, OTG_DISABLE_POINT_CNTL, 0, OTG_MASTER_EN, 0); - - /* CRTC disabled, so disable clock. */ - REG_WAIT(OTG_CLOCK_CONTROL, OTG_BUSY, 0, 1, 100000); -} - -static void optc314_set_odm_bypass(struct timing_generator *optc, - const struct dc_crtc_timing *dc_crtc_timing) -{ - struct optc *optc1 = DCN10TG_FROM_TG(optc); - enum h_timing_div_mode h_div = H_TIMING_NO_DIV; - - REG_SET_5(OPTC_DATA_SOURCE_SELECT, 0, - OPTC_NUM_OF_INPUT_SEGMENT, 0, - OPTC_SEG0_SRC_SEL, optc->inst, - OPTC_SEG1_SRC_SEL, 0xf, - OPTC_SEG2_SRC_SEL, 0xf, - OPTC_SEG3_SRC_SEL, 0xf - ); - - h_div = optc1_is_two_pixels_per_containter(dc_crtc_timing); - REG_UPDATE(OTG_H_TIMING_CNTL, - OTG_H_TIMING_DIV_MODE, h_div); - - REG_SET(OPTC_MEMORY_CONFIG, 0, - OPTC_MEM_SEL, 0); - optc1->opp_count = 1; -} - -static void optc314_set_h_timing_div_manual_mode(struct timing_generator *optc, bool manual_mode) -{ - struct optc *optc1 = DCN10TG_FROM_TG(optc); - - REG_UPDATE(OTG_H_TIMING_CNTL, - OTG_H_TIMING_DIV_MODE_MANUAL, manual_mode ? 1 : 0); -} - - -static struct timing_generator_funcs dcn314_tg_funcs = { - .validate_timing = optc1_validate_timing, - .program_timing = optc1_program_timing, - .setup_vertical_interrupt0 = optc1_setup_vertical_interrupt0, - .setup_vertical_interrupt1 = optc1_setup_vertical_interrupt1, - .setup_vertical_interrupt2 = optc1_setup_vertical_interrupt2, - .program_global_sync = optc1_program_global_sync, - .enable_crtc = optc314_enable_crtc, - .disable_crtc = optc314_disable_crtc, - .immediate_disable_crtc = optc31_immediate_disable_crtc, - .phantom_crtc_post_enable = optc314_phantom_crtc_post_enable, - /* used by enable_timing_synchronization. Not need for FPGA */ - .is_counter_moving = optc1_is_counter_moving, - .get_position = optc1_get_position, - .get_frame_count = optc1_get_vblank_counter, - .get_scanoutpos = optc1_get_crtc_scanoutpos, - .get_otg_active_size = optc1_get_otg_active_size, - .set_early_control = optc1_set_early_control, - /* used by enable_timing_synchronization. Not need for FPGA */ - .wait_for_state = optc1_wait_for_state, - .set_blank_color = optc3_program_blank_color, - .did_triggered_reset_occur = optc1_did_triggered_reset_occur, - .triplebuffer_lock = optc3_triplebuffer_lock, - .triplebuffer_unlock = optc2_triplebuffer_unlock, - .enable_reset_trigger = optc1_enable_reset_trigger, - .enable_crtc_reset = optc1_enable_crtc_reset, - .disable_reset_trigger = optc1_disable_reset_trigger, - .lock = optc3_lock, - .unlock = optc1_unlock, - .lock_doublebuffer_enable = optc3_lock_doublebuffer_enable, - .lock_doublebuffer_disable = optc3_lock_doublebuffer_disable, - .enable_optc_clock = optc1_enable_optc_clock, - .set_drr = optc31_set_drr, - .get_last_used_drr_vtotal = optc2_get_last_used_drr_vtotal, - .set_vtotal_min_max = optc1_set_vtotal_min_max, - .set_static_screen_control = optc1_set_static_screen_control, - .program_stereo = optc1_program_stereo, - .is_stereo_left_eye = optc1_is_stereo_left_eye, - .tg_init = optc3_tg_init, - .is_tg_enabled = optc1_is_tg_enabled, - .is_optc_underflow_occurred = optc1_is_optc_underflow_occurred, - .clear_optc_underflow = optc1_clear_optc_underflow, - .setup_global_swap_lock = NULL, - .get_crc = optc1_get_crc, - .configure_crc = optc1_configure_crc, - .set_dsc_config = optc3_set_dsc_config, - .get_dsc_status = optc2_get_dsc_status, - .set_dwb_source = NULL, - .get_optc_source = optc2_get_optc_source, - .set_out_mux = optc3_set_out_mux, - .set_drr_trigger_window = optc3_set_drr_trigger_window, - .set_vtotal_change_limit = optc3_set_vtotal_change_limit, - .set_gsl = optc2_set_gsl, - .set_gsl_source_select = optc2_set_gsl_source_select, - .set_vtg_params = optc1_set_vtg_params, - .program_manual_trigger = optc2_program_manual_trigger, - .setup_manual_trigger = optc2_setup_manual_trigger, - .get_hw_timing = optc1_get_hw_timing, - .init_odm = optc3_init_odm, - .set_odm_bypass = optc314_set_odm_bypass, - .set_odm_combine = optc314_set_odm_combine, - .set_h_timing_div_manual_mode = optc314_set_h_timing_div_manual_mode, -}; - -void dcn314_timing_generator_init(struct optc *optc1) -{ - optc1->base.funcs = &dcn314_tg_funcs; - - optc1->max_h_total = optc1->tg_mask->OTG_H_TOTAL + 1; - optc1->max_v_total = optc1->tg_mask->OTG_V_TOTAL + 1; - - optc1->min_h_blank = 32; - optc1->min_v_blank = 3; - optc1->min_v_blank_interlace = 5; - optc1->min_h_sync_width = 4; - optc1->min_v_sync_width = 1; -} - diff --git a/drivers/gpu/drm/amd/display/dc/dcn314/dcn314_optc.h b/drivers/gpu/drm/amd/display/dc/dcn314/dcn314_optc.h deleted file mode 100644 index 99c098e76116..000000000000 --- a/drivers/gpu/drm/amd/display/dc/dcn314/dcn314_optc.h +++ /dev/null @@ -1,255 +0,0 @@ -/* SPDX-License-Identifier: MIT */ -/* - * Copyright 2022 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_OPTC_DCN314_H__ -#define __DC_OPTC_DCN314_H__ - -#include "dcn10/dcn10_optc.h" - -#define OPTC_COMMON_REG_LIST_DCN3_14(inst) \ - SRI(OTG_VSTARTUP_PARAM, OTG, inst),\ - SRI(OTG_VUPDATE_PARAM, OTG, inst),\ - SRI(OTG_VREADY_PARAM, OTG, inst),\ - SRI(OTG_MASTER_UPDATE_LOCK, OTG, inst),\ - SRI(OTG_GLOBAL_CONTROL0, OTG, inst),\ - SRI(OTG_GLOBAL_CONTROL1, OTG, inst),\ - SRI(OTG_GLOBAL_CONTROL2, OTG, inst),\ - SRI(OTG_GLOBAL_CONTROL4, OTG, inst),\ - SRI(OTG_DOUBLE_BUFFER_CONTROL, OTG, inst),\ - SRI(OTG_H_TOTAL, OTG, inst),\ - SRI(OTG_H_BLANK_START_END, OTG, inst),\ - SRI(OTG_H_SYNC_A, OTG, inst),\ - SRI(OTG_H_SYNC_A_CNTL, OTG, inst),\ - SRI(OTG_H_TIMING_CNTL, OTG, inst),\ - SRI(OTG_V_TOTAL, OTG, inst),\ - SRI(OTG_V_BLANK_START_END, OTG, inst),\ - SRI(OTG_V_SYNC_A, OTG, inst),\ - SRI(OTG_V_SYNC_A_CNTL, OTG, inst),\ - SRI(OTG_CONTROL, OTG, inst),\ - SRI(OTG_STEREO_CONTROL, OTG, inst),\ - SRI(OTG_3D_STRUCTURE_CONTROL, OTG, inst),\ - SRI(OTG_STEREO_STATUS, OTG, inst),\ - SRI(OTG_V_TOTAL_MAX, OTG, inst),\ - SRI(OTG_V_TOTAL_MIN, OTG, inst),\ - SRI(OTG_V_TOTAL_CONTROL, OTG, inst),\ - SRI(OTG_TRIGA_CNTL, OTG, inst),\ - SRI(OTG_FORCE_COUNT_NOW_CNTL, OTG, inst),\ - SRI(OTG_STATIC_SCREEN_CONTROL, OTG, inst),\ - SRI(OTG_STATUS_FRAME_COUNT, OTG, inst),\ - SRI(OTG_STATUS, OTG, inst),\ - SRI(OTG_STATUS_POSITION, OTG, inst),\ - SRI(OTG_NOM_VERT_POSITION, OTG, inst),\ - SRI(OTG_M_CONST_DTO0, OTG, inst),\ - SRI(OTG_M_CONST_DTO1, OTG, inst),\ - SRI(OTG_CLOCK_CONTROL, OTG, inst),\ - SRI(OTG_VERTICAL_INTERRUPT0_CONTROL, OTG, inst),\ - SRI(OTG_VERTICAL_INTERRUPT0_POSITION, OTG, inst),\ - SRI(OTG_VERTICAL_INTERRUPT1_CONTROL, OTG, inst),\ - SRI(OTG_VERTICAL_INTERRUPT1_POSITION, OTG, inst),\ - SRI(OTG_VERTICAL_INTERRUPT2_CONTROL, OTG, inst),\ - SRI(OTG_VERTICAL_INTERRUPT2_POSITION, OTG, inst),\ - SRI(OPTC_INPUT_CLOCK_CONTROL, ODM, inst),\ - SRI(OPTC_DATA_SOURCE_SELECT, ODM, inst),\ - SRI(OPTC_INPUT_GLOBAL_CONTROL, ODM, inst),\ - SRI(CONTROL, VTG, inst),\ - SRI(OTG_VERT_SYNC_CONTROL, OTG, inst),\ - SRI(OTG_GSL_CONTROL, OTG, inst),\ - SRI(OTG_CRC_CNTL, OTG, inst),\ - SRI(OTG_CRC0_DATA_RG, OTG, inst),\ - SRI(OTG_CRC0_DATA_B, OTG, inst),\ - SRI(OTG_CRC0_WINDOWA_X_CONTROL, OTG, inst),\ - SRI(OTG_CRC0_WINDOWA_Y_CONTROL, OTG, inst),\ - SRI(OTG_CRC0_WINDOWB_X_CONTROL, OTG, inst),\ - SRI(OTG_CRC0_WINDOWB_Y_CONTROL, OTG, inst),\ - SR(GSL_SOURCE_SELECT),\ - SRI(OTG_TRIGA_MANUAL_TRIG, OTG, inst),\ - SRI(OTG_GLOBAL_CONTROL1, OTG, inst),\ - SRI(OTG_GLOBAL_CONTROL2, OTG, inst),\ - SRI(OTG_GSL_WINDOW_X, OTG, inst),\ - SRI(OTG_GSL_WINDOW_Y, OTG, inst),\ - SRI(OTG_VUPDATE_KEEPOUT, OTG, inst),\ - SRI(OTG_DSC_START_POSITION, OTG, inst),\ - SRI(OTG_DRR_TRIGGER_WINDOW, OTG, inst),\ - SRI(OTG_DRR_V_TOTAL_CHANGE, OTG, inst),\ - SRI(OPTC_DATA_FORMAT_CONTROL, ODM, inst),\ - SRI(OPTC_BYTES_PER_PIXEL, ODM, inst),\ - SRI(OPTC_WIDTH_CONTROL, ODM, inst),\ - SRI(OPTC_MEMORY_CONFIG, ODM, inst),\ - SRI(OTG_DRR_CONTROL, OTG, inst) - -#define OPTC_COMMON_MASK_SH_LIST_DCN3_14(mask_sh)\ - SF(OTG0_OTG_VSTARTUP_PARAM, VSTARTUP_START, mask_sh),\ - SF(OTG0_OTG_VUPDATE_PARAM, VUPDATE_OFFSET, mask_sh),\ - SF(OTG0_OTG_VUPDATE_PARAM, VUPDATE_WIDTH, mask_sh),\ - SF(OTG0_OTG_VREADY_PARAM, VREADY_OFFSET, mask_sh),\ - SF(OTG0_OTG_MASTER_UPDATE_LOCK, OTG_MASTER_UPDATE_LOCK, mask_sh),\ - SF(OTG0_OTG_MASTER_UPDATE_LOCK, UPDATE_LOCK_STATUS, mask_sh),\ - SF(OTG0_OTG_GLOBAL_CONTROL0, MASTER_UPDATE_LOCK_DB_START_X, mask_sh),\ - SF(OTG0_OTG_GLOBAL_CONTROL0, MASTER_UPDATE_LOCK_DB_END_X, mask_sh),\ - SF(OTG0_OTG_GLOBAL_CONTROL0, MASTER_UPDATE_LOCK_DB_EN, mask_sh),\ - SF(OTG0_OTG_GLOBAL_CONTROL1, MASTER_UPDATE_LOCK_DB_START_Y, mask_sh),\ - SF(OTG0_OTG_GLOBAL_CONTROL1, MASTER_UPDATE_LOCK_DB_END_Y, mask_sh),\ - SF(OTG0_OTG_GLOBAL_CONTROL2, OTG_MASTER_UPDATE_LOCK_SEL, mask_sh),\ - SF(OTG0_OTG_GLOBAL_CONTROL4, DIG_UPDATE_POSITION_X, mask_sh),\ - SF(OTG0_OTG_GLOBAL_CONTROL4, DIG_UPDATE_POSITION_Y, mask_sh),\ - SF(OTG0_OTG_DOUBLE_BUFFER_CONTROL, OTG_UPDATE_PENDING, mask_sh),\ - SF(OTG0_OTG_H_TOTAL, OTG_H_TOTAL, mask_sh),\ - SF(OTG0_OTG_H_BLANK_START_END, OTG_H_BLANK_START, mask_sh),\ - SF(OTG0_OTG_H_BLANK_START_END, OTG_H_BLANK_END, mask_sh),\ - SF(OTG0_OTG_H_SYNC_A, OTG_H_SYNC_A_START, mask_sh),\ - SF(OTG0_OTG_H_SYNC_A, OTG_H_SYNC_A_END, mask_sh),\ - SF(OTG0_OTG_H_SYNC_A_CNTL, OTG_H_SYNC_A_POL, mask_sh),\ - SF(OTG0_OTG_V_TOTAL, OTG_V_TOTAL, mask_sh),\ - SF(OTG0_OTG_V_BLANK_START_END, OTG_V_BLANK_START, mask_sh),\ - SF(OTG0_OTG_V_BLANK_START_END, OTG_V_BLANK_END, mask_sh),\ - SF(OTG0_OTG_V_SYNC_A, OTG_V_SYNC_A_START, mask_sh),\ - SF(OTG0_OTG_V_SYNC_A, OTG_V_SYNC_A_END, mask_sh),\ - SF(OTG0_OTG_V_SYNC_A_CNTL, OTG_V_SYNC_A_POL, mask_sh),\ - SF(OTG0_OTG_V_SYNC_A_CNTL, OTG_V_SYNC_MODE, mask_sh),\ - SF(OTG0_OTG_CONTROL, OTG_MASTER_EN, mask_sh),\ - SF(OTG0_OTG_CONTROL, OTG_START_POINT_CNTL, mask_sh),\ - SF(OTG0_OTG_CONTROL, OTG_DISABLE_POINT_CNTL, mask_sh),\ - SF(OTG0_OTG_CONTROL, OTG_FIELD_NUMBER_CNTL, mask_sh),\ - SF(OTG0_OTG_CONTROL, OTG_OUT_MUX, mask_sh),\ - SF(OTG0_OTG_STEREO_CONTROL, OTG_STEREO_EN, mask_sh),\ - SF(OTG0_OTG_STEREO_CONTROL, OTG_STEREO_SYNC_OUTPUT_LINE_NUM, mask_sh),\ - SF(OTG0_OTG_STEREO_CONTROL, OTG_STEREO_SYNC_OUTPUT_POLARITY, mask_sh),\ - SF(OTG0_OTG_STEREO_CONTROL, OTG_STEREO_EYE_FLAG_POLARITY, mask_sh),\ - SF(OTG0_OTG_STEREO_CONTROL, OTG_DISABLE_STEREOSYNC_OUTPUT_FOR_DP, mask_sh),\ - SF(OTG0_OTG_STEREO_STATUS, OTG_STEREO_CURRENT_EYE, mask_sh),\ - SF(OTG0_OTG_3D_STRUCTURE_CONTROL, OTG_3D_STRUCTURE_EN, mask_sh),\ - SF(OTG0_OTG_3D_STRUCTURE_CONTROL, OTG_3D_STRUCTURE_V_UPDATE_MODE, mask_sh),\ - SF(OTG0_OTG_3D_STRUCTURE_CONTROL, OTG_3D_STRUCTURE_STEREO_SEL_OVR, mask_sh),\ - SF(OTG0_OTG_V_TOTAL_MAX, OTG_V_TOTAL_MAX, mask_sh),\ - SF(OTG0_OTG_V_TOTAL_MIN, OTG_V_TOTAL_MIN, mask_sh),\ - SF(OTG0_OTG_V_TOTAL_CONTROL, OTG_V_TOTAL_MIN_SEL, mask_sh),\ - SF(OTG0_OTG_V_TOTAL_CONTROL, OTG_V_TOTAL_MAX_SEL, mask_sh),\ - SF(OTG0_OTG_V_TOTAL_CONTROL, OTG_FORCE_LOCK_ON_EVENT, mask_sh),\ - SF(OTG0_OTG_V_TOTAL_CONTROL, OTG_SET_V_TOTAL_MIN_MASK, mask_sh),\ - SF(OTG0_OTG_V_TOTAL_CONTROL, OTG_VTOTAL_MID_REPLACING_MIN_EN, mask_sh),\ - SF(OTG0_OTG_V_TOTAL_CONTROL, OTG_VTOTAL_MID_REPLACING_MAX_EN, mask_sh),\ - SF(OTG0_OTG_FORCE_COUNT_NOW_CNTL, OTG_FORCE_COUNT_NOW_CLEAR, mask_sh),\ - SF(OTG0_OTG_FORCE_COUNT_NOW_CNTL, OTG_FORCE_COUNT_NOW_MODE, mask_sh),\ - SF(OTG0_OTG_FORCE_COUNT_NOW_CNTL, OTG_FORCE_COUNT_NOW_OCCURRED, mask_sh),\ - SF(OTG0_OTG_TRIGA_CNTL, OTG_TRIGA_SOURCE_SELECT, mask_sh),\ - SF(OTG0_OTG_TRIGA_CNTL, OTG_TRIGA_SOURCE_PIPE_SELECT, mask_sh),\ - SF(OTG0_OTG_TRIGA_CNTL, OTG_TRIGA_RISING_EDGE_DETECT_CNTL, mask_sh),\ - SF(OTG0_OTG_TRIGA_CNTL, OTG_TRIGA_FALLING_EDGE_DETECT_CNTL, mask_sh),\ - SF(OTG0_OTG_TRIGA_CNTL, OTG_TRIGA_POLARITY_SELECT, mask_sh),\ - SF(OTG0_OTG_TRIGA_CNTL, OTG_TRIGA_FREQUENCY_SELECT, mask_sh),\ - SF(OTG0_OTG_TRIGA_CNTL, OTG_TRIGA_DELAY, mask_sh),\ - SF(OTG0_OTG_TRIGA_CNTL, OTG_TRIGA_CLEAR, mask_sh),\ - SF(OTG0_OTG_STATIC_SCREEN_CONTROL, OTG_STATIC_SCREEN_EVENT_MASK, mask_sh),\ - SF(OTG0_OTG_STATIC_SCREEN_CONTROL, OTG_STATIC_SCREEN_FRAME_COUNT, mask_sh),\ - SF(OTG0_OTG_STATUS_FRAME_COUNT, OTG_FRAME_COUNT, mask_sh),\ - SF(OTG0_OTG_STATUS, OTG_V_BLANK, mask_sh),\ - SF(OTG0_OTG_STATUS, OTG_V_ACTIVE_DISP, mask_sh),\ - SF(OTG0_OTG_STATUS_POSITION, OTG_HORZ_COUNT, mask_sh),\ - SF(OTG0_OTG_STATUS_POSITION, OTG_VERT_COUNT, mask_sh),\ - SF(OTG0_OTG_NOM_VERT_POSITION, OTG_VERT_COUNT_NOM, mask_sh),\ - SF(OTG0_OTG_M_CONST_DTO0, OTG_M_CONST_DTO_PHASE, mask_sh),\ - SF(OTG0_OTG_M_CONST_DTO1, OTG_M_CONST_DTO_MODULO, mask_sh),\ - SF(OTG0_OTG_CLOCK_CONTROL, OTG_BUSY, mask_sh),\ - SF(OTG0_OTG_CLOCK_CONTROL, OTG_CLOCK_EN, mask_sh),\ - SF(OTG0_OTG_CLOCK_CONTROL, OTG_CLOCK_ON, mask_sh),\ - SF(OTG0_OTG_CLOCK_CONTROL, OTG_CLOCK_GATE_DIS, mask_sh),\ - SF(OTG0_OTG_VERTICAL_INTERRUPT0_CONTROL, OTG_VERTICAL_INTERRUPT0_INT_ENABLE, mask_sh),\ - SF(OTG0_OTG_VERTICAL_INTERRUPT0_POSITION, OTG_VERTICAL_INTERRUPT0_LINE_START, mask_sh),\ - SF(OTG0_OTG_VERTICAL_INTERRUPT0_POSITION, OTG_VERTICAL_INTERRUPT0_LINE_END, mask_sh),\ - SF(OTG0_OTG_VERTICAL_INTERRUPT1_CONTROL, OTG_VERTICAL_INTERRUPT1_INT_ENABLE, mask_sh),\ - SF(OTG0_OTG_VERTICAL_INTERRUPT1_POSITION, OTG_VERTICAL_INTERRUPT1_LINE_START, mask_sh),\ - SF(OTG0_OTG_VERTICAL_INTERRUPT2_CONTROL, OTG_VERTICAL_INTERRUPT2_INT_ENABLE, mask_sh),\ - SF(OTG0_OTG_VERTICAL_INTERRUPT2_POSITION, OTG_VERTICAL_INTERRUPT2_LINE_START, mask_sh),\ - SF(ODM0_OPTC_INPUT_CLOCK_CONTROL, OPTC_INPUT_CLK_EN, mask_sh),\ - SF(ODM0_OPTC_INPUT_CLOCK_CONTROL, OPTC_INPUT_CLK_ON, mask_sh),\ - SF(ODM0_OPTC_INPUT_CLOCK_CONTROL, OPTC_INPUT_CLK_GATE_DIS, mask_sh),\ - SF(ODM0_OPTC_INPUT_GLOBAL_CONTROL, OPTC_UNDERFLOW_OCCURRED_STATUS, mask_sh),\ - SF(ODM0_OPTC_INPUT_GLOBAL_CONTROL, OPTC_UNDERFLOW_CLEAR, mask_sh),\ - SF(VTG0_CONTROL, VTG0_ENABLE, mask_sh),\ - SF(VTG0_CONTROL, VTG0_FP2, mask_sh),\ - SF(VTG0_CONTROL, VTG0_VCOUNT_INIT, mask_sh),\ - SF(OTG0_OTG_VERT_SYNC_CONTROL, OTG_FORCE_VSYNC_NEXT_LINE_OCCURRED, mask_sh),\ - SF(OTG0_OTG_VERT_SYNC_CONTROL, OTG_FORCE_VSYNC_NEXT_LINE_CLEAR, mask_sh),\ - SF(OTG0_OTG_VERT_SYNC_CONTROL, OTG_AUTO_FORCE_VSYNC_MODE, mask_sh),\ - SF(OTG0_OTG_GSL_CONTROL, OTG_GSL0_EN, mask_sh),\ - SF(OTG0_OTG_GSL_CONTROL, OTG_GSL1_EN, mask_sh),\ - SF(OTG0_OTG_GSL_CONTROL, OTG_GSL2_EN, mask_sh),\ - SF(OTG0_OTG_GSL_CONTROL, OTG_GSL_MASTER_EN, mask_sh),\ - SF(OTG0_OTG_GSL_CONTROL, OTG_GSL_FORCE_DELAY, mask_sh),\ - SF(OTG0_OTG_GSL_CONTROL, OTG_GSL_CHECK_ALL_FIELDS, mask_sh),\ - SF(OTG0_OTG_CRC_CNTL, OTG_CRC_CONT_EN, mask_sh),\ - SF(OTG0_OTG_CRC_CNTL, OTG_CRC0_SELECT, mask_sh),\ - SF(OTG0_OTG_CRC_CNTL, OTG_CRC_EN, mask_sh),\ - SF(OTG0_OTG_CRC0_DATA_RG, CRC0_R_CR, mask_sh),\ - SF(OTG0_OTG_CRC0_DATA_RG, CRC0_G_Y, mask_sh),\ - SF(OTG0_OTG_CRC0_DATA_B, CRC0_B_CB, mask_sh),\ - SF(OTG0_OTG_CRC0_WINDOWA_X_CONTROL, OTG_CRC0_WINDOWA_X_START, mask_sh),\ - SF(OTG0_OTG_CRC0_WINDOWA_X_CONTROL, OTG_CRC0_WINDOWA_X_END, mask_sh),\ - SF(OTG0_OTG_CRC0_WINDOWA_Y_CONTROL, OTG_CRC0_WINDOWA_Y_START, mask_sh),\ - SF(OTG0_OTG_CRC0_WINDOWA_Y_CONTROL, OTG_CRC0_WINDOWA_Y_END, mask_sh),\ - SF(OTG0_OTG_CRC0_WINDOWB_X_CONTROL, OTG_CRC0_WINDOWB_X_START, mask_sh),\ - SF(OTG0_OTG_CRC0_WINDOWB_X_CONTROL, OTG_CRC0_WINDOWB_X_END, mask_sh),\ - SF(OTG0_OTG_CRC0_WINDOWB_Y_CONTROL, OTG_CRC0_WINDOWB_Y_START, mask_sh),\ - SF(OTG0_OTG_CRC0_WINDOWB_Y_CONTROL, OTG_CRC0_WINDOWB_Y_END, mask_sh),\ - SF(OTG0_OTG_TRIGA_MANUAL_TRIG, OTG_TRIGA_MANUAL_TRIG, mask_sh),\ - SF(GSL_SOURCE_SELECT, GSL0_READY_SOURCE_SEL, mask_sh),\ - SF(GSL_SOURCE_SELECT, GSL1_READY_SOURCE_SEL, mask_sh),\ - SF(GSL_SOURCE_SELECT, GSL2_READY_SOURCE_SEL, mask_sh),\ - SF(OTG0_OTG_GLOBAL_CONTROL2, MANUAL_FLOW_CONTROL_SEL, mask_sh),\ - SF(OTG0_OTG_GLOBAL_CONTROL2, GLOBAL_UPDATE_LOCK_EN, mask_sh),\ - SF(OTG0_OTG_GSL_WINDOW_X, OTG_GSL_WINDOW_START_X, mask_sh),\ - SF(OTG0_OTG_GSL_WINDOW_X, OTG_GSL_WINDOW_END_X, mask_sh), \ - SF(OTG0_OTG_GSL_WINDOW_Y, OTG_GSL_WINDOW_START_Y, mask_sh),\ - SF(OTG0_OTG_GSL_WINDOW_Y, OTG_GSL_WINDOW_END_Y, mask_sh),\ - SF(OTG0_OTG_VUPDATE_KEEPOUT, OTG_MASTER_UPDATE_LOCK_VUPDATE_KEEPOUT_EN, mask_sh), \ - SF(OTG0_OTG_VUPDATE_KEEPOUT, MASTER_UPDATE_LOCK_VUPDATE_KEEPOUT_START_OFFSET, mask_sh), \ - SF(OTG0_OTG_VUPDATE_KEEPOUT, MASTER_UPDATE_LOCK_VUPDATE_KEEPOUT_END_OFFSET, mask_sh), \ - SF(OTG0_OTG_GSL_CONTROL, OTG_GSL_MASTER_MODE, mask_sh), \ - SF(OTG0_OTG_GSL_CONTROL, OTG_MASTER_UPDATE_LOCK_GSL_EN, mask_sh), \ - SF(OTG0_OTG_DSC_START_POSITION, OTG_DSC_START_POSITION_X, mask_sh), \ - SF(OTG0_OTG_DSC_START_POSITION, OTG_DSC_START_POSITION_LINE_NUM, mask_sh),\ - SF(ODM0_OPTC_DATA_SOURCE_SELECT, OPTC_SEG0_SRC_SEL, mask_sh),\ - SF(ODM0_OPTC_DATA_SOURCE_SELECT, OPTC_SEG1_SRC_SEL, mask_sh),\ - SF(ODM0_OPTC_DATA_SOURCE_SELECT, OPTC_SEG2_SRC_SEL, mask_sh),\ - SF(ODM0_OPTC_DATA_SOURCE_SELECT, OPTC_SEG3_SRC_SEL, mask_sh),\ - SF(ODM0_OPTC_DATA_SOURCE_SELECT, OPTC_NUM_OF_INPUT_SEGMENT, mask_sh),\ - SF(ODM0_OPTC_MEMORY_CONFIG, OPTC_MEM_SEL, mask_sh),\ - SF(ODM0_OPTC_DATA_FORMAT_CONTROL, OPTC_DATA_FORMAT, mask_sh),\ - SF(ODM0_OPTC_DATA_FORMAT_CONTROL, OPTC_DSC_MODE, mask_sh),\ - SF(ODM0_OPTC_BYTES_PER_PIXEL, OPTC_DSC_BYTES_PER_PIXEL, mask_sh),\ - SF(ODM0_OPTC_WIDTH_CONTROL, OPTC_DSC_SLICE_WIDTH, mask_sh),\ - SF(ODM0_OPTC_WIDTH_CONTROL, OPTC_SEGMENT_WIDTH, mask_sh),\ - SF(OTG0_OTG_DRR_TRIGGER_WINDOW, OTG_DRR_TRIGGER_WINDOW_START_X, mask_sh),\ - SF(OTG0_OTG_DRR_TRIGGER_WINDOW, OTG_DRR_TRIGGER_WINDOW_END_X, mask_sh),\ - SF(OTG0_OTG_DRR_V_TOTAL_CHANGE, OTG_DRR_V_TOTAL_CHANGE_LIMIT, mask_sh),\ - SF(OTG0_OTG_H_TIMING_CNTL, OTG_H_TIMING_DIV_MODE, mask_sh),\ - SF(OTG0_OTG_H_TIMING_CNTL, OTG_H_TIMING_DIV_MODE_MANUAL, mask_sh),\ - SF(OTG0_OTG_DOUBLE_BUFFER_CONTROL, OTG_DRR_TIMING_DBUF_UPDATE_MODE, mask_sh),\ - SF(OTG0_OTG_DRR_CONTROL, OTG_V_TOTAL_LAST_USED_BY_DRR, mask_sh) - -void dcn314_timing_generator_init(struct optc *optc1); - -#endif /* __DC_OPTC_DCN314_H__ */ diff --git a/drivers/gpu/drm/amd/display/dc/dcn32/Makefile b/drivers/gpu/drm/amd/display/dc/dcn32/Makefile index 3bb17dd01e4c..905b74b53092 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn32/Makefile +++ b/drivers/gpu/drm/amd/display/dc/dcn32/Makefile @@ -11,9 +11,9 @@ # Makefile for dcn32. DCN32 = dcn32_hubbub.o dcn32_init.o dcn32_dccg.o \ - dcn32_dccg.o dcn32_optc.o dcn32_mmhubbub.o dcn32_hubp.o dcn32_dpp.o \ - dcn32_dio_stream_encoder.o dcn32_dio_link_encoder.o dcn32_hpo_dp_link_encoder.o \ - dcn32_resource_helpers.o dcn32_mpc.o + dcn32_mmhubbub.o dcn32_dpp.o dcn32_hubp.o dcn32_mpc.o \ + dcn32_dio_stream_encoder.o dcn32_dio_link_encoder.o dcn32_resource_helpers.o \ + dcn32_hpo_dp_link_encoder.o AMD_DAL_DCN32 = $(addprefix $(AMDDALPATH)/dc/dcn32/,$(DCN32)) diff --git a/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_optc.c b/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_optc.c deleted file mode 100644 index a2c4db2cebdd..000000000000 --- a/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_optc.c +++ /dev/null @@ -1,357 +0,0 @@ -/* - * Copyright 2022 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 "dcn32_optc.h" - -#include "dcn30/dcn30_optc.h" -#include "dcn31/dcn31_optc.h" -#include "reg_helper.h" -#include "dc.h" -#include "dcn_calc_math.h" -#include "dc_dmub_srv.h" - -#define REG(reg)\ - optc1->tg_regs->reg - -#define CTX \ - optc1->base.ctx - -#undef FN -#define FN(reg_name, field_name) \ - optc1->tg_shift->field_name, optc1->tg_mask->field_name - -static void optc32_set_odm_combine(struct timing_generator *optc, int *opp_id, int opp_cnt, - struct dc_crtc_timing *timing) -{ - struct optc *optc1 = DCN10TG_FROM_TG(optc); - uint32_t memory_mask = 0; - int h_active = timing->h_addressable + timing->h_border_left + timing->h_border_right; - int mpcc_hactive = h_active / opp_cnt; - /* Each memory instance is 2048x(32x2) bits to support half line of 4096 */ - int odm_mem_count = (h_active + 2047) / 2048; - - /* - * display <= 4k : 2 memories + 2 pipes - * 4k < display <= 8k : 4 memories + 2 pipes - * 8k < display <= 12k : 6 memories + 4 pipes - */ - if (opp_cnt == 4) { - if (odm_mem_count <= 2) - memory_mask = 0x3; - else if (odm_mem_count <= 4) - memory_mask = 0xf; - else - memory_mask = 0x3f; - } else { - if (odm_mem_count <= 2) - memory_mask = 0x1 << (opp_id[0] * 2) | 0x1 << (opp_id[1] * 2); - else if (odm_mem_count <= 4) - memory_mask = 0x3 << (opp_id[0] * 2) | 0x3 << (opp_id[1] * 2); - else - memory_mask = 0x77; - } - - REG_SET(OPTC_MEMORY_CONFIG, 0, - OPTC_MEM_SEL, memory_mask); - - if (opp_cnt == 2) { - REG_SET_3(OPTC_DATA_SOURCE_SELECT, 0, - OPTC_NUM_OF_INPUT_SEGMENT, 1, - OPTC_SEG0_SRC_SEL, opp_id[0], - OPTC_SEG1_SRC_SEL, opp_id[1]); - } else if (opp_cnt == 4) { - REG_SET_5(OPTC_DATA_SOURCE_SELECT, 0, - OPTC_NUM_OF_INPUT_SEGMENT, 3, - OPTC_SEG0_SRC_SEL, opp_id[0], - OPTC_SEG1_SRC_SEL, opp_id[1], - OPTC_SEG2_SRC_SEL, opp_id[2], - OPTC_SEG3_SRC_SEL, opp_id[3]); - } - - REG_UPDATE(OPTC_WIDTH_CONTROL, - OPTC_SEGMENT_WIDTH, mpcc_hactive); - - REG_UPDATE(OTG_H_TIMING_CNTL, - OTG_H_TIMING_DIV_MODE, opp_cnt - 1); - optc1->opp_count = opp_cnt; -} - -void optc32_get_odm_combine_segments(struct timing_generator *tg, int *odm_combine_segments) -{ - struct optc *optc1 = DCN10TG_FROM_TG(tg); - int segments; - - REG_GET(OPTC_DATA_SOURCE_SELECT, OPTC_NUM_OF_INPUT_SEGMENT, &segments); - - switch (segments) { - case 0: - *odm_combine_segments = 1; - break; - case 1: - *odm_combine_segments = 2; - break; - case 3: - *odm_combine_segments = 4; - break; - /* 2 is reserved */ - case 2: - default: - *odm_combine_segments = -1; - } -} - -void optc32_set_h_timing_div_manual_mode(struct timing_generator *optc, bool manual_mode) -{ - struct optc *optc1 = DCN10TG_FROM_TG(optc); - - REG_UPDATE(OTG_H_TIMING_CNTL, - OTG_H_TIMING_DIV_MODE_MANUAL, manual_mode ? 1 : 0); -} -/** - * optc32_enable_crtc() - Enable CRTC - call ASIC Control Object to enable Timing generator. - * - * @optc: timing_generator instance. - * - * Return: If CRTC is enabled, return true. - */ -static bool optc32_enable_crtc(struct timing_generator *optc) -{ - struct optc *optc1 = DCN10TG_FROM_TG(optc); - - /* opp instance for OTG, 1 to 1 mapping and odm will adjust */ - REG_UPDATE(OPTC_DATA_SOURCE_SELECT, - OPTC_SEG0_SRC_SEL, optc->inst); - - /* VTG enable first is for HW workaround */ - REG_UPDATE(CONTROL, - VTG0_ENABLE, 1); - - REG_SEQ_START(); - - /* Enable CRTC */ - REG_UPDATE_2(OTG_CONTROL, - OTG_DISABLE_POINT_CNTL, 2, - OTG_MASTER_EN, 1); - - REG_SEQ_SUBMIT(); - REG_SEQ_WAIT_DONE(); - - return true; -} - -/* disable_crtc */ -static bool optc32_disable_crtc(struct timing_generator *optc) -{ - struct optc *optc1 = DCN10TG_FROM_TG(optc); - - /* disable otg request until end of the first line - * in the vertical blank region - */ - REG_UPDATE(OTG_CONTROL, - OTG_MASTER_EN, 0); - - REG_UPDATE(CONTROL, - VTG0_ENABLE, 0); - - /* CRTC disabled, so disable clock. */ - REG_WAIT(OTG_CLOCK_CONTROL, - OTG_BUSY, 0, - 1, 150000); - - return true; -} - -static void optc32_phantom_crtc_post_enable(struct timing_generator *optc) -{ - struct optc *optc1 = DCN10TG_FROM_TG(optc); - - /* Disable immediately. */ - REG_UPDATE_2(OTG_CONTROL, OTG_DISABLE_POINT_CNTL, 0, OTG_MASTER_EN, 0); - - /* CRTC disabled, so disable clock. */ - REG_WAIT(OTG_CLOCK_CONTROL, OTG_BUSY, 0, 1, 100000); -} - -static void optc32_disable_phantom_otg(struct timing_generator *optc) -{ - struct optc *optc1 = DCN10TG_FROM_TG(optc); - - REG_UPDATE(OTG_CONTROL, OTG_MASTER_EN, 0); -} - -void optc32_set_odm_bypass(struct timing_generator *optc, - const struct dc_crtc_timing *dc_crtc_timing) -{ - struct optc *optc1 = DCN10TG_FROM_TG(optc); - enum h_timing_div_mode h_div = H_TIMING_NO_DIV; - - REG_SET_5(OPTC_DATA_SOURCE_SELECT, 0, - OPTC_NUM_OF_INPUT_SEGMENT, 0, - OPTC_SEG0_SRC_SEL, optc->inst, - OPTC_SEG1_SRC_SEL, 0xf, - OPTC_SEG2_SRC_SEL, 0xf, - OPTC_SEG3_SRC_SEL, 0xf - ); - - h_div = optc1_is_two_pixels_per_containter(dc_crtc_timing); - REG_UPDATE(OTG_H_TIMING_CNTL, - OTG_H_TIMING_DIV_MODE, h_div); - - REG_SET(OPTC_MEMORY_CONFIG, 0, - OPTC_MEM_SEL, 0); - optc1->opp_count = 1; -} - -static void optc32_setup_manual_trigger(struct timing_generator *optc) -{ - struct optc *optc1 = DCN10TG_FROM_TG(optc); - struct dc *dc = optc->ctx->dc; - - if (dc->caps.dmub_caps.mclk_sw && !dc->debug.disable_fams) - dc_dmub_srv_set_drr_manual_trigger_cmd(dc, optc->inst); - else { - /* - * MIN_MASK_EN is gone and MASK is now always enabled. - * - * To get it to it work with manual trigger we need to make sure - * we program the correct bit. - */ - REG_UPDATE_4(OTG_V_TOTAL_CONTROL, - OTG_V_TOTAL_MIN_SEL, 1, - OTG_V_TOTAL_MAX_SEL, 1, - OTG_FORCE_LOCK_ON_EVENT, 0, - OTG_SET_V_TOTAL_MIN_MASK, (1 << 1)); /* TRIGA */ - - // Setup manual flow control for EOF via TRIG_A - optc->funcs->setup_manual_trigger(optc); - } -} - -static void optc32_set_drr( - struct timing_generator *optc, - const struct drr_params *params) -{ - struct optc *optc1 = DCN10TG_FROM_TG(optc); - - if (params != NULL && - params->vertical_total_max > 0 && - params->vertical_total_min > 0) { - - if (params->vertical_total_mid != 0) { - - REG_SET(OTG_V_TOTAL_MID, 0, - OTG_V_TOTAL_MID, params->vertical_total_mid - 1); - - REG_UPDATE_2(OTG_V_TOTAL_CONTROL, - OTG_VTOTAL_MID_REPLACING_MAX_EN, 1, - OTG_VTOTAL_MID_FRAME_NUM, - (uint8_t)params->vertical_total_mid_frame_num); - - } - - optc->funcs->set_vtotal_min_max(optc, params->vertical_total_min - 1, params->vertical_total_max - 1); - } - - optc32_setup_manual_trigger(optc); -} - -static struct timing_generator_funcs dcn32_tg_funcs = { - .validate_timing = optc1_validate_timing, - .program_timing = optc1_program_timing, - .setup_vertical_interrupt0 = optc1_setup_vertical_interrupt0, - .setup_vertical_interrupt1 = optc1_setup_vertical_interrupt1, - .setup_vertical_interrupt2 = optc1_setup_vertical_interrupt2, - .program_global_sync = optc1_program_global_sync, - .enable_crtc = optc32_enable_crtc, - .disable_crtc = optc32_disable_crtc, - .phantom_crtc_post_enable = optc32_phantom_crtc_post_enable, - .disable_phantom_crtc = optc32_disable_phantom_otg, - /* used by enable_timing_synchronization. Not need for FPGA */ - .is_counter_moving = optc1_is_counter_moving, - .get_position = optc1_get_position, - .get_frame_count = optc1_get_vblank_counter, - .get_scanoutpos = optc1_get_crtc_scanoutpos, - .get_otg_active_size = optc1_get_otg_active_size, - .set_early_control = optc1_set_early_control, - /* used by enable_timing_synchronization. Not need for FPGA */ - .wait_for_state = optc1_wait_for_state, - .set_blank_color = optc3_program_blank_color, - .did_triggered_reset_occur = optc1_did_triggered_reset_occur, - .triplebuffer_lock = optc3_triplebuffer_lock, - .triplebuffer_unlock = optc2_triplebuffer_unlock, - .enable_reset_trigger = optc1_enable_reset_trigger, - .enable_crtc_reset = optc1_enable_crtc_reset, - .disable_reset_trigger = optc1_disable_reset_trigger, - .lock = optc3_lock, - .unlock = optc1_unlock, - .lock_doublebuffer_enable = optc3_lock_doublebuffer_enable, - .lock_doublebuffer_disable = optc3_lock_doublebuffer_disable, - .enable_optc_clock = optc1_enable_optc_clock, - .set_drr = optc32_set_drr, - .get_last_used_drr_vtotal = optc2_get_last_used_drr_vtotal, - .set_vtotal_min_max = optc3_set_vtotal_min_max, - .set_static_screen_control = optc1_set_static_screen_control, - .program_stereo = optc1_program_stereo, - .is_stereo_left_eye = optc1_is_stereo_left_eye, - .tg_init = optc3_tg_init, - .is_tg_enabled = optc1_is_tg_enabled, - .is_optc_underflow_occurred = optc1_is_optc_underflow_occurred, - .clear_optc_underflow = optc1_clear_optc_underflow, - .setup_global_swap_lock = NULL, - .get_crc = optc1_get_crc, - .configure_crc = optc1_configure_crc, - .set_dsc_config = optc3_set_dsc_config, - .get_dsc_status = optc2_get_dsc_status, - .set_dwb_source = NULL, - .set_odm_bypass = optc32_set_odm_bypass, - .set_odm_combine = optc32_set_odm_combine, - .get_odm_combine_segments = optc32_get_odm_combine_segments, - .set_h_timing_div_manual_mode = optc32_set_h_timing_div_manual_mode, - .get_optc_source = optc2_get_optc_source, - .set_out_mux = optc3_set_out_mux, - .set_drr_trigger_window = optc3_set_drr_trigger_window, - .set_vtotal_change_limit = optc3_set_vtotal_change_limit, - .set_gsl = optc2_set_gsl, - .set_gsl_source_select = optc2_set_gsl_source_select, - .set_vtg_params = optc1_set_vtg_params, - .program_manual_trigger = optc2_program_manual_trigger, - .setup_manual_trigger = optc2_setup_manual_trigger, - .get_hw_timing = optc1_get_hw_timing, -}; - -void dcn32_timing_generator_init(struct optc *optc1) -{ - optc1->base.funcs = &dcn32_tg_funcs; - - optc1->max_h_total = optc1->tg_mask->OTG_H_TOTAL + 1; - optc1->max_v_total = optc1->tg_mask->OTG_V_TOTAL + 1; - - optc1->min_h_blank = 32; - optc1->min_v_blank = 3; - optc1->min_v_blank_interlace = 5; - optc1->min_h_sync_width = 4; - optc1->min_v_sync_width = 1; -} - diff --git a/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_optc.h b/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_optc.h deleted file mode 100644 index 8ce3b178cab0..000000000000 --- a/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_optc.h +++ /dev/null @@ -1,187 +0,0 @@ -/* - * 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_OPTC_DCN32_H__ -#define __DC_OPTC_DCN32_H__ - -#include "dcn10/dcn10_optc.h" - -#define OPTC_COMMON_MASK_SH_LIST_DCN3_2(mask_sh)\ - SF(OTG0_OTG_VSTARTUP_PARAM, VSTARTUP_START, mask_sh),\ - SF(OTG0_OTG_VUPDATE_PARAM, VUPDATE_OFFSET, mask_sh),\ - SF(OTG0_OTG_VUPDATE_PARAM, VUPDATE_WIDTH, mask_sh),\ - SF(OTG0_OTG_VREADY_PARAM, VREADY_OFFSET, mask_sh),\ - SF(OTG0_OTG_MASTER_UPDATE_LOCK, OTG_MASTER_UPDATE_LOCK, mask_sh),\ - SF(OTG0_OTG_MASTER_UPDATE_LOCK, UPDATE_LOCK_STATUS, mask_sh),\ - SF(OTG0_OTG_GLOBAL_CONTROL0, MASTER_UPDATE_LOCK_DB_START_X, mask_sh),\ - SF(OTG0_OTG_GLOBAL_CONTROL0, MASTER_UPDATE_LOCK_DB_END_X, mask_sh),\ - SF(OTG0_OTG_GLOBAL_CONTROL0, MASTER_UPDATE_LOCK_DB_EN, mask_sh),\ - SF(OTG0_OTG_GLOBAL_CONTROL1, MASTER_UPDATE_LOCK_DB_START_Y, mask_sh),\ - SF(OTG0_OTG_GLOBAL_CONTROL1, MASTER_UPDATE_LOCK_DB_END_Y, mask_sh),\ - SF(OTG0_OTG_GLOBAL_CONTROL2, OTG_MASTER_UPDATE_LOCK_SEL, mask_sh),\ - SF(OTG0_OTG_GLOBAL_CONTROL4, DIG_UPDATE_POSITION_X, mask_sh),\ - SF(OTG0_OTG_GLOBAL_CONTROL4, DIG_UPDATE_POSITION_Y, mask_sh),\ - SF(OTG0_OTG_DOUBLE_BUFFER_CONTROL, OTG_UPDATE_PENDING, mask_sh),\ - SF(OTG0_OTG_H_TOTAL, OTG_H_TOTAL, mask_sh),\ - SF(OTG0_OTG_H_BLANK_START_END, OTG_H_BLANK_START, mask_sh),\ - SF(OTG0_OTG_H_BLANK_START_END, OTG_H_BLANK_END, mask_sh),\ - SF(OTG0_OTG_H_SYNC_A, OTG_H_SYNC_A_START, mask_sh),\ - SF(OTG0_OTG_H_SYNC_A, OTG_H_SYNC_A_END, mask_sh),\ - SF(OTG0_OTG_H_SYNC_A_CNTL, OTG_H_SYNC_A_POL, mask_sh),\ - SF(OTG0_OTG_V_TOTAL, OTG_V_TOTAL, mask_sh),\ - SF(OTG0_OTG_V_BLANK_START_END, OTG_V_BLANK_START, mask_sh),\ - SF(OTG0_OTG_V_BLANK_START_END, OTG_V_BLANK_END, mask_sh),\ - SF(OTG0_OTG_V_SYNC_A, OTG_V_SYNC_A_START, mask_sh),\ - SF(OTG0_OTG_V_SYNC_A, OTG_V_SYNC_A_END, mask_sh),\ - SF(OTG0_OTG_V_SYNC_A_CNTL, OTG_V_SYNC_A_POL, mask_sh),\ - SF(OTG0_OTG_V_SYNC_A_CNTL, OTG_V_SYNC_MODE, mask_sh),\ - SF(OTG0_OTG_CONTROL, OTG_MASTER_EN, mask_sh),\ - SF(OTG0_OTG_CONTROL, OTG_START_POINT_CNTL, mask_sh),\ - SF(OTG0_OTG_CONTROL, OTG_DISABLE_POINT_CNTL, mask_sh),\ - SF(OTG0_OTG_CONTROL, OTG_FIELD_NUMBER_CNTL, mask_sh),\ - SF(OTG0_OTG_CONTROL, OTG_OUT_MUX, mask_sh),\ - SF(OTG0_OTG_STEREO_CONTROL, OTG_STEREO_EN, mask_sh),\ - SF(OTG0_OTG_STEREO_CONTROL, OTG_STEREO_SYNC_OUTPUT_LINE_NUM, mask_sh),\ - SF(OTG0_OTG_STEREO_CONTROL, OTG_STEREO_SYNC_OUTPUT_POLARITY, mask_sh),\ - SF(OTG0_OTG_STEREO_CONTROL, OTG_STEREO_EYE_FLAG_POLARITY, mask_sh),\ - SF(OTG0_OTG_STEREO_CONTROL, OTG_DISABLE_STEREOSYNC_OUTPUT_FOR_DP, mask_sh),\ - SF(OTG0_OTG_STEREO_STATUS, OTG_STEREO_CURRENT_EYE, mask_sh),\ - SF(OTG0_OTG_3D_STRUCTURE_CONTROL, OTG_3D_STRUCTURE_EN, mask_sh),\ - SF(OTG0_OTG_3D_STRUCTURE_CONTROL, OTG_3D_STRUCTURE_V_UPDATE_MODE, mask_sh),\ - SF(OTG0_OTG_3D_STRUCTURE_CONTROL, OTG_3D_STRUCTURE_STEREO_SEL_OVR, mask_sh),\ - SF(OTG0_OTG_V_TOTAL_MAX, OTG_V_TOTAL_MAX, mask_sh),\ - SF(OTG0_OTG_V_TOTAL_MIN, OTG_V_TOTAL_MIN, mask_sh),\ - SF(OTG0_OTG_V_TOTAL_CONTROL, OTG_V_TOTAL_MIN_SEL, mask_sh),\ - SF(OTG0_OTG_V_TOTAL_CONTROL, OTG_V_TOTAL_MAX_SEL, mask_sh),\ - SF(OTG0_OTG_V_TOTAL_CONTROL, OTG_FORCE_LOCK_ON_EVENT, mask_sh),\ - SF(OTG0_OTG_V_TOTAL_CONTROL, OTG_SET_V_TOTAL_MIN_MASK, mask_sh),\ - SF(OTG0_OTG_V_TOTAL_CONTROL, OTG_VTOTAL_MID_REPLACING_MIN_EN, mask_sh),\ - SF(OTG0_OTG_V_TOTAL_CONTROL, OTG_VTOTAL_MID_REPLACING_MAX_EN, mask_sh),\ - SF(OTG0_OTG_FORCE_COUNT_NOW_CNTL, OTG_FORCE_COUNT_NOW_CLEAR, mask_sh),\ - SF(OTG0_OTG_FORCE_COUNT_NOW_CNTL, OTG_FORCE_COUNT_NOW_MODE, mask_sh),\ - SF(OTG0_OTG_FORCE_COUNT_NOW_CNTL, OTG_FORCE_COUNT_NOW_OCCURRED, mask_sh),\ - SF(OTG0_OTG_TRIGA_CNTL, OTG_TRIGA_SOURCE_SELECT, mask_sh),\ - SF(OTG0_OTG_TRIGA_CNTL, OTG_TRIGA_SOURCE_PIPE_SELECT, mask_sh),\ - SF(OTG0_OTG_TRIGA_CNTL, OTG_TRIGA_RISING_EDGE_DETECT_CNTL, mask_sh),\ - SF(OTG0_OTG_TRIGA_CNTL, OTG_TRIGA_FALLING_EDGE_DETECT_CNTL, mask_sh),\ - SF(OTG0_OTG_TRIGA_CNTL, OTG_TRIGA_POLARITY_SELECT, mask_sh),\ - SF(OTG0_OTG_TRIGA_CNTL, OTG_TRIGA_FREQUENCY_SELECT, mask_sh),\ - SF(OTG0_OTG_TRIGA_CNTL, OTG_TRIGA_DELAY, mask_sh),\ - SF(OTG0_OTG_TRIGA_CNTL, OTG_TRIGA_CLEAR, mask_sh),\ - SF(OTG0_OTG_STATIC_SCREEN_CONTROL, OTG_STATIC_SCREEN_EVENT_MASK, mask_sh),\ - SF(OTG0_OTG_STATIC_SCREEN_CONTROL, OTG_STATIC_SCREEN_FRAME_COUNT, mask_sh),\ - SF(OTG0_OTG_STATUS_FRAME_COUNT, OTG_FRAME_COUNT, mask_sh),\ - SF(OTG0_OTG_STATUS, OTG_V_BLANK, mask_sh),\ - SF(OTG0_OTG_STATUS, OTG_V_ACTIVE_DISP, mask_sh),\ - SF(OTG0_OTG_STATUS_POSITION, OTG_HORZ_COUNT, mask_sh),\ - SF(OTG0_OTG_STATUS_POSITION, OTG_VERT_COUNT, mask_sh),\ - SF(OTG0_OTG_NOM_VERT_POSITION, OTG_VERT_COUNT_NOM, mask_sh),\ - SF(OTG0_OTG_M_CONST_DTO0, OTG_M_CONST_DTO_PHASE, mask_sh),\ - SF(OTG0_OTG_M_CONST_DTO1, OTG_M_CONST_DTO_MODULO, mask_sh),\ - SF(OTG0_OTG_CLOCK_CONTROL, OTG_BUSY, mask_sh),\ - SF(OTG0_OTG_CLOCK_CONTROL, OTG_CLOCK_EN, mask_sh),\ - SF(OTG0_OTG_CLOCK_CONTROL, OTG_CLOCK_ON, mask_sh),\ - SF(OTG0_OTG_CLOCK_CONTROL, OTG_CLOCK_GATE_DIS, mask_sh),\ - SF(OTG0_OTG_VERTICAL_INTERRUPT0_CONTROL, OTG_VERTICAL_INTERRUPT0_INT_ENABLE, mask_sh),\ - SF(OTG0_OTG_VERTICAL_INTERRUPT0_POSITION, OTG_VERTICAL_INTERRUPT0_LINE_START, mask_sh),\ - SF(OTG0_OTG_VERTICAL_INTERRUPT0_POSITION, OTG_VERTICAL_INTERRUPT0_LINE_END, mask_sh),\ - SF(OTG0_OTG_VERTICAL_INTERRUPT1_CONTROL, OTG_VERTICAL_INTERRUPT1_INT_ENABLE, mask_sh),\ - SF(OTG0_OTG_VERTICAL_INTERRUPT1_POSITION, OTG_VERTICAL_INTERRUPT1_LINE_START, mask_sh),\ - SF(OTG0_OTG_VERTICAL_INTERRUPT2_CONTROL, OTG_VERTICAL_INTERRUPT2_INT_ENABLE, mask_sh),\ - SF(OTG0_OTG_VERTICAL_INTERRUPT2_POSITION, OTG_VERTICAL_INTERRUPT2_LINE_START, mask_sh),\ - SF(ODM0_OPTC_INPUT_CLOCK_CONTROL, OPTC_INPUT_CLK_EN, mask_sh),\ - SF(ODM0_OPTC_INPUT_CLOCK_CONTROL, OPTC_INPUT_CLK_ON, mask_sh),\ - SF(ODM0_OPTC_INPUT_CLOCK_CONTROL, OPTC_INPUT_CLK_GATE_DIS, mask_sh),\ - SF(ODM0_OPTC_INPUT_GLOBAL_CONTROL, OPTC_UNDERFLOW_OCCURRED_STATUS, mask_sh),\ - SF(ODM0_OPTC_INPUT_GLOBAL_CONTROL, OPTC_UNDERFLOW_CLEAR, mask_sh),\ - SF(VTG0_CONTROL, VTG0_ENABLE, mask_sh),\ - SF(VTG0_CONTROL, VTG0_FP2, mask_sh),\ - SF(VTG0_CONTROL, VTG0_VCOUNT_INIT, mask_sh),\ - SF(OTG0_OTG_VERT_SYNC_CONTROL, OTG_FORCE_VSYNC_NEXT_LINE_OCCURRED, mask_sh),\ - SF(OTG0_OTG_VERT_SYNC_CONTROL, OTG_FORCE_VSYNC_NEXT_LINE_CLEAR, mask_sh),\ - SF(OTG0_OTG_VERT_SYNC_CONTROL, OTG_AUTO_FORCE_VSYNC_MODE, mask_sh),\ - SF(OTG0_OTG_GSL_CONTROL, OTG_GSL0_EN, mask_sh),\ - SF(OTG0_OTG_GSL_CONTROL, OTG_GSL1_EN, mask_sh),\ - SF(OTG0_OTG_GSL_CONTROL, OTG_GSL2_EN, mask_sh),\ - SF(OTG0_OTG_GSL_CONTROL, OTG_GSL_MASTER_EN, mask_sh),\ - SF(OTG0_OTG_GSL_CONTROL, OTG_GSL_FORCE_DELAY, mask_sh),\ - SF(OTG0_OTG_GSL_CONTROL, OTG_GSL_CHECK_ALL_FIELDS, mask_sh),\ - SF(OTG0_OTG_CRC_CNTL, OTG_CRC_CONT_EN, mask_sh),\ - SF(OTG0_OTG_CRC_CNTL, OTG_CRC0_SELECT, mask_sh),\ - SF(OTG0_OTG_CRC_CNTL, OTG_CRC_EN, mask_sh),\ - SF(OTG0_OTG_CRC0_DATA_RG, CRC0_R_CR, mask_sh),\ - SF(OTG0_OTG_CRC0_DATA_RG, CRC0_G_Y, mask_sh),\ - SF(OTG0_OTG_CRC0_DATA_B, CRC0_B_CB, mask_sh),\ - SF(OTG0_OTG_CRC0_WINDOWA_X_CONTROL, OTG_CRC0_WINDOWA_X_START, mask_sh),\ - SF(OTG0_OTG_CRC0_WINDOWA_X_CONTROL, OTG_CRC0_WINDOWA_X_END, mask_sh),\ - SF(OTG0_OTG_CRC0_WINDOWA_Y_CONTROL, OTG_CRC0_WINDOWA_Y_START, mask_sh),\ - SF(OTG0_OTG_CRC0_WINDOWA_Y_CONTROL, OTG_CRC0_WINDOWA_Y_END, mask_sh),\ - SF(OTG0_OTG_CRC0_WINDOWB_X_CONTROL, OTG_CRC0_WINDOWB_X_START, mask_sh),\ - SF(OTG0_OTG_CRC0_WINDOWB_X_CONTROL, OTG_CRC0_WINDOWB_X_END, mask_sh),\ - SF(OTG0_OTG_CRC0_WINDOWB_Y_CONTROL, OTG_CRC0_WINDOWB_Y_START, mask_sh),\ - SF(OTG0_OTG_CRC0_WINDOWB_Y_CONTROL, OTG_CRC0_WINDOWB_Y_END, mask_sh),\ - SF(OTG0_OTG_TRIGA_MANUAL_TRIG, OTG_TRIGA_MANUAL_TRIG, mask_sh),\ - SF(GSL_SOURCE_SELECT, GSL0_READY_SOURCE_SEL, mask_sh),\ - SF(GSL_SOURCE_SELECT, GSL1_READY_SOURCE_SEL, mask_sh),\ - SF(GSL_SOURCE_SELECT, GSL2_READY_SOURCE_SEL, mask_sh),\ - SF(OTG0_OTG_GLOBAL_CONTROL2, MANUAL_FLOW_CONTROL_SEL, mask_sh),\ - SF(OTG0_OTG_GLOBAL_CONTROL2, GLOBAL_UPDATE_LOCK_EN, mask_sh),\ - SF(OTG0_OTG_GSL_WINDOW_X, OTG_GSL_WINDOW_START_X, mask_sh),\ - SF(OTG0_OTG_GSL_WINDOW_X, OTG_GSL_WINDOW_END_X, mask_sh), \ - SF(OTG0_OTG_GSL_WINDOW_Y, OTG_GSL_WINDOW_START_Y, mask_sh),\ - SF(OTG0_OTG_GSL_WINDOW_Y, OTG_GSL_WINDOW_END_Y, mask_sh),\ - SF(OTG0_OTG_VUPDATE_KEEPOUT, OTG_MASTER_UPDATE_LOCK_VUPDATE_KEEPOUT_EN, mask_sh), \ - SF(OTG0_OTG_VUPDATE_KEEPOUT, MASTER_UPDATE_LOCK_VUPDATE_KEEPOUT_START_OFFSET, mask_sh), \ - SF(OTG0_OTG_VUPDATE_KEEPOUT, MASTER_UPDATE_LOCK_VUPDATE_KEEPOUT_END_OFFSET, mask_sh), \ - SF(OTG0_OTG_GSL_CONTROL, OTG_GSL_MASTER_MODE, mask_sh), \ - SF(OTG0_OTG_GSL_CONTROL, OTG_MASTER_UPDATE_LOCK_GSL_EN, mask_sh), \ - SF(OTG0_OTG_DSC_START_POSITION, OTG_DSC_START_POSITION_X, mask_sh), \ - SF(OTG0_OTG_DSC_START_POSITION, OTG_DSC_START_POSITION_LINE_NUM, mask_sh),\ - SF(ODM0_OPTC_DATA_SOURCE_SELECT, OPTC_SEG0_SRC_SEL, mask_sh),\ - SF(ODM0_OPTC_DATA_SOURCE_SELECT, OPTC_SEG1_SRC_SEL, mask_sh),\ - SF(ODM0_OPTC_DATA_SOURCE_SELECT, OPTC_SEG2_SRC_SEL, mask_sh),\ - SF(ODM0_OPTC_DATA_SOURCE_SELECT, OPTC_SEG3_SRC_SEL, mask_sh),\ - SF(ODM0_OPTC_DATA_SOURCE_SELECT, OPTC_NUM_OF_INPUT_SEGMENT, mask_sh),\ - SF(ODM0_OPTC_MEMORY_CONFIG, OPTC_MEM_SEL, mask_sh),\ - SF(ODM0_OPTC_DATA_FORMAT_CONTROL, OPTC_DATA_FORMAT, mask_sh),\ - SF(ODM0_OPTC_DATA_FORMAT_CONTROL, OPTC_DSC_MODE, mask_sh),\ - SF(ODM0_OPTC_BYTES_PER_PIXEL, OPTC_DSC_BYTES_PER_PIXEL, mask_sh),\ - SF(ODM0_OPTC_WIDTH_CONTROL, OPTC_DSC_SLICE_WIDTH, mask_sh),\ - SF(ODM0_OPTC_WIDTH_CONTROL, OPTC_SEGMENT_WIDTH, mask_sh),\ - SF(OTG0_OTG_DRR_TRIGGER_WINDOW, OTG_DRR_TRIGGER_WINDOW_START_X, mask_sh),\ - SF(OTG0_OTG_DRR_TRIGGER_WINDOW, OTG_DRR_TRIGGER_WINDOW_END_X, mask_sh),\ - SF(OTG0_OTG_DRR_V_TOTAL_CHANGE, OTG_DRR_V_TOTAL_CHANGE_LIMIT, mask_sh),\ - SF(OTG0_OTG_H_TIMING_CNTL, OTG_H_TIMING_DIV_MODE, mask_sh),\ - SF(OTG0_OTG_H_TIMING_CNTL, OTG_H_TIMING_DIV_MODE_MANUAL, mask_sh),\ - SF(OTG0_OTG_DOUBLE_BUFFER_CONTROL, OTG_DRR_TIMING_DBUF_UPDATE_MODE, mask_sh),\ - SF(OTG0_OTG_DRR_CONTROL, OTG_V_TOTAL_LAST_USED_BY_DRR, mask_sh) - -void dcn32_timing_generator_init(struct optc *optc1); -void optc32_set_h_timing_div_manual_mode(struct timing_generator *optc, bool manual_mode); -void optc32_get_odm_combine_segments(struct timing_generator *tg, int *odm_combine_segments); -void optc32_set_odm_bypass(struct timing_generator *optc, - const struct dc_crtc_timing *dc_crtc_timing); - -#endif /* __DC_OPTC_DCN32_H__ */ diff --git a/drivers/gpu/drm/amd/display/dc/dcn35/Makefile b/drivers/gpu/drm/amd/display/dc/dcn35/Makefile index 85a307babab9..fa7ec82ae5f5 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn35/Makefile +++ b/drivers/gpu/drm/amd/display/dc/dcn35/Makefile @@ -11,7 +11,7 @@ # Makefile for DCN35. DCN35 = dcn35_init.o dcn35_dio_stream_encoder.o \ - dcn35_dio_link_encoder.o dcn35_dccg.o dcn35_optc.o \ + dcn35_dio_link_encoder.o dcn35_dccg.o \ dcn35_hubp.o dcn35_hubbub.o \ dcn35_mmhubbub.o dcn35_opp.o dcn35_dpp.o dcn35_pg_cntl.o dcn35_dwb.o diff --git a/drivers/gpu/drm/amd/display/dc/dcn35/dcn35_optc.c b/drivers/gpu/drm/amd/display/dc/dcn35/dcn35_optc.c deleted file mode 100644 index a4a39f1638cf..000000000000 --- a/drivers/gpu/drm/amd/display/dc/dcn35/dcn35_optc.c +++ /dev/null @@ -1,290 +0,0 @@ -/* SPDX-License-Identifier: MIT */ -/* - * Copyright 2023 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 "dcn35_optc.h" - -#include "dcn30/dcn30_optc.h" -#include "dcn31/dcn31_optc.h" -#include "dcn32/dcn32_optc.h" -#include "reg_helper.h" -#include "dc.h" -#include "dcn_calc_math.h" - -#define REG(reg)\ - optc1->tg_regs->reg - -#define CTX \ - optc1->base.ctx - -#undef FN -#define FN(reg_name, field_name) \ - optc1->tg_shift->field_name, optc1->tg_mask->field_name - -/** - * optc35_set_odm_combine() - Enable CRTC - call ASIC Control Object to enable Timing generator. - * - * @optc: Output Pipe Timing Combine instance reference. - * @opp_id: Output Plane Processor instance ID. - * @opp_cnt: Output Plane Processor count. - * @timing: Timing parameters used to configure DCN blocks. - * - * Return: void. - */ -static void optc35_set_odm_combine(struct timing_generator *optc, int *opp_id, int opp_cnt, - struct dc_crtc_timing *timing) -{ - struct optc *optc1 = DCN10TG_FROM_TG(optc); - uint32_t memory_mask = 0; - int h_active = timing->h_addressable + timing->h_border_left + timing->h_border_right; - int mpcc_hactive = h_active / opp_cnt; - /* Each memory instance is 2048x(314x2) bits to support half line of 4096 */ - int odm_mem_count = (h_active + 2047) / 2048; - - /* - * display <= 4k : 2 memories + 2 pipes - * 4k < display <= 8k : 4 memories + 2 pipes - * 8k < display <= 12k : 6 memories + 4 pipes - */ - if (opp_cnt == 4) { - if (odm_mem_count <= 2) - memory_mask = 0x3; - else if (odm_mem_count <= 4) - memory_mask = 0xf; - else - memory_mask = 0x3f; - } else { - if (odm_mem_count <= 2) - memory_mask = 0x1 << (opp_id[0] * 2) | 0x1 << (opp_id[1] * 2); - else if (odm_mem_count <= 4) - memory_mask = 0x3 << (opp_id[0] * 2) | 0x3 << (opp_id[1] * 2); - else - memory_mask = 0x77; - } - - REG_SET(OPTC_MEMORY_CONFIG, 0, - OPTC_MEM_SEL, memory_mask); - - if (opp_cnt == 2) { - REG_SET_3(OPTC_DATA_SOURCE_SELECT, 0, - OPTC_NUM_OF_INPUT_SEGMENT, 1, - OPTC_SEG0_SRC_SEL, opp_id[0], - OPTC_SEG1_SRC_SEL, opp_id[1]); - } else if (opp_cnt == 4) { - REG_SET_5(OPTC_DATA_SOURCE_SELECT, 0, - OPTC_NUM_OF_INPUT_SEGMENT, 3, - OPTC_SEG0_SRC_SEL, opp_id[0], - OPTC_SEG1_SRC_SEL, opp_id[1], - OPTC_SEG2_SRC_SEL, opp_id[2], - OPTC_SEG3_SRC_SEL, opp_id[3]); - } - - REG_UPDATE(OPTC_WIDTH_CONTROL, - OPTC_SEGMENT_WIDTH, mpcc_hactive); - - REG_UPDATE(OTG_H_TIMING_CNTL, OTG_H_TIMING_DIV_MODE, opp_cnt - 1); - optc1->opp_count = opp_cnt; -} - -static bool optc35_enable_crtc(struct timing_generator *optc) -{ - struct optc *optc1 = DCN10TG_FROM_TG(optc); - - /* opp instance for OTG, 1 to 1 mapping and odm will adjust */ - REG_UPDATE(OPTC_DATA_SOURCE_SELECT, - OPTC_SEG0_SRC_SEL, optc->inst); - - /* VTG enable first is for HW workaround */ - REG_UPDATE(CONTROL, - VTG0_ENABLE, 1); - - REG_SEQ_START(); - - /* Enable CRTC */ - REG_UPDATE_2(OTG_CONTROL, - OTG_DISABLE_POINT_CNTL, 2, - OTG_MASTER_EN, 1); - - REG_SEQ_SUBMIT(); - REG_SEQ_WAIT_DONE(); - - return true; -} - -/* disable_crtc */ -static bool optc35_disable_crtc(struct timing_generator *optc) -{ - struct optc *optc1 = DCN10TG_FROM_TG(optc); - - /* disable otg request until end of the first line - * in the vertical blank region - */ - REG_UPDATE(OTG_CONTROL, - OTG_MASTER_EN, 0); - - REG_UPDATE(CONTROL, - VTG0_ENABLE, 0); - - /* CRTC disabled, so disable clock. */ - REG_WAIT(OTG_CLOCK_CONTROL, - OTG_BUSY, 0, - 1, 100000); - optc1_clear_optc_underflow(optc); - - return true; -} - -static void optc35_phantom_crtc_post_enable(struct timing_generator *optc) -{ - struct optc *optc1 = DCN10TG_FROM_TG(optc); - - /* Disable immediately. */ - REG_UPDATE_2(OTG_CONTROL, OTG_DISABLE_POINT_CNTL, 0, OTG_MASTER_EN, 0); - - /* CRTC disabled, so disable clock. */ - REG_WAIT(OTG_CLOCK_CONTROL, OTG_BUSY, 0, 1, 100000); -} - -static bool optc35_configure_crc(struct timing_generator *optc, - const struct crc_params *params) -{ - struct optc *optc1 = DCN10TG_FROM_TG(optc); - - if (!optc1_is_tg_enabled(optc)) - return false; - REG_WRITE(OTG_CRC_CNTL, 0); - if (!params->enable) - return true; - REG_UPDATE_2(OTG_CRC0_WINDOWA_X_CONTROL, - OTG_CRC0_WINDOWA_X_START, params->windowa_x_start, - OTG_CRC0_WINDOWA_X_END, params->windowa_x_end); - REG_UPDATE_2(OTG_CRC0_WINDOWA_Y_CONTROL, - OTG_CRC0_WINDOWA_Y_START, params->windowa_y_start, - OTG_CRC0_WINDOWA_Y_END, params->windowa_y_end); - REG_UPDATE_2(OTG_CRC0_WINDOWB_X_CONTROL, - OTG_CRC0_WINDOWB_X_START, params->windowb_x_start, - OTG_CRC0_WINDOWB_X_END, params->windowb_x_end); - REG_UPDATE_2(OTG_CRC0_WINDOWB_Y_CONTROL, - OTG_CRC0_WINDOWB_Y_START, params->windowb_y_start, - OTG_CRC0_WINDOWB_Y_END, params->windowb_y_end); - if (optc1->base.ctx->dc->debug.otg_crc_db && optc1->tg_mask->OTG_CRC_WINDOW_DB_EN != 0) { - REG_UPDATE_4(OTG_CRC_CNTL, - OTG_CRC_CONT_EN, params->continuous_mode ? 1 : 0, - OTG_CRC0_SELECT, params->selection, - OTG_CRC_EN, 1, - OTG_CRC_WINDOW_DB_EN, 1); - } else - REG_UPDATE_3(OTG_CRC_CNTL, - OTG_CRC_CONT_EN, params->continuous_mode ? 1 : 0, - OTG_CRC0_SELECT, params->selection, - OTG_CRC_EN, 1); - return true; -} - -static struct timing_generator_funcs dcn35_tg_funcs = { - .validate_timing = optc1_validate_timing, - .program_timing = optc1_program_timing, - .setup_vertical_interrupt0 = optc1_setup_vertical_interrupt0, - .setup_vertical_interrupt1 = optc1_setup_vertical_interrupt1, - .setup_vertical_interrupt2 = optc1_setup_vertical_interrupt2, - .program_global_sync = optc1_program_global_sync, - .enable_crtc = optc35_enable_crtc, - .disable_crtc = optc35_disable_crtc, - .immediate_disable_crtc = optc31_immediate_disable_crtc, - .phantom_crtc_post_enable = optc35_phantom_crtc_post_enable, - /* used by enable_timing_synchronization. Not need for FPGA */ - .is_counter_moving = optc1_is_counter_moving, - .get_position = optc1_get_position, - .get_frame_count = optc1_get_vblank_counter, - .get_scanoutpos = optc1_get_crtc_scanoutpos, - .get_otg_active_size = optc1_get_otg_active_size, - .set_early_control = optc1_set_early_control, - /* used by enable_timing_synchronization. Not need for FPGA */ - .wait_for_state = optc1_wait_for_state, - .set_blank_color = optc3_program_blank_color, - .did_triggered_reset_occur = optc1_did_triggered_reset_occur, - .triplebuffer_lock = optc3_triplebuffer_lock, - .triplebuffer_unlock = optc2_triplebuffer_unlock, - .enable_reset_trigger = optc1_enable_reset_trigger, - .enable_crtc_reset = optc1_enable_crtc_reset, - .disable_reset_trigger = optc1_disable_reset_trigger, - .lock = optc3_lock, - .unlock = optc1_unlock, - .lock_doublebuffer_enable = optc3_lock_doublebuffer_enable, - .lock_doublebuffer_disable = optc3_lock_doublebuffer_disable, - .enable_optc_clock = optc1_enable_optc_clock, - .set_drr = optc31_set_drr, - .get_last_used_drr_vtotal = optc2_get_last_used_drr_vtotal, - .set_vtotal_min_max = optc1_set_vtotal_min_max, - .set_static_screen_control = optc1_set_static_screen_control, - .program_stereo = optc1_program_stereo, - .is_stereo_left_eye = optc1_is_stereo_left_eye, - .tg_init = optc3_tg_init, - .is_tg_enabled = optc1_is_tg_enabled, - .is_optc_underflow_occurred = optc1_is_optc_underflow_occurred, - .clear_optc_underflow = optc1_clear_optc_underflow, - .setup_global_swap_lock = NULL, - .get_crc = optc1_get_crc, - .configure_crc = optc35_configure_crc, - .set_dsc_config = optc3_set_dsc_config, - .get_dsc_status = optc2_get_dsc_status, - .set_dwb_source = NULL, - .set_odm_bypass = optc32_set_odm_bypass, - .set_odm_combine = optc35_set_odm_combine, - .get_optc_source = optc2_get_optc_source, - .set_h_timing_div_manual_mode = optc32_set_h_timing_div_manual_mode, - .set_out_mux = optc3_set_out_mux, - .set_drr_trigger_window = optc3_set_drr_trigger_window, - .set_vtotal_change_limit = optc3_set_vtotal_change_limit, - .set_gsl = optc2_set_gsl, - .set_gsl_source_select = optc2_set_gsl_source_select, - .set_vtg_params = optc1_set_vtg_params, - .program_manual_trigger = optc2_program_manual_trigger, - .setup_manual_trigger = optc2_setup_manual_trigger, - .get_hw_timing = optc1_get_hw_timing, - .init_odm = optc3_init_odm, -}; - -void dcn35_timing_generator_init(struct optc *optc1) -{ - optc1->base.funcs = &dcn35_tg_funcs; - - optc1->max_h_total = optc1->tg_mask->OTG_H_TOTAL + 1; - optc1->max_v_total = optc1->tg_mask->OTG_V_TOTAL + 1; - - optc1->min_h_blank = 32; - optc1->min_v_blank = 3; - optc1->min_v_blank_interlace = 5; - optc1->min_h_sync_width = 4; - optc1->min_v_sync_width = 1; - - dcn35_timing_generator_set_fgcg( - optc1, CTX->dc->debug.enable_fine_grain_clock_gating.bits.optc); -} - -void dcn35_timing_generator_set_fgcg(struct optc *optc1, bool enable) -{ - REG_UPDATE(OPTC_CLOCK_CONTROL, OPTC_FGCG_REP_DIS, !enable); -} diff --git a/drivers/gpu/drm/amd/display/dc/dcn35/dcn35_optc.h b/drivers/gpu/drm/amd/display/dc/dcn35/dcn35_optc.h deleted file mode 100644 index 1f422e4c468f..000000000000 --- a/drivers/gpu/drm/amd/display/dc/dcn35/dcn35_optc.h +++ /dev/null @@ -1,74 +0,0 @@ -/* SPDX-License-Identifier: MIT */ -/* - * Copyright 2023 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_OPTC_DCN35_H__ -#define __DC_OPTC_DCN35_H__ - -#include "dcn10/dcn10_optc.h" -#include "dcn32/dcn32_optc.h" -#define OPTC_COMMON_MASK_SH_LIST_DCN3_5(mask_sh)\ - OPTC_COMMON_MASK_SH_LIST_DCN3_2(mask_sh),\ - SF(OTG0_OTG_CRC_CNTL, OTG_CRC_WINDOW_DB_EN, mask_sh),\ - SF(OTG0_OTG_CRC1_DATA_RG, CRC1_R_CR, mask_sh),\ - SF(OTG0_OTG_CRC1_DATA_RG, CRC1_G_Y, mask_sh),\ - SF(OTG0_OTG_CRC1_DATA_B, CRC1_B_CB, mask_sh),\ - SF(OTG0_OTG_CRC2_DATA_RG, CRC2_R_CR, mask_sh),\ - SF(OTG0_OTG_CRC2_DATA_RG, CRC2_G_Y, mask_sh),\ - SF(OTG0_OTG_CRC2_DATA_B, CRC2_B_CB, mask_sh),\ - SF(OTG0_OTG_CRC3_DATA_RG, CRC3_R_CR, mask_sh),\ - SF(OTG0_OTG_CRC3_DATA_RG, CRC3_G_Y, mask_sh),\ - SF(OTG0_OTG_CRC3_DATA_B, CRC3_B_CB, mask_sh),\ - SF(OTG0_OTG_CRC1_WINDOWA_X_CONTROL, OTG_CRC1_WINDOWA_X_START, mask_sh),\ - SF(OTG0_OTG_CRC1_WINDOWA_X_CONTROL, OTG_CRC1_WINDOWA_X_END, mask_sh),\ - SF(OTG0_OTG_CRC1_WINDOWA_Y_CONTROL, OTG_CRC1_WINDOWA_Y_START, mask_sh),\ - SF(OTG0_OTG_CRC1_WINDOWA_Y_CONTROL, OTG_CRC1_WINDOWA_Y_END, mask_sh),\ - SF(OTG0_OTG_CRC1_WINDOWB_X_CONTROL, OTG_CRC1_WINDOWB_X_START, mask_sh),\ - SF(OTG0_OTG_CRC1_WINDOWB_X_CONTROL, OTG_CRC1_WINDOWB_X_END, mask_sh),\ - SF(OTG0_OTG_CRC1_WINDOWB_Y_CONTROL, OTG_CRC1_WINDOWB_Y_START, mask_sh),\ - SF(OTG0_OTG_CRC1_WINDOWB_Y_CONTROL, OTG_CRC1_WINDOWB_Y_END, mask_sh),\ - SF(OTG0_OTG_CRC0_WINDOWA_X_CONTROL_READBACK, OTG_CRC0_WINDOWA_X_START_READBACK, mask_sh),\ - SF(OTG0_OTG_CRC0_WINDOWA_X_CONTROL_READBACK, OTG_CRC0_WINDOWA_X_END_READBACK, mask_sh),\ - SF(OTG0_OTG_CRC0_WINDOWA_Y_CONTROL_READBACK, OTG_CRC0_WINDOWA_Y_START_READBACK, mask_sh),\ - SF(OTG0_OTG_CRC0_WINDOWA_Y_CONTROL_READBACK, OTG_CRC0_WINDOWA_Y_END_READBACK, mask_sh),\ - SF(OTG0_OTG_CRC0_WINDOWB_X_CONTROL_READBACK, OTG_CRC0_WINDOWB_X_START_READBACK, mask_sh),\ - SF(OTG0_OTG_CRC0_WINDOWB_X_CONTROL_READBACK, OTG_CRC0_WINDOWB_X_END_READBACK, mask_sh),\ - SF(OTG0_OTG_CRC0_WINDOWB_Y_CONTROL_READBACK, OTG_CRC0_WINDOWB_Y_START_READBACK, mask_sh),\ - SF(OTG0_OTG_CRC0_WINDOWB_Y_CONTROL_READBACK, OTG_CRC0_WINDOWB_Y_END_READBACK, mask_sh),\ - SF(OTG0_OTG_CRC1_WINDOWA_X_CONTROL_READBACK, OTG_CRC1_WINDOWA_X_START_READBACK, mask_sh),\ - SF(OTG0_OTG_CRC1_WINDOWA_X_CONTROL_READBACK, OTG_CRC1_WINDOWA_X_END_READBACK, mask_sh),\ - SF(OTG0_OTG_CRC1_WINDOWA_Y_CONTROL_READBACK, OTG_CRC1_WINDOWA_Y_START_READBACK, mask_sh),\ - SF(OTG0_OTG_CRC1_WINDOWA_Y_CONTROL_READBACK, OTG_CRC1_WINDOWA_Y_END_READBACK, mask_sh),\ - SF(OTG0_OTG_CRC1_WINDOWB_X_CONTROL_READBACK, OTG_CRC1_WINDOWB_X_START_READBACK, mask_sh),\ - SF(OTG0_OTG_CRC1_WINDOWB_X_CONTROL_READBACK, OTG_CRC1_WINDOWB_X_END_READBACK, mask_sh),\ - SF(OTG0_OTG_CRC1_WINDOWB_Y_CONTROL_READBACK, OTG_CRC1_WINDOWB_Y_START_READBACK, mask_sh),\ - SF(OTG0_OTG_CRC1_WINDOWB_Y_CONTROL_READBACK, OTG_CRC1_WINDOWB_Y_END_READBACK, mask_sh),\ - SF(OPTC_CLOCK_CONTROL, OPTC_FGCG_REP_DIS, mask_sh) - -void dcn35_timing_generator_init(struct optc *optc1); - -void dcn35_timing_generator_set_fgcg(struct optc *optc1, bool enable); - -#endif /* __DC_OPTC_DCN35_H__ */ diff --git a/drivers/gpu/drm/amd/display/dc/optc/Makefile b/drivers/gpu/drm/amd/display/dc/optc/Makefile new file mode 100644 index 000000000000..bb213335fb9f --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/optc/Makefile @@ -0,0 +1,108 @@ + +# Copyright 2022 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. +# +# Makefile for the 'optc' sub-component of DAL. +# + + +ifdef CONFIG_DRM_AMD_DC_FP +############################################################################### +# DCN +############################################################################### + +OPTC_DCN10 = dcn10_optc.o + +AMD_DAL_OPTC_DCN10 = $(addprefix $(AMDDALPATH)/dc/optc/dcn10/,$(OPTC_DCN10)) + +AMD_DISPLAY_FILES += $(AMD_DAL_OPTC_DCN10) + +############################################################################### + +OPTC_DCN20 = dcn20_optc.o + +AMD_DAL_OPTC_DCN20 = $(addprefix $(AMDDALPATH)/dc/optc/dcn20/,$(OPTC_DCN20)) + +AMD_DISPLAY_FILES += $(AMD_DAL_OPTC_DCN20) + +############################################################################### + +OPTC_DCN201 = dcn201_optc.o + +AMD_DAL_OPTC_DCN201 = $(addprefix $(AMDDALPATH)/dc/optc/dcn201/,$(OPTC_DCN201)) + +AMD_DISPLAY_FILES += $(AMD_DAL_OPTC_DCN201) + +############################################################################### + +############################################################################### + +############################################################################### + +OPTC_DCN30 = dcn30_optc.o + +AMD_DAL_OPTC_DCN30 = $(addprefix $(AMDDALPATH)/dc/optc/dcn30/,$(OPTC_DCN30)) + +AMD_DISPLAY_FILES += $(AMD_DAL_OPTC_DCN30) + +############################################################################### + +OPTC_DCN301 = dcn301_optc.o + +AMD_DAL_OPTC_DCN301 = $(addprefix $(AMDDALPATH)/dc/optc/dcn301/,$(OPTC_DCN301)) + +AMD_DISPLAY_FILES += $(AMD_DAL_OPTC_DCN301) + +############################################################################### + +OPTC_DCN31 = dcn31_optc.o + +AMD_DAL_OPTC_DCN31 = $(addprefix $(AMDDALPATH)/dc/optc/dcn31/,$(OPTC_DCN31)) + +AMD_DISPLAY_FILES += $(AMD_DAL_OPTC_DCN31) + +############################################################################### + +OPTC_DCN314 = dcn314_optc.o + +AMD_DAL_OPTC_DCN314 = $(addprefix $(AMDDALPATH)/dc/optc/dcn314/,$(OPTC_DCN314)) + +AMD_DISPLAY_FILES += $(AMD_DAL_OPTC_DCN314) + +############################################################################### + +OPTC_DCN32 = dcn32_optc.o + +AMD_DAL_OPTC_DCN32 = $(addprefix $(AMDDALPATH)/dc/optc/dcn32/,$(OPTC_DCN32)) + +AMD_DISPLAY_FILES += $(AMD_DAL_OPTC_DCN32) + +############################################################################### + +OPTC_DCN35 = dcn35_optc.o + +AMD_DAL_OPTC_DCN35 = $(addprefix $(AMDDALPATH)/dc/optc/dcn35/,$(OPTC_DCN35)) + +AMD_DISPLAY_FILES += $(AMD_DAL_OPTC_DCN35) + +############################################################################### + +############################################################################### +endif diff --git a/drivers/gpu/drm/amd/display/dc/optc/dcn10/dcn10_optc.c b/drivers/gpu/drm/amd/display/dc/optc/dcn10/dcn10_optc.c new file mode 100644 index 000000000000..0e8f4f36c87c --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/optc/dcn10/dcn10_optc.c @@ -0,0 +1,1621 @@ +/* + * Copyright 2012-15 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 "reg_helper.h" +#include "dcn10_optc.h" +#include "dc.h" +#include "dc_trace.h" + +#define REG(reg)\ + optc1->tg_regs->reg + +#define CTX \ + optc1->base.ctx + +#undef FN +#define FN(reg_name, field_name) \ + optc1->tg_shift->field_name, optc1->tg_mask->field_name + +#define STATIC_SCREEN_EVENT_MASK_RANGETIMING_DOUBLE_BUFFER_UPDATE_EN 0x100 + +/** + * apply_front_porch_workaround() - This is a workaround for a bug that has + * existed since R5xx and has not been fixed + * keep Front porch at minimum 2 for Interlaced + * mode or 1 for progressive. + * + * @timing: Timing parameters used to configure DCN blocks. + */ +static void apply_front_porch_workaround(struct dc_crtc_timing *timing) +{ + if (timing->flags.INTERLACE == 1) { + if (timing->v_front_porch < 2) + timing->v_front_porch = 2; + } else { + if (timing->v_front_porch < 1) + timing->v_front_porch = 1; + } +} + +void optc1_program_global_sync( + struct timing_generator *optc, + int vready_offset, + int vstartup_start, + int vupdate_offset, + int vupdate_width) +{ + struct optc *optc1 = DCN10TG_FROM_TG(optc); + + optc1->vready_offset = vready_offset; + optc1->vstartup_start = vstartup_start; + optc1->vupdate_offset = vupdate_offset; + optc1->vupdate_width = vupdate_width; + + if (optc1->vstartup_start == 0) { + BREAK_TO_DEBUGGER(); + return; + } + + REG_SET(OTG_VSTARTUP_PARAM, 0, + VSTARTUP_START, optc1->vstartup_start); + + REG_SET_2(OTG_VUPDATE_PARAM, 0, + VUPDATE_OFFSET, optc1->vupdate_offset, + VUPDATE_WIDTH, optc1->vupdate_width); + + REG_SET(OTG_VREADY_PARAM, 0, + VREADY_OFFSET, optc1->vready_offset); +} + +static void optc1_disable_stereo(struct timing_generator *optc) +{ + struct optc *optc1 = DCN10TG_FROM_TG(optc); + + REG_SET(OTG_STEREO_CONTROL, 0, + OTG_STEREO_EN, 0); + + REG_SET_2(OTG_3D_STRUCTURE_CONTROL, 0, + OTG_3D_STRUCTURE_EN, 0, + OTG_3D_STRUCTURE_STEREO_SEL_OVR, 0); +} + +void optc1_setup_vertical_interrupt0( + struct timing_generator *optc, + uint32_t start_line, + uint32_t end_line) +{ + struct optc *optc1 = DCN10TG_FROM_TG(optc); + + REG_SET_2(OTG_VERTICAL_INTERRUPT0_POSITION, 0, + OTG_VERTICAL_INTERRUPT0_LINE_START, start_line, + OTG_VERTICAL_INTERRUPT0_LINE_END, end_line); +} + +void optc1_setup_vertical_interrupt1( + struct timing_generator *optc, + uint32_t start_line) +{ + struct optc *optc1 = DCN10TG_FROM_TG(optc); + + REG_SET(OTG_VERTICAL_INTERRUPT1_POSITION, 0, + OTG_VERTICAL_INTERRUPT1_LINE_START, start_line); +} + +void optc1_setup_vertical_interrupt2( + struct timing_generator *optc, + uint32_t start_line) +{ + struct optc *optc1 = DCN10TG_FROM_TG(optc); + + REG_SET(OTG_VERTICAL_INTERRUPT2_POSITION, 0, + OTG_VERTICAL_INTERRUPT2_LINE_START, start_line); +} + +/** + * optc1_program_timing() - used by mode timing set Program + * CRTC Timing Registers - OTG_H_*, + * OTG_V_*, Pixel repetition. + * Including SYNC. Call BIOS command table to program Timings. + * + * @optc: timing_generator instance. + * @dc_crtc_timing: Timing parameters used to configure DCN blocks. + * @vready_offset: Vready's starting position. + * @vstartup_start: Vstartup period. + * @vupdate_offset: Vupdate starting position. + * @vupdate_width: Vupdate duration. + * @signal: DC signal types. + * @use_vbios: to program timings from BIOS command table. + * + */ +void optc1_program_timing( + struct timing_generator *optc, + const struct dc_crtc_timing *dc_crtc_timing, + int vready_offset, + int vstartup_start, + int vupdate_offset, + int vupdate_width, + const enum signal_type signal, + bool use_vbios) +{ + struct dc_crtc_timing patched_crtc_timing; + uint32_t asic_blank_end; + uint32_t asic_blank_start; + uint32_t v_total; + uint32_t v_sync_end; + uint32_t h_sync_polarity, v_sync_polarity; + uint32_t start_point = 0; + uint32_t field_num = 0; + enum h_timing_div_mode h_div = H_TIMING_NO_DIV; + + struct optc *optc1 = DCN10TG_FROM_TG(optc); + + optc1->signal = signal; + optc1->vready_offset = vready_offset; + optc1->vstartup_start = vstartup_start; + optc1->vupdate_offset = vupdate_offset; + optc1->vupdate_width = vupdate_width; + patched_crtc_timing = *dc_crtc_timing; + apply_front_porch_workaround(&patched_crtc_timing); + optc1->orginal_patched_timing = patched_crtc_timing; + + /* Load horizontal timing */ + + /* CRTC_H_TOTAL = vesa.h_total - 1 */ + REG_SET(OTG_H_TOTAL, 0, + OTG_H_TOTAL, patched_crtc_timing.h_total - 1); + + /* h_sync_start = 0, h_sync_end = vesa.h_sync_width */ + REG_UPDATE_2(OTG_H_SYNC_A, + OTG_H_SYNC_A_START, 0, + OTG_H_SYNC_A_END, patched_crtc_timing.h_sync_width); + + /* blank_start = line end - front porch */ + asic_blank_start = patched_crtc_timing.h_total - + patched_crtc_timing.h_front_porch; + + /* blank_end = blank_start - active */ + asic_blank_end = asic_blank_start - + patched_crtc_timing.h_border_right - + patched_crtc_timing.h_addressable - + patched_crtc_timing.h_border_left; + + REG_UPDATE_2(OTG_H_BLANK_START_END, + OTG_H_BLANK_START, asic_blank_start, + OTG_H_BLANK_END, asic_blank_end); + + /* h_sync polarity */ + h_sync_polarity = patched_crtc_timing.flags.HSYNC_POSITIVE_POLARITY ? + 0 : 1; + + REG_UPDATE(OTG_H_SYNC_A_CNTL, + OTG_H_SYNC_A_POL, h_sync_polarity); + + v_total = patched_crtc_timing.v_total - 1; + + REG_SET(OTG_V_TOTAL, 0, + OTG_V_TOTAL, v_total); + + /* In case of V_TOTAL_CONTROL is on, make sure OTG_V_TOTAL_MAX and + * OTG_V_TOTAL_MIN are equal to V_TOTAL. + */ + optc->funcs->set_vtotal_min_max(optc, v_total, v_total); + + /* v_sync_start = 0, v_sync_end = v_sync_width */ + v_sync_end = patched_crtc_timing.v_sync_width; + + REG_UPDATE_2(OTG_V_SYNC_A, + OTG_V_SYNC_A_START, 0, + OTG_V_SYNC_A_END, v_sync_end); + + /* blank_start = frame end - front porch */ + asic_blank_start = patched_crtc_timing.v_total - + patched_crtc_timing.v_front_porch; + + /* blank_end = blank_start - active */ + asic_blank_end = asic_blank_start - + patched_crtc_timing.v_border_bottom - + patched_crtc_timing.v_addressable - + patched_crtc_timing.v_border_top; + + REG_UPDATE_2(OTG_V_BLANK_START_END, + OTG_V_BLANK_START, asic_blank_start, + OTG_V_BLANK_END, asic_blank_end); + + /* v_sync polarity */ + v_sync_polarity = patched_crtc_timing.flags.VSYNC_POSITIVE_POLARITY ? + 0 : 1; + + REG_UPDATE(OTG_V_SYNC_A_CNTL, + OTG_V_SYNC_A_POL, v_sync_polarity); + + if (optc1->signal == SIGNAL_TYPE_DISPLAY_PORT || + optc1->signal == SIGNAL_TYPE_DISPLAY_PORT_MST || + optc1->signal == SIGNAL_TYPE_EDP) { + start_point = 1; + if (patched_crtc_timing.flags.INTERLACE == 1) + field_num = 1; + } + + /* Interlace */ + if (REG(OTG_INTERLACE_CONTROL)) { + if (patched_crtc_timing.flags.INTERLACE == 1) + REG_UPDATE(OTG_INTERLACE_CONTROL, + OTG_INTERLACE_ENABLE, 1); + else + REG_UPDATE(OTG_INTERLACE_CONTROL, + OTG_INTERLACE_ENABLE, 0); + } + + /* VTG enable set to 0 first VInit */ + REG_UPDATE(CONTROL, + VTG0_ENABLE, 0); + + /* original code is using VTG offset to address OTG reg, seems wrong */ + REG_UPDATE_2(OTG_CONTROL, + OTG_START_POINT_CNTL, start_point, + OTG_FIELD_NUMBER_CNTL, field_num); + + optc->funcs->program_global_sync(optc, + vready_offset, + vstartup_start, + vupdate_offset, + vupdate_width); + + optc->funcs->set_vtg_params(optc, dc_crtc_timing, true); + + /* TODO + * patched_crtc_timing.flags.HORZ_COUNT_BY_TWO == 1 + * program_horz_count_by_2 + * for DVI 30bpp mode, 0 otherwise + * program_horz_count_by_2(optc, &patched_crtc_timing); + */ + + /* Enable stereo - only when we need to pack 3D frame. Other types + * of stereo handled in explicit call + */ + + if (optc1_is_two_pixels_per_containter(&patched_crtc_timing) || optc1->opp_count == 2) + h_div = H_TIMING_DIV_BY2; + + if (REG(OPTC_DATA_FORMAT_CONTROL) && optc1->tg_mask->OPTC_DATA_FORMAT != 0) { + uint32_t data_fmt = 0; + + if (patched_crtc_timing.pixel_encoding == PIXEL_ENCODING_YCBCR422) + data_fmt = 1; + else if (patched_crtc_timing.pixel_encoding == PIXEL_ENCODING_YCBCR420) + data_fmt = 2; + + REG_UPDATE(OPTC_DATA_FORMAT_CONTROL, OPTC_DATA_FORMAT, data_fmt); + } + + if (optc1->tg_mask->OTG_H_TIMING_DIV_MODE != 0) { + if (optc1->opp_count == 4) + h_div = H_TIMING_DIV_BY4; + + REG_UPDATE(OTG_H_TIMING_CNTL, + OTG_H_TIMING_DIV_MODE, h_div); + } else { + REG_UPDATE(OTG_H_TIMING_CNTL, + OTG_H_TIMING_DIV_BY2, h_div); + } +} + +/** + * optc1_set_vtg_params - Set Vertical Timing Generator (VTG) parameters + * + * @optc: timing_generator struct used to extract the optc parameters + * @dc_crtc_timing: Timing parameters configured + * @program_fp2: Boolean value indicating if FP2 will be programmed or not + * + * OTG is responsible for generating the global sync signals, including + * vertical timing information for each HUBP in the dcfclk domain. Each VTG is + * associated with one OTG that provides HUBP with vertical timing information + * (i.e., there is 1:1 correspondence between OTG and VTG). This function is + * responsible for setting the OTG parameters to the VTG during the pipe + * programming. + */ +void optc1_set_vtg_params(struct timing_generator *optc, + const struct dc_crtc_timing *dc_crtc_timing, bool program_fp2) +{ + struct dc_crtc_timing patched_crtc_timing; + uint32_t asic_blank_end; + uint32_t v_init; + uint32_t v_fp2 = 0; + int32_t vertical_line_start; + + struct optc *optc1 = DCN10TG_FROM_TG(optc); + + patched_crtc_timing = *dc_crtc_timing; + apply_front_porch_workaround(&patched_crtc_timing); + + /* VCOUNT_INIT is the start of blank */ + v_init = patched_crtc_timing.v_total - patched_crtc_timing.v_front_porch; + + /* end of blank = v_init - active */ + asic_blank_end = v_init - + patched_crtc_timing.v_border_bottom - + patched_crtc_timing.v_addressable - + patched_crtc_timing.v_border_top; + + /* if VSTARTUP is before VSYNC, FP2 is the offset, otherwise 0 */ + vertical_line_start = asic_blank_end - optc1->vstartup_start + 1; + if (vertical_line_start < 0) + v_fp2 = -vertical_line_start; + + /* Interlace */ + if (REG(OTG_INTERLACE_CONTROL)) { + if (patched_crtc_timing.flags.INTERLACE == 1) { + v_init = v_init / 2; + if ((optc1->vstartup_start/2)*2 > asic_blank_end) + v_fp2 = v_fp2 / 2; + } + } + + if (program_fp2) + REG_UPDATE_2(CONTROL, + VTG0_FP2, v_fp2, + VTG0_VCOUNT_INIT, v_init); + else + REG_UPDATE(CONTROL, VTG0_VCOUNT_INIT, v_init); +} + +void optc1_set_blank_data_double_buffer(struct timing_generator *optc, bool enable) +{ + struct optc *optc1 = DCN10TG_FROM_TG(optc); + + uint32_t blank_data_double_buffer_enable = enable ? 1 : 0; + + REG_UPDATE(OTG_DOUBLE_BUFFER_CONTROL, + OTG_BLANK_DATA_DOUBLE_BUFFER_EN, blank_data_double_buffer_enable); +} + +/** + * optc1_set_timing_double_buffer() - DRR double buffering control + * + * Sets double buffer point for V_TOTAL, H_TOTAL, VTOTAL_MIN, + * VTOTAL_MAX, VTOTAL_MIN_SEL and VTOTAL_MAX_SEL registers. + * + * @optc: timing_generator instance. + * @enable: Enable DRR double buffering control if true, disable otherwise. + * + * Options: any time, start of frame, dp start of frame (range timing) + */ +void optc1_set_timing_double_buffer(struct timing_generator *optc, bool enable) +{ + struct optc *optc1 = DCN10TG_FROM_TG(optc); + uint32_t mode = enable ? 2 : 0; + + REG_UPDATE(OTG_DOUBLE_BUFFER_CONTROL, + OTG_RANGE_TIMING_DBUF_UPDATE_MODE, mode); +} + +/** + * optc1_unblank_crtc() - Call ASIC Control Object to UnBlank CRTC. + * + * @optc: timing_generator instance. + */ +static void optc1_unblank_crtc(struct timing_generator *optc) +{ + struct optc *optc1 = DCN10TG_FROM_TG(optc); + + REG_UPDATE_2(OTG_BLANK_CONTROL, + OTG_BLANK_DATA_EN, 0, + OTG_BLANK_DE_MODE, 0); + + /* W/A for automated testing + * Automated testing will fail underflow test as there + * sporadic underflows which occur during the optc blank + * sequence. As a w/a, clear underflow on unblank. + * This prevents the failure, but will not mask actual + * underflow that affect real use cases. + */ + optc1_clear_optc_underflow(optc); +} + +/** + * optc1_blank_crtc() - Call ASIC Control Object to Blank CRTC. + * + * @optc: timing_generator instance. + */ + +static void optc1_blank_crtc(struct timing_generator *optc) +{ + struct optc *optc1 = DCN10TG_FROM_TG(optc); + + REG_UPDATE_2(OTG_BLANK_CONTROL, + OTG_BLANK_DATA_EN, 1, + OTG_BLANK_DE_MODE, 0); + + optc1_set_blank_data_double_buffer(optc, false); +} + +void optc1_set_blank(struct timing_generator *optc, + bool enable_blanking) +{ + if (enable_blanking) + optc1_blank_crtc(optc); + else + optc1_unblank_crtc(optc); +} + +bool optc1_is_blanked(struct timing_generator *optc) +{ + struct optc *optc1 = DCN10TG_FROM_TG(optc); + uint32_t blank_en; + uint32_t blank_state; + + REG_GET_2(OTG_BLANK_CONTROL, + OTG_BLANK_DATA_EN, &blank_en, + OTG_CURRENT_BLANK_STATE, &blank_state); + + return blank_en && blank_state; +} + +void optc1_enable_optc_clock(struct timing_generator *optc, bool enable) +{ + struct optc *optc1 = DCN10TG_FROM_TG(optc); + + if (enable) { + REG_UPDATE_2(OPTC_INPUT_CLOCK_CONTROL, + OPTC_INPUT_CLK_EN, 1, + OPTC_INPUT_CLK_GATE_DIS, 1); + + REG_WAIT(OPTC_INPUT_CLOCK_CONTROL, + OPTC_INPUT_CLK_ON, 1, + 1, 1000); + + /* Enable clock */ + REG_UPDATE_2(OTG_CLOCK_CONTROL, + OTG_CLOCK_EN, 1, + OTG_CLOCK_GATE_DIS, 1); + REG_WAIT(OTG_CLOCK_CONTROL, + OTG_CLOCK_ON, 1, + 1, 1000); + } else { + + //last chance to clear underflow, otherwise, it will always there due to clock is off. + if (optc->funcs->is_optc_underflow_occurred(optc) == true) + optc->funcs->clear_optc_underflow(optc); + + REG_UPDATE_2(OTG_CLOCK_CONTROL, + OTG_CLOCK_GATE_DIS, 0, + OTG_CLOCK_EN, 0); + + REG_UPDATE_2(OPTC_INPUT_CLOCK_CONTROL, + OPTC_INPUT_CLK_GATE_DIS, 0, + OPTC_INPUT_CLK_EN, 0); + } +} + +/** + * optc1_enable_crtc() - Enable CRTC - call ASIC Control Object to enable Timing generator. + * + * @optc: timing_generator instance. + */ +static bool optc1_enable_crtc(struct timing_generator *optc) +{ + /* TODO FPGA wait for answer + * OTG_MASTER_UPDATE_MODE != CRTC_MASTER_UPDATE_MODE + * OTG_MASTER_UPDATE_LOCK != CRTC_MASTER_UPDATE_LOCK + */ + struct optc *optc1 = DCN10TG_FROM_TG(optc); + + /* opp instance for OTG. For DCN1.0, ODM is remoed. + * OPP and OPTC should 1:1 mapping + */ + REG_UPDATE(OPTC_DATA_SOURCE_SELECT, + OPTC_SRC_SEL, optc->inst); + + /* VTG enable first is for HW workaround */ + REG_UPDATE(CONTROL, + VTG0_ENABLE, 1); + + REG_SEQ_START(); + + /* Enable CRTC */ + REG_UPDATE_2(OTG_CONTROL, + OTG_DISABLE_POINT_CNTL, 3, + OTG_MASTER_EN, 1); + + REG_SEQ_SUBMIT(); + REG_SEQ_WAIT_DONE(); + + return true; +} + +/* disable_crtc - call ASIC Control Object to disable Timing generator. */ +bool optc1_disable_crtc(struct timing_generator *optc) +{ + struct optc *optc1 = DCN10TG_FROM_TG(optc); + + /* disable otg request until end of the first line + * in the vertical blank region + */ + REG_UPDATE_2(OTG_CONTROL, + OTG_DISABLE_POINT_CNTL, 3, + OTG_MASTER_EN, 0); + + REG_UPDATE(CONTROL, + VTG0_ENABLE, 0); + + /* CRTC disabled, so disable clock. */ + REG_WAIT(OTG_CLOCK_CONTROL, + OTG_BUSY, 0, + 1, 100000); + + return true; +} + + +void optc1_program_blank_color( + struct timing_generator *optc, + const struct tg_color *black_color) +{ + struct optc *optc1 = DCN10TG_FROM_TG(optc); + + REG_SET_3(OTG_BLACK_COLOR, 0, + OTG_BLACK_COLOR_B_CB, black_color->color_b_cb, + OTG_BLACK_COLOR_G_Y, black_color->color_g_y, + OTG_BLACK_COLOR_R_CR, black_color->color_r_cr); +} + +bool optc1_validate_timing( + struct timing_generator *optc, + const struct dc_crtc_timing *timing) +{ + uint32_t v_blank; + uint32_t h_blank; + uint32_t min_v_blank; + struct optc *optc1 = DCN10TG_FROM_TG(optc); + + ASSERT(timing != NULL); + + v_blank = (timing->v_total - timing->v_addressable - + timing->v_border_top - timing->v_border_bottom); + + h_blank = (timing->h_total - timing->h_addressable - + timing->h_border_right - + timing->h_border_left); + + if (timing->timing_3d_format != TIMING_3D_FORMAT_NONE && + timing->timing_3d_format != TIMING_3D_FORMAT_HW_FRAME_PACKING && + timing->timing_3d_format != TIMING_3D_FORMAT_TOP_AND_BOTTOM && + timing->timing_3d_format != TIMING_3D_FORMAT_SIDE_BY_SIDE && + timing->timing_3d_format != TIMING_3D_FORMAT_FRAME_ALTERNATE && + timing->timing_3d_format != TIMING_3D_FORMAT_INBAND_FA) + return false; + + /* Temporarily blocking interlacing mode until it's supported */ + if (timing->flags.INTERLACE == 1) + return false; + + /* Check maximum number of pixels supported by Timing Generator + * (Currently will never fail, in order to fail needs display which + * needs more than 8192 horizontal and + * more than 8192 vertical total pixels) + */ + if (timing->h_total > optc1->max_h_total || + timing->v_total > optc1->max_v_total) + return false; + + + if (h_blank < optc1->min_h_blank) + return false; + + if (timing->h_sync_width < optc1->min_h_sync_width || + timing->v_sync_width < optc1->min_v_sync_width) + return false; + + min_v_blank = timing->flags.INTERLACE?optc1->min_v_blank_interlace:optc1->min_v_blank; + + if (v_blank < min_v_blank) + return false; + + return true; + +} + +/* + * get_vblank_counter + * + * @brief + * Get counter for vertical blanks. use register CRTC_STATUS_FRAME_COUNT which + * holds the counter of frames. + * + * @param + * struct timing_generator *optc - [in] timing generator which controls the + * desired CRTC + * + * @return + * Counter of frames, which should equal to number of vblanks. + */ +uint32_t optc1_get_vblank_counter(struct timing_generator *optc) +{ + struct optc *optc1 = DCN10TG_FROM_TG(optc); + uint32_t frame_count; + + REG_GET(OTG_STATUS_FRAME_COUNT, + OTG_FRAME_COUNT, &frame_count); + + return frame_count; +} + +void optc1_lock(struct timing_generator *optc) +{ + struct optc *optc1 = DCN10TG_FROM_TG(optc); + + REG_SET(OTG_GLOBAL_CONTROL0, 0, + OTG_MASTER_UPDATE_LOCK_SEL, optc->inst); + REG_SET(OTG_MASTER_UPDATE_LOCK, 0, + OTG_MASTER_UPDATE_LOCK, 1); + + REG_WAIT(OTG_MASTER_UPDATE_LOCK, + UPDATE_LOCK_STATUS, 1, + 1, 10); + + TRACE_OPTC_LOCK_UNLOCK_STATE(optc1, optc->inst, true); +} + +void optc1_unlock(struct timing_generator *optc) +{ + struct optc *optc1 = DCN10TG_FROM_TG(optc); + + REG_SET(OTG_MASTER_UPDATE_LOCK, 0, + OTG_MASTER_UPDATE_LOCK, 0); + + TRACE_OPTC_LOCK_UNLOCK_STATE(optc1, optc->inst, false); +} + +void optc1_get_position(struct timing_generator *optc, + struct crtc_position *position) +{ + struct optc *optc1 = DCN10TG_FROM_TG(optc); + + REG_GET_2(OTG_STATUS_POSITION, + OTG_HORZ_COUNT, &position->horizontal_count, + OTG_VERT_COUNT, &position->vertical_count); + + REG_GET(OTG_NOM_VERT_POSITION, + OTG_VERT_COUNT_NOM, &position->nominal_vcount); +} + +bool optc1_is_counter_moving(struct timing_generator *optc) +{ + struct crtc_position position1, position2; + + optc->funcs->get_position(optc, &position1); + optc->funcs->get_position(optc, &position2); + + if (position1.horizontal_count == position2.horizontal_count && + position1.vertical_count == position2.vertical_count) + return false; + else + return true; +} + +bool optc1_did_triggered_reset_occur( + struct timing_generator *optc) +{ + struct optc *optc1 = DCN10TG_FROM_TG(optc); + uint32_t occurred_force, occurred_vsync; + + REG_GET(OTG_FORCE_COUNT_NOW_CNTL, + OTG_FORCE_COUNT_NOW_OCCURRED, &occurred_force); + + REG_GET(OTG_VERT_SYNC_CONTROL, + OTG_FORCE_VSYNC_NEXT_LINE_OCCURRED, &occurred_vsync); + + return occurred_vsync != 0 || occurred_force != 0; +} + +void optc1_disable_reset_trigger(struct timing_generator *optc) +{ + struct optc *optc1 = DCN10TG_FROM_TG(optc); + + REG_WRITE(OTG_TRIGA_CNTL, 0); + + REG_SET(OTG_FORCE_COUNT_NOW_CNTL, 0, + OTG_FORCE_COUNT_NOW_CLEAR, 1); + + REG_SET(OTG_VERT_SYNC_CONTROL, 0, + OTG_FORCE_VSYNC_NEXT_LINE_CLEAR, 1); +} + +void optc1_enable_reset_trigger(struct timing_generator *optc, int source_tg_inst) +{ + struct optc *optc1 = DCN10TG_FROM_TG(optc); + uint32_t falling_edge; + + REG_GET(OTG_V_SYNC_A_CNTL, + OTG_V_SYNC_A_POL, &falling_edge); + + if (falling_edge) + REG_SET_3(OTG_TRIGA_CNTL, 0, + /* vsync signal from selected OTG pipe based + * on OTG_TRIG_SOURCE_PIPE_SELECT setting + */ + OTG_TRIGA_SOURCE_SELECT, 20, + OTG_TRIGA_SOURCE_PIPE_SELECT, source_tg_inst, + /* always detect falling edge */ + OTG_TRIGA_FALLING_EDGE_DETECT_CNTL, 1); + else + REG_SET_3(OTG_TRIGA_CNTL, 0, + /* vsync signal from selected OTG pipe based + * on OTG_TRIG_SOURCE_PIPE_SELECT setting + */ + OTG_TRIGA_SOURCE_SELECT, 20, + OTG_TRIGA_SOURCE_PIPE_SELECT, source_tg_inst, + /* always detect rising edge */ + OTG_TRIGA_RISING_EDGE_DETECT_CNTL, 1); + + REG_SET(OTG_FORCE_COUNT_NOW_CNTL, 0, + /* force H count to H_TOTAL and V count to V_TOTAL in + * progressive mode and V_TOTAL-1 in interlaced mode + */ + OTG_FORCE_COUNT_NOW_MODE, 2); +} + +void optc1_enable_crtc_reset( + struct timing_generator *optc, + int source_tg_inst, + struct crtc_trigger_info *crtc_tp) +{ + struct optc *optc1 = DCN10TG_FROM_TG(optc); + uint32_t falling_edge = 0; + uint32_t rising_edge = 0; + + switch (crtc_tp->event) { + + case CRTC_EVENT_VSYNC_RISING: + rising_edge = 1; + break; + + case CRTC_EVENT_VSYNC_FALLING: + falling_edge = 1; + break; + } + + REG_SET_4(OTG_TRIGA_CNTL, 0, + /* vsync signal from selected OTG pipe based + * on OTG_TRIG_SOURCE_PIPE_SELECT setting + */ + OTG_TRIGA_SOURCE_SELECT, 20, + OTG_TRIGA_SOURCE_PIPE_SELECT, source_tg_inst, + /* always detect falling edge */ + OTG_TRIGA_RISING_EDGE_DETECT_CNTL, rising_edge, + OTG_TRIGA_FALLING_EDGE_DETECT_CNTL, falling_edge); + + switch (crtc_tp->delay) { + case TRIGGER_DELAY_NEXT_LINE: + REG_SET(OTG_VERT_SYNC_CONTROL, 0, + OTG_AUTO_FORCE_VSYNC_MODE, 1); + break; + case TRIGGER_DELAY_NEXT_PIXEL: + REG_SET(OTG_FORCE_COUNT_NOW_CNTL, 0, + /* force H count to H_TOTAL and V count to V_TOTAL in + * progressive mode and V_TOTAL-1 in interlaced mode + */ + OTG_FORCE_COUNT_NOW_MODE, 2); + break; + } +} + +void optc1_wait_for_state(struct timing_generator *optc, + enum crtc_state state) +{ + struct optc *optc1 = DCN10TG_FROM_TG(optc); + + switch (state) { + case CRTC_STATE_VBLANK: + REG_WAIT(OTG_STATUS, + OTG_V_BLANK, 1, + 1, 100000); /* 1 vupdate at 10hz */ + break; + + case CRTC_STATE_VACTIVE: + REG_WAIT(OTG_STATUS, + OTG_V_ACTIVE_DISP, 1, + 1, 100000); /* 1 vupdate at 10hz */ + break; + + default: + break; + } +} + +void optc1_set_early_control( + struct timing_generator *optc, + uint32_t early_cntl) +{ + /* asic design change, do not need this control + * empty for share caller logic + */ +} + + +void optc1_set_static_screen_control( + struct timing_generator *optc, + uint32_t event_triggers, + uint32_t num_frames) +{ + struct optc *optc1 = DCN10TG_FROM_TG(optc); + + // By register spec, it only takes 8 bit value + if (num_frames > 0xFF) + num_frames = 0xFF; + + /* Bit 8 is no longer applicable in RV for PSR case, + * set bit 8 to 0 if given + */ + if ((event_triggers & STATIC_SCREEN_EVENT_MASK_RANGETIMING_DOUBLE_BUFFER_UPDATE_EN) + != 0) + event_triggers = event_triggers & + ~STATIC_SCREEN_EVENT_MASK_RANGETIMING_DOUBLE_BUFFER_UPDATE_EN; + + REG_SET_2(OTG_STATIC_SCREEN_CONTROL, 0, + OTG_STATIC_SCREEN_EVENT_MASK, event_triggers, + OTG_STATIC_SCREEN_FRAME_COUNT, num_frames); +} + +static void optc1_setup_manual_trigger(struct timing_generator *optc) +{ + struct optc *optc1 = DCN10TG_FROM_TG(optc); + + REG_SET(OTG_GLOBAL_CONTROL2, 0, + MANUAL_FLOW_CONTROL_SEL, optc->inst); + + REG_SET_8(OTG_TRIGA_CNTL, 0, + OTG_TRIGA_SOURCE_SELECT, 22, + OTG_TRIGA_SOURCE_PIPE_SELECT, optc->inst, + OTG_TRIGA_RISING_EDGE_DETECT_CNTL, 1, + OTG_TRIGA_FALLING_EDGE_DETECT_CNTL, 0, + OTG_TRIGA_POLARITY_SELECT, 0, + OTG_TRIGA_FREQUENCY_SELECT, 0, + OTG_TRIGA_DELAY, 0, + OTG_TRIGA_CLEAR, 1); +} + +static void optc1_program_manual_trigger(struct timing_generator *optc) +{ + struct optc *optc1 = DCN10TG_FROM_TG(optc); + + REG_SET(OTG_MANUAL_FLOW_CONTROL, 0, + MANUAL_FLOW_CONTROL, 1); + + REG_SET(OTG_MANUAL_FLOW_CONTROL, 0, + MANUAL_FLOW_CONTROL, 0); +} + +/** + * optc1_set_drr() - Program dynamic refresh rate registers m_OTGx_OTG_V_TOTAL_*. + * + * @optc: timing_generator instance. + * @params: parameters used for Dynamic Refresh Rate. + */ +void optc1_set_drr( + struct timing_generator *optc, + const struct drr_params *params) +{ + struct optc *optc1 = DCN10TG_FROM_TG(optc); + + if (params != NULL && + params->vertical_total_max > 0 && + params->vertical_total_min > 0) { + + if (params->vertical_total_mid != 0) { + + REG_SET(OTG_V_TOTAL_MID, 0, + OTG_V_TOTAL_MID, params->vertical_total_mid - 1); + + REG_UPDATE_2(OTG_V_TOTAL_CONTROL, + OTG_VTOTAL_MID_REPLACING_MAX_EN, 1, + OTG_VTOTAL_MID_FRAME_NUM, + (uint8_t)params->vertical_total_mid_frame_num); + + } + + optc->funcs->set_vtotal_min_max(optc, params->vertical_total_min - 1, params->vertical_total_max - 1); + + REG_UPDATE_5(OTG_V_TOTAL_CONTROL, + OTG_V_TOTAL_MIN_SEL, 1, + OTG_V_TOTAL_MAX_SEL, 1, + OTG_FORCE_LOCK_ON_EVENT, 0, + OTG_SET_V_TOTAL_MIN_MASK_EN, 0, + OTG_SET_V_TOTAL_MIN_MASK, 0); + } + + // Setup manual flow control for EOF via TRIG_A + optc->funcs->setup_manual_trigger(optc); +} + +void optc1_set_vtotal_min_max(struct timing_generator *optc, int vtotal_min, int vtotal_max) +{ + struct optc *optc1 = DCN10TG_FROM_TG(optc); + + REG_SET(OTG_V_TOTAL_MAX, 0, + OTG_V_TOTAL_MAX, vtotal_max); + + REG_SET(OTG_V_TOTAL_MIN, 0, + OTG_V_TOTAL_MIN, vtotal_min); +} + +static void optc1_set_test_pattern( + struct timing_generator *optc, + /* TODO: replace 'controller_dp_test_pattern' by 'test_pattern_mode' + * because this is not DP-specific (which is probably somewhere in DP + * encoder) */ + enum controller_dp_test_pattern test_pattern, + enum dc_color_depth color_depth) +{ + struct optc *optc1 = DCN10TG_FROM_TG(optc); + enum test_pattern_color_format bit_depth; + enum test_pattern_dyn_range dyn_range; + enum test_pattern_mode mode; + uint32_t pattern_mask; + uint32_t pattern_data; + /* color ramp generator mixes 16-bits color */ + uint32_t src_bpc = 16; + /* requested bpc */ + uint32_t dst_bpc; + uint32_t index; + /* RGB values of the color bars. + * Produce two RGB colors: RGB0 - white (all Fs) + * and RGB1 - black (all 0s) + * (three RGB components for two colors) + */ + uint16_t src_color[6] = {0xFFFF, 0xFFFF, 0xFFFF, 0x0000, + 0x0000, 0x0000}; + /* dest color (converted to the specified color format) */ + uint16_t dst_color[6]; + uint32_t inc_base; + + /* translate to bit depth */ + switch (color_depth) { + case COLOR_DEPTH_666: + bit_depth = TEST_PATTERN_COLOR_FORMAT_BPC_6; + break; + case COLOR_DEPTH_888: + bit_depth = TEST_PATTERN_COLOR_FORMAT_BPC_8; + break; + case COLOR_DEPTH_101010: + bit_depth = TEST_PATTERN_COLOR_FORMAT_BPC_10; + break; + case COLOR_DEPTH_121212: + bit_depth = TEST_PATTERN_COLOR_FORMAT_BPC_12; + break; + default: + bit_depth = TEST_PATTERN_COLOR_FORMAT_BPC_8; + break; + } + + switch (test_pattern) { + case CONTROLLER_DP_TEST_PATTERN_COLORSQUARES: + case CONTROLLER_DP_TEST_PATTERN_COLORSQUARES_CEA: + { + dyn_range = (test_pattern == + CONTROLLER_DP_TEST_PATTERN_COLORSQUARES_CEA ? + TEST_PATTERN_DYN_RANGE_CEA : + TEST_PATTERN_DYN_RANGE_VESA); + mode = TEST_PATTERN_MODE_COLORSQUARES_RGB; + + REG_UPDATE_2(OTG_TEST_PATTERN_PARAMETERS, + OTG_TEST_PATTERN_VRES, 6, + OTG_TEST_PATTERN_HRES, 6); + + REG_UPDATE_4(OTG_TEST_PATTERN_CONTROL, + OTG_TEST_PATTERN_EN, 1, + OTG_TEST_PATTERN_MODE, mode, + OTG_TEST_PATTERN_DYNAMIC_RANGE, dyn_range, + OTG_TEST_PATTERN_COLOR_FORMAT, bit_depth); + } + break; + + case CONTROLLER_DP_TEST_PATTERN_VERTICALBARS: + case CONTROLLER_DP_TEST_PATTERN_HORIZONTALBARS: + { + mode = (test_pattern == + CONTROLLER_DP_TEST_PATTERN_VERTICALBARS ? + TEST_PATTERN_MODE_VERTICALBARS : + TEST_PATTERN_MODE_HORIZONTALBARS); + + switch (bit_depth) { + case TEST_PATTERN_COLOR_FORMAT_BPC_6: + dst_bpc = 6; + break; + case TEST_PATTERN_COLOR_FORMAT_BPC_8: + dst_bpc = 8; + break; + case TEST_PATTERN_COLOR_FORMAT_BPC_10: + dst_bpc = 10; + break; + default: + dst_bpc = 8; + break; + } + + /* adjust color to the required colorFormat */ + for (index = 0; index < 6; index++) { + /* dst = 2^dstBpc * src / 2^srcBpc = src >> + * (srcBpc - dstBpc); + */ + dst_color[index] = + src_color[index] >> (src_bpc - dst_bpc); + /* CRTC_TEST_PATTERN_DATA has 16 bits, + * lowest 6 are hardwired to ZERO + * color bits should be left aligned to MSB + * XXXXXXXXXX000000 for 10 bit, + * XXXXXXXX00000000 for 8 bit and XXXXXX0000000000 for 6 + */ + dst_color[index] <<= (16 - dst_bpc); + } + + REG_WRITE(OTG_TEST_PATTERN_PARAMETERS, 0); + + /* We have to write the mask before data, similar to pipeline. + * For example, for 8 bpc, if we want RGB0 to be magenta, + * and RGB1 to be cyan, + * we need to make 7 writes: + * MASK DATA + * 000001 00000000 00000000 set mask to R0 + * 000010 11111111 00000000 R0 255, 0xFF00, set mask to G0 + * 000100 00000000 00000000 G0 0, 0x0000, set mask to B0 + * 001000 11111111 00000000 B0 255, 0xFF00, set mask to R1 + * 010000 00000000 00000000 R1 0, 0x0000, set mask to G1 + * 100000 11111111 00000000 G1 255, 0xFF00, set mask to B1 + * 100000 11111111 00000000 B1 255, 0xFF00 + * + * we will make a loop of 6 in which we prepare the mask, + * then write, then prepare the color for next write. + * first iteration will write mask only, + * but each next iteration color prepared in + * previous iteration will be written within new mask, + * the last component will written separately, + * mask is not changing between 6th and 7th write + * and color will be prepared by last iteration + */ + + /* write color, color values mask in CRTC_TEST_PATTERN_MASK + * is B1, G1, R1, B0, G0, R0 + */ + pattern_data = 0; + for (index = 0; index < 6; index++) { + /* prepare color mask, first write PATTERN_DATA + * will have all zeros + */ + pattern_mask = (1 << index); + + /* write color component */ + REG_SET_2(OTG_TEST_PATTERN_COLOR, 0, + OTG_TEST_PATTERN_MASK, pattern_mask, + OTG_TEST_PATTERN_DATA, pattern_data); + + /* prepare next color component, + * will be written in the next iteration + */ + pattern_data = dst_color[index]; + } + /* write last color component, + * it's been already prepared in the loop + */ + REG_SET_2(OTG_TEST_PATTERN_COLOR, 0, + OTG_TEST_PATTERN_MASK, pattern_mask, + OTG_TEST_PATTERN_DATA, pattern_data); + + /* enable test pattern */ + REG_UPDATE_4(OTG_TEST_PATTERN_CONTROL, + OTG_TEST_PATTERN_EN, 1, + OTG_TEST_PATTERN_MODE, mode, + OTG_TEST_PATTERN_DYNAMIC_RANGE, 0, + OTG_TEST_PATTERN_COLOR_FORMAT, bit_depth); + } + break; + + case CONTROLLER_DP_TEST_PATTERN_COLORRAMP: + { + mode = (bit_depth == + TEST_PATTERN_COLOR_FORMAT_BPC_10 ? + TEST_PATTERN_MODE_DUALRAMP_RGB : + TEST_PATTERN_MODE_SINGLERAMP_RGB); + + switch (bit_depth) { + case TEST_PATTERN_COLOR_FORMAT_BPC_6: + dst_bpc = 6; + break; + case TEST_PATTERN_COLOR_FORMAT_BPC_8: + dst_bpc = 8; + break; + case TEST_PATTERN_COLOR_FORMAT_BPC_10: + dst_bpc = 10; + break; + default: + dst_bpc = 8; + break; + } + + /* increment for the first ramp for one color gradation + * 1 gradation for 6-bit color is 2^10 + * gradations in 16-bit color + */ + inc_base = (src_bpc - dst_bpc); + + switch (bit_depth) { + case TEST_PATTERN_COLOR_FORMAT_BPC_6: + { + REG_UPDATE_5(OTG_TEST_PATTERN_PARAMETERS, + OTG_TEST_PATTERN_INC0, inc_base, + OTG_TEST_PATTERN_INC1, 0, + OTG_TEST_PATTERN_HRES, 6, + OTG_TEST_PATTERN_VRES, 6, + OTG_TEST_PATTERN_RAMP0_OFFSET, 0); + } + break; + case TEST_PATTERN_COLOR_FORMAT_BPC_8: + { + REG_UPDATE_5(OTG_TEST_PATTERN_PARAMETERS, + OTG_TEST_PATTERN_INC0, inc_base, + OTG_TEST_PATTERN_INC1, 0, + OTG_TEST_PATTERN_HRES, 8, + OTG_TEST_PATTERN_VRES, 6, + OTG_TEST_PATTERN_RAMP0_OFFSET, 0); + } + break; + case TEST_PATTERN_COLOR_FORMAT_BPC_10: + { + REG_UPDATE_5(OTG_TEST_PATTERN_PARAMETERS, + OTG_TEST_PATTERN_INC0, inc_base, + OTG_TEST_PATTERN_INC1, inc_base + 2, + OTG_TEST_PATTERN_HRES, 8, + OTG_TEST_PATTERN_VRES, 5, + OTG_TEST_PATTERN_RAMP0_OFFSET, 384 << 6); + } + break; + default: + break; + } + + REG_WRITE(OTG_TEST_PATTERN_COLOR, 0); + + /* enable test pattern */ + REG_WRITE(OTG_TEST_PATTERN_CONTROL, 0); + + REG_SET_4(OTG_TEST_PATTERN_CONTROL, 0, + OTG_TEST_PATTERN_EN, 1, + OTG_TEST_PATTERN_MODE, mode, + OTG_TEST_PATTERN_DYNAMIC_RANGE, 0, + OTG_TEST_PATTERN_COLOR_FORMAT, bit_depth); + } + break; + case CONTROLLER_DP_TEST_PATTERN_VIDEOMODE: + { + REG_WRITE(OTG_TEST_PATTERN_CONTROL, 0); + REG_WRITE(OTG_TEST_PATTERN_COLOR, 0); + REG_WRITE(OTG_TEST_PATTERN_PARAMETERS, 0); + } + break; + default: + break; + + } +} + +void optc1_get_crtc_scanoutpos( + struct timing_generator *optc, + uint32_t *v_blank_start, + uint32_t *v_blank_end, + uint32_t *h_position, + uint32_t *v_position) +{ + struct optc *optc1 = DCN10TG_FROM_TG(optc); + struct crtc_position position; + + REG_GET_2(OTG_V_BLANK_START_END, + OTG_V_BLANK_START, v_blank_start, + OTG_V_BLANK_END, v_blank_end); + + optc1_get_position(optc, &position); + + *h_position = position.horizontal_count; + *v_position = position.vertical_count; +} + +static void optc1_enable_stereo(struct timing_generator *optc, + const struct dc_crtc_timing *timing, struct crtc_stereo_flags *flags) +{ + struct optc *optc1 = DCN10TG_FROM_TG(optc); + + if (flags) { + uint32_t stereo_en; + stereo_en = flags->FRAME_PACKED == 0 ? 1 : 0; + + if (flags->PROGRAM_STEREO) + REG_UPDATE_3(OTG_STEREO_CONTROL, + OTG_STEREO_EN, stereo_en, + OTG_STEREO_SYNC_OUTPUT_LINE_NUM, 0, + OTG_STEREO_SYNC_OUTPUT_POLARITY, flags->RIGHT_EYE_POLARITY == 0 ? 0 : 1); + + if (flags->PROGRAM_POLARITY) + REG_UPDATE(OTG_STEREO_CONTROL, + OTG_STEREO_EYE_FLAG_POLARITY, + flags->RIGHT_EYE_POLARITY == 0 ? 0 : 1); + + if (flags->DISABLE_STEREO_DP_SYNC) + REG_UPDATE(OTG_STEREO_CONTROL, + OTG_DISABLE_STEREOSYNC_OUTPUT_FOR_DP, 1); + + if (flags->PROGRAM_STEREO) + REG_UPDATE_2(OTG_3D_STRUCTURE_CONTROL, + OTG_3D_STRUCTURE_EN, flags->FRAME_PACKED, + OTG_3D_STRUCTURE_STEREO_SEL_OVR, flags->FRAME_PACKED); + + } +} + +void optc1_program_stereo(struct timing_generator *optc, + const struct dc_crtc_timing *timing, struct crtc_stereo_flags *flags) +{ + if (flags->PROGRAM_STEREO) + optc1_enable_stereo(optc, timing, flags); + else + optc1_disable_stereo(optc); +} + + +bool optc1_is_stereo_left_eye(struct timing_generator *optc) +{ + bool ret = false; + uint32_t left_eye = 0; + struct optc *optc1 = DCN10TG_FROM_TG(optc); + + REG_GET(OTG_STEREO_STATUS, + OTG_STEREO_CURRENT_EYE, &left_eye); + if (left_eye == 1) + ret = true; + else + ret = false; + + return ret; +} + +bool optc1_get_hw_timing(struct timing_generator *tg, + struct dc_crtc_timing *hw_crtc_timing) +{ + struct dcn_otg_state s = {0}; + + if (tg == NULL || hw_crtc_timing == NULL) + return false; + + optc1_read_otg_state(DCN10TG_FROM_TG(tg), &s); + + hw_crtc_timing->h_total = s.h_total + 1; + hw_crtc_timing->h_addressable = s.h_total - ((s.h_total - s.h_blank_start) + s.h_blank_end); + hw_crtc_timing->h_front_porch = s.h_total + 1 - s.h_blank_start; + hw_crtc_timing->h_sync_width = s.h_sync_a_end - s.h_sync_a_start; + + hw_crtc_timing->v_total = s.v_total + 1; + hw_crtc_timing->v_addressable = s.v_total - ((s.v_total - s.v_blank_start) + s.v_blank_end); + hw_crtc_timing->v_front_porch = s.v_total + 1 - s.v_blank_start; + hw_crtc_timing->v_sync_width = s.v_sync_a_end - s.v_sync_a_start; + + return true; +} + + +void optc1_read_otg_state(struct optc *optc1, + struct dcn_otg_state *s) +{ + REG_GET(OTG_CONTROL, + OTG_MASTER_EN, &s->otg_enabled); + + REG_GET_2(OTG_V_BLANK_START_END, + OTG_V_BLANK_START, &s->v_blank_start, + OTG_V_BLANK_END, &s->v_blank_end); + + REG_GET(OTG_V_SYNC_A_CNTL, + OTG_V_SYNC_A_POL, &s->v_sync_a_pol); + + REG_GET(OTG_V_TOTAL, + OTG_V_TOTAL, &s->v_total); + + REG_GET(OTG_V_TOTAL_MAX, + OTG_V_TOTAL_MAX, &s->v_total_max); + + REG_GET(OTG_V_TOTAL_MIN, + OTG_V_TOTAL_MIN, &s->v_total_min); + + REG_GET(OTG_V_TOTAL_CONTROL, + OTG_V_TOTAL_MAX_SEL, &s->v_total_max_sel); + + REG_GET(OTG_V_TOTAL_CONTROL, + OTG_V_TOTAL_MIN_SEL, &s->v_total_min_sel); + + REG_GET_2(OTG_V_SYNC_A, + OTG_V_SYNC_A_START, &s->v_sync_a_start, + OTG_V_SYNC_A_END, &s->v_sync_a_end); + + REG_GET_2(OTG_H_BLANK_START_END, + OTG_H_BLANK_START, &s->h_blank_start, + OTG_H_BLANK_END, &s->h_blank_end); + + REG_GET_2(OTG_H_SYNC_A, + OTG_H_SYNC_A_START, &s->h_sync_a_start, + OTG_H_SYNC_A_END, &s->h_sync_a_end); + + REG_GET(OTG_H_SYNC_A_CNTL, + OTG_H_SYNC_A_POL, &s->h_sync_a_pol); + + REG_GET(OTG_H_TOTAL, + OTG_H_TOTAL, &s->h_total); + + REG_GET(OPTC_INPUT_GLOBAL_CONTROL, + OPTC_UNDERFLOW_OCCURRED_STATUS, &s->underflow_occurred_status); + + REG_GET(OTG_VERTICAL_INTERRUPT1_CONTROL, + OTG_VERTICAL_INTERRUPT1_INT_ENABLE, &s->vertical_interrupt1_en); + + REG_GET(OTG_VERTICAL_INTERRUPT1_POSITION, + OTG_VERTICAL_INTERRUPT1_LINE_START, &s->vertical_interrupt1_line); + + REG_GET(OTG_VERTICAL_INTERRUPT2_CONTROL, + OTG_VERTICAL_INTERRUPT2_INT_ENABLE, &s->vertical_interrupt2_en); + + REG_GET(OTG_VERTICAL_INTERRUPT2_POSITION, + OTG_VERTICAL_INTERRUPT2_LINE_START, &s->vertical_interrupt2_line); +} + +bool optc1_get_otg_active_size(struct timing_generator *optc, + uint32_t *otg_active_width, + uint32_t *otg_active_height) +{ + uint32_t otg_enabled; + uint32_t v_blank_start; + uint32_t v_blank_end; + uint32_t h_blank_start; + uint32_t h_blank_end; + struct optc *optc1 = DCN10TG_FROM_TG(optc); + + + REG_GET(OTG_CONTROL, + OTG_MASTER_EN, &otg_enabled); + + if (otg_enabled == 0) + return false; + + REG_GET_2(OTG_V_BLANK_START_END, + OTG_V_BLANK_START, &v_blank_start, + OTG_V_BLANK_END, &v_blank_end); + + REG_GET_2(OTG_H_BLANK_START_END, + OTG_H_BLANK_START, &h_blank_start, + OTG_H_BLANK_END, &h_blank_end); + + *otg_active_width = v_blank_start - v_blank_end; + *otg_active_height = h_blank_start - h_blank_end; + return true; +} + +void optc1_clear_optc_underflow(struct timing_generator *optc) +{ + struct optc *optc1 = DCN10TG_FROM_TG(optc); + + REG_UPDATE(OPTC_INPUT_GLOBAL_CONTROL, OPTC_UNDERFLOW_CLEAR, 1); +} + +void optc1_tg_init(struct timing_generator *optc) +{ + optc1_set_blank_data_double_buffer(optc, true); + optc1_set_timing_double_buffer(optc, true); + optc1_clear_optc_underflow(optc); +} + +bool optc1_is_tg_enabled(struct timing_generator *optc) +{ + struct optc *optc1 = DCN10TG_FROM_TG(optc); + uint32_t otg_enabled = 0; + + REG_GET(OTG_CONTROL, OTG_MASTER_EN, &otg_enabled); + + return (otg_enabled != 0); + +} + +bool optc1_is_optc_underflow_occurred(struct timing_generator *optc) +{ + struct optc *optc1 = DCN10TG_FROM_TG(optc); + uint32_t underflow_occurred = 0; + + REG_GET(OPTC_INPUT_GLOBAL_CONTROL, + OPTC_UNDERFLOW_OCCURRED_STATUS, + &underflow_occurred); + + return (underflow_occurred == 1); +} + +bool optc1_configure_crc(struct timing_generator *optc, + const struct crc_params *params) +{ + struct optc *optc1 = DCN10TG_FROM_TG(optc); + + /* Cannot configure crc on a CRTC that is disabled */ + if (!optc1_is_tg_enabled(optc)) + return false; + + REG_WRITE(OTG_CRC_CNTL, 0); + + if (!params->enable) + return true; + + /* Program frame boundaries */ + /* Window A x axis start and end. */ + REG_UPDATE_2(OTG_CRC0_WINDOWA_X_CONTROL, + OTG_CRC0_WINDOWA_X_START, params->windowa_x_start, + OTG_CRC0_WINDOWA_X_END, params->windowa_x_end); + + /* Window A y axis start and end. */ + REG_UPDATE_2(OTG_CRC0_WINDOWA_Y_CONTROL, + OTG_CRC0_WINDOWA_Y_START, params->windowa_y_start, + OTG_CRC0_WINDOWA_Y_END, params->windowa_y_end); + + /* Window B x axis start and end. */ + REG_UPDATE_2(OTG_CRC0_WINDOWB_X_CONTROL, + OTG_CRC0_WINDOWB_X_START, params->windowb_x_start, + OTG_CRC0_WINDOWB_X_END, params->windowb_x_end); + + /* Window B y axis start and end. */ + REG_UPDATE_2(OTG_CRC0_WINDOWB_Y_CONTROL, + OTG_CRC0_WINDOWB_Y_START, params->windowb_y_start, + OTG_CRC0_WINDOWB_Y_END, params->windowb_y_end); + + /* Set crc mode and selection, and enable. Only using CRC0*/ + REG_UPDATE_3(OTG_CRC_CNTL, + OTG_CRC_CONT_EN, params->continuous_mode ? 1 : 0, + OTG_CRC0_SELECT, params->selection, + OTG_CRC_EN, 1); + + return true; +} + +/** + * optc1_get_crc - Capture CRC result per component + * + * @optc: timing_generator instance. + * @r_cr: 16-bit primary CRC signature for red data. + * @g_y: 16-bit primary CRC signature for green data. + * @b_cb: 16-bit primary CRC signature for blue data. + * + * This function reads the CRC signature from the OPTC registers. Notice that + * we have three registers to keep the CRC result per color component (RGB). + * + * Returns: + * If CRC is disabled, return false; otherwise, return true, and the CRC + * results in the parameters. + */ +bool optc1_get_crc(struct timing_generator *optc, + uint32_t *r_cr, uint32_t *g_y, uint32_t *b_cb) +{ + uint32_t field = 0; + struct optc *optc1 = DCN10TG_FROM_TG(optc); + + REG_GET(OTG_CRC_CNTL, OTG_CRC_EN, &field); + + /* Early return if CRC is not enabled for this CRTC */ + if (!field) + return false; + + /* OTG_CRC0_DATA_RG has the CRC16 results for the red and green component */ + REG_GET_2(OTG_CRC0_DATA_RG, + CRC0_R_CR, r_cr, + CRC0_G_Y, g_y); + + /* OTG_CRC0_DATA_B has the CRC16 results for the blue component */ + REG_GET(OTG_CRC0_DATA_B, + CRC0_B_CB, b_cb); + + return true; +} + +static const struct timing_generator_funcs dcn10_tg_funcs = { + .validate_timing = optc1_validate_timing, + .program_timing = optc1_program_timing, + .setup_vertical_interrupt0 = optc1_setup_vertical_interrupt0, + .setup_vertical_interrupt1 = optc1_setup_vertical_interrupt1, + .setup_vertical_interrupt2 = optc1_setup_vertical_interrupt2, + .program_global_sync = optc1_program_global_sync, + .enable_crtc = optc1_enable_crtc, + .disable_crtc = optc1_disable_crtc, + /* used by enable_timing_synchronization. Not need for FPGA */ + .is_counter_moving = optc1_is_counter_moving, + .get_position = optc1_get_position, + .get_frame_count = optc1_get_vblank_counter, + .get_scanoutpos = optc1_get_crtc_scanoutpos, + .get_otg_active_size = optc1_get_otg_active_size, + .set_early_control = optc1_set_early_control, + /* used by enable_timing_synchronization. Not need for FPGA */ + .wait_for_state = optc1_wait_for_state, + .set_blank = optc1_set_blank, + .is_blanked = optc1_is_blanked, + .set_blank_color = optc1_program_blank_color, + .did_triggered_reset_occur = optc1_did_triggered_reset_occur, + .enable_reset_trigger = optc1_enable_reset_trigger, + .enable_crtc_reset = optc1_enable_crtc_reset, + .disable_reset_trigger = optc1_disable_reset_trigger, + .lock = optc1_lock, + .unlock = optc1_unlock, + .enable_optc_clock = optc1_enable_optc_clock, + .set_drr = optc1_set_drr, + .get_last_used_drr_vtotal = NULL, + .set_vtotal_min_max = optc1_set_vtotal_min_max, + .set_static_screen_control = optc1_set_static_screen_control, + .set_test_pattern = optc1_set_test_pattern, + .program_stereo = optc1_program_stereo, + .is_stereo_left_eye = optc1_is_stereo_left_eye, + .set_blank_data_double_buffer = optc1_set_blank_data_double_buffer, + .tg_init = optc1_tg_init, + .is_tg_enabled = optc1_is_tg_enabled, + .is_optc_underflow_occurred = optc1_is_optc_underflow_occurred, + .clear_optc_underflow = optc1_clear_optc_underflow, + .get_crc = optc1_get_crc, + .configure_crc = optc1_configure_crc, + .set_vtg_params = optc1_set_vtg_params, + .program_manual_trigger = optc1_program_manual_trigger, + .setup_manual_trigger = optc1_setup_manual_trigger, + .get_hw_timing = optc1_get_hw_timing, +}; + +void dcn10_timing_generator_init(struct optc *optc1) +{ + optc1->base.funcs = &dcn10_tg_funcs; + + optc1->max_h_total = optc1->tg_mask->OTG_H_TOTAL + 1; + optc1->max_v_total = optc1->tg_mask->OTG_V_TOTAL + 1; + + optc1->min_h_blank = 32; + optc1->min_v_blank = 3; + optc1->min_v_blank_interlace = 5; + optc1->min_h_sync_width = 4; + optc1->min_v_sync_width = 1; +} + +/* "Containter" vs. "pixel" is a concept within HW blocks, mostly those closer to the back-end. It works like this: + * + * - In most of the formats (RGB or YCbCr 4:4:4, 4:2:2 uncompressed and DSC 4:2:2 Simple) pixel rate is the same as + * containter rate. + * + * - In 4:2:0 (DSC or uncompressed) there are two pixels per container, hence the target container rate has to be + * halved to maintain the correct pixel rate. + * + * - Unlike 4:2:2 uncompressed, DSC 4:2:2 Native also has two pixels per container (this happens when DSC is applied + * to it) and has to be treated the same as 4:2:0, i.e. target containter rate has to be halved in this case as well. + * + */ +bool optc1_is_two_pixels_per_containter(const struct dc_crtc_timing *timing) +{ + bool two_pix = timing->pixel_encoding == PIXEL_ENCODING_YCBCR420; + + two_pix = two_pix || (timing->flags.DSC && timing->pixel_encoding == PIXEL_ENCODING_YCBCR422 + && !timing->dsc_cfg.ycbcr422_simple); + return two_pix; +} + diff --git a/drivers/gpu/drm/amd/display/dc/optc/dcn10/dcn10_optc.h b/drivers/gpu/drm/amd/display/dc/optc/dcn10/dcn10_optc.h new file mode 100644 index 000000000000..ab81594a7fad --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/optc/dcn10/dcn10_optc.h @@ -0,0 +1,599 @@ +/* + * Copyright 2012-15 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_TIMING_GENERATOR_DCN10_H__ +#define __DC_TIMING_GENERATOR_DCN10_H__ + +#include "optc.h" + +#define DCN10TG_FROM_TG(tg)\ + container_of(tg, struct optc, base) + +#define TG_COMMON_REG_LIST_DCN(inst) \ + SRI(OTG_VSTARTUP_PARAM, OTG, inst),\ + SRI(OTG_VUPDATE_PARAM, OTG, inst),\ + SRI(OTG_VREADY_PARAM, OTG, inst),\ + SRI(OTG_BLANK_CONTROL, OTG, inst),\ + SRI(OTG_MASTER_UPDATE_LOCK, OTG, inst),\ + SRI(OTG_GLOBAL_CONTROL0, OTG, inst),\ + SRI(OTG_DOUBLE_BUFFER_CONTROL, OTG, inst),\ + SRI(OTG_H_TOTAL, OTG, inst),\ + SRI(OTG_H_BLANK_START_END, OTG, inst),\ + SRI(OTG_H_SYNC_A, OTG, inst),\ + SRI(OTG_H_SYNC_A_CNTL, OTG, inst),\ + SRI(OTG_H_TIMING_CNTL, OTG, inst),\ + SRI(OTG_V_TOTAL, OTG, inst),\ + SRI(OTG_V_BLANK_START_END, OTG, inst),\ + SRI(OTG_V_SYNC_A, OTG, inst),\ + SRI(OTG_V_SYNC_A_CNTL, OTG, inst),\ + SRI(OTG_INTERLACE_CONTROL, OTG, inst),\ + SRI(OTG_CONTROL, OTG, inst),\ + SRI(OTG_STEREO_CONTROL, OTG, inst),\ + SRI(OTG_3D_STRUCTURE_CONTROL, OTG, inst),\ + SRI(OTG_STEREO_STATUS, OTG, inst),\ + SRI(OTG_V_TOTAL_MAX, OTG, inst),\ + SRI(OTG_V_TOTAL_MID, OTG, inst),\ + SRI(OTG_V_TOTAL_MIN, OTG, inst),\ + SRI(OTG_V_TOTAL_CONTROL, OTG, inst),\ + SRI(OTG_TRIGA_CNTL, OTG, inst),\ + SRI(OTG_FORCE_COUNT_NOW_CNTL, OTG, inst),\ + SRI(OTG_STATIC_SCREEN_CONTROL, OTG, inst),\ + SRI(OTG_STATUS_FRAME_COUNT, OTG, inst),\ + SRI(OTG_STATUS, OTG, inst),\ + SRI(OTG_STATUS_POSITION, OTG, inst),\ + SRI(OTG_NOM_VERT_POSITION, OTG, inst),\ + SRI(OTG_BLACK_COLOR, OTG, inst),\ + SRI(OTG_CLOCK_CONTROL, OTG, inst),\ + SRI(OTG_VERTICAL_INTERRUPT0_CONTROL, OTG, inst),\ + SRI(OTG_VERTICAL_INTERRUPT0_POSITION, OTG, inst),\ + SRI(OTG_VERTICAL_INTERRUPT1_CONTROL, OTG, inst),\ + SRI(OTG_VERTICAL_INTERRUPT1_POSITION, OTG, inst),\ + SRI(OTG_VERTICAL_INTERRUPT2_CONTROL, OTG, inst),\ + SRI(OTG_VERTICAL_INTERRUPT2_POSITION, OTG, inst),\ + SRI(OPTC_INPUT_CLOCK_CONTROL, ODM, inst),\ + SRI(OPTC_DATA_SOURCE_SELECT, ODM, inst),\ + SRI(OPTC_INPUT_GLOBAL_CONTROL, ODM, inst),\ + SRI(CONTROL, VTG, inst),\ + SRI(OTG_VERT_SYNC_CONTROL, OTG, inst),\ + SRI(OTG_MASTER_UPDATE_MODE, OTG, inst),\ + SRI(OTG_GSL_CONTROL, OTG, inst),\ + SRI(OTG_CRC_CNTL, OTG, inst),\ + SRI(OTG_CRC0_DATA_RG, OTG, inst),\ + SRI(OTG_CRC0_DATA_B, OTG, inst),\ + SRI(OTG_CRC0_WINDOWA_X_CONTROL, OTG, inst),\ + SRI(OTG_CRC0_WINDOWA_Y_CONTROL, OTG, inst),\ + SRI(OTG_CRC0_WINDOWB_X_CONTROL, OTG, inst),\ + SRI(OTG_CRC0_WINDOWB_Y_CONTROL, OTG, inst),\ + SR(GSL_SOURCE_SELECT),\ + SRI(OTG_GLOBAL_CONTROL2, OTG, inst),\ + SRI(OTG_TRIGA_MANUAL_TRIG, OTG, inst) + +#define TG_COMMON_REG_LIST_DCN1_0(inst) \ + TG_COMMON_REG_LIST_DCN(inst),\ + SRI(OTG_TEST_PATTERN_PARAMETERS, OTG, inst),\ + SRI(OTG_TEST_PATTERN_CONTROL, OTG, inst),\ + SRI(OTG_TEST_PATTERN_COLOR, OTG, inst),\ + SRI(OTG_MANUAL_FLOW_CONTROL, OTG, inst) + + +struct dcn_optc_registers { + uint32_t OTG_GLOBAL_CONTROL1; + uint32_t OTG_GLOBAL_CONTROL2; + uint32_t OTG_VERT_SYNC_CONTROL; + uint32_t OTG_MASTER_UPDATE_MODE; + uint32_t OTG_GSL_CONTROL; + uint32_t OTG_VSTARTUP_PARAM; + uint32_t OTG_VUPDATE_PARAM; + uint32_t OTG_VREADY_PARAM; + uint32_t OTG_BLANK_CONTROL; + uint32_t OTG_MASTER_UPDATE_LOCK; + uint32_t OTG_GLOBAL_CONTROL0; + uint32_t OTG_DOUBLE_BUFFER_CONTROL; + uint32_t OTG_H_TOTAL; + uint32_t OTG_H_BLANK_START_END; + uint32_t OTG_H_SYNC_A; + uint32_t OTG_H_SYNC_A_CNTL; + uint32_t OTG_H_TIMING_CNTL; + uint32_t OTG_V_TOTAL; + uint32_t OTG_V_BLANK_START_END; + uint32_t OTG_V_SYNC_A; + uint32_t OTG_V_SYNC_A_CNTL; + uint32_t OTG_INTERLACE_CONTROL; + uint32_t OTG_CONTROL; + uint32_t OTG_STEREO_CONTROL; + uint32_t OTG_3D_STRUCTURE_CONTROL; + uint32_t OTG_STEREO_STATUS; + uint32_t OTG_V_TOTAL_MAX; + uint32_t OTG_V_TOTAL_MID; + uint32_t OTG_V_TOTAL_MIN; + uint32_t OTG_V_TOTAL_CONTROL; + uint32_t OTG_TRIGA_CNTL; + uint32_t OTG_TRIGA_MANUAL_TRIG; + uint32_t OTG_MANUAL_FLOW_CONTROL; + uint32_t OTG_FORCE_COUNT_NOW_CNTL; + uint32_t OTG_STATIC_SCREEN_CONTROL; + uint32_t OTG_STATUS_FRAME_COUNT; + uint32_t OTG_STATUS; + uint32_t OTG_STATUS_POSITION; + uint32_t OTG_NOM_VERT_POSITION; + uint32_t OTG_BLACK_COLOR; + uint32_t OTG_TEST_PATTERN_PARAMETERS; + uint32_t OTG_TEST_PATTERN_CONTROL; + uint32_t OTG_TEST_PATTERN_COLOR; + uint32_t OTG_CLOCK_CONTROL; + uint32_t OTG_VERTICAL_INTERRUPT0_CONTROL; + uint32_t OTG_VERTICAL_INTERRUPT0_POSITION; + uint32_t OTG_VERTICAL_INTERRUPT1_CONTROL; + uint32_t OTG_VERTICAL_INTERRUPT1_POSITION; + uint32_t OTG_VERTICAL_INTERRUPT2_CONTROL; + uint32_t OTG_VERTICAL_INTERRUPT2_POSITION; + uint32_t OPTC_INPUT_CLOCK_CONTROL; + uint32_t OPTC_DATA_SOURCE_SELECT; + uint32_t OPTC_MEMORY_CONFIG; + uint32_t OPTC_INPUT_GLOBAL_CONTROL; + uint32_t CONTROL; + uint32_t OTG_GSL_WINDOW_X; + uint32_t OTG_GSL_WINDOW_Y; + uint32_t OTG_VUPDATE_KEEPOUT; + uint32_t OTG_CRC_CNTL; + uint32_t OTG_CRC_CNTL2; + uint32_t OTG_CRC0_DATA_RG; + uint32_t OTG_CRC0_DATA_B; + uint32_t OTG_CRC1_DATA_B; + uint32_t OTG_CRC2_DATA_B; + uint32_t OTG_CRC3_DATA_B; + uint32_t OTG_CRC1_DATA_RG; + uint32_t OTG_CRC2_DATA_RG; + uint32_t OTG_CRC3_DATA_RG; + uint32_t OTG_CRC0_WINDOWA_X_CONTROL; + uint32_t OTG_CRC0_WINDOWA_Y_CONTROL; + uint32_t OTG_CRC0_WINDOWB_X_CONTROL; + uint32_t OTG_CRC0_WINDOWB_Y_CONTROL; + uint32_t OTG_CRC1_WINDOWA_X_CONTROL; + uint32_t OTG_CRC1_WINDOWA_Y_CONTROL; + uint32_t OTG_CRC1_WINDOWB_X_CONTROL; + uint32_t OTG_CRC1_WINDOWB_Y_CONTROL; + uint32_t GSL_SOURCE_SELECT; + uint32_t DWB_SOURCE_SELECT; + uint32_t OTG_DSC_START_POSITION; + uint32_t OPTC_DATA_FORMAT_CONTROL; + uint32_t OPTC_BYTES_PER_PIXEL; + uint32_t OPTC_WIDTH_CONTROL; + uint32_t OTG_DRR_CONTROL; + uint32_t OTG_BLANK_DATA_COLOR; + uint32_t OTG_BLANK_DATA_COLOR_EXT; + uint32_t OTG_DRR_TRIGGER_WINDOW; + uint32_t OTG_M_CONST_DTO0; + uint32_t OTG_M_CONST_DTO1; + uint32_t OTG_DRR_V_TOTAL_CHANGE; + uint32_t OTG_GLOBAL_CONTROL4; + uint32_t OTG_CRC0_WINDOWA_X_CONTROL_READBACK; + uint32_t OTG_CRC0_WINDOWA_Y_CONTROL_READBACK; + uint32_t OTG_CRC0_WINDOWB_X_CONTROL_READBACK; + uint32_t OTG_CRC0_WINDOWB_Y_CONTROL_READBACK; + uint32_t OTG_CRC1_WINDOWA_X_CONTROL_READBACK; + uint32_t OTG_CRC1_WINDOWA_Y_CONTROL_READBACK; + uint32_t OTG_CRC1_WINDOWB_X_CONTROL_READBACK; + uint32_t OTG_CRC1_WINDOWB_Y_CONTROL_READBACK; + uint32_t OPTC_CLOCK_CONTROL; +}; + +#define TG_COMMON_MASK_SH_LIST_DCN(mask_sh)\ + SF(OTG0_OTG_VSTARTUP_PARAM, VSTARTUP_START, mask_sh),\ + SF(OTG0_OTG_VUPDATE_PARAM, VUPDATE_OFFSET, mask_sh),\ + SF(OTG0_OTG_VUPDATE_PARAM, VUPDATE_WIDTH, mask_sh),\ + SF(OTG0_OTG_VREADY_PARAM, VREADY_OFFSET, mask_sh),\ + SF(OTG0_OTG_BLANK_CONTROL, OTG_BLANK_DATA_EN, mask_sh),\ + SF(OTG0_OTG_BLANK_CONTROL, OTG_BLANK_DE_MODE, mask_sh),\ + SF(OTG0_OTG_BLANK_CONTROL, OTG_CURRENT_BLANK_STATE, mask_sh),\ + SF(OTG0_OTG_MASTER_UPDATE_LOCK, OTG_MASTER_UPDATE_LOCK, mask_sh),\ + SF(OTG0_OTG_MASTER_UPDATE_LOCK, UPDATE_LOCK_STATUS, mask_sh),\ + SF(OTG0_OTG_GLOBAL_CONTROL0, OTG_MASTER_UPDATE_LOCK_SEL, mask_sh),\ + SF(OTG0_OTG_DOUBLE_BUFFER_CONTROL, OTG_UPDATE_PENDING, mask_sh),\ + SF(OTG0_OTG_DOUBLE_BUFFER_CONTROL, OTG_BLANK_DATA_DOUBLE_BUFFER_EN, mask_sh),\ + SF(OTG0_OTG_DOUBLE_BUFFER_CONTROL, OTG_RANGE_TIMING_DBUF_UPDATE_MODE, mask_sh),\ + SF(OTG0_OTG_VUPDATE_KEEPOUT, OTG_MASTER_UPDATE_LOCK_VUPDATE_KEEPOUT_EN, mask_sh), \ + SF(OTG0_OTG_VUPDATE_KEEPOUT, MASTER_UPDATE_LOCK_VUPDATE_KEEPOUT_START_OFFSET, mask_sh), \ + SF(OTG0_OTG_VUPDATE_KEEPOUT, MASTER_UPDATE_LOCK_VUPDATE_KEEPOUT_END_OFFSET, mask_sh), \ + SF(OTG0_OTG_H_TOTAL, OTG_H_TOTAL, mask_sh),\ + SF(OTG0_OTG_H_BLANK_START_END, OTG_H_BLANK_START, mask_sh),\ + SF(OTG0_OTG_H_BLANK_START_END, OTG_H_BLANK_END, mask_sh),\ + SF(OTG0_OTG_H_SYNC_A, OTG_H_SYNC_A_START, mask_sh),\ + SF(OTG0_OTG_H_SYNC_A, OTG_H_SYNC_A_END, mask_sh),\ + SF(OTG0_OTG_H_SYNC_A_CNTL, OTG_H_SYNC_A_POL, mask_sh),\ + SF(OTG0_OTG_H_TIMING_CNTL, OTG_H_TIMING_DIV_BY2, mask_sh),\ + SF(OTG0_OTG_V_TOTAL, OTG_V_TOTAL, mask_sh),\ + SF(OTG0_OTG_V_BLANK_START_END, OTG_V_BLANK_START, mask_sh),\ + SF(OTG0_OTG_V_BLANK_START_END, OTG_V_BLANK_END, mask_sh),\ + SF(OTG0_OTG_V_SYNC_A, OTG_V_SYNC_A_START, mask_sh),\ + SF(OTG0_OTG_V_SYNC_A, OTG_V_SYNC_A_END, mask_sh),\ + SF(OTG0_OTG_V_SYNC_A_CNTL, OTG_V_SYNC_A_POL, mask_sh),\ + SF(OTG0_OTG_INTERLACE_CONTROL, OTG_INTERLACE_ENABLE, mask_sh),\ + SF(OTG0_OTG_CONTROL, OTG_MASTER_EN, mask_sh),\ + SF(OTG0_OTG_CONTROL, OTG_START_POINT_CNTL, mask_sh),\ + SF(OTG0_OTG_CONTROL, OTG_DISABLE_POINT_CNTL, mask_sh),\ + SF(OTG0_OTG_CONTROL, OTG_FIELD_NUMBER_CNTL, mask_sh),\ + SF(OTG0_OTG_CONTROL, OTG_CURRENT_MASTER_EN_STATE, mask_sh),\ + SF(OTG0_OTG_STEREO_CONTROL, OTG_STEREO_EN, mask_sh),\ + SF(OTG0_OTG_STEREO_CONTROL, OTG_STEREO_SYNC_OUTPUT_LINE_NUM, mask_sh),\ + SF(OTG0_OTG_STEREO_CONTROL, OTG_STEREO_SYNC_OUTPUT_POLARITY, mask_sh),\ + SF(OTG0_OTG_STEREO_CONTROL, OTG_STEREO_EYE_FLAG_POLARITY, mask_sh),\ + SF(OTG0_OTG_STEREO_CONTROL, OTG_DISABLE_STEREOSYNC_OUTPUT_FOR_DP, mask_sh),\ + SF(OTG0_OTG_STEREO_CONTROL, OTG_DISABLE_STEREOSYNC_OUTPUT_FOR_DP, mask_sh),\ + SF(OTG0_OTG_STEREO_STATUS, OTG_STEREO_CURRENT_EYE, mask_sh),\ + SF(OTG0_OTG_3D_STRUCTURE_CONTROL, OTG_3D_STRUCTURE_EN, mask_sh),\ + SF(OTG0_OTG_3D_STRUCTURE_CONTROL, OTG_3D_STRUCTURE_V_UPDATE_MODE, mask_sh),\ + SF(OTG0_OTG_3D_STRUCTURE_CONTROL, OTG_3D_STRUCTURE_STEREO_SEL_OVR, mask_sh),\ + SF(OTG0_OTG_V_TOTAL_MAX, OTG_V_TOTAL_MAX, mask_sh),\ + SF(OTG0_OTG_V_TOTAL_MID, OTG_V_TOTAL_MID, mask_sh),\ + SF(OTG0_OTG_V_TOTAL_MIN, OTG_V_TOTAL_MIN, mask_sh),\ + SF(OTG0_OTG_V_TOTAL_CONTROL, OTG_V_TOTAL_MIN_SEL, mask_sh),\ + SF(OTG0_OTG_V_TOTAL_CONTROL, OTG_V_TOTAL_MAX_SEL, mask_sh),\ + SF(OTG0_OTG_V_TOTAL_CONTROL, OTG_FORCE_LOCK_ON_EVENT, mask_sh),\ + SF(OTG0_OTG_V_TOTAL_CONTROL, OTG_SET_V_TOTAL_MIN_MASK_EN, mask_sh),\ + SF(OTG0_OTG_V_TOTAL_CONTROL, OTG_SET_V_TOTAL_MIN_MASK, mask_sh),\ + SF(OTG0_OTG_V_TOTAL_CONTROL, OTG_VTOTAL_MID_REPLACING_MAX_EN, mask_sh),\ + SF(OTG0_OTG_V_TOTAL_CONTROL, OTG_VTOTAL_MID_FRAME_NUM, mask_sh),\ + SF(OTG0_OTG_FORCE_COUNT_NOW_CNTL, OTG_FORCE_COUNT_NOW_CLEAR, mask_sh),\ + SF(OTG0_OTG_FORCE_COUNT_NOW_CNTL, OTG_FORCE_COUNT_NOW_MODE, mask_sh),\ + SF(OTG0_OTG_FORCE_COUNT_NOW_CNTL, OTG_FORCE_COUNT_NOW_OCCURRED, mask_sh),\ + SF(OTG0_OTG_TRIGA_CNTL, OTG_TRIGA_SOURCE_SELECT, mask_sh),\ + SF(OTG0_OTG_TRIGA_CNTL, OTG_TRIGA_SOURCE_PIPE_SELECT, mask_sh),\ + SF(OTG0_OTG_TRIGA_CNTL, OTG_TRIGA_RISING_EDGE_DETECT_CNTL, mask_sh),\ + SF(OTG0_OTG_TRIGA_CNTL, OTG_TRIGA_FALLING_EDGE_DETECT_CNTL, mask_sh),\ + SF(OTG0_OTG_TRIGA_CNTL, OTG_TRIGA_POLARITY_SELECT, mask_sh),\ + SF(OTG0_OTG_TRIGA_CNTL, OTG_TRIGA_FREQUENCY_SELECT, mask_sh),\ + SF(OTG0_OTG_TRIGA_CNTL, OTG_TRIGA_DELAY, mask_sh),\ + SF(OTG0_OTG_TRIGA_CNTL, OTG_TRIGA_CLEAR, mask_sh),\ + SF(OTG0_OTG_TRIGA_MANUAL_TRIG, OTG_TRIGA_MANUAL_TRIG, mask_sh),\ + SF(OTG0_OTG_STATIC_SCREEN_CONTROL, OTG_STATIC_SCREEN_EVENT_MASK, mask_sh),\ + SF(OTG0_OTG_STATIC_SCREEN_CONTROL, OTG_STATIC_SCREEN_FRAME_COUNT, mask_sh),\ + SF(OTG0_OTG_STATUS_FRAME_COUNT, OTG_FRAME_COUNT, mask_sh),\ + SF(OTG0_OTG_STATUS, OTG_V_BLANK, mask_sh),\ + SF(OTG0_OTG_STATUS, OTG_V_ACTIVE_DISP, mask_sh),\ + SF(OTG0_OTG_STATUS_POSITION, OTG_HORZ_COUNT, mask_sh),\ + SF(OTG0_OTG_STATUS_POSITION, OTG_VERT_COUNT, mask_sh),\ + SF(OTG0_OTG_NOM_VERT_POSITION, OTG_VERT_COUNT_NOM, mask_sh),\ + SF(OTG0_OTG_BLACK_COLOR, OTG_BLACK_COLOR_B_CB, mask_sh),\ + SF(OTG0_OTG_BLACK_COLOR, OTG_BLACK_COLOR_G_Y, mask_sh),\ + SF(OTG0_OTG_BLACK_COLOR, OTG_BLACK_COLOR_R_CR, mask_sh),\ + SF(OTG0_OTG_CLOCK_CONTROL, OTG_BUSY, mask_sh),\ + SF(OTG0_OTG_CLOCK_CONTROL, OTG_CLOCK_EN, mask_sh),\ + SF(OTG0_OTG_CLOCK_CONTROL, OTG_CLOCK_ON, mask_sh),\ + SF(OTG0_OTG_CLOCK_CONTROL, OTG_CLOCK_GATE_DIS, mask_sh),\ + SF(OTG0_OTG_VERTICAL_INTERRUPT0_CONTROL, OTG_VERTICAL_INTERRUPT0_INT_ENABLE, mask_sh),\ + SF(OTG0_OTG_VERTICAL_INTERRUPT0_POSITION, OTG_VERTICAL_INTERRUPT0_LINE_START, mask_sh),\ + SF(OTG0_OTG_VERTICAL_INTERRUPT0_POSITION, OTG_VERTICAL_INTERRUPT0_LINE_END, mask_sh),\ + SF(OTG0_OTG_VERTICAL_INTERRUPT1_CONTROL, OTG_VERTICAL_INTERRUPT1_INT_ENABLE, mask_sh),\ + SF(OTG0_OTG_VERTICAL_INTERRUPT1_POSITION, OTG_VERTICAL_INTERRUPT1_LINE_START, mask_sh),\ + SF(OTG0_OTG_VERTICAL_INTERRUPT2_CONTROL, OTG_VERTICAL_INTERRUPT2_INT_ENABLE, mask_sh),\ + SF(OTG0_OTG_VERTICAL_INTERRUPT2_POSITION, OTG_VERTICAL_INTERRUPT2_LINE_START, mask_sh),\ + SF(ODM0_OPTC_INPUT_CLOCK_CONTROL, OPTC_INPUT_CLK_EN, mask_sh),\ + SF(ODM0_OPTC_INPUT_CLOCK_CONTROL, OPTC_INPUT_CLK_ON, mask_sh),\ + SF(ODM0_OPTC_INPUT_CLOCK_CONTROL, OPTC_INPUT_CLK_GATE_DIS, mask_sh),\ + SF(ODM0_OPTC_INPUT_GLOBAL_CONTROL, OPTC_UNDERFLOW_OCCURRED_STATUS, mask_sh),\ + SF(ODM0_OPTC_INPUT_GLOBAL_CONTROL, OPTC_UNDERFLOW_CLEAR, mask_sh),\ + SF(VTG0_CONTROL, VTG0_ENABLE, mask_sh),\ + SF(VTG0_CONTROL, VTG0_FP2, mask_sh),\ + SF(VTG0_CONTROL, VTG0_VCOUNT_INIT, mask_sh),\ + SF(OTG0_OTG_VERT_SYNC_CONTROL, OTG_FORCE_VSYNC_NEXT_LINE_OCCURRED, mask_sh),\ + SF(OTG0_OTG_VERT_SYNC_CONTROL, OTG_FORCE_VSYNC_NEXT_LINE_CLEAR, mask_sh),\ + SF(OTG0_OTG_VERT_SYNC_CONTROL, OTG_AUTO_FORCE_VSYNC_MODE, mask_sh),\ + SF(OTG0_OTG_MASTER_UPDATE_MODE, MASTER_UPDATE_INTERLACED_MODE, mask_sh),\ + SF(OTG0_OTG_GSL_CONTROL, OTG_GSL0_EN, mask_sh),\ + SF(OTG0_OTG_GSL_CONTROL, OTG_GSL1_EN, mask_sh),\ + SF(OTG0_OTG_GSL_CONTROL, OTG_GSL2_EN, mask_sh),\ + SF(OTG0_OTG_GSL_CONTROL, OTG_GSL_MASTER_EN, mask_sh),\ + SF(OTG0_OTG_GSL_CONTROL, OTG_GSL_FORCE_DELAY, mask_sh),\ + SF(OTG0_OTG_GSL_CONTROL, OTG_GSL_CHECK_ALL_FIELDS, mask_sh),\ + SF(OTG0_OTG_CRC_CNTL, OTG_CRC_CONT_EN, mask_sh),\ + SF(OTG0_OTG_CRC_CNTL, OTG_CRC0_SELECT, mask_sh),\ + SF(OTG0_OTG_CRC_CNTL, OTG_CRC_EN, mask_sh),\ + SF(OTG0_OTG_CRC0_DATA_RG, CRC0_R_CR, mask_sh),\ + SF(OTG0_OTG_CRC0_DATA_RG, CRC0_G_Y, mask_sh),\ + SF(OTG0_OTG_CRC0_DATA_B, CRC0_B_CB, mask_sh),\ + SF(OTG0_OTG_CRC0_WINDOWA_X_CONTROL, OTG_CRC0_WINDOWA_X_START, mask_sh),\ + SF(OTG0_OTG_CRC0_WINDOWA_X_CONTROL, OTG_CRC0_WINDOWA_X_END, mask_sh),\ + SF(OTG0_OTG_CRC0_WINDOWA_Y_CONTROL, OTG_CRC0_WINDOWA_Y_START, mask_sh),\ + SF(OTG0_OTG_CRC0_WINDOWA_Y_CONTROL, OTG_CRC0_WINDOWA_Y_END, mask_sh),\ + SF(OTG0_OTG_CRC0_WINDOWB_X_CONTROL, OTG_CRC0_WINDOWB_X_START, mask_sh),\ + SF(OTG0_OTG_CRC0_WINDOWB_X_CONTROL, OTG_CRC0_WINDOWB_X_END, mask_sh),\ + SF(OTG0_OTG_CRC0_WINDOWB_Y_CONTROL, OTG_CRC0_WINDOWB_Y_START, mask_sh),\ + SF(OTG0_OTG_CRC0_WINDOWB_Y_CONTROL, OTG_CRC0_WINDOWB_Y_END, mask_sh),\ + SF(GSL_SOURCE_SELECT, GSL0_READY_SOURCE_SEL, mask_sh),\ + SF(GSL_SOURCE_SELECT, GSL1_READY_SOURCE_SEL, mask_sh),\ + SF(GSL_SOURCE_SELECT, GSL2_READY_SOURCE_SEL, mask_sh),\ + SF(OTG0_OTG_GLOBAL_CONTROL2, MANUAL_FLOW_CONTROL_SEL, mask_sh) + + + +#define TG_COMMON_MASK_SH_LIST_DCN1_0(mask_sh)\ + TG_COMMON_MASK_SH_LIST_DCN(mask_sh),\ + SF(OTG0_OTG_TEST_PATTERN_PARAMETERS, OTG_TEST_PATTERN_INC0, mask_sh),\ + SF(OTG0_OTG_TEST_PATTERN_PARAMETERS, OTG_TEST_PATTERN_INC1, mask_sh),\ + SF(OTG0_OTG_TEST_PATTERN_PARAMETERS, OTG_TEST_PATTERN_VRES, mask_sh),\ + SF(OTG0_OTG_TEST_PATTERN_PARAMETERS, OTG_TEST_PATTERN_HRES, mask_sh),\ + SF(OTG0_OTG_TEST_PATTERN_PARAMETERS, OTG_TEST_PATTERN_RAMP0_OFFSET, mask_sh),\ + SF(OTG0_OTG_TEST_PATTERN_CONTROL, OTG_TEST_PATTERN_EN, mask_sh),\ + SF(OTG0_OTG_TEST_PATTERN_CONTROL, OTG_TEST_PATTERN_MODE, mask_sh),\ + SF(OTG0_OTG_TEST_PATTERN_CONTROL, OTG_TEST_PATTERN_DYNAMIC_RANGE, mask_sh),\ + SF(OTG0_OTG_TEST_PATTERN_CONTROL, OTG_TEST_PATTERN_COLOR_FORMAT, mask_sh),\ + SF(OTG0_OTG_TEST_PATTERN_COLOR, OTG_TEST_PATTERN_MASK, mask_sh),\ + SF(OTG0_OTG_TEST_PATTERN_COLOR, OTG_TEST_PATTERN_DATA, mask_sh),\ + SF(ODM0_OPTC_DATA_SOURCE_SELECT, OPTC_SRC_SEL, mask_sh),\ + SF(OTG0_OTG_MANUAL_FLOW_CONTROL, MANUAL_FLOW_CONTROL, mask_sh),\ + +#define TG_REG_FIELD_LIST_DCN1_0(type) \ + type VSTARTUP_START;\ + type VUPDATE_OFFSET;\ + type VUPDATE_WIDTH;\ + type VREADY_OFFSET;\ + type OTG_BLANK_DATA_EN;\ + type OTG_BLANK_DE_MODE;\ + type OTG_CURRENT_BLANK_STATE;\ + type OTG_MASTER_UPDATE_LOCK;\ + type UPDATE_LOCK_STATUS;\ + type OTG_UPDATE_PENDING;\ + type OTG_MASTER_UPDATE_LOCK_SEL;\ + type OTG_BLANK_DATA_DOUBLE_BUFFER_EN;\ + type OTG_H_TOTAL;\ + type OTG_H_BLANK_START;\ + type OTG_H_BLANK_END;\ + type OTG_H_SYNC_A_START;\ + type OTG_H_SYNC_A_END;\ + type OTG_H_SYNC_A_POL;\ + type OTG_H_TIMING_DIV_BY2;\ + type OTG_V_TOTAL;\ + type OTG_V_BLANK_START;\ + type OTG_V_BLANK_END;\ + type OTG_V_SYNC_A_START;\ + type OTG_V_SYNC_A_END;\ + type OTG_V_SYNC_A_POL;\ + type OTG_INTERLACE_ENABLE;\ + type OTG_MASTER_EN;\ + type OTG_START_POINT_CNTL;\ + type OTG_DISABLE_POINT_CNTL;\ + type OTG_FIELD_NUMBER_CNTL;\ + type OTG_CURRENT_MASTER_EN_STATE;\ + type OTG_STEREO_EN;\ + type OTG_STEREO_SYNC_OUTPUT_LINE_NUM;\ + type OTG_STEREO_SYNC_OUTPUT_POLARITY;\ + type OTG_STEREO_EYE_FLAG_POLARITY;\ + type OTG_STEREO_CURRENT_EYE;\ + type OTG_DISABLE_STEREOSYNC_OUTPUT_FOR_DP;\ + type OTG_3D_STRUCTURE_EN;\ + type OTG_3D_STRUCTURE_V_UPDATE_MODE;\ + type OTG_3D_STRUCTURE_STEREO_SEL_OVR;\ + type OTG_V_TOTAL_MAX;\ + type OTG_V_TOTAL_MID;\ + type OTG_V_TOTAL_MIN;\ + type OTG_V_TOTAL_MIN_SEL;\ + type OTG_V_TOTAL_MAX_SEL;\ + type OTG_VTOTAL_MID_REPLACING_MAX_EN;\ + type OTG_VTOTAL_MID_FRAME_NUM;\ + type OTG_FORCE_LOCK_ON_EVENT;\ + type OTG_SET_V_TOTAL_MIN_MASK_EN;\ + type OTG_SET_V_TOTAL_MIN_MASK;\ + type OTG_FORCE_COUNT_NOW_CLEAR;\ + type OTG_FORCE_COUNT_NOW_MODE;\ + type OTG_FORCE_COUNT_NOW_OCCURRED;\ + type OTG_TRIGA_SOURCE_SELECT;\ + type OTG_TRIGA_SOURCE_PIPE_SELECT;\ + type OTG_TRIGA_RISING_EDGE_DETECT_CNTL;\ + type OTG_TRIGA_FALLING_EDGE_DETECT_CNTL;\ + type OTG_TRIGA_POLARITY_SELECT;\ + type OTG_TRIGA_FREQUENCY_SELECT;\ + type OTG_TRIGA_DELAY;\ + type OTG_TRIGA_CLEAR;\ + type OTG_TRIGA_MANUAL_TRIG;\ + type OTG_STATIC_SCREEN_EVENT_MASK;\ + type OTG_STATIC_SCREEN_FRAME_COUNT;\ + type OTG_FRAME_COUNT;\ + type OTG_V_BLANK;\ + type OTG_V_ACTIVE_DISP;\ + type OTG_HORZ_COUNT;\ + type OTG_VERT_COUNT;\ + type OTG_VERT_COUNT_NOM;\ + type OTG_BLACK_COLOR_B_CB;\ + type OTG_BLACK_COLOR_G_Y;\ + type OTG_BLACK_COLOR_R_CR;\ + type OTG_BLANK_DATA_COLOR_BLUE_CB;\ + type OTG_BLANK_DATA_COLOR_GREEN_Y;\ + type OTG_BLANK_DATA_COLOR_RED_CR;\ + type OTG_BLANK_DATA_COLOR_BLUE_CB_EXT;\ + type OTG_BLANK_DATA_COLOR_GREEN_Y_EXT;\ + type OTG_BLANK_DATA_COLOR_RED_CR_EXT;\ + type OTG_VTOTAL_MID_REPLACING_MIN_EN;\ + type OTG_TEST_PATTERN_INC0;\ + type OTG_TEST_PATTERN_INC1;\ + type OTG_TEST_PATTERN_VRES;\ + type OTG_TEST_PATTERN_HRES;\ + type OTG_TEST_PATTERN_RAMP0_OFFSET;\ + type OTG_TEST_PATTERN_EN;\ + type OTG_TEST_PATTERN_MODE;\ + type OTG_TEST_PATTERN_DYNAMIC_RANGE;\ + type OTG_TEST_PATTERN_COLOR_FORMAT;\ + type OTG_TEST_PATTERN_MASK;\ + type OTG_TEST_PATTERN_DATA;\ + type OTG_BUSY;\ + type OTG_CLOCK_EN;\ + type OTG_CLOCK_ON;\ + type OTG_CLOCK_GATE_DIS;\ + type OTG_VERTICAL_INTERRUPT0_INT_ENABLE;\ + type OTG_VERTICAL_INTERRUPT0_LINE_START;\ + type OTG_VERTICAL_INTERRUPT0_LINE_END;\ + type OTG_VERTICAL_INTERRUPT1_INT_ENABLE;\ + type OTG_VERTICAL_INTERRUPT1_LINE_START;\ + type OTG_VERTICAL_INTERRUPT2_INT_ENABLE;\ + type OTG_VERTICAL_INTERRUPT2_LINE_START;\ + type OPTC_INPUT_CLK_EN;\ + type OPTC_INPUT_CLK_ON;\ + type OPTC_INPUT_CLK_GATE_DIS;\ + type OPTC_UNDERFLOW_OCCURRED_STATUS;\ + type OPTC_UNDERFLOW_CLEAR;\ + type OPTC_SRC_SEL;\ + type VTG0_ENABLE;\ + type VTG0_FP2;\ + type VTG0_VCOUNT_INIT;\ + type OTG_FORCE_VSYNC_NEXT_LINE_OCCURRED;\ + type OTG_FORCE_VSYNC_NEXT_LINE_CLEAR;\ + type OTG_AUTO_FORCE_VSYNC_MODE;\ + type MASTER_UPDATE_INTERLACED_MODE;\ + type OTG_GSL0_EN;\ + type OTG_GSL1_EN;\ + type OTG_GSL2_EN;\ + type OTG_GSL_MASTER_EN;\ + type OTG_GSL_FORCE_DELAY;\ + type OTG_GSL_CHECK_ALL_FIELDS;\ + type OTG_GSL_WINDOW_START_X;\ + type OTG_GSL_WINDOW_END_X;\ + type OTG_GSL_WINDOW_START_Y;\ + type OTG_GSL_WINDOW_END_Y;\ + type OTG_RANGE_TIMING_DBUF_UPDATE_MODE;\ + type OTG_GSL_MASTER_MODE;\ + type OTG_MASTER_UPDATE_LOCK_GSL_EN;\ + type MASTER_UPDATE_LOCK_VUPDATE_KEEPOUT_START_OFFSET;\ + type MASTER_UPDATE_LOCK_VUPDATE_KEEPOUT_END_OFFSET;\ + type OTG_MASTER_UPDATE_LOCK_VUPDATE_KEEPOUT_EN;\ + type OTG_CRC_CONT_EN;\ + type OTG_CRC0_SELECT;\ + type OTG_CRC_EN;\ + type CRC0_R_CR;\ + type CRC0_G_Y;\ + type CRC0_B_CB;\ + type CRC1_R_CR;\ + type CRC1_G_Y;\ + type CRC1_B_CB;\ + type CRC2_R_CR;\ + type CRC2_G_Y;\ + type CRC2_B_CB;\ + type CRC3_R_CR;\ + type CRC3_G_Y;\ + type CRC3_B_CB;\ + type OTG_CRC0_WINDOWA_X_START;\ + type OTG_CRC0_WINDOWA_X_END;\ + type OTG_CRC0_WINDOWA_Y_START;\ + type OTG_CRC0_WINDOWA_Y_END;\ + type OTG_CRC0_WINDOWB_X_START;\ + type OTG_CRC0_WINDOWB_X_END;\ + type OTG_CRC0_WINDOWB_Y_START;\ + type OTG_CRC0_WINDOWB_Y_END;\ + type OTG_CRC_WINDOW_DB_EN;\ + type OTG_CRC1_WINDOWA_X_START;\ + type OTG_CRC1_WINDOWA_X_END;\ + type OTG_CRC1_WINDOWA_Y_START;\ + type OTG_CRC1_WINDOWA_Y_END;\ + type OTG_CRC1_WINDOWB_X_START;\ + type OTG_CRC1_WINDOWB_X_END;\ + type OTG_CRC1_WINDOWB_Y_START;\ + type OTG_CRC1_WINDOWB_Y_END;\ + type GSL0_READY_SOURCE_SEL;\ + type GSL1_READY_SOURCE_SEL;\ + type GSL2_READY_SOURCE_SEL;\ + type MANUAL_FLOW_CONTROL;\ + type MANUAL_FLOW_CONTROL_SEL; + +#define TG_REG_FIELD_LIST(type) \ + TG_REG_FIELD_LIST_DCN1_0(type)\ + type OTG_V_SYNC_MODE;\ + type OTG_DRR_TRIGGER_WINDOW_START_X;\ + type OTG_DRR_TRIGGER_WINDOW_END_X;\ + type OTG_DRR_V_TOTAL_CHANGE_LIMIT;\ + type OTG_OUT_MUX;\ + type OTG_M_CONST_DTO_PHASE;\ + type OTG_M_CONST_DTO_MODULO;\ + type MASTER_UPDATE_LOCK_DB_X;\ + type MASTER_UPDATE_LOCK_DB_Y;\ + type MASTER_UPDATE_LOCK_DB_EN;\ + type GLOBAL_UPDATE_LOCK_EN;\ + type DIG_UPDATE_LOCATION;\ + type OTG_DSC_START_POSITION_X;\ + type OTG_DSC_START_POSITION_LINE_NUM;\ + type OPTC_NUM_OF_INPUT_SEGMENT;\ + type OPTC_SEG0_SRC_SEL;\ + type OPTC_SEG1_SRC_SEL;\ + type OPTC_SEG2_SRC_SEL;\ + type OPTC_SEG3_SRC_SEL;\ + type OPTC_MEM_SEL;\ + type OPTC_DATA_FORMAT;\ + type OPTC_DSC_MODE;\ + type OPTC_DSC_BYTES_PER_PIXEL;\ + type OPTC_DSC_SLICE_WIDTH;\ + type OPTC_SEGMENT_WIDTH;\ + type OPTC_DWB0_SOURCE_SELECT;\ + type OPTC_DWB1_SOURCE_SELECT;\ + type MASTER_UPDATE_LOCK_DB_START_X;\ + type MASTER_UPDATE_LOCK_DB_END_X;\ + type MASTER_UPDATE_LOCK_DB_START_Y;\ + type MASTER_UPDATE_LOCK_DB_END_Y;\ + type DIG_UPDATE_POSITION_X;\ + type DIG_UPDATE_POSITION_Y;\ + type OTG_H_TIMING_DIV_MODE;\ + type OTG_DRR_TIMING_DBUF_UPDATE_MODE;\ + type OTG_CRC_DSC_MODE;\ + type OTG_CRC_DATA_STREAM_COMBINE_MODE;\ + type OTG_CRC_DATA_STREAM_SPLIT_MODE;\ + type OTG_CRC_DATA_FORMAT;\ + type OTG_V_TOTAL_LAST_USED_BY_DRR;\ + type OTG_DRR_TIMING_DBUF_UPDATE_PENDING; + +#define TG_REG_FIELD_LIST_DCN3_2(type) \ + type OTG_H_TIMING_DIV_MODE_MANUAL; + + +#define TG_REG_FIELD_LIST_DCN3_5(type) \ + type OTG_CRC0_WINDOWA_X_START_READBACK;\ + type OTG_CRC0_WINDOWA_X_END_READBACK;\ + type OTG_CRC0_WINDOWA_Y_START_READBACK;\ + type OTG_CRC0_WINDOWA_Y_END_READBACK;\ + type OTG_CRC0_WINDOWB_X_START_READBACK;\ + type OTG_CRC0_WINDOWB_X_END_READBACK;\ + type OTG_CRC0_WINDOWB_Y_START_READBACK;\ + type OTG_CRC0_WINDOWB_Y_END_READBACK; \ + type OTG_CRC1_WINDOWA_X_START_READBACK;\ + type OTG_CRC1_WINDOWA_X_END_READBACK;\ + type OTG_CRC1_WINDOWA_Y_START_READBACK;\ + type OTG_CRC1_WINDOWA_Y_END_READBACK;\ + type OTG_CRC1_WINDOWB_X_START_READBACK;\ + type OTG_CRC1_WINDOWB_X_END_READBACK;\ + type OTG_CRC1_WINDOWB_Y_START_READBACK;\ + type OTG_CRC1_WINDOWB_Y_END_READBACK;\ + type OPTC_FGCG_REP_DIS; + +struct dcn_optc_shift { + TG_REG_FIELD_LIST(uint8_t) + TG_REG_FIELD_LIST_DCN3_2(uint8_t) + TG_REG_FIELD_LIST_DCN3_5(uint8_t) +}; + +struct dcn_optc_mask { + TG_REG_FIELD_LIST(uint32_t) + TG_REG_FIELD_LIST_DCN3_2(uint32_t) + TG_REG_FIELD_LIST_DCN3_5(uint32_t) +}; + +void dcn10_timing_generator_init(struct optc *optc); + +#endif /* __DC_TIMING_GENERATOR_DCN10_H__ */ diff --git a/drivers/gpu/drm/amd/display/dc/optc/dcn20/dcn20_optc.c b/drivers/gpu/drm/amd/display/dc/optc/dcn20/dcn20_optc.c new file mode 100644 index 000000000000..58bdbd859bf9 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/optc/dcn20/dcn20_optc.c @@ -0,0 +1,587 @@ +/* + * Copyright 2012-15 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 "reg_helper.h" +#include "dcn20_optc.h" +#include "dc.h" + +#define REG(reg)\ + optc1->tg_regs->reg + +#define CTX \ + optc1->base.ctx + +#undef FN +#define FN(reg_name, field_name) \ + optc1->tg_shift->field_name, optc1->tg_mask->field_name + +/** + * optc2_enable_crtc() - Enable CRTC - call ASIC Control Object to enable Timing generator. + * + * @optc: timing_generator instance. + * + * Return: If CRTC is enabled, return true. + * + */ +bool optc2_enable_crtc(struct timing_generator *optc) +{ + /* TODO FPGA wait for answer + * OTG_MASTER_UPDATE_MODE != CRTC_MASTER_UPDATE_MODE + * OTG_MASTER_UPDATE_LOCK != CRTC_MASTER_UPDATE_LOCK + */ + struct optc *optc1 = DCN10TG_FROM_TG(optc); + + /* opp instance for OTG. For DCN1.0, ODM is remoed. + * OPP and OPTC should 1:1 mapping + */ + REG_UPDATE(OPTC_DATA_SOURCE_SELECT, + OPTC_SEG0_SRC_SEL, optc->inst); + + /* VTG enable first is for HW workaround */ + REG_UPDATE(CONTROL, + VTG0_ENABLE, 1); + + REG_SEQ_START(); + + /* Enable CRTC */ + REG_UPDATE_2(OTG_CONTROL, + OTG_DISABLE_POINT_CNTL, 3, + OTG_MASTER_EN, 1); + + REG_SEQ_SUBMIT(); + REG_SEQ_WAIT_DONE(); + + return true; +} + +/** + * optc2_set_gsl() - Assign OTG to GSL groups, + * set one of the OTGs to be master & rest are slaves + * + * @optc: timing_generator instance. + * @params: pointer to gsl_params + */ +void optc2_set_gsl(struct timing_generator *optc, + const struct gsl_params *params) +{ + struct optc *optc1 = DCN10TG_FROM_TG(optc); + +/* + * There are (MAX_OPTC+1)/2 gsl groups available for use. + * In each group (assign an OTG to a group by setting OTG_GSLX_EN = 1, + * set one of the OTGs to be the master (OTG_GSL_MASTER_EN = 1) and the rest are slaves. + */ + REG_UPDATE_5(OTG_GSL_CONTROL, + OTG_GSL0_EN, params->gsl0_en, + OTG_GSL1_EN, params->gsl1_en, + OTG_GSL2_EN, params->gsl2_en, + OTG_GSL_MASTER_EN, params->gsl_master_en, + OTG_GSL_MASTER_MODE, params->gsl_master_mode); +} + + +void optc2_set_gsl_source_select( + struct timing_generator *optc, + int group_idx, + uint32_t gsl_ready_signal) +{ + struct optc *optc1 = DCN10TG_FROM_TG(optc); + + switch (group_idx) { + case 1: + REG_UPDATE(GSL_SOURCE_SELECT, GSL0_READY_SOURCE_SEL, gsl_ready_signal); + break; + case 2: + REG_UPDATE(GSL_SOURCE_SELECT, GSL1_READY_SOURCE_SEL, gsl_ready_signal); + break; + case 3: + REG_UPDATE(GSL_SOURCE_SELECT, GSL2_READY_SOURCE_SEL, gsl_ready_signal); + break; + default: + break; + } +} + +/* Set DSC-related configuration. + * dsc_mode: 0 disables DSC, other values enable DSC in specified format + * sc_bytes_per_pixel: Bytes per pixel in u3.28 format + * dsc_slice_width: Slice width in pixels + */ +void optc2_set_dsc_config(struct timing_generator *optc, + enum optc_dsc_mode dsc_mode, + uint32_t dsc_bytes_per_pixel, + uint32_t dsc_slice_width) +{ + struct optc *optc1 = DCN10TG_FROM_TG(optc); + + REG_UPDATE(OPTC_DATA_FORMAT_CONTROL, + OPTC_DSC_MODE, dsc_mode); + + REG_SET(OPTC_BYTES_PER_PIXEL, 0, + OPTC_DSC_BYTES_PER_PIXEL, dsc_bytes_per_pixel); + + REG_UPDATE(OPTC_WIDTH_CONTROL, + OPTC_DSC_SLICE_WIDTH, dsc_slice_width); +} + +/* Get DSC-related configuration. + * dsc_mode: 0 disables DSC, other values enable DSC in specified format + */ +void optc2_get_dsc_status(struct timing_generator *optc, + uint32_t *dsc_mode) +{ + struct optc *optc1 = DCN10TG_FROM_TG(optc); + + REG_GET(OPTC_DATA_FORMAT_CONTROL, + OPTC_DSC_MODE, dsc_mode); +} + + +/*TEMP: Need to figure out inheritance model here.*/ +bool optc2_is_two_pixels_per_containter(const struct dc_crtc_timing *timing) +{ + return optc1_is_two_pixels_per_containter(timing); +} + +void optc2_set_odm_bypass(struct timing_generator *optc, + const struct dc_crtc_timing *dc_crtc_timing) +{ + struct optc *optc1 = DCN10TG_FROM_TG(optc); + uint32_t h_div_2 = 0; + + REG_SET_3(OPTC_DATA_SOURCE_SELECT, 0, + OPTC_NUM_OF_INPUT_SEGMENT, 0, + OPTC_SEG0_SRC_SEL, optc->inst, + OPTC_SEG1_SRC_SEL, 0xf); + REG_WRITE(OTG_H_TIMING_CNTL, 0); + + h_div_2 = optc2_is_two_pixels_per_containter(dc_crtc_timing); + REG_UPDATE(OTG_H_TIMING_CNTL, + OTG_H_TIMING_DIV_BY2, h_div_2); + REG_SET(OPTC_MEMORY_CONFIG, 0, + OPTC_MEM_SEL, 0); + optc1->opp_count = 1; +} + +void optc2_set_odm_combine(struct timing_generator *optc, int *opp_id, int opp_cnt, + struct dc_crtc_timing *timing) +{ + struct optc *optc1 = DCN10TG_FROM_TG(optc); + int mpcc_hactive = (timing->h_addressable + timing->h_border_left + timing->h_border_right) + / opp_cnt; + uint32_t memory_mask; + + ASSERT(opp_cnt == 2); + + /* TODO: In pseudocode but does not affect maximus, delete comment if we dont need on asic + * REG_SET(OTG_GLOBAL_CONTROL2, 0, GLOBAL_UPDATE_LOCK_EN, 1); + * Program OTG register MASTER_UPDATE_LOCK_DB_X/Y to the position before DP frame start + * REG_SET_2(OTG_GLOBAL_CONTROL1, 0, + * MASTER_UPDATE_LOCK_DB_X, 160, + * MASTER_UPDATE_LOCK_DB_Y, 240); + */ + + /* 2 pieces of memory required for up to 5120 displays, 4 for up to 8192, + * however, for ODM combine we can simplify by always using 4. + * To make sure there's no overlap, each instance "reserves" 2 memories and + * they are uniquely combined here. + */ + memory_mask = 0x3 << (opp_id[0] * 2) | 0x3 << (opp_id[1] * 2); + + if (REG(OPTC_MEMORY_CONFIG)) + REG_SET(OPTC_MEMORY_CONFIG, 0, + OPTC_MEM_SEL, memory_mask); + + REG_SET_3(OPTC_DATA_SOURCE_SELECT, 0, + OPTC_NUM_OF_INPUT_SEGMENT, 1, + OPTC_SEG0_SRC_SEL, opp_id[0], + OPTC_SEG1_SRC_SEL, opp_id[1]); + + REG_UPDATE(OPTC_WIDTH_CONTROL, + OPTC_SEGMENT_WIDTH, mpcc_hactive); + + REG_SET(OTG_H_TIMING_CNTL, 0, OTG_H_TIMING_DIV_BY2, 1); + optc1->opp_count = opp_cnt; +} + +void optc2_get_optc_source(struct timing_generator *optc, + uint32_t *num_of_src_opp, + uint32_t *src_opp_id_0, + uint32_t *src_opp_id_1) +{ + uint32_t num_of_input_segments; + struct optc *optc1 = DCN10TG_FROM_TG(optc); + + REG_GET_3(OPTC_DATA_SOURCE_SELECT, + OPTC_NUM_OF_INPUT_SEGMENT, &num_of_input_segments, + OPTC_SEG0_SRC_SEL, src_opp_id_0, + OPTC_SEG1_SRC_SEL, src_opp_id_1); + + if (num_of_input_segments == 1) + *num_of_src_opp = 2; + else + *num_of_src_opp = 1; + + /* Work around VBIOS not updating OPTC_NUM_OF_INPUT_SEGMENT */ + if (*src_opp_id_1 == 0xf) + *num_of_src_opp = 1; +} + +static void optc2_set_dwb_source(struct timing_generator *optc, + uint32_t dwb_pipe_inst) +{ + struct optc *optc1 = DCN10TG_FROM_TG(optc); + + if (dwb_pipe_inst == 0) + REG_UPDATE(DWB_SOURCE_SELECT, + OPTC_DWB0_SOURCE_SELECT, optc->inst); + else if (dwb_pipe_inst == 1) + REG_UPDATE(DWB_SOURCE_SELECT, + OPTC_DWB1_SOURCE_SELECT, optc->inst); +} + +static void optc2_align_vblanks( + struct timing_generator *optc_master, + struct timing_generator *optc_slave, + uint32_t master_pixel_clock_100Hz, + uint32_t slave_pixel_clock_100Hz, + uint8_t master_clock_divider, + uint8_t slave_clock_divider) +{ + /* accessing slave OTG registers */ + struct optc *optc1 = DCN10TG_FROM_TG(optc_slave); + + uint32_t master_v_active = 0; + uint32_t master_h_total = 0; + uint32_t slave_h_total = 0; + uint64_t L, XY; + uint32_t X, Y, p = 10000; + uint32_t master_update_lock; + + /* disable slave OTG */ + REG_UPDATE(OTG_CONTROL, OTG_MASTER_EN, 0); + /* wait until disabled */ + REG_WAIT(OTG_CONTROL, + OTG_CURRENT_MASTER_EN_STATE, + 0, 10, 5000); + + REG_GET(OTG_H_TOTAL, OTG_H_TOTAL, &slave_h_total); + + /* assign slave OTG to be controlled by master update lock */ + REG_SET(OTG_GLOBAL_CONTROL0, 0, + OTG_MASTER_UPDATE_LOCK_SEL, optc_master->inst); + + /* accessing master OTG registers */ + optc1 = DCN10TG_FROM_TG(optc_master); + + /* saving update lock state, not sure if it's needed */ + REG_GET(OTG_MASTER_UPDATE_LOCK, + OTG_MASTER_UPDATE_LOCK, &master_update_lock); + /* unlocking master OTG */ + REG_SET(OTG_MASTER_UPDATE_LOCK, 0, + OTG_MASTER_UPDATE_LOCK, 0); + + REG_GET(OTG_V_BLANK_START_END, + OTG_V_BLANK_START, &master_v_active); + REG_GET(OTG_H_TOTAL, OTG_H_TOTAL, &master_h_total); + + /* calculate when to enable slave OTG */ + L = (uint64_t)p * slave_h_total * master_pixel_clock_100Hz; + L = div_u64(L, master_h_total); + L = div_u64(L, slave_pixel_clock_100Hz); + XY = div_u64(L, p); + Y = master_v_active - XY - 1; + X = div_u64(((XY + 1) * p - L) * master_h_total, p * master_clock_divider); + + /* + * set master OTG to unlock when V/H + * counters reach calculated values + */ + REG_UPDATE(OTG_GLOBAL_CONTROL1, + MASTER_UPDATE_LOCK_DB_EN, 1); + REG_UPDATE_2(OTG_GLOBAL_CONTROL1, + MASTER_UPDATE_LOCK_DB_X, + X, + MASTER_UPDATE_LOCK_DB_Y, + Y); + + /* lock master OTG */ + REG_SET(OTG_MASTER_UPDATE_LOCK, 0, + OTG_MASTER_UPDATE_LOCK, 1); + REG_WAIT(OTG_MASTER_UPDATE_LOCK, + UPDATE_LOCK_STATUS, 1, 1, 10); + + /* accessing slave OTG registers */ + optc1 = DCN10TG_FROM_TG(optc_slave); + + /* + * enable slave OTG, the OTG is locked with + * master's update lock, so it will not run + */ + REG_UPDATE(OTG_CONTROL, + OTG_MASTER_EN, 1); + + /* accessing master OTG registers */ + optc1 = DCN10TG_FROM_TG(optc_master); + + /* + * unlock master OTG. When master H/V counters reach + * DB_XY point, slave OTG will start + */ + REG_SET(OTG_MASTER_UPDATE_LOCK, 0, + OTG_MASTER_UPDATE_LOCK, 0); + + /* accessing slave OTG registers */ + optc1 = DCN10TG_FROM_TG(optc_slave); + + /* wait for slave OTG to start running*/ + REG_WAIT(OTG_CONTROL, + OTG_CURRENT_MASTER_EN_STATE, + 1, 10, 5000); + + /* accessing master OTG registers */ + optc1 = DCN10TG_FROM_TG(optc_master); + + /* disable the XY point*/ + REG_UPDATE(OTG_GLOBAL_CONTROL1, + MASTER_UPDATE_LOCK_DB_EN, 0); + REG_UPDATE_2(OTG_GLOBAL_CONTROL1, + MASTER_UPDATE_LOCK_DB_X, + 0, + MASTER_UPDATE_LOCK_DB_Y, + 0); + + /*restore master update lock*/ + REG_SET(OTG_MASTER_UPDATE_LOCK, 0, + OTG_MASTER_UPDATE_LOCK, master_update_lock); + + /* accessing slave OTG registers */ + optc1 = DCN10TG_FROM_TG(optc_slave); + /* restore slave to be controlled by it's own */ + REG_SET(OTG_GLOBAL_CONTROL0, 0, + OTG_MASTER_UPDATE_LOCK_SEL, optc_slave->inst); + +} + +void optc2_triplebuffer_lock(struct timing_generator *optc) +{ + struct optc *optc1 = DCN10TG_FROM_TG(optc); + + REG_SET(OTG_GLOBAL_CONTROL0, 0, + OTG_MASTER_UPDATE_LOCK_SEL, optc->inst); + + REG_SET(OTG_VUPDATE_KEEPOUT, 0, + OTG_MASTER_UPDATE_LOCK_VUPDATE_KEEPOUT_EN, 1); + + REG_SET(OTG_MASTER_UPDATE_LOCK, 0, + OTG_MASTER_UPDATE_LOCK, 1); + + REG_WAIT(OTG_MASTER_UPDATE_LOCK, + UPDATE_LOCK_STATUS, 1, + 1, 10); +} + +void optc2_triplebuffer_unlock(struct timing_generator *optc) +{ + struct optc *optc1 = DCN10TG_FROM_TG(optc); + + REG_SET(OTG_MASTER_UPDATE_LOCK, 0, + OTG_MASTER_UPDATE_LOCK, 0); + + REG_SET(OTG_VUPDATE_KEEPOUT, 0, + OTG_MASTER_UPDATE_LOCK_VUPDATE_KEEPOUT_EN, 0); + +} + +void optc2_lock_doublebuffer_enable(struct timing_generator *optc) +{ + struct optc *optc1 = DCN10TG_FROM_TG(optc); + uint32_t v_blank_start = 0; + uint32_t h_blank_start = 0; + + REG_UPDATE(OTG_GLOBAL_CONTROL1, MASTER_UPDATE_LOCK_DB_EN, 1); + + REG_UPDATE_2(OTG_GLOBAL_CONTROL2, GLOBAL_UPDATE_LOCK_EN, 1, + DIG_UPDATE_LOCATION, 20); + + REG_GET(OTG_V_BLANK_START_END, OTG_V_BLANK_START, &v_blank_start); + + REG_GET(OTG_H_BLANK_START_END, OTG_H_BLANK_START, &h_blank_start); + + REG_UPDATE_2(OTG_GLOBAL_CONTROL1, + MASTER_UPDATE_LOCK_DB_X, + (h_blank_start - 200 - 1) / optc1->opp_count, + MASTER_UPDATE_LOCK_DB_Y, + v_blank_start - 1); + + REG_SET_3(OTG_VUPDATE_KEEPOUT, 0, + MASTER_UPDATE_LOCK_VUPDATE_KEEPOUT_START_OFFSET, 0, + MASTER_UPDATE_LOCK_VUPDATE_KEEPOUT_END_OFFSET, 100, + OTG_MASTER_UPDATE_LOCK_VUPDATE_KEEPOUT_EN, 1); +} + +void optc2_lock_doublebuffer_disable(struct timing_generator *optc) +{ + struct optc *optc1 = DCN10TG_FROM_TG(optc); + + REG_UPDATE_2(OTG_GLOBAL_CONTROL1, + MASTER_UPDATE_LOCK_DB_X, + 0, + MASTER_UPDATE_LOCK_DB_Y, + 0); + + REG_UPDATE_2(OTG_GLOBAL_CONTROL2, GLOBAL_UPDATE_LOCK_EN, 0, + DIG_UPDATE_LOCATION, 0); + + REG_UPDATE(OTG_GLOBAL_CONTROL1, MASTER_UPDATE_LOCK_DB_EN, 0); +} + +void optc2_setup_manual_trigger(struct timing_generator *optc) +{ + struct optc *optc1 = DCN10TG_FROM_TG(optc); + + /* Set the min/max selectors unconditionally so that + * DMCUB fw may change OTG timings when necessary + * TODO: Remove the w/a after fixing the issue in DMCUB firmware + */ + REG_UPDATE_4(OTG_V_TOTAL_CONTROL, + OTG_V_TOTAL_MIN_SEL, 1, + OTG_V_TOTAL_MAX_SEL, 1, + OTG_FORCE_LOCK_ON_EVENT, 0, + OTG_SET_V_TOTAL_MIN_MASK, (1 << 1)); /* TRIGA */ + + REG_SET_8(OTG_TRIGA_CNTL, 0, + OTG_TRIGA_SOURCE_SELECT, 21, + OTG_TRIGA_SOURCE_PIPE_SELECT, optc->inst, + OTG_TRIGA_RISING_EDGE_DETECT_CNTL, 1, + OTG_TRIGA_FALLING_EDGE_DETECT_CNTL, 0, + OTG_TRIGA_POLARITY_SELECT, 0, + OTG_TRIGA_FREQUENCY_SELECT, 0, + OTG_TRIGA_DELAY, 0, + OTG_TRIGA_CLEAR, 1); +} + +void optc2_program_manual_trigger(struct timing_generator *optc) +{ + struct optc *optc1 = DCN10TG_FROM_TG(optc); + + REG_SET(OTG_TRIGA_MANUAL_TRIG, 0, + OTG_TRIGA_MANUAL_TRIG, 1); +} + +bool optc2_configure_crc(struct timing_generator *optc, + const struct crc_params *params) +{ + struct optc *optc1 = DCN10TG_FROM_TG(optc); + + REG_SET_2(OTG_CRC_CNTL2, 0, + OTG_CRC_DSC_MODE, params->dsc_mode, + OTG_CRC_DATA_STREAM_COMBINE_MODE, params->odm_mode); + + return optc1_configure_crc(optc, params); +} + + +void optc2_get_last_used_drr_vtotal(struct timing_generator *optc, uint32_t *refresh_rate) +{ + struct optc *optc1 = DCN10TG_FROM_TG(optc); + + REG_GET(OTG_DRR_CONTROL, OTG_V_TOTAL_LAST_USED_BY_DRR, refresh_rate); +} + +static struct timing_generator_funcs dcn20_tg_funcs = { + .validate_timing = optc1_validate_timing, + .program_timing = optc1_program_timing, + .setup_vertical_interrupt0 = optc1_setup_vertical_interrupt0, + .setup_vertical_interrupt1 = optc1_setup_vertical_interrupt1, + .setup_vertical_interrupt2 = optc1_setup_vertical_interrupt2, + .program_global_sync = optc1_program_global_sync, + .enable_crtc = optc2_enable_crtc, + .disable_crtc = optc1_disable_crtc, + /* used by enable_timing_synchronization. Not need for FPGA */ + .is_counter_moving = optc1_is_counter_moving, + .get_position = optc1_get_position, + .get_frame_count = optc1_get_vblank_counter, + .get_scanoutpos = optc1_get_crtc_scanoutpos, + .get_otg_active_size = optc1_get_otg_active_size, + .set_early_control = optc1_set_early_control, + /* used by enable_timing_synchronization. Not need for FPGA */ + .wait_for_state = optc1_wait_for_state, + .set_blank = optc1_set_blank, + .is_blanked = optc1_is_blanked, + .set_blank_color = optc1_program_blank_color, + .enable_reset_trigger = optc1_enable_reset_trigger, + .enable_crtc_reset = optc1_enable_crtc_reset, + .did_triggered_reset_occur = optc1_did_triggered_reset_occur, + .triplebuffer_lock = optc2_triplebuffer_lock, + .triplebuffer_unlock = optc2_triplebuffer_unlock, + .disable_reset_trigger = optc1_disable_reset_trigger, + .lock = optc1_lock, + .unlock = optc1_unlock, + .lock_doublebuffer_enable = optc2_lock_doublebuffer_enable, + .lock_doublebuffer_disable = optc2_lock_doublebuffer_disable, + .enable_optc_clock = optc1_enable_optc_clock, + .set_drr = optc1_set_drr, + .get_last_used_drr_vtotal = optc2_get_last_used_drr_vtotal, + .set_vtotal_min_max = optc1_set_vtotal_min_max, + .set_static_screen_control = optc1_set_static_screen_control, + .program_stereo = optc1_program_stereo, + .is_stereo_left_eye = optc1_is_stereo_left_eye, + .set_blank_data_double_buffer = optc1_set_blank_data_double_buffer, + .tg_init = optc1_tg_init, + .is_tg_enabled = optc1_is_tg_enabled, + .is_optc_underflow_occurred = optc1_is_optc_underflow_occurred, + .clear_optc_underflow = optc1_clear_optc_underflow, + .setup_global_swap_lock = NULL, + .get_crc = optc1_get_crc, + .configure_crc = optc2_configure_crc, + .set_dsc_config = optc2_set_dsc_config, + .get_dsc_status = optc2_get_dsc_status, + .set_dwb_source = optc2_set_dwb_source, + .set_odm_bypass = optc2_set_odm_bypass, + .set_odm_combine = optc2_set_odm_combine, + .get_optc_source = optc2_get_optc_source, + .set_gsl = optc2_set_gsl, + .set_gsl_source_select = optc2_set_gsl_source_select, + .set_vtg_params = optc1_set_vtg_params, + .program_manual_trigger = optc2_program_manual_trigger, + .setup_manual_trigger = optc2_setup_manual_trigger, + .get_hw_timing = optc1_get_hw_timing, + .align_vblanks = optc2_align_vblanks, +}; + +void dcn20_timing_generator_init(struct optc *optc1) +{ + optc1->base.funcs = &dcn20_tg_funcs; + + optc1->max_h_total = optc1->tg_mask->OTG_H_TOTAL + 1; + optc1->max_v_total = optc1->tg_mask->OTG_V_TOTAL + 1; + + optc1->min_h_blank = 32; + optc1->min_v_blank = 3; + optc1->min_v_blank_interlace = 5; + optc1->min_h_sync_width = 4;// Minimum HSYNC = 8 pixels asked By HW in the first place for no actual reason. Oculus Rift S will not light up with 8 as it's hsyncWidth is 6. Changing it to 4 to fix that issue. + optc1->min_v_sync_width = 1; +} diff --git a/drivers/gpu/drm/amd/display/dc/optc/dcn20/dcn20_optc.h b/drivers/gpu/drm/amd/display/dc/optc/dcn20/dcn20_optc.h new file mode 100644 index 000000000000..c2e03ced392e --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/optc/dcn20/dcn20_optc.h @@ -0,0 +1,124 @@ +/* + * Copyright 2012-15 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_OPTC_DCN20_H__ +#define __DC_OPTC_DCN20_H__ + +#include "dcn10/dcn10_optc.h" + +#define TG_COMMON_REG_LIST_DCN2_0(inst) \ + TG_COMMON_REG_LIST_DCN(inst),\ + SRI(OTG_GLOBAL_CONTROL1, OTG, inst),\ + SRI(OTG_GLOBAL_CONTROL2, OTG, inst),\ + SRI(OTG_GSL_WINDOW_X, OTG, inst),\ + SRI(OTG_GSL_WINDOW_Y, OTG, inst),\ + SRI(OTG_VUPDATE_KEEPOUT, OTG, inst),\ + SRI(OTG_DSC_START_POSITION, OTG, inst),\ + SRI(OTG_CRC_CNTL2, OTG, inst),\ + SRI(OPTC_DATA_FORMAT_CONTROL, ODM, inst),\ + SRI(OPTC_BYTES_PER_PIXEL, ODM, inst),\ + SRI(OPTC_WIDTH_CONTROL, ODM, inst),\ + SRI(OPTC_MEMORY_CONFIG, ODM, inst),\ + SR(DWB_SOURCE_SELECT),\ + SRI(OTG_MANUAL_FLOW_CONTROL, OTG, inst), \ + SRI(OTG_DRR_CONTROL, OTG, inst) + +#define TG_COMMON_MASK_SH_LIST_DCN2_0(mask_sh)\ + TG_COMMON_MASK_SH_LIST_DCN(mask_sh),\ + SF(OTG0_OTG_GLOBAL_CONTROL1, MASTER_UPDATE_LOCK_DB_X, mask_sh),\ + SF(OTG0_OTG_GLOBAL_CONTROL1, MASTER_UPDATE_LOCK_DB_Y, mask_sh),\ + SF(OTG0_OTG_GLOBAL_CONTROL1, MASTER_UPDATE_LOCK_DB_EN, mask_sh),\ + SF(OTG0_OTG_GLOBAL_CONTROL2, GLOBAL_UPDATE_LOCK_EN, mask_sh),\ + SF(OTG0_OTG_GLOBAL_CONTROL2, DIG_UPDATE_LOCATION, mask_sh),\ + SF(OTG0_OTG_DOUBLE_BUFFER_CONTROL, OTG_RANGE_TIMING_DBUF_UPDATE_MODE, mask_sh),\ + SF(OTG0_OTG_GSL_WINDOW_X, OTG_GSL_WINDOW_START_X, mask_sh),\ + SF(OTG0_OTG_GSL_WINDOW_X, OTG_GSL_WINDOW_END_X, mask_sh), \ + SF(OTG0_OTG_GSL_WINDOW_Y, OTG_GSL_WINDOW_START_Y, mask_sh),\ + SF(OTG0_OTG_GSL_WINDOW_Y, OTG_GSL_WINDOW_END_Y, mask_sh),\ + SF(OTG0_OTG_GSL_CONTROL, OTG_GSL_MASTER_MODE, mask_sh), \ + SF(OTG0_OTG_GSL_CONTROL, OTG_MASTER_UPDATE_LOCK_GSL_EN, mask_sh), \ + SF(OTG0_OTG_DSC_START_POSITION, OTG_DSC_START_POSITION_X, mask_sh), \ + SF(OTG0_OTG_DSC_START_POSITION, OTG_DSC_START_POSITION_LINE_NUM, mask_sh),\ + SF(OTG0_OTG_CRC_CNTL2, OTG_CRC_DSC_MODE, mask_sh),\ + SF(OTG0_OTG_CRC_CNTL2, OTG_CRC_DATA_STREAM_COMBINE_MODE, mask_sh),\ + SF(OTG0_OTG_CRC_CNTL2, OTG_CRC_DATA_STREAM_SPLIT_MODE, mask_sh),\ + SF(OTG0_OTG_CRC_CNTL2, OTG_CRC_DATA_FORMAT, mask_sh),\ + SF(ODM0_OPTC_DATA_SOURCE_SELECT, OPTC_SEG0_SRC_SEL, mask_sh),\ + SF(ODM0_OPTC_DATA_SOURCE_SELECT, OPTC_SEG1_SRC_SEL, mask_sh),\ + SF(ODM0_OPTC_DATA_SOURCE_SELECT, OPTC_NUM_OF_INPUT_SEGMENT, mask_sh),\ + SF(ODM0_OPTC_MEMORY_CONFIG, OPTC_MEM_SEL, mask_sh),\ + SF(ODM0_OPTC_DATA_FORMAT_CONTROL, OPTC_DATA_FORMAT, mask_sh),\ + SF(ODM0_OPTC_DATA_FORMAT_CONTROL, OPTC_DSC_MODE, mask_sh),\ + SF(ODM0_OPTC_BYTES_PER_PIXEL, OPTC_DSC_BYTES_PER_PIXEL, mask_sh),\ + SF(ODM0_OPTC_WIDTH_CONTROL, OPTC_DSC_SLICE_WIDTH, mask_sh),\ + SF(ODM0_OPTC_WIDTH_CONTROL, OPTC_SEGMENT_WIDTH, mask_sh),\ + SF(DWB_SOURCE_SELECT, OPTC_DWB0_SOURCE_SELECT, mask_sh),\ + SF(DWB_SOURCE_SELECT, OPTC_DWB1_SOURCE_SELECT, mask_sh),\ + SF(OTG0_OTG_MANUAL_FLOW_CONTROL, MANUAL_FLOW_CONTROL, mask_sh), \ + SF(OTG0_OTG_DRR_CONTROL, OTG_V_TOTAL_LAST_USED_BY_DRR, mask_sh) + +void dcn20_timing_generator_init(struct optc *optc); + +void optc2_get_last_used_drr_vtotal(struct timing_generator *optc, + uint32_t *refresh_rate); + +bool optc2_enable_crtc(struct timing_generator *optc); + +void optc2_set_gsl(struct timing_generator *optc, + const struct gsl_params *params); + +void optc2_set_gsl_source_select(struct timing_generator *optc, + int group_idx, + uint32_t gsl_ready_signal); + +void optc2_set_dsc_config(struct timing_generator *optc, + enum optc_dsc_mode dsc_mode, + uint32_t dsc_bytes_per_pixel, + uint32_t dsc_slice_width); + +void optc2_get_dsc_status(struct timing_generator *optc, + uint32_t *dsc_mode); + +void optc2_set_odm_bypass(struct timing_generator *optc, + const struct dc_crtc_timing *dc_crtc_timing); + +void optc2_set_odm_combine(struct timing_generator *optc, int *opp_id, int opp_cnt, + struct dc_crtc_timing *timing); + +void optc2_get_optc_source(struct timing_generator *optc, + uint32_t *num_of_src_opp, + uint32_t *src_opp_id_0, + uint32_t *src_opp_id_1); + +void optc2_triplebuffer_lock(struct timing_generator *optc); +void optc2_triplebuffer_unlock(struct timing_generator *optc); +void optc2_lock_doublebuffer_disable(struct timing_generator *optc); +void optc2_lock_doublebuffer_enable(struct timing_generator *optc); +void optc2_setup_manual_trigger(struct timing_generator *optc); +void optc2_program_manual_trigger(struct timing_generator *optc); +bool optc2_is_two_pixels_per_containter(const struct dc_crtc_timing *timing); +bool optc2_configure_crc(struct timing_generator *optc, + const struct crc_params *params); +#endif /* __DC_OPTC_DCN20_H__ */ diff --git a/drivers/gpu/drm/amd/display/dc/optc/dcn201/dcn201_optc.c b/drivers/gpu/drm/amd/display/dc/optc/dcn201/dcn201_optc.c new file mode 100644 index 000000000000..70fcbec03fb6 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/optc/dcn201/dcn201_optc.c @@ -0,0 +1,202 @@ +/* + * Copyright 2012-15 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 "reg_helper.h" +#include "dcn201_optc.h" +#include "dcn10/dcn10_optc.h" +#include "dc.h" + +#define REG(reg)\ + optc1->tg_regs->reg + +#define CTX \ + optc1->base.ctx + +#undef FN +#define FN(reg_name, field_name) \ + optc1->tg_shift->field_name, optc1->tg_mask->field_name + +/*TEMP: Need to figure out inheritance model here.*/ +bool optc201_is_two_pixels_per_containter(const struct dc_crtc_timing *timing) +{ + return optc1_is_two_pixels_per_containter(timing); +} + +static void optc201_triplebuffer_lock(struct timing_generator *optc) +{ + struct optc *optc1 = DCN10TG_FROM_TG(optc); + + REG_SET(OTG_GLOBAL_CONTROL0, 0, + OTG_MASTER_UPDATE_LOCK_SEL, optc->inst); + REG_SET(OTG_VUPDATE_KEEPOUT, 0, + OTG_MASTER_UPDATE_LOCK_VUPDATE_KEEPOUT_EN, 1); + REG_SET(OTG_MASTER_UPDATE_LOCK, 0, + OTG_MASTER_UPDATE_LOCK, 1); + + REG_WAIT(OTG_MASTER_UPDATE_LOCK, + UPDATE_LOCK_STATUS, 1, + 1, 10); +} + +static void optc201_triplebuffer_unlock(struct timing_generator *optc) +{ + struct optc *optc1 = DCN10TG_FROM_TG(optc); + + REG_SET(OTG_MASTER_UPDATE_LOCK, 0, + OTG_MASTER_UPDATE_LOCK, 0); + REG_SET(OTG_VUPDATE_KEEPOUT, 0, + OTG_MASTER_UPDATE_LOCK_VUPDATE_KEEPOUT_EN, 0); + +} + +static bool optc201_validate_timing( + struct timing_generator *optc, + const struct dc_crtc_timing *timing) +{ + uint32_t v_blank; + uint32_t h_blank; + uint32_t min_v_blank; + struct optc *optc1 = DCN10TG_FROM_TG(optc); + + ASSERT(timing != NULL); + + v_blank = (timing->v_total - timing->v_addressable - + timing->v_border_top - timing->v_border_bottom); + + h_blank = (timing->h_total - timing->h_addressable - + timing->h_border_right - + timing->h_border_left); + + if (timing->timing_3d_format != TIMING_3D_FORMAT_NONE && + timing->timing_3d_format != TIMING_3D_FORMAT_HW_FRAME_PACKING && + timing->timing_3d_format != TIMING_3D_FORMAT_TOP_AND_BOTTOM && + timing->timing_3d_format != TIMING_3D_FORMAT_SIDE_BY_SIDE && + timing->timing_3d_format != TIMING_3D_FORMAT_FRAME_ALTERNATE && + timing->timing_3d_format != TIMING_3D_FORMAT_INBAND_FA) + return false; + + /* Check maximum number of pixels supported by Timing Generator + * (Currently will never fail, in order to fail needs display which + * needs more than 8192 horizontal and + * more than 8192 vertical total pixels) + */ + if (timing->h_total > optc1->max_h_total || + timing->v_total > optc1->max_v_total) + return false; + + if (h_blank < optc1->min_h_blank) + return false; + + if (timing->h_sync_width < optc1->min_h_sync_width || + timing->v_sync_width < optc1->min_v_sync_width) + return false; + + min_v_blank = timing->flags.INTERLACE?optc1->min_v_blank_interlace:optc1->min_v_blank; + + if (v_blank < min_v_blank) + return false; + + return true; + +} + +static void optc201_get_optc_source(struct timing_generator *optc, + uint32_t *num_of_src_opp, + uint32_t *src_opp_id_0, + uint32_t *src_opp_id_1) +{ + struct optc *optc1 = DCN10TG_FROM_TG(optc); + + REG_GET(OPTC_DATA_SOURCE_SELECT, + OPTC_SEG0_SRC_SEL, src_opp_id_0); + + *num_of_src_opp = 1; +} + +static struct timing_generator_funcs dcn201_tg_funcs = { + .validate_timing = optc201_validate_timing, + .program_timing = optc1_program_timing, + .setup_vertical_interrupt0 = optc1_setup_vertical_interrupt0, + .setup_vertical_interrupt1 = optc1_setup_vertical_interrupt1, + .setup_vertical_interrupt2 = optc1_setup_vertical_interrupt2, + .program_global_sync = optc1_program_global_sync, + .enable_crtc = optc2_enable_crtc, + .disable_crtc = optc1_disable_crtc, + /* used by enable_timing_synchronization. Not need for FPGA */ + .is_counter_moving = optc1_is_counter_moving, + .get_position = optc1_get_position, + .get_frame_count = optc1_get_vblank_counter, + .get_scanoutpos = optc1_get_crtc_scanoutpos, + .get_otg_active_size = optc1_get_otg_active_size, + .set_early_control = optc1_set_early_control, + /* used by enable_timing_synchronization. Not need for FPGA */ + .wait_for_state = optc1_wait_for_state, + .set_blank = optc1_set_blank, + .is_blanked = optc1_is_blanked, + .set_blank_color = optc1_program_blank_color, + .did_triggered_reset_occur = optc1_did_triggered_reset_occur, + .enable_reset_trigger = optc1_enable_reset_trigger, + .enable_crtc_reset = optc1_enable_crtc_reset, + .disable_reset_trigger = optc1_disable_reset_trigger, + .triplebuffer_lock = optc201_triplebuffer_lock, + .triplebuffer_unlock = optc201_triplebuffer_unlock, + .lock = optc1_lock, + .unlock = optc1_unlock, + .enable_optc_clock = optc1_enable_optc_clock, + .set_drr = optc1_set_drr, + .get_last_used_drr_vtotal = NULL, + .set_vtotal_min_max = optc1_set_vtotal_min_max, + .set_static_screen_control = optc1_set_static_screen_control, + .program_stereo = optc1_program_stereo, + .is_stereo_left_eye = optc1_is_stereo_left_eye, + .set_blank_data_double_buffer = optc1_set_blank_data_double_buffer, + .tg_init = optc1_tg_init, + .is_tg_enabled = optc1_is_tg_enabled, + .is_optc_underflow_occurred = optc1_is_optc_underflow_occurred, + .clear_optc_underflow = optc1_clear_optc_underflow, + .get_crc = optc1_get_crc, + .configure_crc = optc2_configure_crc, + .set_dsc_config = optc2_set_dsc_config, + .set_dwb_source = NULL, + .get_optc_source = optc201_get_optc_source, + .set_vtg_params = optc1_set_vtg_params, + .program_manual_trigger = optc2_program_manual_trigger, + .setup_manual_trigger = optc2_setup_manual_trigger, + .get_hw_timing = optc1_get_hw_timing, +}; + +void dcn201_timing_generator_init(struct optc *optc1) +{ + optc1->base.funcs = &dcn201_tg_funcs; + + optc1->max_h_total = optc1->tg_mask->OTG_H_TOTAL + 1; + optc1->max_v_total = optc1->tg_mask->OTG_V_TOTAL + 1; + + optc1->min_h_blank = 32; + optc1->min_v_blank = 3; + optc1->min_v_blank_interlace = 5; + optc1->min_h_sync_width = 8; + optc1->min_v_sync_width = 1; +} diff --git a/drivers/gpu/drm/amd/display/dc/optc/dcn201/dcn201_optc.h b/drivers/gpu/drm/amd/display/dc/optc/dcn201/dcn201_optc.h new file mode 100644 index 000000000000..e9545b73513a --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/optc/dcn201/dcn201_optc.h @@ -0,0 +1,74 @@ +/* + * Copyright 2012-15 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_OPTC_DCN201_H__ +#define __DC_OPTC_DCN201_H__ + +#include "dcn20/dcn20_optc.h" + +#define TG_COMMON_REG_LIST_DCN201(inst) \ + TG_COMMON_REG_LIST_DCN(inst),\ + SRI(OTG_GLOBAL_CONTROL1, OTG, inst),\ + SRI(OTG_GLOBAL_CONTROL2, OTG, inst),\ + SRI(OTG_GSL_WINDOW_X, OTG, inst),\ + SRI(OTG_GSL_WINDOW_Y, OTG, inst),\ + SRI(OTG_VUPDATE_KEEPOUT, OTG, inst),\ + SRI(OTG_DSC_START_POSITION, OTG, inst),\ + SRI(OPTC_DATA_FORMAT_CONTROL, ODM, inst),\ + SRI(OPTC_BYTES_PER_PIXEL, ODM, inst),\ + SRI(OPTC_WIDTH_CONTROL, ODM, inst),\ + SR(DWB_SOURCE_SELECT) + +#define TG_COMMON_MASK_SH_LIST_DCN201(mask_sh)\ + TG_COMMON_MASK_SH_LIST_DCN(mask_sh),\ + SF(OTG0_OTG_GLOBAL_CONTROL1, MASTER_UPDATE_LOCK_DB_X, mask_sh),\ + SF(OTG0_OTG_GLOBAL_CONTROL1, MASTER_UPDATE_LOCK_DB_Y, mask_sh),\ + SF(OTG0_OTG_GLOBAL_CONTROL1, MASTER_UPDATE_LOCK_DB_EN, mask_sh),\ + SF(OTG0_OTG_GLOBAL_CONTROL2, GLOBAL_UPDATE_LOCK_EN, mask_sh),\ + SF(OTG0_OTG_DOUBLE_BUFFER_CONTROL, OTG_RANGE_TIMING_DBUF_UPDATE_MODE, mask_sh),\ + SF(OTG0_OTG_GSL_WINDOW_X, OTG_GSL_WINDOW_START_X, mask_sh),\ + SF(OTG0_OTG_GSL_WINDOW_X, OTG_GSL_WINDOW_END_X, mask_sh), \ + SF(OTG0_OTG_GSL_WINDOW_Y, OTG_GSL_WINDOW_START_Y, mask_sh),\ + SF(OTG0_OTG_GSL_WINDOW_Y, OTG_GSL_WINDOW_END_Y, mask_sh),\ + SF(OTG0_OTG_VUPDATE_KEEPOUT, OTG_MASTER_UPDATE_LOCK_VUPDATE_KEEPOUT_EN, mask_sh), \ + SF(OTG0_OTG_VUPDATE_KEEPOUT, MASTER_UPDATE_LOCK_VUPDATE_KEEPOUT_START_OFFSET, mask_sh), \ + SF(OTG0_OTG_VUPDATE_KEEPOUT, MASTER_UPDATE_LOCK_VUPDATE_KEEPOUT_END_OFFSET, mask_sh), \ + SF(OTG0_OTG_GSL_CONTROL, OTG_GSL_MASTER_MODE, mask_sh), \ + SF(OTG0_OTG_GSL_CONTROL, OTG_MASTER_UPDATE_LOCK_GSL_EN, mask_sh), \ + SF(OTG0_OTG_DSC_START_POSITION, OTG_DSC_START_POSITION_X, mask_sh), \ + SF(OTG0_OTG_DSC_START_POSITION, OTG_DSC_START_POSITION_LINE_NUM, mask_sh),\ + SF(ODM0_OPTC_DATA_SOURCE_SELECT, OPTC_SEG0_SRC_SEL, mask_sh),\ + SF(ODM0_OPTC_DATA_FORMAT_CONTROL, OPTC_DSC_MODE, mask_sh),\ + SF(ODM0_OPTC_BYTES_PER_PIXEL, OPTC_DSC_BYTES_PER_PIXEL, mask_sh),\ + SF(ODM0_OPTC_WIDTH_CONTROL, OPTC_DSC_SLICE_WIDTH, mask_sh),\ + SF(DWB_SOURCE_SELECT, OPTC_DWB0_SOURCE_SELECT, mask_sh),\ + SF(DWB_SOURCE_SELECT, OPTC_DWB1_SOURCE_SELECT, mask_sh),\ + SF(DWB_SOURCE_SELECT, OPTC_DWB1_SOURCE_SELECT, mask_sh) + +void dcn201_timing_generator_init(struct optc *optc); + +bool optc201_is_two_pixels_per_containter(const struct dc_crtc_timing *timing); + +#endif diff --git a/drivers/gpu/drm/amd/display/dc/optc/dcn30/dcn30_optc.c b/drivers/gpu/drm/amd/display/dc/optc/dcn30/dcn30_optc.c new file mode 100644 index 000000000000..b97bdb868a0e --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/optc/dcn30/dcn30_optc.c @@ -0,0 +1,393 @@ +/* + * Copyright 2020 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 "reg_helper.h" +#include "dcn30_optc.h" +#include "dc.h" +#include "dcn_calc_math.h" +#include "dc_dmub_srv.h" + +#include "dml/dcn30/dcn30_fpu.h" +#include "dc_trace.h" + +#define REG(reg)\ + optc1->tg_regs->reg + +#define CTX \ + optc1->base.ctx + +#undef FN +#define FN(reg_name, field_name) \ + optc1->tg_shift->field_name, optc1->tg_mask->field_name + +void optc3_triplebuffer_lock(struct timing_generator *optc) +{ + struct optc *optc1 = DCN10TG_FROM_TG(optc); + + REG_UPDATE(OTG_GLOBAL_CONTROL2, + OTG_MASTER_UPDATE_LOCK_SEL, optc->inst); + + REG_SET(OTG_VUPDATE_KEEPOUT, 0, + OTG_MASTER_UPDATE_LOCK_VUPDATE_KEEPOUT_EN, 1); + + REG_SET(OTG_MASTER_UPDATE_LOCK, 0, + OTG_MASTER_UPDATE_LOCK, 1); + + REG_WAIT(OTG_MASTER_UPDATE_LOCK, + UPDATE_LOCK_STATUS, 1, + 1, 10); + + TRACE_OPTC_LOCK_UNLOCK_STATE(optc1, optc->inst, true); +} + +void optc3_lock_doublebuffer_enable(struct timing_generator *optc) +{ + struct optc *optc1 = DCN10TG_FROM_TG(optc); + uint32_t v_blank_start = 0; + uint32_t v_blank_end = 0; + uint32_t h_blank_start = 0; + uint32_t h_blank_end = 0; + + REG_GET_2(OTG_V_BLANK_START_END, + OTG_V_BLANK_START, &v_blank_start, + OTG_V_BLANK_END, &v_blank_end); + REG_GET_2(OTG_H_BLANK_START_END, + OTG_H_BLANK_START, &h_blank_start, + OTG_H_BLANK_END, &h_blank_end); + + REG_UPDATE_2(OTG_GLOBAL_CONTROL1, + MASTER_UPDATE_LOCK_DB_START_Y, v_blank_start - 1, + MASTER_UPDATE_LOCK_DB_END_Y, v_blank_start); + REG_UPDATE_2(OTG_GLOBAL_CONTROL4, + DIG_UPDATE_POSITION_X, h_blank_start - 180 - 1, + DIG_UPDATE_POSITION_Y, v_blank_start - 1); + // there is a DIG_UPDATE_VCOUNT_MODE and it is 0. + + REG_UPDATE_3(OTG_GLOBAL_CONTROL0, + MASTER_UPDATE_LOCK_DB_START_X, h_blank_start - 200 - 1, + MASTER_UPDATE_LOCK_DB_END_X, h_blank_start - 180, + MASTER_UPDATE_LOCK_DB_EN, 1); + REG_UPDATE(OTG_GLOBAL_CONTROL2, GLOBAL_UPDATE_LOCK_EN, 1); + + REG_SET_3(OTG_VUPDATE_KEEPOUT, 0, + MASTER_UPDATE_LOCK_VUPDATE_KEEPOUT_START_OFFSET, 0, + MASTER_UPDATE_LOCK_VUPDATE_KEEPOUT_END_OFFSET, 100, + OTG_MASTER_UPDATE_LOCK_VUPDATE_KEEPOUT_EN, 1); + + TRACE_OPTC_LOCK_UNLOCK_STATE(optc1, optc->inst, true); +} + +void optc3_lock_doublebuffer_disable(struct timing_generator *optc) +{ + struct optc *optc1 = DCN10TG_FROM_TG(optc); + + REG_UPDATE_2(OTG_GLOBAL_CONTROL0, + MASTER_UPDATE_LOCK_DB_START_X, 0, + MASTER_UPDATE_LOCK_DB_END_X, 0); + REG_UPDATE_2(OTG_GLOBAL_CONTROL1, + MASTER_UPDATE_LOCK_DB_START_Y, 0, + MASTER_UPDATE_LOCK_DB_END_Y, 0); + + REG_UPDATE(OTG_GLOBAL_CONTROL2, GLOBAL_UPDATE_LOCK_EN, 0); + REG_UPDATE(OTG_GLOBAL_CONTROL0, MASTER_UPDATE_LOCK_DB_EN, 0); + + TRACE_OPTC_LOCK_UNLOCK_STATE(optc1, optc->inst, true); +} + +void optc3_lock(struct timing_generator *optc) +{ + struct optc *optc1 = DCN10TG_FROM_TG(optc); + + REG_UPDATE(OTG_GLOBAL_CONTROL2, + OTG_MASTER_UPDATE_LOCK_SEL, optc->inst); + REG_SET(OTG_MASTER_UPDATE_LOCK, 0, + OTG_MASTER_UPDATE_LOCK, 1); + + REG_WAIT(OTG_MASTER_UPDATE_LOCK, + UPDATE_LOCK_STATUS, 1, + 1, 10); + + TRACE_OPTC_LOCK_UNLOCK_STATE(optc1, optc->inst, true); +} + +void optc3_set_out_mux(struct timing_generator *optc, enum otg_out_mux_dest dest) +{ + struct optc *optc1 = DCN10TG_FROM_TG(optc); + + REG_UPDATE(OTG_CONTROL, OTG_OUT_MUX, dest); +} + +void optc3_program_blank_color(struct timing_generator *optc, + const struct tg_color *blank_color) +{ + struct optc *optc1 = DCN10TG_FROM_TG(optc); + + REG_SET_3(OTG_BLANK_DATA_COLOR, 0, + OTG_BLANK_DATA_COLOR_BLUE_CB, blank_color->color_b_cb, + OTG_BLANK_DATA_COLOR_GREEN_Y, blank_color->color_g_y, + OTG_BLANK_DATA_COLOR_RED_CR, blank_color->color_r_cr); + + REG_SET_3(OTG_BLANK_DATA_COLOR_EXT, 0, + OTG_BLANK_DATA_COLOR_BLUE_CB_EXT, blank_color->color_b_cb >> 10, + OTG_BLANK_DATA_COLOR_GREEN_Y_EXT, blank_color->color_g_y >> 10, + OTG_BLANK_DATA_COLOR_RED_CR_EXT, blank_color->color_r_cr >> 10); +} + +void optc3_set_drr_trigger_window(struct timing_generator *optc, + uint32_t window_start, uint32_t window_end) +{ + struct optc *optc1 = DCN10TG_FROM_TG(optc); + + REG_SET_2(OTG_DRR_TRIGGER_WINDOW, 0, + OTG_DRR_TRIGGER_WINDOW_START_X, window_start, + OTG_DRR_TRIGGER_WINDOW_END_X, window_end); +} + +void optc3_set_vtotal_change_limit(struct timing_generator *optc, + uint32_t limit) +{ + struct optc *optc1 = DCN10TG_FROM_TG(optc); + + + REG_SET(OTG_DRR_V_TOTAL_CHANGE, 0, + OTG_DRR_V_TOTAL_CHANGE_LIMIT, limit); +} + + +/* Set DSC-related configuration. + * dsc_mode: 0 disables DSC, other values enable DSC in specified format + * sc_bytes_per_pixel: Bytes per pixel in u3.28 format + * dsc_slice_width: Slice width in pixels + */ +void optc3_set_dsc_config(struct timing_generator *optc, + enum optc_dsc_mode dsc_mode, + uint32_t dsc_bytes_per_pixel, + uint32_t dsc_slice_width) +{ + struct optc *optc1 = DCN10TG_FROM_TG(optc); + + optc2_set_dsc_config(optc, dsc_mode, dsc_bytes_per_pixel, dsc_slice_width); + REG_UPDATE(OTG_V_SYNC_A_CNTL, OTG_V_SYNC_MODE, 0); +} + +void optc3_set_odm_bypass(struct timing_generator *optc, + const struct dc_crtc_timing *dc_crtc_timing) +{ + struct optc *optc1 = DCN10TG_FROM_TG(optc); + enum h_timing_div_mode h_div = H_TIMING_NO_DIV; + + REG_SET_5(OPTC_DATA_SOURCE_SELECT, 0, + OPTC_NUM_OF_INPUT_SEGMENT, 0, + OPTC_SEG0_SRC_SEL, optc->inst, + OPTC_SEG1_SRC_SEL, 0xf, + OPTC_SEG2_SRC_SEL, 0xf, + OPTC_SEG3_SRC_SEL, 0xf + ); + + h_div = optc1_is_two_pixels_per_containter(dc_crtc_timing); + REG_UPDATE(OTG_H_TIMING_CNTL, + OTG_H_TIMING_DIV_MODE, h_div); + + REG_SET(OPTC_MEMORY_CONFIG, 0, + OPTC_MEM_SEL, 0); + optc1->opp_count = 1; +} + +void optc3_set_odm_combine(struct timing_generator *optc, int *opp_id, int opp_cnt, + struct dc_crtc_timing *timing) +{ + struct optc *optc1 = DCN10TG_FROM_TG(optc); + int mpcc_hactive = (timing->h_addressable + timing->h_border_left + timing->h_border_right) + / opp_cnt; + uint32_t memory_mask = 0; + + /* TODO: In pseudocode but does not affect maximus, delete comment if we dont need on asic + * REG_SET(OTG_GLOBAL_CONTROL2, 0, GLOBAL_UPDATE_LOCK_EN, 1); + * Program OTG register MASTER_UPDATE_LOCK_DB_X/Y to the position before DP frame start + * REG_SET_2(OTG_GLOBAL_CONTROL1, 0, + * MASTER_UPDATE_LOCK_DB_X, 160, + * MASTER_UPDATE_LOCK_DB_Y, 240); + */ + + ASSERT(opp_cnt == 2 || opp_cnt == 4); + + /* 2 pieces of memory required for up to 5120 displays, 4 for up to 8192, + * however, for ODM combine we can simplify by always using 4. + */ + if (opp_cnt == 2) { + /* To make sure there's no memory overlap, each instance "reserves" 2 + * memories and they are uniquely combined here. + */ + memory_mask = 0x3 << (opp_id[0] * 2) | 0x3 << (opp_id[1] * 2); + } else if (opp_cnt == 4) { + /* To make sure there's no memory overlap, each instance "reserves" 1 + * memory and they are uniquely combined here. + */ + memory_mask = 0x1 << (opp_id[0] * 2) | 0x1 << (opp_id[1] * 2) | 0x1 << (opp_id[2] * 2) | 0x1 << (opp_id[3] * 2); + } + + if (REG(OPTC_MEMORY_CONFIG)) + REG_SET(OPTC_MEMORY_CONFIG, 0, + OPTC_MEM_SEL, memory_mask); + + if (opp_cnt == 2) { + REG_SET_3(OPTC_DATA_SOURCE_SELECT, 0, + OPTC_NUM_OF_INPUT_SEGMENT, 1, + OPTC_SEG0_SRC_SEL, opp_id[0], + OPTC_SEG1_SRC_SEL, opp_id[1]); + } else if (opp_cnt == 4) { + REG_SET_5(OPTC_DATA_SOURCE_SELECT, 0, + OPTC_NUM_OF_INPUT_SEGMENT, 3, + OPTC_SEG0_SRC_SEL, opp_id[0], + OPTC_SEG1_SRC_SEL, opp_id[1], + OPTC_SEG2_SRC_SEL, opp_id[2], + OPTC_SEG3_SRC_SEL, opp_id[3]); + } + + REG_UPDATE(OPTC_WIDTH_CONTROL, + OPTC_SEGMENT_WIDTH, mpcc_hactive); + + REG_SET(OTG_H_TIMING_CNTL, 0, OTG_H_TIMING_DIV_MODE, opp_cnt - 1); + optc1->opp_count = opp_cnt; +} + +/** + * optc3_set_timing_double_buffer() - DRR double buffering control + * + * Sets double buffer point for V_TOTAL, H_TOTAL, VTOTAL_MIN, + * VTOTAL_MAX, VTOTAL_MIN_SEL and VTOTAL_MAX_SEL registers. + * + * @optc: timing_generator instance. + * @enable: Enable DRR double buffering control if true, disable otherwise. + * + * Options: any time, start of frame, dp start of frame (range timing) + */ +static void optc3_set_timing_double_buffer(struct timing_generator *optc, bool enable) +{ + struct optc *optc1 = DCN10TG_FROM_TG(optc); + uint32_t mode = enable ? 2 : 0; + + REG_UPDATE(OTG_DOUBLE_BUFFER_CONTROL, + OTG_DRR_TIMING_DBUF_UPDATE_MODE, mode); +} + +void optc3_wait_drr_doublebuffer_pending_clear(struct timing_generator *optc) +{ + struct optc *optc1 = DCN10TG_FROM_TG(optc); + + REG_WAIT(OTG_DOUBLE_BUFFER_CONTROL, OTG_DRR_TIMING_DBUF_UPDATE_PENDING, 0, 2, 100000); /* 1 vupdate at 5hz */ + +} + +void optc3_set_vtotal_min_max(struct timing_generator *optc, int vtotal_min, int vtotal_max) +{ + struct dc *dc = optc->ctx->dc; + + if (dc->caps.dmub_caps.mclk_sw && !dc->debug.disable_fams) + dc_dmub_srv_drr_update_cmd(dc, optc->inst, vtotal_min, vtotal_max); + else + optc1_set_vtotal_min_max(optc, vtotal_min, vtotal_max); +} + +void optc3_tg_init(struct timing_generator *optc) +{ + optc3_set_timing_double_buffer(optc, true); + optc1_clear_optc_underflow(optc); +} + +static struct timing_generator_funcs dcn30_tg_funcs = { + .validate_timing = optc1_validate_timing, + .program_timing = optc1_program_timing, + .setup_vertical_interrupt0 = optc1_setup_vertical_interrupt0, + .setup_vertical_interrupt1 = optc1_setup_vertical_interrupt1, + .setup_vertical_interrupt2 = optc1_setup_vertical_interrupt2, + .program_global_sync = optc1_program_global_sync, + .enable_crtc = optc2_enable_crtc, + .disable_crtc = optc1_disable_crtc, + /* used by enable_timing_synchronization. Not need for FPGA */ + .is_counter_moving = optc1_is_counter_moving, + .get_position = optc1_get_position, + .get_frame_count = optc1_get_vblank_counter, + .get_scanoutpos = optc1_get_crtc_scanoutpos, + .get_otg_active_size = optc1_get_otg_active_size, + .set_early_control = optc1_set_early_control, + /* used by enable_timing_synchronization. Not need for FPGA */ + .wait_for_state = optc1_wait_for_state, + .set_blank_color = optc3_program_blank_color, + .did_triggered_reset_occur = optc1_did_triggered_reset_occur, + .triplebuffer_lock = optc3_triplebuffer_lock, + .triplebuffer_unlock = optc2_triplebuffer_unlock, + .enable_reset_trigger = optc1_enable_reset_trigger, + .enable_crtc_reset = optc1_enable_crtc_reset, + .disable_reset_trigger = optc1_disable_reset_trigger, + .lock = optc3_lock, + .unlock = optc1_unlock, + .lock_doublebuffer_enable = optc3_lock_doublebuffer_enable, + .lock_doublebuffer_disable = optc3_lock_doublebuffer_disable, + .enable_optc_clock = optc1_enable_optc_clock, + .set_drr = optc1_set_drr, + .get_last_used_drr_vtotal = optc2_get_last_used_drr_vtotal, + .set_vtotal_min_max = optc3_set_vtotal_min_max, + .set_static_screen_control = optc1_set_static_screen_control, + .program_stereo = optc1_program_stereo, + .is_stereo_left_eye = optc1_is_stereo_left_eye, + .tg_init = optc3_tg_init, + .is_tg_enabled = optc1_is_tg_enabled, + .is_optc_underflow_occurred = optc1_is_optc_underflow_occurred, + .clear_optc_underflow = optc1_clear_optc_underflow, + .setup_global_swap_lock = NULL, + .get_crc = optc1_get_crc, + .configure_crc = optc2_configure_crc, + .set_dsc_config = optc3_set_dsc_config, + .get_dsc_status = optc2_get_dsc_status, + .set_dwb_source = NULL, + .set_odm_bypass = optc3_set_odm_bypass, + .set_odm_combine = optc3_set_odm_combine, + .get_optc_source = optc2_get_optc_source, + .set_out_mux = optc3_set_out_mux, + .set_drr_trigger_window = optc3_set_drr_trigger_window, + .set_vtotal_change_limit = optc3_set_vtotal_change_limit, + .set_gsl = optc2_set_gsl, + .set_gsl_source_select = optc2_set_gsl_source_select, + .set_vtg_params = optc1_set_vtg_params, + .program_manual_trigger = optc2_program_manual_trigger, + .setup_manual_trigger = optc2_setup_manual_trigger, + .get_hw_timing = optc1_get_hw_timing, + .wait_drr_doublebuffer_pending_clear = optc3_wait_drr_doublebuffer_pending_clear, +}; + +void dcn30_timing_generator_init(struct optc *optc1) +{ + optc1->base.funcs = &dcn30_tg_funcs; + + optc1->max_h_total = optc1->tg_mask->OTG_H_TOTAL + 1; + optc1->max_v_total = optc1->tg_mask->OTG_V_TOTAL + 1; + + optc1->min_h_blank = 32; + optc1->min_v_blank = 3; + optc1->min_v_blank_interlace = 5; + optc1->min_h_sync_width = 4; + optc1->min_v_sync_width = 1; +} diff --git a/drivers/gpu/drm/amd/display/dc/optc/dcn30/dcn30_optc.h b/drivers/gpu/drm/amd/display/dc/optc/dcn30/dcn30_optc.h new file mode 100644 index 000000000000..d3a056c12b0d --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/optc/dcn30/dcn30_optc.h @@ -0,0 +1,359 @@ +/* + * Copyright 2020 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_OPTC_DCN30_H__ +#define __DC_OPTC_DCN30_H__ + +#include "dcn20/dcn20_optc.h" + +#define V_TOTAL_REGS_DCN30_SRI(inst) + +#define OPTC_COMMON_REG_LIST_DCN3_BASE(inst) \ + SRI(OTG_VSTARTUP_PARAM, OTG, inst),\ + SRI(OTG_VUPDATE_PARAM, OTG, inst),\ + SRI(OTG_VREADY_PARAM, OTG, inst),\ + SRI(OTG_MASTER_UPDATE_LOCK, OTG, inst),\ + SRI(OTG_GLOBAL_CONTROL0, OTG, inst),\ + SRI(OTG_GLOBAL_CONTROL1, OTG, inst),\ + SRI(OTG_GLOBAL_CONTROL2, OTG, inst),\ + SRI(OTG_GLOBAL_CONTROL4, OTG, inst),\ + SRI(OTG_DOUBLE_BUFFER_CONTROL, OTG, inst),\ + SRI(OTG_H_TOTAL, OTG, inst),\ + SRI(OTG_H_BLANK_START_END, OTG, inst),\ + SRI(OTG_H_SYNC_A, OTG, inst),\ + SRI(OTG_H_SYNC_A_CNTL, OTG, inst),\ + SRI(OTG_H_TIMING_CNTL, OTG, inst),\ + SRI(OTG_V_TOTAL, OTG, inst),\ + SRI(OTG_V_BLANK_START_END, OTG, inst),\ + SRI(OTG_V_SYNC_A, OTG, inst),\ + SRI(OTG_V_SYNC_A_CNTL, OTG, inst),\ + SRI(OTG_CONTROL, OTG, inst),\ + SRI(OTG_STEREO_CONTROL, OTG, inst),\ + SRI(OTG_3D_STRUCTURE_CONTROL, OTG, inst),\ + SRI(OTG_STEREO_STATUS, OTG, inst),\ + SRI(OTG_V_TOTAL_MAX, OTG, inst),\ + SRI(OTG_V_TOTAL_MIN, OTG, inst),\ + SRI(OTG_V_TOTAL_CONTROL, OTG, inst),\ + V_TOTAL_REGS_DCN30_SRI(inst)\ + SRI(OTG_TRIGA_CNTL, OTG, inst),\ + SRI(OTG_FORCE_COUNT_NOW_CNTL, OTG, inst),\ + SRI(OTG_STATIC_SCREEN_CONTROL, OTG, inst),\ + SRI(OTG_STATUS_FRAME_COUNT, OTG, inst),\ + SRI(OTG_STATUS, OTG, inst),\ + SRI(OTG_STATUS_POSITION, OTG, inst),\ + SRI(OTG_NOM_VERT_POSITION, OTG, inst),\ + SRI(OTG_BLANK_DATA_COLOR, OTG, inst),\ + SRI(OTG_BLANK_DATA_COLOR_EXT, OTG, inst),\ + SRI(OTG_M_CONST_DTO0, OTG, inst),\ + SRI(OTG_M_CONST_DTO1, OTG, inst),\ + SRI(OTG_CLOCK_CONTROL, OTG, inst),\ + SRI(OTG_VERTICAL_INTERRUPT0_CONTROL, OTG, inst),\ + SRI(OTG_VERTICAL_INTERRUPT0_POSITION, OTG, inst),\ + SRI(OTG_VERTICAL_INTERRUPT1_CONTROL, OTG, inst),\ + SRI(OTG_VERTICAL_INTERRUPT1_POSITION, OTG, inst),\ + SRI(OTG_VERTICAL_INTERRUPT2_CONTROL, OTG, inst),\ + SRI(OTG_VERTICAL_INTERRUPT2_POSITION, OTG, inst),\ + SRI(OPTC_INPUT_CLOCK_CONTROL, ODM, inst),\ + SRI(OPTC_DATA_SOURCE_SELECT, ODM, inst),\ + SRI(OPTC_INPUT_GLOBAL_CONTROL, ODM, inst),\ + SRI(CONTROL, VTG, inst),\ + SRI(OTG_VERT_SYNC_CONTROL, OTG, inst),\ + SRI(OTG_GSL_CONTROL, OTG, inst),\ + SRI(OTG_CRC_CNTL, OTG, inst),\ + SRI(OTG_CRC_CNTL2, OTG, inst),\ + SRI(OTG_CRC0_DATA_RG, OTG, inst),\ + SRI(OTG_CRC0_DATA_B, OTG, inst),\ + SRI(OTG_CRC0_WINDOWA_X_CONTROL, OTG, inst),\ + SRI(OTG_CRC0_WINDOWA_Y_CONTROL, OTG, inst),\ + SRI(OTG_CRC0_WINDOWB_X_CONTROL, OTG, inst),\ + SRI(OTG_CRC0_WINDOWB_Y_CONTROL, OTG, inst),\ + SR(GSL_SOURCE_SELECT),\ + SRI(OTG_TRIGA_MANUAL_TRIG, OTG, inst),\ + SRI(OTG_DRR_CONTROL, OTG, inst) + + +#define OPTC_COMMON_REG_LIST_DCN3_0(inst) \ + OPTC_COMMON_REG_LIST_DCN3_BASE(inst),\ + SRI(OTG_GLOBAL_CONTROL1, OTG, inst),\ + SRI(OTG_GLOBAL_CONTROL2, OTG, inst),\ + SRI(OTG_GSL_WINDOW_X, OTG, inst),\ + SRI(OTG_GSL_WINDOW_Y, OTG, inst),\ + SRI(OTG_VUPDATE_KEEPOUT, OTG, inst),\ + SRI(OTG_DSC_START_POSITION, OTG, inst),\ + SRI(OTG_CRC_CNTL2, OTG, inst),\ + SRI(OTG_DRR_TRIGGER_WINDOW, OTG, inst),\ + SRI(OTG_DRR_V_TOTAL_CHANGE, OTG, inst),\ + SRI(OPTC_DATA_FORMAT_CONTROL, ODM, inst),\ + SRI(OPTC_BYTES_PER_PIXEL, ODM, inst),\ + SRI(OPTC_WIDTH_CONTROL, ODM, inst),\ + SRI(OPTC_MEMORY_CONFIG, ODM, inst),\ + SR(DWB_SOURCE_SELECT) + +#define DCN30_VTOTAL_REGS_SF(mask_sh) + +#define OPTC_COMMON_MASK_SH_LIST_DCN3_BASE(mask_sh)\ + SF(OTG0_OTG_VSTARTUP_PARAM, VSTARTUP_START, mask_sh),\ + SF(OTG0_OTG_VUPDATE_PARAM, VUPDATE_OFFSET, mask_sh),\ + SF(OTG0_OTG_VUPDATE_PARAM, VUPDATE_WIDTH, mask_sh),\ + SF(OTG0_OTG_VREADY_PARAM, VREADY_OFFSET, mask_sh),\ + SF(OTG0_OTG_MASTER_UPDATE_LOCK, OTG_MASTER_UPDATE_LOCK, mask_sh),\ + SF(OTG0_OTG_MASTER_UPDATE_LOCK, UPDATE_LOCK_STATUS, mask_sh),\ + SF(OTG0_OTG_GLOBAL_CONTROL0, MASTER_UPDATE_LOCK_DB_START_X, mask_sh),\ + SF(OTG0_OTG_GLOBAL_CONTROL0, MASTER_UPDATE_LOCK_DB_END_X, mask_sh),\ + SF(OTG0_OTG_GLOBAL_CONTROL0, MASTER_UPDATE_LOCK_DB_EN, mask_sh),\ + SF(OTG0_OTG_GLOBAL_CONTROL1, MASTER_UPDATE_LOCK_DB_START_Y, mask_sh),\ + SF(OTG0_OTG_GLOBAL_CONTROL1, MASTER_UPDATE_LOCK_DB_END_Y, mask_sh),\ + SF(OTG0_OTG_GLOBAL_CONTROL2, OTG_MASTER_UPDATE_LOCK_SEL, mask_sh),\ + SF(OTG0_OTG_GLOBAL_CONTROL4, DIG_UPDATE_POSITION_X, mask_sh),\ + SF(OTG0_OTG_GLOBAL_CONTROL4, DIG_UPDATE_POSITION_Y, mask_sh),\ + SF(OTG0_OTG_DOUBLE_BUFFER_CONTROL, OTG_UPDATE_PENDING, mask_sh),\ + SF(OTG0_OTG_H_TOTAL, OTG_H_TOTAL, mask_sh),\ + SF(OTG0_OTG_H_BLANK_START_END, OTG_H_BLANK_START, mask_sh),\ + SF(OTG0_OTG_H_BLANK_START_END, OTG_H_BLANK_END, mask_sh),\ + SF(OTG0_OTG_H_SYNC_A, OTG_H_SYNC_A_START, mask_sh),\ + SF(OTG0_OTG_H_SYNC_A, OTG_H_SYNC_A_END, mask_sh),\ + SF(OTG0_OTG_H_SYNC_A_CNTL, OTG_H_SYNC_A_POL, mask_sh),\ + SF(OTG0_OTG_V_TOTAL, OTG_V_TOTAL, mask_sh),\ + SF(OTG0_OTG_V_BLANK_START_END, OTG_V_BLANK_START, mask_sh),\ + SF(OTG0_OTG_V_BLANK_START_END, OTG_V_BLANK_END, mask_sh),\ + SF(OTG0_OTG_V_SYNC_A, OTG_V_SYNC_A_START, mask_sh),\ + SF(OTG0_OTG_V_SYNC_A, OTG_V_SYNC_A_END, mask_sh),\ + SF(OTG0_OTG_V_SYNC_A_CNTL, OTG_V_SYNC_A_POL, mask_sh),\ + SF(OTG0_OTG_V_SYNC_A_CNTL, OTG_V_SYNC_MODE, mask_sh),\ + SF(OTG0_OTG_CONTROL, OTG_MASTER_EN, mask_sh),\ + SF(OTG0_OTG_CONTROL, OTG_START_POINT_CNTL, mask_sh),\ + SF(OTG0_OTG_CONTROL, OTG_DISABLE_POINT_CNTL, mask_sh),\ + SF(OTG0_OTG_CONTROL, OTG_FIELD_NUMBER_CNTL, mask_sh),\ + SF(OTG0_OTG_CONTROL, OTG_OUT_MUX, mask_sh),\ + SF(OTG0_OTG_STEREO_CONTROL, OTG_STEREO_EN, mask_sh),\ + SF(OTG0_OTG_STEREO_CONTROL, OTG_STEREO_SYNC_OUTPUT_LINE_NUM, mask_sh),\ + SF(OTG0_OTG_STEREO_CONTROL, OTG_STEREO_SYNC_OUTPUT_POLARITY, mask_sh),\ + SF(OTG0_OTG_STEREO_CONTROL, OTG_STEREO_EYE_FLAG_POLARITY, mask_sh),\ + SF(OTG0_OTG_STEREO_CONTROL, OTG_DISABLE_STEREOSYNC_OUTPUT_FOR_DP, mask_sh),\ + SF(OTG0_OTG_STEREO_STATUS, OTG_STEREO_CURRENT_EYE, mask_sh),\ + SF(OTG0_OTG_3D_STRUCTURE_CONTROL, OTG_3D_STRUCTURE_EN, mask_sh),\ + SF(OTG0_OTG_3D_STRUCTURE_CONTROL, OTG_3D_STRUCTURE_V_UPDATE_MODE, mask_sh),\ + SF(OTG0_OTG_3D_STRUCTURE_CONTROL, OTG_3D_STRUCTURE_STEREO_SEL_OVR, mask_sh),\ + SF(OTG0_OTG_V_TOTAL_MAX, OTG_V_TOTAL_MAX, mask_sh),\ + SF(OTG0_OTG_V_TOTAL_MIN, OTG_V_TOTAL_MIN, mask_sh),\ + SF(OTG0_OTG_V_TOTAL_CONTROL, OTG_V_TOTAL_MIN_SEL, mask_sh),\ + SF(OTG0_OTG_V_TOTAL_CONTROL, OTG_V_TOTAL_MAX_SEL, mask_sh),\ + SF(OTG0_OTG_V_TOTAL_CONTROL, OTG_FORCE_LOCK_ON_EVENT, mask_sh),\ + SF(OTG0_OTG_V_TOTAL_CONTROL, OTG_SET_V_TOTAL_MIN_MASK_EN, mask_sh),\ + SF(OTG0_OTG_V_TOTAL_CONTROL, OTG_SET_V_TOTAL_MIN_MASK, mask_sh),\ + SF(OTG0_OTG_V_TOTAL_CONTROL, OTG_VTOTAL_MID_REPLACING_MIN_EN, mask_sh),\ + SF(OTG0_OTG_V_TOTAL_CONTROL, OTG_VTOTAL_MID_REPLACING_MAX_EN, mask_sh),\ + DCN30_VTOTAL_REGS_SF(mask_sh)\ + SF(OTG0_OTG_FORCE_COUNT_NOW_CNTL, OTG_FORCE_COUNT_NOW_CLEAR, mask_sh),\ + SF(OTG0_OTG_FORCE_COUNT_NOW_CNTL, OTG_FORCE_COUNT_NOW_MODE, mask_sh),\ + SF(OTG0_OTG_FORCE_COUNT_NOW_CNTL, OTG_FORCE_COUNT_NOW_OCCURRED, mask_sh),\ + SF(OTG0_OTG_TRIGA_CNTL, OTG_TRIGA_SOURCE_SELECT, mask_sh),\ + SF(OTG0_OTG_TRIGA_CNTL, OTG_TRIGA_SOURCE_PIPE_SELECT, mask_sh),\ + SF(OTG0_OTG_TRIGA_CNTL, OTG_TRIGA_RISING_EDGE_DETECT_CNTL, mask_sh),\ + SF(OTG0_OTG_TRIGA_CNTL, OTG_TRIGA_FALLING_EDGE_DETECT_CNTL, mask_sh),\ + SF(OTG0_OTG_TRIGA_CNTL, OTG_TRIGA_POLARITY_SELECT, mask_sh),\ + SF(OTG0_OTG_TRIGA_CNTL, OTG_TRIGA_FREQUENCY_SELECT, mask_sh),\ + SF(OTG0_OTG_TRIGA_CNTL, OTG_TRIGA_DELAY, mask_sh),\ + SF(OTG0_OTG_TRIGA_CNTL, OTG_TRIGA_CLEAR, mask_sh),\ + SF(OTG0_OTG_STATIC_SCREEN_CONTROL, OTG_STATIC_SCREEN_EVENT_MASK, mask_sh),\ + SF(OTG0_OTG_STATIC_SCREEN_CONTROL, OTG_STATIC_SCREEN_FRAME_COUNT, mask_sh),\ + SF(OTG0_OTG_STATUS_FRAME_COUNT, OTG_FRAME_COUNT, mask_sh),\ + SF(OTG0_OTG_STATUS, OTG_V_BLANK, mask_sh),\ + SF(OTG0_OTG_STATUS, OTG_V_ACTIVE_DISP, mask_sh),\ + SF(OTG0_OTG_STATUS_POSITION, OTG_HORZ_COUNT, mask_sh),\ + SF(OTG0_OTG_STATUS_POSITION, OTG_VERT_COUNT, mask_sh),\ + SF(OTG0_OTG_NOM_VERT_POSITION, OTG_VERT_COUNT_NOM, mask_sh),\ + SF(OTG0_OTG_BLANK_DATA_COLOR, OTG_BLANK_DATA_COLOR_BLUE_CB, mask_sh),\ + SF(OTG0_OTG_BLANK_DATA_COLOR, OTG_BLANK_DATA_COLOR_GREEN_Y, mask_sh),\ + SF(OTG0_OTG_BLANK_DATA_COLOR, OTG_BLANK_DATA_COLOR_RED_CR, mask_sh),\ + SF(OTG0_OTG_BLANK_DATA_COLOR_EXT, OTG_BLANK_DATA_COLOR_BLUE_CB_EXT, mask_sh),\ + SF(OTG0_OTG_BLANK_DATA_COLOR_EXT, OTG_BLANK_DATA_COLOR_GREEN_Y_EXT, mask_sh),\ + SF(OTG0_OTG_BLANK_DATA_COLOR_EXT, OTG_BLANK_DATA_COLOR_RED_CR_EXT, mask_sh),\ + SF(OTG0_OTG_M_CONST_DTO0, OTG_M_CONST_DTO_PHASE, mask_sh),\ + SF(OTG0_OTG_M_CONST_DTO1, OTG_M_CONST_DTO_MODULO, mask_sh),\ + SF(OTG0_OTG_CLOCK_CONTROL, OTG_BUSY, mask_sh),\ + SF(OTG0_OTG_CLOCK_CONTROL, OTG_CLOCK_EN, mask_sh),\ + SF(OTG0_OTG_CLOCK_CONTROL, OTG_CLOCK_ON, mask_sh),\ + SF(OTG0_OTG_CLOCK_CONTROL, OTG_CLOCK_GATE_DIS, mask_sh),\ + SF(OTG0_OTG_VERTICAL_INTERRUPT0_CONTROL, OTG_VERTICAL_INTERRUPT0_INT_ENABLE, mask_sh),\ + SF(OTG0_OTG_VERTICAL_INTERRUPT0_POSITION, OTG_VERTICAL_INTERRUPT0_LINE_START, mask_sh),\ + SF(OTG0_OTG_VERTICAL_INTERRUPT0_POSITION, OTG_VERTICAL_INTERRUPT0_LINE_END, mask_sh),\ + SF(OTG0_OTG_VERTICAL_INTERRUPT1_CONTROL, OTG_VERTICAL_INTERRUPT1_INT_ENABLE, mask_sh),\ + SF(OTG0_OTG_VERTICAL_INTERRUPT1_POSITION, OTG_VERTICAL_INTERRUPT1_LINE_START, mask_sh),\ + SF(OTG0_OTG_VERTICAL_INTERRUPT2_CONTROL, OTG_VERTICAL_INTERRUPT2_INT_ENABLE, mask_sh),\ + SF(OTG0_OTG_VERTICAL_INTERRUPT2_POSITION, OTG_VERTICAL_INTERRUPT2_LINE_START, mask_sh),\ + SF(ODM0_OPTC_INPUT_CLOCK_CONTROL, OPTC_INPUT_CLK_EN, mask_sh),\ + SF(ODM0_OPTC_INPUT_CLOCK_CONTROL, OPTC_INPUT_CLK_ON, mask_sh),\ + SF(ODM0_OPTC_INPUT_CLOCK_CONTROL, OPTC_INPUT_CLK_GATE_DIS, mask_sh),\ + SF(ODM0_OPTC_INPUT_GLOBAL_CONTROL, OPTC_UNDERFLOW_OCCURRED_STATUS, mask_sh),\ + SF(ODM0_OPTC_INPUT_GLOBAL_CONTROL, OPTC_UNDERFLOW_CLEAR, mask_sh),\ + SF(VTG0_CONTROL, VTG0_ENABLE, mask_sh),\ + SF(VTG0_CONTROL, VTG0_FP2, mask_sh),\ + SF(VTG0_CONTROL, VTG0_VCOUNT_INIT, mask_sh),\ + SF(OTG0_OTG_VERT_SYNC_CONTROL, OTG_FORCE_VSYNC_NEXT_LINE_OCCURRED, mask_sh),\ + SF(OTG0_OTG_VERT_SYNC_CONTROL, OTG_FORCE_VSYNC_NEXT_LINE_CLEAR, mask_sh),\ + SF(OTG0_OTG_VERT_SYNC_CONTROL, OTG_AUTO_FORCE_VSYNC_MODE, mask_sh),\ + SF(OTG0_OTG_GSL_CONTROL, OTG_GSL0_EN, mask_sh),\ + SF(OTG0_OTG_GSL_CONTROL, OTG_GSL1_EN, mask_sh),\ + SF(OTG0_OTG_GSL_CONTROL, OTG_GSL2_EN, mask_sh),\ + SF(OTG0_OTG_GSL_CONTROL, OTG_GSL_MASTER_EN, mask_sh),\ + SF(OTG0_OTG_GSL_CONTROL, OTG_GSL_FORCE_DELAY, mask_sh),\ + SF(OTG0_OTG_GSL_CONTROL, OTG_GSL_CHECK_ALL_FIELDS, mask_sh),\ + SF(OTG0_OTG_CRC_CNTL, OTG_CRC_CONT_EN, mask_sh),\ + SF(OTG0_OTG_CRC_CNTL, OTG_CRC0_SELECT, mask_sh),\ + SF(OTG0_OTG_CRC_CNTL, OTG_CRC_EN, mask_sh),\ + SF(OTG0_OTG_CRC_CNTL2, OTG_CRC_DSC_MODE, mask_sh),\ + SF(OTG0_OTG_CRC_CNTL2, OTG_CRC_DATA_STREAM_COMBINE_MODE, mask_sh),\ + SF(OTG0_OTG_CRC_CNTL2, OTG_CRC_DATA_STREAM_SPLIT_MODE, mask_sh),\ + SF(OTG0_OTG_CRC_CNTL2, OTG_CRC_DATA_FORMAT, mask_sh),\ + SF(OTG0_OTG_CRC0_DATA_RG, CRC0_R_CR, mask_sh),\ + SF(OTG0_OTG_CRC0_DATA_RG, CRC0_G_Y, mask_sh),\ + SF(OTG0_OTG_CRC0_DATA_B, CRC0_B_CB, mask_sh),\ + SF(OTG0_OTG_CRC0_WINDOWA_X_CONTROL, OTG_CRC0_WINDOWA_X_START, mask_sh),\ + SF(OTG0_OTG_CRC0_WINDOWA_X_CONTROL, OTG_CRC0_WINDOWA_X_END, mask_sh),\ + SF(OTG0_OTG_CRC0_WINDOWA_Y_CONTROL, OTG_CRC0_WINDOWA_Y_START, mask_sh),\ + SF(OTG0_OTG_CRC0_WINDOWA_Y_CONTROL, OTG_CRC0_WINDOWA_Y_END, mask_sh),\ + SF(OTG0_OTG_CRC0_WINDOWB_X_CONTROL, OTG_CRC0_WINDOWB_X_START, mask_sh),\ + SF(OTG0_OTG_CRC0_WINDOWB_X_CONTROL, OTG_CRC0_WINDOWB_X_END, mask_sh),\ + SF(OTG0_OTG_CRC0_WINDOWB_Y_CONTROL, OTG_CRC0_WINDOWB_Y_START, mask_sh),\ + SF(OTG0_OTG_CRC0_WINDOWB_Y_CONTROL, OTG_CRC0_WINDOWB_Y_END, mask_sh),\ + SF(OTG0_OTG_TRIGA_MANUAL_TRIG, OTG_TRIGA_MANUAL_TRIG, mask_sh),\ + SF(GSL_SOURCE_SELECT, GSL0_READY_SOURCE_SEL, mask_sh),\ + SF(GSL_SOURCE_SELECT, GSL1_READY_SOURCE_SEL, mask_sh),\ + SF(GSL_SOURCE_SELECT, GSL2_READY_SOURCE_SEL, mask_sh),\ + SF(OTG0_OTG_GLOBAL_CONTROL2, MANUAL_FLOW_CONTROL_SEL, mask_sh),\ + SF(OTG0_OTG_DRR_CONTROL, OTG_V_TOTAL_LAST_USED_BY_DRR, mask_sh) + +#define OPTC_COMMON_MASK_SH_LIST_DCN3_0(mask_sh)\ + OPTC_COMMON_MASK_SH_LIST_DCN3_BASE(mask_sh),\ + SF(OTG0_OTG_GLOBAL_CONTROL2, GLOBAL_UPDATE_LOCK_EN, mask_sh),\ + SF(OTG0_OTG_GSL_WINDOW_X, OTG_GSL_WINDOW_START_X, mask_sh),\ + SF(OTG0_OTG_GSL_WINDOW_X, OTG_GSL_WINDOW_END_X, mask_sh), \ + SF(OTG0_OTG_GSL_WINDOW_Y, OTG_GSL_WINDOW_START_Y, mask_sh),\ + SF(OTG0_OTG_GSL_WINDOW_Y, OTG_GSL_WINDOW_END_Y, mask_sh),\ + SF(OTG0_OTG_VUPDATE_KEEPOUT, OTG_MASTER_UPDATE_LOCK_VUPDATE_KEEPOUT_EN, mask_sh), \ + SF(OTG0_OTG_VUPDATE_KEEPOUT, MASTER_UPDATE_LOCK_VUPDATE_KEEPOUT_START_OFFSET, mask_sh), \ + SF(OTG0_OTG_VUPDATE_KEEPOUT, MASTER_UPDATE_LOCK_VUPDATE_KEEPOUT_END_OFFSET, mask_sh), \ + SF(OTG0_OTG_GSL_CONTROL, OTG_GSL_MASTER_MODE, mask_sh), \ + SF(OTG0_OTG_GSL_CONTROL, OTG_MASTER_UPDATE_LOCK_GSL_EN, mask_sh), \ + SF(OTG0_OTG_DSC_START_POSITION, OTG_DSC_START_POSITION_X, mask_sh), \ + SF(OTG0_OTG_DSC_START_POSITION, OTG_DSC_START_POSITION_LINE_NUM, mask_sh),\ + SF(OTG0_OTG_CRC_CNTL2, OTG_CRC_DSC_MODE, mask_sh),\ + SF(OTG0_OTG_CRC_CNTL2, OTG_CRC_DATA_STREAM_COMBINE_MODE, mask_sh),\ + SF(OTG0_OTG_CRC_CNTL2, OTG_CRC_DATA_STREAM_SPLIT_MODE, mask_sh),\ + SF(OTG0_OTG_CRC_CNTL2, OTG_CRC_DATA_FORMAT, mask_sh),\ + SF(ODM0_OPTC_DATA_SOURCE_SELECT, OPTC_SEG0_SRC_SEL, mask_sh),\ + SF(ODM0_OPTC_DATA_SOURCE_SELECT, OPTC_SEG1_SRC_SEL, mask_sh),\ + SF(ODM0_OPTC_DATA_SOURCE_SELECT, OPTC_NUM_OF_INPUT_SEGMENT, mask_sh),\ + SF(ODM0_OPTC_MEMORY_CONFIG, OPTC_MEM_SEL, mask_sh),\ + SF(ODM0_OPTC_DATA_FORMAT_CONTROL, OPTC_DATA_FORMAT, mask_sh),\ + SF(ODM0_OPTC_DATA_FORMAT_CONTROL, OPTC_DSC_MODE, mask_sh),\ + SF(ODM0_OPTC_BYTES_PER_PIXEL, OPTC_DSC_BYTES_PER_PIXEL, mask_sh),\ + SF(ODM0_OPTC_WIDTH_CONTROL, OPTC_DSC_SLICE_WIDTH, mask_sh),\ + SF(ODM0_OPTC_WIDTH_CONTROL, OPTC_SEGMENT_WIDTH, mask_sh),\ + SF(DWB_SOURCE_SELECT, OPTC_DWB0_SOURCE_SELECT, mask_sh),\ + SF(DWB_SOURCE_SELECT, OPTC_DWB1_SOURCE_SELECT, mask_sh),\ + SF(OTG0_OTG_DRR_TRIGGER_WINDOW, OTG_DRR_TRIGGER_WINDOW_START_X, mask_sh),\ + SF(OTG0_OTG_DRR_TRIGGER_WINDOW, OTG_DRR_TRIGGER_WINDOW_END_X, mask_sh),\ + SF(OTG0_OTG_DRR_V_TOTAL_CHANGE, OTG_DRR_V_TOTAL_CHANGE_LIMIT, mask_sh),\ + SF(OTG0_OTG_H_TIMING_CNTL, OTG_H_TIMING_DIV_BY2, mask_sh),\ + SF(OTG0_OTG_DOUBLE_BUFFER_CONTROL, OTG_DRR_TIMING_DBUF_UPDATE_PENDING, mask_sh),\ + SF(OTG0_OTG_DOUBLE_BUFFER_CONTROL, OTG_DRR_TIMING_DBUF_UPDATE_MODE, mask_sh),\ + SF(OTG0_OTG_DOUBLE_BUFFER_CONTROL, OTG_BLANK_DATA_DOUBLE_BUFFER_EN, mask_sh) + +#define OPTC_COMMON_MASK_SH_LIST_DCN30(mask_sh)\ + OPTC_COMMON_MASK_SH_LIST_DCN3_BASE(mask_sh),\ + SF(OTG0_OTG_GLOBAL_CONTROL2, GLOBAL_UPDATE_LOCK_EN, mask_sh),\ + SF(OTG0_OTG_GSL_WINDOW_X, OTG_GSL_WINDOW_START_X, mask_sh),\ + SF(OTG0_OTG_GSL_WINDOW_X, OTG_GSL_WINDOW_END_X, mask_sh), \ + SF(OTG0_OTG_GSL_WINDOW_Y, OTG_GSL_WINDOW_START_Y, mask_sh),\ + SF(OTG0_OTG_GSL_WINDOW_Y, OTG_GSL_WINDOW_END_Y, mask_sh),\ + SF(OTG0_OTG_VUPDATE_KEEPOUT, OTG_MASTER_UPDATE_LOCK_VUPDATE_KEEPOUT_EN, mask_sh), \ + SF(OTG0_OTG_VUPDATE_KEEPOUT, MASTER_UPDATE_LOCK_VUPDATE_KEEPOUT_START_OFFSET, mask_sh), \ + SF(OTG0_OTG_VUPDATE_KEEPOUT, MASTER_UPDATE_LOCK_VUPDATE_KEEPOUT_END_OFFSET, mask_sh), \ + SF(OTG0_OTG_GSL_CONTROL, OTG_GSL_MASTER_MODE, mask_sh), \ + SF(OTG0_OTG_GSL_CONTROL, OTG_MASTER_UPDATE_LOCK_GSL_EN, mask_sh), \ + SF(OTG0_OTG_DSC_START_POSITION, OTG_DSC_START_POSITION_X, mask_sh), \ + SF(OTG0_OTG_DSC_START_POSITION, OTG_DSC_START_POSITION_LINE_NUM, mask_sh),\ + SF(OTG0_OTG_CRC_CNTL2, OTG_CRC_DSC_MODE, mask_sh),\ + SF(OTG0_OTG_CRC_CNTL2, OTG_CRC_DATA_STREAM_COMBINE_MODE, mask_sh),\ + SF(OTG0_OTG_CRC_CNTL2, OTG_CRC_DATA_STREAM_SPLIT_MODE, mask_sh),\ + SF(OTG0_OTG_CRC_CNTL2, OTG_CRC_DATA_FORMAT, mask_sh),\ + SF(ODM0_OPTC_DATA_SOURCE_SELECT, OPTC_SEG0_SRC_SEL, mask_sh),\ + SF(ODM0_OPTC_DATA_SOURCE_SELECT, OPTC_SEG1_SRC_SEL, mask_sh),\ + SF(ODM0_OPTC_DATA_SOURCE_SELECT, OPTC_SEG2_SRC_SEL, mask_sh),\ + SF(ODM0_OPTC_DATA_SOURCE_SELECT, OPTC_SEG3_SRC_SEL, mask_sh),\ + SF(ODM0_OPTC_DATA_SOURCE_SELECT, OPTC_NUM_OF_INPUT_SEGMENT, mask_sh),\ + SF(ODM0_OPTC_MEMORY_CONFIG, OPTC_MEM_SEL, mask_sh),\ + SF(ODM0_OPTC_DATA_FORMAT_CONTROL, OPTC_DATA_FORMAT, mask_sh),\ + SF(ODM0_OPTC_DATA_FORMAT_CONTROL, OPTC_DSC_MODE, mask_sh),\ + SF(ODM0_OPTC_BYTES_PER_PIXEL, OPTC_DSC_BYTES_PER_PIXEL, mask_sh),\ + SF(ODM0_OPTC_WIDTH_CONTROL, OPTC_DSC_SLICE_WIDTH, mask_sh),\ + SF(ODM0_OPTC_WIDTH_CONTROL, OPTC_SEGMENT_WIDTH, mask_sh),\ + SF(DWB_SOURCE_SELECT, OPTC_DWB0_SOURCE_SELECT, mask_sh),\ + SF(DWB_SOURCE_SELECT, OPTC_DWB1_SOURCE_SELECT, mask_sh),\ + SF(OTG0_OTG_DRR_TRIGGER_WINDOW, OTG_DRR_TRIGGER_WINDOW_START_X, mask_sh),\ + SF(OTG0_OTG_DRR_TRIGGER_WINDOW, OTG_DRR_TRIGGER_WINDOW_END_X, mask_sh),\ + SF(OTG0_OTG_DRR_V_TOTAL_CHANGE, OTG_DRR_V_TOTAL_CHANGE_LIMIT, mask_sh),\ + SF(OTG0_OTG_H_TIMING_CNTL, OTG_H_TIMING_DIV_MODE, mask_sh),\ + SF(OTG0_OTG_DOUBLE_BUFFER_CONTROL, OTG_DRR_TIMING_DBUF_UPDATE_PENDING, mask_sh),\ + SF(OTG0_OTG_DOUBLE_BUFFER_CONTROL, OTG_DRR_TIMING_DBUF_UPDATE_MODE, mask_sh) + +void dcn30_timing_generator_init(struct optc *optc1); + +void optc3_set_out_mux(struct timing_generator *optc, enum otg_out_mux_dest dest); + +void optc3_lock(struct timing_generator *optc); + +void optc3_lock_doublebuffer_enable(struct timing_generator *optc); + +void optc3_lock_doublebuffer_disable(struct timing_generator *optc); + +void optc3_set_drr_trigger_window(struct timing_generator *optc, + uint32_t window_start, uint32_t window_end); + +void optc3_triplebuffer_lock(struct timing_generator *optc); + +void optc3_program_blank_color(struct timing_generator *optc, + const struct tg_color *blank_color); + +void optc3_set_vtotal_change_limit(struct timing_generator *optc, + uint32_t limit); + +void optc3_set_dsc_config(struct timing_generator *optc, + enum optc_dsc_mode dsc_mode, + uint32_t dsc_bytes_per_pixel, + uint32_t dsc_slice_width); + +void optc3_set_timing_db_mode(struct timing_generator *optc, bool enable); + +void optc3_set_odm_bypass(struct timing_generator *optc, + const struct dc_crtc_timing *dc_crtc_timing); +void optc3_set_odm_combine(struct timing_generator *optc, int *opp_id, int opp_cnt, + struct dc_crtc_timing *timing); +void optc3_wait_drr_doublebuffer_pending_clear(struct timing_generator *optc); +void optc3_tg_init(struct timing_generator *optc); +void optc3_set_vtotal_min_max(struct timing_generator *optc, int vtotal_min, int vtotal_max); +#endif /* __DC_OPTC_DCN30_H__ */ diff --git a/drivers/gpu/drm/amd/display/dc/optc/dcn301/dcn301_optc.c b/drivers/gpu/drm/amd/display/dc/optc/dcn301/dcn301_optc.c new file mode 100644 index 000000000000..b3cfcb887905 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/optc/dcn301/dcn301_optc.c @@ -0,0 +1,185 @@ +/* + * Copyright 2020 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 "reg_helper.h" +#include "dcn301_optc.h" +#include "dc.h" +#include "dcn_calc_math.h" +#include "dc_dmub_srv.h" + +#include "dml/dcn30/dcn30_fpu.h" +#include "dc_trace.h" + +#define REG(reg)\ + optc1->tg_regs->reg + +#define CTX \ + optc1->base.ctx + +#undef FN +#define FN(reg_name, field_name) \ + optc1->tg_shift->field_name, optc1->tg_mask->field_name + + +/** + * optc301_set_drr() - Program dynamic refresh rate registers m_OTGx_OTG_V_TOTAL_*. + * + * @optc: timing_generator instance. + * @params: parameters used for Dynamic Refresh Rate. + */ +void optc301_set_drr( + struct timing_generator *optc, + const struct drr_params *params) +{ + struct optc *optc1 = DCN10TG_FROM_TG(optc); + + if (params != NULL && + params->vertical_total_max > 0 && + params->vertical_total_min > 0) { + + if (params->vertical_total_mid != 0) { + + REG_SET(OTG_V_TOTAL_MID, 0, + OTG_V_TOTAL_MID, params->vertical_total_mid - 1); + + REG_UPDATE_2(OTG_V_TOTAL_CONTROL, + OTG_VTOTAL_MID_REPLACING_MAX_EN, 1, + OTG_VTOTAL_MID_FRAME_NUM, + (uint8_t)params->vertical_total_mid_frame_num); + + } + + optc->funcs->set_vtotal_min_max(optc, params->vertical_total_min - 1, params->vertical_total_max - 1); + + REG_UPDATE_5(OTG_V_TOTAL_CONTROL, + OTG_V_TOTAL_MIN_SEL, 1, + OTG_V_TOTAL_MAX_SEL, 1, + OTG_FORCE_LOCK_ON_EVENT, 0, + OTG_SET_V_TOTAL_MIN_MASK_EN, 0, + OTG_SET_V_TOTAL_MIN_MASK, 0); + // Setup manual flow control for EOF via TRIG_A + optc->funcs->setup_manual_trigger(optc); + + } else { + REG_UPDATE_4(OTG_V_TOTAL_CONTROL, + OTG_SET_V_TOTAL_MIN_MASK, 0, + OTG_V_TOTAL_MIN_SEL, 0, + OTG_V_TOTAL_MAX_SEL, 0, + OTG_FORCE_LOCK_ON_EVENT, 0); + + optc->funcs->set_vtotal_min_max(optc, 0, 0); + } +} + + +void optc301_setup_manual_trigger(struct timing_generator *optc) +{ + struct optc *optc1 = DCN10TG_FROM_TG(optc); + + REG_SET_8(OTG_TRIGA_CNTL, 0, + OTG_TRIGA_SOURCE_SELECT, 21, + OTG_TRIGA_SOURCE_PIPE_SELECT, optc->inst, + OTG_TRIGA_RISING_EDGE_DETECT_CNTL, 1, + OTG_TRIGA_FALLING_EDGE_DETECT_CNTL, 0, + OTG_TRIGA_POLARITY_SELECT, 0, + OTG_TRIGA_FREQUENCY_SELECT, 0, + OTG_TRIGA_DELAY, 0, + OTG_TRIGA_CLEAR, 1); +} + +static struct timing_generator_funcs dcn30_tg_funcs = { + .validate_timing = optc1_validate_timing, + .program_timing = optc1_program_timing, + .setup_vertical_interrupt0 = optc1_setup_vertical_interrupt0, + .setup_vertical_interrupt1 = optc1_setup_vertical_interrupt1, + .setup_vertical_interrupt2 = optc1_setup_vertical_interrupt2, + .program_global_sync = optc1_program_global_sync, + .enable_crtc = optc2_enable_crtc, + .disable_crtc = optc1_disable_crtc, + /* used by enable_timing_synchronization. Not need for FPGA */ + .is_counter_moving = optc1_is_counter_moving, + .get_position = optc1_get_position, + .get_frame_count = optc1_get_vblank_counter, + .get_scanoutpos = optc1_get_crtc_scanoutpos, + .get_otg_active_size = optc1_get_otg_active_size, + .set_early_control = optc1_set_early_control, + /* used by enable_timing_synchronization. Not need for FPGA */ + .wait_for_state = optc1_wait_for_state, + .set_blank_color = optc3_program_blank_color, + .did_triggered_reset_occur = optc1_did_triggered_reset_occur, + .triplebuffer_lock = optc3_triplebuffer_lock, + .triplebuffer_unlock = optc2_triplebuffer_unlock, + .enable_reset_trigger = optc1_enable_reset_trigger, + .enable_crtc_reset = optc1_enable_crtc_reset, + .disable_reset_trigger = optc1_disable_reset_trigger, + .lock = optc3_lock, + .unlock = optc1_unlock, + .lock_doublebuffer_enable = optc3_lock_doublebuffer_enable, + .lock_doublebuffer_disable = optc3_lock_doublebuffer_disable, + .enable_optc_clock = optc1_enable_optc_clock, + .set_drr = optc301_set_drr, + .get_last_used_drr_vtotal = optc2_get_last_used_drr_vtotal, + .set_vtotal_min_max = optc3_set_vtotal_min_max, + .set_static_screen_control = optc1_set_static_screen_control, + .program_stereo = optc1_program_stereo, + .is_stereo_left_eye = optc1_is_stereo_left_eye, + .tg_init = optc3_tg_init, + .is_tg_enabled = optc1_is_tg_enabled, + .is_optc_underflow_occurred = optc1_is_optc_underflow_occurred, + .clear_optc_underflow = optc1_clear_optc_underflow, + .setup_global_swap_lock = NULL, + .get_crc = optc1_get_crc, + .configure_crc = optc2_configure_crc, + .set_dsc_config = optc3_set_dsc_config, + .get_dsc_status = optc2_get_dsc_status, + .set_dwb_source = NULL, + .set_odm_bypass = optc3_set_odm_bypass, + .set_odm_combine = optc3_set_odm_combine, + .get_optc_source = optc2_get_optc_source, + .set_out_mux = optc3_set_out_mux, + .set_drr_trigger_window = optc3_set_drr_trigger_window, + .set_vtotal_change_limit = optc3_set_vtotal_change_limit, + .set_gsl = optc2_set_gsl, + .set_gsl_source_select = optc2_set_gsl_source_select, + .set_vtg_params = optc1_set_vtg_params, + .program_manual_trigger = optc2_program_manual_trigger, + .setup_manual_trigger = optc301_setup_manual_trigger, + .get_hw_timing = optc1_get_hw_timing, + .wait_drr_doublebuffer_pending_clear = optc3_wait_drr_doublebuffer_pending_clear, +}; + +void dcn301_timing_generator_init(struct optc *optc1) +{ + optc1->base.funcs = &dcn30_tg_funcs; + + optc1->max_h_total = optc1->tg_mask->OTG_H_TOTAL + 1; + optc1->max_v_total = optc1->tg_mask->OTG_V_TOTAL + 1; + + optc1->min_h_blank = 32; + optc1->min_v_blank = 3; + optc1->min_v_blank_interlace = 5; + optc1->min_h_sync_width = 4; + optc1->min_v_sync_width = 1; +} diff --git a/drivers/gpu/drm/amd/display/dc/optc/dcn301/dcn301_optc.h b/drivers/gpu/drm/amd/display/dc/optc/dcn301/dcn301_optc.h new file mode 100644 index 000000000000..b49585682a15 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/optc/dcn301/dcn301_optc.h @@ -0,0 +1,36 @@ +/* + * Copyright 2020 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_OPTC_DCN301_H__ +#define __DC_OPTC_DCN301_H__ + +#include "dcn20/dcn20_optc.h" +#include "dcn30/dcn30_optc.h" + +void dcn301_timing_generator_init(struct optc *optc1); +void optc301_setup_manual_trigger(struct timing_generator *optc); +void optc301_set_drr(struct timing_generator *optc, const struct drr_params *params); + +#endif /* __DC_OPTC_DCN301_H__ */ diff --git a/drivers/gpu/drm/amd/display/dc/optc/dcn31/dcn31_optc.c b/drivers/gpu/drm/amd/display/dc/optc/dcn31/dcn31_optc.c new file mode 100644 index 000000000000..63a677c8ee27 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/optc/dcn31/dcn31_optc.c @@ -0,0 +1,310 @@ +/* + * Copyright 2012-15 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 "dcn31_optc.h" + +#include "dcn30/dcn30_optc.h" +#include "reg_helper.h" +#include "dc.h" +#include "dcn_calc_math.h" + +#define REG(reg)\ + optc1->tg_regs->reg + +#define CTX \ + optc1->base.ctx + +#undef FN +#define FN(reg_name, field_name) \ + optc1->tg_shift->field_name, optc1->tg_mask->field_name + +static void optc31_set_odm_combine(struct timing_generator *optc, int *opp_id, int opp_cnt, + struct dc_crtc_timing *timing) +{ + struct optc *optc1 = DCN10TG_FROM_TG(optc); + int mpcc_hactive = (timing->h_addressable + timing->h_border_left + timing->h_border_right) + / opp_cnt; + uint32_t memory_mask = 0; + int mem_count_per_opp = (mpcc_hactive + 2559) / 2560; + + /* Assume less than 6 pipes */ + if (opp_cnt == 4) { + if (mem_count_per_opp == 1) + memory_mask = 0xf; + else { + ASSERT(mem_count_per_opp == 2); + memory_mask = 0xff; + } + } else if (mem_count_per_opp == 1) + memory_mask = 0x1 << (opp_id[0] * 2) | 0x1 << (opp_id[1] * 2); + else if (mem_count_per_opp == 2) + memory_mask = 0x3 << (opp_id[0] * 2) | 0x3 << (opp_id[1] * 2); + else if (mem_count_per_opp == 3) + memory_mask = 0x77; + else if (mem_count_per_opp == 4) + memory_mask = 0xff; + + if (REG(OPTC_MEMORY_CONFIG)) + REG_SET(OPTC_MEMORY_CONFIG, 0, + OPTC_MEM_SEL, memory_mask); + + if (opp_cnt == 2) { + REG_SET_3(OPTC_DATA_SOURCE_SELECT, 0, + OPTC_NUM_OF_INPUT_SEGMENT, 1, + OPTC_SEG0_SRC_SEL, opp_id[0], + OPTC_SEG1_SRC_SEL, opp_id[1]); + } else if (opp_cnt == 4) { + REG_SET_5(OPTC_DATA_SOURCE_SELECT, 0, + OPTC_NUM_OF_INPUT_SEGMENT, 3, + OPTC_SEG0_SRC_SEL, opp_id[0], + OPTC_SEG1_SRC_SEL, opp_id[1], + OPTC_SEG2_SRC_SEL, opp_id[2], + OPTC_SEG3_SRC_SEL, opp_id[3]); + } + + REG_UPDATE(OPTC_WIDTH_CONTROL, + OPTC_SEGMENT_WIDTH, mpcc_hactive); + + REG_SET(OTG_H_TIMING_CNTL, 0, OTG_H_TIMING_DIV_MODE, opp_cnt - 1); + optc1->opp_count = opp_cnt; +} + +/* + * Enable CRTC - call ASIC Control Object to enable Timing generator. + */ +static bool optc31_enable_crtc(struct timing_generator *optc) +{ + struct optc *optc1 = DCN10TG_FROM_TG(optc); + + /* opp instance for OTG, 1 to 1 mapping and odm will adjust */ + REG_UPDATE(OPTC_DATA_SOURCE_SELECT, + OPTC_SEG0_SRC_SEL, optc->inst); + + /* VTG enable first is for HW workaround */ + REG_UPDATE(CONTROL, + VTG0_ENABLE, 1); + + REG_SEQ_START(); + + /* Enable CRTC */ + REG_UPDATE_2(OTG_CONTROL, + OTG_DISABLE_POINT_CNTL, 2, + OTG_MASTER_EN, 1); + + REG_SEQ_SUBMIT(); + REG_SEQ_WAIT_DONE(); + + return true; +} + +/* disable_crtc - call ASIC Control Object to disable Timing generator. */ +static bool optc31_disable_crtc(struct timing_generator *optc) +{ + struct optc *optc1 = DCN10TG_FROM_TG(optc); + /* disable otg request until end of the first line + * in the vertical blank region + */ + REG_UPDATE(OTG_CONTROL, + OTG_MASTER_EN, 0); + + REG_UPDATE(CONTROL, + VTG0_ENABLE, 0); + + /* CRTC disabled, so disable clock. */ + REG_WAIT(OTG_CLOCK_CONTROL, + OTG_BUSY, 0, + 1, 100000); + optc1_clear_optc_underflow(optc); + + return true; +} + +bool optc31_immediate_disable_crtc(struct timing_generator *optc) +{ + struct optc *optc1 = DCN10TG_FROM_TG(optc); + + REG_UPDATE_2(OTG_CONTROL, + OTG_DISABLE_POINT_CNTL, 0, + OTG_MASTER_EN, 0); + + REG_UPDATE(CONTROL, + VTG0_ENABLE, 0); + + /* CRTC disabled, so disable clock. */ + REG_WAIT(OTG_CLOCK_CONTROL, + OTG_BUSY, 0, + 1, 100000); + + /* clear the false state */ + optc1_clear_optc_underflow(optc); + + return true; +} + +void optc31_set_drr( + struct timing_generator *optc, + const struct drr_params *params) +{ + struct optc *optc1 = DCN10TG_FROM_TG(optc); + + if (params != NULL && + params->vertical_total_max > 0 && + params->vertical_total_min > 0) { + + if (params->vertical_total_mid != 0) { + + REG_SET(OTG_V_TOTAL_MID, 0, + OTG_V_TOTAL_MID, params->vertical_total_mid - 1); + + REG_UPDATE_2(OTG_V_TOTAL_CONTROL, + OTG_VTOTAL_MID_REPLACING_MAX_EN, 1, + OTG_VTOTAL_MID_FRAME_NUM, + (uint8_t)params->vertical_total_mid_frame_num); + + } + + optc->funcs->set_vtotal_min_max(optc, params->vertical_total_min - 1, params->vertical_total_max - 1); + + /* + * MIN_MASK_EN is gone and MASK is now always enabled. + * + * To get it to it work with manual trigger we need to make sure + * we program the correct bit. + */ + REG_UPDATE_4(OTG_V_TOTAL_CONTROL, + OTG_V_TOTAL_MIN_SEL, 1, + OTG_V_TOTAL_MAX_SEL, 1, + OTG_FORCE_LOCK_ON_EVENT, 0, + OTG_SET_V_TOTAL_MIN_MASK, (1 << 1)); /* TRIGA */ + + // Setup manual flow control for EOF via TRIG_A + optc->funcs->setup_manual_trigger(optc); + } else { + REG_UPDATE_4(OTG_V_TOTAL_CONTROL, + OTG_SET_V_TOTAL_MIN_MASK, 0, + OTG_V_TOTAL_MIN_SEL, 0, + OTG_V_TOTAL_MAX_SEL, 0, + OTG_FORCE_LOCK_ON_EVENT, 0); + + optc->funcs->set_vtotal_min_max(optc, 0, 0); + } +} + +void optc3_init_odm(struct timing_generator *optc) +{ + struct optc *optc1 = DCN10TG_FROM_TG(optc); + + REG_SET_5(OPTC_DATA_SOURCE_SELECT, 0, + OPTC_NUM_OF_INPUT_SEGMENT, 0, + OPTC_SEG0_SRC_SEL, optc->inst, + OPTC_SEG1_SRC_SEL, 0xf, + OPTC_SEG2_SRC_SEL, 0xf, + OPTC_SEG3_SRC_SEL, 0xf + ); + + REG_SET(OTG_H_TIMING_CNTL, 0, + OTG_H_TIMING_DIV_MODE, 0); + + REG_SET(OPTC_MEMORY_CONFIG, 0, + OPTC_MEM_SEL, 0); + optc1->opp_count = 1; +} + +static struct timing_generator_funcs dcn31_tg_funcs = { + .validate_timing = optc1_validate_timing, + .program_timing = optc1_program_timing, + .setup_vertical_interrupt0 = optc1_setup_vertical_interrupt0, + .setup_vertical_interrupt1 = optc1_setup_vertical_interrupt1, + .setup_vertical_interrupt2 = optc1_setup_vertical_interrupt2, + .program_global_sync = optc1_program_global_sync, + .enable_crtc = optc31_enable_crtc, + .disable_crtc = optc31_disable_crtc, + .immediate_disable_crtc = optc31_immediate_disable_crtc, + /* used by enable_timing_synchronization. Not need for FPGA */ + .is_counter_moving = optc1_is_counter_moving, + .get_position = optc1_get_position, + .get_frame_count = optc1_get_vblank_counter, + .get_scanoutpos = optc1_get_crtc_scanoutpos, + .get_otg_active_size = optc1_get_otg_active_size, + .set_early_control = optc1_set_early_control, + /* used by enable_timing_synchronization. Not need for FPGA */ + .wait_for_state = optc1_wait_for_state, + .set_blank_color = optc3_program_blank_color, + .did_triggered_reset_occur = optc1_did_triggered_reset_occur, + .triplebuffer_lock = optc3_triplebuffer_lock, + .triplebuffer_unlock = optc2_triplebuffer_unlock, + .enable_reset_trigger = optc1_enable_reset_trigger, + .enable_crtc_reset = optc1_enable_crtc_reset, + .disable_reset_trigger = optc1_disable_reset_trigger, + .lock = optc3_lock, + .unlock = optc1_unlock, + .lock_doublebuffer_enable = optc3_lock_doublebuffer_enable, + .lock_doublebuffer_disable = optc3_lock_doublebuffer_disable, + .enable_optc_clock = optc1_enable_optc_clock, + .set_drr = optc31_set_drr, + .get_last_used_drr_vtotal = optc2_get_last_used_drr_vtotal, + .set_vtotal_min_max = optc1_set_vtotal_min_max, + .set_static_screen_control = optc1_set_static_screen_control, + .program_stereo = optc1_program_stereo, + .is_stereo_left_eye = optc1_is_stereo_left_eye, + .tg_init = optc3_tg_init, + .is_tg_enabled = optc1_is_tg_enabled, + .is_optc_underflow_occurred = optc1_is_optc_underflow_occurred, + .clear_optc_underflow = optc1_clear_optc_underflow, + .setup_global_swap_lock = NULL, + .get_crc = optc1_get_crc, + .configure_crc = optc2_configure_crc, + .set_dsc_config = optc3_set_dsc_config, + .get_dsc_status = optc2_get_dsc_status, + .set_dwb_source = NULL, + .set_odm_bypass = optc3_set_odm_bypass, + .set_odm_combine = optc31_set_odm_combine, + .get_optc_source = optc2_get_optc_source, + .set_out_mux = optc3_set_out_mux, + .set_drr_trigger_window = optc3_set_drr_trigger_window, + .set_vtotal_change_limit = optc3_set_vtotal_change_limit, + .set_gsl = optc2_set_gsl, + .set_gsl_source_select = optc2_set_gsl_source_select, + .set_vtg_params = optc1_set_vtg_params, + .program_manual_trigger = optc2_program_manual_trigger, + .setup_manual_trigger = optc2_setup_manual_trigger, + .get_hw_timing = optc1_get_hw_timing, + .init_odm = optc3_init_odm, +}; + +void dcn31_timing_generator_init(struct optc *optc1) +{ + optc1->base.funcs = &dcn31_tg_funcs; + + optc1->max_h_total = optc1->tg_mask->OTG_H_TOTAL + 1; + optc1->max_v_total = optc1->tg_mask->OTG_V_TOTAL + 1; + + optc1->min_h_blank = 32; + optc1->min_v_blank = 3; + optc1->min_v_blank_interlace = 5; + optc1->min_h_sync_width = 4; + optc1->min_v_sync_width = 1; +} + diff --git a/drivers/gpu/drm/amd/display/dc/optc/dcn31/dcn31_optc.h b/drivers/gpu/drm/amd/display/dc/optc/dcn31/dcn31_optc.h new file mode 100644 index 000000000000..30b81a448ce2 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/optc/dcn31/dcn31_optc.h @@ -0,0 +1,267 @@ +/* + * Copyright 2012-15 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_OPTC_DCN31_H__ +#define __DC_OPTC_DCN31_H__ + +#include "dcn10/dcn10_optc.h" + +#define OPTC_COMMON_REG_LIST_DCN3_1(inst) \ + SRI(OTG_VSTARTUP_PARAM, OTG, inst),\ + SRI(OTG_VUPDATE_PARAM, OTG, inst),\ + SRI(OTG_VREADY_PARAM, OTG, inst),\ + SRI(OTG_MASTER_UPDATE_LOCK, OTG, inst),\ + SRI(OTG_GLOBAL_CONTROL0, OTG, inst),\ + SRI(OTG_GLOBAL_CONTROL1, OTG, inst),\ + SRI(OTG_GLOBAL_CONTROL2, OTG, inst),\ + SRI(OTG_GLOBAL_CONTROL4, OTG, inst),\ + SRI(OTG_DOUBLE_BUFFER_CONTROL, OTG, inst),\ + SRI(OTG_H_TOTAL, OTG, inst),\ + SRI(OTG_H_BLANK_START_END, OTG, inst),\ + SRI(OTG_H_SYNC_A, OTG, inst),\ + SRI(OTG_H_SYNC_A_CNTL, OTG, inst),\ + SRI(OTG_H_TIMING_CNTL, OTG, inst),\ + SRI(OTG_V_TOTAL, OTG, inst),\ + SRI(OTG_V_BLANK_START_END, OTG, inst),\ + SRI(OTG_V_SYNC_A, OTG, inst),\ + SRI(OTG_V_SYNC_A_CNTL, OTG, inst),\ + SRI(OTG_CONTROL, OTG, inst),\ + SRI(OTG_STEREO_CONTROL, OTG, inst),\ + SRI(OTG_3D_STRUCTURE_CONTROL, OTG, inst),\ + SRI(OTG_STEREO_STATUS, OTG, inst),\ + SRI(OTG_V_TOTAL_MAX, OTG, inst),\ + SRI(OTG_V_TOTAL_MIN, OTG, inst),\ + SRI(OTG_V_TOTAL_CONTROL, OTG, inst),\ + SRI(OTG_TRIGA_CNTL, OTG, inst),\ + SRI(OTG_FORCE_COUNT_NOW_CNTL, OTG, inst),\ + SRI(OTG_STATIC_SCREEN_CONTROL, OTG, inst),\ + SRI(OTG_STATUS_FRAME_COUNT, OTG, inst),\ + SRI(OTG_STATUS, OTG, inst),\ + SRI(OTG_STATUS_POSITION, OTG, inst),\ + SRI(OTG_NOM_VERT_POSITION, OTG, inst),\ + SRI(OTG_M_CONST_DTO0, OTG, inst),\ + SRI(OTG_M_CONST_DTO1, OTG, inst),\ + SRI(OTG_CLOCK_CONTROL, OTG, inst),\ + SRI(OTG_VERTICAL_INTERRUPT0_CONTROL, OTG, inst),\ + SRI(OTG_VERTICAL_INTERRUPT0_POSITION, OTG, inst),\ + SRI(OTG_VERTICAL_INTERRUPT1_CONTROL, OTG, inst),\ + SRI(OTG_VERTICAL_INTERRUPT1_POSITION, OTG, inst),\ + SRI(OTG_VERTICAL_INTERRUPT2_CONTROL, OTG, inst),\ + SRI(OTG_VERTICAL_INTERRUPT2_POSITION, OTG, inst),\ + SRI(OPTC_INPUT_CLOCK_CONTROL, ODM, inst),\ + SRI(OPTC_DATA_SOURCE_SELECT, ODM, inst),\ + SRI(OPTC_INPUT_GLOBAL_CONTROL, ODM, inst),\ + SRI(CONTROL, VTG, inst),\ + SRI(OTG_VERT_SYNC_CONTROL, OTG, inst),\ + SRI(OTG_GSL_CONTROL, OTG, inst),\ + SRI(OTG_CRC_CNTL, OTG, inst),\ + SRI(OTG_CRC0_DATA_RG, OTG, inst),\ + SRI(OTG_CRC0_DATA_B, OTG, inst),\ + SRI(OTG_CRC0_WINDOWA_X_CONTROL, OTG, inst),\ + SRI(OTG_CRC0_WINDOWA_Y_CONTROL, OTG, inst),\ + SRI(OTG_CRC0_WINDOWB_X_CONTROL, OTG, inst),\ + SRI(OTG_CRC0_WINDOWB_Y_CONTROL, OTG, inst),\ + SR(GSL_SOURCE_SELECT),\ + SRI(OTG_TRIGA_MANUAL_TRIG, OTG, inst),\ + SRI(OTG_GLOBAL_CONTROL1, OTG, inst),\ + SRI(OTG_GLOBAL_CONTROL2, OTG, inst),\ + SRI(OTG_GSL_WINDOW_X, OTG, inst),\ + SRI(OTG_GSL_WINDOW_Y, OTG, inst),\ + SRI(OTG_VUPDATE_KEEPOUT, OTG, inst),\ + SRI(OTG_DSC_START_POSITION, OTG, inst),\ + SRI(OTG_DRR_TRIGGER_WINDOW, OTG, inst),\ + SRI(OTG_DRR_V_TOTAL_CHANGE, OTG, inst),\ + SRI(OPTC_DATA_FORMAT_CONTROL, ODM, inst),\ + SRI(OPTC_BYTES_PER_PIXEL, ODM, inst),\ + SRI(OPTC_WIDTH_CONTROL, ODM, inst),\ + SRI(OPTC_MEMORY_CONFIG, ODM, inst),\ + SRI(OTG_CRC_CNTL2, OTG, inst),\ + SR(DWB_SOURCE_SELECT),\ + SRI(OTG_DRR_CONTROL, OTG, inst) + +#define OPTC_COMMON_MASK_SH_LIST_DCN3_1(mask_sh)\ + SF(OTG0_OTG_VSTARTUP_PARAM, VSTARTUP_START, mask_sh),\ + SF(OTG0_OTG_VUPDATE_PARAM, VUPDATE_OFFSET, mask_sh),\ + SF(OTG0_OTG_VUPDATE_PARAM, VUPDATE_WIDTH, mask_sh),\ + SF(OTG0_OTG_VREADY_PARAM, VREADY_OFFSET, mask_sh),\ + SF(OTG0_OTG_MASTER_UPDATE_LOCK, OTG_MASTER_UPDATE_LOCK, mask_sh),\ + SF(OTG0_OTG_MASTER_UPDATE_LOCK, UPDATE_LOCK_STATUS, mask_sh),\ + SF(OTG0_OTG_GLOBAL_CONTROL0, MASTER_UPDATE_LOCK_DB_START_X, mask_sh),\ + SF(OTG0_OTG_GLOBAL_CONTROL0, MASTER_UPDATE_LOCK_DB_END_X, mask_sh),\ + SF(OTG0_OTG_GLOBAL_CONTROL0, MASTER_UPDATE_LOCK_DB_EN, mask_sh),\ + SF(OTG0_OTG_GLOBAL_CONTROL1, MASTER_UPDATE_LOCK_DB_START_Y, mask_sh),\ + SF(OTG0_OTG_GLOBAL_CONTROL1, MASTER_UPDATE_LOCK_DB_END_Y, mask_sh),\ + SF(OTG0_OTG_GLOBAL_CONTROL2, OTG_MASTER_UPDATE_LOCK_SEL, mask_sh),\ + SF(OTG0_OTG_GLOBAL_CONTROL4, DIG_UPDATE_POSITION_X, mask_sh),\ + SF(OTG0_OTG_GLOBAL_CONTROL4, DIG_UPDATE_POSITION_Y, mask_sh),\ + SF(OTG0_OTG_DOUBLE_BUFFER_CONTROL, OTG_UPDATE_PENDING, mask_sh),\ + SF(OTG0_OTG_H_TOTAL, OTG_H_TOTAL, mask_sh),\ + SF(OTG0_OTG_H_BLANK_START_END, OTG_H_BLANK_START, mask_sh),\ + SF(OTG0_OTG_H_BLANK_START_END, OTG_H_BLANK_END, mask_sh),\ + SF(OTG0_OTG_H_SYNC_A, OTG_H_SYNC_A_START, mask_sh),\ + SF(OTG0_OTG_H_SYNC_A, OTG_H_SYNC_A_END, mask_sh),\ + SF(OTG0_OTG_H_SYNC_A_CNTL, OTG_H_SYNC_A_POL, mask_sh),\ + SF(OTG0_OTG_V_TOTAL, OTG_V_TOTAL, mask_sh),\ + SF(OTG0_OTG_V_BLANK_START_END, OTG_V_BLANK_START, mask_sh),\ + SF(OTG0_OTG_V_BLANK_START_END, OTG_V_BLANK_END, mask_sh),\ + SF(OTG0_OTG_V_SYNC_A, OTG_V_SYNC_A_START, mask_sh),\ + SF(OTG0_OTG_V_SYNC_A, OTG_V_SYNC_A_END, mask_sh),\ + SF(OTG0_OTG_V_SYNC_A_CNTL, OTG_V_SYNC_A_POL, mask_sh),\ + SF(OTG0_OTG_V_SYNC_A_CNTL, OTG_V_SYNC_MODE, mask_sh),\ + SF(OTG0_OTG_CONTROL, OTG_MASTER_EN, mask_sh),\ + SF(OTG0_OTG_CONTROL, OTG_START_POINT_CNTL, mask_sh),\ + SF(OTG0_OTG_CONTROL, OTG_DISABLE_POINT_CNTL, mask_sh),\ + SF(OTG0_OTG_CONTROL, OTG_FIELD_NUMBER_CNTL, mask_sh),\ + SF(OTG0_OTG_CONTROL, OTG_OUT_MUX, mask_sh),\ + SF(OTG0_OTG_STEREO_CONTROL, OTG_STEREO_EN, mask_sh),\ + SF(OTG0_OTG_STEREO_CONTROL, OTG_STEREO_SYNC_OUTPUT_LINE_NUM, mask_sh),\ + SF(OTG0_OTG_STEREO_CONTROL, OTG_STEREO_SYNC_OUTPUT_POLARITY, mask_sh),\ + SF(OTG0_OTG_STEREO_CONTROL, OTG_STEREO_EYE_FLAG_POLARITY, mask_sh),\ + SF(OTG0_OTG_STEREO_CONTROL, OTG_DISABLE_STEREOSYNC_OUTPUT_FOR_DP, mask_sh),\ + SF(OTG0_OTG_STEREO_STATUS, OTG_STEREO_CURRENT_EYE, mask_sh),\ + SF(OTG0_OTG_3D_STRUCTURE_CONTROL, OTG_3D_STRUCTURE_EN, mask_sh),\ + SF(OTG0_OTG_3D_STRUCTURE_CONTROL, OTG_3D_STRUCTURE_V_UPDATE_MODE, mask_sh),\ + SF(OTG0_OTG_3D_STRUCTURE_CONTROL, OTG_3D_STRUCTURE_STEREO_SEL_OVR, mask_sh),\ + SF(OTG0_OTG_V_TOTAL_MAX, OTG_V_TOTAL_MAX, mask_sh),\ + SF(OTG0_OTG_V_TOTAL_MIN, OTG_V_TOTAL_MIN, mask_sh),\ + SF(OTG0_OTG_V_TOTAL_CONTROL, OTG_V_TOTAL_MIN_SEL, mask_sh),\ + SF(OTG0_OTG_V_TOTAL_CONTROL, OTG_V_TOTAL_MAX_SEL, mask_sh),\ + SF(OTG0_OTG_V_TOTAL_CONTROL, OTG_FORCE_LOCK_ON_EVENT, mask_sh),\ + SF(OTG0_OTG_V_TOTAL_CONTROL, OTG_SET_V_TOTAL_MIN_MASK, mask_sh),\ + SF(OTG0_OTG_V_TOTAL_CONTROL, OTG_VTOTAL_MID_REPLACING_MIN_EN, mask_sh),\ + SF(OTG0_OTG_V_TOTAL_CONTROL, OTG_VTOTAL_MID_REPLACING_MAX_EN, mask_sh),\ + SF(OTG0_OTG_FORCE_COUNT_NOW_CNTL, OTG_FORCE_COUNT_NOW_CLEAR, mask_sh),\ + SF(OTG0_OTG_FORCE_COUNT_NOW_CNTL, OTG_FORCE_COUNT_NOW_MODE, mask_sh),\ + SF(OTG0_OTG_FORCE_COUNT_NOW_CNTL, OTG_FORCE_COUNT_NOW_OCCURRED, mask_sh),\ + SF(OTG0_OTG_TRIGA_CNTL, OTG_TRIGA_SOURCE_SELECT, mask_sh),\ + SF(OTG0_OTG_TRIGA_CNTL, OTG_TRIGA_SOURCE_PIPE_SELECT, mask_sh),\ + SF(OTG0_OTG_TRIGA_CNTL, OTG_TRIGA_RISING_EDGE_DETECT_CNTL, mask_sh),\ + SF(OTG0_OTG_TRIGA_CNTL, OTG_TRIGA_FALLING_EDGE_DETECT_CNTL, mask_sh),\ + SF(OTG0_OTG_TRIGA_CNTL, OTG_TRIGA_POLARITY_SELECT, mask_sh),\ + SF(OTG0_OTG_TRIGA_CNTL, OTG_TRIGA_FREQUENCY_SELECT, mask_sh),\ + SF(OTG0_OTG_TRIGA_CNTL, OTG_TRIGA_DELAY, mask_sh),\ + SF(OTG0_OTG_TRIGA_CNTL, OTG_TRIGA_CLEAR, mask_sh),\ + SF(OTG0_OTG_STATIC_SCREEN_CONTROL, OTG_STATIC_SCREEN_EVENT_MASK, mask_sh),\ + SF(OTG0_OTG_STATIC_SCREEN_CONTROL, OTG_STATIC_SCREEN_FRAME_COUNT, mask_sh),\ + SF(OTG0_OTG_STATUS_FRAME_COUNT, OTG_FRAME_COUNT, mask_sh),\ + SF(OTG0_OTG_STATUS, OTG_V_BLANK, mask_sh),\ + SF(OTG0_OTG_STATUS, OTG_V_ACTIVE_DISP, mask_sh),\ + SF(OTG0_OTG_STATUS_POSITION, OTG_HORZ_COUNT, mask_sh),\ + SF(OTG0_OTG_STATUS_POSITION, OTG_VERT_COUNT, mask_sh),\ + SF(OTG0_OTG_NOM_VERT_POSITION, OTG_VERT_COUNT_NOM, mask_sh),\ + SF(OTG0_OTG_M_CONST_DTO0, OTG_M_CONST_DTO_PHASE, mask_sh),\ + SF(OTG0_OTG_M_CONST_DTO1, OTG_M_CONST_DTO_MODULO, mask_sh),\ + SF(OTG0_OTG_CLOCK_CONTROL, OTG_BUSY, mask_sh),\ + SF(OTG0_OTG_CLOCK_CONTROL, OTG_CLOCK_EN, mask_sh),\ + SF(OTG0_OTG_CLOCK_CONTROL, OTG_CLOCK_ON, mask_sh),\ + SF(OTG0_OTG_CLOCK_CONTROL, OTG_CLOCK_GATE_DIS, mask_sh),\ + SF(OTG0_OTG_VERTICAL_INTERRUPT0_CONTROL, OTG_VERTICAL_INTERRUPT0_INT_ENABLE, mask_sh),\ + SF(OTG0_OTG_VERTICAL_INTERRUPT0_POSITION, OTG_VERTICAL_INTERRUPT0_LINE_START, mask_sh),\ + SF(OTG0_OTG_VERTICAL_INTERRUPT0_POSITION, OTG_VERTICAL_INTERRUPT0_LINE_END, mask_sh),\ + SF(OTG0_OTG_VERTICAL_INTERRUPT1_CONTROL, OTG_VERTICAL_INTERRUPT1_INT_ENABLE, mask_sh),\ + SF(OTG0_OTG_VERTICAL_INTERRUPT1_POSITION, OTG_VERTICAL_INTERRUPT1_LINE_START, mask_sh),\ + SF(OTG0_OTG_VERTICAL_INTERRUPT2_CONTROL, OTG_VERTICAL_INTERRUPT2_INT_ENABLE, mask_sh),\ + SF(OTG0_OTG_VERTICAL_INTERRUPT2_POSITION, OTG_VERTICAL_INTERRUPT2_LINE_START, mask_sh),\ + SF(ODM0_OPTC_INPUT_CLOCK_CONTROL, OPTC_INPUT_CLK_EN, mask_sh),\ + SF(ODM0_OPTC_INPUT_CLOCK_CONTROL, OPTC_INPUT_CLK_ON, mask_sh),\ + SF(ODM0_OPTC_INPUT_CLOCK_CONTROL, OPTC_INPUT_CLK_GATE_DIS, mask_sh),\ + SF(ODM0_OPTC_INPUT_GLOBAL_CONTROL, OPTC_UNDERFLOW_OCCURRED_STATUS, mask_sh),\ + SF(ODM0_OPTC_INPUT_GLOBAL_CONTROL, OPTC_UNDERFLOW_CLEAR, mask_sh),\ + SF(VTG0_CONTROL, VTG0_ENABLE, mask_sh),\ + SF(VTG0_CONTROL, VTG0_FP2, mask_sh),\ + SF(VTG0_CONTROL, VTG0_VCOUNT_INIT, mask_sh),\ + SF(OTG0_OTG_VERT_SYNC_CONTROL, OTG_FORCE_VSYNC_NEXT_LINE_OCCURRED, mask_sh),\ + SF(OTG0_OTG_VERT_SYNC_CONTROL, OTG_FORCE_VSYNC_NEXT_LINE_CLEAR, mask_sh),\ + SF(OTG0_OTG_VERT_SYNC_CONTROL, OTG_AUTO_FORCE_VSYNC_MODE, mask_sh),\ + SF(OTG0_OTG_GSL_CONTROL, OTG_GSL0_EN, mask_sh),\ + SF(OTG0_OTG_GSL_CONTROL, OTG_GSL1_EN, mask_sh),\ + SF(OTG0_OTG_GSL_CONTROL, OTG_GSL2_EN, mask_sh),\ + SF(OTG0_OTG_GSL_CONTROL, OTG_GSL_MASTER_EN, mask_sh),\ + SF(OTG0_OTG_GSL_CONTROL, OTG_GSL_FORCE_DELAY, mask_sh),\ + SF(OTG0_OTG_GSL_CONTROL, OTG_GSL_CHECK_ALL_FIELDS, mask_sh),\ + SF(OTG0_OTG_CRC_CNTL, OTG_CRC_CONT_EN, mask_sh),\ + SF(OTG0_OTG_CRC_CNTL, OTG_CRC0_SELECT, mask_sh),\ + SF(OTG0_OTG_CRC_CNTL, OTG_CRC_EN, mask_sh),\ + SF(OTG0_OTG_CRC0_DATA_RG, CRC0_R_CR, mask_sh),\ + SF(OTG0_OTG_CRC0_DATA_RG, CRC0_G_Y, mask_sh),\ + SF(OTG0_OTG_CRC0_DATA_B, CRC0_B_CB, mask_sh),\ + SF(OTG0_OTG_CRC0_WINDOWA_X_CONTROL, OTG_CRC0_WINDOWA_X_START, mask_sh),\ + SF(OTG0_OTG_CRC0_WINDOWA_X_CONTROL, OTG_CRC0_WINDOWA_X_END, mask_sh),\ + SF(OTG0_OTG_CRC0_WINDOWA_Y_CONTROL, OTG_CRC0_WINDOWA_Y_START, mask_sh),\ + SF(OTG0_OTG_CRC0_WINDOWA_Y_CONTROL, OTG_CRC0_WINDOWA_Y_END, mask_sh),\ + SF(OTG0_OTG_CRC0_WINDOWB_X_CONTROL, OTG_CRC0_WINDOWB_X_START, mask_sh),\ + SF(OTG0_OTG_CRC0_WINDOWB_X_CONTROL, OTG_CRC0_WINDOWB_X_END, mask_sh),\ + SF(OTG0_OTG_CRC0_WINDOWB_Y_CONTROL, OTG_CRC0_WINDOWB_Y_START, mask_sh),\ + SF(OTG0_OTG_CRC0_WINDOWB_Y_CONTROL, OTG_CRC0_WINDOWB_Y_END, mask_sh),\ + SF(OTG0_OTG_TRIGA_MANUAL_TRIG, OTG_TRIGA_MANUAL_TRIG, mask_sh),\ + SF(GSL_SOURCE_SELECT, GSL0_READY_SOURCE_SEL, mask_sh),\ + SF(GSL_SOURCE_SELECT, GSL1_READY_SOURCE_SEL, mask_sh),\ + SF(GSL_SOURCE_SELECT, GSL2_READY_SOURCE_SEL, mask_sh),\ + SF(OTG0_OTG_GLOBAL_CONTROL2, MANUAL_FLOW_CONTROL_SEL, mask_sh),\ + SF(OTG0_OTG_GLOBAL_CONTROL2, GLOBAL_UPDATE_LOCK_EN, mask_sh),\ + SF(OTG0_OTG_GSL_WINDOW_X, OTG_GSL_WINDOW_START_X, mask_sh),\ + SF(OTG0_OTG_GSL_WINDOW_X, OTG_GSL_WINDOW_END_X, mask_sh), \ + SF(OTG0_OTG_GSL_WINDOW_Y, OTG_GSL_WINDOW_START_Y, mask_sh),\ + SF(OTG0_OTG_GSL_WINDOW_Y, OTG_GSL_WINDOW_END_Y, mask_sh),\ + SF(OTG0_OTG_VUPDATE_KEEPOUT, OTG_MASTER_UPDATE_LOCK_VUPDATE_KEEPOUT_EN, mask_sh), \ + SF(OTG0_OTG_VUPDATE_KEEPOUT, MASTER_UPDATE_LOCK_VUPDATE_KEEPOUT_START_OFFSET, mask_sh), \ + SF(OTG0_OTG_VUPDATE_KEEPOUT, MASTER_UPDATE_LOCK_VUPDATE_KEEPOUT_END_OFFSET, mask_sh), \ + SF(OTG0_OTG_GSL_CONTROL, OTG_GSL_MASTER_MODE, mask_sh), \ + SF(OTG0_OTG_GSL_CONTROL, OTG_MASTER_UPDATE_LOCK_GSL_EN, mask_sh), \ + SF(OTG0_OTG_DSC_START_POSITION, OTG_DSC_START_POSITION_X, mask_sh), \ + SF(OTG0_OTG_DSC_START_POSITION, OTG_DSC_START_POSITION_LINE_NUM, mask_sh),\ + SF(ODM0_OPTC_DATA_SOURCE_SELECT, OPTC_SEG0_SRC_SEL, mask_sh),\ + SF(ODM0_OPTC_DATA_SOURCE_SELECT, OPTC_SEG1_SRC_SEL, mask_sh),\ + SF(ODM0_OPTC_DATA_SOURCE_SELECT, OPTC_SEG2_SRC_SEL, mask_sh),\ + SF(ODM0_OPTC_DATA_SOURCE_SELECT, OPTC_SEG3_SRC_SEL, mask_sh),\ + SF(ODM0_OPTC_DATA_SOURCE_SELECT, OPTC_NUM_OF_INPUT_SEGMENT, mask_sh),\ + SF(ODM0_OPTC_MEMORY_CONFIG, OPTC_MEM_SEL, mask_sh),\ + SF(ODM0_OPTC_DATA_FORMAT_CONTROL, OPTC_DATA_FORMAT, mask_sh),\ + SF(ODM0_OPTC_DATA_FORMAT_CONTROL, OPTC_DSC_MODE, mask_sh),\ + SF(ODM0_OPTC_BYTES_PER_PIXEL, OPTC_DSC_BYTES_PER_PIXEL, mask_sh),\ + SF(ODM0_OPTC_WIDTH_CONTROL, OPTC_DSC_SLICE_WIDTH, mask_sh),\ + SF(ODM0_OPTC_WIDTH_CONTROL, OPTC_SEGMENT_WIDTH, mask_sh),\ + SF(DWB_SOURCE_SELECT, OPTC_DWB0_SOURCE_SELECT, mask_sh),\ + SF(DWB_SOURCE_SELECT, OPTC_DWB1_SOURCE_SELECT, mask_sh),\ + SF(OTG0_OTG_DRR_TRIGGER_WINDOW, OTG_DRR_TRIGGER_WINDOW_START_X, mask_sh),\ + SF(OTG0_OTG_DRR_TRIGGER_WINDOW, OTG_DRR_TRIGGER_WINDOW_END_X, mask_sh),\ + SF(OTG0_OTG_DRR_V_TOTAL_CHANGE, OTG_DRR_V_TOTAL_CHANGE_LIMIT, mask_sh),\ + SF(OTG0_OTG_H_TIMING_CNTL, OTG_H_TIMING_DIV_MODE, mask_sh),\ + SF(OTG0_OTG_DOUBLE_BUFFER_CONTROL, OTG_DRR_TIMING_DBUF_UPDATE_MODE, mask_sh),\ + SF(OTG0_OTG_CRC_CNTL2, OTG_CRC_DSC_MODE, mask_sh),\ + SF(OTG0_OTG_CRC_CNTL2, OTG_CRC_DATA_STREAM_COMBINE_MODE, mask_sh),\ + SF(OTG0_OTG_CRC_CNTL2, OTG_CRC_DATA_STREAM_SPLIT_MODE, mask_sh),\ + SF(OTG0_OTG_CRC_CNTL2, OTG_CRC_DATA_FORMAT, mask_sh),\ + SF(OTG0_OTG_DRR_CONTROL, OTG_V_TOTAL_LAST_USED_BY_DRR, mask_sh) + +void dcn31_timing_generator_init(struct optc *optc1); + +bool optc31_immediate_disable_crtc(struct timing_generator *optc); + +void optc31_set_drr(struct timing_generator *optc, const struct drr_params *params); + +void optc3_init_odm(struct timing_generator *optc); + +#endif /* __DC_OPTC_DCN31_H__ */ diff --git a/drivers/gpu/drm/amd/display/dc/optc/dcn314/dcn314_optc.c b/drivers/gpu/drm/amd/display/dc/optc/dcn314/dcn314_optc.c new file mode 100644 index 000000000000..0086cafb0f7a --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/optc/dcn314/dcn314_optc.c @@ -0,0 +1,273 @@ +// SPDX-License-Identifier: MIT +/* + * Copyright 2022 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 "dcn314_optc.h" + +#include "dcn30/dcn30_optc.h" +#include "dcn31/dcn31_optc.h" +#include "reg_helper.h" +#include "dc.h" +#include "dcn_calc_math.h" + +#define REG(reg)\ + optc1->tg_regs->reg + +#define CTX \ + optc1->base.ctx + +#undef FN +#define FN(reg_name, field_name) \ + optc1->tg_shift->field_name, optc1->tg_mask->field_name + +/* + * Enable CRTC + * Enable CRTC - call ASIC Control Object to enable Timing generator. + */ + +static void optc314_set_odm_combine(struct timing_generator *optc, int *opp_id, int opp_cnt, + struct dc_crtc_timing *timing) +{ + struct optc *optc1 = DCN10TG_FROM_TG(optc); + uint32_t memory_mask = 0; + int h_active = timing->h_addressable + timing->h_border_left + timing->h_border_right; + int mpcc_hactive = h_active / opp_cnt; + /* Each memory instance is 2048x(314x2) bits to support half line of 4096 */ + int odm_mem_count = (h_active + 2047) / 2048; + + /* + * display <= 4k : 2 memories + 2 pipes + * 4k < display <= 8k : 4 memories + 2 pipes + * 8k < display <= 12k : 6 memories + 4 pipes + */ + if (opp_cnt == 4) { + if (odm_mem_count <= 2) + memory_mask = 0x3; + else if (odm_mem_count <= 4) + memory_mask = 0xf; + else + memory_mask = 0x3f; + } else { + if (odm_mem_count <= 2) + memory_mask = 0x1 << (opp_id[0] * 2) | 0x1 << (opp_id[1] * 2); + else if (odm_mem_count <= 4) + memory_mask = 0x3 << (opp_id[0] * 2) | 0x3 << (opp_id[1] * 2); + else + memory_mask = 0x77; + } + + REG_SET(OPTC_MEMORY_CONFIG, 0, + OPTC_MEM_SEL, memory_mask); + + if (opp_cnt == 2) { + REG_SET_3(OPTC_DATA_SOURCE_SELECT, 0, + OPTC_NUM_OF_INPUT_SEGMENT, 1, + OPTC_SEG0_SRC_SEL, opp_id[0], + OPTC_SEG1_SRC_SEL, opp_id[1]); + } else if (opp_cnt == 4) { + REG_SET_5(OPTC_DATA_SOURCE_SELECT, 0, + OPTC_NUM_OF_INPUT_SEGMENT, 3, + OPTC_SEG0_SRC_SEL, opp_id[0], + OPTC_SEG1_SRC_SEL, opp_id[1], + OPTC_SEG2_SRC_SEL, opp_id[2], + OPTC_SEG3_SRC_SEL, opp_id[3]); + } + + REG_UPDATE(OPTC_WIDTH_CONTROL, + OPTC_SEGMENT_WIDTH, mpcc_hactive); + + REG_UPDATE(OTG_H_TIMING_CNTL, + OTG_H_TIMING_DIV_MODE, opp_cnt - 1); + optc1->opp_count = opp_cnt; +} + +static bool optc314_enable_crtc(struct timing_generator *optc) +{ + struct optc *optc1 = DCN10TG_FROM_TG(optc); + + /* opp instance for OTG, 1 to 1 mapping and odm will adjust */ + REG_UPDATE(OPTC_DATA_SOURCE_SELECT, + OPTC_SEG0_SRC_SEL, optc->inst); + + /* VTG enable first is for HW workaround */ + REG_UPDATE(CONTROL, + VTG0_ENABLE, 1); + + REG_SEQ_START(); + + /* Enable CRTC */ + REG_UPDATE_2(OTG_CONTROL, + OTG_DISABLE_POINT_CNTL, 2, + OTG_MASTER_EN, 1); + + REG_SEQ_SUBMIT(); + REG_SEQ_WAIT_DONE(); + + return true; +} + +/* disable_crtc */ +static bool optc314_disable_crtc(struct timing_generator *optc) +{ + struct optc *optc1 = DCN10TG_FROM_TG(optc); + + /* disable otg request until end of the first line + * in the vertical blank region + */ + REG_UPDATE(OTG_CONTROL, + OTG_MASTER_EN, 0); + + REG_UPDATE(CONTROL, + VTG0_ENABLE, 0); + + /* CRTC disabled, so disable clock. */ + REG_WAIT(OTG_CLOCK_CONTROL, + OTG_BUSY, 0, + 1, 100000); + + return true; +} + +static void optc314_phantom_crtc_post_enable(struct timing_generator *optc) +{ + struct optc *optc1 = DCN10TG_FROM_TG(optc); + + /* Disable immediately. */ + REG_UPDATE_2(OTG_CONTROL, OTG_DISABLE_POINT_CNTL, 0, OTG_MASTER_EN, 0); + + /* CRTC disabled, so disable clock. */ + REG_WAIT(OTG_CLOCK_CONTROL, OTG_BUSY, 0, 1, 100000); +} + +static void optc314_set_odm_bypass(struct timing_generator *optc, + const struct dc_crtc_timing *dc_crtc_timing) +{ + struct optc *optc1 = DCN10TG_FROM_TG(optc); + enum h_timing_div_mode h_div = H_TIMING_NO_DIV; + + REG_SET_5(OPTC_DATA_SOURCE_SELECT, 0, + OPTC_NUM_OF_INPUT_SEGMENT, 0, + OPTC_SEG0_SRC_SEL, optc->inst, + OPTC_SEG1_SRC_SEL, 0xf, + OPTC_SEG2_SRC_SEL, 0xf, + OPTC_SEG3_SRC_SEL, 0xf + ); + + h_div = optc1_is_two_pixels_per_containter(dc_crtc_timing); + REG_UPDATE(OTG_H_TIMING_CNTL, + OTG_H_TIMING_DIV_MODE, h_div); + + REG_SET(OPTC_MEMORY_CONFIG, 0, + OPTC_MEM_SEL, 0); + optc1->opp_count = 1; +} + +static void optc314_set_h_timing_div_manual_mode(struct timing_generator *optc, bool manual_mode) +{ + struct optc *optc1 = DCN10TG_FROM_TG(optc); + + REG_UPDATE(OTG_H_TIMING_CNTL, + OTG_H_TIMING_DIV_MODE_MANUAL, manual_mode ? 1 : 0); +} + + +static struct timing_generator_funcs dcn314_tg_funcs = { + .validate_timing = optc1_validate_timing, + .program_timing = optc1_program_timing, + .setup_vertical_interrupt0 = optc1_setup_vertical_interrupt0, + .setup_vertical_interrupt1 = optc1_setup_vertical_interrupt1, + .setup_vertical_interrupt2 = optc1_setup_vertical_interrupt2, + .program_global_sync = optc1_program_global_sync, + .enable_crtc = optc314_enable_crtc, + .disable_crtc = optc314_disable_crtc, + .immediate_disable_crtc = optc31_immediate_disable_crtc, + .phantom_crtc_post_enable = optc314_phantom_crtc_post_enable, + /* used by enable_timing_synchronization. Not need for FPGA */ + .is_counter_moving = optc1_is_counter_moving, + .get_position = optc1_get_position, + .get_frame_count = optc1_get_vblank_counter, + .get_scanoutpos = optc1_get_crtc_scanoutpos, + .get_otg_active_size = optc1_get_otg_active_size, + .set_early_control = optc1_set_early_control, + /* used by enable_timing_synchronization. Not need for FPGA */ + .wait_for_state = optc1_wait_for_state, + .set_blank_color = optc3_program_blank_color, + .did_triggered_reset_occur = optc1_did_triggered_reset_occur, + .triplebuffer_lock = optc3_triplebuffer_lock, + .triplebuffer_unlock = optc2_triplebuffer_unlock, + .enable_reset_trigger = optc1_enable_reset_trigger, + .enable_crtc_reset = optc1_enable_crtc_reset, + .disable_reset_trigger = optc1_disable_reset_trigger, + .lock = optc3_lock, + .unlock = optc1_unlock, + .lock_doublebuffer_enable = optc3_lock_doublebuffer_enable, + .lock_doublebuffer_disable = optc3_lock_doublebuffer_disable, + .enable_optc_clock = optc1_enable_optc_clock, + .set_drr = optc31_set_drr, + .get_last_used_drr_vtotal = optc2_get_last_used_drr_vtotal, + .set_vtotal_min_max = optc1_set_vtotal_min_max, + .set_static_screen_control = optc1_set_static_screen_control, + .program_stereo = optc1_program_stereo, + .is_stereo_left_eye = optc1_is_stereo_left_eye, + .tg_init = optc3_tg_init, + .is_tg_enabled = optc1_is_tg_enabled, + .is_optc_underflow_occurred = optc1_is_optc_underflow_occurred, + .clear_optc_underflow = optc1_clear_optc_underflow, + .setup_global_swap_lock = NULL, + .get_crc = optc1_get_crc, + .configure_crc = optc1_configure_crc, + .set_dsc_config = optc3_set_dsc_config, + .get_dsc_status = optc2_get_dsc_status, + .set_dwb_source = NULL, + .get_optc_source = optc2_get_optc_source, + .set_out_mux = optc3_set_out_mux, + .set_drr_trigger_window = optc3_set_drr_trigger_window, + .set_vtotal_change_limit = optc3_set_vtotal_change_limit, + .set_gsl = optc2_set_gsl, + .set_gsl_source_select = optc2_set_gsl_source_select, + .set_vtg_params = optc1_set_vtg_params, + .program_manual_trigger = optc2_program_manual_trigger, + .setup_manual_trigger = optc2_setup_manual_trigger, + .get_hw_timing = optc1_get_hw_timing, + .init_odm = optc3_init_odm, + .set_odm_bypass = optc314_set_odm_bypass, + .set_odm_combine = optc314_set_odm_combine, + .set_h_timing_div_manual_mode = optc314_set_h_timing_div_manual_mode, +}; + +void dcn314_timing_generator_init(struct optc *optc1) +{ + optc1->base.funcs = &dcn314_tg_funcs; + + optc1->max_h_total = optc1->tg_mask->OTG_H_TOTAL + 1; + optc1->max_v_total = optc1->tg_mask->OTG_V_TOTAL + 1; + + optc1->min_h_blank = 32; + optc1->min_v_blank = 3; + optc1->min_v_blank_interlace = 5; + optc1->min_h_sync_width = 4; + optc1->min_v_sync_width = 1; +} + diff --git a/drivers/gpu/drm/amd/display/dc/optc/dcn314/dcn314_optc.h b/drivers/gpu/drm/amd/display/dc/optc/dcn314/dcn314_optc.h new file mode 100644 index 000000000000..99c098e76116 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/optc/dcn314/dcn314_optc.h @@ -0,0 +1,255 @@ +/* SPDX-License-Identifier: MIT */ +/* + * Copyright 2022 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_OPTC_DCN314_H__ +#define __DC_OPTC_DCN314_H__ + +#include "dcn10/dcn10_optc.h" + +#define OPTC_COMMON_REG_LIST_DCN3_14(inst) \ + SRI(OTG_VSTARTUP_PARAM, OTG, inst),\ + SRI(OTG_VUPDATE_PARAM, OTG, inst),\ + SRI(OTG_VREADY_PARAM, OTG, inst),\ + SRI(OTG_MASTER_UPDATE_LOCK, OTG, inst),\ + SRI(OTG_GLOBAL_CONTROL0, OTG, inst),\ + SRI(OTG_GLOBAL_CONTROL1, OTG, inst),\ + SRI(OTG_GLOBAL_CONTROL2, OTG, inst),\ + SRI(OTG_GLOBAL_CONTROL4, OTG, inst),\ + SRI(OTG_DOUBLE_BUFFER_CONTROL, OTG, inst),\ + SRI(OTG_H_TOTAL, OTG, inst),\ + SRI(OTG_H_BLANK_START_END, OTG, inst),\ + SRI(OTG_H_SYNC_A, OTG, inst),\ + SRI(OTG_H_SYNC_A_CNTL, OTG, inst),\ + SRI(OTG_H_TIMING_CNTL, OTG, inst),\ + SRI(OTG_V_TOTAL, OTG, inst),\ + SRI(OTG_V_BLANK_START_END, OTG, inst),\ + SRI(OTG_V_SYNC_A, OTG, inst),\ + SRI(OTG_V_SYNC_A_CNTL, OTG, inst),\ + SRI(OTG_CONTROL, OTG, inst),\ + SRI(OTG_STEREO_CONTROL, OTG, inst),\ + SRI(OTG_3D_STRUCTURE_CONTROL, OTG, inst),\ + SRI(OTG_STEREO_STATUS, OTG, inst),\ + SRI(OTG_V_TOTAL_MAX, OTG, inst),\ + SRI(OTG_V_TOTAL_MIN, OTG, inst),\ + SRI(OTG_V_TOTAL_CONTROL, OTG, inst),\ + SRI(OTG_TRIGA_CNTL, OTG, inst),\ + SRI(OTG_FORCE_COUNT_NOW_CNTL, OTG, inst),\ + SRI(OTG_STATIC_SCREEN_CONTROL, OTG, inst),\ + SRI(OTG_STATUS_FRAME_COUNT, OTG, inst),\ + SRI(OTG_STATUS, OTG, inst),\ + SRI(OTG_STATUS_POSITION, OTG, inst),\ + SRI(OTG_NOM_VERT_POSITION, OTG, inst),\ + SRI(OTG_M_CONST_DTO0, OTG, inst),\ + SRI(OTG_M_CONST_DTO1, OTG, inst),\ + SRI(OTG_CLOCK_CONTROL, OTG, inst),\ + SRI(OTG_VERTICAL_INTERRUPT0_CONTROL, OTG, inst),\ + SRI(OTG_VERTICAL_INTERRUPT0_POSITION, OTG, inst),\ + SRI(OTG_VERTICAL_INTERRUPT1_CONTROL, OTG, inst),\ + SRI(OTG_VERTICAL_INTERRUPT1_POSITION, OTG, inst),\ + SRI(OTG_VERTICAL_INTERRUPT2_CONTROL, OTG, inst),\ + SRI(OTG_VERTICAL_INTERRUPT2_POSITION, OTG, inst),\ + SRI(OPTC_INPUT_CLOCK_CONTROL, ODM, inst),\ + SRI(OPTC_DATA_SOURCE_SELECT, ODM, inst),\ + SRI(OPTC_INPUT_GLOBAL_CONTROL, ODM, inst),\ + SRI(CONTROL, VTG, inst),\ + SRI(OTG_VERT_SYNC_CONTROL, OTG, inst),\ + SRI(OTG_GSL_CONTROL, OTG, inst),\ + SRI(OTG_CRC_CNTL, OTG, inst),\ + SRI(OTG_CRC0_DATA_RG, OTG, inst),\ + SRI(OTG_CRC0_DATA_B, OTG, inst),\ + SRI(OTG_CRC0_WINDOWA_X_CONTROL, OTG, inst),\ + SRI(OTG_CRC0_WINDOWA_Y_CONTROL, OTG, inst),\ + SRI(OTG_CRC0_WINDOWB_X_CONTROL, OTG, inst),\ + SRI(OTG_CRC0_WINDOWB_Y_CONTROL, OTG, inst),\ + SR(GSL_SOURCE_SELECT),\ + SRI(OTG_TRIGA_MANUAL_TRIG, OTG, inst),\ + SRI(OTG_GLOBAL_CONTROL1, OTG, inst),\ + SRI(OTG_GLOBAL_CONTROL2, OTG, inst),\ + SRI(OTG_GSL_WINDOW_X, OTG, inst),\ + SRI(OTG_GSL_WINDOW_Y, OTG, inst),\ + SRI(OTG_VUPDATE_KEEPOUT, OTG, inst),\ + SRI(OTG_DSC_START_POSITION, OTG, inst),\ + SRI(OTG_DRR_TRIGGER_WINDOW, OTG, inst),\ + SRI(OTG_DRR_V_TOTAL_CHANGE, OTG, inst),\ + SRI(OPTC_DATA_FORMAT_CONTROL, ODM, inst),\ + SRI(OPTC_BYTES_PER_PIXEL, ODM, inst),\ + SRI(OPTC_WIDTH_CONTROL, ODM, inst),\ + SRI(OPTC_MEMORY_CONFIG, ODM, inst),\ + SRI(OTG_DRR_CONTROL, OTG, inst) + +#define OPTC_COMMON_MASK_SH_LIST_DCN3_14(mask_sh)\ + SF(OTG0_OTG_VSTARTUP_PARAM, VSTARTUP_START, mask_sh),\ + SF(OTG0_OTG_VUPDATE_PARAM, VUPDATE_OFFSET, mask_sh),\ + SF(OTG0_OTG_VUPDATE_PARAM, VUPDATE_WIDTH, mask_sh),\ + SF(OTG0_OTG_VREADY_PARAM, VREADY_OFFSET, mask_sh),\ + SF(OTG0_OTG_MASTER_UPDATE_LOCK, OTG_MASTER_UPDATE_LOCK, mask_sh),\ + SF(OTG0_OTG_MASTER_UPDATE_LOCK, UPDATE_LOCK_STATUS, mask_sh),\ + SF(OTG0_OTG_GLOBAL_CONTROL0, MASTER_UPDATE_LOCK_DB_START_X, mask_sh),\ + SF(OTG0_OTG_GLOBAL_CONTROL0, MASTER_UPDATE_LOCK_DB_END_X, mask_sh),\ + SF(OTG0_OTG_GLOBAL_CONTROL0, MASTER_UPDATE_LOCK_DB_EN, mask_sh),\ + SF(OTG0_OTG_GLOBAL_CONTROL1, MASTER_UPDATE_LOCK_DB_START_Y, mask_sh),\ + SF(OTG0_OTG_GLOBAL_CONTROL1, MASTER_UPDATE_LOCK_DB_END_Y, mask_sh),\ + SF(OTG0_OTG_GLOBAL_CONTROL2, OTG_MASTER_UPDATE_LOCK_SEL, mask_sh),\ + SF(OTG0_OTG_GLOBAL_CONTROL4, DIG_UPDATE_POSITION_X, mask_sh),\ + SF(OTG0_OTG_GLOBAL_CONTROL4, DIG_UPDATE_POSITION_Y, mask_sh),\ + SF(OTG0_OTG_DOUBLE_BUFFER_CONTROL, OTG_UPDATE_PENDING, mask_sh),\ + SF(OTG0_OTG_H_TOTAL, OTG_H_TOTAL, mask_sh),\ + SF(OTG0_OTG_H_BLANK_START_END, OTG_H_BLANK_START, mask_sh),\ + SF(OTG0_OTG_H_BLANK_START_END, OTG_H_BLANK_END, mask_sh),\ + SF(OTG0_OTG_H_SYNC_A, OTG_H_SYNC_A_START, mask_sh),\ + SF(OTG0_OTG_H_SYNC_A, OTG_H_SYNC_A_END, mask_sh),\ + SF(OTG0_OTG_H_SYNC_A_CNTL, OTG_H_SYNC_A_POL, mask_sh),\ + SF(OTG0_OTG_V_TOTAL, OTG_V_TOTAL, mask_sh),\ + SF(OTG0_OTG_V_BLANK_START_END, OTG_V_BLANK_START, mask_sh),\ + SF(OTG0_OTG_V_BLANK_START_END, OTG_V_BLANK_END, mask_sh),\ + SF(OTG0_OTG_V_SYNC_A, OTG_V_SYNC_A_START, mask_sh),\ + SF(OTG0_OTG_V_SYNC_A, OTG_V_SYNC_A_END, mask_sh),\ + SF(OTG0_OTG_V_SYNC_A_CNTL, OTG_V_SYNC_A_POL, mask_sh),\ + SF(OTG0_OTG_V_SYNC_A_CNTL, OTG_V_SYNC_MODE, mask_sh),\ + SF(OTG0_OTG_CONTROL, OTG_MASTER_EN, mask_sh),\ + SF(OTG0_OTG_CONTROL, OTG_START_POINT_CNTL, mask_sh),\ + SF(OTG0_OTG_CONTROL, OTG_DISABLE_POINT_CNTL, mask_sh),\ + SF(OTG0_OTG_CONTROL, OTG_FIELD_NUMBER_CNTL, mask_sh),\ + SF(OTG0_OTG_CONTROL, OTG_OUT_MUX, mask_sh),\ + SF(OTG0_OTG_STEREO_CONTROL, OTG_STEREO_EN, mask_sh),\ + SF(OTG0_OTG_STEREO_CONTROL, OTG_STEREO_SYNC_OUTPUT_LINE_NUM, mask_sh),\ + SF(OTG0_OTG_STEREO_CONTROL, OTG_STEREO_SYNC_OUTPUT_POLARITY, mask_sh),\ + SF(OTG0_OTG_STEREO_CONTROL, OTG_STEREO_EYE_FLAG_POLARITY, mask_sh),\ + SF(OTG0_OTG_STEREO_CONTROL, OTG_DISABLE_STEREOSYNC_OUTPUT_FOR_DP, mask_sh),\ + SF(OTG0_OTG_STEREO_STATUS, OTG_STEREO_CURRENT_EYE, mask_sh),\ + SF(OTG0_OTG_3D_STRUCTURE_CONTROL, OTG_3D_STRUCTURE_EN, mask_sh),\ + SF(OTG0_OTG_3D_STRUCTURE_CONTROL, OTG_3D_STRUCTURE_V_UPDATE_MODE, mask_sh),\ + SF(OTG0_OTG_3D_STRUCTURE_CONTROL, OTG_3D_STRUCTURE_STEREO_SEL_OVR, mask_sh),\ + SF(OTG0_OTG_V_TOTAL_MAX, OTG_V_TOTAL_MAX, mask_sh),\ + SF(OTG0_OTG_V_TOTAL_MIN, OTG_V_TOTAL_MIN, mask_sh),\ + SF(OTG0_OTG_V_TOTAL_CONTROL, OTG_V_TOTAL_MIN_SEL, mask_sh),\ + SF(OTG0_OTG_V_TOTAL_CONTROL, OTG_V_TOTAL_MAX_SEL, mask_sh),\ + SF(OTG0_OTG_V_TOTAL_CONTROL, OTG_FORCE_LOCK_ON_EVENT, mask_sh),\ + SF(OTG0_OTG_V_TOTAL_CONTROL, OTG_SET_V_TOTAL_MIN_MASK, mask_sh),\ + SF(OTG0_OTG_V_TOTAL_CONTROL, OTG_VTOTAL_MID_REPLACING_MIN_EN, mask_sh),\ + SF(OTG0_OTG_V_TOTAL_CONTROL, OTG_VTOTAL_MID_REPLACING_MAX_EN, mask_sh),\ + SF(OTG0_OTG_FORCE_COUNT_NOW_CNTL, OTG_FORCE_COUNT_NOW_CLEAR, mask_sh),\ + SF(OTG0_OTG_FORCE_COUNT_NOW_CNTL, OTG_FORCE_COUNT_NOW_MODE, mask_sh),\ + SF(OTG0_OTG_FORCE_COUNT_NOW_CNTL, OTG_FORCE_COUNT_NOW_OCCURRED, mask_sh),\ + SF(OTG0_OTG_TRIGA_CNTL, OTG_TRIGA_SOURCE_SELECT, mask_sh),\ + SF(OTG0_OTG_TRIGA_CNTL, OTG_TRIGA_SOURCE_PIPE_SELECT, mask_sh),\ + SF(OTG0_OTG_TRIGA_CNTL, OTG_TRIGA_RISING_EDGE_DETECT_CNTL, mask_sh),\ + SF(OTG0_OTG_TRIGA_CNTL, OTG_TRIGA_FALLING_EDGE_DETECT_CNTL, mask_sh),\ + SF(OTG0_OTG_TRIGA_CNTL, OTG_TRIGA_POLARITY_SELECT, mask_sh),\ + SF(OTG0_OTG_TRIGA_CNTL, OTG_TRIGA_FREQUENCY_SELECT, mask_sh),\ + SF(OTG0_OTG_TRIGA_CNTL, OTG_TRIGA_DELAY, mask_sh),\ + SF(OTG0_OTG_TRIGA_CNTL, OTG_TRIGA_CLEAR, mask_sh),\ + SF(OTG0_OTG_STATIC_SCREEN_CONTROL, OTG_STATIC_SCREEN_EVENT_MASK, mask_sh),\ + SF(OTG0_OTG_STATIC_SCREEN_CONTROL, OTG_STATIC_SCREEN_FRAME_COUNT, mask_sh),\ + SF(OTG0_OTG_STATUS_FRAME_COUNT, OTG_FRAME_COUNT, mask_sh),\ + SF(OTG0_OTG_STATUS, OTG_V_BLANK, mask_sh),\ + SF(OTG0_OTG_STATUS, OTG_V_ACTIVE_DISP, mask_sh),\ + SF(OTG0_OTG_STATUS_POSITION, OTG_HORZ_COUNT, mask_sh),\ + SF(OTG0_OTG_STATUS_POSITION, OTG_VERT_COUNT, mask_sh),\ + SF(OTG0_OTG_NOM_VERT_POSITION, OTG_VERT_COUNT_NOM, mask_sh),\ + SF(OTG0_OTG_M_CONST_DTO0, OTG_M_CONST_DTO_PHASE, mask_sh),\ + SF(OTG0_OTG_M_CONST_DTO1, OTG_M_CONST_DTO_MODULO, mask_sh),\ + SF(OTG0_OTG_CLOCK_CONTROL, OTG_BUSY, mask_sh),\ + SF(OTG0_OTG_CLOCK_CONTROL, OTG_CLOCK_EN, mask_sh),\ + SF(OTG0_OTG_CLOCK_CONTROL, OTG_CLOCK_ON, mask_sh),\ + SF(OTG0_OTG_CLOCK_CONTROL, OTG_CLOCK_GATE_DIS, mask_sh),\ + SF(OTG0_OTG_VERTICAL_INTERRUPT0_CONTROL, OTG_VERTICAL_INTERRUPT0_INT_ENABLE, mask_sh),\ + SF(OTG0_OTG_VERTICAL_INTERRUPT0_POSITION, OTG_VERTICAL_INTERRUPT0_LINE_START, mask_sh),\ + SF(OTG0_OTG_VERTICAL_INTERRUPT0_POSITION, OTG_VERTICAL_INTERRUPT0_LINE_END, mask_sh),\ + SF(OTG0_OTG_VERTICAL_INTERRUPT1_CONTROL, OTG_VERTICAL_INTERRUPT1_INT_ENABLE, mask_sh),\ + SF(OTG0_OTG_VERTICAL_INTERRUPT1_POSITION, OTG_VERTICAL_INTERRUPT1_LINE_START, mask_sh),\ + SF(OTG0_OTG_VERTICAL_INTERRUPT2_CONTROL, OTG_VERTICAL_INTERRUPT2_INT_ENABLE, mask_sh),\ + SF(OTG0_OTG_VERTICAL_INTERRUPT2_POSITION, OTG_VERTICAL_INTERRUPT2_LINE_START, mask_sh),\ + SF(ODM0_OPTC_INPUT_CLOCK_CONTROL, OPTC_INPUT_CLK_EN, mask_sh),\ + SF(ODM0_OPTC_INPUT_CLOCK_CONTROL, OPTC_INPUT_CLK_ON, mask_sh),\ + SF(ODM0_OPTC_INPUT_CLOCK_CONTROL, OPTC_INPUT_CLK_GATE_DIS, mask_sh),\ + SF(ODM0_OPTC_INPUT_GLOBAL_CONTROL, OPTC_UNDERFLOW_OCCURRED_STATUS, mask_sh),\ + SF(ODM0_OPTC_INPUT_GLOBAL_CONTROL, OPTC_UNDERFLOW_CLEAR, mask_sh),\ + SF(VTG0_CONTROL, VTG0_ENABLE, mask_sh),\ + SF(VTG0_CONTROL, VTG0_FP2, mask_sh),\ + SF(VTG0_CONTROL, VTG0_VCOUNT_INIT, mask_sh),\ + SF(OTG0_OTG_VERT_SYNC_CONTROL, OTG_FORCE_VSYNC_NEXT_LINE_OCCURRED, mask_sh),\ + SF(OTG0_OTG_VERT_SYNC_CONTROL, OTG_FORCE_VSYNC_NEXT_LINE_CLEAR, mask_sh),\ + SF(OTG0_OTG_VERT_SYNC_CONTROL, OTG_AUTO_FORCE_VSYNC_MODE, mask_sh),\ + SF(OTG0_OTG_GSL_CONTROL, OTG_GSL0_EN, mask_sh),\ + SF(OTG0_OTG_GSL_CONTROL, OTG_GSL1_EN, mask_sh),\ + SF(OTG0_OTG_GSL_CONTROL, OTG_GSL2_EN, mask_sh),\ + SF(OTG0_OTG_GSL_CONTROL, OTG_GSL_MASTER_EN, mask_sh),\ + SF(OTG0_OTG_GSL_CONTROL, OTG_GSL_FORCE_DELAY, mask_sh),\ + SF(OTG0_OTG_GSL_CONTROL, OTG_GSL_CHECK_ALL_FIELDS, mask_sh),\ + SF(OTG0_OTG_CRC_CNTL, OTG_CRC_CONT_EN, mask_sh),\ + SF(OTG0_OTG_CRC_CNTL, OTG_CRC0_SELECT, mask_sh),\ + SF(OTG0_OTG_CRC_CNTL, OTG_CRC_EN, mask_sh),\ + SF(OTG0_OTG_CRC0_DATA_RG, CRC0_R_CR, mask_sh),\ + SF(OTG0_OTG_CRC0_DATA_RG, CRC0_G_Y, mask_sh),\ + SF(OTG0_OTG_CRC0_DATA_B, CRC0_B_CB, mask_sh),\ + SF(OTG0_OTG_CRC0_WINDOWA_X_CONTROL, OTG_CRC0_WINDOWA_X_START, mask_sh),\ + SF(OTG0_OTG_CRC0_WINDOWA_X_CONTROL, OTG_CRC0_WINDOWA_X_END, mask_sh),\ + SF(OTG0_OTG_CRC0_WINDOWA_Y_CONTROL, OTG_CRC0_WINDOWA_Y_START, mask_sh),\ + SF(OTG0_OTG_CRC0_WINDOWA_Y_CONTROL, OTG_CRC0_WINDOWA_Y_END, mask_sh),\ + SF(OTG0_OTG_CRC0_WINDOWB_X_CONTROL, OTG_CRC0_WINDOWB_X_START, mask_sh),\ + SF(OTG0_OTG_CRC0_WINDOWB_X_CONTROL, OTG_CRC0_WINDOWB_X_END, mask_sh),\ + SF(OTG0_OTG_CRC0_WINDOWB_Y_CONTROL, OTG_CRC0_WINDOWB_Y_START, mask_sh),\ + SF(OTG0_OTG_CRC0_WINDOWB_Y_CONTROL, OTG_CRC0_WINDOWB_Y_END, mask_sh),\ + SF(OTG0_OTG_TRIGA_MANUAL_TRIG, OTG_TRIGA_MANUAL_TRIG, mask_sh),\ + SF(GSL_SOURCE_SELECT, GSL0_READY_SOURCE_SEL, mask_sh),\ + SF(GSL_SOURCE_SELECT, GSL1_READY_SOURCE_SEL, mask_sh),\ + SF(GSL_SOURCE_SELECT, GSL2_READY_SOURCE_SEL, mask_sh),\ + SF(OTG0_OTG_GLOBAL_CONTROL2, MANUAL_FLOW_CONTROL_SEL, mask_sh),\ + SF(OTG0_OTG_GLOBAL_CONTROL2, GLOBAL_UPDATE_LOCK_EN, mask_sh),\ + SF(OTG0_OTG_GSL_WINDOW_X, OTG_GSL_WINDOW_START_X, mask_sh),\ + SF(OTG0_OTG_GSL_WINDOW_X, OTG_GSL_WINDOW_END_X, mask_sh), \ + SF(OTG0_OTG_GSL_WINDOW_Y, OTG_GSL_WINDOW_START_Y, mask_sh),\ + SF(OTG0_OTG_GSL_WINDOW_Y, OTG_GSL_WINDOW_END_Y, mask_sh),\ + SF(OTG0_OTG_VUPDATE_KEEPOUT, OTG_MASTER_UPDATE_LOCK_VUPDATE_KEEPOUT_EN, mask_sh), \ + SF(OTG0_OTG_VUPDATE_KEEPOUT, MASTER_UPDATE_LOCK_VUPDATE_KEEPOUT_START_OFFSET, mask_sh), \ + SF(OTG0_OTG_VUPDATE_KEEPOUT, MASTER_UPDATE_LOCK_VUPDATE_KEEPOUT_END_OFFSET, mask_sh), \ + SF(OTG0_OTG_GSL_CONTROL, OTG_GSL_MASTER_MODE, mask_sh), \ + SF(OTG0_OTG_GSL_CONTROL, OTG_MASTER_UPDATE_LOCK_GSL_EN, mask_sh), \ + SF(OTG0_OTG_DSC_START_POSITION, OTG_DSC_START_POSITION_X, mask_sh), \ + SF(OTG0_OTG_DSC_START_POSITION, OTG_DSC_START_POSITION_LINE_NUM, mask_sh),\ + SF(ODM0_OPTC_DATA_SOURCE_SELECT, OPTC_SEG0_SRC_SEL, mask_sh),\ + SF(ODM0_OPTC_DATA_SOURCE_SELECT, OPTC_SEG1_SRC_SEL, mask_sh),\ + SF(ODM0_OPTC_DATA_SOURCE_SELECT, OPTC_SEG2_SRC_SEL, mask_sh),\ + SF(ODM0_OPTC_DATA_SOURCE_SELECT, OPTC_SEG3_SRC_SEL, mask_sh),\ + SF(ODM0_OPTC_DATA_SOURCE_SELECT, OPTC_NUM_OF_INPUT_SEGMENT, mask_sh),\ + SF(ODM0_OPTC_MEMORY_CONFIG, OPTC_MEM_SEL, mask_sh),\ + SF(ODM0_OPTC_DATA_FORMAT_CONTROL, OPTC_DATA_FORMAT, mask_sh),\ + SF(ODM0_OPTC_DATA_FORMAT_CONTROL, OPTC_DSC_MODE, mask_sh),\ + SF(ODM0_OPTC_BYTES_PER_PIXEL, OPTC_DSC_BYTES_PER_PIXEL, mask_sh),\ + SF(ODM0_OPTC_WIDTH_CONTROL, OPTC_DSC_SLICE_WIDTH, mask_sh),\ + SF(ODM0_OPTC_WIDTH_CONTROL, OPTC_SEGMENT_WIDTH, mask_sh),\ + SF(OTG0_OTG_DRR_TRIGGER_WINDOW, OTG_DRR_TRIGGER_WINDOW_START_X, mask_sh),\ + SF(OTG0_OTG_DRR_TRIGGER_WINDOW, OTG_DRR_TRIGGER_WINDOW_END_X, mask_sh),\ + SF(OTG0_OTG_DRR_V_TOTAL_CHANGE, OTG_DRR_V_TOTAL_CHANGE_LIMIT, mask_sh),\ + SF(OTG0_OTG_H_TIMING_CNTL, OTG_H_TIMING_DIV_MODE, mask_sh),\ + SF(OTG0_OTG_H_TIMING_CNTL, OTG_H_TIMING_DIV_MODE_MANUAL, mask_sh),\ + SF(OTG0_OTG_DOUBLE_BUFFER_CONTROL, OTG_DRR_TIMING_DBUF_UPDATE_MODE, mask_sh),\ + SF(OTG0_OTG_DRR_CONTROL, OTG_V_TOTAL_LAST_USED_BY_DRR, mask_sh) + +void dcn314_timing_generator_init(struct optc *optc1); + +#endif /* __DC_OPTC_DCN314_H__ */ diff --git a/drivers/gpu/drm/amd/display/dc/optc/dcn32/dcn32_optc.c b/drivers/gpu/drm/amd/display/dc/optc/dcn32/dcn32_optc.c new file mode 100644 index 000000000000..a2c4db2cebdd --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/optc/dcn32/dcn32_optc.c @@ -0,0 +1,357 @@ +/* + * Copyright 2022 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 "dcn32_optc.h" + +#include "dcn30/dcn30_optc.h" +#include "dcn31/dcn31_optc.h" +#include "reg_helper.h" +#include "dc.h" +#include "dcn_calc_math.h" +#include "dc_dmub_srv.h" + +#define REG(reg)\ + optc1->tg_regs->reg + +#define CTX \ + optc1->base.ctx + +#undef FN +#define FN(reg_name, field_name) \ + optc1->tg_shift->field_name, optc1->tg_mask->field_name + +static void optc32_set_odm_combine(struct timing_generator *optc, int *opp_id, int opp_cnt, + struct dc_crtc_timing *timing) +{ + struct optc *optc1 = DCN10TG_FROM_TG(optc); + uint32_t memory_mask = 0; + int h_active = timing->h_addressable + timing->h_border_left + timing->h_border_right; + int mpcc_hactive = h_active / opp_cnt; + /* Each memory instance is 2048x(32x2) bits to support half line of 4096 */ + int odm_mem_count = (h_active + 2047) / 2048; + + /* + * display <= 4k : 2 memories + 2 pipes + * 4k < display <= 8k : 4 memories + 2 pipes + * 8k < display <= 12k : 6 memories + 4 pipes + */ + if (opp_cnt == 4) { + if (odm_mem_count <= 2) + memory_mask = 0x3; + else if (odm_mem_count <= 4) + memory_mask = 0xf; + else + memory_mask = 0x3f; + } else { + if (odm_mem_count <= 2) + memory_mask = 0x1 << (opp_id[0] * 2) | 0x1 << (opp_id[1] * 2); + else if (odm_mem_count <= 4) + memory_mask = 0x3 << (opp_id[0] * 2) | 0x3 << (opp_id[1] * 2); + else + memory_mask = 0x77; + } + + REG_SET(OPTC_MEMORY_CONFIG, 0, + OPTC_MEM_SEL, memory_mask); + + if (opp_cnt == 2) { + REG_SET_3(OPTC_DATA_SOURCE_SELECT, 0, + OPTC_NUM_OF_INPUT_SEGMENT, 1, + OPTC_SEG0_SRC_SEL, opp_id[0], + OPTC_SEG1_SRC_SEL, opp_id[1]); + } else if (opp_cnt == 4) { + REG_SET_5(OPTC_DATA_SOURCE_SELECT, 0, + OPTC_NUM_OF_INPUT_SEGMENT, 3, + OPTC_SEG0_SRC_SEL, opp_id[0], + OPTC_SEG1_SRC_SEL, opp_id[1], + OPTC_SEG2_SRC_SEL, opp_id[2], + OPTC_SEG3_SRC_SEL, opp_id[3]); + } + + REG_UPDATE(OPTC_WIDTH_CONTROL, + OPTC_SEGMENT_WIDTH, mpcc_hactive); + + REG_UPDATE(OTG_H_TIMING_CNTL, + OTG_H_TIMING_DIV_MODE, opp_cnt - 1); + optc1->opp_count = opp_cnt; +} + +void optc32_get_odm_combine_segments(struct timing_generator *tg, int *odm_combine_segments) +{ + struct optc *optc1 = DCN10TG_FROM_TG(tg); + int segments; + + REG_GET(OPTC_DATA_SOURCE_SELECT, OPTC_NUM_OF_INPUT_SEGMENT, &segments); + + switch (segments) { + case 0: + *odm_combine_segments = 1; + break; + case 1: + *odm_combine_segments = 2; + break; + case 3: + *odm_combine_segments = 4; + break; + /* 2 is reserved */ + case 2: + default: + *odm_combine_segments = -1; + } +} + +void optc32_set_h_timing_div_manual_mode(struct timing_generator *optc, bool manual_mode) +{ + struct optc *optc1 = DCN10TG_FROM_TG(optc); + + REG_UPDATE(OTG_H_TIMING_CNTL, + OTG_H_TIMING_DIV_MODE_MANUAL, manual_mode ? 1 : 0); +} +/** + * optc32_enable_crtc() - Enable CRTC - call ASIC Control Object to enable Timing generator. + * + * @optc: timing_generator instance. + * + * Return: If CRTC is enabled, return true. + */ +static bool optc32_enable_crtc(struct timing_generator *optc) +{ + struct optc *optc1 = DCN10TG_FROM_TG(optc); + + /* opp instance for OTG, 1 to 1 mapping and odm will adjust */ + REG_UPDATE(OPTC_DATA_SOURCE_SELECT, + OPTC_SEG0_SRC_SEL, optc->inst); + + /* VTG enable first is for HW workaround */ + REG_UPDATE(CONTROL, + VTG0_ENABLE, 1); + + REG_SEQ_START(); + + /* Enable CRTC */ + REG_UPDATE_2(OTG_CONTROL, + OTG_DISABLE_POINT_CNTL, 2, + OTG_MASTER_EN, 1); + + REG_SEQ_SUBMIT(); + REG_SEQ_WAIT_DONE(); + + return true; +} + +/* disable_crtc */ +static bool optc32_disable_crtc(struct timing_generator *optc) +{ + struct optc *optc1 = DCN10TG_FROM_TG(optc); + + /* disable otg request until end of the first line + * in the vertical blank region + */ + REG_UPDATE(OTG_CONTROL, + OTG_MASTER_EN, 0); + + REG_UPDATE(CONTROL, + VTG0_ENABLE, 0); + + /* CRTC disabled, so disable clock. */ + REG_WAIT(OTG_CLOCK_CONTROL, + OTG_BUSY, 0, + 1, 150000); + + return true; +} + +static void optc32_phantom_crtc_post_enable(struct timing_generator *optc) +{ + struct optc *optc1 = DCN10TG_FROM_TG(optc); + + /* Disable immediately. */ + REG_UPDATE_2(OTG_CONTROL, OTG_DISABLE_POINT_CNTL, 0, OTG_MASTER_EN, 0); + + /* CRTC disabled, so disable clock. */ + REG_WAIT(OTG_CLOCK_CONTROL, OTG_BUSY, 0, 1, 100000); +} + +static void optc32_disable_phantom_otg(struct timing_generator *optc) +{ + struct optc *optc1 = DCN10TG_FROM_TG(optc); + + REG_UPDATE(OTG_CONTROL, OTG_MASTER_EN, 0); +} + +void optc32_set_odm_bypass(struct timing_generator *optc, + const struct dc_crtc_timing *dc_crtc_timing) +{ + struct optc *optc1 = DCN10TG_FROM_TG(optc); + enum h_timing_div_mode h_div = H_TIMING_NO_DIV; + + REG_SET_5(OPTC_DATA_SOURCE_SELECT, 0, + OPTC_NUM_OF_INPUT_SEGMENT, 0, + OPTC_SEG0_SRC_SEL, optc->inst, + OPTC_SEG1_SRC_SEL, 0xf, + OPTC_SEG2_SRC_SEL, 0xf, + OPTC_SEG3_SRC_SEL, 0xf + ); + + h_div = optc1_is_two_pixels_per_containter(dc_crtc_timing); + REG_UPDATE(OTG_H_TIMING_CNTL, + OTG_H_TIMING_DIV_MODE, h_div); + + REG_SET(OPTC_MEMORY_CONFIG, 0, + OPTC_MEM_SEL, 0); + optc1->opp_count = 1; +} + +static void optc32_setup_manual_trigger(struct timing_generator *optc) +{ + struct optc *optc1 = DCN10TG_FROM_TG(optc); + struct dc *dc = optc->ctx->dc; + + if (dc->caps.dmub_caps.mclk_sw && !dc->debug.disable_fams) + dc_dmub_srv_set_drr_manual_trigger_cmd(dc, optc->inst); + else { + /* + * MIN_MASK_EN is gone and MASK is now always enabled. + * + * To get it to it work with manual trigger we need to make sure + * we program the correct bit. + */ + REG_UPDATE_4(OTG_V_TOTAL_CONTROL, + OTG_V_TOTAL_MIN_SEL, 1, + OTG_V_TOTAL_MAX_SEL, 1, + OTG_FORCE_LOCK_ON_EVENT, 0, + OTG_SET_V_TOTAL_MIN_MASK, (1 << 1)); /* TRIGA */ + + // Setup manual flow control for EOF via TRIG_A + optc->funcs->setup_manual_trigger(optc); + } +} + +static void optc32_set_drr( + struct timing_generator *optc, + const struct drr_params *params) +{ + struct optc *optc1 = DCN10TG_FROM_TG(optc); + + if (params != NULL && + params->vertical_total_max > 0 && + params->vertical_total_min > 0) { + + if (params->vertical_total_mid != 0) { + + REG_SET(OTG_V_TOTAL_MID, 0, + OTG_V_TOTAL_MID, params->vertical_total_mid - 1); + + REG_UPDATE_2(OTG_V_TOTAL_CONTROL, + OTG_VTOTAL_MID_REPLACING_MAX_EN, 1, + OTG_VTOTAL_MID_FRAME_NUM, + (uint8_t)params->vertical_total_mid_frame_num); + + } + + optc->funcs->set_vtotal_min_max(optc, params->vertical_total_min - 1, params->vertical_total_max - 1); + } + + optc32_setup_manual_trigger(optc); +} + +static struct timing_generator_funcs dcn32_tg_funcs = { + .validate_timing = optc1_validate_timing, + .program_timing = optc1_program_timing, + .setup_vertical_interrupt0 = optc1_setup_vertical_interrupt0, + .setup_vertical_interrupt1 = optc1_setup_vertical_interrupt1, + .setup_vertical_interrupt2 = optc1_setup_vertical_interrupt2, + .program_global_sync = optc1_program_global_sync, + .enable_crtc = optc32_enable_crtc, + .disable_crtc = optc32_disable_crtc, + .phantom_crtc_post_enable = optc32_phantom_crtc_post_enable, + .disable_phantom_crtc = optc32_disable_phantom_otg, + /* used by enable_timing_synchronization. Not need for FPGA */ + .is_counter_moving = optc1_is_counter_moving, + .get_position = optc1_get_position, + .get_frame_count = optc1_get_vblank_counter, + .get_scanoutpos = optc1_get_crtc_scanoutpos, + .get_otg_active_size = optc1_get_otg_active_size, + .set_early_control = optc1_set_early_control, + /* used by enable_timing_synchronization. Not need for FPGA */ + .wait_for_state = optc1_wait_for_state, + .set_blank_color = optc3_program_blank_color, + .did_triggered_reset_occur = optc1_did_triggered_reset_occur, + .triplebuffer_lock = optc3_triplebuffer_lock, + .triplebuffer_unlock = optc2_triplebuffer_unlock, + .enable_reset_trigger = optc1_enable_reset_trigger, + .enable_crtc_reset = optc1_enable_crtc_reset, + .disable_reset_trigger = optc1_disable_reset_trigger, + .lock = optc3_lock, + .unlock = optc1_unlock, + .lock_doublebuffer_enable = optc3_lock_doublebuffer_enable, + .lock_doublebuffer_disable = optc3_lock_doublebuffer_disable, + .enable_optc_clock = optc1_enable_optc_clock, + .set_drr = optc32_set_drr, + .get_last_used_drr_vtotal = optc2_get_last_used_drr_vtotal, + .set_vtotal_min_max = optc3_set_vtotal_min_max, + .set_static_screen_control = optc1_set_static_screen_control, + .program_stereo = optc1_program_stereo, + .is_stereo_left_eye = optc1_is_stereo_left_eye, + .tg_init = optc3_tg_init, + .is_tg_enabled = optc1_is_tg_enabled, + .is_optc_underflow_occurred = optc1_is_optc_underflow_occurred, + .clear_optc_underflow = optc1_clear_optc_underflow, + .setup_global_swap_lock = NULL, + .get_crc = optc1_get_crc, + .configure_crc = optc1_configure_crc, + .set_dsc_config = optc3_set_dsc_config, + .get_dsc_status = optc2_get_dsc_status, + .set_dwb_source = NULL, + .set_odm_bypass = optc32_set_odm_bypass, + .set_odm_combine = optc32_set_odm_combine, + .get_odm_combine_segments = optc32_get_odm_combine_segments, + .set_h_timing_div_manual_mode = optc32_set_h_timing_div_manual_mode, + .get_optc_source = optc2_get_optc_source, + .set_out_mux = optc3_set_out_mux, + .set_drr_trigger_window = optc3_set_drr_trigger_window, + .set_vtotal_change_limit = optc3_set_vtotal_change_limit, + .set_gsl = optc2_set_gsl, + .set_gsl_source_select = optc2_set_gsl_source_select, + .set_vtg_params = optc1_set_vtg_params, + .program_manual_trigger = optc2_program_manual_trigger, + .setup_manual_trigger = optc2_setup_manual_trigger, + .get_hw_timing = optc1_get_hw_timing, +}; + +void dcn32_timing_generator_init(struct optc *optc1) +{ + optc1->base.funcs = &dcn32_tg_funcs; + + optc1->max_h_total = optc1->tg_mask->OTG_H_TOTAL + 1; + optc1->max_v_total = optc1->tg_mask->OTG_V_TOTAL + 1; + + optc1->min_h_blank = 32; + optc1->min_v_blank = 3; + optc1->min_v_blank_interlace = 5; + optc1->min_h_sync_width = 4; + optc1->min_v_sync_width = 1; +} + diff --git a/drivers/gpu/drm/amd/display/dc/optc/dcn32/dcn32_optc.h b/drivers/gpu/drm/amd/display/dc/optc/dcn32/dcn32_optc.h new file mode 100644 index 000000000000..8ce3b178cab0 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/optc/dcn32/dcn32_optc.h @@ -0,0 +1,187 @@ +/* + * 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_OPTC_DCN32_H__ +#define __DC_OPTC_DCN32_H__ + +#include "dcn10/dcn10_optc.h" + +#define OPTC_COMMON_MASK_SH_LIST_DCN3_2(mask_sh)\ + SF(OTG0_OTG_VSTARTUP_PARAM, VSTARTUP_START, mask_sh),\ + SF(OTG0_OTG_VUPDATE_PARAM, VUPDATE_OFFSET, mask_sh),\ + SF(OTG0_OTG_VUPDATE_PARAM, VUPDATE_WIDTH, mask_sh),\ + SF(OTG0_OTG_VREADY_PARAM, VREADY_OFFSET, mask_sh),\ + SF(OTG0_OTG_MASTER_UPDATE_LOCK, OTG_MASTER_UPDATE_LOCK, mask_sh),\ + SF(OTG0_OTG_MASTER_UPDATE_LOCK, UPDATE_LOCK_STATUS, mask_sh),\ + SF(OTG0_OTG_GLOBAL_CONTROL0, MASTER_UPDATE_LOCK_DB_START_X, mask_sh),\ + SF(OTG0_OTG_GLOBAL_CONTROL0, MASTER_UPDATE_LOCK_DB_END_X, mask_sh),\ + SF(OTG0_OTG_GLOBAL_CONTROL0, MASTER_UPDATE_LOCK_DB_EN, mask_sh),\ + SF(OTG0_OTG_GLOBAL_CONTROL1, MASTER_UPDATE_LOCK_DB_START_Y, mask_sh),\ + SF(OTG0_OTG_GLOBAL_CONTROL1, MASTER_UPDATE_LOCK_DB_END_Y, mask_sh),\ + SF(OTG0_OTG_GLOBAL_CONTROL2, OTG_MASTER_UPDATE_LOCK_SEL, mask_sh),\ + SF(OTG0_OTG_GLOBAL_CONTROL4, DIG_UPDATE_POSITION_X, mask_sh),\ + SF(OTG0_OTG_GLOBAL_CONTROL4, DIG_UPDATE_POSITION_Y, mask_sh),\ + SF(OTG0_OTG_DOUBLE_BUFFER_CONTROL, OTG_UPDATE_PENDING, mask_sh),\ + SF(OTG0_OTG_H_TOTAL, OTG_H_TOTAL, mask_sh),\ + SF(OTG0_OTG_H_BLANK_START_END, OTG_H_BLANK_START, mask_sh),\ + SF(OTG0_OTG_H_BLANK_START_END, OTG_H_BLANK_END, mask_sh),\ + SF(OTG0_OTG_H_SYNC_A, OTG_H_SYNC_A_START, mask_sh),\ + SF(OTG0_OTG_H_SYNC_A, OTG_H_SYNC_A_END, mask_sh),\ + SF(OTG0_OTG_H_SYNC_A_CNTL, OTG_H_SYNC_A_POL, mask_sh),\ + SF(OTG0_OTG_V_TOTAL, OTG_V_TOTAL, mask_sh),\ + SF(OTG0_OTG_V_BLANK_START_END, OTG_V_BLANK_START, mask_sh),\ + SF(OTG0_OTG_V_BLANK_START_END, OTG_V_BLANK_END, mask_sh),\ + SF(OTG0_OTG_V_SYNC_A, OTG_V_SYNC_A_START, mask_sh),\ + SF(OTG0_OTG_V_SYNC_A, OTG_V_SYNC_A_END, mask_sh),\ + SF(OTG0_OTG_V_SYNC_A_CNTL, OTG_V_SYNC_A_POL, mask_sh),\ + SF(OTG0_OTG_V_SYNC_A_CNTL, OTG_V_SYNC_MODE, mask_sh),\ + SF(OTG0_OTG_CONTROL, OTG_MASTER_EN, mask_sh),\ + SF(OTG0_OTG_CONTROL, OTG_START_POINT_CNTL, mask_sh),\ + SF(OTG0_OTG_CONTROL, OTG_DISABLE_POINT_CNTL, mask_sh),\ + SF(OTG0_OTG_CONTROL, OTG_FIELD_NUMBER_CNTL, mask_sh),\ + SF(OTG0_OTG_CONTROL, OTG_OUT_MUX, mask_sh),\ + SF(OTG0_OTG_STEREO_CONTROL, OTG_STEREO_EN, mask_sh),\ + SF(OTG0_OTG_STEREO_CONTROL, OTG_STEREO_SYNC_OUTPUT_LINE_NUM, mask_sh),\ + SF(OTG0_OTG_STEREO_CONTROL, OTG_STEREO_SYNC_OUTPUT_POLARITY, mask_sh),\ + SF(OTG0_OTG_STEREO_CONTROL, OTG_STEREO_EYE_FLAG_POLARITY, mask_sh),\ + SF(OTG0_OTG_STEREO_CONTROL, OTG_DISABLE_STEREOSYNC_OUTPUT_FOR_DP, mask_sh),\ + SF(OTG0_OTG_STEREO_STATUS, OTG_STEREO_CURRENT_EYE, mask_sh),\ + SF(OTG0_OTG_3D_STRUCTURE_CONTROL, OTG_3D_STRUCTURE_EN, mask_sh),\ + SF(OTG0_OTG_3D_STRUCTURE_CONTROL, OTG_3D_STRUCTURE_V_UPDATE_MODE, mask_sh),\ + SF(OTG0_OTG_3D_STRUCTURE_CONTROL, OTG_3D_STRUCTURE_STEREO_SEL_OVR, mask_sh),\ + SF(OTG0_OTG_V_TOTAL_MAX, OTG_V_TOTAL_MAX, mask_sh),\ + SF(OTG0_OTG_V_TOTAL_MIN, OTG_V_TOTAL_MIN, mask_sh),\ + SF(OTG0_OTG_V_TOTAL_CONTROL, OTG_V_TOTAL_MIN_SEL, mask_sh),\ + SF(OTG0_OTG_V_TOTAL_CONTROL, OTG_V_TOTAL_MAX_SEL, mask_sh),\ + SF(OTG0_OTG_V_TOTAL_CONTROL, OTG_FORCE_LOCK_ON_EVENT, mask_sh),\ + SF(OTG0_OTG_V_TOTAL_CONTROL, OTG_SET_V_TOTAL_MIN_MASK, mask_sh),\ + SF(OTG0_OTG_V_TOTAL_CONTROL, OTG_VTOTAL_MID_REPLACING_MIN_EN, mask_sh),\ + SF(OTG0_OTG_V_TOTAL_CONTROL, OTG_VTOTAL_MID_REPLACING_MAX_EN, mask_sh),\ + SF(OTG0_OTG_FORCE_COUNT_NOW_CNTL, OTG_FORCE_COUNT_NOW_CLEAR, mask_sh),\ + SF(OTG0_OTG_FORCE_COUNT_NOW_CNTL, OTG_FORCE_COUNT_NOW_MODE, mask_sh),\ + SF(OTG0_OTG_FORCE_COUNT_NOW_CNTL, OTG_FORCE_COUNT_NOW_OCCURRED, mask_sh),\ + SF(OTG0_OTG_TRIGA_CNTL, OTG_TRIGA_SOURCE_SELECT, mask_sh),\ + SF(OTG0_OTG_TRIGA_CNTL, OTG_TRIGA_SOURCE_PIPE_SELECT, mask_sh),\ + SF(OTG0_OTG_TRIGA_CNTL, OTG_TRIGA_RISING_EDGE_DETECT_CNTL, mask_sh),\ + SF(OTG0_OTG_TRIGA_CNTL, OTG_TRIGA_FALLING_EDGE_DETECT_CNTL, mask_sh),\ + SF(OTG0_OTG_TRIGA_CNTL, OTG_TRIGA_POLARITY_SELECT, mask_sh),\ + SF(OTG0_OTG_TRIGA_CNTL, OTG_TRIGA_FREQUENCY_SELECT, mask_sh),\ + SF(OTG0_OTG_TRIGA_CNTL, OTG_TRIGA_DELAY, mask_sh),\ + SF(OTG0_OTG_TRIGA_CNTL, OTG_TRIGA_CLEAR, mask_sh),\ + SF(OTG0_OTG_STATIC_SCREEN_CONTROL, OTG_STATIC_SCREEN_EVENT_MASK, mask_sh),\ + SF(OTG0_OTG_STATIC_SCREEN_CONTROL, OTG_STATIC_SCREEN_FRAME_COUNT, mask_sh),\ + SF(OTG0_OTG_STATUS_FRAME_COUNT, OTG_FRAME_COUNT, mask_sh),\ + SF(OTG0_OTG_STATUS, OTG_V_BLANK, mask_sh),\ + SF(OTG0_OTG_STATUS, OTG_V_ACTIVE_DISP, mask_sh),\ + SF(OTG0_OTG_STATUS_POSITION, OTG_HORZ_COUNT, mask_sh),\ + SF(OTG0_OTG_STATUS_POSITION, OTG_VERT_COUNT, mask_sh),\ + SF(OTG0_OTG_NOM_VERT_POSITION, OTG_VERT_COUNT_NOM, mask_sh),\ + SF(OTG0_OTG_M_CONST_DTO0, OTG_M_CONST_DTO_PHASE, mask_sh),\ + SF(OTG0_OTG_M_CONST_DTO1, OTG_M_CONST_DTO_MODULO, mask_sh),\ + SF(OTG0_OTG_CLOCK_CONTROL, OTG_BUSY, mask_sh),\ + SF(OTG0_OTG_CLOCK_CONTROL, OTG_CLOCK_EN, mask_sh),\ + SF(OTG0_OTG_CLOCK_CONTROL, OTG_CLOCK_ON, mask_sh),\ + SF(OTG0_OTG_CLOCK_CONTROL, OTG_CLOCK_GATE_DIS, mask_sh),\ + SF(OTG0_OTG_VERTICAL_INTERRUPT0_CONTROL, OTG_VERTICAL_INTERRUPT0_INT_ENABLE, mask_sh),\ + SF(OTG0_OTG_VERTICAL_INTERRUPT0_POSITION, OTG_VERTICAL_INTERRUPT0_LINE_START, mask_sh),\ + SF(OTG0_OTG_VERTICAL_INTERRUPT0_POSITION, OTG_VERTICAL_INTERRUPT0_LINE_END, mask_sh),\ + SF(OTG0_OTG_VERTICAL_INTERRUPT1_CONTROL, OTG_VERTICAL_INTERRUPT1_INT_ENABLE, mask_sh),\ + SF(OTG0_OTG_VERTICAL_INTERRUPT1_POSITION, OTG_VERTICAL_INTERRUPT1_LINE_START, mask_sh),\ + SF(OTG0_OTG_VERTICAL_INTERRUPT2_CONTROL, OTG_VERTICAL_INTERRUPT2_INT_ENABLE, mask_sh),\ + SF(OTG0_OTG_VERTICAL_INTERRUPT2_POSITION, OTG_VERTICAL_INTERRUPT2_LINE_START, mask_sh),\ + SF(ODM0_OPTC_INPUT_CLOCK_CONTROL, OPTC_INPUT_CLK_EN, mask_sh),\ + SF(ODM0_OPTC_INPUT_CLOCK_CONTROL, OPTC_INPUT_CLK_ON, mask_sh),\ + SF(ODM0_OPTC_INPUT_CLOCK_CONTROL, OPTC_INPUT_CLK_GATE_DIS, mask_sh),\ + SF(ODM0_OPTC_INPUT_GLOBAL_CONTROL, OPTC_UNDERFLOW_OCCURRED_STATUS, mask_sh),\ + SF(ODM0_OPTC_INPUT_GLOBAL_CONTROL, OPTC_UNDERFLOW_CLEAR, mask_sh),\ + SF(VTG0_CONTROL, VTG0_ENABLE, mask_sh),\ + SF(VTG0_CONTROL, VTG0_FP2, mask_sh),\ + SF(VTG0_CONTROL, VTG0_VCOUNT_INIT, mask_sh),\ + SF(OTG0_OTG_VERT_SYNC_CONTROL, OTG_FORCE_VSYNC_NEXT_LINE_OCCURRED, mask_sh),\ + SF(OTG0_OTG_VERT_SYNC_CONTROL, OTG_FORCE_VSYNC_NEXT_LINE_CLEAR, mask_sh),\ + SF(OTG0_OTG_VERT_SYNC_CONTROL, OTG_AUTO_FORCE_VSYNC_MODE, mask_sh),\ + SF(OTG0_OTG_GSL_CONTROL, OTG_GSL0_EN, mask_sh),\ + SF(OTG0_OTG_GSL_CONTROL, OTG_GSL1_EN, mask_sh),\ + SF(OTG0_OTG_GSL_CONTROL, OTG_GSL2_EN, mask_sh),\ + SF(OTG0_OTG_GSL_CONTROL, OTG_GSL_MASTER_EN, mask_sh),\ + SF(OTG0_OTG_GSL_CONTROL, OTG_GSL_FORCE_DELAY, mask_sh),\ + SF(OTG0_OTG_GSL_CONTROL, OTG_GSL_CHECK_ALL_FIELDS, mask_sh),\ + SF(OTG0_OTG_CRC_CNTL, OTG_CRC_CONT_EN, mask_sh),\ + SF(OTG0_OTG_CRC_CNTL, OTG_CRC0_SELECT, mask_sh),\ + SF(OTG0_OTG_CRC_CNTL, OTG_CRC_EN, mask_sh),\ + SF(OTG0_OTG_CRC0_DATA_RG, CRC0_R_CR, mask_sh),\ + SF(OTG0_OTG_CRC0_DATA_RG, CRC0_G_Y, mask_sh),\ + SF(OTG0_OTG_CRC0_DATA_B, CRC0_B_CB, mask_sh),\ + SF(OTG0_OTG_CRC0_WINDOWA_X_CONTROL, OTG_CRC0_WINDOWA_X_START, mask_sh),\ + SF(OTG0_OTG_CRC0_WINDOWA_X_CONTROL, OTG_CRC0_WINDOWA_X_END, mask_sh),\ + SF(OTG0_OTG_CRC0_WINDOWA_Y_CONTROL, OTG_CRC0_WINDOWA_Y_START, mask_sh),\ + SF(OTG0_OTG_CRC0_WINDOWA_Y_CONTROL, OTG_CRC0_WINDOWA_Y_END, mask_sh),\ + SF(OTG0_OTG_CRC0_WINDOWB_X_CONTROL, OTG_CRC0_WINDOWB_X_START, mask_sh),\ + SF(OTG0_OTG_CRC0_WINDOWB_X_CONTROL, OTG_CRC0_WINDOWB_X_END, mask_sh),\ + SF(OTG0_OTG_CRC0_WINDOWB_Y_CONTROL, OTG_CRC0_WINDOWB_Y_START, mask_sh),\ + SF(OTG0_OTG_CRC0_WINDOWB_Y_CONTROL, OTG_CRC0_WINDOWB_Y_END, mask_sh),\ + SF(OTG0_OTG_TRIGA_MANUAL_TRIG, OTG_TRIGA_MANUAL_TRIG, mask_sh),\ + SF(GSL_SOURCE_SELECT, GSL0_READY_SOURCE_SEL, mask_sh),\ + SF(GSL_SOURCE_SELECT, GSL1_READY_SOURCE_SEL, mask_sh),\ + SF(GSL_SOURCE_SELECT, GSL2_READY_SOURCE_SEL, mask_sh),\ + SF(OTG0_OTG_GLOBAL_CONTROL2, MANUAL_FLOW_CONTROL_SEL, mask_sh),\ + SF(OTG0_OTG_GLOBAL_CONTROL2, GLOBAL_UPDATE_LOCK_EN, mask_sh),\ + SF(OTG0_OTG_GSL_WINDOW_X, OTG_GSL_WINDOW_START_X, mask_sh),\ + SF(OTG0_OTG_GSL_WINDOW_X, OTG_GSL_WINDOW_END_X, mask_sh), \ + SF(OTG0_OTG_GSL_WINDOW_Y, OTG_GSL_WINDOW_START_Y, mask_sh),\ + SF(OTG0_OTG_GSL_WINDOW_Y, OTG_GSL_WINDOW_END_Y, mask_sh),\ + SF(OTG0_OTG_VUPDATE_KEEPOUT, OTG_MASTER_UPDATE_LOCK_VUPDATE_KEEPOUT_EN, mask_sh), \ + SF(OTG0_OTG_VUPDATE_KEEPOUT, MASTER_UPDATE_LOCK_VUPDATE_KEEPOUT_START_OFFSET, mask_sh), \ + SF(OTG0_OTG_VUPDATE_KEEPOUT, MASTER_UPDATE_LOCK_VUPDATE_KEEPOUT_END_OFFSET, mask_sh), \ + SF(OTG0_OTG_GSL_CONTROL, OTG_GSL_MASTER_MODE, mask_sh), \ + SF(OTG0_OTG_GSL_CONTROL, OTG_MASTER_UPDATE_LOCK_GSL_EN, mask_sh), \ + SF(OTG0_OTG_DSC_START_POSITION, OTG_DSC_START_POSITION_X, mask_sh), \ + SF(OTG0_OTG_DSC_START_POSITION, OTG_DSC_START_POSITION_LINE_NUM, mask_sh),\ + SF(ODM0_OPTC_DATA_SOURCE_SELECT, OPTC_SEG0_SRC_SEL, mask_sh),\ + SF(ODM0_OPTC_DATA_SOURCE_SELECT, OPTC_SEG1_SRC_SEL, mask_sh),\ + SF(ODM0_OPTC_DATA_SOURCE_SELECT, OPTC_SEG2_SRC_SEL, mask_sh),\ + SF(ODM0_OPTC_DATA_SOURCE_SELECT, OPTC_SEG3_SRC_SEL, mask_sh),\ + SF(ODM0_OPTC_DATA_SOURCE_SELECT, OPTC_NUM_OF_INPUT_SEGMENT, mask_sh),\ + SF(ODM0_OPTC_MEMORY_CONFIG, OPTC_MEM_SEL, mask_sh),\ + SF(ODM0_OPTC_DATA_FORMAT_CONTROL, OPTC_DATA_FORMAT, mask_sh),\ + SF(ODM0_OPTC_DATA_FORMAT_CONTROL, OPTC_DSC_MODE, mask_sh),\ + SF(ODM0_OPTC_BYTES_PER_PIXEL, OPTC_DSC_BYTES_PER_PIXEL, mask_sh),\ + SF(ODM0_OPTC_WIDTH_CONTROL, OPTC_DSC_SLICE_WIDTH, mask_sh),\ + SF(ODM0_OPTC_WIDTH_CONTROL, OPTC_SEGMENT_WIDTH, mask_sh),\ + SF(OTG0_OTG_DRR_TRIGGER_WINDOW, OTG_DRR_TRIGGER_WINDOW_START_X, mask_sh),\ + SF(OTG0_OTG_DRR_TRIGGER_WINDOW, OTG_DRR_TRIGGER_WINDOW_END_X, mask_sh),\ + SF(OTG0_OTG_DRR_V_TOTAL_CHANGE, OTG_DRR_V_TOTAL_CHANGE_LIMIT, mask_sh),\ + SF(OTG0_OTG_H_TIMING_CNTL, OTG_H_TIMING_DIV_MODE, mask_sh),\ + SF(OTG0_OTG_H_TIMING_CNTL, OTG_H_TIMING_DIV_MODE_MANUAL, mask_sh),\ + SF(OTG0_OTG_DOUBLE_BUFFER_CONTROL, OTG_DRR_TIMING_DBUF_UPDATE_MODE, mask_sh),\ + SF(OTG0_OTG_DRR_CONTROL, OTG_V_TOTAL_LAST_USED_BY_DRR, mask_sh) + +void dcn32_timing_generator_init(struct optc *optc1); +void optc32_set_h_timing_div_manual_mode(struct timing_generator *optc, bool manual_mode); +void optc32_get_odm_combine_segments(struct timing_generator *tg, int *odm_combine_segments); +void optc32_set_odm_bypass(struct timing_generator *optc, + const struct dc_crtc_timing *dc_crtc_timing); + +#endif /* __DC_OPTC_DCN32_H__ */ diff --git a/drivers/gpu/drm/amd/display/dc/optc/dcn35/dcn35_optc.c b/drivers/gpu/drm/amd/display/dc/optc/dcn35/dcn35_optc.c new file mode 100644 index 000000000000..a4a39f1638cf --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/optc/dcn35/dcn35_optc.c @@ -0,0 +1,290 @@ +/* SPDX-License-Identifier: MIT */ +/* + * Copyright 2023 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 "dcn35_optc.h" + +#include "dcn30/dcn30_optc.h" +#include "dcn31/dcn31_optc.h" +#include "dcn32/dcn32_optc.h" +#include "reg_helper.h" +#include "dc.h" +#include "dcn_calc_math.h" + +#define REG(reg)\ + optc1->tg_regs->reg + +#define CTX \ + optc1->base.ctx + +#undef FN +#define FN(reg_name, field_name) \ + optc1->tg_shift->field_name, optc1->tg_mask->field_name + +/** + * optc35_set_odm_combine() - Enable CRTC - call ASIC Control Object to enable Timing generator. + * + * @optc: Output Pipe Timing Combine instance reference. + * @opp_id: Output Plane Processor instance ID. + * @opp_cnt: Output Plane Processor count. + * @timing: Timing parameters used to configure DCN blocks. + * + * Return: void. + */ +static void optc35_set_odm_combine(struct timing_generator *optc, int *opp_id, int opp_cnt, + struct dc_crtc_timing *timing) +{ + struct optc *optc1 = DCN10TG_FROM_TG(optc); + uint32_t memory_mask = 0; + int h_active = timing->h_addressable + timing->h_border_left + timing->h_border_right; + int mpcc_hactive = h_active / opp_cnt; + /* Each memory instance is 2048x(314x2) bits to support half line of 4096 */ + int odm_mem_count = (h_active + 2047) / 2048; + + /* + * display <= 4k : 2 memories + 2 pipes + * 4k < display <= 8k : 4 memories + 2 pipes + * 8k < display <= 12k : 6 memories + 4 pipes + */ + if (opp_cnt == 4) { + if (odm_mem_count <= 2) + memory_mask = 0x3; + else if (odm_mem_count <= 4) + memory_mask = 0xf; + else + memory_mask = 0x3f; + } else { + if (odm_mem_count <= 2) + memory_mask = 0x1 << (opp_id[0] * 2) | 0x1 << (opp_id[1] * 2); + else if (odm_mem_count <= 4) + memory_mask = 0x3 << (opp_id[0] * 2) | 0x3 << (opp_id[1] * 2); + else + memory_mask = 0x77; + } + + REG_SET(OPTC_MEMORY_CONFIG, 0, + OPTC_MEM_SEL, memory_mask); + + if (opp_cnt == 2) { + REG_SET_3(OPTC_DATA_SOURCE_SELECT, 0, + OPTC_NUM_OF_INPUT_SEGMENT, 1, + OPTC_SEG0_SRC_SEL, opp_id[0], + OPTC_SEG1_SRC_SEL, opp_id[1]); + } else if (opp_cnt == 4) { + REG_SET_5(OPTC_DATA_SOURCE_SELECT, 0, + OPTC_NUM_OF_INPUT_SEGMENT, 3, + OPTC_SEG0_SRC_SEL, opp_id[0], + OPTC_SEG1_SRC_SEL, opp_id[1], + OPTC_SEG2_SRC_SEL, opp_id[2], + OPTC_SEG3_SRC_SEL, opp_id[3]); + } + + REG_UPDATE(OPTC_WIDTH_CONTROL, + OPTC_SEGMENT_WIDTH, mpcc_hactive); + + REG_UPDATE(OTG_H_TIMING_CNTL, OTG_H_TIMING_DIV_MODE, opp_cnt - 1); + optc1->opp_count = opp_cnt; +} + +static bool optc35_enable_crtc(struct timing_generator *optc) +{ + struct optc *optc1 = DCN10TG_FROM_TG(optc); + + /* opp instance for OTG, 1 to 1 mapping and odm will adjust */ + REG_UPDATE(OPTC_DATA_SOURCE_SELECT, + OPTC_SEG0_SRC_SEL, optc->inst); + + /* VTG enable first is for HW workaround */ + REG_UPDATE(CONTROL, + VTG0_ENABLE, 1); + + REG_SEQ_START(); + + /* Enable CRTC */ + REG_UPDATE_2(OTG_CONTROL, + OTG_DISABLE_POINT_CNTL, 2, + OTG_MASTER_EN, 1); + + REG_SEQ_SUBMIT(); + REG_SEQ_WAIT_DONE(); + + return true; +} + +/* disable_crtc */ +static bool optc35_disable_crtc(struct timing_generator *optc) +{ + struct optc *optc1 = DCN10TG_FROM_TG(optc); + + /* disable otg request until end of the first line + * in the vertical blank region + */ + REG_UPDATE(OTG_CONTROL, + OTG_MASTER_EN, 0); + + REG_UPDATE(CONTROL, + VTG0_ENABLE, 0); + + /* CRTC disabled, so disable clock. */ + REG_WAIT(OTG_CLOCK_CONTROL, + OTG_BUSY, 0, + 1, 100000); + optc1_clear_optc_underflow(optc); + + return true; +} + +static void optc35_phantom_crtc_post_enable(struct timing_generator *optc) +{ + struct optc *optc1 = DCN10TG_FROM_TG(optc); + + /* Disable immediately. */ + REG_UPDATE_2(OTG_CONTROL, OTG_DISABLE_POINT_CNTL, 0, OTG_MASTER_EN, 0); + + /* CRTC disabled, so disable clock. */ + REG_WAIT(OTG_CLOCK_CONTROL, OTG_BUSY, 0, 1, 100000); +} + +static bool optc35_configure_crc(struct timing_generator *optc, + const struct crc_params *params) +{ + struct optc *optc1 = DCN10TG_FROM_TG(optc); + + if (!optc1_is_tg_enabled(optc)) + return false; + REG_WRITE(OTG_CRC_CNTL, 0); + if (!params->enable) + return true; + REG_UPDATE_2(OTG_CRC0_WINDOWA_X_CONTROL, + OTG_CRC0_WINDOWA_X_START, params->windowa_x_start, + OTG_CRC0_WINDOWA_X_END, params->windowa_x_end); + REG_UPDATE_2(OTG_CRC0_WINDOWA_Y_CONTROL, + OTG_CRC0_WINDOWA_Y_START, params->windowa_y_start, + OTG_CRC0_WINDOWA_Y_END, params->windowa_y_end); + REG_UPDATE_2(OTG_CRC0_WINDOWB_X_CONTROL, + OTG_CRC0_WINDOWB_X_START, params->windowb_x_start, + OTG_CRC0_WINDOWB_X_END, params->windowb_x_end); + REG_UPDATE_2(OTG_CRC0_WINDOWB_Y_CONTROL, + OTG_CRC0_WINDOWB_Y_START, params->windowb_y_start, + OTG_CRC0_WINDOWB_Y_END, params->windowb_y_end); + if (optc1->base.ctx->dc->debug.otg_crc_db && optc1->tg_mask->OTG_CRC_WINDOW_DB_EN != 0) { + REG_UPDATE_4(OTG_CRC_CNTL, + OTG_CRC_CONT_EN, params->continuous_mode ? 1 : 0, + OTG_CRC0_SELECT, params->selection, + OTG_CRC_EN, 1, + OTG_CRC_WINDOW_DB_EN, 1); + } else + REG_UPDATE_3(OTG_CRC_CNTL, + OTG_CRC_CONT_EN, params->continuous_mode ? 1 : 0, + OTG_CRC0_SELECT, params->selection, + OTG_CRC_EN, 1); + return true; +} + +static struct timing_generator_funcs dcn35_tg_funcs = { + .validate_timing = optc1_validate_timing, + .program_timing = optc1_program_timing, + .setup_vertical_interrupt0 = optc1_setup_vertical_interrupt0, + .setup_vertical_interrupt1 = optc1_setup_vertical_interrupt1, + .setup_vertical_interrupt2 = optc1_setup_vertical_interrupt2, + .program_global_sync = optc1_program_global_sync, + .enable_crtc = optc35_enable_crtc, + .disable_crtc = optc35_disable_crtc, + .immediate_disable_crtc = optc31_immediate_disable_crtc, + .phantom_crtc_post_enable = optc35_phantom_crtc_post_enable, + /* used by enable_timing_synchronization. Not need for FPGA */ + .is_counter_moving = optc1_is_counter_moving, + .get_position = optc1_get_position, + .get_frame_count = optc1_get_vblank_counter, + .get_scanoutpos = optc1_get_crtc_scanoutpos, + .get_otg_active_size = optc1_get_otg_active_size, + .set_early_control = optc1_set_early_control, + /* used by enable_timing_synchronization. Not need for FPGA */ + .wait_for_state = optc1_wait_for_state, + .set_blank_color = optc3_program_blank_color, + .did_triggered_reset_occur = optc1_did_triggered_reset_occur, + .triplebuffer_lock = optc3_triplebuffer_lock, + .triplebuffer_unlock = optc2_triplebuffer_unlock, + .enable_reset_trigger = optc1_enable_reset_trigger, + .enable_crtc_reset = optc1_enable_crtc_reset, + .disable_reset_trigger = optc1_disable_reset_trigger, + .lock = optc3_lock, + .unlock = optc1_unlock, + .lock_doublebuffer_enable = optc3_lock_doublebuffer_enable, + .lock_doublebuffer_disable = optc3_lock_doublebuffer_disable, + .enable_optc_clock = optc1_enable_optc_clock, + .set_drr = optc31_set_drr, + .get_last_used_drr_vtotal = optc2_get_last_used_drr_vtotal, + .set_vtotal_min_max = optc1_set_vtotal_min_max, + .set_static_screen_control = optc1_set_static_screen_control, + .program_stereo = optc1_program_stereo, + .is_stereo_left_eye = optc1_is_stereo_left_eye, + .tg_init = optc3_tg_init, + .is_tg_enabled = optc1_is_tg_enabled, + .is_optc_underflow_occurred = optc1_is_optc_underflow_occurred, + .clear_optc_underflow = optc1_clear_optc_underflow, + .setup_global_swap_lock = NULL, + .get_crc = optc1_get_crc, + .configure_crc = optc35_configure_crc, + .set_dsc_config = optc3_set_dsc_config, + .get_dsc_status = optc2_get_dsc_status, + .set_dwb_source = NULL, + .set_odm_bypass = optc32_set_odm_bypass, + .set_odm_combine = optc35_set_odm_combine, + .get_optc_source = optc2_get_optc_source, + .set_h_timing_div_manual_mode = optc32_set_h_timing_div_manual_mode, + .set_out_mux = optc3_set_out_mux, + .set_drr_trigger_window = optc3_set_drr_trigger_window, + .set_vtotal_change_limit = optc3_set_vtotal_change_limit, + .set_gsl = optc2_set_gsl, + .set_gsl_source_select = optc2_set_gsl_source_select, + .set_vtg_params = optc1_set_vtg_params, + .program_manual_trigger = optc2_program_manual_trigger, + .setup_manual_trigger = optc2_setup_manual_trigger, + .get_hw_timing = optc1_get_hw_timing, + .init_odm = optc3_init_odm, +}; + +void dcn35_timing_generator_init(struct optc *optc1) +{ + optc1->base.funcs = &dcn35_tg_funcs; + + optc1->max_h_total = optc1->tg_mask->OTG_H_TOTAL + 1; + optc1->max_v_total = optc1->tg_mask->OTG_V_TOTAL + 1; + + optc1->min_h_blank = 32; + optc1->min_v_blank = 3; + optc1->min_v_blank_interlace = 5; + optc1->min_h_sync_width = 4; + optc1->min_v_sync_width = 1; + + dcn35_timing_generator_set_fgcg( + optc1, CTX->dc->debug.enable_fine_grain_clock_gating.bits.optc); +} + +void dcn35_timing_generator_set_fgcg(struct optc *optc1, bool enable) +{ + REG_UPDATE(OPTC_CLOCK_CONTROL, OPTC_FGCG_REP_DIS, !enable); +} diff --git a/drivers/gpu/drm/amd/display/dc/optc/dcn35/dcn35_optc.h b/drivers/gpu/drm/amd/display/dc/optc/dcn35/dcn35_optc.h new file mode 100644 index 000000000000..1f422e4c468f --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/optc/dcn35/dcn35_optc.h @@ -0,0 +1,74 @@ +/* SPDX-License-Identifier: MIT */ +/* + * Copyright 2023 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_OPTC_DCN35_H__ +#define __DC_OPTC_DCN35_H__ + +#include "dcn10/dcn10_optc.h" +#include "dcn32/dcn32_optc.h" +#define OPTC_COMMON_MASK_SH_LIST_DCN3_5(mask_sh)\ + OPTC_COMMON_MASK_SH_LIST_DCN3_2(mask_sh),\ + SF(OTG0_OTG_CRC_CNTL, OTG_CRC_WINDOW_DB_EN, mask_sh),\ + SF(OTG0_OTG_CRC1_DATA_RG, CRC1_R_CR, mask_sh),\ + SF(OTG0_OTG_CRC1_DATA_RG, CRC1_G_Y, mask_sh),\ + SF(OTG0_OTG_CRC1_DATA_B, CRC1_B_CB, mask_sh),\ + SF(OTG0_OTG_CRC2_DATA_RG, CRC2_R_CR, mask_sh),\ + SF(OTG0_OTG_CRC2_DATA_RG, CRC2_G_Y, mask_sh),\ + SF(OTG0_OTG_CRC2_DATA_B, CRC2_B_CB, mask_sh),\ + SF(OTG0_OTG_CRC3_DATA_RG, CRC3_R_CR, mask_sh),\ + SF(OTG0_OTG_CRC3_DATA_RG, CRC3_G_Y, mask_sh),\ + SF(OTG0_OTG_CRC3_DATA_B, CRC3_B_CB, mask_sh),\ + SF(OTG0_OTG_CRC1_WINDOWA_X_CONTROL, OTG_CRC1_WINDOWA_X_START, mask_sh),\ + SF(OTG0_OTG_CRC1_WINDOWA_X_CONTROL, OTG_CRC1_WINDOWA_X_END, mask_sh),\ + SF(OTG0_OTG_CRC1_WINDOWA_Y_CONTROL, OTG_CRC1_WINDOWA_Y_START, mask_sh),\ + SF(OTG0_OTG_CRC1_WINDOWA_Y_CONTROL, OTG_CRC1_WINDOWA_Y_END, mask_sh),\ + SF(OTG0_OTG_CRC1_WINDOWB_X_CONTROL, OTG_CRC1_WINDOWB_X_START, mask_sh),\ + SF(OTG0_OTG_CRC1_WINDOWB_X_CONTROL, OTG_CRC1_WINDOWB_X_END, mask_sh),\ + SF(OTG0_OTG_CRC1_WINDOWB_Y_CONTROL, OTG_CRC1_WINDOWB_Y_START, mask_sh),\ + SF(OTG0_OTG_CRC1_WINDOWB_Y_CONTROL, OTG_CRC1_WINDOWB_Y_END, mask_sh),\ + SF(OTG0_OTG_CRC0_WINDOWA_X_CONTROL_READBACK, OTG_CRC0_WINDOWA_X_START_READBACK, mask_sh),\ + SF(OTG0_OTG_CRC0_WINDOWA_X_CONTROL_READBACK, OTG_CRC0_WINDOWA_X_END_READBACK, mask_sh),\ + SF(OTG0_OTG_CRC0_WINDOWA_Y_CONTROL_READBACK, OTG_CRC0_WINDOWA_Y_START_READBACK, mask_sh),\ + SF(OTG0_OTG_CRC0_WINDOWA_Y_CONTROL_READBACK, OTG_CRC0_WINDOWA_Y_END_READBACK, mask_sh),\ + SF(OTG0_OTG_CRC0_WINDOWB_X_CONTROL_READBACK, OTG_CRC0_WINDOWB_X_START_READBACK, mask_sh),\ + SF(OTG0_OTG_CRC0_WINDOWB_X_CONTROL_READBACK, OTG_CRC0_WINDOWB_X_END_READBACK, mask_sh),\ + SF(OTG0_OTG_CRC0_WINDOWB_Y_CONTROL_READBACK, OTG_CRC0_WINDOWB_Y_START_READBACK, mask_sh),\ + SF(OTG0_OTG_CRC0_WINDOWB_Y_CONTROL_READBACK, OTG_CRC0_WINDOWB_Y_END_READBACK, mask_sh),\ + SF(OTG0_OTG_CRC1_WINDOWA_X_CONTROL_READBACK, OTG_CRC1_WINDOWA_X_START_READBACK, mask_sh),\ + SF(OTG0_OTG_CRC1_WINDOWA_X_CONTROL_READBACK, OTG_CRC1_WINDOWA_X_END_READBACK, mask_sh),\ + SF(OTG0_OTG_CRC1_WINDOWA_Y_CONTROL_READBACK, OTG_CRC1_WINDOWA_Y_START_READBACK, mask_sh),\ + SF(OTG0_OTG_CRC1_WINDOWA_Y_CONTROL_READBACK, OTG_CRC1_WINDOWA_Y_END_READBACK, mask_sh),\ + SF(OTG0_OTG_CRC1_WINDOWB_X_CONTROL_READBACK, OTG_CRC1_WINDOWB_X_START_READBACK, mask_sh),\ + SF(OTG0_OTG_CRC1_WINDOWB_X_CONTROL_READBACK, OTG_CRC1_WINDOWB_X_END_READBACK, mask_sh),\ + SF(OTG0_OTG_CRC1_WINDOWB_Y_CONTROL_READBACK, OTG_CRC1_WINDOWB_Y_START_READBACK, mask_sh),\ + SF(OTG0_OTG_CRC1_WINDOWB_Y_CONTROL_READBACK, OTG_CRC1_WINDOWB_Y_END_READBACK, mask_sh),\ + SF(OPTC_CLOCK_CONTROL, OPTC_FGCG_REP_DIS, mask_sh) + +void dcn35_timing_generator_init(struct optc *optc1); + +void dcn35_timing_generator_set_fgcg(struct optc *optc1, bool enable); + +#endif /* __DC_OPTC_DCN35_H__ */ -- cgit From 5fcf74e002f152db0c39a7cdafa082c952cc5640 Mon Sep 17 00:00:00 2001 From: Nicholas Kazlauskas Date: Fri, 3 Nov 2023 18:07:11 -0400 Subject: drm/amd/display: Update DCN35 clock table policy [Why] The new table doesn't have an implicit mapping between Fclk SOC voltage and MemClk and it currently builds the table off of number of Fclk states rather than DcfClock states. The DML table in use is not correct for functionality or power and does not align with our existing policies for DCN3x. [How] Build the table based on DcfClock with the following assumptions: 1. Raising Soc voltage is the most expensive operation, so assume that running at max DispClock or DppClock is preferable. 2. Assume that we can run at max Fclk / MemClk at any state, but restrict the maximum state to the very last entry in the table as the worst case scenario. 3. Assume that Fclk always has a 2x multiplier on DcfClock unless the table specifies something lower. Reviewed-by: Taimur Hassan Acked-by: Hamza Mahfooz Signed-off-by: Nicholas Kazlauskas Signed-off-by: Alex Deucher --- .../amd/display/dc/clk_mgr/dcn35/dcn35_clk_mgr.c | 77 ++++++++++++++-------- 1 file changed, 51 insertions(+), 26 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn35/dcn35_clk_mgr.c b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn35/dcn35_clk_mgr.c index 0f3f6a9d5144..19f8d83698be 100644 --- a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn35/dcn35_clk_mgr.c +++ b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn35/dcn35_clk_mgr.c @@ -648,27 +648,47 @@ static unsigned int convert_wck_ratio(uint8_t wck_ratio) return 1; } +static inline uint32_t calc_dram_speed_mts(const MemPstateTable_t *entry) +{ + return entry->UClk * convert_wck_ratio(entry->WckRatio) * 2; +} + static void dcn35_clk_mgr_helper_populate_bw_params(struct clk_mgr_internal *clk_mgr, struct integrated_info *bios_info, DpmClocks_t_dcn35 *clock_table) { struct clk_bw_params *bw_params = clk_mgr->base.bw_params; struct clk_limit_table_entry def_max = bw_params->clk_table.entries[bw_params->clk_table.num_entries - 1]; - uint32_t max_pstate = 0, max_uclk = 0, max_fclk = 0; - uint32_t min_pstate = 0, max_dispclk = 0, max_dppclk = 0; + uint32_t max_fclk = 0, min_pstate = 0, max_dispclk = 0, max_dppclk = 0; + uint32_t max_pstate = 0, max_dram_speed_mts = 0, min_dram_speed_mts = 0; int i; + /* Determine min/max p-state values. */ for (i = 0; i < clock_table->NumMemPstatesEnabled; i++) { - if (is_valid_clock_value(clock_table->MemPstateTable[i].UClk) && - clock_table->MemPstateTable[i].UClk > max_uclk) { - max_uclk = clock_table->MemPstateTable[i].UClk; + uint32_t dram_speed_mts = calc_dram_speed_mts(&clock_table->MemPstateTable[i]); + + if (is_valid_clock_value(dram_speed_mts) && dram_speed_mts > max_dram_speed_mts) { + max_dram_speed_mts = dram_speed_mts; max_pstate = i; } } - /* We expect the table to contain at least one valid Uclk entry. */ - ASSERT(is_valid_clock_value(max_uclk)); + min_dram_speed_mts = max_dram_speed_mts; + min_pstate = max_pstate; + for (i = 0; i < clock_table->NumMemPstatesEnabled; i++) { + uint32_t dram_speed_mts = calc_dram_speed_mts(&clock_table->MemPstateTable[i]); + + if (is_valid_clock_value(dram_speed_mts) && dram_speed_mts < min_dram_speed_mts) { + min_dram_speed_mts = dram_speed_mts; + min_pstate = i; + } + } + + /* We expect the table to contain at least one valid P-state entry. */ + ASSERT(clock_table->NumMemPstatesEnabled && + is_valid_clock_value(max_dram_speed_mts) && + is_valid_clock_value(min_dram_speed_mts)); /* dispclk and dppclk can be max at any voltage, same number of levels for both */ if (clock_table->NumDispClkLevelsEnabled <= NUM_DISPCLK_DPM_LEVELS && @@ -678,47 +698,46 @@ static void dcn35_clk_mgr_helper_populate_bw_params(struct clk_mgr_internal *clk max_dppclk = find_max_clk_value(clock_table->DppClocks, clock_table->NumDispClkLevelsEnabled); } else { + /* Invalid number of entries in the table from PMFW. */ ASSERT(0); } - if (clock_table->NumFclkLevelsEnabled <= NUM_FCLK_DPM_LEVELS) - max_fclk = find_max_clk_value(clock_table->FclkClocks_Freq, - clock_table->NumFclkLevelsEnabled); - for (i = 0; i < clock_table->NumMemPstatesEnabled; i++) { - uint32_t min_uclk = clock_table->MemPstateTable[0].UClk; - int j; + /* Base the clock table on dcfclk, need at least one entry regardless of pmfw table */ + ASSERT(clock_table->NumDcfClkLevelsEnabled > 0); - for (j = 1; j < clock_table->NumMemPstatesEnabled; j++) { - if (is_valid_clock_value(clock_table->MemPstateTable[j].UClk) && - clock_table->MemPstateTable[j].UClk < min_uclk && - clock_table->MemPstateTable[j].Voltage <= clock_table->SocVoltage[i]) { - min_uclk = clock_table->MemPstateTable[j].UClk; - min_pstate = j; - } - } + max_fclk = find_max_clk_value(clock_table->FclkClocks_Freq, clock_table->NumFclkLevelsEnabled); + for (i = 0; i < clock_table->NumDcfClkLevelsEnabled; i++) { + int j; + + /* First search defaults for the clocks we don't read using closest lower or equal default dcfclk */ for (j = bw_params->clk_table.num_entries - 1; j > 0; j--) if (bw_params->clk_table.entries[j].dcfclk_mhz <= clock_table->DcfClocks[i]) - break; + break; bw_params->clk_table.entries[i].phyclk_mhz = bw_params->clk_table.entries[j].phyclk_mhz; bw_params->clk_table.entries[i].phyclk_d18_mhz = bw_params->clk_table.entries[j].phyclk_d18_mhz; bw_params->clk_table.entries[i].dtbclk_mhz = bw_params->clk_table.entries[j].dtbclk_mhz; - bw_params->clk_table.entries[i].fclk_mhz = max_fclk; + + /* Now update clocks we do read */ bw_params->clk_table.entries[i].memclk_mhz = clock_table->MemPstateTable[min_pstate].MemClk; bw_params->clk_table.entries[i].voltage = clock_table->MemPstateTable[min_pstate].Voltage; bw_params->clk_table.entries[i].dcfclk_mhz = clock_table->DcfClocks[i]; bw_params->clk_table.entries[i].socclk_mhz = clock_table->SocClocks[i]; bw_params->clk_table.entries[i].dispclk_mhz = max_dispclk; bw_params->clk_table.entries[i].dppclk_mhz = max_dppclk; - bw_params->clk_table.entries[i].wck_ratio = convert_wck_ratio( - clock_table->MemPstateTable[min_pstate].WckRatio); - } + bw_params->clk_table.entries[i].wck_ratio = + convert_wck_ratio(clock_table->MemPstateTable[min_pstate].WckRatio); + + /* Dcfclk and Fclk are tied, but at a different ratio */ + bw_params->clk_table.entries[i].fclk_mhz = min(max_fclk, 2 * clock_table->DcfClocks[i]); + } /* Make sure to include at least one entry at highest pstate */ if (max_pstate != min_pstate || i == 0) { if (i > MAX_NUM_DPM_LVL - 1) i = MAX_NUM_DPM_LVL - 1; + bw_params->clk_table.entries[i].fclk_mhz = max_fclk; bw_params->clk_table.entries[i].memclk_mhz = clock_table->MemPstateTable[max_pstate].MemClk; bw_params->clk_table.entries[i].voltage = clock_table->MemPstateTable[max_pstate].Voltage; @@ -734,6 +753,7 @@ static void dcn35_clk_mgr_helper_populate_bw_params(struct clk_mgr_internal *clk } bw_params->clk_table.num_entries = i--; + /* Make sure all highest clocks are included*/ bw_params->clk_table.entries[i].socclk_mhz = find_max_clk_value(clock_table->SocClocks, NUM_SOCCLK_DPM_LEVELS); bw_params->clk_table.entries[i].dispclk_mhz = @@ -752,6 +772,11 @@ static void dcn35_clk_mgr_helper_populate_bw_params(struct clk_mgr_internal *clk bw_params->clk_table.num_entries_per_clk.num_fclk_levels = clock_table->NumFclkLevelsEnabled; bw_params->clk_table.num_entries_per_clk.num_memclk_levels = clock_table->NumMemPstatesEnabled; bw_params->clk_table.num_entries_per_clk.num_socclk_levels = clock_table->NumSocClkLevelsEnabled; + + /* + * Set any 0 clocks to max default setting. Not an issue for + * power since we aren't doing switching in such case anyway + */ for (i = 0; i < bw_params->clk_table.num_entries; i++) { if (!bw_params->clk_table.entries[i].fclk_mhz) { bw_params->clk_table.entries[i].fclk_mhz = def_max.fclk_mhz; -- cgit From f19c115d9c3c4f386c4662cc7b02ae1ffc2374af Mon Sep 17 00:00:00 2001 From: Taimur Hassan Date: Fri, 10 Nov 2023 10:06:09 -0500 Subject: drm/amd/display: Remove config update [Why] Prevent overwrite of dc->config.use_default_clock_table, as it should be pre-configured. Reviewed-by: Nicholas Kazlauskas Acked-by: Hamza Mahfooz Signed-off-by: Taimur Hassan Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/resource/dcn35/dcn35_resource.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/display/dc/resource/dcn35/dcn35_resource.c b/drivers/gpu/drm/amd/display/dc/resource/dcn35/dcn35_resource.c index 53eefba0b9dc..1a0ed1c7e2d4 100644 --- a/drivers/gpu/drm/amd/display/dc/resource/dcn35/dcn35_resource.c +++ b/drivers/gpu/drm/amd/display/dc/resource/dcn35/dcn35_resource.c @@ -1876,7 +1876,7 @@ static bool dcn35_resource_construct( /* Use pipe context based otg sync logic */ dc->config.use_pipe_ctx_sync_logic = true; - dc->config.use_default_clock_table = false; + /* read VBIOS LTTPR caps */ { if (ctx->dc_bios->funcs->get_lttpr_caps) { -- cgit From fbd2076c31e3281dea7b475d80211b7a6f1500da Mon Sep 17 00:00:00 2001 From: Mukul Joshi Date: Wed, 22 Nov 2023 15:17:22 -0500 Subject: drm/amdkfd: Use common function for IP version check KFD_GC_VERSION was recently updated to use a new function for IP version checks. As a result, use KFD_GC_VERSION as the common function for all IP version checks in KFD. Signed-off-by: Mukul Joshi Reviewed-by: Harish Kasiviswanathan Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdkfd/kfd_priv.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_priv.h b/drivers/gpu/drm/amd/amdkfd/kfd_priv.h index a40f8cfc6aa5..45366b4ca976 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_priv.h +++ b/drivers/gpu/drm/amd/amdkfd/kfd_priv.h @@ -1127,7 +1127,7 @@ static inline struct kfd_node *kfd_node_by_irq_ids(struct amdgpu_device *adev, struct kfd_dev *dev = adev->kfd.dev; uint32_t i; - if (adev->ip_versions[GC_HWIP][0] != IP_VERSION(9, 4, 3)) + if (KFD_GC_VERSION(dev) != IP_VERSION(9, 4, 3)) return dev->nodes[0]; for (i = 0; i < dev->num_nodes; i++) -- cgit From 22136ff27c4e01fae81f6588033363a46c72ed8c Mon Sep 17 00:00:00 2001 From: Taimur Hassan Date: Fri, 10 Nov 2023 10:15:28 -0500 Subject: drm/amd/display: Fix conversions between bytes and KB [Why] There are a number of instances where we convert HostVMMinPageSize or GPUVMMinPageSize from bytes to KB by dividing (rather than multiplying) and vice versa. Additionally, in some cases, a parameter is passed through DML in KB but later checked as if it were in bytes. Cc: stable@vger.kernel.org Reviewed-by: Nicholas Kazlauskas Acked-by: Hamza Mahfooz Signed-off-by: Taimur Hassan Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dml2/display_mode_core.c | 16 ++++++++-------- .../drm/amd/display/dc/dml2/dml2_translation_helper.c | 4 ++-- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/dml2/display_mode_core.c b/drivers/gpu/drm/amd/display/dc/dml2/display_mode_core.c index 510be909cd75..59718ee33e51 100644 --- a/drivers/gpu/drm/amd/display/dc/dml2/display_mode_core.c +++ b/drivers/gpu/drm/amd/display/dc/dml2/display_mode_core.c @@ -6329,7 +6329,7 @@ static void dml_prefetch_check(struct display_mode_lib_st *mode_lib) mode_lib->ms.NoOfDPPThisState, mode_lib->ms.dpte_group_bytes, s->HostVMInefficiencyFactor, - mode_lib->ms.soc.hostvm_min_page_size_kbytes, + mode_lib->ms.soc.hostvm_min_page_size_kbytes * 1024, mode_lib->ms.cache_display_cfg.plane.HostVMMaxPageTableLevels); s->NextMaxVStartup = s->MaxVStartupAllPlanes[j]; @@ -6542,7 +6542,7 @@ static void dml_prefetch_check(struct display_mode_lib_st *mode_lib) mode_lib->ms.cache_display_cfg.plane.HostVMEnable, mode_lib->ms.cache_display_cfg.plane.HostVMMaxPageTableLevels, mode_lib->ms.cache_display_cfg.plane.GPUVMEnable, - mode_lib->ms.soc.hostvm_min_page_size_kbytes, + mode_lib->ms.soc.hostvm_min_page_size_kbytes * 1024, mode_lib->ms.PDEAndMetaPTEBytesPerFrame[j][k], mode_lib->ms.MetaRowBytes[j][k], mode_lib->ms.DPTEBytesPerRow[j][k], @@ -7687,7 +7687,7 @@ dml_bool_t dml_core_mode_support(struct display_mode_lib_st *mode_lib) CalculateVMRowAndSwath_params->HostVMMaxNonCachedPageTableLevels = mode_lib->ms.cache_display_cfg.plane.HostVMMaxPageTableLevels; CalculateVMRowAndSwath_params->GPUVMMaxPageTableLevels = mode_lib->ms.cache_display_cfg.plane.GPUVMMaxPageTableLevels; CalculateVMRowAndSwath_params->GPUVMMinPageSizeKBytes = mode_lib->ms.cache_display_cfg.plane.GPUVMMinPageSizeKBytes; - CalculateVMRowAndSwath_params->HostVMMinPageSize = mode_lib->ms.soc.hostvm_min_page_size_kbytes; + CalculateVMRowAndSwath_params->HostVMMinPageSize = mode_lib->ms.soc.hostvm_min_page_size_kbytes * 1024; CalculateVMRowAndSwath_params->PTEBufferModeOverrideEn = mode_lib->ms.cache_display_cfg.plane.PTEBufferModeOverrideEn; CalculateVMRowAndSwath_params->PTEBufferModeOverrideVal = mode_lib->ms.cache_display_cfg.plane.PTEBufferMode; CalculateVMRowAndSwath_params->PTEBufferSizeNotExceeded = mode_lib->ms.PTEBufferSizeNotExceededPerState; @@ -7957,7 +7957,7 @@ dml_bool_t dml_core_mode_support(struct display_mode_lib_st *mode_lib) UseMinimumDCFCLK_params->GPUVMMaxPageTableLevels = mode_lib->ms.cache_display_cfg.plane.GPUVMMaxPageTableLevels; UseMinimumDCFCLK_params->HostVMEnable = mode_lib->ms.cache_display_cfg.plane.HostVMEnable; UseMinimumDCFCLK_params->NumberOfActiveSurfaces = mode_lib->ms.num_active_planes; - UseMinimumDCFCLK_params->HostVMMinPageSize = mode_lib->ms.soc.hostvm_min_page_size_kbytes; + UseMinimumDCFCLK_params->HostVMMinPageSize = mode_lib->ms.soc.hostvm_min_page_size_kbytes * 1024; UseMinimumDCFCLK_params->HostVMMaxNonCachedPageTableLevels = mode_lib->ms.cache_display_cfg.plane.HostVMMaxPageTableLevels; UseMinimumDCFCLK_params->DynamicMetadataVMEnabled = mode_lib->ms.ip.dynamic_metadata_vm_enabled; UseMinimumDCFCLK_params->ImmediateFlipRequirement = s->ImmediateFlipRequiredFinal; @@ -8699,7 +8699,7 @@ void dml_core_mode_programming(struct display_mode_lib_st *mode_lib, const struc CalculateVMRowAndSwath_params->HostVMMaxNonCachedPageTableLevels = mode_lib->ms.cache_display_cfg.plane.HostVMMaxPageTableLevels; CalculateVMRowAndSwath_params->GPUVMMaxPageTableLevels = mode_lib->ms.cache_display_cfg.plane.GPUVMMaxPageTableLevels; CalculateVMRowAndSwath_params->GPUVMMinPageSizeKBytes = mode_lib->ms.cache_display_cfg.plane.GPUVMMinPageSizeKBytes; - CalculateVMRowAndSwath_params->HostVMMinPageSize = mode_lib->ms.soc.hostvm_min_page_size_kbytes; + CalculateVMRowAndSwath_params->HostVMMinPageSize = mode_lib->ms.soc.hostvm_min_page_size_kbytes * 1024; CalculateVMRowAndSwath_params->PTEBufferModeOverrideEn = mode_lib->ms.cache_display_cfg.plane.PTEBufferModeOverrideEn; CalculateVMRowAndSwath_params->PTEBufferModeOverrideVal = mode_lib->ms.cache_display_cfg.plane.PTEBufferMode; CalculateVMRowAndSwath_params->PTEBufferSizeNotExceeded = s->dummy_boolean_array[0]; @@ -8805,7 +8805,7 @@ void dml_core_mode_programming(struct display_mode_lib_st *mode_lib, const struc mode_lib->ms.cache_display_cfg.hw.DPPPerSurface, locals->dpte_group_bytes, s->HostVMInefficiencyFactor, - mode_lib->ms.soc.hostvm_min_page_size_kbytes, + mode_lib->ms.soc.hostvm_min_page_size_kbytes * 1024, mode_lib->ms.cache_display_cfg.plane.HostVMMaxPageTableLevels); locals->TCalc = 24.0 / locals->DCFCLKDeepSleep; @@ -8995,7 +8995,7 @@ void dml_core_mode_programming(struct display_mode_lib_st *mode_lib, const struc CalculatePrefetchSchedule_params->GPUVMEnable = mode_lib->ms.cache_display_cfg.plane.GPUVMEnable; CalculatePrefetchSchedule_params->HostVMEnable = mode_lib->ms.cache_display_cfg.plane.HostVMEnable; CalculatePrefetchSchedule_params->HostVMMaxNonCachedPageTableLevels = mode_lib->ms.cache_display_cfg.plane.HostVMMaxPageTableLevels; - CalculatePrefetchSchedule_params->HostVMMinPageSize = mode_lib->ms.soc.hostvm_min_page_size_kbytes; + CalculatePrefetchSchedule_params->HostVMMinPageSize = mode_lib->ms.soc.hostvm_min_page_size_kbytes * 1024; CalculatePrefetchSchedule_params->DynamicMetadataEnable = mode_lib->ms.cache_display_cfg.plane.DynamicMetadataEnable[k]; CalculatePrefetchSchedule_params->DynamicMetadataVMEnabled = mode_lib->ms.ip.dynamic_metadata_vm_enabled; CalculatePrefetchSchedule_params->DynamicMetadataLinesBeforeActiveRequired = mode_lib->ms.cache_display_cfg.plane.DynamicMetadataLinesBeforeActiveRequired[k]; @@ -9240,7 +9240,7 @@ void dml_core_mode_programming(struct display_mode_lib_st *mode_lib, const struc mode_lib->ms.cache_display_cfg.plane.HostVMEnable, mode_lib->ms.cache_display_cfg.plane.HostVMMaxPageTableLevels, mode_lib->ms.cache_display_cfg.plane.GPUVMEnable, - mode_lib->ms.soc.hostvm_min_page_size_kbytes, + mode_lib->ms.soc.hostvm_min_page_size_kbytes * 1024, locals->PDEAndMetaPTEBytesFrame[k], locals->MetaRowByte[k], locals->PixelPTEBytesPerRow[k], diff --git a/drivers/gpu/drm/amd/display/dc/dml2/dml2_translation_helper.c b/drivers/gpu/drm/amd/display/dc/dml2/dml2_translation_helper.c index 2b9638c6d9b0..48caa34a5ce7 100644 --- a/drivers/gpu/drm/amd/display/dc/dml2/dml2_translation_helper.c +++ b/drivers/gpu/drm/amd/display/dc/dml2/dml2_translation_helper.c @@ -515,8 +515,8 @@ void dml2_translate_socbb_params(const struct dc *in, struct soc_bounding_box_st out->do_urgent_latency_adjustment = in_soc_params->do_urgent_latency_adjustment; out->dram_channel_width_bytes = (dml_uint_t)in_soc_params->dram_channel_width_bytes; out->fabric_datapath_to_dcn_data_return_bytes = (dml_uint_t)in_soc_params->fabric_datapath_to_dcn_data_return_bytes; - out->gpuvm_min_page_size_kbytes = in_soc_params->gpuvm_min_page_size_bytes * 1024; - out->hostvm_min_page_size_kbytes = in_soc_params->hostvm_min_page_size_bytes * 1024; + out->gpuvm_min_page_size_kbytes = in_soc_params->gpuvm_min_page_size_bytes / 1024; + out->hostvm_min_page_size_kbytes = in_soc_params->hostvm_min_page_size_bytes / 1024; out->mall_allocated_for_dcn_mbytes = (dml_uint_t)in_soc_params->mall_allocated_for_dcn_mbytes; out->max_avg_dram_bw_use_normal_percent = in_soc_params->max_avg_dram_bw_use_normal_percent; out->max_avg_fabric_bw_use_normal_percent = in_soc_params->max_avg_fabric_bw_use_normal_percent; -- cgit From 2d1c884a535fcca74814553132d41c15dc9831ef Mon Sep 17 00:00:00 2001 From: Sung Joon Kim Date: Fri, 10 Nov 2023 11:33:45 -0500 Subject: drm/amd/display: Fix black screen on video playback with embedded panel [why] We have dynamic power control in driver but should be ignored when power is forced on. [how] Bypass any power control when it's forced on. Cc: stable@vger.kernel.org Reviewed-by: Nicholas Kazlauskas Acked-by: Hamza Mahfooz Signed-off-by: Sung Joon Kim Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/clk_mgr/dcn35/dcn35_clk_mgr.c | 1 - drivers/gpu/drm/amd/display/dc/dcn35/dcn35_pg_cntl.c | 10 ++++++++++ 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn35/dcn35_clk_mgr.c b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn35/dcn35_clk_mgr.c index 19f8d83698be..63a0b885b6f0 100644 --- a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn35/dcn35_clk_mgr.c +++ b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn35/dcn35_clk_mgr.c @@ -1132,7 +1132,6 @@ void dcn35_clk_mgr_construct( ctx->dc->debug.disable_dpp_power_gate = false; ctx->dc->debug.disable_hubp_power_gate = false; ctx->dc->debug.disable_dsc_power_gate = false; - ctx->dc->debug.disable_hpo_power_gate = false; } else { /*let's reset the config control flag*/ ctx->dc->config.disable_ips = DMUB_IPS_DISABLE_ALL; /*pmfw not support it, disable it all*/ diff --git a/drivers/gpu/drm/amd/display/dc/dcn35/dcn35_pg_cntl.c b/drivers/gpu/drm/amd/display/dc/dcn35/dcn35_pg_cntl.c index 0f60c40e1fc5..53bd0ae4bab5 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn35/dcn35_pg_cntl.c +++ b/drivers/gpu/drm/amd/display/dc/dcn35/dcn35_pg_cntl.c @@ -261,6 +261,7 @@ void pg_cntl35_hpo_pg_control(struct pg_cntl *pg_cntl, bool power_on) uint32_t power_gate = power_on ? 0 : 1; uint32_t pwr_status = power_on ? 0 : 2; uint32_t org_ip_request_cntl; + uint32_t power_forceon; bool block_enabled; if (pg_cntl->ctx->dc->debug.ignore_pg || @@ -277,6 +278,10 @@ void pg_cntl35_hpo_pg_control(struct pg_cntl *pg_cntl, bool power_on) return; } + REG_GET(DOMAIN25_PG_CONFIG, DOMAIN_POWER_FORCEON, &power_forceon); + if (power_forceon) + return; + REG_GET(DC_IP_REQUEST_CNTL, IP_REQUEST_EN, &org_ip_request_cntl); if (org_ip_request_cntl == 0) REG_SET(DC_IP_REQUEST_CNTL, 0, IP_REQUEST_EN, 1); @@ -304,6 +309,7 @@ void pg_cntl35_io_clk_pg_control(struct pg_cntl *pg_cntl, bool power_on) uint32_t power_gate = power_on ? 0 : 1; uint32_t pwr_status = power_on ? 0 : 2; uint32_t org_ip_request_cntl; + uint32_t power_forceon; bool block_enabled; if (pg_cntl->ctx->dc->debug.ignore_pg || @@ -319,6 +325,10 @@ void pg_cntl35_io_clk_pg_control(struct pg_cntl *pg_cntl, bool power_on) return; } + REG_GET(DOMAIN22_PG_CONFIG, DOMAIN_POWER_FORCEON, &power_forceon); + if (power_forceon) + return; + REG_GET(DC_IP_REQUEST_CNTL, IP_REQUEST_EN, &org_ip_request_cntl); if (org_ip_request_cntl == 0) REG_SET(DC_IP_REQUEST_CNTL, 0, IP_REQUEST_EN, 1); -- cgit From 641220b2a53c64efb8327ffbbc3bfcf96b5a613f Mon Sep 17 00:00:00 2001 From: Anthony Koo Date: Sat, 11 Nov 2023 22:47:50 -0500 Subject: drm/amd/display: [FW Promotion] Release 0.0.193.0 - Add a tracing framework, to measure duration, execution count and longest duration of main loop/vsync interrupt work GPINT command is used to start/stop the measurements. Acked-by: Hamza Mahfooz Signed-off-by: Anthony Koo Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dmub/inc/dmub_cmd.h | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dmub/inc/dmub_cmd.h b/drivers/gpu/drm/amd/display/dmub/inc/dmub_cmd.h index a08073fc92ae..b7d9360bfdc8 100644 --- a/drivers/gpu/drm/amd/display/dmub/inc/dmub_cmd.h +++ b/drivers/gpu/drm/amd/display/dmub/inc/dmub_cmd.h @@ -185,8 +185,7 @@ union abm_flags { unsigned int disable_abm_requested : 1; /** - * @disable_abm_immediately: Indicates if driver has requested ABM to be disabled - * immediately. + * @disable_abm_immediately: Indicates if driver has requested ABM to be disabled immediately. */ unsigned int disable_abm_immediately : 1; @@ -866,6 +865,13 @@ enum dmub_gpint_command { * DESC: Updates the trace buffer mask bit32~bit63. */ DMUB_GPINT__GET_TRACE_BUFFER_MASK_WORD3 = 119, + + /** + * DESC: Enable measurements for various task duration + * ARGS: 0 - Disable measurement + * 1 - Enable measurement + */ + DMUB_GPINT__TRACE_DMUB_WAKE_ACTIVITY = 123, }; /** -- cgit From db4616f7667c9d1f733ec360a754a4d7fd32c28e Mon Sep 17 00:00:00 2001 From: Aric Cyr Date: Mon, 13 Nov 2023 09:07:22 -0500 Subject: drm/amd/display: 3.2.261 This version brings along the following: - DCN314 fixes - DCN32 fixes - DCN35 fixes - DML2 fixes - eDP fixes - HDR fixes - MST fixes - Replay fixes - SubVP support for more configs Acked-by: Hamza Mahfooz Signed-off-by: Aric Cyr Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dc.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h index 85771ef98cd7..6074ac1b180a 100644 --- a/drivers/gpu/drm/amd/display/dc/dc.h +++ b/drivers/gpu/drm/amd/display/dc/dc.h @@ -49,7 +49,7 @@ struct aux_payload; struct set_config_cmd_payload; struct dmub_notification; -#define DC_VER "3.2.260" +#define DC_VER "3.2.261" #define MAX_SURFACES 3 #define MAX_PLANES 6 -- cgit From 201761b5eb57c3fad810cde555795c3b5721a031 Mon Sep 17 00:00:00 2001 From: Lijo Lazar Date: Thu, 9 Nov 2023 10:50:38 +0530 Subject: drm/amdgpu: Move mca debug mode decision to ras Refactor code such that ras block decides the default mca debug mode, and not swsmu block. By default mca debug mode is set to false. v2: squash in uninitialized value fix (Alex) Signed-off-by: Lijo Lazar Reviewed-by: Hawking Zhang Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_mca.c | 2 +- drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c | 14 +++++++++++--- drivers/gpu/drm/amd/amdgpu/amdgpu_ras.h | 2 +- drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_6_ppt.c | 12 ------------ 4 files changed, 13 insertions(+), 17 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_mca.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_mca.c index cf33eb219e25..54f2f346579e 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_mca.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_mca.c @@ -377,7 +377,7 @@ static int amdgpu_mca_smu_debug_mode_set(void *data, u64 val) struct amdgpu_device *adev = (struct amdgpu_device *)data; int ret; - ret = amdgpu_mca_smu_set_debug_mode(adev, val ? true : false); + ret = amdgpu_ras_set_mca_debug_mode(adev, val ? true : false); if (ret) return ret; diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c index a3dc68e98910..f6b47ebce9d6 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c @@ -3132,6 +3132,8 @@ int amdgpu_ras_late_init(struct amdgpu_device *adev) if (amdgpu_sriov_vf(adev)) return 0; + amdgpu_ras_set_mca_debug_mode(adev, false); + list_for_each_entry_safe(node, tmp, &adev->ras_list, node) { if (!node->ras_obj) { dev_warn(adev->dev, "Warning: abnormal ras list node.\n"); @@ -3405,12 +3407,18 @@ int amdgpu_ras_reset_gpu(struct amdgpu_device *adev) return 0; } -void amdgpu_ras_set_mca_debug_mode(struct amdgpu_device *adev, bool enable) +int amdgpu_ras_set_mca_debug_mode(struct amdgpu_device *adev, bool enable) { struct amdgpu_ras *con = amdgpu_ras_get_context(adev); + int ret = 0; - if (con) - con->is_mca_debug_mode = enable; + if (con) { + ret = amdgpu_mca_smu_set_debug_mode(adev, enable); + if (!ret) + con->is_mca_debug_mode = enable; + } + + return ret; } bool amdgpu_ras_get_mca_debug_mode(struct amdgpu_device *adev) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.h index 19161916ac46..6a941eb8fb8f 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.h @@ -773,7 +773,7 @@ struct amdgpu_ras* amdgpu_ras_get_context(struct amdgpu_device *adev); int amdgpu_ras_set_context(struct amdgpu_device *adev, struct amdgpu_ras *ras_con); -void amdgpu_ras_set_mca_debug_mode(struct amdgpu_device *adev, bool enable); +int amdgpu_ras_set_mca_debug_mode(struct amdgpu_device *adev, bool enable); bool amdgpu_ras_get_mca_debug_mode(struct amdgpu_device *adev); bool amdgpu_ras_get_error_query_mode(struct amdgpu_device *adev, unsigned int *mode); diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_6_ppt.c b/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_6_ppt.c index 8ccb8354bb49..dda2249c4994 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_6_ppt.c +++ b/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_6_ppt.c @@ -1516,7 +1516,6 @@ static int smu_v13_0_6_mca_set_debug_mode(struct smu_context *smu, bool enable) if (smu->smc_fw_version < 0x554800) return 0; - amdgpu_ras_set_mca_debug_mode(smu->adev, enable); return smu_cmn_send_smc_msg_with_param(smu, SMU_MSG_ClearMcaOnRead, enable ? 0 : ClearMcaOnRead_UE_FLAG_MASK | ClearMcaOnRead_CE_POLL_MASK, NULL); @@ -2346,16 +2345,6 @@ static int smu_v13_0_6_smu_send_hbm_bad_page_num(struct smu_context *smu, return ret; } -static int smu_v13_0_6_post_init(struct smu_context *smu) -{ - struct amdgpu_device *adev = smu->adev; - - if (!amdgpu_sriov_vf(adev) && adev->ras_enabled) - return smu_v13_0_6_mca_set_debug_mode(smu, false); - - return 0; -} - static int mca_smu_set_debug_mode(struct amdgpu_device *adev, bool enable) { struct smu_context *smu = adev->powerplay.pp_handle; @@ -2920,7 +2909,6 @@ static const struct pptable_funcs smu_v13_0_6_ppt_funcs = { .i2c_init = smu_v13_0_6_i2c_control_init, .i2c_fini = smu_v13_0_6_i2c_control_fini, .send_hbm_bad_pages_num = smu_v13_0_6_smu_send_hbm_bad_page_num, - .post_init = smu_v13_0_6_post_init, }; void smu_v13_0_6_set_ppt_funcs(struct smu_context *smu) -- cgit From 7a6931a476d30f0d6bf70b01a925f76f92d23940 Mon Sep 17 00:00:00 2001 From: Hamza Mahfooz Date: Wed, 22 Nov 2023 14:50:34 -0500 Subject: drm/amd/display: fix ABM disablement On recent versions of DMUB firmware, if we want to completely disable ABM we have to pass ABM_LEVEL_IMMEDIATE_DISABLE as the requested ABM level to DMUB. Otherwise, LCD eDP displays are unable to reach their maximum brightness levels. So, to fix this whenever the user requests an ABM level of 0 pass ABM_LEVEL_IMMEDIATE_DISABLE to DMUB instead. Also, to keep the user's experience consistent map ABM_LEVEL_IMMEDIATE_DISABLE to 0 when a user tries to read the requested ABM level. Cc: stable@vger.kernel.org # 6.1+ Reviewed-by: Harry Wentland Signed-off-by: Hamza Mahfooz Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c index 2be64c593c87..39a4b47b6804 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -6248,7 +6248,7 @@ int amdgpu_dm_connector_atomic_set_property(struct drm_connector *connector, dm_new_state->underscan_enable = val; ret = 0; } else if (property == adev->mode_info.abm_level_property) { - dm_new_state->abm_level = val; + dm_new_state->abm_level = val ?: ABM_LEVEL_IMMEDIATE_DISABLE; ret = 0; } @@ -6293,7 +6293,8 @@ int amdgpu_dm_connector_atomic_get_property(struct drm_connector *connector, *val = dm_state->underscan_enable; ret = 0; } else if (property == adev->mode_info.abm_level_property) { - *val = dm_state->abm_level; + *val = (dm_state->abm_level != ABM_LEVEL_IMMEDIATE_DISABLE) ? + dm_state->abm_level : 0; ret = 0; } @@ -6366,7 +6367,8 @@ void amdgpu_dm_connector_funcs_reset(struct drm_connector *connector) state->pbn = 0; if (connector->connector_type == DRM_MODE_CONNECTOR_eDP) - state->abm_level = amdgpu_dm_abm_level; + state->abm_level = amdgpu_dm_abm_level ?: + ABM_LEVEL_IMMEDIATE_DISABLE; __drm_atomic_helper_connector_reset(connector, &state->base); } -- cgit From 01a1526ac4c8d9342d3d8b703751f3fc5ce487ba Mon Sep 17 00:00:00 2001 From: Dmytro Laktyushkin Date: Fri, 3 Nov 2023 14:55:37 -0400 Subject: drm/amd/display: update dcn315 lpddr pstate latency [WHY/HOW] Increase the pstate latency to improve ac/dc transition Reviewed-by: Charlene Liu Acked-by: Tom Chung Signed-off-by: Dmytro Laktyushkin Tested-by: Daniel Wheeler Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/clk_mgr/dcn315/dcn315_clk_mgr.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn315/dcn315_clk_mgr.c b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn315/dcn315_clk_mgr.c index b2c4f97afc8b..8776055bbeaa 100644 --- a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn315/dcn315_clk_mgr.c +++ b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn315/dcn315_clk_mgr.c @@ -334,7 +334,7 @@ static struct wm_table lpddr5_wm_table = { { .wm_inst = WM_A, .wm_type = WM_TYPE_PSTATE_CHG, - .pstate_latency_us = 11.65333, + .pstate_latency_us = 129.0, .sr_exit_time_us = 11.5, .sr_enter_plus_exit_time_us = 14.5, .valid = true, @@ -342,7 +342,7 @@ static struct wm_table lpddr5_wm_table = { { .wm_inst = WM_B, .wm_type = WM_TYPE_PSTATE_CHG, - .pstate_latency_us = 11.65333, + .pstate_latency_us = 129.0, .sr_exit_time_us = 11.5, .sr_enter_plus_exit_time_us = 14.5, .valid = true, @@ -350,7 +350,7 @@ static struct wm_table lpddr5_wm_table = { { .wm_inst = WM_C, .wm_type = WM_TYPE_PSTATE_CHG, - .pstate_latency_us = 11.65333, + .pstate_latency_us = 129.0, .sr_exit_time_us = 11.5, .sr_enter_plus_exit_time_us = 14.5, .valid = true, @@ -358,7 +358,7 @@ static struct wm_table lpddr5_wm_table = { { .wm_inst = WM_D, .wm_type = WM_TYPE_PSTATE_CHG, - .pstate_latency_us = 11.65333, + .pstate_latency_us = 129.0, .sr_exit_time_us = 11.5, .sr_enter_plus_exit_time_us = 14.5, .valid = true, -- cgit From bcdbd6f607bacb51743ac73f13f40d015cb9de53 Mon Sep 17 00:00:00 2001 From: RutingZhang Date: Tue, 21 Nov 2023 12:36:20 +0800 Subject: drm/amd/display: remove unnecessary braces to fix coding style checkpatch complains that: WARNING: braces {} are not necessary for single statement blocks + if (pool->base.irqs != NULL) { + dal_irq_service_destroy(&pool->base.irqs); + } Fixed it by removing unnecessary braces to fix the coding style issue. Signed-off-by: RutingZhang Reviewed-by: Dongliang Mu Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/resource/dcn21/dcn21_resource.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/resource/dcn21/dcn21_resource.c b/drivers/gpu/drm/amd/display/dc/resource/dcn21/dcn21_resource.c index c07da45e1e2c..65d337731f56 100644 --- a/drivers/gpu/drm/amd/display/dc/resource/dcn21/dcn21_resource.c +++ b/drivers/gpu/drm/amd/display/dc/resource/dcn21/dcn21_resource.c @@ -713,9 +713,8 @@ static void dcn21_resource_destruct(struct dcn21_resource_pool *pool) pool->base.hubps[i] = NULL; } - if (pool->base.irqs != NULL) { + if (pool->base.irqs != NULL) dal_irq_service_destroy(&pool->base.irqs); - } } for (i = 0; i < pool->base.res_cap->num_ddc; i++) { -- cgit From ca0b006939f9701ab2e14a08ed9ef77a8014d2c5 Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Fri, 10 Nov 2023 09:39:18 -0500 Subject: drm/amdgpu: fix AGP addressing when GART is not at 0 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This worked by luck if the GART aperture ended up at 0. When we ended up moving GART on some chips, the GART aperture ended up offsetting the AGP address since the resource->start is a GART offset, not an MC address. Fix this by moving the AGP address setup into amdgpu_bo_gpu_offset_no_check(). v2: check mem_type before checking agp v3: check if the ttm bo has a ttm_tt allocated yet Fixes: 67318cb84341 ("drm/amdgpu/gmc11: set gart placement GC11") Tested-by: Mario Limonciello Reported-by: Jesse Zhang Reported-by: Yifan Zhang Reviewed-by: Christian König Signed-off-by: Alex Deucher Cc: christian.koenig@amd.com Cc: mario.limonciello@amd.com --- drivers/gpu/drm/amd/amdgpu/amdgpu_gmc.c | 3 +++ drivers/gpu/drm/amd/amdgpu/amdgpu_object.c | 10 +++++++--- drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c | 4 +--- 3 files changed, 11 insertions(+), 6 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_gmc.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_gmc.c index 5f71414190e9..d2f273d77e59 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_gmc.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_gmc.c @@ -181,6 +181,9 @@ uint64_t amdgpu_gmc_agp_addr(struct ttm_buffer_object *bo) { struct amdgpu_device *adev = amdgpu_ttm_adev(bo->bdev); + if (!bo->ttm) + return AMDGPU_BO_INVALID_OFFSET; + if (bo->ttm->num_pages != 1 || bo->ttm->caching == ttm_cached) return AMDGPU_BO_INVALID_OFFSET; diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_object.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_object.c index cef920a93924..d79b4ca1ecfc 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_object.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_object.c @@ -1527,10 +1527,14 @@ u64 amdgpu_bo_gpu_offset(struct amdgpu_bo *bo) u64 amdgpu_bo_gpu_offset_no_check(struct amdgpu_bo *bo) { struct amdgpu_device *adev = amdgpu_ttm_adev(bo->tbo.bdev); - uint64_t offset; + uint64_t offset = AMDGPU_BO_INVALID_OFFSET; - offset = (bo->tbo.resource->start << PAGE_SHIFT) + - amdgpu_ttm_domain_start(adev, bo->tbo.resource->mem_type); + if (bo->tbo.resource->mem_type == TTM_PL_TT) + offset = amdgpu_gmc_agp_addr(&bo->tbo); + + if (offset == AMDGPU_BO_INVALID_OFFSET) + offset = (bo->tbo.resource->start << PAGE_SHIFT) + + amdgpu_ttm_domain_start(adev, bo->tbo.resource->mem_type); return amdgpu_gmc_sign_extend(offset); } diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c index 05991c5c8ddb..ab4a762aed5b 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c @@ -959,10 +959,8 @@ int amdgpu_ttm_alloc_gart(struct ttm_buffer_object *bo) return 0; addr = amdgpu_gmc_agp_addr(bo); - if (addr != AMDGPU_BO_INVALID_OFFSET) { - bo->resource->start = addr >> PAGE_SHIFT; + if (addr != AMDGPU_BO_INVALID_OFFSET) return 0; - } /* allocate GART space */ placement.num_placement = 1; -- cgit From b0e5c88d8a88bdcc9834409387e10a5ae1b2753e Mon Sep 17 00:00:00 2001 From: Dinghao Liu Date: Thu, 23 Nov 2023 15:33:22 +0800 Subject: drm/amd/pm: fix a memleak in aldebaran_tables_init When kzalloc() for smu_table->ecc_table fails, we should free the previously allocated resources to prevent memleak. Fixes: edd794208555 ("drm/amd/pm: add message smu to get ecc_table v2") Signed-off-by: Dinghao Liu Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/pm/swsmu/smu13/aldebaran_ppt.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu13/aldebaran_ppt.c b/drivers/gpu/drm/amd/pm/swsmu/smu13/aldebaran_ppt.c index 1a6675d70a4b..f1440869d1ce 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/smu13/aldebaran_ppt.c +++ b/drivers/gpu/drm/amd/pm/swsmu/smu13/aldebaran_ppt.c @@ -257,8 +257,11 @@ static int aldebaran_tables_init(struct smu_context *smu) } smu_table->ecc_table = kzalloc(tables[SMU_TABLE_ECCINFO].size, GFP_KERNEL); - if (!smu_table->ecc_table) + if (!smu_table->ecc_table) { + kfree(smu_table->metrics_table); + kfree(smu_table->gpu_metrics_table); return -ENOMEM; + } return 0; } -- cgit From 7b194fdccb8458779687063e582cf218a0920c29 Mon Sep 17 00:00:00 2001 From: Lu Yao Date: Thu, 23 Nov 2023 09:22:34 +0800 Subject: drm/amdgpu: Fix cat debugfs amdgpu_regs_didt causes kernel null pointer MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit For 'AMDGPU_FAMILY_SI' family cards, in 'si_common_early_init' func, init 'didt_rreg' and 'didt_wreg' to 'NULL'. But in func 'amdgpu_debugfs_regs_didt_read/write', using 'RREG32_DIDT' 'WREG32_DIDT' lacks of relevant judgment. And other 'amdgpu_ip_block_version' that use these two definitions won't be added for 'AMDGPU_FAMILY_SI'. So, add null pointer judgment before calling. Reviewed-by: Christian König Signed-off-by: Lu Yao Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c index a53f436fa9f1..0e61ebdb3f3e 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c @@ -638,6 +638,9 @@ static ssize_t amdgpu_debugfs_regs_didt_read(struct file *f, char __user *buf, if (size & 0x3 || *pos & 0x3) return -EINVAL; + if (!adev->didt_rreg) + return -EOPNOTSUPP; + r = pm_runtime_get_sync(adev_to_drm(adev)->dev); if (r < 0) { pm_runtime_put_autosuspend(adev_to_drm(adev)->dev); @@ -694,6 +697,9 @@ static ssize_t amdgpu_debugfs_regs_didt_write(struct file *f, const char __user if (size & 0x3 || *pos & 0x3) return -EINVAL; + if (!adev->didt_wreg) + return -EOPNOTSUPP; + r = pm_runtime_get_sync(adev_to_drm(adev)->dev); if (r < 0) { pm_runtime_put_autosuspend(adev_to_drm(adev)->dev); -- cgit From bd1f6a31e7762ebc99b97f3eda5e5ea3708fa792 Mon Sep 17 00:00:00 2001 From: Mario Limonciello Date: Fri, 24 Nov 2023 09:56:32 -0600 Subject: drm/amd: Enable PCIe PME from D3 When dGPU is put into BOCO it may be in D3cold but still able send PME on display hotplug event. For this to work it must be enabled as wake source from D3. When runpm is enabled use pci_wake_from_d3() to mark wakeup as enabled by default. Cc: stable@vger.kernel.org # 6.1+ Signed-off-by: Mario Limonciello Acked-by: Alex Deucher Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c index 8f24cabe2155..8b33b130ea36 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c @@ -2263,6 +2263,8 @@ retry_init: pm_runtime_mark_last_busy(ddev->dev); pm_runtime_put_autosuspend(ddev->dev); + pci_wake_from_d3(pdev, TRUE); + /* * For runpm implemented via BACO, PMFW will handle the * timing for BACO in and out: -- cgit From 2e583200907cc43f062321bf751fe4b0960dbecf Mon Sep 17 00:00:00 2001 From: Dmytro Laktyushkin Date: Mon, 13 Nov 2023 13:12:44 -0500 Subject: drm/amd/display: block dcn315 dynamic crb allocation when unintended [WHY/HOW] Limit the dynamic crb to dual stream configs that include eDP Reviewed-by: Charlene Liu Acked-by: Tom Chung Signed-off-by: Dmytro Laktyushkin Tested-by: Daniel Wheeler Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/resource/dcn315/dcn315_resource.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/resource/dcn315/dcn315_resource.c b/drivers/gpu/drm/amd/display/dc/resource/dcn315/dcn315_resource.c index cb8024eee8e4..515ba435f759 100644 --- a/drivers/gpu/drm/amd/display/dc/resource/dcn315/dcn315_resource.c +++ b/drivers/gpu/drm/amd/display/dc/resource/dcn315/dcn315_resource.c @@ -1631,8 +1631,10 @@ static bool allow_pixel_rate_crb(struct dc *dc, struct dc_state *context) int i; struct resource_context *res_ctx = &context->res_ctx; - /*Don't apply for single stream*/ - if (context->stream_count < 2) + /* Only apply for dual stream scenarios with edp*/ + if (context->stream_count != 2) + return false; + if (context->streams[0]->signal != SIGNAL_TYPE_EDP && context->streams[1]->signal != SIGNAL_TYPE_EDP) return false; for (i = 0; i < dc->res_pool->pipe_count; i++) { -- cgit From 4fc26c2f912b5d9232dc4432fb1b7bfd6f016be6 Mon Sep 17 00:00:00 2001 From: Michael Strauss Date: Fri, 13 Oct 2023 12:13:28 -0400 Subject: drm/amd/display: Update Fixed VS/PE Retimer Sequence [WHY/HOW] Add a new AUX sequence provided by vendor to improve interop with specific display configurations. Reviewed-by: Wenjing Liu Acked-by: Tom Chung Signed-off-by: Michael Strauss Tested-by: Daniel Wheeler Signed-off-by: Alex Deucher --- .../dc/link/protocols/link_dp_training_fixed_vs_pe_retimer.c | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_training_fixed_vs_pe_retimer.c b/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_training_fixed_vs_pe_retimer.c index 68096d12f52f..7087cdc9e977 100644 --- a/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_training_fixed_vs_pe_retimer.c +++ b/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_training_fixed_vs_pe_retimer.c @@ -205,6 +205,7 @@ enum link_training_result dp_perform_fixed_vs_pe_training_sequence_legacy( const uint8_t vendor_lttpr_write_data_4lane_3[4] = {0x1, 0x6D, 0xF2, 0x18}; const uint8_t vendor_lttpr_write_data_4lane_4[4] = {0x1, 0x6C, 0xF2, 0x03}; const uint8_t vendor_lttpr_write_data_4lane_5[4] = {0x1, 0x03, 0xF3, 0x06}; + const uint8_t vendor_lttpr_write_data_dpmf[4] = {0x1, 0x6, 0x70, 0x87}; enum link_training_result status = LINK_TRAINING_SUCCESS; uint8_t lane = 0; union down_spread_ctrl downspread = {0}; @@ -293,6 +294,10 @@ enum link_training_result dp_perform_fixed_vs_pe_training_sequence_legacy( DP_DOWNSPREAD_CTRL, lt_settings->link_settings.link_spread); + link_configure_fixed_vs_pe_retimer(link->ddc, + &vendor_lttpr_write_data_dpmf[0], + sizeof(vendor_lttpr_write_data_dpmf)); + if (lt_settings->link_settings.lane_count == LANE_COUNT_FOUR) { link_configure_fixed_vs_pe_retimer(link->ddc, &vendor_lttpr_write_data_4lane_1[0], sizeof(vendor_lttpr_write_data_4lane_1)); @@ -552,6 +557,7 @@ enum link_training_result dp_perform_fixed_vs_pe_training_sequence( const uint8_t vendor_lttpr_write_data_4lane_3[4] = {0x1, 0x6D, 0xF2, 0x18}; const uint8_t vendor_lttpr_write_data_4lane_4[4] = {0x1, 0x6C, 0xF2, 0x03}; const uint8_t vendor_lttpr_write_data_4lane_5[4] = {0x1, 0x03, 0xF3, 0x06}; + const uint8_t vendor_lttpr_write_data_dpmf[4] = {0x1, 0x6, 0x70, 0x87}; enum link_training_result status = LINK_TRAINING_SUCCESS; uint8_t lane = 0; union down_spread_ctrl downspread = {0}; @@ -639,6 +645,10 @@ enum link_training_result dp_perform_fixed_vs_pe_training_sequence( DP_DOWNSPREAD_CTRL, lt_settings->link_settings.link_spread); + link_configure_fixed_vs_pe_retimer(link->ddc, + &vendor_lttpr_write_data_dpmf[0], + sizeof(vendor_lttpr_write_data_dpmf)); + if (lt_settings->link_settings.lane_count == LANE_COUNT_FOUR) { link_configure_fixed_vs_pe_retimer(link->ddc, &vendor_lttpr_write_data_4lane_1[0], sizeof(vendor_lttpr_write_data_4lane_1)); -- cgit From 9a1c1339abf972477aeef4ea037e650f49c5892d Mon Sep 17 00:00:00 2001 From: Felix Kuehling Date: Fri, 27 Oct 2023 18:21:55 -0400 Subject: drm/amdkfd: Run restore_workers on freezable WQs MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Make restore workers freezable so we don't have to explicitly flush them in suspend and GPU reset code paths, and we don't accidentally try to restore BOs while the GPU is suspended. Not having to flush restore_work also helps avoid lock/fence dependencies in the GPU reset case where we're not allowed to wait for fences. A side effect of this is, that we can now have multiple concurrent threads trying to signal the same eviction fence. Rework eviction fence signaling and replacement to account for that. The GPU reset path can no longer rely on restore_process_worker to resume queues because evict/restore workers can run independently of it. Instead call a new restore_process_helper directly. This is an RFC and request for testing. v2: - Reworked eviction fence signaling - Introduced restore_process_helper v3: - Handle unsignaled eviction fences in restore_process_bos Signed-off-by: Felix Kuehling Acked-by: Christian König Tested-by: Emily Deng Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c | 68 ++++++++++++------ drivers/gpu/drm/amd/amdkfd/kfd_process.c | 87 +++++++++++++++--------- drivers/gpu/drm/amd/amdkfd/kfd_svm.c | 4 +- 3 files changed, 104 insertions(+), 55 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c index b98c0969d3be..73288f9ccaf8 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c @@ -1384,7 +1384,6 @@ static int init_kfd_vm(struct amdgpu_vm *vm, void **process_info, amdgpu_amdkfd_restore_userptr_worker); *process_info = info; - *ef = dma_fence_get(&info->eviction_fence->base); } vm->process_info = *process_info; @@ -1415,6 +1414,8 @@ static int init_kfd_vm(struct amdgpu_vm *vm, void **process_info, list_add_tail(&vm->vm_list_node, &(vm->process_info->vm_list_head)); vm->process_info->n_vms++; + + *ef = dma_fence_get(&vm->process_info->eviction_fence->base); mutex_unlock(&vm->process_info->lock); return 0; @@ -1426,10 +1427,7 @@ validate_pd_fail: reserve_pd_fail: vm->process_info = NULL; if (info) { - /* Two fence references: one in info and one in *ef */ dma_fence_put(&info->eviction_fence->base); - dma_fence_put(*ef); - *ef = NULL; *process_info = NULL; put_pid(info->pid); create_evict_fence_fail: @@ -1623,7 +1621,8 @@ int amdgpu_amdkfd_criu_resume(void *p) goto out_unlock; } WRITE_ONCE(pinfo->block_mmu_notifications, false); - schedule_delayed_work(&pinfo->restore_userptr_work, 0); + queue_delayed_work(system_freezable_wq, + &pinfo->restore_userptr_work, 0); out_unlock: mutex_unlock(&pinfo->lock); @@ -2426,7 +2425,8 @@ int amdgpu_amdkfd_evict_userptr(struct mmu_interval_notifier *mni, KFD_QUEUE_EVICTION_TRIGGER_USERPTR); if (r) pr_err("Failed to quiesce KFD\n"); - schedule_delayed_work(&process_info->restore_userptr_work, + queue_delayed_work(system_freezable_wq, + &process_info->restore_userptr_work, msecs_to_jiffies(AMDGPU_USERPTR_RESTORE_DELAY_MS)); } mutex_unlock(&process_info->notifier_lock); @@ -2749,7 +2749,8 @@ unlock_out: /* If validation failed, reschedule another attempt */ if (evicted_bos) { - schedule_delayed_work(&process_info->restore_userptr_work, + queue_delayed_work(system_freezable_wq, + &process_info->restore_userptr_work, msecs_to_jiffies(AMDGPU_USERPTR_RESTORE_DELAY_MS)); kfd_smi_event_queue_restore_rescheduled(mm); @@ -2758,6 +2759,23 @@ unlock_out: put_task_struct(usertask); } +static void replace_eviction_fence(struct dma_fence **ef, + struct dma_fence *new_ef) +{ + struct dma_fence *old_ef = rcu_replace_pointer(*ef, new_ef, true + /* protected by process_info->lock */); + + /* If we're replacing an unsignaled eviction fence, that fence will + * never be signaled, and if anyone is still waiting on that fence, + * they will hang forever. This should never happen. We should only + * replace the fence in restore_work that only gets scheduled after + * eviction work signaled the fence. + */ + WARN_ONCE(!dma_fence_is_signaled(old_ef), + "Replacing unsignaled eviction fence"); + dma_fence_put(old_ef); +} + /** amdgpu_amdkfd_gpuvm_restore_process_bos - Restore all BOs for the given * KFD process identified by process_info * @@ -2781,7 +2799,6 @@ int amdgpu_amdkfd_gpuvm_restore_process_bos(void *info, struct dma_fence **ef) struct amdkfd_process_info *process_info = info; struct amdgpu_vm *peer_vm; struct kgd_mem *mem; - struct amdgpu_amdkfd_fence *new_fence; struct list_head duplicate_save; struct amdgpu_sync sync_obj; unsigned long failed_size = 0; @@ -2907,22 +2924,35 @@ int amdgpu_amdkfd_gpuvm_restore_process_bos(void *info, struct dma_fence **ef) /* Wait for validate and PT updates to finish */ amdgpu_sync_wait(&sync_obj, false); - /* Release old eviction fence and create new one, because fence only - * goes from unsignaled to signaled, fence cannot be reused. - * Use context and mm from the old fence. + /* The old eviction fence may be unsignaled if restore happens + * after a GPU reset or suspend/resume. Keep the old fence in that + * case. Otherwise release the old eviction fence and create new + * one, because fence only goes from unsignaled to signaled once + * and cannot be reused. Use context and mm from the old fence. + * + * If an old eviction fence signals after this check, that's OK. + * Anyone signaling an eviction fence must stop the queues first + * and schedule another restore worker. */ - new_fence = amdgpu_amdkfd_fence_create( + if (dma_fence_is_signaled(&process_info->eviction_fence->base)) { + struct amdgpu_amdkfd_fence *new_fence = + amdgpu_amdkfd_fence_create( process_info->eviction_fence->base.context, process_info->eviction_fence->mm, NULL); - if (!new_fence) { - pr_err("Failed to create eviction fence\n"); - ret = -ENOMEM; - goto validate_map_fail; + + if (!new_fence) { + pr_err("Failed to create eviction fence\n"); + ret = -ENOMEM; + goto validate_map_fail; + } + dma_fence_put(&process_info->eviction_fence->base); + process_info->eviction_fence = new_fence; + replace_eviction_fence(ef, dma_fence_get(&new_fence->base)); + } else { + WARN_ONCE(*ef != &process_info->eviction_fence->base, + "KFD eviction fence doesn't match KGD process_info"); } - dma_fence_put(&process_info->eviction_fence->base); - process_info->eviction_fence = new_fence; - *ef = dma_fence_get(&new_fence->base); /* Attach new eviction fence to all BOs except pinned ones */ list_for_each_entry(mem, &process_info->kfd_bo_list, validate_list) { diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_process.c b/drivers/gpu/drm/amd/amdkfd/kfd_process.c index c10d050e1a61..71df51fcc1b0 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_process.c +++ b/drivers/gpu/drm/amd/amdkfd/kfd_process.c @@ -664,7 +664,8 @@ int kfd_process_create_wq(void) if (!kfd_process_wq) kfd_process_wq = alloc_workqueue("kfd_process_wq", 0, 0); if (!kfd_restore_wq) - kfd_restore_wq = alloc_ordered_workqueue("kfd_restore_wq", 0); + kfd_restore_wq = alloc_ordered_workqueue("kfd_restore_wq", + WQ_FREEZABLE); if (!kfd_process_wq || !kfd_restore_wq) { kfd_process_destroy_wq(); @@ -1642,6 +1643,7 @@ int kfd_process_device_init_vm(struct kfd_process_device *pdd, struct amdgpu_fpriv *drv_priv; struct amdgpu_vm *avm; struct kfd_process *p; + struct dma_fence *ef; struct kfd_node *dev; int ret; @@ -1661,11 +1663,12 @@ int kfd_process_device_init_vm(struct kfd_process_device *pdd, ret = amdgpu_amdkfd_gpuvm_acquire_process_vm(dev->adev, avm, &p->kgd_process_info, - &p->ef); + &ef); if (ret) { pr_err("Failed to create process VM object\n"); return ret; } + RCU_INIT_POINTER(p->ef, ef); pdd->drm_priv = drm_file->private_data; ret = kfd_process_device_reserve_ib_mem(pdd); @@ -1908,6 +1911,21 @@ kfd_process_gpuid_from_node(struct kfd_process *p, struct kfd_node *node, return -EINVAL; } +static int signal_eviction_fence(struct kfd_process *p) +{ + struct dma_fence *ef; + int ret; + + rcu_read_lock(); + ef = dma_fence_get_rcu_safe(&p->ef); + rcu_read_unlock(); + + ret = dma_fence_signal(ef); + dma_fence_put(ef); + + return ret; +} + static void evict_process_worker(struct work_struct *work) { int ret; @@ -1920,31 +1938,46 @@ static void evict_process_worker(struct work_struct *work) * lifetime of this thread, kfd_process p will be valid */ p = container_of(dwork, struct kfd_process, eviction_work); - WARN_ONCE(p->last_eviction_seqno != p->ef->seqno, - "Eviction fence mismatch\n"); - - /* Narrow window of overlap between restore and evict work - * item is possible. Once amdgpu_amdkfd_gpuvm_restore_process_bos - * unreserves KFD BOs, it is possible to evicted again. But - * restore has few more steps of finish. So lets wait for any - * previous restore work to complete - */ - flush_delayed_work(&p->restore_work); pr_debug("Started evicting pasid 0x%x\n", p->pasid); ret = kfd_process_evict_queues(p, KFD_QUEUE_EVICTION_TRIGGER_TTM); if (!ret) { - dma_fence_signal(p->ef); - dma_fence_put(p->ef); - p->ef = NULL; - queue_delayed_work(kfd_restore_wq, &p->restore_work, + /* If another thread already signaled the eviction fence, + * they are responsible stopping the queues and scheduling + * the restore work. + */ + if (!signal_eviction_fence(p)) + queue_delayed_work(kfd_restore_wq, &p->restore_work, msecs_to_jiffies(PROCESS_RESTORE_TIME_MS)); + else + kfd_process_restore_queues(p); pr_debug("Finished evicting pasid 0x%x\n", p->pasid); } else pr_err("Failed to evict queues of pasid 0x%x\n", p->pasid); } +static int restore_process_helper(struct kfd_process *p) +{ + int ret = 0; + + /* VMs may not have been acquired yet during debugging. */ + if (p->kgd_process_info) { + ret = amdgpu_amdkfd_gpuvm_restore_process_bos( + p->kgd_process_info, &p->ef); + if (ret) + return ret; + } + + ret = kfd_process_restore_queues(p); + if (!ret) + pr_debug("Finished restoring pasid 0x%x\n", p->pasid); + else + pr_err("Failed to restore queues of pasid 0x%x\n", p->pasid); + + return ret; +} + static void restore_process_worker(struct work_struct *work) { struct delayed_work *dwork; @@ -1970,24 +2003,15 @@ static void restore_process_worker(struct work_struct *work) */ p->last_restore_timestamp = get_jiffies_64(); - /* VMs may not have been acquired yet during debugging. */ - if (p->kgd_process_info) - ret = amdgpu_amdkfd_gpuvm_restore_process_bos(p->kgd_process_info, - &p->ef); + + ret = restore_process_helper(p); if (ret) { pr_debug("Failed to restore BOs of pasid 0x%x, retry after %d ms\n", p->pasid, PROCESS_BACK_OFF_TIME_MS); ret = queue_delayed_work(kfd_restore_wq, &p->restore_work, msecs_to_jiffies(PROCESS_BACK_OFF_TIME_MS)); WARN(!ret, "reschedule restore work failed\n"); - return; } - - ret = kfd_process_restore_queues(p); - if (!ret) - pr_debug("Finished restoring pasid 0x%x\n", p->pasid); - else - pr_err("Failed to restore queues of pasid 0x%x\n", p->pasid); } void kfd_suspend_all_processes(void) @@ -1998,14 +2022,9 @@ void kfd_suspend_all_processes(void) WARN(debug_evictions, "Evicting all processes"); hash_for_each_rcu(kfd_processes_table, temp, p, kfd_processes) { - cancel_delayed_work_sync(&p->eviction_work); - flush_delayed_work(&p->restore_work); - if (kfd_process_evict_queues(p, KFD_QUEUE_EVICTION_TRIGGER_SUSPEND)) pr_err("Failed to suspend process 0x%x\n", p->pasid); - dma_fence_signal(p->ef); - dma_fence_put(p->ef); - p->ef = NULL; + signal_eviction_fence(p); } srcu_read_unlock(&kfd_processes_srcu, idx); } @@ -2017,7 +2036,7 @@ int kfd_resume_all_processes(void) int ret = 0, idx = srcu_read_lock(&kfd_processes_srcu); hash_for_each_rcu(kfd_processes_table, temp, p, kfd_processes) { - if (!queue_delayed_work(kfd_restore_wq, &p->restore_work, 0)) { + if (restore_process_helper(p)) { pr_err("Restore process %d failed during resume\n", p->pasid); ret = -EFAULT; diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_svm.c b/drivers/gpu/drm/amd/amdkfd/kfd_svm.c index f2f3c338fd94..613f19510287 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_svm.c +++ b/drivers/gpu/drm/amd/amdkfd/kfd_svm.c @@ -1870,7 +1870,7 @@ out_reschedule: /* If validation failed, reschedule another attempt */ if (evicted_ranges) { pr_debug("reschedule to restore svm range\n"); - schedule_delayed_work(&svms->restore_work, + queue_delayed_work(system_freezable_wq, &svms->restore_work, msecs_to_jiffies(AMDGPU_SVM_RANGE_RESTORE_DELAY_MS)); kfd_smi_event_queue_restore_rescheduled(mm); @@ -1946,7 +1946,7 @@ svm_range_evict(struct svm_range *prange, struct mm_struct *mm, pr_debug("failed to quiesce KFD\n"); pr_debug("schedule to restore svm %p ranges\n", svms); - schedule_delayed_work(&svms->restore_work, + queue_delayed_work(system_freezable_wq, &svms->restore_work, msecs_to_jiffies(AMDGPU_SVM_RANGE_RESTORE_DELAY_MS)); } else { unsigned long s, l; -- cgit From 1919fd6bb09f61015549b9e5a5af1541b41f45d9 Mon Sep 17 00:00:00 2001 From: Anthony Koo Date: Sat, 18 Nov 2023 14:39:40 -0500 Subject: drm/amd/display: [FW Promotion] Release 0.0.194.0 - Add a new dmub command in enum dmub_cmd_cab_type Reviewed-by: Tom Chung Acked-by: Tom Chung Signed-off-by: Anthony Koo Tested-by: Daniel Wheeler Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dmub/inc/dmub_cmd.h | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/gpu/drm/amd/display/dmub/inc/dmub_cmd.h b/drivers/gpu/drm/amd/display/dmub/inc/dmub_cmd.h index b7d9360bfdc8..a365f6c096de 100644 --- a/drivers/gpu/drm/amd/display/dmub/inc/dmub_cmd.h +++ b/drivers/gpu/drm/amd/display/dmub/inc/dmub_cmd.h @@ -1345,6 +1345,10 @@ enum dmub_cmd_cab_type { * Fit surfaces in CAB (i.e. CAB enable) */ DMUB_CMD__CAB_DCN_SS_FIT_IN_CAB = 2, + /** + * Do not fit surfaces in CAB (i.e. no CAB) + */ + DMUB_CMD__CAB_DCN_SS_NOT_FIT_IN_CAB = 3, }; /** -- cgit From 061a5bf210cd7b941627092309ff6035a017cda3 Mon Sep 17 00:00:00 2001 From: Nicholas Kazlauskas Date: Tue, 14 Nov 2023 11:22:09 -0500 Subject: drm/amd/display: Allow DTBCLK disable for DCN35 [Why] DTBCLK is enabled on idle and it will burn power. [How] There's a few issues here: - Always enabling DTBCLK on clock manager init - Setting refclk when DTBCLK is supposed to be disabled - Not applying the correct calculated version refclk, but instead the base value which might be zero On dtbclk_en change we'll message PMFW to enable or disable the clock accordingly. The DTBDTO will be then based on refclk, but it will be set to the default fixed value if there was nothing calculated in DML despite the clock being considered enabled. Reviewed-by: Charlene Liu Acked-by: Tom Chung Signed-off-by: Nicholas Kazlauskas Tested-by: Daniel Wheeler Signed-off-by: Alex Deucher --- .../amd/display/dc/clk_mgr/dcn35/dcn35_clk_mgr.c | 27 ++++++++++------------ 1 file changed, 12 insertions(+), 15 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn35/dcn35_clk_mgr.c b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn35/dcn35_clk_mgr.c index 63a0b885b6f0..d5fde7d23fbf 100644 --- a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn35/dcn35_clk_mgr.c +++ b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn35/dcn35_clk_mgr.c @@ -232,6 +232,10 @@ void dcn35_update_clocks(struct clk_mgr *clk_mgr_base, if (dc->work_arounds.skip_clock_update) return; + /* DTBCLK is fixed, so set a default if unspecified. */ + if (new_clocks->dtbclk_en && !new_clocks->ref_dtbclk_khz) + new_clocks->ref_dtbclk_khz = 600000; + /* * if it is safe to lower, but we are already in the lower state, we don't have to do anything * also if safe to lower is false, we just go in the higher state @@ -265,8 +269,10 @@ void dcn35_update_clocks(struct clk_mgr *clk_mgr_base, if (!clk_mgr_base->clks.dtbclk_en && new_clocks->dtbclk_en) { dcn35_smu_set_dtbclk(clk_mgr, true); - dcn35_update_clocks_update_dtb_dto(clk_mgr, context, clk_mgr_base->clks.ref_dtbclk_khz); clk_mgr_base->clks.dtbclk_en = new_clocks->dtbclk_en; + + dcn35_update_clocks_update_dtb_dto(clk_mgr, context, new_clocks->ref_dtbclk_khz); + clk_mgr_base->clks.ref_dtbclk_khz = new_clocks->ref_dtbclk_khz; } /* check that we're not already in D0 */ @@ -314,17 +320,12 @@ void dcn35_update_clocks(struct clk_mgr *clk_mgr_base, update_dispclk = true; } - if (!new_clocks->dtbclk_en) { - new_clocks->ref_dtbclk_khz = 600000; - } - /* clock limits are received with MHz precision, divide by 1000 to prevent setting clocks at every call */ if (!dc->debug.disable_dtb_ref_clk_switch && - should_set_clock(safe_to_lower, new_clocks->ref_dtbclk_khz / 1000, clk_mgr_base->clks.ref_dtbclk_khz / 1000)) { - /* DCCG requires KHz precision for DTBCLK */ - dcn35_smu_set_dtbclk(clk_mgr, true); - - dcn35_update_clocks_update_dtb_dto(clk_mgr, context, clk_mgr_base->clks.ref_dtbclk_khz); + should_set_clock(safe_to_lower, new_clocks->ref_dtbclk_khz / 1000, + clk_mgr_base->clks.ref_dtbclk_khz / 1000)) { + dcn35_update_clocks_update_dtb_dto(clk_mgr, context, new_clocks->ref_dtbclk_khz); + clk_mgr_base->clks.ref_dtbclk_khz = new_clocks->ref_dtbclk_khz; } if (dpp_clock_lowered) { @@ -1048,12 +1049,8 @@ void dcn35_clk_mgr_construct( dcn35_dump_clk_registers(&clk_mgr->base.base.boot_snapshot, &clk_mgr->base.base, &log_info); clk_mgr->base.base.dprefclk_khz = dcn35_smu_get_dprefclk(&clk_mgr->base); - clk_mgr->base.base.clks.ref_dtbclk_khz = dcn35_smu_get_dtbclk(&clk_mgr->base); - - if (!clk_mgr->base.base.clks.ref_dtbclk_khz) - dcn35_smu_set_dtbclk(&clk_mgr->base, true); + clk_mgr->base.base.clks.ref_dtbclk_khz = 600000; - clk_mgr->base.base.clks.dtbclk_en = true; dce_clock_read_ss_info(&clk_mgr->base); /*when clk src is from FCH, it could have ss, same clock src as DPREF clk*/ -- cgit From ca0ad76089a8171d7a075e50b7beecf092f8fd0c Mon Sep 17 00:00:00 2001 From: Candice Li Date: Fri, 24 Nov 2023 09:33:47 +0800 Subject: drm/amdgpu: Update EEPROM I2C address for smu v13_0_0 Check smu v13_0_0 SKU type to select EEPROM I2C address. Signed-off-by: Candice Li Reviewed-by: Hawking Zhang Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_ras_eeprom.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ras_eeprom.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ras_eeprom.c index 65aa218380be..2fde93b00cab 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ras_eeprom.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ras_eeprom.c @@ -214,6 +214,12 @@ static bool __get_eeprom_i2c_addr(struct amdgpu_device *adev, control->i2c_address = EEPROM_I2C_MADDR_0; return true; case IP_VERSION(13, 0, 0): + if (strnstr(atom_ctx->vbios_pn, "D707", + sizeof(atom_ctx->vbios_pn))) + control->i2c_address = EEPROM_I2C_MADDR_0; + else + control->i2c_address = EEPROM_I2C_MADDR_4; + return true; case IP_VERSION(13, 0, 6): case IP_VERSION(13, 0, 10): control->i2c_address = EEPROM_I2C_MADDR_4; -- cgit From d581ceab26a1be9fe94befe2604cbe99eadf1acc Mon Sep 17 00:00:00 2001 From: ZhenGuo Yin Date: Mon, 6 Nov 2023 18:07:51 +0800 Subject: drm/amdkfd: Free gang_ctx_bo and wptr_bo in pqm_uninit [Why] Memory leaks of gang_ctx_bo and wptr_bo. [How] Free gang_ctx_bo and wptr_bo in pqm_uninit. v2: add a common function pqm_clean_queue_resource to free queue's resources. v3: reset pdd->pqd.num_gws when destorying GWS queue. Reviewed-by: Felix Kuehling Signed-off-by: ZhenGuo Yin Signed-off-by: Alex Deucher --- .../gpu/drm/amd/amdkfd/kfd_process_queue_manager.c | 54 +++++++++++++--------- 1 file changed, 33 insertions(+), 21 deletions(-) diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_process_queue_manager.c b/drivers/gpu/drm/amd/amdkfd/kfd_process_queue_manager.c index 77649392e233..77f493262e05 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_process_queue_manager.c +++ b/drivers/gpu/drm/amd/amdkfd/kfd_process_queue_manager.c @@ -169,16 +169,43 @@ int pqm_init(struct process_queue_manager *pqm, struct kfd_process *p) return 0; } +static void pqm_clean_queue_resource(struct process_queue_manager *pqm, + struct process_queue_node *pqn) +{ + struct kfd_node *dev; + struct kfd_process_device *pdd; + + dev = pqn->q->device; + + pdd = kfd_get_process_device_data(dev, pqm->process); + if (!pdd) { + pr_err("Process device data doesn't exist\n"); + return; + } + + if (pqn->q->gws) { + if (KFD_GC_VERSION(pqn->q->device) != IP_VERSION(9, 4, 3) && + !dev->kfd->shared_resources.enable_mes) + amdgpu_amdkfd_remove_gws_from_process( + pqm->process->kgd_process_info, pqn->q->gws); + pdd->qpd.num_gws = 0; + } + + if (dev->kfd->shared_resources.enable_mes) { + amdgpu_amdkfd_free_gtt_mem(dev->adev, pqn->q->gang_ctx_bo); + if (pqn->q->wptr_bo) + amdgpu_amdkfd_free_gtt_mem(dev->adev, pqn->q->wptr_bo); + } +} + void pqm_uninit(struct process_queue_manager *pqm) { struct process_queue_node *pqn, *next; list_for_each_entry_safe(pqn, next, &pqm->queues, process_queue_list) { - if (pqn->q && pqn->q->gws && - KFD_GC_VERSION(pqn->q->device) != IP_VERSION(9, 4, 3) && - !pqn->q->device->kfd->shared_resources.enable_mes) - amdgpu_amdkfd_remove_gws_from_process(pqm->process->kgd_process_info, - pqn->q->gws); + if (pqn->q) + pqm_clean_queue_resource(pqm, pqn); + kfd_procfs_del_queue(pqn->q); uninit_queue(pqn->q); list_del(&pqn->process_queue_list); @@ -461,22 +488,7 @@ int pqm_destroy_queue(struct process_queue_manager *pqm, unsigned int qid) goto err_destroy_queue; } - if (pqn->q->gws) { - if (KFD_GC_VERSION(pqn->q->device) != IP_VERSION(9, 4, 3) && - !dev->kfd->shared_resources.enable_mes) - amdgpu_amdkfd_remove_gws_from_process( - pqm->process->kgd_process_info, - pqn->q->gws); - pdd->qpd.num_gws = 0; - } - - if (dev->kfd->shared_resources.enable_mes) { - amdgpu_amdkfd_free_gtt_mem(dev->adev, - pqn->q->gang_ctx_bo); - if (pqn->q->wptr_bo) - amdgpu_amdkfd_free_gtt_mem(dev->adev, pqn->q->wptr_bo); - - } + pqm_clean_queue_resource(pqm, pqn); uninit_queue(pqn->q); } -- cgit From 5290ed0a8b261115fe4965a6d95a642b0742d159 Mon Sep 17 00:00:00 2001 From: Ilya Bakoulin Date: Thu, 16 Nov 2023 15:28:53 -0500 Subject: drm/amd/display: Add DSC granular throughput adjustment [Why/How] Update DSC DPCD parsing to take granular throughput adjustment into consideration. Reviewed-by: Wenjing Liu Acked-by: Tom Chung Signed-off-by: Ilya Bakoulin Tested-by: Daniel Wheeler Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dsc/dc_dsc.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/dsc/dc_dsc.c b/drivers/gpu/drm/amd/display/dc/dsc/dc_dsc.c index e8b5f17beb96..0df6c55eb326 100644 --- a/drivers/gpu/drm/amd/display/dc/dsc/dc_dsc.c +++ b/drivers/gpu/drm/amd/display/dc/dsc/dc_dsc.c @@ -331,8 +331,9 @@ bool dc_dsc_parse_dsc_dpcd(const struct dc *dc, int buff_block_size; int buff_size; - if (!dsc_buff_block_size_from_dpcd(dpcd_dsc_basic_data[DP_DSC_RC_BUF_BLK_SIZE - DP_DSC_SUPPORT], - &buff_block_size)) + if (!dsc_buff_block_size_from_dpcd( + dpcd_dsc_basic_data[DP_DSC_RC_BUF_BLK_SIZE - DP_DSC_SUPPORT] & 0x03, + &buff_block_size)) return false; buff_size = dpcd_dsc_basic_data[DP_DSC_RC_BUF_SIZE - DP_DSC_SUPPORT] + 1; @@ -357,10 +358,15 @@ bool dc_dsc_parse_dsc_dpcd(const struct dc *dc, { int dpcd_throughput = dpcd_dsc_basic_data[DP_DSC_PEAK_THROUGHPUT - DP_DSC_SUPPORT]; + int dsc_throughput_granular_delta; + + dsc_throughput_granular_delta = dpcd_dsc_basic_data[DP_DSC_RC_BUF_BLK_SIZE - DP_DSC_SUPPORT] >> 3; + dsc_throughput_granular_delta *= 2; if (!dsc_throughput_from_dpcd(dpcd_throughput & DP_DSC_THROUGHPUT_MODE_0_MASK, &dsc_sink_caps->throughput_mode_0_mps)) return false; + dsc_sink_caps->throughput_mode_0_mps += dsc_throughput_granular_delta; dpcd_throughput = (dpcd_throughput & DP_DSC_THROUGHPUT_MODE_1_MASK) >> DP_DSC_THROUGHPUT_MODE_1_SHIFT; if (!dsc_throughput_from_dpcd(dpcd_throughput, &dsc_sink_caps->throughput_mode_1_mps)) -- cgit From 33a6e409165cd23d1dc580031cb749550ca18517 Mon Sep 17 00:00:00 2001 From: Taimur Hassan Date: Fri, 10 Nov 2023 10:24:20 -0500 Subject: drm/amd/display: Fix some HostVM parameters in DML [Why] A number of DML parameters related to HostVM were either missing or being set incorrectly, which may cause inaccuracies in calculating margins and determining BW limitations. [How] Correct these values where needed and populate the missing values. Cc: stable@vger.kernel.org Reviewed-by: Nicholas Kazlauskas Acked-by: Hamza Mahfooz Signed-off-by: Taimur Hassan Signed-off-by: Roman Li Tested-by: Daniel Wheeler Signed-off-by: Alex Deucher --- .../gpu/drm/amd/display/dc/dml/dcn35/dcn35_fpu.c | 33 ++++++++++++++++++++++ .../amd/display/dc/dml2/dml2_translation_helper.c | 9 ++++-- 2 files changed, 39 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/dml/dcn35/dcn35_fpu.c b/drivers/gpu/drm/amd/display/dc/dml/dcn35/dcn35_fpu.c index 21c17d3296a3..39cf1ae3a3e1 100644 --- a/drivers/gpu/drm/amd/display/dc/dml/dcn35/dcn35_fpu.c +++ b/drivers/gpu/drm/amd/display/dc/dml/dcn35/dcn35_fpu.c @@ -330,6 +330,39 @@ void dcn35_update_bw_bounding_box_fpu(struct dc *dc, dml_init_instance(&dc->dml, &dcn3_5_soc, &dcn3_5_ip, DML_PROJECT_DCN31); + /*copy to dml2, before dml2_create*/ + if (clk_table->num_entries > 2) { + + for (i = 0; i < clk_table->num_entries; i++) { + dc->dml2_options.bbox_overrides.clks_table.num_states = + clk_table->num_entries; + dc->dml2_options.bbox_overrides.clks_table.clk_entries[i].dcfclk_mhz = + clock_limits[i].dcfclk_mhz; + dc->dml2_options.bbox_overrides.clks_table.clk_entries[i].fclk_mhz = + clock_limits[i].fabricclk_mhz; + dc->dml2_options.bbox_overrides.clks_table.clk_entries[i].dispclk_mhz = + clock_limits[i].dispclk_mhz; + dc->dml2_options.bbox_overrides.clks_table.clk_entries[i].dppclk_mhz = + clock_limits[i].dppclk_mhz; + dc->dml2_options.bbox_overrides.clks_table.clk_entries[i].socclk_mhz = + clock_limits[i].socclk_mhz; + dc->dml2_options.bbox_overrides.clks_table.clk_entries[i].memclk_mhz = + clk_table->entries[i].memclk_mhz * clk_table->entries[i].wck_ratio; + dc->dml2_options.bbox_overrides.clks_table.num_entries_per_clk.num_dcfclk_levels = + clk_table->num_entries; + dc->dml2_options.bbox_overrides.clks_table.num_entries_per_clk.num_fclk_levels = + clk_table->num_entries; + dc->dml2_options.bbox_overrides.clks_table.num_entries_per_clk.num_dispclk_levels = + clk_table->num_entries; + dc->dml2_options.bbox_overrides.clks_table.num_entries_per_clk.num_dppclk_levels = + clk_table->num_entries; + dc->dml2_options.bbox_overrides.clks_table.num_entries_per_clk.num_socclk_levels = + clk_table->num_entries; + dc->dml2_options.bbox_overrides.clks_table.num_entries_per_clk.num_memclk_levels = + clk_table->num_entries; + } + } + /* Update latency values */ dc->dml2_options.bbox_overrides.dram_clock_change_latency_us = dcn3_5_soc.dram_clock_change_latency_us; diff --git a/drivers/gpu/drm/amd/display/dc/dml2/dml2_translation_helper.c b/drivers/gpu/drm/amd/display/dc/dml2/dml2_translation_helper.c index 48caa34a5ce7..fa8fe5bf7e57 100644 --- a/drivers/gpu/drm/amd/display/dc/dml2/dml2_translation_helper.c +++ b/drivers/gpu/drm/amd/display/dc/dml2/dml2_translation_helper.c @@ -1057,9 +1057,12 @@ void map_dc_state_into_dml_display_cfg(struct dml2_context *dml2, struct dc_stat } //Generally these are set by referencing our latest BB/IP params in dcn32_resource.c file - dml_dispcfg->plane.GPUVMEnable = true; - dml_dispcfg->plane.GPUVMMaxPageTableLevels = 4; - dml_dispcfg->plane.HostVMEnable = false; + dml_dispcfg->plane.GPUVMEnable = dml2->v20.dml_core_ctx.ip.gpuvm_enable; + dml_dispcfg->plane.GPUVMMaxPageTableLevels = dml2->v20.dml_core_ctx.ip.gpuvm_max_page_table_levels; + dml_dispcfg->plane.HostVMEnable = dml2->v20.dml_core_ctx.ip.hostvm_enable; + dml_dispcfg->plane.HostVMMaxPageTableLevels = dml2->v20.dml_core_ctx.ip.hostvm_max_page_table_levels; + if (dml2->v20.dml_core_ctx.ip.hostvm_enable) + dml2->v20.dml_core_ctx.policy.AllowForPStateChangeOrStutterInVBlankFinal = dml_prefetch_support_uclk_fclk_and_stutter; dml2_populate_pipe_to_plane_index_mapping(dml2, context); -- cgit From 70378005378a23fbfe0d4c44dac4187cad07da94 Mon Sep 17 00:00:00 2001 From: Aric Cyr Date: Sun, 19 Nov 2023 23:02:26 -0500 Subject: drm/amd/display: Promote DAL to 3.2.262 This version brings along following fixes: - Add DSC granular throughput adjustment - Allow DTBCLK disable for DCN35 - Update Fixed VS/PE Retimer Sequence - Block dcn315 dynamic crb allocation when unintended - Update dcn315 lpddr pstate latency - Fix some HostVM parameters in DML Reviewed-by: Tom Chung Acked-by: Tom Chung Signed-off-by: Aric Cyr Tested-by: Daniel Wheeler Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dc.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h index 6074ac1b180a..e8c1599ab18a 100644 --- a/drivers/gpu/drm/amd/display/dc/dc.h +++ b/drivers/gpu/drm/amd/display/dc/dc.h @@ -49,7 +49,7 @@ struct aux_payload; struct set_config_cmd_payload; struct dmub_notification; -#define DC_VER "3.2.261" +#define DC_VER "3.2.262" #define MAX_SURFACES 3 #define MAX_PLANES 6 -- cgit From 9a5095e785c38ab8d9f3d91f4ee76f4f73ec4adc Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Wed, 13 Sep 2023 12:00:44 -0400 Subject: drm/amdgpu: add amdgpu_reg_state.h This header defines the reg state structures exposed via sysfs for umr debugging. v2: add content type Signed-off-by: Alex Deucher Signed-off-by: Lijo Lazar Reviewed-by: Hawking Zhang --- drivers/gpu/drm/amd/amdgpu/amdgpu.h | 5 + drivers/gpu/drm/amd/include/amdgpu_reg_state.h | 140 +++++++++++++++++++++++++ 2 files changed, 145 insertions(+) create mode 100644 drivers/gpu/drm/amd/include/amdgpu_reg_state.h diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu.h b/drivers/gpu/drm/amd/amdgpu/amdgpu.h index ea2656bd714f..0af8ac81facd 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu.h @@ -110,6 +110,7 @@ #include "amdgpu_ras.h" #include "amdgpu_xcp.h" #include "amdgpu_seq64.h" +#include "amdgpu_reg_state.h" #define MAX_GPU_INSTANCE 64 @@ -612,6 +613,10 @@ struct amdgpu_asic_funcs { const struct amdgpu_video_codecs **codecs); /* encode "> 32bits" smn addressing */ u64 (*encode_ext_smn_addressing)(int ext_id); + + ssize_t (*get_reg_state)(struct amdgpu_device *adev, + enum amdgpu_reg_state reg_state, void *buf, + size_t max_size); }; /* diff --git a/drivers/gpu/drm/amd/include/amdgpu_reg_state.h b/drivers/gpu/drm/amd/include/amdgpu_reg_state.h new file mode 100644 index 000000000000..3dbdb118db59 --- /dev/null +++ b/drivers/gpu/drm/amd/include/amdgpu_reg_state.h @@ -0,0 +1,140 @@ +/* SPDX-License-Identifier: MIT */ +/* + * Copyright 2023 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. + * + */ + +#ifndef __AMDGPU_REG_STATE_H__ +#define __AMDGPU_REG_STATE_H__ + +enum amdgpu_reg_state { + AMDGPU_REG_STATE_TYPE_INVALID = 0, + AMDGPU_REG_STATE_TYPE_XGMI = 1, + AMDGPU_REG_STATE_TYPE_WAFL = 2, + AMDGPU_REG_STATE_TYPE_PCIE = 3, + AMDGPU_REG_STATE_TYPE_USR = 4, + AMDGPU_REG_STATE_TYPE_USR_1 = 5 +}; + +struct amdgpu_reg_state_header { + uint16_t structure_size; + uint8_t format_revision; + uint8_t content_revision; + uint8_t state_type; + uint8_t num_instances; + uint16_t pad; +}; + +enum amdgpu_reg_inst_state { + AMDGPU_INST_S_OK, + AMDGPU_INST_S_EDISABLED, + AMDGPU_INST_S_EACCESS, +}; + +struct amdgpu_smn_reg_data { + uint64_t addr; + uint32_t value; + uint32_t pad; +}; + +struct amdgpu_reg_inst_header { + uint16_t instance; + uint16_t state; + uint16_t num_smn_regs; + uint16_t pad; +}; + + +struct amdgpu_regs_xgmi_v1_0 { + struct amdgpu_reg_inst_header inst_header; + + struct amdgpu_smn_reg_data smn_reg_values[]; +}; + +struct amdgpu_reg_state_xgmi_v1_0 { + /* common_header.state_type must be AMDGPU_REG_STATE_TYPE_XGMI */ + struct amdgpu_reg_state_header common_header; + + struct amdgpu_regs_xgmi_v1_0 xgmi_state_regs[]; +}; + +struct amdgpu_regs_wafl_v1_0 { + struct amdgpu_reg_inst_header inst_header; + + struct amdgpu_smn_reg_data smn_reg_values[]; +}; + +struct amdgpu_reg_state_wafl_v1_0 { + /* common_header.state_type must be AMDGPU_REG_STATE_TYPE_WAFL */ + struct amdgpu_reg_state_header common_header; + + struct amdgpu_regs_wafl_v1_0 wafl_state_regs[]; +}; + +struct amdgpu_regs_pcie_v1_0 { + struct amdgpu_reg_inst_header inst_header; + + uint16_t device_status; + uint16_t link_status; + uint32_t sub_bus_number_latency; + uint32_t pcie_corr_err_status; + uint32_t pcie_uncorr_err_status; + + struct amdgpu_smn_reg_data smn_reg_values[]; +}; + +struct amdgpu_reg_state_pcie_v1_0 { + /* common_header.state_type must be AMDGPU_REG_STATE_TYPE_PCIE */ + struct amdgpu_reg_state_header common_header; + + struct amdgpu_regs_pcie_v1_0 pci_state_regs[]; +}; + +struct amdgpu_regs_usr_v1_0 { + struct amdgpu_reg_inst_header inst_header; + + struct amdgpu_smn_reg_data smn_reg_values[]; +}; + +struct amdgpu_reg_state_usr_v1_0 { + /* common_header.state_type must be AMDGPU_REG_STATE_TYPE_USR */ + struct amdgpu_reg_state_header common_header; + + struct amdgpu_regs_usr_v1_0 usr_state_regs[]; +}; + +static inline size_t amdgpu_reginst_size(uint16_t num_inst, size_t inst_size, + uint16_t num_regs) +{ + return num_inst * + (inst_size + num_regs * sizeof(struct amdgpu_smn_reg_data)); +} + +#define amdgpu_asic_get_reg_state_supported(adev) \ + ((adev)->asic_funcs->get_reg_state ? 1 : 0) + +#define amdgpu_asic_get_reg_state(adev, state, buf, size) \ + ((adev)->asic_funcs->get_reg_state ? \ + (adev)->asic_funcs->get_reg_state((adev), (state), (buf), \ + (size)) : \ + 0) + +#endif -- cgit From af39e6f4d8032b101907cc2ac12a21a778da568d Mon Sep 17 00:00:00 2001 From: Lijo Lazar Date: Fri, 6 Oct 2023 13:49:03 +0530 Subject: drm/amdgpu: Add reg_state sysfs attribute Add reg_state attribute to fetch the register snapshot of different IPs like XGMI, WAFL,PCIE and USR. To get a snapshot for a particular IP 1) Open the sysfs file 2) Seek to the offset as defined in amdgpu_sysfs_reg_offset 3) Read Signed-off-by: Lijo Lazar Reviewed-by: Hawking Zhang Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_device.c | 62 ++++++++++++++++++++++++++ drivers/gpu/drm/amd/include/amdgpu_reg_state.h | 13 ++++++ 2 files changed, 75 insertions(+) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c index 5d3a83193115..f29d0faf956e 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c @@ -162,6 +162,65 @@ static ssize_t amdgpu_device_get_pcie_replay_count(struct device *dev, static DEVICE_ATTR(pcie_replay_count, 0444, amdgpu_device_get_pcie_replay_count, NULL); +static ssize_t amdgpu_sysfs_reg_state_get(struct file *f, struct kobject *kobj, + struct bin_attribute *attr, char *buf, + loff_t ppos, size_t count) +{ + struct device *dev = kobj_to_dev(kobj); + struct drm_device *ddev = dev_get_drvdata(dev); + struct amdgpu_device *adev = drm_to_adev(ddev); + ssize_t bytes_read; + + switch (ppos) { + case AMDGPU_SYS_REG_STATE_XGMI: + bytes_read = amdgpu_asic_get_reg_state( + adev, AMDGPU_REG_STATE_TYPE_XGMI, buf, count); + break; + case AMDGPU_SYS_REG_STATE_WAFL: + bytes_read = amdgpu_asic_get_reg_state( + adev, AMDGPU_REG_STATE_TYPE_WAFL, buf, count); + break; + case AMDGPU_SYS_REG_STATE_PCIE: + bytes_read = amdgpu_asic_get_reg_state( + adev, AMDGPU_REG_STATE_TYPE_PCIE, buf, count); + break; + case AMDGPU_SYS_REG_STATE_USR: + bytes_read = amdgpu_asic_get_reg_state( + adev, AMDGPU_REG_STATE_TYPE_USR, buf, count); + break; + case AMDGPU_SYS_REG_STATE_USR_1: + bytes_read = amdgpu_asic_get_reg_state( + adev, AMDGPU_REG_STATE_TYPE_USR_1, buf, count); + break; + default: + return -EINVAL; + } + + return bytes_read; +} + +BIN_ATTR(reg_state, 0444, amdgpu_sysfs_reg_state_get, NULL, + AMDGPU_SYS_REG_STATE_END); + +int amdgpu_reg_state_sysfs_init(struct amdgpu_device *adev) +{ + int ret; + + if (!amdgpu_asic_get_reg_state_supported(adev)) + return 0; + + ret = sysfs_create_bin_file(&adev->dev->kobj, &bin_attr_reg_state); + + return ret; +} + +void amdgpu_reg_state_sysfs_fini(struct amdgpu_device *adev) +{ + if (!amdgpu_asic_get_reg_state_supported(adev)) + return; + sysfs_remove_bin_file(&adev->dev->kobj, &bin_attr_reg_state); +} + /** * DOC: board_info * @@ -4233,6 +4292,7 @@ fence_driver_init: "Could not create amdgpu board attributes\n"); amdgpu_fru_sysfs_init(adev); + amdgpu_reg_state_sysfs_init(adev); if (IS_ENABLED(CONFIG_PERF_EVENTS)) r = amdgpu_pmu_init(adev); @@ -4355,6 +4415,8 @@ void amdgpu_device_fini_hw(struct amdgpu_device *adev) sysfs_remove_files(&adev->dev->kobj, amdgpu_dev_attributes); amdgpu_fru_sysfs_fini(adev); + amdgpu_reg_state_sysfs_fini(adev); + /* disable ras feature must before hw fini */ amdgpu_ras_pre_fini(adev); diff --git a/drivers/gpu/drm/amd/include/amdgpu_reg_state.h b/drivers/gpu/drm/amd/include/amdgpu_reg_state.h index 3dbdb118db59..be519c8edf49 100644 --- a/drivers/gpu/drm/amd/include/amdgpu_reg_state.h +++ b/drivers/gpu/drm/amd/include/amdgpu_reg_state.h @@ -34,6 +34,15 @@ enum amdgpu_reg_state { AMDGPU_REG_STATE_TYPE_USR_1 = 5 }; +enum amdgpu_sysfs_reg_offset { + AMDGPU_SYS_REG_STATE_XGMI = 0x0000, + AMDGPU_SYS_REG_STATE_WAFL = 0x1000, + AMDGPU_SYS_REG_STATE_PCIE = 0x2000, + AMDGPU_SYS_REG_STATE_USR = 0x3000, + AMDGPU_SYS_REG_STATE_USR_1 = 0x4000, + AMDGPU_SYS_REG_STATE_END = 0x5000, +}; + struct amdgpu_reg_state_header { uint16_t structure_size; uint8_t format_revision; @@ -137,4 +146,8 @@ static inline size_t amdgpu_reginst_size(uint16_t num_inst, size_t inst_size, (size)) : \ 0) + +int amdgpu_reg_state_sysfs_init(struct amdgpu_device *adev); +void amdgpu_reg_state_sysfs_fini(struct amdgpu_device *adev); + #endif -- cgit From 081a6eda2b25092e1466f09eb46d829488b75730 Mon Sep 17 00:00:00 2001 From: Lijo Lazar Date: Fri, 6 Oct 2023 14:20:45 +0530 Subject: drm/amdgpu: Read aquavanjaram PCIE register state Add support to read aqua vanjaram PCIE register state Signed-off-by: Lijo Lazar Reviewed-by: Hawking Zhang Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/aqua_vanjaram.c | 115 +++++++++++++++++++++++++++++ drivers/gpu/drm/amd/amdgpu/soc15.c | 1 + drivers/gpu/drm/amd/amdgpu/soc15.h | 4 + 3 files changed, 120 insertions(+) diff --git a/drivers/gpu/drm/amd/amdgpu/aqua_vanjaram.c b/drivers/gpu/drm/amd/amdgpu/aqua_vanjaram.c index 3f715e7fe1a9..0a4598480dd5 100644 --- a/drivers/gpu/drm/amd/amdgpu/aqua_vanjaram.c +++ b/drivers/gpu/drm/amd/amdgpu/aqua_vanjaram.c @@ -24,6 +24,7 @@ #include "soc15.h" #include "soc15_common.h" +#include "amdgpu_reg_state.h" #include "amdgpu_xcp.h" #include "gfx_v9_4_3.h" #include "gfxhub_v1_2.h" @@ -656,3 +657,117 @@ int aqua_vanjaram_init_soc_config(struct amdgpu_device *adev) return 0; } + +static void aqua_read_smn(struct amdgpu_device *adev, + struct amdgpu_smn_reg_data *regdata, + uint64_t smn_addr) +{ + regdata->addr = smn_addr; + regdata->value = RREG32_PCIE(smn_addr); +} + +struct aqua_reg_list { + uint64_t start_addr; + uint32_t num_regs; + uint32_t incrx; +}; + +#define DW_ADDR_INCR 4 + +#define smnreg_0x1A340218 0x1A340218 +#define smnreg_0x1A3402E4 0x1A3402E4 +#define smnreg_0x1A340294 0x1A340294 +#define smreg_0x1A380088 0x1A380088 + +#define NUM_PCIE_SMN_REGS 14 + +static struct aqua_reg_list pcie_reg_addrs[] = { + { smnreg_0x1A340218, 1, 0 }, + { smnreg_0x1A3402E4, 1, 0 }, + { smnreg_0x1A340294, 6, DW_ADDR_INCR }, + { smreg_0x1A380088, 6, DW_ADDR_INCR }, +}; + +static ssize_t aqua_vanjaram_read_pcie_state(struct amdgpu_device *adev, + void *buf, size_t max_size) +{ + struct amdgpu_reg_state_pcie_v1_0 *pcie_reg_state; + uint32_t start_addr, incrx, num_regs, szbuf; + struct amdgpu_regs_pcie_v1_0 *pcie_regs; + struct amdgpu_smn_reg_data *reg_data; + struct pci_dev *us_pdev, *ds_pdev; + int aer_cap, r, n; + + if (!buf || !max_size) + return -EINVAL; + + pcie_reg_state = (struct amdgpu_reg_state_pcie_v1_0 *)buf; + + szbuf = sizeof(*pcie_reg_state) + + amdgpu_reginst_size(1, sizeof(*pcie_regs), NUM_PCIE_SMN_REGS); + /* Only one instance of pcie regs */ + if (max_size < szbuf) + return -EOVERFLOW; + + pcie_regs = (struct amdgpu_regs_pcie_v1_0 *)((uint8_t *)buf + + sizeof(*pcie_reg_state)); + pcie_regs->inst_header.instance = 0; + pcie_regs->inst_header.state = AMDGPU_INST_S_OK; + pcie_regs->inst_header.num_smn_regs = NUM_PCIE_SMN_REGS; + + reg_data = pcie_regs->smn_reg_values; + + for (r = 0; r < ARRAY_SIZE(pcie_reg_addrs); r++) { + start_addr = pcie_reg_addrs[r].start_addr; + incrx = pcie_reg_addrs[r].incrx; + num_regs = pcie_reg_addrs[r].num_regs; + for (n = 0; n < num_regs; n++) { + aqua_read_smn(adev, reg_data, start_addr + n * incrx); + ++reg_data; + } + } + + ds_pdev = pci_upstream_bridge(adev->pdev); + us_pdev = pci_upstream_bridge(ds_pdev); + + pcie_capability_read_word(us_pdev, PCI_EXP_DEVSTA, + &pcie_regs->device_status); + pcie_capability_read_word(us_pdev, PCI_EXP_LNKSTA, + &pcie_regs->link_status); + + aer_cap = pci_find_ext_capability(us_pdev, PCI_EXT_CAP_ID_ERR); + if (aer_cap) { + pci_read_config_dword(us_pdev, aer_cap + PCI_ERR_COR_STATUS, + &pcie_regs->pcie_corr_err_status); + pci_read_config_dword(us_pdev, aer_cap + PCI_ERR_UNCOR_STATUS, + &pcie_regs->pcie_uncorr_err_status); + } + + pci_read_config_dword(us_pdev, PCI_PRIMARY_BUS, + &pcie_regs->sub_bus_number_latency); + + pcie_reg_state->common_header.structure_size = szbuf; + pcie_reg_state->common_header.format_revision = 1; + pcie_reg_state->common_header.content_revision = 0; + pcie_reg_state->common_header.state_type = AMDGPU_REG_STATE_TYPE_PCIE; + pcie_reg_state->common_header.num_instances = 1; + + return pcie_reg_state->common_header.structure_size; +} + +ssize_t aqua_vanjaram_get_reg_state(struct amdgpu_device *adev, + enum amdgpu_reg_state reg_state, void *buf, + size_t max_size) +{ + ssize_t size; + + switch (reg_state) { + case AMDGPU_REG_STATE_TYPE_PCIE: + size = aqua_vanjaram_read_pcie_state(adev, buf, max_size); + break; + default: + return -EINVAL; + } + + return size; +} diff --git a/drivers/gpu/drm/amd/amdgpu/soc15.c b/drivers/gpu/drm/amd/amdgpu/soc15.c index d4b8d62f4294..e3d41e8aac9d 100644 --- a/drivers/gpu/drm/amd/amdgpu/soc15.c +++ b/drivers/gpu/drm/amd/amdgpu/soc15.c @@ -902,6 +902,7 @@ static const struct amdgpu_asic_funcs aqua_vanjaram_asic_funcs = .pre_asic_init = &soc15_pre_asic_init, .query_video_codecs = &soc15_query_video_codecs, .encode_ext_smn_addressing = &aqua_vanjaram_encode_ext_smn_addressing, + .get_reg_state = &aqua_vanjaram_get_reg_state, }; static int soc15_common_early_init(void *handle) diff --git a/drivers/gpu/drm/amd/amdgpu/soc15.h b/drivers/gpu/drm/amd/amdgpu/soc15.h index eac54042c6c0..1444b7765e4b 100644 --- a/drivers/gpu/drm/amd/amdgpu/soc15.h +++ b/drivers/gpu/drm/amd/amdgpu/soc15.h @@ -27,6 +27,7 @@ #include "nbio_v6_1.h" #include "nbio_v7_0.h" #include "nbio_v7_4.h" +#include "amdgpu_reg_state.h" extern const struct amdgpu_ip_block_version vega10_common_ip_block; @@ -114,6 +115,9 @@ int aldebaran_reg_base_init(struct amdgpu_device *adev); void aqua_vanjaram_ip_map_init(struct amdgpu_device *adev); u64 aqua_vanjaram_encode_ext_smn_addressing(int ext_id); int aqua_vanjaram_init_soc_config(struct amdgpu_device *adev); +ssize_t aqua_vanjaram_get_reg_state(struct amdgpu_device *adev, + enum amdgpu_reg_state reg_state, void *buf, + size_t max_size); void vega10_doorbell_index_init(struct amdgpu_device *adev); void vega20_doorbell_index_init(struct amdgpu_device *adev); -- cgit From 92e508eaf337d465f0574dda18d805bb4df138bc Mon Sep 17 00:00:00 2001 From: Lijo Lazar Date: Sat, 7 Oct 2023 15:41:27 +0530 Subject: drm/amdgpu: Read aquavanjaram XGMI register state Add support to read state of XGMI links in aquavanjaram SOC. Signed-off-by: Lijo Lazar Reviewed-by: Hawking Zhang Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/aqua_vanjaram.c | 96 ++++++++++++++++++++++++++++++ 1 file changed, 96 insertions(+) diff --git a/drivers/gpu/drm/amd/amdgpu/aqua_vanjaram.c b/drivers/gpu/drm/amd/amdgpu/aqua_vanjaram.c index 0a4598480dd5..a00b8c6f0a94 100644 --- a/drivers/gpu/drm/amd/amdgpu/aqua_vanjaram.c +++ b/drivers/gpu/drm/amd/amdgpu/aqua_vanjaram.c @@ -674,6 +674,15 @@ struct aqua_reg_list { #define DW_ADDR_INCR 4 +static void aqua_read_smn_ext(struct amdgpu_device *adev, + struct amdgpu_smn_reg_data *regdata, + uint64_t smn_addr, int i) +{ + regdata->addr = + smn_addr + adev->asic_funcs->encode_ext_smn_addressing(i); + regdata->value = RREG32_PCIE_EXT(regdata->addr); +} + #define smnreg_0x1A340218 0x1A340218 #define smnreg_0x1A3402E4 0x1A3402E4 #define smnreg_0x1A340294 0x1A340294 @@ -755,6 +764,90 @@ static ssize_t aqua_vanjaram_read_pcie_state(struct amdgpu_device *adev, return pcie_reg_state->common_header.structure_size; } +#define smnreg_0x11A00050 0x11A00050 +#define smnreg_0x11A00180 0x11A00180 +#define smnreg_0x11A00070 0x11A00070 +#define smnreg_0x11A00200 0x11A00200 +#define smnreg_0x11A0020C 0x11A0020C +#define smnreg_0x11A00210 0x11A00210 +#define smnreg_0x11A00108 0x11A00108 + +#define XGMI_LINK_REG(smnreg, l) ((smnreg) | (l << 20)) + +#define NUM_XGMI_SMN_REGS 25 + +static struct aqua_reg_list xgmi_reg_addrs[] = { + { smnreg_0x11A00050, 1, 0 }, + { smnreg_0x11A00180, 16, DW_ADDR_INCR }, + { smnreg_0x11A00070, 4, DW_ADDR_INCR }, + { smnreg_0x11A00200, 1, 0 }, + { smnreg_0x11A0020C, 1, 0 }, + { smnreg_0x11A00210, 1, 0 }, + { smnreg_0x11A00108, 1, 0 }, +}; + +static ssize_t aqua_vanjaram_read_xgmi_state(struct amdgpu_device *adev, + void *buf, size_t max_size) +{ + struct amdgpu_reg_state_xgmi_v1_0 *xgmi_reg_state; + uint32_t start_addr, incrx, num_regs, szbuf; + struct amdgpu_regs_xgmi_v1_0 *xgmi_regs; + struct amdgpu_smn_reg_data *reg_data; + const int max_xgmi_instances = 8; + int inst = 0, i, j, r, n; + const int xgmi_inst = 2; + void *p; + + if (!buf || !max_size) + return -EINVAL; + + xgmi_reg_state = (struct amdgpu_reg_state_xgmi_v1_0 *)buf; + + szbuf = sizeof(*xgmi_reg_state) + + amdgpu_reginst_size(max_xgmi_instances, sizeof(*xgmi_regs), + NUM_XGMI_SMN_REGS); + /* Only one instance of pcie regs */ + if (max_size < szbuf) + return -EOVERFLOW; + + p = &xgmi_reg_state->xgmi_state_regs[0]; + for_each_inst(i, adev->aid_mask) { + for (j = 0; j < xgmi_inst; ++j) { + xgmi_regs = (struct amdgpu_regs_xgmi_v1_0 *)p; + xgmi_regs->inst_header.instance = inst++; + + xgmi_regs->inst_header.state = AMDGPU_INST_S_OK; + xgmi_regs->inst_header.num_smn_regs = NUM_XGMI_SMN_REGS; + + reg_data = xgmi_regs->smn_reg_values; + + for (r = 0; r < ARRAY_SIZE(xgmi_reg_addrs); r++) { + start_addr = xgmi_reg_addrs[r].start_addr; + incrx = xgmi_reg_addrs[r].incrx; + num_regs = xgmi_reg_addrs[r].num_regs; + + for (n = 0; n < num_regs; n++) { + aqua_read_smn_ext( + adev, reg_data, + XGMI_LINK_REG(start_addr, j) + + n * incrx, + i); + ++reg_data; + } + } + p = reg_data; + } + } + + xgmi_reg_state->common_header.structure_size = szbuf; + xgmi_reg_state->common_header.format_revision = 1; + xgmi_reg_state->common_header.content_revision = 0; + xgmi_reg_state->common_header.state_type = AMDGPU_REG_STATE_TYPE_XGMI; + xgmi_reg_state->common_header.num_instances = max_xgmi_instances; + + return xgmi_reg_state->common_header.structure_size; +} + ssize_t aqua_vanjaram_get_reg_state(struct amdgpu_device *adev, enum amdgpu_reg_state reg_state, void *buf, size_t max_size) @@ -765,6 +858,9 @@ ssize_t aqua_vanjaram_get_reg_state(struct amdgpu_device *adev, case AMDGPU_REG_STATE_TYPE_PCIE: size = aqua_vanjaram_read_pcie_state(adev, buf, max_size); break; + case AMDGPU_REG_STATE_TYPE_XGMI: + size = aqua_vanjaram_read_xgmi_state(adev, buf, max_size); + break; default: return -EINVAL; } -- cgit From 36fd9969fa53c40e8a58192714d9a3624cbe04e3 Mon Sep 17 00:00:00 2001 From: Lijo Lazar Date: Tue, 28 Nov 2023 16:47:14 +0530 Subject: drm/amdgpu: Use another offset for GC 9.4.3 remap The legacy region at 0x7F000 maps to valid registers in GC 9.4.3 SOCs. Use 0x1A000 offset instead as MMIO register remap region. Signed-off-by: Lijo Lazar Reviewed-by: Hawking Zhang Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/soc15.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/drivers/gpu/drm/amd/amdgpu/soc15.c b/drivers/gpu/drm/amd/amdgpu/soc15.c index e3d41e8aac9d..9ad4d6d3122b 100644 --- a/drivers/gpu/drm/amd/amdgpu/soc15.c +++ b/drivers/gpu/drm/amd/amdgpu/soc15.c @@ -1162,6 +1162,11 @@ static int soc15_common_early_init(void *handle) AMD_PG_SUPPORT_VCN_DPG | AMD_PG_SUPPORT_JPEG; adev->external_rev_id = adev->rev_id + 0x46; + /* GC 9.4.3 uses MMIO register region hole at a different offset */ + if (!amdgpu_sriov_vf(adev)) { + adev->rmmio_remap.reg_offset = 0x1A000; + adev->rmmio_remap.bus_addr = adev->rmmio_base + 0x1A000; + } break; default: /* FIXME: not supported yet */ -- cgit From 04fcc3fec5dbd316b0b1fb2b9f8a39bfbe07af50 Mon Sep 17 00:00:00 2001 From: ZhenGuo Yin Date: Thu, 23 Nov 2023 16:47:33 +0800 Subject: drm/amdgpu: Skip access gfx11 golden registers under SRIOV [Why] Golden registers are PF-only registers on gfx11. RLCG interface will return "out-of-range" under SRIOV VF. [How] Skip access gfx11 golden registers under SRIOV. Reviewed-by: Horace Chen Signed-off-by: ZhenGuo Yin Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c b/drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c index 8ed4a6fb147a..288e926e5cd4 100644 --- a/drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c @@ -293,6 +293,9 @@ static void gfx_v11_0_set_kiq_pm4_funcs(struct amdgpu_device *adev) static void gfx_v11_0_init_golden_registers(struct amdgpu_device *adev) { + if (amdgpu_sriov_vf(adev)) + return; + switch (amdgpu_ip_version(adev, GC_HWIP, 0)) { case IP_VERSION(11, 0, 1): case IP_VERSION(11, 0, 4): -- cgit From 00f9d49bce844e8196e0c2ea298f9a41a11129d9 Mon Sep 17 00:00:00 2001 From: Yang Wang Date: Thu, 30 Nov 2023 12:58:14 +0800 Subject: drm/amdgpu: Fix missing mca debugfs node Use amdgpu_ip_version() helper function to check ip version. The ip version contains other information, use the helper function to avoid reading wrong value. Reviewed-by: Lijo Lazar Signed-off-by: Yang Wang Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_mca.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_mca.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_mca.c index 54f2f346579e..210aea590a52 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_mca.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_mca.c @@ -485,7 +485,7 @@ DEFINE_DEBUGFS_ATTRIBUTE(mca_debug_mode_fops, NULL, amdgpu_mca_smu_debug_mode_se void amdgpu_mca_smu_debugfs_init(struct amdgpu_device *adev, struct dentry *root) { #if defined(CONFIG_DEBUG_FS) - if (!root || adev->ip_versions[MP1_HWIP][0] != IP_VERSION(13, 0, 6)) + if (!root || amdgpu_ip_version(adev, MP1_HWIP, 0) != IP_VERSION(13, 0, 6)) return; debugfs_create_file("mca_debug_mode", 0200, root, adev, &mca_debug_mode_fops); -- cgit From 9596ffe1cc99dd699e595ea971a2c8ccd2735e21 Mon Sep 17 00:00:00 2001 From: Likun Gao Date: Wed, 29 Nov 2023 10:59:53 +0800 Subject: drm/amdgpu: distinguish rlc fw for different SKU For some SKU, rlc firmware should use different one compared with the normal rlc firmware. Signed-off-by: Likun Gao Reviewed-by: Hawking Zhang Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c b/drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c index 288e926e5cd4..c659ef0f47ce 100644 --- a/drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c @@ -67,6 +67,7 @@ MODULE_FIRMWARE("amdgpu/gc_11_0_0_pfp.bin"); MODULE_FIRMWARE("amdgpu/gc_11_0_0_me.bin"); MODULE_FIRMWARE("amdgpu/gc_11_0_0_mec.bin"); MODULE_FIRMWARE("amdgpu/gc_11_0_0_rlc.bin"); +MODULE_FIRMWARE("amdgpu/gc_11_0_0_rlc_1.bin"); MODULE_FIRMWARE("amdgpu/gc_11_0_0_toc.bin"); MODULE_FIRMWARE("amdgpu/gc_11_0_1_pfp.bin"); MODULE_FIRMWARE("amdgpu/gc_11_0_1_me.bin"); @@ -567,7 +568,11 @@ static int gfx_v11_0_init_microcode(struct amdgpu_device *adev) } if (!amdgpu_sriov_vf(adev)) { - snprintf(fw_name, sizeof(fw_name), "amdgpu/%s_rlc.bin", ucode_prefix); + if (amdgpu_ip_version(adev, GC_HWIP, 0) == IP_VERSION(11, 0, 0) && + adev->pdev->revision == 0xCE) + snprintf(fw_name, sizeof(fw_name), "amdgpu/gc_11_0_0_rlc_1.bin"); + else + snprintf(fw_name, sizeof(fw_name), "amdgpu/%s_rlc.bin", ucode_prefix); err = amdgpu_ucode_request(adev, &adev->gfx.rlc_fw, fw_name); if (err) goto out; -- cgit From f875f61b1fd626a4223a5bdf0339b5372c689e13 Mon Sep 17 00:00:00 2001 From: Yang Wang Date: Thu, 30 Nov 2023 18:39:03 +0800 Subject: drm/amdgpu: enable mca debug mode on APU by default enable MCA debug mode on APU device by default. Signed-off-by: Yang Wang Reviewed-by: Hawking Zhang Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c index f6b47ebce9d6..72634d675e27 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c @@ -3132,7 +3132,8 @@ int amdgpu_ras_late_init(struct amdgpu_device *adev) if (amdgpu_sriov_vf(adev)) return 0; - amdgpu_ras_set_mca_debug_mode(adev, false); + /* enable MCA debug on APU device */ + amdgpu_ras_set_mca_debug_mode(adev, !!(adev->flags & AMD_IS_APU)); list_for_each_entry_safe(node, tmp, &adev->ras_list, node) { if (!node->ras_obj) { -- cgit From 39c960bbf9d9ea862398759e75736cfb68c3446f Mon Sep 17 00:00:00 2001 From: Nikita Zhandarovich Date: Wed, 29 Nov 2023 07:22:30 -0800 Subject: drm/radeon/r600_cs: Fix possible int overflows in r600_cs_check_reg() While improbable, there may be a chance of hitting integer overflow when the result of radeon_get_ib_value() gets shifted left. Avoid it by casting one of the operands to larger data type (u64). Found by Linux Verification Center (linuxtesting.org) with static analysis tool SVACE. Fixes: 1729dd33d20b ("drm/radeon/kms: r600 CS parser fixes") Signed-off-by: Nikita Zhandarovich Signed-off-by: Alex Deucher --- drivers/gpu/drm/radeon/r600_cs.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/radeon/r600_cs.c b/drivers/gpu/drm/radeon/r600_cs.c index 638f861af80f..6cf54a747749 100644 --- a/drivers/gpu/drm/radeon/r600_cs.c +++ b/drivers/gpu/drm/radeon/r600_cs.c @@ -1275,7 +1275,7 @@ static int r600_cs_check_reg(struct radeon_cs_parser *p, u32 reg, u32 idx) return -EINVAL; } tmp = (reg - CB_COLOR0_BASE) / 4; - track->cb_color_bo_offset[tmp] = radeon_get_ib_value(p, idx) << 8; + track->cb_color_bo_offset[tmp] = (u64)radeon_get_ib_value(p, idx) << 8; ib[idx] += (u32)((reloc->gpu_offset >> 8) & 0xffffffff); track->cb_color_base_last[tmp] = ib[idx]; track->cb_color_bo[tmp] = reloc->robj; @@ -1302,7 +1302,7 @@ static int r600_cs_check_reg(struct radeon_cs_parser *p, u32 reg, u32 idx) "0x%04X\n", reg); return -EINVAL; } - track->htile_offset = radeon_get_ib_value(p, idx) << 8; + track->htile_offset = (u64)radeon_get_ib_value(p, idx) << 8; ib[idx] += (u32)((reloc->gpu_offset >> 8) & 0xffffffff); track->htile_bo = reloc->robj; track->db_dirty = true; -- cgit From b5c5baa458faa5430c445acd9a17481274d77ccf Mon Sep 17 00:00:00 2001 From: Nikita Zhandarovich Date: Wed, 29 Nov 2023 07:22:12 -0800 Subject: drm/radeon/r100: Fix integer overflow issues in r100_cs_track_check() It may be possible, albeit unlikely, to encounter integer overflow during the multiplication of several unsigned int variables, the result being assigned to a variable 'size' of wider type. Prevent this potential behaviour by converting one of the multiples to unsigned long. Found by Linux Verification Center (linuxtesting.org) with static analysis tool SVACE. Fixes: 0242f74d29df ("drm/radeon: clean up CS functions in r100.c") Signed-off-by: Nikita Zhandarovich Signed-off-by: Alex Deucher --- drivers/gpu/drm/radeon/r100.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/radeon/r100.c b/drivers/gpu/drm/radeon/r100.c index affa9e0309b2..cfeca2694d5f 100644 --- a/drivers/gpu/drm/radeon/r100.c +++ b/drivers/gpu/drm/radeon/r100.c @@ -2321,7 +2321,7 @@ int r100_cs_track_check(struct radeon_device *rdev, struct r100_cs_track *track) switch (prim_walk) { case 1: for (i = 0; i < track->num_arrays; i++) { - size = track->arrays[i].esize * track->max_indx * 4; + size = track->arrays[i].esize * track->max_indx * 4UL; if (track->arrays[i].robj == NULL) { DRM_ERROR("(PW %u) Vertex array %u no buffer " "bound\n", prim_walk, i); @@ -2340,7 +2340,7 @@ int r100_cs_track_check(struct radeon_device *rdev, struct r100_cs_track *track) break; case 2: for (i = 0; i < track->num_arrays; i++) { - size = track->arrays[i].esize * (nverts - 1) * 4; + size = track->arrays[i].esize * (nverts - 1) * 4UL; if (track->arrays[i].robj == NULL) { DRM_ERROR("(PW %u) Vertex array %u no buffer " "bound\n", prim_walk, i); -- cgit From 71225e1c930942cb1e042fc08c5cc0c4ef30e95e Mon Sep 17 00:00:00 2001 From: Nikita Zhandarovich Date: Tue, 8 Aug 2023 11:04:16 -0700 Subject: drm/radeon: check return value of radeon_ring_lock() In the unlikely event of radeon_ring_lock() failing, its errno return value should be processed. This patch checks said return value and prints a debug message in case of an error. Found by Linux Verification Center (linuxtesting.org) with static analysis tool SVACE. Fixes: 48c0c902e2e6 ("drm/radeon/kms: add support for CP setup on SI") Signed-off-by: Nikita Zhandarovich Signed-off-by: Alex Deucher --- drivers/gpu/drm/radeon/si.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/gpu/drm/radeon/si.c b/drivers/gpu/drm/radeon/si.c index a91012447b56..85e9cba49cec 100644 --- a/drivers/gpu/drm/radeon/si.c +++ b/drivers/gpu/drm/radeon/si.c @@ -3611,6 +3611,10 @@ static int si_cp_start(struct radeon_device *rdev) for (i = RADEON_RING_TYPE_GFX_INDEX; i <= CAYMAN_RING_TYPE_CP2_INDEX; ++i) { ring = &rdev->ring[i]; r = radeon_ring_lock(rdev, ring, 2); + if (r) { + DRM_ERROR("radeon: cp failed to lock ring (%d).\n", r); + return r; + } /* clear the compute context state */ radeon_ring_write(ring, PACKET3_COMPUTE(PACKET3_CLEAR_STATE, 0)); -- cgit From b719a9c15d52d4f56bdea8241a5d90fd9197ce99 Mon Sep 17 00:00:00 2001 From: Mario Limonciello Date: Tue, 28 Nov 2023 18:35:09 -0600 Subject: drm/amd/display: Fix NULL pointer dereference at hibernate During hibernate sequence the source context might not have a clk_mgr. So don't use it to look for DML2 support. Link: https://gitlab.freedesktop.org/drm/amd/-/issues/2980 Fixes: 7966f319c66d ("drm/amd/display: Introduce DML2") Reviewed-by: Harry Wentland Signed-off-by: Mario Limonciello Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc_resource.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c index f3a9fdd2340d..e1c02527d04a 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c @@ -4554,7 +4554,7 @@ void dc_resource_state_copy_construct( struct dml2_context *dml2 = NULL; // Need to preserve allocated dml2 context - if (src_ctx->clk_mgr->ctx->dc->debug.using_dml2) + if (src_ctx->clk_mgr && src_ctx->clk_mgr->ctx->dc->debug.using_dml2) dml2 = dst_ctx->bw_ctx.dml2; #endif @@ -4562,7 +4562,7 @@ void dc_resource_state_copy_construct( #ifdef CONFIG_DRM_AMD_DC_FP // Preserve allocated dml2 context - if (src_ctx->clk_mgr->ctx->dc->debug.using_dml2) + if (src_ctx->clk_mgr && src_ctx->clk_mgr->ctx->dc->debug.using_dml2) dst_ctx->bw_ctx.dml2 = dml2; #endif -- cgit